12961769ea94f69c191a2dd785b2504666c7292d0Svetoslav/* 22961769ea94f69c191a2dd785b2504666c7292d0Svetoslav * Copyright (C) 2014 The Android Open Source Project 32961769ea94f69c191a2dd785b2504666c7292d0Svetoslav * 42961769ea94f69c191a2dd785b2504666c7292d0Svetoslav * Licensed under the Apache License, Version 2.0 (the "License"); 52961769ea94f69c191a2dd785b2504666c7292d0Svetoslav * you may not use this file except in compliance with the License. 62961769ea94f69c191a2dd785b2504666c7292d0Svetoslav * You may obtain a copy of the License at 72961769ea94f69c191a2dd785b2504666c7292d0Svetoslav * 82961769ea94f69c191a2dd785b2504666c7292d0Svetoslav * http://www.apache.org/licenses/LICENSE-2.0 92961769ea94f69c191a2dd785b2504666c7292d0Svetoslav * 102961769ea94f69c191a2dd785b2504666c7292d0Svetoslav * Unless required by applicable law or agreed to in writing, software 112961769ea94f69c191a2dd785b2504666c7292d0Svetoslav * distributed under the License is distributed on an "AS IS" BASIS, 122961769ea94f69c191a2dd785b2504666c7292d0Svetoslav * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 132961769ea94f69c191a2dd785b2504666c7292d0Svetoslav * See the License for the specific language governing permissions and 142961769ea94f69c191a2dd785b2504666c7292d0Svetoslav * limitations under the License. 152961769ea94f69c191a2dd785b2504666c7292d0Svetoslav */ 162961769ea94f69c191a2dd785b2504666c7292d0Svetoslav 172961769ea94f69c191a2dd785b2504666c7292d0Svetoslavpackage android.graphics.pdf; 182961769ea94f69c191a2dd785b2504666c7292d0Svetoslav 192961769ea94f69c191a2dd785b2504666c7292d0Svetoslavimport android.annotation.IntDef; 202961769ea94f69c191a2dd785b2504666c7292d0Svetoslavimport android.annotation.NonNull; 212961769ea94f69c191a2dd785b2504666c7292d0Svetoslavimport android.annotation.Nullable; 222961769ea94f69c191a2dd785b2504666c7292d0Svetoslavimport android.graphics.Bitmap; 232961769ea94f69c191a2dd785b2504666c7292d0Svetoslavimport android.graphics.Bitmap.Config; 242961769ea94f69c191a2dd785b2504666c7292d0Svetoslavimport android.graphics.Matrix; 252961769ea94f69c191a2dd785b2504666c7292d0Svetoslavimport android.graphics.Point; 262961769ea94f69c191a2dd785b2504666c7292d0Svetoslavimport android.graphics.Rect; 272961769ea94f69c191a2dd785b2504666c7292d0Svetoslavimport android.os.ParcelFileDescriptor; 282961769ea94f69c191a2dd785b2504666c7292d0Svetoslavimport android.system.ErrnoException; 292961769ea94f69c191a2dd785b2504666c7292d0Svetoslavimport android.system.OsConstants; 30f126e21f433b36aa4c71f1a621d06b56206df440Philip P. Moltmannimport com.android.internal.util.Preconditions; 312961769ea94f69c191a2dd785b2504666c7292d0Svetoslavimport dalvik.system.CloseGuard; 322961769ea94f69c191a2dd785b2504666c7292d0Svetoslavimport libcore.io.Libcore; 332961769ea94f69c191a2dd785b2504666c7292d0Svetoslav 342961769ea94f69c191a2dd785b2504666c7292d0Svetoslavimport java.io.IOException; 352961769ea94f69c191a2dd785b2504666c7292d0Svetoslavimport java.lang.annotation.Retention; 362961769ea94f69c191a2dd785b2504666c7292d0Svetoslavimport java.lang.annotation.RetentionPolicy; 372961769ea94f69c191a2dd785b2504666c7292d0Svetoslav 382961769ea94f69c191a2dd785b2504666c7292d0Svetoslav/** 392961769ea94f69c191a2dd785b2504666c7292d0Svetoslav * <p> 402961769ea94f69c191a2dd785b2504666c7292d0Svetoslav * This class enables rendering a PDF document. This class is not thread safe. 412961769ea94f69c191a2dd785b2504666c7292d0Svetoslav * </p> 422961769ea94f69c191a2dd785b2504666c7292d0Svetoslav * <p> 432961769ea94f69c191a2dd785b2504666c7292d0Svetoslav * If you want to render a PDF, you create a renderer and for every page you want 442961769ea94f69c191a2dd785b2504666c7292d0Svetoslav * to render, you open the page, render it, and close the page. After you are done 452961769ea94f69c191a2dd785b2504666c7292d0Svetoslav * with rendering, you close the renderer. After the renderer is closed it should not 462961769ea94f69c191a2dd785b2504666c7292d0Svetoslav * be used anymore. Note that the pages are rendered one by one, i.e. you can have 472961769ea94f69c191a2dd785b2504666c7292d0Svetoslav * only a single page opened at any given time. 482961769ea94f69c191a2dd785b2504666c7292d0Svetoslav * </p> 492961769ea94f69c191a2dd785b2504666c7292d0Svetoslav * <p> 502961769ea94f69c191a2dd785b2504666c7292d0Svetoslav * A typical use of the APIs to render a PDF looks like this: 512961769ea94f69c191a2dd785b2504666c7292d0Svetoslav * </p> 522961769ea94f69c191a2dd785b2504666c7292d0Svetoslav * <pre> 532961769ea94f69c191a2dd785b2504666c7292d0Svetoslav * // create a new renderer 542961769ea94f69c191a2dd785b2504666c7292d0Svetoslav * PdfRenderer renderer = new PdfRenderer(getSeekableFileDescriptor()); 552961769ea94f69c191a2dd785b2504666c7292d0Svetoslav * 562961769ea94f69c191a2dd785b2504666c7292d0Svetoslav * // let us just render all pages 572961769ea94f69c191a2dd785b2504666c7292d0Svetoslav * final int pageCount = renderer.getPageCount(); 582961769ea94f69c191a2dd785b2504666c7292d0Svetoslav * for (int i = 0; i < pageCount; i++) { 592961769ea94f69c191a2dd785b2504666c7292d0Svetoslav * Page page = renderer.openPage(i); 602961769ea94f69c191a2dd785b2504666c7292d0Svetoslav * 612961769ea94f69c191a2dd785b2504666c7292d0Svetoslav * // say we render for showing on the screen 6295b6fd8b7af276069cbc415da3499d5ab4873c32Svetoslav * page.render(mBitmap, null, null, Page.RENDER_MODE_FOR_DISPLAY); 632961769ea94f69c191a2dd785b2504666c7292d0Svetoslav * 642961769ea94f69c191a2dd785b2504666c7292d0Svetoslav * // do stuff with the bitmap 652961769ea94f69c191a2dd785b2504666c7292d0Svetoslav * 6695b6fd8b7af276069cbc415da3499d5ab4873c32Svetoslav * // close the page 6795b6fd8b7af276069cbc415da3499d5ab4873c32Svetoslav * page.close(); 682961769ea94f69c191a2dd785b2504666c7292d0Svetoslav * } 692961769ea94f69c191a2dd785b2504666c7292d0Svetoslav * 702961769ea94f69c191a2dd785b2504666c7292d0Svetoslav * // close the renderer 712961769ea94f69c191a2dd785b2504666c7292d0Svetoslav * renderer.close(); 722961769ea94f69c191a2dd785b2504666c7292d0Svetoslav * </pre> 732961769ea94f69c191a2dd785b2504666c7292d0Svetoslav * 74525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov * <h3>Print preview and print output</h3> 75525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov * <p> 76525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov * If you are using this class to rasterize a PDF for printing or show a print 77525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov * preview, it is recommended that you respect the following contract in order 78525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov * to provide a consistent user experience when seeing a preview and printing, 79525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov * i.e. the user sees a preview that is the same as the printout. 80525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov * </p> 81525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov * <ul> 82525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov * <li> 83525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov * Respect the property whether the document would like to be scaled for printing 84525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov * as per {@link #shouldScaleForPrinting()}. 85525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov * </li> 86525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov * <li> 87525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov * When scaling a document for printing the aspect ratio should be preserved. 88525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov * </li> 89525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov * <li> 90525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov * Do not inset the content with any margins from the {@link android.print.PrintAttributes} 91525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov * as the application is responsible to render it such that the margins are respected. 92525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov * </li> 93525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov * <li> 94525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov * If document page size is greater than the printed media size the content should 95525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov * be anchored to the upper left corner of the page for left-to-right locales and 96525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov * top right corner for right-to-left locales. 97525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov * </li> 98525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov * </ul> 99525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov * 1002961769ea94f69c191a2dd785b2504666c7292d0Svetoslav * @see #close() 1012961769ea94f69c191a2dd785b2504666c7292d0Svetoslav */ 1022961769ea94f69c191a2dd785b2504666c7292d0Svetoslavpublic final class PdfRenderer implements AutoCloseable { 1030768a7dc450caf4c873c5b0883a75135536e1546Philip P. Moltmann /** 1040768a7dc450caf4c873c5b0883a75135536e1546Philip P. Moltmann * Any call the native pdfium code has to be single threaded as the library does not support 1050768a7dc450caf4c873c5b0883a75135536e1546Philip P. Moltmann * parallel use. 1060768a7dc450caf4c873c5b0883a75135536e1546Philip P. Moltmann */ 1070768a7dc450caf4c873c5b0883a75135536e1546Philip P. Moltmann final static Object sPdfiumLock = new Object(); 1080768a7dc450caf4c873c5b0883a75135536e1546Philip P. Moltmann 1092961769ea94f69c191a2dd785b2504666c7292d0Svetoslav private final CloseGuard mCloseGuard = CloseGuard.get(); 1102961769ea94f69c191a2dd785b2504666c7292d0Svetoslav 1112961769ea94f69c191a2dd785b2504666c7292d0Svetoslav private final Point mTempPoint = new Point(); 1122961769ea94f69c191a2dd785b2504666c7292d0Svetoslav 1132961769ea94f69c191a2dd785b2504666c7292d0Svetoslav private final long mNativeDocument; 1142961769ea94f69c191a2dd785b2504666c7292d0Svetoslav 1152961769ea94f69c191a2dd785b2504666c7292d0Svetoslav private final int mPageCount; 1162961769ea94f69c191a2dd785b2504666c7292d0Svetoslav 1172961769ea94f69c191a2dd785b2504666c7292d0Svetoslav private ParcelFileDescriptor mInput; 1182961769ea94f69c191a2dd785b2504666c7292d0Svetoslav 1192961769ea94f69c191a2dd785b2504666c7292d0Svetoslav private Page mCurrentPage; 1202961769ea94f69c191a2dd785b2504666c7292d0Svetoslav 1212961769ea94f69c191a2dd785b2504666c7292d0Svetoslav /** @hide */ 1222961769ea94f69c191a2dd785b2504666c7292d0Svetoslav @IntDef({ 1232961769ea94f69c191a2dd785b2504666c7292d0Svetoslav Page.RENDER_MODE_FOR_DISPLAY, 1242961769ea94f69c191a2dd785b2504666c7292d0Svetoslav Page.RENDER_MODE_FOR_PRINT 1252961769ea94f69c191a2dd785b2504666c7292d0Svetoslav }) 1262961769ea94f69c191a2dd785b2504666c7292d0Svetoslav @Retention(RetentionPolicy.SOURCE) 1272961769ea94f69c191a2dd785b2504666c7292d0Svetoslav public @interface RenderMode {} 1282961769ea94f69c191a2dd785b2504666c7292d0Svetoslav 1292961769ea94f69c191a2dd785b2504666c7292d0Svetoslav /** 1302961769ea94f69c191a2dd785b2504666c7292d0Svetoslav * Creates a new instance. 1312961769ea94f69c191a2dd785b2504666c7292d0Svetoslav * <p> 1322961769ea94f69c191a2dd785b2504666c7292d0Svetoslav * <strong>Note:</strong> The provided file descriptor must be <strong>seekable</strong>, 1332961769ea94f69c191a2dd785b2504666c7292d0Svetoslav * i.e. its data being randomly accessed, e.g. pointing to a file. 1342961769ea94f69c191a2dd785b2504666c7292d0Svetoslav * </p> 1352961769ea94f69c191a2dd785b2504666c7292d0Svetoslav * <p> 1362961769ea94f69c191a2dd785b2504666c7292d0Svetoslav * <strong>Note:</strong> This class takes ownership of the passed in file descriptor 1372961769ea94f69c191a2dd785b2504666c7292d0Svetoslav * and is responsible for closing it when the renderer is closed. 1382961769ea94f69c191a2dd785b2504666c7292d0Svetoslav * </p> 1393d0d141710d23b0f08c865100b4d55b4c2976486Philip P. Moltmann * <p> 1403d0d141710d23b0f08c865100b4d55b4c2976486Philip P. Moltmann * If the file is from an untrusted source it is recommended to run the renderer in a separate, 1413d0d141710d23b0f08c865100b4d55b4c2976486Philip P. Moltmann * isolated process with minimal permissions to limit the impact of security exploits. 1423d0d141710d23b0f08c865100b4d55b4c2976486Philip P. Moltmann * </p> 1432961769ea94f69c191a2dd785b2504666c7292d0Svetoslav * 1442961769ea94f69c191a2dd785b2504666c7292d0Svetoslav * @param input Seekable file descriptor to read from. 145fce84f035c35606c5707e735f503f7bdcfd5b2a1Svet Ganov * 146fce84f035c35606c5707e735f503f7bdcfd5b2a1Svet Ganov * @throws java.io.IOException If an error occurs while reading the file. 147fce84f035c35606c5707e735f503f7bdcfd5b2a1Svet Ganov * @throws java.lang.SecurityException If the file requires a password or 148fce84f035c35606c5707e735f503f7bdcfd5b2a1Svet Ganov * the security scheme is not supported. 1492961769ea94f69c191a2dd785b2504666c7292d0Svetoslav */ 1502961769ea94f69c191a2dd785b2504666c7292d0Svetoslav public PdfRenderer(@NonNull ParcelFileDescriptor input) throws IOException { 1512961769ea94f69c191a2dd785b2504666c7292d0Svetoslav if (input == null) { 1522961769ea94f69c191a2dd785b2504666c7292d0Svetoslav throw new NullPointerException("input cannot be null"); 1532961769ea94f69c191a2dd785b2504666c7292d0Svetoslav } 1542961769ea94f69c191a2dd785b2504666c7292d0Svetoslav 1552961769ea94f69c191a2dd785b2504666c7292d0Svetoslav final long size; 1562961769ea94f69c191a2dd785b2504666c7292d0Svetoslav try { 1572961769ea94f69c191a2dd785b2504666c7292d0Svetoslav Libcore.os.lseek(input.getFileDescriptor(), 0, OsConstants.SEEK_SET); 1582961769ea94f69c191a2dd785b2504666c7292d0Svetoslav size = Libcore.os.fstat(input.getFileDescriptor()).st_size; 1592961769ea94f69c191a2dd785b2504666c7292d0Svetoslav } catch (ErrnoException ee) { 1602961769ea94f69c191a2dd785b2504666c7292d0Svetoslav throw new IllegalArgumentException("file descriptor not seekable"); 1612961769ea94f69c191a2dd785b2504666c7292d0Svetoslav } 1622961769ea94f69c191a2dd785b2504666c7292d0Svetoslav 1632961769ea94f69c191a2dd785b2504666c7292d0Svetoslav mInput = input; 1640768a7dc450caf4c873c5b0883a75135536e1546Philip P. Moltmann 1650768a7dc450caf4c873c5b0883a75135536e1546Philip P. Moltmann synchronized (sPdfiumLock) { 1660768a7dc450caf4c873c5b0883a75135536e1546Philip P. Moltmann mNativeDocument = nativeCreate(mInput.getFd(), size); 167c859cd068b3a63be962a201db46f487d13be56daPhilip P. Moltmann try { 168c859cd068b3a63be962a201db46f487d13be56daPhilip P. Moltmann mPageCount = nativeGetPageCount(mNativeDocument); 169c859cd068b3a63be962a201db46f487d13be56daPhilip P. Moltmann } catch (Throwable t) { 170c859cd068b3a63be962a201db46f487d13be56daPhilip P. Moltmann nativeClose(mNativeDocument); 171c859cd068b3a63be962a201db46f487d13be56daPhilip P. Moltmann throw t; 172c859cd068b3a63be962a201db46f487d13be56daPhilip P. Moltmann } 1730768a7dc450caf4c873c5b0883a75135536e1546Philip P. Moltmann } 1740768a7dc450caf4c873c5b0883a75135536e1546Philip P. Moltmann 1752961769ea94f69c191a2dd785b2504666c7292d0Svetoslav mCloseGuard.open("close"); 1762961769ea94f69c191a2dd785b2504666c7292d0Svetoslav } 1772961769ea94f69c191a2dd785b2504666c7292d0Svetoslav 1782961769ea94f69c191a2dd785b2504666c7292d0Svetoslav /** 1792961769ea94f69c191a2dd785b2504666c7292d0Svetoslav * Closes this renderer. You should not use this instance 1802961769ea94f69c191a2dd785b2504666c7292d0Svetoslav * after this method is called. 1812961769ea94f69c191a2dd785b2504666c7292d0Svetoslav */ 1822961769ea94f69c191a2dd785b2504666c7292d0Svetoslav public void close() { 1832961769ea94f69c191a2dd785b2504666c7292d0Svetoslav throwIfClosed(); 1842961769ea94f69c191a2dd785b2504666c7292d0Svetoslav throwIfPageOpened(); 1852961769ea94f69c191a2dd785b2504666c7292d0Svetoslav doClose(); 1862961769ea94f69c191a2dd785b2504666c7292d0Svetoslav } 1872961769ea94f69c191a2dd785b2504666c7292d0Svetoslav 1882961769ea94f69c191a2dd785b2504666c7292d0Svetoslav /** 1892961769ea94f69c191a2dd785b2504666c7292d0Svetoslav * Gets the number of pages in the document. 1902961769ea94f69c191a2dd785b2504666c7292d0Svetoslav * 1912961769ea94f69c191a2dd785b2504666c7292d0Svetoslav * @return The page count. 1922961769ea94f69c191a2dd785b2504666c7292d0Svetoslav */ 1932961769ea94f69c191a2dd785b2504666c7292d0Svetoslav public int getPageCount() { 1942961769ea94f69c191a2dd785b2504666c7292d0Svetoslav throwIfClosed(); 1952961769ea94f69c191a2dd785b2504666c7292d0Svetoslav return mPageCount; 1962961769ea94f69c191a2dd785b2504666c7292d0Svetoslav } 1972961769ea94f69c191a2dd785b2504666c7292d0Svetoslav 1982961769ea94f69c191a2dd785b2504666c7292d0Svetoslav /** 1992961769ea94f69c191a2dd785b2504666c7292d0Svetoslav * Gets whether the document prefers to be scaled for printing. 2002961769ea94f69c191a2dd785b2504666c7292d0Svetoslav * You should take this info account if the document is rendered 2012961769ea94f69c191a2dd785b2504666c7292d0Svetoslav * for printing and the target media size differs from the page 2022961769ea94f69c191a2dd785b2504666c7292d0Svetoslav * size. 2032961769ea94f69c191a2dd785b2504666c7292d0Svetoslav * 2042961769ea94f69c191a2dd785b2504666c7292d0Svetoslav * @return If to scale the document. 2052961769ea94f69c191a2dd785b2504666c7292d0Svetoslav */ 2062961769ea94f69c191a2dd785b2504666c7292d0Svetoslav public boolean shouldScaleForPrinting() { 2072961769ea94f69c191a2dd785b2504666c7292d0Svetoslav throwIfClosed(); 2080768a7dc450caf4c873c5b0883a75135536e1546Philip P. Moltmann 2090768a7dc450caf4c873c5b0883a75135536e1546Philip P. Moltmann synchronized (sPdfiumLock) { 2100768a7dc450caf4c873c5b0883a75135536e1546Philip P. Moltmann return nativeScaleForPrinting(mNativeDocument); 2110768a7dc450caf4c873c5b0883a75135536e1546Philip P. Moltmann } 2122961769ea94f69c191a2dd785b2504666c7292d0Svetoslav } 2132961769ea94f69c191a2dd785b2504666c7292d0Svetoslav 2142961769ea94f69c191a2dd785b2504666c7292d0Svetoslav /** 2152961769ea94f69c191a2dd785b2504666c7292d0Svetoslav * Opens a page for rendering. 2162961769ea94f69c191a2dd785b2504666c7292d0Svetoslav * 2172961769ea94f69c191a2dd785b2504666c7292d0Svetoslav * @param index The page index. 2182961769ea94f69c191a2dd785b2504666c7292d0Svetoslav * @return A page that can be rendered. 2192961769ea94f69c191a2dd785b2504666c7292d0Svetoslav * 22095b6fd8b7af276069cbc415da3499d5ab4873c32Svetoslav * @see android.graphics.pdf.PdfRenderer.Page#close() PdfRenderer.Page.close() 2212961769ea94f69c191a2dd785b2504666c7292d0Svetoslav */ 2222961769ea94f69c191a2dd785b2504666c7292d0Svetoslav public Page openPage(int index) { 2232961769ea94f69c191a2dd785b2504666c7292d0Svetoslav throwIfClosed(); 2242961769ea94f69c191a2dd785b2504666c7292d0Svetoslav throwIfPageOpened(); 22513f542cabd635c55ade5442764cc4a3d2f7880eaSvet Ganov throwIfPageNotInDocument(index); 2262961769ea94f69c191a2dd785b2504666c7292d0Svetoslav mCurrentPage = new Page(index); 2272961769ea94f69c191a2dd785b2504666c7292d0Svetoslav return mCurrentPage; 2282961769ea94f69c191a2dd785b2504666c7292d0Svetoslav } 2292961769ea94f69c191a2dd785b2504666c7292d0Svetoslav 2302961769ea94f69c191a2dd785b2504666c7292d0Svetoslav @Override 2312961769ea94f69c191a2dd785b2504666c7292d0Svetoslav protected void finalize() throws Throwable { 2322961769ea94f69c191a2dd785b2504666c7292d0Svetoslav try { 233492e9e851cadca62df84eaff1a3c1ba788492fbaNarayan Kamath if (mCloseGuard != null) { 234492e9e851cadca62df84eaff1a3c1ba788492fbaNarayan Kamath mCloseGuard.warnIfOpen(); 235492e9e851cadca62df84eaff1a3c1ba788492fbaNarayan Kamath } 236492e9e851cadca62df84eaff1a3c1ba788492fbaNarayan Kamath 2372961769ea94f69c191a2dd785b2504666c7292d0Svetoslav if (mInput != null) { 2382961769ea94f69c191a2dd785b2504666c7292d0Svetoslav doClose(); 2392961769ea94f69c191a2dd785b2504666c7292d0Svetoslav } 2402961769ea94f69c191a2dd785b2504666c7292d0Svetoslav } finally { 2412961769ea94f69c191a2dd785b2504666c7292d0Svetoslav super.finalize(); 2422961769ea94f69c191a2dd785b2504666c7292d0Svetoslav } 2432961769ea94f69c191a2dd785b2504666c7292d0Svetoslav } 2442961769ea94f69c191a2dd785b2504666c7292d0Svetoslav 2452961769ea94f69c191a2dd785b2504666c7292d0Svetoslav private void doClose() { 2462961769ea94f69c191a2dd785b2504666c7292d0Svetoslav if (mCurrentPage != null) { 2472961769ea94f69c191a2dd785b2504666c7292d0Svetoslav mCurrentPage.close(); 2482961769ea94f69c191a2dd785b2504666c7292d0Svetoslav } 2490768a7dc450caf4c873c5b0883a75135536e1546Philip P. Moltmann synchronized (sPdfiumLock) { 2500768a7dc450caf4c873c5b0883a75135536e1546Philip P. Moltmann nativeClose(mNativeDocument); 2510768a7dc450caf4c873c5b0883a75135536e1546Philip P. Moltmann } 2522961769ea94f69c191a2dd785b2504666c7292d0Svetoslav try { 2532961769ea94f69c191a2dd785b2504666c7292d0Svetoslav mInput.close(); 2542961769ea94f69c191a2dd785b2504666c7292d0Svetoslav } catch (IOException ioe) { 2552961769ea94f69c191a2dd785b2504666c7292d0Svetoslav /* ignore - best effort */ 2562961769ea94f69c191a2dd785b2504666c7292d0Svetoslav } 2572961769ea94f69c191a2dd785b2504666c7292d0Svetoslav mInput = null; 2582961769ea94f69c191a2dd785b2504666c7292d0Svetoslav mCloseGuard.close(); 2592961769ea94f69c191a2dd785b2504666c7292d0Svetoslav } 2602961769ea94f69c191a2dd785b2504666c7292d0Svetoslav 2612961769ea94f69c191a2dd785b2504666c7292d0Svetoslav private void throwIfClosed() { 2622961769ea94f69c191a2dd785b2504666c7292d0Svetoslav if (mInput == null) { 2632961769ea94f69c191a2dd785b2504666c7292d0Svetoslav throw new IllegalStateException("Already closed"); 2642961769ea94f69c191a2dd785b2504666c7292d0Svetoslav } 2652961769ea94f69c191a2dd785b2504666c7292d0Svetoslav } 2662961769ea94f69c191a2dd785b2504666c7292d0Svetoslav 2672961769ea94f69c191a2dd785b2504666c7292d0Svetoslav private void throwIfPageOpened() { 2682961769ea94f69c191a2dd785b2504666c7292d0Svetoslav if (mCurrentPage != null) { 2692961769ea94f69c191a2dd785b2504666c7292d0Svetoslav throw new IllegalStateException("Current page not closed"); 2702961769ea94f69c191a2dd785b2504666c7292d0Svetoslav } 2712961769ea94f69c191a2dd785b2504666c7292d0Svetoslav } 2722961769ea94f69c191a2dd785b2504666c7292d0Svetoslav 27313f542cabd635c55ade5442764cc4a3d2f7880eaSvet Ganov private void throwIfPageNotInDocument(int pageIndex) { 27462ce332c141cf7bc7200c4c87d63e395874fc3ecSvetoslav if (pageIndex < 0 || pageIndex >= mPageCount) { 27513f542cabd635c55ade5442764cc4a3d2f7880eaSvet Ganov throw new IllegalArgumentException("Invalid page index"); 27613f542cabd635c55ade5442764cc4a3d2f7880eaSvet Ganov } 27713f542cabd635c55ade5442764cc4a3d2f7880eaSvet Ganov } 27813f542cabd635c55ade5442764cc4a3d2f7880eaSvet Ganov 2792961769ea94f69c191a2dd785b2504666c7292d0Svetoslav /** 2802961769ea94f69c191a2dd785b2504666c7292d0Svetoslav * This class represents a PDF document page for rendering. 2812961769ea94f69c191a2dd785b2504666c7292d0Svetoslav */ 28295b6fd8b7af276069cbc415da3499d5ab4873c32Svetoslav public final class Page implements AutoCloseable { 28395b6fd8b7af276069cbc415da3499d5ab4873c32Svetoslav 28495b6fd8b7af276069cbc415da3499d5ab4873c32Svetoslav private final CloseGuard mCloseGuard = CloseGuard.get(); 2852961769ea94f69c191a2dd785b2504666c7292d0Svetoslav 2862961769ea94f69c191a2dd785b2504666c7292d0Svetoslav /** 2872961769ea94f69c191a2dd785b2504666c7292d0Svetoslav * Mode to render the content for display on a screen. 2882961769ea94f69c191a2dd785b2504666c7292d0Svetoslav */ 2892961769ea94f69c191a2dd785b2504666c7292d0Svetoslav public static final int RENDER_MODE_FOR_DISPLAY = 1; 2902961769ea94f69c191a2dd785b2504666c7292d0Svetoslav 2912961769ea94f69c191a2dd785b2504666c7292d0Svetoslav /** 2922961769ea94f69c191a2dd785b2504666c7292d0Svetoslav * Mode to render the content for printing. 2932961769ea94f69c191a2dd785b2504666c7292d0Svetoslav */ 2942961769ea94f69c191a2dd785b2504666c7292d0Svetoslav public static final int RENDER_MODE_FOR_PRINT = 2; 2952961769ea94f69c191a2dd785b2504666c7292d0Svetoslav 2962961769ea94f69c191a2dd785b2504666c7292d0Svetoslav private final int mIndex; 2972961769ea94f69c191a2dd785b2504666c7292d0Svetoslav private final int mWidth; 2982961769ea94f69c191a2dd785b2504666c7292d0Svetoslav private final int mHeight; 2992961769ea94f69c191a2dd785b2504666c7292d0Svetoslav 3002961769ea94f69c191a2dd785b2504666c7292d0Svetoslav private long mNativePage; 3012961769ea94f69c191a2dd785b2504666c7292d0Svetoslav 3022961769ea94f69c191a2dd785b2504666c7292d0Svetoslav private Page(int index) { 3032961769ea94f69c191a2dd785b2504666c7292d0Svetoslav Point size = mTempPoint; 3040768a7dc450caf4c873c5b0883a75135536e1546Philip P. Moltmann synchronized (sPdfiumLock) { 3050768a7dc450caf4c873c5b0883a75135536e1546Philip P. Moltmann mNativePage = nativeOpenPageAndGetSize(mNativeDocument, index, size); 3060768a7dc450caf4c873c5b0883a75135536e1546Philip P. Moltmann } 3072961769ea94f69c191a2dd785b2504666c7292d0Svetoslav mIndex = index; 3082961769ea94f69c191a2dd785b2504666c7292d0Svetoslav mWidth = size.x; 3092961769ea94f69c191a2dd785b2504666c7292d0Svetoslav mHeight = size.y; 31095b6fd8b7af276069cbc415da3499d5ab4873c32Svetoslav mCloseGuard.open("close"); 3112961769ea94f69c191a2dd785b2504666c7292d0Svetoslav } 3122961769ea94f69c191a2dd785b2504666c7292d0Svetoslav 3132961769ea94f69c191a2dd785b2504666c7292d0Svetoslav /** 3142961769ea94f69c191a2dd785b2504666c7292d0Svetoslav * Gets the page index. 3152961769ea94f69c191a2dd785b2504666c7292d0Svetoslav * 3162961769ea94f69c191a2dd785b2504666c7292d0Svetoslav * @return The index. 3172961769ea94f69c191a2dd785b2504666c7292d0Svetoslav */ 3182961769ea94f69c191a2dd785b2504666c7292d0Svetoslav public int getIndex() { 3192961769ea94f69c191a2dd785b2504666c7292d0Svetoslav return mIndex; 3202961769ea94f69c191a2dd785b2504666c7292d0Svetoslav } 3212961769ea94f69c191a2dd785b2504666c7292d0Svetoslav 3222961769ea94f69c191a2dd785b2504666c7292d0Svetoslav /** 3232961769ea94f69c191a2dd785b2504666c7292d0Svetoslav * Gets the page width in points (1/72"). 3242961769ea94f69c191a2dd785b2504666c7292d0Svetoslav * 3252961769ea94f69c191a2dd785b2504666c7292d0Svetoslav * @return The width in points. 3262961769ea94f69c191a2dd785b2504666c7292d0Svetoslav */ 3272961769ea94f69c191a2dd785b2504666c7292d0Svetoslav public int getWidth() { 3282961769ea94f69c191a2dd785b2504666c7292d0Svetoslav return mWidth; 3292961769ea94f69c191a2dd785b2504666c7292d0Svetoslav } 3302961769ea94f69c191a2dd785b2504666c7292d0Svetoslav 3312961769ea94f69c191a2dd785b2504666c7292d0Svetoslav /** 3322961769ea94f69c191a2dd785b2504666c7292d0Svetoslav * Gets the page height in points (1/72"). 3332961769ea94f69c191a2dd785b2504666c7292d0Svetoslav * 3342961769ea94f69c191a2dd785b2504666c7292d0Svetoslav * @return The height in points. 3352961769ea94f69c191a2dd785b2504666c7292d0Svetoslav */ 3362961769ea94f69c191a2dd785b2504666c7292d0Svetoslav public int getHeight() { 3372961769ea94f69c191a2dd785b2504666c7292d0Svetoslav return mHeight; 3382961769ea94f69c191a2dd785b2504666c7292d0Svetoslav } 3392961769ea94f69c191a2dd785b2504666c7292d0Svetoslav 3402961769ea94f69c191a2dd785b2504666c7292d0Svetoslav /** 3412961769ea94f69c191a2dd785b2504666c7292d0Svetoslav * Renders a page to a bitmap. 3422961769ea94f69c191a2dd785b2504666c7292d0Svetoslav * <p> 3432961769ea94f69c191a2dd785b2504666c7292d0Svetoslav * You may optionally specify a rectangular clip in the bitmap bounds. No rendering 3442961769ea94f69c191a2dd785b2504666c7292d0Svetoslav * outside the clip will be performed, hence it is your responsibility to initialize 3452961769ea94f69c191a2dd785b2504666c7292d0Svetoslav * the bitmap outside the clip. 3462961769ea94f69c191a2dd785b2504666c7292d0Svetoslav * </p> 3472961769ea94f69c191a2dd785b2504666c7292d0Svetoslav * <p> 3482961769ea94f69c191a2dd785b2504666c7292d0Svetoslav * You may optionally specify a matrix to transform the content from page coordinates 349525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov * which are in points (1/72") to bitmap coordinates which are in pixels. If this 3502961769ea94f69c191a2dd785b2504666c7292d0Svetoslav * matrix is not provided this method will apply a transformation that will fit the 35195b6fd8b7af276069cbc415da3499d5ab4873c32Svetoslav * whole page to the destination clip if provided or the destination bitmap if no 3522961769ea94f69c191a2dd785b2504666c7292d0Svetoslav * clip is provided. 3532961769ea94f69c191a2dd785b2504666c7292d0Svetoslav * </p> 3542961769ea94f69c191a2dd785b2504666c7292d0Svetoslav * <p> 3552961769ea94f69c191a2dd785b2504666c7292d0Svetoslav * The clip and transformation are useful for implementing tile rendering where the 3562961769ea94f69c191a2dd785b2504666c7292d0Svetoslav * destination bitmap contains a portion of the image, for example when zooming. 3572961769ea94f69c191a2dd785b2504666c7292d0Svetoslav * Another useful application is for printing where the size of the bitmap holding 3582961769ea94f69c191a2dd785b2504666c7292d0Svetoslav * the page is too large and a client can render the page in stripes. 3592961769ea94f69c191a2dd785b2504666c7292d0Svetoslav * </p> 3602961769ea94f69c191a2dd785b2504666c7292d0Svetoslav * <p> 3612961769ea94f69c191a2dd785b2504666c7292d0Svetoslav * <strong>Note: </strong> The destination bitmap format must be 3622961769ea94f69c191a2dd785b2504666c7292d0Svetoslav * {@link Config#ARGB_8888 ARGB}. 3632961769ea94f69c191a2dd785b2504666c7292d0Svetoslav * </p> 3642961769ea94f69c191a2dd785b2504666c7292d0Svetoslav * <p> 3652961769ea94f69c191a2dd785b2504666c7292d0Svetoslav * <strong>Note: </strong> The optional transformation matrix must be affine as per 36695b6fd8b7af276069cbc415da3499d5ab4873c32Svetoslav * {@link android.graphics.Matrix#isAffine() Matrix.isAffine()}. Hence, you can specify 36795b6fd8b7af276069cbc415da3499d5ab4873c32Svetoslav * rotation, scaling, translation but not a perspective transformation. 3682961769ea94f69c191a2dd785b2504666c7292d0Svetoslav * </p> 3692961769ea94f69c191a2dd785b2504666c7292d0Svetoslav * 3702961769ea94f69c191a2dd785b2504666c7292d0Svetoslav * @param destination Destination bitmap to which to render. 3712961769ea94f69c191a2dd785b2504666c7292d0Svetoslav * @param destClip Optional clip in the bitmap bounds. 3722961769ea94f69c191a2dd785b2504666c7292d0Svetoslav * @param transform Optional transformation to apply when rendering. 3732961769ea94f69c191a2dd785b2504666c7292d0Svetoslav * @param renderMode The render mode. 3742961769ea94f69c191a2dd785b2504666c7292d0Svetoslav * 3752961769ea94f69c191a2dd785b2504666c7292d0Svetoslav * @see #RENDER_MODE_FOR_DISPLAY 3762961769ea94f69c191a2dd785b2504666c7292d0Svetoslav * @see #RENDER_MODE_FOR_PRINT 3772961769ea94f69c191a2dd785b2504666c7292d0Svetoslav */ 3782961769ea94f69c191a2dd785b2504666c7292d0Svetoslav public void render(@NonNull Bitmap destination, @Nullable Rect destClip, 3792961769ea94f69c191a2dd785b2504666c7292d0Svetoslav @Nullable Matrix transform, @RenderMode int renderMode) { 380f3f7cccccf0d8bbf04e19ada76b475f98d30f19cPhilip P. Moltmann if (mNativePage == 0) { 381f3f7cccccf0d8bbf04e19ada76b475f98d30f19cPhilip P. Moltmann throw new NullPointerException(); 382f3f7cccccf0d8bbf04e19ada76b475f98d30f19cPhilip P. Moltmann } 383c859cd068b3a63be962a201db46f487d13be56daPhilip P. Moltmann 384f126e21f433b36aa4c71f1a621d06b56206df440Philip P. Moltmann destination = Preconditions.checkNotNull(destination, "bitmap null"); 385f126e21f433b36aa4c71f1a621d06b56206df440Philip P. Moltmann 3862961769ea94f69c191a2dd785b2504666c7292d0Svetoslav if (destination.getConfig() != Config.ARGB_8888) { 3872961769ea94f69c191a2dd785b2504666c7292d0Svetoslav throw new IllegalArgumentException("Unsupported pixel format"); 3882961769ea94f69c191a2dd785b2504666c7292d0Svetoslav } 3892961769ea94f69c191a2dd785b2504666c7292d0Svetoslav 3902961769ea94f69c191a2dd785b2504666c7292d0Svetoslav if (destClip != null) { 3912961769ea94f69c191a2dd785b2504666c7292d0Svetoslav if (destClip.left < 0 || destClip.top < 0 3922961769ea94f69c191a2dd785b2504666c7292d0Svetoslav || destClip.right > destination.getWidth() 3932961769ea94f69c191a2dd785b2504666c7292d0Svetoslav || destClip.bottom > destination.getHeight()) { 3942961769ea94f69c191a2dd785b2504666c7292d0Svetoslav throw new IllegalArgumentException("destBounds not in destination"); 3952961769ea94f69c191a2dd785b2504666c7292d0Svetoslav } 3962961769ea94f69c191a2dd785b2504666c7292d0Svetoslav } 3972961769ea94f69c191a2dd785b2504666c7292d0Svetoslav 3982961769ea94f69c191a2dd785b2504666c7292d0Svetoslav if (transform != null && !transform.isAffine()) { 3992961769ea94f69c191a2dd785b2504666c7292d0Svetoslav throw new IllegalArgumentException("transform not affine"); 4002961769ea94f69c191a2dd785b2504666c7292d0Svetoslav } 4012961769ea94f69c191a2dd785b2504666c7292d0Svetoslav 4022961769ea94f69c191a2dd785b2504666c7292d0Svetoslav if (renderMode != RENDER_MODE_FOR_PRINT && renderMode != RENDER_MODE_FOR_DISPLAY) { 4032961769ea94f69c191a2dd785b2504666c7292d0Svetoslav throw new IllegalArgumentException("Unsupported render mode"); 4042961769ea94f69c191a2dd785b2504666c7292d0Svetoslav } 4052961769ea94f69c191a2dd785b2504666c7292d0Svetoslav 4062961769ea94f69c191a2dd785b2504666c7292d0Svetoslav if (renderMode == RENDER_MODE_FOR_PRINT && renderMode == RENDER_MODE_FOR_DISPLAY) { 4072961769ea94f69c191a2dd785b2504666c7292d0Svetoslav throw new IllegalArgumentException("Only single render mode supported"); 4082961769ea94f69c191a2dd785b2504666c7292d0Svetoslav } 4092961769ea94f69c191a2dd785b2504666c7292d0Svetoslav 4102961769ea94f69c191a2dd785b2504666c7292d0Svetoslav final int contentLeft = (destClip != null) ? destClip.left : 0; 4112961769ea94f69c191a2dd785b2504666c7292d0Svetoslav final int contentTop = (destClip != null) ? destClip.top : 0; 4122961769ea94f69c191a2dd785b2504666c7292d0Svetoslav final int contentRight = (destClip != null) ? destClip.right 4132961769ea94f69c191a2dd785b2504666c7292d0Svetoslav : destination.getWidth(); 4142961769ea94f69c191a2dd785b2504666c7292d0Svetoslav final int contentBottom = (destClip != null) ? destClip.bottom 4152961769ea94f69c191a2dd785b2504666c7292d0Svetoslav : destination.getHeight(); 4162961769ea94f69c191a2dd785b2504666c7292d0Svetoslav 417d55f20d3018d3328d9e26c971b814dfcb61aa7b2Philip P. Moltmann // If transform is not set, stretch page to whole clipped area 418d55f20d3018d3328d9e26c971b814dfcb61aa7b2Philip P. Moltmann if (transform == null) { 419d55f20d3018d3328d9e26c971b814dfcb61aa7b2Philip P. Moltmann int clipWidth = contentRight - contentLeft; 420d55f20d3018d3328d9e26c971b814dfcb61aa7b2Philip P. Moltmann int clipHeight = contentBottom - contentTop; 421d55f20d3018d3328d9e26c971b814dfcb61aa7b2Philip P. Moltmann 422d55f20d3018d3328d9e26c971b814dfcb61aa7b2Philip P. Moltmann transform = new Matrix(); 423d55f20d3018d3328d9e26c971b814dfcb61aa7b2Philip P. Moltmann transform.postScale((float)clipWidth / getWidth(), 424d55f20d3018d3328d9e26c971b814dfcb61aa7b2Philip P. Moltmann (float)clipHeight / getHeight()); 425d55f20d3018d3328d9e26c971b814dfcb61aa7b2Philip P. Moltmann transform.postTranslate(contentLeft, contentTop); 426d55f20d3018d3328d9e26c971b814dfcb61aa7b2Philip P. Moltmann } 427d55f20d3018d3328d9e26c971b814dfcb61aa7b2Philip P. Moltmann 428d55f20d3018d3328d9e26c971b814dfcb61aa7b2Philip P. Moltmann final long transformPtr = transform.native_instance; 4292961769ea94f69c191a2dd785b2504666c7292d0Svetoslav 4300768a7dc450caf4c873c5b0883a75135536e1546Philip P. Moltmann synchronized (sPdfiumLock) { 4310768a7dc450caf4c873c5b0883a75135536e1546Philip P. Moltmann nativeRenderPage(mNativeDocument, mNativePage, destination, contentLeft, 4320768a7dc450caf4c873c5b0883a75135536e1546Philip P. Moltmann contentTop, contentRight, contentBottom, transformPtr, renderMode); 4330768a7dc450caf4c873c5b0883a75135536e1546Philip P. Moltmann } 4342961769ea94f69c191a2dd785b2504666c7292d0Svetoslav } 4352961769ea94f69c191a2dd785b2504666c7292d0Svetoslav 43695b6fd8b7af276069cbc415da3499d5ab4873c32Svetoslav /** 43795b6fd8b7af276069cbc415da3499d5ab4873c32Svetoslav * Closes this page. 43895b6fd8b7af276069cbc415da3499d5ab4873c32Svetoslav * 43995b6fd8b7af276069cbc415da3499d5ab4873c32Svetoslav * @see android.graphics.pdf.PdfRenderer#openPage(int) 44095b6fd8b7af276069cbc415da3499d5ab4873c32Svetoslav */ 44195b6fd8b7af276069cbc415da3499d5ab4873c32Svetoslav @Override 44295b6fd8b7af276069cbc415da3499d5ab4873c32Svetoslav public void close() { 44395b6fd8b7af276069cbc415da3499d5ab4873c32Svetoslav throwIfClosed(); 44495b6fd8b7af276069cbc415da3499d5ab4873c32Svetoslav doClose(); 44595b6fd8b7af276069cbc415da3499d5ab4873c32Svetoslav } 44695b6fd8b7af276069cbc415da3499d5ab4873c32Svetoslav 44795b6fd8b7af276069cbc415da3499d5ab4873c32Svetoslav @Override 44895b6fd8b7af276069cbc415da3499d5ab4873c32Svetoslav protected void finalize() throws Throwable { 44995b6fd8b7af276069cbc415da3499d5ab4873c32Svetoslav try { 450492e9e851cadca62df84eaff1a3c1ba788492fbaNarayan Kamath if (mCloseGuard != null) { 451492e9e851cadca62df84eaff1a3c1ba788492fbaNarayan Kamath mCloseGuard.warnIfOpen(); 452492e9e851cadca62df84eaff1a3c1ba788492fbaNarayan Kamath } 453492e9e851cadca62df84eaff1a3c1ba788492fbaNarayan Kamath 45495b6fd8b7af276069cbc415da3499d5ab4873c32Svetoslav if (mNativePage != 0) { 45595b6fd8b7af276069cbc415da3499d5ab4873c32Svetoslav doClose(); 45695b6fd8b7af276069cbc415da3499d5ab4873c32Svetoslav } 45795b6fd8b7af276069cbc415da3499d5ab4873c32Svetoslav } finally { 45895b6fd8b7af276069cbc415da3499d5ab4873c32Svetoslav super.finalize(); 45995b6fd8b7af276069cbc415da3499d5ab4873c32Svetoslav } 46095b6fd8b7af276069cbc415da3499d5ab4873c32Svetoslav } 46195b6fd8b7af276069cbc415da3499d5ab4873c32Svetoslav 46295b6fd8b7af276069cbc415da3499d5ab4873c32Svetoslav private void doClose() { 4630768a7dc450caf4c873c5b0883a75135536e1546Philip P. Moltmann synchronized (sPdfiumLock) { 4640768a7dc450caf4c873c5b0883a75135536e1546Philip P. Moltmann nativeClosePage(mNativePage); 4650768a7dc450caf4c873c5b0883a75135536e1546Philip P. Moltmann } 4662961769ea94f69c191a2dd785b2504666c7292d0Svetoslav mNativePage = 0; 46795b6fd8b7af276069cbc415da3499d5ab4873c32Svetoslav mCloseGuard.close(); 468525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov mCurrentPage = null; 46995b6fd8b7af276069cbc415da3499d5ab4873c32Svetoslav } 47095b6fd8b7af276069cbc415da3499d5ab4873c32Svetoslav 47195b6fd8b7af276069cbc415da3499d5ab4873c32Svetoslav private void throwIfClosed() { 47295b6fd8b7af276069cbc415da3499d5ab4873c32Svetoslav if (mNativePage == 0) { 47395b6fd8b7af276069cbc415da3499d5ab4873c32Svetoslav throw new IllegalStateException("Already closed"); 47495b6fd8b7af276069cbc415da3499d5ab4873c32Svetoslav } 4752961769ea94f69c191a2dd785b2504666c7292d0Svetoslav } 4762961769ea94f69c191a2dd785b2504666c7292d0Svetoslav } 4772961769ea94f69c191a2dd785b2504666c7292d0Svetoslav 4782961769ea94f69c191a2dd785b2504666c7292d0Svetoslav private static native long nativeCreate(int fd, long size); 4792961769ea94f69c191a2dd785b2504666c7292d0Svetoslav private static native void nativeClose(long documentPtr); 4802961769ea94f69c191a2dd785b2504666c7292d0Svetoslav private static native int nativeGetPageCount(long documentPtr); 4812961769ea94f69c191a2dd785b2504666c7292d0Svetoslav private static native boolean nativeScaleForPrinting(long documentPtr); 482ed207b92747234eac88dd3664ecfb535e45d8ed1John Reck private static native void nativeRenderPage(long documentPtr, long pagePtr, Bitmap dest, 483d55f20d3018d3328d9e26c971b814dfcb61aa7b2Philip P. Moltmann int clipLeft, int clipTop, int clipRight, int clipBottom, long transformPtr, 484d55f20d3018d3328d9e26c971b814dfcb61aa7b2Philip P. Moltmann int renderMode); 4852961769ea94f69c191a2dd785b2504666c7292d0Svetoslav private static native long nativeOpenPageAndGetSize(long documentPtr, int pageIndex, 4862961769ea94f69c191a2dd785b2504666c7292d0Svetoslav Point outSize); 4872961769ea94f69c191a2dd785b2504666c7292d0Svetoslav private static native void nativeClosePage(long pagePtr); 4882961769ea94f69c191a2dd785b2504666c7292d0Svetoslav} 489