FontFamily.h revision 0f2a025d135f9ca52cc3cf917fffc29d6c126094
19cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien/* 29cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien * Copyright (C) 2013 The Android Open Source Project 39cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien * 49cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien * Licensed under the Apache License, Version 2.0 (the "License"); 59cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien * you may not use this file except in compliance with the License. 69cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien * You may obtain a copy of the License at 79cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien * 89cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien * http://www.apache.org/licenses/LICENSE-2.0 99cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien * 109cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien * Unless required by applicable law or agreed to in writing, software 119cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien * distributed under the License is distributed on an "AS IS" BASIS, 129cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 139cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien * See the License for the specific language governing permissions and 149cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien * limitations under the License. 159cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien */ 169cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien 179cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien#ifndef MINIKIN_FONT_FAMILY_H 189cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien#define MINIKIN_FONT_FAMILY_H 199cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien 209cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien#include <vector> 21a5bb91190edbea0be0e78a8511b3c920b6e99c4eBehdad Esfahbod#include <string> 220f2a025d135f9ca52cc3cf917fffc29d6c126094Seigo Nonaka#include <hb.h> 239cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien 244d4e6bc8118d15542f1f2a9218f0f7a91a29474fRaph Levien#include <utils/TypeHelpers.h> 254d4e6bc8118d15542f1f2a9218f0f7a91a29474fRaph Levien 26b80c1f19c58b927820a8a24bf2218e5645724608Raph Levien#include <minikin/MinikinRefCounted.h> 2713f1aae02bacd475722bc8ea3fc2cf6abc1a82e3Raph Levien#include <minikin/SparseBitSet.h> 28b80c1f19c58b927820a8a24bf2218e5645724608Raph Levien 299cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Leviennamespace android { 309cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien 317b221d97b7b64dc5ce457e19666d55d042e22e62Raph Levienclass MinikinFont; 327b221d97b7b64dc5ce457e19666d55d042e22e62Raph Levien 337b221d97b7b64dc5ce457e19666d55d042e22e62Raph Levien// FontLanguage is a compact representation of a bcp-47 language tag. It 347b221d97b7b64dc5ce457e19666d55d042e22e62Raph Levien// does not capture all possible information, only what directly affects 357b221d97b7b64dc5ce457e19666d55d042e22e62Raph Levien// font rendering. 367b221d97b7b64dc5ce457e19666d55d042e22e62Raph Levienclass FontLanguage { 377b221d97b7b64dc5ce457e19666d55d042e22e62Raph Levien friend class FontStyle; 387b221d97b7b64dc5ce457e19666d55d042e22e62Raph Levienpublic: 397b221d97b7b64dc5ce457e19666d55d042e22e62Raph Levien FontLanguage() : mBits(0) { } 407b221d97b7b64dc5ce457e19666d55d042e22e62Raph Levien 417b221d97b7b64dc5ce457e19666d55d042e22e62Raph Levien // Parse from string 427b221d97b7b64dc5ce457e19666d55d042e22e62Raph Levien FontLanguage(const char* buf, size_t size); 437b221d97b7b64dc5ce457e19666d55d042e22e62Raph Levien 4471ec97055357b6ccb13a2697a56254bb19f43ae9Roozbeh Pournader bool operator==(const FontLanguage other) const { 4571ec97055357b6ccb13a2697a56254bb19f43ae9Roozbeh Pournader return mBits != kUnsupportedLanguage && mBits == other.mBits; 4671ec97055357b6ccb13a2697a56254bb19f43ae9Roozbeh Pournader } 47a5bb91190edbea0be0e78a8511b3c920b6e99c4eBehdad Esfahbod operator bool() const { return mBits != 0; } 48a5bb91190edbea0be0e78a8511b3c920b6e99c4eBehdad Esfahbod 49a5bb91190edbea0be0e78a8511b3c920b6e99c4eBehdad Esfahbod std::string getString() const; 507b221d97b7b64dc5ce457e19666d55d042e22e62Raph Levien 517b221d97b7b64dc5ce457e19666d55d042e22e62Raph Levien // 0 = no match, 1 = language matches, 2 = language and script match 527b221d97b7b64dc5ce457e19666d55d042e22e62Raph Levien int match(const FontLanguage other) const; 537b221d97b7b64dc5ce457e19666d55d042e22e62Raph Levien 547b221d97b7b64dc5ce457e19666d55d042e22e62Raph Levienprivate: 557b221d97b7b64dc5ce457e19666d55d042e22e62Raph Levien explicit FontLanguage(uint32_t bits) : mBits(bits) { } 567b221d97b7b64dc5ce457e19666d55d042e22e62Raph Levien 577b221d97b7b64dc5ce457e19666d55d042e22e62Raph Levien uint32_t bits() const { return mBits; } 587b221d97b7b64dc5ce457e19666d55d042e22e62Raph Levien 5971ec97055357b6ccb13a2697a56254bb19f43ae9Roozbeh Pournader static const uint32_t kUnsupportedLanguage = 0xFFFFFFFFu; 6071ec97055357b6ccb13a2697a56254bb19f43ae9Roozbeh Pournader static const uint32_t kBaseLangMask = 0xFFFFFFu; 6171ec97055357b6ccb13a2697a56254bb19f43ae9Roozbeh Pournader static const uint32_t kScriptMask = (1u << 26) - (1u << 24); 6271ec97055357b6ccb13a2697a56254bb19f43ae9Roozbeh Pournader static const uint32_t kHansFlag = 1u << 24; 6371ec97055357b6ccb13a2697a56254bb19f43ae9Roozbeh Pournader static const uint32_t kHantFlag = 1u << 25; 647b221d97b7b64dc5ce457e19666d55d042e22e62Raph Levien uint32_t mBits; 657b221d97b7b64dc5ce457e19666d55d042e22e62Raph Levien}; 667b221d97b7b64dc5ce457e19666d55d042e22e62Raph Levien 679cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien// FontStyle represents all style information needed to select an actual font 689cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien// from a collection. The implementation is packed into a single 32-bit word 699cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien// so it can be efficiently copied, embedded in other objects, etc. 709cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levienclass FontStyle { 719cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levienpublic: 729cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien FontStyle(int weight = 4, bool italic = false) { 739cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien bits = (weight & kWeightMask) | (italic ? kItalicMask : 0); 749cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien } 757b221d97b7b64dc5ce457e19666d55d042e22e62Raph Levien FontStyle(FontLanguage lang, int variant = 0, int weight = 4, bool italic = false) { 767b221d97b7b64dc5ce457e19666d55d042e22e62Raph Levien bits = (weight & kWeightMask) | (italic ? kItalicMask : 0) 777b221d97b7b64dc5ce457e19666d55d042e22e62Raph Levien | (variant << kVariantShift) | (lang.bits() << kLangShift); 787b221d97b7b64dc5ce457e19666d55d042e22e62Raph Levien } 794d4e6bc8118d15542f1f2a9218f0f7a91a29474fRaph Levien int getWeight() const { return bits & kWeightMask; } 804d4e6bc8118d15542f1f2a9218f0f7a91a29474fRaph Levien bool getItalic() const { return (bits & kItalicMask) != 0; } 817b221d97b7b64dc5ce457e19666d55d042e22e62Raph Levien int getVariant() const { return (bits >> kVariantShift) & kVariantMask; } 827b221d97b7b64dc5ce457e19666d55d042e22e62Raph Levien FontLanguage getLanguage() const { return FontLanguage(bits >> kLangShift); } 837b221d97b7b64dc5ce457e19666d55d042e22e62Raph Levien 844d4e6bc8118d15542f1f2a9218f0f7a91a29474fRaph Levien bool operator==(const FontStyle other) const { return bits == other.bits; } 854d4e6bc8118d15542f1f2a9218f0f7a91a29474fRaph Levien 864d4e6bc8118d15542f1f2a9218f0f7a91a29474fRaph Levien hash_t hash() const { return bits; } 879cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levienprivate: 887b221d97b7b64dc5ce457e19666d55d042e22e62Raph Levien static const uint32_t kWeightMask = (1 << 4) - 1; 897b221d97b7b64dc5ce457e19666d55d042e22e62Raph Levien static const uint32_t kItalicMask = 1 << 4; 907b221d97b7b64dc5ce457e19666d55d042e22e62Raph Levien static const int kVariantShift = 5; 917b221d97b7b64dc5ce457e19666d55d042e22e62Raph Levien static const uint32_t kVariantMask = (1 << 2) - 1; 927b221d97b7b64dc5ce457e19666d55d042e22e62Raph Levien static const int kLangShift = 7; 939cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien uint32_t bits; 949cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien}; 959cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien 967b221d97b7b64dc5ce457e19666d55d042e22e62Raph Levienenum FontVariant { 977b221d97b7b64dc5ce457e19666d55d042e22e62Raph Levien VARIANT_DEFAULT = 0, 987b221d97b7b64dc5ce457e19666d55d042e22e62Raph Levien VARIANT_COMPACT = 1, 997b221d97b7b64dc5ce457e19666d55d042e22e62Raph Levien VARIANT_ELEGANT = 2, 1007b221d97b7b64dc5ce457e19666d55d042e22e62Raph Levien}; 1017b221d97b7b64dc5ce457e19666d55d042e22e62Raph Levien 1024d4e6bc8118d15542f1f2a9218f0f7a91a29474fRaph Levieninline hash_t hash_type(const FontStyle &style) { 1034d4e6bc8118d15542f1f2a9218f0f7a91a29474fRaph Levien return style.hash(); 1044d4e6bc8118d15542f1f2a9218f0f7a91a29474fRaph Levien} 1054d4e6bc8118d15542f1f2a9218f0f7a91a29474fRaph Levien 1069a5f713add8cfb91ac2c9ed5c917309053201ab6Raph Levien// attributes representing transforms (fake bold, fake italic) to match styles 1079a5f713add8cfb91ac2c9ed5c917309053201ab6Raph Levienclass FontFakery { 1089a5f713add8cfb91ac2c9ed5c917309053201ab6Raph Levienpublic: 1099a5f713add8cfb91ac2c9ed5c917309053201ab6Raph Levien FontFakery() : mFakeBold(false), mFakeItalic(false) { } 1109a5f713add8cfb91ac2c9ed5c917309053201ab6Raph Levien FontFakery(bool fakeBold, bool fakeItalic) : mFakeBold(fakeBold), mFakeItalic(fakeItalic) { } 1119a5f713add8cfb91ac2c9ed5c917309053201ab6Raph Levien // TODO: want to support graded fake bolding 1129a5f713add8cfb91ac2c9ed5c917309053201ab6Raph Levien bool isFakeBold() { return mFakeBold; } 1139a5f713add8cfb91ac2c9ed5c917309053201ab6Raph Levien bool isFakeItalic() { return mFakeItalic; } 1149a5f713add8cfb91ac2c9ed5c917309053201ab6Raph Levienprivate: 1159a5f713add8cfb91ac2c9ed5c917309053201ab6Raph Levien bool mFakeBold; 1169a5f713add8cfb91ac2c9ed5c917309053201ab6Raph Levien bool mFakeItalic; 1179a5f713add8cfb91ac2c9ed5c917309053201ab6Raph Levien}; 1189a5f713add8cfb91ac2c9ed5c917309053201ab6Raph Levien 1199a5f713add8cfb91ac2c9ed5c917309053201ab6Raph Levienstruct FakedFont { 1209a5f713add8cfb91ac2c9ed5c917309053201ab6Raph Levien // ownership is the enclosing FontCollection 1219a5f713add8cfb91ac2c9ed5c917309053201ab6Raph Levien MinikinFont* font; 1229a5f713add8cfb91ac2c9ed5c917309053201ab6Raph Levien FontFakery fakery; 1239a5f713add8cfb91ac2c9ed5c917309053201ab6Raph Levien}; 1249a5f713add8cfb91ac2c9ed5c917309053201ab6Raph Levien 125b80c1f19c58b927820a8a24bf2218e5645724608Raph Levienclass FontFamily : public MinikinRefCounted { 1269cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levienpublic: 1270f2a025d135f9ca52cc3cf917fffc29d6c126094Seigo Nonaka FontFamily() : mHbFont(nullptr) { } 1287b221d97b7b64dc5ce457e19666d55d042e22e62Raph Levien 1290f2a025d135f9ca52cc3cf917fffc29d6c126094Seigo Nonaka FontFamily(FontLanguage lang, int variant) : mLang(lang), mVariant(variant), mHbFont(nullptr) { 1307b221d97b7b64dc5ce457e19666d55d042e22e62Raph Levien } 1317b221d97b7b64dc5ce457e19666d55d042e22e62Raph Levien 132b80c1f19c58b927820a8a24bf2218e5645724608Raph Levien ~FontFamily(); 133b80c1f19c58b927820a8a24bf2218e5645724608Raph Levien 1349cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien // Add font to family, extracting style information from the font 135bcc3dc5a2591a95a57e379e27cbad69c18e91e67Raph Levien bool addFont(MinikinFont* typeface); 1369cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien 137bcc3dc5a2591a95a57e379e27cbad69c18e91e67Raph Levien void addFont(MinikinFont* typeface, FontStyle style); 1389a5f713add8cfb91ac2c9ed5c917309053201ab6Raph Levien FakedFont getClosestMatch(FontStyle style) const; 1399cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien 1407b221d97b7b64dc5ce457e19666d55d042e22e62Raph Levien FontLanguage lang() const { return mLang; } 1417b221d97b7b64dc5ce457e19666d55d042e22e62Raph Levien int variant() const { return mVariant; } 1427b221d97b7b64dc5ce457e19666d55d042e22e62Raph Levien 1439cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien // API's for enumerating the fonts in a family. These don't guarantee any particular order 1449cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien size_t getNumFonts() const; 145bcc3dc5a2591a95a57e379e27cbad69c18e91e67Raph Levien MinikinFont* getFont(size_t index) const; 1469cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien FontStyle getStyle(size_t index) const; 14713f1aae02bacd475722bc8ea3fc2cf6abc1a82e3Raph Levien 148cb20a2f0b366bfc16db3a489a60156dec7a9fe21Andreas Gampe // Get Unicode coverage. Lifetime of returned bitset is same as receiver. May return nullptr on 149cb20a2f0b366bfc16db3a489a60156dec7a9fe21Andreas Gampe // error. 15013f1aae02bacd475722bc8ea3fc2cf6abc1a82e3Raph Levien const SparseBitSet* getCoverage(); 1510f2a025d135f9ca52cc3cf917fffc29d6c126094Seigo Nonaka 1520f2a025d135f9ca52cc3cf917fffc29d6c126094Seigo Nonaka // Returns true if the font has a glyph for the code point and variation selector pair. 1530f2a025d135f9ca52cc3cf917fffc29d6c126094Seigo Nonaka // Caller should acquire a lock before calling the method. 1540f2a025d135f9ca52cc3cf917fffc29d6c126094Seigo Nonaka bool hasVariationSelector(uint32_t codepoint, uint32_t variationSelector); 1550f2a025d135f9ca52cc3cf917fffc29d6c126094Seigo Nonaka 1560f2a025d135f9ca52cc3cf917fffc29d6c126094Seigo Nonaka // Purges cached mHbFont. 1570f2a025d135f9ca52cc3cf917fffc29d6c126094Seigo Nonaka // hb_font_t keeps a reference to hb_face_t which is managed by HbFaceCache. Thus, 1580f2a025d135f9ca52cc3cf917fffc29d6c126094Seigo Nonaka // it is good to purge hb_font_t once it is no longer necessary. 1590f2a025d135f9ca52cc3cf917fffc29d6c126094Seigo Nonaka // Caller should acquire a lock before calling the method. 1600f2a025d135f9ca52cc3cf917fffc29d6c126094Seigo Nonaka void purgeHbFontCache(); 1619cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levienprivate: 162c31e3883456e018d742e9f29815ba5ff8b315ea1Raph Levien void addFontLocked(MinikinFont* typeface, FontStyle style); 163c31e3883456e018d742e9f29815ba5ff8b315ea1Raph Levien 1649cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien class Font { 1659cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien public: 166bcc3dc5a2591a95a57e379e27cbad69c18e91e67Raph Levien Font(MinikinFont* typeface, FontStyle style) : 1679cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien typeface(typeface), style(style) { } 168bcc3dc5a2591a95a57e379e27cbad69c18e91e67Raph Levien MinikinFont* typeface; 1699cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien FontStyle style; 1709cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien }; 1717b221d97b7b64dc5ce457e19666d55d042e22e62Raph Levien FontLanguage mLang; 1727b221d97b7b64dc5ce457e19666d55d042e22e62Raph Levien int mVariant; 1739cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien std::vector<Font> mFonts; 17413f1aae02bacd475722bc8ea3fc2cf6abc1a82e3Raph Levien 17513f1aae02bacd475722bc8ea3fc2cf6abc1a82e3Raph Levien SparseBitSet mCoverage; 17613f1aae02bacd475722bc8ea3fc2cf6abc1a82e3Raph Levien bool mCoverageValid; 1770f2a025d135f9ca52cc3cf917fffc29d6c126094Seigo Nonaka 1780f2a025d135f9ca52cc3cf917fffc29d6c126094Seigo Nonaka hb_font_t* mHbFont; 1799cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien}; 1809cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien 1819cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien} // namespace android 1829cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien 1839cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien#endif // MINIKIN_FONT_FAMILY_H 184