• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2024 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package android.graphics.pdf;
18 
19 import android.annotation.IntRange;
20 import android.annotation.NonNull;
21 import android.graphics.Bitmap;
22 import android.graphics.Rect;
23 import android.graphics.pdf.component.PdfAnnotation;
24 import android.graphics.pdf.component.PdfPageObject;
25 import android.graphics.pdf.content.PdfPageGotoLinkContent;
26 import android.graphics.pdf.models.FormWidgetInfo;
27 import android.graphics.pdf.models.jni.LinkRects;
28 import android.graphics.pdf.models.jni.LoadPdfResult;
29 import android.graphics.pdf.models.jni.MatchRects;
30 import android.graphics.pdf.models.jni.PageSelection;
31 import android.graphics.pdf.models.jni.SelectionBoundary;
32 import android.graphics.pdf.utils.StrictModeUtils;
33 import android.os.ParcelFileDescriptor;
34 
35 import java.util.List;
36 
37 /**
38  * This class accesses the PdfClient tools to manipulate and render a PDF document. One instance of
39  * this class corresponds to one PDF document, loads it within PdfClient and keeps an internal
40  * reference to the resulting object, to be re-used in subsequent calls.
41  *
42  * <p>This class is mostly a JNI gateway to PdfClient.
43  *
44  * @hide
45  */
46 public class PdfDocumentProxy {
47     private static final String TAG = "PdfDocument";
48 
49     private static final String LIB_NAME = "pdfclient";
50 
51     /** Internal reference to a native pointer to a Document object. */
52     private final long mPdfDocPtr;
53 
54     private final int mNumPages;
55 
56     /** Constructs a PdfDocument. Do not call directly from java, use {@link #createFromFd}. */
PdfDocumentProxy(long pdfDocPtr, int numPages)57     protected PdfDocumentProxy(long pdfDocPtr, int numPages) {
58         this.mPdfDocPtr = pdfDocPtr;
59         this.mNumPages = numPages;
60     }
61 
62     /**
63      * Tries to load a PdfDocument from native file descriptor.
64      *
65      * @return a LoadPdfResult of status LOADED containing the PdfDocument,
66      * or, an empty LoadPdfResult of a different status indicating failure.
67      */
createFromFd(int fd, String password)68     public static native LoadPdfResult createFromFd(int fd, String password);
69 
70     /**
71      * Loads the PdfClient binary library used to render PDF documents. The library will only be
72      * loaded once so subsequent calls after the first will have no effect. This may be used to
73      * preload the library before use.
74      */
loadLibPdf()75     public static void loadLibPdf() {
76         // TODO(b/324549320): Cleanup if bypassing is not required
77         StrictModeUtils.bypass(() -> System.loadLibrary(LIB_NAME));
78     }
79 
getPdfDocPtr()80     public long getPdfDocPtr() {
81         return mPdfDocPtr;
82     }
83 
getNumPages()84     public int getNumPages() {
85         return mNumPages;
86     }
87 
88     /** Destroys the PDF document and release resources held by PdfClient. */
destroy()89     public native void destroy();
90 
91     /**
92      * Tries to save this PdfDocument to the given native file descriptor, which must be open for
93      * write or append.
94      *
95      * @return true on success
96      */
saveToFd(int fd)97     public native boolean saveToFd(int fd);
98 
99     /**
100      * Saves the current state of this {@link PdfDocument} to the given, writable, file descriptor.
101      * The given file descriptor is closed by this function.
102      *
103      * @param destination the file descriptor to write to
104      * @return true on success
105      */
saveAs(ParcelFileDescriptor destination)106     public boolean saveAs(ParcelFileDescriptor destination) {
107         return saveToFd(destination.detachFd());
108     }
109 
110     /**
111      * Returns the width of the given page of the PDF. This is measured in points, but we
112      * zoom-to-fit, so it doesn't matter.
113      */
getPageWidth(int pageNum)114     public native int getPageWidth(int pageNum);
115 
116     /**
117      * Returns the height of the given page of the PDF. This is measured in points, but we
118      * zoom-to-fit, so it doesn't matter.
119      */
getPageHeight(int pageNum)120     public native int getPageHeight(int pageNum);
121 
122     /**
123      * Renders a page to a bitmap.
124      *
125      * @param pageNum          the page number of the page to be rendered
126      * @param clipLeft         the left coordinate of the clipping boundary in bitmap coordinates
127      * @param clipTop          the top coordinate of the clipping boundary in bitmap coordinates
128      * @param clipRight        the right coordinate of the clipping boundary in bitmap coordinates
129      * @param clipBottom       the bottom coordinate of the clipping boundary in bitmap coordinates
130      * @param transform        an affine transform matrix in the form of an array.
131      * @param renderMode       the render mode
132      * @param showAnnotTypes   Bitmask of renderFlags to indicate the types of annotations to
133      *                         be rendered
134      * @param renderFormFields true to included PDF form content in the output
135      * @return true if the page was rendered into the destination bitmap
136      * @see android.graphics.Matrix#getValues(float[])
137      */
render( int pageNum, Bitmap bitmap, int clipLeft, int clipTop, int clipRight, int clipBottom, float[] transform, int renderMode, int showAnnotTypes, boolean renderFormFields)138     public native boolean render(
139             int pageNum,
140             Bitmap bitmap,
141             int clipLeft,
142             int clipTop,
143             int clipRight,
144             int clipBottom,
145             float[] transform,
146             int renderMode,
147             int showAnnotTypes,
148             boolean renderFormFields);
149 
150     /**
151      * Clones the currently loaded document using the provided file descriptor.
152      * <p>You are required to detach the file descriptor as the native code will close it.
153      *
154      * @param destination native fd pointer
155      * @return true if the cloning was successful
156      */
cloneWithoutSecurity(int destination)157     private native boolean cloneWithoutSecurity(int destination);
158 
159     /**
160      * Clones the currently loaded document using the provided file descriptor.
161      * <p>You are required to detach the file descriptor as the native code will close it.
162      *
163      * @param destination {@link ParcelFileDescriptor} to which the document needs to be written to.
164      * @return true if the cloning was successful
165      */
cloneWithoutSecurity(ParcelFileDescriptor destination)166     public boolean cloneWithoutSecurity(ParcelFileDescriptor destination) {
167         return cloneWithoutSecurity(destination.detachFd());
168     }
169 
170     /**
171      * Gets the text of the entire page as a string, in the order the text is
172      * found in the PDF stream.
173      */
getPageText(int pageNum)174     public native String getPageText(int pageNum);
175 
176     /**
177      * Gets all pieces of alt-text found for the page, in the order the alt-text is found in the
178      * PDF stream.
179      */
getPageAltText(int pageNum)180     public native List<String> getPageAltText(int pageNum);
181 
182     /**
183      * Searches for the given string on the page and returns the bounds of all of the matches.
184      * The number of matches is {@link MatchRects#size()}.
185      */
searchPageText(int pageNum, String query)186     public native MatchRects searchPageText(int pageNum, String query);
187 
188     /**
189      * Get the text selection that spans between the two boundaries (inclusive of start and
190      * exclusive of stop), both of which can be either exactly defined with text indexes, or
191      * approximately defined with points on the page. The resulting selection will also be exactly
192      * defined with both indexes and points. If the start and stop boundary are both the same point,
193      * selects the word at that point.
194      */
selectPageText(int pageNum, SelectionBoundary start, SelectionBoundary stop)195     public native PageSelection selectPageText(int pageNum, SelectionBoundary start,
196             SelectionBoundary stop);
197 
198     /** Get the bounds and URLs of all the links on the given page. */
getPageLinks(int pageNum)199     public native LinkRects getPageLinks(int pageNum);
200 
201     /** Returns bookmarks and other goto links (within the current document) on a page */
getPageGotoLinks(int pageNum)202     public native List<PdfPageGotoLinkContent> getPageGotoLinks(int pageNum);
203 
204     /** Loads a page object and retains it in memory when a page becomes visible. */
retainPage(int pageNum)205     public native void retainPage(int pageNum);
206 
207     /** Cleans up objects in memory related to a page after it is no longer visible. */
releasePage(int pageNum)208     public native void releasePage(int pageNum);
209 
210     /** Returns true if the PDF is linearized. (May give false negatives for <1KB PDFs). */
isPdfLinearized()211     public native boolean isPdfLinearized();
212 
213     /** Returns true if the document prefers to be scaled for printing. */
scaleForPrinting()214     public native boolean scaleForPrinting();
215 
216     /**
217      * Returns an int representing the form type contained in the PDF, e.g. Acro vs XFA (if any).
218      */
getFormType()219     public native int getFormType();
220 
221     /** Obtains information about the widget at point ({@code x}, {@code y}), if any. */
getFormWidgetInfo(int pageNum, int x, int y)222     public native FormWidgetInfo getFormWidgetInfo(int pageNum, int x, int y);
223 
224     /**
225      * Obtains information about the widget with ({@code annotationIndex} on page {@code pageNum}),
226      * if any.
227      */
getFormWidgetInfo(int pageNum, int annotationIndex)228     public native FormWidgetInfo getFormWidgetInfo(int pageNum, int annotationIndex);
229 
230     /**
231      * Obtains information about all form widgets on page ({@code pageNum}, if any.
232      *
233      * <p>Optionally restricts by {@code typeIds}. If {@code typeIds} is empty, all form widgets on
234      * the page will be returned.
235      */
getFormWidgetInfos(int pageNum, int[] typeIds)236     public native List<FormWidgetInfo> getFormWidgetInfos(int pageNum, int[] typeIds);
237 
238     /**
239      * Executes an interactive click on the page at the given point ({@code x}, {@code y}).
240      *
241      * @return rectangular areas of the page bitmap that have been invalidated by this action
242      */
clickOnPage(int pageNum, int x, int y)243     public native List<Rect> clickOnPage(int pageNum, int x, int y);
244 
245     /**
246      * Sets the text of the widget at {@code annotationIndex}, if applicable.
247      *
248      * @return rectangular areas of the page bitmap that have been invalidated by this action
249      */
setFormFieldText(int pageNum, int annotIndex, String text)250     public native List<Rect> setFormFieldText(int pageNum, int annotIndex, String text);
251 
252     /**
253      * Selects the {@code selectedIndices} and unselects all others for the widget at {@code
254      * annotationIndex}, if applicable.
255      *
256      * @return Rectangular areas of the page bitmap that have been invalidated by this action
257      */
setFormFieldSelectedIndices( int pageNum, int annotIndex, int[] selectedIndices)258     public native List<Rect> setFormFieldSelectedIndices(
259             int pageNum, int annotIndex, int[] selectedIndices);
260 
261     /**
262      * Returns the list of {@link PdfAnnotation} present on the page.
263      * The list item is non-null for supported types (freetext, image, stamp) and
264      * null for unsupported types.
265      *
266      * @param pageNum - page number of the page whose annotations list is to be returned
267      * @return A {@link List} of {@link PdfAnnotation}
268      */
getPageAnnotations( @ntRangefrom = 0) int pageNum)269     public native @NonNull List<PdfAnnotation> getPageAnnotations(
270             @IntRange(from = 0) int pageNum);
271 
272     /**
273      * Adds the given {@link PdfAnnotation} to the given page
274      *
275      * @param pageNum    - page number of the page to which annotation is to be added
276      * @param annotation - {@link PdfAnnotation} to be added to the given page
277      * @return index of the annotation added, -1 in case of failure
278      */
addPageAnnotation(@ntRangefrom = 0) int pageNum, @NonNull PdfAnnotation annotation)279     public native int addPageAnnotation(@IntRange(from = 0) int pageNum,
280             @NonNull PdfAnnotation annotation);
281 
282     /**
283      * Removes the {@link PdfAnnotation} with the specified index from the given page.
284      *
285      * @param pageNum      - page number from which {@link PdfAnnotation} is to be removed
286      * @param annotationIndex - index of the {@link PdfAnnotation} to be removed
287      *
288      * @return true if remove was successful, false otherwise
289      */
removePageAnnotation(@ntRangefrom = 0) int pageNum, @IntRange(from = 0) int annotationIndex)290     public native boolean removePageAnnotation(@IntRange(from = 0) int pageNum,
291             @IntRange(from = 0) int annotationIndex);
292 
293     /**
294      * Update the given {@link PdfAnnotation} on the given page
295      *
296      * @param pageNum    page number on which annotation is to be updated
297      * @param annotationIndex index of the annotation
298      * @param annotation annotation to be updated
299      *
300      * @return true if page object is updated, false otherwise
301      */
updatePageAnnotation(@ntRangefrom = 0) int pageNum, int annotationIndex, PdfAnnotation annotation)302     public native boolean updatePageAnnotation(@IntRange(from = 0) int pageNum,
303             int annotationIndex, PdfAnnotation annotation);
304 
305 
306     /**
307      * Returns the list of {@link PdfPageObject} present on the page.
308      * The list item is non-null for supported types and
309      * null for unsupported types.
310      *
311      * @param pageNum - page number of the page whose annotations list is to be returned
312      * @return A {@link List} of {@link PdfPageObject}
313      */
getPageObjects(int pageNum)314     public native List<PdfPageObject> getPageObjects(int pageNum);
315 
316     /**
317      * Adds the given page object to the page.
318      *
319      * @param pageNum    - page number of the page to which pageObject is to be added
320      * @param pageObject - {@link PdfPageObject} to be added to the given page
321      * @return index of added page object, -1 in the case of failure
322      */
addPageObject(int pageNum, @NonNull PdfPageObject pageObject)323     public native int addPageObject(int pageNum, @NonNull PdfPageObject pageObject);
324 
325     /**
326      * Update the given {@link PdfPageObject} on the given page
327      *
328      * @param pageNum    page number on which the {@link PdfPageObject} is to be updated
329      * @param objectIndex   index of the pageObject
330      * @param pageObject pageObject to be updated
331      *
332      * @return true if page object is updated, false otherwise
333      */
updatePageObject(int pageNum, int objectIndex, @NonNull PdfPageObject pageObject)334     public native boolean updatePageObject(int pageNum, int objectIndex,
335             @NonNull PdfPageObject pageObject);
336 
337     /**
338      * Removes the {@link PdfPageObject} with the specified Index from the given page.
339      *
340      * @param pageNum  - page number from which {@link PdfPageObject} is to be removed
341      * @param objectIndex the index of the {@link PdfPageObject} to be removed
342      *
343      * @return true if remove was successful, false otherwise
344      */
removePageObject(int pageNum, int objectIndex)345     public native boolean removePageObject(int pageNum, int objectIndex);
346 }
347