Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit d55f20d3 authored by Philip P. Moltmann's avatar Philip P. Moltmann
Browse files

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
parent 60968b97
Loading
Loading
Loading
Loading
+0 −3
Original line number Diff line number Diff line
@@ -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 \
+31 −107
Original line number Diff line number Diff line
@@ -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();
}
+14 −2
Original line number Diff line number Diff line
@@ -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);