Loading libs/hwui/jni/Typeface.cpp +52 −50 Original line number Diff line number Diff line Loading @@ -204,10 +204,9 @@ static sk_sp<SkData> makeSkDataCached(const std::string& path, bool hasVerity) { return entry; } static std::function<std::shared_ptr<minikin::MinikinFont>()> readMinikinFontSkia( minikin::BufferReader* reader) { const void* buffer = reader->data(); size_t pos = reader->pos(); static std::shared_ptr<minikin::MinikinFont> loadMinikinFontSkia(minikin::BufferReader); static minikin::Font::TypefaceLoader* readMinikinFontSkia(minikin::BufferReader* reader) { // Advance reader's position. reader->skipString(); // fontPath reader->skip<int>(); // fontIndex Loading @@ -217,21 +216,23 @@ static std::function<std::shared_ptr<minikin::MinikinFont>()> readMinikinFontSki reader->skip<uint32_t>(); // expectedFontRevision reader->skipString(); // expectedPostScriptName } return [buffer, pos]() -> std::shared_ptr<minikin::MinikinFont> { minikin::BufferReader fontReader(buffer, pos); std::string_view fontPath = fontReader.readString(); return &loadMinikinFontSkia; } static std::shared_ptr<minikin::MinikinFont> loadMinikinFontSkia(minikin::BufferReader reader) { std::string_view fontPath = reader.readString(); std::string path(fontPath.data(), fontPath.size()); ATRACE_FORMAT("Loading font %s", path.c_str()); int fontIndex = fontReader.read<int>(); int fontIndex = reader.read<int>(); const minikin::FontVariation* axesPtr; uint32_t axesCount; std::tie(axesPtr, axesCount) = fontReader.readArray<minikin::FontVariation>(); bool hasVerity = static_cast<bool>(fontReader.read<int8_t>()); std::tie(axesPtr, axesCount) = reader.readArray<minikin::FontVariation>(); bool hasVerity = static_cast<bool>(reader.read<int8_t>()); uint32_t expectedFontRevision; std::string_view expectedPostScriptName; if (hasVerity) { expectedFontRevision = fontReader.read<uint32_t>(); expectedPostScriptName = fontReader.readString(); expectedFontRevision = reader.read<uint32_t>(); expectedPostScriptName = reader.readString(); } sk_sp<SkData> data = makeSkDataCached(path, hasVerity); if (data.get() == nullptr) { Loading @@ -258,19 +259,20 @@ static std::function<std::shared_ptr<minikin::MinikinFont>()> readMinikinFontSki } } std::vector<minikin::FontVariation> axes(axesPtr, axesPtr + axesCount); std::shared_ptr<minikin::MinikinFont> minikinFont = fonts::createMinikinFontSkia(std::move(data), fontPath, fontPtr, fontSize, fontIndex, axes); std::shared_ptr<minikin::MinikinFont> minikinFont = fonts::createMinikinFontSkia( std::move(data), fontPath, fontPtr, fontSize, fontIndex, axes); if (minikinFont == nullptr) { ALOGE("Failed to create MinikinFontSkia: %s", path.c_str()); return nullptr; } return minikinFont; }; } static void writeMinikinFontSkia(minikin::BufferWriter* writer, const minikin::MinikinFont* typeface) { // When you change the format of font metadata, please update code to parse // typefaceMetadataReader() in // frameworks/base/libs/hwui/jni/fonts/Font.cpp too. const std::string& path = typeface->GetFontPath(); writer->writeString(path); writer->write<int>(typeface->GetFontIndex()); Loading libs/hwui/jni/fonts/Font.cpp +42 −12 Original line number Diff line number Diff line Loading @@ -192,7 +192,7 @@ static jfloat Font_getFontMetrics(JNIEnv* env, jobject, jlong fontHandle, jlong // Critical Native static jlong Font_getMinikinFontPtr(CRITICAL_JNI_PARAMS_COMMA jlong fontPtr) { FontWrapper* font = reinterpret_cast<FontWrapper*>(fontPtr); return reinterpret_cast<jlong>(font->font->typeface().get()); return reinterpret_cast<jlong>(font->font.get()); } // Critical Native Loading Loading @@ -224,6 +224,14 @@ static jlong Font_getReleaseNativeFontFunc(CRITICAL_JNI_PARAMS) { // Fast Native static jstring Font_getFontPath(JNIEnv* env, jobject, jlong fontPtr) { FontWrapper* font = reinterpret_cast<FontWrapper*>(fontPtr); minikin::BufferReader reader = font->font->typefaceMetadataReader(); if (reader.data() != nullptr) { std::string path = std::string(reader.readString()); if (path.empty()) { return nullptr; } return env->NewStringUTF(path.c_str()); } else { const std::shared_ptr<minikin::MinikinFont>& minikinFont = font->font->typeface(); const std::string& path = minikinFont->GetFontPath(); if (path.empty()) { Loading @@ -231,6 +239,7 @@ static jstring Font_getFontPath(JNIEnv* env, jobject, jlong fontPtr) { } return env->NewStringUTF(path.c_str()); } } // Fast Native static jstring Font_getLocaleList(JNIEnv* env, jobject, jlong fontPtr) { Loading @@ -257,22 +266,43 @@ static jint Font_getPackedStyle(CRITICAL_JNI_PARAMS_COMMA jlong fontPtr) { // Critical Native static jint Font_getIndex(CRITICAL_JNI_PARAMS_COMMA jlong fontPtr) { FontWrapper* font = reinterpret_cast<FontWrapper*>(fontPtr); minikin::BufferReader reader = font->font->typefaceMetadataReader(); if (reader.data() != nullptr) { reader.skipString(); // fontPath return reader.read<int>(); } else { const std::shared_ptr<minikin::MinikinFont>& minikinFont = font->font->typeface(); return minikinFont->GetFontIndex(); } } // Critical Native static jint Font_getAxisCount(CRITICAL_JNI_PARAMS_COMMA jlong fontPtr) { FontWrapper* font = reinterpret_cast<FontWrapper*>(fontPtr); minikin::BufferReader reader = font->font->typefaceMetadataReader(); if (reader.data() != nullptr) { reader.skipString(); // fontPath reader.skip<int>(); // fontIndex return reader.readArray<minikin::FontVariation>().second; } else { const std::shared_ptr<minikin::MinikinFont>& minikinFont = font->font->typeface(); return minikinFont->GetAxes().size(); } } // Critical Native static jlong Font_getAxisInfo(CRITICAL_JNI_PARAMS_COMMA jlong fontPtr, jint index) { FontWrapper* font = reinterpret_cast<FontWrapper*>(fontPtr); minikin::BufferReader reader = font->font->typefaceMetadataReader(); minikin::FontVariation var; if (reader.data() != nullptr) { reader.skipString(); // fontPath reader.skip<int>(); // fontIndex var = reader.readArray<minikin::FontVariation>().first[index]; } else { const std::shared_ptr<minikin::MinikinFont>& minikinFont = font->font->typeface(); minikin::FontVariation var = minikinFont->GetAxes().at(index); var = minikinFont->GetAxes().at(index); } uint32_t floatBinary = *reinterpret_cast<const uint32_t*>(&var.value); return (static_cast<uint64_t>(var.axisTag) << 32) | static_cast<uint64_t>(floatBinary); } Loading tests/UpdatableSystemFontTest/Android.bp +1 −0 Original line number Diff line number Diff line Loading @@ -27,6 +27,7 @@ android_test { libs: ["android.test.runner"], static_libs: [ "androidx.test.ext.junit", "androidx.test.uiautomator_uiautomator", "compatibility-device-util-axt", "platform-test-annotations", "truth-prebuilt", Loading tests/UpdatableSystemFontTest/EmojiRenderingTestApp/AndroidManifest.xml +1 −0 Original line number Diff line number Diff line Loading @@ -19,5 +19,6 @@ package="com.android.emojirenderingtestapp"> <application> <activity android:name=".EmojiRenderingTestActivity"/> <activity android:name=".GetAvailableFontsTestActivity"/> </application> </manifest> tests/UpdatableSystemFontTest/EmojiRenderingTestApp/src/com/android/emojirenderingtestapp/GetAvailableFontsTestActivity.java 0 → 100644 +53 −0 Original line number Diff line number Diff line /* * Copyright (C) 2021 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 com.android.emojirenderingtestapp; import static android.view.ViewGroup.LayoutParams.MATCH_PARENT; import static android.view.ViewGroup.LayoutParams.WRAP_CONTENT; import android.app.Activity; import android.graphics.fonts.Font; import android.graphics.fonts.SystemFonts; import android.os.Bundle; import android.widget.LinearLayout; import android.widget.TextView; public class GetAvailableFontsTestActivity extends Activity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); String emojiFontPath = "<Not found>"; for (Font font : SystemFonts.getAvailableFonts()) { // Calls font attribute getters to make sure that they don't open font files. font.getAxes(); font.getFile(); font.getLocaleList(); font.getStyle(); font.getTtcIndex(); if ("NotoColorEmoji.ttf".equals(font.getFile().getName())) { emojiFontPath = font.getFile().getAbsolutePath(); } } LinearLayout container = new LinearLayout(this); container.setOrientation(LinearLayout.VERTICAL); TextView textView = new TextView(this); textView.setText(emojiFontPath); container.addView(textView, new LinearLayout.LayoutParams(MATCH_PARENT, WRAP_CONTENT)); setContentView(container); } } Loading
libs/hwui/jni/Typeface.cpp +52 −50 Original line number Diff line number Diff line Loading @@ -204,10 +204,9 @@ static sk_sp<SkData> makeSkDataCached(const std::string& path, bool hasVerity) { return entry; } static std::function<std::shared_ptr<minikin::MinikinFont>()> readMinikinFontSkia( minikin::BufferReader* reader) { const void* buffer = reader->data(); size_t pos = reader->pos(); static std::shared_ptr<minikin::MinikinFont> loadMinikinFontSkia(minikin::BufferReader); static minikin::Font::TypefaceLoader* readMinikinFontSkia(minikin::BufferReader* reader) { // Advance reader's position. reader->skipString(); // fontPath reader->skip<int>(); // fontIndex Loading @@ -217,21 +216,23 @@ static std::function<std::shared_ptr<minikin::MinikinFont>()> readMinikinFontSki reader->skip<uint32_t>(); // expectedFontRevision reader->skipString(); // expectedPostScriptName } return [buffer, pos]() -> std::shared_ptr<minikin::MinikinFont> { minikin::BufferReader fontReader(buffer, pos); std::string_view fontPath = fontReader.readString(); return &loadMinikinFontSkia; } static std::shared_ptr<minikin::MinikinFont> loadMinikinFontSkia(minikin::BufferReader reader) { std::string_view fontPath = reader.readString(); std::string path(fontPath.data(), fontPath.size()); ATRACE_FORMAT("Loading font %s", path.c_str()); int fontIndex = fontReader.read<int>(); int fontIndex = reader.read<int>(); const minikin::FontVariation* axesPtr; uint32_t axesCount; std::tie(axesPtr, axesCount) = fontReader.readArray<minikin::FontVariation>(); bool hasVerity = static_cast<bool>(fontReader.read<int8_t>()); std::tie(axesPtr, axesCount) = reader.readArray<minikin::FontVariation>(); bool hasVerity = static_cast<bool>(reader.read<int8_t>()); uint32_t expectedFontRevision; std::string_view expectedPostScriptName; if (hasVerity) { expectedFontRevision = fontReader.read<uint32_t>(); expectedPostScriptName = fontReader.readString(); expectedFontRevision = reader.read<uint32_t>(); expectedPostScriptName = reader.readString(); } sk_sp<SkData> data = makeSkDataCached(path, hasVerity); if (data.get() == nullptr) { Loading @@ -258,19 +259,20 @@ static std::function<std::shared_ptr<minikin::MinikinFont>()> readMinikinFontSki } } std::vector<minikin::FontVariation> axes(axesPtr, axesPtr + axesCount); std::shared_ptr<minikin::MinikinFont> minikinFont = fonts::createMinikinFontSkia(std::move(data), fontPath, fontPtr, fontSize, fontIndex, axes); std::shared_ptr<minikin::MinikinFont> minikinFont = fonts::createMinikinFontSkia( std::move(data), fontPath, fontPtr, fontSize, fontIndex, axes); if (minikinFont == nullptr) { ALOGE("Failed to create MinikinFontSkia: %s", path.c_str()); return nullptr; } return minikinFont; }; } static void writeMinikinFontSkia(minikin::BufferWriter* writer, const minikin::MinikinFont* typeface) { // When you change the format of font metadata, please update code to parse // typefaceMetadataReader() in // frameworks/base/libs/hwui/jni/fonts/Font.cpp too. const std::string& path = typeface->GetFontPath(); writer->writeString(path); writer->write<int>(typeface->GetFontIndex()); Loading
libs/hwui/jni/fonts/Font.cpp +42 −12 Original line number Diff line number Diff line Loading @@ -192,7 +192,7 @@ static jfloat Font_getFontMetrics(JNIEnv* env, jobject, jlong fontHandle, jlong // Critical Native static jlong Font_getMinikinFontPtr(CRITICAL_JNI_PARAMS_COMMA jlong fontPtr) { FontWrapper* font = reinterpret_cast<FontWrapper*>(fontPtr); return reinterpret_cast<jlong>(font->font->typeface().get()); return reinterpret_cast<jlong>(font->font.get()); } // Critical Native Loading Loading @@ -224,6 +224,14 @@ static jlong Font_getReleaseNativeFontFunc(CRITICAL_JNI_PARAMS) { // Fast Native static jstring Font_getFontPath(JNIEnv* env, jobject, jlong fontPtr) { FontWrapper* font = reinterpret_cast<FontWrapper*>(fontPtr); minikin::BufferReader reader = font->font->typefaceMetadataReader(); if (reader.data() != nullptr) { std::string path = std::string(reader.readString()); if (path.empty()) { return nullptr; } return env->NewStringUTF(path.c_str()); } else { const std::shared_ptr<minikin::MinikinFont>& minikinFont = font->font->typeface(); const std::string& path = minikinFont->GetFontPath(); if (path.empty()) { Loading @@ -231,6 +239,7 @@ static jstring Font_getFontPath(JNIEnv* env, jobject, jlong fontPtr) { } return env->NewStringUTF(path.c_str()); } } // Fast Native static jstring Font_getLocaleList(JNIEnv* env, jobject, jlong fontPtr) { Loading @@ -257,22 +266,43 @@ static jint Font_getPackedStyle(CRITICAL_JNI_PARAMS_COMMA jlong fontPtr) { // Critical Native static jint Font_getIndex(CRITICAL_JNI_PARAMS_COMMA jlong fontPtr) { FontWrapper* font = reinterpret_cast<FontWrapper*>(fontPtr); minikin::BufferReader reader = font->font->typefaceMetadataReader(); if (reader.data() != nullptr) { reader.skipString(); // fontPath return reader.read<int>(); } else { const std::shared_ptr<minikin::MinikinFont>& minikinFont = font->font->typeface(); return minikinFont->GetFontIndex(); } } // Critical Native static jint Font_getAxisCount(CRITICAL_JNI_PARAMS_COMMA jlong fontPtr) { FontWrapper* font = reinterpret_cast<FontWrapper*>(fontPtr); minikin::BufferReader reader = font->font->typefaceMetadataReader(); if (reader.data() != nullptr) { reader.skipString(); // fontPath reader.skip<int>(); // fontIndex return reader.readArray<minikin::FontVariation>().second; } else { const std::shared_ptr<minikin::MinikinFont>& minikinFont = font->font->typeface(); return minikinFont->GetAxes().size(); } } // Critical Native static jlong Font_getAxisInfo(CRITICAL_JNI_PARAMS_COMMA jlong fontPtr, jint index) { FontWrapper* font = reinterpret_cast<FontWrapper*>(fontPtr); minikin::BufferReader reader = font->font->typefaceMetadataReader(); minikin::FontVariation var; if (reader.data() != nullptr) { reader.skipString(); // fontPath reader.skip<int>(); // fontIndex var = reader.readArray<minikin::FontVariation>().first[index]; } else { const std::shared_ptr<minikin::MinikinFont>& minikinFont = font->font->typeface(); minikin::FontVariation var = minikinFont->GetAxes().at(index); var = minikinFont->GetAxes().at(index); } uint32_t floatBinary = *reinterpret_cast<const uint32_t*>(&var.value); return (static_cast<uint64_t>(var.axisTag) << 32) | static_cast<uint64_t>(floatBinary); } Loading
tests/UpdatableSystemFontTest/Android.bp +1 −0 Original line number Diff line number Diff line Loading @@ -27,6 +27,7 @@ android_test { libs: ["android.test.runner"], static_libs: [ "androidx.test.ext.junit", "androidx.test.uiautomator_uiautomator", "compatibility-device-util-axt", "platform-test-annotations", "truth-prebuilt", Loading
tests/UpdatableSystemFontTest/EmojiRenderingTestApp/AndroidManifest.xml +1 −0 Original line number Diff line number Diff line Loading @@ -19,5 +19,6 @@ package="com.android.emojirenderingtestapp"> <application> <activity android:name=".EmojiRenderingTestActivity"/> <activity android:name=".GetAvailableFontsTestActivity"/> </application> </manifest>
tests/UpdatableSystemFontTest/EmojiRenderingTestApp/src/com/android/emojirenderingtestapp/GetAvailableFontsTestActivity.java 0 → 100644 +53 −0 Original line number Diff line number Diff line /* * Copyright (C) 2021 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 com.android.emojirenderingtestapp; import static android.view.ViewGroup.LayoutParams.MATCH_PARENT; import static android.view.ViewGroup.LayoutParams.WRAP_CONTENT; import android.app.Activity; import android.graphics.fonts.Font; import android.graphics.fonts.SystemFonts; import android.os.Bundle; import android.widget.LinearLayout; import android.widget.TextView; public class GetAvailableFontsTestActivity extends Activity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); String emojiFontPath = "<Not found>"; for (Font font : SystemFonts.getAvailableFonts()) { // Calls font attribute getters to make sure that they don't open font files. font.getAxes(); font.getFile(); font.getLocaleList(); font.getStyle(); font.getTtcIndex(); if ("NotoColorEmoji.ttf".equals(font.getFile().getName())) { emojiFontPath = font.getFile().getAbsolutePath(); } } LinearLayout container = new LinearLayout(this); container.setOrientation(LinearLayout.VERTICAL); TextView textView = new TextView(this); textView.setText(emojiFontPath); container.addView(textView, new LinearLayout.LayoutParams(MATCH_PARENT, WRAP_CONTENT)); setContentView(container); } }