Loading core/api/current.txt +6 −0 Original line number Diff line number Diff line Loading @@ -17442,6 +17442,7 @@ package android.graphics.fonts { ctor public FontFamily.Builder(@NonNull android.graphics.fonts.Font); method @NonNull public android.graphics.fonts.FontFamily.Builder addFont(@NonNull android.graphics.fonts.Font); method @NonNull public android.graphics.fonts.FontFamily build(); method @Nullable public android.graphics.fonts.FontFamily buildVariableFamily(); } public final class FontStyle { Loading Loading @@ -17622,13 +17623,18 @@ package android.graphics.text { method public float getAdvance(); method public float getAscent(); method public float getDescent(); method public boolean getFakeBold(@IntRange(from=0) int); method public boolean getFakeItalic(@IntRange(from=0) int); method @NonNull public android.graphics.fonts.Font getFont(@IntRange(from=0) int); method @IntRange(from=0) public int getGlyphId(@IntRange(from=0) int); method public float getGlyphX(@IntRange(from=0) int); method public float getGlyphY(@IntRange(from=0) int); method public float getItalicOverride(@IntRange(from=0) int); method public float getOffsetX(); method public float getOffsetY(); method public float getWeightOverride(@IntRange(from=0) int); method @IntRange(from=0) public int glyphCount(); field public static final float NO_OVERRIDE = 1.4E-45f; } public class TextRunShaper { graphics/java/android/graphics/fonts/FontFamily.java +131 −5 Original line number Diff line number Diff line Loading @@ -30,6 +30,7 @@ import dalvik.annotation.optimization.FastNative; import libcore.util.NativeAllocationRegistry; import java.util.ArrayList; import java.util.Set; /** * A font family class can be used for creating Typeface. Loading Loading @@ -58,6 +59,7 @@ import java.util.ArrayList; * */ public final class FontFamily { private static final String TAG = "FontFamily"; /** Loading @@ -73,6 +75,7 @@ public final class FontFamily { // initial capacity. private final SparseIntArray mStyles = new SparseIntArray(4); /** * Constructs a builder. * Loading Loading @@ -109,24 +112,64 @@ public final class FontFamily { return this; } /** * Build a variable font family that automatically adjust the `wght` and `ital` axes value * for the requested weight/italic style values. * * To build a variable font family, added fonts must meet one of following conditions. * * If two font files are added, both font files must support `wght` axis and one font must * support {@link FontStyle#FONT_SLANT_UPRIGHT} and another font must support * {@link FontStyle#FONT_SLANT_ITALIC}. If the requested weight value is lower than minimum * value of the supported `wght` axis, the minimum supported `wght` value is used. If the * requested weight value is larger than maximum value of the supported `wght` axis, the * maximum supported `wght` value is used. The weight values of the fonts are ignored. * * If one font file is added, that font must support the `wght` axis. If that font support * `ital` axis, that `ital` value is set to 1 when the italic style is requested. If that * font doesn't support `ital` axis, synthetic italic may be used. If the requested * weight value is lower than minimum value of the supported `wght` axis, the minimum * supported `wght` value is used. If the requested weight value is larger than maximum * value of the supported `wght`axis, the maximum supported `wght` value is used. The weight * value of the font is ignored. * * If none of the above conditions are met, this function return {@code null}. * * @return A variable font family. null if a variable font cannot be built from the given * fonts. */ public @Nullable FontFamily buildVariableFamily() { int variableFamilyType = analyzeAndResolveVariableType(mFonts); if (variableFamilyType == VARIABLE_FONT_FAMILY_TYPE_UNKNOWN) { return null; } return build("", FontConfig.FontFamily.VARIANT_DEFAULT, true /* isCustomFallback */, false /* isDefaultFallback */, variableFamilyType); } /** * Build the font family * @return a font family */ public @NonNull FontFamily build() { return build("", FontConfig.FontFamily.VARIANT_DEFAULT, true /* isCustomFallback */, false /* isDefaultFallback */); return build("", FontConfig.FontFamily.VARIANT_DEFAULT, true /* isCustomFallback */, false /* isDefaultFallback */, VARIABLE_FONT_FAMILY_TYPE_NONE); } /** @hide */ public @NonNull FontFamily build(@NonNull String langTags, int variant, boolean isCustomFallback, boolean isDefaultFallback) { boolean isCustomFallback, boolean isDefaultFallback, int variableFamilyType) { final long builderPtr = nInitBuilder(); for (int i = 0; i < mFonts.size(); ++i) { nAddFont(builderPtr, mFonts.get(i).getNativePtr()); } final long ptr = nBuild(builderPtr, langTags, variant, isCustomFallback, isDefaultFallback); isDefaultFallback, variableFamilyType); final FontFamily family = new FontFamily(ptr); sFamilyRegistory.registerNativeAllocation(family, ptr); return family; Loading @@ -136,11 +179,94 @@ public final class FontFamily { return font.getStyle().getWeight() | (font.getStyle().getSlant() << 16); } /** * @see #buildVariableFamily() * @hide */ public static final int VARIABLE_FONT_FAMILY_TYPE_UNKNOWN = -1; /** * @see #buildVariableFamily() * @hide */ public static final int VARIABLE_FONT_FAMILY_TYPE_NONE = 0; /** * @see #buildVariableFamily() * @hide */ public static final int VARIABLE_FONT_FAMILY_TYPE_SINGLE_FONT_WGHT_ONLY = 1; /** * @see #buildVariableFamily() * @hide */ public static final int VARIABLE_FONT_FAMILY_TYPE_SINGLE_FONT_WGHT_ITAL = 2; /** * @see #buildVariableFamily() * @hide */ public static final int VARIABLE_FONT_FAMILY_TYPE_TWO_FONTS_WGHT = 3; /** * The registered italic axis used for adjusting requested style. * https://learn.microsoft.com/en-us/typography/opentype/spec/dvaraxistag_ital */ private static final int TAG_ital = 0x6974616C; // i(0x69), t(0x74), a(0x61), l(0x6c) /** * The registered weight axis used for adjusting requested style. * https://learn.microsoft.com/en-us/typography/opentype/spec/dvaraxistag_wght */ private static final int TAG_wght = 0x77676874; // w(0x77), g(0x67), h(0x68), t(0x74) private static int analyzeAndResolveVariableType(ArrayList<Font> fonts) { if (fonts.size() > 2) { return VARIABLE_FONT_FAMILY_TYPE_UNKNOWN; } if (fonts.size() == 1) { Font font = fonts.get(0); Set<Integer> supportedAxes = FontFileUtil.getSupportedAxes(font.getBuffer(), font.getTtcIndex()); if (supportedAxes.contains(TAG_wght)) { if (supportedAxes.contains(TAG_ital)) { return VARIABLE_FONT_FAMILY_TYPE_SINGLE_FONT_WGHT_ITAL; } else { return VARIABLE_FONT_FAMILY_TYPE_SINGLE_FONT_WGHT_ONLY; } } else { return VARIABLE_FONT_FAMILY_TYPE_UNKNOWN; } } else { for (int i = 0; i < fonts.size(); ++i) { Font font = fonts.get(i); Set<Integer> supportedAxes = FontFileUtil.getSupportedAxes(font.getBuffer(), font.getTtcIndex()); if (!supportedAxes.contains(TAG_wght)) { return VARIABLE_FONT_FAMILY_TYPE_UNKNOWN; } } boolean italic1 = fonts.get(0).getStyle().getSlant() == FontStyle.FONT_SLANT_ITALIC; boolean italic2 = fonts.get(1).getStyle().getSlant() == FontStyle.FONT_SLANT_ITALIC; if (italic1 == italic2) { return VARIABLE_FONT_FAMILY_TYPE_UNKNOWN; } else { if (italic1) { // Swap fonts to make the first font upright, second font italic. Font firstFont = fonts.get(0); fonts.set(0, fonts.get(1)); fonts.set(1, firstFont); } return VARIABLE_FONT_FAMILY_TYPE_TWO_FONTS_WGHT; } } } private static native long nInitBuilder(); @CriticalNative private static native void nAddFont(long builderPtr, long fontPtr); private static native long nBuild(long builderPtr, String langTags, int variant, boolean isCustomFallback, boolean isDefaultFallback); boolean isCustomFallback, boolean isDefaultFallback, int variableFamilyType); @CriticalNative private static native long nGetReleaseNativeFamily(); } Loading graphics/java/android/graphics/fonts/FontFileUtil.java +71 −0 Original line number Diff line number Diff line Loading @@ -19,11 +19,14 @@ package android.graphics.fonts; import android.annotation.IntRange; import android.annotation.NonNull; import android.annotation.Nullable; import android.util.ArraySet; import dalvik.annotation.optimization.FastNative; import java.nio.ByteBuffer; import java.nio.ByteOrder; import java.util.Collections; import java.util.Set; /** * Provides a utility for font file operations. Loading Loading @@ -62,6 +65,7 @@ public class FontFileUtil { private static final int SFNT_VERSION_OTTO = 0x4F54544F; private static final int TTC_TAG = 0x74746366; private static final int OS2_TABLE_TAG = 0x4F532F32; private static final int FVAR_TABLE_TAG = 0x66766172; private static final int ANALYZE_ERROR = 0xFFFFFFFF; Loading Loading @@ -200,6 +204,73 @@ public class FontFileUtil { } } private static int getUInt16(ByteBuffer buffer, int offset) { return ((int) buffer.getShort(offset)) & 0xFFFF; } /** * Returns supported axes of font * * @param buffer A buffer of the entire font file. * @param index A font index in case of font collection. Must be 0 otherwise. * @return set of supported axes tag. Returns empty set on error. */ public static Set<Integer> getSupportedAxes(@NonNull ByteBuffer buffer, int index) { ByteOrder originalOrder = buffer.order(); buffer.order(ByteOrder.BIG_ENDIAN); try { int fontFileOffset = 0; int magicNumber = buffer.getInt(0); if (magicNumber == TTC_TAG) { // TTC file. if (index >= buffer.getInt(8 /* offset to number of fonts in TTC */)) { return Collections.EMPTY_SET; } fontFileOffset = buffer.getInt( 12 /* offset to array of offsets of font files */ + 4 * index); } int sfntVersion = buffer.getInt(fontFileOffset); if (sfntVersion != SFNT_VERSION_1 && sfntVersion != SFNT_VERSION_OTTO) { return Collections.EMPTY_SET; } int numTables = buffer.getShort(fontFileOffset + 4 /* offset to number of tables */); int fvarTableOffset = -1; for (int i = 0; i < numTables; ++i) { int tableOffset = fontFileOffset + 12 /* size of offset table */ + i * 16 /* size of table record */; if (buffer.getInt(tableOffset) == FVAR_TABLE_TAG) { fvarTableOffset = buffer.getInt(tableOffset + 8 /* offset to the table */); break; } } if (fvarTableOffset == -1) { // Couldn't find OS/2 table. use regular style return Collections.EMPTY_SET; } if (buffer.getShort(fvarTableOffset) != 1 || buffer.getShort(fvarTableOffset + 2) != 0) { return Collections.EMPTY_SET; } int axesArrayOffset = getUInt16(buffer, fvarTableOffset + 4); int axisCount = getUInt16(buffer, fvarTableOffset + 8); int axisSize = getUInt16(buffer, fvarTableOffset + 10); ArraySet<Integer> axes = new ArraySet<>(); for (int i = 0; i < axisCount; ++i) { axes.add(buffer.getInt(fvarTableOffset + axesArrayOffset + axisSize * i)); } return axes; } finally { buffer.order(originalOrder); } } @FastNative private static native long nGetFontRevision(@NonNull ByteBuffer buffer, @IntRange(from = 0) int index); Loading graphics/java/android/graphics/fonts/SystemFonts.java +1 −1 Original line number Diff line number Diff line Loading @@ -194,7 +194,7 @@ public final class SystemFonts { } } return b == null ? null : b.build(languageTags, variant, false /* isCustomFallback */, isDefaultFallback); isDefaultFallback, FontFamily.Builder.VARIABLE_FONT_FAMILY_TYPE_NONE); } private static void appendNamedFamilyList(@NonNull FontConfig.NamedFamilyList namedFamilyList, Loading graphics/java/android/graphics/text/PositionedGlyphs.java +70 −0 Original line number Diff line number Diff line Loading @@ -164,6 +164,68 @@ public final class PositionedGlyphs { return nGetY(mLayoutPtr, index) + mYOffset; } /** * Returns true if the fake bold option used for drawing, otherwise false. * * @param index the glyph index * @return true if the fake bold option is on, otherwise off. */ public boolean getFakeBold(@IntRange(from = 0) int index) { Preconditions.checkArgumentInRange(index, 0, glyphCount() - 1, "index"); return nGetFakeBold(mLayoutPtr, index); } /** * Returns true if the fake italic option used for drawing, otherwise false. * * @param index the glyph index * @return true if the fake italic option is on, otherwise off. */ public boolean getFakeItalic(@IntRange(from = 0) int index) { Preconditions.checkArgumentInRange(index, 0, glyphCount() - 1, "index"); return nGetFakeItalic(mLayoutPtr, index); } /** * A special value returned by {@link #getWeightOverride(int)} and * {@link #getItalicOverride(int)} that indicates no font variation setting is overridden. */ public static final float NO_OVERRIDE = Float.MIN_VALUE; /** * Returns overridden weight value if the font is variable font and `wght` value is overridden * for drawing. Otherwise returns {@link #NO_OVERRIDE}. * * @param index the glyph index * @return overridden weight value or {@link #NO_OVERRIDE}. */ public float getWeightOverride(@IntRange(from = 0) int index) { Preconditions.checkArgumentInRange(index, 0, glyphCount() - 1, "index"); float value = nGetWeightOverride(mLayoutPtr, index); if (value == -1) { return NO_OVERRIDE; } else { return value; } } /** * Returns overridden italic value if the font is variable font and `ital` value is overridden * for drawing. Otherwise returns {@link #NO_OVERRIDE}. * * @param index the glyph index * @return overridden weight value or {@link #NO_OVERRIDE}. */ public float getItalicOverride(@IntRange(from = 0) int index) { Preconditions.checkArgumentInRange(index, 0, glyphCount() - 1, "index"); float value = nGetItalicOverride(mLayoutPtr, index); if (value == -1) { return NO_OVERRIDE; } else { return value; } } /** * Create single style layout from native result. * Loading Loading @@ -210,6 +272,14 @@ public final class PositionedGlyphs { private static native long nGetFont(long minikinLayout, int i); @CriticalNative private static native long nReleaseFunc(); @CriticalNative private static native boolean nGetFakeBold(long minikinLayout, int i); @CriticalNative private static native boolean nGetFakeItalic(long minikinLayout, int i); @CriticalNative private static native float nGetWeightOverride(long minikinLayout, int i); @CriticalNative private static native float nGetItalicOverride(long minikinLayout, int i); @Override public boolean equals(Object o) { Loading Loading
core/api/current.txt +6 −0 Original line number Diff line number Diff line Loading @@ -17442,6 +17442,7 @@ package android.graphics.fonts { ctor public FontFamily.Builder(@NonNull android.graphics.fonts.Font); method @NonNull public android.graphics.fonts.FontFamily.Builder addFont(@NonNull android.graphics.fonts.Font); method @NonNull public android.graphics.fonts.FontFamily build(); method @Nullable public android.graphics.fonts.FontFamily buildVariableFamily(); } public final class FontStyle { Loading Loading @@ -17622,13 +17623,18 @@ package android.graphics.text { method public float getAdvance(); method public float getAscent(); method public float getDescent(); method public boolean getFakeBold(@IntRange(from=0) int); method public boolean getFakeItalic(@IntRange(from=0) int); method @NonNull public android.graphics.fonts.Font getFont(@IntRange(from=0) int); method @IntRange(from=0) public int getGlyphId(@IntRange(from=0) int); method public float getGlyphX(@IntRange(from=0) int); method public float getGlyphY(@IntRange(from=0) int); method public float getItalicOverride(@IntRange(from=0) int); method public float getOffsetX(); method public float getOffsetY(); method public float getWeightOverride(@IntRange(from=0) int); method @IntRange(from=0) public int glyphCount(); field public static final float NO_OVERRIDE = 1.4E-45f; } public class TextRunShaper {
graphics/java/android/graphics/fonts/FontFamily.java +131 −5 Original line number Diff line number Diff line Loading @@ -30,6 +30,7 @@ import dalvik.annotation.optimization.FastNative; import libcore.util.NativeAllocationRegistry; import java.util.ArrayList; import java.util.Set; /** * A font family class can be used for creating Typeface. Loading Loading @@ -58,6 +59,7 @@ import java.util.ArrayList; * */ public final class FontFamily { private static final String TAG = "FontFamily"; /** Loading @@ -73,6 +75,7 @@ public final class FontFamily { // initial capacity. private final SparseIntArray mStyles = new SparseIntArray(4); /** * Constructs a builder. * Loading Loading @@ -109,24 +112,64 @@ public final class FontFamily { return this; } /** * Build a variable font family that automatically adjust the `wght` and `ital` axes value * for the requested weight/italic style values. * * To build a variable font family, added fonts must meet one of following conditions. * * If two font files are added, both font files must support `wght` axis and one font must * support {@link FontStyle#FONT_SLANT_UPRIGHT} and another font must support * {@link FontStyle#FONT_SLANT_ITALIC}. If the requested weight value is lower than minimum * value of the supported `wght` axis, the minimum supported `wght` value is used. If the * requested weight value is larger than maximum value of the supported `wght` axis, the * maximum supported `wght` value is used. The weight values of the fonts are ignored. * * If one font file is added, that font must support the `wght` axis. If that font support * `ital` axis, that `ital` value is set to 1 when the italic style is requested. If that * font doesn't support `ital` axis, synthetic italic may be used. If the requested * weight value is lower than minimum value of the supported `wght` axis, the minimum * supported `wght` value is used. If the requested weight value is larger than maximum * value of the supported `wght`axis, the maximum supported `wght` value is used. The weight * value of the font is ignored. * * If none of the above conditions are met, this function return {@code null}. * * @return A variable font family. null if a variable font cannot be built from the given * fonts. */ public @Nullable FontFamily buildVariableFamily() { int variableFamilyType = analyzeAndResolveVariableType(mFonts); if (variableFamilyType == VARIABLE_FONT_FAMILY_TYPE_UNKNOWN) { return null; } return build("", FontConfig.FontFamily.VARIANT_DEFAULT, true /* isCustomFallback */, false /* isDefaultFallback */, variableFamilyType); } /** * Build the font family * @return a font family */ public @NonNull FontFamily build() { return build("", FontConfig.FontFamily.VARIANT_DEFAULT, true /* isCustomFallback */, false /* isDefaultFallback */); return build("", FontConfig.FontFamily.VARIANT_DEFAULT, true /* isCustomFallback */, false /* isDefaultFallback */, VARIABLE_FONT_FAMILY_TYPE_NONE); } /** @hide */ public @NonNull FontFamily build(@NonNull String langTags, int variant, boolean isCustomFallback, boolean isDefaultFallback) { boolean isCustomFallback, boolean isDefaultFallback, int variableFamilyType) { final long builderPtr = nInitBuilder(); for (int i = 0; i < mFonts.size(); ++i) { nAddFont(builderPtr, mFonts.get(i).getNativePtr()); } final long ptr = nBuild(builderPtr, langTags, variant, isCustomFallback, isDefaultFallback); isDefaultFallback, variableFamilyType); final FontFamily family = new FontFamily(ptr); sFamilyRegistory.registerNativeAllocation(family, ptr); return family; Loading @@ -136,11 +179,94 @@ public final class FontFamily { return font.getStyle().getWeight() | (font.getStyle().getSlant() << 16); } /** * @see #buildVariableFamily() * @hide */ public static final int VARIABLE_FONT_FAMILY_TYPE_UNKNOWN = -1; /** * @see #buildVariableFamily() * @hide */ public static final int VARIABLE_FONT_FAMILY_TYPE_NONE = 0; /** * @see #buildVariableFamily() * @hide */ public static final int VARIABLE_FONT_FAMILY_TYPE_SINGLE_FONT_WGHT_ONLY = 1; /** * @see #buildVariableFamily() * @hide */ public static final int VARIABLE_FONT_FAMILY_TYPE_SINGLE_FONT_WGHT_ITAL = 2; /** * @see #buildVariableFamily() * @hide */ public static final int VARIABLE_FONT_FAMILY_TYPE_TWO_FONTS_WGHT = 3; /** * The registered italic axis used for adjusting requested style. * https://learn.microsoft.com/en-us/typography/opentype/spec/dvaraxistag_ital */ private static final int TAG_ital = 0x6974616C; // i(0x69), t(0x74), a(0x61), l(0x6c) /** * The registered weight axis used for adjusting requested style. * https://learn.microsoft.com/en-us/typography/opentype/spec/dvaraxistag_wght */ private static final int TAG_wght = 0x77676874; // w(0x77), g(0x67), h(0x68), t(0x74) private static int analyzeAndResolveVariableType(ArrayList<Font> fonts) { if (fonts.size() > 2) { return VARIABLE_FONT_FAMILY_TYPE_UNKNOWN; } if (fonts.size() == 1) { Font font = fonts.get(0); Set<Integer> supportedAxes = FontFileUtil.getSupportedAxes(font.getBuffer(), font.getTtcIndex()); if (supportedAxes.contains(TAG_wght)) { if (supportedAxes.contains(TAG_ital)) { return VARIABLE_FONT_FAMILY_TYPE_SINGLE_FONT_WGHT_ITAL; } else { return VARIABLE_FONT_FAMILY_TYPE_SINGLE_FONT_WGHT_ONLY; } } else { return VARIABLE_FONT_FAMILY_TYPE_UNKNOWN; } } else { for (int i = 0; i < fonts.size(); ++i) { Font font = fonts.get(i); Set<Integer> supportedAxes = FontFileUtil.getSupportedAxes(font.getBuffer(), font.getTtcIndex()); if (!supportedAxes.contains(TAG_wght)) { return VARIABLE_FONT_FAMILY_TYPE_UNKNOWN; } } boolean italic1 = fonts.get(0).getStyle().getSlant() == FontStyle.FONT_SLANT_ITALIC; boolean italic2 = fonts.get(1).getStyle().getSlant() == FontStyle.FONT_SLANT_ITALIC; if (italic1 == italic2) { return VARIABLE_FONT_FAMILY_TYPE_UNKNOWN; } else { if (italic1) { // Swap fonts to make the first font upright, second font italic. Font firstFont = fonts.get(0); fonts.set(0, fonts.get(1)); fonts.set(1, firstFont); } return VARIABLE_FONT_FAMILY_TYPE_TWO_FONTS_WGHT; } } } private static native long nInitBuilder(); @CriticalNative private static native void nAddFont(long builderPtr, long fontPtr); private static native long nBuild(long builderPtr, String langTags, int variant, boolean isCustomFallback, boolean isDefaultFallback); boolean isCustomFallback, boolean isDefaultFallback, int variableFamilyType); @CriticalNative private static native long nGetReleaseNativeFamily(); } Loading
graphics/java/android/graphics/fonts/FontFileUtil.java +71 −0 Original line number Diff line number Diff line Loading @@ -19,11 +19,14 @@ package android.graphics.fonts; import android.annotation.IntRange; import android.annotation.NonNull; import android.annotation.Nullable; import android.util.ArraySet; import dalvik.annotation.optimization.FastNative; import java.nio.ByteBuffer; import java.nio.ByteOrder; import java.util.Collections; import java.util.Set; /** * Provides a utility for font file operations. Loading Loading @@ -62,6 +65,7 @@ public class FontFileUtil { private static final int SFNT_VERSION_OTTO = 0x4F54544F; private static final int TTC_TAG = 0x74746366; private static final int OS2_TABLE_TAG = 0x4F532F32; private static final int FVAR_TABLE_TAG = 0x66766172; private static final int ANALYZE_ERROR = 0xFFFFFFFF; Loading Loading @@ -200,6 +204,73 @@ public class FontFileUtil { } } private static int getUInt16(ByteBuffer buffer, int offset) { return ((int) buffer.getShort(offset)) & 0xFFFF; } /** * Returns supported axes of font * * @param buffer A buffer of the entire font file. * @param index A font index in case of font collection. Must be 0 otherwise. * @return set of supported axes tag. Returns empty set on error. */ public static Set<Integer> getSupportedAxes(@NonNull ByteBuffer buffer, int index) { ByteOrder originalOrder = buffer.order(); buffer.order(ByteOrder.BIG_ENDIAN); try { int fontFileOffset = 0; int magicNumber = buffer.getInt(0); if (magicNumber == TTC_TAG) { // TTC file. if (index >= buffer.getInt(8 /* offset to number of fonts in TTC */)) { return Collections.EMPTY_SET; } fontFileOffset = buffer.getInt( 12 /* offset to array of offsets of font files */ + 4 * index); } int sfntVersion = buffer.getInt(fontFileOffset); if (sfntVersion != SFNT_VERSION_1 && sfntVersion != SFNT_VERSION_OTTO) { return Collections.EMPTY_SET; } int numTables = buffer.getShort(fontFileOffset + 4 /* offset to number of tables */); int fvarTableOffset = -1; for (int i = 0; i < numTables; ++i) { int tableOffset = fontFileOffset + 12 /* size of offset table */ + i * 16 /* size of table record */; if (buffer.getInt(tableOffset) == FVAR_TABLE_TAG) { fvarTableOffset = buffer.getInt(tableOffset + 8 /* offset to the table */); break; } } if (fvarTableOffset == -1) { // Couldn't find OS/2 table. use regular style return Collections.EMPTY_SET; } if (buffer.getShort(fvarTableOffset) != 1 || buffer.getShort(fvarTableOffset + 2) != 0) { return Collections.EMPTY_SET; } int axesArrayOffset = getUInt16(buffer, fvarTableOffset + 4); int axisCount = getUInt16(buffer, fvarTableOffset + 8); int axisSize = getUInt16(buffer, fvarTableOffset + 10); ArraySet<Integer> axes = new ArraySet<>(); for (int i = 0; i < axisCount; ++i) { axes.add(buffer.getInt(fvarTableOffset + axesArrayOffset + axisSize * i)); } return axes; } finally { buffer.order(originalOrder); } } @FastNative private static native long nGetFontRevision(@NonNull ByteBuffer buffer, @IntRange(from = 0) int index); Loading
graphics/java/android/graphics/fonts/SystemFonts.java +1 −1 Original line number Diff line number Diff line Loading @@ -194,7 +194,7 @@ public final class SystemFonts { } } return b == null ? null : b.build(languageTags, variant, false /* isCustomFallback */, isDefaultFallback); isDefaultFallback, FontFamily.Builder.VARIABLE_FONT_FAMILY_TYPE_NONE); } private static void appendNamedFamilyList(@NonNull FontConfig.NamedFamilyList namedFamilyList, Loading
graphics/java/android/graphics/text/PositionedGlyphs.java +70 −0 Original line number Diff line number Diff line Loading @@ -164,6 +164,68 @@ public final class PositionedGlyphs { return nGetY(mLayoutPtr, index) + mYOffset; } /** * Returns true if the fake bold option used for drawing, otherwise false. * * @param index the glyph index * @return true if the fake bold option is on, otherwise off. */ public boolean getFakeBold(@IntRange(from = 0) int index) { Preconditions.checkArgumentInRange(index, 0, glyphCount() - 1, "index"); return nGetFakeBold(mLayoutPtr, index); } /** * Returns true if the fake italic option used for drawing, otherwise false. * * @param index the glyph index * @return true if the fake italic option is on, otherwise off. */ public boolean getFakeItalic(@IntRange(from = 0) int index) { Preconditions.checkArgumentInRange(index, 0, glyphCount() - 1, "index"); return nGetFakeItalic(mLayoutPtr, index); } /** * A special value returned by {@link #getWeightOverride(int)} and * {@link #getItalicOverride(int)} that indicates no font variation setting is overridden. */ public static final float NO_OVERRIDE = Float.MIN_VALUE; /** * Returns overridden weight value if the font is variable font and `wght` value is overridden * for drawing. Otherwise returns {@link #NO_OVERRIDE}. * * @param index the glyph index * @return overridden weight value or {@link #NO_OVERRIDE}. */ public float getWeightOverride(@IntRange(from = 0) int index) { Preconditions.checkArgumentInRange(index, 0, glyphCount() - 1, "index"); float value = nGetWeightOverride(mLayoutPtr, index); if (value == -1) { return NO_OVERRIDE; } else { return value; } } /** * Returns overridden italic value if the font is variable font and `ital` value is overridden * for drawing. Otherwise returns {@link #NO_OVERRIDE}. * * @param index the glyph index * @return overridden weight value or {@link #NO_OVERRIDE}. */ public float getItalicOverride(@IntRange(from = 0) int index) { Preconditions.checkArgumentInRange(index, 0, glyphCount() - 1, "index"); float value = nGetItalicOverride(mLayoutPtr, index); if (value == -1) { return NO_OVERRIDE; } else { return value; } } /** * Create single style layout from native result. * Loading Loading @@ -210,6 +272,14 @@ public final class PositionedGlyphs { private static native long nGetFont(long minikinLayout, int i); @CriticalNative private static native long nReleaseFunc(); @CriticalNative private static native boolean nGetFakeBold(long minikinLayout, int i); @CriticalNative private static native boolean nGetFakeItalic(long minikinLayout, int i); @CriticalNative private static native float nGetWeightOverride(long minikinLayout, int i); @CriticalNative private static native float nGetItalicOverride(long minikinLayout, int i); @Override public boolean equals(Object o) { Loading