| // 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 "cc/paint/paint_typeface.h" |
| #include "build/build_config.h" |
| #include "third_party/skia/include/core/SkFontMgr.h" |
| #include "third_party/skia/include/ports/SkFontConfigInterface.h" |
| |
| namespace cc { |
| |
| // static |
| PaintTypeface PaintTypeface::TestTypeface() { |
| PaintTypeface typeface; |
| typeface.type_ = Type::kTestTypeface; |
| typeface.sk_typeface_ = SkTypeface::MakeDefault(); |
| typeface.CreateSkTypeface(); |
| return typeface; |
| } |
| |
| // static |
| PaintTypeface PaintTypeface::FromSkTypeface(const sk_sp<SkTypeface>& tf) { |
| PaintTypeface typeface; |
| typeface.type_ = Type::kSkTypeface; |
| typeface.sk_typeface_ = tf; |
| typeface.CreateSkTypeface(); |
| return typeface; |
| } |
| |
| // static |
| PaintTypeface PaintTypeface::FromFontConfigInterfaceIdAndTtcIndex( |
| int config_id, |
| int ttc_index) { |
| PaintTypeface typeface; |
| typeface.type_ = Type::kFontConfigInterfaceIdAndTtcIndex; |
| typeface.font_config_interface_id_ = config_id; |
| typeface.ttc_index_ = ttc_index; |
| typeface.CreateSkTypeface(); |
| return typeface; |
| } |
| |
| // static |
| PaintTypeface PaintTypeface::FromFilenameAndTtcIndex( |
| const std::string& filename, |
| int ttc_index) { |
| PaintTypeface typeface; |
| typeface.type_ = Type::kFilenameAndTtcIndex; |
| typeface.filename_ = filename; |
| typeface.ttc_index_ = ttc_index; |
| typeface.CreateSkTypeface(); |
| return typeface; |
| } |
| |
| // static |
| PaintTypeface PaintTypeface::FromFamilyNameAndFontStyle( |
| const std::string& family_name, |
| const SkFontStyle& font_style) { |
| PaintTypeface typeface; |
| typeface.type_ = Type::kFamilyNameAndFontStyle; |
| typeface.family_name_ = family_name; |
| typeface.font_style_ = font_style; |
| typeface.CreateSkTypeface(); |
| return typeface; |
| } |
| |
| PaintTypeface::PaintTypeface() = default; |
| PaintTypeface::PaintTypeface(const PaintTypeface& other) { |
| *this = other; |
| } |
| PaintTypeface::PaintTypeface(PaintTypeface&& other) = default; |
| PaintTypeface::~PaintTypeface() { |
| // TODO(crbug.com/785682): Debugging possible ref counting issue. |
| if (sk_typeface_) { |
| // We should be a strong owner of this reference. However, to debug a |
| // possible ref counting issue, we also ensured that we're a weak owner of |
| // this as well. This means that we should be able to always acquire a |
| // strong reference (ie the class isn't deleted because we're weak owners, |
| // and it should always succeed because we're strong owners). |
| if (sk_typeface_->try_ref()) { |
| sk_typeface_->unref(); |
| } else { |
| CHECK(false) << "SkTypeface ref-counting problem detected."; |
| } |
| sk_typeface_->weak_unref(); |
| } |
| // Explicitly delete the typeface so that any crashes resulting from this |
| // would point to this line. |
| sk_typeface_ = nullptr; |
| } |
| |
| PaintTypeface& PaintTypeface::operator=(const PaintTypeface& other) { |
| sk_id_ = other.sk_id_; |
| sk_typeface_ = other.sk_typeface_; |
| |
| // TODO(crbug.com/785682): Debugging possible ref counting issue. |
| if (sk_typeface_) { |
| // Since we're copying this object which will do a weak unref in the dtor, |
| // ensure to bump the weak ref one more time. |
| sk_typeface_->weak_ref(); |
| } |
| |
| type_ = other.type_; |
| font_config_interface_id_ = other.font_config_interface_id_; |
| ttc_index_ = other.ttc_index_; |
| filename_ = other.filename_; |
| family_name_ = other.family_name_; |
| font_style_ = other.font_style_; |
| return *this; |
| } |
| |
| PaintTypeface& PaintTypeface::operator=(PaintTypeface&& other) = default; |
| |
| void PaintTypeface::CreateSkTypeface() { |
| // MacOS doesn't support this type of creation and relies on NSFonts instead. |
| #if !defined(OS_MACOSX) |
| switch (type_) { |
| case Type::kTestTypeface: |
| // Nothing to do here. |
| break; |
| case Type::kSkTypeface: |
| // Nothing to do here. |
| break; |
| case Type::kFontConfigInterfaceIdAndTtcIndex: { |
| // Mimic FontCache::CreateTypeface defines to ensure same behavior. |
| #if !defined(OS_WIN) && !defined(OS_ANDROID) && !defined(OS_FUCHSIA) |
| sk_sp<SkFontConfigInterface> fci(SkFontConfigInterface::RefGlobal()); |
| SkFontConfigInterface::FontIdentity font_identity; |
| font_identity.fID = font_config_interface_id_; |
| font_identity.fTTCIndex = ttc_index_; |
| sk_typeface_ = fci->makeTypeface(font_identity); |
| #endif |
| break; |
| } |
| case Type::kFilenameAndTtcIndex: |
| // Mimic FontCache::CreateTypeface defines to ensure same behavior. |
| #if !defined(OS_WIN) && !defined(OS_ANDROID) && !defined(OS_FUCHSIA) |
| sk_typeface_ = SkTypeface::MakeFromFile(filename_.c_str(), ttc_index_); |
| #endif |
| break; |
| case Type::kFamilyNameAndFontStyle: { |
| // This is a fallthrough in all cases in FontCache::CreateTypeface, so |
| // this is done unconditionally. Since we create the typeface upon |
| // PaintTypeface creation, this should be safe in all cases. |
| auto fm(SkFontMgr::RefDefault()); |
| sk_typeface_ = fm->legacyMakeTypeface(family_name_.c_str(), font_style_); |
| break; |
| } |
| } |
| #endif // !defined(OS_MACOSX) |
| sk_id_ = sk_typeface_ ? sk_typeface_->uniqueID() : 0; |
| |
| // TODO(crbug.com/785682): Debugging possible ref counting issue. |
| if (sk_typeface_) |
| sk_typeface_->weak_ref(); |
| } |
| |
| } // namespace cc |