// Copyright 2017 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. #include "flutter/lib/ui/text/font_collection.h" #include #include "flutter/runtime/test_font_data.h" #include "third_party/rapidjson/rapidjson/document.h" #include "third_party/rapidjson/rapidjson/rapidjson.h" #include "third_party/skia/include/core/SkStream.h" #include "third_party/skia/include/ports/SkFontMgr.h" #include "txt/asset_font_manager.h" #include "txt/test_font_manager.h" namespace blink { FontCollection& FontCollection::ForProcess() { static std::once_flag once = {}; static FontCollection* gCollection = nullptr; std::call_once(once, []() { gCollection = new FontCollection(); }); return *gCollection; } FontCollection::FontCollection() : collection_(std::make_shared()) { collection_->SetDefaultFontManager(SkFontMgr::RefDefault()); } FontCollection::~FontCollection() = default; std::shared_ptr FontCollection::GetFontCollection() const { return collection_; } void FontCollection::RegisterFonts(const AssetManager& asset_manager) { std::vector manifest_data; if (!asset_manager.GetAsBuffer("FontManifest.json", &manifest_data)) { FXL_DLOG(WARNING) << "Could not find the font manifest in the asset store."; return; } rapidjson::Document document; static_assert(sizeof(decltype(manifest_data)::value_type) == sizeof(decltype(document)::Ch), ""); document.Parse( reinterpret_cast(manifest_data.data()), manifest_data.size()); if (document.HasParseError()) { FXL_DLOG(WARNING) << "Error parsing the font manifest in the asset store."; return; } // Structure described in https://flutter.io/custom-fonts/ if (!document.IsArray()) { return; } auto font_asset_data_provider = std::make_unique(); for (const auto& family : document.GetArray()) { auto family_name = family.FindMember("family"); if (family_name == family.MemberEnd() || !family_name->value.IsString()) { continue; } auto family_fonts = family.FindMember("fonts"); if (family_fonts == family.MemberEnd() || !family_fonts->value.IsArray()) { continue; } for (const auto& family_font : family_fonts->value.GetArray()) { if (!family_font.IsObject()) { continue; } auto font_asset = family_font.FindMember("asset"); if (font_asset == family_font.MemberEnd() || !font_asset->value.IsString()) { continue; } // TODO: Handle weights and styles. std::vector font_data; if (asset_manager.GetAsBuffer(font_asset->value.GetString(), &font_data)) { // The data must be copied because it needs to be moved into the // typeface as a stream. auto data = SkMemoryStream::MakeCopy(font_data.data(), font_data.size()); // Ownership of the stream is transferred. auto typeface = SkTypeface::MakeFromStream(data.release()); font_asset_data_provider->RegisterTypeface( std::move(typeface), family_name->value.GetString()); } } } collection_->SetAssetFontManager( sk_make_sp(std::move(font_asset_data_provider))); } void FontCollection::RegisterTestFonts() { sk_sp test_typeface = SkTypeface::MakeFromStream(GetTestFontData().release()); std::unique_ptr asset_data_provider = std::make_unique(); asset_data_provider->RegisterTypeface(std::move(test_typeface), GetTestFontFamilyName()); collection_->SetTestFontManager(sk_make_sp( std::move(asset_data_provider), GetTestFontFamilyName())); collection_->DisableFontFallback(); } } // namespace blink