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.
4
5 #include "pdf/pdf.h"
6
7 #if defined(OS_WIN)
8 #include <windows.h>
9 #endif
10
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"
17
18 bool g_sdk_initialized_via_pepper = false;
19
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
29
30 #if defined(OS_WIN)
31 HMODULE g_hmodule;
32
HandleInvalidParameter(const wchar_t * expression,const wchar_t * function,const wchar_t * file,unsigned int line,uintptr_t reserved)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
HandlePureVirtualCall()43 void HandlePureVirtualCall() {
44 // Do the same as Chrome's CHECK(false) which is undefined.
45 ::base::debug::BreakDebugger();
46 return;
47 }
48
49
DllMain(HMODULE module,DWORD reason_for_call,LPVOID reserved)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);
59 }
60 return TRUE;
61 }
62
63 #endif
64
65 namespace pp {
66
CreateModule()67 PDF_USED Module* CreateModule() {
68 return new chrome_pdf::PDFModule();
69 }
70
71 } // namespace pp
72
73 namespace chrome_pdf {
74
PDFModule()75 PDFModule::PDFModule() {
76 }
77
~PDFModule()78 PDFModule::~PDFModule() {
79 if (g_sdk_initialized_via_pepper) {
80 chrome_pdf::ShutdownSDK();
81 g_sdk_initialized_via_pepper = false;
82 }
83 }
84
Init()85 bool PDFModule::Init() {
86 return true;
87 }
88
CreateInstance(PP_Instance instance)89 pp::Instance* PDFModule::CreateInstance(PP_Instance instance) {
90 if (!g_sdk_initialized_via_pepper) {
91 void* data = NULL;
92 #if defined(OS_WIN)
93 data = g_hmodule;
94 #endif
95 if (!chrome_pdf::InitializeSDK(data))
96 return NULL;
97 g_sdk_initialized_via_pepper = true;
98 }
99
100 if (pp::PDF::IsOutOfProcess(pp::InstanceHandle(instance)))
101 return new OutOfProcessInstance(instance);
102 return new Instance(instance);
103 }
104
105 } // namespace chrome_pdf
106
107 extern "C" {
108
109 // TODO(sanjeevr): It might make sense to provide more stateful wrappers over
110 // the internal PDF SDK (such as LoadDocument, LoadPage etc). Determine if we
111 // need to provide this.
112 // Wrapper exports over the PDF engine that can be used by an external module
113 // such as Chrome (since Chrome cannot directly pull in PDFium sources).
114 #if defined(OS_WIN)
115 // |pdf_buffer| is the buffer that contains the entire PDF document to be
116 // rendered.
117 // |buffer_size| is the size of pdf_buffer in bytes.
118 // |page_number| is the 0-based index of the page to be rendered.
119 // |dc| is the device context to render into.
120 // |dpi_x| and |dpi_y| are the x and y resolutions respectively. If either value
121 // is -1, the dpi from the DC will be used.
122 // |bounds_origin_x|, |bounds_origin_y|, |bounds_width| and |bounds_height|
123 // specify a bounds rectangle within the DC in which to render the PDF page.
124 // |fit_to_bounds| specifies whether the output should be shrunk to fit the
125 // supplied bounds if the page size is larger than the bounds in any
126 // dimension. If this is false, parts of the PDF page that lie outside the
127 // bounds will be clipped.
128 // |stretch_to_bounds| specifies whether the output should be stretched to fit
129 // the supplied bounds if the page size is smaller than the bounds in any
130 // dimension.
131 // If both |fit_to_bounds| and |stretch_to_bounds| are true, then
132 // |fit_to_bounds| is honored first.
133 // |keep_aspect_ratio| If any scaling is to be done is true, this flag specifies
134 // whether the original aspect ratio of the page should be preserved while
135 // scaling.
136 // |center_in_bounds| specifies whether the final image (after any scaling is
137 // done) should be centered within the given bounds.
138 // |autorotate| specifies whether the final image should be rotated to match
139 // the output bound.
140 // Returns false if the document or the page number are not valid.
RenderPDFPageToDC(const void * pdf_buffer,int buffer_size,int page_number,HDC dc,int dpi_x,int dpi_y,int bounds_origin_x,int bounds_origin_y,int bounds_width,int bounds_height,bool fit_to_bounds,bool stretch_to_bounds,bool keep_aspect_ratio,bool center_in_bounds,bool autorotate)141 PP_EXPORT bool RenderPDFPageToDC(const void* pdf_buffer,
142 int buffer_size,
143 int page_number,
144 HDC dc,
145 int dpi_x,
146 int dpi_y,
147 int bounds_origin_x,
148 int bounds_origin_y,
149 int bounds_width,
150 int bounds_height,
151 bool fit_to_bounds,
152 bool stretch_to_bounds,
153 bool keep_aspect_ratio,
154 bool center_in_bounds,
155 bool autorotate) {
156 if (!g_sdk_initialized_via_pepper) {
157 if (!chrome_pdf::InitializeSDK(g_hmodule)) {
158 return false;
159 }
160 }
161 scoped_ptr<chrome_pdf::PDFEngineExports> engine_exports(
162 chrome_pdf::PDFEngineExports::Create());
163 chrome_pdf::PDFEngineExports::RenderingSettings settings(
164 dpi_x, dpi_y, pp::Rect(bounds_origin_x, bounds_origin_y, bounds_width,
165 bounds_height),
166 fit_to_bounds, stretch_to_bounds, keep_aspect_ratio, center_in_bounds,
167 autorotate);
168 bool ret = engine_exports->RenderPDFPageToDC(pdf_buffer, buffer_size,
169 page_number, settings, dc);
170 if (!g_sdk_initialized_via_pepper) {
171 chrome_pdf::ShutdownSDK();
172 }
173 return ret;
174 }
175
176 #endif // OS_WIN
177
178 // |page_count| and |max_page_width| are optional and can be NULL.
179 // Returns false if the document is not valid.
180 PDF_USED PP_EXPORT
GetPDFDocInfo(const void * pdf_buffer,int buffer_size,int * page_count,double * max_page_width)181 bool GetPDFDocInfo(const void* pdf_buffer,
182 int buffer_size, int* page_count,
183 double* max_page_width) {
184 if (!g_sdk_initialized_via_pepper) {
185 void* data = NULL;
186 #if defined(OS_WIN)
187 data = g_hmodule;
188 #endif
189 if (!chrome_pdf::InitializeSDK(data))
190 return false;
191 }
192 scoped_ptr<chrome_pdf::PDFEngineExports> engine_exports(
193 chrome_pdf::PDFEngineExports::Create());
194 bool ret = engine_exports->GetPDFDocInfo(
195 pdf_buffer, buffer_size, page_count, max_page_width);
196 if (!g_sdk_initialized_via_pepper) {
197 chrome_pdf::ShutdownSDK();
198 }
199 return ret;
200 }
201
202 // Renders PDF page into 4-byte per pixel BGRA color bitmap.
203 // |pdf_buffer| is the buffer that contains the entire PDF document to be
204 // rendered.
205 // |pdf_buffer_size| is the size of pdf_buffer in bytes.
206 // |page_number| is the 0-based index of the page to be rendered.
207 // |bitmap_buffer| is the output buffer for bitmap.
208 // |bitmap_width| is the width of the output bitmap.
209 // |bitmap_height| is the height of the output bitmap.
210 // |dpi| is the resolutions.
211 // |autorotate| specifies whether the final image should be rotated to match
212 // the output bound.
213 // Returns false if the document or the page number are not valid.
214 PDF_USED PP_EXPORT
RenderPDFPageToBitmap(const void * pdf_buffer,int pdf_buffer_size,int page_number,void * bitmap_buffer,int bitmap_width,int bitmap_height,int dpi,bool autorotate)215 bool RenderPDFPageToBitmap(const void* pdf_buffer,
216 int pdf_buffer_size,
217 int page_number,
218 void* bitmap_buffer,
219 int bitmap_width,
220 int bitmap_height,
221 int dpi,
222 bool autorotate) {
223 if (!g_sdk_initialized_via_pepper) {
224 void* data = NULL;
225 #if defined(OS_WIN)
226 data = g_hmodule;
227 #endif
228 if (!chrome_pdf::InitializeSDK(data))
229 return false;
230 }
231 scoped_ptr<chrome_pdf::PDFEngineExports> engine_exports(
232 chrome_pdf::PDFEngineExports::Create());
233 chrome_pdf::PDFEngineExports::RenderingSettings settings(
234 dpi, dpi, pp::Rect(bitmap_width, bitmap_height), true, false, true, true,
235 autorotate);
236 bool ret = engine_exports->RenderPDFPageToBitmap(
237 pdf_buffer, pdf_buffer_size, page_number, settings, bitmap_buffer);
238 if (!g_sdk_initialized_via_pepper) {
239 chrome_pdf::ShutdownSDK();
240 }
241 return ret;
242 }
243
244 } // extern "C"
245