blob: 31031e76faeab5aaf084fc58623ed9203150ba06 [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
35#ToDo not all methods are in topics ##
36#ToDo subtopics are not in topics ##
37#Table
38#Legend
39# topics # description ##
40#Legend ##
41# Initializers # Constructors and initialization. ##
42# Destructor # Paint termination. ##
43# Management # Paint copying, moving, comparing. ##
44# Hinting # Glyph outline adjustment. ##
45# Flags # Attributes represented by single bits. ##
46# Anti-alias # Approximating coverage with transparency. ##
47# Dither # Distributing color error. ##
48# Device_Text # Increase precision of glyph position. ##
Cary Clarkce101242017-09-01 15:51:02 -040049# Font_Embedded_Bitmaps # Custom sized bitmap Glyphs. ##
Cary Clark8032b982017-07-28 11:04:54 -040050# Automatic_Hinting # Always adjust glyph paths. ##
51# Vertical_Text # Orient text from top to bottom. ##
52# Fake_Bold # Approximate font styles. ##
53# Full_Hinting_Spacing # Glyph spacing affected by hinting. ##
54# Filter_Quality_Methods # Get and set Filter_Quality. ##
55# Color_Methods # Get and set Color. ##
56# Style # Geometry filling, stroking. ##
57# Stroke_Width # Thickness perpendicular to geometry. ##
58# Miter_Limit # Maximum length of stroked corners. ##
59# Stroke_Cap # Decorations at ends of open strokes. ##
60# Stroke_Join # Decoration at corners of strokes. ##
61# Fill_Path # Make Path from Path_Effect, stroking. ##
62# Shader_Methods # Get and set Shader. ##
63# Color_Filter_Methods # Get and set Color_Filter. ##
64# Blend_Mode_Methods # Get and set Blend_Mode. ##
65# Path_Effect_Methods # Get and set Path_Effect. ##
66# Mask_Filter_Methods # Get and set Mask_Filter. ##
67# Typeface_Methods # Get and set Typeface. ##
Cary Clark8032b982017-07-28 11:04:54 -040068# Image_Filter_Methods # Get and set Image_Filter. ##
69# Draw_Looper_Methods # Get and set Draw_Looper. ##
70# Text_Align # Text placement relative to position. ##
71# Text_Size # Overall height in points. ##
72# Text_Scale_X # Text horizontal scale. ##
73# Text_Skew_X # Text horizontal slant. ##
Cary Clarkce101242017-09-01 15:51:02 -040074# Text_Encoding # Text encoded as characters or Glyphs. ##
Cary Clark8032b982017-07-28 11:04:54 -040075# Font_Metrics # Common glyph dimensions. ##
76# Measure_Text # Width, height, bounds of text. ##
Cary Clarkce101242017-09-01 15:51:02 -040077# Text_Path # Geometry of Glyphs. ##
Cary Clark8032b982017-07-28 11:04:54 -040078# Text_Intercepts # Advanced underline, strike through. ##
Cary Clarkce101242017-09-01 15:51:02 -040079# Fast_Bounds # Approximate area required by Paint. ##
Cary Clark8032b982017-07-28 11:04:54 -040080#Table ##
81#Subtopic ##
82
83#Subtopic Constants
84#Table
85#Legend
86# constants # description ##
87#Legend ##
88# Align # Glyph locations relative to text position. ##
89# Cap # Start and end geometry on stroked shapes. ##
90# Flags # Values described by bits and masks. ##
91# FontMetrics::FontMetricsFlags # Valid Font_Metrics. ##
92# Hinting # Level of glyph outline adjustment. ##
93# Join # Corner geometry on stroked shapes. ##
94# Style # Stroke, fill, or both. ##
Cary Clarkbc5697d2017-10-04 14:31:33 -040095# TextEncoding # Character or glyph encoded size. ##
Cary Clark8032b982017-07-28 11:04:54 -040096#Table ##
97#Subtopic ##
98
99#Subtopic Structs
100#Table
101#Legend
102# struct # description ##
103#Legend ##
104# FontMetrics # Typeface values. ##
105#Table ##
106#Subtopic ##
107
108#Subtopic Constructors
109#Table
110#Legend
111# # description ##
112#Legend ##
113# SkPaint() # Constructs with default values. ##
114# SkPaint(const SkPaint& paint) # Makes a shallow copy. ##
115# SkPaint(SkPaint&& paint) # Moves paint without copying it. ##
116# ~SkPaint() # Decreases Reference_Count of owned objects. ##
117#Table ##
118#Subtopic ##
119
120#Subtopic Operators
121#Table
122#Legend
123# operator # description ##
124#Legend ##
125# operator=(const SkPaint& paint) # Makes a shallow copy. ##
126# operator=(SkPaint&& paint) # Moves paint without copying it. ##
127# operator==(const SkPaint& a, const SkPaint& b) # Compares paints for equality. ##
128# operator!=(const SkPaint& a, const SkPaint& b) # Compares paints for inequality. ##
129#Table ##
130#Subtopic ##
131
132#Subtopic Member_Functions
133#Table
134#Legend
135# function # description ##
136#Legend ##
137# breakText # Returns text that fits in a width. ##
138# canComputeFastBounds # Returns true if settings allow for fast bounds computation. ##
139# computeFastBounds # Returns fill bounds for quick reject tests. ##
140# computeFastStrokeBounds # Returns stroke bounds for quick reject tests. ##
Cary Clarkce101242017-09-01 15:51:02 -0400141# containsText # Returns if all text corresponds to Glyphs. ##
142# countText # Returns number of Glyphs in text. ##
Cary Clark8032b982017-07-28 11:04:54 -0400143# doComputeFastBounds # Returns bounds for quick reject tests. ##
144# flatten() # Serializes into a buffer. ##
145# getAlpha # Returns Color_Alpha, color opacity. ##
Cary Clarkce101242017-09-01 15:51:02 -0400146# getBlendMode # Returns Blend_Mode, how colors combine with Device. ##
Cary Clark8032b982017-07-28 11:04:54 -0400147# getColor # Returns Color_Alpha and Color_RGB, one drawing color. ##
148# getColorFilter # Returns Color_Filter, how colors are altered. ##
149# getDrawLooper # Returns Draw_Looper, multiple layers. ##
150# getFillPath # Returns fill path equivalent to stroke. ##
151# getFilterQuality # Returns Filter_Quality, image filtering level. ##
152# getFlags # Returns Flags stored in a bit field. ##
153# getFontBounds # Returns union all glyph bounds. ##
154# getFontMetrics # Returns Typeface metrics scaled by text size. ##
155# getFontSpacing # Returns recommended spacing between lines. ##
156# getHash # Returns a shallow hash for equality checks. ##
157# getHinting # Returns Hinting, glyph outline adjustment level. ##
158# getImageFilter # Returns Image_Filter, alter pixels; blur. ##
159# getMaskFilter # Returns Mask_Filter, alterations to Mask_Alpha. ##
160# getPathEffect # Returns Path_Effect, modifications to path geometry; dashing. ##
161# getPosTextPath # Returns Path equivalent to positioned text. ##
162# getPosTextIntercepts # Returns where lines intersect positioned text; underlines. ##
163# getPosTextHIntercepts # Returns where lines intersect horizontally positioned text; underlines. ##
Mike Reed8ad91a92018-01-19 19:09:32 -0500164# getShader # Returns Shader, multiple drawing colors; gradients. ##
Cary Clark8032b982017-07-28 11:04:54 -0400165# getStrokeCap # Returns Cap, the area drawn at path ends. ##
166# getStrokeJoin # Returns Join, geometry on path corners. ##
167# getStrokeMiter # Returns Miter_Limit, angles with sharp corners. ##
168# getStrokeWidth # Returns thickness of the stroke. ##
169# getStyle # Returns Style: stroke, fill, or both. ##
170# getTextAlign # Returns Align: left, center, or right. ##
171# getTextBlobIntercepts # Returns where lines intersect Text_Blob; underlines. ##
Cary Clarkbc5697d2017-10-04 14:31:33 -0400172# getTextEncoding # Returns character or glyph encoded size. b ##
Cary Clark8032b982017-07-28 11:04:54 -0400173# getTextIntercepts # Returns where lines intersect text; underlines. ##
174# getTextPath # Returns Path equivalent to text. ##
175# getTextScaleX # Returns the text horizontal scale; condensed text. ##
176# getTextSkewX # Returns the text horizontal skew; oblique text. ##
177# getTextSize # Returns text size in points. ##
178# getTextWidths # Returns advance and bounds for each glyph in text. ##
179# getTypeface # Returns Typeface, font description. ##
Cary Clarkce101242017-09-01 15:51:02 -0400180# glyphsToUnichars # Converts Glyphs into text. ##
Cary Clark8032b982017-07-28 11:04:54 -0400181# isAntiAlias # Returns true if Anti-alias is set. ##
Cary Clarkce101242017-09-01 15:51:02 -0400182# isAutohinted # Returns true if Glyphs are always hinted. ##
Cary Clark8032b982017-07-28 11:04:54 -0400183# isDevKernText # Returns true if Full_Hinting_Spacing is set. ##
184# isDither # Returns true if Dither is set. ##
185# isEmbeddedBitmapText # Returns true if Font_Embedded_Bitmaps is set. ##
186# isFakeBoldText # Returns true if Fake_Bold is set. ##
187# isLCDRenderText # Returns true if LCD_Text is set. ##
188# isSrcOver # Returns true if Blend_Mode is SkBlendMode::kSrcOver. ##
189# isSubpixelText # Returns true if Subpixel_Text is set. ##
190# isVerticalText # Returns true if Vertical_Text is set. ##
191# measureText # Returns advance width and bounds of text. ##
192# nothingToDraw # Returns true if Paint prevents all drawing. ##
193# refColorFilter # References Color_Filter, how colors are altered. ##
194# refDrawLooper # References Draw_Looper, multiple layers. ##
195# refImageFilter # References Image_Filter, alter pixels; blur. ##
196# refMaskFilter # References Mask_Filter, alterations to Mask_Alpha. ##
197# refPathEffect # References Path_Effect, modifications to path geometry; dashing. ##
Mike Reed8ad91a92018-01-19 19:09:32 -0500198# refShader # References Shader, multiple drawing colors; gradients. ##
Cary Clark8032b982017-07-28 11:04:54 -0400199# refTypeface # References Typeface, font description. ##
200# reset() # Sets to default values. ##
201# setAlpha # Sets Color_Alpha, color opacity. ##
202# setAntiAlias # Sets or clears Anti-alias. ##
203# setARGB # Sets color by component. ##
Cary Clarkce101242017-09-01 15:51:02 -0400204# setAutohinted # Sets Glyphs to always be hinted. ##
Cary Clark8032b982017-07-28 11:04:54 -0400205# setBlendMode # Sets Blend_Mode, how colors combine with destination. ##
206# setColor # Sets Color_Alpha and Color_RGB, one drawing color. ##
207# setColorFilter # Sets Color_Filter, alters color. ##
208# setDevKernText # Sets or clears Full_Hinting_Spacing. ##
209# setDither # Sets or clears Dither. ##
210# setDrawLooper # Sets Draw_Looper, multiple layers. ##
211# setEmbeddedBitmapText # Sets or clears Font_Embedded_Bitmaps. ##
212# setFakeBoldText # Sets or clears Fake_Bold. ##
213# setFilterQuality # Sets Filter_Quality, the image filtering level. ##
214# setFlags # Sets multiple Flags in a bit field. ##
215# setHinting # Sets Hinting, glyph outline adjustment level. ##
216# setLCDRenderText # Sets or clears LCD_Text. ##
217# setMaskFilter # Sets Mask_Filter, alterations to Mask_Alpha. ##
218# setPathEffect # Sets Path_Effect, modifications to path geometry; dashing. ##
Cary Clark8032b982017-07-28 11:04:54 -0400219# setImageFilter # Sets Image_Filter, alter pixels; blur. ##
220# setShader # Sets Shader, multiple drawing colors; gradients. ##
221# setStrokeCap # Sets Cap, the area drawn at path ends. ##
222# setStrokeJoin # Sets Join, geometry on path corners. ##
223# setStrokeMiter # Sets Miter_Limit, angles with sharp corners. ##
224# setStrokeWidth # Sets thickness of the stroke. ##
225# setStyle # Sets Style: stroke, fill, or both. ##
226# setSubpixelText # Sets or clears Subpixel_Text. ##
227# setTextAlign # Sets Align: left, center, or right. ##
Cary Clarkbc5697d2017-10-04 14:31:33 -0400228# setTextEncoding # Sets character or glyph encoded size. ##
Cary Clark8032b982017-07-28 11:04:54 -0400229# setTextScaleX # Sets the text horizontal scale; condensed text. ##
230# setTextSkewX # Sets the text horizontal skew; oblique text. ##
231# setTextSize # Sets text size in points. ##
232# setTypeface # Sets Typeface, font description. ##
233# setVerticalText # Sets or clears Vertical_Text. ##
234# textToGlyphs # Converts text into glyph indices. ##
Cary Clarkce101242017-09-01 15:51:02 -0400235# toString # Converts Paint to machine readable form. ##
Cary Clark8032b982017-07-28 11:04:54 -0400236# unflatten() # Populates from a serialized stream. ##
237#Table ##
238#Subtopic ##
239
240#Topic Overview ##
241
242# ------------------------------------------------------------------------------
243#Topic Initializers
244
245#Method SkPaint()
246
247Constructs Paint with default values.
248
249#Table
250#Legend
251# attribute # default value ##
252#Legend ##
253# Anti-alias # false ##
Cary Clarkce101242017-09-01 15:51:02 -0400254# Blend_Mode # SkBlendMode::kSrcOver ##
Cary Clark8032b982017-07-28 11:04:54 -0400255# Color # SK_ColorBLACK ##
256# Color_Alpha # 255 ##
257# Color_Filter # nullptr ##
258# Dither # false ##
259# Draw_Looper # nullptr ##
260# Fake_Bold # false ##
261# Filter_Quality # kNone_SkFilterQuality ##
262# Font_Embedded_Bitmaps # false ##
263# Automatic_Hinting # false ##
264# Full_Hinting_Spacing # false ##
265# Hinting # kNormal_Hinting ##
266# Image_Filter # nullptr ##
267# LCD_Text # false ##
268# Linear_Text # false ##
269# Miter_Limit # 4 ##
270# Mask_Filter # nullptr ##
271# Path_Effect # nullptr ##
Cary Clark8032b982017-07-28 11:04:54 -0400272# Shader # nullptr ##
273# Style # kFill_Style ##
274# Text_Align # kLeft_Align ##
275# Text_Encoding # kUTF8_TextEncoding ##
276# Text_Scale_X # 1 ##
277# Text_Size # 12 ##
278# Text_Skew_X # 0 ##
279# Typeface # nullptr ##
280# Stroke_Cap # kButt_Cap ##
281# Stroke_Join # kMiter_Join ##
282# Stroke_Width # 0 ##
283# Subpixel_Text # false ##
284# Vertical_Text # false ##
285#Table ##
286
287The flags, text size, hinting, and miter limit may be overridden at compile time by defining
Cary Clarkce101242017-09-01 15:51:02 -0400288paint default values. The overrides may be included in "SkUserConfig.h" or predefined by the
Cary Clark8032b982017-07-28 11:04:54 -0400289build system.
290
291#Return default initialized Paint ##
292
293#Example
294#ToDo mark this as no output ##
295#Height 1
296###$ $ redefine markup character so preprocessor commands appear normally
297#ifndef SkUserConfig_DEFINED
298#define SkUserConfig_DEFINED
299
300#define SkPaintDefaults_Flags 0x01 // always enable antialiasing
301#define SkPaintDefaults_TextSize 24.f // double default font size
302#define SkPaintDefaults_Hinting 3 // use full hinting
303#define SkPaintDefaults_MiterLimit 10.f // use HTML Canvas miter limit setting
304
305#endif
306$$$# # restore original markup character
307##
308
309
310##
311
312#Method SkPaint(const SkPaint& paint)
313
314Makes a shallow copy of Paint. Typeface, Path_Effect, Shader,
Mike Reed8ad91a92018-01-19 19:09:32 -0500315Mask_Filter, Color_Filter, Draw_Looper, and Image_Filter are shared
Cary Clarkbad5ad72017-08-03 17:14:08 -0400316between the original paint and the copy. Objects containing Reference_Count increment
317their references by one.
Cary Clark8032b982017-07-28 11:04:54 -0400318
Mike Reed8ad91a92018-01-19 19:09:32 -0500319The referenced objects Path_Effect, Shader, Mask_Filter, Color_Filter,
Cary Clark8032b982017-07-28 11:04:54 -0400320Draw_Looper, and Image_Filter cannot be modified after they are created.
321This prevents objects with Reference_Count from being modified once Paint refers to them.
322
323#Param paint original to copy ##
324
325#Return shallow copy of paint ##
326
327#Example
328#ToDo why is this double-spaced on Fiddle? ##
329 SkPaint paint1;
330 paint1.setColor(SK_ColorRED);
331 SkPaint paint2(paint1);
332 paint2.setColor(SK_ColorBLUE);
333 SkDebugf("SK_ColorRED %c= paint1.getColor()\n", SK_ColorRED == paint1.getColor() ? '=' : '!');
334 SkDebugf("SK_ColorBLUE %c= paint2.getColor()\n", SK_ColorBLUE == paint2.getColor() ? '=' : '!');
335
336 #StdOut
337 SK_ColorRED == paint1.getColor()
338 SK_ColorBLUE == paint2.getColor()
339 ##
340##
341
342##
343
344#Method SkPaint(SkPaint&& paint)
345
Cary Clarkd0530ba2017-09-14 11:25:39 -0400346 Implements a move constructor to avoid increasing the reference counts
Cary Clark8032b982017-07-28 11:04:54 -0400347 of objects referenced by the paint.
348
349 After the call, paint is undefined, and can be safely destructed.
350
351 #Param paint original to move ##
352
353 #Return content of paint ##
354
355 #Example
356 SkPaint paint;
357 float intervals[] = { 5, 5 };
358 paint.setPathEffect(SkDashPathEffect::Make(intervals, SK_ARRAY_COUNT(intervals), 2.5f));
359 SkPaint dashed(std::move(paint));
360 SkDebugf("path effect unique: %s\n", dashed.getPathEffect()->unique() ? "true" : "false");
361
362 #StdOut
363 path effect unique: true
364 ##
365 ##
366
367##
368
369# ------------------------------------------------------------------------------
370
371#Method void reset()
372
Cary Clarkbc5697d2017-10-04 14:31:33 -0400373Sets all Paint contents to their initial values. This is equivalent to replacing
374Paint with the result of SkPaint().
Cary Clark8032b982017-07-28 11:04:54 -0400375
376#Example
377 SkPaint paint1, paint2;
378 paint1.setColor(SK_ColorRED);
379 paint1.reset();
380 SkDebugf("paint1 %c= paint2", paint1 == paint2 ? '=' : '!');
381
382 #StdOut
383 paint1 == paint2
384 ##
385##
386
387##
388
389#Topic ##
390
391# ------------------------------------------------------------------------------
392#Topic Destructor
393
394#Method ~SkPaint()
395
396Decreases Paint Reference_Count of owned objects: Typeface, Path_Effect, Shader,
Mike Reed8ad91a92018-01-19 19:09:32 -0500397Mask_Filter, Color_Filter, Draw_Looper, and Image_Filter. If the
Cary Clarkbad5ad72017-08-03 17:14:08 -0400398objects containing Reference_Count go to zero, they are deleted.
Cary Clark8032b982017-07-28 11:04:54 -0400399
400#NoExample
401##
402
403##
404
405##
406# ------------------------------------------------------------------------------
407#Topic Management
408
409#Method SkPaint& operator=(const SkPaint& paint)
410
411Makes a shallow copy of Paint. Typeface, Path_Effect, Shader,
Mike Reed8ad91a92018-01-19 19:09:32 -0500412Mask_Filter, Color_Filter, Draw_Looper, and Image_Filter are shared
Cary Clarkbad5ad72017-08-03 17:14:08 -0400413between the original paint and the copy. Objects containing Reference_Count in the
Cary Clark8032b982017-07-28 11:04:54 -0400414prior destination are decreased by one, and the referenced objects are deleted if the
Cary Clarkbad5ad72017-08-03 17:14:08 -0400415resulting count is zero. Objects containing Reference_Count in the parameter paint
416are increased by one. paint is unmodified.
Cary Clark8032b982017-07-28 11:04:54 -0400417
418#Param paint original to copy ##
419
420#Return content of paint ##
421
422#Example
423 SkPaint paint1, paint2;
424 paint1.setColor(SK_ColorRED);
425 paint2 = paint1;
426 SkDebugf("SK_ColorRED %c= paint1.getColor()\n", SK_ColorRED == paint1.getColor() ? '=' : '!');
427 SkDebugf("SK_ColorRED %c= paint2.getColor()\n", SK_ColorRED == paint2.getColor() ? '=' : '!');
428
429 #StdOut
430 SK_ColorRED == paint1.getColor()
431 SK_ColorRED == paint2.getColor()
432 ##
433##
434
435##
436
437# ------------------------------------------------------------------------------
438
439#Method SkPaint& operator=(SkPaint&& paint)
440
Cary Clarkd0530ba2017-09-14 11:25:39 -0400441Moves the paint to avoid increasing the reference counts
Cary Clarkbad5ad72017-08-03 17:14:08 -0400442of objects referenced by the paint parameter. Objects containing Reference_Count in the
443prior destination are decreased by one; those objects are deleted if the resulting count
444is zero.
Cary Clark8032b982017-07-28 11:04:54 -0400445
446After the call, paint is undefined, and can be safely destructed.
447
448 #Param paint original to move ##
449
450 #Return content of paint ##
451
452#Example
453 SkPaint paint1, paint2;
454 paint1.setColor(SK_ColorRED);
455 paint2 = std::move(paint1);
456 SkDebugf("SK_ColorRED == paint2.getColor()\n", SK_ColorRED == paint2.getColor() ? '=' : '!');
457
458 #StdOut
459 SK_ColorRED == paint2.getColor()
460 ##
461##
462
463##
464
465# ------------------------------------------------------------------------------
466
467#Method bool operator==(const SkPaint& a, const SkPaint& b)
468
469 Compares a and b, and returns true if a and b are equivalent. May return false
Mike Reed8ad91a92018-01-19 19:09:32 -0500470 if Typeface, Path_Effect, Shader, Mask_Filter, Color_Filter,
Cary Clark8032b982017-07-28 11:04:54 -0400471 Draw_Looper, or Image_Filter have identical contents but different pointers.
472
473 #Param a Paint to compare ##
474 #Param b Paint to compare ##
475
476 #Return true if Paint pair are equivalent ##
477
478 #Example
479 SkPaint paint1, paint2;
480 paint1.setColor(SK_ColorRED);
481 paint2.setColor(0xFFFF0000);
482 SkDebugf("paint1 %c= paint2\n", paint1 == paint2 ? '=' : '!');
483 float intervals[] = { 5, 5 };
484 paint1.setPathEffect(SkDashPathEffect::Make(intervals, 2, 2.5f));
485 paint2.setPathEffect(SkDashPathEffect::Make(intervals, 2, 2.5f));
486 SkDebugf("paint1 %c= paint2\n", paint1 == paint2 ? '=' : '!');
487
488 #StdOut
489 paint1 == paint2
490 paint1 != paint2
491 ##
492 ##
493
494##
495
496# ------------------------------------------------------------------------------
497
498#Method bool operator!=(const SkPaint& a, const SkPaint& b)
499
500 Compares a and b, and returns true if a and b are not equivalent. May return true
Mike Reed8ad91a92018-01-19 19:09:32 -0500501 if Typeface, Path_Effect, Shader, Mask_Filter, Color_Filter,
Cary Clark8032b982017-07-28 11:04:54 -0400502 Draw_Looper, or Image_Filter have identical contents but different pointers.
503
504 #Param a Paint to compare ##
505 #Param b Paint to compare ##
506
507 #Return true if Paint pair are not equivalent ##
508
509#Example
510 SkPaint paint1, paint2;
511 paint1.setColor(SK_ColorRED);
512 paint2.setColor(0xFFFF0000);
513 SkDebugf("paint1 %c= paint2\n", paint1 == paint2 ? '=' : '!');
514 SkDebugf("paint1 %c= paint2\n", paint1 != paint2 ? '!' : '=');
515
516 #StdOut
517 paint1 == paint2
518 paint1 == paint2
519 ##
520##
521
522##
523
524# ------------------------------------------------------------------------------
525
526#Method uint32_t getHash() const
527
528Returns a hash generated from Paint values and pointers.
529Identical hashes guarantee that the paints are
530equivalent, but differing hashes do not guarantee that the paints have differing
531contents.
532
533If operator==(const SkPaint& a, const SkPaint& b) returns true for two paints,
534their hashes are also equal.
535
536The hash returned is platform and implementation specific.
537
538#Return a shallow hash ##
539
540#Example
541 SkPaint paint1, paint2;
542 paint1.setColor(SK_ColorRED);
543 paint2.setColor(0xFFFF0000);
544 SkDebugf("paint1 %c= paint2\n", paint1 == paint2 ? '=' : '!');
545 SkDebugf("paint1.getHash() %c= paint2.getHash()\n",
546 paint1.getHash() == paint2.getHash() ? '=' : '!');
547
548 #StdOut
549 paint1 == paint2
550 paint1.getHash() == paint2.getHash()
551 ##
552##
553
554##
555
556# ------------------------------------------------------------------------------
557
558#Method void flatten(SkWriteBuffer& buffer) const
559
560Serializes Paint into a buffer. A companion unflatten() call
561can reconstitute the paint at a later time.
562
563#Param buffer Write_Buffer receiving the flattened Paint data ##
564
Cary Clark61ca7c52018-01-02 11:34:14 -0500565# why is flatten() public?
566#Bug 6172 ##
Cary Clark8032b982017-07-28 11:04:54 -0400567
Cary Clark61ca7c52018-01-02 11:34:14 -0500568#NoExample
Cary Clark8032b982017-07-28 11:04:54 -0400569##
570
571##
572
573# ------------------------------------------------------------------------------
574
Mike Reede97e7922018-01-18 15:57:38 -0500575#Method bool unflatten(SkReadBuffer& buffer)
Cary Clark8032b982017-07-28 11:04:54 -0400576
577Populates Paint, typically from a serialized stream, created by calling
578flatten() at an earlier time.
579
580SkReadBuffer class is not public, so unflatten() cannot be meaningfully called
581by the client.
582
Cary Clarkce101242017-09-01 15:51:02 -0400583#Param buffer serialized data describing Paint content ##
Cary Clark8032b982017-07-28 11:04:54 -0400584
Mike Reede97e7922018-01-18 15:57:38 -0500585#Return false if the buffer contained invalid data for initializing the paint. ##
586
Cary Clark8032b982017-07-28 11:04:54 -0400587# why is unflatten() public?
588#Bug 6172 ##
589
590#NoExample
591##
592
Cary Clark2ade9972017-11-02 17:49:34 -0400593#SeeAlso SkReadBuffer
Cary Clark8032b982017-07-28 11:04:54 -0400594
595##
596
597#Topic Management ##
598
599# ------------------------------------------------------------------------------
600#Topic Hinting
601
602#Enum Hinting
603
604#Code
605 enum Hinting {
606 kNo_Hinting = 0,
607 kSlight_Hinting = 1,
608 kNormal_Hinting = 2,
Cary Clarkbad5ad72017-08-03 17:14:08 -0400609 kFull_Hinting = 3,
Cary Clark8032b982017-07-28 11:04:54 -0400610 };
611##
612
613Hinting adjusts the glyph outlines so that the shape provides a uniform
614look at a given point size on font engines that support it. Hinting may have a
615muted effect or no effect at all depending on the platform.
616
617The four levels roughly control corresponding features on platforms that use FreeType
618as the Font_Engine.
619
620#Const kNo_Hinting 0
621 Leaves glyph outlines unchanged from their native representation.
622 With FreeType, this is equivalent to the FT_LOAD_NO_HINTING
623 bit-field constant supplied to FT_Load_Glyph, which indicates that the vector
624 outline being loaded should not be fitted to the pixel grid but simply scaled
625 to 26.6 fractional pixels.
626##
627#Const kSlight_Hinting 1
628 Modifies glyph outlines minimally to improve constrast.
629 With FreeType, this is equivalent in spirit to the
630 FT_LOAD_TARGET_LIGHT value supplied to FT_Load_Glyph. It chooses a
631 lighter hinting algorithm for non-monochrome modes.
Cary Clarkce101242017-09-01 15:51:02 -0400632 Generated Glyphs may be fuzzy but better resemble their original shape.
Cary Clark8032b982017-07-28 11:04:54 -0400633##
634#Const kNormal_Hinting 2
635 Modifies glyph outlines to improve constrast. This is the default.
Cary Clark6fc50412017-09-21 12:31:06 -0400636 With FreeType, this supplies FT_LOAD_TARGET_NORMAL to FT_Load_Glyph,
Cary Clark8032b982017-07-28 11:04:54 -0400637 choosing the default hinting algorithm, which is optimized for standard
638 gray-level rendering.
639##
640#Const kFull_Hinting 3
Cary Clark6fc50412017-09-21 12:31:06 -0400641 Modifies glyph outlines for maxiumum constrast. With FreeType, this selects
642 FT_LOAD_TARGET_LCD or FT_LOAD_TARGET_LCD_V if kLCDRenderText_Flag is set.
643 FT_LOAD_TARGET_LCD is a variant of FT_LOAD_TARGET_NORMAL optimized for
644 horizontally decimated LCD displays; FT_LOAD_TARGET_LCD_V is a
Cary Clark8032b982017-07-28 11:04:54 -0400645 variant of FT_LOAD_TARGET_NORMAL optimized for vertically decimated LCD displays.
646##
647
648#Track
649#File SkFontHost_mac.cpp:1777,1806
650#Time 2013-03-03 07:16:29 +0000
651#Bug 915 ##
652On OS_X and iOS, hinting controls whether Core_Graphics dilates the font outlines
653to account for LCD text. No hinting uses Core_Text gray scale output.
654Normal hinting uses Core_Text LCD output. If kLCDRenderText_Flag is clear,
655the LCD output is reduced to a single grayscale channel.
656#Track ##
657
658On Windows with DirectWrite, Hinting has no effect.
659
660Hinting defaults to kNormal_Hinting.
661Set SkPaintDefaults_Hinting at compile time to change the default setting.
662
663#ToDo add an illustration? linux running GM:typefacerendering is best for this
664 the hinting variations are every other character horizontally
665#ToDo ##
666
667#Enum ##
668
669#Method Hinting getHinting() const
670
671 Returns level of glyph outline adjustment.
672
673 #Return one of: kNo_Hinting, kSlight_Hinting, kNormal_Hinting, kFull_Hinting ##
674
675 #Example
676 SkPaint paint;
677 SkDebugf("SkPaint::kNormal_Hinting %c= paint.getHinting()\n",
678 SkPaint::kNormal_Hinting == paint.getHinting() ? '=' : ':');
679
680 #StdOut
681 SkPaint::kNormal_Hinting == paint.getHinting()
682 ##
683 ##
684##
685
686#Method void setHinting(Hinting hintingLevel)
687
688 Sets level of glyph outline adjustment.
689 Does not check for valid values of hintingLevel.
690
691 #Table
692 #Legend
693 # Hinting # value # effect on generated glyph outlines ##
694 ##
695 # kNo_Hinting # 0 # leaves glyph outlines unchanged from their native representation ##
Cary Clarkce101242017-09-01 15:51:02 -0400696 # kSlight_Hinting # 1 # modifies glyph outlines minimally to improve contrast ##
697 # kNormal_Hinting # 2 # modifies glyph outlines to improve contrast ##
698 # kFull_Hinting # 3 # modifies glyph outlines for maximum contrast ##
Cary Clark8032b982017-07-28 11:04:54 -0400699 ##
700
701 #Param hintingLevel one of: kNo_Hinting, kSlight_Hinting, kNormal_Hinting, kFull_Hinting ##
702
703 #Example
704 SkPaint paint1, paint2;
705 paint2.setHinting(SkPaint::kNormal_Hinting);
706 SkDebugf("paint1 %c= paint2\n", paint1 == paint2 ? '=' : ':');
707
708 #StdOut
709 paint1 == paint2
710 ##
711 ##
712##
713
714#Topic ##
715# ------------------------------------------------------------------------------
716#Topic Flags
717
718#Enum Flags
719
720#Code
721 enum Flags {
722 kAntiAlias_Flag = 0x01,
723 kDither_Flag = 0x04,
724 kFakeBoldText_Flag = 0x20,
725 kLinearText_Flag = 0x40,
726 kSubpixelText_Flag = 0x80,
727 kDevKernText_Flag = 0x100,
728 kLCDRenderText_Flag = 0x200,
729 kEmbeddedBitmapText_Flag = 0x400,
730 kAutoHinting_Flag = 0x800,
731 kVerticalText_Flag = 0x1000,
732 kGenA8FromLCD_Flag = 0x2000,
733
734 kAllFlags = 0xFFFF,
735 };
736
737##
738
739The bit values stored in Flags.
740The default value for Flags, normally zero, can be changed at compile time
741with a custom definition of SkPaintDefaults_Flags.
742All flags can be read and written explicitly; Flags allows manipulating
743multiple settings at once.
744
745 #Const kAntiAlias_Flag 0x0001
746 mask for setting Anti-alias
747 ##
748 #Const kDither_Flag 0x0004
749 mask for setting Dither
750 ##
751
752 #Const kFakeBoldText_Flag 0x0020
753 mask for setting Fake_Bold
754 ##
755 #Const kLinearText_Flag 0x0040
756 mask for setting Linear_Text
757 ##
758 #Const kSubpixelText_Flag 0x0080
759 mask for setting Subpixel_Text
760 ##
761 #Const kDevKernText_Flag 0x0100
762 mask for setting Full_Hinting_Spacing
763 ##
764 #Const kLCDRenderText_Flag 0x0200
765 mask for setting LCD_Text
766 ##
767 #Const kEmbeddedBitmapText_Flag 0x0400
768 mask for setting Font_Embedded_Bitmaps
769 ##
770 #Const kAutoHinting_Flag 0x0800
771 mask for setting Automatic_Hinting
772 ##
773 #Const kVerticalText_Flag 0x1000
774 mask for setting Vertical_Text
775 ##
776 #Const kGenA8FromLCD_Flag 0x2000
777 #Private
778 Hack for GDI -- do not use if you can help it
779 ##
780 not intended for public use
781 ##
782 #Const kAllFlags 0xFFFF
783 mask of all Flags, including private flags and flags reserved for future use
784 ##
785
786Flags default to all flags clear, disabling the associated feature.
787
788#Enum ##
789
790#Enum ReserveFlags
791
792#Private
793To be deprecated; only valid for Android framework.
794##
795
796#Code
797 enum ReserveFlags {
798 kUnderlineText_ReserveFlag = 0x08,
799 kStrikeThruText_ReserveFlag = 0x10,
800 };
801##
802
803 #Const kUnderlineText_ReserveFlag 0x0008
804 mask for underline text
805 ##
806 #Const kStrikeThruText_ReserveFlag 0x0010
807 mask for strike-thru text
808 ##
809
Cary Clark2ade9972017-11-02 17:49:34 -0400810#SeeAlso Flags getFlags
Cary Clark8032b982017-07-28 11:04:54 -0400811
812#Enum ##
813
814#Method uint32_t getFlags() const
815
816Returns paint settings described by Flags. Each setting uses one
817bit, and can be tested with Flags members.
818
819#Return zero, one, or more bits described by Flags ##
820
821#Example
822 SkPaint paint;
823 paint.setAntiAlias(true);
824 SkDebugf("(SkPaint::kAntiAlias_Flag & paint.getFlags()) %c= 0\n",
825 SkPaint::kAntiAlias_Flag & paint.getFlags() ? '!' : '=');
826
827 #StdOut
828 (SkPaint::kAntiAlias_Flag & paint.getFlags()) != 0
829 ##
830##
831
832##
833
834#Method void setFlags(uint32_t flags)
835
836Replaces Flags with flags, the union of the Flags members.
837All Flags members may be cleared, or one or more may be set.
838
839#Param flags union of Flags for Paint ##
840
841#Example
842 SkPaint paint;
843 paint.setFlags((uint32_t) (SkPaint::kAntiAlias_Flag | SkPaint::kDither_Flag));
844 SkDebugf("paint.isAntiAlias()\n", paint.isAntiAlias() ? '!' : '=');
845 SkDebugf("paint.isDither()\n", paint.isDither() ? '!' : '=');
846
847 #StdOut
848 paint.isAntiAlias()
849 paint.isDither()
850 ##
851##
852
853##
854
855#Topic ##
856# ------------------------------------------------------------------------------
857#Topic Anti-alias
858#Alias Anti-alias # permit hyphen in topic name, should probably not substitute hyphen with _
859
860Anti-alias drawing approximates partial pixel coverage with transparency.
861If kAntiAlias_Flag is clear, pixel centers contained by the shape edge are drawn opaque.
862If kAntiAlias_Flag is set, pixels are drawn with Color_Alpha equal to their coverage.
863
Cary Clarkce101242017-09-01 15:51:02 -0400864The rule for Aliased pixels is inconsistent across platforms. A shape edge
Cary Clark8032b982017-07-28 11:04:54 -0400865passing through the pixel center may, but is not required to, draw the pixel.
866
Cary Clarkce101242017-09-01 15:51:02 -0400867Raster_Engine draws Aliased pixels whose centers are on or to the right of the start of an
Cary Clark8032b982017-07-28 11:04:54 -0400868active Path edge, and whose center is to the left of the end of the active Path edge.
869
870#ToDo add illustration of raster pixels ##
871
Cary Clarkce101242017-09-01 15:51:02 -0400872A platform may only support Anti-aliased drawing. Some GPU-backed platforms use
873Supersampling to Anti-alias all drawing, and have no mechanism to selectively
874Alias.
Cary Clark8032b982017-07-28 11:04:54 -0400875
Cary Clarkce101242017-09-01 15:51:02 -0400876The amount of coverage computed for Anti-aliased pixels also varies across platforms.
Cary Clark8032b982017-07-28 11:04:54 -0400877
878Anti-alias is disabled by default.
879Anti-alias can be enabled by default by setting SkPaintDefaults_Flags to kAntiAlias_Flag
880at compile time.
881
882 #Example
883 #Width 512
884 #Description
885 A red line is drawn with transparency on the edges to make it look smoother.
886 A blue line draws only where the pixel centers are contained.
Cary Clarkce101242017-09-01 15:51:02 -0400887 The lines are drawn into Bitmap, then drawn magnified to make the
888 Aliasing easier to see.
Cary Clark8032b982017-07-28 11:04:54 -0400889 ##
890
891 void draw(SkCanvas* canvas) {
892 SkBitmap bitmap;
893 bitmap.allocN32Pixels(50, 50);
894 SkCanvas offscreen(bitmap);
895 SkPaint paint;
896 paint.setStyle(SkPaint::kStroke_Style);
897 paint.setStrokeWidth(10);
898 for (bool antialias : { false, true }) {
899 paint.setColor(antialias ? SK_ColorRED : SK_ColorBLUE);
900 paint.setAntiAlias(antialias);
901 bitmap.eraseColor(0);
902 offscreen.drawLine(5, 5, 15, 30, paint);
903 canvas->drawLine(5, 5, 15, 30, paint);
904 canvas->save();
905 canvas->scale(10, 10);
906 canvas->drawBitmap(bitmap, antialias ? 12 : 0, 0);
907 canvas->restore();
908 canvas->translate(15, 0);
909 }
910 }
911 ##
912
913#Method bool isAntiAlias() const
914
915 If true, pixels on the active edges of Path may be drawn with partial transparency.
916
917 Equivalent to getFlags masked with kAntiAlias_Flag.
918
919 #Return kAntiAlias_Flag state ##
920
921 #Example
922 SkPaint paint;
923 SkDebugf("paint.isAntiAlias() %c= !!(paint.getFlags() & SkPaint::kAntiAlias_Flag)\n",
924 paint.isAntiAlias() == !!(paint.getFlags() & SkPaint::kAntiAlias_Flag) ? '=' : '!');
925 paint.setAntiAlias(true);
926 SkDebugf("paint.isAntiAlias() %c= !!(paint.getFlags() & SkPaint::kAntiAlias_Flag)\n",
927 paint.isAntiAlias() == !!(paint.getFlags() & SkPaint::kAntiAlias_Flag) ? '=' : '!');
928
929 #StdOut
930 paint.isAntiAlias() == !!(paint.getFlags() & SkPaint::kAntiAlias_Flag)
931 paint.isAntiAlias() == !!(paint.getFlags() & SkPaint::kAntiAlias_Flag)
932 ##
933 ##
934##
935
936#Method void setAntiAlias(bool aa)
937
938 Requests, but does not require, that Path edge pixels draw opaque or with
939 partial transparency.
940
941 Sets kAntiAlias_Flag if aa is true.
942 Clears kAntiAlias_Flag if aa is false.
943
944 #Param aa setting for kAntiAlias_Flag ##
945
946 #Example
947 SkPaint paint1, paint2;
948 paint1.setAntiAlias(true);
949 paint2.setFlags(paint2.getFlags() | SkPaint::kAntiAlias_Flag);
950 SkDebugf("paint1 %c= paint2\n", paint1 == paint2 ? '=' : '!');
951
952 #StdOut
953 paint1 == paint2
954 ##
955 ##
956
957##
958
959#Topic ##
960# ------------------------------------------------------------------------------
961#Topic Dither
962
Cary Clarkce101242017-09-01 15:51:02 -0400963Dither increases fidelity by adjusting the color of adjacent pixels.
Cary Clark8032b982017-07-28 11:04:54 -0400964This can help to smooth color transitions and reducing banding in gradients.
965Dithering lessens visible banding from kRGB_565_SkColorType
966and kRGBA_8888_SkColorType gradients,
967and improves rendering into a kRGB_565_SkColorType Surface.
968
969Dithering is always enabled for linear gradients drawing into
970kRGB_565_SkColorType Surface and kRGBA_8888_SkColorType Surface.
971Dither cannot be enabled for kAlpha_8_SkColorType Surface and
972kRGBA_F16_SkColorType Surface.
973
974Dither is disabled by default.
975Dither can be enabled by default by setting SkPaintDefaults_Flags to kDither_Flag
976at compile time.
977
978Some platform implementations may ignore dithering. Set
979
980#Define SK_IGNORE_GPU_DITHER
981
982to ignore Dither on GPU_Surface.
983
984#Example
985#Description
986Dithering in the bottom half more closely approximates the requested color by
987alternating nearby colors from pixel to pixel.
988##
989void draw(SkCanvas* canvas) {
990 SkBitmap bm16;
991 bm16.allocPixels(SkImageInfo::Make(32, 32, kRGB_565_SkColorType, kOpaque_SkAlphaType));
992 SkCanvas c16(bm16);
993 SkPaint colorPaint;
994 for (auto dither : { false, true } ) {
995 colorPaint.setDither(dither);
996 for (auto colors : { 0xFF333333, 0xFF666666, 0xFF999999, 0xFFCCCCCC } ) {
997 for (auto mask : { 0xFFFF0000, 0xFF00FF00, 0xFF0000FF, 0xFFFFFFFF } ) {
998 colorPaint.setColor(colors & mask);
999 c16.drawRect({0, 0, 8, 4}, colorPaint);
1000 c16.translate(8, 0);
1001 }
1002 c16.translate(-32, 4);
1003 }
1004 }
1005 canvas->scale(8, 8);
1006 canvas->drawBitmap(bm16, 0, 0);
1007}
1008##
1009
1010#Example
1011#Description
1012Dithering introduces subtle adjustments to color to smooth gradients.
1013Drawing the gradient repeatedly with SkBlendMode::kPlus exaggerates the
1014dither, making it easier to see.
1015##
1016void draw(SkCanvas* canvas) {
1017 canvas->clear(0);
1018 SkBitmap bm32;
1019 bm32.allocPixels(SkImageInfo::Make(20, 10, kN32_SkColorType, kPremul_SkAlphaType));
1020 SkCanvas c32(bm32);
1021 SkPoint points[] = {{0, 0}, {20, 0}};
1022 SkColor colors[] = {0xFF334455, 0xFF662211 };
1023 SkPaint paint;
1024 paint.setShader(SkGradientShader::MakeLinear(
1025 points, colors, nullptr, SK_ARRAY_COUNT(colors),
1026 SkShader::kClamp_TileMode, 0, nullptr));
1027 paint.setDither(true);
1028 c32.drawPaint(paint);
1029 canvas->scale(12, 12);
1030 canvas->drawBitmap(bm32, 0, 0);
1031 paint.setBlendMode(SkBlendMode::kPlus);
1032 canvas->drawBitmap(bm32, 0, 11, &paint);
1033 canvas->drawBitmap(bm32, 0, 11, &paint);
1034 canvas->drawBitmap(bm32, 0, 11, &paint);
1035}
1036##
1037
1038#Method bool isDither() const
1039
1040 If true, color error may be distributed to smooth color transition.
1041
1042 Equivalent to getFlags masked with kDither_Flag.
1043
1044 #Return kDither_Flag state ##
1045
1046 #Example
1047 SkPaint paint;
1048 SkDebugf("paint.isDither() %c= !!(paint.getFlags() & SkPaint::kDither_Flag)\n",
1049 paint.isDither() == !!(paint.getFlags() & SkPaint::kDither_Flag) ? '=' : '!');
1050 paint.setDither(true);
1051 SkDebugf("paint.isDither() %c= !!(paint.getFlags() & SkPaint::kDither_Flag)\n",
1052 paint.isDither() == !!(paint.getFlags() & SkPaint::kDither_Flag) ? '=' : '!');
1053
1054 #StdOut
1055 paint.isDither() == !!(paint.getFlags() & SkPaint::kDither_Flag)
1056 paint.isDither() == !!(paint.getFlags() & SkPaint::kDither_Flag)
1057 ##
1058 ##
1059
1060##
1061
1062#Method void setDither(bool dither)
1063
1064 Requests, but does not require, to distribute color error.
1065
1066 Sets kDither_Flag if dither is true.
1067 Clears kDither_Flag if dither is false.
1068
1069 #Param dither setting for kDither_Flag ##
1070
1071 #Example
1072 SkPaint paint1, paint2;
1073 paint1.setDither(true);
1074 paint2.setFlags(paint2.getFlags() | SkPaint::kDither_Flag);
1075 SkDebugf("paint1 %c= paint2\n", paint1 == paint2 ? '=' : '!');
1076
1077 #StdOut
1078 paint1 == paint2
1079 ##
1080 ##
1081
1082 #SeeAlso kRGB_565_SkColorType
1083
1084##
1085
1086#SeeAlso Gradient Color_RGB-565
1087
1088#Topic ##
1089# ------------------------------------------------------------------------------
1090#Topic Device_Text
1091
1092LCD_Text and Subpixel_Text increase the precision of glyph position.
1093
1094When set, Flags kLCDRenderText_Flag takes advantage of the organization of Color_RGB stripes that
1095create a color, and relies
Cary Clarkce101242017-09-01 15:51:02 -04001096on the small size of the stripe and visual perception to make the color fringing imperceptible.
Cary Clark8032b982017-07-28 11:04:54 -04001097LCD_Text can be enabled on devices that orient stripes horizontally or vertically, and that order
1098the color components as Color_RGB or Color_RBG.
1099
1100Flags kSubpixelText_Flag uses the pixel transparency to represent a fractional offset.
1101As the opaqueness
1102of the color increases, the edge of the glyph appears to move towards the outside of the pixel.
1103
1104Either or both techniques can be enabled.
1105kLCDRenderText_Flag and kSubpixelText_Flag are clear by default.
1106LCD_Text or Subpixel_Text can be enabled by default by setting SkPaintDefaults_Flags to
1107kLCDRenderText_Flag or kSubpixelText_Flag (or both) at compile time.
1108
1109#Example
1110 #Description
1111 Four commas are drawn normally and with combinations of LCD_Text and Subpixel_Text.
Cary Clarkce101242017-09-01 15:51:02 -04001112 When Subpixel_Text is disabled, the comma Glyphs are identical, but not evenly spaced.
1113 When Subpixel_Text is enabled, the comma Glyphs are unique, but appear evenly spaced.
Cary Clark8032b982017-07-28 11:04:54 -04001114 ##
1115
1116 SkBitmap bitmap;
1117 bitmap.allocN32Pixels(24, 33);
1118 SkCanvas offscreen(bitmap);
1119 offscreen.clear(SK_ColorWHITE);
1120 SkPaint paint;
1121 paint.setAntiAlias(true);
1122 paint.setTextSize(20);
1123 for (bool lcd : { false, true }) {
1124 paint.setLCDRenderText(lcd);
1125 for (bool subpixel : { false, true }) {
1126 paint.setSubpixelText(subpixel);
1127 offscreen.drawString(",,,,", 0, 4, paint);
1128 offscreen.translate(0, 7);
1129 }
1130 }
1131 canvas->drawBitmap(bitmap, 4, 12);
1132 canvas->scale(9, 9);
1133 canvas->drawBitmap(bitmap, 4, -1);
1134##
1135
1136#Subtopic Linear_Text
1137#Alias Linear_Text # makes this a top level name, since it is under subtopic Device_Text
1138
1139Linear_Text selects whether text is rendered as a Glyph or as a Path.
1140If kLinearText_Flag is set, it has the same effect as setting Hinting to kNormal_Hinting.
Cary Clarkd0530ba2017-09-14 11:25:39 -04001141If kLinearText_Flag is clear, it is the same as setting Hinting to kNo_Hinting.
Cary Clark8032b982017-07-28 11:04:54 -04001142
1143#Method bool isLinearText() const
1144
1145 If true, text is converted to Path before drawing and measuring.
1146
1147 Equivalent to getFlags masked with kLinearText_Flag.
1148
1149 #Return kLinearText_Flag state ##
1150
1151 #Example
1152 #Height 128
1153 void draw(SkCanvas* canvas) {
1154 SkPaint paint;
1155 paint.setAntiAlias(true);
1156 const char testStr[] = "xxxx xxxx";
1157 for (auto linearText : { false, true } ) {
1158 paint.setLinearText(linearText);
1159 paint.setTextSize(24);
1160 canvas->drawString(paint.isLinearText() ? "linear" : "hinted", 128, 30, paint);
1161 for (SkScalar textSize = 8; textSize < 30; textSize *= 1.22f) {
1162 paint.setTextSize(textSize);
1163 canvas->translate(0, textSize);
1164 canvas->drawString(testStr, 10, 0, paint);
1165 }
1166 }
1167 }
1168 ##
1169
1170 #SeeAlso setLinearText Hinting
1171##
1172
1173#Method void setLinearText(bool linearText)
1174
1175 If true, text is converted to Path before drawing and measuring.
1176 By default, kLinearText_Flag is clear.
1177
1178 Sets kLinearText_Flag if linearText is true.
1179 Clears kLinearText_Flag if linearText is false.
1180
1181 #Param linearText setting for kLinearText_Flag ##
1182
1183 #Example
1184 #Height 128
1185 void draw(SkCanvas* canvas) {
1186 SkPaint paint;
1187 paint.setAntiAlias(true);
1188 const char testStr[] = "abcd efgh";
1189 for (int textSize : { 12, 24 } ) {
1190 paint.setTextSize(textSize);
1191 for (auto linearText : { false, true } ) {
1192 paint.setLinearText(linearText);
1193 SkString width;
1194 width.appendScalar(paint.measureText(testStr, SK_ARRAY_COUNT(testStr), nullptr));
1195 canvas->translate(0, textSize + 4);
1196 canvas->drawString(testStr, 10, 0, paint);
1197 canvas->drawString(width, 128, 0, paint);
1198 }
1199 }
1200 }
1201 ##
1202
1203 #SeeAlso isLinearText Hinting
1204##
1205
1206#Subtopic ##
1207
1208#Subtopic Subpixel_Text
1209#Alias Subpixel_Text # makes this a top level name, since it is under subtopic Device_Text
1210
1211Flags kSubpixelText_Flag uses the pixel transparency to represent a fractional offset.
1212As the opaqueness
1213of the color increases, the edge of the glyph appears to move towards the outside of the pixel.
1214
1215#Method bool isSubpixelText() const
1216
Cary Clarkce101242017-09-01 15:51:02 -04001217 If true, Glyphs at different sub-pixel positions may differ on pixel edge coverage.
Cary Clark8032b982017-07-28 11:04:54 -04001218
1219 Equivalent to getFlags masked with kSubpixelText_Flag.
1220
1221 #Return kSubpixelText_Flag state ##
1222
1223 #Example
1224SkPaint paint;
1225SkDebugf("paint.isSubpixelText() %c= !!(paint.getFlags() & SkPaint::kSubpixelText_Flag)\n",
1226 paint.isSubpixelText() == !!(paint.getFlags() & SkPaint::kSubpixelText_Flag) ? '=' : '!');
1227paint.setSubpixelText(true);
1228SkDebugf("paint.isSubpixelText() %c= !!(paint.getFlags() & SkPaint::kSubpixelText_Flag)\n",
1229 paint.isSubpixelText() == !!(paint.getFlags() & SkPaint::kSubpixelText_Flag) ? '=' : '!');
1230
1231 #StdOut
1232 paint.isSubpixelText() == !!(paint.getFlags() & SkPaint::kSubpixelText_Flag)
1233 paint.isSubpixelText() == !!(paint.getFlags() & SkPaint::kSubpixelText_Flag)
1234 ##
1235 ##
1236
1237##
1238
1239#Method void setSubpixelText(bool subpixelText)
1240
Cary Clarkce101242017-09-01 15:51:02 -04001241 Requests, but does not require, that Glyphs respect sub-pixel positioning.
Cary Clark8032b982017-07-28 11:04:54 -04001242
1243 Sets kSubpixelText_Flag if subpixelText is true.
1244 Clears kSubpixelText_Flag if subpixelText is false.
1245
1246 #Param subpixelText setting for kSubpixelText_Flag ##
1247
1248 #Example
1249 SkPaint paint1, paint2;
1250 paint1.setSubpixelText(true);
1251 paint2.setFlags(paint2.getFlags() | SkPaint::kSubpixelText_Flag);
1252 SkDebugf("paint1 %c= paint2\n", paint1 == paint2 ? '=' : '!');
1253
1254 #StdOut
1255 paint1 == paint2
1256 ##
1257 ##
1258
1259##
1260
1261#Subtopic ##
1262
1263#Subtopic LCD_Text
1264#Alias LCD_Text # makes this a top level name, since it is under subtopic Device_Text
1265
1266When set, Flags kLCDRenderText_Flag takes advantage of the organization of Color_RGB stripes that
1267create a color, and relies
Cary Clarkce101242017-09-01 15:51:02 -04001268on the small size of the stripe and visual perception to make the color fringing imperceptible.
Cary Clark8032b982017-07-28 11:04:54 -04001269LCD_Text can be enabled on devices that orient stripes horizontally or vertically, and that order
1270the color components as Color_RGB or Color_RBG.
1271
1272#Method bool isLCDRenderText() const
1273
Cary Clarkce101242017-09-01 15:51:02 -04001274 If true, Glyphs may use LCD striping to improve glyph edges.
Cary Clark8032b982017-07-28 11:04:54 -04001275
1276 Returns true if Flags kLCDRenderText_Flag is set.
1277
1278 #Return kLCDRenderText_Flag state ##
1279
1280 #Example
1281SkPaint paint;
1282SkDebugf("paint.isLCDRenderText() %c= !!(paint.getFlags() & SkPaint::kLCDRenderText_Flag)\n",
1283 paint.isLCDRenderText() == !!(paint.getFlags() & SkPaint::kLCDRenderText_Flag) ? '=' : '!');
1284paint.setLCDRenderText(true);
1285SkDebugf("paint.isLCDRenderText() %c= !!(paint.getFlags() & SkPaint::kLCDRenderText_Flag)\n",
1286 paint.isLCDRenderText() == !!(paint.getFlags() & SkPaint::kLCDRenderText_Flag) ? '=' : '!');
1287
1288 #StdOut
1289 paint.isLCDRenderText() == !!(paint.getFlags() & SkPaint::kLCDRenderText_Flag)
1290 paint.isLCDRenderText() == !!(paint.getFlags() & SkPaint::kLCDRenderText_Flag)
1291 ##
1292 ##
1293
1294##
1295
1296#Method void setLCDRenderText(bool lcdText)
1297
Cary Clarkce101242017-09-01 15:51:02 -04001298 Requests, but does not require, that Glyphs use LCD striping for glyph edges.
Cary Clark8032b982017-07-28 11:04:54 -04001299
1300 Sets kLCDRenderText_Flag if lcdText is true.
1301 Clears kLCDRenderText_Flag if lcdText is false.
1302
1303 #Param lcdText setting for kLCDRenderText_Flag ##
1304
1305 #Example
1306 SkPaint paint1, paint2;
1307 paint1.setLCDRenderText(true);
1308 paint2.setFlags(paint2.getFlags() | SkPaint::kLCDRenderText_Flag);
1309 SkDebugf("paint1 %c= paint2\n", paint1 == paint2 ? '=' : '!');
1310
1311 #StdOut
1312 paint1 == paint2
1313 ##
1314 ##
1315
1316
1317##
1318
1319#Subtopic ##
1320
1321#Topic ##
1322# ------------------------------------------------------------------------------
1323#Topic Font_Embedded_Bitmaps
1324#Alias Font_Embedded_Bitmaps # long-winded enough, alias so I don't type Paint_Font_...
1325
Cary Clarkce101242017-09-01 15:51:02 -04001326Font_Embedded_Bitmaps allows selecting custom sized bitmap Glyphs.
Cary Clark8032b982017-07-28 11:04:54 -04001327Flags kEmbeddedBitmapText_Flag when set chooses an embedded bitmap glyph over an outline contained
1328in a font if the platform supports this option.
1329
1330FreeType selects the bitmap glyph if available when kEmbeddedBitmapText_Flag is set, and selects
1331the outline glyph if kEmbeddedBitmapText_Flag is clear.
1332Windows may select the bitmap glyph but is not required to do so.
1333OS_X and iOS do not support this option.
1334
1335Font_Embedded_Bitmaps is disabled by default.
1336Font_Embedded_Bitmaps can be enabled by default by setting SkPaintDefaults_Flags to
1337kEmbeddedBitmapText_Flag at compile time.
1338
1339#Example
1340 #ToDo image will only output on Ubuntu ... how to handle that in fiddle? ##
1341 #Platform !fiddle
1342 #Description
Cary Clarkce101242017-09-01 15:51:02 -04001343 The "hintgasp" TrueType font in the Skia resources/fonts directory
1344 includes an embedded bitmap Glyph at odd font sizes. This example works
1345 on platforms that use FreeType as their Font_Engine.
1346 Windows may, but is not required to, return a bitmap glyph if
1347 kEmbeddedBitmapText_Flag is set.
Cary Clark8032b982017-07-28 11:04:54 -04001348 ##
1349 #Image embeddedbitmap.png
1350
1351 SkBitmap bitmap;
1352 bitmap.allocN32Pixels(30, 15);
1353 bitmap.eraseColor(0);
1354 SkCanvas offscreen(bitmap);
1355 SkPaint paint;
1356 paint.setAntiAlias(true);
1357 paint.setTextSize(13);
Hal Canary53e5e7d2017-12-08 14:25:14 -05001358 paint.setTypeface(MakeResourceAsTypeface("fonts/hintgasp.ttf"));
Cary Clark8032b982017-07-28 11:04:54 -04001359 for (bool embedded : { false, true}) {
1360 paint.setEmbeddedBitmapText(embedded);
1361 offscreen.drawString("A", embedded ? 5 : 15, 15, paint);
1362 }
1363 canvas->drawBitmap(bitmap, 0, 0);
1364 canvas->scale(10, 10);
1365 canvas->drawBitmap(bitmap, -2, 1);
1366##
1367
1368#Method bool isEmbeddedBitmapText() const
1369
Cary Clarkce101242017-09-01 15:51:02 -04001370 If true, Font_Engine may return Glyphs from font bitmaps instead of from outlines.
Cary Clark8032b982017-07-28 11:04:54 -04001371
1372 Equivalent to getFlags masked with kEmbeddedBitmapText_Flag.
1373
1374 #Return kEmbeddedBitmapText_Flag state ##
1375
1376 #Example
1377 SkPaint paint;
1378 SkDebugf("paint.isEmbeddedBitmapText() %c="
1379 " !!(paint.getFlags() & SkPaint::kEmbeddedBitmapText_Flag)\n",
1380 paint.isEmbeddedBitmapText() ==
1381 !!(paint.getFlags() & SkPaint::kEmbeddedBitmapText_Flag) ? '=' : '!');
1382 paint.setEmbeddedBitmapText(true);
1383 SkDebugf("paint.isEmbeddedBitmapText() %c="
1384 " !!(paint.getFlags() & SkPaint::kEmbeddedBitmapText_Flag)\n",
1385 paint.isEmbeddedBitmapText() ==
1386 !!(paint.getFlags() & SkPaint::kEmbeddedBitmapText_Flag) ? '=' : '!');
1387
1388 #StdOut
1389 paint.isEmbeddedBitmapText() == !!(paint.getFlags() & SkPaint::kEmbeddedBitmapText_Flag)
1390 paint.isEmbeddedBitmapText() == !!(paint.getFlags() & SkPaint::kEmbeddedBitmapText_Flag)
1391 ##
1392 ##
1393
1394##
1395
1396#Method void setEmbeddedBitmapText(bool useEmbeddedBitmapText)
1397
1398 Requests, but does not require, to use bitmaps in fonts instead of outlines.
1399
1400 Sets kEmbeddedBitmapText_Flag if useEmbeddedBitmapText is true.
1401 Clears kEmbeddedBitmapText_Flag if useEmbeddedBitmapText is false.
1402
1403 #Param useEmbeddedBitmapText setting for kEmbeddedBitmapText_Flag ##
1404
1405 #Example
1406 SkPaint paint1, paint2;
1407 paint1.setEmbeddedBitmapText(true);
1408 paint2.setFlags(paint2.getFlags() | SkPaint::kEmbeddedBitmapText_Flag);
1409 SkDebugf("paint1 %c= paint2\n", paint1 == paint2 ? '=' : '!');
1410
1411 #StdOut
1412 paint1 == paint2
1413 ##
1414 ##
1415
1416##
1417
1418#Topic ##
1419# ------------------------------------------------------------------------------
1420#Topic Automatic_Hinting
1421#Substitute auto-hinting
1422
1423If Hinting is set to kNormal_Hinting or kFull_Hinting, Automatic_Hinting
Cary Clarkce101242017-09-01 15:51:02 -04001424instructs the Font_Manager to always hint Glyphs.
Cary Clark8032b982017-07-28 11:04:54 -04001425Automatic_Hinting has no effect if Hinting is set to kNo_Hinting or
1426kSlight_Hinting.
1427
1428Automatic_Hinting only affects platforms that use FreeType as the Font_Manager.
1429
1430#Method bool isAutohinted() const
1431
1432 If true, and if Hinting is set to kNormal_Hinting or kFull_Hinting, and if
1433 platform uses FreeType as the Font_Manager, instruct the Font_Manager to always hint
Cary Clarkce101242017-09-01 15:51:02 -04001434 Glyphs.
Cary Clark8032b982017-07-28 11:04:54 -04001435
1436 Equivalent to getFlags masked with kAutoHinting_Flag.
1437
1438 #Return kAutoHinting_Flag state ##
1439
1440 #Example
1441 SkPaint paint;
1442 for (auto forceAutoHinting : { false, true} ) {
1443 paint.setAutohinted(forceAutoHinting);
1444 SkDebugf("paint.isAutohinted() %c="
1445 " !!(paint.getFlags() & SkPaint::kAutoHinting_Flag)\n",
1446 paint.isAutohinted() ==
1447 !!(paint.getFlags() & SkPaint::kAutoHinting_Flag) ? '=' : '!');
1448 }
1449 #StdOut
1450 paint.isAutohinted() == !!(paint.getFlags() & SkPaint::kAutoHinting_Flag)
1451 paint.isAutohinted() == !!(paint.getFlags() & SkPaint::kAutoHinting_Flag)
1452 ##
1453 ##
1454
1455 #SeeAlso setAutohinted Hinting
1456
1457##
1458
1459#Method void setAutohinted(bool useAutohinter)
1460
1461 If Hinting is set to kNormal_Hinting or kFull_Hinting and useAutohinter is set,
Cary Clarkce101242017-09-01 15:51:02 -04001462 instruct the Font_Manager to always hint Glyphs.
Cary Clark8032b982017-07-28 11:04:54 -04001463 Automatic_Hinting has no effect if Hinting is set to kNo_Hinting or
1464 kSlight_Hinting.
1465
Cary Clark579985c2017-07-31 11:48:27 -04001466 Only affects platforms that use FreeType as the Font_Manager.
Cary Clark8032b982017-07-28 11:04:54 -04001467
1468 Sets kAutoHinting_Flag if useAutohinter is true.
1469 Clears kAutoHinting_Flag if useAutohinter is false.
1470
1471 #Param useAutohinter setting for kAutoHinting_Flag ##
1472
1473 #Example
1474 void draw(SkCanvas* canvas) {
1475 SkPaint paint;
1476 paint.setAntiAlias(true);
1477 const char testStr[] = "xxxx xxxx";
1478 for (auto forceAutoHinting : { false, true} ) {
1479 paint.setAutohinted(forceAutoHinting);
1480 paint.setTextSize(24);
1481 canvas->drawString(paint.isAutohinted() ? "auto-hinted" : "default", 108, 30, paint);
1482 for (SkScalar textSize = 8; textSize < 30; textSize *= 1.22f) {
1483 paint.setTextSize(textSize);
1484 canvas->translate(0, textSize);
1485 canvas->drawString(testStr, 10, 0, paint);
1486 }
1487 }
1488 }
1489 ##
1490
1491 #SeeAlso isAutohinted Hinting
1492
1493##
1494
1495#Topic ##
1496# ------------------------------------------------------------------------------
1497#Topic Vertical_Text
1498
1499Text may be drawn by positioning each glyph, or by positioning the first glyph and
Cary Clarkce101242017-09-01 15:51:02 -04001500using Font_Advance to position subsequent Glyphs. By default, each successive glyph
1501is positioned to the right of the preceding glyph. Vertical_Text sets successive
1502Glyphs to position below the preceding glyph.
Cary Clark8032b982017-07-28 11:04:54 -04001503
Cary Clarkce101242017-09-01 15:51:02 -04001504Skia can translate text character codes as a series of Glyphs, but does not implement
Cary Clark8032b982017-07-28 11:04:54 -04001505font substitution,
Cary Clarkce101242017-09-01 15:51:02 -04001506textual substitution, line layout, or contextual spacing like Kerning pairs. Use
Cary Clark6fc50412017-09-21 12:31:06 -04001507a text shaping engine like
1508#A HarfBuzz # http://harfbuzz.org/ ##
1509 to translate text runs
Cary Clark8032b982017-07-28 11:04:54 -04001510into glyph series.
1511
1512Vertical_Text is clear if text is drawn left to right or set if drawn from top to bottom.
1513
1514Flags kVerticalText_Flag if clear draws text left to right.
1515Flags kVerticalText_Flag if set draws text top to bottom.
1516
1517Vertical_Text is clear by default.
1518Vertical_Text can be set by default by setting SkPaintDefaults_Flags to
1519kVerticalText_Flag at compile time.
1520
1521#Example
1522
1523void draw(SkCanvas* canvas) {
1524 SkPaint paint;
1525 paint.setAntiAlias(true);
1526 paint.setTextSize(50);
1527 for (bool vertical : { false, true } ) {
1528 paint.setVerticalText(vertical);
1529 canvas->drawString("aAlL", 25, 50, paint);
1530 }
1531}
1532
1533##
1534
1535#Method bool isVerticalText() const
1536
Cary Clarkce101242017-09-01 15:51:02 -04001537 If true, Glyphs are drawn top to bottom instead of left to right.
Cary Clark8032b982017-07-28 11:04:54 -04001538
1539 Equivalent to getFlags masked with kVerticalText_Flag.
1540
1541 #Return kVerticalText_Flag state ##
1542
1543 #Example
1544 SkPaint paint;
1545 SkDebugf("paint.isVerticalText() %c= !!(paint.getFlags() & SkPaint::kVerticalText_Flag)\n",
1546 paint.isVerticalText() == !!(paint.getFlags() & SkPaint::kVerticalText_Flag) ? '=' : '!');
1547 paint.setVerticalText(true);
1548 SkDebugf("paint.isVerticalText() %c= !!(paint.getFlags() & SkPaint::kVerticalText_Flag)\n",
1549 paint.isVerticalText() == !!(paint.getFlags() & SkPaint::kVerticalText_Flag) ? '=' : '!');
1550
1551 #StdOut
1552 paint.isVerticalText() == !!(paint.getFlags() & SkPaint::kVerticalText_Flag)
1553 paint.isVerticalText() == !!(paint.getFlags() & SkPaint::kVerticalText_Flag)
1554 ##
1555 ##
1556
1557##
1558
1559#Method void setVerticalText(bool verticalText)
1560
1561 If true, text advance positions the next glyph below the previous glyph instead of to the
1562 right of previous glyph.
1563
1564 Sets kVerticalText_Flag if vertical is true.
1565 Clears kVerticalText_Flag if vertical is false.
1566
1567 #Param verticalText setting for kVerticalText_Flag ##
1568
1569 #Example
1570 SkPaint paint1, paint2;
1571 paint1.setVerticalText(true);
1572 paint2.setFlags(paint2.getFlags() | SkPaint::kVerticalText_Flag);
1573 SkDebugf("paint1 %c= paint2\n", paint1 == paint2 ? '=' : '!');
1574
1575 #StdOut
1576 paint1 == paint2
1577 ##
1578 ##
1579
1580##
1581
1582#Topic ##
1583# ------------------------------------------------------------------------------
1584
1585#Topic Fake_Bold
1586
1587Fake_Bold approximates the bold font style accompanying a normal font when a bold font face
1588is not available. Skia does not provide font substitution; it is up to the client to find the
Cary Clarkbc5697d2017-10-04 14:31:33 -04001589bold font face using the platform Font_Manager.
Cary Clark8032b982017-07-28 11:04:54 -04001590
1591Use Text_Skew_X to approximate an italic font style when the italic font face
1592is not available.
1593
Cary Clarkce101242017-09-01 15:51:02 -04001594A FreeType based port may define SK_USE_FREETYPE_EMBOLDEN at compile time to direct
1595the font engine to create the bold Glyphs. Otherwise, the extra bold is computed
Cary Clark8032b982017-07-28 11:04:54 -04001596by increasing the stroke width and setting the Style to kStrokeAndFill_Style as needed.
1597
1598Fake_Bold is disabled by default.
1599
1600#Example
1601#Height 128
1602void draw(SkCanvas* canvas) {
1603 SkPaint paint;
1604 paint.setAntiAlias(true);
1605 paint.setTextSize(40);
1606 canvas->drawString("OjYy_-", 10, 35, paint);
1607 paint.setFakeBoldText(true);
1608 canvas->drawString("OjYy_-", 10, 75, paint);
1609 // create a custom fake bold by varying the stroke width
1610 paint.setFakeBoldText(false);
1611 paint.setStyle(SkPaint::kStrokeAndFill_Style);
1612 paint.setStrokeWidth(40.f / 48);
1613 canvas->drawString("OjYy_-", 10, 115, paint);
1614}
1615##
1616
1617#Method bool isFakeBoldText() const
1618
1619 If true, approximate bold by increasing the stroke width when creating glyph bitmaps
1620 from outlines.
1621
1622 Equivalent to getFlags masked with kFakeBoldText_Flag.
1623
1624 #Return kFakeBoldText_Flag state ##
1625
1626 #Example
1627 SkPaint paint;
1628 SkDebugf("paint.isFakeBoldText() %c= !!(paint.getFlags() & SkPaint::kFakeBoldText_Flag)\n",
1629 paint.isFakeBoldText() == !!(paint.getFlags() & SkPaint::kFakeBoldText_Flag) ? '=' : '!');
1630 paint.setFakeBoldText(true);
1631 SkDebugf("paint.isFakeBoldText() %c= !!(paint.getFlags() & SkPaint::kFakeBoldText_Flag)\n",
1632 paint.isFakeBoldText() == !!(paint.getFlags() & SkPaint::kFakeBoldText_Flag) ? '=' : '!');
1633
1634 #StdOut
1635 paint.isFakeBoldText() == !!(paint.getFlags() & SkPaint::kFakeBoldText_Flag)
1636 paint.isFakeBoldText() == !!(paint.getFlags() & SkPaint::kFakeBoldText_Flag)
1637 ##
1638 ##
1639
1640##
1641
1642#Method void setFakeBoldText(bool fakeBoldText)
1643
Cary Clarkce101242017-09-01 15:51:02 -04001644 Use increased stroke width when creating glyph bitmaps to approximate a bold typeface.
Cary Clark8032b982017-07-28 11:04:54 -04001645
1646 Sets kFakeBoldText_Flag if fakeBoldText is true.
1647 Clears kFakeBoldText_Flag if fakeBoldText is false.
1648
1649 #Param fakeBoldText setting for kFakeBoldText_Flag ##
1650
1651 #Example
1652 SkPaint paint1, paint2;
1653 paint1.setFakeBoldText(true);
1654 paint2.setFlags(paint2.getFlags() | SkPaint::kFakeBoldText_Flag);
1655 SkDebugf("paint1 %c= paint2\n", paint1 == paint2 ? '=' : '!');
1656
1657 #StdOut
1658 paint1 == paint2
1659 ##
1660 ##
1661
1662##
1663
1664#Topic ##
1665
1666# ------------------------------------------------------------------------------
1667#Topic Full_Hinting_Spacing
1668#Alias Full_Hinting_Spacing # long winded enough -- maybe things with two underscores auto-aliased?
1669
Cary Clarkce101242017-09-01 15:51:02 -04001670if Hinting is set to kFull_Hinting, Full_Hinting_Spacing adjusts the character
1671spacing by the difference of the hinted and Unhinted Left_Side_Bearing and
1672Right_Side_Bearing. Full_Hinting_Spacing only applies to platforms that use
1673FreeType as their Font_Engine.
Cary Clark8032b982017-07-28 11:04:54 -04001674
Cary Clarkce101242017-09-01 15:51:02 -04001675Full_Hinting_Spacing is not related to text Kerning, where the space between
Cary Clarkbc5697d2017-10-04 14:31:33 -04001676a specific pair of characters is adjusted using data in the font Kerning tables.
Cary Clark8032b982017-07-28 11:04:54 -04001677
1678#Method bool isDevKernText() const
1679
1680 Returns if character spacing may be adjusted by the hinting difference.
1681
1682 Equivalent to getFlags masked with kDevKernText_Flag.
1683
1684 #Return kDevKernText_Flag state ##
1685
1686 #Example
1687 SkPaint paint;
1688 SkDebugf("paint.isDevKernText() %c= !!(paint.getFlags() & SkPaint::kDevKernText_Flag)\n",
1689 paint.isDevKernText() == !!(paint.getFlags() & SkPaint::kDevKernText_Flag) ? '=' : '!');
1690 paint.setDevKernText(true);
1691 SkDebugf("paint.isDevKernText() %c= !!(paint.getFlags() & SkPaint::kDevKernText_Flag)\n",
1692 paint.isDevKernText() == !!(paint.getFlags() & SkPaint::kDevKernText_Flag) ? '=' : '!');
1693 ##
1694
1695##
1696
1697#Method void setDevKernText(bool devKernText)
1698
1699 Requests, but does not require, to use hinting to adjust glyph spacing.
1700
1701 Sets kDevKernText_Flag if devKernText is true.
1702 Clears kDevKernText_Flag if devKernText is false.
1703
1704 #Param devKernText setting for devKernText ##
1705
1706 #Example
1707 SkPaint paint1, paint2;
1708 paint1.setDevKernText(true);
1709 paint2.setFlags(paint2.getFlags() | SkPaint::kDevKernText_Flag);
1710 SkDebugf("paint1 %c= paint2\n", paint1 == paint2 ? '=' : '!');
1711
1712 #StdOut
1713 paint1 == paint2
1714 ##
1715 ##
1716
1717##
1718
1719#Topic ##
1720# ------------------------------------------------------------------------------
1721#Topic Filter_Quality_Methods
1722
1723Filter_Quality trades speed for image filtering when the image is scaled.
1724A lower Filter_Quality draws faster, but has less fidelity.
1725A higher Filter_Quality draws slower, but looks better.
Cary Clarkce101242017-09-01 15:51:02 -04001726If the image is drawn without scaling, the Filter_Quality choice will not result
1727in a noticeable difference.
Cary Clark8032b982017-07-28 11:04:54 -04001728
1729Filter_Quality is used in Paint passed as a parameter to
1730#List
1731# SkCanvas::drawBitmap ##
1732# SkCanvas::drawBitmapRect ##
1733# SkCanvas::drawImage ##
1734# SkCanvas::drawImageRect ##
1735 #ToDo probably more... ##
1736#List ##
1737and when Paint has a Shader specialization that uses Image or Bitmap.
1738
1739Filter_Quality is kNone_SkFilterQuality by default.
1740
1741#Example
1742#Image 3
1743void draw(SkCanvas* canvas) {
1744 SkPaint paint;
1745 canvas->scale(.2f, .2f);
1746 for (SkFilterQuality q : { kNone_SkFilterQuality, kLow_SkFilterQuality,
1747 kMedium_SkFilterQuality, kHigh_SkFilterQuality } ) {
1748 paint.setFilterQuality(q);
1749 canvas->drawImage(image.get(), 0, 0, &paint);
1750 canvas->translate(550, 0);
1751 if (kLow_SkFilterQuality == q) canvas->translate(-1100, 550);
1752 }
1753}
1754##
1755
1756#Method SkFilterQuality getFilterQuality() const
1757
1758Returns Filter_Quality, the image filtering level. A lower setting
1759draws faster; a higher setting looks better when the image is scaled.
1760
1761#Return one of: kNone_SkFilterQuality, kLow_SkFilterQuality,
1762 kMedium_SkFilterQuality, kHigh_SkFilterQuality
1763#Return ##
1764
1765#Example
1766 SkPaint paint;
1767 SkDebugf("kNone_SkFilterQuality %c= paint.getFilterQuality()\n",
1768 kNone_SkFilterQuality == paint.getFilterQuality() ? '=' : '!');
1769
1770 #StdOut
1771 kNone_SkFilterQuality == paint.getFilterQuality()
1772 ##
1773##
1774
1775##
1776
1777
1778#Method void setFilterQuality(SkFilterQuality quality)
1779
1780Sets Filter_Quality, the image filtering level. A lower setting
1781draws faster; a higher setting looks better when the image is scaled.
Cary Clark579985c2017-07-31 11:48:27 -04001782Does not check to see if quality is valid.
Cary Clark8032b982017-07-28 11:04:54 -04001783
1784#Param quality one of: kNone_SkFilterQuality, kLow_SkFilterQuality,
1785 kMedium_SkFilterQuality, kHigh_SkFilterQuality
1786##
1787
1788#Example
1789 SkPaint paint;
1790 paint.setFilterQuality(kHigh_SkFilterQuality);
1791 SkDebugf("kHigh_SkFilterQuality %c= paint.getFilterQuality()\n",
1792 kHigh_SkFilterQuality == paint.getFilterQuality() ? '=' : '!');
1793
1794 #StdOut
1795 kHigh_SkFilterQuality == paint.getFilterQuality()
1796 ##
1797##
1798
1799#SeeAlso SkFilterQuality Image_Scaling
1800
1801##
1802
1803#Topic ##
1804# ------------------------------------------------------------------------------
1805#Topic Color_Methods
1806
1807Color specifies the Color_RGB_Red, Color_RGB_Blue, Color_RGB_Green, and Color_Alpha values used to draw a filled
1808or stroked shape in a
180932-bit value. Each component occupies 8-bits, ranging from zero: no contribution;
1810to 255: full intensity. All values in any combination are valid.
1811
Cary Clarkce101242017-09-01 15:51:02 -04001812Color is not Premultiplied;
Cary Clark8032b982017-07-28 11:04:54 -04001813Color_Alpha sets the transparency independent of Color_RGB: Color_RGB_Red, Color_RGB_Blue, and Color_RGB_Green.
1814
1815The bit positions of Color_Alpha and Color_RGB are independent of the bit positions
1816on the output device, which may have more or fewer bits, and may have a different arrangement.
1817
1818#Table
1819#Legend
1820# bit positions # Color_Alpha # Color_RGB_Red # Color_RGB_Blue # Color_RGB_Green ##
1821#Legend ##
1822# # 31 - 24 # 23 - 16 # 15 - 8 # 7 - 0 ##
1823#Table ##
1824
1825#Example
1826#Height 128
1827 void draw(SkCanvas* canvas) {
1828 SkPaint paint;
1829 paint.setColor(0x8000FF00); // transparent green
1830 canvas->drawCircle(50, 50, 40, paint);
1831 paint.setARGB(128, 255, 0, 0); // transparent red
1832 canvas->drawCircle(80, 50, 40, paint);
1833 paint.setColor(SK_ColorBLUE);
1834 paint.setAlpha(0x80);
1835 canvas->drawCircle(65, 65, 40, paint);
1836 }
1837##
1838
1839#Method SkColor getColor() const
1840
Cary Clarkce101242017-09-01 15:51:02 -04001841 Retrieves Alpha and Color_RGB, Unpremultiplied, packed into 32 bits.
Cary Clark8032b982017-07-28 11:04:54 -04001842 Use helpers SkColorGetA, SkColorGetR, SkColorGetG, and SkColorGetB to extract
1843 a color component.
1844
1845 #Return Unpremultiplied Color_ARGB ##
1846
1847 #Example
1848 SkPaint paint;
1849 paint.setColor(SK_ColorYELLOW);
1850 SkColor y = paint.getColor();
1851 SkDebugf("Yellow is %d%% red, %d%% green, and %d%% blue.\n", (int) (SkColorGetR(y) / 2.55f),
1852 (int) (SkColorGetG(y) / 2.55f), (int) (SkColorGetB(y) / 2.55f));
1853
1854 #StdOut
1855 Yellow is 100% red, 100% green, and 0% blue.
1856 ##
1857 ##
1858
1859 #SeeAlso SkColor
1860
1861##
1862
1863#Method void setColor(SkColor color)
1864
Cary Clarkce101242017-09-01 15:51:02 -04001865 Sets Alpha and Color_RGB used when stroking and filling. The color is a 32-bit value,
1866 Unpremultiplied, packing 8-bit components for Alpha, Red, Blue, and Green.
Cary Clark8032b982017-07-28 11:04:54 -04001867
1868 #Param color Unpremultiplied Color_ARGB ##
Cary Clark0c5f5462017-12-15 11:21:51 -05001869
1870 #Example
Cary Clark8032b982017-07-28 11:04:54 -04001871 SkPaint green1, green2;
1872 unsigned a = 255;
1873 unsigned r = 0;
1874 unsigned g = 255;
1875 unsigned b = 0;
1876 green1.setColor((a << 24) + (r << 16) + (g << 8) + (b << 0));
1877 green2.setColor(0xFF00FF00);
1878 SkDebugf("green1 %c= green2\n", green1 == green2 ? '=' : '!');
1879
1880 #StdOut
1881 green1 == green2
1882 ##
1883 ##
1884
1885 #SeeAlso SkColor setARGB SkColorSetARGB
1886
1887##
1888
1889#Subtopic Alpha_Methods
1890
1891Color_Alpha sets the transparency independent of Color_RGB: Color_RGB_Red, Color_RGB_Blue, and Color_RGB_Green.
1892
1893#Method uint8_t getAlpha() const
1894
Cary Clarkce101242017-09-01 15:51:02 -04001895 Retrieves Alpha from the Color used when stroking and filling.
Cary Clark8032b982017-07-28 11:04:54 -04001896
Cary Clarkce101242017-09-01 15:51:02 -04001897 #Return Alpha ranging from zero, fully transparent, to 255, fully opaque ##
Cary Clark8032b982017-07-28 11:04:54 -04001898
1899 #Example
1900 SkPaint paint;
1901 SkDebugf("255 %c= paint.getAlpha()\n", 255 == paint.getAlpha() ? '=' : '!');
1902
1903 #StdOut
1904 255 == paint.getAlpha()
1905 ##
1906 ##
1907
1908##
1909
1910#Method void setAlpha(U8CPU a)
1911
Cary Clarkce101242017-09-01 15:51:02 -04001912 Replaces Alpha, leaving Color_RGB
Cary Clark8032b982017-07-28 11:04:54 -04001913 unchanged. An out of range value triggers an assert in the debug
1914 build. a is a value from zero to 255.
1915 a set to zero makes Color fully transparent; a set to 255 makes Color
1916 fully opaque.
1917
Cary Clarkce101242017-09-01 15:51:02 -04001918 #Param a Alpha component of Color ##
Cary Clark8032b982017-07-28 11:04:54 -04001919
1920 #Example
1921 SkPaint paint;
1922 paint.setColor(0x00112233);
1923 paint.setAlpha(0x44);
1924 SkDebugf("0x44112233 %c= paint.getColor()\n", 0x44112233 == paint.getColor() ? '=' : '!');
1925
1926 #StdOut
1927 0x44112233 == paint.getColor()
1928 ##
1929 ##
1930
1931##
1932
1933#Subtopic ##
1934
1935#Method void setARGB(U8CPU a, U8CPU r, U8CPU g, U8CPU b)
1936
1937 Sets Color used when drawing solid fills. The color components range from 0 to 255.
Cary Clarkce101242017-09-01 15:51:02 -04001938 The color is Unpremultiplied; Alpha sets the transparency independent of Color_RGB.
Cary Clark8032b982017-07-28 11:04:54 -04001939
1940 #Param a amount of Color_Alpha, from fully transparent (0) to fully opaque (255) ##
1941 #Param r amount of Color_RGB_Red, from no red (0) to full red (255) ##
1942 #Param g amount of Color_RGB_Green, from no green (0) to full green (255) ##
1943 #Param b amount of Color_RGB_Blue, from no blue (0) to full blue (255) ##
1944
1945 #Example
1946 SkPaint transRed1, transRed2;
1947 transRed1.setARGB(255 / 2, 255, 0, 0);
1948 transRed2.setColor(SkColorSetARGB(255 / 2, 255, 0, 0));
1949 SkDebugf("transRed1 %c= transRed2", transRed1 == transRed2 ? '=' : '!');
1950
1951 #StdOut
1952 transRed1 == transRed2
1953 ##
1954 ##
1955
1956 #SeeAlso setColor SkColorSetARGB
1957
1958##
1959
1960#Topic Color_Methods ##
1961
1962# ------------------------------------------------------------------------------
1963#Topic Style
1964
1965Style specifies if the geometry is filled, stroked, or both filled and stroked.
1966Some shapes ignore Style and are always drawn filled or stroked.
1967
1968Set Style to kFill_Style to fill the shape.
1969The fill covers the area inside the geometry for most shapes.
1970
1971Set Style to kStroke_Style to stroke the shape.
1972
1973# ------------------------------------------------------------------------------
1974#Subtopic Fill
1975
1976#ToDo write up whatever generalities make sense to describe filling ##
1977
1978#SeeAlso Path_Fill_Type
1979#Subtopic ##
1980
1981#Subtopic Stroke
Cary Clarkbc5697d2017-10-04 14:31:33 -04001982The stroke covers the area described by following the shape edge with a pen or brush of
Cary Clark8032b982017-07-28 11:04:54 -04001983Stroke_Width. The area covered where the shape starts and stops is described by Stroke_Cap.
1984The area covered where the shape turns a corner is described by Stroke_Join.
Cary Clarkbc5697d2017-10-04 14:31:33 -04001985The stroke is centered on the shape; it extends equally on either side of the shape edge.
Cary Clark8032b982017-07-28 11:04:54 -04001986
1987As Stroke_Width gets smaller, the drawn path frame is thinner. Stroke_Width less than one
1988may have gaps, and if kAntiAlias_Flag is set, Color_Alpha will increase to visually decrease coverage.
1989#Subtopic ##
1990
1991#Subtopic Hairline
1992#Alias Hairline # maybe should be Stroke_Hairline ?
1993
1994Stroke_Width of zero has a special meaning and switches drawing to use Hairline.
1995Hairline draws the thinnest continuous frame. If kAntiAlias_Flag is clear, adjacent pixels
1996flow horizontally, vertically,or diagonally.
1997
Cary Clarkce101242017-09-01 15:51:02 -04001998#ToDo what is the description of Anti-aliased hairlines? ##
Cary Clark8032b982017-07-28 11:04:54 -04001999
2000Path drawing with Hairline may hit the same pixel more than once. For instance, Path containing
2001two lines in one Path_Contour will draw the corner point once, but may both lines may draw the adjacent
2002pixel. If kAntiAlias_Flag is set, transparency is applied twice, resulting in a darker pixel. Some
2003GPU-backed implementations apply transparency at a later drawing stage, avoiding double hit pixels
2004while stroking.
2005
2006#Subtopic ##
2007
2008#Enum Style
2009
2010#Code
2011 enum Style {
2012 kFill_Style,
2013 kStroke_Style,
2014 kStrokeAndFill_Style,
2015 };
2016##
2017
2018Set Style to fill, stroke, or both fill and stroke geometry.
2019The stroke and fill
2020share all paint attributes; for instance, they are drawn with the same color.
2021
2022Use kStrokeAndFill_Style to avoid hitting the same pixels twice with a stroke draw and
2023a fill draw.
2024
2025#Const kFill_Style 0
2026 Set to fill geometry.
Cary Clarkce101242017-09-01 15:51:02 -04002027 Applies to Rect, Region, Round_Rect, Circles, Ovals, Path, and Text.
2028 Bitmap, Image, Patches, Region, Sprites, and Vertices are painted as if
Cary Clark8032b982017-07-28 11:04:54 -04002029 kFill_Style is set, and ignore the set Style.
2030 The Path_Fill_Type specifies additional rules to fill the area outside the path edge,
2031 and to create an unfilled hole inside the shape.
2032 Style is set to kFill_Style by default.
2033##
2034
2035#Const kStroke_Style 1
2036 Set to stroke geometry.
Cary Clarkce101242017-09-01 15:51:02 -04002037 Applies to Rect, Region, Round_Rect, Arcs, Circles, Ovals, Path, and Text.
2038 Arcs, Lines, and Points, are always drawn as if kStroke_Style is set,
Cary Clark8032b982017-07-28 11:04:54 -04002039 and ignore the set Style.
2040 The stroke construction is unaffected by the Path_Fill_Type.
2041##
2042
2043#Const kStrokeAndFill_Style 2
2044 Set to stroke and fill geometry.
Cary Clarkce101242017-09-01 15:51:02 -04002045 Applies to Rect, Region, Round_Rect, Circles, Ovals, Path, and Text.
Cary Clark8032b982017-07-28 11:04:54 -04002046 Path is treated as if it is set to SkPath::kWinding_FillType,
2047 and the set Path_Fill_Type is ignored.
2048##
2049
2050#Enum ##
2051
2052#Enum
2053
2054#Code
2055 enum {
Cary Clarkbad5ad72017-08-03 17:14:08 -04002056 kStyleCount = kStrokeAndFill_Style + 1,
Cary Clark8032b982017-07-28 11:04:54 -04002057 };
2058##
2059
2060#Const kStyleCount 3
2061The number of different Style values defined.
2062May be used to verify that Style is a legal value.
2063##
2064
2065#Enum ##
2066
2067#Method Style getStyle() const
2068
2069 Whether the geometry is filled, stroked, or filled and stroked.
2070
2071 #Return one of:kFill_Style, kStroke_Style, kStrokeAndFill_Style ##
2072
2073 #Example
2074 SkPaint paint;
2075 SkDebugf("SkPaint::kFill_Style %c= paint.getStyle()\n",
2076 SkPaint::kFill_Style == paint.getStyle() ? '=' : '!');
2077
2078 #StdOut
2079 SkPaint::kFill_Style == paint.getStyle()
2080 ##
2081 ##
2082
2083#SeeAlso Style setStyle
2084##
2085
2086#Method void setStyle(Style style)
2087
2088 Sets whether the geometry is filled, stroked, or filled and stroked.
2089 Has no effect if style is not a legal Style value.
2090
2091 #Param style one of: kFill_Style, kStroke_Style, kStrokeAndFill_Style
2092 ##
2093
2094 #Example
2095 void draw(SkCanvas* canvas) {
2096 SkPaint paint;
2097 paint.setStrokeWidth(5);
2098 SkRegion region;
2099 region.op(140, 10, 160, 30, SkRegion::kUnion_Op);
2100 region.op(170, 40, 190, 60, SkRegion::kUnion_Op);
2101 SkBitmap bitmap;
2102 bitmap.setInfo(SkImageInfo::MakeA8(50, 50), 50);
2103 uint8_t pixels[50][50];
2104 for (int x = 0; x < 50; ++x) {
2105 for (int y = 0; y < 50; ++y) {
2106 pixels[y][x] = (x + y) % 5 ? 0xFF : 0x00;
2107 }
2108 }
2109 bitmap.setPixels(pixels);
2110 for (auto style : { SkPaint::kFill_Style,
2111 SkPaint::kStroke_Style,
2112 SkPaint::kStrokeAndFill_Style }) {
2113 paint.setStyle(style);
2114 canvas->drawLine(10, 10, 60, 60, paint);
2115 canvas->drawRect({80, 10, 130, 60}, paint);
2116 canvas->drawRegion(region, paint);
2117 canvas->drawBitmap(bitmap, 200, 10, &paint);
2118 canvas->translate(0, 80);
2119 }
2120 }
2121 ##
2122
2123#SeeAlso Style getStyle
2124##
2125
2126#SeeAlso Path_Fill_Type Path_Effect Style_Fill Style_Stroke
2127#Topic Style ##
2128
2129# ------------------------------------------------------------------------------
2130#Topic Stroke_Width
2131
2132Stroke_Width sets the width for stroking. The width is the thickness
Cary Clarkbc5697d2017-10-04 14:31:33 -04002133of the stroke perpendicular to the path direction when the paint style is
Cary Clark8032b982017-07-28 11:04:54 -04002134set to kStroke_Style or kStrokeAndFill_Style.
2135
2136When width is greater than zero, the stroke encompasses as many pixels partially
2137or fully as needed. When the width equals zero, the paint enables hairlines;
2138the stroke is always one pixel wide.
2139
Cary Clarkbc5697d2017-10-04 14:31:33 -04002140The stroke dimensions are scaled by the canvas matrix, but Hairline stroke
Cary Clark8032b982017-07-28 11:04:54 -04002141remains one pixel wide regardless of scaling.
2142
2143The default width for the paint is zero.
2144
2145#Example
2146#Height 170
2147 #Platform raster gpu
2148 #Description
2149 The pixels hit to represent thin lines vary with the angle of the
Cary Clarkbc5697d2017-10-04 14:31:33 -04002150 line and the platform implementation.
Cary Clark8032b982017-07-28 11:04:54 -04002151 ##
2152 void draw(SkCanvas* canvas) {
2153 SkPaint paint;
2154 for (bool antialias : { false, true }) {
2155 paint.setAntiAlias(antialias);
2156 for (int width = 0; width <= 4; ++width) {
2157 SkScalar offset = antialias * 100 + width * 20;
2158 paint.setStrokeWidth(width * 0.25f);
2159 canvas->drawLine(10 + offset, 10, 20 + offset, 60, paint);
2160 canvas->drawLine(10 + offset, 110, 60 + offset, 160, paint);
2161 }
2162 }
2163 }
2164##
2165
2166#Method SkScalar getStrokeWidth() const
2167
2168 Returns the thickness of the pen used by Paint to
2169 outline the shape.
2170
2171 #Return zero for Hairline, greater than zero for pen thickness ##
2172
2173 #Example
2174 SkPaint paint;
2175 SkDebugf("0 %c= paint.getStrokeWidth()\n", 0 == paint.getStrokeWidth() ? '=' : '!');
2176
2177 #StdOut
2178 0 == paint.getStrokeWidth()
2179 ##
2180 ##
2181
2182##
2183
2184#Method void setStrokeWidth(SkScalar width)
2185
2186 Sets the thickness of the pen used by the paint to
2187 outline the shape.
2188 Has no effect if width is less than zero.
2189
2190 #Param width zero thickness for Hairline; greater than zero for pen thickness
2191 ##
2192
2193 #Example
2194 SkPaint paint;
2195 paint.setStrokeWidth(5);
2196 paint.setStrokeWidth(-1);
2197 SkDebugf("5 %c= paint.getStrokeWidth()\n", 5 == paint.getStrokeWidth() ? '=' : '!');
2198
2199 #StdOut
2200 5 == paint.getStrokeWidth()
2201 ##
2202 ##
2203
2204##
2205
2206#Topic ##
2207# ------------------------------------------------------------------------------
2208#Topic Miter_Limit
2209
2210Miter_Limit specifies the maximum miter length,
2211relative to the stroke width.
2212
2213Miter_Limit is used when the Stroke_Join
2214is set to kMiter_Join, and the Style is either kStroke_Style
2215or kStrokeAndFill_Style.
2216
2217If the miter at a corner exceeds this limit, kMiter_Join
2218is replaced with kBevel_Join.
2219
2220Miter_Limit can be computed from the corner angle:
2221
2222#Formula
2223 miter limit = 1 / sin ( angle / 2 )
2224#Formula ##
2225
2226Miter_Limit default value is 4.
2227The default may be changed at compile time by setting SkPaintDefaults_MiterLimit
Cary Clarkce101242017-09-01 15:51:02 -04002228in "SkUserConfig.h" or as a define supplied by the build environment.
Cary Clark8032b982017-07-28 11:04:54 -04002229
2230Here are some miter limits and the angles that triggers them.
2231#Table
2232#Legend
2233 # miter limit # angle in degrees ##
2234#Legend ##
2235 # 10 # 11.48 ##
2236 # 9 # 12.76 ##
2237 # 8 # 14.36 ##
2238 # 7 # 16.43 ##
2239 # 6 # 19.19 ##
2240 # 5 # 23.07 ##
2241 # 4 # 28.96 ##
2242 # 3 # 38.94 ##
2243 # 2 # 60 ##
2244 # 1 # 180 ##
2245#Table ##
2246
2247#Example
2248 #Height 170
2249 #Width 384
2250 #Description
2251 This example draws a stroked corner and the miter length beneath.
2252 When the miter limit is decreased slightly, the miter join is replaced
2253 by a bevel join.
2254 ##
2255 void draw(SkCanvas* canvas) {
2256 SkPoint pts[] = {{ 10, 50 }, { 110, 80 }, { 10, 110 }};
2257 SkVector v[] = { pts[0] - pts[1], pts[2] - pts[1] };
2258 SkScalar angle1 = SkScalarATan2(v[0].fY, v[0].fX);
2259 SkScalar angle2 = SkScalarATan2(v[1].fY, v[1].fX);
2260 const SkScalar strokeWidth = 20;
2261 SkScalar miterLimit = 1 / SkScalarSin((angle2 - angle1) / 2);
2262 SkScalar miterLength = strokeWidth * miterLimit;
2263 SkPath path;
2264 path.moveTo(pts[0]);
2265 path.lineTo(pts[1]);
2266 path.lineTo(pts[2]);
2267 SkPaint paint; // set to default kMiter_Join
2268 paint.setAntiAlias(true);
2269 paint.setStyle(SkPaint::kStroke_Style);
2270 paint.setStrokeMiter(miterLimit);
2271 paint.setStrokeWidth(strokeWidth);
2272 canvas->drawPath(path, paint);
2273 paint.setStrokeWidth(1);
2274 canvas->drawLine(pts[1].fX - miterLength / 2, pts[1].fY + 50,
2275 pts[1].fX + miterLength / 2, pts[1].fY + 50, paint);
2276 canvas->translate(200, 0);
2277 miterLimit *= 0.99f;
2278 paint.setStrokeMiter(miterLimit);
2279 paint.setStrokeWidth(strokeWidth);
2280 canvas->drawPath(path, paint);
2281 paint.setStrokeWidth(1);
2282 canvas->drawLine(pts[1].fX - miterLength / 2, pts[1].fY + 50,
2283 pts[1].fX + miterLength / 2, pts[1].fY + 50, paint);
2284 }
2285##
2286
2287#Method SkScalar getStrokeMiter() const
2288
2289 The limit at which a sharp corner is drawn beveled.
2290
2291 #Return zero and greater Miter_Limit ##
2292
2293 #Example
2294 SkPaint paint;
2295 SkDebugf("default miter limit == %g\n", paint.getStrokeMiter());
2296
2297 #StdOut
2298 default miter limit == 4
2299 ##
2300 ##
2301
2302 #SeeAlso Miter_Limit setStrokeMiter Join
2303
2304##
2305
2306#Method void setStrokeMiter(SkScalar miter)
2307
2308 The limit at which a sharp corner is drawn beveled.
2309 Valid values are zero and greater.
2310 Has no effect if miter is less than zero.
2311
2312 #Param miter zero and greater Miter_Limit
2313 ##
2314
2315 #Example
2316 SkPaint paint;
2317 paint.setStrokeMiter(8);
2318 paint.setStrokeMiter(-1);
2319 SkDebugf("default miter limit == %g\n", paint.getStrokeMiter());
2320
2321 #StdOut
2322 default miter limit == 8
2323 ##
2324 ##
2325
2326 #SeeAlso Miter_Limit getStrokeMiter Join
2327
2328##
2329
2330#Topic ##
2331# ------------------------------------------------------------------------------
2332#Topic Stroke_Cap
2333
2334#Enum Cap
2335
2336#Code
2337 enum Cap {
2338 kButt_Cap,
2339 kRound_Cap,
2340 kSquare_Cap,
2341
2342 kLast_Cap = kSquare_Cap,
Cary Clarkbad5ad72017-08-03 17:14:08 -04002343 kDefault_Cap = kButt_Cap,
Cary Clark8032b982017-07-28 11:04:54 -04002344 };
Cary Clark6fc50412017-09-21 12:31:06 -04002345
Cary Clark8032b982017-07-28 11:04:54 -04002346 static constexpr int kCapCount = kLast_Cap + 1;
2347##
2348
2349Stroke_Cap draws at the beginning and end of an open Path_Contour.
2350
2351 #Const kButt_Cap 0
2352 Does not extend the stroke past the beginning or the end.
2353 ##
2354 #Const kRound_Cap 1
2355 Adds a circle with a diameter equal to Stroke_Width at the beginning
2356 and end.
2357 ##
2358 #Const kSquare_Cap 2
2359 Adds a square with sides equal to Stroke_Width at the beginning
2360 and end. The square sides are parallel to the initial and final direction
2361 of the stroke.
2362 ##
2363 #Const kLast_Cap 2
2364 Equivalent to the largest value for Stroke_Cap.
2365 ##
2366 #Const kDefault_Cap 0
2367 Equivalent to kButt_Cap.
2368 Stroke_Cap is set to kButt_Cap by default.
2369 ##
2370
2371 #Const kCapCount 3
2372 The number of different Stroke_Cap values defined.
2373 May be used to verify that Stroke_Cap is a legal value.
2374 ##
2375#Enum ##
2376
2377Stroke describes the area covered by a pen of Stroke_Width as it
Cary Clarkbc5697d2017-10-04 14:31:33 -04002378follows the Path_Contour, moving parallel to the contour direction.
Cary Clark8032b982017-07-28 11:04:54 -04002379
2380If the Path_Contour is not terminated by SkPath::kClose_Verb, the contour has a
2381visible beginning and end.
2382
2383Path_Contour may start and end at the same point; defining Zero_Length_Contour.
2384
2385kButt_Cap and Zero_Length_Contour is not drawn.
2386kRound_Cap and Zero_Length_Contour draws a circle of diameter Stroke_Width
2387at the contour point.
2388kSquare_Cap and Zero_Length_Contour draws an upright square with a side of
2389Stroke_Width at the contour point.
2390
2391Stroke_Cap is kButt_Cap by default.
2392
2393#Example
Cary Clark2ade9972017-11-02 17:49:34 -04002394#Height 200
Cary Clark8032b982017-07-28 11:04:54 -04002395 SkPaint paint;
2396 paint.setStyle(SkPaint::kStroke_Style);
2397 paint.setStrokeWidth(20);
2398 SkPath path;
2399 path.moveTo(30, 30);
2400 path.lineTo(30, 30);
2401 path.moveTo(70, 30);
2402 path.lineTo(90, 40);
2403 for (SkPaint::Cap c : { SkPaint::kButt_Cap, SkPaint::kRound_Cap, SkPaint::kSquare_Cap } ) {
2404 paint.setStrokeCap(c);
2405 canvas->drawPath(path, paint);
2406 canvas->translate(0, 70);
2407 }
2408##
2409
2410#Method Cap getStrokeCap() const
2411
2412 The geometry drawn at the beginning and end of strokes.
2413
2414 #Return one of: kButt_Cap, kRound_Cap, kSquare_Cap ##
2415
2416 #Example
2417 SkPaint paint;
2418 SkDebugf("kButt_Cap %c= default stroke cap\n",
2419 SkPaint::kButt_Cap == paint.getStrokeCap() ? '=' : '!');
2420
2421 #StdOut
2422 kButt_Cap == default stroke cap
2423 ##
2424 ##
2425
2426 #SeeAlso Stroke_Cap setStrokeCap
2427##
2428
2429#Method void setStrokeCap(Cap cap)
2430
2431 The geometry drawn at the beginning and end of strokes.
2432
2433 #Param cap one of: kButt_Cap, kRound_Cap, kSquare_Cap;
2434 has no effect if cap is not valid
2435 ##
2436
2437 #Example
2438 SkPaint paint;
2439 paint.setStrokeCap(SkPaint::kRound_Cap);
2440 paint.setStrokeCap((SkPaint::Cap) SkPaint::kCapCount);
2441 SkDebugf("kRound_Cap %c= paint.getStrokeCap()\n",
2442 SkPaint::kRound_Cap == paint.getStrokeCap() ? '=' : '!');
2443
2444 #StdOut
2445 kRound_Cap == paint.getStrokeCap()
2446 ##
2447 ##
2448
2449 #SeeAlso Stroke_Cap getStrokeCap
2450##
2451
2452#Topic ##
2453# ------------------------------------------------------------------------------
2454#Topic Stroke_Join
2455
2456Stroke_Join draws at the sharp corners of an open or closed Path_Contour.
2457
2458Stroke describes the area covered by a pen of Stroke_Width as it
Cary Clarkbc5697d2017-10-04 14:31:33 -04002459follows the Path_Contour, moving parallel to the contour direction.
Cary Clark8032b982017-07-28 11:04:54 -04002460
2461If the contour direction changes abruptly, because the tangent direction leading
2462to the end of a curve within the contour does not match the tangent direction of
2463the following curve, the pair of curves meet at Stroke_Join.
2464
2465#Example
Cary Clark2ade9972017-11-02 17:49:34 -04002466#Height 200
Cary Clarka560c472017-11-27 10:44:06 -05002467 SkPaint paint;
2468 paint.setStyle(SkPaint::kStroke_Style);
2469 paint.setStrokeWidth(20);
2470 SkPath path;
2471 path.moveTo(30, 20);
2472 path.lineTo(40, 40);
2473 path.conicTo(70, 20, 100, 20, .707f);
2474 for (SkPaint::Join j : { SkPaint::kMiter_Join, SkPaint::kRound_Join, SkPaint::kBevel_Join } ) {
2475 paint.setStrokeJoin(j);
2476 canvas->drawPath(path, paint);
2477 canvas->translate(0, 70);
2478 }
Cary Clark8032b982017-07-28 11:04:54 -04002479##
2480
2481#Enum Join
2482#Code
2483 enum Join {
2484 kMiter_Join,
2485 kRound_Join,
2486 kBevel_Join,
2487
2488 kLast_Join = kBevel_Join,
Cary Clarkbad5ad72017-08-03 17:14:08 -04002489 kDefault_Join = kMiter_Join,
Cary Clark8032b982017-07-28 11:04:54 -04002490 };
Cary Clark6fc50412017-09-21 12:31:06 -04002491
Cary Clark8032b982017-07-28 11:04:54 -04002492 static constexpr int kJoinCount = kLast_Join + 1;
2493##
2494
Cary Clark1eace2d2017-07-31 07:52:43 -04002495Join specifies how corners are drawn when a shape is stroked. Join
Cary Clark8032b982017-07-28 11:04:54 -04002496affects the four corners of a stroked rectangle, and the connected segments in a
2497stroked path.
2498
2499Choose miter join to draw sharp corners. Choose round join to draw a circle with a
2500radius equal to the stroke width on top of the corner. Choose bevel join to minimally
2501connect the thick strokes.
2502
2503The fill path constructed to describe the stroked path respects the join setting but may
2504not contain the actual join. For instance, a fill path constructed with round joins does
2505not necessarily include circles at each connected segment.
2506
2507#Const kMiter_Join 0
2508 Extends the outside corner to the extent allowed by Miter_Limit.
2509 If the extension exceeds Miter_Limit, kBevel_Join is used instead.
2510##
2511
2512#Const kRound_Join 1
2513 Adds a circle with a diameter of Stroke_Width at the sharp corner.
2514##
2515
2516#Const kBevel_Join 2
2517 Connects the outside edges of the sharp corner.
2518##
2519
2520#Const kLast_Join 2
2521 Equivalent to the largest value for Stroke_Join.
2522##
2523
2524#Const kDefault_Join 1
2525 Equivalent to kMiter_Join.
2526 Stroke_Join is set to kMiter_Join by default.
2527##
2528
2529#Const kJoinCount 3
2530 The number of different Stroke_Join values defined.
2531 May be used to verify that Stroke_Join is a legal value.
2532##
2533
2534#Example
2535#Width 462
2536void draw(SkCanvas* canvas) {
2537 SkPath path;
2538 path.moveTo(10, 50);
2539 path.quadTo(35, 110, 60, 210);
2540 path.quadTo(105, 110, 130, 10);
2541 SkPaint paint; // set to default kMiter_Join
2542 paint.setAntiAlias(true);
2543 paint.setStyle(SkPaint::kStroke_Style);
2544 paint.setStrokeWidth(20);
2545 canvas->drawPath(path, paint);
2546 canvas->translate(150, 0);
2547 paint.setStrokeJoin(SkPaint::kBevel_Join);
2548 canvas->drawPath(path, paint);
2549 canvas->translate(150, 0);
2550 paint.setStrokeJoin(SkPaint::kRound_Join);
2551 canvas->drawPath(path, paint);
2552}
2553##
2554
2555#SeeAlso setStrokeJoin getStrokeJoin setStrokeMiter getStrokeMiter
2556
2557#Enum ##
2558
2559#Method Join getStrokeJoin() const
2560
Cary Clark0c5f5462017-12-15 11:21:51 -05002561 The geometry drawn at the corners of strokes.
Cary Clark8032b982017-07-28 11:04:54 -04002562
2563 #Return one of: kMiter_Join, kRound_Join, kBevel_Join ##
2564
2565 #Example
2566 SkPaint paint;
2567 SkDebugf("kMiter_Join %c= default stroke join\n",
2568 SkPaint::kMiter_Join == paint.getStrokeJoin() ? '=' : '!');
2569
2570 #StdOut
2571 kMiter_Join == default stroke join
2572 ##
2573 ##
2574
2575 #SeeAlso Stroke_Join setStrokeJoin
2576##
2577
2578#Method void setStrokeJoin(Join join)
2579
Cary Clark0c5f5462017-12-15 11:21:51 -05002580 The geometry drawn at the corners of strokes.
Cary Clark8032b982017-07-28 11:04:54 -04002581
2582 #Param join one of: kMiter_Join, kRound_Join, kBevel_Join;
Cary Clark579985c2017-07-31 11:48:27 -04002583 otherwise, has no effect
Cary Clark8032b982017-07-28 11:04:54 -04002584 ##
2585
2586 #Example
2587 SkPaint paint;
2588 paint.setStrokeJoin(SkPaint::kMiter_Join);
2589 paint.setStrokeJoin((SkPaint::Join) SkPaint::kJoinCount);
2590 SkDebugf("kMiter_Join %c= paint.getStrokeJoin()\n",
2591 SkPaint::kMiter_Join == paint.getStrokeJoin() ? '=' : '!');
2592
2593 #StdOut
2594 kMiter_Join == paint.getStrokeJoin()
2595 ##
2596 ##
2597
2598 #SeeAlso Stroke_Join getStrokeJoin
2599##
2600
2601#SeeAlso Miter_Limit
2602
2603#Topic Stroke_Join ##
2604# ------------------------------------------------------------------------------
2605#Topic Fill_Path
2606
2607Fill_Path creates a Path by applying the Path_Effect, followed by the Style_Stroke.
2608
2609If Paint contains Path_Effect, Path_Effect operates on the source Path; the result
2610replaces the destination Path. Otherwise, the source Path is replaces the
2611destination Path.
2612
2613Fill Path can request the Path_Effect to restrict to a culling rectangle, but
2614the Path_Effect is not required to do so.
2615
2616If Style is kStroke_Style or kStrokeAndFill_Style,
2617and Stroke_Width is greater than zero, the Stroke_Width, Stroke_Cap, Stroke_Join,
2618and Miter_Limit operate on the destination Path, replacing it.
2619
2620Fill Path can specify the precision used by Stroke_Width to approximate the stroke geometry.
2621
2622If the Style is kStroke_Style and the Stroke_Width is zero, getFillPath
2623returns false since Hairline has no filled equivalent.
2624
2625#Method bool getFillPath(const SkPath& src, SkPath* dst, const SkRect* cullRect,
2626 SkScalar resScale = 1) const
2627
2628 The filled equivalent of the stroked path.
2629
2630 #Param src Path read to create a filled version ##
2631 #Param dst resulting Path; may be the same as src, but may not be nullptr ##
2632 #Param cullRect optional limit passed to Path_Effect ##
2633 #Param resScale if > 1, increase precision, else if (0 < res < 1) reduce precision
2634 to favor speed and size
2635 ##
2636 #Return true if the path represents Style_Fill, or false if it represents Hairline ##
2637
2638 #Example
2639 #Height 192
2640 #Description
Cary Clarkce101242017-09-01 15:51:02 -04002641 A very small Quad stroke is turned into a filled path with increasing levels of precision.
2642 At the lowest precision, the Quad stroke is approximated by a rectangle.
Cary Clark8032b982017-07-28 11:04:54 -04002643 At the highest precision, the filled path has high fidelity compared to the original stroke.
2644 ##
2645 void draw(SkCanvas* canvas) {
2646 SkPaint strokePaint;
2647 strokePaint.setAntiAlias(true);
2648 strokePaint.setStyle(SkPaint::kStroke_Style);
2649 strokePaint.setStrokeWidth(.1f);
2650 SkPath strokePath;
2651 strokePath.moveTo(.08f, .08f);
2652 strokePath.quadTo(.09f, .08f, .17f, .17f);
2653 SkPath fillPath;
2654 SkPaint outlinePaint(strokePaint);
2655 outlinePaint.setStrokeWidth(2);
2656 SkMatrix scale = SkMatrix::MakeScale(300, 300);
2657 for (SkScalar precision : { 0.01f, .1f, 1.f, 10.f, 100.f } ) {
2658 strokePaint.getFillPath(strokePath, &fillPath, nullptr, precision);
2659 fillPath.transform(scale);
2660 canvas->drawPath(fillPath, outlinePaint);
2661 canvas->translate(60, 0);
2662 if (1.f == precision) canvas->translate(-180, 100);
2663 }
2664 strokePath.transform(scale);
2665 strokePaint.setStrokeWidth(30);
2666 canvas->drawPath(strokePath, strokePaint);
2667 }
2668 ##
2669
2670##
2671
2672#Method bool getFillPath(const SkPath& src, SkPath* dst) const
2673
2674 The filled equivalent of the stroked path.
2675
2676 Replaces dst with the src path modified by Path_Effect and Style_Stroke.
2677 Path_Effect, if any, is not culled. Stroke_Width is created with default precision.
2678
2679 #Param src Path read to create a filled version ##
2680 #Param dst resulting Path dst may be the same as src, but may not be nullptr ##
2681 #Return true if the path represents Style_Fill, or false if it represents Hairline ##
2682
2683 #Example
2684 #Height 128
2685 void draw(SkCanvas* canvas) {
2686 SkPaint paint;
2687 paint.setStyle(SkPaint::kStroke_Style);
2688 paint.setStrokeWidth(10);
2689 SkPath strokePath;
2690 strokePath.moveTo(20, 20);
2691 strokePath.lineTo(100, 100);
2692 canvas->drawPath(strokePath, paint);
2693 SkPath fillPath;
2694 paint.getFillPath(strokePath, &fillPath);
2695 paint.setStrokeWidth(2);
2696 canvas->translate(40, 0);
2697 canvas->drawPath(fillPath, paint);
2698 }
2699 ##
2700
2701##
2702
2703#SeeAlso Style_Stroke Stroke_Width Path_Effect
2704
2705#Topic ##
2706# ------------------------------------------------------------------------------
2707#Topic Shader_Methods
2708
2709Shader defines the colors used when drawing a shape.
2710Shader may be an image, a gradient, or a computed fill.
2711If Paint has no Shader, then Color fills the shape.
2712
2713Shader is modulated by Color_Alpha component of Color.
2714If Shader object defines only Color_Alpha, then Color modulated by Color_Alpha describes
2715the fill.
2716
2717The drawn transparency can be modified without altering Shader, by changing Color_Alpha.
2718
2719#Example
2720void draw(SkCanvas* canvas) {
2721 SkPaint paint;
2722 SkPoint center = { 50, 50 };
2723 SkScalar radius = 50;
2724 const SkColor colors[] = { 0xFFFFFFFF, 0xFF000000 };
2725 paint.setShader(SkGradientShader::MakeRadial(center, radius, colors,
2726 nullptr, SK_ARRAY_COUNT(colors), SkShader::kClamp_TileMode));
2727 for (SkScalar a : { 0.3f, 0.6f, 1.0f } ) {
2728 paint.setAlpha((int) (a * 255));
2729 canvas->drawCircle(center.fX, center.fY, radius, paint);
2730 canvas->translate(70, 70);
2731 }
2732}
2733##
2734
2735If Shader generates only Color_Alpha then all components of Color modulate the output.
2736
2737#Example
2738void draw(SkCanvas* canvas) {
2739 SkPaint paint;
2740 SkBitmap bitmap;
2741 bitmap.setInfo(SkImageInfo::MakeA8(5, 1), 5); // bitmap only contains alpha
2742 uint8_t pixels[5] = { 0x22, 0x55, 0x88, 0xBB, 0xFF };
2743 bitmap.setPixels(pixels);
2744 paint.setShader(SkShader::MakeBitmapShader(bitmap,
2745 SkShader::kMirror_TileMode, SkShader::kMirror_TileMode));
2746 for (SkColor c : { SK_ColorRED, SK_ColorBLUE, SK_ColorGREEN } ) {
2747 paint.setColor(c); // all components in color affect shader
2748 canvas->drawCircle(50, 50, 50, paint);
2749 canvas->translate(70, 70);
2750 }
2751}
2752##
2753
2754#Method SkShader* getShader() const
2755
2756 Optional colors used when filling a path, such as a gradient.
2757
2758 Does not alter Shader Reference_Count.
2759
2760 #Return Shader if previously set, nullptr otherwise ##
2761
2762 #Example
2763 void draw(SkCanvas* canvas) {
2764 SkPaint paint;
2765 SkDebugf("nullptr %c= shader\n", paint.getShader() ? '!' : '=');
2766 paint.setShader(SkShader::MakeEmptyShader());
2767 SkDebugf("nullptr %c= shader\n", paint.getShader() ? '!' : '=');
2768 }
2769
2770 #StdOut
2771 nullptr == shader
2772 nullptr != shader
2773 ##
2774 ##
2775
2776##
2777
2778#Method sk_sp<SkShader> refShader() const
2779
2780 Optional colors used when filling a path, such as a gradient.
2781
2782 Increases Shader Reference_Count by one.
2783
2784 #Return Shader if previously set, nullptr otherwise ##
2785
2786 #Example
2787 void draw(SkCanvas* canvas) {
2788 SkPaint paint1, paint2;
2789 paint1.setShader(SkShader::MakeEmptyShader());
2790 SkDebugf("shader unique: %s\n", paint1.getShader()->unique() ? "true" : "false");
2791 paint2.setShader(paint1.refShader());
2792 SkDebugf("shader unique: %s\n", paint1.getShader()->unique() ? "true" : "false");
2793 }
2794
2795 #StdOut
2796 shader unique: true
2797 shader unique: false
2798 ##
2799 ##
2800
2801##
2802
2803#Method void setShader(sk_sp<SkShader> shader)
2804
2805 Optional colors used when filling a path, such as a gradient.
2806
Cary Clarkd0530ba2017-09-14 11:25:39 -04002807 Sets Shader to shader, decreasing Reference_Count of the previous Shader.
Cary Clark6fc50412017-09-21 12:31:06 -04002808 Increments shader Reference_Count by one.
Cary Clark8032b982017-07-28 11:04:54 -04002809
2810 #Param shader how geometry is filled with color; if nullptr, Color is used instead ##
2811
2812 #Example
2813 #Height 64
2814 void draw(SkCanvas* canvas) {
2815 SkPaint paint;
2816 paint.setColor(SK_ColorBLUE);
2817 paint.setShader(SkShader::MakeColorShader(SK_ColorRED));
2818 canvas->drawRect(SkRect::MakeWH(40, 40), paint);
2819 paint.setShader(nullptr);
2820 canvas->translate(50, 0);
2821 canvas->drawRect(SkRect::MakeWH(40, 40), paint);
2822 }
2823 ##
2824
2825##
2826
2827#Topic ##
2828# ------------------------------------------------------------------------------
2829#Topic Color_Filter_Methods
2830
2831Color_Filter alters the color used when drawing a shape.
2832Color_Filter may apply Blend_Mode, transform the color through a matrix, or composite multiple filters.
2833If Paint has no Color_Filter, the color is unaltered.
2834
2835The drawn transparency can be modified without altering Color_Filter, by changing Color_Alpha.
2836
2837#Example
2838#Height 128
2839void draw(SkCanvas* canvas) {
2840 SkPaint paint;
2841 paint.setColorFilter(SkColorMatrixFilter::MakeLightingFilter(0xFFFFFF, 0xFF0000));
2842 for (SkColor c : { SK_ColorBLACK, SK_ColorGREEN } ) {
2843 paint.setColor(c);
2844 canvas->drawRect(SkRect::MakeXYWH(10, 10, 50, 50), paint);
2845 paint.setAlpha(0x80);
2846 canvas->drawRect(SkRect::MakeXYWH(60, 60, 50, 50), paint);
2847 canvas->translate(100, 0);
2848 }
2849}
2850##
2851
2852#Method SkColorFilter* getColorFilter() const
2853
2854 Returns Color_Filter if set, or nullptr.
2855 Does not alter Color_Filter Reference_Count.
2856
2857 #Return Color_Filter if previously set, nullptr otherwise ##
2858
2859 #Example
2860 void draw(SkCanvas* canvas) {
2861 SkPaint paint;
2862 SkDebugf("nullptr %c= color filter\n", paint.getColorFilter() ? '!' : '=');
2863 paint.setColorFilter(SkColorFilter::MakeModeFilter(SK_ColorLTGRAY, SkBlendMode::kSrcIn));
2864 SkDebugf("nullptr %c= color filter\n", paint.getColorFilter() ? '!' : '=');
2865 }
2866
2867 #StdOut
2868 nullptr == color filter
2869 nullptr != color filter
2870 ##
2871 ##
2872##
2873
2874#Method sk_sp<SkColorFilter> refColorFilter() const
2875
2876 Returns Color_Filter if set, or nullptr.
2877 Increases Color_Filter Reference_Count by one.
2878
2879 #Return Color_Filter if set, or nullptr ##
2880
2881 #Example
2882 void draw(SkCanvas* canvas) {
2883 SkPaint paint1, paint2;
2884 paint1.setColorFilter(SkColorFilter::MakeModeFilter(0xFFFF0000, SkBlendMode::kSrcATop));
2885 SkDebugf("color filter unique: %s\n", paint1.getColorFilter()->unique() ? "true" : "false");
2886 paint2.setColorFilter(paint1.refColorFilter());
2887 SkDebugf("color filter unique: %s\n", paint1.getColorFilter()->unique() ? "true" : "false");
2888 }
2889
2890 #StdOut
2891 color filter unique: true
2892 color filter unique: false
2893 ##
2894 ##
2895##
2896
2897#Method void setColorFilter(sk_sp<SkColorFilter> colorFilter)
2898
Cary Clark6fc50412017-09-21 12:31:06 -04002899Sets Color_Filter to filter, decreasing Reference_Count of the previous
2900Color_Filter. Pass nullptr to clear Color_Filter.
2901
2902Increments filter Reference_Count by one.
Cary Clark8032b982017-07-28 11:04:54 -04002903
2904 #Param colorFilter Color_Filter to apply to subsequent draw ##
2905
2906 #Example
2907 #Height 64
2908 void draw(SkCanvas* canvas) {
2909 SkPaint paint;
2910 paint.setColorFilter(SkColorFilter::MakeModeFilter(SK_ColorLTGRAY, SkBlendMode::kSrcIn));
2911 canvas->drawRect(SkRect::MakeWH(50, 50), paint);
2912 paint.setColorFilter(nullptr);
2913 canvas->translate(70, 0);
2914 canvas->drawRect(SkRect::MakeWH(50, 50), paint);
2915 }
2916 ##
2917
2918##
2919
2920#Topic ##
2921# ------------------------------------------------------------------------------
2922#Topic Blend_Mode_Methods
2923
2924Blend_Mode describes how Color combines with the destination color.
2925The default setting, SkBlendMode::kSrcOver, draws the source color
2926over the destination color.
2927
2928#Example
2929void draw(SkCanvas* canvas) {
2930 SkPaint normal, blender;
2931 normal.setColor(0xFF58a889);
2932 blender.setColor(0xFF8958a8);
2933 canvas->clear(0);
2934 for (SkBlendMode m : { SkBlendMode::kSrcOver, SkBlendMode::kSrcIn, SkBlendMode::kSrcOut } ) {
2935 normal.setBlendMode(SkBlendMode::kSrcOver);
2936 canvas->drawOval(SkRect::MakeXYWH(30, 30, 30, 80), normal);
2937 blender.setBlendMode(m);
2938 canvas->drawOval(SkRect::MakeXYWH(10, 50, 80, 30), blender);
2939 canvas->translate(70, 70);
2940 }
2941}
2942##
2943
2944#SeeAlso Blend_Mode
2945
2946#Method SkBlendMode getBlendMode() const
2947
2948 Returns Blend_Mode.
Cary Clark579985c2017-07-31 11:48:27 -04002949 By default, returns SkBlendMode::kSrcOver.
Cary Clark8032b982017-07-28 11:04:54 -04002950
2951 #Return mode used to combine source color with destination color ##
2952
2953 #Example
2954 void draw(SkCanvas* canvas) {
2955 SkPaint paint;
2956 SkDebugf("kSrcOver %c= getBlendMode\n",
2957 SkBlendMode::kSrcOver == paint.getBlendMode() ? '=' : '!');
2958 paint.setBlendMode(SkBlendMode::kSrc);
2959 SkDebugf("kSrcOver %c= getBlendMode\n",
2960 SkBlendMode::kSrcOver == paint.getBlendMode() ? '=' : '!');
2961 }
2962
2963 #StdOut
2964 kSrcOver == getBlendMode
2965 kSrcOver != getBlendMode
2966 ##
2967 ##
2968
2969##
2970
2971#Method bool isSrcOver() const
2972
2973 Returns true if Blend_Mode is SkBlendMode::kSrcOver, the default.
2974
2975 #Return true if Blend_Mode is SkBlendMode::kSrcOver ##
2976
2977 #Example
2978 void draw(SkCanvas* canvas) {
2979 SkPaint paint;
2980 SkDebugf("isSrcOver %c= true\n", paint.isSrcOver() ? '=' : '!');
2981 paint.setBlendMode(SkBlendMode::kSrc);
2982 SkDebugf("isSrcOver %c= true\n", paint.isSrcOver() ? '=' : '!');
2983 }
2984
2985 #StdOut
2986 isSrcOver == true
2987 isSrcOver != true
2988 ##
2989 ##
2990
2991##
2992
2993#Method void setBlendMode(SkBlendMode mode)
2994
2995 Sets Blend_Mode to mode.
2996 Does not check for valid input.
2997
2998 #Param mode SkBlendMode used to combine source color and destination ##
2999
3000 #Example
3001 void draw(SkCanvas* canvas) {
3002 SkPaint paint;
3003 SkDebugf("isSrcOver %c= true\n", paint.isSrcOver() ? '=' : '!');
3004 paint.setBlendMode(SkBlendMode::kSrc);
3005 SkDebugf("isSrcOver %c= true\n", paint.isSrcOver() ? '=' : '!');
3006 }
3007
3008 #StdOut
3009 isSrcOver == true
3010 isSrcOver != true
3011 ##
3012 ##
3013
3014##
3015
3016#Topic ##
3017# ------------------------------------------------------------------------------
3018#Topic Path_Effect_Methods
3019
3020Path_Effect modifies the path geometry before drawing it.
3021Path_Effect may implement dashing, custom fill effects and custom stroke effects.
3022If Paint has no Path_Effect, the path geometry is unaltered when filled or stroked.
3023
3024#Example
3025#Height 160
3026 void draw(SkCanvas* canvas) {
3027 SkPaint paint;
3028 paint.setStyle(SkPaint::kStroke_Style);
3029 paint.setStrokeWidth(16);
3030 SkScalar intervals[] = {30, 10};
3031 paint.setPathEffect(SkDashPathEffect::Make(intervals, SK_ARRAY_COUNT(intervals), 1));
3032 canvas->drawRoundRect({20, 20, 120, 120}, 20, 20, paint);
3033 }
3034##
3035
3036#SeeAlso Path_Effect
3037
3038#Method SkPathEffect* getPathEffect() const
3039
3040 Returns Path_Effect if set, or nullptr.
3041 Does not alter Path_Effect Reference_Count.
3042
3043 #Return Path_Effect if previously set, nullptr otherwise ##
3044
3045 #Example
3046 void draw(SkCanvas* canvas) {
3047 SkPaint paint;
3048 SkDebugf("nullptr %c= path effect\n", paint.getPathEffect() ? '!' : '=');
3049 paint.setPathEffect(SkCornerPathEffect::Make(10));
3050 SkDebugf("nullptr %c= path effect\n", paint.getPathEffect() ? '!' : '=');
3051 }
3052
3053 #StdOut
3054 nullptr == path effect
3055 nullptr != path effect
3056 ##
3057 ##
3058
3059##
3060
3061
3062#Method sk_sp<SkPathEffect> refPathEffect() const
3063
3064 Returns Path_Effect if set, or nullptr.
3065 Increases Path_Effect Reference_Count by one.
3066
3067 #Return Path_Effect if previously set, nullptr otherwise ##
3068
3069 #Example
3070 void draw(SkCanvas* canvas) {
3071 SkPaint paint1, paint2;
Cary Clarka560c472017-11-27 10:44:06 -05003072 SkScalar intervals[] = {1, 2};
3073 paint1.setPathEffect(SkDashPathEffect::Make(intervals, SK_ARRAY_COUNT(intervals), 10));
Cary Clark8032b982017-07-28 11:04:54 -04003074 SkDebugf("path effect unique: %s\n", paint1.getPathEffect()->unique() ? "true" : "false");
3075 paint2.setPathEffect(paint1.refPathEffect());
3076 SkDebugf("path effect unique: %s\n", paint1.getPathEffect()->unique() ? "true" : "false");
3077 }
3078
3079 #StdOut
3080 path effect unique: true
3081 path effect unique: false
3082 ##
3083 ##
3084
3085##
3086
3087
3088#Method void setPathEffect(sk_sp<SkPathEffect> pathEffect)
3089
Cary Clark6fc50412017-09-21 12:31:06 -04003090Sets Path_Effect to pathEffect, decreasing Reference_Count of the previous
3091Path_Effect. Pass nullptr to leave the path geometry unaltered.
3092
3093Increments pathEffect Reference_Count by one.
Cary Clark8032b982017-07-28 11:04:54 -04003094
3095 #Param pathEffect replace Path with a modification when drawn ##
3096
3097 #Example
3098 void draw(SkCanvas* canvas) {
3099 SkPaint paint;
3100 paint.setPathEffect(SkDiscretePathEffect::Make(3, 5));
3101 canvas->drawRect(SkRect::MakeXYWH(40, 40, 175, 175), paint);
3102 }
3103 ##
3104
3105##
3106
3107#Topic ##
3108# ------------------------------------------------------------------------------
3109#Topic Mask_Filter_Methods
3110
Cary Clarkce101242017-09-01 15:51:02 -04003111Mask_Filter uses coverage of the shape drawn to create Mask_Alpha.
Mike Reed8ad91a92018-01-19 19:09:32 -05003112Mask_Filter takes a Mask, and returns a Mask.
Cary Clark6fc50412017-09-21 12:31:06 -04003113
3114Mask_Filter may change the geometry and transparency of the shape, such as
3115creating a blur effect. Set Mask_Filter to nullptr to prevent Mask_Filter from
3116modifying the draw.
Cary Clark8032b982017-07-28 11:04:54 -04003117
3118#Example
3119 void draw(SkCanvas* canvas) {
3120 SkPaint paint;
3121 paint.setMaskFilter(SkBlurMaskFilter::Make(kSolid_SkBlurStyle, 3));
3122 canvas->drawRect(SkRect::MakeXYWH(40, 40, 175, 175), paint);
3123 }
3124##
3125
3126#Method SkMaskFilter* getMaskFilter() const
3127
3128 Returns Mask_Filter if set, or nullptr.
3129 Does not alter Mask_Filter Reference_Count.
3130
3131 #Return Mask_Filter if previously set, nullptr otherwise ##
3132
3133 #Example
3134 void draw(SkCanvas* canvas) {
3135 SkPaint paint;
3136 SkDebugf("nullptr %c= mask filter\n", paint.getMaskFilter() ? '!' : '=');
3137 paint.setMaskFilter(SkBlurMaskFilter::Make(kOuter_SkBlurStyle, 3));
3138 SkDebugf("nullptr %c= mask filter\n", paint.getMaskFilter() ? '!' : '=');
3139 }
3140
3141 #StdOut
3142 nullptr == mask filter
3143 nullptr != mask filter
3144 ##
3145 ##
3146
3147##
3148
3149#Method sk_sp<SkMaskFilter> refMaskFilter() const
3150
3151 Returns Mask_Filter if set, or nullptr.
Cary Clark6fc50412017-09-21 12:31:06 -04003152
Cary Clark8032b982017-07-28 11:04:54 -04003153 Increases Mask_Filter Reference_Count by one.
3154
3155 #Return Mask_Filter if previously set, nullptr otherwise ##
3156
3157 #Example
3158 void draw(SkCanvas* canvas) {
3159 SkPaint paint1, paint2;
3160 paint1.setMaskFilter(SkBlurMaskFilter::Make(kNormal_SkBlurStyle, 1));
3161 SkDebugf("mask filter unique: %s\n", paint1.getMaskFilter()->unique() ? "true" : "false");
3162 paint2.setMaskFilter(paint1.refMaskFilter());
3163 SkDebugf("mask filter unique: %s\n", paint1.getMaskFilter()->unique() ? "true" : "false");
3164 }
3165
3166 #StdOut
3167 mask filter unique: true
3168 mask filter unique: false
3169 ##
3170 ##
3171
3172##
3173
3174#Method void setMaskFilter(sk_sp<SkMaskFilter> maskFilter)
3175
Cary Clark6fc50412017-09-21 12:31:06 -04003176Sets Mask_Filter to maskFilter, decreasing Reference_Count of the previous
3177Mask_Filter. Pass nullptr to clear Mask_Filter and leave Mask_Filter effect on
3178Mask_Alpha unaltered.
3179
Cary Clark6fc50412017-09-21 12:31:06 -04003180Increments maskFilter Reference_Count by one.
Cary Clark8032b982017-07-28 11:04:54 -04003181
3182 #Param maskFilter modifies clipping mask generated from drawn geometry ##
3183
3184 #Example
3185 void draw(SkCanvas* canvas) {
3186 SkPaint paint;
3187 paint.setStyle(SkPaint::kStroke_Style);
3188 paint.setStrokeWidth(10);
3189 paint.setMaskFilter(SkBlurMaskFilter::Make(kNormal_SkBlurStyle, 10));
3190 canvas->drawRect(SkRect::MakeXYWH(40, 40, 175, 175), paint);
3191 }
3192 ##
3193
3194##
3195
3196#Topic ##
3197# ------------------------------------------------------------------------------
3198#Topic Typeface_Methods
3199
3200Typeface identifies the font used when drawing and measuring text.
3201Typeface may be specified by name, from a file, or from a data stream.
3202The default Typeface defers to the platform-specific default font
3203implementation.
3204
3205#Example
3206#Height 100
3207 void draw(SkCanvas* canvas) {
3208 SkPaint paint;
Ben Wagner700ff172017-11-08 15:37:22 -05003209 paint.setTypeface(SkTypeface::MakeFromName(nullptr, SkFontStyle()));
Cary Clark8032b982017-07-28 11:04:54 -04003210 paint.setAntiAlias(true);
3211 paint.setTextSize(36);
3212 canvas->drawString("A Big Hello!", 10, 40, paint);
3213 paint.setTypeface(nullptr);
3214 paint.setFakeBoldText(true);
3215 canvas->drawString("A Big Hello!", 10, 80, paint);
3216 }
3217##
3218
3219#Method SkTypeface* getTypeface() const
3220
3221 Returns Typeface if set, or nullptr.
Cary Clark6fc50412017-09-21 12:31:06 -04003222 Increments Typeface Reference_Count by one.
Cary Clark8032b982017-07-28 11:04:54 -04003223
3224 #Return Typeface if previously set, nullptr otherwise ##
3225
3226 #Example
3227 void draw(SkCanvas* canvas) {
3228 SkPaint paint;
3229 SkDebugf("nullptr %c= typeface\n", paint.getTypeface() ? '!' : '=');
Cary Clark71961fb2018-01-05 14:21:59 -05003230 paint.setTypeface(SkTypeface::MakeFromName("monospace", SkFontStyle()));
Cary Clark8032b982017-07-28 11:04:54 -04003231 SkDebugf("nullptr %c= typeface\n", paint.getTypeface() ? '!' : '=');
3232 }
3233
3234 #StdOut
3235 nullptr == typeface
3236 nullptr != typeface
3237 ##
3238 ##
3239
3240##
3241
3242#Method sk_sp<SkTypeface> refTypeface() const
3243
3244 Increases Typeface Reference_Count by one.
3245
3246 #Return Typeface if previously set, nullptr otherwise ##
3247
3248 #Example
3249 void draw(SkCanvas* canvas) {
3250 SkPaint paint1, paint2;
Cary Clark71961fb2018-01-05 14:21:59 -05003251 paint1.setTypeface(SkTypeface::MakeFromName("monospace",
Cary Clark8032b982017-07-28 11:04:54 -04003252 SkFontStyle(SkFontStyle::kNormal_Weight, SkFontStyle::kNormal_Width,
3253 SkFontStyle::kItalic_Slant)));
3254 SkDebugf("typeface1 %c= typeface2\n",
3255 paint1.getTypeface() == paint2.getTypeface() ? '=' : '!');
3256 paint2.setTypeface(paint1.refTypeface());
3257 SkDebugf("typeface1 %c= typeface2\n",
3258 paint1.getTypeface() == paint2.getTypeface() ? '=' : '!');
3259 }
3260
3261 #StdOut
3262 typeface1 != typeface2
3263 typeface1 == typeface2
3264 ##
3265 ##
3266
3267##
3268
3269#Method void setTypeface(sk_sp<SkTypeface> typeface)
3270
Cary Clark6fc50412017-09-21 12:31:06 -04003271Sets Typeface to typeface, decreasing Reference_Count of the previous Typeface.
3272Pass nullptr to clear Typeface and use the default typeface. Increments
3273typeface Reference_Count by one.
Cary Clark8032b982017-07-28 11:04:54 -04003274
3275 #Param typeface font and style used to draw text ##
3276
3277 #Example
3278 #Height 64
3279 void draw(SkCanvas* canvas) {
3280 SkPaint paint;
Cary Clark71961fb2018-01-05 14:21:59 -05003281 paint.setTypeface(SkTypeface::MakeFromName("monospace", SkFontStyle()));
3282 canvas->drawString("hamburgerfons", 10, 30, paint);
Cary Clark8032b982017-07-28 11:04:54 -04003283 paint.setTypeface(nullptr);
Cary Clark71961fb2018-01-05 14:21:59 -05003284 canvas->drawString("hamburgerfons", 10, 50, paint);
Cary Clark8032b982017-07-28 11:04:54 -04003285 }
3286 ##
3287
3288##
3289
3290#Topic ##
3291# ------------------------------------------------------------------------------
Cary Clark8032b982017-07-28 11:04:54 -04003292#Topic Image_Filter_Methods
3293
3294Image_Filter operates on the pixel representation of the shape, as modified by Paint
3295with Blend_Mode set to SkBlendMode::kSrcOver. Image_Filter creates a new bitmap,
3296which is drawn to the device using the set Blend_Mode.
Cary Clark6fc50412017-09-21 12:31:06 -04003297
Cary Clark8032b982017-07-28 11:04:54 -04003298Image_Filter is higher level than Mask_Filter; for instance, an Image_Filter
Cary Clarkce101242017-09-01 15:51:02 -04003299can operate on all channels of Color, while Mask_Filter generates Alpha only.
Cary Clark8032b982017-07-28 11:04:54 -04003300Image_Filter operates independently of and can be used in combination with
Mike Reed8ad91a92018-01-19 19:09:32 -05003301Mask_Filter.
Cary Clark8032b982017-07-28 11:04:54 -04003302
3303#Example
3304 #ToDo explain why the two draws are so different ##
3305 void draw(SkCanvas* canvas) {
3306 SkPaint paint;
3307 paint.setStyle(SkPaint::kStroke_Style);
3308 paint.setStrokeWidth(2);
3309 SkRegion region;
3310 region.op( 10, 10, 50, 50, SkRegion::kUnion_Op);
3311 region.op( 10, 50, 90, 90, SkRegion::kUnion_Op);
Cary Clarka560c472017-11-27 10:44:06 -05003312 paint.setImageFilter(SkBlurImageFilter::Make(5.0f, 5.0f, nullptr));
Cary Clark8032b982017-07-28 11:04:54 -04003313 canvas->drawRegion(region, paint);
3314 paint.setImageFilter(nullptr);
3315 paint.setMaskFilter(SkBlurMaskFilter::Make(kNormal_SkBlurStyle, 5));
3316 canvas->translate(100, 100);
3317 canvas->drawRegion(region, paint);
3318 }
3319##
3320
3321#Method SkImageFilter* getImageFilter() const
3322
3323 Returns Image_Filter if set, or nullptr.
3324 Does not alter Image_Filter Reference_Count.
3325
3326 #Return Image_Filter if previously set, nullptr otherwise ##
3327
3328 #Example
3329 void draw(SkCanvas* canvas) {
3330 SkPaint paint;
3331 SkDebugf("nullptr %c= image filter\n", paint.getImageFilter() ? '!' : '=');
Cary Clarka560c472017-11-27 10:44:06 -05003332 paint.setImageFilter(SkBlurImageFilter::Make(kOuter_SkBlurStyle, 3, nullptr, nullptr));
Cary Clark8032b982017-07-28 11:04:54 -04003333 SkDebugf("nullptr %c= image filter\n", paint.getImageFilter() ? '!' : '=');
3334 }
3335
3336 #StdOut
3337 nullptr == image filter
3338 nullptr != image filter
3339 ##
3340 ##
3341
3342##
3343
3344#Method sk_sp<SkImageFilter> refImageFilter() const
3345
3346 Returns Image_Filter if set, or nullptr.
3347 Increases Image_Filter Reference_Count by one.
3348
3349 #Return Image_Filter if previously set, nullptr otherwise ##
3350
3351 #Example
3352 void draw(SkCanvas* canvas) {
3353 SkPaint paint1, paint2;
3354 paint1.setImageFilter(SkOffsetImageFilter::Make(25, 25, nullptr));
3355 SkDebugf("image filter unique: %s\n", paint1.getImageFilter()->unique() ? "true" : "false");
3356 paint2.setImageFilter(paint1.refImageFilter());
3357 SkDebugf("image filter unique: %s\n", paint1.getImageFilter()->unique() ? "true" : "false");
3358 }
3359
3360 #StdOut
3361 image filter unique: true
3362 image filter unique: false
3363 ##
3364 ##
3365
3366##
3367
3368#Method void setImageFilter(sk_sp<SkImageFilter> imageFilter)
3369
Cary Clark6fc50412017-09-21 12:31:06 -04003370Sets Image_Filter to imageFilter, decreasing Reference_Count of the previous
3371Image_Filter. Pass nullptr to clear Image_Filter, and remove Image_Filter effect
3372on drawing.
3373
Cary Clark6fc50412017-09-21 12:31:06 -04003374Increments imageFilter Reference_Count by one.
Cary Clark8032b982017-07-28 11:04:54 -04003375
3376 #Param imageFilter how Image is sampled when transformed ##
3377
3378 #Example
3379 #Height 160
3380 void draw(SkCanvas* canvas) {
3381 SkBitmap bitmap;
3382 bitmap.allocN32Pixels(100, 100);
3383 SkCanvas offscreen(bitmap);
3384 SkPaint paint;
3385 paint.setAntiAlias(true);
3386 paint.setColor(SK_ColorWHITE);
3387 paint.setTextSize(96);
3388 offscreen.clear(0);
3389 offscreen.drawString("e", 20, 70, paint);
3390 paint.setImageFilter(
3391 SkLightingImageFilter::MakePointLitDiffuse(SkPoint3::Make(80, 100, 10),
3392 SK_ColorWHITE, 1, 2, nullptr, nullptr));
3393 canvas->drawBitmap(bitmap, 0, 0, &paint);
3394 }
3395 ##
3396
3397##
3398
3399#Topic ##
3400# ------------------------------------------------------------------------------
3401#Topic Draw_Looper_Methods
3402
3403Draw_Looper sets a modifier that communicates state from one Draw_Layer
3404to another to construct the draw.
Cary Clark6fc50412017-09-21 12:31:06 -04003405
Cary Clark8032b982017-07-28 11:04:54 -04003406Draw_Looper draws one or more times, modifying the canvas and paint each time.
3407Draw_Looper may be used to draw multiple colors or create a colored shadow.
3408Set Draw_Looper to nullptr to prevent Draw_Looper from modifying the draw.
3409
3410#Example
3411#Height 128
3412 void draw(SkCanvas* canvas) {
3413 SkLayerDrawLooper::LayerInfo info;
3414 info.fPaintBits = (SkLayerDrawLooper::BitFlags) SkLayerDrawLooper::kColorFilter_Bit;
3415 info.fColorMode = SkBlendMode::kSrc;
3416 SkLayerDrawLooper::Builder looperBuilder;
3417 SkPaint* loopPaint = looperBuilder.addLayer(info);
3418 loopPaint->setColor(SK_ColorRED);
3419 info.fOffset.set(20, 20);
3420 loopPaint = looperBuilder.addLayer(info);
3421 loopPaint->setColor(SK_ColorBLUE);
3422 SkPaint paint;
3423 paint.setDrawLooper(looperBuilder.detach());
3424 canvas->drawCircle(50, 50, 50, paint);
3425 }
3426
3427##
3428
3429#Method SkDrawLooper* getDrawLooper() const
3430
3431 Returns Draw_Looper if set, or nullptr.
3432 Does not alter Draw_Looper Reference_Count.
3433
3434 #Return Draw_Looper if previously set, nullptr otherwise ##
3435
3436 #Example
3437 void draw(SkCanvas* canvas) {
3438 SkPaint paint;
3439 SkDebugf("nullptr %c= draw looper\n", paint.getDrawLooper() ? '!' : '=');
3440 SkLayerDrawLooper::Builder looperBuilder;
3441 paint.setDrawLooper(looperBuilder.detach());
3442 SkDebugf("nullptr %c= draw looper\n", paint.getDrawLooper() ? '!' : '=');
3443 }
3444
3445 #StdOut
3446 nullptr == draw looper
3447 nullptr != draw looper
3448 ##
3449 ##
3450
3451##
3452
3453#Method sk_sp<SkDrawLooper> refDrawLooper() const
3454
3455 Returns Draw_Looper if set, or nullptr.
3456 Increases Draw_Looper Reference_Count by one.
3457
3458 #Return Draw_Looper if previously set, nullptr otherwise ##
3459
3460 #Example
3461 void draw(SkCanvas* canvas) {
3462 SkPaint paint1, paint2;
3463 SkLayerDrawLooper::Builder looperBuilder;
3464 paint1.setDrawLooper(looperBuilder.detach());
3465 SkDebugf("draw looper unique: %s\n", paint1.getDrawLooper()->unique() ? "true" : "false");
3466 paint2.setDrawLooper(paint1.refDrawLooper());
3467 SkDebugf("draw looper unique: %s\n", paint1.getDrawLooper()->unique() ? "true" : "false");
3468 }
3469
3470 #StdOut
3471 draw looper unique: true
3472 draw looper unique: false
3473 ##
3474 ##
3475
3476##
3477
3478#Method SkDrawLooper* getLooper() const
3479
3480Deprecated.
3481
3482#Deprecated
3483(see bug.skia.org/6259)
3484#Deprecated ##
3485
3486#Return Draw_Looper if previously set, nullptr otherwise ##
3487##
3488
3489#Method void setDrawLooper(sk_sp<SkDrawLooper> drawLooper)
3490
Cary Clark6fc50412017-09-21 12:31:06 -04003491Sets Draw_Looper to drawLooper, decreasing Reference_Count of the previous
3492drawLooper. Pass nullptr to clear Draw_Looper and leave Draw_Looper effect on
3493drawing unaltered.
3494
3495Increments drawLooper Reference_Count by one.
Cary Clark8032b982017-07-28 11:04:54 -04003496
Cary Clarka523d2d2017-08-30 08:58:10 -04003497 #Param drawLooper iterates through drawing one or more time, altering Paint ##
Cary Clark8032b982017-07-28 11:04:54 -04003498
3499 #Example
3500 #Height 128
3501 void draw(SkCanvas* canvas) {
3502 SkPaint paint;
3503 paint.setDrawLooper(SkBlurDrawLooper::Make(0x7FFF0000, 4, -5, -10));
3504 paint.setStyle(SkPaint::kStroke_Style);
3505 paint.setStrokeWidth(10);
3506 paint.setAntiAlias(true);
3507 paint.setColor(0x7f0000ff);
3508 canvas->drawCircle(70, 70, 50, paint);
3509 }
3510 ##
3511
3512##
3513
3514#Method void setLooper(sk_sp<SkDrawLooper> drawLooper)
3515
3516Deprecated.
3517
3518#Deprecated
3519(see bug.skia.org/6259)
3520#Deprecated ##
3521
3522#Param drawLooper sets Draw_Looper to drawLooper ##
3523
3524##
3525
3526#Topic ##
3527# ------------------------------------------------------------------------------
3528#Topic Text_Align
3529
3530#Enum Align
3531#Code
3532 enum Align {
3533 kLeft_Align,
3534 kCenter_Align,
3535 kRight_Align,
3536 };
3537##
3538
3539Align adjusts the text relative to the text position.
Cary Clarkce101242017-09-01 15:51:02 -04003540Align affects Glyphs drawn with: SkCanvas::drawText, SkCanvas::drawPosText,
Cary Clark8032b982017-07-28 11:04:54 -04003541SkCanvas::drawPosTextH, SkCanvas::drawTextOnPath,
3542SkCanvas::drawTextOnPathHV, SkCanvas::drawTextRSXform, SkCanvas::drawTextBlob,
3543and SkCanvas::drawString;
Cary Clarkce101242017-09-01 15:51:02 -04003544as well as calls that place text Glyphs like getTextWidths and getTextPath.
Cary Clark8032b982017-07-28 11:04:54 -04003545
3546The text position is set by the font for both horizontal and vertical text.
3547Typically, for horizontal text, the position is to the left side of the glyph on the
3548base line; and for vertical text, the position is the horizontal center of the glyph
3549at the caps height.
3550
3551Align adjusts the glyph position to center it or move it to abut the position
3552using the metrics returned by the font.
3553
3554Align defaults to kLeft_Align.
3555
3556#Const kLeft_Align 0
3557 Leaves the glyph at the position computed by the font offset by the text position.
3558##
3559
3560#Const kCenter_Align 1
3561 Moves the glyph half its width if Flags has kVerticalText_Flag clear, and
3562 half its height if Flags has kVerticalText_Flag set.
3563##
3564
3565#Const kRight_Align 2
3566 Moves the glyph by its width if Flags has kVerticalText_Flag clear,
3567 and by its height if Flags has kVerticalText_Flag set.
3568##
3569
3570#Enum ##
3571
3572#Enum
3573
3574#Code
3575 enum {
Cary Clarkbad5ad72017-08-03 17:14:08 -04003576 kAlignCount = 3,
Cary Clark8032b982017-07-28 11:04:54 -04003577 };
3578##
3579
3580#Const kAlignCount 3
3581 The number of different Text_Align values defined.
3582##
3583
3584#Enum ##
3585
3586#Example
3587 #Height 160
3588 #Description
3589 Each position separately moves the glyph in drawPosText.
3590 ##
3591 void draw(SkCanvas* canvas) {
3592 SkPaint paint;
3593 paint.setTextSize(40);
3594 SkPoint position[] = {{100, 50}, {150, 40}};
3595 for (SkPaint::Align a : { SkPaint::kLeft_Align,
3596 SkPaint::kCenter_Align,
3597 SkPaint::kRight_Align}) {
3598 paint.setTextAlign(a);
3599 canvas->drawPosText("Aa", 2, position, paint);
3600 canvas->translate(0, 50);
3601 }
3602 }
3603##
3604
3605#Example
3606 #Height 160
3607 #Description
3608 Vertical_Text treats kLeft_Align as top align, and kRight_Align as bottom align.
3609 ##
3610 void draw(SkCanvas* canvas) {
3611 SkPaint paint;
3612 paint.setTextSize(40);
3613 paint.setVerticalText(true);
3614 for (SkPaint::Align a : { SkPaint::kLeft_Align,
3615 SkPaint::kCenter_Align,
3616 SkPaint::kRight_Align }) {
3617 paint.setTextAlign(a);
3618 canvas->drawString("Aa", 50, 80, paint);
3619 canvas->translate(50, 0);
3620 }
3621 }
3622##
3623
3624#Method Align getTextAlign() const
3625
3626 Returns Text_Align.
3627 Returns kLeft_Align if Text_Align has not been set.
3628
3629 #Return text placement relative to position ##
3630
3631 #Example
3632 SkPaint paint;
3633 SkDebugf("kLeft_Align %c= default\n", SkPaint::kLeft_Align == paint.getTextAlign() ? '=' : '!');
3634
3635 #StdOut
3636 kLeft_Align == default
3637 ##
3638 ##
3639##
3640
3641#Method void setTextAlign(Align align)
3642
3643 Sets Text_Align to align.
3644 Has no effect if align is an invalid value.
3645
3646 #Param align text placement relative to position ##
3647
3648 #Example
3649 #Height 160
3650 #Description
3651 Text is left-aligned by default, and then set to center. Setting the
3652 alignment out of range has no effect.
3653 ##
3654 void draw(SkCanvas* canvas) {
3655 SkPaint paint;
3656 paint.setTextSize(40);
3657 canvas->drawString("Aa", 100, 50, paint);
3658 paint.setTextAlign(SkPaint::kCenter_Align);
3659 canvas->drawString("Aa", 100, 100, paint);
3660 paint.setTextAlign((SkPaint::Align) SkPaint::kAlignCount);
3661 canvas->drawString("Aa", 100, 150, paint);
3662 }
3663 ##
3664
3665##
3666
3667#Topic ##
3668# ------------------------------------------------------------------------------
3669#Topic Text_Size
3670
3671Text_Size adjusts the overall text size in points.
3672Text_Size can be set to any positive value or zero.
3673Text_Size defaults to 12.
3674Set SkPaintDefaults_TextSize at compile time to change the default setting.
3675
3676#Example
3677#Height 135
3678 void draw(SkCanvas* canvas) {
3679 SkPaint paint;
3680 canvas->drawString("12 point", 10, 20, paint);
3681 paint.setTextSize(24);
3682 canvas->drawString("24 point", 10, 60, paint);
3683 paint.setTextSize(48);
3684 canvas->drawString("48 point", 10, 120, paint);
3685 }
3686##
3687
3688#Method SkScalar getTextSize() const
3689
3690 Returns Text_Size in points.
3691
3692 #Return typographic height of text ##
3693
3694 #Example
3695 SkPaint paint;
3696 SkDebugf("12 %c= default text size\n", 12 == paint.getTextSize() ? '=' : '!');
3697 ##
3698
3699##
3700
3701#Method void setTextSize(SkScalar textSize)
3702
3703 Sets Text_Size in points.
3704 Has no effect if textSize is not greater than or equal to zero.
3705
3706 #Param textSize typographic height of text ##
3707
3708 #Example
3709 SkPaint paint;
3710 SkDebugf("12 %c= text size\n", 12 == paint.getTextSize() ? '=' : '!');
3711 paint.setTextSize(-20);
3712 SkDebugf("12 %c= text size\n", 12 == paint.getTextSize() ? '=' : '!');
3713 ##
3714
3715##
3716
3717#Topic ##
3718# ------------------------------------------------------------------------------
3719#Topic Text_Scale_X
3720
3721Text_Scale_X adjusts the text horizontal scale.
3722Text scaling approximates condensed and expanded type faces when the actual face
3723is not available.
3724Text_Scale_X can be set to any value.
3725Text_Scale_X defaults to 1.
3726
3727#Example
3728#Height 128
3729 void draw(SkCanvas* canvas) {
3730 SkPaint paint;
3731 paint.setAntiAlias(true);
3732 paint.setTextSize(24);
3733 paint.setTextScaleX(.8f);
3734 canvas->drawString("narrow", 10, 20, paint);
3735 paint.setTextScaleX(1);
3736 canvas->drawString("normal", 10, 60, paint);
3737 paint.setTextScaleX(1.2f);
3738 canvas->drawString("wide", 10, 100, paint);
3739 }
3740##
3741
3742#Method SkScalar getTextScaleX() const
3743
3744 Returns Text_Scale_X.
3745 Default value is 1.
3746
3747 #Return text horizontal scale ##
3748
3749 #Example
3750 SkPaint paint;
3751 SkDebugf("1 %c= default text scale x\n", 1 == paint.getTextScaleX() ? '=' : '!');
3752 ##
3753
3754##
3755
3756
3757#Method void setTextScaleX(SkScalar scaleX)
3758
3759 Sets Text_Scale_X.
3760 Default value is 1.
3761
3762 #Param scaleX text horizontal scale ##
3763
3764 #Example
3765 SkPaint paint;
3766 paint.setTextScaleX(0.f / 0.f);
3767 SkDebugf("text scale %s-a-number\n", SkScalarIsNaN(paint.getTextScaleX()) ? "not" : "is");
3768 ##
3769
3770##
3771
3772#Topic ##
3773
3774#Topic Text_Skew_X
3775
3776
3777Text_Skew_X adjusts the text horizontal slant.
3778Text skewing approximates italic and oblique type faces when the actual face
3779is not available.
3780Text_Skew_X can be set to any value.
3781Text_Skew_X defaults to 0.
3782
3783#Example
3784#Height 128
3785 void draw(SkCanvas* canvas) {
3786 SkPaint paint;
3787 paint.setAntiAlias(true);
3788 paint.setTextSize(24);
3789 paint.setTextSkewX(-.25f);
3790 canvas->drawString("right-leaning", 10, 100, paint);
3791 paint.setTextSkewX(0);
3792 canvas->drawString("normal", 10, 60, paint);
3793 paint.setTextSkewX(.25f);
3794 canvas->drawString("left-leaning", 10, 20, paint);
3795 }
3796##
3797
3798#Method SkScalar getTextSkewX() const
3799
3800 Returns Text_Skew_X.
3801 Default value is zero.
3802
3803 #Return additional shear in x-axis relative to y-axis ##
3804
3805 #Example
3806 SkPaint paint;
3807 SkDebugf("0 %c= default text skew x\n", 0 == paint.getTextSkewX() ? '=' : '!');
3808 ##
3809
3810##
3811
3812#Method void setTextSkewX(SkScalar skewX)
3813
3814 Sets Text_Skew_X.
3815 Default value is zero.
3816
3817 #Param skewX additional shear in x-axis relative to y-axis ##
3818
3819 #Example
3820 SkPaint paint;
3821 paint.setTextScaleX(1.f / 0.f);
3822 SkDebugf("text scale %s-finite\n", SkScalarIsFinite(paint.getTextScaleX()) ? "is" : "not");
3823 ##
3824
3825##
3826
3827#Topic ##
3828
3829# ------------------------------------------------------------------------------
3830#Topic Text_Encoding
3831
3832#Enum TextEncoding
3833
3834#Code
3835 enum TextEncoding {
3836 kUTF8_TextEncoding,
3837 kUTF16_TextEncoding,
3838 kUTF32_TextEncoding,
Cary Clarkbad5ad72017-08-03 17:14:08 -04003839 kGlyphID_TextEncoding,
Cary Clark8032b982017-07-28 11:04:54 -04003840 };
3841##
3842
Cary Clark6fc50412017-09-21 12:31:06 -04003843TextEncoding determines whether text specifies character codes and their encoded
Cary Clarkbc5697d2017-10-04 14:31:33 -04003844size, or glyph indices. Characters are encoded as specified by the
Cary Clark6fc50412017-09-21 12:31:06 -04003845#A Unicode standard # http://unicode.org/standard/standard.html ##
3846.
3847
Cary Clark8032b982017-07-28 11:04:54 -04003848Character codes encoded size are specified by UTF-8, UTF-16, or UTF-32.
Cary Clarkbc5697d2017-10-04 14:31:33 -04003849All character code formats are able to represent all of Unicode, differing only
Cary Clark8032b982017-07-28 11:04:54 -04003850in the total storage required.
3851
Cary Clark6fc50412017-09-21 12:31:06 -04003852#A UTF-8 (RFC 3629) # https://tools.ietf.org/html/rfc3629 ##
3853 encodes each character as one or more 8-bit bytes.
3854
3855#A UTF-16 (RFC 2781) # https://tools.ietf.org/html/rfc2781 ##
3856 encodes each character as one or two 16-bit words.
3857
3858#A UTF-32 # http://www.unicode.org/versions/Unicode5.0.0/ch03.pdf ##
3859 encodes each character as one 32-bit word.
Cary Clark8032b982017-07-28 11:04:54 -04003860
3861Font_Manager uses font data to convert character code points into glyph indices.
3862A glyph index is a 16-bit word.
3863
3864TextEncoding is set to kUTF8_TextEncoding by default.
3865
3866#Const kUTF8_TextEncoding 0
3867Uses bytes to represent UTF-8 or ASCII.
3868##
3869#Const kUTF16_TextEncoding 1
3870Uses two byte words to represent most of Unicode.
3871##
3872#Const kUTF32_TextEncoding 2
3873Uses four byte words to represent all of Unicode.
3874##
3875#Const kGlyphID_TextEncoding 3
3876Uses two byte words to represent glyph indices.
3877##
3878
3879#Enum ##
3880
3881#Example
3882#Height 128
3883#Description
Cary Clarkbc5697d2017-10-04 14:31:33 -04003884First line is encoded in UTF-8.
3885Second line is encoded in UTF-16.
3886Third line is encoded in UTF-32.
Cary Clark8032b982017-07-28 11:04:54 -04003887Fourth line has 16 bit glyph indices.
3888##
3889void draw(SkCanvas* canvas) {
3890 SkPaint paint;
3891 const char hello8[] = "Hello" "\xE2" "\x98" "\xBA";
3892 const uint16_t hello16[] = { 'H', 'e', 'l', 'l', 'o', 0x263A };
3893 const uint32_t hello32[] = { 'H', 'e', 'l', 'l', 'o', 0x263A };
3894 paint.setTextSize(24);
3895 canvas->drawText(hello8, sizeof(hello8) - 1, 10, 30, paint);
3896 paint.setTextEncoding(SkPaint::kUTF16_TextEncoding);
3897 canvas->drawText(hello16, sizeof(hello16), 10, 60, paint);
3898 paint.setTextEncoding(SkPaint::kUTF32_TextEncoding);
3899 canvas->drawText(hello32, sizeof(hello32), 10, 90, paint);
3900 uint16_t glyphs[SK_ARRAY_COUNT(hello32)];
3901 paint.textToGlyphs(hello32, sizeof(hello32), glyphs);
3902 paint.setTextEncoding(SkPaint::kGlyphID_TextEncoding);
3903 canvas->drawText(glyphs, sizeof(glyphs), 10, 120, paint);
3904}
3905##
3906
3907#Method TextEncoding getTextEncoding() const
3908
3909 Returns Text_Encoding.
3910 Text_Encoding determines how character code points are mapped to font glyph indices.
3911
3912 #Return one of: kUTF8_TextEncoding, kUTF16_TextEncoding, kUTF32_TextEncoding, or
3913 kGlyphID_TextEncoding
3914 ##
3915
3916 #Example
3917 SkPaint paint;
3918 SkDebugf("kUTF8_TextEncoding %c= text encoding\n",
3919 SkPaint::kUTF8_TextEncoding == paint.getTextEncoding() ? '=' : '!');
3920 paint.setTextEncoding(SkPaint::kGlyphID_TextEncoding);
3921 SkDebugf("kGlyphID_TextEncoding %c= text encoding\n",
3922 SkPaint::kGlyphID_TextEncoding == paint.getTextEncoding() ? '=' : '!');
3923
3924 #StdOut
3925 kUTF8_TextEncoding == text encoding
3926 kGlyphID_TextEncoding == text encoding
3927 ##
3928 ##
3929
3930##
3931
3932
3933#Method void setTextEncoding(TextEncoding encoding)
3934
3935 Sets Text_Encoding to encoding.
3936 Text_Encoding determines how character code points are mapped to font glyph indices.
3937 Invalid values for encoding are ignored.
3938
3939 #Param encoding one of: kUTF8_TextEncoding, kUTF16_TextEncoding, kUTF32_TextEncoding, or
Cary Clark579985c2017-07-31 11:48:27 -04003940 kGlyphID_TextEncoding
3941 #Param ##
Cary Clark8032b982017-07-28 11:04:54 -04003942
3943 #Example
3944 SkPaint paint;
3945 paint.setTextEncoding((SkPaint::TextEncoding) 4);
3946 SkDebugf("4 %c= text encoding\n", 4 == paint.getTextEncoding() ? '=' : '!');
3947
3948 #StdOut
3949 4 != text encoding
3950 ##
3951 ##
3952
3953##
3954
3955#Topic ##
3956# ------------------------------------------------------------------------------
3957#Topic Font_Metrics
3958
Cary Clarkce101242017-09-01 15:51:02 -04003959Font_Metrics describe dimensions common to the Glyphs in Typeface.
Cary Clark8032b982017-07-28 11:04:54 -04003960The dimensions are computed by Font_Manager from font data and do not take
3961Paint settings other than Text_Size into account.
3962
3963Font dimensions specify the anchor to the left of the glyph at baseline as the origin.
3964X-axis values to the left of the glyph are negative, and to the right of the left glyph edge
3965are positive.
3966Y-axis values above the baseline are negative, and below the baseline are positive.
Ben Wagnere5806492017-11-09 12:08:31 -05003967
Cary Clark8032b982017-07-28 11:04:54 -04003968#Example
3969#Width 512
3970void draw(SkCanvas* canvas) {
3971 SkPaint paint;
3972 paint.setAntiAlias(true);
3973 paint.setTextSize(120);
3974 SkPaint::FontMetrics fm;
3975 SkScalar lineHeight = paint.getFontMetrics(&fm);
3976 SkPoint pt = { 70, 180 };
3977 canvas->drawString("M", pt.fX, pt.fY, paint);
3978 canvas->drawLine(pt.fX, pt.fY, pt.fX, pt.fY + fm.fTop, paint);
3979 SkScalar ascent = pt.fY + fm.fAscent;
3980 canvas->drawLine(pt.fX - 25, ascent, pt.fX - 25, ascent + lineHeight, paint);
3981 canvas->drawLine(pt.fX - 50, pt.fY, pt.fX - 50, pt.fY + fm.fDescent, paint);
3982 canvas->drawLine(pt.fX + 100, pt.fY, pt.fX + 100, pt.fY + fm.fAscent, paint);
3983 canvas->drawLine(pt.fX + 125, pt.fY, pt.fX + 125, pt.fY - fm.fXHeight, paint);
3984 canvas->drawLine(pt.fX + 150, pt.fY, pt.fX + 150, pt.fY - fm.fCapHeight, paint);
3985 canvas->drawLine(pt.fX + 5, pt.fY, pt.fX + 5, pt.fY + fm.fBottom, paint);
3986 SkScalar xmin = pt.fX + fm.fXMin;
3987 canvas->drawLine(xmin, pt.fY + 60, xmin + fm.fMaxCharWidth, pt.fY + 60, paint);
3988 canvas->drawLine(xmin, pt.fY - 145, pt.fX, pt.fY - 145, paint);
3989 canvas->drawLine(pt.fX + fm.fXMax, pt.fY - 160, pt.fX, pt.fY - 160, paint);
3990 SkScalar upos = pt.fY + fm.fUnderlinePosition;
Ben Wagnere5806492017-11-09 12:08:31 -05003991 canvas->drawLine(pt.fX + 25, upos, pt.fX + 160, upos, paint);
3992 SkScalar ut = fm.fUnderlineThickness;
3993 canvas->drawLine(pt.fX + 130, upos + ut, pt.fX + 160, upos + ut, paint);
Cary Clark8032b982017-07-28 11:04:54 -04003994 paint.setTextSize(12);
3995 canvas->drawString("x-min", pt.fX - 50, pt.fY - 148, paint);
3996 canvas->drawString("x-max", pt.fX + 140, pt.fY - 150, paint);
3997 canvas->drawString("max char width", pt.fX + 120, pt.fY + 57, paint);
3998 canvas->drawString("underline position", pt.fX + 30, pt.fY + 22, paint);
3999 canvas->drawString("underline thickness", pt.fX + 162, pt.fY + 13, paint);
4000 canvas->rotate(-90);
4001 canvas->drawString("descent", -pt.fY - 30, pt.fX - 54, paint);
4002 canvas->drawString("line height", -pt.fY, pt.fX - 29, paint);
4003 canvas->drawString("top", -pt.fY + 30, pt.fX - 4, paint);
4004 canvas->drawString("ascent", -pt.fY, pt.fX + 110, paint);
4005 canvas->drawString("x-height", -pt.fY, pt.fX + 135, paint);
4006 canvas->drawString("cap-height", -pt.fY, pt.fX + 160, paint);
4007 canvas->drawString("bottom", -pt.fY - 50, pt.fX + 15, paint);
4008}
4009##
4010
4011#Struct FontMetrics
4012
4013#Code
4014 struct FontMetrics {
4015 enum FontMetricsFlags {
4016 kUnderlineThicknessIsValid_Flag = 1 << 0,
4017 kUnderlinePositionIsValid_Flag = 1 << 1,
4018 kStrikeoutThicknessIsValid_Flag = 1 << 2,
4019 kStrikeoutPositionIsValid_Flag = 1 << 3,
4020 };
4021
4022 uint32_t fFlags;
4023 SkScalar fTop;
4024 SkScalar fAscent;
4025 SkScalar fDescent;
4026 SkScalar fBottom;
4027 SkScalar fLeading;
4028 SkScalar fAvgCharWidth;
4029 SkScalar fMaxCharWidth;
4030 SkScalar fXMin;
4031 SkScalar fXMax;
4032 SkScalar fXHeight;
4033 SkScalar fCapHeight;
4034 SkScalar fUnderlineThickness;
4035 SkScalar fUnderlinePosition;
4036 SkScalar fStrikeoutThickness;
4037 SkScalar fStrikeoutPosition;
4038
4039 bool hasUnderlineThickness(SkScalar* thickness) const;
4040 bool hasUnderlinePosition(SkScalar* position) const;
4041 bool hasStrikeoutThickness(SkScalar* thickness) const;
4042 bool hasStrikeoutPosition(SkScalar* position) const;
4043 };
4044##
4045
Cary Clark154beea2017-10-26 07:58:48 -04004046 FontMetrics is filled out by getFontMetrics. FontMetrics contents reflect the values
4047 computed by Font_Manager using Typeface. Values are set to zero if they are
4048 not available.
Cary Clarke4aa3712017-09-15 02:56:12 -04004049
Ben Wagnere5806492017-11-09 12:08:31 -05004050 All vertical values relative to the baseline are given y-down. As such, zero is on the
4051 baseline, negative values are above the baseline, and positive values are below the
4052 baseline.
4053
Cary Clark154beea2017-10-26 07:58:48 -04004054 fUnderlineThickness and fUnderlinePosition have a bit set in fFlags if their values
4055 are valid, since their value may be zero.
Ben Wagnere5806492017-11-09 12:08:31 -05004056
Cary Clark154beea2017-10-26 07:58:48 -04004057 fStrikeoutThickness and fStrikeoutPosition have a bit set in fFlags if their values
4058 are valid, since their value may be zero.
4059
4060 #Enum FontMetricsFlags
Cary Clarke4aa3712017-09-15 02:56:12 -04004061
Cary Clark8032b982017-07-28 11:04:54 -04004062 #Code
4063 enum FontMetricsFlags {
4064 kUnderlineThicknessIsValid_Flag = 1 << 0,
4065 kUnderlinePositionIsValid_Flag = 1 << 1,
4066 kStrikeoutThicknessIsValid_Flag = 1 << 2,
4067 kStrikeoutPositionIsValid_Flag = 1 << 3,
4068 };
4069 ##
4070
Cary Clark154beea2017-10-26 07:58:48 -04004071 FontMetricsFlags are set in fFlags when underline and strikeout metrics are valid;
4072 the underline or strikeout metric may be valid and zero.
4073 Fonts with embedded bitmaps may not have valid underline or strikeout metrics.
4074
Cary Clark8032b982017-07-28 11:04:54 -04004075 #Const kUnderlineThicknessIsValid_Flag 0x0001
4076 Set if fUnderlineThickness is valid.
4077 ##
4078 #Const kUnderlinePositionIsValid_Flag 0x0002
4079 Set if fUnderlinePosition is valid.
4080 ##
4081 #Const kStrikeoutThicknessIsValid_Flag 0x0004
4082 Set if fStrikeoutThickness is valid.
4083 ##
4084 #Const kStrikeoutPositionIsValid_Flag 0x0008
4085 Set if fStrikeoutPosition is valid.
4086 ##
4087
4088 #Enum ##
4089
4090 #Member uint32_t fFlags
4091 fFlags is set when underline metrics are valid.
4092 ##
Ben Wagnere5806492017-11-09 12:08:31 -05004093
Cary Clark8032b982017-07-28 11:04:54 -04004094 #Member SkScalar fTop
Ben Wagnere5806492017-11-09 12:08:31 -05004095 Greatest extent above the baseline for any glyph.
4096 Typically less than zero.
Cary Clark8032b982017-07-28 11:04:54 -04004097 ##
Ben Wagnere5806492017-11-09 12:08:31 -05004098
Cary Clark8032b982017-07-28 11:04:54 -04004099 #Member SkScalar fAscent
4100 Recommended distance above the baseline to reserve for a line of text.
Ben Wagnere5806492017-11-09 12:08:31 -05004101 Typically less than zero.
Cary Clark8032b982017-07-28 11:04:54 -04004102 ##
Ben Wagnere5806492017-11-09 12:08:31 -05004103
Cary Clark8032b982017-07-28 11:04:54 -04004104 #Member SkScalar fDescent
4105 Recommended distance below the baseline to reserve for a line of text.
Ben Wagnere5806492017-11-09 12:08:31 -05004106 Typically greater than zero.
Cary Clark8032b982017-07-28 11:04:54 -04004107 ##
Ben Wagnere5806492017-11-09 12:08:31 -05004108
Cary Clark8032b982017-07-28 11:04:54 -04004109 #Member SkScalar fBottom
Ben Wagnere5806492017-11-09 12:08:31 -05004110 Greatest extent below the baseline for any glyph.
4111 Typically greater than zero.
Cary Clark8032b982017-07-28 11:04:54 -04004112 ##
Ben Wagnere5806492017-11-09 12:08:31 -05004113
Cary Clark8032b982017-07-28 11:04:54 -04004114 #Member SkScalar fLeading
4115 Recommended distance to add between lines of text.
Ben Wagnere5806492017-11-09 12:08:31 -05004116 Typically greater than or equal to zero.
Cary Clark8032b982017-07-28 11:04:54 -04004117 ##
Ben Wagnere5806492017-11-09 12:08:31 -05004118
Cary Clark8032b982017-07-28 11:04:54 -04004119 #Member SkScalar fAvgCharWidth
4120 Average character width, if it is available.
4121 Zero if no average width is stored in the font.
4122 ##
Ben Wagnere5806492017-11-09 12:08:31 -05004123
Cary Clark8032b982017-07-28 11:04:54 -04004124 #Member SkScalar fMaxCharWidth
4125 Maximum character width.
4126 ##
Ben Wagnere5806492017-11-09 12:08:31 -05004127
Cary Clark8032b982017-07-28 11:04:54 -04004128 #Member SkScalar fXMin
Ben Wagnere5806492017-11-09 12:08:31 -05004129 Minimum bounding box x value for all Glyphs.
Cary Clark8032b982017-07-28 11:04:54 -04004130 Typically less than zero.
4131 ##
Ben Wagnere5806492017-11-09 12:08:31 -05004132
Cary Clark8032b982017-07-28 11:04:54 -04004133 #Member SkScalar fXMax
Cary Clarkce101242017-09-01 15:51:02 -04004134 Maximum bounding box x value for all Glyphs.
Cary Clark8032b982017-07-28 11:04:54 -04004135 Typically greater than zero.
4136 ##
Ben Wagnere5806492017-11-09 12:08:31 -05004137
Cary Clark8032b982017-07-28 11:04:54 -04004138 #Member SkScalar fXHeight
4139 Height of a lower-case 'x'.
4140 May be zero if no lower-case height is stored in the font.
4141 ##
Ben Wagnere5806492017-11-09 12:08:31 -05004142
Cary Clark8032b982017-07-28 11:04:54 -04004143 #Member SkScalar fCapHeight
4144 Height of an upper-case letter.
4145 May be zero if no upper-case height is stored in the font.
4146 ##
Ben Wagnere5806492017-11-09 12:08:31 -05004147
Cary Clark8032b982017-07-28 11:04:54 -04004148 #Member SkScalar fUnderlineThickness
Ben Wagnere5806492017-11-09 12:08:31 -05004149 Underline thickness.
4150
4151 If the metric is valid, the kUnderlineThicknessIsValid_Flag is set in fFlags.
Cary Clark8032b982017-07-28 11:04:54 -04004152 If kUnderlineThicknessIsValid_Flag is clear, fUnderlineThickness is zero.
4153 ##
Ben Wagnere5806492017-11-09 12:08:31 -05004154
Cary Clark8032b982017-07-28 11:04:54 -04004155 #Member SkScalar fUnderlinePosition
Ben Wagnere5806492017-11-09 12:08:31 -05004156 Position of the top of the underline stroke relative to the baseline.
4157 Typically positive when valid.
Cary Clark8032b982017-07-28 11:04:54 -04004158
4159 If the metric is valid, the kUnderlinePositionIsValid_Flag is set in fFlags.
4160 If kUnderlinePositionIsValid_Flag is clear, fUnderlinePosition is zero.
4161 ##
4162
4163 #Member SkScalar fStrikeoutThickness
Ben Wagnere5806492017-11-09 12:08:31 -05004164 Strikeout thickness.
4165
4166 If the metric is valid, the kStrikeoutThicknessIsValid_Flag is set in fFlags.
Cary Clark8032b982017-07-28 11:04:54 -04004167 If kStrikeoutThicknessIsValid_Flag is clear, fStrikeoutThickness is zero.
4168 ##
4169
4170 #Member SkScalar fStrikeoutPosition
Ben Wagnere5806492017-11-09 12:08:31 -05004171 Position of the bottom of the strikeout stroke relative to the baseline.
4172 Typically negative when valid.
Cary Clark8032b982017-07-28 11:04:54 -04004173
Ben Wagnere5806492017-11-09 12:08:31 -05004174 If the metric is valid, the kStrikeoutPositionIsValid_Flag is set in fFlags.
4175 If kStrikeoutPositionIsValid_Flag is clear, fStrikeoutPosition is zero.
Cary Clark8032b982017-07-28 11:04:54 -04004176 ##
4177
4178 #Method bool hasUnderlineThickness(SkScalar* thickness) const
4179
Ben Wagnere5806492017-11-09 12:08:31 -05004180 If Font_Metrics has a valid underline thickness, return true, and set
Cary Clarkce101242017-09-01 15:51:02 -04004181 thickness to that value. If the underline thickness is not valid,
4182 return false, and ignore thickness.
Cary Clark8032b982017-07-28 11:04:54 -04004183
4184 #Param thickness storage for underline width ##
4185
4186 #Return true if font specifies underline width ##
4187
4188 #NoExample
4189 ##
4190 ##
4191
4192 #Method bool hasUnderlinePosition(SkScalar* position) const
4193
Ben Wagnere5806492017-11-09 12:08:31 -05004194 If Font_Metrics has a valid underline position, return true, and set
Cary Clarkce101242017-09-01 15:51:02 -04004195 position to that value. If the underline position is not valid,
4196 return false, and ignore position.
Cary Clark8032b982017-07-28 11:04:54 -04004197
4198 #Param position storage for underline position ##
4199
4200 #Return true if font specifies underline position ##
4201
4202 #NoExample
4203 ##
4204 ##
4205
4206 #Method bool hasStrikeoutThickness(SkScalar* thickness) const
4207
Ben Wagnere5806492017-11-09 12:08:31 -05004208 If Font_Metrics has a valid strikeout thickness, return true, and set
Cary Clarkce101242017-09-01 15:51:02 -04004209 thickness to that value. If the underline thickness is not valid,
4210 return false, and ignore thickness.
Cary Clark8032b982017-07-28 11:04:54 -04004211
4212 #Param thickness storage for strikeout width ##
4213
4214 #Return true if font specifies strikeout width ##
4215
4216 #NoExample
4217 ##
4218 ##
4219
4220 #Method bool hasStrikeoutPosition(SkScalar* position) const
4221
Ben Wagnere5806492017-11-09 12:08:31 -05004222 If Font_Metrics has a valid strikeout position, return true, and set
Cary Clarkce101242017-09-01 15:51:02 -04004223 position to that value. If the underline position is not valid,
4224 return false, and ignore position.
Cary Clark8032b982017-07-28 11:04:54 -04004225
4226 #Param position storage for strikeout position ##
4227
4228 #Return true if font specifies strikeout position ##
4229
4230 #NoExample
4231 ##
4232 ##
4233
4234#Struct ##
4235
4236#Method SkScalar getFontMetrics(FontMetrics* metrics, SkScalar scale = 0) const
4237
4238 Returns Font_Metrics associated with Typeface.
4239 The return value is the recommended spacing between lines: the sum of metrics
4240 descent, ascent, and leading.
4241 If metrics is not nullptr, Font_Metrics is copied to metrics.
4242 Results are scaled by Text_Size but does not take into account
4243 dimensions required by Text_Scale_X, Text_Skew_X, Fake_Bold,
4244 Style_Stroke, and Path_Effect.
4245 Results can be additionally scaled by scale; a scale of zero
4246 is ignored.
4247
4248 #Param metrics storage for Font_Metrics from Typeface; may be nullptr ##
4249 #Param scale additional multiplier for returned values ##
4250
4251 #Return recommended spacing between lines ##
4252
4253 #Example
4254 #Height 128
4255 void draw(SkCanvas* canvas) {
4256 SkPaint paint;
4257 paint.setTextSize(32);
4258 SkScalar lineHeight = paint.getFontMetrics(nullptr);
4259 canvas->drawString("line 1", 10, 40, paint);
4260 canvas->drawString("line 2", 10, 40 + lineHeight, paint);
4261 paint.setStyle(SkPaint::kStroke_Style);
4262 paint.setStrokeWidth(10);
4263 lineHeight = paint.getFontMetrics(nullptr, 1.10f); // account for stroke height
4264 canvas->drawString("line 3", 120, 40, paint);
4265 canvas->drawString("line 4", 120, 40 + lineHeight, paint);
4266 }
4267 ##
4268
4269 #SeeAlso Text_Size Typeface Typeface_Methods
4270
4271##
4272
4273
4274#Method SkScalar getFontSpacing() const
4275
4276 Returns the recommended spacing between lines: the sum of metrics
4277 descent, ascent, and leading.
4278 Result is scaled by Text_Size but does not take into account
4279 dimensions required by stroking and Path_Effect.
Cary Clark579985c2017-07-31 11:48:27 -04004280 Returns the same result as getFontMetrics.
Cary Clark8032b982017-07-28 11:04:54 -04004281
Cary Clark0c5f5462017-12-15 11:21:51 -05004282 #Return recommended spacing between lines ##
Cary Clark8032b982017-07-28 11:04:54 -04004283
4284 #Example
4285 SkPaint paint;
4286 for (SkScalar textSize : { 12, 18, 24, 32 } ) {
4287 paint.setTextSize(textSize);
4288 SkDebugf("textSize: %g fontSpacing: %g\n", textSize, paint.getFontSpacing());
4289 }
4290
4291 #StdOut
4292 textSize: 12 fontSpacing: 13.9688
4293 textSize: 18 fontSpacing: 20.9531
4294 textSize: 24 fontSpacing: 27.9375
4295 textSize: 32 fontSpacing: 37.25
4296 ##
4297 ##
4298
4299##
4300
4301
4302#Method SkRect getFontBounds() const
4303
Cary Clarkce101242017-09-01 15:51:02 -04004304Returns the union of bounds of all Glyphs.
Cary Clark8032b982017-07-28 11:04:54 -04004305Returned dimensions are computed by Font_Manager from font data,
Cary Clark579985c2017-07-31 11:48:27 -04004306ignoring Hinting. Includes Text_Size, Text_Scale_X,
Cary Clark8032b982017-07-28 11:04:54 -04004307and Text_Skew_X, but not Fake_Bold or Path_Effect.
4308
4309If Text_Size is large, Text_Scale_X is one, and Text_Skew_X is zero,
Cary Clark579985c2017-07-31 11:48:27 -04004310returns the same bounds as Font_Metrics { FontMetrics::fXMin,
Cary Clark8032b982017-07-28 11:04:54 -04004311FontMetrics::fTop, FontMetrics::fXMax, FontMetrics::fBottom }.
4312
Cary Clarkce101242017-09-01 15:51:02 -04004313#Return union of bounds of all Glyphs ##
Cary Clark8032b982017-07-28 11:04:54 -04004314
4315#Example
4316 SkPaint paint;
4317 SkPaint::FontMetrics fm;
4318 paint.getFontMetrics(&fm);
4319 SkRect fb = paint.getFontBounds();
4320 SkDebugf("metrics bounds = { %g, %g, %g, %g }\n", fm.fXMin, fm.fTop, fm.fXMax, fm.fBottom );
4321 SkDebugf("font bounds = { %g, %g, %g, %g }\n", fb.fLeft, fb.fTop, fb.fRight, fm.fBottom );
4322
4323 #StdOut
4324 metrics bounds = { -12.2461, -14.7891, 21.5215, 5.55469 }
4325 font bounds = { -12.2461, -14.7891, 21.5215, 5.55469 }
4326 ##
4327##
4328
4329##
4330
4331#Topic ##
4332# ------------------------------------------------------------------------------
4333
4334#Method int textToGlyphs(const void* text, size_t byteLength,
4335 SkGlyphID glyphs[]) const
4336
4337Converts text into glyph indices.
4338Returns the number of glyph indices represented by text.
4339Text_Encoding specifies how text represents characters or glyphs.
4340glyphs may be nullptr, to compute the glyph count.
4341
Cary Clarkbc5697d2017-10-04 14:31:33 -04004342Does not check text for valid character codes or valid glyph indices.
Cary Clark8032b982017-07-28 11:04:54 -04004343
Cary Clark579985c2017-07-31 11:48:27 -04004344If byteLength equals zero, returns zero.
Cary Clark8032b982017-07-28 11:04:54 -04004345If byteLength includes a partial character, the partial character is ignored.
4346
4347If Text_Encoding is kUTF8_TextEncoding and
4348text contains an invalid UTF-8 sequence, zero is returned.
4349
Cary Clarkce101242017-09-01 15:51:02 -04004350#Param text character storage encoded with Text_Encoding ##
Cary Clark8032b982017-07-28 11:04:54 -04004351#Param byteLength length of character storage in bytes ##
4352#Param glyphs storage for glyph indices; may be nullptr ##
4353
4354#Return number of glyphs represented by text of length byteLength ##
4355
4356 #Example
4357 #Height 64
4358 void draw(SkCanvas* canvas) {
4359 SkPaint paint;
4360 const uint8_t utf8[] = { 0x24, 0xC2, 0xA2, 0xE2, 0x82, 0xAC, 0xC2, 0xA5, 0xC2, 0xA3 };
4361 std::vector<SkGlyphID> glyphs;
4362 int count = paint.textToGlyphs(utf8, sizeof(utf8), nullptr);
4363 glyphs.resize(count);
4364 (void) paint.textToGlyphs(utf8, sizeof(utf8), &glyphs.front());
4365 paint.setTextEncoding(SkPaint::kGlyphID_TextEncoding);
4366 paint.setTextSize(32);
4367 canvas->drawText(&glyphs.front(), glyphs.size() * sizeof(SkGlyphID), 10, 40, paint);
4368 }
4369 ##
4370
4371##
4372
4373#Method int countText(const void* text, size_t byteLength) const
4374
Cary Clarkce101242017-09-01 15:51:02 -04004375 Returns the number of Glyphs in text.
4376 Uses Text_Encoding to count the Glyphs.
Cary Clark8032b982017-07-28 11:04:54 -04004377 Returns the same result as textToGlyphs.
4378
Cary Clarkce101242017-09-01 15:51:02 -04004379#Param text character storage encoded with Text_Encoding ##
Cary Clark8032b982017-07-28 11:04:54 -04004380#Param byteLength length of character storage in bytes ##
4381
Cary Clarkce101242017-09-01 15:51:02 -04004382#Return number of Glyphs represented by text of length byteLength ##
Cary Clark8032b982017-07-28 11:04:54 -04004383
4384 #Example
4385 SkPaint paint;
4386 const uint8_t utf8[] = { 0x24, 0xC2, 0xA2, 0xE2, 0x82, 0xAC, 0xC2, 0xA5, 0xC2, 0xA3 };
4387 SkDebugf("count = %d\n", paint.countText(utf8, sizeof(utf8)));
4388
4389 #StdOut
4390 count = 5
4391 ##
4392 ##
4393##
4394
4395# ------------------------------------------------------------------------------
4396
4397#Method bool containsText(const void* text, size_t byteLength) const
4398
4399 Returns true if all text corresponds to a non-zero glyph index.
4400 Returns false if any characters in text are not supported in
4401 Typeface.
4402
Cary Clark579985c2017-07-31 11:48:27 -04004403 If Text_Encoding is kGlyphID_TextEncoding,
4404 returns true if all glyph indices in text are non-zero;
Cary Clark8032b982017-07-28 11:04:54 -04004405 does not check to see if text contains valid glyph indices for Typeface.
4406
Cary Clarkce101242017-09-01 15:51:02 -04004407 Returns true if byteLength is zero.
Cary Clark8032b982017-07-28 11:04:54 -04004408
Cary Clarkce101242017-09-01 15:51:02 -04004409 #Param text array of characters or Glyphs ##
Cary Clark8032b982017-07-28 11:04:54 -04004410 #Param byteLength number of bytes in text array ##
4411
4412 #Return true if all text corresponds to a non-zero glyph index ##
4413
4414 #Example
4415 #Description
4416 containsText succeeds for degree symbol, but cannot find a glyph index
4417 corresponding to the Unicode surrogate code point.
4418 ##
4419 SkPaint paint;
4420 const uint16_t goodChar = 0x00B0; // degree symbol
4421 const uint16_t badChar = 0xD800; // Unicode surrogate
4422 paint.setTextEncoding(SkPaint::kUTF16_TextEncoding);
4423 SkDebugf("0x%04x %c= has char\n", goodChar,
4424 paint.containsText(&goodChar, 2) ? '=' : '!');
4425 SkDebugf("0x%04x %c= has char\n", badChar,
4426 paint.containsText(&badChar, 2) ? '=' : '!');
4427
4428 #StdOut
4429 0x00b0 == has char
4430 0xd800 != has char
4431 ##
4432 ##
4433
4434 #Example
4435 #Description
4436 containsText returns true that glyph index is greater than zero, not
4437 that it corresponds to an entry in Typeface.
4438 ##
4439 SkPaint paint;
4440 const uint16_t goodGlyph = 511;
4441 const uint16_t zeroGlyph = 0;
4442 const uint16_t badGlyph = 65535; // larger than glyph count in font
4443 paint.setTextEncoding(SkPaint::kGlyphID_TextEncoding);
4444 SkDebugf("0x%04x %c= has glyph\n", goodGlyph,
4445 paint.containsText(&goodGlyph, 2) ? '=' : '!');
4446 SkDebugf("0x%04x %c= has glyph\n", zeroGlyph,
4447 paint.containsText(&zeroGlyph, 2) ? '=' : '!');
4448 SkDebugf("0x%04x %c= has glyph\n", badGlyph,
4449 paint.containsText(&badGlyph, 2) ? '=' : '!');
4450
4451 #StdOut
4452 0x01ff == has glyph
4453 0x0000 != has glyph
4454 0xffff == has glyph
4455 ##
4456 ##
4457
4458#SeeAlso setTextEncoding Typeface
4459
4460##
4461
4462# ------------------------------------------------------------------------------
4463
4464#Method void glyphsToUnichars(const SkGlyphID glyphs[],
4465 int count, SkUnichar text[]) const
4466
4467 Converts glyphs into text if possible.
4468 Glyph values without direct Unicode equivalents are mapped to zero.
4469 Uses the Typeface, but is unaffected
4470 by Text_Encoding; the text values returned are equivalent to kUTF32_TextEncoding.
4471
4472 Only supported on platforms that use FreeType as the Font_Engine.
4473
4474 #Param glyphs array of indices into font ##
4475 #Param count length of glyph array ##
4476 #Param text storage for character codes, one per glyph ##
4477
4478 #Example
4479 #Height 64
4480 #Description
4481 Convert UTF-8 text to glyphs; then convert glyphs to Unichar code points.
4482 ##
4483 void draw(SkCanvas* canvas) {
4484 SkPaint paint;
4485 const char hello[] = "Hello!";
4486 const int count = sizeof(hello) - 1;
4487 SkGlyphID glyphs[count];
4488 if (count != paint.textToGlyphs(hello, count, glyphs)) {
4489 return;
4490 }
4491 SkUnichar unichars[count];
4492 paint.glyphsToUnichars(glyphs, count, unichars);
4493 paint.setTextEncoding(SkPaint::kUTF32_TextEncoding);
4494 canvas->drawText(unichars, sizeof(unichars), 10, 30, paint);
4495 }
4496 ##
4497
4498##
4499
4500# ------------------------------------------------------------------------------
4501#Topic Measure_Text
4502
4503#Method SkScalar measureText(const void* text, size_t length, SkRect* bounds) const
4504
4505 Returns the advance width of text if kVerticalText_Flag is clear,
4506 and the height of text if kVerticalText_Flag is set.
4507 The advance is the normal distance to move before drawing additional text.
4508 Uses Text_Encoding to decode text, Typeface to get the font metrics,
4509 and Text_Size, Text_Scale_X, Text_Skew_X, Stroke_Width, and
4510 Path_Effect to scale the metrics and bounds.
4511 Returns the bounding box of text if bounds is not nullptr.
4512 The bounding box is computed as if the text was drawn at the origin.
4513
4514 #Param text character codes or glyph indices to be measured ##
4515 #Param length number of bytes of text to measure ##
4516 #Param bounds returns bounding box relative to (0, 0) if not nullptr ##
4517
4518 #Return advance width or height ##
4519
4520 #Example
4521 #Height 64
4522 void draw(SkCanvas* canvas) {
4523 SkPaint paint;
4524 paint.setAntiAlias(true);
4525 paint.setTextSize(50);
4526 const char str[] = "ay^jZ";
4527 const int count = sizeof(str) - 1;
4528 canvas->drawText(str, count, 25, 50, paint);
4529 SkRect bounds;
4530 paint.measureText(str, count, &bounds);
4531 canvas->translate(25, 50);
4532 paint.setStyle(SkPaint::kStroke_Style);
4533 canvas->drawRect(bounds, paint);
4534 }
4535 ##
4536
4537##
4538
4539#Method SkScalar measureText(const void* text, size_t length) const
4540
4541 Returns the advance width of text if kVerticalText_Flag is clear,
4542 and the height of text if kVerticalText_Flag is set.
4543 The advance is the normal distance to move before drawing additional text.
4544 Uses Text_Encoding to decode text, Typeface to get the font metrics,
4545 and Text_Size to scale the metrics.
4546 Does not scale the advance or bounds by Fake_Bold or Path_Effect.
4547
4548 #Param text character codes or glyph indices to be measured ##
4549 #Param length number of bytes of text to measure ##
4550
4551 #Return advance width or height ##
4552
4553 #Example
4554 SkPaint paint;
4555 SkDebugf("default width = %g\n", paint.measureText("!", 1));
4556 paint.setTextSize(paint.getTextSize() * 2);
4557 SkDebugf("double width = %g\n", paint.measureText("!", 1));
4558
4559 #StdOut
4560 default width = 5
4561 double width = 10
4562 ##
4563 ##
4564
4565##
4566
4567#Method size_t breakText(const void* text, size_t length, SkScalar maxWidth,
Cary Clark73fa9722017-08-29 17:36:51 -04004568 SkScalar* measuredWidth = nullptr) const
Cary Clark8032b982017-07-28 11:04:54 -04004569
4570 Returns the bytes of text that fit within maxWidth.
4571 If kVerticalText_Flag is clear, the text fragment fits if its advance width is less than or
4572 equal to maxWidth.
4573 If kVerticalText_Flag is set, the text fragment fits if its advance height is less than or
4574 equal to maxWidth.
4575 Measures only while the advance is less than or equal to maxWidth.
4576 Returns the advance or the text fragment in measuredWidth if it not nullptr.
4577 Uses Text_Encoding to decode text, Typeface to get the font metrics,
4578 and Text_Size to scale the metrics.
4579 Does not scale the advance or bounds by Fake_Bold or Path_Effect.
4580
4581 #Param text character codes or glyph indices to be measured ##
4582 #Param length number of bytes of text to measure ##
4583 #Param maxWidth advance limit; text is measured while advance is less than maxWidth ##
4584 #Param measuredWidth returns the width of the text less than or equal to maxWidth ##
4585 #Return bytes of text that fit, always less than or equal to length ##
4586
4587 #Example
4588 #Description
4589 Line under "Breakfast" shows desired width, shorter than available characters.
4590 Line under "Bre" shows measured width after breaking text.
4591 ##
4592 #Height 128
4593 #Width 280
4594 void draw(SkCanvas* canvas) {
4595 SkPaint paint;
4596 paint.setAntiAlias(true);
4597 paint.setTextSize(50);
4598 const char str[] = "Breakfast";
4599 const int count = sizeof(str) - 1;
4600 canvas->drawText(str, count, 25, 50, paint);
4601 SkScalar measuredWidth;
4602 int partialBytes = paint.breakText(str, count, 100, &measuredWidth);
4603 canvas->drawText(str, partialBytes, 25, 100, paint);
4604 canvas->drawLine(25, 60, 25 + 100, 60, paint);
4605 canvas->drawLine(25, 110, 25 + measuredWidth, 110, paint);
4606 }
4607 ##
4608
4609##
4610
4611#Method int getTextWidths(const void* text, size_t byteLength, SkScalar widths[],
Cary Clark73fa9722017-08-29 17:36:51 -04004612 SkRect bounds[] = nullptr) const
Cary Clark8032b982017-07-28 11:04:54 -04004613
4614 Retrieves the advance and bounds for each glyph in text, and returns
4615 the glyph count in text.
4616 Both widths and bounds may be nullptr.
4617 If widths is not nullptr, widths must be an array of glyph count entries.
4618 if bounds is not nullptr, bounds must be an array of glyph count entries.
4619 If kVerticalText_Flag is clear, widths returns the horizontal advance.
4620 If kVerticalText_Flag is set, widths returns the vertical advance.
4621 Uses Text_Encoding to decode text, Typeface to get the font metrics,
4622 and Text_Size to scale the widths and bounds.
4623 Does not scale the advance by Fake_Bold or Path_Effect.
4624 Does include Fake_Bold and Path_Effect in the bounds.
4625
4626 #Param text character codes or glyph indices to be measured ##
4627 #Param byteLength number of bytes of text to measure ##
4628 #Param widths returns text advances for each glyph; may be nullptr ##
4629 #Param bounds returns bounds for each glyph relative to (0, 0); may be nullptr ##
4630
4631 #Return glyph count in text ##
4632
4633 #Example
4634 #Height 160
4635 #Description
Cary Clarkce101242017-09-01 15:51:02 -04004636 Bounds of Glyphs increase for stroked text, but text advance remains the same.
Cary Clark8032b982017-07-28 11:04:54 -04004637 The underlines show the text advance, spaced to keep them distinct.
4638 ##
4639 void draw(SkCanvas* canvas) {
4640 SkPaint paint;
4641 paint.setAntiAlias(true);
4642 paint.setTextSize(50);
4643 const char str[] = "abc";
4644 const int bytes = sizeof(str) - 1;
4645 int count = paint.getTextWidths(str, bytes, nullptr);
4646 std::vector<SkScalar> widths;
4647 std::vector<SkRect> bounds;
4648 widths.resize(count);
4649 bounds.resize(count);
4650 for (int loop = 0; loop < 2; ++loop) {
4651 (void) paint.getTextWidths(str, count, &widths.front(), &bounds.front());
4652 SkPoint loc = { 25, 50 };
4653 canvas->drawText(str, bytes, loc.fX, loc.fY, paint);
4654 paint.setStyle(SkPaint::kStroke_Style);
4655 paint.setStrokeWidth(0);
4656 SkScalar advanceY = loc.fY + 10;
4657 for (int index = 0; index < count; ++index) {
4658 bounds[index].offset(loc.fX, loc.fY);
4659 canvas->drawRect(bounds[index], paint);
4660 canvas->drawLine(loc.fX, advanceY, loc.fX + widths[index], advanceY, paint);
4661 loc.fX += widths[index];
4662 advanceY += 5;
4663 }
4664 canvas->translate(0, 80);
4665 paint.setStrokeWidth(3);
4666 }
4667 }
4668 ##
4669
4670##
4671
4672#Topic ##
4673# ------------------------------------------------------------------------------
4674#Topic Text_Path
4675
Cary Clarkce101242017-09-01 15:51:02 -04004676Text_Path describes the geometry of Glyphs used to draw text.
Cary Clark8032b982017-07-28 11:04:54 -04004677
4678#Method void getTextPath(const void* text, size_t length, SkScalar x, SkScalar y,
4679 SkPath* path) const
4680
4681Returns the geometry as Path equivalent to the drawn text.
4682Uses Text_Encoding to decode text, Typeface to get the glyph paths,
4683and Text_Size, Fake_Bold, and Path_Effect to scale and modify the glyph paths.
4684All of the glyph paths are stored in path.
Cary Clark579985c2017-07-31 11:48:27 -04004685Uses x, y, and Text_Align to position path.
Cary Clark8032b982017-07-28 11:04:54 -04004686
4687 #Param text character codes or glyph indices ##
4688 #Param length number of bytes of text ##
4689 #Param x x-coordinate of the origin of the text ##
4690 #Param y y-coordinate of the origin of the text ##
Cary Clarkce101242017-09-01 15:51:02 -04004691 #Param path geometry of the Glyphs ##
Cary Clark8032b982017-07-28 11:04:54 -04004692
4693 #Example
4694 #Description
4695 Text is added to Path, offset, and subtracted from Path, then added at
4696 the offset location. The result is rendered with one draw call.
4697 ##
4698 #Height 128
4699 void draw(SkCanvas* canvas) {
4700 SkPaint paint;
4701 paint.setTextSize(80);
4702 SkPath path, path2;
4703 paint.getTextPath("ABC", 3, 20, 80, &path);
4704 path.offset(20, 20, &path2);
4705 Op(path, path2, SkPathOp::kDifference_SkPathOp, &path);
4706 path.addPath(path2);
4707 paint.setStyle(SkPaint::kStroke_Style);
4708 canvas->drawPath(path, paint);
4709 }
4710 ##
4711
4712##
4713
4714#Method void getPosTextPath(const void* text, size_t length,
4715 const SkPoint pos[], SkPath* path) const
4716
4717Returns the geometry as Path equivalent to the drawn text.
4718Uses Text_Encoding to decode text, Typeface to get the glyph paths,
4719and Text_Size, Fake_Bold, and Path_Effect to scale and modify the glyph paths.
4720All of the glyph paths are stored in path.
4721Uses pos array and Text_Align to position path.
4722pos contains a position for each glyph.
4723
4724 #Param text character codes or glyph indices ##
4725 #Param length number of bytes of text ##
4726 #Param pos positions of each glyph ##
Cary Clarkce101242017-09-01 15:51:02 -04004727 #Param path geometry of the Glyphs ##
Cary Clark8032b982017-07-28 11:04:54 -04004728
4729 #Example
4730 #Height 85
4731 #Description
Cary Clarkce101242017-09-01 15:51:02 -04004732 Simplifies three Glyphs to eliminate overlaps, and strokes the result.
Cary Clark8032b982017-07-28 11:04:54 -04004733 ##
4734 void draw(SkCanvas* canvas) {
4735 SkPaint paint;
4736 paint.setTextSize(80);
4737 SkPath path, path2;
4738 SkPoint pos[] = {{20, 60}, {30, 70}, {40, 80}};
4739 paint.getPosTextPath("ABC", 3, pos, &path);
4740 Simplify(path, &path);
4741 paint.setStyle(SkPaint::kStroke_Style);
4742 canvas->drawPath(path, paint);
4743 }
4744 ##
4745
4746##
4747
4748#Topic ##
4749# ------------------------------------------------------------------------------
4750#Topic Text_Intercepts
4751
Cary Clarkce101242017-09-01 15:51:02 -04004752Text_Intercepts describe the intersection of drawn text Glyphs with a pair
Cary Clark8032b982017-07-28 11:04:54 -04004753of lines parallel to the text advance. Text_Intercepts permits creating a
Cary Clarkce101242017-09-01 15:51:02 -04004754underline that skips Descenders.
Cary Clark8032b982017-07-28 11:04:54 -04004755
4756#Method int getTextIntercepts(const void* text, size_t length, SkScalar x, SkScalar y,
4757 const SkScalar bounds[2], SkScalar* intervals) const
4758
4759 Returns the number of intervals that intersect bounds.
4760 bounds describes a pair of lines parallel to the text advance.
Cary Clarkce101242017-09-01 15:51:02 -04004761 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 -04004762 the string.
4763 Uses Text_Encoding to decode text, Typeface to get the glyph paths,
4764 and Text_Size, Fake_Bold, and Path_Effect to scale and modify the glyph paths.
4765 Uses x, y, and Text_Align to position intervals.
4766
4767 Pass nullptr for intervals to determine the size of the interval array.
4768
4769 intervals are cached to improve performance for multiple calls.
4770
4771 #Param text character codes or glyph indices ##
4772 #Param length number of bytes of text ##
4773 #Param x x-coordinate of the origin of the text ##
4774 #Param y y-coordinate of the origin of the text ##
4775 #Param bounds lower and upper line parallel to the advance ##
4776 #Param intervals returned intersections; may be nullptr ##
4777
4778 #Return number of intersections; may be zero ##
4779
4780#Example
4781#Height 128
4782#Description
Cary Clarkce101242017-09-01 15:51:02 -04004783Underline uses intercepts to draw on either side of the glyph Descender.
Cary Clark8032b982017-07-28 11:04:54 -04004784##
4785void draw(SkCanvas* canvas) {
4786 SkPaint paint;
4787 paint.setTextSize(120);
4788 SkPoint textOrigin = { 20, 100 };
4789 SkScalar bounds[] = { 100, 108 };
4790 int count = paint.getTextIntercepts("y", 1, textOrigin.fX, textOrigin.fY, bounds, nullptr);
4791 std::vector<SkScalar> intervals;
4792 intervals.resize(count);
4793 (void) paint.getTextIntercepts("y", 1, textOrigin.fX, textOrigin.fY, bounds,
4794 &intervals.front());
4795 canvas->drawString("y", textOrigin.fX, textOrigin.fY, paint);
4796 paint.setColor(SK_ColorRED);
4797 SkScalar x = textOrigin.fX;
4798 for (int i = 0; i < count; i += 2) {
4799 canvas->drawRect({x, bounds[0], intervals[i], bounds[1]}, paint);
4800 x = intervals[i + 1];
4801 }
4802 canvas->drawRect({intervals[count - 1], bounds[0],
4803 textOrigin.fX + paint.measureText("y", 1), bounds[1]}, paint);
4804}
4805##
4806
4807##
4808
4809#Method int getPosTextIntercepts(const void* text, size_t length, const SkPoint pos[],
4810 const SkScalar bounds[2], SkScalar* intervals) const
4811
4812 Returns the number of intervals that intersect bounds.
4813 bounds describes a pair of lines parallel to the text advance.
Cary Clarkce101242017-09-01 15:51:02 -04004814 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 -04004815 the string.
4816 Uses Text_Encoding to decode text, Typeface to get the glyph paths,
4817 and Text_Size, Fake_Bold, and Path_Effect to scale and modify the glyph paths.
4818 Uses pos array and Text_Align to position intervals.
4819
4820 Pass nullptr for intervals to determine the size of the interval array.
4821
4822 intervals are cached to improve performance for multiple calls.
4823
4824 #Param text character codes or glyph indices ##
4825 #Param length number of bytes of text ##
4826 #Param pos positions of each glyph ##
4827 #Param bounds lower and upper line parallel to the advance ##
4828 #Param intervals returned intersections; may be nullptr ##
4829
Cary Clarka523d2d2017-08-30 08:58:10 -04004830 #Return number of intersections; may be zero ##
Cary Clark8032b982017-07-28 11:04:54 -04004831
4832 #Example
4833 #Description
Cary Clarkce101242017-09-01 15:51:02 -04004834 Text intercepts draw on either side of, but not inside, Glyphs in a run.
Cary Clark8032b982017-07-28 11:04:54 -04004835 ##
4836 void draw(SkCanvas* canvas) {
4837 SkPaint paint;
4838 paint.setTextSize(120);
4839 paint.setVerticalText(true);
4840 SkPoint textPos[] = {{ 60, 40 }, { 60, 140 }};
4841 SkScalar bounds[] = { 56, 64 };
4842 const char str[] = "A-";
4843 int len = sizeof(str) - 1;
4844 int count = paint.getPosTextIntercepts(str, len, textPos, bounds, nullptr);
4845 std::vector<SkScalar> intervals;
4846 intervals.resize(count);
4847 (void) paint.getPosTextIntercepts(str, len, textPos, bounds, &intervals.front());
4848 canvas->drawPosText(str, len, textPos, paint);
4849 paint.setColor(SK_ColorRED);
4850 SkScalar y = textPos[0].fY;
4851 for (int i = 0; i < count; i+= 2) {
4852 canvas->drawRect({bounds[0], y, bounds[1], intervals[i]}, paint);
4853 y = intervals[i + 1];
4854 }
4855 canvas->drawRect({bounds[0], intervals[count - 1], bounds[1], 240}, paint);
4856 }
4857 ##
4858
4859##
4860
4861#Method int getPosTextHIntercepts(const void* text, size_t length, const SkScalar xpos[],
4862 SkScalar constY, const SkScalar bounds[2],
4863 SkScalar* intervals) const
4864
4865 Returns the number of intervals that intersect bounds.
4866 bounds describes a pair of lines parallel to the text advance.
Cary Clarkce101242017-09-01 15:51:02 -04004867 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 -04004868 the string.
4869 Uses Text_Encoding to decode text, Typeface to get the glyph paths,
4870 and Text_Size, Fake_Bold, and Path_Effect to scale and modify the glyph paths.
4871 Uses xpos array, constY, and Text_Align to position intervals.
4872
4873 Pass nullptr for intervals to determine the size of the interval array.
4874
4875 intervals are cached to improve performance for multiple calls.
4876
4877 #Param text character codes or glyph indices ##
4878 #Param length number of bytes of text ##
4879 #Param xpos positions of each glyph in x ##
4880 #Param constY position of each glyph in y ##
4881 #Param bounds lower and upper line parallel to the advance ##
4882 #Param intervals returned intersections; may be nullptr ##
4883
4884 #Return number of intersections; may be zero ##
4885
4886 #Example
4887 #Height 128
4888 #Description
4889 Text intercepts do not take stroke thickness into consideration.
4890 ##
4891 void draw(SkCanvas* canvas) {
4892 SkPaint paint;
4893 paint.setTextSize(120);
4894 paint.setStyle(SkPaint::kStroke_Style);
4895 paint.setStrokeWidth(4);
4896 SkScalar textPosH[] = { 20, 80, 140 };
4897 SkScalar y = 100;
4898 SkScalar bounds[] = { 56, 78 };
4899 const char str[] = "\\-/";
4900 int len = sizeof(str) - 1;
4901 int count = paint.getPosTextHIntercepts(str, len, textPosH, y, bounds, nullptr);
4902 std::vector<SkScalar> intervals;
4903 intervals.resize(count);
4904 (void) paint.getPosTextHIntercepts(str, len, textPosH, y, bounds, &intervals.front());
4905 canvas->drawPosTextH(str, len, textPosH, y, paint);
4906 paint.setColor(0xFFFF7777);
4907 paint.setStyle(SkPaint::kFill_Style);
4908 SkScalar x = textPosH[0];
4909 for (int i = 0; i < count; i+= 2) {
4910 canvas->drawRect({x, bounds[0], intervals[i], bounds[1]}, paint);
4911 x = intervals[i + 1];
4912 }
4913 canvas->drawRect({intervals[count - 1], bounds[0], 180, bounds[1]}, paint);
4914 }
4915 ##
4916
4917##
4918
4919
4920#Method int getTextBlobIntercepts(const SkTextBlob* blob, const SkScalar bounds[2],
4921 SkScalar* intervals) const
4922
4923 Returns the number of intervals that intersect bounds.
4924 bounds describes a pair of lines parallel to the text advance.
Cary Clarkce101242017-09-01 15:51:02 -04004925 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 -04004926 the string.
Cary Clark3cd22cc2017-12-01 11:49:58 -05004927 Uses Typeface to get the glyph paths,
Cary Clark8032b982017-07-28 11:04:54 -04004928 and Text_Size, Fake_Bold, and Path_Effect to scale and modify the glyph paths.
Cary Clarkce101242017-09-01 15:51:02 -04004929 Uses run array and Text_Align to position intervals.
Cary Clark8032b982017-07-28 11:04:54 -04004930
Cary Clark3cd22cc2017-12-01 11:49:58 -05004931 Text_Encoding must be set to SkPaint::kGlyphID_TextEncoding.
4932
Cary Clark8032b982017-07-28 11:04:54 -04004933 Pass nullptr for intervals to determine the size of the interval array.
4934
4935 intervals are cached to improve performance for multiple calls.
4936
Cary Clarkce101242017-09-01 15:51:02 -04004937 #Param blob Glyphs, positions, and text paint attributes ##
Cary Clark8032b982017-07-28 11:04:54 -04004938 #Param bounds lower and upper line parallel to the advance ##
4939 #Param intervals returned intersections; may be nullptr ##
4940
4941 #Return number of intersections; may be zero ##
4942
4943 #Example
4944 #Height 143
4945 void draw(SkCanvas* canvas) {
4946 SkPaint paint;
Cary Clark3cd22cc2017-12-01 11:49:58 -05004947 paint.setTextEncoding(SkPaint::kGlyphID_TextEncoding);
Cary Clark8032b982017-07-28 11:04:54 -04004948 paint.setTextSize(120);
4949 SkPoint textPos = { 20, 110 };
4950 int len = 3;
4951 SkTextBlobBuilder textBlobBuilder;
4952 const SkTextBlobBuilder::RunBuffer& run =
4953 textBlobBuilder.allocRun(paint, len, textPos.fX, textPos.fY);
4954 run.glyphs[0] = 10;
4955 run.glyphs[1] = 20;
4956 run.glyphs[2] = 30;
4957 sk_sp<const SkTextBlob> blob = textBlobBuilder.make();
4958 canvas->drawTextBlob(blob.get(), textPos.fX, textPos.fY, paint);
4959 SkScalar bounds[] = { 116, 134 };
4960 int count = paint.getTextBlobIntercepts(blob.get(), bounds, nullptr);
4961 std::vector<SkScalar> intervals;
4962 intervals.resize(count);
4963 (void) paint.getTextBlobIntercepts(blob.get(), bounds, &intervals.front());
4964 canvas->drawTextBlob(blob.get(), 0, 0, paint);
4965 paint.setColor(0xFFFF7777);
4966 SkScalar x = textPos.fX;
4967 for (int i = 0; i < count; i+= 2) {
4968 canvas->drawRect({x, bounds[0], intervals[i], bounds[1]}, paint);
4969 x = intervals[i + 1];
4970 }
4971 canvas->drawRect({intervals[count - 1], bounds[0], 180, bounds[1]}, paint);
4972 }
4973 ##
4974
4975##
4976
4977#Topic ##
4978# ------------------------------------------------------------------------------
4979
4980#Method bool nothingToDraw() const
4981
Cary Clark579985c2017-07-31 11:48:27 -04004982 Returns true if Paint prevents all drawing;
4983 otherwise, the Paint may or may not allow drawing.
Cary Clark8032b982017-07-28 11:04:54 -04004984
Cary Clarkce101242017-09-01 15:51:02 -04004985 Returns true if, for example, Blend_Mode combined with Color_Alpha computes a
4986 new Alpha of zero.
Cary Clark8032b982017-07-28 11:04:54 -04004987
4988 #Return true if Paint prevents all drawing ##
4989
4990 #Example
4991 void draw(SkCanvas* canvas) {
4992 auto debugster = [](const char* prefix, const SkPaint& p) -> void {
4993 SkDebugf("%s nothing to draw: %s\n", prefix,
4994 p.nothingToDraw() ? "true" : "false");
4995 };
4996 SkPaint paint;
4997 debugster("initial", paint);
4998 paint.setBlendMode(SkBlendMode::kDst);
4999 debugster("blend dst", paint);
5000 paint.setBlendMode(SkBlendMode::kSrcOver);
5001 debugster("blend src over", paint);
5002 paint.setAlpha(0);
5003 debugster("alpha 0", paint);
5004 }
5005
5006 #StdOut
5007 initial nothing to draw: false
5008 blend dst nothing to draw: true
5009 blend src over nothing to draw: false
5010 alpha 0 nothing to draw: true
5011 #StdOut ##
5012 ##
5013
5014##
5015
5016# ------------------------------------------------------------------------------
5017#Topic Fast_Bounds
5018 #Private
5019 To be made private.
5020 ##
5021
5022Fast_Bounds methods conservatively outset a drawing bounds by additional area
5023Paint may draw to.
5024
5025#Method bool canComputeFastBounds() const
5026 #Private
5027 (to be made private)
5028 ##
5029
5030 Returns true if Paint does not include elements requiring extensive computation
5031 to compute Device bounds of drawn geometry. For instance, Paint with Path_Effect
5032 always returns false.
5033
5034 #Return true if Paint allows for fast computation of bounds ##
5035##
5036
5037#Method const SkRect& computeFastBounds(const SkRect& orig, SkRect* storage) const
5038 #Private
5039 (to be made private)
5040 ##
5041
5042 Only call this if canComputeFastBounds returned true. This takes a
5043 raw rectangle (the raw bounds of a shape), and adjusts it for stylistic
5044 effects in the paint (e.g. stroking). If needed, it uses the storage
Cary Clarkce101242017-09-01 15:51:02 -04005045 parameter. It returns the adjusted bounds that can then be used
Cary Clark8032b982017-07-28 11:04:54 -04005046 for SkCanvas::quickReject tests.
5047
Cary Clarkce101242017-09-01 15:51:02 -04005048 The returned Rect will either be orig or storage, thus the caller
Cary Clark8032b982017-07-28 11:04:54 -04005049 should not rely on storage being set to the result, but should always
Cary Clarkce101242017-09-01 15:51:02 -04005050 use the returned value. It is legal for orig and storage to be the same
5051 Rect.
Cary Clark8032b982017-07-28 11:04:54 -04005052
5053 #Private
5054 e.g.
5055 if (paint.canComputeFastBounds()) {
5056 SkRect r, storage;
5057 path.computeBounds(&r, SkPath::kFast_BoundsType);
5058 const SkRect& fastR = paint.computeFastBounds(r, &storage);
5059 if (canvas->quickReject(fastR, ...)) {
5060 // don't draw the path
5061 }
5062 }
5063 ##
5064
5065 #Param orig geometry modified by Paint when drawn ##
5066 #Param storage computed bounds of geometry; may not be nullptr ##
5067
5068 #Return fast computed bounds ##
5069##
5070
5071#Method const SkRect& computeFastStrokeBounds(const SkRect& orig,
5072 SkRect* storage) const
5073 #Private
5074 (to be made private)
5075 ##
5076
5077 #Param orig geometry modified by Paint when drawn ##
5078 #Param storage computed bounds of geometry ##
5079
5080 #Return fast computed bounds ##
5081##
5082
5083#Method const SkRect& doComputeFastBounds(const SkRect& orig, SkRect* storage,
5084 Style style) const
5085 #Private
5086 (to be made private)
5087 ##
5088
Cary Clarkce101242017-09-01 15:51:02 -04005089 Computes the bounds, overriding the Paint Style. This can be used to
5090 account for additional width required by stroking orig, without
5091 altering Style set to fill.
Cary Clark8032b982017-07-28 11:04:54 -04005092
5093 #Param orig geometry modified by Paint when drawn ##
5094 #Param storage computed bounds of geometry ##
5095 #Param style overrides Style ##
5096
5097 #Return fast computed bounds ##
5098##
5099
5100#Topic Fast_Bounds ##
5101
5102# ------------------------------------------------------------------------------
5103#Method void toString(SkString* str) const;
5104
5105#DefinedBy SK_TO_STRING_NONVIRT() ##
5106
5107#Private
5108macro expands to: void toString(SkString* str) const;
5109##
5110
Cary Clarkce101242017-09-01 15:51:02 -04005111Creates string representation of Paint. The representation is read by
5112internal debugging tools. The interface and implementation may be
5113suppressed by defining SK_IGNORE_TO_STRING.
Cary Clark8032b982017-07-28 11:04:54 -04005114
Cary Clarkce101242017-09-01 15:51:02 -04005115#Param str storage for string representation of Paint ##
Cary Clark8032b982017-07-28 11:04:54 -04005116
5117#Example
5118 SkPaint paint;
5119 SkString str;
5120 paint.toString(&str);
5121 const char textSize[] = "TextSize:";
5122 const int trailerSize = strlen("</dd><dt>");
5123 int textSizeLoc = str.find(textSize) + strlen(textSize) + trailerSize;
5124 const char* sizeStart = &str.c_str()[textSizeLoc];
5125 int textSizeEnd = SkStrFind(sizeStart, "</dd>");
5126 SkDebugf("text size = %.*s\n", textSizeEnd, sizeStart);
5127
5128 #StdOut
5129 text size = 12
5130 ##
5131
5132##
5133
Cary Clark2ade9972017-11-02 17:49:34 -04005134#SeeAlso SkPathEffect::toString SkMaskFilter::toString SkColorFilter::toString SkImageFilter::toString
Cary Clark8032b982017-07-28 11:04:54 -04005135
5136##
5137
5138# ------------------------------------------------------------------------------
5139
5140#Class SkPaint ##
5141
5142#Topic Paint ##