OLD | NEW |
1 // Copyright (c) 2010 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2010 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "pdf/pdf.h" | 5 #include "pdf/pdf.h" |
6 | 6 |
7 #if defined(OS_WIN) | 7 #if defined(OS_WIN) |
8 #include <windows.h> | 8 #include <windows.h> |
9 #endif | 9 #endif |
10 | 10 |
11 #include "base/command_line.h" | 11 #include "base/command_line.h" |
12 #include "base/logging.h" | 12 #include "base/logging.h" |
13 #include "pdf/instance.h" | 13 #include "pdf/instance.h" |
14 #include "pdf/out_of_process_instance.h" | 14 #include "pdf/out_of_process_instance.h" |
15 #include "ppapi/c/ppp.h" | 15 #include "ppapi/c/ppp.h" |
16 #include "ppapi/cpp/private/internal_module.h" | |
17 #include "ppapi/cpp/private/pdf.h" | 16 #include "ppapi/cpp/private/pdf.h" |
18 #include "v8/include/v8.h" | 17 #include "v8/include/v8.h" |
19 | 18 |
20 bool g_sdk_initialized_via_pepper = false; | 19 bool g_sdk_initialized_via_pepper = false; |
21 | 20 |
| 21 // The Mac release builds discard CreateModule and the entire PDFModule |
| 22 // definition because they are not referenced here. This causes the Pepper |
| 23 // exports (PPP_GetInterface etc) to not be exported. So we force the linker |
| 24 // to include this code by using __attribute__((used)). |
| 25 #if __GNUC__ >= 4 |
| 26 #define PDF_USED __attribute__((used)) |
| 27 #else |
| 28 #define PDF_USED |
| 29 #endif |
| 30 |
| 31 #if defined(OS_WIN) |
| 32 |
| 33 void HandleInvalidParameter(const wchar_t* expression, |
| 34 const wchar_t* function, |
| 35 const wchar_t* file, |
| 36 unsigned int line, |
| 37 uintptr_t reserved) { |
| 38 // Do the same as Chrome's CHECK(false) which is undefined. |
| 39 ::base::debug::BreakDebugger(); |
| 40 return; |
| 41 } |
| 42 |
| 43 void HandlePureVirtualCall() { |
| 44 // Do the same as Chrome's CHECK(false) which is undefined. |
| 45 ::base::debug::BreakDebugger(); |
| 46 return; |
| 47 } |
| 48 |
| 49 |
| 50 BOOL APIENTRY DllMain(HMODULE module, DWORD reason_for_call, LPVOID reserved) { |
| 51 if (reason_for_call == DLL_PROCESS_ATTACH) { |
| 52 // On windows following handlers work only inside module. So breakpad in |
| 53 // chrome.dll does not catch that. To avoid linking related code or |
| 54 // duplication breakpad_win.cc::InitCrashReporter() just catch errors here |
| 55 // and crash in a way interceptable by breakpad of parent module. |
| 56 _set_invalid_parameter_handler(HandleInvalidParameter); |
| 57 _set_purecall_handler(HandlePureVirtualCall); |
| 58 |
| 59 #if defined(ARCH_CPU_X86_64) && _MSC_VER <= 1800 |
| 60 // VS2013's CRT only checks the existence of FMA3 instructions, not the |
| 61 // enabled-ness of them at the OS level (this is fixed in VS2015). We force |
| 62 // off usage of FMA3 instructions in the CRT to avoid using that path and |
| 63 // hitting illegal instructions when running on CPUs that support FMA3, but |
| 64 // OSs that don't. Because we use the static library CRT we have to call |
| 65 // this function once in each DLL. |
| 66 // See http://crbug.com/436603. |
| 67 _set_FMA3_enable(0); |
| 68 #endif // ARCH_CPU_X86_64 && _MSC_VER <= 1800 |
| 69 } |
| 70 return TRUE; |
| 71 } |
| 72 |
| 73 #endif |
| 74 |
| 75 namespace pp { |
| 76 |
| 77 PDF_USED Module* CreateModule() { |
| 78 return new chrome_pdf::PDFModule(); |
| 79 } |
| 80 |
| 81 } // namespace pp |
| 82 |
22 namespace chrome_pdf { | 83 namespace chrome_pdf { |
23 | 84 |
24 PDFModule::PDFModule() { | 85 PDFModule::PDFModule() { |
25 } | 86 } |
26 | 87 |
27 PDFModule::~PDFModule() { | 88 PDFModule::~PDFModule() { |
28 if (g_sdk_initialized_via_pepper) { | 89 if (g_sdk_initialized_via_pepper) { |
29 chrome_pdf::ShutdownSDK(); | 90 chrome_pdf::ShutdownSDK(); |
30 g_sdk_initialized_via_pepper = false; | 91 g_sdk_initialized_via_pepper = false; |
31 } | 92 } |
(...skipping 17 matching lines...) Expand all Loading... |
49 if (!chrome_pdf::InitializeSDK()) | 110 if (!chrome_pdf::InitializeSDK()) |
50 return NULL; | 111 return NULL; |
51 g_sdk_initialized_via_pepper = true; | 112 g_sdk_initialized_via_pepper = true; |
52 } | 113 } |
53 | 114 |
54 if (pp::PDF::IsOutOfProcess(pp::InstanceHandle(instance))) | 115 if (pp::PDF::IsOutOfProcess(pp::InstanceHandle(instance))) |
55 return new OutOfProcessInstance(instance); | 116 return new OutOfProcessInstance(instance); |
56 return new Instance(instance); | 117 return new Instance(instance); |
57 } | 118 } |
58 | 119 |
| 120 } // namespace chrome_pdf |
59 | 121 |
60 // Implementation of Global PPP functions --------------------------------- | 122 extern "C" { |
61 int32_t PPP_InitializeModule(PP_Module module_id, | |
62 PPB_GetInterface get_browser_interface) { | |
63 PDFModule* module = new PDFModule(); | |
64 if (!module->InternalInit(module_id, get_browser_interface)) { | |
65 delete module; | |
66 return PP_ERROR_FAILED; | |
67 } | |
68 | 123 |
69 pp::InternalSetModuleSingleton(module); | 124 // TODO(sanjeevr): It might make sense to provide more stateful wrappers over |
70 return PP_OK; | 125 // the internal PDF SDK (such as LoadDocument, LoadPage etc). Determine if we |
71 } | 126 // need to provide this. |
72 | 127 // Wrapper exports over the PDF engine that can be used by an external module |
73 void PPP_ShutdownModule() { | 128 // such as Chrome (since Chrome cannot directly pull in PDFium sources). |
74 delete pp::Module::Get(); | |
75 pp::InternalSetModuleSingleton(NULL); | |
76 } | |
77 | |
78 const void* PPP_GetInterface(const char* interface_name) { | |
79 if (!pp::Module::Get()) | |
80 return NULL; | |
81 return pp::Module::Get()->GetPluginInterface(interface_name); | |
82 } | |
83 | |
84 #if defined(OS_WIN) | 129 #if defined(OS_WIN) |
85 bool RenderPDFPageToDC(const void* pdf_buffer, | 130 // |pdf_buffer| is the buffer that contains the entire PDF document to be |
| 131 // rendered. |
| 132 // |buffer_size| is the size of |pdf_buffer| in bytes. |
| 133 // |page_number| is the 0-based index of the page to be rendered. |
| 134 // |dc| is the device context to render into. |
| 135 // |dpi_x| and |dpi_y| are the x and y resolutions respectively. If either |
| 136 // value is -1, the dpi from the DC will be used. |
| 137 // |bounds_origin_x|, |bounds_origin_y|, |bounds_width| and |bounds_height| |
| 138 // specify a bounds rectangle within the DC in which to render the PDF |
| 139 // page. |
| 140 // |fit_to_bounds| specifies whether the output should be shrunk to fit the |
| 141 // supplied bounds if the page size is larger than the bounds in any |
| 142 // dimension. If this is false, parts of the PDF page that lie outside |
| 143 // the bounds will be clipped. |
| 144 // |stretch_to_bounds| specifies whether the output should be stretched to fit |
| 145 // the supplied bounds if the page size is smaller than the bounds in any |
| 146 // dimension. |
| 147 // If both |fit_to_bounds| and |stretch_to_bounds| are true, then |
| 148 // |fit_to_bounds| is honored first. |
| 149 // |keep_aspect_ratio| If any scaling is to be done is true, this flag |
| 150 // specifies whether the original aspect ratio of the page should be |
| 151 // preserved while scaling. |
| 152 // |center_in_bounds| specifies whether the final image (after any scaling is |
| 153 // done) should be centered within the given bounds. |
| 154 // |autorotate| specifies whether the final image should be rotated to match |
| 155 // the output bound. |
| 156 // Returns false if the document or the page number are not valid. |
| 157 PP_EXPORT bool RenderPDFPageToDC(const void* pdf_buffer, |
86 int buffer_size, | 158 int buffer_size, |
87 int page_number, | 159 int page_number, |
88 HDC dc, | 160 HDC dc, |
89 int dpi, | 161 int dpi_x, |
| 162 int dpi_y, |
90 int bounds_origin_x, | 163 int bounds_origin_x, |
91 int bounds_origin_y, | 164 int bounds_origin_y, |
92 int bounds_width, | 165 int bounds_width, |
93 int bounds_height, | 166 int bounds_height, |
94 bool fit_to_bounds, | 167 bool fit_to_bounds, |
95 bool stretch_to_bounds, | 168 bool stretch_to_bounds, |
96 bool keep_aspect_ratio, | 169 bool keep_aspect_ratio, |
97 bool center_in_bounds, | 170 bool center_in_bounds, |
98 bool autorotate) { | 171 bool autorotate) { |
99 if (!g_sdk_initialized_via_pepper) { | 172 if (!g_sdk_initialized_via_pepper) { |
100 if (!chrome_pdf::InitializeSDK()) { | 173 if (!chrome_pdf::InitializeSDK()) { |
101 return false; | 174 return false; |
102 } | 175 } |
103 } | 176 } |
104 scoped_ptr<chrome_pdf::PDFEngineExports> engine_exports( | 177 scoped_ptr<chrome_pdf::PDFEngineExports> engine_exports( |
105 chrome_pdf::PDFEngineExports::Create()); | 178 chrome_pdf::PDFEngineExports::Create()); |
106 chrome_pdf::PDFEngineExports::RenderingSettings settings( | 179 chrome_pdf::PDFEngineExports::RenderingSettings settings( |
107 dpi, dpi, pp::Rect(bounds_origin_x, bounds_origin_y, bounds_width, | 180 dpi_x, dpi_y, pp::Rect(bounds_origin_x, bounds_origin_y, bounds_width, |
108 bounds_height), | 181 bounds_height), |
109 fit_to_bounds, stretch_to_bounds, keep_aspect_ratio, center_in_bounds, | 182 fit_to_bounds, stretch_to_bounds, keep_aspect_ratio, center_in_bounds, |
110 autorotate); | 183 autorotate); |
111 bool ret = engine_exports->RenderPDFPageToDC(pdf_buffer, buffer_size, | 184 bool ret = engine_exports->RenderPDFPageToDC(pdf_buffer, buffer_size, |
112 page_number, settings, dc); | 185 page_number, settings, dc); |
113 if (!g_sdk_initialized_via_pepper) { | 186 if (!g_sdk_initialized_via_pepper) { |
114 chrome_pdf::ShutdownSDK(); | 187 chrome_pdf::ShutdownSDK(); |
115 } | 188 } |
116 return ret; | 189 return ret; |
117 } | 190 } |
118 | 191 |
119 #endif // OS_WIN | 192 #endif // OS_WIN |
120 | 193 |
| 194 // |page_count| and |max_page_width| are optional and can be NULL. |
| 195 // Returns false if the document is not valid. |
| 196 PDF_USED PP_EXPORT |
121 bool GetPDFDocInfo(const void* pdf_buffer, | 197 bool GetPDFDocInfo(const void* pdf_buffer, |
122 int buffer_size, int* page_count, | 198 int buffer_size, int* page_count, |
123 double* max_page_width) { | 199 double* max_page_width) { |
124 if (!g_sdk_initialized_via_pepper) { | 200 if (!g_sdk_initialized_via_pepper) { |
125 if (!chrome_pdf::InitializeSDK()) | 201 if (!chrome_pdf::InitializeSDK()) |
126 return false; | 202 return false; |
127 } | 203 } |
128 scoped_ptr<chrome_pdf::PDFEngineExports> engine_exports( | 204 scoped_ptr<chrome_pdf::PDFEngineExports> engine_exports( |
129 chrome_pdf::PDFEngineExports::Create()); | 205 chrome_pdf::PDFEngineExports::Create()); |
130 bool ret = engine_exports->GetPDFDocInfo( | 206 bool ret = engine_exports->GetPDFDocInfo( |
131 pdf_buffer, buffer_size, page_count, max_page_width); | 207 pdf_buffer, buffer_size, page_count, max_page_width); |
132 if (!g_sdk_initialized_via_pepper) { | 208 if (!g_sdk_initialized_via_pepper) { |
133 chrome_pdf::ShutdownSDK(); | 209 chrome_pdf::ShutdownSDK(); |
134 } | 210 } |
135 return ret; | 211 return ret; |
136 } | 212 } |
137 | 213 |
| 214 // Gets the dimensions of a specific page in a document. |
| 215 // |pdf_buffer| is the buffer that contains the entire PDF document to be |
| 216 // rendered. |
| 217 // |pdf_buffer_size| is the size of |pdf_buffer| in bytes. |
| 218 // |page_number| is the page number that the function will get the dimensions |
| 219 // of. |
| 220 // |width| is the output for the width of the page in points. |
| 221 // |height| is the output for the height of the page in points. |
| 222 // Returns false if the document or the page number are not valid. |
| 223 PDF_USED PP_EXPORT |
138 bool GetPDFPageSizeByIndex(const void* pdf_buffer, | 224 bool GetPDFPageSizeByIndex(const void* pdf_buffer, |
139 int pdf_buffer_size, int page_number, | 225 int pdf_buffer_size, int page_number, |
140 double* width, double* height) { | 226 double* width, double* height) { |
141 if (!g_sdk_initialized_via_pepper) { | 227 if (!g_sdk_initialized_via_pepper) { |
142 if (!chrome_pdf::InitializeSDK()) | 228 if (!chrome_pdf::InitializeSDK()) |
143 return false; | 229 return false; |
144 } | 230 } |
145 scoped_ptr<chrome_pdf::PDFEngineExports> engine_exports( | 231 scoped_ptr<chrome_pdf::PDFEngineExports> engine_exports( |
146 chrome_pdf::PDFEngineExports::Create()); | 232 chrome_pdf::PDFEngineExports::Create()); |
147 bool ret = engine_exports->GetPDFPageSizeByIndex( | 233 bool ret = engine_exports->GetPDFPageSizeByIndex( |
148 pdf_buffer, pdf_buffer_size, page_number, width, height); | 234 pdf_buffer, pdf_buffer_size, page_number, width, height); |
149 if (!g_sdk_initialized_via_pepper) | 235 if (!g_sdk_initialized_via_pepper) |
150 chrome_pdf::ShutdownSDK(); | 236 chrome_pdf::ShutdownSDK(); |
151 return ret; | 237 return ret; |
152 } | 238 } |
153 | 239 |
| 240 // Renders PDF page into 4-byte per pixel BGRA color bitmap. |
| 241 // |pdf_buffer| is the buffer that contains the entire PDF document to be |
| 242 // rendered. |
| 243 // |pdf_buffer_size| is the size of |pdf_buffer| in bytes. |
| 244 // |page_number| is the 0-based index of the page to be rendered. |
| 245 // |bitmap_buffer| is the output buffer for bitmap. |
| 246 // |bitmap_width| is the width of the output bitmap. |
| 247 // |bitmap_height| is the height of the output bitmap. |
| 248 // |dpi| is the resolutions. |
| 249 // |autorotate| specifies whether the final image should be rotated to match |
| 250 // the output bound. |
| 251 // Returns false if the document or the page number are not valid. |
| 252 PDF_USED PP_EXPORT |
154 bool RenderPDFPageToBitmap(const void* pdf_buffer, | 253 bool RenderPDFPageToBitmap(const void* pdf_buffer, |
155 int pdf_buffer_size, | 254 int pdf_buffer_size, |
156 int page_number, | 255 int page_number, |
157 void* bitmap_buffer, | 256 void* bitmap_buffer, |
158 int bitmap_width, | 257 int bitmap_width, |
159 int bitmap_height, | 258 int bitmap_height, |
160 int dpi, | 259 int dpi, |
161 bool autorotate) { | 260 bool autorotate) { |
162 if (!g_sdk_initialized_via_pepper) { | 261 if (!g_sdk_initialized_via_pepper) { |
163 if (!chrome_pdf::InitializeSDK()) | 262 if (!chrome_pdf::InitializeSDK()) |
164 return false; | 263 return false; |
165 } | 264 } |
166 scoped_ptr<chrome_pdf::PDFEngineExports> engine_exports( | 265 scoped_ptr<chrome_pdf::PDFEngineExports> engine_exports( |
167 chrome_pdf::PDFEngineExports::Create()); | 266 chrome_pdf::PDFEngineExports::Create()); |
168 chrome_pdf::PDFEngineExports::RenderingSettings settings( | 267 chrome_pdf::PDFEngineExports::RenderingSettings settings( |
169 dpi, dpi, pp::Rect(bitmap_width, bitmap_height), true, false, true, true, | 268 dpi, dpi, pp::Rect(bitmap_width, bitmap_height), true, false, true, true, |
170 autorotate); | 269 autorotate); |
171 bool ret = engine_exports->RenderPDFPageToBitmap( | 270 bool ret = engine_exports->RenderPDFPageToBitmap( |
172 pdf_buffer, pdf_buffer_size, page_number, settings, bitmap_buffer); | 271 pdf_buffer, pdf_buffer_size, page_number, settings, bitmap_buffer); |
173 if (!g_sdk_initialized_via_pepper) { | 272 if (!g_sdk_initialized_via_pepper) { |
174 chrome_pdf::ShutdownSDK(); | 273 chrome_pdf::ShutdownSDK(); |
175 } | 274 } |
176 return ret; | 275 return ret; |
177 } | 276 } |
178 | 277 |
179 } // namespace chrome_pdf | 278 } // extern "C" |
OLD | NEW |