Loading graphics/java/android/graphics/fonts/Font.java +20 −32 Original line number Diff line number Diff line Loading @@ -123,6 +123,19 @@ public final class Font { mLocaleList = localeList; } /** * Construct a builder with a byte buffer and file path. * * This method is intended to be called only from SystemFonts. * @param path font file path * @param localeList comma concatenated BCP47 compliant language tag. * @hide */ public Builder(@NonNull File path, @NonNull String localeList) { this(path); mLocaleList = localeList; } /** * Constructs a builder with a file path. * Loading Loading @@ -809,29 +822,13 @@ public final class Font { // If not found, create Font object from native object for Java API users. ByteBuffer buffer = NativeFontBufferHelper.refByteBuffer(ptr); long packed = nGetFontInfo(ptr); int weight = (int) (packed & 0x0000_0000_0000_FFFFL); boolean italic = (packed & 0x0000_0000_0001_0000L) != 0; int ttcIndex = (int) ((packed & 0x0000_FFFF_0000_0000L) >> 32); int axisCount = (int) ((packed & 0xFFFF_0000_0000_0000L) >> 48); FontVariationAxis[] axes = new FontVariationAxis[axisCount]; char[] charBuffer = new char[4]; for (int i = 0; i < axisCount; ++i) { long packedAxis = nGetAxisInfo(ptr, i); float value = Float.intBitsToFloat((int) (packedAxis & 0x0000_0000_FFFF_FFFFL)); charBuffer[0] = (char) ((packedAxis & 0xFF00_0000_0000_0000L) >> 56); charBuffer[1] = (char) ((packedAxis & 0x00FF_0000_0000_0000L) >> 48); charBuffer[2] = (char) ((packedAxis & 0x0000_FF00_0000_0000L) >> 40); charBuffer[3] = (char) ((packedAxis & 0x0000_00FF_0000_0000L) >> 32); axes[i] = new FontVariationAxis(new String(charBuffer), value); } String path = nGetFontPath(ptr); File file = (path == null) ? null : new File(path); Font.Builder builder = new Font.Builder(buffer, file, "") .setWeight(weight) .setSlant(italic ? FontStyle.FONT_SLANT_ITALIC : FontStyle.FONT_SLANT_UPRIGHT) .setTtcIndex(ttcIndex) .setFontVariationSettings(axes); NativeFont.Font font = NativeFont.readNativeFont(ptr); Font.Builder builder = new Font.Builder(buffer, font.getFile(), "") .setWeight(font.getStyle().getWeight()) .setSlant(font.getStyle().getSlant()) .setTtcIndex(font.getIndex()) .setFontVariationSettings(font.getAxes()); Font newFont = null; try { Loading @@ -845,15 +842,6 @@ public final class Font { } } @CriticalNative private static native long nGetFontInfo(long ptr); @CriticalNative private static native long nGetAxisInfo(long ptr, int i); @FastNative private static native String nGetFontPath(long ptr); @FastNative private static native float nGetGlyphBounds(long font, int glyphId, long paint, RectF rect); Loading graphics/java/android/graphics/fonts/NativeFont.java 0 → 100644 +205 −0 Original line number Diff line number Diff line /* * Copyright (C) 2020 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package android.graphics.fonts; import android.graphics.Typeface; import dalvik.annotation.optimization.CriticalNative; import dalvik.annotation.optimization.FastNative; import java.io.File; import java.util.ArrayList; import java.util.Arrays; import java.util.List; import java.util.Objects; /** * Read native font objects. * * @hide */ public class NativeFont { /** * Represents native font object. */ public static final class Font { private final File mFile; private final int mIndex; private final FontVariationAxis[] mAxes; private final FontStyle mStyle; public Font(File file, int index, FontVariationAxis[] axes, FontStyle style) { mFile = file; mIndex = index; mAxes = axes; mStyle = style; } public File getFile() { return mFile; } public FontVariationAxis[] getAxes() { return mAxes; } public FontStyle getStyle() { return mStyle; } public int getIndex() { return mIndex; } @Override public boolean equals(Object o) { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; Font font = (Font) o; return mIndex == font.mIndex && mFile.equals(font.mFile) && Arrays.equals(mAxes, font.mAxes) && mStyle.equals(font.mStyle); } @Override public int hashCode() { int result = Objects.hash(mFile, mIndex, mStyle); result = 31 * result + Arrays.hashCode(mAxes); return result; } } /** * Represents native font family object. */ public static final class Family { private final List<Font> mFonts; private final String mLocale; public Family(List<Font> fonts, String locale) { mFonts = fonts; mLocale = locale; } public List<Font> getFonts() { return mFonts; } public String getLocale() { return mLocale; } @Override public boolean equals(Object o) { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; Family family = (Family) o; return mFonts.equals(family.mFonts) && mLocale.equals(family.mLocale); } @Override public int hashCode() { return Objects.hash(mFonts, mLocale); } } /** * Get underlying font families from Typeface * * @param typeface a typeface * @return list of family */ public static List<Family> readTypeface(Typeface typeface) { int familyCount = nGetFamilyCount(typeface.native_instance); List<Family> result = new ArrayList<>(familyCount); for (int i = 0; i < familyCount; ++i) { result.add(readNativeFamily(nGetFamily(typeface.native_instance, i))); } return result; } /** * Read family object from native pointer * * @param familyPtr a font family pointer * @return a family */ public static Family readNativeFamily(long familyPtr) { int fontCount = nGetFontCount(familyPtr); List<Font> result = new ArrayList<>(fontCount); for (int i = 0; i < fontCount; ++i) { result.add(readNativeFont(nGetFont(familyPtr, i))); } String localeList = nGetLocaleList(familyPtr); return new Family(result, localeList); } /** * Read font object from native pointer. * * @param ptr a font pointer * @return a font */ public static Font readNativeFont(long ptr) { long packed = nGetFontInfo(ptr); int weight = (int) (packed & 0x0000_0000_0000_FFFFL); boolean italic = (packed & 0x0000_0000_0001_0000L) != 0; int ttcIndex = (int) ((packed & 0x0000_FFFF_0000_0000L) >> 32); int axisCount = (int) ((packed & 0xFFFF_0000_0000_0000L) >> 48); FontVariationAxis[] axes = new FontVariationAxis[axisCount]; char[] charBuffer = new char[4]; for (int i = 0; i < axisCount; ++i) { long packedAxis = nGetAxisInfo(ptr, i); float value = Float.intBitsToFloat((int) (packedAxis & 0x0000_0000_FFFF_FFFFL)); charBuffer[0] = (char) ((packedAxis & 0xFF00_0000_0000_0000L) >> 56); charBuffer[1] = (char) ((packedAxis & 0x00FF_0000_0000_0000L) >> 48); charBuffer[2] = (char) ((packedAxis & 0x0000_FF00_0000_0000L) >> 40); charBuffer[3] = (char) ((packedAxis & 0x0000_00FF_0000_0000L) >> 32); axes[i] = new FontVariationAxis(new String(charBuffer), value); } String path = nGetFontPath(ptr); File file = (path == null) ? null : new File(path); FontStyle style = new FontStyle(weight, italic ? FontStyle.FONT_SLANT_ITALIC : FontStyle.FONT_SLANT_UPRIGHT); return new Font(file, ttcIndex, axes, style); } @CriticalNative private static native int nGetFamilyCount(long ptr); @CriticalNative private static native long nGetFamily(long ptr, int index); @FastNative private static native String nGetLocaleList(long familyPtr); @CriticalNative private static native long nGetFont(long familyPtr, int fontIndex); @CriticalNative private static native int nGetFontCount(long familyPtr); @CriticalNative private static native long nGetFontInfo(long fontPtr); @CriticalNative private static native long nGetAxisInfo(long fontPtr, int i); @FastNative private static native String nGetFontPath(long fontPtr); } graphics/java/android/graphics/fonts/SystemFonts.java +40 −8 Original line number Diff line number Diff line Loading @@ -19,6 +19,7 @@ package android.graphics.fonts; import android.annotation.NonNull; import android.annotation.Nullable; import android.graphics.FontListParser; import android.graphics.Typeface; import android.text.FontConfig; import android.util.ArrayMap; import android.util.Log; Loading Loading @@ -68,8 +69,10 @@ public final class SystemFonts { return sAvailableFonts; } if (Typeface.ENABLE_LAZY_TYPEFACE_INITIALIZATION) { sAvailableFonts = collectAllFonts(); } else { Set<Font> set = new HashSet<>(); for (FontFamily[] items : sFamilyMap.values()) { for (FontFamily family : items) { for (int i = 0; i < family.getSize(); ++i) { Loading @@ -79,10 +82,39 @@ public final class SystemFonts { } sAvailableFonts = Collections.unmodifiableSet(set); } return sAvailableFonts; } } private static @NonNull Set<Font> collectAllFonts() { Map<String, Typeface> map = Typeface.getSystemFontMap(); HashSet<NativeFont.Font> seenFonts = new HashSet<>(); HashSet<Font> result = new HashSet<>(); for (Typeface typeface : map.values()) { List<NativeFont.Family> families = NativeFont.readTypeface(typeface); for (NativeFont.Family family : families) { for (NativeFont.Font font : family.getFonts()) { if (seenFonts.contains(font)) { continue; } seenFonts.add(font); try { result.add(new Font.Builder(font.getFile(), family.getLocale()) .setFontVariationSettings(font.getAxes()) .setTtcIndex(font.getIndex()) .setWeight(font.getStyle().getWeight()) .setSlant(font.getStyle().getSlant()) .build()); } catch (IOException e) { Log.w(TAG, "Failed to load " + font.getFile(), e); } } } } return result; } private static @Nullable ByteBuffer mmap(@NonNull String fullPath) { try (FileInputStream file = new FileInputStream(fullPath)) { final FileChannel fileChannel = file.getChannel(); Loading libs/hwui/Android.bp +1 −0 Original line number Diff line number Diff line Loading @@ -333,6 +333,7 @@ cc_defaults { "jni/YuvToJpegEncoder.cpp", "jni/fonts/Font.cpp", "jni/fonts/FontFamily.cpp", "jni/fonts/NativeFont.cpp", "jni/text/LineBreaker.cpp", "jni/text/MeasuredText.cpp", "jni/text/TextShaper.cpp", Loading libs/hwui/apex/jni_runtime.cpp +2 −0 Original line number Diff line number Diff line Loading @@ -69,6 +69,7 @@ extern int register_android_graphics_drawable_AnimatedVectorDrawable(JNIEnv* env extern int register_android_graphics_drawable_VectorDrawable(JNIEnv* env); extern int register_android_graphics_fonts_Font(JNIEnv* env); extern int register_android_graphics_fonts_FontFamily(JNIEnv* env); extern int register_android_graphics_fonts_NativeFont(JNIEnv* env); extern int register_android_graphics_pdf_PdfDocument(JNIEnv* env); extern int register_android_graphics_pdf_PdfEditor(JNIEnv* env); extern int register_android_graphics_pdf_PdfRenderer(JNIEnv* env); Loading Loading @@ -135,6 +136,7 @@ static const RegJNIRec gRegJNI[] = { REG_JNI(register_android_graphics_drawable_VectorDrawable), REG_JNI(register_android_graphics_fonts_Font), REG_JNI(register_android_graphics_fonts_FontFamily), REG_JNI(register_android_graphics_fonts_NativeFont), REG_JNI(register_android_graphics_pdf_PdfDocument), REG_JNI(register_android_graphics_pdf_PdfEditor), REG_JNI(register_android_graphics_pdf_PdfRenderer), Loading Loading
graphics/java/android/graphics/fonts/Font.java +20 −32 Original line number Diff line number Diff line Loading @@ -123,6 +123,19 @@ public final class Font { mLocaleList = localeList; } /** * Construct a builder with a byte buffer and file path. * * This method is intended to be called only from SystemFonts. * @param path font file path * @param localeList comma concatenated BCP47 compliant language tag. * @hide */ public Builder(@NonNull File path, @NonNull String localeList) { this(path); mLocaleList = localeList; } /** * Constructs a builder with a file path. * Loading Loading @@ -809,29 +822,13 @@ public final class Font { // If not found, create Font object from native object for Java API users. ByteBuffer buffer = NativeFontBufferHelper.refByteBuffer(ptr); long packed = nGetFontInfo(ptr); int weight = (int) (packed & 0x0000_0000_0000_FFFFL); boolean italic = (packed & 0x0000_0000_0001_0000L) != 0; int ttcIndex = (int) ((packed & 0x0000_FFFF_0000_0000L) >> 32); int axisCount = (int) ((packed & 0xFFFF_0000_0000_0000L) >> 48); FontVariationAxis[] axes = new FontVariationAxis[axisCount]; char[] charBuffer = new char[4]; for (int i = 0; i < axisCount; ++i) { long packedAxis = nGetAxisInfo(ptr, i); float value = Float.intBitsToFloat((int) (packedAxis & 0x0000_0000_FFFF_FFFFL)); charBuffer[0] = (char) ((packedAxis & 0xFF00_0000_0000_0000L) >> 56); charBuffer[1] = (char) ((packedAxis & 0x00FF_0000_0000_0000L) >> 48); charBuffer[2] = (char) ((packedAxis & 0x0000_FF00_0000_0000L) >> 40); charBuffer[3] = (char) ((packedAxis & 0x0000_00FF_0000_0000L) >> 32); axes[i] = new FontVariationAxis(new String(charBuffer), value); } String path = nGetFontPath(ptr); File file = (path == null) ? null : new File(path); Font.Builder builder = new Font.Builder(buffer, file, "") .setWeight(weight) .setSlant(italic ? FontStyle.FONT_SLANT_ITALIC : FontStyle.FONT_SLANT_UPRIGHT) .setTtcIndex(ttcIndex) .setFontVariationSettings(axes); NativeFont.Font font = NativeFont.readNativeFont(ptr); Font.Builder builder = new Font.Builder(buffer, font.getFile(), "") .setWeight(font.getStyle().getWeight()) .setSlant(font.getStyle().getSlant()) .setTtcIndex(font.getIndex()) .setFontVariationSettings(font.getAxes()); Font newFont = null; try { Loading @@ -845,15 +842,6 @@ public final class Font { } } @CriticalNative private static native long nGetFontInfo(long ptr); @CriticalNative private static native long nGetAxisInfo(long ptr, int i); @FastNative private static native String nGetFontPath(long ptr); @FastNative private static native float nGetGlyphBounds(long font, int glyphId, long paint, RectF rect); Loading
graphics/java/android/graphics/fonts/NativeFont.java 0 → 100644 +205 −0 Original line number Diff line number Diff line /* * Copyright (C) 2020 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package android.graphics.fonts; import android.graphics.Typeface; import dalvik.annotation.optimization.CriticalNative; import dalvik.annotation.optimization.FastNative; import java.io.File; import java.util.ArrayList; import java.util.Arrays; import java.util.List; import java.util.Objects; /** * Read native font objects. * * @hide */ public class NativeFont { /** * Represents native font object. */ public static final class Font { private final File mFile; private final int mIndex; private final FontVariationAxis[] mAxes; private final FontStyle mStyle; public Font(File file, int index, FontVariationAxis[] axes, FontStyle style) { mFile = file; mIndex = index; mAxes = axes; mStyle = style; } public File getFile() { return mFile; } public FontVariationAxis[] getAxes() { return mAxes; } public FontStyle getStyle() { return mStyle; } public int getIndex() { return mIndex; } @Override public boolean equals(Object o) { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; Font font = (Font) o; return mIndex == font.mIndex && mFile.equals(font.mFile) && Arrays.equals(mAxes, font.mAxes) && mStyle.equals(font.mStyle); } @Override public int hashCode() { int result = Objects.hash(mFile, mIndex, mStyle); result = 31 * result + Arrays.hashCode(mAxes); return result; } } /** * Represents native font family object. */ public static final class Family { private final List<Font> mFonts; private final String mLocale; public Family(List<Font> fonts, String locale) { mFonts = fonts; mLocale = locale; } public List<Font> getFonts() { return mFonts; } public String getLocale() { return mLocale; } @Override public boolean equals(Object o) { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; Family family = (Family) o; return mFonts.equals(family.mFonts) && mLocale.equals(family.mLocale); } @Override public int hashCode() { return Objects.hash(mFonts, mLocale); } } /** * Get underlying font families from Typeface * * @param typeface a typeface * @return list of family */ public static List<Family> readTypeface(Typeface typeface) { int familyCount = nGetFamilyCount(typeface.native_instance); List<Family> result = new ArrayList<>(familyCount); for (int i = 0; i < familyCount; ++i) { result.add(readNativeFamily(nGetFamily(typeface.native_instance, i))); } return result; } /** * Read family object from native pointer * * @param familyPtr a font family pointer * @return a family */ public static Family readNativeFamily(long familyPtr) { int fontCount = nGetFontCount(familyPtr); List<Font> result = new ArrayList<>(fontCount); for (int i = 0; i < fontCount; ++i) { result.add(readNativeFont(nGetFont(familyPtr, i))); } String localeList = nGetLocaleList(familyPtr); return new Family(result, localeList); } /** * Read font object from native pointer. * * @param ptr a font pointer * @return a font */ public static Font readNativeFont(long ptr) { long packed = nGetFontInfo(ptr); int weight = (int) (packed & 0x0000_0000_0000_FFFFL); boolean italic = (packed & 0x0000_0000_0001_0000L) != 0; int ttcIndex = (int) ((packed & 0x0000_FFFF_0000_0000L) >> 32); int axisCount = (int) ((packed & 0xFFFF_0000_0000_0000L) >> 48); FontVariationAxis[] axes = new FontVariationAxis[axisCount]; char[] charBuffer = new char[4]; for (int i = 0; i < axisCount; ++i) { long packedAxis = nGetAxisInfo(ptr, i); float value = Float.intBitsToFloat((int) (packedAxis & 0x0000_0000_FFFF_FFFFL)); charBuffer[0] = (char) ((packedAxis & 0xFF00_0000_0000_0000L) >> 56); charBuffer[1] = (char) ((packedAxis & 0x00FF_0000_0000_0000L) >> 48); charBuffer[2] = (char) ((packedAxis & 0x0000_FF00_0000_0000L) >> 40); charBuffer[3] = (char) ((packedAxis & 0x0000_00FF_0000_0000L) >> 32); axes[i] = new FontVariationAxis(new String(charBuffer), value); } String path = nGetFontPath(ptr); File file = (path == null) ? null : new File(path); FontStyle style = new FontStyle(weight, italic ? FontStyle.FONT_SLANT_ITALIC : FontStyle.FONT_SLANT_UPRIGHT); return new Font(file, ttcIndex, axes, style); } @CriticalNative private static native int nGetFamilyCount(long ptr); @CriticalNative private static native long nGetFamily(long ptr, int index); @FastNative private static native String nGetLocaleList(long familyPtr); @CriticalNative private static native long nGetFont(long familyPtr, int fontIndex); @CriticalNative private static native int nGetFontCount(long familyPtr); @CriticalNative private static native long nGetFontInfo(long fontPtr); @CriticalNative private static native long nGetAxisInfo(long fontPtr, int i); @FastNative private static native String nGetFontPath(long fontPtr); }
graphics/java/android/graphics/fonts/SystemFonts.java +40 −8 Original line number Diff line number Diff line Loading @@ -19,6 +19,7 @@ package android.graphics.fonts; import android.annotation.NonNull; import android.annotation.Nullable; import android.graphics.FontListParser; import android.graphics.Typeface; import android.text.FontConfig; import android.util.ArrayMap; import android.util.Log; Loading Loading @@ -68,8 +69,10 @@ public final class SystemFonts { return sAvailableFonts; } if (Typeface.ENABLE_LAZY_TYPEFACE_INITIALIZATION) { sAvailableFonts = collectAllFonts(); } else { Set<Font> set = new HashSet<>(); for (FontFamily[] items : sFamilyMap.values()) { for (FontFamily family : items) { for (int i = 0; i < family.getSize(); ++i) { Loading @@ -79,10 +82,39 @@ public final class SystemFonts { } sAvailableFonts = Collections.unmodifiableSet(set); } return sAvailableFonts; } } private static @NonNull Set<Font> collectAllFonts() { Map<String, Typeface> map = Typeface.getSystemFontMap(); HashSet<NativeFont.Font> seenFonts = new HashSet<>(); HashSet<Font> result = new HashSet<>(); for (Typeface typeface : map.values()) { List<NativeFont.Family> families = NativeFont.readTypeface(typeface); for (NativeFont.Family family : families) { for (NativeFont.Font font : family.getFonts()) { if (seenFonts.contains(font)) { continue; } seenFonts.add(font); try { result.add(new Font.Builder(font.getFile(), family.getLocale()) .setFontVariationSettings(font.getAxes()) .setTtcIndex(font.getIndex()) .setWeight(font.getStyle().getWeight()) .setSlant(font.getStyle().getSlant()) .build()); } catch (IOException e) { Log.w(TAG, "Failed to load " + font.getFile(), e); } } } } return result; } private static @Nullable ByteBuffer mmap(@NonNull String fullPath) { try (FileInputStream file = new FileInputStream(fullPath)) { final FileChannel fileChannel = file.getChannel(); Loading
libs/hwui/Android.bp +1 −0 Original line number Diff line number Diff line Loading @@ -333,6 +333,7 @@ cc_defaults { "jni/YuvToJpegEncoder.cpp", "jni/fonts/Font.cpp", "jni/fonts/FontFamily.cpp", "jni/fonts/NativeFont.cpp", "jni/text/LineBreaker.cpp", "jni/text/MeasuredText.cpp", "jni/text/TextShaper.cpp", Loading
libs/hwui/apex/jni_runtime.cpp +2 −0 Original line number Diff line number Diff line Loading @@ -69,6 +69,7 @@ extern int register_android_graphics_drawable_AnimatedVectorDrawable(JNIEnv* env extern int register_android_graphics_drawable_VectorDrawable(JNIEnv* env); extern int register_android_graphics_fonts_Font(JNIEnv* env); extern int register_android_graphics_fonts_FontFamily(JNIEnv* env); extern int register_android_graphics_fonts_NativeFont(JNIEnv* env); extern int register_android_graphics_pdf_PdfDocument(JNIEnv* env); extern int register_android_graphics_pdf_PdfEditor(JNIEnv* env); extern int register_android_graphics_pdf_PdfRenderer(JNIEnv* env); Loading Loading @@ -135,6 +136,7 @@ static const RegJNIRec gRegJNI[] = { REG_JNI(register_android_graphics_drawable_VectorDrawable), REG_JNI(register_android_graphics_fonts_Font), REG_JNI(register_android_graphics_fonts_FontFamily), REG_JNI(register_android_graphics_fonts_NativeFont), REG_JNI(register_android_graphics_pdf_PdfDocument), REG_JNI(register_android_graphics_pdf_PdfEditor), REG_JNI(register_android_graphics_pdf_PdfRenderer), Loading