Line data Source code
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 SkPaint_DEFINED
9 : #define SkPaint_DEFINED
10 :
11 : #include "SkBlendMode.h"
12 : #include "SkColor.h"
13 : #include "SkFilterQuality.h"
14 : #include "SkMatrix.h"
15 : #include "SkRefCnt.h"
16 :
17 : class SkAutoDescriptor;
18 : class SkAutoGlyphCache;
19 : class SkColorFilter;
20 : class SkData;
21 : class SkDescriptor;
22 : class SkDrawLooper;
23 : class SkReadBuffer;
24 : class SkWriteBuffer;
25 : class SkGlyph;
26 : struct SkRect;
27 : class SkGlyphCache;
28 : class SkImageFilter;
29 : class SkMaskFilter;
30 : class SkPath;
31 : class SkPathEffect;
32 : struct SkPoint;
33 : class SkRasterizer;
34 : struct SkScalerContextEffects;
35 : class SkShader;
36 : class SkSurfaceProps;
37 : class SkTextBlob;
38 : class SkTypeface;
39 :
40 : /** \class SkPaint
41 :
42 : The SkPaint class holds the style and color information about how to draw
43 : geometries, text and bitmaps.
44 : */
45 : class SK_API SkPaint {
46 : public:
47 : SkPaint();
48 : SkPaint(const SkPaint& paint);
49 : SkPaint(SkPaint&& paint);
50 : ~SkPaint();
51 :
52 : SkPaint& operator=(const SkPaint&);
53 : SkPaint& operator=(SkPaint&&);
54 :
55 : /** operator== may give false negatives: two paints that draw equivalently
56 : may return false. It will never give false positives: two paints that
57 : are not equivalent always return false.
58 : */
59 : SK_API friend bool operator==(const SkPaint& a, const SkPaint& b);
60 : friend bool operator!=(const SkPaint& a, const SkPaint& b) {
61 : return !(a == b);
62 : }
63 :
64 : /** getHash() is a shallow hash, with the same limitations as operator==.
65 : * If operator== returns true for two paints, getHash() returns the same value for each.
66 : */
67 : uint32_t getHash() const;
68 :
69 : void flatten(SkWriteBuffer&) const;
70 : void unflatten(SkReadBuffer&);
71 :
72 : /** Restores the paint to its initial settings.
73 : */
74 : void reset();
75 :
76 : /** Specifies the level of hinting to be performed. These names are taken
77 : from the Gnome/Cairo names for the same. They are translated into
78 : Freetype concepts the same as in cairo-ft-font.c:
79 : kNo_Hinting -> FT_LOAD_NO_HINTING
80 : kSlight_Hinting -> FT_LOAD_TARGET_LIGHT
81 : kNormal_Hinting -> <default, no option>
82 : kFull_Hinting -> <same as kNormalHinting, unless we are rendering
83 : subpixel glyphs, in which case TARGET_LCD or
84 : TARGET_LCD_V is used>
85 : */
86 : enum Hinting {
87 : kNo_Hinting = 0,
88 : kSlight_Hinting = 1,
89 : kNormal_Hinting = 2, //!< this is the default
90 : kFull_Hinting = 3
91 : };
92 :
93 21 : Hinting getHinting() const {
94 21 : return static_cast<Hinting>(fBitfields.fHinting);
95 : }
96 :
97 : void setHinting(Hinting hintingLevel);
98 :
99 : /** Specifies the bit values that are stored in the paint's flags.
100 : */
101 : enum Flags {
102 : kAntiAlias_Flag = 0x01, //!< mask to enable antialiasing
103 : kDither_Flag = 0x04, //!< mask to enable dithering
104 : kFakeBoldText_Flag = 0x20, //!< mask to enable fake-bold text
105 : kLinearText_Flag = 0x40, //!< mask to enable linear-text
106 : kSubpixelText_Flag = 0x80, //!< mask to enable subpixel text positioning
107 : kDevKernText_Flag = 0x100, //!< mask to enable device kerning text
108 : kLCDRenderText_Flag = 0x200, //!< mask to enable subpixel glyph renderering
109 : kEmbeddedBitmapText_Flag = 0x400, //!< mask to enable embedded bitmap strikes
110 : kAutoHinting_Flag = 0x800, //!< mask to force Freetype's autohinter
111 : kVerticalText_Flag = 0x1000,
112 : kGenA8FromLCD_Flag = 0x2000, // hack for GDI -- do not use if you can help it
113 : // when adding extra flags, note that the fFlags member is specified
114 : // with a bit-width and you'll have to expand it.
115 :
116 : kAllFlags = 0xFFFF,
117 : };
118 :
119 : #ifdef SK_BUILD_FOR_ANDROID_FRAMEWORK
120 : enum ReserveFlags {
121 : // These are not used by paint, but the bits are reserved for private use by the
122 : // android framework.
123 : kUnderlineText_ReserveFlag = 0x08, //!< mask to enable underline text
124 : kStrikeThruText_ReserveFlag = 0x10, //!< mask to enable strike-thru text
125 : };
126 : #endif
127 :
128 : /** Return the paint's flags. Use the Flag enum to test flag values.
129 : @return the paint's flags (see enums ending in _Flag for bit masks)
130 : */
131 964 : uint32_t getFlags() const { return fBitfields.fFlags; }
132 :
133 : /** Set the paint's flags. Use the Flag enum to specific flag values.
134 : @param flags The new flag bits for the paint (see Flags enum)
135 : */
136 : void setFlags(uint32_t flags);
137 :
138 : /** Helper for getFlags(), returning true if kAntiAlias_Flag bit is set
139 : @return true if the antialias bit is set in the paint's flags.
140 : */
141 666 : bool isAntiAlias() const {
142 666 : return SkToBool(this->getFlags() & kAntiAlias_Flag);
143 : }
144 :
145 : /** Helper for setFlags(), setting or clearing the kAntiAlias_Flag bit
146 : @param aa true to enable antialiasing, false to disable it
147 : */
148 : void setAntiAlias(bool aa);
149 :
150 : /** Helper for getFlags(), returning true if kDither_Flag bit is set
151 : @return true if the dithering bit is set in the paint's flags.
152 : */
153 25 : bool isDither() const {
154 25 : return SkToBool(this->getFlags() & kDither_Flag);
155 : }
156 :
157 : /** Helper for setFlags(), setting or clearing the kDither_Flag bit
158 : @param dither true to enable dithering, false to disable it
159 : */
160 : void setDither(bool dither);
161 :
162 : /** Helper for getFlags(), returning true if kLinearText_Flag bit is set
163 : @return true if the lineartext bit is set in the paint's flags
164 : */
165 21 : bool isLinearText() const {
166 21 : return SkToBool(this->getFlags() & kLinearText_Flag);
167 : }
168 :
169 : /** Helper for setFlags(), setting or clearing the kLinearText_Flag bit
170 : @param linearText true to set the linearText bit in the paint's flags,
171 : false to clear it.
172 : */
173 : void setLinearText(bool linearText);
174 :
175 : /** Helper for getFlags(), returning true if kSubpixelText_Flag bit is set
176 : @return true if the lineartext bit is set in the paint's flags
177 : */
178 21 : bool isSubpixelText() const {
179 21 : return SkToBool(this->getFlags() & kSubpixelText_Flag);
180 : }
181 :
182 : /**
183 : * Helper for setFlags(), setting or clearing the kSubpixelText_Flag.
184 : * @param subpixelText true to set the subpixelText bit in the paint's
185 : * flags, false to clear it.
186 : */
187 : void setSubpixelText(bool subpixelText);
188 :
189 21 : bool isLCDRenderText() const {
190 21 : return SkToBool(this->getFlags() & kLCDRenderText_Flag);
191 : }
192 :
193 : /**
194 : * Helper for setFlags(), setting or clearing the kLCDRenderText_Flag.
195 : * Note: antialiasing must also be on for lcd rendering
196 : * @param lcdText true to set the LCDRenderText bit in the paint's flags,
197 : * false to clear it.
198 : */
199 : void setLCDRenderText(bool lcdText);
200 :
201 21 : bool isEmbeddedBitmapText() const {
202 21 : return SkToBool(this->getFlags() & kEmbeddedBitmapText_Flag);
203 : }
204 :
205 : /** Helper for setFlags(), setting or clearing the kEmbeddedBitmapText_Flag bit
206 : @param useEmbeddedBitmapText true to set the kEmbeddedBitmapText bit in the paint's flags,
207 : false to clear it.
208 : */
209 : void setEmbeddedBitmapText(bool useEmbeddedBitmapText);
210 :
211 21 : bool isAutohinted() const {
212 21 : return SkToBool(this->getFlags() & kAutoHinting_Flag);
213 : }
214 :
215 : /** Helper for setFlags(), setting or clearing the kAutoHinting_Flag bit
216 : @param useAutohinter true to set the kEmbeddedBitmapText bit in the
217 : paint's flags,
218 : false to clear it.
219 : */
220 : void setAutohinted(bool useAutohinter);
221 :
222 21 : bool isVerticalText() const {
223 21 : return SkToBool(this->getFlags() & kVerticalText_Flag);
224 : }
225 :
226 : /**
227 : * Helper for setting or clearing the kVerticalText_Flag bit in
228 : * setFlags(...).
229 : *
230 : * If this bit is set, then advances are treated as Y values rather than
231 : * X values, and drawText will places its glyphs vertically rather than
232 : * horizontally.
233 : */
234 : void setVerticalText(bool);
235 :
236 : /** Helper for getFlags(), returns true if kFakeBoldText_Flag bit is set
237 : @return true if the kFakeBoldText_Flag bit is set in the paint's flags.
238 : */
239 42 : bool isFakeBoldText() const {
240 42 : return SkToBool(this->getFlags() & kFakeBoldText_Flag);
241 : }
242 :
243 : /** Helper for setFlags(), setting or clearing the kFakeBoldText_Flag bit
244 : @param fakeBoldText true to set the kFakeBoldText_Flag bit in the paint's
245 : flags, false to clear it.
246 : */
247 : void setFakeBoldText(bool fakeBoldText);
248 :
249 : /** Helper for getFlags(), returns true if kDevKernText_Flag bit is set
250 : @return true if the kernText bit is set in the paint's flags.
251 : */
252 21 : bool isDevKernText() const {
253 21 : return SkToBool(this->getFlags() & kDevKernText_Flag);
254 : }
255 :
256 : /** Helper for setFlags(), setting or clearing the kKernText_Flag bit
257 : @param kernText true to set the kKernText_Flag bit in the paint's
258 : flags, false to clear it.
259 : */
260 : void setDevKernText(bool devKernText);
261 :
262 : /**
263 : * Return the filter level. This affects the quality (and performance) of
264 : * drawing scaled images.
265 : */
266 426 : SkFilterQuality getFilterQuality() const {
267 426 : return (SkFilterQuality)fBitfields.fFilterQuality;
268 : }
269 :
270 : /**
271 : * Set the filter quality. This affects the quality (and performance) of
272 : * drawing scaled images.
273 : */
274 : void setFilterQuality(SkFilterQuality quality);
275 :
276 : /** Styles apply to rect, oval, path, and text.
277 : Bitmaps are always drawn in "fill", and lines are always drawn in
278 : "stroke".
279 :
280 : Note: strokeandfill implicitly draws the result with
281 : SkPath::kWinding_FillType, so if the original path is even-odd, the
282 : results may not appear the same as if it was drawn twice, filled and
283 : then stroked.
284 : */
285 : enum Style {
286 : kFill_Style, //!< fill the geometry
287 : kStroke_Style, //!< stroke the geometry
288 : kStrokeAndFill_Style, //!< fill and stroke the geometry
289 : };
290 : enum {
291 : kStyleCount = kStrokeAndFill_Style + 1
292 : };
293 :
294 : /** Return the paint's style, used for controlling how primitives'
295 : geometries are interpreted (except for drawBitmap, which always assumes
296 : kFill_Style).
297 : @return the paint's Style
298 : */
299 1185 : Style getStyle() const { return (Style)fBitfields.fStyle; }
300 :
301 : /** Set the paint's style, used for controlling how primitives'
302 : geometries are interpreted (except for drawBitmap, which always assumes
303 : Fill).
304 : @param style The new style to set in the paint
305 : */
306 : void setStyle(Style style);
307 :
308 : /** Return the paint's color. Note that the color is a 32bit value
309 : containing alpha as well as r,g,b. This 32bit value is not
310 : premultiplied, meaning that its alpha can be any value, regardless of
311 : the values of r,g,b.
312 : @return the paint's color (and alpha).
313 : */
314 779 : SkColor getColor() const { return fColor; }
315 :
316 : /** Set the paint's color. Note that the color is a 32bit value containing
317 : alpha as well as r,g,b. This 32bit value is not premultiplied, meaning
318 : that its alpha can be any value, regardless of the values of r,g,b.
319 : @param color The new color (including alpha) to set in the paint.
320 : */
321 : void setColor(SkColor color);
322 :
323 : /** Helper to getColor() that just returns the color's alpha value.
324 : @return the alpha component of the paint's color.
325 : */
326 914 : uint8_t getAlpha() const { return SkToU8(SkColorGetA(fColor)); }
327 :
328 : /** Helper to setColor(), that only assigns the color's alpha value,
329 : leaving its r,g,b values unchanged.
330 : @param a set the alpha component (0..255) of the paint's color.
331 : */
332 : void setAlpha(U8CPU a);
333 :
334 : /** Helper to setColor(), that takes a,r,g,b and constructs the color value
335 : using SkColorSetARGB()
336 : @param a The new alpha component (0..255) of the paint's color.
337 : @param r The new red component (0..255) of the paint's color.
338 : @param g The new green component (0..255) of the paint's color.
339 : @param b The new blue component (0..255) of the paint's color.
340 : */
341 : void setARGB(U8CPU a, U8CPU r, U8CPU g, U8CPU b);
342 :
343 : /** Return the width for stroking.
344 : <p />
345 : A value of 0 strokes in hairline mode.
346 : Hairlines always draw 1-pixel wide, regardless of the matrix.
347 : @return the paint's stroke width, used whenever the paint's style is
348 : Stroke or StrokeAndFill.
349 : */
350 297 : SkScalar getStrokeWidth() const { return fWidth; }
351 :
352 : /** Set the width for stroking.
353 : Pass 0 to stroke in hairline mode.
354 : Hairlines always draw 1-pixel wide, regardless of the matrix.
355 : @param width set the paint's stroke width, used whenever the paint's
356 : style is Stroke or StrokeAndFill.
357 : */
358 : void setStrokeWidth(SkScalar width);
359 :
360 : /** Return the paint's stroke miter value. This is used to control the
361 : behavior of miter joins when the joins angle is sharp.
362 : @return the paint's miter limit, used whenever the paint's style is
363 : Stroke or StrokeAndFill.
364 : */
365 30 : SkScalar getStrokeMiter() const { return fMiterLimit; }
366 :
367 : /** Set the paint's stroke miter value. This is used to control the
368 : behavior of miter joins when the joins angle is sharp. This value must
369 : be >= 0.
370 : @param miter set the miter limit on the paint, used whenever the
371 : paint's style is Stroke or StrokeAndFill.
372 : */
373 : void setStrokeMiter(SkScalar miter);
374 :
375 : /** Cap enum specifies the settings for the paint's strokecap. This is the
376 : treatment that is applied to the beginning and end of each non-closed
377 : contour (e.g. lines).
378 :
379 : If the cap is round or square, the caps are drawn when the contour has
380 : a zero length. Zero length contours can be created by following moveTo
381 : with a lineTo at the same point, or a moveTo followed by a close.
382 :
383 : A dash with an on interval of zero also creates a zero length contour.
384 :
385 : The zero length contour draws the square cap without rotation, since
386 : the no direction can be inferred.
387 : */
388 : enum Cap {
389 : kButt_Cap, //!< begin/end contours with no extension
390 : kRound_Cap, //!< begin/end contours with a semi-circle extension
391 : kSquare_Cap, //!< begin/end contours with a half square extension
392 :
393 : kLast_Cap = kSquare_Cap,
394 : kDefault_Cap = kButt_Cap
395 : };
396 : static constexpr int kCapCount = kLast_Cap + 1;
397 :
398 : /** Join enum specifies the settings for the paint's strokejoin. This is
399 : the treatment that is applied to corners in paths and rectangles.
400 : */
401 : enum Join {
402 : kMiter_Join, //!< connect path segments with a sharp join
403 : kRound_Join, //!< connect path segments with a round join
404 : kBevel_Join, //!< connect path segments with a flat bevel join
405 :
406 : kLast_Join = kBevel_Join,
407 : kDefault_Join = kMiter_Join
408 : };
409 : static constexpr int kJoinCount = kLast_Join + 1;
410 :
411 : /** Return the paint's stroke cap type, controlling how the start and end
412 : of stroked lines and paths are treated.
413 : @return the line cap style for the paint, used whenever the paint's
414 : style is Stroke or StrokeAndFill.
415 : */
416 28 : Cap getStrokeCap() const { return (Cap)fBitfields.fCapType; }
417 :
418 : /** Set the paint's stroke cap type.
419 : @param cap set the paint's line cap style, used whenever the paint's
420 : style is Stroke or StrokeAndFill.
421 : */
422 : void setStrokeCap(Cap cap);
423 :
424 : /** Return the paint's stroke join type.
425 : @return the paint's line join style, used whenever the paint's style is
426 : Stroke or StrokeAndFill.
427 : */
428 30 : Join getStrokeJoin() const { return (Join)fBitfields.fJoinType; }
429 :
430 : /** Set the paint's stroke join type.
431 : @param join set the paint's line join style, used whenever the paint's
432 : style is Stroke or StrokeAndFill.
433 : */
434 : void setStrokeJoin(Join join);
435 :
436 : /**
437 : * Applies any/all effects (patheffect, stroking) to src, returning the
438 : * result in dst. The result is that drawing src with this paint will be
439 : * the same as drawing dst with a default paint (at least from the
440 : * geometric perspective).
441 : *
442 : * @param src input path
443 : * @param dst output path (may be the same as src)
444 : * @param cullRect If not null, the dst path may be culled to this rect.
445 : * @param resScale If > 1, increase precision, else if (0 < res < 1) reduce precision
446 : * in favor of speed/size.
447 : * @return true if the path should be filled, or false if it should be
448 : * drawn with a hairline (width == 0)
449 : */
450 : bool getFillPath(const SkPath& src, SkPath* dst, const SkRect* cullRect,
451 : SkScalar resScale = 1) const;
452 :
453 0 : bool getFillPath(const SkPath& src, SkPath* dst) const {
454 0 : return this->getFillPath(src, dst, NULL, 1);
455 : }
456 :
457 : /** Get the paint's shader object.
458 : <p />
459 : The shader's reference count is not affected.
460 : @return the paint's shader (or NULL)
461 : */
462 828 : SkShader* getShader() const { return fShader.get(); }
463 : sk_sp<SkShader> refShader() const;
464 :
465 : /** Set or clear the shader object.
466 : * Shaders specify the source color(s) for what is being drawn. If a paint
467 : * has no shader, then the paint's color is used. If the paint has a
468 : * shader, then the shader's color(s) are use instead, but they are
469 : * modulated by the paint's alpha. This makes it easy to create a shader
470 : * once (e.g. bitmap tiling or gradient) and then change its transparency
471 : * w/o having to modify the original shader... only the paint's alpha needs
472 : * to be modified.
473 : *
474 : * There is an exception to this only-respect-paint's-alpha rule: If the shader only generates
475 : * alpha (e.g. SkShader::CreateBitmapShader(bitmap, ...) where bitmap's colortype is kAlpha_8)
476 : * then the shader will use the paint's entire color to "colorize" its output (modulating the
477 : * bitmap's alpha with the paint's color+alpha).
478 : *
479 : * Pass NULL to clear any previous shader.
480 : * As a convenience, the parameter passed is also returned.
481 : * If a previous shader exists, its reference count is decremented.
482 : * If shader is not NULL, its reference count is incremented.
483 : * @param shader May be NULL. The shader to be installed in the paint
484 : */
485 : void setShader(sk_sp<SkShader>);
486 :
487 : /** Get the paint's colorfilter. If there is a colorfilter, its reference
488 : count is not changed.
489 : @return the paint's colorfilter (or NULL)
490 : */
491 946 : SkColorFilter* getColorFilter() const { return fColorFilter.get(); }
492 : sk_sp<SkColorFilter> refColorFilter() const;
493 :
494 : /** Set or clear the paint's colorfilter.
495 : <p />
496 : If the paint already has a filter, its reference count is decremented.
497 : If filter is not NULL, its reference count is incremented.
498 : @param filter May be NULL. The filter to be installed in the paint
499 : */
500 : void setColorFilter(sk_sp<SkColorFilter>);
501 :
502 948 : SkBlendMode getBlendMode() const { return (SkBlendMode)fBlendMode; }
503 122 : bool isSrcOver() const { return (SkBlendMode)fBlendMode == SkBlendMode::kSrcOver; }
504 441 : void setBlendMode(SkBlendMode mode) { fBlendMode = (unsigned)mode; }
505 :
506 : /** Get the paint's patheffect object.
507 : <p />
508 : The patheffect reference count is not affected.
509 : @return the paint's patheffect (or NULL)
510 : */
511 766 : SkPathEffect* getPathEffect() const { return fPathEffect.get(); }
512 : sk_sp<SkPathEffect> refPathEffect() const;
513 :
514 : /** Set or clear the patheffect object.
515 : <p />
516 : Pass NULL to clear any previous patheffect.
517 : As a convenience, the parameter passed is also returned.
518 : If a previous patheffect exists, its reference count is decremented.
519 : If patheffect is not NULL, its reference count is incremented.
520 : @param effect May be NULL. The new patheffect to be installed in the
521 : paint
522 : @return effect
523 : */
524 : void setPathEffect(sk_sp<SkPathEffect>);
525 :
526 : /** Get the paint's maskfilter object.
527 : <p />
528 : The maskfilter reference count is not affected.
529 : @return the paint's maskfilter (or NULL)
530 : */
531 1471 : SkMaskFilter* getMaskFilter() const { return fMaskFilter.get(); }
532 : sk_sp<SkMaskFilter> refMaskFilter() const;
533 :
534 : /** Set or clear the maskfilter object.
535 : <p />
536 : Pass NULL to clear any previous maskfilter.
537 : As a convenience, the parameter passed is also returned.
538 : If a previous maskfilter exists, its reference count is decremented.
539 : If maskfilter is not NULL, its reference count is incremented.
540 : @param maskfilter May be NULL. The new maskfilter to be installed in
541 : the paint
542 : @return maskfilter
543 : */
544 : void setMaskFilter(sk_sp<SkMaskFilter>);
545 :
546 : // These attributes are for text/fonts
547 :
548 : /** Get the paint's typeface object.
549 : <p />
550 : The typeface object identifies which font to use when drawing or
551 : measuring text. The typeface reference count is not affected.
552 : @return the paint's typeface (or NULL)
553 : */
554 63 : SkTypeface* getTypeface() const { return fTypeface.get(); }
555 : sk_sp<SkTypeface> refTypeface() const;
556 :
557 : /** Set or clear the typeface object.
558 : <p />
559 : Pass NULL to clear any previous typeface.
560 : As a convenience, the parameter passed is also returned.
561 : If a previous typeface exists, its reference count is decremented.
562 : If typeface is not NULL, its reference count is incremented.
563 : @param typeface May be NULL. The new typeface to be installed in the
564 : paint
565 : @return typeface
566 : */
567 : void setTypeface(sk_sp<SkTypeface>);
568 :
569 : /** Get the paint's rasterizer (or NULL).
570 : <p />
571 : The raster controls how paths/text are turned into alpha masks.
572 : @return the paint's rasterizer (or NULL)
573 : */
574 740 : SkRasterizer* getRasterizer() const { return fRasterizer.get(); }
575 : sk_sp<SkRasterizer> refRasterizer() const;
576 :
577 : /** Set or clear the rasterizer object.
578 : <p />
579 : Pass NULL to clear any previous rasterizer.
580 : As a convenience, the parameter passed is also returned.
581 : If a previous rasterizer exists in the paint, its reference count is
582 : decremented. If rasterizer is not NULL, its reference count is
583 : incremented.
584 : @param rasterizer May be NULL. The new rasterizer to be installed in
585 : the paint.
586 : @return rasterizer
587 : */
588 : void setRasterizer(sk_sp<SkRasterizer>);
589 :
590 1766 : SkImageFilter* getImageFilter() const { return fImageFilter.get(); }
591 : sk_sp<SkImageFilter> refImageFilter() const;
592 : void setImageFilter(sk_sp<SkImageFilter>);
593 :
594 : /**
595 : * Return the paint's SkDrawLooper (if any). Does not affect the looper's
596 : * reference count.
597 : */
598 0 : SkDrawLooper* getDrawLooper() const { return fDrawLooper.get(); }
599 : sk_sp<SkDrawLooper> refDrawLooper() const;
600 :
601 1264 : SkDrawLooper* getLooper() const { return fDrawLooper.get(); }
602 : /**
603 : * Set or clear the looper object.
604 : * <p />
605 : * Pass NULL to clear any previous looper.
606 : * If a previous looper exists in the paint, its reference count is
607 : * decremented. If looper is not NULL, its reference count is
608 : * incremented.
609 : * @param looper May be NULL. The new looper to be installed in the paint.
610 : */
611 : void setDrawLooper(sk_sp<SkDrawLooper>);
612 :
613 : void setLooper(sk_sp<SkDrawLooper>);
614 :
615 : enum Align {
616 : kLeft_Align,
617 : kCenter_Align,
618 : kRight_Align,
619 : };
620 : enum {
621 : kAlignCount = 3
622 : };
623 :
624 : /** Return the paint's Align value for drawing text.
625 : @return the paint's Align value for drawing text.
626 : */
627 21 : Align getTextAlign() const { return (Align)fBitfields.fTextAlign; }
628 :
629 : /** Set the paint's text alignment.
630 : @param align set the paint's Align value for drawing text.
631 : */
632 : void setTextAlign(Align align);
633 :
634 : /** Return the paint's text size.
635 : @return the paint's text size.
636 : */
637 21 : SkScalar getTextSize() const { return fTextSize; }
638 :
639 : /** Set the paint's text size. This value must be > 0
640 : @param textSize set the paint's text size.
641 : */
642 : void setTextSize(SkScalar textSize);
643 :
644 : /** Return the paint's horizontal scale factor for text. The default value
645 : is 1.0.
646 : @return the paint's scale factor in X for drawing/measuring text
647 : */
648 21 : SkScalar getTextScaleX() const { return fTextScaleX; }
649 :
650 : /** Set the paint's horizontal scale factor for text. The default value
651 : is 1.0. Values > 1.0 will stretch the text wider. Values < 1.0 will
652 : stretch the text narrower.
653 : @param scaleX set the paint's scale factor in X for drawing/measuring
654 : text.
655 : */
656 : void setTextScaleX(SkScalar scaleX);
657 :
658 : /** Return the paint's horizontal skew factor for text. The default value
659 : is 0.
660 : @return the paint's skew factor in X for drawing text.
661 : */
662 21 : SkScalar getTextSkewX() const { return fTextSkewX; }
663 :
664 : /** Set the paint's horizontal skew factor for text. The default value
665 : is 0. For approximating oblique text, use values around -0.25.
666 : @param skewX set the paint's skew factor in X for drawing text.
667 : */
668 : void setTextSkewX(SkScalar skewX);
669 :
670 : /** Describes how to interpret the text parameters that are passed to paint
671 : methods like measureText() and getTextWidths().
672 : */
673 : enum TextEncoding {
674 : kUTF8_TextEncoding, //!< the text parameters are UTF8
675 : kUTF16_TextEncoding, //!< the text parameters are UTF16
676 : kUTF32_TextEncoding, //!< the text parameters are UTF32
677 : kGlyphID_TextEncoding //!< the text parameters are glyph indices
678 : };
679 :
680 21 : TextEncoding getTextEncoding() const {
681 21 : return (TextEncoding)fBitfields.fTextEncoding;
682 : }
683 :
684 : void setTextEncoding(TextEncoding encoding);
685 :
686 : struct FontMetrics {
687 : /** Flags which indicate the confidence level of various metrics.
688 : A set flag indicates that the metric may be trusted.
689 : */
690 : enum FontMetricsFlags {
691 : kUnderlineThicknessIsValid_Flag = 1 << 0,
692 : kUnderlinePositionIsValid_Flag = 1 << 1,
693 : };
694 :
695 : uint32_t fFlags; //!< Bit field to identify which values are unknown
696 : SkScalar fTop; //!< The greatest distance above the baseline for any glyph (will be <= 0)
697 : SkScalar fAscent; //!< The recommended distance above the baseline (will be <= 0)
698 : SkScalar fDescent; //!< The recommended distance below the baseline (will be >= 0)
699 : SkScalar fBottom; //!< The greatest distance below the baseline for any glyph (will be >= 0)
700 : SkScalar fLeading; //!< The recommended distance to add between lines of text (will be >= 0)
701 : SkScalar fAvgCharWidth; //!< the average character width (>= 0)
702 : SkScalar fMaxCharWidth; //!< the max character width (>= 0)
703 : SkScalar fXMin; //!< The minimum bounding box x value for all glyphs
704 : SkScalar fXMax; //!< The maximum bounding box x value for all glyphs
705 : SkScalar fXHeight; //!< The height of an 'x' in px, or 0 if no 'x' in face
706 : SkScalar fCapHeight; //!< The cap height (> 0), or 0 if cannot be determined.
707 : SkScalar fUnderlineThickness; //!< underline thickness, or 0 if cannot be determined
708 :
709 : /** Underline Position - position of the top of the Underline stroke
710 : relative to the baseline, this can have following values
711 : - Negative - means underline should be drawn above baseline.
712 : - Positive - means below baseline.
713 : - Zero - mean underline should be drawn on baseline.
714 : */
715 : SkScalar fUnderlinePosition; //!< underline position, or 0 if cannot be determined
716 :
717 : /** If the fontmetrics has a valid underline thickness, return true, and set the
718 : thickness param to that value. If it doesn't return false and ignore the
719 : thickness param.
720 : */
721 : bool hasUnderlineThickness(SkScalar* thickness) const {
722 : if (SkToBool(fFlags & kUnderlineThicknessIsValid_Flag)) {
723 : *thickness = fUnderlineThickness;
724 : return true;
725 : }
726 : return false;
727 : }
728 :
729 : /** If the fontmetrics has a valid underline position, return true, and set the
730 : position param to that value. If it doesn't return false and ignore the
731 : position param.
732 : */
733 : bool hasUnderlinePosition(SkScalar* position) const {
734 : if (SkToBool(fFlags & kUnderlinePositionIsValid_Flag)) {
735 : *position = fUnderlinePosition;
736 : return true;
737 : }
738 : return false;
739 : }
740 :
741 : };
742 :
743 : /** Return the recommend spacing between lines (which will be
744 : fDescent - fAscent + fLeading).
745 : If metrics is not null, return in it the font metrics for the
746 : typeface/pointsize/etc. currently set in the paint.
747 : @param metrics If not null, returns the font metrics for the
748 : current typeface/pointsize/etc setting in this
749 : paint.
750 : @param scale If not 0, return width as if the canvas were scaled
751 : by this value
752 : @param return the recommended spacing between lines
753 : */
754 : SkScalar getFontMetrics(FontMetrics* metrics, SkScalar scale = 0) const;
755 :
756 : /** Return the recommend line spacing. This will be
757 : fDescent - fAscent + fLeading
758 : */
759 : SkScalar getFontSpacing() const { return this->getFontMetrics(NULL, 0); }
760 :
761 : /** Convert the specified text into glyph IDs, returning the number of
762 : glyphs ID written. If glyphs is NULL, it is ignore and only the count
763 : is returned.
764 : */
765 : int textToGlyphs(const void* text, size_t byteLength,
766 : SkGlyphID glyphs[]) const;
767 :
768 : /** Return true if all of the specified text has a corresponding non-zero
769 : glyph ID. If any of the code-points in the text are not supported in
770 : the typeface (i.e. the glyph ID would be zero), then return false.
771 :
772 : If the text encoding for the paint is kGlyph_TextEncoding, then this
773 : returns true if all of the specified glyph IDs are non-zero.
774 : */
775 : bool containsText(const void* text, size_t byteLength) const;
776 :
777 : /** Convert the glyph array into Unichars. Unconvertable glyphs are mapped
778 : to zero. Note: this does not look at the text-encoding setting in the
779 : paint, only at the typeface.
780 : */
781 : void glyphsToUnichars(const SkGlyphID glyphs[], int count, SkUnichar text[]) const;
782 :
783 : /** Return the number of drawable units in the specified text buffer.
784 : This looks at the current TextEncoding field of the paint. If you also
785 : want to have the text converted into glyph IDs, call textToGlyphs
786 : instead.
787 : */
788 0 : int countText(const void* text, size_t byteLength) const {
789 0 : return this->textToGlyphs(text, byteLength, NULL);
790 : }
791 :
792 : /** Return the width of the text. This will return the vertical measure
793 : * if isVerticalText() is true, in which case the returned value should
794 : * be treated has a height instead of a width.
795 : *
796 : * @param text The text to be measured
797 : * @param length Number of bytes of text to measure
798 : * @param bounds If not NULL, returns the bounds of the text,
799 : * relative to (0, 0).
800 : * @return The advance width of the text
801 : */
802 : SkScalar measureText(const void* text, size_t length, SkRect* bounds) const;
803 :
804 : /** Return the width of the text. This will return the vertical measure
805 : * if isVerticalText() is true, in which case the returned value should
806 : * be treated has a height instead of a width.
807 : *
808 : * @param text Address of the text
809 : * @param length Number of bytes of text to measure
810 : * @return The advance width of the text
811 : */
812 : SkScalar measureText(const void* text, size_t length) const {
813 : return this->measureText(text, length, NULL);
814 : }
815 :
816 : /** Return the number of bytes of text that were measured. If
817 : * isVerticalText() is true, then the vertical advances are used for
818 : * the measurement.
819 : *
820 : * @param text The text to be measured
821 : * @param length Number of bytes of text to measure
822 : * @param maxWidth Maximum width. Only the subset of text whose accumulated
823 : * widths are <= maxWidth are measured.
824 : * @param measuredWidth Optional. If non-null, this returns the actual
825 : * width of the measured text.
826 : * @return The number of bytes of text that were measured. Will be
827 : * <= length.
828 : */
829 : size_t breakText(const void* text, size_t length, SkScalar maxWidth,
830 : SkScalar* measuredWidth = NULL) const;
831 :
832 : /** Return the advances for the text. These will be vertical advances if
833 : * isVerticalText() returns true.
834 : *
835 : * @param text the text
836 : * @param byteLength number of bytes to of text
837 : * @param widths If not null, returns the array of advances for
838 : * the glyphs. If not NULL, must be at least a large
839 : * as the number of unichars in the specified text.
840 : * @param bounds If not null, returns the bounds for each of
841 : * character, relative to (0, 0)
842 : * @return the number of unichars in the specified text.
843 : */
844 : int getTextWidths(const void* text, size_t byteLength, SkScalar widths[],
845 : SkRect bounds[] = NULL) const;
846 :
847 : /** Return the path (outline) for the specified text.
848 : * Note: just like SkCanvas::drawText, this will respect the Align setting
849 : * in the paint.
850 : *
851 : * @param text the text
852 : * @param length number of bytes of text
853 : * @param x The x-coordinate of the origin of the text.
854 : * @param y The y-coordinate of the origin of the text.
855 : * @param path The outline of the text.
856 : */
857 : void getTextPath(const void* text, size_t length, SkScalar x, SkScalar y,
858 : SkPath* path) const;
859 :
860 : /** Return the path (outline) for the specified text.
861 : * Note: just like SkCanvas::drawText, this will respect the Align setting
862 : * in the paint.
863 : *
864 : * @param text the text
865 : * @param length number of bytes of text
866 : * @param pos array of positions, used to position each character
867 : * @param path The outline of the text.
868 : */
869 : void getPosTextPath(const void* text, size_t length,
870 : const SkPoint pos[], SkPath* path) const;
871 :
872 : /** Return the number of intervals that intersect the intercept along the axis of the advance.
873 : * The return count is zero or a multiple of two, and is at most the number of glyphs * 2 in
874 : * the string. The caller may pass nullptr for intervals to determine the size of the interval
875 : * array, or may conservatively pre-allocate an array with length * 2 entries. The computed
876 : * intervals are cached by glyph to improve performance for multiple calls.
877 : * This permits constructing an underline that skips the descenders.
878 : *
879 : * @param text the text
880 : * @param length number of bytes of text
881 : * @param x The x-coordinate of the origin of the text.
882 : * @param y The y-coordinate of the origin of the text.
883 : * @param bounds The lower and upper line parallel to the advance.
884 : * @param array If not null, the found intersections.
885 : *
886 : * @return The number of intersections, which may be zero.
887 : */
888 : int getTextIntercepts(const void* text, size_t length, SkScalar x, SkScalar y,
889 : const SkScalar bounds[2], SkScalar* intervals) const;
890 :
891 : /** Return the number of intervals that intersect the intercept along the axis of the advance.
892 : * The return count is zero or a multiple of two, and is at most the number of glyphs * 2 in
893 : * string. The caller may pass nullptr for intervals to determine the size of the interval
894 : * array, or may conservatively pre-allocate an array with length * 2 entries. The computed
895 : * intervals are cached by glyph to improve performance for multiple calls.
896 : * This permits constructing an underline that skips the descenders.
897 : *
898 : * @param text the text
899 : * @param length number of bytes of text
900 : * @param pos array of positions, used to position each character
901 : * @param bounds The lower and upper line parallel to the advance.
902 : * @param array If not null, the glyph bounds contained by the advance parallel lines.
903 : *
904 : * @return The number of intersections, which may be zero.
905 : */
906 : int getPosTextIntercepts(const void* text, size_t length, const SkPoint pos[],
907 : const SkScalar bounds[2], SkScalar* intervals) const;
908 :
909 : /** Return the number of intervals that intersect the intercept along the axis of the advance.
910 : * The return count is zero or a multiple of two, and is at most the number of glyphs * 2 in
911 : * string. The caller may pass nullptr for intervals to determine the size of the interval
912 : * array, or may conservatively pre-allocate an array with length * 2 entries. The computed
913 : * intervals are cached by glyph to improve performance for multiple calls.
914 : * This permits constructing an underline that skips the descenders.
915 : *
916 : * @param text The text.
917 : * @param length Number of bytes of text.
918 : * @param xpos Array of x-positions, used to position each character.
919 : * @param constY The shared Y coordinate for all of the positions.
920 : * @param bounds The lower and upper line parallel to the advance.
921 : * @param array If not null, the glyph bounds contained by the advance parallel lines.
922 : *
923 : * @return The number of intersections, which may be zero.
924 : */
925 : int getPosTextHIntercepts(const void* text, size_t length, const SkScalar xpos[],
926 : SkScalar constY, const SkScalar bounds[2], SkScalar* intervals) const;
927 :
928 : /** Return the number of intervals that intersect the intercept along the axis of the advance.
929 : * The return count is zero or a multiple of two, and is at most the number of glyphs * 2 in
930 : * text blob. The caller may pass nullptr for intervals to determine the size of the interval
931 : * array. The computed intervals are cached by glyph to improve performance for multiple calls.
932 : * This permits constructing an underline that skips the descenders.
933 : *
934 : * @param blob The text blob.
935 : * @param bounds The lower and upper line parallel to the advance.
936 : * @param array If not null, the glyph bounds contained by the advance parallel lines.
937 : *
938 : * @return The number of intersections, which may be zero.
939 : */
940 : int getTextBlobIntercepts(const SkTextBlob* blob, const SkScalar bounds[2],
941 : SkScalar* intervals) const;
942 :
943 : /**
944 : * Return a rectangle that represents the union of the bounds of all
945 : * of the glyphs, but each one positioned at (0,0). This may be conservatively large, and
946 : * will not take into account any hinting, but will respect any text-scale-x or text-skew-x
947 : * on this paint.
948 : */
949 : SkRect getFontBounds() const;
950 :
951 : // returns true if the paint's settings (e.g. xfermode + alpha) resolve to
952 : // mean that we need not draw at all (e.g. SrcOver + 0-alpha)
953 : bool nothingToDraw() const;
954 :
955 : ///////////////////////////////////////////////////////////////////////////
956 : // would prefer to make these private...
957 :
958 : /** Returns true if the current paint settings allow for fast computation of
959 : bounds (i.e. there is nothing complex like a patheffect that would make
960 : the bounds computation expensive.
961 : */
962 : bool canComputeFastBounds() const;
963 :
964 : /** Only call this if canComputeFastBounds() returned true. This takes a
965 : raw rectangle (the raw bounds of a shape), and adjusts it for stylistic
966 : effects in the paint (e.g. stroking). If needed, it uses the storage
967 : rect parameter. It returns the adjusted bounds that can then be used
968 : for quickReject tests.
969 :
970 : The returned rect will either be orig or storage, thus the caller
971 : should not rely on storage being set to the result, but should always
972 : use the retured value. It is legal for orig and storage to be the same
973 : rect.
974 :
975 : e.g.
976 : if (paint.canComputeFastBounds()) {
977 : SkRect r, storage;
978 : path.computeBounds(&r, SkPath::kFast_BoundsType);
979 : const SkRect& fastR = paint.computeFastBounds(r, &storage);
980 : if (canvas->quickReject(fastR, ...)) {
981 : // don't draw the path
982 : }
983 : }
984 : */
985 393 : const SkRect& computeFastBounds(const SkRect& orig, SkRect* storage) const {
986 393 : SkPaint::Style style = this->getStyle();
987 : // ultra fast-case: filling with no effects that affect geometry
988 393 : if (kFill_Style == style) {
989 391 : uintptr_t effects = reinterpret_cast<uintptr_t>(this->getLooper());
990 391 : effects |= reinterpret_cast<uintptr_t>(this->getMaskFilter());
991 391 : effects |= reinterpret_cast<uintptr_t>(this->getPathEffect());
992 391 : effects |= reinterpret_cast<uintptr_t>(this->getImageFilter());
993 391 : if (!effects) {
994 391 : return orig;
995 : }
996 : }
997 :
998 2 : return this->doComputeFastBounds(orig, storage, style);
999 : }
1000 :
1001 13 : const SkRect& computeFastStrokeBounds(const SkRect& orig,
1002 : SkRect* storage) const {
1003 13 : return this->doComputeFastBounds(orig, storage, kStroke_Style);
1004 : }
1005 :
1006 : // Take the style explicitly, so the caller can force us to be stroked
1007 : // without having to make a copy of the paint just to change that field.
1008 : const SkRect& doComputeFastBounds(const SkRect& orig, SkRect* storage,
1009 : Style) const;
1010 :
1011 : /**
1012 : * Return a matrix that applies the paint's text values: size, scale, skew
1013 : */
1014 23 : static SkMatrix* SetTextMatrix(SkMatrix* matrix, SkScalar size,
1015 : SkScalar scaleX, SkScalar skewX) {
1016 23 : matrix->setScale(size * scaleX, size);
1017 23 : if (skewX) {
1018 0 : matrix->postSkew(skewX, 0);
1019 : }
1020 23 : return matrix;
1021 : }
1022 :
1023 21 : SkMatrix* setTextMatrix(SkMatrix* matrix) const {
1024 21 : return SetTextMatrix(matrix, fTextSize, fTextScaleX, fTextSkewX);
1025 : }
1026 :
1027 : typedef const SkGlyph& (*GlyphCacheProc)(SkGlyphCache*, const char**);
1028 :
1029 : SK_TO_STRING_NONVIRT()
1030 :
1031 : private:
1032 : sk_sp<SkTypeface> fTypeface;
1033 : sk_sp<SkPathEffect> fPathEffect;
1034 : sk_sp<SkShader> fShader;
1035 : sk_sp<SkMaskFilter> fMaskFilter;
1036 : sk_sp<SkColorFilter> fColorFilter;
1037 : sk_sp<SkRasterizer> fRasterizer;
1038 : sk_sp<SkDrawLooper> fDrawLooper;
1039 : sk_sp<SkImageFilter> fImageFilter;
1040 :
1041 : SkScalar fTextSize;
1042 : SkScalar fTextScaleX;
1043 : SkScalar fTextSkewX;
1044 : SkColor fColor;
1045 : SkScalar fWidth;
1046 : SkScalar fMiterLimit;
1047 : uint32_t fBlendMode; // just need 5-6 bits
1048 : union {
1049 : struct {
1050 : // all of these bitfields should add up to 32
1051 : unsigned fFlags : 16;
1052 : unsigned fTextAlign : 2;
1053 : unsigned fCapType : 2;
1054 : unsigned fJoinType : 2;
1055 : unsigned fStyle : 2;
1056 : unsigned fTextEncoding : 2; // 3 values
1057 : unsigned fHinting : 2;
1058 : unsigned fFilterQuality : 2;
1059 : //unsigned fFreeBits : 2;
1060 : } fBitfields;
1061 : uint32_t fBitfieldsUInt;
1062 : };
1063 :
1064 : static GlyphCacheProc GetGlyphCacheProc(TextEncoding encoding,
1065 : bool isDevKern,
1066 : bool needFullMetrics);
1067 :
1068 : SkScalar measure_text(SkGlyphCache*, const char* text, size_t length,
1069 : int* count, SkRect* bounds) const;
1070 :
1071 : enum ScalerContextFlags : uint32_t {
1072 : kNone_ScalerContextFlags = 0,
1073 :
1074 : kFakeGamma_ScalerContextFlag = 1 << 0,
1075 : kBoostContrast_ScalerContextFlag = 1 << 1,
1076 :
1077 : kFakeGammaAndBoostContrast_ScalerContextFlags =
1078 : kFakeGamma_ScalerContextFlag | kBoostContrast_ScalerContextFlag,
1079 : };
1080 :
1081 : /*
1082 : * Allocs an SkDescriptor on the heap and return it to the caller as a refcnted
1083 : * SkData. Caller is responsible for managing the lifetime of this object.
1084 : */
1085 : void getScalerContextDescriptor(SkScalerContextEffects*, SkAutoDescriptor*,
1086 : const SkSurfaceProps& surfaceProps,
1087 : uint32_t scalerContextFlags, const SkMatrix*) const;
1088 :
1089 : SkGlyphCache* detachCache(const SkSurfaceProps* surfaceProps, uint32_t scalerContextFlags,
1090 : const SkMatrix*) const;
1091 :
1092 : void descriptorProc(const SkSurfaceProps* surfaceProps, uint32_t scalerContextFlags,
1093 : const SkMatrix* deviceMatrix,
1094 : void (*proc)(SkTypeface*, const SkScalerContextEffects&,
1095 : const SkDescriptor*, void*),
1096 : void* context) const;
1097 :
1098 : /*
1099 : * The luminance color is used to determine which Gamma Canonical color to map to. This is
1100 : * really only used by backends which want to cache glyph masks, and need some way to know if
1101 : * they need to generate new masks based off a given color.
1102 : */
1103 : SkColor computeLuminanceColor() const;
1104 :
1105 : enum {
1106 : /* This is the size we use when we ask for a glyph's path. We then
1107 : * post-transform it as we draw to match the request.
1108 : * This is done to try to re-use cache entries for the path.
1109 : *
1110 : * This value is somewhat arbitrary. In theory, it could be 1, since
1111 : * we store paths as floats. However, we get the path from the font
1112 : * scaler, and it may represent its paths as fixed-point (or 26.6),
1113 : * so we shouldn't ask for something too big (might overflow 16.16)
1114 : * or too small (underflow 26.6).
1115 : *
1116 : * This value could track kMaxSizeForGlyphCache, assuming the above
1117 : * constraints, but since we ask for unhinted paths, the two values
1118 : * need not match per-se.
1119 : */
1120 : kCanonicalTextSizeForPaths = 64,
1121 :
1122 : /*
1123 : * Above this size (taking into account CTM and textSize), we never use
1124 : * the cache for bits or metrics (we might overflow), so we just ask
1125 : * for a caononical size and post-transform that.
1126 : */
1127 : kMaxSizeForGlyphCache = 256,
1128 : };
1129 :
1130 : static bool TooBigToUseCache(const SkMatrix& ctm, const SkMatrix& textM);
1131 :
1132 : // Set flags/hinting/textSize up to use for drawing text as paths.
1133 : // Returns scale factor to restore the original textSize, since will will
1134 : // have change it to kCanonicalTextSizeForPaths.
1135 : SkScalar setupForAsPaths();
1136 :
1137 21 : static SkScalar MaxCacheSize2() {
1138 : static const SkScalar kMaxSize = SkIntToScalar(kMaxSizeForGlyphCache);
1139 : static const SkScalar kMag2Max = kMaxSize * kMaxSize;
1140 21 : return kMag2Max;
1141 : }
1142 :
1143 : friend class SkAutoGlyphCache;
1144 : friend class SkAutoGlyphCacheNoGamma;
1145 : friend class SkCanvas;
1146 : friend class SkDraw;
1147 : friend class SkPDFDevice;
1148 : friend class GrAtlasTextBlob;
1149 : friend class GrAtlasTextContext;
1150 : friend class GrStencilAndCoverTextContext;
1151 : friend class GrPathRendering;
1152 : friend class GrTextUtils;
1153 : friend class GrGLPathRendering;
1154 : friend class SkScalerContext;
1155 : friend class SkTextBaseIter;
1156 : friend class SkCanonicalizePaint;
1157 : };
1158 :
1159 : #endif
|