blob: c08bc297fd9a67fd10d14963a73dcb6b7a541320 [file] [log] [blame]
Cary Clark0c5f5462017-12-15 11:21:51 -05001#Topic Paint
Cary Clark12799e12017-07-28 15:18:29 -04002#Alias Paint_Reference
Cary Clark8032b982017-07-28 11:04:54 -04003
Cary Clarke4aa3712017-09-15 02:56:12 -04004#Class SkPaint
5
Cary Clark8032b982017-07-28 11:04:54 -04006Paint controls options applied when drawing and measuring. Paint collects all
7options outside of the Canvas_Clip and Canvas_Matrix.
8
9Various options apply to text, strokes and fills, and images.
10
11Some options may not be implemented on all platforms; in these cases, setting
12the option has no effect. Some options are conveniences that duplicate Canvas
13functionality; for instance, text size is identical to matrix scale.
14
15Paint options are rarely exclusive; each option modifies a stage of the drawing
16pipeline and multiple pipeline stages may be affected by a single Paint.
17
18Paint collects effects and filters that describe single-pass and multiple-pass
19algorithms that alter the drawing geometry, color, and transparency. For instance,
20Paint does not directly implement dashing or blur, but contains the objects that do so.
21
22The objects contained by Paint are opaque, and cannot be edited outside of the Paint
23to affect it. The implementation is free to defer computations associated with the
24Paint, or ignore them altogether. For instance, some GPU implementations draw all
Cary Clarkce101242017-09-01 15:51:02 -040025Path geometries with Anti-aliasing, regardless of how SkPaint::kAntiAlias_Flag
Cary Clarkbad5ad72017-08-03 17:14:08 -040026is set in Paint.
Cary Clark8032b982017-07-28 11:04:54 -040027
28Paint describes a single color, a single font, a single image quality, and so on.
29Multiple colors are drawn either by using multiple paints or with objects like
30Shader attached to Paint.
31
Cary Clark8032b982017-07-28 11:04:54 -040032#Topic Overview
33
34#Subtopic Subtopics
Cary Clark8032b982017-07-28 11:04:54 -040035#Table
36#Legend
Cary Clark5081eed2018-01-22 07:55:48 -050037# name # description ##
Cary Clark8032b982017-07-28 11:04:54 -040038#Legend ##
Cary Clark5081eed2018-01-22 07:55:48 -050039# Classes_and_Structs # embedded struct and class members ##
40# Constants # enum and enum class, const values ##
41# Constructors # list of functions that construct SkPath ##
42# Member_Functions # list of static functions and member methods ##
43# Operators # operator overloading methods ##
44# Related_Functions # similar methods grouped together ##
45#Table ##
46#Subtopic ##
47
48#Subtopic Related_Functions
49#Table
50#Legend
51# name # description ##
52#Legend ##
53# Anti-alias # approximating coverage with transparency ##
54# Automatic_Hinting # always adjust glyph paths ##
55# Blend_Mode_Methods # get and set Blend_Mode ##
56# Color_Filter_Methods # get and set Color_Filter ##
57# Color_Methods # get and set Color ##
58# Destructor # paint termination ##
59# Device_Text # increase precision of glyph position ##
60# Dither # distributing color error ##
61# Draw_Looper_Methods # get and set Draw_Looper ##
62# Fake_Bold # approximate font styles ##
63# Fast_Bounds # approximate area required by Paint ##
64# Fill_Path # make Path from Path_Effect, stroking ##
65# Filter_Quality_Methods # get and set Filter_Quality ##
66# Flags # attributes represented by single bits ##
67# Font_Embedded_Bitmaps # custom sized bitmap Glyphs ##
68# Font_Metrics # common glyph dimensions ##
69# Full_Hinting_Spacing # glyph spacing affected by hinting ##
70# Hinting # glyph outline adjustment ##
71# Image_Filter_Methods # get and set Image_Filter ##
72# Initializers # constructors and initialization ##
73# Management # paint copying, moving, comparing ##
74# Mask_Filter_Methods # get and set Mask_Filter ##
75# Measure_Text # width, height, bounds of text ##
76# Miter_Limit # maximum length of stroked corners ##
77# Path_Effect_Methods # get and set Path_Effect ##
78# Shader_Methods # get and set Shader ##
79# Stroke_Cap # decorations at ends of open strokes ##
80# Stroke_Join # decoration at corners of strokes ##
81# Stroke_Width # thickness perpendicular to geometry ##
82# Style # geometry filling, stroking ##
83# Text_Align # text placement relative to position ##
84# Text_Encoding # text encoded as characters or Glyphs ##
85# Text_Intercepts # advanced underline, strike through ##
86# Text_Path # geometry of Glyphs ##
87# Text_Scale_X # text horizontal scale ##
88# Text_Size # overall height in points ##
89# Text_Skew_X # text horizontal slant ##
90# Typeface_Methods # get and set Typeface ##
91# Vertical_Text # orient text from top to bottom ##
Cary Clark8032b982017-07-28 11:04:54 -040092#Table ##
93#Subtopic ##
94
95#Subtopic Constants
96#Table
97#Legend
Cary Clark5081eed2018-01-22 07:55:48 -050098# name # description ##
Cary Clark8032b982017-07-28 11:04:54 -040099#Legend ##
Cary Clark5081eed2018-01-22 07:55:48 -0500100# Align # glyph locations relative to text position ##
101# Cap # start and end geometry on stroked shapes ##
102# Flags # values described by bits and masks ##
103# FontMetrics::FontMetricsFlags # valid Font_Metrics ##
104# Hinting # level of glyph outline adjustment ##
105# Join # corner geometry on stroked shapes ##
106# Style # stroke, fill, or both ##
107# TextEncoding # character or glyph encoded size ##
Cary Clark8032b982017-07-28 11:04:54 -0400108#Table ##
109#Subtopic ##
110
Cary Clark5081eed2018-01-22 07:55:48 -0500111#Subtopic Classes_and_Structs
Cary Clark8032b982017-07-28 11:04:54 -0400112#Table
113#Legend
Cary Clark5081eed2018-01-22 07:55:48 -0500114# name # description ##
Cary Clark8032b982017-07-28 11:04:54 -0400115#Legend ##
Cary Clark5081eed2018-01-22 07:55:48 -0500116# FontMetrics # typeface values ##
Cary Clark8032b982017-07-28 11:04:54 -0400117#Table ##
118#Subtopic ##
119
120#Subtopic Constructors
121#Table
122#Legend
Cary Clark5081eed2018-01-22 07:55:48 -0500123# name # description ##
Cary Clark8032b982017-07-28 11:04:54 -0400124#Legend ##
Cary Clark5081eed2018-01-22 07:55:48 -0500125# SkPaint() # constructs with default values ##
126# SkPaint(SkPaint&& paint) # moves paint without copying it ##
127# SkPaint(const SkPaint& paint) # makes a shallow copy ##
128# ~SkPaint() # decreases Reference_Count of owned objects ##
Cary Clark8032b982017-07-28 11:04:54 -0400129#Table ##
130#Subtopic ##
131
132#Subtopic Operators
133#Table
134#Legend
Cary Clark5081eed2018-01-22 07:55:48 -0500135# name # description ##
Cary Clark8032b982017-07-28 11:04:54 -0400136#Legend ##
Cary Clark5081eed2018-01-22 07:55:48 -0500137# operator!=(const SkPaint& a, const SkPaint& b) # compares paints for inequality ##
138# operator=(SkPaint&& paint) # moves paint without copying it ##
139# operator=(const SkPaint& paint) # makes a shallow copy ##
140# operator==(const SkPaint& a, const SkPaint& b) # compares paints for equality ##
Cary Clark8032b982017-07-28 11:04:54 -0400141#Table ##
142#Subtopic ##
143
144#Subtopic Member_Functions
145#Table
146#Legend
Cary Clark5081eed2018-01-22 07:55:48 -0500147# name # description ##
Cary Clark8032b982017-07-28 11:04:54 -0400148#Legend ##
Cary Clark5081eed2018-01-22 07:55:48 -0500149# breakText # returns text that fits in a width ##
150# canComputeFastBounds # returns true if settings allow for fast bounds computation ##
151# computeFastBounds # returns fill bounds for quick reject tests ##
152# computeFastStrokeBounds # returns stroke bounds for quick reject tests ##
153# containsText # returns if all text corresponds to Glyphs ##
154# countText # returns number of Glyphs in text ##
155# doComputeFastBounds # returns bounds for quick reject tests ##
156# flatten() # serializes into a buffer ##
157# getAlpha # returns Color_Alpha, color opacity ##
158# getBlendMode # returns Blend_Mode, how colors combine with Device ##
159# getColor # returns Color_Alpha and Color_RGB, one drawing color ##
160# getColorFilter # returns Color_Filter, how colors are altered ##
161# getDrawLooper # returns Draw_Looper, multiple layers ##
162# getFillPath # returns fill path equivalent to stroke ##
163# getFilterQuality # returns Filter_Quality, image filtering level ##
164# getFlags # returns Flags stored in a bit field ##
165# getFontBounds # returns union all glyph bounds ##
166# getFontMetrics # returns Typeface metrics scaled by text size ##
167# getFontSpacing # returns recommended spacing between lines ##
168# getHash # returns a shallow hash for equality checks ##
169# getHinting # returns Hinting, glyph outline adjustment level ##
170# getImageFilter # returns Image_Filter, alter pixels; blur ##
171# getMaskFilter # returns Mask_Filter, alterations to Mask_Alpha ##
172# getPathEffect # returns Path_Effect, modifications to path geometry; dashing ##
173# getPosTextHIntercepts # returns where lines intersect horizontally positioned text; underlines ##
174# getPosTextIntercepts # returns where lines intersect positioned text; underlines ##
175# getPosTextPath # returns Path equivalent to positioned text ##
176# getShader # returns Shader, multiple drawing colors; gradients ##
177# getStrokeCap # returns Cap, the area drawn at path ends ##
178# getStrokeJoin # returns Join, geometry on path corners ##
179# getStrokeMiter # returns Miter_Limit, angles with sharp corners ##
180# getStrokeWidth # returns thickness of the stroke ##
181# getStyle # returns Style: stroke, fill, or both ##
182# getTextAlign # returns Align: left, center, or right ##
183# getTextBlobIntercepts # returns where lines intersect Text_Blob; underlines ##
184# getTextEncoding # returns character or glyph encoded size ##
185# getTextIntercepts # returns where lines intersect text; underlines ##
186# getTextPath # returns Path equivalent to text ##
187# getTextScaleX # returns the text horizontal scale; condensed text ##
188# getTextSize # returns text size in points ##
189# getTextSkewX # returns the text horizontal skew; oblique text ##
190# getTextWidths # returns advance and bounds for each glyph in text ##
191# getTypeface # returns Typeface, font description ##
192# glyphsToUnichars # converts Glyphs into text ##
193# isAntiAlias # returns true if Anti-alias is set ##
194# isAutohinted # returns true if Glyphs are always hinted ##
195# isDevKernText # returns true if Full_Hinting_Spacing is set ##
196# isDither # returns true if Dither is set ##
197# isEmbeddedBitmapText # returns true if Font_Embedded_Bitmaps is set ##
198# isFakeBoldText # returns true if Fake_Bold is set ##
199# isLCDRenderText # returns true if LCD_Text is set ##
200# isSrcOver # returns true if Blend_Mode is SkBlendMode::kSrcOver ##
201# isSubpixelText # returns true if Subpixel_Text is set ##
202# isVerticalText # returns true if Vertical_Text is set ##
203# measureText # returns advance width and bounds of text ##
204# nothingToDraw # returns true if Paint prevents all drawing ##
205# refColorFilter # references Color_Filter, how colors are altered ##
206# refDrawLooper # references Draw_Looper, multiple layers ##
207# refImageFilter # references Image_Filter, alter pixels; blur ##
208# refMaskFilter # references Mask_Filter, alterations to Mask_Alpha ##
209# refPathEffect # references Path_Effect, modifications to path geometry; dashing ##
210# refShader # references Shader, multiple drawing colors; gradients ##
211# refTypeface # references Typeface, font description ##
212# reset() # sets to default values ##
213# setARGB # sets color by component ##
214# setAlpha # sets Color_Alpha, color opacity ##
215# setAntiAlias # sets or clears Anti-alias ##
216# setAutohinted # sets Glyphs to always be hinted ##
217# setBlendMode # sets Blend_Mode, how colors combine with destination ##
218# setColor # sets Color_Alpha and Color_RGB, one drawing color ##
219# setColorFilter # sets Color_Filter, alters color ##
220# setDevKernText # sets or clears Full_Hinting_Spacing ##
221# setDither # sets or clears Dither ##
222# setDrawLooper # sets Draw_Looper, multiple layers ##
223# setEmbeddedBitmapText # sets or clears Font_Embedded_Bitmaps ##
224# setFakeBoldText # sets or clears Fake_Bold ##
225# setFilterQuality # sets Filter_Quality, the image filtering level ##
226# setFlags # sets multiple Flags in a bit field ##
227# setHinting # sets Hinting, glyph outline adjustment level ##
228# setImageFilter # sets Image_Filter, alter pixels; blur ##
229# setLCDRenderText # sets or clears LCD_Text ##
230# setMaskFilter # sets Mask_Filter, alterations to Mask_Alpha ##
231# setPathEffect # sets Path_Effect, modifications to path geometry; dashing ##
232# setShader # sets Shader, multiple drawing colors; gradients ##
233# setStrokeCap # sets Cap, the area drawn at path ends ##
234# setStrokeJoin # sets Join, geometry on path corners ##
235# setStrokeMiter # sets Miter_Limit, angles with sharp corners ##
236# setStrokeWidth # sets thickness of the stroke ##
237# setStyle # sets Style: stroke, fill, or both ##
238# setSubpixelText # sets or clears Subpixel_Text ##
239# setTextAlign # sets Align: left, center, or right ##
240# setTextEncoding # sets character or glyph encoded size ##
241# setTextScaleX # sets the text horizontal scale; condensed text ##
242# setTextSize # sets text size in points ##
243# setTextSkewX # sets the text horizontal skew; oblique text ##
244# setTypeface # sets Typeface, font description ##
245# setVerticalText # sets or clears Vertical_Text ##
246# textToGlyphs # converts text into glyph indices ##
247# toString # converts Paint to machine readable form ##
248# unflatten() # populates from a serialized stream ##
Cary Clark8032b982017-07-28 11:04:54 -0400249#Table ##
250#Subtopic ##
251
252#Topic Overview ##
253
254# ------------------------------------------------------------------------------
255#Topic Initializers
256
257#Method SkPaint()
258
259Constructs Paint with default values.
260
261#Table
262#Legend
263# attribute # default value ##
264#Legend ##
265# Anti-alias # false ##
Cary Clarkce101242017-09-01 15:51:02 -0400266# Blend_Mode # SkBlendMode::kSrcOver ##
Cary Clark8032b982017-07-28 11:04:54 -0400267# Color # SK_ColorBLACK ##
268# Color_Alpha # 255 ##
269# Color_Filter # nullptr ##
270# Dither # false ##
271# Draw_Looper # nullptr ##
272# Fake_Bold # false ##
273# Filter_Quality # kNone_SkFilterQuality ##
274# Font_Embedded_Bitmaps # false ##
275# Automatic_Hinting # false ##
276# Full_Hinting_Spacing # false ##
277# Hinting # kNormal_Hinting ##
278# Image_Filter # nullptr ##
279# LCD_Text # false ##
280# Linear_Text # false ##
281# Miter_Limit # 4 ##
282# Mask_Filter # nullptr ##
283# Path_Effect # nullptr ##
Cary Clark8032b982017-07-28 11:04:54 -0400284# Shader # nullptr ##
285# Style # kFill_Style ##
286# Text_Align # kLeft_Align ##
287# Text_Encoding # kUTF8_TextEncoding ##
288# Text_Scale_X # 1 ##
289# Text_Size # 12 ##
290# Text_Skew_X # 0 ##
291# Typeface # nullptr ##
292# Stroke_Cap # kButt_Cap ##
293# Stroke_Join # kMiter_Join ##
294# Stroke_Width # 0 ##
295# Subpixel_Text # false ##
296# Vertical_Text # false ##
297#Table ##
298
299The flags, text size, hinting, and miter limit may be overridden at compile time by defining
Cary Clarkce101242017-09-01 15:51:02 -0400300paint default values. The overrides may be included in "SkUserConfig.h" or predefined by the
Cary Clark8032b982017-07-28 11:04:54 -0400301build system.
302
303#Return default initialized Paint ##
304
305#Example
306#ToDo mark this as no output ##
307#Height 1
308###$ $ redefine markup character so preprocessor commands appear normally
309#ifndef SkUserConfig_DEFINED
310#define SkUserConfig_DEFINED
311
312#define SkPaintDefaults_Flags 0x01 // always enable antialiasing
313#define SkPaintDefaults_TextSize 24.f // double default font size
314#define SkPaintDefaults_Hinting 3 // use full hinting
315#define SkPaintDefaults_MiterLimit 10.f // use HTML Canvas miter limit setting
316
317#endif
318$$$# # restore original markup character
319##
320
321
322##
323
324#Method SkPaint(const SkPaint& paint)
325
326Makes a shallow copy of Paint. Typeface, Path_Effect, Shader,
Mike Reed8ad91a92018-01-19 19:09:32 -0500327Mask_Filter, Color_Filter, Draw_Looper, and Image_Filter are shared
Cary Clarkbad5ad72017-08-03 17:14:08 -0400328between the original paint and the copy. Objects containing Reference_Count increment
329their references by one.
Cary Clark8032b982017-07-28 11:04:54 -0400330
Mike Reed8ad91a92018-01-19 19:09:32 -0500331The referenced objects Path_Effect, Shader, Mask_Filter, Color_Filter,
Cary Clark8032b982017-07-28 11:04:54 -0400332Draw_Looper, and Image_Filter cannot be modified after they are created.
333This prevents objects with Reference_Count from being modified once Paint refers to them.
334
335#Param paint original to copy ##
336
337#Return shallow copy of paint ##
338
339#Example
340#ToDo why is this double-spaced on Fiddle? ##
341 SkPaint paint1;
342 paint1.setColor(SK_ColorRED);
343 SkPaint paint2(paint1);
344 paint2.setColor(SK_ColorBLUE);
345 SkDebugf("SK_ColorRED %c= paint1.getColor()\n", SK_ColorRED == paint1.getColor() ? '=' : '!');
346 SkDebugf("SK_ColorBLUE %c= paint2.getColor()\n", SK_ColorBLUE == paint2.getColor() ? '=' : '!');
347
348 #StdOut
349 SK_ColorRED == paint1.getColor()
350 SK_ColorBLUE == paint2.getColor()
351 ##
352##
353
354##
355
356#Method SkPaint(SkPaint&& paint)
357
Cary Clarkd0530ba2017-09-14 11:25:39 -0400358 Implements a move constructor to avoid increasing the reference counts
Cary Clark8032b982017-07-28 11:04:54 -0400359 of objects referenced by the paint.
360
361 After the call, paint is undefined, and can be safely destructed.
362
363 #Param paint original to move ##
364
365 #Return content of paint ##
366
367 #Example
368 SkPaint paint;
369 float intervals[] = { 5, 5 };
370 paint.setPathEffect(SkDashPathEffect::Make(intervals, SK_ARRAY_COUNT(intervals), 2.5f));
371 SkPaint dashed(std::move(paint));
372 SkDebugf("path effect unique: %s\n", dashed.getPathEffect()->unique() ? "true" : "false");
373
374 #StdOut
375 path effect unique: true
376 ##
377 ##
378
379##
380
381# ------------------------------------------------------------------------------
382
383#Method void reset()
384
Cary Clarkbc5697d2017-10-04 14:31:33 -0400385Sets all Paint contents to their initial values. This is equivalent to replacing
386Paint with the result of SkPaint().
Cary Clark8032b982017-07-28 11:04:54 -0400387
388#Example
389 SkPaint paint1, paint2;
390 paint1.setColor(SK_ColorRED);
391 paint1.reset();
392 SkDebugf("paint1 %c= paint2", paint1 == paint2 ? '=' : '!');
393
394 #StdOut
395 paint1 == paint2
396 ##
397##
398
399##
400
401#Topic ##
402
403# ------------------------------------------------------------------------------
404#Topic Destructor
405
406#Method ~SkPaint()
407
408Decreases Paint Reference_Count of owned objects: Typeface, Path_Effect, Shader,
Mike Reed8ad91a92018-01-19 19:09:32 -0500409Mask_Filter, Color_Filter, Draw_Looper, and Image_Filter. If the
Cary Clarkbad5ad72017-08-03 17:14:08 -0400410objects containing Reference_Count go to zero, they are deleted.
Cary Clark8032b982017-07-28 11:04:54 -0400411
412#NoExample
413##
414
415##
416
417##
418# ------------------------------------------------------------------------------
419#Topic Management
420
421#Method SkPaint& operator=(const SkPaint& paint)
422
423Makes a shallow copy of Paint. Typeface, Path_Effect, Shader,
Mike Reed8ad91a92018-01-19 19:09:32 -0500424Mask_Filter, Color_Filter, Draw_Looper, and Image_Filter are shared
Cary Clarkbad5ad72017-08-03 17:14:08 -0400425between the original paint and the copy. Objects containing Reference_Count in the
Cary Clark8032b982017-07-28 11:04:54 -0400426prior destination are decreased by one, and the referenced objects are deleted if the
Cary Clarkbad5ad72017-08-03 17:14:08 -0400427resulting count is zero. Objects containing Reference_Count in the parameter paint
428are increased by one. paint is unmodified.
Cary Clark8032b982017-07-28 11:04:54 -0400429
430#Param paint original to copy ##
431
432#Return content of paint ##
433
434#Example
435 SkPaint paint1, paint2;
436 paint1.setColor(SK_ColorRED);
437 paint2 = paint1;
438 SkDebugf("SK_ColorRED %c= paint1.getColor()\n", SK_ColorRED == paint1.getColor() ? '=' : '!');
439 SkDebugf("SK_ColorRED %c= paint2.getColor()\n", SK_ColorRED == paint2.getColor() ? '=' : '!');
440
441 #StdOut
442 SK_ColorRED == paint1.getColor()
443 SK_ColorRED == paint2.getColor()
444 ##
445##
446
447##
448
449# ------------------------------------------------------------------------------
450
451#Method SkPaint& operator=(SkPaint&& paint)
452
Cary Clarkd0530ba2017-09-14 11:25:39 -0400453Moves the paint to avoid increasing the reference counts
Cary Clarkbad5ad72017-08-03 17:14:08 -0400454of objects referenced by the paint parameter. Objects containing Reference_Count in the
455prior destination are decreased by one; those objects are deleted if the resulting count
456is zero.
Cary Clark8032b982017-07-28 11:04:54 -0400457
458After the call, paint is undefined, and can be safely destructed.
459
460 #Param paint original to move ##
461
462 #Return content of paint ##
463
464#Example
465 SkPaint paint1, paint2;
466 paint1.setColor(SK_ColorRED);
467 paint2 = std::move(paint1);
468 SkDebugf("SK_ColorRED == paint2.getColor()\n", SK_ColorRED == paint2.getColor() ? '=' : '!');
469
470 #StdOut
471 SK_ColorRED == paint2.getColor()
472 ##
473##
474
475##
476
477# ------------------------------------------------------------------------------
478
479#Method bool operator==(const SkPaint& a, const SkPaint& b)
480
481 Compares a and b, and returns true if a and b are equivalent. May return false
Mike Reed8ad91a92018-01-19 19:09:32 -0500482 if Typeface, Path_Effect, Shader, Mask_Filter, Color_Filter,
Cary Clark8032b982017-07-28 11:04:54 -0400483 Draw_Looper, or Image_Filter have identical contents but different pointers.
484
485 #Param a Paint to compare ##
486 #Param b Paint to compare ##
487
488 #Return true if Paint pair are equivalent ##
489
490 #Example
491 SkPaint paint1, paint2;
492 paint1.setColor(SK_ColorRED);
493 paint2.setColor(0xFFFF0000);
494 SkDebugf("paint1 %c= paint2\n", paint1 == paint2 ? '=' : '!');
495 float intervals[] = { 5, 5 };
496 paint1.setPathEffect(SkDashPathEffect::Make(intervals, 2, 2.5f));
497 paint2.setPathEffect(SkDashPathEffect::Make(intervals, 2, 2.5f));
498 SkDebugf("paint1 %c= paint2\n", paint1 == paint2 ? '=' : '!');
499
500 #StdOut
501 paint1 == paint2
502 paint1 != paint2
503 ##
504 ##
505
506##
507
508# ------------------------------------------------------------------------------
509
510#Method bool operator!=(const SkPaint& a, const SkPaint& b)
511
512 Compares a and b, and returns true if a and b are not equivalent. May return true
Mike Reed8ad91a92018-01-19 19:09:32 -0500513 if Typeface, Path_Effect, Shader, Mask_Filter, Color_Filter,
Cary Clark8032b982017-07-28 11:04:54 -0400514 Draw_Looper, or Image_Filter have identical contents but different pointers.
515
516 #Param a Paint to compare ##
517 #Param b Paint to compare ##
518
519 #Return true if Paint pair are not equivalent ##
520
521#Example
522 SkPaint paint1, paint2;
523 paint1.setColor(SK_ColorRED);
524 paint2.setColor(0xFFFF0000);
525 SkDebugf("paint1 %c= paint2\n", paint1 == paint2 ? '=' : '!');
526 SkDebugf("paint1 %c= paint2\n", paint1 != paint2 ? '!' : '=');
527
528 #StdOut
529 paint1 == paint2
530 paint1 == paint2
531 ##
532##
533
534##
535
536# ------------------------------------------------------------------------------
537
538#Method uint32_t getHash() const
539
540Returns a hash generated from Paint values and pointers.
541Identical hashes guarantee that the paints are
542equivalent, but differing hashes do not guarantee that the paints have differing
543contents.
544
545If operator==(const SkPaint& a, const SkPaint& b) returns true for two paints,
546their hashes are also equal.
547
548The hash returned is platform and implementation specific.
549
550#Return a shallow hash ##
551
552#Example
553 SkPaint paint1, paint2;
554 paint1.setColor(SK_ColorRED);
555 paint2.setColor(0xFFFF0000);
556 SkDebugf("paint1 %c= paint2\n", paint1 == paint2 ? '=' : '!');
557 SkDebugf("paint1.getHash() %c= paint2.getHash()\n",
558 paint1.getHash() == paint2.getHash() ? '=' : '!');
559
560 #StdOut
561 paint1 == paint2
562 paint1.getHash() == paint2.getHash()
563 ##
564##
565
566##
567
568# ------------------------------------------------------------------------------
569
570#Method void flatten(SkWriteBuffer& buffer) const
571
572Serializes Paint into a buffer. A companion unflatten() call
573can reconstitute the paint at a later time.
574
575#Param buffer Write_Buffer receiving the flattened Paint data ##
576
Cary Clark61ca7c52018-01-02 11:34:14 -0500577# why is flatten() public?
578#Bug 6172 ##
Cary Clark8032b982017-07-28 11:04:54 -0400579
Cary Clark61ca7c52018-01-02 11:34:14 -0500580#NoExample
Cary Clark8032b982017-07-28 11:04:54 -0400581##
582
583##
584
585# ------------------------------------------------------------------------------
586
Mike Reede97e7922018-01-18 15:57:38 -0500587#Method bool unflatten(SkReadBuffer& buffer)
Cary Clark8032b982017-07-28 11:04:54 -0400588
589Populates Paint, typically from a serialized stream, created by calling
590flatten() at an earlier time.
591
592SkReadBuffer class is not public, so unflatten() cannot be meaningfully called
593by the client.
594
Cary Clarkce101242017-09-01 15:51:02 -0400595#Param buffer serialized data describing Paint content ##
Cary Clark8032b982017-07-28 11:04:54 -0400596
Cary Clark5081eed2018-01-22 07:55:48 -0500597#Return false if the buffer contains invalid data ##
Mike Reede97e7922018-01-18 15:57:38 -0500598
Cary Clark8032b982017-07-28 11:04:54 -0400599# why is unflatten() public?
600#Bug 6172 ##
601
602#NoExample
603##
604
Cary Clark2ade9972017-11-02 17:49:34 -0400605#SeeAlso SkReadBuffer
Cary Clark8032b982017-07-28 11:04:54 -0400606
607##
608
609#Topic Management ##
610
611# ------------------------------------------------------------------------------
612#Topic Hinting
613
614#Enum Hinting
615
616#Code
617 enum Hinting {
618 kNo_Hinting = 0,
619 kSlight_Hinting = 1,
620 kNormal_Hinting = 2,
Cary Clarkbad5ad72017-08-03 17:14:08 -0400621 kFull_Hinting = 3,
Cary Clark8032b982017-07-28 11:04:54 -0400622 };
623##
624
625Hinting adjusts the glyph outlines so that the shape provides a uniform
626look at a given point size on font engines that support it. Hinting may have a
627muted effect or no effect at all depending on the platform.
628
629The four levels roughly control corresponding features on platforms that use FreeType
630as the Font_Engine.
631
632#Const kNo_Hinting 0
633 Leaves glyph outlines unchanged from their native representation.
634 With FreeType, this is equivalent to the FT_LOAD_NO_HINTING
635 bit-field constant supplied to FT_Load_Glyph, which indicates that the vector
636 outline being loaded should not be fitted to the pixel grid but simply scaled
637 to 26.6 fractional pixels.
638##
639#Const kSlight_Hinting 1
640 Modifies glyph outlines minimally to improve constrast.
641 With FreeType, this is equivalent in spirit to the
642 FT_LOAD_TARGET_LIGHT value supplied to FT_Load_Glyph. It chooses a
643 lighter hinting algorithm for non-monochrome modes.
Cary Clarkce101242017-09-01 15:51:02 -0400644 Generated Glyphs may be fuzzy but better resemble their original shape.
Cary Clark8032b982017-07-28 11:04:54 -0400645##
646#Const kNormal_Hinting 2
647 Modifies glyph outlines to improve constrast. This is the default.
Cary Clark6fc50412017-09-21 12:31:06 -0400648 With FreeType, this supplies FT_LOAD_TARGET_NORMAL to FT_Load_Glyph,
Cary Clark8032b982017-07-28 11:04:54 -0400649 choosing the default hinting algorithm, which is optimized for standard
650 gray-level rendering.
651##
652#Const kFull_Hinting 3
Cary Clark6fc50412017-09-21 12:31:06 -0400653 Modifies glyph outlines for maxiumum constrast. With FreeType, this selects
654 FT_LOAD_TARGET_LCD or FT_LOAD_TARGET_LCD_V if kLCDRenderText_Flag is set.
655 FT_LOAD_TARGET_LCD is a variant of FT_LOAD_TARGET_NORMAL optimized for
656 horizontally decimated LCD displays; FT_LOAD_TARGET_LCD_V is a
Cary Clark8032b982017-07-28 11:04:54 -0400657 variant of FT_LOAD_TARGET_NORMAL optimized for vertically decimated LCD displays.
658##
659
660#Track
661#File SkFontHost_mac.cpp:1777,1806
662#Time 2013-03-03 07:16:29 +0000
663#Bug 915 ##
664On OS_X and iOS, hinting controls whether Core_Graphics dilates the font outlines
665to account for LCD text. No hinting uses Core_Text gray scale output.
666Normal hinting uses Core_Text LCD output. If kLCDRenderText_Flag is clear,
667the LCD output is reduced to a single grayscale channel.
668#Track ##
669
670On Windows with DirectWrite, Hinting has no effect.
671
672Hinting defaults to kNormal_Hinting.
673Set SkPaintDefaults_Hinting at compile time to change the default setting.
674
675#ToDo add an illustration? linux running GM:typefacerendering is best for this
676 the hinting variations are every other character horizontally
677#ToDo ##
678
679#Enum ##
680
681#Method Hinting getHinting() const
682
683 Returns level of glyph outline adjustment.
684
685 #Return one of: kNo_Hinting, kSlight_Hinting, kNormal_Hinting, kFull_Hinting ##
686
687 #Example
688 SkPaint paint;
689 SkDebugf("SkPaint::kNormal_Hinting %c= paint.getHinting()\n",
690 SkPaint::kNormal_Hinting == paint.getHinting() ? '=' : ':');
691
692 #StdOut
693 SkPaint::kNormal_Hinting == paint.getHinting()
694 ##
695 ##
696##
697
698#Method void setHinting(Hinting hintingLevel)
699
700 Sets level of glyph outline adjustment.
701 Does not check for valid values of hintingLevel.
702
703 #Table
704 #Legend
705 # Hinting # value # effect on generated glyph outlines ##
706 ##
707 # kNo_Hinting # 0 # leaves glyph outlines unchanged from their native representation ##
Cary Clarkce101242017-09-01 15:51:02 -0400708 # kSlight_Hinting # 1 # modifies glyph outlines minimally to improve contrast ##
709 # kNormal_Hinting # 2 # modifies glyph outlines to improve contrast ##
710 # kFull_Hinting # 3 # modifies glyph outlines for maximum contrast ##
Cary Clark8032b982017-07-28 11:04:54 -0400711 ##
712
713 #Param hintingLevel one of: kNo_Hinting, kSlight_Hinting, kNormal_Hinting, kFull_Hinting ##
714
715 #Example
716 SkPaint paint1, paint2;
717 paint2.setHinting(SkPaint::kNormal_Hinting);
718 SkDebugf("paint1 %c= paint2\n", paint1 == paint2 ? '=' : ':');
719
720 #StdOut
721 paint1 == paint2
722 ##
723 ##
724##
725
726#Topic ##
727# ------------------------------------------------------------------------------
728#Topic Flags
729
730#Enum Flags
731
732#Code
733 enum Flags {
734 kAntiAlias_Flag = 0x01,
735 kDither_Flag = 0x04,
736 kFakeBoldText_Flag = 0x20,
737 kLinearText_Flag = 0x40,
738 kSubpixelText_Flag = 0x80,
739 kDevKernText_Flag = 0x100,
740 kLCDRenderText_Flag = 0x200,
741 kEmbeddedBitmapText_Flag = 0x400,
742 kAutoHinting_Flag = 0x800,
743 kVerticalText_Flag = 0x1000,
744 kGenA8FromLCD_Flag = 0x2000,
745
746 kAllFlags = 0xFFFF,
747 };
748
749##
750
751The bit values stored in Flags.
752The default value for Flags, normally zero, can be changed at compile time
753with a custom definition of SkPaintDefaults_Flags.
754All flags can be read and written explicitly; Flags allows manipulating
755multiple settings at once.
756
757 #Const kAntiAlias_Flag 0x0001
758 mask for setting Anti-alias
759 ##
760 #Const kDither_Flag 0x0004
761 mask for setting Dither
762 ##
763
764 #Const kFakeBoldText_Flag 0x0020
765 mask for setting Fake_Bold
766 ##
767 #Const kLinearText_Flag 0x0040
768 mask for setting Linear_Text
769 ##
770 #Const kSubpixelText_Flag 0x0080
771 mask for setting Subpixel_Text
772 ##
773 #Const kDevKernText_Flag 0x0100
774 mask for setting Full_Hinting_Spacing
775 ##
776 #Const kLCDRenderText_Flag 0x0200
777 mask for setting LCD_Text
778 ##
779 #Const kEmbeddedBitmapText_Flag 0x0400
780 mask for setting Font_Embedded_Bitmaps
781 ##
782 #Const kAutoHinting_Flag 0x0800
783 mask for setting Automatic_Hinting
784 ##
785 #Const kVerticalText_Flag 0x1000
786 mask for setting Vertical_Text
787 ##
788 #Const kGenA8FromLCD_Flag 0x2000
789 #Private
790 Hack for GDI -- do not use if you can help it
791 ##
792 not intended for public use
793 ##
794 #Const kAllFlags 0xFFFF
795 mask of all Flags, including private flags and flags reserved for future use
796 ##
797
798Flags default to all flags clear, disabling the associated feature.
799
800#Enum ##
801
802#Enum ReserveFlags
803
804#Private
805To be deprecated; only valid for Android framework.
806##
807
808#Code
809 enum ReserveFlags {
810 kUnderlineText_ReserveFlag = 0x08,
811 kStrikeThruText_ReserveFlag = 0x10,
812 };
813##
814
815 #Const kUnderlineText_ReserveFlag 0x0008
816 mask for underline text
817 ##
818 #Const kStrikeThruText_ReserveFlag 0x0010
819 mask for strike-thru text
820 ##
821
Cary Clark2ade9972017-11-02 17:49:34 -0400822#SeeAlso Flags getFlags
Cary Clark8032b982017-07-28 11:04:54 -0400823
824#Enum ##
825
826#Method uint32_t getFlags() const
827
828Returns paint settings described by Flags. Each setting uses one
829bit, and can be tested with Flags members.
830
831#Return zero, one, or more bits described by Flags ##
832
833#Example
834 SkPaint paint;
835 paint.setAntiAlias(true);
836 SkDebugf("(SkPaint::kAntiAlias_Flag & paint.getFlags()) %c= 0\n",
837 SkPaint::kAntiAlias_Flag & paint.getFlags() ? '!' : '=');
838
839 #StdOut
840 (SkPaint::kAntiAlias_Flag & paint.getFlags()) != 0
841 ##
842##
843
844##
845
846#Method void setFlags(uint32_t flags)
847
848Replaces Flags with flags, the union of the Flags members.
849All Flags members may be cleared, or one or more may be set.
850
851#Param flags union of Flags for Paint ##
852
853#Example
854 SkPaint paint;
855 paint.setFlags((uint32_t) (SkPaint::kAntiAlias_Flag | SkPaint::kDither_Flag));
856 SkDebugf("paint.isAntiAlias()\n", paint.isAntiAlias() ? '!' : '=');
857 SkDebugf("paint.isDither()\n", paint.isDither() ? '!' : '=');
858
859 #StdOut
860 paint.isAntiAlias()
861 paint.isDither()
862 ##
863##
864
865##
866
867#Topic ##
868# ------------------------------------------------------------------------------
869#Topic Anti-alias
870#Alias Anti-alias # permit hyphen in topic name, should probably not substitute hyphen with _
871
872Anti-alias drawing approximates partial pixel coverage with transparency.
873If kAntiAlias_Flag is clear, pixel centers contained by the shape edge are drawn opaque.
874If kAntiAlias_Flag is set, pixels are drawn with Color_Alpha equal to their coverage.
875
Cary Clarkce101242017-09-01 15:51:02 -0400876The rule for Aliased pixels is inconsistent across platforms. A shape edge
Cary Clark8032b982017-07-28 11:04:54 -0400877passing through the pixel center may, but is not required to, draw the pixel.
878
Cary Clarkce101242017-09-01 15:51:02 -0400879Raster_Engine draws Aliased pixels whose centers are on or to the right of the start of an
Cary Clark8032b982017-07-28 11:04:54 -0400880active Path edge, and whose center is to the left of the end of the active Path edge.
881
882#ToDo add illustration of raster pixels ##
883
Cary Clarkce101242017-09-01 15:51:02 -0400884A platform may only support Anti-aliased drawing. Some GPU-backed platforms use
885Supersampling to Anti-alias all drawing, and have no mechanism to selectively
886Alias.
Cary Clark8032b982017-07-28 11:04:54 -0400887
Cary Clarkce101242017-09-01 15:51:02 -0400888The amount of coverage computed for Anti-aliased pixels also varies across platforms.
Cary Clark8032b982017-07-28 11:04:54 -0400889
890Anti-alias is disabled by default.
891Anti-alias can be enabled by default by setting SkPaintDefaults_Flags to kAntiAlias_Flag
892at compile time.
893
894 #Example
895 #Width 512
896 #Description
897 A red line is drawn with transparency on the edges to make it look smoother.
898 A blue line draws only where the pixel centers are contained.
Cary Clarkce101242017-09-01 15:51:02 -0400899 The lines are drawn into Bitmap, then drawn magnified to make the
900 Aliasing easier to see.
Cary Clark8032b982017-07-28 11:04:54 -0400901 ##
902
903 void draw(SkCanvas* canvas) {
904 SkBitmap bitmap;
905 bitmap.allocN32Pixels(50, 50);
906 SkCanvas offscreen(bitmap);
907 SkPaint paint;
908 paint.setStyle(SkPaint::kStroke_Style);
909 paint.setStrokeWidth(10);
910 for (bool antialias : { false, true }) {
911 paint.setColor(antialias ? SK_ColorRED : SK_ColorBLUE);
912 paint.setAntiAlias(antialias);
913 bitmap.eraseColor(0);
914 offscreen.drawLine(5, 5, 15, 30, paint);
915 canvas->drawLine(5, 5, 15, 30, paint);
916 canvas->save();
917 canvas->scale(10, 10);
918 canvas->drawBitmap(bitmap, antialias ? 12 : 0, 0);
919 canvas->restore();
920 canvas->translate(15, 0);
921 }
922 }
923 ##
924
925#Method bool isAntiAlias() const
926
927 If true, pixels on the active edges of Path may be drawn with partial transparency.
928
929 Equivalent to getFlags masked with kAntiAlias_Flag.
930
931 #Return kAntiAlias_Flag state ##
932
933 #Example
934 SkPaint paint;
935 SkDebugf("paint.isAntiAlias() %c= !!(paint.getFlags() & SkPaint::kAntiAlias_Flag)\n",
936 paint.isAntiAlias() == !!(paint.getFlags() & SkPaint::kAntiAlias_Flag) ? '=' : '!');
937 paint.setAntiAlias(true);
938 SkDebugf("paint.isAntiAlias() %c= !!(paint.getFlags() & SkPaint::kAntiAlias_Flag)\n",
939 paint.isAntiAlias() == !!(paint.getFlags() & SkPaint::kAntiAlias_Flag) ? '=' : '!');
940
941 #StdOut
942 paint.isAntiAlias() == !!(paint.getFlags() & SkPaint::kAntiAlias_Flag)
943 paint.isAntiAlias() == !!(paint.getFlags() & SkPaint::kAntiAlias_Flag)
944 ##
945 ##
946##
947
948#Method void setAntiAlias(bool aa)
949
950 Requests, but does not require, that Path edge pixels draw opaque or with
951 partial transparency.
952
953 Sets kAntiAlias_Flag if aa is true.
954 Clears kAntiAlias_Flag if aa is false.
955
956 #Param aa setting for kAntiAlias_Flag ##
957
958 #Example
959 SkPaint paint1, paint2;
960 paint1.setAntiAlias(true);
961 paint2.setFlags(paint2.getFlags() | SkPaint::kAntiAlias_Flag);
962 SkDebugf("paint1 %c= paint2\n", paint1 == paint2 ? '=' : '!');
963
964 #StdOut
965 paint1 == paint2
966 ##
967 ##
968
969##
970
971#Topic ##
972# ------------------------------------------------------------------------------
973#Topic Dither
974
Cary Clarkce101242017-09-01 15:51:02 -0400975Dither increases fidelity by adjusting the color of adjacent pixels.
Cary Clark8032b982017-07-28 11:04:54 -0400976This can help to smooth color transitions and reducing banding in gradients.
977Dithering lessens visible banding from kRGB_565_SkColorType
978and kRGBA_8888_SkColorType gradients,
979and improves rendering into a kRGB_565_SkColorType Surface.
980
981Dithering is always enabled for linear gradients drawing into
982kRGB_565_SkColorType Surface and kRGBA_8888_SkColorType Surface.
983Dither cannot be enabled for kAlpha_8_SkColorType Surface and
984kRGBA_F16_SkColorType Surface.
985
986Dither is disabled by default.
987Dither can be enabled by default by setting SkPaintDefaults_Flags to kDither_Flag
988at compile time.
989
990Some platform implementations may ignore dithering. Set
991
992#Define SK_IGNORE_GPU_DITHER
993
994to ignore Dither on GPU_Surface.
995
996#Example
997#Description
998Dithering in the bottom half more closely approximates the requested color by
999alternating nearby colors from pixel to pixel.
1000##
1001void draw(SkCanvas* canvas) {
1002 SkBitmap bm16;
1003 bm16.allocPixels(SkImageInfo::Make(32, 32, kRGB_565_SkColorType, kOpaque_SkAlphaType));
1004 SkCanvas c16(bm16);
1005 SkPaint colorPaint;
1006 for (auto dither : { false, true } ) {
1007 colorPaint.setDither(dither);
1008 for (auto colors : { 0xFF333333, 0xFF666666, 0xFF999999, 0xFFCCCCCC } ) {
1009 for (auto mask : { 0xFFFF0000, 0xFF00FF00, 0xFF0000FF, 0xFFFFFFFF } ) {
1010 colorPaint.setColor(colors & mask);
1011 c16.drawRect({0, 0, 8, 4}, colorPaint);
1012 c16.translate(8, 0);
1013 }
1014 c16.translate(-32, 4);
1015 }
1016 }
1017 canvas->scale(8, 8);
1018 canvas->drawBitmap(bm16, 0, 0);
1019}
1020##
1021
1022#Example
1023#Description
1024Dithering introduces subtle adjustments to color to smooth gradients.
1025Drawing the gradient repeatedly with SkBlendMode::kPlus exaggerates the
1026dither, making it easier to see.
1027##
1028void draw(SkCanvas* canvas) {
1029 canvas->clear(0);
1030 SkBitmap bm32;
1031 bm32.allocPixels(SkImageInfo::Make(20, 10, kN32_SkColorType, kPremul_SkAlphaType));
1032 SkCanvas c32(bm32);
1033 SkPoint points[] = {{0, 0}, {20, 0}};
1034 SkColor colors[] = {0xFF334455, 0xFF662211 };
1035 SkPaint paint;
1036 paint.setShader(SkGradientShader::MakeLinear(
1037 points, colors, nullptr, SK_ARRAY_COUNT(colors),
1038 SkShader::kClamp_TileMode, 0, nullptr));
1039 paint.setDither(true);
1040 c32.drawPaint(paint);
1041 canvas->scale(12, 12);
1042 canvas->drawBitmap(bm32, 0, 0);
1043 paint.setBlendMode(SkBlendMode::kPlus);
1044 canvas->drawBitmap(bm32, 0, 11, &paint);
1045 canvas->drawBitmap(bm32, 0, 11, &paint);
1046 canvas->drawBitmap(bm32, 0, 11, &paint);
1047}
1048##
1049
1050#Method bool isDither() const
1051
1052 If true, color error may be distributed to smooth color transition.
1053
1054 Equivalent to getFlags masked with kDither_Flag.
1055
1056 #Return kDither_Flag state ##
1057
1058 #Example
1059 SkPaint paint;
1060 SkDebugf("paint.isDither() %c= !!(paint.getFlags() & SkPaint::kDither_Flag)\n",
1061 paint.isDither() == !!(paint.getFlags() & SkPaint::kDither_Flag) ? '=' : '!');
1062 paint.setDither(true);
1063 SkDebugf("paint.isDither() %c= !!(paint.getFlags() & SkPaint::kDither_Flag)\n",
1064 paint.isDither() == !!(paint.getFlags() & SkPaint::kDither_Flag) ? '=' : '!');
1065
1066 #StdOut
1067 paint.isDither() == !!(paint.getFlags() & SkPaint::kDither_Flag)
1068 paint.isDither() == !!(paint.getFlags() & SkPaint::kDither_Flag)
1069 ##
1070 ##
1071
1072##
1073
1074#Method void setDither(bool dither)
1075
1076 Requests, but does not require, to distribute color error.
1077
1078 Sets kDither_Flag if dither is true.
1079 Clears kDither_Flag if dither is false.
1080
1081 #Param dither setting for kDither_Flag ##
1082
1083 #Example
1084 SkPaint paint1, paint2;
1085 paint1.setDither(true);
1086 paint2.setFlags(paint2.getFlags() | SkPaint::kDither_Flag);
1087 SkDebugf("paint1 %c= paint2\n", paint1 == paint2 ? '=' : '!');
1088
1089 #StdOut
1090 paint1 == paint2
1091 ##
1092 ##
1093
1094 #SeeAlso kRGB_565_SkColorType
1095
1096##
1097
1098#SeeAlso Gradient Color_RGB-565
1099
1100#Topic ##
1101# ------------------------------------------------------------------------------
1102#Topic Device_Text
1103
1104LCD_Text and Subpixel_Text increase the precision of glyph position.
1105
1106When set, Flags kLCDRenderText_Flag takes advantage of the organization of Color_RGB stripes that
1107create a color, and relies
Cary Clarkce101242017-09-01 15:51:02 -04001108on the small size of the stripe and visual perception to make the color fringing imperceptible.
Cary Clark8032b982017-07-28 11:04:54 -04001109LCD_Text can be enabled on devices that orient stripes horizontally or vertically, and that order
1110the color components as Color_RGB or Color_RBG.
1111
1112Flags kSubpixelText_Flag uses the pixel transparency to represent a fractional offset.
1113As the opaqueness
1114of the color increases, the edge of the glyph appears to move towards the outside of the pixel.
1115
1116Either or both techniques can be enabled.
1117kLCDRenderText_Flag and kSubpixelText_Flag are clear by default.
1118LCD_Text or Subpixel_Text can be enabled by default by setting SkPaintDefaults_Flags to
1119kLCDRenderText_Flag or kSubpixelText_Flag (or both) at compile time.
1120
1121#Example
1122 #Description
1123 Four commas are drawn normally and with combinations of LCD_Text and Subpixel_Text.
Cary Clarkce101242017-09-01 15:51:02 -04001124 When Subpixel_Text is disabled, the comma Glyphs are identical, but not evenly spaced.
1125 When Subpixel_Text is enabled, the comma Glyphs are unique, but appear evenly spaced.
Cary Clark8032b982017-07-28 11:04:54 -04001126 ##
1127
1128 SkBitmap bitmap;
1129 bitmap.allocN32Pixels(24, 33);
1130 SkCanvas offscreen(bitmap);
1131 offscreen.clear(SK_ColorWHITE);
1132 SkPaint paint;
1133 paint.setAntiAlias(true);
1134 paint.setTextSize(20);
1135 for (bool lcd : { false, true }) {
1136 paint.setLCDRenderText(lcd);
1137 for (bool subpixel : { false, true }) {
1138 paint.setSubpixelText(subpixel);
1139 offscreen.drawString(",,,,", 0, 4, paint);
1140 offscreen.translate(0, 7);
1141 }
1142 }
1143 canvas->drawBitmap(bitmap, 4, 12);
1144 canvas->scale(9, 9);
1145 canvas->drawBitmap(bitmap, 4, -1);
1146##
1147
1148#Subtopic Linear_Text
1149#Alias Linear_Text # makes this a top level name, since it is under subtopic Device_Text
1150
1151Linear_Text selects whether text is rendered as a Glyph or as a Path.
1152If kLinearText_Flag is set, it has the same effect as setting Hinting to kNormal_Hinting.
Cary Clarkd0530ba2017-09-14 11:25:39 -04001153If kLinearText_Flag is clear, it is the same as setting Hinting to kNo_Hinting.
Cary Clark8032b982017-07-28 11:04:54 -04001154
1155#Method bool isLinearText() const
1156
1157 If true, text is converted to Path before drawing and measuring.
1158
1159 Equivalent to getFlags masked with kLinearText_Flag.
1160
1161 #Return kLinearText_Flag state ##
1162
1163 #Example
1164 #Height 128
1165 void draw(SkCanvas* canvas) {
1166 SkPaint paint;
1167 paint.setAntiAlias(true);
1168 const char testStr[] = "xxxx xxxx";
1169 for (auto linearText : { false, true } ) {
1170 paint.setLinearText(linearText);
1171 paint.setTextSize(24);
1172 canvas->drawString(paint.isLinearText() ? "linear" : "hinted", 128, 30, paint);
1173 for (SkScalar textSize = 8; textSize < 30; textSize *= 1.22f) {
1174 paint.setTextSize(textSize);
1175 canvas->translate(0, textSize);
1176 canvas->drawString(testStr, 10, 0, paint);
1177 }
1178 }
1179 }
1180 ##
1181
1182 #SeeAlso setLinearText Hinting
1183##
1184
1185#Method void setLinearText(bool linearText)
1186
1187 If true, text is converted to Path before drawing and measuring.
1188 By default, kLinearText_Flag is clear.
1189
1190 Sets kLinearText_Flag if linearText is true.
1191 Clears kLinearText_Flag if linearText is false.
1192
1193 #Param linearText setting for kLinearText_Flag ##
1194
1195 #Example
1196 #Height 128
1197 void draw(SkCanvas* canvas) {
1198 SkPaint paint;
1199 paint.setAntiAlias(true);
1200 const char testStr[] = "abcd efgh";
1201 for (int textSize : { 12, 24 } ) {
1202 paint.setTextSize(textSize);
1203 for (auto linearText : { false, true } ) {
1204 paint.setLinearText(linearText);
1205 SkString width;
1206 width.appendScalar(paint.measureText(testStr, SK_ARRAY_COUNT(testStr), nullptr));
1207 canvas->translate(0, textSize + 4);
1208 canvas->drawString(testStr, 10, 0, paint);
1209 canvas->drawString(width, 128, 0, paint);
1210 }
1211 }
1212 }
1213 ##
1214
1215 #SeeAlso isLinearText Hinting
1216##
1217
1218#Subtopic ##
1219
1220#Subtopic Subpixel_Text
1221#Alias Subpixel_Text # makes this a top level name, since it is under subtopic Device_Text
1222
1223Flags kSubpixelText_Flag uses the pixel transparency to represent a fractional offset.
1224As the opaqueness
1225of the color increases, the edge of the glyph appears to move towards the outside of the pixel.
1226
1227#Method bool isSubpixelText() const
1228
Cary Clarkce101242017-09-01 15:51:02 -04001229 If true, Glyphs at different sub-pixel positions may differ on pixel edge coverage.
Cary Clark8032b982017-07-28 11:04:54 -04001230
1231 Equivalent to getFlags masked with kSubpixelText_Flag.
1232
1233 #Return kSubpixelText_Flag state ##
1234
1235 #Example
1236SkPaint paint;
1237SkDebugf("paint.isSubpixelText() %c= !!(paint.getFlags() & SkPaint::kSubpixelText_Flag)\n",
1238 paint.isSubpixelText() == !!(paint.getFlags() & SkPaint::kSubpixelText_Flag) ? '=' : '!');
1239paint.setSubpixelText(true);
1240SkDebugf("paint.isSubpixelText() %c= !!(paint.getFlags() & SkPaint::kSubpixelText_Flag)\n",
1241 paint.isSubpixelText() == !!(paint.getFlags() & SkPaint::kSubpixelText_Flag) ? '=' : '!');
1242
1243 #StdOut
1244 paint.isSubpixelText() == !!(paint.getFlags() & SkPaint::kSubpixelText_Flag)
1245 paint.isSubpixelText() == !!(paint.getFlags() & SkPaint::kSubpixelText_Flag)
1246 ##
1247 ##
1248
1249##
1250
1251#Method void setSubpixelText(bool subpixelText)
1252
Cary Clarkce101242017-09-01 15:51:02 -04001253 Requests, but does not require, that Glyphs respect sub-pixel positioning.
Cary Clark8032b982017-07-28 11:04:54 -04001254
1255 Sets kSubpixelText_Flag if subpixelText is true.
1256 Clears kSubpixelText_Flag if subpixelText is false.
1257
1258 #Param subpixelText setting for kSubpixelText_Flag ##
1259
1260 #Example
1261 SkPaint paint1, paint2;
1262 paint1.setSubpixelText(true);
1263 paint2.setFlags(paint2.getFlags() | SkPaint::kSubpixelText_Flag);
1264 SkDebugf("paint1 %c= paint2\n", paint1 == paint2 ? '=' : '!');
1265
1266 #StdOut
1267 paint1 == paint2
1268 ##
1269 ##
1270
1271##
1272
1273#Subtopic ##
1274
1275#Subtopic LCD_Text
1276#Alias LCD_Text # makes this a top level name, since it is under subtopic Device_Text
1277
1278When set, Flags kLCDRenderText_Flag takes advantage of the organization of Color_RGB stripes that
1279create a color, and relies
Cary Clarkce101242017-09-01 15:51:02 -04001280on the small size of the stripe and visual perception to make the color fringing imperceptible.
Cary Clark8032b982017-07-28 11:04:54 -04001281LCD_Text can be enabled on devices that orient stripes horizontally or vertically, and that order
1282the color components as Color_RGB or Color_RBG.
1283
1284#Method bool isLCDRenderText() const
1285
Cary Clarkce101242017-09-01 15:51:02 -04001286 If true, Glyphs may use LCD striping to improve glyph edges.
Cary Clark8032b982017-07-28 11:04:54 -04001287
1288 Returns true if Flags kLCDRenderText_Flag is set.
1289
1290 #Return kLCDRenderText_Flag state ##
1291
1292 #Example
1293SkPaint paint;
1294SkDebugf("paint.isLCDRenderText() %c= !!(paint.getFlags() & SkPaint::kLCDRenderText_Flag)\n",
1295 paint.isLCDRenderText() == !!(paint.getFlags() & SkPaint::kLCDRenderText_Flag) ? '=' : '!');
1296paint.setLCDRenderText(true);
1297SkDebugf("paint.isLCDRenderText() %c= !!(paint.getFlags() & SkPaint::kLCDRenderText_Flag)\n",
1298 paint.isLCDRenderText() == !!(paint.getFlags() & SkPaint::kLCDRenderText_Flag) ? '=' : '!');
1299
1300 #StdOut
1301 paint.isLCDRenderText() == !!(paint.getFlags() & SkPaint::kLCDRenderText_Flag)
1302 paint.isLCDRenderText() == !!(paint.getFlags() & SkPaint::kLCDRenderText_Flag)
1303 ##
1304 ##
1305
1306##
1307
1308#Method void setLCDRenderText(bool lcdText)
1309
Cary Clarkce101242017-09-01 15:51:02 -04001310 Requests, but does not require, that Glyphs use LCD striping for glyph edges.
Cary Clark8032b982017-07-28 11:04:54 -04001311
1312 Sets kLCDRenderText_Flag if lcdText is true.
1313 Clears kLCDRenderText_Flag if lcdText is false.
1314
1315 #Param lcdText setting for kLCDRenderText_Flag ##
1316
1317 #Example
1318 SkPaint paint1, paint2;
1319 paint1.setLCDRenderText(true);
1320 paint2.setFlags(paint2.getFlags() | SkPaint::kLCDRenderText_Flag);
1321 SkDebugf("paint1 %c= paint2\n", paint1 == paint2 ? '=' : '!');
1322
1323 #StdOut
1324 paint1 == paint2
1325 ##
1326 ##
1327
1328
1329##
1330
1331#Subtopic ##
1332
1333#Topic ##
1334# ------------------------------------------------------------------------------
1335#Topic Font_Embedded_Bitmaps
1336#Alias Font_Embedded_Bitmaps # long-winded enough, alias so I don't type Paint_Font_...
1337
Cary Clarkce101242017-09-01 15:51:02 -04001338Font_Embedded_Bitmaps allows selecting custom sized bitmap Glyphs.
Cary Clark8032b982017-07-28 11:04:54 -04001339Flags kEmbeddedBitmapText_Flag when set chooses an embedded bitmap glyph over an outline contained
1340in a font if the platform supports this option.
1341
1342FreeType selects the bitmap glyph if available when kEmbeddedBitmapText_Flag is set, and selects
1343the outline glyph if kEmbeddedBitmapText_Flag is clear.
1344Windows may select the bitmap glyph but is not required to do so.
1345OS_X and iOS do not support this option.
1346
1347Font_Embedded_Bitmaps is disabled by default.
1348Font_Embedded_Bitmaps can be enabled by default by setting SkPaintDefaults_Flags to
1349kEmbeddedBitmapText_Flag at compile time.
1350
1351#Example
1352 #ToDo image will only output on Ubuntu ... how to handle that in fiddle? ##
1353 #Platform !fiddle
1354 #Description
Cary Clarkce101242017-09-01 15:51:02 -04001355 The "hintgasp" TrueType font in the Skia resources/fonts directory
1356 includes an embedded bitmap Glyph at odd font sizes. This example works
1357 on platforms that use FreeType as their Font_Engine.
1358 Windows may, but is not required to, return a bitmap glyph if
1359 kEmbeddedBitmapText_Flag is set.
Cary Clark8032b982017-07-28 11:04:54 -04001360 ##
1361 #Image embeddedbitmap.png
1362
1363 SkBitmap bitmap;
1364 bitmap.allocN32Pixels(30, 15);
1365 bitmap.eraseColor(0);
1366 SkCanvas offscreen(bitmap);
1367 SkPaint paint;
1368 paint.setAntiAlias(true);
1369 paint.setTextSize(13);
Hal Canary53e5e7d2017-12-08 14:25:14 -05001370 paint.setTypeface(MakeResourceAsTypeface("fonts/hintgasp.ttf"));
Cary Clark8032b982017-07-28 11:04:54 -04001371 for (bool embedded : { false, true}) {
1372 paint.setEmbeddedBitmapText(embedded);
1373 offscreen.drawString("A", embedded ? 5 : 15, 15, paint);
1374 }
1375 canvas->drawBitmap(bitmap, 0, 0);
1376 canvas->scale(10, 10);
1377 canvas->drawBitmap(bitmap, -2, 1);
1378##
1379
1380#Method bool isEmbeddedBitmapText() const
1381
Cary Clarkce101242017-09-01 15:51:02 -04001382 If true, Font_Engine may return Glyphs from font bitmaps instead of from outlines.
Cary Clark8032b982017-07-28 11:04:54 -04001383
1384 Equivalent to getFlags masked with kEmbeddedBitmapText_Flag.
1385
1386 #Return kEmbeddedBitmapText_Flag state ##
1387
1388 #Example
1389 SkPaint paint;
1390 SkDebugf("paint.isEmbeddedBitmapText() %c="
1391 " !!(paint.getFlags() & SkPaint::kEmbeddedBitmapText_Flag)\n",
1392 paint.isEmbeddedBitmapText() ==
1393 !!(paint.getFlags() & SkPaint::kEmbeddedBitmapText_Flag) ? '=' : '!');
1394 paint.setEmbeddedBitmapText(true);
1395 SkDebugf("paint.isEmbeddedBitmapText() %c="
1396 " !!(paint.getFlags() & SkPaint::kEmbeddedBitmapText_Flag)\n",
1397 paint.isEmbeddedBitmapText() ==
1398 !!(paint.getFlags() & SkPaint::kEmbeddedBitmapText_Flag) ? '=' : '!');
1399
1400 #StdOut
1401 paint.isEmbeddedBitmapText() == !!(paint.getFlags() & SkPaint::kEmbeddedBitmapText_Flag)
1402 paint.isEmbeddedBitmapText() == !!(paint.getFlags() & SkPaint::kEmbeddedBitmapText_Flag)
1403 ##
1404 ##
1405
1406##
1407
1408#Method void setEmbeddedBitmapText(bool useEmbeddedBitmapText)
1409
1410 Requests, but does not require, to use bitmaps in fonts instead of outlines.
1411
1412 Sets kEmbeddedBitmapText_Flag if useEmbeddedBitmapText is true.
1413 Clears kEmbeddedBitmapText_Flag if useEmbeddedBitmapText is false.
1414
1415 #Param useEmbeddedBitmapText setting for kEmbeddedBitmapText_Flag ##
1416
1417 #Example
1418 SkPaint paint1, paint2;
1419 paint1.setEmbeddedBitmapText(true);
1420 paint2.setFlags(paint2.getFlags() | SkPaint::kEmbeddedBitmapText_Flag);
1421 SkDebugf("paint1 %c= paint2\n", paint1 == paint2 ? '=' : '!');
1422
1423 #StdOut
1424 paint1 == paint2
1425 ##
1426 ##
1427
1428##
1429
1430#Topic ##
1431# ------------------------------------------------------------------------------
1432#Topic Automatic_Hinting
1433#Substitute auto-hinting
1434
1435If Hinting is set to kNormal_Hinting or kFull_Hinting, Automatic_Hinting
Cary Clarkce101242017-09-01 15:51:02 -04001436instructs the Font_Manager to always hint Glyphs.
Cary Clark8032b982017-07-28 11:04:54 -04001437Automatic_Hinting has no effect if Hinting is set to kNo_Hinting or
1438kSlight_Hinting.
1439
1440Automatic_Hinting only affects platforms that use FreeType as the Font_Manager.
1441
1442#Method bool isAutohinted() const
1443
1444 If true, and if Hinting is set to kNormal_Hinting or kFull_Hinting, and if
1445 platform uses FreeType as the Font_Manager, instruct the Font_Manager to always hint
Cary Clarkce101242017-09-01 15:51:02 -04001446 Glyphs.
Cary Clark8032b982017-07-28 11:04:54 -04001447
1448 Equivalent to getFlags masked with kAutoHinting_Flag.
1449
1450 #Return kAutoHinting_Flag state ##
1451
1452 #Example
1453 SkPaint paint;
1454 for (auto forceAutoHinting : { false, true} ) {
1455 paint.setAutohinted(forceAutoHinting);
1456 SkDebugf("paint.isAutohinted() %c="
1457 " !!(paint.getFlags() & SkPaint::kAutoHinting_Flag)\n",
1458 paint.isAutohinted() ==
1459 !!(paint.getFlags() & SkPaint::kAutoHinting_Flag) ? '=' : '!');
1460 }
1461 #StdOut
1462 paint.isAutohinted() == !!(paint.getFlags() & SkPaint::kAutoHinting_Flag)
1463 paint.isAutohinted() == !!(paint.getFlags() & SkPaint::kAutoHinting_Flag)
1464 ##
1465 ##
1466
1467 #SeeAlso setAutohinted Hinting
1468
1469##
1470
1471#Method void setAutohinted(bool useAutohinter)
1472
1473 If Hinting is set to kNormal_Hinting or kFull_Hinting and useAutohinter is set,
Cary Clarkce101242017-09-01 15:51:02 -04001474 instruct the Font_Manager to always hint Glyphs.
Cary Clark8032b982017-07-28 11:04:54 -04001475 Automatic_Hinting has no effect if Hinting is set to kNo_Hinting or
1476 kSlight_Hinting.
1477
Cary Clark579985c2017-07-31 11:48:27 -04001478 Only affects platforms that use FreeType as the Font_Manager.
Cary Clark8032b982017-07-28 11:04:54 -04001479
1480 Sets kAutoHinting_Flag if useAutohinter is true.
1481 Clears kAutoHinting_Flag if useAutohinter is false.
1482
1483 #Param useAutohinter setting for kAutoHinting_Flag ##
1484
1485 #Example
1486 void draw(SkCanvas* canvas) {
1487 SkPaint paint;
1488 paint.setAntiAlias(true);
1489 const char testStr[] = "xxxx xxxx";
1490 for (auto forceAutoHinting : { false, true} ) {
1491 paint.setAutohinted(forceAutoHinting);
1492 paint.setTextSize(24);
1493 canvas->drawString(paint.isAutohinted() ? "auto-hinted" : "default", 108, 30, paint);
1494 for (SkScalar textSize = 8; textSize < 30; textSize *= 1.22f) {
1495 paint.setTextSize(textSize);
1496 canvas->translate(0, textSize);
1497 canvas->drawString(testStr, 10, 0, paint);
1498 }
1499 }
1500 }
1501 ##
1502
1503 #SeeAlso isAutohinted Hinting
1504
1505##
1506
1507#Topic ##
1508# ------------------------------------------------------------------------------
1509#Topic Vertical_Text
1510
1511Text may be drawn by positioning each glyph, or by positioning the first glyph and
Cary Clarkce101242017-09-01 15:51:02 -04001512using Font_Advance to position subsequent Glyphs. By default, each successive glyph
1513is positioned to the right of the preceding glyph. Vertical_Text sets successive
1514Glyphs to position below the preceding glyph.
Cary Clark8032b982017-07-28 11:04:54 -04001515
Cary Clarkce101242017-09-01 15:51:02 -04001516Skia can translate text character codes as a series of Glyphs, but does not implement
Cary Clark8032b982017-07-28 11:04:54 -04001517font substitution,
Cary Clarkce101242017-09-01 15:51:02 -04001518textual substitution, line layout, or contextual spacing like Kerning pairs. Use
Cary Clark6fc50412017-09-21 12:31:06 -04001519a text shaping engine like
1520#A HarfBuzz # http://harfbuzz.org/ ##
1521 to translate text runs
Cary Clark8032b982017-07-28 11:04:54 -04001522into glyph series.
1523
1524Vertical_Text is clear if text is drawn left to right or set if drawn from top to bottom.
1525
1526Flags kVerticalText_Flag if clear draws text left to right.
1527Flags kVerticalText_Flag if set draws text top to bottom.
1528
1529Vertical_Text is clear by default.
1530Vertical_Text can be set by default by setting SkPaintDefaults_Flags to
1531kVerticalText_Flag at compile time.
1532
1533#Example
1534
1535void draw(SkCanvas* canvas) {
1536 SkPaint paint;
1537 paint.setAntiAlias(true);
1538 paint.setTextSize(50);
1539 for (bool vertical : { false, true } ) {
1540 paint.setVerticalText(vertical);
1541 canvas->drawString("aAlL", 25, 50, paint);
1542 }
1543}
1544
1545##
1546
1547#Method bool isVerticalText() const
1548
Cary Clarkce101242017-09-01 15:51:02 -04001549 If true, Glyphs are drawn top to bottom instead of left to right.
Cary Clark8032b982017-07-28 11:04:54 -04001550
1551 Equivalent to getFlags masked with kVerticalText_Flag.
1552
1553 #Return kVerticalText_Flag state ##
1554
1555 #Example
1556 SkPaint paint;
1557 SkDebugf("paint.isVerticalText() %c= !!(paint.getFlags() & SkPaint::kVerticalText_Flag)\n",
1558 paint.isVerticalText() == !!(paint.getFlags() & SkPaint::kVerticalText_Flag) ? '=' : '!');
1559 paint.setVerticalText(true);
1560 SkDebugf("paint.isVerticalText() %c= !!(paint.getFlags() & SkPaint::kVerticalText_Flag)\n",
1561 paint.isVerticalText() == !!(paint.getFlags() & SkPaint::kVerticalText_Flag) ? '=' : '!');
1562
1563 #StdOut
1564 paint.isVerticalText() == !!(paint.getFlags() & SkPaint::kVerticalText_Flag)
1565 paint.isVerticalText() == !!(paint.getFlags() & SkPaint::kVerticalText_Flag)
1566 ##
1567 ##
1568
1569##
1570
1571#Method void setVerticalText(bool verticalText)
1572
1573 If true, text advance positions the next glyph below the previous glyph instead of to the
1574 right of previous glyph.
1575
1576 Sets kVerticalText_Flag if vertical is true.
1577 Clears kVerticalText_Flag if vertical is false.
1578
1579 #Param verticalText setting for kVerticalText_Flag ##
1580
1581 #Example
1582 SkPaint paint1, paint2;
1583 paint1.setVerticalText(true);
1584 paint2.setFlags(paint2.getFlags() | SkPaint::kVerticalText_Flag);
1585 SkDebugf("paint1 %c= paint2\n", paint1 == paint2 ? '=' : '!');
1586
1587 #StdOut
1588 paint1 == paint2
1589 ##
1590 ##
1591
1592##
1593
1594#Topic ##
1595# ------------------------------------------------------------------------------
1596
1597#Topic Fake_Bold
1598
1599Fake_Bold approximates the bold font style accompanying a normal font when a bold font face
1600is not available. Skia does not provide font substitution; it is up to the client to find the
Cary Clarkbc5697d2017-10-04 14:31:33 -04001601bold font face using the platform Font_Manager.
Cary Clark8032b982017-07-28 11:04:54 -04001602
1603Use Text_Skew_X to approximate an italic font style when the italic font face
1604is not available.
1605
Cary Clarkce101242017-09-01 15:51:02 -04001606A FreeType based port may define SK_USE_FREETYPE_EMBOLDEN at compile time to direct
1607the font engine to create the bold Glyphs. Otherwise, the extra bold is computed
Cary Clark8032b982017-07-28 11:04:54 -04001608by increasing the stroke width and setting the Style to kStrokeAndFill_Style as needed.
1609
1610Fake_Bold is disabled by default.
1611
1612#Example
1613#Height 128
1614void draw(SkCanvas* canvas) {
1615 SkPaint paint;
1616 paint.setAntiAlias(true);
1617 paint.setTextSize(40);
1618 canvas->drawString("OjYy_-", 10, 35, paint);
1619 paint.setFakeBoldText(true);
1620 canvas->drawString("OjYy_-", 10, 75, paint);
1621 // create a custom fake bold by varying the stroke width
1622 paint.setFakeBoldText(false);
1623 paint.setStyle(SkPaint::kStrokeAndFill_Style);
1624 paint.setStrokeWidth(40.f / 48);
1625 canvas->drawString("OjYy_-", 10, 115, paint);
1626}
1627##
1628
1629#Method bool isFakeBoldText() const
1630
1631 If true, approximate bold by increasing the stroke width when creating glyph bitmaps
1632 from outlines.
1633
1634 Equivalent to getFlags masked with kFakeBoldText_Flag.
1635
1636 #Return kFakeBoldText_Flag state ##
1637
1638 #Example
1639 SkPaint paint;
1640 SkDebugf("paint.isFakeBoldText() %c= !!(paint.getFlags() & SkPaint::kFakeBoldText_Flag)\n",
1641 paint.isFakeBoldText() == !!(paint.getFlags() & SkPaint::kFakeBoldText_Flag) ? '=' : '!');
1642 paint.setFakeBoldText(true);
1643 SkDebugf("paint.isFakeBoldText() %c= !!(paint.getFlags() & SkPaint::kFakeBoldText_Flag)\n",
1644 paint.isFakeBoldText() == !!(paint.getFlags() & SkPaint::kFakeBoldText_Flag) ? '=' : '!');
1645
1646 #StdOut
1647 paint.isFakeBoldText() == !!(paint.getFlags() & SkPaint::kFakeBoldText_Flag)
1648 paint.isFakeBoldText() == !!(paint.getFlags() & SkPaint::kFakeBoldText_Flag)
1649 ##
1650 ##
1651
1652##
1653
1654#Method void setFakeBoldText(bool fakeBoldText)
1655
Cary Clarkce101242017-09-01 15:51:02 -04001656 Use increased stroke width when creating glyph bitmaps to approximate a bold typeface.
Cary Clark8032b982017-07-28 11:04:54 -04001657
1658 Sets kFakeBoldText_Flag if fakeBoldText is true.
1659 Clears kFakeBoldText_Flag if fakeBoldText is false.
1660
1661 #Param fakeBoldText setting for kFakeBoldText_Flag ##
1662
1663 #Example
1664 SkPaint paint1, paint2;
1665 paint1.setFakeBoldText(true);
1666 paint2.setFlags(paint2.getFlags() | SkPaint::kFakeBoldText_Flag);
1667 SkDebugf("paint1 %c= paint2\n", paint1 == paint2 ? '=' : '!');
1668
1669 #StdOut
1670 paint1 == paint2
1671 ##
1672 ##
1673
1674##
1675
1676#Topic ##
1677
1678# ------------------------------------------------------------------------------
1679#Topic Full_Hinting_Spacing
1680#Alias Full_Hinting_Spacing # long winded enough -- maybe things with two underscores auto-aliased?
1681
Cary Clarkce101242017-09-01 15:51:02 -04001682if Hinting is set to kFull_Hinting, Full_Hinting_Spacing adjusts the character
1683spacing by the difference of the hinted and Unhinted Left_Side_Bearing and
1684Right_Side_Bearing. Full_Hinting_Spacing only applies to platforms that use
1685FreeType as their Font_Engine.
Cary Clark8032b982017-07-28 11:04:54 -04001686
Cary Clarkce101242017-09-01 15:51:02 -04001687Full_Hinting_Spacing is not related to text Kerning, where the space between
Cary Clarkbc5697d2017-10-04 14:31:33 -04001688a specific pair of characters is adjusted using data in the font Kerning tables.
Cary Clark8032b982017-07-28 11:04:54 -04001689
1690#Method bool isDevKernText() const
1691
1692 Returns if character spacing may be adjusted by the hinting difference.
1693
1694 Equivalent to getFlags masked with kDevKernText_Flag.
1695
1696 #Return kDevKernText_Flag state ##
1697
1698 #Example
1699 SkPaint paint;
1700 SkDebugf("paint.isDevKernText() %c= !!(paint.getFlags() & SkPaint::kDevKernText_Flag)\n",
1701 paint.isDevKernText() == !!(paint.getFlags() & SkPaint::kDevKernText_Flag) ? '=' : '!');
1702 paint.setDevKernText(true);
1703 SkDebugf("paint.isDevKernText() %c= !!(paint.getFlags() & SkPaint::kDevKernText_Flag)\n",
1704 paint.isDevKernText() == !!(paint.getFlags() & SkPaint::kDevKernText_Flag) ? '=' : '!');
1705 ##
1706
1707##
1708
1709#Method void setDevKernText(bool devKernText)
1710
1711 Requests, but does not require, to use hinting to adjust glyph spacing.
1712
1713 Sets kDevKernText_Flag if devKernText is true.
1714 Clears kDevKernText_Flag if devKernText is false.
1715
1716 #Param devKernText setting for devKernText ##
1717
1718 #Example
1719 SkPaint paint1, paint2;
1720 paint1.setDevKernText(true);
1721 paint2.setFlags(paint2.getFlags() | SkPaint::kDevKernText_Flag);
1722 SkDebugf("paint1 %c= paint2\n", paint1 == paint2 ? '=' : '!');
1723
1724 #StdOut
1725 paint1 == paint2
1726 ##
1727 ##
1728
1729##
1730
1731#Topic ##
1732# ------------------------------------------------------------------------------
1733#Topic Filter_Quality_Methods
1734
1735Filter_Quality trades speed for image filtering when the image is scaled.
1736A lower Filter_Quality draws faster, but has less fidelity.
1737A higher Filter_Quality draws slower, but looks better.
Cary Clarkce101242017-09-01 15:51:02 -04001738If the image is drawn without scaling, the Filter_Quality choice will not result
1739in a noticeable difference.
Cary Clark8032b982017-07-28 11:04:54 -04001740
1741Filter_Quality is used in Paint passed as a parameter to
1742#List
1743# SkCanvas::drawBitmap ##
1744# SkCanvas::drawBitmapRect ##
1745# SkCanvas::drawImage ##
1746# SkCanvas::drawImageRect ##
1747 #ToDo probably more... ##
1748#List ##
1749and when Paint has a Shader specialization that uses Image or Bitmap.
1750
1751Filter_Quality is kNone_SkFilterQuality by default.
1752
1753#Example
1754#Image 3
1755void draw(SkCanvas* canvas) {
1756 SkPaint paint;
1757 canvas->scale(.2f, .2f);
1758 for (SkFilterQuality q : { kNone_SkFilterQuality, kLow_SkFilterQuality,
1759 kMedium_SkFilterQuality, kHigh_SkFilterQuality } ) {
1760 paint.setFilterQuality(q);
1761 canvas->drawImage(image.get(), 0, 0, &paint);
1762 canvas->translate(550, 0);
1763 if (kLow_SkFilterQuality == q) canvas->translate(-1100, 550);
1764 }
1765}
1766##
1767
1768#Method SkFilterQuality getFilterQuality() const
1769
1770Returns Filter_Quality, the image filtering level. A lower setting
1771draws faster; a higher setting looks better when the image is scaled.
1772
1773#Return one of: kNone_SkFilterQuality, kLow_SkFilterQuality,
1774 kMedium_SkFilterQuality, kHigh_SkFilterQuality
1775#Return ##
1776
1777#Example
1778 SkPaint paint;
1779 SkDebugf("kNone_SkFilterQuality %c= paint.getFilterQuality()\n",
1780 kNone_SkFilterQuality == paint.getFilterQuality() ? '=' : '!');
1781
1782 #StdOut
1783 kNone_SkFilterQuality == paint.getFilterQuality()
1784 ##
1785##
1786
1787##
1788
1789
1790#Method void setFilterQuality(SkFilterQuality quality)
1791
1792Sets Filter_Quality, the image filtering level. A lower setting
1793draws faster; a higher setting looks better when the image is scaled.
Cary Clark579985c2017-07-31 11:48:27 -04001794Does not check to see if quality is valid.
Cary Clark8032b982017-07-28 11:04:54 -04001795
1796#Param quality one of: kNone_SkFilterQuality, kLow_SkFilterQuality,
1797 kMedium_SkFilterQuality, kHigh_SkFilterQuality
1798##
1799
1800#Example
1801 SkPaint paint;
1802 paint.setFilterQuality(kHigh_SkFilterQuality);
1803 SkDebugf("kHigh_SkFilterQuality %c= paint.getFilterQuality()\n",
1804 kHigh_SkFilterQuality == paint.getFilterQuality() ? '=' : '!');
1805
1806 #StdOut
1807 kHigh_SkFilterQuality == paint.getFilterQuality()
1808 ##
1809##
1810
1811#SeeAlso SkFilterQuality Image_Scaling
1812
1813##
1814
1815#Topic ##
1816# ------------------------------------------------------------------------------
1817#Topic Color_Methods
1818
1819Color specifies the Color_RGB_Red, Color_RGB_Blue, Color_RGB_Green, and Color_Alpha values used to draw a filled
1820or stroked shape in a
182132-bit value. Each component occupies 8-bits, ranging from zero: no contribution;
1822to 255: full intensity. All values in any combination are valid.
1823
Cary Clarkce101242017-09-01 15:51:02 -04001824Color is not Premultiplied;
Cary Clark8032b982017-07-28 11:04:54 -04001825Color_Alpha sets the transparency independent of Color_RGB: Color_RGB_Red, Color_RGB_Blue, and Color_RGB_Green.
1826
1827The bit positions of Color_Alpha and Color_RGB are independent of the bit positions
1828on the output device, which may have more or fewer bits, and may have a different arrangement.
1829
1830#Table
1831#Legend
1832# bit positions # Color_Alpha # Color_RGB_Red # Color_RGB_Blue # Color_RGB_Green ##
1833#Legend ##
1834# # 31 - 24 # 23 - 16 # 15 - 8 # 7 - 0 ##
1835#Table ##
1836
1837#Example
1838#Height 128
1839 void draw(SkCanvas* canvas) {
1840 SkPaint paint;
1841 paint.setColor(0x8000FF00); // transparent green
1842 canvas->drawCircle(50, 50, 40, paint);
1843 paint.setARGB(128, 255, 0, 0); // transparent red
1844 canvas->drawCircle(80, 50, 40, paint);
1845 paint.setColor(SK_ColorBLUE);
1846 paint.setAlpha(0x80);
1847 canvas->drawCircle(65, 65, 40, paint);
1848 }
1849##
1850
1851#Method SkColor getColor() const
1852
Cary Clarkce101242017-09-01 15:51:02 -04001853 Retrieves Alpha and Color_RGB, Unpremultiplied, packed into 32 bits.
Cary Clark8032b982017-07-28 11:04:54 -04001854 Use helpers SkColorGetA, SkColorGetR, SkColorGetG, and SkColorGetB to extract
1855 a color component.
1856
1857 #Return Unpremultiplied Color_ARGB ##
1858
1859 #Example
1860 SkPaint paint;
1861 paint.setColor(SK_ColorYELLOW);
1862 SkColor y = paint.getColor();
1863 SkDebugf("Yellow is %d%% red, %d%% green, and %d%% blue.\n", (int) (SkColorGetR(y) / 2.55f),
1864 (int) (SkColorGetG(y) / 2.55f), (int) (SkColorGetB(y) / 2.55f));
1865
1866 #StdOut
1867 Yellow is 100% red, 100% green, and 0% blue.
1868 ##
1869 ##
1870
1871 #SeeAlso SkColor
1872
1873##
1874
1875#Method void setColor(SkColor color)
1876
Cary Clarkce101242017-09-01 15:51:02 -04001877 Sets Alpha and Color_RGB used when stroking and filling. The color is a 32-bit value,
1878 Unpremultiplied, packing 8-bit components for Alpha, Red, Blue, and Green.
Cary Clark8032b982017-07-28 11:04:54 -04001879
1880 #Param color Unpremultiplied Color_ARGB ##
Cary Clark0c5f5462017-12-15 11:21:51 -05001881
1882 #Example
Cary Clark8032b982017-07-28 11:04:54 -04001883 SkPaint green1, green2;
1884 unsigned a = 255;
1885 unsigned r = 0;
1886 unsigned g = 255;
1887 unsigned b = 0;
1888 green1.setColor((a << 24) + (r << 16) + (g << 8) + (b << 0));
1889 green2.setColor(0xFF00FF00);
1890 SkDebugf("green1 %c= green2\n", green1 == green2 ? '=' : '!');
1891
1892 #StdOut
1893 green1 == green2
1894 ##
1895 ##
1896
1897 #SeeAlso SkColor setARGB SkColorSetARGB
1898
1899##
1900
1901#Subtopic Alpha_Methods
1902
1903Color_Alpha sets the transparency independent of Color_RGB: Color_RGB_Red, Color_RGB_Blue, and Color_RGB_Green.
1904
1905#Method uint8_t getAlpha() const
1906
Cary Clarkce101242017-09-01 15:51:02 -04001907 Retrieves Alpha from the Color used when stroking and filling.
Cary Clark8032b982017-07-28 11:04:54 -04001908
Cary Clarkce101242017-09-01 15:51:02 -04001909 #Return Alpha ranging from zero, fully transparent, to 255, fully opaque ##
Cary Clark8032b982017-07-28 11:04:54 -04001910
1911 #Example
1912 SkPaint paint;
1913 SkDebugf("255 %c= paint.getAlpha()\n", 255 == paint.getAlpha() ? '=' : '!');
1914
1915 #StdOut
1916 255 == paint.getAlpha()
1917 ##
1918 ##
1919
1920##
1921
1922#Method void setAlpha(U8CPU a)
1923
Cary Clarkce101242017-09-01 15:51:02 -04001924 Replaces Alpha, leaving Color_RGB
Cary Clark8032b982017-07-28 11:04:54 -04001925 unchanged. An out of range value triggers an assert in the debug
1926 build. a is a value from zero to 255.
1927 a set to zero makes Color fully transparent; a set to 255 makes Color
1928 fully opaque.
1929
Cary Clarkce101242017-09-01 15:51:02 -04001930 #Param a Alpha component of Color ##
Cary Clark8032b982017-07-28 11:04:54 -04001931
1932 #Example
1933 SkPaint paint;
1934 paint.setColor(0x00112233);
1935 paint.setAlpha(0x44);
1936 SkDebugf("0x44112233 %c= paint.getColor()\n", 0x44112233 == paint.getColor() ? '=' : '!');
1937
1938 #StdOut
1939 0x44112233 == paint.getColor()
1940 ##
1941 ##
1942
1943##
1944
1945#Subtopic ##
1946
1947#Method void setARGB(U8CPU a, U8CPU r, U8CPU g, U8CPU b)
1948
1949 Sets Color used when drawing solid fills. The color components range from 0 to 255.
Cary Clarkce101242017-09-01 15:51:02 -04001950 The color is Unpremultiplied; Alpha sets the transparency independent of Color_RGB.
Cary Clark8032b982017-07-28 11:04:54 -04001951
1952 #Param a amount of Color_Alpha, from fully transparent (0) to fully opaque (255) ##
1953 #Param r amount of Color_RGB_Red, from no red (0) to full red (255) ##
1954 #Param g amount of Color_RGB_Green, from no green (0) to full green (255) ##
1955 #Param b amount of Color_RGB_Blue, from no blue (0) to full blue (255) ##
1956
1957 #Example
1958 SkPaint transRed1, transRed2;
1959 transRed1.setARGB(255 / 2, 255, 0, 0);
1960 transRed2.setColor(SkColorSetARGB(255 / 2, 255, 0, 0));
1961 SkDebugf("transRed1 %c= transRed2", transRed1 == transRed2 ? '=' : '!');
1962
1963 #StdOut
1964 transRed1 == transRed2
1965 ##
1966 ##
1967
1968 #SeeAlso setColor SkColorSetARGB
1969
1970##
1971
1972#Topic Color_Methods ##
1973
1974# ------------------------------------------------------------------------------
1975#Topic Style
1976
1977Style specifies if the geometry is filled, stroked, or both filled and stroked.
1978Some shapes ignore Style and are always drawn filled or stroked.
1979
1980Set Style to kFill_Style to fill the shape.
1981The fill covers the area inside the geometry for most shapes.
1982
1983Set Style to kStroke_Style to stroke the shape.
1984
1985# ------------------------------------------------------------------------------
1986#Subtopic Fill
1987
1988#ToDo write up whatever generalities make sense to describe filling ##
1989
1990#SeeAlso Path_Fill_Type
1991#Subtopic ##
1992
1993#Subtopic Stroke
Cary Clarkbc5697d2017-10-04 14:31:33 -04001994The stroke covers the area described by following the shape edge with a pen or brush of
Cary Clark8032b982017-07-28 11:04:54 -04001995Stroke_Width. The area covered where the shape starts and stops is described by Stroke_Cap.
1996The area covered where the shape turns a corner is described by Stroke_Join.
Cary Clarkbc5697d2017-10-04 14:31:33 -04001997The stroke is centered on the shape; it extends equally on either side of the shape edge.
Cary Clark8032b982017-07-28 11:04:54 -04001998
1999As Stroke_Width gets smaller, the drawn path frame is thinner. Stroke_Width less than one
2000may have gaps, and if kAntiAlias_Flag is set, Color_Alpha will increase to visually decrease coverage.
2001#Subtopic ##
2002
2003#Subtopic Hairline
2004#Alias Hairline # maybe should be Stroke_Hairline ?
2005
2006Stroke_Width of zero has a special meaning and switches drawing to use Hairline.
2007Hairline draws the thinnest continuous frame. If kAntiAlias_Flag is clear, adjacent pixels
2008flow horizontally, vertically,or diagonally.
2009
Cary Clarkce101242017-09-01 15:51:02 -04002010#ToDo what is the description of Anti-aliased hairlines? ##
Cary Clark8032b982017-07-28 11:04:54 -04002011
2012Path drawing with Hairline may hit the same pixel more than once. For instance, Path containing
2013two lines in one Path_Contour will draw the corner point once, but may both lines may draw the adjacent
2014pixel. If kAntiAlias_Flag is set, transparency is applied twice, resulting in a darker pixel. Some
2015GPU-backed implementations apply transparency at a later drawing stage, avoiding double hit pixels
2016while stroking.
2017
2018#Subtopic ##
2019
2020#Enum Style
2021
2022#Code
2023 enum Style {
2024 kFill_Style,
2025 kStroke_Style,
2026 kStrokeAndFill_Style,
2027 };
2028##
2029
2030Set Style to fill, stroke, or both fill and stroke geometry.
2031The stroke and fill
2032share all paint attributes; for instance, they are drawn with the same color.
2033
2034Use kStrokeAndFill_Style to avoid hitting the same pixels twice with a stroke draw and
2035a fill draw.
2036
2037#Const kFill_Style 0
2038 Set to fill geometry.
Cary Clarkce101242017-09-01 15:51:02 -04002039 Applies to Rect, Region, Round_Rect, Circles, Ovals, Path, and Text.
2040 Bitmap, Image, Patches, Region, Sprites, and Vertices are painted as if
Cary Clark8032b982017-07-28 11:04:54 -04002041 kFill_Style is set, and ignore the set Style.
2042 The Path_Fill_Type specifies additional rules to fill the area outside the path edge,
2043 and to create an unfilled hole inside the shape.
2044 Style is set to kFill_Style by default.
2045##
2046
2047#Const kStroke_Style 1
2048 Set to stroke geometry.
Cary Clarkce101242017-09-01 15:51:02 -04002049 Applies to Rect, Region, Round_Rect, Arcs, Circles, Ovals, Path, and Text.
2050 Arcs, Lines, and Points, are always drawn as if kStroke_Style is set,
Cary Clark8032b982017-07-28 11:04:54 -04002051 and ignore the set Style.
2052 The stroke construction is unaffected by the Path_Fill_Type.
2053##
2054
2055#Const kStrokeAndFill_Style 2
2056 Set to stroke and fill geometry.
Cary Clarkce101242017-09-01 15:51:02 -04002057 Applies to Rect, Region, Round_Rect, Circles, Ovals, Path, and Text.
Cary Clark8032b982017-07-28 11:04:54 -04002058 Path is treated as if it is set to SkPath::kWinding_FillType,
2059 and the set Path_Fill_Type is ignored.
2060##
2061
2062#Enum ##
2063
2064#Enum
2065
2066#Code
2067 enum {
Cary Clarkbad5ad72017-08-03 17:14:08 -04002068 kStyleCount = kStrokeAndFill_Style + 1,
Cary Clark8032b982017-07-28 11:04:54 -04002069 };
2070##
2071
2072#Const kStyleCount 3
2073The number of different Style values defined.
2074May be used to verify that Style is a legal value.
2075##
2076
2077#Enum ##
2078
2079#Method Style getStyle() const
2080
2081 Whether the geometry is filled, stroked, or filled and stroked.
2082
2083 #Return one of:kFill_Style, kStroke_Style, kStrokeAndFill_Style ##
2084
2085 #Example
2086 SkPaint paint;
2087 SkDebugf("SkPaint::kFill_Style %c= paint.getStyle()\n",
2088 SkPaint::kFill_Style == paint.getStyle() ? '=' : '!');
2089
2090 #StdOut
2091 SkPaint::kFill_Style == paint.getStyle()
2092 ##
2093 ##
2094
2095#SeeAlso Style setStyle
2096##
2097
2098#Method void setStyle(Style style)
2099
2100 Sets whether the geometry is filled, stroked, or filled and stroked.
2101 Has no effect if style is not a legal Style value.
2102
2103 #Param style one of: kFill_Style, kStroke_Style, kStrokeAndFill_Style
2104 ##
2105
2106 #Example
2107 void draw(SkCanvas* canvas) {
2108 SkPaint paint;
2109 paint.setStrokeWidth(5);
2110 SkRegion region;
2111 region.op(140, 10, 160, 30, SkRegion::kUnion_Op);
2112 region.op(170, 40, 190, 60, SkRegion::kUnion_Op);
2113 SkBitmap bitmap;
2114 bitmap.setInfo(SkImageInfo::MakeA8(50, 50), 50);
2115 uint8_t pixels[50][50];
2116 for (int x = 0; x < 50; ++x) {
2117 for (int y = 0; y < 50; ++y) {
2118 pixels[y][x] = (x + y) % 5 ? 0xFF : 0x00;
2119 }
2120 }
2121 bitmap.setPixels(pixels);
2122 for (auto style : { SkPaint::kFill_Style,
2123 SkPaint::kStroke_Style,
2124 SkPaint::kStrokeAndFill_Style }) {
2125 paint.setStyle(style);
2126 canvas->drawLine(10, 10, 60, 60, paint);
2127 canvas->drawRect({80, 10, 130, 60}, paint);
2128 canvas->drawRegion(region, paint);
2129 canvas->drawBitmap(bitmap, 200, 10, &paint);
2130 canvas->translate(0, 80);
2131 }
2132 }
2133 ##
2134
2135#SeeAlso Style getStyle
2136##
2137
2138#SeeAlso Path_Fill_Type Path_Effect Style_Fill Style_Stroke
2139#Topic Style ##
2140
2141# ------------------------------------------------------------------------------
2142#Topic Stroke_Width
2143
2144Stroke_Width sets the width for stroking. The width is the thickness
Cary Clarkbc5697d2017-10-04 14:31:33 -04002145of the stroke perpendicular to the path direction when the paint style is
Cary Clark8032b982017-07-28 11:04:54 -04002146set to kStroke_Style or kStrokeAndFill_Style.
2147
2148When width is greater than zero, the stroke encompasses as many pixels partially
2149or fully as needed. When the width equals zero, the paint enables hairlines;
2150the stroke is always one pixel wide.
2151
Cary Clarkbc5697d2017-10-04 14:31:33 -04002152The stroke dimensions are scaled by the canvas matrix, but Hairline stroke
Cary Clark8032b982017-07-28 11:04:54 -04002153remains one pixel wide regardless of scaling.
2154
2155The default width for the paint is zero.
2156
2157#Example
2158#Height 170
2159 #Platform raster gpu
2160 #Description
2161 The pixels hit to represent thin lines vary with the angle of the
Cary Clarkbc5697d2017-10-04 14:31:33 -04002162 line and the platform implementation.
Cary Clark8032b982017-07-28 11:04:54 -04002163 ##
2164 void draw(SkCanvas* canvas) {
2165 SkPaint paint;
2166 for (bool antialias : { false, true }) {
2167 paint.setAntiAlias(antialias);
2168 for (int width = 0; width <= 4; ++width) {
2169 SkScalar offset = antialias * 100 + width * 20;
2170 paint.setStrokeWidth(width * 0.25f);
2171 canvas->drawLine(10 + offset, 10, 20 + offset, 60, paint);
2172 canvas->drawLine(10 + offset, 110, 60 + offset, 160, paint);
2173 }
2174 }
2175 }
2176##
2177
2178#Method SkScalar getStrokeWidth() const
2179
2180 Returns the thickness of the pen used by Paint to
2181 outline the shape.
2182
2183 #Return zero for Hairline, greater than zero for pen thickness ##
2184
2185 #Example
2186 SkPaint paint;
2187 SkDebugf("0 %c= paint.getStrokeWidth()\n", 0 == paint.getStrokeWidth() ? '=' : '!');
2188
2189 #StdOut
2190 0 == paint.getStrokeWidth()
2191 ##
2192 ##
2193
2194##
2195
2196#Method void setStrokeWidth(SkScalar width)
2197
2198 Sets the thickness of the pen used by the paint to
2199 outline the shape.
2200 Has no effect if width is less than zero.
2201
2202 #Param width zero thickness for Hairline; greater than zero for pen thickness
2203 ##
2204
2205 #Example
2206 SkPaint paint;
2207 paint.setStrokeWidth(5);
2208 paint.setStrokeWidth(-1);
2209 SkDebugf("5 %c= paint.getStrokeWidth()\n", 5 == paint.getStrokeWidth() ? '=' : '!');
2210
2211 #StdOut
2212 5 == paint.getStrokeWidth()
2213 ##
2214 ##
2215
2216##
2217
2218#Topic ##
2219# ------------------------------------------------------------------------------
2220#Topic Miter_Limit
2221
2222Miter_Limit specifies the maximum miter length,
2223relative to the stroke width.
2224
2225Miter_Limit is used when the Stroke_Join
2226is set to kMiter_Join, and the Style is either kStroke_Style
2227or kStrokeAndFill_Style.
2228
2229If the miter at a corner exceeds this limit, kMiter_Join
2230is replaced with kBevel_Join.
2231
2232Miter_Limit can be computed from the corner angle:
2233
2234#Formula
2235 miter limit = 1 / sin ( angle / 2 )
2236#Formula ##
2237
2238Miter_Limit default value is 4.
2239The default may be changed at compile time by setting SkPaintDefaults_MiterLimit
Cary Clarkce101242017-09-01 15:51:02 -04002240in "SkUserConfig.h" or as a define supplied by the build environment.
Cary Clark8032b982017-07-28 11:04:54 -04002241
2242Here are some miter limits and the angles that triggers them.
2243#Table
2244#Legend
2245 # miter limit # angle in degrees ##
2246#Legend ##
2247 # 10 # 11.48 ##
2248 # 9 # 12.76 ##
2249 # 8 # 14.36 ##
2250 # 7 # 16.43 ##
2251 # 6 # 19.19 ##
2252 # 5 # 23.07 ##
2253 # 4 # 28.96 ##
2254 # 3 # 38.94 ##
2255 # 2 # 60 ##
2256 # 1 # 180 ##
2257#Table ##
2258
2259#Example
2260 #Height 170
2261 #Width 384
2262 #Description
2263 This example draws a stroked corner and the miter length beneath.
2264 When the miter limit is decreased slightly, the miter join is replaced
2265 by a bevel join.
2266 ##
2267 void draw(SkCanvas* canvas) {
2268 SkPoint pts[] = {{ 10, 50 }, { 110, 80 }, { 10, 110 }};
2269 SkVector v[] = { pts[0] - pts[1], pts[2] - pts[1] };
2270 SkScalar angle1 = SkScalarATan2(v[0].fY, v[0].fX);
2271 SkScalar angle2 = SkScalarATan2(v[1].fY, v[1].fX);
2272 const SkScalar strokeWidth = 20;
2273 SkScalar miterLimit = 1 / SkScalarSin((angle2 - angle1) / 2);
2274 SkScalar miterLength = strokeWidth * miterLimit;
2275 SkPath path;
2276 path.moveTo(pts[0]);
2277 path.lineTo(pts[1]);
2278 path.lineTo(pts[2]);
2279 SkPaint paint; // set to default kMiter_Join
2280 paint.setAntiAlias(true);
2281 paint.setStyle(SkPaint::kStroke_Style);
2282 paint.setStrokeMiter(miterLimit);
2283 paint.setStrokeWidth(strokeWidth);
2284 canvas->drawPath(path, paint);
2285 paint.setStrokeWidth(1);
2286 canvas->drawLine(pts[1].fX - miterLength / 2, pts[1].fY + 50,
2287 pts[1].fX + miterLength / 2, pts[1].fY + 50, paint);
2288 canvas->translate(200, 0);
2289 miterLimit *= 0.99f;
2290 paint.setStrokeMiter(miterLimit);
2291 paint.setStrokeWidth(strokeWidth);
2292 canvas->drawPath(path, paint);
2293 paint.setStrokeWidth(1);
2294 canvas->drawLine(pts[1].fX - miterLength / 2, pts[1].fY + 50,
2295 pts[1].fX + miterLength / 2, pts[1].fY + 50, paint);
2296 }
2297##
2298
2299#Method SkScalar getStrokeMiter() const
2300
2301 The limit at which a sharp corner is drawn beveled.
2302
2303 #Return zero and greater Miter_Limit ##
2304
2305 #Example
2306 SkPaint paint;
2307 SkDebugf("default miter limit == %g\n", paint.getStrokeMiter());
2308
2309 #StdOut
2310 default miter limit == 4
2311 ##
2312 ##
2313
2314 #SeeAlso Miter_Limit setStrokeMiter Join
2315
2316##
2317
2318#Method void setStrokeMiter(SkScalar miter)
2319
2320 The limit at which a sharp corner is drawn beveled.
2321 Valid values are zero and greater.
2322 Has no effect if miter is less than zero.
2323
2324 #Param miter zero and greater Miter_Limit
2325 ##
2326
2327 #Example
2328 SkPaint paint;
2329 paint.setStrokeMiter(8);
2330 paint.setStrokeMiter(-1);
2331 SkDebugf("default miter limit == %g\n", paint.getStrokeMiter());
2332
2333 #StdOut
2334 default miter limit == 8
2335 ##
2336 ##
2337
2338 #SeeAlso Miter_Limit getStrokeMiter Join
2339
2340##
2341
2342#Topic ##
2343# ------------------------------------------------------------------------------
2344#Topic Stroke_Cap
2345
2346#Enum Cap
2347
2348#Code
2349 enum Cap {
2350 kButt_Cap,
2351 kRound_Cap,
2352 kSquare_Cap,
2353
2354 kLast_Cap = kSquare_Cap,
Cary Clarkbad5ad72017-08-03 17:14:08 -04002355 kDefault_Cap = kButt_Cap,
Cary Clark8032b982017-07-28 11:04:54 -04002356 };
Cary Clark6fc50412017-09-21 12:31:06 -04002357
Cary Clark8032b982017-07-28 11:04:54 -04002358 static constexpr int kCapCount = kLast_Cap + 1;
2359##
2360
2361Stroke_Cap draws at the beginning and end of an open Path_Contour.
2362
2363 #Const kButt_Cap 0
2364 Does not extend the stroke past the beginning or the end.
2365 ##
2366 #Const kRound_Cap 1
2367 Adds a circle with a diameter equal to Stroke_Width at the beginning
2368 and end.
2369 ##
2370 #Const kSquare_Cap 2
2371 Adds a square with sides equal to Stroke_Width at the beginning
2372 and end. The square sides are parallel to the initial and final direction
2373 of the stroke.
2374 ##
2375 #Const kLast_Cap 2
2376 Equivalent to the largest value for Stroke_Cap.
2377 ##
2378 #Const kDefault_Cap 0
2379 Equivalent to kButt_Cap.
2380 Stroke_Cap is set to kButt_Cap by default.
2381 ##
2382
2383 #Const kCapCount 3
2384 The number of different Stroke_Cap values defined.
2385 May be used to verify that Stroke_Cap is a legal value.
2386 ##
2387#Enum ##
2388
2389Stroke describes the area covered by a pen of Stroke_Width as it
Cary Clarkbc5697d2017-10-04 14:31:33 -04002390follows the Path_Contour, moving parallel to the contour direction.
Cary Clark8032b982017-07-28 11:04:54 -04002391
2392If the Path_Contour is not terminated by SkPath::kClose_Verb, the contour has a
2393visible beginning and end.
2394
2395Path_Contour may start and end at the same point; defining Zero_Length_Contour.
2396
2397kButt_Cap and Zero_Length_Contour is not drawn.
2398kRound_Cap and Zero_Length_Contour draws a circle of diameter Stroke_Width
2399at the contour point.
2400kSquare_Cap and Zero_Length_Contour draws an upright square with a side of
2401Stroke_Width at the contour point.
2402
2403Stroke_Cap is kButt_Cap by default.
2404
2405#Example
Cary Clark2ade9972017-11-02 17:49:34 -04002406#Height 200
Cary Clark8032b982017-07-28 11:04:54 -04002407 SkPaint paint;
2408 paint.setStyle(SkPaint::kStroke_Style);
2409 paint.setStrokeWidth(20);
2410 SkPath path;
2411 path.moveTo(30, 30);
2412 path.lineTo(30, 30);
2413 path.moveTo(70, 30);
2414 path.lineTo(90, 40);
2415 for (SkPaint::Cap c : { SkPaint::kButt_Cap, SkPaint::kRound_Cap, SkPaint::kSquare_Cap } ) {
2416 paint.setStrokeCap(c);
2417 canvas->drawPath(path, paint);
2418 canvas->translate(0, 70);
2419 }
2420##
2421
2422#Method Cap getStrokeCap() const
2423
2424 The geometry drawn at the beginning and end of strokes.
2425
2426 #Return one of: kButt_Cap, kRound_Cap, kSquare_Cap ##
2427
2428 #Example
2429 SkPaint paint;
2430 SkDebugf("kButt_Cap %c= default stroke cap\n",
2431 SkPaint::kButt_Cap == paint.getStrokeCap() ? '=' : '!');
2432
2433 #StdOut
2434 kButt_Cap == default stroke cap
2435 ##
2436 ##
2437
2438 #SeeAlso Stroke_Cap setStrokeCap
2439##
2440
2441#Method void setStrokeCap(Cap cap)
2442
2443 The geometry drawn at the beginning and end of strokes.
2444
2445 #Param cap one of: kButt_Cap, kRound_Cap, kSquare_Cap;
2446 has no effect if cap is not valid
2447 ##
2448
2449 #Example
2450 SkPaint paint;
2451 paint.setStrokeCap(SkPaint::kRound_Cap);
2452 paint.setStrokeCap((SkPaint::Cap) SkPaint::kCapCount);
2453 SkDebugf("kRound_Cap %c= paint.getStrokeCap()\n",
2454 SkPaint::kRound_Cap == paint.getStrokeCap() ? '=' : '!');
2455
2456 #StdOut
2457 kRound_Cap == paint.getStrokeCap()
2458 ##
2459 ##
2460
2461 #SeeAlso Stroke_Cap getStrokeCap
2462##
2463
2464#Topic ##
2465# ------------------------------------------------------------------------------
2466#Topic Stroke_Join
2467
2468Stroke_Join draws at the sharp corners of an open or closed Path_Contour.
2469
2470Stroke describes the area covered by a pen of Stroke_Width as it
Cary Clarkbc5697d2017-10-04 14:31:33 -04002471follows the Path_Contour, moving parallel to the contour direction.
Cary Clark8032b982017-07-28 11:04:54 -04002472
2473If the contour direction changes abruptly, because the tangent direction leading
2474to the end of a curve within the contour does not match the tangent direction of
2475the following curve, the pair of curves meet at Stroke_Join.
2476
2477#Example
Cary Clark2ade9972017-11-02 17:49:34 -04002478#Height 200
Cary Clarka560c472017-11-27 10:44:06 -05002479 SkPaint paint;
2480 paint.setStyle(SkPaint::kStroke_Style);
2481 paint.setStrokeWidth(20);
2482 SkPath path;
2483 path.moveTo(30, 20);
2484 path.lineTo(40, 40);
2485 path.conicTo(70, 20, 100, 20, .707f);
2486 for (SkPaint::Join j : { SkPaint::kMiter_Join, SkPaint::kRound_Join, SkPaint::kBevel_Join } ) {
2487 paint.setStrokeJoin(j);
2488 canvas->drawPath(path, paint);
2489 canvas->translate(0, 70);
2490 }
Cary Clark8032b982017-07-28 11:04:54 -04002491##
2492
2493#Enum Join
2494#Code
2495 enum Join {
2496 kMiter_Join,
2497 kRound_Join,
2498 kBevel_Join,
2499
2500 kLast_Join = kBevel_Join,
Cary Clarkbad5ad72017-08-03 17:14:08 -04002501 kDefault_Join = kMiter_Join,
Cary Clark8032b982017-07-28 11:04:54 -04002502 };
Cary Clark6fc50412017-09-21 12:31:06 -04002503
Cary Clark8032b982017-07-28 11:04:54 -04002504 static constexpr int kJoinCount = kLast_Join + 1;
2505##
2506
Cary Clark1eace2d2017-07-31 07:52:43 -04002507Join specifies how corners are drawn when a shape is stroked. Join
Cary Clark8032b982017-07-28 11:04:54 -04002508affects the four corners of a stroked rectangle, and the connected segments in a
2509stroked path.
2510
2511Choose miter join to draw sharp corners. Choose round join to draw a circle with a
2512radius equal to the stroke width on top of the corner. Choose bevel join to minimally
2513connect the thick strokes.
2514
2515The fill path constructed to describe the stroked path respects the join setting but may
2516not contain the actual join. For instance, a fill path constructed with round joins does
2517not necessarily include circles at each connected segment.
2518
2519#Const kMiter_Join 0
2520 Extends the outside corner to the extent allowed by Miter_Limit.
2521 If the extension exceeds Miter_Limit, kBevel_Join is used instead.
2522##
2523
2524#Const kRound_Join 1
2525 Adds a circle with a diameter of Stroke_Width at the sharp corner.
2526##
2527
2528#Const kBevel_Join 2
2529 Connects the outside edges of the sharp corner.
2530##
2531
2532#Const kLast_Join 2
2533 Equivalent to the largest value for Stroke_Join.
2534##
2535
2536#Const kDefault_Join 1
2537 Equivalent to kMiter_Join.
2538 Stroke_Join is set to kMiter_Join by default.
2539##
2540
2541#Const kJoinCount 3
2542 The number of different Stroke_Join values defined.
2543 May be used to verify that Stroke_Join is a legal value.
2544##
2545
2546#Example
2547#Width 462
2548void draw(SkCanvas* canvas) {
2549 SkPath path;
2550 path.moveTo(10, 50);
2551 path.quadTo(35, 110, 60, 210);
2552 path.quadTo(105, 110, 130, 10);
2553 SkPaint paint; // set to default kMiter_Join
2554 paint.setAntiAlias(true);
2555 paint.setStyle(SkPaint::kStroke_Style);
2556 paint.setStrokeWidth(20);
2557 canvas->drawPath(path, paint);
2558 canvas->translate(150, 0);
2559 paint.setStrokeJoin(SkPaint::kBevel_Join);
2560 canvas->drawPath(path, paint);
2561 canvas->translate(150, 0);
2562 paint.setStrokeJoin(SkPaint::kRound_Join);
2563 canvas->drawPath(path, paint);
2564}
2565##
2566
2567#SeeAlso setStrokeJoin getStrokeJoin setStrokeMiter getStrokeMiter
2568
2569#Enum ##
2570
2571#Method Join getStrokeJoin() const
2572
Cary Clark0c5f5462017-12-15 11:21:51 -05002573 The geometry drawn at the corners of strokes.
Cary Clark8032b982017-07-28 11:04:54 -04002574
2575 #Return one of: kMiter_Join, kRound_Join, kBevel_Join ##
2576
2577 #Example
2578 SkPaint paint;
2579 SkDebugf("kMiter_Join %c= default stroke join\n",
2580 SkPaint::kMiter_Join == paint.getStrokeJoin() ? '=' : '!');
2581
2582 #StdOut
2583 kMiter_Join == default stroke join
2584 ##
2585 ##
2586
2587 #SeeAlso Stroke_Join setStrokeJoin
2588##
2589
2590#Method void setStrokeJoin(Join join)
2591
Cary Clark0c5f5462017-12-15 11:21:51 -05002592 The geometry drawn at the corners of strokes.
Cary Clark8032b982017-07-28 11:04:54 -04002593
2594 #Param join one of: kMiter_Join, kRound_Join, kBevel_Join;
Cary Clark579985c2017-07-31 11:48:27 -04002595 otherwise, has no effect
Cary Clark8032b982017-07-28 11:04:54 -04002596 ##
2597
2598 #Example
2599 SkPaint paint;
2600 paint.setStrokeJoin(SkPaint::kMiter_Join);
2601 paint.setStrokeJoin((SkPaint::Join) SkPaint::kJoinCount);
2602 SkDebugf("kMiter_Join %c= paint.getStrokeJoin()\n",
2603 SkPaint::kMiter_Join == paint.getStrokeJoin() ? '=' : '!');
2604
2605 #StdOut
2606 kMiter_Join == paint.getStrokeJoin()
2607 ##
2608 ##
2609
2610 #SeeAlso Stroke_Join getStrokeJoin
2611##
2612
2613#SeeAlso Miter_Limit
2614
2615#Topic Stroke_Join ##
2616# ------------------------------------------------------------------------------
2617#Topic Fill_Path
2618
2619Fill_Path creates a Path by applying the Path_Effect, followed by the Style_Stroke.
2620
2621If Paint contains Path_Effect, Path_Effect operates on the source Path; the result
2622replaces the destination Path. Otherwise, the source Path is replaces the
2623destination Path.
2624
2625Fill Path can request the Path_Effect to restrict to a culling rectangle, but
2626the Path_Effect is not required to do so.
2627
2628If Style is kStroke_Style or kStrokeAndFill_Style,
2629and Stroke_Width is greater than zero, the Stroke_Width, Stroke_Cap, Stroke_Join,
2630and Miter_Limit operate on the destination Path, replacing it.
2631
2632Fill Path can specify the precision used by Stroke_Width to approximate the stroke geometry.
2633
2634If the Style is kStroke_Style and the Stroke_Width is zero, getFillPath
2635returns false since Hairline has no filled equivalent.
2636
2637#Method bool getFillPath(const SkPath& src, SkPath* dst, const SkRect* cullRect,
2638 SkScalar resScale = 1) const
2639
2640 The filled equivalent of the stroked path.
2641
2642 #Param src Path read to create a filled version ##
2643 #Param dst resulting Path; may be the same as src, but may not be nullptr ##
2644 #Param cullRect optional limit passed to Path_Effect ##
2645 #Param resScale if > 1, increase precision, else if (0 < res < 1) reduce precision
2646 to favor speed and size
2647 ##
2648 #Return true if the path represents Style_Fill, or false if it represents Hairline ##
2649
2650 #Example
2651 #Height 192
2652 #Description
Cary Clarkce101242017-09-01 15:51:02 -04002653 A very small Quad stroke is turned into a filled path with increasing levels of precision.
2654 At the lowest precision, the Quad stroke is approximated by a rectangle.
Cary Clark8032b982017-07-28 11:04:54 -04002655 At the highest precision, the filled path has high fidelity compared to the original stroke.
2656 ##
2657 void draw(SkCanvas* canvas) {
2658 SkPaint strokePaint;
2659 strokePaint.setAntiAlias(true);
2660 strokePaint.setStyle(SkPaint::kStroke_Style);
2661 strokePaint.setStrokeWidth(.1f);
2662 SkPath strokePath;
2663 strokePath.moveTo(.08f, .08f);
2664 strokePath.quadTo(.09f, .08f, .17f, .17f);
2665 SkPath fillPath;
2666 SkPaint outlinePaint(strokePaint);
2667 outlinePaint.setStrokeWidth(2);
2668 SkMatrix scale = SkMatrix::MakeScale(300, 300);
2669 for (SkScalar precision : { 0.01f, .1f, 1.f, 10.f, 100.f } ) {
2670 strokePaint.getFillPath(strokePath, &fillPath, nullptr, precision);
2671 fillPath.transform(scale);
2672 canvas->drawPath(fillPath, outlinePaint);
2673 canvas->translate(60, 0);
2674 if (1.f == precision) canvas->translate(-180, 100);
2675 }
2676 strokePath.transform(scale);
2677 strokePaint.setStrokeWidth(30);
2678 canvas->drawPath(strokePath, strokePaint);
2679 }
2680 ##
2681
2682##
2683
2684#Method bool getFillPath(const SkPath& src, SkPath* dst) const
2685
2686 The filled equivalent of the stroked path.
2687
2688 Replaces dst with the src path modified by Path_Effect and Style_Stroke.
2689 Path_Effect, if any, is not culled. Stroke_Width is created with default precision.
2690
2691 #Param src Path read to create a filled version ##
2692 #Param dst resulting Path dst may be the same as src, but may not be nullptr ##
2693 #Return true if the path represents Style_Fill, or false if it represents Hairline ##
2694
2695 #Example
2696 #Height 128
2697 void draw(SkCanvas* canvas) {
2698 SkPaint paint;
2699 paint.setStyle(SkPaint::kStroke_Style);
2700 paint.setStrokeWidth(10);
2701 SkPath strokePath;
2702 strokePath.moveTo(20, 20);
2703 strokePath.lineTo(100, 100);
2704 canvas->drawPath(strokePath, paint);
2705 SkPath fillPath;
2706 paint.getFillPath(strokePath, &fillPath);
2707 paint.setStrokeWidth(2);
2708 canvas->translate(40, 0);
2709 canvas->drawPath(fillPath, paint);
2710 }
2711 ##
2712
2713##
2714
2715#SeeAlso Style_Stroke Stroke_Width Path_Effect
2716
2717#Topic ##
2718# ------------------------------------------------------------------------------
2719#Topic Shader_Methods
2720
2721Shader defines the colors used when drawing a shape.
2722Shader may be an image, a gradient, or a computed fill.
2723If Paint has no Shader, then Color fills the shape.
2724
2725Shader is modulated by Color_Alpha component of Color.
2726If Shader object defines only Color_Alpha, then Color modulated by Color_Alpha describes
2727the fill.
2728
2729The drawn transparency can be modified without altering Shader, by changing Color_Alpha.
2730
2731#Example
2732void draw(SkCanvas* canvas) {
2733 SkPaint paint;
2734 SkPoint center = { 50, 50 };
2735 SkScalar radius = 50;
2736 const SkColor colors[] = { 0xFFFFFFFF, 0xFF000000 };
2737 paint.setShader(SkGradientShader::MakeRadial(center, radius, colors,
2738 nullptr, SK_ARRAY_COUNT(colors), SkShader::kClamp_TileMode));
2739 for (SkScalar a : { 0.3f, 0.6f, 1.0f } ) {
2740 paint.setAlpha((int) (a * 255));
2741 canvas->drawCircle(center.fX, center.fY, radius, paint);
2742 canvas->translate(70, 70);
2743 }
2744}
2745##
2746
2747If Shader generates only Color_Alpha then all components of Color modulate the output.
2748
2749#Example
2750void draw(SkCanvas* canvas) {
2751 SkPaint paint;
2752 SkBitmap bitmap;
2753 bitmap.setInfo(SkImageInfo::MakeA8(5, 1), 5); // bitmap only contains alpha
2754 uint8_t pixels[5] = { 0x22, 0x55, 0x88, 0xBB, 0xFF };
2755 bitmap.setPixels(pixels);
2756 paint.setShader(SkShader::MakeBitmapShader(bitmap,
2757 SkShader::kMirror_TileMode, SkShader::kMirror_TileMode));
2758 for (SkColor c : { SK_ColorRED, SK_ColorBLUE, SK_ColorGREEN } ) {
2759 paint.setColor(c); // all components in color affect shader
2760 canvas->drawCircle(50, 50, 50, paint);
2761 canvas->translate(70, 70);
2762 }
2763}
2764##
2765
2766#Method SkShader* getShader() const
2767
2768 Optional colors used when filling a path, such as a gradient.
2769
2770 Does not alter Shader Reference_Count.
2771
2772 #Return Shader if previously set, nullptr otherwise ##
2773
2774 #Example
2775 void draw(SkCanvas* canvas) {
2776 SkPaint paint;
2777 SkDebugf("nullptr %c= shader\n", paint.getShader() ? '!' : '=');
2778 paint.setShader(SkShader::MakeEmptyShader());
2779 SkDebugf("nullptr %c= shader\n", paint.getShader() ? '!' : '=');
2780 }
2781
2782 #StdOut
2783 nullptr == shader
2784 nullptr != shader
2785 ##
2786 ##
2787
2788##
2789
2790#Method sk_sp<SkShader> refShader() const
2791
2792 Optional colors used when filling a path, such as a gradient.
2793
2794 Increases Shader Reference_Count by one.
2795
2796 #Return Shader if previously set, nullptr otherwise ##
2797
2798 #Example
2799 void draw(SkCanvas* canvas) {
2800 SkPaint paint1, paint2;
2801 paint1.setShader(SkShader::MakeEmptyShader());
2802 SkDebugf("shader unique: %s\n", paint1.getShader()->unique() ? "true" : "false");
2803 paint2.setShader(paint1.refShader());
2804 SkDebugf("shader unique: %s\n", paint1.getShader()->unique() ? "true" : "false");
2805 }
2806
2807 #StdOut
2808 shader unique: true
2809 shader unique: false
2810 ##
2811 ##
2812
2813##
2814
2815#Method void setShader(sk_sp<SkShader> shader)
2816
2817 Optional colors used when filling a path, such as a gradient.
2818
Cary Clarkd0530ba2017-09-14 11:25:39 -04002819 Sets Shader to shader, decreasing Reference_Count of the previous Shader.
Cary Clark6fc50412017-09-21 12:31:06 -04002820 Increments shader Reference_Count by one.
Cary Clark8032b982017-07-28 11:04:54 -04002821
2822 #Param shader how geometry is filled with color; if nullptr, Color is used instead ##
2823
2824 #Example
2825 #Height 64
2826 void draw(SkCanvas* canvas) {
2827 SkPaint paint;
2828 paint.setColor(SK_ColorBLUE);
2829 paint.setShader(SkShader::MakeColorShader(SK_ColorRED));
2830 canvas->drawRect(SkRect::MakeWH(40, 40), paint);
2831 paint.setShader(nullptr);
2832 canvas->translate(50, 0);
2833 canvas->drawRect(SkRect::MakeWH(40, 40), paint);
2834 }
2835 ##
2836
2837##
2838
2839#Topic ##
2840# ------------------------------------------------------------------------------
2841#Topic Color_Filter_Methods
2842
2843Color_Filter alters the color used when drawing a shape.
2844Color_Filter may apply Blend_Mode, transform the color through a matrix, or composite multiple filters.
2845If Paint has no Color_Filter, the color is unaltered.
2846
2847The drawn transparency can be modified without altering Color_Filter, by changing Color_Alpha.
2848
2849#Example
2850#Height 128
2851void draw(SkCanvas* canvas) {
2852 SkPaint paint;
2853 paint.setColorFilter(SkColorMatrixFilter::MakeLightingFilter(0xFFFFFF, 0xFF0000));
2854 for (SkColor c : { SK_ColorBLACK, SK_ColorGREEN } ) {
2855 paint.setColor(c);
2856 canvas->drawRect(SkRect::MakeXYWH(10, 10, 50, 50), paint);
2857 paint.setAlpha(0x80);
2858 canvas->drawRect(SkRect::MakeXYWH(60, 60, 50, 50), paint);
2859 canvas->translate(100, 0);
2860 }
2861}
2862##
2863
2864#Method SkColorFilter* getColorFilter() const
2865
2866 Returns Color_Filter if set, or nullptr.
2867 Does not alter Color_Filter Reference_Count.
2868
2869 #Return Color_Filter if previously set, nullptr otherwise ##
2870
2871 #Example
2872 void draw(SkCanvas* canvas) {
2873 SkPaint paint;
2874 SkDebugf("nullptr %c= color filter\n", paint.getColorFilter() ? '!' : '=');
2875 paint.setColorFilter(SkColorFilter::MakeModeFilter(SK_ColorLTGRAY, SkBlendMode::kSrcIn));
2876 SkDebugf("nullptr %c= color filter\n", paint.getColorFilter() ? '!' : '=');
2877 }
2878
2879 #StdOut
2880 nullptr == color filter
2881 nullptr != color filter
2882 ##
2883 ##
2884##
2885
2886#Method sk_sp<SkColorFilter> refColorFilter() const
2887
2888 Returns Color_Filter if set, or nullptr.
2889 Increases Color_Filter Reference_Count by one.
2890
2891 #Return Color_Filter if set, or nullptr ##
2892
2893 #Example
2894 void draw(SkCanvas* canvas) {
2895 SkPaint paint1, paint2;
2896 paint1.setColorFilter(SkColorFilter::MakeModeFilter(0xFFFF0000, SkBlendMode::kSrcATop));
2897 SkDebugf("color filter unique: %s\n", paint1.getColorFilter()->unique() ? "true" : "false");
2898 paint2.setColorFilter(paint1.refColorFilter());
2899 SkDebugf("color filter unique: %s\n", paint1.getColorFilter()->unique() ? "true" : "false");
2900 }
2901
2902 #StdOut
2903 color filter unique: true
2904 color filter unique: false
2905 ##
2906 ##
2907##
2908
2909#Method void setColorFilter(sk_sp<SkColorFilter> colorFilter)
2910
Cary Clark6fc50412017-09-21 12:31:06 -04002911Sets Color_Filter to filter, decreasing Reference_Count of the previous
2912Color_Filter. Pass nullptr to clear Color_Filter.
2913
2914Increments filter Reference_Count by one.
Cary Clark8032b982017-07-28 11:04:54 -04002915
2916 #Param colorFilter Color_Filter to apply to subsequent draw ##
2917
2918 #Example
2919 #Height 64
2920 void draw(SkCanvas* canvas) {
2921 SkPaint paint;
2922 paint.setColorFilter(SkColorFilter::MakeModeFilter(SK_ColorLTGRAY, SkBlendMode::kSrcIn));
2923 canvas->drawRect(SkRect::MakeWH(50, 50), paint);
2924 paint.setColorFilter(nullptr);
2925 canvas->translate(70, 0);
2926 canvas->drawRect(SkRect::MakeWH(50, 50), paint);
2927 }
2928 ##
2929
2930##
2931
2932#Topic ##
2933# ------------------------------------------------------------------------------
2934#Topic Blend_Mode_Methods
2935
2936Blend_Mode describes how Color combines with the destination color.
2937The default setting, SkBlendMode::kSrcOver, draws the source color
2938over the destination color.
2939
2940#Example
2941void draw(SkCanvas* canvas) {
2942 SkPaint normal, blender;
2943 normal.setColor(0xFF58a889);
2944 blender.setColor(0xFF8958a8);
2945 canvas->clear(0);
2946 for (SkBlendMode m : { SkBlendMode::kSrcOver, SkBlendMode::kSrcIn, SkBlendMode::kSrcOut } ) {
2947 normal.setBlendMode(SkBlendMode::kSrcOver);
2948 canvas->drawOval(SkRect::MakeXYWH(30, 30, 30, 80), normal);
2949 blender.setBlendMode(m);
2950 canvas->drawOval(SkRect::MakeXYWH(10, 50, 80, 30), blender);
2951 canvas->translate(70, 70);
2952 }
2953}
2954##
2955
2956#SeeAlso Blend_Mode
2957
2958#Method SkBlendMode getBlendMode() const
2959
2960 Returns Blend_Mode.
Cary Clark579985c2017-07-31 11:48:27 -04002961 By default, returns SkBlendMode::kSrcOver.
Cary Clark8032b982017-07-28 11:04:54 -04002962
2963 #Return mode used to combine source color with destination color ##
2964
2965 #Example
2966 void draw(SkCanvas* canvas) {
2967 SkPaint paint;
2968 SkDebugf("kSrcOver %c= getBlendMode\n",
2969 SkBlendMode::kSrcOver == paint.getBlendMode() ? '=' : '!');
2970 paint.setBlendMode(SkBlendMode::kSrc);
2971 SkDebugf("kSrcOver %c= getBlendMode\n",
2972 SkBlendMode::kSrcOver == paint.getBlendMode() ? '=' : '!');
2973 }
2974
2975 #StdOut
2976 kSrcOver == getBlendMode
2977 kSrcOver != getBlendMode
2978 ##
2979 ##
2980
2981##
2982
2983#Method bool isSrcOver() const
2984
2985 Returns true if Blend_Mode is SkBlendMode::kSrcOver, the default.
2986
2987 #Return true if Blend_Mode is SkBlendMode::kSrcOver ##
2988
2989 #Example
2990 void draw(SkCanvas* canvas) {
2991 SkPaint paint;
2992 SkDebugf("isSrcOver %c= true\n", paint.isSrcOver() ? '=' : '!');
2993 paint.setBlendMode(SkBlendMode::kSrc);
2994 SkDebugf("isSrcOver %c= true\n", paint.isSrcOver() ? '=' : '!');
2995 }
2996
2997 #StdOut
2998 isSrcOver == true
2999 isSrcOver != true
3000 ##
3001 ##
3002
3003##
3004
3005#Method void setBlendMode(SkBlendMode mode)
3006
3007 Sets Blend_Mode to mode.
3008 Does not check for valid input.
3009
3010 #Param mode SkBlendMode used to combine source color and destination ##
3011
3012 #Example
3013 void draw(SkCanvas* canvas) {
3014 SkPaint paint;
3015 SkDebugf("isSrcOver %c= true\n", paint.isSrcOver() ? '=' : '!');
3016 paint.setBlendMode(SkBlendMode::kSrc);
3017 SkDebugf("isSrcOver %c= true\n", paint.isSrcOver() ? '=' : '!');
3018 }
3019
3020 #StdOut
3021 isSrcOver == true
3022 isSrcOver != true
3023 ##
3024 ##
3025
3026##
3027
3028#Topic ##
3029# ------------------------------------------------------------------------------
3030#Topic Path_Effect_Methods
3031
3032Path_Effect modifies the path geometry before drawing it.
3033Path_Effect may implement dashing, custom fill effects and custom stroke effects.
3034If Paint has no Path_Effect, the path geometry is unaltered when filled or stroked.
3035
3036#Example
3037#Height 160
3038 void draw(SkCanvas* canvas) {
3039 SkPaint paint;
3040 paint.setStyle(SkPaint::kStroke_Style);
3041 paint.setStrokeWidth(16);
3042 SkScalar intervals[] = {30, 10};
3043 paint.setPathEffect(SkDashPathEffect::Make(intervals, SK_ARRAY_COUNT(intervals), 1));
3044 canvas->drawRoundRect({20, 20, 120, 120}, 20, 20, paint);
3045 }
3046##
3047
3048#SeeAlso Path_Effect
3049
3050#Method SkPathEffect* getPathEffect() const
3051
3052 Returns Path_Effect if set, or nullptr.
3053 Does not alter Path_Effect Reference_Count.
3054
3055 #Return Path_Effect if previously set, nullptr otherwise ##
3056
3057 #Example
3058 void draw(SkCanvas* canvas) {
3059 SkPaint paint;
3060 SkDebugf("nullptr %c= path effect\n", paint.getPathEffect() ? '!' : '=');
3061 paint.setPathEffect(SkCornerPathEffect::Make(10));
3062 SkDebugf("nullptr %c= path effect\n", paint.getPathEffect() ? '!' : '=');
3063 }
3064
3065 #StdOut
3066 nullptr == path effect
3067 nullptr != path effect
3068 ##
3069 ##
3070
3071##
3072
3073
3074#Method sk_sp<SkPathEffect> refPathEffect() const
3075
3076 Returns Path_Effect if set, or nullptr.
3077 Increases Path_Effect Reference_Count by one.
3078
3079 #Return Path_Effect if previously set, nullptr otherwise ##
3080
3081 #Example
3082 void draw(SkCanvas* canvas) {
3083 SkPaint paint1, paint2;
Cary Clarka560c472017-11-27 10:44:06 -05003084 SkScalar intervals[] = {1, 2};
3085 paint1.setPathEffect(SkDashPathEffect::Make(intervals, SK_ARRAY_COUNT(intervals), 10));
Cary Clark8032b982017-07-28 11:04:54 -04003086 SkDebugf("path effect unique: %s\n", paint1.getPathEffect()->unique() ? "true" : "false");
3087 paint2.setPathEffect(paint1.refPathEffect());
3088 SkDebugf("path effect unique: %s\n", paint1.getPathEffect()->unique() ? "true" : "false");
3089 }
3090
3091 #StdOut
3092 path effect unique: true
3093 path effect unique: false
3094 ##
3095 ##
3096
3097##
3098
3099
3100#Method void setPathEffect(sk_sp<SkPathEffect> pathEffect)
3101
Cary Clark6fc50412017-09-21 12:31:06 -04003102Sets Path_Effect to pathEffect, decreasing Reference_Count of the previous
3103Path_Effect. Pass nullptr to leave the path geometry unaltered.
3104
3105Increments pathEffect Reference_Count by one.
Cary Clark8032b982017-07-28 11:04:54 -04003106
3107 #Param pathEffect replace Path with a modification when drawn ##
3108
3109 #Example
3110 void draw(SkCanvas* canvas) {
3111 SkPaint paint;
3112 paint.setPathEffect(SkDiscretePathEffect::Make(3, 5));
3113 canvas->drawRect(SkRect::MakeXYWH(40, 40, 175, 175), paint);
3114 }
3115 ##
3116
3117##
3118
3119#Topic ##
3120# ------------------------------------------------------------------------------
3121#Topic Mask_Filter_Methods
3122
Cary Clarkce101242017-09-01 15:51:02 -04003123Mask_Filter uses coverage of the shape drawn to create Mask_Alpha.
Mike Reed8ad91a92018-01-19 19:09:32 -05003124Mask_Filter takes a Mask, and returns a Mask.
Cary Clark6fc50412017-09-21 12:31:06 -04003125
3126Mask_Filter may change the geometry and transparency of the shape, such as
3127creating a blur effect. Set Mask_Filter to nullptr to prevent Mask_Filter from
3128modifying the draw.
Cary Clark8032b982017-07-28 11:04:54 -04003129
3130#Example
3131 void draw(SkCanvas* canvas) {
3132 SkPaint paint;
3133 paint.setMaskFilter(SkBlurMaskFilter::Make(kSolid_SkBlurStyle, 3));
3134 canvas->drawRect(SkRect::MakeXYWH(40, 40, 175, 175), paint);
3135 }
3136##
3137
3138#Method SkMaskFilter* getMaskFilter() const
3139
3140 Returns Mask_Filter if set, or nullptr.
3141 Does not alter Mask_Filter Reference_Count.
3142
3143 #Return Mask_Filter if previously set, nullptr otherwise ##
3144
3145 #Example
3146 void draw(SkCanvas* canvas) {
3147 SkPaint paint;
3148 SkDebugf("nullptr %c= mask filter\n", paint.getMaskFilter() ? '!' : '=');
3149 paint.setMaskFilter(SkBlurMaskFilter::Make(kOuter_SkBlurStyle, 3));
3150 SkDebugf("nullptr %c= mask filter\n", paint.getMaskFilter() ? '!' : '=');
3151 }
3152
3153 #StdOut
3154 nullptr == mask filter
3155 nullptr != mask filter
3156 ##
3157 ##
3158
3159##
3160
3161#Method sk_sp<SkMaskFilter> refMaskFilter() const
3162
3163 Returns Mask_Filter if set, or nullptr.
Cary Clark6fc50412017-09-21 12:31:06 -04003164
Cary Clark8032b982017-07-28 11:04:54 -04003165 Increases Mask_Filter Reference_Count by one.
3166
3167 #Return Mask_Filter if previously set, nullptr otherwise ##
3168
3169 #Example
3170 void draw(SkCanvas* canvas) {
3171 SkPaint paint1, paint2;
3172 paint1.setMaskFilter(SkBlurMaskFilter::Make(kNormal_SkBlurStyle, 1));
3173 SkDebugf("mask filter unique: %s\n", paint1.getMaskFilter()->unique() ? "true" : "false");
3174 paint2.setMaskFilter(paint1.refMaskFilter());
3175 SkDebugf("mask filter unique: %s\n", paint1.getMaskFilter()->unique() ? "true" : "false");
3176 }
3177
3178 #StdOut
3179 mask filter unique: true
3180 mask filter unique: false
3181 ##
3182 ##
3183
3184##
3185
3186#Method void setMaskFilter(sk_sp<SkMaskFilter> maskFilter)
3187
Cary Clark6fc50412017-09-21 12:31:06 -04003188Sets Mask_Filter to maskFilter, decreasing Reference_Count of the previous
3189Mask_Filter. Pass nullptr to clear Mask_Filter and leave Mask_Filter effect on
3190Mask_Alpha unaltered.
3191
Cary Clark6fc50412017-09-21 12:31:06 -04003192Increments maskFilter Reference_Count by one.
Cary Clark8032b982017-07-28 11:04:54 -04003193
3194 #Param maskFilter modifies clipping mask generated from drawn geometry ##
3195
3196 #Example
3197 void draw(SkCanvas* canvas) {
3198 SkPaint paint;
3199 paint.setStyle(SkPaint::kStroke_Style);
3200 paint.setStrokeWidth(10);
3201 paint.setMaskFilter(SkBlurMaskFilter::Make(kNormal_SkBlurStyle, 10));
3202 canvas->drawRect(SkRect::MakeXYWH(40, 40, 175, 175), paint);
3203 }
3204 ##
3205
3206##
3207
3208#Topic ##
3209# ------------------------------------------------------------------------------
3210#Topic Typeface_Methods
3211
3212Typeface identifies the font used when drawing and measuring text.
3213Typeface may be specified by name, from a file, or from a data stream.
3214The default Typeface defers to the platform-specific default font
3215implementation.
3216
3217#Example
3218#Height 100
3219 void draw(SkCanvas* canvas) {
3220 SkPaint paint;
Ben Wagner700ff172017-11-08 15:37:22 -05003221 paint.setTypeface(SkTypeface::MakeFromName(nullptr, SkFontStyle()));
Cary Clark8032b982017-07-28 11:04:54 -04003222 paint.setAntiAlias(true);
3223 paint.setTextSize(36);
3224 canvas->drawString("A Big Hello!", 10, 40, paint);
3225 paint.setTypeface(nullptr);
3226 paint.setFakeBoldText(true);
3227 canvas->drawString("A Big Hello!", 10, 80, paint);
3228 }
3229##
3230
3231#Method SkTypeface* getTypeface() const
3232
3233 Returns Typeface if set, or nullptr.
Cary Clark6fc50412017-09-21 12:31:06 -04003234 Increments Typeface Reference_Count by one.
Cary Clark8032b982017-07-28 11:04:54 -04003235
3236 #Return Typeface if previously set, nullptr otherwise ##
3237
3238 #Example
3239 void draw(SkCanvas* canvas) {
3240 SkPaint paint;
3241 SkDebugf("nullptr %c= typeface\n", paint.getTypeface() ? '!' : '=');
Cary Clark71961fb2018-01-05 14:21:59 -05003242 paint.setTypeface(SkTypeface::MakeFromName("monospace", SkFontStyle()));
Cary Clark8032b982017-07-28 11:04:54 -04003243 SkDebugf("nullptr %c= typeface\n", paint.getTypeface() ? '!' : '=');
3244 }
3245
3246 #StdOut
3247 nullptr == typeface
3248 nullptr != typeface
3249 ##
3250 ##
3251
3252##
3253
3254#Method sk_sp<SkTypeface> refTypeface() const
3255
3256 Increases Typeface Reference_Count by one.
3257
3258 #Return Typeface if previously set, nullptr otherwise ##
3259
3260 #Example
3261 void draw(SkCanvas* canvas) {
3262 SkPaint paint1, paint2;
Cary Clark71961fb2018-01-05 14:21:59 -05003263 paint1.setTypeface(SkTypeface::MakeFromName("monospace",
Cary Clark8032b982017-07-28 11:04:54 -04003264 SkFontStyle(SkFontStyle::kNormal_Weight, SkFontStyle::kNormal_Width,
3265 SkFontStyle::kItalic_Slant)));
3266 SkDebugf("typeface1 %c= typeface2\n",
3267 paint1.getTypeface() == paint2.getTypeface() ? '=' : '!');
3268 paint2.setTypeface(paint1.refTypeface());
3269 SkDebugf("typeface1 %c= typeface2\n",
3270 paint1.getTypeface() == paint2.getTypeface() ? '=' : '!');
3271 }
3272
3273 #StdOut
3274 typeface1 != typeface2
3275 typeface1 == typeface2
3276 ##
3277 ##
3278
3279##
3280
3281#Method void setTypeface(sk_sp<SkTypeface> typeface)
3282
Cary Clark6fc50412017-09-21 12:31:06 -04003283Sets Typeface to typeface, decreasing Reference_Count of the previous Typeface.
3284Pass nullptr to clear Typeface and use the default typeface. Increments
3285typeface Reference_Count by one.
Cary Clark8032b982017-07-28 11:04:54 -04003286
3287 #Param typeface font and style used to draw text ##
3288
3289 #Example
3290 #Height 64
3291 void draw(SkCanvas* canvas) {
3292 SkPaint paint;
Cary Clark71961fb2018-01-05 14:21:59 -05003293 paint.setTypeface(SkTypeface::MakeFromName("monospace", SkFontStyle()));
3294 canvas->drawString("hamburgerfons", 10, 30, paint);
Cary Clark8032b982017-07-28 11:04:54 -04003295 paint.setTypeface(nullptr);
Cary Clark71961fb2018-01-05 14:21:59 -05003296 canvas->drawString("hamburgerfons", 10, 50, paint);
Cary Clark8032b982017-07-28 11:04:54 -04003297 }
3298 ##
3299
3300##
3301
3302#Topic ##
3303# ------------------------------------------------------------------------------
Cary Clark8032b982017-07-28 11:04:54 -04003304#Topic Image_Filter_Methods
3305
3306Image_Filter operates on the pixel representation of the shape, as modified by Paint
3307with Blend_Mode set to SkBlendMode::kSrcOver. Image_Filter creates a new bitmap,
3308which is drawn to the device using the set Blend_Mode.
Cary Clark6fc50412017-09-21 12:31:06 -04003309
Cary Clark8032b982017-07-28 11:04:54 -04003310Image_Filter is higher level than Mask_Filter; for instance, an Image_Filter
Cary Clarkce101242017-09-01 15:51:02 -04003311can operate on all channels of Color, while Mask_Filter generates Alpha only.
Cary Clark8032b982017-07-28 11:04:54 -04003312Image_Filter operates independently of and can be used in combination with
Mike Reed8ad91a92018-01-19 19:09:32 -05003313Mask_Filter.
Cary Clark8032b982017-07-28 11:04:54 -04003314
3315#Example
3316 #ToDo explain why the two draws are so different ##
3317 void draw(SkCanvas* canvas) {
3318 SkPaint paint;
3319 paint.setStyle(SkPaint::kStroke_Style);
3320 paint.setStrokeWidth(2);
3321 SkRegion region;
3322 region.op( 10, 10, 50, 50, SkRegion::kUnion_Op);
3323 region.op( 10, 50, 90, 90, SkRegion::kUnion_Op);
Cary Clarka560c472017-11-27 10:44:06 -05003324 paint.setImageFilter(SkBlurImageFilter::Make(5.0f, 5.0f, nullptr));
Cary Clark8032b982017-07-28 11:04:54 -04003325 canvas->drawRegion(region, paint);
3326 paint.setImageFilter(nullptr);
3327 paint.setMaskFilter(SkBlurMaskFilter::Make(kNormal_SkBlurStyle, 5));
3328 canvas->translate(100, 100);
3329 canvas->drawRegion(region, paint);
3330 }
3331##
3332
3333#Method SkImageFilter* getImageFilter() const
3334
3335 Returns Image_Filter if set, or nullptr.
3336 Does not alter Image_Filter Reference_Count.
3337
3338 #Return Image_Filter if previously set, nullptr otherwise ##
3339
3340 #Example
3341 void draw(SkCanvas* canvas) {
3342 SkPaint paint;
3343 SkDebugf("nullptr %c= image filter\n", paint.getImageFilter() ? '!' : '=');
Cary Clarka560c472017-11-27 10:44:06 -05003344 paint.setImageFilter(SkBlurImageFilter::Make(kOuter_SkBlurStyle, 3, nullptr, nullptr));
Cary Clark8032b982017-07-28 11:04:54 -04003345 SkDebugf("nullptr %c= image filter\n", paint.getImageFilter() ? '!' : '=');
3346 }
3347
3348 #StdOut
3349 nullptr == image filter
3350 nullptr != image filter
3351 ##
3352 ##
3353
3354##
3355
3356#Method sk_sp<SkImageFilter> refImageFilter() const
3357
3358 Returns Image_Filter if set, or nullptr.
3359 Increases Image_Filter Reference_Count by one.
3360
3361 #Return Image_Filter if previously set, nullptr otherwise ##
3362
3363 #Example
3364 void draw(SkCanvas* canvas) {
3365 SkPaint paint1, paint2;
3366 paint1.setImageFilter(SkOffsetImageFilter::Make(25, 25, nullptr));
3367 SkDebugf("image filter unique: %s\n", paint1.getImageFilter()->unique() ? "true" : "false");
3368 paint2.setImageFilter(paint1.refImageFilter());
3369 SkDebugf("image filter unique: %s\n", paint1.getImageFilter()->unique() ? "true" : "false");
3370 }
3371
3372 #StdOut
3373 image filter unique: true
3374 image filter unique: false
3375 ##
3376 ##
3377
3378##
3379
3380#Method void setImageFilter(sk_sp<SkImageFilter> imageFilter)
3381
Cary Clark6fc50412017-09-21 12:31:06 -04003382Sets Image_Filter to imageFilter, decreasing Reference_Count of the previous
3383Image_Filter. Pass nullptr to clear Image_Filter, and remove Image_Filter effect
3384on drawing.
3385
Cary Clark6fc50412017-09-21 12:31:06 -04003386Increments imageFilter Reference_Count by one.
Cary Clark8032b982017-07-28 11:04:54 -04003387
3388 #Param imageFilter how Image is sampled when transformed ##
3389
3390 #Example
3391 #Height 160
3392 void draw(SkCanvas* canvas) {
3393 SkBitmap bitmap;
3394 bitmap.allocN32Pixels(100, 100);
3395 SkCanvas offscreen(bitmap);
3396 SkPaint paint;
3397 paint.setAntiAlias(true);
3398 paint.setColor(SK_ColorWHITE);
3399 paint.setTextSize(96);
3400 offscreen.clear(0);
3401 offscreen.drawString("e", 20, 70, paint);
3402 paint.setImageFilter(
3403 SkLightingImageFilter::MakePointLitDiffuse(SkPoint3::Make(80, 100, 10),
3404 SK_ColorWHITE, 1, 2, nullptr, nullptr));
3405 canvas->drawBitmap(bitmap, 0, 0, &paint);
3406 }
3407 ##
3408
3409##
3410
3411#Topic ##
3412# ------------------------------------------------------------------------------
3413#Topic Draw_Looper_Methods
3414
3415Draw_Looper sets a modifier that communicates state from one Draw_Layer
3416to another to construct the draw.
Cary Clark6fc50412017-09-21 12:31:06 -04003417
Cary Clark8032b982017-07-28 11:04:54 -04003418Draw_Looper draws one or more times, modifying the canvas and paint each time.
3419Draw_Looper may be used to draw multiple colors or create a colored shadow.
3420Set Draw_Looper to nullptr to prevent Draw_Looper from modifying the draw.
3421
3422#Example
3423#Height 128
3424 void draw(SkCanvas* canvas) {
3425 SkLayerDrawLooper::LayerInfo info;
3426 info.fPaintBits = (SkLayerDrawLooper::BitFlags) SkLayerDrawLooper::kColorFilter_Bit;
3427 info.fColorMode = SkBlendMode::kSrc;
3428 SkLayerDrawLooper::Builder looperBuilder;
3429 SkPaint* loopPaint = looperBuilder.addLayer(info);
3430 loopPaint->setColor(SK_ColorRED);
3431 info.fOffset.set(20, 20);
3432 loopPaint = looperBuilder.addLayer(info);
3433 loopPaint->setColor(SK_ColorBLUE);
3434 SkPaint paint;
3435 paint.setDrawLooper(looperBuilder.detach());
3436 canvas->drawCircle(50, 50, 50, paint);
3437 }
3438
3439##
3440
3441#Method SkDrawLooper* getDrawLooper() const
3442
3443 Returns Draw_Looper if set, or nullptr.
3444 Does not alter Draw_Looper Reference_Count.
3445
3446 #Return Draw_Looper if previously set, nullptr otherwise ##
3447
3448 #Example
3449 void draw(SkCanvas* canvas) {
3450 SkPaint paint;
3451 SkDebugf("nullptr %c= draw looper\n", paint.getDrawLooper() ? '!' : '=');
3452 SkLayerDrawLooper::Builder looperBuilder;
3453 paint.setDrawLooper(looperBuilder.detach());
3454 SkDebugf("nullptr %c= draw looper\n", paint.getDrawLooper() ? '!' : '=');
3455 }
3456
3457 #StdOut
3458 nullptr == draw looper
3459 nullptr != draw looper
3460 ##
3461 ##
3462
3463##
3464
3465#Method sk_sp<SkDrawLooper> refDrawLooper() const
3466
3467 Returns Draw_Looper if set, or nullptr.
3468 Increases Draw_Looper Reference_Count by one.
3469
3470 #Return Draw_Looper if previously set, nullptr otherwise ##
3471
3472 #Example
3473 void draw(SkCanvas* canvas) {
3474 SkPaint paint1, paint2;
3475 SkLayerDrawLooper::Builder looperBuilder;
3476 paint1.setDrawLooper(looperBuilder.detach());
3477 SkDebugf("draw looper unique: %s\n", paint1.getDrawLooper()->unique() ? "true" : "false");
3478 paint2.setDrawLooper(paint1.refDrawLooper());
3479 SkDebugf("draw looper unique: %s\n", paint1.getDrawLooper()->unique() ? "true" : "false");
3480 }
3481
3482 #StdOut
3483 draw looper unique: true
3484 draw looper unique: false
3485 ##
3486 ##
3487
3488##
3489
3490#Method SkDrawLooper* getLooper() const
3491
3492Deprecated.
3493
3494#Deprecated
3495(see bug.skia.org/6259)
3496#Deprecated ##
3497
3498#Return Draw_Looper if previously set, nullptr otherwise ##
3499##
3500
3501#Method void setDrawLooper(sk_sp<SkDrawLooper> drawLooper)
3502
Cary Clark6fc50412017-09-21 12:31:06 -04003503Sets Draw_Looper to drawLooper, decreasing Reference_Count of the previous
3504drawLooper. Pass nullptr to clear Draw_Looper and leave Draw_Looper effect on
3505drawing unaltered.
3506
3507Increments drawLooper Reference_Count by one.
Cary Clark8032b982017-07-28 11:04:54 -04003508
Cary Clarka523d2d2017-08-30 08:58:10 -04003509 #Param drawLooper iterates through drawing one or more time, altering Paint ##
Cary Clark8032b982017-07-28 11:04:54 -04003510
3511 #Example
3512 #Height 128
3513 void draw(SkCanvas* canvas) {
3514 SkPaint paint;
3515 paint.setDrawLooper(SkBlurDrawLooper::Make(0x7FFF0000, 4, -5, -10));
3516 paint.setStyle(SkPaint::kStroke_Style);
3517 paint.setStrokeWidth(10);
3518 paint.setAntiAlias(true);
3519 paint.setColor(0x7f0000ff);
3520 canvas->drawCircle(70, 70, 50, paint);
3521 }
3522 ##
3523
3524##
3525
3526#Method void setLooper(sk_sp<SkDrawLooper> drawLooper)
3527
3528Deprecated.
3529
3530#Deprecated
3531(see bug.skia.org/6259)
3532#Deprecated ##
3533
3534#Param drawLooper sets Draw_Looper to drawLooper ##
3535
3536##
3537
3538#Topic ##
3539# ------------------------------------------------------------------------------
3540#Topic Text_Align
3541
3542#Enum Align
3543#Code
3544 enum Align {
3545 kLeft_Align,
3546 kCenter_Align,
3547 kRight_Align,
3548 };
3549##
3550
3551Align adjusts the text relative to the text position.
Cary Clarkce101242017-09-01 15:51:02 -04003552Align affects Glyphs drawn with: SkCanvas::drawText, SkCanvas::drawPosText,
Cary Clark8032b982017-07-28 11:04:54 -04003553SkCanvas::drawPosTextH, SkCanvas::drawTextOnPath,
3554SkCanvas::drawTextOnPathHV, SkCanvas::drawTextRSXform, SkCanvas::drawTextBlob,
3555and SkCanvas::drawString;
Cary Clarkce101242017-09-01 15:51:02 -04003556as well as calls that place text Glyphs like getTextWidths and getTextPath.
Cary Clark8032b982017-07-28 11:04:54 -04003557
3558The text position is set by the font for both horizontal and vertical text.
3559Typically, for horizontal text, the position is to the left side of the glyph on the
3560base line; and for vertical text, the position is the horizontal center of the glyph
3561at the caps height.
3562
3563Align adjusts the glyph position to center it or move it to abut the position
3564using the metrics returned by the font.
3565
3566Align defaults to kLeft_Align.
3567
3568#Const kLeft_Align 0
3569 Leaves the glyph at the position computed by the font offset by the text position.
3570##
3571
3572#Const kCenter_Align 1
3573 Moves the glyph half its width if Flags has kVerticalText_Flag clear, and
3574 half its height if Flags has kVerticalText_Flag set.
3575##
3576
3577#Const kRight_Align 2
3578 Moves the glyph by its width if Flags has kVerticalText_Flag clear,
3579 and by its height if Flags has kVerticalText_Flag set.
3580##
3581
3582#Enum ##
3583
3584#Enum
3585
3586#Code
3587 enum {
Cary Clarkbad5ad72017-08-03 17:14:08 -04003588 kAlignCount = 3,
Cary Clark8032b982017-07-28 11:04:54 -04003589 };
3590##
3591
3592#Const kAlignCount 3
3593 The number of different Text_Align values defined.
3594##
3595
3596#Enum ##
3597
3598#Example
3599 #Height 160
3600 #Description
3601 Each position separately moves the glyph in drawPosText.
3602 ##
3603 void draw(SkCanvas* canvas) {
3604 SkPaint paint;
3605 paint.setTextSize(40);
3606 SkPoint position[] = {{100, 50}, {150, 40}};
3607 for (SkPaint::Align a : { SkPaint::kLeft_Align,
3608 SkPaint::kCenter_Align,
3609 SkPaint::kRight_Align}) {
3610 paint.setTextAlign(a);
3611 canvas->drawPosText("Aa", 2, position, paint);
3612 canvas->translate(0, 50);
3613 }
3614 }
3615##
3616
3617#Example
3618 #Height 160
3619 #Description
3620 Vertical_Text treats kLeft_Align as top align, and kRight_Align as bottom align.
3621 ##
3622 void draw(SkCanvas* canvas) {
3623 SkPaint paint;
3624 paint.setTextSize(40);
3625 paint.setVerticalText(true);
3626 for (SkPaint::Align a : { SkPaint::kLeft_Align,
3627 SkPaint::kCenter_Align,
3628 SkPaint::kRight_Align }) {
3629 paint.setTextAlign(a);
3630 canvas->drawString("Aa", 50, 80, paint);
3631 canvas->translate(50, 0);
3632 }
3633 }
3634##
3635
3636#Method Align getTextAlign() const
3637
3638 Returns Text_Align.
3639 Returns kLeft_Align if Text_Align has not been set.
3640
3641 #Return text placement relative to position ##
3642
3643 #Example
3644 SkPaint paint;
3645 SkDebugf("kLeft_Align %c= default\n", SkPaint::kLeft_Align == paint.getTextAlign() ? '=' : '!');
3646
3647 #StdOut
3648 kLeft_Align == default
3649 ##
3650 ##
3651##
3652
3653#Method void setTextAlign(Align align)
3654
3655 Sets Text_Align to align.
3656 Has no effect if align is an invalid value.
3657
3658 #Param align text placement relative to position ##
3659
3660 #Example
3661 #Height 160
3662 #Description
3663 Text is left-aligned by default, and then set to center. Setting the
3664 alignment out of range has no effect.
3665 ##
3666 void draw(SkCanvas* canvas) {
3667 SkPaint paint;
3668 paint.setTextSize(40);
3669 canvas->drawString("Aa", 100, 50, paint);
3670 paint.setTextAlign(SkPaint::kCenter_Align);
3671 canvas->drawString("Aa", 100, 100, paint);
3672 paint.setTextAlign((SkPaint::Align) SkPaint::kAlignCount);
3673 canvas->drawString("Aa", 100, 150, paint);
3674 }
3675 ##
3676
3677##
3678
3679#Topic ##
3680# ------------------------------------------------------------------------------
3681#Topic Text_Size
3682
3683Text_Size adjusts the overall text size in points.
3684Text_Size can be set to any positive value or zero.
3685Text_Size defaults to 12.
3686Set SkPaintDefaults_TextSize at compile time to change the default setting.
3687
3688#Example
3689#Height 135
3690 void draw(SkCanvas* canvas) {
3691 SkPaint paint;
3692 canvas->drawString("12 point", 10, 20, paint);
3693 paint.setTextSize(24);
3694 canvas->drawString("24 point", 10, 60, paint);
3695 paint.setTextSize(48);
3696 canvas->drawString("48 point", 10, 120, paint);
3697 }
3698##
3699
3700#Method SkScalar getTextSize() const
3701
3702 Returns Text_Size in points.
3703
3704 #Return typographic height of text ##
3705
3706 #Example
3707 SkPaint paint;
3708 SkDebugf("12 %c= default text size\n", 12 == paint.getTextSize() ? '=' : '!');
3709 ##
3710
3711##
3712
3713#Method void setTextSize(SkScalar textSize)
3714
3715 Sets Text_Size in points.
3716 Has no effect if textSize is not greater than or equal to zero.
3717
3718 #Param textSize typographic height of text ##
3719
3720 #Example
3721 SkPaint paint;
3722 SkDebugf("12 %c= text size\n", 12 == paint.getTextSize() ? '=' : '!');
3723 paint.setTextSize(-20);
3724 SkDebugf("12 %c= text size\n", 12 == paint.getTextSize() ? '=' : '!');
3725 ##
3726
3727##
3728
3729#Topic ##
3730# ------------------------------------------------------------------------------
3731#Topic Text_Scale_X
3732
3733Text_Scale_X adjusts the text horizontal scale.
3734Text scaling approximates condensed and expanded type faces when the actual face
3735is not available.
3736Text_Scale_X can be set to any value.
3737Text_Scale_X defaults to 1.
3738
3739#Example
3740#Height 128
3741 void draw(SkCanvas* canvas) {
3742 SkPaint paint;
3743 paint.setAntiAlias(true);
3744 paint.setTextSize(24);
3745 paint.setTextScaleX(.8f);
3746 canvas->drawString("narrow", 10, 20, paint);
3747 paint.setTextScaleX(1);
3748 canvas->drawString("normal", 10, 60, paint);
3749 paint.setTextScaleX(1.2f);
3750 canvas->drawString("wide", 10, 100, paint);
3751 }
3752##
3753
3754#Method SkScalar getTextScaleX() const
3755
3756 Returns Text_Scale_X.
3757 Default value is 1.
3758
3759 #Return text horizontal scale ##
3760
3761 #Example
3762 SkPaint paint;
3763 SkDebugf("1 %c= default text scale x\n", 1 == paint.getTextScaleX() ? '=' : '!');
3764 ##
3765
3766##
3767
3768
3769#Method void setTextScaleX(SkScalar scaleX)
3770
3771 Sets Text_Scale_X.
3772 Default value is 1.
3773
3774 #Param scaleX text horizontal scale ##
3775
3776 #Example
3777 SkPaint paint;
3778 paint.setTextScaleX(0.f / 0.f);
3779 SkDebugf("text scale %s-a-number\n", SkScalarIsNaN(paint.getTextScaleX()) ? "not" : "is");
3780 ##
3781
3782##
3783
3784#Topic ##
3785
3786#Topic Text_Skew_X
3787
3788
3789Text_Skew_X adjusts the text horizontal slant.
3790Text skewing approximates italic and oblique type faces when the actual face
3791is not available.
3792Text_Skew_X can be set to any value.
3793Text_Skew_X defaults to 0.
3794
3795#Example
3796#Height 128
3797 void draw(SkCanvas* canvas) {
3798 SkPaint paint;
3799 paint.setAntiAlias(true);
3800 paint.setTextSize(24);
3801 paint.setTextSkewX(-.25f);
3802 canvas->drawString("right-leaning", 10, 100, paint);
3803 paint.setTextSkewX(0);
3804 canvas->drawString("normal", 10, 60, paint);
3805 paint.setTextSkewX(.25f);
3806 canvas->drawString("left-leaning", 10, 20, paint);
3807 }
3808##
3809
3810#Method SkScalar getTextSkewX() const
3811
3812 Returns Text_Skew_X.
3813 Default value is zero.
3814
3815 #Return additional shear in x-axis relative to y-axis ##
3816
3817 #Example
3818 SkPaint paint;
3819 SkDebugf("0 %c= default text skew x\n", 0 == paint.getTextSkewX() ? '=' : '!');
3820 ##
3821
3822##
3823
3824#Method void setTextSkewX(SkScalar skewX)
3825
3826 Sets Text_Skew_X.
3827 Default value is zero.
3828
3829 #Param skewX additional shear in x-axis relative to y-axis ##
3830
3831 #Example
3832 SkPaint paint;
3833 paint.setTextScaleX(1.f / 0.f);
3834 SkDebugf("text scale %s-finite\n", SkScalarIsFinite(paint.getTextScaleX()) ? "is" : "not");
3835 ##
3836
3837##
3838
3839#Topic ##
3840
3841# ------------------------------------------------------------------------------
3842#Topic Text_Encoding
3843
3844#Enum TextEncoding
3845
3846#Code
3847 enum TextEncoding {
3848 kUTF8_TextEncoding,
3849 kUTF16_TextEncoding,
3850 kUTF32_TextEncoding,
Cary Clarkbad5ad72017-08-03 17:14:08 -04003851 kGlyphID_TextEncoding,
Cary Clark8032b982017-07-28 11:04:54 -04003852 };
3853##
3854
Cary Clark6fc50412017-09-21 12:31:06 -04003855TextEncoding determines whether text specifies character codes and their encoded
Cary Clarkbc5697d2017-10-04 14:31:33 -04003856size, or glyph indices. Characters are encoded as specified by the
Cary Clark6fc50412017-09-21 12:31:06 -04003857#A Unicode standard # http://unicode.org/standard/standard.html ##
3858.
3859
Cary Clark8032b982017-07-28 11:04:54 -04003860Character codes encoded size are specified by UTF-8, UTF-16, or UTF-32.
Cary Clarkbc5697d2017-10-04 14:31:33 -04003861All character code formats are able to represent all of Unicode, differing only
Cary Clark8032b982017-07-28 11:04:54 -04003862in the total storage required.
3863
Cary Clark6fc50412017-09-21 12:31:06 -04003864#A UTF-8 (RFC 3629) # https://tools.ietf.org/html/rfc3629 ##
3865 encodes each character as one or more 8-bit bytes.
3866
3867#A UTF-16 (RFC 2781) # https://tools.ietf.org/html/rfc2781 ##
3868 encodes each character as one or two 16-bit words.
3869
3870#A UTF-32 # http://www.unicode.org/versions/Unicode5.0.0/ch03.pdf ##
3871 encodes each character as one 32-bit word.
Cary Clark8032b982017-07-28 11:04:54 -04003872
3873Font_Manager uses font data to convert character code points into glyph indices.
3874A glyph index is a 16-bit word.
3875
3876TextEncoding is set to kUTF8_TextEncoding by default.
3877
3878#Const kUTF8_TextEncoding 0
3879Uses bytes to represent UTF-8 or ASCII.
3880##
3881#Const kUTF16_TextEncoding 1
3882Uses two byte words to represent most of Unicode.
3883##
3884#Const kUTF32_TextEncoding 2
3885Uses four byte words to represent all of Unicode.
3886##
3887#Const kGlyphID_TextEncoding 3
3888Uses two byte words to represent glyph indices.
3889##
3890
3891#Enum ##
3892
3893#Example
3894#Height 128
3895#Description
Cary Clarkbc5697d2017-10-04 14:31:33 -04003896First line is encoded in UTF-8.
3897Second line is encoded in UTF-16.
3898Third line is encoded in UTF-32.
Cary Clark8032b982017-07-28 11:04:54 -04003899Fourth line has 16 bit glyph indices.
3900##
3901void draw(SkCanvas* canvas) {
3902 SkPaint paint;
3903 const char hello8[] = "Hello" "\xE2" "\x98" "\xBA";
3904 const uint16_t hello16[] = { 'H', 'e', 'l', 'l', 'o', 0x263A };
3905 const uint32_t hello32[] = { 'H', 'e', 'l', 'l', 'o', 0x263A };
3906 paint.setTextSize(24);
3907 canvas->drawText(hello8, sizeof(hello8) - 1, 10, 30, paint);
3908 paint.setTextEncoding(SkPaint::kUTF16_TextEncoding);
3909 canvas->drawText(hello16, sizeof(hello16), 10, 60, paint);
3910 paint.setTextEncoding(SkPaint::kUTF32_TextEncoding);
3911 canvas->drawText(hello32, sizeof(hello32), 10, 90, paint);
3912 uint16_t glyphs[SK_ARRAY_COUNT(hello32)];
3913 paint.textToGlyphs(hello32, sizeof(hello32), glyphs);
3914 paint.setTextEncoding(SkPaint::kGlyphID_TextEncoding);
3915 canvas->drawText(glyphs, sizeof(glyphs), 10, 120, paint);
3916}
3917##
3918
3919#Method TextEncoding getTextEncoding() const
3920
3921 Returns Text_Encoding.
3922 Text_Encoding determines how character code points are mapped to font glyph indices.
3923
3924 #Return one of: kUTF8_TextEncoding, kUTF16_TextEncoding, kUTF32_TextEncoding, or
3925 kGlyphID_TextEncoding
3926 ##
3927
3928 #Example
3929 SkPaint paint;
3930 SkDebugf("kUTF8_TextEncoding %c= text encoding\n",
3931 SkPaint::kUTF8_TextEncoding == paint.getTextEncoding() ? '=' : '!');
3932 paint.setTextEncoding(SkPaint::kGlyphID_TextEncoding);
3933 SkDebugf("kGlyphID_TextEncoding %c= text encoding\n",
3934 SkPaint::kGlyphID_TextEncoding == paint.getTextEncoding() ? '=' : '!');
3935
3936 #StdOut
3937 kUTF8_TextEncoding == text encoding
3938 kGlyphID_TextEncoding == text encoding
3939 ##
3940 ##
3941
3942##
3943
3944
3945#Method void setTextEncoding(TextEncoding encoding)
3946
3947 Sets Text_Encoding to encoding.
3948 Text_Encoding determines how character code points are mapped to font glyph indices.
3949 Invalid values for encoding are ignored.
3950
3951 #Param encoding one of: kUTF8_TextEncoding, kUTF16_TextEncoding, kUTF32_TextEncoding, or
Cary Clark579985c2017-07-31 11:48:27 -04003952 kGlyphID_TextEncoding
3953 #Param ##
Cary Clark8032b982017-07-28 11:04:54 -04003954
3955 #Example
3956 SkPaint paint;
3957 paint.setTextEncoding((SkPaint::TextEncoding) 4);
3958 SkDebugf("4 %c= text encoding\n", 4 == paint.getTextEncoding() ? '=' : '!');
3959
3960 #StdOut
3961 4 != text encoding
3962 ##
3963 ##
3964
3965##
3966
3967#Topic ##
3968# ------------------------------------------------------------------------------
3969#Topic Font_Metrics
3970
Cary Clarkce101242017-09-01 15:51:02 -04003971Font_Metrics describe dimensions common to the Glyphs in Typeface.
Cary Clark8032b982017-07-28 11:04:54 -04003972The dimensions are computed by Font_Manager from font data and do not take
3973Paint settings other than Text_Size into account.
3974
3975Font dimensions specify the anchor to the left of the glyph at baseline as the origin.
3976X-axis values to the left of the glyph are negative, and to the right of the left glyph edge
3977are positive.
3978Y-axis values above the baseline are negative, and below the baseline are positive.
Ben Wagnere5806492017-11-09 12:08:31 -05003979
Cary Clark8032b982017-07-28 11:04:54 -04003980#Example
3981#Width 512
3982void draw(SkCanvas* canvas) {
3983 SkPaint paint;
3984 paint.setAntiAlias(true);
3985 paint.setTextSize(120);
3986 SkPaint::FontMetrics fm;
3987 SkScalar lineHeight = paint.getFontMetrics(&fm);
3988 SkPoint pt = { 70, 180 };
3989 canvas->drawString("M", pt.fX, pt.fY, paint);
3990 canvas->drawLine(pt.fX, pt.fY, pt.fX, pt.fY + fm.fTop, paint);
3991 SkScalar ascent = pt.fY + fm.fAscent;
3992 canvas->drawLine(pt.fX - 25, ascent, pt.fX - 25, ascent + lineHeight, paint);
3993 canvas->drawLine(pt.fX - 50, pt.fY, pt.fX - 50, pt.fY + fm.fDescent, paint);
3994 canvas->drawLine(pt.fX + 100, pt.fY, pt.fX + 100, pt.fY + fm.fAscent, paint);
3995 canvas->drawLine(pt.fX + 125, pt.fY, pt.fX + 125, pt.fY - fm.fXHeight, paint);
3996 canvas->drawLine(pt.fX + 150, pt.fY, pt.fX + 150, pt.fY - fm.fCapHeight, paint);
3997 canvas->drawLine(pt.fX + 5, pt.fY, pt.fX + 5, pt.fY + fm.fBottom, paint);
3998 SkScalar xmin = pt.fX + fm.fXMin;
3999 canvas->drawLine(xmin, pt.fY + 60, xmin + fm.fMaxCharWidth, pt.fY + 60, paint);
4000 canvas->drawLine(xmin, pt.fY - 145, pt.fX, pt.fY - 145, paint);
4001 canvas->drawLine(pt.fX + fm.fXMax, pt.fY - 160, pt.fX, pt.fY - 160, paint);
4002 SkScalar upos = pt.fY + fm.fUnderlinePosition;
Ben Wagnere5806492017-11-09 12:08:31 -05004003 canvas->drawLine(pt.fX + 25, upos, pt.fX + 160, upos, paint);
4004 SkScalar ut = fm.fUnderlineThickness;
4005 canvas->drawLine(pt.fX + 130, upos + ut, pt.fX + 160, upos + ut, paint);
Cary Clark8032b982017-07-28 11:04:54 -04004006 paint.setTextSize(12);
4007 canvas->drawString("x-min", pt.fX - 50, pt.fY - 148, paint);
4008 canvas->drawString("x-max", pt.fX + 140, pt.fY - 150, paint);
4009 canvas->drawString("max char width", pt.fX + 120, pt.fY + 57, paint);
4010 canvas->drawString("underline position", pt.fX + 30, pt.fY + 22, paint);
4011 canvas->drawString("underline thickness", pt.fX + 162, pt.fY + 13, paint);
4012 canvas->rotate(-90);
4013 canvas->drawString("descent", -pt.fY - 30, pt.fX - 54, paint);
4014 canvas->drawString("line height", -pt.fY, pt.fX - 29, paint);
4015 canvas->drawString("top", -pt.fY + 30, pt.fX - 4, paint);
4016 canvas->drawString("ascent", -pt.fY, pt.fX + 110, paint);
4017 canvas->drawString("x-height", -pt.fY, pt.fX + 135, paint);
4018 canvas->drawString("cap-height", -pt.fY, pt.fX + 160, paint);
4019 canvas->drawString("bottom", -pt.fY - 50, pt.fX + 15, paint);
4020}
4021##
4022
4023#Struct FontMetrics
4024
4025#Code
4026 struct FontMetrics {
4027 enum FontMetricsFlags {
4028 kUnderlineThicknessIsValid_Flag = 1 << 0,
4029 kUnderlinePositionIsValid_Flag = 1 << 1,
4030 kStrikeoutThicknessIsValid_Flag = 1 << 2,
4031 kStrikeoutPositionIsValid_Flag = 1 << 3,
4032 };
4033
4034 uint32_t fFlags;
4035 SkScalar fTop;
4036 SkScalar fAscent;
4037 SkScalar fDescent;
4038 SkScalar fBottom;
4039 SkScalar fLeading;
4040 SkScalar fAvgCharWidth;
4041 SkScalar fMaxCharWidth;
4042 SkScalar fXMin;
4043 SkScalar fXMax;
4044 SkScalar fXHeight;
4045 SkScalar fCapHeight;
4046 SkScalar fUnderlineThickness;
4047 SkScalar fUnderlinePosition;
4048 SkScalar fStrikeoutThickness;
4049 SkScalar fStrikeoutPosition;
4050
4051 bool hasUnderlineThickness(SkScalar* thickness) const;
4052 bool hasUnderlinePosition(SkScalar* position) const;
4053 bool hasStrikeoutThickness(SkScalar* thickness) const;
4054 bool hasStrikeoutPosition(SkScalar* position) const;
4055 };
4056##
4057
Cary Clark154beea2017-10-26 07:58:48 -04004058 FontMetrics is filled out by getFontMetrics. FontMetrics contents reflect the values
4059 computed by Font_Manager using Typeface. Values are set to zero if they are
4060 not available.
Cary Clarke4aa3712017-09-15 02:56:12 -04004061
Ben Wagnere5806492017-11-09 12:08:31 -05004062 All vertical values relative to the baseline are given y-down. As such, zero is on the
4063 baseline, negative values are above the baseline, and positive values are below the
4064 baseline.
4065
Cary Clark154beea2017-10-26 07:58:48 -04004066 fUnderlineThickness and fUnderlinePosition have a bit set in fFlags if their values
4067 are valid, since their value may be zero.
Ben Wagnere5806492017-11-09 12:08:31 -05004068
Cary Clark154beea2017-10-26 07:58:48 -04004069 fStrikeoutThickness and fStrikeoutPosition have a bit set in fFlags if their values
4070 are valid, since their value may be zero.
4071
4072 #Enum FontMetricsFlags
Cary Clarke4aa3712017-09-15 02:56:12 -04004073
Cary Clark8032b982017-07-28 11:04:54 -04004074 #Code
4075 enum FontMetricsFlags {
4076 kUnderlineThicknessIsValid_Flag = 1 << 0,
4077 kUnderlinePositionIsValid_Flag = 1 << 1,
4078 kStrikeoutThicknessIsValid_Flag = 1 << 2,
4079 kStrikeoutPositionIsValid_Flag = 1 << 3,
4080 };
4081 ##
4082
Cary Clark154beea2017-10-26 07:58:48 -04004083 FontMetricsFlags are set in fFlags when underline and strikeout metrics are valid;
4084 the underline or strikeout metric may be valid and zero.
4085 Fonts with embedded bitmaps may not have valid underline or strikeout metrics.
4086
Cary Clark8032b982017-07-28 11:04:54 -04004087 #Const kUnderlineThicknessIsValid_Flag 0x0001
4088 Set if fUnderlineThickness is valid.
4089 ##
4090 #Const kUnderlinePositionIsValid_Flag 0x0002
4091 Set if fUnderlinePosition is valid.
4092 ##
4093 #Const kStrikeoutThicknessIsValid_Flag 0x0004
4094 Set if fStrikeoutThickness is valid.
4095 ##
4096 #Const kStrikeoutPositionIsValid_Flag 0x0008
4097 Set if fStrikeoutPosition is valid.
4098 ##
4099
4100 #Enum ##
4101
4102 #Member uint32_t fFlags
4103 fFlags is set when underline metrics are valid.
4104 ##
Ben Wagnere5806492017-11-09 12:08:31 -05004105
Cary Clark8032b982017-07-28 11:04:54 -04004106 #Member SkScalar fTop
Ben Wagnere5806492017-11-09 12:08:31 -05004107 Greatest extent above the baseline for any glyph.
4108 Typically less than zero.
Cary Clark8032b982017-07-28 11:04:54 -04004109 ##
Ben Wagnere5806492017-11-09 12:08:31 -05004110
Cary Clark8032b982017-07-28 11:04:54 -04004111 #Member SkScalar fAscent
4112 Recommended distance above the baseline to reserve for a line of text.
Ben Wagnere5806492017-11-09 12:08:31 -05004113 Typically less than zero.
Cary Clark8032b982017-07-28 11:04:54 -04004114 ##
Ben Wagnere5806492017-11-09 12:08:31 -05004115
Cary Clark8032b982017-07-28 11:04:54 -04004116 #Member SkScalar fDescent
4117 Recommended distance below the baseline to reserve for a line of text.
Ben Wagnere5806492017-11-09 12:08:31 -05004118 Typically greater than zero.
Cary Clark8032b982017-07-28 11:04:54 -04004119 ##
Ben Wagnere5806492017-11-09 12:08:31 -05004120
Cary Clark8032b982017-07-28 11:04:54 -04004121 #Member SkScalar fBottom
Ben Wagnere5806492017-11-09 12:08:31 -05004122 Greatest extent below the baseline for any glyph.
4123 Typically greater than zero.
Cary Clark8032b982017-07-28 11:04:54 -04004124 ##
Ben Wagnere5806492017-11-09 12:08:31 -05004125
Cary Clark8032b982017-07-28 11:04:54 -04004126 #Member SkScalar fLeading
4127 Recommended distance to add between lines of text.
Ben Wagnere5806492017-11-09 12:08:31 -05004128 Typically greater than or equal to zero.
Cary Clark8032b982017-07-28 11:04:54 -04004129 ##
Ben Wagnere5806492017-11-09 12:08:31 -05004130
Cary Clark8032b982017-07-28 11:04:54 -04004131 #Member SkScalar fAvgCharWidth
4132 Average character width, if it is available.
4133 Zero if no average width is stored in the font.
4134 ##
Ben Wagnere5806492017-11-09 12:08:31 -05004135
Cary Clark8032b982017-07-28 11:04:54 -04004136 #Member SkScalar fMaxCharWidth
4137 Maximum character width.
4138 ##
Ben Wagnere5806492017-11-09 12:08:31 -05004139
Cary Clark8032b982017-07-28 11:04:54 -04004140 #Member SkScalar fXMin
Ben Wagnere5806492017-11-09 12:08:31 -05004141 Minimum bounding box x value for all Glyphs.
Cary Clark8032b982017-07-28 11:04:54 -04004142 Typically less than zero.
4143 ##
Ben Wagnere5806492017-11-09 12:08:31 -05004144
Cary Clark8032b982017-07-28 11:04:54 -04004145 #Member SkScalar fXMax
Cary Clarkce101242017-09-01 15:51:02 -04004146 Maximum bounding box x value for all Glyphs.
Cary Clark8032b982017-07-28 11:04:54 -04004147 Typically greater than zero.
4148 ##
Ben Wagnere5806492017-11-09 12:08:31 -05004149
Cary Clark8032b982017-07-28 11:04:54 -04004150 #Member SkScalar fXHeight
4151 Height of a lower-case 'x'.
4152 May be zero if no lower-case height is stored in the font.
4153 ##
Ben Wagnere5806492017-11-09 12:08:31 -05004154
Cary Clark8032b982017-07-28 11:04:54 -04004155 #Member SkScalar fCapHeight
4156 Height of an upper-case letter.
4157 May be zero if no upper-case height is stored in the font.
4158 ##
Ben Wagnere5806492017-11-09 12:08:31 -05004159
Cary Clark8032b982017-07-28 11:04:54 -04004160 #Member SkScalar fUnderlineThickness
Ben Wagnere5806492017-11-09 12:08:31 -05004161 Underline thickness.
4162
4163 If the metric is valid, the kUnderlineThicknessIsValid_Flag is set in fFlags.
Cary Clark8032b982017-07-28 11:04:54 -04004164 If kUnderlineThicknessIsValid_Flag is clear, fUnderlineThickness is zero.
4165 ##
Ben Wagnere5806492017-11-09 12:08:31 -05004166
Cary Clark8032b982017-07-28 11:04:54 -04004167 #Member SkScalar fUnderlinePosition
Ben Wagnere5806492017-11-09 12:08:31 -05004168 Position of the top of the underline stroke relative to the baseline.
4169 Typically positive when valid.
Cary Clark8032b982017-07-28 11:04:54 -04004170
4171 If the metric is valid, the kUnderlinePositionIsValid_Flag is set in fFlags.
4172 If kUnderlinePositionIsValid_Flag is clear, fUnderlinePosition is zero.
4173 ##
4174
4175 #Member SkScalar fStrikeoutThickness
Ben Wagnere5806492017-11-09 12:08:31 -05004176 Strikeout thickness.
4177
4178 If the metric is valid, the kStrikeoutThicknessIsValid_Flag is set in fFlags.
Cary Clark8032b982017-07-28 11:04:54 -04004179 If kStrikeoutThicknessIsValid_Flag is clear, fStrikeoutThickness is zero.
4180 ##
4181
4182 #Member SkScalar fStrikeoutPosition
Ben Wagnere5806492017-11-09 12:08:31 -05004183 Position of the bottom of the strikeout stroke relative to the baseline.
4184 Typically negative when valid.
Cary Clark8032b982017-07-28 11:04:54 -04004185
Ben Wagnere5806492017-11-09 12:08:31 -05004186 If the metric is valid, the kStrikeoutPositionIsValid_Flag is set in fFlags.
4187 If kStrikeoutPositionIsValid_Flag is clear, fStrikeoutPosition is zero.
Cary Clark8032b982017-07-28 11:04:54 -04004188 ##
4189
4190 #Method bool hasUnderlineThickness(SkScalar* thickness) const
4191
Ben Wagnere5806492017-11-09 12:08:31 -05004192 If Font_Metrics has a valid underline thickness, return true, and set
Cary Clarkce101242017-09-01 15:51:02 -04004193 thickness to that value. If the underline thickness is not valid,
4194 return false, and ignore thickness.
Cary Clark8032b982017-07-28 11:04:54 -04004195
4196 #Param thickness storage for underline width ##
4197
4198 #Return true if font specifies underline width ##
4199
4200 #NoExample
4201 ##
4202 ##
4203
4204 #Method bool hasUnderlinePosition(SkScalar* position) const
4205
Ben Wagnere5806492017-11-09 12:08:31 -05004206 If Font_Metrics has a valid underline position, return true, and set
Cary Clarkce101242017-09-01 15:51:02 -04004207 position to that value. If the underline position is not valid,
4208 return false, and ignore position.
Cary Clark8032b982017-07-28 11:04:54 -04004209
4210 #Param position storage for underline position ##
4211
4212 #Return true if font specifies underline position ##
4213
4214 #NoExample
4215 ##
4216 ##
4217
4218 #Method bool hasStrikeoutThickness(SkScalar* thickness) const
4219
Ben Wagnere5806492017-11-09 12:08:31 -05004220 If Font_Metrics has a valid strikeout thickness, return true, and set
Cary Clarkce101242017-09-01 15:51:02 -04004221 thickness to that value. If the underline thickness is not valid,
4222 return false, and ignore thickness.
Cary Clark8032b982017-07-28 11:04:54 -04004223
4224 #Param thickness storage for strikeout width ##
4225
4226 #Return true if font specifies strikeout width ##
4227
4228 #NoExample
4229 ##
4230 ##
4231
4232 #Method bool hasStrikeoutPosition(SkScalar* position) const
4233
Ben Wagnere5806492017-11-09 12:08:31 -05004234 If Font_Metrics has a valid strikeout position, return true, and set
Cary Clarkce101242017-09-01 15:51:02 -04004235 position to that value. If the underline position is not valid,
4236 return false, and ignore position.
Cary Clark8032b982017-07-28 11:04:54 -04004237
4238 #Param position storage for strikeout position ##
4239
4240 #Return true if font specifies strikeout position ##
4241
4242 #NoExample
4243 ##
4244 ##
4245
4246#Struct ##
4247
4248#Method SkScalar getFontMetrics(FontMetrics* metrics, SkScalar scale = 0) const
4249
4250 Returns Font_Metrics associated with Typeface.
4251 The return value is the recommended spacing between lines: the sum of metrics
4252 descent, ascent, and leading.
4253 If metrics is not nullptr, Font_Metrics is copied to metrics.
4254 Results are scaled by Text_Size but does not take into account
4255 dimensions required by Text_Scale_X, Text_Skew_X, Fake_Bold,
4256 Style_Stroke, and Path_Effect.
4257 Results can be additionally scaled by scale; a scale of zero
4258 is ignored.
4259
4260 #Param metrics storage for Font_Metrics from Typeface; may be nullptr ##
4261 #Param scale additional multiplier for returned values ##
4262
4263 #Return recommended spacing between lines ##
4264
4265 #Example
4266 #Height 128
4267 void draw(SkCanvas* canvas) {
4268 SkPaint paint;
4269 paint.setTextSize(32);
4270 SkScalar lineHeight = paint.getFontMetrics(nullptr);
4271 canvas->drawString("line 1", 10, 40, paint);
4272 canvas->drawString("line 2", 10, 40 + lineHeight, paint);
4273 paint.setStyle(SkPaint::kStroke_Style);
4274 paint.setStrokeWidth(10);
4275 lineHeight = paint.getFontMetrics(nullptr, 1.10f); // account for stroke height
4276 canvas->drawString("line 3", 120, 40, paint);
4277 canvas->drawString("line 4", 120, 40 + lineHeight, paint);
4278 }
4279 ##
4280
4281 #SeeAlso Text_Size Typeface Typeface_Methods
4282
4283##
4284
4285
4286#Method SkScalar getFontSpacing() const
4287
4288 Returns the recommended spacing between lines: the sum of metrics
4289 descent, ascent, and leading.
4290 Result is scaled by Text_Size but does not take into account
4291 dimensions required by stroking and Path_Effect.
Cary Clark579985c2017-07-31 11:48:27 -04004292 Returns the same result as getFontMetrics.
Cary Clark8032b982017-07-28 11:04:54 -04004293
Cary Clark0c5f5462017-12-15 11:21:51 -05004294 #Return recommended spacing between lines ##
Cary Clark8032b982017-07-28 11:04:54 -04004295
4296 #Example
4297 SkPaint paint;
4298 for (SkScalar textSize : { 12, 18, 24, 32 } ) {
4299 paint.setTextSize(textSize);
4300 SkDebugf("textSize: %g fontSpacing: %g\n", textSize, paint.getFontSpacing());
4301 }
4302
4303 #StdOut
4304 textSize: 12 fontSpacing: 13.9688
4305 textSize: 18 fontSpacing: 20.9531
4306 textSize: 24 fontSpacing: 27.9375
4307 textSize: 32 fontSpacing: 37.25
4308 ##
4309 ##
4310
4311##
4312
4313
4314#Method SkRect getFontBounds() const
4315
Cary Clarkce101242017-09-01 15:51:02 -04004316Returns the union of bounds of all Glyphs.
Cary Clark8032b982017-07-28 11:04:54 -04004317Returned dimensions are computed by Font_Manager from font data,
Cary Clark579985c2017-07-31 11:48:27 -04004318ignoring Hinting. Includes Text_Size, Text_Scale_X,
Cary Clark8032b982017-07-28 11:04:54 -04004319and Text_Skew_X, but not Fake_Bold or Path_Effect.
4320
4321If Text_Size is large, Text_Scale_X is one, and Text_Skew_X is zero,
Cary Clark579985c2017-07-31 11:48:27 -04004322returns the same bounds as Font_Metrics { FontMetrics::fXMin,
Cary Clark8032b982017-07-28 11:04:54 -04004323FontMetrics::fTop, FontMetrics::fXMax, FontMetrics::fBottom }.
4324
Cary Clarkce101242017-09-01 15:51:02 -04004325#Return union of bounds of all Glyphs ##
Cary Clark8032b982017-07-28 11:04:54 -04004326
4327#Example
4328 SkPaint paint;
4329 SkPaint::FontMetrics fm;
4330 paint.getFontMetrics(&fm);
4331 SkRect fb = paint.getFontBounds();
4332 SkDebugf("metrics bounds = { %g, %g, %g, %g }\n", fm.fXMin, fm.fTop, fm.fXMax, fm.fBottom );
4333 SkDebugf("font bounds = { %g, %g, %g, %g }\n", fb.fLeft, fb.fTop, fb.fRight, fm.fBottom );
4334
4335 #StdOut
4336 metrics bounds = { -12.2461, -14.7891, 21.5215, 5.55469 }
4337 font bounds = { -12.2461, -14.7891, 21.5215, 5.55469 }
4338 ##
4339##
4340
4341##
4342
4343#Topic ##
4344# ------------------------------------------------------------------------------
4345
4346#Method int textToGlyphs(const void* text, size_t byteLength,
4347 SkGlyphID glyphs[]) const
4348
4349Converts text into glyph indices.
4350Returns the number of glyph indices represented by text.
4351Text_Encoding specifies how text represents characters or glyphs.
4352glyphs may be nullptr, to compute the glyph count.
4353
Cary Clarkbc5697d2017-10-04 14:31:33 -04004354Does not check text for valid character codes or valid glyph indices.
Cary Clark8032b982017-07-28 11:04:54 -04004355
Cary Clark579985c2017-07-31 11:48:27 -04004356If byteLength equals zero, returns zero.
Cary Clark8032b982017-07-28 11:04:54 -04004357If byteLength includes a partial character, the partial character is ignored.
4358
4359If Text_Encoding is kUTF8_TextEncoding and
4360text contains an invalid UTF-8 sequence, zero is returned.
4361
Cary Clarkce101242017-09-01 15:51:02 -04004362#Param text character storage encoded with Text_Encoding ##
Cary Clark8032b982017-07-28 11:04:54 -04004363#Param byteLength length of character storage in bytes ##
4364#Param glyphs storage for glyph indices; may be nullptr ##
4365
4366#Return number of glyphs represented by text of length byteLength ##
4367
4368 #Example
4369 #Height 64
4370 void draw(SkCanvas* canvas) {
4371 SkPaint paint;
4372 const uint8_t utf8[] = { 0x24, 0xC2, 0xA2, 0xE2, 0x82, 0xAC, 0xC2, 0xA5, 0xC2, 0xA3 };
4373 std::vector<SkGlyphID> glyphs;
4374 int count = paint.textToGlyphs(utf8, sizeof(utf8), nullptr);
4375 glyphs.resize(count);
4376 (void) paint.textToGlyphs(utf8, sizeof(utf8), &glyphs.front());
4377 paint.setTextEncoding(SkPaint::kGlyphID_TextEncoding);
4378 paint.setTextSize(32);
4379 canvas->drawText(&glyphs.front(), glyphs.size() * sizeof(SkGlyphID), 10, 40, paint);
4380 }
4381 ##
4382
4383##
4384
4385#Method int countText(const void* text, size_t byteLength) const
4386
Cary Clarkce101242017-09-01 15:51:02 -04004387 Returns the number of Glyphs in text.
4388 Uses Text_Encoding to count the Glyphs.
Cary Clark8032b982017-07-28 11:04:54 -04004389 Returns the same result as textToGlyphs.
4390
Cary Clarkce101242017-09-01 15:51:02 -04004391#Param text character storage encoded with Text_Encoding ##
Cary Clark8032b982017-07-28 11:04:54 -04004392#Param byteLength length of character storage in bytes ##
4393
Cary Clarkce101242017-09-01 15:51:02 -04004394#Return number of Glyphs represented by text of length byteLength ##
Cary Clark8032b982017-07-28 11:04:54 -04004395
4396 #Example
4397 SkPaint paint;
4398 const uint8_t utf8[] = { 0x24, 0xC2, 0xA2, 0xE2, 0x82, 0xAC, 0xC2, 0xA5, 0xC2, 0xA3 };
4399 SkDebugf("count = %d\n", paint.countText(utf8, sizeof(utf8)));
4400
4401 #StdOut
4402 count = 5
4403 ##
4404 ##
4405##
4406
4407# ------------------------------------------------------------------------------
4408
4409#Method bool containsText(const void* text, size_t byteLength) const
4410
4411 Returns true if all text corresponds to a non-zero glyph index.
4412 Returns false if any characters in text are not supported in
4413 Typeface.
4414
Cary Clark579985c2017-07-31 11:48:27 -04004415 If Text_Encoding is kGlyphID_TextEncoding,
4416 returns true if all glyph indices in text are non-zero;
Cary Clark8032b982017-07-28 11:04:54 -04004417 does not check to see if text contains valid glyph indices for Typeface.
4418
Cary Clarkce101242017-09-01 15:51:02 -04004419 Returns true if byteLength is zero.
Cary Clark8032b982017-07-28 11:04:54 -04004420
Cary Clarkce101242017-09-01 15:51:02 -04004421 #Param text array of characters or Glyphs ##
Cary Clark8032b982017-07-28 11:04:54 -04004422 #Param byteLength number of bytes in text array ##
4423
4424 #Return true if all text corresponds to a non-zero glyph index ##
4425
4426 #Example
4427 #Description
4428 containsText succeeds for degree symbol, but cannot find a glyph index
4429 corresponding to the Unicode surrogate code point.
4430 ##
4431 SkPaint paint;
4432 const uint16_t goodChar = 0x00B0; // degree symbol
4433 const uint16_t badChar = 0xD800; // Unicode surrogate
4434 paint.setTextEncoding(SkPaint::kUTF16_TextEncoding);
4435 SkDebugf("0x%04x %c= has char\n", goodChar,
4436 paint.containsText(&goodChar, 2) ? '=' : '!');
4437 SkDebugf("0x%04x %c= has char\n", badChar,
4438 paint.containsText(&badChar, 2) ? '=' : '!');
4439
4440 #StdOut
4441 0x00b0 == has char
4442 0xd800 != has char
4443 ##
4444 ##
4445
4446 #Example
4447 #Description
4448 containsText returns true that glyph index is greater than zero, not
4449 that it corresponds to an entry in Typeface.
4450 ##
4451 SkPaint paint;
4452 const uint16_t goodGlyph = 511;
4453 const uint16_t zeroGlyph = 0;
4454 const uint16_t badGlyph = 65535; // larger than glyph count in font
4455 paint.setTextEncoding(SkPaint::kGlyphID_TextEncoding);
4456 SkDebugf("0x%04x %c= has glyph\n", goodGlyph,
4457 paint.containsText(&goodGlyph, 2) ? '=' : '!');
4458 SkDebugf("0x%04x %c= has glyph\n", zeroGlyph,
4459 paint.containsText(&zeroGlyph, 2) ? '=' : '!');
4460 SkDebugf("0x%04x %c= has glyph\n", badGlyph,
4461 paint.containsText(&badGlyph, 2) ? '=' : '!');
4462
4463 #StdOut
4464 0x01ff == has glyph
4465 0x0000 != has glyph
4466 0xffff == has glyph
4467 ##
4468 ##
4469
4470#SeeAlso setTextEncoding Typeface
4471
4472##
4473
4474# ------------------------------------------------------------------------------
4475
4476#Method void glyphsToUnichars(const SkGlyphID glyphs[],
4477 int count, SkUnichar text[]) const
4478
4479 Converts glyphs into text if possible.
4480 Glyph values without direct Unicode equivalents are mapped to zero.
4481 Uses the Typeface, but is unaffected
4482 by Text_Encoding; the text values returned are equivalent to kUTF32_TextEncoding.
4483
4484 Only supported on platforms that use FreeType as the Font_Engine.
4485
4486 #Param glyphs array of indices into font ##
4487 #Param count length of glyph array ##
4488 #Param text storage for character codes, one per glyph ##
4489
4490 #Example
4491 #Height 64
4492 #Description
4493 Convert UTF-8 text to glyphs; then convert glyphs to Unichar code points.
4494 ##
4495 void draw(SkCanvas* canvas) {
4496 SkPaint paint;
4497 const char hello[] = "Hello!";
4498 const int count = sizeof(hello) - 1;
4499 SkGlyphID glyphs[count];
4500 if (count != paint.textToGlyphs(hello, count, glyphs)) {
4501 return;
4502 }
4503 SkUnichar unichars[count];
4504 paint.glyphsToUnichars(glyphs, count, unichars);
4505 paint.setTextEncoding(SkPaint::kUTF32_TextEncoding);
4506 canvas->drawText(unichars, sizeof(unichars), 10, 30, paint);
4507 }
4508 ##
4509
4510##
4511
4512# ------------------------------------------------------------------------------
4513#Topic Measure_Text
4514
4515#Method SkScalar measureText(const void* text, size_t length, SkRect* bounds) const
4516
4517 Returns the advance width of text if kVerticalText_Flag is clear,
4518 and the height of text if kVerticalText_Flag is set.
4519 The advance is the normal distance to move before drawing additional text.
4520 Uses Text_Encoding to decode text, Typeface to get the font metrics,
4521 and Text_Size, Text_Scale_X, Text_Skew_X, Stroke_Width, and
4522 Path_Effect to scale the metrics and bounds.
4523 Returns the bounding box of text if bounds is not nullptr.
4524 The bounding box is computed as if the text was drawn at the origin.
4525
4526 #Param text character codes or glyph indices to be measured ##
4527 #Param length number of bytes of text to measure ##
4528 #Param bounds returns bounding box relative to (0, 0) if not nullptr ##
4529
4530 #Return advance width or height ##
4531
4532 #Example
4533 #Height 64
4534 void draw(SkCanvas* canvas) {
4535 SkPaint paint;
4536 paint.setAntiAlias(true);
4537 paint.setTextSize(50);
4538 const char str[] = "ay^jZ";
4539 const int count = sizeof(str) - 1;
4540 canvas->drawText(str, count, 25, 50, paint);
4541 SkRect bounds;
4542 paint.measureText(str, count, &bounds);
4543 canvas->translate(25, 50);
4544 paint.setStyle(SkPaint::kStroke_Style);
4545 canvas->drawRect(bounds, paint);
4546 }
4547 ##
4548
4549##
4550
4551#Method SkScalar measureText(const void* text, size_t length) const
4552
4553 Returns the advance width of text if kVerticalText_Flag is clear,
4554 and the height of text if kVerticalText_Flag is set.
4555 The advance is the normal distance to move before drawing additional text.
4556 Uses Text_Encoding to decode text, Typeface to get the font metrics,
4557 and Text_Size to scale the metrics.
4558 Does not scale the advance or bounds by Fake_Bold or Path_Effect.
4559
4560 #Param text character codes or glyph indices to be measured ##
4561 #Param length number of bytes of text to measure ##
4562
4563 #Return advance width or height ##
4564
4565 #Example
4566 SkPaint paint;
4567 SkDebugf("default width = %g\n", paint.measureText("!", 1));
4568 paint.setTextSize(paint.getTextSize() * 2);
4569 SkDebugf("double width = %g\n", paint.measureText("!", 1));
4570
4571 #StdOut
4572 default width = 5
4573 double width = 10
4574 ##
4575 ##
4576
4577##
4578
4579#Method size_t breakText(const void* text, size_t length, SkScalar maxWidth,
Cary Clark73fa9722017-08-29 17:36:51 -04004580 SkScalar* measuredWidth = nullptr) const
Cary Clark8032b982017-07-28 11:04:54 -04004581
4582 Returns the bytes of text that fit within maxWidth.
4583 If kVerticalText_Flag is clear, the text fragment fits if its advance width is less than or
4584 equal to maxWidth.
4585 If kVerticalText_Flag is set, the text fragment fits if its advance height is less than or
4586 equal to maxWidth.
4587 Measures only while the advance is less than or equal to maxWidth.
4588 Returns the advance or the text fragment in measuredWidth if it not nullptr.
4589 Uses Text_Encoding to decode text, Typeface to get the font metrics,
4590 and Text_Size to scale the metrics.
4591 Does not scale the advance or bounds by Fake_Bold or Path_Effect.
4592
4593 #Param text character codes or glyph indices to be measured ##
4594 #Param length number of bytes of text to measure ##
4595 #Param maxWidth advance limit; text is measured while advance is less than maxWidth ##
4596 #Param measuredWidth returns the width of the text less than or equal to maxWidth ##
4597 #Return bytes of text that fit, always less than or equal to length ##
4598
4599 #Example
4600 #Description
4601 Line under "Breakfast" shows desired width, shorter than available characters.
4602 Line under "Bre" shows measured width after breaking text.
4603 ##
4604 #Height 128
4605 #Width 280
4606 void draw(SkCanvas* canvas) {
4607 SkPaint paint;
4608 paint.setAntiAlias(true);
4609 paint.setTextSize(50);
4610 const char str[] = "Breakfast";
4611 const int count = sizeof(str) - 1;
4612 canvas->drawText(str, count, 25, 50, paint);
4613 SkScalar measuredWidth;
4614 int partialBytes = paint.breakText(str, count, 100, &measuredWidth);
4615 canvas->drawText(str, partialBytes, 25, 100, paint);
4616 canvas->drawLine(25, 60, 25 + 100, 60, paint);
4617 canvas->drawLine(25, 110, 25 + measuredWidth, 110, paint);
4618 }
4619 ##
4620
4621##
4622
4623#Method int getTextWidths(const void* text, size_t byteLength, SkScalar widths[],
Cary Clark73fa9722017-08-29 17:36:51 -04004624 SkRect bounds[] = nullptr) const
Cary Clark8032b982017-07-28 11:04:54 -04004625
4626 Retrieves the advance and bounds for each glyph in text, and returns
4627 the glyph count in text.
4628 Both widths and bounds may be nullptr.
4629 If widths is not nullptr, widths must be an array of glyph count entries.
4630 if bounds is not nullptr, bounds must be an array of glyph count entries.
4631 If kVerticalText_Flag is clear, widths returns the horizontal advance.
4632 If kVerticalText_Flag is set, widths returns the vertical advance.
4633 Uses Text_Encoding to decode text, Typeface to get the font metrics,
4634 and Text_Size to scale the widths and bounds.
4635 Does not scale the advance by Fake_Bold or Path_Effect.
4636 Does include Fake_Bold and Path_Effect in the bounds.
4637
4638 #Param text character codes or glyph indices to be measured ##
4639 #Param byteLength number of bytes of text to measure ##
4640 #Param widths returns text advances for each glyph; may be nullptr ##
4641 #Param bounds returns bounds for each glyph relative to (0, 0); may be nullptr ##
4642
4643 #Return glyph count in text ##
4644
4645 #Example
4646 #Height 160
4647 #Description
Cary Clarkce101242017-09-01 15:51:02 -04004648 Bounds of Glyphs increase for stroked text, but text advance remains the same.
Cary Clark8032b982017-07-28 11:04:54 -04004649 The underlines show the text advance, spaced to keep them distinct.
4650 ##
4651 void draw(SkCanvas* canvas) {
4652 SkPaint paint;
4653 paint.setAntiAlias(true);
4654 paint.setTextSize(50);
4655 const char str[] = "abc";
4656 const int bytes = sizeof(str) - 1;
4657 int count = paint.getTextWidths(str, bytes, nullptr);
4658 std::vector<SkScalar> widths;
4659 std::vector<SkRect> bounds;
4660 widths.resize(count);
4661 bounds.resize(count);
4662 for (int loop = 0; loop < 2; ++loop) {
4663 (void) paint.getTextWidths(str, count, &widths.front(), &bounds.front());
4664 SkPoint loc = { 25, 50 };
4665 canvas->drawText(str, bytes, loc.fX, loc.fY, paint);
4666 paint.setStyle(SkPaint::kStroke_Style);
4667 paint.setStrokeWidth(0);
4668 SkScalar advanceY = loc.fY + 10;
4669 for (int index = 0; index < count; ++index) {
4670 bounds[index].offset(loc.fX, loc.fY);
4671 canvas->drawRect(bounds[index], paint);
4672 canvas->drawLine(loc.fX, advanceY, loc.fX + widths[index], advanceY, paint);
4673 loc.fX += widths[index];
4674 advanceY += 5;
4675 }
4676 canvas->translate(0, 80);
4677 paint.setStrokeWidth(3);
4678 }
4679 }
4680 ##
4681
4682##
4683
4684#Topic ##
4685# ------------------------------------------------------------------------------
4686#Topic Text_Path
4687
Cary Clarkce101242017-09-01 15:51:02 -04004688Text_Path describes the geometry of Glyphs used to draw text.
Cary Clark8032b982017-07-28 11:04:54 -04004689
4690#Method void getTextPath(const void* text, size_t length, SkScalar x, SkScalar y,
4691 SkPath* path) const
4692
4693Returns the geometry as Path equivalent to the drawn text.
4694Uses Text_Encoding to decode text, Typeface to get the glyph paths,
4695and Text_Size, Fake_Bold, and Path_Effect to scale and modify the glyph paths.
4696All of the glyph paths are stored in path.
Cary Clark579985c2017-07-31 11:48:27 -04004697Uses x, y, and Text_Align to position path.
Cary Clark8032b982017-07-28 11:04:54 -04004698
4699 #Param text character codes or glyph indices ##
4700 #Param length number of bytes of text ##
4701 #Param x x-coordinate of the origin of the text ##
4702 #Param y y-coordinate of the origin of the text ##
Cary Clarkce101242017-09-01 15:51:02 -04004703 #Param path geometry of the Glyphs ##
Cary Clark8032b982017-07-28 11:04:54 -04004704
4705 #Example
4706 #Description
4707 Text is added to Path, offset, and subtracted from Path, then added at
4708 the offset location. The result is rendered with one draw call.
4709 ##
4710 #Height 128
4711 void draw(SkCanvas* canvas) {
4712 SkPaint paint;
4713 paint.setTextSize(80);
4714 SkPath path, path2;
4715 paint.getTextPath("ABC", 3, 20, 80, &path);
4716 path.offset(20, 20, &path2);
4717 Op(path, path2, SkPathOp::kDifference_SkPathOp, &path);
4718 path.addPath(path2);
4719 paint.setStyle(SkPaint::kStroke_Style);
4720 canvas->drawPath(path, paint);
4721 }
4722 ##
4723
4724##
4725
4726#Method void getPosTextPath(const void* text, size_t length,
4727 const SkPoint pos[], SkPath* path) const
4728
4729Returns the geometry as Path equivalent to the drawn text.
4730Uses Text_Encoding to decode text, Typeface to get the glyph paths,
4731and Text_Size, Fake_Bold, and Path_Effect to scale and modify the glyph paths.
4732All of the glyph paths are stored in path.
4733Uses pos array and Text_Align to position path.
4734pos contains a position for each glyph.
4735
4736 #Param text character codes or glyph indices ##
4737 #Param length number of bytes of text ##
4738 #Param pos positions of each glyph ##
Cary Clarkce101242017-09-01 15:51:02 -04004739 #Param path geometry of the Glyphs ##
Cary Clark8032b982017-07-28 11:04:54 -04004740
4741 #Example
4742 #Height 85
4743 #Description
Cary Clarkce101242017-09-01 15:51:02 -04004744 Simplifies three Glyphs to eliminate overlaps, and strokes the result.
Cary Clark8032b982017-07-28 11:04:54 -04004745 ##
4746 void draw(SkCanvas* canvas) {
4747 SkPaint paint;
4748 paint.setTextSize(80);
4749 SkPath path, path2;
4750 SkPoint pos[] = {{20, 60}, {30, 70}, {40, 80}};
4751 paint.getPosTextPath("ABC", 3, pos, &path);
4752 Simplify(path, &path);
4753 paint.setStyle(SkPaint::kStroke_Style);
4754 canvas->drawPath(path, paint);
4755 }
4756 ##
4757
4758##
4759
4760#Topic ##
4761# ------------------------------------------------------------------------------
4762#Topic Text_Intercepts
4763
Cary Clarkce101242017-09-01 15:51:02 -04004764Text_Intercepts describe the intersection of drawn text Glyphs with a pair
Cary Clark8032b982017-07-28 11:04:54 -04004765of lines parallel to the text advance. Text_Intercepts permits creating a
Cary Clarkce101242017-09-01 15:51:02 -04004766underline that skips Descenders.
Cary Clark8032b982017-07-28 11:04:54 -04004767
4768#Method int getTextIntercepts(const void* text, size_t length, SkScalar x, SkScalar y,
4769 const SkScalar bounds[2], SkScalar* intervals) const
4770
4771 Returns the number of intervals that intersect bounds.
4772 bounds describes a pair of lines parallel to the text advance.
Cary Clarkce101242017-09-01 15:51:02 -04004773 The return count is zero or a multiple of two, and is at most twice the number of Glyphs in
Cary Clark8032b982017-07-28 11:04:54 -04004774 the string.
4775 Uses Text_Encoding to decode text, Typeface to get the glyph paths,
4776 and Text_Size, Fake_Bold, and Path_Effect to scale and modify the glyph paths.
4777 Uses x, y, and Text_Align to position intervals.
4778
4779 Pass nullptr for intervals to determine the size of the interval array.
4780
4781 intervals are cached to improve performance for multiple calls.
4782
4783 #Param text character codes or glyph indices ##
4784 #Param length number of bytes of text ##
4785 #Param x x-coordinate of the origin of the text ##
4786 #Param y y-coordinate of the origin of the text ##
4787 #Param bounds lower and upper line parallel to the advance ##
4788 #Param intervals returned intersections; may be nullptr ##
4789
4790 #Return number of intersections; may be zero ##
4791
4792#Example
4793#Height 128
4794#Description
Cary Clarkce101242017-09-01 15:51:02 -04004795Underline uses intercepts to draw on either side of the glyph Descender.
Cary Clark8032b982017-07-28 11:04:54 -04004796##
4797void draw(SkCanvas* canvas) {
4798 SkPaint paint;
4799 paint.setTextSize(120);
4800 SkPoint textOrigin = { 20, 100 };
4801 SkScalar bounds[] = { 100, 108 };
4802 int count = paint.getTextIntercepts("y", 1, textOrigin.fX, textOrigin.fY, bounds, nullptr);
4803 std::vector<SkScalar> intervals;
4804 intervals.resize(count);
4805 (void) paint.getTextIntercepts("y", 1, textOrigin.fX, textOrigin.fY, bounds,
4806 &intervals.front());
4807 canvas->drawString("y", textOrigin.fX, textOrigin.fY, paint);
4808 paint.setColor(SK_ColorRED);
4809 SkScalar x = textOrigin.fX;
4810 for (int i = 0; i < count; i += 2) {
4811 canvas->drawRect({x, bounds[0], intervals[i], bounds[1]}, paint);
4812 x = intervals[i + 1];
4813 }
4814 canvas->drawRect({intervals[count - 1], bounds[0],
4815 textOrigin.fX + paint.measureText("y", 1), bounds[1]}, paint);
4816}
4817##
4818
4819##
4820
4821#Method int getPosTextIntercepts(const void* text, size_t length, const SkPoint pos[],
4822 const SkScalar bounds[2], SkScalar* intervals) const
4823
4824 Returns the number of intervals that intersect bounds.
4825 bounds describes a pair of lines parallel to the text advance.
Cary Clarkce101242017-09-01 15:51:02 -04004826 The return count is zero or a multiple of two, and is at most twice the number of Glyphs in
Cary Clark8032b982017-07-28 11:04:54 -04004827 the string.
4828 Uses Text_Encoding to decode text, Typeface to get the glyph paths,
4829 and Text_Size, Fake_Bold, and Path_Effect to scale and modify the glyph paths.
4830 Uses pos array and Text_Align to position intervals.
4831
4832 Pass nullptr for intervals to determine the size of the interval array.
4833
4834 intervals are cached to improve performance for multiple calls.
4835
4836 #Param text character codes or glyph indices ##
4837 #Param length number of bytes of text ##
4838 #Param pos positions of each glyph ##
4839 #Param bounds lower and upper line parallel to the advance ##
4840 #Param intervals returned intersections; may be nullptr ##
4841
Cary Clarka523d2d2017-08-30 08:58:10 -04004842 #Return number of intersections; may be zero ##
Cary Clark8032b982017-07-28 11:04:54 -04004843
4844 #Example
4845 #Description
Cary Clarkce101242017-09-01 15:51:02 -04004846 Text intercepts draw on either side of, but not inside, Glyphs in a run.
Cary Clark8032b982017-07-28 11:04:54 -04004847 ##
4848 void draw(SkCanvas* canvas) {
4849 SkPaint paint;
4850 paint.setTextSize(120);
4851 paint.setVerticalText(true);
4852 SkPoint textPos[] = {{ 60, 40 }, { 60, 140 }};
4853 SkScalar bounds[] = { 56, 64 };
4854 const char str[] = "A-";
4855 int len = sizeof(str) - 1;
4856 int count = paint.getPosTextIntercepts(str, len, textPos, bounds, nullptr);
4857 std::vector<SkScalar> intervals;
4858 intervals.resize(count);
4859 (void) paint.getPosTextIntercepts(str, len, textPos, bounds, &intervals.front());
4860 canvas->drawPosText(str, len, textPos, paint);
4861 paint.setColor(SK_ColorRED);
4862 SkScalar y = textPos[0].fY;
4863 for (int i = 0; i < count; i+= 2) {
4864 canvas->drawRect({bounds[0], y, bounds[1], intervals[i]}, paint);
4865 y = intervals[i + 1];
4866 }
4867 canvas->drawRect({bounds[0], intervals[count - 1], bounds[1], 240}, paint);
4868 }
4869 ##
4870
4871##
4872
4873#Method int getPosTextHIntercepts(const void* text, size_t length, const SkScalar xpos[],
4874 SkScalar constY, const SkScalar bounds[2],
4875 SkScalar* intervals) const
4876
4877 Returns the number of intervals that intersect bounds.
4878 bounds describes a pair of lines parallel to the text advance.
Cary Clarkce101242017-09-01 15:51:02 -04004879 The return count is zero or a multiple of two, and is at most twice the number of Glyphs in
Cary Clark8032b982017-07-28 11:04:54 -04004880 the string.
4881 Uses Text_Encoding to decode text, Typeface to get the glyph paths,
4882 and Text_Size, Fake_Bold, and Path_Effect to scale and modify the glyph paths.
4883 Uses xpos array, constY, and Text_Align to position intervals.
4884
4885 Pass nullptr for intervals to determine the size of the interval array.
4886
4887 intervals are cached to improve performance for multiple calls.
4888
4889 #Param text character codes or glyph indices ##
4890 #Param length number of bytes of text ##
4891 #Param xpos positions of each glyph in x ##
4892 #Param constY position of each glyph in y ##
4893 #Param bounds lower and upper line parallel to the advance ##
4894 #Param intervals returned intersections; may be nullptr ##
4895
4896 #Return number of intersections; may be zero ##
4897
4898 #Example
4899 #Height 128
4900 #Description
4901 Text intercepts do not take stroke thickness into consideration.
4902 ##
4903 void draw(SkCanvas* canvas) {
4904 SkPaint paint;
4905 paint.setTextSize(120);
4906 paint.setStyle(SkPaint::kStroke_Style);
4907 paint.setStrokeWidth(4);
4908 SkScalar textPosH[] = { 20, 80, 140 };
4909 SkScalar y = 100;
4910 SkScalar bounds[] = { 56, 78 };
4911 const char str[] = "\\-/";
4912 int len = sizeof(str) - 1;
4913 int count = paint.getPosTextHIntercepts(str, len, textPosH, y, bounds, nullptr);
4914 std::vector<SkScalar> intervals;
4915 intervals.resize(count);
4916 (void) paint.getPosTextHIntercepts(str, len, textPosH, y, bounds, &intervals.front());
4917 canvas->drawPosTextH(str, len, textPosH, y, paint);
4918 paint.setColor(0xFFFF7777);
4919 paint.setStyle(SkPaint::kFill_Style);
4920 SkScalar x = textPosH[0];
4921 for (int i = 0; i < count; i+= 2) {
4922 canvas->drawRect({x, bounds[0], intervals[i], bounds[1]}, paint);
4923 x = intervals[i + 1];
4924 }
4925 canvas->drawRect({intervals[count - 1], bounds[0], 180, bounds[1]}, paint);
4926 }
4927 ##
4928
4929##
4930
4931
4932#Method int getTextBlobIntercepts(const SkTextBlob* blob, const SkScalar bounds[2],
4933 SkScalar* intervals) const
4934
4935 Returns the number of intervals that intersect bounds.
4936 bounds describes a pair of lines parallel to the text advance.
Cary Clarkce101242017-09-01 15:51:02 -04004937 The return count is zero or a multiple of two, and is at most twice the number of Glyphs in
Cary Clark8032b982017-07-28 11:04:54 -04004938 the string.
Cary Clark3cd22cc2017-12-01 11:49:58 -05004939 Uses Typeface to get the glyph paths,
Cary Clark8032b982017-07-28 11:04:54 -04004940 and Text_Size, Fake_Bold, and Path_Effect to scale and modify the glyph paths.
Cary Clarkce101242017-09-01 15:51:02 -04004941 Uses run array and Text_Align to position intervals.
Cary Clark8032b982017-07-28 11:04:54 -04004942
Cary Clark3cd22cc2017-12-01 11:49:58 -05004943 Text_Encoding must be set to SkPaint::kGlyphID_TextEncoding.
4944
Cary Clark8032b982017-07-28 11:04:54 -04004945 Pass nullptr for intervals to determine the size of the interval array.
4946
4947 intervals are cached to improve performance for multiple calls.
4948
Cary Clarkce101242017-09-01 15:51:02 -04004949 #Param blob Glyphs, positions, and text paint attributes ##
Cary Clark8032b982017-07-28 11:04:54 -04004950 #Param bounds lower and upper line parallel to the advance ##
4951 #Param intervals returned intersections; may be nullptr ##
4952
4953 #Return number of intersections; may be zero ##
4954
4955 #Example
4956 #Height 143
4957 void draw(SkCanvas* canvas) {
4958 SkPaint paint;
Cary Clark3cd22cc2017-12-01 11:49:58 -05004959 paint.setTextEncoding(SkPaint::kGlyphID_TextEncoding);
Cary Clark8032b982017-07-28 11:04:54 -04004960 paint.setTextSize(120);
4961 SkPoint textPos = { 20, 110 };
4962 int len = 3;
4963 SkTextBlobBuilder textBlobBuilder;
4964 const SkTextBlobBuilder::RunBuffer& run =
4965 textBlobBuilder.allocRun(paint, len, textPos.fX, textPos.fY);
4966 run.glyphs[0] = 10;
4967 run.glyphs[1] = 20;
4968 run.glyphs[2] = 30;
4969 sk_sp<const SkTextBlob> blob = textBlobBuilder.make();
4970 canvas->drawTextBlob(blob.get(), textPos.fX, textPos.fY, paint);
4971 SkScalar bounds[] = { 116, 134 };
4972 int count = paint.getTextBlobIntercepts(blob.get(), bounds, nullptr);
4973 std::vector<SkScalar> intervals;
4974 intervals.resize(count);
4975 (void) paint.getTextBlobIntercepts(blob.get(), bounds, &intervals.front());
4976 canvas->drawTextBlob(blob.get(), 0, 0, paint);
4977 paint.setColor(0xFFFF7777);
4978 SkScalar x = textPos.fX;
4979 for (int i = 0; i < count; i+= 2) {
4980 canvas->drawRect({x, bounds[0], intervals[i], bounds[1]}, paint);
4981 x = intervals[i + 1];
4982 }
4983 canvas->drawRect({intervals[count - 1], bounds[0], 180, bounds[1]}, paint);
4984 }
4985 ##
4986
4987##
4988
4989#Topic ##
4990# ------------------------------------------------------------------------------
4991
4992#Method bool nothingToDraw() const
4993
Cary Clark579985c2017-07-31 11:48:27 -04004994 Returns true if Paint prevents all drawing;
4995 otherwise, the Paint may or may not allow drawing.
Cary Clark8032b982017-07-28 11:04:54 -04004996
Cary Clarkce101242017-09-01 15:51:02 -04004997 Returns true if, for example, Blend_Mode combined with Color_Alpha computes a
4998 new Alpha of zero.
Cary Clark8032b982017-07-28 11:04:54 -04004999
5000 #Return true if Paint prevents all drawing ##
5001
5002 #Example
5003 void draw(SkCanvas* canvas) {
5004 auto debugster = [](const char* prefix, const SkPaint& p) -> void {
5005 SkDebugf("%s nothing to draw: %s\n", prefix,
5006 p.nothingToDraw() ? "true" : "false");
5007 };
5008 SkPaint paint;
5009 debugster("initial", paint);
5010 paint.setBlendMode(SkBlendMode::kDst);
5011 debugster("blend dst", paint);
5012 paint.setBlendMode(SkBlendMode::kSrcOver);
5013 debugster("blend src over", paint);
5014 paint.setAlpha(0);
5015 debugster("alpha 0", paint);
5016 }
5017
5018 #StdOut
5019 initial nothing to draw: false
5020 blend dst nothing to draw: true
5021 blend src over nothing to draw: false
5022 alpha 0 nothing to draw: true
5023 #StdOut ##
5024 ##
5025
5026##
5027
5028# ------------------------------------------------------------------------------
5029#Topic Fast_Bounds
5030 #Private
5031 To be made private.
5032 ##
5033
5034Fast_Bounds methods conservatively outset a drawing bounds by additional area
5035Paint may draw to.
5036
5037#Method bool canComputeFastBounds() const
5038 #Private
5039 (to be made private)
5040 ##
5041
5042 Returns true if Paint does not include elements requiring extensive computation
5043 to compute Device bounds of drawn geometry. For instance, Paint with Path_Effect
5044 always returns false.
5045
5046 #Return true if Paint allows for fast computation of bounds ##
5047##
5048
5049#Method const SkRect& computeFastBounds(const SkRect& orig, SkRect* storage) const
5050 #Private
5051 (to be made private)
5052 ##
5053
5054 Only call this if canComputeFastBounds returned true. This takes a
5055 raw rectangle (the raw bounds of a shape), and adjusts it for stylistic
5056 effects in the paint (e.g. stroking). If needed, it uses the storage
Cary Clarkce101242017-09-01 15:51:02 -04005057 parameter. It returns the adjusted bounds that can then be used
Cary Clark8032b982017-07-28 11:04:54 -04005058 for SkCanvas::quickReject tests.
5059
Cary Clarkce101242017-09-01 15:51:02 -04005060 The returned Rect will either be orig or storage, thus the caller
Cary Clark8032b982017-07-28 11:04:54 -04005061 should not rely on storage being set to the result, but should always
Cary Clarkce101242017-09-01 15:51:02 -04005062 use the returned value. It is legal for orig and storage to be the same
5063 Rect.
Cary Clark8032b982017-07-28 11:04:54 -04005064
5065 #Private
5066 e.g.
5067 if (paint.canComputeFastBounds()) {
5068 SkRect r, storage;
5069 path.computeBounds(&r, SkPath::kFast_BoundsType);
5070 const SkRect& fastR = paint.computeFastBounds(r, &storage);
5071 if (canvas->quickReject(fastR, ...)) {
5072 // don't draw the path
5073 }
5074 }
5075 ##
5076
5077 #Param orig geometry modified by Paint when drawn ##
5078 #Param storage computed bounds of geometry; may not be nullptr ##
5079
5080 #Return fast computed bounds ##
5081##
5082
5083#Method const SkRect& computeFastStrokeBounds(const SkRect& orig,
5084 SkRect* storage) const
5085 #Private
5086 (to be made private)
5087 ##
5088
5089 #Param orig geometry modified by Paint when drawn ##
5090 #Param storage computed bounds of geometry ##
5091
5092 #Return fast computed bounds ##
5093##
5094
5095#Method const SkRect& doComputeFastBounds(const SkRect& orig, SkRect* storage,
5096 Style style) const
5097 #Private
5098 (to be made private)
5099 ##
5100
Cary Clarkce101242017-09-01 15:51:02 -04005101 Computes the bounds, overriding the Paint Style. This can be used to
5102 account for additional width required by stroking orig, without
5103 altering Style set to fill.
Cary Clark8032b982017-07-28 11:04:54 -04005104
5105 #Param orig geometry modified by Paint when drawn ##
5106 #Param storage computed bounds of geometry ##
5107 #Param style overrides Style ##
5108
5109 #Return fast computed bounds ##
5110##
5111
5112#Topic Fast_Bounds ##
5113
5114# ------------------------------------------------------------------------------
Cary Clark2dc84ad2018-01-26 12:56:22 -05005115#Method void toString(SkString* str) const
Cary Clark8032b982017-07-28 11:04:54 -04005116
5117#DefinedBy SK_TO_STRING_NONVIRT() ##
5118
5119#Private
5120macro expands to: void toString(SkString* str) const;
5121##
5122
Cary Clarkce101242017-09-01 15:51:02 -04005123Creates string representation of Paint. The representation is read by
5124internal debugging tools. The interface and implementation may be
5125suppressed by defining SK_IGNORE_TO_STRING.
Cary Clark8032b982017-07-28 11:04:54 -04005126
Cary Clarkce101242017-09-01 15:51:02 -04005127#Param str storage for string representation of Paint ##
Cary Clark8032b982017-07-28 11:04:54 -04005128
5129#Example
5130 SkPaint paint;
5131 SkString str;
5132 paint.toString(&str);
5133 const char textSize[] = "TextSize:";
5134 const int trailerSize = strlen("</dd><dt>");
5135 int textSizeLoc = str.find(textSize) + strlen(textSize) + trailerSize;
5136 const char* sizeStart = &str.c_str()[textSizeLoc];
5137 int textSizeEnd = SkStrFind(sizeStart, "</dd>");
5138 SkDebugf("text size = %.*s\n", textSizeEnd, sizeStart);
5139
5140 #StdOut
5141 text size = 12
5142 ##
5143
5144##
5145
Cary Clark2ade9972017-11-02 17:49:34 -04005146#SeeAlso SkPathEffect::toString SkMaskFilter::toString SkColorFilter::toString SkImageFilter::toString
Cary Clark8032b982017-07-28 11:04:54 -04005147
5148##
5149
5150# ------------------------------------------------------------------------------
5151
5152#Class SkPaint ##
5153
5154#Topic Paint ##