font_collection.cc 5.2 KB
Newer Older
M
Michael Goderbauer 已提交
1
// Copyright 2013 The Flutter Authors. All rights reserved.
2 3 4 5
// 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"
6

7
#include <mutex>
8

9
#include "flutter/lib/ui/text/asset_manager_font_provider.h"
10 11
#include "flutter/lib/ui/ui_dart_state.h"
#include "flutter/lib/ui/window/window.h"
12
#include "flutter/runtime/test_font_data.h"
13 14
#include "rapidjson/document.h"
#include "rapidjson/rapidjson.h"
15
#include "third_party/skia/include/core/SkFontMgr.h"
16
#include "third_party/skia/include/core/SkGraphics.h"
17
#include "third_party/skia/include/core/SkStream.h"
18
#include "third_party/skia/include/core/SkTypeface.h"
19 20 21 22
#include "third_party/tonic/dart_args.h"
#include "third_party/tonic/dart_library_natives.h"
#include "third_party/tonic/logging/dart_invoke.h"
#include "third_party/tonic/typed_data/uint8_list.h"
23
#include "txt/asset_font_manager.h"
24
#include "txt/test_font_manager.h"
25 26 27

namespace blink {

28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46
namespace {

void LoadFontFromList(tonic::Uint8List& font_data,
                      Dart_Handle callback,
                      std::string family_name) {
  FontCollection& font_collection =
      UIDartState::Current()->window()->client()->GetFontCollection();
  font_collection.LoadFontFromList(font_data.data(), font_data.num_elements(),
                                   family_name);
  font_data.Release();
  tonic::DartInvoke(callback, {tonic::ToDart(0)});
}

void _LoadFontFromList(Dart_NativeArguments args) {
  tonic::DartCallStatic(LoadFontFromList, args);
}

}  // namespace

47 48
FontCollection::FontCollection()
    : collection_(std::make_shared<txt::FontCollection>()) {
49
  collection_->SetDefaultFontManager(SkFontMgr::RefDefault());
50 51 52

  dynamic_font_manager_ = sk_make_sp<txt::DynamicFontManager>();
  collection_->SetDynamicFontManager(dynamic_font_manager_);
53 54
}

55 56 57 58
FontCollection::~FontCollection() {
  collection_.reset();
  SkGraphics::PurgeFontCache();
}
59

60 61 62 63 64 65
void FontCollection::RegisterNatives(tonic::DartLibraryNatives* natives) {
  natives->Register({
      {"loadFontFromList", _LoadFontFromList, 3, true},
  });
}

66 67 68 69
std::shared_ptr<txt::FontCollection> FontCollection::GetFontCollection() const {
  return collection_;
}

70 71
void FontCollection::RegisterFonts(
    std::shared_ptr<AssetManager> asset_manager) {
72 73 74
  std::unique_ptr<fml::Mapping> manifest_mapping =
      asset_manager->GetAsMapping("FontManifest.json");
  if (manifest_mapping == nullptr) {
75
    FML_DLOG(WARNING) << "Could not find the font manifest in the asset store.";
76 77 78 79
    return;
  }

  rapidjson::Document document;
80 81 82 83
  static_assert(sizeof(decltype(document)::Ch) == sizeof(uint8_t), "");
  document.Parse(reinterpret_cast<const decltype(document)::Ch*>(
                     manifest_mapping->GetMapping()),
                 manifest_mapping->GetSize());
84 85

  if (document.HasParseError()) {
86
    FML_DLOG(WARNING) << "Error parsing the font manifest in the asset store.";
87 88 89 90 91 92 93 94 95
    return;
  }

  // Structure described in https://flutter.io/custom-fonts/

  if (!document.IsArray()) {
    return;
  }

96 97
  auto font_provider =
      std::make_unique<AssetManagerFontProvider>(asset_manager);
98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121

  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.
122 123
      font_provider->RegisterAsset(family_name->value.GetString(),
                                   font_asset->value.GetString());
124 125 126
    }
  }

127
  collection_->SetAssetFontManager(
128
      sk_make_sp<txt::AssetFontManager>(std::move(font_provider)));
129 130
}

131 132
void FontCollection::RegisterTestFonts() {
  sk_sp<SkTypeface> test_typeface =
133
      SkTypeface::MakeFromStream(GetTestFontData());
134

135 136
  std::unique_ptr<txt::TypefaceFontAssetProvider> font_provider =
      std::make_unique<txt::TypefaceFontAssetProvider>();
137

138 139
  font_provider->RegisterTypeface(std::move(test_typeface),
                                  GetTestFontFamilyName());
140

141
  collection_->SetTestFontManager(sk_make_sp<txt::TestFontManager>(
142
      std::move(font_provider), GetTestFontFamilyName()));
143 144

  collection_->DisableFontFallback();
145 146
}

147 148 149 150 151 152 153 154 155 156 157 158 159 160
void FontCollection::LoadFontFromList(const uint8_t* font_data,
                                      int length,
                                      std::string family_name) {
  std::unique_ptr<SkStreamAsset> font_stream =
      std::make_unique<SkMemoryStream>(font_data, length, true);
  sk_sp<SkTypeface> typeface =
      SkTypeface::MakeFromStream(std::move(font_stream));
  txt::TypefaceFontAssetProvider& font_provider =
      dynamic_font_manager_->font_provider();
  if (family_name.empty()) {
    font_provider.RegisterTypeface(typeface);
  } else {
    font_provider.RegisterTypeface(typeface, family_name);
  }
161
  collection_->ClearFontFamilyCache();
162 163
}

164
}  // namespace blink