blob: 208ccab9639e74e5979902f2d5032f1849c2bb8a [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 Clark11407e52018-11-05 21:26:13 -0500299#Method void setHinting(SkFontHinting hintingLevel)
Cary Clarkab2621d2018-01-30 10:08:57 -0500300#In Hinting
301#Line # sets Hinting, glyph outline adjustment level ##
Cary Clark11407e52018-11-05 21:26:13 -0500302#Populate
Cary Clark8032b982017-07-28 11:04:54 -0400303
Cary Clark11407e52018-11-05 21:26:13 -0500304 #Example
305 SkPaint paint1, paint2;
Mike Reed42af4922018-11-30 08:54:46 -0500306 paint2.setHinting(SkFontHinting::kNormal);
Cary Clark11407e52018-11-05 21:26:13 -0500307 SkDebugf("paint1 %c= paint2\n", paint1 == paint2 ? '=' : ':');
Cary Clark8032b982017-07-28 11:04:54 -0400308
Cary Clark11407e52018-11-05 21:26:13 -0500309 #StdOut
310 paint1 == paint2
311 ##
312 ##
313##
314
Cary Clark8cc4cdc2018-11-09 23:16:58 -0500315#Method SkFontHinting getHinting() const
316#In Hinting
317#Line # returns Hinting, glyph outline adjustment level ##
318#Populate
319
320 #Example
321 SkPaint paint;
322 SkDebugf("SkFontHinting::kNormal %c= paint.getHinting()\n",
323 SkFontHinting::kNormal == paint.getHinting() ? '=' : ':');
324
325 #StdOut
326 SkFontHinting::kNormal == paint.getHinting()
327 ##
328 ##
329##
330
Cary Clark8032b982017-07-28 11:04:54 -0400331# ------------------------------------------------------------------------------
Cary Clark08895c42018-02-01 09:37:32 -0500332#Subtopic Flags
333#Line # attributes represented by single bits ##
Cary Clarka90ea222018-10-16 10:30:28 -0400334##
Cary Clark8032b982017-07-28 11:04:54 -0400335
336#Enum Flags
Cary Clark08895c42018-02-01 09:37:32 -0500337#Line # values described by bits and masks ##
Cary Clark8032b982017-07-28 11:04:54 -0400338
339#Code
Cary Clarka90ea222018-10-16 10:30:28 -0400340#Populate
Cary Clark8032b982017-07-28 11:04:54 -0400341##
342
343The bit values stored in Flags.
344The default value for Flags, normally zero, can be changed at compile time
345with a custom definition of SkPaintDefaults_Flags.
346All flags can be read and written explicitly; Flags allows manipulating
347multiple settings at once.
348
Herb Derbyfcac00f2018-05-01 11:57:56 -0400349 #Const kAntiAlias_Flag 0x0001
Cary Clarkffb3d682018-05-17 12:17:28 -0400350 #Line # mask for setting Anti_Alias ##
Cary Clark8032b982017-07-28 11:04:54 -0400351 ##
352 #Const kDither_Flag 0x0004
Cary Clark682c58d2018-05-16 07:07:07 -0400353 #Line # mask for setting Dither ##
Cary Clark8032b982017-07-28 11:04:54 -0400354 ##
Cary Clark8032b982017-07-28 11:04:54 -0400355 #Const kFakeBoldText_Flag 0x0020
Cary Clark682c58d2018-05-16 07:07:07 -0400356 #Line # mask for setting Fake_Bold ##
Cary Clark8032b982017-07-28 11:04:54 -0400357 ##
358 #Const kLinearText_Flag 0x0040
Cary Clark682c58d2018-05-16 07:07:07 -0400359 #Line # mask for setting Linear_Text ##
Cary Clark8032b982017-07-28 11:04:54 -0400360 ##
361 #Const kSubpixelText_Flag 0x0080
Cary Clark682c58d2018-05-16 07:07:07 -0400362 #Line # mask for setting Subpixel_Text ##
Cary Clark8032b982017-07-28 11:04:54 -0400363 ##
Cary Clark8032b982017-07-28 11:04:54 -0400364 #Const kLCDRenderText_Flag 0x0200
Cary Clark682c58d2018-05-16 07:07:07 -0400365 #Line # mask for setting LCD_Text ##
Cary Clark8032b982017-07-28 11:04:54 -0400366 ##
367 #Const kEmbeddedBitmapText_Flag 0x0400
Cary Clark682c58d2018-05-16 07:07:07 -0400368 #Line # mask for setting Font_Embedded_Bitmaps ##
Cary Clark8032b982017-07-28 11:04:54 -0400369 ##
370 #Const kAutoHinting_Flag 0x0800
Cary Clark682c58d2018-05-16 07:07:07 -0400371 #Line # mask for setting Automatic_Hinting ##
Cary Clark8032b982017-07-28 11:04:54 -0400372 ##
Cary Clark8032b982017-07-28 11:04:54 -0400373 #Const kAllFlags 0xFFFF
Cary Clark682c58d2018-05-16 07:07:07 -0400374 #Line # mask of all Flags ##
Cary Clark8032b982017-07-28 11:04:54 -0400375 mask of all Flags, including private flags and flags reserved for future use
376 ##
377
378Flags default to all flags clear, disabling the associated feature.
379
380#Enum ##
381
Cary Clark8032b982017-07-28 11:04:54 -0400382#Method uint32_t getFlags() const
Cary Clarkab2621d2018-01-30 10:08:57 -0500383#In Flags
384#Line # returns Flags stored in a bit field ##
Cary Clark09d80c02018-10-31 12:14:03 -0400385#Populate
Cary Clark8032b982017-07-28 11:04:54 -0400386
387#Example
388 SkPaint paint;
389 paint.setAntiAlias(true);
390 SkDebugf("(SkPaint::kAntiAlias_Flag & paint.getFlags()) %c= 0\n",
391 SkPaint::kAntiAlias_Flag & paint.getFlags() ? '!' : '=');
392
393 #StdOut
394 (SkPaint::kAntiAlias_Flag & paint.getFlags()) != 0
395 ##
396##
397
398##
399
400#Method void setFlags(uint32_t flags)
Cary Clarkab2621d2018-01-30 10:08:57 -0500401#In Flags
402#Line # sets multiple Flags in a bit field ##
Cary Clark09d80c02018-10-31 12:14:03 -0400403#Populate
Cary Clark8032b982017-07-28 11:04:54 -0400404
405#Example
406 SkPaint paint;
407 paint.setFlags((uint32_t) (SkPaint::kAntiAlias_Flag | SkPaint::kDither_Flag));
408 SkDebugf("paint.isAntiAlias()\n", paint.isAntiAlias() ? '!' : '=');
409 SkDebugf("paint.isDither()\n", paint.isDither() ? '!' : '=');
410
411 #StdOut
412 paint.isAntiAlias()
413 paint.isDither()
414 ##
415##
416
417##
418
Cary Clark8032b982017-07-28 11:04:54 -0400419# ------------------------------------------------------------------------------
Cary Clarkffb3d682018-05-17 12:17:28 -0400420#Subtopic Anti_Alias
421#Alias Anti_Alias
Cary Clark137b8742018-05-30 09:21:49 -0400422#Substitute anti-alias
423##
Cary Clarkffb3d682018-05-17 12:17:28 -0400424#Alias Anti_Aliased
Cary Clark137b8742018-05-30 09:21:49 -0400425#Substitute anti-aliased
426##
Cary Clarkffb3d682018-05-17 12:17:28 -0400427#Alias Anti_Aliasing
Cary Clark137b8742018-05-30 09:21:49 -0400428#Substitute anti-aliasing
429##
Cary Clark4855f782018-02-06 09:41:53 -0500430#In Related_Function
Cary Clarkab2621d2018-01-30 10:08:57 -0500431#Line # approximating coverage with transparency ##
Cary Clark8032b982017-07-28 11:04:54 -0400432
Cary Clarkffb3d682018-05-17 12:17:28 -0400433Anti_Alias drawing approximates partial pixel coverage with transparency.
Cary Clark8032b982017-07-28 11:04:54 -0400434If kAntiAlias_Flag is clear, pixel centers contained by the shape edge are drawn opaque.
435If kAntiAlias_Flag is set, pixels are drawn with Color_Alpha equal to their coverage.
436
Herb Derbyfcac00f2018-05-01 11:57:56 -0400437The rule for Aliased pixels is inconsistent across platforms. A shape edge
Cary Clark8032b982017-07-28 11:04:54 -0400438passing through the pixel center may, but is not required to, draw the pixel.
439
Cary Clarkce101242017-09-01 15:51:02 -0400440Raster_Engine draws Aliased pixels whose centers are on or to the right of the start of an
Cary Clark8032b982017-07-28 11:04:54 -0400441active Path edge, and whose center is to the left of the end of the active Path edge.
442
443#ToDo add illustration of raster pixels ##
444
Cary Clarkffb3d682018-05-17 12:17:28 -0400445A platform may only support Anti_Aliased drawing. Some GPU-backed platforms use
446Supersampling to Anti_Alias all drawing, and have no mechanism to selectively
Cary Clarkce101242017-09-01 15:51:02 -0400447Alias.
Cary Clark8032b982017-07-28 11:04:54 -0400448
Cary Clarkffb3d682018-05-17 12:17:28 -0400449The amount of coverage computed for Anti_Aliased pixels also varies across platforms.
Cary Clark8032b982017-07-28 11:04:54 -0400450
Cary Clarkffb3d682018-05-17 12:17:28 -0400451Anti_Alias is disabled by default.
452Anti_Alias can be enabled by default by setting SkPaintDefaults_Flags to kAntiAlias_Flag
Cary Clark8032b982017-07-28 11:04:54 -0400453at compile time.
454
Cary Clarkab2621d2018-01-30 10:08:57 -0500455#Example
Cary Clark8032b982017-07-28 11:04:54 -0400456 #Width 512
457 #Description
458 A red line is drawn with transparency on the edges to make it look smoother.
459 A blue line draws only where the pixel centers are contained.
Cary Clarkce101242017-09-01 15:51:02 -0400460 The lines are drawn into Bitmap, then drawn magnified to make the
461 Aliasing easier to see.
Cary Clark8032b982017-07-28 11:04:54 -0400462 ##
463
464 void draw(SkCanvas* canvas) {
465 SkBitmap bitmap;
466 bitmap.allocN32Pixels(50, 50);
467 SkCanvas offscreen(bitmap);
468 SkPaint paint;
469 paint.setStyle(SkPaint::kStroke_Style);
470 paint.setStrokeWidth(10);
471 for (bool antialias : { false, true }) {
472 paint.setColor(antialias ? SK_ColorRED : SK_ColorBLUE);
473 paint.setAntiAlias(antialias);
474 bitmap.eraseColor(0);
475 offscreen.drawLine(5, 5, 15, 30, paint);
476 canvas->drawLine(5, 5, 15, 30, paint);
477 canvas->save();
478 canvas->scale(10, 10);
479 canvas->drawBitmap(bitmap, antialias ? 12 : 0, 0);
480 canvas->restore();
481 canvas->translate(15, 0);
482 }
483 }
Cary Clarkab2621d2018-01-30 10:08:57 -0500484##
Cary Clarka90ea222018-10-16 10:30:28 -0400485#Subtopic Anti_Alias ##
Cary Clark8032b982017-07-28 11:04:54 -0400486
487#Method bool isAntiAlias() const
Cary Clark78de7512018-02-07 07:27:09 -0500488#In Anti_alias
Cary Clarkffb3d682018-05-17 12:17:28 -0400489#Line # returns true if Anti_Alias is set ##
Cary Clark09d80c02018-10-31 12:14:03 -0400490#Populate
Cary Clark8032b982017-07-28 11:04:54 -0400491
Cary Clark09d80c02018-10-31 12:14:03 -0400492#Example
Cary Clark8032b982017-07-28 11:04:54 -0400493 SkPaint paint;
494 SkDebugf("paint.isAntiAlias() %c= !!(paint.getFlags() & SkPaint::kAntiAlias_Flag)\n",
495 paint.isAntiAlias() == !!(paint.getFlags() & SkPaint::kAntiAlias_Flag) ? '=' : '!');
496 paint.setAntiAlias(true);
497 SkDebugf("paint.isAntiAlias() %c= !!(paint.getFlags() & SkPaint::kAntiAlias_Flag)\n",
498 paint.isAntiAlias() == !!(paint.getFlags() & SkPaint::kAntiAlias_Flag) ? '=' : '!');
499
500 #StdOut
501 paint.isAntiAlias() == !!(paint.getFlags() & SkPaint::kAntiAlias_Flag)
502 paint.isAntiAlias() == !!(paint.getFlags() & SkPaint::kAntiAlias_Flag)
503 ##
504 ##
505##
506
507#Method void setAntiAlias(bool aa)
Cary Clark78de7512018-02-07 07:27:09 -0500508#In Anti_alias
Cary Clarkffb3d682018-05-17 12:17:28 -0400509#Line # sets or clears Anti_Alias ##
Cary Clark09d80c02018-10-31 12:14:03 -0400510#Populate
Cary Clark8032b982017-07-28 11:04:54 -0400511
Cary Clark09d80c02018-10-31 12:14:03 -0400512#Example
Cary Clark8032b982017-07-28 11:04:54 -0400513 SkPaint paint1, paint2;
514 paint1.setAntiAlias(true);
515 paint2.setFlags(paint2.getFlags() | SkPaint::kAntiAlias_Flag);
516 SkDebugf("paint1 %c= paint2\n", paint1 == paint2 ? '=' : '!');
517
518 #StdOut
519 paint1 == paint2
520 ##
521 ##
522
523##
524
Cary Clark8032b982017-07-28 11:04:54 -0400525# ------------------------------------------------------------------------------
Cary Clark08895c42018-02-01 09:37:32 -0500526#Subtopic Dither
527#Line # distributing color error ##
Cary Clark8032b982017-07-28 11:04:54 -0400528
Herb Derbyfcac00f2018-05-01 11:57:56 -0400529Dither increases fidelity by adjusting the color of adjacent pixels.
Cary Clark8032b982017-07-28 11:04:54 -0400530This can help to smooth color transitions and reducing banding in gradients.
531Dithering lessens visible banding from kRGB_565_SkColorType
Herb Derbyfcac00f2018-05-01 11:57:56 -0400532and kRGBA_8888_SkColorType gradients,
Cary Clark8032b982017-07-28 11:04:54 -0400533and improves rendering into a kRGB_565_SkColorType Surface.
534
535Dithering is always enabled for linear gradients drawing into
536kRGB_565_SkColorType Surface and kRGBA_8888_SkColorType Surface.
537Dither cannot be enabled for kAlpha_8_SkColorType Surface and
538kRGBA_F16_SkColorType Surface.
539
540Dither is disabled by default.
541Dither can be enabled by default by setting SkPaintDefaults_Flags to kDither_Flag
542at compile time.
543
Cary Clark2be81cf2018-09-13 12:04:30 -0400544Some platform implementations may ignore dithering. Set #Formula # SK_IGNORE_GPU_DITHER ##
Cary Clark8032b982017-07-28 11:04:54 -0400545to ignore Dither on GPU_Surface.
546
547#Example
Herb Derbyfcac00f2018-05-01 11:57:56 -0400548#Description
Cary Clark8032b982017-07-28 11:04:54 -0400549Dithering in the bottom half more closely approximates the requested color by
550alternating nearby colors from pixel to pixel.
551##
552void draw(SkCanvas* canvas) {
553 SkBitmap bm16;
554 bm16.allocPixels(SkImageInfo::Make(32, 32, kRGB_565_SkColorType, kOpaque_SkAlphaType));
555 SkCanvas c16(bm16);
556 SkPaint colorPaint;
557 for (auto dither : { false, true } ) {
558 colorPaint.setDither(dither);
559 for (auto colors : { 0xFF333333, 0xFF666666, 0xFF999999, 0xFFCCCCCC } ) {
560 for (auto mask : { 0xFFFF0000, 0xFF00FF00, 0xFF0000FF, 0xFFFFFFFF } ) {
561 colorPaint.setColor(colors & mask);
562 c16.drawRect({0, 0, 8, 4}, colorPaint);
563 c16.translate(8, 0);
564 }
565 c16.translate(-32, 4);
566 }
567 }
568 canvas->scale(8, 8);
569 canvas->drawBitmap(bm16, 0, 0);
570}
571##
572
573#Example
Herb Derbyfcac00f2018-05-01 11:57:56 -0400574#Description
Cary Clark8032b982017-07-28 11:04:54 -0400575Dithering introduces subtle adjustments to color to smooth gradients.
576Drawing the gradient repeatedly with SkBlendMode::kPlus exaggerates the
577dither, making it easier to see.
578##
579void draw(SkCanvas* canvas) {
580 canvas->clear(0);
581 SkBitmap bm32;
582 bm32.allocPixels(SkImageInfo::Make(20, 10, kN32_SkColorType, kPremul_SkAlphaType));
583 SkCanvas c32(bm32);
584 SkPoint points[] = {{0, 0}, {20, 0}};
585 SkColor colors[] = {0xFF334455, 0xFF662211 };
586 SkPaint paint;
587 paint.setShader(SkGradientShader::MakeLinear(
588 points, colors, nullptr, SK_ARRAY_COUNT(colors),
589 SkShader::kClamp_TileMode, 0, nullptr));
590 paint.setDither(true);
591 c32.drawPaint(paint);
592 canvas->scale(12, 12);
593 canvas->drawBitmap(bm32, 0, 0);
594 paint.setBlendMode(SkBlendMode::kPlus);
595 canvas->drawBitmap(bm32, 0, 11, &paint);
596 canvas->drawBitmap(bm32, 0, 11, &paint);
597 canvas->drawBitmap(bm32, 0, 11, &paint);
598}
599##
Cary Clarka90ea222018-10-16 10:30:28 -0400600#SeeAlso Gradient kRGB_565_SkColorType
601#Subtopic Dither ##
Cary Clark8032b982017-07-28 11:04:54 -0400602
603#Method bool isDither() const
Cary Clarkab2621d2018-01-30 10:08:57 -0500604#In Dither
605#Line # returns true if Dither is set ##
Cary Clark09d80c02018-10-31 12:14:03 -0400606#Populate
Herb Derbyfcac00f2018-05-01 11:57:56 -0400607
Cary Clark09d80c02018-10-31 12:14:03 -0400608#Example
Cary Clark8032b982017-07-28 11:04:54 -0400609 SkPaint paint;
610 SkDebugf("paint.isDither() %c= !!(paint.getFlags() & SkPaint::kDither_Flag)\n",
611 paint.isDither() == !!(paint.getFlags() & SkPaint::kDither_Flag) ? '=' : '!');
612 paint.setDither(true);
613 SkDebugf("paint.isDither() %c= !!(paint.getFlags() & SkPaint::kDither_Flag)\n",
614 paint.isDither() == !!(paint.getFlags() & SkPaint::kDither_Flag) ? '=' : '!');
615
616 #StdOut
617 paint.isDither() == !!(paint.getFlags() & SkPaint::kDither_Flag)
618 paint.isDither() == !!(paint.getFlags() & SkPaint::kDither_Flag)
619 ##
620 ##
621
622##
623
624#Method void setDither(bool dither)
Cary Clarkab2621d2018-01-30 10:08:57 -0500625#In Dither
626#Line # sets or clears Dither ##
Cary Clark09d80c02018-10-31 12:14:03 -0400627#Populate
Cary Clark8032b982017-07-28 11:04:54 -0400628
Cary Clark09d80c02018-10-31 12:14:03 -0400629#Example
Cary Clark8032b982017-07-28 11:04:54 -0400630 SkPaint paint1, paint2;
631 paint1.setDither(true);
632 paint2.setFlags(paint2.getFlags() | SkPaint::kDither_Flag);
633 SkDebugf("paint1 %c= paint2\n", paint1 == paint2 ? '=' : '!');
634
635 #StdOut
636 paint1 == paint2
637 ##
638 ##
639
640 #SeeAlso kRGB_565_SkColorType
641
642##
643
Cary Clark8032b982017-07-28 11:04:54 -0400644# ------------------------------------------------------------------------------
Cary Clark08895c42018-02-01 09:37:32 -0500645#Subtopic Device_Text
646#Line # increase precision of glyph position ##
Cary Clark8032b982017-07-28 11:04:54 -0400647
648LCD_Text and Subpixel_Text increase the precision of glyph position.
649
Cary Clarkffb3d682018-05-17 12:17:28 -0400650When set, Flags kLCDRenderText_Flag takes advantage of the organization of RGB stripes that
Cary Clark8032b982017-07-28 11:04:54 -0400651create a color, and relies
Cary Clarkce101242017-09-01 15:51:02 -0400652on the small size of the stripe and visual perception to make the color fringing imperceptible.
Cary Clark8032b982017-07-28 11:04:54 -0400653LCD_Text can be enabled on devices that orient stripes horizontally or vertically, and that order
Cary Clarkffb3d682018-05-17 12:17:28 -0400654the color components as RGB or BGR.
Cary Clark8032b982017-07-28 11:04:54 -0400655
Herb Derbyfcac00f2018-05-01 11:57:56 -0400656Flags kSubpixelText_Flag uses the pixel transparency to represent a fractional offset.
Cary Clark8032b982017-07-28 11:04:54 -0400657As the opaqueness
658of the color increases, the edge of the glyph appears to move towards the outside of the pixel.
659
660Either or both techniques can be enabled.
661kLCDRenderText_Flag and kSubpixelText_Flag are clear by default.
Herb Derbyfcac00f2018-05-01 11:57:56 -0400662LCD_Text or Subpixel_Text can be enabled by default by setting SkPaintDefaults_Flags to
Cary Clark8032b982017-07-28 11:04:54 -0400663kLCDRenderText_Flag or kSubpixelText_Flag (or both) at compile time.
664
665#Example
666 #Description
667 Four commas are drawn normally and with combinations of LCD_Text and Subpixel_Text.
Cary Clarkce101242017-09-01 15:51:02 -0400668 When Subpixel_Text is disabled, the comma Glyphs are identical, but not evenly spaced.
669 When Subpixel_Text is enabled, the comma Glyphs are unique, but appear evenly spaced.
Cary Clark8032b982017-07-28 11:04:54 -0400670 ##
671
672 SkBitmap bitmap;
673 bitmap.allocN32Pixels(24, 33);
674 SkCanvas offscreen(bitmap);
675 offscreen.clear(SK_ColorWHITE);
676 SkPaint paint;
677 paint.setAntiAlias(true);
678 paint.setTextSize(20);
679 for (bool lcd : { false, true }) {
680 paint.setLCDRenderText(lcd);
681 for (bool subpixel : { false, true }) {
682 paint.setSubpixelText(subpixel);
683 offscreen.drawString(",,,,", 0, 4, paint);
684 offscreen.translate(0, 7);
685 }
686 }
687 canvas->drawBitmap(bitmap, 4, 12);
688 canvas->scale(9, 9);
689 canvas->drawBitmap(bitmap, 4, -1);
690##
Cary Clark08895c42018-02-01 09:37:32 -0500691#Subtopic Device_Text ##
Cary Clark8032b982017-07-28 11:04:54 -0400692
693#Subtopic Linear_Text
Cary Clark137b8742018-05-30 09:21:49 -0400694#Alias Linear_Text ##
Cary Clark08895c42018-02-01 09:37:32 -0500695#Line # selects text rendering as Glyph or Path ##
Cary Clark8032b982017-07-28 11:04:54 -0400696
697Linear_Text selects whether text is rendered as a Glyph or as a Path.
Cary Clark4a23bbf2018-11-08 16:00:33 -0500698If kLinearText_Flag is set, it has the same effect as setting Hinting to SkFontHinting::kNormal.
699If kLinearText_Flag is clear, it is the same as setting Hinting to SkFontHinting::kNone.
Cary Clarka90ea222018-10-16 10:30:28 -0400700#Subtopic Linear_Text ##
Cary Clark8032b982017-07-28 11:04:54 -0400701
702#Method bool isLinearText() const
Cary Clarkab2621d2018-01-30 10:08:57 -0500703#In Linear_Text
Cary Clarka90ea222018-10-16 10:30:28 -0400704#Line # returns true if text is converted to Path ##
Cary Clark09d80c02018-10-31 12:14:03 -0400705#Populate
Cary Clark8032b982017-07-28 11:04:54 -0400706
Cary Clark09d80c02018-10-31 12:14:03 -0400707#Example
Cary Clark8032b982017-07-28 11:04:54 -0400708 #Height 128
709 void draw(SkCanvas* canvas) {
710 SkPaint paint;
711 paint.setAntiAlias(true);
712 const char testStr[] = "xxxx xxxx";
713 for (auto linearText : { false, true } ) {
714 paint.setLinearText(linearText);
715 paint.setTextSize(24);
716 canvas->drawString(paint.isLinearText() ? "linear" : "hinted", 128, 30, paint);
717 for (SkScalar textSize = 8; textSize < 30; textSize *= 1.22f) {
718 paint.setTextSize(textSize);
719 canvas->translate(0, textSize);
720 canvas->drawString(testStr, 10, 0, paint);
721 }
722 }
723 }
724 ##
725
726 #SeeAlso setLinearText Hinting
727##
728
729#Method void setLinearText(bool linearText)
Cary Clarkab2621d2018-01-30 10:08:57 -0500730#In Linear_Text
Cary Clarka90ea222018-10-16 10:30:28 -0400731#Line # converts to Path before draw or measure ##
Cary Clark09d80c02018-10-31 12:14:03 -0400732#Populate
Cary Clark8032b982017-07-28 11:04:54 -0400733
Cary Clark09d80c02018-10-31 12:14:03 -0400734#Example
Cary Clark8032b982017-07-28 11:04:54 -0400735 #Height 128
736 void draw(SkCanvas* canvas) {
737 SkPaint paint;
738 paint.setAntiAlias(true);
739 const char testStr[] = "abcd efgh";
740 for (int textSize : { 12, 24 } ) {
741 paint.setTextSize(textSize);
742 for (auto linearText : { false, true } ) {
743 paint.setLinearText(linearText);
744 SkString width;
745 width.appendScalar(paint.measureText(testStr, SK_ARRAY_COUNT(testStr), nullptr));
746 canvas->translate(0, textSize + 4);
747 canvas->drawString(testStr, 10, 0, paint);
748 canvas->drawString(width, 128, 0, paint);
749 }
750 }
Herb Derbyfcac00f2018-05-01 11:57:56 -0400751 }
Cary Clark8032b982017-07-28 11:04:54 -0400752 ##
753
754 #SeeAlso isLinearText Hinting
755##
756
Cary Clark8032b982017-07-28 11:04:54 -0400757#Subtopic Subpixel_Text
Cary Clark137b8742018-05-30 09:21:49 -0400758#Alias Subpixel_Text ##
Cary Clark08895c42018-02-01 09:37:32 -0500759#Line # uses pixel transparency to represent fractional offset ##
Cary Clark8032b982017-07-28 11:04:54 -0400760
Herb Derbyfcac00f2018-05-01 11:57:56 -0400761Flags kSubpixelText_Flag uses the pixel transparency to represent a fractional offset.
Cary Clark8032b982017-07-28 11:04:54 -0400762As the opaqueness
763of the color increases, the edge of the glyph appears to move towards the outside of the pixel.
Cary Clarka90ea222018-10-16 10:30:28 -0400764#Subtopic Subpixel_Text ##
Cary Clark8032b982017-07-28 11:04:54 -0400765
766#Method bool isSubpixelText() const
Cary Clarkab2621d2018-01-30 10:08:57 -0500767#In Subpixel_Text
768#Line # returns true if Subpixel_Text is set ##
Cary Clark09d80c02018-10-31 12:14:03 -0400769#Populate
Cary Clark8032b982017-07-28 11:04:54 -0400770
Cary Clark09d80c02018-10-31 12:14:03 -0400771#Example
Cary Clark8032b982017-07-28 11:04:54 -0400772SkPaint paint;
773SkDebugf("paint.isSubpixelText() %c= !!(paint.getFlags() & SkPaint::kSubpixelText_Flag)\n",
774 paint.isSubpixelText() == !!(paint.getFlags() & SkPaint::kSubpixelText_Flag) ? '=' : '!');
775paint.setSubpixelText(true);
776SkDebugf("paint.isSubpixelText() %c= !!(paint.getFlags() & SkPaint::kSubpixelText_Flag)\n",
777 paint.isSubpixelText() == !!(paint.getFlags() & SkPaint::kSubpixelText_Flag) ? '=' : '!');
778
779 #StdOut
780 paint.isSubpixelText() == !!(paint.getFlags() & SkPaint::kSubpixelText_Flag)
781 paint.isSubpixelText() == !!(paint.getFlags() & SkPaint::kSubpixelText_Flag)
782 ##
783 ##
784
785##
786
787#Method void setSubpixelText(bool subpixelText)
Cary Clarkab2621d2018-01-30 10:08:57 -0500788#In Subpixel_Text
789#Line # sets or clears Subpixel_Text ##
Cary Clark09d80c02018-10-31 12:14:03 -0400790#Populate
Cary Clark8032b982017-07-28 11:04:54 -0400791
Cary Clark09d80c02018-10-31 12:14:03 -0400792#Example
Cary Clark8032b982017-07-28 11:04:54 -0400793 SkPaint paint1, paint2;
794 paint1.setSubpixelText(true);
795 paint2.setFlags(paint2.getFlags() | SkPaint::kSubpixelText_Flag);
796 SkDebugf("paint1 %c= paint2\n", paint1 == paint2 ? '=' : '!');
797
798 #StdOut
799 paint1 == paint2
800 ##
801 ##
802
803##
804
Cary Clark8032b982017-07-28 11:04:54 -0400805#Subtopic LCD_Text
Cary Clarkffb3d682018-05-17 12:17:28 -0400806#Line # text relying on the order of RGB stripes ##
Cary Clark137b8742018-05-30 09:21:49 -0400807
808# make this a top level name, since it is under subtopic Device_Text
809#Alias LCD_Text
810#Substitute LCD text
811##
Cary Clark8032b982017-07-28 11:04:54 -0400812
Cary Clarkffb3d682018-05-17 12:17:28 -0400813When set, Flags kLCDRenderText_Flag takes advantage of the organization of RGB stripes that
Cary Clark8032b982017-07-28 11:04:54 -0400814create a color, and relies
Cary Clarkce101242017-09-01 15:51:02 -0400815on the small size of the stripe and visual perception to make the color fringing imperceptible.
Cary Clark8032b982017-07-28 11:04:54 -0400816LCD_Text can be enabled on devices that orient stripes horizontally or vertically, and that order
Cary Clarkffb3d682018-05-17 12:17:28 -0400817the color components as RGB or BGR.
Cary Clarka90ea222018-10-16 10:30:28 -0400818#Subtopic LCD_Text ##
Cary Clark8032b982017-07-28 11:04:54 -0400819
820#Method bool isLCDRenderText() const
Cary Clarkab2621d2018-01-30 10:08:57 -0500821#In LCD_Text
822#Line # returns true if LCD_Text is set ##
Cary Clark09d80c02018-10-31 12:14:03 -0400823#Populate
Cary Clark8032b982017-07-28 11:04:54 -0400824
Cary Clark09d80c02018-10-31 12:14:03 -0400825#Example
Cary Clark8032b982017-07-28 11:04:54 -0400826SkPaint paint;
827SkDebugf("paint.isLCDRenderText() %c= !!(paint.getFlags() & SkPaint::kLCDRenderText_Flag)\n",
828 paint.isLCDRenderText() == !!(paint.getFlags() & SkPaint::kLCDRenderText_Flag) ? '=' : '!');
829paint.setLCDRenderText(true);
830SkDebugf("paint.isLCDRenderText() %c= !!(paint.getFlags() & SkPaint::kLCDRenderText_Flag)\n",
831 paint.isLCDRenderText() == !!(paint.getFlags() & SkPaint::kLCDRenderText_Flag) ? '=' : '!');
832
833 #StdOut
834 paint.isLCDRenderText() == !!(paint.getFlags() & SkPaint::kLCDRenderText_Flag)
835 paint.isLCDRenderText() == !!(paint.getFlags() & SkPaint::kLCDRenderText_Flag)
836 ##
837 ##
838
839##
840
841#Method void setLCDRenderText(bool lcdText)
Cary Clarkab2621d2018-01-30 10:08:57 -0500842#In LCD_Text
843#Line # sets or clears LCD_Text ##
Cary Clark09d80c02018-10-31 12:14:03 -0400844#Populate
Cary Clark8032b982017-07-28 11:04:54 -0400845
Cary Clark09d80c02018-10-31 12:14:03 -0400846#Example
Cary Clark8032b982017-07-28 11:04:54 -0400847 SkPaint paint1, paint2;
848 paint1.setLCDRenderText(true);
849 paint2.setFlags(paint2.getFlags() | SkPaint::kLCDRenderText_Flag);
850 SkDebugf("paint1 %c= paint2\n", paint1 == paint2 ? '=' : '!');
851
852 #StdOut
853 paint1 == paint2
854 ##
855 ##
856
857
858##
859
Cary Clark8032b982017-07-28 11:04:54 -0400860# ------------------------------------------------------------------------------
Cary Clark08895c42018-02-01 09:37:32 -0500861#Subtopic Font_Embedded_Bitmaps
862#Line # custom sized bitmap Glyphs ##
Cary Clark137b8742018-05-30 09:21:49 -0400863#Alias Font_Embedded_Bitmaps ## # long-winded enough, alias so I don't type Paint_Font_...
Cary Clark8032b982017-07-28 11:04:54 -0400864
Cary Clarkce101242017-09-01 15:51:02 -0400865Font_Embedded_Bitmaps allows selecting custom sized bitmap Glyphs.
Cary Clark8032b982017-07-28 11:04:54 -0400866Flags kEmbeddedBitmapText_Flag when set chooses an embedded bitmap glyph over an outline contained
Herb Derbyfcac00f2018-05-01 11:57:56 -0400867in a font if the platform supports this option.
Cary Clark8032b982017-07-28 11:04:54 -0400868
869FreeType selects the bitmap glyph if available when kEmbeddedBitmapText_Flag is set, and selects
870the outline glyph if kEmbeddedBitmapText_Flag is clear.
871Windows may select the bitmap glyph but is not required to do so.
872OS_X and iOS do not support this option.
873
874Font_Embedded_Bitmaps is disabled by default.
875Font_Embedded_Bitmaps can be enabled by default by setting SkPaintDefaults_Flags to
876kEmbeddedBitmapText_Flag at compile time.
877
878#Example
879 #ToDo image will only output on Ubuntu ... how to handle that in fiddle? ##
880 #Platform !fiddle
881 #Description
Cary Clarkce101242017-09-01 15:51:02 -0400882 The "hintgasp" TrueType font in the Skia resources/fonts directory
883 includes an embedded bitmap Glyph at odd font sizes. This example works
884 on platforms that use FreeType as their Font_Engine.
885 Windows may, but is not required to, return a bitmap glyph if
886 kEmbeddedBitmapText_Flag is set.
Cary Clark8032b982017-07-28 11:04:54 -0400887 ##
888 #Image embeddedbitmap.png
889
890 SkBitmap bitmap;
891 bitmap.allocN32Pixels(30, 15);
892 bitmap.eraseColor(0);
893 SkCanvas offscreen(bitmap);
894 SkPaint paint;
895 paint.setAntiAlias(true);
896 paint.setTextSize(13);
Hal Canary53e5e7d2017-12-08 14:25:14 -0500897 paint.setTypeface(MakeResourceAsTypeface("fonts/hintgasp.ttf"));
Cary Clark8032b982017-07-28 11:04:54 -0400898 for (bool embedded : { false, true}) {
899 paint.setEmbeddedBitmapText(embedded);
900 offscreen.drawString("A", embedded ? 5 : 15, 15, paint);
901 }
902 canvas->drawBitmap(bitmap, 0, 0);
903 canvas->scale(10, 10);
904 canvas->drawBitmap(bitmap, -2, 1);
905##
Cary Clarka90ea222018-10-16 10:30:28 -0400906#Subtopic Font_Embedded_Bitmaps ##
Cary Clark8032b982017-07-28 11:04:54 -0400907
908#Method bool isEmbeddedBitmapText() const
Cary Clarkab2621d2018-01-30 10:08:57 -0500909#In Font_Embedded_Bitmaps
910#Line # returns true if Font_Embedded_Bitmaps is set ##
Cary Clark09d80c02018-10-31 12:14:03 -0400911#Populate
Cary Clark8032b982017-07-28 11:04:54 -0400912
Cary Clark09d80c02018-10-31 12:14:03 -0400913#Example
Cary Clark8032b982017-07-28 11:04:54 -0400914 SkPaint paint;
915 SkDebugf("paint.isEmbeddedBitmapText() %c="
916 " !!(paint.getFlags() & SkPaint::kEmbeddedBitmapText_Flag)\n",
917 paint.isEmbeddedBitmapText() ==
918 !!(paint.getFlags() & SkPaint::kEmbeddedBitmapText_Flag) ? '=' : '!');
919 paint.setEmbeddedBitmapText(true);
920 SkDebugf("paint.isEmbeddedBitmapText() %c="
921 " !!(paint.getFlags() & SkPaint::kEmbeddedBitmapText_Flag)\n",
922 paint.isEmbeddedBitmapText() ==
923 !!(paint.getFlags() & SkPaint::kEmbeddedBitmapText_Flag) ? '=' : '!');
924
925 #StdOut
926 paint.isEmbeddedBitmapText() == !!(paint.getFlags() & SkPaint::kEmbeddedBitmapText_Flag)
927 paint.isEmbeddedBitmapText() == !!(paint.getFlags() & SkPaint::kEmbeddedBitmapText_Flag)
928 ##
929 ##
930
931##
932
933#Method void setEmbeddedBitmapText(bool useEmbeddedBitmapText)
Cary Clarkab2621d2018-01-30 10:08:57 -0500934#In Font_Embedded_Bitmaps
935#Line # sets or clears Font_Embedded_Bitmaps ##
Cary Clark09d80c02018-10-31 12:14:03 -0400936#Populate
Cary Clark8032b982017-07-28 11:04:54 -0400937
Cary Clark09d80c02018-10-31 12:14:03 -0400938#Example
Cary Clark8032b982017-07-28 11:04:54 -0400939 SkPaint paint1, paint2;
940 paint1.setEmbeddedBitmapText(true);
941 paint2.setFlags(paint2.getFlags() | SkPaint::kEmbeddedBitmapText_Flag);
942 SkDebugf("paint1 %c= paint2\n", paint1 == paint2 ? '=' : '!');
943
944 #StdOut
945 paint1 == paint2
946 ##
947 ##
948
949##
950
Cary Clark8032b982017-07-28 11:04:54 -0400951# ------------------------------------------------------------------------------
Cary Clark08895c42018-02-01 09:37:32 -0500952#Subtopic Automatic_Hinting
953#Line # always adjust glyph paths ##
Cary Clark8032b982017-07-28 11:04:54 -0400954#Substitute auto-hinting
955
Cary Clark4a23bbf2018-11-08 16:00:33 -0500956If Hinting is set to SkFontHinting::kNormal or SkFontHinting::kFull, Automatic_Hinting
Cary Clarkce101242017-09-01 15:51:02 -0400957instructs the Font_Manager to always hint Glyphs.
Cary Clark777eede2018-11-09 16:04:58 -0500958Automatic_Hinting has no effect if Hinting is set to SkFontHinting::kNone or
959SkFontHinting::kSlight.
Cary Clark8032b982017-07-28 11:04:54 -0400960
961Automatic_Hinting only affects platforms that use FreeType as the Font_Manager.
Cary Clarka90ea222018-10-16 10:30:28 -0400962#Subtopic Automatic_Hinting ##
Cary Clark8032b982017-07-28 11:04:54 -0400963
964#Method bool isAutohinted() const
Cary Clarkab2621d2018-01-30 10:08:57 -0500965#In Automatic_Hinting
966#Line # returns true if Glyphs are always hinted ##
Cary Clark09d80c02018-10-31 12:14:03 -0400967#Populate
Cary Clark8032b982017-07-28 11:04:54 -0400968
Cary Clark09d80c02018-10-31 12:14:03 -0400969#Example
Cary Clark8032b982017-07-28 11:04:54 -0400970 SkPaint paint;
971 for (auto forceAutoHinting : { false, true} ) {
972 paint.setAutohinted(forceAutoHinting);
973 SkDebugf("paint.isAutohinted() %c="
974 " !!(paint.getFlags() & SkPaint::kAutoHinting_Flag)\n",
975 paint.isAutohinted() ==
976 !!(paint.getFlags() & SkPaint::kAutoHinting_Flag) ? '=' : '!');
977 }
978 #StdOut
979 paint.isAutohinted() == !!(paint.getFlags() & SkPaint::kAutoHinting_Flag)
980 paint.isAutohinted() == !!(paint.getFlags() & SkPaint::kAutoHinting_Flag)
981 ##
982 ##
983
984 #SeeAlso setAutohinted Hinting
985
986##
987
988#Method void setAutohinted(bool useAutohinter)
Cary Clarkab2621d2018-01-30 10:08:57 -0500989#In Automatic_Hinting
990#Line # sets Glyphs to always be hinted ##
Cary Clark09d80c02018-10-31 12:14:03 -0400991#Populate
Cary Clark8032b982017-07-28 11:04:54 -0400992
Cary Clark09d80c02018-10-31 12:14:03 -0400993#Example
Cary Clark8032b982017-07-28 11:04:54 -0400994 void draw(SkCanvas* canvas) {
995 SkPaint paint;
996 paint.setAntiAlias(true);
997 const char testStr[] = "xxxx xxxx";
998 for (auto forceAutoHinting : { false, true} ) {
999 paint.setAutohinted(forceAutoHinting);
1000 paint.setTextSize(24);
1001 canvas->drawString(paint.isAutohinted() ? "auto-hinted" : "default", 108, 30, paint);
1002 for (SkScalar textSize = 8; textSize < 30; textSize *= 1.22f) {
1003 paint.setTextSize(textSize);
1004 canvas->translate(0, textSize);
1005 canvas->drawString(testStr, 10, 0, paint);
1006 }
1007 }
1008 }
1009 ##
1010
1011 #SeeAlso isAutohinted Hinting
1012
1013##
1014
Cary Clark8032b982017-07-28 11:04:54 -04001015# ------------------------------------------------------------------------------
Cary Clark8032b982017-07-28 11:04:54 -04001016
Cary Clark08895c42018-02-01 09:37:32 -05001017#Subtopic Fake_Bold
1018#Line # approximate font styles ##
Cary Clark8032b982017-07-28 11:04:54 -04001019
1020Fake_Bold approximates the bold font style accompanying a normal font when a bold font face
1021is not available. Skia does not provide font substitution; it is up to the client to find the
Cary Clarkbc5697d2017-10-04 14:31:33 -04001022bold font face using the platform Font_Manager.
Cary Clark8032b982017-07-28 11:04:54 -04001023
Herb Derbyfcac00f2018-05-01 11:57:56 -04001024Use Text_Skew_X to approximate an italic font style when the italic font face
Cary Clark8032b982017-07-28 11:04:54 -04001025is not available.
1026
Cary Clarkce101242017-09-01 15:51:02 -04001027A FreeType based port may define SK_USE_FREETYPE_EMBOLDEN at compile time to direct
1028the font engine to create the bold Glyphs. Otherwise, the extra bold is computed
Herb Derbyfcac00f2018-05-01 11:57:56 -04001029by increasing the stroke width and setting the Style to kStrokeAndFill_Style as needed.
Cary Clark8032b982017-07-28 11:04:54 -04001030
1031Fake_Bold is disabled by default.
1032
1033#Example
1034#Height 128
1035void draw(SkCanvas* canvas) {
1036 SkPaint paint;
1037 paint.setAntiAlias(true);
1038 paint.setTextSize(40);
1039 canvas->drawString("OjYy_-", 10, 35, paint);
1040 paint.setFakeBoldText(true);
1041 canvas->drawString("OjYy_-", 10, 75, paint);
1042 // create a custom fake bold by varying the stroke width
1043 paint.setFakeBoldText(false);
1044 paint.setStyle(SkPaint::kStrokeAndFill_Style);
1045 paint.setStrokeWidth(40.f / 48);
1046 canvas->drawString("OjYy_-", 10, 115, paint);
1047}
1048##
Cary Clarka90ea222018-10-16 10:30:28 -04001049#Subtopic Fake_Bold ##
Cary Clark8032b982017-07-28 11:04:54 -04001050
1051#Method bool isFakeBoldText() const
Cary Clarkab2621d2018-01-30 10:08:57 -05001052#In Fake_Bold
1053#Line # returns true if Fake_Bold is set ##
Cary Clark09d80c02018-10-31 12:14:03 -04001054#Populate
Cary Clark8032b982017-07-28 11:04:54 -04001055
Cary Clark09d80c02018-10-31 12:14:03 -04001056#Example
Cary Clark8032b982017-07-28 11:04:54 -04001057 SkPaint paint;
1058 SkDebugf("paint.isFakeBoldText() %c= !!(paint.getFlags() & SkPaint::kFakeBoldText_Flag)\n",
1059 paint.isFakeBoldText() == !!(paint.getFlags() & SkPaint::kFakeBoldText_Flag) ? '=' : '!');
1060 paint.setFakeBoldText(true);
1061 SkDebugf("paint.isFakeBoldText() %c= !!(paint.getFlags() & SkPaint::kFakeBoldText_Flag)\n",
1062 paint.isFakeBoldText() == !!(paint.getFlags() & SkPaint::kFakeBoldText_Flag) ? '=' : '!');
1063
1064 #StdOut
1065 paint.isFakeBoldText() == !!(paint.getFlags() & SkPaint::kFakeBoldText_Flag)
1066 paint.isFakeBoldText() == !!(paint.getFlags() & SkPaint::kFakeBoldText_Flag)
1067 ##
1068 ##
1069
1070##
1071
1072#Method void setFakeBoldText(bool fakeBoldText)
Cary Clarkab2621d2018-01-30 10:08:57 -05001073#In Fake_Bold
1074#Line # sets or clears Fake_Bold ##
Cary Clark09d80c02018-10-31 12:14:03 -04001075#Populate
Cary Clark8032b982017-07-28 11:04:54 -04001076
Cary Clark09d80c02018-10-31 12:14:03 -04001077#Example
Cary Clark8032b982017-07-28 11:04:54 -04001078 SkPaint paint1, paint2;
1079 paint1.setFakeBoldText(true);
1080 paint2.setFlags(paint2.getFlags() | SkPaint::kFakeBoldText_Flag);
1081 SkDebugf("paint1 %c= paint2\n", paint1 == paint2 ? '=' : '!');
1082
1083 #StdOut
1084 paint1 == paint2
1085 ##
1086 ##
1087
1088##
1089
Cary Clark8032b982017-07-28 11:04:54 -04001090# ------------------------------------------------------------------------------
Cary Clark08895c42018-02-01 09:37:32 -05001091#Subtopic Full_Hinting_Spacing
1092#Line # glyph spacing affected by hinting ##
Cary Clark137b8742018-05-30 09:21:49 -04001093#Alias Full_Hinting_Spacing ## # long winded enough -- maybe things with two underscores auto-aliased?
Cary Clark8032b982017-07-28 11:04:54 -04001094
Cary Clark777eede2018-11-09 16:04:58 -05001095if Hinting is set to SkFontHinting::kFull, Full_Hinting_Spacing adjusts the character
Cary Clark09d80c02018-10-31 12:14:03 -04001096spacing by the difference of the hinted and unhinted Left_Side_Bearing and
Cary Clarkce101242017-09-01 15:51:02 -04001097Right_Side_Bearing. Full_Hinting_Spacing only applies to platforms that use
1098FreeType as their Font_Engine.
Cary Clark8032b982017-07-28 11:04:54 -04001099
Cary Clark09d80c02018-10-31 12:14:03 -04001100Full_Hinting_Spacing is not related to text kerning, where the space between
1101a specific pair of characters is adjusted using data in the font kerning tables.
Cary Clarka90ea222018-10-16 10:30:28 -04001102#Subtopic Full_Hinting_Spacing ##
Cary Clark8032b982017-07-28 11:04:54 -04001103
Cary Clark8032b982017-07-28 11:04:54 -04001104# ------------------------------------------------------------------------------
Cary Clark08895c42018-02-01 09:37:32 -05001105#Subtopic Filter_Quality_Methods
1106#Line # get and set Filter_Quality ##
Cary Clark8032b982017-07-28 11:04:54 -04001107
1108Filter_Quality trades speed for image filtering when the image is scaled.
1109A lower Filter_Quality draws faster, but has less fidelity.
1110A higher Filter_Quality draws slower, but looks better.
Cary Clarkce101242017-09-01 15:51:02 -04001111If the image is drawn without scaling, the Filter_Quality choice will not result
1112in a noticeable difference.
Cary Clark8032b982017-07-28 11:04:54 -04001113
1114Filter_Quality is used in Paint passed as a parameter to
1115#List
1116# SkCanvas::drawBitmap ##
1117# SkCanvas::drawBitmapRect ##
1118# SkCanvas::drawImage ##
1119# SkCanvas::drawImageRect ##
1120 #ToDo probably more... ##
1121#List ##
1122and when Paint has a Shader specialization that uses Image or Bitmap.
1123
1124Filter_Quality is kNone_SkFilterQuality by default.
1125
1126#Example
1127#Image 3
1128void draw(SkCanvas* canvas) {
1129 SkPaint paint;
1130 canvas->scale(.2f, .2f);
Herb Derbyfcac00f2018-05-01 11:57:56 -04001131 for (SkFilterQuality q : { kNone_SkFilterQuality, kLow_SkFilterQuality,
Cary Clark8032b982017-07-28 11:04:54 -04001132 kMedium_SkFilterQuality, kHigh_SkFilterQuality } ) {
1133 paint.setFilterQuality(q);
1134 canvas->drawImage(image.get(), 0, 0, &paint);
1135 canvas->translate(550, 0);
1136 if (kLow_SkFilterQuality == q) canvas->translate(-1100, 550);
1137 }
1138}
1139##
Cary Clarka90ea222018-10-16 10:30:28 -04001140#Subtopic Filter_Quality_Methods ##
Cary Clark8032b982017-07-28 11:04:54 -04001141
1142#Method SkFilterQuality getFilterQuality() const
Cary Clarkab2621d2018-01-30 10:08:57 -05001143#In Filter_Quality_Methods
1144#Line # returns Filter_Quality, image filtering level ##
Cary Clark09d80c02018-10-31 12:14:03 -04001145#Populate
Cary Clark8032b982017-07-28 11:04:54 -04001146
1147#Example
1148 SkPaint paint;
1149 SkDebugf("kNone_SkFilterQuality %c= paint.getFilterQuality()\n",
1150 kNone_SkFilterQuality == paint.getFilterQuality() ? '=' : '!');
1151
1152 #StdOut
1153 kNone_SkFilterQuality == paint.getFilterQuality()
1154 ##
1155##
1156
1157##
1158
1159
1160#Method void setFilterQuality(SkFilterQuality quality)
Cary Clarkab2621d2018-01-30 10:08:57 -05001161#In Filter_Quality_Methods
1162#Line # sets Filter_Quality, the image filtering level ##
Cary Clark09d80c02018-10-31 12:14:03 -04001163#Populate
Cary Clark8032b982017-07-28 11:04:54 -04001164
1165#Example
1166 SkPaint paint;
1167 paint.setFilterQuality(kHigh_SkFilterQuality);
1168 SkDebugf("kHigh_SkFilterQuality %c= paint.getFilterQuality()\n",
1169 kHigh_SkFilterQuality == paint.getFilterQuality() ? '=' : '!');
1170
1171 #StdOut
1172 kHigh_SkFilterQuality == paint.getFilterQuality()
1173 ##
1174##
1175
1176#SeeAlso SkFilterQuality Image_Scaling
1177
1178##
1179
Cary Clark8032b982017-07-28 11:04:54 -04001180# ------------------------------------------------------------------------------
Cary Clark08895c42018-02-01 09:37:32 -05001181#Subtopic Color_Methods
1182#Line # get and set Color ##
Cary Clark8032b982017-07-28 11:04:54 -04001183
Cary Clarkab2621d2018-01-30 10:08:57 -05001184#Table
1185#Legend
1186# name # description ##
1187#Legend ##
Cary Clarkffb3d682018-05-17 12:17:28 -04001188# getColor # returns Color_Alpha and RGB, one drawing color ##
1189# setColor # sets Color_Alpha and RGB, one drawing color ##
Cary Clarkab2621d2018-01-30 10:08:57 -05001190#Table ##
Cary Clark8032b982017-07-28 11:04:54 -04001191
Cary Clarkffb3d682018-05-17 12:17:28 -04001192Color specifies the red, blue, green, and Color_Alpha
Cary Clarkab2621d2018-01-30 10:08:57 -05001193values used to draw a filled or stroked shape in a 32-bit value. Each component
1194occupies 8-bits, ranging from zero: no contribution; to 255: full intensity.
1195All values in any combination are valid.
Cary Clark8032b982017-07-28 11:04:54 -04001196
Cary Clarkab2621d2018-01-30 10:08:57 -05001197Color is not Premultiplied; Color_Alpha sets the transparency independent of
Cary Clarkffb3d682018-05-17 12:17:28 -04001198RGB: red, blue, and green.
Cary Clarkab2621d2018-01-30 10:08:57 -05001199
Cary Clarkffb3d682018-05-17 12:17:28 -04001200The bit positions of Color_Alpha and RGB are independent of the bit
Cary Clarkab2621d2018-01-30 10:08:57 -05001201positions on the output device, which may have more or fewer bits, and may have
1202a different arrangement.
Cary Clark8032b982017-07-28 11:04:54 -04001203
1204#Table
1205#Legend
Cary Clarkffb3d682018-05-17 12:17:28 -04001206# bit positions # Color_Alpha # red # blue # green ##
Cary Clark8032b982017-07-28 11:04:54 -04001207#Legend ##
1208# # 31 - 24 # 23 - 16 # 15 - 8 # 7 - 0 ##
1209#Table ##
1210
1211#Example
1212#Height 128
1213 void draw(SkCanvas* canvas) {
1214 SkPaint paint;
1215 paint.setColor(0x8000FF00); // transparent green
1216 canvas->drawCircle(50, 50, 40, paint);
1217 paint.setARGB(128, 255, 0, 0); // transparent red
1218 canvas->drawCircle(80, 50, 40, paint);
1219 paint.setColor(SK_ColorBLUE);
1220 paint.setAlpha(0x80);
1221 canvas->drawCircle(65, 65, 40, paint);
1222 }
1223##
Cary Clarka90ea222018-10-16 10:30:28 -04001224#Subtopic Color_Methods ##
Cary Clark8032b982017-07-28 11:04:54 -04001225
1226#Method SkColor getColor() const
Cary Clarkab2621d2018-01-30 10:08:57 -05001227#In Color_Methods
Cary Clarkffb3d682018-05-17 12:17:28 -04001228#Line # returns Color_Alpha and RGB, one drawing color ##
Cary Clark09d80c02018-10-31 12:14:03 -04001229#Populate
Cary Clark8032b982017-07-28 11:04:54 -04001230
Cary Clark09d80c02018-10-31 12:14:03 -04001231#Example
Cary Clark8032b982017-07-28 11:04:54 -04001232 SkPaint paint;
1233 paint.setColor(SK_ColorYELLOW);
1234 SkColor y = paint.getColor();
1235 SkDebugf("Yellow is %d%% red, %d%% green, and %d%% blue.\n", (int) (SkColorGetR(y) / 2.55f),
1236 (int) (SkColorGetG(y) / 2.55f), (int) (SkColorGetB(y) / 2.55f));
1237
1238 #StdOut
1239 Yellow is 100% red, 100% green, and 0% blue.
1240 ##
1241 ##
1242
Cary Clarkbbe8ff92018-09-05 11:39:01 -04001243 #SeeAlso getColor4f SkColor
Cary Clark8032b982017-07-28 11:04:54 -04001244
1245##
1246
Cary Clarkbbe8ff92018-09-05 11:39:01 -04001247#Method SkColor4f getColor4f() const
1248#In Color_Methods
1249#Line # returns Color_Alpha and RGB, one drawing color ##
Cary Clark09d80c02018-10-31 12:14:03 -04001250#Populate
Brian Osman3f70d172018-09-04 19:50:28 +00001251
Cary Clark09d80c02018-10-31 12:14:03 -04001252#Example
Cary Clarkbbe8ff92018-09-05 11:39:01 -04001253 SkPaint paint;
1254 paint.setColor(SK_ColorYELLOW);
1255 SkColor4f y = paint.getColor4f();
1256 SkDebugf("Yellow is %d%% red, %d%% green, and %d%% blue.\n", (int) (y.fR * 100),
1257 (int) (y.fG * 100), (int) (y.fB * 100));
1258
1259 #StdOut
1260 Yellow is 100% red, 100% green, and 0% blue.
1261 ##
1262 ##
1263
1264 #SeeAlso getColor SkColor
1265##
1266
1267
1268#Method void setColor(SkColor color)
Cary Clarkab2621d2018-01-30 10:08:57 -05001269#In Color_Methods
Cary Clarkffb3d682018-05-17 12:17:28 -04001270#Line # sets Color_Alpha and RGB, one drawing color ##
Cary Clark09d80c02018-10-31 12:14:03 -04001271#Populate
Cary Clark8032b982017-07-28 11:04:54 -04001272
Cary Clark09d80c02018-10-31 12:14:03 -04001273#Example
Cary Clark8032b982017-07-28 11:04:54 -04001274 SkPaint green1, green2;
1275 unsigned a = 255;
1276 unsigned r = 0;
1277 unsigned g = 255;
1278 unsigned b = 0;
1279 green1.setColor((a << 24) + (r << 16) + (g << 8) + (b << 0));
1280 green2.setColor(0xFF00FF00);
1281 SkDebugf("green1 %c= green2\n", green1 == green2 ? '=' : '!');
1282
1283 #StdOut
1284 green1 == green2
1285 ##
1286 ##
1287
Cary Clarkbbe8ff92018-09-05 11:39:01 -04001288 #SeeAlso SkColor setColor4f setARGB SkColorSetARGB
Cary Clark8032b982017-07-28 11:04:54 -04001289
1290##
Cary Clarkbbe8ff92018-09-05 11:39:01 -04001291
1292#Method void setColor4f(const SkColor4f& color, SkColorSpace* colorSpace)
1293#In Color_Methods
1294#Line # sets Color_Alpha and RGB, one drawing color ##
Cary Clark09d80c02018-10-31 12:14:03 -04001295#Populate
Cary Clarkbbe8ff92018-09-05 11:39:01 -04001296
Cary Clark09d80c02018-10-31 12:14:03 -04001297#Example
Cary Clarkbbe8ff92018-09-05 11:39:01 -04001298 SkPaint green1, green2;
1299 green1.setColor4f({0, 1, 0, 1}, nullptr); // R=0 G=1 B=0 A=1
1300 green2.setColor(0xFF00FF00); // A=255 R=0 G=255 B=0
1301 SkDebugf("green1 %c= green2\n", green1 == green2 ? '=' : '!');
1302
1303 #StdOut
1304 green1 == green2
1305 ##
1306 ##
1307
1308 #SeeAlso SkColor setColor setARGB SkColorSetARGB
1309
1310##
1311
Cary Clark8032b982017-07-28 11:04:54 -04001312#Subtopic Alpha_Methods
Cary Clark08895c42018-02-01 09:37:32 -05001313#Line # get and set Alpha ##
Cary Clark8032b982017-07-28 11:04:54 -04001314
Cary Clarkffb3d682018-05-17 12:17:28 -04001315Color_Alpha sets the transparency independent of RGB: red, blue, and green.
Cary Clarka90ea222018-10-16 10:30:28 -04001316#Subtopic Alpha_Methods ##
Cary Clark8032b982017-07-28 11:04:54 -04001317
1318#Method uint8_t getAlpha() const
Cary Clarkab2621d2018-01-30 10:08:57 -05001319#In Alpha_Methods
1320#Line # returns Color_Alpha, color opacity ##
Cary Clark09d80c02018-10-31 12:14:03 -04001321#Populate
Cary Clark8032b982017-07-28 11:04:54 -04001322
Cary Clark09d80c02018-10-31 12:14:03 -04001323#Example
Cary Clark8032b982017-07-28 11:04:54 -04001324 SkPaint paint;
1325 SkDebugf("255 %c= paint.getAlpha()\n", 255 == paint.getAlpha() ? '=' : '!');
1326
1327 #StdOut
1328 255 == paint.getAlpha()
1329 ##
1330 ##
1331
1332##
1333
1334#Method void setAlpha(U8CPU a)
Cary Clarkab2621d2018-01-30 10:08:57 -05001335#In Alpha_Methods
1336#Line # sets Color_Alpha, color opacity ##
Cary Clark09d80c02018-10-31 12:14:03 -04001337#Populate
Cary Clark8032b982017-07-28 11:04:54 -04001338
Cary Clark09d80c02018-10-31 12:14:03 -04001339#Example
Cary Clark8032b982017-07-28 11:04:54 -04001340 SkPaint paint;
1341 paint.setColor(0x00112233);
1342 paint.setAlpha(0x44);
1343 SkDebugf("0x44112233 %c= paint.getColor()\n", 0x44112233 == paint.getColor() ? '=' : '!');
1344
1345 #StdOut
1346 0x44112233 == paint.getColor()
1347 ##
1348 ##
1349
1350##
1351
Cary Clark8032b982017-07-28 11:04:54 -04001352#Method void setARGB(U8CPU a, U8CPU r, U8CPU g, U8CPU b)
Cary Clarkab2621d2018-01-30 10:08:57 -05001353#In Color_Methods
1354#Line # sets color by component ##
Cary Clark09d80c02018-10-31 12:14:03 -04001355#Populate
Cary Clark8032b982017-07-28 11:04:54 -04001356
Cary Clark09d80c02018-10-31 12:14:03 -04001357#Example
Cary Clark8032b982017-07-28 11:04:54 -04001358 SkPaint transRed1, transRed2;
1359 transRed1.setARGB(255 / 2, 255, 0, 0);
1360 transRed2.setColor(SkColorSetARGB(255 / 2, 255, 0, 0));
1361 SkDebugf("transRed1 %c= transRed2", transRed1 == transRed2 ? '=' : '!');
1362
1363 #StdOut
1364 transRed1 == transRed2
1365 ##
1366 ##
1367
1368 #SeeAlso setColor SkColorSetARGB
1369
1370##
1371
Cary Clark8032b982017-07-28 11:04:54 -04001372# ------------------------------------------------------------------------------
Cary Clark08895c42018-02-01 09:37:32 -05001373#Subtopic Style
1374#Line # geometry filling, stroking ##
Cary Clark8032b982017-07-28 11:04:54 -04001375
1376Style specifies if the geometry is filled, stroked, or both filled and stroked.
1377Some shapes ignore Style and are always drawn filled or stroked.
1378
Cary Clarka90ea222018-10-16 10:30:28 -04001379#Subtopic Fill
Cary Clark8032b982017-07-28 11:04:54 -04001380Set Style to kFill_Style to fill the shape.
1381The fill covers the area inside the geometry for most shapes.
Cary Clark08895c42018-02-01 09:37:32 -05001382#Subtopic Fill ##
Cary Clark8032b982017-07-28 11:04:54 -04001383
1384#Subtopic Stroke
Cary Clarka90ea222018-10-16 10:30:28 -04001385Set Style to kStroke_Style to stroke the shape.
1386
Cary Clarkbc5697d2017-10-04 14:31:33 -04001387The stroke covers the area described by following the shape edge with a pen or brush of
Cary Clark8032b982017-07-28 11:04:54 -04001388Stroke_Width. The area covered where the shape starts and stops is described by Stroke_Cap.
1389The area covered where the shape turns a corner is described by Stroke_Join.
Cary Clarkbc5697d2017-10-04 14:31:33 -04001390The stroke is centered on the shape; it extends equally on either side of the shape edge.
Cary Clarka90ea222018-10-16 10:30:28 -04001391#Subtopic Stroke ##
Cary Clark8032b982017-07-28 11:04:54 -04001392
1393As Stroke_Width gets smaller, the drawn path frame is thinner. Stroke_Width less than one
1394may have gaps, and if kAntiAlias_Flag is set, Color_Alpha will increase to visually decrease coverage.
Cary Clarka90ea222018-10-16 10:30:28 -04001395
1396#SeeAlso Path_Fill_Type Path_Effect Style_Fill Style_Stroke
1397#Subtopic Style ##
Cary Clark8032b982017-07-28 11:04:54 -04001398
1399#Subtopic Hairline
Cary Clark8032b982017-07-28 11:04:54 -04001400Stroke_Width of zero has a special meaning and switches drawing to use Hairline.
Herb Derbyfcac00f2018-05-01 11:57:56 -04001401Hairline draws the thinnest continuous frame. If kAntiAlias_Flag is clear, adjacent pixels
1402flow horizontally, vertically,or diagonally.
Cary Clark8032b982017-07-28 11:04:54 -04001403
Cary Clarkffb3d682018-05-17 12:17:28 -04001404#ToDo what is the description of Anti_Aliased hairlines? ##
Cary Clark8032b982017-07-28 11:04:54 -04001405
1406Path drawing with Hairline may hit the same pixel more than once. For instance, Path containing
1407two lines in one Path_Contour will draw the corner point once, but may both lines may draw the adjacent
1408pixel. If kAntiAlias_Flag is set, transparency is applied twice, resulting in a darker pixel. Some
1409GPU-backed implementations apply transparency at a later drawing stage, avoiding double hit pixels
1410while stroking.
1411
Cary Clarka90ea222018-10-16 10:30:28 -04001412#SeeAlso Path_Fill_Type Path_Effect Style_Fill Style_Stroke
Cary Clark08895c42018-02-01 09:37:32 -05001413#Subtopic Hairline ##
Cary Clark8032b982017-07-28 11:04:54 -04001414
1415#Enum Style
Cary Clark08895c42018-02-01 09:37:32 -05001416#Line # stroke, fill, or both ##
Cary Clark8032b982017-07-28 11:04:54 -04001417
1418#Code
Cary Clarka90ea222018-10-16 10:30:28 -04001419#Populate
1420##
Cary Clarkd98f78c2018-04-26 08:32:37 -04001421
Cary Clarka90ea222018-10-16 10:30:28 -04001422#Code
1423#In Constant
1424#Filter kStyle
1425#Populate
Cary Clark8032b982017-07-28 11:04:54 -04001426##
1427
1428Set Style to fill, stroke, or both fill and stroke geometry.
1429The stroke and fill
1430share all paint attributes; for instance, they are drawn with the same color.
1431
1432Use kStrokeAndFill_Style to avoid hitting the same pixels twice with a stroke draw and
1433a fill draw.
1434
1435#Const kFill_Style 0
Cary Clark682c58d2018-05-16 07:07:07 -04001436#Line # set to fill geometry ##
Herb Derbyfcac00f2018-05-01 11:57:56 -04001437 Applies to Rect, Region, Round_Rect, Circles, Ovals, Path, and Text.
Cary Clarkce101242017-09-01 15:51:02 -04001438 Bitmap, Image, Patches, Region, Sprites, and Vertices are painted as if
Cary Clark8032b982017-07-28 11:04:54 -04001439 kFill_Style is set, and ignore the set Style.
1440 The Path_Fill_Type specifies additional rules to fill the area outside the path edge,
1441 and to create an unfilled hole inside the shape.
1442 Style is set to kFill_Style by default.
1443##
1444
1445#Const kStroke_Style 1
Cary Clark682c58d2018-05-16 07:07:07 -04001446#Line # set to stroke geometry ##
Herb Derbyfcac00f2018-05-01 11:57:56 -04001447 Applies to Rect, Region, Round_Rect, Arcs, Circles, Ovals, Path, and Text.
Cary Clark56356312018-02-08 14:45:18 -05001448 Arcs, Lines, and points, are always drawn as if kStroke_Style is set,
Cary Clark8032b982017-07-28 11:04:54 -04001449 and ignore the set Style.
1450 The stroke construction is unaffected by the Path_Fill_Type.
1451##
1452
1453#Const kStrokeAndFill_Style 2
Cary Clark682c58d2018-05-16 07:07:07 -04001454#Line # sets to stroke and fill geometry ##
Cary Clarkce101242017-09-01 15:51:02 -04001455 Applies to Rect, Region, Round_Rect, Circles, Ovals, Path, and Text.
Cary Clark8032b982017-07-28 11:04:54 -04001456 Path is treated as if it is set to SkPath::kWinding_FillType,
Herb Derbyfcac00f2018-05-01 11:57:56 -04001457 and the set Path_Fill_Type is ignored.
Cary Clark8032b982017-07-28 11:04:54 -04001458##
1459
Cary Clark8032b982017-07-28 11:04:54 -04001460#Const kStyleCount 3
Cary Clark682c58d2018-05-16 07:07:07 -04001461#Line # number of different Style values defined ##
Cary Clark8032b982017-07-28 11:04:54 -04001462May be used to verify that Style is a legal value.
1463##
1464
Cary Clarkd98f78c2018-04-26 08:32:37 -04001465#Enum Style ##
Cary Clark8032b982017-07-28 11:04:54 -04001466
1467#Method Style getStyle() const
Cary Clarkab2621d2018-01-30 10:08:57 -05001468#In Style
1469#Line # returns Style: stroke, fill, or both ##
Cary Clark09d80c02018-10-31 12:14:03 -04001470#Populate
Cary Clark8032b982017-07-28 11:04:54 -04001471
Cary Clark09d80c02018-10-31 12:14:03 -04001472#Example
Cary Clark8032b982017-07-28 11:04:54 -04001473 SkPaint paint;
1474 SkDebugf("SkPaint::kFill_Style %c= paint.getStyle()\n",
1475 SkPaint::kFill_Style == paint.getStyle() ? '=' : '!');
1476
1477 #StdOut
1478 SkPaint::kFill_Style == paint.getStyle()
1479 ##
1480 ##
1481
1482#SeeAlso Style setStyle
1483##
1484
1485#Method void setStyle(Style style)
Cary Clarkab2621d2018-01-30 10:08:57 -05001486#In Style
1487#Line # sets Style: stroke, fill, or both ##
Cary Clark09d80c02018-10-31 12:14:03 -04001488#Populate
Cary Clark8032b982017-07-28 11:04:54 -04001489
Cary Clark09d80c02018-10-31 12:14:03 -04001490#Example
Cary Clark8032b982017-07-28 11:04:54 -04001491 void draw(SkCanvas* canvas) {
1492 SkPaint paint;
1493 paint.setStrokeWidth(5);
1494 SkRegion region;
1495 region.op(140, 10, 160, 30, SkRegion::kUnion_Op);
1496 region.op(170, 40, 190, 60, SkRegion::kUnion_Op);
1497 SkBitmap bitmap;
1498 bitmap.setInfo(SkImageInfo::MakeA8(50, 50), 50);
1499 uint8_t pixels[50][50];
1500 for (int x = 0; x < 50; ++x) {
1501 for (int y = 0; y < 50; ++y) {
1502 pixels[y][x] = (x + y) % 5 ? 0xFF : 0x00;
1503 }
1504 }
1505 bitmap.setPixels(pixels);
1506 for (auto style : { SkPaint::kFill_Style,
1507 SkPaint::kStroke_Style,
1508 SkPaint::kStrokeAndFill_Style }) {
1509 paint.setStyle(style);
1510 canvas->drawLine(10, 10, 60, 60, paint);
1511 canvas->drawRect({80, 10, 130, 60}, paint);
1512 canvas->drawRegion(region, paint);
1513 canvas->drawBitmap(bitmap, 200, 10, &paint);
1514 canvas->translate(0, 80);
1515 }
1516 }
1517 ##
1518
1519#SeeAlso Style getStyle
1520##
1521
Cary Clark8032b982017-07-28 11:04:54 -04001522# ------------------------------------------------------------------------------
Cary Clark08895c42018-02-01 09:37:32 -05001523#Subtopic Stroke_Width
1524#Line # thickness perpendicular to geometry ##
Cary Clark8032b982017-07-28 11:04:54 -04001525
1526Stroke_Width sets the width for stroking. The width is the thickness
Herb Derbyfcac00f2018-05-01 11:57:56 -04001527of the stroke perpendicular to the path direction when the paint style is
Cary Clark8032b982017-07-28 11:04:54 -04001528set to kStroke_Style or kStrokeAndFill_Style.
1529
1530When width is greater than zero, the stroke encompasses as many pixels partially
1531or fully as needed. When the width equals zero, the paint enables hairlines;
Herb Derbyfcac00f2018-05-01 11:57:56 -04001532the stroke is always one pixel wide.
Cary Clark8032b982017-07-28 11:04:54 -04001533
Cary Clarkbc5697d2017-10-04 14:31:33 -04001534The stroke dimensions are scaled by the canvas matrix, but Hairline stroke
Cary Clark8032b982017-07-28 11:04:54 -04001535remains one pixel wide regardless of scaling.
1536
1537The default width for the paint is zero.
1538
1539#Example
1540#Height 170
1541 #Platform raster gpu
1542 #Description
Herb Derbyfcac00f2018-05-01 11:57:56 -04001543 The pixels hit to represent thin lines vary with the angle of the
Cary Clarkbc5697d2017-10-04 14:31:33 -04001544 line and the platform implementation.
Cary Clark8032b982017-07-28 11:04:54 -04001545 ##
1546 void draw(SkCanvas* canvas) {
1547 SkPaint paint;
Herb Derbyfcac00f2018-05-01 11:57:56 -04001548 for (bool antialias : { false, true }) {
Cary Clark8032b982017-07-28 11:04:54 -04001549 paint.setAntiAlias(antialias);
1550 for (int width = 0; width <= 4; ++width) {
1551 SkScalar offset = antialias * 100 + width * 20;
1552 paint.setStrokeWidth(width * 0.25f);
1553 canvas->drawLine(10 + offset, 10, 20 + offset, 60, paint);
1554 canvas->drawLine(10 + offset, 110, 60 + offset, 160, paint);
1555 }
1556 }
1557 }
1558##
1559
1560#Method SkScalar getStrokeWidth() const
1561
Cary Clarkab2621d2018-01-30 10:08:57 -05001562#In Stroke_Width
1563#Line # returns thickness of the stroke ##
Cary Clark09d80c02018-10-31 12:14:03 -04001564#Populate
Cary Clark8032b982017-07-28 11:04:54 -04001565
Cary Clark09d80c02018-10-31 12:14:03 -04001566#Example
Cary Clark8032b982017-07-28 11:04:54 -04001567 SkPaint paint;
1568 SkDebugf("0 %c= paint.getStrokeWidth()\n", 0 == paint.getStrokeWidth() ? '=' : '!');
1569
1570 #StdOut
1571 0 == paint.getStrokeWidth()
1572 ##
1573 ##
1574
1575##
1576
1577#Method void setStrokeWidth(SkScalar width)
1578
Cary Clarkab2621d2018-01-30 10:08:57 -05001579#In Stroke_Width
1580#Line # sets thickness of the stroke ##
Cary Clark09d80c02018-10-31 12:14:03 -04001581#Populate
Cary Clark8032b982017-07-28 11:04:54 -04001582
Cary Clark09d80c02018-10-31 12:14:03 -04001583#Example
Cary Clark8032b982017-07-28 11:04:54 -04001584 SkPaint paint;
1585 paint.setStrokeWidth(5);
1586 paint.setStrokeWidth(-1);
1587 SkDebugf("5 %c= paint.getStrokeWidth()\n", 5 == paint.getStrokeWidth() ? '=' : '!');
1588
1589 #StdOut
1590 5 == paint.getStrokeWidth()
1591 ##
1592 ##
1593
1594##
1595
Cary Clark08895c42018-02-01 09:37:32 -05001596#Subtopic Stroke_Width ##
Cary Clark8032b982017-07-28 11:04:54 -04001597# ------------------------------------------------------------------------------
Cary Clark08895c42018-02-01 09:37:32 -05001598#Subtopic Miter_Limit
1599#Line # maximum length of stroked corners ##
Cary Clark8032b982017-07-28 11:04:54 -04001600
1601Miter_Limit specifies the maximum miter length,
1602relative to the stroke width.
1603
1604Miter_Limit is used when the Stroke_Join
1605is set to kMiter_Join, and the Style is either kStroke_Style
1606or kStrokeAndFill_Style.
1607
1608If the miter at a corner exceeds this limit, kMiter_Join
1609is replaced with kBevel_Join.
1610
Cary Clark2be81cf2018-09-13 12:04:30 -04001611Miter_Limit can be computed from the corner angle using:
1612#Formula # miter limit = 1 / sin ( angle / 2 ) ##.
Cary Clark8032b982017-07-28 11:04:54 -04001613
1614Miter_Limit default value is 4.
1615The default may be changed at compile time by setting SkPaintDefaults_MiterLimit
Cary Clarkce101242017-09-01 15:51:02 -04001616in "SkUserConfig.h" or as a define supplied by the build environment.
Cary Clark8032b982017-07-28 11:04:54 -04001617
1618Here are some miter limits and the angles that triggers them.
1619#Table
1620#Legend
1621 # miter limit # angle in degrees ##
1622#Legend ##
1623 # 10 # 11.48 ##
1624 # 9 # 12.76 ##
1625 # 8 # 14.36 ##
1626 # 7 # 16.43 ##
1627 # 6 # 19.19 ##
1628 # 5 # 23.07 ##
1629 # 4 # 28.96 ##
1630 # 3 # 38.94 ##
1631 # 2 # 60 ##
1632 # 1 # 180 ##
1633#Table ##
1634
1635#Example
1636 #Height 170
1637 #Width 384
1638 #Description
1639 This example draws a stroked corner and the miter length beneath.
1640 When the miter limit is decreased slightly, the miter join is replaced
1641 by a bevel join.
1642 ##
1643 void draw(SkCanvas* canvas) {
1644 SkPoint pts[] = {{ 10, 50 }, { 110, 80 }, { 10, 110 }};
1645 SkVector v[] = { pts[0] - pts[1], pts[2] - pts[1] };
1646 SkScalar angle1 = SkScalarATan2(v[0].fY, v[0].fX);
1647 SkScalar angle2 = SkScalarATan2(v[1].fY, v[1].fX);
1648 const SkScalar strokeWidth = 20;
1649 SkScalar miterLimit = 1 / SkScalarSin((angle2 - angle1) / 2);
1650 SkScalar miterLength = strokeWidth * miterLimit;
1651 SkPath path;
1652 path.moveTo(pts[0]);
1653 path.lineTo(pts[1]);
1654 path.lineTo(pts[2]);
1655 SkPaint paint; // set to default kMiter_Join
1656 paint.setAntiAlias(true);
1657 paint.setStyle(SkPaint::kStroke_Style);
1658 paint.setStrokeMiter(miterLimit);
1659 paint.setStrokeWidth(strokeWidth);
1660 canvas->drawPath(path, paint);
1661 paint.setStrokeWidth(1);
1662 canvas->drawLine(pts[1].fX - miterLength / 2, pts[1].fY + 50,
1663 pts[1].fX + miterLength / 2, pts[1].fY + 50, paint);
1664 canvas->translate(200, 0);
1665 miterLimit *= 0.99f;
1666 paint.setStrokeMiter(miterLimit);
1667 paint.setStrokeWidth(strokeWidth);
1668 canvas->drawPath(path, paint);
1669 paint.setStrokeWidth(1);
1670 canvas->drawLine(pts[1].fX - miterLength / 2, pts[1].fY + 50,
1671 pts[1].fX + miterLength / 2, pts[1].fY + 50, paint);
1672 }
1673##
1674
1675#Method SkScalar getStrokeMiter() const
1676
Cary Clarkab2621d2018-01-30 10:08:57 -05001677#In Miter_Limit
1678#Line # returns Miter_Limit, angles with sharp corners ##
Cary Clark09d80c02018-10-31 12:14:03 -04001679#Populate
Cary Clark8032b982017-07-28 11:04:54 -04001680
Cary Clark09d80c02018-10-31 12:14:03 -04001681#Example
Cary Clark8032b982017-07-28 11:04:54 -04001682 SkPaint paint;
1683 SkDebugf("default miter limit == %g\n", paint.getStrokeMiter());
1684
1685 #StdOut
1686 default miter limit == 4
1687 ##
1688 ##
1689
1690 #SeeAlso Miter_Limit setStrokeMiter Join
1691
1692##
1693
1694#Method void setStrokeMiter(SkScalar miter)
1695
Cary Clarkab2621d2018-01-30 10:08:57 -05001696#In Miter_Limit
1697#Line # sets Miter_Limit, angles with sharp corners ##
Cary Clark09d80c02018-10-31 12:14:03 -04001698#Populate
Cary Clark8032b982017-07-28 11:04:54 -04001699
Cary Clark09d80c02018-10-31 12:14:03 -04001700#Example
Cary Clark8032b982017-07-28 11:04:54 -04001701 SkPaint paint;
1702 paint.setStrokeMiter(8);
1703 paint.setStrokeMiter(-1);
1704 SkDebugf("default miter limit == %g\n", paint.getStrokeMiter());
1705
1706 #StdOut
1707 default miter limit == 8
1708 ##
1709 ##
1710
1711 #SeeAlso Miter_Limit getStrokeMiter Join
1712
1713##
1714
Cary Clark08895c42018-02-01 09:37:32 -05001715#Subtopic Miter_Limit ##
Cary Clark8032b982017-07-28 11:04:54 -04001716# ------------------------------------------------------------------------------
Cary Clark08895c42018-02-01 09:37:32 -05001717#Subtopic Stroke_Cap
1718#Line # decorations at ends of open strokes ##
Cary Clarka90ea222018-10-16 10:30:28 -04001719#Subtopic Stroke_Cap ##
Cary Clark8032b982017-07-28 11:04:54 -04001720
1721#Enum Cap
Cary Clark08895c42018-02-01 09:37:32 -05001722#Line # start and end geometry on stroked shapes ##
Cary Clark8032b982017-07-28 11:04:54 -04001723
1724#Code
Cary Clarka90ea222018-10-16 10:30:28 -04001725#Populate
1726##
Cary Clark8032b982017-07-28 11:04:54 -04001727
Cary Clarka90ea222018-10-16 10:30:28 -04001728#Code
1729#In Constant
1730#Filter kCap
1731#Populate
Cary Clark8032b982017-07-28 11:04:54 -04001732##
1733
1734Stroke_Cap draws at the beginning and end of an open Path_Contour.
1735
1736 #Const kButt_Cap 0
Cary Clark682c58d2018-05-16 07:07:07 -04001737 #Line # no stroke extension ##
Cary Clark8032b982017-07-28 11:04:54 -04001738 Does not extend the stroke past the beginning or the end.
1739 ##
1740 #Const kRound_Cap 1
Cary Clark682c58d2018-05-16 07:07:07 -04001741 #Line # adds circle ##
Cary Clark8032b982017-07-28 11:04:54 -04001742 Adds a circle with a diameter equal to Stroke_Width at the beginning
1743 and end.
1744 ##
1745 #Const kSquare_Cap 2
Cary Clark682c58d2018-05-16 07:07:07 -04001746 #Line # adds square ##
Cary Clark8032b982017-07-28 11:04:54 -04001747 Adds a square with sides equal to Stroke_Width at the beginning
1748 and end. The square sides are parallel to the initial and final direction
1749 of the stroke.
1750 ##
1751 #Const kLast_Cap 2
Cary Clark682c58d2018-05-16 07:07:07 -04001752 #Line # largest Stroke_Cap value ##
Cary Clark8032b982017-07-28 11:04:54 -04001753 Equivalent to the largest value for Stroke_Cap.
1754 ##
1755 #Const kDefault_Cap 0
Cary Clark682c58d2018-05-16 07:07:07 -04001756 #Line # equivalent to kButt_Cap ##
Cary Clark8032b982017-07-28 11:04:54 -04001757 Stroke_Cap is set to kButt_Cap by default.
1758 ##
1759
1760 #Const kCapCount 3
Cary Clark682c58d2018-05-16 07:07:07 -04001761 #Line # number of different Stroke_Cap values defined ##
Cary Clark8032b982017-07-28 11:04:54 -04001762 May be used to verify that Stroke_Cap is a legal value.
1763 ##
1764#Enum ##
1765
Herb Derbyfcac00f2018-05-01 11:57:56 -04001766Stroke describes the area covered by a pen of Stroke_Width as it
Cary Clarkbc5697d2017-10-04 14:31:33 -04001767follows the Path_Contour, moving parallel to the contour direction.
Cary Clark8032b982017-07-28 11:04:54 -04001768
1769If the Path_Contour is not terminated by SkPath::kClose_Verb, the contour has a
1770visible beginning and end.
1771
1772Path_Contour may start and end at the same point; defining Zero_Length_Contour.
1773
1774kButt_Cap and Zero_Length_Contour is not drawn.
Herb Derbyfcac00f2018-05-01 11:57:56 -04001775kRound_Cap and Zero_Length_Contour draws a circle of diameter Stroke_Width
Cary Clark8032b982017-07-28 11:04:54 -04001776at the contour point.
1777kSquare_Cap and Zero_Length_Contour draws an upright square with a side of
1778Stroke_Width at the contour point.
1779
1780Stroke_Cap is kButt_Cap by default.
1781
1782#Example
Cary Clark2ade9972017-11-02 17:49:34 -04001783#Height 200
Cary Clark8032b982017-07-28 11:04:54 -04001784 SkPaint paint;
1785 paint.setStyle(SkPaint::kStroke_Style);
1786 paint.setStrokeWidth(20);
1787 SkPath path;
1788 path.moveTo(30, 30);
1789 path.lineTo(30, 30);
1790 path.moveTo(70, 30);
1791 path.lineTo(90, 40);
1792 for (SkPaint::Cap c : { SkPaint::kButt_Cap, SkPaint::kRound_Cap, SkPaint::kSquare_Cap } ) {
1793 paint.setStrokeCap(c);
1794 canvas->drawPath(path, paint);
1795 canvas->translate(0, 70);
1796 }
1797##
1798
1799#Method Cap getStrokeCap() const
1800
Cary Clarkab2621d2018-01-30 10:08:57 -05001801#In Stroke_Cap
1802#Line # returns Cap, the area drawn at path ends ##
Cary Clark09d80c02018-10-31 12:14:03 -04001803#Populate
Cary Clark8032b982017-07-28 11:04:54 -04001804
Cary Clark09d80c02018-10-31 12:14:03 -04001805#Example
Cary Clark8032b982017-07-28 11:04:54 -04001806 SkPaint paint;
1807 SkDebugf("kButt_Cap %c= default stroke cap\n",
1808 SkPaint::kButt_Cap == paint.getStrokeCap() ? '=' : '!');
1809
1810 #StdOut
1811 kButt_Cap == default stroke cap
1812 ##
1813 ##
1814
1815 #SeeAlso Stroke_Cap setStrokeCap
1816##
1817
1818#Method void setStrokeCap(Cap cap)
1819
Cary Clarkab2621d2018-01-30 10:08:57 -05001820#In Stroke_Cap
1821#Line # sets Cap, the area drawn at path ends ##
Cary Clark09d80c02018-10-31 12:14:03 -04001822#Populate
Cary Clark8032b982017-07-28 11:04:54 -04001823
Cary Clark09d80c02018-10-31 12:14:03 -04001824#Example
Cary Clark8032b982017-07-28 11:04:54 -04001825 SkPaint paint;
1826 paint.setStrokeCap(SkPaint::kRound_Cap);
1827 paint.setStrokeCap((SkPaint::Cap) SkPaint::kCapCount);
1828 SkDebugf("kRound_Cap %c= paint.getStrokeCap()\n",
1829 SkPaint::kRound_Cap == paint.getStrokeCap() ? '=' : '!');
Herb Derbyfcac00f2018-05-01 11:57:56 -04001830
Cary Clark8032b982017-07-28 11:04:54 -04001831 #StdOut
1832 kRound_Cap == paint.getStrokeCap()
1833 ##
1834 ##
1835
1836 #SeeAlso Stroke_Cap getStrokeCap
1837##
1838
Cary Clark8032b982017-07-28 11:04:54 -04001839# ------------------------------------------------------------------------------
Cary Clark08895c42018-02-01 09:37:32 -05001840#Subtopic Stroke_Join
1841#Line # decoration at corners of strokes ##
Cary Clarka90ea222018-10-16 10:30:28 -04001842#Subtopic Stroke_Join ##
Cary Clark8032b982017-07-28 11:04:54 -04001843
1844Stroke_Join draws at the sharp corners of an open or closed Path_Contour.
1845
Herb Derbyfcac00f2018-05-01 11:57:56 -04001846Stroke describes the area covered by a pen of Stroke_Width as it
Cary Clarkbc5697d2017-10-04 14:31:33 -04001847follows the Path_Contour, moving parallel to the contour direction.
Cary Clark8032b982017-07-28 11:04:54 -04001848
1849If the contour direction changes abruptly, because the tangent direction leading
1850to the end of a curve within the contour does not match the tangent direction of
1851the following curve, the pair of curves meet at Stroke_Join.
1852
1853#Example
Cary Clark2ade9972017-11-02 17:49:34 -04001854#Height 200
Cary Clarka560c472017-11-27 10:44:06 -05001855 SkPaint paint;
1856 paint.setStyle(SkPaint::kStroke_Style);
1857 paint.setStrokeWidth(20);
1858 SkPath path;
1859 path.moveTo(30, 20);
1860 path.lineTo(40, 40);
1861 path.conicTo(70, 20, 100, 20, .707f);
1862 for (SkPaint::Join j : { SkPaint::kMiter_Join, SkPaint::kRound_Join, SkPaint::kBevel_Join } ) {
1863 paint.setStrokeJoin(j);
1864 canvas->drawPath(path, paint);
1865 canvas->translate(0, 70);
1866 }
Cary Clark8032b982017-07-28 11:04:54 -04001867##
1868
1869#Enum Join
Cary Clark08895c42018-02-01 09:37:32 -05001870#Line # corner geometry on stroked shapes ##
Cary Clark8032b982017-07-28 11:04:54 -04001871#Code
Cary Clarka90ea222018-10-16 10:30:28 -04001872#Populate
1873##
Cary Clark8032b982017-07-28 11:04:54 -04001874
Cary Clarka90ea222018-10-16 10:30:28 -04001875#Code
1876#In Constant
1877#Filter kJoin
1878#Populate
Cary Clark8032b982017-07-28 11:04:54 -04001879##
1880
Cary Clark1eace2d2017-07-31 07:52:43 -04001881Join specifies how corners are drawn when a shape is stroked. Join
Cary Clark8032b982017-07-28 11:04:54 -04001882affects the four corners of a stroked rectangle, and the connected segments in a
1883stroked path.
1884
1885Choose miter join to draw sharp corners. Choose round join to draw a circle with a
1886radius equal to the stroke width on top of the corner. Choose bevel join to minimally
1887connect the thick strokes.
1888
Herb Derbyfcac00f2018-05-01 11:57:56 -04001889The fill path constructed to describe the stroked path respects the join setting but may
Cary Clark8032b982017-07-28 11:04:54 -04001890not contain the actual join. For instance, a fill path constructed with round joins does
1891not necessarily include circles at each connected segment.
1892
1893#Const kMiter_Join 0
Cary Clark682c58d2018-05-16 07:07:07 -04001894#Line # extends to Miter_Limit ##
Cary Clark8032b982017-07-28 11:04:54 -04001895 Extends the outside corner to the extent allowed by Miter_Limit.
1896 If the extension exceeds Miter_Limit, kBevel_Join is used instead.
1897##
1898
1899#Const kRound_Join 1
Cary Clark682c58d2018-05-16 07:07:07 -04001900#Line # adds circle ##
Cary Clark8032b982017-07-28 11:04:54 -04001901 Adds a circle with a diameter of Stroke_Width at the sharp corner.
1902##
1903
1904#Const kBevel_Join 2
Cary Clark682c58d2018-05-16 07:07:07 -04001905#Line # connects outside edges ##
Cary Clark8032b982017-07-28 11:04:54 -04001906 Connects the outside edges of the sharp corner.
1907##
1908
1909#Const kLast_Join 2
Cary Clark682c58d2018-05-16 07:07:07 -04001910#Line # equivalent to the largest value for Stroke_Join ##
Cary Clark8032b982017-07-28 11:04:54 -04001911##
1912
1913#Const kDefault_Join 1
Cary Clark682c58d2018-05-16 07:07:07 -04001914#Line # equivalent to kMiter_Join ##
Herb Derbyfcac00f2018-05-01 11:57:56 -04001915 Stroke_Join is set to kMiter_Join by default.
Cary Clark8032b982017-07-28 11:04:54 -04001916##
1917
1918#Const kJoinCount 3
Cary Clark682c58d2018-05-16 07:07:07 -04001919#Line # number of different Stroke_Join values defined ##
Cary Clark8032b982017-07-28 11:04:54 -04001920 May be used to verify that Stroke_Join is a legal value.
1921##
1922
1923#Example
1924#Width 462
1925void draw(SkCanvas* canvas) {
1926 SkPath path;
1927 path.moveTo(10, 50);
1928 path.quadTo(35, 110, 60, 210);
1929 path.quadTo(105, 110, 130, 10);
1930 SkPaint paint; // set to default kMiter_Join
1931 paint.setAntiAlias(true);
1932 paint.setStyle(SkPaint::kStroke_Style);
1933 paint.setStrokeWidth(20);
1934 canvas->drawPath(path, paint);
1935 canvas->translate(150, 0);
1936 paint.setStrokeJoin(SkPaint::kBevel_Join);
1937 canvas->drawPath(path, paint);
1938 canvas->translate(150, 0);
1939 paint.setStrokeJoin(SkPaint::kRound_Join);
1940 canvas->drawPath(path, paint);
1941}
1942##
1943
1944#SeeAlso setStrokeJoin getStrokeJoin setStrokeMiter getStrokeMiter
1945
1946#Enum ##
1947
1948#Method Join getStrokeJoin() const
1949
Cary Clarkab2621d2018-01-30 10:08:57 -05001950#In Stroke_Join
1951#Line # returns Join, geometry on path corners ##
Cary Clark09d80c02018-10-31 12:14:03 -04001952#Populate
Cary Clark8032b982017-07-28 11:04:54 -04001953
Cary Clark09d80c02018-10-31 12:14:03 -04001954#Example
Cary Clark8032b982017-07-28 11:04:54 -04001955 SkPaint paint;
1956 SkDebugf("kMiter_Join %c= default stroke join\n",
1957 SkPaint::kMiter_Join == paint.getStrokeJoin() ? '=' : '!');
1958
1959 #StdOut
1960 kMiter_Join == default stroke join
1961 ##
1962 ##
1963
1964 #SeeAlso Stroke_Join setStrokeJoin
1965##
1966
1967#Method void setStrokeJoin(Join join)
1968
Cary Clarkab2621d2018-01-30 10:08:57 -05001969#In Stroke_Join
1970#Line # sets Join, geometry on path corners ##
Cary Clark09d80c02018-10-31 12:14:03 -04001971#Populate
Cary Clark8032b982017-07-28 11:04:54 -04001972
Cary Clark09d80c02018-10-31 12:14:03 -04001973#Example
Cary Clark8032b982017-07-28 11:04:54 -04001974 SkPaint paint;
1975 paint.setStrokeJoin(SkPaint::kMiter_Join);
1976 paint.setStrokeJoin((SkPaint::Join) SkPaint::kJoinCount);
1977 SkDebugf("kMiter_Join %c= paint.getStrokeJoin()\n",
1978 SkPaint::kMiter_Join == paint.getStrokeJoin() ? '=' : '!');
1979
1980 #StdOut
1981 kMiter_Join == paint.getStrokeJoin()
1982 ##
1983 ##
1984
1985 #SeeAlso Stroke_Join getStrokeJoin
1986##
1987
1988#SeeAlso Miter_Limit
1989
Cary Clark8032b982017-07-28 11:04:54 -04001990# ------------------------------------------------------------------------------
Cary Clark08895c42018-02-01 09:37:32 -05001991#Subtopic Fill_Path
1992#Line # make Path from Path_Effect, stroking ##
Cary Clark8032b982017-07-28 11:04:54 -04001993
1994Fill_Path creates a Path by applying the Path_Effect, followed by the Style_Stroke.
1995
1996If Paint contains Path_Effect, Path_Effect operates on the source Path; the result
1997replaces the destination Path. Otherwise, the source Path is replaces the
1998destination Path.
1999
2000Fill Path can request the Path_Effect to restrict to a culling rectangle, but
2001the Path_Effect is not required to do so.
2002
Herb Derbyfcac00f2018-05-01 11:57:56 -04002003If Style is kStroke_Style or kStrokeAndFill_Style,
Cary Clark8032b982017-07-28 11:04:54 -04002004and Stroke_Width is greater than zero, the Stroke_Width, Stroke_Cap, Stroke_Join,
2005and Miter_Limit operate on the destination Path, replacing it.
2006
Herb Derbyfcac00f2018-05-01 11:57:56 -04002007Fill Path can specify the precision used by Stroke_Width to approximate the stroke geometry.
Cary Clark8032b982017-07-28 11:04:54 -04002008
2009If the Style is kStroke_Style and the Stroke_Width is zero, getFillPath
2010returns false since Hairline has no filled equivalent.
2011
Cary Clarka90ea222018-10-16 10:30:28 -04002012#SeeAlso Style_Stroke Stroke_Width Path_Effect
2013
2014#Subtopic Fill_Path ##
2015
Cary Clark8032b982017-07-28 11:04:54 -04002016#Method bool getFillPath(const SkPath& src, SkPath* dst, const SkRect* cullRect,
2017 SkScalar resScale = 1) const
Cary Clarkab2621d2018-01-30 10:08:57 -05002018#In Fill_Path
2019#Line # returns fill path equivalent to stroke ##
Cary Clark09d80c02018-10-31 12:14:03 -04002020#Populate
Cary Clark8032b982017-07-28 11:04:54 -04002021
Cary Clark09d80c02018-10-31 12:14:03 -04002022#Example
Cary Clark8032b982017-07-28 11:04:54 -04002023 #Height 192
2024 #Description
Cary Clarkce101242017-09-01 15:51:02 -04002025 A very small Quad stroke is turned into a filled path with increasing levels of precision.
Herb Derbyfcac00f2018-05-01 11:57:56 -04002026 At the lowest precision, the Quad stroke is approximated by a rectangle.
Cary Clark8032b982017-07-28 11:04:54 -04002027 At the highest precision, the filled path has high fidelity compared to the original stroke.
2028 ##
2029 void draw(SkCanvas* canvas) {
2030 SkPaint strokePaint;
2031 strokePaint.setAntiAlias(true);
2032 strokePaint.setStyle(SkPaint::kStroke_Style);
2033 strokePaint.setStrokeWidth(.1f);
2034 SkPath strokePath;
2035 strokePath.moveTo(.08f, .08f);
2036 strokePath.quadTo(.09f, .08f, .17f, .17f);
2037 SkPath fillPath;
2038 SkPaint outlinePaint(strokePaint);
2039 outlinePaint.setStrokeWidth(2);
2040 SkMatrix scale = SkMatrix::MakeScale(300, 300);
2041 for (SkScalar precision : { 0.01f, .1f, 1.f, 10.f, 100.f } ) {
2042 strokePaint.getFillPath(strokePath, &fillPath, nullptr, precision);
2043 fillPath.transform(scale);
2044 canvas->drawPath(fillPath, outlinePaint);
2045 canvas->translate(60, 0);
2046 if (1.f == precision) canvas->translate(-180, 100);
2047 }
2048 strokePath.transform(scale);
2049 strokePaint.setStrokeWidth(30);
2050 canvas->drawPath(strokePath, strokePaint);
2051 }
2052 ##
2053
2054##
2055
2056#Method bool getFillPath(const SkPath& src, SkPath* dst) const
2057
Cary Clarkab2621d2018-01-30 10:08:57 -05002058#In Fill_Path
Cary Clark09d80c02018-10-31 12:14:03 -04002059#Populate
Cary Clark8032b982017-07-28 11:04:54 -04002060
Cary Clark09d80c02018-10-31 12:14:03 -04002061#Example
Cary Clark8032b982017-07-28 11:04:54 -04002062 #Height 128
2063 void draw(SkCanvas* canvas) {
2064 SkPaint paint;
2065 paint.setStyle(SkPaint::kStroke_Style);
2066 paint.setStrokeWidth(10);
2067 SkPath strokePath;
2068 strokePath.moveTo(20, 20);
2069 strokePath.lineTo(100, 100);
2070 canvas->drawPath(strokePath, paint);
2071 SkPath fillPath;
2072 paint.getFillPath(strokePath, &fillPath);
2073 paint.setStrokeWidth(2);
2074 canvas->translate(40, 0);
2075 canvas->drawPath(fillPath, paint);
2076 }
2077 ##
2078
2079##
2080
Cary Clark8032b982017-07-28 11:04:54 -04002081# ------------------------------------------------------------------------------
Cary Clark08895c42018-02-01 09:37:32 -05002082#Subtopic Shader_Methods
2083#Line # get and set Shader ##
Cary Clark8032b982017-07-28 11:04:54 -04002084
2085Shader defines the colors used when drawing a shape.
2086Shader may be an image, a gradient, or a computed fill.
Herb Derbyfcac00f2018-05-01 11:57:56 -04002087If Paint has no Shader, then Color fills the shape.
Cary Clark8032b982017-07-28 11:04:54 -04002088
2089Shader is modulated by Color_Alpha component of Color.
2090If Shader object defines only Color_Alpha, then Color modulated by Color_Alpha describes
2091the fill.
2092
2093The drawn transparency can be modified without altering Shader, by changing Color_Alpha.
2094
2095#Example
2096void draw(SkCanvas* canvas) {
2097 SkPaint paint;
2098 SkPoint center = { 50, 50 };
2099 SkScalar radius = 50;
2100 const SkColor colors[] = { 0xFFFFFFFF, 0xFF000000 };
2101 paint.setShader(SkGradientShader::MakeRadial(center, radius, colors,
2102 nullptr, SK_ARRAY_COUNT(colors), SkShader::kClamp_TileMode));
2103 for (SkScalar a : { 0.3f, 0.6f, 1.0f } ) {
2104 paint.setAlpha((int) (a * 255));
2105 canvas->drawCircle(center.fX, center.fY, radius, paint);
2106 canvas->translate(70, 70);
2107 }
2108}
2109##
2110
2111If Shader generates only Color_Alpha then all components of Color modulate the output.
2112
2113#Example
2114void draw(SkCanvas* canvas) {
2115 SkPaint paint;
2116 SkBitmap bitmap;
2117 bitmap.setInfo(SkImageInfo::MakeA8(5, 1), 5); // bitmap only contains alpha
2118 uint8_t pixels[5] = { 0x22, 0x55, 0x88, 0xBB, 0xFF };
2119 bitmap.setPixels(pixels);
Herb Derbyfcac00f2018-05-01 11:57:56 -04002120 paint.setShader(SkShader::MakeBitmapShader(bitmap,
Cary Clark8032b982017-07-28 11:04:54 -04002121 SkShader::kMirror_TileMode, SkShader::kMirror_TileMode));
2122 for (SkColor c : { SK_ColorRED, SK_ColorBLUE, SK_ColorGREEN } ) {
2123 paint.setColor(c); // all components in color affect shader
2124 canvas->drawCircle(50, 50, 50, paint);
2125 canvas->translate(70, 70);
2126 }
2127}
2128##
2129
2130#Method SkShader* getShader() const
2131
Cary Clarkab2621d2018-01-30 10:08:57 -05002132#In Shader_Methods
2133#Line # returns Shader, multiple drawing colors; gradients ##
Cary Clark09d80c02018-10-31 12:14:03 -04002134#Populate
Cary Clark8032b982017-07-28 11:04:54 -04002135
Cary Clark09d80c02018-10-31 12:14:03 -04002136#Example
Cary Clark8032b982017-07-28 11:04:54 -04002137 void draw(SkCanvas* canvas) {
2138 SkPaint paint;
2139 SkDebugf("nullptr %c= shader\n", paint.getShader() ? '!' : '=');
2140 paint.setShader(SkShader::MakeEmptyShader());
2141 SkDebugf("nullptr %c= shader\n", paint.getShader() ? '!' : '=');
2142 }
2143
2144 #StdOut
2145 nullptr == shader
2146 nullptr != shader
2147 ##
2148 ##
2149
2150##
2151
2152#Method sk_sp<SkShader> refShader() const
2153
Cary Clarkab2621d2018-01-30 10:08:57 -05002154#In Shader_Methods
2155#Line # references Shader, multiple drawing colors; gradients ##
Cary Clark09d80c02018-10-31 12:14:03 -04002156#Populate
Cary Clark8032b982017-07-28 11:04:54 -04002157
Cary Clark09d80c02018-10-31 12:14:03 -04002158#Example
Cary Clark8032b982017-07-28 11:04:54 -04002159 void draw(SkCanvas* canvas) {
2160 SkPaint paint1, paint2;
2161 paint1.setShader(SkShader::MakeEmptyShader());
2162 SkDebugf("shader unique: %s\n", paint1.getShader()->unique() ? "true" : "false");
2163 paint2.setShader(paint1.refShader());
2164 SkDebugf("shader unique: %s\n", paint1.getShader()->unique() ? "true" : "false");
2165 }
2166
2167 #StdOut
2168 shader unique: true
2169 shader unique: false
2170 ##
2171 ##
2172
2173##
2174
2175#Method void setShader(sk_sp<SkShader> shader)
2176
Cary Clarkab2621d2018-01-30 10:08:57 -05002177#In Shader_Methods
2178#Line # sets Shader, multiple drawing colors; gradients ##
Cary Clark09d80c02018-10-31 12:14:03 -04002179#Populate
Cary Clark8032b982017-07-28 11:04:54 -04002180
Cary Clark09d80c02018-10-31 12:14:03 -04002181#Example
Cary Clark8032b982017-07-28 11:04:54 -04002182 #Height 64
2183 void draw(SkCanvas* canvas) {
2184 SkPaint paint;
2185 paint.setColor(SK_ColorBLUE);
2186 paint.setShader(SkShader::MakeColorShader(SK_ColorRED));
2187 canvas->drawRect(SkRect::MakeWH(40, 40), paint);
2188 paint.setShader(nullptr);
2189 canvas->translate(50, 0);
2190 canvas->drawRect(SkRect::MakeWH(40, 40), paint);
2191 }
2192 ##
2193
2194##
2195
Cary Clark08895c42018-02-01 09:37:32 -05002196#Subtopic Shader_Methods ##
Cary Clark8032b982017-07-28 11:04:54 -04002197# ------------------------------------------------------------------------------
Cary Clark08895c42018-02-01 09:37:32 -05002198#Subtopic Color_Filter_Methods
2199#Line # get and set Color_Filter ##
Cary Clark8032b982017-07-28 11:04:54 -04002200
2201Color_Filter alters the color used when drawing a shape.
2202Color_Filter may apply Blend_Mode, transform the color through a matrix, or composite multiple filters.
2203If Paint has no Color_Filter, the color is unaltered.
2204
2205The drawn transparency can be modified without altering Color_Filter, by changing Color_Alpha.
2206
2207#Example
2208#Height 128
2209void draw(SkCanvas* canvas) {
2210 SkPaint paint;
2211 paint.setColorFilter(SkColorMatrixFilter::MakeLightingFilter(0xFFFFFF, 0xFF0000));
2212 for (SkColor c : { SK_ColorBLACK, SK_ColorGREEN } ) {
2213 paint.setColor(c);
2214 canvas->drawRect(SkRect::MakeXYWH(10, 10, 50, 50), paint);
2215 paint.setAlpha(0x80);
2216 canvas->drawRect(SkRect::MakeXYWH(60, 60, 50, 50), paint);
2217 canvas->translate(100, 0);
2218 }
2219}
2220##
2221
2222#Method SkColorFilter* getColorFilter() const
2223
Cary Clarkab2621d2018-01-30 10:08:57 -05002224#In Color_Filter_Methods
2225#Line # returns Color_Filter, how colors are altered ##
Cary Clark09d80c02018-10-31 12:14:03 -04002226#Populate
Herb Derbyfcac00f2018-05-01 11:57:56 -04002227
Cary Clark09d80c02018-10-31 12:14:03 -04002228#Example
Cary Clark8032b982017-07-28 11:04:54 -04002229 void draw(SkCanvas* canvas) {
2230 SkPaint paint;
2231 SkDebugf("nullptr %c= color filter\n", paint.getColorFilter() ? '!' : '=');
2232 paint.setColorFilter(SkColorFilter::MakeModeFilter(SK_ColorLTGRAY, SkBlendMode::kSrcIn));
2233 SkDebugf("nullptr %c= color filter\n", paint.getColorFilter() ? '!' : '=');
2234 }
2235
2236 #StdOut
2237 nullptr == color filter
2238 nullptr != color filter
2239 ##
2240 ##
2241##
2242
2243#Method sk_sp<SkColorFilter> refColorFilter() const
2244
Cary Clarkab2621d2018-01-30 10:08:57 -05002245#In Color_Filter_Methods
2246#Line # references Color_Filter, how colors are altered ##
Cary Clark09d80c02018-10-31 12:14:03 -04002247#Populate
Cary Clark8032b982017-07-28 11:04:54 -04002248
Cary Clark09d80c02018-10-31 12:14:03 -04002249#Example
Cary Clark8032b982017-07-28 11:04:54 -04002250 void draw(SkCanvas* canvas) {
2251 SkPaint paint1, paint2;
2252 paint1.setColorFilter(SkColorFilter::MakeModeFilter(0xFFFF0000, SkBlendMode::kSrcATop));
2253 SkDebugf("color filter unique: %s\n", paint1.getColorFilter()->unique() ? "true" : "false");
2254 paint2.setColorFilter(paint1.refColorFilter());
2255 SkDebugf("color filter unique: %s\n", paint1.getColorFilter()->unique() ? "true" : "false");
2256 }
2257
2258 #StdOut
2259 color filter unique: true
2260 color filter unique: false
2261 ##
2262 ##
2263##
2264
2265#Method void setColorFilter(sk_sp<SkColorFilter> colorFilter)
2266
Cary Clarkab2621d2018-01-30 10:08:57 -05002267#In Color_Filter_Methods
2268#Line # sets Color_Filter, alters color ##
Cary Clark09d80c02018-10-31 12:14:03 -04002269#Populate
Cary Clark6fc50412017-09-21 12:31:06 -04002270
Cary Clark09d80c02018-10-31 12:14:03 -04002271#Example
Cary Clark8032b982017-07-28 11:04:54 -04002272 #Height 64
2273 void draw(SkCanvas* canvas) {
2274 SkPaint paint;
2275 paint.setColorFilter(SkColorFilter::MakeModeFilter(SK_ColorLTGRAY, SkBlendMode::kSrcIn));
2276 canvas->drawRect(SkRect::MakeWH(50, 50), paint);
2277 paint.setColorFilter(nullptr);
2278 canvas->translate(70, 0);
2279 canvas->drawRect(SkRect::MakeWH(50, 50), paint);
2280 }
2281 ##
2282
2283##
2284
Cary Clark08895c42018-02-01 09:37:32 -05002285#Subtopic Color_Filter_Methods ##
Cary Clark8032b982017-07-28 11:04:54 -04002286# ------------------------------------------------------------------------------
Cary Clark08895c42018-02-01 09:37:32 -05002287#Subtopic Blend_Mode_Methods
2288#Line # get and set Blend_Mode ##
Cary Clark8032b982017-07-28 11:04:54 -04002289
2290Blend_Mode describes how Color combines with the destination color.
2291The default setting, SkBlendMode::kSrcOver, draws the source color
2292over the destination color.
2293
2294#Example
2295void draw(SkCanvas* canvas) {
2296 SkPaint normal, blender;
2297 normal.setColor(0xFF58a889);
2298 blender.setColor(0xFF8958a8);
2299 canvas->clear(0);
2300 for (SkBlendMode m : { SkBlendMode::kSrcOver, SkBlendMode::kSrcIn, SkBlendMode::kSrcOut } ) {
2301 normal.setBlendMode(SkBlendMode::kSrcOver);
2302 canvas->drawOval(SkRect::MakeXYWH(30, 30, 30, 80), normal);
2303 blender.setBlendMode(m);
2304 canvas->drawOval(SkRect::MakeXYWH(10, 50, 80, 30), blender);
2305 canvas->translate(70, 70);
2306 }
2307}
2308##
2309
2310#SeeAlso Blend_Mode
2311
2312#Method SkBlendMode getBlendMode() const
2313
Cary Clarkab2621d2018-01-30 10:08:57 -05002314#In Blend_Mode_Methods
2315#Line # returns Blend_Mode, how colors combine with Device ##
Cary Clark09d80c02018-10-31 12:14:03 -04002316#Populate
Cary Clark8032b982017-07-28 11:04:54 -04002317
Cary Clark09d80c02018-10-31 12:14:03 -04002318#Example
Cary Clark8032b982017-07-28 11:04:54 -04002319 void draw(SkCanvas* canvas) {
2320 SkPaint paint;
Herb Derbyfcac00f2018-05-01 11:57:56 -04002321 SkDebugf("kSrcOver %c= getBlendMode\n",
Cary Clark8032b982017-07-28 11:04:54 -04002322 SkBlendMode::kSrcOver == paint.getBlendMode() ? '=' : '!');
2323 paint.setBlendMode(SkBlendMode::kSrc);
Herb Derbyfcac00f2018-05-01 11:57:56 -04002324 SkDebugf("kSrcOver %c= getBlendMode\n",
Cary Clark8032b982017-07-28 11:04:54 -04002325 SkBlendMode::kSrcOver == paint.getBlendMode() ? '=' : '!');
2326 }
2327
2328 #StdOut
2329 kSrcOver == getBlendMode
2330 kSrcOver != getBlendMode
2331 ##
2332 ##
2333
2334##
2335
2336#Method bool isSrcOver() const
2337
Cary Clarkab2621d2018-01-30 10:08:57 -05002338#In Blend_Mode_Methods
2339#Line # returns true if Blend_Mode is SkBlendMode::kSrcOver ##
Cary Clark09d80c02018-10-31 12:14:03 -04002340#Populate
Cary Clark8032b982017-07-28 11:04:54 -04002341
Cary Clark09d80c02018-10-31 12:14:03 -04002342#Example
Cary Clark8032b982017-07-28 11:04:54 -04002343 void draw(SkCanvas* canvas) {
2344 SkPaint paint;
2345 SkDebugf("isSrcOver %c= true\n", paint.isSrcOver() ? '=' : '!');
2346 paint.setBlendMode(SkBlendMode::kSrc);
2347 SkDebugf("isSrcOver %c= true\n", paint.isSrcOver() ? '=' : '!');
2348 }
2349
2350 #StdOut
2351 isSrcOver == true
2352 isSrcOver != true
2353 ##
2354 ##
2355
2356##
2357
2358#Method void setBlendMode(SkBlendMode mode)
2359
Cary Clarkab2621d2018-01-30 10:08:57 -05002360#In Blend_Mode_Methods
2361#Line # sets Blend_Mode, how colors combine with destination ##
Cary Clark09d80c02018-10-31 12:14:03 -04002362#Populate
Cary Clark8032b982017-07-28 11:04:54 -04002363
Cary Clark09d80c02018-10-31 12:14:03 -04002364#Example
Cary Clark8032b982017-07-28 11:04:54 -04002365 void draw(SkCanvas* canvas) {
2366 SkPaint paint;
2367 SkDebugf("isSrcOver %c= true\n", paint.isSrcOver() ? '=' : '!');
2368 paint.setBlendMode(SkBlendMode::kSrc);
2369 SkDebugf("isSrcOver %c= true\n", paint.isSrcOver() ? '=' : '!');
2370 }
2371
2372 #StdOut
2373 isSrcOver == true
2374 isSrcOver != true
2375 ##
2376 ##
2377
2378##
2379
Cary Clark08895c42018-02-01 09:37:32 -05002380#Subtopic Blend_Mode_Methods ##
Cary Clark8032b982017-07-28 11:04:54 -04002381# ------------------------------------------------------------------------------
Cary Clark08895c42018-02-01 09:37:32 -05002382#Subtopic Path_Effect_Methods
2383#Line # get and set Path_Effect ##
Cary Clark8032b982017-07-28 11:04:54 -04002384
2385Path_Effect modifies the path geometry before drawing it.
2386Path_Effect may implement dashing, custom fill effects and custom stroke effects.
2387If Paint has no Path_Effect, the path geometry is unaltered when filled or stroked.
2388
2389#Example
2390#Height 160
2391 void draw(SkCanvas* canvas) {
2392 SkPaint paint;
2393 paint.setStyle(SkPaint::kStroke_Style);
2394 paint.setStrokeWidth(16);
2395 SkScalar intervals[] = {30, 10};
2396 paint.setPathEffect(SkDashPathEffect::Make(intervals, SK_ARRAY_COUNT(intervals), 1));
2397 canvas->drawRoundRect({20, 20, 120, 120}, 20, 20, paint);
2398 }
2399##
2400
2401#SeeAlso Path_Effect
2402
2403#Method SkPathEffect* getPathEffect() const
2404
Cary Clarkab2621d2018-01-30 10:08:57 -05002405#In Path_Effect_Methods
2406#Line # returns Path_Effect, modifications to path geometry; dashing ##
Cary Clark09d80c02018-10-31 12:14:03 -04002407#Populate
Herb Derbyfcac00f2018-05-01 11:57:56 -04002408
Cary Clark09d80c02018-10-31 12:14:03 -04002409#Example
Cary Clark8032b982017-07-28 11:04:54 -04002410 void draw(SkCanvas* canvas) {
2411 SkPaint paint;
2412 SkDebugf("nullptr %c= path effect\n", paint.getPathEffect() ? '!' : '=');
2413 paint.setPathEffect(SkCornerPathEffect::Make(10));
2414 SkDebugf("nullptr %c= path effect\n", paint.getPathEffect() ? '!' : '=');
2415 }
2416
2417 #StdOut
2418 nullptr == path effect
2419 nullptr != path effect
2420 ##
2421 ##
2422
2423##
2424
2425
2426#Method sk_sp<SkPathEffect> refPathEffect() const
2427
Cary Clarkab2621d2018-01-30 10:08:57 -05002428#In Path_Effect_Methods
2429#Line # references Path_Effect, modifications to path geometry; dashing ##
Cary Clark09d80c02018-10-31 12:14:03 -04002430#Populate
Cary Clark8032b982017-07-28 11:04:54 -04002431
Cary Clark09d80c02018-10-31 12:14:03 -04002432#Example
Cary Clark8032b982017-07-28 11:04:54 -04002433 void draw(SkCanvas* canvas) {
2434 SkPaint paint1, paint2;
Cary Clarka560c472017-11-27 10:44:06 -05002435 SkScalar intervals[] = {1, 2};
2436 paint1.setPathEffect(SkDashPathEffect::Make(intervals, SK_ARRAY_COUNT(intervals), 10));
Cary Clark8032b982017-07-28 11:04:54 -04002437 SkDebugf("path effect unique: %s\n", paint1.getPathEffect()->unique() ? "true" : "false");
2438 paint2.setPathEffect(paint1.refPathEffect());
2439 SkDebugf("path effect unique: %s\n", paint1.getPathEffect()->unique() ? "true" : "false");
2440 }
2441
2442 #StdOut
2443 path effect unique: true
2444 path effect unique: false
2445 ##
2446 ##
2447
2448##
2449
2450
2451#Method void setPathEffect(sk_sp<SkPathEffect> pathEffect)
2452
Cary Clarkab2621d2018-01-30 10:08:57 -05002453#In Path_Effect_Methods
2454#Line # sets Path_Effect, modifications to path geometry; dashing ##
Cary Clark09d80c02018-10-31 12:14:03 -04002455#Populate
Cary Clark6fc50412017-09-21 12:31:06 -04002456
Cary Clark09d80c02018-10-31 12:14:03 -04002457#Example
Cary Clark8032b982017-07-28 11:04:54 -04002458 void draw(SkCanvas* canvas) {
2459 SkPaint paint;
2460 paint.setPathEffect(SkDiscretePathEffect::Make(3, 5));
2461 canvas->drawRect(SkRect::MakeXYWH(40, 40, 175, 175), paint);
2462 }
2463 ##
2464
2465##
2466
Cary Clark08895c42018-02-01 09:37:32 -05002467#Subtopic Path_Effect_Methods ##
Cary Clark8032b982017-07-28 11:04:54 -04002468# ------------------------------------------------------------------------------
Cary Clark08895c42018-02-01 09:37:32 -05002469#Subtopic Mask_Filter_Methods
2470#Line # get and set Mask_Filter ##
Cary Clark8032b982017-07-28 11:04:54 -04002471
Cary Clarkce101242017-09-01 15:51:02 -04002472Mask_Filter uses coverage of the shape drawn to create Mask_Alpha.
Mike Reed8ad91a92018-01-19 19:09:32 -05002473Mask_Filter takes a Mask, and returns a Mask.
Cary Clark6fc50412017-09-21 12:31:06 -04002474
2475Mask_Filter may change the geometry and transparency of the shape, such as
2476creating a blur effect. Set Mask_Filter to nullptr to prevent Mask_Filter from
2477modifying the draw.
Cary Clark8032b982017-07-28 11:04:54 -04002478
2479#Example
2480 void draw(SkCanvas* canvas) {
2481 SkPaint paint;
Cary Clark681287e2018-03-16 11:34:15 -04002482 paint.setMaskFilter(SkMaskFilter::MakeBlur(kSolid_SkBlurStyle, 3));
Cary Clark8032b982017-07-28 11:04:54 -04002483 canvas->drawRect(SkRect::MakeXYWH(40, 40, 175, 175), paint);
2484 }
2485##
2486
2487#Method SkMaskFilter* getMaskFilter() const
2488
Cary Clarkab2621d2018-01-30 10:08:57 -05002489#In Mask_Filter_Methods
2490#Line # returns Mask_Filter, alterations to Mask_Alpha ##
Cary Clark09d80c02018-10-31 12:14:03 -04002491#Populate
Herb Derbyfcac00f2018-05-01 11:57:56 -04002492
Cary Clark09d80c02018-10-31 12:14:03 -04002493#Example
Cary Clark8032b982017-07-28 11:04:54 -04002494 void draw(SkCanvas* canvas) {
2495 SkPaint paint;
2496 SkDebugf("nullptr %c= mask filter\n", paint.getMaskFilter() ? '!' : '=');
Cary Clark681287e2018-03-16 11:34:15 -04002497 paint.setMaskFilter(SkMaskFilter::MakeBlur(kOuter_SkBlurStyle, 3));
Cary Clark8032b982017-07-28 11:04:54 -04002498 SkDebugf("nullptr %c= mask filter\n", paint.getMaskFilter() ? '!' : '=');
2499 }
2500
2501 #StdOut
2502 nullptr == mask filter
2503 nullptr != mask filter
2504 ##
2505 ##
2506
2507##
2508
2509#Method sk_sp<SkMaskFilter> refMaskFilter() const
2510
Cary Clarkab2621d2018-01-30 10:08:57 -05002511#In Mask_Filter_Methods
2512#Line # references Mask_Filter, alterations to Mask_Alpha ##
Cary Clark09d80c02018-10-31 12:14:03 -04002513#Populate
Cary Clark6fc50412017-09-21 12:31:06 -04002514
Cary Clark09d80c02018-10-31 12:14:03 -04002515#Example
Cary Clark8032b982017-07-28 11:04:54 -04002516 void draw(SkCanvas* canvas) {
2517 SkPaint paint1, paint2;
Cary Clark681287e2018-03-16 11:34:15 -04002518 paint1.setMaskFilter(SkMaskFilter::MakeBlur(kNormal_SkBlurStyle, 1));
Cary Clark8032b982017-07-28 11:04:54 -04002519 SkDebugf("mask filter unique: %s\n", paint1.getMaskFilter()->unique() ? "true" : "false");
2520 paint2.setMaskFilter(paint1.refMaskFilter());
2521 SkDebugf("mask filter unique: %s\n", paint1.getMaskFilter()->unique() ? "true" : "false");
2522 }
2523
2524 #StdOut
2525 mask filter unique: true
2526 mask filter unique: false
2527 ##
2528 ##
2529
2530##
2531
2532#Method void setMaskFilter(sk_sp<SkMaskFilter> maskFilter)
2533
Cary Clarkab2621d2018-01-30 10:08:57 -05002534#In Mask_Filter_Methods
2535#Line # sets Mask_Filter, alterations to Mask_Alpha ##
Cary Clark09d80c02018-10-31 12:14:03 -04002536#Populate
Cary Clark6fc50412017-09-21 12:31:06 -04002537
Cary Clark09d80c02018-10-31 12:14:03 -04002538#Example
Cary Clark8032b982017-07-28 11:04:54 -04002539 void draw(SkCanvas* canvas) {
2540 SkPaint paint;
2541 paint.setStyle(SkPaint::kStroke_Style);
2542 paint.setStrokeWidth(10);
Cary Clark681287e2018-03-16 11:34:15 -04002543 paint.setMaskFilter(SkMaskFilter::MakeBlur(kNormal_SkBlurStyle, 10));
Cary Clark8032b982017-07-28 11:04:54 -04002544 canvas->drawRect(SkRect::MakeXYWH(40, 40, 175, 175), paint);
2545 }
2546 ##
2547
2548##
2549
Cary Clark08895c42018-02-01 09:37:32 -05002550#Subtopic Mask_Filter_Methods ##
Cary Clark8032b982017-07-28 11:04:54 -04002551# ------------------------------------------------------------------------------
Cary Clark08895c42018-02-01 09:37:32 -05002552#Subtopic Typeface_Methods
2553#Line # get and set Typeface ##
Cary Clark8032b982017-07-28 11:04:54 -04002554
2555Typeface identifies the font used when drawing and measuring text.
2556Typeface may be specified by name, from a file, or from a data stream.
2557The default Typeface defers to the platform-specific default font
2558implementation.
2559
2560#Example
2561#Height 100
2562 void draw(SkCanvas* canvas) {
2563 SkPaint paint;
Ben Wagner700ff172017-11-08 15:37:22 -05002564 paint.setTypeface(SkTypeface::MakeFromName(nullptr, SkFontStyle()));
Cary Clark8032b982017-07-28 11:04:54 -04002565 paint.setAntiAlias(true);
2566 paint.setTextSize(36);
2567 canvas->drawString("A Big Hello!", 10, 40, paint);
2568 paint.setTypeface(nullptr);
2569 paint.setFakeBoldText(true);
2570 canvas->drawString("A Big Hello!", 10, 80, paint);
2571 }
2572##
2573
2574#Method SkTypeface* getTypeface() const
2575
Cary Clarkab2621d2018-01-30 10:08:57 -05002576#In Typeface_Methods
2577#Line # returns Typeface, font description ##
Cary Clark09d80c02018-10-31 12:14:03 -04002578#Populate
Herb Derbyfcac00f2018-05-01 11:57:56 -04002579
Cary Clark09d80c02018-10-31 12:14:03 -04002580#Example
Cary Clark8032b982017-07-28 11:04:54 -04002581 void draw(SkCanvas* canvas) {
2582 SkPaint paint;
2583 SkDebugf("nullptr %c= typeface\n", paint.getTypeface() ? '!' : '=');
Cary Clark71961fb2018-01-05 14:21:59 -05002584 paint.setTypeface(SkTypeface::MakeFromName("monospace", SkFontStyle()));
Cary Clark8032b982017-07-28 11:04:54 -04002585 SkDebugf("nullptr %c= typeface\n", paint.getTypeface() ? '!' : '=');
2586 }
2587
2588 #StdOut
2589 nullptr == typeface
2590 nullptr != typeface
2591 ##
2592 ##
2593
2594##
2595
2596#Method sk_sp<SkTypeface> refTypeface() const
2597
Cary Clarkab2621d2018-01-30 10:08:57 -05002598#In Typeface_Methods
2599#Line # references Typeface, font description ##
Cary Clark09d80c02018-10-31 12:14:03 -04002600#Populate
Cary Clark8032b982017-07-28 11:04:54 -04002601
Cary Clark09d80c02018-10-31 12:14:03 -04002602#Example
Cary Clark8032b982017-07-28 11:04:54 -04002603 void draw(SkCanvas* canvas) {
2604 SkPaint paint1, paint2;
Herb Derbyfcac00f2018-05-01 11:57:56 -04002605 paint1.setTypeface(SkTypeface::MakeFromName("monospace",
Cary Clark8032b982017-07-28 11:04:54 -04002606 SkFontStyle(SkFontStyle::kNormal_Weight, SkFontStyle::kNormal_Width,
2607 SkFontStyle::kItalic_Slant)));
2608 SkDebugf("typeface1 %c= typeface2\n",
2609 paint1.getTypeface() == paint2.getTypeface() ? '=' : '!');
2610 paint2.setTypeface(paint1.refTypeface());
2611 SkDebugf("typeface1 %c= typeface2\n",
2612 paint1.getTypeface() == paint2.getTypeface() ? '=' : '!');
2613 }
2614
2615 #StdOut
2616 typeface1 != typeface2
2617 typeface1 == typeface2
2618 ##
2619 ##
2620
2621##
2622
2623#Method void setTypeface(sk_sp<SkTypeface> typeface)
2624
Cary Clarkab2621d2018-01-30 10:08:57 -05002625#In Typeface_Methods
2626#Line # sets Typeface, font description ##
Cary Clark09d80c02018-10-31 12:14:03 -04002627#Populate
Cary Clark8032b982017-07-28 11:04:54 -04002628
Cary Clark09d80c02018-10-31 12:14:03 -04002629#Example
Cary Clark8032b982017-07-28 11:04:54 -04002630 #Height 64
2631 void draw(SkCanvas* canvas) {
2632 SkPaint paint;
Cary Clark71961fb2018-01-05 14:21:59 -05002633 paint.setTypeface(SkTypeface::MakeFromName("monospace", SkFontStyle()));
2634 canvas->drawString("hamburgerfons", 10, 30, paint);
Cary Clark8032b982017-07-28 11:04:54 -04002635 paint.setTypeface(nullptr);
Cary Clark71961fb2018-01-05 14:21:59 -05002636 canvas->drawString("hamburgerfons", 10, 50, paint);
Cary Clark8032b982017-07-28 11:04:54 -04002637 }
2638 ##
2639
2640##
2641
Cary Clark08895c42018-02-01 09:37:32 -05002642#Subtopic Typeface_Methods ##
Cary Clark8032b982017-07-28 11:04:54 -04002643# ------------------------------------------------------------------------------
Cary Clark08895c42018-02-01 09:37:32 -05002644#Subtopic Image_Filter_Methods
2645#Line # get and set Image_Filter ##
Cary Clark8032b982017-07-28 11:04:54 -04002646
2647Image_Filter operates on the pixel representation of the shape, as modified by Paint
2648with Blend_Mode set to SkBlendMode::kSrcOver. Image_Filter creates a new bitmap,
2649which is drawn to the device using the set Blend_Mode.
Cary Clark6fc50412017-09-21 12:31:06 -04002650
Cary Clark8032b982017-07-28 11:04:54 -04002651Image_Filter is higher level than Mask_Filter; for instance, an Image_Filter
Cary Clarkce101242017-09-01 15:51:02 -04002652can operate on all channels of Color, while Mask_Filter generates Alpha only.
Cary Clark8032b982017-07-28 11:04:54 -04002653Image_Filter operates independently of and can be used in combination with
Mike Reed8ad91a92018-01-19 19:09:32 -05002654Mask_Filter.
Cary Clark8032b982017-07-28 11:04:54 -04002655
2656#Example
2657 #ToDo explain why the two draws are so different ##
Cary Clark81abc432018-06-25 16:30:08 -04002658 #Function
2659 ###$
2660 #include "SkBlurImageFilter.h"
2661 $$$#
2662 ##
Cary Clark8032b982017-07-28 11:04:54 -04002663 void draw(SkCanvas* canvas) {
2664 SkPaint paint;
2665 paint.setStyle(SkPaint::kStroke_Style);
2666 paint.setStrokeWidth(2);
2667 SkRegion region;
2668 region.op( 10, 10, 50, 50, SkRegion::kUnion_Op);
2669 region.op( 10, 50, 90, 90, SkRegion::kUnion_Op);
Cary Clarka560c472017-11-27 10:44:06 -05002670 paint.setImageFilter(SkBlurImageFilter::Make(5.0f, 5.0f, nullptr));
Cary Clark8032b982017-07-28 11:04:54 -04002671 canvas->drawRegion(region, paint);
2672 paint.setImageFilter(nullptr);
Cary Clarka7b84c52018-03-18 11:46:54 -04002673 paint.setMaskFilter(SkMaskFilter::MakeBlur(kNormal_SkBlurStyle, 5));
Cary Clark8032b982017-07-28 11:04:54 -04002674 canvas->translate(100, 100);
2675 canvas->drawRegion(region, paint);
2676 }
2677##
2678
2679#Method SkImageFilter* getImageFilter() const
2680
Cary Clarkab2621d2018-01-30 10:08:57 -05002681#In Image_Filter_Methods
2682#Line # returns Image_Filter, alter pixels; blur ##
Cary Clark09d80c02018-10-31 12:14:03 -04002683#Populate
Herb Derbyfcac00f2018-05-01 11:57:56 -04002684
Cary Clark09d80c02018-10-31 12:14:03 -04002685#Example
Cary Clark81abc432018-06-25 16:30:08 -04002686 #Function
2687 ###$
2688 #include "SkBlurImageFilter.h"
2689 $$$#
2690 ##
Cary Clark8032b982017-07-28 11:04:54 -04002691 void draw(SkCanvas* canvas) {
2692 SkPaint paint;
2693 SkDebugf("nullptr %c= image filter\n", paint.getImageFilter() ? '!' : '=');
Cary Clarka560c472017-11-27 10:44:06 -05002694 paint.setImageFilter(SkBlurImageFilter::Make(kOuter_SkBlurStyle, 3, nullptr, nullptr));
Cary Clark8032b982017-07-28 11:04:54 -04002695 SkDebugf("nullptr %c= image filter\n", paint.getImageFilter() ? '!' : '=');
2696 }
2697
2698 #StdOut
2699 nullptr == image filter
2700 nullptr != image filter
2701 ##
2702 ##
2703
2704##
2705
2706#Method sk_sp<SkImageFilter> refImageFilter() const
2707
Cary Clarkab2621d2018-01-30 10:08:57 -05002708#In Image_Filter_Methods
2709#Line # references Image_Filter, alter pixels; blur ##
Cary Clark09d80c02018-10-31 12:14:03 -04002710#Populate
Cary Clark8032b982017-07-28 11:04:54 -04002711
Cary Clark09d80c02018-10-31 12:14:03 -04002712#Example
Cary Clark8032b982017-07-28 11:04:54 -04002713 void draw(SkCanvas* canvas) {
2714 SkPaint paint1, paint2;
2715 paint1.setImageFilter(SkOffsetImageFilter::Make(25, 25, nullptr));
2716 SkDebugf("image filter unique: %s\n", paint1.getImageFilter()->unique() ? "true" : "false");
2717 paint2.setImageFilter(paint1.refImageFilter());
2718 SkDebugf("image filter unique: %s\n", paint1.getImageFilter()->unique() ? "true" : "false");
2719 }
2720
2721 #StdOut
2722 image filter unique: true
2723 image filter unique: false
2724 ##
2725 ##
2726
2727##
2728
2729#Method void setImageFilter(sk_sp<SkImageFilter> imageFilter)
2730
Cary Clarkab2621d2018-01-30 10:08:57 -05002731#In Image_Filter_Methods
2732#Line # sets Image_Filter, alter pixels; blur ##
Cary Clark09d80c02018-10-31 12:14:03 -04002733#Populate
Cary Clark6fc50412017-09-21 12:31:06 -04002734
Cary Clark09d80c02018-10-31 12:14:03 -04002735#Example
Cary Clark8032b982017-07-28 11:04:54 -04002736 #Height 160
2737 void draw(SkCanvas* canvas) {
2738 SkBitmap bitmap;
2739 bitmap.allocN32Pixels(100, 100);
2740 SkCanvas offscreen(bitmap);
2741 SkPaint paint;
2742 paint.setAntiAlias(true);
2743 paint.setColor(SK_ColorWHITE);
2744 paint.setTextSize(96);
2745 offscreen.clear(0);
2746 offscreen.drawString("e", 20, 70, paint);
2747 paint.setImageFilter(
2748 SkLightingImageFilter::MakePointLitDiffuse(SkPoint3::Make(80, 100, 10),
2749 SK_ColorWHITE, 1, 2, nullptr, nullptr));
2750 canvas->drawBitmap(bitmap, 0, 0, &paint);
2751 }
2752 ##
2753
2754##
2755
Cary Clark08895c42018-02-01 09:37:32 -05002756#Subtopic Image_Filter_Methods ##
Cary Clark8032b982017-07-28 11:04:54 -04002757# ------------------------------------------------------------------------------
Cary Clark08895c42018-02-01 09:37:32 -05002758#Subtopic Draw_Looper_Methods
2759#Line # get and set Draw_Looper ##
Cary Clark8032b982017-07-28 11:04:54 -04002760
2761Draw_Looper sets a modifier that communicates state from one Draw_Layer
2762to another to construct the draw.
Cary Clark6fc50412017-09-21 12:31:06 -04002763
Cary Clark8032b982017-07-28 11:04:54 -04002764Draw_Looper draws one or more times, modifying the canvas and paint each time.
2765Draw_Looper may be used to draw multiple colors or create a colored shadow.
Herb Derbyfcac00f2018-05-01 11:57:56 -04002766Set Draw_Looper to nullptr to prevent Draw_Looper from modifying the draw.
Cary Clark8032b982017-07-28 11:04:54 -04002767
2768#Example
2769#Height 128
2770 void draw(SkCanvas* canvas) {
2771 SkLayerDrawLooper::LayerInfo info;
2772 info.fPaintBits = (SkLayerDrawLooper::BitFlags) SkLayerDrawLooper::kColorFilter_Bit;
2773 info.fColorMode = SkBlendMode::kSrc;
2774 SkLayerDrawLooper::Builder looperBuilder;
2775 SkPaint* loopPaint = looperBuilder.addLayer(info);
2776 loopPaint->setColor(SK_ColorRED);
2777 info.fOffset.set(20, 20);
2778 loopPaint = looperBuilder.addLayer(info);
2779 loopPaint->setColor(SK_ColorBLUE);
2780 SkPaint paint;
2781 paint.setDrawLooper(looperBuilder.detach());
2782 canvas->drawCircle(50, 50, 50, paint);
2783 }
2784
2785##
2786
2787#Method SkDrawLooper* getDrawLooper() const
2788
Cary Clarkab2621d2018-01-30 10:08:57 -05002789#In Draw_Looper_Methods
2790#Line # returns Draw_Looper, multiple layers ##
Cary Clark09d80c02018-10-31 12:14:03 -04002791#Populate
Herb Derbyfcac00f2018-05-01 11:57:56 -04002792
Cary Clark09d80c02018-10-31 12:14:03 -04002793#Example
Cary Clark8032b982017-07-28 11:04:54 -04002794 void draw(SkCanvas* canvas) {
2795 SkPaint paint;
2796 SkDebugf("nullptr %c= draw looper\n", paint.getDrawLooper() ? '!' : '=');
2797 SkLayerDrawLooper::Builder looperBuilder;
2798 paint.setDrawLooper(looperBuilder.detach());
2799 SkDebugf("nullptr %c= draw looper\n", paint.getDrawLooper() ? '!' : '=');
2800 }
2801
2802 #StdOut
2803 nullptr == draw looper
2804 nullptr != draw looper
2805 ##
2806 ##
2807
2808##
2809
2810#Method sk_sp<SkDrawLooper> refDrawLooper() const
2811
Cary Clarkab2621d2018-01-30 10:08:57 -05002812#In Draw_Looper_Methods
2813#Line # references Draw_Looper, multiple layers ##
Cary Clark09d80c02018-10-31 12:14:03 -04002814#Populate
Cary Clark8032b982017-07-28 11:04:54 -04002815
Cary Clark09d80c02018-10-31 12:14:03 -04002816#Example
Cary Clark8032b982017-07-28 11:04:54 -04002817 void draw(SkCanvas* canvas) {
2818 SkPaint paint1, paint2;
2819 SkLayerDrawLooper::Builder looperBuilder;
2820 paint1.setDrawLooper(looperBuilder.detach());
2821 SkDebugf("draw looper unique: %s\n", paint1.getDrawLooper()->unique() ? "true" : "false");
2822 paint2.setDrawLooper(paint1.refDrawLooper());
2823 SkDebugf("draw looper unique: %s\n", paint1.getDrawLooper()->unique() ? "true" : "false");
2824 }
2825
2826 #StdOut
2827 draw looper unique: true
2828 draw looper unique: false
2829 ##
2830 ##
2831
2832##
2833
Cary Clark8032b982017-07-28 11:04:54 -04002834#Method void setDrawLooper(sk_sp<SkDrawLooper> drawLooper)
Cary Clarkab2621d2018-01-30 10:08:57 -05002835#In Draw_Looper_Methods
2836#Line # sets Draw_Looper, multiple layers ##
Cary Clark09d80c02018-10-31 12:14:03 -04002837#Populate
Cary Clark6fc50412017-09-21 12:31:06 -04002838
Cary Clark09d80c02018-10-31 12:14:03 -04002839#Example
Cary Clark8032b982017-07-28 11:04:54 -04002840 #Height 128
2841 void draw(SkCanvas* canvas) {
2842 SkPaint paint;
2843 paint.setDrawLooper(SkBlurDrawLooper::Make(0x7FFF0000, 4, -5, -10));
2844 paint.setStyle(SkPaint::kStroke_Style);
2845 paint.setStrokeWidth(10);
2846 paint.setAntiAlias(true);
2847 paint.setColor(0x7f0000ff);
2848 canvas->drawCircle(70, 70, 50, paint);
2849 }
2850 ##
2851
2852##
2853
Cary Clark08895c42018-02-01 09:37:32 -05002854#Subtopic Draw_Looper_Methods ##
Cary Clark4855f782018-02-06 09:41:53 -05002855
Cary Clark08895c42018-02-01 09:37:32 -05002856#Subtopic Text_Size
2857#Line # overall height in points ##
Cary Clark8032b982017-07-28 11:04:54 -04002858
2859Text_Size adjusts the overall text size in points.
2860Text_Size can be set to any positive value or zero.
2861Text_Size defaults to 12.
2862Set SkPaintDefaults_TextSize at compile time to change the default setting.
2863
2864#Example
2865#Height 135
2866 void draw(SkCanvas* canvas) {
2867 SkPaint paint;
2868 canvas->drawString("12 point", 10, 20, paint);
2869 paint.setTextSize(24);
2870 canvas->drawString("24 point", 10, 60, paint);
2871 paint.setTextSize(48);
2872 canvas->drawString("48 point", 10, 120, paint);
2873 }
2874##
2875
2876#Method SkScalar getTextSize() const
2877
Cary Clarkab2621d2018-01-30 10:08:57 -05002878#In Text_Size
2879#Line # returns text size in points ##
Cary Clark09d80c02018-10-31 12:14:03 -04002880#Populate
Cary Clark8032b982017-07-28 11:04:54 -04002881
Cary Clark09d80c02018-10-31 12:14:03 -04002882#Example
Cary Clark8032b982017-07-28 11:04:54 -04002883 SkPaint paint;
2884 SkDebugf("12 %c= default text size\n", 12 == paint.getTextSize() ? '=' : '!');
2885 ##
2886
2887##
2888
2889#Method void setTextSize(SkScalar textSize)
2890
Cary Clarkab2621d2018-01-30 10:08:57 -05002891#In Text_Size
2892#Line # sets text size in points ##
Cary Clark09d80c02018-10-31 12:14:03 -04002893#Populate
Herb Derbyfcac00f2018-05-01 11:57:56 -04002894
Cary Clark09d80c02018-10-31 12:14:03 -04002895#Example
Cary Clark8032b982017-07-28 11:04:54 -04002896 SkPaint paint;
2897 SkDebugf("12 %c= text size\n", 12 == paint.getTextSize() ? '=' : '!');
2898 paint.setTextSize(-20);
2899 SkDebugf("12 %c= text size\n", 12 == paint.getTextSize() ? '=' : '!');
2900 ##
2901
2902##
2903
Cary Clark08895c42018-02-01 09:37:32 -05002904#Subtopic Text_Size ##
Cary Clark8032b982017-07-28 11:04:54 -04002905# ------------------------------------------------------------------------------
Cary Clark08895c42018-02-01 09:37:32 -05002906#Subtopic Text_Scale_X
2907#Line # text horizontal scale ##
Cary Clark8032b982017-07-28 11:04:54 -04002908
2909Text_Scale_X adjusts the text horizontal scale.
2910Text scaling approximates condensed and expanded type faces when the actual face
2911is not available.
2912Text_Scale_X can be set to any value.
2913Text_Scale_X defaults to 1.
2914
2915#Example
2916#Height 128
2917 void draw(SkCanvas* canvas) {
2918 SkPaint paint;
2919 paint.setAntiAlias(true);
2920 paint.setTextSize(24);
2921 paint.setTextScaleX(.8f);
2922 canvas->drawString("narrow", 10, 20, paint);
2923 paint.setTextScaleX(1);
2924 canvas->drawString("normal", 10, 60, paint);
2925 paint.setTextScaleX(1.2f);
2926 canvas->drawString("wide", 10, 100, paint);
2927 }
2928##
2929
2930#Method SkScalar getTextScaleX() const
2931
Cary Clarkab2621d2018-01-30 10:08:57 -05002932#In Text_Scale_X
2933#Line # returns the text horizontal scale; condensed text ##
Cary Clark09d80c02018-10-31 12:14:03 -04002934#Populate
Cary Clark8032b982017-07-28 11:04:54 -04002935
Cary Clark09d80c02018-10-31 12:14:03 -04002936#Example
Cary Clark8032b982017-07-28 11:04:54 -04002937 SkPaint paint;
2938 SkDebugf("1 %c= default text scale x\n", 1 == paint.getTextScaleX() ? '=' : '!');
2939 ##
2940
2941##
2942
2943
2944#Method void setTextScaleX(SkScalar scaleX)
2945
Cary Clarkab2621d2018-01-30 10:08:57 -05002946#In Text_Scale_X
2947#Line # sets the text horizontal scale; condensed text ##
Cary Clark09d80c02018-10-31 12:14:03 -04002948#Populate
Herb Derbyfcac00f2018-05-01 11:57:56 -04002949
Cary Clark09d80c02018-10-31 12:14:03 -04002950#Example
Cary Clark8032b982017-07-28 11:04:54 -04002951 SkPaint paint;
2952 paint.setTextScaleX(0.f / 0.f);
2953 SkDebugf("text scale %s-a-number\n", SkScalarIsNaN(paint.getTextScaleX()) ? "not" : "is");
2954 ##
2955
2956##
2957
Cary Clark08895c42018-02-01 09:37:32 -05002958#Subtopic Text_Scale_X ##
Cary Clark8032b982017-07-28 11:04:54 -04002959
Cary Clark08895c42018-02-01 09:37:32 -05002960#Subtopic Text_Skew_X
2961#Line # text horizontal slant ##
Cary Clark8032b982017-07-28 11:04:54 -04002962
2963
2964Text_Skew_X adjusts the text horizontal slant.
2965Text skewing approximates italic and oblique type faces when the actual face
2966is not available.
2967Text_Skew_X can be set to any value.
2968Text_Skew_X defaults to 0.
2969
2970#Example
2971#Height 128
2972 void draw(SkCanvas* canvas) {
2973 SkPaint paint;
2974 paint.setAntiAlias(true);
2975 paint.setTextSize(24);
2976 paint.setTextSkewX(-.25f);
2977 canvas->drawString("right-leaning", 10, 100, paint);
2978 paint.setTextSkewX(0);
2979 canvas->drawString("normal", 10, 60, paint);
2980 paint.setTextSkewX(.25f);
2981 canvas->drawString("left-leaning", 10, 20, paint);
2982 }
2983##
2984
2985#Method SkScalar getTextSkewX() const
2986
Cary Clarkab2621d2018-01-30 10:08:57 -05002987#In Text_Skew_X
2988#Line # returns the text horizontal skew; oblique text ##
Cary Clark09d80c02018-10-31 12:14:03 -04002989#Populate
Cary Clark8032b982017-07-28 11:04:54 -04002990
Cary Clark09d80c02018-10-31 12:14:03 -04002991#Example
Cary Clark8032b982017-07-28 11:04:54 -04002992 SkPaint paint;
2993 SkDebugf("0 %c= default text skew x\n", 0 == paint.getTextSkewX() ? '=' : '!');
2994 ##
2995
2996##
2997
2998#Method void setTextSkewX(SkScalar skewX)
2999
Cary Clarkab2621d2018-01-30 10:08:57 -05003000#In Text_Skew_X
3001#Line # sets the text horizontal skew; oblique text ##
Cary Clark09d80c02018-10-31 12:14:03 -04003002#Populate
Cary Clark8032b982017-07-28 11:04:54 -04003003
Cary Clark09d80c02018-10-31 12:14:03 -04003004#Example
Cary Clark8032b982017-07-28 11:04:54 -04003005 SkPaint paint;
3006 paint.setTextScaleX(1.f / 0.f);
3007 SkDebugf("text scale %s-finite\n", SkScalarIsFinite(paint.getTextScaleX()) ? "is" : "not");
3008 ##
3009
3010##
3011
Cary Clark08895c42018-02-01 09:37:32 -05003012#Subtopic Text_Skew_X ##
Cary Clark8032b982017-07-28 11:04:54 -04003013
3014# ------------------------------------------------------------------------------
Cary Clark08895c42018-02-01 09:37:32 -05003015#Subtopic Text_Encoding
3016#Line # text encoded as characters or Glyphs ##
Cary Clark8032b982017-07-28 11:04:54 -04003017
3018#Enum TextEncoding
Cary Clark08895c42018-02-01 09:37:32 -05003019#Line # character or glyph encoded size ##
Cary Clark8032b982017-07-28 11:04:54 -04003020
3021#Code
Cary Clarka90ea222018-10-16 10:30:28 -04003022#Populate
Cary Clark8032b982017-07-28 11:04:54 -04003023##
3024
Cary Clark6fc50412017-09-21 12:31:06 -04003025TextEncoding determines whether text specifies character codes and their encoded
Cary Clarkbc5697d2017-10-04 14:31:33 -04003026size, or glyph indices. Characters are encoded as specified by the
Cary Clark682c58d2018-05-16 07:07:07 -04003027#A Unicode standard # https://unicode.org/standard/standard.html ##
Cary Clark6fc50412017-09-21 12:31:06 -04003028.
3029
Cary Clark8032b982017-07-28 11:04:54 -04003030Character codes encoded size are specified by UTF-8, UTF-16, or UTF-32.
Cary Clarkbc5697d2017-10-04 14:31:33 -04003031All character code formats are able to represent all of Unicode, differing only
Cary Clark8032b982017-07-28 11:04:54 -04003032in the total storage required.
3033
Cary Clark6fc50412017-09-21 12:31:06 -04003034#A UTF-8 (RFC 3629) # https://tools.ietf.org/html/rfc3629 ##
3035 encodes each character as one or more 8-bit bytes.
3036
3037#A UTF-16 (RFC 2781) # https://tools.ietf.org/html/rfc2781 ##
3038 encodes each character as one or two 16-bit words.
3039
Cary Clark682c58d2018-05-16 07:07:07 -04003040#A UTF-32 # https://www.unicode.org/versions/Unicode5.0.0/ch03.pdf ##
Cary Clark6fc50412017-09-21 12:31:06 -04003041 encodes each character as one 32-bit word.
Cary Clark8032b982017-07-28 11:04:54 -04003042
Herb Derbyfcac00f2018-05-01 11:57:56 -04003043Font_Manager uses font data to convert character code points into glyph indices.
Cary Clark8032b982017-07-28 11:04:54 -04003044A glyph index is a 16-bit word.
3045
3046TextEncoding is set to kUTF8_TextEncoding by default.
3047
3048#Const kUTF8_TextEncoding 0
Cary Clark682c58d2018-05-16 07:07:07 -04003049#Line # uses bytes to represent UTF-8 or ASCII ##
Cary Clark8032b982017-07-28 11:04:54 -04003050##
3051#Const kUTF16_TextEncoding 1
Cary Clark682c58d2018-05-16 07:07:07 -04003052#Line # uses two byte words to represent most of Unicode ##
Cary Clark8032b982017-07-28 11:04:54 -04003053##
3054#Const kUTF32_TextEncoding 2
Cary Clark682c58d2018-05-16 07:07:07 -04003055#Line # uses four byte words to represent all of Unicode ##
Cary Clark8032b982017-07-28 11:04:54 -04003056##
3057#Const kGlyphID_TextEncoding 3
Cary Clark682c58d2018-05-16 07:07:07 -04003058#Line # uses two byte words to represent glyph indices ##
Cary Clark8032b982017-07-28 11:04:54 -04003059##
3060
3061#Enum ##
3062
3063#Example
3064#Height 128
3065#Description
Cary Clarkbc5697d2017-10-04 14:31:33 -04003066First line is encoded in UTF-8.
3067Second line is encoded in UTF-16.
3068Third line is encoded in UTF-32.
Cary Clark682c58d2018-05-16 07:07:07 -04003069Fourth line has 16-bit glyph indices.
Cary Clark8032b982017-07-28 11:04:54 -04003070##
3071void draw(SkCanvas* canvas) {
3072 SkPaint paint;
3073 const char hello8[] = "Hello" "\xE2" "\x98" "\xBA";
3074 const uint16_t hello16[] = { 'H', 'e', 'l', 'l', 'o', 0x263A };
3075 const uint32_t hello32[] = { 'H', 'e', 'l', 'l', 'o', 0x263A };
3076 paint.setTextSize(24);
3077 canvas->drawText(hello8, sizeof(hello8) - 1, 10, 30, paint);
3078 paint.setTextEncoding(SkPaint::kUTF16_TextEncoding);
3079 canvas->drawText(hello16, sizeof(hello16), 10, 60, paint);
3080 paint.setTextEncoding(SkPaint::kUTF32_TextEncoding);
3081 canvas->drawText(hello32, sizeof(hello32), 10, 90, paint);
3082 uint16_t glyphs[SK_ARRAY_COUNT(hello32)];
3083 paint.textToGlyphs(hello32, sizeof(hello32), glyphs);
3084 paint.setTextEncoding(SkPaint::kGlyphID_TextEncoding);
3085 canvas->drawText(glyphs, sizeof(glyphs), 10, 120, paint);
3086}
3087##
3088
3089#Method TextEncoding getTextEncoding() const
3090
Cary Clarkab2621d2018-01-30 10:08:57 -05003091#In Text_Encoding
3092#Line # returns character or glyph encoded size ##
Cary Clark09d80c02018-10-31 12:14:03 -04003093#Populate
Cary Clark8032b982017-07-28 11:04:54 -04003094
Cary Clark09d80c02018-10-31 12:14:03 -04003095#Example
Cary Clark8032b982017-07-28 11:04:54 -04003096 SkPaint paint;
Herb Derbyfcac00f2018-05-01 11:57:56 -04003097 SkDebugf("kUTF8_TextEncoding %c= text encoding\n",
Cary Clark8032b982017-07-28 11:04:54 -04003098 SkPaint::kUTF8_TextEncoding == paint.getTextEncoding() ? '=' : '!');
3099 paint.setTextEncoding(SkPaint::kGlyphID_TextEncoding);
Herb Derbyfcac00f2018-05-01 11:57:56 -04003100 SkDebugf("kGlyphID_TextEncoding %c= text encoding\n",
Cary Clark8032b982017-07-28 11:04:54 -04003101 SkPaint::kGlyphID_TextEncoding == paint.getTextEncoding() ? '=' : '!');
3102
3103 #StdOut
3104 kUTF8_TextEncoding == text encoding
3105 kGlyphID_TextEncoding == text encoding
3106 ##
3107 ##
3108
3109##
3110
3111
3112#Method void setTextEncoding(TextEncoding encoding)
3113
Cary Clarkab2621d2018-01-30 10:08:57 -05003114#In Text_Encoding
3115#Line # sets character or glyph encoded size ##
Cary Clark09d80c02018-10-31 12:14:03 -04003116#Populate
Cary Clark8032b982017-07-28 11:04:54 -04003117
Cary Clark09d80c02018-10-31 12:14:03 -04003118#Example
Cary Clark8032b982017-07-28 11:04:54 -04003119 SkPaint paint;
3120 paint.setTextEncoding((SkPaint::TextEncoding) 4);
Cary Clark75fd4492018-06-20 12:45:16 -04003121 SkDebugf("4 %c= text encoding\n", (SkPaint::TextEncoding) 4 == paint.getTextEncoding() ? '=' : '!');
Cary Clark8032b982017-07-28 11:04:54 -04003122
3123 #StdOut
3124 4 != text encoding
3125 ##
3126 ##
3127
3128##
3129
Cary Clark7e69c8f2018-11-06 20:40:45 -05003130#Typedef typedef SkFontMetrics FontMetrics
3131##
3132
Cary Clark08895c42018-02-01 09:37:32 -05003133#Subtopic Text_Encoding ##
Cary Clark8032b982017-07-28 11:04:54 -04003134# ------------------------------------------------------------------------------
Cary Clark08895c42018-02-01 09:37:32 -05003135#Subtopic Font_Metrics
Cary Clark8032b982017-07-28 11:04:54 -04003136
Cary Clark7e69c8f2018-11-06 20:40:45 -05003137#Method SkScalar getFontMetrics(SkFontMetrics* metrics) const
Cary Clark8032b982017-07-28 11:04:54 -04003138
Cary Clarkab2621d2018-01-30 10:08:57 -05003139#In Font_Metrics
3140#Line # returns Typeface metrics scaled by text size ##
Cary Clark09d80c02018-10-31 12:14:03 -04003141#Populate
Cary Clark8032b982017-07-28 11:04:54 -04003142
Cary Clark09d80c02018-10-31 12:14:03 -04003143#Example
Cary Clark8032b982017-07-28 11:04:54 -04003144 #Height 128
3145 void draw(SkCanvas* canvas) {
3146 SkPaint paint;
3147 paint.setTextSize(32);
3148 SkScalar lineHeight = paint.getFontMetrics(nullptr);
3149 canvas->drawString("line 1", 10, 40, paint);
3150 canvas->drawString("line 2", 10, 40 + lineHeight, paint);
Cary Clark8032b982017-07-28 11:04:54 -04003151 }
3152 ##
3153
3154 #SeeAlso Text_Size Typeface Typeface_Methods
3155
3156##
3157
3158
3159#Method SkScalar getFontSpacing() const
3160
Cary Clarkab2621d2018-01-30 10:08:57 -05003161#In Font_Metrics
3162#Line # returns recommended spacing between lines ##
Cary Clark09d80c02018-10-31 12:14:03 -04003163#Populate
Cary Clark8032b982017-07-28 11:04:54 -04003164
Cary Clark09d80c02018-10-31 12:14:03 -04003165#Example
Cary Clark8032b982017-07-28 11:04:54 -04003166 SkPaint paint;
3167 for (SkScalar textSize : { 12, 18, 24, 32 } ) {
3168 paint.setTextSize(textSize);
3169 SkDebugf("textSize: %g fontSpacing: %g\n", textSize, paint.getFontSpacing());
3170 }
3171
3172 #StdOut
3173 textSize: 12 fontSpacing: 13.9688
3174 textSize: 18 fontSpacing: 20.9531
3175 textSize: 24 fontSpacing: 27.9375
3176 textSize: 32 fontSpacing: 37.25
3177 ##
3178 ##
3179
3180##
3181
Cary Clark08895c42018-02-01 09:37:32 -05003182#Subtopic Font_Metrics ##
Cary Clark77b3f3a2018-11-07 14:59:03 -05003183
Cary Clark8032b982017-07-28 11:04:54 -04003184# ------------------------------------------------------------------------------
3185
3186#Method int textToGlyphs(const void* text, size_t byteLength,
3187 SkGlyphID glyphs[]) const
Cary Clark78de7512018-02-07 07:27:09 -05003188#In Utility
Cary Clarkab2621d2018-01-30 10:08:57 -05003189#Line # converts text into glyph indices ##
Cary Clark09d80c02018-10-31 12:14:03 -04003190#Populate
Cary Clark8032b982017-07-28 11:04:54 -04003191
Cary Clark09d80c02018-10-31 12:14:03 -04003192#Example
Cary Clark8032b982017-07-28 11:04:54 -04003193 #Height 64
3194 void draw(SkCanvas* canvas) {
3195 SkPaint paint;
3196 const uint8_t utf8[] = { 0x24, 0xC2, 0xA2, 0xE2, 0x82, 0xAC, 0xC2, 0xA5, 0xC2, 0xA3 };
3197 std::vector<SkGlyphID> glyphs;
3198 int count = paint.textToGlyphs(utf8, sizeof(utf8), nullptr);
3199 glyphs.resize(count);
3200 (void) paint.textToGlyphs(utf8, sizeof(utf8), &glyphs.front());
3201 paint.setTextEncoding(SkPaint::kGlyphID_TextEncoding);
3202 paint.setTextSize(32);
3203 canvas->drawText(&glyphs.front(), glyphs.size() * sizeof(SkGlyphID), 10, 40, paint);
3204 }
3205 ##
3206
3207##
3208
3209#Method int countText(const void* text, size_t byteLength) const
Cary Clark78de7512018-02-07 07:27:09 -05003210#In Utility
Cary Clarkab2621d2018-01-30 10:08:57 -05003211#Line # returns number of Glyphs in text ##
Cary Clark09d80c02018-10-31 12:14:03 -04003212#Populate
Cary Clark8032b982017-07-28 11:04:54 -04003213
Cary Clark09d80c02018-10-31 12:14:03 -04003214#Example
Cary Clark8032b982017-07-28 11:04:54 -04003215 SkPaint paint;
3216 const uint8_t utf8[] = { 0x24, 0xC2, 0xA2, 0xE2, 0x82, 0xAC, 0xC2, 0xA5, 0xC2, 0xA3 };
3217 SkDebugf("count = %d\n", paint.countText(utf8, sizeof(utf8)));
3218
3219 #StdOut
3220 count = 5
3221 ##
3222 ##
3223##
3224
3225# ------------------------------------------------------------------------------
3226
3227#Method bool containsText(const void* text, size_t byteLength) const
Cary Clark78de7512018-02-07 07:27:09 -05003228#In Utility
Cary Clarkab2621d2018-01-30 10:08:57 -05003229#Line # returns if all text corresponds to Glyphs ##
Cary Clark09d80c02018-10-31 12:14:03 -04003230#Populate
Cary Clark8032b982017-07-28 11:04:54 -04003231
Cary Clark09d80c02018-10-31 12:14:03 -04003232#NoExample
Cary Clark8032b982017-07-28 11:04:54 -04003233 #Description
3234 containsText succeeds for degree symbol, but cannot find a glyph index
3235 corresponding to the Unicode surrogate code point.
3236 ##
3237 SkPaint paint;
3238 const uint16_t goodChar = 0x00B0; // degree symbol
3239 const uint16_t badChar = 0xD800; // Unicode surrogate
3240 paint.setTextEncoding(SkPaint::kUTF16_TextEncoding);
Herb Derbyfcac00f2018-05-01 11:57:56 -04003241 SkDebugf("0x%04x %c= has char\n", goodChar,
Cary Clark8032b982017-07-28 11:04:54 -04003242 paint.containsText(&goodChar, 2) ? '=' : '!');
3243 SkDebugf("0x%04x %c= has char\n", badChar,
3244 paint.containsText(&badChar, 2) ? '=' : '!');
3245
3246 #StdOut
3247 0x00b0 == has char
3248 0xd800 != has char
3249 ##
3250 ##
3251
3252 #Example
3253 #Description
3254 containsText returns true that glyph index is greater than zero, not
3255 that it corresponds to an entry in Typeface.
3256 ##
3257 SkPaint paint;
3258 const uint16_t goodGlyph = 511;
3259 const uint16_t zeroGlyph = 0;
3260 const uint16_t badGlyph = 65535; // larger than glyph count in font
3261 paint.setTextEncoding(SkPaint::kGlyphID_TextEncoding);
Herb Derbyfcac00f2018-05-01 11:57:56 -04003262 SkDebugf("0x%04x %c= has glyph\n", goodGlyph,
Cary Clark8032b982017-07-28 11:04:54 -04003263 paint.containsText(&goodGlyph, 2) ? '=' : '!');
3264 SkDebugf("0x%04x %c= has glyph\n", zeroGlyph,
3265 paint.containsText(&zeroGlyph, 2) ? '=' : '!');
3266 SkDebugf("0x%04x %c= has glyph\n", badGlyph,
3267 paint.containsText(&badGlyph, 2) ? '=' : '!');
3268
3269 #StdOut
3270 0x01ff == has glyph
3271 0x0000 != has glyph
3272 0xffff == has glyph
3273 ##
3274 ##
3275
3276#SeeAlso setTextEncoding Typeface
3277
3278##
3279
3280# ------------------------------------------------------------------------------
3281
3282#Method void glyphsToUnichars(const SkGlyphID glyphs[],
3283 int count, SkUnichar text[]) const
Cary Clark78de7512018-02-07 07:27:09 -05003284#In Utility
Cary Clarkab2621d2018-01-30 10:08:57 -05003285#Line # converts Glyphs into text ##
Cary Clark09d80c02018-10-31 12:14:03 -04003286#Populate
Cary Clark8032b982017-07-28 11:04:54 -04003287
Cary Clark09d80c02018-10-31 12:14:03 -04003288#Example
Cary Clark8032b982017-07-28 11:04:54 -04003289 #Height 64
3290 #Description
3291 Convert UTF-8 text to glyphs; then convert glyphs to Unichar code points.
3292 ##
3293 void draw(SkCanvas* canvas) {
3294 SkPaint paint;
3295 const char hello[] = "Hello!";
3296 const int count = sizeof(hello) - 1;
3297 SkGlyphID glyphs[count];
3298 if (count != paint.textToGlyphs(hello, count, glyphs)) {
3299 return;
3300 }
3301 SkUnichar unichars[count];
3302 paint.glyphsToUnichars(glyphs, count, unichars);
3303 paint.setTextEncoding(SkPaint::kUTF32_TextEncoding);
3304 canvas->drawText(unichars, sizeof(unichars), 10, 30, paint);
3305 }
3306 ##
3307
3308##
3309
3310# ------------------------------------------------------------------------------
Cary Clark08895c42018-02-01 09:37:32 -05003311#Subtopic Measure_Text
3312#Line # width, height, bounds of text ##
Cary Clark8032b982017-07-28 11:04:54 -04003313
3314#Method SkScalar measureText(const void* text, size_t length, SkRect* bounds) const
3315
Cary Clarkab2621d2018-01-30 10:08:57 -05003316#In Measure_Text
3317#Line # returns advance width and bounds of text ##
Cary Clark09d80c02018-10-31 12:14:03 -04003318#Populate
Herb Derbyfcac00f2018-05-01 11:57:56 -04003319
Cary Clark09d80c02018-10-31 12:14:03 -04003320#Example
Cary Clark8032b982017-07-28 11:04:54 -04003321 #Height 64
3322 void draw(SkCanvas* canvas) {
3323 SkPaint paint;
3324 paint.setAntiAlias(true);
3325 paint.setTextSize(50);
3326 const char str[] = "ay^jZ";
3327 const int count = sizeof(str) - 1;
3328 canvas->drawText(str, count, 25, 50, paint);
3329 SkRect bounds;
3330 paint.measureText(str, count, &bounds);
3331 canvas->translate(25, 50);
3332 paint.setStyle(SkPaint::kStroke_Style);
3333 canvas->drawRect(bounds, paint);
3334 }
3335 ##
3336
3337##
3338
3339#Method SkScalar measureText(const void* text, size_t length) const
3340
Cary Clarkab2621d2018-01-30 10:08:57 -05003341#In Measure_Text
Cary Clark09d80c02018-10-31 12:14:03 -04003342#Populate
Cary Clark8032b982017-07-28 11:04:54 -04003343
Cary Clark09d80c02018-10-31 12:14:03 -04003344#Example
Cary Clark8032b982017-07-28 11:04:54 -04003345 SkPaint paint;
3346 SkDebugf("default width = %g\n", paint.measureText("!", 1));
3347 paint.setTextSize(paint.getTextSize() * 2);
3348 SkDebugf("double width = %g\n", paint.measureText("!", 1));
3349
3350 #StdOut
3351 default width = 5
3352 double width = 10
3353 ##
3354 ##
3355
3356##
3357
3358#Method size_t breakText(const void* text, size_t length, SkScalar maxWidth,
Cary Clark73fa9722017-08-29 17:36:51 -04003359 SkScalar* measuredWidth = nullptr) const
Cary Clarkab2621d2018-01-30 10:08:57 -05003360#In Measure_Text
3361#Line # returns text that fits in a width ##
Cary Clark09d80c02018-10-31 12:14:03 -04003362#Populate
Cary Clark8032b982017-07-28 11:04:54 -04003363
Cary Clark09d80c02018-10-31 12:14:03 -04003364#Example
Cary Clark8032b982017-07-28 11:04:54 -04003365 #Description
3366 Line under "Breakfast" shows desired width, shorter than available characters.
3367 Line under "Bre" shows measured width after breaking text.
3368 ##
3369 #Height 128
3370 #Width 280
3371 void draw(SkCanvas* canvas) {
3372 SkPaint paint;
3373 paint.setAntiAlias(true);
3374 paint.setTextSize(50);
3375 const char str[] = "Breakfast";
3376 const int count = sizeof(str) - 1;
3377 canvas->drawText(str, count, 25, 50, paint);
3378 SkScalar measuredWidth;
3379 int partialBytes = paint.breakText(str, count, 100, &measuredWidth);
3380 canvas->drawText(str, partialBytes, 25, 100, paint);
3381 canvas->drawLine(25, 60, 25 + 100, 60, paint);
3382 canvas->drawLine(25, 110, 25 + measuredWidth, 110, paint);
3383 }
3384 ##
3385
3386##
3387
3388#Method int getTextWidths(const void* text, size_t byteLength, SkScalar widths[],
Cary Clark73fa9722017-08-29 17:36:51 -04003389 SkRect bounds[] = nullptr) const
Cary Clarkab2621d2018-01-30 10:08:57 -05003390#In Measure_Text
3391#Line # returns advance and bounds for each glyph in text ##
Cary Clark09d80c02018-10-31 12:14:03 -04003392#Populate
Cary Clark8032b982017-07-28 11:04:54 -04003393
Cary Clark09d80c02018-10-31 12:14:03 -04003394#Example
Cary Clark8032b982017-07-28 11:04:54 -04003395 #Height 160
3396 #Description
Cary Clarkce101242017-09-01 15:51:02 -04003397 Bounds of Glyphs increase for stroked text, but text advance remains the same.
Cary Clark8032b982017-07-28 11:04:54 -04003398 The underlines show the text advance, spaced to keep them distinct.
3399 ##
3400 void draw(SkCanvas* canvas) {
3401 SkPaint paint;
3402 paint.setAntiAlias(true);
3403 paint.setTextSize(50);
3404 const char str[] = "abc";
3405 const int bytes = sizeof(str) - 1;
3406 int count = paint.getTextWidths(str, bytes, nullptr);
3407 std::vector<SkScalar> widths;
3408 std::vector<SkRect> bounds;
3409 widths.resize(count);
3410 bounds.resize(count);
3411 for (int loop = 0; loop < 2; ++loop) {
3412 (void) paint.getTextWidths(str, count, &widths.front(), &bounds.front());
3413 SkPoint loc = { 25, 50 };
3414 canvas->drawText(str, bytes, loc.fX, loc.fY, paint);
3415 paint.setStyle(SkPaint::kStroke_Style);
3416 paint.setStrokeWidth(0);
3417 SkScalar advanceY = loc.fY + 10;
3418 for (int index = 0; index < count; ++index) {
3419 bounds[index].offset(loc.fX, loc.fY);
3420 canvas->drawRect(bounds[index], paint);
3421 canvas->drawLine(loc.fX, advanceY, loc.fX + widths[index], advanceY, paint);
3422 loc.fX += widths[index];
3423 advanceY += 5;
3424 }
3425 canvas->translate(0, 80);
3426 paint.setStrokeWidth(3);
3427 }
3428 }
3429 ##
3430
3431##
3432
Cary Clark08895c42018-02-01 09:37:32 -05003433#Subtopic Measure_Text ##
Cary Clark8032b982017-07-28 11:04:54 -04003434# ------------------------------------------------------------------------------
Cary Clark08895c42018-02-01 09:37:32 -05003435#Subtopic Text_Path
3436#Line # geometry of Glyphs ##
Cary Clark8032b982017-07-28 11:04:54 -04003437
Cary Clarkce101242017-09-01 15:51:02 -04003438Text_Path describes the geometry of Glyphs used to draw text.
Cary Clark8032b982017-07-28 11:04:54 -04003439
3440#Method void getTextPath(const void* text, size_t length, SkScalar x, SkScalar y,
3441 SkPath* path) const
Cary Clarkab2621d2018-01-30 10:08:57 -05003442#In Text_Path
3443#Line # returns Path equivalent to text ##
Cary Clark09d80c02018-10-31 12:14:03 -04003444#Populate
Cary Clark8032b982017-07-28 11:04:54 -04003445
Cary Clark09d80c02018-10-31 12:14:03 -04003446#Example
Cary Clark8032b982017-07-28 11:04:54 -04003447 #Description
3448 Text is added to Path, offset, and subtracted from Path, then added at
3449 the offset location. The result is rendered with one draw call.
3450 ##
3451 #Height 128
3452 void draw(SkCanvas* canvas) {
3453 SkPaint paint;
3454 paint.setTextSize(80);
3455 SkPath path, path2;
3456 paint.getTextPath("ABC", 3, 20, 80, &path);
3457 path.offset(20, 20, &path2);
3458 Op(path, path2, SkPathOp::kDifference_SkPathOp, &path);
3459 path.addPath(path2);
3460 paint.setStyle(SkPaint::kStroke_Style);
3461 canvas->drawPath(path, paint);
3462 }
3463 ##
3464
3465##
3466
3467#Method void getPosTextPath(const void* text, size_t length,
3468 const SkPoint pos[], SkPath* path) const
Cary Clarkab2621d2018-01-30 10:08:57 -05003469#In Text_Path
3470#Line # returns Path equivalent to positioned text ##
Cary Clark09d80c02018-10-31 12:14:03 -04003471#Populate
Cary Clark8032b982017-07-28 11:04:54 -04003472
Cary Clark09d80c02018-10-31 12:14:03 -04003473#Example
Cary Clark8032b982017-07-28 11:04:54 -04003474 #Height 85
3475 #Description
Cary Clarkce101242017-09-01 15:51:02 -04003476 Simplifies three Glyphs to eliminate overlaps, and strokes the result.
Cary Clark8032b982017-07-28 11:04:54 -04003477 ##
3478 void draw(SkCanvas* canvas) {
3479 SkPaint paint;
3480 paint.setTextSize(80);
3481 SkPath path, path2;
3482 SkPoint pos[] = {{20, 60}, {30, 70}, {40, 80}};
3483 paint.getPosTextPath("ABC", 3, pos, &path);
3484 Simplify(path, &path);
3485 paint.setStyle(SkPaint::kStroke_Style);
3486 canvas->drawPath(path, paint);
3487 }
3488 ##
3489
3490##
3491
Cary Clark08895c42018-02-01 09:37:32 -05003492#Subtopic Text_Path ##
Cary Clark8032b982017-07-28 11:04:54 -04003493# ------------------------------------------------------------------------------
Cary Clark08895c42018-02-01 09:37:32 -05003494#Subtopic Text_Intercepts
3495#Line # advanced underline, strike through ##
Cary Clark8032b982017-07-28 11:04:54 -04003496
Cary Clarkce101242017-09-01 15:51:02 -04003497Text_Intercepts describe the intersection of drawn text Glyphs with a pair
Cary Clark8032b982017-07-28 11:04:54 -04003498of lines parallel to the text advance. Text_Intercepts permits creating a
Cary Clarkce101242017-09-01 15:51:02 -04003499underline that skips Descenders.
Cary Clark8032b982017-07-28 11:04:54 -04003500
3501#Method int getTextIntercepts(const void* text, size_t length, SkScalar x, SkScalar y,
3502 const SkScalar bounds[2], SkScalar* intervals) const
Cary Clarkab2621d2018-01-30 10:08:57 -05003503#In Text_Intercepts
3504#Line # returns where lines intersect text; underlines ##
Cary Clark09d80c02018-10-31 12:14:03 -04003505#Populate
Cary Clark8032b982017-07-28 11:04:54 -04003506
Cary Clarke9c5a152018-11-21 11:45:57 -05003507#NoExample
Cary Clark8032b982017-07-28 11:04:54 -04003508#Height 128
3509#Description
Cary Clarkce101242017-09-01 15:51:02 -04003510Underline uses intercepts to draw on either side of the glyph Descender.
Cary Clark8032b982017-07-28 11:04:54 -04003511##
3512void draw(SkCanvas* canvas) {
3513 SkPaint paint;
3514 paint.setTextSize(120);
3515 SkPoint textOrigin = { 20, 100 };
3516 SkScalar bounds[] = { 100, 108 };
3517 int count = paint.getTextIntercepts("y", 1, textOrigin.fX, textOrigin.fY, bounds, nullptr);
3518 std::vector<SkScalar> intervals;
3519 intervals.resize(count);
3520 (void) paint.getTextIntercepts("y", 1, textOrigin.fX, textOrigin.fY, bounds,
3521 &intervals.front());
3522 canvas->drawString("y", textOrigin.fX, textOrigin.fY, paint);
3523 paint.setColor(SK_ColorRED);
3524 SkScalar x = textOrigin.fX;
3525 for (int i = 0; i < count; i += 2) {
3526 canvas->drawRect({x, bounds[0], intervals[i], bounds[1]}, paint);
3527 x = intervals[i + 1];
3528 }
3529 canvas->drawRect({intervals[count - 1], bounds[0],
3530 textOrigin.fX + paint.measureText("y", 1), bounds[1]}, paint);
3531}
3532##
3533
3534##
3535
3536#Method int getPosTextIntercepts(const void* text, size_t length, const SkPoint pos[],
3537 const SkScalar bounds[2], SkScalar* intervals) const
Cary Clarkab2621d2018-01-30 10:08:57 -05003538#In Text_Intercepts
3539#Line # returns where lines intersect positioned text; underlines ##
Cary Clark09d80c02018-10-31 12:14:03 -04003540#Populate
Cary Clark8032b982017-07-28 11:04:54 -04003541
Cary Clarke9c5a152018-11-21 11:45:57 -05003542#NoExample
Cary Clark8032b982017-07-28 11:04:54 -04003543 #Description
Cary Clarkce101242017-09-01 15:51:02 -04003544 Text intercepts draw on either side of, but not inside, Glyphs in a run.
Cary Clark8032b982017-07-28 11:04:54 -04003545 ##
Cary Clark92694be2018-10-25 08:15:36 -04003546 void draw(SkCanvas* canvas) {
3547 SkPaint paint;
3548 paint.setTextSize(120);
3549 SkPoint textPos[] = {{ 60, 90 }, { 120, 90 }};
3550 SkScalar bounds[] = { 40, 70 };
3551 const char str[] = "A+";
3552 int len = sizeof(str) - 1;
3553 int count = paint.getPosTextIntercepts(str, len, textPos, bounds, nullptr);
3554 std::vector<SkScalar> intervals;
3555 intervals.resize(count);
3556 (void) paint.getPosTextIntercepts(str, len, textPos, bounds, &intervals.front());
3557 canvas->drawPosText(str, len, textPos, paint);
3558 paint.setColor(SK_ColorRED);
3559 SkScalar x = textPos[0].fX;
3560 for (int i = 0; i < count; i+= 2) {
3561 canvas->drawRect({x, bounds[0], intervals[i], bounds[1]}, paint);
3562 x = intervals[i + 1];
Cary Clark8032b982017-07-28 11:04:54 -04003563 }
Cary Clark92694be2018-10-25 08:15:36 -04003564 if (count) {
3565 canvas->drawRect({intervals[count - 1], bounds[0], 180, bounds[1]}, paint);
3566 }
3567 }
Cary Clark8032b982017-07-28 11:04:54 -04003568 ##
3569
3570##
3571
3572#Method int getPosTextHIntercepts(const void* text, size_t length, const SkScalar xpos[],
3573 SkScalar constY, const SkScalar bounds[2],
3574 SkScalar* intervals) const
Cary Clarkab2621d2018-01-30 10:08:57 -05003575#In Text_Intercepts
3576#Line # returns where lines intersect horizontally positioned text; underlines ##
Cary Clark09d80c02018-10-31 12:14:03 -04003577#Populate
Cary Clark8032b982017-07-28 11:04:54 -04003578
Cary Clarke9c5a152018-11-21 11:45:57 -05003579#NoExample
Cary Clark8032b982017-07-28 11:04:54 -04003580 #Height 128
3581 #Description
3582 Text intercepts do not take stroke thickness into consideration.
3583 ##
3584 void draw(SkCanvas* canvas) {
3585 SkPaint paint;
3586 paint.setTextSize(120);
3587 paint.setStyle(SkPaint::kStroke_Style);
3588 paint.setStrokeWidth(4);
3589 SkScalar textPosH[] = { 20, 80, 140 };
3590 SkScalar y = 100;
3591 SkScalar bounds[] = { 56, 78 };
3592 const char str[] = "\\-/";
3593 int len = sizeof(str) - 1;
3594 int count = paint.getPosTextHIntercepts(str, len, textPosH, y, bounds, nullptr);
3595 std::vector<SkScalar> intervals;
3596 intervals.resize(count);
3597 (void) paint.getPosTextHIntercepts(str, len, textPosH, y, bounds, &intervals.front());
3598 canvas->drawPosTextH(str, len, textPosH, y, paint);
3599 paint.setColor(0xFFFF7777);
3600 paint.setStyle(SkPaint::kFill_Style);
3601 SkScalar x = textPosH[0];
3602 for (int i = 0; i < count; i+= 2) {
3603 canvas->drawRect({x, bounds[0], intervals[i], bounds[1]}, paint);
3604 x = intervals[i + 1];
3605 }
3606 canvas->drawRect({intervals[count - 1], bounds[0], 180, bounds[1]}, paint);
3607 }
3608 ##
3609
3610##
3611
3612
3613#Method int getTextBlobIntercepts(const SkTextBlob* blob, const SkScalar bounds[2],
3614 SkScalar* intervals) const
Cary Clarkab2621d2018-01-30 10:08:57 -05003615#In Text_Intercepts
3616#Line # returns where lines intersect Text_Blob; underlines ##
Cary Clark09d80c02018-10-31 12:14:03 -04003617#Populate
Cary Clark8032b982017-07-28 11:04:54 -04003618
Cary Clark09d80c02018-10-31 12:14:03 -04003619#Example
Cary Clark8032b982017-07-28 11:04:54 -04003620 #Height 143
3621 void draw(SkCanvas* canvas) {
Mike Reed42af4922018-11-30 08:54:46 -05003622 SkFont font;
3623 font.setSize(120);
3624 SkPoint textPos = { 20, 110 };
3625 int len = 3;
3626 SkTextBlobBuilder textBlobBuilder;
3627 const SkTextBlobBuilder::RunBuffer& run =
3628 textBlobBuilder.allocRun(font, len, textPos.fX, textPos.fY);
3629 run.glyphs[0] = 10;
3630 run.glyphs[1] = 20;
3631 run.glyphs[2] = 30;
3632 sk_sp<const SkTextBlob> blob = textBlobBuilder.make();
3633 SkPaint paint;
3634 SkScalar bounds[] = { 116, 134 };
3635 int count = paint.getTextBlobIntercepts(blob.get(), bounds, nullptr);
3636 std::vector<SkScalar> intervals;
3637 intervals.resize(count);
3638 (void) paint.getTextBlobIntercepts(blob.get(), bounds, &intervals.front());
3639 canvas->drawTextBlob(blob.get(), 0, 0, paint);
3640 paint.setColor(0xFFFF7777);
3641 SkScalar x = textPos.fX;
3642 for (int i = 0; i < count; i+= 2) {
3643 canvas->drawRect({x, bounds[0], intervals[i], bounds[1]}, paint);
3644 x = intervals[i + 1];
3645 }
3646 canvas->drawRect({intervals[count - 1], bounds[0], 180, bounds[1]}, paint);
Cary Clark8032b982017-07-28 11:04:54 -04003647 }
3648 ##
3649
3650##
3651
Cary Clark08895c42018-02-01 09:37:32 -05003652#Subtopic Text_Intercepts ##
Cary Clark8032b982017-07-28 11:04:54 -04003653# ------------------------------------------------------------------------------
3654
Cary Clark77b3f3a2018-11-07 14:59:03 -05003655#Method SkRect getFontBounds() const
3656
3657#In Font_Metrics
3658#Line # returns union all glyph bounds ##
3659#Populate
3660
3661#Example
3662 SkPaint paint;
Mike Reedb5784ac2018-11-12 09:35:15 -05003663 SkFontMetrics fm;
Cary Clark77b3f3a2018-11-07 14:59:03 -05003664 paint.getFontMetrics(&fm);
3665 SkRect fb = paint.getFontBounds();
3666 SkDebugf("metrics bounds = { %g, %g, %g, %g }\n", fm.fXMin, fm.fTop, fm.fXMax, fm.fBottom );
3667 SkDebugf("font bounds = { %g, %g, %g, %g }\n", fb.fLeft, fb.fTop, fb.fRight, fm.fBottom );
3668
3669 #StdOut
3670 metrics bounds = { -12.2461, -14.7891, 21.5215, 5.55469 }
3671 font bounds = { -12.2461, -14.7891, 21.5215, 5.55469 }
3672 ##
3673##
3674
3675##
3676
Cary Clark8032b982017-07-28 11:04:54 -04003677#Method bool nothingToDraw() const
Cary Clark78de7512018-02-07 07:27:09 -05003678#In Utility
Cary Clarkab2621d2018-01-30 10:08:57 -05003679#Line # returns true if Paint prevents all drawing ##
Cary Clark09d80c02018-10-31 12:14:03 -04003680#Populate
Cary Clark8032b982017-07-28 11:04:54 -04003681
Cary Clark09d80c02018-10-31 12:14:03 -04003682#Example
Cary Clark8032b982017-07-28 11:04:54 -04003683 void draw(SkCanvas* canvas) {
3684 auto debugster = [](const char* prefix, const SkPaint& p) -> void {
Herb Derbyfcac00f2018-05-01 11:57:56 -04003685 SkDebugf("%s nothing to draw: %s\n", prefix,
Cary Clark8032b982017-07-28 11:04:54 -04003686 p.nothingToDraw() ? "true" : "false");
3687 };
3688 SkPaint paint;
3689 debugster("initial", paint);
3690 paint.setBlendMode(SkBlendMode::kDst);
3691 debugster("blend dst", paint);
3692 paint.setBlendMode(SkBlendMode::kSrcOver);
3693 debugster("blend src over", paint);
3694 paint.setAlpha(0);
3695 debugster("alpha 0", paint);
3696 }
3697
3698 #StdOut
3699 initial nothing to draw: false
3700 blend dst nothing to draw: true
3701 blend src over nothing to draw: false
3702 alpha 0 nothing to draw: true
3703 #StdOut ##
3704 ##
3705
3706##
3707
3708# ------------------------------------------------------------------------------
Cary Clark78de7512018-02-07 07:27:09 -05003709#Subtopic Utility
Cary Clark78de7512018-02-07 07:27:09 -05003710#Line # rarely called management functions ##
3711##
Cary Clark8032b982017-07-28 11:04:54 -04003712
Cary Clark8032b982017-07-28 11:04:54 -04003713# ------------------------------------------------------------------------------
3714
3715#Class SkPaint ##
3716
3717#Topic Paint ##