Use only official pdfium APIs

Fixes: 28051413
Test: cts-tradefed run cts-dev -m CtsGraphicsTestCases -t android.graphics.pdf.cts
      cts-tradefed run cts-dev -m Print -t android.print.pdf.cts
Change-Id: Iab52463ba225d3cddb1e97fe52cb9f56318cce68
This commit is contained in:
Philip P. Moltmann
2017-02-16 15:18:40 -08:00
parent 60968b9783
commit d55f20d301
3 changed files with 45 additions and 112 deletions

View File

@ -210,10 +210,7 @@ LOCAL_C_INCLUDES += \
$(TOP)/system/media/camera/include \
$(TOP)/system/netd/include \
external/giflib \
external/pdfium/core/include/fpdfapi \
external/pdfium/fpdfsdk/include \
external/pdfium/public \
external/pdfium \
external/skia/include/private \
external/skia/src/core \
external/skia/src/effects \

View File

@ -23,11 +23,6 @@
#include "SkMatrix.h"
#include "fpdfview.h"
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wdelete-non-virtual-dtor"
#include "fsdk_rendercontext.h"
#pragma GCC diagnostic pop
#include "core_jni_helpers.h"
#include <vector>
#include <utils/Log.h>
@ -80,103 +75,10 @@ static void nativeClosePage(JNIEnv* env, jclass thiz, jlong pagePtr) {
HANDLE_PDFIUM_ERROR_STATE(env)
}
static void DropContext(void* data) {
delete (CRenderContext*) data;
}
static void renderPageBitmap(FPDF_BITMAP bitmap, FPDF_PAGE page, int destLeft, int destTop,
int destRight, int destBottom, SkMatrix* transform, int flags) {
// Note: this code ignores the currently unused RENDER_NO_NATIVETEXT,
// FPDF_RENDER_LIMITEDIMAGECACHE, FPDF_RENDER_FORCEHALFTONE, FPDF_GRAYSCALE,
// and FPDF_ANNOT flags. To add support for that refer to FPDF_RenderPage_Retail
// in fpdfview.cpp
CRenderContext* pContext = new CRenderContext;
CPDF_Page* pPage = (CPDF_Page*) page;
pPage->SetPrivateData((void*) 1, pContext, DropContext);
CFX_FxgeDevice* fxgeDevice = new CFX_FxgeDevice;
pContext->m_pDevice = fxgeDevice;
// Reverse the bytes (last argument TRUE) since the Android
// format is ARGB while the renderer uses BGRA internally.
fxgeDevice->Attach((CFX_DIBitmap*) bitmap, 0, TRUE);
CPDF_RenderOptions* renderOptions = pContext->m_pOptions;
if (!renderOptions) {
renderOptions = new CPDF_RenderOptions;
pContext->m_pOptions = renderOptions;
}
if (flags & FPDF_LCD_TEXT) {
renderOptions->m_Flags |= RENDER_CLEARTYPE;
} else {
renderOptions->m_Flags &= ~RENDER_CLEARTYPE;
}
const CPDF_OCContext::UsageType usage = (flags & FPDF_PRINTING)
? CPDF_OCContext::Print : CPDF_OCContext::View;
renderOptions->m_AddFlags = flags >> 8;
renderOptions->m_pOCContext = new CPDF_OCContext(pPage->m_pDocument, usage);
fxgeDevice->SaveState();
FX_RECT clip;
clip.left = destLeft;
clip.right = destRight;
clip.top = destTop;
clip.bottom = destBottom;
fxgeDevice->SetClip_Rect(&clip);
CPDF_RenderContext* pageContext = new CPDF_RenderContext(pPage);
pContext->m_pContext = pageContext;
CFX_Matrix matrix;
if (!transform) {
pPage->GetDisplayMatrix(matrix, destLeft, destTop, destRight - destLeft,
destBottom - destTop, 0);
} else {
// PDF's coordinate system origin is left-bottom while
// in graphics it is the top-left, so remap the origin.
SkMatrix reflectOnX = SkMatrix::MakeScale(1, -1);
SkMatrix moveUp = SkMatrix::MakeTrans(0, FPDF_GetPageHeight(page));
SkMatrix m = SkMatrix::Concat(moveUp, reflectOnX);
// Concatenate transformation and origin transformation
m.setConcat(*transform, m);
SkScalar transformValues[6];
if (!m.asAffine(transformValues)) {
// Already checked for a return value of false in the caller, so this should never
// happen.
ALOGE("Error rendering page!");
}
matrix = {transformValues[SkMatrix::kAScaleX], transformValues[SkMatrix::kASkewY],
transformValues[SkMatrix::kASkewX], transformValues[SkMatrix::kAScaleY],
transformValues[SkMatrix::kATransX], transformValues[SkMatrix::kATransY]};
}
pageContext->AppendObjectList(pPage, &matrix);
pContext->m_pRenderer = new CPDF_ProgressiveRenderer(pageContext, fxgeDevice, renderOptions);
pContext->m_pRenderer->Start(NULL);
fxgeDevice->RestoreState();
pPage->RemovePrivateData((void*) 1);
delete pContext;
}
static void nativeRenderPage(JNIEnv* env, jclass thiz, jlong documentPtr, jlong pagePtr,
jobject jbitmap, jint destLeft, jint destTop, jint destRight, jint destBottom,
jlong matrixPtr, jint renderMode) {
jobject jbitmap, jint clipLeft, jint clipTop, jint clipRight, jint clipBottom,
jlong transformPtr, jint renderMode) {
FPDF_PAGE page = reinterpret_cast<FPDF_PAGE>(pagePtr);
SkMatrix* skMatrix = reinterpret_cast<SkMatrix*>(matrixPtr);
SkBitmap skBitmap;
GraphicsJNI::getSkBitmap(env, jbitmap, &skBitmap);
@ -187,27 +89,49 @@ static void nativeRenderPage(JNIEnv* env, jclass thiz, jlong documentPtr, jlong
FPDF_BITMAP bitmap = FPDFBitmap_CreateEx(skBitmap.width(), skBitmap.height(),
FPDFBitmap_BGRA, skBitmap.getPixels(), stride);
if (!bitmap) {
ALOGE("Erorr creating bitmap");
bool isExceptionPending = forwardPdfiumError(env);
if (isExceptionPending || bitmap == NULL) {
ALOGE("Error creating bitmap");
return;
}
int renderFlags = 0;
int renderFlags = FPDF_REVERSE_BYTE_ORDER;
if (renderMode == RENDER_MODE_FOR_DISPLAY) {
renderFlags |= FPDF_LCD_TEXT;
} else if (renderMode == RENDER_MODE_FOR_PRINT) {
renderFlags |= FPDF_PRINTING;
}
if (skMatrix && !skMatrix->asAffine(NULL)) {
// PDF's coordinate system origin is left-bottom while in graphics it
// is the top-left. So, translate the PDF coordinates to ours.
SkMatrix reflectOnX = SkMatrix::MakeScale(1, -1);
SkMatrix moveUp = SkMatrix::MakeTrans(0, FPDF_GetPageHeight(page));
SkMatrix coordinateChange = SkMatrix::Concat(moveUp, reflectOnX);
// Apply the transformation
SkMatrix matrix;
if (transformPtr == 0) {
matrix = coordinateChange;
} else {
matrix = SkMatrix::Concat(*reinterpret_cast<SkMatrix*>(transformPtr), coordinateChange);
}
SkScalar transformValues[6];
if (!matrix.asAffine(transformValues)) {
jniThrowException(env, "java/lang/IllegalArgumentException",
"transform matrix has perspective. Only affine matrices are allowed.");
return;
}
renderPageBitmap(bitmap, page, destLeft, destTop, destRight,
destBottom, skMatrix, renderFlags);
FS_MATRIX transform = {transformValues[SkMatrix::kAScaleX], transformValues[SkMatrix::kASkewY],
transformValues[SkMatrix::kASkewX], transformValues[SkMatrix::kAScaleY],
transformValues[SkMatrix::kATransX],
transformValues[SkMatrix::kATransY]};
FS_RECTF clip = {(float) clipLeft, (float) clipTop, (float) clipRight, (float) clipBottom};
FPDF_RenderPageBitmapWithMatrix(bitmap, page, &transform, &clip, renderFlags);
HANDLE_PDFIUM_ERROR_STATE(env);
skBitmap.notifyPixelsChanged();
}

View File

@ -411,7 +411,18 @@ public final class PdfRenderer implements AutoCloseable {
final int contentBottom = (destClip != null) ? destClip.bottom
: destination.getHeight();
final long transformPtr = (transform != null) ? transform.native_instance : 0;
// If transform is not set, stretch page to whole clipped area
if (transform == null) {
int clipWidth = contentRight - contentLeft;
int clipHeight = contentBottom - contentTop;
transform = new Matrix();
transform.postScale((float)clipWidth / getWidth(),
(float)clipHeight / getHeight());
transform.postTranslate(contentLeft, contentTop);
}
final long transformPtr = transform.native_instance;
synchronized (sPdfiumLock) {
nativeRenderPage(mNativeDocument, mNativePage, destination, contentLeft,
@ -463,7 +474,8 @@ public final class PdfRenderer implements AutoCloseable {
private static native int nativeGetPageCount(long documentPtr);
private static native boolean nativeScaleForPrinting(long documentPtr);
private static native void nativeRenderPage(long documentPtr, long pagePtr, Bitmap dest,
int destLeft, int destTop, int destRight, int destBottom, long matrixPtr, int renderMode);
int clipLeft, int clipTop, int clipRight, int clipBottom, long transformPtr,
int renderMode);
private static native long nativeOpenPageAndGetSize(long documentPtr, int pageIndex,
Point outSize);
private static native void nativeClosePage(long pagePtr);