• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 
2 /*
3  * Copyright 2006 The Android Open Source Project
4  *
5  * Use of this source code is governed by a BSD-style license that can be
6  * found in the LICENSE file.
7  */
8 
9 
10 #ifndef SkScalerContext_DEFINED
11 #define SkScalerContext_DEFINED
12 
13 #include "SkMask.h"
14 #include "SkMatrix.h"
15 #include "SkPaint.h"
16 #include "SkPath.h"
17 #include "SkPoint.h"
18 #include "SkTypeface.h"
19 
20 #ifdef SK_BUILD_FOR_ANDROID
21 #include "SkLanguage.h"
22 #endif
23 
24 //#define SK_USE_COLOR_LUMINANCE
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                    SkMask::kLCD32_Format == format)
65         {
66 			rb <<= 2;
67 		} else if (SkMask::kLCD16_Format == format) {
68 			rb = SkAlign4(rb << 1);
69         } else {
70             rb = SkAlign4(rb);
71         }
72         return rb;
73     }
74 
rowBytesSkGlyph75     unsigned rowBytes() const {
76         return ComputeRowBytes(fWidth, (SkMask::Format)fMaskFormat);
77     }
78 
isJustAdvanceSkGlyph79     bool isJustAdvance() const {
80         return MASK_FORMAT_JUST_ADVANCE == fMaskFormat;
81     }
82 
isFullMetricsSkGlyph83     bool isFullMetrics() const {
84         return MASK_FORMAT_JUST_ADVANCE != fMaskFormat;
85     }
86 
getGlyphIDSkGlyph87     uint16_t getGlyphID() const {
88         return ID2Code(fID);
89     }
90 
getGlyphIDSkGlyph91     unsigned getGlyphID(unsigned baseGlyphCount) const {
92         unsigned code = ID2Code(fID);
93         SkASSERT(code >= baseGlyphCount);
94         return code - baseGlyphCount;
95     }
96 
getSubXSkGlyph97     unsigned getSubX() const {
98         return ID2SubX(fID);
99     }
100 
getSubXFixedSkGlyph101     SkFixed getSubXFixed() const {
102         return SubToFixed(ID2SubX(fID));
103     }
104 
getSubYFixedSkGlyph105     SkFixed getSubYFixed() const {
106         return SubToFixed(ID2SubY(fID));
107     }
108 
109     size_t computeImageSize() const;
110 
111     /** Call this to set all of the metrics fields to 0 (e.g. if the scaler
112         encounters an error measuring a glyph). Note: this does not alter the
113         fImage, fPath, fID, fMaskFormat fields.
114      */
115     void zeroMetrics();
116 
117     enum {
118         kSubBits = 2,
119         kSubMask = ((1 << kSubBits) - 1),
120         kSubShift = 24, // must be large enough for glyphs and unichars
121         kCodeMask = ((1 << kSubShift) - 1),
122         // relative offsets for X and Y subpixel bits
123         kSubShiftX = kSubBits,
124         kSubShiftY = 0
125     };
126 
ID2CodeSkGlyph127     static unsigned ID2Code(uint32_t id) {
128         return id & kCodeMask;
129     }
130 
ID2SubXSkGlyph131     static unsigned ID2SubX(uint32_t id) {
132         return id >> (kSubShift + kSubShiftX);
133     }
134 
ID2SubYSkGlyph135     static unsigned ID2SubY(uint32_t id) {
136         return (id >> (kSubShift + kSubShiftY)) & kSubMask;
137     }
138 
FixedToSubSkGlyph139     static unsigned FixedToSub(SkFixed n) {
140         return (n >> (16 - kSubBits)) & kSubMask;
141     }
142 
SubToFixedSkGlyph143     static SkFixed SubToFixed(unsigned sub) {
144         SkASSERT(sub <= kSubMask);
145         return sub << (16 - kSubBits);
146     }
147 
MakeIDSkGlyph148     static uint32_t MakeID(unsigned code) {
149         return code;
150     }
151 
MakeIDSkGlyph152     static uint32_t MakeID(unsigned code, SkFixed x, SkFixed y) {
153         SkASSERT(code <= kCodeMask);
154         x = FixedToSub(x);
155         y = FixedToSub(y);
156         return (x << (kSubShift + kSubShiftX)) |
157                (y << (kSubShift + kSubShiftY)) |
158                code;
159     }
160 
161     void toMask(SkMask* mask) const;
162 };
163 
164 class SkScalerContext {
165 public:
166     enum Flags {
167         kFrameAndFill_Flag        = 0x0001,
168         kDevKernText_Flag         = 0x0002,
169         kEmbeddedBitmapText_Flag  = 0x0004,
170         kEmbolden_Flag            = 0x0008,
171         kSubpixelPositioning_Flag = 0x0010,
172         kAutohinting_Flag         = 0x0020,
173         kVertical_Flag            = 0x0040,
174 
175         // together, these two flags resulting in a two bit value which matches
176         // up with the SkPaint::Hinting enum.
177         kHinting_Shift            = 7, // to shift into the other flags above
178         kHintingBit1_Flag         = 0x0080,
179         kHintingBit2_Flag         = 0x0100,
180 
181         // these should only ever be set if fMaskFormat is LCD16 or LCD32
182         kLCD_Vertical_Flag        = 0x0200,    // else Horizontal
183         kLCD_BGROrder_Flag        = 0x0400,    // else RGB order
184 
185         // Generate A8 from LCD source (for GDI), only meaningful if fMaskFormat is kA8
186         // Perhaps we can store this (instead) in fMaskFormat, in hight bit?
187         kGenA8FromLCD_Flag        = 0x0800,
188 
189 #ifdef SK_USE_COLOR_LUMINANCE
190         kLuminance_Bits           = 3,
191 #else
192         // luminance : 0 for black text, kLuminance_Max for white text
193         kLuminance_Shift          = 13, // shift to land in the high 3-bits of Flags
194         kLuminance_Bits           = 3,  // ensure Flags doesn't exceed 16bits
195 #endif
196     };
197 
198     // computed values
199     enum {
200         kHinting_Mask   = kHintingBit1_Flag | kHintingBit2_Flag,
201 #ifdef SK_USE_COLOR_LUMINANCE
202 #else
203         kLuminance_Max  = (1 << kLuminance_Bits) - 1,
204         kLuminance_Mask = kLuminance_Max << kLuminance_Shift,
205 #endif
206     };
207 
208     struct Rec {
209         uint32_t    fOrigFontID;
210         uint32_t    fFontID;
211         SkScalar    fTextSize, fPreScaleX, fPreSkewX;
212         SkScalar    fPost2x2[2][2];
213         SkScalar    fFrameWidth, fMiterLimit;
214 #ifdef SK_USE_COLOR_LUMINANCE
215         uint32_t    fLumBits;
216 #endif
217 #ifdef SK_BUILD_FOR_ANDROID
218         SkLanguage fLanguage;
219         SkPaint::FontVariant fFontVariant;
220 #endif
221         uint8_t     fMaskFormat;
222         uint8_t     fStrokeJoin;
223         uint16_t    fFlags;
224         // Warning: when adding members note that the size of this structure
225         // must be a multiple of 4. SkDescriptor requires that its arguments be
226         // multiples of four and this structure is put in an SkDescriptor in
227         // SkPaint::MakeRec.
228 
229         void    getMatrixFrom2x2(SkMatrix*) const;
230         void    getLocalMatrix(SkMatrix*) const;
231         void    getSingleMatrix(SkMatrix*) const;
232 
getHintingRec233         SkPaint::Hinting getHinting() const {
234             unsigned hint = (fFlags & kHinting_Mask) >> kHinting_Shift;
235             return static_cast<SkPaint::Hinting>(hint);
236         }
237 
setHintingRec238         void setHinting(SkPaint::Hinting hinting) {
239             fFlags = (fFlags & ~kHinting_Mask) | (hinting << kHinting_Shift);
240         }
241 
getFormatRec242         SkMask::Format getFormat() const {
243             return static_cast<SkMask::Format>(fMaskFormat);
244         }
245 #ifdef SK_USE_COLOR_LUMINANCE
getLuminanceColorRec246         SkColor getLuminanceColor() const {
247             return fLumBits;
248         }
249 
setLuminanceColorRec250         void setLuminanceColor(SkColor c) {
251             fLumBits = c;
252         }
253 #else
getLuminanceBitsRec254         unsigned getLuminanceBits() const {
255             return (fFlags & kLuminance_Mask) >> kLuminance_Shift;
256         }
257 
setLuminanceBitsRec258         void setLuminanceBits(unsigned lum) {
259             SkASSERT(lum <= kLuminance_Max);
260             fFlags = (fFlags & ~kLuminance_Mask) | (lum << kLuminance_Shift);
261         }
262 
getLuminanceByteRec263         U8CPU getLuminanceByte() const {
264             SkASSERT(3 == kLuminance_Bits);
265             unsigned lum = this->getLuminanceBits();
266             lum |= (lum << kLuminance_Bits);
267             lum |= (lum << kLuminance_Bits*2);
268             return lum >> (4*kLuminance_Bits - 8);
269         }
270 #endif
271     };
272 
273     SkScalerContext(const SkDescriptor* desc);
274     virtual ~SkScalerContext();
275 
getMaskFormat()276     SkMask::Format getMaskFormat() const {
277         return (SkMask::Format)fRec.fMaskFormat;
278     }
279 
isSubpixel()280     bool isSubpixel() const {
281         return SkToBool(fRec.fFlags & kSubpixelPositioning_Flag);
282     }
283 
284     // remember our glyph offset/base
setBaseGlyphCount(unsigned baseGlyphCount)285     void setBaseGlyphCount(unsigned baseGlyphCount) {
286         fBaseGlyphCount = baseGlyphCount;
287     }
288 
289     /** Return the corresponding glyph for the specified unichar. Since contexts
290         may be chained (under the hood), the glyphID that is returned may in
291         fact correspond to a different font/context. In that case, we use the
292         base-glyph-count to know how to translate back into local glyph space.
293      */
294     uint16_t charToGlyphID(SkUnichar uni);
295 
296     /** Map the glyphID to its glyph index, and then to its char code. Unmapped
297         glyphs return zero.
298     */
299     SkUnichar glyphIDToChar(uint16_t glyphID);
300 
getGlyphCount()301     unsigned    getGlyphCount() { return this->generateGlyphCount(); }
302     void        getAdvance(SkGlyph*);
303     void        getMetrics(SkGlyph*);
304     void        getImage(const SkGlyph&);
305     void        getPath(const SkGlyph&, SkPath*);
306     void        getFontMetrics(SkPaint::FontMetrics* mX,
307                                SkPaint::FontMetrics* mY);
308 
309 #ifdef SK_BUILD_FOR_ANDROID
310     // This function must be public for SkTypeface_android.h, but should not be
311     // called by other callers
312     SkFontID findTypefaceIdForChar(SkUnichar uni);
313 
314     unsigned getBaseGlyphCount(SkUnichar charCode);
315 #endif
316 
317     static inline void MakeRec(const SkPaint&, const SkMatrix*, Rec* rec);
318     static inline void PostMakeRec(Rec*);
319 
320     static SkScalerContext* Create(const SkDescriptor*);
321 
322 protected:
323     Rec         fRec;
324     unsigned    fBaseGlyphCount;
325 
326     virtual unsigned generateGlyphCount() = 0;
327     virtual uint16_t generateCharToGlyph(SkUnichar) = 0;
328     virtual void generateAdvance(SkGlyph*) = 0;
329     virtual void generateMetrics(SkGlyph*) = 0;
330     virtual void generateImage(const SkGlyph&) = 0;
331     virtual void generatePath(const SkGlyph&, SkPath*) = 0;
332     virtual void generateFontMetrics(SkPaint::FontMetrics* mX,
333                                      SkPaint::FontMetrics* mY) = 0;
334     // default impl returns 0, indicating failure.
335     virtual SkUnichar generateGlyphToChar(uint16_t);
336 
forceGenerateImageFromPath()337     void forceGenerateImageFromPath() { fGenerateImageFromPath = true; }
338 
339 private:
340     SkScalerContext* getContextFromChar(SkUnichar uni, unsigned& glyphID);
341 
342     SkPathEffect*   fPathEffect;
343     SkMaskFilter*   fMaskFilter;
344     SkRasterizer*   fRasterizer;
345     SkScalar        fDevFrameWidth;
346 
347     // if this is set, we draw the image from a path, rather than
348     // calling generateImage.
349     bool fGenerateImageFromPath;
350 
351     void internalGetPath(const SkGlyph& glyph, SkPath* fillPath,
352                          SkPath* devPath, SkMatrix* fillToDevMatrix);
353 
354     // return the next context, treating fNextContext as a cache of the answer
355     SkScalerContext* getNextContext();
356 
357     // returns the right context from our link-list for this glyph. If no match
358     // is found, just returns the original context (this)
359     SkScalerContext* getGlyphContext(const SkGlyph& glyph);
360 
361     // link-list of context, to handle missing chars. null-terminated.
362     SkScalerContext* fNextContext;
363 };
364 
365 #define kRec_SkDescriptorTag            SkSetFourByteTag('s', 'r', 'e', 'c')
366 #define kPathEffect_SkDescriptorTag     SkSetFourByteTag('p', 't', 'h', 'e')
367 #define kMaskFilter_SkDescriptorTag     SkSetFourByteTag('m', 's', 'k', 'f')
368 #define kRasterizer_SkDescriptorTag     SkSetFourByteTag('r', 'a', 's', 't')
369 
370 ///////////////////////////////////////////////////////////////////////////////
371 
372 enum SkAxisAlignment {
373     kNone_SkAxisAlignment,
374     kX_SkAxisAlignment,
375     kY_SkAxisAlignment
376 };
377 
378 /**
379  *  Return the axis (if any) that the baseline for horizontal text will land on
380  *  after running through the specified matrix.
381  *
382  *  As an example, the identity matrix will return kX_SkAxisAlignment
383  */
384 SkAxisAlignment SkComputeAxisAlignmentForHText(const SkMatrix& matrix);
385 
386 #endif
387 
388