• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2006 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 SkScalerContext_DEFINED
18 #define SkScalerContext_DEFINED
19 
20 #include "SkMask.h"
21 #include "SkMatrix.h"
22 #include "SkPaint.h"
23 #include "SkPath.h"
24 #include "SkPoint.h"
25 
26 class SkDescriptor;
27 class SkMaskFilter;
28 class SkPathEffect;
29 class SkRasterizer;
30 
31 // needs to be != to any valid SkMask::Format
32 #define MASK_FORMAT_UNKNOWN         (0xFF)
33 #define MASK_FORMAT_JUST_ADVANCE    MASK_FORMAT_UNKNOWN
34 
35 #define kMaxGlyphWidth (1<<13)
36 
37 struct SkGlyph {
38     void*       fImage;
39     SkPath*     fPath;
40     SkFixed     fAdvanceX, fAdvanceY;
41 
42     uint32_t    fID;
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 
initSkGlyph49     void init(uint32_t id) {
50         fID             = id;
51         fImage          = NULL;
52         fPath           = NULL;
53         fMaskFormat     = MASK_FORMAT_UNKNOWN;
54     }
55 
56     /**
57      *  Compute the rowbytes for the specified width and mask-format.
58      */
ComputeRowBytesSkGlyph59     static unsigned ComputeRowBytes(unsigned width, SkMask::Format format) {
60         unsigned rb = width;
61         if (SkMask::kBW_Format == format) {
62             rb = (rb + 7) >> 3;
63 		} else if (SkMask::kARGB32_Format == format) {
64 			rb <<= 2;
65 		} else if (SkMask::kLCD16_Format == format) {
66 			rb = SkAlign4(rb << 1);
67         } else {
68             rb = SkAlign4(rb);
69         }
70         return rb;
71     }
72 
rowBytesSkGlyph73     unsigned rowBytes() const {
74         return ComputeRowBytes(fWidth, (SkMask::Format)fMaskFormat);
75     }
76 
isJustAdvanceSkGlyph77     bool isJustAdvance() const {
78         return MASK_FORMAT_JUST_ADVANCE == fMaskFormat;
79     }
80 
isFullMetricsSkGlyph81     bool isFullMetrics() const {
82         return MASK_FORMAT_JUST_ADVANCE != fMaskFormat;
83     }
84 
getGlyphIDSkGlyph85     uint16_t getGlyphID() const {
86         return ID2Code(fID);
87     }
88 
getGlyphIDSkGlyph89     unsigned getGlyphID(unsigned baseGlyphCount) const {
90         unsigned code = ID2Code(fID);
91         SkASSERT(code >= baseGlyphCount);
92         return code - baseGlyphCount;
93     }
94 
getSubXSkGlyph95     unsigned getSubX() const {
96         return ID2SubX(fID);
97     }
98 
getSubXFixedSkGlyph99     SkFixed getSubXFixed() const {
100         return SubToFixed(ID2SubX(fID));
101     }
102 
getSubYFixedSkGlyph103     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     enum {
116         kSubBits = 2,
117         kSubMask = ((1 << kSubBits) - 1),
118         kSubShift = 24, // must be large enough for glyphs and unichars
119         kCodeMask = ((1 << kSubShift) - 1),
120         // relative offsets for X and Y subpixel bits
121         kSubShiftX = kSubBits,
122         kSubShiftY = 0
123     };
124 
ID2CodeSkGlyph125     static unsigned ID2Code(uint32_t id) {
126         return id & kCodeMask;
127     }
128 
ID2SubXSkGlyph129     static unsigned ID2SubX(uint32_t id) {
130         return id >> (kSubShift + kSubShiftX);
131     }
132 
ID2SubYSkGlyph133     static unsigned ID2SubY(uint32_t id) {
134         return (id >> (kSubShift + kSubShiftY)) & kSubMask;
135     }
136 
FixedToSubSkGlyph137     static unsigned FixedToSub(SkFixed n) {
138         return (n >> (16 - kSubBits)) & kSubMask;
139     }
140 
SubToFixedSkGlyph141     static SkFixed SubToFixed(unsigned sub) {
142         SkASSERT(sub <= kSubMask);
143         return sub << (16 - kSubBits);
144     }
145 
MakeIDSkGlyph146     static uint32_t MakeID(unsigned code) {
147         return code;
148     }
149 
MakeIDSkGlyph150     static uint32_t MakeID(unsigned code, SkFixed x, SkFixed y) {
151         SkASSERT(code <= kCodeMask);
152         x = FixedToSub(x);
153         y = FixedToSub(y);
154         return (x << (kSubShift + kSubShiftX)) |
155                (y << (kSubShift + kSubShiftY)) |
156                code;
157     }
158 
159     void toMask(SkMask* mask) const;
160 
161     /** Given a glyph which is has a mask format of LCD or VerticalLCD, take
162         the A8 plane in fImage and produce a valid LCD plane from it.
163     */
164     void expandA8ToLCD() const;
165 };
166 
167 class SkScalerContext {
168 public:
169     enum Flags {
170         kFrameAndFill_Flag  = 0x01,
171         kDevKernText_Flag   = 0x02,
172         kGammaForBlack_Flag = 0x04, // illegal to set both Gamma flags
173         kGammaForWhite_Flag = 0x08, // illegal to set both Gamma flags
174         // together, these two flags resulting in a two bit value which matches
175         // up with the SkPaint::Hinting enum.
176         kHintingBit1_Flag   = 0x10,
177         kHintingBit2_Flag   = 0x20,
178         kEmbeddedBitmapText_Flag = 0x40,
179         kEmbolden_Flag      = 0x80,
180         kSubpixelPositioning_Flag = 0x100,
181         kAutohinting_Flag   = 0x200,
182         // these should only ever be set if fMaskFormat is LCD
183         kLCD_Vertical_Flag  = 0x400,    // else Horizontal
184         kLCD_BGROrder_Flag  = 0x800,    // else RGB order
185     };
186 private:
187     enum {
188         kHintingMask = kHintingBit1_Flag | kHintingBit2_Flag
189     };
190 public:
191     struct Rec {
192         uint32_t    fOrigFontID;
193         uint32_t    fFontID;
194         SkScalar    fTextSize, fPreScaleX, fPreSkewX;
195         SkScalar    fPost2x2[2][2];
196         SkScalar    fFrameWidth, fMiterLimit;
197         uint8_t     fMaskFormat;
198         uint8_t     fStrokeJoin;
199         uint16_t    fFlags;
200         // Warning: when adding members note that the size of this structure
201         // must be a multiple of 4. SkDescriptor requires that its arguments be
202         // multiples of four and this structure is put in an SkDescriptor in
203         // SkPaint::MakeRec.
204 
205         void    getMatrixFrom2x2(SkMatrix*) const;
206         void    getLocalMatrix(SkMatrix*) const;
207         void    getSingleMatrix(SkMatrix*) const;
208 
getHintingRec209         SkPaint::Hinting getHinting() const {
210             return static_cast<SkPaint::Hinting>((fFlags & kHintingMask) >> 4);
211         }
212 
setHintingRec213         void setHinting(SkPaint::Hinting hinting) {
214             fFlags = (fFlags & ~kHintingMask) | (hinting << 4);
215         }
216 
getFormatRec217         SkMask::Format getFormat() const {
218             return static_cast<SkMask::Format>(fMaskFormat);
219         }
220 
isLCDRec221         bool isLCD() const {
222             return SkMask::FormatIsLCD(this->getFormat());
223         }
224     };
225 
226     SkScalerContext(const SkDescriptor* desc);
227     virtual ~SkScalerContext();
228 
getMaskFormat()229     SkMask::Format getMaskFormat() const {
230         return (SkMask::Format)fRec.fMaskFormat;
231     }
232 
233     // remember our glyph offset/base
setBaseGlyphCount(unsigned baseGlyphCount)234     void setBaseGlyphCount(unsigned baseGlyphCount) {
235         fBaseGlyphCount = baseGlyphCount;
236     }
237 
238     /** Return the corresponding glyph for the specified unichar. Since contexts
239         may be chained (under the hood), the glyphID that is returned may in
240         fact correspond to a different font/context. In that case, we use the
241         base-glyph-count to know how to translate back into local glyph space.
242      */
243     uint16_t    charToGlyphID(SkUnichar uni);
244 
245     /** Map the glyphID to its glyph index, and then to its char code. Unmapped
246         glyphs return zero.
247     */
248     SkUnichar glyphIDToChar(uint16_t glyphID);
249 
getGlyphCount()250     unsigned    getGlyphCount() { return this->generateGlyphCount(); }
251     void        getAdvance(SkGlyph*);
252     void        getMetrics(SkGlyph*);
253     void        getImage(const SkGlyph&);
254     void        getPath(const SkGlyph&, SkPath*);
255     void        getFontMetrics(SkPaint::FontMetrics* mX,
256                                SkPaint::FontMetrics* mY);
257 
258     static inline void MakeRec(const SkPaint&, const SkMatrix*, Rec* rec);
259     static SkScalerContext* Create(const SkDescriptor*);
260 
261 protected:
262     Rec         fRec;
263     unsigned    fBaseGlyphCount;
264 
265     virtual unsigned generateGlyphCount() = 0;
266     virtual uint16_t generateCharToGlyph(SkUnichar) = 0;
267     virtual void generateAdvance(SkGlyph*) = 0;
268     virtual void generateMetrics(SkGlyph*) = 0;
269     virtual void generateImage(const SkGlyph&) = 0;
270     virtual void generatePath(const SkGlyph&, SkPath*) = 0;
271     virtual void generateFontMetrics(SkPaint::FontMetrics* mX,
272                                      SkPaint::FontMetrics* mY) = 0;
273     // default impl returns 0, indicating failure.
274     virtual SkUnichar generateGlyphToChar(uint16_t);
275 
276 private:
277     SkPathEffect*   fPathEffect;
278     SkMaskFilter*   fMaskFilter;
279     SkRasterizer*   fRasterizer;
280     SkScalar        fDevFrameWidth;
281 
282     void internalGetPath(const SkGlyph& glyph, SkPath* fillPath,
283                          SkPath* devPath, SkMatrix* fillToDevMatrix);
284 
285     // return the next context, treating fNextContext as a cache of the answer
286     SkScalerContext* getNextContext();
287 
288     // returns the right context from our link-list for this glyph. If no match
289     // is found, just returns the original context (this)
290     SkScalerContext* getGlyphContext(const SkGlyph& glyph);
291 
292     // link-list of context, to handle missing chars. null-terminated.
293     SkScalerContext* fNextContext;
294 };
295 
296 #define kRec_SkDescriptorTag            SkSetFourByteTag('s', 'r', 'e', 'c')
297 #define kPathEffect_SkDescriptorTag     SkSetFourByteTag('p', 't', 'h', 'e')
298 #define kMaskFilter_SkDescriptorTag     SkSetFourByteTag('m', 's', 'k', 'f')
299 #define kRasterizer_SkDescriptorTag     SkSetFourByteTag('r', 'a', 's', 't')
300 
301 #endif
302 
303