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