blob: 057135414ef0f21584b9746d5119c9210005fb64 [file] [log] [blame]
Cary Clark0c5f5462017-12-15 11:21:51 -05001#Topic Paint
Cary Clark12799e12017-07-28 15:18:29 -04002#Alias Paint_Reference
Cary Clark8032b982017-07-28 11:04:54 -04003
Cary Clarke4aa3712017-09-15 02:56:12 -04004#Class SkPaint
5
Cary Clark8032b982017-07-28 11:04:54 -04006Paint controls options applied when drawing and measuring. Paint collects all
7options outside of the Canvas_Clip and Canvas_Matrix.
8
Herb Derbyfcac00f2018-05-01 11:57:56 -04009Various options apply to text, strokes and fills, and images.
Cary Clark8032b982017-07-28 11:04:54 -040010
11Some options may not be implemented on all platforms; in these cases, setting
12the option has no effect. Some options are conveniences that duplicate Canvas
13functionality; for instance, text size is identical to matrix scale.
14
15Paint options are rarely exclusive; each option modifies a stage of the drawing
16pipeline and multiple pipeline stages may be affected by a single Paint.
17
Herb Derbyfcac00f2018-05-01 11:57:56 -040018Paint collects effects and filters that describe single-pass and multiple-pass
Cary Clark8032b982017-07-28 11:04:54 -040019algorithms that alter the drawing geometry, color, and transparency. For instance,
Herb Derbyfcac00f2018-05-01 11:57:56 -040020Paint does not directly implement dashing or blur, but contains the objects that do so.
Cary Clark8032b982017-07-28 11:04:54 -040021
22The objects contained by Paint are opaque, and cannot be edited outside of the Paint
23to affect it. The implementation is free to defer computations associated with the
24Paint, or ignore them altogether. For instance, some GPU implementations draw all
Cary Clarkffb3d682018-05-17 12:17:28 -040025Path geometries with Anti_Aliasing, regardless of how SkPaint::kAntiAlias_Flag
Cary Clarkbad5ad72017-08-03 17:14:08 -040026is set in Paint.
Cary Clark8032b982017-07-28 11:04:54 -040027
28Paint describes a single color, a single font, a single image quality, and so on.
29Multiple colors are drawn either by using multiple paints or with objects like
30Shader attached to Paint.
31
Cary Clark682c58d2018-05-16 07:07:07 -040032#Subtopic Overview
33#Populate
34##
35
Cary Clark4855f782018-02-06 09:41:53 -050036#Subtopic Related_Function
Cary Clark08895c42018-02-01 09:37:32 -050037#Populate
38##
Cary Clark8032b982017-07-28 11:04:54 -040039
Cary Clark4855f782018-02-06 09:41:53 -050040#Subtopic Constant
Cary Clark08895c42018-02-01 09:37:32 -050041#Populate
42##
Cary Clark8032b982017-07-28 11:04:54 -040043
Cary Clark682c58d2018-05-16 07:07:07 -040044#Subtopic Struct
Cary Clark08895c42018-02-01 09:37:32 -050045#Populate
46##
Cary Clark8032b982017-07-28 11:04:54 -040047
Cary Clark4855f782018-02-06 09:41:53 -050048#Subtopic Constructor
Cary Clark08895c42018-02-01 09:37:32 -050049#Populate
50##
Cary Clark8032b982017-07-28 11:04:54 -040051
Cary Clark4855f782018-02-06 09:41:53 -050052#Subtopic Operator
Cary Clark08895c42018-02-01 09:37:32 -050053#Populate
54##
Cary Clark8032b982017-07-28 11:04:54 -040055
Cary Clark4855f782018-02-06 09:41:53 -050056#Subtopic Member_Function
Cary Clark08895c42018-02-01 09:37:32 -050057#Populate
58##
Cary Clark8032b982017-07-28 11:04:54 -040059
60# ------------------------------------------------------------------------------
Cary Clark08895c42018-02-01 09:37:32 -050061#Subtopic Initializers
62#Line # constructors and initialization ##
Cary Clark8032b982017-07-28 11:04:54 -040063
64#Method SkPaint()
65
Cary Clarkab2621d2018-01-30 10:08:57 -050066#In Initializers
67#Line # constructs with default values ##
Cary Clark8032b982017-07-28 11:04:54 -040068Constructs Paint with default values.
69
70#Table
71#Legend
72# attribute # default value ##
73#Legend ##
Cary Clarkffb3d682018-05-17 12:17:28 -040074# Anti_Alias # false ##
Cary Clarkce101242017-09-01 15:51:02 -040075# Blend_Mode # SkBlendMode::kSrcOver ##
Cary Clark8032b982017-07-28 11:04:54 -040076# Color # SK_ColorBLACK ##
77# Color_Alpha # 255 ##
78# Color_Filter # nullptr ##
79# Dither # false ##
80# Draw_Looper # nullptr ##
81# Fake_Bold # false ##
82# Filter_Quality # kNone_SkFilterQuality ##
83# Font_Embedded_Bitmaps # false ##
84# Automatic_Hinting # false ##
85# Full_Hinting_Spacing # false ##
86# Hinting # kNormal_Hinting ##
87# Image_Filter # nullptr ##
88# LCD_Text # false ##
89# Linear_Text # false ##
90# Miter_Limit # 4 ##
91# Mask_Filter # nullptr ##
92# Path_Effect # nullptr ##
Cary Clark8032b982017-07-28 11:04:54 -040093# Shader # nullptr ##
94# Style # kFill_Style ##
95# Text_Align # kLeft_Align ##
96# Text_Encoding # kUTF8_TextEncoding ##
97# Text_Scale_X # 1 ##
98# Text_Size # 12 ##
99# Text_Skew_X # 0 ##
100# Typeface # nullptr ##
101# Stroke_Cap # kButt_Cap ##
102# Stroke_Join # kMiter_Join ##
103# Stroke_Width # 0 ##
104# Subpixel_Text # false ##
105# Vertical_Text # false ##
106#Table ##
107
108The flags, text size, hinting, and miter limit may be overridden at compile time by defining
Herb Derbyfcac00f2018-05-01 11:57:56 -0400109paint default values. The overrides may be included in "SkUserConfig.h" or predefined by the
Cary Clark8032b982017-07-28 11:04:54 -0400110build system.
111
112#Return default initialized Paint ##
113
114#Example
115#ToDo mark this as no output ##
116#Height 1
117###$ $ redefine markup character so preprocessor commands appear normally
118#ifndef SkUserConfig_DEFINED
119#define SkUserConfig_DEFINED
120
121#define SkPaintDefaults_Flags 0x01 // always enable antialiasing
122#define SkPaintDefaults_TextSize 24.f // double default font size
123#define SkPaintDefaults_Hinting 3 // use full hinting
124#define SkPaintDefaults_MiterLimit 10.f // use HTML Canvas miter limit setting
125
126#endif
127$$$# # restore original markup character
128##
129
130
131##
132
133#Method SkPaint(const SkPaint& paint)
134
Cary Clarkab2621d2018-01-30 10:08:57 -0500135#In Initializers
136#Line # makes a shallow copy ##
Cary Clark8032b982017-07-28 11:04:54 -0400137Makes a shallow copy of Paint. Typeface, Path_Effect, Shader,
Mike Reed8ad91a92018-01-19 19:09:32 -0500138Mask_Filter, Color_Filter, Draw_Looper, and Image_Filter are shared
Cary Clarkbad5ad72017-08-03 17:14:08 -0400139between the original paint and the copy. Objects containing Reference_Count increment
140their references by one.
Cary Clark8032b982017-07-28 11:04:54 -0400141
Mike Reed8ad91a92018-01-19 19:09:32 -0500142The referenced objects Path_Effect, Shader, Mask_Filter, Color_Filter,
Cary Clark8032b982017-07-28 11:04:54 -0400143Draw_Looper, and Image_Filter cannot be modified after they are created.
144This prevents objects with Reference_Count from being modified once Paint refers to them.
145
146#Param paint original to copy ##
147
148#Return shallow copy of paint ##
149
150#Example
151#ToDo why is this double-spaced on Fiddle? ##
152 SkPaint paint1;
153 paint1.setColor(SK_ColorRED);
154 SkPaint paint2(paint1);
155 paint2.setColor(SK_ColorBLUE);
156 SkDebugf("SK_ColorRED %c= paint1.getColor()\n", SK_ColorRED == paint1.getColor() ? '=' : '!');
157 SkDebugf("SK_ColorBLUE %c= paint2.getColor()\n", SK_ColorBLUE == paint2.getColor() ? '=' : '!');
158
159 #StdOut
160 SK_ColorRED == paint1.getColor()
161 SK_ColorBLUE == paint2.getColor()
162 ##
163##
164
165##
166
167#Method SkPaint(SkPaint&& paint)
168
Cary Clarkab2621d2018-01-30 10:08:57 -0500169#In Initializers
170#Line # moves paint without copying it ##
Cary Clarkd0530ba2017-09-14 11:25:39 -0400171 Implements a move constructor to avoid increasing the reference counts
Cary Clark8032b982017-07-28 11:04:54 -0400172 of objects referenced by the paint.
173
174 After the call, paint is undefined, and can be safely destructed.
175
176 #Param paint original to move ##
177
178 #Return content of paint ##
179
180 #Example
181 SkPaint paint;
182 float intervals[] = { 5, 5 };
183 paint.setPathEffect(SkDashPathEffect::Make(intervals, SK_ARRAY_COUNT(intervals), 2.5f));
184 SkPaint dashed(std::move(paint));
185 SkDebugf("path effect unique: %s\n", dashed.getPathEffect()->unique() ? "true" : "false");
186
187 #StdOut
188 path effect unique: true
189 ##
190 ##
191
192##
193
194# ------------------------------------------------------------------------------
195
196#Method void reset()
197
Cary Clarkab2621d2018-01-30 10:08:57 -0500198#In Initializers
199#Line # sets to default values ##
Cary Clarkbc5697d2017-10-04 14:31:33 -0400200Sets all Paint contents to their initial values. This is equivalent to replacing
201Paint with the result of SkPaint().
Cary Clark8032b982017-07-28 11:04:54 -0400202
203#Example
204 SkPaint paint1, paint2;
205 paint1.setColor(SK_ColorRED);
206 paint1.reset();
207 SkDebugf("paint1 %c= paint2", paint1 == paint2 ? '=' : '!');
208
209 #StdOut
210 paint1 == paint2
211 ##
212##
213
214##
215
Cary Clark08895c42018-02-01 09:37:32 -0500216#Subtopic Initializers ##
Cary Clark8032b982017-07-28 11:04:54 -0400217
218# ------------------------------------------------------------------------------
Cary Clark8032b982017-07-28 11:04:54 -0400219
220#Method ~SkPaint()
221
Cary Clarkab2621d2018-01-30 10:08:57 -0500222#Line # decreases Reference_Count of owned objects ##
Cary Clark8032b982017-07-28 11:04:54 -0400223Decreases Paint Reference_Count of owned objects: Typeface, Path_Effect, Shader,
Mike Reed8ad91a92018-01-19 19:09:32 -0500224Mask_Filter, Color_Filter, Draw_Looper, and Image_Filter. If the
Cary Clarkbad5ad72017-08-03 17:14:08 -0400225objects containing Reference_Count go to zero, they are deleted.
Cary Clark8032b982017-07-28 11:04:54 -0400226
Herb Derbyfcac00f2018-05-01 11:57:56 -0400227#NoExample
Cary Clark8032b982017-07-28 11:04:54 -0400228##
229
230##
231
Cary Clark08895c42018-02-01 09:37:32 -0500232
Cary Clark8032b982017-07-28 11:04:54 -0400233# ------------------------------------------------------------------------------
Cary Clark08895c42018-02-01 09:37:32 -0500234#Subtopic Management
235#Line # paint copying, moving, comparing ##
Cary Clark8032b982017-07-28 11:04:54 -0400236
237#Method SkPaint& operator=(const SkPaint& paint)
238
Cary Clarkab2621d2018-01-30 10:08:57 -0500239#In Management
240#Line # makes a shallow copy ##
Cary Clark8032b982017-07-28 11:04:54 -0400241Makes a shallow copy of Paint. Typeface, Path_Effect, Shader,
Mike Reed8ad91a92018-01-19 19:09:32 -0500242Mask_Filter, Color_Filter, Draw_Looper, and Image_Filter are shared
Cary Clarkbad5ad72017-08-03 17:14:08 -0400243between the original paint and the copy. Objects containing Reference_Count in the
Cary Clark8032b982017-07-28 11:04:54 -0400244prior destination are decreased by one, and the referenced objects are deleted if the
Cary Clarkbad5ad72017-08-03 17:14:08 -0400245resulting count is zero. Objects containing Reference_Count in the parameter paint
246are increased by one. paint is unmodified.
Cary Clark8032b982017-07-28 11:04:54 -0400247
248#Param paint original to copy ##
249
250#Return content of paint ##
251
252#Example
253 SkPaint paint1, paint2;
254 paint1.setColor(SK_ColorRED);
255 paint2 = paint1;
256 SkDebugf("SK_ColorRED %c= paint1.getColor()\n", SK_ColorRED == paint1.getColor() ? '=' : '!');
257 SkDebugf("SK_ColorRED %c= paint2.getColor()\n", SK_ColorRED == paint2.getColor() ? '=' : '!');
258
259 #StdOut
260 SK_ColorRED == paint1.getColor()
261 SK_ColorRED == paint2.getColor()
262 ##
263##
264
265##
266
267# ------------------------------------------------------------------------------
268
269#Method SkPaint& operator=(SkPaint&& paint)
270
Cary Clarkab2621d2018-01-30 10:08:57 -0500271#In Management
272#Line # moves paint without copying it ##
Cary Clarkd0530ba2017-09-14 11:25:39 -0400273Moves the paint to avoid increasing the reference counts
Cary Clarkbad5ad72017-08-03 17:14:08 -0400274of objects referenced by the paint parameter. Objects containing Reference_Count in the
275prior destination are decreased by one; those objects are deleted if the resulting count
276is zero.
Cary Clark8032b982017-07-28 11:04:54 -0400277
278After the call, paint is undefined, and can be safely destructed.
279
280 #Param paint original to move ##
281
282 #Return content of paint ##
283
284#Example
285 SkPaint paint1, paint2;
286 paint1.setColor(SK_ColorRED);
287 paint2 = std::move(paint1);
288 SkDebugf("SK_ColorRED == paint2.getColor()\n", SK_ColorRED == paint2.getColor() ? '=' : '!');
289
290 #StdOut
291 SK_ColorRED == paint2.getColor()
292 ##
293##
294
295##
296
297# ------------------------------------------------------------------------------
298
299#Method bool operator==(const SkPaint& a, const SkPaint& b)
300
Cary Clarkab2621d2018-01-30 10:08:57 -0500301#In Management
302#Line # compares paints for equality ##
Cary Clark8032b982017-07-28 11:04:54 -0400303 Compares a and b, and returns true if a and b are equivalent. May return false
Mike Reed8ad91a92018-01-19 19:09:32 -0500304 if Typeface, Path_Effect, Shader, Mask_Filter, Color_Filter,
Cary Clark8032b982017-07-28 11:04:54 -0400305 Draw_Looper, or Image_Filter have identical contents but different pointers.
306
307 #Param a Paint to compare ##
308 #Param b Paint to compare ##
309
310 #Return true if Paint pair are equivalent ##
311
312 #Example
313 SkPaint paint1, paint2;
314 paint1.setColor(SK_ColorRED);
315 paint2.setColor(0xFFFF0000);
316 SkDebugf("paint1 %c= paint2\n", paint1 == paint2 ? '=' : '!');
317 float intervals[] = { 5, 5 };
318 paint1.setPathEffect(SkDashPathEffect::Make(intervals, 2, 2.5f));
319 paint2.setPathEffect(SkDashPathEffect::Make(intervals, 2, 2.5f));
320 SkDebugf("paint1 %c= paint2\n", paint1 == paint2 ? '=' : '!');
321
322 #StdOut
323 paint1 == paint2
324 paint1 != paint2
325 ##
326 ##
Cary Clark06c20f32018-03-20 15:53:27 -0400327#SeeAlso operator!=(const SkPaint& a, const SkPaint& b)
Cary Clark8032b982017-07-28 11:04:54 -0400328##
329
330# ------------------------------------------------------------------------------
331
332#Method bool operator!=(const SkPaint& a, const SkPaint& b)
333
Cary Clarkab2621d2018-01-30 10:08:57 -0500334#In Management
335#Line # compares paints for inequality ##
Cary Clark8032b982017-07-28 11:04:54 -0400336 Compares a and b, and returns true if a and b are not equivalent. May return true
Mike Reed8ad91a92018-01-19 19:09:32 -0500337 if Typeface, Path_Effect, Shader, Mask_Filter, Color_Filter,
Cary Clark8032b982017-07-28 11:04:54 -0400338 Draw_Looper, or Image_Filter have identical contents but different pointers.
339
340 #Param a Paint to compare ##
341 #Param b Paint to compare ##
342
343 #Return true if Paint pair are not equivalent ##
344
345#Example
346 SkPaint paint1, paint2;
347 paint1.setColor(SK_ColorRED);
348 paint2.setColor(0xFFFF0000);
349 SkDebugf("paint1 %c= paint2\n", paint1 == paint2 ? '=' : '!');
350 SkDebugf("paint1 %c= paint2\n", paint1 != paint2 ? '!' : '=');
351
352 #StdOut
353 paint1 == paint2
354 paint1 == paint2
355 ##
356##
Cary Clark06c20f32018-03-20 15:53:27 -0400357#SeeAlso operator==(const SkPaint& a, const SkPaint& b)
Cary Clark8032b982017-07-28 11:04:54 -0400358##
359
360# ------------------------------------------------------------------------------
361
362#Method uint32_t getHash() const
363
Cary Clarkab2621d2018-01-30 10:08:57 -0500364#In Management
365#Line # returns a shallow hash for equality checks ##
Cary Clark8032b982017-07-28 11:04:54 -0400366Returns a hash generated from Paint values and pointers.
367Identical hashes guarantee that the paints are
368equivalent, but differing hashes do not guarantee that the paints have differing
369contents.
370
371If operator==(const SkPaint& a, const SkPaint& b) returns true for two paints,
372their hashes are also equal.
373
374The hash returned is platform and implementation specific.
375
376#Return a shallow hash ##
377
378#Example
379 SkPaint paint1, paint2;
380 paint1.setColor(SK_ColorRED);
381 paint2.setColor(0xFFFF0000);
382 SkDebugf("paint1 %c= paint2\n", paint1 == paint2 ? '=' : '!');
383 SkDebugf("paint1.getHash() %c= paint2.getHash()\n",
384 paint1.getHash() == paint2.getHash() ? '=' : '!');
385
386 #StdOut
387 paint1 == paint2
388 paint1.getHash() == paint2.getHash()
389 ##
390##
391
392##
393
Cary Clark08895c42018-02-01 09:37:32 -0500394#Subtopic Management ##
Cary Clark8032b982017-07-28 11:04:54 -0400395
396# ------------------------------------------------------------------------------
Cary Clark08895c42018-02-01 09:37:32 -0500397#Subtopic Hinting
398#Line # glyph outline adjustment ##
Cary Clark8032b982017-07-28 11:04:54 -0400399
400#Enum Hinting
Cary Clark08895c42018-02-01 09:37:32 -0500401#Line # level of glyph outline adjustment ##
Cary Clark8032b982017-07-28 11:04:54 -0400402
403#Code
404 enum Hinting {
405 kNo_Hinting = 0,
406 kSlight_Hinting = 1,
407 kNormal_Hinting = 2,
Cary Clarkbad5ad72017-08-03 17:14:08 -0400408 kFull_Hinting = 3,
Cary Clark8032b982017-07-28 11:04:54 -0400409 };
410##
411
412Hinting adjusts the glyph outlines so that the shape provides a uniform
413look at a given point size on font engines that support it. Hinting may have a
414muted effect or no effect at all depending on the platform.
415
416The four levels roughly control corresponding features on platforms that use FreeType
417as the Font_Engine.
418
419#Const kNo_Hinting 0
Cary Clark682c58d2018-05-16 07:07:07 -0400420#Line # glyph outlines unchanged ##
Cary Clark8032b982017-07-28 11:04:54 -0400421 Leaves glyph outlines unchanged from their native representation.
422 With FreeType, this is equivalent to the FT_LOAD_NO_HINTING
423 bit-field constant supplied to FT_Load_Glyph, which indicates that the vector
424 outline being loaded should not be fitted to the pixel grid but simply scaled
425 to 26.6 fractional pixels.
426##
427#Const kSlight_Hinting 1
Cary Clark682c58d2018-05-16 07:07:07 -0400428#Line # minimal modification to improve constrast ##
Cary Clark8032b982017-07-28 11:04:54 -0400429 Modifies glyph outlines minimally to improve constrast.
430 With FreeType, this is equivalent in spirit to the
Herb Derbyfcac00f2018-05-01 11:57:56 -0400431 FT_LOAD_TARGET_LIGHT value supplied to FT_Load_Glyph. It chooses a
Cary Clark8032b982017-07-28 11:04:54 -0400432 lighter hinting algorithm for non-monochrome modes.
Cary Clarkce101242017-09-01 15:51:02 -0400433 Generated Glyphs may be fuzzy but better resemble their original shape.
Cary Clark8032b982017-07-28 11:04:54 -0400434##
435#Const kNormal_Hinting 2
Cary Clark682c58d2018-05-16 07:07:07 -0400436#Line # glyph outlines modified to improve constrast ##
Cary Clark8032b982017-07-28 11:04:54 -0400437 Modifies glyph outlines to improve constrast. This is the default.
Cary Clark6fc50412017-09-21 12:31:06 -0400438 With FreeType, this supplies FT_LOAD_TARGET_NORMAL to FT_Load_Glyph,
Herb Derbyfcac00f2018-05-01 11:57:56 -0400439 choosing the default hinting algorithm, which is optimized for standard
440 gray-level rendering.
Cary Clark8032b982017-07-28 11:04:54 -0400441##
442#Const kFull_Hinting 3
Cary Clark682c58d2018-05-16 07:07:07 -0400443#Line # modifies glyph outlines for maxiumum constrast ##
Cary Clark6fc50412017-09-21 12:31:06 -0400444 Modifies glyph outlines for maxiumum constrast. With FreeType, this selects
Herb Derbyfcac00f2018-05-01 11:57:56 -0400445 FT_LOAD_TARGET_LCD or FT_LOAD_TARGET_LCD_V if kLCDRenderText_Flag is set.
446 FT_LOAD_TARGET_LCD is a variant of FT_LOAD_TARGET_NORMAL optimized for
447 horizontally decimated LCD displays; FT_LOAD_TARGET_LCD_V is a
Cary Clark8032b982017-07-28 11:04:54 -0400448 variant of FT_LOAD_TARGET_NORMAL optimized for vertically decimated LCD displays.
449##
450
Cary Clark4855f782018-02-06 09:41:53 -0500451#Bug 915
Cary Clark8032b982017-07-28 11:04:54 -0400452On OS_X and iOS, hinting controls whether Core_Graphics dilates the font outlines
453to account for LCD text. No hinting uses Core_Text gray scale output.
454Normal hinting uses Core_Text LCD output. If kLCDRenderText_Flag is clear,
455the LCD output is reduced to a single grayscale channel.
Cary Clark8032b982017-07-28 11:04:54 -0400456
457On Windows with DirectWrite, Hinting has no effect.
458
459Hinting defaults to kNormal_Hinting.
460Set SkPaintDefaults_Hinting at compile time to change the default setting.
461
462#ToDo add an illustration? linux running GM:typefacerendering is best for this
463 the hinting variations are every other character horizontally
464#ToDo ##
465
466#Enum ##
467
468#Method Hinting getHinting() const
469
Cary Clarkab2621d2018-01-30 10:08:57 -0500470#In Hinting
471#Line # returns Hinting, glyph outline adjustment level ##
Cary Clark8032b982017-07-28 11:04:54 -0400472 Returns level of glyph outline adjustment.
473
474 #Return one of: kNo_Hinting, kSlight_Hinting, kNormal_Hinting, kFull_Hinting ##
475
476 #Example
477 SkPaint paint;
478 SkDebugf("SkPaint::kNormal_Hinting %c= paint.getHinting()\n",
479 SkPaint::kNormal_Hinting == paint.getHinting() ? '=' : ':');
480
481 #StdOut
482 SkPaint::kNormal_Hinting == paint.getHinting()
483 ##
484 ##
485##
486
487#Method void setHinting(Hinting hintingLevel)
488
Cary Clarkab2621d2018-01-30 10:08:57 -0500489#In Hinting
490#Line # sets Hinting, glyph outline adjustment level ##
Cary Clark8032b982017-07-28 11:04:54 -0400491 Sets level of glyph outline adjustment.
492 Does not check for valid values of hintingLevel.
493
494 #Table
495 #Legend
496 # Hinting # value # effect on generated glyph outlines ##
497 ##
498 # kNo_Hinting # 0 # leaves glyph outlines unchanged from their native representation ##
Cary Clarkce101242017-09-01 15:51:02 -0400499 # kSlight_Hinting # 1 # modifies glyph outlines minimally to improve contrast ##
500 # kNormal_Hinting # 2 # modifies glyph outlines to improve contrast ##
Herb Derbyfcac00f2018-05-01 11:57:56 -0400501 # kFull_Hinting # 3 # modifies glyph outlines for maximum contrast ##
Cary Clark8032b982017-07-28 11:04:54 -0400502 ##
503
504 #Param hintingLevel one of: kNo_Hinting, kSlight_Hinting, kNormal_Hinting, kFull_Hinting ##
505
506 #Example
507 SkPaint paint1, paint2;
508 paint2.setHinting(SkPaint::kNormal_Hinting);
509 SkDebugf("paint1 %c= paint2\n", paint1 == paint2 ? '=' : ':');
510
511 #StdOut
512 paint1 == paint2
513 ##
514 ##
515##
516
Cary Clark08895c42018-02-01 09:37:32 -0500517#Subtopic Hinting ##
Cary Clark8032b982017-07-28 11:04:54 -0400518# ------------------------------------------------------------------------------
Cary Clark08895c42018-02-01 09:37:32 -0500519#Subtopic Flags
520#Line # attributes represented by single bits ##
Cary Clark8032b982017-07-28 11:04:54 -0400521
522#Enum Flags
Cary Clark08895c42018-02-01 09:37:32 -0500523#Line # values described by bits and masks ##
Cary Clark8032b982017-07-28 11:04:54 -0400524
525#Code
526 enum Flags {
527 kAntiAlias_Flag = 0x01,
528 kDither_Flag = 0x04,
529 kFakeBoldText_Flag = 0x20,
530 kLinearText_Flag = 0x40,
531 kSubpixelText_Flag = 0x80,
Cary Clark8032b982017-07-28 11:04:54 -0400532 kLCDRenderText_Flag = 0x200,
533 kEmbeddedBitmapText_Flag = 0x400,
534 kAutoHinting_Flag = 0x800,
535 kVerticalText_Flag = 0x1000,
Cary Clark8032b982017-07-28 11:04:54 -0400536
537 kAllFlags = 0xFFFF,
538 };
539
540##
541
542The bit values stored in Flags.
543The default value for Flags, normally zero, can be changed at compile time
544with a custom definition of SkPaintDefaults_Flags.
545All flags can be read and written explicitly; Flags allows manipulating
546multiple settings at once.
547
Herb Derbyfcac00f2018-05-01 11:57:56 -0400548 #Const kAntiAlias_Flag 0x0001
Cary Clarkffb3d682018-05-17 12:17:28 -0400549 #Line # mask for setting Anti_Alias ##
Cary Clark8032b982017-07-28 11:04:54 -0400550 ##
551 #Const kDither_Flag 0x0004
Cary Clark682c58d2018-05-16 07:07:07 -0400552 #Line # mask for setting Dither ##
Cary Clark8032b982017-07-28 11:04:54 -0400553 ##
Cary Clark8032b982017-07-28 11:04:54 -0400554 #Const kFakeBoldText_Flag 0x0020
Cary Clark682c58d2018-05-16 07:07:07 -0400555 #Line # mask for setting Fake_Bold ##
Cary Clark8032b982017-07-28 11:04:54 -0400556 ##
557 #Const kLinearText_Flag 0x0040
Cary Clark682c58d2018-05-16 07:07:07 -0400558 #Line # mask for setting Linear_Text ##
Cary Clark8032b982017-07-28 11:04:54 -0400559 ##
560 #Const kSubpixelText_Flag 0x0080
Cary Clark682c58d2018-05-16 07:07:07 -0400561 #Line # mask for setting Subpixel_Text ##
Cary Clark8032b982017-07-28 11:04:54 -0400562 ##
Cary Clark8032b982017-07-28 11:04:54 -0400563 #Const kLCDRenderText_Flag 0x0200
Cary Clark682c58d2018-05-16 07:07:07 -0400564 #Line # mask for setting LCD_Text ##
Cary Clark8032b982017-07-28 11:04:54 -0400565 ##
566 #Const kEmbeddedBitmapText_Flag 0x0400
Cary Clark682c58d2018-05-16 07:07:07 -0400567 #Line # mask for setting Font_Embedded_Bitmaps ##
Cary Clark8032b982017-07-28 11:04:54 -0400568 ##
569 #Const kAutoHinting_Flag 0x0800
Cary Clark682c58d2018-05-16 07:07:07 -0400570 #Line # mask for setting Automatic_Hinting ##
Cary Clark8032b982017-07-28 11:04:54 -0400571 ##
572 #Const kVerticalText_Flag 0x1000
Cary Clark682c58d2018-05-16 07:07:07 -0400573 #Line # mask for setting Vertical_Text ##
Cary Clark8032b982017-07-28 11:04:54 -0400574 ##
Cary Clark8032b982017-07-28 11:04:54 -0400575 #Const kAllFlags 0xFFFF
Cary Clark682c58d2018-05-16 07:07:07 -0400576 #Line # mask of all Flags ##
Cary Clark8032b982017-07-28 11:04:54 -0400577 mask of all Flags, including private flags and flags reserved for future use
578 ##
579
580Flags default to all flags clear, disabling the associated feature.
581
582#Enum ##
583
584#Enum ReserveFlags
Cary Clark4855f782018-02-06 09:41:53 -0500585#Deprecated soon
Cary Clark8032b982017-07-28 11:04:54 -0400586
Cary Clark4855f782018-02-06 09:41:53 -0500587Only valid for Android framework.
Cary Clark8032b982017-07-28 11:04:54 -0400588
589#Code
590 enum ReserveFlags {
591 kUnderlineText_ReserveFlag = 0x08,
592 kStrikeThruText_ReserveFlag = 0x10,
593 };
594##
595
Cary Clark4855f782018-02-06 09:41:53 -0500596#Const kUnderlineText_ReserveFlag 0x0008
597#Deprecated soon
598##
599#Const kStrikeThruText_ReserveFlag 0x0010
600#Deprecated soon
601##
602##
Cary Clark8032b982017-07-28 11:04:54 -0400603
604#Method uint32_t getFlags() const
605
Cary Clarkab2621d2018-01-30 10:08:57 -0500606#In Flags
607#Line # returns Flags stored in a bit field ##
Cary Clark8032b982017-07-28 11:04:54 -0400608Returns paint settings described by Flags. Each setting uses one
609bit, and can be tested with Flags members.
610
611#Return zero, one, or more bits described by Flags ##
612
613#Example
614 SkPaint paint;
615 paint.setAntiAlias(true);
616 SkDebugf("(SkPaint::kAntiAlias_Flag & paint.getFlags()) %c= 0\n",
617 SkPaint::kAntiAlias_Flag & paint.getFlags() ? '!' : '=');
618
619 #StdOut
620 (SkPaint::kAntiAlias_Flag & paint.getFlags()) != 0
621 ##
622##
623
624##
625
626#Method void setFlags(uint32_t flags)
627
Cary Clarkab2621d2018-01-30 10:08:57 -0500628#In Flags
629#Line # sets multiple Flags in a bit field ##
Cary Clark8032b982017-07-28 11:04:54 -0400630Replaces Flags with flags, the union of the Flags members.
631All Flags members may be cleared, or one or more may be set.
632
633#Param flags union of Flags for Paint ##
634
635#Example
636 SkPaint paint;
637 paint.setFlags((uint32_t) (SkPaint::kAntiAlias_Flag | SkPaint::kDither_Flag));
638 SkDebugf("paint.isAntiAlias()\n", paint.isAntiAlias() ? '!' : '=');
639 SkDebugf("paint.isDither()\n", paint.isDither() ? '!' : '=');
640
641 #StdOut
642 paint.isAntiAlias()
643 paint.isDither()
644 ##
645##
646
647##
648
Cary Clark08895c42018-02-01 09:37:32 -0500649#Subtopic Flags ##
Cary Clark8032b982017-07-28 11:04:54 -0400650# ------------------------------------------------------------------------------
Cary Clarkffb3d682018-05-17 12:17:28 -0400651#Subtopic Anti_Alias
652#Alias Anti_Alias
653#Substitute Anti-alias
654#Alias Anti_Aliased
655#Substitute Anti-aliased
656#Alias Anti_Aliasing
657#Substitute Anti-aliasing
Cary Clark4855f782018-02-06 09:41:53 -0500658#In Related_Function
Cary Clarkab2621d2018-01-30 10:08:57 -0500659#Line # approximating coverage with transparency ##
Cary Clark8032b982017-07-28 11:04:54 -0400660
Cary Clarkffb3d682018-05-17 12:17:28 -0400661Anti_Alias drawing approximates partial pixel coverage with transparency.
Cary Clark8032b982017-07-28 11:04:54 -0400662If kAntiAlias_Flag is clear, pixel centers contained by the shape edge are drawn opaque.
663If kAntiAlias_Flag is set, pixels are drawn with Color_Alpha equal to their coverage.
664
Herb Derbyfcac00f2018-05-01 11:57:56 -0400665The rule for Aliased pixels is inconsistent across platforms. A shape edge
Cary Clark8032b982017-07-28 11:04:54 -0400666passing through the pixel center may, but is not required to, draw the pixel.
667
Cary Clarkce101242017-09-01 15:51:02 -0400668Raster_Engine draws Aliased pixels whose centers are on or to the right of the start of an
Cary Clark8032b982017-07-28 11:04:54 -0400669active Path edge, and whose center is to the left of the end of the active Path edge.
670
671#ToDo add illustration of raster pixels ##
672
Cary Clarkffb3d682018-05-17 12:17:28 -0400673A platform may only support Anti_Aliased drawing. Some GPU-backed platforms use
674Supersampling to Anti_Alias all drawing, and have no mechanism to selectively
Cary Clarkce101242017-09-01 15:51:02 -0400675Alias.
Cary Clark8032b982017-07-28 11:04:54 -0400676
Cary Clarkffb3d682018-05-17 12:17:28 -0400677The amount of coverage computed for Anti_Aliased pixels also varies across platforms.
Cary Clark8032b982017-07-28 11:04:54 -0400678
Cary Clarkffb3d682018-05-17 12:17:28 -0400679Anti_Alias is disabled by default.
680Anti_Alias can be enabled by default by setting SkPaintDefaults_Flags to kAntiAlias_Flag
Cary Clark8032b982017-07-28 11:04:54 -0400681at compile time.
682
Cary Clarkab2621d2018-01-30 10:08:57 -0500683#Example
Cary Clark8032b982017-07-28 11:04:54 -0400684 #Width 512
685 #Description
686 A red line is drawn with transparency on the edges to make it look smoother.
687 A blue line draws only where the pixel centers are contained.
Cary Clarkce101242017-09-01 15:51:02 -0400688 The lines are drawn into Bitmap, then drawn magnified to make the
689 Aliasing easier to see.
Cary Clark8032b982017-07-28 11:04:54 -0400690 ##
691
692 void draw(SkCanvas* canvas) {
693 SkBitmap bitmap;
694 bitmap.allocN32Pixels(50, 50);
695 SkCanvas offscreen(bitmap);
696 SkPaint paint;
697 paint.setStyle(SkPaint::kStroke_Style);
698 paint.setStrokeWidth(10);
699 for (bool antialias : { false, true }) {
700 paint.setColor(antialias ? SK_ColorRED : SK_ColorBLUE);
701 paint.setAntiAlias(antialias);
702 bitmap.eraseColor(0);
703 offscreen.drawLine(5, 5, 15, 30, paint);
704 canvas->drawLine(5, 5, 15, 30, paint);
705 canvas->save();
706 canvas->scale(10, 10);
707 canvas->drawBitmap(bitmap, antialias ? 12 : 0, 0);
708 canvas->restore();
709 canvas->translate(15, 0);
710 }
711 }
Cary Clarkab2621d2018-01-30 10:08:57 -0500712##
Cary Clark8032b982017-07-28 11:04:54 -0400713
714#Method bool isAntiAlias() const
Cary Clark78de7512018-02-07 07:27:09 -0500715#In Anti_alias
Cary Clarkffb3d682018-05-17 12:17:28 -0400716#Line # returns true if Anti_Alias is set ##
Cary Clark8032b982017-07-28 11:04:54 -0400717
718 If true, pixels on the active edges of Path may be drawn with partial transparency.
719
720 Equivalent to getFlags masked with kAntiAlias_Flag.
721
722 #Return kAntiAlias_Flag state ##
723
724 #Example
725 SkPaint paint;
726 SkDebugf("paint.isAntiAlias() %c= !!(paint.getFlags() & SkPaint::kAntiAlias_Flag)\n",
727 paint.isAntiAlias() == !!(paint.getFlags() & SkPaint::kAntiAlias_Flag) ? '=' : '!');
728 paint.setAntiAlias(true);
729 SkDebugf("paint.isAntiAlias() %c= !!(paint.getFlags() & SkPaint::kAntiAlias_Flag)\n",
730 paint.isAntiAlias() == !!(paint.getFlags() & SkPaint::kAntiAlias_Flag) ? '=' : '!');
731
732 #StdOut
733 paint.isAntiAlias() == !!(paint.getFlags() & SkPaint::kAntiAlias_Flag)
734 paint.isAntiAlias() == !!(paint.getFlags() & SkPaint::kAntiAlias_Flag)
735 ##
736 ##
737##
738
739#Method void setAntiAlias(bool aa)
740
Cary Clark78de7512018-02-07 07:27:09 -0500741#In Anti_alias
Cary Clarkffb3d682018-05-17 12:17:28 -0400742#Line # sets or clears Anti_Alias ##
Cary Clark8032b982017-07-28 11:04:54 -0400743 Requests, but does not require, that Path edge pixels draw opaque or with
744 partial transparency.
745
746 Sets kAntiAlias_Flag if aa is true.
747 Clears kAntiAlias_Flag if aa is false.
748
749 #Param aa setting for kAntiAlias_Flag ##
750
751 #Example
752 SkPaint paint1, paint2;
753 paint1.setAntiAlias(true);
754 paint2.setFlags(paint2.getFlags() | SkPaint::kAntiAlias_Flag);
755 SkDebugf("paint1 %c= paint2\n", paint1 == paint2 ? '=' : '!');
756
757 #StdOut
758 paint1 == paint2
759 ##
760 ##
761
762##
763
Cary Clarkffb3d682018-05-17 12:17:28 -0400764#Subtopic Anti_Alias ##
Cary Clark8032b982017-07-28 11:04:54 -0400765# ------------------------------------------------------------------------------
Cary Clark08895c42018-02-01 09:37:32 -0500766#Subtopic Dither
767#Line # distributing color error ##
Cary Clark8032b982017-07-28 11:04:54 -0400768
Herb Derbyfcac00f2018-05-01 11:57:56 -0400769Dither increases fidelity by adjusting the color of adjacent pixels.
Cary Clark8032b982017-07-28 11:04:54 -0400770This can help to smooth color transitions and reducing banding in gradients.
771Dithering lessens visible banding from kRGB_565_SkColorType
Herb Derbyfcac00f2018-05-01 11:57:56 -0400772and kRGBA_8888_SkColorType gradients,
Cary Clark8032b982017-07-28 11:04:54 -0400773and improves rendering into a kRGB_565_SkColorType Surface.
774
775Dithering is always enabled for linear gradients drawing into
776kRGB_565_SkColorType Surface and kRGBA_8888_SkColorType Surface.
777Dither cannot be enabled for kAlpha_8_SkColorType Surface and
778kRGBA_F16_SkColorType Surface.
779
780Dither is disabled by default.
781Dither can be enabled by default by setting SkPaintDefaults_Flags to kDither_Flag
782at compile time.
783
784Some platform implementations may ignore dithering. Set
785
Cary Clark2d4bf5f2018-04-16 08:37:38 -0400786#Formula
787SK_IGNORE_GPU_DITHER
788##
Cary Clark8032b982017-07-28 11:04:54 -0400789
790to ignore Dither on GPU_Surface.
791
792#Example
Herb Derbyfcac00f2018-05-01 11:57:56 -0400793#Description
Cary Clark8032b982017-07-28 11:04:54 -0400794Dithering in the bottom half more closely approximates the requested color by
795alternating nearby colors from pixel to pixel.
796##
797void draw(SkCanvas* canvas) {
798 SkBitmap bm16;
799 bm16.allocPixels(SkImageInfo::Make(32, 32, kRGB_565_SkColorType, kOpaque_SkAlphaType));
800 SkCanvas c16(bm16);
801 SkPaint colorPaint;
802 for (auto dither : { false, true } ) {
803 colorPaint.setDither(dither);
804 for (auto colors : { 0xFF333333, 0xFF666666, 0xFF999999, 0xFFCCCCCC } ) {
805 for (auto mask : { 0xFFFF0000, 0xFF00FF00, 0xFF0000FF, 0xFFFFFFFF } ) {
806 colorPaint.setColor(colors & mask);
807 c16.drawRect({0, 0, 8, 4}, colorPaint);
808 c16.translate(8, 0);
809 }
810 c16.translate(-32, 4);
811 }
812 }
813 canvas->scale(8, 8);
814 canvas->drawBitmap(bm16, 0, 0);
815}
816##
817
818#Example
Herb Derbyfcac00f2018-05-01 11:57:56 -0400819#Description
Cary Clark8032b982017-07-28 11:04:54 -0400820Dithering introduces subtle adjustments to color to smooth gradients.
821Drawing the gradient repeatedly with SkBlendMode::kPlus exaggerates the
822dither, making it easier to see.
823##
824void draw(SkCanvas* canvas) {
825 canvas->clear(0);
826 SkBitmap bm32;
827 bm32.allocPixels(SkImageInfo::Make(20, 10, kN32_SkColorType, kPremul_SkAlphaType));
828 SkCanvas c32(bm32);
829 SkPoint points[] = {{0, 0}, {20, 0}};
830 SkColor colors[] = {0xFF334455, 0xFF662211 };
831 SkPaint paint;
832 paint.setShader(SkGradientShader::MakeLinear(
833 points, colors, nullptr, SK_ARRAY_COUNT(colors),
834 SkShader::kClamp_TileMode, 0, nullptr));
835 paint.setDither(true);
836 c32.drawPaint(paint);
837 canvas->scale(12, 12);
838 canvas->drawBitmap(bm32, 0, 0);
839 paint.setBlendMode(SkBlendMode::kPlus);
840 canvas->drawBitmap(bm32, 0, 11, &paint);
841 canvas->drawBitmap(bm32, 0, 11, &paint);
842 canvas->drawBitmap(bm32, 0, 11, &paint);
843}
844##
845
846#Method bool isDither() const
847
Cary Clarkab2621d2018-01-30 10:08:57 -0500848#In Dither
849#Line # returns true if Dither is set ##
Cary Clark8032b982017-07-28 11:04:54 -0400850 If true, color error may be distributed to smooth color transition.
Herb Derbyfcac00f2018-05-01 11:57:56 -0400851
Cary Clark8032b982017-07-28 11:04:54 -0400852 Equivalent to getFlags masked with kDither_Flag.
853
854 #Return kDither_Flag state ##
855
856 #Example
857 SkPaint paint;
858 SkDebugf("paint.isDither() %c= !!(paint.getFlags() & SkPaint::kDither_Flag)\n",
859 paint.isDither() == !!(paint.getFlags() & SkPaint::kDither_Flag) ? '=' : '!');
860 paint.setDither(true);
861 SkDebugf("paint.isDither() %c= !!(paint.getFlags() & SkPaint::kDither_Flag)\n",
862 paint.isDither() == !!(paint.getFlags() & SkPaint::kDither_Flag) ? '=' : '!');
863
864 #StdOut
865 paint.isDither() == !!(paint.getFlags() & SkPaint::kDither_Flag)
866 paint.isDither() == !!(paint.getFlags() & SkPaint::kDither_Flag)
867 ##
868 ##
869
870##
871
872#Method void setDither(bool dither)
873
Cary Clarkab2621d2018-01-30 10:08:57 -0500874#In Dither
875#Line # sets or clears Dither ##
Cary Clark8032b982017-07-28 11:04:54 -0400876 Requests, but does not require, to distribute color error.
877
878 Sets kDither_Flag if dither is true.
879 Clears kDither_Flag if dither is false.
880
881 #Param dither setting for kDither_Flag ##
882
883 #Example
884 SkPaint paint1, paint2;
885 paint1.setDither(true);
886 paint2.setFlags(paint2.getFlags() | SkPaint::kDither_Flag);
887 SkDebugf("paint1 %c= paint2\n", paint1 == paint2 ? '=' : '!');
888
889 #StdOut
890 paint1 == paint2
891 ##
892 ##
893
894 #SeeAlso kRGB_565_SkColorType
895
896##
897
Cary Clarkffb3d682018-05-17 12:17:28 -0400898#SeeAlso Gradient kRGB_565_SkColorType
Cary Clark8032b982017-07-28 11:04:54 -0400899
Cary Clark08895c42018-02-01 09:37:32 -0500900#Subtopic Dither ##
Cary Clark8032b982017-07-28 11:04:54 -0400901# ------------------------------------------------------------------------------
Cary Clark08895c42018-02-01 09:37:32 -0500902#Subtopic Device_Text
903#Line # increase precision of glyph position ##
Cary Clark8032b982017-07-28 11:04:54 -0400904
905LCD_Text and Subpixel_Text increase the precision of glyph position.
906
Cary Clarkffb3d682018-05-17 12:17:28 -0400907When set, Flags kLCDRenderText_Flag takes advantage of the organization of RGB stripes that
Cary Clark8032b982017-07-28 11:04:54 -0400908create a color, and relies
Cary Clarkce101242017-09-01 15:51:02 -0400909on the small size of the stripe and visual perception to make the color fringing imperceptible.
Cary Clark8032b982017-07-28 11:04:54 -0400910LCD_Text can be enabled on devices that orient stripes horizontally or vertically, and that order
Cary Clarkffb3d682018-05-17 12:17:28 -0400911the color components as RGB or BGR.
Cary Clark8032b982017-07-28 11:04:54 -0400912
Herb Derbyfcac00f2018-05-01 11:57:56 -0400913Flags kSubpixelText_Flag uses the pixel transparency to represent a fractional offset.
Cary Clark8032b982017-07-28 11:04:54 -0400914As the opaqueness
915of the color increases, the edge of the glyph appears to move towards the outside of the pixel.
916
917Either or both techniques can be enabled.
918kLCDRenderText_Flag and kSubpixelText_Flag are clear by default.
Herb Derbyfcac00f2018-05-01 11:57:56 -0400919LCD_Text or Subpixel_Text can be enabled by default by setting SkPaintDefaults_Flags to
Cary Clark8032b982017-07-28 11:04:54 -0400920kLCDRenderText_Flag or kSubpixelText_Flag (or both) at compile time.
921
922#Example
923 #Description
924 Four commas are drawn normally and with combinations of LCD_Text and Subpixel_Text.
Cary Clarkce101242017-09-01 15:51:02 -0400925 When Subpixel_Text is disabled, the comma Glyphs are identical, but not evenly spaced.
926 When Subpixel_Text is enabled, the comma Glyphs are unique, but appear evenly spaced.
Cary Clark8032b982017-07-28 11:04:54 -0400927 ##
928
929 SkBitmap bitmap;
930 bitmap.allocN32Pixels(24, 33);
931 SkCanvas offscreen(bitmap);
932 offscreen.clear(SK_ColorWHITE);
933 SkPaint paint;
934 paint.setAntiAlias(true);
935 paint.setTextSize(20);
936 for (bool lcd : { false, true }) {
937 paint.setLCDRenderText(lcd);
938 for (bool subpixel : { false, true }) {
939 paint.setSubpixelText(subpixel);
940 offscreen.drawString(",,,,", 0, 4, paint);
941 offscreen.translate(0, 7);
942 }
943 }
944 canvas->drawBitmap(bitmap, 4, 12);
945 canvas->scale(9, 9);
946 canvas->drawBitmap(bitmap, 4, -1);
947##
Cary Clark08895c42018-02-01 09:37:32 -0500948#Subtopic Device_Text ##
Cary Clark8032b982017-07-28 11:04:54 -0400949
950#Subtopic Linear_Text
Cary Clark08895c42018-02-01 09:37:32 -0500951#Alias Linear_Text
952#Line # selects text rendering as Glyph or Path ##
Cary Clark8032b982017-07-28 11:04:54 -0400953
954Linear_Text selects whether text is rendered as a Glyph or as a Path.
955If kLinearText_Flag is set, it has the same effect as setting Hinting to kNormal_Hinting.
Cary Clarkd0530ba2017-09-14 11:25:39 -0400956If kLinearText_Flag is clear, it is the same as setting Hinting to kNo_Hinting.
Cary Clark8032b982017-07-28 11:04:54 -0400957
958#Method bool isLinearText() const
959
Cary Clark08895c42018-02-01 09:37:32 -0500960#Line # returns true if text is converted to Path ##
Cary Clarkab2621d2018-01-30 10:08:57 -0500961#In Linear_Text
Cary Clark8032b982017-07-28 11:04:54 -0400962 If true, text is converted to Path before drawing and measuring.
963
964 Equivalent to getFlags masked with kLinearText_Flag.
965
966 #Return kLinearText_Flag state ##
967
968 #Example
969 #Height 128
970 void draw(SkCanvas* canvas) {
971 SkPaint paint;
972 paint.setAntiAlias(true);
973 const char testStr[] = "xxxx xxxx";
974 for (auto linearText : { false, true } ) {
975 paint.setLinearText(linearText);
976 paint.setTextSize(24);
977 canvas->drawString(paint.isLinearText() ? "linear" : "hinted", 128, 30, paint);
978 for (SkScalar textSize = 8; textSize < 30; textSize *= 1.22f) {
979 paint.setTextSize(textSize);
980 canvas->translate(0, textSize);
981 canvas->drawString(testStr, 10, 0, paint);
982 }
983 }
984 }
985 ##
986
987 #SeeAlso setLinearText Hinting
988##
989
990#Method void setLinearText(bool linearText)
991
Cary Clark08895c42018-02-01 09:37:32 -0500992#Line # converts to Path before draw or measure ##
Cary Clarkab2621d2018-01-30 10:08:57 -0500993#In Linear_Text
Cary Clark8032b982017-07-28 11:04:54 -0400994 If true, text is converted to Path before drawing and measuring.
995 By default, kLinearText_Flag is clear.
996
997 Sets kLinearText_Flag if linearText is true.
998 Clears kLinearText_Flag if linearText is false.
999
1000 #Param linearText setting for kLinearText_Flag ##
1001
1002 #Example
1003 #Height 128
1004 void draw(SkCanvas* canvas) {
1005 SkPaint paint;
1006 paint.setAntiAlias(true);
1007 const char testStr[] = "abcd efgh";
1008 for (int textSize : { 12, 24 } ) {
1009 paint.setTextSize(textSize);
1010 for (auto linearText : { false, true } ) {
1011 paint.setLinearText(linearText);
1012 SkString width;
1013 width.appendScalar(paint.measureText(testStr, SK_ARRAY_COUNT(testStr), nullptr));
1014 canvas->translate(0, textSize + 4);
1015 canvas->drawString(testStr, 10, 0, paint);
1016 canvas->drawString(width, 128, 0, paint);
1017 }
1018 }
Herb Derbyfcac00f2018-05-01 11:57:56 -04001019 }
Cary Clark8032b982017-07-28 11:04:54 -04001020 ##
1021
1022 #SeeAlso isLinearText Hinting
1023##
1024
Cary Clark08895c42018-02-01 09:37:32 -05001025#Subtopic Linear_Text ##
Cary Clark8032b982017-07-28 11:04:54 -04001026
1027#Subtopic Subpixel_Text
Cary Clark08895c42018-02-01 09:37:32 -05001028#Alias Subpixel_Text
1029#Line # uses pixel transparency to represent fractional offset ##
Cary Clark8032b982017-07-28 11:04:54 -04001030
Herb Derbyfcac00f2018-05-01 11:57:56 -04001031Flags kSubpixelText_Flag uses the pixel transparency to represent a fractional offset.
Cary Clark8032b982017-07-28 11:04:54 -04001032As the opaqueness
1033of the color increases, the edge of the glyph appears to move towards the outside of the pixel.
1034
1035#Method bool isSubpixelText() const
Herb Derbyfcac00f2018-05-01 11:57:56 -04001036
Cary Clarkab2621d2018-01-30 10:08:57 -05001037#In Subpixel_Text
1038#Line # returns true if Subpixel_Text is set ##
Cary Clarkce101242017-09-01 15:51:02 -04001039 If true, Glyphs at different sub-pixel positions may differ on pixel edge coverage.
Cary Clark8032b982017-07-28 11:04:54 -04001040
1041 Equivalent to getFlags masked with kSubpixelText_Flag.
1042
1043 #Return kSubpixelText_Flag state ##
1044
1045 #Example
1046SkPaint paint;
1047SkDebugf("paint.isSubpixelText() %c= !!(paint.getFlags() & SkPaint::kSubpixelText_Flag)\n",
1048 paint.isSubpixelText() == !!(paint.getFlags() & SkPaint::kSubpixelText_Flag) ? '=' : '!');
1049paint.setSubpixelText(true);
1050SkDebugf("paint.isSubpixelText() %c= !!(paint.getFlags() & SkPaint::kSubpixelText_Flag)\n",
1051 paint.isSubpixelText() == !!(paint.getFlags() & SkPaint::kSubpixelText_Flag) ? '=' : '!');
1052
1053 #StdOut
1054 paint.isSubpixelText() == !!(paint.getFlags() & SkPaint::kSubpixelText_Flag)
1055 paint.isSubpixelText() == !!(paint.getFlags() & SkPaint::kSubpixelText_Flag)
1056 ##
1057 ##
1058
1059##
1060
1061#Method void setSubpixelText(bool subpixelText)
1062
Cary Clarkab2621d2018-01-30 10:08:57 -05001063#In Subpixel_Text
1064#Line # sets or clears Subpixel_Text ##
Cary Clarkce101242017-09-01 15:51:02 -04001065 Requests, but does not require, that Glyphs respect sub-pixel positioning.
Cary Clark8032b982017-07-28 11:04:54 -04001066
1067 Sets kSubpixelText_Flag if subpixelText is true.
1068 Clears kSubpixelText_Flag if subpixelText is false.
1069
1070 #Param subpixelText setting for kSubpixelText_Flag ##
1071
1072 #Example
1073 SkPaint paint1, paint2;
1074 paint1.setSubpixelText(true);
1075 paint2.setFlags(paint2.getFlags() | SkPaint::kSubpixelText_Flag);
1076 SkDebugf("paint1 %c= paint2\n", paint1 == paint2 ? '=' : '!');
1077
1078 #StdOut
1079 paint1 == paint2
1080 ##
1081 ##
1082
1083##
1084
Cary Clark08895c42018-02-01 09:37:32 -05001085#Subtopic Subpixel_Text ##
Cary Clark8032b982017-07-28 11:04:54 -04001086
1087#Subtopic LCD_Text
Cary Clarkc68ba1d2018-02-20 10:35:29 -05001088#Substitute LCD text
Cary Clarkffb3d682018-05-17 12:17:28 -04001089#Line # text relying on the order of RGB stripes ##
Cary Clark8032b982017-07-28 11:04:54 -04001090#Alias LCD_Text # makes this a top level name, since it is under subtopic Device_Text
1091
Cary Clarkffb3d682018-05-17 12:17:28 -04001092When set, Flags kLCDRenderText_Flag takes advantage of the organization of RGB stripes that
Cary Clark8032b982017-07-28 11:04:54 -04001093create a color, and relies
Cary Clarkce101242017-09-01 15:51:02 -04001094on the small size of the stripe and visual perception to make the color fringing imperceptible.
Cary Clark8032b982017-07-28 11:04:54 -04001095LCD_Text can be enabled on devices that orient stripes horizontally or vertically, and that order
Cary Clarkffb3d682018-05-17 12:17:28 -04001096the color components as RGB or BGR.
Cary Clark8032b982017-07-28 11:04:54 -04001097
1098#Method bool isLCDRenderText() const
1099
Cary Clarkab2621d2018-01-30 10:08:57 -05001100#In LCD_Text
1101#Line # returns true if LCD_Text is set ##
Cary Clarkce101242017-09-01 15:51:02 -04001102 If true, Glyphs may use LCD striping to improve glyph edges.
Cary Clark8032b982017-07-28 11:04:54 -04001103
1104 Returns true if Flags kLCDRenderText_Flag is set.
1105
1106 #Return kLCDRenderText_Flag state ##
1107
1108 #Example
1109SkPaint paint;
1110SkDebugf("paint.isLCDRenderText() %c= !!(paint.getFlags() & SkPaint::kLCDRenderText_Flag)\n",
1111 paint.isLCDRenderText() == !!(paint.getFlags() & SkPaint::kLCDRenderText_Flag) ? '=' : '!');
1112paint.setLCDRenderText(true);
1113SkDebugf("paint.isLCDRenderText() %c= !!(paint.getFlags() & SkPaint::kLCDRenderText_Flag)\n",
1114 paint.isLCDRenderText() == !!(paint.getFlags() & SkPaint::kLCDRenderText_Flag) ? '=' : '!');
1115
1116 #StdOut
1117 paint.isLCDRenderText() == !!(paint.getFlags() & SkPaint::kLCDRenderText_Flag)
1118 paint.isLCDRenderText() == !!(paint.getFlags() & SkPaint::kLCDRenderText_Flag)
1119 ##
1120 ##
1121
1122##
1123
1124#Method void setLCDRenderText(bool lcdText)
1125
Cary Clarkab2621d2018-01-30 10:08:57 -05001126#In LCD_Text
1127#Line # sets or clears LCD_Text ##
Cary Clarkce101242017-09-01 15:51:02 -04001128 Requests, but does not require, that Glyphs use LCD striping for glyph edges.
Cary Clark8032b982017-07-28 11:04:54 -04001129
1130 Sets kLCDRenderText_Flag if lcdText is true.
1131 Clears kLCDRenderText_Flag if lcdText is false.
1132
1133 #Param lcdText setting for kLCDRenderText_Flag ##
1134
1135 #Example
1136 SkPaint paint1, paint2;
1137 paint1.setLCDRenderText(true);
1138 paint2.setFlags(paint2.getFlags() | SkPaint::kLCDRenderText_Flag);
1139 SkDebugf("paint1 %c= paint2\n", paint1 == paint2 ? '=' : '!');
1140
1141 #StdOut
1142 paint1 == paint2
1143 ##
1144 ##
1145
1146
1147##
1148
Cary Clark08895c42018-02-01 09:37:32 -05001149#Subtopic LCD_Text ##
Cary Clark8032b982017-07-28 11:04:54 -04001150
Cary Clark8032b982017-07-28 11:04:54 -04001151# ------------------------------------------------------------------------------
Cary Clark08895c42018-02-01 09:37:32 -05001152#Subtopic Font_Embedded_Bitmaps
1153#Line # custom sized bitmap Glyphs ##
Cary Clark8032b982017-07-28 11:04:54 -04001154#Alias Font_Embedded_Bitmaps # long-winded enough, alias so I don't type Paint_Font_...
1155
Cary Clarkce101242017-09-01 15:51:02 -04001156Font_Embedded_Bitmaps allows selecting custom sized bitmap Glyphs.
Cary Clark8032b982017-07-28 11:04:54 -04001157Flags kEmbeddedBitmapText_Flag when set chooses an embedded bitmap glyph over an outline contained
Herb Derbyfcac00f2018-05-01 11:57:56 -04001158in a font if the platform supports this option.
Cary Clark8032b982017-07-28 11:04:54 -04001159
1160FreeType selects the bitmap glyph if available when kEmbeddedBitmapText_Flag is set, and selects
1161the outline glyph if kEmbeddedBitmapText_Flag is clear.
1162Windows may select the bitmap glyph but is not required to do so.
1163OS_X and iOS do not support this option.
1164
1165Font_Embedded_Bitmaps is disabled by default.
1166Font_Embedded_Bitmaps can be enabled by default by setting SkPaintDefaults_Flags to
1167kEmbeddedBitmapText_Flag at compile time.
1168
1169#Example
1170 #ToDo image will only output on Ubuntu ... how to handle that in fiddle? ##
1171 #Platform !fiddle
1172 #Description
Cary Clarkce101242017-09-01 15:51:02 -04001173 The "hintgasp" TrueType font in the Skia resources/fonts directory
1174 includes an embedded bitmap Glyph at odd font sizes. This example works
1175 on platforms that use FreeType as their Font_Engine.
1176 Windows may, but is not required to, return a bitmap glyph if
1177 kEmbeddedBitmapText_Flag is set.
Cary Clark8032b982017-07-28 11:04:54 -04001178 ##
1179 #Image embeddedbitmap.png
1180
1181 SkBitmap bitmap;
1182 bitmap.allocN32Pixels(30, 15);
1183 bitmap.eraseColor(0);
1184 SkCanvas offscreen(bitmap);
1185 SkPaint paint;
1186 paint.setAntiAlias(true);
1187 paint.setTextSize(13);
Hal Canary53e5e7d2017-12-08 14:25:14 -05001188 paint.setTypeface(MakeResourceAsTypeface("fonts/hintgasp.ttf"));
Cary Clark8032b982017-07-28 11:04:54 -04001189 for (bool embedded : { false, true}) {
1190 paint.setEmbeddedBitmapText(embedded);
1191 offscreen.drawString("A", embedded ? 5 : 15, 15, paint);
1192 }
1193 canvas->drawBitmap(bitmap, 0, 0);
1194 canvas->scale(10, 10);
1195 canvas->drawBitmap(bitmap, -2, 1);
1196##
1197
1198#Method bool isEmbeddedBitmapText() const
1199
Cary Clarkab2621d2018-01-30 10:08:57 -05001200#In Font_Embedded_Bitmaps
1201#Line # returns true if Font_Embedded_Bitmaps is set ##
Cary Clarkce101242017-09-01 15:51:02 -04001202 If true, Font_Engine may return Glyphs from font bitmaps instead of from outlines.
Cary Clark8032b982017-07-28 11:04:54 -04001203
1204 Equivalent to getFlags masked with kEmbeddedBitmapText_Flag.
1205
1206 #Return kEmbeddedBitmapText_Flag state ##
1207
1208 #Example
1209 SkPaint paint;
1210 SkDebugf("paint.isEmbeddedBitmapText() %c="
1211 " !!(paint.getFlags() & SkPaint::kEmbeddedBitmapText_Flag)\n",
1212 paint.isEmbeddedBitmapText() ==
1213 !!(paint.getFlags() & SkPaint::kEmbeddedBitmapText_Flag) ? '=' : '!');
1214 paint.setEmbeddedBitmapText(true);
1215 SkDebugf("paint.isEmbeddedBitmapText() %c="
1216 " !!(paint.getFlags() & SkPaint::kEmbeddedBitmapText_Flag)\n",
1217 paint.isEmbeddedBitmapText() ==
1218 !!(paint.getFlags() & SkPaint::kEmbeddedBitmapText_Flag) ? '=' : '!');
1219
1220 #StdOut
1221 paint.isEmbeddedBitmapText() == !!(paint.getFlags() & SkPaint::kEmbeddedBitmapText_Flag)
1222 paint.isEmbeddedBitmapText() == !!(paint.getFlags() & SkPaint::kEmbeddedBitmapText_Flag)
1223 ##
1224 ##
1225
1226##
1227
1228#Method void setEmbeddedBitmapText(bool useEmbeddedBitmapText)
1229
Cary Clarkab2621d2018-01-30 10:08:57 -05001230#In Font_Embedded_Bitmaps
1231#Line # sets or clears Font_Embedded_Bitmaps ##
Cary Clark8032b982017-07-28 11:04:54 -04001232 Requests, but does not require, to use bitmaps in fonts instead of outlines.
1233
1234 Sets kEmbeddedBitmapText_Flag if useEmbeddedBitmapText is true.
1235 Clears kEmbeddedBitmapText_Flag if useEmbeddedBitmapText is false.
1236
1237 #Param useEmbeddedBitmapText setting for kEmbeddedBitmapText_Flag ##
1238
1239 #Example
1240 SkPaint paint1, paint2;
1241 paint1.setEmbeddedBitmapText(true);
1242 paint2.setFlags(paint2.getFlags() | SkPaint::kEmbeddedBitmapText_Flag);
1243 SkDebugf("paint1 %c= paint2\n", paint1 == paint2 ? '=' : '!');
1244
1245 #StdOut
1246 paint1 == paint2
1247 ##
1248 ##
1249
1250##
1251
Cary Clark08895c42018-02-01 09:37:32 -05001252#Subtopic Font_Embedded_Bitmaps ##
Cary Clark8032b982017-07-28 11:04:54 -04001253# ------------------------------------------------------------------------------
Cary Clark08895c42018-02-01 09:37:32 -05001254#Subtopic Automatic_Hinting
1255#Line # always adjust glyph paths ##
Cary Clark8032b982017-07-28 11:04:54 -04001256#Substitute auto-hinting
1257
1258If Hinting is set to kNormal_Hinting or kFull_Hinting, Automatic_Hinting
Cary Clarkce101242017-09-01 15:51:02 -04001259instructs the Font_Manager to always hint Glyphs.
Cary Clark8032b982017-07-28 11:04:54 -04001260Automatic_Hinting has no effect if Hinting is set to kNo_Hinting or
1261kSlight_Hinting.
1262
1263Automatic_Hinting only affects platforms that use FreeType as the Font_Manager.
1264
1265#Method bool isAutohinted() const
1266
Cary Clarkab2621d2018-01-30 10:08:57 -05001267#In Automatic_Hinting
1268#Line # returns true if Glyphs are always hinted ##
Cary Clark8032b982017-07-28 11:04:54 -04001269 If true, and if Hinting is set to kNormal_Hinting or kFull_Hinting, and if
1270 platform uses FreeType as the Font_Manager, instruct the Font_Manager to always hint
Cary Clarkce101242017-09-01 15:51:02 -04001271 Glyphs.
Cary Clark8032b982017-07-28 11:04:54 -04001272
1273 Equivalent to getFlags masked with kAutoHinting_Flag.
1274
1275 #Return kAutoHinting_Flag state ##
1276
1277 #Example
1278 SkPaint paint;
1279 for (auto forceAutoHinting : { false, true} ) {
1280 paint.setAutohinted(forceAutoHinting);
1281 SkDebugf("paint.isAutohinted() %c="
1282 " !!(paint.getFlags() & SkPaint::kAutoHinting_Flag)\n",
1283 paint.isAutohinted() ==
1284 !!(paint.getFlags() & SkPaint::kAutoHinting_Flag) ? '=' : '!');
1285 }
1286 #StdOut
1287 paint.isAutohinted() == !!(paint.getFlags() & SkPaint::kAutoHinting_Flag)
1288 paint.isAutohinted() == !!(paint.getFlags() & SkPaint::kAutoHinting_Flag)
1289 ##
1290 ##
1291
1292 #SeeAlso setAutohinted Hinting
1293
1294##
1295
1296#Method void setAutohinted(bool useAutohinter)
1297
Cary Clarkab2621d2018-01-30 10:08:57 -05001298#In Automatic_Hinting
1299#Line # sets Glyphs to always be hinted ##
Cary Clark8032b982017-07-28 11:04:54 -04001300 If Hinting is set to kNormal_Hinting or kFull_Hinting and useAutohinter is set,
Cary Clarkce101242017-09-01 15:51:02 -04001301 instruct the Font_Manager to always hint Glyphs.
Cary Clark8032b982017-07-28 11:04:54 -04001302 Automatic_Hinting has no effect if Hinting is set to kNo_Hinting or
1303 kSlight_Hinting.
1304
Cary Clark579985c2017-07-31 11:48:27 -04001305 Only affects platforms that use FreeType as the Font_Manager.
Cary Clark8032b982017-07-28 11:04:54 -04001306
1307 Sets kAutoHinting_Flag if useAutohinter is true.
1308 Clears kAutoHinting_Flag if useAutohinter is false.
1309
1310 #Param useAutohinter setting for kAutoHinting_Flag ##
1311
1312 #Example
1313 void draw(SkCanvas* canvas) {
1314 SkPaint paint;
1315 paint.setAntiAlias(true);
1316 const char testStr[] = "xxxx xxxx";
1317 for (auto forceAutoHinting : { false, true} ) {
1318 paint.setAutohinted(forceAutoHinting);
1319 paint.setTextSize(24);
1320 canvas->drawString(paint.isAutohinted() ? "auto-hinted" : "default", 108, 30, paint);
1321 for (SkScalar textSize = 8; textSize < 30; textSize *= 1.22f) {
1322 paint.setTextSize(textSize);
1323 canvas->translate(0, textSize);
1324 canvas->drawString(testStr, 10, 0, paint);
1325 }
1326 }
1327 }
1328 ##
1329
1330 #SeeAlso isAutohinted Hinting
1331
1332##
1333
Cary Clark08895c42018-02-01 09:37:32 -05001334#Subtopic Automatic_Hinting ##
Cary Clark8032b982017-07-28 11:04:54 -04001335# ------------------------------------------------------------------------------
Cary Clark08895c42018-02-01 09:37:32 -05001336#Subtopic Vertical_Text
1337#Line # orient text from top to bottom ##
Cary Clark8032b982017-07-28 11:04:54 -04001338
1339Text may be drawn by positioning each glyph, or by positioning the first glyph and
Cary Clarkce101242017-09-01 15:51:02 -04001340using Font_Advance to position subsequent Glyphs. By default, each successive glyph
1341is positioned to the right of the preceding glyph. Vertical_Text sets successive
1342Glyphs to position below the preceding glyph.
Cary Clark8032b982017-07-28 11:04:54 -04001343
Cary Clarkce101242017-09-01 15:51:02 -04001344Skia can translate text character codes as a series of Glyphs, but does not implement
Herb Derbyfcac00f2018-05-01 11:57:56 -04001345font substitution,
Cary Clarkce101242017-09-01 15:51:02 -04001346textual substitution, line layout, or contextual spacing like Kerning pairs. Use
Cary Clark6fc50412017-09-21 12:31:06 -04001347a text shaping engine like
Cary Clark682c58d2018-05-16 07:07:07 -04001348#A HarfBuzz # https://harfbuzz.org/ ##
Cary Clark6fc50412017-09-21 12:31:06 -04001349 to translate text runs
Cary Clark8032b982017-07-28 11:04:54 -04001350into glyph series.
1351
1352Vertical_Text is clear if text is drawn left to right or set if drawn from top to bottom.
1353
1354Flags kVerticalText_Flag if clear draws text left to right.
1355Flags kVerticalText_Flag if set draws text top to bottom.
1356
1357Vertical_Text is clear by default.
1358Vertical_Text can be set by default by setting SkPaintDefaults_Flags to
1359kVerticalText_Flag at compile time.
1360
1361#Example
1362
1363void draw(SkCanvas* canvas) {
1364 SkPaint paint;
1365 paint.setAntiAlias(true);
1366 paint.setTextSize(50);
1367 for (bool vertical : { false, true } ) {
1368 paint.setVerticalText(vertical);
1369 canvas->drawString("aAlL", 25, 50, paint);
1370 }
1371}
1372
1373##
1374
1375#Method bool isVerticalText() const
1376
Cary Clarkab2621d2018-01-30 10:08:57 -05001377#In Vertical_Text
1378#Line # returns true if Vertical_Text is set ##
Cary Clarkce101242017-09-01 15:51:02 -04001379 If true, Glyphs are drawn top to bottom instead of left to right.
Cary Clark8032b982017-07-28 11:04:54 -04001380
1381 Equivalent to getFlags masked with kVerticalText_Flag.
1382
1383 #Return kVerticalText_Flag state ##
1384
1385 #Example
1386 SkPaint paint;
1387 SkDebugf("paint.isVerticalText() %c= !!(paint.getFlags() & SkPaint::kVerticalText_Flag)\n",
1388 paint.isVerticalText() == !!(paint.getFlags() & SkPaint::kVerticalText_Flag) ? '=' : '!');
1389 paint.setVerticalText(true);
1390 SkDebugf("paint.isVerticalText() %c= !!(paint.getFlags() & SkPaint::kVerticalText_Flag)\n",
1391 paint.isVerticalText() == !!(paint.getFlags() & SkPaint::kVerticalText_Flag) ? '=' : '!');
1392
1393 #StdOut
1394 paint.isVerticalText() == !!(paint.getFlags() & SkPaint::kVerticalText_Flag)
1395 paint.isVerticalText() == !!(paint.getFlags() & SkPaint::kVerticalText_Flag)
1396 ##
1397 ##
1398
1399##
1400
1401#Method void setVerticalText(bool verticalText)
1402
Cary Clarkab2621d2018-01-30 10:08:57 -05001403#In Vertical_Text
1404#Line # sets or clears Vertical_Text ##
Cary Clark8032b982017-07-28 11:04:54 -04001405 If true, text advance positions the next glyph below the previous glyph instead of to the
1406 right of previous glyph.
1407
1408 Sets kVerticalText_Flag if vertical is true.
1409 Clears kVerticalText_Flag if vertical is false.
1410
1411 #Param verticalText setting for kVerticalText_Flag ##
1412
1413 #Example
1414 SkPaint paint1, paint2;
1415 paint1.setVerticalText(true);
1416 paint2.setFlags(paint2.getFlags() | SkPaint::kVerticalText_Flag);
1417 SkDebugf("paint1 %c= paint2\n", paint1 == paint2 ? '=' : '!');
1418
1419 #StdOut
1420 paint1 == paint2
1421 ##
1422 ##
1423
1424##
1425
Cary Clark08895c42018-02-01 09:37:32 -05001426#Subtopic Vertical_Text ##
Cary Clark8032b982017-07-28 11:04:54 -04001427# ------------------------------------------------------------------------------
1428
Cary Clark08895c42018-02-01 09:37:32 -05001429#Subtopic Fake_Bold
1430#Line # approximate font styles ##
Cary Clark8032b982017-07-28 11:04:54 -04001431
1432Fake_Bold approximates the bold font style accompanying a normal font when a bold font face
1433is not available. Skia does not provide font substitution; it is up to the client to find the
Cary Clarkbc5697d2017-10-04 14:31:33 -04001434bold font face using the platform Font_Manager.
Cary Clark8032b982017-07-28 11:04:54 -04001435
Herb Derbyfcac00f2018-05-01 11:57:56 -04001436Use Text_Skew_X to approximate an italic font style when the italic font face
Cary Clark8032b982017-07-28 11:04:54 -04001437is not available.
1438
Cary Clarkce101242017-09-01 15:51:02 -04001439A FreeType based port may define SK_USE_FREETYPE_EMBOLDEN at compile time to direct
1440the font engine to create the bold Glyphs. Otherwise, the extra bold is computed
Herb Derbyfcac00f2018-05-01 11:57:56 -04001441by increasing the stroke width and setting the Style to kStrokeAndFill_Style as needed.
Cary Clark8032b982017-07-28 11:04:54 -04001442
1443Fake_Bold is disabled by default.
1444
1445#Example
1446#Height 128
1447void draw(SkCanvas* canvas) {
1448 SkPaint paint;
1449 paint.setAntiAlias(true);
1450 paint.setTextSize(40);
1451 canvas->drawString("OjYy_-", 10, 35, paint);
1452 paint.setFakeBoldText(true);
1453 canvas->drawString("OjYy_-", 10, 75, paint);
1454 // create a custom fake bold by varying the stroke width
1455 paint.setFakeBoldText(false);
1456 paint.setStyle(SkPaint::kStrokeAndFill_Style);
1457 paint.setStrokeWidth(40.f / 48);
1458 canvas->drawString("OjYy_-", 10, 115, paint);
1459}
1460##
1461
1462#Method bool isFakeBoldText() const
1463
Cary Clarkab2621d2018-01-30 10:08:57 -05001464#In Fake_Bold
1465#Line # returns true if Fake_Bold is set ##
Cary Clark8032b982017-07-28 11:04:54 -04001466 If true, approximate bold by increasing the stroke width when creating glyph bitmaps
1467 from outlines.
1468
1469 Equivalent to getFlags masked with kFakeBoldText_Flag.
1470
1471 #Return kFakeBoldText_Flag state ##
1472
1473 #Example
1474 SkPaint paint;
1475 SkDebugf("paint.isFakeBoldText() %c= !!(paint.getFlags() & SkPaint::kFakeBoldText_Flag)\n",
1476 paint.isFakeBoldText() == !!(paint.getFlags() & SkPaint::kFakeBoldText_Flag) ? '=' : '!');
1477 paint.setFakeBoldText(true);
1478 SkDebugf("paint.isFakeBoldText() %c= !!(paint.getFlags() & SkPaint::kFakeBoldText_Flag)\n",
1479 paint.isFakeBoldText() == !!(paint.getFlags() & SkPaint::kFakeBoldText_Flag) ? '=' : '!');
1480
1481 #StdOut
1482 paint.isFakeBoldText() == !!(paint.getFlags() & SkPaint::kFakeBoldText_Flag)
1483 paint.isFakeBoldText() == !!(paint.getFlags() & SkPaint::kFakeBoldText_Flag)
1484 ##
1485 ##
1486
1487##
1488
1489#Method void setFakeBoldText(bool fakeBoldText)
1490
Cary Clarkab2621d2018-01-30 10:08:57 -05001491#In Fake_Bold
1492#Line # sets or clears Fake_Bold ##
Cary Clarkce101242017-09-01 15:51:02 -04001493 Use increased stroke width when creating glyph bitmaps to approximate a bold typeface.
Cary Clark8032b982017-07-28 11:04:54 -04001494
1495 Sets kFakeBoldText_Flag if fakeBoldText is true.
1496 Clears kFakeBoldText_Flag if fakeBoldText is false.
1497
1498 #Param fakeBoldText setting for kFakeBoldText_Flag ##
1499
1500 #Example
1501 SkPaint paint1, paint2;
1502 paint1.setFakeBoldText(true);
1503 paint2.setFlags(paint2.getFlags() | SkPaint::kFakeBoldText_Flag);
1504 SkDebugf("paint1 %c= paint2\n", paint1 == paint2 ? '=' : '!');
1505
1506 #StdOut
1507 paint1 == paint2
1508 ##
1509 ##
1510
1511##
1512
Cary Clark08895c42018-02-01 09:37:32 -05001513#Subtopic Fake_Bold ##
Cary Clark8032b982017-07-28 11:04:54 -04001514
1515# ------------------------------------------------------------------------------
Cary Clark08895c42018-02-01 09:37:32 -05001516#Subtopic Full_Hinting_Spacing
1517#Line # glyph spacing affected by hinting ##
Cary Clark8032b982017-07-28 11:04:54 -04001518#Alias Full_Hinting_Spacing # long winded enough -- maybe things with two underscores auto-aliased?
1519
Cary Clarkce101242017-09-01 15:51:02 -04001520if Hinting is set to kFull_Hinting, Full_Hinting_Spacing adjusts the character
1521spacing by the difference of the hinted and Unhinted Left_Side_Bearing and
1522Right_Side_Bearing. Full_Hinting_Spacing only applies to platforms that use
1523FreeType as their Font_Engine.
Cary Clark8032b982017-07-28 11:04:54 -04001524
Cary Clarkce101242017-09-01 15:51:02 -04001525Full_Hinting_Spacing is not related to text Kerning, where the space between
Cary Clarkbc5697d2017-10-04 14:31:33 -04001526a specific pair of characters is adjusted using data in the font Kerning tables.
Cary Clark8032b982017-07-28 11:04:54 -04001527
1528#Method bool isDevKernText() const
Herb Derbyfcac00f2018-05-01 11:57:56 -04001529#Deprecated
Cary Clark8032b982017-07-28 11:04:54 -04001530##
1531
Herb Derbyfcac00f2018-05-01 11:57:56 -04001532#Method void setDevKernText(bool)
1533#Deprecated
Cary Clark8032b982017-07-28 11:04:54 -04001534##
1535
Cary Clark08895c42018-02-01 09:37:32 -05001536#Subtopic Full_Hinting_Spacing ##
Cary Clark8032b982017-07-28 11:04:54 -04001537# ------------------------------------------------------------------------------
Cary Clark08895c42018-02-01 09:37:32 -05001538#Subtopic Filter_Quality_Methods
1539#Line # get and set Filter_Quality ##
Cary Clark8032b982017-07-28 11:04:54 -04001540
1541Filter_Quality trades speed for image filtering when the image is scaled.
1542A lower Filter_Quality draws faster, but has less fidelity.
1543A higher Filter_Quality draws slower, but looks better.
Cary Clarkce101242017-09-01 15:51:02 -04001544If the image is drawn without scaling, the Filter_Quality choice will not result
1545in a noticeable difference.
Cary Clark8032b982017-07-28 11:04:54 -04001546
1547Filter_Quality is used in Paint passed as a parameter to
1548#List
1549# SkCanvas::drawBitmap ##
1550# SkCanvas::drawBitmapRect ##
1551# SkCanvas::drawImage ##
1552# SkCanvas::drawImageRect ##
1553 #ToDo probably more... ##
1554#List ##
1555and when Paint has a Shader specialization that uses Image or Bitmap.
1556
1557Filter_Quality is kNone_SkFilterQuality by default.
1558
1559#Example
1560#Image 3
1561void draw(SkCanvas* canvas) {
1562 SkPaint paint;
1563 canvas->scale(.2f, .2f);
Herb Derbyfcac00f2018-05-01 11:57:56 -04001564 for (SkFilterQuality q : { kNone_SkFilterQuality, kLow_SkFilterQuality,
Cary Clark8032b982017-07-28 11:04:54 -04001565 kMedium_SkFilterQuality, kHigh_SkFilterQuality } ) {
1566 paint.setFilterQuality(q);
1567 canvas->drawImage(image.get(), 0, 0, &paint);
1568 canvas->translate(550, 0);
1569 if (kLow_SkFilterQuality == q) canvas->translate(-1100, 550);
1570 }
1571}
1572##
1573
1574#Method SkFilterQuality getFilterQuality() const
1575
Cary Clarkab2621d2018-01-30 10:08:57 -05001576#In Filter_Quality_Methods
1577#Line # returns Filter_Quality, image filtering level ##
Cary Clark8032b982017-07-28 11:04:54 -04001578Returns Filter_Quality, the image filtering level. A lower setting
1579draws faster; a higher setting looks better when the image is scaled.
1580
Herb Derbyfcac00f2018-05-01 11:57:56 -04001581#Return one of: kNone_SkFilterQuality, kLow_SkFilterQuality,
Cary Clark8032b982017-07-28 11:04:54 -04001582 kMedium_SkFilterQuality, kHigh_SkFilterQuality
1583#Return ##
1584
1585#Example
1586 SkPaint paint;
1587 SkDebugf("kNone_SkFilterQuality %c= paint.getFilterQuality()\n",
1588 kNone_SkFilterQuality == paint.getFilterQuality() ? '=' : '!');
1589
1590 #StdOut
1591 kNone_SkFilterQuality == paint.getFilterQuality()
1592 ##
1593##
1594
1595##
1596
1597
1598#Method void setFilterQuality(SkFilterQuality quality)
1599
Cary Clarkab2621d2018-01-30 10:08:57 -05001600#In Filter_Quality_Methods
1601#Line # sets Filter_Quality, the image filtering level ##
Cary Clark8032b982017-07-28 11:04:54 -04001602Sets Filter_Quality, the image filtering level. A lower setting
1603draws faster; a higher setting looks better when the image is scaled.
Herb Derbyfcac00f2018-05-01 11:57:56 -04001604Does not check to see if quality is valid.
Cary Clark8032b982017-07-28 11:04:54 -04001605
Herb Derbyfcac00f2018-05-01 11:57:56 -04001606#Param quality one of: kNone_SkFilterQuality, kLow_SkFilterQuality,
Cary Clark8032b982017-07-28 11:04:54 -04001607 kMedium_SkFilterQuality, kHigh_SkFilterQuality
1608##
1609
1610#Example
1611 SkPaint paint;
1612 paint.setFilterQuality(kHigh_SkFilterQuality);
1613 SkDebugf("kHigh_SkFilterQuality %c= paint.getFilterQuality()\n",
1614 kHigh_SkFilterQuality == paint.getFilterQuality() ? '=' : '!');
1615
1616 #StdOut
1617 kHigh_SkFilterQuality == paint.getFilterQuality()
1618 ##
1619##
1620
1621#SeeAlso SkFilterQuality Image_Scaling
1622
1623##
1624
Cary Clark08895c42018-02-01 09:37:32 -05001625#Subtopic Filter_Quality_Methods ##
Cary Clark8032b982017-07-28 11:04:54 -04001626# ------------------------------------------------------------------------------
Cary Clark08895c42018-02-01 09:37:32 -05001627#Subtopic Color_Methods
1628#Line # get and set Color ##
Cary Clark8032b982017-07-28 11:04:54 -04001629
Cary Clarkab2621d2018-01-30 10:08:57 -05001630#Table
1631#Legend
1632# name # description ##
1633#Legend ##
Cary Clarkffb3d682018-05-17 12:17:28 -04001634# getColor # returns Color_Alpha and RGB, one drawing color ##
1635# setColor # sets Color_Alpha and RGB, one drawing color ##
Cary Clarkab2621d2018-01-30 10:08:57 -05001636#Table ##
Cary Clark8032b982017-07-28 11:04:54 -04001637
Cary Clarkffb3d682018-05-17 12:17:28 -04001638Color specifies the red, blue, green, and Color_Alpha
Cary Clarkab2621d2018-01-30 10:08:57 -05001639values used to draw a filled or stroked shape in a 32-bit value. Each component
1640occupies 8-bits, ranging from zero: no contribution; to 255: full intensity.
1641All values in any combination are valid.
Cary Clark8032b982017-07-28 11:04:54 -04001642
Cary Clarkab2621d2018-01-30 10:08:57 -05001643Color is not Premultiplied; Color_Alpha sets the transparency independent of
Cary Clarkffb3d682018-05-17 12:17:28 -04001644RGB: red, blue, and green.
Cary Clarkab2621d2018-01-30 10:08:57 -05001645
Cary Clarkffb3d682018-05-17 12:17:28 -04001646The bit positions of Color_Alpha and RGB are independent of the bit
Cary Clarkab2621d2018-01-30 10:08:57 -05001647positions on the output device, which may have more or fewer bits, and may have
1648a different arrangement.
Cary Clark8032b982017-07-28 11:04:54 -04001649
1650#Table
1651#Legend
Cary Clarkffb3d682018-05-17 12:17:28 -04001652# bit positions # Color_Alpha # red # blue # green ##
Cary Clark8032b982017-07-28 11:04:54 -04001653#Legend ##
1654# # 31 - 24 # 23 - 16 # 15 - 8 # 7 - 0 ##
1655#Table ##
1656
1657#Example
1658#Height 128
1659 void draw(SkCanvas* canvas) {
1660 SkPaint paint;
1661 paint.setColor(0x8000FF00); // transparent green
1662 canvas->drawCircle(50, 50, 40, paint);
1663 paint.setARGB(128, 255, 0, 0); // transparent red
1664 canvas->drawCircle(80, 50, 40, paint);
1665 paint.setColor(SK_ColorBLUE);
1666 paint.setAlpha(0x80);
1667 canvas->drawCircle(65, 65, 40, paint);
1668 }
1669##
1670
1671#Method SkColor getColor() const
1672
Cary Clarkab2621d2018-01-30 10:08:57 -05001673#In Color_Methods
Cary Clarkffb3d682018-05-17 12:17:28 -04001674#Line # returns Color_Alpha and RGB, one drawing color ##
1675 Retrieves Alpha and RGB, Unpremultiplied, packed into 32 bits.
Cary Clark8032b982017-07-28 11:04:54 -04001676 Use helpers SkColorGetA, SkColorGetR, SkColorGetG, and SkColorGetB to extract
1677 a color component.
1678
Cary Clarkffb3d682018-05-17 12:17:28 -04001679 #Return Unpremultiplied ARGB ##
Cary Clark8032b982017-07-28 11:04:54 -04001680
1681 #Example
1682 SkPaint paint;
1683 paint.setColor(SK_ColorYELLOW);
1684 SkColor y = paint.getColor();
1685 SkDebugf("Yellow is %d%% red, %d%% green, and %d%% blue.\n", (int) (SkColorGetR(y) / 2.55f),
1686 (int) (SkColorGetG(y) / 2.55f), (int) (SkColorGetB(y) / 2.55f));
1687
1688 #StdOut
1689 Yellow is 100% red, 100% green, and 0% blue.
1690 ##
1691 ##
1692
1693 #SeeAlso SkColor
1694
1695##
1696
1697#Method void setColor(SkColor color)
1698
Cary Clarkab2621d2018-01-30 10:08:57 -05001699#In Color_Methods
Cary Clarkffb3d682018-05-17 12:17:28 -04001700#Line # sets Color_Alpha and RGB, one drawing color ##
1701 Sets Alpha and RGB used when stroking and filling. The color is a 32-bit value,
1702 Unpremultiplied, packing 8-bit components for Alpha, red, blue, and green.
Cary Clark8032b982017-07-28 11:04:54 -04001703
Cary Clarkffb3d682018-05-17 12:17:28 -04001704 #Param color Unpremultiplied ARGB ##
Herb Derbyfcac00f2018-05-01 11:57:56 -04001705
Cary Clark0c5f5462017-12-15 11:21:51 -05001706 #Example
Cary Clark8032b982017-07-28 11:04:54 -04001707 SkPaint green1, green2;
1708 unsigned a = 255;
1709 unsigned r = 0;
1710 unsigned g = 255;
1711 unsigned b = 0;
1712 green1.setColor((a << 24) + (r << 16) + (g << 8) + (b << 0));
1713 green2.setColor(0xFF00FF00);
1714 SkDebugf("green1 %c= green2\n", green1 == green2 ? '=' : '!');
1715
1716 #StdOut
1717 green1 == green2
1718 ##
1719 ##
1720
1721 #SeeAlso SkColor setARGB SkColorSetARGB
1722
1723##
Cary Clark08895c42018-02-01 09:37:32 -05001724#Subtopic Color_Methods ##
Cary Clark8032b982017-07-28 11:04:54 -04001725
1726#Subtopic Alpha_Methods
Cary Clark08895c42018-02-01 09:37:32 -05001727#Line # get and set Alpha ##
Cary Clark8032b982017-07-28 11:04:54 -04001728
Cary Clarkffb3d682018-05-17 12:17:28 -04001729Color_Alpha sets the transparency independent of RGB: red, blue, and green.
Cary Clark8032b982017-07-28 11:04:54 -04001730
1731#Method uint8_t getAlpha() const
1732
Cary Clarkab2621d2018-01-30 10:08:57 -05001733#In Alpha_Methods
1734#Line # returns Color_Alpha, color opacity ##
Cary Clarkce101242017-09-01 15:51:02 -04001735 Retrieves Alpha from the Color used when stroking and filling.
Cary Clark8032b982017-07-28 11:04:54 -04001736
Cary Clarkce101242017-09-01 15:51:02 -04001737 #Return Alpha ranging from zero, fully transparent, to 255, fully opaque ##
Cary Clark8032b982017-07-28 11:04:54 -04001738
1739 #Example
1740 SkPaint paint;
1741 SkDebugf("255 %c= paint.getAlpha()\n", 255 == paint.getAlpha() ? '=' : '!');
1742
1743 #StdOut
1744 255 == paint.getAlpha()
1745 ##
1746 ##
1747
1748##
1749
1750#Method void setAlpha(U8CPU a)
1751
Cary Clarkab2621d2018-01-30 10:08:57 -05001752#In Alpha_Methods
1753#Line # sets Color_Alpha, color opacity ##
Cary Clarkffb3d682018-05-17 12:17:28 -04001754 Replaces Alpha, leaving RGB
Cary Clark8032b982017-07-28 11:04:54 -04001755 unchanged. An out of range value triggers an assert in the debug
1756 build. a is a value from zero to 255.
1757 a set to zero makes Color fully transparent; a set to 255 makes Color
1758 fully opaque.
1759
Cary Clarkce101242017-09-01 15:51:02 -04001760 #Param a Alpha component of Color ##
Cary Clark8032b982017-07-28 11:04:54 -04001761
1762 #Example
1763 SkPaint paint;
1764 paint.setColor(0x00112233);
1765 paint.setAlpha(0x44);
1766 SkDebugf("0x44112233 %c= paint.getColor()\n", 0x44112233 == paint.getColor() ? '=' : '!');
1767
1768 #StdOut
1769 0x44112233 == paint.getColor()
1770 ##
1771 ##
1772
1773##
1774
Cary Clark08895c42018-02-01 09:37:32 -05001775#Subtopic Alpha_Methods ##
Cary Clark8032b982017-07-28 11:04:54 -04001776
1777#Method void setARGB(U8CPU a, U8CPU r, U8CPU g, U8CPU b)
1778
Cary Clarkab2621d2018-01-30 10:08:57 -05001779#In Color_Methods
1780#Line # sets color by component ##
Cary Clark8032b982017-07-28 11:04:54 -04001781 Sets Color used when drawing solid fills. The color components range from 0 to 255.
Cary Clarkffb3d682018-05-17 12:17:28 -04001782 The color is Unpremultiplied; Alpha sets the transparency independent of RGB.
Cary Clark8032b982017-07-28 11:04:54 -04001783
1784 #Param a amount of Color_Alpha, from fully transparent (0) to fully opaque (255) ##
Cary Clarkffb3d682018-05-17 12:17:28 -04001785 #Param r amount of red, from no red (0) to full red (255) ##
1786 #Param g amount of green, from no green (0) to full green (255) ##
1787 #Param b amount of blue, from no blue (0) to full blue (255) ##
Herb Derbyfcac00f2018-05-01 11:57:56 -04001788
Cary Clark8032b982017-07-28 11:04:54 -04001789 #Example
1790 SkPaint transRed1, transRed2;
1791 transRed1.setARGB(255 / 2, 255, 0, 0);
1792 transRed2.setColor(SkColorSetARGB(255 / 2, 255, 0, 0));
1793 SkDebugf("transRed1 %c= transRed2", transRed1 == transRed2 ? '=' : '!');
1794
1795 #StdOut
1796 transRed1 == transRed2
1797 ##
1798 ##
1799
1800 #SeeAlso setColor SkColorSetARGB
1801
1802##
1803
Cary Clark8032b982017-07-28 11:04:54 -04001804# ------------------------------------------------------------------------------
Cary Clark08895c42018-02-01 09:37:32 -05001805#Subtopic Style
1806#Line # geometry filling, stroking ##
Cary Clark8032b982017-07-28 11:04:54 -04001807
1808Style specifies if the geometry is filled, stroked, or both filled and stroked.
1809Some shapes ignore Style and are always drawn filled or stroked.
1810
1811Set Style to kFill_Style to fill the shape.
1812The fill covers the area inside the geometry for most shapes.
1813
1814Set Style to kStroke_Style to stroke the shape.
1815
1816# ------------------------------------------------------------------------------
1817#Subtopic Fill
Cary Clark08895c42018-02-01 09:37:32 -05001818#Line # fill and stroke ##
Cary Clark8032b982017-07-28 11:04:54 -04001819#ToDo write up whatever generalities make sense to describe filling ##
1820
1821#SeeAlso Path_Fill_Type
Cary Clark08895c42018-02-01 09:37:32 -05001822#Subtopic Fill ##
Cary Clark8032b982017-07-28 11:04:54 -04001823
1824#Subtopic Stroke
Cary Clark08895c42018-02-01 09:37:32 -05001825#Line # lines and curves with width ##
Cary Clarkbc5697d2017-10-04 14:31:33 -04001826The stroke covers the area described by following the shape edge with a pen or brush of
Cary Clark8032b982017-07-28 11:04:54 -04001827Stroke_Width. The area covered where the shape starts and stops is described by Stroke_Cap.
1828The area covered where the shape turns a corner is described by Stroke_Join.
Cary Clarkbc5697d2017-10-04 14:31:33 -04001829The stroke is centered on the shape; it extends equally on either side of the shape edge.
Cary Clark8032b982017-07-28 11:04:54 -04001830
1831As Stroke_Width gets smaller, the drawn path frame is thinner. Stroke_Width less than one
1832may have gaps, and if kAntiAlias_Flag is set, Color_Alpha will increase to visually decrease coverage.
Cary Clark08895c42018-02-01 09:37:32 -05001833#Subtopic Stroke ##
Cary Clark8032b982017-07-28 11:04:54 -04001834
1835#Subtopic Hairline
Cary Clark08895c42018-02-01 09:37:32 -05001836#Line # lines and curves with minimal width ##
Cary Clark8032b982017-07-28 11:04:54 -04001837#Alias Hairline # maybe should be Stroke_Hairline ?
1838
1839Stroke_Width of zero has a special meaning and switches drawing to use Hairline.
Herb Derbyfcac00f2018-05-01 11:57:56 -04001840Hairline draws the thinnest continuous frame. If kAntiAlias_Flag is clear, adjacent pixels
1841flow horizontally, vertically,or diagonally.
Cary Clark8032b982017-07-28 11:04:54 -04001842
Cary Clarkffb3d682018-05-17 12:17:28 -04001843#ToDo what is the description of Anti_Aliased hairlines? ##
Cary Clark8032b982017-07-28 11:04:54 -04001844
1845Path drawing with Hairline may hit the same pixel more than once. For instance, Path containing
1846two lines in one Path_Contour will draw the corner point once, but may both lines may draw the adjacent
1847pixel. If kAntiAlias_Flag is set, transparency is applied twice, resulting in a darker pixel. Some
1848GPU-backed implementations apply transparency at a later drawing stage, avoiding double hit pixels
1849while stroking.
1850
Cary Clark08895c42018-02-01 09:37:32 -05001851#Subtopic Hairline ##
Cary Clark8032b982017-07-28 11:04:54 -04001852
1853#Enum Style
Cary Clark08895c42018-02-01 09:37:32 -05001854#Line # stroke, fill, or both ##
Cary Clark8032b982017-07-28 11:04:54 -04001855
1856#Code
1857 enum Style {
1858 kFill_Style,
1859 kStroke_Style,
1860 kStrokeAndFill_Style,
1861 };
Cary Clarkd98f78c2018-04-26 08:32:37 -04001862
1863 static constexpr int kStyleCount = kStrokeAndFill_Style + 1;
Cary Clark8032b982017-07-28 11:04:54 -04001864##
1865
1866Set Style to fill, stroke, or both fill and stroke geometry.
1867The stroke and fill
1868share all paint attributes; for instance, they are drawn with the same color.
1869
1870Use kStrokeAndFill_Style to avoid hitting the same pixels twice with a stroke draw and
1871a fill draw.
1872
1873#Const kFill_Style 0
Cary Clark682c58d2018-05-16 07:07:07 -04001874#Line # set to fill geometry ##
Herb Derbyfcac00f2018-05-01 11:57:56 -04001875 Applies to Rect, Region, Round_Rect, Circles, Ovals, Path, and Text.
Cary Clarkce101242017-09-01 15:51:02 -04001876 Bitmap, Image, Patches, Region, Sprites, and Vertices are painted as if
Cary Clark8032b982017-07-28 11:04:54 -04001877 kFill_Style is set, and ignore the set Style.
1878 The Path_Fill_Type specifies additional rules to fill the area outside the path edge,
1879 and to create an unfilled hole inside the shape.
1880 Style is set to kFill_Style by default.
1881##
1882
1883#Const kStroke_Style 1
Cary Clark682c58d2018-05-16 07:07:07 -04001884#Line # set to stroke geometry ##
Herb Derbyfcac00f2018-05-01 11:57:56 -04001885 Applies to Rect, Region, Round_Rect, Arcs, Circles, Ovals, Path, and Text.
Cary Clark56356312018-02-08 14:45:18 -05001886 Arcs, Lines, and points, are always drawn as if kStroke_Style is set,
Cary Clark8032b982017-07-28 11:04:54 -04001887 and ignore the set Style.
1888 The stroke construction is unaffected by the Path_Fill_Type.
1889##
1890
1891#Const kStrokeAndFill_Style 2
Cary Clark682c58d2018-05-16 07:07:07 -04001892#Line # sets to stroke and fill geometry ##
Cary Clarkce101242017-09-01 15:51:02 -04001893 Applies to Rect, Region, Round_Rect, Circles, Ovals, Path, and Text.
Cary Clark8032b982017-07-28 11:04:54 -04001894 Path is treated as if it is set to SkPath::kWinding_FillType,
Herb Derbyfcac00f2018-05-01 11:57:56 -04001895 and the set Path_Fill_Type is ignored.
Cary Clark8032b982017-07-28 11:04:54 -04001896##
1897
Cary Clark8032b982017-07-28 11:04:54 -04001898#Const kStyleCount 3
Cary Clark682c58d2018-05-16 07:07:07 -04001899#Line # number of different Style values defined ##
Cary Clark8032b982017-07-28 11:04:54 -04001900May be used to verify that Style is a legal value.
1901##
1902
Cary Clarkd98f78c2018-04-26 08:32:37 -04001903#Enum Style ##
Cary Clark8032b982017-07-28 11:04:54 -04001904
1905#Method Style getStyle() const
1906
Cary Clarkab2621d2018-01-30 10:08:57 -05001907#In Style
1908#Line # returns Style: stroke, fill, or both ##
Cary Clark8032b982017-07-28 11:04:54 -04001909 Whether the geometry is filled, stroked, or filled and stroked.
1910
1911 #Return one of:kFill_Style, kStroke_Style, kStrokeAndFill_Style ##
1912
1913 #Example
1914 SkPaint paint;
1915 SkDebugf("SkPaint::kFill_Style %c= paint.getStyle()\n",
1916 SkPaint::kFill_Style == paint.getStyle() ? '=' : '!');
1917
1918 #StdOut
1919 SkPaint::kFill_Style == paint.getStyle()
1920 ##
1921 ##
1922
1923#SeeAlso Style setStyle
1924##
1925
1926#Method void setStyle(Style style)
1927
Cary Clarkab2621d2018-01-30 10:08:57 -05001928#In Style
1929#Line # sets Style: stroke, fill, or both ##
Cary Clark8032b982017-07-28 11:04:54 -04001930 Sets whether the geometry is filled, stroked, or filled and stroked.
1931 Has no effect if style is not a legal Style value.
1932
1933 #Param style one of: kFill_Style, kStroke_Style, kStrokeAndFill_Style
1934 ##
1935
1936 #Example
1937 void draw(SkCanvas* canvas) {
1938 SkPaint paint;
1939 paint.setStrokeWidth(5);
1940 SkRegion region;
1941 region.op(140, 10, 160, 30, SkRegion::kUnion_Op);
1942 region.op(170, 40, 190, 60, SkRegion::kUnion_Op);
1943 SkBitmap bitmap;
1944 bitmap.setInfo(SkImageInfo::MakeA8(50, 50), 50);
1945 uint8_t pixels[50][50];
1946 for (int x = 0; x < 50; ++x) {
1947 for (int y = 0; y < 50; ++y) {
1948 pixels[y][x] = (x + y) % 5 ? 0xFF : 0x00;
1949 }
1950 }
1951 bitmap.setPixels(pixels);
1952 for (auto style : { SkPaint::kFill_Style,
1953 SkPaint::kStroke_Style,
1954 SkPaint::kStrokeAndFill_Style }) {
1955 paint.setStyle(style);
1956 canvas->drawLine(10, 10, 60, 60, paint);
1957 canvas->drawRect({80, 10, 130, 60}, paint);
1958 canvas->drawRegion(region, paint);
1959 canvas->drawBitmap(bitmap, 200, 10, &paint);
1960 canvas->translate(0, 80);
1961 }
1962 }
1963 ##
1964
1965#SeeAlso Style getStyle
1966##
1967
1968#SeeAlso Path_Fill_Type Path_Effect Style_Fill Style_Stroke
Cary Clark08895c42018-02-01 09:37:32 -05001969#Subtopic Style ##
Cary Clark8032b982017-07-28 11:04:54 -04001970
1971# ------------------------------------------------------------------------------
Cary Clark08895c42018-02-01 09:37:32 -05001972#Subtopic Stroke_Width
1973#Line # thickness perpendicular to geometry ##
Cary Clark8032b982017-07-28 11:04:54 -04001974
1975Stroke_Width sets the width for stroking. The width is the thickness
Herb Derbyfcac00f2018-05-01 11:57:56 -04001976of the stroke perpendicular to the path direction when the paint style is
Cary Clark8032b982017-07-28 11:04:54 -04001977set to kStroke_Style or kStrokeAndFill_Style.
1978
1979When width is greater than zero, the stroke encompasses as many pixels partially
1980or fully as needed. When the width equals zero, the paint enables hairlines;
Herb Derbyfcac00f2018-05-01 11:57:56 -04001981the stroke is always one pixel wide.
Cary Clark8032b982017-07-28 11:04:54 -04001982
Cary Clarkbc5697d2017-10-04 14:31:33 -04001983The stroke dimensions are scaled by the canvas matrix, but Hairline stroke
Cary Clark8032b982017-07-28 11:04:54 -04001984remains one pixel wide regardless of scaling.
1985
1986The default width for the paint is zero.
1987
1988#Example
1989#Height 170
1990 #Platform raster gpu
1991 #Description
Herb Derbyfcac00f2018-05-01 11:57:56 -04001992 The pixels hit to represent thin lines vary with the angle of the
Cary Clarkbc5697d2017-10-04 14:31:33 -04001993 line and the platform implementation.
Cary Clark8032b982017-07-28 11:04:54 -04001994 ##
1995 void draw(SkCanvas* canvas) {
1996 SkPaint paint;
Herb Derbyfcac00f2018-05-01 11:57:56 -04001997 for (bool antialias : { false, true }) {
Cary Clark8032b982017-07-28 11:04:54 -04001998 paint.setAntiAlias(antialias);
1999 for (int width = 0; width <= 4; ++width) {
2000 SkScalar offset = antialias * 100 + width * 20;
2001 paint.setStrokeWidth(width * 0.25f);
2002 canvas->drawLine(10 + offset, 10, 20 + offset, 60, paint);
2003 canvas->drawLine(10 + offset, 110, 60 + offset, 160, paint);
2004 }
2005 }
2006 }
2007##
2008
2009#Method SkScalar getStrokeWidth() const
2010
Cary Clarkab2621d2018-01-30 10:08:57 -05002011#In Stroke_Width
2012#Line # returns thickness of the stroke ##
Cary Clark8032b982017-07-28 11:04:54 -04002013 Returns the thickness of the pen used by Paint to
2014 outline the shape.
2015
2016 #Return zero for Hairline, greater than zero for pen thickness ##
Herb Derbyfcac00f2018-05-01 11:57:56 -04002017
Cary Clark8032b982017-07-28 11:04:54 -04002018 #Example
2019 SkPaint paint;
2020 SkDebugf("0 %c= paint.getStrokeWidth()\n", 0 == paint.getStrokeWidth() ? '=' : '!');
2021
2022 #StdOut
2023 0 == paint.getStrokeWidth()
2024 ##
2025 ##
2026
2027##
2028
2029#Method void setStrokeWidth(SkScalar width)
2030
Cary Clarkab2621d2018-01-30 10:08:57 -05002031#In Stroke_Width
2032#Line # sets thickness of the stroke ##
Cary Clark8032b982017-07-28 11:04:54 -04002033 Sets the thickness of the pen used by the paint to
Herb Derbyfcac00f2018-05-01 11:57:56 -04002034 outline the shape.
2035 Has no effect if width is less than zero.
Cary Clark8032b982017-07-28 11:04:54 -04002036
Herb Derbyfcac00f2018-05-01 11:57:56 -04002037 #Param width zero thickness for Hairline; greater than zero for pen thickness
Cary Clark8032b982017-07-28 11:04:54 -04002038 ##
2039
2040 #Example
2041 SkPaint paint;
2042 paint.setStrokeWidth(5);
2043 paint.setStrokeWidth(-1);
2044 SkDebugf("5 %c= paint.getStrokeWidth()\n", 5 == paint.getStrokeWidth() ? '=' : '!');
2045
2046 #StdOut
2047 5 == paint.getStrokeWidth()
2048 ##
2049 ##
2050
2051##
2052
Cary Clark08895c42018-02-01 09:37:32 -05002053#Subtopic Stroke_Width ##
Cary Clark8032b982017-07-28 11:04:54 -04002054# ------------------------------------------------------------------------------
Cary Clark08895c42018-02-01 09:37:32 -05002055#Subtopic Miter_Limit
2056#Line # maximum length of stroked corners ##
Cary Clark8032b982017-07-28 11:04:54 -04002057
2058Miter_Limit specifies the maximum miter length,
2059relative to the stroke width.
2060
2061Miter_Limit is used when the Stroke_Join
2062is set to kMiter_Join, and the Style is either kStroke_Style
2063or kStrokeAndFill_Style.
2064
2065If the miter at a corner exceeds this limit, kMiter_Join
2066is replaced with kBevel_Join.
2067
2068Miter_Limit can be computed from the corner angle:
2069
2070#Formula
2071 miter limit = 1 / sin ( angle / 2 )
2072#Formula ##
2073
2074Miter_Limit default value is 4.
2075The default may be changed at compile time by setting SkPaintDefaults_MiterLimit
Cary Clarkce101242017-09-01 15:51:02 -04002076in "SkUserConfig.h" or as a define supplied by the build environment.
Cary Clark8032b982017-07-28 11:04:54 -04002077
2078Here are some miter limits and the angles that triggers them.
2079#Table
2080#Legend
2081 # miter limit # angle in degrees ##
2082#Legend ##
2083 # 10 # 11.48 ##
2084 # 9 # 12.76 ##
2085 # 8 # 14.36 ##
2086 # 7 # 16.43 ##
2087 # 6 # 19.19 ##
2088 # 5 # 23.07 ##
2089 # 4 # 28.96 ##
2090 # 3 # 38.94 ##
2091 # 2 # 60 ##
2092 # 1 # 180 ##
2093#Table ##
2094
2095#Example
2096 #Height 170
2097 #Width 384
2098 #Description
2099 This example draws a stroked corner and the miter length beneath.
2100 When the miter limit is decreased slightly, the miter join is replaced
2101 by a bevel join.
2102 ##
2103 void draw(SkCanvas* canvas) {
2104 SkPoint pts[] = {{ 10, 50 }, { 110, 80 }, { 10, 110 }};
2105 SkVector v[] = { pts[0] - pts[1], pts[2] - pts[1] };
2106 SkScalar angle1 = SkScalarATan2(v[0].fY, v[0].fX);
2107 SkScalar angle2 = SkScalarATan2(v[1].fY, v[1].fX);
2108 const SkScalar strokeWidth = 20;
2109 SkScalar miterLimit = 1 / SkScalarSin((angle2 - angle1) / 2);
2110 SkScalar miterLength = strokeWidth * miterLimit;
2111 SkPath path;
2112 path.moveTo(pts[0]);
2113 path.lineTo(pts[1]);
2114 path.lineTo(pts[2]);
2115 SkPaint paint; // set to default kMiter_Join
2116 paint.setAntiAlias(true);
2117 paint.setStyle(SkPaint::kStroke_Style);
2118 paint.setStrokeMiter(miterLimit);
2119 paint.setStrokeWidth(strokeWidth);
2120 canvas->drawPath(path, paint);
2121 paint.setStrokeWidth(1);
2122 canvas->drawLine(pts[1].fX - miterLength / 2, pts[1].fY + 50,
2123 pts[1].fX + miterLength / 2, pts[1].fY + 50, paint);
2124 canvas->translate(200, 0);
2125 miterLimit *= 0.99f;
2126 paint.setStrokeMiter(miterLimit);
2127 paint.setStrokeWidth(strokeWidth);
2128 canvas->drawPath(path, paint);
2129 paint.setStrokeWidth(1);
2130 canvas->drawLine(pts[1].fX - miterLength / 2, pts[1].fY + 50,
2131 pts[1].fX + miterLength / 2, pts[1].fY + 50, paint);
2132 }
2133##
2134
2135#Method SkScalar getStrokeMiter() const
2136
Cary Clarkab2621d2018-01-30 10:08:57 -05002137#In Miter_Limit
2138#Line # returns Miter_Limit, angles with sharp corners ##
Cary Clark8032b982017-07-28 11:04:54 -04002139 The limit at which a sharp corner is drawn beveled.
2140
2141 #Return zero and greater Miter_Limit ##
2142
2143 #Example
2144 SkPaint paint;
2145 SkDebugf("default miter limit == %g\n", paint.getStrokeMiter());
2146
2147 #StdOut
2148 default miter limit == 4
2149 ##
2150 ##
2151
2152 #SeeAlso Miter_Limit setStrokeMiter Join
2153
2154##
2155
2156#Method void setStrokeMiter(SkScalar miter)
2157
Cary Clarkab2621d2018-01-30 10:08:57 -05002158#In Miter_Limit
2159#Line # sets Miter_Limit, angles with sharp corners ##
Cary Clark8032b982017-07-28 11:04:54 -04002160 The limit at which a sharp corner is drawn beveled.
2161 Valid values are zero and greater.
2162 Has no effect if miter is less than zero.
2163
2164 #Param miter zero and greater Miter_Limit
2165 ##
2166
2167 #Example
2168 SkPaint paint;
2169 paint.setStrokeMiter(8);
2170 paint.setStrokeMiter(-1);
2171 SkDebugf("default miter limit == %g\n", paint.getStrokeMiter());
2172
2173 #StdOut
2174 default miter limit == 8
2175 ##
2176 ##
2177
2178 #SeeAlso Miter_Limit getStrokeMiter Join
2179
2180##
2181
Cary Clark08895c42018-02-01 09:37:32 -05002182#Subtopic Miter_Limit ##
Cary Clark8032b982017-07-28 11:04:54 -04002183# ------------------------------------------------------------------------------
Cary Clark08895c42018-02-01 09:37:32 -05002184#Subtopic Stroke_Cap
2185#Line # decorations at ends of open strokes ##
Cary Clark8032b982017-07-28 11:04:54 -04002186
2187#Enum Cap
Cary Clark08895c42018-02-01 09:37:32 -05002188#Line # start and end geometry on stroked shapes ##
Cary Clark8032b982017-07-28 11:04:54 -04002189
2190#Code
2191 enum Cap {
2192 kButt_Cap,
2193 kRound_Cap,
2194 kSquare_Cap,
2195
2196 kLast_Cap = kSquare_Cap,
Cary Clarkbad5ad72017-08-03 17:14:08 -04002197 kDefault_Cap = kButt_Cap,
Cary Clark8032b982017-07-28 11:04:54 -04002198 };
Cary Clark6fc50412017-09-21 12:31:06 -04002199
Cary Clark8032b982017-07-28 11:04:54 -04002200 static constexpr int kCapCount = kLast_Cap + 1;
2201##
2202
2203Stroke_Cap draws at the beginning and end of an open Path_Contour.
2204
2205 #Const kButt_Cap 0
Cary Clark682c58d2018-05-16 07:07:07 -04002206 #Line # no stroke extension ##
Cary Clark8032b982017-07-28 11:04:54 -04002207 Does not extend the stroke past the beginning or the end.
2208 ##
2209 #Const kRound_Cap 1
Cary Clark682c58d2018-05-16 07:07:07 -04002210 #Line # adds circle ##
Cary Clark8032b982017-07-28 11:04:54 -04002211 Adds a circle with a diameter equal to Stroke_Width at the beginning
2212 and end.
2213 ##
2214 #Const kSquare_Cap 2
Cary Clark682c58d2018-05-16 07:07:07 -04002215 #Line # adds square ##
Cary Clark8032b982017-07-28 11:04:54 -04002216 Adds a square with sides equal to Stroke_Width at the beginning
2217 and end. The square sides are parallel to the initial and final direction
2218 of the stroke.
2219 ##
2220 #Const kLast_Cap 2
Cary Clark682c58d2018-05-16 07:07:07 -04002221 #Line # largest Stroke_Cap value ##
Cary Clark8032b982017-07-28 11:04:54 -04002222 Equivalent to the largest value for Stroke_Cap.
2223 ##
2224 #Const kDefault_Cap 0
Cary Clark682c58d2018-05-16 07:07:07 -04002225 #Line # equivalent to kButt_Cap ##
Cary Clark8032b982017-07-28 11:04:54 -04002226 Stroke_Cap is set to kButt_Cap by default.
2227 ##
2228
2229 #Const kCapCount 3
Cary Clark682c58d2018-05-16 07:07:07 -04002230 #Line # number of different Stroke_Cap values defined ##
Cary Clark8032b982017-07-28 11:04:54 -04002231 May be used to verify that Stroke_Cap is a legal value.
2232 ##
2233#Enum ##
2234
Herb Derbyfcac00f2018-05-01 11:57:56 -04002235Stroke describes the area covered by a pen of Stroke_Width as it
Cary Clarkbc5697d2017-10-04 14:31:33 -04002236follows the Path_Contour, moving parallel to the contour direction.
Cary Clark8032b982017-07-28 11:04:54 -04002237
2238If the Path_Contour is not terminated by SkPath::kClose_Verb, the contour has a
2239visible beginning and end.
2240
2241Path_Contour may start and end at the same point; defining Zero_Length_Contour.
2242
2243kButt_Cap and Zero_Length_Contour is not drawn.
Herb Derbyfcac00f2018-05-01 11:57:56 -04002244kRound_Cap and Zero_Length_Contour draws a circle of diameter Stroke_Width
Cary Clark8032b982017-07-28 11:04:54 -04002245at the contour point.
2246kSquare_Cap and Zero_Length_Contour draws an upright square with a side of
2247Stroke_Width at the contour point.
2248
2249Stroke_Cap is kButt_Cap by default.
2250
2251#Example
Cary Clark2ade9972017-11-02 17:49:34 -04002252#Height 200
Cary Clark8032b982017-07-28 11:04:54 -04002253 SkPaint paint;
2254 paint.setStyle(SkPaint::kStroke_Style);
2255 paint.setStrokeWidth(20);
2256 SkPath path;
2257 path.moveTo(30, 30);
2258 path.lineTo(30, 30);
2259 path.moveTo(70, 30);
2260 path.lineTo(90, 40);
2261 for (SkPaint::Cap c : { SkPaint::kButt_Cap, SkPaint::kRound_Cap, SkPaint::kSquare_Cap } ) {
2262 paint.setStrokeCap(c);
2263 canvas->drawPath(path, paint);
2264 canvas->translate(0, 70);
2265 }
2266##
2267
2268#Method Cap getStrokeCap() const
2269
Cary Clarkab2621d2018-01-30 10:08:57 -05002270#In Stroke_Cap
2271#Line # returns Cap, the area drawn at path ends ##
Cary Clark8032b982017-07-28 11:04:54 -04002272 The geometry drawn at the beginning and end of strokes.
2273
2274 #Return one of: kButt_Cap, kRound_Cap, kSquare_Cap ##
2275
2276 #Example
2277 SkPaint paint;
2278 SkDebugf("kButt_Cap %c= default stroke cap\n",
2279 SkPaint::kButt_Cap == paint.getStrokeCap() ? '=' : '!');
2280
2281 #StdOut
2282 kButt_Cap == default stroke cap
2283 ##
2284 ##
2285
2286 #SeeAlso Stroke_Cap setStrokeCap
2287##
2288
2289#Method void setStrokeCap(Cap cap)
2290
Cary Clarkab2621d2018-01-30 10:08:57 -05002291#In Stroke_Cap
2292#Line # sets Cap, the area drawn at path ends ##
Cary Clark8032b982017-07-28 11:04:54 -04002293 The geometry drawn at the beginning and end of strokes.
2294
2295 #Param cap one of: kButt_Cap, kRound_Cap, kSquare_Cap;
2296 has no effect if cap is not valid
Herb Derbyfcac00f2018-05-01 11:57:56 -04002297 ##
Cary Clark8032b982017-07-28 11:04:54 -04002298
2299 #Example
2300 SkPaint paint;
2301 paint.setStrokeCap(SkPaint::kRound_Cap);
2302 paint.setStrokeCap((SkPaint::Cap) SkPaint::kCapCount);
2303 SkDebugf("kRound_Cap %c= paint.getStrokeCap()\n",
2304 SkPaint::kRound_Cap == paint.getStrokeCap() ? '=' : '!');
Herb Derbyfcac00f2018-05-01 11:57:56 -04002305
Cary Clark8032b982017-07-28 11:04:54 -04002306 #StdOut
2307 kRound_Cap == paint.getStrokeCap()
2308 ##
2309 ##
2310
2311 #SeeAlso Stroke_Cap getStrokeCap
2312##
2313
Cary Clark08895c42018-02-01 09:37:32 -05002314#Subtopic Stroke_Cap ##
Cary Clark8032b982017-07-28 11:04:54 -04002315# ------------------------------------------------------------------------------
Cary Clark08895c42018-02-01 09:37:32 -05002316#Subtopic Stroke_Join
2317#Line # decoration at corners of strokes ##
Cary Clark8032b982017-07-28 11:04:54 -04002318
2319Stroke_Join draws at the sharp corners of an open or closed Path_Contour.
2320
Herb Derbyfcac00f2018-05-01 11:57:56 -04002321Stroke describes the area covered by a pen of Stroke_Width as it
Cary Clarkbc5697d2017-10-04 14:31:33 -04002322follows the Path_Contour, moving parallel to the contour direction.
Cary Clark8032b982017-07-28 11:04:54 -04002323
2324If the contour direction changes abruptly, because the tangent direction leading
2325to the end of a curve within the contour does not match the tangent direction of
2326the following curve, the pair of curves meet at Stroke_Join.
2327
2328#Example
Cary Clark2ade9972017-11-02 17:49:34 -04002329#Height 200
Cary Clarka560c472017-11-27 10:44:06 -05002330 SkPaint paint;
2331 paint.setStyle(SkPaint::kStroke_Style);
2332 paint.setStrokeWidth(20);
2333 SkPath path;
2334 path.moveTo(30, 20);
2335 path.lineTo(40, 40);
2336 path.conicTo(70, 20, 100, 20, .707f);
2337 for (SkPaint::Join j : { SkPaint::kMiter_Join, SkPaint::kRound_Join, SkPaint::kBevel_Join } ) {
2338 paint.setStrokeJoin(j);
2339 canvas->drawPath(path, paint);
2340 canvas->translate(0, 70);
2341 }
Cary Clark8032b982017-07-28 11:04:54 -04002342##
2343
2344#Enum Join
Cary Clark08895c42018-02-01 09:37:32 -05002345#Line # corner geometry on stroked shapes ##
Cary Clark8032b982017-07-28 11:04:54 -04002346#Code
2347 enum Join {
2348 kMiter_Join,
2349 kRound_Join,
2350 kBevel_Join,
2351
2352 kLast_Join = kBevel_Join,
Cary Clarkbad5ad72017-08-03 17:14:08 -04002353 kDefault_Join = kMiter_Join,
Cary Clark8032b982017-07-28 11:04:54 -04002354 };
Cary Clark6fc50412017-09-21 12:31:06 -04002355
Cary Clark8032b982017-07-28 11:04:54 -04002356 static constexpr int kJoinCount = kLast_Join + 1;
2357##
2358
Cary Clark1eace2d2017-07-31 07:52:43 -04002359Join specifies how corners are drawn when a shape is stroked. Join
Cary Clark8032b982017-07-28 11:04:54 -04002360affects the four corners of a stroked rectangle, and the connected segments in a
2361stroked path.
2362
2363Choose miter join to draw sharp corners. Choose round join to draw a circle with a
2364radius equal to the stroke width on top of the corner. Choose bevel join to minimally
2365connect the thick strokes.
2366
Herb Derbyfcac00f2018-05-01 11:57:56 -04002367The fill path constructed to describe the stroked path respects the join setting but may
Cary Clark8032b982017-07-28 11:04:54 -04002368not contain the actual join. For instance, a fill path constructed with round joins does
2369not necessarily include circles at each connected segment.
2370
2371#Const kMiter_Join 0
Cary Clark682c58d2018-05-16 07:07:07 -04002372#Line # extends to Miter_Limit ##
Cary Clark8032b982017-07-28 11:04:54 -04002373 Extends the outside corner to the extent allowed by Miter_Limit.
2374 If the extension exceeds Miter_Limit, kBevel_Join is used instead.
2375##
2376
2377#Const kRound_Join 1
Cary Clark682c58d2018-05-16 07:07:07 -04002378#Line # adds circle ##
Cary Clark8032b982017-07-28 11:04:54 -04002379 Adds a circle with a diameter of Stroke_Width at the sharp corner.
2380##
2381
2382#Const kBevel_Join 2
Cary Clark682c58d2018-05-16 07:07:07 -04002383#Line # connects outside edges ##
Cary Clark8032b982017-07-28 11:04:54 -04002384 Connects the outside edges of the sharp corner.
2385##
2386
2387#Const kLast_Join 2
Cary Clark682c58d2018-05-16 07:07:07 -04002388#Line # equivalent to the largest value for Stroke_Join ##
Cary Clark8032b982017-07-28 11:04:54 -04002389##
2390
2391#Const kDefault_Join 1
Cary Clark682c58d2018-05-16 07:07:07 -04002392#Line # equivalent to kMiter_Join ##
Herb Derbyfcac00f2018-05-01 11:57:56 -04002393 Stroke_Join is set to kMiter_Join by default.
Cary Clark8032b982017-07-28 11:04:54 -04002394##
2395
2396#Const kJoinCount 3
Cary Clark682c58d2018-05-16 07:07:07 -04002397#Line # number of different Stroke_Join values defined ##
Cary Clark8032b982017-07-28 11:04:54 -04002398 May be used to verify that Stroke_Join is a legal value.
2399##
2400
2401#Example
2402#Width 462
2403void draw(SkCanvas* canvas) {
2404 SkPath path;
2405 path.moveTo(10, 50);
2406 path.quadTo(35, 110, 60, 210);
2407 path.quadTo(105, 110, 130, 10);
2408 SkPaint paint; // set to default kMiter_Join
2409 paint.setAntiAlias(true);
2410 paint.setStyle(SkPaint::kStroke_Style);
2411 paint.setStrokeWidth(20);
2412 canvas->drawPath(path, paint);
2413 canvas->translate(150, 0);
2414 paint.setStrokeJoin(SkPaint::kBevel_Join);
2415 canvas->drawPath(path, paint);
2416 canvas->translate(150, 0);
2417 paint.setStrokeJoin(SkPaint::kRound_Join);
2418 canvas->drawPath(path, paint);
2419}
2420##
2421
2422#SeeAlso setStrokeJoin getStrokeJoin setStrokeMiter getStrokeMiter
2423
2424#Enum ##
2425
2426#Method Join getStrokeJoin() const
2427
Cary Clarkab2621d2018-01-30 10:08:57 -05002428#In Stroke_Join
2429#Line # returns Join, geometry on path corners ##
Cary Clark0c5f5462017-12-15 11:21:51 -05002430 The geometry drawn at the corners of strokes.
Cary Clark8032b982017-07-28 11:04:54 -04002431
2432 #Return one of: kMiter_Join, kRound_Join, kBevel_Join ##
2433
2434 #Example
2435 SkPaint paint;
2436 SkDebugf("kMiter_Join %c= default stroke join\n",
2437 SkPaint::kMiter_Join == paint.getStrokeJoin() ? '=' : '!');
2438
2439 #StdOut
2440 kMiter_Join == default stroke join
2441 ##
2442 ##
2443
2444 #SeeAlso Stroke_Join setStrokeJoin
2445##
2446
2447#Method void setStrokeJoin(Join join)
2448
Cary Clarkab2621d2018-01-30 10:08:57 -05002449#In Stroke_Join
2450#Line # sets Join, geometry on path corners ##
Cary Clark0c5f5462017-12-15 11:21:51 -05002451 The geometry drawn at the corners of strokes.
Cary Clark8032b982017-07-28 11:04:54 -04002452
2453 #Param join one of: kMiter_Join, kRound_Join, kBevel_Join;
Herb Derbyfcac00f2018-05-01 11:57:56 -04002454 otherwise, has no effect
Cary Clark8032b982017-07-28 11:04:54 -04002455 ##
2456
2457 #Example
2458 SkPaint paint;
2459 paint.setStrokeJoin(SkPaint::kMiter_Join);
2460 paint.setStrokeJoin((SkPaint::Join) SkPaint::kJoinCount);
2461 SkDebugf("kMiter_Join %c= paint.getStrokeJoin()\n",
2462 SkPaint::kMiter_Join == paint.getStrokeJoin() ? '=' : '!');
2463
2464 #StdOut
2465 kMiter_Join == paint.getStrokeJoin()
2466 ##
2467 ##
2468
2469 #SeeAlso Stroke_Join getStrokeJoin
2470##
2471
2472#SeeAlso Miter_Limit
2473
Cary Clark08895c42018-02-01 09:37:32 -05002474#Subtopic Stroke_Join ##
Cary Clark8032b982017-07-28 11:04:54 -04002475# ------------------------------------------------------------------------------
Cary Clark08895c42018-02-01 09:37:32 -05002476#Subtopic Fill_Path
2477#Line # make Path from Path_Effect, stroking ##
Cary Clark8032b982017-07-28 11:04:54 -04002478
2479Fill_Path creates a Path by applying the Path_Effect, followed by the Style_Stroke.
2480
2481If Paint contains Path_Effect, Path_Effect operates on the source Path; the result
2482replaces the destination Path. Otherwise, the source Path is replaces the
2483destination Path.
2484
2485Fill Path can request the Path_Effect to restrict to a culling rectangle, but
2486the Path_Effect is not required to do so.
2487
Herb Derbyfcac00f2018-05-01 11:57:56 -04002488If Style is kStroke_Style or kStrokeAndFill_Style,
Cary Clark8032b982017-07-28 11:04:54 -04002489and Stroke_Width is greater than zero, the Stroke_Width, Stroke_Cap, Stroke_Join,
2490and Miter_Limit operate on the destination Path, replacing it.
2491
Herb Derbyfcac00f2018-05-01 11:57:56 -04002492Fill Path can specify the precision used by Stroke_Width to approximate the stroke geometry.
Cary Clark8032b982017-07-28 11:04:54 -04002493
2494If the Style is kStroke_Style and the Stroke_Width is zero, getFillPath
2495returns false since Hairline has no filled equivalent.
2496
2497#Method bool getFillPath(const SkPath& src, SkPath* dst, const SkRect* cullRect,
2498 SkScalar resScale = 1) const
Cary Clarkab2621d2018-01-30 10:08:57 -05002499#In Fill_Path
2500#Line # returns fill path equivalent to stroke ##
Cary Clark8032b982017-07-28 11:04:54 -04002501
2502 The filled equivalent of the stroked path.
2503
2504 #Param src Path read to create a filled version ##
2505 #Param dst resulting Path; may be the same as src, but may not be nullptr ##
2506 #Param cullRect optional limit passed to Path_Effect ##
2507 #Param resScale if > 1, increase precision, else if (0 < res < 1) reduce precision
2508 to favor speed and size
2509 ##
2510 #Return true if the path represents Style_Fill, or false if it represents Hairline ##
2511
2512 #Example
2513 #Height 192
2514 #Description
Cary Clarkce101242017-09-01 15:51:02 -04002515 A very small Quad stroke is turned into a filled path with increasing levels of precision.
Herb Derbyfcac00f2018-05-01 11:57:56 -04002516 At the lowest precision, the Quad stroke is approximated by a rectangle.
Cary Clark8032b982017-07-28 11:04:54 -04002517 At the highest precision, the filled path has high fidelity compared to the original stroke.
2518 ##
2519 void draw(SkCanvas* canvas) {
2520 SkPaint strokePaint;
2521 strokePaint.setAntiAlias(true);
2522 strokePaint.setStyle(SkPaint::kStroke_Style);
2523 strokePaint.setStrokeWidth(.1f);
2524 SkPath strokePath;
2525 strokePath.moveTo(.08f, .08f);
2526 strokePath.quadTo(.09f, .08f, .17f, .17f);
2527 SkPath fillPath;
2528 SkPaint outlinePaint(strokePaint);
2529 outlinePaint.setStrokeWidth(2);
2530 SkMatrix scale = SkMatrix::MakeScale(300, 300);
2531 for (SkScalar precision : { 0.01f, .1f, 1.f, 10.f, 100.f } ) {
2532 strokePaint.getFillPath(strokePath, &fillPath, nullptr, precision);
2533 fillPath.transform(scale);
2534 canvas->drawPath(fillPath, outlinePaint);
2535 canvas->translate(60, 0);
2536 if (1.f == precision) canvas->translate(-180, 100);
2537 }
2538 strokePath.transform(scale);
2539 strokePaint.setStrokeWidth(30);
2540 canvas->drawPath(strokePath, strokePaint);
2541 }
2542 ##
2543
2544##
2545
2546#Method bool getFillPath(const SkPath& src, SkPath* dst) const
2547
Cary Clarkab2621d2018-01-30 10:08:57 -05002548#In Fill_Path
Cary Clark8032b982017-07-28 11:04:54 -04002549 The filled equivalent of the stroked path.
2550
2551 Replaces dst with the src path modified by Path_Effect and Style_Stroke.
2552 Path_Effect, if any, is not culled. Stroke_Width is created with default precision.
2553
2554 #Param src Path read to create a filled version ##
2555 #Param dst resulting Path dst may be the same as src, but may not be nullptr ##
2556 #Return true if the path represents Style_Fill, or false if it represents Hairline ##
2557
2558 #Example
2559 #Height 128
2560 void draw(SkCanvas* canvas) {
2561 SkPaint paint;
2562 paint.setStyle(SkPaint::kStroke_Style);
2563 paint.setStrokeWidth(10);
2564 SkPath strokePath;
2565 strokePath.moveTo(20, 20);
2566 strokePath.lineTo(100, 100);
2567 canvas->drawPath(strokePath, paint);
2568 SkPath fillPath;
2569 paint.getFillPath(strokePath, &fillPath);
2570 paint.setStrokeWidth(2);
2571 canvas->translate(40, 0);
2572 canvas->drawPath(fillPath, paint);
2573 }
2574 ##
2575
2576##
2577
2578#SeeAlso Style_Stroke Stroke_Width Path_Effect
2579
Cary Clark08895c42018-02-01 09:37:32 -05002580#Subtopic Fill_Path ##
Cary Clark8032b982017-07-28 11:04:54 -04002581# ------------------------------------------------------------------------------
Cary Clark08895c42018-02-01 09:37:32 -05002582#Subtopic Shader_Methods
2583#Line # get and set Shader ##
Cary Clark8032b982017-07-28 11:04:54 -04002584
2585Shader defines the colors used when drawing a shape.
2586Shader may be an image, a gradient, or a computed fill.
Herb Derbyfcac00f2018-05-01 11:57:56 -04002587If Paint has no Shader, then Color fills the shape.
Cary Clark8032b982017-07-28 11:04:54 -04002588
2589Shader is modulated by Color_Alpha component of Color.
2590If Shader object defines only Color_Alpha, then Color modulated by Color_Alpha describes
2591the fill.
2592
2593The drawn transparency can be modified without altering Shader, by changing Color_Alpha.
2594
2595#Example
2596void draw(SkCanvas* canvas) {
2597 SkPaint paint;
2598 SkPoint center = { 50, 50 };
2599 SkScalar radius = 50;
2600 const SkColor colors[] = { 0xFFFFFFFF, 0xFF000000 };
2601 paint.setShader(SkGradientShader::MakeRadial(center, radius, colors,
2602 nullptr, SK_ARRAY_COUNT(colors), SkShader::kClamp_TileMode));
2603 for (SkScalar a : { 0.3f, 0.6f, 1.0f } ) {
2604 paint.setAlpha((int) (a * 255));
2605 canvas->drawCircle(center.fX, center.fY, radius, paint);
2606 canvas->translate(70, 70);
2607 }
2608}
2609##
2610
2611If Shader generates only Color_Alpha then all components of Color modulate the output.
2612
2613#Example
2614void draw(SkCanvas* canvas) {
2615 SkPaint paint;
2616 SkBitmap bitmap;
2617 bitmap.setInfo(SkImageInfo::MakeA8(5, 1), 5); // bitmap only contains alpha
2618 uint8_t pixels[5] = { 0x22, 0x55, 0x88, 0xBB, 0xFF };
2619 bitmap.setPixels(pixels);
Herb Derbyfcac00f2018-05-01 11:57:56 -04002620 paint.setShader(SkShader::MakeBitmapShader(bitmap,
Cary Clark8032b982017-07-28 11:04:54 -04002621 SkShader::kMirror_TileMode, SkShader::kMirror_TileMode));
2622 for (SkColor c : { SK_ColorRED, SK_ColorBLUE, SK_ColorGREEN } ) {
2623 paint.setColor(c); // all components in color affect shader
2624 canvas->drawCircle(50, 50, 50, paint);
2625 canvas->translate(70, 70);
2626 }
2627}
2628##
2629
2630#Method SkShader* getShader() const
2631
Cary Clarkab2621d2018-01-30 10:08:57 -05002632#In Shader_Methods
2633#Line # returns Shader, multiple drawing colors; gradients ##
Cary Clark8032b982017-07-28 11:04:54 -04002634 Optional colors used when filling a path, such as a gradient.
2635
2636 Does not alter Shader Reference_Count.
Herb Derbyfcac00f2018-05-01 11:57:56 -04002637
Cary Clark8032b982017-07-28 11:04:54 -04002638 #Return Shader if previously set, nullptr otherwise ##
2639
2640 #Example
2641 void draw(SkCanvas* canvas) {
2642 SkPaint paint;
2643 SkDebugf("nullptr %c= shader\n", paint.getShader() ? '!' : '=');
2644 paint.setShader(SkShader::MakeEmptyShader());
2645 SkDebugf("nullptr %c= shader\n", paint.getShader() ? '!' : '=');
2646 }
2647
2648 #StdOut
2649 nullptr == shader
2650 nullptr != shader
2651 ##
2652 ##
2653
2654##
2655
2656#Method sk_sp<SkShader> refShader() const
2657
Cary Clarkab2621d2018-01-30 10:08:57 -05002658#In Shader_Methods
2659#Line # references Shader, multiple drawing colors; gradients ##
Cary Clark8032b982017-07-28 11:04:54 -04002660 Optional colors used when filling a path, such as a gradient.
2661
2662 Increases Shader Reference_Count by one.
2663
2664 #Return Shader if previously set, nullptr otherwise ##
2665
2666 #Example
2667 void draw(SkCanvas* canvas) {
2668 SkPaint paint1, paint2;
2669 paint1.setShader(SkShader::MakeEmptyShader());
2670 SkDebugf("shader unique: %s\n", paint1.getShader()->unique() ? "true" : "false");
2671 paint2.setShader(paint1.refShader());
2672 SkDebugf("shader unique: %s\n", paint1.getShader()->unique() ? "true" : "false");
2673 }
2674
2675 #StdOut
2676 shader unique: true
2677 shader unique: false
2678 ##
2679 ##
2680
2681##
2682
2683#Method void setShader(sk_sp<SkShader> shader)
2684
Cary Clarkab2621d2018-01-30 10:08:57 -05002685#In Shader_Methods
2686#Line # sets Shader, multiple drawing colors; gradients ##
Cary Clark8032b982017-07-28 11:04:54 -04002687 Optional colors used when filling a path, such as a gradient.
2688
Cary Clarkd0530ba2017-09-14 11:25:39 -04002689 Sets Shader to shader, decreasing Reference_Count of the previous Shader.
Cary Clark6fc50412017-09-21 12:31:06 -04002690 Increments shader Reference_Count by one.
Cary Clark8032b982017-07-28 11:04:54 -04002691
2692 #Param shader how geometry is filled with color; if nullptr, Color is used instead ##
2693
2694 #Example
2695 #Height 64
2696 void draw(SkCanvas* canvas) {
2697 SkPaint paint;
2698 paint.setColor(SK_ColorBLUE);
2699 paint.setShader(SkShader::MakeColorShader(SK_ColorRED));
2700 canvas->drawRect(SkRect::MakeWH(40, 40), paint);
2701 paint.setShader(nullptr);
2702 canvas->translate(50, 0);
2703 canvas->drawRect(SkRect::MakeWH(40, 40), paint);
2704 }
2705 ##
2706
2707##
2708
Cary Clark08895c42018-02-01 09:37:32 -05002709#Subtopic Shader_Methods ##
Cary Clark8032b982017-07-28 11:04:54 -04002710# ------------------------------------------------------------------------------
Cary Clark08895c42018-02-01 09:37:32 -05002711#Subtopic Color_Filter_Methods
2712#Line # get and set Color_Filter ##
Cary Clark8032b982017-07-28 11:04:54 -04002713
2714Color_Filter alters the color used when drawing a shape.
2715Color_Filter may apply Blend_Mode, transform the color through a matrix, or composite multiple filters.
2716If Paint has no Color_Filter, the color is unaltered.
2717
2718The drawn transparency can be modified without altering Color_Filter, by changing Color_Alpha.
2719
2720#Example
2721#Height 128
2722void draw(SkCanvas* canvas) {
2723 SkPaint paint;
2724 paint.setColorFilter(SkColorMatrixFilter::MakeLightingFilter(0xFFFFFF, 0xFF0000));
2725 for (SkColor c : { SK_ColorBLACK, SK_ColorGREEN } ) {
2726 paint.setColor(c);
2727 canvas->drawRect(SkRect::MakeXYWH(10, 10, 50, 50), paint);
2728 paint.setAlpha(0x80);
2729 canvas->drawRect(SkRect::MakeXYWH(60, 60, 50, 50), paint);
2730 canvas->translate(100, 0);
2731 }
2732}
2733##
2734
2735#Method SkColorFilter* getColorFilter() const
2736
Cary Clarkab2621d2018-01-30 10:08:57 -05002737#In Color_Filter_Methods
2738#Line # returns Color_Filter, how colors are altered ##
Cary Clark8032b982017-07-28 11:04:54 -04002739 Returns Color_Filter if set, or nullptr.
2740 Does not alter Color_Filter Reference_Count.
Herb Derbyfcac00f2018-05-01 11:57:56 -04002741
Cary Clark8032b982017-07-28 11:04:54 -04002742 #Return Color_Filter if previously set, nullptr otherwise ##
2743
2744 #Example
2745 void draw(SkCanvas* canvas) {
2746 SkPaint paint;
2747 SkDebugf("nullptr %c= color filter\n", paint.getColorFilter() ? '!' : '=');
2748 paint.setColorFilter(SkColorFilter::MakeModeFilter(SK_ColorLTGRAY, SkBlendMode::kSrcIn));
2749 SkDebugf("nullptr %c= color filter\n", paint.getColorFilter() ? '!' : '=');
2750 }
2751
2752 #StdOut
2753 nullptr == color filter
2754 nullptr != color filter
2755 ##
2756 ##
2757##
2758
2759#Method sk_sp<SkColorFilter> refColorFilter() const
2760
Cary Clarkab2621d2018-01-30 10:08:57 -05002761#In Color_Filter_Methods
2762#Line # references Color_Filter, how colors are altered ##
Cary Clark8032b982017-07-28 11:04:54 -04002763 Returns Color_Filter if set, or nullptr.
2764 Increases Color_Filter Reference_Count by one.
2765
2766 #Return Color_Filter if set, or nullptr ##
2767
2768 #Example
2769 void draw(SkCanvas* canvas) {
2770 SkPaint paint1, paint2;
2771 paint1.setColorFilter(SkColorFilter::MakeModeFilter(0xFFFF0000, SkBlendMode::kSrcATop));
2772 SkDebugf("color filter unique: %s\n", paint1.getColorFilter()->unique() ? "true" : "false");
2773 paint2.setColorFilter(paint1.refColorFilter());
2774 SkDebugf("color filter unique: %s\n", paint1.getColorFilter()->unique() ? "true" : "false");
2775 }
2776
2777 #StdOut
2778 color filter unique: true
2779 color filter unique: false
2780 ##
2781 ##
2782##
2783
2784#Method void setColorFilter(sk_sp<SkColorFilter> colorFilter)
2785
Cary Clarkab2621d2018-01-30 10:08:57 -05002786#In Color_Filter_Methods
2787#Line # sets Color_Filter, alters color ##
Cary Clark6fc50412017-09-21 12:31:06 -04002788Sets Color_Filter to filter, decreasing Reference_Count of the previous
2789Color_Filter. Pass nullptr to clear Color_Filter.
2790
2791Increments filter Reference_Count by one.
Cary Clark8032b982017-07-28 11:04:54 -04002792
2793 #Param colorFilter Color_Filter to apply to subsequent draw ##
2794
2795 #Example
2796 #Height 64
2797 void draw(SkCanvas* canvas) {
2798 SkPaint paint;
2799 paint.setColorFilter(SkColorFilter::MakeModeFilter(SK_ColorLTGRAY, SkBlendMode::kSrcIn));
2800 canvas->drawRect(SkRect::MakeWH(50, 50), paint);
2801 paint.setColorFilter(nullptr);
2802 canvas->translate(70, 0);
2803 canvas->drawRect(SkRect::MakeWH(50, 50), paint);
2804 }
2805 ##
2806
2807##
2808
Cary Clark08895c42018-02-01 09:37:32 -05002809#Subtopic Color_Filter_Methods ##
Cary Clark8032b982017-07-28 11:04:54 -04002810# ------------------------------------------------------------------------------
Cary Clark08895c42018-02-01 09:37:32 -05002811#Subtopic Blend_Mode_Methods
2812#Line # get and set Blend_Mode ##
Cary Clark8032b982017-07-28 11:04:54 -04002813
2814Blend_Mode describes how Color combines with the destination color.
2815The default setting, SkBlendMode::kSrcOver, draws the source color
2816over the destination color.
2817
2818#Example
2819void draw(SkCanvas* canvas) {
2820 SkPaint normal, blender;
2821 normal.setColor(0xFF58a889);
2822 blender.setColor(0xFF8958a8);
2823 canvas->clear(0);
2824 for (SkBlendMode m : { SkBlendMode::kSrcOver, SkBlendMode::kSrcIn, SkBlendMode::kSrcOut } ) {
2825 normal.setBlendMode(SkBlendMode::kSrcOver);
2826 canvas->drawOval(SkRect::MakeXYWH(30, 30, 30, 80), normal);
2827 blender.setBlendMode(m);
2828 canvas->drawOval(SkRect::MakeXYWH(10, 50, 80, 30), blender);
2829 canvas->translate(70, 70);
2830 }
2831}
2832##
2833
2834#SeeAlso Blend_Mode
2835
2836#Method SkBlendMode getBlendMode() const
2837
Cary Clarkab2621d2018-01-30 10:08:57 -05002838#In Blend_Mode_Methods
2839#Line # returns Blend_Mode, how colors combine with Device ##
Cary Clark8032b982017-07-28 11:04:54 -04002840 Returns Blend_Mode.
Cary Clark579985c2017-07-31 11:48:27 -04002841 By default, returns SkBlendMode::kSrcOver.
Cary Clark8032b982017-07-28 11:04:54 -04002842
2843 #Return mode used to combine source color with destination color ##
2844
2845 #Example
2846 void draw(SkCanvas* canvas) {
2847 SkPaint paint;
Herb Derbyfcac00f2018-05-01 11:57:56 -04002848 SkDebugf("kSrcOver %c= getBlendMode\n",
Cary Clark8032b982017-07-28 11:04:54 -04002849 SkBlendMode::kSrcOver == paint.getBlendMode() ? '=' : '!');
2850 paint.setBlendMode(SkBlendMode::kSrc);
Herb Derbyfcac00f2018-05-01 11:57:56 -04002851 SkDebugf("kSrcOver %c= getBlendMode\n",
Cary Clark8032b982017-07-28 11:04:54 -04002852 SkBlendMode::kSrcOver == paint.getBlendMode() ? '=' : '!');
2853 }
2854
2855 #StdOut
2856 kSrcOver == getBlendMode
2857 kSrcOver != getBlendMode
2858 ##
2859 ##
2860
2861##
2862
2863#Method bool isSrcOver() const
2864
Cary Clarkab2621d2018-01-30 10:08:57 -05002865#In Blend_Mode_Methods
2866#Line # returns true if Blend_Mode is SkBlendMode::kSrcOver ##
Cary Clark8032b982017-07-28 11:04:54 -04002867 Returns true if Blend_Mode is SkBlendMode::kSrcOver, the default.
2868
2869 #Return true if Blend_Mode is SkBlendMode::kSrcOver ##
2870
2871 #Example
2872 void draw(SkCanvas* canvas) {
2873 SkPaint paint;
2874 SkDebugf("isSrcOver %c= true\n", paint.isSrcOver() ? '=' : '!');
2875 paint.setBlendMode(SkBlendMode::kSrc);
2876 SkDebugf("isSrcOver %c= true\n", paint.isSrcOver() ? '=' : '!');
2877 }
2878
2879 #StdOut
2880 isSrcOver == true
2881 isSrcOver != true
2882 ##
2883 ##
2884
2885##
2886
2887#Method void setBlendMode(SkBlendMode mode)
2888
Cary Clarkab2621d2018-01-30 10:08:57 -05002889#In Blend_Mode_Methods
2890#Line # sets Blend_Mode, how colors combine with destination ##
Herb Derbyfcac00f2018-05-01 11:57:56 -04002891 Sets Blend_Mode to mode.
Cary Clark8032b982017-07-28 11:04:54 -04002892 Does not check for valid input.
2893
2894 #Param mode SkBlendMode used to combine source color and destination ##
2895
2896 #Example
2897 void draw(SkCanvas* canvas) {
2898 SkPaint paint;
2899 SkDebugf("isSrcOver %c= true\n", paint.isSrcOver() ? '=' : '!');
2900 paint.setBlendMode(SkBlendMode::kSrc);
2901 SkDebugf("isSrcOver %c= true\n", paint.isSrcOver() ? '=' : '!');
2902 }
2903
2904 #StdOut
2905 isSrcOver == true
2906 isSrcOver != true
2907 ##
2908 ##
2909
2910##
2911
Cary Clark08895c42018-02-01 09:37:32 -05002912#Subtopic Blend_Mode_Methods ##
Cary Clark8032b982017-07-28 11:04:54 -04002913# ------------------------------------------------------------------------------
Cary Clark08895c42018-02-01 09:37:32 -05002914#Subtopic Path_Effect_Methods
2915#Line # get and set Path_Effect ##
Cary Clark8032b982017-07-28 11:04:54 -04002916
2917Path_Effect modifies the path geometry before drawing it.
2918Path_Effect may implement dashing, custom fill effects and custom stroke effects.
2919If Paint has no Path_Effect, the path geometry is unaltered when filled or stroked.
2920
2921#Example
2922#Height 160
2923 void draw(SkCanvas* canvas) {
2924 SkPaint paint;
2925 paint.setStyle(SkPaint::kStroke_Style);
2926 paint.setStrokeWidth(16);
2927 SkScalar intervals[] = {30, 10};
2928 paint.setPathEffect(SkDashPathEffect::Make(intervals, SK_ARRAY_COUNT(intervals), 1));
2929 canvas->drawRoundRect({20, 20, 120, 120}, 20, 20, paint);
2930 }
2931##
2932
2933#SeeAlso Path_Effect
2934
2935#Method SkPathEffect* getPathEffect() const
2936
Cary Clarkab2621d2018-01-30 10:08:57 -05002937#In Path_Effect_Methods
2938#Line # returns Path_Effect, modifications to path geometry; dashing ##
Cary Clark8032b982017-07-28 11:04:54 -04002939 Returns Path_Effect if set, or nullptr.
2940 Does not alter Path_Effect Reference_Count.
Herb Derbyfcac00f2018-05-01 11:57:56 -04002941
Cary Clark8032b982017-07-28 11:04:54 -04002942 #Return Path_Effect if previously set, nullptr otherwise ##
2943
2944 #Example
2945 void draw(SkCanvas* canvas) {
2946 SkPaint paint;
2947 SkDebugf("nullptr %c= path effect\n", paint.getPathEffect() ? '!' : '=');
2948 paint.setPathEffect(SkCornerPathEffect::Make(10));
2949 SkDebugf("nullptr %c= path effect\n", paint.getPathEffect() ? '!' : '=');
2950 }
2951
2952 #StdOut
2953 nullptr == path effect
2954 nullptr != path effect
2955 ##
2956 ##
2957
2958##
2959
2960
2961#Method sk_sp<SkPathEffect> refPathEffect() const
2962
Cary Clarkab2621d2018-01-30 10:08:57 -05002963#In Path_Effect_Methods
2964#Line # references Path_Effect, modifications to path geometry; dashing ##
Cary Clark8032b982017-07-28 11:04:54 -04002965 Returns Path_Effect if set, or nullptr.
2966 Increases Path_Effect Reference_Count by one.
2967
2968 #Return Path_Effect if previously set, nullptr otherwise ##
2969
2970 #Example
2971 void draw(SkCanvas* canvas) {
2972 SkPaint paint1, paint2;
Cary Clarka560c472017-11-27 10:44:06 -05002973 SkScalar intervals[] = {1, 2};
2974 paint1.setPathEffect(SkDashPathEffect::Make(intervals, SK_ARRAY_COUNT(intervals), 10));
Cary Clark8032b982017-07-28 11:04:54 -04002975 SkDebugf("path effect unique: %s\n", paint1.getPathEffect()->unique() ? "true" : "false");
2976 paint2.setPathEffect(paint1.refPathEffect());
2977 SkDebugf("path effect unique: %s\n", paint1.getPathEffect()->unique() ? "true" : "false");
2978 }
2979
2980 #StdOut
2981 path effect unique: true
2982 path effect unique: false
2983 ##
2984 ##
2985
2986##
2987
2988
2989#Method void setPathEffect(sk_sp<SkPathEffect> pathEffect)
2990
Cary Clarkab2621d2018-01-30 10:08:57 -05002991#In Path_Effect_Methods
2992#Line # sets Path_Effect, modifications to path geometry; dashing ##
Cary Clark6fc50412017-09-21 12:31:06 -04002993Sets Path_Effect to pathEffect, decreasing Reference_Count of the previous
2994Path_Effect. Pass nullptr to leave the path geometry unaltered.
2995
2996Increments pathEffect Reference_Count by one.
Cary Clark8032b982017-07-28 11:04:54 -04002997
2998 #Param pathEffect replace Path with a modification when drawn ##
2999
3000 #Example
3001 void draw(SkCanvas* canvas) {
3002 SkPaint paint;
3003 paint.setPathEffect(SkDiscretePathEffect::Make(3, 5));
3004 canvas->drawRect(SkRect::MakeXYWH(40, 40, 175, 175), paint);
3005 }
3006 ##
3007
3008##
3009
Cary Clark08895c42018-02-01 09:37:32 -05003010#Subtopic Path_Effect_Methods ##
Cary Clark8032b982017-07-28 11:04:54 -04003011# ------------------------------------------------------------------------------
Cary Clark08895c42018-02-01 09:37:32 -05003012#Subtopic Mask_Filter_Methods
3013#Line # get and set Mask_Filter ##
Cary Clark8032b982017-07-28 11:04:54 -04003014
Cary Clarkce101242017-09-01 15:51:02 -04003015Mask_Filter uses coverage of the shape drawn to create Mask_Alpha.
Mike Reed8ad91a92018-01-19 19:09:32 -05003016Mask_Filter takes a Mask, and returns a Mask.
Cary Clark6fc50412017-09-21 12:31:06 -04003017
3018Mask_Filter may change the geometry and transparency of the shape, such as
3019creating a blur effect. Set Mask_Filter to nullptr to prevent Mask_Filter from
3020modifying the draw.
Cary Clark8032b982017-07-28 11:04:54 -04003021
3022#Example
3023 void draw(SkCanvas* canvas) {
3024 SkPaint paint;
Cary Clark681287e2018-03-16 11:34:15 -04003025 paint.setMaskFilter(SkMaskFilter::MakeBlur(kSolid_SkBlurStyle, 3));
Cary Clark8032b982017-07-28 11:04:54 -04003026 canvas->drawRect(SkRect::MakeXYWH(40, 40, 175, 175), paint);
3027 }
3028##
3029
3030#Method SkMaskFilter* getMaskFilter() const
3031
Cary Clarkab2621d2018-01-30 10:08:57 -05003032#In Mask_Filter_Methods
3033#Line # returns Mask_Filter, alterations to Mask_Alpha ##
Cary Clark8032b982017-07-28 11:04:54 -04003034 Returns Mask_Filter if set, or nullptr.
3035 Does not alter Mask_Filter Reference_Count.
Herb Derbyfcac00f2018-05-01 11:57:56 -04003036
Cary Clark8032b982017-07-28 11:04:54 -04003037 #Return Mask_Filter if previously set, nullptr otherwise ##
3038
3039 #Example
3040 void draw(SkCanvas* canvas) {
3041 SkPaint paint;
3042 SkDebugf("nullptr %c= mask filter\n", paint.getMaskFilter() ? '!' : '=');
Cary Clark681287e2018-03-16 11:34:15 -04003043 paint.setMaskFilter(SkMaskFilter::MakeBlur(kOuter_SkBlurStyle, 3));
Cary Clark8032b982017-07-28 11:04:54 -04003044 SkDebugf("nullptr %c= mask filter\n", paint.getMaskFilter() ? '!' : '=');
3045 }
3046
3047 #StdOut
3048 nullptr == mask filter
3049 nullptr != mask filter
3050 ##
3051 ##
3052
3053##
3054
3055#Method sk_sp<SkMaskFilter> refMaskFilter() const
3056
Cary Clarkab2621d2018-01-30 10:08:57 -05003057#In Mask_Filter_Methods
3058#Line # references Mask_Filter, alterations to Mask_Alpha ##
Cary Clark8032b982017-07-28 11:04:54 -04003059 Returns Mask_Filter if set, or nullptr.
Cary Clark6fc50412017-09-21 12:31:06 -04003060
Cary Clark8032b982017-07-28 11:04:54 -04003061 Increases Mask_Filter Reference_Count by one.
Herb Derbyfcac00f2018-05-01 11:57:56 -04003062
Cary Clark8032b982017-07-28 11:04:54 -04003063 #Return Mask_Filter if previously set, nullptr otherwise ##
3064
3065 #Example
3066 void draw(SkCanvas* canvas) {
3067 SkPaint paint1, paint2;
Cary Clark681287e2018-03-16 11:34:15 -04003068 paint1.setMaskFilter(SkMaskFilter::MakeBlur(kNormal_SkBlurStyle, 1));
Cary Clark8032b982017-07-28 11:04:54 -04003069 SkDebugf("mask filter unique: %s\n", paint1.getMaskFilter()->unique() ? "true" : "false");
3070 paint2.setMaskFilter(paint1.refMaskFilter());
3071 SkDebugf("mask filter unique: %s\n", paint1.getMaskFilter()->unique() ? "true" : "false");
3072 }
3073
3074 #StdOut
3075 mask filter unique: true
3076 mask filter unique: false
3077 ##
3078 ##
3079
3080##
3081
3082#Method void setMaskFilter(sk_sp<SkMaskFilter> maskFilter)
3083
Cary Clarkab2621d2018-01-30 10:08:57 -05003084#In Mask_Filter_Methods
3085#Line # sets Mask_Filter, alterations to Mask_Alpha ##
Cary Clark6fc50412017-09-21 12:31:06 -04003086Sets Mask_Filter to maskFilter, decreasing Reference_Count of the previous
3087Mask_Filter. Pass nullptr to clear Mask_Filter and leave Mask_Filter effect on
3088Mask_Alpha unaltered.
3089
Cary Clark6fc50412017-09-21 12:31:06 -04003090Increments maskFilter Reference_Count by one.
Cary Clark8032b982017-07-28 11:04:54 -04003091
3092 #Param maskFilter modifies clipping mask generated from drawn geometry ##
3093
3094 #Example
3095 void draw(SkCanvas* canvas) {
3096 SkPaint paint;
3097 paint.setStyle(SkPaint::kStroke_Style);
3098 paint.setStrokeWidth(10);
Cary Clark681287e2018-03-16 11:34:15 -04003099 paint.setMaskFilter(SkMaskFilter::MakeBlur(kNormal_SkBlurStyle, 10));
Cary Clark8032b982017-07-28 11:04:54 -04003100 canvas->drawRect(SkRect::MakeXYWH(40, 40, 175, 175), paint);
3101 }
3102 ##
3103
3104##
3105
Cary Clark08895c42018-02-01 09:37:32 -05003106#Subtopic Mask_Filter_Methods ##
Cary Clark8032b982017-07-28 11:04:54 -04003107# ------------------------------------------------------------------------------
Cary Clark08895c42018-02-01 09:37:32 -05003108#Subtopic Typeface_Methods
3109#Line # get and set Typeface ##
Cary Clark8032b982017-07-28 11:04:54 -04003110
3111Typeface identifies the font used when drawing and measuring text.
3112Typeface may be specified by name, from a file, or from a data stream.
3113The default Typeface defers to the platform-specific default font
3114implementation.
3115
3116#Example
3117#Height 100
3118 void draw(SkCanvas* canvas) {
3119 SkPaint paint;
Ben Wagner700ff172017-11-08 15:37:22 -05003120 paint.setTypeface(SkTypeface::MakeFromName(nullptr, SkFontStyle()));
Cary Clark8032b982017-07-28 11:04:54 -04003121 paint.setAntiAlias(true);
3122 paint.setTextSize(36);
3123 canvas->drawString("A Big Hello!", 10, 40, paint);
3124 paint.setTypeface(nullptr);
3125 paint.setFakeBoldText(true);
3126 canvas->drawString("A Big Hello!", 10, 80, paint);
3127 }
3128##
3129
3130#Method SkTypeface* getTypeface() const
3131
Cary Clarkab2621d2018-01-30 10:08:57 -05003132#In Typeface_Methods
3133#Line # returns Typeface, font description ##
Cary Clark8032b982017-07-28 11:04:54 -04003134 Returns Typeface if set, or nullptr.
Cary Clark6fc50412017-09-21 12:31:06 -04003135 Increments Typeface Reference_Count by one.
Herb Derbyfcac00f2018-05-01 11:57:56 -04003136
Cary Clark8032b982017-07-28 11:04:54 -04003137 #Return Typeface if previously set, nullptr otherwise ##
3138
3139 #Example
3140 void draw(SkCanvas* canvas) {
3141 SkPaint paint;
3142 SkDebugf("nullptr %c= typeface\n", paint.getTypeface() ? '!' : '=');
Cary Clark71961fb2018-01-05 14:21:59 -05003143 paint.setTypeface(SkTypeface::MakeFromName("monospace", SkFontStyle()));
Cary Clark8032b982017-07-28 11:04:54 -04003144 SkDebugf("nullptr %c= typeface\n", paint.getTypeface() ? '!' : '=');
3145 }
3146
3147 #StdOut
3148 nullptr == typeface
3149 nullptr != typeface
3150 ##
3151 ##
3152
3153##
3154
3155#Method sk_sp<SkTypeface> refTypeface() const
3156
Cary Clarkab2621d2018-01-30 10:08:57 -05003157#In Typeface_Methods
3158#Line # references Typeface, font description ##
Cary Clark8032b982017-07-28 11:04:54 -04003159 Increases Typeface Reference_Count by one.
3160
3161 #Return Typeface if previously set, nullptr otherwise ##
3162
3163 #Example
3164 void draw(SkCanvas* canvas) {
3165 SkPaint paint1, paint2;
Herb Derbyfcac00f2018-05-01 11:57:56 -04003166 paint1.setTypeface(SkTypeface::MakeFromName("monospace",
Cary Clark8032b982017-07-28 11:04:54 -04003167 SkFontStyle(SkFontStyle::kNormal_Weight, SkFontStyle::kNormal_Width,
3168 SkFontStyle::kItalic_Slant)));
3169 SkDebugf("typeface1 %c= typeface2\n",
3170 paint1.getTypeface() == paint2.getTypeface() ? '=' : '!');
3171 paint2.setTypeface(paint1.refTypeface());
3172 SkDebugf("typeface1 %c= typeface2\n",
3173 paint1.getTypeface() == paint2.getTypeface() ? '=' : '!');
3174 }
3175
3176 #StdOut
3177 typeface1 != typeface2
3178 typeface1 == typeface2
3179 ##
3180 ##
3181
3182##
3183
3184#Method void setTypeface(sk_sp<SkTypeface> typeface)
3185
Cary Clarkab2621d2018-01-30 10:08:57 -05003186#In Typeface_Methods
3187#Line # sets Typeface, font description ##
Herb Derbyfcac00f2018-05-01 11:57:56 -04003188Sets Typeface to typeface, decreasing Reference_Count of the previous Typeface.
Cary Clark6fc50412017-09-21 12:31:06 -04003189Pass nullptr to clear Typeface and use the default typeface. Increments
3190typeface Reference_Count by one.
Cary Clark8032b982017-07-28 11:04:54 -04003191
3192 #Param typeface font and style used to draw text ##
3193
3194 #Example
3195 #Height 64
3196 void draw(SkCanvas* canvas) {
3197 SkPaint paint;
Cary Clark71961fb2018-01-05 14:21:59 -05003198 paint.setTypeface(SkTypeface::MakeFromName("monospace", SkFontStyle()));
3199 canvas->drawString("hamburgerfons", 10, 30, paint);
Cary Clark8032b982017-07-28 11:04:54 -04003200 paint.setTypeface(nullptr);
Cary Clark71961fb2018-01-05 14:21:59 -05003201 canvas->drawString("hamburgerfons", 10, 50, paint);
Cary Clark8032b982017-07-28 11:04:54 -04003202 }
3203 ##
3204
3205##
3206
Cary Clark08895c42018-02-01 09:37:32 -05003207#Subtopic Typeface_Methods ##
Cary Clark8032b982017-07-28 11:04:54 -04003208# ------------------------------------------------------------------------------
Cary Clark08895c42018-02-01 09:37:32 -05003209#Subtopic Image_Filter_Methods
3210#Line # get and set Image_Filter ##
Cary Clark8032b982017-07-28 11:04:54 -04003211
3212Image_Filter operates on the pixel representation of the shape, as modified by Paint
3213with Blend_Mode set to SkBlendMode::kSrcOver. Image_Filter creates a new bitmap,
3214which is drawn to the device using the set Blend_Mode.
Cary Clark6fc50412017-09-21 12:31:06 -04003215
Cary Clark8032b982017-07-28 11:04:54 -04003216Image_Filter is higher level than Mask_Filter; for instance, an Image_Filter
Cary Clarkce101242017-09-01 15:51:02 -04003217can operate on all channels of Color, while Mask_Filter generates Alpha only.
Cary Clark8032b982017-07-28 11:04:54 -04003218Image_Filter operates independently of and can be used in combination with
Mike Reed8ad91a92018-01-19 19:09:32 -05003219Mask_Filter.
Cary Clark8032b982017-07-28 11:04:54 -04003220
3221#Example
3222 #ToDo explain why the two draws are so different ##
3223 void draw(SkCanvas* canvas) {
3224 SkPaint paint;
3225 paint.setStyle(SkPaint::kStroke_Style);
3226 paint.setStrokeWidth(2);
3227 SkRegion region;
3228 region.op( 10, 10, 50, 50, SkRegion::kUnion_Op);
3229 region.op( 10, 50, 90, 90, SkRegion::kUnion_Op);
Cary Clarka560c472017-11-27 10:44:06 -05003230 paint.setImageFilter(SkBlurImageFilter::Make(5.0f, 5.0f, nullptr));
Cary Clark8032b982017-07-28 11:04:54 -04003231 canvas->drawRegion(region, paint);
3232 paint.setImageFilter(nullptr);
Cary Clarka7b84c52018-03-18 11:46:54 -04003233 paint.setMaskFilter(SkMaskFilter::MakeBlur(kNormal_SkBlurStyle, 5));
Cary Clark8032b982017-07-28 11:04:54 -04003234 canvas->translate(100, 100);
3235 canvas->drawRegion(region, paint);
3236 }
3237##
3238
3239#Method SkImageFilter* getImageFilter() const
3240
Cary Clarkab2621d2018-01-30 10:08:57 -05003241#In Image_Filter_Methods
3242#Line # returns Image_Filter, alter pixels; blur ##
Cary Clark8032b982017-07-28 11:04:54 -04003243 Returns Image_Filter if set, or nullptr.
3244 Does not alter Image_Filter Reference_Count.
Herb Derbyfcac00f2018-05-01 11:57:56 -04003245
Cary Clark8032b982017-07-28 11:04:54 -04003246 #Return Image_Filter if previously set, nullptr otherwise ##
3247
3248 #Example
3249 void draw(SkCanvas* canvas) {
3250 SkPaint paint;
3251 SkDebugf("nullptr %c= image filter\n", paint.getImageFilter() ? '!' : '=');
Cary Clarka560c472017-11-27 10:44:06 -05003252 paint.setImageFilter(SkBlurImageFilter::Make(kOuter_SkBlurStyle, 3, nullptr, nullptr));
Cary Clark8032b982017-07-28 11:04:54 -04003253 SkDebugf("nullptr %c= image filter\n", paint.getImageFilter() ? '!' : '=');
3254 }
3255
3256 #StdOut
3257 nullptr == image filter
3258 nullptr != image filter
3259 ##
3260 ##
3261
3262##
3263
3264#Method sk_sp<SkImageFilter> refImageFilter() const
3265
Cary Clarkab2621d2018-01-30 10:08:57 -05003266#In Image_Filter_Methods
3267#Line # references Image_Filter, alter pixels; blur ##
Cary Clark8032b982017-07-28 11:04:54 -04003268 Returns Image_Filter if set, or nullptr.
3269 Increases Image_Filter Reference_Count by one.
3270
3271 #Return Image_Filter if previously set, nullptr otherwise ##
3272
3273 #Example
3274 void draw(SkCanvas* canvas) {
3275 SkPaint paint1, paint2;
3276 paint1.setImageFilter(SkOffsetImageFilter::Make(25, 25, nullptr));
3277 SkDebugf("image filter unique: %s\n", paint1.getImageFilter()->unique() ? "true" : "false");
3278 paint2.setImageFilter(paint1.refImageFilter());
3279 SkDebugf("image filter unique: %s\n", paint1.getImageFilter()->unique() ? "true" : "false");
3280 }
3281
3282 #StdOut
3283 image filter unique: true
3284 image filter unique: false
3285 ##
3286 ##
3287
3288##
3289
3290#Method void setImageFilter(sk_sp<SkImageFilter> imageFilter)
3291
Cary Clarkab2621d2018-01-30 10:08:57 -05003292#In Image_Filter_Methods
3293#Line # sets Image_Filter, alter pixels; blur ##
Cary Clark6fc50412017-09-21 12:31:06 -04003294Sets Image_Filter to imageFilter, decreasing Reference_Count of the previous
3295Image_Filter. Pass nullptr to clear Image_Filter, and remove Image_Filter effect
3296on drawing.
3297
Cary Clark6fc50412017-09-21 12:31:06 -04003298Increments imageFilter Reference_Count by one.
Cary Clark8032b982017-07-28 11:04:54 -04003299
3300 #Param imageFilter how Image is sampled when transformed ##
3301
3302 #Example
3303 #Height 160
3304 void draw(SkCanvas* canvas) {
3305 SkBitmap bitmap;
3306 bitmap.allocN32Pixels(100, 100);
3307 SkCanvas offscreen(bitmap);
3308 SkPaint paint;
3309 paint.setAntiAlias(true);
3310 paint.setColor(SK_ColorWHITE);
3311 paint.setTextSize(96);
3312 offscreen.clear(0);
3313 offscreen.drawString("e", 20, 70, paint);
3314 paint.setImageFilter(
3315 SkLightingImageFilter::MakePointLitDiffuse(SkPoint3::Make(80, 100, 10),
3316 SK_ColorWHITE, 1, 2, nullptr, nullptr));
3317 canvas->drawBitmap(bitmap, 0, 0, &paint);
3318 }
3319 ##
3320
3321##
3322
Cary Clark08895c42018-02-01 09:37:32 -05003323#Subtopic Image_Filter_Methods ##
Cary Clark8032b982017-07-28 11:04:54 -04003324# ------------------------------------------------------------------------------
Cary Clark08895c42018-02-01 09:37:32 -05003325#Subtopic Draw_Looper_Methods
3326#Line # get and set Draw_Looper ##
Cary Clark8032b982017-07-28 11:04:54 -04003327
3328Draw_Looper sets a modifier that communicates state from one Draw_Layer
3329to another to construct the draw.
Cary Clark6fc50412017-09-21 12:31:06 -04003330
Cary Clark8032b982017-07-28 11:04:54 -04003331Draw_Looper draws one or more times, modifying the canvas and paint each time.
3332Draw_Looper may be used to draw multiple colors or create a colored shadow.
Herb Derbyfcac00f2018-05-01 11:57:56 -04003333Set Draw_Looper to nullptr to prevent Draw_Looper from modifying the draw.
Cary Clark8032b982017-07-28 11:04:54 -04003334
3335#Example
3336#Height 128
3337 void draw(SkCanvas* canvas) {
3338 SkLayerDrawLooper::LayerInfo info;
3339 info.fPaintBits = (SkLayerDrawLooper::BitFlags) SkLayerDrawLooper::kColorFilter_Bit;
3340 info.fColorMode = SkBlendMode::kSrc;
3341 SkLayerDrawLooper::Builder looperBuilder;
3342 SkPaint* loopPaint = looperBuilder.addLayer(info);
3343 loopPaint->setColor(SK_ColorRED);
3344 info.fOffset.set(20, 20);
3345 loopPaint = looperBuilder.addLayer(info);
3346 loopPaint->setColor(SK_ColorBLUE);
3347 SkPaint paint;
3348 paint.setDrawLooper(looperBuilder.detach());
3349 canvas->drawCircle(50, 50, 50, paint);
3350 }
3351
3352##
3353
3354#Method SkDrawLooper* getDrawLooper() const
3355
Cary Clarkab2621d2018-01-30 10:08:57 -05003356#In Draw_Looper_Methods
3357#Line # returns Draw_Looper, multiple layers ##
Cary Clark8032b982017-07-28 11:04:54 -04003358 Returns Draw_Looper if set, or nullptr.
3359 Does not alter Draw_Looper Reference_Count.
Herb Derbyfcac00f2018-05-01 11:57:56 -04003360
Cary Clark8032b982017-07-28 11:04:54 -04003361 #Return Draw_Looper if previously set, nullptr otherwise ##
3362
3363 #Example
3364 void draw(SkCanvas* canvas) {
3365 SkPaint paint;
3366 SkDebugf("nullptr %c= draw looper\n", paint.getDrawLooper() ? '!' : '=');
3367 SkLayerDrawLooper::Builder looperBuilder;
3368 paint.setDrawLooper(looperBuilder.detach());
3369 SkDebugf("nullptr %c= draw looper\n", paint.getDrawLooper() ? '!' : '=');
3370 }
3371
3372 #StdOut
3373 nullptr == draw looper
3374 nullptr != draw looper
3375 ##
3376 ##
3377
3378##
3379
3380#Method sk_sp<SkDrawLooper> refDrawLooper() const
3381
Cary Clarkab2621d2018-01-30 10:08:57 -05003382#In Draw_Looper_Methods
3383#Line # references Draw_Looper, multiple layers ##
Cary Clark8032b982017-07-28 11:04:54 -04003384 Returns Draw_Looper if set, or nullptr.
3385 Increases Draw_Looper Reference_Count by one.
3386
3387 #Return Draw_Looper if previously set, nullptr otherwise ##
3388
3389 #Example
3390 void draw(SkCanvas* canvas) {
3391 SkPaint paint1, paint2;
3392 SkLayerDrawLooper::Builder looperBuilder;
3393 paint1.setDrawLooper(looperBuilder.detach());
3394 SkDebugf("draw looper unique: %s\n", paint1.getDrawLooper()->unique() ? "true" : "false");
3395 paint2.setDrawLooper(paint1.refDrawLooper());
3396 SkDebugf("draw looper unique: %s\n", paint1.getDrawLooper()->unique() ? "true" : "false");
3397 }
3398
3399 #StdOut
3400 draw looper unique: true
3401 draw looper unique: false
3402 ##
3403 ##
3404
3405##
3406
3407#Method SkDrawLooper* getLooper() const
Cary Clark4855f782018-02-06 09:41:53 -05003408#Bug 6259
Cary Clark8032b982017-07-28 11:04:54 -04003409#Deprecated
Cary Clark8032b982017-07-28 11:04:54 -04003410##
3411
3412#Method void setDrawLooper(sk_sp<SkDrawLooper> drawLooper)
Cary Clarkab2621d2018-01-30 10:08:57 -05003413#In Draw_Looper_Methods
3414#Line # sets Draw_Looper, multiple layers ##
Cary Clark6fc50412017-09-21 12:31:06 -04003415Sets Draw_Looper to drawLooper, decreasing Reference_Count of the previous
3416drawLooper. Pass nullptr to clear Draw_Looper and leave Draw_Looper effect on
3417drawing unaltered.
3418
3419Increments drawLooper Reference_Count by one.
Cary Clark8032b982017-07-28 11:04:54 -04003420
Cary Clarka523d2d2017-08-30 08:58:10 -04003421 #Param drawLooper iterates through drawing one or more time, altering Paint ##
Cary Clark8032b982017-07-28 11:04:54 -04003422
3423 #Example
3424 #Height 128
3425 void draw(SkCanvas* canvas) {
3426 SkPaint paint;
3427 paint.setDrawLooper(SkBlurDrawLooper::Make(0x7FFF0000, 4, -5, -10));
3428 paint.setStyle(SkPaint::kStroke_Style);
3429 paint.setStrokeWidth(10);
3430 paint.setAntiAlias(true);
3431 paint.setColor(0x7f0000ff);
3432 canvas->drawCircle(70, 70, 50, paint);
3433 }
3434 ##
3435
3436##
3437
3438#Method void setLooper(sk_sp<SkDrawLooper> drawLooper)
Cary Clark4855f782018-02-06 09:41:53 -05003439#Bug 6259
Cary Clark8032b982017-07-28 11:04:54 -04003440#Deprecated
Cary Clark8032b982017-07-28 11:04:54 -04003441##
3442
Cary Clark08895c42018-02-01 09:37:32 -05003443#Subtopic Draw_Looper_Methods ##
Cary Clark4855f782018-02-06 09:41:53 -05003444
Cary Clark8032b982017-07-28 11:04:54 -04003445# ------------------------------------------------------------------------------
Cary Clark08895c42018-02-01 09:37:32 -05003446#Subtopic Text_Align
3447#Line # text placement relative to position ##
Cary Clark8032b982017-07-28 11:04:54 -04003448
3449#Enum Align
Cary Clark08895c42018-02-01 09:37:32 -05003450#Line # glyph locations relative to text position ##
Cary Clark8032b982017-07-28 11:04:54 -04003451#Code
3452 enum Align {
3453 kLeft_Align,
3454 kCenter_Align,
3455 kRight_Align,
3456 };
Cary Clarkd98f78c2018-04-26 08:32:37 -04003457
3458 static constexpr int kAlignCount = 3;
Cary Clark8032b982017-07-28 11:04:54 -04003459##
3460
3461Align adjusts the text relative to the text position.
Cary Clarkce101242017-09-01 15:51:02 -04003462Align affects Glyphs drawn with: SkCanvas::drawText, SkCanvas::drawPosText,
Herb Derbyfcac00f2018-05-01 11:57:56 -04003463SkCanvas::drawPosTextH, SkCanvas::drawTextOnPath,
Cary Clark8032b982017-07-28 11:04:54 -04003464SkCanvas::drawTextOnPathHV, SkCanvas::drawTextRSXform, SkCanvas::drawTextBlob,
Herb Derbyfcac00f2018-05-01 11:57:56 -04003465and SkCanvas::drawString;
Cary Clarkce101242017-09-01 15:51:02 -04003466as well as calls that place text Glyphs like getTextWidths and getTextPath.
Cary Clark8032b982017-07-28 11:04:54 -04003467
3468The text position is set by the font for both horizontal and vertical text.
3469Typically, for horizontal text, the position is to the left side of the glyph on the
3470base line; and for vertical text, the position is the horizontal center of the glyph
3471at the caps height.
3472
Herb Derbyfcac00f2018-05-01 11:57:56 -04003473Align adjusts the glyph position to center it or move it to abut the position
Cary Clark8032b982017-07-28 11:04:54 -04003474using the metrics returned by the font.
3475
3476Align defaults to kLeft_Align.
3477
3478#Const kLeft_Align 0
Cary Clark682c58d2018-05-16 07:07:07 -04003479#Line # positions glyph by computed font offset ##
Cary Clark8032b982017-07-28 11:04:54 -04003480 Leaves the glyph at the position computed by the font offset by the text position.
3481##
3482
3483#Const kCenter_Align 1
Cary Clark682c58d2018-05-16 07:07:07 -04003484#Line # centers line of glyphs by its width or height ##
Cary Clark8032b982017-07-28 11:04:54 -04003485 Moves the glyph half its width if Flags has kVerticalText_Flag clear, and
3486 half its height if Flags has kVerticalText_Flag set.
3487##
3488
3489#Const kRight_Align 2
Cary Clark682c58d2018-05-16 07:07:07 -04003490#Line # moves lines of glyphs by its width or height ##
Cary Clark8032b982017-07-28 11:04:54 -04003491 Moves the glyph by its width if Flags has kVerticalText_Flag clear,
3492 and by its height if Flags has kVerticalText_Flag set.
3493##
3494
Cary Clark8032b982017-07-28 11:04:54 -04003495#Const kAlignCount 3
Cary Clark682c58d2018-05-16 07:07:07 -04003496#Line # number of different Text_Align values defined ##
Cary Clark8032b982017-07-28 11:04:54 -04003497##
3498
3499#Enum ##
3500
3501#Example
3502 #Height 160
3503 #Description
3504 Each position separately moves the glyph in drawPosText.
3505 ##
3506 void draw(SkCanvas* canvas) {
3507 SkPaint paint;
3508 paint.setTextSize(40);
3509 SkPoint position[] = {{100, 50}, {150, 40}};
3510 for (SkPaint::Align a : { SkPaint::kLeft_Align,
3511 SkPaint::kCenter_Align,
3512 SkPaint::kRight_Align}) {
3513 paint.setTextAlign(a);
3514 canvas->drawPosText("Aa", 2, position, paint);
3515 canvas->translate(0, 50);
3516 }
3517 }
3518##
3519
3520#Example
3521 #Height 160
3522 #Description
3523 Vertical_Text treats kLeft_Align as top align, and kRight_Align as bottom align.
3524 ##
3525 void draw(SkCanvas* canvas) {
3526 SkPaint paint;
3527 paint.setTextSize(40);
3528 paint.setVerticalText(true);
3529 for (SkPaint::Align a : { SkPaint::kLeft_Align,
3530 SkPaint::kCenter_Align,
3531 SkPaint::kRight_Align }) {
3532 paint.setTextAlign(a);
3533 canvas->drawString("Aa", 50, 80, paint);
3534 canvas->translate(50, 0);
3535 }
3536 }
3537##
3538
3539#Method Align getTextAlign() const
3540
Cary Clarkab2621d2018-01-30 10:08:57 -05003541#In Text_Align
3542#Line # returns Align: left, center, or right ##
Cary Clark8032b982017-07-28 11:04:54 -04003543 Returns Text_Align.
3544 Returns kLeft_Align if Text_Align has not been set.
3545
3546 #Return text placement relative to position ##
3547
3548 #Example
3549 SkPaint paint;
3550 SkDebugf("kLeft_Align %c= default\n", SkPaint::kLeft_Align == paint.getTextAlign() ? '=' : '!');
3551
3552 #StdOut
3553 kLeft_Align == default
3554 ##
3555 ##
3556##
3557
3558#Method void setTextAlign(Align align)
3559
Cary Clarkab2621d2018-01-30 10:08:57 -05003560#In Text_Align
3561#Line # sets Align: left, center, or right ##
Cary Clark8032b982017-07-28 11:04:54 -04003562 Sets Text_Align to align.
3563 Has no effect if align is an invalid value.
3564
3565 #Param align text placement relative to position ##
3566
3567 #Example
3568 #Height 160
3569 #Description
3570 Text is left-aligned by default, and then set to center. Setting the
3571 alignment out of range has no effect.
3572 ##
3573 void draw(SkCanvas* canvas) {
3574 SkPaint paint;
3575 paint.setTextSize(40);
3576 canvas->drawString("Aa", 100, 50, paint);
3577 paint.setTextAlign(SkPaint::kCenter_Align);
3578 canvas->drawString("Aa", 100, 100, paint);
3579 paint.setTextAlign((SkPaint::Align) SkPaint::kAlignCount);
3580 canvas->drawString("Aa", 100, 150, paint);
3581 }
3582 ##
3583
3584##
3585
Cary Clark08895c42018-02-01 09:37:32 -05003586#Subtopic Text_Align ##
Cary Clark8032b982017-07-28 11:04:54 -04003587# ------------------------------------------------------------------------------
Cary Clark08895c42018-02-01 09:37:32 -05003588#Subtopic Text_Size
3589#Line # overall height in points ##
Cary Clark8032b982017-07-28 11:04:54 -04003590
3591Text_Size adjusts the overall text size in points.
3592Text_Size can be set to any positive value or zero.
3593Text_Size defaults to 12.
3594Set SkPaintDefaults_TextSize at compile time to change the default setting.
3595
3596#Example
3597#Height 135
3598 void draw(SkCanvas* canvas) {
3599 SkPaint paint;
3600 canvas->drawString("12 point", 10, 20, paint);
3601 paint.setTextSize(24);
3602 canvas->drawString("24 point", 10, 60, paint);
3603 paint.setTextSize(48);
3604 canvas->drawString("48 point", 10, 120, paint);
3605 }
3606##
3607
3608#Method SkScalar getTextSize() const
3609
Cary Clarkab2621d2018-01-30 10:08:57 -05003610#In Text_Size
3611#Line # returns text size in points ##
Cary Clark8032b982017-07-28 11:04:54 -04003612 Returns Text_Size in points.
3613
3614 #Return typographic height of text ##
3615
3616 #Example
3617 SkPaint paint;
3618 SkDebugf("12 %c= default text size\n", 12 == paint.getTextSize() ? '=' : '!');
3619 ##
3620
3621##
3622
3623#Method void setTextSize(SkScalar textSize)
3624
Cary Clarkab2621d2018-01-30 10:08:57 -05003625#In Text_Size
3626#Line # sets text size in points ##
Cary Clark8032b982017-07-28 11:04:54 -04003627 Sets Text_Size in points.
3628 Has no effect if textSize is not greater than or equal to zero.
Herb Derbyfcac00f2018-05-01 11:57:56 -04003629
Cary Clark8032b982017-07-28 11:04:54 -04003630 #Param textSize typographic height of text ##
3631
3632 #Example
3633 SkPaint paint;
3634 SkDebugf("12 %c= text size\n", 12 == paint.getTextSize() ? '=' : '!');
3635 paint.setTextSize(-20);
3636 SkDebugf("12 %c= text size\n", 12 == paint.getTextSize() ? '=' : '!');
3637 ##
3638
3639##
3640
Cary Clark08895c42018-02-01 09:37:32 -05003641#Subtopic Text_Size ##
Cary Clark8032b982017-07-28 11:04:54 -04003642# ------------------------------------------------------------------------------
Cary Clark08895c42018-02-01 09:37:32 -05003643#Subtopic Text_Scale_X
3644#Line # text horizontal scale ##
Cary Clark8032b982017-07-28 11:04:54 -04003645
3646Text_Scale_X adjusts the text horizontal scale.
3647Text scaling approximates condensed and expanded type faces when the actual face
3648is not available.
3649Text_Scale_X can be set to any value.
3650Text_Scale_X defaults to 1.
3651
3652#Example
3653#Height 128
3654 void draw(SkCanvas* canvas) {
3655 SkPaint paint;
3656 paint.setAntiAlias(true);
3657 paint.setTextSize(24);
3658 paint.setTextScaleX(.8f);
3659 canvas->drawString("narrow", 10, 20, paint);
3660 paint.setTextScaleX(1);
3661 canvas->drawString("normal", 10, 60, paint);
3662 paint.setTextScaleX(1.2f);
3663 canvas->drawString("wide", 10, 100, paint);
3664 }
3665##
3666
3667#Method SkScalar getTextScaleX() const
3668
Cary Clarkab2621d2018-01-30 10:08:57 -05003669#In Text_Scale_X
3670#Line # returns the text horizontal scale; condensed text ##
Cary Clark8032b982017-07-28 11:04:54 -04003671 Returns Text_Scale_X.
3672 Default value is 1.
3673
3674 #Return text horizontal scale ##
3675
3676 #Example
3677 SkPaint paint;
3678 SkDebugf("1 %c= default text scale x\n", 1 == paint.getTextScaleX() ? '=' : '!');
3679 ##
3680
3681##
3682
3683
3684#Method void setTextScaleX(SkScalar scaleX)
3685
Cary Clarkab2621d2018-01-30 10:08:57 -05003686#In Text_Scale_X
3687#Line # sets the text horizontal scale; condensed text ##
Cary Clark8032b982017-07-28 11:04:54 -04003688 Sets Text_Scale_X.
3689 Default value is 1.
Herb Derbyfcac00f2018-05-01 11:57:56 -04003690
Cary Clark8032b982017-07-28 11:04:54 -04003691 #Param scaleX text horizontal scale ##
3692
3693 #Example
3694 SkPaint paint;
3695 paint.setTextScaleX(0.f / 0.f);
3696 SkDebugf("text scale %s-a-number\n", SkScalarIsNaN(paint.getTextScaleX()) ? "not" : "is");
3697 ##
3698
3699##
3700
Cary Clark08895c42018-02-01 09:37:32 -05003701#Subtopic Text_Scale_X ##
Cary Clark8032b982017-07-28 11:04:54 -04003702
Cary Clark08895c42018-02-01 09:37:32 -05003703#Subtopic Text_Skew_X
3704#Line # text horizontal slant ##
Cary Clark8032b982017-07-28 11:04:54 -04003705
3706
3707Text_Skew_X adjusts the text horizontal slant.
3708Text skewing approximates italic and oblique type faces when the actual face
3709is not available.
3710Text_Skew_X can be set to any value.
3711Text_Skew_X defaults to 0.
3712
3713#Example
3714#Height 128
3715 void draw(SkCanvas* canvas) {
3716 SkPaint paint;
3717 paint.setAntiAlias(true);
3718 paint.setTextSize(24);
3719 paint.setTextSkewX(-.25f);
3720 canvas->drawString("right-leaning", 10, 100, paint);
3721 paint.setTextSkewX(0);
3722 canvas->drawString("normal", 10, 60, paint);
3723 paint.setTextSkewX(.25f);
3724 canvas->drawString("left-leaning", 10, 20, paint);
3725 }
3726##
3727
3728#Method SkScalar getTextSkewX() const
3729
Cary Clarkab2621d2018-01-30 10:08:57 -05003730#In Text_Skew_X
3731#Line # returns the text horizontal skew; oblique text ##
Cary Clark8032b982017-07-28 11:04:54 -04003732 Returns Text_Skew_X.
3733 Default value is zero.
3734
3735 #Return additional shear in x-axis relative to y-axis ##
3736
3737 #Example
3738 SkPaint paint;
3739 SkDebugf("0 %c= default text skew x\n", 0 == paint.getTextSkewX() ? '=' : '!');
3740 ##
3741
3742##
3743
3744#Method void setTextSkewX(SkScalar skewX)
3745
Cary Clarkab2621d2018-01-30 10:08:57 -05003746#In Text_Skew_X
3747#Line # sets the text horizontal skew; oblique text ##
Cary Clark8032b982017-07-28 11:04:54 -04003748 Sets Text_Skew_X.
3749 Default value is zero.
3750
3751 #Param skewX additional shear in x-axis relative to y-axis ##
3752
3753 #Example
3754 SkPaint paint;
3755 paint.setTextScaleX(1.f / 0.f);
3756 SkDebugf("text scale %s-finite\n", SkScalarIsFinite(paint.getTextScaleX()) ? "is" : "not");
3757 ##
3758
3759##
3760
Cary Clark08895c42018-02-01 09:37:32 -05003761#Subtopic Text_Skew_X ##
Cary Clark8032b982017-07-28 11:04:54 -04003762
3763# ------------------------------------------------------------------------------
Cary Clark08895c42018-02-01 09:37:32 -05003764#Subtopic Text_Encoding
3765#Line # text encoded as characters or Glyphs ##
Cary Clark8032b982017-07-28 11:04:54 -04003766
3767#Enum TextEncoding
Cary Clark08895c42018-02-01 09:37:32 -05003768#Line # character or glyph encoded size ##
Cary Clark8032b982017-07-28 11:04:54 -04003769
3770#Code
3771 enum TextEncoding {
3772 kUTF8_TextEncoding,
3773 kUTF16_TextEncoding,
3774 kUTF32_TextEncoding,
Cary Clarkbad5ad72017-08-03 17:14:08 -04003775 kGlyphID_TextEncoding,
Cary Clark8032b982017-07-28 11:04:54 -04003776 };
3777##
3778
Cary Clark6fc50412017-09-21 12:31:06 -04003779TextEncoding determines whether text specifies character codes and their encoded
Cary Clarkbc5697d2017-10-04 14:31:33 -04003780size, or glyph indices. Characters are encoded as specified by the
Cary Clark682c58d2018-05-16 07:07:07 -04003781#A Unicode standard # https://unicode.org/standard/standard.html ##
Cary Clark6fc50412017-09-21 12:31:06 -04003782.
3783
Cary Clark8032b982017-07-28 11:04:54 -04003784Character codes encoded size are specified by UTF-8, UTF-16, or UTF-32.
Cary Clarkbc5697d2017-10-04 14:31:33 -04003785All character code formats are able to represent all of Unicode, differing only
Cary Clark8032b982017-07-28 11:04:54 -04003786in the total storage required.
3787
Cary Clark6fc50412017-09-21 12:31:06 -04003788#A UTF-8 (RFC 3629) # https://tools.ietf.org/html/rfc3629 ##
3789 encodes each character as one or more 8-bit bytes.
3790
3791#A UTF-16 (RFC 2781) # https://tools.ietf.org/html/rfc2781 ##
3792 encodes each character as one or two 16-bit words.
3793
Cary Clark682c58d2018-05-16 07:07:07 -04003794#A UTF-32 # https://www.unicode.org/versions/Unicode5.0.0/ch03.pdf ##
Cary Clark6fc50412017-09-21 12:31:06 -04003795 encodes each character as one 32-bit word.
Cary Clark8032b982017-07-28 11:04:54 -04003796
Herb Derbyfcac00f2018-05-01 11:57:56 -04003797Font_Manager uses font data to convert character code points into glyph indices.
Cary Clark8032b982017-07-28 11:04:54 -04003798A glyph index is a 16-bit word.
3799
3800TextEncoding is set to kUTF8_TextEncoding by default.
3801
3802#Const kUTF8_TextEncoding 0
Cary Clark682c58d2018-05-16 07:07:07 -04003803#Line # uses bytes to represent UTF-8 or ASCII ##
Cary Clark8032b982017-07-28 11:04:54 -04003804##
3805#Const kUTF16_TextEncoding 1
Cary Clark682c58d2018-05-16 07:07:07 -04003806#Line # uses two byte words to represent most of Unicode ##
Cary Clark8032b982017-07-28 11:04:54 -04003807##
3808#Const kUTF32_TextEncoding 2
Cary Clark682c58d2018-05-16 07:07:07 -04003809#Line # uses four byte words to represent all of Unicode ##
Cary Clark8032b982017-07-28 11:04:54 -04003810##
3811#Const kGlyphID_TextEncoding 3
Cary Clark682c58d2018-05-16 07:07:07 -04003812#Line # uses two byte words to represent glyph indices ##
Cary Clark8032b982017-07-28 11:04:54 -04003813##
3814
3815#Enum ##
3816
3817#Example
3818#Height 128
3819#Description
Cary Clarkbc5697d2017-10-04 14:31:33 -04003820First line is encoded in UTF-8.
3821Second line is encoded in UTF-16.
3822Third line is encoded in UTF-32.
Cary Clark682c58d2018-05-16 07:07:07 -04003823Fourth line has 16-bit glyph indices.
Cary Clark8032b982017-07-28 11:04:54 -04003824##
3825void draw(SkCanvas* canvas) {
3826 SkPaint paint;
3827 const char hello8[] = "Hello" "\xE2" "\x98" "\xBA";
3828 const uint16_t hello16[] = { 'H', 'e', 'l', 'l', 'o', 0x263A };
3829 const uint32_t hello32[] = { 'H', 'e', 'l', 'l', 'o', 0x263A };
3830 paint.setTextSize(24);
3831 canvas->drawText(hello8, sizeof(hello8) - 1, 10, 30, paint);
3832 paint.setTextEncoding(SkPaint::kUTF16_TextEncoding);
3833 canvas->drawText(hello16, sizeof(hello16), 10, 60, paint);
3834 paint.setTextEncoding(SkPaint::kUTF32_TextEncoding);
3835 canvas->drawText(hello32, sizeof(hello32), 10, 90, paint);
3836 uint16_t glyphs[SK_ARRAY_COUNT(hello32)];
3837 paint.textToGlyphs(hello32, sizeof(hello32), glyphs);
3838 paint.setTextEncoding(SkPaint::kGlyphID_TextEncoding);
3839 canvas->drawText(glyphs, sizeof(glyphs), 10, 120, paint);
3840}
3841##
3842
3843#Method TextEncoding getTextEncoding() const
3844
Cary Clarkab2621d2018-01-30 10:08:57 -05003845#In Text_Encoding
3846#Line # returns character or glyph encoded size ##
Cary Clark8032b982017-07-28 11:04:54 -04003847 Returns Text_Encoding.
3848 Text_Encoding determines how character code points are mapped to font glyph indices.
3849
Herb Derbyfcac00f2018-05-01 11:57:56 -04003850 #Return one of: kUTF8_TextEncoding, kUTF16_TextEncoding, kUTF32_TextEncoding, or
3851 kGlyphID_TextEncoding
Cary Clark8032b982017-07-28 11:04:54 -04003852 ##
3853
3854 #Example
3855 SkPaint paint;
Herb Derbyfcac00f2018-05-01 11:57:56 -04003856 SkDebugf("kUTF8_TextEncoding %c= text encoding\n",
Cary Clark8032b982017-07-28 11:04:54 -04003857 SkPaint::kUTF8_TextEncoding == paint.getTextEncoding() ? '=' : '!');
3858 paint.setTextEncoding(SkPaint::kGlyphID_TextEncoding);
Herb Derbyfcac00f2018-05-01 11:57:56 -04003859 SkDebugf("kGlyphID_TextEncoding %c= text encoding\n",
Cary Clark8032b982017-07-28 11:04:54 -04003860 SkPaint::kGlyphID_TextEncoding == paint.getTextEncoding() ? '=' : '!');
3861
3862 #StdOut
3863 kUTF8_TextEncoding == text encoding
3864 kGlyphID_TextEncoding == text encoding
3865 ##
3866 ##
3867
3868##
3869
3870
3871#Method void setTextEncoding(TextEncoding encoding)
3872
Cary Clarkab2621d2018-01-30 10:08:57 -05003873#In Text_Encoding
3874#Line # sets character or glyph encoded size ##
Herb Derbyfcac00f2018-05-01 11:57:56 -04003875 Sets Text_Encoding to encoding.
Cary Clark8032b982017-07-28 11:04:54 -04003876 Text_Encoding determines how character code points are mapped to font glyph indices.
3877 Invalid values for encoding are ignored.
3878
Herb Derbyfcac00f2018-05-01 11:57:56 -04003879 #Param encoding one of: kUTF8_TextEncoding, kUTF16_TextEncoding, kUTF32_TextEncoding, or
3880 kGlyphID_TextEncoding
Cary Clark579985c2017-07-31 11:48:27 -04003881 #Param ##
Cary Clark8032b982017-07-28 11:04:54 -04003882
3883 #Example
3884 SkPaint paint;
3885 paint.setTextEncoding((SkPaint::TextEncoding) 4);
3886 SkDebugf("4 %c= text encoding\n", 4 == paint.getTextEncoding() ? '=' : '!');
3887
3888 #StdOut
3889 4 != text encoding
3890 ##
3891 ##
3892
3893##
3894
Cary Clark08895c42018-02-01 09:37:32 -05003895#Subtopic Text_Encoding ##
Cary Clark8032b982017-07-28 11:04:54 -04003896# ------------------------------------------------------------------------------
Cary Clark08895c42018-02-01 09:37:32 -05003897#Subtopic Font_Metrics
3898#Line # common glyph dimensions ##
Cary Clark8032b982017-07-28 11:04:54 -04003899
Cary Clarkce101242017-09-01 15:51:02 -04003900Font_Metrics describe dimensions common to the Glyphs in Typeface.
Herb Derbyfcac00f2018-05-01 11:57:56 -04003901The dimensions are computed by Font_Manager from font data and do not take
Cary Clark8032b982017-07-28 11:04:54 -04003902Paint settings other than Text_Size into account.
3903
3904Font dimensions specify the anchor to the left of the glyph at baseline as the origin.
3905X-axis values to the left of the glyph are negative, and to the right of the left glyph edge
3906are positive.
3907Y-axis values above the baseline are negative, and below the baseline are positive.
Ben Wagnere5806492017-11-09 12:08:31 -05003908
Cary Clark8032b982017-07-28 11:04:54 -04003909#Example
3910#Width 512
3911void draw(SkCanvas* canvas) {
3912 SkPaint paint;
3913 paint.setAntiAlias(true);
3914 paint.setTextSize(120);
3915 SkPaint::FontMetrics fm;
3916 SkScalar lineHeight = paint.getFontMetrics(&fm);
3917 SkPoint pt = { 70, 180 };
3918 canvas->drawString("M", pt.fX, pt.fY, paint);
3919 canvas->drawLine(pt.fX, pt.fY, pt.fX, pt.fY + fm.fTop, paint);
3920 SkScalar ascent = pt.fY + fm.fAscent;
3921 canvas->drawLine(pt.fX - 25, ascent, pt.fX - 25, ascent + lineHeight, paint);
3922 canvas->drawLine(pt.fX - 50, pt.fY, pt.fX - 50, pt.fY + fm.fDescent, paint);
3923 canvas->drawLine(pt.fX + 100, pt.fY, pt.fX + 100, pt.fY + fm.fAscent, paint);
3924 canvas->drawLine(pt.fX + 125, pt.fY, pt.fX + 125, pt.fY - fm.fXHeight, paint);
3925 canvas->drawLine(pt.fX + 150, pt.fY, pt.fX + 150, pt.fY - fm.fCapHeight, paint);
3926 canvas->drawLine(pt.fX + 5, pt.fY, pt.fX + 5, pt.fY + fm.fBottom, paint);
3927 SkScalar xmin = pt.fX + fm.fXMin;
3928 canvas->drawLine(xmin, pt.fY + 60, xmin + fm.fMaxCharWidth, pt.fY + 60, paint);
3929 canvas->drawLine(xmin, pt.fY - 145, pt.fX, pt.fY - 145, paint);
3930 canvas->drawLine(pt.fX + fm.fXMax, pt.fY - 160, pt.fX, pt.fY - 160, paint);
3931 SkScalar upos = pt.fY + fm.fUnderlinePosition;
Ben Wagnere5806492017-11-09 12:08:31 -05003932 canvas->drawLine(pt.fX + 25, upos, pt.fX + 160, upos, paint);
3933 SkScalar ut = fm.fUnderlineThickness;
3934 canvas->drawLine(pt.fX + 130, upos + ut, pt.fX + 160, upos + ut, paint);
Cary Clark8032b982017-07-28 11:04:54 -04003935 paint.setTextSize(12);
3936 canvas->drawString("x-min", pt.fX - 50, pt.fY - 148, paint);
3937 canvas->drawString("x-max", pt.fX + 140, pt.fY - 150, paint);
3938 canvas->drawString("max char width", pt.fX + 120, pt.fY + 57, paint);
3939 canvas->drawString("underline position", pt.fX + 30, pt.fY + 22, paint);
3940 canvas->drawString("underline thickness", pt.fX + 162, pt.fY + 13, paint);
3941 canvas->rotate(-90);
3942 canvas->drawString("descent", -pt.fY - 30, pt.fX - 54, paint);
3943 canvas->drawString("line height", -pt.fY, pt.fX - 29, paint);
3944 canvas->drawString("top", -pt.fY + 30, pt.fX - 4, paint);
3945 canvas->drawString("ascent", -pt.fY, pt.fX + 110, paint);
3946 canvas->drawString("x-height", -pt.fY, pt.fX + 135, paint);
3947 canvas->drawString("cap-height", -pt.fY, pt.fX + 160, paint);
3948 canvas->drawString("bottom", -pt.fY - 50, pt.fX + 15, paint);
3949}
3950##
3951
3952#Struct FontMetrics
Cary Clark08895c42018-02-01 09:37:32 -05003953#Line # values computed by Font_Manager using Typeface ##
Cary Clark8032b982017-07-28 11:04:54 -04003954
3955#Code
3956 struct FontMetrics {
3957 enum FontMetricsFlags {
3958 kUnderlineThicknessIsValid_Flag = 1 << 0,
3959 kUnderlinePositionIsValid_Flag = 1 << 1,
3960 kStrikeoutThicknessIsValid_Flag = 1 << 2,
3961 kStrikeoutPositionIsValid_Flag = 1 << 3,
3962 };
3963
3964 uint32_t fFlags;
3965 SkScalar fTop;
3966 SkScalar fAscent;
3967 SkScalar fDescent;
3968 SkScalar fBottom;
3969 SkScalar fLeading;
3970 SkScalar fAvgCharWidth;
3971 SkScalar fMaxCharWidth;
3972 SkScalar fXMin;
3973 SkScalar fXMax;
3974 SkScalar fXHeight;
3975 SkScalar fCapHeight;
3976 SkScalar fUnderlineThickness;
3977 SkScalar fUnderlinePosition;
3978 SkScalar fStrikeoutThickness;
3979 SkScalar fStrikeoutPosition;
3980
3981 bool hasUnderlineThickness(SkScalar* thickness) const;
3982 bool hasUnderlinePosition(SkScalar* position) const;
3983 bool hasStrikeoutThickness(SkScalar* thickness) const;
3984 bool hasStrikeoutPosition(SkScalar* position) const;
3985 };
3986##
3987
Cary Clark154beea2017-10-26 07:58:48 -04003988 FontMetrics is filled out by getFontMetrics. FontMetrics contents reflect the values
3989 computed by Font_Manager using Typeface. Values are set to zero if they are
3990 not available.
Cary Clarke4aa3712017-09-15 02:56:12 -04003991
Ben Wagnere5806492017-11-09 12:08:31 -05003992 All vertical values relative to the baseline are given y-down. As such, zero is on the
3993 baseline, negative values are above the baseline, and positive values are below the
3994 baseline.
3995
Cary Clark154beea2017-10-26 07:58:48 -04003996 fUnderlineThickness and fUnderlinePosition have a bit set in fFlags if their values
3997 are valid, since their value may be zero.
Ben Wagnere5806492017-11-09 12:08:31 -05003998
Cary Clark154beea2017-10-26 07:58:48 -04003999 fStrikeoutThickness and fStrikeoutPosition have a bit set in fFlags if their values
4000 are valid, since their value may be zero.
4001
4002 #Enum FontMetricsFlags
Cary Clark682c58d2018-05-16 07:07:07 -04004003 #Line # valid Font_Metrics ##
Cary Clarke4aa3712017-09-15 02:56:12 -04004004
Cary Clark8032b982017-07-28 11:04:54 -04004005 #Code
4006 enum FontMetricsFlags {
4007 kUnderlineThicknessIsValid_Flag = 1 << 0,
4008 kUnderlinePositionIsValid_Flag = 1 << 1,
4009 kStrikeoutThicknessIsValid_Flag = 1 << 2,
4010 kStrikeoutPositionIsValid_Flag = 1 << 3,
4011 };
4012 ##
4013
Cary Clark154beea2017-10-26 07:58:48 -04004014 FontMetricsFlags are set in fFlags when underline and strikeout metrics are valid;
4015 the underline or strikeout metric may be valid and zero.
4016 Fonts with embedded bitmaps may not have valid underline or strikeout metrics.
4017
Cary Clark8032b982017-07-28 11:04:54 -04004018 #Const kUnderlineThicknessIsValid_Flag 0x0001
Cary Clark682c58d2018-05-16 07:07:07 -04004019 #Line # set if fUnderlineThickness is valid ##
Cary Clark8032b982017-07-28 11:04:54 -04004020 ##
4021 #Const kUnderlinePositionIsValid_Flag 0x0002
Cary Clark682c58d2018-05-16 07:07:07 -04004022 #Line # set if fUnderlinePosition is valid ##
Cary Clark8032b982017-07-28 11:04:54 -04004023 ##
4024 #Const kStrikeoutThicknessIsValid_Flag 0x0004
Cary Clark682c58d2018-05-16 07:07:07 -04004025 #Line # set if fStrikeoutThickness is valid ##
Cary Clark8032b982017-07-28 11:04:54 -04004026 ##
4027 #Const kStrikeoutPositionIsValid_Flag 0x0008
Cary Clark682c58d2018-05-16 07:07:07 -04004028 #Line # set if fStrikeoutPosition is valid ##
Cary Clark8032b982017-07-28 11:04:54 -04004029 ##
4030
4031 #Enum ##
4032
4033 #Member uint32_t fFlags
Cary Clark682c58d2018-05-16 07:07:07 -04004034 #Line # is set to FontMetricsFlags when metrics are valid ##
Cary Clark8032b982017-07-28 11:04:54 -04004035 ##
Ben Wagnere5806492017-11-09 12:08:31 -05004036
Cary Clark8032b982017-07-28 11:04:54 -04004037 #Member SkScalar fTop
Cary Clark682c58d2018-05-16 07:07:07 -04004038 #Line # extent above baseline ##
Ben Wagnere5806492017-11-09 12:08:31 -05004039 Greatest extent above the baseline for any glyph.
4040 Typically less than zero.
Cary Clark8032b982017-07-28 11:04:54 -04004041 ##
Ben Wagnere5806492017-11-09 12:08:31 -05004042
Cary Clark8032b982017-07-28 11:04:54 -04004043 #Member SkScalar fAscent
Cary Clark682c58d2018-05-16 07:07:07 -04004044 #Line # distance to reserve above baseline ##
Cary Clark8032b982017-07-28 11:04:54 -04004045 Recommended distance above the baseline to reserve for a line of text.
Ben Wagnere5806492017-11-09 12:08:31 -05004046 Typically less than zero.
Cary Clark8032b982017-07-28 11:04:54 -04004047 ##
Ben Wagnere5806492017-11-09 12:08:31 -05004048
Cary Clark8032b982017-07-28 11:04:54 -04004049 #Member SkScalar fDescent
Cary Clark682c58d2018-05-16 07:07:07 -04004050 #Line # distance to reserve below baseline ##
Cary Clark8032b982017-07-28 11:04:54 -04004051 Recommended distance below the baseline to reserve for a line of text.
Ben Wagnere5806492017-11-09 12:08:31 -05004052 Typically greater than zero.
Cary Clark8032b982017-07-28 11:04:54 -04004053 ##
Ben Wagnere5806492017-11-09 12:08:31 -05004054
Cary Clark8032b982017-07-28 11:04:54 -04004055 #Member SkScalar fBottom
Cary Clark682c58d2018-05-16 07:07:07 -04004056 #Line # extent below baseline ##
Ben Wagnere5806492017-11-09 12:08:31 -05004057 Greatest extent below the baseline for any glyph.
4058 Typically greater than zero.
Cary Clark8032b982017-07-28 11:04:54 -04004059 ##
Ben Wagnere5806492017-11-09 12:08:31 -05004060
Cary Clark8032b982017-07-28 11:04:54 -04004061 #Member SkScalar fLeading
Cary Clark682c58d2018-05-16 07:07:07 -04004062 #Line # distance to add between lines ##
Cary Clark8032b982017-07-28 11:04:54 -04004063 Recommended distance to add between lines of text.
Ben Wagnere5806492017-11-09 12:08:31 -05004064 Typically greater than or equal to zero.
Cary Clark8032b982017-07-28 11:04:54 -04004065 ##
Ben Wagnere5806492017-11-09 12:08:31 -05004066
Cary Clark8032b982017-07-28 11:04:54 -04004067 #Member SkScalar fAvgCharWidth
Cary Clark682c58d2018-05-16 07:07:07 -04004068 #Line # average character width ##
Cary Clark8032b982017-07-28 11:04:54 -04004069 Average character width, if it is available.
4070 Zero if no average width is stored in the font.
4071 ##
Ben Wagnere5806492017-11-09 12:08:31 -05004072
Cary Clark8032b982017-07-28 11:04:54 -04004073 #Member SkScalar fMaxCharWidth
Cary Clark682c58d2018-05-16 07:07:07 -04004074 #Line # maximum character width ##
Cary Clark8032b982017-07-28 11:04:54 -04004075 ##
Ben Wagnere5806492017-11-09 12:08:31 -05004076
Cary Clark8032b982017-07-28 11:04:54 -04004077 #Member SkScalar fXMin
Cary Clark682c58d2018-05-16 07:07:07 -04004078 #Line # minimum x ##
4079 Minimum bounding box x-value for all Glyphs.
Cary Clark8032b982017-07-28 11:04:54 -04004080 Typically less than zero.
4081 ##
Ben Wagnere5806492017-11-09 12:08:31 -05004082
Cary Clark8032b982017-07-28 11:04:54 -04004083 #Member SkScalar fXMax
Cary Clark682c58d2018-05-16 07:07:07 -04004084 #Line # maximum x ##
Cary Clarkce101242017-09-01 15:51:02 -04004085 Maximum bounding box x value for all Glyphs.
Cary Clark8032b982017-07-28 11:04:54 -04004086 Typically greater than zero.
4087 ##
Ben Wagnere5806492017-11-09 12:08:31 -05004088
Cary Clark8032b982017-07-28 11:04:54 -04004089 #Member SkScalar fXHeight
Cary Clark682c58d2018-05-16 07:07:07 -04004090 #Line # height of lower-case 'x' ##
Cary Clark8032b982017-07-28 11:04:54 -04004091 May be zero if no lower-case height is stored in the font.
4092 ##
Ben Wagnere5806492017-11-09 12:08:31 -05004093
Cary Clark8032b982017-07-28 11:04:54 -04004094 #Member SkScalar fCapHeight
Cary Clark682c58d2018-05-16 07:07:07 -04004095 #Line # height of an upper-case letter ##
Cary Clark8032b982017-07-28 11:04:54 -04004096 May be zero if no upper-case height is stored in the font.
4097 ##
Ben Wagnere5806492017-11-09 12:08:31 -05004098
Cary Clark8032b982017-07-28 11:04:54 -04004099 #Member SkScalar fUnderlineThickness
Cary Clark682c58d2018-05-16 07:07:07 -04004100 #Line # underline thickness ##
Ben Wagnere5806492017-11-09 12:08:31 -05004101 If the metric is valid, the kUnderlineThicknessIsValid_Flag is set in fFlags.
Cary Clark8032b982017-07-28 11:04:54 -04004102 If kUnderlineThicknessIsValid_Flag is clear, fUnderlineThickness is zero.
4103 ##
Ben Wagnere5806492017-11-09 12:08:31 -05004104
Cary Clark8032b982017-07-28 11:04:54 -04004105 #Member SkScalar fUnderlinePosition
Cary Clark682c58d2018-05-16 07:07:07 -04004106 #Line # underline position relative to baseline ##
Ben Wagnere5806492017-11-09 12:08:31 -05004107 Position of the top of the underline stroke relative to the baseline.
4108 Typically positive when valid.
Cary Clark8032b982017-07-28 11:04:54 -04004109
4110 If the metric is valid, the kUnderlinePositionIsValid_Flag is set in fFlags.
4111 If kUnderlinePositionIsValid_Flag is clear, fUnderlinePosition is zero.
4112 ##
4113
4114 #Member SkScalar fStrikeoutThickness
Cary Clark682c58d2018-05-16 07:07:07 -04004115 #Line # strikeout thickness ##
Ben Wagnere5806492017-11-09 12:08:31 -05004116
4117 If the metric is valid, the kStrikeoutThicknessIsValid_Flag is set in fFlags.
Cary Clark8032b982017-07-28 11:04:54 -04004118 If kStrikeoutThicknessIsValid_Flag is clear, fStrikeoutThickness is zero.
4119 ##
4120
4121 #Member SkScalar fStrikeoutPosition
Cary Clark682c58d2018-05-16 07:07:07 -04004122 #Line # strikeout position relative to baseline ##
Ben Wagnere5806492017-11-09 12:08:31 -05004123 Position of the bottom of the strikeout stroke relative to the baseline.
4124 Typically negative when valid.
Cary Clark8032b982017-07-28 11:04:54 -04004125
Ben Wagnere5806492017-11-09 12:08:31 -05004126 If the metric is valid, the kStrikeoutPositionIsValid_Flag is set in fFlags.
4127 If kStrikeoutPositionIsValid_Flag is clear, fStrikeoutPosition is zero.
Cary Clark8032b982017-07-28 11:04:54 -04004128 ##
4129
4130 #Method bool hasUnderlineThickness(SkScalar* thickness) const
Cary Clark682c58d2018-05-16 07:07:07 -04004131 #Line # returns underline thickness if set ##
Cary Clark8032b982017-07-28 11:04:54 -04004132
Ben Wagnere5806492017-11-09 12:08:31 -05004133 If Font_Metrics has a valid underline thickness, return true, and set
Cary Clarkce101242017-09-01 15:51:02 -04004134 thickness to that value. If the underline thickness is not valid,
4135 return false, and ignore thickness.
Cary Clark8032b982017-07-28 11:04:54 -04004136
4137 #Param thickness storage for underline width ##
4138
4139 #Return true if font specifies underline width ##
4140
4141 #NoExample
4142 ##
4143 ##
4144
4145 #Method bool hasUnderlinePosition(SkScalar* position) const
Cary Clark682c58d2018-05-16 07:07:07 -04004146 #Line # returns underline position if set ##
Cary Clark8032b982017-07-28 11:04:54 -04004147
Ben Wagnere5806492017-11-09 12:08:31 -05004148 If Font_Metrics has a valid underline position, return true, and set
Cary Clarkce101242017-09-01 15:51:02 -04004149 position to that value. If the underline position is not valid,
4150 return false, and ignore position.
Cary Clark8032b982017-07-28 11:04:54 -04004151
4152 #Param position storage for underline position ##
4153
4154 #Return true if font specifies underline position ##
4155
4156 #NoExample
4157 ##
4158 ##
4159
4160 #Method bool hasStrikeoutThickness(SkScalar* thickness) const
Cary Clark682c58d2018-05-16 07:07:07 -04004161 #Line # returns strikeout thickness if set ##
Cary Clark8032b982017-07-28 11:04:54 -04004162
Ben Wagnere5806492017-11-09 12:08:31 -05004163 If Font_Metrics has a valid strikeout thickness, return true, and set
Cary Clarkce101242017-09-01 15:51:02 -04004164 thickness to that value. If the underline thickness is not valid,
4165 return false, and ignore thickness.
Cary Clark8032b982017-07-28 11:04:54 -04004166
4167 #Param thickness storage for strikeout width ##
4168
4169 #Return true if font specifies strikeout width ##
4170
4171 #NoExample
4172 ##
4173 ##
4174
4175 #Method bool hasStrikeoutPosition(SkScalar* position) const
Cary Clark682c58d2018-05-16 07:07:07 -04004176 #Line # returns strikeout position if set ##
Cary Clark8032b982017-07-28 11:04:54 -04004177
Ben Wagnere5806492017-11-09 12:08:31 -05004178 If Font_Metrics has a valid strikeout position, return true, and set
Cary Clarkce101242017-09-01 15:51:02 -04004179 position to that value. If the underline position is not valid,
4180 return false, and ignore position.
Cary Clark8032b982017-07-28 11:04:54 -04004181
4182 #Param position storage for strikeout position ##
4183
4184 #Return true if font specifies strikeout position ##
4185
4186 #NoExample
4187 ##
4188 ##
4189
4190#Struct ##
4191
4192#Method SkScalar getFontMetrics(FontMetrics* metrics, SkScalar scale = 0) const
4193
Cary Clarkab2621d2018-01-30 10:08:57 -05004194#In Font_Metrics
4195#Line # returns Typeface metrics scaled by text size ##
Cary Clark8032b982017-07-28 11:04:54 -04004196 Returns Font_Metrics associated with Typeface.
4197 The return value is the recommended spacing between lines: the sum of metrics
4198 descent, ascent, and leading.
4199 If metrics is not nullptr, Font_Metrics is copied to metrics.
4200 Results are scaled by Text_Size but does not take into account
4201 dimensions required by Text_Scale_X, Text_Skew_X, Fake_Bold,
4202 Style_Stroke, and Path_Effect.
4203 Results can be additionally scaled by scale; a scale of zero
4204 is ignored.
4205
4206 #Param metrics storage for Font_Metrics from Typeface; may be nullptr ##
4207 #Param scale additional multiplier for returned values ##
4208
4209 #Return recommended spacing between lines ##
4210
4211 #Example
4212 #Height 128
4213 void draw(SkCanvas* canvas) {
4214 SkPaint paint;
4215 paint.setTextSize(32);
4216 SkScalar lineHeight = paint.getFontMetrics(nullptr);
4217 canvas->drawString("line 1", 10, 40, paint);
4218 canvas->drawString("line 2", 10, 40 + lineHeight, paint);
4219 paint.setStyle(SkPaint::kStroke_Style);
4220 paint.setStrokeWidth(10);
4221 lineHeight = paint.getFontMetrics(nullptr, 1.10f); // account for stroke height
4222 canvas->drawString("line 3", 120, 40, paint);
4223 canvas->drawString("line 4", 120, 40 + lineHeight, paint);
4224 }
4225 ##
4226
4227 #SeeAlso Text_Size Typeface Typeface_Methods
4228
4229##
4230
4231
4232#Method SkScalar getFontSpacing() const
4233
Cary Clarkab2621d2018-01-30 10:08:57 -05004234#In Font_Metrics
4235#Line # returns recommended spacing between lines ##
Cary Clark8032b982017-07-28 11:04:54 -04004236 Returns the recommended spacing between lines: the sum of metrics
4237 descent, ascent, and leading.
4238 Result is scaled by Text_Size but does not take into account
4239 dimensions required by stroking and Path_Effect.
Cary Clark579985c2017-07-31 11:48:27 -04004240 Returns the same result as getFontMetrics.
Cary Clark8032b982017-07-28 11:04:54 -04004241
Cary Clark0c5f5462017-12-15 11:21:51 -05004242 #Return recommended spacing between lines ##
Cary Clark8032b982017-07-28 11:04:54 -04004243
4244 #Example
4245 SkPaint paint;
4246 for (SkScalar textSize : { 12, 18, 24, 32 } ) {
4247 paint.setTextSize(textSize);
4248 SkDebugf("textSize: %g fontSpacing: %g\n", textSize, paint.getFontSpacing());
4249 }
4250
4251 #StdOut
4252 textSize: 12 fontSpacing: 13.9688
4253 textSize: 18 fontSpacing: 20.9531
4254 textSize: 24 fontSpacing: 27.9375
4255 textSize: 32 fontSpacing: 37.25
4256 ##
4257 ##
4258
4259##
4260
4261
4262#Method SkRect getFontBounds() const
4263
Cary Clarkab2621d2018-01-30 10:08:57 -05004264#In Font_Metrics
4265#Line # returns union all glyph bounds ##
Cary Clarkce101242017-09-01 15:51:02 -04004266Returns the union of bounds of all Glyphs.
Herb Derbyfcac00f2018-05-01 11:57:56 -04004267Returned dimensions are computed by Font_Manager from font data,
Cary Clark579985c2017-07-31 11:48:27 -04004268ignoring Hinting. Includes Text_Size, Text_Scale_X,
Cary Clark8032b982017-07-28 11:04:54 -04004269and Text_Skew_X, but not Fake_Bold or Path_Effect.
4270
4271If Text_Size is large, Text_Scale_X is one, and Text_Skew_X is zero,
Herb Derbyfcac00f2018-05-01 11:57:56 -04004272returns the same bounds as Font_Metrics { FontMetrics::fXMin,
Cary Clark8032b982017-07-28 11:04:54 -04004273FontMetrics::fTop, FontMetrics::fXMax, FontMetrics::fBottom }.
4274
Cary Clarkce101242017-09-01 15:51:02 -04004275#Return union of bounds of all Glyphs ##
Cary Clark8032b982017-07-28 11:04:54 -04004276
4277#Example
4278 SkPaint paint;
4279 SkPaint::FontMetrics fm;
4280 paint.getFontMetrics(&fm);
4281 SkRect fb = paint.getFontBounds();
4282 SkDebugf("metrics bounds = { %g, %g, %g, %g }\n", fm.fXMin, fm.fTop, fm.fXMax, fm.fBottom );
4283 SkDebugf("font bounds = { %g, %g, %g, %g }\n", fb.fLeft, fb.fTop, fb.fRight, fm.fBottom );
4284
4285 #StdOut
4286 metrics bounds = { -12.2461, -14.7891, 21.5215, 5.55469 }
4287 font bounds = { -12.2461, -14.7891, 21.5215, 5.55469 }
4288 ##
4289##
4290
4291##
4292
Cary Clark08895c42018-02-01 09:37:32 -05004293#Subtopic Font_Metrics ##
Cary Clark8032b982017-07-28 11:04:54 -04004294# ------------------------------------------------------------------------------
4295
4296#Method int textToGlyphs(const void* text, size_t byteLength,
4297 SkGlyphID glyphs[]) const
Cary Clark78de7512018-02-07 07:27:09 -05004298#In Utility
Cary Clarkab2621d2018-01-30 10:08:57 -05004299#Line # converts text into glyph indices ##
Cary Clark8032b982017-07-28 11:04:54 -04004300
4301Converts text into glyph indices.
4302Returns the number of glyph indices represented by text.
4303Text_Encoding specifies how text represents characters or glyphs.
4304glyphs may be nullptr, to compute the glyph count.
4305
Cary Clarkbc5697d2017-10-04 14:31:33 -04004306Does not check text for valid character codes or valid glyph indices.
Cary Clark8032b982017-07-28 11:04:54 -04004307
Cary Clark579985c2017-07-31 11:48:27 -04004308If byteLength equals zero, returns zero.
Cary Clark8032b982017-07-28 11:04:54 -04004309If byteLength includes a partial character, the partial character is ignored.
4310
4311If Text_Encoding is kUTF8_TextEncoding and
4312text contains an invalid UTF-8 sequence, zero is returned.
4313
Cary Clarkce101242017-09-01 15:51:02 -04004314#Param text character storage encoded with Text_Encoding ##
Cary Clark8032b982017-07-28 11:04:54 -04004315#Param byteLength length of character storage in bytes ##
4316#Param glyphs storage for glyph indices; may be nullptr ##
4317
4318#Return number of glyphs represented by text of length byteLength ##
4319
4320 #Example
4321 #Height 64
4322 void draw(SkCanvas* canvas) {
4323 SkPaint paint;
4324 const uint8_t utf8[] = { 0x24, 0xC2, 0xA2, 0xE2, 0x82, 0xAC, 0xC2, 0xA5, 0xC2, 0xA3 };
4325 std::vector<SkGlyphID> glyphs;
4326 int count = paint.textToGlyphs(utf8, sizeof(utf8), nullptr);
4327 glyphs.resize(count);
4328 (void) paint.textToGlyphs(utf8, sizeof(utf8), &glyphs.front());
4329 paint.setTextEncoding(SkPaint::kGlyphID_TextEncoding);
4330 paint.setTextSize(32);
4331 canvas->drawText(&glyphs.front(), glyphs.size() * sizeof(SkGlyphID), 10, 40, paint);
4332 }
4333 ##
4334
4335##
4336
4337#Method int countText(const void* text, size_t byteLength) const
Cary Clark78de7512018-02-07 07:27:09 -05004338#In Utility
Cary Clarkab2621d2018-01-30 10:08:57 -05004339#Line # returns number of Glyphs in text ##
Cary Clarkce101242017-09-01 15:51:02 -04004340 Returns the number of Glyphs in text.
4341 Uses Text_Encoding to count the Glyphs.
Cary Clark8032b982017-07-28 11:04:54 -04004342 Returns the same result as textToGlyphs.
4343
Cary Clarkce101242017-09-01 15:51:02 -04004344#Param text character storage encoded with Text_Encoding ##
Cary Clark8032b982017-07-28 11:04:54 -04004345#Param byteLength length of character storage in bytes ##
4346
Cary Clarkce101242017-09-01 15:51:02 -04004347#Return number of Glyphs represented by text of length byteLength ##
Cary Clark8032b982017-07-28 11:04:54 -04004348
4349 #Example
4350 SkPaint paint;
4351 const uint8_t utf8[] = { 0x24, 0xC2, 0xA2, 0xE2, 0x82, 0xAC, 0xC2, 0xA5, 0xC2, 0xA3 };
4352 SkDebugf("count = %d\n", paint.countText(utf8, sizeof(utf8)));
4353
4354 #StdOut
4355 count = 5
4356 ##
4357 ##
4358##
4359
4360# ------------------------------------------------------------------------------
4361
4362#Method bool containsText(const void* text, size_t byteLength) const
Cary Clark78de7512018-02-07 07:27:09 -05004363#In Utility
Cary Clarkab2621d2018-01-30 10:08:57 -05004364#Line # returns if all text corresponds to Glyphs ##
Herb Derbyfcac00f2018-05-01 11:57:56 -04004365 Returns true if all text corresponds to a non-zero glyph index.
Cary Clark8032b982017-07-28 11:04:54 -04004366 Returns false if any characters in text are not supported in
4367 Typeface.
4368
Cary Clark579985c2017-07-31 11:48:27 -04004369 If Text_Encoding is kGlyphID_TextEncoding,
4370 returns true if all glyph indices in text are non-zero;
Cary Clark8032b982017-07-28 11:04:54 -04004371 does not check to see if text contains valid glyph indices for Typeface.
4372
Cary Clarkce101242017-09-01 15:51:02 -04004373 Returns true if byteLength is zero.
Cary Clark8032b982017-07-28 11:04:54 -04004374
Cary Clarkce101242017-09-01 15:51:02 -04004375 #Param text array of characters or Glyphs ##
Cary Clark8032b982017-07-28 11:04:54 -04004376 #Param byteLength number of bytes in text array ##
4377
4378 #Return true if all text corresponds to a non-zero glyph index ##
4379
4380 #Example
4381 #Description
4382 containsText succeeds for degree symbol, but cannot find a glyph index
4383 corresponding to the Unicode surrogate code point.
4384 ##
4385 SkPaint paint;
4386 const uint16_t goodChar = 0x00B0; // degree symbol
4387 const uint16_t badChar = 0xD800; // Unicode surrogate
4388 paint.setTextEncoding(SkPaint::kUTF16_TextEncoding);
Herb Derbyfcac00f2018-05-01 11:57:56 -04004389 SkDebugf("0x%04x %c= has char\n", goodChar,
Cary Clark8032b982017-07-28 11:04:54 -04004390 paint.containsText(&goodChar, 2) ? '=' : '!');
4391 SkDebugf("0x%04x %c= has char\n", badChar,
4392 paint.containsText(&badChar, 2) ? '=' : '!');
4393
4394 #StdOut
4395 0x00b0 == has char
4396 0xd800 != has char
4397 ##
4398 ##
4399
4400 #Example
4401 #Description
4402 containsText returns true that glyph index is greater than zero, not
4403 that it corresponds to an entry in Typeface.
4404 ##
4405 SkPaint paint;
4406 const uint16_t goodGlyph = 511;
4407 const uint16_t zeroGlyph = 0;
4408 const uint16_t badGlyph = 65535; // larger than glyph count in font
4409 paint.setTextEncoding(SkPaint::kGlyphID_TextEncoding);
Herb Derbyfcac00f2018-05-01 11:57:56 -04004410 SkDebugf("0x%04x %c= has glyph\n", goodGlyph,
Cary Clark8032b982017-07-28 11:04:54 -04004411 paint.containsText(&goodGlyph, 2) ? '=' : '!');
4412 SkDebugf("0x%04x %c= has glyph\n", zeroGlyph,
4413 paint.containsText(&zeroGlyph, 2) ? '=' : '!');
4414 SkDebugf("0x%04x %c= has glyph\n", badGlyph,
4415 paint.containsText(&badGlyph, 2) ? '=' : '!');
4416
4417 #StdOut
4418 0x01ff == has glyph
4419 0x0000 != has glyph
4420 0xffff == has glyph
4421 ##
4422 ##
4423
4424#SeeAlso setTextEncoding Typeface
4425
4426##
4427
4428# ------------------------------------------------------------------------------
4429
4430#Method void glyphsToUnichars(const SkGlyphID glyphs[],
4431 int count, SkUnichar text[]) const
Cary Clark78de7512018-02-07 07:27:09 -05004432#In Utility
Cary Clarkab2621d2018-01-30 10:08:57 -05004433#Line # converts Glyphs into text ##
Cary Clark8032b982017-07-28 11:04:54 -04004434
Herb Derbyfcac00f2018-05-01 11:57:56 -04004435 Converts glyphs into text if possible.
4436 Glyph values without direct Unicode equivalents are mapped to zero.
Cary Clark8032b982017-07-28 11:04:54 -04004437 Uses the Typeface, but is unaffected
4438 by Text_Encoding; the text values returned are equivalent to kUTF32_TextEncoding.
4439
4440 Only supported on platforms that use FreeType as the Font_Engine.
4441
4442 #Param glyphs array of indices into font ##
4443 #Param count length of glyph array ##
4444 #Param text storage for character codes, one per glyph ##
4445
4446 #Example
4447 #Height 64
4448 #Description
4449 Convert UTF-8 text to glyphs; then convert glyphs to Unichar code points.
4450 ##
4451 void draw(SkCanvas* canvas) {
4452 SkPaint paint;
4453 const char hello[] = "Hello!";
4454 const int count = sizeof(hello) - 1;
4455 SkGlyphID glyphs[count];
4456 if (count != paint.textToGlyphs(hello, count, glyphs)) {
4457 return;
4458 }
4459 SkUnichar unichars[count];
4460 paint.glyphsToUnichars(glyphs, count, unichars);
4461 paint.setTextEncoding(SkPaint::kUTF32_TextEncoding);
4462 canvas->drawText(unichars, sizeof(unichars), 10, 30, paint);
4463 }
4464 ##
4465
4466##
4467
4468# ------------------------------------------------------------------------------
Cary Clark08895c42018-02-01 09:37:32 -05004469#Subtopic Measure_Text
4470#Line # width, height, bounds of text ##
Cary Clark8032b982017-07-28 11:04:54 -04004471
4472#Method SkScalar measureText(const void* text, size_t length, SkRect* bounds) const
4473
Cary Clarkab2621d2018-01-30 10:08:57 -05004474#In Measure_Text
4475#Line # returns advance width and bounds of text ##
Cary Clark8032b982017-07-28 11:04:54 -04004476 Returns the advance width of text if kVerticalText_Flag is clear,
4477 and the height of text if kVerticalText_Flag is set.
4478 The advance is the normal distance to move before drawing additional text.
4479 Uses Text_Encoding to decode text, Typeface to get the font metrics,
4480 and Text_Size, Text_Scale_X, Text_Skew_X, Stroke_Width, and
4481 Path_Effect to scale the metrics and bounds.
4482 Returns the bounding box of text if bounds is not nullptr.
4483 The bounding box is computed as if the text was drawn at the origin.
Herb Derbyfcac00f2018-05-01 11:57:56 -04004484
Cary Clark8032b982017-07-28 11:04:54 -04004485 #Param text character codes or glyph indices to be measured ##
4486 #Param length number of bytes of text to measure ##
4487 #Param bounds returns bounding box relative to (0, 0) if not nullptr ##
4488
4489 #Return advance width or height ##
4490
4491 #Example
4492 #Height 64
4493 void draw(SkCanvas* canvas) {
4494 SkPaint paint;
4495 paint.setAntiAlias(true);
4496 paint.setTextSize(50);
4497 const char str[] = "ay^jZ";
4498 const int count = sizeof(str) - 1;
4499 canvas->drawText(str, count, 25, 50, paint);
4500 SkRect bounds;
4501 paint.measureText(str, count, &bounds);
4502 canvas->translate(25, 50);
4503 paint.setStyle(SkPaint::kStroke_Style);
4504 canvas->drawRect(bounds, paint);
4505 }
4506 ##
4507
4508##
4509
4510#Method SkScalar measureText(const void* text, size_t length) const
4511
Cary Clarkab2621d2018-01-30 10:08:57 -05004512#In Measure_Text
Cary Clark8032b982017-07-28 11:04:54 -04004513 Returns the advance width of text if kVerticalText_Flag is clear,
4514 and the height of text if kVerticalText_Flag is set.
4515 The advance is the normal distance to move before drawing additional text.
4516 Uses Text_Encoding to decode text, Typeface to get the font metrics,
4517 and Text_Size to scale the metrics.
4518 Does not scale the advance or bounds by Fake_Bold or Path_Effect.
4519
4520 #Param text character codes or glyph indices to be measured ##
4521 #Param length number of bytes of text to measure ##
4522
4523 #Return advance width or height ##
4524
4525 #Example
4526 SkPaint paint;
4527 SkDebugf("default width = %g\n", paint.measureText("!", 1));
4528 paint.setTextSize(paint.getTextSize() * 2);
4529 SkDebugf("double width = %g\n", paint.measureText("!", 1));
4530
4531 #StdOut
4532 default width = 5
4533 double width = 10
4534 ##
4535 ##
4536
4537##
4538
4539#Method size_t breakText(const void* text, size_t length, SkScalar maxWidth,
Cary Clark73fa9722017-08-29 17:36:51 -04004540 SkScalar* measuredWidth = nullptr) const
Cary Clarkab2621d2018-01-30 10:08:57 -05004541#In Measure_Text
4542#Line # returns text that fits in a width ##
Cary Clark8032b982017-07-28 11:04:54 -04004543
4544 Returns the bytes of text that fit within maxWidth.
4545 If kVerticalText_Flag is clear, the text fragment fits if its advance width is less than or
4546 equal to maxWidth.
4547 If kVerticalText_Flag is set, the text fragment fits if its advance height is less than or
4548 equal to maxWidth.
4549 Measures only while the advance is less than or equal to maxWidth.
4550 Returns the advance or the text fragment in measuredWidth if it not nullptr.
4551 Uses Text_Encoding to decode text, Typeface to get the font metrics,
4552 and Text_Size to scale the metrics.
4553 Does not scale the advance or bounds by Fake_Bold or Path_Effect.
4554
4555 #Param text character codes or glyph indices to be measured ##
4556 #Param length number of bytes of text to measure ##
4557 #Param maxWidth advance limit; text is measured while advance is less than maxWidth ##
4558 #Param measuredWidth returns the width of the text less than or equal to maxWidth ##
4559 #Return bytes of text that fit, always less than or equal to length ##
Herb Derbyfcac00f2018-05-01 11:57:56 -04004560
Cary Clark8032b982017-07-28 11:04:54 -04004561 #Example
4562 #Description
4563 Line under "Breakfast" shows desired width, shorter than available characters.
4564 Line under "Bre" shows measured width after breaking text.
4565 ##
4566 #Height 128
4567 #Width 280
4568 void draw(SkCanvas* canvas) {
4569 SkPaint paint;
4570 paint.setAntiAlias(true);
4571 paint.setTextSize(50);
4572 const char str[] = "Breakfast";
4573 const int count = sizeof(str) - 1;
4574 canvas->drawText(str, count, 25, 50, paint);
4575 SkScalar measuredWidth;
4576 int partialBytes = paint.breakText(str, count, 100, &measuredWidth);
4577 canvas->drawText(str, partialBytes, 25, 100, paint);
4578 canvas->drawLine(25, 60, 25 + 100, 60, paint);
4579 canvas->drawLine(25, 110, 25 + measuredWidth, 110, paint);
4580 }
4581 ##
4582
4583##
4584
4585#Method int getTextWidths(const void* text, size_t byteLength, SkScalar widths[],
Cary Clark73fa9722017-08-29 17:36:51 -04004586 SkRect bounds[] = nullptr) const
Cary Clarkab2621d2018-01-30 10:08:57 -05004587#In Measure_Text
4588#Line # returns advance and bounds for each glyph in text ##
Cary Clark8032b982017-07-28 11:04:54 -04004589
4590 Retrieves the advance and bounds for each glyph in text, and returns
4591 the glyph count in text.
4592 Both widths and bounds may be nullptr.
4593 If widths is not nullptr, widths must be an array of glyph count entries.
Herb Derbyfcac00f2018-05-01 11:57:56 -04004594 if bounds is not nullptr, bounds must be an array of glyph count entries.
Cary Clark8032b982017-07-28 11:04:54 -04004595 If kVerticalText_Flag is clear, widths returns the horizontal advance.
4596 If kVerticalText_Flag is set, widths returns the vertical advance.
4597 Uses Text_Encoding to decode text, Typeface to get the font metrics,
4598 and Text_Size to scale the widths and bounds.
4599 Does not scale the advance by Fake_Bold or Path_Effect.
4600 Does include Fake_Bold and Path_Effect in the bounds.
Herb Derbyfcac00f2018-05-01 11:57:56 -04004601
Cary Clark8032b982017-07-28 11:04:54 -04004602 #Param text character codes or glyph indices to be measured ##
4603 #Param byteLength number of bytes of text to measure ##
4604 #Param widths returns text advances for each glyph; may be nullptr ##
4605 #Param bounds returns bounds for each glyph relative to (0, 0); may be nullptr ##
Herb Derbyfcac00f2018-05-01 11:57:56 -04004606
Cary Clark8032b982017-07-28 11:04:54 -04004607 #Return glyph count in text ##
4608
4609 #Example
4610 #Height 160
4611 #Description
Cary Clarkce101242017-09-01 15:51:02 -04004612 Bounds of Glyphs increase for stroked text, but text advance remains the same.
Cary Clark8032b982017-07-28 11:04:54 -04004613 The underlines show the text advance, spaced to keep them distinct.
4614 ##
4615 void draw(SkCanvas* canvas) {
4616 SkPaint paint;
4617 paint.setAntiAlias(true);
4618 paint.setTextSize(50);
4619 const char str[] = "abc";
4620 const int bytes = sizeof(str) - 1;
4621 int count = paint.getTextWidths(str, bytes, nullptr);
4622 std::vector<SkScalar> widths;
4623 std::vector<SkRect> bounds;
4624 widths.resize(count);
4625 bounds.resize(count);
4626 for (int loop = 0; loop < 2; ++loop) {
4627 (void) paint.getTextWidths(str, count, &widths.front(), &bounds.front());
4628 SkPoint loc = { 25, 50 };
4629 canvas->drawText(str, bytes, loc.fX, loc.fY, paint);
4630 paint.setStyle(SkPaint::kStroke_Style);
4631 paint.setStrokeWidth(0);
4632 SkScalar advanceY = loc.fY + 10;
4633 for (int index = 0; index < count; ++index) {
4634 bounds[index].offset(loc.fX, loc.fY);
4635 canvas->drawRect(bounds[index], paint);
4636 canvas->drawLine(loc.fX, advanceY, loc.fX + widths[index], advanceY, paint);
4637 loc.fX += widths[index];
4638 advanceY += 5;
4639 }
4640 canvas->translate(0, 80);
4641 paint.setStrokeWidth(3);
4642 }
4643 }
4644 ##
4645
4646##
4647
Cary Clark08895c42018-02-01 09:37:32 -05004648#Subtopic Measure_Text ##
Cary Clark8032b982017-07-28 11:04:54 -04004649# ------------------------------------------------------------------------------
Cary Clark08895c42018-02-01 09:37:32 -05004650#Subtopic Text_Path
4651#Line # geometry of Glyphs ##
Cary Clark8032b982017-07-28 11:04:54 -04004652
Cary Clarkce101242017-09-01 15:51:02 -04004653Text_Path describes the geometry of Glyphs used to draw text.
Cary Clark8032b982017-07-28 11:04:54 -04004654
4655#Method void getTextPath(const void* text, size_t length, SkScalar x, SkScalar y,
4656 SkPath* path) const
Cary Clarkab2621d2018-01-30 10:08:57 -05004657#In Text_Path
4658#Line # returns Path equivalent to text ##
Cary Clark8032b982017-07-28 11:04:54 -04004659
4660Returns the geometry as Path equivalent to the drawn text.
4661Uses Text_Encoding to decode text, Typeface to get the glyph paths,
4662and Text_Size, Fake_Bold, and Path_Effect to scale and modify the glyph paths.
4663All of the glyph paths are stored in path.
Cary Clark579985c2017-07-31 11:48:27 -04004664Uses x, y, and Text_Align to position path.
Cary Clark8032b982017-07-28 11:04:54 -04004665
4666 #Param text character codes or glyph indices ##
4667 #Param length number of bytes of text ##
4668 #Param x x-coordinate of the origin of the text ##
4669 #Param y y-coordinate of the origin of the text ##
Cary Clarkce101242017-09-01 15:51:02 -04004670 #Param path geometry of the Glyphs ##
Cary Clark8032b982017-07-28 11:04:54 -04004671
4672 #Example
4673 #Description
4674 Text is added to Path, offset, and subtracted from Path, then added at
4675 the offset location. The result is rendered with one draw call.
4676 ##
4677 #Height 128
4678 void draw(SkCanvas* canvas) {
4679 SkPaint paint;
4680 paint.setTextSize(80);
4681 SkPath path, path2;
4682 paint.getTextPath("ABC", 3, 20, 80, &path);
4683 path.offset(20, 20, &path2);
4684 Op(path, path2, SkPathOp::kDifference_SkPathOp, &path);
4685 path.addPath(path2);
4686 paint.setStyle(SkPaint::kStroke_Style);
4687 canvas->drawPath(path, paint);
4688 }
4689 ##
4690
4691##
4692
4693#Method void getPosTextPath(const void* text, size_t length,
4694 const SkPoint pos[], SkPath* path) const
Cary Clarkab2621d2018-01-30 10:08:57 -05004695#In Text_Path
4696#Line # returns Path equivalent to positioned text ##
Cary Clark8032b982017-07-28 11:04:54 -04004697
4698Returns the geometry as Path equivalent to the drawn text.
4699Uses Text_Encoding to decode text, Typeface to get the glyph paths,
4700and Text_Size, Fake_Bold, and Path_Effect to scale and modify the glyph paths.
4701All of the glyph paths are stored in path.
4702Uses pos array and Text_Align to position path.
4703pos contains a position for each glyph.
4704
4705 #Param text character codes or glyph indices ##
4706 #Param length number of bytes of text ##
4707 #Param pos positions of each glyph ##
Cary Clarkce101242017-09-01 15:51:02 -04004708 #Param path geometry of the Glyphs ##
Cary Clark8032b982017-07-28 11:04:54 -04004709
4710 #Example
4711 #Height 85
4712 #Description
Cary Clarkce101242017-09-01 15:51:02 -04004713 Simplifies three Glyphs to eliminate overlaps, and strokes the result.
Cary Clark8032b982017-07-28 11:04:54 -04004714 ##
4715 void draw(SkCanvas* canvas) {
4716 SkPaint paint;
4717 paint.setTextSize(80);
4718 SkPath path, path2;
4719 SkPoint pos[] = {{20, 60}, {30, 70}, {40, 80}};
4720 paint.getPosTextPath("ABC", 3, pos, &path);
4721 Simplify(path, &path);
4722 paint.setStyle(SkPaint::kStroke_Style);
4723 canvas->drawPath(path, paint);
4724 }
4725 ##
4726
4727##
4728
Cary Clark08895c42018-02-01 09:37:32 -05004729#Subtopic Text_Path ##
Cary Clark8032b982017-07-28 11:04:54 -04004730# ------------------------------------------------------------------------------
Cary Clark08895c42018-02-01 09:37:32 -05004731#Subtopic Text_Intercepts
4732#Line # advanced underline, strike through ##
Cary Clark8032b982017-07-28 11:04:54 -04004733
Cary Clarkce101242017-09-01 15:51:02 -04004734Text_Intercepts describe the intersection of drawn text Glyphs with a pair
Cary Clark8032b982017-07-28 11:04:54 -04004735of lines parallel to the text advance. Text_Intercepts permits creating a
Cary Clarkce101242017-09-01 15:51:02 -04004736underline that skips Descenders.
Cary Clark8032b982017-07-28 11:04:54 -04004737
4738#Method int getTextIntercepts(const void* text, size_t length, SkScalar x, SkScalar y,
4739 const SkScalar bounds[2], SkScalar* intervals) const
Cary Clarkab2621d2018-01-30 10:08:57 -05004740#In Text_Intercepts
4741#Line # returns where lines intersect text; underlines ##
Cary Clark8032b982017-07-28 11:04:54 -04004742
4743 Returns the number of intervals that intersect bounds.
4744 bounds describes a pair of lines parallel to the text advance.
Cary Clarkce101242017-09-01 15:51:02 -04004745 The return count is zero or a multiple of two, and is at most twice the number of Glyphs in
Herb Derbyfcac00f2018-05-01 11:57:56 -04004746 the string.
Cary Clark8032b982017-07-28 11:04:54 -04004747 Uses Text_Encoding to decode text, Typeface to get the glyph paths,
4748 and Text_Size, Fake_Bold, and Path_Effect to scale and modify the glyph paths.
4749 Uses x, y, and Text_Align to position intervals.
Herb Derbyfcac00f2018-05-01 11:57:56 -04004750
Cary Clark8032b982017-07-28 11:04:54 -04004751 Pass nullptr for intervals to determine the size of the interval array.
Herb Derbyfcac00f2018-05-01 11:57:56 -04004752
Cary Clark8032b982017-07-28 11:04:54 -04004753 intervals are cached to improve performance for multiple calls.
4754
4755 #Param text character codes or glyph indices ##
4756 #Param length number of bytes of text ##
4757 #Param x x-coordinate of the origin of the text ##
4758 #Param y y-coordinate of the origin of the text ##
4759 #Param bounds lower and upper line parallel to the advance ##
4760 #Param intervals returned intersections; may be nullptr ##
4761
4762 #Return number of intersections; may be zero ##
4763
4764#Example
4765#Height 128
4766#Description
Cary Clarkce101242017-09-01 15:51:02 -04004767Underline uses intercepts to draw on either side of the glyph Descender.
Cary Clark8032b982017-07-28 11:04:54 -04004768##
4769void draw(SkCanvas* canvas) {
4770 SkPaint paint;
4771 paint.setTextSize(120);
4772 SkPoint textOrigin = { 20, 100 };
4773 SkScalar bounds[] = { 100, 108 };
4774 int count = paint.getTextIntercepts("y", 1, textOrigin.fX, textOrigin.fY, bounds, nullptr);
4775 std::vector<SkScalar> intervals;
4776 intervals.resize(count);
4777 (void) paint.getTextIntercepts("y", 1, textOrigin.fX, textOrigin.fY, bounds,
4778 &intervals.front());
4779 canvas->drawString("y", textOrigin.fX, textOrigin.fY, paint);
4780 paint.setColor(SK_ColorRED);
4781 SkScalar x = textOrigin.fX;
4782 for (int i = 0; i < count; i += 2) {
4783 canvas->drawRect({x, bounds[0], intervals[i], bounds[1]}, paint);
4784 x = intervals[i + 1];
4785 }
4786 canvas->drawRect({intervals[count - 1], bounds[0],
4787 textOrigin.fX + paint.measureText("y", 1), bounds[1]}, paint);
4788}
4789##
4790
4791##
4792
4793#Method int getPosTextIntercepts(const void* text, size_t length, const SkPoint pos[],
4794 const SkScalar bounds[2], SkScalar* intervals) const
Cary Clarkab2621d2018-01-30 10:08:57 -05004795#In Text_Intercepts
4796#Line # returns where lines intersect positioned text; underlines ##
Cary Clark8032b982017-07-28 11:04:54 -04004797
4798 Returns the number of intervals that intersect bounds.
4799 bounds describes a pair of lines parallel to the text advance.
Cary Clarkce101242017-09-01 15:51:02 -04004800 The return count is zero or a multiple of two, and is at most twice the number of Glyphs in
Herb Derbyfcac00f2018-05-01 11:57:56 -04004801 the string.
Cary Clark8032b982017-07-28 11:04:54 -04004802 Uses Text_Encoding to decode text, Typeface to get the glyph paths,
4803 and Text_Size, Fake_Bold, and Path_Effect to scale and modify the glyph paths.
4804 Uses pos array and Text_Align to position intervals.
Herb Derbyfcac00f2018-05-01 11:57:56 -04004805
Cary Clark8032b982017-07-28 11:04:54 -04004806 Pass nullptr for intervals to determine the size of the interval array.
Herb Derbyfcac00f2018-05-01 11:57:56 -04004807
Cary Clark8032b982017-07-28 11:04:54 -04004808 intervals are cached to improve performance for multiple calls.
4809
4810 #Param text character codes or glyph indices ##
4811 #Param length number of bytes of text ##
4812 #Param pos positions of each glyph ##
4813 #Param bounds lower and upper line parallel to the advance ##
4814 #Param intervals returned intersections; may be nullptr ##
4815
Cary Clarka523d2d2017-08-30 08:58:10 -04004816 #Return number of intersections; may be zero ##
Cary Clark8032b982017-07-28 11:04:54 -04004817
4818 #Example
4819 #Description
Cary Clarkce101242017-09-01 15:51:02 -04004820 Text intercepts draw on either side of, but not inside, Glyphs in a run.
Cary Clark8032b982017-07-28 11:04:54 -04004821 ##
4822 void draw(SkCanvas* canvas) {
4823 SkPaint paint;
4824 paint.setTextSize(120);
4825 paint.setVerticalText(true);
4826 SkPoint textPos[] = {{ 60, 40 }, { 60, 140 }};
4827 SkScalar bounds[] = { 56, 64 };
4828 const char str[] = "A-";
4829 int len = sizeof(str) - 1;
4830 int count = paint.getPosTextIntercepts(str, len, textPos, bounds, nullptr);
4831 std::vector<SkScalar> intervals;
4832 intervals.resize(count);
4833 (void) paint.getPosTextIntercepts(str, len, textPos, bounds, &intervals.front());
4834 canvas->drawPosText(str, len, textPos, paint);
4835 paint.setColor(SK_ColorRED);
4836 SkScalar y = textPos[0].fY;
4837 for (int i = 0; i < count; i+= 2) {
4838 canvas->drawRect({bounds[0], y, bounds[1], intervals[i]}, paint);
4839 y = intervals[i + 1];
4840 }
4841 canvas->drawRect({bounds[0], intervals[count - 1], bounds[1], 240}, paint);
4842 }
4843 ##
4844
4845##
4846
4847#Method int getPosTextHIntercepts(const void* text, size_t length, const SkScalar xpos[],
4848 SkScalar constY, const SkScalar bounds[2],
4849 SkScalar* intervals) const
Cary Clarkab2621d2018-01-30 10:08:57 -05004850#In Text_Intercepts
4851#Line # returns where lines intersect horizontally positioned text; underlines ##
Cary Clark8032b982017-07-28 11:04:54 -04004852
4853 Returns the number of intervals that intersect bounds.
4854 bounds describes a pair of lines parallel to the text advance.
Cary Clarkce101242017-09-01 15:51:02 -04004855 The return count is zero or a multiple of two, and is at most twice the number of Glyphs in
Herb Derbyfcac00f2018-05-01 11:57:56 -04004856 the string.
Cary Clark8032b982017-07-28 11:04:54 -04004857 Uses Text_Encoding to decode text, Typeface to get the glyph paths,
4858 and Text_Size, Fake_Bold, and Path_Effect to scale and modify the glyph paths.
4859 Uses xpos array, constY, and Text_Align to position intervals.
Herb Derbyfcac00f2018-05-01 11:57:56 -04004860
Cary Clark8032b982017-07-28 11:04:54 -04004861 Pass nullptr for intervals to determine the size of the interval array.
Herb Derbyfcac00f2018-05-01 11:57:56 -04004862
Cary Clark8032b982017-07-28 11:04:54 -04004863 intervals are cached to improve performance for multiple calls.
4864
4865 #Param text character codes or glyph indices ##
4866 #Param length number of bytes of text ##
4867 #Param xpos positions of each glyph in x ##
4868 #Param constY position of each glyph in y ##
4869 #Param bounds lower and upper line parallel to the advance ##
4870 #Param intervals returned intersections; may be nullptr ##
4871
4872 #Return number of intersections; may be zero ##
4873
4874 #Example
4875 #Height 128
4876 #Description
4877 Text intercepts do not take stroke thickness into consideration.
4878 ##
4879 void draw(SkCanvas* canvas) {
4880 SkPaint paint;
4881 paint.setTextSize(120);
4882 paint.setStyle(SkPaint::kStroke_Style);
4883 paint.setStrokeWidth(4);
4884 SkScalar textPosH[] = { 20, 80, 140 };
4885 SkScalar y = 100;
4886 SkScalar bounds[] = { 56, 78 };
4887 const char str[] = "\\-/";
4888 int len = sizeof(str) - 1;
4889 int count = paint.getPosTextHIntercepts(str, len, textPosH, y, bounds, nullptr);
4890 std::vector<SkScalar> intervals;
4891 intervals.resize(count);
4892 (void) paint.getPosTextHIntercepts(str, len, textPosH, y, bounds, &intervals.front());
4893 canvas->drawPosTextH(str, len, textPosH, y, paint);
4894 paint.setColor(0xFFFF7777);
4895 paint.setStyle(SkPaint::kFill_Style);
4896 SkScalar x = textPosH[0];
4897 for (int i = 0; i < count; i+= 2) {
4898 canvas->drawRect({x, bounds[0], intervals[i], bounds[1]}, paint);
4899 x = intervals[i + 1];
4900 }
4901 canvas->drawRect({intervals[count - 1], bounds[0], 180, bounds[1]}, paint);
4902 }
4903 ##
4904
4905##
4906
4907
4908#Method int getTextBlobIntercepts(const SkTextBlob* blob, const SkScalar bounds[2],
4909 SkScalar* intervals) const
Cary Clarkab2621d2018-01-30 10:08:57 -05004910#In Text_Intercepts
4911#Line # returns where lines intersect Text_Blob; underlines ##
Cary Clark8032b982017-07-28 11:04:54 -04004912
4913 Returns the number of intervals that intersect bounds.
4914 bounds describes a pair of lines parallel to the text advance.
Cary Clarkce101242017-09-01 15:51:02 -04004915 The return count is zero or a multiple of two, and is at most twice the number of Glyphs in
Herb Derbyfcac00f2018-05-01 11:57:56 -04004916 the string.
Cary Clark3cd22cc2017-12-01 11:49:58 -05004917 Uses Typeface to get the glyph paths,
Cary Clark8032b982017-07-28 11:04:54 -04004918 and Text_Size, Fake_Bold, and Path_Effect to scale and modify the glyph paths.
Cary Clarkce101242017-09-01 15:51:02 -04004919 Uses run array and Text_Align to position intervals.
Herb Derbyfcac00f2018-05-01 11:57:56 -04004920
Cary Clark3cd22cc2017-12-01 11:49:58 -05004921 Text_Encoding must be set to SkPaint::kGlyphID_TextEncoding.
4922
Cary Clark8032b982017-07-28 11:04:54 -04004923 Pass nullptr for intervals to determine the size of the interval array.
Herb Derbyfcac00f2018-05-01 11:57:56 -04004924
Cary Clark8032b982017-07-28 11:04:54 -04004925 intervals are cached to improve performance for multiple calls.
4926
Cary Clarkce101242017-09-01 15:51:02 -04004927 #Param blob Glyphs, positions, and text paint attributes ##
Cary Clark8032b982017-07-28 11:04:54 -04004928 #Param bounds lower and upper line parallel to the advance ##
4929 #Param intervals returned intersections; may be nullptr ##
4930
4931 #Return number of intersections; may be zero ##
4932
4933 #Example
4934 #Height 143
4935 void draw(SkCanvas* canvas) {
4936 SkPaint paint;
Cary Clark3cd22cc2017-12-01 11:49:58 -05004937 paint.setTextEncoding(SkPaint::kGlyphID_TextEncoding);
Cary Clark8032b982017-07-28 11:04:54 -04004938 paint.setTextSize(120);
4939 SkPoint textPos = { 20, 110 };
4940 int len = 3;
4941 SkTextBlobBuilder textBlobBuilder;
Herb Derbyfcac00f2018-05-01 11:57:56 -04004942 const SkTextBlobBuilder::RunBuffer& run =
Cary Clark8032b982017-07-28 11:04:54 -04004943 textBlobBuilder.allocRun(paint, len, textPos.fX, textPos.fY);
4944 run.glyphs[0] = 10;
4945 run.glyphs[1] = 20;
Herb Derbyfcac00f2018-05-01 11:57:56 -04004946 run.glyphs[2] = 30;
Cary Clark8032b982017-07-28 11:04:54 -04004947 sk_sp<const SkTextBlob> blob = textBlobBuilder.make();
4948 canvas->drawTextBlob(blob.get(), textPos.fX, textPos.fY, paint);
4949 SkScalar bounds[] = { 116, 134 };
4950 int count = paint.getTextBlobIntercepts(blob.get(), bounds, nullptr);
4951 std::vector<SkScalar> intervals;
4952 intervals.resize(count);
4953 (void) paint.getTextBlobIntercepts(blob.get(), bounds, &intervals.front());
4954 canvas->drawTextBlob(blob.get(), 0, 0, paint);
4955 paint.setColor(0xFFFF7777);
4956 SkScalar x = textPos.fX;
4957 for (int i = 0; i < count; i+= 2) {
4958 canvas->drawRect({x, bounds[0], intervals[i], bounds[1]}, paint);
4959 x = intervals[i + 1];
4960 }
4961 canvas->drawRect({intervals[count - 1], bounds[0], 180, bounds[1]}, paint);
4962 }
4963 ##
4964
4965##
4966
Cary Clark08895c42018-02-01 09:37:32 -05004967#Subtopic Text_Intercepts ##
Cary Clark8032b982017-07-28 11:04:54 -04004968# ------------------------------------------------------------------------------
4969
4970#Method bool nothingToDraw() const
Cary Clark78de7512018-02-07 07:27:09 -05004971#In Utility
Cary Clarkab2621d2018-01-30 10:08:57 -05004972#Line # returns true if Paint prevents all drawing ##
Cary Clark579985c2017-07-31 11:48:27 -04004973 Returns true if Paint prevents all drawing;
4974 otherwise, the Paint may or may not allow drawing.
Cary Clark8032b982017-07-28 11:04:54 -04004975
Cary Clarkce101242017-09-01 15:51:02 -04004976 Returns true if, for example, Blend_Mode combined with Color_Alpha computes a
4977 new Alpha of zero.
Cary Clark8032b982017-07-28 11:04:54 -04004978
4979 #Return true if Paint prevents all drawing ##
4980
4981 #Example
4982 void draw(SkCanvas* canvas) {
4983 auto debugster = [](const char* prefix, const SkPaint& p) -> void {
Herb Derbyfcac00f2018-05-01 11:57:56 -04004984 SkDebugf("%s nothing to draw: %s\n", prefix,
Cary Clark8032b982017-07-28 11:04:54 -04004985 p.nothingToDraw() ? "true" : "false");
4986 };
4987 SkPaint paint;
4988 debugster("initial", paint);
4989 paint.setBlendMode(SkBlendMode::kDst);
4990 debugster("blend dst", paint);
4991 paint.setBlendMode(SkBlendMode::kSrcOver);
4992 debugster("blend src over", paint);
4993 paint.setAlpha(0);
4994 debugster("alpha 0", paint);
4995 }
4996
4997 #StdOut
4998 initial nothing to draw: false
4999 blend dst nothing to draw: true
5000 blend src over nothing to draw: false
5001 alpha 0 nothing to draw: true
5002 #StdOut ##
5003 ##
5004
5005##
5006
5007# ------------------------------------------------------------------------------
Cary Clark08895c42018-02-01 09:37:32 -05005008#Subtopic Fast_Bounds
5009#Line # approximate area required by Paint ##
Herb Derbyfcac00f2018-05-01 11:57:56 -04005010 #Private
5011 To be made private.
Cary Clark8032b982017-07-28 11:04:54 -04005012 ##
5013
Cary Clark682c58d2018-05-16 07:07:07 -04005014Fast_Bounds functions conservatively outset a drawing bounds by additional area
Cary Clark8032b982017-07-28 11:04:54 -04005015Paint may draw to.
5016
5017#Method bool canComputeFastBounds() const
Herb Derbyfcac00f2018-05-01 11:57:56 -04005018
Cary Clarkab2621d2018-01-30 10:08:57 -05005019#In Fast_Bounds
Cary Clark1a8d7622018-03-05 13:26:16 -05005020#Line # returns true if settings allow for fast bounds computation ##
Herb Derbyfcac00f2018-05-01 11:57:56 -04005021 #Private
Cary Clark8032b982017-07-28 11:04:54 -04005022 (to be made private)
5023 ##
5024
5025 Returns true if Paint does not include elements requiring extensive computation
5026 to compute Device bounds of drawn geometry. For instance, Paint with Path_Effect
5027 always returns false.
5028
5029 #Return true if Paint allows for fast computation of bounds ##
5030##
5031
5032#Method const SkRect& computeFastBounds(const SkRect& orig, SkRect* storage) const
Herb Derbyfcac00f2018-05-01 11:57:56 -04005033
Cary Clarkab2621d2018-01-30 10:08:57 -05005034#In Fast_Bounds
Cary Clark1a8d7622018-03-05 13:26:16 -05005035#Line # returns fill bounds for quick reject tests ##
Herb Derbyfcac00f2018-05-01 11:57:56 -04005036 #Private
Cary Clark8032b982017-07-28 11:04:54 -04005037 (to be made private)
5038 ##
5039
5040 Only call this if canComputeFastBounds returned true. This takes a
5041 raw rectangle (the raw bounds of a shape), and adjusts it for stylistic
5042 effects in the paint (e.g. stroking). If needed, it uses the storage
Cary Clarkce101242017-09-01 15:51:02 -04005043 parameter. It returns the adjusted bounds that can then be used
Cary Clark8032b982017-07-28 11:04:54 -04005044 for SkCanvas::quickReject tests.
5045
Cary Clarkce101242017-09-01 15:51:02 -04005046 The returned Rect will either be orig or storage, thus the caller
Cary Clark8032b982017-07-28 11:04:54 -04005047 should not rely on storage being set to the result, but should always
Cary Clarkce101242017-09-01 15:51:02 -04005048 use the returned value. It is legal for orig and storage to be the same
5049 Rect.
Cary Clark8032b982017-07-28 11:04:54 -04005050
Herb Derbyfcac00f2018-05-01 11:57:56 -04005051 #Private
Cary Clark682c58d2018-05-16 07:07:07 -04005052 For example:
5053 if (!path.isInverseFillType() && paint.canComputeFastBounds()) {
5054 SkRect storage;
5055 if (canvas->quickReject(paint.computeFastBounds(path.getBounds(), &storage))) {
5056 return; // don't draw the path
5057 }
Cary Clark8032b982017-07-28 11:04:54 -04005058 }
Cary Clark682c58d2018-05-16 07:07:07 -04005059 // draw the path
Cary Clark8032b982017-07-28 11:04:54 -04005060 ##
5061
5062 #Param orig geometry modified by Paint when drawn ##
5063 #Param storage computed bounds of geometry; may not be nullptr ##
5064
5065 #Return fast computed bounds ##
5066##
5067
5068#Method const SkRect& computeFastStrokeBounds(const SkRect& orig,
5069 SkRect* storage) const
Cary Clarkab2621d2018-01-30 10:08:57 -05005070#In Fast_Bounds
5071#Line # returns stroke bounds for quick reject tests ##
Herb Derbyfcac00f2018-05-01 11:57:56 -04005072 #Private
Cary Clark8032b982017-07-28 11:04:54 -04005073 (to be made private)
5074 ##
5075
5076 #Param orig geometry modified by Paint when drawn ##
5077 #Param storage computed bounds of geometry ##
5078
5079 #Return fast computed bounds ##
5080##
5081
5082#Method const SkRect& doComputeFastBounds(const SkRect& orig, SkRect* storage,
5083 Style style) const
Cary Clarkab2621d2018-01-30 10:08:57 -05005084#In Fast_Bounds
5085#Line # returns bounds for quick reject tests ##
Herb Derbyfcac00f2018-05-01 11:57:56 -04005086 #Private
Cary Clark8032b982017-07-28 11:04:54 -04005087 (to be made private)
5088 ##
5089
Cary Clarkce101242017-09-01 15:51:02 -04005090 Computes the bounds, overriding the Paint Style. This can be used to
5091 account for additional width required by stroking orig, without
5092 altering Style set to fill.
Cary Clark8032b982017-07-28 11:04:54 -04005093
5094 #Param orig geometry modified by Paint when drawn ##
5095 #Param storage computed bounds of geometry ##
5096 #Param style overrides Style ##
5097
5098 #Return fast computed bounds ##
5099##
5100
Cary Clark1a8d7622018-03-05 13:26:16 -05005101#Subtopic Fast_Bounds ##
Cary Clark8032b982017-07-28 11:04:54 -04005102
5103# ------------------------------------------------------------------------------
Cary Clark78de7512018-02-07 07:27:09 -05005104#Subtopic Utility
5105#Populate
5106#Line # rarely called management functions ##
5107##
Cary Clark8032b982017-07-28 11:04:54 -04005108
Cary Clark78de7512018-02-07 07:27:09 -05005109#Method void toString(SkString* str) const
5110#In Utility
Cary Clarkab2621d2018-01-30 10:08:57 -05005111#Line # converts Paint to machine readable form ##
Cary Clark8032b982017-07-28 11:04:54 -04005112
Cary Clarkce101242017-09-01 15:51:02 -04005113Creates string representation of Paint. The representation is read by
Cary Clark99885412018-04-05 13:09:58 -04005114internal debugging tools.
Cary Clark8032b982017-07-28 11:04:54 -04005115
Cary Clarkce101242017-09-01 15:51:02 -04005116#Param str storage for string representation of Paint ##
Cary Clark8032b982017-07-28 11:04:54 -04005117
5118#Example
5119 SkPaint paint;
5120 SkString str;
5121 paint.toString(&str);
5122 const char textSize[] = "TextSize:";
5123 const int trailerSize = strlen("</dd><dt>");
5124 int textSizeLoc = str.find(textSize) + strlen(textSize) + trailerSize;
5125 const char* sizeStart = &str.c_str()[textSizeLoc];
5126 int textSizeEnd = SkStrFind(sizeStart, "</dd>");
5127 SkDebugf("text size = %.*s\n", textSizeEnd, sizeStart);
5128
5129 #StdOut
5130 text size = 12
5131 ##
5132
5133##
5134
Cary Clark2ade9972017-11-02 17:49:34 -04005135#SeeAlso SkPathEffect::toString SkMaskFilter::toString SkColorFilter::toString SkImageFilter::toString
Cary Clark8032b982017-07-28 11:04:54 -04005136
5137##
5138
5139# ------------------------------------------------------------------------------
5140
5141#Class SkPaint ##
5142
5143#Topic Paint ##
Cary Clark4855f782018-02-06 09:41:53 -05005144