blob: 677d5c1da5c42b91cb8e0fba3711765a50ef992e [file] [log] [blame]
Cary Clark0c5f5462017-12-15 11:21:51 -05001#Topic Paint
Cary Clark12799e12017-07-28 15:18:29 -04002#Alias Paint_Reference
Cary Clark8032b982017-07-28 11:04:54 -04003
Cary Clark08895c42018-02-01 09:37:32 -05004#Subtopic Overview
Cary Clark4855f782018-02-06 09:41:53 -05005 #Subtopic Subtopic
Cary Clark08895c42018-02-01 09:37:32 -05006 #Populate
7 ##
8##
9
Cary Clarke4aa3712017-09-15 02:56:12 -040010#Class SkPaint
11
Cary Clark8032b982017-07-28 11:04:54 -040012Paint controls options applied when drawing and measuring. Paint collects all
13options outside of the Canvas_Clip and Canvas_Matrix.
14
Herb Derbyfcac00f2018-05-01 11:57:56 -040015Various options apply to text, strokes and fills, and images.
Cary Clark8032b982017-07-28 11:04:54 -040016
17Some options may not be implemented on all platforms; in these cases, setting
18the option has no effect. Some options are conveniences that duplicate Canvas
19functionality; for instance, text size is identical to matrix scale.
20
21Paint options are rarely exclusive; each option modifies a stage of the drawing
22pipeline and multiple pipeline stages may be affected by a single Paint.
23
Herb Derbyfcac00f2018-05-01 11:57:56 -040024Paint collects effects and filters that describe single-pass and multiple-pass
Cary Clark8032b982017-07-28 11:04:54 -040025algorithms that alter the drawing geometry, color, and transparency. For instance,
Herb Derbyfcac00f2018-05-01 11:57:56 -040026Paint does not directly implement dashing or blur, but contains the objects that do so.
Cary Clark8032b982017-07-28 11:04:54 -040027
28The objects contained by Paint are opaque, and cannot be edited outside of the Paint
29to affect it. The implementation is free to defer computations associated with the
30Paint, or ignore them altogether. For instance, some GPU implementations draw all
Herb Derbyfcac00f2018-05-01 11:57:56 -040031Path geometries with Anti-aliasing, regardless of how SkPaint::kAntiAlias_Flag
Cary Clarkbad5ad72017-08-03 17:14:08 -040032is set in Paint.
Cary Clark8032b982017-07-28 11:04:54 -040033
34Paint describes a single color, a single font, a single image quality, and so on.
35Multiple colors are drawn either by using multiple paints or with objects like
36Shader attached to Paint.
37
Cary Clark4855f782018-02-06 09:41:53 -050038#Subtopic Related_Function
Cary Clark08895c42018-02-01 09:37:32 -050039#Populate
40##
Cary Clark8032b982017-07-28 11:04:54 -040041
Cary Clark4855f782018-02-06 09:41:53 -050042#Subtopic Constant
Cary Clark08895c42018-02-01 09:37:32 -050043#Populate
44##
Cary Clark8032b982017-07-28 11:04:54 -040045
Cary Clark4855f782018-02-06 09:41:53 -050046#Subtopic Class_or_Struct
Cary Clark08895c42018-02-01 09:37:32 -050047#Populate
48##
Cary Clark8032b982017-07-28 11:04:54 -040049
Cary Clark4855f782018-02-06 09:41:53 -050050#Subtopic Constructor
Cary Clark08895c42018-02-01 09:37:32 -050051#Populate
52##
Cary Clark8032b982017-07-28 11:04:54 -040053
Cary Clark4855f782018-02-06 09:41:53 -050054#Subtopic Operator
Cary Clark08895c42018-02-01 09:37:32 -050055#Populate
56##
Cary Clark8032b982017-07-28 11:04:54 -040057
Cary Clark4855f782018-02-06 09:41:53 -050058#Subtopic Member_Function
Cary Clark08895c42018-02-01 09:37:32 -050059#Populate
60##
Cary Clark8032b982017-07-28 11:04:54 -040061
62# ------------------------------------------------------------------------------
Cary Clark08895c42018-02-01 09:37:32 -050063#Subtopic Initializers
64#Line # constructors and initialization ##
Cary Clark8032b982017-07-28 11:04:54 -040065
66#Method SkPaint()
67
Cary Clarkab2621d2018-01-30 10:08:57 -050068#In Initializers
69#Line # constructs with default values ##
Cary Clark8032b982017-07-28 11:04:54 -040070Constructs Paint with default values.
71
72#Table
73#Legend
74# attribute # default value ##
75#Legend ##
76# Anti-alias # false ##
Cary Clarkce101242017-09-01 15:51:02 -040077# Blend_Mode # SkBlendMode::kSrcOver ##
Cary Clark8032b982017-07-28 11:04:54 -040078# Color # SK_ColorBLACK ##
79# Color_Alpha # 255 ##
80# Color_Filter # nullptr ##
81# Dither # false ##
82# Draw_Looper # nullptr ##
83# Fake_Bold # false ##
84# Filter_Quality # kNone_SkFilterQuality ##
85# Font_Embedded_Bitmaps # false ##
86# Automatic_Hinting # false ##
87# Full_Hinting_Spacing # false ##
88# Hinting # kNormal_Hinting ##
89# Image_Filter # nullptr ##
90# LCD_Text # false ##
91# Linear_Text # false ##
92# Miter_Limit # 4 ##
93# Mask_Filter # nullptr ##
94# Path_Effect # nullptr ##
Cary Clark8032b982017-07-28 11:04:54 -040095# Shader # nullptr ##
96# Style # kFill_Style ##
97# Text_Align # kLeft_Align ##
98# Text_Encoding # kUTF8_TextEncoding ##
99# Text_Scale_X # 1 ##
100# Text_Size # 12 ##
101# Text_Skew_X # 0 ##
102# Typeface # nullptr ##
103# Stroke_Cap # kButt_Cap ##
104# Stroke_Join # kMiter_Join ##
105# Stroke_Width # 0 ##
106# Subpixel_Text # false ##
107# Vertical_Text # false ##
108#Table ##
109
110The flags, text size, hinting, and miter limit may be overridden at compile time by defining
Herb Derbyfcac00f2018-05-01 11:57:56 -0400111paint default values. The overrides may be included in "SkUserConfig.h" or predefined by the
Cary Clark8032b982017-07-28 11:04:54 -0400112build system.
113
114#Return default initialized Paint ##
115
116#Example
117#ToDo mark this as no output ##
118#Height 1
119###$ $ redefine markup character so preprocessor commands appear normally
120#ifndef SkUserConfig_DEFINED
121#define SkUserConfig_DEFINED
122
123#define SkPaintDefaults_Flags 0x01 // always enable antialiasing
124#define SkPaintDefaults_TextSize 24.f // double default font size
125#define SkPaintDefaults_Hinting 3 // use full hinting
126#define SkPaintDefaults_MiterLimit 10.f // use HTML Canvas miter limit setting
127
128#endif
129$$$# # restore original markup character
130##
131
132
133##
134
135#Method SkPaint(const SkPaint& paint)
136
Cary Clarkab2621d2018-01-30 10:08:57 -0500137#In Initializers
138#Line # makes a shallow copy ##
Cary Clark8032b982017-07-28 11:04:54 -0400139Makes a shallow copy of Paint. Typeface, Path_Effect, Shader,
Mike Reed8ad91a92018-01-19 19:09:32 -0500140Mask_Filter, Color_Filter, Draw_Looper, and Image_Filter are shared
Cary Clarkbad5ad72017-08-03 17:14:08 -0400141between the original paint and the copy. Objects containing Reference_Count increment
142their references by one.
Cary Clark8032b982017-07-28 11:04:54 -0400143
Mike Reed8ad91a92018-01-19 19:09:32 -0500144The referenced objects Path_Effect, Shader, Mask_Filter, Color_Filter,
Cary Clark8032b982017-07-28 11:04:54 -0400145Draw_Looper, and Image_Filter cannot be modified after they are created.
146This prevents objects with Reference_Count from being modified once Paint refers to them.
147
148#Param paint original to copy ##
149
150#Return shallow copy of paint ##
151
152#Example
153#ToDo why is this double-spaced on Fiddle? ##
154 SkPaint paint1;
155 paint1.setColor(SK_ColorRED);
156 SkPaint paint2(paint1);
157 paint2.setColor(SK_ColorBLUE);
158 SkDebugf("SK_ColorRED %c= paint1.getColor()\n", SK_ColorRED == paint1.getColor() ? '=' : '!');
159 SkDebugf("SK_ColorBLUE %c= paint2.getColor()\n", SK_ColorBLUE == paint2.getColor() ? '=' : '!');
160
161 #StdOut
162 SK_ColorRED == paint1.getColor()
163 SK_ColorBLUE == paint2.getColor()
164 ##
165##
166
167##
168
169#Method SkPaint(SkPaint&& paint)
170
Cary Clarkab2621d2018-01-30 10:08:57 -0500171#In Initializers
172#Line # moves paint without copying it ##
Cary Clarkd0530ba2017-09-14 11:25:39 -0400173 Implements a move constructor to avoid increasing the reference counts
Cary Clark8032b982017-07-28 11:04:54 -0400174 of objects referenced by the paint.
175
176 After the call, paint is undefined, and can be safely destructed.
177
178 #Param paint original to move ##
179
180 #Return content of paint ##
181
182 #Example
183 SkPaint paint;
184 float intervals[] = { 5, 5 };
185 paint.setPathEffect(SkDashPathEffect::Make(intervals, SK_ARRAY_COUNT(intervals), 2.5f));
186 SkPaint dashed(std::move(paint));
187 SkDebugf("path effect unique: %s\n", dashed.getPathEffect()->unique() ? "true" : "false");
188
189 #StdOut
190 path effect unique: true
191 ##
192 ##
193
194##
195
196# ------------------------------------------------------------------------------
197
198#Method void reset()
199
Cary Clarkab2621d2018-01-30 10:08:57 -0500200#In Initializers
201#Line # sets to default values ##
Cary Clarkbc5697d2017-10-04 14:31:33 -0400202Sets all Paint contents to their initial values. This is equivalent to replacing
203Paint with the result of SkPaint().
Cary Clark8032b982017-07-28 11:04:54 -0400204
205#Example
206 SkPaint paint1, paint2;
207 paint1.setColor(SK_ColorRED);
208 paint1.reset();
209 SkDebugf("paint1 %c= paint2", paint1 == paint2 ? '=' : '!');
210
211 #StdOut
212 paint1 == paint2
213 ##
214##
215
216##
217
Cary Clark08895c42018-02-01 09:37:32 -0500218#Subtopic Initializers ##
Cary Clark8032b982017-07-28 11:04:54 -0400219
220# ------------------------------------------------------------------------------
Cary Clark8032b982017-07-28 11:04:54 -0400221
222#Method ~SkPaint()
223
Cary Clarkab2621d2018-01-30 10:08:57 -0500224#Line # decreases Reference_Count of owned objects ##
Cary Clark8032b982017-07-28 11:04:54 -0400225Decreases Paint Reference_Count of owned objects: Typeface, Path_Effect, Shader,
Mike Reed8ad91a92018-01-19 19:09:32 -0500226Mask_Filter, Color_Filter, Draw_Looper, and Image_Filter. If the
Cary Clarkbad5ad72017-08-03 17:14:08 -0400227objects containing Reference_Count go to zero, they are deleted.
Cary Clark8032b982017-07-28 11:04:54 -0400228
Herb Derbyfcac00f2018-05-01 11:57:56 -0400229#NoExample
Cary Clark8032b982017-07-28 11:04:54 -0400230##
231
232##
233
Cary Clark08895c42018-02-01 09:37:32 -0500234
Cary Clark8032b982017-07-28 11:04:54 -0400235# ------------------------------------------------------------------------------
Cary Clark08895c42018-02-01 09:37:32 -0500236#Subtopic Management
237#Line # paint copying, moving, comparing ##
Cary Clark8032b982017-07-28 11:04:54 -0400238
239#Method SkPaint& operator=(const SkPaint& paint)
240
Cary Clarkab2621d2018-01-30 10:08:57 -0500241#In Management
242#Line # makes a shallow copy ##
Cary Clark8032b982017-07-28 11:04:54 -0400243Makes a shallow copy of Paint. Typeface, Path_Effect, Shader,
Mike Reed8ad91a92018-01-19 19:09:32 -0500244Mask_Filter, Color_Filter, Draw_Looper, and Image_Filter are shared
Cary Clarkbad5ad72017-08-03 17:14:08 -0400245between the original paint and the copy. Objects containing Reference_Count in the
Cary Clark8032b982017-07-28 11:04:54 -0400246prior destination are decreased by one, and the referenced objects are deleted if the
Cary Clarkbad5ad72017-08-03 17:14:08 -0400247resulting count is zero. Objects containing Reference_Count in the parameter paint
248are increased by one. paint is unmodified.
Cary Clark8032b982017-07-28 11:04:54 -0400249
250#Param paint original to copy ##
251
252#Return content of paint ##
253
254#Example
255 SkPaint paint1, paint2;
256 paint1.setColor(SK_ColorRED);
257 paint2 = paint1;
258 SkDebugf("SK_ColorRED %c= paint1.getColor()\n", SK_ColorRED == paint1.getColor() ? '=' : '!');
259 SkDebugf("SK_ColorRED %c= paint2.getColor()\n", SK_ColorRED == paint2.getColor() ? '=' : '!');
260
261 #StdOut
262 SK_ColorRED == paint1.getColor()
263 SK_ColorRED == paint2.getColor()
264 ##
265##
266
267##
268
269# ------------------------------------------------------------------------------
270
271#Method SkPaint& operator=(SkPaint&& paint)
272
Cary Clarkab2621d2018-01-30 10:08:57 -0500273#In Management
274#Line # moves paint without copying it ##
Cary Clarkd0530ba2017-09-14 11:25:39 -0400275Moves the paint to avoid increasing the reference counts
Cary Clarkbad5ad72017-08-03 17:14:08 -0400276of objects referenced by the paint parameter. Objects containing Reference_Count in the
277prior destination are decreased by one; those objects are deleted if the resulting count
278is zero.
Cary Clark8032b982017-07-28 11:04:54 -0400279
280After the call, paint is undefined, and can be safely destructed.
281
282 #Param paint original to move ##
283
284 #Return content of paint ##
285
286#Example
287 SkPaint paint1, paint2;
288 paint1.setColor(SK_ColorRED);
289 paint2 = std::move(paint1);
290 SkDebugf("SK_ColorRED == paint2.getColor()\n", SK_ColorRED == paint2.getColor() ? '=' : '!');
291
292 #StdOut
293 SK_ColorRED == paint2.getColor()
294 ##
295##
296
297##
298
299# ------------------------------------------------------------------------------
300
301#Method bool operator==(const SkPaint& a, const SkPaint& b)
302
Cary Clarkab2621d2018-01-30 10:08:57 -0500303#In Management
304#Line # compares paints for equality ##
Cary Clark8032b982017-07-28 11:04:54 -0400305 Compares a and b, and returns true if a and b are equivalent. May return false
Mike Reed8ad91a92018-01-19 19:09:32 -0500306 if Typeface, Path_Effect, Shader, Mask_Filter, Color_Filter,
Cary Clark8032b982017-07-28 11:04:54 -0400307 Draw_Looper, or Image_Filter have identical contents but different pointers.
308
309 #Param a Paint to compare ##
310 #Param b Paint to compare ##
311
312 #Return true if Paint pair are equivalent ##
313
314 #Example
315 SkPaint paint1, paint2;
316 paint1.setColor(SK_ColorRED);
317 paint2.setColor(0xFFFF0000);
318 SkDebugf("paint1 %c= paint2\n", paint1 == paint2 ? '=' : '!');
319 float intervals[] = { 5, 5 };
320 paint1.setPathEffect(SkDashPathEffect::Make(intervals, 2, 2.5f));
321 paint2.setPathEffect(SkDashPathEffect::Make(intervals, 2, 2.5f));
322 SkDebugf("paint1 %c= paint2\n", paint1 == paint2 ? '=' : '!');
323
324 #StdOut
325 paint1 == paint2
326 paint1 != paint2
327 ##
328 ##
Cary Clark06c20f32018-03-20 15:53:27 -0400329#SeeAlso operator!=(const SkPaint& a, const SkPaint& b)
Cary Clark8032b982017-07-28 11:04:54 -0400330##
331
332# ------------------------------------------------------------------------------
333
334#Method bool operator!=(const SkPaint& a, const SkPaint& b)
335
Cary Clarkab2621d2018-01-30 10:08:57 -0500336#In Management
337#Line # compares paints for inequality ##
Cary Clark8032b982017-07-28 11:04:54 -0400338 Compares a and b, and returns true if a and b are not equivalent. May return true
Mike Reed8ad91a92018-01-19 19:09:32 -0500339 if Typeface, Path_Effect, Shader, Mask_Filter, Color_Filter,
Cary Clark8032b982017-07-28 11:04:54 -0400340 Draw_Looper, or Image_Filter have identical contents but different pointers.
341
342 #Param a Paint to compare ##
343 #Param b Paint to compare ##
344
345 #Return true if Paint pair are not equivalent ##
346
347#Example
348 SkPaint paint1, paint2;
349 paint1.setColor(SK_ColorRED);
350 paint2.setColor(0xFFFF0000);
351 SkDebugf("paint1 %c= paint2\n", paint1 == paint2 ? '=' : '!');
352 SkDebugf("paint1 %c= paint2\n", paint1 != paint2 ? '!' : '=');
353
354 #StdOut
355 paint1 == paint2
356 paint1 == paint2
357 ##
358##
Cary Clark06c20f32018-03-20 15:53:27 -0400359#SeeAlso operator==(const SkPaint& a, const SkPaint& b)
Cary Clark8032b982017-07-28 11:04:54 -0400360##
361
362# ------------------------------------------------------------------------------
363
364#Method uint32_t getHash() const
365
Cary Clarkab2621d2018-01-30 10:08:57 -0500366#In Management
367#Line # returns a shallow hash for equality checks ##
Cary Clark8032b982017-07-28 11:04:54 -0400368Returns a hash generated from Paint values and pointers.
369Identical hashes guarantee that the paints are
370equivalent, but differing hashes do not guarantee that the paints have differing
371contents.
372
373If operator==(const SkPaint& a, const SkPaint& b) returns true for two paints,
374their hashes are also equal.
375
376The hash returned is platform and implementation specific.
377
378#Return a shallow hash ##
379
380#Example
381 SkPaint paint1, paint2;
382 paint1.setColor(SK_ColorRED);
383 paint2.setColor(0xFFFF0000);
384 SkDebugf("paint1 %c= paint2\n", paint1 == paint2 ? '=' : '!');
385 SkDebugf("paint1.getHash() %c= paint2.getHash()\n",
386 paint1.getHash() == paint2.getHash() ? '=' : '!');
387
388 #StdOut
389 paint1 == paint2
390 paint1.getHash() == paint2.getHash()
391 ##
392##
393
394##
395
Cary Clark08895c42018-02-01 09:37:32 -0500396#Subtopic Management ##
Cary Clark8032b982017-07-28 11:04:54 -0400397
398# ------------------------------------------------------------------------------
Cary Clark08895c42018-02-01 09:37:32 -0500399#Subtopic Hinting
400#Line # glyph outline adjustment ##
Cary Clark8032b982017-07-28 11:04:54 -0400401
402#Enum Hinting
Cary Clark08895c42018-02-01 09:37:32 -0500403#Line # level of glyph outline adjustment ##
Cary Clark8032b982017-07-28 11:04:54 -0400404
405#Code
406 enum Hinting {
407 kNo_Hinting = 0,
408 kSlight_Hinting = 1,
409 kNormal_Hinting = 2,
Cary Clarkbad5ad72017-08-03 17:14:08 -0400410 kFull_Hinting = 3,
Cary Clark8032b982017-07-28 11:04:54 -0400411 };
412##
413
414Hinting adjusts the glyph outlines so that the shape provides a uniform
415look at a given point size on font engines that support it. Hinting may have a
416muted effect or no effect at all depending on the platform.
417
418The four levels roughly control corresponding features on platforms that use FreeType
419as the Font_Engine.
420
421#Const kNo_Hinting 0
422 Leaves glyph outlines unchanged from their native representation.
423 With FreeType, this is equivalent to the FT_LOAD_NO_HINTING
424 bit-field constant supplied to FT_Load_Glyph, which indicates that the vector
425 outline being loaded should not be fitted to the pixel grid but simply scaled
426 to 26.6 fractional pixels.
427##
428#Const kSlight_Hinting 1
429 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
436 Modifies glyph outlines to improve constrast. This is the default.
Cary Clark6fc50412017-09-21 12:31:06 -0400437 With FreeType, this supplies FT_LOAD_TARGET_NORMAL to FT_Load_Glyph,
Herb Derbyfcac00f2018-05-01 11:57:56 -0400438 choosing the default hinting algorithm, which is optimized for standard
439 gray-level rendering.
Cary Clark8032b982017-07-28 11:04:54 -0400440##
441#Const kFull_Hinting 3
Cary Clark6fc50412017-09-21 12:31:06 -0400442 Modifies glyph outlines for maxiumum constrast. With FreeType, this selects
Herb Derbyfcac00f2018-05-01 11:57:56 -0400443 FT_LOAD_TARGET_LCD or FT_LOAD_TARGET_LCD_V if kLCDRenderText_Flag is set.
444 FT_LOAD_TARGET_LCD is a variant of FT_LOAD_TARGET_NORMAL optimized for
445 horizontally decimated LCD displays; FT_LOAD_TARGET_LCD_V is a
Cary Clark8032b982017-07-28 11:04:54 -0400446 variant of FT_LOAD_TARGET_NORMAL optimized for vertically decimated LCD displays.
447##
448
449#Track
450#File SkFontHost_mac.cpp:1777,1806
451#Time 2013-03-03 07:16:29 +0000
Cary Clark4855f782018-02-06 09:41:53 -0500452#Bug 915
Cary Clark8032b982017-07-28 11:04:54 -0400453On OS_X and iOS, hinting controls whether Core_Graphics dilates the font outlines
454to account for LCD text. No hinting uses Core_Text gray scale output.
455Normal hinting uses Core_Text LCD output. If kLCDRenderText_Flag is clear,
456the LCD output is reduced to a single grayscale channel.
457#Track ##
458
459On Windows with DirectWrite, Hinting has no effect.
460
461Hinting defaults to kNormal_Hinting.
462Set SkPaintDefaults_Hinting at compile time to change the default setting.
463
464#ToDo add an illustration? linux running GM:typefacerendering is best for this
465 the hinting variations are every other character horizontally
466#ToDo ##
467
468#Enum ##
469
470#Method Hinting getHinting() const
471
Cary Clarkab2621d2018-01-30 10:08:57 -0500472#In Hinting
473#Line # returns Hinting, glyph outline adjustment level ##
Cary Clark8032b982017-07-28 11:04:54 -0400474 Returns level of glyph outline adjustment.
475
476 #Return one of: kNo_Hinting, kSlight_Hinting, kNormal_Hinting, kFull_Hinting ##
477
478 #Example
479 SkPaint paint;
480 SkDebugf("SkPaint::kNormal_Hinting %c= paint.getHinting()\n",
481 SkPaint::kNormal_Hinting == paint.getHinting() ? '=' : ':');
482
483 #StdOut
484 SkPaint::kNormal_Hinting == paint.getHinting()
485 ##
486 ##
487##
488
489#Method void setHinting(Hinting hintingLevel)
490
Cary Clarkab2621d2018-01-30 10:08:57 -0500491#In Hinting
492#Line # sets Hinting, glyph outline adjustment level ##
Cary Clark8032b982017-07-28 11:04:54 -0400493 Sets level of glyph outline adjustment.
494 Does not check for valid values of hintingLevel.
495
496 #Table
497 #Legend
498 # Hinting # value # effect on generated glyph outlines ##
499 ##
500 # kNo_Hinting # 0 # leaves glyph outlines unchanged from their native representation ##
Cary Clarkce101242017-09-01 15:51:02 -0400501 # kSlight_Hinting # 1 # modifies glyph outlines minimally to improve contrast ##
502 # kNormal_Hinting # 2 # modifies glyph outlines to improve contrast ##
Herb Derbyfcac00f2018-05-01 11:57:56 -0400503 # kFull_Hinting # 3 # modifies glyph outlines for maximum contrast ##
Cary Clark8032b982017-07-28 11:04:54 -0400504 ##
505
506 #Param hintingLevel one of: kNo_Hinting, kSlight_Hinting, kNormal_Hinting, kFull_Hinting ##
507
508 #Example
509 SkPaint paint1, paint2;
510 paint2.setHinting(SkPaint::kNormal_Hinting);
511 SkDebugf("paint1 %c= paint2\n", paint1 == paint2 ? '=' : ':');
512
513 #StdOut
514 paint1 == paint2
515 ##
516 ##
517##
518
Cary Clark08895c42018-02-01 09:37:32 -0500519#Subtopic Hinting ##
Cary Clark8032b982017-07-28 11:04:54 -0400520# ------------------------------------------------------------------------------
Cary Clark08895c42018-02-01 09:37:32 -0500521#Subtopic Flags
522#Line # attributes represented by single bits ##
Cary Clark8032b982017-07-28 11:04:54 -0400523
524#Enum Flags
Cary Clark08895c42018-02-01 09:37:32 -0500525#Line # values described by bits and masks ##
Cary Clark8032b982017-07-28 11:04:54 -0400526
527#Code
528 enum Flags {
529 kAntiAlias_Flag = 0x01,
530 kDither_Flag = 0x04,
531 kFakeBoldText_Flag = 0x20,
532 kLinearText_Flag = 0x40,
533 kSubpixelText_Flag = 0x80,
534 kDevKernText_Flag = 0x100,
535 kLCDRenderText_Flag = 0x200,
536 kEmbeddedBitmapText_Flag = 0x400,
537 kAutoHinting_Flag = 0x800,
538 kVerticalText_Flag = 0x1000,
Cary Clark8032b982017-07-28 11:04:54 -0400539
540 kAllFlags = 0xFFFF,
541 };
542
543##
544
545The bit values stored in Flags.
546The default value for Flags, normally zero, can be changed at compile time
547with a custom definition of SkPaintDefaults_Flags.
548All flags can be read and written explicitly; Flags allows manipulating
549multiple settings at once.
550
Herb Derbyfcac00f2018-05-01 11:57:56 -0400551 #Const kAntiAlias_Flag 0x0001
Cary Clark8032b982017-07-28 11:04:54 -0400552 mask for setting Anti-alias
553 ##
554 #Const kDither_Flag 0x0004
555 mask for setting Dither
556 ##
557
558 #Const kFakeBoldText_Flag 0x0020
559 mask for setting Fake_Bold
560 ##
561 #Const kLinearText_Flag 0x0040
562 mask for setting Linear_Text
563 ##
564 #Const kSubpixelText_Flag 0x0080
Herb Derbyfcac00f2018-05-01 11:57:56 -0400565 mask for setting Subpixel_Text
Cary Clark8032b982017-07-28 11:04:54 -0400566 ##
567 #Const kDevKernText_Flag 0x0100
Herb Derbyfcac00f2018-05-01 11:57:56 -0400568 #Deprecated
Cary Clark8032b982017-07-28 11:04:54 -0400569 ##
570 #Const kLCDRenderText_Flag 0x0200
571 mask for setting LCD_Text
572 ##
573 #Const kEmbeddedBitmapText_Flag 0x0400
Herb Derbyfcac00f2018-05-01 11:57:56 -0400574 mask for setting Font_Embedded_Bitmaps
Cary Clark8032b982017-07-28 11:04:54 -0400575 ##
576 #Const kAutoHinting_Flag 0x0800
577 mask for setting Automatic_Hinting
578 ##
579 #Const kVerticalText_Flag 0x1000
580 mask for setting Vertical_Text
581 ##
Cary Clark8032b982017-07-28 11:04:54 -0400582 #Const kAllFlags 0xFFFF
583 mask of all Flags, including private flags and flags reserved for future use
584 ##
585
586Flags default to all flags clear, disabling the associated feature.
587
588#Enum ##
589
590#Enum ReserveFlags
Cary Clark4855f782018-02-06 09:41:53 -0500591#Deprecated soon
Cary Clark8032b982017-07-28 11:04:54 -0400592
Cary Clark4855f782018-02-06 09:41:53 -0500593Only valid for Android framework.
Cary Clark8032b982017-07-28 11:04:54 -0400594
595#Code
596 enum ReserveFlags {
597 kUnderlineText_ReserveFlag = 0x08,
598 kStrikeThruText_ReserveFlag = 0x10,
599 };
600##
601
Cary Clark4855f782018-02-06 09:41:53 -0500602#Const kUnderlineText_ReserveFlag 0x0008
603#Deprecated soon
604##
605#Const kStrikeThruText_ReserveFlag 0x0010
606#Deprecated soon
607##
608##
Cary Clark8032b982017-07-28 11:04:54 -0400609
610#Method uint32_t getFlags() const
611
Cary Clarkab2621d2018-01-30 10:08:57 -0500612#In Flags
613#Line # returns Flags stored in a bit field ##
Cary Clark8032b982017-07-28 11:04:54 -0400614Returns paint settings described by Flags. Each setting uses one
615bit, and can be tested with Flags members.
616
617#Return zero, one, or more bits described by Flags ##
618
619#Example
620 SkPaint paint;
621 paint.setAntiAlias(true);
622 SkDebugf("(SkPaint::kAntiAlias_Flag & paint.getFlags()) %c= 0\n",
623 SkPaint::kAntiAlias_Flag & paint.getFlags() ? '!' : '=');
624
625 #StdOut
626 (SkPaint::kAntiAlias_Flag & paint.getFlags()) != 0
627 ##
628##
629
630##
631
632#Method void setFlags(uint32_t flags)
633
Cary Clarkab2621d2018-01-30 10:08:57 -0500634#In Flags
635#Line # sets multiple Flags in a bit field ##
Cary Clark8032b982017-07-28 11:04:54 -0400636Replaces Flags with flags, the union of the Flags members.
637All Flags members may be cleared, or one or more may be set.
638
639#Param flags union of Flags for Paint ##
640
641#Example
642 SkPaint paint;
643 paint.setFlags((uint32_t) (SkPaint::kAntiAlias_Flag | SkPaint::kDither_Flag));
644 SkDebugf("paint.isAntiAlias()\n", paint.isAntiAlias() ? '!' : '=');
645 SkDebugf("paint.isDither()\n", paint.isDither() ? '!' : '=');
646
647 #StdOut
648 paint.isAntiAlias()
649 paint.isDither()
650 ##
651##
652
653##
654
Cary Clark08895c42018-02-01 09:37:32 -0500655#Subtopic Flags ##
Cary Clark8032b982017-07-28 11:04:54 -0400656# ------------------------------------------------------------------------------
Cary Clark08895c42018-02-01 09:37:32 -0500657#Subtopic Anti-alias
Cary Clark8032b982017-07-28 11:04:54 -0400658#Alias Anti-alias # permit hyphen in topic name, should probably not substitute hyphen with _
Cary Clark4855f782018-02-06 09:41:53 -0500659#In Related_Function
Cary Clarkab2621d2018-01-30 10:08:57 -0500660#Line # approximating coverage with transparency ##
Cary Clark8032b982017-07-28 11:04:54 -0400661
662Anti-alias drawing approximates partial pixel coverage with transparency.
663If kAntiAlias_Flag is clear, pixel centers contained by the shape edge are drawn opaque.
664If kAntiAlias_Flag is set, pixels are drawn with Color_Alpha equal to their coverage.
665
Herb Derbyfcac00f2018-05-01 11:57:56 -0400666The rule for Aliased pixels is inconsistent across platforms. A shape edge
Cary Clark8032b982017-07-28 11:04:54 -0400667passing through the pixel center may, but is not required to, draw the pixel.
668
Cary Clarkce101242017-09-01 15:51:02 -0400669Raster_Engine draws Aliased pixels whose centers are on or to the right of the start of an
Cary Clark8032b982017-07-28 11:04:54 -0400670active Path edge, and whose center is to the left of the end of the active Path edge.
671
672#ToDo add illustration of raster pixels ##
673
Cary Clarkce101242017-09-01 15:51:02 -0400674A platform may only support Anti-aliased drawing. Some GPU-backed platforms use
675Supersampling to Anti-alias all drawing, and have no mechanism to selectively
676Alias.
Cary Clark8032b982017-07-28 11:04:54 -0400677
Cary Clarkce101242017-09-01 15:51:02 -0400678The amount of coverage computed for Anti-aliased pixels also varies across platforms.
Cary Clark8032b982017-07-28 11:04:54 -0400679
680Anti-alias is disabled by default.
681Anti-alias can be enabled by default by setting SkPaintDefaults_Flags to kAntiAlias_Flag
682at compile time.
683
Cary Clarkab2621d2018-01-30 10:08:57 -0500684#Example
Cary Clark8032b982017-07-28 11:04:54 -0400685 #Width 512
686 #Description
687 A red line is drawn with transparency on the edges to make it look smoother.
688 A blue line draws only where the pixel centers are contained.
Cary Clarkce101242017-09-01 15:51:02 -0400689 The lines are drawn into Bitmap, then drawn magnified to make the
690 Aliasing easier to see.
Cary Clark8032b982017-07-28 11:04:54 -0400691 ##
692
693 void draw(SkCanvas* canvas) {
694 SkBitmap bitmap;
695 bitmap.allocN32Pixels(50, 50);
696 SkCanvas offscreen(bitmap);
697 SkPaint paint;
698 paint.setStyle(SkPaint::kStroke_Style);
699 paint.setStrokeWidth(10);
700 for (bool antialias : { false, true }) {
701 paint.setColor(antialias ? SK_ColorRED : SK_ColorBLUE);
702 paint.setAntiAlias(antialias);
703 bitmap.eraseColor(0);
704 offscreen.drawLine(5, 5, 15, 30, paint);
705 canvas->drawLine(5, 5, 15, 30, paint);
706 canvas->save();
707 canvas->scale(10, 10);
708 canvas->drawBitmap(bitmap, antialias ? 12 : 0, 0);
709 canvas->restore();
710 canvas->translate(15, 0);
711 }
712 }
Cary Clarkab2621d2018-01-30 10:08:57 -0500713##
Cary Clark8032b982017-07-28 11:04:54 -0400714
715#Method bool isAntiAlias() const
Cary Clark78de7512018-02-07 07:27:09 -0500716#In Anti_alias
Cary Clarkab2621d2018-01-30 10:08:57 -0500717#Line # returns true if Anti-alias is set ##
Cary Clark8032b982017-07-28 11:04:54 -0400718
719 If true, pixels on the active edges of Path may be drawn with partial transparency.
720
721 Equivalent to getFlags masked with kAntiAlias_Flag.
722
723 #Return kAntiAlias_Flag state ##
724
725 #Example
726 SkPaint paint;
727 SkDebugf("paint.isAntiAlias() %c= !!(paint.getFlags() & SkPaint::kAntiAlias_Flag)\n",
728 paint.isAntiAlias() == !!(paint.getFlags() & SkPaint::kAntiAlias_Flag) ? '=' : '!');
729 paint.setAntiAlias(true);
730 SkDebugf("paint.isAntiAlias() %c= !!(paint.getFlags() & SkPaint::kAntiAlias_Flag)\n",
731 paint.isAntiAlias() == !!(paint.getFlags() & SkPaint::kAntiAlias_Flag) ? '=' : '!');
732
733 #StdOut
734 paint.isAntiAlias() == !!(paint.getFlags() & SkPaint::kAntiAlias_Flag)
735 paint.isAntiAlias() == !!(paint.getFlags() & SkPaint::kAntiAlias_Flag)
736 ##
737 ##
738##
739
740#Method void setAntiAlias(bool aa)
741
Cary Clark78de7512018-02-07 07:27:09 -0500742#In Anti_alias
Cary Clarkab2621d2018-01-30 10:08:57 -0500743#Line # sets or clears Anti-alias ##
Cary Clark8032b982017-07-28 11:04:54 -0400744 Requests, but does not require, that Path edge pixels draw opaque or with
745 partial transparency.
746
747 Sets kAntiAlias_Flag if aa is true.
748 Clears kAntiAlias_Flag if aa is false.
749
750 #Param aa setting for kAntiAlias_Flag ##
751
752 #Example
753 SkPaint paint1, paint2;
754 paint1.setAntiAlias(true);
755 paint2.setFlags(paint2.getFlags() | SkPaint::kAntiAlias_Flag);
756 SkDebugf("paint1 %c= paint2\n", paint1 == paint2 ? '=' : '!');
757
758 #StdOut
759 paint1 == paint2
760 ##
761 ##
762
763##
764
Cary Clarkf895a422018-02-27 09:54:21 -0500765#Subtopic Anti-alias ##
Cary Clark8032b982017-07-28 11:04:54 -0400766# ------------------------------------------------------------------------------
Cary Clark08895c42018-02-01 09:37:32 -0500767#Subtopic Dither
768#Line # distributing color error ##
Cary Clark8032b982017-07-28 11:04:54 -0400769
Herb Derbyfcac00f2018-05-01 11:57:56 -0400770Dither increases fidelity by adjusting the color of adjacent pixels.
Cary Clark8032b982017-07-28 11:04:54 -0400771This can help to smooth color transitions and reducing banding in gradients.
772Dithering lessens visible banding from kRGB_565_SkColorType
Herb Derbyfcac00f2018-05-01 11:57:56 -0400773and kRGBA_8888_SkColorType gradients,
Cary Clark8032b982017-07-28 11:04:54 -0400774and improves rendering into a kRGB_565_SkColorType Surface.
775
776Dithering is always enabled for linear gradients drawing into
777kRGB_565_SkColorType Surface and kRGBA_8888_SkColorType Surface.
778Dither cannot be enabled for kAlpha_8_SkColorType Surface and
779kRGBA_F16_SkColorType Surface.
780
781Dither is disabled by default.
782Dither can be enabled by default by setting SkPaintDefaults_Flags to kDither_Flag
783at compile time.
784
785Some platform implementations may ignore dithering. Set
786
Cary Clark2d4bf5f2018-04-16 08:37:38 -0400787#Formula
788SK_IGNORE_GPU_DITHER
789##
Cary Clark8032b982017-07-28 11:04:54 -0400790
791to ignore Dither on GPU_Surface.
792
793#Example
Herb Derbyfcac00f2018-05-01 11:57:56 -0400794#Description
Cary Clark8032b982017-07-28 11:04:54 -0400795Dithering in the bottom half more closely approximates the requested color by
796alternating nearby colors from pixel to pixel.
797##
798void draw(SkCanvas* canvas) {
799 SkBitmap bm16;
800 bm16.allocPixels(SkImageInfo::Make(32, 32, kRGB_565_SkColorType, kOpaque_SkAlphaType));
801 SkCanvas c16(bm16);
802 SkPaint colorPaint;
803 for (auto dither : { false, true } ) {
804 colorPaint.setDither(dither);
805 for (auto colors : { 0xFF333333, 0xFF666666, 0xFF999999, 0xFFCCCCCC } ) {
806 for (auto mask : { 0xFFFF0000, 0xFF00FF00, 0xFF0000FF, 0xFFFFFFFF } ) {
807 colorPaint.setColor(colors & mask);
808 c16.drawRect({0, 0, 8, 4}, colorPaint);
809 c16.translate(8, 0);
810 }
811 c16.translate(-32, 4);
812 }
813 }
814 canvas->scale(8, 8);
815 canvas->drawBitmap(bm16, 0, 0);
816}
817##
818
819#Example
Herb Derbyfcac00f2018-05-01 11:57:56 -0400820#Description
Cary Clark8032b982017-07-28 11:04:54 -0400821Dithering introduces subtle adjustments to color to smooth gradients.
822Drawing the gradient repeatedly with SkBlendMode::kPlus exaggerates the
823dither, making it easier to see.
824##
825void draw(SkCanvas* canvas) {
826 canvas->clear(0);
827 SkBitmap bm32;
828 bm32.allocPixels(SkImageInfo::Make(20, 10, kN32_SkColorType, kPremul_SkAlphaType));
829 SkCanvas c32(bm32);
830 SkPoint points[] = {{0, 0}, {20, 0}};
831 SkColor colors[] = {0xFF334455, 0xFF662211 };
832 SkPaint paint;
833 paint.setShader(SkGradientShader::MakeLinear(
834 points, colors, nullptr, SK_ARRAY_COUNT(colors),
835 SkShader::kClamp_TileMode, 0, nullptr));
836 paint.setDither(true);
837 c32.drawPaint(paint);
838 canvas->scale(12, 12);
839 canvas->drawBitmap(bm32, 0, 0);
840 paint.setBlendMode(SkBlendMode::kPlus);
841 canvas->drawBitmap(bm32, 0, 11, &paint);
842 canvas->drawBitmap(bm32, 0, 11, &paint);
843 canvas->drawBitmap(bm32, 0, 11, &paint);
844}
845##
846
847#Method bool isDither() const
848
Cary Clarkab2621d2018-01-30 10:08:57 -0500849#In Dither
850#Line # returns true if Dither is set ##
Cary Clark8032b982017-07-28 11:04:54 -0400851 If true, color error may be distributed to smooth color transition.
Herb Derbyfcac00f2018-05-01 11:57:56 -0400852
Cary Clark8032b982017-07-28 11:04:54 -0400853 Equivalent to getFlags masked with kDither_Flag.
854
855 #Return kDither_Flag state ##
856
857 #Example
858 SkPaint paint;
859 SkDebugf("paint.isDither() %c= !!(paint.getFlags() & SkPaint::kDither_Flag)\n",
860 paint.isDither() == !!(paint.getFlags() & SkPaint::kDither_Flag) ? '=' : '!');
861 paint.setDither(true);
862 SkDebugf("paint.isDither() %c= !!(paint.getFlags() & SkPaint::kDither_Flag)\n",
863 paint.isDither() == !!(paint.getFlags() & SkPaint::kDither_Flag) ? '=' : '!');
864
865 #StdOut
866 paint.isDither() == !!(paint.getFlags() & SkPaint::kDither_Flag)
867 paint.isDither() == !!(paint.getFlags() & SkPaint::kDither_Flag)
868 ##
869 ##
870
871##
872
873#Method void setDither(bool dither)
874
Cary Clarkab2621d2018-01-30 10:08:57 -0500875#In Dither
876#Line # sets or clears Dither ##
Cary Clark8032b982017-07-28 11:04:54 -0400877 Requests, but does not require, to distribute color error.
878
879 Sets kDither_Flag if dither is true.
880 Clears kDither_Flag if dither is false.
881
882 #Param dither setting for kDither_Flag ##
883
884 #Example
885 SkPaint paint1, paint2;
886 paint1.setDither(true);
887 paint2.setFlags(paint2.getFlags() | SkPaint::kDither_Flag);
888 SkDebugf("paint1 %c= paint2\n", paint1 == paint2 ? '=' : '!');
889
890 #StdOut
891 paint1 == paint2
892 ##
893 ##
894
895 #SeeAlso kRGB_565_SkColorType
896
897##
898
899#SeeAlso Gradient Color_RGB-565
900
Cary Clark08895c42018-02-01 09:37:32 -0500901#Subtopic Dither ##
Cary Clark8032b982017-07-28 11:04:54 -0400902# ------------------------------------------------------------------------------
Cary Clark08895c42018-02-01 09:37:32 -0500903#Subtopic Device_Text
904#Line # increase precision of glyph position ##
Cary Clark8032b982017-07-28 11:04:54 -0400905
906LCD_Text and Subpixel_Text increase the precision of glyph position.
907
Herb Derbyfcac00f2018-05-01 11:57:56 -0400908When set, Flags kLCDRenderText_Flag takes advantage of the organization of Color_RGB stripes that
Cary Clark8032b982017-07-28 11:04:54 -0400909create a color, and relies
Cary Clarkce101242017-09-01 15:51:02 -0400910on the small size of the stripe and visual perception to make the color fringing imperceptible.
Cary Clark8032b982017-07-28 11:04:54 -0400911LCD_Text can be enabled on devices that orient stripes horizontally or vertically, and that order
912the color components as Color_RGB or Color_RBG.
913
Herb Derbyfcac00f2018-05-01 11:57:56 -0400914Flags kSubpixelText_Flag uses the pixel transparency to represent a fractional offset.
Cary Clark8032b982017-07-28 11:04:54 -0400915As the opaqueness
916of the color increases, the edge of the glyph appears to move towards the outside of the pixel.
917
918Either or both techniques can be enabled.
919kLCDRenderText_Flag and kSubpixelText_Flag are clear by default.
Herb Derbyfcac00f2018-05-01 11:57:56 -0400920LCD_Text or Subpixel_Text can be enabled by default by setting SkPaintDefaults_Flags to
Cary Clark8032b982017-07-28 11:04:54 -0400921kLCDRenderText_Flag or kSubpixelText_Flag (or both) at compile time.
922
923#Example
924 #Description
925 Four commas are drawn normally and with combinations of LCD_Text and Subpixel_Text.
Cary Clarkce101242017-09-01 15:51:02 -0400926 When Subpixel_Text is disabled, the comma Glyphs are identical, but not evenly spaced.
927 When Subpixel_Text is enabled, the comma Glyphs are unique, but appear evenly spaced.
Cary Clark8032b982017-07-28 11:04:54 -0400928 ##
929
930 SkBitmap bitmap;
931 bitmap.allocN32Pixels(24, 33);
932 SkCanvas offscreen(bitmap);
933 offscreen.clear(SK_ColorWHITE);
934 SkPaint paint;
935 paint.setAntiAlias(true);
936 paint.setTextSize(20);
937 for (bool lcd : { false, true }) {
938 paint.setLCDRenderText(lcd);
939 for (bool subpixel : { false, true }) {
940 paint.setSubpixelText(subpixel);
941 offscreen.drawString(",,,,", 0, 4, paint);
942 offscreen.translate(0, 7);
943 }
944 }
945 canvas->drawBitmap(bitmap, 4, 12);
946 canvas->scale(9, 9);
947 canvas->drawBitmap(bitmap, 4, -1);
948##
Cary Clark08895c42018-02-01 09:37:32 -0500949#Subtopic Device_Text ##
Cary Clark8032b982017-07-28 11:04:54 -0400950
951#Subtopic Linear_Text
Cary Clark08895c42018-02-01 09:37:32 -0500952#Alias Linear_Text
953#Line # selects text rendering as Glyph or Path ##
Cary Clark8032b982017-07-28 11:04:54 -0400954
955Linear_Text selects whether text is rendered as a Glyph or as a Path.
956If kLinearText_Flag is set, it has the same effect as setting Hinting to kNormal_Hinting.
Cary Clarkd0530ba2017-09-14 11:25:39 -0400957If kLinearText_Flag is clear, it is the same as setting Hinting to kNo_Hinting.
Cary Clark8032b982017-07-28 11:04:54 -0400958
959#Method bool isLinearText() const
960
Cary Clark08895c42018-02-01 09:37:32 -0500961#Line # returns true if text is converted to Path ##
Cary Clarkab2621d2018-01-30 10:08:57 -0500962#In Linear_Text
Cary Clark8032b982017-07-28 11:04:54 -0400963 If true, text is converted to Path before drawing and measuring.
964
965 Equivalent to getFlags masked with kLinearText_Flag.
966
967 #Return kLinearText_Flag state ##
968
969 #Example
970 #Height 128
971 void draw(SkCanvas* canvas) {
972 SkPaint paint;
973 paint.setAntiAlias(true);
974 const char testStr[] = "xxxx xxxx";
975 for (auto linearText : { false, true } ) {
976 paint.setLinearText(linearText);
977 paint.setTextSize(24);
978 canvas->drawString(paint.isLinearText() ? "linear" : "hinted", 128, 30, paint);
979 for (SkScalar textSize = 8; textSize < 30; textSize *= 1.22f) {
980 paint.setTextSize(textSize);
981 canvas->translate(0, textSize);
982 canvas->drawString(testStr, 10, 0, paint);
983 }
984 }
985 }
986 ##
987
988 #SeeAlso setLinearText Hinting
989##
990
991#Method void setLinearText(bool linearText)
992
Cary Clark08895c42018-02-01 09:37:32 -0500993#Line # converts to Path before draw or measure ##
Cary Clarkab2621d2018-01-30 10:08:57 -0500994#In Linear_Text
Cary Clark8032b982017-07-28 11:04:54 -0400995 If true, text is converted to Path before drawing and measuring.
996 By default, kLinearText_Flag is clear.
997
998 Sets kLinearText_Flag if linearText is true.
999 Clears kLinearText_Flag if linearText is false.
1000
1001 #Param linearText setting for kLinearText_Flag ##
1002
1003 #Example
1004 #Height 128
1005 void draw(SkCanvas* canvas) {
1006 SkPaint paint;
1007 paint.setAntiAlias(true);
1008 const char testStr[] = "abcd efgh";
1009 for (int textSize : { 12, 24 } ) {
1010 paint.setTextSize(textSize);
1011 for (auto linearText : { false, true } ) {
1012 paint.setLinearText(linearText);
1013 SkString width;
1014 width.appendScalar(paint.measureText(testStr, SK_ARRAY_COUNT(testStr), nullptr));
1015 canvas->translate(0, textSize + 4);
1016 canvas->drawString(testStr, 10, 0, paint);
1017 canvas->drawString(width, 128, 0, paint);
1018 }
1019 }
Herb Derbyfcac00f2018-05-01 11:57:56 -04001020 }
Cary Clark8032b982017-07-28 11:04:54 -04001021 ##
1022
1023 #SeeAlso isLinearText Hinting
1024##
1025
Cary Clark08895c42018-02-01 09:37:32 -05001026#Subtopic Linear_Text ##
Cary Clark8032b982017-07-28 11:04:54 -04001027
1028#Subtopic Subpixel_Text
Cary Clark08895c42018-02-01 09:37:32 -05001029#Alias Subpixel_Text
1030#Line # uses pixel transparency to represent fractional offset ##
Cary Clark8032b982017-07-28 11:04:54 -04001031
Herb Derbyfcac00f2018-05-01 11:57:56 -04001032Flags kSubpixelText_Flag uses the pixel transparency to represent a fractional offset.
Cary Clark8032b982017-07-28 11:04:54 -04001033As the opaqueness
1034of the color increases, the edge of the glyph appears to move towards the outside of the pixel.
1035
1036#Method bool isSubpixelText() const
Herb Derbyfcac00f2018-05-01 11:57:56 -04001037
Cary Clarkab2621d2018-01-30 10:08:57 -05001038#In Subpixel_Text
1039#Line # returns true if Subpixel_Text is set ##
Cary Clarkce101242017-09-01 15:51:02 -04001040 If true, Glyphs at different sub-pixel positions may differ on pixel edge coverage.
Cary Clark8032b982017-07-28 11:04:54 -04001041
1042 Equivalent to getFlags masked with kSubpixelText_Flag.
1043
1044 #Return kSubpixelText_Flag state ##
1045
1046 #Example
1047SkPaint paint;
1048SkDebugf("paint.isSubpixelText() %c= !!(paint.getFlags() & SkPaint::kSubpixelText_Flag)\n",
1049 paint.isSubpixelText() == !!(paint.getFlags() & SkPaint::kSubpixelText_Flag) ? '=' : '!');
1050paint.setSubpixelText(true);
1051SkDebugf("paint.isSubpixelText() %c= !!(paint.getFlags() & SkPaint::kSubpixelText_Flag)\n",
1052 paint.isSubpixelText() == !!(paint.getFlags() & SkPaint::kSubpixelText_Flag) ? '=' : '!');
1053
1054 #StdOut
1055 paint.isSubpixelText() == !!(paint.getFlags() & SkPaint::kSubpixelText_Flag)
1056 paint.isSubpixelText() == !!(paint.getFlags() & SkPaint::kSubpixelText_Flag)
1057 ##
1058 ##
1059
1060##
1061
1062#Method void setSubpixelText(bool subpixelText)
1063
Cary Clarkab2621d2018-01-30 10:08:57 -05001064#In Subpixel_Text
1065#Line # sets or clears Subpixel_Text ##
Cary Clarkce101242017-09-01 15:51:02 -04001066 Requests, but does not require, that Glyphs respect sub-pixel positioning.
Cary Clark8032b982017-07-28 11:04:54 -04001067
1068 Sets kSubpixelText_Flag if subpixelText is true.
1069 Clears kSubpixelText_Flag if subpixelText is false.
1070
1071 #Param subpixelText setting for kSubpixelText_Flag ##
1072
1073 #Example
1074 SkPaint paint1, paint2;
1075 paint1.setSubpixelText(true);
1076 paint2.setFlags(paint2.getFlags() | SkPaint::kSubpixelText_Flag);
1077 SkDebugf("paint1 %c= paint2\n", paint1 == paint2 ? '=' : '!');
1078
1079 #StdOut
1080 paint1 == paint2
1081 ##
1082 ##
1083
1084##
1085
Cary Clark08895c42018-02-01 09:37:32 -05001086#Subtopic Subpixel_Text ##
Cary Clark8032b982017-07-28 11:04:54 -04001087
1088#Subtopic LCD_Text
Cary Clarkc68ba1d2018-02-20 10:35:29 -05001089#Substitute LCD text
Cary Clark08895c42018-02-01 09:37:32 -05001090#Line # text relying on the order of Color_RGB stripes ##
Cary Clark8032b982017-07-28 11:04:54 -04001091#Alias LCD_Text # makes this a top level name, since it is under subtopic Device_Text
1092
Herb Derbyfcac00f2018-05-01 11:57:56 -04001093When set, Flags kLCDRenderText_Flag takes advantage of the organization of Color_RGB stripes that
Cary Clark8032b982017-07-28 11:04:54 -04001094create a color, and relies
Cary Clarkce101242017-09-01 15:51:02 -04001095on the small size of the stripe and visual perception to make the color fringing imperceptible.
Cary Clark8032b982017-07-28 11:04:54 -04001096LCD_Text can be enabled on devices that orient stripes horizontally or vertically, and that order
1097the color components as Color_RGB or Color_RBG.
1098
1099#Method bool isLCDRenderText() const
1100
Cary Clarkab2621d2018-01-30 10:08:57 -05001101#In LCD_Text
1102#Line # returns true if LCD_Text is set ##
Cary Clarkce101242017-09-01 15:51:02 -04001103 If true, Glyphs may use LCD striping to improve glyph edges.
Cary Clark8032b982017-07-28 11:04:54 -04001104
1105 Returns true if Flags kLCDRenderText_Flag is set.
1106
1107 #Return kLCDRenderText_Flag state ##
1108
1109 #Example
1110SkPaint paint;
1111SkDebugf("paint.isLCDRenderText() %c= !!(paint.getFlags() & SkPaint::kLCDRenderText_Flag)\n",
1112 paint.isLCDRenderText() == !!(paint.getFlags() & SkPaint::kLCDRenderText_Flag) ? '=' : '!');
1113paint.setLCDRenderText(true);
1114SkDebugf("paint.isLCDRenderText() %c= !!(paint.getFlags() & SkPaint::kLCDRenderText_Flag)\n",
1115 paint.isLCDRenderText() == !!(paint.getFlags() & SkPaint::kLCDRenderText_Flag) ? '=' : '!');
1116
1117 #StdOut
1118 paint.isLCDRenderText() == !!(paint.getFlags() & SkPaint::kLCDRenderText_Flag)
1119 paint.isLCDRenderText() == !!(paint.getFlags() & SkPaint::kLCDRenderText_Flag)
1120 ##
1121 ##
1122
1123##
1124
1125#Method void setLCDRenderText(bool lcdText)
1126
Cary Clarkab2621d2018-01-30 10:08:57 -05001127#In LCD_Text
1128#Line # sets or clears LCD_Text ##
Cary Clarkce101242017-09-01 15:51:02 -04001129 Requests, but does not require, that Glyphs use LCD striping for glyph edges.
Cary Clark8032b982017-07-28 11:04:54 -04001130
1131 Sets kLCDRenderText_Flag if lcdText is true.
1132 Clears kLCDRenderText_Flag if lcdText is false.
1133
1134 #Param lcdText setting for kLCDRenderText_Flag ##
1135
1136 #Example
1137 SkPaint paint1, paint2;
1138 paint1.setLCDRenderText(true);
1139 paint2.setFlags(paint2.getFlags() | SkPaint::kLCDRenderText_Flag);
1140 SkDebugf("paint1 %c= paint2\n", paint1 == paint2 ? '=' : '!');
1141
1142 #StdOut
1143 paint1 == paint2
1144 ##
1145 ##
1146
1147
1148##
1149
Cary Clark08895c42018-02-01 09:37:32 -05001150#Subtopic LCD_Text ##
Cary Clark8032b982017-07-28 11:04:54 -04001151
Cary Clark8032b982017-07-28 11:04:54 -04001152# ------------------------------------------------------------------------------
Cary Clark08895c42018-02-01 09:37:32 -05001153#Subtopic Font_Embedded_Bitmaps
1154#Line # custom sized bitmap Glyphs ##
Cary Clark8032b982017-07-28 11:04:54 -04001155#Alias Font_Embedded_Bitmaps # long-winded enough, alias so I don't type Paint_Font_...
1156
Cary Clarkce101242017-09-01 15:51:02 -04001157Font_Embedded_Bitmaps allows selecting custom sized bitmap Glyphs.
Cary Clark8032b982017-07-28 11:04:54 -04001158Flags kEmbeddedBitmapText_Flag when set chooses an embedded bitmap glyph over an outline contained
Herb Derbyfcac00f2018-05-01 11:57:56 -04001159in a font if the platform supports this option.
Cary Clark8032b982017-07-28 11:04:54 -04001160
1161FreeType selects the bitmap glyph if available when kEmbeddedBitmapText_Flag is set, and selects
1162the outline glyph if kEmbeddedBitmapText_Flag is clear.
1163Windows may select the bitmap glyph but is not required to do so.
1164OS_X and iOS do not support this option.
1165
1166Font_Embedded_Bitmaps is disabled by default.
1167Font_Embedded_Bitmaps can be enabled by default by setting SkPaintDefaults_Flags to
1168kEmbeddedBitmapText_Flag at compile time.
1169
1170#Example
1171 #ToDo image will only output on Ubuntu ... how to handle that in fiddle? ##
1172 #Platform !fiddle
1173 #Description
Cary Clarkce101242017-09-01 15:51:02 -04001174 The "hintgasp" TrueType font in the Skia resources/fonts directory
1175 includes an embedded bitmap Glyph at odd font sizes. This example works
1176 on platforms that use FreeType as their Font_Engine.
1177 Windows may, but is not required to, return a bitmap glyph if
1178 kEmbeddedBitmapText_Flag is set.
Cary Clark8032b982017-07-28 11:04:54 -04001179 ##
1180 #Image embeddedbitmap.png
1181
1182 SkBitmap bitmap;
1183 bitmap.allocN32Pixels(30, 15);
1184 bitmap.eraseColor(0);
1185 SkCanvas offscreen(bitmap);
1186 SkPaint paint;
1187 paint.setAntiAlias(true);
1188 paint.setTextSize(13);
Hal Canary53e5e7d2017-12-08 14:25:14 -05001189 paint.setTypeface(MakeResourceAsTypeface("fonts/hintgasp.ttf"));
Cary Clark8032b982017-07-28 11:04:54 -04001190 for (bool embedded : { false, true}) {
1191 paint.setEmbeddedBitmapText(embedded);
1192 offscreen.drawString("A", embedded ? 5 : 15, 15, paint);
1193 }
1194 canvas->drawBitmap(bitmap, 0, 0);
1195 canvas->scale(10, 10);
1196 canvas->drawBitmap(bitmap, -2, 1);
1197##
1198
1199#Method bool isEmbeddedBitmapText() const
1200
Cary Clarkab2621d2018-01-30 10:08:57 -05001201#In Font_Embedded_Bitmaps
1202#Line # returns true if Font_Embedded_Bitmaps is set ##
Cary Clarkce101242017-09-01 15:51:02 -04001203 If true, Font_Engine may return Glyphs from font bitmaps instead of from outlines.
Cary Clark8032b982017-07-28 11:04:54 -04001204
1205 Equivalent to getFlags masked with kEmbeddedBitmapText_Flag.
1206
1207 #Return kEmbeddedBitmapText_Flag state ##
1208
1209 #Example
1210 SkPaint paint;
1211 SkDebugf("paint.isEmbeddedBitmapText() %c="
1212 " !!(paint.getFlags() & SkPaint::kEmbeddedBitmapText_Flag)\n",
1213 paint.isEmbeddedBitmapText() ==
1214 !!(paint.getFlags() & SkPaint::kEmbeddedBitmapText_Flag) ? '=' : '!');
1215 paint.setEmbeddedBitmapText(true);
1216 SkDebugf("paint.isEmbeddedBitmapText() %c="
1217 " !!(paint.getFlags() & SkPaint::kEmbeddedBitmapText_Flag)\n",
1218 paint.isEmbeddedBitmapText() ==
1219 !!(paint.getFlags() & SkPaint::kEmbeddedBitmapText_Flag) ? '=' : '!');
1220
1221 #StdOut
1222 paint.isEmbeddedBitmapText() == !!(paint.getFlags() & SkPaint::kEmbeddedBitmapText_Flag)
1223 paint.isEmbeddedBitmapText() == !!(paint.getFlags() & SkPaint::kEmbeddedBitmapText_Flag)
1224 ##
1225 ##
1226
1227##
1228
1229#Method void setEmbeddedBitmapText(bool useEmbeddedBitmapText)
1230
Cary Clarkab2621d2018-01-30 10:08:57 -05001231#In Font_Embedded_Bitmaps
1232#Line # sets or clears Font_Embedded_Bitmaps ##
Cary Clark8032b982017-07-28 11:04:54 -04001233 Requests, but does not require, to use bitmaps in fonts instead of outlines.
1234
1235 Sets kEmbeddedBitmapText_Flag if useEmbeddedBitmapText is true.
1236 Clears kEmbeddedBitmapText_Flag if useEmbeddedBitmapText is false.
1237
1238 #Param useEmbeddedBitmapText setting for kEmbeddedBitmapText_Flag ##
1239
1240 #Example
1241 SkPaint paint1, paint2;
1242 paint1.setEmbeddedBitmapText(true);
1243 paint2.setFlags(paint2.getFlags() | SkPaint::kEmbeddedBitmapText_Flag);
1244 SkDebugf("paint1 %c= paint2\n", paint1 == paint2 ? '=' : '!');
1245
1246 #StdOut
1247 paint1 == paint2
1248 ##
1249 ##
1250
1251##
1252
Cary Clark08895c42018-02-01 09:37:32 -05001253#Subtopic Font_Embedded_Bitmaps ##
Cary Clark8032b982017-07-28 11:04:54 -04001254# ------------------------------------------------------------------------------
Cary Clark08895c42018-02-01 09:37:32 -05001255#Subtopic Automatic_Hinting
1256#Line # always adjust glyph paths ##
Cary Clark8032b982017-07-28 11:04:54 -04001257#Substitute auto-hinting
1258
1259If Hinting is set to kNormal_Hinting or kFull_Hinting, Automatic_Hinting
Cary Clarkce101242017-09-01 15:51:02 -04001260instructs the Font_Manager to always hint Glyphs.
Cary Clark8032b982017-07-28 11:04:54 -04001261Automatic_Hinting has no effect if Hinting is set to kNo_Hinting or
1262kSlight_Hinting.
1263
1264Automatic_Hinting only affects platforms that use FreeType as the Font_Manager.
1265
1266#Method bool isAutohinted() const
1267
Cary Clarkab2621d2018-01-30 10:08:57 -05001268#In Automatic_Hinting
1269#Line # returns true if Glyphs are always hinted ##
Cary Clark8032b982017-07-28 11:04:54 -04001270 If true, and if Hinting is set to kNormal_Hinting or kFull_Hinting, and if
1271 platform uses FreeType as the Font_Manager, instruct the Font_Manager to always hint
Cary Clarkce101242017-09-01 15:51:02 -04001272 Glyphs.
Cary Clark8032b982017-07-28 11:04:54 -04001273
1274 Equivalent to getFlags masked with kAutoHinting_Flag.
1275
1276 #Return kAutoHinting_Flag state ##
1277
1278 #Example
1279 SkPaint paint;
1280 for (auto forceAutoHinting : { false, true} ) {
1281 paint.setAutohinted(forceAutoHinting);
1282 SkDebugf("paint.isAutohinted() %c="
1283 " !!(paint.getFlags() & SkPaint::kAutoHinting_Flag)\n",
1284 paint.isAutohinted() ==
1285 !!(paint.getFlags() & SkPaint::kAutoHinting_Flag) ? '=' : '!');
1286 }
1287 #StdOut
1288 paint.isAutohinted() == !!(paint.getFlags() & SkPaint::kAutoHinting_Flag)
1289 paint.isAutohinted() == !!(paint.getFlags() & SkPaint::kAutoHinting_Flag)
1290 ##
1291 ##
1292
1293 #SeeAlso setAutohinted Hinting
1294
1295##
1296
1297#Method void setAutohinted(bool useAutohinter)
1298
Cary Clarkab2621d2018-01-30 10:08:57 -05001299#In Automatic_Hinting
1300#Line # sets Glyphs to always be hinted ##
Cary Clark8032b982017-07-28 11:04:54 -04001301 If Hinting is set to kNormal_Hinting or kFull_Hinting and useAutohinter is set,
Cary Clarkce101242017-09-01 15:51:02 -04001302 instruct the Font_Manager to always hint Glyphs.
Cary Clark8032b982017-07-28 11:04:54 -04001303 Automatic_Hinting has no effect if Hinting is set to kNo_Hinting or
1304 kSlight_Hinting.
1305
Cary Clark579985c2017-07-31 11:48:27 -04001306 Only affects platforms that use FreeType as the Font_Manager.
Cary Clark8032b982017-07-28 11:04:54 -04001307
1308 Sets kAutoHinting_Flag if useAutohinter is true.
1309 Clears kAutoHinting_Flag if useAutohinter is false.
1310
1311 #Param useAutohinter setting for kAutoHinting_Flag ##
1312
1313 #Example
1314 void draw(SkCanvas* canvas) {
1315 SkPaint paint;
1316 paint.setAntiAlias(true);
1317 const char testStr[] = "xxxx xxxx";
1318 for (auto forceAutoHinting : { false, true} ) {
1319 paint.setAutohinted(forceAutoHinting);
1320 paint.setTextSize(24);
1321 canvas->drawString(paint.isAutohinted() ? "auto-hinted" : "default", 108, 30, paint);
1322 for (SkScalar textSize = 8; textSize < 30; textSize *= 1.22f) {
1323 paint.setTextSize(textSize);
1324 canvas->translate(0, textSize);
1325 canvas->drawString(testStr, 10, 0, paint);
1326 }
1327 }
1328 }
1329 ##
1330
1331 #SeeAlso isAutohinted Hinting
1332
1333##
1334
Cary Clark08895c42018-02-01 09:37:32 -05001335#Subtopic Automatic_Hinting ##
Cary Clark8032b982017-07-28 11:04:54 -04001336# ------------------------------------------------------------------------------
Cary Clark08895c42018-02-01 09:37:32 -05001337#Subtopic Vertical_Text
1338#Line # orient text from top to bottom ##
Cary Clark8032b982017-07-28 11:04:54 -04001339
1340Text may be drawn by positioning each glyph, or by positioning the first glyph and
Cary Clarkce101242017-09-01 15:51:02 -04001341using Font_Advance to position subsequent Glyphs. By default, each successive glyph
1342is positioned to the right of the preceding glyph. Vertical_Text sets successive
1343Glyphs to position below the preceding glyph.
Cary Clark8032b982017-07-28 11:04:54 -04001344
Cary Clarkce101242017-09-01 15:51:02 -04001345Skia can translate text character codes as a series of Glyphs, but does not implement
Herb Derbyfcac00f2018-05-01 11:57:56 -04001346font substitution,
Cary Clarkce101242017-09-01 15:51:02 -04001347textual substitution, line layout, or contextual spacing like Kerning pairs. Use
Cary Clark6fc50412017-09-21 12:31:06 -04001348a text shaping engine like
1349#A HarfBuzz # http://harfbuzz.org/ ##
1350 to translate text runs
Cary Clark8032b982017-07-28 11:04:54 -04001351into glyph series.
1352
1353Vertical_Text is clear if text is drawn left to right or set if drawn from top to bottom.
1354
1355Flags kVerticalText_Flag if clear draws text left to right.
1356Flags kVerticalText_Flag if set draws text top to bottom.
1357
1358Vertical_Text is clear by default.
1359Vertical_Text can be set by default by setting SkPaintDefaults_Flags to
1360kVerticalText_Flag at compile time.
1361
1362#Example
1363
1364void draw(SkCanvas* canvas) {
1365 SkPaint paint;
1366 paint.setAntiAlias(true);
1367 paint.setTextSize(50);
1368 for (bool vertical : { false, true } ) {
1369 paint.setVerticalText(vertical);
1370 canvas->drawString("aAlL", 25, 50, paint);
1371 }
1372}
1373
1374##
1375
1376#Method bool isVerticalText() const
1377
Cary Clarkab2621d2018-01-30 10:08:57 -05001378#In Vertical_Text
1379#Line # returns true if Vertical_Text is set ##
Cary Clarkce101242017-09-01 15:51:02 -04001380 If true, Glyphs are drawn top to bottom instead of left to right.
Cary Clark8032b982017-07-28 11:04:54 -04001381
1382 Equivalent to getFlags masked with kVerticalText_Flag.
1383
1384 #Return kVerticalText_Flag state ##
1385
1386 #Example
1387 SkPaint paint;
1388 SkDebugf("paint.isVerticalText() %c= !!(paint.getFlags() & SkPaint::kVerticalText_Flag)\n",
1389 paint.isVerticalText() == !!(paint.getFlags() & SkPaint::kVerticalText_Flag) ? '=' : '!');
1390 paint.setVerticalText(true);
1391 SkDebugf("paint.isVerticalText() %c= !!(paint.getFlags() & SkPaint::kVerticalText_Flag)\n",
1392 paint.isVerticalText() == !!(paint.getFlags() & SkPaint::kVerticalText_Flag) ? '=' : '!');
1393
1394 #StdOut
1395 paint.isVerticalText() == !!(paint.getFlags() & SkPaint::kVerticalText_Flag)
1396 paint.isVerticalText() == !!(paint.getFlags() & SkPaint::kVerticalText_Flag)
1397 ##
1398 ##
1399
1400##
1401
1402#Method void setVerticalText(bool verticalText)
1403
Cary Clarkab2621d2018-01-30 10:08:57 -05001404#In Vertical_Text
1405#Line # sets or clears Vertical_Text ##
Cary Clark8032b982017-07-28 11:04:54 -04001406 If true, text advance positions the next glyph below the previous glyph instead of to the
1407 right of previous glyph.
1408
1409 Sets kVerticalText_Flag if vertical is true.
1410 Clears kVerticalText_Flag if vertical is false.
1411
1412 #Param verticalText setting for kVerticalText_Flag ##
1413
1414 #Example
1415 SkPaint paint1, paint2;
1416 paint1.setVerticalText(true);
1417 paint2.setFlags(paint2.getFlags() | SkPaint::kVerticalText_Flag);
1418 SkDebugf("paint1 %c= paint2\n", paint1 == paint2 ? '=' : '!');
1419
1420 #StdOut
1421 paint1 == paint2
1422 ##
1423 ##
1424
1425##
1426
Cary Clark08895c42018-02-01 09:37:32 -05001427#Subtopic Vertical_Text ##
Cary Clark8032b982017-07-28 11:04:54 -04001428# ------------------------------------------------------------------------------
1429
Cary Clark08895c42018-02-01 09:37:32 -05001430#Subtopic Fake_Bold
1431#Line # approximate font styles ##
Cary Clark8032b982017-07-28 11:04:54 -04001432
1433Fake_Bold approximates the bold font style accompanying a normal font when a bold font face
1434is not available. Skia does not provide font substitution; it is up to the client to find the
Cary Clarkbc5697d2017-10-04 14:31:33 -04001435bold font face using the platform Font_Manager.
Cary Clark8032b982017-07-28 11:04:54 -04001436
Herb Derbyfcac00f2018-05-01 11:57:56 -04001437Use Text_Skew_X to approximate an italic font style when the italic font face
Cary Clark8032b982017-07-28 11:04:54 -04001438is not available.
1439
Cary Clarkce101242017-09-01 15:51:02 -04001440A FreeType based port may define SK_USE_FREETYPE_EMBOLDEN at compile time to direct
1441the font engine to create the bold Glyphs. Otherwise, the extra bold is computed
Herb Derbyfcac00f2018-05-01 11:57:56 -04001442by increasing the stroke width and setting the Style to kStrokeAndFill_Style as needed.
Cary Clark8032b982017-07-28 11:04:54 -04001443
1444Fake_Bold is disabled by default.
1445
1446#Example
1447#Height 128
1448void draw(SkCanvas* canvas) {
1449 SkPaint paint;
1450 paint.setAntiAlias(true);
1451 paint.setTextSize(40);
1452 canvas->drawString("OjYy_-", 10, 35, paint);
1453 paint.setFakeBoldText(true);
1454 canvas->drawString("OjYy_-", 10, 75, paint);
1455 // create a custom fake bold by varying the stroke width
1456 paint.setFakeBoldText(false);
1457 paint.setStyle(SkPaint::kStrokeAndFill_Style);
1458 paint.setStrokeWidth(40.f / 48);
1459 canvas->drawString("OjYy_-", 10, 115, paint);
1460}
1461##
1462
1463#Method bool isFakeBoldText() const
1464
Cary Clarkab2621d2018-01-30 10:08:57 -05001465#In Fake_Bold
1466#Line # returns true if Fake_Bold is set ##
Cary Clark8032b982017-07-28 11:04:54 -04001467 If true, approximate bold by increasing the stroke width when creating glyph bitmaps
1468 from outlines.
1469
1470 Equivalent to getFlags masked with kFakeBoldText_Flag.
1471
1472 #Return kFakeBoldText_Flag state ##
1473
1474 #Example
1475 SkPaint paint;
1476 SkDebugf("paint.isFakeBoldText() %c= !!(paint.getFlags() & SkPaint::kFakeBoldText_Flag)\n",
1477 paint.isFakeBoldText() == !!(paint.getFlags() & SkPaint::kFakeBoldText_Flag) ? '=' : '!');
1478 paint.setFakeBoldText(true);
1479 SkDebugf("paint.isFakeBoldText() %c= !!(paint.getFlags() & SkPaint::kFakeBoldText_Flag)\n",
1480 paint.isFakeBoldText() == !!(paint.getFlags() & SkPaint::kFakeBoldText_Flag) ? '=' : '!');
1481
1482 #StdOut
1483 paint.isFakeBoldText() == !!(paint.getFlags() & SkPaint::kFakeBoldText_Flag)
1484 paint.isFakeBoldText() == !!(paint.getFlags() & SkPaint::kFakeBoldText_Flag)
1485 ##
1486 ##
1487
1488##
1489
1490#Method void setFakeBoldText(bool fakeBoldText)
1491
Cary Clarkab2621d2018-01-30 10:08:57 -05001492#In Fake_Bold
1493#Line # sets or clears Fake_Bold ##
Cary Clarkce101242017-09-01 15:51:02 -04001494 Use increased stroke width when creating glyph bitmaps to approximate a bold typeface.
Cary Clark8032b982017-07-28 11:04:54 -04001495
1496 Sets kFakeBoldText_Flag if fakeBoldText is true.
1497 Clears kFakeBoldText_Flag if fakeBoldText is false.
1498
1499 #Param fakeBoldText setting for kFakeBoldText_Flag ##
1500
1501 #Example
1502 SkPaint paint1, paint2;
1503 paint1.setFakeBoldText(true);
1504 paint2.setFlags(paint2.getFlags() | SkPaint::kFakeBoldText_Flag);
1505 SkDebugf("paint1 %c= paint2\n", paint1 == paint2 ? '=' : '!');
1506
1507 #StdOut
1508 paint1 == paint2
1509 ##
1510 ##
1511
1512##
1513
Cary Clark08895c42018-02-01 09:37:32 -05001514#Subtopic Fake_Bold ##
Cary Clark8032b982017-07-28 11:04:54 -04001515
1516# ------------------------------------------------------------------------------
Cary Clark08895c42018-02-01 09:37:32 -05001517#Subtopic Full_Hinting_Spacing
1518#Line # glyph spacing affected by hinting ##
Cary Clark8032b982017-07-28 11:04:54 -04001519#Alias Full_Hinting_Spacing # long winded enough -- maybe things with two underscores auto-aliased?
1520
Cary Clarkce101242017-09-01 15:51:02 -04001521if Hinting is set to kFull_Hinting, Full_Hinting_Spacing adjusts the character
1522spacing by the difference of the hinted and Unhinted Left_Side_Bearing and
1523Right_Side_Bearing. Full_Hinting_Spacing only applies to platforms that use
1524FreeType as their Font_Engine.
Cary Clark8032b982017-07-28 11:04:54 -04001525
Cary Clarkce101242017-09-01 15:51:02 -04001526Full_Hinting_Spacing is not related to text Kerning, where the space between
Cary Clarkbc5697d2017-10-04 14:31:33 -04001527a specific pair of characters is adjusted using data in the font Kerning tables.
Cary Clark8032b982017-07-28 11:04:54 -04001528
1529#Method bool isDevKernText() const
Herb Derbyfcac00f2018-05-01 11:57:56 -04001530#Deprecated
Cary Clark8032b982017-07-28 11:04:54 -04001531##
1532
Herb Derbyfcac00f2018-05-01 11:57:56 -04001533#Method void setDevKernText(bool)
1534#Deprecated
Cary Clark8032b982017-07-28 11:04:54 -04001535##
1536
Cary Clark08895c42018-02-01 09:37:32 -05001537#Subtopic Full_Hinting_Spacing ##
Cary Clark8032b982017-07-28 11:04:54 -04001538# ------------------------------------------------------------------------------
Cary Clark08895c42018-02-01 09:37:32 -05001539#Subtopic Filter_Quality_Methods
1540#Line # get and set Filter_Quality ##
Cary Clark8032b982017-07-28 11:04:54 -04001541
1542Filter_Quality trades speed for image filtering when the image is scaled.
1543A lower Filter_Quality draws faster, but has less fidelity.
1544A higher Filter_Quality draws slower, but looks better.
Cary Clarkce101242017-09-01 15:51:02 -04001545If the image is drawn without scaling, the Filter_Quality choice will not result
1546in a noticeable difference.
Cary Clark8032b982017-07-28 11:04:54 -04001547
1548Filter_Quality is used in Paint passed as a parameter to
1549#List
1550# SkCanvas::drawBitmap ##
1551# SkCanvas::drawBitmapRect ##
1552# SkCanvas::drawImage ##
1553# SkCanvas::drawImageRect ##
1554 #ToDo probably more... ##
1555#List ##
1556and when Paint has a Shader specialization that uses Image or Bitmap.
1557
1558Filter_Quality is kNone_SkFilterQuality by default.
1559
1560#Example
1561#Image 3
1562void draw(SkCanvas* canvas) {
1563 SkPaint paint;
1564 canvas->scale(.2f, .2f);
Herb Derbyfcac00f2018-05-01 11:57:56 -04001565 for (SkFilterQuality q : { kNone_SkFilterQuality, kLow_SkFilterQuality,
Cary Clark8032b982017-07-28 11:04:54 -04001566 kMedium_SkFilterQuality, kHigh_SkFilterQuality } ) {
1567 paint.setFilterQuality(q);
1568 canvas->drawImage(image.get(), 0, 0, &paint);
1569 canvas->translate(550, 0);
1570 if (kLow_SkFilterQuality == q) canvas->translate(-1100, 550);
1571 }
1572}
1573##
1574
1575#Method SkFilterQuality getFilterQuality() const
1576
Cary Clarkab2621d2018-01-30 10:08:57 -05001577#In Filter_Quality_Methods
1578#Line # returns Filter_Quality, image filtering level ##
Cary Clark8032b982017-07-28 11:04:54 -04001579Returns Filter_Quality, the image filtering level. A lower setting
1580draws faster; a higher setting looks better when the image is scaled.
1581
Herb Derbyfcac00f2018-05-01 11:57:56 -04001582#Return one of: kNone_SkFilterQuality, kLow_SkFilterQuality,
Cary Clark8032b982017-07-28 11:04:54 -04001583 kMedium_SkFilterQuality, kHigh_SkFilterQuality
1584#Return ##
1585
1586#Example
1587 SkPaint paint;
1588 SkDebugf("kNone_SkFilterQuality %c= paint.getFilterQuality()\n",
1589 kNone_SkFilterQuality == paint.getFilterQuality() ? '=' : '!');
1590
1591 #StdOut
1592 kNone_SkFilterQuality == paint.getFilterQuality()
1593 ##
1594##
1595
1596##
1597
1598
1599#Method void setFilterQuality(SkFilterQuality quality)
1600
Cary Clarkab2621d2018-01-30 10:08:57 -05001601#In Filter_Quality_Methods
1602#Line # sets Filter_Quality, the image filtering level ##
Cary Clark8032b982017-07-28 11:04:54 -04001603Sets Filter_Quality, the image filtering level. A lower setting
1604draws faster; a higher setting looks better when the image is scaled.
Herb Derbyfcac00f2018-05-01 11:57:56 -04001605Does not check to see if quality is valid.
Cary Clark8032b982017-07-28 11:04:54 -04001606
Herb Derbyfcac00f2018-05-01 11:57:56 -04001607#Param quality one of: kNone_SkFilterQuality, kLow_SkFilterQuality,
Cary Clark8032b982017-07-28 11:04:54 -04001608 kMedium_SkFilterQuality, kHigh_SkFilterQuality
1609##
1610
1611#Example
1612 SkPaint paint;
1613 paint.setFilterQuality(kHigh_SkFilterQuality);
1614 SkDebugf("kHigh_SkFilterQuality %c= paint.getFilterQuality()\n",
1615 kHigh_SkFilterQuality == paint.getFilterQuality() ? '=' : '!');
1616
1617 #StdOut
1618 kHigh_SkFilterQuality == paint.getFilterQuality()
1619 ##
1620##
1621
1622#SeeAlso SkFilterQuality Image_Scaling
1623
1624##
1625
Cary Clark08895c42018-02-01 09:37:32 -05001626#Subtopic Filter_Quality_Methods ##
Cary Clark8032b982017-07-28 11:04:54 -04001627# ------------------------------------------------------------------------------
Cary Clark08895c42018-02-01 09:37:32 -05001628#Subtopic Color_Methods
1629#Line # get and set Color ##
Cary Clark8032b982017-07-28 11:04:54 -04001630
Cary Clarkab2621d2018-01-30 10:08:57 -05001631#Table
1632#Legend
1633# name # description ##
1634#Legend ##
1635# getColor # returns Color_Alpha and Color_RGB, one drawing color ##
1636# setColor # sets Color_Alpha and Color_RGB, one drawing color ##
1637#Table ##
Cary Clark8032b982017-07-28 11:04:54 -04001638
Cary Clarkab2621d2018-01-30 10:08:57 -05001639Color specifies the Color_RGB_Red, Color_RGB_Blue, Color_RGB_Green, and Color_Alpha
1640values used to draw a filled or stroked shape in a 32-bit value. Each component
1641occupies 8-bits, ranging from zero: no contribution; to 255: full intensity.
1642All values in any combination are valid.
Cary Clark8032b982017-07-28 11:04:54 -04001643
Cary Clarkab2621d2018-01-30 10:08:57 -05001644Color is not Premultiplied; Color_Alpha sets the transparency independent of
1645Color_RGB: Color_RGB_Red, Color_RGB_Blue, and Color_RGB_Green.
1646
1647The bit positions of Color_Alpha and Color_RGB are independent of the bit
1648positions on the output device, which may have more or fewer bits, and may have
1649a different arrangement.
Cary Clark8032b982017-07-28 11:04:54 -04001650
1651#Table
1652#Legend
1653# bit positions # Color_Alpha # Color_RGB_Red # Color_RGB_Blue # Color_RGB_Green ##
1654#Legend ##
1655# # 31 - 24 # 23 - 16 # 15 - 8 # 7 - 0 ##
1656#Table ##
1657
1658#Example
1659#Height 128
1660 void draw(SkCanvas* canvas) {
1661 SkPaint paint;
1662 paint.setColor(0x8000FF00); // transparent green
1663 canvas->drawCircle(50, 50, 40, paint);
1664 paint.setARGB(128, 255, 0, 0); // transparent red
1665 canvas->drawCircle(80, 50, 40, paint);
1666 paint.setColor(SK_ColorBLUE);
1667 paint.setAlpha(0x80);
1668 canvas->drawCircle(65, 65, 40, paint);
1669 }
1670##
1671
1672#Method SkColor getColor() const
1673
Cary Clarkab2621d2018-01-30 10:08:57 -05001674#In Color_Methods
1675#Line # returns Color_Alpha and Color_RGB, one drawing color ##
Cary Clarkce101242017-09-01 15:51:02 -04001676 Retrieves Alpha and Color_RGB, Unpremultiplied, packed into 32 bits.
Cary Clark8032b982017-07-28 11:04:54 -04001677 Use helpers SkColorGetA, SkColorGetR, SkColorGetG, and SkColorGetB to extract
1678 a color component.
1679
1680 #Return Unpremultiplied Color_ARGB ##
1681
1682 #Example
1683 SkPaint paint;
1684 paint.setColor(SK_ColorYELLOW);
1685 SkColor y = paint.getColor();
1686 SkDebugf("Yellow is %d%% red, %d%% green, and %d%% blue.\n", (int) (SkColorGetR(y) / 2.55f),
1687 (int) (SkColorGetG(y) / 2.55f), (int) (SkColorGetB(y) / 2.55f));
1688
1689 #StdOut
1690 Yellow is 100% red, 100% green, and 0% blue.
1691 ##
1692 ##
1693
1694 #SeeAlso SkColor
1695
1696##
1697
1698#Method void setColor(SkColor color)
1699
Cary Clarkab2621d2018-01-30 10:08:57 -05001700#In Color_Methods
1701#Line # sets Color_Alpha and Color_RGB, one drawing color ##
Cary Clarkce101242017-09-01 15:51:02 -04001702 Sets Alpha and Color_RGB used when stroking and filling. The color is a 32-bit value,
Herb Derbyfcac00f2018-05-01 11:57:56 -04001703 Unpremultiplied, packing 8-bit components for Alpha, Red, Blue, and Green.
Cary Clark8032b982017-07-28 11:04:54 -04001704
1705 #Param color Unpremultiplied Color_ARGB ##
Herb Derbyfcac00f2018-05-01 11:57:56 -04001706
Cary Clark0c5f5462017-12-15 11:21:51 -05001707 #Example
Cary Clark8032b982017-07-28 11:04:54 -04001708 SkPaint green1, green2;
1709 unsigned a = 255;
1710 unsigned r = 0;
1711 unsigned g = 255;
1712 unsigned b = 0;
1713 green1.setColor((a << 24) + (r << 16) + (g << 8) + (b << 0));
1714 green2.setColor(0xFF00FF00);
1715 SkDebugf("green1 %c= green2\n", green1 == green2 ? '=' : '!');
1716
1717 #StdOut
1718 green1 == green2
1719 ##
1720 ##
1721
1722 #SeeAlso SkColor setARGB SkColorSetARGB
1723
1724##
Cary Clark08895c42018-02-01 09:37:32 -05001725#Subtopic Color_Methods ##
Cary Clark8032b982017-07-28 11:04:54 -04001726
1727#Subtopic Alpha_Methods
Cary Clark08895c42018-02-01 09:37:32 -05001728#Line # get and set Alpha ##
Cary Clark8032b982017-07-28 11:04:54 -04001729
1730Color_Alpha sets the transparency independent of Color_RGB: Color_RGB_Red, Color_RGB_Blue, and Color_RGB_Green.
1731
1732#Method uint8_t getAlpha() const
1733
Cary Clarkab2621d2018-01-30 10:08:57 -05001734#In Alpha_Methods
1735#Line # returns Color_Alpha, color opacity ##
Cary Clarkce101242017-09-01 15:51:02 -04001736 Retrieves Alpha from the Color used when stroking and filling.
Cary Clark8032b982017-07-28 11:04:54 -04001737
Cary Clarkce101242017-09-01 15:51:02 -04001738 #Return Alpha ranging from zero, fully transparent, to 255, fully opaque ##
Cary Clark8032b982017-07-28 11:04:54 -04001739
1740 #Example
1741 SkPaint paint;
1742 SkDebugf("255 %c= paint.getAlpha()\n", 255 == paint.getAlpha() ? '=' : '!');
1743
1744 #StdOut
1745 255 == paint.getAlpha()
1746 ##
1747 ##
1748
1749##
1750
1751#Method void setAlpha(U8CPU a)
1752
Cary Clarkab2621d2018-01-30 10:08:57 -05001753#In Alpha_Methods
1754#Line # sets Color_Alpha, color opacity ##
Herb Derbyfcac00f2018-05-01 11:57:56 -04001755 Replaces Alpha, leaving Color_RGB
Cary Clark8032b982017-07-28 11:04:54 -04001756 unchanged. An out of range value triggers an assert in the debug
1757 build. a is a value from zero to 255.
1758 a set to zero makes Color fully transparent; a set to 255 makes Color
1759 fully opaque.
1760
Cary Clarkce101242017-09-01 15:51:02 -04001761 #Param a Alpha component of Color ##
Cary Clark8032b982017-07-28 11:04:54 -04001762
1763 #Example
1764 SkPaint paint;
1765 paint.setColor(0x00112233);
1766 paint.setAlpha(0x44);
1767 SkDebugf("0x44112233 %c= paint.getColor()\n", 0x44112233 == paint.getColor() ? '=' : '!');
1768
1769 #StdOut
1770 0x44112233 == paint.getColor()
1771 ##
1772 ##
1773
1774##
1775
Cary Clark08895c42018-02-01 09:37:32 -05001776#Subtopic Alpha_Methods ##
Cary Clark8032b982017-07-28 11:04:54 -04001777
1778#Method void setARGB(U8CPU a, U8CPU r, U8CPU g, U8CPU b)
1779
Cary Clarkab2621d2018-01-30 10:08:57 -05001780#In Color_Methods
1781#Line # sets color by component ##
Cary Clark8032b982017-07-28 11:04:54 -04001782 Sets Color used when drawing solid fills. The color components range from 0 to 255.
Cary Clarkce101242017-09-01 15:51:02 -04001783 The color is Unpremultiplied; Alpha sets the transparency independent of Color_RGB.
Cary Clark8032b982017-07-28 11:04:54 -04001784
1785 #Param a amount of Color_Alpha, from fully transparent (0) to fully opaque (255) ##
1786 #Param r amount of Color_RGB_Red, from no red (0) to full red (255) ##
1787 #Param g amount of Color_RGB_Green, from no green (0) to full green (255) ##
1788 #Param b amount of Color_RGB_Blue, from no blue (0) to full blue (255) ##
Herb Derbyfcac00f2018-05-01 11:57:56 -04001789
Cary Clark8032b982017-07-28 11:04:54 -04001790 #Example
1791 SkPaint transRed1, transRed2;
1792 transRed1.setARGB(255 / 2, 255, 0, 0);
1793 transRed2.setColor(SkColorSetARGB(255 / 2, 255, 0, 0));
1794 SkDebugf("transRed1 %c= transRed2", transRed1 == transRed2 ? '=' : '!');
1795
1796 #StdOut
1797 transRed1 == transRed2
1798 ##
1799 ##
1800
1801 #SeeAlso setColor SkColorSetARGB
1802
1803##
1804
Cary Clark8032b982017-07-28 11:04:54 -04001805# ------------------------------------------------------------------------------
Cary Clark08895c42018-02-01 09:37:32 -05001806#Subtopic Style
1807#Line # geometry filling, stroking ##
Cary Clark8032b982017-07-28 11:04:54 -04001808
1809Style specifies if the geometry is filled, stroked, or both filled and stroked.
1810Some shapes ignore Style and are always drawn filled or stroked.
1811
1812Set Style to kFill_Style to fill the shape.
1813The fill covers the area inside the geometry for most shapes.
1814
1815Set Style to kStroke_Style to stroke the shape.
1816
1817# ------------------------------------------------------------------------------
1818#Subtopic Fill
Cary Clark08895c42018-02-01 09:37:32 -05001819#Line # fill and stroke ##
Cary Clark8032b982017-07-28 11:04:54 -04001820#ToDo write up whatever generalities make sense to describe filling ##
1821
1822#SeeAlso Path_Fill_Type
Cary Clark08895c42018-02-01 09:37:32 -05001823#Subtopic Fill ##
Cary Clark8032b982017-07-28 11:04:54 -04001824
1825#Subtopic Stroke
Cary Clark08895c42018-02-01 09:37:32 -05001826#Line # lines and curves with width ##
Cary Clarkbc5697d2017-10-04 14:31:33 -04001827The stroke covers the area described by following the shape edge with a pen or brush of
Cary Clark8032b982017-07-28 11:04:54 -04001828Stroke_Width. The area covered where the shape starts and stops is described by Stroke_Cap.
1829The area covered where the shape turns a corner is described by Stroke_Join.
Cary Clarkbc5697d2017-10-04 14:31:33 -04001830The stroke is centered on the shape; it extends equally on either side of the shape edge.
Cary Clark8032b982017-07-28 11:04:54 -04001831
1832As Stroke_Width gets smaller, the drawn path frame is thinner. Stroke_Width less than one
1833may have gaps, and if kAntiAlias_Flag is set, Color_Alpha will increase to visually decrease coverage.
Cary Clark08895c42018-02-01 09:37:32 -05001834#Subtopic Stroke ##
Cary Clark8032b982017-07-28 11:04:54 -04001835
1836#Subtopic Hairline
Cary Clark08895c42018-02-01 09:37:32 -05001837#Line # lines and curves with minimal width ##
Cary Clark8032b982017-07-28 11:04:54 -04001838#Alias Hairline # maybe should be Stroke_Hairline ?
1839
1840Stroke_Width of zero has a special meaning and switches drawing to use Hairline.
Herb Derbyfcac00f2018-05-01 11:57:56 -04001841Hairline draws the thinnest continuous frame. If kAntiAlias_Flag is clear, adjacent pixels
1842flow horizontally, vertically,or diagonally.
Cary Clark8032b982017-07-28 11:04:54 -04001843
Cary Clarkce101242017-09-01 15:51:02 -04001844#ToDo what is the description of Anti-aliased hairlines? ##
Cary Clark8032b982017-07-28 11:04:54 -04001845
1846Path drawing with Hairline may hit the same pixel more than once. For instance, Path containing
1847two lines in one Path_Contour will draw the corner point once, but may both lines may draw the adjacent
1848pixel. If kAntiAlias_Flag is set, transparency is applied twice, resulting in a darker pixel. Some
1849GPU-backed implementations apply transparency at a later drawing stage, avoiding double hit pixels
1850while stroking.
1851
Cary Clark08895c42018-02-01 09:37:32 -05001852#Subtopic Hairline ##
Cary Clark8032b982017-07-28 11:04:54 -04001853
1854#Enum Style
Cary Clark08895c42018-02-01 09:37:32 -05001855#Line # stroke, fill, or both ##
Cary Clark8032b982017-07-28 11:04:54 -04001856
1857#Code
1858 enum Style {
1859 kFill_Style,
1860 kStroke_Style,
1861 kStrokeAndFill_Style,
1862 };
Cary Clarkd98f78c2018-04-26 08:32:37 -04001863
1864 static constexpr int kStyleCount = kStrokeAndFill_Style + 1;
Cary Clark8032b982017-07-28 11:04:54 -04001865##
1866
1867Set Style to fill, stroke, or both fill and stroke geometry.
1868The stroke and fill
1869share all paint attributes; for instance, they are drawn with the same color.
1870
1871Use kStrokeAndFill_Style to avoid hitting the same pixels twice with a stroke draw and
1872a fill draw.
1873
1874#Const kFill_Style 0
1875 Set to fill geometry.
Herb Derbyfcac00f2018-05-01 11:57:56 -04001876 Applies to Rect, Region, Round_Rect, Circles, Ovals, Path, and Text.
Cary Clarkce101242017-09-01 15:51:02 -04001877 Bitmap, Image, Patches, Region, Sprites, and Vertices are painted as if
Cary Clark8032b982017-07-28 11:04:54 -04001878 kFill_Style is set, and ignore the set Style.
1879 The Path_Fill_Type specifies additional rules to fill the area outside the path edge,
1880 and to create an unfilled hole inside the shape.
1881 Style is set to kFill_Style by default.
1882##
1883
1884#Const kStroke_Style 1
1885 Set to stroke geometry.
Herb Derbyfcac00f2018-05-01 11:57:56 -04001886 Applies to Rect, Region, Round_Rect, Arcs, Circles, Ovals, Path, and Text.
Cary Clark56356312018-02-08 14:45:18 -05001887 Arcs, Lines, and points, are always drawn as if kStroke_Style is set,
Cary Clark8032b982017-07-28 11:04:54 -04001888 and ignore the set Style.
1889 The stroke construction is unaffected by the Path_Fill_Type.
1890##
1891
1892#Const kStrokeAndFill_Style 2
1893 Set to stroke and fill geometry.
Cary Clarkce101242017-09-01 15:51:02 -04001894 Applies to Rect, Region, Round_Rect, Circles, Ovals, Path, and Text.
Cary Clark8032b982017-07-28 11:04:54 -04001895 Path is treated as if it is set to SkPath::kWinding_FillType,
Herb Derbyfcac00f2018-05-01 11:57:56 -04001896 and the set Path_Fill_Type is ignored.
Cary Clark8032b982017-07-28 11:04:54 -04001897##
1898
Cary Clark8032b982017-07-28 11:04:54 -04001899#Const kStyleCount 3
1900The number of different Style values defined.
1901May be used to verify that Style is a legal value.
1902##
1903
Cary Clarkd98f78c2018-04-26 08:32:37 -04001904#Enum Style ##
Cary Clark8032b982017-07-28 11:04:54 -04001905
1906#Method Style getStyle() const
1907
Cary Clarkab2621d2018-01-30 10:08:57 -05001908#In Style
1909#Line # returns Style: stroke, fill, or both ##
Cary Clark8032b982017-07-28 11:04:54 -04001910 Whether the geometry is filled, stroked, or filled and stroked.
1911
1912 #Return one of:kFill_Style, kStroke_Style, kStrokeAndFill_Style ##
1913
1914 #Example
1915 SkPaint paint;
1916 SkDebugf("SkPaint::kFill_Style %c= paint.getStyle()\n",
1917 SkPaint::kFill_Style == paint.getStyle() ? '=' : '!');
1918
1919 #StdOut
1920 SkPaint::kFill_Style == paint.getStyle()
1921 ##
1922 ##
1923
1924#SeeAlso Style setStyle
1925##
1926
1927#Method void setStyle(Style style)
1928
Cary Clarkab2621d2018-01-30 10:08:57 -05001929#In Style
1930#Line # sets Style: stroke, fill, or both ##
Cary Clark8032b982017-07-28 11:04:54 -04001931 Sets whether the geometry is filled, stroked, or filled and stroked.
1932 Has no effect if style is not a legal Style value.
1933
1934 #Param style one of: kFill_Style, kStroke_Style, kStrokeAndFill_Style
1935 ##
1936
1937 #Example
1938 void draw(SkCanvas* canvas) {
1939 SkPaint paint;
1940 paint.setStrokeWidth(5);
1941 SkRegion region;
1942 region.op(140, 10, 160, 30, SkRegion::kUnion_Op);
1943 region.op(170, 40, 190, 60, SkRegion::kUnion_Op);
1944 SkBitmap bitmap;
1945 bitmap.setInfo(SkImageInfo::MakeA8(50, 50), 50);
1946 uint8_t pixels[50][50];
1947 for (int x = 0; x < 50; ++x) {
1948 for (int y = 0; y < 50; ++y) {
1949 pixels[y][x] = (x + y) % 5 ? 0xFF : 0x00;
1950 }
1951 }
1952 bitmap.setPixels(pixels);
1953 for (auto style : { SkPaint::kFill_Style,
1954 SkPaint::kStroke_Style,
1955 SkPaint::kStrokeAndFill_Style }) {
1956 paint.setStyle(style);
1957 canvas->drawLine(10, 10, 60, 60, paint);
1958 canvas->drawRect({80, 10, 130, 60}, paint);
1959 canvas->drawRegion(region, paint);
1960 canvas->drawBitmap(bitmap, 200, 10, &paint);
1961 canvas->translate(0, 80);
1962 }
1963 }
1964 ##
1965
1966#SeeAlso Style getStyle
1967##
1968
1969#SeeAlso Path_Fill_Type Path_Effect Style_Fill Style_Stroke
Cary Clark08895c42018-02-01 09:37:32 -05001970#Subtopic Style ##
Cary Clark8032b982017-07-28 11:04:54 -04001971
1972# ------------------------------------------------------------------------------
Cary Clark08895c42018-02-01 09:37:32 -05001973#Subtopic Stroke_Width
1974#Line # thickness perpendicular to geometry ##
Cary Clark8032b982017-07-28 11:04:54 -04001975
1976Stroke_Width sets the width for stroking. The width is the thickness
Herb Derbyfcac00f2018-05-01 11:57:56 -04001977of the stroke perpendicular to the path direction when the paint style is
Cary Clark8032b982017-07-28 11:04:54 -04001978set to kStroke_Style or kStrokeAndFill_Style.
1979
1980When width is greater than zero, the stroke encompasses as many pixels partially
1981or fully as needed. When the width equals zero, the paint enables hairlines;
Herb Derbyfcac00f2018-05-01 11:57:56 -04001982the stroke is always one pixel wide.
Cary Clark8032b982017-07-28 11:04:54 -04001983
Cary Clarkbc5697d2017-10-04 14:31:33 -04001984The stroke dimensions are scaled by the canvas matrix, but Hairline stroke
Cary Clark8032b982017-07-28 11:04:54 -04001985remains one pixel wide regardless of scaling.
1986
1987The default width for the paint is zero.
1988
1989#Example
1990#Height 170
1991 #Platform raster gpu
1992 #Description
Herb Derbyfcac00f2018-05-01 11:57:56 -04001993 The pixels hit to represent thin lines vary with the angle of the
Cary Clarkbc5697d2017-10-04 14:31:33 -04001994 line and the platform implementation.
Cary Clark8032b982017-07-28 11:04:54 -04001995 ##
1996 void draw(SkCanvas* canvas) {
1997 SkPaint paint;
Herb Derbyfcac00f2018-05-01 11:57:56 -04001998 for (bool antialias : { false, true }) {
Cary Clark8032b982017-07-28 11:04:54 -04001999 paint.setAntiAlias(antialias);
2000 for (int width = 0; width <= 4; ++width) {
2001 SkScalar offset = antialias * 100 + width * 20;
2002 paint.setStrokeWidth(width * 0.25f);
2003 canvas->drawLine(10 + offset, 10, 20 + offset, 60, paint);
2004 canvas->drawLine(10 + offset, 110, 60 + offset, 160, paint);
2005 }
2006 }
2007 }
2008##
2009
2010#Method SkScalar getStrokeWidth() const
2011
Cary Clarkab2621d2018-01-30 10:08:57 -05002012#In Stroke_Width
2013#Line # returns thickness of the stroke ##
Cary Clark8032b982017-07-28 11:04:54 -04002014 Returns the thickness of the pen used by Paint to
2015 outline the shape.
2016
2017 #Return zero for Hairline, greater than zero for pen thickness ##
Herb Derbyfcac00f2018-05-01 11:57:56 -04002018
Cary Clark8032b982017-07-28 11:04:54 -04002019 #Example
2020 SkPaint paint;
2021 SkDebugf("0 %c= paint.getStrokeWidth()\n", 0 == paint.getStrokeWidth() ? '=' : '!');
2022
2023 #StdOut
2024 0 == paint.getStrokeWidth()
2025 ##
2026 ##
2027
2028##
2029
2030#Method void setStrokeWidth(SkScalar width)
2031
Cary Clarkab2621d2018-01-30 10:08:57 -05002032#In Stroke_Width
2033#Line # sets thickness of the stroke ##
Cary Clark8032b982017-07-28 11:04:54 -04002034 Sets the thickness of the pen used by the paint to
Herb Derbyfcac00f2018-05-01 11:57:56 -04002035 outline the shape.
2036 Has no effect if width is less than zero.
Cary Clark8032b982017-07-28 11:04:54 -04002037
Herb Derbyfcac00f2018-05-01 11:57:56 -04002038 #Param width zero thickness for Hairline; greater than zero for pen thickness
Cary Clark8032b982017-07-28 11:04:54 -04002039 ##
2040
2041 #Example
2042 SkPaint paint;
2043 paint.setStrokeWidth(5);
2044 paint.setStrokeWidth(-1);
2045 SkDebugf("5 %c= paint.getStrokeWidth()\n", 5 == paint.getStrokeWidth() ? '=' : '!');
2046
2047 #StdOut
2048 5 == paint.getStrokeWidth()
2049 ##
2050 ##
2051
2052##
2053
Cary Clark08895c42018-02-01 09:37:32 -05002054#Subtopic Stroke_Width ##
Cary Clark8032b982017-07-28 11:04:54 -04002055# ------------------------------------------------------------------------------
Cary Clark08895c42018-02-01 09:37:32 -05002056#Subtopic Miter_Limit
2057#Line # maximum length of stroked corners ##
Cary Clark8032b982017-07-28 11:04:54 -04002058
2059Miter_Limit specifies the maximum miter length,
2060relative to the stroke width.
2061
2062Miter_Limit is used when the Stroke_Join
2063is set to kMiter_Join, and the Style is either kStroke_Style
2064or kStrokeAndFill_Style.
2065
2066If the miter at a corner exceeds this limit, kMiter_Join
2067is replaced with kBevel_Join.
2068
2069Miter_Limit can be computed from the corner angle:
2070
2071#Formula
2072 miter limit = 1 / sin ( angle / 2 )
2073#Formula ##
2074
2075Miter_Limit default value is 4.
2076The default may be changed at compile time by setting SkPaintDefaults_MiterLimit
Cary Clarkce101242017-09-01 15:51:02 -04002077in "SkUserConfig.h" or as a define supplied by the build environment.
Cary Clark8032b982017-07-28 11:04:54 -04002078
2079Here are some miter limits and the angles that triggers them.
2080#Table
2081#Legend
2082 # miter limit # angle in degrees ##
2083#Legend ##
2084 # 10 # 11.48 ##
2085 # 9 # 12.76 ##
2086 # 8 # 14.36 ##
2087 # 7 # 16.43 ##
2088 # 6 # 19.19 ##
2089 # 5 # 23.07 ##
2090 # 4 # 28.96 ##
2091 # 3 # 38.94 ##
2092 # 2 # 60 ##
2093 # 1 # 180 ##
2094#Table ##
2095
2096#Example
2097 #Height 170
2098 #Width 384
2099 #Description
2100 This example draws a stroked corner and the miter length beneath.
2101 When the miter limit is decreased slightly, the miter join is replaced
2102 by a bevel join.
2103 ##
2104 void draw(SkCanvas* canvas) {
2105 SkPoint pts[] = {{ 10, 50 }, { 110, 80 }, { 10, 110 }};
2106 SkVector v[] = { pts[0] - pts[1], pts[2] - pts[1] };
2107 SkScalar angle1 = SkScalarATan2(v[0].fY, v[0].fX);
2108 SkScalar angle2 = SkScalarATan2(v[1].fY, v[1].fX);
2109 const SkScalar strokeWidth = 20;
2110 SkScalar miterLimit = 1 / SkScalarSin((angle2 - angle1) / 2);
2111 SkScalar miterLength = strokeWidth * miterLimit;
2112 SkPath path;
2113 path.moveTo(pts[0]);
2114 path.lineTo(pts[1]);
2115 path.lineTo(pts[2]);
2116 SkPaint paint; // set to default kMiter_Join
2117 paint.setAntiAlias(true);
2118 paint.setStyle(SkPaint::kStroke_Style);
2119 paint.setStrokeMiter(miterLimit);
2120 paint.setStrokeWidth(strokeWidth);
2121 canvas->drawPath(path, paint);
2122 paint.setStrokeWidth(1);
2123 canvas->drawLine(pts[1].fX - miterLength / 2, pts[1].fY + 50,
2124 pts[1].fX + miterLength / 2, pts[1].fY + 50, paint);
2125 canvas->translate(200, 0);
2126 miterLimit *= 0.99f;
2127 paint.setStrokeMiter(miterLimit);
2128 paint.setStrokeWidth(strokeWidth);
2129 canvas->drawPath(path, paint);
2130 paint.setStrokeWidth(1);
2131 canvas->drawLine(pts[1].fX - miterLength / 2, pts[1].fY + 50,
2132 pts[1].fX + miterLength / 2, pts[1].fY + 50, paint);
2133 }
2134##
2135
2136#Method SkScalar getStrokeMiter() const
2137
Cary Clarkab2621d2018-01-30 10:08:57 -05002138#In Miter_Limit
2139#Line # returns Miter_Limit, angles with sharp corners ##
Cary Clark8032b982017-07-28 11:04:54 -04002140 The limit at which a sharp corner is drawn beveled.
2141
2142 #Return zero and greater Miter_Limit ##
2143
2144 #Example
2145 SkPaint paint;
2146 SkDebugf("default miter limit == %g\n", paint.getStrokeMiter());
2147
2148 #StdOut
2149 default miter limit == 4
2150 ##
2151 ##
2152
2153 #SeeAlso Miter_Limit setStrokeMiter Join
2154
2155##
2156
2157#Method void setStrokeMiter(SkScalar miter)
2158
Cary Clarkab2621d2018-01-30 10:08:57 -05002159#In Miter_Limit
2160#Line # sets Miter_Limit, angles with sharp corners ##
Cary Clark8032b982017-07-28 11:04:54 -04002161 The limit at which a sharp corner is drawn beveled.
2162 Valid values are zero and greater.
2163 Has no effect if miter is less than zero.
2164
2165 #Param miter zero and greater Miter_Limit
2166 ##
2167
2168 #Example
2169 SkPaint paint;
2170 paint.setStrokeMiter(8);
2171 paint.setStrokeMiter(-1);
2172 SkDebugf("default miter limit == %g\n", paint.getStrokeMiter());
2173
2174 #StdOut
2175 default miter limit == 8
2176 ##
2177 ##
2178
2179 #SeeAlso Miter_Limit getStrokeMiter Join
2180
2181##
2182
Cary Clark08895c42018-02-01 09:37:32 -05002183#Subtopic Miter_Limit ##
Cary Clark8032b982017-07-28 11:04:54 -04002184# ------------------------------------------------------------------------------
Cary Clark08895c42018-02-01 09:37:32 -05002185#Subtopic Stroke_Cap
2186#Line # decorations at ends of open strokes ##
Cary Clark8032b982017-07-28 11:04:54 -04002187
2188#Enum Cap
Cary Clark08895c42018-02-01 09:37:32 -05002189#Line # start and end geometry on stroked shapes ##
Cary Clark8032b982017-07-28 11:04:54 -04002190
2191#Code
2192 enum Cap {
2193 kButt_Cap,
2194 kRound_Cap,
2195 kSquare_Cap,
2196
2197 kLast_Cap = kSquare_Cap,
Cary Clarkbad5ad72017-08-03 17:14:08 -04002198 kDefault_Cap = kButt_Cap,
Cary Clark8032b982017-07-28 11:04:54 -04002199 };
Cary Clark6fc50412017-09-21 12:31:06 -04002200
Cary Clark8032b982017-07-28 11:04:54 -04002201 static constexpr int kCapCount = kLast_Cap + 1;
2202##
2203
2204Stroke_Cap draws at the beginning and end of an open Path_Contour.
2205
2206 #Const kButt_Cap 0
2207 Does not extend the stroke past the beginning or the end.
2208 ##
2209 #Const kRound_Cap 1
2210 Adds a circle with a diameter equal to Stroke_Width at the beginning
2211 and end.
2212 ##
2213 #Const kSquare_Cap 2
2214 Adds a square with sides equal to Stroke_Width at the beginning
2215 and end. The square sides are parallel to the initial and final direction
2216 of the stroke.
2217 ##
2218 #Const kLast_Cap 2
2219 Equivalent to the largest value for Stroke_Cap.
2220 ##
2221 #Const kDefault_Cap 0
2222 Equivalent to kButt_Cap.
2223 Stroke_Cap is set to kButt_Cap by default.
2224 ##
2225
2226 #Const kCapCount 3
2227 The number of different Stroke_Cap values defined.
2228 May be used to verify that Stroke_Cap is a legal value.
2229 ##
2230#Enum ##
2231
Herb Derbyfcac00f2018-05-01 11:57:56 -04002232Stroke describes the area covered by a pen of Stroke_Width as it
Cary Clarkbc5697d2017-10-04 14:31:33 -04002233follows the Path_Contour, moving parallel to the contour direction.
Cary Clark8032b982017-07-28 11:04:54 -04002234
2235If the Path_Contour is not terminated by SkPath::kClose_Verb, the contour has a
2236visible beginning and end.
2237
2238Path_Contour may start and end at the same point; defining Zero_Length_Contour.
2239
2240kButt_Cap and Zero_Length_Contour is not drawn.
Herb Derbyfcac00f2018-05-01 11:57:56 -04002241kRound_Cap and Zero_Length_Contour draws a circle of diameter Stroke_Width
Cary Clark8032b982017-07-28 11:04:54 -04002242at the contour point.
2243kSquare_Cap and Zero_Length_Contour draws an upright square with a side of
2244Stroke_Width at the contour point.
2245
2246Stroke_Cap is kButt_Cap by default.
2247
2248#Example
Cary Clark2ade9972017-11-02 17:49:34 -04002249#Height 200
Cary Clark8032b982017-07-28 11:04:54 -04002250 SkPaint paint;
2251 paint.setStyle(SkPaint::kStroke_Style);
2252 paint.setStrokeWidth(20);
2253 SkPath path;
2254 path.moveTo(30, 30);
2255 path.lineTo(30, 30);
2256 path.moveTo(70, 30);
2257 path.lineTo(90, 40);
2258 for (SkPaint::Cap c : { SkPaint::kButt_Cap, SkPaint::kRound_Cap, SkPaint::kSquare_Cap } ) {
2259 paint.setStrokeCap(c);
2260 canvas->drawPath(path, paint);
2261 canvas->translate(0, 70);
2262 }
2263##
2264
2265#Method Cap getStrokeCap() const
2266
Cary Clarkab2621d2018-01-30 10:08:57 -05002267#In Stroke_Cap
2268#Line # returns Cap, the area drawn at path ends ##
Cary Clark8032b982017-07-28 11:04:54 -04002269 The geometry drawn at the beginning and end of strokes.
2270
2271 #Return one of: kButt_Cap, kRound_Cap, kSquare_Cap ##
2272
2273 #Example
2274 SkPaint paint;
2275 SkDebugf("kButt_Cap %c= default stroke cap\n",
2276 SkPaint::kButt_Cap == paint.getStrokeCap() ? '=' : '!');
2277
2278 #StdOut
2279 kButt_Cap == default stroke cap
2280 ##
2281 ##
2282
2283 #SeeAlso Stroke_Cap setStrokeCap
2284##
2285
2286#Method void setStrokeCap(Cap cap)
2287
Cary Clarkab2621d2018-01-30 10:08:57 -05002288#In Stroke_Cap
2289#Line # sets Cap, the area drawn at path ends ##
Cary Clark8032b982017-07-28 11:04:54 -04002290 The geometry drawn at the beginning and end of strokes.
2291
2292 #Param cap one of: kButt_Cap, kRound_Cap, kSquare_Cap;
2293 has no effect if cap is not valid
Herb Derbyfcac00f2018-05-01 11:57:56 -04002294 ##
Cary Clark8032b982017-07-28 11:04:54 -04002295
2296 #Example
2297 SkPaint paint;
2298 paint.setStrokeCap(SkPaint::kRound_Cap);
2299 paint.setStrokeCap((SkPaint::Cap) SkPaint::kCapCount);
2300 SkDebugf("kRound_Cap %c= paint.getStrokeCap()\n",
2301 SkPaint::kRound_Cap == paint.getStrokeCap() ? '=' : '!');
Herb Derbyfcac00f2018-05-01 11:57:56 -04002302
Cary Clark8032b982017-07-28 11:04:54 -04002303 #StdOut
2304 kRound_Cap == paint.getStrokeCap()
2305 ##
2306 ##
2307
2308 #SeeAlso Stroke_Cap getStrokeCap
2309##
2310
Cary Clark08895c42018-02-01 09:37:32 -05002311#Subtopic Stroke_Cap ##
Cary Clark8032b982017-07-28 11:04:54 -04002312# ------------------------------------------------------------------------------
Cary Clark08895c42018-02-01 09:37:32 -05002313#Subtopic Stroke_Join
2314#Line # decoration at corners of strokes ##
Cary Clark8032b982017-07-28 11:04:54 -04002315
2316Stroke_Join draws at the sharp corners of an open or closed Path_Contour.
2317
Herb Derbyfcac00f2018-05-01 11:57:56 -04002318Stroke describes the area covered by a pen of Stroke_Width as it
Cary Clarkbc5697d2017-10-04 14:31:33 -04002319follows the Path_Contour, moving parallel to the contour direction.
Cary Clark8032b982017-07-28 11:04:54 -04002320
2321If the contour direction changes abruptly, because the tangent direction leading
2322to the end of a curve within the contour does not match the tangent direction of
2323the following curve, the pair of curves meet at Stroke_Join.
2324
2325#Example
Cary Clark2ade9972017-11-02 17:49:34 -04002326#Height 200
Cary Clarka560c472017-11-27 10:44:06 -05002327 SkPaint paint;
2328 paint.setStyle(SkPaint::kStroke_Style);
2329 paint.setStrokeWidth(20);
2330 SkPath path;
2331 path.moveTo(30, 20);
2332 path.lineTo(40, 40);
2333 path.conicTo(70, 20, 100, 20, .707f);
2334 for (SkPaint::Join j : { SkPaint::kMiter_Join, SkPaint::kRound_Join, SkPaint::kBevel_Join } ) {
2335 paint.setStrokeJoin(j);
2336 canvas->drawPath(path, paint);
2337 canvas->translate(0, 70);
2338 }
Cary Clark8032b982017-07-28 11:04:54 -04002339##
2340
2341#Enum Join
Cary Clark08895c42018-02-01 09:37:32 -05002342#Line # corner geometry on stroked shapes ##
Cary Clark8032b982017-07-28 11:04:54 -04002343#Code
2344 enum Join {
2345 kMiter_Join,
2346 kRound_Join,
2347 kBevel_Join,
2348
2349 kLast_Join = kBevel_Join,
Cary Clarkbad5ad72017-08-03 17:14:08 -04002350 kDefault_Join = kMiter_Join,
Cary Clark8032b982017-07-28 11:04:54 -04002351 };
Cary Clark6fc50412017-09-21 12:31:06 -04002352
Cary Clark8032b982017-07-28 11:04:54 -04002353 static constexpr int kJoinCount = kLast_Join + 1;
2354##
2355
Cary Clark1eace2d2017-07-31 07:52:43 -04002356Join specifies how corners are drawn when a shape is stroked. Join
Cary Clark8032b982017-07-28 11:04:54 -04002357affects the four corners of a stroked rectangle, and the connected segments in a
2358stroked path.
2359
2360Choose miter join to draw sharp corners. Choose round join to draw a circle with a
2361radius equal to the stroke width on top of the corner. Choose bevel join to minimally
2362connect the thick strokes.
2363
Herb Derbyfcac00f2018-05-01 11:57:56 -04002364The fill path constructed to describe the stroked path respects the join setting but may
Cary Clark8032b982017-07-28 11:04:54 -04002365not contain the actual join. For instance, a fill path constructed with round joins does
2366not necessarily include circles at each connected segment.
2367
2368#Const kMiter_Join 0
2369 Extends the outside corner to the extent allowed by Miter_Limit.
2370 If the extension exceeds Miter_Limit, kBevel_Join is used instead.
2371##
2372
2373#Const kRound_Join 1
2374 Adds a circle with a diameter of Stroke_Width at the sharp corner.
2375##
2376
2377#Const kBevel_Join 2
2378 Connects the outside edges of the sharp corner.
2379##
2380
2381#Const kLast_Join 2
2382 Equivalent to the largest value for Stroke_Join.
2383##
2384
2385#Const kDefault_Join 1
2386 Equivalent to kMiter_Join.
Herb Derbyfcac00f2018-05-01 11:57:56 -04002387 Stroke_Join is set to kMiter_Join by default.
Cary Clark8032b982017-07-28 11:04:54 -04002388##
2389
2390#Const kJoinCount 3
2391 The number of different Stroke_Join values defined.
2392 May be used to verify that Stroke_Join is a legal value.
2393##
2394
2395#Example
2396#Width 462
2397void draw(SkCanvas* canvas) {
2398 SkPath path;
2399 path.moveTo(10, 50);
2400 path.quadTo(35, 110, 60, 210);
2401 path.quadTo(105, 110, 130, 10);
2402 SkPaint paint; // set to default kMiter_Join
2403 paint.setAntiAlias(true);
2404 paint.setStyle(SkPaint::kStroke_Style);
2405 paint.setStrokeWidth(20);
2406 canvas->drawPath(path, paint);
2407 canvas->translate(150, 0);
2408 paint.setStrokeJoin(SkPaint::kBevel_Join);
2409 canvas->drawPath(path, paint);
2410 canvas->translate(150, 0);
2411 paint.setStrokeJoin(SkPaint::kRound_Join);
2412 canvas->drawPath(path, paint);
2413}
2414##
2415
2416#SeeAlso setStrokeJoin getStrokeJoin setStrokeMiter getStrokeMiter
2417
2418#Enum ##
2419
2420#Method Join getStrokeJoin() const
2421
Cary Clarkab2621d2018-01-30 10:08:57 -05002422#In Stroke_Join
2423#Line # returns Join, geometry on path corners ##
Cary Clark0c5f5462017-12-15 11:21:51 -05002424 The geometry drawn at the corners of strokes.
Cary Clark8032b982017-07-28 11:04:54 -04002425
2426 #Return one of: kMiter_Join, kRound_Join, kBevel_Join ##
2427
2428 #Example
2429 SkPaint paint;
2430 SkDebugf("kMiter_Join %c= default stroke join\n",
2431 SkPaint::kMiter_Join == paint.getStrokeJoin() ? '=' : '!');
2432
2433 #StdOut
2434 kMiter_Join == default stroke join
2435 ##
2436 ##
2437
2438 #SeeAlso Stroke_Join setStrokeJoin
2439##
2440
2441#Method void setStrokeJoin(Join join)
2442
Cary Clarkab2621d2018-01-30 10:08:57 -05002443#In Stroke_Join
2444#Line # sets Join, geometry on path corners ##
Cary Clark0c5f5462017-12-15 11:21:51 -05002445 The geometry drawn at the corners of strokes.
Cary Clark8032b982017-07-28 11:04:54 -04002446
2447 #Param join one of: kMiter_Join, kRound_Join, kBevel_Join;
Herb Derbyfcac00f2018-05-01 11:57:56 -04002448 otherwise, has no effect
Cary Clark8032b982017-07-28 11:04:54 -04002449 ##
2450
2451 #Example
2452 SkPaint paint;
2453 paint.setStrokeJoin(SkPaint::kMiter_Join);
2454 paint.setStrokeJoin((SkPaint::Join) SkPaint::kJoinCount);
2455 SkDebugf("kMiter_Join %c= paint.getStrokeJoin()\n",
2456 SkPaint::kMiter_Join == paint.getStrokeJoin() ? '=' : '!');
2457
2458 #StdOut
2459 kMiter_Join == paint.getStrokeJoin()
2460 ##
2461 ##
2462
2463 #SeeAlso Stroke_Join getStrokeJoin
2464##
2465
2466#SeeAlso Miter_Limit
2467
Cary Clark08895c42018-02-01 09:37:32 -05002468#Subtopic Stroke_Join ##
Cary Clark8032b982017-07-28 11:04:54 -04002469# ------------------------------------------------------------------------------
Cary Clark08895c42018-02-01 09:37:32 -05002470#Subtopic Fill_Path
2471#Line # make Path from Path_Effect, stroking ##
Cary Clark8032b982017-07-28 11:04:54 -04002472
2473Fill_Path creates a Path by applying the Path_Effect, followed by the Style_Stroke.
2474
2475If Paint contains Path_Effect, Path_Effect operates on the source Path; the result
2476replaces the destination Path. Otherwise, the source Path is replaces the
2477destination Path.
2478
2479Fill Path can request the Path_Effect to restrict to a culling rectangle, but
2480the Path_Effect is not required to do so.
2481
Herb Derbyfcac00f2018-05-01 11:57:56 -04002482If Style is kStroke_Style or kStrokeAndFill_Style,
Cary Clark8032b982017-07-28 11:04:54 -04002483and Stroke_Width is greater than zero, the Stroke_Width, Stroke_Cap, Stroke_Join,
2484and Miter_Limit operate on the destination Path, replacing it.
2485
Herb Derbyfcac00f2018-05-01 11:57:56 -04002486Fill Path can specify the precision used by Stroke_Width to approximate the stroke geometry.
Cary Clark8032b982017-07-28 11:04:54 -04002487
2488If the Style is kStroke_Style and the Stroke_Width is zero, getFillPath
2489returns false since Hairline has no filled equivalent.
2490
2491#Method bool getFillPath(const SkPath& src, SkPath* dst, const SkRect* cullRect,
2492 SkScalar resScale = 1) const
Cary Clarkab2621d2018-01-30 10:08:57 -05002493#In Fill_Path
2494#Line # returns fill path equivalent to stroke ##
Cary Clark8032b982017-07-28 11:04:54 -04002495
2496 The filled equivalent of the stroked path.
2497
2498 #Param src Path read to create a filled version ##
2499 #Param dst resulting Path; may be the same as src, but may not be nullptr ##
2500 #Param cullRect optional limit passed to Path_Effect ##
2501 #Param resScale if > 1, increase precision, else if (0 < res < 1) reduce precision
2502 to favor speed and size
2503 ##
2504 #Return true if the path represents Style_Fill, or false if it represents Hairline ##
2505
2506 #Example
2507 #Height 192
2508 #Description
Cary Clarkce101242017-09-01 15:51:02 -04002509 A very small Quad stroke is turned into a filled path with increasing levels of precision.
Herb Derbyfcac00f2018-05-01 11:57:56 -04002510 At the lowest precision, the Quad stroke is approximated by a rectangle.
Cary Clark8032b982017-07-28 11:04:54 -04002511 At the highest precision, the filled path has high fidelity compared to the original stroke.
2512 ##
2513 void draw(SkCanvas* canvas) {
2514 SkPaint strokePaint;
2515 strokePaint.setAntiAlias(true);
2516 strokePaint.setStyle(SkPaint::kStroke_Style);
2517 strokePaint.setStrokeWidth(.1f);
2518 SkPath strokePath;
2519 strokePath.moveTo(.08f, .08f);
2520 strokePath.quadTo(.09f, .08f, .17f, .17f);
2521 SkPath fillPath;
2522 SkPaint outlinePaint(strokePaint);
2523 outlinePaint.setStrokeWidth(2);
2524 SkMatrix scale = SkMatrix::MakeScale(300, 300);
2525 for (SkScalar precision : { 0.01f, .1f, 1.f, 10.f, 100.f } ) {
2526 strokePaint.getFillPath(strokePath, &fillPath, nullptr, precision);
2527 fillPath.transform(scale);
2528 canvas->drawPath(fillPath, outlinePaint);
2529 canvas->translate(60, 0);
2530 if (1.f == precision) canvas->translate(-180, 100);
2531 }
2532 strokePath.transform(scale);
2533 strokePaint.setStrokeWidth(30);
2534 canvas->drawPath(strokePath, strokePaint);
2535 }
2536 ##
2537
2538##
2539
2540#Method bool getFillPath(const SkPath& src, SkPath* dst) const
2541
Cary Clarkab2621d2018-01-30 10:08:57 -05002542#In Fill_Path
Cary Clark8032b982017-07-28 11:04:54 -04002543 The filled equivalent of the stroked path.
2544
2545 Replaces dst with the src path modified by Path_Effect and Style_Stroke.
2546 Path_Effect, if any, is not culled. Stroke_Width is created with default precision.
2547
2548 #Param src Path read to create a filled version ##
2549 #Param dst resulting Path dst may be the same as src, but may not be nullptr ##
2550 #Return true if the path represents Style_Fill, or false if it represents Hairline ##
2551
2552 #Example
2553 #Height 128
2554 void draw(SkCanvas* canvas) {
2555 SkPaint paint;
2556 paint.setStyle(SkPaint::kStroke_Style);
2557 paint.setStrokeWidth(10);
2558 SkPath strokePath;
2559 strokePath.moveTo(20, 20);
2560 strokePath.lineTo(100, 100);
2561 canvas->drawPath(strokePath, paint);
2562 SkPath fillPath;
2563 paint.getFillPath(strokePath, &fillPath);
2564 paint.setStrokeWidth(2);
2565 canvas->translate(40, 0);
2566 canvas->drawPath(fillPath, paint);
2567 }
2568 ##
2569
2570##
2571
2572#SeeAlso Style_Stroke Stroke_Width Path_Effect
2573
Cary Clark08895c42018-02-01 09:37:32 -05002574#Subtopic Fill_Path ##
Cary Clark8032b982017-07-28 11:04:54 -04002575# ------------------------------------------------------------------------------
Cary Clark08895c42018-02-01 09:37:32 -05002576#Subtopic Shader_Methods
2577#Line # get and set Shader ##
Cary Clark8032b982017-07-28 11:04:54 -04002578
2579Shader defines the colors used when drawing a shape.
2580Shader may be an image, a gradient, or a computed fill.
Herb Derbyfcac00f2018-05-01 11:57:56 -04002581If Paint has no Shader, then Color fills the shape.
Cary Clark8032b982017-07-28 11:04:54 -04002582
2583Shader is modulated by Color_Alpha component of Color.
2584If Shader object defines only Color_Alpha, then Color modulated by Color_Alpha describes
2585the fill.
2586
2587The drawn transparency can be modified without altering Shader, by changing Color_Alpha.
2588
2589#Example
2590void draw(SkCanvas* canvas) {
2591 SkPaint paint;
2592 SkPoint center = { 50, 50 };
2593 SkScalar radius = 50;
2594 const SkColor colors[] = { 0xFFFFFFFF, 0xFF000000 };
2595 paint.setShader(SkGradientShader::MakeRadial(center, radius, colors,
2596 nullptr, SK_ARRAY_COUNT(colors), SkShader::kClamp_TileMode));
2597 for (SkScalar a : { 0.3f, 0.6f, 1.0f } ) {
2598 paint.setAlpha((int) (a * 255));
2599 canvas->drawCircle(center.fX, center.fY, radius, paint);
2600 canvas->translate(70, 70);
2601 }
2602}
2603##
2604
2605If Shader generates only Color_Alpha then all components of Color modulate the output.
2606
2607#Example
2608void draw(SkCanvas* canvas) {
2609 SkPaint paint;
2610 SkBitmap bitmap;
2611 bitmap.setInfo(SkImageInfo::MakeA8(5, 1), 5); // bitmap only contains alpha
2612 uint8_t pixels[5] = { 0x22, 0x55, 0x88, 0xBB, 0xFF };
2613 bitmap.setPixels(pixels);
Herb Derbyfcac00f2018-05-01 11:57:56 -04002614 paint.setShader(SkShader::MakeBitmapShader(bitmap,
Cary Clark8032b982017-07-28 11:04:54 -04002615 SkShader::kMirror_TileMode, SkShader::kMirror_TileMode));
2616 for (SkColor c : { SK_ColorRED, SK_ColorBLUE, SK_ColorGREEN } ) {
2617 paint.setColor(c); // all components in color affect shader
2618 canvas->drawCircle(50, 50, 50, paint);
2619 canvas->translate(70, 70);
2620 }
2621}
2622##
2623
2624#Method SkShader* getShader() const
2625
Cary Clarkab2621d2018-01-30 10:08:57 -05002626#In Shader_Methods
2627#Line # returns Shader, multiple drawing colors; gradients ##
Cary Clark8032b982017-07-28 11:04:54 -04002628 Optional colors used when filling a path, such as a gradient.
2629
2630 Does not alter Shader Reference_Count.
Herb Derbyfcac00f2018-05-01 11:57:56 -04002631
Cary Clark8032b982017-07-28 11:04:54 -04002632 #Return Shader if previously set, nullptr otherwise ##
2633
2634 #Example
2635 void draw(SkCanvas* canvas) {
2636 SkPaint paint;
2637 SkDebugf("nullptr %c= shader\n", paint.getShader() ? '!' : '=');
2638 paint.setShader(SkShader::MakeEmptyShader());
2639 SkDebugf("nullptr %c= shader\n", paint.getShader() ? '!' : '=');
2640 }
2641
2642 #StdOut
2643 nullptr == shader
2644 nullptr != shader
2645 ##
2646 ##
2647
2648##
2649
2650#Method sk_sp<SkShader> refShader() const
2651
Cary Clarkab2621d2018-01-30 10:08:57 -05002652#In Shader_Methods
2653#Line # references Shader, multiple drawing colors; gradients ##
Cary Clark8032b982017-07-28 11:04:54 -04002654 Optional colors used when filling a path, such as a gradient.
2655
2656 Increases Shader Reference_Count by one.
2657
2658 #Return Shader if previously set, nullptr otherwise ##
2659
2660 #Example
2661 void draw(SkCanvas* canvas) {
2662 SkPaint paint1, paint2;
2663 paint1.setShader(SkShader::MakeEmptyShader());
2664 SkDebugf("shader unique: %s\n", paint1.getShader()->unique() ? "true" : "false");
2665 paint2.setShader(paint1.refShader());
2666 SkDebugf("shader unique: %s\n", paint1.getShader()->unique() ? "true" : "false");
2667 }
2668
2669 #StdOut
2670 shader unique: true
2671 shader unique: false
2672 ##
2673 ##
2674
2675##
2676
2677#Method void setShader(sk_sp<SkShader> shader)
2678
Cary Clarkab2621d2018-01-30 10:08:57 -05002679#In Shader_Methods
2680#Line # sets Shader, multiple drawing colors; gradients ##
Cary Clark8032b982017-07-28 11:04:54 -04002681 Optional colors used when filling a path, such as a gradient.
2682
Cary Clarkd0530ba2017-09-14 11:25:39 -04002683 Sets Shader to shader, decreasing Reference_Count of the previous Shader.
Cary Clark6fc50412017-09-21 12:31:06 -04002684 Increments shader Reference_Count by one.
Cary Clark8032b982017-07-28 11:04:54 -04002685
2686 #Param shader how geometry is filled with color; if nullptr, Color is used instead ##
2687
2688 #Example
2689 #Height 64
2690 void draw(SkCanvas* canvas) {
2691 SkPaint paint;
2692 paint.setColor(SK_ColorBLUE);
2693 paint.setShader(SkShader::MakeColorShader(SK_ColorRED));
2694 canvas->drawRect(SkRect::MakeWH(40, 40), paint);
2695 paint.setShader(nullptr);
2696 canvas->translate(50, 0);
2697 canvas->drawRect(SkRect::MakeWH(40, 40), paint);
2698 }
2699 ##
2700
2701##
2702
Cary Clark08895c42018-02-01 09:37:32 -05002703#Subtopic Shader_Methods ##
Cary Clark8032b982017-07-28 11:04:54 -04002704# ------------------------------------------------------------------------------
Cary Clark08895c42018-02-01 09:37:32 -05002705#Subtopic Color_Filter_Methods
2706#Line # get and set Color_Filter ##
Cary Clark8032b982017-07-28 11:04:54 -04002707
2708Color_Filter alters the color used when drawing a shape.
2709Color_Filter may apply Blend_Mode, transform the color through a matrix, or composite multiple filters.
2710If Paint has no Color_Filter, the color is unaltered.
2711
2712The drawn transparency can be modified without altering Color_Filter, by changing Color_Alpha.
2713
2714#Example
2715#Height 128
2716void draw(SkCanvas* canvas) {
2717 SkPaint paint;
2718 paint.setColorFilter(SkColorMatrixFilter::MakeLightingFilter(0xFFFFFF, 0xFF0000));
2719 for (SkColor c : { SK_ColorBLACK, SK_ColorGREEN } ) {
2720 paint.setColor(c);
2721 canvas->drawRect(SkRect::MakeXYWH(10, 10, 50, 50), paint);
2722 paint.setAlpha(0x80);
2723 canvas->drawRect(SkRect::MakeXYWH(60, 60, 50, 50), paint);
2724 canvas->translate(100, 0);
2725 }
2726}
2727##
2728
2729#Method SkColorFilter* getColorFilter() const
2730
Cary Clarkab2621d2018-01-30 10:08:57 -05002731#In Color_Filter_Methods
2732#Line # returns Color_Filter, how colors are altered ##
Cary Clark8032b982017-07-28 11:04:54 -04002733 Returns Color_Filter if set, or nullptr.
2734 Does not alter Color_Filter Reference_Count.
Herb Derbyfcac00f2018-05-01 11:57:56 -04002735
Cary Clark8032b982017-07-28 11:04:54 -04002736 #Return Color_Filter if previously set, nullptr otherwise ##
2737
2738 #Example
2739 void draw(SkCanvas* canvas) {
2740 SkPaint paint;
2741 SkDebugf("nullptr %c= color filter\n", paint.getColorFilter() ? '!' : '=');
2742 paint.setColorFilter(SkColorFilter::MakeModeFilter(SK_ColorLTGRAY, SkBlendMode::kSrcIn));
2743 SkDebugf("nullptr %c= color filter\n", paint.getColorFilter() ? '!' : '=');
2744 }
2745
2746 #StdOut
2747 nullptr == color filter
2748 nullptr != color filter
2749 ##
2750 ##
2751##
2752
2753#Method sk_sp<SkColorFilter> refColorFilter() const
2754
Cary Clarkab2621d2018-01-30 10:08:57 -05002755#In Color_Filter_Methods
2756#Line # references Color_Filter, how colors are altered ##
Cary Clark8032b982017-07-28 11:04:54 -04002757 Returns Color_Filter if set, or nullptr.
2758 Increases Color_Filter Reference_Count by one.
2759
2760 #Return Color_Filter if set, or nullptr ##
2761
2762 #Example
2763 void draw(SkCanvas* canvas) {
2764 SkPaint paint1, paint2;
2765 paint1.setColorFilter(SkColorFilter::MakeModeFilter(0xFFFF0000, SkBlendMode::kSrcATop));
2766 SkDebugf("color filter unique: %s\n", paint1.getColorFilter()->unique() ? "true" : "false");
2767 paint2.setColorFilter(paint1.refColorFilter());
2768 SkDebugf("color filter unique: %s\n", paint1.getColorFilter()->unique() ? "true" : "false");
2769 }
2770
2771 #StdOut
2772 color filter unique: true
2773 color filter unique: false
2774 ##
2775 ##
2776##
2777
2778#Method void setColorFilter(sk_sp<SkColorFilter> colorFilter)
2779
Cary Clarkab2621d2018-01-30 10:08:57 -05002780#In Color_Filter_Methods
2781#Line # sets Color_Filter, alters color ##
Cary Clark6fc50412017-09-21 12:31:06 -04002782Sets Color_Filter to filter, decreasing Reference_Count of the previous
2783Color_Filter. Pass nullptr to clear Color_Filter.
2784
2785Increments filter Reference_Count by one.
Cary Clark8032b982017-07-28 11:04:54 -04002786
2787 #Param colorFilter Color_Filter to apply to subsequent draw ##
2788
2789 #Example
2790 #Height 64
2791 void draw(SkCanvas* canvas) {
2792 SkPaint paint;
2793 paint.setColorFilter(SkColorFilter::MakeModeFilter(SK_ColorLTGRAY, SkBlendMode::kSrcIn));
2794 canvas->drawRect(SkRect::MakeWH(50, 50), paint);
2795 paint.setColorFilter(nullptr);
2796 canvas->translate(70, 0);
2797 canvas->drawRect(SkRect::MakeWH(50, 50), paint);
2798 }
2799 ##
2800
2801##
2802
Cary Clark08895c42018-02-01 09:37:32 -05002803#Subtopic Color_Filter_Methods ##
Cary Clark8032b982017-07-28 11:04:54 -04002804# ------------------------------------------------------------------------------
Cary Clark08895c42018-02-01 09:37:32 -05002805#Subtopic Blend_Mode_Methods
2806#Line # get and set Blend_Mode ##
Cary Clark8032b982017-07-28 11:04:54 -04002807
2808Blend_Mode describes how Color combines with the destination color.
2809The default setting, SkBlendMode::kSrcOver, draws the source color
2810over the destination color.
2811
2812#Example
2813void draw(SkCanvas* canvas) {
2814 SkPaint normal, blender;
2815 normal.setColor(0xFF58a889);
2816 blender.setColor(0xFF8958a8);
2817 canvas->clear(0);
2818 for (SkBlendMode m : { SkBlendMode::kSrcOver, SkBlendMode::kSrcIn, SkBlendMode::kSrcOut } ) {
2819 normal.setBlendMode(SkBlendMode::kSrcOver);
2820 canvas->drawOval(SkRect::MakeXYWH(30, 30, 30, 80), normal);
2821 blender.setBlendMode(m);
2822 canvas->drawOval(SkRect::MakeXYWH(10, 50, 80, 30), blender);
2823 canvas->translate(70, 70);
2824 }
2825}
2826##
2827
2828#SeeAlso Blend_Mode
2829
2830#Method SkBlendMode getBlendMode() const
2831
Cary Clarkab2621d2018-01-30 10:08:57 -05002832#In Blend_Mode_Methods
2833#Line # returns Blend_Mode, how colors combine with Device ##
Cary Clark8032b982017-07-28 11:04:54 -04002834 Returns Blend_Mode.
Cary Clark579985c2017-07-31 11:48:27 -04002835 By default, returns SkBlendMode::kSrcOver.
Cary Clark8032b982017-07-28 11:04:54 -04002836
2837 #Return mode used to combine source color with destination color ##
2838
2839 #Example
2840 void draw(SkCanvas* canvas) {
2841 SkPaint paint;
Herb Derbyfcac00f2018-05-01 11:57:56 -04002842 SkDebugf("kSrcOver %c= getBlendMode\n",
Cary Clark8032b982017-07-28 11:04:54 -04002843 SkBlendMode::kSrcOver == paint.getBlendMode() ? '=' : '!');
2844 paint.setBlendMode(SkBlendMode::kSrc);
Herb Derbyfcac00f2018-05-01 11:57:56 -04002845 SkDebugf("kSrcOver %c= getBlendMode\n",
Cary Clark8032b982017-07-28 11:04:54 -04002846 SkBlendMode::kSrcOver == paint.getBlendMode() ? '=' : '!');
2847 }
2848
2849 #StdOut
2850 kSrcOver == getBlendMode
2851 kSrcOver != getBlendMode
2852 ##
2853 ##
2854
2855##
2856
2857#Method bool isSrcOver() const
2858
Cary Clarkab2621d2018-01-30 10:08:57 -05002859#In Blend_Mode_Methods
2860#Line # returns true if Blend_Mode is SkBlendMode::kSrcOver ##
Cary Clark8032b982017-07-28 11:04:54 -04002861 Returns true if Blend_Mode is SkBlendMode::kSrcOver, the default.
2862
2863 #Return true if Blend_Mode is SkBlendMode::kSrcOver ##
2864
2865 #Example
2866 void draw(SkCanvas* canvas) {
2867 SkPaint paint;
2868 SkDebugf("isSrcOver %c= true\n", paint.isSrcOver() ? '=' : '!');
2869 paint.setBlendMode(SkBlendMode::kSrc);
2870 SkDebugf("isSrcOver %c= true\n", paint.isSrcOver() ? '=' : '!');
2871 }
2872
2873 #StdOut
2874 isSrcOver == true
2875 isSrcOver != true
2876 ##
2877 ##
2878
2879##
2880
2881#Method void setBlendMode(SkBlendMode mode)
2882
Cary Clarkab2621d2018-01-30 10:08:57 -05002883#In Blend_Mode_Methods
2884#Line # sets Blend_Mode, how colors combine with destination ##
Herb Derbyfcac00f2018-05-01 11:57:56 -04002885 Sets Blend_Mode to mode.
Cary Clark8032b982017-07-28 11:04:54 -04002886 Does not check for valid input.
2887
2888 #Param mode SkBlendMode used to combine source color and destination ##
2889
2890 #Example
2891 void draw(SkCanvas* canvas) {
2892 SkPaint paint;
2893 SkDebugf("isSrcOver %c= true\n", paint.isSrcOver() ? '=' : '!');
2894 paint.setBlendMode(SkBlendMode::kSrc);
2895 SkDebugf("isSrcOver %c= true\n", paint.isSrcOver() ? '=' : '!');
2896 }
2897
2898 #StdOut
2899 isSrcOver == true
2900 isSrcOver != true
2901 ##
2902 ##
2903
2904##
2905
Cary Clark08895c42018-02-01 09:37:32 -05002906#Subtopic Blend_Mode_Methods ##
Cary Clark8032b982017-07-28 11:04:54 -04002907# ------------------------------------------------------------------------------
Cary Clark08895c42018-02-01 09:37:32 -05002908#Subtopic Path_Effect_Methods
2909#Line # get and set Path_Effect ##
Cary Clark8032b982017-07-28 11:04:54 -04002910
2911Path_Effect modifies the path geometry before drawing it.
2912Path_Effect may implement dashing, custom fill effects and custom stroke effects.
2913If Paint has no Path_Effect, the path geometry is unaltered when filled or stroked.
2914
2915#Example
2916#Height 160
2917 void draw(SkCanvas* canvas) {
2918 SkPaint paint;
2919 paint.setStyle(SkPaint::kStroke_Style);
2920 paint.setStrokeWidth(16);
2921 SkScalar intervals[] = {30, 10};
2922 paint.setPathEffect(SkDashPathEffect::Make(intervals, SK_ARRAY_COUNT(intervals), 1));
2923 canvas->drawRoundRect({20, 20, 120, 120}, 20, 20, paint);
2924 }
2925##
2926
2927#SeeAlso Path_Effect
2928
2929#Method SkPathEffect* getPathEffect() const
2930
Cary Clarkab2621d2018-01-30 10:08:57 -05002931#In Path_Effect_Methods
2932#Line # returns Path_Effect, modifications to path geometry; dashing ##
Cary Clark8032b982017-07-28 11:04:54 -04002933 Returns Path_Effect if set, or nullptr.
2934 Does not alter Path_Effect Reference_Count.
Herb Derbyfcac00f2018-05-01 11:57:56 -04002935
Cary Clark8032b982017-07-28 11:04:54 -04002936 #Return Path_Effect if previously set, nullptr otherwise ##
2937
2938 #Example
2939 void draw(SkCanvas* canvas) {
2940 SkPaint paint;
2941 SkDebugf("nullptr %c= path effect\n", paint.getPathEffect() ? '!' : '=');
2942 paint.setPathEffect(SkCornerPathEffect::Make(10));
2943 SkDebugf("nullptr %c= path effect\n", paint.getPathEffect() ? '!' : '=');
2944 }
2945
2946 #StdOut
2947 nullptr == path effect
2948 nullptr != path effect
2949 ##
2950 ##
2951
2952##
2953
2954
2955#Method sk_sp<SkPathEffect> refPathEffect() const
2956
Cary Clarkab2621d2018-01-30 10:08:57 -05002957#In Path_Effect_Methods
2958#Line # references Path_Effect, modifications to path geometry; dashing ##
Cary Clark8032b982017-07-28 11:04:54 -04002959 Returns Path_Effect if set, or nullptr.
2960 Increases Path_Effect Reference_Count by one.
2961
2962 #Return Path_Effect if previously set, nullptr otherwise ##
2963
2964 #Example
2965 void draw(SkCanvas* canvas) {
2966 SkPaint paint1, paint2;
Cary Clarka560c472017-11-27 10:44:06 -05002967 SkScalar intervals[] = {1, 2};
2968 paint1.setPathEffect(SkDashPathEffect::Make(intervals, SK_ARRAY_COUNT(intervals), 10));
Cary Clark8032b982017-07-28 11:04:54 -04002969 SkDebugf("path effect unique: %s\n", paint1.getPathEffect()->unique() ? "true" : "false");
2970 paint2.setPathEffect(paint1.refPathEffect());
2971 SkDebugf("path effect unique: %s\n", paint1.getPathEffect()->unique() ? "true" : "false");
2972 }
2973
2974 #StdOut
2975 path effect unique: true
2976 path effect unique: false
2977 ##
2978 ##
2979
2980##
2981
2982
2983#Method void setPathEffect(sk_sp<SkPathEffect> pathEffect)
2984
Cary Clarkab2621d2018-01-30 10:08:57 -05002985#In Path_Effect_Methods
2986#Line # sets Path_Effect, modifications to path geometry; dashing ##
Cary Clark6fc50412017-09-21 12:31:06 -04002987Sets Path_Effect to pathEffect, decreasing Reference_Count of the previous
2988Path_Effect. Pass nullptr to leave the path geometry unaltered.
2989
2990Increments pathEffect Reference_Count by one.
Cary Clark8032b982017-07-28 11:04:54 -04002991
2992 #Param pathEffect replace Path with a modification when drawn ##
2993
2994 #Example
2995 void draw(SkCanvas* canvas) {
2996 SkPaint paint;
2997 paint.setPathEffect(SkDiscretePathEffect::Make(3, 5));
2998 canvas->drawRect(SkRect::MakeXYWH(40, 40, 175, 175), paint);
2999 }
3000 ##
3001
3002##
3003
Cary Clark08895c42018-02-01 09:37:32 -05003004#Subtopic Path_Effect_Methods ##
Cary Clark8032b982017-07-28 11:04:54 -04003005# ------------------------------------------------------------------------------
Cary Clark08895c42018-02-01 09:37:32 -05003006#Subtopic Mask_Filter_Methods
3007#Line # get and set Mask_Filter ##
Cary Clark8032b982017-07-28 11:04:54 -04003008
Cary Clarkce101242017-09-01 15:51:02 -04003009Mask_Filter uses coverage of the shape drawn to create Mask_Alpha.
Mike Reed8ad91a92018-01-19 19:09:32 -05003010Mask_Filter takes a Mask, and returns a Mask.
Cary Clark6fc50412017-09-21 12:31:06 -04003011
3012Mask_Filter may change the geometry and transparency of the shape, such as
3013creating a blur effect. Set Mask_Filter to nullptr to prevent Mask_Filter from
3014modifying the draw.
Cary Clark8032b982017-07-28 11:04:54 -04003015
3016#Example
3017 void draw(SkCanvas* canvas) {
3018 SkPaint paint;
Cary Clark681287e2018-03-16 11:34:15 -04003019 paint.setMaskFilter(SkMaskFilter::MakeBlur(kSolid_SkBlurStyle, 3));
Cary Clark8032b982017-07-28 11:04:54 -04003020 canvas->drawRect(SkRect::MakeXYWH(40, 40, 175, 175), paint);
3021 }
3022##
3023
3024#Method SkMaskFilter* getMaskFilter() const
3025
Cary Clarkab2621d2018-01-30 10:08:57 -05003026#In Mask_Filter_Methods
3027#Line # returns Mask_Filter, alterations to Mask_Alpha ##
Cary Clark8032b982017-07-28 11:04:54 -04003028 Returns Mask_Filter if set, or nullptr.
3029 Does not alter Mask_Filter Reference_Count.
Herb Derbyfcac00f2018-05-01 11:57:56 -04003030
Cary Clark8032b982017-07-28 11:04:54 -04003031 #Return Mask_Filter if previously set, nullptr otherwise ##
3032
3033 #Example
3034 void draw(SkCanvas* canvas) {
3035 SkPaint paint;
3036 SkDebugf("nullptr %c= mask filter\n", paint.getMaskFilter() ? '!' : '=');
Cary Clark681287e2018-03-16 11:34:15 -04003037 paint.setMaskFilter(SkMaskFilter::MakeBlur(kOuter_SkBlurStyle, 3));
Cary Clark8032b982017-07-28 11:04:54 -04003038 SkDebugf("nullptr %c= mask filter\n", paint.getMaskFilter() ? '!' : '=');
3039 }
3040
3041 #StdOut
3042 nullptr == mask filter
3043 nullptr != mask filter
3044 ##
3045 ##
3046
3047##
3048
3049#Method sk_sp<SkMaskFilter> refMaskFilter() const
3050
Cary Clarkab2621d2018-01-30 10:08:57 -05003051#In Mask_Filter_Methods
3052#Line # references Mask_Filter, alterations to Mask_Alpha ##
Cary Clark8032b982017-07-28 11:04:54 -04003053 Returns Mask_Filter if set, or nullptr.
Cary Clark6fc50412017-09-21 12:31:06 -04003054
Cary Clark8032b982017-07-28 11:04:54 -04003055 Increases Mask_Filter Reference_Count by one.
Herb Derbyfcac00f2018-05-01 11:57:56 -04003056
Cary Clark8032b982017-07-28 11:04:54 -04003057 #Return Mask_Filter if previously set, nullptr otherwise ##
3058
3059 #Example
3060 void draw(SkCanvas* canvas) {
3061 SkPaint paint1, paint2;
Cary Clark681287e2018-03-16 11:34:15 -04003062 paint1.setMaskFilter(SkMaskFilter::MakeBlur(kNormal_SkBlurStyle, 1));
Cary Clark8032b982017-07-28 11:04:54 -04003063 SkDebugf("mask filter unique: %s\n", paint1.getMaskFilter()->unique() ? "true" : "false");
3064 paint2.setMaskFilter(paint1.refMaskFilter());
3065 SkDebugf("mask filter unique: %s\n", paint1.getMaskFilter()->unique() ? "true" : "false");
3066 }
3067
3068 #StdOut
3069 mask filter unique: true
3070 mask filter unique: false
3071 ##
3072 ##
3073
3074##
3075
3076#Method void setMaskFilter(sk_sp<SkMaskFilter> maskFilter)
3077
Cary Clarkab2621d2018-01-30 10:08:57 -05003078#In Mask_Filter_Methods
3079#Line # sets Mask_Filter, alterations to Mask_Alpha ##
Cary Clark6fc50412017-09-21 12:31:06 -04003080Sets Mask_Filter to maskFilter, decreasing Reference_Count of the previous
3081Mask_Filter. Pass nullptr to clear Mask_Filter and leave Mask_Filter effect on
3082Mask_Alpha unaltered.
3083
Cary Clark6fc50412017-09-21 12:31:06 -04003084Increments maskFilter Reference_Count by one.
Cary Clark8032b982017-07-28 11:04:54 -04003085
3086 #Param maskFilter modifies clipping mask generated from drawn geometry ##
3087
3088 #Example
3089 void draw(SkCanvas* canvas) {
3090 SkPaint paint;
3091 paint.setStyle(SkPaint::kStroke_Style);
3092 paint.setStrokeWidth(10);
Cary Clark681287e2018-03-16 11:34:15 -04003093 paint.setMaskFilter(SkMaskFilter::MakeBlur(kNormal_SkBlurStyle, 10));
Cary Clark8032b982017-07-28 11:04:54 -04003094 canvas->drawRect(SkRect::MakeXYWH(40, 40, 175, 175), paint);
3095 }
3096 ##
3097
3098##
3099
Cary Clark08895c42018-02-01 09:37:32 -05003100#Subtopic Mask_Filter_Methods ##
Cary Clark8032b982017-07-28 11:04:54 -04003101# ------------------------------------------------------------------------------
Cary Clark08895c42018-02-01 09:37:32 -05003102#Subtopic Typeface_Methods
3103#Line # get and set Typeface ##
Cary Clark8032b982017-07-28 11:04:54 -04003104
3105Typeface identifies the font used when drawing and measuring text.
3106Typeface may be specified by name, from a file, or from a data stream.
3107The default Typeface defers to the platform-specific default font
3108implementation.
3109
3110#Example
3111#Height 100
3112 void draw(SkCanvas* canvas) {
3113 SkPaint paint;
Ben Wagner700ff172017-11-08 15:37:22 -05003114 paint.setTypeface(SkTypeface::MakeFromName(nullptr, SkFontStyle()));
Cary Clark8032b982017-07-28 11:04:54 -04003115 paint.setAntiAlias(true);
3116 paint.setTextSize(36);
3117 canvas->drawString("A Big Hello!", 10, 40, paint);
3118 paint.setTypeface(nullptr);
3119 paint.setFakeBoldText(true);
3120 canvas->drawString("A Big Hello!", 10, 80, paint);
3121 }
3122##
3123
3124#Method SkTypeface* getTypeface() const
3125
Cary Clarkab2621d2018-01-30 10:08:57 -05003126#In Typeface_Methods
3127#Line # returns Typeface, font description ##
Cary Clark8032b982017-07-28 11:04:54 -04003128 Returns Typeface if set, or nullptr.
Cary Clark6fc50412017-09-21 12:31:06 -04003129 Increments Typeface Reference_Count by one.
Herb Derbyfcac00f2018-05-01 11:57:56 -04003130
Cary Clark8032b982017-07-28 11:04:54 -04003131 #Return Typeface if previously set, nullptr otherwise ##
3132
3133 #Example
3134 void draw(SkCanvas* canvas) {
3135 SkPaint paint;
3136 SkDebugf("nullptr %c= typeface\n", paint.getTypeface() ? '!' : '=');
Cary Clark71961fb2018-01-05 14:21:59 -05003137 paint.setTypeface(SkTypeface::MakeFromName("monospace", SkFontStyle()));
Cary Clark8032b982017-07-28 11:04:54 -04003138 SkDebugf("nullptr %c= typeface\n", paint.getTypeface() ? '!' : '=');
3139 }
3140
3141 #StdOut
3142 nullptr == typeface
3143 nullptr != typeface
3144 ##
3145 ##
3146
3147##
3148
3149#Method sk_sp<SkTypeface> refTypeface() const
3150
Cary Clarkab2621d2018-01-30 10:08:57 -05003151#In Typeface_Methods
3152#Line # references Typeface, font description ##
Cary Clark8032b982017-07-28 11:04:54 -04003153 Increases Typeface Reference_Count by one.
3154
3155 #Return Typeface if previously set, nullptr otherwise ##
3156
3157 #Example
3158 void draw(SkCanvas* canvas) {
3159 SkPaint paint1, paint2;
Herb Derbyfcac00f2018-05-01 11:57:56 -04003160 paint1.setTypeface(SkTypeface::MakeFromName("monospace",
Cary Clark8032b982017-07-28 11:04:54 -04003161 SkFontStyle(SkFontStyle::kNormal_Weight, SkFontStyle::kNormal_Width,
3162 SkFontStyle::kItalic_Slant)));
3163 SkDebugf("typeface1 %c= typeface2\n",
3164 paint1.getTypeface() == paint2.getTypeface() ? '=' : '!');
3165 paint2.setTypeface(paint1.refTypeface());
3166 SkDebugf("typeface1 %c= typeface2\n",
3167 paint1.getTypeface() == paint2.getTypeface() ? '=' : '!');
3168 }
3169
3170 #StdOut
3171 typeface1 != typeface2
3172 typeface1 == typeface2
3173 ##
3174 ##
3175
3176##
3177
3178#Method void setTypeface(sk_sp<SkTypeface> typeface)
3179
Cary Clarkab2621d2018-01-30 10:08:57 -05003180#In Typeface_Methods
3181#Line # sets Typeface, font description ##
Herb Derbyfcac00f2018-05-01 11:57:56 -04003182Sets Typeface to typeface, decreasing Reference_Count of the previous Typeface.
Cary Clark6fc50412017-09-21 12:31:06 -04003183Pass nullptr to clear Typeface and use the default typeface. Increments
3184typeface Reference_Count by one.
Cary Clark8032b982017-07-28 11:04:54 -04003185
3186 #Param typeface font and style used to draw text ##
3187
3188 #Example
3189 #Height 64
3190 void draw(SkCanvas* canvas) {
3191 SkPaint paint;
Cary Clark71961fb2018-01-05 14:21:59 -05003192 paint.setTypeface(SkTypeface::MakeFromName("monospace", SkFontStyle()));
3193 canvas->drawString("hamburgerfons", 10, 30, paint);
Cary Clark8032b982017-07-28 11:04:54 -04003194 paint.setTypeface(nullptr);
Cary Clark71961fb2018-01-05 14:21:59 -05003195 canvas->drawString("hamburgerfons", 10, 50, paint);
Cary Clark8032b982017-07-28 11:04:54 -04003196 }
3197 ##
3198
3199##
3200
Cary Clark08895c42018-02-01 09:37:32 -05003201#Subtopic Typeface_Methods ##
Cary Clark8032b982017-07-28 11:04:54 -04003202# ------------------------------------------------------------------------------
Cary Clark08895c42018-02-01 09:37:32 -05003203#Subtopic Image_Filter_Methods
3204#Line # get and set Image_Filter ##
Cary Clark8032b982017-07-28 11:04:54 -04003205
3206Image_Filter operates on the pixel representation of the shape, as modified by Paint
3207with Blend_Mode set to SkBlendMode::kSrcOver. Image_Filter creates a new bitmap,
3208which is drawn to the device using the set Blend_Mode.
Cary Clark6fc50412017-09-21 12:31:06 -04003209
Cary Clark8032b982017-07-28 11:04:54 -04003210Image_Filter is higher level than Mask_Filter; for instance, an Image_Filter
Cary Clarkce101242017-09-01 15:51:02 -04003211can operate on all channels of Color, while Mask_Filter generates Alpha only.
Cary Clark8032b982017-07-28 11:04:54 -04003212Image_Filter operates independently of and can be used in combination with
Mike Reed8ad91a92018-01-19 19:09:32 -05003213Mask_Filter.
Cary Clark8032b982017-07-28 11:04:54 -04003214
3215#Example
3216 #ToDo explain why the two draws are so different ##
3217 void draw(SkCanvas* canvas) {
3218 SkPaint paint;
3219 paint.setStyle(SkPaint::kStroke_Style);
3220 paint.setStrokeWidth(2);
3221 SkRegion region;
3222 region.op( 10, 10, 50, 50, SkRegion::kUnion_Op);
3223 region.op( 10, 50, 90, 90, SkRegion::kUnion_Op);
Cary Clarka560c472017-11-27 10:44:06 -05003224 paint.setImageFilter(SkBlurImageFilter::Make(5.0f, 5.0f, nullptr));
Cary Clark8032b982017-07-28 11:04:54 -04003225 canvas->drawRegion(region, paint);
3226 paint.setImageFilter(nullptr);
Cary Clarka7b84c52018-03-18 11:46:54 -04003227 paint.setMaskFilter(SkMaskFilter::MakeBlur(kNormal_SkBlurStyle, 5));
Cary Clark8032b982017-07-28 11:04:54 -04003228 canvas->translate(100, 100);
3229 canvas->drawRegion(region, paint);
3230 }
3231##
3232
3233#Method SkImageFilter* getImageFilter() const
3234
Cary Clarkab2621d2018-01-30 10:08:57 -05003235#In Image_Filter_Methods
3236#Line # returns Image_Filter, alter pixels; blur ##
Cary Clark8032b982017-07-28 11:04:54 -04003237 Returns Image_Filter if set, or nullptr.
3238 Does not alter Image_Filter Reference_Count.
Herb Derbyfcac00f2018-05-01 11:57:56 -04003239
Cary Clark8032b982017-07-28 11:04:54 -04003240 #Return Image_Filter if previously set, nullptr otherwise ##
3241
3242 #Example
3243 void draw(SkCanvas* canvas) {
3244 SkPaint paint;
3245 SkDebugf("nullptr %c= image filter\n", paint.getImageFilter() ? '!' : '=');
Cary Clarka560c472017-11-27 10:44:06 -05003246 paint.setImageFilter(SkBlurImageFilter::Make(kOuter_SkBlurStyle, 3, nullptr, nullptr));
Cary Clark8032b982017-07-28 11:04:54 -04003247 SkDebugf("nullptr %c= image filter\n", paint.getImageFilter() ? '!' : '=');
3248 }
3249
3250 #StdOut
3251 nullptr == image filter
3252 nullptr != image filter
3253 ##
3254 ##
3255
3256##
3257
3258#Method sk_sp<SkImageFilter> refImageFilter() const
3259
Cary Clarkab2621d2018-01-30 10:08:57 -05003260#In Image_Filter_Methods
3261#Line # references Image_Filter, alter pixels; blur ##
Cary Clark8032b982017-07-28 11:04:54 -04003262 Returns Image_Filter if set, or nullptr.
3263 Increases Image_Filter Reference_Count by one.
3264
3265 #Return Image_Filter if previously set, nullptr otherwise ##
3266
3267 #Example
3268 void draw(SkCanvas* canvas) {
3269 SkPaint paint1, paint2;
3270 paint1.setImageFilter(SkOffsetImageFilter::Make(25, 25, nullptr));
3271 SkDebugf("image filter unique: %s\n", paint1.getImageFilter()->unique() ? "true" : "false");
3272 paint2.setImageFilter(paint1.refImageFilter());
3273 SkDebugf("image filter unique: %s\n", paint1.getImageFilter()->unique() ? "true" : "false");
3274 }
3275
3276 #StdOut
3277 image filter unique: true
3278 image filter unique: false
3279 ##
3280 ##
3281
3282##
3283
3284#Method void setImageFilter(sk_sp<SkImageFilter> imageFilter)
3285
Cary Clarkab2621d2018-01-30 10:08:57 -05003286#In Image_Filter_Methods
3287#Line # sets Image_Filter, alter pixels; blur ##
Cary Clark6fc50412017-09-21 12:31:06 -04003288Sets Image_Filter to imageFilter, decreasing Reference_Count of the previous
3289Image_Filter. Pass nullptr to clear Image_Filter, and remove Image_Filter effect
3290on drawing.
3291
Cary Clark6fc50412017-09-21 12:31:06 -04003292Increments imageFilter Reference_Count by one.
Cary Clark8032b982017-07-28 11:04:54 -04003293
3294 #Param imageFilter how Image is sampled when transformed ##
3295
3296 #Example
3297 #Height 160
3298 void draw(SkCanvas* canvas) {
3299 SkBitmap bitmap;
3300 bitmap.allocN32Pixels(100, 100);
3301 SkCanvas offscreen(bitmap);
3302 SkPaint paint;
3303 paint.setAntiAlias(true);
3304 paint.setColor(SK_ColorWHITE);
3305 paint.setTextSize(96);
3306 offscreen.clear(0);
3307 offscreen.drawString("e", 20, 70, paint);
3308 paint.setImageFilter(
3309 SkLightingImageFilter::MakePointLitDiffuse(SkPoint3::Make(80, 100, 10),
3310 SK_ColorWHITE, 1, 2, nullptr, nullptr));
3311 canvas->drawBitmap(bitmap, 0, 0, &paint);
3312 }
3313 ##
3314
3315##
3316
Cary Clark08895c42018-02-01 09:37:32 -05003317#Subtopic Image_Filter_Methods ##
Cary Clark8032b982017-07-28 11:04:54 -04003318# ------------------------------------------------------------------------------
Cary Clark08895c42018-02-01 09:37:32 -05003319#Subtopic Draw_Looper_Methods
3320#Line # get and set Draw_Looper ##
Cary Clark8032b982017-07-28 11:04:54 -04003321
3322Draw_Looper sets a modifier that communicates state from one Draw_Layer
3323to another to construct the draw.
Cary Clark6fc50412017-09-21 12:31:06 -04003324
Cary Clark8032b982017-07-28 11:04:54 -04003325Draw_Looper draws one or more times, modifying the canvas and paint each time.
3326Draw_Looper may be used to draw multiple colors or create a colored shadow.
Herb Derbyfcac00f2018-05-01 11:57:56 -04003327Set Draw_Looper to nullptr to prevent Draw_Looper from modifying the draw.
Cary Clark8032b982017-07-28 11:04:54 -04003328
3329#Example
3330#Height 128
3331 void draw(SkCanvas* canvas) {
3332 SkLayerDrawLooper::LayerInfo info;
3333 info.fPaintBits = (SkLayerDrawLooper::BitFlags) SkLayerDrawLooper::kColorFilter_Bit;
3334 info.fColorMode = SkBlendMode::kSrc;
3335 SkLayerDrawLooper::Builder looperBuilder;
3336 SkPaint* loopPaint = looperBuilder.addLayer(info);
3337 loopPaint->setColor(SK_ColorRED);
3338 info.fOffset.set(20, 20);
3339 loopPaint = looperBuilder.addLayer(info);
3340 loopPaint->setColor(SK_ColorBLUE);
3341 SkPaint paint;
3342 paint.setDrawLooper(looperBuilder.detach());
3343 canvas->drawCircle(50, 50, 50, paint);
3344 }
3345
3346##
3347
3348#Method SkDrawLooper* getDrawLooper() const
3349
Cary Clarkab2621d2018-01-30 10:08:57 -05003350#In Draw_Looper_Methods
3351#Line # returns Draw_Looper, multiple layers ##
Cary Clark8032b982017-07-28 11:04:54 -04003352 Returns Draw_Looper if set, or nullptr.
3353 Does not alter Draw_Looper Reference_Count.
Herb Derbyfcac00f2018-05-01 11:57:56 -04003354
Cary Clark8032b982017-07-28 11:04:54 -04003355 #Return Draw_Looper if previously set, nullptr otherwise ##
3356
3357 #Example
3358 void draw(SkCanvas* canvas) {
3359 SkPaint paint;
3360 SkDebugf("nullptr %c= draw looper\n", paint.getDrawLooper() ? '!' : '=');
3361 SkLayerDrawLooper::Builder looperBuilder;
3362 paint.setDrawLooper(looperBuilder.detach());
3363 SkDebugf("nullptr %c= draw looper\n", paint.getDrawLooper() ? '!' : '=');
3364 }
3365
3366 #StdOut
3367 nullptr == draw looper
3368 nullptr != draw looper
3369 ##
3370 ##
3371
3372##
3373
3374#Method sk_sp<SkDrawLooper> refDrawLooper() const
3375
Cary Clarkab2621d2018-01-30 10:08:57 -05003376#In Draw_Looper_Methods
3377#Line # references Draw_Looper, multiple layers ##
Cary Clark8032b982017-07-28 11:04:54 -04003378 Returns Draw_Looper if set, or nullptr.
3379 Increases Draw_Looper Reference_Count by one.
3380
3381 #Return Draw_Looper if previously set, nullptr otherwise ##
3382
3383 #Example
3384 void draw(SkCanvas* canvas) {
3385 SkPaint paint1, paint2;
3386 SkLayerDrawLooper::Builder looperBuilder;
3387 paint1.setDrawLooper(looperBuilder.detach());
3388 SkDebugf("draw looper unique: %s\n", paint1.getDrawLooper()->unique() ? "true" : "false");
3389 paint2.setDrawLooper(paint1.refDrawLooper());
3390 SkDebugf("draw looper unique: %s\n", paint1.getDrawLooper()->unique() ? "true" : "false");
3391 }
3392
3393 #StdOut
3394 draw looper unique: true
3395 draw looper unique: false
3396 ##
3397 ##
3398
3399##
3400
3401#Method SkDrawLooper* getLooper() const
Cary Clark4855f782018-02-06 09:41:53 -05003402#Bug 6259
Cary Clark8032b982017-07-28 11:04:54 -04003403#Deprecated
Cary Clark8032b982017-07-28 11:04:54 -04003404##
3405
3406#Method void setDrawLooper(sk_sp<SkDrawLooper> drawLooper)
Cary Clarkab2621d2018-01-30 10:08:57 -05003407#In Draw_Looper_Methods
3408#Line # sets Draw_Looper, multiple layers ##
Cary Clark6fc50412017-09-21 12:31:06 -04003409Sets Draw_Looper to drawLooper, decreasing Reference_Count of the previous
3410drawLooper. Pass nullptr to clear Draw_Looper and leave Draw_Looper effect on
3411drawing unaltered.
3412
3413Increments drawLooper Reference_Count by one.
Cary Clark8032b982017-07-28 11:04:54 -04003414
Cary Clarka523d2d2017-08-30 08:58:10 -04003415 #Param drawLooper iterates through drawing one or more time, altering Paint ##
Cary Clark8032b982017-07-28 11:04:54 -04003416
3417 #Example
3418 #Height 128
3419 void draw(SkCanvas* canvas) {
3420 SkPaint paint;
3421 paint.setDrawLooper(SkBlurDrawLooper::Make(0x7FFF0000, 4, -5, -10));
3422 paint.setStyle(SkPaint::kStroke_Style);
3423 paint.setStrokeWidth(10);
3424 paint.setAntiAlias(true);
3425 paint.setColor(0x7f0000ff);
3426 canvas->drawCircle(70, 70, 50, paint);
3427 }
3428 ##
3429
3430##
3431
3432#Method void setLooper(sk_sp<SkDrawLooper> drawLooper)
Cary Clark4855f782018-02-06 09:41:53 -05003433#Bug 6259
Cary Clark8032b982017-07-28 11:04:54 -04003434#Deprecated
Cary Clark8032b982017-07-28 11:04:54 -04003435##
3436
Cary Clark08895c42018-02-01 09:37:32 -05003437#Subtopic Draw_Looper_Methods ##
Cary Clark4855f782018-02-06 09:41:53 -05003438
Cary Clark8032b982017-07-28 11:04:54 -04003439# ------------------------------------------------------------------------------
Cary Clark08895c42018-02-01 09:37:32 -05003440#Subtopic Text_Align
3441#Line # text placement relative to position ##
Cary Clark8032b982017-07-28 11:04:54 -04003442
3443#Enum Align
Cary Clark08895c42018-02-01 09:37:32 -05003444#Line # glyph locations relative to text position ##
Cary Clark8032b982017-07-28 11:04:54 -04003445#Code
3446 enum Align {
3447 kLeft_Align,
3448 kCenter_Align,
3449 kRight_Align,
3450 };
Cary Clarkd98f78c2018-04-26 08:32:37 -04003451
3452 static constexpr int kAlignCount = 3;
Cary Clark8032b982017-07-28 11:04:54 -04003453##
3454
3455Align adjusts the text relative to the text position.
Cary Clarkce101242017-09-01 15:51:02 -04003456Align affects Glyphs drawn with: SkCanvas::drawText, SkCanvas::drawPosText,
Herb Derbyfcac00f2018-05-01 11:57:56 -04003457SkCanvas::drawPosTextH, SkCanvas::drawTextOnPath,
Cary Clark8032b982017-07-28 11:04:54 -04003458SkCanvas::drawTextOnPathHV, SkCanvas::drawTextRSXform, SkCanvas::drawTextBlob,
Herb Derbyfcac00f2018-05-01 11:57:56 -04003459and SkCanvas::drawString;
Cary Clarkce101242017-09-01 15:51:02 -04003460as well as calls that place text Glyphs like getTextWidths and getTextPath.
Cary Clark8032b982017-07-28 11:04:54 -04003461
3462The text position is set by the font for both horizontal and vertical text.
3463Typically, for horizontal text, the position is to the left side of the glyph on the
3464base line; and for vertical text, the position is the horizontal center of the glyph
3465at the caps height.
3466
Herb Derbyfcac00f2018-05-01 11:57:56 -04003467Align adjusts the glyph position to center it or move it to abut the position
Cary Clark8032b982017-07-28 11:04:54 -04003468using the metrics returned by the font.
3469
3470Align defaults to kLeft_Align.
3471
3472#Const kLeft_Align 0
3473 Leaves the glyph at the position computed by the font offset by the text position.
3474##
3475
3476#Const kCenter_Align 1
3477 Moves the glyph half its width if Flags has kVerticalText_Flag clear, and
3478 half its height if Flags has kVerticalText_Flag set.
3479##
3480
3481#Const kRight_Align 2
3482 Moves the glyph by its width if Flags has kVerticalText_Flag clear,
3483 and by its height if Flags has kVerticalText_Flag set.
3484##
3485
Cary Clark8032b982017-07-28 11:04:54 -04003486#Const kAlignCount 3
3487 The number of different Text_Align values defined.
3488##
3489
3490#Enum ##
3491
3492#Example
3493 #Height 160
3494 #Description
3495 Each position separately moves the glyph in drawPosText.
3496 ##
3497 void draw(SkCanvas* canvas) {
3498 SkPaint paint;
3499 paint.setTextSize(40);
3500 SkPoint position[] = {{100, 50}, {150, 40}};
3501 for (SkPaint::Align a : { SkPaint::kLeft_Align,
3502 SkPaint::kCenter_Align,
3503 SkPaint::kRight_Align}) {
3504 paint.setTextAlign(a);
3505 canvas->drawPosText("Aa", 2, position, paint);
3506 canvas->translate(0, 50);
3507 }
3508 }
3509##
3510
3511#Example
3512 #Height 160
3513 #Description
3514 Vertical_Text treats kLeft_Align as top align, and kRight_Align as bottom align.
3515 ##
3516 void draw(SkCanvas* canvas) {
3517 SkPaint paint;
3518 paint.setTextSize(40);
3519 paint.setVerticalText(true);
3520 for (SkPaint::Align a : { SkPaint::kLeft_Align,
3521 SkPaint::kCenter_Align,
3522 SkPaint::kRight_Align }) {
3523 paint.setTextAlign(a);
3524 canvas->drawString("Aa", 50, 80, paint);
3525 canvas->translate(50, 0);
3526 }
3527 }
3528##
3529
3530#Method Align getTextAlign() const
3531
Cary Clarkab2621d2018-01-30 10:08:57 -05003532#In Text_Align
3533#Line # returns Align: left, center, or right ##
Cary Clark8032b982017-07-28 11:04:54 -04003534 Returns Text_Align.
3535 Returns kLeft_Align if Text_Align has not been set.
3536
3537 #Return text placement relative to position ##
3538
3539 #Example
3540 SkPaint paint;
3541 SkDebugf("kLeft_Align %c= default\n", SkPaint::kLeft_Align == paint.getTextAlign() ? '=' : '!');
3542
3543 #StdOut
3544 kLeft_Align == default
3545 ##
3546 ##
3547##
3548
3549#Method void setTextAlign(Align align)
3550
Cary Clarkab2621d2018-01-30 10:08:57 -05003551#In Text_Align
3552#Line # sets Align: left, center, or right ##
Cary Clark8032b982017-07-28 11:04:54 -04003553 Sets Text_Align to align.
3554 Has no effect if align is an invalid value.
3555
3556 #Param align text placement relative to position ##
3557
3558 #Example
3559 #Height 160
3560 #Description
3561 Text is left-aligned by default, and then set to center. Setting the
3562 alignment out of range has no effect.
3563 ##
3564 void draw(SkCanvas* canvas) {
3565 SkPaint paint;
3566 paint.setTextSize(40);
3567 canvas->drawString("Aa", 100, 50, paint);
3568 paint.setTextAlign(SkPaint::kCenter_Align);
3569 canvas->drawString("Aa", 100, 100, paint);
3570 paint.setTextAlign((SkPaint::Align) SkPaint::kAlignCount);
3571 canvas->drawString("Aa", 100, 150, paint);
3572 }
3573 ##
3574
3575##
3576
Cary Clark08895c42018-02-01 09:37:32 -05003577#Subtopic Text_Align ##
Cary Clark8032b982017-07-28 11:04:54 -04003578# ------------------------------------------------------------------------------
Cary Clark08895c42018-02-01 09:37:32 -05003579#Subtopic Text_Size
3580#Line # overall height in points ##
Cary Clark8032b982017-07-28 11:04:54 -04003581
3582Text_Size adjusts the overall text size in points.
3583Text_Size can be set to any positive value or zero.
3584Text_Size defaults to 12.
3585Set SkPaintDefaults_TextSize at compile time to change the default setting.
3586
3587#Example
3588#Height 135
3589 void draw(SkCanvas* canvas) {
3590 SkPaint paint;
3591 canvas->drawString("12 point", 10, 20, paint);
3592 paint.setTextSize(24);
3593 canvas->drawString("24 point", 10, 60, paint);
3594 paint.setTextSize(48);
3595 canvas->drawString("48 point", 10, 120, paint);
3596 }
3597##
3598
3599#Method SkScalar getTextSize() const
3600
Cary Clarkab2621d2018-01-30 10:08:57 -05003601#In Text_Size
3602#Line # returns text size in points ##
Cary Clark8032b982017-07-28 11:04:54 -04003603 Returns Text_Size in points.
3604
3605 #Return typographic height of text ##
3606
3607 #Example
3608 SkPaint paint;
3609 SkDebugf("12 %c= default text size\n", 12 == paint.getTextSize() ? '=' : '!');
3610 ##
3611
3612##
3613
3614#Method void setTextSize(SkScalar textSize)
3615
Cary Clarkab2621d2018-01-30 10:08:57 -05003616#In Text_Size
3617#Line # sets text size in points ##
Cary Clark8032b982017-07-28 11:04:54 -04003618 Sets Text_Size in points.
3619 Has no effect if textSize is not greater than or equal to zero.
Herb Derbyfcac00f2018-05-01 11:57:56 -04003620
Cary Clark8032b982017-07-28 11:04:54 -04003621 #Param textSize typographic height of text ##
3622
3623 #Example
3624 SkPaint paint;
3625 SkDebugf("12 %c= text size\n", 12 == paint.getTextSize() ? '=' : '!');
3626 paint.setTextSize(-20);
3627 SkDebugf("12 %c= text size\n", 12 == paint.getTextSize() ? '=' : '!');
3628 ##
3629
3630##
3631
Cary Clark08895c42018-02-01 09:37:32 -05003632#Subtopic Text_Size ##
Cary Clark8032b982017-07-28 11:04:54 -04003633# ------------------------------------------------------------------------------
Cary Clark08895c42018-02-01 09:37:32 -05003634#Subtopic Text_Scale_X
3635#Line # text horizontal scale ##
Cary Clark8032b982017-07-28 11:04:54 -04003636
3637Text_Scale_X adjusts the text horizontal scale.
3638Text scaling approximates condensed and expanded type faces when the actual face
3639is not available.
3640Text_Scale_X can be set to any value.
3641Text_Scale_X defaults to 1.
3642
3643#Example
3644#Height 128
3645 void draw(SkCanvas* canvas) {
3646 SkPaint paint;
3647 paint.setAntiAlias(true);
3648 paint.setTextSize(24);
3649 paint.setTextScaleX(.8f);
3650 canvas->drawString("narrow", 10, 20, paint);
3651 paint.setTextScaleX(1);
3652 canvas->drawString("normal", 10, 60, paint);
3653 paint.setTextScaleX(1.2f);
3654 canvas->drawString("wide", 10, 100, paint);
3655 }
3656##
3657
3658#Method SkScalar getTextScaleX() const
3659
Cary Clarkab2621d2018-01-30 10:08:57 -05003660#In Text_Scale_X
3661#Line # returns the text horizontal scale; condensed text ##
Cary Clark8032b982017-07-28 11:04:54 -04003662 Returns Text_Scale_X.
3663 Default value is 1.
3664
3665 #Return text horizontal scale ##
3666
3667 #Example
3668 SkPaint paint;
3669 SkDebugf("1 %c= default text scale x\n", 1 == paint.getTextScaleX() ? '=' : '!');
3670 ##
3671
3672##
3673
3674
3675#Method void setTextScaleX(SkScalar scaleX)
3676
Cary Clarkab2621d2018-01-30 10:08:57 -05003677#In Text_Scale_X
3678#Line # sets the text horizontal scale; condensed text ##
Cary Clark8032b982017-07-28 11:04:54 -04003679 Sets Text_Scale_X.
3680 Default value is 1.
Herb Derbyfcac00f2018-05-01 11:57:56 -04003681
Cary Clark8032b982017-07-28 11:04:54 -04003682 #Param scaleX text horizontal scale ##
3683
3684 #Example
3685 SkPaint paint;
3686 paint.setTextScaleX(0.f / 0.f);
3687 SkDebugf("text scale %s-a-number\n", SkScalarIsNaN(paint.getTextScaleX()) ? "not" : "is");
3688 ##
3689
3690##
3691
Cary Clark08895c42018-02-01 09:37:32 -05003692#Subtopic Text_Scale_X ##
Cary Clark8032b982017-07-28 11:04:54 -04003693
Cary Clark08895c42018-02-01 09:37:32 -05003694#Subtopic Text_Skew_X
3695#Line # text horizontal slant ##
Cary Clark8032b982017-07-28 11:04:54 -04003696
3697
3698Text_Skew_X adjusts the text horizontal slant.
3699Text skewing approximates italic and oblique type faces when the actual face
3700is not available.
3701Text_Skew_X can be set to any value.
3702Text_Skew_X defaults to 0.
3703
3704#Example
3705#Height 128
3706 void draw(SkCanvas* canvas) {
3707 SkPaint paint;
3708 paint.setAntiAlias(true);
3709 paint.setTextSize(24);
3710 paint.setTextSkewX(-.25f);
3711 canvas->drawString("right-leaning", 10, 100, paint);
3712 paint.setTextSkewX(0);
3713 canvas->drawString("normal", 10, 60, paint);
3714 paint.setTextSkewX(.25f);
3715 canvas->drawString("left-leaning", 10, 20, paint);
3716 }
3717##
3718
3719#Method SkScalar getTextSkewX() const
3720
Cary Clarkab2621d2018-01-30 10:08:57 -05003721#In Text_Skew_X
3722#Line # returns the text horizontal skew; oblique text ##
Cary Clark8032b982017-07-28 11:04:54 -04003723 Returns Text_Skew_X.
3724 Default value is zero.
3725
3726 #Return additional shear in x-axis relative to y-axis ##
3727
3728 #Example
3729 SkPaint paint;
3730 SkDebugf("0 %c= default text skew x\n", 0 == paint.getTextSkewX() ? '=' : '!');
3731 ##
3732
3733##
3734
3735#Method void setTextSkewX(SkScalar skewX)
3736
Cary Clarkab2621d2018-01-30 10:08:57 -05003737#In Text_Skew_X
3738#Line # sets the text horizontal skew; oblique text ##
Cary Clark8032b982017-07-28 11:04:54 -04003739 Sets Text_Skew_X.
3740 Default value is zero.
3741
3742 #Param skewX additional shear in x-axis relative to y-axis ##
3743
3744 #Example
3745 SkPaint paint;
3746 paint.setTextScaleX(1.f / 0.f);
3747 SkDebugf("text scale %s-finite\n", SkScalarIsFinite(paint.getTextScaleX()) ? "is" : "not");
3748 ##
3749
3750##
3751
Cary Clark08895c42018-02-01 09:37:32 -05003752#Subtopic Text_Skew_X ##
Cary Clark8032b982017-07-28 11:04:54 -04003753
3754# ------------------------------------------------------------------------------
Cary Clark08895c42018-02-01 09:37:32 -05003755#Subtopic Text_Encoding
3756#Line # text encoded as characters or Glyphs ##
Cary Clark8032b982017-07-28 11:04:54 -04003757
3758#Enum TextEncoding
Cary Clark08895c42018-02-01 09:37:32 -05003759#Line # character or glyph encoded size ##
Cary Clark8032b982017-07-28 11:04:54 -04003760
3761#Code
3762 enum TextEncoding {
3763 kUTF8_TextEncoding,
3764 kUTF16_TextEncoding,
3765 kUTF32_TextEncoding,
Cary Clarkbad5ad72017-08-03 17:14:08 -04003766 kGlyphID_TextEncoding,
Cary Clark8032b982017-07-28 11:04:54 -04003767 };
3768##
3769
Cary Clark6fc50412017-09-21 12:31:06 -04003770TextEncoding determines whether text specifies character codes and their encoded
Cary Clarkbc5697d2017-10-04 14:31:33 -04003771size, or glyph indices. Characters are encoded as specified by the
Cary Clark6fc50412017-09-21 12:31:06 -04003772#A Unicode standard # http://unicode.org/standard/standard.html ##
3773.
3774
Cary Clark8032b982017-07-28 11:04:54 -04003775Character codes encoded size are specified by UTF-8, UTF-16, or UTF-32.
Cary Clarkbc5697d2017-10-04 14:31:33 -04003776All character code formats are able to represent all of Unicode, differing only
Cary Clark8032b982017-07-28 11:04:54 -04003777in the total storage required.
3778
Cary Clark6fc50412017-09-21 12:31:06 -04003779#A UTF-8 (RFC 3629) # https://tools.ietf.org/html/rfc3629 ##
3780 encodes each character as one or more 8-bit bytes.
3781
3782#A UTF-16 (RFC 2781) # https://tools.ietf.org/html/rfc2781 ##
3783 encodes each character as one or two 16-bit words.
3784
3785#A UTF-32 # http://www.unicode.org/versions/Unicode5.0.0/ch03.pdf ##
3786 encodes each character as one 32-bit word.
Cary Clark8032b982017-07-28 11:04:54 -04003787
Herb Derbyfcac00f2018-05-01 11:57:56 -04003788Font_Manager uses font data to convert character code points into glyph indices.
Cary Clark8032b982017-07-28 11:04:54 -04003789A glyph index is a 16-bit word.
3790
3791TextEncoding is set to kUTF8_TextEncoding by default.
3792
3793#Const kUTF8_TextEncoding 0
3794Uses bytes to represent UTF-8 or ASCII.
3795##
3796#Const kUTF16_TextEncoding 1
3797Uses two byte words to represent most of Unicode.
3798##
3799#Const kUTF32_TextEncoding 2
3800Uses four byte words to represent all of Unicode.
3801##
3802#Const kGlyphID_TextEncoding 3
3803Uses two byte words to represent glyph indices.
3804##
3805
3806#Enum ##
3807
3808#Example
3809#Height 128
3810#Description
Cary Clarkbc5697d2017-10-04 14:31:33 -04003811First line is encoded in UTF-8.
3812Second line is encoded in UTF-16.
3813Third line is encoded in UTF-32.
Cary Clark8032b982017-07-28 11:04:54 -04003814Fourth line has 16 bit glyph indices.
3815##
3816void draw(SkCanvas* canvas) {
3817 SkPaint paint;
3818 const char hello8[] = "Hello" "\xE2" "\x98" "\xBA";
3819 const uint16_t hello16[] = { 'H', 'e', 'l', 'l', 'o', 0x263A };
3820 const uint32_t hello32[] = { 'H', 'e', 'l', 'l', 'o', 0x263A };
3821 paint.setTextSize(24);
3822 canvas->drawText(hello8, sizeof(hello8) - 1, 10, 30, paint);
3823 paint.setTextEncoding(SkPaint::kUTF16_TextEncoding);
3824 canvas->drawText(hello16, sizeof(hello16), 10, 60, paint);
3825 paint.setTextEncoding(SkPaint::kUTF32_TextEncoding);
3826 canvas->drawText(hello32, sizeof(hello32), 10, 90, paint);
3827 uint16_t glyphs[SK_ARRAY_COUNT(hello32)];
3828 paint.textToGlyphs(hello32, sizeof(hello32), glyphs);
3829 paint.setTextEncoding(SkPaint::kGlyphID_TextEncoding);
3830 canvas->drawText(glyphs, sizeof(glyphs), 10, 120, paint);
3831}
3832##
3833
3834#Method TextEncoding getTextEncoding() const
3835
Cary Clarkab2621d2018-01-30 10:08:57 -05003836#In Text_Encoding
3837#Line # returns character or glyph encoded size ##
Cary Clark8032b982017-07-28 11:04:54 -04003838 Returns Text_Encoding.
3839 Text_Encoding determines how character code points are mapped to font glyph indices.
3840
Herb Derbyfcac00f2018-05-01 11:57:56 -04003841 #Return one of: kUTF8_TextEncoding, kUTF16_TextEncoding, kUTF32_TextEncoding, or
3842 kGlyphID_TextEncoding
Cary Clark8032b982017-07-28 11:04:54 -04003843 ##
3844
3845 #Example
3846 SkPaint paint;
Herb Derbyfcac00f2018-05-01 11:57:56 -04003847 SkDebugf("kUTF8_TextEncoding %c= text encoding\n",
Cary Clark8032b982017-07-28 11:04:54 -04003848 SkPaint::kUTF8_TextEncoding == paint.getTextEncoding() ? '=' : '!');
3849 paint.setTextEncoding(SkPaint::kGlyphID_TextEncoding);
Herb Derbyfcac00f2018-05-01 11:57:56 -04003850 SkDebugf("kGlyphID_TextEncoding %c= text encoding\n",
Cary Clark8032b982017-07-28 11:04:54 -04003851 SkPaint::kGlyphID_TextEncoding == paint.getTextEncoding() ? '=' : '!');
3852
3853 #StdOut
3854 kUTF8_TextEncoding == text encoding
3855 kGlyphID_TextEncoding == text encoding
3856 ##
3857 ##
3858
3859##
3860
3861
3862#Method void setTextEncoding(TextEncoding encoding)
3863
Cary Clarkab2621d2018-01-30 10:08:57 -05003864#In Text_Encoding
3865#Line # sets character or glyph encoded size ##
Herb Derbyfcac00f2018-05-01 11:57:56 -04003866 Sets Text_Encoding to encoding.
Cary Clark8032b982017-07-28 11:04:54 -04003867 Text_Encoding determines how character code points are mapped to font glyph indices.
3868 Invalid values for encoding are ignored.
3869
Herb Derbyfcac00f2018-05-01 11:57:56 -04003870 #Param encoding one of: kUTF8_TextEncoding, kUTF16_TextEncoding, kUTF32_TextEncoding, or
3871 kGlyphID_TextEncoding
Cary Clark579985c2017-07-31 11:48:27 -04003872 #Param ##
Cary Clark8032b982017-07-28 11:04:54 -04003873
3874 #Example
3875 SkPaint paint;
3876 paint.setTextEncoding((SkPaint::TextEncoding) 4);
3877 SkDebugf("4 %c= text encoding\n", 4 == paint.getTextEncoding() ? '=' : '!');
3878
3879 #StdOut
3880 4 != text encoding
3881 ##
3882 ##
3883
3884##
3885
Cary Clark08895c42018-02-01 09:37:32 -05003886#Subtopic Text_Encoding ##
Cary Clark8032b982017-07-28 11:04:54 -04003887# ------------------------------------------------------------------------------
Cary Clark08895c42018-02-01 09:37:32 -05003888#Subtopic Font_Metrics
3889#Line # common glyph dimensions ##
Cary Clark8032b982017-07-28 11:04:54 -04003890
Cary Clarkce101242017-09-01 15:51:02 -04003891Font_Metrics describe dimensions common to the Glyphs in Typeface.
Herb Derbyfcac00f2018-05-01 11:57:56 -04003892The dimensions are computed by Font_Manager from font data and do not take
Cary Clark8032b982017-07-28 11:04:54 -04003893Paint settings other than Text_Size into account.
3894
3895Font dimensions specify the anchor to the left of the glyph at baseline as the origin.
3896X-axis values to the left of the glyph are negative, and to the right of the left glyph edge
3897are positive.
3898Y-axis values above the baseline are negative, and below the baseline are positive.
Ben Wagnere5806492017-11-09 12:08:31 -05003899
Cary Clark8032b982017-07-28 11:04:54 -04003900#Example
3901#Width 512
3902void draw(SkCanvas* canvas) {
3903 SkPaint paint;
3904 paint.setAntiAlias(true);
3905 paint.setTextSize(120);
3906 SkPaint::FontMetrics fm;
3907 SkScalar lineHeight = paint.getFontMetrics(&fm);
3908 SkPoint pt = { 70, 180 };
3909 canvas->drawString("M", pt.fX, pt.fY, paint);
3910 canvas->drawLine(pt.fX, pt.fY, pt.fX, pt.fY + fm.fTop, paint);
3911 SkScalar ascent = pt.fY + fm.fAscent;
3912 canvas->drawLine(pt.fX - 25, ascent, pt.fX - 25, ascent + lineHeight, paint);
3913 canvas->drawLine(pt.fX - 50, pt.fY, pt.fX - 50, pt.fY + fm.fDescent, paint);
3914 canvas->drawLine(pt.fX + 100, pt.fY, pt.fX + 100, pt.fY + fm.fAscent, paint);
3915 canvas->drawLine(pt.fX + 125, pt.fY, pt.fX + 125, pt.fY - fm.fXHeight, paint);
3916 canvas->drawLine(pt.fX + 150, pt.fY, pt.fX + 150, pt.fY - fm.fCapHeight, paint);
3917 canvas->drawLine(pt.fX + 5, pt.fY, pt.fX + 5, pt.fY + fm.fBottom, paint);
3918 SkScalar xmin = pt.fX + fm.fXMin;
3919 canvas->drawLine(xmin, pt.fY + 60, xmin + fm.fMaxCharWidth, pt.fY + 60, paint);
3920 canvas->drawLine(xmin, pt.fY - 145, pt.fX, pt.fY - 145, paint);
3921 canvas->drawLine(pt.fX + fm.fXMax, pt.fY - 160, pt.fX, pt.fY - 160, paint);
3922 SkScalar upos = pt.fY + fm.fUnderlinePosition;
Ben Wagnere5806492017-11-09 12:08:31 -05003923 canvas->drawLine(pt.fX + 25, upos, pt.fX + 160, upos, paint);
3924 SkScalar ut = fm.fUnderlineThickness;
3925 canvas->drawLine(pt.fX + 130, upos + ut, pt.fX + 160, upos + ut, paint);
Cary Clark8032b982017-07-28 11:04:54 -04003926 paint.setTextSize(12);
3927 canvas->drawString("x-min", pt.fX - 50, pt.fY - 148, paint);
3928 canvas->drawString("x-max", pt.fX + 140, pt.fY - 150, paint);
3929 canvas->drawString("max char width", pt.fX + 120, pt.fY + 57, paint);
3930 canvas->drawString("underline position", pt.fX + 30, pt.fY + 22, paint);
3931 canvas->drawString("underline thickness", pt.fX + 162, pt.fY + 13, paint);
3932 canvas->rotate(-90);
3933 canvas->drawString("descent", -pt.fY - 30, pt.fX - 54, paint);
3934 canvas->drawString("line height", -pt.fY, pt.fX - 29, paint);
3935 canvas->drawString("top", -pt.fY + 30, pt.fX - 4, paint);
3936 canvas->drawString("ascent", -pt.fY, pt.fX + 110, paint);
3937 canvas->drawString("x-height", -pt.fY, pt.fX + 135, paint);
3938 canvas->drawString("cap-height", -pt.fY, pt.fX + 160, paint);
3939 canvas->drawString("bottom", -pt.fY - 50, pt.fX + 15, paint);
3940}
3941##
3942
3943#Struct FontMetrics
Cary Clark08895c42018-02-01 09:37:32 -05003944#Line # values computed by Font_Manager using Typeface ##
Cary Clark8032b982017-07-28 11:04:54 -04003945
3946#Code
3947 struct FontMetrics {
3948 enum FontMetricsFlags {
3949 kUnderlineThicknessIsValid_Flag = 1 << 0,
3950 kUnderlinePositionIsValid_Flag = 1 << 1,
3951 kStrikeoutThicknessIsValid_Flag = 1 << 2,
3952 kStrikeoutPositionIsValid_Flag = 1 << 3,
3953 };
3954
3955 uint32_t fFlags;
3956 SkScalar fTop;
3957 SkScalar fAscent;
3958 SkScalar fDescent;
3959 SkScalar fBottom;
3960 SkScalar fLeading;
3961 SkScalar fAvgCharWidth;
3962 SkScalar fMaxCharWidth;
3963 SkScalar fXMin;
3964 SkScalar fXMax;
3965 SkScalar fXHeight;
3966 SkScalar fCapHeight;
3967 SkScalar fUnderlineThickness;
3968 SkScalar fUnderlinePosition;
3969 SkScalar fStrikeoutThickness;
3970 SkScalar fStrikeoutPosition;
3971
3972 bool hasUnderlineThickness(SkScalar* thickness) const;
3973 bool hasUnderlinePosition(SkScalar* position) const;
3974 bool hasStrikeoutThickness(SkScalar* thickness) const;
3975 bool hasStrikeoutPosition(SkScalar* position) const;
3976 };
3977##
3978
Cary Clark154beea2017-10-26 07:58:48 -04003979 FontMetrics is filled out by getFontMetrics. FontMetrics contents reflect the values
3980 computed by Font_Manager using Typeface. Values are set to zero if they are
3981 not available.
Cary Clarke4aa3712017-09-15 02:56:12 -04003982
Ben Wagnere5806492017-11-09 12:08:31 -05003983 All vertical values relative to the baseline are given y-down. As such, zero is on the
3984 baseline, negative values are above the baseline, and positive values are below the
3985 baseline.
3986
Cary Clark154beea2017-10-26 07:58:48 -04003987 fUnderlineThickness and fUnderlinePosition have a bit set in fFlags if their values
3988 are valid, since their value may be zero.
Ben Wagnere5806492017-11-09 12:08:31 -05003989
Cary Clark154beea2017-10-26 07:58:48 -04003990 fStrikeoutThickness and fStrikeoutPosition have a bit set in fFlags if their values
3991 are valid, since their value may be zero.
3992
3993 #Enum FontMetricsFlags
Cary Clark08895c42018-02-01 09:37:32 -05003994#Line # valid Font_Metrics ##
Cary Clarke4aa3712017-09-15 02:56:12 -04003995
Cary Clark8032b982017-07-28 11:04:54 -04003996 #Code
3997 enum FontMetricsFlags {
3998 kUnderlineThicknessIsValid_Flag = 1 << 0,
3999 kUnderlinePositionIsValid_Flag = 1 << 1,
4000 kStrikeoutThicknessIsValid_Flag = 1 << 2,
4001 kStrikeoutPositionIsValid_Flag = 1 << 3,
4002 };
4003 ##
4004
Cary Clark154beea2017-10-26 07:58:48 -04004005 FontMetricsFlags are set in fFlags when underline and strikeout metrics are valid;
4006 the underline or strikeout metric may be valid and zero.
4007 Fonts with embedded bitmaps may not have valid underline or strikeout metrics.
4008
Cary Clark8032b982017-07-28 11:04:54 -04004009 #Const kUnderlineThicknessIsValid_Flag 0x0001
4010 Set if fUnderlineThickness is valid.
4011 ##
4012 #Const kUnderlinePositionIsValid_Flag 0x0002
4013 Set if fUnderlinePosition is valid.
4014 ##
4015 #Const kStrikeoutThicknessIsValid_Flag 0x0004
4016 Set if fStrikeoutThickness is valid.
4017 ##
4018 #Const kStrikeoutPositionIsValid_Flag 0x0008
4019 Set if fStrikeoutPosition is valid.
4020 ##
4021
4022 #Enum ##
4023
4024 #Member uint32_t fFlags
4025 fFlags is set when underline metrics are valid.
4026 ##
Ben Wagnere5806492017-11-09 12:08:31 -05004027
Cary Clark8032b982017-07-28 11:04:54 -04004028 #Member SkScalar fTop
Ben Wagnere5806492017-11-09 12:08:31 -05004029 Greatest extent above the baseline for any glyph.
4030 Typically less than zero.
Cary Clark8032b982017-07-28 11:04:54 -04004031 ##
Ben Wagnere5806492017-11-09 12:08:31 -05004032
Cary Clark8032b982017-07-28 11:04:54 -04004033 #Member SkScalar fAscent
4034 Recommended distance above the baseline to reserve for a line of text.
Ben Wagnere5806492017-11-09 12:08:31 -05004035 Typically less than zero.
Cary Clark8032b982017-07-28 11:04:54 -04004036 ##
Ben Wagnere5806492017-11-09 12:08:31 -05004037
Cary Clark8032b982017-07-28 11:04:54 -04004038 #Member SkScalar fDescent
4039 Recommended distance below the baseline to reserve for a line of text.
Ben Wagnere5806492017-11-09 12:08:31 -05004040 Typically greater than zero.
Cary Clark8032b982017-07-28 11:04:54 -04004041 ##
Ben Wagnere5806492017-11-09 12:08:31 -05004042
Cary Clark8032b982017-07-28 11:04:54 -04004043 #Member SkScalar fBottom
Ben Wagnere5806492017-11-09 12:08:31 -05004044 Greatest extent below the baseline for any glyph.
4045 Typically greater than zero.
Cary Clark8032b982017-07-28 11:04:54 -04004046 ##
Ben Wagnere5806492017-11-09 12:08:31 -05004047
Cary Clark8032b982017-07-28 11:04:54 -04004048 #Member SkScalar fLeading
4049 Recommended distance to add between lines of text.
Ben Wagnere5806492017-11-09 12:08:31 -05004050 Typically greater than or equal to zero.
Cary Clark8032b982017-07-28 11:04:54 -04004051 ##
Ben Wagnere5806492017-11-09 12:08:31 -05004052
Cary Clark8032b982017-07-28 11:04:54 -04004053 #Member SkScalar fAvgCharWidth
4054 Average character width, if it is available.
4055 Zero if no average width is stored in the font.
4056 ##
Ben Wagnere5806492017-11-09 12:08:31 -05004057
Cary Clark8032b982017-07-28 11:04:54 -04004058 #Member SkScalar fMaxCharWidth
4059 Maximum character width.
4060 ##
Ben Wagnere5806492017-11-09 12:08:31 -05004061
Cary Clark8032b982017-07-28 11:04:54 -04004062 #Member SkScalar fXMin
Ben Wagnere5806492017-11-09 12:08:31 -05004063 Minimum bounding box x value for all Glyphs.
Cary Clark8032b982017-07-28 11:04:54 -04004064 Typically less than zero.
4065 ##
Ben Wagnere5806492017-11-09 12:08:31 -05004066
Cary Clark8032b982017-07-28 11:04:54 -04004067 #Member SkScalar fXMax
Cary Clarkce101242017-09-01 15:51:02 -04004068 Maximum bounding box x value for all Glyphs.
Cary Clark8032b982017-07-28 11:04:54 -04004069 Typically greater than zero.
4070 ##
Ben Wagnere5806492017-11-09 12:08:31 -05004071
Cary Clark8032b982017-07-28 11:04:54 -04004072 #Member SkScalar fXHeight
4073 Height of a lower-case 'x'.
4074 May be zero if no lower-case height is stored in the font.
4075 ##
Ben Wagnere5806492017-11-09 12:08:31 -05004076
Cary Clark8032b982017-07-28 11:04:54 -04004077 #Member SkScalar fCapHeight
4078 Height of an upper-case letter.
4079 May be zero if no upper-case height is stored in the font.
4080 ##
Ben Wagnere5806492017-11-09 12:08:31 -05004081
Cary Clark8032b982017-07-28 11:04:54 -04004082 #Member SkScalar fUnderlineThickness
Ben Wagnere5806492017-11-09 12:08:31 -05004083 Underline thickness.
4084
4085 If the metric is valid, the kUnderlineThicknessIsValid_Flag is set in fFlags.
Cary Clark8032b982017-07-28 11:04:54 -04004086 If kUnderlineThicknessIsValid_Flag is clear, fUnderlineThickness is zero.
4087 ##
Ben Wagnere5806492017-11-09 12:08:31 -05004088
Cary Clark8032b982017-07-28 11:04:54 -04004089 #Member SkScalar fUnderlinePosition
Ben Wagnere5806492017-11-09 12:08:31 -05004090 Position of the top of the underline stroke relative to the baseline.
4091 Typically positive when valid.
Cary Clark8032b982017-07-28 11:04:54 -04004092
4093 If the metric is valid, the kUnderlinePositionIsValid_Flag is set in fFlags.
4094 If kUnderlinePositionIsValid_Flag is clear, fUnderlinePosition is zero.
4095 ##
4096
4097 #Member SkScalar fStrikeoutThickness
Ben Wagnere5806492017-11-09 12:08:31 -05004098 Strikeout thickness.
4099
4100 If the metric is valid, the kStrikeoutThicknessIsValid_Flag is set in fFlags.
Cary Clark8032b982017-07-28 11:04:54 -04004101 If kStrikeoutThicknessIsValid_Flag is clear, fStrikeoutThickness is zero.
4102 ##
4103
4104 #Member SkScalar fStrikeoutPosition
Ben Wagnere5806492017-11-09 12:08:31 -05004105 Position of the bottom of the strikeout stroke relative to the baseline.
4106 Typically negative when valid.
Cary Clark8032b982017-07-28 11:04:54 -04004107
Ben Wagnere5806492017-11-09 12:08:31 -05004108 If the metric is valid, the kStrikeoutPositionIsValid_Flag is set in fFlags.
4109 If kStrikeoutPositionIsValid_Flag is clear, fStrikeoutPosition is zero.
Cary Clark8032b982017-07-28 11:04:54 -04004110 ##
4111
4112 #Method bool hasUnderlineThickness(SkScalar* thickness) const
4113
Ben Wagnere5806492017-11-09 12:08:31 -05004114 If Font_Metrics has a valid underline thickness, return true, and set
Cary Clarkce101242017-09-01 15:51:02 -04004115 thickness to that value. If the underline thickness is not valid,
4116 return false, and ignore thickness.
Cary Clark8032b982017-07-28 11:04:54 -04004117
4118 #Param thickness storage for underline width ##
4119
4120 #Return true if font specifies underline width ##
4121
4122 #NoExample
4123 ##
4124 ##
4125
4126 #Method bool hasUnderlinePosition(SkScalar* position) const
4127
Ben Wagnere5806492017-11-09 12:08:31 -05004128 If Font_Metrics has a valid underline position, return true, and set
Cary Clarkce101242017-09-01 15:51:02 -04004129 position to that value. If the underline position is not valid,
4130 return false, and ignore position.
Cary Clark8032b982017-07-28 11:04:54 -04004131
4132 #Param position storage for underline position ##
4133
4134 #Return true if font specifies underline position ##
4135
4136 #NoExample
4137 ##
4138 ##
4139
4140 #Method bool hasStrikeoutThickness(SkScalar* thickness) const
4141
Ben Wagnere5806492017-11-09 12:08:31 -05004142 If Font_Metrics has a valid strikeout thickness, return true, and set
Cary Clarkce101242017-09-01 15:51:02 -04004143 thickness to that value. If the underline thickness is not valid,
4144 return false, and ignore thickness.
Cary Clark8032b982017-07-28 11:04:54 -04004145
4146 #Param thickness storage for strikeout width ##
4147
4148 #Return true if font specifies strikeout width ##
4149
4150 #NoExample
4151 ##
4152 ##
4153
4154 #Method bool hasStrikeoutPosition(SkScalar* position) const
4155
Ben Wagnere5806492017-11-09 12:08:31 -05004156 If Font_Metrics has a valid strikeout position, return true, and set
Cary Clarkce101242017-09-01 15:51:02 -04004157 position to that value. If the underline position is not valid,
4158 return false, and ignore position.
Cary Clark8032b982017-07-28 11:04:54 -04004159
4160 #Param position storage for strikeout position ##
4161
4162 #Return true if font specifies strikeout position ##
4163
4164 #NoExample
4165 ##
4166 ##
4167
4168#Struct ##
4169
4170#Method SkScalar getFontMetrics(FontMetrics* metrics, SkScalar scale = 0) const
4171
Cary Clarkab2621d2018-01-30 10:08:57 -05004172#In Font_Metrics
4173#Line # returns Typeface metrics scaled by text size ##
Cary Clark8032b982017-07-28 11:04:54 -04004174 Returns Font_Metrics associated with Typeface.
4175 The return value is the recommended spacing between lines: the sum of metrics
4176 descent, ascent, and leading.
4177 If metrics is not nullptr, Font_Metrics is copied to metrics.
4178 Results are scaled by Text_Size but does not take into account
4179 dimensions required by Text_Scale_X, Text_Skew_X, Fake_Bold,
4180 Style_Stroke, and Path_Effect.
4181 Results can be additionally scaled by scale; a scale of zero
4182 is ignored.
4183
4184 #Param metrics storage for Font_Metrics from Typeface; may be nullptr ##
4185 #Param scale additional multiplier for returned values ##
4186
4187 #Return recommended spacing between lines ##
4188
4189 #Example
4190 #Height 128
4191 void draw(SkCanvas* canvas) {
4192 SkPaint paint;
4193 paint.setTextSize(32);
4194 SkScalar lineHeight = paint.getFontMetrics(nullptr);
4195 canvas->drawString("line 1", 10, 40, paint);
4196 canvas->drawString("line 2", 10, 40 + lineHeight, paint);
4197 paint.setStyle(SkPaint::kStroke_Style);
4198 paint.setStrokeWidth(10);
4199 lineHeight = paint.getFontMetrics(nullptr, 1.10f); // account for stroke height
4200 canvas->drawString("line 3", 120, 40, paint);
4201 canvas->drawString("line 4", 120, 40 + lineHeight, paint);
4202 }
4203 ##
4204
4205 #SeeAlso Text_Size Typeface Typeface_Methods
4206
4207##
4208
4209
4210#Method SkScalar getFontSpacing() const
4211
Cary Clarkab2621d2018-01-30 10:08:57 -05004212#In Font_Metrics
4213#Line # returns recommended spacing between lines ##
Cary Clark8032b982017-07-28 11:04:54 -04004214 Returns the recommended spacing between lines: the sum of metrics
4215 descent, ascent, and leading.
4216 Result is scaled by Text_Size but does not take into account
4217 dimensions required by stroking and Path_Effect.
Cary Clark579985c2017-07-31 11:48:27 -04004218 Returns the same result as getFontMetrics.
Cary Clark8032b982017-07-28 11:04:54 -04004219
Cary Clark0c5f5462017-12-15 11:21:51 -05004220 #Return recommended spacing between lines ##
Cary Clark8032b982017-07-28 11:04:54 -04004221
4222 #Example
4223 SkPaint paint;
4224 for (SkScalar textSize : { 12, 18, 24, 32 } ) {
4225 paint.setTextSize(textSize);
4226 SkDebugf("textSize: %g fontSpacing: %g\n", textSize, paint.getFontSpacing());
4227 }
4228
4229 #StdOut
4230 textSize: 12 fontSpacing: 13.9688
4231 textSize: 18 fontSpacing: 20.9531
4232 textSize: 24 fontSpacing: 27.9375
4233 textSize: 32 fontSpacing: 37.25
4234 ##
4235 ##
4236
4237##
4238
4239
4240#Method SkRect getFontBounds() const
4241
Cary Clarkab2621d2018-01-30 10:08:57 -05004242#In Font_Metrics
4243#Line # returns union all glyph bounds ##
Cary Clarkce101242017-09-01 15:51:02 -04004244Returns the union of bounds of all Glyphs.
Herb Derbyfcac00f2018-05-01 11:57:56 -04004245Returned dimensions are computed by Font_Manager from font data,
Cary Clark579985c2017-07-31 11:48:27 -04004246ignoring Hinting. Includes Text_Size, Text_Scale_X,
Cary Clark8032b982017-07-28 11:04:54 -04004247and Text_Skew_X, but not Fake_Bold or Path_Effect.
4248
4249If Text_Size is large, Text_Scale_X is one, and Text_Skew_X is zero,
Herb Derbyfcac00f2018-05-01 11:57:56 -04004250returns the same bounds as Font_Metrics { FontMetrics::fXMin,
Cary Clark8032b982017-07-28 11:04:54 -04004251FontMetrics::fTop, FontMetrics::fXMax, FontMetrics::fBottom }.
4252
Cary Clarkce101242017-09-01 15:51:02 -04004253#Return union of bounds of all Glyphs ##
Cary Clark8032b982017-07-28 11:04:54 -04004254
4255#Example
4256 SkPaint paint;
4257 SkPaint::FontMetrics fm;
4258 paint.getFontMetrics(&fm);
4259 SkRect fb = paint.getFontBounds();
4260 SkDebugf("metrics bounds = { %g, %g, %g, %g }\n", fm.fXMin, fm.fTop, fm.fXMax, fm.fBottom );
4261 SkDebugf("font bounds = { %g, %g, %g, %g }\n", fb.fLeft, fb.fTop, fb.fRight, fm.fBottom );
4262
4263 #StdOut
4264 metrics bounds = { -12.2461, -14.7891, 21.5215, 5.55469 }
4265 font bounds = { -12.2461, -14.7891, 21.5215, 5.55469 }
4266 ##
4267##
4268
4269##
4270
Cary Clark08895c42018-02-01 09:37:32 -05004271#Subtopic Font_Metrics ##
Cary Clark8032b982017-07-28 11:04:54 -04004272# ------------------------------------------------------------------------------
4273
4274#Method int textToGlyphs(const void* text, size_t byteLength,
4275 SkGlyphID glyphs[]) const
Cary Clark78de7512018-02-07 07:27:09 -05004276#In Utility
Cary Clarkab2621d2018-01-30 10:08:57 -05004277#Line # converts text into glyph indices ##
Cary Clark8032b982017-07-28 11:04:54 -04004278
4279Converts text into glyph indices.
4280Returns the number of glyph indices represented by text.
4281Text_Encoding specifies how text represents characters or glyphs.
4282glyphs may be nullptr, to compute the glyph count.
4283
Cary Clarkbc5697d2017-10-04 14:31:33 -04004284Does not check text for valid character codes or valid glyph indices.
Cary Clark8032b982017-07-28 11:04:54 -04004285
Cary Clark579985c2017-07-31 11:48:27 -04004286If byteLength equals zero, returns zero.
Cary Clark8032b982017-07-28 11:04:54 -04004287If byteLength includes a partial character, the partial character is ignored.
4288
4289If Text_Encoding is kUTF8_TextEncoding and
4290text contains an invalid UTF-8 sequence, zero is returned.
4291
Cary Clarkce101242017-09-01 15:51:02 -04004292#Param text character storage encoded with Text_Encoding ##
Cary Clark8032b982017-07-28 11:04:54 -04004293#Param byteLength length of character storage in bytes ##
4294#Param glyphs storage for glyph indices; may be nullptr ##
4295
4296#Return number of glyphs represented by text of length byteLength ##
4297
4298 #Example
4299 #Height 64
4300 void draw(SkCanvas* canvas) {
4301 SkPaint paint;
4302 const uint8_t utf8[] = { 0x24, 0xC2, 0xA2, 0xE2, 0x82, 0xAC, 0xC2, 0xA5, 0xC2, 0xA3 };
4303 std::vector<SkGlyphID> glyphs;
4304 int count = paint.textToGlyphs(utf8, sizeof(utf8), nullptr);
4305 glyphs.resize(count);
4306 (void) paint.textToGlyphs(utf8, sizeof(utf8), &glyphs.front());
4307 paint.setTextEncoding(SkPaint::kGlyphID_TextEncoding);
4308 paint.setTextSize(32);
4309 canvas->drawText(&glyphs.front(), glyphs.size() * sizeof(SkGlyphID), 10, 40, paint);
4310 }
4311 ##
4312
4313##
4314
4315#Method int countText(const void* text, size_t byteLength) const
Cary Clark78de7512018-02-07 07:27:09 -05004316#In Utility
Cary Clarkab2621d2018-01-30 10:08:57 -05004317#Line # returns number of Glyphs in text ##
Cary Clarkce101242017-09-01 15:51:02 -04004318 Returns the number of Glyphs in text.
4319 Uses Text_Encoding to count the Glyphs.
Cary Clark8032b982017-07-28 11:04:54 -04004320 Returns the same result as textToGlyphs.
4321
Cary Clarkce101242017-09-01 15:51:02 -04004322#Param text character storage encoded with Text_Encoding ##
Cary Clark8032b982017-07-28 11:04:54 -04004323#Param byteLength length of character storage in bytes ##
4324
Cary Clarkce101242017-09-01 15:51:02 -04004325#Return number of Glyphs represented by text of length byteLength ##
Cary Clark8032b982017-07-28 11:04:54 -04004326
4327 #Example
4328 SkPaint paint;
4329 const uint8_t utf8[] = { 0x24, 0xC2, 0xA2, 0xE2, 0x82, 0xAC, 0xC2, 0xA5, 0xC2, 0xA3 };
4330 SkDebugf("count = %d\n", paint.countText(utf8, sizeof(utf8)));
4331
4332 #StdOut
4333 count = 5
4334 ##
4335 ##
4336##
4337
4338# ------------------------------------------------------------------------------
4339
4340#Method bool containsText(const void* text, size_t byteLength) const
Cary Clark78de7512018-02-07 07:27:09 -05004341#In Utility
Cary Clarkab2621d2018-01-30 10:08:57 -05004342#Line # returns if all text corresponds to Glyphs ##
Herb Derbyfcac00f2018-05-01 11:57:56 -04004343 Returns true if all text corresponds to a non-zero glyph index.
Cary Clark8032b982017-07-28 11:04:54 -04004344 Returns false if any characters in text are not supported in
4345 Typeface.
4346
Cary Clark579985c2017-07-31 11:48:27 -04004347 If Text_Encoding is kGlyphID_TextEncoding,
4348 returns true if all glyph indices in text are non-zero;
Cary Clark8032b982017-07-28 11:04:54 -04004349 does not check to see if text contains valid glyph indices for Typeface.
4350
Cary Clarkce101242017-09-01 15:51:02 -04004351 Returns true if byteLength is zero.
Cary Clark8032b982017-07-28 11:04:54 -04004352
Cary Clarkce101242017-09-01 15:51:02 -04004353 #Param text array of characters or Glyphs ##
Cary Clark8032b982017-07-28 11:04:54 -04004354 #Param byteLength number of bytes in text array ##
4355
4356 #Return true if all text corresponds to a non-zero glyph index ##
4357
4358 #Example
4359 #Description
4360 containsText succeeds for degree symbol, but cannot find a glyph index
4361 corresponding to the Unicode surrogate code point.
4362 ##
4363 SkPaint paint;
4364 const uint16_t goodChar = 0x00B0; // degree symbol
4365 const uint16_t badChar = 0xD800; // Unicode surrogate
4366 paint.setTextEncoding(SkPaint::kUTF16_TextEncoding);
Herb Derbyfcac00f2018-05-01 11:57:56 -04004367 SkDebugf("0x%04x %c= has char\n", goodChar,
Cary Clark8032b982017-07-28 11:04:54 -04004368 paint.containsText(&goodChar, 2) ? '=' : '!');
4369 SkDebugf("0x%04x %c= has char\n", badChar,
4370 paint.containsText(&badChar, 2) ? '=' : '!');
4371
4372 #StdOut
4373 0x00b0 == has char
4374 0xd800 != has char
4375 ##
4376 ##
4377
4378 #Example
4379 #Description
4380 containsText returns true that glyph index is greater than zero, not
4381 that it corresponds to an entry in Typeface.
4382 ##
4383 SkPaint paint;
4384 const uint16_t goodGlyph = 511;
4385 const uint16_t zeroGlyph = 0;
4386 const uint16_t badGlyph = 65535; // larger than glyph count in font
4387 paint.setTextEncoding(SkPaint::kGlyphID_TextEncoding);
Herb Derbyfcac00f2018-05-01 11:57:56 -04004388 SkDebugf("0x%04x %c= has glyph\n", goodGlyph,
Cary Clark8032b982017-07-28 11:04:54 -04004389 paint.containsText(&goodGlyph, 2) ? '=' : '!');
4390 SkDebugf("0x%04x %c= has glyph\n", zeroGlyph,
4391 paint.containsText(&zeroGlyph, 2) ? '=' : '!');
4392 SkDebugf("0x%04x %c= has glyph\n", badGlyph,
4393 paint.containsText(&badGlyph, 2) ? '=' : '!');
4394
4395 #StdOut
4396 0x01ff == has glyph
4397 0x0000 != has glyph
4398 0xffff == has glyph
4399 ##
4400 ##
4401
4402#SeeAlso setTextEncoding Typeface
4403
4404##
4405
4406# ------------------------------------------------------------------------------
4407
4408#Method void glyphsToUnichars(const SkGlyphID glyphs[],
4409 int count, SkUnichar text[]) const
Cary Clark78de7512018-02-07 07:27:09 -05004410#In Utility
Cary Clarkab2621d2018-01-30 10:08:57 -05004411#Line # converts Glyphs into text ##
Cary Clark8032b982017-07-28 11:04:54 -04004412
Herb Derbyfcac00f2018-05-01 11:57:56 -04004413 Converts glyphs into text if possible.
4414 Glyph values without direct Unicode equivalents are mapped to zero.
Cary Clark8032b982017-07-28 11:04:54 -04004415 Uses the Typeface, but is unaffected
4416 by Text_Encoding; the text values returned are equivalent to kUTF32_TextEncoding.
4417
4418 Only supported on platforms that use FreeType as the Font_Engine.
4419
4420 #Param glyphs array of indices into font ##
4421 #Param count length of glyph array ##
4422 #Param text storage for character codes, one per glyph ##
4423
4424 #Example
4425 #Height 64
4426 #Description
4427 Convert UTF-8 text to glyphs; then convert glyphs to Unichar code points.
4428 ##
4429 void draw(SkCanvas* canvas) {
4430 SkPaint paint;
4431 const char hello[] = "Hello!";
4432 const int count = sizeof(hello) - 1;
4433 SkGlyphID glyphs[count];
4434 if (count != paint.textToGlyphs(hello, count, glyphs)) {
4435 return;
4436 }
4437 SkUnichar unichars[count];
4438 paint.glyphsToUnichars(glyphs, count, unichars);
4439 paint.setTextEncoding(SkPaint::kUTF32_TextEncoding);
4440 canvas->drawText(unichars, sizeof(unichars), 10, 30, paint);
4441 }
4442 ##
4443
4444##
4445
4446# ------------------------------------------------------------------------------
Cary Clark08895c42018-02-01 09:37:32 -05004447#Subtopic Measure_Text
4448#Line # width, height, bounds of text ##
Cary Clark8032b982017-07-28 11:04:54 -04004449
4450#Method SkScalar measureText(const void* text, size_t length, SkRect* bounds) const
4451
Cary Clarkab2621d2018-01-30 10:08:57 -05004452#In Measure_Text
4453#Line # returns advance width and bounds of text ##
Cary Clark8032b982017-07-28 11:04:54 -04004454 Returns the advance width of text if kVerticalText_Flag is clear,
4455 and the height of text if kVerticalText_Flag is set.
4456 The advance is the normal distance to move before drawing additional text.
4457 Uses Text_Encoding to decode text, Typeface to get the font metrics,
4458 and Text_Size, Text_Scale_X, Text_Skew_X, Stroke_Width, and
4459 Path_Effect to scale the metrics and bounds.
4460 Returns the bounding box of text if bounds is not nullptr.
4461 The bounding box is computed as if the text was drawn at the origin.
Herb Derbyfcac00f2018-05-01 11:57:56 -04004462
Cary Clark8032b982017-07-28 11:04:54 -04004463 #Param text character codes or glyph indices to be measured ##
4464 #Param length number of bytes of text to measure ##
4465 #Param bounds returns bounding box relative to (0, 0) if not nullptr ##
4466
4467 #Return advance width or height ##
4468
4469 #Example
4470 #Height 64
4471 void draw(SkCanvas* canvas) {
4472 SkPaint paint;
4473 paint.setAntiAlias(true);
4474 paint.setTextSize(50);
4475 const char str[] = "ay^jZ";
4476 const int count = sizeof(str) - 1;
4477 canvas->drawText(str, count, 25, 50, paint);
4478 SkRect bounds;
4479 paint.measureText(str, count, &bounds);
4480 canvas->translate(25, 50);
4481 paint.setStyle(SkPaint::kStroke_Style);
4482 canvas->drawRect(bounds, paint);
4483 }
4484 ##
4485
4486##
4487
4488#Method SkScalar measureText(const void* text, size_t length) const
4489
Cary Clarkab2621d2018-01-30 10:08:57 -05004490#In Measure_Text
Cary Clark8032b982017-07-28 11:04:54 -04004491 Returns the advance width of text if kVerticalText_Flag is clear,
4492 and the height of text if kVerticalText_Flag is set.
4493 The advance is the normal distance to move before drawing additional text.
4494 Uses Text_Encoding to decode text, Typeface to get the font metrics,
4495 and Text_Size to scale the metrics.
4496 Does not scale the advance or bounds by Fake_Bold or Path_Effect.
4497
4498 #Param text character codes or glyph indices to be measured ##
4499 #Param length number of bytes of text to measure ##
4500
4501 #Return advance width or height ##
4502
4503 #Example
4504 SkPaint paint;
4505 SkDebugf("default width = %g\n", paint.measureText("!", 1));
4506 paint.setTextSize(paint.getTextSize() * 2);
4507 SkDebugf("double width = %g\n", paint.measureText("!", 1));
4508
4509 #StdOut
4510 default width = 5
4511 double width = 10
4512 ##
4513 ##
4514
4515##
4516
4517#Method size_t breakText(const void* text, size_t length, SkScalar maxWidth,
Cary Clark73fa9722017-08-29 17:36:51 -04004518 SkScalar* measuredWidth = nullptr) const
Cary Clarkab2621d2018-01-30 10:08:57 -05004519#In Measure_Text
4520#Line # returns text that fits in a width ##
Cary Clark8032b982017-07-28 11:04:54 -04004521
4522 Returns the bytes of text that fit within maxWidth.
4523 If kVerticalText_Flag is clear, the text fragment fits if its advance width is less than or
4524 equal to maxWidth.
4525 If kVerticalText_Flag is set, the text fragment fits if its advance height is less than or
4526 equal to maxWidth.
4527 Measures only while the advance is less than or equal to maxWidth.
4528 Returns the advance or the text fragment in measuredWidth if it not nullptr.
4529 Uses Text_Encoding to decode text, Typeface to get the font metrics,
4530 and Text_Size to scale the metrics.
4531 Does not scale the advance or bounds by Fake_Bold or Path_Effect.
4532
4533 #Param text character codes or glyph indices to be measured ##
4534 #Param length number of bytes of text to measure ##
4535 #Param maxWidth advance limit; text is measured while advance is less than maxWidth ##
4536 #Param measuredWidth returns the width of the text less than or equal to maxWidth ##
4537 #Return bytes of text that fit, always less than or equal to length ##
Herb Derbyfcac00f2018-05-01 11:57:56 -04004538
Cary Clark8032b982017-07-28 11:04:54 -04004539 #Example
4540 #Description
4541 Line under "Breakfast" shows desired width, shorter than available characters.
4542 Line under "Bre" shows measured width after breaking text.
4543 ##
4544 #Height 128
4545 #Width 280
4546 void draw(SkCanvas* canvas) {
4547 SkPaint paint;
4548 paint.setAntiAlias(true);
4549 paint.setTextSize(50);
4550 const char str[] = "Breakfast";
4551 const int count = sizeof(str) - 1;
4552 canvas->drawText(str, count, 25, 50, paint);
4553 SkScalar measuredWidth;
4554 int partialBytes = paint.breakText(str, count, 100, &measuredWidth);
4555 canvas->drawText(str, partialBytes, 25, 100, paint);
4556 canvas->drawLine(25, 60, 25 + 100, 60, paint);
4557 canvas->drawLine(25, 110, 25 + measuredWidth, 110, paint);
4558 }
4559 ##
4560
4561##
4562
4563#Method int getTextWidths(const void* text, size_t byteLength, SkScalar widths[],
Cary Clark73fa9722017-08-29 17:36:51 -04004564 SkRect bounds[] = nullptr) const
Cary Clarkab2621d2018-01-30 10:08:57 -05004565#In Measure_Text
4566#Line # returns advance and bounds for each glyph in text ##
Cary Clark8032b982017-07-28 11:04:54 -04004567
4568 Retrieves the advance and bounds for each glyph in text, and returns
4569 the glyph count in text.
4570 Both widths and bounds may be nullptr.
4571 If widths is not nullptr, widths must be an array of glyph count entries.
Herb Derbyfcac00f2018-05-01 11:57:56 -04004572 if bounds is not nullptr, bounds must be an array of glyph count entries.
Cary Clark8032b982017-07-28 11:04:54 -04004573 If kVerticalText_Flag is clear, widths returns the horizontal advance.
4574 If kVerticalText_Flag is set, widths returns the vertical advance.
4575 Uses Text_Encoding to decode text, Typeface to get the font metrics,
4576 and Text_Size to scale the widths and bounds.
4577 Does not scale the advance by Fake_Bold or Path_Effect.
4578 Does include Fake_Bold and Path_Effect in the bounds.
Herb Derbyfcac00f2018-05-01 11:57:56 -04004579
Cary Clark8032b982017-07-28 11:04:54 -04004580 #Param text character codes or glyph indices to be measured ##
4581 #Param byteLength number of bytes of text to measure ##
4582 #Param widths returns text advances for each glyph; may be nullptr ##
4583 #Param bounds returns bounds for each glyph relative to (0, 0); may be nullptr ##
Herb Derbyfcac00f2018-05-01 11:57:56 -04004584
Cary Clark8032b982017-07-28 11:04:54 -04004585 #Return glyph count in text ##
4586
4587 #Example
4588 #Height 160
4589 #Description
Cary Clarkce101242017-09-01 15:51:02 -04004590 Bounds of Glyphs increase for stroked text, but text advance remains the same.
Cary Clark8032b982017-07-28 11:04:54 -04004591 The underlines show the text advance, spaced to keep them distinct.
4592 ##
4593 void draw(SkCanvas* canvas) {
4594 SkPaint paint;
4595 paint.setAntiAlias(true);
4596 paint.setTextSize(50);
4597 const char str[] = "abc";
4598 const int bytes = sizeof(str) - 1;
4599 int count = paint.getTextWidths(str, bytes, nullptr);
4600 std::vector<SkScalar> widths;
4601 std::vector<SkRect> bounds;
4602 widths.resize(count);
4603 bounds.resize(count);
4604 for (int loop = 0; loop < 2; ++loop) {
4605 (void) paint.getTextWidths(str, count, &widths.front(), &bounds.front());
4606 SkPoint loc = { 25, 50 };
4607 canvas->drawText(str, bytes, loc.fX, loc.fY, paint);
4608 paint.setStyle(SkPaint::kStroke_Style);
4609 paint.setStrokeWidth(0);
4610 SkScalar advanceY = loc.fY + 10;
4611 for (int index = 0; index < count; ++index) {
4612 bounds[index].offset(loc.fX, loc.fY);
4613 canvas->drawRect(bounds[index], paint);
4614 canvas->drawLine(loc.fX, advanceY, loc.fX + widths[index], advanceY, paint);
4615 loc.fX += widths[index];
4616 advanceY += 5;
4617 }
4618 canvas->translate(0, 80);
4619 paint.setStrokeWidth(3);
4620 }
4621 }
4622 ##
4623
4624##
4625
Cary Clark08895c42018-02-01 09:37:32 -05004626#Subtopic Measure_Text ##
Cary Clark8032b982017-07-28 11:04:54 -04004627# ------------------------------------------------------------------------------
Cary Clark08895c42018-02-01 09:37:32 -05004628#Subtopic Text_Path
4629#Line # geometry of Glyphs ##
Cary Clark8032b982017-07-28 11:04:54 -04004630
Cary Clarkce101242017-09-01 15:51:02 -04004631Text_Path describes the geometry of Glyphs used to draw text.
Cary Clark8032b982017-07-28 11:04:54 -04004632
4633#Method void getTextPath(const void* text, size_t length, SkScalar x, SkScalar y,
4634 SkPath* path) const
Cary Clarkab2621d2018-01-30 10:08:57 -05004635#In Text_Path
4636#Line # returns Path equivalent to text ##
Cary Clark8032b982017-07-28 11:04:54 -04004637
4638Returns the geometry as Path equivalent to the drawn text.
4639Uses Text_Encoding to decode text, Typeface to get the glyph paths,
4640and Text_Size, Fake_Bold, and Path_Effect to scale and modify the glyph paths.
4641All of the glyph paths are stored in path.
Cary Clark579985c2017-07-31 11:48:27 -04004642Uses x, y, and Text_Align to position path.
Cary Clark8032b982017-07-28 11:04:54 -04004643
4644 #Param text character codes or glyph indices ##
4645 #Param length number of bytes of text ##
4646 #Param x x-coordinate of the origin of the text ##
4647 #Param y y-coordinate of the origin of the text ##
Cary Clarkce101242017-09-01 15:51:02 -04004648 #Param path geometry of the Glyphs ##
Cary Clark8032b982017-07-28 11:04:54 -04004649
4650 #Example
4651 #Description
4652 Text is added to Path, offset, and subtracted from Path, then added at
4653 the offset location. The result is rendered with one draw call.
4654 ##
4655 #Height 128
4656 void draw(SkCanvas* canvas) {
4657 SkPaint paint;
4658 paint.setTextSize(80);
4659 SkPath path, path2;
4660 paint.getTextPath("ABC", 3, 20, 80, &path);
4661 path.offset(20, 20, &path2);
4662 Op(path, path2, SkPathOp::kDifference_SkPathOp, &path);
4663 path.addPath(path2);
4664 paint.setStyle(SkPaint::kStroke_Style);
4665 canvas->drawPath(path, paint);
4666 }
4667 ##
4668
4669##
4670
4671#Method void getPosTextPath(const void* text, size_t length,
4672 const SkPoint pos[], SkPath* path) const
Cary Clarkab2621d2018-01-30 10:08:57 -05004673#In Text_Path
4674#Line # returns Path equivalent to positioned text ##
Cary Clark8032b982017-07-28 11:04:54 -04004675
4676Returns the geometry as Path equivalent to the drawn text.
4677Uses Text_Encoding to decode text, Typeface to get the glyph paths,
4678and Text_Size, Fake_Bold, and Path_Effect to scale and modify the glyph paths.
4679All of the glyph paths are stored in path.
4680Uses pos array and Text_Align to position path.
4681pos contains a position for each glyph.
4682
4683 #Param text character codes or glyph indices ##
4684 #Param length number of bytes of text ##
4685 #Param pos positions of each glyph ##
Cary Clarkce101242017-09-01 15:51:02 -04004686 #Param path geometry of the Glyphs ##
Cary Clark8032b982017-07-28 11:04:54 -04004687
4688 #Example
4689 #Height 85
4690 #Description
Cary Clarkce101242017-09-01 15:51:02 -04004691 Simplifies three Glyphs to eliminate overlaps, and strokes the result.
Cary Clark8032b982017-07-28 11:04:54 -04004692 ##
4693 void draw(SkCanvas* canvas) {
4694 SkPaint paint;
4695 paint.setTextSize(80);
4696 SkPath path, path2;
4697 SkPoint pos[] = {{20, 60}, {30, 70}, {40, 80}};
4698 paint.getPosTextPath("ABC", 3, pos, &path);
4699 Simplify(path, &path);
4700 paint.setStyle(SkPaint::kStroke_Style);
4701 canvas->drawPath(path, paint);
4702 }
4703 ##
4704
4705##
4706
Cary Clark08895c42018-02-01 09:37:32 -05004707#Subtopic Text_Path ##
Cary Clark8032b982017-07-28 11:04:54 -04004708# ------------------------------------------------------------------------------
Cary Clark08895c42018-02-01 09:37:32 -05004709#Subtopic Text_Intercepts
4710#Line # advanced underline, strike through ##
Cary Clark8032b982017-07-28 11:04:54 -04004711
Cary Clarkce101242017-09-01 15:51:02 -04004712Text_Intercepts describe the intersection of drawn text Glyphs with a pair
Cary Clark8032b982017-07-28 11:04:54 -04004713of lines parallel to the text advance. Text_Intercepts permits creating a
Cary Clarkce101242017-09-01 15:51:02 -04004714underline that skips Descenders.
Cary Clark8032b982017-07-28 11:04:54 -04004715
4716#Method int getTextIntercepts(const void* text, size_t length, SkScalar x, SkScalar y,
4717 const SkScalar bounds[2], SkScalar* intervals) const
Cary Clarkab2621d2018-01-30 10:08:57 -05004718#In Text_Intercepts
4719#Line # returns where lines intersect text; underlines ##
Cary Clark8032b982017-07-28 11:04:54 -04004720
4721 Returns the number of intervals that intersect bounds.
4722 bounds describes a pair of lines parallel to the text advance.
Cary Clarkce101242017-09-01 15:51:02 -04004723 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 -04004724 the string.
Cary Clark8032b982017-07-28 11:04:54 -04004725 Uses Text_Encoding to decode text, Typeface to get the glyph paths,
4726 and Text_Size, Fake_Bold, and Path_Effect to scale and modify the glyph paths.
4727 Uses x, y, and Text_Align to position intervals.
Herb Derbyfcac00f2018-05-01 11:57:56 -04004728
Cary Clark8032b982017-07-28 11:04:54 -04004729 Pass nullptr for intervals to determine the size of the interval array.
Herb Derbyfcac00f2018-05-01 11:57:56 -04004730
Cary Clark8032b982017-07-28 11:04:54 -04004731 intervals are cached to improve performance for multiple calls.
4732
4733 #Param text character codes or glyph indices ##
4734 #Param length number of bytes of text ##
4735 #Param x x-coordinate of the origin of the text ##
4736 #Param y y-coordinate of the origin of the text ##
4737 #Param bounds lower and upper line parallel to the advance ##
4738 #Param intervals returned intersections; may be nullptr ##
4739
4740 #Return number of intersections; may be zero ##
4741
4742#Example
4743#Height 128
4744#Description
Cary Clarkce101242017-09-01 15:51:02 -04004745Underline uses intercepts to draw on either side of the glyph Descender.
Cary Clark8032b982017-07-28 11:04:54 -04004746##
4747void draw(SkCanvas* canvas) {
4748 SkPaint paint;
4749 paint.setTextSize(120);
4750 SkPoint textOrigin = { 20, 100 };
4751 SkScalar bounds[] = { 100, 108 };
4752 int count = paint.getTextIntercepts("y", 1, textOrigin.fX, textOrigin.fY, bounds, nullptr);
4753 std::vector<SkScalar> intervals;
4754 intervals.resize(count);
4755 (void) paint.getTextIntercepts("y", 1, textOrigin.fX, textOrigin.fY, bounds,
4756 &intervals.front());
4757 canvas->drawString("y", textOrigin.fX, textOrigin.fY, paint);
4758 paint.setColor(SK_ColorRED);
4759 SkScalar x = textOrigin.fX;
4760 for (int i = 0; i < count; i += 2) {
4761 canvas->drawRect({x, bounds[0], intervals[i], bounds[1]}, paint);
4762 x = intervals[i + 1];
4763 }
4764 canvas->drawRect({intervals[count - 1], bounds[0],
4765 textOrigin.fX + paint.measureText("y", 1), bounds[1]}, paint);
4766}
4767##
4768
4769##
4770
4771#Method int getPosTextIntercepts(const void* text, size_t length, const SkPoint pos[],
4772 const SkScalar bounds[2], SkScalar* intervals) const
Cary Clarkab2621d2018-01-30 10:08:57 -05004773#In Text_Intercepts
4774#Line # returns where lines intersect positioned text; underlines ##
Cary Clark8032b982017-07-28 11:04:54 -04004775
4776 Returns the number of intervals that intersect bounds.
4777 bounds describes a pair of lines parallel to the text advance.
Cary Clarkce101242017-09-01 15:51:02 -04004778 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 -04004779 the string.
Cary Clark8032b982017-07-28 11:04:54 -04004780 Uses Text_Encoding to decode text, Typeface to get the glyph paths,
4781 and Text_Size, Fake_Bold, and Path_Effect to scale and modify the glyph paths.
4782 Uses pos array and Text_Align to position intervals.
Herb Derbyfcac00f2018-05-01 11:57:56 -04004783
Cary Clark8032b982017-07-28 11:04:54 -04004784 Pass nullptr for intervals to determine the size of the interval array.
Herb Derbyfcac00f2018-05-01 11:57:56 -04004785
Cary Clark8032b982017-07-28 11:04:54 -04004786 intervals are cached to improve performance for multiple calls.
4787
4788 #Param text character codes or glyph indices ##
4789 #Param length number of bytes of text ##
4790 #Param pos positions of each glyph ##
4791 #Param bounds lower and upper line parallel to the advance ##
4792 #Param intervals returned intersections; may be nullptr ##
4793
Cary Clarka523d2d2017-08-30 08:58:10 -04004794 #Return number of intersections; may be zero ##
Cary Clark8032b982017-07-28 11:04:54 -04004795
4796 #Example
4797 #Description
Cary Clarkce101242017-09-01 15:51:02 -04004798 Text intercepts draw on either side of, but not inside, Glyphs in a run.
Cary Clark8032b982017-07-28 11:04:54 -04004799 ##
4800 void draw(SkCanvas* canvas) {
4801 SkPaint paint;
4802 paint.setTextSize(120);
4803 paint.setVerticalText(true);
4804 SkPoint textPos[] = {{ 60, 40 }, { 60, 140 }};
4805 SkScalar bounds[] = { 56, 64 };
4806 const char str[] = "A-";
4807 int len = sizeof(str) - 1;
4808 int count = paint.getPosTextIntercepts(str, len, textPos, bounds, nullptr);
4809 std::vector<SkScalar> intervals;
4810 intervals.resize(count);
4811 (void) paint.getPosTextIntercepts(str, len, textPos, bounds, &intervals.front());
4812 canvas->drawPosText(str, len, textPos, paint);
4813 paint.setColor(SK_ColorRED);
4814 SkScalar y = textPos[0].fY;
4815 for (int i = 0; i < count; i+= 2) {
4816 canvas->drawRect({bounds[0], y, bounds[1], intervals[i]}, paint);
4817 y = intervals[i + 1];
4818 }
4819 canvas->drawRect({bounds[0], intervals[count - 1], bounds[1], 240}, paint);
4820 }
4821 ##
4822
4823##
4824
4825#Method int getPosTextHIntercepts(const void* text, size_t length, const SkScalar xpos[],
4826 SkScalar constY, const SkScalar bounds[2],
4827 SkScalar* intervals) const
Cary Clarkab2621d2018-01-30 10:08:57 -05004828#In Text_Intercepts
4829#Line # returns where lines intersect horizontally positioned text; underlines ##
Cary Clark8032b982017-07-28 11:04:54 -04004830
4831 Returns the number of intervals that intersect bounds.
4832 bounds describes a pair of lines parallel to the text advance.
Cary Clarkce101242017-09-01 15:51:02 -04004833 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 -04004834 the string.
Cary Clark8032b982017-07-28 11:04:54 -04004835 Uses Text_Encoding to decode text, Typeface to get the glyph paths,
4836 and Text_Size, Fake_Bold, and Path_Effect to scale and modify the glyph paths.
4837 Uses xpos array, constY, and Text_Align to position intervals.
Herb Derbyfcac00f2018-05-01 11:57:56 -04004838
Cary Clark8032b982017-07-28 11:04:54 -04004839 Pass nullptr for intervals to determine the size of the interval array.
Herb Derbyfcac00f2018-05-01 11:57:56 -04004840
Cary Clark8032b982017-07-28 11:04:54 -04004841 intervals are cached to improve performance for multiple calls.
4842
4843 #Param text character codes or glyph indices ##
4844 #Param length number of bytes of text ##
4845 #Param xpos positions of each glyph in x ##
4846 #Param constY position of each glyph in y ##
4847 #Param bounds lower and upper line parallel to the advance ##
4848 #Param intervals returned intersections; may be nullptr ##
4849
4850 #Return number of intersections; may be zero ##
4851
4852 #Example
4853 #Height 128
4854 #Description
4855 Text intercepts do not take stroke thickness into consideration.
4856 ##
4857 void draw(SkCanvas* canvas) {
4858 SkPaint paint;
4859 paint.setTextSize(120);
4860 paint.setStyle(SkPaint::kStroke_Style);
4861 paint.setStrokeWidth(4);
4862 SkScalar textPosH[] = { 20, 80, 140 };
4863 SkScalar y = 100;
4864 SkScalar bounds[] = { 56, 78 };
4865 const char str[] = "\\-/";
4866 int len = sizeof(str) - 1;
4867 int count = paint.getPosTextHIntercepts(str, len, textPosH, y, bounds, nullptr);
4868 std::vector<SkScalar> intervals;
4869 intervals.resize(count);
4870 (void) paint.getPosTextHIntercepts(str, len, textPosH, y, bounds, &intervals.front());
4871 canvas->drawPosTextH(str, len, textPosH, y, paint);
4872 paint.setColor(0xFFFF7777);
4873 paint.setStyle(SkPaint::kFill_Style);
4874 SkScalar x = textPosH[0];
4875 for (int i = 0; i < count; i+= 2) {
4876 canvas->drawRect({x, bounds[0], intervals[i], bounds[1]}, paint);
4877 x = intervals[i + 1];
4878 }
4879 canvas->drawRect({intervals[count - 1], bounds[0], 180, bounds[1]}, paint);
4880 }
4881 ##
4882
4883##
4884
4885
4886#Method int getTextBlobIntercepts(const SkTextBlob* blob, const SkScalar bounds[2],
4887 SkScalar* intervals) const
Cary Clarkab2621d2018-01-30 10:08:57 -05004888#In Text_Intercepts
4889#Line # returns where lines intersect Text_Blob; underlines ##
Cary Clark8032b982017-07-28 11:04:54 -04004890
4891 Returns the number of intervals that intersect bounds.
4892 bounds describes a pair of lines parallel to the text advance.
Cary Clarkce101242017-09-01 15:51:02 -04004893 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 -04004894 the string.
Cary Clark3cd22cc2017-12-01 11:49:58 -05004895 Uses Typeface to get the glyph paths,
Cary Clark8032b982017-07-28 11:04:54 -04004896 and Text_Size, Fake_Bold, and Path_Effect to scale and modify the glyph paths.
Cary Clarkce101242017-09-01 15:51:02 -04004897 Uses run array and Text_Align to position intervals.
Herb Derbyfcac00f2018-05-01 11:57:56 -04004898
Cary Clark3cd22cc2017-12-01 11:49:58 -05004899 Text_Encoding must be set to SkPaint::kGlyphID_TextEncoding.
4900
Cary Clark8032b982017-07-28 11:04:54 -04004901 Pass nullptr for intervals to determine the size of the interval array.
Herb Derbyfcac00f2018-05-01 11:57:56 -04004902
Cary Clark8032b982017-07-28 11:04:54 -04004903 intervals are cached to improve performance for multiple calls.
4904
Cary Clarkce101242017-09-01 15:51:02 -04004905 #Param blob Glyphs, positions, and text paint attributes ##
Cary Clark8032b982017-07-28 11:04:54 -04004906 #Param bounds lower and upper line parallel to the advance ##
4907 #Param intervals returned intersections; may be nullptr ##
4908
4909 #Return number of intersections; may be zero ##
4910
4911 #Example
4912 #Height 143
4913 void draw(SkCanvas* canvas) {
4914 SkPaint paint;
Cary Clark3cd22cc2017-12-01 11:49:58 -05004915 paint.setTextEncoding(SkPaint::kGlyphID_TextEncoding);
Cary Clark8032b982017-07-28 11:04:54 -04004916 paint.setTextSize(120);
4917 SkPoint textPos = { 20, 110 };
4918 int len = 3;
4919 SkTextBlobBuilder textBlobBuilder;
Herb Derbyfcac00f2018-05-01 11:57:56 -04004920 const SkTextBlobBuilder::RunBuffer& run =
Cary Clark8032b982017-07-28 11:04:54 -04004921 textBlobBuilder.allocRun(paint, len, textPos.fX, textPos.fY);
4922 run.glyphs[0] = 10;
4923 run.glyphs[1] = 20;
Herb Derbyfcac00f2018-05-01 11:57:56 -04004924 run.glyphs[2] = 30;
Cary Clark8032b982017-07-28 11:04:54 -04004925 sk_sp<const SkTextBlob> blob = textBlobBuilder.make();
4926 canvas->drawTextBlob(blob.get(), textPos.fX, textPos.fY, paint);
4927 SkScalar bounds[] = { 116, 134 };
4928 int count = paint.getTextBlobIntercepts(blob.get(), bounds, nullptr);
4929 std::vector<SkScalar> intervals;
4930 intervals.resize(count);
4931 (void) paint.getTextBlobIntercepts(blob.get(), bounds, &intervals.front());
4932 canvas->drawTextBlob(blob.get(), 0, 0, paint);
4933 paint.setColor(0xFFFF7777);
4934 SkScalar x = textPos.fX;
4935 for (int i = 0; i < count; i+= 2) {
4936 canvas->drawRect({x, bounds[0], intervals[i], bounds[1]}, paint);
4937 x = intervals[i + 1];
4938 }
4939 canvas->drawRect({intervals[count - 1], bounds[0], 180, bounds[1]}, paint);
4940 }
4941 ##
4942
4943##
4944
Cary Clark08895c42018-02-01 09:37:32 -05004945#Subtopic Text_Intercepts ##
Cary Clark8032b982017-07-28 11:04:54 -04004946# ------------------------------------------------------------------------------
4947
4948#Method bool nothingToDraw() const
Cary Clark78de7512018-02-07 07:27:09 -05004949#In Utility
Cary Clarkab2621d2018-01-30 10:08:57 -05004950#Line # returns true if Paint prevents all drawing ##
Cary Clark579985c2017-07-31 11:48:27 -04004951 Returns true if Paint prevents all drawing;
4952 otherwise, the Paint may or may not allow drawing.
Cary Clark8032b982017-07-28 11:04:54 -04004953
Cary Clarkce101242017-09-01 15:51:02 -04004954 Returns true if, for example, Blend_Mode combined with Color_Alpha computes a
4955 new Alpha of zero.
Cary Clark8032b982017-07-28 11:04:54 -04004956
4957 #Return true if Paint prevents all drawing ##
4958
4959 #Example
4960 void draw(SkCanvas* canvas) {
4961 auto debugster = [](const char* prefix, const SkPaint& p) -> void {
Herb Derbyfcac00f2018-05-01 11:57:56 -04004962 SkDebugf("%s nothing to draw: %s\n", prefix,
Cary Clark8032b982017-07-28 11:04:54 -04004963 p.nothingToDraw() ? "true" : "false");
4964 };
4965 SkPaint paint;
4966 debugster("initial", paint);
4967 paint.setBlendMode(SkBlendMode::kDst);
4968 debugster("blend dst", paint);
4969 paint.setBlendMode(SkBlendMode::kSrcOver);
4970 debugster("blend src over", paint);
4971 paint.setAlpha(0);
4972 debugster("alpha 0", paint);
4973 }
4974
4975 #StdOut
4976 initial nothing to draw: false
4977 blend dst nothing to draw: true
4978 blend src over nothing to draw: false
4979 alpha 0 nothing to draw: true
4980 #StdOut ##
4981 ##
4982
4983##
4984
4985# ------------------------------------------------------------------------------
Cary Clark08895c42018-02-01 09:37:32 -05004986#Subtopic Fast_Bounds
4987#Line # approximate area required by Paint ##
Herb Derbyfcac00f2018-05-01 11:57:56 -04004988 #Private
4989 To be made private.
Cary Clark8032b982017-07-28 11:04:54 -04004990 ##
4991
4992Fast_Bounds methods conservatively outset a drawing bounds by additional area
4993Paint may draw to.
4994
4995#Method bool canComputeFastBounds() const
Herb Derbyfcac00f2018-05-01 11:57:56 -04004996
Cary Clarkab2621d2018-01-30 10:08:57 -05004997#In Fast_Bounds
Cary Clark1a8d7622018-03-05 13:26:16 -05004998#Line # returns true if settings allow for fast bounds computation ##
Herb Derbyfcac00f2018-05-01 11:57:56 -04004999 #Private
Cary Clark8032b982017-07-28 11:04:54 -04005000 (to be made private)
5001 ##
5002
5003 Returns true if Paint does not include elements requiring extensive computation
5004 to compute Device bounds of drawn geometry. For instance, Paint with Path_Effect
5005 always returns false.
5006
5007 #Return true if Paint allows for fast computation of bounds ##
5008##
5009
5010#Method const SkRect& computeFastBounds(const SkRect& orig, SkRect* storage) const
Herb Derbyfcac00f2018-05-01 11:57:56 -04005011
Cary Clarkab2621d2018-01-30 10:08:57 -05005012#In Fast_Bounds
Cary Clark1a8d7622018-03-05 13:26:16 -05005013#Line # returns fill bounds for quick reject tests ##
Herb Derbyfcac00f2018-05-01 11:57:56 -04005014 #Private
Cary Clark8032b982017-07-28 11:04:54 -04005015 (to be made private)
5016 ##
5017
5018 Only call this if canComputeFastBounds returned true. This takes a
5019 raw rectangle (the raw bounds of a shape), and adjusts it for stylistic
5020 effects in the paint (e.g. stroking). If needed, it uses the storage
Cary Clarkce101242017-09-01 15:51:02 -04005021 parameter. It returns the adjusted bounds that can then be used
Cary Clark8032b982017-07-28 11:04:54 -04005022 for SkCanvas::quickReject tests.
5023
Cary Clarkce101242017-09-01 15:51:02 -04005024 The returned Rect will either be orig or storage, thus the caller
Cary Clark8032b982017-07-28 11:04:54 -04005025 should not rely on storage being set to the result, but should always
Cary Clarkce101242017-09-01 15:51:02 -04005026 use the returned value. It is legal for orig and storage to be the same
5027 Rect.
Cary Clark8032b982017-07-28 11:04:54 -04005028
Herb Derbyfcac00f2018-05-01 11:57:56 -04005029 #Private
Cary Clark8032b982017-07-28 11:04:54 -04005030 e.g.
5031 if (paint.canComputeFastBounds()) {
5032 SkRect r, storage;
5033 path.computeBounds(&r, SkPath::kFast_BoundsType);
5034 const SkRect& fastR = paint.computeFastBounds(r, &storage);
5035 if (canvas->quickReject(fastR, ...)) {
5036 // don't draw the path
5037 }
5038 }
5039 ##
5040
5041 #Param orig geometry modified by Paint when drawn ##
5042 #Param storage computed bounds of geometry; may not be nullptr ##
5043
5044 #Return fast computed bounds ##
5045##
5046
5047#Method const SkRect& computeFastStrokeBounds(const SkRect& orig,
5048 SkRect* storage) const
Cary Clarkab2621d2018-01-30 10:08:57 -05005049#In Fast_Bounds
5050#Line # returns stroke bounds for quick reject tests ##
Herb Derbyfcac00f2018-05-01 11:57:56 -04005051 #Private
Cary Clark8032b982017-07-28 11:04:54 -04005052 (to be made private)
5053 ##
5054
5055 #Param orig geometry modified by Paint when drawn ##
5056 #Param storage computed bounds of geometry ##
5057
5058 #Return fast computed bounds ##
5059##
5060
5061#Method const SkRect& doComputeFastBounds(const SkRect& orig, SkRect* storage,
5062 Style style) const
Cary Clarkab2621d2018-01-30 10:08:57 -05005063#In Fast_Bounds
5064#Line # returns bounds for quick reject tests ##
Herb Derbyfcac00f2018-05-01 11:57:56 -04005065 #Private
Cary Clark8032b982017-07-28 11:04:54 -04005066 (to be made private)
5067 ##
5068
Cary Clarkce101242017-09-01 15:51:02 -04005069 Computes the bounds, overriding the Paint Style. This can be used to
5070 account for additional width required by stroking orig, without
5071 altering Style set to fill.
Cary Clark8032b982017-07-28 11:04:54 -04005072
5073 #Param orig geometry modified by Paint when drawn ##
5074 #Param storage computed bounds of geometry ##
5075 #Param style overrides Style ##
5076
5077 #Return fast computed bounds ##
5078##
5079
Cary Clark1a8d7622018-03-05 13:26:16 -05005080#Subtopic Fast_Bounds ##
Cary Clark8032b982017-07-28 11:04:54 -04005081
5082# ------------------------------------------------------------------------------
Cary Clark78de7512018-02-07 07:27:09 -05005083#Subtopic Utility
5084#Populate
5085#Line # rarely called management functions ##
5086##
Cary Clark8032b982017-07-28 11:04:54 -04005087
Cary Clark78de7512018-02-07 07:27:09 -05005088#Method void toString(SkString* str) const
5089#In Utility
Cary Clarkab2621d2018-01-30 10:08:57 -05005090#Line # converts Paint to machine readable form ##
Cary Clark8032b982017-07-28 11:04:54 -04005091
Cary Clarkce101242017-09-01 15:51:02 -04005092Creates string representation of Paint. The representation is read by
Cary Clark99885412018-04-05 13:09:58 -04005093internal debugging tools.
Cary Clark8032b982017-07-28 11:04:54 -04005094
Cary Clarkce101242017-09-01 15:51:02 -04005095#Param str storage for string representation of Paint ##
Cary Clark8032b982017-07-28 11:04:54 -04005096
5097#Example
5098 SkPaint paint;
5099 SkString str;
5100 paint.toString(&str);
5101 const char textSize[] = "TextSize:";
5102 const int trailerSize = strlen("</dd><dt>");
5103 int textSizeLoc = str.find(textSize) + strlen(textSize) + trailerSize;
5104 const char* sizeStart = &str.c_str()[textSizeLoc];
5105 int textSizeEnd = SkStrFind(sizeStart, "</dd>");
5106 SkDebugf("text size = %.*s\n", textSizeEnd, sizeStart);
5107
5108 #StdOut
5109 text size = 12
5110 ##
5111
5112##
5113
Cary Clark2ade9972017-11-02 17:49:34 -04005114#SeeAlso SkPathEffect::toString SkMaskFilter::toString SkColorFilter::toString SkImageFilter::toString
Cary Clark8032b982017-07-28 11:04:54 -04005115
5116##
5117
5118# ------------------------------------------------------------------------------
5119
5120#Class SkPaint ##
5121
5122#Topic Paint ##
Cary Clark4855f782018-02-06 09:41:53 -05005123