1 /*
2  * Copyright 2006 The Android Open Source Project
3  *
4  * Use of this source code is governed by a BSD-style license that can be
5  * found in the LICENSE file.
6  */
7 
8 #ifndef SkGlyph_DEFINED
9 #define SkGlyph_DEFINED
10 
11 #include "SkChecksum.h"
12 #include "SkTypes.h"
13 #include "SkFixed.h"
14 #include "SkMask.h"
15 
16 class SkPath;
17 class SkGlyphCache;
18 
19 // needs to be != to any valid SkMask::Format
20 #define MASK_FORMAT_UNKNOWN         (0xFF)
21 #define MASK_FORMAT_JUST_ADVANCE    MASK_FORMAT_UNKNOWN
22 
23 #define kMaxGlyphWidth (1<<13)
24 
25 SK_BEGIN_REQUIRE_DENSE
26 class SkGlyph {
27     enum {
28         kSubBits = 2,
29         kSubMask = ((1 << kSubBits) - 1),
30         kSubShift = 24, // must be large enough for glyphs and unichars
31         kCodeMask = ((1 << kSubShift) - 1),
32         // relative offsets for X and Y subpixel bits
33         kSubShiftX = kSubBits,
34         kSubShiftY = 0
35     };
36 
37     // Support horizontal and vertical skipping strike-through / underlines.
38     // The caller walks the linked list looking for a match. For a horizontal underline,
39     // the fBounds contains the top and bottom of the underline. The fInterval pair contains the
40     // beginning and end of of the intersection of the bounds and the glyph's path.
41     // If interval[0] >= interval[1], no intesection was found.
42     struct Intercept {
43         Intercept* fNext;
44         SkScalar   fBounds[2];    // for horz underlines, the boundaries in Y
45         SkScalar   fInterval[2];  // the outside intersections of the axis and the glyph
46     };
47 
48     struct PathData {
49         Intercept* fIntercept;
50         SkPath*    fPath;
51     };
52 
53 public:
54     static const SkFixed kSubpixelRound = SK_FixedHalf >> SkGlyph::kSubBits;
55     // A value that can never be generated by MakeID.
56     static const uint32_t kImpossibleID = ~0;
57     void*       fImage;
58     PathData*   fPathData;
59     SkFixed     fAdvanceX, fAdvanceY;
60 
61     uint16_t    fWidth, fHeight;
62     int16_t     fTop, fLeft;
63 
64     uint8_t     fMaskFormat;
65     int8_t      fRsbDelta, fLsbDelta;  // used by auto-kerning
66     int8_t      fForceBW;
67 
initWithGlyphID(uint32_t glyph_id)68     void initWithGlyphID(uint32_t glyph_id) {
69         this->initCommon(MakeID(glyph_id));
70     }
71 
initGlyphIdFrom(const SkGlyph & glyph)72     void initGlyphIdFrom(const SkGlyph& glyph) {
73         this->initCommon(glyph.fID);
74     }
75 
initGlyphFromCombinedID(uint32_t combined_id)76     void initGlyphFromCombinedID(uint32_t combined_id) {
77       this->initCommon(combined_id);
78     }
79 
80     /**
81      *  Compute the rowbytes for the specified width and mask-format.
82      */
ComputeRowBytes(unsigned width,SkMask::Format format)83     static unsigned ComputeRowBytes(unsigned width, SkMask::Format format) {
84         unsigned rb = width;
85         if (SkMask::kBW_Format == format) {
86             rb = (rb + 7) >> 3;
87         } else if (SkMask::kARGB32_Format == format) {
88             rb <<= 2;
89         } else if (SkMask::kLCD16_Format == format) {
90             rb = SkAlign4(rb << 1);
91         } else {
92             rb = SkAlign4(rb);
93         }
94         return rb;
95     }
96 
rowBytes()97     unsigned rowBytes() const {
98         return ComputeRowBytes(fWidth, (SkMask::Format)fMaskFormat);
99     }
100 
isJustAdvance()101     bool isJustAdvance() const {
102         return MASK_FORMAT_JUST_ADVANCE == fMaskFormat;
103     }
104 
isFullMetrics()105     bool isFullMetrics() const {
106         return MASK_FORMAT_JUST_ADVANCE != fMaskFormat;
107     }
108 
getGlyphID()109     uint16_t getGlyphID() const {
110         return ID2Code(fID);
111     }
112 
getSubX()113     unsigned getSubX() const {
114         return ID2SubX(fID);
115     }
116 
getSubXFixed()117     SkFixed getSubXFixed() const {
118         return SubToFixed(ID2SubX(fID));
119     }
120 
getSubYFixed()121     SkFixed getSubYFixed() const {
122         return SubToFixed(ID2SubY(fID));
123     }
124 
125     size_t computeImageSize() const;
126 
127     /** Call this to set all of the metrics fields to 0 (e.g. if the scaler
128         encounters an error measuring a glyph). Note: this does not alter the
129         fImage, fPath, fID, fMaskFormat fields.
130      */
131     void zeroMetrics();
132 
133     void toMask(SkMask* mask) const;
134 
135     class HashTraits {
136     public:
GetKey(const SkGlyph & glyph)137         static uint32_t GetKey(const SkGlyph& glyph) {
138             return glyph.fID;
139         }
Hash(uint32_t glyphId)140         static uint32_t Hash(uint32_t glyphId) {
141             return SkChecksum::CheapMix(glyphId);
142         }
143     };
144 
145  private:
146     // TODO(herb) remove friend statement after SkGlyphCache cleanup.
147     friend class SkGlyphCache;
148 
initCommon(uint32_t id)149     void initCommon(uint32_t id) {
150         fID             = id;
151         fImage          = nullptr;
152         fPathData       = nullptr;
153         fMaskFormat     = MASK_FORMAT_UNKNOWN;
154         fForceBW        = 0;
155     }
156 
ID2Code(uint32_t id)157     static unsigned ID2Code(uint32_t id) {
158         return id & kCodeMask;
159     }
160 
ID2SubX(uint32_t id)161     static unsigned ID2SubX(uint32_t id) {
162         return id >> (kSubShift + kSubShiftX);
163     }
164 
ID2SubY(uint32_t id)165     static unsigned ID2SubY(uint32_t id) {
166         return (id >> (kSubShift + kSubShiftY)) & kSubMask;
167     }
168 
FixedToSub(SkFixed n)169     static unsigned FixedToSub(SkFixed n) {
170         return (n >> (16 - kSubBits)) & kSubMask;
171     }
172 
SubToFixed(unsigned sub)173     static SkFixed SubToFixed(unsigned sub) {
174         SkASSERT(sub <= kSubMask);
175         return sub << (16 - kSubBits);
176     }
177 
MakeID(unsigned code)178     static uint32_t MakeID(unsigned code) {
179         SkASSERT(code <= kCodeMask);
180         SkASSERT(code != kImpossibleID);
181         return code;
182     }
183 
MakeID(unsigned code,SkFixed x,SkFixed y)184     static uint32_t MakeID(unsigned code, SkFixed x, SkFixed y) {
185         SkASSERT(code <= kCodeMask);
186         x = FixedToSub(x);
187         y = FixedToSub(y);
188         uint32_t ID = (x << (kSubShift + kSubShiftX)) |
189                       (y << (kSubShift + kSubShiftY)) |
190                       code;
191         SkASSERT(ID != kImpossibleID);
192         return ID;
193     }
194 
195     // FIXME - This is needed because the Android frame work directly
196   // accesses fID. Remove when fID accesses are cleaned up.
197 #ifdef SK_BUILD_FOR_ANDROID_FRAMEWORK
198   public:
199 #endif
200     uint32_t    fID;
201 };
202 SK_END_REQUIRE_DENSE
203 
204 #endif
205