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