blob: 373be0e50920b85b705bb0dcdc9b3d6155a39c43 [file] [log] [blame]
Cary Clark0c5f5462017-12-15 11:21:51 -05001#Topic Paint
Cary Clark137b8742018-05-30 09:21:49 -04002#Alias Paint_Reference ##
Cary Clark8032b982017-07-28 11:04:54 -04003
Cary Clark61313f32018-10-08 14:57:48 -04004#PhraseDef paint_font_metrics
5Typeface, Paint_Text_Size, Paint_Text_Scale_X,
Mike Reed5f617982018-11-02 19:52:03 -04006Paint_Text_Skew_X, Paint_Hinting, Anti_Alias, Paint_Fake_Bold,
Cary Clark61313f32018-10-08 14:57:48 -04007Font_Embedded_Bitmaps, Full_Hinting_Spacing, LCD_Text, Linear_Text,
8and Subpixel_Text
9##
10
Cary Clarke4aa3712017-09-15 02:56:12 -040011#Class SkPaint
12
Cary Clark61313f32018-10-08 14:57:48 -040013#Code
14#Populate
15##
16
Cary Clark8032b982017-07-28 11:04:54 -040017Paint controls options applied when drawing and measuring. Paint collects all
18options outside of the Canvas_Clip and Canvas_Matrix.
19
Herb Derbyfcac00f2018-05-01 11:57:56 -040020Various options apply to text, strokes and fills, and images.
Cary Clark8032b982017-07-28 11:04:54 -040021
22Some options may not be implemented on all platforms; in these cases, setting
23the option has no effect. Some options are conveniences that duplicate Canvas
24functionality; for instance, text size is identical to matrix scale.
25
26Paint options are rarely exclusive; each option modifies a stage of the drawing
27pipeline and multiple pipeline stages may be affected by a single Paint.
28
Herb Derbyfcac00f2018-05-01 11:57:56 -040029Paint collects effects and filters that describe single-pass and multiple-pass
Cary Clark8032b982017-07-28 11:04:54 -040030algorithms that alter the drawing geometry, color, and transparency. For instance,
Herb Derbyfcac00f2018-05-01 11:57:56 -040031Paint does not directly implement dashing or blur, but contains the objects that do so.
Cary Clark8032b982017-07-28 11:04:54 -040032
33The objects contained by Paint are opaque, and cannot be edited outside of the Paint
34to affect it. The implementation is free to defer computations associated with the
35Paint, or ignore them altogether. For instance, some GPU implementations draw all
Cary Clarkffb3d682018-05-17 12:17:28 -040036Path geometries with Anti_Aliasing, regardless of how SkPaint::kAntiAlias_Flag
Cary Clarkbad5ad72017-08-03 17:14:08 -040037is set in Paint.
Cary Clark8032b982017-07-28 11:04:54 -040038
39Paint describes a single color, a single font, a single image quality, and so on.
40Multiple colors are drawn either by using multiple paints or with objects like
41Shader attached to Paint.
42
Cary Clark8032b982017-07-28 11:04:54 -040043#Method SkPaint()
Cary Clarkab2621d2018-01-30 10:08:57 -050044#Line # constructs with default values ##
Cary Clark8032b982017-07-28 11:04:54 -040045Constructs Paint with default values.
46
47#Table
48#Legend
49# attribute # default value ##
50#Legend ##
Cary Clarkffb3d682018-05-17 12:17:28 -040051# Anti_Alias # false ##
Cary Clarkce101242017-09-01 15:51:02 -040052# Blend_Mode # SkBlendMode::kSrcOver ##
Cary Clark8032b982017-07-28 11:04:54 -040053# Color # SK_ColorBLACK ##
54# Color_Alpha # 255 ##
55# Color_Filter # nullptr ##
56# Dither # false ##
57# Draw_Looper # nullptr ##
58# Fake_Bold # false ##
59# Filter_Quality # kNone_SkFilterQuality ##
60# Font_Embedded_Bitmaps # false ##
61# Automatic_Hinting # false ##
62# Full_Hinting_Spacing # false ##
Cary Clark4a23bbf2018-11-08 16:00:33 -050063# Hinting # SkFontHinting::kNormal ##
Cary Clark8032b982017-07-28 11:04:54 -040064# Image_Filter # nullptr ##
65# LCD_Text # false ##
66# Linear_Text # false ##
67# Miter_Limit # 4 ##
68# Mask_Filter # nullptr ##
69# Path_Effect # nullptr ##
Cary Clark8032b982017-07-28 11:04:54 -040070# Shader # nullptr ##
71# Style # kFill_Style ##
Cary Clark8032b982017-07-28 11:04:54 -040072# Text_Encoding # kUTF8_TextEncoding ##
73# Text_Scale_X # 1 ##
74# Text_Size # 12 ##
75# Text_Skew_X # 0 ##
76# Typeface # nullptr ##
77# Stroke_Cap # kButt_Cap ##
78# Stroke_Join # kMiter_Join ##
79# Stroke_Width # 0 ##
80# Subpixel_Text # false ##
Cary Clark8032b982017-07-28 11:04:54 -040081#Table ##
82
83The flags, text size, hinting, and miter limit may be overridden at compile time by defining
Herb Derbyfcac00f2018-05-01 11:57:56 -040084paint default values. The overrides may be included in "SkUserConfig.h" or predefined by the
Cary Clark8032b982017-07-28 11:04:54 -040085build system.
86
87#Return default initialized Paint ##
88
89#Example
90#ToDo mark this as no output ##
91#Height 1
92###$ $ redefine markup character so preprocessor commands appear normally
93#ifndef SkUserConfig_DEFINED
94#define SkUserConfig_DEFINED
95
96#define SkPaintDefaults_Flags 0x01 // always enable antialiasing
97#define SkPaintDefaults_TextSize 24.f // double default font size
98#define SkPaintDefaults_Hinting 3 // use full hinting
99#define SkPaintDefaults_MiterLimit 10.f // use HTML Canvas miter limit setting
100
101#endif
102$$$# # restore original markup character
103##
104
105
106##
107
108#Method SkPaint(const SkPaint& paint)
Cary Clarkab2621d2018-01-30 10:08:57 -0500109#Line # makes a shallow copy ##
Cary Clark09d80c02018-10-31 12:14:03 -0400110#Populate
Cary Clark8032b982017-07-28 11:04:54 -0400111
112#Example
113#ToDo why is this double-spaced on Fiddle? ##
114 SkPaint paint1;
115 paint1.setColor(SK_ColorRED);
116 SkPaint paint2(paint1);
117 paint2.setColor(SK_ColorBLUE);
118 SkDebugf("SK_ColorRED %c= paint1.getColor()\n", SK_ColorRED == paint1.getColor() ? '=' : '!');
119 SkDebugf("SK_ColorBLUE %c= paint2.getColor()\n", SK_ColorBLUE == paint2.getColor() ? '=' : '!');
120
121 #StdOut
122 SK_ColorRED == paint1.getColor()
123 SK_ColorBLUE == paint2.getColor()
124 ##
125##
126
127##
128
129#Method SkPaint(SkPaint&& paint)
Cary Clarkab2621d2018-01-30 10:08:57 -0500130#Line # moves paint without copying it ##
Cary Clark09d80c02018-10-31 12:14:03 -0400131#Populate
Cary Clark8032b982017-07-28 11:04:54 -0400132
Cary Clark09d80c02018-10-31 12:14:03 -0400133#Example
Cary Clark8032b982017-07-28 11:04:54 -0400134 SkPaint paint;
135 float intervals[] = { 5, 5 };
136 paint.setPathEffect(SkDashPathEffect::Make(intervals, SK_ARRAY_COUNT(intervals), 2.5f));
137 SkPaint dashed(std::move(paint));
138 SkDebugf("path effect unique: %s\n", dashed.getPathEffect()->unique() ? "true" : "false");
139
140 #StdOut
141 path effect unique: true
142 ##
143 ##
144
145##
146
147# ------------------------------------------------------------------------------
148
149#Method void reset()
Cary Clarka90ea222018-10-16 10:30:28 -0400150#In Constructors
Cary Clarkab2621d2018-01-30 10:08:57 -0500151#Line # sets to default values ##
Cary Clark09d80c02018-10-31 12:14:03 -0400152#Populate
Cary Clark8032b982017-07-28 11:04:54 -0400153
154#Example
155 SkPaint paint1, paint2;
156 paint1.setColor(SK_ColorRED);
157 paint1.reset();
158 SkDebugf("paint1 %c= paint2", paint1 == paint2 ? '=' : '!');
159
160 #StdOut
161 paint1 == paint2
162 ##
163##
164
165##
166
Cary Clark8032b982017-07-28 11:04:54 -0400167# ------------------------------------------------------------------------------
Cary Clark8032b982017-07-28 11:04:54 -0400168
169#Method ~SkPaint()
Cary Clarkab2621d2018-01-30 10:08:57 -0500170#Line # decreases Reference_Count of owned objects ##
Cary Clark09d80c02018-10-31 12:14:03 -0400171#Populate
Cary Clark8032b982017-07-28 11:04:54 -0400172
Herb Derbyfcac00f2018-05-01 11:57:56 -0400173#NoExample
Cary Clark8032b982017-07-28 11:04:54 -0400174##
175
176##
177
Cary Clark08895c42018-02-01 09:37:32 -0500178
Cary Clark8032b982017-07-28 11:04:54 -0400179# ------------------------------------------------------------------------------
Cary Clark61313f32018-10-08 14:57:48 -0400180
Cary Clark08895c42018-02-01 09:37:32 -0500181#Subtopic Management
182#Line # paint copying, moving, comparing ##
Cary Clarka90ea222018-10-16 10:30:28 -0400183##
Cary Clark8032b982017-07-28 11:04:54 -0400184
185#Method SkPaint& operator=(const SkPaint& paint)
Cary Clarkab2621d2018-01-30 10:08:57 -0500186#In Management
187#Line # makes a shallow copy ##
Cary Clark09d80c02018-10-31 12:14:03 -0400188#Populate
Cary Clark8032b982017-07-28 11:04:54 -0400189
190#Example
191 SkPaint paint1, paint2;
192 paint1.setColor(SK_ColorRED);
193 paint2 = paint1;
194 SkDebugf("SK_ColorRED %c= paint1.getColor()\n", SK_ColorRED == paint1.getColor() ? '=' : '!');
195 SkDebugf("SK_ColorRED %c= paint2.getColor()\n", SK_ColorRED == paint2.getColor() ? '=' : '!');
196
197 #StdOut
198 SK_ColorRED == paint1.getColor()
199 SK_ColorRED == paint2.getColor()
200 ##
201##
202
203##
204
205# ------------------------------------------------------------------------------
206
207#Method SkPaint& operator=(SkPaint&& paint)
Cary Clarkab2621d2018-01-30 10:08:57 -0500208#In Management
209#Line # moves paint without copying it ##
Cary Clark09d80c02018-10-31 12:14:03 -0400210#Populate
Cary Clark8032b982017-07-28 11:04:54 -0400211
212#Example
213 SkPaint paint1, paint2;
214 paint1.setColor(SK_ColorRED);
215 paint2 = std::move(paint1);
216 SkDebugf("SK_ColorRED == paint2.getColor()\n", SK_ColorRED == paint2.getColor() ? '=' : '!');
217
218 #StdOut
219 SK_ColorRED == paint2.getColor()
220 ##
221##
222
223##
224
225# ------------------------------------------------------------------------------
226
227#Method bool operator==(const SkPaint& a, const SkPaint& b)
Cary Clarkab2621d2018-01-30 10:08:57 -0500228#Line # compares paints for equality ##
Cary Clark09d80c02018-10-31 12:14:03 -0400229#Populate
Cary Clark8032b982017-07-28 11:04:54 -0400230
Cary Clark09d80c02018-10-31 12:14:03 -0400231#Example
Cary Clark8032b982017-07-28 11:04:54 -0400232 SkPaint paint1, paint2;
233 paint1.setColor(SK_ColorRED);
234 paint2.setColor(0xFFFF0000);
235 SkDebugf("paint1 %c= paint2\n", paint1 == paint2 ? '=' : '!');
236 float intervals[] = { 5, 5 };
237 paint1.setPathEffect(SkDashPathEffect::Make(intervals, 2, 2.5f));
238 paint2.setPathEffect(SkDashPathEffect::Make(intervals, 2, 2.5f));
239 SkDebugf("paint1 %c= paint2\n", paint1 == paint2 ? '=' : '!');
240
241 #StdOut
242 paint1 == paint2
243 paint1 != paint2
244 ##
245 ##
Cary Clark06c20f32018-03-20 15:53:27 -0400246#SeeAlso operator!=(const SkPaint& a, const SkPaint& b)
Cary Clark8032b982017-07-28 11:04:54 -0400247##
248
249# ------------------------------------------------------------------------------
250
251#Method bool operator!=(const SkPaint& a, const SkPaint& b)
Cary Clarkab2621d2018-01-30 10:08:57 -0500252#Line # compares paints for inequality ##
Cary Clark09d80c02018-10-31 12:14:03 -0400253#Populate
Cary Clark8032b982017-07-28 11:04:54 -0400254
255#Example
256 SkPaint paint1, paint2;
257 paint1.setColor(SK_ColorRED);
258 paint2.setColor(0xFFFF0000);
259 SkDebugf("paint1 %c= paint2\n", paint1 == paint2 ? '=' : '!');
260 SkDebugf("paint1 %c= paint2\n", paint1 != paint2 ? '!' : '=');
261
262 #StdOut
263 paint1 == paint2
264 paint1 == paint2
265 ##
266##
Cary Clark06c20f32018-03-20 15:53:27 -0400267#SeeAlso operator==(const SkPaint& a, const SkPaint& b)
Cary Clark8032b982017-07-28 11:04:54 -0400268##
269
270# ------------------------------------------------------------------------------
271
272#Method uint32_t getHash() const
Cary Clarkab2621d2018-01-30 10:08:57 -0500273#In Management
274#Line # returns a shallow hash for equality checks ##
Cary Clark09d80c02018-10-31 12:14:03 -0400275#Populate
Cary Clark8032b982017-07-28 11:04:54 -0400276
277#Example
278 SkPaint paint1, paint2;
279 paint1.setColor(SK_ColorRED);
280 paint2.setColor(0xFFFF0000);
281 SkDebugf("paint1 %c= paint2\n", paint1 == paint2 ? '=' : '!');
282 SkDebugf("paint1.getHash() %c= paint2.getHash()\n",
283 paint1.getHash() == paint2.getHash() ? '=' : '!');
284
285 #StdOut
286 paint1 == paint2
287 paint1.getHash() == paint2.getHash()
288 ##
289##
290
291##
292
Cary Clark8032b982017-07-28 11:04:54 -0400293# ------------------------------------------------------------------------------
Cary Clark61313f32018-10-08 14:57:48 -0400294
Cary Clark08895c42018-02-01 09:37:32 -0500295#Subtopic Hinting
296#Line # glyph outline adjustment ##
Cary Clarka90ea222018-10-16 10:30:28 -0400297##
Cary Clark8032b982017-07-28 11:04:54 -0400298
Cary Clark8cc4cdc2018-11-09 23:16:58 -0500299#Enum Hinting
300#Line # level of glyph outline adjustment ##
301
302#Code
Cary Clark09d80c02018-10-31 12:14:03 -0400303#Populate
Cary Clark8cc4cdc2018-11-09 23:16:58 -0500304##
Cary Clark8032b982017-07-28 11:04:54 -0400305
Cary Clark8cc4cdc2018-11-09 23:16:58 -0500306#Const kNo_Hinting 0
307#Deprecated
308##
309#Const kSlight_Hinting 1
310#Deprecated
311##
312#Const kNormal_Hinting 2
313#Deprecated
314##
315#Const kFull_Hinting 3
316#Deprecated
317##
Cary Clark8032b982017-07-28 11:04:54 -0400318
Cary Clark8032b982017-07-28 11:04:54 -0400319##
320
Cary Clark11407e52018-11-05 21:26:13 -0500321#Method void setHinting(SkFontHinting hintingLevel)
Cary Clarkab2621d2018-01-30 10:08:57 -0500322#In Hinting
323#Line # sets Hinting, glyph outline adjustment level ##
Cary Clark11407e52018-11-05 21:26:13 -0500324#Populate
Cary Clark8032b982017-07-28 11:04:54 -0400325
Cary Clark11407e52018-11-05 21:26:13 -0500326 #Example
327 SkPaint paint1, paint2;
328 paint2.setHinting(kNormal_SkFontHinting);
329 SkDebugf("paint1 %c= paint2\n", paint1 == paint2 ? '=' : ':');
Cary Clark8032b982017-07-28 11:04:54 -0400330
Cary Clark11407e52018-11-05 21:26:13 -0500331 #StdOut
332 paint1 == paint2
333 ##
334 ##
335##
336
Cary Clark8cc4cdc2018-11-09 23:16:58 -0500337#Method Hinting getHinting() const
338#In Hinting
339#Line # returns Hinting, glyph outline adjustment level ##
340#Populate
341#NoExample
342##
343##
344
345#Method void setHinting(Hinting h)
346#In Hinting
347#Line # returns Hinting, glyph outline adjustment level ##
348#Populate
349#NoExample
350##
351##
352
353# Disable for now
354#ToDo no spelling errors
355###$ block comment
356
357#Method SkFontHinting getHinting() const
358#In Hinting
359#Line # returns Hinting, glyph outline adjustment level ##
360#Populate
361
362 #Example
363 SkPaint paint;
364 SkDebugf("SkFontHinting::kNormal %c= paint.getHinting()\n",
365 SkFontHinting::kNormal == paint.getHinting() ? '=' : ':');
366
367 #StdOut
368 SkFontHinting::kNormal == paint.getHinting()
369 ##
370 ##
371##
372
373$$$# end of block comment
374#ToDo ##
375
Cary Clark8032b982017-07-28 11:04:54 -0400376# ------------------------------------------------------------------------------
Cary Clark08895c42018-02-01 09:37:32 -0500377#Subtopic Flags
378#Line # attributes represented by single bits ##
Cary Clarka90ea222018-10-16 10:30:28 -0400379##
Cary Clark8032b982017-07-28 11:04:54 -0400380
381#Enum Flags
Cary Clark08895c42018-02-01 09:37:32 -0500382#Line # values described by bits and masks ##
Cary Clark8032b982017-07-28 11:04:54 -0400383
384#Code
Cary Clarka90ea222018-10-16 10:30:28 -0400385#Populate
Cary Clark8032b982017-07-28 11:04:54 -0400386##
387
388The bit values stored in Flags.
389The default value for Flags, normally zero, can be changed at compile time
390with a custom definition of SkPaintDefaults_Flags.
391All flags can be read and written explicitly; Flags allows manipulating
392multiple settings at once.
393
Herb Derbyfcac00f2018-05-01 11:57:56 -0400394 #Const kAntiAlias_Flag 0x0001
Cary Clarkffb3d682018-05-17 12:17:28 -0400395 #Line # mask for setting Anti_Alias ##
Cary Clark8032b982017-07-28 11:04:54 -0400396 ##
397 #Const kDither_Flag 0x0004
Cary Clark682c58d2018-05-16 07:07:07 -0400398 #Line # mask for setting Dither ##
Cary Clark8032b982017-07-28 11:04:54 -0400399 ##
Cary Clark8032b982017-07-28 11:04:54 -0400400 #Const kFakeBoldText_Flag 0x0020
Cary Clark682c58d2018-05-16 07:07:07 -0400401 #Line # mask for setting Fake_Bold ##
Cary Clark8032b982017-07-28 11:04:54 -0400402 ##
403 #Const kLinearText_Flag 0x0040
Cary Clark682c58d2018-05-16 07:07:07 -0400404 #Line # mask for setting Linear_Text ##
Cary Clark8032b982017-07-28 11:04:54 -0400405 ##
406 #Const kSubpixelText_Flag 0x0080
Cary Clark682c58d2018-05-16 07:07:07 -0400407 #Line # mask for setting Subpixel_Text ##
Cary Clark8032b982017-07-28 11:04:54 -0400408 ##
Cary Clark8032b982017-07-28 11:04:54 -0400409 #Const kLCDRenderText_Flag 0x0200
Cary Clark682c58d2018-05-16 07:07:07 -0400410 #Line # mask for setting LCD_Text ##
Cary Clark8032b982017-07-28 11:04:54 -0400411 ##
412 #Const kEmbeddedBitmapText_Flag 0x0400
Cary Clark682c58d2018-05-16 07:07:07 -0400413 #Line # mask for setting Font_Embedded_Bitmaps ##
Cary Clark8032b982017-07-28 11:04:54 -0400414 ##
415 #Const kAutoHinting_Flag 0x0800
Cary Clark682c58d2018-05-16 07:07:07 -0400416 #Line # mask for setting Automatic_Hinting ##
Cary Clark8032b982017-07-28 11:04:54 -0400417 ##
Cary Clark8032b982017-07-28 11:04:54 -0400418 #Const kAllFlags 0xFFFF
Cary Clark682c58d2018-05-16 07:07:07 -0400419 #Line # mask of all Flags ##
Cary Clark8032b982017-07-28 11:04:54 -0400420 mask of all Flags, including private flags and flags reserved for future use
421 ##
422
423Flags default to all flags clear, disabling the associated feature.
424
425#Enum ##
426
427#Enum ReserveFlags
Cary Clark4855f782018-02-06 09:41:53 -0500428#Deprecated soon
Cary Clark8032b982017-07-28 11:04:54 -0400429
Cary Clark4855f782018-02-06 09:41:53 -0500430Only valid for Android framework.
Cary Clark8032b982017-07-28 11:04:54 -0400431
432#Code
Cary Clarka90ea222018-10-16 10:30:28 -0400433#Populate
Cary Clark8032b982017-07-28 11:04:54 -0400434##
435
Cary Clark4855f782018-02-06 09:41:53 -0500436#Const kUnderlineText_ReserveFlag 0x0008
437#Deprecated soon
438##
439#Const kStrikeThruText_ReserveFlag 0x0010
440#Deprecated soon
441##
442##
Cary Clark8032b982017-07-28 11:04:54 -0400443
444#Method uint32_t getFlags() const
Cary Clarkab2621d2018-01-30 10:08:57 -0500445#In Flags
446#Line # returns Flags stored in a bit field ##
Cary Clark09d80c02018-10-31 12:14:03 -0400447#Populate
Cary Clark8032b982017-07-28 11:04:54 -0400448
449#Example
450 SkPaint paint;
451 paint.setAntiAlias(true);
452 SkDebugf("(SkPaint::kAntiAlias_Flag & paint.getFlags()) %c= 0\n",
453 SkPaint::kAntiAlias_Flag & paint.getFlags() ? '!' : '=');
454
455 #StdOut
456 (SkPaint::kAntiAlias_Flag & paint.getFlags()) != 0
457 ##
458##
459
460##
461
462#Method void setFlags(uint32_t flags)
Cary Clarkab2621d2018-01-30 10:08:57 -0500463#In Flags
464#Line # sets multiple Flags in a bit field ##
Cary Clark09d80c02018-10-31 12:14:03 -0400465#Populate
Cary Clark8032b982017-07-28 11:04:54 -0400466
467#Example
468 SkPaint paint;
469 paint.setFlags((uint32_t) (SkPaint::kAntiAlias_Flag | SkPaint::kDither_Flag));
470 SkDebugf("paint.isAntiAlias()\n", paint.isAntiAlias() ? '!' : '=');
471 SkDebugf("paint.isDither()\n", paint.isDither() ? '!' : '=');
472
473 #StdOut
474 paint.isAntiAlias()
475 paint.isDither()
476 ##
477##
478
479##
480
Cary Clark8032b982017-07-28 11:04:54 -0400481# ------------------------------------------------------------------------------
Cary Clarkffb3d682018-05-17 12:17:28 -0400482#Subtopic Anti_Alias
483#Alias Anti_Alias
Cary Clark137b8742018-05-30 09:21:49 -0400484#Substitute anti-alias
485##
Cary Clarkffb3d682018-05-17 12:17:28 -0400486#Alias Anti_Aliased
Cary Clark137b8742018-05-30 09:21:49 -0400487#Substitute anti-aliased
488##
Cary Clarkffb3d682018-05-17 12:17:28 -0400489#Alias Anti_Aliasing
Cary Clark137b8742018-05-30 09:21:49 -0400490#Substitute anti-aliasing
491##
Cary Clark4855f782018-02-06 09:41:53 -0500492#In Related_Function
Cary Clarkab2621d2018-01-30 10:08:57 -0500493#Line # approximating coverage with transparency ##
Cary Clark8032b982017-07-28 11:04:54 -0400494
Cary Clarkffb3d682018-05-17 12:17:28 -0400495Anti_Alias drawing approximates partial pixel coverage with transparency.
Cary Clark8032b982017-07-28 11:04:54 -0400496If kAntiAlias_Flag is clear, pixel centers contained by the shape edge are drawn opaque.
497If kAntiAlias_Flag is set, pixels are drawn with Color_Alpha equal to their coverage.
498
Herb Derbyfcac00f2018-05-01 11:57:56 -0400499The rule for Aliased pixels is inconsistent across platforms. A shape edge
Cary Clark8032b982017-07-28 11:04:54 -0400500passing through the pixel center may, but is not required to, draw the pixel.
501
Cary Clarkce101242017-09-01 15:51:02 -0400502Raster_Engine draws Aliased pixels whose centers are on or to the right of the start of an
Cary Clark8032b982017-07-28 11:04:54 -0400503active Path edge, and whose center is to the left of the end of the active Path edge.
504
505#ToDo add illustration of raster pixels ##
506
Cary Clarkffb3d682018-05-17 12:17:28 -0400507A platform may only support Anti_Aliased drawing. Some GPU-backed platforms use
508Supersampling to Anti_Alias all drawing, and have no mechanism to selectively
Cary Clarkce101242017-09-01 15:51:02 -0400509Alias.
Cary Clark8032b982017-07-28 11:04:54 -0400510
Cary Clarkffb3d682018-05-17 12:17:28 -0400511The amount of coverage computed for Anti_Aliased pixels also varies across platforms.
Cary Clark8032b982017-07-28 11:04:54 -0400512
Cary Clarkffb3d682018-05-17 12:17:28 -0400513Anti_Alias is disabled by default.
514Anti_Alias can be enabled by default by setting SkPaintDefaults_Flags to kAntiAlias_Flag
Cary Clark8032b982017-07-28 11:04:54 -0400515at compile time.
516
Cary Clarkab2621d2018-01-30 10:08:57 -0500517#Example
Cary Clark8032b982017-07-28 11:04:54 -0400518 #Width 512
519 #Description
520 A red line is drawn with transparency on the edges to make it look smoother.
521 A blue line draws only where the pixel centers are contained.
Cary Clarkce101242017-09-01 15:51:02 -0400522 The lines are drawn into Bitmap, then drawn magnified to make the
523 Aliasing easier to see.
Cary Clark8032b982017-07-28 11:04:54 -0400524 ##
525
526 void draw(SkCanvas* canvas) {
527 SkBitmap bitmap;
528 bitmap.allocN32Pixels(50, 50);
529 SkCanvas offscreen(bitmap);
530 SkPaint paint;
531 paint.setStyle(SkPaint::kStroke_Style);
532 paint.setStrokeWidth(10);
533 for (bool antialias : { false, true }) {
534 paint.setColor(antialias ? SK_ColorRED : SK_ColorBLUE);
535 paint.setAntiAlias(antialias);
536 bitmap.eraseColor(0);
537 offscreen.drawLine(5, 5, 15, 30, paint);
538 canvas->drawLine(5, 5, 15, 30, paint);
539 canvas->save();
540 canvas->scale(10, 10);
541 canvas->drawBitmap(bitmap, antialias ? 12 : 0, 0);
542 canvas->restore();
543 canvas->translate(15, 0);
544 }
545 }
Cary Clarkab2621d2018-01-30 10:08:57 -0500546##
Cary Clarka90ea222018-10-16 10:30:28 -0400547#Subtopic Anti_Alias ##
Cary Clark8032b982017-07-28 11:04:54 -0400548
549#Method bool isAntiAlias() const
Cary Clark78de7512018-02-07 07:27:09 -0500550#In Anti_alias
Cary Clarkffb3d682018-05-17 12:17:28 -0400551#Line # returns true if Anti_Alias is set ##
Cary Clark09d80c02018-10-31 12:14:03 -0400552#Populate
Cary Clark8032b982017-07-28 11:04:54 -0400553
Cary Clark09d80c02018-10-31 12:14:03 -0400554#Example
Cary Clark8032b982017-07-28 11:04:54 -0400555 SkPaint paint;
556 SkDebugf("paint.isAntiAlias() %c= !!(paint.getFlags() & SkPaint::kAntiAlias_Flag)\n",
557 paint.isAntiAlias() == !!(paint.getFlags() & SkPaint::kAntiAlias_Flag) ? '=' : '!');
558 paint.setAntiAlias(true);
559 SkDebugf("paint.isAntiAlias() %c= !!(paint.getFlags() & SkPaint::kAntiAlias_Flag)\n",
560 paint.isAntiAlias() == !!(paint.getFlags() & SkPaint::kAntiAlias_Flag) ? '=' : '!');
561
562 #StdOut
563 paint.isAntiAlias() == !!(paint.getFlags() & SkPaint::kAntiAlias_Flag)
564 paint.isAntiAlias() == !!(paint.getFlags() & SkPaint::kAntiAlias_Flag)
565 ##
566 ##
567##
568
569#Method void setAntiAlias(bool aa)
Cary Clark78de7512018-02-07 07:27:09 -0500570#In Anti_alias
Cary Clarkffb3d682018-05-17 12:17:28 -0400571#Line # sets or clears Anti_Alias ##
Cary Clark09d80c02018-10-31 12:14:03 -0400572#Populate
Cary Clark8032b982017-07-28 11:04:54 -0400573
Cary Clark09d80c02018-10-31 12:14:03 -0400574#Example
Cary Clark8032b982017-07-28 11:04:54 -0400575 SkPaint paint1, paint2;
576 paint1.setAntiAlias(true);
577 paint2.setFlags(paint2.getFlags() | SkPaint::kAntiAlias_Flag);
578 SkDebugf("paint1 %c= paint2\n", paint1 == paint2 ? '=' : '!');
579
580 #StdOut
581 paint1 == paint2
582 ##
583 ##
584
585##
586
Cary Clark8032b982017-07-28 11:04:54 -0400587# ------------------------------------------------------------------------------
Cary Clark08895c42018-02-01 09:37:32 -0500588#Subtopic Dither
589#Line # distributing color error ##
Cary Clark8032b982017-07-28 11:04:54 -0400590
Herb Derbyfcac00f2018-05-01 11:57:56 -0400591Dither increases fidelity by adjusting the color of adjacent pixels.
Cary Clark8032b982017-07-28 11:04:54 -0400592This can help to smooth color transitions and reducing banding in gradients.
593Dithering lessens visible banding from kRGB_565_SkColorType
Herb Derbyfcac00f2018-05-01 11:57:56 -0400594and kRGBA_8888_SkColorType gradients,
Cary Clark8032b982017-07-28 11:04:54 -0400595and improves rendering into a kRGB_565_SkColorType Surface.
596
597Dithering is always enabled for linear gradients drawing into
598kRGB_565_SkColorType Surface and kRGBA_8888_SkColorType Surface.
599Dither cannot be enabled for kAlpha_8_SkColorType Surface and
600kRGBA_F16_SkColorType Surface.
601
602Dither is disabled by default.
603Dither can be enabled by default by setting SkPaintDefaults_Flags to kDither_Flag
604at compile time.
605
Cary Clark2be81cf2018-09-13 12:04:30 -0400606Some platform implementations may ignore dithering. Set #Formula # SK_IGNORE_GPU_DITHER ##
Cary Clark8032b982017-07-28 11:04:54 -0400607to ignore Dither on GPU_Surface.
608
609#Example
Herb Derbyfcac00f2018-05-01 11:57:56 -0400610#Description
Cary Clark8032b982017-07-28 11:04:54 -0400611Dithering in the bottom half more closely approximates the requested color by
612alternating nearby colors from pixel to pixel.
613##
614void draw(SkCanvas* canvas) {
615 SkBitmap bm16;
616 bm16.allocPixels(SkImageInfo::Make(32, 32, kRGB_565_SkColorType, kOpaque_SkAlphaType));
617 SkCanvas c16(bm16);
618 SkPaint colorPaint;
619 for (auto dither : { false, true } ) {
620 colorPaint.setDither(dither);
621 for (auto colors : { 0xFF333333, 0xFF666666, 0xFF999999, 0xFFCCCCCC } ) {
622 for (auto mask : { 0xFFFF0000, 0xFF00FF00, 0xFF0000FF, 0xFFFFFFFF } ) {
623 colorPaint.setColor(colors & mask);
624 c16.drawRect({0, 0, 8, 4}, colorPaint);
625 c16.translate(8, 0);
626 }
627 c16.translate(-32, 4);
628 }
629 }
630 canvas->scale(8, 8);
631 canvas->drawBitmap(bm16, 0, 0);
632}
633##
634
635#Example
Herb Derbyfcac00f2018-05-01 11:57:56 -0400636#Description
Cary Clark8032b982017-07-28 11:04:54 -0400637Dithering introduces subtle adjustments to color to smooth gradients.
638Drawing the gradient repeatedly with SkBlendMode::kPlus exaggerates the
639dither, making it easier to see.
640##
641void draw(SkCanvas* canvas) {
642 canvas->clear(0);
643 SkBitmap bm32;
644 bm32.allocPixels(SkImageInfo::Make(20, 10, kN32_SkColorType, kPremul_SkAlphaType));
645 SkCanvas c32(bm32);
646 SkPoint points[] = {{0, 0}, {20, 0}};
647 SkColor colors[] = {0xFF334455, 0xFF662211 };
648 SkPaint paint;
649 paint.setShader(SkGradientShader::MakeLinear(
650 points, colors, nullptr, SK_ARRAY_COUNT(colors),
651 SkShader::kClamp_TileMode, 0, nullptr));
652 paint.setDither(true);
653 c32.drawPaint(paint);
654 canvas->scale(12, 12);
655 canvas->drawBitmap(bm32, 0, 0);
656 paint.setBlendMode(SkBlendMode::kPlus);
657 canvas->drawBitmap(bm32, 0, 11, &paint);
658 canvas->drawBitmap(bm32, 0, 11, &paint);
659 canvas->drawBitmap(bm32, 0, 11, &paint);
660}
661##
Cary Clarka90ea222018-10-16 10:30:28 -0400662#SeeAlso Gradient kRGB_565_SkColorType
663#Subtopic Dither ##
Cary Clark8032b982017-07-28 11:04:54 -0400664
665#Method bool isDither() const
Cary Clarkab2621d2018-01-30 10:08:57 -0500666#In Dither
667#Line # returns true if Dither is set ##
Cary Clark09d80c02018-10-31 12:14:03 -0400668#Populate
Herb Derbyfcac00f2018-05-01 11:57:56 -0400669
Cary Clark09d80c02018-10-31 12:14:03 -0400670#Example
Cary Clark8032b982017-07-28 11:04:54 -0400671 SkPaint paint;
672 SkDebugf("paint.isDither() %c= !!(paint.getFlags() & SkPaint::kDither_Flag)\n",
673 paint.isDither() == !!(paint.getFlags() & SkPaint::kDither_Flag) ? '=' : '!');
674 paint.setDither(true);
675 SkDebugf("paint.isDither() %c= !!(paint.getFlags() & SkPaint::kDither_Flag)\n",
676 paint.isDither() == !!(paint.getFlags() & SkPaint::kDither_Flag) ? '=' : '!');
677
678 #StdOut
679 paint.isDither() == !!(paint.getFlags() & SkPaint::kDither_Flag)
680 paint.isDither() == !!(paint.getFlags() & SkPaint::kDither_Flag)
681 ##
682 ##
683
684##
685
686#Method void setDither(bool dither)
Cary Clarkab2621d2018-01-30 10:08:57 -0500687#In Dither
688#Line # sets or clears Dither ##
Cary Clark09d80c02018-10-31 12:14:03 -0400689#Populate
Cary Clark8032b982017-07-28 11:04:54 -0400690
Cary Clark09d80c02018-10-31 12:14:03 -0400691#Example
Cary Clark8032b982017-07-28 11:04:54 -0400692 SkPaint paint1, paint2;
693 paint1.setDither(true);
694 paint2.setFlags(paint2.getFlags() | SkPaint::kDither_Flag);
695 SkDebugf("paint1 %c= paint2\n", paint1 == paint2 ? '=' : '!');
696
697 #StdOut
698 paint1 == paint2
699 ##
700 ##
701
702 #SeeAlso kRGB_565_SkColorType
703
704##
705
Cary Clark8032b982017-07-28 11:04:54 -0400706# ------------------------------------------------------------------------------
Cary Clark08895c42018-02-01 09:37:32 -0500707#Subtopic Device_Text
708#Line # increase precision of glyph position ##
Cary Clark8032b982017-07-28 11:04:54 -0400709
710LCD_Text and Subpixel_Text increase the precision of glyph position.
711
Cary Clarkffb3d682018-05-17 12:17:28 -0400712When set, Flags kLCDRenderText_Flag takes advantage of the organization of RGB stripes that
Cary Clark8032b982017-07-28 11:04:54 -0400713create a color, and relies
Cary Clarkce101242017-09-01 15:51:02 -0400714on the small size of the stripe and visual perception to make the color fringing imperceptible.
Cary Clark8032b982017-07-28 11:04:54 -0400715LCD_Text can be enabled on devices that orient stripes horizontally or vertically, and that order
Cary Clarkffb3d682018-05-17 12:17:28 -0400716the color components as RGB or BGR.
Cary Clark8032b982017-07-28 11:04:54 -0400717
Herb Derbyfcac00f2018-05-01 11:57:56 -0400718Flags kSubpixelText_Flag uses the pixel transparency to represent a fractional offset.
Cary Clark8032b982017-07-28 11:04:54 -0400719As the opaqueness
720of the color increases, the edge of the glyph appears to move towards the outside of the pixel.
721
722Either or both techniques can be enabled.
723kLCDRenderText_Flag and kSubpixelText_Flag are clear by default.
Herb Derbyfcac00f2018-05-01 11:57:56 -0400724LCD_Text or Subpixel_Text can be enabled by default by setting SkPaintDefaults_Flags to
Cary Clark8032b982017-07-28 11:04:54 -0400725kLCDRenderText_Flag or kSubpixelText_Flag (or both) at compile time.
726
727#Example
728 #Description
729 Four commas are drawn normally and with combinations of LCD_Text and Subpixel_Text.
Cary Clarkce101242017-09-01 15:51:02 -0400730 When Subpixel_Text is disabled, the comma Glyphs are identical, but not evenly spaced.
731 When Subpixel_Text is enabled, the comma Glyphs are unique, but appear evenly spaced.
Cary Clark8032b982017-07-28 11:04:54 -0400732 ##
733
734 SkBitmap bitmap;
735 bitmap.allocN32Pixels(24, 33);
736 SkCanvas offscreen(bitmap);
737 offscreen.clear(SK_ColorWHITE);
738 SkPaint paint;
739 paint.setAntiAlias(true);
740 paint.setTextSize(20);
741 for (bool lcd : { false, true }) {
742 paint.setLCDRenderText(lcd);
743 for (bool subpixel : { false, true }) {
744 paint.setSubpixelText(subpixel);
745 offscreen.drawString(",,,,", 0, 4, paint);
746 offscreen.translate(0, 7);
747 }
748 }
749 canvas->drawBitmap(bitmap, 4, 12);
750 canvas->scale(9, 9);
751 canvas->drawBitmap(bitmap, 4, -1);
752##
Cary Clark08895c42018-02-01 09:37:32 -0500753#Subtopic Device_Text ##
Cary Clark8032b982017-07-28 11:04:54 -0400754
755#Subtopic Linear_Text
Cary Clark137b8742018-05-30 09:21:49 -0400756#Alias Linear_Text ##
Cary Clark08895c42018-02-01 09:37:32 -0500757#Line # selects text rendering as Glyph or Path ##
Cary Clark8032b982017-07-28 11:04:54 -0400758
759Linear_Text selects whether text is rendered as a Glyph or as a Path.
Cary Clark4a23bbf2018-11-08 16:00:33 -0500760If kLinearText_Flag is set, it has the same effect as setting Hinting to SkFontHinting::kNormal.
761If kLinearText_Flag is clear, it is the same as setting Hinting to SkFontHinting::kNone.
Cary Clarka90ea222018-10-16 10:30:28 -0400762#Subtopic Linear_Text ##
Cary Clark8032b982017-07-28 11:04:54 -0400763
764#Method bool isLinearText() const
Cary Clarkab2621d2018-01-30 10:08:57 -0500765#In Linear_Text
Cary Clarka90ea222018-10-16 10:30:28 -0400766#Line # returns true if text is converted to Path ##
Cary Clark09d80c02018-10-31 12:14:03 -0400767#Populate
Cary Clark8032b982017-07-28 11:04:54 -0400768
Cary Clark09d80c02018-10-31 12:14:03 -0400769#Example
Cary Clark8032b982017-07-28 11:04:54 -0400770 #Height 128
771 void draw(SkCanvas* canvas) {
772 SkPaint paint;
773 paint.setAntiAlias(true);
774 const char testStr[] = "xxxx xxxx";
775 for (auto linearText : { false, true } ) {
776 paint.setLinearText(linearText);
777 paint.setTextSize(24);
778 canvas->drawString(paint.isLinearText() ? "linear" : "hinted", 128, 30, paint);
779 for (SkScalar textSize = 8; textSize < 30; textSize *= 1.22f) {
780 paint.setTextSize(textSize);
781 canvas->translate(0, textSize);
782 canvas->drawString(testStr, 10, 0, paint);
783 }
784 }
785 }
786 ##
787
788 #SeeAlso setLinearText Hinting
789##
790
791#Method void setLinearText(bool linearText)
Cary Clarkab2621d2018-01-30 10:08:57 -0500792#In Linear_Text
Cary Clarka90ea222018-10-16 10:30:28 -0400793#Line # converts to Path before draw or measure ##
Cary Clark09d80c02018-10-31 12:14:03 -0400794#Populate
Cary Clark8032b982017-07-28 11:04:54 -0400795
Cary Clark09d80c02018-10-31 12:14:03 -0400796#Example
Cary Clark8032b982017-07-28 11:04:54 -0400797 #Height 128
798 void draw(SkCanvas* canvas) {
799 SkPaint paint;
800 paint.setAntiAlias(true);
801 const char testStr[] = "abcd efgh";
802 for (int textSize : { 12, 24 } ) {
803 paint.setTextSize(textSize);
804 for (auto linearText : { false, true } ) {
805 paint.setLinearText(linearText);
806 SkString width;
807 width.appendScalar(paint.measureText(testStr, SK_ARRAY_COUNT(testStr), nullptr));
808 canvas->translate(0, textSize + 4);
809 canvas->drawString(testStr, 10, 0, paint);
810 canvas->drawString(width, 128, 0, paint);
811 }
812 }
Herb Derbyfcac00f2018-05-01 11:57:56 -0400813 }
Cary Clark8032b982017-07-28 11:04:54 -0400814 ##
815
816 #SeeAlso isLinearText Hinting
817##
818
Cary Clark8032b982017-07-28 11:04:54 -0400819#Subtopic Subpixel_Text
Cary Clark137b8742018-05-30 09:21:49 -0400820#Alias Subpixel_Text ##
Cary Clark08895c42018-02-01 09:37:32 -0500821#Line # uses pixel transparency to represent fractional offset ##
Cary Clark8032b982017-07-28 11:04:54 -0400822
Herb Derbyfcac00f2018-05-01 11:57:56 -0400823Flags kSubpixelText_Flag uses the pixel transparency to represent a fractional offset.
Cary Clark8032b982017-07-28 11:04:54 -0400824As the opaqueness
825of the color increases, the edge of the glyph appears to move towards the outside of the pixel.
Cary Clarka90ea222018-10-16 10:30:28 -0400826#Subtopic Subpixel_Text ##
Cary Clark8032b982017-07-28 11:04:54 -0400827
828#Method bool isSubpixelText() const
Cary Clarkab2621d2018-01-30 10:08:57 -0500829#In Subpixel_Text
830#Line # returns true if Subpixel_Text is set ##
Cary Clark09d80c02018-10-31 12:14:03 -0400831#Populate
Cary Clark8032b982017-07-28 11:04:54 -0400832
Cary Clark09d80c02018-10-31 12:14:03 -0400833#Example
Cary Clark8032b982017-07-28 11:04:54 -0400834SkPaint paint;
835SkDebugf("paint.isSubpixelText() %c= !!(paint.getFlags() & SkPaint::kSubpixelText_Flag)\n",
836 paint.isSubpixelText() == !!(paint.getFlags() & SkPaint::kSubpixelText_Flag) ? '=' : '!');
837paint.setSubpixelText(true);
838SkDebugf("paint.isSubpixelText() %c= !!(paint.getFlags() & SkPaint::kSubpixelText_Flag)\n",
839 paint.isSubpixelText() == !!(paint.getFlags() & SkPaint::kSubpixelText_Flag) ? '=' : '!');
840
841 #StdOut
842 paint.isSubpixelText() == !!(paint.getFlags() & SkPaint::kSubpixelText_Flag)
843 paint.isSubpixelText() == !!(paint.getFlags() & SkPaint::kSubpixelText_Flag)
844 ##
845 ##
846
847##
848
849#Method void setSubpixelText(bool subpixelText)
Cary Clarkab2621d2018-01-30 10:08:57 -0500850#In Subpixel_Text
851#Line # sets or clears Subpixel_Text ##
Cary Clark09d80c02018-10-31 12:14:03 -0400852#Populate
Cary Clark8032b982017-07-28 11:04:54 -0400853
Cary Clark09d80c02018-10-31 12:14:03 -0400854#Example
Cary Clark8032b982017-07-28 11:04:54 -0400855 SkPaint paint1, paint2;
856 paint1.setSubpixelText(true);
857 paint2.setFlags(paint2.getFlags() | SkPaint::kSubpixelText_Flag);
858 SkDebugf("paint1 %c= paint2\n", paint1 == paint2 ? '=' : '!');
859
860 #StdOut
861 paint1 == paint2
862 ##
863 ##
864
865##
866
Cary Clark8032b982017-07-28 11:04:54 -0400867#Subtopic LCD_Text
Cary Clarkffb3d682018-05-17 12:17:28 -0400868#Line # text relying on the order of RGB stripes ##
Cary Clark137b8742018-05-30 09:21:49 -0400869
870# make this a top level name, since it is under subtopic Device_Text
871#Alias LCD_Text
872#Substitute LCD text
873##
Cary Clark8032b982017-07-28 11:04:54 -0400874
Cary Clarkffb3d682018-05-17 12:17:28 -0400875When set, Flags kLCDRenderText_Flag takes advantage of the organization of RGB stripes that
Cary Clark8032b982017-07-28 11:04:54 -0400876create a color, and relies
Cary Clarkce101242017-09-01 15:51:02 -0400877on the small size of the stripe and visual perception to make the color fringing imperceptible.
Cary Clark8032b982017-07-28 11:04:54 -0400878LCD_Text can be enabled on devices that orient stripes horizontally or vertically, and that order
Cary Clarkffb3d682018-05-17 12:17:28 -0400879the color components as RGB or BGR.
Cary Clarka90ea222018-10-16 10:30:28 -0400880#Subtopic LCD_Text ##
Cary Clark8032b982017-07-28 11:04:54 -0400881
882#Method bool isLCDRenderText() const
Cary Clarkab2621d2018-01-30 10:08:57 -0500883#In LCD_Text
884#Line # returns true if LCD_Text is set ##
Cary Clark09d80c02018-10-31 12:14:03 -0400885#Populate
Cary Clark8032b982017-07-28 11:04:54 -0400886
Cary Clark09d80c02018-10-31 12:14:03 -0400887#Example
Cary Clark8032b982017-07-28 11:04:54 -0400888SkPaint paint;
889SkDebugf("paint.isLCDRenderText() %c= !!(paint.getFlags() & SkPaint::kLCDRenderText_Flag)\n",
890 paint.isLCDRenderText() == !!(paint.getFlags() & SkPaint::kLCDRenderText_Flag) ? '=' : '!');
891paint.setLCDRenderText(true);
892SkDebugf("paint.isLCDRenderText() %c= !!(paint.getFlags() & SkPaint::kLCDRenderText_Flag)\n",
893 paint.isLCDRenderText() == !!(paint.getFlags() & SkPaint::kLCDRenderText_Flag) ? '=' : '!');
894
895 #StdOut
896 paint.isLCDRenderText() == !!(paint.getFlags() & SkPaint::kLCDRenderText_Flag)
897 paint.isLCDRenderText() == !!(paint.getFlags() & SkPaint::kLCDRenderText_Flag)
898 ##
899 ##
900
901##
902
903#Method void setLCDRenderText(bool lcdText)
Cary Clarkab2621d2018-01-30 10:08:57 -0500904#In LCD_Text
905#Line # sets or clears LCD_Text ##
Cary Clark09d80c02018-10-31 12:14:03 -0400906#Populate
Cary Clark8032b982017-07-28 11:04:54 -0400907
Cary Clark09d80c02018-10-31 12:14:03 -0400908#Example
Cary Clark8032b982017-07-28 11:04:54 -0400909 SkPaint paint1, paint2;
910 paint1.setLCDRenderText(true);
911 paint2.setFlags(paint2.getFlags() | SkPaint::kLCDRenderText_Flag);
912 SkDebugf("paint1 %c= paint2\n", paint1 == paint2 ? '=' : '!');
913
914 #StdOut
915 paint1 == paint2
916 ##
917 ##
918
919
920##
921
Cary Clark8032b982017-07-28 11:04:54 -0400922# ------------------------------------------------------------------------------
Cary Clark08895c42018-02-01 09:37:32 -0500923#Subtopic Font_Embedded_Bitmaps
924#Line # custom sized bitmap Glyphs ##
Cary Clark137b8742018-05-30 09:21:49 -0400925#Alias Font_Embedded_Bitmaps ## # long-winded enough, alias so I don't type Paint_Font_...
Cary Clark8032b982017-07-28 11:04:54 -0400926
Cary Clarkce101242017-09-01 15:51:02 -0400927Font_Embedded_Bitmaps allows selecting custom sized bitmap Glyphs.
Cary Clark8032b982017-07-28 11:04:54 -0400928Flags kEmbeddedBitmapText_Flag when set chooses an embedded bitmap glyph over an outline contained
Herb Derbyfcac00f2018-05-01 11:57:56 -0400929in a font if the platform supports this option.
Cary Clark8032b982017-07-28 11:04:54 -0400930
931FreeType selects the bitmap glyph if available when kEmbeddedBitmapText_Flag is set, and selects
932the outline glyph if kEmbeddedBitmapText_Flag is clear.
933Windows may select the bitmap glyph but is not required to do so.
934OS_X and iOS do not support this option.
935
936Font_Embedded_Bitmaps is disabled by default.
937Font_Embedded_Bitmaps can be enabled by default by setting SkPaintDefaults_Flags to
938kEmbeddedBitmapText_Flag at compile time.
939
940#Example
941 #ToDo image will only output on Ubuntu ... how to handle that in fiddle? ##
942 #Platform !fiddle
943 #Description
Cary Clarkce101242017-09-01 15:51:02 -0400944 The "hintgasp" TrueType font in the Skia resources/fonts directory
945 includes an embedded bitmap Glyph at odd font sizes. This example works
946 on platforms that use FreeType as their Font_Engine.
947 Windows may, but is not required to, return a bitmap glyph if
948 kEmbeddedBitmapText_Flag is set.
Cary Clark8032b982017-07-28 11:04:54 -0400949 ##
950 #Image embeddedbitmap.png
951
952 SkBitmap bitmap;
953 bitmap.allocN32Pixels(30, 15);
954 bitmap.eraseColor(0);
955 SkCanvas offscreen(bitmap);
956 SkPaint paint;
957 paint.setAntiAlias(true);
958 paint.setTextSize(13);
Hal Canary53e5e7d2017-12-08 14:25:14 -0500959 paint.setTypeface(MakeResourceAsTypeface("fonts/hintgasp.ttf"));
Cary Clark8032b982017-07-28 11:04:54 -0400960 for (bool embedded : { false, true}) {
961 paint.setEmbeddedBitmapText(embedded);
962 offscreen.drawString("A", embedded ? 5 : 15, 15, paint);
963 }
964 canvas->drawBitmap(bitmap, 0, 0);
965 canvas->scale(10, 10);
966 canvas->drawBitmap(bitmap, -2, 1);
967##
Cary Clarka90ea222018-10-16 10:30:28 -0400968#Subtopic Font_Embedded_Bitmaps ##
Cary Clark8032b982017-07-28 11:04:54 -0400969
970#Method bool isEmbeddedBitmapText() const
Cary Clarkab2621d2018-01-30 10:08:57 -0500971#In Font_Embedded_Bitmaps
972#Line # returns true if Font_Embedded_Bitmaps is set ##
Cary Clark09d80c02018-10-31 12:14:03 -0400973#Populate
Cary Clark8032b982017-07-28 11:04:54 -0400974
Cary Clark09d80c02018-10-31 12:14:03 -0400975#Example
Cary Clark8032b982017-07-28 11:04:54 -0400976 SkPaint paint;
977 SkDebugf("paint.isEmbeddedBitmapText() %c="
978 " !!(paint.getFlags() & SkPaint::kEmbeddedBitmapText_Flag)\n",
979 paint.isEmbeddedBitmapText() ==
980 !!(paint.getFlags() & SkPaint::kEmbeddedBitmapText_Flag) ? '=' : '!');
981 paint.setEmbeddedBitmapText(true);
982 SkDebugf("paint.isEmbeddedBitmapText() %c="
983 " !!(paint.getFlags() & SkPaint::kEmbeddedBitmapText_Flag)\n",
984 paint.isEmbeddedBitmapText() ==
985 !!(paint.getFlags() & SkPaint::kEmbeddedBitmapText_Flag) ? '=' : '!');
986
987 #StdOut
988 paint.isEmbeddedBitmapText() == !!(paint.getFlags() & SkPaint::kEmbeddedBitmapText_Flag)
989 paint.isEmbeddedBitmapText() == !!(paint.getFlags() & SkPaint::kEmbeddedBitmapText_Flag)
990 ##
991 ##
992
993##
994
995#Method void setEmbeddedBitmapText(bool useEmbeddedBitmapText)
Cary Clarkab2621d2018-01-30 10:08:57 -0500996#In Font_Embedded_Bitmaps
997#Line # sets or clears Font_Embedded_Bitmaps ##
Cary Clark09d80c02018-10-31 12:14:03 -0400998#Populate
Cary Clark8032b982017-07-28 11:04:54 -0400999
Cary Clark09d80c02018-10-31 12:14:03 -04001000#Example
Cary Clark8032b982017-07-28 11:04:54 -04001001 SkPaint paint1, paint2;
1002 paint1.setEmbeddedBitmapText(true);
1003 paint2.setFlags(paint2.getFlags() | SkPaint::kEmbeddedBitmapText_Flag);
1004 SkDebugf("paint1 %c= paint2\n", paint1 == paint2 ? '=' : '!');
1005
1006 #StdOut
1007 paint1 == paint2
1008 ##
1009 ##
1010
1011##
1012
Cary Clark8032b982017-07-28 11:04:54 -04001013# ------------------------------------------------------------------------------
Cary Clark08895c42018-02-01 09:37:32 -05001014#Subtopic Automatic_Hinting
1015#Line # always adjust glyph paths ##
Cary Clark8032b982017-07-28 11:04:54 -04001016#Substitute auto-hinting
1017
Cary Clark4a23bbf2018-11-08 16:00:33 -05001018If Hinting is set to SkFontHinting::kNormal or SkFontHinting::kFull, Automatic_Hinting
Cary Clarkce101242017-09-01 15:51:02 -04001019instructs the Font_Manager to always hint Glyphs.
Cary Clark777eede2018-11-09 16:04:58 -05001020Automatic_Hinting has no effect if Hinting is set to SkFontHinting::kNone or
1021SkFontHinting::kSlight.
Cary Clark8032b982017-07-28 11:04:54 -04001022
1023Automatic_Hinting only affects platforms that use FreeType as the Font_Manager.
Cary Clarka90ea222018-10-16 10:30:28 -04001024#Subtopic Automatic_Hinting ##
Cary Clark8032b982017-07-28 11:04:54 -04001025
1026#Method bool isAutohinted() const
Cary Clarkab2621d2018-01-30 10:08:57 -05001027#In Automatic_Hinting
1028#Line # returns true if Glyphs are always hinted ##
Cary Clark09d80c02018-10-31 12:14:03 -04001029#Populate
Cary Clark8032b982017-07-28 11:04:54 -04001030
Cary Clark09d80c02018-10-31 12:14:03 -04001031#Example
Cary Clark8032b982017-07-28 11:04:54 -04001032 SkPaint paint;
1033 for (auto forceAutoHinting : { false, true} ) {
1034 paint.setAutohinted(forceAutoHinting);
1035 SkDebugf("paint.isAutohinted() %c="
1036 " !!(paint.getFlags() & SkPaint::kAutoHinting_Flag)\n",
1037 paint.isAutohinted() ==
1038 !!(paint.getFlags() & SkPaint::kAutoHinting_Flag) ? '=' : '!');
1039 }
1040 #StdOut
1041 paint.isAutohinted() == !!(paint.getFlags() & SkPaint::kAutoHinting_Flag)
1042 paint.isAutohinted() == !!(paint.getFlags() & SkPaint::kAutoHinting_Flag)
1043 ##
1044 ##
1045
1046 #SeeAlso setAutohinted Hinting
1047
1048##
1049
1050#Method void setAutohinted(bool useAutohinter)
Cary Clarkab2621d2018-01-30 10:08:57 -05001051#In Automatic_Hinting
1052#Line # sets Glyphs to always be hinted ##
Cary Clark09d80c02018-10-31 12:14:03 -04001053#Populate
Cary Clark8032b982017-07-28 11:04:54 -04001054
Cary Clark09d80c02018-10-31 12:14:03 -04001055#Example
Cary Clark8032b982017-07-28 11:04:54 -04001056 void draw(SkCanvas* canvas) {
1057 SkPaint paint;
1058 paint.setAntiAlias(true);
1059 const char testStr[] = "xxxx xxxx";
1060 for (auto forceAutoHinting : { false, true} ) {
1061 paint.setAutohinted(forceAutoHinting);
1062 paint.setTextSize(24);
1063 canvas->drawString(paint.isAutohinted() ? "auto-hinted" : "default", 108, 30, paint);
1064 for (SkScalar textSize = 8; textSize < 30; textSize *= 1.22f) {
1065 paint.setTextSize(textSize);
1066 canvas->translate(0, textSize);
1067 canvas->drawString(testStr, 10, 0, paint);
1068 }
1069 }
1070 }
1071 ##
1072
1073 #SeeAlso isAutohinted Hinting
1074
1075##
1076
Cary Clark8032b982017-07-28 11:04:54 -04001077# ------------------------------------------------------------------------------
Cary Clark8032b982017-07-28 11:04:54 -04001078
Cary Clark08895c42018-02-01 09:37:32 -05001079#Subtopic Fake_Bold
1080#Line # approximate font styles ##
Cary Clark8032b982017-07-28 11:04:54 -04001081
1082Fake_Bold approximates the bold font style accompanying a normal font when a bold font face
1083is not available. Skia does not provide font substitution; it is up to the client to find the
Cary Clarkbc5697d2017-10-04 14:31:33 -04001084bold font face using the platform Font_Manager.
Cary Clark8032b982017-07-28 11:04:54 -04001085
Herb Derbyfcac00f2018-05-01 11:57:56 -04001086Use Text_Skew_X to approximate an italic font style when the italic font face
Cary Clark8032b982017-07-28 11:04:54 -04001087is not available.
1088
Cary Clarkce101242017-09-01 15:51:02 -04001089A FreeType based port may define SK_USE_FREETYPE_EMBOLDEN at compile time to direct
1090the font engine to create the bold Glyphs. Otherwise, the extra bold is computed
Herb Derbyfcac00f2018-05-01 11:57:56 -04001091by increasing the stroke width and setting the Style to kStrokeAndFill_Style as needed.
Cary Clark8032b982017-07-28 11:04:54 -04001092
1093Fake_Bold is disabled by default.
1094
1095#Example
1096#Height 128
1097void draw(SkCanvas* canvas) {
1098 SkPaint paint;
1099 paint.setAntiAlias(true);
1100 paint.setTextSize(40);
1101 canvas->drawString("OjYy_-", 10, 35, paint);
1102 paint.setFakeBoldText(true);
1103 canvas->drawString("OjYy_-", 10, 75, paint);
1104 // create a custom fake bold by varying the stroke width
1105 paint.setFakeBoldText(false);
1106 paint.setStyle(SkPaint::kStrokeAndFill_Style);
1107 paint.setStrokeWidth(40.f / 48);
1108 canvas->drawString("OjYy_-", 10, 115, paint);
1109}
1110##
Cary Clarka90ea222018-10-16 10:30:28 -04001111#Subtopic Fake_Bold ##
Cary Clark8032b982017-07-28 11:04:54 -04001112
1113#Method bool isFakeBoldText() const
Cary Clarkab2621d2018-01-30 10:08:57 -05001114#In Fake_Bold
1115#Line # returns true if Fake_Bold is set ##
Cary Clark09d80c02018-10-31 12:14:03 -04001116#Populate
Cary Clark8032b982017-07-28 11:04:54 -04001117
Cary Clark09d80c02018-10-31 12:14:03 -04001118#Example
Cary Clark8032b982017-07-28 11:04:54 -04001119 SkPaint paint;
1120 SkDebugf("paint.isFakeBoldText() %c= !!(paint.getFlags() & SkPaint::kFakeBoldText_Flag)\n",
1121 paint.isFakeBoldText() == !!(paint.getFlags() & SkPaint::kFakeBoldText_Flag) ? '=' : '!');
1122 paint.setFakeBoldText(true);
1123 SkDebugf("paint.isFakeBoldText() %c= !!(paint.getFlags() & SkPaint::kFakeBoldText_Flag)\n",
1124 paint.isFakeBoldText() == !!(paint.getFlags() & SkPaint::kFakeBoldText_Flag) ? '=' : '!');
1125
1126 #StdOut
1127 paint.isFakeBoldText() == !!(paint.getFlags() & SkPaint::kFakeBoldText_Flag)
1128 paint.isFakeBoldText() == !!(paint.getFlags() & SkPaint::kFakeBoldText_Flag)
1129 ##
1130 ##
1131
1132##
1133
1134#Method void setFakeBoldText(bool fakeBoldText)
Cary Clarkab2621d2018-01-30 10:08:57 -05001135#In Fake_Bold
1136#Line # sets or clears Fake_Bold ##
Cary Clark09d80c02018-10-31 12:14:03 -04001137#Populate
Cary Clark8032b982017-07-28 11:04:54 -04001138
Cary Clark09d80c02018-10-31 12:14:03 -04001139#Example
Cary Clark8032b982017-07-28 11:04:54 -04001140 SkPaint paint1, paint2;
1141 paint1.setFakeBoldText(true);
1142 paint2.setFlags(paint2.getFlags() | SkPaint::kFakeBoldText_Flag);
1143 SkDebugf("paint1 %c= paint2\n", paint1 == paint2 ? '=' : '!');
1144
1145 #StdOut
1146 paint1 == paint2
1147 ##
1148 ##
1149
1150##
1151
Cary Clark8032b982017-07-28 11:04:54 -04001152# ------------------------------------------------------------------------------
Cary Clark08895c42018-02-01 09:37:32 -05001153#Subtopic Full_Hinting_Spacing
1154#Line # glyph spacing affected by hinting ##
Cary Clark137b8742018-05-30 09:21:49 -04001155#Alias Full_Hinting_Spacing ## # long winded enough -- maybe things with two underscores auto-aliased?
Cary Clark8032b982017-07-28 11:04:54 -04001156
Cary Clark777eede2018-11-09 16:04:58 -05001157if Hinting is set to SkFontHinting::kFull, Full_Hinting_Spacing adjusts the character
Cary Clark09d80c02018-10-31 12:14:03 -04001158spacing by the difference of the hinted and unhinted Left_Side_Bearing and
Cary Clarkce101242017-09-01 15:51:02 -04001159Right_Side_Bearing. Full_Hinting_Spacing only applies to platforms that use
1160FreeType as their Font_Engine.
Cary Clark8032b982017-07-28 11:04:54 -04001161
Cary Clark09d80c02018-10-31 12:14:03 -04001162Full_Hinting_Spacing is not related to text kerning, where the space between
1163a specific pair of characters is adjusted using data in the font kerning tables.
Cary Clarka90ea222018-10-16 10:30:28 -04001164#Subtopic Full_Hinting_Spacing ##
Cary Clark8032b982017-07-28 11:04:54 -04001165
Cary Clark8032b982017-07-28 11:04:54 -04001166# ------------------------------------------------------------------------------
Cary Clark08895c42018-02-01 09:37:32 -05001167#Subtopic Filter_Quality_Methods
1168#Line # get and set Filter_Quality ##
Cary Clark8032b982017-07-28 11:04:54 -04001169
1170Filter_Quality trades speed for image filtering when the image is scaled.
1171A lower Filter_Quality draws faster, but has less fidelity.
1172A higher Filter_Quality draws slower, but looks better.
Cary Clarkce101242017-09-01 15:51:02 -04001173If the image is drawn without scaling, the Filter_Quality choice will not result
1174in a noticeable difference.
Cary Clark8032b982017-07-28 11:04:54 -04001175
1176Filter_Quality is used in Paint passed as a parameter to
1177#List
1178# SkCanvas::drawBitmap ##
1179# SkCanvas::drawBitmapRect ##
1180# SkCanvas::drawImage ##
1181# SkCanvas::drawImageRect ##
1182 #ToDo probably more... ##
1183#List ##
1184and when Paint has a Shader specialization that uses Image or Bitmap.
1185
1186Filter_Quality is kNone_SkFilterQuality by default.
1187
1188#Example
1189#Image 3
1190void draw(SkCanvas* canvas) {
1191 SkPaint paint;
1192 canvas->scale(.2f, .2f);
Herb Derbyfcac00f2018-05-01 11:57:56 -04001193 for (SkFilterQuality q : { kNone_SkFilterQuality, kLow_SkFilterQuality,
Cary Clark8032b982017-07-28 11:04:54 -04001194 kMedium_SkFilterQuality, kHigh_SkFilterQuality } ) {
1195 paint.setFilterQuality(q);
1196 canvas->drawImage(image.get(), 0, 0, &paint);
1197 canvas->translate(550, 0);
1198 if (kLow_SkFilterQuality == q) canvas->translate(-1100, 550);
1199 }
1200}
1201##
Cary Clarka90ea222018-10-16 10:30:28 -04001202#Subtopic Filter_Quality_Methods ##
Cary Clark8032b982017-07-28 11:04:54 -04001203
1204#Method SkFilterQuality getFilterQuality() const
Cary Clarkab2621d2018-01-30 10:08:57 -05001205#In Filter_Quality_Methods
1206#Line # returns Filter_Quality, image filtering level ##
Cary Clark09d80c02018-10-31 12:14:03 -04001207#Populate
Cary Clark8032b982017-07-28 11:04:54 -04001208
1209#Example
1210 SkPaint paint;
1211 SkDebugf("kNone_SkFilterQuality %c= paint.getFilterQuality()\n",
1212 kNone_SkFilterQuality == paint.getFilterQuality() ? '=' : '!');
1213
1214 #StdOut
1215 kNone_SkFilterQuality == paint.getFilterQuality()
1216 ##
1217##
1218
1219##
1220
1221
1222#Method void setFilterQuality(SkFilterQuality quality)
Cary Clarkab2621d2018-01-30 10:08:57 -05001223#In Filter_Quality_Methods
1224#Line # sets Filter_Quality, the image filtering level ##
Cary Clark09d80c02018-10-31 12:14:03 -04001225#Populate
Cary Clark8032b982017-07-28 11:04:54 -04001226
1227#Example
1228 SkPaint paint;
1229 paint.setFilterQuality(kHigh_SkFilterQuality);
1230 SkDebugf("kHigh_SkFilterQuality %c= paint.getFilterQuality()\n",
1231 kHigh_SkFilterQuality == paint.getFilterQuality() ? '=' : '!');
1232
1233 #StdOut
1234 kHigh_SkFilterQuality == paint.getFilterQuality()
1235 ##
1236##
1237
1238#SeeAlso SkFilterQuality Image_Scaling
1239
1240##
1241
Cary Clark8032b982017-07-28 11:04:54 -04001242# ------------------------------------------------------------------------------
Cary Clark08895c42018-02-01 09:37:32 -05001243#Subtopic Color_Methods
1244#Line # get and set Color ##
Cary Clark8032b982017-07-28 11:04:54 -04001245
Cary Clarkab2621d2018-01-30 10:08:57 -05001246#Table
1247#Legend
1248# name # description ##
1249#Legend ##
Cary Clarkffb3d682018-05-17 12:17:28 -04001250# getColor # returns Color_Alpha and RGB, one drawing color ##
1251# setColor # sets Color_Alpha and RGB, one drawing color ##
Cary Clarkab2621d2018-01-30 10:08:57 -05001252#Table ##
Cary Clark8032b982017-07-28 11:04:54 -04001253
Cary Clarkffb3d682018-05-17 12:17:28 -04001254Color specifies the red, blue, green, and Color_Alpha
Cary Clarkab2621d2018-01-30 10:08:57 -05001255values used to draw a filled or stroked shape in a 32-bit value. Each component
1256occupies 8-bits, ranging from zero: no contribution; to 255: full intensity.
1257All values in any combination are valid.
Cary Clark8032b982017-07-28 11:04:54 -04001258
Cary Clarkab2621d2018-01-30 10:08:57 -05001259Color is not Premultiplied; Color_Alpha sets the transparency independent of
Cary Clarkffb3d682018-05-17 12:17:28 -04001260RGB: red, blue, and green.
Cary Clarkab2621d2018-01-30 10:08:57 -05001261
Cary Clarkffb3d682018-05-17 12:17:28 -04001262The bit positions of Color_Alpha and RGB are independent of the bit
Cary Clarkab2621d2018-01-30 10:08:57 -05001263positions on the output device, which may have more or fewer bits, and may have
1264a different arrangement.
Cary Clark8032b982017-07-28 11:04:54 -04001265
1266#Table
1267#Legend
Cary Clarkffb3d682018-05-17 12:17:28 -04001268# bit positions # Color_Alpha # red # blue # green ##
Cary Clark8032b982017-07-28 11:04:54 -04001269#Legend ##
1270# # 31 - 24 # 23 - 16 # 15 - 8 # 7 - 0 ##
1271#Table ##
1272
1273#Example
1274#Height 128
1275 void draw(SkCanvas* canvas) {
1276 SkPaint paint;
1277 paint.setColor(0x8000FF00); // transparent green
1278 canvas->drawCircle(50, 50, 40, paint);
1279 paint.setARGB(128, 255, 0, 0); // transparent red
1280 canvas->drawCircle(80, 50, 40, paint);
1281 paint.setColor(SK_ColorBLUE);
1282 paint.setAlpha(0x80);
1283 canvas->drawCircle(65, 65, 40, paint);
1284 }
1285##
Cary Clarka90ea222018-10-16 10:30:28 -04001286#Subtopic Color_Methods ##
Cary Clark8032b982017-07-28 11:04:54 -04001287
1288#Method SkColor getColor() const
Cary Clarkab2621d2018-01-30 10:08:57 -05001289#In Color_Methods
Cary Clarkffb3d682018-05-17 12:17:28 -04001290#Line # returns Color_Alpha and RGB, one drawing color ##
Cary Clark09d80c02018-10-31 12:14:03 -04001291#Populate
Cary Clark8032b982017-07-28 11:04:54 -04001292
Cary Clark09d80c02018-10-31 12:14:03 -04001293#Example
Cary Clark8032b982017-07-28 11:04:54 -04001294 SkPaint paint;
1295 paint.setColor(SK_ColorYELLOW);
1296 SkColor y = paint.getColor();
1297 SkDebugf("Yellow is %d%% red, %d%% green, and %d%% blue.\n", (int) (SkColorGetR(y) / 2.55f),
1298 (int) (SkColorGetG(y) / 2.55f), (int) (SkColorGetB(y) / 2.55f));
1299
1300 #StdOut
1301 Yellow is 100% red, 100% green, and 0% blue.
1302 ##
1303 ##
1304
Cary Clarkbbe8ff92018-09-05 11:39:01 -04001305 #SeeAlso getColor4f SkColor
Cary Clark8032b982017-07-28 11:04:54 -04001306
1307##
1308
Cary Clarkbbe8ff92018-09-05 11:39:01 -04001309#Method SkColor4f getColor4f() const
1310#In Color_Methods
1311#Line # returns Color_Alpha and RGB, one drawing color ##
Cary Clark09d80c02018-10-31 12:14:03 -04001312#Populate
Brian Osman3f70d172018-09-04 19:50:28 +00001313
Cary Clark09d80c02018-10-31 12:14:03 -04001314#Example
Cary Clarkbbe8ff92018-09-05 11:39:01 -04001315 SkPaint paint;
1316 paint.setColor(SK_ColorYELLOW);
1317 SkColor4f y = paint.getColor4f();
1318 SkDebugf("Yellow is %d%% red, %d%% green, and %d%% blue.\n", (int) (y.fR * 100),
1319 (int) (y.fG * 100), (int) (y.fB * 100));
1320
1321 #StdOut
1322 Yellow is 100% red, 100% green, and 0% blue.
1323 ##
1324 ##
1325
1326 #SeeAlso getColor SkColor
1327##
1328
1329
1330#Method void setColor(SkColor color)
Cary Clarkab2621d2018-01-30 10:08:57 -05001331#In Color_Methods
Cary Clarkffb3d682018-05-17 12:17:28 -04001332#Line # sets Color_Alpha and RGB, one drawing color ##
Cary Clark09d80c02018-10-31 12:14:03 -04001333#Populate
Cary Clark8032b982017-07-28 11:04:54 -04001334
Cary Clark09d80c02018-10-31 12:14:03 -04001335#Example
Cary Clark8032b982017-07-28 11:04:54 -04001336 SkPaint green1, green2;
1337 unsigned a = 255;
1338 unsigned r = 0;
1339 unsigned g = 255;
1340 unsigned b = 0;
1341 green1.setColor((a << 24) + (r << 16) + (g << 8) + (b << 0));
1342 green2.setColor(0xFF00FF00);
1343 SkDebugf("green1 %c= green2\n", green1 == green2 ? '=' : '!');
1344
1345 #StdOut
1346 green1 == green2
1347 ##
1348 ##
1349
Cary Clarkbbe8ff92018-09-05 11:39:01 -04001350 #SeeAlso SkColor setColor4f setARGB SkColorSetARGB
Cary Clark8032b982017-07-28 11:04:54 -04001351
1352##
Cary Clarkbbe8ff92018-09-05 11:39:01 -04001353
1354#Method void setColor4f(const SkColor4f& color, SkColorSpace* colorSpace)
1355#In Color_Methods
1356#Line # sets Color_Alpha and RGB, one drawing color ##
Cary Clark09d80c02018-10-31 12:14:03 -04001357#Populate
Cary Clarkbbe8ff92018-09-05 11:39:01 -04001358
Cary Clark09d80c02018-10-31 12:14:03 -04001359#Example
Cary Clarkbbe8ff92018-09-05 11:39:01 -04001360 SkPaint green1, green2;
1361 green1.setColor4f({0, 1, 0, 1}, nullptr); // R=0 G=1 B=0 A=1
1362 green2.setColor(0xFF00FF00); // A=255 R=0 G=255 B=0
1363 SkDebugf("green1 %c= green2\n", green1 == green2 ? '=' : '!');
1364
1365 #StdOut
1366 green1 == green2
1367 ##
1368 ##
1369
1370 #SeeAlso SkColor setColor setARGB SkColorSetARGB
1371
1372##
1373
Cary Clark8032b982017-07-28 11:04:54 -04001374#Subtopic Alpha_Methods
Cary Clark08895c42018-02-01 09:37:32 -05001375#Line # get and set Alpha ##
Cary Clark8032b982017-07-28 11:04:54 -04001376
Cary Clarkffb3d682018-05-17 12:17:28 -04001377Color_Alpha sets the transparency independent of RGB: red, blue, and green.
Cary Clarka90ea222018-10-16 10:30:28 -04001378#Subtopic Alpha_Methods ##
Cary Clark8032b982017-07-28 11:04:54 -04001379
1380#Method uint8_t getAlpha() const
Cary Clarkab2621d2018-01-30 10:08:57 -05001381#In Alpha_Methods
1382#Line # returns Color_Alpha, color opacity ##
Cary Clark09d80c02018-10-31 12:14:03 -04001383#Populate
Cary Clark8032b982017-07-28 11:04:54 -04001384
Cary Clark09d80c02018-10-31 12:14:03 -04001385#Example
Cary Clark8032b982017-07-28 11:04:54 -04001386 SkPaint paint;
1387 SkDebugf("255 %c= paint.getAlpha()\n", 255 == paint.getAlpha() ? '=' : '!');
1388
1389 #StdOut
1390 255 == paint.getAlpha()
1391 ##
1392 ##
1393
1394##
1395
1396#Method void setAlpha(U8CPU a)
Cary Clarkab2621d2018-01-30 10:08:57 -05001397#In Alpha_Methods
1398#Line # sets Color_Alpha, color opacity ##
Cary Clark09d80c02018-10-31 12:14:03 -04001399#Populate
Cary Clark8032b982017-07-28 11:04:54 -04001400
Cary Clark09d80c02018-10-31 12:14:03 -04001401#Example
Cary Clark8032b982017-07-28 11:04:54 -04001402 SkPaint paint;
1403 paint.setColor(0x00112233);
1404 paint.setAlpha(0x44);
1405 SkDebugf("0x44112233 %c= paint.getColor()\n", 0x44112233 == paint.getColor() ? '=' : '!');
1406
1407 #StdOut
1408 0x44112233 == paint.getColor()
1409 ##
1410 ##
1411
1412##
1413
Cary Clark8032b982017-07-28 11:04:54 -04001414#Method void setARGB(U8CPU a, U8CPU r, U8CPU g, U8CPU b)
Cary Clarkab2621d2018-01-30 10:08:57 -05001415#In Color_Methods
1416#Line # sets color by component ##
Cary Clark09d80c02018-10-31 12:14:03 -04001417#Populate
Cary Clark8032b982017-07-28 11:04:54 -04001418
Cary Clark09d80c02018-10-31 12:14:03 -04001419#Example
Cary Clark8032b982017-07-28 11:04:54 -04001420 SkPaint transRed1, transRed2;
1421 transRed1.setARGB(255 / 2, 255, 0, 0);
1422 transRed2.setColor(SkColorSetARGB(255 / 2, 255, 0, 0));
1423 SkDebugf("transRed1 %c= transRed2", transRed1 == transRed2 ? '=' : '!');
1424
1425 #StdOut
1426 transRed1 == transRed2
1427 ##
1428 ##
1429
1430 #SeeAlso setColor SkColorSetARGB
1431
1432##
1433
Cary Clark8032b982017-07-28 11:04:54 -04001434# ------------------------------------------------------------------------------
Cary Clark08895c42018-02-01 09:37:32 -05001435#Subtopic Style
1436#Line # geometry filling, stroking ##
Cary Clark8032b982017-07-28 11:04:54 -04001437
1438Style specifies if the geometry is filled, stroked, or both filled and stroked.
1439Some shapes ignore Style and are always drawn filled or stroked.
1440
Cary Clarka90ea222018-10-16 10:30:28 -04001441#Subtopic Fill
Cary Clark8032b982017-07-28 11:04:54 -04001442Set Style to kFill_Style to fill the shape.
1443The fill covers the area inside the geometry for most shapes.
Cary Clark08895c42018-02-01 09:37:32 -05001444#Subtopic Fill ##
Cary Clark8032b982017-07-28 11:04:54 -04001445
1446#Subtopic Stroke
Cary Clarka90ea222018-10-16 10:30:28 -04001447Set Style to kStroke_Style to stroke the shape.
1448
Cary Clarkbc5697d2017-10-04 14:31:33 -04001449The stroke covers the area described by following the shape edge with a pen or brush of
Cary Clark8032b982017-07-28 11:04:54 -04001450Stroke_Width. The area covered where the shape starts and stops is described by Stroke_Cap.
1451The area covered where the shape turns a corner is described by Stroke_Join.
Cary Clarkbc5697d2017-10-04 14:31:33 -04001452The stroke is centered on the shape; it extends equally on either side of the shape edge.
Cary Clarka90ea222018-10-16 10:30:28 -04001453#Subtopic Stroke ##
Cary Clark8032b982017-07-28 11:04:54 -04001454
1455As Stroke_Width gets smaller, the drawn path frame is thinner. Stroke_Width less than one
1456may have gaps, and if kAntiAlias_Flag is set, Color_Alpha will increase to visually decrease coverage.
Cary Clarka90ea222018-10-16 10:30:28 -04001457
1458#SeeAlso Path_Fill_Type Path_Effect Style_Fill Style_Stroke
1459#Subtopic Style ##
Cary Clark8032b982017-07-28 11:04:54 -04001460
1461#Subtopic Hairline
Cary Clark8032b982017-07-28 11:04:54 -04001462Stroke_Width of zero has a special meaning and switches drawing to use Hairline.
Herb Derbyfcac00f2018-05-01 11:57:56 -04001463Hairline draws the thinnest continuous frame. If kAntiAlias_Flag is clear, adjacent pixels
1464flow horizontally, vertically,or diagonally.
Cary Clark8032b982017-07-28 11:04:54 -04001465
Cary Clarkffb3d682018-05-17 12:17:28 -04001466#ToDo what is the description of Anti_Aliased hairlines? ##
Cary Clark8032b982017-07-28 11:04:54 -04001467
1468Path drawing with Hairline may hit the same pixel more than once. For instance, Path containing
1469two lines in one Path_Contour will draw the corner point once, but may both lines may draw the adjacent
1470pixel. If kAntiAlias_Flag is set, transparency is applied twice, resulting in a darker pixel. Some
1471GPU-backed implementations apply transparency at a later drawing stage, avoiding double hit pixels
1472while stroking.
1473
Cary Clarka90ea222018-10-16 10:30:28 -04001474#SeeAlso Path_Fill_Type Path_Effect Style_Fill Style_Stroke
Cary Clark08895c42018-02-01 09:37:32 -05001475#Subtopic Hairline ##
Cary Clark8032b982017-07-28 11:04:54 -04001476
1477#Enum Style
Cary Clark08895c42018-02-01 09:37:32 -05001478#Line # stroke, fill, or both ##
Cary Clark8032b982017-07-28 11:04:54 -04001479
1480#Code
Cary Clarka90ea222018-10-16 10:30:28 -04001481#Populate
1482##
Cary Clarkd98f78c2018-04-26 08:32:37 -04001483
Cary Clarka90ea222018-10-16 10:30:28 -04001484#Code
1485#In Constant
1486#Filter kStyle
1487#Populate
Cary Clark8032b982017-07-28 11:04:54 -04001488##
1489
1490Set Style to fill, stroke, or both fill and stroke geometry.
1491The stroke and fill
1492share all paint attributes; for instance, they are drawn with the same color.
1493
1494Use kStrokeAndFill_Style to avoid hitting the same pixels twice with a stroke draw and
1495a fill draw.
1496
1497#Const kFill_Style 0
Cary Clark682c58d2018-05-16 07:07:07 -04001498#Line # set to fill geometry ##
Herb Derbyfcac00f2018-05-01 11:57:56 -04001499 Applies to Rect, Region, Round_Rect, Circles, Ovals, Path, and Text.
Cary Clarkce101242017-09-01 15:51:02 -04001500 Bitmap, Image, Patches, Region, Sprites, and Vertices are painted as if
Cary Clark8032b982017-07-28 11:04:54 -04001501 kFill_Style is set, and ignore the set Style.
1502 The Path_Fill_Type specifies additional rules to fill the area outside the path edge,
1503 and to create an unfilled hole inside the shape.
1504 Style is set to kFill_Style by default.
1505##
1506
1507#Const kStroke_Style 1
Cary Clark682c58d2018-05-16 07:07:07 -04001508#Line # set to stroke geometry ##
Herb Derbyfcac00f2018-05-01 11:57:56 -04001509 Applies to Rect, Region, Round_Rect, Arcs, Circles, Ovals, Path, and Text.
Cary Clark56356312018-02-08 14:45:18 -05001510 Arcs, Lines, and points, are always drawn as if kStroke_Style is set,
Cary Clark8032b982017-07-28 11:04:54 -04001511 and ignore the set Style.
1512 The stroke construction is unaffected by the Path_Fill_Type.
1513##
1514
1515#Const kStrokeAndFill_Style 2
Cary Clark682c58d2018-05-16 07:07:07 -04001516#Line # sets to stroke and fill geometry ##
Cary Clarkce101242017-09-01 15:51:02 -04001517 Applies to Rect, Region, Round_Rect, Circles, Ovals, Path, and Text.
Cary Clark8032b982017-07-28 11:04:54 -04001518 Path is treated as if it is set to SkPath::kWinding_FillType,
Herb Derbyfcac00f2018-05-01 11:57:56 -04001519 and the set Path_Fill_Type is ignored.
Cary Clark8032b982017-07-28 11:04:54 -04001520##
1521
Cary Clark8032b982017-07-28 11:04:54 -04001522#Const kStyleCount 3
Cary Clark682c58d2018-05-16 07:07:07 -04001523#Line # number of different Style values defined ##
Cary Clark8032b982017-07-28 11:04:54 -04001524May be used to verify that Style is a legal value.
1525##
1526
Cary Clarkd98f78c2018-04-26 08:32:37 -04001527#Enum Style ##
Cary Clark8032b982017-07-28 11:04:54 -04001528
1529#Method Style getStyle() const
Cary Clarkab2621d2018-01-30 10:08:57 -05001530#In Style
1531#Line # returns Style: stroke, fill, or both ##
Cary Clark09d80c02018-10-31 12:14:03 -04001532#Populate
Cary Clark8032b982017-07-28 11:04:54 -04001533
Cary Clark09d80c02018-10-31 12:14:03 -04001534#Example
Cary Clark8032b982017-07-28 11:04:54 -04001535 SkPaint paint;
1536 SkDebugf("SkPaint::kFill_Style %c= paint.getStyle()\n",
1537 SkPaint::kFill_Style == paint.getStyle() ? '=' : '!');
1538
1539 #StdOut
1540 SkPaint::kFill_Style == paint.getStyle()
1541 ##
1542 ##
1543
1544#SeeAlso Style setStyle
1545##
1546
1547#Method void setStyle(Style style)
Cary Clarkab2621d2018-01-30 10:08:57 -05001548#In Style
1549#Line # sets Style: stroke, fill, or both ##
Cary Clark09d80c02018-10-31 12:14:03 -04001550#Populate
Cary Clark8032b982017-07-28 11:04:54 -04001551
Cary Clark09d80c02018-10-31 12:14:03 -04001552#Example
Cary Clark8032b982017-07-28 11:04:54 -04001553 void draw(SkCanvas* canvas) {
1554 SkPaint paint;
1555 paint.setStrokeWidth(5);
1556 SkRegion region;
1557 region.op(140, 10, 160, 30, SkRegion::kUnion_Op);
1558 region.op(170, 40, 190, 60, SkRegion::kUnion_Op);
1559 SkBitmap bitmap;
1560 bitmap.setInfo(SkImageInfo::MakeA8(50, 50), 50);
1561 uint8_t pixels[50][50];
1562 for (int x = 0; x < 50; ++x) {
1563 for (int y = 0; y < 50; ++y) {
1564 pixels[y][x] = (x + y) % 5 ? 0xFF : 0x00;
1565 }
1566 }
1567 bitmap.setPixels(pixels);
1568 for (auto style : { SkPaint::kFill_Style,
1569 SkPaint::kStroke_Style,
1570 SkPaint::kStrokeAndFill_Style }) {
1571 paint.setStyle(style);
1572 canvas->drawLine(10, 10, 60, 60, paint);
1573 canvas->drawRect({80, 10, 130, 60}, paint);
1574 canvas->drawRegion(region, paint);
1575 canvas->drawBitmap(bitmap, 200, 10, &paint);
1576 canvas->translate(0, 80);
1577 }
1578 }
1579 ##
1580
1581#SeeAlso Style getStyle
1582##
1583
Cary Clark8032b982017-07-28 11:04:54 -04001584# ------------------------------------------------------------------------------
Cary Clark08895c42018-02-01 09:37:32 -05001585#Subtopic Stroke_Width
1586#Line # thickness perpendicular to geometry ##
Cary Clark8032b982017-07-28 11:04:54 -04001587
1588Stroke_Width sets the width for stroking. The width is the thickness
Herb Derbyfcac00f2018-05-01 11:57:56 -04001589of the stroke perpendicular to the path direction when the paint style is
Cary Clark8032b982017-07-28 11:04:54 -04001590set to kStroke_Style or kStrokeAndFill_Style.
1591
1592When width is greater than zero, the stroke encompasses as many pixels partially
1593or fully as needed. When the width equals zero, the paint enables hairlines;
Herb Derbyfcac00f2018-05-01 11:57:56 -04001594the stroke is always one pixel wide.
Cary Clark8032b982017-07-28 11:04:54 -04001595
Cary Clarkbc5697d2017-10-04 14:31:33 -04001596The stroke dimensions are scaled by the canvas matrix, but Hairline stroke
Cary Clark8032b982017-07-28 11:04:54 -04001597remains one pixel wide regardless of scaling.
1598
1599The default width for the paint is zero.
1600
1601#Example
1602#Height 170
1603 #Platform raster gpu
1604 #Description
Herb Derbyfcac00f2018-05-01 11:57:56 -04001605 The pixels hit to represent thin lines vary with the angle of the
Cary Clarkbc5697d2017-10-04 14:31:33 -04001606 line and the platform implementation.
Cary Clark8032b982017-07-28 11:04:54 -04001607 ##
1608 void draw(SkCanvas* canvas) {
1609 SkPaint paint;
Herb Derbyfcac00f2018-05-01 11:57:56 -04001610 for (bool antialias : { false, true }) {
Cary Clark8032b982017-07-28 11:04:54 -04001611 paint.setAntiAlias(antialias);
1612 for (int width = 0; width <= 4; ++width) {
1613 SkScalar offset = antialias * 100 + width * 20;
1614 paint.setStrokeWidth(width * 0.25f);
1615 canvas->drawLine(10 + offset, 10, 20 + offset, 60, paint);
1616 canvas->drawLine(10 + offset, 110, 60 + offset, 160, paint);
1617 }
1618 }
1619 }
1620##
1621
1622#Method SkScalar getStrokeWidth() const
1623
Cary Clarkab2621d2018-01-30 10:08:57 -05001624#In Stroke_Width
1625#Line # returns thickness of the stroke ##
Cary Clark09d80c02018-10-31 12:14:03 -04001626#Populate
Cary Clark8032b982017-07-28 11:04:54 -04001627
Cary Clark09d80c02018-10-31 12:14:03 -04001628#Example
Cary Clark8032b982017-07-28 11:04:54 -04001629 SkPaint paint;
1630 SkDebugf("0 %c= paint.getStrokeWidth()\n", 0 == paint.getStrokeWidth() ? '=' : '!');
1631
1632 #StdOut
1633 0 == paint.getStrokeWidth()
1634 ##
1635 ##
1636
1637##
1638
1639#Method void setStrokeWidth(SkScalar width)
1640
Cary Clarkab2621d2018-01-30 10:08:57 -05001641#In Stroke_Width
1642#Line # sets thickness of the stroke ##
Cary Clark09d80c02018-10-31 12:14:03 -04001643#Populate
Cary Clark8032b982017-07-28 11:04:54 -04001644
Cary Clark09d80c02018-10-31 12:14:03 -04001645#Example
Cary Clark8032b982017-07-28 11:04:54 -04001646 SkPaint paint;
1647 paint.setStrokeWidth(5);
1648 paint.setStrokeWidth(-1);
1649 SkDebugf("5 %c= paint.getStrokeWidth()\n", 5 == paint.getStrokeWidth() ? '=' : '!');
1650
1651 #StdOut
1652 5 == paint.getStrokeWidth()
1653 ##
1654 ##
1655
1656##
1657
Cary Clark08895c42018-02-01 09:37:32 -05001658#Subtopic Stroke_Width ##
Cary Clark8032b982017-07-28 11:04:54 -04001659# ------------------------------------------------------------------------------
Cary Clark08895c42018-02-01 09:37:32 -05001660#Subtopic Miter_Limit
1661#Line # maximum length of stroked corners ##
Cary Clark8032b982017-07-28 11:04:54 -04001662
1663Miter_Limit specifies the maximum miter length,
1664relative to the stroke width.
1665
1666Miter_Limit is used when the Stroke_Join
1667is set to kMiter_Join, and the Style is either kStroke_Style
1668or kStrokeAndFill_Style.
1669
1670If the miter at a corner exceeds this limit, kMiter_Join
1671is replaced with kBevel_Join.
1672
Cary Clark2be81cf2018-09-13 12:04:30 -04001673Miter_Limit can be computed from the corner angle using:
1674#Formula # miter limit = 1 / sin ( angle / 2 ) ##.
Cary Clark8032b982017-07-28 11:04:54 -04001675
1676Miter_Limit default value is 4.
1677The default may be changed at compile time by setting SkPaintDefaults_MiterLimit
Cary Clarkce101242017-09-01 15:51:02 -04001678in "SkUserConfig.h" or as a define supplied by the build environment.
Cary Clark8032b982017-07-28 11:04:54 -04001679
1680Here are some miter limits and the angles that triggers them.
1681#Table
1682#Legend
1683 # miter limit # angle in degrees ##
1684#Legend ##
1685 # 10 # 11.48 ##
1686 # 9 # 12.76 ##
1687 # 8 # 14.36 ##
1688 # 7 # 16.43 ##
1689 # 6 # 19.19 ##
1690 # 5 # 23.07 ##
1691 # 4 # 28.96 ##
1692 # 3 # 38.94 ##
1693 # 2 # 60 ##
1694 # 1 # 180 ##
1695#Table ##
1696
1697#Example
1698 #Height 170
1699 #Width 384
1700 #Description
1701 This example draws a stroked corner and the miter length beneath.
1702 When the miter limit is decreased slightly, the miter join is replaced
1703 by a bevel join.
1704 ##
1705 void draw(SkCanvas* canvas) {
1706 SkPoint pts[] = {{ 10, 50 }, { 110, 80 }, { 10, 110 }};
1707 SkVector v[] = { pts[0] - pts[1], pts[2] - pts[1] };
1708 SkScalar angle1 = SkScalarATan2(v[0].fY, v[0].fX);
1709 SkScalar angle2 = SkScalarATan2(v[1].fY, v[1].fX);
1710 const SkScalar strokeWidth = 20;
1711 SkScalar miterLimit = 1 / SkScalarSin((angle2 - angle1) / 2);
1712 SkScalar miterLength = strokeWidth * miterLimit;
1713 SkPath path;
1714 path.moveTo(pts[0]);
1715 path.lineTo(pts[1]);
1716 path.lineTo(pts[2]);
1717 SkPaint paint; // set to default kMiter_Join
1718 paint.setAntiAlias(true);
1719 paint.setStyle(SkPaint::kStroke_Style);
1720 paint.setStrokeMiter(miterLimit);
1721 paint.setStrokeWidth(strokeWidth);
1722 canvas->drawPath(path, paint);
1723 paint.setStrokeWidth(1);
1724 canvas->drawLine(pts[1].fX - miterLength / 2, pts[1].fY + 50,
1725 pts[1].fX + miterLength / 2, pts[1].fY + 50, paint);
1726 canvas->translate(200, 0);
1727 miterLimit *= 0.99f;
1728 paint.setStrokeMiter(miterLimit);
1729 paint.setStrokeWidth(strokeWidth);
1730 canvas->drawPath(path, paint);
1731 paint.setStrokeWidth(1);
1732 canvas->drawLine(pts[1].fX - miterLength / 2, pts[1].fY + 50,
1733 pts[1].fX + miterLength / 2, pts[1].fY + 50, paint);
1734 }
1735##
1736
1737#Method SkScalar getStrokeMiter() const
1738
Cary Clarkab2621d2018-01-30 10:08:57 -05001739#In Miter_Limit
1740#Line # returns Miter_Limit, angles with sharp corners ##
Cary Clark09d80c02018-10-31 12:14:03 -04001741#Populate
Cary Clark8032b982017-07-28 11:04:54 -04001742
Cary Clark09d80c02018-10-31 12:14:03 -04001743#Example
Cary Clark8032b982017-07-28 11:04:54 -04001744 SkPaint paint;
1745 SkDebugf("default miter limit == %g\n", paint.getStrokeMiter());
1746
1747 #StdOut
1748 default miter limit == 4
1749 ##
1750 ##
1751
1752 #SeeAlso Miter_Limit setStrokeMiter Join
1753
1754##
1755
1756#Method void setStrokeMiter(SkScalar miter)
1757
Cary Clarkab2621d2018-01-30 10:08:57 -05001758#In Miter_Limit
1759#Line # sets Miter_Limit, angles with sharp corners ##
Cary Clark09d80c02018-10-31 12:14:03 -04001760#Populate
Cary Clark8032b982017-07-28 11:04:54 -04001761
Cary Clark09d80c02018-10-31 12:14:03 -04001762#Example
Cary Clark8032b982017-07-28 11:04:54 -04001763 SkPaint paint;
1764 paint.setStrokeMiter(8);
1765 paint.setStrokeMiter(-1);
1766 SkDebugf("default miter limit == %g\n", paint.getStrokeMiter());
1767
1768 #StdOut
1769 default miter limit == 8
1770 ##
1771 ##
1772
1773 #SeeAlso Miter_Limit getStrokeMiter Join
1774
1775##
1776
Cary Clark08895c42018-02-01 09:37:32 -05001777#Subtopic Miter_Limit ##
Cary Clark8032b982017-07-28 11:04:54 -04001778# ------------------------------------------------------------------------------
Cary Clark08895c42018-02-01 09:37:32 -05001779#Subtopic Stroke_Cap
1780#Line # decorations at ends of open strokes ##
Cary Clarka90ea222018-10-16 10:30:28 -04001781#Subtopic Stroke_Cap ##
Cary Clark8032b982017-07-28 11:04:54 -04001782
1783#Enum Cap
Cary Clark08895c42018-02-01 09:37:32 -05001784#Line # start and end geometry on stroked shapes ##
Cary Clark8032b982017-07-28 11:04:54 -04001785
1786#Code
Cary Clarka90ea222018-10-16 10:30:28 -04001787#Populate
1788##
Cary Clark8032b982017-07-28 11:04:54 -04001789
Cary Clarka90ea222018-10-16 10:30:28 -04001790#Code
1791#In Constant
1792#Filter kCap
1793#Populate
Cary Clark8032b982017-07-28 11:04:54 -04001794##
1795
1796Stroke_Cap draws at the beginning and end of an open Path_Contour.
1797
1798 #Const kButt_Cap 0
Cary Clark682c58d2018-05-16 07:07:07 -04001799 #Line # no stroke extension ##
Cary Clark8032b982017-07-28 11:04:54 -04001800 Does not extend the stroke past the beginning or the end.
1801 ##
1802 #Const kRound_Cap 1
Cary Clark682c58d2018-05-16 07:07:07 -04001803 #Line # adds circle ##
Cary Clark8032b982017-07-28 11:04:54 -04001804 Adds a circle with a diameter equal to Stroke_Width at the beginning
1805 and end.
1806 ##
1807 #Const kSquare_Cap 2
Cary Clark682c58d2018-05-16 07:07:07 -04001808 #Line # adds square ##
Cary Clark8032b982017-07-28 11:04:54 -04001809 Adds a square with sides equal to Stroke_Width at the beginning
1810 and end. The square sides are parallel to the initial and final direction
1811 of the stroke.
1812 ##
1813 #Const kLast_Cap 2
Cary Clark682c58d2018-05-16 07:07:07 -04001814 #Line # largest Stroke_Cap value ##
Cary Clark8032b982017-07-28 11:04:54 -04001815 Equivalent to the largest value for Stroke_Cap.
1816 ##
1817 #Const kDefault_Cap 0
Cary Clark682c58d2018-05-16 07:07:07 -04001818 #Line # equivalent to kButt_Cap ##
Cary Clark8032b982017-07-28 11:04:54 -04001819 Stroke_Cap is set to kButt_Cap by default.
1820 ##
1821
1822 #Const kCapCount 3
Cary Clark682c58d2018-05-16 07:07:07 -04001823 #Line # number of different Stroke_Cap values defined ##
Cary Clark8032b982017-07-28 11:04:54 -04001824 May be used to verify that Stroke_Cap is a legal value.
1825 ##
1826#Enum ##
1827
Herb Derbyfcac00f2018-05-01 11:57:56 -04001828Stroke describes the area covered by a pen of Stroke_Width as it
Cary Clarkbc5697d2017-10-04 14:31:33 -04001829follows the Path_Contour, moving parallel to the contour direction.
Cary Clark8032b982017-07-28 11:04:54 -04001830
1831If the Path_Contour is not terminated by SkPath::kClose_Verb, the contour has a
1832visible beginning and end.
1833
1834Path_Contour may start and end at the same point; defining Zero_Length_Contour.
1835
1836kButt_Cap and Zero_Length_Contour is not drawn.
Herb Derbyfcac00f2018-05-01 11:57:56 -04001837kRound_Cap and Zero_Length_Contour draws a circle of diameter Stroke_Width
Cary Clark8032b982017-07-28 11:04:54 -04001838at the contour point.
1839kSquare_Cap and Zero_Length_Contour draws an upright square with a side of
1840Stroke_Width at the contour point.
1841
1842Stroke_Cap is kButt_Cap by default.
1843
1844#Example
Cary Clark2ade9972017-11-02 17:49:34 -04001845#Height 200
Cary Clark8032b982017-07-28 11:04:54 -04001846 SkPaint paint;
1847 paint.setStyle(SkPaint::kStroke_Style);
1848 paint.setStrokeWidth(20);
1849 SkPath path;
1850 path.moveTo(30, 30);
1851 path.lineTo(30, 30);
1852 path.moveTo(70, 30);
1853 path.lineTo(90, 40);
1854 for (SkPaint::Cap c : { SkPaint::kButt_Cap, SkPaint::kRound_Cap, SkPaint::kSquare_Cap } ) {
1855 paint.setStrokeCap(c);
1856 canvas->drawPath(path, paint);
1857 canvas->translate(0, 70);
1858 }
1859##
1860
1861#Method Cap getStrokeCap() const
1862
Cary Clarkab2621d2018-01-30 10:08:57 -05001863#In Stroke_Cap
1864#Line # returns Cap, the area drawn at path ends ##
Cary Clark09d80c02018-10-31 12:14:03 -04001865#Populate
Cary Clark8032b982017-07-28 11:04:54 -04001866
Cary Clark09d80c02018-10-31 12:14:03 -04001867#Example
Cary Clark8032b982017-07-28 11:04:54 -04001868 SkPaint paint;
1869 SkDebugf("kButt_Cap %c= default stroke cap\n",
1870 SkPaint::kButt_Cap == paint.getStrokeCap() ? '=' : '!');
1871
1872 #StdOut
1873 kButt_Cap == default stroke cap
1874 ##
1875 ##
1876
1877 #SeeAlso Stroke_Cap setStrokeCap
1878##
1879
1880#Method void setStrokeCap(Cap cap)
1881
Cary Clarkab2621d2018-01-30 10:08:57 -05001882#In Stroke_Cap
1883#Line # sets Cap, the area drawn at path ends ##
Cary Clark09d80c02018-10-31 12:14:03 -04001884#Populate
Cary Clark8032b982017-07-28 11:04:54 -04001885
Cary Clark09d80c02018-10-31 12:14:03 -04001886#Example
Cary Clark8032b982017-07-28 11:04:54 -04001887 SkPaint paint;
1888 paint.setStrokeCap(SkPaint::kRound_Cap);
1889 paint.setStrokeCap((SkPaint::Cap) SkPaint::kCapCount);
1890 SkDebugf("kRound_Cap %c= paint.getStrokeCap()\n",
1891 SkPaint::kRound_Cap == paint.getStrokeCap() ? '=' : '!');
Herb Derbyfcac00f2018-05-01 11:57:56 -04001892
Cary Clark8032b982017-07-28 11:04:54 -04001893 #StdOut
1894 kRound_Cap == paint.getStrokeCap()
1895 ##
1896 ##
1897
1898 #SeeAlso Stroke_Cap getStrokeCap
1899##
1900
Cary Clark8032b982017-07-28 11:04:54 -04001901# ------------------------------------------------------------------------------
Cary Clark08895c42018-02-01 09:37:32 -05001902#Subtopic Stroke_Join
1903#Line # decoration at corners of strokes ##
Cary Clarka90ea222018-10-16 10:30:28 -04001904#Subtopic Stroke_Join ##
Cary Clark8032b982017-07-28 11:04:54 -04001905
1906Stroke_Join draws at the sharp corners of an open or closed Path_Contour.
1907
Herb Derbyfcac00f2018-05-01 11:57:56 -04001908Stroke describes the area covered by a pen of Stroke_Width as it
Cary Clarkbc5697d2017-10-04 14:31:33 -04001909follows the Path_Contour, moving parallel to the contour direction.
Cary Clark8032b982017-07-28 11:04:54 -04001910
1911If the contour direction changes abruptly, because the tangent direction leading
1912to the end of a curve within the contour does not match the tangent direction of
1913the following curve, the pair of curves meet at Stroke_Join.
1914
1915#Example
Cary Clark2ade9972017-11-02 17:49:34 -04001916#Height 200
Cary Clarka560c472017-11-27 10:44:06 -05001917 SkPaint paint;
1918 paint.setStyle(SkPaint::kStroke_Style);
1919 paint.setStrokeWidth(20);
1920 SkPath path;
1921 path.moveTo(30, 20);
1922 path.lineTo(40, 40);
1923 path.conicTo(70, 20, 100, 20, .707f);
1924 for (SkPaint::Join j : { SkPaint::kMiter_Join, SkPaint::kRound_Join, SkPaint::kBevel_Join } ) {
1925 paint.setStrokeJoin(j);
1926 canvas->drawPath(path, paint);
1927 canvas->translate(0, 70);
1928 }
Cary Clark8032b982017-07-28 11:04:54 -04001929##
1930
1931#Enum Join
Cary Clark08895c42018-02-01 09:37:32 -05001932#Line # corner geometry on stroked shapes ##
Cary Clark8032b982017-07-28 11:04:54 -04001933#Code
Cary Clarka90ea222018-10-16 10:30:28 -04001934#Populate
1935##
Cary Clark8032b982017-07-28 11:04:54 -04001936
Cary Clarka90ea222018-10-16 10:30:28 -04001937#Code
1938#In Constant
1939#Filter kJoin
1940#Populate
Cary Clark8032b982017-07-28 11:04:54 -04001941##
1942
Cary Clark1eace2d2017-07-31 07:52:43 -04001943Join specifies how corners are drawn when a shape is stroked. Join
Cary Clark8032b982017-07-28 11:04:54 -04001944affects the four corners of a stroked rectangle, and the connected segments in a
1945stroked path.
1946
1947Choose miter join to draw sharp corners. Choose round join to draw a circle with a
1948radius equal to the stroke width on top of the corner. Choose bevel join to minimally
1949connect the thick strokes.
1950
Herb Derbyfcac00f2018-05-01 11:57:56 -04001951The fill path constructed to describe the stroked path respects the join setting but may
Cary Clark8032b982017-07-28 11:04:54 -04001952not contain the actual join. For instance, a fill path constructed with round joins does
1953not necessarily include circles at each connected segment.
1954
1955#Const kMiter_Join 0
Cary Clark682c58d2018-05-16 07:07:07 -04001956#Line # extends to Miter_Limit ##
Cary Clark8032b982017-07-28 11:04:54 -04001957 Extends the outside corner to the extent allowed by Miter_Limit.
1958 If the extension exceeds Miter_Limit, kBevel_Join is used instead.
1959##
1960
1961#Const kRound_Join 1
Cary Clark682c58d2018-05-16 07:07:07 -04001962#Line # adds circle ##
Cary Clark8032b982017-07-28 11:04:54 -04001963 Adds a circle with a diameter of Stroke_Width at the sharp corner.
1964##
1965
1966#Const kBevel_Join 2
Cary Clark682c58d2018-05-16 07:07:07 -04001967#Line # connects outside edges ##
Cary Clark8032b982017-07-28 11:04:54 -04001968 Connects the outside edges of the sharp corner.
1969##
1970
1971#Const kLast_Join 2
Cary Clark682c58d2018-05-16 07:07:07 -04001972#Line # equivalent to the largest value for Stroke_Join ##
Cary Clark8032b982017-07-28 11:04:54 -04001973##
1974
1975#Const kDefault_Join 1
Cary Clark682c58d2018-05-16 07:07:07 -04001976#Line # equivalent to kMiter_Join ##
Herb Derbyfcac00f2018-05-01 11:57:56 -04001977 Stroke_Join is set to kMiter_Join by default.
Cary Clark8032b982017-07-28 11:04:54 -04001978##
1979
1980#Const kJoinCount 3
Cary Clark682c58d2018-05-16 07:07:07 -04001981#Line # number of different Stroke_Join values defined ##
Cary Clark8032b982017-07-28 11:04:54 -04001982 May be used to verify that Stroke_Join is a legal value.
1983##
1984
1985#Example
1986#Width 462
1987void draw(SkCanvas* canvas) {
1988 SkPath path;
1989 path.moveTo(10, 50);
1990 path.quadTo(35, 110, 60, 210);
1991 path.quadTo(105, 110, 130, 10);
1992 SkPaint paint; // set to default kMiter_Join
1993 paint.setAntiAlias(true);
1994 paint.setStyle(SkPaint::kStroke_Style);
1995 paint.setStrokeWidth(20);
1996 canvas->drawPath(path, paint);
1997 canvas->translate(150, 0);
1998 paint.setStrokeJoin(SkPaint::kBevel_Join);
1999 canvas->drawPath(path, paint);
2000 canvas->translate(150, 0);
2001 paint.setStrokeJoin(SkPaint::kRound_Join);
2002 canvas->drawPath(path, paint);
2003}
2004##
2005
2006#SeeAlso setStrokeJoin getStrokeJoin setStrokeMiter getStrokeMiter
2007
2008#Enum ##
2009
2010#Method Join getStrokeJoin() const
2011
Cary Clarkab2621d2018-01-30 10:08:57 -05002012#In Stroke_Join
2013#Line # returns Join, geometry on path corners ##
Cary Clark09d80c02018-10-31 12:14:03 -04002014#Populate
Cary Clark8032b982017-07-28 11:04:54 -04002015
Cary Clark09d80c02018-10-31 12:14:03 -04002016#Example
Cary Clark8032b982017-07-28 11:04:54 -04002017 SkPaint paint;
2018 SkDebugf("kMiter_Join %c= default stroke join\n",
2019 SkPaint::kMiter_Join == paint.getStrokeJoin() ? '=' : '!');
2020
2021 #StdOut
2022 kMiter_Join == default stroke join
2023 ##
2024 ##
2025
2026 #SeeAlso Stroke_Join setStrokeJoin
2027##
2028
2029#Method void setStrokeJoin(Join join)
2030
Cary Clarkab2621d2018-01-30 10:08:57 -05002031#In Stroke_Join
2032#Line # sets Join, geometry on path corners ##
Cary Clark09d80c02018-10-31 12:14:03 -04002033#Populate
Cary Clark8032b982017-07-28 11:04:54 -04002034
Cary Clark09d80c02018-10-31 12:14:03 -04002035#Example
Cary Clark8032b982017-07-28 11:04:54 -04002036 SkPaint paint;
2037 paint.setStrokeJoin(SkPaint::kMiter_Join);
2038 paint.setStrokeJoin((SkPaint::Join) SkPaint::kJoinCount);
2039 SkDebugf("kMiter_Join %c= paint.getStrokeJoin()\n",
2040 SkPaint::kMiter_Join == paint.getStrokeJoin() ? '=' : '!');
2041
2042 #StdOut
2043 kMiter_Join == paint.getStrokeJoin()
2044 ##
2045 ##
2046
2047 #SeeAlso Stroke_Join getStrokeJoin
2048##
2049
2050#SeeAlso Miter_Limit
2051
Cary Clark8032b982017-07-28 11:04:54 -04002052# ------------------------------------------------------------------------------
Cary Clark08895c42018-02-01 09:37:32 -05002053#Subtopic Fill_Path
2054#Line # make Path from Path_Effect, stroking ##
Cary Clark8032b982017-07-28 11:04:54 -04002055
2056Fill_Path creates a Path by applying the Path_Effect, followed by the Style_Stroke.
2057
2058If Paint contains Path_Effect, Path_Effect operates on the source Path; the result
2059replaces the destination Path. Otherwise, the source Path is replaces the
2060destination Path.
2061
2062Fill Path can request the Path_Effect to restrict to a culling rectangle, but
2063the Path_Effect is not required to do so.
2064
Herb Derbyfcac00f2018-05-01 11:57:56 -04002065If Style is kStroke_Style or kStrokeAndFill_Style,
Cary Clark8032b982017-07-28 11:04:54 -04002066and Stroke_Width is greater than zero, the Stroke_Width, Stroke_Cap, Stroke_Join,
2067and Miter_Limit operate on the destination Path, replacing it.
2068
Herb Derbyfcac00f2018-05-01 11:57:56 -04002069Fill Path can specify the precision used by Stroke_Width to approximate the stroke geometry.
Cary Clark8032b982017-07-28 11:04:54 -04002070
2071If the Style is kStroke_Style and the Stroke_Width is zero, getFillPath
2072returns false since Hairline has no filled equivalent.
2073
Cary Clarka90ea222018-10-16 10:30:28 -04002074#SeeAlso Style_Stroke Stroke_Width Path_Effect
2075
2076#Subtopic Fill_Path ##
2077
Cary Clark8032b982017-07-28 11:04:54 -04002078#Method bool getFillPath(const SkPath& src, SkPath* dst, const SkRect* cullRect,
2079 SkScalar resScale = 1) const
Cary Clarkab2621d2018-01-30 10:08:57 -05002080#In Fill_Path
2081#Line # returns fill path equivalent to stroke ##
Cary Clark09d80c02018-10-31 12:14:03 -04002082#Populate
Cary Clark8032b982017-07-28 11:04:54 -04002083
Cary Clark09d80c02018-10-31 12:14:03 -04002084#Example
Cary Clark8032b982017-07-28 11:04:54 -04002085 #Height 192
2086 #Description
Cary Clarkce101242017-09-01 15:51:02 -04002087 A very small Quad stroke is turned into a filled path with increasing levels of precision.
Herb Derbyfcac00f2018-05-01 11:57:56 -04002088 At the lowest precision, the Quad stroke is approximated by a rectangle.
Cary Clark8032b982017-07-28 11:04:54 -04002089 At the highest precision, the filled path has high fidelity compared to the original stroke.
2090 ##
2091 void draw(SkCanvas* canvas) {
2092 SkPaint strokePaint;
2093 strokePaint.setAntiAlias(true);
2094 strokePaint.setStyle(SkPaint::kStroke_Style);
2095 strokePaint.setStrokeWidth(.1f);
2096 SkPath strokePath;
2097 strokePath.moveTo(.08f, .08f);
2098 strokePath.quadTo(.09f, .08f, .17f, .17f);
2099 SkPath fillPath;
2100 SkPaint outlinePaint(strokePaint);
2101 outlinePaint.setStrokeWidth(2);
2102 SkMatrix scale = SkMatrix::MakeScale(300, 300);
2103 for (SkScalar precision : { 0.01f, .1f, 1.f, 10.f, 100.f } ) {
2104 strokePaint.getFillPath(strokePath, &fillPath, nullptr, precision);
2105 fillPath.transform(scale);
2106 canvas->drawPath(fillPath, outlinePaint);
2107 canvas->translate(60, 0);
2108 if (1.f == precision) canvas->translate(-180, 100);
2109 }
2110 strokePath.transform(scale);
2111 strokePaint.setStrokeWidth(30);
2112 canvas->drawPath(strokePath, strokePaint);
2113 }
2114 ##
2115
2116##
2117
2118#Method bool getFillPath(const SkPath& src, SkPath* dst) const
2119
Cary Clarkab2621d2018-01-30 10:08:57 -05002120#In Fill_Path
Cary Clark09d80c02018-10-31 12:14:03 -04002121#Populate
Cary Clark8032b982017-07-28 11:04:54 -04002122
Cary Clark09d80c02018-10-31 12:14:03 -04002123#Example
Cary Clark8032b982017-07-28 11:04:54 -04002124 #Height 128
2125 void draw(SkCanvas* canvas) {
2126 SkPaint paint;
2127 paint.setStyle(SkPaint::kStroke_Style);
2128 paint.setStrokeWidth(10);
2129 SkPath strokePath;
2130 strokePath.moveTo(20, 20);
2131 strokePath.lineTo(100, 100);
2132 canvas->drawPath(strokePath, paint);
2133 SkPath fillPath;
2134 paint.getFillPath(strokePath, &fillPath);
2135 paint.setStrokeWidth(2);
2136 canvas->translate(40, 0);
2137 canvas->drawPath(fillPath, paint);
2138 }
2139 ##
2140
2141##
2142
Cary Clark8032b982017-07-28 11:04:54 -04002143# ------------------------------------------------------------------------------
Cary Clark08895c42018-02-01 09:37:32 -05002144#Subtopic Shader_Methods
2145#Line # get and set Shader ##
Cary Clark8032b982017-07-28 11:04:54 -04002146
2147Shader defines the colors used when drawing a shape.
2148Shader may be an image, a gradient, or a computed fill.
Herb Derbyfcac00f2018-05-01 11:57:56 -04002149If Paint has no Shader, then Color fills the shape.
Cary Clark8032b982017-07-28 11:04:54 -04002150
2151Shader is modulated by Color_Alpha component of Color.
2152If Shader object defines only Color_Alpha, then Color modulated by Color_Alpha describes
2153the fill.
2154
2155The drawn transparency can be modified without altering Shader, by changing Color_Alpha.
2156
2157#Example
2158void draw(SkCanvas* canvas) {
2159 SkPaint paint;
2160 SkPoint center = { 50, 50 };
2161 SkScalar radius = 50;
2162 const SkColor colors[] = { 0xFFFFFFFF, 0xFF000000 };
2163 paint.setShader(SkGradientShader::MakeRadial(center, radius, colors,
2164 nullptr, SK_ARRAY_COUNT(colors), SkShader::kClamp_TileMode));
2165 for (SkScalar a : { 0.3f, 0.6f, 1.0f } ) {
2166 paint.setAlpha((int) (a * 255));
2167 canvas->drawCircle(center.fX, center.fY, radius, paint);
2168 canvas->translate(70, 70);
2169 }
2170}
2171##
2172
2173If Shader generates only Color_Alpha then all components of Color modulate the output.
2174
2175#Example
2176void draw(SkCanvas* canvas) {
2177 SkPaint paint;
2178 SkBitmap bitmap;
2179 bitmap.setInfo(SkImageInfo::MakeA8(5, 1), 5); // bitmap only contains alpha
2180 uint8_t pixels[5] = { 0x22, 0x55, 0x88, 0xBB, 0xFF };
2181 bitmap.setPixels(pixels);
Herb Derbyfcac00f2018-05-01 11:57:56 -04002182 paint.setShader(SkShader::MakeBitmapShader(bitmap,
Cary Clark8032b982017-07-28 11:04:54 -04002183 SkShader::kMirror_TileMode, SkShader::kMirror_TileMode));
2184 for (SkColor c : { SK_ColorRED, SK_ColorBLUE, SK_ColorGREEN } ) {
2185 paint.setColor(c); // all components in color affect shader
2186 canvas->drawCircle(50, 50, 50, paint);
2187 canvas->translate(70, 70);
2188 }
2189}
2190##
2191
2192#Method SkShader* getShader() const
2193
Cary Clarkab2621d2018-01-30 10:08:57 -05002194#In Shader_Methods
2195#Line # returns Shader, multiple drawing colors; gradients ##
Cary Clark09d80c02018-10-31 12:14:03 -04002196#Populate
Cary Clark8032b982017-07-28 11:04:54 -04002197
Cary Clark09d80c02018-10-31 12:14:03 -04002198#Example
Cary Clark8032b982017-07-28 11:04:54 -04002199 void draw(SkCanvas* canvas) {
2200 SkPaint paint;
2201 SkDebugf("nullptr %c= shader\n", paint.getShader() ? '!' : '=');
2202 paint.setShader(SkShader::MakeEmptyShader());
2203 SkDebugf("nullptr %c= shader\n", paint.getShader() ? '!' : '=');
2204 }
2205
2206 #StdOut
2207 nullptr == shader
2208 nullptr != shader
2209 ##
2210 ##
2211
2212##
2213
2214#Method sk_sp<SkShader> refShader() const
2215
Cary Clarkab2621d2018-01-30 10:08:57 -05002216#In Shader_Methods
2217#Line # references Shader, multiple drawing colors; gradients ##
Cary Clark09d80c02018-10-31 12:14:03 -04002218#Populate
Cary Clark8032b982017-07-28 11:04:54 -04002219
Cary Clark09d80c02018-10-31 12:14:03 -04002220#Example
Cary Clark8032b982017-07-28 11:04:54 -04002221 void draw(SkCanvas* canvas) {
2222 SkPaint paint1, paint2;
2223 paint1.setShader(SkShader::MakeEmptyShader());
2224 SkDebugf("shader unique: %s\n", paint1.getShader()->unique() ? "true" : "false");
2225 paint2.setShader(paint1.refShader());
2226 SkDebugf("shader unique: %s\n", paint1.getShader()->unique() ? "true" : "false");
2227 }
2228
2229 #StdOut
2230 shader unique: true
2231 shader unique: false
2232 ##
2233 ##
2234
2235##
2236
2237#Method void setShader(sk_sp<SkShader> shader)
2238
Cary Clarkab2621d2018-01-30 10:08:57 -05002239#In Shader_Methods
2240#Line # sets Shader, multiple drawing colors; gradients ##
Cary Clark09d80c02018-10-31 12:14:03 -04002241#Populate
Cary Clark8032b982017-07-28 11:04:54 -04002242
Cary Clark09d80c02018-10-31 12:14:03 -04002243#Example
Cary Clark8032b982017-07-28 11:04:54 -04002244 #Height 64
2245 void draw(SkCanvas* canvas) {
2246 SkPaint paint;
2247 paint.setColor(SK_ColorBLUE);
2248 paint.setShader(SkShader::MakeColorShader(SK_ColorRED));
2249 canvas->drawRect(SkRect::MakeWH(40, 40), paint);
2250 paint.setShader(nullptr);
2251 canvas->translate(50, 0);
2252 canvas->drawRect(SkRect::MakeWH(40, 40), paint);
2253 }
2254 ##
2255
2256##
2257
Cary Clark08895c42018-02-01 09:37:32 -05002258#Subtopic Shader_Methods ##
Cary Clark8032b982017-07-28 11:04:54 -04002259# ------------------------------------------------------------------------------
Cary Clark08895c42018-02-01 09:37:32 -05002260#Subtopic Color_Filter_Methods
2261#Line # get and set Color_Filter ##
Cary Clark8032b982017-07-28 11:04:54 -04002262
2263Color_Filter alters the color used when drawing a shape.
2264Color_Filter may apply Blend_Mode, transform the color through a matrix, or composite multiple filters.
2265If Paint has no Color_Filter, the color is unaltered.
2266
2267The drawn transparency can be modified without altering Color_Filter, by changing Color_Alpha.
2268
2269#Example
2270#Height 128
2271void draw(SkCanvas* canvas) {
2272 SkPaint paint;
2273 paint.setColorFilter(SkColorMatrixFilter::MakeLightingFilter(0xFFFFFF, 0xFF0000));
2274 for (SkColor c : { SK_ColorBLACK, SK_ColorGREEN } ) {
2275 paint.setColor(c);
2276 canvas->drawRect(SkRect::MakeXYWH(10, 10, 50, 50), paint);
2277 paint.setAlpha(0x80);
2278 canvas->drawRect(SkRect::MakeXYWH(60, 60, 50, 50), paint);
2279 canvas->translate(100, 0);
2280 }
2281}
2282##
2283
2284#Method SkColorFilter* getColorFilter() const
2285
Cary Clarkab2621d2018-01-30 10:08:57 -05002286#In Color_Filter_Methods
2287#Line # returns Color_Filter, how colors are altered ##
Cary Clark09d80c02018-10-31 12:14:03 -04002288#Populate
Herb Derbyfcac00f2018-05-01 11:57:56 -04002289
Cary Clark09d80c02018-10-31 12:14:03 -04002290#Example
Cary Clark8032b982017-07-28 11:04:54 -04002291 void draw(SkCanvas* canvas) {
2292 SkPaint paint;
2293 SkDebugf("nullptr %c= color filter\n", paint.getColorFilter() ? '!' : '=');
2294 paint.setColorFilter(SkColorFilter::MakeModeFilter(SK_ColorLTGRAY, SkBlendMode::kSrcIn));
2295 SkDebugf("nullptr %c= color filter\n", paint.getColorFilter() ? '!' : '=');
2296 }
2297
2298 #StdOut
2299 nullptr == color filter
2300 nullptr != color filter
2301 ##
2302 ##
2303##
2304
2305#Method sk_sp<SkColorFilter> refColorFilter() const
2306
Cary Clarkab2621d2018-01-30 10:08:57 -05002307#In Color_Filter_Methods
2308#Line # references Color_Filter, how colors are altered ##
Cary Clark09d80c02018-10-31 12:14:03 -04002309#Populate
Cary Clark8032b982017-07-28 11:04:54 -04002310
Cary Clark09d80c02018-10-31 12:14:03 -04002311#Example
Cary Clark8032b982017-07-28 11:04:54 -04002312 void draw(SkCanvas* canvas) {
2313 SkPaint paint1, paint2;
2314 paint1.setColorFilter(SkColorFilter::MakeModeFilter(0xFFFF0000, SkBlendMode::kSrcATop));
2315 SkDebugf("color filter unique: %s\n", paint1.getColorFilter()->unique() ? "true" : "false");
2316 paint2.setColorFilter(paint1.refColorFilter());
2317 SkDebugf("color filter unique: %s\n", paint1.getColorFilter()->unique() ? "true" : "false");
2318 }
2319
2320 #StdOut
2321 color filter unique: true
2322 color filter unique: false
2323 ##
2324 ##
2325##
2326
2327#Method void setColorFilter(sk_sp<SkColorFilter> colorFilter)
2328
Cary Clarkab2621d2018-01-30 10:08:57 -05002329#In Color_Filter_Methods
2330#Line # sets Color_Filter, alters color ##
Cary Clark09d80c02018-10-31 12:14:03 -04002331#Populate
Cary Clark6fc50412017-09-21 12:31:06 -04002332
Cary Clark09d80c02018-10-31 12:14:03 -04002333#Example
Cary Clark8032b982017-07-28 11:04:54 -04002334 #Height 64
2335 void draw(SkCanvas* canvas) {
2336 SkPaint paint;
2337 paint.setColorFilter(SkColorFilter::MakeModeFilter(SK_ColorLTGRAY, SkBlendMode::kSrcIn));
2338 canvas->drawRect(SkRect::MakeWH(50, 50), paint);
2339 paint.setColorFilter(nullptr);
2340 canvas->translate(70, 0);
2341 canvas->drawRect(SkRect::MakeWH(50, 50), paint);
2342 }
2343 ##
2344
2345##
2346
Cary Clark08895c42018-02-01 09:37:32 -05002347#Subtopic Color_Filter_Methods ##
Cary Clark8032b982017-07-28 11:04:54 -04002348# ------------------------------------------------------------------------------
Cary Clark08895c42018-02-01 09:37:32 -05002349#Subtopic Blend_Mode_Methods
2350#Line # get and set Blend_Mode ##
Cary Clark8032b982017-07-28 11:04:54 -04002351
2352Blend_Mode describes how Color combines with the destination color.
2353The default setting, SkBlendMode::kSrcOver, draws the source color
2354over the destination color.
2355
2356#Example
2357void draw(SkCanvas* canvas) {
2358 SkPaint normal, blender;
2359 normal.setColor(0xFF58a889);
2360 blender.setColor(0xFF8958a8);
2361 canvas->clear(0);
2362 for (SkBlendMode m : { SkBlendMode::kSrcOver, SkBlendMode::kSrcIn, SkBlendMode::kSrcOut } ) {
2363 normal.setBlendMode(SkBlendMode::kSrcOver);
2364 canvas->drawOval(SkRect::MakeXYWH(30, 30, 30, 80), normal);
2365 blender.setBlendMode(m);
2366 canvas->drawOval(SkRect::MakeXYWH(10, 50, 80, 30), blender);
2367 canvas->translate(70, 70);
2368 }
2369}
2370##
2371
2372#SeeAlso Blend_Mode
2373
2374#Method SkBlendMode getBlendMode() const
2375
Cary Clarkab2621d2018-01-30 10:08:57 -05002376#In Blend_Mode_Methods
2377#Line # returns Blend_Mode, how colors combine with Device ##
Cary Clark09d80c02018-10-31 12:14:03 -04002378#Populate
Cary Clark8032b982017-07-28 11:04:54 -04002379
Cary Clark09d80c02018-10-31 12:14:03 -04002380#Example
Cary Clark8032b982017-07-28 11:04:54 -04002381 void draw(SkCanvas* canvas) {
2382 SkPaint paint;
Herb Derbyfcac00f2018-05-01 11:57:56 -04002383 SkDebugf("kSrcOver %c= getBlendMode\n",
Cary Clark8032b982017-07-28 11:04:54 -04002384 SkBlendMode::kSrcOver == paint.getBlendMode() ? '=' : '!');
2385 paint.setBlendMode(SkBlendMode::kSrc);
Herb Derbyfcac00f2018-05-01 11:57:56 -04002386 SkDebugf("kSrcOver %c= getBlendMode\n",
Cary Clark8032b982017-07-28 11:04:54 -04002387 SkBlendMode::kSrcOver == paint.getBlendMode() ? '=' : '!');
2388 }
2389
2390 #StdOut
2391 kSrcOver == getBlendMode
2392 kSrcOver != getBlendMode
2393 ##
2394 ##
2395
2396##
2397
2398#Method bool isSrcOver() const
2399
Cary Clarkab2621d2018-01-30 10:08:57 -05002400#In Blend_Mode_Methods
2401#Line # returns true if Blend_Mode is SkBlendMode::kSrcOver ##
Cary Clark09d80c02018-10-31 12:14:03 -04002402#Populate
Cary Clark8032b982017-07-28 11:04:54 -04002403
Cary Clark09d80c02018-10-31 12:14:03 -04002404#Example
Cary Clark8032b982017-07-28 11:04:54 -04002405 void draw(SkCanvas* canvas) {
2406 SkPaint paint;
2407 SkDebugf("isSrcOver %c= true\n", paint.isSrcOver() ? '=' : '!');
2408 paint.setBlendMode(SkBlendMode::kSrc);
2409 SkDebugf("isSrcOver %c= true\n", paint.isSrcOver() ? '=' : '!');
2410 }
2411
2412 #StdOut
2413 isSrcOver == true
2414 isSrcOver != true
2415 ##
2416 ##
2417
2418##
2419
2420#Method void setBlendMode(SkBlendMode mode)
2421
Cary Clarkab2621d2018-01-30 10:08:57 -05002422#In Blend_Mode_Methods
2423#Line # sets Blend_Mode, how colors combine with destination ##
Cary Clark09d80c02018-10-31 12:14:03 -04002424#Populate
Cary Clark8032b982017-07-28 11:04:54 -04002425
Cary Clark09d80c02018-10-31 12:14:03 -04002426#Example
Cary Clark8032b982017-07-28 11:04:54 -04002427 void draw(SkCanvas* canvas) {
2428 SkPaint paint;
2429 SkDebugf("isSrcOver %c= true\n", paint.isSrcOver() ? '=' : '!');
2430 paint.setBlendMode(SkBlendMode::kSrc);
2431 SkDebugf("isSrcOver %c= true\n", paint.isSrcOver() ? '=' : '!');
2432 }
2433
2434 #StdOut
2435 isSrcOver == true
2436 isSrcOver != true
2437 ##
2438 ##
2439
2440##
2441
Cary Clark08895c42018-02-01 09:37:32 -05002442#Subtopic Blend_Mode_Methods ##
Cary Clark8032b982017-07-28 11:04:54 -04002443# ------------------------------------------------------------------------------
Cary Clark08895c42018-02-01 09:37:32 -05002444#Subtopic Path_Effect_Methods
2445#Line # get and set Path_Effect ##
Cary Clark8032b982017-07-28 11:04:54 -04002446
2447Path_Effect modifies the path geometry before drawing it.
2448Path_Effect may implement dashing, custom fill effects and custom stroke effects.
2449If Paint has no Path_Effect, the path geometry is unaltered when filled or stroked.
2450
2451#Example
2452#Height 160
2453 void draw(SkCanvas* canvas) {
2454 SkPaint paint;
2455 paint.setStyle(SkPaint::kStroke_Style);
2456 paint.setStrokeWidth(16);
2457 SkScalar intervals[] = {30, 10};
2458 paint.setPathEffect(SkDashPathEffect::Make(intervals, SK_ARRAY_COUNT(intervals), 1));
2459 canvas->drawRoundRect({20, 20, 120, 120}, 20, 20, paint);
2460 }
2461##
2462
2463#SeeAlso Path_Effect
2464
2465#Method SkPathEffect* getPathEffect() const
2466
Cary Clarkab2621d2018-01-30 10:08:57 -05002467#In Path_Effect_Methods
2468#Line # returns Path_Effect, modifications to path geometry; dashing ##
Cary Clark09d80c02018-10-31 12:14:03 -04002469#Populate
Herb Derbyfcac00f2018-05-01 11:57:56 -04002470
Cary Clark09d80c02018-10-31 12:14:03 -04002471#Example
Cary Clark8032b982017-07-28 11:04:54 -04002472 void draw(SkCanvas* canvas) {
2473 SkPaint paint;
2474 SkDebugf("nullptr %c= path effect\n", paint.getPathEffect() ? '!' : '=');
2475 paint.setPathEffect(SkCornerPathEffect::Make(10));
2476 SkDebugf("nullptr %c= path effect\n", paint.getPathEffect() ? '!' : '=');
2477 }
2478
2479 #StdOut
2480 nullptr == path effect
2481 nullptr != path effect
2482 ##
2483 ##
2484
2485##
2486
2487
2488#Method sk_sp<SkPathEffect> refPathEffect() const
2489
Cary Clarkab2621d2018-01-30 10:08:57 -05002490#In Path_Effect_Methods
2491#Line # references Path_Effect, modifications to path geometry; dashing ##
Cary Clark09d80c02018-10-31 12:14:03 -04002492#Populate
Cary Clark8032b982017-07-28 11:04:54 -04002493
Cary Clark09d80c02018-10-31 12:14:03 -04002494#Example
Cary Clark8032b982017-07-28 11:04:54 -04002495 void draw(SkCanvas* canvas) {
2496 SkPaint paint1, paint2;
Cary Clarka560c472017-11-27 10:44:06 -05002497 SkScalar intervals[] = {1, 2};
2498 paint1.setPathEffect(SkDashPathEffect::Make(intervals, SK_ARRAY_COUNT(intervals), 10));
Cary Clark8032b982017-07-28 11:04:54 -04002499 SkDebugf("path effect unique: %s\n", paint1.getPathEffect()->unique() ? "true" : "false");
2500 paint2.setPathEffect(paint1.refPathEffect());
2501 SkDebugf("path effect unique: %s\n", paint1.getPathEffect()->unique() ? "true" : "false");
2502 }
2503
2504 #StdOut
2505 path effect unique: true
2506 path effect unique: false
2507 ##
2508 ##
2509
2510##
2511
2512
2513#Method void setPathEffect(sk_sp<SkPathEffect> pathEffect)
2514
Cary Clarkab2621d2018-01-30 10:08:57 -05002515#In Path_Effect_Methods
2516#Line # sets Path_Effect, modifications to path geometry; dashing ##
Cary Clark09d80c02018-10-31 12:14:03 -04002517#Populate
Cary Clark6fc50412017-09-21 12:31:06 -04002518
Cary Clark09d80c02018-10-31 12:14:03 -04002519#Example
Cary Clark8032b982017-07-28 11:04:54 -04002520 void draw(SkCanvas* canvas) {
2521 SkPaint paint;
2522 paint.setPathEffect(SkDiscretePathEffect::Make(3, 5));
2523 canvas->drawRect(SkRect::MakeXYWH(40, 40, 175, 175), paint);
2524 }
2525 ##
2526
2527##
2528
Cary Clark08895c42018-02-01 09:37:32 -05002529#Subtopic Path_Effect_Methods ##
Cary Clark8032b982017-07-28 11:04:54 -04002530# ------------------------------------------------------------------------------
Cary Clark08895c42018-02-01 09:37:32 -05002531#Subtopic Mask_Filter_Methods
2532#Line # get and set Mask_Filter ##
Cary Clark8032b982017-07-28 11:04:54 -04002533
Cary Clarkce101242017-09-01 15:51:02 -04002534Mask_Filter uses coverage of the shape drawn to create Mask_Alpha.
Mike Reed8ad91a92018-01-19 19:09:32 -05002535Mask_Filter takes a Mask, and returns a Mask.
Cary Clark6fc50412017-09-21 12:31:06 -04002536
2537Mask_Filter may change the geometry and transparency of the shape, such as
2538creating a blur effect. Set Mask_Filter to nullptr to prevent Mask_Filter from
2539modifying the draw.
Cary Clark8032b982017-07-28 11:04:54 -04002540
2541#Example
2542 void draw(SkCanvas* canvas) {
2543 SkPaint paint;
Cary Clark681287e2018-03-16 11:34:15 -04002544 paint.setMaskFilter(SkMaskFilter::MakeBlur(kSolid_SkBlurStyle, 3));
Cary Clark8032b982017-07-28 11:04:54 -04002545 canvas->drawRect(SkRect::MakeXYWH(40, 40, 175, 175), paint);
2546 }
2547##
2548
2549#Method SkMaskFilter* getMaskFilter() const
2550
Cary Clarkab2621d2018-01-30 10:08:57 -05002551#In Mask_Filter_Methods
2552#Line # returns Mask_Filter, alterations to Mask_Alpha ##
Cary Clark09d80c02018-10-31 12:14:03 -04002553#Populate
Herb Derbyfcac00f2018-05-01 11:57:56 -04002554
Cary Clark09d80c02018-10-31 12:14:03 -04002555#Example
Cary Clark8032b982017-07-28 11:04:54 -04002556 void draw(SkCanvas* canvas) {
2557 SkPaint paint;
2558 SkDebugf("nullptr %c= mask filter\n", paint.getMaskFilter() ? '!' : '=');
Cary Clark681287e2018-03-16 11:34:15 -04002559 paint.setMaskFilter(SkMaskFilter::MakeBlur(kOuter_SkBlurStyle, 3));
Cary Clark8032b982017-07-28 11:04:54 -04002560 SkDebugf("nullptr %c= mask filter\n", paint.getMaskFilter() ? '!' : '=');
2561 }
2562
2563 #StdOut
2564 nullptr == mask filter
2565 nullptr != mask filter
2566 ##
2567 ##
2568
2569##
2570
2571#Method sk_sp<SkMaskFilter> refMaskFilter() const
2572
Cary Clarkab2621d2018-01-30 10:08:57 -05002573#In Mask_Filter_Methods
2574#Line # references Mask_Filter, alterations to Mask_Alpha ##
Cary Clark09d80c02018-10-31 12:14:03 -04002575#Populate
Cary Clark6fc50412017-09-21 12:31:06 -04002576
Cary Clark09d80c02018-10-31 12:14:03 -04002577#Example
Cary Clark8032b982017-07-28 11:04:54 -04002578 void draw(SkCanvas* canvas) {
2579 SkPaint paint1, paint2;
Cary Clark681287e2018-03-16 11:34:15 -04002580 paint1.setMaskFilter(SkMaskFilter::MakeBlur(kNormal_SkBlurStyle, 1));
Cary Clark8032b982017-07-28 11:04:54 -04002581 SkDebugf("mask filter unique: %s\n", paint1.getMaskFilter()->unique() ? "true" : "false");
2582 paint2.setMaskFilter(paint1.refMaskFilter());
2583 SkDebugf("mask filter unique: %s\n", paint1.getMaskFilter()->unique() ? "true" : "false");
2584 }
2585
2586 #StdOut
2587 mask filter unique: true
2588 mask filter unique: false
2589 ##
2590 ##
2591
2592##
2593
2594#Method void setMaskFilter(sk_sp<SkMaskFilter> maskFilter)
2595
Cary Clarkab2621d2018-01-30 10:08:57 -05002596#In Mask_Filter_Methods
2597#Line # sets Mask_Filter, alterations to Mask_Alpha ##
Cary Clark09d80c02018-10-31 12:14:03 -04002598#Populate
Cary Clark6fc50412017-09-21 12:31:06 -04002599
Cary Clark09d80c02018-10-31 12:14:03 -04002600#Example
Cary Clark8032b982017-07-28 11:04:54 -04002601 void draw(SkCanvas* canvas) {
2602 SkPaint paint;
2603 paint.setStyle(SkPaint::kStroke_Style);
2604 paint.setStrokeWidth(10);
Cary Clark681287e2018-03-16 11:34:15 -04002605 paint.setMaskFilter(SkMaskFilter::MakeBlur(kNormal_SkBlurStyle, 10));
Cary Clark8032b982017-07-28 11:04:54 -04002606 canvas->drawRect(SkRect::MakeXYWH(40, 40, 175, 175), paint);
2607 }
2608 ##
2609
2610##
2611
Cary Clark08895c42018-02-01 09:37:32 -05002612#Subtopic Mask_Filter_Methods ##
Cary Clark8032b982017-07-28 11:04:54 -04002613# ------------------------------------------------------------------------------
Cary Clark08895c42018-02-01 09:37:32 -05002614#Subtopic Typeface_Methods
2615#Line # get and set Typeface ##
Cary Clark8032b982017-07-28 11:04:54 -04002616
2617Typeface identifies the font used when drawing and measuring text.
2618Typeface may be specified by name, from a file, or from a data stream.
2619The default Typeface defers to the platform-specific default font
2620implementation.
2621
2622#Example
2623#Height 100
2624 void draw(SkCanvas* canvas) {
2625 SkPaint paint;
Ben Wagner700ff172017-11-08 15:37:22 -05002626 paint.setTypeface(SkTypeface::MakeFromName(nullptr, SkFontStyle()));
Cary Clark8032b982017-07-28 11:04:54 -04002627 paint.setAntiAlias(true);
2628 paint.setTextSize(36);
2629 canvas->drawString("A Big Hello!", 10, 40, paint);
2630 paint.setTypeface(nullptr);
2631 paint.setFakeBoldText(true);
2632 canvas->drawString("A Big Hello!", 10, 80, paint);
2633 }
2634##
2635
2636#Method SkTypeface* getTypeface() const
2637
Cary Clarkab2621d2018-01-30 10:08:57 -05002638#In Typeface_Methods
2639#Line # returns Typeface, font description ##
Cary Clark09d80c02018-10-31 12:14:03 -04002640#Populate
Herb Derbyfcac00f2018-05-01 11:57:56 -04002641
Cary Clark09d80c02018-10-31 12:14:03 -04002642#Example
Cary Clark8032b982017-07-28 11:04:54 -04002643 void draw(SkCanvas* canvas) {
2644 SkPaint paint;
2645 SkDebugf("nullptr %c= typeface\n", paint.getTypeface() ? '!' : '=');
Cary Clark71961fb2018-01-05 14:21:59 -05002646 paint.setTypeface(SkTypeface::MakeFromName("monospace", SkFontStyle()));
Cary Clark8032b982017-07-28 11:04:54 -04002647 SkDebugf("nullptr %c= typeface\n", paint.getTypeface() ? '!' : '=');
2648 }
2649
2650 #StdOut
2651 nullptr == typeface
2652 nullptr != typeface
2653 ##
2654 ##
2655
2656##
2657
2658#Method sk_sp<SkTypeface> refTypeface() const
2659
Cary Clarkab2621d2018-01-30 10:08:57 -05002660#In Typeface_Methods
2661#Line # references Typeface, font description ##
Cary Clark09d80c02018-10-31 12:14:03 -04002662#Populate
Cary Clark8032b982017-07-28 11:04:54 -04002663
Cary Clark09d80c02018-10-31 12:14:03 -04002664#Example
Cary Clark8032b982017-07-28 11:04:54 -04002665 void draw(SkCanvas* canvas) {
2666 SkPaint paint1, paint2;
Herb Derbyfcac00f2018-05-01 11:57:56 -04002667 paint1.setTypeface(SkTypeface::MakeFromName("monospace",
Cary Clark8032b982017-07-28 11:04:54 -04002668 SkFontStyle(SkFontStyle::kNormal_Weight, SkFontStyle::kNormal_Width,
2669 SkFontStyle::kItalic_Slant)));
2670 SkDebugf("typeface1 %c= typeface2\n",
2671 paint1.getTypeface() == paint2.getTypeface() ? '=' : '!');
2672 paint2.setTypeface(paint1.refTypeface());
2673 SkDebugf("typeface1 %c= typeface2\n",
2674 paint1.getTypeface() == paint2.getTypeface() ? '=' : '!');
2675 }
2676
2677 #StdOut
2678 typeface1 != typeface2
2679 typeface1 == typeface2
2680 ##
2681 ##
2682
2683##
2684
2685#Method void setTypeface(sk_sp<SkTypeface> typeface)
2686
Cary Clarkab2621d2018-01-30 10:08:57 -05002687#In Typeface_Methods
2688#Line # sets Typeface, font description ##
Cary Clark09d80c02018-10-31 12:14:03 -04002689#Populate
Cary Clark8032b982017-07-28 11:04:54 -04002690
Cary Clark09d80c02018-10-31 12:14:03 -04002691#Example
Cary Clark8032b982017-07-28 11:04:54 -04002692 #Height 64
2693 void draw(SkCanvas* canvas) {
2694 SkPaint paint;
Cary Clark71961fb2018-01-05 14:21:59 -05002695 paint.setTypeface(SkTypeface::MakeFromName("monospace", SkFontStyle()));
2696 canvas->drawString("hamburgerfons", 10, 30, paint);
Cary Clark8032b982017-07-28 11:04:54 -04002697 paint.setTypeface(nullptr);
Cary Clark71961fb2018-01-05 14:21:59 -05002698 canvas->drawString("hamburgerfons", 10, 50, paint);
Cary Clark8032b982017-07-28 11:04:54 -04002699 }
2700 ##
2701
2702##
2703
Cary Clark08895c42018-02-01 09:37:32 -05002704#Subtopic Typeface_Methods ##
Cary Clark8032b982017-07-28 11:04:54 -04002705# ------------------------------------------------------------------------------
Cary Clark08895c42018-02-01 09:37:32 -05002706#Subtopic Image_Filter_Methods
2707#Line # get and set Image_Filter ##
Cary Clark8032b982017-07-28 11:04:54 -04002708
2709Image_Filter operates on the pixel representation of the shape, as modified by Paint
2710with Blend_Mode set to SkBlendMode::kSrcOver. Image_Filter creates a new bitmap,
2711which is drawn to the device using the set Blend_Mode.
Cary Clark6fc50412017-09-21 12:31:06 -04002712
Cary Clark8032b982017-07-28 11:04:54 -04002713Image_Filter is higher level than Mask_Filter; for instance, an Image_Filter
Cary Clarkce101242017-09-01 15:51:02 -04002714can operate on all channels of Color, while Mask_Filter generates Alpha only.
Cary Clark8032b982017-07-28 11:04:54 -04002715Image_Filter operates independently of and can be used in combination with
Mike Reed8ad91a92018-01-19 19:09:32 -05002716Mask_Filter.
Cary Clark8032b982017-07-28 11:04:54 -04002717
2718#Example
2719 #ToDo explain why the two draws are so different ##
Cary Clark81abc432018-06-25 16:30:08 -04002720 #Function
2721 ###$
2722 #include "SkBlurImageFilter.h"
2723 $$$#
2724 ##
Cary Clark8032b982017-07-28 11:04:54 -04002725 void draw(SkCanvas* canvas) {
2726 SkPaint paint;
2727 paint.setStyle(SkPaint::kStroke_Style);
2728 paint.setStrokeWidth(2);
2729 SkRegion region;
2730 region.op( 10, 10, 50, 50, SkRegion::kUnion_Op);
2731 region.op( 10, 50, 90, 90, SkRegion::kUnion_Op);
Cary Clarka560c472017-11-27 10:44:06 -05002732 paint.setImageFilter(SkBlurImageFilter::Make(5.0f, 5.0f, nullptr));
Cary Clark8032b982017-07-28 11:04:54 -04002733 canvas->drawRegion(region, paint);
2734 paint.setImageFilter(nullptr);
Cary Clarka7b84c52018-03-18 11:46:54 -04002735 paint.setMaskFilter(SkMaskFilter::MakeBlur(kNormal_SkBlurStyle, 5));
Cary Clark8032b982017-07-28 11:04:54 -04002736 canvas->translate(100, 100);
2737 canvas->drawRegion(region, paint);
2738 }
2739##
2740
2741#Method SkImageFilter* getImageFilter() const
2742
Cary Clarkab2621d2018-01-30 10:08:57 -05002743#In Image_Filter_Methods
2744#Line # returns Image_Filter, alter pixels; blur ##
Cary Clark09d80c02018-10-31 12:14:03 -04002745#Populate
Herb Derbyfcac00f2018-05-01 11:57:56 -04002746
Cary Clark09d80c02018-10-31 12:14:03 -04002747#Example
Cary Clark81abc432018-06-25 16:30:08 -04002748 #Function
2749 ###$
2750 #include "SkBlurImageFilter.h"
2751 $$$#
2752 ##
Cary Clark8032b982017-07-28 11:04:54 -04002753 void draw(SkCanvas* canvas) {
2754 SkPaint paint;
2755 SkDebugf("nullptr %c= image filter\n", paint.getImageFilter() ? '!' : '=');
Cary Clarka560c472017-11-27 10:44:06 -05002756 paint.setImageFilter(SkBlurImageFilter::Make(kOuter_SkBlurStyle, 3, nullptr, nullptr));
Cary Clark8032b982017-07-28 11:04:54 -04002757 SkDebugf("nullptr %c= image filter\n", paint.getImageFilter() ? '!' : '=');
2758 }
2759
2760 #StdOut
2761 nullptr == image filter
2762 nullptr != image filter
2763 ##
2764 ##
2765
2766##
2767
2768#Method sk_sp<SkImageFilter> refImageFilter() const
2769
Cary Clarkab2621d2018-01-30 10:08:57 -05002770#In Image_Filter_Methods
2771#Line # references Image_Filter, alter pixels; blur ##
Cary Clark09d80c02018-10-31 12:14:03 -04002772#Populate
Cary Clark8032b982017-07-28 11:04:54 -04002773
Cary Clark09d80c02018-10-31 12:14:03 -04002774#Example
Cary Clark8032b982017-07-28 11:04:54 -04002775 void draw(SkCanvas* canvas) {
2776 SkPaint paint1, paint2;
2777 paint1.setImageFilter(SkOffsetImageFilter::Make(25, 25, nullptr));
2778 SkDebugf("image filter unique: %s\n", paint1.getImageFilter()->unique() ? "true" : "false");
2779 paint2.setImageFilter(paint1.refImageFilter());
2780 SkDebugf("image filter unique: %s\n", paint1.getImageFilter()->unique() ? "true" : "false");
2781 }
2782
2783 #StdOut
2784 image filter unique: true
2785 image filter unique: false
2786 ##
2787 ##
2788
2789##
2790
2791#Method void setImageFilter(sk_sp<SkImageFilter> imageFilter)
2792
Cary Clarkab2621d2018-01-30 10:08:57 -05002793#In Image_Filter_Methods
2794#Line # sets Image_Filter, alter pixels; blur ##
Cary Clark09d80c02018-10-31 12:14:03 -04002795#Populate
Cary Clark6fc50412017-09-21 12:31:06 -04002796
Cary Clark09d80c02018-10-31 12:14:03 -04002797#Example
Cary Clark8032b982017-07-28 11:04:54 -04002798 #Height 160
2799 void draw(SkCanvas* canvas) {
2800 SkBitmap bitmap;
2801 bitmap.allocN32Pixels(100, 100);
2802 SkCanvas offscreen(bitmap);
2803 SkPaint paint;
2804 paint.setAntiAlias(true);
2805 paint.setColor(SK_ColorWHITE);
2806 paint.setTextSize(96);
2807 offscreen.clear(0);
2808 offscreen.drawString("e", 20, 70, paint);
2809 paint.setImageFilter(
2810 SkLightingImageFilter::MakePointLitDiffuse(SkPoint3::Make(80, 100, 10),
2811 SK_ColorWHITE, 1, 2, nullptr, nullptr));
2812 canvas->drawBitmap(bitmap, 0, 0, &paint);
2813 }
2814 ##
2815
2816##
2817
Cary Clark08895c42018-02-01 09:37:32 -05002818#Subtopic Image_Filter_Methods ##
Cary Clark8032b982017-07-28 11:04:54 -04002819# ------------------------------------------------------------------------------
Cary Clark08895c42018-02-01 09:37:32 -05002820#Subtopic Draw_Looper_Methods
2821#Line # get and set Draw_Looper ##
Cary Clark8032b982017-07-28 11:04:54 -04002822
2823Draw_Looper sets a modifier that communicates state from one Draw_Layer
2824to another to construct the draw.
Cary Clark6fc50412017-09-21 12:31:06 -04002825
Cary Clark8032b982017-07-28 11:04:54 -04002826Draw_Looper draws one or more times, modifying the canvas and paint each time.
2827Draw_Looper may be used to draw multiple colors or create a colored shadow.
Herb Derbyfcac00f2018-05-01 11:57:56 -04002828Set Draw_Looper to nullptr to prevent Draw_Looper from modifying the draw.
Cary Clark8032b982017-07-28 11:04:54 -04002829
2830#Example
2831#Height 128
2832 void draw(SkCanvas* canvas) {
2833 SkLayerDrawLooper::LayerInfo info;
2834 info.fPaintBits = (SkLayerDrawLooper::BitFlags) SkLayerDrawLooper::kColorFilter_Bit;
2835 info.fColorMode = SkBlendMode::kSrc;
2836 SkLayerDrawLooper::Builder looperBuilder;
2837 SkPaint* loopPaint = looperBuilder.addLayer(info);
2838 loopPaint->setColor(SK_ColorRED);
2839 info.fOffset.set(20, 20);
2840 loopPaint = looperBuilder.addLayer(info);
2841 loopPaint->setColor(SK_ColorBLUE);
2842 SkPaint paint;
2843 paint.setDrawLooper(looperBuilder.detach());
2844 canvas->drawCircle(50, 50, 50, paint);
2845 }
2846
2847##
2848
2849#Method SkDrawLooper* getDrawLooper() const
2850
Cary Clarkab2621d2018-01-30 10:08:57 -05002851#In Draw_Looper_Methods
2852#Line # returns Draw_Looper, multiple layers ##
Cary Clark09d80c02018-10-31 12:14:03 -04002853#Populate
Herb Derbyfcac00f2018-05-01 11:57:56 -04002854
Cary Clark09d80c02018-10-31 12:14:03 -04002855#Example
Cary Clark8032b982017-07-28 11:04:54 -04002856 void draw(SkCanvas* canvas) {
2857 SkPaint paint;
2858 SkDebugf("nullptr %c= draw looper\n", paint.getDrawLooper() ? '!' : '=');
2859 SkLayerDrawLooper::Builder looperBuilder;
2860 paint.setDrawLooper(looperBuilder.detach());
2861 SkDebugf("nullptr %c= draw looper\n", paint.getDrawLooper() ? '!' : '=');
2862 }
2863
2864 #StdOut
2865 nullptr == draw looper
2866 nullptr != draw looper
2867 ##
2868 ##
2869
2870##
2871
2872#Method sk_sp<SkDrawLooper> refDrawLooper() const
2873
Cary Clarkab2621d2018-01-30 10:08:57 -05002874#In Draw_Looper_Methods
2875#Line # references Draw_Looper, multiple layers ##
Cary Clark09d80c02018-10-31 12:14:03 -04002876#Populate
Cary Clark8032b982017-07-28 11:04:54 -04002877
Cary Clark09d80c02018-10-31 12:14:03 -04002878#Example
Cary Clark8032b982017-07-28 11:04:54 -04002879 void draw(SkCanvas* canvas) {
2880 SkPaint paint1, paint2;
2881 SkLayerDrawLooper::Builder looperBuilder;
2882 paint1.setDrawLooper(looperBuilder.detach());
2883 SkDebugf("draw looper unique: %s\n", paint1.getDrawLooper()->unique() ? "true" : "false");
2884 paint2.setDrawLooper(paint1.refDrawLooper());
2885 SkDebugf("draw looper unique: %s\n", paint1.getDrawLooper()->unique() ? "true" : "false");
2886 }
2887
2888 #StdOut
2889 draw looper unique: true
2890 draw looper unique: false
2891 ##
2892 ##
2893
2894##
2895
2896#Method SkDrawLooper* getLooper() const
Cary Clark4855f782018-02-06 09:41:53 -05002897#Bug 6259
Cary Clark8032b982017-07-28 11:04:54 -04002898#Deprecated
Cary Clark8032b982017-07-28 11:04:54 -04002899##
2900
2901#Method void setDrawLooper(sk_sp<SkDrawLooper> drawLooper)
Cary Clarkab2621d2018-01-30 10:08:57 -05002902#In Draw_Looper_Methods
2903#Line # sets Draw_Looper, multiple layers ##
Cary Clark09d80c02018-10-31 12:14:03 -04002904#Populate
Cary Clark6fc50412017-09-21 12:31:06 -04002905
Cary Clark09d80c02018-10-31 12:14:03 -04002906#Example
Cary Clark8032b982017-07-28 11:04:54 -04002907 #Height 128
2908 void draw(SkCanvas* canvas) {
2909 SkPaint paint;
2910 paint.setDrawLooper(SkBlurDrawLooper::Make(0x7FFF0000, 4, -5, -10));
2911 paint.setStyle(SkPaint::kStroke_Style);
2912 paint.setStrokeWidth(10);
2913 paint.setAntiAlias(true);
2914 paint.setColor(0x7f0000ff);
2915 canvas->drawCircle(70, 70, 50, paint);
2916 }
2917 ##
2918
2919##
2920
2921#Method void setLooper(sk_sp<SkDrawLooper> drawLooper)
Cary Clark4855f782018-02-06 09:41:53 -05002922#Bug 6259
Cary Clark8032b982017-07-28 11:04:54 -04002923#Deprecated
Cary Clark8032b982017-07-28 11:04:54 -04002924##
2925
Cary Clark08895c42018-02-01 09:37:32 -05002926#Subtopic Draw_Looper_Methods ##
Cary Clark4855f782018-02-06 09:41:53 -05002927
Cary Clark08895c42018-02-01 09:37:32 -05002928#Subtopic Text_Size
2929#Line # overall height in points ##
Cary Clark8032b982017-07-28 11:04:54 -04002930
2931Text_Size adjusts the overall text size in points.
2932Text_Size can be set to any positive value or zero.
2933Text_Size defaults to 12.
2934Set SkPaintDefaults_TextSize at compile time to change the default setting.
2935
2936#Example
2937#Height 135
2938 void draw(SkCanvas* canvas) {
2939 SkPaint paint;
2940 canvas->drawString("12 point", 10, 20, paint);
2941 paint.setTextSize(24);
2942 canvas->drawString("24 point", 10, 60, paint);
2943 paint.setTextSize(48);
2944 canvas->drawString("48 point", 10, 120, paint);
2945 }
2946##
2947
2948#Method SkScalar getTextSize() const
2949
Cary Clarkab2621d2018-01-30 10:08:57 -05002950#In Text_Size
2951#Line # returns text size in points ##
Cary Clark09d80c02018-10-31 12:14:03 -04002952#Populate
Cary Clark8032b982017-07-28 11:04:54 -04002953
Cary Clark09d80c02018-10-31 12:14:03 -04002954#Example
Cary Clark8032b982017-07-28 11:04:54 -04002955 SkPaint paint;
2956 SkDebugf("12 %c= default text size\n", 12 == paint.getTextSize() ? '=' : '!');
2957 ##
2958
2959##
2960
2961#Method void setTextSize(SkScalar textSize)
2962
Cary Clarkab2621d2018-01-30 10:08:57 -05002963#In Text_Size
2964#Line # sets text size in points ##
Cary Clark09d80c02018-10-31 12:14:03 -04002965#Populate
Herb Derbyfcac00f2018-05-01 11:57:56 -04002966
Cary Clark09d80c02018-10-31 12:14:03 -04002967#Example
Cary Clark8032b982017-07-28 11:04:54 -04002968 SkPaint paint;
2969 SkDebugf("12 %c= text size\n", 12 == paint.getTextSize() ? '=' : '!');
2970 paint.setTextSize(-20);
2971 SkDebugf("12 %c= text size\n", 12 == paint.getTextSize() ? '=' : '!');
2972 ##
2973
2974##
2975
Cary Clark08895c42018-02-01 09:37:32 -05002976#Subtopic Text_Size ##
Cary Clark8032b982017-07-28 11:04:54 -04002977# ------------------------------------------------------------------------------
Cary Clark08895c42018-02-01 09:37:32 -05002978#Subtopic Text_Scale_X
2979#Line # text horizontal scale ##
Cary Clark8032b982017-07-28 11:04:54 -04002980
2981Text_Scale_X adjusts the text horizontal scale.
2982Text scaling approximates condensed and expanded type faces when the actual face
2983is not available.
2984Text_Scale_X can be set to any value.
2985Text_Scale_X defaults to 1.
2986
2987#Example
2988#Height 128
2989 void draw(SkCanvas* canvas) {
2990 SkPaint paint;
2991 paint.setAntiAlias(true);
2992 paint.setTextSize(24);
2993 paint.setTextScaleX(.8f);
2994 canvas->drawString("narrow", 10, 20, paint);
2995 paint.setTextScaleX(1);
2996 canvas->drawString("normal", 10, 60, paint);
2997 paint.setTextScaleX(1.2f);
2998 canvas->drawString("wide", 10, 100, paint);
2999 }
3000##
3001
3002#Method SkScalar getTextScaleX() const
3003
Cary Clarkab2621d2018-01-30 10:08:57 -05003004#In Text_Scale_X
3005#Line # returns the text horizontal scale; condensed text ##
Cary Clark09d80c02018-10-31 12:14:03 -04003006#Populate
Cary Clark8032b982017-07-28 11:04:54 -04003007
Cary Clark09d80c02018-10-31 12:14:03 -04003008#Example
Cary Clark8032b982017-07-28 11:04:54 -04003009 SkPaint paint;
3010 SkDebugf("1 %c= default text scale x\n", 1 == paint.getTextScaleX() ? '=' : '!');
3011 ##
3012
3013##
3014
3015
3016#Method void setTextScaleX(SkScalar scaleX)
3017
Cary Clarkab2621d2018-01-30 10:08:57 -05003018#In Text_Scale_X
3019#Line # sets the text horizontal scale; condensed text ##
Cary Clark09d80c02018-10-31 12:14:03 -04003020#Populate
Herb Derbyfcac00f2018-05-01 11:57:56 -04003021
Cary Clark09d80c02018-10-31 12:14:03 -04003022#Example
Cary Clark8032b982017-07-28 11:04:54 -04003023 SkPaint paint;
3024 paint.setTextScaleX(0.f / 0.f);
3025 SkDebugf("text scale %s-a-number\n", SkScalarIsNaN(paint.getTextScaleX()) ? "not" : "is");
3026 ##
3027
3028##
3029
Cary Clark08895c42018-02-01 09:37:32 -05003030#Subtopic Text_Scale_X ##
Cary Clark8032b982017-07-28 11:04:54 -04003031
Cary Clark08895c42018-02-01 09:37:32 -05003032#Subtopic Text_Skew_X
3033#Line # text horizontal slant ##
Cary Clark8032b982017-07-28 11:04:54 -04003034
3035
3036Text_Skew_X adjusts the text horizontal slant.
3037Text skewing approximates italic and oblique type faces when the actual face
3038is not available.
3039Text_Skew_X can be set to any value.
3040Text_Skew_X defaults to 0.
3041
3042#Example
3043#Height 128
3044 void draw(SkCanvas* canvas) {
3045 SkPaint paint;
3046 paint.setAntiAlias(true);
3047 paint.setTextSize(24);
3048 paint.setTextSkewX(-.25f);
3049 canvas->drawString("right-leaning", 10, 100, paint);
3050 paint.setTextSkewX(0);
3051 canvas->drawString("normal", 10, 60, paint);
3052 paint.setTextSkewX(.25f);
3053 canvas->drawString("left-leaning", 10, 20, paint);
3054 }
3055##
3056
3057#Method SkScalar getTextSkewX() const
3058
Cary Clarkab2621d2018-01-30 10:08:57 -05003059#In Text_Skew_X
3060#Line # returns the text horizontal skew; oblique text ##
Cary Clark09d80c02018-10-31 12:14:03 -04003061#Populate
Cary Clark8032b982017-07-28 11:04:54 -04003062
Cary Clark09d80c02018-10-31 12:14:03 -04003063#Example
Cary Clark8032b982017-07-28 11:04:54 -04003064 SkPaint paint;
3065 SkDebugf("0 %c= default text skew x\n", 0 == paint.getTextSkewX() ? '=' : '!');
3066 ##
3067
3068##
3069
3070#Method void setTextSkewX(SkScalar skewX)
3071
Cary Clarkab2621d2018-01-30 10:08:57 -05003072#In Text_Skew_X
3073#Line # sets the text horizontal skew; oblique text ##
Cary Clark09d80c02018-10-31 12:14:03 -04003074#Populate
Cary Clark8032b982017-07-28 11:04:54 -04003075
Cary Clark09d80c02018-10-31 12:14:03 -04003076#Example
Cary Clark8032b982017-07-28 11:04:54 -04003077 SkPaint paint;
3078 paint.setTextScaleX(1.f / 0.f);
3079 SkDebugf("text scale %s-finite\n", SkScalarIsFinite(paint.getTextScaleX()) ? "is" : "not");
3080 ##
3081
3082##
3083
Cary Clark08895c42018-02-01 09:37:32 -05003084#Subtopic Text_Skew_X ##
Cary Clark8032b982017-07-28 11:04:54 -04003085
3086# ------------------------------------------------------------------------------
Cary Clark08895c42018-02-01 09:37:32 -05003087#Subtopic Text_Encoding
3088#Line # text encoded as characters or Glyphs ##
Cary Clark8032b982017-07-28 11:04:54 -04003089
3090#Enum TextEncoding
Cary Clark08895c42018-02-01 09:37:32 -05003091#Line # character or glyph encoded size ##
Cary Clark8032b982017-07-28 11:04:54 -04003092
3093#Code
Cary Clarka90ea222018-10-16 10:30:28 -04003094#Populate
Cary Clark8032b982017-07-28 11:04:54 -04003095##
3096
Cary Clark6fc50412017-09-21 12:31:06 -04003097TextEncoding determines whether text specifies character codes and their encoded
Cary Clarkbc5697d2017-10-04 14:31:33 -04003098size, or glyph indices. Characters are encoded as specified by the
Cary Clark682c58d2018-05-16 07:07:07 -04003099#A Unicode standard # https://unicode.org/standard/standard.html ##
Cary Clark6fc50412017-09-21 12:31:06 -04003100.
3101
Cary Clark8032b982017-07-28 11:04:54 -04003102Character codes encoded size are specified by UTF-8, UTF-16, or UTF-32.
Cary Clarkbc5697d2017-10-04 14:31:33 -04003103All character code formats are able to represent all of Unicode, differing only
Cary Clark8032b982017-07-28 11:04:54 -04003104in the total storage required.
3105
Cary Clark6fc50412017-09-21 12:31:06 -04003106#A UTF-8 (RFC 3629) # https://tools.ietf.org/html/rfc3629 ##
3107 encodes each character as one or more 8-bit bytes.
3108
3109#A UTF-16 (RFC 2781) # https://tools.ietf.org/html/rfc2781 ##
3110 encodes each character as one or two 16-bit words.
3111
Cary Clark682c58d2018-05-16 07:07:07 -04003112#A UTF-32 # https://www.unicode.org/versions/Unicode5.0.0/ch03.pdf ##
Cary Clark6fc50412017-09-21 12:31:06 -04003113 encodes each character as one 32-bit word.
Cary Clark8032b982017-07-28 11:04:54 -04003114
Herb Derbyfcac00f2018-05-01 11:57:56 -04003115Font_Manager uses font data to convert character code points into glyph indices.
Cary Clark8032b982017-07-28 11:04:54 -04003116A glyph index is a 16-bit word.
3117
3118TextEncoding is set to kUTF8_TextEncoding by default.
3119
3120#Const kUTF8_TextEncoding 0
Cary Clark682c58d2018-05-16 07:07:07 -04003121#Line # uses bytes to represent UTF-8 or ASCII ##
Cary Clark8032b982017-07-28 11:04:54 -04003122##
3123#Const kUTF16_TextEncoding 1
Cary Clark682c58d2018-05-16 07:07:07 -04003124#Line # uses two byte words to represent most of Unicode ##
Cary Clark8032b982017-07-28 11:04:54 -04003125##
3126#Const kUTF32_TextEncoding 2
Cary Clark682c58d2018-05-16 07:07:07 -04003127#Line # uses four byte words to represent all of Unicode ##
Cary Clark8032b982017-07-28 11:04:54 -04003128##
3129#Const kGlyphID_TextEncoding 3
Cary Clark682c58d2018-05-16 07:07:07 -04003130#Line # uses two byte words to represent glyph indices ##
Cary Clark8032b982017-07-28 11:04:54 -04003131##
3132
3133#Enum ##
3134
3135#Example
3136#Height 128
3137#Description
Cary Clarkbc5697d2017-10-04 14:31:33 -04003138First line is encoded in UTF-8.
3139Second line is encoded in UTF-16.
3140Third line is encoded in UTF-32.
Cary Clark682c58d2018-05-16 07:07:07 -04003141Fourth line has 16-bit glyph indices.
Cary Clark8032b982017-07-28 11:04:54 -04003142##
3143void draw(SkCanvas* canvas) {
3144 SkPaint paint;
3145 const char hello8[] = "Hello" "\xE2" "\x98" "\xBA";
3146 const uint16_t hello16[] = { 'H', 'e', 'l', 'l', 'o', 0x263A };
3147 const uint32_t hello32[] = { 'H', 'e', 'l', 'l', 'o', 0x263A };
3148 paint.setTextSize(24);
3149 canvas->drawText(hello8, sizeof(hello8) - 1, 10, 30, paint);
3150 paint.setTextEncoding(SkPaint::kUTF16_TextEncoding);
3151 canvas->drawText(hello16, sizeof(hello16), 10, 60, paint);
3152 paint.setTextEncoding(SkPaint::kUTF32_TextEncoding);
3153 canvas->drawText(hello32, sizeof(hello32), 10, 90, paint);
3154 uint16_t glyphs[SK_ARRAY_COUNT(hello32)];
3155 paint.textToGlyphs(hello32, sizeof(hello32), glyphs);
3156 paint.setTextEncoding(SkPaint::kGlyphID_TextEncoding);
3157 canvas->drawText(glyphs, sizeof(glyphs), 10, 120, paint);
3158}
3159##
3160
3161#Method TextEncoding getTextEncoding() const
3162
Cary Clarkab2621d2018-01-30 10:08:57 -05003163#In Text_Encoding
3164#Line # returns character or glyph encoded size ##
Cary Clark09d80c02018-10-31 12:14:03 -04003165#Populate
Cary Clark8032b982017-07-28 11:04:54 -04003166
Cary Clark09d80c02018-10-31 12:14:03 -04003167#Example
Cary Clark8032b982017-07-28 11:04:54 -04003168 SkPaint paint;
Herb Derbyfcac00f2018-05-01 11:57:56 -04003169 SkDebugf("kUTF8_TextEncoding %c= text encoding\n",
Cary Clark8032b982017-07-28 11:04:54 -04003170 SkPaint::kUTF8_TextEncoding == paint.getTextEncoding() ? '=' : '!');
3171 paint.setTextEncoding(SkPaint::kGlyphID_TextEncoding);
Herb Derbyfcac00f2018-05-01 11:57:56 -04003172 SkDebugf("kGlyphID_TextEncoding %c= text encoding\n",
Cary Clark8032b982017-07-28 11:04:54 -04003173 SkPaint::kGlyphID_TextEncoding == paint.getTextEncoding() ? '=' : '!');
3174
3175 #StdOut
3176 kUTF8_TextEncoding == text encoding
3177 kGlyphID_TextEncoding == text encoding
3178 ##
3179 ##
3180
3181##
3182
3183
3184#Method void setTextEncoding(TextEncoding encoding)
3185
Cary Clarkab2621d2018-01-30 10:08:57 -05003186#In Text_Encoding
3187#Line # sets character or glyph encoded size ##
Cary Clark09d80c02018-10-31 12:14:03 -04003188#Populate
Cary Clark8032b982017-07-28 11:04:54 -04003189
Cary Clark09d80c02018-10-31 12:14:03 -04003190#Example
Cary Clark8032b982017-07-28 11:04:54 -04003191 SkPaint paint;
3192 paint.setTextEncoding((SkPaint::TextEncoding) 4);
Cary Clark75fd4492018-06-20 12:45:16 -04003193 SkDebugf("4 %c= text encoding\n", (SkPaint::TextEncoding) 4 == paint.getTextEncoding() ? '=' : '!');
Cary Clark8032b982017-07-28 11:04:54 -04003194
3195 #StdOut
3196 4 != text encoding
3197 ##
3198 ##
3199
3200##
3201
Cary Clark7e69c8f2018-11-06 20:40:45 -05003202#Typedef typedef SkFontMetrics FontMetrics
3203##
3204
Cary Clark08895c42018-02-01 09:37:32 -05003205#Subtopic Text_Encoding ##
Cary Clark8032b982017-07-28 11:04:54 -04003206# ------------------------------------------------------------------------------
Cary Clark08895c42018-02-01 09:37:32 -05003207#Subtopic Font_Metrics
Cary Clark8032b982017-07-28 11:04:54 -04003208
Cary Clark7e69c8f2018-11-06 20:40:45 -05003209#Method SkScalar getFontMetrics(SkFontMetrics* metrics) const
Cary Clark8032b982017-07-28 11:04:54 -04003210
Cary Clarkab2621d2018-01-30 10:08:57 -05003211#In Font_Metrics
3212#Line # returns Typeface metrics scaled by text size ##
Cary Clark09d80c02018-10-31 12:14:03 -04003213#Populate
Cary Clark8032b982017-07-28 11:04:54 -04003214
Cary Clark09d80c02018-10-31 12:14:03 -04003215#Example
Cary Clark8032b982017-07-28 11:04:54 -04003216 #Height 128
3217 void draw(SkCanvas* canvas) {
3218 SkPaint paint;
3219 paint.setTextSize(32);
3220 SkScalar lineHeight = paint.getFontMetrics(nullptr);
3221 canvas->drawString("line 1", 10, 40, paint);
3222 canvas->drawString("line 2", 10, 40 + lineHeight, paint);
Cary Clark8032b982017-07-28 11:04:54 -04003223 }
3224 ##
3225
3226 #SeeAlso Text_Size Typeface Typeface_Methods
3227
3228##
3229
3230
3231#Method SkScalar getFontSpacing() const
3232
Cary Clarkab2621d2018-01-30 10:08:57 -05003233#In Font_Metrics
3234#Line # returns recommended spacing between lines ##
Cary Clark09d80c02018-10-31 12:14:03 -04003235#Populate
Cary Clark8032b982017-07-28 11:04:54 -04003236
Cary Clark09d80c02018-10-31 12:14:03 -04003237#Example
Cary Clark8032b982017-07-28 11:04:54 -04003238 SkPaint paint;
3239 for (SkScalar textSize : { 12, 18, 24, 32 } ) {
3240 paint.setTextSize(textSize);
3241 SkDebugf("textSize: %g fontSpacing: %g\n", textSize, paint.getFontSpacing());
3242 }
3243
3244 #StdOut
3245 textSize: 12 fontSpacing: 13.9688
3246 textSize: 18 fontSpacing: 20.9531
3247 textSize: 24 fontSpacing: 27.9375
3248 textSize: 32 fontSpacing: 37.25
3249 ##
3250 ##
3251
3252##
3253
Cary Clark08895c42018-02-01 09:37:32 -05003254#Subtopic Font_Metrics ##
Cary Clark77b3f3a2018-11-07 14:59:03 -05003255
Cary Clark8032b982017-07-28 11:04:54 -04003256# ------------------------------------------------------------------------------
3257
3258#Method int textToGlyphs(const void* text, size_t byteLength,
3259 SkGlyphID glyphs[]) const
Cary Clark78de7512018-02-07 07:27:09 -05003260#In Utility
Cary Clarkab2621d2018-01-30 10:08:57 -05003261#Line # converts text into glyph indices ##
Cary Clark09d80c02018-10-31 12:14:03 -04003262#Populate
Cary Clark8032b982017-07-28 11:04:54 -04003263
Cary Clark09d80c02018-10-31 12:14:03 -04003264#Example
Cary Clark8032b982017-07-28 11:04:54 -04003265 #Height 64
3266 void draw(SkCanvas* canvas) {
3267 SkPaint paint;
3268 const uint8_t utf8[] = { 0x24, 0xC2, 0xA2, 0xE2, 0x82, 0xAC, 0xC2, 0xA5, 0xC2, 0xA3 };
3269 std::vector<SkGlyphID> glyphs;
3270 int count = paint.textToGlyphs(utf8, sizeof(utf8), nullptr);
3271 glyphs.resize(count);
3272 (void) paint.textToGlyphs(utf8, sizeof(utf8), &glyphs.front());
3273 paint.setTextEncoding(SkPaint::kGlyphID_TextEncoding);
3274 paint.setTextSize(32);
3275 canvas->drawText(&glyphs.front(), glyphs.size() * sizeof(SkGlyphID), 10, 40, paint);
3276 }
3277 ##
3278
3279##
3280
3281#Method int countText(const void* text, size_t byteLength) const
Cary Clark78de7512018-02-07 07:27:09 -05003282#In Utility
Cary Clarkab2621d2018-01-30 10:08:57 -05003283#Line # returns number of Glyphs in text ##
Cary Clark09d80c02018-10-31 12:14:03 -04003284#Populate
Cary Clark8032b982017-07-28 11:04:54 -04003285
Cary Clark09d80c02018-10-31 12:14:03 -04003286#Example
Cary Clark8032b982017-07-28 11:04:54 -04003287 SkPaint paint;
3288 const uint8_t utf8[] = { 0x24, 0xC2, 0xA2, 0xE2, 0x82, 0xAC, 0xC2, 0xA5, 0xC2, 0xA3 };
3289 SkDebugf("count = %d\n", paint.countText(utf8, sizeof(utf8)));
3290
3291 #StdOut
3292 count = 5
3293 ##
3294 ##
3295##
3296
3297# ------------------------------------------------------------------------------
3298
3299#Method bool containsText(const void* text, size_t byteLength) const
Cary Clark78de7512018-02-07 07:27:09 -05003300#In Utility
Cary Clarkab2621d2018-01-30 10:08:57 -05003301#Line # returns if all text corresponds to Glyphs ##
Cary Clark09d80c02018-10-31 12:14:03 -04003302#Populate
Cary Clark8032b982017-07-28 11:04:54 -04003303
Cary Clark09d80c02018-10-31 12:14:03 -04003304#NoExample
Cary Clark8032b982017-07-28 11:04:54 -04003305 #Description
3306 containsText succeeds for degree symbol, but cannot find a glyph index
3307 corresponding to the Unicode surrogate code point.
3308 ##
3309 SkPaint paint;
3310 const uint16_t goodChar = 0x00B0; // degree symbol
3311 const uint16_t badChar = 0xD800; // Unicode surrogate
3312 paint.setTextEncoding(SkPaint::kUTF16_TextEncoding);
Herb Derbyfcac00f2018-05-01 11:57:56 -04003313 SkDebugf("0x%04x %c= has char\n", goodChar,
Cary Clark8032b982017-07-28 11:04:54 -04003314 paint.containsText(&goodChar, 2) ? '=' : '!');
3315 SkDebugf("0x%04x %c= has char\n", badChar,
3316 paint.containsText(&badChar, 2) ? '=' : '!');
3317
3318 #StdOut
3319 0x00b0 == has char
3320 0xd800 != has char
3321 ##
3322 ##
3323
3324 #Example
3325 #Description
3326 containsText returns true that glyph index is greater than zero, not
3327 that it corresponds to an entry in Typeface.
3328 ##
3329 SkPaint paint;
3330 const uint16_t goodGlyph = 511;
3331 const uint16_t zeroGlyph = 0;
3332 const uint16_t badGlyph = 65535; // larger than glyph count in font
3333 paint.setTextEncoding(SkPaint::kGlyphID_TextEncoding);
Herb Derbyfcac00f2018-05-01 11:57:56 -04003334 SkDebugf("0x%04x %c= has glyph\n", goodGlyph,
Cary Clark8032b982017-07-28 11:04:54 -04003335 paint.containsText(&goodGlyph, 2) ? '=' : '!');
3336 SkDebugf("0x%04x %c= has glyph\n", zeroGlyph,
3337 paint.containsText(&zeroGlyph, 2) ? '=' : '!');
3338 SkDebugf("0x%04x %c= has glyph\n", badGlyph,
3339 paint.containsText(&badGlyph, 2) ? '=' : '!');
3340
3341 #StdOut
3342 0x01ff == has glyph
3343 0x0000 != has glyph
3344 0xffff == has glyph
3345 ##
3346 ##
3347
3348#SeeAlso setTextEncoding Typeface
3349
3350##
3351
3352# ------------------------------------------------------------------------------
3353
3354#Method void glyphsToUnichars(const SkGlyphID glyphs[],
3355 int count, SkUnichar text[]) const
Cary Clark78de7512018-02-07 07:27:09 -05003356#In Utility
Cary Clarkab2621d2018-01-30 10:08:57 -05003357#Line # converts Glyphs into text ##
Cary Clark09d80c02018-10-31 12:14:03 -04003358#Populate
Cary Clark8032b982017-07-28 11:04:54 -04003359
Cary Clark09d80c02018-10-31 12:14:03 -04003360#Example
Cary Clark8032b982017-07-28 11:04:54 -04003361 #Height 64
3362 #Description
3363 Convert UTF-8 text to glyphs; then convert glyphs to Unichar code points.
3364 ##
3365 void draw(SkCanvas* canvas) {
3366 SkPaint paint;
3367 const char hello[] = "Hello!";
3368 const int count = sizeof(hello) - 1;
3369 SkGlyphID glyphs[count];
3370 if (count != paint.textToGlyphs(hello, count, glyphs)) {
3371 return;
3372 }
3373 SkUnichar unichars[count];
3374 paint.glyphsToUnichars(glyphs, count, unichars);
3375 paint.setTextEncoding(SkPaint::kUTF32_TextEncoding);
3376 canvas->drawText(unichars, sizeof(unichars), 10, 30, paint);
3377 }
3378 ##
3379
3380##
3381
3382# ------------------------------------------------------------------------------
Cary Clark08895c42018-02-01 09:37:32 -05003383#Subtopic Measure_Text
3384#Line # width, height, bounds of text ##
Cary Clark8032b982017-07-28 11:04:54 -04003385
3386#Method SkScalar measureText(const void* text, size_t length, SkRect* bounds) const
3387
Cary Clarkab2621d2018-01-30 10:08:57 -05003388#In Measure_Text
3389#Line # returns advance width and bounds of text ##
Cary Clark09d80c02018-10-31 12:14:03 -04003390#Populate
Herb Derbyfcac00f2018-05-01 11:57:56 -04003391
Cary Clark09d80c02018-10-31 12:14:03 -04003392#Example
Cary Clark8032b982017-07-28 11:04:54 -04003393 #Height 64
3394 void draw(SkCanvas* canvas) {
3395 SkPaint paint;
3396 paint.setAntiAlias(true);
3397 paint.setTextSize(50);
3398 const char str[] = "ay^jZ";
3399 const int count = sizeof(str) - 1;
3400 canvas->drawText(str, count, 25, 50, paint);
3401 SkRect bounds;
3402 paint.measureText(str, count, &bounds);
3403 canvas->translate(25, 50);
3404 paint.setStyle(SkPaint::kStroke_Style);
3405 canvas->drawRect(bounds, paint);
3406 }
3407 ##
3408
3409##
3410
3411#Method SkScalar measureText(const void* text, size_t length) const
3412
Cary Clarkab2621d2018-01-30 10:08:57 -05003413#In Measure_Text
Cary Clark09d80c02018-10-31 12:14:03 -04003414#Populate
Cary Clark8032b982017-07-28 11:04:54 -04003415
Cary Clark09d80c02018-10-31 12:14:03 -04003416#Example
Cary Clark8032b982017-07-28 11:04:54 -04003417 SkPaint paint;
3418 SkDebugf("default width = %g\n", paint.measureText("!", 1));
3419 paint.setTextSize(paint.getTextSize() * 2);
3420 SkDebugf("double width = %g\n", paint.measureText("!", 1));
3421
3422 #StdOut
3423 default width = 5
3424 double width = 10
3425 ##
3426 ##
3427
3428##
3429
3430#Method size_t breakText(const void* text, size_t length, SkScalar maxWidth,
Cary Clark73fa9722017-08-29 17:36:51 -04003431 SkScalar* measuredWidth = nullptr) const
Cary Clarkab2621d2018-01-30 10:08:57 -05003432#In Measure_Text
3433#Line # returns text that fits in a width ##
Cary Clark09d80c02018-10-31 12:14:03 -04003434#Populate
Cary Clark8032b982017-07-28 11:04:54 -04003435
Cary Clark09d80c02018-10-31 12:14:03 -04003436#Example
Cary Clark8032b982017-07-28 11:04:54 -04003437 #Description
3438 Line under "Breakfast" shows desired width, shorter than available characters.
3439 Line under "Bre" shows measured width after breaking text.
3440 ##
3441 #Height 128
3442 #Width 280
3443 void draw(SkCanvas* canvas) {
3444 SkPaint paint;
3445 paint.setAntiAlias(true);
3446 paint.setTextSize(50);
3447 const char str[] = "Breakfast";
3448 const int count = sizeof(str) - 1;
3449 canvas->drawText(str, count, 25, 50, paint);
3450 SkScalar measuredWidth;
3451 int partialBytes = paint.breakText(str, count, 100, &measuredWidth);
3452 canvas->drawText(str, partialBytes, 25, 100, paint);
3453 canvas->drawLine(25, 60, 25 + 100, 60, paint);
3454 canvas->drawLine(25, 110, 25 + measuredWidth, 110, paint);
3455 }
3456 ##
3457
3458##
3459
3460#Method int getTextWidths(const void* text, size_t byteLength, SkScalar widths[],
Cary Clark73fa9722017-08-29 17:36:51 -04003461 SkRect bounds[] = nullptr) const
Cary Clarkab2621d2018-01-30 10:08:57 -05003462#In Measure_Text
3463#Line # returns advance and bounds for each glyph in text ##
Cary Clark09d80c02018-10-31 12:14:03 -04003464#Populate
Cary Clark8032b982017-07-28 11:04:54 -04003465
Cary Clark09d80c02018-10-31 12:14:03 -04003466#Example
Cary Clark8032b982017-07-28 11:04:54 -04003467 #Height 160
3468 #Description
Cary Clarkce101242017-09-01 15:51:02 -04003469 Bounds of Glyphs increase for stroked text, but text advance remains the same.
Cary Clark8032b982017-07-28 11:04:54 -04003470 The underlines show the text advance, spaced to keep them distinct.
3471 ##
3472 void draw(SkCanvas* canvas) {
3473 SkPaint paint;
3474 paint.setAntiAlias(true);
3475 paint.setTextSize(50);
3476 const char str[] = "abc";
3477 const int bytes = sizeof(str) - 1;
3478 int count = paint.getTextWidths(str, bytes, nullptr);
3479 std::vector<SkScalar> widths;
3480 std::vector<SkRect> bounds;
3481 widths.resize(count);
3482 bounds.resize(count);
3483 for (int loop = 0; loop < 2; ++loop) {
3484 (void) paint.getTextWidths(str, count, &widths.front(), &bounds.front());
3485 SkPoint loc = { 25, 50 };
3486 canvas->drawText(str, bytes, loc.fX, loc.fY, paint);
3487 paint.setStyle(SkPaint::kStroke_Style);
3488 paint.setStrokeWidth(0);
3489 SkScalar advanceY = loc.fY + 10;
3490 for (int index = 0; index < count; ++index) {
3491 bounds[index].offset(loc.fX, loc.fY);
3492 canvas->drawRect(bounds[index], paint);
3493 canvas->drawLine(loc.fX, advanceY, loc.fX + widths[index], advanceY, paint);
3494 loc.fX += widths[index];
3495 advanceY += 5;
3496 }
3497 canvas->translate(0, 80);
3498 paint.setStrokeWidth(3);
3499 }
3500 }
3501 ##
3502
3503##
3504
Cary Clark08895c42018-02-01 09:37:32 -05003505#Subtopic Measure_Text ##
Cary Clark8032b982017-07-28 11:04:54 -04003506# ------------------------------------------------------------------------------
Cary Clark08895c42018-02-01 09:37:32 -05003507#Subtopic Text_Path
3508#Line # geometry of Glyphs ##
Cary Clark8032b982017-07-28 11:04:54 -04003509
Cary Clarkce101242017-09-01 15:51:02 -04003510Text_Path describes the geometry of Glyphs used to draw text.
Cary Clark8032b982017-07-28 11:04:54 -04003511
3512#Method void getTextPath(const void* text, size_t length, SkScalar x, SkScalar y,
3513 SkPath* path) const
Cary Clarkab2621d2018-01-30 10:08:57 -05003514#In Text_Path
3515#Line # returns Path equivalent to text ##
Cary Clark09d80c02018-10-31 12:14:03 -04003516#Populate
Cary Clark8032b982017-07-28 11:04:54 -04003517
Cary Clark09d80c02018-10-31 12:14:03 -04003518#Example
Cary Clark8032b982017-07-28 11:04:54 -04003519 #Description
3520 Text is added to Path, offset, and subtracted from Path, then added at
3521 the offset location. The result is rendered with one draw call.
3522 ##
3523 #Height 128
3524 void draw(SkCanvas* canvas) {
3525 SkPaint paint;
3526 paint.setTextSize(80);
3527 SkPath path, path2;
3528 paint.getTextPath("ABC", 3, 20, 80, &path);
3529 path.offset(20, 20, &path2);
3530 Op(path, path2, SkPathOp::kDifference_SkPathOp, &path);
3531 path.addPath(path2);
3532 paint.setStyle(SkPaint::kStroke_Style);
3533 canvas->drawPath(path, paint);
3534 }
3535 ##
3536
3537##
3538
3539#Method void getPosTextPath(const void* text, size_t length,
3540 const SkPoint pos[], SkPath* path) const
Cary Clarkab2621d2018-01-30 10:08:57 -05003541#In Text_Path
3542#Line # returns Path equivalent to positioned text ##
Cary Clark09d80c02018-10-31 12:14:03 -04003543#Populate
Cary Clark8032b982017-07-28 11:04:54 -04003544
Cary Clark09d80c02018-10-31 12:14:03 -04003545#Example
Cary Clark8032b982017-07-28 11:04:54 -04003546 #Height 85
3547 #Description
Cary Clarkce101242017-09-01 15:51:02 -04003548 Simplifies three Glyphs to eliminate overlaps, and strokes the result.
Cary Clark8032b982017-07-28 11:04:54 -04003549 ##
3550 void draw(SkCanvas* canvas) {
3551 SkPaint paint;
3552 paint.setTextSize(80);
3553 SkPath path, path2;
3554 SkPoint pos[] = {{20, 60}, {30, 70}, {40, 80}};
3555 paint.getPosTextPath("ABC", 3, pos, &path);
3556 Simplify(path, &path);
3557 paint.setStyle(SkPaint::kStroke_Style);
3558 canvas->drawPath(path, paint);
3559 }
3560 ##
3561
3562##
3563
Cary Clark08895c42018-02-01 09:37:32 -05003564#Subtopic Text_Path ##
Cary Clark8032b982017-07-28 11:04:54 -04003565# ------------------------------------------------------------------------------
Cary Clark08895c42018-02-01 09:37:32 -05003566#Subtopic Text_Intercepts
3567#Line # advanced underline, strike through ##
Cary Clark8032b982017-07-28 11:04:54 -04003568
Cary Clarkce101242017-09-01 15:51:02 -04003569Text_Intercepts describe the intersection of drawn text Glyphs with a pair
Cary Clark8032b982017-07-28 11:04:54 -04003570of lines parallel to the text advance. Text_Intercepts permits creating a
Cary Clarkce101242017-09-01 15:51:02 -04003571underline that skips Descenders.
Cary Clark8032b982017-07-28 11:04:54 -04003572
3573#Method int getTextIntercepts(const void* text, size_t length, SkScalar x, SkScalar y,
3574 const SkScalar bounds[2], SkScalar* intervals) const
Cary Clarkab2621d2018-01-30 10:08:57 -05003575#In Text_Intercepts
3576#Line # returns where lines intersect text; underlines ##
Cary Clark09d80c02018-10-31 12:14:03 -04003577#Populate
Cary Clark8032b982017-07-28 11:04:54 -04003578
3579#Example
3580#Height 128
3581#Description
Cary Clarkce101242017-09-01 15:51:02 -04003582Underline uses intercepts to draw on either side of the glyph Descender.
Cary Clark8032b982017-07-28 11:04:54 -04003583##
3584void draw(SkCanvas* canvas) {
3585 SkPaint paint;
3586 paint.setTextSize(120);
3587 SkPoint textOrigin = { 20, 100 };
3588 SkScalar bounds[] = { 100, 108 };
3589 int count = paint.getTextIntercepts("y", 1, textOrigin.fX, textOrigin.fY, bounds, nullptr);
3590 std::vector<SkScalar> intervals;
3591 intervals.resize(count);
3592 (void) paint.getTextIntercepts("y", 1, textOrigin.fX, textOrigin.fY, bounds,
3593 &intervals.front());
3594 canvas->drawString("y", textOrigin.fX, textOrigin.fY, paint);
3595 paint.setColor(SK_ColorRED);
3596 SkScalar x = textOrigin.fX;
3597 for (int i = 0; i < count; i += 2) {
3598 canvas->drawRect({x, bounds[0], intervals[i], bounds[1]}, paint);
3599 x = intervals[i + 1];
3600 }
3601 canvas->drawRect({intervals[count - 1], bounds[0],
3602 textOrigin.fX + paint.measureText("y", 1), bounds[1]}, paint);
3603}
3604##
3605
3606##
3607
3608#Method int getPosTextIntercepts(const void* text, size_t length, const SkPoint pos[],
3609 const SkScalar bounds[2], SkScalar* intervals) const
Cary Clarkab2621d2018-01-30 10:08:57 -05003610#In Text_Intercepts
3611#Line # returns where lines intersect positioned text; underlines ##
Cary Clark09d80c02018-10-31 12:14:03 -04003612#Populate
Cary Clark8032b982017-07-28 11:04:54 -04003613
Cary Clark09d80c02018-10-31 12:14:03 -04003614#Example
Cary Clark8032b982017-07-28 11:04:54 -04003615 #Description
Cary Clarkce101242017-09-01 15:51:02 -04003616 Text intercepts draw on either side of, but not inside, Glyphs in a run.
Cary Clark8032b982017-07-28 11:04:54 -04003617 ##
Cary Clark92694be2018-10-25 08:15:36 -04003618 void draw(SkCanvas* canvas) {
3619 SkPaint paint;
3620 paint.setTextSize(120);
3621 SkPoint textPos[] = {{ 60, 90 }, { 120, 90 }};
3622 SkScalar bounds[] = { 40, 70 };
3623 const char str[] = "A+";
3624 int len = sizeof(str) - 1;
3625 int count = paint.getPosTextIntercepts(str, len, textPos, bounds, nullptr);
3626 std::vector<SkScalar> intervals;
3627 intervals.resize(count);
3628 (void) paint.getPosTextIntercepts(str, len, textPos, bounds, &intervals.front());
3629 canvas->drawPosText(str, len, textPos, paint);
3630 paint.setColor(SK_ColorRED);
3631 SkScalar x = textPos[0].fX;
3632 for (int i = 0; i < count; i+= 2) {
3633 canvas->drawRect({x, bounds[0], intervals[i], bounds[1]}, paint);
3634 x = intervals[i + 1];
Cary Clark8032b982017-07-28 11:04:54 -04003635 }
Cary Clark92694be2018-10-25 08:15:36 -04003636 if (count) {
3637 canvas->drawRect({intervals[count - 1], bounds[0], 180, bounds[1]}, paint);
3638 }
3639 }
Cary Clark8032b982017-07-28 11:04:54 -04003640 ##
3641
3642##
3643
3644#Method int getPosTextHIntercepts(const void* text, size_t length, const SkScalar xpos[],
3645 SkScalar constY, const SkScalar bounds[2],
3646 SkScalar* intervals) const
Cary Clarkab2621d2018-01-30 10:08:57 -05003647#In Text_Intercepts
3648#Line # returns where lines intersect horizontally positioned text; underlines ##
Cary Clark09d80c02018-10-31 12:14:03 -04003649#Populate
Cary Clark8032b982017-07-28 11:04:54 -04003650
Cary Clark09d80c02018-10-31 12:14:03 -04003651#Example
Cary Clark8032b982017-07-28 11:04:54 -04003652 #Height 128
3653 #Description
3654 Text intercepts do not take stroke thickness into consideration.
3655 ##
3656 void draw(SkCanvas* canvas) {
3657 SkPaint paint;
3658 paint.setTextSize(120);
3659 paint.setStyle(SkPaint::kStroke_Style);
3660 paint.setStrokeWidth(4);
3661 SkScalar textPosH[] = { 20, 80, 140 };
3662 SkScalar y = 100;
3663 SkScalar bounds[] = { 56, 78 };
3664 const char str[] = "\\-/";
3665 int len = sizeof(str) - 1;
3666 int count = paint.getPosTextHIntercepts(str, len, textPosH, y, bounds, nullptr);
3667 std::vector<SkScalar> intervals;
3668 intervals.resize(count);
3669 (void) paint.getPosTextHIntercepts(str, len, textPosH, y, bounds, &intervals.front());
3670 canvas->drawPosTextH(str, len, textPosH, y, paint);
3671 paint.setColor(0xFFFF7777);
3672 paint.setStyle(SkPaint::kFill_Style);
3673 SkScalar x = textPosH[0];
3674 for (int i = 0; i < count; i+= 2) {
3675 canvas->drawRect({x, bounds[0], intervals[i], bounds[1]}, paint);
3676 x = intervals[i + 1];
3677 }
3678 canvas->drawRect({intervals[count - 1], bounds[0], 180, bounds[1]}, paint);
3679 }
3680 ##
3681
3682##
3683
3684
3685#Method int getTextBlobIntercepts(const SkTextBlob* blob, const SkScalar bounds[2],
3686 SkScalar* intervals) const
Cary Clarkab2621d2018-01-30 10:08:57 -05003687#In Text_Intercepts
3688#Line # returns where lines intersect Text_Blob; underlines ##
Cary Clark09d80c02018-10-31 12:14:03 -04003689#Populate
Cary Clark8032b982017-07-28 11:04:54 -04003690
Cary Clark09d80c02018-10-31 12:14:03 -04003691#Example
Cary Clark8032b982017-07-28 11:04:54 -04003692 #Height 143
3693 void draw(SkCanvas* canvas) {
3694 SkPaint paint;
Cary Clark3cd22cc2017-12-01 11:49:58 -05003695 paint.setTextEncoding(SkPaint::kGlyphID_TextEncoding);
Cary Clark8032b982017-07-28 11:04:54 -04003696 paint.setTextSize(120);
3697 SkPoint textPos = { 20, 110 };
3698 int len = 3;
3699 SkTextBlobBuilder textBlobBuilder;
Herb Derbyfcac00f2018-05-01 11:57:56 -04003700 const SkTextBlobBuilder::RunBuffer& run =
Cary Clark8032b982017-07-28 11:04:54 -04003701 textBlobBuilder.allocRun(paint, len, textPos.fX, textPos.fY);
3702 run.glyphs[0] = 10;
3703 run.glyphs[1] = 20;
Herb Derbyfcac00f2018-05-01 11:57:56 -04003704 run.glyphs[2] = 30;
Cary Clark8032b982017-07-28 11:04:54 -04003705 sk_sp<const SkTextBlob> blob = textBlobBuilder.make();
3706 canvas->drawTextBlob(blob.get(), textPos.fX, textPos.fY, paint);
3707 SkScalar bounds[] = { 116, 134 };
3708 int count = paint.getTextBlobIntercepts(blob.get(), bounds, nullptr);
3709 std::vector<SkScalar> intervals;
3710 intervals.resize(count);
3711 (void) paint.getTextBlobIntercepts(blob.get(), bounds, &intervals.front());
3712 canvas->drawTextBlob(blob.get(), 0, 0, paint);
3713 paint.setColor(0xFFFF7777);
3714 SkScalar x = textPos.fX;
3715 for (int i = 0; i < count; i+= 2) {
3716 canvas->drawRect({x, bounds[0], intervals[i], bounds[1]}, paint);
3717 x = intervals[i + 1];
3718 }
3719 canvas->drawRect({intervals[count - 1], bounds[0], 180, bounds[1]}, paint);
3720 }
3721 ##
3722
3723##
3724
Cary Clark08895c42018-02-01 09:37:32 -05003725#Subtopic Text_Intercepts ##
Cary Clark8032b982017-07-28 11:04:54 -04003726# ------------------------------------------------------------------------------
3727
Cary Clark77b3f3a2018-11-07 14:59:03 -05003728#Method SkRect getFontBounds() const
3729
3730#In Font_Metrics
3731#Line # returns union all glyph bounds ##
3732#Populate
3733
3734#Example
3735 SkPaint paint;
Mike Reedb5784ac2018-11-12 09:35:15 -05003736 SkFontMetrics fm;
Cary Clark77b3f3a2018-11-07 14:59:03 -05003737 paint.getFontMetrics(&fm);
3738 SkRect fb = paint.getFontBounds();
3739 SkDebugf("metrics bounds = { %g, %g, %g, %g }\n", fm.fXMin, fm.fTop, fm.fXMax, fm.fBottom );
3740 SkDebugf("font bounds = { %g, %g, %g, %g }\n", fb.fLeft, fb.fTop, fb.fRight, fm.fBottom );
3741
3742 #StdOut
3743 metrics bounds = { -12.2461, -14.7891, 21.5215, 5.55469 }
3744 font bounds = { -12.2461, -14.7891, 21.5215, 5.55469 }
3745 ##
3746##
3747
3748##
3749
Cary Clark8032b982017-07-28 11:04:54 -04003750#Method bool nothingToDraw() const
Cary Clark78de7512018-02-07 07:27:09 -05003751#In Utility
Cary Clarkab2621d2018-01-30 10:08:57 -05003752#Line # returns true if Paint prevents all drawing ##
Cary Clark09d80c02018-10-31 12:14:03 -04003753#Populate
Cary Clark8032b982017-07-28 11:04:54 -04003754
Cary Clark09d80c02018-10-31 12:14:03 -04003755#Example
Cary Clark8032b982017-07-28 11:04:54 -04003756 void draw(SkCanvas* canvas) {
3757 auto debugster = [](const char* prefix, const SkPaint& p) -> void {
Herb Derbyfcac00f2018-05-01 11:57:56 -04003758 SkDebugf("%s nothing to draw: %s\n", prefix,
Cary Clark8032b982017-07-28 11:04:54 -04003759 p.nothingToDraw() ? "true" : "false");
3760 };
3761 SkPaint paint;
3762 debugster("initial", paint);
3763 paint.setBlendMode(SkBlendMode::kDst);
3764 debugster("blend dst", paint);
3765 paint.setBlendMode(SkBlendMode::kSrcOver);
3766 debugster("blend src over", paint);
3767 paint.setAlpha(0);
3768 debugster("alpha 0", paint);
3769 }
3770
3771 #StdOut
3772 initial nothing to draw: false
3773 blend dst nothing to draw: true
3774 blend src over nothing to draw: false
3775 alpha 0 nothing to draw: true
3776 #StdOut ##
3777 ##
3778
3779##
3780
3781# ------------------------------------------------------------------------------
Cary Clark08895c42018-02-01 09:37:32 -05003782#Subtopic Fast_Bounds
3783#Line # approximate area required by Paint ##
Herb Derbyfcac00f2018-05-01 11:57:56 -04003784 #Private
3785 To be made private.
Cary Clark8032b982017-07-28 11:04:54 -04003786 ##
3787
Cary Clark682c58d2018-05-16 07:07:07 -04003788Fast_Bounds functions conservatively outset a drawing bounds by additional area
Cary Clark8032b982017-07-28 11:04:54 -04003789Paint may draw to.
3790
3791#Method bool canComputeFastBounds() const
Herb Derbyfcac00f2018-05-01 11:57:56 -04003792
Cary Clarkab2621d2018-01-30 10:08:57 -05003793#In Fast_Bounds
Cary Clark1a8d7622018-03-05 13:26:16 -05003794#Line # returns true if settings allow for fast bounds computation ##
Herb Derbyfcac00f2018-05-01 11:57:56 -04003795 #Private
Cary Clark8032b982017-07-28 11:04:54 -04003796 (to be made private)
3797 ##
3798
3799 Returns true if Paint does not include elements requiring extensive computation
3800 to compute Device bounds of drawn geometry. For instance, Paint with Path_Effect
3801 always returns false.
3802
3803 #Return true if Paint allows for fast computation of bounds ##
3804##
3805
3806#Method const SkRect& computeFastBounds(const SkRect& orig, SkRect* storage) const
Herb Derbyfcac00f2018-05-01 11:57:56 -04003807
Cary Clarkab2621d2018-01-30 10:08:57 -05003808#In Fast_Bounds
Cary Clark1a8d7622018-03-05 13:26:16 -05003809#Line # returns fill bounds for quick reject tests ##
Herb Derbyfcac00f2018-05-01 11:57:56 -04003810 #Private
Cary Clark8032b982017-07-28 11:04:54 -04003811 (to be made private)
3812 ##
3813
Cary Clark77b3f3a2018-11-07 14:59:03 -05003814 Only call if canComputeFastBounds returned true. This takes a
3815 raw rectangle, the raw bounds of a shape; and adjusts it for stylistic
3816 effects in the paint, such as stroking. If needed, it uses the storage
Cary Clarkce101242017-09-01 15:51:02 -04003817 parameter. It returns the adjusted bounds that can then be used
Cary Clark8032b982017-07-28 11:04:54 -04003818 for SkCanvas::quickReject tests.
3819
Cary Clarkce101242017-09-01 15:51:02 -04003820 The returned Rect will either be orig or storage, thus the caller
Cary Clark8032b982017-07-28 11:04:54 -04003821 should not rely on storage being set to the result, but should always
Cary Clarkce101242017-09-01 15:51:02 -04003822 use the returned value. It is legal for orig and storage to be the same
3823 Rect.
Cary Clark8032b982017-07-28 11:04:54 -04003824
Herb Derbyfcac00f2018-05-01 11:57:56 -04003825 #Private
Cary Clark682c58d2018-05-16 07:07:07 -04003826 For example:
3827 if (!path.isInverseFillType() && paint.canComputeFastBounds()) {
3828 SkRect storage;
3829 if (canvas->quickReject(paint.computeFastBounds(path.getBounds(), &storage))) {
Cary Clark137b8742018-05-30 09:21:49 -04003830 return; // do not draw the path
Cary Clark682c58d2018-05-16 07:07:07 -04003831 }
Cary Clark8032b982017-07-28 11:04:54 -04003832 }
Cary Clark682c58d2018-05-16 07:07:07 -04003833 // draw the path
Cary Clark8032b982017-07-28 11:04:54 -04003834 ##
3835
3836 #Param orig geometry modified by Paint when drawn ##
3837 #Param storage computed bounds of geometry; may not be nullptr ##
3838
3839 #Return fast computed bounds ##
3840##
3841
3842#Method const SkRect& computeFastStrokeBounds(const SkRect& orig,
3843 SkRect* storage) const
Cary Clarkab2621d2018-01-30 10:08:57 -05003844#In Fast_Bounds
3845#Line # returns stroke bounds for quick reject tests ##
Herb Derbyfcac00f2018-05-01 11:57:56 -04003846 #Private
Cary Clark8032b982017-07-28 11:04:54 -04003847 (to be made private)
3848 ##
3849
3850 #Param orig geometry modified by Paint when drawn ##
3851 #Param storage computed bounds of geometry ##
3852
3853 #Return fast computed bounds ##
3854##
3855
3856#Method const SkRect& doComputeFastBounds(const SkRect& orig, SkRect* storage,
3857 Style style) const
Cary Clarkab2621d2018-01-30 10:08:57 -05003858#In Fast_Bounds
3859#Line # returns bounds for quick reject tests ##
Herb Derbyfcac00f2018-05-01 11:57:56 -04003860 #Private
Cary Clark8032b982017-07-28 11:04:54 -04003861 (to be made private)
3862 ##
3863
Cary Clarkce101242017-09-01 15:51:02 -04003864 Computes the bounds, overriding the Paint Style. This can be used to
3865 account for additional width required by stroking orig, without
3866 altering Style set to fill.
Cary Clark8032b982017-07-28 11:04:54 -04003867
3868 #Param orig geometry modified by Paint when drawn ##
3869 #Param storage computed bounds of geometry ##
3870 #Param style overrides Style ##
3871
3872 #Return fast computed bounds ##
3873##
3874
Cary Clark1a8d7622018-03-05 13:26:16 -05003875#Subtopic Fast_Bounds ##
Cary Clark8032b982017-07-28 11:04:54 -04003876
3877# ------------------------------------------------------------------------------
Cary Clark78de7512018-02-07 07:27:09 -05003878#Subtopic Utility
Cary Clark78de7512018-02-07 07:27:09 -05003879#Line # rarely called management functions ##
3880##
Cary Clark8032b982017-07-28 11:04:54 -04003881
Cary Clark8032b982017-07-28 11:04:54 -04003882# ------------------------------------------------------------------------------
3883
3884#Class SkPaint ##
3885
3886#Topic Paint ##