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.content;
18 
19 import android.annotation.FlaggedApi;
20 import android.annotation.FloatRange;
21 import android.annotation.IntRange;
22 import android.annotation.NonNull;
23 import android.graphics.RectF;
24 import android.graphics.pdf.flags.Flags;
25 import android.graphics.pdf.utils.Preconditions;
26 import android.os.Parcel;
27 import android.os.Parcelable;
28 
29 import java.util.List;
30 
31 /**
32  * Represents the content associated with a goto link on a page in the PDF document. Goto Link is an
33  * internal navigation link which directs the user to a different location within the same pdf
34  * document
35  */
36 @FlaggedApi(Flags.FLAG_ENABLE_PDF_VIEWER)
37 public final class PdfPageGotoLinkContent implements Parcelable {
38     @NonNull
39     public static final Creator<PdfPageGotoLinkContent> CREATOR =
40             new Creator<>() {
41                 @Override
42                 public PdfPageGotoLinkContent createFromParcel(Parcel in) {
43                     return new PdfPageGotoLinkContent(in);
44                 }
45 
46                 @Override
47                 public PdfPageGotoLinkContent[] newArray(int size) {
48                     return new PdfPageGotoLinkContent[size];
49                 }
50             };
51     @NonNull
52     private final List<RectF> mBounds;
53     @NonNull
54     private final Destination mDestination;
55 
56     /**
57      * Creates a new instance of {@link PdfPageGotoLinkContent} using the bounds of the goto link
58      * and the destination where it is directing
59      *
60      * @param bounds      Bounds which envelop the goto link
61      * @param destination Destination where the goto link is directing
62      * @throws NullPointerException     If bounds or destination is null.
63      * @throws IllegalArgumentException If the bounds list is empty.
64      */
PdfPageGotoLinkContent(@onNull List<RectF> bounds, @NonNull Destination destination)65     public PdfPageGotoLinkContent(@NonNull List<RectF> bounds, @NonNull Destination
66             destination) {
67         Preconditions.checkNotNull(bounds, "Bounds cannot be null");
68         Preconditions.checkArgument(!bounds.isEmpty(), "Bounds cannot be empty");
69         Preconditions.checkNotNull(destination, "Destination cannot be null");
70         this.mBounds = bounds;
71         this.mDestination = destination;
72     }
73 
74 
PdfPageGotoLinkContent(Parcel in)75     private PdfPageGotoLinkContent(Parcel in) {
76         this.mBounds = in.createTypedArrayList(RectF.CREATOR);
77         this.mDestination = in.readParcelable(Destination.class.getClassLoader());
78     }
79 
80     /**
81      * Gets the bounds of a {@link PdfPageGotoLinkContent} represented as a list of {@link RectF}.
82      * Links which are spread across multiple lines will be surrounded by multiple {@link RectF}
83      * in order of viewing.
84      *
85      * <p><strong>Note:</strong> Each {@link RectF} represents a bound of the goto link in a single
86      * line and defines the coordinates of its 4 edges (left, top, right and bottom) in
87      * points (1/72"). The developer will need to render the highlighter as well as
88      * intercept the touch events for functionalities such as clicking the link.
89      *
90      * @return The bounds of the goto link.
91      */
92     @NonNull
getBounds()93     public List<RectF> getBounds() {
94         return mBounds;
95     }
96 
97     /**
98      * Gets the destination {@link Destination} of the {@link PdfPageGotoLinkContent}.
99      *
100      * @return Destination where goto link is directing the user.
101      */
102     @NonNull
getDestination()103     public Destination getDestination() {
104         return mDestination;
105     }
106 
107     @Override
describeContents()108     public int describeContents() {
109         return 0;
110     }
111 
112     @Override
writeToParcel(@ndroidx.annotation.NonNull Parcel dest, int flags)113     public void writeToParcel(@androidx.annotation.NonNull Parcel dest, int flags) {
114         dest.writeTypedList(mBounds);
115         dest.writeParcelable(mDestination, flags);
116     }
117 
118     /**
119      * Represents the content associated with the destination where a goto link is directing
120      */
121     public static final class Destination implements Parcelable {
122         @NonNull
123         public static final Creator<Destination> CREATOR = new Creator<Destination>() {
124             @Override
125             public Destination createFromParcel(Parcel in) {
126                 return new Destination(in);
127             }
128 
129             @Override
130             public Destination[] newArray(int size) {
131                 return new Destination[size];
132             }
133         };
134         private final int mPageNumber;
135         private final float mXCoordinate;
136         private final float mYCoordinate;
137         private final float mZoom;
138 
139 
140         /**
141          * Creates a new instance of {@link Destination} using the page number, x coordinate, and
142          * y coordinate of the destination where goto link is directing, and the zoom factor of the
143          * page when goto link takes to the destination
144          * <p><strong>Note:</strong> Here (0,0) represents top-left corner of the page
145          *
146          * @param pageNumber  Page number of the goto link Destination
147          * @param xCoordinate X coordinate of the goto link Destination in points (1/72")
148          * @param yCoordinate Y coordinate of the goto link Destination in points (1/72")
149          * @param zoom        Zoom factor {@link Destination#getZoom()} of the page when goto link
150          *                    takes to the destination
151          * @throws IllegalArgumentException If pageNumber or either of the coordinates or zoom are
152          *                                  less than zero
153          */
Destination(int pageNumber, float xCoordinate, float yCoordinate, float zoom)154         public Destination(int pageNumber, float xCoordinate, float yCoordinate, float zoom) {
155             Preconditions.checkArgument(pageNumber >= 0, "Page number must be"
156                     + " greater than or equal to 0");
157             Preconditions.checkArgument(xCoordinate >= 0, "X coordinate "
158                     + "must be greater than or equal to 0");
159             Preconditions.checkArgument(yCoordinate >= 0, "Y coordinate must "
160                     + "be greater than or equal to 0");
161             Preconditions.checkArgument(zoom >= 0, "Zoom factor number must be "
162                     + "greater than or equal to 0");
163             this.mPageNumber = pageNumber;
164             this.mXCoordinate = xCoordinate;
165             this.mYCoordinate = yCoordinate;
166             this.mZoom = zoom;
167         }
168 
Destination(Parcel in)169         private Destination(Parcel in) {
170             mPageNumber = in.readInt();
171             mXCoordinate = in.readFloat();
172             mYCoordinate = in.readFloat();
173             mZoom = in.readFloat();
174         }
175 
176         /**
177          * Gets the page number of the destination where the {@link PdfPageGotoLinkContent}
178          * is directing.
179          *
180          * @return page number of the destination where goto link is directing the user.
181          */
182         @IntRange(from = 0)
getPageNumber()183         public int getPageNumber() {
184             return mPageNumber;
185         }
186 
187 
188         /**
189          * Gets the x coordinate in points (1/72") of the destination where
190          * the {@link PdfPageGotoLinkContent} is directing.
191          * <p><strong>Note:</strong> If underlying pdfium library can't determine the x coordinate,
192          * it will be set to 0
193          *
194          * @return x coordinate of the Destination where the goto link is directing the user.
195          */
196         @FloatRange(from = 0.0f)
getXCoordinate()197         public float getXCoordinate() {
198             return mXCoordinate;
199         }
200 
201 
202         /**
203          * Gets the y coordinate in points (1/72") of the destination where
204          * the {@link PdfPageGotoLinkContent} is directing.
205          * <p><strong>Note:</strong> If underlying pdfium library can't determine the y coordinate,
206          * it will be set to 0
207          *
208          * @return y coordinate of the Destination where the goto link is directing the user.
209          */
210         @FloatRange(from = 0.0f)
getYCoordinate()211         public float getYCoordinate() {
212             return mYCoordinate;
213         }
214 
215 
216         /**
217          * Gets the zoom factor of the page when the goto link takes to the destination
218          * <p><strong>Note:</strong> If there is no zoom value embedded, default value of Zoom
219          * will be zero. Otherwise, it will be less than 1.0f in case of zoom out and greater
220          * than 1.0f in case of zoom in.
221          *
222          * @return zoom factor of the page when the goto link takes to the destination
223          */
224         @FloatRange(from = 0.0f)
getZoom()225         public float getZoom() {
226             return mZoom;
227         }
228 
229         @Override
describeContents()230         public int describeContents() {
231             return 0;
232         }
233 
234         @Override
writeToParcel(@ndroidx.annotation.NonNull Parcel dest, int flags)235         public void writeToParcel(@androidx.annotation.NonNull Parcel dest, int flags) {
236             dest.writeInt(mPageNumber);
237             dest.writeFloat(mXCoordinate);
238             dest.writeFloat(mYCoordinate);
239             dest.writeFloat(mZoom);
240         }
241     }
242 }
243