diff options
| author | 2024-01-18 18:38:50 -0700 | |
|---|---|---|
| committer | 2024-02-03 00:26:07 +0000 | |
| commit | d84522ce1ff9ffd5b24d3b8d8891cd49491894f2 (patch) | |
| tree | b826752f81704edf8844db9bb151d16814c217f3 | |
| parent | 6971e714a20244355d0a0cba53370abcb1522848 (diff) | |
Move PdfRenderer java and native code to packages/providers/MediaProvider
PdfEditor will be mainlined post-V due to API review bandwidth constraints.
Test: manual testing against printspooler usage of this API, CTS
Bug: 319339682
Change-Id: I65fa29c0268f9fa9294807e8ba3fb68f7a7519dd
| -rw-r--r-- | core/api/current.txt | 18 | ||||
| -rw-r--r-- | graphics/java/android/graphics/pdf/PdfEditor.java | 32 | ||||
| -rw-r--r-- | graphics/java/android/graphics/pdf/PdfRenderer.java | 502 | ||||
| -rw-r--r-- | libs/hwui/Android.bp | 1 | ||||
| -rw-r--r-- | libs/hwui/apex/jni_runtime.cpp | 2 | ||||
| -rw-r--r-- | libs/hwui/jni/pdf/PdfRenderer.cpp | 134 |
6 files changed, 20 insertions, 669 deletions
diff --git a/core/api/current.txt b/core/api/current.txt index a3775b05cf2e..33d171239b7e 100644 --- a/core/api/current.txt +++ b/core/api/current.txt @@ -17922,24 +17922,6 @@ package android.graphics.pdf { method public android.graphics.pdf.PdfDocument.PageInfo.Builder setContentRect(android.graphics.Rect); } - public final class PdfRenderer implements java.lang.AutoCloseable { - ctor public PdfRenderer(@NonNull android.os.ParcelFileDescriptor) throws java.io.IOException; - method public void close(); - method public int getPageCount(); - method public android.graphics.pdf.PdfRenderer.Page openPage(int); - method public boolean shouldScaleForPrinting(); - } - - public final class PdfRenderer.Page implements java.lang.AutoCloseable { - method public void close(); - method public int getHeight(); - method public int getIndex(); - method public int getWidth(); - method public void render(@NonNull android.graphics.Bitmap, @Nullable android.graphics.Rect, @Nullable android.graphics.Matrix, int); - field public static final int RENDER_MODE_FOR_DISPLAY = 1; // 0x1 - field public static final int RENDER_MODE_FOR_PRINT = 2; // 0x2 - } - } package android.graphics.text { diff --git a/graphics/java/android/graphics/pdf/PdfEditor.java b/graphics/java/android/graphics/pdf/PdfEditor.java index 3cd709ea10e5..69e19824da26 100644 --- a/graphics/java/android/graphics/pdf/PdfEditor.java +++ b/graphics/java/android/graphics/pdf/PdfEditor.java @@ -25,7 +25,9 @@ import android.os.ParcelFileDescriptor; import android.system.ErrnoException; import android.system.Os; import android.system.OsConstants; + import dalvik.system.CloseGuard; + import libcore.io.IoUtils; import java.io.IOException; @@ -37,6 +39,12 @@ import java.io.IOException; */ public final class PdfEditor { + /** + * Any call the native pdfium code has to be single threaded as the library does not support + * parallel use. + */ + private static final Object sPdfiumLock = new Object(); + private final CloseGuard mCloseGuard = CloseGuard.get(); private long mNativeDocument; @@ -79,7 +87,7 @@ public final class PdfEditor { } mInput = input; - synchronized (PdfRenderer.sPdfiumLock) { + synchronized (sPdfiumLock) { mNativeDocument = nativeOpen(mInput.getFd(), size); try { mPageCount = nativeGetPageCount(mNativeDocument); @@ -112,7 +120,7 @@ public final class PdfEditor { throwIfClosed(); throwIfPageNotInDocument(pageIndex); - synchronized (PdfRenderer.sPdfiumLock) { + synchronized (sPdfiumLock) { mPageCount = nativeRemovePage(mNativeDocument, pageIndex); } } @@ -138,12 +146,12 @@ public final class PdfEditor { Point size = new Point(); getPageSize(pageIndex, size); - synchronized (PdfRenderer.sPdfiumLock) { + synchronized (sPdfiumLock) { nativeSetTransformAndClip(mNativeDocument, pageIndex, transform.ni(), 0, 0, size.x, size.y); } } else { - synchronized (PdfRenderer.sPdfiumLock) { + synchronized (sPdfiumLock) { nativeSetTransformAndClip(mNativeDocument, pageIndex, transform.ni(), clip.left, clip.top, clip.right, clip.bottom); } @@ -161,7 +169,7 @@ public final class PdfEditor { throwIfOutSizeNull(outSize); throwIfPageNotInDocument(pageIndex); - synchronized (PdfRenderer.sPdfiumLock) { + synchronized (sPdfiumLock) { nativeGetPageSize(mNativeDocument, pageIndex, outSize); } } @@ -177,7 +185,7 @@ public final class PdfEditor { throwIfOutMediaBoxNull(outMediaBox); throwIfPageNotInDocument(pageIndex); - synchronized (PdfRenderer.sPdfiumLock) { + synchronized (sPdfiumLock) { return nativeGetPageMediaBox(mNativeDocument, pageIndex, outMediaBox); } } @@ -193,7 +201,7 @@ public final class PdfEditor { throwIfMediaBoxNull(mediaBox); throwIfPageNotInDocument(pageIndex); - synchronized (PdfRenderer.sPdfiumLock) { + synchronized (sPdfiumLock) { nativeSetPageMediaBox(mNativeDocument, pageIndex, mediaBox); } } @@ -209,7 +217,7 @@ public final class PdfEditor { throwIfOutCropBoxNull(outCropBox); throwIfPageNotInDocument(pageIndex); - synchronized (PdfRenderer.sPdfiumLock) { + synchronized (sPdfiumLock) { return nativeGetPageCropBox(mNativeDocument, pageIndex, outCropBox); } } @@ -225,7 +233,7 @@ public final class PdfEditor { throwIfCropBoxNull(cropBox); throwIfPageNotInDocument(pageIndex); - synchronized (PdfRenderer.sPdfiumLock) { + synchronized (sPdfiumLock) { nativeSetPageCropBox(mNativeDocument, pageIndex, cropBox); } } @@ -238,7 +246,7 @@ public final class PdfEditor { public boolean shouldScaleForPrinting() { throwIfClosed(); - synchronized (PdfRenderer.sPdfiumLock) { + synchronized (sPdfiumLock) { return nativeScaleForPrinting(mNativeDocument); } } @@ -255,7 +263,7 @@ public final class PdfEditor { try { throwIfClosed(); - synchronized (PdfRenderer.sPdfiumLock) { + synchronized (sPdfiumLock) { nativeWrite(mNativeDocument, output.getFd()); } } finally { @@ -287,7 +295,7 @@ public final class PdfEditor { private void doClose() { if (mNativeDocument != 0) { - synchronized (PdfRenderer.sPdfiumLock) { + synchronized (sPdfiumLock) { nativeClose(mNativeDocument); } mNativeDocument = 0; diff --git a/graphics/java/android/graphics/pdf/PdfRenderer.java b/graphics/java/android/graphics/pdf/PdfRenderer.java deleted file mode 100644 index 4666963b5dd4..000000000000 --- a/graphics/java/android/graphics/pdf/PdfRenderer.java +++ /dev/null @@ -1,502 +0,0 @@ -/* - * Copyright (C) 2014 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package android.graphics.pdf; - -import android.annotation.IntDef; -import android.annotation.NonNull; -import android.annotation.Nullable; -import android.compat.annotation.UnsupportedAppUsage; -import android.graphics.Bitmap; -import android.graphics.Bitmap.Config; -import android.graphics.Matrix; -import android.graphics.Point; -import android.graphics.Rect; -import android.os.Build; -import android.os.ParcelFileDescriptor; -import android.system.ErrnoException; -import android.system.Os; -import android.system.OsConstants; - -import com.android.internal.util.Preconditions; - -import dalvik.system.CloseGuard; - -import libcore.io.IoUtils; - -import java.io.IOException; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; - -/** - * <p> - * This class enables rendering a PDF document. This class is not thread safe. - * </p> - * <p> - * If you want to render a PDF, you create a renderer and for every page you want - * to render, you open the page, render it, and close the page. After you are done - * with rendering, you close the renderer. After the renderer is closed it should not - * be used anymore. Note that the pages are rendered one by one, i.e. you can have - * only a single page opened at any given time. - * </p> - * <p> - * A typical use of the APIs to render a PDF looks like this: - * </p> - * <pre> - * // create a new renderer - * PdfRenderer renderer = new PdfRenderer(getSeekableFileDescriptor()); - * - * // let us just render all pages - * final int pageCount = renderer.getPageCount(); - * for (int i = 0; i < pageCount; i++) { - * Page page = renderer.openPage(i); - * - * // say we render for showing on the screen - * page.render(mBitmap, null, null, Page.RENDER_MODE_FOR_DISPLAY); - * - * // do stuff with the bitmap - * - * // close the page - * page.close(); - * } - * - * // close the renderer - * renderer.close(); - * </pre> - * - * <h3>Print preview and print output</h3> - * <p> - * If you are using this class to rasterize a PDF for printing or show a print - * preview, it is recommended that you respect the following contract in order - * to provide a consistent user experience when seeing a preview and printing, - * i.e. the user sees a preview that is the same as the printout. - * </p> - * <ul> - * <li> - * Respect the property whether the document would like to be scaled for printing - * as per {@link #shouldScaleForPrinting()}. - * </li> - * <li> - * When scaling a document for printing the aspect ratio should be preserved. - * </li> - * <li> - * Do not inset the content with any margins from the {@link android.print.PrintAttributes} - * as the application is responsible to render it such that the margins are respected. - * </li> - * <li> - * If document page size is greater than the printed media size the content should - * be anchored to the upper left corner of the page for left-to-right locales and - * top right corner for right-to-left locales. - * </li> - * </ul> - * - * @see #close() - */ -public final class PdfRenderer implements AutoCloseable { - /** - * Any call the native pdfium code has to be single threaded as the library does not support - * parallel use. - */ - final static Object sPdfiumLock = new Object(); - - private final CloseGuard mCloseGuard = CloseGuard.get(); - - private final Point mTempPoint = new Point(); - - private long mNativeDocument; - - private final int mPageCount; - - private ParcelFileDescriptor mInput; - - @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) - private Page mCurrentPage; - - /** @hide */ - @IntDef({ - Page.RENDER_MODE_FOR_DISPLAY, - Page.RENDER_MODE_FOR_PRINT - }) - @Retention(RetentionPolicy.SOURCE) - public @interface RenderMode {} - - /** - * Creates a new instance. - * <p> - * <strong>Note:</strong> The provided file descriptor must be <strong>seekable</strong>, - * i.e. its data being randomly accessed, e.g. pointing to a file. - * </p> - * <p> - * <strong>Note:</strong> This class takes ownership of the passed in file descriptor - * and is responsible for closing it when the renderer is closed. - * </p> - * <p> - * If the file is from an untrusted source it is recommended to run the renderer in a separate, - * isolated process with minimal permissions to limit the impact of security exploits. - * </p> - * - * @param input Seekable file descriptor to read from. - * - * @throws java.io.IOException If an error occurs while reading the file. - * @throws java.lang.SecurityException If the file requires a password or - * the security scheme is not supported. - */ - public PdfRenderer(@NonNull ParcelFileDescriptor input) throws IOException { - if (input == null) { - throw new NullPointerException("input cannot be null"); - } - - final long size; - try { - Os.lseek(input.getFileDescriptor(), 0, OsConstants.SEEK_SET); - size = Os.fstat(input.getFileDescriptor()).st_size; - } catch (ErrnoException ee) { - throw new IllegalArgumentException("file descriptor not seekable"); - } - mInput = input; - - synchronized (sPdfiumLock) { - mNativeDocument = nativeCreate(mInput.getFd(), size); - try { - mPageCount = nativeGetPageCount(mNativeDocument); - } catch (Throwable t) { - nativeClose(mNativeDocument); - mNativeDocument = 0; - throw t; - } - } - - mCloseGuard.open("close"); - } - - /** - * Closes this renderer. You should not use this instance - * after this method is called. - */ - public void close() { - throwIfClosed(); - throwIfPageOpened(); - doClose(); - } - - /** - * Gets the number of pages in the document. - * - * @return The page count. - */ - public int getPageCount() { - throwIfClosed(); - return mPageCount; - } - - /** - * Gets whether the document prefers to be scaled for printing. - * You should take this info account if the document is rendered - * for printing and the target media size differs from the page - * size. - * - * @return If to scale the document. - */ - public boolean shouldScaleForPrinting() { - throwIfClosed(); - - synchronized (sPdfiumLock) { - return nativeScaleForPrinting(mNativeDocument); - } - } - - /** - * Opens a page for rendering. - * - * @param index The page index. - * @return A page that can be rendered. - * - * @see android.graphics.pdf.PdfRenderer.Page#close() PdfRenderer.Page.close() - */ - public Page openPage(int index) { - throwIfClosed(); - throwIfPageOpened(); - throwIfPageNotInDocument(index); - mCurrentPage = new Page(index); - return mCurrentPage; - } - - @Override - protected void finalize() throws Throwable { - try { - if (mCloseGuard != null) { - mCloseGuard.warnIfOpen(); - } - - doClose(); - } finally { - super.finalize(); - } - } - - @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) - private void doClose() { - if (mCurrentPage != null) { - mCurrentPage.close(); - mCurrentPage = null; - } - - if (mNativeDocument != 0) { - synchronized (sPdfiumLock) { - nativeClose(mNativeDocument); - } - mNativeDocument = 0; - } - - if (mInput != null) { - IoUtils.closeQuietly(mInput); - mInput = null; - } - mCloseGuard.close(); - } - - private void throwIfClosed() { - if (mInput == null) { - throw new IllegalStateException("Already closed"); - } - } - - private void throwIfPageOpened() { - if (mCurrentPage != null) { - throw new IllegalStateException("Current page not closed"); - } - } - - private void throwIfPageNotInDocument(int pageIndex) { - if (pageIndex < 0 || pageIndex >= mPageCount) { - throw new IllegalArgumentException("Invalid page index"); - } - } - - /** - * This class represents a PDF document page for rendering. - */ - public final class Page implements AutoCloseable { - - private final CloseGuard mCloseGuard = CloseGuard.get(); - - /** - * Mode to render the content for display on a screen. - */ - public static final int RENDER_MODE_FOR_DISPLAY = 1; - - /** - * Mode to render the content for printing. - */ - public static final int RENDER_MODE_FOR_PRINT = 2; - - private final int mIndex; - private final int mWidth; - private final int mHeight; - - private long mNativePage; - - private Page(int index) { - Point size = mTempPoint; - synchronized (sPdfiumLock) { - mNativePage = nativeOpenPageAndGetSize(mNativeDocument, index, size); - } - mIndex = index; - mWidth = size.x; - mHeight = size.y; - mCloseGuard.open("close"); - } - - /** - * Gets the page index. - * - * @return The index. - */ - public int getIndex() { - return mIndex; - } - - /** - * Gets the page width in points (1/72"). - * - * @return The width in points. - */ - public int getWidth() { - return mWidth; - } - - /** - * Gets the page height in points (1/72"). - * - * @return The height in points. - */ - public int getHeight() { - return mHeight; - } - - /** - * Renders a page to a bitmap. - * <p> - * You may optionally specify a rectangular clip in the bitmap bounds. No rendering - * outside the clip will be performed, hence it is your responsibility to initialize - * the bitmap outside the clip. - * </p> - * <p> - * You may optionally specify a matrix to transform the content from page coordinates - * which are in points (1/72") to bitmap coordinates which are in pixels. If this - * matrix is not provided this method will apply a transformation that will fit the - * whole page to the destination clip if provided or the destination bitmap if no - * clip is provided. - * </p> - * <p> - * The clip and transformation are useful for implementing tile rendering where the - * destination bitmap contains a portion of the image, for example when zooming. - * Another useful application is for printing where the size of the bitmap holding - * the page is too large and a client can render the page in stripes. - * </p> - * <p> - * <strong>Note: </strong> The destination bitmap format must be - * {@link Config#ARGB_8888 ARGB}. - * </p> - * <p> - * <strong>Note: </strong> The optional transformation matrix must be affine as per - * {@link android.graphics.Matrix#isAffine() Matrix.isAffine()}. Hence, you can specify - * rotation, scaling, translation but not a perspective transformation. - * </p> - * - * @param destination Destination bitmap to which to render. - * @param destClip Optional clip in the bitmap bounds. - * @param transform Optional transformation to apply when rendering. - * @param renderMode The render mode. - * - * @see #RENDER_MODE_FOR_DISPLAY - * @see #RENDER_MODE_FOR_PRINT - */ - public void render(@NonNull Bitmap destination, @Nullable Rect destClip, - @Nullable Matrix transform, @RenderMode int renderMode) { - if (mNativePage == 0) { - throw new NullPointerException(); - } - - destination = Preconditions.checkNotNull(destination, "bitmap null"); - - if (destination.getConfig() != Config.ARGB_8888) { - throw new IllegalArgumentException("Unsupported pixel format"); - } - - if (destClip != null) { - if (destClip.left < 0 || destClip.top < 0 - || destClip.right > destination.getWidth() - || destClip.bottom > destination.getHeight()) { - throw new IllegalArgumentException("destBounds not in destination"); - } - } - - if (transform != null && !transform.isAffine()) { - throw new IllegalArgumentException("transform not affine"); - } - - if (renderMode != RENDER_MODE_FOR_PRINT && renderMode != RENDER_MODE_FOR_DISPLAY) { - throw new IllegalArgumentException("Unsupported render mode"); - } - - if (renderMode == RENDER_MODE_FOR_PRINT && renderMode == RENDER_MODE_FOR_DISPLAY) { - throw new IllegalArgumentException("Only single render mode supported"); - } - - final int contentLeft = (destClip != null) ? destClip.left : 0; - final int contentTop = (destClip != null) ? destClip.top : 0; - final int contentRight = (destClip != null) ? destClip.right - : destination.getWidth(); - final int contentBottom = (destClip != null) ? destClip.bottom - : destination.getHeight(); - - // 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); - } - - // FIXME: This code is planned to be outside the UI rendering module, so it should not - // be able to access native instances from Bitmap, Matrix, etc. - final long transformPtr = transform.ni(); - - synchronized (sPdfiumLock) { - nativeRenderPage(mNativeDocument, mNativePage, destination.getNativeInstance(), - contentLeft, contentTop, contentRight, contentBottom, transformPtr, - renderMode); - } - } - - /** - * Closes this page. - * - * @see android.graphics.pdf.PdfRenderer#openPage(int) - */ - @Override - public void close() { - throwIfClosed(); - doClose(); - } - - @Override - protected void finalize() throws Throwable { - try { - if (mCloseGuard != null) { - mCloseGuard.warnIfOpen(); - } - - doClose(); - } finally { - super.finalize(); - } - } - - private void doClose() { - if (mNativePage != 0) { - synchronized (sPdfiumLock) { - nativeClosePage(mNativePage); - } - mNativePage = 0; - } - - mCloseGuard.close(); - mCurrentPage = null; - } - - private void throwIfClosed() { - if (mNativePage == 0) { - throw new IllegalStateException("Already closed"); - } - } - } - - private static native long nativeCreate(int fd, long size); - private static native void nativeClose(long documentPtr); - private static native int nativeGetPageCount(long documentPtr); - private static native boolean nativeScaleForPrinting(long documentPtr); - private static native void nativeRenderPage(long documentPtr, long pagePtr, long bitmapHandle, - 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); -} diff --git a/libs/hwui/Android.bp b/libs/hwui/Android.bp index 4e330da417be..e4f3e2defb25 100644 --- a/libs/hwui/Android.bp +++ b/libs/hwui/Android.bp @@ -427,7 +427,6 @@ cc_defaults { "jni/MovieImpl.cpp", "jni/pdf/PdfDocument.cpp", "jni/pdf/PdfEditor.cpp", - "jni/pdf/PdfRenderer.cpp", "jni/pdf/PdfUtils.cpp", ], shared_libs: [ diff --git a/libs/hwui/apex/jni_runtime.cpp b/libs/hwui/apex/jni_runtime.cpp index 883f273b5d3d..fb0cdb034575 100644 --- a/libs/hwui/apex/jni_runtime.cpp +++ b/libs/hwui/apex/jni_runtime.cpp @@ -70,7 +70,6 @@ extern int register_android_graphics_fonts_Font(JNIEnv* env); extern int register_android_graphics_fonts_FontFamily(JNIEnv* env); extern int register_android_graphics_pdf_PdfDocument(JNIEnv* env); extern int register_android_graphics_pdf_PdfEditor(JNIEnv* env); -extern int register_android_graphics_pdf_PdfRenderer(JNIEnv* env); extern int register_android_graphics_text_MeasuredText(JNIEnv* env); extern int register_android_graphics_text_LineBreaker(JNIEnv *env); extern int register_android_graphics_text_TextShaper(JNIEnv *env); @@ -142,7 +141,6 @@ extern int register_android_graphics_HardwareBufferRenderer(JNIEnv* env); REG_JNI(register_android_graphics_fonts_FontFamily), REG_JNI(register_android_graphics_pdf_PdfDocument), REG_JNI(register_android_graphics_pdf_PdfEditor), - REG_JNI(register_android_graphics_pdf_PdfRenderer), REG_JNI(register_android_graphics_text_MeasuredText), REG_JNI(register_android_graphics_text_LineBreaker), REG_JNI(register_android_graphics_text_TextShaper), diff --git a/libs/hwui/jni/pdf/PdfRenderer.cpp b/libs/hwui/jni/pdf/PdfRenderer.cpp deleted file mode 100644 index cc1f96197c74..000000000000 --- a/libs/hwui/jni/pdf/PdfRenderer.cpp +++ /dev/null @@ -1,134 +0,0 @@ -/* - * Copyright (C) 2014 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "PdfUtils.h" - -#include "GraphicsJNI.h" -#include "SkBitmap.h" -#include "SkMatrix.h" -#include "fpdfview.h" - -#include <vector> -#include <utils/Log.h> -#include <unistd.h> -#include <sys/types.h> -#include <unistd.h> - -namespace android { - -static const int RENDER_MODE_FOR_DISPLAY = 1; -static const int RENDER_MODE_FOR_PRINT = 2; - -static struct { - jfieldID x; - jfieldID y; -} gPointClassInfo; - -static jlong nativeOpenPageAndGetSize(JNIEnv* env, jclass thiz, jlong documentPtr, - jint pageIndex, jobject outSize) { - FPDF_DOCUMENT document = reinterpret_cast<FPDF_DOCUMENT>(documentPtr); - - FPDF_PAGE page = FPDF_LoadPage(document, pageIndex); - if (!page) { - jniThrowException(env, "java/lang/IllegalStateException", - "cannot load page"); - return -1; - } - - double width = 0; - double height = 0; - - int result = FPDF_GetPageSizeByIndex(document, pageIndex, &width, &height); - if (!result) { - jniThrowException(env, "java/lang/IllegalStateException", - "cannot get page size"); - return -1; - } - - env->SetIntField(outSize, gPointClassInfo.x, width); - env->SetIntField(outSize, gPointClassInfo.y, height); - - return reinterpret_cast<jlong>(page); -} - -static void nativeClosePage(JNIEnv* env, jclass thiz, jlong pagePtr) { - FPDF_PAGE page = reinterpret_cast<FPDF_PAGE>(pagePtr); - FPDF_ClosePage(page); -} - -static void nativeRenderPage(JNIEnv* env, jclass thiz, jlong documentPtr, jlong pagePtr, - jlong bitmapPtr, jint clipLeft, jint clipTop, jint clipRight, jint clipBottom, - jlong transformPtr, jint renderMode) { - FPDF_PAGE page = reinterpret_cast<FPDF_PAGE>(pagePtr); - - SkBitmap skBitmap; - bitmap::toBitmap(bitmapPtr).getSkBitmap(&skBitmap); - - const int stride = skBitmap.width() * 4; - - FPDF_BITMAP bitmap = FPDFBitmap_CreateEx(skBitmap.width(), skBitmap.height(), - FPDFBitmap_BGRA, skBitmap.getPixels(), stride); - - 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; - } - - SkMatrix matrix = *reinterpret_cast<SkMatrix*>(transformPtr); - SkScalar transformValues[6]; - if (!matrix.asAffine(transformValues)) { - jniThrowException(env, "java/lang/IllegalArgumentException", - "transform matrix has perspective. Only affine matrices are allowed."); - return; - } - - 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); - - skBitmap.notifyPixelsChanged(); -} - -static const JNINativeMethod gPdfRenderer_Methods[] = { - {"nativeCreate", "(IJ)J", (void*) nativeOpen}, - {"nativeClose", "(J)V", (void*) nativeClose}, - {"nativeGetPageCount", "(J)I", (void*) nativeGetPageCount}, - {"nativeScaleForPrinting", "(J)Z", (void*) nativeScaleForPrinting}, - {"nativeRenderPage", "(JJJIIIIJI)V", (void*) nativeRenderPage}, - {"nativeOpenPageAndGetSize", "(JILandroid/graphics/Point;)J", (void*) nativeOpenPageAndGetSize}, - {"nativeClosePage", "(J)V", (void*) nativeClosePage} -}; - -int register_android_graphics_pdf_PdfRenderer(JNIEnv* env) { - int result = RegisterMethodsOrDie( - env, "android/graphics/pdf/PdfRenderer", gPdfRenderer_Methods, - NELEM(gPdfRenderer_Methods)); - - jclass clazz = FindClassOrDie(env, "android/graphics/Point"); - gPointClassInfo.x = GetFieldIDOrDie(env, clazz, "x", "I"); - gPointClassInfo.y = GetFieldIDOrDie(env, clazz, "y", "I"); - - return result; -}; - -}; |