blob: 2b844fc9ebac765957f18d5939c8701d08339a1f [file] [log] [blame]
Cary Clark0c5f5462017-12-15 11:21:51 -05001#Topic Paint
Cary Clark137b8742018-05-30 09:21:49 -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 Clark137b8742018-05-30 09:21:49 -0400443#Line # modifies glyph outlines for maximum constrast ##
444 Modifies glyph outlines for maximum 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
Cary Clark137b8742018-05-30 09:21:49 -0400453to account for LCD text. No hinting uses Core_Text Grayscale output.
Cary Clark8032b982017-07-28 11:04:54 -0400454Normal hinting uses Core_Text LCD output. If kLCDRenderText_Flag is clear,
Cary Clark137b8742018-05-30 09:21:49 -0400455the 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
Cary Clark137b8742018-05-30 09:21:49 -0400653#Substitute anti-alias
654##
Cary Clarkffb3d682018-05-17 12:17:28 -0400655#Alias Anti_Aliased
Cary Clark137b8742018-05-30 09:21:49 -0400656#Substitute anti-aliased
657##
Cary Clarkffb3d682018-05-17 12:17:28 -0400658#Alias Anti_Aliasing
Cary Clark137b8742018-05-30 09:21:49 -0400659#Substitute anti-aliasing
660##
Cary Clark4855f782018-02-06 09:41:53 -0500661#In Related_Function
Cary Clarkab2621d2018-01-30 10:08:57 -0500662#Line # approximating coverage with transparency ##
Cary Clark8032b982017-07-28 11:04:54 -0400663
Cary Clarkffb3d682018-05-17 12:17:28 -0400664Anti_Alias drawing approximates partial pixel coverage with transparency.
Cary Clark8032b982017-07-28 11:04:54 -0400665If kAntiAlias_Flag is clear, pixel centers contained by the shape edge are drawn opaque.
666If kAntiAlias_Flag is set, pixels are drawn with Color_Alpha equal to their coverage.
667
Herb Derbyfcac00f2018-05-01 11:57:56 -0400668The rule for Aliased pixels is inconsistent across platforms. A shape edge
Cary Clark8032b982017-07-28 11:04:54 -0400669passing through the pixel center may, but is not required to, draw the pixel.
670
Cary Clarkce101242017-09-01 15:51:02 -0400671Raster_Engine draws Aliased pixels whose centers are on or to the right of the start of an
Cary Clark8032b982017-07-28 11:04:54 -0400672active Path edge, and whose center is to the left of the end of the active Path edge.
673
674#ToDo add illustration of raster pixels ##
675
Cary Clarkffb3d682018-05-17 12:17:28 -0400676A platform may only support Anti_Aliased drawing. Some GPU-backed platforms use
677Supersampling to Anti_Alias all drawing, and have no mechanism to selectively
Cary Clarkce101242017-09-01 15:51:02 -0400678Alias.
Cary Clark8032b982017-07-28 11:04:54 -0400679
Cary Clarkffb3d682018-05-17 12:17:28 -0400680The amount of coverage computed for Anti_Aliased pixels also varies across platforms.
Cary Clark8032b982017-07-28 11:04:54 -0400681
Cary Clarkffb3d682018-05-17 12:17:28 -0400682Anti_Alias is disabled by default.
683Anti_Alias can be enabled by default by setting SkPaintDefaults_Flags to kAntiAlias_Flag
Cary Clark8032b982017-07-28 11:04:54 -0400684at compile time.
685
Cary Clarkab2621d2018-01-30 10:08:57 -0500686#Example
Cary Clark8032b982017-07-28 11:04:54 -0400687 #Width 512
688 #Description
689 A red line is drawn with transparency on the edges to make it look smoother.
690 A blue line draws only where the pixel centers are contained.
Cary Clarkce101242017-09-01 15:51:02 -0400691 The lines are drawn into Bitmap, then drawn magnified to make the
692 Aliasing easier to see.
Cary Clark8032b982017-07-28 11:04:54 -0400693 ##
694
695 void draw(SkCanvas* canvas) {
696 SkBitmap bitmap;
697 bitmap.allocN32Pixels(50, 50);
698 SkCanvas offscreen(bitmap);
699 SkPaint paint;
700 paint.setStyle(SkPaint::kStroke_Style);
701 paint.setStrokeWidth(10);
702 for (bool antialias : { false, true }) {
703 paint.setColor(antialias ? SK_ColorRED : SK_ColorBLUE);
704 paint.setAntiAlias(antialias);
705 bitmap.eraseColor(0);
706 offscreen.drawLine(5, 5, 15, 30, paint);
707 canvas->drawLine(5, 5, 15, 30, paint);
708 canvas->save();
709 canvas->scale(10, 10);
710 canvas->drawBitmap(bitmap, antialias ? 12 : 0, 0);
711 canvas->restore();
712 canvas->translate(15, 0);
713 }
714 }
Cary Clarkab2621d2018-01-30 10:08:57 -0500715##
Cary Clark8032b982017-07-28 11:04:54 -0400716
717#Method bool isAntiAlias() const
Cary Clark78de7512018-02-07 07:27:09 -0500718#In Anti_alias
Cary Clarkffb3d682018-05-17 12:17:28 -0400719#Line # returns true if Anti_Alias is set ##
Cary Clark8032b982017-07-28 11:04:54 -0400720
721 If true, pixels on the active edges of Path may be drawn with partial transparency.
722
723 Equivalent to getFlags masked with kAntiAlias_Flag.
724
725 #Return kAntiAlias_Flag state ##
726
727 #Example
728 SkPaint paint;
729 SkDebugf("paint.isAntiAlias() %c= !!(paint.getFlags() & SkPaint::kAntiAlias_Flag)\n",
730 paint.isAntiAlias() == !!(paint.getFlags() & SkPaint::kAntiAlias_Flag) ? '=' : '!');
731 paint.setAntiAlias(true);
732 SkDebugf("paint.isAntiAlias() %c= !!(paint.getFlags() & SkPaint::kAntiAlias_Flag)\n",
733 paint.isAntiAlias() == !!(paint.getFlags() & SkPaint::kAntiAlias_Flag) ? '=' : '!');
734
735 #StdOut
736 paint.isAntiAlias() == !!(paint.getFlags() & SkPaint::kAntiAlias_Flag)
737 paint.isAntiAlias() == !!(paint.getFlags() & SkPaint::kAntiAlias_Flag)
738 ##
739 ##
740##
741
742#Method void setAntiAlias(bool aa)
743
Cary Clark78de7512018-02-07 07:27:09 -0500744#In Anti_alias
Cary Clarkffb3d682018-05-17 12:17:28 -0400745#Line # sets or clears Anti_Alias ##
Cary Clark8032b982017-07-28 11:04:54 -0400746 Requests, but does not require, that Path edge pixels draw opaque or with
747 partial transparency.
748
749 Sets kAntiAlias_Flag if aa is true.
750 Clears kAntiAlias_Flag if aa is false.
751
752 #Param aa setting for kAntiAlias_Flag ##
753
754 #Example
755 SkPaint paint1, paint2;
756 paint1.setAntiAlias(true);
757 paint2.setFlags(paint2.getFlags() | SkPaint::kAntiAlias_Flag);
758 SkDebugf("paint1 %c= paint2\n", paint1 == paint2 ? '=' : '!');
759
760 #StdOut
761 paint1 == paint2
762 ##
763 ##
764
765##
766
Cary Clarkffb3d682018-05-17 12:17:28 -0400767#Subtopic Anti_Alias ##
Cary Clark8032b982017-07-28 11:04:54 -0400768# ------------------------------------------------------------------------------
Cary Clark08895c42018-02-01 09:37:32 -0500769#Subtopic Dither
770#Line # distributing color error ##
Cary Clark8032b982017-07-28 11:04:54 -0400771
Herb Derbyfcac00f2018-05-01 11:57:56 -0400772Dither increases fidelity by adjusting the color of adjacent pixels.
Cary Clark8032b982017-07-28 11:04:54 -0400773This can help to smooth color transitions and reducing banding in gradients.
774Dithering lessens visible banding from kRGB_565_SkColorType
Herb Derbyfcac00f2018-05-01 11:57:56 -0400775and kRGBA_8888_SkColorType gradients,
Cary Clark8032b982017-07-28 11:04:54 -0400776and improves rendering into a kRGB_565_SkColorType Surface.
777
778Dithering is always enabled for linear gradients drawing into
779kRGB_565_SkColorType Surface and kRGBA_8888_SkColorType Surface.
780Dither cannot be enabled for kAlpha_8_SkColorType Surface and
781kRGBA_F16_SkColorType Surface.
782
783Dither is disabled by default.
784Dither can be enabled by default by setting SkPaintDefaults_Flags to kDither_Flag
785at compile time.
786
787Some platform implementations may ignore dithering. Set
788
Cary Clark2d4bf5f2018-04-16 08:37:38 -0400789#Formula
790SK_IGNORE_GPU_DITHER
791##
Cary Clark8032b982017-07-28 11:04:54 -0400792
793to ignore Dither on GPU_Surface.
794
795#Example
Herb Derbyfcac00f2018-05-01 11:57:56 -0400796#Description
Cary Clark8032b982017-07-28 11:04:54 -0400797Dithering in the bottom half more closely approximates the requested color by
798alternating nearby colors from pixel to pixel.
799##
800void draw(SkCanvas* canvas) {
801 SkBitmap bm16;
802 bm16.allocPixels(SkImageInfo::Make(32, 32, kRGB_565_SkColorType, kOpaque_SkAlphaType));
803 SkCanvas c16(bm16);
804 SkPaint colorPaint;
805 for (auto dither : { false, true } ) {
806 colorPaint.setDither(dither);
807 for (auto colors : { 0xFF333333, 0xFF666666, 0xFF999999, 0xFFCCCCCC } ) {
808 for (auto mask : { 0xFFFF0000, 0xFF00FF00, 0xFF0000FF, 0xFFFFFFFF } ) {
809 colorPaint.setColor(colors & mask);
810 c16.drawRect({0, 0, 8, 4}, colorPaint);
811 c16.translate(8, 0);
812 }
813 c16.translate(-32, 4);
814 }
815 }
816 canvas->scale(8, 8);
817 canvas->drawBitmap(bm16, 0, 0);
818}
819##
820
821#Example
Herb Derbyfcac00f2018-05-01 11:57:56 -0400822#Description
Cary Clark8032b982017-07-28 11:04:54 -0400823Dithering introduces subtle adjustments to color to smooth gradients.
824Drawing the gradient repeatedly with SkBlendMode::kPlus exaggerates the
825dither, making it easier to see.
826##
827void draw(SkCanvas* canvas) {
828 canvas->clear(0);
829 SkBitmap bm32;
830 bm32.allocPixels(SkImageInfo::Make(20, 10, kN32_SkColorType, kPremul_SkAlphaType));
831 SkCanvas c32(bm32);
832 SkPoint points[] = {{0, 0}, {20, 0}};
833 SkColor colors[] = {0xFF334455, 0xFF662211 };
834 SkPaint paint;
835 paint.setShader(SkGradientShader::MakeLinear(
836 points, colors, nullptr, SK_ARRAY_COUNT(colors),
837 SkShader::kClamp_TileMode, 0, nullptr));
838 paint.setDither(true);
839 c32.drawPaint(paint);
840 canvas->scale(12, 12);
841 canvas->drawBitmap(bm32, 0, 0);
842 paint.setBlendMode(SkBlendMode::kPlus);
843 canvas->drawBitmap(bm32, 0, 11, &paint);
844 canvas->drawBitmap(bm32, 0, 11, &paint);
845 canvas->drawBitmap(bm32, 0, 11, &paint);
846}
847##
848
849#Method bool isDither() const
850
Cary Clarkab2621d2018-01-30 10:08:57 -0500851#In Dither
852#Line # returns true if Dither is set ##
Cary Clark8032b982017-07-28 11:04:54 -0400853 If true, color error may be distributed to smooth color transition.
Herb Derbyfcac00f2018-05-01 11:57:56 -0400854
Cary Clark8032b982017-07-28 11:04:54 -0400855 Equivalent to getFlags masked with kDither_Flag.
856
857 #Return kDither_Flag state ##
858
859 #Example
860 SkPaint paint;
861 SkDebugf("paint.isDither() %c= !!(paint.getFlags() & SkPaint::kDither_Flag)\n",
862 paint.isDither() == !!(paint.getFlags() & SkPaint::kDither_Flag) ? '=' : '!');
863 paint.setDither(true);
864 SkDebugf("paint.isDither() %c= !!(paint.getFlags() & SkPaint::kDither_Flag)\n",
865 paint.isDither() == !!(paint.getFlags() & SkPaint::kDither_Flag) ? '=' : '!');
866
867 #StdOut
868 paint.isDither() == !!(paint.getFlags() & SkPaint::kDither_Flag)
869 paint.isDither() == !!(paint.getFlags() & SkPaint::kDither_Flag)
870 ##
871 ##
872
873##
874
875#Method void setDither(bool dither)
876
Cary Clarkab2621d2018-01-30 10:08:57 -0500877#In Dither
878#Line # sets or clears Dither ##
Cary Clark8032b982017-07-28 11:04:54 -0400879 Requests, but does not require, to distribute color error.
880
881 Sets kDither_Flag if dither is true.
882 Clears kDither_Flag if dither is false.
883
884 #Param dither setting for kDither_Flag ##
885
886 #Example
887 SkPaint paint1, paint2;
888 paint1.setDither(true);
889 paint2.setFlags(paint2.getFlags() | SkPaint::kDither_Flag);
890 SkDebugf("paint1 %c= paint2\n", paint1 == paint2 ? '=' : '!');
891
892 #StdOut
893 paint1 == paint2
894 ##
895 ##
896
897 #SeeAlso kRGB_565_SkColorType
898
899##
900
Cary Clarkffb3d682018-05-17 12:17:28 -0400901#SeeAlso Gradient kRGB_565_SkColorType
Cary Clark8032b982017-07-28 11:04:54 -0400902
Cary Clark08895c42018-02-01 09:37:32 -0500903#Subtopic Dither ##
Cary Clark8032b982017-07-28 11:04:54 -0400904# ------------------------------------------------------------------------------
Cary Clark08895c42018-02-01 09:37:32 -0500905#Subtopic Device_Text
906#Line # increase precision of glyph position ##
Cary Clark8032b982017-07-28 11:04:54 -0400907
908LCD_Text and Subpixel_Text increase the precision of glyph position.
909
Cary Clarkffb3d682018-05-17 12:17:28 -0400910When set, Flags kLCDRenderText_Flag takes advantage of the organization of RGB stripes that
Cary Clark8032b982017-07-28 11:04:54 -0400911create a color, and relies
Cary Clarkce101242017-09-01 15:51:02 -0400912on the small size of the stripe and visual perception to make the color fringing imperceptible.
Cary Clark8032b982017-07-28 11:04:54 -0400913LCD_Text can be enabled on devices that orient stripes horizontally or vertically, and that order
Cary Clarkffb3d682018-05-17 12:17:28 -0400914the color components as RGB or BGR.
Cary Clark8032b982017-07-28 11:04:54 -0400915
Herb Derbyfcac00f2018-05-01 11:57:56 -0400916Flags kSubpixelText_Flag uses the pixel transparency to represent a fractional offset.
Cary Clark8032b982017-07-28 11:04:54 -0400917As the opaqueness
918of the color increases, the edge of the glyph appears to move towards the outside of the pixel.
919
920Either or both techniques can be enabled.
921kLCDRenderText_Flag and kSubpixelText_Flag are clear by default.
Herb Derbyfcac00f2018-05-01 11:57:56 -0400922LCD_Text or Subpixel_Text can be enabled by default by setting SkPaintDefaults_Flags to
Cary Clark8032b982017-07-28 11:04:54 -0400923kLCDRenderText_Flag or kSubpixelText_Flag (or both) at compile time.
924
925#Example
926 #Description
927 Four commas are drawn normally and with combinations of LCD_Text and Subpixel_Text.
Cary Clarkce101242017-09-01 15:51:02 -0400928 When Subpixel_Text is disabled, the comma Glyphs are identical, but not evenly spaced.
929 When Subpixel_Text is enabled, the comma Glyphs are unique, but appear evenly spaced.
Cary Clark8032b982017-07-28 11:04:54 -0400930 ##
931
932 SkBitmap bitmap;
933 bitmap.allocN32Pixels(24, 33);
934 SkCanvas offscreen(bitmap);
935 offscreen.clear(SK_ColorWHITE);
936 SkPaint paint;
937 paint.setAntiAlias(true);
938 paint.setTextSize(20);
939 for (bool lcd : { false, true }) {
940 paint.setLCDRenderText(lcd);
941 for (bool subpixel : { false, true }) {
942 paint.setSubpixelText(subpixel);
943 offscreen.drawString(",,,,", 0, 4, paint);
944 offscreen.translate(0, 7);
945 }
946 }
947 canvas->drawBitmap(bitmap, 4, 12);
948 canvas->scale(9, 9);
949 canvas->drawBitmap(bitmap, 4, -1);
950##
Cary Clark08895c42018-02-01 09:37:32 -0500951#Subtopic Device_Text ##
Cary Clark8032b982017-07-28 11:04:54 -0400952
953#Subtopic Linear_Text
Cary Clark137b8742018-05-30 09:21:49 -0400954#Alias Linear_Text ##
Cary Clark08895c42018-02-01 09:37:32 -0500955#Line # selects text rendering as Glyph or Path ##
Cary Clark8032b982017-07-28 11:04:54 -0400956
957Linear_Text selects whether text is rendered as a Glyph or as a Path.
958If kLinearText_Flag is set, it has the same effect as setting Hinting to kNormal_Hinting.
Cary Clarkd0530ba2017-09-14 11:25:39 -0400959If kLinearText_Flag is clear, it is the same as setting Hinting to kNo_Hinting.
Cary Clark8032b982017-07-28 11:04:54 -0400960
961#Method bool isLinearText() const
962
Cary Clark08895c42018-02-01 09:37:32 -0500963#Line # returns true if text is converted to Path ##
Cary Clarkab2621d2018-01-30 10:08:57 -0500964#In Linear_Text
Cary Clark8032b982017-07-28 11:04:54 -0400965 If true, text is converted to Path before drawing and measuring.
966
967 Equivalent to getFlags masked with kLinearText_Flag.
968
969 #Return kLinearText_Flag state ##
970
971 #Example
972 #Height 128
973 void draw(SkCanvas* canvas) {
974 SkPaint paint;
975 paint.setAntiAlias(true);
976 const char testStr[] = "xxxx xxxx";
977 for (auto linearText : { false, true } ) {
978 paint.setLinearText(linearText);
979 paint.setTextSize(24);
980 canvas->drawString(paint.isLinearText() ? "linear" : "hinted", 128, 30, paint);
981 for (SkScalar textSize = 8; textSize < 30; textSize *= 1.22f) {
982 paint.setTextSize(textSize);
983 canvas->translate(0, textSize);
984 canvas->drawString(testStr, 10, 0, paint);
985 }
986 }
987 }
988 ##
989
990 #SeeAlso setLinearText Hinting
991##
992
993#Method void setLinearText(bool linearText)
994
Cary Clark08895c42018-02-01 09:37:32 -0500995#Line # converts to Path before draw or measure ##
Cary Clarkab2621d2018-01-30 10:08:57 -0500996#In Linear_Text
Cary Clark8032b982017-07-28 11:04:54 -0400997 If true, text is converted to Path before drawing and measuring.
998 By default, kLinearText_Flag is clear.
999
1000 Sets kLinearText_Flag if linearText is true.
1001 Clears kLinearText_Flag if linearText is false.
1002
1003 #Param linearText setting for kLinearText_Flag ##
1004
1005 #Example
1006 #Height 128
1007 void draw(SkCanvas* canvas) {
1008 SkPaint paint;
1009 paint.setAntiAlias(true);
1010 const char testStr[] = "abcd efgh";
1011 for (int textSize : { 12, 24 } ) {
1012 paint.setTextSize(textSize);
1013 for (auto linearText : { false, true } ) {
1014 paint.setLinearText(linearText);
1015 SkString width;
1016 width.appendScalar(paint.measureText(testStr, SK_ARRAY_COUNT(testStr), nullptr));
1017 canvas->translate(0, textSize + 4);
1018 canvas->drawString(testStr, 10, 0, paint);
1019 canvas->drawString(width, 128, 0, paint);
1020 }
1021 }
Herb Derbyfcac00f2018-05-01 11:57:56 -04001022 }
Cary Clark8032b982017-07-28 11:04:54 -04001023 ##
1024
1025 #SeeAlso isLinearText Hinting
1026##
1027
Cary Clark08895c42018-02-01 09:37:32 -05001028#Subtopic Linear_Text ##
Cary Clark8032b982017-07-28 11:04:54 -04001029
1030#Subtopic Subpixel_Text
Cary Clark137b8742018-05-30 09:21:49 -04001031#Alias Subpixel_Text ##
Cary Clark08895c42018-02-01 09:37:32 -05001032#Line # uses pixel transparency to represent fractional offset ##
Cary Clark8032b982017-07-28 11:04:54 -04001033
Herb Derbyfcac00f2018-05-01 11:57:56 -04001034Flags kSubpixelText_Flag uses the pixel transparency to represent a fractional offset.
Cary Clark8032b982017-07-28 11:04:54 -04001035As the opaqueness
1036of the color increases, the edge of the glyph appears to move towards the outside of the pixel.
1037
1038#Method bool isSubpixelText() const
Herb Derbyfcac00f2018-05-01 11:57:56 -04001039
Cary Clarkab2621d2018-01-30 10:08:57 -05001040#In Subpixel_Text
1041#Line # returns true if Subpixel_Text is set ##
Cary Clarkce101242017-09-01 15:51:02 -04001042 If true, Glyphs at different sub-pixel positions may differ on pixel edge coverage.
Cary Clark8032b982017-07-28 11:04:54 -04001043
1044 Equivalent to getFlags masked with kSubpixelText_Flag.
1045
1046 #Return kSubpixelText_Flag state ##
1047
1048 #Example
1049SkPaint paint;
1050SkDebugf("paint.isSubpixelText() %c= !!(paint.getFlags() & SkPaint::kSubpixelText_Flag)\n",
1051 paint.isSubpixelText() == !!(paint.getFlags() & SkPaint::kSubpixelText_Flag) ? '=' : '!');
1052paint.setSubpixelText(true);
1053SkDebugf("paint.isSubpixelText() %c= !!(paint.getFlags() & SkPaint::kSubpixelText_Flag)\n",
1054 paint.isSubpixelText() == !!(paint.getFlags() & SkPaint::kSubpixelText_Flag) ? '=' : '!');
1055
1056 #StdOut
1057 paint.isSubpixelText() == !!(paint.getFlags() & SkPaint::kSubpixelText_Flag)
1058 paint.isSubpixelText() == !!(paint.getFlags() & SkPaint::kSubpixelText_Flag)
1059 ##
1060 ##
1061
1062##
1063
1064#Method void setSubpixelText(bool subpixelText)
1065
Cary Clarkab2621d2018-01-30 10:08:57 -05001066#In Subpixel_Text
1067#Line # sets or clears Subpixel_Text ##
Cary Clarkce101242017-09-01 15:51:02 -04001068 Requests, but does not require, that Glyphs respect sub-pixel positioning.
Cary Clark8032b982017-07-28 11:04:54 -04001069
1070 Sets kSubpixelText_Flag if subpixelText is true.
1071 Clears kSubpixelText_Flag if subpixelText is false.
1072
1073 #Param subpixelText setting for kSubpixelText_Flag ##
1074
1075 #Example
1076 SkPaint paint1, paint2;
1077 paint1.setSubpixelText(true);
1078 paint2.setFlags(paint2.getFlags() | SkPaint::kSubpixelText_Flag);
1079 SkDebugf("paint1 %c= paint2\n", paint1 == paint2 ? '=' : '!');
1080
1081 #StdOut
1082 paint1 == paint2
1083 ##
1084 ##
1085
1086##
1087
Cary Clark08895c42018-02-01 09:37:32 -05001088#Subtopic Subpixel_Text ##
Cary Clark8032b982017-07-28 11:04:54 -04001089
1090#Subtopic LCD_Text
Cary Clarkffb3d682018-05-17 12:17:28 -04001091#Line # text relying on the order of RGB stripes ##
Cary Clark137b8742018-05-30 09:21:49 -04001092
1093# make this a top level name, since it is under subtopic Device_Text
1094#Alias LCD_Text
1095#Substitute LCD text
1096##
Cary Clark8032b982017-07-28 11:04:54 -04001097
Cary Clarkffb3d682018-05-17 12:17:28 -04001098When set, Flags kLCDRenderText_Flag takes advantage of the organization of RGB stripes that
Cary Clark8032b982017-07-28 11:04:54 -04001099create a color, and relies
Cary Clarkce101242017-09-01 15:51:02 -04001100on the small size of the stripe and visual perception to make the color fringing imperceptible.
Cary Clark8032b982017-07-28 11:04:54 -04001101LCD_Text can be enabled on devices that orient stripes horizontally or vertically, and that order
Cary Clarkffb3d682018-05-17 12:17:28 -04001102the color components as RGB or BGR.
Cary Clark8032b982017-07-28 11:04:54 -04001103
1104#Method bool isLCDRenderText() const
1105
Cary Clarkab2621d2018-01-30 10:08:57 -05001106#In LCD_Text
1107#Line # returns true if LCD_Text is set ##
Cary Clarkce101242017-09-01 15:51:02 -04001108 If true, Glyphs may use LCD striping to improve glyph edges.
Cary Clark8032b982017-07-28 11:04:54 -04001109
1110 Returns true if Flags kLCDRenderText_Flag is set.
1111
1112 #Return kLCDRenderText_Flag state ##
1113
1114 #Example
1115SkPaint paint;
1116SkDebugf("paint.isLCDRenderText() %c= !!(paint.getFlags() & SkPaint::kLCDRenderText_Flag)\n",
1117 paint.isLCDRenderText() == !!(paint.getFlags() & SkPaint::kLCDRenderText_Flag) ? '=' : '!');
1118paint.setLCDRenderText(true);
1119SkDebugf("paint.isLCDRenderText() %c= !!(paint.getFlags() & SkPaint::kLCDRenderText_Flag)\n",
1120 paint.isLCDRenderText() == !!(paint.getFlags() & SkPaint::kLCDRenderText_Flag) ? '=' : '!');
1121
1122 #StdOut
1123 paint.isLCDRenderText() == !!(paint.getFlags() & SkPaint::kLCDRenderText_Flag)
1124 paint.isLCDRenderText() == !!(paint.getFlags() & SkPaint::kLCDRenderText_Flag)
1125 ##
1126 ##
1127
1128##
1129
1130#Method void setLCDRenderText(bool lcdText)
1131
Cary Clarkab2621d2018-01-30 10:08:57 -05001132#In LCD_Text
1133#Line # sets or clears LCD_Text ##
Cary Clarkce101242017-09-01 15:51:02 -04001134 Requests, but does not require, that Glyphs use LCD striping for glyph edges.
Cary Clark8032b982017-07-28 11:04:54 -04001135
1136 Sets kLCDRenderText_Flag if lcdText is true.
1137 Clears kLCDRenderText_Flag if lcdText is false.
1138
1139 #Param lcdText setting for kLCDRenderText_Flag ##
1140
1141 #Example
1142 SkPaint paint1, paint2;
1143 paint1.setLCDRenderText(true);
1144 paint2.setFlags(paint2.getFlags() | SkPaint::kLCDRenderText_Flag);
1145 SkDebugf("paint1 %c= paint2\n", paint1 == paint2 ? '=' : '!');
1146
1147 #StdOut
1148 paint1 == paint2
1149 ##
1150 ##
1151
1152
1153##
1154
Cary Clark08895c42018-02-01 09:37:32 -05001155#Subtopic LCD_Text ##
Cary Clark8032b982017-07-28 11:04:54 -04001156
Cary Clark8032b982017-07-28 11:04:54 -04001157# ------------------------------------------------------------------------------
Cary Clark08895c42018-02-01 09:37:32 -05001158#Subtopic Font_Embedded_Bitmaps
1159#Line # custom sized bitmap Glyphs ##
Cary Clark137b8742018-05-30 09:21:49 -04001160#Alias Font_Embedded_Bitmaps ## # long-winded enough, alias so I don't type Paint_Font_...
Cary Clark8032b982017-07-28 11:04:54 -04001161
Cary Clarkce101242017-09-01 15:51:02 -04001162Font_Embedded_Bitmaps allows selecting custom sized bitmap Glyphs.
Cary Clark8032b982017-07-28 11:04:54 -04001163Flags kEmbeddedBitmapText_Flag when set chooses an embedded bitmap glyph over an outline contained
Herb Derbyfcac00f2018-05-01 11:57:56 -04001164in a font if the platform supports this option.
Cary Clark8032b982017-07-28 11:04:54 -04001165
1166FreeType selects the bitmap glyph if available when kEmbeddedBitmapText_Flag is set, and selects
1167the outline glyph if kEmbeddedBitmapText_Flag is clear.
1168Windows may select the bitmap glyph but is not required to do so.
1169OS_X and iOS do not support this option.
1170
1171Font_Embedded_Bitmaps is disabled by default.
1172Font_Embedded_Bitmaps can be enabled by default by setting SkPaintDefaults_Flags to
1173kEmbeddedBitmapText_Flag at compile time.
1174
1175#Example
1176 #ToDo image will only output on Ubuntu ... how to handle that in fiddle? ##
1177 #Platform !fiddle
1178 #Description
Cary Clarkce101242017-09-01 15:51:02 -04001179 The "hintgasp" TrueType font in the Skia resources/fonts directory
1180 includes an embedded bitmap Glyph at odd font sizes. This example works
1181 on platforms that use FreeType as their Font_Engine.
1182 Windows may, but is not required to, return a bitmap glyph if
1183 kEmbeddedBitmapText_Flag is set.
Cary Clark8032b982017-07-28 11:04:54 -04001184 ##
1185 #Image embeddedbitmap.png
1186
1187 SkBitmap bitmap;
1188 bitmap.allocN32Pixels(30, 15);
1189 bitmap.eraseColor(0);
1190 SkCanvas offscreen(bitmap);
1191 SkPaint paint;
1192 paint.setAntiAlias(true);
1193 paint.setTextSize(13);
Hal Canary53e5e7d2017-12-08 14:25:14 -05001194 paint.setTypeface(MakeResourceAsTypeface("fonts/hintgasp.ttf"));
Cary Clark8032b982017-07-28 11:04:54 -04001195 for (bool embedded : { false, true}) {
1196 paint.setEmbeddedBitmapText(embedded);
1197 offscreen.drawString("A", embedded ? 5 : 15, 15, paint);
1198 }
1199 canvas->drawBitmap(bitmap, 0, 0);
1200 canvas->scale(10, 10);
1201 canvas->drawBitmap(bitmap, -2, 1);
1202##
1203
1204#Method bool isEmbeddedBitmapText() const
1205
Cary Clarkab2621d2018-01-30 10:08:57 -05001206#In Font_Embedded_Bitmaps
1207#Line # returns true if Font_Embedded_Bitmaps is set ##
Cary Clarkce101242017-09-01 15:51:02 -04001208 If true, Font_Engine may return Glyphs from font bitmaps instead of from outlines.
Cary Clark8032b982017-07-28 11:04:54 -04001209
1210 Equivalent to getFlags masked with kEmbeddedBitmapText_Flag.
1211
1212 #Return kEmbeddedBitmapText_Flag state ##
1213
1214 #Example
1215 SkPaint paint;
1216 SkDebugf("paint.isEmbeddedBitmapText() %c="
1217 " !!(paint.getFlags() & SkPaint::kEmbeddedBitmapText_Flag)\n",
1218 paint.isEmbeddedBitmapText() ==
1219 !!(paint.getFlags() & SkPaint::kEmbeddedBitmapText_Flag) ? '=' : '!');
1220 paint.setEmbeddedBitmapText(true);
1221 SkDebugf("paint.isEmbeddedBitmapText() %c="
1222 " !!(paint.getFlags() & SkPaint::kEmbeddedBitmapText_Flag)\n",
1223 paint.isEmbeddedBitmapText() ==
1224 !!(paint.getFlags() & SkPaint::kEmbeddedBitmapText_Flag) ? '=' : '!');
1225
1226 #StdOut
1227 paint.isEmbeddedBitmapText() == !!(paint.getFlags() & SkPaint::kEmbeddedBitmapText_Flag)
1228 paint.isEmbeddedBitmapText() == !!(paint.getFlags() & SkPaint::kEmbeddedBitmapText_Flag)
1229 ##
1230 ##
1231
1232##
1233
1234#Method void setEmbeddedBitmapText(bool useEmbeddedBitmapText)
1235
Cary Clarkab2621d2018-01-30 10:08:57 -05001236#In Font_Embedded_Bitmaps
1237#Line # sets or clears Font_Embedded_Bitmaps ##
Cary Clark8032b982017-07-28 11:04:54 -04001238 Requests, but does not require, to use bitmaps in fonts instead of outlines.
1239
1240 Sets kEmbeddedBitmapText_Flag if useEmbeddedBitmapText is true.
1241 Clears kEmbeddedBitmapText_Flag if useEmbeddedBitmapText is false.
1242
1243 #Param useEmbeddedBitmapText setting for kEmbeddedBitmapText_Flag ##
1244
1245 #Example
1246 SkPaint paint1, paint2;
1247 paint1.setEmbeddedBitmapText(true);
1248 paint2.setFlags(paint2.getFlags() | SkPaint::kEmbeddedBitmapText_Flag);
1249 SkDebugf("paint1 %c= paint2\n", paint1 == paint2 ? '=' : '!');
1250
1251 #StdOut
1252 paint1 == paint2
1253 ##
1254 ##
1255
1256##
1257
Cary Clark08895c42018-02-01 09:37:32 -05001258#Subtopic Font_Embedded_Bitmaps ##
Cary Clark8032b982017-07-28 11:04:54 -04001259# ------------------------------------------------------------------------------
Cary Clark08895c42018-02-01 09:37:32 -05001260#Subtopic Automatic_Hinting
1261#Line # always adjust glyph paths ##
Cary Clark8032b982017-07-28 11:04:54 -04001262#Substitute auto-hinting
1263
1264If Hinting is set to kNormal_Hinting or kFull_Hinting, Automatic_Hinting
Cary Clarkce101242017-09-01 15:51:02 -04001265instructs the Font_Manager to always hint Glyphs.
Cary Clark8032b982017-07-28 11:04:54 -04001266Automatic_Hinting has no effect if Hinting is set to kNo_Hinting or
1267kSlight_Hinting.
1268
1269Automatic_Hinting only affects platforms that use FreeType as the Font_Manager.
1270
1271#Method bool isAutohinted() const
1272
Cary Clarkab2621d2018-01-30 10:08:57 -05001273#In Automatic_Hinting
1274#Line # returns true if Glyphs are always hinted ##
Cary Clark8032b982017-07-28 11:04:54 -04001275 If true, and if Hinting is set to kNormal_Hinting or kFull_Hinting, and if
1276 platform uses FreeType as the Font_Manager, instruct the Font_Manager to always hint
Cary Clarkce101242017-09-01 15:51:02 -04001277 Glyphs.
Cary Clark8032b982017-07-28 11:04:54 -04001278
1279 Equivalent to getFlags masked with kAutoHinting_Flag.
1280
1281 #Return kAutoHinting_Flag state ##
1282
1283 #Example
1284 SkPaint paint;
1285 for (auto forceAutoHinting : { false, true} ) {
1286 paint.setAutohinted(forceAutoHinting);
1287 SkDebugf("paint.isAutohinted() %c="
1288 " !!(paint.getFlags() & SkPaint::kAutoHinting_Flag)\n",
1289 paint.isAutohinted() ==
1290 !!(paint.getFlags() & SkPaint::kAutoHinting_Flag) ? '=' : '!');
1291 }
1292 #StdOut
1293 paint.isAutohinted() == !!(paint.getFlags() & SkPaint::kAutoHinting_Flag)
1294 paint.isAutohinted() == !!(paint.getFlags() & SkPaint::kAutoHinting_Flag)
1295 ##
1296 ##
1297
1298 #SeeAlso setAutohinted Hinting
1299
1300##
1301
1302#Method void setAutohinted(bool useAutohinter)
1303
Cary Clarkab2621d2018-01-30 10:08:57 -05001304#In Automatic_Hinting
1305#Line # sets Glyphs to always be hinted ##
Cary Clark8032b982017-07-28 11:04:54 -04001306 If Hinting is set to kNormal_Hinting or kFull_Hinting and useAutohinter is set,
Cary Clarkce101242017-09-01 15:51:02 -04001307 instruct the Font_Manager to always hint Glyphs.
Cary Clark8032b982017-07-28 11:04:54 -04001308 Automatic_Hinting has no effect if Hinting is set to kNo_Hinting or
1309 kSlight_Hinting.
1310
Cary Clark579985c2017-07-31 11:48:27 -04001311 Only affects platforms that use FreeType as the Font_Manager.
Cary Clark8032b982017-07-28 11:04:54 -04001312
1313 Sets kAutoHinting_Flag if useAutohinter is true.
1314 Clears kAutoHinting_Flag if useAutohinter is false.
1315
1316 #Param useAutohinter setting for kAutoHinting_Flag ##
1317
1318 #Example
1319 void draw(SkCanvas* canvas) {
1320 SkPaint paint;
1321 paint.setAntiAlias(true);
1322 const char testStr[] = "xxxx xxxx";
1323 for (auto forceAutoHinting : { false, true} ) {
1324 paint.setAutohinted(forceAutoHinting);
1325 paint.setTextSize(24);
1326 canvas->drawString(paint.isAutohinted() ? "auto-hinted" : "default", 108, 30, paint);
1327 for (SkScalar textSize = 8; textSize < 30; textSize *= 1.22f) {
1328 paint.setTextSize(textSize);
1329 canvas->translate(0, textSize);
1330 canvas->drawString(testStr, 10, 0, paint);
1331 }
1332 }
1333 }
1334 ##
1335
1336 #SeeAlso isAutohinted Hinting
1337
1338##
1339
Cary Clark08895c42018-02-01 09:37:32 -05001340#Subtopic Automatic_Hinting ##
Cary Clark8032b982017-07-28 11:04:54 -04001341# ------------------------------------------------------------------------------
Cary Clark08895c42018-02-01 09:37:32 -05001342#Subtopic Vertical_Text
1343#Line # orient text from top to bottom ##
Cary Clark8032b982017-07-28 11:04:54 -04001344
1345Text may be drawn by positioning each glyph, or by positioning the first glyph and
Cary Clarkce101242017-09-01 15:51:02 -04001346using Font_Advance to position subsequent Glyphs. By default, each successive glyph
1347is positioned to the right of the preceding glyph. Vertical_Text sets successive
1348Glyphs to position below the preceding glyph.
Cary Clark8032b982017-07-28 11:04:54 -04001349
Cary Clarkce101242017-09-01 15:51:02 -04001350Skia can translate text character codes as a series of Glyphs, but does not implement
Herb Derbyfcac00f2018-05-01 11:57:56 -04001351font substitution,
Cary Clarkce101242017-09-01 15:51:02 -04001352textual substitution, line layout, or contextual spacing like Kerning pairs. Use
Cary Clark6fc50412017-09-21 12:31:06 -04001353a text shaping engine like
Cary Clark682c58d2018-05-16 07:07:07 -04001354#A HarfBuzz # https://harfbuzz.org/ ##
Cary Clark6fc50412017-09-21 12:31:06 -04001355 to translate text runs
Cary Clark8032b982017-07-28 11:04:54 -04001356into glyph series.
1357
1358Vertical_Text is clear if text is drawn left to right or set if drawn from top to bottom.
1359
1360Flags kVerticalText_Flag if clear draws text left to right.
1361Flags kVerticalText_Flag if set draws text top to bottom.
1362
1363Vertical_Text is clear by default.
1364Vertical_Text can be set by default by setting SkPaintDefaults_Flags to
1365kVerticalText_Flag at compile time.
1366
1367#Example
1368
1369void draw(SkCanvas* canvas) {
1370 SkPaint paint;
1371 paint.setAntiAlias(true);
1372 paint.setTextSize(50);
1373 for (bool vertical : { false, true } ) {
1374 paint.setVerticalText(vertical);
1375 canvas->drawString("aAlL", 25, 50, paint);
1376 }
1377}
1378
1379##
1380
1381#Method bool isVerticalText() const
1382
Cary Clarkab2621d2018-01-30 10:08:57 -05001383#In Vertical_Text
1384#Line # returns true if Vertical_Text is set ##
Cary Clarkce101242017-09-01 15:51:02 -04001385 If true, Glyphs are drawn top to bottom instead of left to right.
Cary Clark8032b982017-07-28 11:04:54 -04001386
1387 Equivalent to getFlags masked with kVerticalText_Flag.
1388
1389 #Return kVerticalText_Flag state ##
1390
1391 #Example
1392 SkPaint paint;
1393 SkDebugf("paint.isVerticalText() %c= !!(paint.getFlags() & SkPaint::kVerticalText_Flag)\n",
1394 paint.isVerticalText() == !!(paint.getFlags() & SkPaint::kVerticalText_Flag) ? '=' : '!');
1395 paint.setVerticalText(true);
1396 SkDebugf("paint.isVerticalText() %c= !!(paint.getFlags() & SkPaint::kVerticalText_Flag)\n",
1397 paint.isVerticalText() == !!(paint.getFlags() & SkPaint::kVerticalText_Flag) ? '=' : '!');
1398
1399 #StdOut
1400 paint.isVerticalText() == !!(paint.getFlags() & SkPaint::kVerticalText_Flag)
1401 paint.isVerticalText() == !!(paint.getFlags() & SkPaint::kVerticalText_Flag)
1402 ##
1403 ##
1404
1405##
1406
1407#Method void setVerticalText(bool verticalText)
1408
Cary Clarkab2621d2018-01-30 10:08:57 -05001409#In Vertical_Text
1410#Line # sets or clears Vertical_Text ##
Cary Clark8032b982017-07-28 11:04:54 -04001411 If true, text advance positions the next glyph below the previous glyph instead of to the
1412 right of previous glyph.
1413
1414 Sets kVerticalText_Flag if vertical is true.
1415 Clears kVerticalText_Flag if vertical is false.
1416
1417 #Param verticalText setting for kVerticalText_Flag ##
1418
1419 #Example
1420 SkPaint paint1, paint2;
1421 paint1.setVerticalText(true);
1422 paint2.setFlags(paint2.getFlags() | SkPaint::kVerticalText_Flag);
1423 SkDebugf("paint1 %c= paint2\n", paint1 == paint2 ? '=' : '!');
1424
1425 #StdOut
1426 paint1 == paint2
1427 ##
1428 ##
1429
1430##
1431
Cary Clark08895c42018-02-01 09:37:32 -05001432#Subtopic Vertical_Text ##
Cary Clark8032b982017-07-28 11:04:54 -04001433# ------------------------------------------------------------------------------
1434
Cary Clark08895c42018-02-01 09:37:32 -05001435#Subtopic Fake_Bold
1436#Line # approximate font styles ##
Cary Clark8032b982017-07-28 11:04:54 -04001437
1438Fake_Bold approximates the bold font style accompanying a normal font when a bold font face
1439is not available. Skia does not provide font substitution; it is up to the client to find the
Cary Clarkbc5697d2017-10-04 14:31:33 -04001440bold font face using the platform Font_Manager.
Cary Clark8032b982017-07-28 11:04:54 -04001441
Herb Derbyfcac00f2018-05-01 11:57:56 -04001442Use Text_Skew_X to approximate an italic font style when the italic font face
Cary Clark8032b982017-07-28 11:04:54 -04001443is not available.
1444
Cary Clarkce101242017-09-01 15:51:02 -04001445A FreeType based port may define SK_USE_FREETYPE_EMBOLDEN at compile time to direct
1446the font engine to create the bold Glyphs. Otherwise, the extra bold is computed
Herb Derbyfcac00f2018-05-01 11:57:56 -04001447by increasing the stroke width and setting the Style to kStrokeAndFill_Style as needed.
Cary Clark8032b982017-07-28 11:04:54 -04001448
1449Fake_Bold is disabled by default.
1450
1451#Example
1452#Height 128
1453void draw(SkCanvas* canvas) {
1454 SkPaint paint;
1455 paint.setAntiAlias(true);
1456 paint.setTextSize(40);
1457 canvas->drawString("OjYy_-", 10, 35, paint);
1458 paint.setFakeBoldText(true);
1459 canvas->drawString("OjYy_-", 10, 75, paint);
1460 // create a custom fake bold by varying the stroke width
1461 paint.setFakeBoldText(false);
1462 paint.setStyle(SkPaint::kStrokeAndFill_Style);
1463 paint.setStrokeWidth(40.f / 48);
1464 canvas->drawString("OjYy_-", 10, 115, paint);
1465}
1466##
1467
1468#Method bool isFakeBoldText() const
1469
Cary Clarkab2621d2018-01-30 10:08:57 -05001470#In Fake_Bold
1471#Line # returns true if Fake_Bold is set ##
Cary Clark8032b982017-07-28 11:04:54 -04001472 If true, approximate bold by increasing the stroke width when creating glyph bitmaps
1473 from outlines.
1474
1475 Equivalent to getFlags masked with kFakeBoldText_Flag.
1476
1477 #Return kFakeBoldText_Flag state ##
1478
1479 #Example
1480 SkPaint paint;
1481 SkDebugf("paint.isFakeBoldText() %c= !!(paint.getFlags() & SkPaint::kFakeBoldText_Flag)\n",
1482 paint.isFakeBoldText() == !!(paint.getFlags() & SkPaint::kFakeBoldText_Flag) ? '=' : '!');
1483 paint.setFakeBoldText(true);
1484 SkDebugf("paint.isFakeBoldText() %c= !!(paint.getFlags() & SkPaint::kFakeBoldText_Flag)\n",
1485 paint.isFakeBoldText() == !!(paint.getFlags() & SkPaint::kFakeBoldText_Flag) ? '=' : '!');
1486
1487 #StdOut
1488 paint.isFakeBoldText() == !!(paint.getFlags() & SkPaint::kFakeBoldText_Flag)
1489 paint.isFakeBoldText() == !!(paint.getFlags() & SkPaint::kFakeBoldText_Flag)
1490 ##
1491 ##
1492
1493##
1494
1495#Method void setFakeBoldText(bool fakeBoldText)
1496
Cary Clarkab2621d2018-01-30 10:08:57 -05001497#In Fake_Bold
1498#Line # sets or clears Fake_Bold ##
Cary Clarkce101242017-09-01 15:51:02 -04001499 Use increased stroke width when creating glyph bitmaps to approximate a bold typeface.
Cary Clark8032b982017-07-28 11:04:54 -04001500
1501 Sets kFakeBoldText_Flag if fakeBoldText is true.
1502 Clears kFakeBoldText_Flag if fakeBoldText is false.
1503
1504 #Param fakeBoldText setting for kFakeBoldText_Flag ##
1505
1506 #Example
1507 SkPaint paint1, paint2;
1508 paint1.setFakeBoldText(true);
1509 paint2.setFlags(paint2.getFlags() | SkPaint::kFakeBoldText_Flag);
1510 SkDebugf("paint1 %c= paint2\n", paint1 == paint2 ? '=' : '!');
1511
1512 #StdOut
1513 paint1 == paint2
1514 ##
1515 ##
1516
1517##
1518
Cary Clark08895c42018-02-01 09:37:32 -05001519#Subtopic Fake_Bold ##
Cary Clark8032b982017-07-28 11:04:54 -04001520
1521# ------------------------------------------------------------------------------
Cary Clark08895c42018-02-01 09:37:32 -05001522#Subtopic Full_Hinting_Spacing
1523#Line # glyph spacing affected by hinting ##
Cary Clark137b8742018-05-30 09:21:49 -04001524#Alias Full_Hinting_Spacing ## # long winded enough -- maybe things with two underscores auto-aliased?
Cary Clark8032b982017-07-28 11:04:54 -04001525
Cary Clarkce101242017-09-01 15:51:02 -04001526if Hinting is set to kFull_Hinting, Full_Hinting_Spacing adjusts the character
1527spacing by the difference of the hinted and Unhinted Left_Side_Bearing and
1528Right_Side_Bearing. Full_Hinting_Spacing only applies to platforms that use
1529FreeType as their Font_Engine.
Cary Clark8032b982017-07-28 11:04:54 -04001530
Cary Clarkce101242017-09-01 15:51:02 -04001531Full_Hinting_Spacing is not related to text Kerning, where the space between
Cary Clarkbc5697d2017-10-04 14:31:33 -04001532a specific pair of characters is adjusted using data in the font Kerning tables.
Cary Clark8032b982017-07-28 11:04:54 -04001533
1534#Method bool isDevKernText() const
Herb Derbyfcac00f2018-05-01 11:57:56 -04001535#Deprecated
Cary Clark8032b982017-07-28 11:04:54 -04001536##
1537
Herb Derbyfcac00f2018-05-01 11:57:56 -04001538#Method void setDevKernText(bool)
1539#Deprecated
Cary Clark8032b982017-07-28 11:04:54 -04001540##
1541
Cary Clark08895c42018-02-01 09:37:32 -05001542#Subtopic Full_Hinting_Spacing ##
Cary Clark8032b982017-07-28 11:04:54 -04001543# ------------------------------------------------------------------------------
Cary Clark08895c42018-02-01 09:37:32 -05001544#Subtopic Filter_Quality_Methods
1545#Line # get and set Filter_Quality ##
Cary Clark8032b982017-07-28 11:04:54 -04001546
1547Filter_Quality trades speed for image filtering when the image is scaled.
1548A lower Filter_Quality draws faster, but has less fidelity.
1549A higher Filter_Quality draws slower, but looks better.
Cary Clarkce101242017-09-01 15:51:02 -04001550If the image is drawn without scaling, the Filter_Quality choice will not result
1551in a noticeable difference.
Cary Clark8032b982017-07-28 11:04:54 -04001552
1553Filter_Quality is used in Paint passed as a parameter to
1554#List
1555# SkCanvas::drawBitmap ##
1556# SkCanvas::drawBitmapRect ##
1557# SkCanvas::drawImage ##
1558# SkCanvas::drawImageRect ##
1559 #ToDo probably more... ##
1560#List ##
1561and when Paint has a Shader specialization that uses Image or Bitmap.
1562
1563Filter_Quality is kNone_SkFilterQuality by default.
1564
1565#Example
1566#Image 3
1567void draw(SkCanvas* canvas) {
1568 SkPaint paint;
1569 canvas->scale(.2f, .2f);
Herb Derbyfcac00f2018-05-01 11:57:56 -04001570 for (SkFilterQuality q : { kNone_SkFilterQuality, kLow_SkFilterQuality,
Cary Clark8032b982017-07-28 11:04:54 -04001571 kMedium_SkFilterQuality, kHigh_SkFilterQuality } ) {
1572 paint.setFilterQuality(q);
1573 canvas->drawImage(image.get(), 0, 0, &paint);
1574 canvas->translate(550, 0);
1575 if (kLow_SkFilterQuality == q) canvas->translate(-1100, 550);
1576 }
1577}
1578##
1579
1580#Method SkFilterQuality getFilterQuality() const
1581
Cary Clarkab2621d2018-01-30 10:08:57 -05001582#In Filter_Quality_Methods
1583#Line # returns Filter_Quality, image filtering level ##
Cary Clark8032b982017-07-28 11:04:54 -04001584Returns Filter_Quality, the image filtering level. A lower setting
1585draws faster; a higher setting looks better when the image is scaled.
1586
Herb Derbyfcac00f2018-05-01 11:57:56 -04001587#Return one of: kNone_SkFilterQuality, kLow_SkFilterQuality,
Cary Clark8032b982017-07-28 11:04:54 -04001588 kMedium_SkFilterQuality, kHigh_SkFilterQuality
1589#Return ##
1590
1591#Example
1592 SkPaint paint;
1593 SkDebugf("kNone_SkFilterQuality %c= paint.getFilterQuality()\n",
1594 kNone_SkFilterQuality == paint.getFilterQuality() ? '=' : '!');
1595
1596 #StdOut
1597 kNone_SkFilterQuality == paint.getFilterQuality()
1598 ##
1599##
1600
1601##
1602
1603
1604#Method void setFilterQuality(SkFilterQuality quality)
1605
Cary Clarkab2621d2018-01-30 10:08:57 -05001606#In Filter_Quality_Methods
1607#Line # sets Filter_Quality, the image filtering level ##
Cary Clark8032b982017-07-28 11:04:54 -04001608Sets Filter_Quality, the image filtering level. A lower setting
1609draws faster; a higher setting looks better when the image is scaled.
Herb Derbyfcac00f2018-05-01 11:57:56 -04001610Does not check to see if quality is valid.
Cary Clark8032b982017-07-28 11:04:54 -04001611
Herb Derbyfcac00f2018-05-01 11:57:56 -04001612#Param quality one of: kNone_SkFilterQuality, kLow_SkFilterQuality,
Cary Clark8032b982017-07-28 11:04:54 -04001613 kMedium_SkFilterQuality, kHigh_SkFilterQuality
1614##
1615
1616#Example
1617 SkPaint paint;
1618 paint.setFilterQuality(kHigh_SkFilterQuality);
1619 SkDebugf("kHigh_SkFilterQuality %c= paint.getFilterQuality()\n",
1620 kHigh_SkFilterQuality == paint.getFilterQuality() ? '=' : '!');
1621
1622 #StdOut
1623 kHigh_SkFilterQuality == paint.getFilterQuality()
1624 ##
1625##
1626
1627#SeeAlso SkFilterQuality Image_Scaling
1628
1629##
1630
Cary Clark08895c42018-02-01 09:37:32 -05001631#Subtopic Filter_Quality_Methods ##
Cary Clark8032b982017-07-28 11:04:54 -04001632# ------------------------------------------------------------------------------
Cary Clark08895c42018-02-01 09:37:32 -05001633#Subtopic Color_Methods
1634#Line # get and set Color ##
Cary Clark8032b982017-07-28 11:04:54 -04001635
Cary Clarkab2621d2018-01-30 10:08:57 -05001636#Table
1637#Legend
1638# name # description ##
1639#Legend ##
Cary Clarkffb3d682018-05-17 12:17:28 -04001640# getColor # returns Color_Alpha and RGB, one drawing color ##
1641# setColor # sets Color_Alpha and RGB, one drawing color ##
Cary Clarkab2621d2018-01-30 10:08:57 -05001642#Table ##
Cary Clark8032b982017-07-28 11:04:54 -04001643
Cary Clarkffb3d682018-05-17 12:17:28 -04001644Color specifies the red, blue, green, and Color_Alpha
Cary Clarkab2621d2018-01-30 10:08:57 -05001645values used to draw a filled or stroked shape in a 32-bit value. Each component
1646occupies 8-bits, ranging from zero: no contribution; to 255: full intensity.
1647All values in any combination are valid.
Cary Clark8032b982017-07-28 11:04:54 -04001648
Cary Clarkab2621d2018-01-30 10:08:57 -05001649Color is not Premultiplied; Color_Alpha sets the transparency independent of
Cary Clarkffb3d682018-05-17 12:17:28 -04001650RGB: red, blue, and green.
Cary Clarkab2621d2018-01-30 10:08:57 -05001651
Cary Clarkffb3d682018-05-17 12:17:28 -04001652The bit positions of Color_Alpha and RGB are independent of the bit
Cary Clarkab2621d2018-01-30 10:08:57 -05001653positions on the output device, which may have more or fewer bits, and may have
1654a different arrangement.
Cary Clark8032b982017-07-28 11:04:54 -04001655
1656#Table
1657#Legend
Cary Clarkffb3d682018-05-17 12:17:28 -04001658# bit positions # Color_Alpha # red # blue # green ##
Cary Clark8032b982017-07-28 11:04:54 -04001659#Legend ##
1660# # 31 - 24 # 23 - 16 # 15 - 8 # 7 - 0 ##
1661#Table ##
1662
1663#Example
1664#Height 128
1665 void draw(SkCanvas* canvas) {
1666 SkPaint paint;
1667 paint.setColor(0x8000FF00); // transparent green
1668 canvas->drawCircle(50, 50, 40, paint);
1669 paint.setARGB(128, 255, 0, 0); // transparent red
1670 canvas->drawCircle(80, 50, 40, paint);
1671 paint.setColor(SK_ColorBLUE);
1672 paint.setAlpha(0x80);
1673 canvas->drawCircle(65, 65, 40, paint);
1674 }
1675##
1676
1677#Method SkColor getColor() const
1678
Cary Clarkab2621d2018-01-30 10:08:57 -05001679#In Color_Methods
Cary Clarkffb3d682018-05-17 12:17:28 -04001680#Line # returns Color_Alpha and RGB, one drawing color ##
1681 Retrieves Alpha and RGB, Unpremultiplied, packed into 32 bits.
Cary Clark8032b982017-07-28 11:04:54 -04001682 Use helpers SkColorGetA, SkColorGetR, SkColorGetG, and SkColorGetB to extract
1683 a color component.
1684
Cary Clarkffb3d682018-05-17 12:17:28 -04001685 #Return Unpremultiplied ARGB ##
Cary Clark8032b982017-07-28 11:04:54 -04001686
1687 #Example
1688 SkPaint paint;
1689 paint.setColor(SK_ColorYELLOW);
1690 SkColor y = paint.getColor();
1691 SkDebugf("Yellow is %d%% red, %d%% green, and %d%% blue.\n", (int) (SkColorGetR(y) / 2.55f),
1692 (int) (SkColorGetG(y) / 2.55f), (int) (SkColorGetB(y) / 2.55f));
1693
1694 #StdOut
1695 Yellow is 100% red, 100% green, and 0% blue.
1696 ##
1697 ##
1698
1699 #SeeAlso SkColor
1700
1701##
1702
1703#Method void setColor(SkColor color)
1704
Cary Clarkab2621d2018-01-30 10:08:57 -05001705#In Color_Methods
Cary Clarkffb3d682018-05-17 12:17:28 -04001706#Line # sets Color_Alpha and RGB, one drawing color ##
1707 Sets Alpha and RGB used when stroking and filling. The color is a 32-bit value,
1708 Unpremultiplied, packing 8-bit components for Alpha, red, blue, and green.
Cary Clark8032b982017-07-28 11:04:54 -04001709
Cary Clarkffb3d682018-05-17 12:17:28 -04001710 #Param color Unpremultiplied ARGB ##
Herb Derbyfcac00f2018-05-01 11:57:56 -04001711
Cary Clark0c5f5462017-12-15 11:21:51 -05001712 #Example
Cary Clark8032b982017-07-28 11:04:54 -04001713 SkPaint green1, green2;
1714 unsigned a = 255;
1715 unsigned r = 0;
1716 unsigned g = 255;
1717 unsigned b = 0;
1718 green1.setColor((a << 24) + (r << 16) + (g << 8) + (b << 0));
1719 green2.setColor(0xFF00FF00);
1720 SkDebugf("green1 %c= green2\n", green1 == green2 ? '=' : '!');
1721
1722 #StdOut
1723 green1 == green2
1724 ##
1725 ##
1726
1727 #SeeAlso SkColor setARGB SkColorSetARGB
1728
1729##
Cary Clark08895c42018-02-01 09:37:32 -05001730#Subtopic Color_Methods ##
Cary Clark8032b982017-07-28 11:04:54 -04001731
1732#Subtopic Alpha_Methods
Cary Clark08895c42018-02-01 09:37:32 -05001733#Line # get and set Alpha ##
Cary Clark8032b982017-07-28 11:04:54 -04001734
Cary Clarkffb3d682018-05-17 12:17:28 -04001735Color_Alpha sets the transparency independent of RGB: red, blue, and green.
Cary Clark8032b982017-07-28 11:04:54 -04001736
1737#Method uint8_t getAlpha() const
1738
Cary Clarkab2621d2018-01-30 10:08:57 -05001739#In Alpha_Methods
1740#Line # returns Color_Alpha, color opacity ##
Cary Clarkce101242017-09-01 15:51:02 -04001741 Retrieves Alpha from the Color used when stroking and filling.
Cary Clark8032b982017-07-28 11:04:54 -04001742
Cary Clarkce101242017-09-01 15:51:02 -04001743 #Return Alpha ranging from zero, fully transparent, to 255, fully opaque ##
Cary Clark8032b982017-07-28 11:04:54 -04001744
1745 #Example
1746 SkPaint paint;
1747 SkDebugf("255 %c= paint.getAlpha()\n", 255 == paint.getAlpha() ? '=' : '!');
1748
1749 #StdOut
1750 255 == paint.getAlpha()
1751 ##
1752 ##
1753
1754##
1755
1756#Method void setAlpha(U8CPU a)
1757
Cary Clarkab2621d2018-01-30 10:08:57 -05001758#In Alpha_Methods
1759#Line # sets Color_Alpha, color opacity ##
Cary Clarkffb3d682018-05-17 12:17:28 -04001760 Replaces Alpha, leaving RGB
Cary Clark8032b982017-07-28 11:04:54 -04001761 unchanged. An out of range value triggers an assert in the debug
1762 build. a is a value from zero to 255.
1763 a set to zero makes Color fully transparent; a set to 255 makes Color
1764 fully opaque.
1765
Cary Clarkce101242017-09-01 15:51:02 -04001766 #Param a Alpha component of Color ##
Cary Clark8032b982017-07-28 11:04:54 -04001767
1768 #Example
1769 SkPaint paint;
1770 paint.setColor(0x00112233);
1771 paint.setAlpha(0x44);
1772 SkDebugf("0x44112233 %c= paint.getColor()\n", 0x44112233 == paint.getColor() ? '=' : '!');
1773
1774 #StdOut
1775 0x44112233 == paint.getColor()
1776 ##
1777 ##
1778
1779##
1780
Cary Clark08895c42018-02-01 09:37:32 -05001781#Subtopic Alpha_Methods ##
Cary Clark8032b982017-07-28 11:04:54 -04001782
1783#Method void setARGB(U8CPU a, U8CPU r, U8CPU g, U8CPU b)
1784
Cary Clarkab2621d2018-01-30 10:08:57 -05001785#In Color_Methods
1786#Line # sets color by component ##
Cary Clark8032b982017-07-28 11:04:54 -04001787 Sets Color used when drawing solid fills. The color components range from 0 to 255.
Cary Clarkffb3d682018-05-17 12:17:28 -04001788 The color is Unpremultiplied; Alpha sets the transparency independent of RGB.
Cary Clark8032b982017-07-28 11:04:54 -04001789
1790 #Param a amount of Color_Alpha, from fully transparent (0) to fully opaque (255) ##
Cary Clarkffb3d682018-05-17 12:17:28 -04001791 #Param r amount of red, from no red (0) to full red (255) ##
1792 #Param g amount of green, from no green (0) to full green (255) ##
1793 #Param b amount of blue, from no blue (0) to full blue (255) ##
Herb Derbyfcac00f2018-05-01 11:57:56 -04001794
Cary Clark8032b982017-07-28 11:04:54 -04001795 #Example
1796 SkPaint transRed1, transRed2;
1797 transRed1.setARGB(255 / 2, 255, 0, 0);
1798 transRed2.setColor(SkColorSetARGB(255 / 2, 255, 0, 0));
1799 SkDebugf("transRed1 %c= transRed2", transRed1 == transRed2 ? '=' : '!');
1800
1801 #StdOut
1802 transRed1 == transRed2
1803 ##
1804 ##
1805
1806 #SeeAlso setColor SkColorSetARGB
1807
1808##
1809
Cary Clark8032b982017-07-28 11:04:54 -04001810# ------------------------------------------------------------------------------
Cary Clark08895c42018-02-01 09:37:32 -05001811#Subtopic Style
1812#Line # geometry filling, stroking ##
Cary Clark8032b982017-07-28 11:04:54 -04001813
1814Style specifies if the geometry is filled, stroked, or both filled and stroked.
1815Some shapes ignore Style and are always drawn filled or stroked.
1816
1817Set Style to kFill_Style to fill the shape.
1818The fill covers the area inside the geometry for most shapes.
1819
1820Set Style to kStroke_Style to stroke the shape.
1821
1822# ------------------------------------------------------------------------------
1823#Subtopic Fill
Cary Clark08895c42018-02-01 09:37:32 -05001824#Line # fill and stroke ##
Cary Clark8032b982017-07-28 11:04:54 -04001825#ToDo write up whatever generalities make sense to describe filling ##
1826
1827#SeeAlso Path_Fill_Type
Cary Clark08895c42018-02-01 09:37:32 -05001828#Subtopic Fill ##
Cary Clark8032b982017-07-28 11:04:54 -04001829
1830#Subtopic Stroke
Cary Clark08895c42018-02-01 09:37:32 -05001831#Line # lines and curves with width ##
Cary Clarkbc5697d2017-10-04 14:31:33 -04001832The stroke covers the area described by following the shape edge with a pen or brush of
Cary Clark8032b982017-07-28 11:04:54 -04001833Stroke_Width. The area covered where the shape starts and stops is described by Stroke_Cap.
1834The area covered where the shape turns a corner is described by Stroke_Join.
Cary Clarkbc5697d2017-10-04 14:31:33 -04001835The stroke is centered on the shape; it extends equally on either side of the shape edge.
Cary Clark8032b982017-07-28 11:04:54 -04001836
1837As Stroke_Width gets smaller, the drawn path frame is thinner. Stroke_Width less than one
1838may have gaps, and if kAntiAlias_Flag is set, Color_Alpha will increase to visually decrease coverage.
Cary Clark08895c42018-02-01 09:37:32 -05001839#Subtopic Stroke ##
Cary Clark8032b982017-07-28 11:04:54 -04001840
1841#Subtopic Hairline
Cary Clark08895c42018-02-01 09:37:32 -05001842#Line # lines and curves with minimal width ##
Cary Clark137b8742018-05-30 09:21:49 -04001843#Alias Hairline ## # maybe should be Stroke_Hairline ?
Cary Clark8032b982017-07-28 11:04:54 -04001844
1845Stroke_Width of zero has a special meaning and switches drawing to use Hairline.
Herb Derbyfcac00f2018-05-01 11:57:56 -04001846Hairline draws the thinnest continuous frame. If kAntiAlias_Flag is clear, adjacent pixels
1847flow horizontally, vertically,or diagonally.
Cary Clark8032b982017-07-28 11:04:54 -04001848
Cary Clarkffb3d682018-05-17 12:17:28 -04001849#ToDo what is the description of Anti_Aliased hairlines? ##
Cary Clark8032b982017-07-28 11:04:54 -04001850
1851Path drawing with Hairline may hit the same pixel more than once. For instance, Path containing
1852two lines in one Path_Contour will draw the corner point once, but may both lines may draw the adjacent
1853pixel. If kAntiAlias_Flag is set, transparency is applied twice, resulting in a darker pixel. Some
1854GPU-backed implementations apply transparency at a later drawing stage, avoiding double hit pixels
1855while stroking.
1856
Cary Clark08895c42018-02-01 09:37:32 -05001857#Subtopic Hairline ##
Cary Clark8032b982017-07-28 11:04:54 -04001858
1859#Enum Style
Cary Clark08895c42018-02-01 09:37:32 -05001860#Line # stroke, fill, or both ##
Cary Clark8032b982017-07-28 11:04:54 -04001861
1862#Code
1863 enum Style {
1864 kFill_Style,
1865 kStroke_Style,
1866 kStrokeAndFill_Style,
1867 };
Cary Clarkd98f78c2018-04-26 08:32:37 -04001868
1869 static constexpr int kStyleCount = kStrokeAndFill_Style + 1;
Cary Clark8032b982017-07-28 11:04:54 -04001870##
1871
1872Set Style to fill, stroke, or both fill and stroke geometry.
1873The stroke and fill
1874share all paint attributes; for instance, they are drawn with the same color.
1875
1876Use kStrokeAndFill_Style to avoid hitting the same pixels twice with a stroke draw and
1877a fill draw.
1878
1879#Const kFill_Style 0
Cary Clark682c58d2018-05-16 07:07:07 -04001880#Line # set to fill geometry ##
Herb Derbyfcac00f2018-05-01 11:57:56 -04001881 Applies to Rect, Region, Round_Rect, Circles, Ovals, Path, and Text.
Cary Clarkce101242017-09-01 15:51:02 -04001882 Bitmap, Image, Patches, Region, Sprites, and Vertices are painted as if
Cary Clark8032b982017-07-28 11:04:54 -04001883 kFill_Style is set, and ignore the set Style.
1884 The Path_Fill_Type specifies additional rules to fill the area outside the path edge,
1885 and to create an unfilled hole inside the shape.
1886 Style is set to kFill_Style by default.
1887##
1888
1889#Const kStroke_Style 1
Cary Clark682c58d2018-05-16 07:07:07 -04001890#Line # set to stroke geometry ##
Herb Derbyfcac00f2018-05-01 11:57:56 -04001891 Applies to Rect, Region, Round_Rect, Arcs, Circles, Ovals, Path, and Text.
Cary Clark56356312018-02-08 14:45:18 -05001892 Arcs, Lines, and points, are always drawn as if kStroke_Style is set,
Cary Clark8032b982017-07-28 11:04:54 -04001893 and ignore the set Style.
1894 The stroke construction is unaffected by the Path_Fill_Type.
1895##
1896
1897#Const kStrokeAndFill_Style 2
Cary Clark682c58d2018-05-16 07:07:07 -04001898#Line # sets to stroke and fill geometry ##
Cary Clarkce101242017-09-01 15:51:02 -04001899 Applies to Rect, Region, Round_Rect, Circles, Ovals, Path, and Text.
Cary Clark8032b982017-07-28 11:04:54 -04001900 Path is treated as if it is set to SkPath::kWinding_FillType,
Herb Derbyfcac00f2018-05-01 11:57:56 -04001901 and the set Path_Fill_Type is ignored.
Cary Clark8032b982017-07-28 11:04:54 -04001902##
1903
Cary Clark8032b982017-07-28 11:04:54 -04001904#Const kStyleCount 3
Cary Clark682c58d2018-05-16 07:07:07 -04001905#Line # number of different Style values defined ##
Cary Clark8032b982017-07-28 11:04:54 -04001906May be used to verify that Style is a legal value.
1907##
1908
Cary Clarkd98f78c2018-04-26 08:32:37 -04001909#Enum Style ##
Cary Clark8032b982017-07-28 11:04:54 -04001910
1911#Method Style getStyle() const
1912
Cary Clarkab2621d2018-01-30 10:08:57 -05001913#In Style
1914#Line # returns Style: stroke, fill, or both ##
Cary Clark8032b982017-07-28 11:04:54 -04001915 Whether the geometry is filled, stroked, or filled and stroked.
1916
1917 #Return one of:kFill_Style, kStroke_Style, kStrokeAndFill_Style ##
1918
1919 #Example
1920 SkPaint paint;
1921 SkDebugf("SkPaint::kFill_Style %c= paint.getStyle()\n",
1922 SkPaint::kFill_Style == paint.getStyle() ? '=' : '!');
1923
1924 #StdOut
1925 SkPaint::kFill_Style == paint.getStyle()
1926 ##
1927 ##
1928
1929#SeeAlso Style setStyle
1930##
1931
1932#Method void setStyle(Style style)
1933
Cary Clarkab2621d2018-01-30 10:08:57 -05001934#In Style
1935#Line # sets Style: stroke, fill, or both ##
Cary Clark8032b982017-07-28 11:04:54 -04001936 Sets whether the geometry is filled, stroked, or filled and stroked.
1937 Has no effect if style is not a legal Style value.
1938
1939 #Param style one of: kFill_Style, kStroke_Style, kStrokeAndFill_Style
1940 ##
1941
1942 #Example
1943 void draw(SkCanvas* canvas) {
1944 SkPaint paint;
1945 paint.setStrokeWidth(5);
1946 SkRegion region;
1947 region.op(140, 10, 160, 30, SkRegion::kUnion_Op);
1948 region.op(170, 40, 190, 60, SkRegion::kUnion_Op);
1949 SkBitmap bitmap;
1950 bitmap.setInfo(SkImageInfo::MakeA8(50, 50), 50);
1951 uint8_t pixels[50][50];
1952 for (int x = 0; x < 50; ++x) {
1953 for (int y = 0; y < 50; ++y) {
1954 pixels[y][x] = (x + y) % 5 ? 0xFF : 0x00;
1955 }
1956 }
1957 bitmap.setPixels(pixels);
1958 for (auto style : { SkPaint::kFill_Style,
1959 SkPaint::kStroke_Style,
1960 SkPaint::kStrokeAndFill_Style }) {
1961 paint.setStyle(style);
1962 canvas->drawLine(10, 10, 60, 60, paint);
1963 canvas->drawRect({80, 10, 130, 60}, paint);
1964 canvas->drawRegion(region, paint);
1965 canvas->drawBitmap(bitmap, 200, 10, &paint);
1966 canvas->translate(0, 80);
1967 }
1968 }
1969 ##
1970
1971#SeeAlso Style getStyle
1972##
1973
1974#SeeAlso Path_Fill_Type Path_Effect Style_Fill Style_Stroke
Cary Clark08895c42018-02-01 09:37:32 -05001975#Subtopic Style ##
Cary Clark8032b982017-07-28 11:04:54 -04001976
1977# ------------------------------------------------------------------------------
Cary Clark08895c42018-02-01 09:37:32 -05001978#Subtopic Stroke_Width
1979#Line # thickness perpendicular to geometry ##
Cary Clark8032b982017-07-28 11:04:54 -04001980
1981Stroke_Width sets the width for stroking. The width is the thickness
Herb Derbyfcac00f2018-05-01 11:57:56 -04001982of the stroke perpendicular to the path direction when the paint style is
Cary Clark8032b982017-07-28 11:04:54 -04001983set to kStroke_Style or kStrokeAndFill_Style.
1984
1985When width is greater than zero, the stroke encompasses as many pixels partially
1986or fully as needed. When the width equals zero, the paint enables hairlines;
Herb Derbyfcac00f2018-05-01 11:57:56 -04001987the stroke is always one pixel wide.
Cary Clark8032b982017-07-28 11:04:54 -04001988
Cary Clarkbc5697d2017-10-04 14:31:33 -04001989The stroke dimensions are scaled by the canvas matrix, but Hairline stroke
Cary Clark8032b982017-07-28 11:04:54 -04001990remains one pixel wide regardless of scaling.
1991
1992The default width for the paint is zero.
1993
1994#Example
1995#Height 170
1996 #Platform raster gpu
1997 #Description
Herb Derbyfcac00f2018-05-01 11:57:56 -04001998 The pixels hit to represent thin lines vary with the angle of the
Cary Clarkbc5697d2017-10-04 14:31:33 -04001999 line and the platform implementation.
Cary Clark8032b982017-07-28 11:04:54 -04002000 ##
2001 void draw(SkCanvas* canvas) {
2002 SkPaint paint;
Herb Derbyfcac00f2018-05-01 11:57:56 -04002003 for (bool antialias : { false, true }) {
Cary Clark8032b982017-07-28 11:04:54 -04002004 paint.setAntiAlias(antialias);
2005 for (int width = 0; width <= 4; ++width) {
2006 SkScalar offset = antialias * 100 + width * 20;
2007 paint.setStrokeWidth(width * 0.25f);
2008 canvas->drawLine(10 + offset, 10, 20 + offset, 60, paint);
2009 canvas->drawLine(10 + offset, 110, 60 + offset, 160, paint);
2010 }
2011 }
2012 }
2013##
2014
2015#Method SkScalar getStrokeWidth() const
2016
Cary Clarkab2621d2018-01-30 10:08:57 -05002017#In Stroke_Width
2018#Line # returns thickness of the stroke ##
Cary Clark8032b982017-07-28 11:04:54 -04002019 Returns the thickness of the pen used by Paint to
2020 outline the shape.
2021
2022 #Return zero for Hairline, greater than zero for pen thickness ##
Herb Derbyfcac00f2018-05-01 11:57:56 -04002023
Cary Clark8032b982017-07-28 11:04:54 -04002024 #Example
2025 SkPaint paint;
2026 SkDebugf("0 %c= paint.getStrokeWidth()\n", 0 == paint.getStrokeWidth() ? '=' : '!');
2027
2028 #StdOut
2029 0 == paint.getStrokeWidth()
2030 ##
2031 ##
2032
2033##
2034
2035#Method void setStrokeWidth(SkScalar width)
2036
Cary Clarkab2621d2018-01-30 10:08:57 -05002037#In Stroke_Width
2038#Line # sets thickness of the stroke ##
Cary Clark8032b982017-07-28 11:04:54 -04002039 Sets the thickness of the pen used by the paint to
Herb Derbyfcac00f2018-05-01 11:57:56 -04002040 outline the shape.
2041 Has no effect if width is less than zero.
Cary Clark8032b982017-07-28 11:04:54 -04002042
Herb Derbyfcac00f2018-05-01 11:57:56 -04002043 #Param width zero thickness for Hairline; greater than zero for pen thickness
Cary Clark8032b982017-07-28 11:04:54 -04002044 ##
2045
2046 #Example
2047 SkPaint paint;
2048 paint.setStrokeWidth(5);
2049 paint.setStrokeWidth(-1);
2050 SkDebugf("5 %c= paint.getStrokeWidth()\n", 5 == paint.getStrokeWidth() ? '=' : '!');
2051
2052 #StdOut
2053 5 == paint.getStrokeWidth()
2054 ##
2055 ##
2056
2057##
2058
Cary Clark08895c42018-02-01 09:37:32 -05002059#Subtopic Stroke_Width ##
Cary Clark8032b982017-07-28 11:04:54 -04002060# ------------------------------------------------------------------------------
Cary Clark08895c42018-02-01 09:37:32 -05002061#Subtopic Miter_Limit
2062#Line # maximum length of stroked corners ##
Cary Clark8032b982017-07-28 11:04:54 -04002063
2064Miter_Limit specifies the maximum miter length,
2065relative to the stroke width.
2066
2067Miter_Limit is used when the Stroke_Join
2068is set to kMiter_Join, and the Style is either kStroke_Style
2069or kStrokeAndFill_Style.
2070
2071If the miter at a corner exceeds this limit, kMiter_Join
2072is replaced with kBevel_Join.
2073
2074Miter_Limit can be computed from the corner angle:
2075
2076#Formula
2077 miter limit = 1 / sin ( angle / 2 )
2078#Formula ##
2079
2080Miter_Limit default value is 4.
2081The default may be changed at compile time by setting SkPaintDefaults_MiterLimit
Cary Clarkce101242017-09-01 15:51:02 -04002082in "SkUserConfig.h" or as a define supplied by the build environment.
Cary Clark8032b982017-07-28 11:04:54 -04002083
2084Here are some miter limits and the angles that triggers them.
2085#Table
2086#Legend
2087 # miter limit # angle in degrees ##
2088#Legend ##
2089 # 10 # 11.48 ##
2090 # 9 # 12.76 ##
2091 # 8 # 14.36 ##
2092 # 7 # 16.43 ##
2093 # 6 # 19.19 ##
2094 # 5 # 23.07 ##
2095 # 4 # 28.96 ##
2096 # 3 # 38.94 ##
2097 # 2 # 60 ##
2098 # 1 # 180 ##
2099#Table ##
2100
2101#Example
2102 #Height 170
2103 #Width 384
2104 #Description
2105 This example draws a stroked corner and the miter length beneath.
2106 When the miter limit is decreased slightly, the miter join is replaced
2107 by a bevel join.
2108 ##
2109 void draw(SkCanvas* canvas) {
2110 SkPoint pts[] = {{ 10, 50 }, { 110, 80 }, { 10, 110 }};
2111 SkVector v[] = { pts[0] - pts[1], pts[2] - pts[1] };
2112 SkScalar angle1 = SkScalarATan2(v[0].fY, v[0].fX);
2113 SkScalar angle2 = SkScalarATan2(v[1].fY, v[1].fX);
2114 const SkScalar strokeWidth = 20;
2115 SkScalar miterLimit = 1 / SkScalarSin((angle2 - angle1) / 2);
2116 SkScalar miterLength = strokeWidth * miterLimit;
2117 SkPath path;
2118 path.moveTo(pts[0]);
2119 path.lineTo(pts[1]);
2120 path.lineTo(pts[2]);
2121 SkPaint paint; // set to default kMiter_Join
2122 paint.setAntiAlias(true);
2123 paint.setStyle(SkPaint::kStroke_Style);
2124 paint.setStrokeMiter(miterLimit);
2125 paint.setStrokeWidth(strokeWidth);
2126 canvas->drawPath(path, paint);
2127 paint.setStrokeWidth(1);
2128 canvas->drawLine(pts[1].fX - miterLength / 2, pts[1].fY + 50,
2129 pts[1].fX + miterLength / 2, pts[1].fY + 50, paint);
2130 canvas->translate(200, 0);
2131 miterLimit *= 0.99f;
2132 paint.setStrokeMiter(miterLimit);
2133 paint.setStrokeWidth(strokeWidth);
2134 canvas->drawPath(path, paint);
2135 paint.setStrokeWidth(1);
2136 canvas->drawLine(pts[1].fX - miterLength / 2, pts[1].fY + 50,
2137 pts[1].fX + miterLength / 2, pts[1].fY + 50, paint);
2138 }
2139##
2140
2141#Method SkScalar getStrokeMiter() const
2142
Cary Clarkab2621d2018-01-30 10:08:57 -05002143#In Miter_Limit
2144#Line # returns Miter_Limit, angles with sharp corners ##
Cary Clark8032b982017-07-28 11:04:54 -04002145 The limit at which a sharp corner is drawn beveled.
2146
2147 #Return zero and greater Miter_Limit ##
2148
2149 #Example
2150 SkPaint paint;
2151 SkDebugf("default miter limit == %g\n", paint.getStrokeMiter());
2152
2153 #StdOut
2154 default miter limit == 4
2155 ##
2156 ##
2157
2158 #SeeAlso Miter_Limit setStrokeMiter Join
2159
2160##
2161
2162#Method void setStrokeMiter(SkScalar miter)
2163
Cary Clarkab2621d2018-01-30 10:08:57 -05002164#In Miter_Limit
2165#Line # sets Miter_Limit, angles with sharp corners ##
Cary Clark8032b982017-07-28 11:04:54 -04002166 The limit at which a sharp corner is drawn beveled.
2167 Valid values are zero and greater.
2168 Has no effect if miter is less than zero.
2169
2170 #Param miter zero and greater Miter_Limit
2171 ##
2172
2173 #Example
2174 SkPaint paint;
2175 paint.setStrokeMiter(8);
2176 paint.setStrokeMiter(-1);
2177 SkDebugf("default miter limit == %g\n", paint.getStrokeMiter());
2178
2179 #StdOut
2180 default miter limit == 8
2181 ##
2182 ##
2183
2184 #SeeAlso Miter_Limit getStrokeMiter Join
2185
2186##
2187
Cary Clark08895c42018-02-01 09:37:32 -05002188#Subtopic Miter_Limit ##
Cary Clark8032b982017-07-28 11:04:54 -04002189# ------------------------------------------------------------------------------
Cary Clark08895c42018-02-01 09:37:32 -05002190#Subtopic Stroke_Cap
2191#Line # decorations at ends of open strokes ##
Cary Clark8032b982017-07-28 11:04:54 -04002192
2193#Enum Cap
Cary Clark08895c42018-02-01 09:37:32 -05002194#Line # start and end geometry on stroked shapes ##
Cary Clark8032b982017-07-28 11:04:54 -04002195
2196#Code
2197 enum Cap {
2198 kButt_Cap,
2199 kRound_Cap,
2200 kSquare_Cap,
2201
2202 kLast_Cap = kSquare_Cap,
Cary Clarkbad5ad72017-08-03 17:14:08 -04002203 kDefault_Cap = kButt_Cap,
Cary Clark8032b982017-07-28 11:04:54 -04002204 };
Cary Clark6fc50412017-09-21 12:31:06 -04002205
Cary Clark8032b982017-07-28 11:04:54 -04002206 static constexpr int kCapCount = kLast_Cap + 1;
2207##
2208
2209Stroke_Cap draws at the beginning and end of an open Path_Contour.
2210
2211 #Const kButt_Cap 0
Cary Clark682c58d2018-05-16 07:07:07 -04002212 #Line # no stroke extension ##
Cary Clark8032b982017-07-28 11:04:54 -04002213 Does not extend the stroke past the beginning or the end.
2214 ##
2215 #Const kRound_Cap 1
Cary Clark682c58d2018-05-16 07:07:07 -04002216 #Line # adds circle ##
Cary Clark8032b982017-07-28 11:04:54 -04002217 Adds a circle with a diameter equal to Stroke_Width at the beginning
2218 and end.
2219 ##
2220 #Const kSquare_Cap 2
Cary Clark682c58d2018-05-16 07:07:07 -04002221 #Line # adds square ##
Cary Clark8032b982017-07-28 11:04:54 -04002222 Adds a square with sides equal to Stroke_Width at the beginning
2223 and end. The square sides are parallel to the initial and final direction
2224 of the stroke.
2225 ##
2226 #Const kLast_Cap 2
Cary Clark682c58d2018-05-16 07:07:07 -04002227 #Line # largest Stroke_Cap value ##
Cary Clark8032b982017-07-28 11:04:54 -04002228 Equivalent to the largest value for Stroke_Cap.
2229 ##
2230 #Const kDefault_Cap 0
Cary Clark682c58d2018-05-16 07:07:07 -04002231 #Line # equivalent to kButt_Cap ##
Cary Clark8032b982017-07-28 11:04:54 -04002232 Stroke_Cap is set to kButt_Cap by default.
2233 ##
2234
2235 #Const kCapCount 3
Cary Clark682c58d2018-05-16 07:07:07 -04002236 #Line # number of different Stroke_Cap values defined ##
Cary Clark8032b982017-07-28 11:04:54 -04002237 May be used to verify that Stroke_Cap is a legal value.
2238 ##
2239#Enum ##
2240
Herb Derbyfcac00f2018-05-01 11:57:56 -04002241Stroke describes the area covered by a pen of Stroke_Width as it
Cary Clarkbc5697d2017-10-04 14:31:33 -04002242follows the Path_Contour, moving parallel to the contour direction.
Cary Clark8032b982017-07-28 11:04:54 -04002243
2244If the Path_Contour is not terminated by SkPath::kClose_Verb, the contour has a
2245visible beginning and end.
2246
2247Path_Contour may start and end at the same point; defining Zero_Length_Contour.
2248
2249kButt_Cap and Zero_Length_Contour is not drawn.
Herb Derbyfcac00f2018-05-01 11:57:56 -04002250kRound_Cap and Zero_Length_Contour draws a circle of diameter Stroke_Width
Cary Clark8032b982017-07-28 11:04:54 -04002251at the contour point.
2252kSquare_Cap and Zero_Length_Contour draws an upright square with a side of
2253Stroke_Width at the contour point.
2254
2255Stroke_Cap is kButt_Cap by default.
2256
2257#Example
Cary Clark2ade9972017-11-02 17:49:34 -04002258#Height 200
Cary Clark8032b982017-07-28 11:04:54 -04002259 SkPaint paint;
2260 paint.setStyle(SkPaint::kStroke_Style);
2261 paint.setStrokeWidth(20);
2262 SkPath path;
2263 path.moveTo(30, 30);
2264 path.lineTo(30, 30);
2265 path.moveTo(70, 30);
2266 path.lineTo(90, 40);
2267 for (SkPaint::Cap c : { SkPaint::kButt_Cap, SkPaint::kRound_Cap, SkPaint::kSquare_Cap } ) {
2268 paint.setStrokeCap(c);
2269 canvas->drawPath(path, paint);
2270 canvas->translate(0, 70);
2271 }
2272##
2273
2274#Method Cap getStrokeCap() const
2275
Cary Clarkab2621d2018-01-30 10:08:57 -05002276#In Stroke_Cap
2277#Line # returns Cap, the area drawn at path ends ##
Cary Clark8032b982017-07-28 11:04:54 -04002278 The geometry drawn at the beginning and end of strokes.
2279
2280 #Return one of: kButt_Cap, kRound_Cap, kSquare_Cap ##
2281
2282 #Example
2283 SkPaint paint;
2284 SkDebugf("kButt_Cap %c= default stroke cap\n",
2285 SkPaint::kButt_Cap == paint.getStrokeCap() ? '=' : '!');
2286
2287 #StdOut
2288 kButt_Cap == default stroke cap
2289 ##
2290 ##
2291
2292 #SeeAlso Stroke_Cap setStrokeCap
2293##
2294
2295#Method void setStrokeCap(Cap cap)
2296
Cary Clarkab2621d2018-01-30 10:08:57 -05002297#In Stroke_Cap
2298#Line # sets Cap, the area drawn at path ends ##
Cary Clark8032b982017-07-28 11:04:54 -04002299 The geometry drawn at the beginning and end of strokes.
2300
2301 #Param cap one of: kButt_Cap, kRound_Cap, kSquare_Cap;
2302 has no effect if cap is not valid
Herb Derbyfcac00f2018-05-01 11:57:56 -04002303 ##
Cary Clark8032b982017-07-28 11:04:54 -04002304
2305 #Example
2306 SkPaint paint;
2307 paint.setStrokeCap(SkPaint::kRound_Cap);
2308 paint.setStrokeCap((SkPaint::Cap) SkPaint::kCapCount);
2309 SkDebugf("kRound_Cap %c= paint.getStrokeCap()\n",
2310 SkPaint::kRound_Cap == paint.getStrokeCap() ? '=' : '!');
Herb Derbyfcac00f2018-05-01 11:57:56 -04002311
Cary Clark8032b982017-07-28 11:04:54 -04002312 #StdOut
2313 kRound_Cap == paint.getStrokeCap()
2314 ##
2315 ##
2316
2317 #SeeAlso Stroke_Cap getStrokeCap
2318##
2319
Cary Clark08895c42018-02-01 09:37:32 -05002320#Subtopic Stroke_Cap ##
Cary Clark8032b982017-07-28 11:04:54 -04002321# ------------------------------------------------------------------------------
Cary Clark08895c42018-02-01 09:37:32 -05002322#Subtopic Stroke_Join
2323#Line # decoration at corners of strokes ##
Cary Clark8032b982017-07-28 11:04:54 -04002324
2325Stroke_Join draws at the sharp corners of an open or closed Path_Contour.
2326
Herb Derbyfcac00f2018-05-01 11:57:56 -04002327Stroke describes the area covered by a pen of Stroke_Width as it
Cary Clarkbc5697d2017-10-04 14:31:33 -04002328follows the Path_Contour, moving parallel to the contour direction.
Cary Clark8032b982017-07-28 11:04:54 -04002329
2330If the contour direction changes abruptly, because the tangent direction leading
2331to the end of a curve within the contour does not match the tangent direction of
2332the following curve, the pair of curves meet at Stroke_Join.
2333
2334#Example
Cary Clark2ade9972017-11-02 17:49:34 -04002335#Height 200
Cary Clarka560c472017-11-27 10:44:06 -05002336 SkPaint paint;
2337 paint.setStyle(SkPaint::kStroke_Style);
2338 paint.setStrokeWidth(20);
2339 SkPath path;
2340 path.moveTo(30, 20);
2341 path.lineTo(40, 40);
2342 path.conicTo(70, 20, 100, 20, .707f);
2343 for (SkPaint::Join j : { SkPaint::kMiter_Join, SkPaint::kRound_Join, SkPaint::kBevel_Join } ) {
2344 paint.setStrokeJoin(j);
2345 canvas->drawPath(path, paint);
2346 canvas->translate(0, 70);
2347 }
Cary Clark8032b982017-07-28 11:04:54 -04002348##
2349
2350#Enum Join
Cary Clark08895c42018-02-01 09:37:32 -05002351#Line # corner geometry on stroked shapes ##
Cary Clark8032b982017-07-28 11:04:54 -04002352#Code
2353 enum Join {
2354 kMiter_Join,
2355 kRound_Join,
2356 kBevel_Join,
2357
2358 kLast_Join = kBevel_Join,
Cary Clarkbad5ad72017-08-03 17:14:08 -04002359 kDefault_Join = kMiter_Join,
Cary Clark8032b982017-07-28 11:04:54 -04002360 };
Cary Clark6fc50412017-09-21 12:31:06 -04002361
Cary Clark8032b982017-07-28 11:04:54 -04002362 static constexpr int kJoinCount = kLast_Join + 1;
2363##
2364
Cary Clark1eace2d2017-07-31 07:52:43 -04002365Join specifies how corners are drawn when a shape is stroked. Join
Cary Clark8032b982017-07-28 11:04:54 -04002366affects the four corners of a stroked rectangle, and the connected segments in a
2367stroked path.
2368
2369Choose miter join to draw sharp corners. Choose round join to draw a circle with a
2370radius equal to the stroke width on top of the corner. Choose bevel join to minimally
2371connect the thick strokes.
2372
Herb Derbyfcac00f2018-05-01 11:57:56 -04002373The fill path constructed to describe the stroked path respects the join setting but may
Cary Clark8032b982017-07-28 11:04:54 -04002374not contain the actual join. For instance, a fill path constructed with round joins does
2375not necessarily include circles at each connected segment.
2376
2377#Const kMiter_Join 0
Cary Clark682c58d2018-05-16 07:07:07 -04002378#Line # extends to Miter_Limit ##
Cary Clark8032b982017-07-28 11:04:54 -04002379 Extends the outside corner to the extent allowed by Miter_Limit.
2380 If the extension exceeds Miter_Limit, kBevel_Join is used instead.
2381##
2382
2383#Const kRound_Join 1
Cary Clark682c58d2018-05-16 07:07:07 -04002384#Line # adds circle ##
Cary Clark8032b982017-07-28 11:04:54 -04002385 Adds a circle with a diameter of Stroke_Width at the sharp corner.
2386##
2387
2388#Const kBevel_Join 2
Cary Clark682c58d2018-05-16 07:07:07 -04002389#Line # connects outside edges ##
Cary Clark8032b982017-07-28 11:04:54 -04002390 Connects the outside edges of the sharp corner.
2391##
2392
2393#Const kLast_Join 2
Cary Clark682c58d2018-05-16 07:07:07 -04002394#Line # equivalent to the largest value for Stroke_Join ##
Cary Clark8032b982017-07-28 11:04:54 -04002395##
2396
2397#Const kDefault_Join 1
Cary Clark682c58d2018-05-16 07:07:07 -04002398#Line # equivalent to kMiter_Join ##
Herb Derbyfcac00f2018-05-01 11:57:56 -04002399 Stroke_Join is set to kMiter_Join by default.
Cary Clark8032b982017-07-28 11:04:54 -04002400##
2401
2402#Const kJoinCount 3
Cary Clark682c58d2018-05-16 07:07:07 -04002403#Line # number of different Stroke_Join values defined ##
Cary Clark8032b982017-07-28 11:04:54 -04002404 May be used to verify that Stroke_Join is a legal value.
2405##
2406
2407#Example
2408#Width 462
2409void draw(SkCanvas* canvas) {
2410 SkPath path;
2411 path.moveTo(10, 50);
2412 path.quadTo(35, 110, 60, 210);
2413 path.quadTo(105, 110, 130, 10);
2414 SkPaint paint; // set to default kMiter_Join
2415 paint.setAntiAlias(true);
2416 paint.setStyle(SkPaint::kStroke_Style);
2417 paint.setStrokeWidth(20);
2418 canvas->drawPath(path, paint);
2419 canvas->translate(150, 0);
2420 paint.setStrokeJoin(SkPaint::kBevel_Join);
2421 canvas->drawPath(path, paint);
2422 canvas->translate(150, 0);
2423 paint.setStrokeJoin(SkPaint::kRound_Join);
2424 canvas->drawPath(path, paint);
2425}
2426##
2427
2428#SeeAlso setStrokeJoin getStrokeJoin setStrokeMiter getStrokeMiter
2429
2430#Enum ##
2431
2432#Method Join getStrokeJoin() const
2433
Cary Clarkab2621d2018-01-30 10:08:57 -05002434#In Stroke_Join
2435#Line # returns Join, geometry on path corners ##
Cary Clark0c5f5462017-12-15 11:21:51 -05002436 The geometry drawn at the corners of strokes.
Cary Clark8032b982017-07-28 11:04:54 -04002437
2438 #Return one of: kMiter_Join, kRound_Join, kBevel_Join ##
2439
2440 #Example
2441 SkPaint paint;
2442 SkDebugf("kMiter_Join %c= default stroke join\n",
2443 SkPaint::kMiter_Join == paint.getStrokeJoin() ? '=' : '!');
2444
2445 #StdOut
2446 kMiter_Join == default stroke join
2447 ##
2448 ##
2449
2450 #SeeAlso Stroke_Join setStrokeJoin
2451##
2452
2453#Method void setStrokeJoin(Join join)
2454
Cary Clarkab2621d2018-01-30 10:08:57 -05002455#In Stroke_Join
2456#Line # sets Join, geometry on path corners ##
Cary Clark0c5f5462017-12-15 11:21:51 -05002457 The geometry drawn at the corners of strokes.
Cary Clark8032b982017-07-28 11:04:54 -04002458
2459 #Param join one of: kMiter_Join, kRound_Join, kBevel_Join;
Herb Derbyfcac00f2018-05-01 11:57:56 -04002460 otherwise, has no effect
Cary Clark8032b982017-07-28 11:04:54 -04002461 ##
2462
2463 #Example
2464 SkPaint paint;
2465 paint.setStrokeJoin(SkPaint::kMiter_Join);
2466 paint.setStrokeJoin((SkPaint::Join) SkPaint::kJoinCount);
2467 SkDebugf("kMiter_Join %c= paint.getStrokeJoin()\n",
2468 SkPaint::kMiter_Join == paint.getStrokeJoin() ? '=' : '!');
2469
2470 #StdOut
2471 kMiter_Join == paint.getStrokeJoin()
2472 ##
2473 ##
2474
2475 #SeeAlso Stroke_Join getStrokeJoin
2476##
2477
2478#SeeAlso Miter_Limit
2479
Cary Clark08895c42018-02-01 09:37:32 -05002480#Subtopic Stroke_Join ##
Cary Clark8032b982017-07-28 11:04:54 -04002481# ------------------------------------------------------------------------------
Cary Clark08895c42018-02-01 09:37:32 -05002482#Subtopic Fill_Path
2483#Line # make Path from Path_Effect, stroking ##
Cary Clark8032b982017-07-28 11:04:54 -04002484
2485Fill_Path creates a Path by applying the Path_Effect, followed by the Style_Stroke.
2486
2487If Paint contains Path_Effect, Path_Effect operates on the source Path; the result
2488replaces the destination Path. Otherwise, the source Path is replaces the
2489destination Path.
2490
2491Fill Path can request the Path_Effect to restrict to a culling rectangle, but
2492the Path_Effect is not required to do so.
2493
Herb Derbyfcac00f2018-05-01 11:57:56 -04002494If Style is kStroke_Style or kStrokeAndFill_Style,
Cary Clark8032b982017-07-28 11:04:54 -04002495and Stroke_Width is greater than zero, the Stroke_Width, Stroke_Cap, Stroke_Join,
2496and Miter_Limit operate on the destination Path, replacing it.
2497
Herb Derbyfcac00f2018-05-01 11:57:56 -04002498Fill Path can specify the precision used by Stroke_Width to approximate the stroke geometry.
Cary Clark8032b982017-07-28 11:04:54 -04002499
2500If the Style is kStroke_Style and the Stroke_Width is zero, getFillPath
2501returns false since Hairline has no filled equivalent.
2502
2503#Method bool getFillPath(const SkPath& src, SkPath* dst, const SkRect* cullRect,
2504 SkScalar resScale = 1) const
Cary Clarkab2621d2018-01-30 10:08:57 -05002505#In Fill_Path
2506#Line # returns fill path equivalent to stroke ##
Cary Clark8032b982017-07-28 11:04:54 -04002507
2508 The filled equivalent of the stroked path.
2509
2510 #Param src Path read to create a filled version ##
2511 #Param dst resulting Path; may be the same as src, but may not be nullptr ##
2512 #Param cullRect optional limit passed to Path_Effect ##
2513 #Param resScale if > 1, increase precision, else if (0 < res < 1) reduce precision
2514 to favor speed and size
2515 ##
2516 #Return true if the path represents Style_Fill, or false if it represents Hairline ##
2517
2518 #Example
2519 #Height 192
2520 #Description
Cary Clarkce101242017-09-01 15:51:02 -04002521 A very small Quad stroke is turned into a filled path with increasing levels of precision.
Herb Derbyfcac00f2018-05-01 11:57:56 -04002522 At the lowest precision, the Quad stroke is approximated by a rectangle.
Cary Clark8032b982017-07-28 11:04:54 -04002523 At the highest precision, the filled path has high fidelity compared to the original stroke.
2524 ##
2525 void draw(SkCanvas* canvas) {
2526 SkPaint strokePaint;
2527 strokePaint.setAntiAlias(true);
2528 strokePaint.setStyle(SkPaint::kStroke_Style);
2529 strokePaint.setStrokeWidth(.1f);
2530 SkPath strokePath;
2531 strokePath.moveTo(.08f, .08f);
2532 strokePath.quadTo(.09f, .08f, .17f, .17f);
2533 SkPath fillPath;
2534 SkPaint outlinePaint(strokePaint);
2535 outlinePaint.setStrokeWidth(2);
2536 SkMatrix scale = SkMatrix::MakeScale(300, 300);
2537 for (SkScalar precision : { 0.01f, .1f, 1.f, 10.f, 100.f } ) {
2538 strokePaint.getFillPath(strokePath, &fillPath, nullptr, precision);
2539 fillPath.transform(scale);
2540 canvas->drawPath(fillPath, outlinePaint);
2541 canvas->translate(60, 0);
2542 if (1.f == precision) canvas->translate(-180, 100);
2543 }
2544 strokePath.transform(scale);
2545 strokePaint.setStrokeWidth(30);
2546 canvas->drawPath(strokePath, strokePaint);
2547 }
2548 ##
2549
2550##
2551
2552#Method bool getFillPath(const SkPath& src, SkPath* dst) const
2553
Cary Clarkab2621d2018-01-30 10:08:57 -05002554#In Fill_Path
Cary Clark8032b982017-07-28 11:04:54 -04002555 The filled equivalent of the stroked path.
2556
2557 Replaces dst with the src path modified by Path_Effect and Style_Stroke.
2558 Path_Effect, if any, is not culled. Stroke_Width is created with default precision.
2559
2560 #Param src Path read to create a filled version ##
2561 #Param dst resulting Path dst may be the same as src, but may not be nullptr ##
2562 #Return true if the path represents Style_Fill, or false if it represents Hairline ##
2563
2564 #Example
2565 #Height 128
2566 void draw(SkCanvas* canvas) {
2567 SkPaint paint;
2568 paint.setStyle(SkPaint::kStroke_Style);
2569 paint.setStrokeWidth(10);
2570 SkPath strokePath;
2571 strokePath.moveTo(20, 20);
2572 strokePath.lineTo(100, 100);
2573 canvas->drawPath(strokePath, paint);
2574 SkPath fillPath;
2575 paint.getFillPath(strokePath, &fillPath);
2576 paint.setStrokeWidth(2);
2577 canvas->translate(40, 0);
2578 canvas->drawPath(fillPath, paint);
2579 }
2580 ##
2581
2582##
2583
2584#SeeAlso Style_Stroke Stroke_Width Path_Effect
2585
Cary Clark08895c42018-02-01 09:37:32 -05002586#Subtopic Fill_Path ##
Cary Clark8032b982017-07-28 11:04:54 -04002587# ------------------------------------------------------------------------------
Cary Clark08895c42018-02-01 09:37:32 -05002588#Subtopic Shader_Methods
2589#Line # get and set Shader ##
Cary Clark8032b982017-07-28 11:04:54 -04002590
2591Shader defines the colors used when drawing a shape.
2592Shader may be an image, a gradient, or a computed fill.
Herb Derbyfcac00f2018-05-01 11:57:56 -04002593If Paint has no Shader, then Color fills the shape.
Cary Clark8032b982017-07-28 11:04:54 -04002594
2595Shader is modulated by Color_Alpha component of Color.
2596If Shader object defines only Color_Alpha, then Color modulated by Color_Alpha describes
2597the fill.
2598
2599The drawn transparency can be modified without altering Shader, by changing Color_Alpha.
2600
2601#Example
2602void draw(SkCanvas* canvas) {
2603 SkPaint paint;
2604 SkPoint center = { 50, 50 };
2605 SkScalar radius = 50;
2606 const SkColor colors[] = { 0xFFFFFFFF, 0xFF000000 };
2607 paint.setShader(SkGradientShader::MakeRadial(center, radius, colors,
2608 nullptr, SK_ARRAY_COUNT(colors), SkShader::kClamp_TileMode));
2609 for (SkScalar a : { 0.3f, 0.6f, 1.0f } ) {
2610 paint.setAlpha((int) (a * 255));
2611 canvas->drawCircle(center.fX, center.fY, radius, paint);
2612 canvas->translate(70, 70);
2613 }
2614}
2615##
2616
2617If Shader generates only Color_Alpha then all components of Color modulate the output.
2618
2619#Example
2620void draw(SkCanvas* canvas) {
2621 SkPaint paint;
2622 SkBitmap bitmap;
2623 bitmap.setInfo(SkImageInfo::MakeA8(5, 1), 5); // bitmap only contains alpha
2624 uint8_t pixels[5] = { 0x22, 0x55, 0x88, 0xBB, 0xFF };
2625 bitmap.setPixels(pixels);
Herb Derbyfcac00f2018-05-01 11:57:56 -04002626 paint.setShader(SkShader::MakeBitmapShader(bitmap,
Cary Clark8032b982017-07-28 11:04:54 -04002627 SkShader::kMirror_TileMode, SkShader::kMirror_TileMode));
2628 for (SkColor c : { SK_ColorRED, SK_ColorBLUE, SK_ColorGREEN } ) {
2629 paint.setColor(c); // all components in color affect shader
2630 canvas->drawCircle(50, 50, 50, paint);
2631 canvas->translate(70, 70);
2632 }
2633}
2634##
2635
2636#Method SkShader* getShader() const
2637
Cary Clarkab2621d2018-01-30 10:08:57 -05002638#In Shader_Methods
2639#Line # returns Shader, multiple drawing colors; gradients ##
Cary Clark8032b982017-07-28 11:04:54 -04002640 Optional colors used when filling a path, such as a gradient.
2641
2642 Does not alter Shader Reference_Count.
Herb Derbyfcac00f2018-05-01 11:57:56 -04002643
Cary Clark8032b982017-07-28 11:04:54 -04002644 #Return Shader if previously set, nullptr otherwise ##
2645
2646 #Example
2647 void draw(SkCanvas* canvas) {
2648 SkPaint paint;
2649 SkDebugf("nullptr %c= shader\n", paint.getShader() ? '!' : '=');
2650 paint.setShader(SkShader::MakeEmptyShader());
2651 SkDebugf("nullptr %c= shader\n", paint.getShader() ? '!' : '=');
2652 }
2653
2654 #StdOut
2655 nullptr == shader
2656 nullptr != shader
2657 ##
2658 ##
2659
2660##
2661
2662#Method sk_sp<SkShader> refShader() const
2663
Cary Clarkab2621d2018-01-30 10:08:57 -05002664#In Shader_Methods
2665#Line # references Shader, multiple drawing colors; gradients ##
Cary Clark8032b982017-07-28 11:04:54 -04002666 Optional colors used when filling a path, such as a gradient.
2667
2668 Increases Shader Reference_Count by one.
2669
2670 #Return Shader if previously set, nullptr otherwise ##
2671
2672 #Example
2673 void draw(SkCanvas* canvas) {
2674 SkPaint paint1, paint2;
2675 paint1.setShader(SkShader::MakeEmptyShader());
2676 SkDebugf("shader unique: %s\n", paint1.getShader()->unique() ? "true" : "false");
2677 paint2.setShader(paint1.refShader());
2678 SkDebugf("shader unique: %s\n", paint1.getShader()->unique() ? "true" : "false");
2679 }
2680
2681 #StdOut
2682 shader unique: true
2683 shader unique: false
2684 ##
2685 ##
2686
2687##
2688
2689#Method void setShader(sk_sp<SkShader> shader)
2690
Cary Clarkab2621d2018-01-30 10:08:57 -05002691#In Shader_Methods
2692#Line # sets Shader, multiple drawing colors; gradients ##
Cary Clark8032b982017-07-28 11:04:54 -04002693 Optional colors used when filling a path, such as a gradient.
2694
Cary Clarkd0530ba2017-09-14 11:25:39 -04002695 Sets Shader to shader, decreasing Reference_Count of the previous Shader.
Cary Clark6fc50412017-09-21 12:31:06 -04002696 Increments shader Reference_Count by one.
Cary Clark8032b982017-07-28 11:04:54 -04002697
2698 #Param shader how geometry is filled with color; if nullptr, Color is used instead ##
2699
2700 #Example
2701 #Height 64
2702 void draw(SkCanvas* canvas) {
2703 SkPaint paint;
2704 paint.setColor(SK_ColorBLUE);
2705 paint.setShader(SkShader::MakeColorShader(SK_ColorRED));
2706 canvas->drawRect(SkRect::MakeWH(40, 40), paint);
2707 paint.setShader(nullptr);
2708 canvas->translate(50, 0);
2709 canvas->drawRect(SkRect::MakeWH(40, 40), paint);
2710 }
2711 ##
2712
2713##
2714
Cary Clark08895c42018-02-01 09:37:32 -05002715#Subtopic Shader_Methods ##
Cary Clark8032b982017-07-28 11:04:54 -04002716# ------------------------------------------------------------------------------
Cary Clark08895c42018-02-01 09:37:32 -05002717#Subtopic Color_Filter_Methods
2718#Line # get and set Color_Filter ##
Cary Clark8032b982017-07-28 11:04:54 -04002719
2720Color_Filter alters the color used when drawing a shape.
2721Color_Filter may apply Blend_Mode, transform the color through a matrix, or composite multiple filters.
2722If Paint has no Color_Filter, the color is unaltered.
2723
2724The drawn transparency can be modified without altering Color_Filter, by changing Color_Alpha.
2725
2726#Example
2727#Height 128
2728void draw(SkCanvas* canvas) {
2729 SkPaint paint;
2730 paint.setColorFilter(SkColorMatrixFilter::MakeLightingFilter(0xFFFFFF, 0xFF0000));
2731 for (SkColor c : { SK_ColorBLACK, SK_ColorGREEN } ) {
2732 paint.setColor(c);
2733 canvas->drawRect(SkRect::MakeXYWH(10, 10, 50, 50), paint);
2734 paint.setAlpha(0x80);
2735 canvas->drawRect(SkRect::MakeXYWH(60, 60, 50, 50), paint);
2736 canvas->translate(100, 0);
2737 }
2738}
2739##
2740
2741#Method SkColorFilter* getColorFilter() const
2742
Cary Clarkab2621d2018-01-30 10:08:57 -05002743#In Color_Filter_Methods
2744#Line # returns Color_Filter, how colors are altered ##
Cary Clark8032b982017-07-28 11:04:54 -04002745 Returns Color_Filter if set, or nullptr.
2746 Does not alter Color_Filter Reference_Count.
Herb Derbyfcac00f2018-05-01 11:57:56 -04002747
Cary Clark8032b982017-07-28 11:04:54 -04002748 #Return Color_Filter if previously set, nullptr otherwise ##
2749
2750 #Example
2751 void draw(SkCanvas* canvas) {
2752 SkPaint paint;
2753 SkDebugf("nullptr %c= color filter\n", paint.getColorFilter() ? '!' : '=');
2754 paint.setColorFilter(SkColorFilter::MakeModeFilter(SK_ColorLTGRAY, SkBlendMode::kSrcIn));
2755 SkDebugf("nullptr %c= color filter\n", paint.getColorFilter() ? '!' : '=');
2756 }
2757
2758 #StdOut
2759 nullptr == color filter
2760 nullptr != color filter
2761 ##
2762 ##
2763##
2764
2765#Method sk_sp<SkColorFilter> refColorFilter() const
2766
Cary Clarkab2621d2018-01-30 10:08:57 -05002767#In Color_Filter_Methods
2768#Line # references Color_Filter, how colors are altered ##
Cary Clark8032b982017-07-28 11:04:54 -04002769 Returns Color_Filter if set, or nullptr.
2770 Increases Color_Filter Reference_Count by one.
2771
2772 #Return Color_Filter if set, or nullptr ##
2773
2774 #Example
2775 void draw(SkCanvas* canvas) {
2776 SkPaint paint1, paint2;
2777 paint1.setColorFilter(SkColorFilter::MakeModeFilter(0xFFFF0000, SkBlendMode::kSrcATop));
2778 SkDebugf("color filter unique: %s\n", paint1.getColorFilter()->unique() ? "true" : "false");
2779 paint2.setColorFilter(paint1.refColorFilter());
2780 SkDebugf("color filter unique: %s\n", paint1.getColorFilter()->unique() ? "true" : "false");
2781 }
2782
2783 #StdOut
2784 color filter unique: true
2785 color filter unique: false
2786 ##
2787 ##
2788##
2789
2790#Method void setColorFilter(sk_sp<SkColorFilter> colorFilter)
2791
Cary Clarkab2621d2018-01-30 10:08:57 -05002792#In Color_Filter_Methods
2793#Line # sets Color_Filter, alters color ##
Cary Clark6fc50412017-09-21 12:31:06 -04002794Sets Color_Filter to filter, decreasing Reference_Count of the previous
2795Color_Filter. Pass nullptr to clear Color_Filter.
2796
2797Increments filter Reference_Count by one.
Cary Clark8032b982017-07-28 11:04:54 -04002798
2799 #Param colorFilter Color_Filter to apply to subsequent draw ##
2800
2801 #Example
2802 #Height 64
2803 void draw(SkCanvas* canvas) {
2804 SkPaint paint;
2805 paint.setColorFilter(SkColorFilter::MakeModeFilter(SK_ColorLTGRAY, SkBlendMode::kSrcIn));
2806 canvas->drawRect(SkRect::MakeWH(50, 50), paint);
2807 paint.setColorFilter(nullptr);
2808 canvas->translate(70, 0);
2809 canvas->drawRect(SkRect::MakeWH(50, 50), paint);
2810 }
2811 ##
2812
2813##
2814
Cary Clark08895c42018-02-01 09:37:32 -05002815#Subtopic Color_Filter_Methods ##
Cary Clark8032b982017-07-28 11:04:54 -04002816# ------------------------------------------------------------------------------
Cary Clark08895c42018-02-01 09:37:32 -05002817#Subtopic Blend_Mode_Methods
2818#Line # get and set Blend_Mode ##
Cary Clark8032b982017-07-28 11:04:54 -04002819
2820Blend_Mode describes how Color combines with the destination color.
2821The default setting, SkBlendMode::kSrcOver, draws the source color
2822over the destination color.
2823
2824#Example
2825void draw(SkCanvas* canvas) {
2826 SkPaint normal, blender;
2827 normal.setColor(0xFF58a889);
2828 blender.setColor(0xFF8958a8);
2829 canvas->clear(0);
2830 for (SkBlendMode m : { SkBlendMode::kSrcOver, SkBlendMode::kSrcIn, SkBlendMode::kSrcOut } ) {
2831 normal.setBlendMode(SkBlendMode::kSrcOver);
2832 canvas->drawOval(SkRect::MakeXYWH(30, 30, 30, 80), normal);
2833 blender.setBlendMode(m);
2834 canvas->drawOval(SkRect::MakeXYWH(10, 50, 80, 30), blender);
2835 canvas->translate(70, 70);
2836 }
2837}
2838##
2839
2840#SeeAlso Blend_Mode
2841
2842#Method SkBlendMode getBlendMode() const
2843
Cary Clarkab2621d2018-01-30 10:08:57 -05002844#In Blend_Mode_Methods
2845#Line # returns Blend_Mode, how colors combine with Device ##
Cary Clark8032b982017-07-28 11:04:54 -04002846 Returns Blend_Mode.
Cary Clark579985c2017-07-31 11:48:27 -04002847 By default, returns SkBlendMode::kSrcOver.
Cary Clark8032b982017-07-28 11:04:54 -04002848
2849 #Return mode used to combine source color with destination color ##
2850
2851 #Example
2852 void draw(SkCanvas* canvas) {
2853 SkPaint paint;
Herb Derbyfcac00f2018-05-01 11:57:56 -04002854 SkDebugf("kSrcOver %c= getBlendMode\n",
Cary Clark8032b982017-07-28 11:04:54 -04002855 SkBlendMode::kSrcOver == paint.getBlendMode() ? '=' : '!');
2856 paint.setBlendMode(SkBlendMode::kSrc);
Herb Derbyfcac00f2018-05-01 11:57:56 -04002857 SkDebugf("kSrcOver %c= getBlendMode\n",
Cary Clark8032b982017-07-28 11:04:54 -04002858 SkBlendMode::kSrcOver == paint.getBlendMode() ? '=' : '!');
2859 }
2860
2861 #StdOut
2862 kSrcOver == getBlendMode
2863 kSrcOver != getBlendMode
2864 ##
2865 ##
2866
2867##
2868
2869#Method bool isSrcOver() const
2870
Cary Clarkab2621d2018-01-30 10:08:57 -05002871#In Blend_Mode_Methods
2872#Line # returns true if Blend_Mode is SkBlendMode::kSrcOver ##
Cary Clark8032b982017-07-28 11:04:54 -04002873 Returns true if Blend_Mode is SkBlendMode::kSrcOver, the default.
2874
2875 #Return true if Blend_Mode is SkBlendMode::kSrcOver ##
2876
2877 #Example
2878 void draw(SkCanvas* canvas) {
2879 SkPaint paint;
2880 SkDebugf("isSrcOver %c= true\n", paint.isSrcOver() ? '=' : '!');
2881 paint.setBlendMode(SkBlendMode::kSrc);
2882 SkDebugf("isSrcOver %c= true\n", paint.isSrcOver() ? '=' : '!');
2883 }
2884
2885 #StdOut
2886 isSrcOver == true
2887 isSrcOver != true
2888 ##
2889 ##
2890
2891##
2892
2893#Method void setBlendMode(SkBlendMode mode)
2894
Cary Clarkab2621d2018-01-30 10:08:57 -05002895#In Blend_Mode_Methods
2896#Line # sets Blend_Mode, how colors combine with destination ##
Herb Derbyfcac00f2018-05-01 11:57:56 -04002897 Sets Blend_Mode to mode.
Cary Clark8032b982017-07-28 11:04:54 -04002898 Does not check for valid input.
2899
2900 #Param mode SkBlendMode used to combine source color and destination ##
2901
2902 #Example
2903 void draw(SkCanvas* canvas) {
2904 SkPaint paint;
2905 SkDebugf("isSrcOver %c= true\n", paint.isSrcOver() ? '=' : '!');
2906 paint.setBlendMode(SkBlendMode::kSrc);
2907 SkDebugf("isSrcOver %c= true\n", paint.isSrcOver() ? '=' : '!');
2908 }
2909
2910 #StdOut
2911 isSrcOver == true
2912 isSrcOver != true
2913 ##
2914 ##
2915
2916##
2917
Cary Clark08895c42018-02-01 09:37:32 -05002918#Subtopic Blend_Mode_Methods ##
Cary Clark8032b982017-07-28 11:04:54 -04002919# ------------------------------------------------------------------------------
Cary Clark08895c42018-02-01 09:37:32 -05002920#Subtopic Path_Effect_Methods
2921#Line # get and set Path_Effect ##
Cary Clark8032b982017-07-28 11:04:54 -04002922
2923Path_Effect modifies the path geometry before drawing it.
2924Path_Effect may implement dashing, custom fill effects and custom stroke effects.
2925If Paint has no Path_Effect, the path geometry is unaltered when filled or stroked.
2926
2927#Example
2928#Height 160
2929 void draw(SkCanvas* canvas) {
2930 SkPaint paint;
2931 paint.setStyle(SkPaint::kStroke_Style);
2932 paint.setStrokeWidth(16);
2933 SkScalar intervals[] = {30, 10};
2934 paint.setPathEffect(SkDashPathEffect::Make(intervals, SK_ARRAY_COUNT(intervals), 1));
2935 canvas->drawRoundRect({20, 20, 120, 120}, 20, 20, paint);
2936 }
2937##
2938
2939#SeeAlso Path_Effect
2940
2941#Method SkPathEffect* getPathEffect() const
2942
Cary Clarkab2621d2018-01-30 10:08:57 -05002943#In Path_Effect_Methods
2944#Line # returns Path_Effect, modifications to path geometry; dashing ##
Cary Clark8032b982017-07-28 11:04:54 -04002945 Returns Path_Effect if set, or nullptr.
2946 Does not alter Path_Effect Reference_Count.
Herb Derbyfcac00f2018-05-01 11:57:56 -04002947
Cary Clark8032b982017-07-28 11:04:54 -04002948 #Return Path_Effect if previously set, nullptr otherwise ##
2949
2950 #Example
2951 void draw(SkCanvas* canvas) {
2952 SkPaint paint;
2953 SkDebugf("nullptr %c= path effect\n", paint.getPathEffect() ? '!' : '=');
2954 paint.setPathEffect(SkCornerPathEffect::Make(10));
2955 SkDebugf("nullptr %c= path effect\n", paint.getPathEffect() ? '!' : '=');
2956 }
2957
2958 #StdOut
2959 nullptr == path effect
2960 nullptr != path effect
2961 ##
2962 ##
2963
2964##
2965
2966
2967#Method sk_sp<SkPathEffect> refPathEffect() const
2968
Cary Clarkab2621d2018-01-30 10:08:57 -05002969#In Path_Effect_Methods
2970#Line # references Path_Effect, modifications to path geometry; dashing ##
Cary Clark8032b982017-07-28 11:04:54 -04002971 Returns Path_Effect if set, or nullptr.
2972 Increases Path_Effect Reference_Count by one.
2973
2974 #Return Path_Effect if previously set, nullptr otherwise ##
2975
2976 #Example
2977 void draw(SkCanvas* canvas) {
2978 SkPaint paint1, paint2;
Cary Clarka560c472017-11-27 10:44:06 -05002979 SkScalar intervals[] = {1, 2};
2980 paint1.setPathEffect(SkDashPathEffect::Make(intervals, SK_ARRAY_COUNT(intervals), 10));
Cary Clark8032b982017-07-28 11:04:54 -04002981 SkDebugf("path effect unique: %s\n", paint1.getPathEffect()->unique() ? "true" : "false");
2982 paint2.setPathEffect(paint1.refPathEffect());
2983 SkDebugf("path effect unique: %s\n", paint1.getPathEffect()->unique() ? "true" : "false");
2984 }
2985
2986 #StdOut
2987 path effect unique: true
2988 path effect unique: false
2989 ##
2990 ##
2991
2992##
2993
2994
2995#Method void setPathEffect(sk_sp<SkPathEffect> pathEffect)
2996
Cary Clarkab2621d2018-01-30 10:08:57 -05002997#In Path_Effect_Methods
2998#Line # sets Path_Effect, modifications to path geometry; dashing ##
Cary Clark6fc50412017-09-21 12:31:06 -04002999Sets Path_Effect to pathEffect, decreasing Reference_Count of the previous
3000Path_Effect. Pass nullptr to leave the path geometry unaltered.
3001
3002Increments pathEffect Reference_Count by one.
Cary Clark8032b982017-07-28 11:04:54 -04003003
3004 #Param pathEffect replace Path with a modification when drawn ##
3005
3006 #Example
3007 void draw(SkCanvas* canvas) {
3008 SkPaint paint;
3009 paint.setPathEffect(SkDiscretePathEffect::Make(3, 5));
3010 canvas->drawRect(SkRect::MakeXYWH(40, 40, 175, 175), paint);
3011 }
3012 ##
3013
3014##
3015
Cary Clark08895c42018-02-01 09:37:32 -05003016#Subtopic Path_Effect_Methods ##
Cary Clark8032b982017-07-28 11:04:54 -04003017# ------------------------------------------------------------------------------
Cary Clark08895c42018-02-01 09:37:32 -05003018#Subtopic Mask_Filter_Methods
3019#Line # get and set Mask_Filter ##
Cary Clark8032b982017-07-28 11:04:54 -04003020
Cary Clarkce101242017-09-01 15:51:02 -04003021Mask_Filter uses coverage of the shape drawn to create Mask_Alpha.
Mike Reed8ad91a92018-01-19 19:09:32 -05003022Mask_Filter takes a Mask, and returns a Mask.
Cary Clark6fc50412017-09-21 12:31:06 -04003023
3024Mask_Filter may change the geometry and transparency of the shape, such as
3025creating a blur effect. Set Mask_Filter to nullptr to prevent Mask_Filter from
3026modifying the draw.
Cary Clark8032b982017-07-28 11:04:54 -04003027
3028#Example
3029 void draw(SkCanvas* canvas) {
3030 SkPaint paint;
Cary Clark681287e2018-03-16 11:34:15 -04003031 paint.setMaskFilter(SkMaskFilter::MakeBlur(kSolid_SkBlurStyle, 3));
Cary Clark8032b982017-07-28 11:04:54 -04003032 canvas->drawRect(SkRect::MakeXYWH(40, 40, 175, 175), paint);
3033 }
3034##
3035
3036#Method SkMaskFilter* getMaskFilter() const
3037
Cary Clarkab2621d2018-01-30 10:08:57 -05003038#In Mask_Filter_Methods
3039#Line # returns Mask_Filter, alterations to Mask_Alpha ##
Cary Clark8032b982017-07-28 11:04:54 -04003040 Returns Mask_Filter if set, or nullptr.
3041 Does not alter Mask_Filter Reference_Count.
Herb Derbyfcac00f2018-05-01 11:57:56 -04003042
Cary Clark8032b982017-07-28 11:04:54 -04003043 #Return Mask_Filter if previously set, nullptr otherwise ##
3044
3045 #Example
3046 void draw(SkCanvas* canvas) {
3047 SkPaint paint;
3048 SkDebugf("nullptr %c= mask filter\n", paint.getMaskFilter() ? '!' : '=');
Cary Clark681287e2018-03-16 11:34:15 -04003049 paint.setMaskFilter(SkMaskFilter::MakeBlur(kOuter_SkBlurStyle, 3));
Cary Clark8032b982017-07-28 11:04:54 -04003050 SkDebugf("nullptr %c= mask filter\n", paint.getMaskFilter() ? '!' : '=');
3051 }
3052
3053 #StdOut
3054 nullptr == mask filter
3055 nullptr != mask filter
3056 ##
3057 ##
3058
3059##
3060
3061#Method sk_sp<SkMaskFilter> refMaskFilter() const
3062
Cary Clarkab2621d2018-01-30 10:08:57 -05003063#In Mask_Filter_Methods
3064#Line # references Mask_Filter, alterations to Mask_Alpha ##
Cary Clark8032b982017-07-28 11:04:54 -04003065 Returns Mask_Filter if set, or nullptr.
Cary Clark6fc50412017-09-21 12:31:06 -04003066
Cary Clark8032b982017-07-28 11:04:54 -04003067 Increases Mask_Filter Reference_Count by one.
Herb Derbyfcac00f2018-05-01 11:57:56 -04003068
Cary Clark8032b982017-07-28 11:04:54 -04003069 #Return Mask_Filter if previously set, nullptr otherwise ##
3070
3071 #Example
3072 void draw(SkCanvas* canvas) {
3073 SkPaint paint1, paint2;
Cary Clark681287e2018-03-16 11:34:15 -04003074 paint1.setMaskFilter(SkMaskFilter::MakeBlur(kNormal_SkBlurStyle, 1));
Cary Clark8032b982017-07-28 11:04:54 -04003075 SkDebugf("mask filter unique: %s\n", paint1.getMaskFilter()->unique() ? "true" : "false");
3076 paint2.setMaskFilter(paint1.refMaskFilter());
3077 SkDebugf("mask filter unique: %s\n", paint1.getMaskFilter()->unique() ? "true" : "false");
3078 }
3079
3080 #StdOut
3081 mask filter unique: true
3082 mask filter unique: false
3083 ##
3084 ##
3085
3086##
3087
3088#Method void setMaskFilter(sk_sp<SkMaskFilter> maskFilter)
3089
Cary Clarkab2621d2018-01-30 10:08:57 -05003090#In Mask_Filter_Methods
3091#Line # sets Mask_Filter, alterations to Mask_Alpha ##
Cary Clark6fc50412017-09-21 12:31:06 -04003092Sets Mask_Filter to maskFilter, decreasing Reference_Count of the previous
3093Mask_Filter. Pass nullptr to clear Mask_Filter and leave Mask_Filter effect on
3094Mask_Alpha unaltered.
3095
Cary Clark6fc50412017-09-21 12:31:06 -04003096Increments maskFilter Reference_Count by one.
Cary Clark8032b982017-07-28 11:04:54 -04003097
3098 #Param maskFilter modifies clipping mask generated from drawn geometry ##
3099
3100 #Example
3101 void draw(SkCanvas* canvas) {
3102 SkPaint paint;
3103 paint.setStyle(SkPaint::kStroke_Style);
3104 paint.setStrokeWidth(10);
Cary Clark681287e2018-03-16 11:34:15 -04003105 paint.setMaskFilter(SkMaskFilter::MakeBlur(kNormal_SkBlurStyle, 10));
Cary Clark8032b982017-07-28 11:04:54 -04003106 canvas->drawRect(SkRect::MakeXYWH(40, 40, 175, 175), paint);
3107 }
3108 ##
3109
3110##
3111
Cary Clark08895c42018-02-01 09:37:32 -05003112#Subtopic Mask_Filter_Methods ##
Cary Clark8032b982017-07-28 11:04:54 -04003113# ------------------------------------------------------------------------------
Cary Clark08895c42018-02-01 09:37:32 -05003114#Subtopic Typeface_Methods
3115#Line # get and set Typeface ##
Cary Clark8032b982017-07-28 11:04:54 -04003116
3117Typeface identifies the font used when drawing and measuring text.
3118Typeface may be specified by name, from a file, or from a data stream.
3119The default Typeface defers to the platform-specific default font
3120implementation.
3121
3122#Example
3123#Height 100
3124 void draw(SkCanvas* canvas) {
3125 SkPaint paint;
Ben Wagner700ff172017-11-08 15:37:22 -05003126 paint.setTypeface(SkTypeface::MakeFromName(nullptr, SkFontStyle()));
Cary Clark8032b982017-07-28 11:04:54 -04003127 paint.setAntiAlias(true);
3128 paint.setTextSize(36);
3129 canvas->drawString("A Big Hello!", 10, 40, paint);
3130 paint.setTypeface(nullptr);
3131 paint.setFakeBoldText(true);
3132 canvas->drawString("A Big Hello!", 10, 80, paint);
3133 }
3134##
3135
3136#Method SkTypeface* getTypeface() const
3137
Cary Clarkab2621d2018-01-30 10:08:57 -05003138#In Typeface_Methods
3139#Line # returns Typeface, font description ##
Cary Clark8032b982017-07-28 11:04:54 -04003140 Returns Typeface if set, or nullptr.
Ben Wagner900b5362018-06-22 14:29:08 -04003141 Does not alter Typeface Reference_Count.
Herb Derbyfcac00f2018-05-01 11:57:56 -04003142
Cary Clark8032b982017-07-28 11:04:54 -04003143 #Return Typeface if previously set, nullptr otherwise ##
3144
3145 #Example
3146 void draw(SkCanvas* canvas) {
3147 SkPaint paint;
3148 SkDebugf("nullptr %c= typeface\n", paint.getTypeface() ? '!' : '=');
Cary Clark71961fb2018-01-05 14:21:59 -05003149 paint.setTypeface(SkTypeface::MakeFromName("monospace", SkFontStyle()));
Cary Clark8032b982017-07-28 11:04:54 -04003150 SkDebugf("nullptr %c= typeface\n", paint.getTypeface() ? '!' : '=');
3151 }
3152
3153 #StdOut
3154 nullptr == typeface
3155 nullptr != typeface
3156 ##
3157 ##
3158
3159##
3160
3161#Method sk_sp<SkTypeface> refTypeface() const
3162
Cary Clarkab2621d2018-01-30 10:08:57 -05003163#In Typeface_Methods
3164#Line # references Typeface, font description ##
Cary Clark8032b982017-07-28 11:04:54 -04003165 Increases Typeface Reference_Count by one.
3166
3167 #Return Typeface if previously set, nullptr otherwise ##
3168
3169 #Example
3170 void draw(SkCanvas* canvas) {
3171 SkPaint paint1, paint2;
Herb Derbyfcac00f2018-05-01 11:57:56 -04003172 paint1.setTypeface(SkTypeface::MakeFromName("monospace",
Cary Clark8032b982017-07-28 11:04:54 -04003173 SkFontStyle(SkFontStyle::kNormal_Weight, SkFontStyle::kNormal_Width,
3174 SkFontStyle::kItalic_Slant)));
3175 SkDebugf("typeface1 %c= typeface2\n",
3176 paint1.getTypeface() == paint2.getTypeface() ? '=' : '!');
3177 paint2.setTypeface(paint1.refTypeface());
3178 SkDebugf("typeface1 %c= typeface2\n",
3179 paint1.getTypeface() == paint2.getTypeface() ? '=' : '!');
3180 }
3181
3182 #StdOut
3183 typeface1 != typeface2
3184 typeface1 == typeface2
3185 ##
3186 ##
3187
3188##
3189
3190#Method void setTypeface(sk_sp<SkTypeface> typeface)
3191
Cary Clarkab2621d2018-01-30 10:08:57 -05003192#In Typeface_Methods
3193#Line # sets Typeface, font description ##
Herb Derbyfcac00f2018-05-01 11:57:56 -04003194Sets Typeface to typeface, decreasing Reference_Count of the previous Typeface.
Cary Clark6fc50412017-09-21 12:31:06 -04003195Pass nullptr to clear Typeface and use the default typeface. Increments
3196typeface Reference_Count by one.
Cary Clark8032b982017-07-28 11:04:54 -04003197
3198 #Param typeface font and style used to draw text ##
3199
3200 #Example
3201 #Height 64
3202 void draw(SkCanvas* canvas) {
3203 SkPaint paint;
Cary Clark71961fb2018-01-05 14:21:59 -05003204 paint.setTypeface(SkTypeface::MakeFromName("monospace", SkFontStyle()));
3205 canvas->drawString("hamburgerfons", 10, 30, paint);
Cary Clark8032b982017-07-28 11:04:54 -04003206 paint.setTypeface(nullptr);
Cary Clark71961fb2018-01-05 14:21:59 -05003207 canvas->drawString("hamburgerfons", 10, 50, paint);
Cary Clark8032b982017-07-28 11:04:54 -04003208 }
3209 ##
3210
3211##
3212
Cary Clark08895c42018-02-01 09:37:32 -05003213#Subtopic Typeface_Methods ##
Cary Clark8032b982017-07-28 11:04:54 -04003214# ------------------------------------------------------------------------------
Cary Clark08895c42018-02-01 09:37:32 -05003215#Subtopic Image_Filter_Methods
3216#Line # get and set Image_Filter ##
Cary Clark8032b982017-07-28 11:04:54 -04003217
3218Image_Filter operates on the pixel representation of the shape, as modified by Paint
3219with Blend_Mode set to SkBlendMode::kSrcOver. Image_Filter creates a new bitmap,
3220which is drawn to the device using the set Blend_Mode.
Cary Clark6fc50412017-09-21 12:31:06 -04003221
Cary Clark8032b982017-07-28 11:04:54 -04003222Image_Filter is higher level than Mask_Filter; for instance, an Image_Filter
Cary Clarkce101242017-09-01 15:51:02 -04003223can operate on all channels of Color, while Mask_Filter generates Alpha only.
Cary Clark8032b982017-07-28 11:04:54 -04003224Image_Filter operates independently of and can be used in combination with
Mike Reed8ad91a92018-01-19 19:09:32 -05003225Mask_Filter.
Cary Clark8032b982017-07-28 11:04:54 -04003226
3227#Example
3228 #ToDo explain why the two draws are so different ##
Cary Clark81abc432018-06-25 16:30:08 -04003229 #Function
3230 ###$
3231 #include "SkBlurImageFilter.h"
3232 $$$#
3233 ##
Cary Clark8032b982017-07-28 11:04:54 -04003234 void draw(SkCanvas* canvas) {
3235 SkPaint paint;
3236 paint.setStyle(SkPaint::kStroke_Style);
3237 paint.setStrokeWidth(2);
3238 SkRegion region;
3239 region.op( 10, 10, 50, 50, SkRegion::kUnion_Op);
3240 region.op( 10, 50, 90, 90, SkRegion::kUnion_Op);
Cary Clarka560c472017-11-27 10:44:06 -05003241 paint.setImageFilter(SkBlurImageFilter::Make(5.0f, 5.0f, nullptr));
Cary Clark8032b982017-07-28 11:04:54 -04003242 canvas->drawRegion(region, paint);
3243 paint.setImageFilter(nullptr);
Cary Clarka7b84c52018-03-18 11:46:54 -04003244 paint.setMaskFilter(SkMaskFilter::MakeBlur(kNormal_SkBlurStyle, 5));
Cary Clark8032b982017-07-28 11:04:54 -04003245 canvas->translate(100, 100);
3246 canvas->drawRegion(region, paint);
3247 }
3248##
3249
3250#Method SkImageFilter* getImageFilter() const
3251
Cary Clarkab2621d2018-01-30 10:08:57 -05003252#In Image_Filter_Methods
3253#Line # returns Image_Filter, alter pixels; blur ##
Cary Clark8032b982017-07-28 11:04:54 -04003254 Returns Image_Filter if set, or nullptr.
3255 Does not alter Image_Filter Reference_Count.
Herb Derbyfcac00f2018-05-01 11:57:56 -04003256
Cary Clark8032b982017-07-28 11:04:54 -04003257 #Return Image_Filter if previously set, nullptr otherwise ##
3258
3259 #Example
Cary Clark81abc432018-06-25 16:30:08 -04003260 #Function
3261 ###$
3262 #include "SkBlurImageFilter.h"
3263 $$$#
3264 ##
Cary Clark8032b982017-07-28 11:04:54 -04003265 void draw(SkCanvas* canvas) {
3266 SkPaint paint;
3267 SkDebugf("nullptr %c= image filter\n", paint.getImageFilter() ? '!' : '=');
Cary Clarka560c472017-11-27 10:44:06 -05003268 paint.setImageFilter(SkBlurImageFilter::Make(kOuter_SkBlurStyle, 3, nullptr, nullptr));
Cary Clark8032b982017-07-28 11:04:54 -04003269 SkDebugf("nullptr %c= image filter\n", paint.getImageFilter() ? '!' : '=');
3270 }
3271
3272 #StdOut
3273 nullptr == image filter
3274 nullptr != image filter
3275 ##
3276 ##
3277
3278##
3279
3280#Method sk_sp<SkImageFilter> refImageFilter() const
3281
Cary Clarkab2621d2018-01-30 10:08:57 -05003282#In Image_Filter_Methods
3283#Line # references Image_Filter, alter pixels; blur ##
Cary Clark8032b982017-07-28 11:04:54 -04003284 Returns Image_Filter if set, or nullptr.
3285 Increases Image_Filter Reference_Count by one.
3286
3287 #Return Image_Filter if previously set, nullptr otherwise ##
3288
3289 #Example
3290 void draw(SkCanvas* canvas) {
3291 SkPaint paint1, paint2;
3292 paint1.setImageFilter(SkOffsetImageFilter::Make(25, 25, nullptr));
3293 SkDebugf("image filter unique: %s\n", paint1.getImageFilter()->unique() ? "true" : "false");
3294 paint2.setImageFilter(paint1.refImageFilter());
3295 SkDebugf("image filter unique: %s\n", paint1.getImageFilter()->unique() ? "true" : "false");
3296 }
3297
3298 #StdOut
3299 image filter unique: true
3300 image filter unique: false
3301 ##
3302 ##
3303
3304##
3305
3306#Method void setImageFilter(sk_sp<SkImageFilter> imageFilter)
3307
Cary Clarkab2621d2018-01-30 10:08:57 -05003308#In Image_Filter_Methods
3309#Line # sets Image_Filter, alter pixels; blur ##
Cary Clark6fc50412017-09-21 12:31:06 -04003310Sets Image_Filter to imageFilter, decreasing Reference_Count of the previous
3311Image_Filter. Pass nullptr to clear Image_Filter, and remove Image_Filter effect
3312on drawing.
3313
Cary Clark6fc50412017-09-21 12:31:06 -04003314Increments imageFilter Reference_Count by one.
Cary Clark8032b982017-07-28 11:04:54 -04003315
3316 #Param imageFilter how Image is sampled when transformed ##
3317
3318 #Example
3319 #Height 160
3320 void draw(SkCanvas* canvas) {
3321 SkBitmap bitmap;
3322 bitmap.allocN32Pixels(100, 100);
3323 SkCanvas offscreen(bitmap);
3324 SkPaint paint;
3325 paint.setAntiAlias(true);
3326 paint.setColor(SK_ColorWHITE);
3327 paint.setTextSize(96);
3328 offscreen.clear(0);
3329 offscreen.drawString("e", 20, 70, paint);
3330 paint.setImageFilter(
3331 SkLightingImageFilter::MakePointLitDiffuse(SkPoint3::Make(80, 100, 10),
3332 SK_ColorWHITE, 1, 2, nullptr, nullptr));
3333 canvas->drawBitmap(bitmap, 0, 0, &paint);
3334 }
3335 ##
3336
3337##
3338
Cary Clark08895c42018-02-01 09:37:32 -05003339#Subtopic Image_Filter_Methods ##
Cary Clark8032b982017-07-28 11:04:54 -04003340# ------------------------------------------------------------------------------
Cary Clark08895c42018-02-01 09:37:32 -05003341#Subtopic Draw_Looper_Methods
3342#Line # get and set Draw_Looper ##
Cary Clark8032b982017-07-28 11:04:54 -04003343
3344Draw_Looper sets a modifier that communicates state from one Draw_Layer
3345to another to construct the draw.
Cary Clark6fc50412017-09-21 12:31:06 -04003346
Cary Clark8032b982017-07-28 11:04:54 -04003347Draw_Looper draws one or more times, modifying the canvas and paint each time.
3348Draw_Looper may be used to draw multiple colors or create a colored shadow.
Herb Derbyfcac00f2018-05-01 11:57:56 -04003349Set Draw_Looper to nullptr to prevent Draw_Looper from modifying the draw.
Cary Clark8032b982017-07-28 11:04:54 -04003350
3351#Example
3352#Height 128
3353 void draw(SkCanvas* canvas) {
3354 SkLayerDrawLooper::LayerInfo info;
3355 info.fPaintBits = (SkLayerDrawLooper::BitFlags) SkLayerDrawLooper::kColorFilter_Bit;
3356 info.fColorMode = SkBlendMode::kSrc;
3357 SkLayerDrawLooper::Builder looperBuilder;
3358 SkPaint* loopPaint = looperBuilder.addLayer(info);
3359 loopPaint->setColor(SK_ColorRED);
3360 info.fOffset.set(20, 20);
3361 loopPaint = looperBuilder.addLayer(info);
3362 loopPaint->setColor(SK_ColorBLUE);
3363 SkPaint paint;
3364 paint.setDrawLooper(looperBuilder.detach());
3365 canvas->drawCircle(50, 50, 50, paint);
3366 }
3367
3368##
3369
3370#Method SkDrawLooper* getDrawLooper() const
3371
Cary Clarkab2621d2018-01-30 10:08:57 -05003372#In Draw_Looper_Methods
3373#Line # returns Draw_Looper, multiple layers ##
Cary Clark8032b982017-07-28 11:04:54 -04003374 Returns Draw_Looper if set, or nullptr.
3375 Does not alter Draw_Looper Reference_Count.
Herb Derbyfcac00f2018-05-01 11:57:56 -04003376
Cary Clark8032b982017-07-28 11:04:54 -04003377 #Return Draw_Looper if previously set, nullptr otherwise ##
3378
3379 #Example
3380 void draw(SkCanvas* canvas) {
3381 SkPaint paint;
3382 SkDebugf("nullptr %c= draw looper\n", paint.getDrawLooper() ? '!' : '=');
3383 SkLayerDrawLooper::Builder looperBuilder;
3384 paint.setDrawLooper(looperBuilder.detach());
3385 SkDebugf("nullptr %c= draw looper\n", paint.getDrawLooper() ? '!' : '=');
3386 }
3387
3388 #StdOut
3389 nullptr == draw looper
3390 nullptr != draw looper
3391 ##
3392 ##
3393
3394##
3395
3396#Method sk_sp<SkDrawLooper> refDrawLooper() const
3397
Cary Clarkab2621d2018-01-30 10:08:57 -05003398#In Draw_Looper_Methods
3399#Line # references Draw_Looper, multiple layers ##
Cary Clark8032b982017-07-28 11:04:54 -04003400 Returns Draw_Looper if set, or nullptr.
3401 Increases Draw_Looper Reference_Count by one.
3402
3403 #Return Draw_Looper if previously set, nullptr otherwise ##
3404
3405 #Example
3406 void draw(SkCanvas* canvas) {
3407 SkPaint paint1, paint2;
3408 SkLayerDrawLooper::Builder looperBuilder;
3409 paint1.setDrawLooper(looperBuilder.detach());
3410 SkDebugf("draw looper unique: %s\n", paint1.getDrawLooper()->unique() ? "true" : "false");
3411 paint2.setDrawLooper(paint1.refDrawLooper());
3412 SkDebugf("draw looper unique: %s\n", paint1.getDrawLooper()->unique() ? "true" : "false");
3413 }
3414
3415 #StdOut
3416 draw looper unique: true
3417 draw looper unique: false
3418 ##
3419 ##
3420
3421##
3422
3423#Method SkDrawLooper* getLooper() const
Cary Clark4855f782018-02-06 09:41:53 -05003424#Bug 6259
Cary Clark8032b982017-07-28 11:04:54 -04003425#Deprecated
Cary Clark8032b982017-07-28 11:04:54 -04003426##
3427
3428#Method void setDrawLooper(sk_sp<SkDrawLooper> drawLooper)
Cary Clarkab2621d2018-01-30 10:08:57 -05003429#In Draw_Looper_Methods
3430#Line # sets Draw_Looper, multiple layers ##
Cary Clark6fc50412017-09-21 12:31:06 -04003431Sets Draw_Looper to drawLooper, decreasing Reference_Count of the previous
3432drawLooper. Pass nullptr to clear Draw_Looper and leave Draw_Looper effect on
3433drawing unaltered.
3434
3435Increments drawLooper Reference_Count by one.
Cary Clark8032b982017-07-28 11:04:54 -04003436
Cary Clarka523d2d2017-08-30 08:58:10 -04003437 #Param drawLooper iterates through drawing one or more time, altering Paint ##
Cary Clark8032b982017-07-28 11:04:54 -04003438
3439 #Example
3440 #Height 128
3441 void draw(SkCanvas* canvas) {
3442 SkPaint paint;
3443 paint.setDrawLooper(SkBlurDrawLooper::Make(0x7FFF0000, 4, -5, -10));
3444 paint.setStyle(SkPaint::kStroke_Style);
3445 paint.setStrokeWidth(10);
3446 paint.setAntiAlias(true);
3447 paint.setColor(0x7f0000ff);
3448 canvas->drawCircle(70, 70, 50, paint);
3449 }
3450 ##
3451
3452##
3453
3454#Method void setLooper(sk_sp<SkDrawLooper> drawLooper)
Cary Clark4855f782018-02-06 09:41:53 -05003455#Bug 6259
Cary Clark8032b982017-07-28 11:04:54 -04003456#Deprecated
Cary Clark8032b982017-07-28 11:04:54 -04003457##
3458
Cary Clark08895c42018-02-01 09:37:32 -05003459#Subtopic Draw_Looper_Methods ##
Cary Clark4855f782018-02-06 09:41:53 -05003460
Cary Clark8032b982017-07-28 11:04:54 -04003461# ------------------------------------------------------------------------------
Cary Clark08895c42018-02-01 09:37:32 -05003462#Subtopic Text_Align
3463#Line # text placement relative to position ##
Cary Clark8032b982017-07-28 11:04:54 -04003464
3465#Enum Align
Cary Clark08895c42018-02-01 09:37:32 -05003466#Line # glyph locations relative to text position ##
Cary Clark8032b982017-07-28 11:04:54 -04003467#Code
3468 enum Align {
3469 kLeft_Align,
3470 kCenter_Align,
3471 kRight_Align,
3472 };
Cary Clarkd98f78c2018-04-26 08:32:37 -04003473
3474 static constexpr int kAlignCount = 3;
Cary Clark8032b982017-07-28 11:04:54 -04003475##
3476
3477Align adjusts the text relative to the text position.
Cary Clarkce101242017-09-01 15:51:02 -04003478Align affects Glyphs drawn with: SkCanvas::drawText, SkCanvas::drawPosText,
Herb Derbyfcac00f2018-05-01 11:57:56 -04003479SkCanvas::drawPosTextH, SkCanvas::drawTextOnPath,
Cary Clark8032b982017-07-28 11:04:54 -04003480SkCanvas::drawTextOnPathHV, SkCanvas::drawTextRSXform, SkCanvas::drawTextBlob,
Herb Derbyfcac00f2018-05-01 11:57:56 -04003481and SkCanvas::drawString;
Cary Clarkce101242017-09-01 15:51:02 -04003482as well as calls that place text Glyphs like getTextWidths and getTextPath.
Cary Clark8032b982017-07-28 11:04:54 -04003483
3484The text position is set by the font for both horizontal and vertical text.
3485Typically, for horizontal text, the position is to the left side of the glyph on the
3486base line; and for vertical text, the position is the horizontal center of the glyph
3487at the caps height.
3488
Herb Derbyfcac00f2018-05-01 11:57:56 -04003489Align adjusts the glyph position to center it or move it to abut the position
Cary Clark8032b982017-07-28 11:04:54 -04003490using the metrics returned by the font.
3491
3492Align defaults to kLeft_Align.
3493
3494#Const kLeft_Align 0
Cary Clark682c58d2018-05-16 07:07:07 -04003495#Line # positions glyph by computed font offset ##
Cary Clark8032b982017-07-28 11:04:54 -04003496 Leaves the glyph at the position computed by the font offset by the text position.
3497##
3498
3499#Const kCenter_Align 1
Cary Clark682c58d2018-05-16 07:07:07 -04003500#Line # centers line of glyphs by its width or height ##
Cary Clark8032b982017-07-28 11:04:54 -04003501 Moves the glyph half its width if Flags has kVerticalText_Flag clear, and
3502 half its height if Flags has kVerticalText_Flag set.
3503##
3504
3505#Const kRight_Align 2
Cary Clark682c58d2018-05-16 07:07:07 -04003506#Line # moves lines of glyphs by its width or height ##
Cary Clark8032b982017-07-28 11:04:54 -04003507 Moves the glyph by its width if Flags has kVerticalText_Flag clear,
3508 and by its height if Flags has kVerticalText_Flag set.
3509##
3510
Cary Clark8032b982017-07-28 11:04:54 -04003511#Const kAlignCount 3
Cary Clark682c58d2018-05-16 07:07:07 -04003512#Line # number of different Text_Align values defined ##
Cary Clark137b8742018-05-30 09:21:49 -04003513May be used to verify that Align is a legal value.
Cary Clark8032b982017-07-28 11:04:54 -04003514##
3515
3516#Enum ##
3517
3518#Example
3519 #Height 160
3520 #Description
3521 Each position separately moves the glyph in drawPosText.
3522 ##
3523 void draw(SkCanvas* canvas) {
3524 SkPaint paint;
3525 paint.setTextSize(40);
3526 SkPoint position[] = {{100, 50}, {150, 40}};
3527 for (SkPaint::Align a : { SkPaint::kLeft_Align,
3528 SkPaint::kCenter_Align,
3529 SkPaint::kRight_Align}) {
3530 paint.setTextAlign(a);
3531 canvas->drawPosText("Aa", 2, position, paint);
3532 canvas->translate(0, 50);
3533 }
3534 }
3535##
3536
3537#Example
3538 #Height 160
3539 #Description
3540 Vertical_Text treats kLeft_Align as top align, and kRight_Align as bottom align.
3541 ##
3542 void draw(SkCanvas* canvas) {
3543 SkPaint paint;
3544 paint.setTextSize(40);
3545 paint.setVerticalText(true);
3546 for (SkPaint::Align a : { SkPaint::kLeft_Align,
3547 SkPaint::kCenter_Align,
3548 SkPaint::kRight_Align }) {
3549 paint.setTextAlign(a);
3550 canvas->drawString("Aa", 50, 80, paint);
3551 canvas->translate(50, 0);
3552 }
3553 }
3554##
3555
3556#Method Align getTextAlign() const
3557
Cary Clarkab2621d2018-01-30 10:08:57 -05003558#In Text_Align
3559#Line # returns Align: left, center, or right ##
Cary Clark8032b982017-07-28 11:04:54 -04003560 Returns Text_Align.
3561 Returns kLeft_Align if Text_Align has not been set.
3562
3563 #Return text placement relative to position ##
3564
3565 #Example
3566 SkPaint paint;
3567 SkDebugf("kLeft_Align %c= default\n", SkPaint::kLeft_Align == paint.getTextAlign() ? '=' : '!');
3568
3569 #StdOut
3570 kLeft_Align == default
3571 ##
3572 ##
3573##
3574
3575#Method void setTextAlign(Align align)
3576
Cary Clarkab2621d2018-01-30 10:08:57 -05003577#In Text_Align
3578#Line # sets Align: left, center, or right ##
Cary Clark8032b982017-07-28 11:04:54 -04003579 Sets Text_Align to align.
3580 Has no effect if align is an invalid value.
3581
3582 #Param align text placement relative to position ##
3583
3584 #Example
3585 #Height 160
3586 #Description
3587 Text is left-aligned by default, and then set to center. Setting the
3588 alignment out of range has no effect.
3589 ##
3590 void draw(SkCanvas* canvas) {
3591 SkPaint paint;
3592 paint.setTextSize(40);
3593 canvas->drawString("Aa", 100, 50, paint);
3594 paint.setTextAlign(SkPaint::kCenter_Align);
3595 canvas->drawString("Aa", 100, 100, paint);
3596 paint.setTextAlign((SkPaint::Align) SkPaint::kAlignCount);
3597 canvas->drawString("Aa", 100, 150, paint);
3598 }
3599 ##
3600
3601##
3602
Cary Clark08895c42018-02-01 09:37:32 -05003603#Subtopic Text_Align ##
Cary Clark8032b982017-07-28 11:04:54 -04003604# ------------------------------------------------------------------------------
Cary Clark08895c42018-02-01 09:37:32 -05003605#Subtopic Text_Size
3606#Line # overall height in points ##
Cary Clark8032b982017-07-28 11:04:54 -04003607
3608Text_Size adjusts the overall text size in points.
3609Text_Size can be set to any positive value or zero.
3610Text_Size defaults to 12.
3611Set SkPaintDefaults_TextSize at compile time to change the default setting.
3612
3613#Example
3614#Height 135
3615 void draw(SkCanvas* canvas) {
3616 SkPaint paint;
3617 canvas->drawString("12 point", 10, 20, paint);
3618 paint.setTextSize(24);
3619 canvas->drawString("24 point", 10, 60, paint);
3620 paint.setTextSize(48);
3621 canvas->drawString("48 point", 10, 120, paint);
3622 }
3623##
3624
3625#Method SkScalar getTextSize() const
3626
Cary Clarkab2621d2018-01-30 10:08:57 -05003627#In Text_Size
3628#Line # returns text size in points ##
Cary Clark8032b982017-07-28 11:04:54 -04003629 Returns Text_Size in points.
3630
3631 #Return typographic height of text ##
3632
3633 #Example
3634 SkPaint paint;
3635 SkDebugf("12 %c= default text size\n", 12 == paint.getTextSize() ? '=' : '!');
3636 ##
3637
3638##
3639
3640#Method void setTextSize(SkScalar textSize)
3641
Cary Clarkab2621d2018-01-30 10:08:57 -05003642#In Text_Size
3643#Line # sets text size in points ##
Cary Clark8032b982017-07-28 11:04:54 -04003644 Sets Text_Size in points.
3645 Has no effect if textSize is not greater than or equal to zero.
Herb Derbyfcac00f2018-05-01 11:57:56 -04003646
Cary Clark8032b982017-07-28 11:04:54 -04003647 #Param textSize typographic height of text ##
3648
3649 #Example
3650 SkPaint paint;
3651 SkDebugf("12 %c= text size\n", 12 == paint.getTextSize() ? '=' : '!');
3652 paint.setTextSize(-20);
3653 SkDebugf("12 %c= text size\n", 12 == paint.getTextSize() ? '=' : '!');
3654 ##
3655
3656##
3657
Cary Clark08895c42018-02-01 09:37:32 -05003658#Subtopic Text_Size ##
Cary Clark8032b982017-07-28 11:04:54 -04003659# ------------------------------------------------------------------------------
Cary Clark08895c42018-02-01 09:37:32 -05003660#Subtopic Text_Scale_X
3661#Line # text horizontal scale ##
Cary Clark8032b982017-07-28 11:04:54 -04003662
3663Text_Scale_X adjusts the text horizontal scale.
3664Text scaling approximates condensed and expanded type faces when the actual face
3665is not available.
3666Text_Scale_X can be set to any value.
3667Text_Scale_X defaults to 1.
3668
3669#Example
3670#Height 128
3671 void draw(SkCanvas* canvas) {
3672 SkPaint paint;
3673 paint.setAntiAlias(true);
3674 paint.setTextSize(24);
3675 paint.setTextScaleX(.8f);
3676 canvas->drawString("narrow", 10, 20, paint);
3677 paint.setTextScaleX(1);
3678 canvas->drawString("normal", 10, 60, paint);
3679 paint.setTextScaleX(1.2f);
3680 canvas->drawString("wide", 10, 100, paint);
3681 }
3682##
3683
3684#Method SkScalar getTextScaleX() const
3685
Cary Clarkab2621d2018-01-30 10:08:57 -05003686#In Text_Scale_X
3687#Line # returns the text horizontal scale; condensed text ##
Cary Clark8032b982017-07-28 11:04:54 -04003688 Returns Text_Scale_X.
3689 Default value is 1.
3690
3691 #Return text horizontal scale ##
3692
3693 #Example
3694 SkPaint paint;
3695 SkDebugf("1 %c= default text scale x\n", 1 == paint.getTextScaleX() ? '=' : '!');
3696 ##
3697
3698##
3699
3700
3701#Method void setTextScaleX(SkScalar scaleX)
3702
Cary Clarkab2621d2018-01-30 10:08:57 -05003703#In Text_Scale_X
3704#Line # sets the text horizontal scale; condensed text ##
Cary Clark8032b982017-07-28 11:04:54 -04003705 Sets Text_Scale_X.
3706 Default value is 1.
Herb Derbyfcac00f2018-05-01 11:57:56 -04003707
Cary Clark8032b982017-07-28 11:04:54 -04003708 #Param scaleX text horizontal scale ##
3709
3710 #Example
3711 SkPaint paint;
3712 paint.setTextScaleX(0.f / 0.f);
3713 SkDebugf("text scale %s-a-number\n", SkScalarIsNaN(paint.getTextScaleX()) ? "not" : "is");
3714 ##
3715
3716##
3717
Cary Clark08895c42018-02-01 09:37:32 -05003718#Subtopic Text_Scale_X ##
Cary Clark8032b982017-07-28 11:04:54 -04003719
Cary Clark08895c42018-02-01 09:37:32 -05003720#Subtopic Text_Skew_X
3721#Line # text horizontal slant ##
Cary Clark8032b982017-07-28 11:04:54 -04003722
3723
3724Text_Skew_X adjusts the text horizontal slant.
3725Text skewing approximates italic and oblique type faces when the actual face
3726is not available.
3727Text_Skew_X can be set to any value.
3728Text_Skew_X defaults to 0.
3729
3730#Example
3731#Height 128
3732 void draw(SkCanvas* canvas) {
3733 SkPaint paint;
3734 paint.setAntiAlias(true);
3735 paint.setTextSize(24);
3736 paint.setTextSkewX(-.25f);
3737 canvas->drawString("right-leaning", 10, 100, paint);
3738 paint.setTextSkewX(0);
3739 canvas->drawString("normal", 10, 60, paint);
3740 paint.setTextSkewX(.25f);
3741 canvas->drawString("left-leaning", 10, 20, paint);
3742 }
3743##
3744
3745#Method SkScalar getTextSkewX() const
3746
Cary Clarkab2621d2018-01-30 10:08:57 -05003747#In Text_Skew_X
3748#Line # returns the text horizontal skew; oblique text ##
Cary Clark8032b982017-07-28 11:04:54 -04003749 Returns Text_Skew_X.
3750 Default value is zero.
3751
3752 #Return additional shear in x-axis relative to y-axis ##
3753
3754 #Example
3755 SkPaint paint;
3756 SkDebugf("0 %c= default text skew x\n", 0 == paint.getTextSkewX() ? '=' : '!');
3757 ##
3758
3759##
3760
3761#Method void setTextSkewX(SkScalar skewX)
3762
Cary Clarkab2621d2018-01-30 10:08:57 -05003763#In Text_Skew_X
3764#Line # sets the text horizontal skew; oblique text ##
Cary Clark8032b982017-07-28 11:04:54 -04003765 Sets Text_Skew_X.
3766 Default value is zero.
3767
3768 #Param skewX additional shear in x-axis relative to y-axis ##
3769
3770 #Example
3771 SkPaint paint;
3772 paint.setTextScaleX(1.f / 0.f);
3773 SkDebugf("text scale %s-finite\n", SkScalarIsFinite(paint.getTextScaleX()) ? "is" : "not");
3774 ##
3775
3776##
3777
Cary Clark08895c42018-02-01 09:37:32 -05003778#Subtopic Text_Skew_X ##
Cary Clark8032b982017-07-28 11:04:54 -04003779
3780# ------------------------------------------------------------------------------
Cary Clark08895c42018-02-01 09:37:32 -05003781#Subtopic Text_Encoding
3782#Line # text encoded as characters or Glyphs ##
Cary Clark8032b982017-07-28 11:04:54 -04003783
3784#Enum TextEncoding
Cary Clark08895c42018-02-01 09:37:32 -05003785#Line # character or glyph encoded size ##
Cary Clark8032b982017-07-28 11:04:54 -04003786
3787#Code
3788 enum TextEncoding {
3789 kUTF8_TextEncoding,
3790 kUTF16_TextEncoding,
3791 kUTF32_TextEncoding,
Cary Clarkbad5ad72017-08-03 17:14:08 -04003792 kGlyphID_TextEncoding,
Cary Clark8032b982017-07-28 11:04:54 -04003793 };
3794##
3795
Cary Clark6fc50412017-09-21 12:31:06 -04003796TextEncoding determines whether text specifies character codes and their encoded
Cary Clarkbc5697d2017-10-04 14:31:33 -04003797size, or glyph indices. Characters are encoded as specified by the
Cary Clark682c58d2018-05-16 07:07:07 -04003798#A Unicode standard # https://unicode.org/standard/standard.html ##
Cary Clark6fc50412017-09-21 12:31:06 -04003799.
3800
Cary Clark8032b982017-07-28 11:04:54 -04003801Character codes encoded size are specified by UTF-8, UTF-16, or UTF-32.
Cary Clarkbc5697d2017-10-04 14:31:33 -04003802All character code formats are able to represent all of Unicode, differing only
Cary Clark8032b982017-07-28 11:04:54 -04003803in the total storage required.
3804
Cary Clark6fc50412017-09-21 12:31:06 -04003805#A UTF-8 (RFC 3629) # https://tools.ietf.org/html/rfc3629 ##
3806 encodes each character as one or more 8-bit bytes.
3807
3808#A UTF-16 (RFC 2781) # https://tools.ietf.org/html/rfc2781 ##
3809 encodes each character as one or two 16-bit words.
3810
Cary Clark682c58d2018-05-16 07:07:07 -04003811#A UTF-32 # https://www.unicode.org/versions/Unicode5.0.0/ch03.pdf ##
Cary Clark6fc50412017-09-21 12:31:06 -04003812 encodes each character as one 32-bit word.
Cary Clark8032b982017-07-28 11:04:54 -04003813
Herb Derbyfcac00f2018-05-01 11:57:56 -04003814Font_Manager uses font data to convert character code points into glyph indices.
Cary Clark8032b982017-07-28 11:04:54 -04003815A glyph index is a 16-bit word.
3816
3817TextEncoding is set to kUTF8_TextEncoding by default.
3818
3819#Const kUTF8_TextEncoding 0
Cary Clark682c58d2018-05-16 07:07:07 -04003820#Line # uses bytes to represent UTF-8 or ASCII ##
Cary Clark8032b982017-07-28 11:04:54 -04003821##
3822#Const kUTF16_TextEncoding 1
Cary Clark682c58d2018-05-16 07:07:07 -04003823#Line # uses two byte words to represent most of Unicode ##
Cary Clark8032b982017-07-28 11:04:54 -04003824##
3825#Const kUTF32_TextEncoding 2
Cary Clark682c58d2018-05-16 07:07:07 -04003826#Line # uses four byte words to represent all of Unicode ##
Cary Clark8032b982017-07-28 11:04:54 -04003827##
3828#Const kGlyphID_TextEncoding 3
Cary Clark682c58d2018-05-16 07:07:07 -04003829#Line # uses two byte words to represent glyph indices ##
Cary Clark8032b982017-07-28 11:04:54 -04003830##
3831
3832#Enum ##
3833
3834#Example
3835#Height 128
3836#Description
Cary Clarkbc5697d2017-10-04 14:31:33 -04003837First line is encoded in UTF-8.
3838Second line is encoded in UTF-16.
3839Third line is encoded in UTF-32.
Cary Clark682c58d2018-05-16 07:07:07 -04003840Fourth line has 16-bit glyph indices.
Cary Clark8032b982017-07-28 11:04:54 -04003841##
3842void draw(SkCanvas* canvas) {
3843 SkPaint paint;
3844 const char hello8[] = "Hello" "\xE2" "\x98" "\xBA";
3845 const uint16_t hello16[] = { 'H', 'e', 'l', 'l', 'o', 0x263A };
3846 const uint32_t hello32[] = { 'H', 'e', 'l', 'l', 'o', 0x263A };
3847 paint.setTextSize(24);
3848 canvas->drawText(hello8, sizeof(hello8) - 1, 10, 30, paint);
3849 paint.setTextEncoding(SkPaint::kUTF16_TextEncoding);
3850 canvas->drawText(hello16, sizeof(hello16), 10, 60, paint);
3851 paint.setTextEncoding(SkPaint::kUTF32_TextEncoding);
3852 canvas->drawText(hello32, sizeof(hello32), 10, 90, paint);
3853 uint16_t glyphs[SK_ARRAY_COUNT(hello32)];
3854 paint.textToGlyphs(hello32, sizeof(hello32), glyphs);
3855 paint.setTextEncoding(SkPaint::kGlyphID_TextEncoding);
3856 canvas->drawText(glyphs, sizeof(glyphs), 10, 120, paint);
3857}
3858##
3859
3860#Method TextEncoding getTextEncoding() const
3861
Cary Clarkab2621d2018-01-30 10:08:57 -05003862#In Text_Encoding
3863#Line # returns character or glyph encoded size ##
Cary Clark8032b982017-07-28 11:04:54 -04003864 Returns Text_Encoding.
3865 Text_Encoding determines how character code points are mapped to font glyph indices.
3866
Herb Derbyfcac00f2018-05-01 11:57:56 -04003867 #Return one of: kUTF8_TextEncoding, kUTF16_TextEncoding, kUTF32_TextEncoding, or
3868 kGlyphID_TextEncoding
Cary Clark8032b982017-07-28 11:04:54 -04003869 ##
3870
3871 #Example
3872 SkPaint paint;
Herb Derbyfcac00f2018-05-01 11:57:56 -04003873 SkDebugf("kUTF8_TextEncoding %c= text encoding\n",
Cary Clark8032b982017-07-28 11:04:54 -04003874 SkPaint::kUTF8_TextEncoding == paint.getTextEncoding() ? '=' : '!');
3875 paint.setTextEncoding(SkPaint::kGlyphID_TextEncoding);
Herb Derbyfcac00f2018-05-01 11:57:56 -04003876 SkDebugf("kGlyphID_TextEncoding %c= text encoding\n",
Cary Clark8032b982017-07-28 11:04:54 -04003877 SkPaint::kGlyphID_TextEncoding == paint.getTextEncoding() ? '=' : '!');
3878
3879 #StdOut
3880 kUTF8_TextEncoding == text encoding
3881 kGlyphID_TextEncoding == text encoding
3882 ##
3883 ##
3884
3885##
3886
3887
3888#Method void setTextEncoding(TextEncoding encoding)
3889
Cary Clarkab2621d2018-01-30 10:08:57 -05003890#In Text_Encoding
3891#Line # sets character or glyph encoded size ##
Herb Derbyfcac00f2018-05-01 11:57:56 -04003892 Sets Text_Encoding to encoding.
Cary Clark8032b982017-07-28 11:04:54 -04003893 Text_Encoding determines how character code points are mapped to font glyph indices.
3894 Invalid values for encoding are ignored.
3895
Herb Derbyfcac00f2018-05-01 11:57:56 -04003896 #Param encoding one of: kUTF8_TextEncoding, kUTF16_TextEncoding, kUTF32_TextEncoding, or
3897 kGlyphID_TextEncoding
Cary Clark579985c2017-07-31 11:48:27 -04003898 #Param ##
Cary Clark8032b982017-07-28 11:04:54 -04003899
3900 #Example
3901 SkPaint paint;
3902 paint.setTextEncoding((SkPaint::TextEncoding) 4);
Cary Clark75fd4492018-06-20 12:45:16 -04003903 SkDebugf("4 %c= text encoding\n", (SkPaint::TextEncoding) 4 == paint.getTextEncoding() ? '=' : '!');
Cary Clark8032b982017-07-28 11:04:54 -04003904
3905 #StdOut
3906 4 != text encoding
3907 ##
3908 ##
3909
3910##
3911
Cary Clark08895c42018-02-01 09:37:32 -05003912#Subtopic Text_Encoding ##
Cary Clark8032b982017-07-28 11:04:54 -04003913# ------------------------------------------------------------------------------
Cary Clark08895c42018-02-01 09:37:32 -05003914#Subtopic Font_Metrics
3915#Line # common glyph dimensions ##
Cary Clark8032b982017-07-28 11:04:54 -04003916
Cary Clarkce101242017-09-01 15:51:02 -04003917Font_Metrics describe dimensions common to the Glyphs in Typeface.
Herb Derbyfcac00f2018-05-01 11:57:56 -04003918The dimensions are computed by Font_Manager from font data and do not take
Cary Clark8032b982017-07-28 11:04:54 -04003919Paint settings other than Text_Size into account.
3920
3921Font dimensions specify the anchor to the left of the glyph at baseline as the origin.
3922X-axis values to the left of the glyph are negative, and to the right of the left glyph edge
3923are positive.
3924Y-axis values above the baseline are negative, and below the baseline are positive.
Ben Wagnere5806492017-11-09 12:08:31 -05003925
Cary Clark8032b982017-07-28 11:04:54 -04003926#Example
3927#Width 512
3928void draw(SkCanvas* canvas) {
3929 SkPaint paint;
3930 paint.setAntiAlias(true);
3931 paint.setTextSize(120);
3932 SkPaint::FontMetrics fm;
3933 SkScalar lineHeight = paint.getFontMetrics(&fm);
3934 SkPoint pt = { 70, 180 };
3935 canvas->drawString("M", pt.fX, pt.fY, paint);
3936 canvas->drawLine(pt.fX, pt.fY, pt.fX, pt.fY + fm.fTop, paint);
3937 SkScalar ascent = pt.fY + fm.fAscent;
3938 canvas->drawLine(pt.fX - 25, ascent, pt.fX - 25, ascent + lineHeight, paint);
3939 canvas->drawLine(pt.fX - 50, pt.fY, pt.fX - 50, pt.fY + fm.fDescent, paint);
3940 canvas->drawLine(pt.fX + 100, pt.fY, pt.fX + 100, pt.fY + fm.fAscent, paint);
3941 canvas->drawLine(pt.fX + 125, pt.fY, pt.fX + 125, pt.fY - fm.fXHeight, paint);
3942 canvas->drawLine(pt.fX + 150, pt.fY, pt.fX + 150, pt.fY - fm.fCapHeight, paint);
3943 canvas->drawLine(pt.fX + 5, pt.fY, pt.fX + 5, pt.fY + fm.fBottom, paint);
3944 SkScalar xmin = pt.fX + fm.fXMin;
3945 canvas->drawLine(xmin, pt.fY + 60, xmin + fm.fMaxCharWidth, pt.fY + 60, paint);
3946 canvas->drawLine(xmin, pt.fY - 145, pt.fX, pt.fY - 145, paint);
3947 canvas->drawLine(pt.fX + fm.fXMax, pt.fY - 160, pt.fX, pt.fY - 160, paint);
3948 SkScalar upos = pt.fY + fm.fUnderlinePosition;
Ben Wagnere5806492017-11-09 12:08:31 -05003949 canvas->drawLine(pt.fX + 25, upos, pt.fX + 160, upos, paint);
3950 SkScalar ut = fm.fUnderlineThickness;
3951 canvas->drawLine(pt.fX + 130, upos + ut, pt.fX + 160, upos + ut, paint);
Cary Clark8032b982017-07-28 11:04:54 -04003952 paint.setTextSize(12);
3953 canvas->drawString("x-min", pt.fX - 50, pt.fY - 148, paint);
3954 canvas->drawString("x-max", pt.fX + 140, pt.fY - 150, paint);
3955 canvas->drawString("max char width", pt.fX + 120, pt.fY + 57, paint);
3956 canvas->drawString("underline position", pt.fX + 30, pt.fY + 22, paint);
3957 canvas->drawString("underline thickness", pt.fX + 162, pt.fY + 13, paint);
3958 canvas->rotate(-90);
3959 canvas->drawString("descent", -pt.fY - 30, pt.fX - 54, paint);
3960 canvas->drawString("line height", -pt.fY, pt.fX - 29, paint);
3961 canvas->drawString("top", -pt.fY + 30, pt.fX - 4, paint);
3962 canvas->drawString("ascent", -pt.fY, pt.fX + 110, paint);
3963 canvas->drawString("x-height", -pt.fY, pt.fX + 135, paint);
3964 canvas->drawString("cap-height", -pt.fY, pt.fX + 160, paint);
3965 canvas->drawString("bottom", -pt.fY - 50, pt.fX + 15, paint);
3966}
3967##
3968
3969#Struct FontMetrics
Cary Clark08895c42018-02-01 09:37:32 -05003970#Line # values computed by Font_Manager using Typeface ##
Cary Clark8032b982017-07-28 11:04:54 -04003971
3972#Code
3973 struct FontMetrics {
3974 enum FontMetricsFlags {
3975 kUnderlineThicknessIsValid_Flag = 1 << 0,
3976 kUnderlinePositionIsValid_Flag = 1 << 1,
3977 kStrikeoutThicknessIsValid_Flag = 1 << 2,
3978 kStrikeoutPositionIsValid_Flag = 1 << 3,
3979 };
3980
3981 uint32_t fFlags;
3982 SkScalar fTop;
3983 SkScalar fAscent;
3984 SkScalar fDescent;
3985 SkScalar fBottom;
3986 SkScalar fLeading;
3987 SkScalar fAvgCharWidth;
3988 SkScalar fMaxCharWidth;
3989 SkScalar fXMin;
3990 SkScalar fXMax;
3991 SkScalar fXHeight;
3992 SkScalar fCapHeight;
3993 SkScalar fUnderlineThickness;
3994 SkScalar fUnderlinePosition;
3995 SkScalar fStrikeoutThickness;
3996 SkScalar fStrikeoutPosition;
3997
3998 bool hasUnderlineThickness(SkScalar* thickness) const;
3999 bool hasUnderlinePosition(SkScalar* position) const;
4000 bool hasStrikeoutThickness(SkScalar* thickness) const;
4001 bool hasStrikeoutPosition(SkScalar* position) const;
4002 };
4003##
4004
Cary Clark154beea2017-10-26 07:58:48 -04004005 FontMetrics is filled out by getFontMetrics. FontMetrics contents reflect the values
4006 computed by Font_Manager using Typeface. Values are set to zero if they are
4007 not available.
Cary Clarke4aa3712017-09-15 02:56:12 -04004008
Cary Clark5538c132018-06-14 12:28:14 -04004009 All vertical values are relative to the baseline, on a y-axis pointing down.
4010 Zero is on the baseline, negative values are above the baseline, and positive
4011 values are below the baseline.
Ben Wagnere5806492017-11-09 12:08:31 -05004012
Cary Clark154beea2017-10-26 07:58:48 -04004013 fUnderlineThickness and fUnderlinePosition have a bit set in fFlags if their values
4014 are valid, since their value may be zero.
Ben Wagnere5806492017-11-09 12:08:31 -05004015
Cary Clark154beea2017-10-26 07:58:48 -04004016 fStrikeoutThickness and fStrikeoutPosition have a bit set in fFlags if their values
4017 are valid, since their value may be zero.
4018
4019 #Enum FontMetricsFlags
Cary Clark682c58d2018-05-16 07:07:07 -04004020 #Line # valid Font_Metrics ##
Cary Clarke4aa3712017-09-15 02:56:12 -04004021
Cary Clark8032b982017-07-28 11:04:54 -04004022 #Code
4023 enum FontMetricsFlags {
4024 kUnderlineThicknessIsValid_Flag = 1 << 0,
4025 kUnderlinePositionIsValid_Flag = 1 << 1,
4026 kStrikeoutThicknessIsValid_Flag = 1 << 2,
4027 kStrikeoutPositionIsValid_Flag = 1 << 3,
4028 };
4029 ##
4030
Cary Clark154beea2017-10-26 07:58:48 -04004031 FontMetricsFlags are set in fFlags when underline and strikeout metrics are valid;
4032 the underline or strikeout metric may be valid and zero.
4033 Fonts with embedded bitmaps may not have valid underline or strikeout metrics.
4034
Cary Clark8032b982017-07-28 11:04:54 -04004035 #Const kUnderlineThicknessIsValid_Flag 0x0001
Cary Clark682c58d2018-05-16 07:07:07 -04004036 #Line # set if fUnderlineThickness is valid ##
Cary Clark8032b982017-07-28 11:04:54 -04004037 ##
4038 #Const kUnderlinePositionIsValid_Flag 0x0002
Cary Clark682c58d2018-05-16 07:07:07 -04004039 #Line # set if fUnderlinePosition is valid ##
Cary Clark8032b982017-07-28 11:04:54 -04004040 ##
4041 #Const kStrikeoutThicknessIsValid_Flag 0x0004
Cary Clark682c58d2018-05-16 07:07:07 -04004042 #Line # set if fStrikeoutThickness is valid ##
Cary Clark8032b982017-07-28 11:04:54 -04004043 ##
4044 #Const kStrikeoutPositionIsValid_Flag 0x0008
Cary Clark682c58d2018-05-16 07:07:07 -04004045 #Line # set if fStrikeoutPosition is valid ##
Cary Clark8032b982017-07-28 11:04:54 -04004046 ##
4047
4048 #Enum ##
4049
4050 #Member uint32_t fFlags
Cary Clark682c58d2018-05-16 07:07:07 -04004051 #Line # is set to FontMetricsFlags when metrics are valid ##
Cary Clark8032b982017-07-28 11:04:54 -04004052 ##
Ben Wagnere5806492017-11-09 12:08:31 -05004053
Cary Clark8032b982017-07-28 11:04:54 -04004054 #Member SkScalar fTop
Cary Clark682c58d2018-05-16 07:07:07 -04004055 #Line # extent above baseline ##
Ben Wagnere5806492017-11-09 12:08:31 -05004056 Greatest extent above the baseline for any glyph.
4057 Typically less than zero.
Cary Clark8032b982017-07-28 11:04:54 -04004058 ##
Ben Wagnere5806492017-11-09 12:08:31 -05004059
Cary Clark8032b982017-07-28 11:04:54 -04004060 #Member SkScalar fAscent
Cary Clark682c58d2018-05-16 07:07:07 -04004061 #Line # distance to reserve above baseline ##
Cary Clark8032b982017-07-28 11:04:54 -04004062 Recommended distance above the baseline to reserve for a line of text.
Ben Wagnere5806492017-11-09 12:08:31 -05004063 Typically less than zero.
Cary Clark8032b982017-07-28 11:04:54 -04004064 ##
Ben Wagnere5806492017-11-09 12:08:31 -05004065
Cary Clark8032b982017-07-28 11:04:54 -04004066 #Member SkScalar fDescent
Cary Clark682c58d2018-05-16 07:07:07 -04004067 #Line # distance to reserve below baseline ##
Cary Clark8032b982017-07-28 11:04:54 -04004068 Recommended distance below the baseline to reserve for a line of text.
Ben Wagnere5806492017-11-09 12:08:31 -05004069 Typically greater than zero.
Cary Clark8032b982017-07-28 11:04:54 -04004070 ##
Ben Wagnere5806492017-11-09 12:08:31 -05004071
Cary Clark8032b982017-07-28 11:04:54 -04004072 #Member SkScalar fBottom
Cary Clark682c58d2018-05-16 07:07:07 -04004073 #Line # extent below baseline ##
Ben Wagnere5806492017-11-09 12:08:31 -05004074 Greatest extent below the baseline for any glyph.
4075 Typically greater than zero.
Cary Clark8032b982017-07-28 11:04:54 -04004076 ##
Ben Wagnere5806492017-11-09 12:08:31 -05004077
Cary Clark8032b982017-07-28 11:04:54 -04004078 #Member SkScalar fLeading
Cary Clark682c58d2018-05-16 07:07:07 -04004079 #Line # distance to add between lines ##
Cary Clark8032b982017-07-28 11:04:54 -04004080 Recommended distance to add between lines of text.
Ben Wagnere5806492017-11-09 12:08:31 -05004081 Typically greater than or equal to zero.
Cary Clark8032b982017-07-28 11:04:54 -04004082 ##
Ben Wagnere5806492017-11-09 12:08:31 -05004083
Cary Clark8032b982017-07-28 11:04:54 -04004084 #Member SkScalar fAvgCharWidth
Cary Clark682c58d2018-05-16 07:07:07 -04004085 #Line # average character width ##
Cary Clark8032b982017-07-28 11:04:54 -04004086 Average character width, if it is available.
4087 Zero if no average width is stored in the font.
4088 ##
Ben Wagnere5806492017-11-09 12:08:31 -05004089
Cary Clark8032b982017-07-28 11:04:54 -04004090 #Member SkScalar fMaxCharWidth
Cary Clark682c58d2018-05-16 07:07:07 -04004091 #Line # maximum character width ##
Cary Clark8032b982017-07-28 11:04:54 -04004092 ##
Ben Wagnere5806492017-11-09 12:08:31 -05004093
Cary Clark8032b982017-07-28 11:04:54 -04004094 #Member SkScalar fXMin
Cary Clark682c58d2018-05-16 07:07:07 -04004095 #Line # minimum x ##
Cary Clark5538c132018-06-14 12:28:14 -04004096 Minimum bounding box x-axis value for all Glyphs.
Cary Clark8032b982017-07-28 11:04:54 -04004097 Typically less than zero.
4098 ##
Ben Wagnere5806492017-11-09 12:08:31 -05004099
Cary Clark8032b982017-07-28 11:04:54 -04004100 #Member SkScalar fXMax
Cary Clark682c58d2018-05-16 07:07:07 -04004101 #Line # maximum x ##
Cary Clark5538c132018-06-14 12:28:14 -04004102 Maximum bounding box x-axis value for all Glyphs.
Cary Clark8032b982017-07-28 11:04:54 -04004103 Typically greater than zero.
4104 ##
Ben Wagnere5806492017-11-09 12:08:31 -05004105
Cary Clark8032b982017-07-28 11:04:54 -04004106 #Member SkScalar fXHeight
Cary Clark682c58d2018-05-16 07:07:07 -04004107 #Line # height of lower-case 'x' ##
Cary Clark8032b982017-07-28 11:04:54 -04004108 May be zero if no lower-case height is stored in the font.
4109 ##
Ben Wagnere5806492017-11-09 12:08:31 -05004110
Cary Clark8032b982017-07-28 11:04:54 -04004111 #Member SkScalar fCapHeight
Cary Clark682c58d2018-05-16 07:07:07 -04004112 #Line # height of an upper-case letter ##
Cary Clark8032b982017-07-28 11:04:54 -04004113 May be zero if no upper-case height is stored in the font.
4114 ##
Ben Wagnere5806492017-11-09 12:08:31 -05004115
Cary Clark8032b982017-07-28 11:04:54 -04004116 #Member SkScalar fUnderlineThickness
Cary Clark682c58d2018-05-16 07:07:07 -04004117 #Line # underline thickness ##
Ben Wagnere5806492017-11-09 12:08:31 -05004118 If the metric is valid, the kUnderlineThicknessIsValid_Flag is set in fFlags.
Cary Clark8032b982017-07-28 11:04:54 -04004119 If kUnderlineThicknessIsValid_Flag is clear, fUnderlineThickness is zero.
4120 ##
Ben Wagnere5806492017-11-09 12:08:31 -05004121
Cary Clark8032b982017-07-28 11:04:54 -04004122 #Member SkScalar fUnderlinePosition
Cary Clark682c58d2018-05-16 07:07:07 -04004123 #Line # underline position relative to baseline ##
Ben Wagnere5806492017-11-09 12:08:31 -05004124 Position of the top of the underline stroke relative to the baseline.
4125 Typically positive when valid.
Cary Clark8032b982017-07-28 11:04:54 -04004126
4127 If the metric is valid, the kUnderlinePositionIsValid_Flag is set in fFlags.
4128 If kUnderlinePositionIsValid_Flag is clear, fUnderlinePosition is zero.
4129 ##
4130
4131 #Member SkScalar fStrikeoutThickness
Cary Clark682c58d2018-05-16 07:07:07 -04004132 #Line # strikeout thickness ##
Ben Wagnere5806492017-11-09 12:08:31 -05004133
4134 If the metric is valid, the kStrikeoutThicknessIsValid_Flag is set in fFlags.
Cary Clark8032b982017-07-28 11:04:54 -04004135 If kStrikeoutThicknessIsValid_Flag is clear, fStrikeoutThickness is zero.
4136 ##
4137
4138 #Member SkScalar fStrikeoutPosition
Cary Clark682c58d2018-05-16 07:07:07 -04004139 #Line # strikeout position relative to baseline ##
Ben Wagnere5806492017-11-09 12:08:31 -05004140 Position of the bottom of the strikeout stroke relative to the baseline.
4141 Typically negative when valid.
Cary Clark8032b982017-07-28 11:04:54 -04004142
Ben Wagnere5806492017-11-09 12:08:31 -05004143 If the metric is valid, the kStrikeoutPositionIsValid_Flag is set in fFlags.
4144 If kStrikeoutPositionIsValid_Flag is clear, fStrikeoutPosition is zero.
Cary Clark8032b982017-07-28 11:04:54 -04004145 ##
4146
4147 #Method bool hasUnderlineThickness(SkScalar* thickness) const
Cary Clark682c58d2018-05-16 07:07:07 -04004148 #Line # returns underline thickness if set ##
Cary Clark8032b982017-07-28 11:04:54 -04004149
Ben Wagnere5806492017-11-09 12:08:31 -05004150 If Font_Metrics has a valid underline thickness, return true, and set
Cary Clarkce101242017-09-01 15:51:02 -04004151 thickness to that value. If the underline thickness is not valid,
4152 return false, and ignore thickness.
Cary Clark8032b982017-07-28 11:04:54 -04004153
4154 #Param thickness storage for underline width ##
4155
4156 #Return true if font specifies underline width ##
4157
4158 #NoExample
4159 ##
4160 ##
4161
4162 #Method bool hasUnderlinePosition(SkScalar* position) const
Cary Clark682c58d2018-05-16 07:07:07 -04004163 #Line # returns underline position if set ##
Cary Clark8032b982017-07-28 11:04:54 -04004164
Ben Wagnere5806492017-11-09 12:08:31 -05004165 If Font_Metrics has a valid underline position, return true, and set
Cary Clarkce101242017-09-01 15:51:02 -04004166 position to that value. If the underline position is not valid,
4167 return false, and ignore position.
Cary Clark8032b982017-07-28 11:04:54 -04004168
4169 #Param position storage for underline position ##
4170
4171 #Return true if font specifies underline position ##
4172
4173 #NoExample
4174 ##
4175 ##
4176
4177 #Method bool hasStrikeoutThickness(SkScalar* thickness) const
Cary Clark682c58d2018-05-16 07:07:07 -04004178 #Line # returns strikeout thickness if set ##
Cary Clark8032b982017-07-28 11:04:54 -04004179
Ben Wagnere5806492017-11-09 12:08:31 -05004180 If Font_Metrics has a valid strikeout thickness, return true, and set
Cary Clarkce101242017-09-01 15:51:02 -04004181 thickness to that value. If the underline thickness is not valid,
4182 return false, and ignore thickness.
Cary Clark8032b982017-07-28 11:04:54 -04004183
4184 #Param thickness storage for strikeout width ##
4185
4186 #Return true if font specifies strikeout width ##
4187
4188 #NoExample
4189 ##
4190 ##
4191
4192 #Method bool hasStrikeoutPosition(SkScalar* position) const
Cary Clark682c58d2018-05-16 07:07:07 -04004193 #Line # returns strikeout position if set ##
Cary Clark8032b982017-07-28 11:04:54 -04004194
Ben Wagnere5806492017-11-09 12:08:31 -05004195 If Font_Metrics has a valid strikeout position, return true, and set
Cary Clarkce101242017-09-01 15:51:02 -04004196 position to that value. If the underline position is not valid,
4197 return false, and ignore position.
Cary Clark8032b982017-07-28 11:04:54 -04004198
4199 #Param position storage for strikeout position ##
4200
4201 #Return true if font specifies strikeout position ##
4202
4203 #NoExample
4204 ##
4205 ##
4206
4207#Struct ##
4208
4209#Method SkScalar getFontMetrics(FontMetrics* metrics, SkScalar scale = 0) const
4210
Cary Clarkab2621d2018-01-30 10:08:57 -05004211#In Font_Metrics
4212#Line # returns Typeface metrics scaled by text size ##
Cary Clark8032b982017-07-28 11:04:54 -04004213 Returns Font_Metrics associated with Typeface.
4214 The return value is the recommended spacing between lines: the sum of metrics
4215 descent, ascent, and leading.
4216 If metrics is not nullptr, Font_Metrics is copied to metrics.
4217 Results are scaled by Text_Size but does not take into account
4218 dimensions required by Text_Scale_X, Text_Skew_X, Fake_Bold,
4219 Style_Stroke, and Path_Effect.
4220 Results can be additionally scaled by scale; a scale of zero
4221 is ignored.
4222
4223 #Param metrics storage for Font_Metrics from Typeface; may be nullptr ##
4224 #Param scale additional multiplier for returned values ##
4225
4226 #Return recommended spacing between lines ##
4227
4228 #Example
4229 #Height 128
4230 void draw(SkCanvas* canvas) {
4231 SkPaint paint;
4232 paint.setTextSize(32);
4233 SkScalar lineHeight = paint.getFontMetrics(nullptr);
4234 canvas->drawString("line 1", 10, 40, paint);
4235 canvas->drawString("line 2", 10, 40 + lineHeight, paint);
4236 paint.setStyle(SkPaint::kStroke_Style);
4237 paint.setStrokeWidth(10);
4238 lineHeight = paint.getFontMetrics(nullptr, 1.10f); // account for stroke height
4239 canvas->drawString("line 3", 120, 40, paint);
4240 canvas->drawString("line 4", 120, 40 + lineHeight, paint);
4241 }
4242 ##
4243
4244 #SeeAlso Text_Size Typeface Typeface_Methods
4245
4246##
4247
4248
4249#Method SkScalar getFontSpacing() const
4250
Cary Clarkab2621d2018-01-30 10:08:57 -05004251#In Font_Metrics
4252#Line # returns recommended spacing between lines ##
Cary Clark8032b982017-07-28 11:04:54 -04004253 Returns the recommended spacing between lines: the sum of metrics
4254 descent, ascent, and leading.
4255 Result is scaled by Text_Size but does not take into account
4256 dimensions required by stroking and Path_Effect.
Cary Clark579985c2017-07-31 11:48:27 -04004257 Returns the same result as getFontMetrics.
Cary Clark8032b982017-07-28 11:04:54 -04004258
Cary Clark0c5f5462017-12-15 11:21:51 -05004259 #Return recommended spacing between lines ##
Cary Clark8032b982017-07-28 11:04:54 -04004260
4261 #Example
4262 SkPaint paint;
4263 for (SkScalar textSize : { 12, 18, 24, 32 } ) {
4264 paint.setTextSize(textSize);
4265 SkDebugf("textSize: %g fontSpacing: %g\n", textSize, paint.getFontSpacing());
4266 }
4267
4268 #StdOut
4269 textSize: 12 fontSpacing: 13.9688
4270 textSize: 18 fontSpacing: 20.9531
4271 textSize: 24 fontSpacing: 27.9375
4272 textSize: 32 fontSpacing: 37.25
4273 ##
4274 ##
4275
4276##
4277
4278
4279#Method SkRect getFontBounds() const
4280
Cary Clarkab2621d2018-01-30 10:08:57 -05004281#In Font_Metrics
4282#Line # returns union all glyph bounds ##
Cary Clarkce101242017-09-01 15:51:02 -04004283Returns the union of bounds of all Glyphs.
Herb Derbyfcac00f2018-05-01 11:57:56 -04004284Returned dimensions are computed by Font_Manager from font data,
Cary Clark579985c2017-07-31 11:48:27 -04004285ignoring Hinting. Includes Text_Size, Text_Scale_X,
Cary Clark8032b982017-07-28 11:04:54 -04004286and Text_Skew_X, but not Fake_Bold or Path_Effect.
4287
4288If Text_Size is large, Text_Scale_X is one, and Text_Skew_X is zero,
Herb Derbyfcac00f2018-05-01 11:57:56 -04004289returns the same bounds as Font_Metrics { FontMetrics::fXMin,
Cary Clark8032b982017-07-28 11:04:54 -04004290FontMetrics::fTop, FontMetrics::fXMax, FontMetrics::fBottom }.
4291
Cary Clarkce101242017-09-01 15:51:02 -04004292#Return union of bounds of all Glyphs ##
Cary Clark8032b982017-07-28 11:04:54 -04004293
4294#Example
4295 SkPaint paint;
4296 SkPaint::FontMetrics fm;
4297 paint.getFontMetrics(&fm);
4298 SkRect fb = paint.getFontBounds();
4299 SkDebugf("metrics bounds = { %g, %g, %g, %g }\n", fm.fXMin, fm.fTop, fm.fXMax, fm.fBottom );
4300 SkDebugf("font bounds = { %g, %g, %g, %g }\n", fb.fLeft, fb.fTop, fb.fRight, fm.fBottom );
4301
4302 #StdOut
4303 metrics bounds = { -12.2461, -14.7891, 21.5215, 5.55469 }
4304 font bounds = { -12.2461, -14.7891, 21.5215, 5.55469 }
4305 ##
4306##
4307
4308##
4309
Cary Clark08895c42018-02-01 09:37:32 -05004310#Subtopic Font_Metrics ##
Cary Clark8032b982017-07-28 11:04:54 -04004311# ------------------------------------------------------------------------------
4312
4313#Method int textToGlyphs(const void* text, size_t byteLength,
4314 SkGlyphID glyphs[]) const
Cary Clark78de7512018-02-07 07:27:09 -05004315#In Utility
Cary Clarkab2621d2018-01-30 10:08:57 -05004316#Line # converts text into glyph indices ##
Cary Clark8032b982017-07-28 11:04:54 -04004317
4318Converts text into glyph indices.
4319Returns the number of glyph indices represented by text.
4320Text_Encoding specifies how text represents characters or glyphs.
4321glyphs may be nullptr, to compute the glyph count.
4322
Cary Clarkbc5697d2017-10-04 14:31:33 -04004323Does not check text for valid character codes or valid glyph indices.
Cary Clark8032b982017-07-28 11:04:54 -04004324
Cary Clark579985c2017-07-31 11:48:27 -04004325If byteLength equals zero, returns zero.
Cary Clark8032b982017-07-28 11:04:54 -04004326If byteLength includes a partial character, the partial character is ignored.
4327
4328If Text_Encoding is kUTF8_TextEncoding and
4329text contains an invalid UTF-8 sequence, zero is returned.
4330
Cary Clarkce101242017-09-01 15:51:02 -04004331#Param text character storage encoded with Text_Encoding ##
Cary Clark8032b982017-07-28 11:04:54 -04004332#Param byteLength length of character storage in bytes ##
4333#Param glyphs storage for glyph indices; may be nullptr ##
4334
4335#Return number of glyphs represented by text of length byteLength ##
4336
4337 #Example
4338 #Height 64
4339 void draw(SkCanvas* canvas) {
4340 SkPaint paint;
4341 const uint8_t utf8[] = { 0x24, 0xC2, 0xA2, 0xE2, 0x82, 0xAC, 0xC2, 0xA5, 0xC2, 0xA3 };
4342 std::vector<SkGlyphID> glyphs;
4343 int count = paint.textToGlyphs(utf8, sizeof(utf8), nullptr);
4344 glyphs.resize(count);
4345 (void) paint.textToGlyphs(utf8, sizeof(utf8), &glyphs.front());
4346 paint.setTextEncoding(SkPaint::kGlyphID_TextEncoding);
4347 paint.setTextSize(32);
4348 canvas->drawText(&glyphs.front(), glyphs.size() * sizeof(SkGlyphID), 10, 40, paint);
4349 }
4350 ##
4351
4352##
4353
4354#Method int countText(const void* text, size_t byteLength) const
Cary Clark78de7512018-02-07 07:27:09 -05004355#In Utility
Cary Clarkab2621d2018-01-30 10:08:57 -05004356#Line # returns number of Glyphs in text ##
Cary Clarkce101242017-09-01 15:51:02 -04004357 Returns the number of Glyphs in text.
4358 Uses Text_Encoding to count the Glyphs.
Cary Clark8032b982017-07-28 11:04:54 -04004359 Returns the same result as textToGlyphs.
4360
Cary Clarkce101242017-09-01 15:51:02 -04004361#Param text character storage encoded with Text_Encoding ##
Cary Clark8032b982017-07-28 11:04:54 -04004362#Param byteLength length of character storage in bytes ##
4363
Cary Clarkce101242017-09-01 15:51:02 -04004364#Return number of Glyphs represented by text of length byteLength ##
Cary Clark8032b982017-07-28 11:04:54 -04004365
4366 #Example
4367 SkPaint paint;
4368 const uint8_t utf8[] = { 0x24, 0xC2, 0xA2, 0xE2, 0x82, 0xAC, 0xC2, 0xA5, 0xC2, 0xA3 };
4369 SkDebugf("count = %d\n", paint.countText(utf8, sizeof(utf8)));
4370
4371 #StdOut
4372 count = 5
4373 ##
4374 ##
4375##
4376
4377# ------------------------------------------------------------------------------
4378
4379#Method bool containsText(const void* text, size_t byteLength) const
Cary Clark78de7512018-02-07 07:27:09 -05004380#In Utility
Cary Clarkab2621d2018-01-30 10:08:57 -05004381#Line # returns if all text corresponds to Glyphs ##
Herb Derbyfcac00f2018-05-01 11:57:56 -04004382 Returns true if all text corresponds to a non-zero glyph index.
Cary Clark8032b982017-07-28 11:04:54 -04004383 Returns false if any characters in text are not supported in
4384 Typeface.
4385
Cary Clark579985c2017-07-31 11:48:27 -04004386 If Text_Encoding is kGlyphID_TextEncoding,
4387 returns true if all glyph indices in text are non-zero;
Cary Clark8032b982017-07-28 11:04:54 -04004388 does not check to see if text contains valid glyph indices for Typeface.
4389
Cary Clarkce101242017-09-01 15:51:02 -04004390 Returns true if byteLength is zero.
Cary Clark8032b982017-07-28 11:04:54 -04004391
Cary Clarkce101242017-09-01 15:51:02 -04004392 #Param text array of characters or Glyphs ##
Cary Clark8032b982017-07-28 11:04:54 -04004393 #Param byteLength number of bytes in text array ##
4394
4395 #Return true if all text corresponds to a non-zero glyph index ##
4396
Ruiqi Mao94d57c42018-07-02 15:20:10 -04004397 #NoExample
Cary Clark8032b982017-07-28 11:04:54 -04004398 #Description
4399 containsText succeeds for degree symbol, but cannot find a glyph index
4400 corresponding to the Unicode surrogate code point.
4401 ##
4402 SkPaint paint;
4403 const uint16_t goodChar = 0x00B0; // degree symbol
4404 const uint16_t badChar = 0xD800; // Unicode surrogate
4405 paint.setTextEncoding(SkPaint::kUTF16_TextEncoding);
Herb Derbyfcac00f2018-05-01 11:57:56 -04004406 SkDebugf("0x%04x %c= has char\n", goodChar,
Cary Clark8032b982017-07-28 11:04:54 -04004407 paint.containsText(&goodChar, 2) ? '=' : '!');
4408 SkDebugf("0x%04x %c= has char\n", badChar,
4409 paint.containsText(&badChar, 2) ? '=' : '!');
4410
4411 #StdOut
4412 0x00b0 == has char
4413 0xd800 != has char
4414 ##
4415 ##
4416
4417 #Example
4418 #Description
4419 containsText returns true that glyph index is greater than zero, not
4420 that it corresponds to an entry in Typeface.
4421 ##
4422 SkPaint paint;
4423 const uint16_t goodGlyph = 511;
4424 const uint16_t zeroGlyph = 0;
4425 const uint16_t badGlyph = 65535; // larger than glyph count in font
4426 paint.setTextEncoding(SkPaint::kGlyphID_TextEncoding);
Herb Derbyfcac00f2018-05-01 11:57:56 -04004427 SkDebugf("0x%04x %c= has glyph\n", goodGlyph,
Cary Clark8032b982017-07-28 11:04:54 -04004428 paint.containsText(&goodGlyph, 2) ? '=' : '!');
4429 SkDebugf("0x%04x %c= has glyph\n", zeroGlyph,
4430 paint.containsText(&zeroGlyph, 2) ? '=' : '!');
4431 SkDebugf("0x%04x %c= has glyph\n", badGlyph,
4432 paint.containsText(&badGlyph, 2) ? '=' : '!');
4433
4434 #StdOut
4435 0x01ff == has glyph
4436 0x0000 != has glyph
4437 0xffff == has glyph
4438 ##
4439 ##
4440
4441#SeeAlso setTextEncoding Typeface
4442
4443##
4444
4445# ------------------------------------------------------------------------------
4446
4447#Method void glyphsToUnichars(const SkGlyphID glyphs[],
4448 int count, SkUnichar text[]) const
Cary Clark78de7512018-02-07 07:27:09 -05004449#In Utility
Cary Clarkab2621d2018-01-30 10:08:57 -05004450#Line # converts Glyphs into text ##
Cary Clark8032b982017-07-28 11:04:54 -04004451
Herb Derbyfcac00f2018-05-01 11:57:56 -04004452 Converts glyphs into text if possible.
4453 Glyph values without direct Unicode equivalents are mapped to zero.
Cary Clark8032b982017-07-28 11:04:54 -04004454 Uses the Typeface, but is unaffected
4455 by Text_Encoding; the text values returned are equivalent to kUTF32_TextEncoding.
4456
4457 Only supported on platforms that use FreeType as the Font_Engine.
4458
4459 #Param glyphs array of indices into font ##
4460 #Param count length of glyph array ##
4461 #Param text storage for character codes, one per glyph ##
4462
4463 #Example
4464 #Height 64
4465 #Description
4466 Convert UTF-8 text to glyphs; then convert glyphs to Unichar code points.
4467 ##
4468 void draw(SkCanvas* canvas) {
4469 SkPaint paint;
4470 const char hello[] = "Hello!";
4471 const int count = sizeof(hello) - 1;
4472 SkGlyphID glyphs[count];
4473 if (count != paint.textToGlyphs(hello, count, glyphs)) {
4474 return;
4475 }
4476 SkUnichar unichars[count];
4477 paint.glyphsToUnichars(glyphs, count, unichars);
4478 paint.setTextEncoding(SkPaint::kUTF32_TextEncoding);
4479 canvas->drawText(unichars, sizeof(unichars), 10, 30, paint);
4480 }
4481 ##
4482
4483##
4484
4485# ------------------------------------------------------------------------------
Cary Clark08895c42018-02-01 09:37:32 -05004486#Subtopic Measure_Text
4487#Line # width, height, bounds of text ##
Cary Clark8032b982017-07-28 11:04:54 -04004488
4489#Method SkScalar measureText(const void* text, size_t length, SkRect* bounds) const
4490
Cary Clarkab2621d2018-01-30 10:08:57 -05004491#In Measure_Text
4492#Line # returns advance width and bounds of text ##
Cary Clark8032b982017-07-28 11:04:54 -04004493 Returns the advance width of text if kVerticalText_Flag is clear,
4494 and the height of text if kVerticalText_Flag is set.
4495 The advance is the normal distance to move before drawing additional text.
4496 Uses Text_Encoding to decode text, Typeface to get the font metrics,
4497 and Text_Size, Text_Scale_X, Text_Skew_X, Stroke_Width, and
4498 Path_Effect to scale the metrics and bounds.
4499 Returns the bounding box of text if bounds is not nullptr.
4500 The bounding box is computed as if the text was drawn at the origin.
Herb Derbyfcac00f2018-05-01 11:57:56 -04004501
Cary Clark8032b982017-07-28 11:04:54 -04004502 #Param text character codes or glyph indices to be measured ##
4503 #Param length number of bytes of text to measure ##
4504 #Param bounds returns bounding box relative to (0, 0) if not nullptr ##
4505
4506 #Return advance width or height ##
4507
4508 #Example
4509 #Height 64
4510 void draw(SkCanvas* canvas) {
4511 SkPaint paint;
4512 paint.setAntiAlias(true);
4513 paint.setTextSize(50);
4514 const char str[] = "ay^jZ";
4515 const int count = sizeof(str) - 1;
4516 canvas->drawText(str, count, 25, 50, paint);
4517 SkRect bounds;
4518 paint.measureText(str, count, &bounds);
4519 canvas->translate(25, 50);
4520 paint.setStyle(SkPaint::kStroke_Style);
4521 canvas->drawRect(bounds, paint);
4522 }
4523 ##
4524
4525##
4526
4527#Method SkScalar measureText(const void* text, size_t length) const
4528
Cary Clarkab2621d2018-01-30 10:08:57 -05004529#In Measure_Text
Cary Clark8032b982017-07-28 11:04:54 -04004530 Returns the advance width of text if kVerticalText_Flag is clear,
4531 and the height of text if kVerticalText_Flag is set.
4532 The advance is the normal distance to move before drawing additional text.
4533 Uses Text_Encoding to decode text, Typeface to get the font metrics,
4534 and Text_Size to scale the metrics.
4535 Does not scale the advance or bounds by Fake_Bold or Path_Effect.
4536
4537 #Param text character codes or glyph indices to be measured ##
4538 #Param length number of bytes of text to measure ##
4539
4540 #Return advance width or height ##
4541
4542 #Example
4543 SkPaint paint;
4544 SkDebugf("default width = %g\n", paint.measureText("!", 1));
4545 paint.setTextSize(paint.getTextSize() * 2);
4546 SkDebugf("double width = %g\n", paint.measureText("!", 1));
4547
4548 #StdOut
4549 default width = 5
4550 double width = 10
4551 ##
4552 ##
4553
4554##
4555
4556#Method size_t breakText(const void* text, size_t length, SkScalar maxWidth,
Cary Clark73fa9722017-08-29 17:36:51 -04004557 SkScalar* measuredWidth = nullptr) const
Cary Clarkab2621d2018-01-30 10:08:57 -05004558#In Measure_Text
4559#Line # returns text that fits in a width ##
Cary Clark8032b982017-07-28 11:04:54 -04004560
4561 Returns the bytes of text that fit within maxWidth.
4562 If kVerticalText_Flag is clear, the text fragment fits if its advance width is less than or
4563 equal to maxWidth.
4564 If kVerticalText_Flag is set, the text fragment fits if its advance height is less than or
4565 equal to maxWidth.
4566 Measures only while the advance is less than or equal to maxWidth.
4567 Returns the advance or the text fragment in measuredWidth if it not nullptr.
4568 Uses Text_Encoding to decode text, Typeface to get the font metrics,
4569 and Text_Size to scale the metrics.
4570 Does not scale the advance or bounds by Fake_Bold or Path_Effect.
4571
4572 #Param text character codes or glyph indices to be measured ##
4573 #Param length number of bytes of text to measure ##
4574 #Param maxWidth advance limit; text is measured while advance is less than maxWidth ##
4575 #Param measuredWidth returns the width of the text less than or equal to maxWidth ##
4576 #Return bytes of text that fit, always less than or equal to length ##
Herb Derbyfcac00f2018-05-01 11:57:56 -04004577
Cary Clark8032b982017-07-28 11:04:54 -04004578 #Example
4579 #Description
4580 Line under "Breakfast" shows desired width, shorter than available characters.
4581 Line under "Bre" shows measured width after breaking text.
4582 ##
4583 #Height 128
4584 #Width 280
4585 void draw(SkCanvas* canvas) {
4586 SkPaint paint;
4587 paint.setAntiAlias(true);
4588 paint.setTextSize(50);
4589 const char str[] = "Breakfast";
4590 const int count = sizeof(str) - 1;
4591 canvas->drawText(str, count, 25, 50, paint);
4592 SkScalar measuredWidth;
4593 int partialBytes = paint.breakText(str, count, 100, &measuredWidth);
4594 canvas->drawText(str, partialBytes, 25, 100, paint);
4595 canvas->drawLine(25, 60, 25 + 100, 60, paint);
4596 canvas->drawLine(25, 110, 25 + measuredWidth, 110, paint);
4597 }
4598 ##
4599
4600##
4601
4602#Method int getTextWidths(const void* text, size_t byteLength, SkScalar widths[],
Cary Clark73fa9722017-08-29 17:36:51 -04004603 SkRect bounds[] = nullptr) const
Cary Clarkab2621d2018-01-30 10:08:57 -05004604#In Measure_Text
4605#Line # returns advance and bounds for each glyph in text ##
Cary Clark8032b982017-07-28 11:04:54 -04004606
4607 Retrieves the advance and bounds for each glyph in text, and returns
4608 the glyph count in text.
4609 Both widths and bounds may be nullptr.
4610 If widths is not nullptr, widths must be an array of glyph count entries.
Herb Derbyfcac00f2018-05-01 11:57:56 -04004611 if bounds is not nullptr, bounds must be an array of glyph count entries.
Cary Clark8032b982017-07-28 11:04:54 -04004612 If kVerticalText_Flag is clear, widths returns the horizontal advance.
4613 If kVerticalText_Flag is set, widths returns the vertical advance.
4614 Uses Text_Encoding to decode text, Typeface to get the font metrics,
4615 and Text_Size to scale the widths and bounds.
4616 Does not scale the advance by Fake_Bold or Path_Effect.
4617 Does include Fake_Bold and Path_Effect in the bounds.
Herb Derbyfcac00f2018-05-01 11:57:56 -04004618
Cary Clark8032b982017-07-28 11:04:54 -04004619 #Param text character codes or glyph indices to be measured ##
4620 #Param byteLength number of bytes of text to measure ##
4621 #Param widths returns text advances for each glyph; may be nullptr ##
4622 #Param bounds returns bounds for each glyph relative to (0, 0); may be nullptr ##
Herb Derbyfcac00f2018-05-01 11:57:56 -04004623
Cary Clark8032b982017-07-28 11:04:54 -04004624 #Return glyph count in text ##
4625
4626 #Example
4627 #Height 160
4628 #Description
Cary Clarkce101242017-09-01 15:51:02 -04004629 Bounds of Glyphs increase for stroked text, but text advance remains the same.
Cary Clark8032b982017-07-28 11:04:54 -04004630 The underlines show the text advance, spaced to keep them distinct.
4631 ##
4632 void draw(SkCanvas* canvas) {
4633 SkPaint paint;
4634 paint.setAntiAlias(true);
4635 paint.setTextSize(50);
4636 const char str[] = "abc";
4637 const int bytes = sizeof(str) - 1;
4638 int count = paint.getTextWidths(str, bytes, nullptr);
4639 std::vector<SkScalar> widths;
4640 std::vector<SkRect> bounds;
4641 widths.resize(count);
4642 bounds.resize(count);
4643 for (int loop = 0; loop < 2; ++loop) {
4644 (void) paint.getTextWidths(str, count, &widths.front(), &bounds.front());
4645 SkPoint loc = { 25, 50 };
4646 canvas->drawText(str, bytes, loc.fX, loc.fY, paint);
4647 paint.setStyle(SkPaint::kStroke_Style);
4648 paint.setStrokeWidth(0);
4649 SkScalar advanceY = loc.fY + 10;
4650 for (int index = 0; index < count; ++index) {
4651 bounds[index].offset(loc.fX, loc.fY);
4652 canvas->drawRect(bounds[index], paint);
4653 canvas->drawLine(loc.fX, advanceY, loc.fX + widths[index], advanceY, paint);
4654 loc.fX += widths[index];
4655 advanceY += 5;
4656 }
4657 canvas->translate(0, 80);
4658 paint.setStrokeWidth(3);
4659 }
4660 }
4661 ##
4662
4663##
4664
Cary Clark08895c42018-02-01 09:37:32 -05004665#Subtopic Measure_Text ##
Cary Clark8032b982017-07-28 11:04:54 -04004666# ------------------------------------------------------------------------------
Cary Clark08895c42018-02-01 09:37:32 -05004667#Subtopic Text_Path
4668#Line # geometry of Glyphs ##
Cary Clark8032b982017-07-28 11:04:54 -04004669
Cary Clarkce101242017-09-01 15:51:02 -04004670Text_Path describes the geometry of Glyphs used to draw text.
Cary Clark8032b982017-07-28 11:04:54 -04004671
4672#Method void getTextPath(const void* text, size_t length, SkScalar x, SkScalar y,
4673 SkPath* path) const
Cary Clarkab2621d2018-01-30 10:08:57 -05004674#In Text_Path
4675#Line # returns Path equivalent to text ##
Cary Clark8032b982017-07-28 11:04:54 -04004676
4677Returns the geometry as Path equivalent to the drawn text.
4678Uses Text_Encoding to decode text, Typeface to get the glyph paths,
4679and Text_Size, Fake_Bold, and Path_Effect to scale and modify the glyph paths.
4680All of the glyph paths are stored in path.
Cary Clark579985c2017-07-31 11:48:27 -04004681Uses x, y, and Text_Align to position path.
Cary Clark8032b982017-07-28 11:04:54 -04004682
4683 #Param text character codes or glyph indices ##
4684 #Param length number of bytes of text ##
Cary Clark5538c132018-06-14 12:28:14 -04004685 #Param x x-axis value of the origin of the text ##
4686 #Param y y-axis value of the origin of the text ##
Cary Clarkce101242017-09-01 15:51:02 -04004687 #Param path geometry of the Glyphs ##
Cary Clark8032b982017-07-28 11:04:54 -04004688
4689 #Example
4690 #Description
4691 Text is added to Path, offset, and subtracted from Path, then added at
4692 the offset location. The result is rendered with one draw call.
4693 ##
4694 #Height 128
4695 void draw(SkCanvas* canvas) {
4696 SkPaint paint;
4697 paint.setTextSize(80);
4698 SkPath path, path2;
4699 paint.getTextPath("ABC", 3, 20, 80, &path);
4700 path.offset(20, 20, &path2);
4701 Op(path, path2, SkPathOp::kDifference_SkPathOp, &path);
4702 path.addPath(path2);
4703 paint.setStyle(SkPaint::kStroke_Style);
4704 canvas->drawPath(path, paint);
4705 }
4706 ##
4707
4708##
4709
4710#Method void getPosTextPath(const void* text, size_t length,
4711 const SkPoint pos[], SkPath* path) const
Cary Clarkab2621d2018-01-30 10:08:57 -05004712#In Text_Path
4713#Line # returns Path equivalent to positioned text ##
Cary Clark8032b982017-07-28 11:04:54 -04004714
4715Returns the geometry as Path equivalent to the drawn text.
4716Uses Text_Encoding to decode text, Typeface to get the glyph paths,
4717and Text_Size, Fake_Bold, and Path_Effect to scale and modify the glyph paths.
4718All of the glyph paths are stored in path.
4719Uses pos array and Text_Align to position path.
4720pos contains a position for each glyph.
4721
4722 #Param text character codes or glyph indices ##
4723 #Param length number of bytes of text ##
4724 #Param pos positions of each glyph ##
Cary Clarkce101242017-09-01 15:51:02 -04004725 #Param path geometry of the Glyphs ##
Cary Clark8032b982017-07-28 11:04:54 -04004726
4727 #Example
4728 #Height 85
4729 #Description
Cary Clarkce101242017-09-01 15:51:02 -04004730 Simplifies three Glyphs to eliminate overlaps, and strokes the result.
Cary Clark8032b982017-07-28 11:04:54 -04004731 ##
4732 void draw(SkCanvas* canvas) {
4733 SkPaint paint;
4734 paint.setTextSize(80);
4735 SkPath path, path2;
4736 SkPoint pos[] = {{20, 60}, {30, 70}, {40, 80}};
4737 paint.getPosTextPath("ABC", 3, pos, &path);
4738 Simplify(path, &path);
4739 paint.setStyle(SkPaint::kStroke_Style);
4740 canvas->drawPath(path, paint);
4741 }
4742 ##
4743
4744##
4745
Cary Clark08895c42018-02-01 09:37:32 -05004746#Subtopic Text_Path ##
Cary Clark8032b982017-07-28 11:04:54 -04004747# ------------------------------------------------------------------------------
Cary Clark08895c42018-02-01 09:37:32 -05004748#Subtopic Text_Intercepts
4749#Line # advanced underline, strike through ##
Cary Clark8032b982017-07-28 11:04:54 -04004750
Cary Clarkce101242017-09-01 15:51:02 -04004751Text_Intercepts describe the intersection of drawn text Glyphs with a pair
Cary Clark8032b982017-07-28 11:04:54 -04004752of lines parallel to the text advance. Text_Intercepts permits creating a
Cary Clarkce101242017-09-01 15:51:02 -04004753underline that skips Descenders.
Cary Clark8032b982017-07-28 11:04:54 -04004754
4755#Method int getTextIntercepts(const void* text, size_t length, SkScalar x, SkScalar y,
4756 const SkScalar bounds[2], SkScalar* intervals) const
Cary Clarkab2621d2018-01-30 10:08:57 -05004757#In Text_Intercepts
4758#Line # returns where lines intersect text; underlines ##
Cary Clark8032b982017-07-28 11:04:54 -04004759
4760 Returns the number of intervals that intersect bounds.
4761 bounds describes a pair of lines parallel to the text advance.
Cary Clarkce101242017-09-01 15:51:02 -04004762 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 -04004763 the string.
Cary Clark8032b982017-07-28 11:04:54 -04004764 Uses Text_Encoding to decode text, Typeface to get the glyph paths,
4765 and Text_Size, Fake_Bold, and Path_Effect to scale and modify the glyph paths.
4766 Uses x, y, and Text_Align to position intervals.
Herb Derbyfcac00f2018-05-01 11:57:56 -04004767
Cary Clark8032b982017-07-28 11:04:54 -04004768 Pass nullptr for intervals to determine the size of the interval array.
Herb Derbyfcac00f2018-05-01 11:57:56 -04004769
Cary Clark8032b982017-07-28 11:04:54 -04004770 intervals are cached to improve performance for multiple calls.
4771
4772 #Param text character codes or glyph indices ##
4773 #Param length number of bytes of text ##
Cary Clark5538c132018-06-14 12:28:14 -04004774 #Param x x-axis value of the origin of the text ##
4775 #Param y y-axis value of the origin of the text ##
Cary Clark8032b982017-07-28 11:04:54 -04004776 #Param bounds lower and upper line parallel to the advance ##
4777 #Param intervals returned intersections; may be nullptr ##
4778
4779 #Return number of intersections; may be zero ##
4780
4781#Example
4782#Height 128
4783#Description
Cary Clarkce101242017-09-01 15:51:02 -04004784Underline uses intercepts to draw on either side of the glyph Descender.
Cary Clark8032b982017-07-28 11:04:54 -04004785##
4786void draw(SkCanvas* canvas) {
4787 SkPaint paint;
4788 paint.setTextSize(120);
4789 SkPoint textOrigin = { 20, 100 };
4790 SkScalar bounds[] = { 100, 108 };
4791 int count = paint.getTextIntercepts("y", 1, textOrigin.fX, textOrigin.fY, bounds, nullptr);
4792 std::vector<SkScalar> intervals;
4793 intervals.resize(count);
4794 (void) paint.getTextIntercepts("y", 1, textOrigin.fX, textOrigin.fY, bounds,
4795 &intervals.front());
4796 canvas->drawString("y", textOrigin.fX, textOrigin.fY, paint);
4797 paint.setColor(SK_ColorRED);
4798 SkScalar x = textOrigin.fX;
4799 for (int i = 0; i < count; i += 2) {
4800 canvas->drawRect({x, bounds[0], intervals[i], bounds[1]}, paint);
4801 x = intervals[i + 1];
4802 }
4803 canvas->drawRect({intervals[count - 1], bounds[0],
4804 textOrigin.fX + paint.measureText("y", 1), bounds[1]}, paint);
4805}
4806##
4807
4808##
4809
4810#Method int getPosTextIntercepts(const void* text, size_t length, const SkPoint pos[],
4811 const SkScalar bounds[2], SkScalar* intervals) const
Cary Clarkab2621d2018-01-30 10:08:57 -05004812#In Text_Intercepts
4813#Line # returns where lines intersect positioned text; underlines ##
Cary Clark8032b982017-07-28 11:04:54 -04004814
4815 Returns the number of intervals that intersect bounds.
4816 bounds describes a pair of lines parallel to the text advance.
Cary Clarkce101242017-09-01 15:51:02 -04004817 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 -04004818 the string.
Cary Clark8032b982017-07-28 11:04:54 -04004819 Uses Text_Encoding to decode text, Typeface to get the glyph paths,
4820 and Text_Size, Fake_Bold, and Path_Effect to scale and modify the glyph paths.
4821 Uses pos array and Text_Align to position intervals.
Herb Derbyfcac00f2018-05-01 11:57:56 -04004822
Cary Clark8032b982017-07-28 11:04:54 -04004823 Pass nullptr for intervals to determine the size of the interval array.
Herb Derbyfcac00f2018-05-01 11:57:56 -04004824
Cary Clark8032b982017-07-28 11:04:54 -04004825 intervals are cached to improve performance for multiple calls.
4826
4827 #Param text character codes or glyph indices ##
4828 #Param length number of bytes of text ##
4829 #Param pos positions of each glyph ##
4830 #Param bounds lower and upper line parallel to the advance ##
4831 #Param intervals returned intersections; may be nullptr ##
4832
Cary Clarka523d2d2017-08-30 08:58:10 -04004833 #Return number of intersections; may be zero ##
Cary Clark8032b982017-07-28 11:04:54 -04004834
4835 #Example
4836 #Description
Cary Clarkce101242017-09-01 15:51:02 -04004837 Text intercepts draw on either side of, but not inside, Glyphs in a run.
Cary Clark8032b982017-07-28 11:04:54 -04004838 ##
4839 void draw(SkCanvas* canvas) {
4840 SkPaint paint;
4841 paint.setTextSize(120);
4842 paint.setVerticalText(true);
4843 SkPoint textPos[] = {{ 60, 40 }, { 60, 140 }};
4844 SkScalar bounds[] = { 56, 64 };
4845 const char str[] = "A-";
4846 int len = sizeof(str) - 1;
4847 int count = paint.getPosTextIntercepts(str, len, textPos, bounds, nullptr);
4848 std::vector<SkScalar> intervals;
4849 intervals.resize(count);
4850 (void) paint.getPosTextIntercepts(str, len, textPos, bounds, &intervals.front());
4851 canvas->drawPosText(str, len, textPos, paint);
4852 paint.setColor(SK_ColorRED);
4853 SkScalar y = textPos[0].fY;
4854 for (int i = 0; i < count; i+= 2) {
4855 canvas->drawRect({bounds[0], y, bounds[1], intervals[i]}, paint);
4856 y = intervals[i + 1];
4857 }
4858 canvas->drawRect({bounds[0], intervals[count - 1], bounds[1], 240}, paint);
4859 }
4860 ##
4861
4862##
4863
4864#Method int getPosTextHIntercepts(const void* text, size_t length, const SkScalar xpos[],
4865 SkScalar constY, const SkScalar bounds[2],
4866 SkScalar* intervals) const
Cary Clarkab2621d2018-01-30 10:08:57 -05004867#In Text_Intercepts
4868#Line # returns where lines intersect horizontally positioned text; underlines ##
Cary Clark8032b982017-07-28 11:04:54 -04004869
4870 Returns the number of intervals that intersect bounds.
4871 bounds describes a pair of lines parallel to the text advance.
Cary Clarkce101242017-09-01 15:51:02 -04004872 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 -04004873 the string.
Cary Clark8032b982017-07-28 11:04:54 -04004874 Uses Text_Encoding to decode text, Typeface to get the glyph paths,
4875 and Text_Size, Fake_Bold, and Path_Effect to scale and modify the glyph paths.
4876 Uses xpos array, constY, and Text_Align to position intervals.
Herb Derbyfcac00f2018-05-01 11:57:56 -04004877
Cary Clark8032b982017-07-28 11:04:54 -04004878 Pass nullptr for intervals to determine the size of the interval array.
Herb Derbyfcac00f2018-05-01 11:57:56 -04004879
Cary Clark8032b982017-07-28 11:04:54 -04004880 intervals are cached to improve performance for multiple calls.
4881
4882 #Param text character codes or glyph indices ##
4883 #Param length number of bytes of text ##
4884 #Param xpos positions of each glyph in x ##
4885 #Param constY position of each glyph in y ##
4886 #Param bounds lower and upper line parallel to the advance ##
4887 #Param intervals returned intersections; may be nullptr ##
4888
4889 #Return number of intersections; may be zero ##
4890
4891 #Example
4892 #Height 128
4893 #Description
4894 Text intercepts do not take stroke thickness into consideration.
4895 ##
4896 void draw(SkCanvas* canvas) {
4897 SkPaint paint;
4898 paint.setTextSize(120);
4899 paint.setStyle(SkPaint::kStroke_Style);
4900 paint.setStrokeWidth(4);
4901 SkScalar textPosH[] = { 20, 80, 140 };
4902 SkScalar y = 100;
4903 SkScalar bounds[] = { 56, 78 };
4904 const char str[] = "\\-/";
4905 int len = sizeof(str) - 1;
4906 int count = paint.getPosTextHIntercepts(str, len, textPosH, y, bounds, nullptr);
4907 std::vector<SkScalar> intervals;
4908 intervals.resize(count);
4909 (void) paint.getPosTextHIntercepts(str, len, textPosH, y, bounds, &intervals.front());
4910 canvas->drawPosTextH(str, len, textPosH, y, paint);
4911 paint.setColor(0xFFFF7777);
4912 paint.setStyle(SkPaint::kFill_Style);
4913 SkScalar x = textPosH[0];
4914 for (int i = 0; i < count; i+= 2) {
4915 canvas->drawRect({x, bounds[0], intervals[i], bounds[1]}, paint);
4916 x = intervals[i + 1];
4917 }
4918 canvas->drawRect({intervals[count - 1], bounds[0], 180, bounds[1]}, paint);
4919 }
4920 ##
4921
4922##
4923
4924
4925#Method int getTextBlobIntercepts(const SkTextBlob* blob, const SkScalar bounds[2],
4926 SkScalar* intervals) const
Cary Clarkab2621d2018-01-30 10:08:57 -05004927#In Text_Intercepts
4928#Line # returns where lines intersect Text_Blob; underlines ##
Cary Clark8032b982017-07-28 11:04:54 -04004929
4930 Returns the number of intervals that intersect bounds.
4931 bounds describes a pair of lines parallel to the text advance.
Cary Clarkce101242017-09-01 15:51:02 -04004932 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 -04004933 the string.
Cary Clark3cd22cc2017-12-01 11:49:58 -05004934 Uses Typeface to get the glyph paths,
Cary Clark8032b982017-07-28 11:04:54 -04004935 and Text_Size, Fake_Bold, and Path_Effect to scale and modify the glyph paths.
Cary Clarkce101242017-09-01 15:51:02 -04004936 Uses run array and Text_Align to position intervals.
Herb Derbyfcac00f2018-05-01 11:57:56 -04004937
Cary Clark3cd22cc2017-12-01 11:49:58 -05004938 Text_Encoding must be set to SkPaint::kGlyphID_TextEncoding.
4939
Cary Clark8032b982017-07-28 11:04:54 -04004940 Pass nullptr for intervals to determine the size of the interval array.
Herb Derbyfcac00f2018-05-01 11:57:56 -04004941
Cary Clark8032b982017-07-28 11:04:54 -04004942 intervals are cached to improve performance for multiple calls.
4943
Cary Clarkce101242017-09-01 15:51:02 -04004944 #Param blob Glyphs, positions, and text paint attributes ##
Cary Clark8032b982017-07-28 11:04:54 -04004945 #Param bounds lower and upper line parallel to the advance ##
4946 #Param intervals returned intersections; may be nullptr ##
4947
4948 #Return number of intersections; may be zero ##
4949
4950 #Example
4951 #Height 143
4952 void draw(SkCanvas* canvas) {
4953 SkPaint paint;
Cary Clark3cd22cc2017-12-01 11:49:58 -05004954 paint.setTextEncoding(SkPaint::kGlyphID_TextEncoding);
Cary Clark8032b982017-07-28 11:04:54 -04004955 paint.setTextSize(120);
4956 SkPoint textPos = { 20, 110 };
4957 int len = 3;
4958 SkTextBlobBuilder textBlobBuilder;
Herb Derbyfcac00f2018-05-01 11:57:56 -04004959 const SkTextBlobBuilder::RunBuffer& run =
Cary Clark8032b982017-07-28 11:04:54 -04004960 textBlobBuilder.allocRun(paint, len, textPos.fX, textPos.fY);
4961 run.glyphs[0] = 10;
4962 run.glyphs[1] = 20;
Herb Derbyfcac00f2018-05-01 11:57:56 -04004963 run.glyphs[2] = 30;
Cary Clark8032b982017-07-28 11:04:54 -04004964 sk_sp<const SkTextBlob> blob = textBlobBuilder.make();
4965 canvas->drawTextBlob(blob.get(), textPos.fX, textPos.fY, paint);
4966 SkScalar bounds[] = { 116, 134 };
4967 int count = paint.getTextBlobIntercepts(blob.get(), bounds, nullptr);
4968 std::vector<SkScalar> intervals;
4969 intervals.resize(count);
4970 (void) paint.getTextBlobIntercepts(blob.get(), bounds, &intervals.front());
4971 canvas->drawTextBlob(blob.get(), 0, 0, paint);
4972 paint.setColor(0xFFFF7777);
4973 SkScalar x = textPos.fX;
4974 for (int i = 0; i < count; i+= 2) {
4975 canvas->drawRect({x, bounds[0], intervals[i], bounds[1]}, paint);
4976 x = intervals[i + 1];
4977 }
4978 canvas->drawRect({intervals[count - 1], bounds[0], 180, bounds[1]}, paint);
4979 }
4980 ##
4981
4982##
4983
Cary Clark08895c42018-02-01 09:37:32 -05004984#Subtopic Text_Intercepts ##
Cary Clark8032b982017-07-28 11:04:54 -04004985# ------------------------------------------------------------------------------
4986
4987#Method bool nothingToDraw() const
Cary Clark78de7512018-02-07 07:27:09 -05004988#In Utility
Cary Clarkab2621d2018-01-30 10:08:57 -05004989#Line # returns true if Paint prevents all drawing ##
Cary Clark579985c2017-07-31 11:48:27 -04004990 Returns true if Paint prevents all drawing;
4991 otherwise, the Paint may or may not allow drawing.
Cary Clark8032b982017-07-28 11:04:54 -04004992
Cary Clarkce101242017-09-01 15:51:02 -04004993 Returns true if, for example, Blend_Mode combined with Color_Alpha computes a
4994 new Alpha of zero.
Cary Clark8032b982017-07-28 11:04:54 -04004995
4996 #Return true if Paint prevents all drawing ##
4997
4998 #Example
4999 void draw(SkCanvas* canvas) {
5000 auto debugster = [](const char* prefix, const SkPaint& p) -> void {
Herb Derbyfcac00f2018-05-01 11:57:56 -04005001 SkDebugf("%s nothing to draw: %s\n", prefix,
Cary Clark8032b982017-07-28 11:04:54 -04005002 p.nothingToDraw() ? "true" : "false");
5003 };
5004 SkPaint paint;
5005 debugster("initial", paint);
5006 paint.setBlendMode(SkBlendMode::kDst);
5007 debugster("blend dst", paint);
5008 paint.setBlendMode(SkBlendMode::kSrcOver);
5009 debugster("blend src over", paint);
5010 paint.setAlpha(0);
5011 debugster("alpha 0", paint);
5012 }
5013
5014 #StdOut
5015 initial nothing to draw: false
5016 blend dst nothing to draw: true
5017 blend src over nothing to draw: false
5018 alpha 0 nothing to draw: true
5019 #StdOut ##
5020 ##
5021
5022##
5023
5024# ------------------------------------------------------------------------------
Cary Clark08895c42018-02-01 09:37:32 -05005025#Subtopic Fast_Bounds
5026#Line # approximate area required by Paint ##
Herb Derbyfcac00f2018-05-01 11:57:56 -04005027 #Private
5028 To be made private.
Cary Clark8032b982017-07-28 11:04:54 -04005029 ##
5030
Cary Clark682c58d2018-05-16 07:07:07 -04005031Fast_Bounds functions conservatively outset a drawing bounds by additional area
Cary Clark8032b982017-07-28 11:04:54 -04005032Paint may draw to.
5033
5034#Method bool canComputeFastBounds() const
Herb Derbyfcac00f2018-05-01 11:57:56 -04005035
Cary Clarkab2621d2018-01-30 10:08:57 -05005036#In Fast_Bounds
Cary Clark1a8d7622018-03-05 13:26:16 -05005037#Line # returns true if settings allow for fast bounds computation ##
Herb Derbyfcac00f2018-05-01 11:57:56 -04005038 #Private
Cary Clark8032b982017-07-28 11:04:54 -04005039 (to be made private)
5040 ##
5041
5042 Returns true if Paint does not include elements requiring extensive computation
5043 to compute Device bounds of drawn geometry. For instance, Paint with Path_Effect
5044 always returns false.
5045
5046 #Return true if Paint allows for fast computation of bounds ##
5047##
5048
5049#Method const SkRect& computeFastBounds(const SkRect& orig, SkRect* storage) const
Herb Derbyfcac00f2018-05-01 11:57:56 -04005050
Cary Clarkab2621d2018-01-30 10:08:57 -05005051#In Fast_Bounds
Cary Clark1a8d7622018-03-05 13:26:16 -05005052#Line # returns fill bounds for quick reject tests ##
Herb Derbyfcac00f2018-05-01 11:57:56 -04005053 #Private
Cary Clark8032b982017-07-28 11:04:54 -04005054 (to be made private)
5055 ##
5056
5057 Only call this if canComputeFastBounds returned true. This takes a
5058 raw rectangle (the raw bounds of a shape), and adjusts it for stylistic
5059 effects in the paint (e.g. stroking). If needed, it uses the storage
Cary Clarkce101242017-09-01 15:51:02 -04005060 parameter. It returns the adjusted bounds that can then be used
Cary Clark8032b982017-07-28 11:04:54 -04005061 for SkCanvas::quickReject tests.
5062
Cary Clarkce101242017-09-01 15:51:02 -04005063 The returned Rect will either be orig or storage, thus the caller
Cary Clark8032b982017-07-28 11:04:54 -04005064 should not rely on storage being set to the result, but should always
Cary Clarkce101242017-09-01 15:51:02 -04005065 use the returned value. It is legal for orig and storage to be the same
5066 Rect.
Cary Clark8032b982017-07-28 11:04:54 -04005067
Herb Derbyfcac00f2018-05-01 11:57:56 -04005068 #Private
Cary Clark682c58d2018-05-16 07:07:07 -04005069 For example:
5070 if (!path.isInverseFillType() && paint.canComputeFastBounds()) {
5071 SkRect storage;
5072 if (canvas->quickReject(paint.computeFastBounds(path.getBounds(), &storage))) {
Cary Clark137b8742018-05-30 09:21:49 -04005073 return; // do not draw the path
Cary Clark682c58d2018-05-16 07:07:07 -04005074 }
Cary Clark8032b982017-07-28 11:04:54 -04005075 }
Cary Clark682c58d2018-05-16 07:07:07 -04005076 // draw the path
Cary Clark8032b982017-07-28 11:04:54 -04005077 ##
5078
5079 #Param orig geometry modified by Paint when drawn ##
5080 #Param storage computed bounds of geometry; may not be nullptr ##
5081
5082 #Return fast computed bounds ##
5083##
5084
5085#Method const SkRect& computeFastStrokeBounds(const SkRect& orig,
5086 SkRect* storage) const
Cary Clarkab2621d2018-01-30 10:08:57 -05005087#In Fast_Bounds
5088#Line # returns stroke bounds for quick reject tests ##
Herb Derbyfcac00f2018-05-01 11:57:56 -04005089 #Private
Cary Clark8032b982017-07-28 11:04:54 -04005090 (to be made private)
5091 ##
5092
5093 #Param orig geometry modified by Paint when drawn ##
5094 #Param storage computed bounds of geometry ##
5095
5096 #Return fast computed bounds ##
5097##
5098
5099#Method const SkRect& doComputeFastBounds(const SkRect& orig, SkRect* storage,
5100 Style style) const
Cary Clarkab2621d2018-01-30 10:08:57 -05005101#In Fast_Bounds
5102#Line # returns bounds for quick reject tests ##
Herb Derbyfcac00f2018-05-01 11:57:56 -04005103 #Private
Cary Clark8032b982017-07-28 11:04:54 -04005104 (to be made private)
5105 ##
5106
Cary Clarkce101242017-09-01 15:51:02 -04005107 Computes the bounds, overriding the Paint Style. This can be used to
5108 account for additional width required by stroking orig, without
5109 altering Style set to fill.
Cary Clark8032b982017-07-28 11:04:54 -04005110
5111 #Param orig geometry modified by Paint when drawn ##
5112 #Param storage computed bounds of geometry ##
5113 #Param style overrides Style ##
5114
5115 #Return fast computed bounds ##
5116##
5117
Cary Clark1a8d7622018-03-05 13:26:16 -05005118#Subtopic Fast_Bounds ##
Cary Clark8032b982017-07-28 11:04:54 -04005119
5120# ------------------------------------------------------------------------------
Cary Clark78de7512018-02-07 07:27:09 -05005121#Subtopic Utility
5122#Populate
5123#Line # rarely called management functions ##
5124##
Cary Clark8032b982017-07-28 11:04:54 -04005125
Cary Clark8032b982017-07-28 11:04:54 -04005126# ------------------------------------------------------------------------------
5127
5128#Class SkPaint ##
5129
5130#Topic Paint ##
Cary Clark4855f782018-02-06 09:41:53 -05005131