Add necessary APIs for supporting glyph level drawing
This CL adds following APIs
Font#cloneWithSettings
This API provides a faster Font instance creation for different
variation settings.
Font#getBounds
This API provides glyph advance and bounding box information.
Font#getMetrics
This API provides font metrics that will be used for deciding line
height and/or baseline.
Bug: 168136332
Test: atest FontTest
Test: TreeHugger
Change-Id: I335557ce47ea0ca8e012c2a48b804c00bb348392
diff --git a/api/current.txt b/api/current.txt
index c0dbdef..3cfd0d2 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -16390,7 +16390,9 @@
method @Nullable public android.graphics.fonts.FontVariationAxis[] getAxes();
method @NonNull public java.nio.ByteBuffer getBuffer();
method @Nullable public java.io.File getFile();
+ method public float getGlyphBounds(@IntRange(from=0) int, @NonNull android.graphics.Paint, @Nullable android.graphics.RectF);
method @NonNull public android.os.LocaleList getLocaleList();
+ method public void getMetrics(@NonNull android.graphics.Paint, @Nullable android.graphics.Paint.FontMetrics);
method @NonNull public android.graphics.fonts.FontStyle getStyle();
method @IntRange(from=0) public int getTtcIndex();
}
@@ -16402,6 +16404,7 @@
ctor public Font.Builder(@NonNull android.os.ParcelFileDescriptor, @IntRange(from=0) long, @IntRange(from=0xffffffff) long);
ctor public Font.Builder(@NonNull android.content.res.AssetManager, @NonNull String);
ctor public Font.Builder(@NonNull android.content.res.Resources, int);
+ ctor public Font.Builder(@NonNull android.graphics.fonts.Font);
method @NonNull public android.graphics.fonts.Font build() throws java.io.IOException;
method @NonNull public android.graphics.fonts.Font.Builder setFontVariationSettings(@Nullable String);
method @NonNull public android.graphics.fonts.Font.Builder setFontVariationSettings(@Nullable android.graphics.fonts.FontVariationAxis[]);
diff --git a/graphics/java/android/graphics/fonts/Font.java b/graphics/java/android/graphics/fonts/Font.java
index b09082e..cbae675 100644
--- a/graphics/java/android/graphics/fonts/Font.java
+++ b/graphics/java/android/graphics/fonts/Font.java
@@ -22,6 +22,8 @@
import android.content.res.AssetFileDescriptor;
import android.content.res.AssetManager;
import android.content.res.Resources;
+import android.graphics.Paint;
+import android.graphics.RectF;
import android.os.LocaleList;
import android.os.ParcelFileDescriptor;
import android.util.TypedValue;
@@ -29,6 +31,7 @@
import com.android.internal.util.Preconditions;
import dalvik.annotation.optimization.CriticalNative;
+import dalvik.annotation.optimization.FastNative;
import libcore.util.NativeAllocationRegistry;
@@ -63,6 +66,7 @@
private @Nullable ByteBuffer mBuffer;
private @Nullable File mFile;
+ private @Nullable Font mFont;
private @NonNull String mLocaleList = "";
private @IntRange(from = -1, to = 1000) int mWeight = NOT_SPECIFIED;
private @IntRange(from = -1, to = 1) int mItalic = NOT_SPECIFIED;
@@ -204,6 +208,22 @@
}
/**
+ * Constructs a builder from existing Font instance.
+ *
+ * @param font the font instance.
+ */
+ public Builder(@NonNull Font font) {
+ mFont = font;
+ // Copies all parameters as a default value.
+ mBuffer = font.getBuffer();
+ mWeight = font.getStyle().getWeight();
+ mItalic = font.getStyle().getSlant();
+ mAxes = font.getAxes();
+ mFile = font.getFile();
+ mTtcIndex = font.getTtcIndex();
+ }
+
+ /**
* Creates a buffer containing font data using the assetManager and other
* provided inputs.
*
@@ -430,8 +450,13 @@
}
final ByteBuffer readonlyBuffer = mBuffer.asReadOnlyBuffer();
final String filePath = mFile == null ? "" : mFile.getAbsolutePath();
- final long ptr = nBuild(builderPtr, readonlyBuffer, filePath, mWeight, italic,
- mTtcIndex);
+
+ long ptr;
+ if (mFont == null) {
+ ptr = nBuild(builderPtr, readonlyBuffer, filePath, mWeight, italic, mTtcIndex);
+ } else {
+ ptr = nClone(mFont.getNativePtr(), builderPtr, mWeight, italic, mTtcIndex);
+ }
final Font font = new Font(ptr, readonlyBuffer, mFile,
new FontStyle(mWeight, slant), mTtcIndex, mAxes, mLocaleList);
sFontRegistry.registerNativeAllocation(font, ptr);
@@ -449,6 +474,10 @@
boolean italic, int ttcIndex);
@CriticalNative
private static native long nGetReleaseNativeFont();
+
+ @FastNative
+ private static native long nClone(long fontPtr, long builderPtr, int weight,
+ boolean italic, int ttcIndex);
}
private final long mNativePtr; // address of the shared ptr of minikin::Font
@@ -538,6 +567,40 @@
return LocaleList.forLanguageTags(mLocaleList);
}
+ /**
+ * Retrieve the glyph horizontal advance and bounding box.
+ *
+ * Note that {@link android.graphics.Typeface} in {@link android.graphics.Paint} is ignored.
+ *
+ * @param glyphId a glyph ID
+ * @param paint a paint object used for resolving glyph style
+ * @param rect a nullable destination object. If null is passed, this function just return the
+ * horizontal advance. If non-null is passed, this function fills bounding box
+ * information to this object.
+ * @return the amount of horizontal advance in pixels
+ */
+ public float getGlyphBounds(@IntRange(from = 0) int glyphId, @NonNull Paint paint,
+ @Nullable RectF rect) {
+ return nGetGlyphBounds(mNativePtr, glyphId, paint.getNativeInstance(), rect);
+ }
+
+ /**
+ * Retrieve the font metrics information.
+ *
+ * Note that {@link android.graphics.Typeface} in {@link android.graphics.Paint} is ignored.
+ *
+ * @param paint a paint object used for retrieving font metrics.
+ * @param metrics a nullable destination object. If null is passed, this function only retrieve
+ * recommended interline spacing. If non-null is passed, this function fills to
+ * font metrics to it.
+ *
+ * @see Paint#getFontMetrics()
+ * @see Paint#getFontMetricsInt()
+ */
+ public void getMetrics(@NonNull Paint paint, @Nullable Paint.FontMetrics metrics) {
+ nGetFontMetrics(mNativePtr, paint.getNativeInstance(), metrics);
+ }
+
/** @hide */
public long getNativePtr() {
return mNativePtr;
@@ -573,4 +636,10 @@
+ ", buffer=" + mBuffer
+ "}";
}
+
+ @FastNative
+ private static native float nGetGlyphBounds(long font, int glyphId, long paint, RectF rect);
+
+ @FastNative
+ private static native float nGetFontMetrics(long font, long paint, Paint.FontMetrics metrics);
}
diff --git a/libs/hwui/jni/Graphics.cpp b/libs/hwui/jni/Graphics.cpp
index ecbb55ec..77f46be 100644
--- a/libs/hwui/jni/Graphics.cpp
+++ b/libs/hwui/jni/Graphics.cpp
@@ -9,6 +9,7 @@
#include "GraphicsJNI.h"
#include "SkCanvas.h"
+#include "SkFontMetrics.h"
#include "SkMath.h"
#include "SkRegion.h"
#include <cutils/ashmem.h>
@@ -228,6 +229,20 @@
static jclass gTransferParameters_class;
static jmethodID gTransferParameters_constructorMethodID;
+static jclass gFontMetrics_class;
+static jfieldID gFontMetrics_top;
+static jfieldID gFontMetrics_ascent;
+static jfieldID gFontMetrics_descent;
+static jfieldID gFontMetrics_bottom;
+static jfieldID gFontMetrics_leading;
+
+static jclass gFontMetricsInt_class;
+static jfieldID gFontMetricsInt_top;
+static jfieldID gFontMetricsInt_ascent;
+static jfieldID gFontMetricsInt_descent;
+static jfieldID gFontMetricsInt_bottom;
+static jfieldID gFontMetricsInt_leading;
+
///////////////////////////////////////////////////////////////////////////////
void GraphicsJNI::get_jrect(JNIEnv* env, jobject obj, int* L, int* T, int* R, int* B)
@@ -468,6 +483,32 @@
return r;
}
+void GraphicsJNI::set_metrics(JNIEnv* env, jobject metrics, const SkFontMetrics& skmetrics) {
+ if (metrics == nullptr) return;
+ SkASSERT(env->IsInstanceOf(metrics, gFontMetrics_class));
+ env->SetFloatField(metrics, gFontMetrics_top, SkScalarToFloat(skmetrics.fTop));
+ env->SetFloatField(metrics, gFontMetrics_ascent, SkScalarToFloat(skmetrics.fAscent));
+ env->SetFloatField(metrics, gFontMetrics_descent, SkScalarToFloat(skmetrics.fDescent));
+ env->SetFloatField(metrics, gFontMetrics_bottom, SkScalarToFloat(skmetrics.fBottom));
+ env->SetFloatField(metrics, gFontMetrics_leading, SkScalarToFloat(skmetrics.fLeading));
+}
+
+int GraphicsJNI::set_metrics_int(JNIEnv* env, jobject metrics, const SkFontMetrics& skmetrics) {
+ int ascent = SkScalarRoundToInt(skmetrics.fAscent);
+ int descent = SkScalarRoundToInt(skmetrics.fDescent);
+ int leading = SkScalarRoundToInt(skmetrics.fLeading);
+
+ if (metrics) {
+ SkASSERT(env->IsInstanceOf(metrics, gFontMetricsInt_class));
+ env->SetIntField(metrics, gFontMetricsInt_top, SkScalarFloorToInt(skmetrics.fTop));
+ env->SetIntField(metrics, gFontMetricsInt_ascent, ascent);
+ env->SetIntField(metrics, gFontMetricsInt_descent, descent);
+ env->SetIntField(metrics, gFontMetricsInt_bottom, SkScalarCeilToInt(skmetrics.fBottom));
+ env->SetIntField(metrics, gFontMetricsInt_leading, leading);
+ }
+ return descent - ascent + leading;
+}
+
///////////////////////////////////////////////////////////////////////////////////////////
jobject GraphicsJNI::createBitmapRegionDecoder(JNIEnv* env, skia::BitmapRegionDecoder* bitmap)
@@ -764,5 +805,23 @@
gTransferParameters_constructorMethodID = GetMethodIDOrDie(env, gTransferParameters_class,
"<init>", "(DDDDDDD)V");
+ gFontMetrics_class = FindClassOrDie(env, "android/graphics/Paint$FontMetrics");
+ gFontMetrics_class = MakeGlobalRefOrDie(env, gFontMetrics_class);
+
+ gFontMetrics_top = GetFieldIDOrDie(env, gFontMetrics_class, "top", "F");
+ gFontMetrics_ascent = GetFieldIDOrDie(env, gFontMetrics_class, "ascent", "F");
+ gFontMetrics_descent = GetFieldIDOrDie(env, gFontMetrics_class, "descent", "F");
+ gFontMetrics_bottom = GetFieldIDOrDie(env, gFontMetrics_class, "bottom", "F");
+ gFontMetrics_leading = GetFieldIDOrDie(env, gFontMetrics_class, "leading", "F");
+
+ gFontMetricsInt_class = FindClassOrDie(env, "android/graphics/Paint$FontMetricsInt");
+ gFontMetricsInt_class = MakeGlobalRefOrDie(env, gFontMetricsInt_class);
+
+ gFontMetricsInt_top = GetFieldIDOrDie(env, gFontMetricsInt_class, "top", "I");
+ gFontMetricsInt_ascent = GetFieldIDOrDie(env, gFontMetricsInt_class, "ascent", "I");
+ gFontMetricsInt_descent = GetFieldIDOrDie(env, gFontMetricsInt_class, "descent", "I");
+ gFontMetricsInt_bottom = GetFieldIDOrDie(env, gFontMetricsInt_class, "bottom", "I");
+ gFontMetricsInt_leading = GetFieldIDOrDie(env, gFontMetricsInt_class, "leading", "I");
+
return 0;
}
diff --git a/libs/hwui/jni/GraphicsJNI.h b/libs/hwui/jni/GraphicsJNI.h
index 79ab617..541d5a5 100644
--- a/libs/hwui/jni/GraphicsJNI.h
+++ b/libs/hwui/jni/GraphicsJNI.h
@@ -18,6 +18,7 @@
#include "graphics_jni_helpers.h"
class SkCanvas;
+struct SkFontMetrics;
namespace android {
namespace skia {
@@ -85,6 +86,17 @@
bool* isHardware);
static SkRegion* getNativeRegion(JNIEnv*, jobject region);
+ /**
+ * Set SkFontMetrics to Java Paint.FontMetrics.
+ * Do nothing if metrics is nullptr.
+ */
+ static void set_metrics(JNIEnv*, jobject metrics, const SkFontMetrics& skmetrics);
+ /**
+ * Set SkFontMetrics to Java Paint.FontMetricsInt and return recommended interline space.
+ * Do nothing if metrics is nullptr.
+ */
+ static int set_metrics_int(JNIEnv*, jobject metrics, const SkFontMetrics& skmetrics);
+
/*
* LegacyBitmapConfig is the old enum in Skia that matched the enum int values
* in Bitmap.Config. Skia no longer supports this config, but has replaced it
diff --git a/libs/hwui/jni/Paint.cpp b/libs/hwui/jni/Paint.cpp
index 554674a..d275659 100644
--- a/libs/hwui/jni/Paint.cpp
+++ b/libs/hwui/jni/Paint.cpp
@@ -59,20 +59,6 @@
namespace android {
-struct JMetricsID {
- jfieldID top;
- jfieldID ascent;
- jfieldID descent;
- jfieldID bottom;
- jfieldID leading;
-};
-
-static jclass gFontMetrics_class;
-static JMetricsID gFontMetrics_fieldID;
-
-static jclass gFontMetricsInt_class;
-static JMetricsID gFontMetricsInt_fieldID;
-
static void getPosTextPath(const SkFont& font, const uint16_t glyphs[], int count,
const SkPoint pos[], SkPath* dst) {
dst->reset();
@@ -618,35 +604,14 @@
static jfloat getFontMetrics(JNIEnv* env, jobject, jlong paintHandle, jobject metricsObj) {
SkFontMetrics metrics;
SkScalar spacing = getMetricsInternal(paintHandle, &metrics);
-
- if (metricsObj) {
- SkASSERT(env->IsInstanceOf(metricsObj, gFontMetrics_class));
- env->SetFloatField(metricsObj, gFontMetrics_fieldID.top, SkScalarToFloat(metrics.fTop));
- env->SetFloatField(metricsObj, gFontMetrics_fieldID.ascent, SkScalarToFloat(metrics.fAscent));
- env->SetFloatField(metricsObj, gFontMetrics_fieldID.descent, SkScalarToFloat(metrics.fDescent));
- env->SetFloatField(metricsObj, gFontMetrics_fieldID.bottom, SkScalarToFloat(metrics.fBottom));
- env->SetFloatField(metricsObj, gFontMetrics_fieldID.leading, SkScalarToFloat(metrics.fLeading));
- }
+ GraphicsJNI::set_metrics(env, metricsObj, metrics);
return SkScalarToFloat(spacing);
}
static jint getFontMetricsInt(JNIEnv* env, jobject, jlong paintHandle, jobject metricsObj) {
SkFontMetrics metrics;
-
getMetricsInternal(paintHandle, &metrics);
- int ascent = SkScalarRoundToInt(metrics.fAscent);
- int descent = SkScalarRoundToInt(metrics.fDescent);
- int leading = SkScalarRoundToInt(metrics.fLeading);
-
- if (metricsObj) {
- SkASSERT(env->IsInstanceOf(metricsObj, gFontMetricsInt_class));
- env->SetIntField(metricsObj, gFontMetricsInt_fieldID.top, SkScalarFloorToInt(metrics.fTop));
- env->SetIntField(metricsObj, gFontMetricsInt_fieldID.ascent, ascent);
- env->SetIntField(metricsObj, gFontMetricsInt_fieldID.descent, descent);
- env->SetIntField(metricsObj, gFontMetricsInt_fieldID.bottom, SkScalarCeilToInt(metrics.fBottom));
- env->SetIntField(metricsObj, gFontMetricsInt_fieldID.leading, leading);
- }
- return descent - ascent + leading;
+ return GraphicsJNI::set_metrics_int(env, metricsObj, metrics);
}
@@ -1137,24 +1102,6 @@
};
int register_android_graphics_Paint(JNIEnv* env) {
- gFontMetrics_class = FindClassOrDie(env, "android/graphics/Paint$FontMetrics");
- gFontMetrics_class = MakeGlobalRefOrDie(env, gFontMetrics_class);
-
- gFontMetrics_fieldID.top = GetFieldIDOrDie(env, gFontMetrics_class, "top", "F");
- gFontMetrics_fieldID.ascent = GetFieldIDOrDie(env, gFontMetrics_class, "ascent", "F");
- gFontMetrics_fieldID.descent = GetFieldIDOrDie(env, gFontMetrics_class, "descent", "F");
- gFontMetrics_fieldID.bottom = GetFieldIDOrDie(env, gFontMetrics_class, "bottom", "F");
- gFontMetrics_fieldID.leading = GetFieldIDOrDie(env, gFontMetrics_class, "leading", "F");
-
- gFontMetricsInt_class = FindClassOrDie(env, "android/graphics/Paint$FontMetricsInt");
- gFontMetricsInt_class = MakeGlobalRefOrDie(env, gFontMetricsInt_class);
-
- gFontMetricsInt_fieldID.top = GetFieldIDOrDie(env, gFontMetricsInt_class, "top", "I");
- gFontMetricsInt_fieldID.ascent = GetFieldIDOrDie(env, gFontMetricsInt_class, "ascent", "I");
- gFontMetricsInt_fieldID.descent = GetFieldIDOrDie(env, gFontMetricsInt_class, "descent", "I");
- gFontMetricsInt_fieldID.bottom = GetFieldIDOrDie(env, gFontMetricsInt_class, "bottom", "I");
- gFontMetricsInt_fieldID.leading = GetFieldIDOrDie(env, gFontMetricsInt_class, "leading", "I");
-
return RegisterMethodsOrDie(env, "android/graphics/Paint", methods, NELEM(methods));
}
diff --git a/libs/hwui/jni/fonts/Font.cpp b/libs/hwui/jni/fonts/Font.cpp
index 996cdce..bcdb4f5 100644
--- a/libs/hwui/jni/fonts/Font.cpp
+++ b/libs/hwui/jni/fonts/Font.cpp
@@ -18,6 +18,8 @@
#define LOG_TAG "Minikin"
#include "SkData.h"
+#include "SkFont.h"
+#include "SkFontMetrics.h"
#include "SkFontMgr.h"
#include "SkRefCnt.h"
#include "SkTypeface.h"
@@ -27,6 +29,7 @@
#include "FontUtils.h"
#include <hwui/MinikinSkia.h>
+#include <hwui/Paint.h>
#include <hwui/Typeface.h>
#include <minikin/FontFamily.h>
#include <ui/FatVector.h>
@@ -120,6 +123,36 @@
return reinterpret_cast<jlong>(new FontWrapper(std::move(font)));
}
+// Fast Native
+static jlong Font_Builder_clone(JNIEnv* env, jobject clazz, jlong fontPtr, jlong builderPtr,
+ jint weight, jboolean italic, jint ttcIndex) {
+ FontWrapper* font = reinterpret_cast<FontWrapper*>(fontPtr);
+ MinikinFontSkia* minikinSkia = static_cast<MinikinFontSkia*>(font->font.typeface().get());
+ std::unique_ptr<NativeFontBuilder> builder(toBuilder(builderPtr));
+
+ // Reconstruct SkTypeface with different arguments from existing SkTypeface.
+ FatVector<SkFontArguments::VariationPosition::Coordinate, 2> skVariation;
+ for (const auto& axis : builder->axes) {
+ skVariation.push_back({axis.axisTag, axis.value});
+ }
+ SkFontArguments args;
+ args.setCollectionIndex(ttcIndex);
+ args.setVariationDesignPosition({skVariation.data(), static_cast<int>(skVariation.size())});
+
+ sk_sp<SkTypeface> newTypeface = minikinSkia->GetSkTypeface()->makeClone(args);
+
+ std::shared_ptr<minikin::MinikinFont> newMinikinFont = std::make_shared<MinikinFontSkia>(
+ std::move(newTypeface),
+ minikinSkia->GetFontData(),
+ minikinSkia->GetFontSize(),
+ minikinSkia->getFilePath(),
+ minikinSkia->GetFontIndex(),
+ builder->axes);
+ minikin::Font newFont = minikin::Font::Builder(newMinikinFont).setWeight(weight)
+ .setSlant(static_cast<minikin::FontStyle::Slant>(italic)).build();
+ return reinterpret_cast<jlong>(new FontWrapper(std::move(newFont)));
+}
+
// Critical Native
static jlong Font_Builder_getReleaseNativeFont(CRITICAL_JNI_PARAMS) {
return reinterpret_cast<jlong>(releaseFont);
@@ -127,16 +160,64 @@
///////////////////////////////////////////////////////////////////////////////
+// Fast Native
+static jfloat Font_getGlyphBounds(JNIEnv* env, jobject, jlong fontHandle, jint glyphId,
+ jlong paintHandle, jobject rect) {
+ FontWrapper* font = reinterpret_cast<FontWrapper*>(fontHandle);
+ MinikinFontSkia* minikinSkia = static_cast<MinikinFontSkia*>(font->font.typeface().get());
+ Paint* paint = reinterpret_cast<Paint*>(paintHandle);
+
+ SkFont* skFont = &paint->getSkFont();
+ // We don't use populateSkFont since it is designed to be used for layout result with addressing
+ // auto fake-bolding.
+ skFont->setTypeface(minikinSkia->RefSkTypeface());
+
+ uint16_t glyph16 = glyphId;
+ SkRect skBounds;
+ SkScalar skWidth;
+ skFont->getWidthsBounds(&glyph16, 1, &skWidth, &skBounds, nullptr);
+ GraphicsJNI::rect_to_jrectf(skBounds, env, rect);
+ return SkScalarToFloat(skWidth);
+}
+
+// Fast Native
+static jfloat Font_getFontMetrics(JNIEnv* env, jobject, jlong fontHandle, jlong paintHandle,
+ jobject metricsObj) {
+ FontWrapper* font = reinterpret_cast<FontWrapper*>(fontHandle);
+ MinikinFontSkia* minikinSkia = static_cast<MinikinFontSkia*>(font->font.typeface().get());
+ Paint* paint = reinterpret_cast<Paint*>(paintHandle);
+
+ SkFont* skFont = &paint->getSkFont();
+ // We don't use populateSkFont since it is designed to be used for layout result with addressing
+ // auto fake-bolding.
+ skFont->setTypeface(minikinSkia->RefSkTypeface());
+
+ SkFontMetrics metrics;
+ SkScalar spacing = skFont->getMetrics(&metrics);
+ GraphicsJNI::set_metrics(env, metricsObj, metrics);
+ return spacing;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
static const JNINativeMethod gFontBuilderMethods[] = {
{ "nInitBuilder", "()J", (void*) Font_Builder_initBuilder },
{ "nAddAxis", "(JIF)V", (void*) Font_Builder_addAxis },
{ "nBuild", "(JLjava/nio/ByteBuffer;Ljava/lang/String;IZI)J", (void*) Font_Builder_build },
+ { "nClone", "(JJIZI)J", (void*) Font_Builder_clone },
{ "nGetReleaseNativeFont", "()J", (void*) Font_Builder_getReleaseNativeFont },
};
+static const JNINativeMethod gFontMethods[] = {
+ { "nGetGlyphBounds", "(JIJLandroid/graphics/RectF;)F", (void*) Font_getGlyphBounds },
+ { "nGetFontMetrics", "(JJLandroid/graphics/Paint$FontMetrics;)F", (void*) Font_getFontMetrics },
+};
+
int register_android_graphics_fonts_Font(JNIEnv* env) {
return RegisterMethodsOrDie(env, "android/graphics/fonts/Font$Builder", gFontBuilderMethods,
- NELEM(gFontBuilderMethods));
+ NELEM(gFontBuilderMethods)) +
+ RegisterMethodsOrDie(env, "android/graphics/fonts/Font", gFontMethods,
+ NELEM(gFontMethods));
}
}
diff --git a/non-updatable-api/current.txt b/non-updatable-api/current.txt
index 2d5d48f..bc6a505 100644
--- a/non-updatable-api/current.txt
+++ b/non-updatable-api/current.txt
@@ -16372,7 +16372,9 @@
method @Nullable public android.graphics.fonts.FontVariationAxis[] getAxes();
method @NonNull public java.nio.ByteBuffer getBuffer();
method @Nullable public java.io.File getFile();
+ method public float getGlyphBounds(@IntRange(from=0) int, @NonNull android.graphics.Paint, @Nullable android.graphics.RectF);
method @NonNull public android.os.LocaleList getLocaleList();
+ method public void getMetrics(@NonNull android.graphics.Paint, @Nullable android.graphics.Paint.FontMetrics);
method @NonNull public android.graphics.fonts.FontStyle getStyle();
method @IntRange(from=0) public int getTtcIndex();
}
@@ -16384,6 +16386,7 @@
ctor public Font.Builder(@NonNull android.os.ParcelFileDescriptor, @IntRange(from=0) long, @IntRange(from=0xffffffff) long);
ctor public Font.Builder(@NonNull android.content.res.AssetManager, @NonNull String);
ctor public Font.Builder(@NonNull android.content.res.Resources, int);
+ ctor public Font.Builder(@NonNull android.graphics.fonts.Font);
method @NonNull public android.graphics.fonts.Font build() throws java.io.IOException;
method @NonNull public android.graphics.fonts.Font.Builder setFontVariationSettings(@Nullable String);
method @NonNull public android.graphics.fonts.Font.Builder setFontVariationSettings(@Nullable android.graphics.fonts.FontVariationAxis[]);