SkScalerContext.h revision 1c980e0d7772f05f570ae0227d91635f017c2227
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
26class SkDescriptor;
27class SkMaskFilter;
28class SkPathEffect;
29class SkRasterizer;
30
31// needs to be != to any valid SkMask::Format
32#define MASK_FORMAT_JUST_ADVANCE    (0xFF)
33
34struct SkGlyph {
35    void*       fImage;
36    SkPath*     fPath;
37    SkFixed     fAdvanceX, fAdvanceY;
38
39    uint32_t    fID;
40    uint16_t    fWidth, fHeight;
41    int16_t     fTop, fLeft;
42
43    uint8_t     fMaskFormat;
44    int8_t      fRsbDelta, fLsbDelta;  // used by auto-kerning
45
46    unsigned rowBytes() const {
47        unsigned rb = fWidth;
48        if (SkMask::kBW_Format == fMaskFormat) {
49            rb = (rb + 7) >> 3;
50        } else {
51            rb = SkAlign4(rb);
52        }
53        return rb;
54    }
55
56    bool isJustAdvance() const {
57        return MASK_FORMAT_JUST_ADVANCE == fMaskFormat;
58    }
59
60    bool isFullMetrics() const {
61        return MASK_FORMAT_JUST_ADVANCE != fMaskFormat;
62    }
63
64    uint16_t getGlyphID() const {
65        return ID2Code(fID);
66    }
67
68    unsigned getGlyphID(unsigned baseGlyphCount) const {
69        unsigned code = ID2Code(fID);
70        SkASSERT(code >= baseGlyphCount);
71        return code - baseGlyphCount;
72    }
73
74    unsigned getSubX() const {
75        return ID2SubX(fID);
76    }
77
78    SkFixed getSubXFixed() const {
79        return SubToFixed(ID2SubX(fID));
80    }
81
82    SkFixed getSubYFixed() const {
83        return SubToFixed(ID2SubY(fID));
84    }
85
86    size_t computeImageSize() const;
87
88    /** Call this to set all of the metrics fields to 0 (e.g. if the scaler
89        encounters an error measuring a glyph). Note: this does not alter the
90        fImage, fPath, fID, fMaskFormat fields.
91     */
92    void zeroMetrics();
93
94    enum {
95        kSubBits = 2,
96        kSubMask = ((1 << kSubBits) - 1),
97        kSubShift = 24, // must be large enough for glyphs and unichars
98        kCodeMask = ((1 << kSubShift) - 1),
99        // relative offsets for X and Y subpixel bits
100        kSubShiftX = kSubBits,
101        kSubShiftY = 0
102    };
103
104    static unsigned ID2Code(uint32_t id) {
105        return id & kCodeMask;
106    }
107
108    static unsigned ID2SubX(uint32_t id) {
109        return id >> (kSubShift + kSubShiftX);
110    }
111
112    static unsigned ID2SubY(uint32_t id) {
113        return (id >> (kSubShift + kSubShiftY)) & kSubMask;
114    }
115
116    static unsigned FixedToSub(SkFixed n) {
117        return (n >> (16 - kSubBits)) & kSubMask;
118    }
119
120    static SkFixed SubToFixed(unsigned sub) {
121        SkASSERT(sub <= kSubMask);
122        return sub << (16 - kSubBits);
123    }
124
125    static uint32_t MakeID(unsigned code) {
126        return code;
127    }
128
129    static uint32_t MakeID(unsigned code, SkFixed x, SkFixed y) {
130        SkASSERT(code <= kCodeMask);
131        x = FixedToSub(x);
132        y = FixedToSub(y);
133        return (x << (kSubShift + kSubShiftX)) |
134               (y << (kSubShift + kSubShiftY)) |
135               code;
136    }
137
138    void toMask(SkMask* mask) const;
139
140    /** Given a glyph which is has a mask format of LCD or VerticalLCD, take
141        the A8 plane in fImage and produce a valid LCD plane from it.
142    */
143    void expandA8ToLCD() const;
144};
145
146class SkScalerContext {
147public:
148    enum Flags {
149        kFrameAndFill_Flag  = 0x01,
150        kDevKernText_Flag   = 0x02,
151        kGammaForBlack_Flag = 0x04, // illegal to set both Gamma flags
152        kGammaForWhite_Flag = 0x08, // illegal to set both Gamma flags
153        // together, these two flags resulting in a two bit value which matches
154        // up with the SkPaint::Hinting enum.
155        kHintingBit1_Flag   = 0x10,
156        kHintingBit2_Flag   = 0x20,
157        kEmbeddedBitmapText_Flag = 0x40,
158        kEmbolden_Flag      = 0x80,
159    };
160private:
161    enum {
162        kHintingMask = kHintingBit1_Flag | kHintingBit2_Flag
163    };
164public:
165    struct Rec {
166        uint32_t    fFontID;
167        SkScalar    fTextSize, fPreScaleX, fPreSkewX;
168        SkScalar    fPost2x2[2][2];
169        SkScalar    fFrameWidth, fMiterLimit;
170        bool        fSubpixelPositioning;
171        uint8_t     fMaskFormat;
172        uint8_t     fStrokeJoin;
173        uint8_t     fFlags;
174        // Warning: when adding members note that the size of this structure
175        // must be a multiple of 4. SkDescriptor requires that its arguments be
176        // multiples of four and this structure is put in an SkDescriptor in
177        // SkPaint::MakeRec.
178
179        void    getMatrixFrom2x2(SkMatrix*) const;
180        void    getLocalMatrix(SkMatrix*) const;
181        void    getSingleMatrix(SkMatrix*) const;
182
183        SkPaint::Hinting getHinting() const {
184            return static_cast<SkPaint::Hinting>((fFlags & kHintingMask) >> 4);
185        }
186
187        void setHinting(SkPaint::Hinting hinting) {
188            fFlags = (fFlags & ~kHintingMask) | (hinting << 4);
189        }
190
191        SkMask::Format getFormat() const {
192            return static_cast<SkMask::Format>(fMaskFormat);
193        }
194
195        bool isLCD() const {
196            return SkMask::FormatIsLCD(this->getFormat());
197        }
198    };
199
200    SkScalerContext(const SkDescriptor* desc);
201    virtual ~SkScalerContext();
202
203    // remember our glyph offset/base
204    void setBaseGlyphCount(unsigned baseGlyphCount) {
205        fBaseGlyphCount = baseGlyphCount;
206    }
207
208    /** Return the corresponding glyph for the specified unichar. Since contexts
209        may be chained (under the hood), the glyphID that is returned may in
210        fact correspond to a different font/context. In that case, we use the
211        base-glyph-count to know how to translate back into local glyph space.
212     */
213    uint16_t    charToGlyphID(SkUnichar uni);
214
215    /** Map the glyphID to its glyph index, and then to its char code. Unmapped
216        glyphs return zero.
217    */
218    SkUnichar glyphIDToChar(uint16_t glyphID);
219
220    unsigned    getGlyphCount() const { return this->generateGlyphCount(); }
221    void        getAdvance(SkGlyph*);
222    void        getMetrics(SkGlyph*);
223    void        getImage(const SkGlyph&);
224    void        getPath(const SkGlyph&, SkPath*);
225    void        getFontMetrics(SkPaint::FontMetrics* mX,
226                               SkPaint::FontMetrics* mY);
227
228    static inline void MakeRec(const SkPaint&, const SkMatrix*, Rec* rec);
229    static SkScalerContext* Create(const SkDescriptor*);
230
231protected:
232    Rec         fRec;
233    unsigned    fBaseGlyphCount;
234
235    virtual unsigned generateGlyphCount() const = 0;
236    virtual uint16_t generateCharToGlyph(SkUnichar) = 0;
237    virtual void generateAdvance(SkGlyph*) = 0;
238    virtual void generateMetrics(SkGlyph*) = 0;
239    virtual void generateImage(const SkGlyph&) = 0;
240    virtual void generatePath(const SkGlyph&, SkPath*) = 0;
241    virtual void generateFontMetrics(SkPaint::FontMetrics* mX,
242                                     SkPaint::FontMetrics* mY) = 0;
243    // default impl returns 0, indicating failure.
244    virtual SkUnichar generateGlyphToChar(uint16_t);
245
246private:
247    SkPathEffect*   fPathEffect;
248    SkMaskFilter*   fMaskFilter;
249    SkRasterizer*   fRasterizer;
250    SkScalar        fDevFrameWidth;
251
252    void internalGetPath(const SkGlyph& glyph, SkPath* fillPath,
253                         SkPath* devPath, SkMatrix* fillToDevMatrix);
254
255    // return the next context, treating fNextContext as a cache of the answer
256    SkScalerContext* getNextContext();
257
258    // returns the right context from our link-list for this glyph. If no match
259    // is found, just returns the original context (this)
260    SkScalerContext* getGlyphContext(const SkGlyph& glyph);
261
262    // link-list of context, to handle missing chars. null-terminated.
263    SkScalerContext* fNextContext;
264};
265
266#define kRec_SkDescriptorTag            SkSetFourByteTag('s', 'r', 'e', 'c')
267#define kPathEffect_SkDescriptorTag     SkSetFourByteTag('p', 't', 'h', 'e')
268#define kMaskFilter_SkDescriptorTag     SkSetFourByteTag('m', 's', 'k', 'f')
269#define kRasterizer_SkDescriptorTag     SkSetFourByteTag('r', 'a', 's', 't')
270
271#endif
272
273