blob: 67feecf60d78d00984cefd797f2d6e1a4dc6b207 [file] [log] [blame]
* Copyright (C) 2018 The Android Open Source Project
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* See the License for the specific language governing permissions and
* limitations under the License.
#include <memory>
#include <mutex>
#include <unordered_set>
#include "minikin/Buffer.h"
#include "minikin/FontStyle.h"
#include "minikin/FontVariation.h"
#include "minikin/HbUtils.h"
#include "minikin/LocaleList.h"
#include "minikin/Macros.h"
#include "minikin/MinikinFont.h"
namespace minikin {
class Font;
// attributes representing transforms (fake bold, fake italic) to match styles
class FontFakery {
FontFakery() : mFakeBold(false), mFakeItalic(false) {}
FontFakery(bool fakeBold, bool fakeItalic) : mFakeBold(fakeBold), mFakeItalic(fakeItalic) {}
// TODO: want to support graded fake bolding
bool isFakeBold() { return mFakeBold; }
bool isFakeItalic() { return mFakeItalic; }
inline bool operator==(const FontFakery& o) const {
return mFakeBold == o.mFakeBold && mFakeItalic == o.mFakeItalic;
inline bool operator!=(const FontFakery& o) const { return !(*this == o); }
bool mFakeBold;
bool mFakeItalic;
struct FakedFont {
inline bool operator==(const FakedFont& o) const {
return font == o.font && fakery == o.fakery;
inline bool operator!=(const FakedFont& o) const { return !(*this == o); }
// ownership is the enclosing FontCollection
// FakedFont will be stored in the LayoutCache. It is not a good idea too keep font instance
// even if the enclosing FontCollection, i.e. Typeface is GC-ed. The layout cache is only
// purged when it is overflown, thus intentionally keep only reference.
const std::shared_ptr<Font>& font;
FontFakery fakery;
// Represents a single font file.
class Font {
class Builder {
Builder(const std::shared_ptr<MinikinFont>& typeface) : mTypeface(typeface) {}
// Override the font style. If not called, info from OS/2 table is used.
Builder& setStyle(FontStyle style) {
mWeight = style.weight();
mSlant = style.slant();
mIsWeightSet = mIsSlantSet = true;
return *this;
// Override the font weight. If not called, info from OS/2 table is used.
Builder& setWeight(uint16_t weight) {
mWeight = weight;
mIsWeightSet = true;
return *this;
// Override the font slant. If not called, info from OS/2 table is used.
Builder& setSlant(FontStyle::Slant slant) {
mSlant = slant;
mIsSlantSet = true;
return *this;
Builder& setLocaleListId(uint32_t id) {
mLocaleListId = id;
return *this;
std::shared_ptr<Font> build();
std::shared_ptr<MinikinFont> mTypeface;
uint16_t mWeight = static_cast<uint16_t>(FontStyle::Weight::NORMAL);
FontStyle::Slant mSlant = FontStyle::Slant::UPRIGHT;
uint32_t mLocaleListId = kEmptyLocaleListId;
bool mIsWeightSet = false;
bool mIsSlantSet = false;
// Type for functions to load MinikinFont lazily.
using TypefaceLoader = std::shared_ptr<MinikinFont>(BufferReader reader);
// Type for functions to read MinikinFont metadata and return
// TypefaceLoader.
using TypefaceReader = TypefaceLoader*(BufferReader* reader);
// Type for functions to write MinikinFont metadata.
using TypefaceWriter = void(BufferWriter* writer, const MinikinFont* typeface);
template <TypefaceReader typefaceReader>
static std::shared_ptr<Font> readFrom(BufferReader* reader, uint32_t localeListId) {
FontStyle style = FontStyle(reader);
BufferReader typefaceMetadataReader = *reader;
TypefaceLoader* typefaceLoader = typefaceReader(reader);
return std::shared_ptr<Font>(
new Font(style, typefaceMetadataReader, typefaceLoader, localeListId));
template <TypefaceWriter typefaceWriter>
void writeTo(BufferWriter* writer) const {
typefaceWriter(writer, typeface().get());
// This locale list is just for API compatibility. This is not used in font selection or family
// fallback.
uint32_t getLocaleListId() const { return mLocaleListId; }
const std::shared_ptr<MinikinFont>& typeface() const;
inline FontStyle style() const { return mStyle; }
const HbFontUniquePtr& baseFont() const;
BufferReader typefaceMetadataReader() const { return mTypefaceMetadataReader; }
std::unordered_set<AxisTag> getSupportedAxes() const;
// Use Builder instead.
Font(std::shared_ptr<MinikinFont>&& typeface, FontStyle style, HbFontUniquePtr&& baseFont,
uint32_t localeListId)
: mTypeface(std::move(typeface)),
mLocaleListId(localeListId) {}
Font(FontStyle style, BufferReader typefaceMetadataReader, TypefaceLoader* typefaceLoader,
uint32_t localeListId)
: mStyle(style),
mLocaleListId(localeListId) {}
void initTypefaceLocked() const EXCLUSIVE_LOCKS_REQUIRED(mTypefaceMutex);
static HbFontUniquePtr prepareFont(const std::shared_ptr<MinikinFont>& typeface);
static FontStyle analyzeStyle(const HbFontUniquePtr& font);
// Lazy-initialized if created by readFrom().
mutable std::shared_ptr<MinikinFont> mTypeface GUARDED_BY(mTypefaceMutex);
FontStyle mStyle;
// Lazy-initialized if created by readFrom().
mutable HbFontUniquePtr mBaseFont GUARDED_BY(mTypefaceMutex);
mutable std::mutex mTypefaceMutex;
// Non-null if created by readFrom().
TypefaceLoader* mTypefaceLoader;
// Non-null if created by readFrom().
BufferReader mTypefaceMetadataReader;
uint32_t mLocaleListId;
// Stop copying and moving
Font(Font&& o) = delete;
Font& operator=(Font&& o) = delete;
Font(const Font& o) = delete;
Font& operator=(const Font& o) = delete;
} // namespace minikin
#endif // MINIKIN_FONT_H