diff options
Diffstat (limited to 'xfa_test/pdf/pdf.cc')
-rw-r--r-- | xfa_test/pdf/pdf.cc | 275 |
1 files changed, 275 insertions, 0 deletions
diff --git a/xfa_test/pdf/pdf.cc b/xfa_test/pdf/pdf.cc new file mode 100644 index 0000000000..6a4507f4fc --- /dev/null +++ b/xfa_test/pdf/pdf.cc @@ -0,0 +1,275 @@ +// 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" |