PdfRenderer.java revision 95b6fd8b7af276069cbc415da3499d5ab4873c32
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; 302961769ea94f69c191a2dd785b2504666c7292d0Svetoslavimport dalvik.system.CloseGuard; 312961769ea94f69c191a2dd785b2504666c7292d0Svetoslavimport libcore.io.Libcore; 322961769ea94f69c191a2dd785b2504666c7292d0Svetoslav 332961769ea94f69c191a2dd785b2504666c7292d0Svetoslavimport java.io.IOException; 342961769ea94f69c191a2dd785b2504666c7292d0Svetoslavimport java.lang.annotation.Retention; 352961769ea94f69c191a2dd785b2504666c7292d0Svetoslavimport java.lang.annotation.RetentionPolicy; 362961769ea94f69c191a2dd785b2504666c7292d0Svetoslav 372961769ea94f69c191a2dd785b2504666c7292d0Svetoslav/** 382961769ea94f69c191a2dd785b2504666c7292d0Svetoslav * <p> 392961769ea94f69c191a2dd785b2504666c7292d0Svetoslav * This class enables rendering a PDF document. This class is not thread safe. 402961769ea94f69c191a2dd785b2504666c7292d0Svetoslav * </p> 412961769ea94f69c191a2dd785b2504666c7292d0Svetoslav * <p> 422961769ea94f69c191a2dd785b2504666c7292d0Svetoslav * If you want to render a PDF, you create a renderer and for every page you want 432961769ea94f69c191a2dd785b2504666c7292d0Svetoslav * to render, you open the page, render it, and close the page. After you are done 442961769ea94f69c191a2dd785b2504666c7292d0Svetoslav * with rendering, you close the renderer. After the renderer is closed it should not 452961769ea94f69c191a2dd785b2504666c7292d0Svetoslav * be used anymore. Note that the pages are rendered one by one, i.e. you can have 462961769ea94f69c191a2dd785b2504666c7292d0Svetoslav * only a single page opened at any given time. 472961769ea94f69c191a2dd785b2504666c7292d0Svetoslav * </p> 482961769ea94f69c191a2dd785b2504666c7292d0Svetoslav * <p> 492961769ea94f69c191a2dd785b2504666c7292d0Svetoslav * A typical use of the APIs to render a PDF looks like this: 502961769ea94f69c191a2dd785b2504666c7292d0Svetoslav * </p> 512961769ea94f69c191a2dd785b2504666c7292d0Svetoslav * <pre> 522961769ea94f69c191a2dd785b2504666c7292d0Svetoslav * // create a new renderer 532961769ea94f69c191a2dd785b2504666c7292d0Svetoslav * PdfRenderer renderer = new PdfRenderer(getSeekableFileDescriptor()); 542961769ea94f69c191a2dd785b2504666c7292d0Svetoslav * 552961769ea94f69c191a2dd785b2504666c7292d0Svetoslav * // let us just render all pages 562961769ea94f69c191a2dd785b2504666c7292d0Svetoslav * final int pageCount = renderer.getPageCount(); 572961769ea94f69c191a2dd785b2504666c7292d0Svetoslav * for (int i = 0; i < pageCount; i++) { 582961769ea94f69c191a2dd785b2504666c7292d0Svetoslav * Page page = renderer.openPage(i); 592961769ea94f69c191a2dd785b2504666c7292d0Svetoslav * 602961769ea94f69c191a2dd785b2504666c7292d0Svetoslav * // say we render for showing on the screen 6195b6fd8b7af276069cbc415da3499d5ab4873c32Svetoslav * page.render(mBitmap, null, null, Page.RENDER_MODE_FOR_DISPLAY); 622961769ea94f69c191a2dd785b2504666c7292d0Svetoslav * 632961769ea94f69c191a2dd785b2504666c7292d0Svetoslav * // do stuff with the bitmap 642961769ea94f69c191a2dd785b2504666c7292d0Svetoslav * 6595b6fd8b7af276069cbc415da3499d5ab4873c32Svetoslav * // close the page 6695b6fd8b7af276069cbc415da3499d5ab4873c32Svetoslav * page.close(); 672961769ea94f69c191a2dd785b2504666c7292d0Svetoslav * } 682961769ea94f69c191a2dd785b2504666c7292d0Svetoslav * 692961769ea94f69c191a2dd785b2504666c7292d0Svetoslav * // close the renderer 702961769ea94f69c191a2dd785b2504666c7292d0Svetoslav * renderer.close(); 712961769ea94f69c191a2dd785b2504666c7292d0Svetoslav * </pre> 722961769ea94f69c191a2dd785b2504666c7292d0Svetoslav * 732961769ea94f69c191a2dd785b2504666c7292d0Svetoslav * @see #close() 742961769ea94f69c191a2dd785b2504666c7292d0Svetoslav */ 752961769ea94f69c191a2dd785b2504666c7292d0Svetoslavpublic final class PdfRenderer implements AutoCloseable { 762961769ea94f69c191a2dd785b2504666c7292d0Svetoslav private final CloseGuard mCloseGuard = CloseGuard.get(); 772961769ea94f69c191a2dd785b2504666c7292d0Svetoslav 782961769ea94f69c191a2dd785b2504666c7292d0Svetoslav private final Point mTempPoint = new Point(); 792961769ea94f69c191a2dd785b2504666c7292d0Svetoslav 802961769ea94f69c191a2dd785b2504666c7292d0Svetoslav private final long mNativeDocument; 812961769ea94f69c191a2dd785b2504666c7292d0Svetoslav 822961769ea94f69c191a2dd785b2504666c7292d0Svetoslav private final int mPageCount; 832961769ea94f69c191a2dd785b2504666c7292d0Svetoslav 842961769ea94f69c191a2dd785b2504666c7292d0Svetoslav private ParcelFileDescriptor mInput; 852961769ea94f69c191a2dd785b2504666c7292d0Svetoslav 862961769ea94f69c191a2dd785b2504666c7292d0Svetoslav private Page mCurrentPage; 872961769ea94f69c191a2dd785b2504666c7292d0Svetoslav 882961769ea94f69c191a2dd785b2504666c7292d0Svetoslav /** @hide */ 892961769ea94f69c191a2dd785b2504666c7292d0Svetoslav @IntDef({ 902961769ea94f69c191a2dd785b2504666c7292d0Svetoslav Page.RENDER_MODE_FOR_DISPLAY, 912961769ea94f69c191a2dd785b2504666c7292d0Svetoslav Page.RENDER_MODE_FOR_PRINT 922961769ea94f69c191a2dd785b2504666c7292d0Svetoslav }) 932961769ea94f69c191a2dd785b2504666c7292d0Svetoslav @Retention(RetentionPolicy.SOURCE) 942961769ea94f69c191a2dd785b2504666c7292d0Svetoslav public @interface RenderMode {} 952961769ea94f69c191a2dd785b2504666c7292d0Svetoslav 962961769ea94f69c191a2dd785b2504666c7292d0Svetoslav /** 972961769ea94f69c191a2dd785b2504666c7292d0Svetoslav * Creates a new instance. 982961769ea94f69c191a2dd785b2504666c7292d0Svetoslav * <p> 992961769ea94f69c191a2dd785b2504666c7292d0Svetoslav * <strong>Note:</strong> The provided file descriptor must be <strong>seekable</strong>, 1002961769ea94f69c191a2dd785b2504666c7292d0Svetoslav * i.e. its data being randomly accessed, e.g. pointing to a file. 1012961769ea94f69c191a2dd785b2504666c7292d0Svetoslav * </p> 1022961769ea94f69c191a2dd785b2504666c7292d0Svetoslav * <p> 1032961769ea94f69c191a2dd785b2504666c7292d0Svetoslav * <strong>Note:</strong> This class takes ownership of the passed in file descriptor 1042961769ea94f69c191a2dd785b2504666c7292d0Svetoslav * and is responsible for closing it when the renderer is closed. 1052961769ea94f69c191a2dd785b2504666c7292d0Svetoslav * </p> 1062961769ea94f69c191a2dd785b2504666c7292d0Svetoslav * 1072961769ea94f69c191a2dd785b2504666c7292d0Svetoslav * @param input Seekable file descriptor to read from. 1082961769ea94f69c191a2dd785b2504666c7292d0Svetoslav */ 1092961769ea94f69c191a2dd785b2504666c7292d0Svetoslav public PdfRenderer(@NonNull ParcelFileDescriptor input) throws IOException { 1102961769ea94f69c191a2dd785b2504666c7292d0Svetoslav if (input == null) { 1112961769ea94f69c191a2dd785b2504666c7292d0Svetoslav throw new NullPointerException("input cannot be null"); 1122961769ea94f69c191a2dd785b2504666c7292d0Svetoslav } 1132961769ea94f69c191a2dd785b2504666c7292d0Svetoslav 1142961769ea94f69c191a2dd785b2504666c7292d0Svetoslav final long size; 1152961769ea94f69c191a2dd785b2504666c7292d0Svetoslav try { 1162961769ea94f69c191a2dd785b2504666c7292d0Svetoslav Libcore.os.lseek(input.getFileDescriptor(), 0, OsConstants.SEEK_SET); 1172961769ea94f69c191a2dd785b2504666c7292d0Svetoslav size = Libcore.os.fstat(input.getFileDescriptor()).st_size; 1182961769ea94f69c191a2dd785b2504666c7292d0Svetoslav } catch (ErrnoException ee) { 1192961769ea94f69c191a2dd785b2504666c7292d0Svetoslav throw new IllegalArgumentException("file descriptor not seekable"); 1202961769ea94f69c191a2dd785b2504666c7292d0Svetoslav } 1212961769ea94f69c191a2dd785b2504666c7292d0Svetoslav 1222961769ea94f69c191a2dd785b2504666c7292d0Svetoslav mInput = input; 1232961769ea94f69c191a2dd785b2504666c7292d0Svetoslav mNativeDocument = nativeCreate(mInput.getFd(), size); 1242961769ea94f69c191a2dd785b2504666c7292d0Svetoslav mPageCount = nativeGetPageCount(mNativeDocument); 1252961769ea94f69c191a2dd785b2504666c7292d0Svetoslav mCloseGuard.open("close"); 1262961769ea94f69c191a2dd785b2504666c7292d0Svetoslav } 1272961769ea94f69c191a2dd785b2504666c7292d0Svetoslav 1282961769ea94f69c191a2dd785b2504666c7292d0Svetoslav /** 1292961769ea94f69c191a2dd785b2504666c7292d0Svetoslav * Closes this renderer. You should not use this instance 1302961769ea94f69c191a2dd785b2504666c7292d0Svetoslav * after this method is called. 1312961769ea94f69c191a2dd785b2504666c7292d0Svetoslav */ 1322961769ea94f69c191a2dd785b2504666c7292d0Svetoslav public void close() { 1332961769ea94f69c191a2dd785b2504666c7292d0Svetoslav throwIfClosed(); 1342961769ea94f69c191a2dd785b2504666c7292d0Svetoslav throwIfPageOpened(); 1352961769ea94f69c191a2dd785b2504666c7292d0Svetoslav doClose(); 1362961769ea94f69c191a2dd785b2504666c7292d0Svetoslav } 1372961769ea94f69c191a2dd785b2504666c7292d0Svetoslav 1382961769ea94f69c191a2dd785b2504666c7292d0Svetoslav /** 1392961769ea94f69c191a2dd785b2504666c7292d0Svetoslav * Gets the number of pages in the document. 1402961769ea94f69c191a2dd785b2504666c7292d0Svetoslav * 1412961769ea94f69c191a2dd785b2504666c7292d0Svetoslav * @return The page count. 1422961769ea94f69c191a2dd785b2504666c7292d0Svetoslav */ 1432961769ea94f69c191a2dd785b2504666c7292d0Svetoslav public int getPageCount() { 1442961769ea94f69c191a2dd785b2504666c7292d0Svetoslav throwIfClosed(); 1452961769ea94f69c191a2dd785b2504666c7292d0Svetoslav return mPageCount; 1462961769ea94f69c191a2dd785b2504666c7292d0Svetoslav } 1472961769ea94f69c191a2dd785b2504666c7292d0Svetoslav 1482961769ea94f69c191a2dd785b2504666c7292d0Svetoslav /** 1492961769ea94f69c191a2dd785b2504666c7292d0Svetoslav * Gets whether the document prefers to be scaled for printing. 1502961769ea94f69c191a2dd785b2504666c7292d0Svetoslav * You should take this info account if the document is rendered 1512961769ea94f69c191a2dd785b2504666c7292d0Svetoslav * for printing and the target media size differs from the page 1522961769ea94f69c191a2dd785b2504666c7292d0Svetoslav * size. 1532961769ea94f69c191a2dd785b2504666c7292d0Svetoslav * 1542961769ea94f69c191a2dd785b2504666c7292d0Svetoslav * @return If to scale the document. 1552961769ea94f69c191a2dd785b2504666c7292d0Svetoslav */ 1562961769ea94f69c191a2dd785b2504666c7292d0Svetoslav public boolean shouldScaleForPrinting() { 1572961769ea94f69c191a2dd785b2504666c7292d0Svetoslav throwIfClosed(); 1582961769ea94f69c191a2dd785b2504666c7292d0Svetoslav return nativeScaleForPrinting(mNativeDocument); 1592961769ea94f69c191a2dd785b2504666c7292d0Svetoslav } 1602961769ea94f69c191a2dd785b2504666c7292d0Svetoslav 1612961769ea94f69c191a2dd785b2504666c7292d0Svetoslav /** 1622961769ea94f69c191a2dd785b2504666c7292d0Svetoslav * Opens a page for rendering. 1632961769ea94f69c191a2dd785b2504666c7292d0Svetoslav * 1642961769ea94f69c191a2dd785b2504666c7292d0Svetoslav * @param index The page index. 1652961769ea94f69c191a2dd785b2504666c7292d0Svetoslav * @return A page that can be rendered. 1662961769ea94f69c191a2dd785b2504666c7292d0Svetoslav * 16795b6fd8b7af276069cbc415da3499d5ab4873c32Svetoslav * @see android.graphics.pdf.PdfRenderer.Page#close() PdfRenderer.Page.close() 1682961769ea94f69c191a2dd785b2504666c7292d0Svetoslav */ 1692961769ea94f69c191a2dd785b2504666c7292d0Svetoslav public Page openPage(int index) { 1702961769ea94f69c191a2dd785b2504666c7292d0Svetoslav throwIfClosed(); 1712961769ea94f69c191a2dd785b2504666c7292d0Svetoslav throwIfPageOpened(); 1722961769ea94f69c191a2dd785b2504666c7292d0Svetoslav mCurrentPage = new Page(index); 1732961769ea94f69c191a2dd785b2504666c7292d0Svetoslav return mCurrentPage; 1742961769ea94f69c191a2dd785b2504666c7292d0Svetoslav } 1752961769ea94f69c191a2dd785b2504666c7292d0Svetoslav 1762961769ea94f69c191a2dd785b2504666c7292d0Svetoslav @Override 1772961769ea94f69c191a2dd785b2504666c7292d0Svetoslav protected void finalize() throws Throwable { 1782961769ea94f69c191a2dd785b2504666c7292d0Svetoslav try { 1792961769ea94f69c191a2dd785b2504666c7292d0Svetoslav mCloseGuard.warnIfOpen(); 1802961769ea94f69c191a2dd785b2504666c7292d0Svetoslav if (mInput != null) { 1812961769ea94f69c191a2dd785b2504666c7292d0Svetoslav doClose(); 1822961769ea94f69c191a2dd785b2504666c7292d0Svetoslav } 1832961769ea94f69c191a2dd785b2504666c7292d0Svetoslav } finally { 1842961769ea94f69c191a2dd785b2504666c7292d0Svetoslav super.finalize(); 1852961769ea94f69c191a2dd785b2504666c7292d0Svetoslav } 1862961769ea94f69c191a2dd785b2504666c7292d0Svetoslav } 1872961769ea94f69c191a2dd785b2504666c7292d0Svetoslav 1882961769ea94f69c191a2dd785b2504666c7292d0Svetoslav private void doClose() { 1892961769ea94f69c191a2dd785b2504666c7292d0Svetoslav if (mCurrentPage != null) { 1902961769ea94f69c191a2dd785b2504666c7292d0Svetoslav mCurrentPage.close(); 1912961769ea94f69c191a2dd785b2504666c7292d0Svetoslav mCurrentPage = null; 1922961769ea94f69c191a2dd785b2504666c7292d0Svetoslav } 1932961769ea94f69c191a2dd785b2504666c7292d0Svetoslav nativeClose(mNativeDocument); 1942961769ea94f69c191a2dd785b2504666c7292d0Svetoslav try { 1952961769ea94f69c191a2dd785b2504666c7292d0Svetoslav mInput.close(); 1962961769ea94f69c191a2dd785b2504666c7292d0Svetoslav } catch (IOException ioe) { 1972961769ea94f69c191a2dd785b2504666c7292d0Svetoslav /* ignore - best effort */ 1982961769ea94f69c191a2dd785b2504666c7292d0Svetoslav } 1992961769ea94f69c191a2dd785b2504666c7292d0Svetoslav mInput = null; 2002961769ea94f69c191a2dd785b2504666c7292d0Svetoslav mCloseGuard.close(); 2012961769ea94f69c191a2dd785b2504666c7292d0Svetoslav } 2022961769ea94f69c191a2dd785b2504666c7292d0Svetoslav 2032961769ea94f69c191a2dd785b2504666c7292d0Svetoslav private void throwIfClosed() { 2042961769ea94f69c191a2dd785b2504666c7292d0Svetoslav if (mInput == null) { 2052961769ea94f69c191a2dd785b2504666c7292d0Svetoslav throw new IllegalStateException("Already closed"); 2062961769ea94f69c191a2dd785b2504666c7292d0Svetoslav } 2072961769ea94f69c191a2dd785b2504666c7292d0Svetoslav } 2082961769ea94f69c191a2dd785b2504666c7292d0Svetoslav 2092961769ea94f69c191a2dd785b2504666c7292d0Svetoslav private void throwIfPageOpened() { 2102961769ea94f69c191a2dd785b2504666c7292d0Svetoslav if (mCurrentPage != null) { 2112961769ea94f69c191a2dd785b2504666c7292d0Svetoslav throw new IllegalStateException("Current page not closed"); 2122961769ea94f69c191a2dd785b2504666c7292d0Svetoslav } 2132961769ea94f69c191a2dd785b2504666c7292d0Svetoslav } 2142961769ea94f69c191a2dd785b2504666c7292d0Svetoslav 2152961769ea94f69c191a2dd785b2504666c7292d0Svetoslav /** 2162961769ea94f69c191a2dd785b2504666c7292d0Svetoslav * This class represents a PDF document page for rendering. 2172961769ea94f69c191a2dd785b2504666c7292d0Svetoslav */ 21895b6fd8b7af276069cbc415da3499d5ab4873c32Svetoslav public final class Page implements AutoCloseable { 21995b6fd8b7af276069cbc415da3499d5ab4873c32Svetoslav 22095b6fd8b7af276069cbc415da3499d5ab4873c32Svetoslav private final CloseGuard mCloseGuard = CloseGuard.get(); 2212961769ea94f69c191a2dd785b2504666c7292d0Svetoslav 2222961769ea94f69c191a2dd785b2504666c7292d0Svetoslav /** 2232961769ea94f69c191a2dd785b2504666c7292d0Svetoslav * Mode to render the content for display on a screen. 2242961769ea94f69c191a2dd785b2504666c7292d0Svetoslav */ 2252961769ea94f69c191a2dd785b2504666c7292d0Svetoslav public static final int RENDER_MODE_FOR_DISPLAY = 1; 2262961769ea94f69c191a2dd785b2504666c7292d0Svetoslav 2272961769ea94f69c191a2dd785b2504666c7292d0Svetoslav /** 2282961769ea94f69c191a2dd785b2504666c7292d0Svetoslav * Mode to render the content for printing. 2292961769ea94f69c191a2dd785b2504666c7292d0Svetoslav */ 2302961769ea94f69c191a2dd785b2504666c7292d0Svetoslav public static final int RENDER_MODE_FOR_PRINT = 2; 2312961769ea94f69c191a2dd785b2504666c7292d0Svetoslav 2322961769ea94f69c191a2dd785b2504666c7292d0Svetoslav private final int mIndex; 2332961769ea94f69c191a2dd785b2504666c7292d0Svetoslav private final int mWidth; 2342961769ea94f69c191a2dd785b2504666c7292d0Svetoslav private final int mHeight; 2352961769ea94f69c191a2dd785b2504666c7292d0Svetoslav 2362961769ea94f69c191a2dd785b2504666c7292d0Svetoslav private long mNativePage; 2372961769ea94f69c191a2dd785b2504666c7292d0Svetoslav 2382961769ea94f69c191a2dd785b2504666c7292d0Svetoslav private Page(int index) { 2392961769ea94f69c191a2dd785b2504666c7292d0Svetoslav Point size = mTempPoint; 2402961769ea94f69c191a2dd785b2504666c7292d0Svetoslav mNativePage = nativeOpenPageAndGetSize(mNativeDocument, index, size); 2412961769ea94f69c191a2dd785b2504666c7292d0Svetoslav mIndex = index; 2422961769ea94f69c191a2dd785b2504666c7292d0Svetoslav mWidth = size.x; 2432961769ea94f69c191a2dd785b2504666c7292d0Svetoslav mHeight = size.y; 24495b6fd8b7af276069cbc415da3499d5ab4873c32Svetoslav mCloseGuard.open("close"); 2452961769ea94f69c191a2dd785b2504666c7292d0Svetoslav } 2462961769ea94f69c191a2dd785b2504666c7292d0Svetoslav 2472961769ea94f69c191a2dd785b2504666c7292d0Svetoslav /** 2482961769ea94f69c191a2dd785b2504666c7292d0Svetoslav * Gets the page index. 2492961769ea94f69c191a2dd785b2504666c7292d0Svetoslav * 2502961769ea94f69c191a2dd785b2504666c7292d0Svetoslav * @return The index. 2512961769ea94f69c191a2dd785b2504666c7292d0Svetoslav */ 2522961769ea94f69c191a2dd785b2504666c7292d0Svetoslav public int getIndex() { 2532961769ea94f69c191a2dd785b2504666c7292d0Svetoslav return mIndex; 2542961769ea94f69c191a2dd785b2504666c7292d0Svetoslav } 2552961769ea94f69c191a2dd785b2504666c7292d0Svetoslav 2562961769ea94f69c191a2dd785b2504666c7292d0Svetoslav /** 2572961769ea94f69c191a2dd785b2504666c7292d0Svetoslav * Gets the page width in points (1/72"). 2582961769ea94f69c191a2dd785b2504666c7292d0Svetoslav * 2592961769ea94f69c191a2dd785b2504666c7292d0Svetoslav * @return The width in points. 2602961769ea94f69c191a2dd785b2504666c7292d0Svetoslav */ 2612961769ea94f69c191a2dd785b2504666c7292d0Svetoslav public int getWidth() { 2622961769ea94f69c191a2dd785b2504666c7292d0Svetoslav return mWidth; 2632961769ea94f69c191a2dd785b2504666c7292d0Svetoslav } 2642961769ea94f69c191a2dd785b2504666c7292d0Svetoslav 2652961769ea94f69c191a2dd785b2504666c7292d0Svetoslav /** 2662961769ea94f69c191a2dd785b2504666c7292d0Svetoslav * Gets the page height in points (1/72"). 2672961769ea94f69c191a2dd785b2504666c7292d0Svetoslav * 2682961769ea94f69c191a2dd785b2504666c7292d0Svetoslav * @return The height in points. 2692961769ea94f69c191a2dd785b2504666c7292d0Svetoslav */ 2702961769ea94f69c191a2dd785b2504666c7292d0Svetoslav public int getHeight() { 2712961769ea94f69c191a2dd785b2504666c7292d0Svetoslav return mHeight; 2722961769ea94f69c191a2dd785b2504666c7292d0Svetoslav } 2732961769ea94f69c191a2dd785b2504666c7292d0Svetoslav 2742961769ea94f69c191a2dd785b2504666c7292d0Svetoslav /** 2752961769ea94f69c191a2dd785b2504666c7292d0Svetoslav * Renders a page to a bitmap. 2762961769ea94f69c191a2dd785b2504666c7292d0Svetoslav * <p> 2772961769ea94f69c191a2dd785b2504666c7292d0Svetoslav * You may optionally specify a rectangular clip in the bitmap bounds. No rendering 2782961769ea94f69c191a2dd785b2504666c7292d0Svetoslav * outside the clip will be performed, hence it is your responsibility to initialize 2792961769ea94f69c191a2dd785b2504666c7292d0Svetoslav * the bitmap outside the clip. 2802961769ea94f69c191a2dd785b2504666c7292d0Svetoslav * </p> 2812961769ea94f69c191a2dd785b2504666c7292d0Svetoslav * <p> 2822961769ea94f69c191a2dd785b2504666c7292d0Svetoslav * You may optionally specify a matrix to transform the content from page coordinates 2832961769ea94f69c191a2dd785b2504666c7292d0Svetoslav * which are in points (1/72") to bitmap coordintates which are in pixels. If this 2842961769ea94f69c191a2dd785b2504666c7292d0Svetoslav * matrix is not provided this method will apply a transformation that will fit the 28595b6fd8b7af276069cbc415da3499d5ab4873c32Svetoslav * whole page to the destination clip if provided or the destination bitmap if no 2862961769ea94f69c191a2dd785b2504666c7292d0Svetoslav * clip is provided. 2872961769ea94f69c191a2dd785b2504666c7292d0Svetoslav * </p> 2882961769ea94f69c191a2dd785b2504666c7292d0Svetoslav * <p> 2892961769ea94f69c191a2dd785b2504666c7292d0Svetoslav * The clip and transformation are useful for implementing tile rendering where the 2902961769ea94f69c191a2dd785b2504666c7292d0Svetoslav * destination bitmap contains a portion of the image, for example when zooming. 2912961769ea94f69c191a2dd785b2504666c7292d0Svetoslav * Another useful application is for printing where the size of the bitmap holding 2922961769ea94f69c191a2dd785b2504666c7292d0Svetoslav * the page is too large and a client can render the page in stripes. 2932961769ea94f69c191a2dd785b2504666c7292d0Svetoslav * </p> 2942961769ea94f69c191a2dd785b2504666c7292d0Svetoslav * <p> 2952961769ea94f69c191a2dd785b2504666c7292d0Svetoslav * <strong>Note: </strong> The destination bitmap format must be 2962961769ea94f69c191a2dd785b2504666c7292d0Svetoslav * {@link Config#ARGB_8888 ARGB}. 2972961769ea94f69c191a2dd785b2504666c7292d0Svetoslav * </p> 2982961769ea94f69c191a2dd785b2504666c7292d0Svetoslav * <p> 2992961769ea94f69c191a2dd785b2504666c7292d0Svetoslav * <strong>Note: </strong> The optional transformation matrix must be affine as per 30095b6fd8b7af276069cbc415da3499d5ab4873c32Svetoslav * {@link android.graphics.Matrix#isAffine() Matrix.isAffine()}. Hence, you can specify 30195b6fd8b7af276069cbc415da3499d5ab4873c32Svetoslav * rotation, scaling, translation but not a perspective transformation. 3022961769ea94f69c191a2dd785b2504666c7292d0Svetoslav * </p> 3032961769ea94f69c191a2dd785b2504666c7292d0Svetoslav * 3042961769ea94f69c191a2dd785b2504666c7292d0Svetoslav * @param destination Destination bitmap to which to render. 3052961769ea94f69c191a2dd785b2504666c7292d0Svetoslav * @param destClip Optional clip in the bitmap bounds. 3062961769ea94f69c191a2dd785b2504666c7292d0Svetoslav * @param transform Optional transformation to apply when rendering. 3072961769ea94f69c191a2dd785b2504666c7292d0Svetoslav * @param renderMode The render mode. 3082961769ea94f69c191a2dd785b2504666c7292d0Svetoslav * 3092961769ea94f69c191a2dd785b2504666c7292d0Svetoslav * @see #RENDER_MODE_FOR_DISPLAY 3102961769ea94f69c191a2dd785b2504666c7292d0Svetoslav * @see #RENDER_MODE_FOR_PRINT 3112961769ea94f69c191a2dd785b2504666c7292d0Svetoslav */ 3122961769ea94f69c191a2dd785b2504666c7292d0Svetoslav public void render(@NonNull Bitmap destination, @Nullable Rect destClip, 3132961769ea94f69c191a2dd785b2504666c7292d0Svetoslav @Nullable Matrix transform, @RenderMode int renderMode) { 3142961769ea94f69c191a2dd785b2504666c7292d0Svetoslav if (destination.getConfig() != Config.ARGB_8888) { 3152961769ea94f69c191a2dd785b2504666c7292d0Svetoslav throw new IllegalArgumentException("Unsupported pixel format"); 3162961769ea94f69c191a2dd785b2504666c7292d0Svetoslav } 3172961769ea94f69c191a2dd785b2504666c7292d0Svetoslav 3182961769ea94f69c191a2dd785b2504666c7292d0Svetoslav if (destClip != null) { 3192961769ea94f69c191a2dd785b2504666c7292d0Svetoslav if (destClip.left < 0 || destClip.top < 0 3202961769ea94f69c191a2dd785b2504666c7292d0Svetoslav || destClip.right > destination.getWidth() 3212961769ea94f69c191a2dd785b2504666c7292d0Svetoslav || destClip.bottom > destination.getHeight()) { 3222961769ea94f69c191a2dd785b2504666c7292d0Svetoslav throw new IllegalArgumentException("destBounds not in destination"); 3232961769ea94f69c191a2dd785b2504666c7292d0Svetoslav } 3242961769ea94f69c191a2dd785b2504666c7292d0Svetoslav } 3252961769ea94f69c191a2dd785b2504666c7292d0Svetoslav 3262961769ea94f69c191a2dd785b2504666c7292d0Svetoslav if (transform != null && !transform.isAffine()) { 3272961769ea94f69c191a2dd785b2504666c7292d0Svetoslav throw new IllegalArgumentException("transform not affine"); 3282961769ea94f69c191a2dd785b2504666c7292d0Svetoslav } 3292961769ea94f69c191a2dd785b2504666c7292d0Svetoslav 3302961769ea94f69c191a2dd785b2504666c7292d0Svetoslav if (renderMode != RENDER_MODE_FOR_PRINT && renderMode != RENDER_MODE_FOR_DISPLAY) { 3312961769ea94f69c191a2dd785b2504666c7292d0Svetoslav throw new IllegalArgumentException("Unsupported render mode"); 3322961769ea94f69c191a2dd785b2504666c7292d0Svetoslav } 3332961769ea94f69c191a2dd785b2504666c7292d0Svetoslav 3342961769ea94f69c191a2dd785b2504666c7292d0Svetoslav if (renderMode == RENDER_MODE_FOR_PRINT && renderMode == RENDER_MODE_FOR_DISPLAY) { 3352961769ea94f69c191a2dd785b2504666c7292d0Svetoslav throw new IllegalArgumentException("Only single render mode supported"); 3362961769ea94f69c191a2dd785b2504666c7292d0Svetoslav } 3372961769ea94f69c191a2dd785b2504666c7292d0Svetoslav 3382961769ea94f69c191a2dd785b2504666c7292d0Svetoslav final int contentLeft = (destClip != null) ? destClip.left : 0; 3392961769ea94f69c191a2dd785b2504666c7292d0Svetoslav final int contentTop = (destClip != null) ? destClip.top : 0; 3402961769ea94f69c191a2dd785b2504666c7292d0Svetoslav final int contentRight = (destClip != null) ? destClip.right 3412961769ea94f69c191a2dd785b2504666c7292d0Svetoslav : destination.getWidth(); 3422961769ea94f69c191a2dd785b2504666c7292d0Svetoslav final int contentBottom = (destClip != null) ? destClip.bottom 3432961769ea94f69c191a2dd785b2504666c7292d0Svetoslav : destination.getHeight(); 3442961769ea94f69c191a2dd785b2504666c7292d0Svetoslav 3452961769ea94f69c191a2dd785b2504666c7292d0Svetoslav final long transformPtr = (transform != null) ? transform.native_instance : 0; 3462961769ea94f69c191a2dd785b2504666c7292d0Svetoslav 3472961769ea94f69c191a2dd785b2504666c7292d0Svetoslav nativeRenderPage(mNativeDocument, mNativePage, destination.mNativeBitmap, contentLeft, 3482961769ea94f69c191a2dd785b2504666c7292d0Svetoslav contentTop, contentRight, contentBottom, transformPtr, renderMode); 3492961769ea94f69c191a2dd785b2504666c7292d0Svetoslav } 3502961769ea94f69c191a2dd785b2504666c7292d0Svetoslav 35195b6fd8b7af276069cbc415da3499d5ab4873c32Svetoslav /** 35295b6fd8b7af276069cbc415da3499d5ab4873c32Svetoslav * Closes this page. 35395b6fd8b7af276069cbc415da3499d5ab4873c32Svetoslav * 35495b6fd8b7af276069cbc415da3499d5ab4873c32Svetoslav * @see android.graphics.pdf.PdfRenderer#openPage(int) 35595b6fd8b7af276069cbc415da3499d5ab4873c32Svetoslav */ 35695b6fd8b7af276069cbc415da3499d5ab4873c32Svetoslav @Override 35795b6fd8b7af276069cbc415da3499d5ab4873c32Svetoslav public void close() { 35895b6fd8b7af276069cbc415da3499d5ab4873c32Svetoslav throwIfClosed(); 35995b6fd8b7af276069cbc415da3499d5ab4873c32Svetoslav doClose(); 36095b6fd8b7af276069cbc415da3499d5ab4873c32Svetoslav } 36195b6fd8b7af276069cbc415da3499d5ab4873c32Svetoslav 36295b6fd8b7af276069cbc415da3499d5ab4873c32Svetoslav @Override 36395b6fd8b7af276069cbc415da3499d5ab4873c32Svetoslav protected void finalize() throws Throwable { 36495b6fd8b7af276069cbc415da3499d5ab4873c32Svetoslav try { 36595b6fd8b7af276069cbc415da3499d5ab4873c32Svetoslav mCloseGuard.warnIfOpen(); 36695b6fd8b7af276069cbc415da3499d5ab4873c32Svetoslav if (mNativePage != 0) { 36795b6fd8b7af276069cbc415da3499d5ab4873c32Svetoslav doClose(); 36895b6fd8b7af276069cbc415da3499d5ab4873c32Svetoslav } 36995b6fd8b7af276069cbc415da3499d5ab4873c32Svetoslav } finally { 37095b6fd8b7af276069cbc415da3499d5ab4873c32Svetoslav super.finalize(); 37195b6fd8b7af276069cbc415da3499d5ab4873c32Svetoslav } 37295b6fd8b7af276069cbc415da3499d5ab4873c32Svetoslav } 37395b6fd8b7af276069cbc415da3499d5ab4873c32Svetoslav 37495b6fd8b7af276069cbc415da3499d5ab4873c32Svetoslav private void doClose() { 3752961769ea94f69c191a2dd785b2504666c7292d0Svetoslav nativeClosePage(mNativePage); 3762961769ea94f69c191a2dd785b2504666c7292d0Svetoslav mNativePage = 0; 37795b6fd8b7af276069cbc415da3499d5ab4873c32Svetoslav mCloseGuard.close(); 37895b6fd8b7af276069cbc415da3499d5ab4873c32Svetoslav } 37995b6fd8b7af276069cbc415da3499d5ab4873c32Svetoslav 38095b6fd8b7af276069cbc415da3499d5ab4873c32Svetoslav private void throwIfClosed() { 38195b6fd8b7af276069cbc415da3499d5ab4873c32Svetoslav if (mNativePage == 0) { 38295b6fd8b7af276069cbc415da3499d5ab4873c32Svetoslav throw new IllegalStateException("Already closed"); 38395b6fd8b7af276069cbc415da3499d5ab4873c32Svetoslav } 3842961769ea94f69c191a2dd785b2504666c7292d0Svetoslav } 3852961769ea94f69c191a2dd785b2504666c7292d0Svetoslav } 3862961769ea94f69c191a2dd785b2504666c7292d0Svetoslav 3872961769ea94f69c191a2dd785b2504666c7292d0Svetoslav private static native long nativeCreate(int fd, long size); 3882961769ea94f69c191a2dd785b2504666c7292d0Svetoslav private static native void nativeClose(long documentPtr); 3892961769ea94f69c191a2dd785b2504666c7292d0Svetoslav private static native int nativeGetPageCount(long documentPtr); 3902961769ea94f69c191a2dd785b2504666c7292d0Svetoslav private static native boolean nativeScaleForPrinting(long documentPtr); 3912961769ea94f69c191a2dd785b2504666c7292d0Svetoslav private static native void nativeRenderPage(long documentPtr, long pagePtr, long destPtr, 3922961769ea94f69c191a2dd785b2504666c7292d0Svetoslav int destLeft, int destTop, int destRight, int destBottom, long matrixPtr, int renderMode); 3932961769ea94f69c191a2dd785b2504666c7292d0Svetoslav private static native long nativeOpenPageAndGetSize(long documentPtr, int pageIndex, 3942961769ea94f69c191a2dd785b2504666c7292d0Svetoslav Point outSize); 3952961769ea94f69c191a2dd785b2504666c7292d0Svetoslav private static native void nativeClosePage(long pagePtr); 3962961769ea94f69c191a2dd785b2504666c7292d0Svetoslav} 397