Unflake PlatformNotificationServiceTest.NotificationPermissionLastUsage
[chromium-blink-merge.git] / pdf / pdf.cc
blobf15c8892278a6e4bf9b134ae322e0ad73bd4ddfa
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
3 // found in the LICENSE file.
5 #include "pdf/pdf.h"
7 #if defined(OS_WIN)
8 #include <windows.h>
9 #endif
11 #include "base/command_line.h"
12 #include "base/logging.h"
13 #include "pdf/instance.h"
14 #include "pdf/out_of_process_instance.h"
15 #include "ppapi/c/ppp.h"
16 #include "ppapi/cpp/private/pdf.h"
18 bool g_sdk_initialized_via_pepper = false;
20 // The Mac release builds discard CreateModule and the entire PDFModule
21 // definition because they are not referenced here. This causes the Pepper
22 // exports (PPP_GetInterface etc) to not be exported. So we force the linker
23 // to include this code by using __attribute__((used)).
24 #if __GNUC__ >= 4
25 #define PDF_USED __attribute__((used))
26 #else
27 #define PDF_USED
28 #endif
30 #if defined(OS_WIN)
31 HMODULE g_hmodule;
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;
43 void HandlePureVirtualCall() {
44 // Do the same as Chrome's CHECK(false) which is undefined.
45 ::base::debug::BreakDebugger();
46 return;
50 BOOL APIENTRY DllMain(HMODULE module, DWORD reason_for_call, LPVOID reserved) {
51 g_hmodule = module;
52 if (reason_for_call == DLL_PROCESS_ATTACH) {
53 // On windows following handlers work only inside module. So breakpad in
54 // chrome.dll does not catch that. To avoid linking related code or
55 // duplication breakpad_win.cc::InitCrashReporter() just catch errors here
56 // and crash in a way interceptable by breakpad of parent module.
57 _set_invalid_parameter_handler(HandleInvalidParameter);
58 _set_purecall_handler(HandlePureVirtualCall);
60 #if defined(ARCH_CPU_X86_64) && _MSC_VER <= 1800
61 // VS2013's CRT only checks the existence of FMA3 instructions, not the
62 // enabled-ness of them at the OS level (this is fixed in VS2015). We force
63 // off usage of FMA3 instructions in the CRT to avoid using that path and
64 // hitting illegal instructions when running on CPUs that support FMA3, but
65 // OSs that don't. Because we use the static library CRT we have to call
66 // this function once in each DLL.
67 // See http://crbug.com/436603.
68 _set_FMA3_enable(0);
69 #endif // ARCH_CPU_X86_64 && _MSC_VER <= 1800
71 return TRUE;
74 #endif
76 namespace pp {
78 PDF_USED Module* CreateModule() {
79 return new chrome_pdf::PDFModule();
82 } // namespace pp
84 namespace chrome_pdf {
86 PDFModule::PDFModule() {
89 PDFModule::~PDFModule() {
90 if (g_sdk_initialized_via_pepper) {
91 chrome_pdf::ShutdownSDK();
92 g_sdk_initialized_via_pepper = false;
96 bool PDFModule::Init() {
97 return true;
100 pp::Instance* PDFModule::CreateInstance(PP_Instance instance) {
101 if (!g_sdk_initialized_via_pepper) {
102 void* data = NULL;
103 #if defined(OS_WIN)
104 data = g_hmodule;
105 #endif
106 if (!chrome_pdf::InitializeSDK(data))
107 return NULL;
108 g_sdk_initialized_via_pepper = true;
111 if (pp::PDF::IsOutOfProcess(pp::InstanceHandle(instance)))
112 return new OutOfProcessInstance(instance);
113 return new Instance(instance);
116 } // namespace chrome_pdf
118 extern "C" {
120 // TODO(sanjeevr): It might make sense to provide more stateful wrappers over
121 // the internal PDF SDK (such as LoadDocument, LoadPage etc). Determine if we
122 // need to provide this.
123 // Wrapper exports over the PDF engine that can be used by an external module
124 // such as Chrome (since Chrome cannot directly pull in PDFium sources).
125 #if defined(OS_WIN)
126 // |pdf_buffer| is the buffer that contains the entire PDF document to be
127 // rendered.
128 // |buffer_size| is the size of |pdf_buffer| in bytes.
129 // |page_number| is the 0-based index of the page to be rendered.
130 // |dc| is the device context to render into.
131 // |dpi_x| and |dpi_y| are the x and y resolutions respectively. If either
132 // value is -1, the dpi from the DC will be used.
133 // |bounds_origin_x|, |bounds_origin_y|, |bounds_width| and |bounds_height|
134 // specify a bounds rectangle within the DC in which to render the PDF
135 // page.
136 // |fit_to_bounds| specifies whether the output should be shrunk to fit the
137 // supplied bounds if the page size is larger than the bounds in any
138 // dimension. If this is false, parts of the PDF page that lie outside
139 // the bounds will be clipped.
140 // |stretch_to_bounds| specifies whether the output should be stretched to fit
141 // the supplied bounds if the page size is smaller than the bounds in any
142 // dimension.
143 // If both |fit_to_bounds| and |stretch_to_bounds| are true, then
144 // |fit_to_bounds| is honored first.
145 // |keep_aspect_ratio| If any scaling is to be done is true, this flag
146 // specifies whether the original aspect ratio of the page should be
147 // preserved while scaling.
148 // |center_in_bounds| specifies whether the final image (after any scaling is
149 // done) should be centered within the given bounds.
150 // |autorotate| specifies whether the final image should be rotated to match
151 // the output bound.
152 // Returns false if the document or the page number are not valid.
153 PP_EXPORT bool RenderPDFPageToDC(const void* pdf_buffer,
154 int buffer_size,
155 int page_number,
156 HDC dc,
157 int dpi_x,
158 int dpi_y,
159 int bounds_origin_x,
160 int bounds_origin_y,
161 int bounds_width,
162 int bounds_height,
163 bool fit_to_bounds,
164 bool stretch_to_bounds,
165 bool keep_aspect_ratio,
166 bool center_in_bounds,
167 bool autorotate) {
168 if (!g_sdk_initialized_via_pepper) {
169 if (!chrome_pdf::InitializeSDK(g_hmodule)) {
170 return false;
173 scoped_ptr<chrome_pdf::PDFEngineExports> engine_exports(
174 chrome_pdf::PDFEngineExports::Create());
175 chrome_pdf::PDFEngineExports::RenderingSettings settings(
176 dpi_x, dpi_y, pp::Rect(bounds_origin_x, bounds_origin_y, bounds_width,
177 bounds_height),
178 fit_to_bounds, stretch_to_bounds, keep_aspect_ratio, center_in_bounds,
179 autorotate);
180 bool ret = engine_exports->RenderPDFPageToDC(pdf_buffer, buffer_size,
181 page_number, settings, dc);
182 if (!g_sdk_initialized_via_pepper) {
183 chrome_pdf::ShutdownSDK();
185 return ret;
188 #endif // OS_WIN
190 // |page_count| and |max_page_width| are optional and can be NULL.
191 // Returns false if the document is not valid.
192 PDF_USED PP_EXPORT
193 bool GetPDFDocInfo(const void* pdf_buffer,
194 int buffer_size, int* page_count,
195 double* max_page_width) {
196 if (!g_sdk_initialized_via_pepper) {
197 void* data = NULL;
198 #if defined(OS_WIN)
199 data = g_hmodule;
200 #endif
201 if (!chrome_pdf::InitializeSDK(data))
202 return false;
204 scoped_ptr<chrome_pdf::PDFEngineExports> engine_exports(
205 chrome_pdf::PDFEngineExports::Create());
206 bool ret = engine_exports->GetPDFDocInfo(
207 pdf_buffer, buffer_size, page_count, max_page_width);
208 if (!g_sdk_initialized_via_pepper) {
209 chrome_pdf::ShutdownSDK();
211 return ret;
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
224 bool GetPDFPageSizeByIndex(const void* pdf_buffer,
225 int pdf_buffer_size, int page_number,
226 double* width, double* height) {
227 if (!g_sdk_initialized_via_pepper) {
228 void* data = NULL;
229 #if defined(OS_WIN)
230 data = g_hmodule;
231 #endif
232 if (!chrome_pdf::InitializeSDK(data))
233 return false;
235 scoped_ptr<chrome_pdf::PDFEngineExports> engine_exports(
236 chrome_pdf::PDFEngineExports::Create());
237 bool ret = engine_exports->GetPDFPageSizeByIndex(
238 pdf_buffer, pdf_buffer_size, page_number, width, height);
239 if (!g_sdk_initialized_via_pepper)
240 chrome_pdf::ShutdownSDK();
241 return ret;
244 // Renders PDF page into 4-byte per pixel BGRA color bitmap.
245 // |pdf_buffer| is the buffer that contains the entire PDF document to be
246 // rendered.
247 // |pdf_buffer_size| is the size of |pdf_buffer| in bytes.
248 // |page_number| is the 0-based index of the page to be rendered.
249 // |bitmap_buffer| is the output buffer for bitmap.
250 // |bitmap_width| is the width of the output bitmap.
251 // |bitmap_height| is the height of the output bitmap.
252 // |dpi| is the resolutions.
253 // |autorotate| specifies whether the final image should be rotated to match
254 // the output bound.
255 // Returns false if the document or the page number are not valid.
256 PDF_USED PP_EXPORT
257 bool RenderPDFPageToBitmap(const void* pdf_buffer,
258 int pdf_buffer_size,
259 int page_number,
260 void* bitmap_buffer,
261 int bitmap_width,
262 int bitmap_height,
263 int dpi,
264 bool autorotate) {
265 if (!g_sdk_initialized_via_pepper) {
266 void* data = NULL;
267 #if defined(OS_WIN)
268 data = g_hmodule;
269 #endif
270 if (!chrome_pdf::InitializeSDK(data))
271 return false;
273 scoped_ptr<chrome_pdf::PDFEngineExports> engine_exports(
274 chrome_pdf::PDFEngineExports::Create());
275 chrome_pdf::PDFEngineExports::RenderingSettings settings(
276 dpi, dpi, pp::Rect(bitmap_width, bitmap_height), true, false, true, true,
277 autorotate);
278 bool ret = engine_exports->RenderPDFPageToBitmap(
279 pdf_buffer, pdf_buffer_size, page_number, settings, bitmap_buffer);
280 if (!g_sdk_initialized_via_pepper) {
281 chrome_pdf::ShutdownSDK();
283 return ret;
286 } // extern "C"