| // 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 <mutex> |
| #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" |
| |
| 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<txt::FontCollection>()) { |
| collection_->PushBack(SkFontMgr::RefDefault()); |
| } |
| |
| FontCollection::~FontCollection() = default; |
| |
| std::shared_ptr<txt::FontCollection> FontCollection::GetFontCollection() const { |
| return collection_; |
| } |
| |
| void FontCollection::RegisterFontsFromAssetStore( |
| fxl::RefPtr<blink::ZipAssetStore> asset_store) { |
| if (!asset_store) { |
| return; |
| } |
| |
| std::vector<uint8_t> manifest_data; |
| if (!asset_store->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<decltype(document)::Ch*>(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<txt::AssetDataProvider>(); |
| |
| 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<uint8_t> font_data; |
| if (asset_store->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_->PushFront( |
| sk_make_sp<txt::AssetFontManager>(std::move(font_asset_data_provider))); |
| } |
| |
| } // namespace blink |