From: uazo Date: Sat, 15 Feb 2025 16:25:31 +0000 Subject: Android fonts fingerprinting mitigation Replaces system fonts with a predefined set downloaded from www.cromite.org License: GPL-2.0-or-later - https://spdx.org/licenses/GPL-2.0-or-later.html --- .../common/ProductionSupportedFlagList.java | 3 + .../component_updater/registration.cc | 9 + build/config/freetype/freetype.gni | 2 +- .../java/res/xml/developer_preferences.xml | 5 + chrome/browser/BUILD.gn | 7 + .../browser/component_updater/registration.cc | 10 + ...droid-fonts-fingerprinting-mitigation.grdp | 9 + chrome/browser/ui/prefs/prefs_tab_helper.cc | 9 +- chrome/renderer/BUILD.gn | 4 + .../installer_policies/BUILD.gn | 7 + .../fonts_pack_component_installer.cc | 96 + .../fonts_pack_component_installer.h | 60 + components/services/font/BUILD.gn | 10 + components/services/font/font_service_app.cc | 46 + components/services/font/font_service_app.h | 1 + .../services/font/public/cpp/font_loader.cc | 11 + .../services/font/public/cpp/font_loader.h | 1 + .../font/public/cpp/font_service_thread.cc | 48 + .../font/public/cpp/font_service_thread.h | 5 + .../font/public/mojom/font_service.mojom | 2 + content/browser/BUILD.gn | 18 + ...der_process_host_impl_receiver_bindings.cc | 12 + content/child/BUILD.gn | 7 + content/renderer/BUILD.gn | 4 + .../renderer/renderer_blink_platform_impl.cc | 55 +- content/renderer/renderer_main.cc | 2 - ...ndroid-fonts-fingerprinting-mitigation.inc | 12 + ...ndroid-fonts-fingerprinting-mitigation.inc | 7 + ...ndroid-fonts-fingerprinting-mitigation.inc | 5 + skia/BUILD.gn | 12 + skia/ext/font_utils.cc | 1 + .../freetype/config/ftoption.h | 2 +- .../include/ports/SkFontConfigInterface.h | 2 + .../skia/include/ports/SkFontMgr_android.h | 42 +- .../skia/src/ports/SkFontConfigInterface.cpp | 5 + .../ports/SkFontConfigInterface_direct.cpp | 5 + .../src/ports/SkFontConfigInterface_direct.h | 1 + .../skia/src/ports/SkFontMgr_android.cpp | 286 ++- .../skia/src/ports/SkFontMgr_android_data.cpp | 1641 +++++++++++++++++ .../skia/src/ports/SkFontMgr_android_ndk.cpp | 2 +- .../src/ports/SkFontMgr_android_parser.cpp | 69 +- .../skia/src/ports/SkFontMgr_android_parser.h | 5 +- 42 files changed, 2451 insertions(+), 89 deletions(-) create mode 100644 chrome/browser/ui/android/strings/cromite_android_chrome_strings_grd/Android-fonts-fingerprinting-mitigation.grdp create mode 100644 components/component_updater/installer_policies/fonts_pack_component_installer.cc create mode 100644 components/component_updater/installer_policies/fonts_pack_component_installer.h create mode 100644 cromite_flags/chrome/browser/about_flags_cc/Android-fonts-fingerprinting-mitigation.inc create mode 100644 cromite_flags/third_party/blink/common/features_cc/Android-fonts-fingerprinting-mitigation.inc create mode 100644 cromite_flags/third_party/blink/common/features_h/Android-fonts-fingerprinting-mitigation.inc create mode 100644 third_party/skia/src/ports/SkFontMgr_android_data.cpp diff --git a/android_webview/java/src/org/chromium/android_webview/common/ProductionSupportedFlagList.java b/android_webview/java/src/org/chromium/android_webview/common/ProductionSupportedFlagList.java --- a/android_webview/java/src/org/chromium/android_webview/common/ProductionSupportedFlagList.java +++ b/android_webview/java/src/org/chromium/android_webview/common/ProductionSupportedFlagList.java @@ -998,6 +998,9 @@ public final class ProductionSupportedFlagList { "Hides user preference on the system keyboard by setting the standard " + "eng layout and removing the layout information from the " + "javascript keyboard events."), + Flag.baseFeature( + "AndroidFontsFingerprintingMitigation", + "Android fonts fingerprinting mitigation: replaces all system fonts with the same for all devices.."), Flag.baseFeature( BlinkFeatures.ASYNC_SET_COOKIE, "When enabled, the communication between renderer and network service is " diff --git a/android_webview/nonembedded/component_updater/registration.cc b/android_webview/nonembedded/component_updater/registration.cc --- a/android_webview/nonembedded/component_updater/registration.cc +++ b/android_webview/nonembedded/component_updater/registration.cc @@ -20,6 +20,9 @@ #include "components/component_updater/installer_policies/origin_trials_component_installer.h" #include "components/update_client/update_client.h" +#include "third_party/blink/public/common/features.h" +#include "components/component_updater/installer_policies/fonts_pack_component_installer.h" + namespace android_webview { void RegisterComponentsForUpdate( @@ -36,6 +39,12 @@ void RegisterComponentsForUpdate( std::vector> component_installer_list_cromite; + if (base::FeatureList::IsEnabled(blink::features::kAndroidFontsFingerprintingMitigation)) { + component_installer_list_cromite.push_back( + std::make_unique< + component_updater::FontsPackComponentInstallerPolicy>()); + } + component_installer_list.push_back( std::make_unique< component_updater::OriginTrialsComponentInstallerPolicy>()); diff --git a/build/config/freetype/freetype.gni b/build/config/freetype/freetype.gni --- a/build/config/freetype/freetype.gni +++ b/build/config/freetype/freetype.gni @@ -24,5 +24,5 @@ declare_args() { # This should be kept in sync with the value of `enable_pdf` in # //pdf/features.gni, but for layering reasons, # we can't import pdf's features.gni here. - enable_freetype = !is_android && !is_ios && !is_castos && !is_fuchsia + enable_freetype = is_android || (!is_ios && !is_castos && !is_fuchsia) } diff --git a/chrome/android/java/res/xml/developer_preferences.xml b/chrome/android/java/res/xml/developer_preferences.xml --- a/chrome/android/java/res/xml/developer_preferences.xml +++ b/chrome/android/java/res/xml/developer_preferences.xml @@ -28,4 +28,9 @@ found in the LICENSE file. android:summary="@string/android_gpu_sandbox_summary" app:featureName="android-gpu-sandbox" app:needRestart="true" /> + diff --git a/chrome/browser/BUILD.gn b/chrome/browser/BUILD.gn --- a/chrome/browser/BUILD.gn +++ b/chrome/browser/BUILD.gn @@ -7326,6 +7326,13 @@ static_library("browser") { ] } + if (is_android) { + deps += [ + "//components/services/font:lib", + "//components/services/font/public/mojom", + ] + } + if (enable_chrome_notifications) { assert(enable_message_center) sources += [ diff --git a/chrome/browser/component_updater/registration.cc b/chrome/browser/component_updater/registration.cc --- a/chrome/browser/component_updater/registration.cc +++ b/chrome/browser/component_updater/registration.cc @@ -103,6 +103,11 @@ #include "chrome/browser/component_updater/file_type_policies_component_installer.h" #endif +#if BUILDFLAG(IS_ANDROID) +#include "components/component_updater/installer_policies/fonts_pack_component_installer.h" +#include "third_party/blink/public/common/features.h" +#endif + namespace component_updater { namespace { @@ -135,6 +140,11 @@ void DeleteOldComponents(const base::FilePath& user_data_dir) { void RegisterComponentsForUpdate() { auto* const cus = g_browser_process->component_updater(); +#if BUILDFLAG(IS_ANDROID) + if (base::FeatureList::IsEnabled(blink::features::kAndroidFontsFingerprintingMitigation)) { + RegisterFontsPackComponent(cus); + } +#endif if ((true)) return; diff --git a/chrome/browser/ui/android/strings/cromite_android_chrome_strings_grd/Android-fonts-fingerprinting-mitigation.grdp b/chrome/browser/ui/android/strings/cromite_android_chrome_strings_grd/Android-fonts-fingerprinting-mitigation.grdp new file mode 100644 --- /dev/null +++ b/chrome/browser/ui/android/strings/cromite_android_chrome_strings_grd/Android-fonts-fingerprinting-mitigation.grdp @@ -0,0 +1,9 @@ + + + + Android fonts fingerprinting mitigation + + + Replaces all system fonts with the same for all devices + + diff --git a/chrome/browser/ui/prefs/prefs_tab_helper.cc b/chrome/browser/ui/prefs/prefs_tab_helper.cc --- a/chrome/browser/ui/prefs/prefs_tab_helper.cc +++ b/chrome/browser/ui/prefs/prefs_tab_helper.cc @@ -64,8 +64,7 @@ #include #endif -#if BUILDFLAG(IS_MAC) || BUILDFLAG(IS_WIN) || BUILDFLAG(IS_LINUX) || \ - BUILDFLAG(IS_ANDROID) || BUILDFLAG(ENABLE_DESKTOP_ANDROID_EXTENSIONS) +#if BUILDFLAG(IS_MAC) || BUILDFLAG(IS_WIN) || BUILDFLAG(IS_LINUX) // If a font name in prefs default values starts with a comma, consider it's a // comma-separated font list and resolve it to the first available font. #define PREFS_FONT_LIST 1 @@ -447,9 +446,9 @@ void PrefsTabHelper::RegisterProfilePrefs( value = gfx::FontList::FirstAvailableOrFirst(value); } #else // !PREFS_FONT_LIST - DCHECK(!value.starts_with(',')) - << "This platform doesn't support default font lists. " - << pref.pref_name << "=" << value; + // DCHECK(!value.starts_with(',')) + // << "This platform doesn't support default font lists. " + // << pref.pref_name << "=" << value; #endif // PREFS_FONT_LIST registry->RegisterStringPref(pref.pref_name, value); fonts_with_defaults.insert(pref.pref_name); diff --git a/chrome/renderer/BUILD.gn b/chrome/renderer/BUILD.gn --- a/chrome/renderer/BUILD.gn +++ b/chrome/renderer/BUILD.gn @@ -270,6 +270,10 @@ static_library("renderer") { deps += [ "//components/strings" ] } + if (is_android) { + deps += [ "//components/services/font/public/cpp" ] + } + if (enable_pdf) { deps += [ "//components/pdf/renderer", diff --git a/components/component_updater/installer_policies/BUILD.gn b/components/component_updater/installer_policies/BUILD.gn --- a/components/component_updater/installer_policies/BUILD.gn +++ b/components/component_updater/installer_policies/BUILD.gn @@ -30,6 +30,13 @@ static_library("installer_policies_no_content_deps") { "trust_token_key_commitments_component_installer_policy.h", ] + if (is_android) { + sources += [ + "fonts_pack_component_installer.h", + "fonts_pack_component_installer.cc", + ] + } + deps = [ "//base", "//components/autofill/core/browser", diff --git a/components/component_updater/installer_policies/fonts_pack_component_installer.cc b/components/component_updater/installer_policies/fonts_pack_component_installer.cc new file mode 100644 --- /dev/null +++ b/components/component_updater/installer_policies/fonts_pack_component_installer.cc @@ -0,0 +1,96 @@ +#include "fonts_pack_component_installer.h" + +#include +#include + +#include "base/logging.h" +#include "base/files/file_path.h" +#include "base/files/file_util.h" +#include "base/functional/callback.h" +#include "base/memory/ref_counted.h" +#include "base/path_service.h" +#include "base/values.h" +#include "base/version.h" +#include "components/component_updater/component_updater_paths.h" + +using component_updater::ComponentUpdateService; + +namespace component_updater { + +// The extension id is: gcmjkmgdlgnkkcocmoeiminaijmmjnii +const uint8_t kFontsPackPublicKeySHA256[32] = { + 0x62, 0xc9, 0xac, 0x63, 0xb6, 0xda, 0xa2, 0xe2, 0xce, 0x48, 0xc8, + 0xd0, 0x89, 0xcc, 0x9d, 0x88, 0x02, 0x7c, 0x3e, 0x71, 0xcf, 0x5d, + 0x6b, 0xb5, 0xdf, 0x21, 0x65, 0x82, 0x08, 0x97, 0x6a, 0x26}; + +const char kFontsPackSetFetcherManifestName[] = + "System Fonts Pack"; + +FontsPackComponentInstallerPolicy:: + FontsPackComponentInstallerPolicy() = default; + +FontsPackComponentInstallerPolicy:: + ~FontsPackComponentInstallerPolicy() = default; + +bool FontsPackComponentInstallerPolicy:: + SupportsGroupPolicyEnabledComponentUpdates() const { + return false; +} + +bool FontsPackComponentInstallerPolicy::RequiresNetworkEncryption() + const { + return true; +} + +update_client::CrxInstaller::Result +FontsPackComponentInstallerPolicy::OnCustomInstall( + const base::DictValue& manifest, + const base::FilePath& install_dir) { + return update_client::CrxInstaller::Result(0); // Nothing custom here. +} + +void FontsPackComponentInstallerPolicy::OnCustomUninstall() {} + +void FontsPackComponentInstallerPolicy::ComponentReady( + const base::Version& version, + const base::FilePath& install_dir, + base::DictValue manifest) { + DCHECK(!install_dir.empty()); + LOG(INFO) << "Fonts Pack Version Ready: " << install_dir.value(); +} + +// Called during startup and installation before ComponentReady(). +bool FontsPackComponentInstallerPolicy::VerifyInstallation( + const base::DictValue& manifest, + const base::FilePath& install_dir) const { + return base::PathExists(install_dir); +} + +base::FilePath +FontsPackComponentInstallerPolicy::GetRelativeInstallDir() const { + return base::FilePath("fonts"); +} + +void FontsPackComponentInstallerPolicy::GetHash( + std::vector* hash) const { + hash->assign(std::begin(kFontsPackPublicKeySHA256), + std::end(kFontsPackPublicKeySHA256)); +} + +std::string FontsPackComponentInstallerPolicy::GetName() const { + return kFontsPackSetFetcherManifestName; +} + +update_client::InstallerAttributes +FontsPackComponentInstallerPolicy::GetInstallerAttributes() const { + update_client::InstallerAttributes attributes; + return attributes; +} + +void RegisterFontsPackComponent(ComponentUpdateService* cus) { + auto installer = base::MakeRefCounted( + std::make_unique()); + installer->Register(cus, base::OnceClosure(), /*allowed*/true); +} + +} // namespace component_updater diff --git a/components/component_updater/installer_policies/fonts_pack_component_installer.h b/components/component_updater/installer_policies/fonts_pack_component_installer.h new file mode 100644 --- /dev/null +++ b/components/component_updater/installer_policies/fonts_pack_component_installer.h @@ -0,0 +1,60 @@ +#ifndef COMPONENTS_COMPONENT_UPDATER_INSTALLER_POLICIES_FONTS_PACK_COMPONENT_INSTALLER_H_ +#define COMPONENTS_COMPONENT_UPDATER_INSTALLER_POLICIES_FONTS_PACK_COMPONENT_INSTALLER_H_ + +#include +#include +#include + +#include "base/values.h" +#include "components/component_updater/component_installer.h" + +namespace base { +class FilePath; +} // namespace base + +namespace component_updater { + +class ComponentUpdateService; + +// Component for receiving System fonts overrides. +class FontsPackComponentInstallerPolicy + : public ComponentInstallerPolicy { + public: + static const char kManifestRulesetFormatKey[]; + static const int kCurrentRulesetFormat; + + FontsPackComponentInstallerPolicy(); + + FontsPackComponentInstallerPolicy( + const FontsPackComponentInstallerPolicy&) = delete; + FontsPackComponentInstallerPolicy& operator=( + const FontsPackComponentInstallerPolicy&) = delete; + + ~FontsPackComponentInstallerPolicy() override; + + private: + static std::string GetInstallerTag(); + + // ComponentInstallerPolicy implementation. + bool SupportsGroupPolicyEnabledComponentUpdates() const override; + bool RequiresNetworkEncryption() const override; + update_client::CrxInstaller::Result OnCustomInstall( + const base::DictValue& manifest, + const base::FilePath& install_dir) override; + void OnCustomUninstall() override; + bool VerifyInstallation(const base::DictValue& manifest, + const base::FilePath& install_dir) const override; + void ComponentReady(const base::Version& version, + const base::FilePath& install_dir, + base::DictValue manifest) override; + base::FilePath GetRelativeInstallDir() const override; + void GetHash(std::vector* hash) const override; + std::string GetName() const override; + update_client::InstallerAttributes GetInstallerAttributes() const override; +}; + +void RegisterFontsPackComponent(ComponentUpdateService* cus); + +} // namespace component_updater + +#endif // COMPONENTS_COMPONENT_UPDATER_INSTALLER_POLICIES_FONTS_PACK_COMPONENT_INSTALLER_H_ diff --git a/components/services/font/BUILD.gn b/components/services/font/BUILD.gn --- a/components/services/font/BUILD.gn +++ b/components/services/font/BUILD.gn @@ -23,6 +23,16 @@ source_set("lib") { "//ui/gfx", ] + if (is_android) { + sources -= [ + "fontconfig_matching.cc", + "fontconfig_matching.h", + ] + deps -= [ + "//third_party/fontconfig", + ] + } + public_deps = [ "//skia" ] if (enable_pdf && (is_linux || is_chromeos)) { diff --git a/components/services/font/font_service_app.cc b/components/services/font/font_service_app.cc --- a/components/services/font/font_service_app.cc +++ b/components/services/font/font_service_app.cc @@ -4,7 +4,9 @@ #include "components/services/font/font_service_app.h" +#if !BUILDFLAG(IS_ANDROID) #include +#endif #include #include @@ -26,6 +28,12 @@ #include "ui/gfx/font_fallback_linux.h" #include "ui/gfx/font_render_params.h" +#if BUILDFLAG(IS_ANDROID) +#include "base/path_service.h" +#include "base/files/file_util.h" +#include "components/component_updater/component_updater_paths.h" +#endif + #if BUILDFLAG(ENABLE_PDF) #include "components/services/font/pdf_fontconfig_matching.h" // nogncheck #endif @@ -101,6 +109,7 @@ void FontServiceApp::BindReceiver( void FontServiceApp::MatchFamilyName(const std::string& family_name, mojom::TypefaceStylePtr requested_style, MatchFamilyNameCallback callback) { +#if !BUILDFLAG(IS_ANDROID) TRACE_EVENT0("fonts", "FontServiceApp::MatchFamilyName"); SkFontConfigInterface::FontIdentity result_identity; @@ -161,6 +170,7 @@ void FontServiceApp::MatchFamilyName(const std::string& family_name, std::move(callback).Run(std::move(identity), result_family_cppstring, std::move(style)); +#endif } void FontServiceApp::OpenStream(uint32_t id_number, @@ -175,12 +185,43 @@ void FontServiceApp::OpenStream(uint32_t id_number, std::move(callback).Run(std::move(file)); } +void FontServiceApp::OpenStreamFromName(const std::string& name, + OpenStreamCallback callback) { +#if BUILDFLAG(IS_ANDROID) + TRACE_EVENT0("fonts", "FontServiceApp::OpenStreamFromName"); + + base::File empty_file; + + base::FilePath local_install_path; + if (!base::PathService::Get(component_updater::DIR_COMPONENT_USER, &local_install_path)) { + std::move(callback).Run(std::move(empty_file)); + return; + } + local_install_path = local_install_path + .Append("fonts") + .Append("1.0.0") + .AppendASCII(name); + + if (!base::PathExists(local_install_path)) { + LOG(ERROR) << "System font " << local_install_path << " not found"; + std::move(callback).Run(std::move(empty_file)); + return; + } + + base::File font_file(local_install_path, base::File::FLAG_OPEN | base::File::FLAG_READ); + std::move(callback).Run(std::move(font_file)); +#endif +} + void FontServiceApp::FallbackFontForCharacter( uint32_t character, const std::string& locale, FallbackFontForCharacterCallback callback) { TRACE_EVENT0("fonts", "FontServiceApp::FallbackFontForCharacter"); +#if BUILDFLAG(IS_ANDROID) + std::move(callback).Run(nullptr, "", false, false); +#else gfx::FallbackFontData fallback_font; if (gfx::GetFallbackFontForChar(character, locale, &fallback_font)) { size_t index = FindOrAddPath(fallback_font.filepath); @@ -195,6 +236,7 @@ void FontServiceApp::FallbackFontForCharacter( } else { std::move(callback).Run(nullptr, "", false, false); } +#endif } void FontServiceApp::FontRenderStyleForStrike( @@ -238,6 +280,9 @@ void FontServiceApp::MatchFontByPostscriptNameOrFullFontName( TRACE_EVENT0("fonts", "FontServiceApp::MatchFontByPostscriptNameOrFullFontName"); +#if BUILDFLAG(IS_ANDROID) + std::move(callback).Run(nullptr); +#else std::optional match_result = FontConfigLocalMatching::FindFontByPostscriptNameOrFullFontName(family); if (match_result) { @@ -249,6 +294,7 @@ void FontServiceApp::MatchFontByPostscriptNameOrFullFontName( return; } std::move(callback).Run(nullptr); +#endif } #if BUILDFLAG(ENABLE_PDF) diff --git a/components/services/font/font_service_app.h b/components/services/font/font_service_app.h --- a/components/services/font/font_service_app.h +++ b/components/services/font/font_service_app.h @@ -36,6 +36,7 @@ class FontServiceApp : public mojom::FontService { mojom::TypefaceStylePtr requested_style, MatchFamilyNameCallback callback) override; void OpenStream(uint32_t id_number, OpenStreamCallback callback) override; + void OpenStreamFromName(const std::string& name, OpenStreamCallback callback) override; void FallbackFontForCharacter( uint32_t character, const std::string& locale, diff --git a/components/services/font/public/cpp/font_loader.cc b/components/services/font/public/cpp/font_loader.cc --- a/components/services/font/public/cpp/font_loader.cc +++ b/components/services/font/public/cpp/font_loader.cc @@ -82,6 +82,17 @@ SkStreamAsset* FontLoader::openStream(const FontIdentity& identity) { } } +SkStreamAsset* FontLoader::openStreamFromName(const char* filename) { + scoped_refptr mapped_font_file = + thread_->OpenStreamFromFile(filename); + if (!mapped_font_file) + return nullptr; + + // Get notified with |mapped_font_file| is destroyed. + mapped_font_file->set_observer(this); + return mapped_font_file->CreateMemoryStream(); +} + sk_sp FontLoader::makeTypeface(const FontIdentity& identity, sk_sp mgr) { TRACE_EVENT0("fonts", "FontServiceThread::makeTypeface"); diff --git a/components/services/font/public/cpp/font_loader.h b/components/services/font/public/cpp/font_loader.h --- a/components/services/font/public/cpp/font_loader.h +++ b/components/services/font/public/cpp/font_loader.h @@ -56,6 +56,7 @@ class FontLoader : public SkFontConfigInterface, SkFontStyle* out_style) override; SkStreamAsset* openStream(const FontIdentity& identity) override LOCKS_EXCLUDED(mapped_font_files_lock_); + SkStreamAsset* openStreamFromName(const char* filename) override; sk_sp makeTypeface(const FontIdentity& identity, sk_sp mgr) override LOCKS_EXCLUDED(typeface_cache_lock_); diff --git a/components/services/font/public/cpp/font_service_thread.cc b/components/services/font/public/cpp/font_service_thread.cc --- a/components/services/font/public/cpp/font_service_thread.cc +++ b/components/services/font/public/cpp/font_service_thread.cc @@ -258,6 +258,54 @@ void FontServiceThread::OpenStreamImpl(base::WaitableEvent* done_event, done_event, output_file)); } +scoped_refptr FontServiceThread::OpenStreamFromFile( + const std::string& filename) { + DCHECK(!task_runner_->RunsTasksInCurrentSequence()); + + base::ElapsedTimer timer; + + base::File stream_file; + // This proxies to the other thread, which proxies to mojo. Only on the + // reply from mojo do we return from this. + base::WaitableEvent done_event; + task_runner_->PostTask( + FROM_HERE, base::BindOnce(&FontServiceThread::OpenStreamFromFileImpl, this, + &done_event, &stream_file, filename)); + done_event.Wait(); + + base::UmaHistogramMicrosecondsTimes( + "Blink.Fonts.FontServiceThread.OpenStreamTime", timer.Elapsed()); + + if (!stream_file.IsValid()) { + // The font-service may have been killed. + return nullptr; + } + + // Converts the file to out internal type. + scoped_refptr mapped_font_file = + new MappedFontFile(0); + if (!mapped_font_file->Initialize(std::move(stream_file))) + return nullptr; + + return mapped_font_file; +} + +void FontServiceThread::OpenStreamFromFileImpl(base::WaitableEvent* done_event, + base::File* output_file, + const std::string& file) { + DCHECK(task_runner_->RunsTasksInCurrentSequence()); + + if (!font_service_.is_connected()) { + done_event->Signal(); + return; + } + + pending_waitable_events_.insert(done_event); + font_service_->OpenStreamFromName( + file, base::BindOnce(&FontServiceThread::OnOpenStreamComplete, this, + done_event, output_file)); +} + void FontServiceThread::OnOpenStreamComplete(base::WaitableEvent* done_event, base::File* output_file, base::File file) { diff --git a/components/services/font/public/cpp/font_service_thread.h b/components/services/font/public/cpp/font_service_thread.h --- a/components/services/font/public/cpp/font_service_thread.h +++ b/components/services/font/public/cpp/font_service_thread.h @@ -57,6 +57,8 @@ class FontServiceThread : public base::RefCountedThreadSafe { SkFontStyle* out_style); scoped_refptr OpenStream( const SkFontConfigInterface::FontIdentity& identity); + scoped_refptr OpenStreamFromFile( + const std::string& filename); bool FallbackFontForCharacter( uint32_t character, @@ -121,6 +123,9 @@ class FontServiceThread : public base::RefCountedThreadSafe { void OpenStreamImpl(base::WaitableEvent* done_event, base::File* output_file, const uint32_t id_number); + void OpenStreamFromFileImpl(base::WaitableEvent* done_event, + base::File* output_file, + const std::string& filename); void OnOpenStreamComplete(base::WaitableEvent* done_event, base::File* output_file, base::File file); diff --git a/components/services/font/public/mojom/font_service.mojom b/components/services/font/public/mojom/font_service.mojom --- a/components/services/font/public/mojom/font_service.mojom +++ b/components/services/font/public/mojom/font_service.mojom @@ -66,6 +66,8 @@ interface FontService { // Returns a handle to the raw font specified by |id_number|. OpenStream(uint32 id_number) => (mojo_base.mojom.ReadOnlyFile? font_handle); + OpenStreamFromName(string family_name) => (mojo_base.mojom.ReadOnlyFile? font_handle); + // Returns a fallback FontIdentity and Typeface style for the given character // and locale. If no fallback font can be found, returns a null identity. FallbackFontForCharacter(uint32 character, string locale) diff --git a/content/browser/BUILD.gn b/content/browser/BUILD.gn --- a/content/browser/BUILD.gn +++ b/content/browser/BUILD.gn @@ -2648,6 +2648,17 @@ source_set("browser") { ] } + if (is_android) { + sources += [ + "font_service.cc", + "font_service.h", + ] + + deps += [ "//pdf:buildflags" ] + + public_deps += [ "//components/services/font/public/mojom" ] + } + if (is_linux || is_chromeos) { sources -= [ "file_system_access/file_path_watcher/file_path_watcher_stub.cc" ] @@ -2694,6 +2705,13 @@ source_set("browser") { deps += [ "//components/services/font_data:lib" ] } + if (is_android) { + deps += [ + "//components/services/font:lib", + ] + public_deps += [ "//components/services/font/public/mojom" ] + } + if (allow_oop_video_decoder) { sources += [ "media/oop_video_decoder_factory.cc" ] deps += [ "//media/mojo/mojom" ] diff --git a/content/browser/renderer_host/render_process_host_impl_receiver_bindings.cc b/content/browser/renderer_host/render_process_host_impl_receiver_bindings.cc --- a/content/browser/renderer_host/render_process_host_impl_receiver_bindings.cc +++ b/content/browser/renderer_host/render_process_host_impl_receiver_bindings.cc @@ -56,6 +56,11 @@ #include "content/browser/renderer_host/p2p/socket_dispatcher_host.h" #endif // BUILDFLAG(IS_P2P_ENABLED) +#if BUILDFLAG(IS_ANDROID) +#include "components/services/font/public/mojom/font_service.mojom.h" // nogncheck +#include "content/browser/font_service.h" // nogncheck +#endif + #if BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS) #include "components/services/font/public/mojom/font_service.mojom.h" // nogncheck #include "content/browser/font_service.h" // nogncheck @@ -356,6 +361,13 @@ void RenderProcessHostImpl::IOThreadHostImpl::BindHostReceiver( } #endif +#if BUILDFLAG(IS_ANDROID) + if (auto font_receiver = receiver.As()) { + ConnectToFontService(std::move(font_receiver)); + return; + } +#endif + #if BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS) if (auto font_receiver = receiver.As()) { ConnectToFontService(std::move(font_receiver)); diff --git a/content/child/BUILD.gn b/content/child/BUILD.gn --- a/content/child/BUILD.gn +++ b/content/child/BUILD.gn @@ -137,6 +137,13 @@ target(link_target_type, "child") { ] } + if (is_android) { + deps += [ + "//components/services/font/public/cpp", + "//components/services/font/public/mojom", + ] + } + if (is_win) { sources += [ "child_process_sandbox_support_impl_win.cc", diff --git a/content/renderer/BUILD.gn b/content/renderer/BUILD.gn --- a/content/renderer/BUILD.gn +++ b/content/renderer/BUILD.gn @@ -351,6 +351,10 @@ target(link_target_type, "renderer") { deps += [ "//services/screen_ai/public/mojom" ] } + if (is_android) { + deps += [ "//components/services/font/public/cpp" ] + } + if (is_linux || is_chromeos) { deps += [ "//components/services/font/public/cpp" ] } diff --git a/content/renderer/renderer_blink_platform_impl.cc b/content/renderer/renderer_blink_platform_impl.cc --- a/content/renderer/renderer_blink_platform_impl.cc +++ b/content/renderer/renderer_blink_platform_impl.cc @@ -141,6 +141,23 @@ #include "content/common/android/sync_compositor_statics.h" #endif +#if BUILDFLAG(IS_ANDROID) +#include "components/services/font/public/mojom/font_service.mojom.h" // nogncheck +#include "components/services/font/public/cpp/font_loader.h" +#include "content/browser/font_service.h" // nogncheck + +#include "base/path_service.h" +#include "base/base_paths_android.h" +#include "base/file_descriptor_store.h" +#include "base/strings/string_number_conversions.h" +#include "base/files/file_path.h" +#include "content/public/common/content_descriptor_keys.h" +#include "skia/ext/font_utils.h" +#include "third_party/skia/include/core/SkFontMgr.h" +#include "third_party/skia/include/ports/SkFontMgr_android.h" +#include "third_party/blink/public/platform/web_font_render_style.h" +#endif + using blink::Platform; using blink::WebAudioDevice; using blink::WebAudioLatencyHint; @@ -191,6 +208,37 @@ viz::command_buffer_metrics::ContextType ToVizContextType( NOTREACHED(); } +#if BUILDFLAG(IS_ANDROID) +void InitializeCustomFonts() { + if (!base::FeatureList::IsEnabled(blink::features::kAndroidFontsFingerprintingMitigation)) { + return; + } + std::string font_config = "cromite_fonts.xml"; + sk_sp fci(SkFontConfigInterface::RefGlobal()); + SkStreamAsset* asset = fci->openStreamFromName(font_config.c_str()); + if (!asset) { + LOG(ERROR) << "Unable to activate custom fonts."; + return; + } + + std::string android_fonts_dir = "use_fd"; + + auto custom = std::make_unique(); + custom->fSystemFontUse = + SkFontMgr_Android_CustomFonts::SystemFontUse::kOnlyCustom; + custom->fBasePath = android_fonts_dir.c_str(); + custom->fFontsXml = font_config.c_str(); + custom->fFallbackFontsXml = font_config.c_str(); + // If set to true the SkFontMgr will acquire all requisite + // system IO resources on initialization. + custom->fIsolated = false; + + sk_sp skia_font_manager = + SkFontMgr_New_Android(std::move(custom)); + skia::OverrideDefaultSkFontMgr(std::move(skia_font_manager)); +} +#endif + } // namespace //------------------------------------------------------------------------------ @@ -204,18 +252,21 @@ RendererBlinkPlatformImpl::RendererBlinkPlatformImpl( is_locked_to_site_(false), main_thread_scheduler_(main_thread_scheduler), next_frame_sink_id_(uint32_t{std::numeric_limits::max()} + 1) { -#if BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS) +#if BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS) || BUILDFLAG(IS_ANDROID) sk_sp font_loader; #endif // RenderThread may not exist in some tests. if (RenderThreadImpl::current()) { -#if BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS) +#if BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS) || BUILDFLAG(IS_ANDROID) mojo::PendingRemote font_service; RenderThreadImpl::current()->BindHostReceiver( font_service.InitWithNewPipeAndPassReceiver()); font_loader = sk_make_sp(std::move(font_service)); SkFontConfigInterface::SetGlobal(font_loader); +#if BUILDFLAG(IS_ANDROID) + InitializeCustomFonts(); +#endif #endif #if BUILDFLAG(IS_WIN) || BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS) diff --git a/content/renderer/renderer_main.cc b/content/renderer/renderer_main.cc --- a/content/renderer/renderer_main.cc +++ b/content/renderer/renderer_main.cc @@ -183,8 +183,6 @@ int RendererMain(MainFunctionParams parameters) { // On Linux, Windows, and ChromeOS, the font manager is overridden or // specially handled in RendererBlinkPlatformImpl(). On other platforms, // initialise the default one on a thread pool, to avoid blocking on it later. - base::ThreadPool::PostTask(FROM_HERE, - base::BindOnce([] { skia::DefaultFontMgr(); })); #endif // This function allows pausing execution using the --renderer-startup-dialog diff --git a/cromite_flags/chrome/browser/about_flags_cc/Android-fonts-fingerprinting-mitigation.inc b/cromite_flags/chrome/browser/about_flags_cc/Android-fonts-fingerprinting-mitigation.inc new file mode 100644 --- /dev/null +++ b/cromite_flags/chrome/browser/about_flags_cc/Android-fonts-fingerprinting-mitigation.inc @@ -0,0 +1,12 @@ +#if BUILDFLAG(IS_ANDROID) + +#ifdef FLAG_SECTION + + {"android-fonts-fingerprinting-mitigation", + "Android fonts fingerprinting mitigation", + "Replaces all system fonts with the same for all devices.", kOsAndroid, + FEATURE_VALUE_TYPE(blink::features::kAndroidFontsFingerprintingMitigation)}, + +#endif + +#endif diff --git a/cromite_flags/third_party/blink/common/features_cc/Android-fonts-fingerprinting-mitigation.inc b/cromite_flags/third_party/blink/common/features_cc/Android-fonts-fingerprinting-mitigation.inc new file mode 100644 --- /dev/null +++ b/cromite_flags/third_party/blink/common/features_cc/Android-fonts-fingerprinting-mitigation.inc @@ -0,0 +1,7 @@ +#if BUILDFLAG(IS_ANDROID) + +CROMITE_FEATURE(kAndroidFontsFingerprintingMitigation, + "AndroidFontsFingerprintingMitigation", + base::FEATURE_ENABLED_BY_DEFAULT); + +#endif diff --git a/cromite_flags/third_party/blink/common/features_h/Android-fonts-fingerprinting-mitigation.inc b/cromite_flags/third_party/blink/common/features_h/Android-fonts-fingerprinting-mitigation.inc new file mode 100644 --- /dev/null +++ b/cromite_flags/third_party/blink/common/features_h/Android-fonts-fingerprinting-mitigation.inc @@ -0,0 +1,5 @@ +#if BUILDFLAG(IS_ANDROID) + +BLINK_COMMON_EXPORT BASE_DECLARE_FEATURE(kAndroidFontsFingerprintingMitigation); + +#endif diff --git a/skia/BUILD.gn b/skia/BUILD.gn --- a/skia/BUILD.gn +++ b/skia/BUILD.gn @@ -446,6 +446,18 @@ component("skia") { sources += skia_ports_fci_sources } + if (is_android) { + sources += [ + "//third_party/skia/src/ports/SkFontConfigInterface.cpp", + "//third_party/skia/src/ports/SkFontMgr_FontConfigInterface.cpp", + ] + public += [ + "include/ports/SkFontConfigInterface.h", + "include/ports/SkFontMgr_FontConfigInterface.h", + ] + defines += [ "CROMITE_IS_ANDROID" ] + } + if (is_linux || is_chromeos || is_android) { # Retain the files for the SkFontMgr_Android on linux to emulate android # fonts. See content/zygote/zygote_main_linux.cc diff --git a/skia/ext/font_utils.cc b/skia/ext/font_utils.cc --- a/skia/ext/font_utils.cc +++ b/skia/ext/font_utils.cc @@ -60,6 +60,7 @@ SkFontMgr* g_fontmgr_override = nullptr; #if BUILDFLAG(IS_ANDROID) // https://crbug.com/461659286 Failure to create any font causes crash. BASE_FEATURE(kUseAndroidNDKFontAPI, base::FEATURE_DISABLED_BY_DEFAULT); +SET_CROMITE_FEATURE_DISABLED(kUseAndroidNDKFontAPI); #endif } // namespace diff --git a/third_party/freetype/include/freetype-custom/freetype/config/ftoption.h b/third_party/freetype/include/freetype-custom/freetype/config/ftoption.h --- a/third_party/freetype/include/freetype-custom/freetype/config/ftoption.h +++ b/third_party/freetype/include/freetype-custom/freetype/config/ftoption.h @@ -607,7 +607,7 @@ FT_BEGIN_HEADER * module (namely TrueType~& OpenType). */ /* Not needed since PDFs do not support any of the color font formats. */ -/* #define TT_CONFIG_OPTION_COLOR_LAYERS */ +#define TT_CONFIG_OPTION_COLOR_LAYERS /************************************************************************** diff --git a/third_party/skia/include/ports/SkFontConfigInterface.h b/third_party/skia/include/ports/SkFontConfigInterface.h --- a/third_party/skia/include/ports/SkFontConfigInterface.h +++ b/third_party/skia/include/ports/SkFontConfigInterface.h @@ -91,6 +91,8 @@ public: */ virtual SkStreamAsset* openStream(const FontIdentity&) = 0; + virtual SkStreamAsset* openStreamFromName(const char* filename) = 0; + /** * Return an SkTypeface for the given FontIdentity. * diff --git a/third_party/skia/include/ports/SkFontMgr_android.h b/third_party/skia/include/ports/SkFontMgr_android.h --- a/third_party/skia/include/ports/SkFontMgr_android.h +++ b/third_party/skia/include/ports/SkFontMgr_android.h @@ -9,6 +9,11 @@ #define SkFontMgr_android_DEFINED #include "include/core/SkRefCnt.h" +#include "include/core/SkStream.h" +#include "src/core/SkTHash.h" + +#include "include/ports/SkFontConfigInterface.h" +#include "include/ports/SkFontMgr_FontConfigInterface.h" #include @@ -40,9 +45,44 @@ struct SkFontMgr_Android_CustomFonts { * system IO resources on initialization. */ bool fIsolated; + + struct SkFontMgr_Android_CustomFonts_MappedData { + int fd; + int64_t offset; + size_t size; + }; + skia_private::THashMap platform_file_map; + + void add_platform_file(std::string key, int fd, int64_t offset, size_t size) { + SkFontMgr_Android_CustomFonts_MappedData data = {fd, offset, size}; + platform_file_map.set(key, std::move(data)); + } + + std::unique_ptr getPlatformFile(const char* filename) const { + // SkDebugf("-- open platform file '%s'\n", filename); + sk_sp fci(SkFontConfigInterface::RefGlobal()); + SkStreamAsset* asset = fci->openStreamFromName(filename); + if (asset) { + return std::unique_ptr(asset); + } + + const auto* it = platform_file_map.find(filename); + if (!it) { + return nullptr; + } + auto whole_data = SkData::MakeFromFD(it->fd); + auto data = SkData::MakeSubset(whole_data.get(), it->offset, it->size); + if (!data) { + return nullptr; + } + return std::unique_ptr(new SkMemoryStream(std::move(data))); + } }; /** Create a font manager for Android. If 'custom' is NULL, use only system fonts. */ -SK_API sk_sp SkFontMgr_New_Android(const SkFontMgr_Android_CustomFonts* custom, +SK_API sk_sp SkFontMgr_New_Android(std::unique_ptr custom); + +SK_API sk_sp SkFontMgr_New_Android(std::unique_ptr custom, std::unique_ptr scanner); #endif // SkFontMgr_android_DEFINED diff --git a/third_party/skia/src/ports/SkFontConfigInterface.cpp b/third_party/skia/src/ports/SkFontConfigInterface.cpp --- a/third_party/skia/src/ports/SkFontConfigInterface.cpp +++ b/third_party/skia/src/ports/SkFontConfigInterface.cpp @@ -22,7 +22,12 @@ sk_sp SkFontConfigInterface::RefGlobal() { if (gFontConfigInterface) { return sk_ref_sp(gFontConfigInterface); } +#if defined(CROMITE_IS_ANDROID) + SkASSERT(false); + return nullptr; +#else return sk_ref_sp(SkFontConfigInterface::GetSingletonDirectInterface()); +#endif } void SkFontConfigInterface::SetGlobal(sk_sp fc) { diff --git a/third_party/skia/src/ports/SkFontConfigInterface_direct.cpp b/third_party/skia/src/ports/SkFontConfigInterface_direct.cpp --- a/third_party/skia/src/ports/SkFontConfigInterface_direct.cpp +++ b/third_party/skia/src/ports/SkFontConfigInterface_direct.cpp @@ -715,3 +715,8 @@ bool SkFontConfigInterfaceDirect::matchFamilyName(const char familyName[], SkStreamAsset* SkFontConfigInterfaceDirect::openStream(const FontIdentity& identity) { return SkStream::MakeFromFile(identity.fString.c_str()).release(); } + +SkStreamAsset* SkFontConfigInterfaceDirect::openStreamFromName(const char* filename) { + SkASSERT(false); + return nullptr; +} diff --git a/third_party/skia/src/ports/SkFontConfigInterface_direct.h b/third_party/skia/src/ports/SkFontConfigInterface_direct.h --- a/third_party/skia/src/ports/SkFontConfigInterface_direct.h +++ b/third_party/skia/src/ports/SkFontConfigInterface_direct.h @@ -29,6 +29,7 @@ public: SkFontStyle* outStyle) override; SkStreamAsset* openStream(const FontIdentity&) override; + SkStreamAsset* openStreamFromName(const char* filename) override; protected: virtual bool isAccessible(const char* filename); diff --git a/third_party/skia/src/ports/SkFontMgr_android.cpp b/third_party/skia/src/ports/SkFontMgr_android.cpp --- a/third_party/skia/src/ports/SkFontMgr_android.cpp +++ b/third_party/skia/src/ports/SkFontMgr_android.cpp @@ -16,6 +16,7 @@ #include "include/core/SkStream.h" #include "include/core/SkString.h" #include "include/ports/SkFontMgr_android.h" +#include "include/ports/SkFontScanner_FreeType.h" #include "include/private/base/SkFixed.h" #include "include/private/base/SkTArray.h" #include "include/private/base/SkTDArray.h" @@ -27,6 +28,7 @@ #include "src/core/SkTypefaceCache.h" #include "src/ports/SkFontMgr_android_parser.h" #include "src/ports/SkTypeface_proxy.h" +#include "src/ports/SkFontScanner_FreeType_priv.h" #include #include @@ -37,7 +39,95 @@ class SkData; namespace { -[[maybe_unused]] static inline const constexpr bool kSkFontMgrVerbose = false; +static inline const constexpr bool kSkFontMgrVerbose = true; + +#include "SkFontMgr_android_data.cpp" + +class SkTypeface_AndroidSystemCustom : public SkTypeface_FreeType { +public: + SkTypeface_AndroidSystemCustom(const SkString& pathName, + int index, + const SkFixed* axes, int axesCount, + const SkFontStyle& style, + bool isFixedPitch, + const SkString& familyName, + const TArray& lang, + FontVariant variantStyle, + const SkFontMgr_Android_CustomFonts* custom) + : INHERITED(style, isFixedPitch) + , fPathName(pathName) + , fFamilyName(familyName) + , fIndex(index) + , fAxes(axes, axesCount) + , fLang(lang) + , fVariantStyle(variantStyle) + , fFile(nullptr) + , custom_(custom) {} + + std::unique_ptr makeStream() const { + if (custom_) { + return custom_->getPlatformFile(fPathName.c_str()); + } + if (fFile) { + sk_sp data(SkData::MakeFromFILE(fFile)); + return data ? std::make_unique(std::move(data)) : nullptr; + } + return SkStream::MakeFromFile(fPathName.c_str()); + } + + void onGetFamilyName(SkString* familyName) const override { + *familyName = fFamilyName; + } + + void onGetFontDescriptor(SkFontDescriptor* desc, bool* serialize) const override { + SkASSERT(desc); + SkASSERT(serialize); + desc->setFamilyName(fFamilyName.c_str()); + desc->setStyle(this->fontStyle()); + desc->setFactoryId(SkTypeface_FreeType::FactoryId); + *serialize = false; + } + + std::unique_ptr onOpenStream(int* ttcIndex) const override { + *ttcIndex = fIndex; + return this->makeStream(); + } + + std::unique_ptr onMakeFontData() const override { + return std::make_unique( + this->makeStream(), fIndex, 0, fAxes.begin(), fAxes.size(), nullptr, 0); + } + + sk_sp onMakeClone(const SkFontArguments& args) const override { + SkFontStyle style = this->fontStyle(); + std::unique_ptr data = this->cloneFontData(args, &style); + if (!data) { + SkASSERT(false); + return nullptr; + } + return sk_make_sp( + fPathName, + fIndex, + data->getAxis(), + data->getAxisCount(), + style, + this->isFixedPitch(), + fFamilyName, + fLang, + fVariantStyle, custom_); + } + + const SkString fPathName; + const SkString fFamilyName; + int fIndex; + const STArray<4, SkFixed, true> fAxes; + const STArray<4, SkLanguage, true> fLang; + const FontVariant fVariantStyle; + SkAutoTCallVProc fFile; + const SkFontMgr_Android_CustomFonts* custom_; + + using INHERITED = SkTypeface_FreeType; +}; class SkTypeface_AndroidSystem : public SkTypeface_proxy { public: @@ -112,7 +202,8 @@ using StreamForPathCache = skia_private::THashMap* streamPtr = streamForPath.find(pathName); - if (!streamPtr) { - streamPtr = streamForPath.set(pathName, SkStream::MakeFromFile(pathName.c_str())); - } - if (!*streamPtr) { - SkDEBUGF("Requested font file %s cannot be opened.\n", pathName.c_str()); - continue; - } - std::unique_ptr stream = (*streamPtr)->duplicate(); - if (!stream) { - SkDEBUGF("Requested font file %s could not be duplicated.\n", pathName.c_str()); - continue; + const int ttcIndex = fontFile.fIndex; + SkString familyName; + SkFontStyle fontStyle; + bool isFixedWidth; + SkFontScanner::AxisDefinitions axisDefinitions; + SkFontScanner::VariationPosition current; + SkFontArguments::VariationPosition position; + + std::unique_ptr stream; + if (!custom && !fontFile.fFileName.startsWith('#')) { + std::unique_ptr* streamPtr = streamForPath.find(pathName); + if (!streamPtr) { + streamPtr = streamForPath.set(pathName, SkStream::MakeFromFile(pathName.c_str())); + } + if (!*streamPtr) { + SkDEBUGF("Requested font file %s cannot be opened.\n", pathName.c_str()); + continue; + } + stream = (*streamPtr)->duplicate(); + if (!stream) { + SkDEBUGF("Requested font file %s could not be duplicated.\n", pathName.c_str()); + continue; + } + } else if (custom) { + use_custom = true; + if (!GetFontData(fontFile.fFileName, + &familyName, &fontStyle, &isFixedWidth, &axisDefinitions)) { + stream = custom->getPlatformFile(fontFile.fFileName.c_str()); + } + pathName = fontFile.fFileName; } - SkFontArguments::VariationPosition position = { - fontFile.fVariationDesignPosition.begin(), - fontFile.fVariationDesignPosition.size() + sk_sp proxy; + position = { + fontFile.fVariationDesignPosition.begin(), + fontFile.fVariationDesignPosition.size() }; // TODO: this creates the proxy with the given stream, so always cacheFontFiles. - auto proxy = scanner->MakeFromStream( - std::move(stream), - SkFontArguments().setCollectionIndex(fontFile.fIndex) - .setVariationDesignPosition(position)); - if (!proxy) { - SkDEBUGF("Requested font file %s does not have valid font data.\n", - pathName.c_str()); - continue; + if (!use_custom || stream) { + proxy = scanner->MakeFromStream( + std::move(stream), + SkFontArguments().setCollectionIndex(fontFile.fIndex) + .setVariationDesignPosition(position)); + if (!proxy) { + SkDEBUGF("Requested font file %s does not have valid font data.\n", + pathName.c_str()); + continue; + } } uint32_t variant = family.fVariant; @@ -163,13 +276,25 @@ public: // The first specified family name overrides the family name found in the font. // TODO: SkTypeface_AndroidSystem::onCreateFamilyNameIterator should return // all of the specified family names in addition to the names found in the font. - SkString familyName; - proxy->getFamilyName(&familyName); - if (cannonicalFamilyName != nullptr) { - familyName = *cannonicalFamilyName; - } + AutoSTMalloc<4, SkFixed> axisValues(axisDefinitions.size()); - SkFontStyle fontStyle = proxy->fontStyle(); + if (!use_custom || stream) { + proxy->getFamilyName(&familyName); + if (cannonicalFamilyName != nullptr) { + familyName = *cannonicalFamilyName; + } + fontStyle = proxy->fontStyle(); + isFixedWidth = proxy->isFixedPitch(); + } else { + variant = kCompact_FontVariant | kElegant_FontVariant; + SkFontScanner_FreeType::computeAxisValues( + axisDefinitions, + SkFontArguments::VariationPosition{current.data(), current.size()}, + position, axisValues, familyName, &fontStyle); + if (cannonicalFamilyName != nullptr) { + familyName = *cannonicalFamilyName; + } + } int weight = fontFile.fWeight != 0 ? fontFile.fWeight : fontStyle.weight(); SkFontStyle::Slant slant = fontStyle.slant(); switch (fontFile.fStyle) { @@ -180,6 +305,19 @@ public: } fontStyle = SkFontStyle(weight, fontStyle.width(), slant); + if (use_custom) { + fStyles.push_back().reset( + new SkTypeface_AndroidSystemCustom(pathName, + fontFile.fIndex, + axisValues.get(), axisDefinitions.size(), + fontStyle, + isFixedWidth, + familyName, + family.fLanguages, + variant, + custom)); + continue; + } fStyles.push_back( SkTypeface_AndroidSystem::Make(proxy, fontStyle, proxy->isFixedPitch(), @@ -208,15 +346,18 @@ public: return fStyles[index]; } - sk_sp matchAStyle(const SkFontStyle& pattern) { + sk_sp matchCromiteStyle(const SkFontStyle& pattern) { + return sk_sp_static_cast(this->matchStyleCSS3(pattern)); + } + sk_sp matchAndroidStyle(const SkFontStyle& pattern) { return sk_sp_static_cast(this->matchStyleCSS3(pattern)); } sk_sp matchStyle(const SkFontStyle& pattern) override { - return this->matchAStyle(pattern); + return this->matchStyleCSS3(pattern); } private: - TArray> fStyles; + TArray> fStyles; SkString fFallbackFor; friend struct NameToFamily; @@ -237,24 +378,26 @@ struct NameToFamily { class SkFontMgr_Android : public SkFontMgr { public: - SkFontMgr_Android(const SkFontMgr_Android_CustomFonts* custom, + SkFontMgr_Android(std::unique_ptr custom_in, std::unique_ptr scanner) : fScanner(std::move(scanner)) { + custom_ = std::move(custom_in); + auto* custom = custom_.get(); std::vector> families; if (custom && SkFontMgr_Android_CustomFonts::kPreferSystem != custom->fSystemFontUse) { SkString base(custom->fBasePath); SkFontMgr_Android_Parser::GetCustomFontFamilies( - families, base, custom->fFontsXml, custom->fFallbackFontsXml); + families, base, custom, custom->fFontsXml, custom->fFallbackFontsXml); } if (!custom || (custom && SkFontMgr_Android_CustomFonts::kOnlyCustom != custom->fSystemFontUse)) { - SkFontMgr_Android_Parser::GetSystemFontFamilies(families); + SkFontMgr_Android_Parser::GetSystemFontFamilies(families, custom); } if (custom && SkFontMgr_Android_CustomFonts::kPreferSystem == custom->fSystemFontUse) { SkString base(custom->fBasePath); SkFontMgr_Android_Parser::GetCustomFontFamilies( - families, base, custom->fFontsXml, custom->fFallbackFontsXml); + families, base, custom, custom->fFontsXml, custom->fFallbackFontsXml); } this->buildNameToFamilyMap(families, custom ? custom->fIsolated : false); this->findDefaultStyleSet(); @@ -309,33 +452,53 @@ protected: } using Matcher = bool (*)(const SkString& familyName, const NameToFamily&); - static sk_sp find_family_style_character( + sk_sp find_family_style_character( const SkString& familyName, const TArray& nameToFamilyMap, const SkFontStyle& style, bool elegant, const SkString& langTag, SkUnichar character, - Matcher matcher) + Matcher matcher) const { for (auto&& nameToFamily : nameToFamilyMap) { if (!matcher(familyName, nameToFamily)) { continue; } - sk_sp face(nameToFamily.styleSet->matchAStyle(style)); + if (custom_) { + sk_sp face(nameToFamily.styleSet->matchCromiteStyle(style)); + + if (!langTag.isEmpty() && + std::none_of(face->fLang.begin(), face->fLang.end(), [&](const SkLanguage& lang){ + return lang.getTag().startsWith(langTag.c_str()); + })) + { + continue; + } - if (!langTag.isEmpty() && - std::none_of(face->fLang.begin(), face->fLang.end(), [&](const SkLanguage& lang){ - return lang.getTag().startsWith(langTag.c_str()); - })) - { - continue; - } + if (SkToBool(face->fVariantStyle & kElegant_FontVariant) != elegant) { + continue; + } - if (SkToBool(face->fVariantStyle & kElegant_FontVariant) != elegant) { - continue; - } + if (face->unicharToGlyph(character) != 0) { + return face; + } + } else { + sk_sp face(nameToFamily.styleSet->matchAndroidStyle(style)); + + if (!langTag.isEmpty() && + std::none_of(face->fLang.begin(), face->fLang.end(), [&](const SkLanguage& lang){ + return lang.getTag().startsWith(langTag.c_str()); + })) + { + continue; + } + + if (SkToBool(face->fVariantStyle & kElegant_FontVariant) != elegant) { + continue; + } - if (face->unicharToGlyph(character) != 0) { - return face; + if (face->unicharToGlyph(character) != 0) { + return face; + } } } return nullptr; @@ -360,9 +523,9 @@ protected: auto find = [this, &style, &character](const SkString& familyName, const SkString& lang, - bool elegant) -> sk_sp + bool elegant) -> sk_sp { - sk_sp matchingTypeface; + sk_sp matchingTypeface; if (!familyName.isEmpty()) { matchingTypeface = find_family_style_character( familyName, fNameToFamilyMap, style, elegant, lang, character, @@ -410,7 +573,7 @@ protected: }; - sk_sp matchingTypeface; + sk_sp matchingTypeface; // If familyName is empty, don't look through everything twice. SkString familyNames[2] = { SkString(familyName), SkString() }; size_t familyNamesCount = familyNames[0].isEmpty() ? 1 : 2; @@ -475,6 +638,7 @@ protected: private: std::unique_ptr fScanner; + std::unique_ptr custom_; TArray> fStyleSets; sk_sp fDefaultStyleSet; @@ -496,7 +660,7 @@ private: } sk_sp newSet = - sk_make_sp(family, fScanner.get(), isolated, streamForPath); + sk_make_sp(family, fScanner.get(), isolated, streamForPath, custom_.get()); if (0 == newSet->count()) { return; } @@ -542,7 +706,11 @@ static char const * const gSystemFontUseStrings[] = { } // namespace -sk_sp SkFontMgr_New_Android(const SkFontMgr_Android_CustomFonts* custom, +sk_sp SkFontMgr_New_Android(std::unique_ptr custom) { + return SkFontMgr_New_Android(std::move(custom), SkFontScanner_Make_FreeType()); +} + +sk_sp SkFontMgr_New_Android(std::unique_ptr custom, std::unique_ptr scanner) { if (custom) { SkASSERT(0 <= custom->fSystemFontUse); @@ -555,5 +723,5 @@ sk_sp SkFontMgr_New_Android(const SkFontMgr_Android_CustomFonts* cust custom->fFallbackFontsXml); } } - return sk_make_sp(custom, std::move(scanner)); + return sk_make_sp(std::move(custom), std::move(scanner)); } diff --git a/third_party/skia/src/ports/SkFontMgr_android_data.cpp b/third_party/skia/src/ports/SkFontMgr_android_data.cpp new file mode 100644 --- /dev/null +++ b/third_party/skia/src/ports/SkFontMgr_android_data.cpp @@ -0,0 +1,1641 @@ +// AUTOGENERATED +// +// SkString dumpAxis("axis|"); +// dumpAxis.appendS32(axisDefinitions.size()); +// dumpAxis.append("|"); +// for (auto& def : axisDefinitions) { +// dumpAxis.appendS32(def.fTag); +// dumpAxis.append("|"); +// dumpAxis.appendScalar(def.fMinimum); +// dumpAxis.append("|"); +// dumpAxis.appendScalar(def.fDefault); +// dumpAxis.append("|"); +// dumpAxis.appendScalar(def.fMaximum); +// dumpAxis.append("|"); +// } +// SkDEBUGF("font file='%s' familyName='%s' width=%d weight=%d slant=%d axisDefinitions=%d isFixedWidth=%d axis=%s\n", +// pathName.c_str(), +// familyName.c_str(), +// style.width(), +// style.weight(), +// style.slant(), +// axisDefinitions.size(), +// (int)isFixedWidth, +// dumpAxis.c_str()); + +bool GetFontData(const SkString& file, + SkString* familyName, + SkFontStyle* style, + bool* isFixedPitch, + SkFontScanner::AxisDefinitions* axes) { + if (file.equals("CarroisGothicSC-Regular.ttf")) { + familyName->set("Carrois Gothic SC"); + *style = SkFontStyle(400, 5, SkFontStyle::kUpright_Slant); + *isFixedPitch = false; + axes->reset(0); + return true; + } + else if (file.equals("ComingSoon.ttf")) { + familyName->set("Coming Soon"); + *style = SkFontStyle(400, 5, SkFontStyle::kUpright_Slant); + *isFixedPitch = false; + axes->reset(0); + return true; + } + else if (file.equals("CutiveMono.ttf")) { + familyName->set("Cutive Mono"); + *style = SkFontStyle(400, 5, SkFontStyle::kUpright_Slant); + *isFixedPitch = true; + axes->reset(0); + return true; + } + else if (file.equals("DancingScript-Bold.ttf")) { + familyName->set("Dancing Script"); + *style = SkFontStyle(700, 5, SkFontStyle::kUpright_Slant); + *isFixedPitch = false; + axes->reset(0); + return true; + } + else if (file.equals("DancingScript-Regular.ttf")) { + familyName->set("Dancing Script"); + *style = SkFontStyle(400, 5, SkFontStyle::kUpright_Slant); + *isFixedPitch = false; + axes->reset(0); + return true; + } + else if (file.equals("DroidSansMono.ttf")) { + familyName->set("Droid Sans Mono"); + *style = SkFontStyle(400, 5, SkFontStyle::kUpright_Slant); + *isFixedPitch = true; + axes->reset(0); + return true; + } + else if (file.equals("NotoColorEmoji.ttf")) { + familyName->set("Noto Color Emoji"); + *style = SkFontStyle(400, 5, SkFontStyle::kUpright_Slant); + *isFixedPitch = false; + axes->reset(0); + return true; + } + else if (file.equals("NotoColorEmojiFlags.ttf")) { + familyName->set("Noto Color Emoji Flags"); + *style = SkFontStyle(400, 5, SkFontStyle::kUpright_Slant); + *isFixedPitch = true; + axes->reset(0); + return true; + } + else if (file.equals("NotoColorEmojiLegacy.ttf")) { + familyName->set("Noto Color Emoji"); + *style = SkFontStyle(400, 5, SkFontStyle::kUpright_Slant); + *isFixedPitch = true; + axes->reset(0); + return true; + } + else if (file.equals("NotoNaskhArabic-Bold.ttf")) { + familyName->set("Noto Naskh Arabic"); + *style = SkFontStyle(700, 5, SkFontStyle::kUpright_Slant); + *isFixedPitch = false; + axes->reset(0); + return true; + } + else if (file.equals("NotoNaskhArabic-Regular.ttf")) { + familyName->set("Noto Naskh Arabic"); + *style = SkFontStyle(400, 5, SkFontStyle::kUpright_Slant); + *isFixedPitch = false; + axes->reset(0); + return true; + } + else if (file.equals("NotoNaskhArabicUI-Bold.ttf")) { + familyName->set("Noto Naskh Arabic UI"); + *style = SkFontStyle(700, 5, SkFontStyle::kUpright_Slant); + *isFixedPitch = false; + axes->reset(0); + return true; + } + else if (file.equals("NotoNaskhArabicUI-Regular.ttf")) { + familyName->set("Noto Naskh Arabic UI"); + *style = SkFontStyle(400, 5, SkFontStyle::kUpright_Slant); + *isFixedPitch = false; + axes->reset(0); + return true; + } + else if (file.equals("NotoSansAdlam-VF.ttf")) { + familyName->set("Noto Sans Adlam"); + *style = SkFontStyle(400, 5, SkFontStyle::kUpright_Slant); + *isFixedPitch = false; + axes->reset(1); + (*axes)[0].tag = SkSetFourByteTag('w', 'g', 'h', 't');; + (*axes)[0].min = 400; + (*axes)[0].def = 400; + (*axes)[0].max = 700; + return true; + } + else if (file.equals("NotoSansAhom-Regular.otf")) { + familyName->set("Noto Sans Ahom"); + *style = SkFontStyle(400, 5, SkFontStyle::kUpright_Slant); + *isFixedPitch = false; + axes->reset(0); + return true; + } + else if (file.equals("NotoSansAnatolianHieroglyphs-Regular.otf")) { + familyName->set("Noto Sans Anatolian Hieroglyphs"); + *style = SkFontStyle(400, 5, SkFontStyle::kUpright_Slant); + *isFixedPitch = false; + axes->reset(0); + return true; + } + else if (file.equals("NotoSansArmenian-VF.ttf")) { + familyName->set("Noto Sans Armenian"); + *style = SkFontStyle(400, 5, SkFontStyle::kUpright_Slant); + *isFixedPitch = false; + axes->reset(1); + (*axes)[0].tag = SkSetFourByteTag('w', 'g', 'h', 't');; + (*axes)[0].min = 400; + (*axes)[0].def = 400; + (*axes)[0].max = 700; + return true; + } + else if (file.equals("NotoSansAvestan-Regular.ttf")) { + familyName->set("Noto Sans Avestan"); + *style = SkFontStyle(400, 5, SkFontStyle::kUpright_Slant); + *isFixedPitch = false; + axes->reset(0); + return true; + } + else if (file.equals("NotoSansBalinese-Regular.ttf")) { + familyName->set("Noto Sans Balinese"); + *style = SkFontStyle(400, 5, SkFontStyle::kUpright_Slant); + *isFixedPitch = false; + axes->reset(0); + return true; + } + else if (file.equals("NotoSansBamum-Regular.ttf")) { + familyName->set("Noto Sans Bamum"); + *style = SkFontStyle(400, 5, SkFontStyle::kUpright_Slant); + *isFixedPitch = false; + axes->reset(0); + return true; + } + else if (file.equals("NotoSansBassaVah-Regular.otf")) { + familyName->set("Noto Sans Bassa Vah"); + *style = SkFontStyle(400, 5, SkFontStyle::kUpright_Slant); + *isFixedPitch = false; + axes->reset(0); + return true; + } + else if (file.equals("NotoSansBatak-Regular.ttf")) { + familyName->set("Noto Sans Batak"); + *style = SkFontStyle(400, 5, SkFontStyle::kUpright_Slant); + *isFixedPitch = false; + axes->reset(0); + return true; + } + else if (file.equals("NotoSansBengaliUI-VF.ttf")) { + familyName->set("Noto Sans Bengali UI"); + *style = SkFontStyle(400, 5, SkFontStyle::kUpright_Slant); + *isFixedPitch = false; + axes->reset(1); + (*axes)[0].tag = SkSetFourByteTag('w', 'g', 'h', 't');; + (*axes)[0].min = 400; + (*axes)[0].def = 400; + (*axes)[0].max = 700; + return true; + } + else if (file.equals("NotoSansBengali-VF.ttf")) { + familyName->set("Noto Sans Bengali"); + *style = SkFontStyle(400, 5, SkFontStyle::kUpright_Slant); + *isFixedPitch = false; + axes->reset(1); + (*axes)[0].tag = SkSetFourByteTag('w', 'g', 'h', 't');; + (*axes)[0].min = 400; + (*axes)[0].def = 400; + (*axes)[0].max = 700; + return true; + } + else if (file.equals("NotoSansBhaiksuki-Regular.otf")) { + familyName->set("Noto Sans Bhaiksuki"); + *style = SkFontStyle(400, 5, SkFontStyle::kUpright_Slant); + *isFixedPitch = false; + axes->reset(0); + return true; + } + else if (file.equals("NotoSansBrahmi-Regular.ttf")) { + familyName->set("Noto Sans Brahmi"); + *style = SkFontStyle(400, 5, SkFontStyle::kUpright_Slant); + *isFixedPitch = false; + axes->reset(0); + return true; + } + else if (file.equals("NotoSansBuginese-Regular.ttf")) { + familyName->set("Noto Sans Buginese"); + *style = SkFontStyle(400, 5, SkFontStyle::kUpright_Slant); + *isFixedPitch = false; + axes->reset(0); + return true; + } + else if (file.equals("NotoSansBuhid-Regular.ttf")) { + familyName->set("Noto Sans Buhid"); + *style = SkFontStyle(400, 5, SkFontStyle::kUpright_Slant); + *isFixedPitch = false; + axes->reset(0); + return true; + } + else if (file.equals("NotoSansCanadianAboriginal-Regular.ttf")) { + familyName->set("Noto Sans Canadian Aboriginal"); + *style = SkFontStyle(400, 5, SkFontStyle::kUpright_Slant); + *isFixedPitch = false; + axes->reset(0); + return true; + } + else if (file.equals("NotoSansCarian-Regular.ttf")) { + familyName->set("Noto Sans Carian"); + *style = SkFontStyle(400, 5, SkFontStyle::kUpright_Slant); + *isFixedPitch = false; + axes->reset(0); + return true; + } + else if (file.equals("NotoSansChakma-Regular.otf")) { + familyName->set("Noto Sans Chakma"); + *style = SkFontStyle(400, 5, SkFontStyle::kUpright_Slant); + *isFixedPitch = false; + axes->reset(0); + return true; + } + else if (file.equals("NotoSansCham-Bold.ttf")) { + familyName->set("Noto Sans Cham"); + *style = SkFontStyle(700, 5, SkFontStyle::kUpright_Slant); + *isFixedPitch = false; + axes->reset(0); + return true; + } + else if (file.equals("NotoSansCham-Regular.ttf")) { + familyName->set("Noto Sans Cham"); + *style = SkFontStyle(400, 5, SkFontStyle::kUpright_Slant); + *isFixedPitch = false; + axes->reset(0); + return true; + } + else if (file.equals("NotoSansCherokee-Regular.ttf")) { + familyName->set("Noto Sans Cherokee"); + *style = SkFontStyle(400, 5, SkFontStyle::kUpright_Slant); + *isFixedPitch = false; + axes->reset(0); + return true; + } + else if (file.equals("NotoSansCJK-Regular.ttc")) { + familyName->set("Noto Sans CJK SC"); + *style = SkFontStyle(400, 5, SkFontStyle::kUpright_Slant); + *isFixedPitch = false; + axes->reset(0); + return true; + } + else if (file.equals("NotoSansCoptic-Regular.ttf")) { + familyName->set("Noto Sans Coptic"); + *style = SkFontStyle(400, 5, SkFontStyle::kUpright_Slant); + *isFixedPitch = false; + axes->reset(0); + return true; + } + else if (file.equals("NotoSansCuneiform-Regular.ttf")) { + familyName->set("Noto Sans Cuneiform"); + *style = SkFontStyle(400, 5, SkFontStyle::kUpright_Slant); + *isFixedPitch = false; + axes->reset(0); + return true; + } + else if (file.equals("NotoSansCypriot-Regular.ttf")) { + familyName->set("Noto Sans Cypriot"); + *style = SkFontStyle(400, 5, SkFontStyle::kUpright_Slant); + *isFixedPitch = false; + axes->reset(0); + return true; + } + else if (file.equals("NotoSansDeseret-Regular.ttf")) { + familyName->set("Noto Sans Deseret"); + *style = SkFontStyle(400, 5, SkFontStyle::kUpright_Slant); + *isFixedPitch = false; + axes->reset(0); + return true; + } + else if (file.equals("NotoSansDevanagariUI-VF.ttf")) { + familyName->set("Noto Sans Devanagari UI"); + *style = SkFontStyle(400, 5, SkFontStyle::kUpright_Slant); + *isFixedPitch = false; + axes->reset(1); + (*axes)[0].tag = SkSetFourByteTag('w', 'g', 'h', 't');; + (*axes)[0].min = 400; + (*axes)[0].def = 400; + (*axes)[0].max = 700; + return true; + } + else if (file.equals("NotoSansDevanagari-VF.ttf")) { + familyName->set("Noto Sans Devanagari"); + *style = SkFontStyle(400, 5, SkFontStyle::kUpright_Slant); + *isFixedPitch = false; + axes->reset(1); + (*axes)[0].tag = SkSetFourByteTag('w', 'g', 'h', 't');; + (*axes)[0].min = 400; + (*axes)[0].def = 400; + (*axes)[0].max = 700; + return true; + } + else if (file.equals("NotoSansEgyptianHieroglyphs-Regular.ttf")) { + familyName->set("Noto Sans Egyptian Hieroglyphs"); + *style = SkFontStyle(400, 5, SkFontStyle::kUpright_Slant); + *isFixedPitch = false; + axes->reset(0); + return true; + } + else if (file.equals("NotoSansElbasan-Regular.otf")) { + familyName->set("Noto Sans Elbasan"); + *style = SkFontStyle(400, 5, SkFontStyle::kUpright_Slant); + *isFixedPitch = false; + axes->reset(0); + return true; + } + else if (file.equals("NotoSansEthiopic-VF.ttf")) { + familyName->set("Noto Sans Ethiopic"); + *style = SkFontStyle(400, 5, SkFontStyle::kUpright_Slant); + *isFixedPitch = false; + axes->reset(1); + (*axes)[0].tag = SkSetFourByteTag('w', 'g', 'h', 't');; + (*axes)[0].min = 400; + (*axes)[0].def = 400; + (*axes)[0].max = 700; + return true; + } + else if (file.equals("NotoSansGeorgian-VF.ttf")) { + familyName->set("Noto Sans Georgian"); + *style = SkFontStyle(400, 5, SkFontStyle::kUpright_Slant); + *isFixedPitch = false; + axes->reset(1); + (*axes)[0].tag = SkSetFourByteTag('w', 'g', 'h', 't');; + (*axes)[0].min = 400; + (*axes)[0].def = 400; + (*axes)[0].max = 700; + return true; + } + else if (file.equals("NotoSansGlagolitic-Regular.ttf")) { + familyName->set("Noto Sans Glagolitic"); + *style = SkFontStyle(400, 5, SkFontStyle::kUpright_Slant); + *isFixedPitch = false; + axes->reset(0); + return true; + } + else if (file.equals("NotoSansGothic-Regular.ttf")) { + familyName->set("Noto Sans Gothic"); + *style = SkFontStyle(400, 5, SkFontStyle::kUpright_Slant); + *isFixedPitch = false; + axes->reset(0); + return true; + } + else if (file.equals("NotoSansGrantha-Regular.ttf")) { + familyName->set("Noto Sans Grantha"); + *style = SkFontStyle(400, 5, SkFontStyle::kUpright_Slant); + *isFixedPitch = false; + axes->reset(0); + return true; + } + else if (file.equals("NotoSansGujarati-Bold.ttf")) { + familyName->set("Noto Sans Gujarati"); + *style = SkFontStyle(700, 5, SkFontStyle::kUpright_Slant); + *isFixedPitch = false; + axes->reset(0); + return true; + } + else if (file.equals("NotoSansGujarati-Regular.ttf")) { + familyName->set("Noto Sans Gujarati"); + *style = SkFontStyle(400, 5, SkFontStyle::kUpright_Slant); + *isFixedPitch = false; + axes->reset(0); + return true; + } + else if (file.equals("NotoSansGujaratiUI-Bold.ttf")) { + familyName->set("Noto Sans Gujarati UI"); + *style = SkFontStyle(700, 5, SkFontStyle::kUpright_Slant); + *isFixedPitch = false; + axes->reset(0); + return true; + } + else if (file.equals("NotoSansGujaratiUI-Regular.ttf")) { + familyName->set("Noto Sans Gujarati UI"); + *style = SkFontStyle(400, 5, SkFontStyle::kUpright_Slant); + *isFixedPitch = false; + axes->reset(0); + return true; + } + else if (file.equals("NotoSansGunjalaGondi-Regular.otf")) { + familyName->set("Noto Sans Gunjala Gondi"); + *style = SkFontStyle(400, 5, SkFontStyle::kUpright_Slant); + *isFixedPitch = false; + axes->reset(0); + return true; + } + else if (file.equals("NotoSansGurmukhiUI-VF.ttf")) { + familyName->set("Noto Sans Gurmukhi UI"); + *style = SkFontStyle(400, 5, SkFontStyle::kUpright_Slant); + *isFixedPitch = false; + axes->reset(1); + (*axes)[0].tag = SkSetFourByteTag('w', 'g', 'h', 't');; + (*axes)[0].min = 400; + (*axes)[0].def = 400; + (*axes)[0].max = 700; + return true; + } + else if (file.equals("NotoSansGurmukhi-VF.ttf")) { + familyName->set("Noto Sans Gurmukhi"); + *style = SkFontStyle(400, 5, SkFontStyle::kUpright_Slant); + *isFixedPitch = false; + axes->reset(1); + (*axes)[0].tag = SkSetFourByteTag('w', 'g', 'h', 't');; + (*axes)[0].min = 400; + (*axes)[0].def = 400; + (*axes)[0].max = 700; + return true; + } + else if (file.equals("NotoSansHanifiRohingya-Regular.otf")) { + familyName->set("Noto Sans Hanifi Rohingya"); + *style = SkFontStyle(400, 5, SkFontStyle::kUpright_Slant); + *isFixedPitch = false; + axes->reset(0); + return true; + } + else if (file.equals("NotoSansHanunoo-Regular.ttf")) { + familyName->set("Noto Sans Hanunoo"); + *style = SkFontStyle(400, 5, SkFontStyle::kUpright_Slant); + *isFixedPitch = false; + axes->reset(0); + return true; + } + else if (file.equals("NotoSansHatran-Regular.otf")) { + familyName->set("Noto Sans Hatran"); + *style = SkFontStyle(400, 5, SkFontStyle::kUpright_Slant); + *isFixedPitch = false; + axes->reset(0); + return true; + } + else if (file.equals("NotoSansHebrew-Bold.ttf")) { + familyName->set("Noto Sans Hebrew"); + *style = SkFontStyle(700, 5, SkFontStyle::kUpright_Slant); + *isFixedPitch = false; + axes->reset(0); + return true; + } + else if (file.equals("NotoSansHebrew-Regular.ttf")) { + familyName->set("Noto Sans Hebrew"); + *style = SkFontStyle(400, 5, SkFontStyle::kUpright_Slant); + *isFixedPitch = false; + axes->reset(0); + return true; + } + else if (file.equals("NotoSansImperialAramaic-Regular.ttf")) { + familyName->set("Noto Sans Imperial Aramaic"); + *style = SkFontStyle(400, 5, SkFontStyle::kUpright_Slant); + *isFixedPitch = false; + axes->reset(0); + return true; + } + else if (file.equals("NotoSansInscriptionalPahlavi-Regular.ttf")) { + familyName->set("Noto Sans Inscriptional Pahlavi"); + *style = SkFontStyle(400, 5, SkFontStyle::kUpright_Slant); + *isFixedPitch = false; + axes->reset(0); + return true; + } + else if (file.equals("NotoSansInscriptionalParthian-Regular.ttf")) { + familyName->set("Noto Sans Inscriptional Parthian"); + *style = SkFontStyle(400, 5, SkFontStyle::kUpright_Slant); + *isFixedPitch = false; + axes->reset(0); + return true; + } + else if (file.equals("NotoSansJavanese-Regular.otf")) { + familyName->set("Noto Sans Javanese"); + *style = SkFontStyle(400, 5, SkFontStyle::kUpright_Slant); + *isFixedPitch = false; + axes->reset(0); + return true; + } + else if (file.equals("NotoSansKaithi-Regular.ttf")) { + familyName->set("Noto Sans Kaithi"); + *style = SkFontStyle(400, 5, SkFontStyle::kUpright_Slant); + *isFixedPitch = false; + axes->reset(0); + return true; + } + else if (file.equals("NotoSansKannadaUI-VF.ttf")) { + familyName->set("Noto Sans Kannada UI"); + *style = SkFontStyle(400, 5, SkFontStyle::kUpright_Slant); + *isFixedPitch = false; + axes->reset(1); + (*axes)[0].tag = SkSetFourByteTag('w', 'g', 'h', 't');; + (*axes)[0].min = 400; + (*axes)[0].def = 400; + (*axes)[0].max = 700; + return true; + } + else if (file.equals("NotoSansKannada-VF.ttf")) { + familyName->set("Noto Sans Kannada"); + *style = SkFontStyle(400, 5, SkFontStyle::kUpright_Slant); + *isFixedPitch = false; + axes->reset(1); + (*axes)[0].tag = SkSetFourByteTag('w', 'g', 'h', 't');; + (*axes)[0].min = 400; + (*axes)[0].def = 400; + (*axes)[0].max = 700; + return true; + } + else if (file.equals("NotoSansKayahLi-Regular.ttf")) { + familyName->set("Noto Sans Kayah Li"); + *style = SkFontStyle(400, 5, SkFontStyle::kUpright_Slant); + *isFixedPitch = false; + axes->reset(0); + return true; + } + else if (file.equals("NotoSansKharoshthi-Regular.ttf")) { + familyName->set("Noto Sans Kharoshthi"); + *style = SkFontStyle(400, 5, SkFontStyle::kUpright_Slant); + *isFixedPitch = false; + axes->reset(0); + return true; + } + else if (file.equals("NotoSansKhmerUI-Bold.ttf")) { + familyName->set("Noto Sans Khmer UI"); + *style = SkFontStyle(700, 5, SkFontStyle::kUpright_Slant); + *isFixedPitch = false; + axes->reset(0); + return true; + } + else if (file.equals("NotoSansKhmerUI-Regular.ttf")) { + familyName->set("Noto Sans Khmer UI"); + *style = SkFontStyle(400, 5, SkFontStyle::kUpright_Slant); + *isFixedPitch = false; + axes->reset(0); + return true; + } + else if (file.equals("NotoSansKhmer-VF.ttf")) { + familyName->set("Noto Sans Khmer"); + *style = SkFontStyle(90, 5, SkFontStyle::kUpright_Slant); + *isFixedPitch = false; + axes->reset(2); + (*axes)[0].tag = SkSetFourByteTag('w', 'g', 'h', 't');; + (*axes)[0].min = 26; + (*axes)[0].def = 90; + (*axes)[0].max = 190; + (*axes)[1].tag = SkSetFourByteTag('w', 'd', 't', 'h'); + (*axes)[1].min = 70; + (*axes)[1].def = 100; + (*axes)[1].max = 100; + return true; + } + else if (file.equals("NotoSansKhojki-Regular.otf")) { + familyName->set("Noto Sans Khojki"); + *style = SkFontStyle(400, 5, SkFontStyle::kUpright_Slant); + *isFixedPitch = false; + axes->reset(0); + return true; + } + else if (file.equals("NotoSansLao-Bold.ttf")) { + familyName->set("Noto Sans Lao"); + *style = SkFontStyle(700, 5, SkFontStyle::kUpright_Slant); + *isFixedPitch = false; + axes->reset(0); + return true; + } + else if (file.equals("NotoSansLao-Regular.ttf")) { + familyName->set("Noto Sans Lao"); + *style = SkFontStyle(400, 5, SkFontStyle::kUpright_Slant); + *isFixedPitch = false; + axes->reset(0); + return true; + } + else if (file.equals("NotoSansLaoUI-Bold.ttf")) { + familyName->set("Noto Sans Lao UI"); + *style = SkFontStyle(700, 5, SkFontStyle::kUpright_Slant); + *isFixedPitch = false; + axes->reset(0); + return true; + } + else if (file.equals("NotoSansLaoUI-Regular.ttf")) { + familyName->set("Noto Sans Lao UI"); + *style = SkFontStyle(400, 5, SkFontStyle::kUpright_Slant); + *isFixedPitch = false; + axes->reset(0); + return true; + } + else if (file.equals("NotoSansLepcha-Regular.ttf")) { + familyName->set("Noto Sans Lepcha"); + *style = SkFontStyle(400, 5, SkFontStyle::kUpright_Slant); + *isFixedPitch = false; + axes->reset(0); + return true; + } + else if (file.equals("NotoSansLimbu-Regular.ttf")) { + familyName->set("Noto Sans Limbu"); + *style = SkFontStyle(400, 5, SkFontStyle::kUpright_Slant); + *isFixedPitch = false; + axes->reset(0); + return true; + } + else if (file.equals("NotoSansLinearA-Regular.otf")) { + familyName->set("Noto Sans Linear A"); + *style = SkFontStyle(400, 5, SkFontStyle::kUpright_Slant); + *isFixedPitch = false; + axes->reset(0); + return true; + } + else if (file.equals("NotoSansLinearB-Regular.ttf")) { + familyName->set("Noto Sans Linear B"); + *style = SkFontStyle(400, 5, SkFontStyle::kUpright_Slant); + *isFixedPitch = false; + axes->reset(0); + return true; + } + else if (file.equals("NotoSansLisu-Regular.ttf")) { + familyName->set("Noto Sans Lisu"); + *style = SkFontStyle(400, 5, SkFontStyle::kUpright_Slant); + *isFixedPitch = false; + axes->reset(0); + return true; + } + else if (file.equals("NotoSansLycian-Regular.ttf")) { + familyName->set("Noto Sans Lycian"); + *style = SkFontStyle(400, 5, SkFontStyle::kUpright_Slant); + *isFixedPitch = false; + axes->reset(0); + return true; + } + else if (file.equals("NotoSansLydian-Regular.ttf")) { + familyName->set("Noto Sans Lydian"); + *style = SkFontStyle(400, 5, SkFontStyle::kUpright_Slant); + *isFixedPitch = false; + axes->reset(0); + return true; + } + else if (file.equals("NotoSansMalayalamUI-VF.ttf")) { + familyName->set("Noto Sans Malayalam UI"); + *style = SkFontStyle(400, 5, SkFontStyle::kUpright_Slant); + *isFixedPitch = false; + axes->reset(1); + (*axes)[0].tag = SkSetFourByteTag('w', 'g', 'h', 't');; + (*axes)[0].min = 400; + (*axes)[0].def = 400; + (*axes)[0].max = 700; + return true; + } + else if (file.equals("NotoSansMalayalam-VF.ttf")) { + familyName->set("Noto Sans Malayalam"); + *style = SkFontStyle(400, 5, SkFontStyle::kUpright_Slant); + *isFixedPitch = false; + axes->reset(1); + (*axes)[0].tag = SkSetFourByteTag('w', 'g', 'h', 't');; + (*axes)[0].min = 400; + (*axes)[0].def = 400; + (*axes)[0].max = 700; + return true; + } + else if (file.equals("NotoSansMandaic-Regular.ttf")) { + familyName->set("Noto Sans Mandaic"); + *style = SkFontStyle(400, 5, SkFontStyle::kUpright_Slant); + *isFixedPitch = false; + axes->reset(0); + return true; + } + else if (file.equals("NotoSansManichaean-Regular.otf")) { + familyName->set("Noto Sans Manichaean"); + *style = SkFontStyle(400, 5, SkFontStyle::kUpright_Slant); + *isFixedPitch = false; + axes->reset(0); + return true; + } + else if (file.equals("NotoSansMarchen-Regular.otf")) { + familyName->set("Noto Sans Marchen"); + *style = SkFontStyle(400, 5, SkFontStyle::kUpright_Slant); + *isFixedPitch = false; + axes->reset(0); + return true; + } + else if (file.equals("NotoSansMasaramGondi-Regular.otf")) { + familyName->set("Noto Sans Masaram Gondi"); + *style = SkFontStyle(400, 5, SkFontStyle::kUpright_Slant); + *isFixedPitch = false; + axes->reset(0); + return true; + } + else if (file.equals("NotoSansMedefaidrin-VF.ttf")) { + familyName->set("Noto Sans Medefaidrin"); + *style = SkFontStyle(400, 5, SkFontStyle::kUpright_Slant); + *isFixedPitch = false; + axes->reset(1); + (*axes)[0].tag = SkSetFourByteTag('w', 'g', 'h', 't');; + (*axes)[0].min = 400; + (*axes)[0].def = 400; + (*axes)[0].max = 700; + return true; + } + else if (file.equals("NotoSansMeeteiMayek-Regular.ttf")) { + familyName->set("Noto Sans Meetei Mayek"); + *style = SkFontStyle(400, 5, SkFontStyle::kUpright_Slant); + *isFixedPitch = false; + axes->reset(0); + return true; + } + else if (file.equals("NotoSansMeroitic-Regular.otf")) { + familyName->set("Noto Sans Meroitic"); + *style = SkFontStyle(400, 5, SkFontStyle::kUpright_Slant); + *isFixedPitch = false; + axes->reset(0); + return true; + } + else if (file.equals("NotoSansMiao-Regular.otf")) { + familyName->set("Noto Sans Miao"); + *style = SkFontStyle(400, 5, SkFontStyle::kUpright_Slant); + *isFixedPitch = false; + axes->reset(0); + return true; + } + else if (file.equals("NotoSansModi-Regular.ttf")) { + familyName->set("Noto Sans Modi"); + *style = SkFontStyle(400, 5, SkFontStyle::kUpright_Slant); + *isFixedPitch = false; + axes->reset(0); + return true; + } + else if (file.equals("NotoSansMongolian-Regular.ttf")) { + familyName->set("Noto Sans Mongolian"); + *style = SkFontStyle(400, 5, SkFontStyle::kUpright_Slant); + *isFixedPitch = false; + axes->reset(0); + return true; + } + else if (file.equals("NotoSansMro-Regular.otf")) { + familyName->set("Noto Sans Mro"); + *style = SkFontStyle(400, 5, SkFontStyle::kUpright_Slant); + *isFixedPitch = false; + axes->reset(0); + return true; + } + else if (file.equals("NotoSansMultani-Regular.otf")) { + familyName->set("Noto Sans Multani"); + *style = SkFontStyle(400, 5, SkFontStyle::kUpright_Slant); + *isFixedPitch = false; + axes->reset(0); + return true; + } + else if (file.equals("NotoSansMyanmar-Bold.otf")) { + familyName->set("Noto Sans Myanmar"); + *style = SkFontStyle(700, 5, SkFontStyle::kUpright_Slant); + *isFixedPitch = false; + axes->reset(0); + return true; + } + else if (file.equals("NotoSansMyanmar-Medium.otf")) { + familyName->set("Noto Sans Myanmar"); + *style = SkFontStyle(500, 5, SkFontStyle::kUpright_Slant); + *isFixedPitch = false; + axes->reset(0); + return true; + } + else if (file.equals("NotoSansMyanmar-Regular.otf")) { + familyName->set("Noto Sans Myanmar"); + *style = SkFontStyle(400, 5, SkFontStyle::kUpright_Slant); + *isFixedPitch = false; + axes->reset(0); + return true; + } + else if (file.equals("NotoSansMyanmarUI-Bold.otf")) { + familyName->set("Noto Sans Myanmar UI"); + *style = SkFontStyle(700, 5, SkFontStyle::kUpright_Slant); + *isFixedPitch = false; + axes->reset(0); + return true; + } + else if (file.equals("NotoSansMyanmarUI-Medium.otf")) { + familyName->set("Noto Sans Myanmar UI"); + *style = SkFontStyle(500, 5, SkFontStyle::kUpright_Slant); + *isFixedPitch = false; + axes->reset(0); + return true; + } + else if (file.equals("NotoSansMyanmarUI-Regular.otf")) { + familyName->set("Noto Sans Myanmar UI"); + *style = SkFontStyle(400, 5, SkFontStyle::kUpright_Slant); + *isFixedPitch = false; + axes->reset(0); + return true; + } + else if (file.equals("NotoSansNabataean-Regular.otf")) { + familyName->set("Noto Sans Nabataean"); + *style = SkFontStyle(400, 5, SkFontStyle::kUpright_Slant); + *isFixedPitch = false; + axes->reset(0); + return true; + } + else if (file.equals("NotoSansNewa-Regular.otf")) { + familyName->set("Noto Sans Newa"); + *style = SkFontStyle(400, 5, SkFontStyle::kUpright_Slant); + *isFixedPitch = false; + axes->reset(0); + return true; + } + else if (file.equals("NotoSansNewTaiLue-Regular.ttf")) { + familyName->set("Noto Sans New Tai Lue"); + *style = SkFontStyle(400, 5, SkFontStyle::kUpright_Slant); + *isFixedPitch = false; + axes->reset(0); + return true; + } + else if (file.equals("NotoSansNKo-Regular.ttf")) { + familyName->set("Noto Sans NKo"); + *style = SkFontStyle(400, 5, SkFontStyle::kUpright_Slant); + *isFixedPitch = false; + axes->reset(0); + return true; + } + else if (file.equals("NotoSansOgham-Regular.ttf")) { + familyName->set("Noto Sans Ogham"); + *style = SkFontStyle(400, 5, SkFontStyle::kUpright_Slant); + *isFixedPitch = false; + axes->reset(0); + return true; + } + else if (file.equals("NotoSansOlChiki-Regular.ttf")) { + familyName->set("Noto Sans Ol Chiki"); + *style = SkFontStyle(400, 5, SkFontStyle::kUpright_Slant); + *isFixedPitch = false; + axes->reset(0); + return true; + } + else if (file.equals("NotoSansOldItalic-Regular.ttf")) { + familyName->set("Noto Sans Old Italic"); + *style = SkFontStyle(400, 5, SkFontStyle::kUpright_Slant); + *isFixedPitch = false; + axes->reset(0); + return true; + } + else if (file.equals("NotoSansOldNorthArabian-Regular.otf")) { + familyName->set("Noto Sans Old North Arabian"); + *style = SkFontStyle(400, 5, SkFontStyle::kUpright_Slant); + *isFixedPitch = false; + axes->reset(0); + return true; + } + else if (file.equals("NotoSansOldPermic-Regular.otf")) { + familyName->set("Noto Sans Old Permic"); + *style = SkFontStyle(400, 5, SkFontStyle::kUpright_Slant); + *isFixedPitch = false; + axes->reset(0); + return true; + } + else if (file.equals("NotoSansOldPersian-Regular.ttf")) { + familyName->set("Noto Sans Old Persian"); + *style = SkFontStyle(400, 5, SkFontStyle::kUpright_Slant); + *isFixedPitch = false; + axes->reset(0); + return true; + } + else if (file.equals("NotoSansOldSouthArabian-Regular.ttf")) { + familyName->set("Noto Sans Old South Arabian"); + *style = SkFontStyle(400, 5, SkFontStyle::kUpright_Slant); + *isFixedPitch = false; + axes->reset(0); + return true; + } + else if (file.equals("NotoSansOldTurkic-Regular.ttf")) { + familyName->set("Noto Sans Old Turkic"); + *style = SkFontStyle(400, 5, SkFontStyle::kUpright_Slant); + *isFixedPitch = false; + axes->reset(0); + return true; + } + else if (file.equals("NotoSansOriya-Bold.ttf")) { + familyName->set("Noto Sans Oriya"); + *style = SkFontStyle(700, 5, SkFontStyle::kUpright_Slant); + *isFixedPitch = false; + axes->reset(0); + return true; + } + else if (file.equals("NotoSansOriya-Regular.ttf")) { + familyName->set("Noto Sans Oriya"); + *style = SkFontStyle(400, 5, SkFontStyle::kUpright_Slant); + *isFixedPitch = false; + axes->reset(0); + return true; + } + else if (file.equals("NotoSansOriyaUI-Bold.ttf")) { + familyName->set("Noto Sans Oriya UI"); + *style = SkFontStyle(700, 5, SkFontStyle::kUpright_Slant); + *isFixedPitch = false; + axes->reset(0); + return true; + } + else if (file.equals("NotoSansOriyaUI-Regular.ttf")) { + familyName->set("Noto Sans Oriya UI"); + *style = SkFontStyle(400, 5, SkFontStyle::kUpright_Slant); + *isFixedPitch = false; + axes->reset(0); + return true; + } + else if (file.equals("NotoSansOsage-Regular.ttf")) { + familyName->set("Noto Sans Osage"); + *style = SkFontStyle(400, 5, SkFontStyle::kUpright_Slant); + *isFixedPitch = false; + axes->reset(0); + return true; + } + else if (file.equals("NotoSansOsmanya-Regular.ttf")) { + familyName->set("Noto Sans Osmanya"); + *style = SkFontStyle(400, 5, SkFontStyle::kUpright_Slant); + *isFixedPitch = false; + axes->reset(0); + return true; + } + else if (file.equals("NotoSansPahawhHmong-Regular.otf")) { + familyName->set("Noto Sans Pahawh Hmong"); + *style = SkFontStyle(400, 5, SkFontStyle::kUpright_Slant); + *isFixedPitch = false; + axes->reset(0); + return true; + } + else if (file.equals("NotoSansPalmyrene-Regular.otf")) { + familyName->set("Noto Sans Palmyrene"); + *style = SkFontStyle(400, 5, SkFontStyle::kUpright_Slant); + *isFixedPitch = false; + axes->reset(0); + return true; + } + else if (file.equals("NotoSansPauCinHau-Regular.otf")) { + familyName->set("Noto Sans Pau Cin Hau"); + *style = SkFontStyle(400, 5, SkFontStyle::kUpright_Slant); + *isFixedPitch = false; + axes->reset(0); + return true; + } + else if (file.equals("NotoSansPhagsPa-Regular.ttf")) { + familyName->set("Noto Sans Phags Pa"); + *style = SkFontStyle(400, 5, SkFontStyle::kUpright_Slant); + *isFixedPitch = false; + axes->reset(0); + return true; + } + else if (file.equals("NotoSansPhoenician-Regular.ttf")) { + familyName->set("Noto Sans Phoenician"); + *style = SkFontStyle(400, 5, SkFontStyle::kUpright_Slant); + *isFixedPitch = false; + axes->reset(0); + return true; + } + else if (file.equals("NotoSansRejang-Regular.ttf")) { + familyName->set("Noto Sans Rejang"); + *style = SkFontStyle(400, 5, SkFontStyle::kUpright_Slant); + *isFixedPitch = false; + axes->reset(0); + return true; + } + else if (file.equals("NotoSansRunic-Regular.ttf")) { + familyName->set("Noto Sans Runic"); + *style = SkFontStyle(400, 5, SkFontStyle::kUpright_Slant); + *isFixedPitch = false; + axes->reset(0); + return true; + } + else if (file.equals("NotoSansSamaritan-Regular.ttf")) { + familyName->set("Noto Sans Samaritan"); + *style = SkFontStyle(400, 5, SkFontStyle::kUpright_Slant); + *isFixedPitch = false; + axes->reset(0); + return true; + } + else if (file.equals("NotoSansSaurashtra-Regular.ttf")) { + familyName->set("Noto Sans Saurashtra"); + *style = SkFontStyle(400, 5, SkFontStyle::kUpright_Slant); + *isFixedPitch = false; + axes->reset(0); + return true; + } + else if (file.equals("NotoSansSharada-Regular.otf")) { + familyName->set("Noto Sans Sharada"); + *style = SkFontStyle(400, 5, SkFontStyle::kUpright_Slant); + *isFixedPitch = false; + axes->reset(0); + return true; + } + else if (file.equals("NotoSansShavian-Regular.ttf")) { + familyName->set("Noto Sans Shavian"); + *style = SkFontStyle(400, 5, SkFontStyle::kUpright_Slant); + *isFixedPitch = false; + axes->reset(0); + return true; + } + else if (file.equals("NotoSansSinhalaUI-VF.ttf")) { + familyName->set("Noto Sans Sinhala UI"); + *style = SkFontStyle(400, 5, SkFontStyle::kUpright_Slant); + *isFixedPitch = false; + axes->reset(1); + (*axes)[0].tag = SkSetFourByteTag('w', 'g', 'h', 't');; + (*axes)[0].min = 400; + (*axes)[0].def = 400; + (*axes)[0].max = 700; + return true; + } + else if (file.equals("NotoSansSinhala-VF.ttf")) { + familyName->set("Noto Sans Sinhala"); + *style = SkFontStyle(400, 5, SkFontStyle::kUpright_Slant); + *isFixedPitch = false; + axes->reset(1); + (*axes)[0].tag = SkSetFourByteTag('w', 'g', 'h', 't');; + (*axes)[0].min = 400; + (*axes)[0].def = 400; + (*axes)[0].max = 700; + return true; + } + else if (file.equals("NotoSansSoraSompeng-Regular.otf")) { + familyName->set("Noto Sans Sora Sompeng"); + *style = SkFontStyle(400, 5, SkFontStyle::kUpright_Slant); + *isFixedPitch = false; + axes->reset(0); + return true; + } + else if (file.equals("NotoSansSoyombo-VF.ttf")) { + familyName->set("Noto Sans Soyombo"); + *style = SkFontStyle(400, 5, SkFontStyle::kUpright_Slant); + *isFixedPitch = false; + axes->reset(1); + (*axes)[0].tag = SkSetFourByteTag('w', 'g', 'h', 't');; + (*axes)[0].min = 400; + (*axes)[0].def = 400; + (*axes)[0].max = 700; + return true; + } + else if (file.equals("NotoSansSundanese-Regular.ttf")) { + familyName->set("Noto Sans Sundanese"); + *style = SkFontStyle(400, 5, SkFontStyle::kUpright_Slant); + *isFixedPitch = false; + axes->reset(0); + return true; + } + else if (file.equals("NotoSansSylotiNagri-Regular.ttf")) { + familyName->set("Noto Sans Syloti Nagri"); + *style = SkFontStyle(400, 5, SkFontStyle::kUpright_Slant); + *isFixedPitch = false; + axes->reset(0); + return true; + } + else if (file.equals("NotoSansSymbols-Regular-Subsetted.ttf")) { + familyName->set("Noto Sans Symbols"); + *style = SkFontStyle(400, 5, SkFontStyle::kUpright_Slant); + *isFixedPitch = false; + axes->reset(0); + return true; + } + else if (file.equals("NotoSansSymbols-Regular-Subsetted2.ttf")) { + familyName->set("Noto Sans Symbols"); + *style = SkFontStyle(400, 5, SkFontStyle::kUpright_Slant); + *isFixedPitch = false; + axes->reset(0); + return true; + } + else if (file.equals("NotoSansSyriacEastern-Regular.ttf")) { + familyName->set("Noto Sans Syriac Eastern"); + *style = SkFontStyle(400, 5, SkFontStyle::kUpright_Slant); + *isFixedPitch = false; + axes->reset(0); + return true; + } + else if (file.equals("NotoSansSyriacEstrangela-Regular.ttf")) { + familyName->set("Noto Sans Syriac Estrangela"); + *style = SkFontStyle(400, 5, SkFontStyle::kUpright_Slant); + *isFixedPitch = false; + axes->reset(0); + return true; + } + else if (file.equals("NotoSansSyriacWestern-Regular.ttf")) { + familyName->set("Noto Sans Syriac Western"); + *style = SkFontStyle(400, 5, SkFontStyle::kUpright_Slant); + *isFixedPitch = false; + axes->reset(0); + return true; + } + else if (file.equals("NotoSansTagalog-Regular.ttf")) { + familyName->set("Noto Sans Tagalog"); + *style = SkFontStyle(400, 5, SkFontStyle::kUpright_Slant); + *isFixedPitch = false; + axes->reset(0); + return true; + } + else if (file.equals("NotoSansTagbanwa-Regular.ttf")) { + familyName->set("Noto Sans Tagbanwa"); + *style = SkFontStyle(400, 5, SkFontStyle::kUpright_Slant); + *isFixedPitch = false; + axes->reset(0); + return true; + } + else if (file.equals("NotoSansTaiLe-Regular.ttf")) { + familyName->set("Noto Sans Tai Le"); + *style = SkFontStyle(400, 5, SkFontStyle::kUpright_Slant); + *isFixedPitch = false; + axes->reset(0); + return true; + } + else if (file.equals("NotoSansTaiTham-Regular.ttf")) { + familyName->set("Noto Sans Tai Tham"); + *style = SkFontStyle(400, 5, SkFontStyle::kUpright_Slant); + *isFixedPitch = false; + axes->reset(0); + return true; + } + else if (file.equals("NotoSansTaiViet-Regular.ttf")) { + familyName->set("Noto Sans Tai Viet"); + *style = SkFontStyle(400, 5, SkFontStyle::kUpright_Slant); + *isFixedPitch = false; + axes->reset(0); + return true; + } + else if (file.equals("NotoSansTakri-VF.ttf")) { + familyName->set("Noto Sans Takri"); + *style = SkFontStyle(400, 5, SkFontStyle::kUpright_Slant); + *isFixedPitch = false; + axes->reset(1); + (*axes)[0].tag = SkSetFourByteTag('w', 'g', 'h', 't');; + (*axes)[0].min = 400; + (*axes)[0].def = 400; + (*axes)[0].max = 700; + return true; + } + else if (file.equals("NotoSansTamilUI-VF.ttf")) { + familyName->set("Noto Sans Tamil"); + *style = SkFontStyle(400, 2, SkFontStyle::kUpright_Slant); + *isFixedPitch = false; + axes->reset(1); + (*axes)[0].tag = SkSetFourByteTag('w', 'g', 'h', 't');; + (*axes)[0].min = 400; + (*axes)[0].def = 400; + (*axes)[0].max = 700; + return true; + } + else if (file.equals("NotoSansTamil-VF.ttf")) { + familyName->set("Noto Sans Tamil"); + *style = SkFontStyle(400, 5, SkFontStyle::kUpright_Slant); + *isFixedPitch = false; + axes->reset(1); + (*axes)[0].tag = SkSetFourByteTag('w', 'g', 'h', 't');; + (*axes)[0].min = 400; + (*axes)[0].def = 400; + (*axes)[0].max = 700; + return true; + } + else if (file.equals("NotoSansTeluguUI-VF.ttf")) { + familyName->set("Noto Sans Telugu UI"); + *style = SkFontStyle(400, 5, SkFontStyle::kUpright_Slant); + *isFixedPitch = false; + axes->reset(1); + (*axes)[0].tag = SkSetFourByteTag('w', 'g', 'h', 't');; + (*axes)[0].min = 400; + (*axes)[0].def = 400; + (*axes)[0].max = 700; + return true; + } + else if (file.equals("NotoSansTelugu-VF.ttf")) { + familyName->set("Noto Sans Telugu"); + *style = SkFontStyle(400, 5, SkFontStyle::kUpright_Slant); + *isFixedPitch = false; + axes->reset(1); + (*axes)[0].tag = SkSetFourByteTag('w', 'g', 'h', 't');; + (*axes)[0].min = 400; + (*axes)[0].def = 400; + (*axes)[0].max = 700; + return true; + } + else if (file.equals("NotoSansThaana-Bold.ttf")) { + familyName->set("Noto Sans Thaana"); + *style = SkFontStyle(700, 5, SkFontStyle::kUpright_Slant); + *isFixedPitch = false; + axes->reset(0); + return true; + } + else if (file.equals("NotoSansThaana-Regular.ttf")) { + familyName->set("Noto Sans Thaana"); + *style = SkFontStyle(400, 5, SkFontStyle::kUpright_Slant); + *isFixedPitch = false; + axes->reset(0); + return true; + } + else if (file.equals("NotoSansThai-Bold.ttf")) { + familyName->set("Noto Sans Thai"); + *style = SkFontStyle(700, 5, SkFontStyle::kUpright_Slant); + *isFixedPitch = false; + axes->reset(0); + return true; + } + else if (file.equals("NotoSansThai-Regular.ttf")) { + familyName->set("Noto Sans Thai"); + *style = SkFontStyle(400, 5, SkFontStyle::kUpright_Slant); + *isFixedPitch = false; + axes->reset(0); + return true; + } + else if (file.equals("NotoSansThaiUI-Bold.ttf")) { + familyName->set("Noto Sans Thai UI"); + *style = SkFontStyle(700, 5, SkFontStyle::kUpright_Slant); + *isFixedPitch = false; + axes->reset(0); + return true; + } + else if (file.equals("NotoSansThaiUI-Regular.ttf")) { + familyName->set("Noto Sans Thai UI"); + *style = SkFontStyle(400, 5, SkFontStyle::kUpright_Slant); + *isFixedPitch = false; + axes->reset(0); + return true; + } + else if (file.equals("NotoSansTifinagh-Regular.otf")) { + familyName->set("Noto Sans Tifinagh"); + *style = SkFontStyle(400, 5, SkFontStyle::kUpright_Slant); + *isFixedPitch = false; + axes->reset(0); + return true; + } + else if (file.equals("NotoSansUgaritic-Regular.ttf")) { + familyName->set("Noto Sans Ugaritic"); + *style = SkFontStyle(400, 5, SkFontStyle::kUpright_Slant); + *isFixedPitch = false; + axes->reset(0); + return true; + } + else if (file.equals("NotoSansVai-Regular.ttf")) { + familyName->set("Noto Sans Vai"); + *style = SkFontStyle(400, 5, SkFontStyle::kUpright_Slant); + *isFixedPitch = false; + axes->reset(0); + return true; + } + else if (file.equals("NotoSansWancho-Regular.otf")) { + familyName->set("Noto Sans Wancho"); + *style = SkFontStyle(400, 5, SkFontStyle::kUpright_Slant); + *isFixedPitch = false; + axes->reset(0); + return true; + } + else if (file.equals("NotoSansWarangCiti-Regular.otf")) { + familyName->set("Noto Sans Warang Citi"); + *style = SkFontStyle(400, 5, SkFontStyle::kUpright_Slant); + *isFixedPitch = false; + axes->reset(0); + return true; + } + else if (file.equals("NotoSansYi-Regular.ttf")) { + familyName->set("Noto Sans Yi"); + *style = SkFontStyle(400, 5, SkFontStyle::kUpright_Slant); + *isFixedPitch = false; + axes->reset(0); + return true; + } + else if (file.equals("NotoSerifArmenian-VF.ttf")) { + familyName->set("Noto Serif Armenian"); + *style = SkFontStyle(400, 5, SkFontStyle::kUpright_Slant); + *isFixedPitch = false; + axes->reset(1); + (*axes)[0].tag = SkSetFourByteTag('w', 'g', 'h', 't');; + (*axes)[0].min = 400; + (*axes)[0].def = 400; + (*axes)[0].max = 700; + return true; + } + else if (file.equals("NotoSerifBengali-VF.ttf")) { + familyName->set("Noto Serif Bengali"); + *style = SkFontStyle(400, 5, SkFontStyle::kUpright_Slant); + *isFixedPitch = false; + axes->reset(1); + (*axes)[0].tag = SkSetFourByteTag('w', 'g', 'h', 't');; + (*axes)[0].min = 400; + (*axes)[0].def = 400; + (*axes)[0].max = 700; + return true; + } + else if (file.equals("NotoSerif-Bold.ttf")) { + familyName->set("Noto Serif"); + *style = SkFontStyle(700, 5, SkFontStyle::kUpright_Slant); + *isFixedPitch = false; + axes->reset(0); + return true; + } + else if (file.equals("NotoSerif-BoldItalic.ttf")) { + familyName->set("Noto Serif"); + *style = SkFontStyle(700, 5, SkFontStyle::kUpright_Slant); + *isFixedPitch = false; + axes->reset(0); + return true; + } + else if (file.equals("NotoSerifCJK-Regular.ttc")) { + familyName->set("Noto Serif CJK SC"); + *style = SkFontStyle(400, 5, SkFontStyle::kUpright_Slant); + *isFixedPitch = false; + axes->reset(0); + return true; + } + else if (file.equals("NotoSerifDevanagari-VF.ttf")) { + familyName->set("Noto Serif Devanagari"); + *style = SkFontStyle(400, 5, SkFontStyle::kUpright_Slant); + *isFixedPitch = false; + axes->reset(1); + (*axes)[0].tag = SkSetFourByteTag('w', 'g', 'h', 't');; + (*axes)[0].min = 400; + (*axes)[0].def = 400; + (*axes)[0].max = 700; + return true; + } + else if (file.equals("NotoSerifDogra-Regular.ttf")) { + familyName->set("Noto Serif Dogra"); + *style = SkFontStyle(400, 5, SkFontStyle::kUpright_Slant); + *isFixedPitch = false; + axes->reset(0); + return true; + } + else if (file.equals("NotoSerifEthiopic-VF.ttf")) { + familyName->set("Noto Serif Ethiopic"); + *style = SkFontStyle(400, 5, SkFontStyle::kUpright_Slant); + *isFixedPitch = false; + axes->reset(1); + (*axes)[0].tag = SkSetFourByteTag('w', 'g', 'h', 't');; + (*axes)[0].min = 400; + (*axes)[0].def = 400; + (*axes)[0].max = 700; + return true; + } + else if (file.equals("NotoSerifGeorgian-VF.ttf")) { + familyName->set("Noto Serif Georgian"); + *style = SkFontStyle(400, 5, SkFontStyle::kUpright_Slant); + *isFixedPitch = false; + axes->reset(1); + (*axes)[0].tag = SkSetFourByteTag('w', 'g', 'h', 't');; + (*axes)[0].min = 400; + (*axes)[0].def = 400; + (*axes)[0].max = 700; + return true; + } + else if (file.equals("NotoSerifGujarati-VF.ttf")) { + familyName->set("Noto Serif Gujarati"); + *style = SkFontStyle(400, 5, SkFontStyle::kUpright_Slant); + *isFixedPitch = false; + axes->reset(1); + (*axes)[0].tag = SkSetFourByteTag('w', 'g', 'h', 't');; + (*axes)[0].min = 400; + (*axes)[0].def = 400; + (*axes)[0].max = 700; + return true; + } + else if (file.equals("NotoSerifGurmukhi-VF.ttf")) { + familyName->set("Noto Serif Gurmukhi"); + *style = SkFontStyle(400, 5, SkFontStyle::kUpright_Slant); + *isFixedPitch = false; + axes->reset(1); + (*axes)[0].tag = SkSetFourByteTag('w', 'g', 'h', 't');; + (*axes)[0].min = 400; + (*axes)[0].def = 400; + (*axes)[0].max = 700; + return true; + } + else if (file.equals("NotoSerifHebrew-Bold.ttf")) { + familyName->set("Noto Serif Hebrew"); + *style = SkFontStyle(700, 5, SkFontStyle::kUpright_Slant); + *isFixedPitch = false; + axes->reset(0); + return true; + } + else if (file.equals("NotoSerifHebrew-Regular.ttf")) { + familyName->set("Noto Serif Hebrew"); + *style = SkFontStyle(400, 5, SkFontStyle::kUpright_Slant); + *isFixedPitch = false; + axes->reset(0); + return true; + } + else if (file.equals("NotoSerif-Italic.ttf")) { + familyName->set("Noto Serif"); + *style = SkFontStyle(400, 5, SkFontStyle::kUpright_Slant); + *isFixedPitch = false; + axes->reset(0); + return true; + } + else if (file.equals("NotoSerifKannada-VF.ttf")) { + familyName->set("Noto Serif Kannada"); + *style = SkFontStyle(400, 5, SkFontStyle::kUpright_Slant); + *isFixedPitch = false; + axes->reset(1); + (*axes)[0].tag = SkSetFourByteTag('w', 'g', 'h', 't');; + (*axes)[0].min = 400; + (*axes)[0].def = 400; + (*axes)[0].max = 700; + return true; + } + else if (file.equals("NotoSerifKhmer-Bold.otf")) { + familyName->set("Noto Serif Khmer"); + *style = SkFontStyle(700, 5, SkFontStyle::kUpright_Slant); + *isFixedPitch = false; + axes->reset(0); + return true; + } + else if (file.equals("NotoSerifKhmer-Regular.otf")) { + familyName->set("Noto Serif Khmer"); + *style = SkFontStyle(400, 5, SkFontStyle::kUpright_Slant); + *isFixedPitch = false; + axes->reset(0); + return true; + } + else if (file.equals("NotoSerifLao-Bold.ttf")) { + familyName->set("Noto Serif Lao"); + *style = SkFontStyle(700, 5, SkFontStyle::kUpright_Slant); + *isFixedPitch = false; + axes->reset(0); + return true; + } + else if (file.equals("NotoSerifLao-Regular.ttf")) { + familyName->set("Noto Serif Lao"); + *style = SkFontStyle(400, 5, SkFontStyle::kUpright_Slant); + *isFixedPitch = false; + axes->reset(0); + return true; + } + else if (file.equals("NotoSerifMalayalam-VF.ttf")) { + familyName->set("Noto Serif Malayalam"); + *style = SkFontStyle(400, 5, SkFontStyle::kUpright_Slant); + *isFixedPitch = false; + axes->reset(1); + (*axes)[0].tag = SkSetFourByteTag('w', 'g', 'h', 't');; + (*axes)[0].min = 400; + (*axes)[0].def = 400; + (*axes)[0].max = 700; + return true; + } + else if (file.equals("NotoSerifMyanmar-Bold.otf")) { + familyName->set("Noto Serif Myanmar"); + *style = SkFontStyle(700, 5, SkFontStyle::kUpright_Slant); + *isFixedPitch = false; + axes->reset(0); + return true; + } + else if (file.equals("NotoSerifMyanmar-Regular.otf")) { + familyName->set("Noto Serif Myanmar"); + *style = SkFontStyle(400, 5, SkFontStyle::kUpright_Slant); + *isFixedPitch = false; + axes->reset(0); + return true; + } + else if (file.equals("NotoSerifNyiakengPuachueHmong-VF.ttf")) { + familyName->set("Noto Serif Nyiakeng Puachue Hmong"); + *style = SkFontStyle(400, 5, SkFontStyle::kUpright_Slant); + *isFixedPitch = false; + axes->reset(1); + (*axes)[0].tag = SkSetFourByteTag('w', 'g', 'h', 't');; + (*axes)[0].min = 400; + (*axes)[0].def = 400; + (*axes)[0].max = 700; + return true; + } + else if (file.equals("NotoSerif-Regular.ttf")) { + familyName->set("Noto Serif"); + *style = SkFontStyle(400, 5, SkFontStyle::kUpright_Slant); + *isFixedPitch = false; + axes->reset(0); + return true; + } + else if (file.equals("NotoSerifSinhala-VF.ttf")) { + familyName->set("Noto Serif Sinhala"); + *style = SkFontStyle(400, 5, SkFontStyle::kUpright_Slant); + *isFixedPitch = false; + axes->reset(1); + (*axes)[0].tag = SkSetFourByteTag('w', 'g', 'h', 't');; + (*axes)[0].min = 400; + (*axes)[0].def = 400; + (*axes)[0].max = 700; + return true; + } + else if (file.equals("NotoSerifTamil-VF.ttf")) { + familyName->set("Noto Serif Tamil"); + *style = SkFontStyle(400, 5, SkFontStyle::kUpright_Slant); + *isFixedPitch = false; + axes->reset(1); + (*axes)[0].tag = SkSetFourByteTag('w', 'g', 'h', 't');; + (*axes)[0].min = 400; + (*axes)[0].def = 400; + (*axes)[0].max = 700; + return true; + } + else if (file.equals("NotoSerifTelugu-VF.ttf")) { + familyName->set("Noto Serif Telugu"); + *style = SkFontStyle(400, 5, SkFontStyle::kUpright_Slant); + *isFixedPitch = false; + axes->reset(1); + (*axes)[0].tag = SkSetFourByteTag('w', 'g', 'h', 't');; + (*axes)[0].min = 400; + (*axes)[0].def = 400; + (*axes)[0].max = 700; + return true; + } + else if (file.equals("NotoSerifThai-Bold.ttf")) { + familyName->set("Noto Serif Thai"); + *style = SkFontStyle(700, 5, SkFontStyle::kUpright_Slant); + *isFixedPitch = false; + axes->reset(0); + return true; + } + else if (file.equals("NotoSerifThai-Regular.ttf")) { + familyName->set("Noto Serif Thai"); + *style = SkFontStyle(400, 5, SkFontStyle::kUpright_Slant); + *isFixedPitch = false; + axes->reset(0); + return true; + } + else if (file.equals("NotoSerifTibetan-VF.ttf")) { + familyName->set("Noto Serif Tibetan"); + *style = SkFontStyle(400, 5, SkFontStyle::kUpright_Slant); + *isFixedPitch = false; + axes->reset(1); + (*axes)[0].tag = SkSetFourByteTag('w', 'g', 'h', 't');; + (*axes)[0].min = 400; + (*axes)[0].def = 400; + (*axes)[0].max = 700; + return true; + } + else if (file.equals("NotoSerifYezidi-VF.ttf")) { + familyName->set("Noto Serif Yezidi"); + *style = SkFontStyle(400, 5, SkFontStyle::kUpright_Slant); + *isFixedPitch = false; + axes->reset(1); + (*axes)[0].tag = SkSetFourByteTag('w', 'g', 'h', 't');; + (*axes)[0].min = 400; + (*axes)[0].def = 400; + (*axes)[0].max = 700; + return true; + } + else if (file.equals("Roboto-Regular.ttf")) { + familyName->set("Roboto"); + *style = SkFontStyle(400, 5, SkFontStyle::kUpright_Slant); + *isFixedPitch = false; + axes->reset(3); + (*axes)[0].tag = SkSetFourByteTag('w', 'g', 'h', 't');; + (*axes)[0].min = 100; + (*axes)[0].def = 400; + (*axes)[0].max = 900; + (*axes)[1].tag = SkSetFourByteTag('w', 'd', 't', 'h'); + (*axes)[1].min = 75; + (*axes)[1].def = 100; + (*axes)[1].max = 100; + (*axes)[2].tag = SkSetFourByteTag('i', 't', 'a', 'l'); + (*axes)[2].min = 0; + (*axes)[2].def = 0; + (*axes)[2].max = 1; + return true; + } + else if (file.equals("RobotoStatic-Regular.ttf")) { + // see https://android.googlesource.com/platform/frameworks/base/+/89abe560d722a6f4136b7a05d80f23b269413aad + familyName->set("RobotoStatic"); + *style = SkFontStyle(400, 5, SkFontStyle::kUpright_Slant); + *isFixedPitch = false; + axes->reset(0); + return true; + } + else if (file.equals("SourceSansPro-Bold.ttf")) { + familyName->set("Source Sans Pro"); + *style = SkFontStyle(700, 5, SkFontStyle::kUpright_Slant); + *isFixedPitch = false; + axes->reset(0); + return true; + } + else if (file.equals("SourceSansPro-BoldItalic.ttf")) { + familyName->set("Source Sans Pro"); + *style = SkFontStyle(700, 5, SkFontStyle::kUpright_Slant); + *isFixedPitch = false; + axes->reset(0); + return true; + } + else if (file.equals("SourceSansPro-Italic.ttf")) { + familyName->set("Source Sans Pro"); + *style = SkFontStyle(400, 5, SkFontStyle::kUpright_Slant); + *isFixedPitch = false; + axes->reset(0); + return true; + } + else if (file.equals("SourceSansPro-Regular.ttf")) { + familyName->set("Source Sans Pro"); + *style = SkFontStyle(400, 5, SkFontStyle::kUpright_Slant); + *isFixedPitch = false; + axes->reset(0); + return true; + } + else if (file.equals("SourceSansPro-SemiBold.ttf")) { + familyName->set("Source Sans Pro"); + *style = SkFontStyle(600, 5, SkFontStyle::kUpright_Slant); + *isFixedPitch = false; + axes->reset(0); + return true; + } + else if (file.equals("SourceSansPro-SemiBoldItalic.ttf")) { + familyName->set("Source Sans Pro"); + *style = SkFontStyle(600, 5, SkFontStyle::kUpright_Slant); + *isFixedPitch = false; + axes->reset(0); + return true; + } + + return false; +} diff --git a/third_party/skia/src/ports/SkFontMgr_android_ndk.cpp b/third_party/skia/src/ports/SkFontMgr_android_ndk.cpp --- a/third_party/skia/src/ports/SkFontMgr_android_ndk.cpp +++ b/third_party/skia/src/ports/SkFontMgr_android_ndk.cpp @@ -996,7 +996,7 @@ public: } std::vector> xmlFamilies; - SkFontMgr_Android_Parser::GetSystemFontFamilies(xmlFamilies); + SkFontMgr_Android_Parser::GetSystemFontFamilies(xmlFamilies, /*custom*/ nullptr); skia_private::THashMap> streamForPath; diff --git a/third_party/skia/src/ports/SkFontMgr_android_parser.cpp b/third_party/skia/src/ports/SkFontMgr_android_parser.cpp --- a/third_party/skia/src/ports/SkFontMgr_android_parser.cpp +++ b/third_party/skia/src/ports/SkFontMgr_android_parser.cpp @@ -713,14 +713,27 @@ static const XML_Memory_Handling_Suite sk_XML_alloc = { */ static int parse_config_file(const char* filename, std::vector>& families, - const SkString& basePath, bool isFallback) + const SkString& basePath, bool isFallback, + const SkFontMgr_Android_CustomFonts* custom = nullptr) { SkFILEStream file(filename); - - // Some of the files we attempt to parse (in particular, /vendor/etc/fallback_fonts.xml) - // are optional - failure here is okay because one of these optional files may not exist. - if (!file.isValid()) { - SkDebugf(SK_FONTMGR_ANDROID_PARSER_PREFIX "'%s' could not be opened\n", filename); + std::unique_ptr stream; + if (!custom && filename[0] != '#') { + // Some of the files we attempt to parse (in particular, /vendor/etc/fallback_fonts.xml) + // are optional - failure here is okay because one of these optional files may not exist. + if (!file.isValid()) { + SkDebugf(SK_FONTMGR_ANDROID_PARSER_PREFIX "'%s' could not be opened\n", filename); + return -1; + } + stream = file.fork(); + } else if (custom) { + stream = custom->getPlatformFile(filename); + if (!stream) { + SkDebugf(SK_FONTMGR_ANDROID_PARSER_PREFIX "'%s' platform file map not found\n", filename); + return -1; + } + } else { + SkDebugf(SK_FONTMGR_ANDROID_PARSER_PREFIX "'%s' custom fonts not set\n", filename); return -1; } @@ -752,8 +765,8 @@ static int parse_config_file(const char* filename, SkDebugf(SK_FONTMGR_ANDROID_PARSER_PREFIX "could not buffer enough to continue\n"); return -1; } - size_t len = file.read(buffer, bufferSize); - done = file.isAtEnd(); + size_t len = stream->read(buffer, bufferSize); + done = stream->isAtEnd(); XML_Status status = XML_ParseBuffer(parser, len, done); if (XML_STATUS_ERROR == status) { XML_Error error = XML_GetErrorCode(parser); @@ -765,6 +778,23 @@ static int parse_config_file(const char* filename, return -1; } } + if (custom) { + // remove NotoColorEmojiLegacy.ttf + for (int i = 0; i < families.size(); ++i) { + bool exists = false; + auto& family = families[i]; + for (auto& font : family->fFonts) { + if (font.fFileName.equals("NotoColorEmojiLegacy.ttf")) { + exists = true; + break; + } + } + if (exists) { + families.erase(families.begin() + i); + break; + } + } + } return self.fVersion; } @@ -827,8 +857,10 @@ static void append_fallback_font_families_for_locale( static void append_system_fallback_font_families( std::vector>& fallbackFonts, - const SkString& basePath) + const SkString& basePath, + const SkFontMgr_Android_CustomFonts* custom) { + if (custom) return; parse_config_file(FALLBACK_FONTS_FILE, fallbackFonts, basePath, true); append_fallback_font_families_for_locale(fallbackFonts, LOCALE_FALLBACK_FONTS_SYSTEM_DIR, @@ -837,8 +869,10 @@ static void append_system_fallback_font_families( static void mixin_vendor_fallback_font_families( std::vector>& fallbackFonts, - const SkString& basePath) + const SkString& basePath, + const SkFontMgr_Android_CustomFonts* custom) { + if (custom) return; std::vector> vendorFonts; parse_config_file(VENDOR_FONTS_FILE, vendorFonts, basePath, true); append_fallback_font_families_for_locale(vendorFonts, @@ -870,7 +904,8 @@ static void mixin_vendor_fallback_font_families( } void SkFontMgr_Android_Parser::GetSystemFontFamilies( - std::vector>& fontFamilies) { + std::vector>& fontFamilies, + const SkFontMgr_Android_CustomFonts* custom) { static constexpr char kFontFilePrefix[] = "/fonts/"; // Version 21 of the system font configuration does not need any fallback configuration files. @@ -881,15 +916,16 @@ void SkFontMgr_Android_Parser::GetSystemFontFamilies( // Product fonts (fonts_customization.xml) leverage // Therefore, we only attempt to parse them on modern devices (Android Lollipop+). // Pre-21 systems fall through to the legacy fallback fonts handling below. + if (!custom) SkFontMgr_Android_Parser::GetCustomFontFamilies( - fontFamilies, basePath, PRODUCT_CUSTOMIZATION_FILE, nullptr, nullptr); + fontFamilies, basePath, custom, PRODUCT_CUSTOMIZATION_FILE, nullptr, nullptr); return; } // Append all the fallback fonts to system fonts std::vector> fallbackFonts; - append_system_fallback_font_families(fallbackFonts, basePath); - mixin_vendor_fallback_font_families(fallbackFonts, basePath); + append_system_fallback_font_families(fallbackFonts, basePath, custom); + mixin_vendor_fallback_font_families(fallbackFonts, basePath, custom); fontFamilies.insert(fontFamilies.end(), std::make_move_iterator(fallbackFonts.begin()), std::make_move_iterator(fallbackFonts.end())); @@ -898,15 +934,16 @@ void SkFontMgr_Android_Parser::GetSystemFontFamilies( void SkFontMgr_Android_Parser::GetCustomFontFamilies( std::vector>& fontFamilies, const SkString& basePath, + const SkFontMgr_Android_CustomFonts* custom, const char* fontsXml, const char* fallbackFontsXml, const char* langFallbackFontsDir) { if (fontsXml) { - parse_config_file(fontsXml, fontFamilies, basePath, false); + parse_config_file(fontsXml, fontFamilies, basePath, false, custom); } if (fallbackFontsXml) { - parse_config_file(fallbackFontsXml, fontFamilies, basePath, true); + parse_config_file(fallbackFontsXml, fontFamilies, basePath, true, custom); } if (langFallbackFontsDir) { append_fallback_font_families_for_locale(fontFamilies, diff --git a/third_party/skia/src/ports/SkFontMgr_android_parser.h b/third_party/skia/src/ports/SkFontMgr_android_parser.h --- a/third_party/skia/src/ports/SkFontMgr_android_parser.h +++ b/third_party/skia/src/ports/SkFontMgr_android_parser.h @@ -17,6 +17,7 @@ #include "include/private/base/SkTArray.h" #include "include/private/base/SkTDArray.h" #include "src/core/SkTHash.h" +#include "include/ports/SkFontMgr_android.h" #include #include @@ -109,11 +110,13 @@ struct FontFamily { namespace SkFontMgr_Android_Parser { /** Parses system font configuration files and appends result to fontFamilies. */ -void GetSystemFontFamilies(std::vector>& fontFamilies); +void GetSystemFontFamilies(std::vector>& fontFamilies, + const SkFontMgr_Android_CustomFonts* custom); /** Parses font configuration files and appends result to fontFamilies. */ void GetCustomFontFamilies(std::vector>& fontFamilies, const SkString& basePath, + const SkFontMgr_Android_CustomFonts* custom, const char* fontsXml, const char* fallbackFontsXml, const char* langFallbackFontsDir = nullptr); --