SkScalerContext.h revision 81957ccb58db76c172e195dc3e31eba85d3e4ac9
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//#define SK_USE_COLOR_LUMINANCE
21
22class SkDescriptor;
23class SkMaskFilter;
24class SkPathEffect;
25class SkRasterizer;
26
27// needs to be != to any valid SkMask::Format
28#define MASK_FORMAT_UNKNOWN         (0xFF)
29#define MASK_FORMAT_JUST_ADVANCE    MASK_FORMAT_UNKNOWN
30
31#define kMaxGlyphWidth (1<<13)
32
33struct SkGlyph {
34    void*       fImage;
35    SkPath*     fPath;
36    SkFixed     fAdvanceX, fAdvanceY;
37
38    uint32_t    fID;
39    uint16_t    fWidth, fHeight;
40    int16_t     fTop, fLeft;
41
42    uint8_t     fMaskFormat;
43    int8_t      fRsbDelta, fLsbDelta;  // used by auto-kerning
44
45    void init(uint32_t id) {
46        fID             = id;
47        fImage          = NULL;
48        fPath           = NULL;
49        fMaskFormat     = MASK_FORMAT_UNKNOWN;
50    }
51
52    /**
53     *  Compute the rowbytes for the specified width and mask-format.
54     */
55    static unsigned ComputeRowBytes(unsigned width, SkMask::Format format) {
56        unsigned rb = width;
57        if (SkMask::kBW_Format == format) {
58            rb = (rb + 7) >> 3;
59		} else if (SkMask::kARGB32_Format == format ||
60                   SkMask::kLCD32_Format == format)
61        {
62			rb <<= 2;
63		} else if (SkMask::kLCD16_Format == format) {
64			rb = SkAlign4(rb << 1);
65        } else {
66            rb = SkAlign4(rb);
67        }
68        return rb;
69    }
70
71    unsigned rowBytes() const {
72        return ComputeRowBytes(fWidth, (SkMask::Format)fMaskFormat);
73    }
74
75    bool isJustAdvance() const {
76        return MASK_FORMAT_JUST_ADVANCE == fMaskFormat;
77    }
78
79    bool isFullMetrics() const {
80        return MASK_FORMAT_JUST_ADVANCE != fMaskFormat;
81    }
82
83    uint16_t getGlyphID() const {
84        return ID2Code(fID);
85    }
86
87    unsigned getGlyphID(unsigned baseGlyphCount) const {
88        unsigned code = ID2Code(fID);
89        SkASSERT(code >= baseGlyphCount);
90        return code - baseGlyphCount;
91    }
92
93    unsigned getSubX() const {
94        return ID2SubX(fID);
95    }
96
97    SkFixed getSubXFixed() const {
98        return SubToFixed(ID2SubX(fID));
99    }
100
101    SkFixed getSubYFixed() const {
102        return SubToFixed(ID2SubY(fID));
103    }
104
105    size_t computeImageSize() const;
106
107    /** Call this to set all of the metrics fields to 0 (e.g. if the scaler
108        encounters an error measuring a glyph). Note: this does not alter the
109        fImage, fPath, fID, fMaskFormat fields.
110     */
111    void zeroMetrics();
112
113    enum {
114        kSubBits = 2,
115        kSubMask = ((1 << kSubBits) - 1),
116        kSubShift = 24, // must be large enough for glyphs and unichars
117        kCodeMask = ((1 << kSubShift) - 1),
118        // relative offsets for X and Y subpixel bits
119        kSubShiftX = kSubBits,
120        kSubShiftY = 0
121    };
122
123    static unsigned ID2Code(uint32_t id) {
124        return id & kCodeMask;
125    }
126
127    static unsigned ID2SubX(uint32_t id) {
128        return id >> (kSubShift + kSubShiftX);
129    }
130
131    static unsigned ID2SubY(uint32_t id) {
132        return (id >> (kSubShift + kSubShiftY)) & kSubMask;
133    }
134
135    static unsigned FixedToSub(SkFixed n) {
136        return (n >> (16 - kSubBits)) & kSubMask;
137    }
138
139    static SkFixed SubToFixed(unsigned sub) {
140        SkASSERT(sub <= kSubMask);
141        return sub << (16 - kSubBits);
142    }
143
144    static uint32_t MakeID(unsigned code) {
145        return code;
146    }
147
148    static uint32_t MakeID(unsigned code, SkFixed x, SkFixed y) {
149        SkASSERT(code <= kCodeMask);
150        x = FixedToSub(x);
151        y = FixedToSub(y);
152        return (x << (kSubShift + kSubShiftX)) |
153               (y << (kSubShift + kSubShiftY)) |
154               code;
155    }
156
157    void toMask(SkMask* mask) const;
158};
159
160class SkScalerContext {
161public:
162    enum Flags {
163        kFrameAndFill_Flag        = 0x0001,
164        kDevKernText_Flag         = 0x0002,
165        kEmbeddedBitmapText_Flag  = 0x0004,
166        kEmbolden_Flag            = 0x0008,
167        kSubpixelPositioning_Flag = 0x0010,
168        kAutohinting_Flag         = 0x0020,
169        kVertical_Flag            = 0x0040,
170
171        // together, these two flags resulting in a two bit value which matches
172        // up with the SkPaint::Hinting enum.
173        kHinting_Shift            = 7, // to shift into the other flags above
174        kHintingBit1_Flag         = 0x0080,
175        kHintingBit2_Flag         = 0x0100,
176
177        // these should only ever be set if fMaskFormat is LCD16 or LCD32
178        kLCD_Vertical_Flag        = 0x0200,    // else Horizontal
179        kLCD_BGROrder_Flag        = 0x0400,    // else RGB order
180
181        // Generate A8 from LCD source (for GDI), only meaningful if fMaskFormat is kA8
182        // Perhaps we can store this (instead) in fMaskFormat, in hight bit?
183        kGenA8FromLCD_Flag        = 0x0800,
184
185#ifdef SK_USE_COLOR_LUMINANCE
186        kLuminance_Bits           = 3,
187#else
188        // luminance : 0 for black text, kLuminance_Max for white text
189        kLuminance_Shift          = 13, // shift to land in the high 3-bits of Flags
190        kLuminance_Bits           = 3,  // ensure Flags doesn't exceed 16bits
191#endif
192    };
193
194    // computed values
195    enum {
196        kHinting_Mask   = kHintingBit1_Flag | kHintingBit2_Flag,
197#ifdef SK_USE_COLOR_LUMINANCE
198#else
199        kLuminance_Max  = (1 << kLuminance_Bits) - 1,
200        kLuminance_Mask = kLuminance_Max << kLuminance_Shift,
201#endif
202    };
203
204    struct Rec {
205        uint32_t    fOrigFontID;
206        uint32_t    fFontID;
207        SkScalar    fTextSize, fPreScaleX, fPreSkewX;
208        SkScalar    fPost2x2[2][2];
209        SkScalar    fFrameWidth, fMiterLimit;
210#ifdef SK_USE_COLOR_LUMINANCE
211        uint32_t    fLumBits;
212#endif
213        uint8_t     fMaskFormat;
214        uint8_t     fStrokeJoin;
215        uint16_t    fFlags;
216        // Warning: when adding members note that the size of this structure
217        // must be a multiple of 4. SkDescriptor requires that its arguments be
218        // multiples of four and this structure is put in an SkDescriptor in
219        // SkPaint::MakeRec.
220
221        void    getMatrixFrom2x2(SkMatrix*) const;
222        void    getLocalMatrix(SkMatrix*) const;
223        void    getSingleMatrix(SkMatrix*) const;
224
225        SkPaint::Hinting getHinting() const {
226            unsigned hint = (fFlags & kHinting_Mask) >> kHinting_Shift;
227            return static_cast<SkPaint::Hinting>(hint);
228        }
229
230        void setHinting(SkPaint::Hinting hinting) {
231            fFlags = (fFlags & ~kHinting_Mask) | (hinting << kHinting_Shift);
232        }
233
234        SkMask::Format getFormat() const {
235            return static_cast<SkMask::Format>(fMaskFormat);
236        }
237
238#ifdef SK_USE_COLOR_LUMINANCE
239        SkColor getLuminanceColor() const {
240            return fLumBits;
241        }
242
243        void setLuminanceColor(SkColor c) {
244            fLumBits = c;
245        }
246#else
247        unsigned getLuminanceBits() const {
248            return (fFlags & kLuminance_Mask) >> kLuminance_Shift;
249        }
250
251        void setLuminanceBits(unsigned lum) {
252            SkASSERT(lum <= kLuminance_Max);
253            fFlags = (fFlags & ~kLuminance_Mask) | (lum << kLuminance_Shift);
254        }
255
256        U8CPU getLuminanceByte() const {
257            SkASSERT(3 == kLuminance_Bits);
258            unsigned lum = this->getLuminanceBits();
259            lum |= (lum << kLuminance_Bits);
260            lum |= (lum << kLuminance_Bits*2);
261            return lum >> (4*kLuminance_Bits - 8);
262        }
263#endif
264    };
265
266    SkScalerContext(const SkDescriptor* desc);
267    virtual ~SkScalerContext();
268
269    SkMask::Format getMaskFormat() const {
270        return (SkMask::Format)fRec.fMaskFormat;
271    }
272
273    bool isSubpixel() const {
274        return SkToBool(fRec.fFlags & kSubpixelPositioning_Flag);
275    }
276
277    // remember our glyph offset/base
278    void setBaseGlyphCount(unsigned baseGlyphCount) {
279        fBaseGlyphCount = baseGlyphCount;
280    }
281
282    /** Return the corresponding glyph for the specified unichar. Since contexts
283        may be chained (under the hood), the glyphID that is returned may in
284        fact correspond to a different font/context. In that case, we use the
285        base-glyph-count to know how to translate back into local glyph space.
286     */
287    uint16_t charToGlyphID(SkUnichar uni);
288
289    /** Map the glyphID to its glyph index, and then to its char code. Unmapped
290        glyphs return zero.
291    */
292    SkUnichar glyphIDToChar(uint16_t glyphID);
293
294    unsigned    getGlyphCount() { return this->generateGlyphCount(); }
295    void        getAdvance(SkGlyph*);
296    void        getMetrics(SkGlyph*);
297    void        getImage(const SkGlyph&);
298    void        getPath(const SkGlyph&, SkPath*);
299    void        getFontMetrics(SkPaint::FontMetrics* mX,
300                               SkPaint::FontMetrics* mY);
301
302#ifdef SK_BUILD_FOR_ANDROID
303    // This function must be public for SkTypeface_android.h, but should not be
304    // called by other callers
305    SkFontID findTypefaceIdForChar(SkUnichar uni) {
306        SkScalerContext* ctx = this;
307        while (NULL != ctx) {
308            if (ctx->generateCharToGlyph(uni)) {
309                return ctx->fRec.fFontID;
310            }
311            ctx = ctx->getNextContext();
312        }
313        return 0;
314    }
315
316    unsigned getBaseGlyphCount(SkUnichar charCode);
317#endif
318
319    static inline void MakeRec(const SkPaint&, const SkMatrix*, Rec* rec);
320    static inline void PostMakeRec(Rec*);
321
322    static SkScalerContext* Create(const SkDescriptor*);
323
324protected:
325    Rec         fRec;
326    unsigned    fBaseGlyphCount;
327
328    virtual unsigned generateGlyphCount() = 0;
329    virtual uint16_t generateCharToGlyph(SkUnichar) = 0;
330    virtual void generateAdvance(SkGlyph*) = 0;
331    virtual void generateMetrics(SkGlyph*) = 0;
332    virtual void generateImage(const SkGlyph&) = 0;
333    virtual void generatePath(const SkGlyph&, SkPath*) = 0;
334    virtual void generateFontMetrics(SkPaint::FontMetrics* mX,
335                                     SkPaint::FontMetrics* mY) = 0;
336    // default impl returns 0, indicating failure.
337    virtual SkUnichar generateGlyphToChar(uint16_t);
338
339    void forceGenerateImageFromPath() { fGenerateImageFromPath = true; }
340
341private:
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
372enum 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 */
384SkAxisAlignment SkComputeAxisAlignmentForHText(const SkMatrix& matrix);
385
386#endif
387
388