1/* 2 * Copyright (C) 2013 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17#ifndef MINIKIN_FONT_FAMILY_H 18#define MINIKIN_FONT_FAMILY_H 19 20#include <memory> 21#include <string> 22#include <unordered_set> 23#include <vector> 24 25#include <hb.h> 26 27#include <utils/TypeHelpers.h> 28 29#include <minikin/SparseBitSet.h> 30 31namespace minikin { 32 33class MinikinFont; 34 35// FontStyle represents all style information needed to select an actual font 36// from a collection. The implementation is packed into two 32-bit words 37// so it can be efficiently copied, embedded in other objects, etc. 38class FontStyle { 39public: 40 FontStyle() : FontStyle(0 /* variant */, 4 /* weight */, false /* italic */) {} 41 FontStyle(int weight, bool italic) : FontStyle(0 /* variant */, weight, italic) {} 42 FontStyle(uint32_t langListId) // NOLINT(implicit) 43 : FontStyle(langListId, 0 /* variant */, 4 /* weight */, false /* italic */) {} 44 45 FontStyle(int variant, int weight, bool italic); 46 FontStyle(uint32_t langListId, int variant, int weight, bool italic); 47 48 int getWeight() const { return bits & kWeightMask; } 49 bool getItalic() const { return (bits & kItalicMask) != 0; } 50 int getVariant() const { return (bits >> kVariantShift) & kVariantMask; } 51 uint32_t getLanguageListId() const { return mLanguageListId; } 52 53 bool operator==(const FontStyle other) const { 54 return bits == other.bits && mLanguageListId == other.mLanguageListId; 55 } 56 57 android::hash_t hash() const; 58 59 // Looks up a language list from an internal cache and returns its ID. 60 // If the passed language list is not in the cache, registers it and returns newly assigned ID. 61 static uint32_t registerLanguageList(const std::string& languages); 62private: 63 static const uint32_t kWeightMask = (1 << 4) - 1; 64 static const uint32_t kItalicMask = 1 << 4; 65 static const int kVariantShift = 5; 66 static const uint32_t kVariantMask = (1 << 2) - 1; 67 68 static uint32_t pack(int variant, int weight, bool italic); 69 70 uint32_t bits; 71 uint32_t mLanguageListId; 72}; 73 74enum FontVariant { 75 VARIANT_DEFAULT = 0, 76 VARIANT_COMPACT = 1, 77 VARIANT_ELEGANT = 2, 78}; 79 80inline android::hash_t hash_type(const FontStyle &style) { 81 return style.hash(); 82} 83 84// attributes representing transforms (fake bold, fake italic) to match styles 85class FontFakery { 86public: 87 FontFakery() : mFakeBold(false), mFakeItalic(false) { } 88 FontFakery(bool fakeBold, bool fakeItalic) : mFakeBold(fakeBold), mFakeItalic(fakeItalic) { } 89 // TODO: want to support graded fake bolding 90 bool isFakeBold() { return mFakeBold; } 91 bool isFakeItalic() { return mFakeItalic; } 92private: 93 bool mFakeBold; 94 bool mFakeItalic; 95}; 96 97struct FakedFont { 98 // ownership is the enclosing FontCollection 99 MinikinFont* font; 100 FontFakery fakery; 101}; 102 103typedef uint32_t AxisTag; 104 105struct Font { 106 Font(const std::shared_ptr<MinikinFont>& typeface, FontStyle style); 107 Font(std::shared_ptr<MinikinFont>&& typeface, FontStyle style); 108 Font(Font&& o); 109 Font(const Font& o); 110 111 std::shared_ptr<MinikinFont> typeface; 112 FontStyle style; 113 114 std::unordered_set<AxisTag> getSupportedAxesLocked() const; 115}; 116 117struct FontVariation { 118 FontVariation(AxisTag axisTag, float value) : axisTag(axisTag), value(value) {} 119 AxisTag axisTag; 120 float value; 121}; 122 123class FontFamily { 124public: 125 explicit FontFamily(std::vector<Font>&& fonts); 126 FontFamily(int variant, std::vector<Font>&& fonts); 127 FontFamily(uint32_t langId, int variant, std::vector<Font>&& fonts); 128 129 // TODO: Good to expose FontUtil.h. 130 static bool analyzeStyle(const std::shared_ptr<MinikinFont>& typeface, int* weight, 131 bool* italic); 132 FakedFont getClosestMatch(FontStyle style) const; 133 134 uint32_t langId() const { return mLangId; } 135 int variant() const { return mVariant; } 136 137 // API's for enumerating the fonts in a family. These don't guarantee any particular order 138 size_t getNumFonts() const { return mFonts.size(); } 139 const std::shared_ptr<MinikinFont>& getFont(size_t index) const { 140 return mFonts[index].typeface; 141 } 142 FontStyle getStyle(size_t index) const { return mFonts[index].style; } 143 bool isColorEmojiFamily() const; 144 const std::unordered_set<AxisTag>& supportedAxes() const { return mSupportedAxes; } 145 146 // Get Unicode coverage. 147 const SparseBitSet& getCoverage() const { return mCoverage; } 148 149 // Returns true if the font has a glyph for the code point and variation selector pair. 150 // Caller should acquire a lock before calling the method. 151 bool hasGlyph(uint32_t codepoint, uint32_t variationSelector) const; 152 153 // Returns true if this font family has a variaion sequence table (cmap format 14 subtable). 154 bool hasVSTable() const { return !mCmapFmt14Coverage.empty(); } 155 156 // Creates new FontFamily based on this family while applying font variations. Returns nullptr 157 // if none of variations apply to this family. 158 std::shared_ptr<FontFamily> createFamilyWithVariation( 159 const std::vector<FontVariation>& variations) const; 160 161private: 162 void computeCoverage(); 163 164 uint32_t mLangId; 165 int mVariant; 166 std::vector<Font> mFonts; 167 std::unordered_set<AxisTag> mSupportedAxes; 168 169 SparseBitSet mCoverage; 170 std::vector<std::unique_ptr<SparseBitSet>> mCmapFmt14Coverage; 171 172 // Forbid copying and assignment. 173 FontFamily(const FontFamily&) = delete; 174 void operator=(const FontFamily&) = delete; 175}; 176 177} // namespace minikin 178 179#endif // MINIKIN_FONT_FAMILY_H 180