| // Copyright (c) 2010 The Chromium Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #include "pdf/pdf.h" |
| |
| #if defined(OS_WIN) |
| #include <windows.h> |
| #endif |
| |
| #include "base/command_line.h" |
| #include "base/logging.h" |
| #include "pdf/instance.h" |
| #include "pdf/out_of_process_instance.h" |
| #include "ppapi/c/ppp.h" |
| #include "ppapi/cpp/private/pdf.h" |
| |
| bool g_sdk_initialized_via_pepper = false; |
| |
| // The Mac release builds discard CreateModule and the entire PDFModule |
| // definition because they are not referenced here. This causes the Pepper |
| // exports (PPP_GetInterface etc) to not be exported. So we force the linker |
| // to include this code by using __attribute__((used)). |
| #if __GNUC__ >= 4 |
| #define PDF_USED __attribute__((used)) |
| #else |
| #define PDF_USED |
| #endif |
| |
| #if defined(OS_WIN) |
| HMODULE g_hmodule; |
| |
| void HandleInvalidParameter(const wchar_t* expression, |
| const wchar_t* function, |
| const wchar_t* file, |
| unsigned int line, |
| uintptr_t reserved) { |
| // Do the same as Chrome's CHECK(false) which is undefined. |
| ::base::debug::BreakDebugger(); |
| return; |
| } |
| |
| void HandlePureVirtualCall() { |
| // Do the same as Chrome's CHECK(false) which is undefined. |
| ::base::debug::BreakDebugger(); |
| return; |
| } |
| |
| |
| BOOL APIENTRY DllMain(HMODULE module, DWORD reason_for_call, LPVOID reserved) { |
| g_hmodule = module; |
| if (reason_for_call == DLL_PROCESS_ATTACH) { |
| // On windows following handlers work only inside module. So breakpad in |
| // chrome.dll does not catch that. To avoid linking related code or |
| // duplication breakpad_win.cc::InitCrashReporter() just catch errors here |
| // and crash in a way interceptable by breakpad of parent module. |
| _set_invalid_parameter_handler(HandleInvalidParameter); |
| _set_purecall_handler(HandlePureVirtualCall); |
| } |
| return TRUE; |
| } |
| |
| #endif |
| |
| namespace pp { |
| |
| PDF_USED Module* CreateModule() { |
| return new chrome_pdf::PDFModule(); |
| } |
| |
| } // namespace pp |
| |
| namespace chrome_pdf { |
| |
| PDFModule::PDFModule() { |
| } |
| |
| PDFModule::~PDFModule() { |
| if (g_sdk_initialized_via_pepper) { |
| chrome_pdf::ShutdownSDK(); |
| g_sdk_initialized_via_pepper = false; |
| } |
| } |
| |
| bool PDFModule::Init() { |
| return true; |
| } |
| |
| pp::Instance* PDFModule::CreateInstance(PP_Instance instance) { |
| if (!g_sdk_initialized_via_pepper) { |
| void* data = NULL; |
| #if defined(OS_WIN) |
| data = g_hmodule; |
| #endif |
| if (!chrome_pdf::InitializeSDK(data)) |
| return NULL; |
| g_sdk_initialized_via_pepper = true; |
| } |
| |
| if (pp::PDF::IsOutOfProcess(pp::InstanceHandle(instance))) |
| return new OutOfProcessInstance(instance); |
| return new Instance(instance); |
| } |
| |
| } // namespace chrome_pdf |
| |
| extern "C" { |
| |
| // TODO(sanjeevr): It might make sense to provide more stateful wrappers over |
| // the internal PDF SDK (such as LoadDocument, LoadPage etc). Determine if we |
| // need to provide this. |
| // Wrapper exports over the PDF engine that can be used by an external module |
| // such as Chrome (since Chrome cannot directly pull in PDFium sources). |
| #if defined(OS_WIN) |
| // |pdf_buffer| is the buffer that contains the entire PDF document to be |
| // rendered. |
| // |buffer_size| is the size of |pdf_buffer| in bytes. |
| // |page_number| is the 0-based index of the page to be rendered. |
| // |dc| is the device context to render into. |
| // |dpi_x| and |dpi_y| are the x and y resolutions respectively. If either |
| // value is -1, the dpi from the DC will be used. |
| // |bounds_origin_x|, |bounds_origin_y|, |bounds_width| and |bounds_height| |
| // specify a bounds rectangle within the DC in which to render the PDF |
| // page. |
| // |fit_to_bounds| specifies whether the output should be shrunk to fit the |
| // supplied bounds if the page size is larger than the bounds in any |
| // dimension. If this is false, parts of the PDF page that lie outside |
| // the bounds will be clipped. |
| // |stretch_to_bounds| specifies whether the output should be stretched to fit |
| // the supplied bounds if the page size is smaller than the bounds in any |
| // dimension. |
| // If both |fit_to_bounds| and |stretch_to_bounds| are true, then |
| // |fit_to_bounds| is honored first. |
| // |keep_aspect_ratio| If any scaling is to be done is true, this flag |
| // specifies whether the original aspect ratio of the page should be |
| // preserved while scaling. |
| // |center_in_bounds| specifies whether the final image (after any scaling is |
| // done) should be centered within the given bounds. |
| // |autorotate| specifies whether the final image should be rotated to match |
| // the output bound. |
| // Returns false if the document or the page number are not valid. |
| PP_EXPORT bool 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) { |
| if (!g_sdk_initialized_via_pepper) { |
| if (!chrome_pdf::InitializeSDK(g_hmodule)) { |
| return false; |
| } |
| } |
| scoped_ptr<chrome_pdf::PDFEngineExports> engine_exports( |
| chrome_pdf::PDFEngineExports::Create()); |
| chrome_pdf::PDFEngineExports::RenderingSettings settings( |
| dpi_x, dpi_y, pp::Rect(bounds_origin_x, bounds_origin_y, bounds_width, |
| bounds_height), |
| fit_to_bounds, stretch_to_bounds, keep_aspect_ratio, center_in_bounds, |
| autorotate); |
| bool ret = engine_exports->RenderPDFPageToDC(pdf_buffer, buffer_size, |
| page_number, settings, dc); |
| if (!g_sdk_initialized_via_pepper) { |
| chrome_pdf::ShutdownSDK(); |
| } |
| return ret; |
| } |
| |
| #endif // OS_WIN |
| |
| // |page_count| and |max_page_width| are optional and can be NULL. |
| // Returns false if the document is not valid. |
| PDF_USED PP_EXPORT |
| bool GetPDFDocInfo(const void* pdf_buffer, |
| int buffer_size, int* page_count, |
| double* max_page_width) { |
| if (!g_sdk_initialized_via_pepper) { |
| void* data = NULL; |
| #if defined(OS_WIN) |
| data = g_hmodule; |
| #endif |
| if (!chrome_pdf::InitializeSDK(data)) |
| return false; |
| } |
| scoped_ptr<chrome_pdf::PDFEngineExports> engine_exports( |
| chrome_pdf::PDFEngineExports::Create()); |
| bool ret = engine_exports->GetPDFDocInfo( |
| pdf_buffer, buffer_size, page_count, max_page_width); |
| if (!g_sdk_initialized_via_pepper) { |
| chrome_pdf::ShutdownSDK(); |
| } |
| return ret; |
| } |
| |
| // Gets the dimensions of a specific page in a document. |
| // |pdf_buffer| is the buffer that contains the entire PDF document to be |
| // rendered. |
| // |pdf_buffer_size| is the size of |pdf_buffer| in bytes. |
| // |page_number| is the page number that the function will get the dimensions |
| // of. |
| // |width| is the output for the width of the page in points. |
| // |height| is the output for the height of the page in points. |
| // Returns false if the document or the page number are not valid. |
| PDF_USED PP_EXPORT |
| bool GetPDFPageSizeByIndex(const void* pdf_buffer, |
| int pdf_buffer_size, int page_number, |
| double* width, double* height) { |
| if (!g_sdk_initialized_via_pepper) { |
| void* data = NULL; |
| #if defined(OS_WIN) |
| data = g_hmodule; |
| #endif |
| if (!chrome_pdf::InitializeSDK(data)) |
| return false; |
| } |
| scoped_ptr<chrome_pdf::PDFEngineExports> engine_exports( |
| chrome_pdf::PDFEngineExports::Create()); |
| bool ret = engine_exports->GetPDFPageSizeByIndex( |
| pdf_buffer, pdf_buffer_size, page_number, width, height); |
| if (!g_sdk_initialized_via_pepper) |
| chrome_pdf::ShutdownSDK(); |
| return ret; |
| } |
| |
| // Renders PDF page into 4-byte per pixel BGRA color bitmap. |
| // |pdf_buffer| is the buffer that contains the entire PDF document to be |
| // rendered. |
| // |pdf_buffer_size| is the size of |pdf_buffer| in bytes. |
| // |page_number| is the 0-based index of the page to be rendered. |
| // |bitmap_buffer| is the output buffer for bitmap. |
| // |bitmap_width| is the width of the output bitmap. |
| // |bitmap_height| is the height of the output bitmap. |
| // |dpi| is the resolutions. |
| // |autorotate| specifies whether the final image should be rotated to match |
| // the output bound. |
| // Returns false if the document or the page number are not valid. |
| PDF_USED PP_EXPORT |
| bool 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) { |
| if (!g_sdk_initialized_via_pepper) { |
| void* data = NULL; |
| #if defined(OS_WIN) |
| data = g_hmodule; |
| #endif |
| if (!chrome_pdf::InitializeSDK(data)) |
| return false; |
| } |
| scoped_ptr<chrome_pdf::PDFEngineExports> engine_exports( |
| chrome_pdf::PDFEngineExports::Create()); |
| chrome_pdf::PDFEngineExports::RenderingSettings settings( |
| dpi, dpi, pp::Rect(bitmap_width, bitmap_height), true, false, true, true, |
| autorotate); |
| bool ret = engine_exports->RenderPDFPageToBitmap( |
| pdf_buffer, pdf_buffer_size, page_number, settings, bitmap_buffer); |
| if (!g_sdk_initialized_via_pepper) { |
| chrome_pdf::ShutdownSDK(); |
| } |
| return ret; |
| } |
| |
| } // extern "C" |