blob: b07472f7e7292f1aff1b6fc1aac52ef9a03cfdcb [file] [log] [blame]
// Copyright 2013 The Flutter 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/asset_manager_font_provider.h"
#include "flutter/fml/logging.h"
#include "third_party/skia/include/core/SkData.h"
#include "third_party/skia/include/core/SkStream.h"
#include "third_party/skia/include/core/SkString.h"
#include "third_party/skia/include/core/SkTypeface.h"
namespace flutter {
namespace {
void MappingReleaseProc(const void* ptr, void* context) {
delete reinterpret_cast<fml::Mapping*>(context);
}
} // anonymous namespace
AssetManagerFontProvider::AssetManagerFontProvider(
std::shared_ptr<AssetManager> asset_manager)
: asset_manager_(asset_manager) {}
AssetManagerFontProvider::~AssetManagerFontProvider() = default;
// |FontAssetProvider|
size_t AssetManagerFontProvider::GetFamilyCount() const {
return family_names_.size();
}
// |FontAssetProvider|
std::string AssetManagerFontProvider::GetFamilyName(int index) const {
FML_DCHECK(index >= 0 && static_cast<size_t>(index) < family_names_.size());
return family_names_[index];
}
// |FontAssetProvider|
SkFontStyleSet* AssetManagerFontProvider::MatchFamily(
const std::string& family_name) {
auto found = registered_families_.find(CanonicalFamilyName(family_name));
if (found == registered_families_.end()) {
return nullptr;
}
sk_sp<SkFontStyleSet> font_style_set = found->second;
return font_style_set.release();
}
void AssetManagerFontProvider::RegisterAsset(std::string family_name,
std::string asset) {
std::string canonical_name = CanonicalFamilyName(family_name);
auto family_it = registered_families_.find(canonical_name);
if (family_it == registered_families_.end()) {
family_names_.push_back(family_name);
auto value = std::make_pair(
canonical_name,
sk_make_sp<AssetManagerFontStyleSet>(asset_manager_, family_name));
family_it = registered_families_.emplace(value).first;
}
family_it->second->registerAsset(asset);
}
AssetManagerFontStyleSet::AssetManagerFontStyleSet(
std::shared_ptr<AssetManager> asset_manager,
std::string family_name)
: asset_manager_(asset_manager), family_name_(family_name) {}
AssetManagerFontStyleSet::~AssetManagerFontStyleSet() = default;
void AssetManagerFontStyleSet::registerAsset(std::string asset) {
assets_.emplace_back(asset);
}
int AssetManagerFontStyleSet::count() {
return assets_.size();
}
void AssetManagerFontStyleSet::getStyle(int index,
SkFontStyle* style,
SkString* name) {
FML_DCHECK(index < static_cast<int>(assets_.size()));
if (style) {
sk_sp<SkTypeface> typeface(createTypeface(index));
if (typeface) {
*style = typeface->fontStyle();
}
}
if (name) {
*name = family_name_.c_str();
}
}
SkTypeface* AssetManagerFontStyleSet::createTypeface(int i) {
size_t index = i;
if (index >= assets_.size()) {
return nullptr;
}
TypefaceAsset& asset = assets_[index];
if (!asset.typeface) {
std::unique_ptr<fml::Mapping> asset_mapping =
asset_manager_->GetAsMapping(asset.asset);
if (asset_mapping == nullptr) {
return nullptr;
}
fml::Mapping* asset_mapping_ptr = asset_mapping.release();
sk_sp<SkData> asset_data = SkData::MakeWithProc(
asset_mapping_ptr->GetMapping(), asset_mapping_ptr->GetSize(),
MappingReleaseProc, asset_mapping_ptr);
std::unique_ptr<SkMemoryStream> stream = SkMemoryStream::Make(asset_data);
// Ownership of the stream is transferred.
asset.typeface = SkTypeface::MakeFromStream(std::move(stream));
if (!asset.typeface) {
FML_DLOG(ERROR) << "Unable to load font asset for family: "
<< family_name_;
return nullptr;
}
}
return SkRef(asset.typeface.get());
}
SkTypeface* AssetManagerFontStyleSet::matchStyle(const SkFontStyle& pattern) {
return matchStyleCSS3(pattern);
}
AssetManagerFontStyleSet::TypefaceAsset::TypefaceAsset(std::string a)
: asset(std::move(a)) {}
AssetManagerFontStyleSet::TypefaceAsset::TypefaceAsset(
const AssetManagerFontStyleSet::TypefaceAsset& other) = default;
AssetManagerFontStyleSet::TypefaceAsset::~TypefaceAsset() = default;
} // namespace flutter