summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorthestig <thestig@chromium.org>2016-11-23 15:25:48 -0800
committerCommit bot <commit-bot@chromium.org>2016-11-23 15:25:48 -0800
commita78ba6043eafc9fd05481e64c37002b487357bbf (patch)
tree17c346faee807b0ccf9660a51638f16f2e85e1c3
parent4e847e36fe013bcfddf71c79221887a308b9fadb (diff)
downloadpdfium-a78ba6043eafc9fd05481e64c37002b487357bbf.tar.xz
Add FPDF_RenderPageBitmapWithMatrix API.
BUG=pdfium:522 Review-Url: https://codereview.chromium.org/2526473002
-rw-r--r--core/fpdfdoc/cpdf_annotlist.cpp6
-rw-r--r--core/fpdfdoc/cpdf_annotlist.h6
-rw-r--r--fpdfsdk/fpdfview.cpp168
-rw-r--r--fpdfsdk/fpdfview_c_api_test.c1
-rw-r--r--fpdfsdk/fpdfview_embeddertest.cpp51
-rw-r--r--public/fpdfview.h32
6 files changed, 199 insertions, 65 deletions
diff --git a/core/fpdfdoc/cpdf_annotlist.cpp b/core/fpdfdoc/cpdf_annotlist.cpp
index e68e08a1f6..1ad6ab23a6 100644
--- a/core/fpdfdoc/cpdf_annotlist.cpp
+++ b/core/fpdfdoc/cpdf_annotlist.cpp
@@ -106,7 +106,7 @@ void CPDF_AnnotList::DisplayPass(CPDF_Page* pPage,
CFX_RenderDevice* pDevice,
CPDF_RenderContext* pContext,
bool bPrinting,
- CFX_Matrix* pMatrix,
+ const CFX_Matrix* pMatrix,
bool bWidgetPass,
CPDF_RenderOptions* pOptions,
FX_RECT* clip_rect) {
@@ -156,7 +156,7 @@ void CPDF_AnnotList::DisplayAnnots(CPDF_Page* pPage,
CFX_RenderDevice* pDevice,
CPDF_RenderContext* pContext,
bool bPrinting,
- CFX_Matrix* pUser2Device,
+ const CFX_Matrix* pUser2Device,
uint32_t dwAnnotFlags,
CPDF_RenderOptions* pOptions,
FX_RECT* pClipRect) {
@@ -173,7 +173,7 @@ void CPDF_AnnotList::DisplayAnnots(CPDF_Page* pPage,
void CPDF_AnnotList::DisplayAnnots(CPDF_Page* pPage,
CPDF_RenderContext* pContext,
bool bPrinting,
- CFX_Matrix* pMatrix,
+ const CFX_Matrix* pMatrix,
bool bShowWidget,
CPDF_RenderOptions* pOptions) {
uint32_t dwAnnotFlags = bShowWidget ? ANNOTFLAG_INVISIBLE | ANNOTFLAG_HIDDEN
diff --git a/core/fpdfdoc/cpdf_annotlist.h b/core/fpdfdoc/cpdf_annotlist.h
index e17b958517..3443277b68 100644
--- a/core/fpdfdoc/cpdf_annotlist.h
+++ b/core/fpdfdoc/cpdf_annotlist.h
@@ -28,7 +28,7 @@ class CPDF_AnnotList {
void DisplayAnnots(CPDF_Page* pPage,
CPDF_RenderContext* pContext,
bool bPrinting,
- CFX_Matrix* pMatrix,
+ const CFX_Matrix* pMatrix,
bool bShowWidget,
CPDF_RenderOptions* pOptions);
@@ -36,7 +36,7 @@ class CPDF_AnnotList {
CFX_RenderDevice* pDevice,
CPDF_RenderContext* pContext,
bool bPrinting,
- CFX_Matrix* pMatrix,
+ const CFX_Matrix* pMatrix,
uint32_t dwAnnotFlags,
CPDF_RenderOptions* pOptions,
FX_RECT* pClipRect);
@@ -52,7 +52,7 @@ class CPDF_AnnotList {
CFX_RenderDevice* pDevice,
CPDF_RenderContext* pContext,
bool bPrinting,
- CFX_Matrix* pMatrix,
+ const CFX_Matrix* pMatrix,
bool bWidget,
CPDF_RenderOptions* pOptions,
FX_RECT* clip_rect);
diff --git a/fpdfsdk/fpdfview.cpp b/fpdfsdk/fpdfview.cpp
index 3f5115afd6..c7cc1242fe 100644
--- a/fpdfsdk/fpdfview.cpp
+++ b/fpdfsdk/fpdfview.cpp
@@ -48,6 +48,74 @@
#include "core/fxge/cfx_windowsdevice.h"
#endif
+namespace {
+
+void RenderPageImpl(CPDF_PageRenderContext* pContext,
+ CPDF_Page* pPage,
+ const CFX_Matrix& matrix,
+ const FX_RECT& clipping_rect,
+ int flags,
+ bool bNeedToRestore,
+ IFSDK_PAUSE_Adapter* pause) {
+ if (!pContext->m_pOptions)
+ pContext->m_pOptions = pdfium::MakeUnique<CPDF_RenderOptions>();
+
+ if (flags & FPDF_LCD_TEXT)
+ pContext->m_pOptions->m_Flags |= RENDER_CLEARTYPE;
+ else
+ pContext->m_pOptions->m_Flags &= ~RENDER_CLEARTYPE;
+
+ if (flags & FPDF_NO_NATIVETEXT)
+ pContext->m_pOptions->m_Flags |= RENDER_NO_NATIVETEXT;
+ if (flags & FPDF_RENDER_LIMITEDIMAGECACHE)
+ pContext->m_pOptions->m_Flags |= RENDER_LIMITEDIMAGECACHE;
+ if (flags & FPDF_RENDER_FORCEHALFTONE)
+ pContext->m_pOptions->m_Flags |= RENDER_FORCE_HALFTONE;
+#ifndef PDF_ENABLE_XFA
+ if (flags & FPDF_RENDER_NO_SMOOTHTEXT)
+ pContext->m_pOptions->m_Flags |= RENDER_NOTEXTSMOOTH;
+ if (flags & FPDF_RENDER_NO_SMOOTHIMAGE)
+ pContext->m_pOptions->m_Flags |= RENDER_NOIMAGESMOOTH;
+ if (flags & FPDF_RENDER_NO_SMOOTHPATH)
+ pContext->m_pOptions->m_Flags |= RENDER_NOPATHSMOOTH;
+#endif // PDF_ENABLE_XFA
+
+ // Grayscale output
+ if (flags & FPDF_GRAYSCALE) {
+ pContext->m_pOptions->m_ColorMode = RENDER_COLOR_GRAY;
+ pContext->m_pOptions->m_ForeColor = 0;
+ pContext->m_pOptions->m_BackColor = 0xffffff;
+ }
+
+ const CPDF_OCContext::UsageType usage =
+ (flags & FPDF_PRINTING) ? CPDF_OCContext::Print : CPDF_OCContext::View;
+ pContext->m_pOptions->m_AddFlags = flags >> 8;
+ pContext->m_pOptions->m_pOCContext =
+ new CPDF_OCContext(pPage->m_pDocument, usage);
+
+ pContext->m_pDevice->SaveState();
+ pContext->m_pDevice->SetClip_Rect(clipping_rect);
+
+ pContext->m_pContext = pdfium::MakeUnique<CPDF_RenderContext>(pPage);
+ pContext->m_pContext->AppendLayer(pPage, &matrix);
+
+ if (flags & FPDF_ANNOT) {
+ pContext->m_pAnnots = pdfium::MakeUnique<CPDF_AnnotList>(pPage);
+ bool bPrinting = pContext->m_pDevice->GetDeviceClass() != FXDC_DISPLAY;
+ pContext->m_pAnnots->DisplayAnnots(pPage, pContext->m_pContext.get(),
+ bPrinting, &matrix, false, nullptr);
+ }
+
+ pContext->m_pRenderer = pdfium::MakeUnique<CPDF_ProgressiveRenderer>(
+ pContext->m_pContext.get(), pContext->m_pDevice.get(),
+ pContext->m_pOptions.get());
+ pContext->m_pRenderer->Start(pause);
+ if (bNeedToRestore)
+ pContext->m_pDevice->RestoreState(false);
+}
+
+} // namespace
+
UnderlyingDocumentType* UnderlyingFromFPDFDocument(FPDF_DOCUMENT doc) {
return static_cast<UnderlyingDocumentType*>(doc);
}
@@ -604,6 +672,50 @@ DLLEXPORT void STDCALL FPDF_RenderPageBitmap(FPDF_BITMAP bitmap,
pPage->SetRenderContext(nullptr);
}
+DLLEXPORT void STDCALL FPDF_RenderPageBitmapWithMatrix(FPDF_BITMAP bitmap,
+ FPDF_PAGE page,
+ const FS_MATRIX* matrix,
+ const FS_RECTF* clipping,
+ int flags) {
+ if (!bitmap)
+ return;
+
+ CPDF_Page* pPage = CPDFPageFromFPDFPage(page);
+ if (!pPage)
+ return;
+
+ CPDF_PageRenderContext* pContext = new CPDF_PageRenderContext;
+ pPage->SetRenderContext(pdfium::WrapUnique(pContext));
+ CFX_FxgeDevice* pDevice = new CFX_FxgeDevice;
+ pContext->m_pDevice.reset(pDevice);
+ CFX_DIBitmap* pBitmap = CFXBitmapFromFPDFBitmap(bitmap);
+ pDevice->Attach(pBitmap, !!(flags & FPDF_REVERSE_BYTE_ORDER), nullptr, false);
+
+ CFX_Matrix transform_matrix = pPage->GetPageMatrix();
+ if (matrix) {
+ CFX_Matrix cmatrix;
+ cmatrix.a = matrix->a;
+ cmatrix.b = matrix->b;
+ cmatrix.c = matrix->c;
+ cmatrix.d = matrix->d;
+ cmatrix.e = matrix->e;
+ cmatrix.f = matrix->f;
+ transform_matrix.Concat(cmatrix);
+ }
+
+ CFX_FloatRect clipping_rect;
+ if (clipping) {
+ clipping_rect.left = clipping->left;
+ clipping_rect.bottom = clipping->bottom;
+ clipping_rect.right = clipping->right;
+ clipping_rect.top = clipping->top;
+ }
+ RenderPageImpl(pContext, pPage, transform_matrix, clipping_rect.ToFxRect(),
+ flags, true, nullptr);
+
+ pPage->SetRenderContext(nullptr);
+}
+
#ifdef _SKIA_SUPPORT_
DLLEXPORT FPDF_RECORDER STDCALL FPDF_RenderPageSkp(FPDF_PAGE page,
int size_x,
@@ -813,62 +925,10 @@ void FPDF_RenderPage_Retail(CPDF_PageRenderContext* pContext,
if (!pPage)
return;
- if (!pContext->m_pOptions)
- pContext->m_pOptions = pdfium::MakeUnique<CPDF_RenderOptions>();
-
- if (flags & FPDF_LCD_TEXT)
- pContext->m_pOptions->m_Flags |= RENDER_CLEARTYPE;
- else
- pContext->m_pOptions->m_Flags &= ~RENDER_CLEARTYPE;
- if (flags & FPDF_NO_NATIVETEXT)
- pContext->m_pOptions->m_Flags |= RENDER_NO_NATIVETEXT;
- if (flags & FPDF_RENDER_LIMITEDIMAGECACHE)
- pContext->m_pOptions->m_Flags |= RENDER_LIMITEDIMAGECACHE;
- if (flags & FPDF_RENDER_FORCEHALFTONE)
- pContext->m_pOptions->m_Flags |= RENDER_FORCE_HALFTONE;
-#ifndef PDF_ENABLE_XFA
- if (flags & FPDF_RENDER_NO_SMOOTHTEXT)
- pContext->m_pOptions->m_Flags |= RENDER_NOTEXTSMOOTH;
- if (flags & FPDF_RENDER_NO_SMOOTHIMAGE)
- pContext->m_pOptions->m_Flags |= RENDER_NOIMAGESMOOTH;
- if (flags & FPDF_RENDER_NO_SMOOTHPATH)
- pContext->m_pOptions->m_Flags |= RENDER_NOPATHSMOOTH;
-#endif // PDF_ENABLE_XFA
- // Grayscale output
- if (flags & FPDF_GRAYSCALE) {
- pContext->m_pOptions->m_ColorMode = RENDER_COLOR_GRAY;
- pContext->m_pOptions->m_ForeColor = 0;
- pContext->m_pOptions->m_BackColor = 0xffffff;
- }
- const CPDF_OCContext::UsageType usage =
- (flags & FPDF_PRINTING) ? CPDF_OCContext::Print : CPDF_OCContext::View;
- pContext->m_pOptions->m_AddFlags = flags >> 8;
- pContext->m_pOptions->m_pOCContext =
- new CPDF_OCContext(pPage->m_pDocument, usage);
-
CFX_Matrix matrix;
pPage->GetDisplayMatrix(matrix, start_x, start_y, size_x, size_y, rotate);
-
- pContext->m_pDevice->SaveState();
- pContext->m_pDevice->SetClip_Rect(
- FX_RECT(start_x, start_y, start_x + size_x, start_y + size_y));
-
- pContext->m_pContext = pdfium::MakeUnique<CPDF_RenderContext>(pPage);
- pContext->m_pContext->AppendLayer(pPage, &matrix);
-
- if (flags & FPDF_ANNOT) {
- pContext->m_pAnnots = pdfium::MakeUnique<CPDF_AnnotList>(pPage);
- bool bPrinting = pContext->m_pDevice->GetDeviceClass() != FXDC_DISPLAY;
- pContext->m_pAnnots->DisplayAnnots(pPage, pContext->m_pContext.get(),
- bPrinting, &matrix, false, nullptr);
- }
-
- pContext->m_pRenderer = pdfium::MakeUnique<CPDF_ProgressiveRenderer>(
- pContext->m_pContext.get(), pContext->m_pDevice.get(),
- pContext->m_pOptions.get());
- pContext->m_pRenderer->Start(pause);
- if (bNeedToRestore)
- pContext->m_pDevice->RestoreState(false);
+ FX_RECT rect(start_x, start_y, start_x + size_x, start_y + size_y);
+ RenderPageImpl(pContext, pPage, matrix, rect, flags, bNeedToRestore, pause);
}
DLLEXPORT int STDCALL FPDF_GetPageSizeByIndex(FPDF_DOCUMENT document,
diff --git a/fpdfsdk/fpdfview_c_api_test.c b/fpdfsdk/fpdfview_c_api_test.c
index ed9a3fafe2..8cbbf4f3db 100644
--- a/fpdfsdk/fpdfview_c_api_test.c
+++ b/fpdfsdk/fpdfview_c_api_test.c
@@ -225,6 +225,7 @@ int CheckPDFiumCApi() {
CHK(FPDF_GetPageHeight);
CHK(FPDF_GetPageSizeByIndex);
CHK(FPDF_RenderPageBitmap);
+ CHK(FPDF_RenderPageBitmapWithMatrix);
CHK(FPDF_ClosePage);
CHK(FPDF_CloseDocument);
CHK(FPDF_DeviceToPage);
diff --git a/fpdfsdk/fpdfview_embeddertest.cpp b/fpdfsdk/fpdfview_embeddertest.cpp
index 65e52fec39..1d94b72553 100644
--- a/fpdfsdk/fpdfview_embeddertest.cpp
+++ b/fpdfsdk/fpdfview_embeddertest.cpp
@@ -327,3 +327,54 @@ TEST_F(FPDFViewEmbeddertest, Hang_355) {
TEST_F(FPDFViewEmbeddertest, Hang_360) {
EXPECT_FALSE(OpenDocument("bug_360.pdf"));
}
+
+TEST_F(FPDFViewEmbeddertest, FPDF_RenderPageBitmapWithMatrix) {
+ const char kAllBlackMd5sum[] = "5708fc5c4a8bd0abde99c8e8f0390615";
+ const char kTopLeftQuarterBlackMd5sum[] = "24e4d1ec06fa0258af758cfc8b2ad50a";
+
+ EXPECT_TRUE(OpenDocument("black.pdf"));
+ FPDF_PAGE page = LoadPage(0);
+ EXPECT_NE(nullptr, page);
+ const int width = static_cast<int>(FPDF_GetPageWidth(page));
+ const int height = static_cast<int>(FPDF_GetPageHeight(page));
+ EXPECT_EQ(612, width);
+ EXPECT_EQ(792, height);
+
+ FPDF_BITMAP bitmap = RenderPage(page);
+ CompareBitmap(bitmap, width, height, kAllBlackMd5sum);
+ FPDFBitmap_Destroy(bitmap);
+
+ // Try rendering with an identity matrix. The output should be the same as
+ // the RenderPage() output.
+ FS_MATRIX matrix;
+ matrix.a = 1;
+ matrix.b = 0;
+ matrix.c = 0;
+ matrix.d = 1;
+ matrix.e = 0;
+ matrix.f = 0;
+
+ FS_RECTF rect;
+ rect.left = 0;
+ rect.top = 0;
+ rect.right = width;
+ rect.bottom = height;
+
+ bitmap = FPDFBitmap_Create(width, height, 0);
+ FPDFBitmap_FillRect(bitmap, 0, 0, width, height, 0xFFFFFFFF);
+ FPDF_RenderPageBitmapWithMatrix(bitmap, page, &matrix, &rect, 0);
+ CompareBitmap(bitmap, width, height, kAllBlackMd5sum);
+ FPDFBitmap_Destroy(bitmap);
+
+ // Now render again with the image scaled.
+ matrix.a = 0.5;
+ matrix.d = 0.5;
+
+ bitmap = FPDFBitmap_Create(width, height, 0);
+ FPDFBitmap_FillRect(bitmap, 0, 0, width, height, 0xFFFFFFFF);
+ FPDF_RenderPageBitmapWithMatrix(bitmap, page, &matrix, &rect, 0);
+ CompareBitmap(bitmap, width, height, kTopLeftQuarterBlackMd5sum);
+ FPDFBitmap_Destroy(bitmap);
+
+ UnloadPage(page);
+}
diff --git a/public/fpdfview.h b/public/fpdfview.h
index 581951c7e2..403f4e46ec 100644
--- a/public/fpdfview.h
+++ b/public/fpdfview.h
@@ -596,11 +596,11 @@ DLLEXPORT void STDCALL FPDF_RenderPage(HDC dc,
// 1 (rotated 90 degrees clockwise)
// 2 (rotated 180 degrees)
// 3 (rotated 90 degrees counter-clockwise)
-// flags - 0 for normal display, or combination of flags
-// defined above. With FPDF_ANNOT flag, it renders all
-// annotations that does not require user-interaction,
-// which are all annotations except widget and popup
-// annotations.
+// flags - 0 for normal display, or combination of the Page
+// Rendering flags defined above. With the FPDF_ANNOT
+// flag, it renders all annotations that do not require
+// user-interaction, which are all annotations except
+// widget and popup annotations.
// Return value:
// None.
DLLEXPORT void STDCALL FPDF_RenderPageBitmap(FPDF_BITMAP bitmap,
@@ -612,6 +612,28 @@ DLLEXPORT void STDCALL FPDF_RenderPageBitmap(FPDF_BITMAP bitmap,
int rotate,
int flags);
+// Function: FPDF_RenderPageBitmapWithMatrix
+// Render contents of a page to a device independent bitmap.
+// Parameters:
+// bitmap - Handle to the device independent bitmap (as the
+// output buffer). The bitmap handle can be created
+// by FPDFBitmap_Create.
+// page - Handle to the page. Returned by FPDF_LoadPage
+// matrix - The transform matrix.
+// clipping - The rect to clip to.
+// flags - 0 for normal display, or combination of the Page
+// Rendering flags defined above. With the FPDF_ANNOT
+// flag, it renders all annotations that do not require
+// user-interaction, which are all annotations except
+// widget and popup annotations.
+// Return value:
+// None.
+DLLEXPORT void STDCALL FPDF_RenderPageBitmapWithMatrix(FPDF_BITMAP bitmap,
+ FPDF_PAGE page,
+ const FS_MATRIX* matrix,
+ const FS_RECTF* clipping,
+ int flags);
+
#ifdef _SKIA_SUPPORT_
DLLEXPORT FPDF_RECORDER STDCALL FPDF_RenderPageSkp(FPDF_PAGE page,
int size_x,