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 "SkTypes.h"
12 #include "SkFixed.h"
13 #include "SkMask.h"
14 
15 class SkPath;
16 class SkGlyphCache;
17 
18 // needs to be != to any valid SkMask::Format
19 #define MASK_FORMAT_UNKNOWN         (0xFF)
20 #define MASK_FORMAT_JUST_ADVANCE    MASK_FORMAT_UNKNOWN
21 
22 #define kMaxGlyphWidth (1<<13)
23 
24 class SkGlyph {
25     enum {
26         kSubBits = 2,
27         kSubMask = ((1 << kSubBits) - 1),
28         kSubShift = 24, // must be large enough for glyphs and unichars
29         kCodeMask = ((1 << kSubShift) - 1),
30         // relative offsets for X and Y subpixel bits
31         kSubShiftX = kSubBits,
32         kSubShiftY = 0
33     };
34 
35  public:
36     static const SkFixed kSubpixelRound = SK_FixedHalf >> SkGlyph::kSubBits;
37     // A value that can never be generated by MakeID.
38     static const uint32_t kImpossibleID = ~0;
39     void*       fImage;
40     SkPath*     fPath;
41     SkFixed     fAdvanceX, fAdvanceY;
42 
43     uint16_t    fWidth, fHeight;
44     int16_t     fTop, fLeft;
45 
46     uint8_t     fMaskFormat;
47     int8_t      fRsbDelta, fLsbDelta;  // used by auto-kerning
48     int8_t      fForceBW;
49 
initWithGlyphID(uint32_t glyph_id)50     void initWithGlyphID(uint32_t glyph_id) {
51         this->initCommon(MakeID(glyph_id));
52     }
53 
initGlyphIdFrom(const SkGlyph & glyph)54     void initGlyphIdFrom(const SkGlyph& glyph) {
55         this->initCommon(glyph.fID);
56     }
57 
initGlyphFromCombinedID(uint32_t combined_id)58     void initGlyphFromCombinedID(uint32_t combined_id) {
59       this->initCommon(combined_id);
60     }
61 
62     /**
63      *  Compute the rowbytes for the specified width and mask-format.
64      */
ComputeRowBytes(unsigned width,SkMask::Format format)65     static unsigned ComputeRowBytes(unsigned width, SkMask::Format format) {
66         unsigned rb = width;
67         if (SkMask::kBW_Format == format) {
68             rb = (rb + 7) >> 3;
69         } else if (SkMask::kARGB32_Format == format) {
70             rb <<= 2;
71         } else if (SkMask::kLCD16_Format == format) {
72             rb = SkAlign4(rb << 1);
73         } else {
74             rb = SkAlign4(rb);
75         }
76         return rb;
77     }
78 
rowBytes()79     unsigned rowBytes() const {
80         return ComputeRowBytes(fWidth, (SkMask::Format)fMaskFormat);
81     }
82 
isJustAdvance()83     bool isJustAdvance() const {
84         return MASK_FORMAT_JUST_ADVANCE == fMaskFormat;
85     }
86 
isFullMetrics()87     bool isFullMetrics() const {
88         return MASK_FORMAT_JUST_ADVANCE != fMaskFormat;
89     }
90 
getGlyphID()91     uint16_t getGlyphID() const {
92         return ID2Code(fID);
93     }
94 
getSubX()95     unsigned getSubX() const {
96         return ID2SubX(fID);
97     }
98 
getSubXFixed()99     SkFixed getSubXFixed() const {
100         return SubToFixed(ID2SubX(fID));
101     }
102 
getSubYFixed()103     SkFixed getSubYFixed() const {
104         return SubToFixed(ID2SubY(fID));
105     }
106 
107     size_t computeImageSize() const;
108 
109     /** Call this to set all of the metrics fields to 0 (e.g. if the scaler
110         encounters an error measuring a glyph). Note: this does not alter the
111         fImage, fPath, fID, fMaskFormat fields.
112      */
113     void zeroMetrics();
114 
115     void toMask(SkMask* mask) const;
116 
117  private:
118     // TODO(herb) remove friend statement after SkGlyphCache cleanup.
119     friend class SkGlyphCache;
120 
initCommon(uint32_t id)121     void initCommon(uint32_t id) {
122         fID             = id;
123         fImage          = NULL;
124         fPath           = NULL;
125         fMaskFormat     = MASK_FORMAT_UNKNOWN;
126         fForceBW        = 0;
127     }
128 
ID2Code(uint32_t id)129     static unsigned ID2Code(uint32_t id) {
130         return id & kCodeMask;
131     }
132 
ID2SubX(uint32_t id)133     static unsigned ID2SubX(uint32_t id) {
134         return id >> (kSubShift + kSubShiftX);
135     }
136 
ID2SubY(uint32_t id)137     static unsigned ID2SubY(uint32_t id) {
138         return (id >> (kSubShift + kSubShiftY)) & kSubMask;
139     }
140 
FixedToSub(SkFixed n)141     static unsigned FixedToSub(SkFixed n) {
142         return (n >> (16 - kSubBits)) & kSubMask;
143     }
144 
SubToFixed(unsigned sub)145     static SkFixed SubToFixed(unsigned sub) {
146         SkASSERT(sub <= kSubMask);
147         return sub << (16 - kSubBits);
148     }
149 
MakeID(unsigned code)150     static uint32_t MakeID(unsigned code) {
151         SkASSERT(code <= kCodeMask);
152         SkASSERT(code != kImpossibleID);
153         return code;
154     }
155 
MakeID(unsigned code,SkFixed x,SkFixed y)156     static uint32_t MakeID(unsigned code, SkFixed x, SkFixed y) {
157         SkASSERT(code <= kCodeMask);
158         x = FixedToSub(x);
159         y = FixedToSub(y);
160         uint32_t ID = (x << (kSubShift + kSubShiftX)) |
161                       (y << (kSubShift + kSubShiftY)) |
162                       code;
163         SkASSERT(ID != kImpossibleID);
164         return ID;
165     }
166 
167   // FIXME - This is needed because the Android frame work directly
168   // accesses fID. Remove when fID accesses are cleaned up.
169 #ifdef SK_BUILD_FOR_ANDROID_FRAMEWORK
170   public:
171 #endif
172     uint32_t    fID;
173 };
174 
175 #endif
176