1 /* 2 * Copyright (C) 2021 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.fonts; 18 19 import android.annotation.IntRange; 20 import android.annotation.NonNull; 21 import android.annotation.SystemApi; 22 23 import com.android.internal.util.Preconditions; 24 25 import java.util.ArrayList; 26 import java.util.Collections; 27 import java.util.List; 28 import java.util.Objects; 29 30 /** 31 * Request for updating or adding a font family on the system. 32 * 33 * <p>You can update or add a font family with custom style parameters. The following example 34 * defines a font family called "roboto" using "Roboto-Regular" font file that is already available 35 * on the system by preloading or {@link FontManager#updateFontFile}. 36 * <pre> 37 * FontManager fm = getContext().getSystemService(FontManager.class); 38 * fm.updateFontFamily(new FontFamilyUpdateRequest.Builder() 39 * .addFontFamily(new FontFamilyUpdateRequest.FontFamily("roboto", Arrays.asList( 40 * new FontFamilyUpdateRequest.Font( 41 * "Roboto-Regular", 42 * new FontStyle(FONT_WEIGHT_NORMAL, FONT_SLANT_UPRIGHT), 43 * Collections.emptyList()), 44 * new FontFamilyUpdateRequest.Font( 45 * "Roboto-Regular", 46 * new FontStyle(FONT_WEIGHT_NORMAL, FONT_SLANT_ITALIC), 47 * Collections.emptyList())))) 48 * .build(), fm.getFontConfig().getConfigVersion()); 49 * </pre> 50 * 51 * <p>You can update or add font files in the same request by calling 52 * {@link FontFamilyUpdateRequest.Builder#addFontFileUpdateRequest(FontFileUpdateRequest)}. 53 * The following example adds "YourFont" font file and defines "your-font" font family in the same 54 * request. In this case, the font file represented by {@code yourFontFd} should be an OpenType 55 * compliant font file and have "YourFont" as PostScript name (ID=6) in 'name' table. 56 * <pre> 57 * FontManager fm = getContext().getSystemService(FontManager.class); 58 * fm.updateFontFamily(new FontFamilyUpdateRequest.Builder() 59 * .addFontFileUpdateRequest(new FontFileUpdateRequest(yourFontFd, signature)) 60 * .addFontFamily(new FontFamilyUpdateRequest.FontFamily("your-font", Arrays.asList( 61 * new FontFamilyUpdateRequest.Font( 62 * "YourFont", 63 * new FontStyle(FONT_WEIGHT_NORMAL, FONT_SLANT_UPRIGHT), 64 * Collections.emptyList())))) 65 * .build(), fm.getFontConfig().getConfigVersion()); 66 * </pre> 67 * 68 * @hide 69 */ 70 @SystemApi 71 @android.ravenwood.annotation.RavenwoodKeepWholeClass 72 public final class FontFamilyUpdateRequest { 73 74 /** 75 * A font family definition. 76 */ 77 public static final class FontFamily { 78 79 /** 80 * Builds a {@link FontFamily}. 81 */ 82 public static final class Builder { 83 @NonNull private final String mName; 84 @NonNull private final List<Font> mFonts; 85 86 /** 87 * Constructs a {@link FontFamily.Builder}. 88 */ Builder(@onNull String name, @NonNull List<Font> fonts)89 public Builder(@NonNull String name, @NonNull List<Font> fonts) { 90 Objects.requireNonNull(name); 91 Preconditions.checkStringNotEmpty(name); 92 Objects.requireNonNull(fonts); 93 Preconditions.checkCollectionElementsNotNull(fonts, "fonts"); 94 Preconditions.checkCollectionNotEmpty(fonts, "fonts"); 95 mName = name; 96 mFonts = new ArrayList<>(fonts); 97 } 98 99 /** 100 * Adds a {@link Font} to the builder. 101 * 102 * @return This builder object. 103 */ addFont(@onNull Font font)104 public @NonNull Builder addFont(@NonNull Font font) { 105 mFonts.add(font); 106 return this; 107 } 108 109 /** 110 * Builds a {@link FontFamily}. 111 */ build()112 public @NonNull FontFamily build() { 113 return new FontFamily(mName, mFonts); 114 } 115 } 116 117 @NonNull 118 private final String mName; 119 @NonNull 120 private final List<Font> mFonts; 121 122 /** 123 * Constructs a FontFamily. 124 * 125 * <p>A font family has a name to identify the font family. Apps can use 126 * {@link android.graphics.Typeface#create(String, int)} or XML resources to use a specific 127 * font family. 128 * 129 * <p>A font family consists of multiple fonts with different styles. The style information 130 * can be specified by {@link Font}. 131 * 132 * @see android.graphics.Typeface#create(String, int) 133 * @see Font 134 */ FontFamily(@onNull String name, @NonNull List<Font> fonts)135 private FontFamily(@NonNull String name, @NonNull List<Font> fonts) { 136 mName = name; 137 mFonts = fonts; 138 } 139 140 /** 141 * Returns the name of this family. 142 */ 143 @NonNull getName()144 public String getName() { 145 return mName; 146 } 147 148 /** 149 * Returns the fonts in this family. 150 */ 151 @NonNull getFonts()152 public List<Font> getFonts() { 153 return mFonts; 154 } 155 } 156 157 /** 158 * A single entry in a font family representing a font. 159 */ 160 public static final class Font { 161 162 /** 163 * Builds a {@link Font}. 164 */ 165 public static final class Builder { 166 private final@NonNull String mPostScriptName; 167 private final @NonNull FontStyle mStyle; 168 private @NonNull List<FontVariationAxis> mAxes = Collections.emptyList(); 169 private @IntRange(from = 0) int mIndex = 0; 170 171 /** 172 * Construct a {@link Font.Builder} 173 * 174 * @param postScriptName The PostScript name of the font file to use. PostScript name is 175 * in Name ID 6 field in 'name' table, as specified by OpenType 176 * specification. 177 * @param style The style for this font. 178 */ Builder(@onNull String postScriptName, @NonNull FontStyle style)179 public Builder(@NonNull String postScriptName, @NonNull FontStyle style) { 180 Objects.requireNonNull(postScriptName); 181 Preconditions.checkStringNotEmpty(postScriptName); 182 Objects.requireNonNull(style); 183 mPostScriptName = postScriptName; 184 mStyle = style; 185 } 186 187 /** 188 * A list of {@link FontVariationAxis} to specify axis tags and values for variable 189 * fonts. 190 */ setAxes(@onNull List<FontVariationAxis> axes)191 public @NonNull Builder setAxes(@NonNull List<FontVariationAxis> axes) { 192 Objects.requireNonNull(axes); 193 Preconditions.checkCollectionElementsNotNull(axes, "axes"); 194 mAxes = axes; 195 return this; 196 } 197 198 /** 199 * Sets font collection index for the Font. 200 * 201 * @see {@link android.R.attr#ttcIndex}. 202 */ setIndex(@ntRangefrom = 0) int index)203 public @NonNull Builder setIndex(@IntRange(from = 0) int index) { 204 Preconditions.checkArgumentNonnegative(index); 205 mIndex = index; 206 return this; 207 } 208 209 /** 210 * Build a {@link Font} instance. 211 */ build()212 public @NonNull Font build() { 213 return new Font(mPostScriptName, mStyle, mIndex, mAxes); 214 } 215 } 216 217 @NonNull 218 private final String mPostScriptName; 219 @NonNull 220 private final FontStyle mStyle; 221 @NonNull 222 private final List<FontVariationAxis> mAxes; 223 224 private final @IntRange(from = 0) int mIndex; 225 226 /** 227 * Constructs a FontStyleVariation. 228 * 229 * <p>A font has a PostScript name to identify the font file to use, a {@link FontStyle} 230 * to specify the style, and a list of {@link FontVariationAxis} to specify axis tags and 231 * values for variable fonts. If the font file identified by {@code postScriptName} is not a 232 * variable font, {@code axes} must be empty. 233 * 234 * @param postScriptName The PostScript name of the font file to use. PostScript name is in 235 * Name ID 6 field in 'name' table, as specified by OpenType 236 * specification. 237 * @param style The style for this font. 238 * @param index The index of the font in the collection. 239 * @param axes A list of {@link FontVariationAxis} to specify axis tags and values 240 * for variable fonts. 241 */ Font(@onNull String postScriptName, @NonNull FontStyle style, @IntRange(from = 0) int index, @NonNull List<FontVariationAxis> axes)242 private Font(@NonNull String postScriptName, @NonNull FontStyle style, 243 @IntRange(from = 0) int index, @NonNull List<FontVariationAxis> axes) { 244 mPostScriptName = postScriptName; 245 mStyle = style; 246 mIndex = index; 247 mAxes = axes; 248 } 249 250 /** 251 * Returns PostScript name of the font file to use. 252 */ 253 @NonNull getPostScriptName()254 public String getPostScriptName() { 255 return mPostScriptName; 256 } 257 258 /** 259 * Returns the style. 260 */ 261 @NonNull getStyle()262 public FontStyle getStyle() { 263 return mStyle; 264 } 265 266 267 /** 268 * Returns the list of {@link FontVariationAxis}. 269 */ 270 @NonNull getAxes()271 public List<FontVariationAxis> getAxes() { 272 return mAxes; 273 } 274 275 /** 276 * Returns the index of collection 277 */ getIndex()278 public @IntRange(from = 0) int getIndex() { 279 return mIndex; 280 } 281 } 282 283 /** 284 * Builds a {@link FontFamilyUpdateRequest}. 285 */ 286 public static final class Builder { 287 @NonNull 288 private final List<FontFileUpdateRequest> mFontFileUpdateRequests = new ArrayList<>(); 289 @NonNull 290 private final List<FontFamily> mFontFamilies = new ArrayList<>(); 291 292 /** 293 * Constructs a FontFamilyUpdateRequest.Builder. 294 */ Builder()295 public Builder() { 296 } 297 298 /** 299 * Adds a {@link FontFileUpdateRequest} to execute as a part of the constructed 300 * {@link FontFamilyUpdateRequest}. 301 * 302 * @param request A font file update request. 303 * @return This builder object. 304 */ 305 @NonNull addFontFileUpdateRequest(@onNull FontFileUpdateRequest request)306 public Builder addFontFileUpdateRequest(@NonNull FontFileUpdateRequest request) { 307 Objects.requireNonNull(request); 308 mFontFileUpdateRequests.add(request); 309 return this; 310 } 311 312 /** 313 * Adds a font family to update an existing font family in the system font config or 314 * add as a new font family to the system font config. 315 * 316 * @param fontFamily An font family definition to add or update. 317 * @return This builder object. 318 */ 319 @NonNull addFontFamily(@onNull FontFamily fontFamily)320 public Builder addFontFamily(@NonNull FontFamily fontFamily) { 321 Objects.requireNonNull(fontFamily); 322 mFontFamilies.add(fontFamily); 323 return this; 324 } 325 326 /** 327 * Builds a {@link FontFamilyUpdateRequest}. 328 */ 329 @NonNull build()330 public FontFamilyUpdateRequest build() { 331 return new FontFamilyUpdateRequest(mFontFileUpdateRequests, mFontFamilies); 332 } 333 } 334 335 @NonNull 336 private final List<FontFileUpdateRequest> mFontFiles; 337 338 @NonNull 339 private final List<FontFamily> mFontFamilies; 340 FontFamilyUpdateRequest(@onNull List<FontFileUpdateRequest> fontFiles, @NonNull List<FontFamily> fontFamilies)341 private FontFamilyUpdateRequest(@NonNull List<FontFileUpdateRequest> fontFiles, 342 @NonNull List<FontFamily> fontFamilies) { 343 mFontFiles = fontFiles; 344 mFontFamilies = fontFamilies; 345 } 346 347 /** 348 * Returns the list of {@link FontFileUpdateRequest} that will be executed as a part of this 349 * request. 350 */ 351 @NonNull getFontFileUpdateRequests()352 public List<FontFileUpdateRequest> getFontFileUpdateRequests() { 353 return mFontFiles; 354 } 355 356 /** 357 * Returns the list of {@link FontFamily} that will be updated in this request. 358 */ 359 @NonNull getFontFamilies()360 public List<FontFamily> getFontFamilies() { 361 return mFontFamilies; 362 } 363 } 364