• 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_JUST_ADVANCE    (0xFF)
33 
34 struct 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 
rowBytesSkGlyph46     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 
isJustAdvanceSkGlyph56     bool isJustAdvance() const {
57         return MASK_FORMAT_JUST_ADVANCE == fMaskFormat;
58     }
59 
isFullMetricsSkGlyph60     bool isFullMetrics() const {
61         return MASK_FORMAT_JUST_ADVANCE != fMaskFormat;
62     }
63 
getGlyphIDSkGlyph64     uint16_t getGlyphID() const {
65         return ID2Code(fID);
66     }
67 
getGlyphIDSkGlyph68     unsigned getGlyphID(unsigned baseGlyphCount) const {
69         unsigned code = ID2Code(fID);
70         SkASSERT(code >= baseGlyphCount);
71         return code - baseGlyphCount;
72     }
73 
getSubXSkGlyph74     unsigned getSubX() const {
75         return ID2SubX(fID);
76     }
77 
getSubXFixedSkGlyph78     SkFixed getSubXFixed() const {
79         return SubToFixed(ID2SubX(fID));
80     }
81 
getSubYFixedSkGlyph82     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 
ID2CodeSkGlyph104     static unsigned ID2Code(uint32_t id) {
105         return id & kCodeMask;
106     }
107 
ID2SubXSkGlyph108     static unsigned ID2SubX(uint32_t id) {
109         return id >> (kSubShift + kSubShiftX);
110     }
111 
ID2SubYSkGlyph112     static unsigned ID2SubY(uint32_t id) {
113         return (id >> (kSubShift + kSubShiftY)) & kSubMask;
114     }
115 
FixedToSubSkGlyph116     static unsigned FixedToSub(SkFixed n) {
117         return (n >> (16 - kSubBits)) & kSubMask;
118     }
119 
SubToFixedSkGlyph120     static SkFixed SubToFixed(unsigned sub) {
121         SkASSERT(sub <= kSubMask);
122         return sub << (16 - kSubBits);
123     }
124 
MakeIDSkGlyph125     static uint32_t MakeID(unsigned code) {
126         return code;
127     }
128 
MakeIDSkGlyph129     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 
146 class SkScalerContext {
147 public:
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     };
160 private:
161     enum {
162         kHintingMask = kHintingBit1_Flag | kHintingBit2_Flag
163     };
164 public:
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 
getHintingRec183         SkPaint::Hinting getHinting() const {
184             return static_cast<SkPaint::Hinting>((fFlags & kHintingMask) >> 4);
185         }
186 
setHintingRec187         void setHinting(SkPaint::Hinting hinting) {
188             fFlags = (fFlags & ~kHintingMask) | (hinting << 4);
189         }
190 
getFormatRec191         SkMask::Format getFormat() const {
192             return static_cast<SkMask::Format>(fMaskFormat);
193         }
194 
isLCDRec195         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
setBaseGlyphCount(unsigned baseGlyphCount)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 
getGlyphCount()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 
231 protected:
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 
246 private:
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