Home | History | Annotate | Download | only in minikin
      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 
     31 namespace minikin {
     32 
     33 class 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.
     38 class FontStyle {
     39 public:
     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);
     62 private:
     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 
     74 enum FontVariant {
     75     VARIANT_DEFAULT = 0,
     76     VARIANT_COMPACT = 1,
     77     VARIANT_ELEGANT = 2,
     78 };
     79 
     80 inline 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
     85 class FontFakery {
     86 public:
     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; }
     92 private:
     93     bool mFakeBold;
     94     bool mFakeItalic;
     95 };
     96 
     97 struct FakedFont {
     98     // ownership is the enclosing FontCollection
     99     MinikinFont* font;
    100     FontFakery fakery;
    101 };
    102 
    103 typedef uint32_t AxisTag;
    104 
    105 struct 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 
    117 struct FontVariation {
    118     FontVariation(AxisTag axisTag, float value) : axisTag(axisTag), value(value) {}
    119     AxisTag axisTag;
    120     float value;
    121 };
    122 
    123 class FontFamily {
    124 public:
    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 
    161 private:
    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