|
1 /* |
|
2 * Copyright 2006 The Android Open Source Project |
|
3 * |
|
4 * Use of this source code is governed by a BSD-style license that can be |
|
5 * found in the LICENSE file. |
|
6 */ |
|
7 |
|
8 #ifndef SkScalerContext_DEFINED |
|
9 #define SkScalerContext_DEFINED |
|
10 |
|
11 #include "SkMask.h" |
|
12 #include "SkMaskGamma.h" |
|
13 #include "SkMatrix.h" |
|
14 #include "SkPaint.h" |
|
15 #include "SkTypeface.h" |
|
16 |
|
17 #ifdef SK_BUILD_FOR_ANDROID |
|
18 #include "SkPaintOptionsAndroid.h" |
|
19 #endif |
|
20 |
|
21 struct SkGlyph; |
|
22 class SkDescriptor; |
|
23 class SkMaskFilter; |
|
24 class SkPathEffect; |
|
25 class SkRasterizer; |
|
26 |
|
27 /* |
|
28 * To allow this to be forward-declared, it must be its own typename, rather |
|
29 * than a nested struct inside SkScalerContext (where it started). |
|
30 */ |
|
31 struct SkScalerContextRec { |
|
32 uint32_t fOrigFontID; |
|
33 uint32_t fFontID; |
|
34 SkScalar fTextSize, fPreScaleX, fPreSkewX; |
|
35 SkScalar fPost2x2[2][2]; |
|
36 SkScalar fFrameWidth, fMiterLimit; |
|
37 |
|
38 //These describe the parameters to create (uniquely identify) the pre-blend. |
|
39 uint32_t fLumBits; |
|
40 uint8_t fDeviceGamma; //2.6, (0.0, 4.0) gamma, 0.0 for sRGB |
|
41 uint8_t fPaintGamma; //2.6, (0.0, 4.0) gamma, 0.0 for sRGB |
|
42 uint8_t fContrast; //0.8+1, [0.0, 1.0] artificial contrast |
|
43 uint8_t fReservedAlign; |
|
44 |
|
45 SkScalar getDeviceGamma() const { |
|
46 return SkIntToScalar(fDeviceGamma) / (1 << 6); |
|
47 } |
|
48 void setDeviceGamma(SkScalar dg) { |
|
49 SkASSERT(0 <= dg && dg < SkIntToScalar(4)); |
|
50 fDeviceGamma = SkScalarFloorToInt(dg * (1 << 6)); |
|
51 } |
|
52 |
|
53 SkScalar getPaintGamma() const { |
|
54 return SkIntToScalar(fPaintGamma) / (1 << 6); |
|
55 } |
|
56 void setPaintGamma(SkScalar pg) { |
|
57 SkASSERT(0 <= pg && pg < SkIntToScalar(4)); |
|
58 fPaintGamma = SkScalarFloorToInt(pg * (1 << 6)); |
|
59 } |
|
60 |
|
61 SkScalar getContrast() const { |
|
62 return SkIntToScalar(fContrast) / ((1 << 8) - 1); |
|
63 } |
|
64 void setContrast(SkScalar c) { |
|
65 SkASSERT(0 <= c && c <= SK_Scalar1); |
|
66 fContrast = SkScalarRoundToInt(c * ((1 << 8) - 1)); |
|
67 } |
|
68 |
|
69 /** |
|
70 * Causes the luminance color and contrast to be ignored, and the |
|
71 * paint and device gamma to be effectively 1.0. |
|
72 */ |
|
73 void ignorePreBlend() { |
|
74 setLuminanceColor(SK_ColorTRANSPARENT); |
|
75 setPaintGamma(SK_Scalar1); |
|
76 setDeviceGamma(SK_Scalar1); |
|
77 setContrast(0); |
|
78 } |
|
79 |
|
80 uint8_t fMaskFormat; |
|
81 uint8_t fStrokeJoin; |
|
82 uint16_t fFlags; |
|
83 // Warning: when adding members note that the size of this structure |
|
84 // must be a multiple of 4. SkDescriptor requires that its arguments be |
|
85 // multiples of four and this structure is put in an SkDescriptor in |
|
86 // SkPaint::MakeRec. |
|
87 |
|
88 void getMatrixFrom2x2(SkMatrix*) const; |
|
89 void getLocalMatrix(SkMatrix*) const; |
|
90 void getSingleMatrix(SkMatrix*) const; |
|
91 |
|
92 inline SkPaint::Hinting getHinting() const; |
|
93 inline void setHinting(SkPaint::Hinting); |
|
94 |
|
95 SkMask::Format getFormat() const { |
|
96 return static_cast<SkMask::Format>(fMaskFormat); |
|
97 } |
|
98 |
|
99 SkColor getLuminanceColor() const { |
|
100 return fLumBits; |
|
101 } |
|
102 |
|
103 void setLuminanceColor(SkColor c) { |
|
104 fLumBits = c; |
|
105 } |
|
106 }; |
|
107 |
|
108 //The following typedef hides from the rest of the implementation the number of |
|
109 //most significant bits to consider when creating mask gamma tables. Two bits |
|
110 //per channel was chosen as a balance between fidelity (more bits) and cache |
|
111 //sizes (fewer bits). Three bits per channel was chosen when #303942; (used by |
|
112 //the Chrome UI) turned out too green. |
|
113 typedef SkTMaskGamma<3, 3, 3> SkMaskGamma; |
|
114 |
|
115 class SkScalerContext { |
|
116 public: |
|
117 typedef SkScalerContextRec Rec; |
|
118 |
|
119 enum Flags { |
|
120 kFrameAndFill_Flag = 0x0001, |
|
121 kDevKernText_Flag = 0x0002, |
|
122 kEmbeddedBitmapText_Flag = 0x0004, |
|
123 kEmbolden_Flag = 0x0008, |
|
124 kSubpixelPositioning_Flag = 0x0010, |
|
125 kForceAutohinting_Flag = 0x0020, // Use auto instead of bytcode hinting if hinting. |
|
126 kVertical_Flag = 0x0040, |
|
127 |
|
128 // together, these two flags resulting in a two bit value which matches |
|
129 // up with the SkPaint::Hinting enum. |
|
130 kHinting_Shift = 7, // to shift into the other flags above |
|
131 kHintingBit1_Flag = 0x0080, |
|
132 kHintingBit2_Flag = 0x0100, |
|
133 |
|
134 // Pixel geometry information. |
|
135 // only meaningful if fMaskFormat is LCD16 or LCD32 |
|
136 kLCD_Vertical_Flag = 0x0200, // else Horizontal |
|
137 kLCD_BGROrder_Flag = 0x0400, // else RGB order |
|
138 |
|
139 // Generate A8 from LCD source (for GDI and CoreGraphics). |
|
140 // only meaningful if fMaskFormat is kA8 |
|
141 kGenA8FromLCD_Flag = 0x0800, // could be 0x200 (bit meaning dependent on fMaskFormat) |
|
142 }; |
|
143 |
|
144 // computed values |
|
145 enum { |
|
146 kHinting_Mask = kHintingBit1_Flag | kHintingBit2_Flag, |
|
147 }; |
|
148 |
|
149 |
|
150 SkScalerContext(SkTypeface*, const SkDescriptor*); |
|
151 virtual ~SkScalerContext(); |
|
152 |
|
153 SkTypeface* getTypeface() const { return fTypeface.get(); } |
|
154 |
|
155 SkMask::Format getMaskFormat() const { |
|
156 return (SkMask::Format)fRec.fMaskFormat; |
|
157 } |
|
158 |
|
159 bool isSubpixel() const { |
|
160 return SkToBool(fRec.fFlags & kSubpixelPositioning_Flag); |
|
161 } |
|
162 |
|
163 // remember our glyph offset/base |
|
164 void setBaseGlyphCount(unsigned baseGlyphCount) { |
|
165 fBaseGlyphCount = baseGlyphCount; |
|
166 } |
|
167 |
|
168 /** Return the corresponding glyph for the specified unichar. Since contexts |
|
169 may be chained (under the hood), the glyphID that is returned may in |
|
170 fact correspond to a different font/context. In that case, we use the |
|
171 base-glyph-count to know how to translate back into local glyph space. |
|
172 */ |
|
173 uint16_t charToGlyphID(SkUnichar uni); |
|
174 |
|
175 /** Map the glyphID to its glyph index, and then to its char code. Unmapped |
|
176 glyphs return zero. |
|
177 */ |
|
178 SkUnichar glyphIDToChar(uint16_t glyphID); |
|
179 |
|
180 unsigned getGlyphCount() { return this->generateGlyphCount(); } |
|
181 void getAdvance(SkGlyph*); |
|
182 void getMetrics(SkGlyph*); |
|
183 void getImage(const SkGlyph&); |
|
184 void getPath(const SkGlyph&, SkPath*); |
|
185 void getFontMetrics(SkPaint::FontMetrics*); |
|
186 |
|
187 #ifdef SK_BUILD_FOR_ANDROID |
|
188 unsigned getBaseGlyphCount(SkUnichar charCode); |
|
189 |
|
190 // This function must be public for SkTypeface_android.h, but should not be |
|
191 // called by other callers |
|
192 SkFontID findTypefaceIdForChar(SkUnichar uni); |
|
193 #endif |
|
194 |
|
195 static inline void MakeRec(const SkPaint&, const SkDeviceProperties* deviceProperties, |
|
196 const SkMatrix*, Rec* rec); |
|
197 static inline void PostMakeRec(const SkPaint&, Rec*); |
|
198 |
|
199 static SkMaskGamma::PreBlend GetMaskPreBlend(const Rec& rec); |
|
200 |
|
201 protected: |
|
202 Rec fRec; |
|
203 unsigned fBaseGlyphCount; |
|
204 |
|
205 /** Generates the contents of glyph.fAdvanceX and glyph.fAdvanceY. |
|
206 * May call getMetrics if that would be just as fast. |
|
207 */ |
|
208 virtual void generateAdvance(SkGlyph* glyph) = 0; |
|
209 |
|
210 /** Generates the contents of glyph.fWidth, fHeight, fTop, fLeft, |
|
211 * as well as fAdvanceX and fAdvanceY if not already set. |
|
212 * |
|
213 * TODO: fMaskFormat is set by getMetrics later; cannot be set here. |
|
214 */ |
|
215 virtual void generateMetrics(SkGlyph* glyph) = 0; |
|
216 |
|
217 /** Generates the contents of glyph.fImage. |
|
218 * When called, glyph.fImage will be pointing to a pre-allocated, |
|
219 * uninitialized region of memory of size glyph.computeImageSize(). |
|
220 * This method may change glyph.fMaskFormat if the new image size is |
|
221 * less than or equal to the old image size. |
|
222 * |
|
223 * Because glyph.computeImageSize() will determine the size of fImage, |
|
224 * generateMetrics will be called before generateImage. |
|
225 */ |
|
226 virtual void generateImage(const SkGlyph& glyph) = 0; |
|
227 |
|
228 /** Sets the passed path to the glyph outline. |
|
229 * If this cannot be done the path is set to empty; |
|
230 * this is indistinguishable from a glyph with an empty path. |
|
231 * This does not set glyph.fPath. |
|
232 * |
|
233 * TODO: path is always glyph.fPath, no reason to pass separately. |
|
234 */ |
|
235 virtual void generatePath(const SkGlyph& glyph, SkPath* path) = 0; |
|
236 |
|
237 /** Retrieves font metrics. |
|
238 * TODO: there is now a vertical bit, no need for two parameters. |
|
239 */ |
|
240 virtual void generateFontMetrics(SkPaint::FontMetrics* mX, |
|
241 SkPaint::FontMetrics* mY) = 0; |
|
242 |
|
243 /** Returns the number of glyphs in the font. */ |
|
244 virtual unsigned generateGlyphCount() = 0; |
|
245 |
|
246 /** Returns the glyph id for the given unichar. |
|
247 * If there is no 1:1 mapping from the unichar to a glyph id, returns 0. |
|
248 */ |
|
249 virtual uint16_t generateCharToGlyph(SkUnichar unichar) = 0; |
|
250 |
|
251 /** Returns the unichar for the given glyph id. |
|
252 * If there is no 1:1 mapping from the glyph id to a unichar, returns 0. |
|
253 * The default implementation always returns 0, indicating failure. |
|
254 */ |
|
255 virtual SkUnichar generateGlyphToChar(uint16_t glyphId); |
|
256 |
|
257 void forceGenerateImageFromPath() { fGenerateImageFromPath = true; } |
|
258 |
|
259 private: |
|
260 // never null |
|
261 SkAutoTUnref<SkTypeface> fTypeface; |
|
262 |
|
263 #ifdef SK_BUILD_FOR_ANDROID |
|
264 SkPaintOptionsAndroid fPaintOptionsAndroid; |
|
265 #endif |
|
266 |
|
267 // optional object, which may be null |
|
268 SkPathEffect* fPathEffect; |
|
269 SkMaskFilter* fMaskFilter; |
|
270 SkRasterizer* fRasterizer; |
|
271 |
|
272 // if this is set, we draw the image from a path, rather than |
|
273 // calling generateImage. |
|
274 bool fGenerateImageFromPath; |
|
275 |
|
276 void internalGetPath(const SkGlyph& glyph, SkPath* fillPath, |
|
277 SkPath* devPath, SkMatrix* fillToDevMatrix); |
|
278 |
|
279 // Return the context associated with the next logical typeface, or NULL if |
|
280 // there are no more entries in the fallback chain. |
|
281 SkScalerContext* allocNextContext() const; |
|
282 |
|
283 // return the next context, treating fNextContext as a cache of the answer |
|
284 SkScalerContext* getNextContext(); |
|
285 |
|
286 // returns the right context from our link-list for this glyph. If no match |
|
287 // is found, just returns the original context (this) |
|
288 SkScalerContext* getGlyphContext(const SkGlyph& glyph); |
|
289 |
|
290 // returns the right context from our link-list for this char. If no match |
|
291 // is found it returns NULL. If a match is found then the glyphID param is |
|
292 // set to the glyphID that maps to the provided char. |
|
293 SkScalerContext* getContextFromChar(SkUnichar uni, uint16_t* glyphID); |
|
294 |
|
295 // link-list of context, to handle missing chars. null-terminated. |
|
296 SkScalerContext* fNextContext; |
|
297 |
|
298 // SkMaskGamma::PreBlend converts linear masks to gamma correcting masks. |
|
299 protected: |
|
300 // Visible to subclasses so that generateImage can apply the pre-blend directly. |
|
301 const SkMaskGamma::PreBlend fPreBlend; |
|
302 private: |
|
303 // When there is a filter, previous steps must create a linear mask |
|
304 // and the pre-blend applied as a final step. |
|
305 const SkMaskGamma::PreBlend fPreBlendForFilter; |
|
306 }; |
|
307 |
|
308 #define kRec_SkDescriptorTag SkSetFourByteTag('s', 'r', 'e', 'c') |
|
309 #define kPathEffect_SkDescriptorTag SkSetFourByteTag('p', 't', 'h', 'e') |
|
310 #define kMaskFilter_SkDescriptorTag SkSetFourByteTag('m', 's', 'k', 'f') |
|
311 #define kRasterizer_SkDescriptorTag SkSetFourByteTag('r', 'a', 's', 't') |
|
312 #ifdef SK_BUILD_FOR_ANDROID |
|
313 #define kAndroidOpts_SkDescriptorTag SkSetFourByteTag('a', 'n', 'd', 'r') |
|
314 #endif |
|
315 |
|
316 /////////////////////////////////////////////////////////////////////////////// |
|
317 |
|
318 enum SkAxisAlignment { |
|
319 kNone_SkAxisAlignment, |
|
320 kX_SkAxisAlignment, |
|
321 kY_SkAxisAlignment |
|
322 }; |
|
323 |
|
324 /** |
|
325 * Return the axis (if any) that the baseline for horizontal text will land on |
|
326 * after running through the specified matrix. |
|
327 * |
|
328 * As an example, the identity matrix will return kX_SkAxisAlignment |
|
329 */ |
|
330 SkAxisAlignment SkComputeAxisAlignmentForHText(const SkMatrix& matrix); |
|
331 |
|
332 /////////////////////////////////////////////////////////////////////////////// |
|
333 |
|
334 SkPaint::Hinting SkScalerContextRec::getHinting() const { |
|
335 unsigned hint = (fFlags & SkScalerContext::kHinting_Mask) >> |
|
336 SkScalerContext::kHinting_Shift; |
|
337 return static_cast<SkPaint::Hinting>(hint); |
|
338 } |
|
339 |
|
340 void SkScalerContextRec::setHinting(SkPaint::Hinting hinting) { |
|
341 fFlags = (fFlags & ~SkScalerContext::kHinting_Mask) | |
|
342 (hinting << SkScalerContext::kHinting_Shift); |
|
343 } |
|
344 |
|
345 |
|
346 #endif |