blob: 3369cd286136fbdeacca6d4cf10fa7f41d9e1ffb [file] [log] [blame]
Cary Clark8032b982017-07-28 11:04:54 -04001#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. ##
68# Rasterizer_Methods # Get and set Rasterizer. ##
69# Image_Filter_Methods # Get and set Image_Filter. ##
70# Draw_Looper_Methods # Get and set Draw_Looper. ##
71# Text_Align # Text placement relative to position. ##
72# Text_Size # Overall height in points. ##
73# Text_Scale_X # Text horizontal scale. ##
74# Text_Skew_X # Text horizontal slant. ##
Cary Clarkce101242017-09-01 15:51:02 -040075# Text_Encoding # Text encoded as characters or Glyphs. ##
Cary Clark8032b982017-07-28 11:04:54 -040076# Font_Metrics # Common glyph dimensions. ##
77# Measure_Text # Width, height, bounds of text. ##
Cary Clarkce101242017-09-01 15:51:02 -040078# Text_Path # Geometry of Glyphs. ##
Cary Clark8032b982017-07-28 11:04:54 -040079# Text_Intercepts # Advanced underline, strike through. ##
Cary Clarkce101242017-09-01 15:51:02 -040080# Fast_Bounds # Approximate area required by Paint. ##
Cary Clark8032b982017-07-28 11:04:54 -040081#Table ##
82#Subtopic ##
83
84#Subtopic Constants
85#Table
86#Legend
87# constants # description ##
88#Legend ##
89# Align # Glyph locations relative to text position. ##
90# Cap # Start and end geometry on stroked shapes. ##
91# Flags # Values described by bits and masks. ##
92# FontMetrics::FontMetricsFlags # Valid Font_Metrics. ##
93# Hinting # Level of glyph outline adjustment. ##
94# Join # Corner geometry on stroked shapes. ##
95# Style # Stroke, fill, or both. ##
Cary Clarkbc5697d2017-10-04 14:31:33 -040096# TextEncoding # Character or glyph encoded size. ##
Cary Clark8032b982017-07-28 11:04:54 -040097#Table ##
98#Subtopic ##
99
100#Subtopic Structs
101#Table
102#Legend
103# struct # description ##
104#Legend ##
105# FontMetrics # Typeface values. ##
106#Table ##
107#Subtopic ##
108
109#Subtopic Constructors
110#Table
111#Legend
112# # description ##
113#Legend ##
114# SkPaint() # Constructs with default values. ##
115# SkPaint(const SkPaint& paint) # Makes a shallow copy. ##
116# SkPaint(SkPaint&& paint) # Moves paint without copying it. ##
117# ~SkPaint() # Decreases Reference_Count of owned objects. ##
118#Table ##
119#Subtopic ##
120
121#Subtopic Operators
122#Table
123#Legend
124# operator # description ##
125#Legend ##
126# operator=(const SkPaint& paint) # Makes a shallow copy. ##
127# operator=(SkPaint&& paint) # Moves paint without copying it. ##
128# operator==(const SkPaint& a, const SkPaint& b) # Compares paints for equality. ##
129# operator!=(const SkPaint& a, const SkPaint& b) # Compares paints for inequality. ##
130#Table ##
131#Subtopic ##
132
133#Subtopic Member_Functions
134#Table
135#Legend
136# function # description ##
137#Legend ##
138# breakText # Returns text that fits in a width. ##
139# canComputeFastBounds # Returns true if settings allow for fast bounds computation. ##
140# computeFastBounds # Returns fill bounds for quick reject tests. ##
141# computeFastStrokeBounds # Returns stroke bounds for quick reject tests. ##
Cary Clarkce101242017-09-01 15:51:02 -0400142# containsText # Returns if all text corresponds to Glyphs. ##
143# countText # Returns number of Glyphs in text. ##
Cary Clark8032b982017-07-28 11:04:54 -0400144# doComputeFastBounds # Returns bounds for quick reject tests. ##
145# flatten() # Serializes into a buffer. ##
146# getAlpha # Returns Color_Alpha, color opacity. ##
Cary Clarkce101242017-09-01 15:51:02 -0400147# getBlendMode # Returns Blend_Mode, how colors combine with Device. ##
Cary Clark8032b982017-07-28 11:04:54 -0400148# getColor # Returns Color_Alpha and Color_RGB, one drawing color. ##
149# getColorFilter # Returns Color_Filter, how colors are altered. ##
150# getDrawLooper # Returns Draw_Looper, multiple layers. ##
151# getFillPath # Returns fill path equivalent to stroke. ##
152# getFilterQuality # Returns Filter_Quality, image filtering level. ##
153# getFlags # Returns Flags stored in a bit field. ##
154# getFontBounds # Returns union all glyph bounds. ##
155# getFontMetrics # Returns Typeface metrics scaled by text size. ##
156# getFontSpacing # Returns recommended spacing between lines. ##
157# getHash # Returns a shallow hash for equality checks. ##
158# getHinting # Returns Hinting, glyph outline adjustment level. ##
159# getImageFilter # Returns Image_Filter, alter pixels; blur. ##
160# getMaskFilter # Returns Mask_Filter, alterations to Mask_Alpha. ##
161# getPathEffect # Returns Path_Effect, modifications to path geometry; dashing. ##
162# getPosTextPath # Returns Path equivalent to positioned text. ##
163# getPosTextIntercepts # Returns where lines intersect positioned text; underlines. ##
164# getPosTextHIntercepts # Returns where lines intersect horizontally positioned text; underlines. ##
165# getRasterizer # Returns Rasterizer, Mask_Alpha generation from Path. ##
166# getShader # Returns Shader, multiple drawing colors; gradients. ##
167# getStrokeCap # Returns Cap, the area drawn at path ends. ##
168# getStrokeJoin # Returns Join, geometry on path corners. ##
169# getStrokeMiter # Returns Miter_Limit, angles with sharp corners. ##
170# getStrokeWidth # Returns thickness of the stroke. ##
171# getStyle # Returns Style: stroke, fill, or both. ##
172# getTextAlign # Returns Align: left, center, or right. ##
173# getTextBlobIntercepts # Returns where lines intersect Text_Blob; underlines. ##
Cary Clarkbc5697d2017-10-04 14:31:33 -0400174# getTextEncoding # Returns character or glyph encoded size. b ##
Cary Clark8032b982017-07-28 11:04:54 -0400175# getTextIntercepts # Returns where lines intersect text; underlines. ##
176# getTextPath # Returns Path equivalent to text. ##
177# getTextScaleX # Returns the text horizontal scale; condensed text. ##
178# getTextSkewX # Returns the text horizontal skew; oblique text. ##
179# getTextSize # Returns text size in points. ##
180# getTextWidths # Returns advance and bounds for each glyph in text. ##
181# getTypeface # Returns Typeface, font description. ##
Cary Clarkce101242017-09-01 15:51:02 -0400182# glyphsToUnichars # Converts Glyphs into text. ##
Cary Clark8032b982017-07-28 11:04:54 -0400183# isAntiAlias # Returns true if Anti-alias is set. ##
Cary Clarkce101242017-09-01 15:51:02 -0400184# isAutohinted # Returns true if Glyphs are always hinted. ##
Cary Clark8032b982017-07-28 11:04:54 -0400185# isDevKernText # Returns true if Full_Hinting_Spacing is set. ##
186# isDither # Returns true if Dither is set. ##
187# isEmbeddedBitmapText # Returns true if Font_Embedded_Bitmaps is set. ##
188# isFakeBoldText # Returns true if Fake_Bold is set. ##
189# isLCDRenderText # Returns true if LCD_Text is set. ##
190# isSrcOver # Returns true if Blend_Mode is SkBlendMode::kSrcOver. ##
191# isSubpixelText # Returns true if Subpixel_Text is set. ##
192# isVerticalText # Returns true if Vertical_Text is set. ##
193# measureText # Returns advance width and bounds of text. ##
194# nothingToDraw # Returns true if Paint prevents all drawing. ##
195# refColorFilter # References Color_Filter, how colors are altered. ##
196# refDrawLooper # References Draw_Looper, multiple layers. ##
197# refImageFilter # References Image_Filter, alter pixels; blur. ##
198# refMaskFilter # References Mask_Filter, alterations to Mask_Alpha. ##
199# refPathEffect # References Path_Effect, modifications to path geometry; dashing. ##
200# refRasterizer # References Rasterizer, mask generation from path. ##
201# refShader # References Shader, multiple drawing colors; gradients. ##
202# refTypeface # References Typeface, font description. ##
203# reset() # Sets to default values. ##
204# setAlpha # Sets Color_Alpha, color opacity. ##
205# setAntiAlias # Sets or clears Anti-alias. ##
206# setARGB # Sets color by component. ##
Cary Clarkce101242017-09-01 15:51:02 -0400207# setAutohinted # Sets Glyphs to always be hinted. ##
Cary Clark8032b982017-07-28 11:04:54 -0400208# setBlendMode # Sets Blend_Mode, how colors combine with destination. ##
209# setColor # Sets Color_Alpha and Color_RGB, one drawing color. ##
210# setColorFilter # Sets Color_Filter, alters color. ##
211# setDevKernText # Sets or clears Full_Hinting_Spacing. ##
212# setDither # Sets or clears Dither. ##
213# setDrawLooper # Sets Draw_Looper, multiple layers. ##
214# setEmbeddedBitmapText # Sets or clears Font_Embedded_Bitmaps. ##
215# setFakeBoldText # Sets or clears Fake_Bold. ##
216# setFilterQuality # Sets Filter_Quality, the image filtering level. ##
217# setFlags # Sets multiple Flags in a bit field. ##
218# setHinting # Sets Hinting, glyph outline adjustment level. ##
219# setLCDRenderText # Sets or clears LCD_Text. ##
220# setMaskFilter # Sets Mask_Filter, alterations to Mask_Alpha. ##
221# setPathEffect # Sets Path_Effect, modifications to path geometry; dashing. ##
222# setRasterizer # Sets Rasterizer, Mask_Alpha generation from Path. ##
223# setImageFilter # Sets Image_Filter, alter pixels; blur. ##
224# setShader # Sets Shader, multiple drawing colors; gradients. ##
225# setStrokeCap # Sets Cap, the area drawn at path ends. ##
226# setStrokeJoin # Sets Join, geometry on path corners. ##
227# setStrokeMiter # Sets Miter_Limit, angles with sharp corners. ##
228# setStrokeWidth # Sets thickness of the stroke. ##
229# setStyle # Sets Style: stroke, fill, or both. ##
230# setSubpixelText # Sets or clears Subpixel_Text. ##
231# setTextAlign # Sets Align: left, center, or right. ##
Cary Clarkbc5697d2017-10-04 14:31:33 -0400232# setTextEncoding # Sets character or glyph encoded size. ##
Cary Clark8032b982017-07-28 11:04:54 -0400233# setTextScaleX # Sets the text horizontal scale; condensed text. ##
234# setTextSkewX # Sets the text horizontal skew; oblique text. ##
235# setTextSize # Sets text size in points. ##
236# setTypeface # Sets Typeface, font description. ##
237# setVerticalText # Sets or clears Vertical_Text. ##
238# textToGlyphs # Converts text into glyph indices. ##
Cary Clarkce101242017-09-01 15:51:02 -0400239# toString # Converts Paint to machine readable form. ##
Cary Clark8032b982017-07-28 11:04:54 -0400240# unflatten() # Populates from a serialized stream. ##
241#Table ##
242#Subtopic ##
243
244#Topic Overview ##
245
246# ------------------------------------------------------------------------------
247#Topic Initializers
248
249#Method SkPaint()
250
251Constructs Paint with default values.
252
253#Table
254#Legend
255# attribute # default value ##
256#Legend ##
257# Anti-alias # false ##
Cary Clarkce101242017-09-01 15:51:02 -0400258# Blend_Mode # SkBlendMode::kSrcOver ##
Cary Clark8032b982017-07-28 11:04:54 -0400259# Color # SK_ColorBLACK ##
260# Color_Alpha # 255 ##
261# Color_Filter # nullptr ##
262# Dither # false ##
263# Draw_Looper # nullptr ##
264# Fake_Bold # false ##
265# Filter_Quality # kNone_SkFilterQuality ##
266# Font_Embedded_Bitmaps # false ##
267# Automatic_Hinting # false ##
268# Full_Hinting_Spacing # false ##
269# Hinting # kNormal_Hinting ##
270# Image_Filter # nullptr ##
271# LCD_Text # false ##
272# Linear_Text # false ##
273# Miter_Limit # 4 ##
274# Mask_Filter # nullptr ##
275# Path_Effect # nullptr ##
276# Rasterizer # nullptr ##
277# Shader # nullptr ##
278# Style # kFill_Style ##
279# Text_Align # kLeft_Align ##
280# Text_Encoding # kUTF8_TextEncoding ##
281# Text_Scale_X # 1 ##
282# Text_Size # 12 ##
283# Text_Skew_X # 0 ##
284# Typeface # nullptr ##
285# Stroke_Cap # kButt_Cap ##
286# Stroke_Join # kMiter_Join ##
287# Stroke_Width # 0 ##
288# Subpixel_Text # false ##
289# Vertical_Text # false ##
290#Table ##
291
292The flags, text size, hinting, and miter limit may be overridden at compile time by defining
Cary Clarkce101242017-09-01 15:51:02 -0400293paint default values. The overrides may be included in "SkUserConfig.h" or predefined by the
Cary Clark8032b982017-07-28 11:04:54 -0400294build system.
295
296#Return default initialized Paint ##
297
298#Example
299#ToDo mark this as no output ##
300#Height 1
301###$ $ redefine markup character so preprocessor commands appear normally
302#ifndef SkUserConfig_DEFINED
303#define SkUserConfig_DEFINED
304
305#define SkPaintDefaults_Flags 0x01 // always enable antialiasing
306#define SkPaintDefaults_TextSize 24.f // double default font size
307#define SkPaintDefaults_Hinting 3 // use full hinting
308#define SkPaintDefaults_MiterLimit 10.f // use HTML Canvas miter limit setting
309
310#endif
311$$$# # restore original markup character
312##
313
314
315##
316
317#Method SkPaint(const SkPaint& paint)
318
319Makes a shallow copy of Paint. Typeface, Path_Effect, Shader,
320Mask_Filter, Color_Filter, Rasterizer, Draw_Looper, and Image_Filter are shared
Cary Clarkbad5ad72017-08-03 17:14:08 -0400321between the original paint and the copy. Objects containing Reference_Count increment
322their references by one.
Cary Clark8032b982017-07-28 11:04:54 -0400323
324The referenced objects Path_Effect, Shader, Mask_Filter, Color_Filter, Rasterizer,
325Draw_Looper, and Image_Filter cannot be modified after they are created.
326This prevents objects with Reference_Count from being modified once Paint refers to them.
327
328#Param paint original to copy ##
329
330#Return shallow copy of paint ##
331
332#Example
333#ToDo why is this double-spaced on Fiddle? ##
334 SkPaint paint1;
335 paint1.setColor(SK_ColorRED);
336 SkPaint paint2(paint1);
337 paint2.setColor(SK_ColorBLUE);
338 SkDebugf("SK_ColorRED %c= paint1.getColor()\n", SK_ColorRED == paint1.getColor() ? '=' : '!');
339 SkDebugf("SK_ColorBLUE %c= paint2.getColor()\n", SK_ColorBLUE == paint2.getColor() ? '=' : '!');
340
341 #StdOut
342 SK_ColorRED == paint1.getColor()
343 SK_ColorBLUE == paint2.getColor()
344 ##
345##
346
347##
348
349#Method SkPaint(SkPaint&& paint)
350
Cary Clarkd0530ba2017-09-14 11:25:39 -0400351 Implements a move constructor to avoid increasing the reference counts
Cary Clark8032b982017-07-28 11:04:54 -0400352 of objects referenced by the paint.
353
354 After the call, paint is undefined, and can be safely destructed.
355
356 #Param paint original to move ##
357
358 #Return content of paint ##
359
360 #Example
361 SkPaint paint;
362 float intervals[] = { 5, 5 };
363 paint.setPathEffect(SkDashPathEffect::Make(intervals, SK_ARRAY_COUNT(intervals), 2.5f));
364 SkPaint dashed(std::move(paint));
365 SkDebugf("path effect unique: %s\n", dashed.getPathEffect()->unique() ? "true" : "false");
366
367 #StdOut
368 path effect unique: true
369 ##
370 ##
371
372##
373
374# ------------------------------------------------------------------------------
375
376#Method void reset()
377
Cary Clarkbc5697d2017-10-04 14:31:33 -0400378Sets all Paint contents to their initial values. This is equivalent to replacing
379Paint with the result of SkPaint().
Cary Clark8032b982017-07-28 11:04:54 -0400380
381#Example
382 SkPaint paint1, paint2;
383 paint1.setColor(SK_ColorRED);
384 paint1.reset();
385 SkDebugf("paint1 %c= paint2", paint1 == paint2 ? '=' : '!');
386
387 #StdOut
388 paint1 == paint2
389 ##
390##
391
392##
393
394#Topic ##
395
396# ------------------------------------------------------------------------------
397#Topic Destructor
398
399#Method ~SkPaint()
400
401Decreases Paint Reference_Count of owned objects: Typeface, Path_Effect, Shader,
402Mask_Filter, Color_Filter, Rasterizer, Draw_Looper, and Image_Filter. If the
Cary Clarkbad5ad72017-08-03 17:14:08 -0400403objects containing Reference_Count go to zero, they are deleted.
Cary Clark8032b982017-07-28 11:04:54 -0400404
405#NoExample
406##
407
408##
409
410##
411# ------------------------------------------------------------------------------
412#Topic Management
413
414#Method SkPaint& operator=(const SkPaint& paint)
415
416Makes a shallow copy of Paint. Typeface, Path_Effect, Shader,
417Mask_Filter, Color_Filter, Rasterizer, Draw_Looper, and Image_Filter are shared
Cary Clarkbad5ad72017-08-03 17:14:08 -0400418between the original paint and the copy. Objects containing Reference_Count in the
Cary Clark8032b982017-07-28 11:04:54 -0400419prior destination are decreased by one, and the referenced objects are deleted if the
Cary Clarkbad5ad72017-08-03 17:14:08 -0400420resulting count is zero. Objects containing Reference_Count in the parameter paint
421are increased by one. paint is unmodified.
Cary Clark8032b982017-07-28 11:04:54 -0400422
423#Param paint original to copy ##
424
425#Return content of paint ##
426
427#Example
428 SkPaint paint1, paint2;
429 paint1.setColor(SK_ColorRED);
430 paint2 = paint1;
431 SkDebugf("SK_ColorRED %c= paint1.getColor()\n", SK_ColorRED == paint1.getColor() ? '=' : '!');
432 SkDebugf("SK_ColorRED %c= paint2.getColor()\n", SK_ColorRED == paint2.getColor() ? '=' : '!');
433
434 #StdOut
435 SK_ColorRED == paint1.getColor()
436 SK_ColorRED == paint2.getColor()
437 ##
438##
439
440##
441
442# ------------------------------------------------------------------------------
443
444#Method SkPaint& operator=(SkPaint&& paint)
445
Cary Clarkd0530ba2017-09-14 11:25:39 -0400446Moves the paint to avoid increasing the reference counts
Cary Clarkbad5ad72017-08-03 17:14:08 -0400447of objects referenced by the paint parameter. Objects containing Reference_Count in the
448prior destination are decreased by one; those objects are deleted if the resulting count
449is zero.
Cary Clark8032b982017-07-28 11:04:54 -0400450
451After the call, paint is undefined, and can be safely destructed.
452
453 #Param paint original to move ##
454
455 #Return content of paint ##
456
457#Example
458 SkPaint paint1, paint2;
459 paint1.setColor(SK_ColorRED);
460 paint2 = std::move(paint1);
461 SkDebugf("SK_ColorRED == paint2.getColor()\n", SK_ColorRED == paint2.getColor() ? '=' : '!');
462
463 #StdOut
464 SK_ColorRED == paint2.getColor()
465 ##
466##
467
468##
469
470# ------------------------------------------------------------------------------
471
472#Method bool operator==(const SkPaint& a, const SkPaint& b)
473
474 Compares a and b, and returns true if a and b are equivalent. May return false
475 if Typeface, Path_Effect, Shader, Mask_Filter, Color_Filter, Rasterizer,
476 Draw_Looper, or Image_Filter have identical contents but different pointers.
477
478 #Param a Paint to compare ##
479 #Param b Paint to compare ##
480
481 #Return true if Paint pair are equivalent ##
482
483 #Example
484 SkPaint paint1, paint2;
485 paint1.setColor(SK_ColorRED);
486 paint2.setColor(0xFFFF0000);
487 SkDebugf("paint1 %c= paint2\n", paint1 == paint2 ? '=' : '!');
488 float intervals[] = { 5, 5 };
489 paint1.setPathEffect(SkDashPathEffect::Make(intervals, 2, 2.5f));
490 paint2.setPathEffect(SkDashPathEffect::Make(intervals, 2, 2.5f));
491 SkDebugf("paint1 %c= paint2\n", paint1 == paint2 ? '=' : '!');
492
493 #StdOut
494 paint1 == paint2
495 paint1 != paint2
496 ##
497 ##
498
499##
500
501# ------------------------------------------------------------------------------
502
503#Method bool operator!=(const SkPaint& a, const SkPaint& b)
504
505 Compares a and b, and returns true if a and b are not equivalent. May return true
506 if Typeface, Path_Effect, Shader, Mask_Filter, Color_Filter, Rasterizer,
507 Draw_Looper, or Image_Filter have identical contents but different pointers.
508
509 #Param a Paint to compare ##
510 #Param b Paint to compare ##
511
512 #Return true if Paint pair are not equivalent ##
513
514#Example
515 SkPaint paint1, paint2;
516 paint1.setColor(SK_ColorRED);
517 paint2.setColor(0xFFFF0000);
518 SkDebugf("paint1 %c= paint2\n", paint1 == paint2 ? '=' : '!');
519 SkDebugf("paint1 %c= paint2\n", paint1 != paint2 ? '!' : '=');
520
521 #StdOut
522 paint1 == paint2
523 paint1 == paint2
524 ##
525##
526
527##
528
529# ------------------------------------------------------------------------------
530
531#Method uint32_t getHash() const
532
533Returns a hash generated from Paint values and pointers.
534Identical hashes guarantee that the paints are
535equivalent, but differing hashes do not guarantee that the paints have differing
536contents.
537
538If operator==(const SkPaint& a, const SkPaint& b) returns true for two paints,
539their hashes are also equal.
540
541The hash returned is platform and implementation specific.
542
543#Return a shallow hash ##
544
545#Example
546 SkPaint paint1, paint2;
547 paint1.setColor(SK_ColorRED);
548 paint2.setColor(0xFFFF0000);
549 SkDebugf("paint1 %c= paint2\n", paint1 == paint2 ? '=' : '!');
550 SkDebugf("paint1.getHash() %c= paint2.getHash()\n",
551 paint1.getHash() == paint2.getHash() ? '=' : '!');
552
553 #StdOut
554 paint1 == paint2
555 paint1.getHash() == paint2.getHash()
556 ##
557##
558
559##
560
561# ------------------------------------------------------------------------------
562
563#Method void flatten(SkWriteBuffer& buffer) const
564
565Serializes Paint into a buffer. A companion unflatten() call
566can reconstitute the paint at a later time.
567
568#Param buffer Write_Buffer receiving the flattened Paint data ##
569
570#Example
571 class PaintDumper : public SkWriteBuffer {
572 public:
573 bool isCrossProcess() const override { return false; };
574 void writeByteArray(const void* data, size_t size) override {}
575 void writeBool(bool value) override {}
576 void writeScalar(SkScalar value) override {}
577 void writeScalarArray(const SkScalar* value, uint32_t count) override {}
578 void writeInt(int32_t value) override {}
579 void writeIntArray(const int32_t* value, uint32_t count) override {}
580 void writeUInt(uint32_t value) override {}
581 void writeString(const char* value) override {}
582 void writeFlattenable(const SkFlattenable* flattenable) override {}
583 void writeColorArray(const SkColor* color, uint32_t count) override {}
584 void writeColor4f(const SkColor4f& color) override {}
585 void writeColor4fArray(const SkColor4f* color, uint32_t count) override {}
586 void writePoint(const SkPoint& point) override {}
587 void writePointArray(const SkPoint* point, uint32_t count) override {}
588 void writeMatrix(const SkMatrix& matrix) override {}
589 void writeIRect(const SkIRect& rect) override {}
590 void writeRect(const SkRect& rect) override {}
591 void writeRegion(const SkRegion& region) override {}
592 void writePath(const SkPath& path) override {}
593 size_t writeStream(SkStream* stream, size_t length) override { return 0; }
594 void writeBitmap(const SkBitmap& bitmap) override {}
595 void writeImage(const SkImage*) override {}
596 void writeTypeface(SkTypeface* typeface) override {}
597 void writePaint(const SkPaint& paint) override {}
598
599 void writeColor(SkColor color) override {
600 SkDebugf("color = 0x%08x\n", color);
601 }
602 } dumper;
603
604 SkPaint paint;
605 paint.setColor(SK_ColorRED);
606 paint.flatten(dumper);
607
608 #StdOut
609 color = 0xffff0000
610 ##
611##
612
613##
614
615# ------------------------------------------------------------------------------
616
617#Method void unflatten(SkReadBuffer& buffer)
618
619Populates Paint, typically from a serialized stream, created by calling
620flatten() at an earlier time.
621
622SkReadBuffer class is not public, so unflatten() cannot be meaningfully called
623by the client.
624
Cary Clarkce101242017-09-01 15:51:02 -0400625#Param buffer serialized data describing Paint content ##
Cary Clark8032b982017-07-28 11:04:54 -0400626
627# why is unflatten() public?
628#Bug 6172 ##
629
630#NoExample
631##
632
633#ToDo incomplete ##
634
635##
636
637#Topic Management ##
638
639# ------------------------------------------------------------------------------
640#Topic Hinting
641
642#Enum Hinting
643
644#Code
645 enum Hinting {
646 kNo_Hinting = 0,
647 kSlight_Hinting = 1,
648 kNormal_Hinting = 2,
Cary Clarkbad5ad72017-08-03 17:14:08 -0400649 kFull_Hinting = 3,
Cary Clark8032b982017-07-28 11:04:54 -0400650 };
651##
652
653Hinting adjusts the glyph outlines so that the shape provides a uniform
654look at a given point size on font engines that support it. Hinting may have a
655muted effect or no effect at all depending on the platform.
656
657The four levels roughly control corresponding features on platforms that use FreeType
658as the Font_Engine.
659
660#Const kNo_Hinting 0
661 Leaves glyph outlines unchanged from their native representation.
662 With FreeType, this is equivalent to the FT_LOAD_NO_HINTING
663 bit-field constant supplied to FT_Load_Glyph, which indicates that the vector
664 outline being loaded should not be fitted to the pixel grid but simply scaled
665 to 26.6 fractional pixels.
666##
667#Const kSlight_Hinting 1
668 Modifies glyph outlines minimally to improve constrast.
669 With FreeType, this is equivalent in spirit to the
670 FT_LOAD_TARGET_LIGHT value supplied to FT_Load_Glyph. It chooses a
671 lighter hinting algorithm for non-monochrome modes.
Cary Clarkce101242017-09-01 15:51:02 -0400672 Generated Glyphs may be fuzzy but better resemble their original shape.
Cary Clark8032b982017-07-28 11:04:54 -0400673##
674#Const kNormal_Hinting 2
675 Modifies glyph outlines to improve constrast. This is the default.
Cary Clark6fc50412017-09-21 12:31:06 -0400676 With FreeType, this supplies FT_LOAD_TARGET_NORMAL to FT_Load_Glyph,
Cary Clark8032b982017-07-28 11:04:54 -0400677 choosing the default hinting algorithm, which is optimized for standard
678 gray-level rendering.
679##
680#Const kFull_Hinting 3
Cary Clark6fc50412017-09-21 12:31:06 -0400681 Modifies glyph outlines for maxiumum constrast. With FreeType, this selects
682 FT_LOAD_TARGET_LCD or FT_LOAD_TARGET_LCD_V if kLCDRenderText_Flag is set.
683 FT_LOAD_TARGET_LCD is a variant of FT_LOAD_TARGET_NORMAL optimized for
684 horizontally decimated LCD displays; FT_LOAD_TARGET_LCD_V is a
Cary Clark8032b982017-07-28 11:04:54 -0400685 variant of FT_LOAD_TARGET_NORMAL optimized for vertically decimated LCD displays.
686##
687
688#Track
689#File SkFontHost_mac.cpp:1777,1806
690#Time 2013-03-03 07:16:29 +0000
691#Bug 915 ##
692On OS_X and iOS, hinting controls whether Core_Graphics dilates the font outlines
693to account for LCD text. No hinting uses Core_Text gray scale output.
694Normal hinting uses Core_Text LCD output. If kLCDRenderText_Flag is clear,
695the LCD output is reduced to a single grayscale channel.
696#Track ##
697
698On Windows with DirectWrite, Hinting has no effect.
699
700Hinting defaults to kNormal_Hinting.
701Set SkPaintDefaults_Hinting at compile time to change the default setting.
702
703#ToDo add an illustration? linux running GM:typefacerendering is best for this
704 the hinting variations are every other character horizontally
705#ToDo ##
706
707#Enum ##
708
709#Method Hinting getHinting() const
710
711 Returns level of glyph outline adjustment.
712
713 #Return one of: kNo_Hinting, kSlight_Hinting, kNormal_Hinting, kFull_Hinting ##
714
715 #Example
716 SkPaint paint;
717 SkDebugf("SkPaint::kNormal_Hinting %c= paint.getHinting()\n",
718 SkPaint::kNormal_Hinting == paint.getHinting() ? '=' : ':');
719
720 #StdOut
721 SkPaint::kNormal_Hinting == paint.getHinting()
722 ##
723 ##
724##
725
726#Method void setHinting(Hinting hintingLevel)
727
728 Sets level of glyph outline adjustment.
729 Does not check for valid values of hintingLevel.
730
731 #Table
732 #Legend
733 # Hinting # value # effect on generated glyph outlines ##
734 ##
735 # kNo_Hinting # 0 # leaves glyph outlines unchanged from their native representation ##
Cary Clarkce101242017-09-01 15:51:02 -0400736 # kSlight_Hinting # 1 # modifies glyph outlines minimally to improve contrast ##
737 # kNormal_Hinting # 2 # modifies glyph outlines to improve contrast ##
738 # kFull_Hinting # 3 # modifies glyph outlines for maximum contrast ##
Cary Clark8032b982017-07-28 11:04:54 -0400739 ##
740
741 #Param hintingLevel one of: kNo_Hinting, kSlight_Hinting, kNormal_Hinting, kFull_Hinting ##
742
743 #Example
744 SkPaint paint1, paint2;
745 paint2.setHinting(SkPaint::kNormal_Hinting);
746 SkDebugf("paint1 %c= paint2\n", paint1 == paint2 ? '=' : ':');
747
748 #StdOut
749 paint1 == paint2
750 ##
751 ##
752##
753
754#Topic ##
755# ------------------------------------------------------------------------------
756#Topic Flags
757
758#Enum Flags
759
760#Code
761 enum Flags {
762 kAntiAlias_Flag = 0x01,
763 kDither_Flag = 0x04,
764 kFakeBoldText_Flag = 0x20,
765 kLinearText_Flag = 0x40,
766 kSubpixelText_Flag = 0x80,
767 kDevKernText_Flag = 0x100,
768 kLCDRenderText_Flag = 0x200,
769 kEmbeddedBitmapText_Flag = 0x400,
770 kAutoHinting_Flag = 0x800,
771 kVerticalText_Flag = 0x1000,
772 kGenA8FromLCD_Flag = 0x2000,
773
774 kAllFlags = 0xFFFF,
775 };
776
777##
778
779The bit values stored in Flags.
780The default value for Flags, normally zero, can be changed at compile time
781with a custom definition of SkPaintDefaults_Flags.
782All flags can be read and written explicitly; Flags allows manipulating
783multiple settings at once.
784
785 #Const kAntiAlias_Flag 0x0001
786 mask for setting Anti-alias
787 ##
788 #Const kDither_Flag 0x0004
789 mask for setting Dither
790 ##
791
792 #Const kFakeBoldText_Flag 0x0020
793 mask for setting Fake_Bold
794 ##
795 #Const kLinearText_Flag 0x0040
796 mask for setting Linear_Text
797 ##
798 #Const kSubpixelText_Flag 0x0080
799 mask for setting Subpixel_Text
800 ##
801 #Const kDevKernText_Flag 0x0100
802 mask for setting Full_Hinting_Spacing
803 ##
804 #Const kLCDRenderText_Flag 0x0200
805 mask for setting LCD_Text
806 ##
807 #Const kEmbeddedBitmapText_Flag 0x0400
808 mask for setting Font_Embedded_Bitmaps
809 ##
810 #Const kAutoHinting_Flag 0x0800
811 mask for setting Automatic_Hinting
812 ##
813 #Const kVerticalText_Flag 0x1000
814 mask for setting Vertical_Text
815 ##
816 #Const kGenA8FromLCD_Flag 0x2000
817 #Private
818 Hack for GDI -- do not use if you can help it
819 ##
820 not intended for public use
821 ##
822 #Const kAllFlags 0xFFFF
823 mask of all Flags, including private flags and flags reserved for future use
824 ##
825
826Flags default to all flags clear, disabling the associated feature.
827
828#Enum ##
829
830#Enum ReserveFlags
831
832#Private
833To be deprecated; only valid for Android framework.
834##
835
836#Code
837 enum ReserveFlags {
838 kUnderlineText_ReserveFlag = 0x08,
839 kStrikeThruText_ReserveFlag = 0x10,
840 };
841##
842
843 #Const kUnderlineText_ReserveFlag 0x0008
844 mask for underline text
845 ##
846 #Const kStrikeThruText_ReserveFlag 0x0010
847 mask for strike-thru text
848 ##
849
850#ToDo incomplete ##
851
852#Enum ##
853
854#Method uint32_t getFlags() const
855
856Returns paint settings described by Flags. Each setting uses one
857bit, and can be tested with Flags members.
858
859#Return zero, one, or more bits described by Flags ##
860
861#Example
862 SkPaint paint;
863 paint.setAntiAlias(true);
864 SkDebugf("(SkPaint::kAntiAlias_Flag & paint.getFlags()) %c= 0\n",
865 SkPaint::kAntiAlias_Flag & paint.getFlags() ? '!' : '=');
866
867 #StdOut
868 (SkPaint::kAntiAlias_Flag & paint.getFlags()) != 0
869 ##
870##
871
872##
873
874#Method void setFlags(uint32_t flags)
875
876Replaces Flags with flags, the union of the Flags members.
877All Flags members may be cleared, or one or more may be set.
878
879#Param flags union of Flags for Paint ##
880
881#Example
882 SkPaint paint;
883 paint.setFlags((uint32_t) (SkPaint::kAntiAlias_Flag | SkPaint::kDither_Flag));
884 SkDebugf("paint.isAntiAlias()\n", paint.isAntiAlias() ? '!' : '=');
885 SkDebugf("paint.isDither()\n", paint.isDither() ? '!' : '=');
886
887 #StdOut
888 paint.isAntiAlias()
889 paint.isDither()
890 ##
891##
892
893##
894
895#Topic ##
896# ------------------------------------------------------------------------------
897#Topic Anti-alias
898#Alias Anti-alias # permit hyphen in topic name, should probably not substitute hyphen with _
899
900Anti-alias drawing approximates partial pixel coverage with transparency.
901If kAntiAlias_Flag is clear, pixel centers contained by the shape edge are drawn opaque.
902If kAntiAlias_Flag is set, pixels are drawn with Color_Alpha equal to their coverage.
903
Cary Clarkce101242017-09-01 15:51:02 -0400904The rule for Aliased pixels is inconsistent across platforms. A shape edge
Cary Clark8032b982017-07-28 11:04:54 -0400905passing through the pixel center may, but is not required to, draw the pixel.
906
Cary Clarkce101242017-09-01 15:51:02 -0400907Raster_Engine draws Aliased pixels whose centers are on or to the right of the start of an
Cary Clark8032b982017-07-28 11:04:54 -0400908active Path edge, and whose center is to the left of the end of the active Path edge.
909
910#ToDo add illustration of raster pixels ##
911
Cary Clarkce101242017-09-01 15:51:02 -0400912A platform may only support Anti-aliased drawing. Some GPU-backed platforms use
913Supersampling to Anti-alias all drawing, and have no mechanism to selectively
914Alias.
Cary Clark8032b982017-07-28 11:04:54 -0400915
Cary Clarkce101242017-09-01 15:51:02 -0400916The amount of coverage computed for Anti-aliased pixels also varies across platforms.
Cary Clark8032b982017-07-28 11:04:54 -0400917
918Anti-alias is disabled by default.
919Anti-alias can be enabled by default by setting SkPaintDefaults_Flags to kAntiAlias_Flag
920at compile time.
921
922 #Example
923 #Width 512
924 #Description
925 A red line is drawn with transparency on the edges to make it look smoother.
926 A blue line draws only where the pixel centers are contained.
Cary Clarkce101242017-09-01 15:51:02 -0400927 The lines are drawn into Bitmap, then drawn magnified to make the
928 Aliasing easier to see.
Cary Clark8032b982017-07-28 11:04:54 -0400929 ##
930
931 void draw(SkCanvas* canvas) {
932 SkBitmap bitmap;
933 bitmap.allocN32Pixels(50, 50);
934 SkCanvas offscreen(bitmap);
935 SkPaint paint;
936 paint.setStyle(SkPaint::kStroke_Style);
937 paint.setStrokeWidth(10);
938 for (bool antialias : { false, true }) {
939 paint.setColor(antialias ? SK_ColorRED : SK_ColorBLUE);
940 paint.setAntiAlias(antialias);
941 bitmap.eraseColor(0);
942 offscreen.drawLine(5, 5, 15, 30, paint);
943 canvas->drawLine(5, 5, 15, 30, paint);
944 canvas->save();
945 canvas->scale(10, 10);
946 canvas->drawBitmap(bitmap, antialias ? 12 : 0, 0);
947 canvas->restore();
948 canvas->translate(15, 0);
949 }
950 }
951 ##
952
953#Method bool isAntiAlias() const
954
955 If true, pixels on the active edges of Path may be drawn with partial transparency.
956
957 Equivalent to getFlags masked with kAntiAlias_Flag.
958
959 #Return kAntiAlias_Flag state ##
960
961 #Example
962 SkPaint paint;
963 SkDebugf("paint.isAntiAlias() %c= !!(paint.getFlags() & SkPaint::kAntiAlias_Flag)\n",
964 paint.isAntiAlias() == !!(paint.getFlags() & SkPaint::kAntiAlias_Flag) ? '=' : '!');
965 paint.setAntiAlias(true);
966 SkDebugf("paint.isAntiAlias() %c= !!(paint.getFlags() & SkPaint::kAntiAlias_Flag)\n",
967 paint.isAntiAlias() == !!(paint.getFlags() & SkPaint::kAntiAlias_Flag) ? '=' : '!');
968
969 #StdOut
970 paint.isAntiAlias() == !!(paint.getFlags() & SkPaint::kAntiAlias_Flag)
971 paint.isAntiAlias() == !!(paint.getFlags() & SkPaint::kAntiAlias_Flag)
972 ##
973 ##
974##
975
976#Method void setAntiAlias(bool aa)
977
978 Requests, but does not require, that Path edge pixels draw opaque or with
979 partial transparency.
980
981 Sets kAntiAlias_Flag if aa is true.
982 Clears kAntiAlias_Flag if aa is false.
983
984 #Param aa setting for kAntiAlias_Flag ##
985
986 #Example
987 SkPaint paint1, paint2;
988 paint1.setAntiAlias(true);
989 paint2.setFlags(paint2.getFlags() | SkPaint::kAntiAlias_Flag);
990 SkDebugf("paint1 %c= paint2\n", paint1 == paint2 ? '=' : '!');
991
992 #StdOut
993 paint1 == paint2
994 ##
995 ##
996
997##
998
999#Topic ##
1000# ------------------------------------------------------------------------------
1001#Topic Dither
1002
Cary Clarkce101242017-09-01 15:51:02 -04001003Dither increases fidelity by adjusting the color of adjacent pixels.
Cary Clark8032b982017-07-28 11:04:54 -04001004This can help to smooth color transitions and reducing banding in gradients.
1005Dithering lessens visible banding from kRGB_565_SkColorType
1006and kRGBA_8888_SkColorType gradients,
1007and improves rendering into a kRGB_565_SkColorType Surface.
1008
1009Dithering is always enabled for linear gradients drawing into
1010kRGB_565_SkColorType Surface and kRGBA_8888_SkColorType Surface.
1011Dither cannot be enabled for kAlpha_8_SkColorType Surface and
1012kRGBA_F16_SkColorType Surface.
1013
1014Dither is disabled by default.
1015Dither can be enabled by default by setting SkPaintDefaults_Flags to kDither_Flag
1016at compile time.
1017
1018Some platform implementations may ignore dithering. Set
1019
1020#Define SK_IGNORE_GPU_DITHER
1021
1022to ignore Dither on GPU_Surface.
1023
1024#Example
1025#Description
1026Dithering in the bottom half more closely approximates the requested color by
1027alternating nearby colors from pixel to pixel.
1028##
1029void draw(SkCanvas* canvas) {
1030 SkBitmap bm16;
1031 bm16.allocPixels(SkImageInfo::Make(32, 32, kRGB_565_SkColorType, kOpaque_SkAlphaType));
1032 SkCanvas c16(bm16);
1033 SkPaint colorPaint;
1034 for (auto dither : { false, true } ) {
1035 colorPaint.setDither(dither);
1036 for (auto colors : { 0xFF333333, 0xFF666666, 0xFF999999, 0xFFCCCCCC } ) {
1037 for (auto mask : { 0xFFFF0000, 0xFF00FF00, 0xFF0000FF, 0xFFFFFFFF } ) {
1038 colorPaint.setColor(colors & mask);
1039 c16.drawRect({0, 0, 8, 4}, colorPaint);
1040 c16.translate(8, 0);
1041 }
1042 c16.translate(-32, 4);
1043 }
1044 }
1045 canvas->scale(8, 8);
1046 canvas->drawBitmap(bm16, 0, 0);
1047}
1048##
1049
1050#Example
1051#Description
1052Dithering introduces subtle adjustments to color to smooth gradients.
1053Drawing the gradient repeatedly with SkBlendMode::kPlus exaggerates the
1054dither, making it easier to see.
1055##
1056void draw(SkCanvas* canvas) {
1057 canvas->clear(0);
1058 SkBitmap bm32;
1059 bm32.allocPixels(SkImageInfo::Make(20, 10, kN32_SkColorType, kPremul_SkAlphaType));
1060 SkCanvas c32(bm32);
1061 SkPoint points[] = {{0, 0}, {20, 0}};
1062 SkColor colors[] = {0xFF334455, 0xFF662211 };
1063 SkPaint paint;
1064 paint.setShader(SkGradientShader::MakeLinear(
1065 points, colors, nullptr, SK_ARRAY_COUNT(colors),
1066 SkShader::kClamp_TileMode, 0, nullptr));
1067 paint.setDither(true);
1068 c32.drawPaint(paint);
1069 canvas->scale(12, 12);
1070 canvas->drawBitmap(bm32, 0, 0);
1071 paint.setBlendMode(SkBlendMode::kPlus);
1072 canvas->drawBitmap(bm32, 0, 11, &paint);
1073 canvas->drawBitmap(bm32, 0, 11, &paint);
1074 canvas->drawBitmap(bm32, 0, 11, &paint);
1075}
1076##
1077
1078#Method bool isDither() const
1079
1080 If true, color error may be distributed to smooth color transition.
1081
1082 Equivalent to getFlags masked with kDither_Flag.
1083
1084 #Return kDither_Flag state ##
1085
1086 #Example
1087 SkPaint paint;
1088 SkDebugf("paint.isDither() %c= !!(paint.getFlags() & SkPaint::kDither_Flag)\n",
1089 paint.isDither() == !!(paint.getFlags() & SkPaint::kDither_Flag) ? '=' : '!');
1090 paint.setDither(true);
1091 SkDebugf("paint.isDither() %c= !!(paint.getFlags() & SkPaint::kDither_Flag)\n",
1092 paint.isDither() == !!(paint.getFlags() & SkPaint::kDither_Flag) ? '=' : '!');
1093
1094 #StdOut
1095 paint.isDither() == !!(paint.getFlags() & SkPaint::kDither_Flag)
1096 paint.isDither() == !!(paint.getFlags() & SkPaint::kDither_Flag)
1097 ##
1098 ##
1099
1100##
1101
1102#Method void setDither(bool dither)
1103
1104 Requests, but does not require, to distribute color error.
1105
1106 Sets kDither_Flag if dither is true.
1107 Clears kDither_Flag if dither is false.
1108
1109 #Param dither setting for kDither_Flag ##
1110
1111 #Example
1112 SkPaint paint1, paint2;
1113 paint1.setDither(true);
1114 paint2.setFlags(paint2.getFlags() | SkPaint::kDither_Flag);
1115 SkDebugf("paint1 %c= paint2\n", paint1 == paint2 ? '=' : '!');
1116
1117 #StdOut
1118 paint1 == paint2
1119 ##
1120 ##
1121
1122 #SeeAlso kRGB_565_SkColorType
1123
1124##
1125
1126#SeeAlso Gradient Color_RGB-565
1127
1128#Topic ##
1129# ------------------------------------------------------------------------------
1130#Topic Device_Text
1131
1132LCD_Text and Subpixel_Text increase the precision of glyph position.
1133
1134When set, Flags kLCDRenderText_Flag takes advantage of the organization of Color_RGB stripes that
1135create a color, and relies
Cary Clarkce101242017-09-01 15:51:02 -04001136on the small size of the stripe and visual perception to make the color fringing imperceptible.
Cary Clark8032b982017-07-28 11:04:54 -04001137LCD_Text can be enabled on devices that orient stripes horizontally or vertically, and that order
1138the color components as Color_RGB or Color_RBG.
1139
1140Flags kSubpixelText_Flag uses the pixel transparency to represent a fractional offset.
1141As the opaqueness
1142of the color increases, the edge of the glyph appears to move towards the outside of the pixel.
1143
1144Either or both techniques can be enabled.
1145kLCDRenderText_Flag and kSubpixelText_Flag are clear by default.
1146LCD_Text or Subpixel_Text can be enabled by default by setting SkPaintDefaults_Flags to
1147kLCDRenderText_Flag or kSubpixelText_Flag (or both) at compile time.
1148
1149#Example
1150 #Description
1151 Four commas are drawn normally and with combinations of LCD_Text and Subpixel_Text.
Cary Clarkce101242017-09-01 15:51:02 -04001152 When Subpixel_Text is disabled, the comma Glyphs are identical, but not evenly spaced.
1153 When Subpixel_Text is enabled, the comma Glyphs are unique, but appear evenly spaced.
Cary Clark8032b982017-07-28 11:04:54 -04001154 ##
1155
1156 SkBitmap bitmap;
1157 bitmap.allocN32Pixels(24, 33);
1158 SkCanvas offscreen(bitmap);
1159 offscreen.clear(SK_ColorWHITE);
1160 SkPaint paint;
1161 paint.setAntiAlias(true);
1162 paint.setTextSize(20);
1163 for (bool lcd : { false, true }) {
1164 paint.setLCDRenderText(lcd);
1165 for (bool subpixel : { false, true }) {
1166 paint.setSubpixelText(subpixel);
1167 offscreen.drawString(",,,,", 0, 4, paint);
1168 offscreen.translate(0, 7);
1169 }
1170 }
1171 canvas->drawBitmap(bitmap, 4, 12);
1172 canvas->scale(9, 9);
1173 canvas->drawBitmap(bitmap, 4, -1);
1174##
1175
1176#Subtopic Linear_Text
1177#Alias Linear_Text # makes this a top level name, since it is under subtopic Device_Text
1178
1179Linear_Text selects whether text is rendered as a Glyph or as a Path.
1180If kLinearText_Flag is set, it has the same effect as setting Hinting to kNormal_Hinting.
Cary Clarkd0530ba2017-09-14 11:25:39 -04001181If kLinearText_Flag is clear, it is the same as setting Hinting to kNo_Hinting.
Cary Clark8032b982017-07-28 11:04:54 -04001182
1183#Method bool isLinearText() const
1184
1185 If true, text is converted to Path before drawing and measuring.
1186
1187 Equivalent to getFlags masked with kLinearText_Flag.
1188
1189 #Return kLinearText_Flag state ##
1190
1191 #Example
1192 #Height 128
1193 void draw(SkCanvas* canvas) {
1194 SkPaint paint;
1195 paint.setAntiAlias(true);
1196 const char testStr[] = "xxxx xxxx";
1197 for (auto linearText : { false, true } ) {
1198 paint.setLinearText(linearText);
1199 paint.setTextSize(24);
1200 canvas->drawString(paint.isLinearText() ? "linear" : "hinted", 128, 30, paint);
1201 for (SkScalar textSize = 8; textSize < 30; textSize *= 1.22f) {
1202 paint.setTextSize(textSize);
1203 canvas->translate(0, textSize);
1204 canvas->drawString(testStr, 10, 0, paint);
1205 }
1206 }
1207 }
1208 ##
1209
1210 #SeeAlso setLinearText Hinting
1211##
1212
1213#Method void setLinearText(bool linearText)
1214
1215 If true, text is converted to Path before drawing and measuring.
1216 By default, kLinearText_Flag is clear.
1217
1218 Sets kLinearText_Flag if linearText is true.
1219 Clears kLinearText_Flag if linearText is false.
1220
1221 #Param linearText setting for kLinearText_Flag ##
1222
1223 #Example
1224 #Height 128
1225 void draw(SkCanvas* canvas) {
1226 SkPaint paint;
1227 paint.setAntiAlias(true);
1228 const char testStr[] = "abcd efgh";
1229 for (int textSize : { 12, 24 } ) {
1230 paint.setTextSize(textSize);
1231 for (auto linearText : { false, true } ) {
1232 paint.setLinearText(linearText);
1233 SkString width;
1234 width.appendScalar(paint.measureText(testStr, SK_ARRAY_COUNT(testStr), nullptr));
1235 canvas->translate(0, textSize + 4);
1236 canvas->drawString(testStr, 10, 0, paint);
1237 canvas->drawString(width, 128, 0, paint);
1238 }
1239 }
1240 }
1241 ##
1242
1243 #SeeAlso isLinearText Hinting
1244##
1245
1246#Subtopic ##
1247
1248#Subtopic Subpixel_Text
1249#Alias Subpixel_Text # makes this a top level name, since it is under subtopic Device_Text
1250
1251Flags kSubpixelText_Flag uses the pixel transparency to represent a fractional offset.
1252As the opaqueness
1253of the color increases, the edge of the glyph appears to move towards the outside of the pixel.
1254
1255#Method bool isSubpixelText() const
1256
Cary Clarkce101242017-09-01 15:51:02 -04001257 If true, Glyphs at different sub-pixel positions may differ on pixel edge coverage.
Cary Clark8032b982017-07-28 11:04:54 -04001258
1259 Equivalent to getFlags masked with kSubpixelText_Flag.
1260
1261 #Return kSubpixelText_Flag state ##
1262
1263 #Example
1264SkPaint paint;
1265SkDebugf("paint.isSubpixelText() %c= !!(paint.getFlags() & SkPaint::kSubpixelText_Flag)\n",
1266 paint.isSubpixelText() == !!(paint.getFlags() & SkPaint::kSubpixelText_Flag) ? '=' : '!');
1267paint.setSubpixelText(true);
1268SkDebugf("paint.isSubpixelText() %c= !!(paint.getFlags() & SkPaint::kSubpixelText_Flag)\n",
1269 paint.isSubpixelText() == !!(paint.getFlags() & SkPaint::kSubpixelText_Flag) ? '=' : '!');
1270
1271 #StdOut
1272 paint.isSubpixelText() == !!(paint.getFlags() & SkPaint::kSubpixelText_Flag)
1273 paint.isSubpixelText() == !!(paint.getFlags() & SkPaint::kSubpixelText_Flag)
1274 ##
1275 ##
1276
1277##
1278
1279#Method void setSubpixelText(bool subpixelText)
1280
Cary Clarkce101242017-09-01 15:51:02 -04001281 Requests, but does not require, that Glyphs respect sub-pixel positioning.
Cary Clark8032b982017-07-28 11:04:54 -04001282
1283 Sets kSubpixelText_Flag if subpixelText is true.
1284 Clears kSubpixelText_Flag if subpixelText is false.
1285
1286 #Param subpixelText setting for kSubpixelText_Flag ##
1287
1288 #Example
1289 SkPaint paint1, paint2;
1290 paint1.setSubpixelText(true);
1291 paint2.setFlags(paint2.getFlags() | SkPaint::kSubpixelText_Flag);
1292 SkDebugf("paint1 %c= paint2\n", paint1 == paint2 ? '=' : '!');
1293
1294 #StdOut
1295 paint1 == paint2
1296 ##
1297 ##
1298
1299##
1300
1301#Subtopic ##
1302
1303#Subtopic LCD_Text
1304#Alias LCD_Text # makes this a top level name, since it is under subtopic Device_Text
1305
1306When set, Flags kLCDRenderText_Flag takes advantage of the organization of Color_RGB stripes that
1307create a color, and relies
Cary Clarkce101242017-09-01 15:51:02 -04001308on the small size of the stripe and visual perception to make the color fringing imperceptible.
Cary Clark8032b982017-07-28 11:04:54 -04001309LCD_Text can be enabled on devices that orient stripes horizontally or vertically, and that order
1310the color components as Color_RGB or Color_RBG.
1311
1312#Method bool isLCDRenderText() const
1313
Cary Clarkce101242017-09-01 15:51:02 -04001314 If true, Glyphs may use LCD striping to improve glyph edges.
Cary Clark8032b982017-07-28 11:04:54 -04001315
1316 Returns true if Flags kLCDRenderText_Flag is set.
1317
1318 #Return kLCDRenderText_Flag state ##
1319
1320 #Example
1321SkPaint paint;
1322SkDebugf("paint.isLCDRenderText() %c= !!(paint.getFlags() & SkPaint::kLCDRenderText_Flag)\n",
1323 paint.isLCDRenderText() == !!(paint.getFlags() & SkPaint::kLCDRenderText_Flag) ? '=' : '!');
1324paint.setLCDRenderText(true);
1325SkDebugf("paint.isLCDRenderText() %c= !!(paint.getFlags() & SkPaint::kLCDRenderText_Flag)\n",
1326 paint.isLCDRenderText() == !!(paint.getFlags() & SkPaint::kLCDRenderText_Flag) ? '=' : '!');
1327
1328 #StdOut
1329 paint.isLCDRenderText() == !!(paint.getFlags() & SkPaint::kLCDRenderText_Flag)
1330 paint.isLCDRenderText() == !!(paint.getFlags() & SkPaint::kLCDRenderText_Flag)
1331 ##
1332 ##
1333
1334##
1335
1336#Method void setLCDRenderText(bool lcdText)
1337
Cary Clarkce101242017-09-01 15:51:02 -04001338 Requests, but does not require, that Glyphs use LCD striping for glyph edges.
Cary Clark8032b982017-07-28 11:04:54 -04001339
1340 Sets kLCDRenderText_Flag if lcdText is true.
1341 Clears kLCDRenderText_Flag if lcdText is false.
1342
1343 #Param lcdText setting for kLCDRenderText_Flag ##
1344
1345 #Example
1346 SkPaint paint1, paint2;
1347 paint1.setLCDRenderText(true);
1348 paint2.setFlags(paint2.getFlags() | SkPaint::kLCDRenderText_Flag);
1349 SkDebugf("paint1 %c= paint2\n", paint1 == paint2 ? '=' : '!');
1350
1351 #StdOut
1352 paint1 == paint2
1353 ##
1354 ##
1355
1356
1357##
1358
1359#Subtopic ##
1360
1361#Topic ##
1362# ------------------------------------------------------------------------------
1363#Topic Font_Embedded_Bitmaps
1364#Alias Font_Embedded_Bitmaps # long-winded enough, alias so I don't type Paint_Font_...
1365
Cary Clarkce101242017-09-01 15:51:02 -04001366Font_Embedded_Bitmaps allows selecting custom sized bitmap Glyphs.
Cary Clark8032b982017-07-28 11:04:54 -04001367Flags kEmbeddedBitmapText_Flag when set chooses an embedded bitmap glyph over an outline contained
1368in a font if the platform supports this option.
1369
1370FreeType selects the bitmap glyph if available when kEmbeddedBitmapText_Flag is set, and selects
1371the outline glyph if kEmbeddedBitmapText_Flag is clear.
1372Windows may select the bitmap glyph but is not required to do so.
1373OS_X and iOS do not support this option.
1374
1375Font_Embedded_Bitmaps is disabled by default.
1376Font_Embedded_Bitmaps can be enabled by default by setting SkPaintDefaults_Flags to
1377kEmbeddedBitmapText_Flag at compile time.
1378
1379#Example
1380 #ToDo image will only output on Ubuntu ... how to handle that in fiddle? ##
1381 #Platform !fiddle
1382 #Description
Cary Clarkce101242017-09-01 15:51:02 -04001383 The "hintgasp" TrueType font in the Skia resources/fonts directory
1384 includes an embedded bitmap Glyph at odd font sizes. This example works
1385 on platforms that use FreeType as their Font_Engine.
1386 Windows may, but is not required to, return a bitmap glyph if
1387 kEmbeddedBitmapText_Flag is set.
Cary Clark8032b982017-07-28 11:04:54 -04001388 ##
1389 #Image embeddedbitmap.png
1390
1391 SkBitmap bitmap;
1392 bitmap.allocN32Pixels(30, 15);
1393 bitmap.eraseColor(0);
1394 SkCanvas offscreen(bitmap);
1395 SkPaint paint;
1396 paint.setAntiAlias(true);
1397 paint.setTextSize(13);
1398 paint.setTypeface(MakeResourceAsTypeface("/fonts/hintgasp.ttf"));
1399 for (bool embedded : { false, true}) {
1400 paint.setEmbeddedBitmapText(embedded);
1401 offscreen.drawString("A", embedded ? 5 : 15, 15, paint);
1402 }
1403 canvas->drawBitmap(bitmap, 0, 0);
1404 canvas->scale(10, 10);
1405 canvas->drawBitmap(bitmap, -2, 1);
1406##
1407
1408#Method bool isEmbeddedBitmapText() const
1409
Cary Clarkce101242017-09-01 15:51:02 -04001410 If true, Font_Engine may return Glyphs from font bitmaps instead of from outlines.
Cary Clark8032b982017-07-28 11:04:54 -04001411
1412 Equivalent to getFlags masked with kEmbeddedBitmapText_Flag.
1413
1414 #Return kEmbeddedBitmapText_Flag state ##
1415
1416 #Example
1417 SkPaint paint;
1418 SkDebugf("paint.isEmbeddedBitmapText() %c="
1419 " !!(paint.getFlags() & SkPaint::kEmbeddedBitmapText_Flag)\n",
1420 paint.isEmbeddedBitmapText() ==
1421 !!(paint.getFlags() & SkPaint::kEmbeddedBitmapText_Flag) ? '=' : '!');
1422 paint.setEmbeddedBitmapText(true);
1423 SkDebugf("paint.isEmbeddedBitmapText() %c="
1424 " !!(paint.getFlags() & SkPaint::kEmbeddedBitmapText_Flag)\n",
1425 paint.isEmbeddedBitmapText() ==
1426 !!(paint.getFlags() & SkPaint::kEmbeddedBitmapText_Flag) ? '=' : '!');
1427
1428 #StdOut
1429 paint.isEmbeddedBitmapText() == !!(paint.getFlags() & SkPaint::kEmbeddedBitmapText_Flag)
1430 paint.isEmbeddedBitmapText() == !!(paint.getFlags() & SkPaint::kEmbeddedBitmapText_Flag)
1431 ##
1432 ##
1433
1434##
1435
1436#Method void setEmbeddedBitmapText(bool useEmbeddedBitmapText)
1437
1438 Requests, but does not require, to use bitmaps in fonts instead of outlines.
1439
1440 Sets kEmbeddedBitmapText_Flag if useEmbeddedBitmapText is true.
1441 Clears kEmbeddedBitmapText_Flag if useEmbeddedBitmapText is false.
1442
1443 #Param useEmbeddedBitmapText setting for kEmbeddedBitmapText_Flag ##
1444
1445 #Example
1446 SkPaint paint1, paint2;
1447 paint1.setEmbeddedBitmapText(true);
1448 paint2.setFlags(paint2.getFlags() | SkPaint::kEmbeddedBitmapText_Flag);
1449 SkDebugf("paint1 %c= paint2\n", paint1 == paint2 ? '=' : '!');
1450
1451 #StdOut
1452 paint1 == paint2
1453 ##
1454 ##
1455
1456##
1457
1458#Topic ##
1459# ------------------------------------------------------------------------------
1460#Topic Automatic_Hinting
1461#Substitute auto-hinting
1462
1463If Hinting is set to kNormal_Hinting or kFull_Hinting, Automatic_Hinting
Cary Clarkce101242017-09-01 15:51:02 -04001464instructs the Font_Manager to always hint Glyphs.
Cary Clark8032b982017-07-28 11:04:54 -04001465Automatic_Hinting has no effect if Hinting is set to kNo_Hinting or
1466kSlight_Hinting.
1467
1468Automatic_Hinting only affects platforms that use FreeType as the Font_Manager.
1469
1470#Method bool isAutohinted() const
1471
1472 If true, and if Hinting is set to kNormal_Hinting or kFull_Hinting, and if
1473 platform uses FreeType as the Font_Manager, instruct the Font_Manager to always hint
Cary Clarkce101242017-09-01 15:51:02 -04001474 Glyphs.
Cary Clark8032b982017-07-28 11:04:54 -04001475
1476 Equivalent to getFlags masked with kAutoHinting_Flag.
1477
1478 #Return kAutoHinting_Flag state ##
1479
1480 #Example
1481 SkPaint paint;
1482 for (auto forceAutoHinting : { false, true} ) {
1483 paint.setAutohinted(forceAutoHinting);
1484 SkDebugf("paint.isAutohinted() %c="
1485 " !!(paint.getFlags() & SkPaint::kAutoHinting_Flag)\n",
1486 paint.isAutohinted() ==
1487 !!(paint.getFlags() & SkPaint::kAutoHinting_Flag) ? '=' : '!');
1488 }
1489 #StdOut
1490 paint.isAutohinted() == !!(paint.getFlags() & SkPaint::kAutoHinting_Flag)
1491 paint.isAutohinted() == !!(paint.getFlags() & SkPaint::kAutoHinting_Flag)
1492 ##
1493 ##
1494
1495 #SeeAlso setAutohinted Hinting
1496
1497##
1498
1499#Method void setAutohinted(bool useAutohinter)
1500
1501 If Hinting is set to kNormal_Hinting or kFull_Hinting and useAutohinter is set,
Cary Clarkce101242017-09-01 15:51:02 -04001502 instruct the Font_Manager to always hint Glyphs.
Cary Clark8032b982017-07-28 11:04:54 -04001503 Automatic_Hinting has no effect if Hinting is set to kNo_Hinting or
1504 kSlight_Hinting.
1505
Cary Clark579985c2017-07-31 11:48:27 -04001506 Only affects platforms that use FreeType as the Font_Manager.
Cary Clark8032b982017-07-28 11:04:54 -04001507
1508 Sets kAutoHinting_Flag if useAutohinter is true.
1509 Clears kAutoHinting_Flag if useAutohinter is false.
1510
1511 #Param useAutohinter setting for kAutoHinting_Flag ##
1512
1513 #Example
1514 void draw(SkCanvas* canvas) {
1515 SkPaint paint;
1516 paint.setAntiAlias(true);
1517 const char testStr[] = "xxxx xxxx";
1518 for (auto forceAutoHinting : { false, true} ) {
1519 paint.setAutohinted(forceAutoHinting);
1520 paint.setTextSize(24);
1521 canvas->drawString(paint.isAutohinted() ? "auto-hinted" : "default", 108, 30, paint);
1522 for (SkScalar textSize = 8; textSize < 30; textSize *= 1.22f) {
1523 paint.setTextSize(textSize);
1524 canvas->translate(0, textSize);
1525 canvas->drawString(testStr, 10, 0, paint);
1526 }
1527 }
1528 }
1529 ##
1530
1531 #SeeAlso isAutohinted Hinting
1532
1533##
1534
1535#Topic ##
1536# ------------------------------------------------------------------------------
1537#Topic Vertical_Text
1538
1539Text may be drawn by positioning each glyph, or by positioning the first glyph and
Cary Clarkce101242017-09-01 15:51:02 -04001540using Font_Advance to position subsequent Glyphs. By default, each successive glyph
1541is positioned to the right of the preceding glyph. Vertical_Text sets successive
1542Glyphs to position below the preceding glyph.
Cary Clark8032b982017-07-28 11:04:54 -04001543
Cary Clarkce101242017-09-01 15:51:02 -04001544Skia can translate text character codes as a series of Glyphs, but does not implement
Cary Clark8032b982017-07-28 11:04:54 -04001545font substitution,
Cary Clarkce101242017-09-01 15:51:02 -04001546textual substitution, line layout, or contextual spacing like Kerning pairs. Use
Cary Clark6fc50412017-09-21 12:31:06 -04001547a text shaping engine like
1548#A HarfBuzz # http://harfbuzz.org/ ##
1549 to translate text runs
Cary Clark8032b982017-07-28 11:04:54 -04001550into glyph series.
1551
1552Vertical_Text is clear if text is drawn left to right or set if drawn from top to bottom.
1553
1554Flags kVerticalText_Flag if clear draws text left to right.
1555Flags kVerticalText_Flag if set draws text top to bottom.
1556
1557Vertical_Text is clear by default.
1558Vertical_Text can be set by default by setting SkPaintDefaults_Flags to
1559kVerticalText_Flag at compile time.
1560
1561#Example
1562
1563void draw(SkCanvas* canvas) {
1564 SkPaint paint;
1565 paint.setAntiAlias(true);
1566 paint.setTextSize(50);
1567 for (bool vertical : { false, true } ) {
1568 paint.setVerticalText(vertical);
1569 canvas->drawString("aAlL", 25, 50, paint);
1570 }
1571}
1572
1573##
1574
1575#Method bool isVerticalText() const
1576
Cary Clarkce101242017-09-01 15:51:02 -04001577 If true, Glyphs are drawn top to bottom instead of left to right.
Cary Clark8032b982017-07-28 11:04:54 -04001578
1579 Equivalent to getFlags masked with kVerticalText_Flag.
1580
1581 #Return kVerticalText_Flag state ##
1582
1583 #Example
1584 SkPaint paint;
1585 SkDebugf("paint.isVerticalText() %c= !!(paint.getFlags() & SkPaint::kVerticalText_Flag)\n",
1586 paint.isVerticalText() == !!(paint.getFlags() & SkPaint::kVerticalText_Flag) ? '=' : '!');
1587 paint.setVerticalText(true);
1588 SkDebugf("paint.isVerticalText() %c= !!(paint.getFlags() & SkPaint::kVerticalText_Flag)\n",
1589 paint.isVerticalText() == !!(paint.getFlags() & SkPaint::kVerticalText_Flag) ? '=' : '!');
1590
1591 #StdOut
1592 paint.isVerticalText() == !!(paint.getFlags() & SkPaint::kVerticalText_Flag)
1593 paint.isVerticalText() == !!(paint.getFlags() & SkPaint::kVerticalText_Flag)
1594 ##
1595 ##
1596
1597##
1598
1599#Method void setVerticalText(bool verticalText)
1600
1601 If true, text advance positions the next glyph below the previous glyph instead of to the
1602 right of previous glyph.
1603
1604 Sets kVerticalText_Flag if vertical is true.
1605 Clears kVerticalText_Flag if vertical is false.
1606
1607 #Param verticalText setting for kVerticalText_Flag ##
1608
1609 #Example
1610 SkPaint paint1, paint2;
1611 paint1.setVerticalText(true);
1612 paint2.setFlags(paint2.getFlags() | SkPaint::kVerticalText_Flag);
1613 SkDebugf("paint1 %c= paint2\n", paint1 == paint2 ? '=' : '!');
1614
1615 #StdOut
1616 paint1 == paint2
1617 ##
1618 ##
1619
1620##
1621
1622#Topic ##
1623# ------------------------------------------------------------------------------
1624
1625#Topic Fake_Bold
1626
1627Fake_Bold approximates the bold font style accompanying a normal font when a bold font face
1628is not available. Skia does not provide font substitution; it is up to the client to find the
Cary Clarkbc5697d2017-10-04 14:31:33 -04001629bold font face using the platform Font_Manager.
Cary Clark8032b982017-07-28 11:04:54 -04001630
1631Use Text_Skew_X to approximate an italic font style when the italic font face
1632is not available.
1633
Cary Clarkce101242017-09-01 15:51:02 -04001634A FreeType based port may define SK_USE_FREETYPE_EMBOLDEN at compile time to direct
1635the font engine to create the bold Glyphs. Otherwise, the extra bold is computed
Cary Clark8032b982017-07-28 11:04:54 -04001636by increasing the stroke width and setting the Style to kStrokeAndFill_Style as needed.
1637
1638Fake_Bold is disabled by default.
1639
1640#Example
1641#Height 128
1642void draw(SkCanvas* canvas) {
1643 SkPaint paint;
1644 paint.setAntiAlias(true);
1645 paint.setTextSize(40);
1646 canvas->drawString("OjYy_-", 10, 35, paint);
1647 paint.setFakeBoldText(true);
1648 canvas->drawString("OjYy_-", 10, 75, paint);
1649 // create a custom fake bold by varying the stroke width
1650 paint.setFakeBoldText(false);
1651 paint.setStyle(SkPaint::kStrokeAndFill_Style);
1652 paint.setStrokeWidth(40.f / 48);
1653 canvas->drawString("OjYy_-", 10, 115, paint);
1654}
1655##
1656
1657#Method bool isFakeBoldText() const
1658
1659 If true, approximate bold by increasing the stroke width when creating glyph bitmaps
1660 from outlines.
1661
1662 Equivalent to getFlags masked with kFakeBoldText_Flag.
1663
1664 #Return kFakeBoldText_Flag state ##
1665
1666 #Example
1667 SkPaint paint;
1668 SkDebugf("paint.isFakeBoldText() %c= !!(paint.getFlags() & SkPaint::kFakeBoldText_Flag)\n",
1669 paint.isFakeBoldText() == !!(paint.getFlags() & SkPaint::kFakeBoldText_Flag) ? '=' : '!');
1670 paint.setFakeBoldText(true);
1671 SkDebugf("paint.isFakeBoldText() %c= !!(paint.getFlags() & SkPaint::kFakeBoldText_Flag)\n",
1672 paint.isFakeBoldText() == !!(paint.getFlags() & SkPaint::kFakeBoldText_Flag) ? '=' : '!');
1673
1674 #StdOut
1675 paint.isFakeBoldText() == !!(paint.getFlags() & SkPaint::kFakeBoldText_Flag)
1676 paint.isFakeBoldText() == !!(paint.getFlags() & SkPaint::kFakeBoldText_Flag)
1677 ##
1678 ##
1679
1680##
1681
1682#Method void setFakeBoldText(bool fakeBoldText)
1683
Cary Clarkce101242017-09-01 15:51:02 -04001684 Use increased stroke width when creating glyph bitmaps to approximate a bold typeface.
Cary Clark8032b982017-07-28 11:04:54 -04001685
1686 Sets kFakeBoldText_Flag if fakeBoldText is true.
1687 Clears kFakeBoldText_Flag if fakeBoldText is false.
1688
1689 #Param fakeBoldText setting for kFakeBoldText_Flag ##
1690
1691 #Example
1692 SkPaint paint1, paint2;
1693 paint1.setFakeBoldText(true);
1694 paint2.setFlags(paint2.getFlags() | SkPaint::kFakeBoldText_Flag);
1695 SkDebugf("paint1 %c= paint2\n", paint1 == paint2 ? '=' : '!');
1696
1697 #StdOut
1698 paint1 == paint2
1699 ##
1700 ##
1701
1702##
1703
1704#Topic ##
1705
1706# ------------------------------------------------------------------------------
1707#Topic Full_Hinting_Spacing
1708#Alias Full_Hinting_Spacing # long winded enough -- maybe things with two underscores auto-aliased?
1709
Cary Clarkce101242017-09-01 15:51:02 -04001710if Hinting is set to kFull_Hinting, Full_Hinting_Spacing adjusts the character
1711spacing by the difference of the hinted and Unhinted Left_Side_Bearing and
1712Right_Side_Bearing. Full_Hinting_Spacing only applies to platforms that use
1713FreeType as their Font_Engine.
Cary Clark8032b982017-07-28 11:04:54 -04001714
Cary Clarkce101242017-09-01 15:51:02 -04001715Full_Hinting_Spacing is not related to text Kerning, where the space between
Cary Clarkbc5697d2017-10-04 14:31:33 -04001716a specific pair of characters is adjusted using data in the font Kerning tables.
Cary Clark8032b982017-07-28 11:04:54 -04001717
1718#Method bool isDevKernText() const
1719
1720 Returns if character spacing may be adjusted by the hinting difference.
1721
1722 Equivalent to getFlags masked with kDevKernText_Flag.
1723
1724 #Return kDevKernText_Flag state ##
1725
1726 #Example
1727 SkPaint paint;
1728 SkDebugf("paint.isDevKernText() %c= !!(paint.getFlags() & SkPaint::kDevKernText_Flag)\n",
1729 paint.isDevKernText() == !!(paint.getFlags() & SkPaint::kDevKernText_Flag) ? '=' : '!');
1730 paint.setDevKernText(true);
1731 SkDebugf("paint.isDevKernText() %c= !!(paint.getFlags() & SkPaint::kDevKernText_Flag)\n",
1732 paint.isDevKernText() == !!(paint.getFlags() & SkPaint::kDevKernText_Flag) ? '=' : '!');
1733 ##
1734
1735##
1736
1737#Method void setDevKernText(bool devKernText)
1738
1739 Requests, but does not require, to use hinting to adjust glyph spacing.
1740
1741 Sets kDevKernText_Flag if devKernText is true.
1742 Clears kDevKernText_Flag if devKernText is false.
1743
1744 #Param devKernText setting for devKernText ##
1745
1746 #Example
1747 SkPaint paint1, paint2;
1748 paint1.setDevKernText(true);
1749 paint2.setFlags(paint2.getFlags() | SkPaint::kDevKernText_Flag);
1750 SkDebugf("paint1 %c= paint2\n", paint1 == paint2 ? '=' : '!');
1751
1752 #StdOut
1753 paint1 == paint2
1754 ##
1755 ##
1756
1757##
1758
1759#Topic ##
1760# ------------------------------------------------------------------------------
1761#Topic Filter_Quality_Methods
1762
1763Filter_Quality trades speed for image filtering when the image is scaled.
1764A lower Filter_Quality draws faster, but has less fidelity.
1765A higher Filter_Quality draws slower, but looks better.
Cary Clarkce101242017-09-01 15:51:02 -04001766If the image is drawn without scaling, the Filter_Quality choice will not result
1767in a noticeable difference.
Cary Clark8032b982017-07-28 11:04:54 -04001768
1769Filter_Quality is used in Paint passed as a parameter to
1770#List
1771# SkCanvas::drawBitmap ##
1772# SkCanvas::drawBitmapRect ##
1773# SkCanvas::drawImage ##
1774# SkCanvas::drawImageRect ##
1775 #ToDo probably more... ##
1776#List ##
1777and when Paint has a Shader specialization that uses Image or Bitmap.
1778
1779Filter_Quality is kNone_SkFilterQuality by default.
1780
1781#Example
1782#Image 3
1783void draw(SkCanvas* canvas) {
1784 SkPaint paint;
1785 canvas->scale(.2f, .2f);
1786 for (SkFilterQuality q : { kNone_SkFilterQuality, kLow_SkFilterQuality,
1787 kMedium_SkFilterQuality, kHigh_SkFilterQuality } ) {
1788 paint.setFilterQuality(q);
1789 canvas->drawImage(image.get(), 0, 0, &paint);
1790 canvas->translate(550, 0);
1791 if (kLow_SkFilterQuality == q) canvas->translate(-1100, 550);
1792 }
1793}
1794##
1795
1796#Method SkFilterQuality getFilterQuality() const
1797
1798Returns Filter_Quality, the image filtering level. A lower setting
1799draws faster; a higher setting looks better when the image is scaled.
1800
1801#Return one of: kNone_SkFilterQuality, kLow_SkFilterQuality,
1802 kMedium_SkFilterQuality, kHigh_SkFilterQuality
1803#Return ##
1804
1805#Example
1806 SkPaint paint;
1807 SkDebugf("kNone_SkFilterQuality %c= paint.getFilterQuality()\n",
1808 kNone_SkFilterQuality == paint.getFilterQuality() ? '=' : '!');
1809
1810 #StdOut
1811 kNone_SkFilterQuality == paint.getFilterQuality()
1812 ##
1813##
1814
1815##
1816
1817
1818#Method void setFilterQuality(SkFilterQuality quality)
1819
1820Sets Filter_Quality, the image filtering level. A lower setting
1821draws faster; a higher setting looks better when the image is scaled.
Cary Clark579985c2017-07-31 11:48:27 -04001822Does not check to see if quality is valid.
Cary Clark8032b982017-07-28 11:04:54 -04001823
1824#Param quality one of: kNone_SkFilterQuality, kLow_SkFilterQuality,
1825 kMedium_SkFilterQuality, kHigh_SkFilterQuality
1826##
1827
1828#Example
1829 SkPaint paint;
1830 paint.setFilterQuality(kHigh_SkFilterQuality);
1831 SkDebugf("kHigh_SkFilterQuality %c= paint.getFilterQuality()\n",
1832 kHigh_SkFilterQuality == paint.getFilterQuality() ? '=' : '!');
1833
1834 #StdOut
1835 kHigh_SkFilterQuality == paint.getFilterQuality()
1836 ##
1837##
1838
1839#SeeAlso SkFilterQuality Image_Scaling
1840
1841##
1842
1843#Topic ##
1844# ------------------------------------------------------------------------------
1845#Topic Color_Methods
1846
1847Color specifies the Color_RGB_Red, Color_RGB_Blue, Color_RGB_Green, and Color_Alpha values used to draw a filled
1848or stroked shape in a
184932-bit value. Each component occupies 8-bits, ranging from zero: no contribution;
1850to 255: full intensity. All values in any combination are valid.
1851
Cary Clarkce101242017-09-01 15:51:02 -04001852Color is not Premultiplied;
Cary Clark8032b982017-07-28 11:04:54 -04001853Color_Alpha sets the transparency independent of Color_RGB: Color_RGB_Red, Color_RGB_Blue, and Color_RGB_Green.
1854
1855The bit positions of Color_Alpha and Color_RGB are independent of the bit positions
1856on the output device, which may have more or fewer bits, and may have a different arrangement.
1857
1858#Table
1859#Legend
1860# bit positions # Color_Alpha # Color_RGB_Red # Color_RGB_Blue # Color_RGB_Green ##
1861#Legend ##
1862# # 31 - 24 # 23 - 16 # 15 - 8 # 7 - 0 ##
1863#Table ##
1864
1865#Example
1866#Height 128
1867 void draw(SkCanvas* canvas) {
1868 SkPaint paint;
1869 paint.setColor(0x8000FF00); // transparent green
1870 canvas->drawCircle(50, 50, 40, paint);
1871 paint.setARGB(128, 255, 0, 0); // transparent red
1872 canvas->drawCircle(80, 50, 40, paint);
1873 paint.setColor(SK_ColorBLUE);
1874 paint.setAlpha(0x80);
1875 canvas->drawCircle(65, 65, 40, paint);
1876 }
1877##
1878
1879#Method SkColor getColor() const
1880
Cary Clarkce101242017-09-01 15:51:02 -04001881 Retrieves Alpha and Color_RGB, Unpremultiplied, packed into 32 bits.
Cary Clark8032b982017-07-28 11:04:54 -04001882 Use helpers SkColorGetA, SkColorGetR, SkColorGetG, and SkColorGetB to extract
1883 a color component.
1884
1885 #Return Unpremultiplied Color_ARGB ##
1886
1887 #Example
1888 SkPaint paint;
1889 paint.setColor(SK_ColorYELLOW);
1890 SkColor y = paint.getColor();
1891 SkDebugf("Yellow is %d%% red, %d%% green, and %d%% blue.\n", (int) (SkColorGetR(y) / 2.55f),
1892 (int) (SkColorGetG(y) / 2.55f), (int) (SkColorGetB(y) / 2.55f));
1893
1894 #StdOut
1895 Yellow is 100% red, 100% green, and 0% blue.
1896 ##
1897 ##
1898
1899 #SeeAlso SkColor
1900
1901##
1902
1903#Method void setColor(SkColor color)
1904
Cary Clarkce101242017-09-01 15:51:02 -04001905 Sets Alpha and Color_RGB used when stroking and filling. The color is a 32-bit value,
1906 Unpremultiplied, packing 8-bit components for Alpha, Red, Blue, and Green.
Cary Clark8032b982017-07-28 11:04:54 -04001907
1908 #Param color Unpremultiplied Color_ARGB ##
1909
1910 #Example
1911 SkPaint green1, green2;
1912 unsigned a = 255;
1913 unsigned r = 0;
1914 unsigned g = 255;
1915 unsigned b = 0;
1916 green1.setColor((a << 24) + (r << 16) + (g << 8) + (b << 0));
1917 green2.setColor(0xFF00FF00);
1918 SkDebugf("green1 %c= green2\n", green1 == green2 ? '=' : '!');
1919
1920 #StdOut
1921 green1 == green2
1922 ##
1923 ##
1924
1925 #SeeAlso SkColor setARGB SkColorSetARGB
1926
1927##
1928
1929#Subtopic Alpha_Methods
1930
1931Color_Alpha sets the transparency independent of Color_RGB: Color_RGB_Red, Color_RGB_Blue, and Color_RGB_Green.
1932
1933#Method uint8_t getAlpha() const
1934
Cary Clarkce101242017-09-01 15:51:02 -04001935 Retrieves Alpha from the Color used when stroking and filling.
Cary Clark8032b982017-07-28 11:04:54 -04001936
Cary Clarkce101242017-09-01 15:51:02 -04001937 #Return Alpha ranging from zero, fully transparent, to 255, fully opaque ##
Cary Clark8032b982017-07-28 11:04:54 -04001938
1939 #Example
1940 SkPaint paint;
1941 SkDebugf("255 %c= paint.getAlpha()\n", 255 == paint.getAlpha() ? '=' : '!');
1942
1943 #StdOut
1944 255 == paint.getAlpha()
1945 ##
1946 ##
1947
1948##
1949
1950#Method void setAlpha(U8CPU a)
1951
Cary Clarkce101242017-09-01 15:51:02 -04001952 Replaces Alpha, leaving Color_RGB
Cary Clark8032b982017-07-28 11:04:54 -04001953 unchanged. An out of range value triggers an assert in the debug
1954 build. a is a value from zero to 255.
1955 a set to zero makes Color fully transparent; a set to 255 makes Color
1956 fully opaque.
1957
Cary Clarkce101242017-09-01 15:51:02 -04001958 #Param a Alpha component of Color ##
Cary Clark8032b982017-07-28 11:04:54 -04001959
1960 #Example
1961 SkPaint paint;
1962 paint.setColor(0x00112233);
1963 paint.setAlpha(0x44);
1964 SkDebugf("0x44112233 %c= paint.getColor()\n", 0x44112233 == paint.getColor() ? '=' : '!');
1965
1966 #StdOut
1967 0x44112233 == paint.getColor()
1968 ##
1969 ##
1970
1971##
1972
1973#Subtopic ##
1974
1975#Method void setARGB(U8CPU a, U8CPU r, U8CPU g, U8CPU b)
1976
1977 Sets Color used when drawing solid fills. The color components range from 0 to 255.
Cary Clarkce101242017-09-01 15:51:02 -04001978 The color is Unpremultiplied; Alpha sets the transparency independent of Color_RGB.
Cary Clark8032b982017-07-28 11:04:54 -04001979
1980 #Param a amount of Color_Alpha, from fully transparent (0) to fully opaque (255) ##
1981 #Param r amount of Color_RGB_Red, from no red (0) to full red (255) ##
1982 #Param g amount of Color_RGB_Green, from no green (0) to full green (255) ##
1983 #Param b amount of Color_RGB_Blue, from no blue (0) to full blue (255) ##
1984
1985 #Example
1986 SkPaint transRed1, transRed2;
1987 transRed1.setARGB(255 / 2, 255, 0, 0);
1988 transRed2.setColor(SkColorSetARGB(255 / 2, 255, 0, 0));
1989 SkDebugf("transRed1 %c= transRed2", transRed1 == transRed2 ? '=' : '!');
1990
1991 #StdOut
1992 transRed1 == transRed2
1993 ##
1994 ##
1995
1996 #SeeAlso setColor SkColorSetARGB
1997
1998##
1999
2000#Topic Color_Methods ##
2001
2002# ------------------------------------------------------------------------------
2003#Topic Style
2004
2005Style specifies if the geometry is filled, stroked, or both filled and stroked.
2006Some shapes ignore Style and are always drawn filled or stroked.
2007
2008Set Style to kFill_Style to fill the shape.
2009The fill covers the area inside the geometry for most shapes.
2010
2011Set Style to kStroke_Style to stroke the shape.
2012
2013# ------------------------------------------------------------------------------
2014#Subtopic Fill
2015
2016#ToDo write up whatever generalities make sense to describe filling ##
2017
2018#SeeAlso Path_Fill_Type
2019#Subtopic ##
2020
2021#Subtopic Stroke
Cary Clarkbc5697d2017-10-04 14:31:33 -04002022The stroke covers the area described by following the shape edge with a pen or brush of
Cary Clark8032b982017-07-28 11:04:54 -04002023Stroke_Width. The area covered where the shape starts and stops is described by Stroke_Cap.
2024The area covered where the shape turns a corner is described by Stroke_Join.
Cary Clarkbc5697d2017-10-04 14:31:33 -04002025The stroke is centered on the shape; it extends equally on either side of the shape edge.
Cary Clark8032b982017-07-28 11:04:54 -04002026
2027As Stroke_Width gets smaller, the drawn path frame is thinner. Stroke_Width less than one
2028may have gaps, and if kAntiAlias_Flag is set, Color_Alpha will increase to visually decrease coverage.
2029#Subtopic ##
2030
2031#Subtopic Hairline
2032#Alias Hairline # maybe should be Stroke_Hairline ?
2033
2034Stroke_Width of zero has a special meaning and switches drawing to use Hairline.
2035Hairline draws the thinnest continuous frame. If kAntiAlias_Flag is clear, adjacent pixels
2036flow horizontally, vertically,or diagonally.
2037
Cary Clarkce101242017-09-01 15:51:02 -04002038#ToDo what is the description of Anti-aliased hairlines? ##
Cary Clark8032b982017-07-28 11:04:54 -04002039
2040Path drawing with Hairline may hit the same pixel more than once. For instance, Path containing
2041two lines in one Path_Contour will draw the corner point once, but may both lines may draw the adjacent
2042pixel. If kAntiAlias_Flag is set, transparency is applied twice, resulting in a darker pixel. Some
2043GPU-backed implementations apply transparency at a later drawing stage, avoiding double hit pixels
2044while stroking.
2045
2046#Subtopic ##
2047
2048#Enum Style
2049
2050#Code
2051 enum Style {
2052 kFill_Style,
2053 kStroke_Style,
2054 kStrokeAndFill_Style,
2055 };
2056##
2057
2058Set Style to fill, stroke, or both fill and stroke geometry.
2059The stroke and fill
2060share all paint attributes; for instance, they are drawn with the same color.
2061
2062Use kStrokeAndFill_Style to avoid hitting the same pixels twice with a stroke draw and
2063a fill draw.
2064
2065#Const kFill_Style 0
2066 Set to fill geometry.
Cary Clarkce101242017-09-01 15:51:02 -04002067 Applies to Rect, Region, Round_Rect, Circles, Ovals, Path, and Text.
2068 Bitmap, Image, Patches, Region, Sprites, and Vertices are painted as if
Cary Clark8032b982017-07-28 11:04:54 -04002069 kFill_Style is set, and ignore the set Style.
2070 The Path_Fill_Type specifies additional rules to fill the area outside the path edge,
2071 and to create an unfilled hole inside the shape.
2072 Style is set to kFill_Style by default.
2073##
2074
2075#Const kStroke_Style 1
2076 Set to stroke geometry.
Cary Clarkce101242017-09-01 15:51:02 -04002077 Applies to Rect, Region, Round_Rect, Arcs, Circles, Ovals, Path, and Text.
2078 Arcs, Lines, and Points, are always drawn as if kStroke_Style is set,
Cary Clark8032b982017-07-28 11:04:54 -04002079 and ignore the set Style.
2080 The stroke construction is unaffected by the Path_Fill_Type.
2081##
2082
2083#Const kStrokeAndFill_Style 2
2084 Set to stroke and fill geometry.
Cary Clarkce101242017-09-01 15:51:02 -04002085 Applies to Rect, Region, Round_Rect, Circles, Ovals, Path, and Text.
Cary Clark8032b982017-07-28 11:04:54 -04002086 Path is treated as if it is set to SkPath::kWinding_FillType,
2087 and the set Path_Fill_Type is ignored.
2088##
2089
2090#Enum ##
2091
2092#Enum
2093
2094#Code
2095 enum {
Cary Clarkbad5ad72017-08-03 17:14:08 -04002096 kStyleCount = kStrokeAndFill_Style + 1,
Cary Clark8032b982017-07-28 11:04:54 -04002097 };
2098##
2099
2100#Const kStyleCount 3
2101The number of different Style values defined.
2102May be used to verify that Style is a legal value.
2103##
2104
2105#Enum ##
2106
2107#Method Style getStyle() const
2108
2109 Whether the geometry is filled, stroked, or filled and stroked.
2110
2111 #Return one of:kFill_Style, kStroke_Style, kStrokeAndFill_Style ##
2112
2113 #Example
2114 SkPaint paint;
2115 SkDebugf("SkPaint::kFill_Style %c= paint.getStyle()\n",
2116 SkPaint::kFill_Style == paint.getStyle() ? '=' : '!');
2117
2118 #StdOut
2119 SkPaint::kFill_Style == paint.getStyle()
2120 ##
2121 ##
2122
2123#SeeAlso Style setStyle
2124##
2125
2126#Method void setStyle(Style style)
2127
2128 Sets whether the geometry is filled, stroked, or filled and stroked.
2129 Has no effect if style is not a legal Style value.
2130
2131 #Param style one of: kFill_Style, kStroke_Style, kStrokeAndFill_Style
2132 ##
2133
2134 #Example
2135 void draw(SkCanvas* canvas) {
2136 SkPaint paint;
2137 paint.setStrokeWidth(5);
2138 SkRegion region;
2139 region.op(140, 10, 160, 30, SkRegion::kUnion_Op);
2140 region.op(170, 40, 190, 60, SkRegion::kUnion_Op);
2141 SkBitmap bitmap;
2142 bitmap.setInfo(SkImageInfo::MakeA8(50, 50), 50);
2143 uint8_t pixels[50][50];
2144 for (int x = 0; x < 50; ++x) {
2145 for (int y = 0; y < 50; ++y) {
2146 pixels[y][x] = (x + y) % 5 ? 0xFF : 0x00;
2147 }
2148 }
2149 bitmap.setPixels(pixels);
2150 for (auto style : { SkPaint::kFill_Style,
2151 SkPaint::kStroke_Style,
2152 SkPaint::kStrokeAndFill_Style }) {
2153 paint.setStyle(style);
2154 canvas->drawLine(10, 10, 60, 60, paint);
2155 canvas->drawRect({80, 10, 130, 60}, paint);
2156 canvas->drawRegion(region, paint);
2157 canvas->drawBitmap(bitmap, 200, 10, &paint);
2158 canvas->translate(0, 80);
2159 }
2160 }
2161 ##
2162
2163#SeeAlso Style getStyle
2164##
2165
2166#SeeAlso Path_Fill_Type Path_Effect Style_Fill Style_Stroke
2167#Topic Style ##
2168
2169# ------------------------------------------------------------------------------
2170#Topic Stroke_Width
2171
2172Stroke_Width sets the width for stroking. The width is the thickness
Cary Clarkbc5697d2017-10-04 14:31:33 -04002173of the stroke perpendicular to the path direction when the paint style is
Cary Clark8032b982017-07-28 11:04:54 -04002174set to kStroke_Style or kStrokeAndFill_Style.
2175
2176When width is greater than zero, the stroke encompasses as many pixels partially
2177or fully as needed. When the width equals zero, the paint enables hairlines;
2178the stroke is always one pixel wide.
2179
Cary Clarkbc5697d2017-10-04 14:31:33 -04002180The stroke dimensions are scaled by the canvas matrix, but Hairline stroke
Cary Clark8032b982017-07-28 11:04:54 -04002181remains one pixel wide regardless of scaling.
2182
2183The default width for the paint is zero.
2184
2185#Example
2186#Height 170
2187 #Platform raster gpu
2188 #Description
2189 The pixels hit to represent thin lines vary with the angle of the
Cary Clarkbc5697d2017-10-04 14:31:33 -04002190 line and the platform implementation.
Cary Clark8032b982017-07-28 11:04:54 -04002191 ##
2192 void draw(SkCanvas* canvas) {
2193 SkPaint paint;
2194 for (bool antialias : { false, true }) {
2195 paint.setAntiAlias(antialias);
2196 for (int width = 0; width <= 4; ++width) {
2197 SkScalar offset = antialias * 100 + width * 20;
2198 paint.setStrokeWidth(width * 0.25f);
2199 canvas->drawLine(10 + offset, 10, 20 + offset, 60, paint);
2200 canvas->drawLine(10 + offset, 110, 60 + offset, 160, paint);
2201 }
2202 }
2203 }
2204##
2205
2206#Method SkScalar getStrokeWidth() const
2207
2208 Returns the thickness of the pen used by Paint to
2209 outline the shape.
2210
2211 #Return zero for Hairline, greater than zero for pen thickness ##
2212
2213 #Example
2214 SkPaint paint;
2215 SkDebugf("0 %c= paint.getStrokeWidth()\n", 0 == paint.getStrokeWidth() ? '=' : '!');
2216
2217 #StdOut
2218 0 == paint.getStrokeWidth()
2219 ##
2220 ##
2221
2222##
2223
2224#Method void setStrokeWidth(SkScalar width)
2225
2226 Sets the thickness of the pen used by the paint to
2227 outline the shape.
2228 Has no effect if width is less than zero.
2229
2230 #Param width zero thickness for Hairline; greater than zero for pen thickness
2231 ##
2232
2233 #Example
2234 SkPaint paint;
2235 paint.setStrokeWidth(5);
2236 paint.setStrokeWidth(-1);
2237 SkDebugf("5 %c= paint.getStrokeWidth()\n", 5 == paint.getStrokeWidth() ? '=' : '!');
2238
2239 #StdOut
2240 5 == paint.getStrokeWidth()
2241 ##
2242 ##
2243
2244##
2245
2246#Topic ##
2247# ------------------------------------------------------------------------------
2248#Topic Miter_Limit
2249
2250Miter_Limit specifies the maximum miter length,
2251relative to the stroke width.
2252
2253Miter_Limit is used when the Stroke_Join
2254is set to kMiter_Join, and the Style is either kStroke_Style
2255or kStrokeAndFill_Style.
2256
2257If the miter at a corner exceeds this limit, kMiter_Join
2258is replaced with kBevel_Join.
2259
2260Miter_Limit can be computed from the corner angle:
2261
2262#Formula
2263 miter limit = 1 / sin ( angle / 2 )
2264#Formula ##
2265
2266Miter_Limit default value is 4.
2267The default may be changed at compile time by setting SkPaintDefaults_MiterLimit
Cary Clarkce101242017-09-01 15:51:02 -04002268in "SkUserConfig.h" or as a define supplied by the build environment.
Cary Clark8032b982017-07-28 11:04:54 -04002269
2270Here are some miter limits and the angles that triggers them.
2271#Table
2272#Legend
2273 # miter limit # angle in degrees ##
2274#Legend ##
2275 # 10 # 11.48 ##
2276 # 9 # 12.76 ##
2277 # 8 # 14.36 ##
2278 # 7 # 16.43 ##
2279 # 6 # 19.19 ##
2280 # 5 # 23.07 ##
2281 # 4 # 28.96 ##
2282 # 3 # 38.94 ##
2283 # 2 # 60 ##
2284 # 1 # 180 ##
2285#Table ##
2286
2287#Example
2288 #Height 170
2289 #Width 384
2290 #Description
2291 This example draws a stroked corner and the miter length beneath.
2292 When the miter limit is decreased slightly, the miter join is replaced
2293 by a bevel join.
2294 ##
2295 void draw(SkCanvas* canvas) {
2296 SkPoint pts[] = {{ 10, 50 }, { 110, 80 }, { 10, 110 }};
2297 SkVector v[] = { pts[0] - pts[1], pts[2] - pts[1] };
2298 SkScalar angle1 = SkScalarATan2(v[0].fY, v[0].fX);
2299 SkScalar angle2 = SkScalarATan2(v[1].fY, v[1].fX);
2300 const SkScalar strokeWidth = 20;
2301 SkScalar miterLimit = 1 / SkScalarSin((angle2 - angle1) / 2);
2302 SkScalar miterLength = strokeWidth * miterLimit;
2303 SkPath path;
2304 path.moveTo(pts[0]);
2305 path.lineTo(pts[1]);
2306 path.lineTo(pts[2]);
2307 SkPaint paint; // set to default kMiter_Join
2308 paint.setAntiAlias(true);
2309 paint.setStyle(SkPaint::kStroke_Style);
2310 paint.setStrokeMiter(miterLimit);
2311 paint.setStrokeWidth(strokeWidth);
2312 canvas->drawPath(path, paint);
2313 paint.setStrokeWidth(1);
2314 canvas->drawLine(pts[1].fX - miterLength / 2, pts[1].fY + 50,
2315 pts[1].fX + miterLength / 2, pts[1].fY + 50, paint);
2316 canvas->translate(200, 0);
2317 miterLimit *= 0.99f;
2318 paint.setStrokeMiter(miterLimit);
2319 paint.setStrokeWidth(strokeWidth);
2320 canvas->drawPath(path, paint);
2321 paint.setStrokeWidth(1);
2322 canvas->drawLine(pts[1].fX - miterLength / 2, pts[1].fY + 50,
2323 pts[1].fX + miterLength / 2, pts[1].fY + 50, paint);
2324 }
2325##
2326
2327#Method SkScalar getStrokeMiter() const
2328
2329 The limit at which a sharp corner is drawn beveled.
2330
2331 #Return zero and greater Miter_Limit ##
2332
2333 #Example
2334 SkPaint paint;
2335 SkDebugf("default miter limit == %g\n", paint.getStrokeMiter());
2336
2337 #StdOut
2338 default miter limit == 4
2339 ##
2340 ##
2341
2342 #SeeAlso Miter_Limit setStrokeMiter Join
2343
2344##
2345
2346#Method void setStrokeMiter(SkScalar miter)
2347
2348 The limit at which a sharp corner is drawn beveled.
2349 Valid values are zero and greater.
2350 Has no effect if miter is less than zero.
2351
2352 #Param miter zero and greater Miter_Limit
2353 ##
2354
2355 #Example
2356 SkPaint paint;
2357 paint.setStrokeMiter(8);
2358 paint.setStrokeMiter(-1);
2359 SkDebugf("default miter limit == %g\n", paint.getStrokeMiter());
2360
2361 #StdOut
2362 default miter limit == 8
2363 ##
2364 ##
2365
2366 #SeeAlso Miter_Limit getStrokeMiter Join
2367
2368##
2369
2370#Topic ##
2371# ------------------------------------------------------------------------------
2372#Topic Stroke_Cap
2373
2374#Enum Cap
2375
2376#Code
2377 enum Cap {
2378 kButt_Cap,
2379 kRound_Cap,
2380 kSquare_Cap,
2381
2382 kLast_Cap = kSquare_Cap,
Cary Clarkbad5ad72017-08-03 17:14:08 -04002383 kDefault_Cap = kButt_Cap,
Cary Clark8032b982017-07-28 11:04:54 -04002384 };
Cary Clark6fc50412017-09-21 12:31:06 -04002385
Cary Clark8032b982017-07-28 11:04:54 -04002386 static constexpr int kCapCount = kLast_Cap + 1;
2387##
2388
2389Stroke_Cap draws at the beginning and end of an open Path_Contour.
2390
2391 #Const kButt_Cap 0
2392 Does not extend the stroke past the beginning or the end.
2393 ##
2394 #Const kRound_Cap 1
2395 Adds a circle with a diameter equal to Stroke_Width at the beginning
2396 and end.
2397 ##
2398 #Const kSquare_Cap 2
2399 Adds a square with sides equal to Stroke_Width at the beginning
2400 and end. The square sides are parallel to the initial and final direction
2401 of the stroke.
2402 ##
2403 #Const kLast_Cap 2
2404 Equivalent to the largest value for Stroke_Cap.
2405 ##
2406 #Const kDefault_Cap 0
2407 Equivalent to kButt_Cap.
2408 Stroke_Cap is set to kButt_Cap by default.
2409 ##
2410
2411 #Const kCapCount 3
2412 The number of different Stroke_Cap values defined.
2413 May be used to verify that Stroke_Cap is a legal value.
2414 ##
2415#Enum ##
2416
2417Stroke describes the area covered by a pen of Stroke_Width as it
Cary Clarkbc5697d2017-10-04 14:31:33 -04002418follows the Path_Contour, moving parallel to the contour direction.
Cary Clark8032b982017-07-28 11:04:54 -04002419
2420If the Path_Contour is not terminated by SkPath::kClose_Verb, the contour has a
2421visible beginning and end.
2422
2423Path_Contour may start and end at the same point; defining Zero_Length_Contour.
2424
2425kButt_Cap and Zero_Length_Contour is not drawn.
2426kRound_Cap and Zero_Length_Contour draws a circle of diameter Stroke_Width
2427at the contour point.
2428kSquare_Cap and Zero_Length_Contour draws an upright square with a side of
2429Stroke_Width at the contour point.
2430
2431Stroke_Cap is kButt_Cap by default.
2432
2433#Example
2434 SkPaint paint;
2435 paint.setStyle(SkPaint::kStroke_Style);
2436 paint.setStrokeWidth(20);
2437 SkPath path;
2438 path.moveTo(30, 30);
2439 path.lineTo(30, 30);
2440 path.moveTo(70, 30);
2441 path.lineTo(90, 40);
2442 for (SkPaint::Cap c : { SkPaint::kButt_Cap, SkPaint::kRound_Cap, SkPaint::kSquare_Cap } ) {
2443 paint.setStrokeCap(c);
2444 canvas->drawPath(path, paint);
2445 canvas->translate(0, 70);
2446 }
2447##
2448
2449#Method Cap getStrokeCap() const
2450
2451 The geometry drawn at the beginning and end of strokes.
2452
2453 #Return one of: kButt_Cap, kRound_Cap, kSquare_Cap ##
2454
2455 #Example
2456 SkPaint paint;
2457 SkDebugf("kButt_Cap %c= default stroke cap\n",
2458 SkPaint::kButt_Cap == paint.getStrokeCap() ? '=' : '!');
2459
2460 #StdOut
2461 kButt_Cap == default stroke cap
2462 ##
2463 ##
2464
2465 #SeeAlso Stroke_Cap setStrokeCap
2466##
2467
2468#Method void setStrokeCap(Cap cap)
2469
2470 The geometry drawn at the beginning and end of strokes.
2471
2472 #Param cap one of: kButt_Cap, kRound_Cap, kSquare_Cap;
2473 has no effect if cap is not valid
2474 ##
2475
2476 #Example
2477 SkPaint paint;
2478 paint.setStrokeCap(SkPaint::kRound_Cap);
2479 paint.setStrokeCap((SkPaint::Cap) SkPaint::kCapCount);
2480 SkDebugf("kRound_Cap %c= paint.getStrokeCap()\n",
2481 SkPaint::kRound_Cap == paint.getStrokeCap() ? '=' : '!');
2482
2483 #StdOut
2484 kRound_Cap == paint.getStrokeCap()
2485 ##
2486 ##
2487
2488 #SeeAlso Stroke_Cap getStrokeCap
2489##
2490
2491#Topic ##
2492# ------------------------------------------------------------------------------
2493#Topic Stroke_Join
2494
2495Stroke_Join draws at the sharp corners of an open or closed Path_Contour.
2496
2497Stroke describes the area covered by a pen of Stroke_Width as it
Cary Clarkbc5697d2017-10-04 14:31:33 -04002498follows the Path_Contour, moving parallel to the contour direction.
Cary Clark8032b982017-07-28 11:04:54 -04002499
2500If the contour direction changes abruptly, because the tangent direction leading
2501to the end of a curve within the contour does not match the tangent direction of
2502the following curve, the pair of curves meet at Stroke_Join.
2503
2504#Example
2505 SkPaint paint;
2506 paint.setStyle(SkPaint::kStroke_Style);
2507 paint.setStrokeWidth(20);
2508 SkPath path;
2509 path.moveTo(30, 30);
2510 path.lineTo(40, 50);
2511 path.conicTo(70, 30, 100, 30, .707f);
2512 for (SkPaint::Join j : { SkPaint::kMiter_Join, SkPaint::kRound_Join, SkPaint::kBevel_Join } ) {
2513 paint.setStrokeJoin(j);
2514 canvas->drawPath(path, paint);
2515 canvas->translate(0, 70);
2516 }
2517##
2518
2519#Enum Join
2520#Code
2521 enum Join {
2522 kMiter_Join,
2523 kRound_Join,
2524 kBevel_Join,
2525
2526 kLast_Join = kBevel_Join,
Cary Clarkbad5ad72017-08-03 17:14:08 -04002527 kDefault_Join = kMiter_Join,
Cary Clark8032b982017-07-28 11:04:54 -04002528 };
Cary Clark6fc50412017-09-21 12:31:06 -04002529
Cary Clark8032b982017-07-28 11:04:54 -04002530 static constexpr int kJoinCount = kLast_Join + 1;
2531##
2532
Cary Clark1eace2d2017-07-31 07:52:43 -04002533Join specifies how corners are drawn when a shape is stroked. Join
Cary Clark8032b982017-07-28 11:04:54 -04002534affects the four corners of a stroked rectangle, and the connected segments in a
2535stroked path.
2536
2537Choose miter join to draw sharp corners. Choose round join to draw a circle with a
2538radius equal to the stroke width on top of the corner. Choose bevel join to minimally
2539connect the thick strokes.
2540
2541The fill path constructed to describe the stroked path respects the join setting but may
2542not contain the actual join. For instance, a fill path constructed with round joins does
2543not necessarily include circles at each connected segment.
2544
2545#Const kMiter_Join 0
2546 Extends the outside corner to the extent allowed by Miter_Limit.
2547 If the extension exceeds Miter_Limit, kBevel_Join is used instead.
2548##
2549
2550#Const kRound_Join 1
2551 Adds a circle with a diameter of Stroke_Width at the sharp corner.
2552##
2553
2554#Const kBevel_Join 2
2555 Connects the outside edges of the sharp corner.
2556##
2557
2558#Const kLast_Join 2
2559 Equivalent to the largest value for Stroke_Join.
2560##
2561
2562#Const kDefault_Join 1
2563 Equivalent to kMiter_Join.
2564 Stroke_Join is set to kMiter_Join by default.
2565##
2566
2567#Const kJoinCount 3
2568 The number of different Stroke_Join values defined.
2569 May be used to verify that Stroke_Join is a legal value.
2570##
2571
2572#Example
2573#Width 462
2574void draw(SkCanvas* canvas) {
2575 SkPath path;
2576 path.moveTo(10, 50);
2577 path.quadTo(35, 110, 60, 210);
2578 path.quadTo(105, 110, 130, 10);
2579 SkPaint paint; // set to default kMiter_Join
2580 paint.setAntiAlias(true);
2581 paint.setStyle(SkPaint::kStroke_Style);
2582 paint.setStrokeWidth(20);
2583 canvas->drawPath(path, paint);
2584 canvas->translate(150, 0);
2585 paint.setStrokeJoin(SkPaint::kBevel_Join);
2586 canvas->drawPath(path, paint);
2587 canvas->translate(150, 0);
2588 paint.setStrokeJoin(SkPaint::kRound_Join);
2589 canvas->drawPath(path, paint);
2590}
2591##
2592
2593#SeeAlso setStrokeJoin getStrokeJoin setStrokeMiter getStrokeMiter
2594
2595#Enum ##
2596
2597#Method Join getStrokeJoin() const
2598
2599 The geometry drawn at the corners of strokes.
2600
2601 #Return one of: kMiter_Join, kRound_Join, kBevel_Join ##
2602
2603 #Example
2604 SkPaint paint;
2605 SkDebugf("kMiter_Join %c= default stroke join\n",
2606 SkPaint::kMiter_Join == paint.getStrokeJoin() ? '=' : '!');
2607
2608 #StdOut
2609 kMiter_Join == default stroke join
2610 ##
2611 ##
2612
2613 #SeeAlso Stroke_Join setStrokeJoin
2614##
2615
2616#Method void setStrokeJoin(Join join)
2617
2618 The geometry drawn at the corners of strokes.
2619
2620 #Param join one of: kMiter_Join, kRound_Join, kBevel_Join;
Cary Clark579985c2017-07-31 11:48:27 -04002621 otherwise, has no effect
Cary Clark8032b982017-07-28 11:04:54 -04002622 ##
2623
2624 #Example
2625 SkPaint paint;
2626 paint.setStrokeJoin(SkPaint::kMiter_Join);
2627 paint.setStrokeJoin((SkPaint::Join) SkPaint::kJoinCount);
2628 SkDebugf("kMiter_Join %c= paint.getStrokeJoin()\n",
2629 SkPaint::kMiter_Join == paint.getStrokeJoin() ? '=' : '!');
2630
2631 #StdOut
2632 kMiter_Join == paint.getStrokeJoin()
2633 ##
2634 ##
2635
2636 #SeeAlso Stroke_Join getStrokeJoin
2637##
2638
2639#SeeAlso Miter_Limit
2640
2641#Topic Stroke_Join ##
2642# ------------------------------------------------------------------------------
2643#Topic Fill_Path
2644
2645Fill_Path creates a Path by applying the Path_Effect, followed by the Style_Stroke.
2646
2647If Paint contains Path_Effect, Path_Effect operates on the source Path; the result
2648replaces the destination Path. Otherwise, the source Path is replaces the
2649destination Path.
2650
2651Fill Path can request the Path_Effect to restrict to a culling rectangle, but
2652the Path_Effect is not required to do so.
2653
2654If Style is kStroke_Style or kStrokeAndFill_Style,
2655and Stroke_Width is greater than zero, the Stroke_Width, Stroke_Cap, Stroke_Join,
2656and Miter_Limit operate on the destination Path, replacing it.
2657
2658Fill Path can specify the precision used by Stroke_Width to approximate the stroke geometry.
2659
2660If the Style is kStroke_Style and the Stroke_Width is zero, getFillPath
2661returns false since Hairline has no filled equivalent.
2662
2663#Method bool getFillPath(const SkPath& src, SkPath* dst, const SkRect* cullRect,
2664 SkScalar resScale = 1) const
2665
2666 The filled equivalent of the stroked path.
2667
2668 #Param src Path read to create a filled version ##
2669 #Param dst resulting Path; may be the same as src, but may not be nullptr ##
2670 #Param cullRect optional limit passed to Path_Effect ##
2671 #Param resScale if > 1, increase precision, else if (0 < res < 1) reduce precision
2672 to favor speed and size
2673 ##
2674 #Return true if the path represents Style_Fill, or false if it represents Hairline ##
2675
2676 #Example
2677 #Height 192
2678 #Description
Cary Clarkce101242017-09-01 15:51:02 -04002679 A very small Quad stroke is turned into a filled path with increasing levels of precision.
2680 At the lowest precision, the Quad stroke is approximated by a rectangle.
Cary Clark8032b982017-07-28 11:04:54 -04002681 At the highest precision, the filled path has high fidelity compared to the original stroke.
2682 ##
2683 void draw(SkCanvas* canvas) {
2684 SkPaint strokePaint;
2685 strokePaint.setAntiAlias(true);
2686 strokePaint.setStyle(SkPaint::kStroke_Style);
2687 strokePaint.setStrokeWidth(.1f);
2688 SkPath strokePath;
2689 strokePath.moveTo(.08f, .08f);
2690 strokePath.quadTo(.09f, .08f, .17f, .17f);
2691 SkPath fillPath;
2692 SkPaint outlinePaint(strokePaint);
2693 outlinePaint.setStrokeWidth(2);
2694 SkMatrix scale = SkMatrix::MakeScale(300, 300);
2695 for (SkScalar precision : { 0.01f, .1f, 1.f, 10.f, 100.f } ) {
2696 strokePaint.getFillPath(strokePath, &fillPath, nullptr, precision);
2697 fillPath.transform(scale);
2698 canvas->drawPath(fillPath, outlinePaint);
2699 canvas->translate(60, 0);
2700 if (1.f == precision) canvas->translate(-180, 100);
2701 }
2702 strokePath.transform(scale);
2703 strokePaint.setStrokeWidth(30);
2704 canvas->drawPath(strokePath, strokePaint);
2705 }
2706 ##
2707
2708##
2709
2710#Method bool getFillPath(const SkPath& src, SkPath* dst) const
2711
2712 The filled equivalent of the stroked path.
2713
2714 Replaces dst with the src path modified by Path_Effect and Style_Stroke.
2715 Path_Effect, if any, is not culled. Stroke_Width is created with default precision.
2716
2717 #Param src Path read to create a filled version ##
2718 #Param dst resulting Path dst may be the same as src, but may not be nullptr ##
2719 #Return true if the path represents Style_Fill, or false if it represents Hairline ##
2720
2721 #Example
2722 #Height 128
2723 void draw(SkCanvas* canvas) {
2724 SkPaint paint;
2725 paint.setStyle(SkPaint::kStroke_Style);
2726 paint.setStrokeWidth(10);
2727 SkPath strokePath;
2728 strokePath.moveTo(20, 20);
2729 strokePath.lineTo(100, 100);
2730 canvas->drawPath(strokePath, paint);
2731 SkPath fillPath;
2732 paint.getFillPath(strokePath, &fillPath);
2733 paint.setStrokeWidth(2);
2734 canvas->translate(40, 0);
2735 canvas->drawPath(fillPath, paint);
2736 }
2737 ##
2738
2739##
2740
2741#SeeAlso Style_Stroke Stroke_Width Path_Effect
2742
2743#Topic ##
2744# ------------------------------------------------------------------------------
2745#Topic Shader_Methods
2746
2747Shader defines the colors used when drawing a shape.
2748Shader may be an image, a gradient, or a computed fill.
2749If Paint has no Shader, then Color fills the shape.
2750
2751Shader is modulated by Color_Alpha component of Color.
2752If Shader object defines only Color_Alpha, then Color modulated by Color_Alpha describes
2753the fill.
2754
2755The drawn transparency can be modified without altering Shader, by changing Color_Alpha.
2756
2757#Example
2758void draw(SkCanvas* canvas) {
2759 SkPaint paint;
2760 SkPoint center = { 50, 50 };
2761 SkScalar radius = 50;
2762 const SkColor colors[] = { 0xFFFFFFFF, 0xFF000000 };
2763 paint.setShader(SkGradientShader::MakeRadial(center, radius, colors,
2764 nullptr, SK_ARRAY_COUNT(colors), SkShader::kClamp_TileMode));
2765 for (SkScalar a : { 0.3f, 0.6f, 1.0f } ) {
2766 paint.setAlpha((int) (a * 255));
2767 canvas->drawCircle(center.fX, center.fY, radius, paint);
2768 canvas->translate(70, 70);
2769 }
2770}
2771##
2772
2773If Shader generates only Color_Alpha then all components of Color modulate the output.
2774
2775#Example
2776void draw(SkCanvas* canvas) {
2777 SkPaint paint;
2778 SkBitmap bitmap;
2779 bitmap.setInfo(SkImageInfo::MakeA8(5, 1), 5); // bitmap only contains alpha
2780 uint8_t pixels[5] = { 0x22, 0x55, 0x88, 0xBB, 0xFF };
2781 bitmap.setPixels(pixels);
2782 paint.setShader(SkShader::MakeBitmapShader(bitmap,
2783 SkShader::kMirror_TileMode, SkShader::kMirror_TileMode));
2784 for (SkColor c : { SK_ColorRED, SK_ColorBLUE, SK_ColorGREEN } ) {
2785 paint.setColor(c); // all components in color affect shader
2786 canvas->drawCircle(50, 50, 50, paint);
2787 canvas->translate(70, 70);
2788 }
2789}
2790##
2791
2792#Method SkShader* getShader() const
2793
2794 Optional colors used when filling a path, such as a gradient.
2795
2796 Does not alter Shader Reference_Count.
2797
2798 #Return Shader if previously set, nullptr otherwise ##
2799
2800 #Example
2801 void draw(SkCanvas* canvas) {
2802 SkPaint paint;
2803 SkDebugf("nullptr %c= shader\n", paint.getShader() ? '!' : '=');
2804 paint.setShader(SkShader::MakeEmptyShader());
2805 SkDebugf("nullptr %c= shader\n", paint.getShader() ? '!' : '=');
2806 }
2807
2808 #StdOut
2809 nullptr == shader
2810 nullptr != shader
2811 ##
2812 ##
2813
2814##
2815
2816#Method sk_sp<SkShader> refShader() const
2817
2818 Optional colors used when filling a path, such as a gradient.
2819
2820 Increases Shader Reference_Count by one.
2821
2822 #Return Shader if previously set, nullptr otherwise ##
2823
2824 #Example
2825 void draw(SkCanvas* canvas) {
2826 SkPaint paint1, paint2;
2827 paint1.setShader(SkShader::MakeEmptyShader());
2828 SkDebugf("shader unique: %s\n", paint1.getShader()->unique() ? "true" : "false");
2829 paint2.setShader(paint1.refShader());
2830 SkDebugf("shader unique: %s\n", paint1.getShader()->unique() ? "true" : "false");
2831 }
2832
2833 #StdOut
2834 shader unique: true
2835 shader unique: false
2836 ##
2837 ##
2838
2839##
2840
2841#Method void setShader(sk_sp<SkShader> shader)
2842
2843 Optional colors used when filling a path, such as a gradient.
2844
Cary Clarkd0530ba2017-09-14 11:25:39 -04002845 Sets Shader to shader, decreasing Reference_Count of the previous Shader.
Cary Clark6fc50412017-09-21 12:31:06 -04002846 Increments shader Reference_Count by one.
Cary Clark8032b982017-07-28 11:04:54 -04002847
2848 #Param shader how geometry is filled with color; if nullptr, Color is used instead ##
2849
2850 #Example
2851 #Height 64
2852 void draw(SkCanvas* canvas) {
2853 SkPaint paint;
2854 paint.setColor(SK_ColorBLUE);
2855 paint.setShader(SkShader::MakeColorShader(SK_ColorRED));
2856 canvas->drawRect(SkRect::MakeWH(40, 40), paint);
2857 paint.setShader(nullptr);
2858 canvas->translate(50, 0);
2859 canvas->drawRect(SkRect::MakeWH(40, 40), paint);
2860 }
2861 ##
2862
2863##
2864
2865#Topic ##
2866# ------------------------------------------------------------------------------
2867#Topic Color_Filter_Methods
2868
2869Color_Filter alters the color used when drawing a shape.
2870Color_Filter may apply Blend_Mode, transform the color through a matrix, or composite multiple filters.
2871If Paint has no Color_Filter, the color is unaltered.
2872
2873The drawn transparency can be modified without altering Color_Filter, by changing Color_Alpha.
2874
2875#Example
2876#Height 128
2877void draw(SkCanvas* canvas) {
2878 SkPaint paint;
2879 paint.setColorFilter(SkColorMatrixFilter::MakeLightingFilter(0xFFFFFF, 0xFF0000));
2880 for (SkColor c : { SK_ColorBLACK, SK_ColorGREEN } ) {
2881 paint.setColor(c);
2882 canvas->drawRect(SkRect::MakeXYWH(10, 10, 50, 50), paint);
2883 paint.setAlpha(0x80);
2884 canvas->drawRect(SkRect::MakeXYWH(60, 60, 50, 50), paint);
2885 canvas->translate(100, 0);
2886 }
2887}
2888##
2889
2890#Method SkColorFilter* getColorFilter() const
2891
2892 Returns Color_Filter if set, or nullptr.
2893 Does not alter Color_Filter Reference_Count.
2894
2895 #Return Color_Filter if previously set, nullptr otherwise ##
2896
2897 #Example
2898 void draw(SkCanvas* canvas) {
2899 SkPaint paint;
2900 SkDebugf("nullptr %c= color filter\n", paint.getColorFilter() ? '!' : '=');
2901 paint.setColorFilter(SkColorFilter::MakeModeFilter(SK_ColorLTGRAY, SkBlendMode::kSrcIn));
2902 SkDebugf("nullptr %c= color filter\n", paint.getColorFilter() ? '!' : '=');
2903 }
2904
2905 #StdOut
2906 nullptr == color filter
2907 nullptr != color filter
2908 ##
2909 ##
2910##
2911
2912#Method sk_sp<SkColorFilter> refColorFilter() const
2913
2914 Returns Color_Filter if set, or nullptr.
2915 Increases Color_Filter Reference_Count by one.
2916
2917 #Return Color_Filter if set, or nullptr ##
2918
2919 #Example
2920 void draw(SkCanvas* canvas) {
2921 SkPaint paint1, paint2;
2922 paint1.setColorFilter(SkColorFilter::MakeModeFilter(0xFFFF0000, SkBlendMode::kSrcATop));
2923 SkDebugf("color filter unique: %s\n", paint1.getColorFilter()->unique() ? "true" : "false");
2924 paint2.setColorFilter(paint1.refColorFilter());
2925 SkDebugf("color filter unique: %s\n", paint1.getColorFilter()->unique() ? "true" : "false");
2926 }
2927
2928 #StdOut
2929 color filter unique: true
2930 color filter unique: false
2931 ##
2932 ##
2933##
2934
2935#Method void setColorFilter(sk_sp<SkColorFilter> colorFilter)
2936
Cary Clark6fc50412017-09-21 12:31:06 -04002937Sets Color_Filter to filter, decreasing Reference_Count of the previous
2938Color_Filter. Pass nullptr to clear Color_Filter.
2939
2940Increments filter Reference_Count by one.
Cary Clark8032b982017-07-28 11:04:54 -04002941
2942 #Param colorFilter Color_Filter to apply to subsequent draw ##
2943
2944 #Example
2945 #Height 64
2946 void draw(SkCanvas* canvas) {
2947 SkPaint paint;
2948 paint.setColorFilter(SkColorFilter::MakeModeFilter(SK_ColorLTGRAY, SkBlendMode::kSrcIn));
2949 canvas->drawRect(SkRect::MakeWH(50, 50), paint);
2950 paint.setColorFilter(nullptr);
2951 canvas->translate(70, 0);
2952 canvas->drawRect(SkRect::MakeWH(50, 50), paint);
2953 }
2954 ##
2955
2956##
2957
2958#Topic ##
2959# ------------------------------------------------------------------------------
2960#Topic Blend_Mode_Methods
2961
2962Blend_Mode describes how Color combines with the destination color.
2963The default setting, SkBlendMode::kSrcOver, draws the source color
2964over the destination color.
2965
2966#Example
2967void draw(SkCanvas* canvas) {
2968 SkPaint normal, blender;
2969 normal.setColor(0xFF58a889);
2970 blender.setColor(0xFF8958a8);
2971 canvas->clear(0);
2972 for (SkBlendMode m : { SkBlendMode::kSrcOver, SkBlendMode::kSrcIn, SkBlendMode::kSrcOut } ) {
2973 normal.setBlendMode(SkBlendMode::kSrcOver);
2974 canvas->drawOval(SkRect::MakeXYWH(30, 30, 30, 80), normal);
2975 blender.setBlendMode(m);
2976 canvas->drawOval(SkRect::MakeXYWH(10, 50, 80, 30), blender);
2977 canvas->translate(70, 70);
2978 }
2979}
2980##
2981
2982#SeeAlso Blend_Mode
2983
2984#Method SkBlendMode getBlendMode() const
2985
2986 Returns Blend_Mode.
Cary Clark579985c2017-07-31 11:48:27 -04002987 By default, returns SkBlendMode::kSrcOver.
Cary Clark8032b982017-07-28 11:04:54 -04002988
2989 #Return mode used to combine source color with destination color ##
2990
2991 #Example
2992 void draw(SkCanvas* canvas) {
2993 SkPaint paint;
2994 SkDebugf("kSrcOver %c= getBlendMode\n",
2995 SkBlendMode::kSrcOver == paint.getBlendMode() ? '=' : '!');
2996 paint.setBlendMode(SkBlendMode::kSrc);
2997 SkDebugf("kSrcOver %c= getBlendMode\n",
2998 SkBlendMode::kSrcOver == paint.getBlendMode() ? '=' : '!');
2999 }
3000
3001 #StdOut
3002 kSrcOver == getBlendMode
3003 kSrcOver != getBlendMode
3004 ##
3005 ##
3006
3007##
3008
3009#Method bool isSrcOver() const
3010
3011 Returns true if Blend_Mode is SkBlendMode::kSrcOver, the default.
3012
3013 #Return true if Blend_Mode is SkBlendMode::kSrcOver ##
3014
3015 #Example
3016 void draw(SkCanvas* canvas) {
3017 SkPaint paint;
3018 SkDebugf("isSrcOver %c= true\n", paint.isSrcOver() ? '=' : '!');
3019 paint.setBlendMode(SkBlendMode::kSrc);
3020 SkDebugf("isSrcOver %c= true\n", paint.isSrcOver() ? '=' : '!');
3021 }
3022
3023 #StdOut
3024 isSrcOver == true
3025 isSrcOver != true
3026 ##
3027 ##
3028
3029##
3030
3031#Method void setBlendMode(SkBlendMode mode)
3032
3033 Sets Blend_Mode to mode.
3034 Does not check for valid input.
3035
3036 #Param mode SkBlendMode used to combine source color and destination ##
3037
3038 #Example
3039 void draw(SkCanvas* canvas) {
3040 SkPaint paint;
3041 SkDebugf("isSrcOver %c= true\n", paint.isSrcOver() ? '=' : '!');
3042 paint.setBlendMode(SkBlendMode::kSrc);
3043 SkDebugf("isSrcOver %c= true\n", paint.isSrcOver() ? '=' : '!');
3044 }
3045
3046 #StdOut
3047 isSrcOver == true
3048 isSrcOver != true
3049 ##
3050 ##
3051
3052##
3053
3054#Topic ##
3055# ------------------------------------------------------------------------------
3056#Topic Path_Effect_Methods
3057
3058Path_Effect modifies the path geometry before drawing it.
3059Path_Effect may implement dashing, custom fill effects and custom stroke effects.
3060If Paint has no Path_Effect, the path geometry is unaltered when filled or stroked.
3061
3062#Example
3063#Height 160
3064 void draw(SkCanvas* canvas) {
3065 SkPaint paint;
3066 paint.setStyle(SkPaint::kStroke_Style);
3067 paint.setStrokeWidth(16);
3068 SkScalar intervals[] = {30, 10};
3069 paint.setPathEffect(SkDashPathEffect::Make(intervals, SK_ARRAY_COUNT(intervals), 1));
3070 canvas->drawRoundRect({20, 20, 120, 120}, 20, 20, paint);
3071 }
3072##
3073
3074#SeeAlso Path_Effect
3075
3076#Method SkPathEffect* getPathEffect() const
3077
3078 Returns Path_Effect if set, or nullptr.
3079 Does not alter Path_Effect Reference_Count.
3080
3081 #Return Path_Effect if previously set, nullptr otherwise ##
3082
3083 #Example
3084 void draw(SkCanvas* canvas) {
3085 SkPaint paint;
3086 SkDebugf("nullptr %c= path effect\n", paint.getPathEffect() ? '!' : '=');
3087 paint.setPathEffect(SkCornerPathEffect::Make(10));
3088 SkDebugf("nullptr %c= path effect\n", paint.getPathEffect() ? '!' : '=');
3089 }
3090
3091 #StdOut
3092 nullptr == path effect
3093 nullptr != path effect
3094 ##
3095 ##
3096
3097##
3098
3099
3100#Method sk_sp<SkPathEffect> refPathEffect() const
3101
3102 Returns Path_Effect if set, or nullptr.
3103 Increases Path_Effect Reference_Count by one.
3104
3105 #Return Path_Effect if previously set, nullptr otherwise ##
3106
3107 #Example
3108 void draw(SkCanvas* canvas) {
3109 SkPaint paint1, paint2;
3110 paint1.setPathEffect(SkArcToPathEffect::Make(10));
3111 SkDebugf("path effect unique: %s\n", paint1.getPathEffect()->unique() ? "true" : "false");
3112 paint2.setPathEffect(paint1.refPathEffect());
3113 SkDebugf("path effect unique: %s\n", paint1.getPathEffect()->unique() ? "true" : "false");
3114 }
3115
3116 #StdOut
3117 path effect unique: true
3118 path effect unique: false
3119 ##
3120 ##
3121
3122##
3123
3124
3125#Method void setPathEffect(sk_sp<SkPathEffect> pathEffect)
3126
Cary Clark6fc50412017-09-21 12:31:06 -04003127Sets Path_Effect to pathEffect, decreasing Reference_Count of the previous
3128Path_Effect. Pass nullptr to leave the path geometry unaltered.
3129
3130Increments pathEffect Reference_Count by one.
Cary Clark8032b982017-07-28 11:04:54 -04003131
3132 #Param pathEffect replace Path with a modification when drawn ##
3133
3134 #Example
3135 void draw(SkCanvas* canvas) {
3136 SkPaint paint;
3137 paint.setPathEffect(SkDiscretePathEffect::Make(3, 5));
3138 canvas->drawRect(SkRect::MakeXYWH(40, 40, 175, 175), paint);
3139 }
3140 ##
3141
3142##
3143
3144#Topic ##
3145# ------------------------------------------------------------------------------
3146#Topic Mask_Filter_Methods
3147
Cary Clarkce101242017-09-01 15:51:02 -04003148Mask_Filter uses coverage of the shape drawn to create Mask_Alpha.
Cary Clark8032b982017-07-28 11:04:54 -04003149Mask_Filter operates at a lower level than Rasterizer; Mask_Filter takes a Mask,
3150and returns a Mask.
Cary Clark6fc50412017-09-21 12:31:06 -04003151
3152Mask_Filter may change the geometry and transparency of the shape, such as
3153creating a blur effect. Set Mask_Filter to nullptr to prevent Mask_Filter from
3154modifying the draw.
Cary Clark8032b982017-07-28 11:04:54 -04003155
3156#Example
3157 void draw(SkCanvas* canvas) {
3158 SkPaint paint;
3159 paint.setMaskFilter(SkBlurMaskFilter::Make(kSolid_SkBlurStyle, 3));
3160 canvas->drawRect(SkRect::MakeXYWH(40, 40, 175, 175), paint);
3161 }
3162##
3163
3164#Method SkMaskFilter* getMaskFilter() const
3165
3166 Returns Mask_Filter if set, or nullptr.
3167 Does not alter Mask_Filter Reference_Count.
3168
3169 #Return Mask_Filter if previously set, nullptr otherwise ##
3170
3171 #Example
3172 void draw(SkCanvas* canvas) {
3173 SkPaint paint;
3174 SkDebugf("nullptr %c= mask filter\n", paint.getMaskFilter() ? '!' : '=');
3175 paint.setMaskFilter(SkBlurMaskFilter::Make(kOuter_SkBlurStyle, 3));
3176 SkDebugf("nullptr %c= mask filter\n", paint.getMaskFilter() ? '!' : '=');
3177 }
3178
3179 #StdOut
3180 nullptr == mask filter
3181 nullptr != mask filter
3182 ##
3183 ##
3184
3185##
3186
3187#Method sk_sp<SkMaskFilter> refMaskFilter() const
3188
3189 Returns Mask_Filter if set, or nullptr.
Cary Clark6fc50412017-09-21 12:31:06 -04003190
Cary Clark8032b982017-07-28 11:04:54 -04003191 Increases Mask_Filter Reference_Count by one.
3192
3193 #Return Mask_Filter if previously set, nullptr otherwise ##
3194
3195 #Example
3196 void draw(SkCanvas* canvas) {
3197 SkPaint paint1, paint2;
3198 paint1.setMaskFilter(SkBlurMaskFilter::Make(kNormal_SkBlurStyle, 1));
3199 SkDebugf("mask filter unique: %s\n", paint1.getMaskFilter()->unique() ? "true" : "false");
3200 paint2.setMaskFilter(paint1.refMaskFilter());
3201 SkDebugf("mask filter unique: %s\n", paint1.getMaskFilter()->unique() ? "true" : "false");
3202 }
3203
3204 #StdOut
3205 mask filter unique: true
3206 mask filter unique: false
3207 ##
3208 ##
3209
3210##
3211
3212#Method void setMaskFilter(sk_sp<SkMaskFilter> maskFilter)
3213
Cary Clark6fc50412017-09-21 12:31:06 -04003214Sets Mask_Filter to maskFilter, decreasing Reference_Count of the previous
3215Mask_Filter. Pass nullptr to clear Mask_Filter and leave Mask_Filter effect on
3216Mask_Alpha unaltered.
3217
3218Does not affect Rasterizer.
3219Increments maskFilter Reference_Count by one.
Cary Clark8032b982017-07-28 11:04:54 -04003220
3221 #Param maskFilter modifies clipping mask generated from drawn geometry ##
3222
3223 #Example
3224 void draw(SkCanvas* canvas) {
3225 SkPaint paint;
3226 paint.setStyle(SkPaint::kStroke_Style);
3227 paint.setStrokeWidth(10);
3228 paint.setMaskFilter(SkBlurMaskFilter::Make(kNormal_SkBlurStyle, 10));
3229 canvas->drawRect(SkRect::MakeXYWH(40, 40, 175, 175), paint);
3230 }
3231 ##
3232
3233##
3234
3235#Topic ##
3236# ------------------------------------------------------------------------------
3237#Topic Typeface_Methods
3238
3239Typeface identifies the font used when drawing and measuring text.
3240Typeface may be specified by name, from a file, or from a data stream.
3241The default Typeface defers to the platform-specific default font
3242implementation.
3243
3244#Example
3245#Height 100
3246 void draw(SkCanvas* canvas) {
3247 SkPaint paint;
3248 paint.setTypeface(SkTypeface::MakeDefault(SkTypeface::kBold));
3249 paint.setAntiAlias(true);
3250 paint.setTextSize(36);
3251 canvas->drawString("A Big Hello!", 10, 40, paint);
3252 paint.setTypeface(nullptr);
3253 paint.setFakeBoldText(true);
3254 canvas->drawString("A Big Hello!", 10, 80, paint);
3255 }
3256##
3257
3258#Method SkTypeface* getTypeface() const
3259
3260 Returns Typeface if set, or nullptr.
Cary Clark6fc50412017-09-21 12:31:06 -04003261 Increments Typeface Reference_Count by one.
Cary Clark8032b982017-07-28 11:04:54 -04003262
3263 #Return Typeface if previously set, nullptr otherwise ##
3264
3265 #Example
3266 void draw(SkCanvas* canvas) {
3267 SkPaint paint;
3268 SkDebugf("nullptr %c= typeface\n", paint.getTypeface() ? '!' : '=');
3269 paint.setTypeface(SkTypeface::MakeFromName("Times New Roman", SkFontStyle()));
3270 SkDebugf("nullptr %c= typeface\n", paint.getTypeface() ? '!' : '=');
3271 }
3272
3273 #StdOut
3274 nullptr == typeface
3275 nullptr != typeface
3276 ##
3277 ##
3278
3279##
3280
3281#Method sk_sp<SkTypeface> refTypeface() const
3282
3283 Increases Typeface Reference_Count by one.
3284
3285 #Return Typeface if previously set, nullptr otherwise ##
3286
3287 #Example
3288 void draw(SkCanvas* canvas) {
3289 SkPaint paint1, paint2;
3290 paint1.setTypeface(SkTypeface::MakeFromName("Times New Roman",
3291 SkFontStyle(SkFontStyle::kNormal_Weight, SkFontStyle::kNormal_Width,
3292 SkFontStyle::kItalic_Slant)));
3293 SkDebugf("typeface1 %c= typeface2\n",
3294 paint1.getTypeface() == paint2.getTypeface() ? '=' : '!');
3295 paint2.setTypeface(paint1.refTypeface());
3296 SkDebugf("typeface1 %c= typeface2\n",
3297 paint1.getTypeface() == paint2.getTypeface() ? '=' : '!');
3298 }
3299
3300 #StdOut
3301 typeface1 != typeface2
3302 typeface1 == typeface2
3303 ##
3304 ##
3305
3306##
3307
3308#Method void setTypeface(sk_sp<SkTypeface> typeface)
3309
Cary Clark6fc50412017-09-21 12:31:06 -04003310Sets Typeface to typeface, decreasing Reference_Count of the previous Typeface.
3311Pass nullptr to clear Typeface and use the default typeface. Increments
3312typeface Reference_Count by one.
Cary Clark8032b982017-07-28 11:04:54 -04003313
3314 #Param typeface font and style used to draw text ##
3315
3316 #Example
3317 #Height 64
3318 void draw(SkCanvas* canvas) {
3319 SkPaint paint;
3320 paint.setTypeface(SkTypeface::MakeFromName("Courier New", SkFontStyle()));
3321 canvas->drawString("Courier New", 10, 30, paint);
3322 paint.setTypeface(nullptr);
3323 canvas->drawString("default", 10, 50, paint);
3324 }
3325 ##
3326
3327##
3328
3329#Topic ##
3330# ------------------------------------------------------------------------------
3331#Topic Rasterizer_Methods
3332
3333Rasterizer controls how shapes are converted to Mask_Alpha.
3334Rasterizer operates at a higher level than Mask_Filter; Rasterizer takes a Path,
3335and returns a Mask.
Cary Clark6fc50412017-09-21 12:31:06 -04003336
Cary Clark8032b982017-07-28 11:04:54 -04003337Rasterizer may change the geometry and transparency of the shape, such as
3338creating a shadow effect. Rasterizer forms the base of Rasterizer_Layer, which
3339creates effects like embossing and outlining.
Cary Clark6fc50412017-09-21 12:31:06 -04003340
Cary Clarkce101242017-09-01 15:51:02 -04003341Rasterizer applies to Rect, Region, Round_Rect, Arcs, Circles, Ovals,
Cary Clark8032b982017-07-28 11:04:54 -04003342Path, and Text.
3343
3344#Example
3345#Height 64
3346 void draw(SkCanvas* canvas) {
3347 SkLayerRasterizer::Builder layerBuilder;
3348 SkPaint paint;
3349 paint.setAntiAlias(true);
3350 paint.setStyle(SkPaint::kStroke_Style);
3351 paint.setStrokeWidth(1);
3352 layerBuilder.addLayer(paint);
3353 paint.setAlpha(0x10);
3354 paint.setStyle(SkPaint::kFill_Style);
3355 paint.setBlendMode(SkBlendMode::kSrc);
3356 layerBuilder.addLayer(paint);
3357 paint.reset();
3358 paint.setAntiAlias(true);
3359 paint.setTextSize(50);
3360 paint.setRasterizer(layerBuilder.detach());
3361 canvas->drawString("outline", 10, 50, paint);
3362 }
3363##
3364
3365#Method SkRasterizer* getRasterizer() const
3366
3367 Returns Rasterizer if set, or nullptr.
3368 Does not alter Rasterizer Reference_Count.
3369
3370 #Return Rasterizer if previously set, nullptr otherwise ##
3371
3372 #Example
3373 #Function
3374 class DummyRasterizer : public SkRasterizer {
3375 public:
3376 SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(DummyRasterizer)
3377 };
3378
3379 sk_sp<SkFlattenable> DummyRasterizer::CreateProc(SkReadBuffer&) {
3380 return sk_make_sp<DummyRasterizer>();
3381 }
3382
3383 #Function ##
3384 void draw(SkCanvas* canvas) {
3385 SkPaint paint;
3386 DummyRasterizer dummy;
3387 SkDebugf("nullptr %c= rasterizer\n", paint.getRasterizer() ? '!' : '=');
3388 paint.setRasterizer(sk_make_sp<DummyRasterizer>());
3389 SkDebugf("nullptr %c= rasterizer\n", paint.getRasterizer() ? '!' : '=');
3390 }
3391
3392 #StdOut
3393 nullptr == rasterizer
3394 nullptr != rasterizer
3395 ##
3396 ##
3397
3398##
3399
3400#Method sk_sp<SkRasterizer> refRasterizer() const
3401
3402 Returns Rasterizer if set, or nullptr.
3403 Increases Rasterizer Reference_Count by one.
3404
3405 #Return Rasterizer if previously set, nullptr otherwise ##
3406
3407 #Example
3408 void draw(SkCanvas* canvas) {
3409 SkLayerRasterizer::Builder layerBuilder;
3410 SkPaint paint1, paint2;
3411 layerBuilder.addLayer(paint2);
3412 paint1.setRasterizer(layerBuilder.detach());
3413 SkDebugf("rasterizer unique: %s\n", paint1.getRasterizer()->unique() ? "true" : "false");
3414 paint2.setRasterizer(paint1.refRasterizer());
3415 SkDebugf("rasterizer unique: %s\n", paint1.getRasterizer()->unique() ? "true" : "false");
3416 }
3417
3418 #StdOut
3419 rasterizer unique: true
3420 rasterizer unique: false
3421 ##
3422 ##
3423
3424##
3425
3426#Method void setRasterizer(sk_sp<SkRasterizer> rasterizer)
3427
Cary Clark6fc50412017-09-21 12:31:06 -04003428Sets Rasterizer to rasterizer, decreasing Reference_Count of the previous
3429Rasterizer. Pass nullptr to clear Rasterizer and leave Rasterizer effect on
3430Mask_Alpha unaltered.
3431
3432Does not affect Mask_Filter.
3433Increments rasterizer Reference_Count by one.
Cary Clark8032b982017-07-28 11:04:54 -04003434
3435 #Param rasterizer how geometry is converted to Mask_Alpha ##
3436
3437 #Example
3438 #Height 64
3439 SkLayerRasterizer::Builder layerBuilder;
3440 SkPaint paint;
3441 paint.setAntiAlias(true);
3442 paint.setStyle(SkPaint::kStroke_Style);
3443 paint.setStrokeWidth(2);
3444 layerBuilder.addLayer(paint);
3445 paint.reset();
3446 paint.setAntiAlias(true);
3447 paint.setTextSize(50);
3448 paint.setMaskFilter(SkBlurMaskFilter::Make(kNormal_SkBlurStyle, 3));
3449 paint.setRasterizer(layerBuilder.detach());
3450 canvas->drawString("blurry out", 0, 50, paint);
3451 ##
3452
3453##
3454
3455#Topic ##
3456# ------------------------------------------------------------------------------
3457#Topic Image_Filter_Methods
3458
3459Image_Filter operates on the pixel representation of the shape, as modified by Paint
3460with Blend_Mode set to SkBlendMode::kSrcOver. Image_Filter creates a new bitmap,
3461which is drawn to the device using the set Blend_Mode.
Cary Clark6fc50412017-09-21 12:31:06 -04003462
Cary Clark8032b982017-07-28 11:04:54 -04003463Image_Filter is higher level than Mask_Filter; for instance, an Image_Filter
Cary Clarkce101242017-09-01 15:51:02 -04003464can operate on all channels of Color, while Mask_Filter generates Alpha only.
Cary Clark8032b982017-07-28 11:04:54 -04003465Image_Filter operates independently of and can be used in combination with
3466Mask_Filter and Rasterizer.
3467
3468#Example
3469 #ToDo explain why the two draws are so different ##
3470 void draw(SkCanvas* canvas) {
3471 SkPaint paint;
3472 paint.setStyle(SkPaint::kStroke_Style);
3473 paint.setStrokeWidth(2);
3474 SkRegion region;
3475 region.op( 10, 10, 50, 50, SkRegion::kUnion_Op);
3476 region.op( 10, 50, 90, 90, SkRegion::kUnion_Op);
3477 paint.setImageFilter(SkImageFilter::MakeBlur(5.0f, 5.0f, nullptr));
3478 canvas->drawRegion(region, paint);
3479 paint.setImageFilter(nullptr);
3480 paint.setMaskFilter(SkBlurMaskFilter::Make(kNormal_SkBlurStyle, 5));
3481 canvas->translate(100, 100);
3482 canvas->drawRegion(region, paint);
3483 }
3484##
3485
3486#Method SkImageFilter* getImageFilter() const
3487
3488 Returns Image_Filter if set, or nullptr.
3489 Does not alter Image_Filter Reference_Count.
3490
3491 #Return Image_Filter if previously set, nullptr otherwise ##
3492
3493 #Example
3494 void draw(SkCanvas* canvas) {
3495 SkPaint paint;
3496 SkDebugf("nullptr %c= image filter\n", paint.getImageFilter() ? '!' : '=');
3497 paint.setImageFilter(SkImageFilter::MakeBlur(kOuter_SkBlurStyle, 3, nullptr, nullptr));
3498 SkDebugf("nullptr %c= image filter\n", paint.getImageFilter() ? '!' : '=');
3499 }
3500
3501 #StdOut
3502 nullptr == image filter
3503 nullptr != image filter
3504 ##
3505 ##
3506
3507##
3508
3509#Method sk_sp<SkImageFilter> refImageFilter() const
3510
3511 Returns Image_Filter if set, or nullptr.
3512 Increases Image_Filter Reference_Count by one.
3513
3514 #Return Image_Filter if previously set, nullptr otherwise ##
3515
3516 #Example
3517 void draw(SkCanvas* canvas) {
3518 SkPaint paint1, paint2;
3519 paint1.setImageFilter(SkOffsetImageFilter::Make(25, 25, nullptr));
3520 SkDebugf("image filter unique: %s\n", paint1.getImageFilter()->unique() ? "true" : "false");
3521 paint2.setImageFilter(paint1.refImageFilter());
3522 SkDebugf("image filter unique: %s\n", paint1.getImageFilter()->unique() ? "true" : "false");
3523 }
3524
3525 #StdOut
3526 image filter unique: true
3527 image filter unique: false
3528 ##
3529 ##
3530
3531##
3532
3533#Method void setImageFilter(sk_sp<SkImageFilter> imageFilter)
3534
Cary Clark6fc50412017-09-21 12:31:06 -04003535Sets Image_Filter to imageFilter, decreasing Reference_Count of the previous
3536Image_Filter. Pass nullptr to clear Image_Filter, and remove Image_Filter effect
3537on drawing.
3538
3539Does not affect Rasterizer or Mask_Filter.
3540Increments imageFilter Reference_Count by one.
Cary Clark8032b982017-07-28 11:04:54 -04003541
3542 #Param imageFilter how Image is sampled when transformed ##
3543
3544 #Example
3545 #Height 160
3546 void draw(SkCanvas* canvas) {
3547 SkBitmap bitmap;
3548 bitmap.allocN32Pixels(100, 100);
3549 SkCanvas offscreen(bitmap);
3550 SkPaint paint;
3551 paint.setAntiAlias(true);
3552 paint.setColor(SK_ColorWHITE);
3553 paint.setTextSize(96);
3554 offscreen.clear(0);
3555 offscreen.drawString("e", 20, 70, paint);
3556 paint.setImageFilter(
3557 SkLightingImageFilter::MakePointLitDiffuse(SkPoint3::Make(80, 100, 10),
3558 SK_ColorWHITE, 1, 2, nullptr, nullptr));
3559 canvas->drawBitmap(bitmap, 0, 0, &paint);
3560 }
3561 ##
3562
3563##
3564
3565#Topic ##
3566# ------------------------------------------------------------------------------
3567#Topic Draw_Looper_Methods
3568
3569Draw_Looper sets a modifier that communicates state from one Draw_Layer
3570to another to construct the draw.
Cary Clark6fc50412017-09-21 12:31:06 -04003571
Cary Clark8032b982017-07-28 11:04:54 -04003572Draw_Looper draws one or more times, modifying the canvas and paint each time.
3573Draw_Looper may be used to draw multiple colors or create a colored shadow.
3574Set Draw_Looper to nullptr to prevent Draw_Looper from modifying the draw.
3575
3576#Example
3577#Height 128
3578 void draw(SkCanvas* canvas) {
3579 SkLayerDrawLooper::LayerInfo info;
3580 info.fPaintBits = (SkLayerDrawLooper::BitFlags) SkLayerDrawLooper::kColorFilter_Bit;
3581 info.fColorMode = SkBlendMode::kSrc;
3582 SkLayerDrawLooper::Builder looperBuilder;
3583 SkPaint* loopPaint = looperBuilder.addLayer(info);
3584 loopPaint->setColor(SK_ColorRED);
3585 info.fOffset.set(20, 20);
3586 loopPaint = looperBuilder.addLayer(info);
3587 loopPaint->setColor(SK_ColorBLUE);
3588 SkPaint paint;
3589 paint.setDrawLooper(looperBuilder.detach());
3590 canvas->drawCircle(50, 50, 50, paint);
3591 }
3592
3593##
3594
3595#Method SkDrawLooper* getDrawLooper() const
3596
3597 Returns Draw_Looper if set, or nullptr.
3598 Does not alter Draw_Looper Reference_Count.
3599
3600 #Return Draw_Looper if previously set, nullptr otherwise ##
3601
3602 #Example
3603 void draw(SkCanvas* canvas) {
3604 SkPaint paint;
3605 SkDebugf("nullptr %c= draw looper\n", paint.getDrawLooper() ? '!' : '=');
3606 SkLayerDrawLooper::Builder looperBuilder;
3607 paint.setDrawLooper(looperBuilder.detach());
3608 SkDebugf("nullptr %c= draw looper\n", paint.getDrawLooper() ? '!' : '=');
3609 }
3610
3611 #StdOut
3612 nullptr == draw looper
3613 nullptr != draw looper
3614 ##
3615 ##
3616
3617##
3618
3619#Method sk_sp<SkDrawLooper> refDrawLooper() const
3620
3621 Returns Draw_Looper if set, or nullptr.
3622 Increases Draw_Looper Reference_Count by one.
3623
3624 #Return Draw_Looper if previously set, nullptr otherwise ##
3625
3626 #Example
3627 void draw(SkCanvas* canvas) {
3628 SkPaint paint1, paint2;
3629 SkLayerDrawLooper::Builder looperBuilder;
3630 paint1.setDrawLooper(looperBuilder.detach());
3631 SkDebugf("draw looper unique: %s\n", paint1.getDrawLooper()->unique() ? "true" : "false");
3632 paint2.setDrawLooper(paint1.refDrawLooper());
3633 SkDebugf("draw looper unique: %s\n", paint1.getDrawLooper()->unique() ? "true" : "false");
3634 }
3635
3636 #StdOut
3637 draw looper unique: true
3638 draw looper unique: false
3639 ##
3640 ##
3641
3642##
3643
3644#Method SkDrawLooper* getLooper() const
3645
3646Deprecated.
3647
3648#Deprecated
3649(see bug.skia.org/6259)
3650#Deprecated ##
3651
3652#Return Draw_Looper if previously set, nullptr otherwise ##
3653##
3654
3655#Method void setDrawLooper(sk_sp<SkDrawLooper> drawLooper)
3656
Cary Clark6fc50412017-09-21 12:31:06 -04003657Sets Draw_Looper to drawLooper, decreasing Reference_Count of the previous
3658drawLooper. Pass nullptr to clear Draw_Looper and leave Draw_Looper effect on
3659drawing unaltered.
3660
3661Increments drawLooper Reference_Count by one.
Cary Clark8032b982017-07-28 11:04:54 -04003662
Cary Clarka523d2d2017-08-30 08:58:10 -04003663 #Param drawLooper iterates through drawing one or more time, altering Paint ##
Cary Clark8032b982017-07-28 11:04:54 -04003664
3665 #Example
3666 #Height 128
3667 void draw(SkCanvas* canvas) {
3668 SkPaint paint;
3669 paint.setDrawLooper(SkBlurDrawLooper::Make(0x7FFF0000, 4, -5, -10));
3670 paint.setStyle(SkPaint::kStroke_Style);
3671 paint.setStrokeWidth(10);
3672 paint.setAntiAlias(true);
3673 paint.setColor(0x7f0000ff);
3674 canvas->drawCircle(70, 70, 50, paint);
3675 }
3676 ##
3677
3678##
3679
3680#Method void setLooper(sk_sp<SkDrawLooper> drawLooper)
3681
3682Deprecated.
3683
3684#Deprecated
3685(see bug.skia.org/6259)
3686#Deprecated ##
3687
3688#Param drawLooper sets Draw_Looper to drawLooper ##
3689
3690##
3691
3692#Topic ##
3693# ------------------------------------------------------------------------------
3694#Topic Text_Align
3695
3696#Enum Align
3697#Code
3698 enum Align {
3699 kLeft_Align,
3700 kCenter_Align,
3701 kRight_Align,
3702 };
3703##
3704
3705Align adjusts the text relative to the text position.
Cary Clarkce101242017-09-01 15:51:02 -04003706Align affects Glyphs drawn with: SkCanvas::drawText, SkCanvas::drawPosText,
Cary Clark8032b982017-07-28 11:04:54 -04003707SkCanvas::drawPosTextH, SkCanvas::drawTextOnPath,
3708SkCanvas::drawTextOnPathHV, SkCanvas::drawTextRSXform, SkCanvas::drawTextBlob,
3709and SkCanvas::drawString;
Cary Clarkce101242017-09-01 15:51:02 -04003710as well as calls that place text Glyphs like getTextWidths and getTextPath.
Cary Clark8032b982017-07-28 11:04:54 -04003711
3712The text position is set by the font for both horizontal and vertical text.
3713Typically, for horizontal text, the position is to the left side of the glyph on the
3714base line; and for vertical text, the position is the horizontal center of the glyph
3715at the caps height.
3716
3717Align adjusts the glyph position to center it or move it to abut the position
3718using the metrics returned by the font.
3719
3720Align defaults to kLeft_Align.
3721
3722#Const kLeft_Align 0
3723 Leaves the glyph at the position computed by the font offset by the text position.
3724##
3725
3726#Const kCenter_Align 1
3727 Moves the glyph half its width if Flags has kVerticalText_Flag clear, and
3728 half its height if Flags has kVerticalText_Flag set.
3729##
3730
3731#Const kRight_Align 2
3732 Moves the glyph by its width if Flags has kVerticalText_Flag clear,
3733 and by its height if Flags has kVerticalText_Flag set.
3734##
3735
3736#Enum ##
3737
3738#Enum
3739
3740#Code
3741 enum {
Cary Clarkbad5ad72017-08-03 17:14:08 -04003742 kAlignCount = 3,
Cary Clark8032b982017-07-28 11:04:54 -04003743 };
3744##
3745
3746#Const kAlignCount 3
3747 The number of different Text_Align values defined.
3748##
3749
3750#Enum ##
3751
3752#Example
3753 #Height 160
3754 #Description
3755 Each position separately moves the glyph in drawPosText.
3756 ##
3757 void draw(SkCanvas* canvas) {
3758 SkPaint paint;
3759 paint.setTextSize(40);
3760 SkPoint position[] = {{100, 50}, {150, 40}};
3761 for (SkPaint::Align a : { SkPaint::kLeft_Align,
3762 SkPaint::kCenter_Align,
3763 SkPaint::kRight_Align}) {
3764 paint.setTextAlign(a);
3765 canvas->drawPosText("Aa", 2, position, paint);
3766 canvas->translate(0, 50);
3767 }
3768 }
3769##
3770
3771#Example
3772 #Height 160
3773 #Description
3774 Vertical_Text treats kLeft_Align as top align, and kRight_Align as bottom align.
3775 ##
3776 void draw(SkCanvas* canvas) {
3777 SkPaint paint;
3778 paint.setTextSize(40);
3779 paint.setVerticalText(true);
3780 for (SkPaint::Align a : { SkPaint::kLeft_Align,
3781 SkPaint::kCenter_Align,
3782 SkPaint::kRight_Align }) {
3783 paint.setTextAlign(a);
3784 canvas->drawString("Aa", 50, 80, paint);
3785 canvas->translate(50, 0);
3786 }
3787 }
3788##
3789
3790#Method Align getTextAlign() const
3791
3792 Returns Text_Align.
3793 Returns kLeft_Align if Text_Align has not been set.
3794
3795 #Return text placement relative to position ##
3796
3797 #Example
3798 SkPaint paint;
3799 SkDebugf("kLeft_Align %c= default\n", SkPaint::kLeft_Align == paint.getTextAlign() ? '=' : '!');
3800
3801 #StdOut
3802 kLeft_Align == default
3803 ##
3804 ##
3805##
3806
3807#Method void setTextAlign(Align align)
3808
3809 Sets Text_Align to align.
3810 Has no effect if align is an invalid value.
3811
3812 #Param align text placement relative to position ##
3813
3814 #Example
3815 #Height 160
3816 #Description
3817 Text is left-aligned by default, and then set to center. Setting the
3818 alignment out of range has no effect.
3819 ##
3820 void draw(SkCanvas* canvas) {
3821 SkPaint paint;
3822 paint.setTextSize(40);
3823 canvas->drawString("Aa", 100, 50, paint);
3824 paint.setTextAlign(SkPaint::kCenter_Align);
3825 canvas->drawString("Aa", 100, 100, paint);
3826 paint.setTextAlign((SkPaint::Align) SkPaint::kAlignCount);
3827 canvas->drawString("Aa", 100, 150, paint);
3828 }
3829 ##
3830
3831##
3832
3833#Topic ##
3834# ------------------------------------------------------------------------------
3835#Topic Text_Size
3836
3837Text_Size adjusts the overall text size in points.
3838Text_Size can be set to any positive value or zero.
3839Text_Size defaults to 12.
3840Set SkPaintDefaults_TextSize at compile time to change the default setting.
3841
3842#Example
3843#Height 135
3844 void draw(SkCanvas* canvas) {
3845 SkPaint paint;
3846 canvas->drawString("12 point", 10, 20, paint);
3847 paint.setTextSize(24);
3848 canvas->drawString("24 point", 10, 60, paint);
3849 paint.setTextSize(48);
3850 canvas->drawString("48 point", 10, 120, paint);
3851 }
3852##
3853
3854#Method SkScalar getTextSize() const
3855
3856 Returns Text_Size in points.
3857
3858 #Return typographic height of text ##
3859
3860 #Example
3861 SkPaint paint;
3862 SkDebugf("12 %c= default text size\n", 12 == paint.getTextSize() ? '=' : '!');
3863 ##
3864
3865##
3866
3867#Method void setTextSize(SkScalar textSize)
3868
3869 Sets Text_Size in points.
3870 Has no effect if textSize is not greater than or equal to zero.
3871
3872 #Param textSize typographic height of text ##
3873
3874 #Example
3875 SkPaint paint;
3876 SkDebugf("12 %c= text size\n", 12 == paint.getTextSize() ? '=' : '!');
3877 paint.setTextSize(-20);
3878 SkDebugf("12 %c= text size\n", 12 == paint.getTextSize() ? '=' : '!');
3879 ##
3880
3881##
3882
3883#Topic ##
3884# ------------------------------------------------------------------------------
3885#Topic Text_Scale_X
3886
3887Text_Scale_X adjusts the text horizontal scale.
3888Text scaling approximates condensed and expanded type faces when the actual face
3889is not available.
3890Text_Scale_X can be set to any value.
3891Text_Scale_X defaults to 1.
3892
3893#Example
3894#Height 128
3895 void draw(SkCanvas* canvas) {
3896 SkPaint paint;
3897 paint.setAntiAlias(true);
3898 paint.setTextSize(24);
3899 paint.setTextScaleX(.8f);
3900 canvas->drawString("narrow", 10, 20, paint);
3901 paint.setTextScaleX(1);
3902 canvas->drawString("normal", 10, 60, paint);
3903 paint.setTextScaleX(1.2f);
3904 canvas->drawString("wide", 10, 100, paint);
3905 }
3906##
3907
3908#Method SkScalar getTextScaleX() const
3909
3910 Returns Text_Scale_X.
3911 Default value is 1.
3912
3913 #Return text horizontal scale ##
3914
3915 #Example
3916 SkPaint paint;
3917 SkDebugf("1 %c= default text scale x\n", 1 == paint.getTextScaleX() ? '=' : '!');
3918 ##
3919
3920##
3921
3922
3923#Method void setTextScaleX(SkScalar scaleX)
3924
3925 Sets Text_Scale_X.
3926 Default value is 1.
3927
3928 #Param scaleX text horizontal scale ##
3929
3930 #Example
3931 SkPaint paint;
3932 paint.setTextScaleX(0.f / 0.f);
3933 SkDebugf("text scale %s-a-number\n", SkScalarIsNaN(paint.getTextScaleX()) ? "not" : "is");
3934 ##
3935
3936##
3937
3938#Topic ##
3939
3940#Topic Text_Skew_X
3941
3942
3943Text_Skew_X adjusts the text horizontal slant.
3944Text skewing approximates italic and oblique type faces when the actual face
3945is not available.
3946Text_Skew_X can be set to any value.
3947Text_Skew_X defaults to 0.
3948
3949#Example
3950#Height 128
3951 void draw(SkCanvas* canvas) {
3952 SkPaint paint;
3953 paint.setAntiAlias(true);
3954 paint.setTextSize(24);
3955 paint.setTextSkewX(-.25f);
3956 canvas->drawString("right-leaning", 10, 100, paint);
3957 paint.setTextSkewX(0);
3958 canvas->drawString("normal", 10, 60, paint);
3959 paint.setTextSkewX(.25f);
3960 canvas->drawString("left-leaning", 10, 20, paint);
3961 }
3962##
3963
3964#Method SkScalar getTextSkewX() const
3965
3966 Returns Text_Skew_X.
3967 Default value is zero.
3968
3969 #Return additional shear in x-axis relative to y-axis ##
3970
3971 #Example
3972 SkPaint paint;
3973 SkDebugf("0 %c= default text skew x\n", 0 == paint.getTextSkewX() ? '=' : '!');
3974 ##
3975
3976##
3977
3978#Method void setTextSkewX(SkScalar skewX)
3979
3980 Sets Text_Skew_X.
3981 Default value is zero.
3982
3983 #Param skewX additional shear in x-axis relative to y-axis ##
3984
3985 #Example
3986 SkPaint paint;
3987 paint.setTextScaleX(1.f / 0.f);
3988 SkDebugf("text scale %s-finite\n", SkScalarIsFinite(paint.getTextScaleX()) ? "is" : "not");
3989 ##
3990
3991##
3992
3993#Topic ##
3994
3995# ------------------------------------------------------------------------------
3996#Topic Text_Encoding
3997
3998#Enum TextEncoding
3999
4000#Code
4001 enum TextEncoding {
4002 kUTF8_TextEncoding,
4003 kUTF16_TextEncoding,
4004 kUTF32_TextEncoding,
Cary Clarkbad5ad72017-08-03 17:14:08 -04004005 kGlyphID_TextEncoding,
Cary Clark8032b982017-07-28 11:04:54 -04004006 };
4007##
4008
Cary Clark6fc50412017-09-21 12:31:06 -04004009TextEncoding determines whether text specifies character codes and their encoded
Cary Clarkbc5697d2017-10-04 14:31:33 -04004010size, or glyph indices. Characters are encoded as specified by the
Cary Clark6fc50412017-09-21 12:31:06 -04004011#A Unicode standard # http://unicode.org/standard/standard.html ##
4012.
4013
Cary Clark8032b982017-07-28 11:04:54 -04004014Character codes encoded size are specified by UTF-8, UTF-16, or UTF-32.
Cary Clarkbc5697d2017-10-04 14:31:33 -04004015All character code formats are able to represent all of Unicode, differing only
Cary Clark8032b982017-07-28 11:04:54 -04004016in the total storage required.
4017
Cary Clark6fc50412017-09-21 12:31:06 -04004018#A UTF-8 (RFC 3629) # https://tools.ietf.org/html/rfc3629 ##
4019 encodes each character as one or more 8-bit bytes.
4020
4021#A UTF-16 (RFC 2781) # https://tools.ietf.org/html/rfc2781 ##
4022 encodes each character as one or two 16-bit words.
4023
4024#A UTF-32 # http://www.unicode.org/versions/Unicode5.0.0/ch03.pdf ##
4025 encodes each character as one 32-bit word.
Cary Clark8032b982017-07-28 11:04:54 -04004026
4027Font_Manager uses font data to convert character code points into glyph indices.
4028A glyph index is a 16-bit word.
4029
4030TextEncoding is set to kUTF8_TextEncoding by default.
4031
4032#Const kUTF8_TextEncoding 0
4033Uses bytes to represent UTF-8 or ASCII.
4034##
4035#Const kUTF16_TextEncoding 1
4036Uses two byte words to represent most of Unicode.
4037##
4038#Const kUTF32_TextEncoding 2
4039Uses four byte words to represent all of Unicode.
4040##
4041#Const kGlyphID_TextEncoding 3
4042Uses two byte words to represent glyph indices.
4043##
4044
4045#Enum ##
4046
4047#Example
4048#Height 128
4049#Description
Cary Clarkbc5697d2017-10-04 14:31:33 -04004050First line is encoded in UTF-8.
4051Second line is encoded in UTF-16.
4052Third line is encoded in UTF-32.
Cary Clark8032b982017-07-28 11:04:54 -04004053Fourth line has 16 bit glyph indices.
4054##
4055void draw(SkCanvas* canvas) {
4056 SkPaint paint;
4057 const char hello8[] = "Hello" "\xE2" "\x98" "\xBA";
4058 const uint16_t hello16[] = { 'H', 'e', 'l', 'l', 'o', 0x263A };
4059 const uint32_t hello32[] = { 'H', 'e', 'l', 'l', 'o', 0x263A };
4060 paint.setTextSize(24);
4061 canvas->drawText(hello8, sizeof(hello8) - 1, 10, 30, paint);
4062 paint.setTextEncoding(SkPaint::kUTF16_TextEncoding);
4063 canvas->drawText(hello16, sizeof(hello16), 10, 60, paint);
4064 paint.setTextEncoding(SkPaint::kUTF32_TextEncoding);
4065 canvas->drawText(hello32, sizeof(hello32), 10, 90, paint);
4066 uint16_t glyphs[SK_ARRAY_COUNT(hello32)];
4067 paint.textToGlyphs(hello32, sizeof(hello32), glyphs);
4068 paint.setTextEncoding(SkPaint::kGlyphID_TextEncoding);
4069 canvas->drawText(glyphs, sizeof(glyphs), 10, 120, paint);
4070}
4071##
4072
4073#Method TextEncoding getTextEncoding() const
4074
4075 Returns Text_Encoding.
4076 Text_Encoding determines how character code points are mapped to font glyph indices.
4077
4078 #Return one of: kUTF8_TextEncoding, kUTF16_TextEncoding, kUTF32_TextEncoding, or
4079 kGlyphID_TextEncoding
4080 ##
4081
4082 #Example
4083 SkPaint paint;
4084 SkDebugf("kUTF8_TextEncoding %c= text encoding\n",
4085 SkPaint::kUTF8_TextEncoding == paint.getTextEncoding() ? '=' : '!');
4086 paint.setTextEncoding(SkPaint::kGlyphID_TextEncoding);
4087 SkDebugf("kGlyphID_TextEncoding %c= text encoding\n",
4088 SkPaint::kGlyphID_TextEncoding == paint.getTextEncoding() ? '=' : '!');
4089
4090 #StdOut
4091 kUTF8_TextEncoding == text encoding
4092 kGlyphID_TextEncoding == text encoding
4093 ##
4094 ##
4095
4096##
4097
4098
4099#Method void setTextEncoding(TextEncoding encoding)
4100
4101 Sets Text_Encoding to encoding.
4102 Text_Encoding determines how character code points are mapped to font glyph indices.
4103 Invalid values for encoding are ignored.
4104
4105 #Param encoding one of: kUTF8_TextEncoding, kUTF16_TextEncoding, kUTF32_TextEncoding, or
Cary Clark579985c2017-07-31 11:48:27 -04004106 kGlyphID_TextEncoding
4107 #Param ##
Cary Clark8032b982017-07-28 11:04:54 -04004108
4109 #Example
4110 SkPaint paint;
4111 paint.setTextEncoding((SkPaint::TextEncoding) 4);
4112 SkDebugf("4 %c= text encoding\n", 4 == paint.getTextEncoding() ? '=' : '!');
4113
4114 #StdOut
4115 4 != text encoding
4116 ##
4117 ##
4118
4119##
4120
4121#Topic ##
4122# ------------------------------------------------------------------------------
4123#Topic Font_Metrics
4124
Cary Clarkce101242017-09-01 15:51:02 -04004125Font_Metrics describe dimensions common to the Glyphs in Typeface.
Cary Clark8032b982017-07-28 11:04:54 -04004126The dimensions are computed by Font_Manager from font data and do not take
4127Paint settings other than Text_Size into account.
4128
4129Font dimensions specify the anchor to the left of the glyph at baseline as the origin.
4130X-axis values to the left of the glyph are negative, and to the right of the left glyph edge
4131are positive.
4132Y-axis values above the baseline are negative, and below the baseline are positive.
4133
4134#Example
4135#Width 512
4136void draw(SkCanvas* canvas) {
4137 SkPaint paint;
4138 paint.setAntiAlias(true);
4139 paint.setTextSize(120);
4140 SkPaint::FontMetrics fm;
4141 SkScalar lineHeight = paint.getFontMetrics(&fm);
4142 SkPoint pt = { 70, 180 };
4143 canvas->drawString("M", pt.fX, pt.fY, paint);
4144 canvas->drawLine(pt.fX, pt.fY, pt.fX, pt.fY + fm.fTop, paint);
4145 SkScalar ascent = pt.fY + fm.fAscent;
4146 canvas->drawLine(pt.fX - 25, ascent, pt.fX - 25, ascent + lineHeight, paint);
4147 canvas->drawLine(pt.fX - 50, pt.fY, pt.fX - 50, pt.fY + fm.fDescent, paint);
4148 canvas->drawLine(pt.fX + 100, pt.fY, pt.fX + 100, pt.fY + fm.fAscent, paint);
4149 canvas->drawLine(pt.fX + 125, pt.fY, pt.fX + 125, pt.fY - fm.fXHeight, paint);
4150 canvas->drawLine(pt.fX + 150, pt.fY, pt.fX + 150, pt.fY - fm.fCapHeight, paint);
4151 canvas->drawLine(pt.fX + 5, pt.fY, pt.fX + 5, pt.fY + fm.fBottom, paint);
4152 SkScalar xmin = pt.fX + fm.fXMin;
4153 canvas->drawLine(xmin, pt.fY + 60, xmin + fm.fMaxCharWidth, pt.fY + 60, paint);
4154 canvas->drawLine(xmin, pt.fY - 145, pt.fX, pt.fY - 145, paint);
4155 canvas->drawLine(pt.fX + fm.fXMax, pt.fY - 160, pt.fX, pt.fY - 160, paint);
4156 SkScalar upos = pt.fY + fm.fUnderlinePosition;
4157 canvas->drawLine(pt.fX + 25, upos, pt.fX + 130, upos, paint);
4158 SkScalar urad = fm.fUnderlineThickness / 2;
4159 canvas->drawLine(pt.fX + 130, upos - urad, pt.fX + 160, upos - urad, paint);
4160 canvas->drawLine(pt.fX + 130, upos + urad, pt.fX + 160, upos + urad, paint);
4161 paint.setTextSize(12);
4162 canvas->drawString("x-min", pt.fX - 50, pt.fY - 148, paint);
4163 canvas->drawString("x-max", pt.fX + 140, pt.fY - 150, paint);
4164 canvas->drawString("max char width", pt.fX + 120, pt.fY + 57, paint);
4165 canvas->drawString("underline position", pt.fX + 30, pt.fY + 22, paint);
4166 canvas->drawString("underline thickness", pt.fX + 162, pt.fY + 13, paint);
4167 canvas->rotate(-90);
4168 canvas->drawString("descent", -pt.fY - 30, pt.fX - 54, paint);
4169 canvas->drawString("line height", -pt.fY, pt.fX - 29, paint);
4170 canvas->drawString("top", -pt.fY + 30, pt.fX - 4, paint);
4171 canvas->drawString("ascent", -pt.fY, pt.fX + 110, paint);
4172 canvas->drawString("x-height", -pt.fY, pt.fX + 135, paint);
4173 canvas->drawString("cap-height", -pt.fY, pt.fX + 160, paint);
4174 canvas->drawString("bottom", -pt.fY - 50, pt.fX + 15, paint);
4175}
4176##
4177
4178#Struct FontMetrics
4179
4180#Code
4181 struct FontMetrics {
4182 enum FontMetricsFlags {
4183 kUnderlineThicknessIsValid_Flag = 1 << 0,
4184 kUnderlinePositionIsValid_Flag = 1 << 1,
4185 kStrikeoutThicknessIsValid_Flag = 1 << 2,
4186 kStrikeoutPositionIsValid_Flag = 1 << 3,
4187 };
4188
4189 uint32_t fFlags;
4190 SkScalar fTop;
4191 SkScalar fAscent;
4192 SkScalar fDescent;
4193 SkScalar fBottom;
4194 SkScalar fLeading;
4195 SkScalar fAvgCharWidth;
4196 SkScalar fMaxCharWidth;
4197 SkScalar fXMin;
4198 SkScalar fXMax;
4199 SkScalar fXHeight;
4200 SkScalar fCapHeight;
4201 SkScalar fUnderlineThickness;
4202 SkScalar fUnderlinePosition;
4203 SkScalar fStrikeoutThickness;
4204 SkScalar fStrikeoutPosition;
4205
4206 bool hasUnderlineThickness(SkScalar* thickness) const;
4207 bool hasUnderlinePosition(SkScalar* position) const;
4208 bool hasStrikeoutThickness(SkScalar* thickness) const;
4209 bool hasStrikeoutPosition(SkScalar* position) const;
4210 };
4211##
4212
Cary Clark154beea2017-10-26 07:58:48 -04004213 FontMetrics is filled out by getFontMetrics. FontMetrics contents reflect the values
4214 computed by Font_Manager using Typeface. Values are set to zero if they are
4215 not available.
Cary Clarke4aa3712017-09-15 02:56:12 -04004216
Cary Clark154beea2017-10-26 07:58:48 -04004217 fUnderlineThickness and fUnderlinePosition have a bit set in fFlags if their values
4218 are valid, since their value may be zero.
4219
4220 fStrikeoutThickness and fStrikeoutPosition have a bit set in fFlags if their values
4221 are valid, since their value may be zero.
4222
4223 #Enum FontMetricsFlags
Cary Clarke4aa3712017-09-15 02:56:12 -04004224
Cary Clark8032b982017-07-28 11:04:54 -04004225 #Code
4226 enum FontMetricsFlags {
4227 kUnderlineThicknessIsValid_Flag = 1 << 0,
4228 kUnderlinePositionIsValid_Flag = 1 << 1,
4229 kStrikeoutThicknessIsValid_Flag = 1 << 2,
4230 kStrikeoutPositionIsValid_Flag = 1 << 3,
4231 };
4232 ##
4233
Cary Clark154beea2017-10-26 07:58:48 -04004234 FontMetricsFlags are set in fFlags when underline and strikeout metrics are valid;
4235 the underline or strikeout metric may be valid and zero.
4236 Fonts with embedded bitmaps may not have valid underline or strikeout metrics.
4237
Cary Clark8032b982017-07-28 11:04:54 -04004238 #Const kUnderlineThicknessIsValid_Flag 0x0001
4239 Set if fUnderlineThickness is valid.
4240 ##
4241 #Const kUnderlinePositionIsValid_Flag 0x0002
4242 Set if fUnderlinePosition is valid.
4243 ##
4244 #Const kStrikeoutThicknessIsValid_Flag 0x0004
4245 Set if fStrikeoutThickness is valid.
4246 ##
4247 #Const kStrikeoutPositionIsValid_Flag 0x0008
4248 Set if fStrikeoutPosition is valid.
4249 ##
4250
4251 #Enum ##
4252
4253 #Member uint32_t fFlags
4254 fFlags is set when underline metrics are valid.
4255 ##
4256
4257 #Member SkScalar fTop
4258 Largest height for any glyph.
4259 A measure from the baseline, and is less than or equal to zero.
4260 ##
4261
4262 #Member SkScalar fAscent
4263 Recommended distance above the baseline to reserve for a line of text.
4264 A measure from the baseline, and is less than or equal to zero.
4265 ##
4266
4267 #Member SkScalar fDescent
4268 Recommended distance below the baseline to reserve for a line of text.
4269 A measure from the baseline, and is greater than or equal to zero.
4270 ##
4271
4272 #Member SkScalar fBottom
4273 Greatest extent below the baseline for any glyph.
4274 A measure from the baseline, and is greater than or equal to zero.
4275 ##
4276
4277 #Member SkScalar fLeading
4278 Recommended distance to add between lines of text.
4279 Greater than or equal to zero.
4280 ##
4281
4282 #Member SkScalar fAvgCharWidth
4283 Average character width, if it is available.
4284 Zero if no average width is stored in the font.
4285 ##
4286
4287 #Member SkScalar fMaxCharWidth
4288 Maximum character width.
4289 ##
4290
4291 #Member SkScalar fXMin
Cary Clarkce101242017-09-01 15:51:02 -04004292 Minimum bounding box x value for all Glyphs.
Cary Clark8032b982017-07-28 11:04:54 -04004293 Typically less than zero.
4294 ##
4295
4296 #Member SkScalar fXMax
Cary Clarkce101242017-09-01 15:51:02 -04004297 Maximum bounding box x value for all Glyphs.
Cary Clark8032b982017-07-28 11:04:54 -04004298 Typically greater than zero.
4299 ##
4300
4301 #Member SkScalar fXHeight
4302 Height of a lower-case 'x'.
4303 May be zero if no lower-case height is stored in the font.
4304 ##
4305
4306 #Member SkScalar fCapHeight
4307 Height of an upper-case letter.
4308 May be zero if no upper-case height is stored in the font.
4309 ##
4310
4311 #Member SkScalar fUnderlineThickness
4312 Underline thickness. If the metric
4313 is valid, the kUnderlineThicknessIsValid_Flag is set in fFlags.
4314 If kUnderlineThicknessIsValid_Flag is clear, fUnderlineThickness is zero.
4315 ##
4316
4317 #Member SkScalar fUnderlinePosition
4318 Underline position relative to the baseline.
4319 It may be negative, to draw the underline above the baseline, zero
4320 to draw the underline on the baseline, or positive to draw the underline
4321 below the baseline.
4322
4323 If the metric is valid, the kUnderlinePositionIsValid_Flag is set in fFlags.
4324 If kUnderlinePositionIsValid_Flag is clear, fUnderlinePosition is zero.
4325 ##
4326
4327 #Member SkScalar fStrikeoutThickness
4328 Strikeout thickness. If the metric
4329 is valid, the kStrikeoutThicknessIsValid_Flag is set in fFlags.
4330 If kStrikeoutThicknessIsValid_Flag is clear, fStrikeoutThickness is zero.
4331 ##
4332
4333 #Member SkScalar fStrikeoutPosition
4334 Strikeout position relative to the baseline.
4335 It may be negative, to draw the strikeout above the baseline, zero
4336 to draw the strikeout on the baseline, or positive to draw the strikeout
4337 below the baseline.
4338
4339 If the metric is valid, the kStrikeoutPositionIsValid_Flag is set in fFlags.
4340 If kStrikeoutPositionIsValid_Flag is clear, fStrikeoutPosition is zero.
4341 ##
4342
4343 #Method bool hasUnderlineThickness(SkScalar* thickness) const
4344
4345 If Font_Metrics has a valid underline thickness, return true, and set
Cary Clarkce101242017-09-01 15:51:02 -04004346 thickness to that value. If the underline thickness is not valid,
4347 return false, and ignore thickness.
Cary Clark8032b982017-07-28 11:04:54 -04004348
4349 #Param thickness storage for underline width ##
4350
4351 #Return true if font specifies underline width ##
4352
4353 #NoExample
4354 ##
4355 ##
4356
4357 #Method bool hasUnderlinePosition(SkScalar* position) const
4358
4359 If Font_Metrics has a valid underline position, return true, and set
Cary Clarkce101242017-09-01 15:51:02 -04004360 position to that value. If the underline position is not valid,
4361 return false, and ignore position.
Cary Clark8032b982017-07-28 11:04:54 -04004362
4363 #Param position storage for underline position ##
4364
4365 #Return true if font specifies underline position ##
4366
4367 #NoExample
4368 ##
4369 ##
4370
4371 #Method bool hasStrikeoutThickness(SkScalar* thickness) const
4372
4373 If Font_Metrics has a valid strikeout thickness, return true, and set
Cary Clarkce101242017-09-01 15:51:02 -04004374 thickness to that value. If the underline thickness is not valid,
4375 return false, and ignore thickness.
Cary Clark8032b982017-07-28 11:04:54 -04004376
4377 #Param thickness storage for strikeout width ##
4378
4379 #Return true if font specifies strikeout width ##
4380
4381 #NoExample
4382 ##
4383 ##
4384
4385 #Method bool hasStrikeoutPosition(SkScalar* position) const
4386
4387 If Font_Metrics has a valid strikeout position, return true, and set
Cary Clarkce101242017-09-01 15:51:02 -04004388 position to that value. If the underline position is not valid,
4389 return false, and ignore position.
Cary Clark8032b982017-07-28 11:04:54 -04004390
4391 #Param position storage for strikeout position ##
4392
4393 #Return true if font specifies strikeout position ##
4394
4395 #NoExample
4396 ##
4397 ##
4398
4399#Struct ##
4400
4401#Method SkScalar getFontMetrics(FontMetrics* metrics, SkScalar scale = 0) const
4402
4403 Returns Font_Metrics associated with Typeface.
4404 The return value is the recommended spacing between lines: the sum of metrics
4405 descent, ascent, and leading.
4406 If metrics is not nullptr, Font_Metrics is copied to metrics.
4407 Results are scaled by Text_Size but does not take into account
4408 dimensions required by Text_Scale_X, Text_Skew_X, Fake_Bold,
4409 Style_Stroke, and Path_Effect.
4410 Results can be additionally scaled by scale; a scale of zero
4411 is ignored.
4412
4413 #Param metrics storage for Font_Metrics from Typeface; may be nullptr ##
4414 #Param scale additional multiplier for returned values ##
4415
4416 #Return recommended spacing between lines ##
4417
4418 #Example
4419 #Height 128
4420 void draw(SkCanvas* canvas) {
4421 SkPaint paint;
4422 paint.setTextSize(32);
4423 SkScalar lineHeight = paint.getFontMetrics(nullptr);
4424 canvas->drawString("line 1", 10, 40, paint);
4425 canvas->drawString("line 2", 10, 40 + lineHeight, paint);
4426 paint.setStyle(SkPaint::kStroke_Style);
4427 paint.setStrokeWidth(10);
4428 lineHeight = paint.getFontMetrics(nullptr, 1.10f); // account for stroke height
4429 canvas->drawString("line 3", 120, 40, paint);
4430 canvas->drawString("line 4", 120, 40 + lineHeight, paint);
4431 }
4432 ##
4433
4434 #SeeAlso Text_Size Typeface Typeface_Methods
4435
4436##
4437
4438
4439#Method SkScalar getFontSpacing() const
4440
4441 Returns the recommended spacing between lines: the sum of metrics
4442 descent, ascent, and leading.
4443 Result is scaled by Text_Size but does not take into account
4444 dimensions required by stroking and Path_Effect.
Cary Clark579985c2017-07-31 11:48:27 -04004445 Returns the same result as getFontMetrics.
Cary Clark8032b982017-07-28 11:04:54 -04004446
4447 #Return recommended spacing between lines ##
4448
4449 #Example
4450 SkPaint paint;
4451 for (SkScalar textSize : { 12, 18, 24, 32 } ) {
4452 paint.setTextSize(textSize);
4453 SkDebugf("textSize: %g fontSpacing: %g\n", textSize, paint.getFontSpacing());
4454 }
4455
4456 #StdOut
4457 textSize: 12 fontSpacing: 13.9688
4458 textSize: 18 fontSpacing: 20.9531
4459 textSize: 24 fontSpacing: 27.9375
4460 textSize: 32 fontSpacing: 37.25
4461 ##
4462 ##
4463
4464##
4465
4466
4467#Method SkRect getFontBounds() const
4468
Cary Clarkce101242017-09-01 15:51:02 -04004469Returns the union of bounds of all Glyphs.
Cary Clark8032b982017-07-28 11:04:54 -04004470Returned dimensions are computed by Font_Manager from font data,
Cary Clark579985c2017-07-31 11:48:27 -04004471ignoring Hinting. Includes Text_Size, Text_Scale_X,
Cary Clark8032b982017-07-28 11:04:54 -04004472and Text_Skew_X, but not Fake_Bold or Path_Effect.
4473
4474If Text_Size is large, Text_Scale_X is one, and Text_Skew_X is zero,
Cary Clark579985c2017-07-31 11:48:27 -04004475returns the same bounds as Font_Metrics { FontMetrics::fXMin,
Cary Clark8032b982017-07-28 11:04:54 -04004476FontMetrics::fTop, FontMetrics::fXMax, FontMetrics::fBottom }.
4477
Cary Clarkce101242017-09-01 15:51:02 -04004478#Return union of bounds of all Glyphs ##
Cary Clark8032b982017-07-28 11:04:54 -04004479
4480#Example
4481 SkPaint paint;
4482 SkPaint::FontMetrics fm;
4483 paint.getFontMetrics(&fm);
4484 SkRect fb = paint.getFontBounds();
4485 SkDebugf("metrics bounds = { %g, %g, %g, %g }\n", fm.fXMin, fm.fTop, fm.fXMax, fm.fBottom );
4486 SkDebugf("font bounds = { %g, %g, %g, %g }\n", fb.fLeft, fb.fTop, fb.fRight, fm.fBottom );
4487
4488 #StdOut
4489 metrics bounds = { -12.2461, -14.7891, 21.5215, 5.55469 }
4490 font bounds = { -12.2461, -14.7891, 21.5215, 5.55469 }
4491 ##
4492##
4493
4494##
4495
4496#Topic ##
4497# ------------------------------------------------------------------------------
4498
4499#Method int textToGlyphs(const void* text, size_t byteLength,
4500 SkGlyphID glyphs[]) const
4501
4502Converts text into glyph indices.
4503Returns the number of glyph indices represented by text.
4504Text_Encoding specifies how text represents characters or glyphs.
4505glyphs may be nullptr, to compute the glyph count.
4506
Cary Clarkbc5697d2017-10-04 14:31:33 -04004507Does not check text for valid character codes or valid glyph indices.
Cary Clark8032b982017-07-28 11:04:54 -04004508
Cary Clark579985c2017-07-31 11:48:27 -04004509If byteLength equals zero, returns zero.
Cary Clark8032b982017-07-28 11:04:54 -04004510If byteLength includes a partial character, the partial character is ignored.
4511
4512If Text_Encoding is kUTF8_TextEncoding and
4513text contains an invalid UTF-8 sequence, zero is returned.
4514
Cary Clarkce101242017-09-01 15:51:02 -04004515#Param text character storage encoded with Text_Encoding ##
Cary Clark8032b982017-07-28 11:04:54 -04004516#Param byteLength length of character storage in bytes ##
4517#Param glyphs storage for glyph indices; may be nullptr ##
4518
4519#Return number of glyphs represented by text of length byteLength ##
4520
4521 #Example
4522 #Height 64
4523 void draw(SkCanvas* canvas) {
4524 SkPaint paint;
4525 const uint8_t utf8[] = { 0x24, 0xC2, 0xA2, 0xE2, 0x82, 0xAC, 0xC2, 0xA5, 0xC2, 0xA3 };
4526 std::vector<SkGlyphID> glyphs;
4527 int count = paint.textToGlyphs(utf8, sizeof(utf8), nullptr);
4528 glyphs.resize(count);
4529 (void) paint.textToGlyphs(utf8, sizeof(utf8), &glyphs.front());
4530 paint.setTextEncoding(SkPaint::kGlyphID_TextEncoding);
4531 paint.setTextSize(32);
4532 canvas->drawText(&glyphs.front(), glyphs.size() * sizeof(SkGlyphID), 10, 40, paint);
4533 }
4534 ##
4535
4536##
4537
4538#Method int countText(const void* text, size_t byteLength) const
4539
Cary Clarkce101242017-09-01 15:51:02 -04004540 Returns the number of Glyphs in text.
4541 Uses Text_Encoding to count the Glyphs.
Cary Clark8032b982017-07-28 11:04:54 -04004542 Returns the same result as textToGlyphs.
4543
Cary Clarkce101242017-09-01 15:51:02 -04004544#Param text character storage encoded with Text_Encoding ##
Cary Clark8032b982017-07-28 11:04:54 -04004545#Param byteLength length of character storage in bytes ##
4546
Cary Clarkce101242017-09-01 15:51:02 -04004547#Return number of Glyphs represented by text of length byteLength ##
Cary Clark8032b982017-07-28 11:04:54 -04004548
4549 #Example
4550 SkPaint paint;
4551 const uint8_t utf8[] = { 0x24, 0xC2, 0xA2, 0xE2, 0x82, 0xAC, 0xC2, 0xA5, 0xC2, 0xA3 };
4552 SkDebugf("count = %d\n", paint.countText(utf8, sizeof(utf8)));
4553
4554 #StdOut
4555 count = 5
4556 ##
4557 ##
4558##
4559
4560# ------------------------------------------------------------------------------
4561
4562#Method bool containsText(const void* text, size_t byteLength) const
4563
4564 Returns true if all text corresponds to a non-zero glyph index.
4565 Returns false if any characters in text are not supported in
4566 Typeface.
4567
Cary Clark579985c2017-07-31 11:48:27 -04004568 If Text_Encoding is kGlyphID_TextEncoding,
4569 returns true if all glyph indices in text are non-zero;
Cary Clark8032b982017-07-28 11:04:54 -04004570 does not check to see if text contains valid glyph indices for Typeface.
4571
Cary Clarkce101242017-09-01 15:51:02 -04004572 Returns true if byteLength is zero.
Cary Clark8032b982017-07-28 11:04:54 -04004573
Cary Clarkce101242017-09-01 15:51:02 -04004574 #Param text array of characters or Glyphs ##
Cary Clark8032b982017-07-28 11:04:54 -04004575 #Param byteLength number of bytes in text array ##
4576
4577 #Return true if all text corresponds to a non-zero glyph index ##
4578
4579 #Example
4580 #Description
4581 containsText succeeds for degree symbol, but cannot find a glyph index
4582 corresponding to the Unicode surrogate code point.
4583 ##
4584 SkPaint paint;
4585 const uint16_t goodChar = 0x00B0; // degree symbol
4586 const uint16_t badChar = 0xD800; // Unicode surrogate
4587 paint.setTextEncoding(SkPaint::kUTF16_TextEncoding);
4588 SkDebugf("0x%04x %c= has char\n", goodChar,
4589 paint.containsText(&goodChar, 2) ? '=' : '!');
4590 SkDebugf("0x%04x %c= has char\n", badChar,
4591 paint.containsText(&badChar, 2) ? '=' : '!');
4592
4593 #StdOut
4594 0x00b0 == has char
4595 0xd800 != has char
4596 ##
4597 ##
4598
4599 #Example
4600 #Description
4601 containsText returns true that glyph index is greater than zero, not
4602 that it corresponds to an entry in Typeface.
4603 ##
4604 SkPaint paint;
4605 const uint16_t goodGlyph = 511;
4606 const uint16_t zeroGlyph = 0;
4607 const uint16_t badGlyph = 65535; // larger than glyph count in font
4608 paint.setTextEncoding(SkPaint::kGlyphID_TextEncoding);
4609 SkDebugf("0x%04x %c= has glyph\n", goodGlyph,
4610 paint.containsText(&goodGlyph, 2) ? '=' : '!');
4611 SkDebugf("0x%04x %c= has glyph\n", zeroGlyph,
4612 paint.containsText(&zeroGlyph, 2) ? '=' : '!');
4613 SkDebugf("0x%04x %c= has glyph\n", badGlyph,
4614 paint.containsText(&badGlyph, 2) ? '=' : '!');
4615
4616 #StdOut
4617 0x01ff == has glyph
4618 0x0000 != has glyph
4619 0xffff == has glyph
4620 ##
4621 ##
4622
4623#SeeAlso setTextEncoding Typeface
4624
4625##
4626
4627# ------------------------------------------------------------------------------
4628
4629#Method void glyphsToUnichars(const SkGlyphID glyphs[],
4630 int count, SkUnichar text[]) const
4631
4632 Converts glyphs into text if possible.
4633 Glyph values without direct Unicode equivalents are mapped to zero.
4634 Uses the Typeface, but is unaffected
4635 by Text_Encoding; the text values returned are equivalent to kUTF32_TextEncoding.
4636
4637 Only supported on platforms that use FreeType as the Font_Engine.
4638
4639 #Param glyphs array of indices into font ##
4640 #Param count length of glyph array ##
4641 #Param text storage for character codes, one per glyph ##
4642
4643 #Example
4644 #Height 64
4645 #Description
4646 Convert UTF-8 text to glyphs; then convert glyphs to Unichar code points.
4647 ##
4648 void draw(SkCanvas* canvas) {
4649 SkPaint paint;
4650 const char hello[] = "Hello!";
4651 const int count = sizeof(hello) - 1;
4652 SkGlyphID glyphs[count];
4653 if (count != paint.textToGlyphs(hello, count, glyphs)) {
4654 return;
4655 }
4656 SkUnichar unichars[count];
4657 paint.glyphsToUnichars(glyphs, count, unichars);
4658 paint.setTextEncoding(SkPaint::kUTF32_TextEncoding);
4659 canvas->drawText(unichars, sizeof(unichars), 10, 30, paint);
4660 }
4661 ##
4662
4663##
4664
4665# ------------------------------------------------------------------------------
4666#Topic Measure_Text
4667
4668#Method SkScalar measureText(const void* text, size_t length, SkRect* bounds) const
4669
4670 Returns the advance width of text if kVerticalText_Flag is clear,
4671 and the height of text if kVerticalText_Flag is set.
4672 The advance is the normal distance to move before drawing additional text.
4673 Uses Text_Encoding to decode text, Typeface to get the font metrics,
4674 and Text_Size, Text_Scale_X, Text_Skew_X, Stroke_Width, and
4675 Path_Effect to scale the metrics and bounds.
4676 Returns the bounding box of text if bounds is not nullptr.
4677 The bounding box is computed as if the text was drawn at the origin.
4678
4679 #Param text character codes or glyph indices to be measured ##
4680 #Param length number of bytes of text to measure ##
4681 #Param bounds returns bounding box relative to (0, 0) if not nullptr ##
4682
4683 #Return advance width or height ##
4684
4685 #Example
4686 #Height 64
4687 void draw(SkCanvas* canvas) {
4688 SkPaint paint;
4689 paint.setAntiAlias(true);
4690 paint.setTextSize(50);
4691 const char str[] = "ay^jZ";
4692 const int count = sizeof(str) - 1;
4693 canvas->drawText(str, count, 25, 50, paint);
4694 SkRect bounds;
4695 paint.measureText(str, count, &bounds);
4696 canvas->translate(25, 50);
4697 paint.setStyle(SkPaint::kStroke_Style);
4698 canvas->drawRect(bounds, paint);
4699 }
4700 ##
4701
4702##
4703
4704#Method SkScalar measureText(const void* text, size_t length) const
4705
4706 Returns the advance width of text if kVerticalText_Flag is clear,
4707 and the height of text if kVerticalText_Flag is set.
4708 The advance is the normal distance to move before drawing additional text.
4709 Uses Text_Encoding to decode text, Typeface to get the font metrics,
4710 and Text_Size to scale the metrics.
4711 Does not scale the advance or bounds by Fake_Bold or Path_Effect.
4712
4713 #Param text character codes or glyph indices to be measured ##
4714 #Param length number of bytes of text to measure ##
4715
4716 #Return advance width or height ##
4717
4718 #Example
4719 SkPaint paint;
4720 SkDebugf("default width = %g\n", paint.measureText("!", 1));
4721 paint.setTextSize(paint.getTextSize() * 2);
4722 SkDebugf("double width = %g\n", paint.measureText("!", 1));
4723
4724 #StdOut
4725 default width = 5
4726 double width = 10
4727 ##
4728 ##
4729
4730##
4731
4732#Method size_t breakText(const void* text, size_t length, SkScalar maxWidth,
Cary Clark73fa9722017-08-29 17:36:51 -04004733 SkScalar* measuredWidth = nullptr) const
Cary Clark8032b982017-07-28 11:04:54 -04004734
4735 Returns the bytes of text that fit within maxWidth.
4736 If kVerticalText_Flag is clear, the text fragment fits if its advance width is less than or
4737 equal to maxWidth.
4738 If kVerticalText_Flag is set, the text fragment fits if its advance height is less than or
4739 equal to maxWidth.
4740 Measures only while the advance is less than or equal to maxWidth.
4741 Returns the advance or the text fragment in measuredWidth if it not nullptr.
4742 Uses Text_Encoding to decode text, Typeface to get the font metrics,
4743 and Text_Size to scale the metrics.
4744 Does not scale the advance or bounds by Fake_Bold or Path_Effect.
4745
4746 #Param text character codes or glyph indices to be measured ##
4747 #Param length number of bytes of text to measure ##
4748 #Param maxWidth advance limit; text is measured while advance is less than maxWidth ##
4749 #Param measuredWidth returns the width of the text less than or equal to maxWidth ##
4750 #Return bytes of text that fit, always less than or equal to length ##
4751
4752 #Example
4753 #Description
4754 Line under "Breakfast" shows desired width, shorter than available characters.
4755 Line under "Bre" shows measured width after breaking text.
4756 ##
4757 #Height 128
4758 #Width 280
4759 void draw(SkCanvas* canvas) {
4760 SkPaint paint;
4761 paint.setAntiAlias(true);
4762 paint.setTextSize(50);
4763 const char str[] = "Breakfast";
4764 const int count = sizeof(str) - 1;
4765 canvas->drawText(str, count, 25, 50, paint);
4766 SkScalar measuredWidth;
4767 int partialBytes = paint.breakText(str, count, 100, &measuredWidth);
4768 canvas->drawText(str, partialBytes, 25, 100, paint);
4769 canvas->drawLine(25, 60, 25 + 100, 60, paint);
4770 canvas->drawLine(25, 110, 25 + measuredWidth, 110, paint);
4771 }
4772 ##
4773
4774##
4775
4776#Method int getTextWidths(const void* text, size_t byteLength, SkScalar widths[],
Cary Clark73fa9722017-08-29 17:36:51 -04004777 SkRect bounds[] = nullptr) const
Cary Clark8032b982017-07-28 11:04:54 -04004778
4779 Retrieves the advance and bounds for each glyph in text, and returns
4780 the glyph count in text.
4781 Both widths and bounds may be nullptr.
4782 If widths is not nullptr, widths must be an array of glyph count entries.
4783 if bounds is not nullptr, bounds must be an array of glyph count entries.
4784 If kVerticalText_Flag is clear, widths returns the horizontal advance.
4785 If kVerticalText_Flag is set, widths returns the vertical advance.
4786 Uses Text_Encoding to decode text, Typeface to get the font metrics,
4787 and Text_Size to scale the widths and bounds.
4788 Does not scale the advance by Fake_Bold or Path_Effect.
4789 Does include Fake_Bold and Path_Effect in the bounds.
4790
4791 #Param text character codes or glyph indices to be measured ##
4792 #Param byteLength number of bytes of text to measure ##
4793 #Param widths returns text advances for each glyph; may be nullptr ##
4794 #Param bounds returns bounds for each glyph relative to (0, 0); may be nullptr ##
4795
4796 #Return glyph count in text ##
4797
4798 #Example
4799 #Height 160
4800 #Description
Cary Clarkce101242017-09-01 15:51:02 -04004801 Bounds of Glyphs increase for stroked text, but text advance remains the same.
Cary Clark8032b982017-07-28 11:04:54 -04004802 The underlines show the text advance, spaced to keep them distinct.
4803 ##
4804 void draw(SkCanvas* canvas) {
4805 SkPaint paint;
4806 paint.setAntiAlias(true);
4807 paint.setTextSize(50);
4808 const char str[] = "abc";
4809 const int bytes = sizeof(str) - 1;
4810 int count = paint.getTextWidths(str, bytes, nullptr);
4811 std::vector<SkScalar> widths;
4812 std::vector<SkRect> bounds;
4813 widths.resize(count);
4814 bounds.resize(count);
4815 for (int loop = 0; loop < 2; ++loop) {
4816 (void) paint.getTextWidths(str, count, &widths.front(), &bounds.front());
4817 SkPoint loc = { 25, 50 };
4818 canvas->drawText(str, bytes, loc.fX, loc.fY, paint);
4819 paint.setStyle(SkPaint::kStroke_Style);
4820 paint.setStrokeWidth(0);
4821 SkScalar advanceY = loc.fY + 10;
4822 for (int index = 0; index < count; ++index) {
4823 bounds[index].offset(loc.fX, loc.fY);
4824 canvas->drawRect(bounds[index], paint);
4825 canvas->drawLine(loc.fX, advanceY, loc.fX + widths[index], advanceY, paint);
4826 loc.fX += widths[index];
4827 advanceY += 5;
4828 }
4829 canvas->translate(0, 80);
4830 paint.setStrokeWidth(3);
4831 }
4832 }
4833 ##
4834
4835##
4836
4837#Topic ##
4838# ------------------------------------------------------------------------------
4839#Topic Text_Path
4840
Cary Clarkce101242017-09-01 15:51:02 -04004841Text_Path describes the geometry of Glyphs used to draw text.
Cary Clark8032b982017-07-28 11:04:54 -04004842
4843#Method void getTextPath(const void* text, size_t length, SkScalar x, SkScalar y,
4844 SkPath* path) const
4845
4846Returns the geometry as Path equivalent to the drawn text.
4847Uses Text_Encoding to decode text, Typeface to get the glyph paths,
4848and Text_Size, Fake_Bold, and Path_Effect to scale and modify the glyph paths.
4849All of the glyph paths are stored in path.
Cary Clark579985c2017-07-31 11:48:27 -04004850Uses x, y, and Text_Align to position path.
Cary Clark8032b982017-07-28 11:04:54 -04004851
4852 #Param text character codes or glyph indices ##
4853 #Param length number of bytes of text ##
4854 #Param x x-coordinate of the origin of the text ##
4855 #Param y y-coordinate of the origin of the text ##
Cary Clarkce101242017-09-01 15:51:02 -04004856 #Param path geometry of the Glyphs ##
Cary Clark8032b982017-07-28 11:04:54 -04004857
4858 #Example
4859 #Description
4860 Text is added to Path, offset, and subtracted from Path, then added at
4861 the offset location. The result is rendered with one draw call.
4862 ##
4863 #Height 128
4864 void draw(SkCanvas* canvas) {
4865 SkPaint paint;
4866 paint.setTextSize(80);
4867 SkPath path, path2;
4868 paint.getTextPath("ABC", 3, 20, 80, &path);
4869 path.offset(20, 20, &path2);
4870 Op(path, path2, SkPathOp::kDifference_SkPathOp, &path);
4871 path.addPath(path2);
4872 paint.setStyle(SkPaint::kStroke_Style);
4873 canvas->drawPath(path, paint);
4874 }
4875 ##
4876
4877##
4878
4879#Method void getPosTextPath(const void* text, size_t length,
4880 const SkPoint pos[], SkPath* path) const
4881
4882Returns the geometry as Path equivalent to the drawn text.
4883Uses Text_Encoding to decode text, Typeface to get the glyph paths,
4884and Text_Size, Fake_Bold, and Path_Effect to scale and modify the glyph paths.
4885All of the glyph paths are stored in path.
4886Uses pos array and Text_Align to position path.
4887pos contains a position for each glyph.
4888
4889 #Param text character codes or glyph indices ##
4890 #Param length number of bytes of text ##
4891 #Param pos positions of each glyph ##
Cary Clarkce101242017-09-01 15:51:02 -04004892 #Param path geometry of the Glyphs ##
Cary Clark8032b982017-07-28 11:04:54 -04004893
4894 #Example
4895 #Height 85
4896 #Description
Cary Clarkce101242017-09-01 15:51:02 -04004897 Simplifies three Glyphs to eliminate overlaps, and strokes the result.
Cary Clark8032b982017-07-28 11:04:54 -04004898 ##
4899 void draw(SkCanvas* canvas) {
4900 SkPaint paint;
4901 paint.setTextSize(80);
4902 SkPath path, path2;
4903 SkPoint pos[] = {{20, 60}, {30, 70}, {40, 80}};
4904 paint.getPosTextPath("ABC", 3, pos, &path);
4905 Simplify(path, &path);
4906 paint.setStyle(SkPaint::kStroke_Style);
4907 canvas->drawPath(path, paint);
4908 }
4909 ##
4910
4911##
4912
4913#Topic ##
4914# ------------------------------------------------------------------------------
4915#Topic Text_Intercepts
4916
Cary Clarkce101242017-09-01 15:51:02 -04004917Text_Intercepts describe the intersection of drawn text Glyphs with a pair
Cary Clark8032b982017-07-28 11:04:54 -04004918of lines parallel to the text advance. Text_Intercepts permits creating a
Cary Clarkce101242017-09-01 15:51:02 -04004919underline that skips Descenders.
Cary Clark8032b982017-07-28 11:04:54 -04004920
4921#Method int getTextIntercepts(const void* text, size_t length, SkScalar x, SkScalar y,
4922 const SkScalar bounds[2], SkScalar* intervals) const
4923
4924 Returns the number of intervals that intersect bounds.
4925 bounds describes a pair of lines parallel to the text advance.
Cary Clarkce101242017-09-01 15:51:02 -04004926 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 -04004927 the string.
4928 Uses Text_Encoding to decode text, Typeface to get the glyph paths,
4929 and Text_Size, Fake_Bold, and Path_Effect to scale and modify the glyph paths.
4930 Uses x, y, and Text_Align to position intervals.
4931
4932 Pass nullptr for intervals to determine the size of the interval array.
4933
4934 intervals are cached to improve performance for multiple calls.
4935
4936 #Param text character codes or glyph indices ##
4937 #Param length number of bytes of text ##
4938 #Param x x-coordinate of the origin of the text ##
4939 #Param y y-coordinate of the origin of the text ##
4940 #Param bounds lower and upper line parallel to the advance ##
4941 #Param intervals returned intersections; may be nullptr ##
4942
4943 #Return number of intersections; may be zero ##
4944
4945#Example
4946#Height 128
4947#Description
Cary Clarkce101242017-09-01 15:51:02 -04004948Underline uses intercepts to draw on either side of the glyph Descender.
Cary Clark8032b982017-07-28 11:04:54 -04004949##
4950void draw(SkCanvas* canvas) {
4951 SkPaint paint;
4952 paint.setTextSize(120);
4953 SkPoint textOrigin = { 20, 100 };
4954 SkScalar bounds[] = { 100, 108 };
4955 int count = paint.getTextIntercepts("y", 1, textOrigin.fX, textOrigin.fY, bounds, nullptr);
4956 std::vector<SkScalar> intervals;
4957 intervals.resize(count);
4958 (void) paint.getTextIntercepts("y", 1, textOrigin.fX, textOrigin.fY, bounds,
4959 &intervals.front());
4960 canvas->drawString("y", textOrigin.fX, textOrigin.fY, paint);
4961 paint.setColor(SK_ColorRED);
4962 SkScalar x = textOrigin.fX;
4963 for (int i = 0; i < count; i += 2) {
4964 canvas->drawRect({x, bounds[0], intervals[i], bounds[1]}, paint);
4965 x = intervals[i + 1];
4966 }
4967 canvas->drawRect({intervals[count - 1], bounds[0],
4968 textOrigin.fX + paint.measureText("y", 1), bounds[1]}, paint);
4969}
4970##
4971
4972##
4973
4974#Method int getPosTextIntercepts(const void* text, size_t length, const SkPoint pos[],
4975 const SkScalar bounds[2], SkScalar* intervals) const
4976
4977 Returns the number of intervals that intersect bounds.
4978 bounds describes a pair of lines parallel to the text advance.
Cary Clarkce101242017-09-01 15:51:02 -04004979 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 -04004980 the string.
4981 Uses Text_Encoding to decode text, Typeface to get the glyph paths,
4982 and Text_Size, Fake_Bold, and Path_Effect to scale and modify the glyph paths.
4983 Uses pos array and Text_Align to position intervals.
4984
4985 Pass nullptr for intervals to determine the size of the interval array.
4986
4987 intervals are cached to improve performance for multiple calls.
4988
4989 #Param text character codes or glyph indices ##
4990 #Param length number of bytes of text ##
4991 #Param pos positions of each glyph ##
4992 #Param bounds lower and upper line parallel to the advance ##
4993 #Param intervals returned intersections; may be nullptr ##
4994
Cary Clarka523d2d2017-08-30 08:58:10 -04004995 #Return number of intersections; may be zero ##
Cary Clark8032b982017-07-28 11:04:54 -04004996
4997 #Example
4998 #Description
Cary Clarkce101242017-09-01 15:51:02 -04004999 Text intercepts draw on either side of, but not inside, Glyphs in a run.
Cary Clark8032b982017-07-28 11:04:54 -04005000 ##
5001 void draw(SkCanvas* canvas) {
5002 SkPaint paint;
5003 paint.setTextSize(120);
5004 paint.setVerticalText(true);
5005 SkPoint textPos[] = {{ 60, 40 }, { 60, 140 }};
5006 SkScalar bounds[] = { 56, 64 };
5007 const char str[] = "A-";
5008 int len = sizeof(str) - 1;
5009 int count = paint.getPosTextIntercepts(str, len, textPos, bounds, nullptr);
5010 std::vector<SkScalar> intervals;
5011 intervals.resize(count);
5012 (void) paint.getPosTextIntercepts(str, len, textPos, bounds, &intervals.front());
5013 canvas->drawPosText(str, len, textPos, paint);
5014 paint.setColor(SK_ColorRED);
5015 SkScalar y = textPos[0].fY;
5016 for (int i = 0; i < count; i+= 2) {
5017 canvas->drawRect({bounds[0], y, bounds[1], intervals[i]}, paint);
5018 y = intervals[i + 1];
5019 }
5020 canvas->drawRect({bounds[0], intervals[count - 1], bounds[1], 240}, paint);
5021 }
5022 ##
5023
5024##
5025
5026#Method int getPosTextHIntercepts(const void* text, size_t length, const SkScalar xpos[],
5027 SkScalar constY, const SkScalar bounds[2],
5028 SkScalar* intervals) const
5029
5030 Returns the number of intervals that intersect bounds.
5031 bounds describes a pair of lines parallel to the text advance.
Cary Clarkce101242017-09-01 15:51:02 -04005032 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 -04005033 the string.
5034 Uses Text_Encoding to decode text, Typeface to get the glyph paths,
5035 and Text_Size, Fake_Bold, and Path_Effect to scale and modify the glyph paths.
5036 Uses xpos array, constY, and Text_Align to position intervals.
5037
5038 Pass nullptr for intervals to determine the size of the interval array.
5039
5040 intervals are cached to improve performance for multiple calls.
5041
5042 #Param text character codes or glyph indices ##
5043 #Param length number of bytes of text ##
5044 #Param xpos positions of each glyph in x ##
5045 #Param constY position of each glyph in y ##
5046 #Param bounds lower and upper line parallel to the advance ##
5047 #Param intervals returned intersections; may be nullptr ##
5048
5049 #Return number of intersections; may be zero ##
5050
5051 #Example
5052 #Height 128
5053 #Description
5054 Text intercepts do not take stroke thickness into consideration.
5055 ##
5056 void draw(SkCanvas* canvas) {
5057 SkPaint paint;
5058 paint.setTextSize(120);
5059 paint.setStyle(SkPaint::kStroke_Style);
5060 paint.setStrokeWidth(4);
5061 SkScalar textPosH[] = { 20, 80, 140 };
5062 SkScalar y = 100;
5063 SkScalar bounds[] = { 56, 78 };
5064 const char str[] = "\\-/";
5065 int len = sizeof(str) - 1;
5066 int count = paint.getPosTextHIntercepts(str, len, textPosH, y, bounds, nullptr);
5067 std::vector<SkScalar> intervals;
5068 intervals.resize(count);
5069 (void) paint.getPosTextHIntercepts(str, len, textPosH, y, bounds, &intervals.front());
5070 canvas->drawPosTextH(str, len, textPosH, y, paint);
5071 paint.setColor(0xFFFF7777);
5072 paint.setStyle(SkPaint::kFill_Style);
5073 SkScalar x = textPosH[0];
5074 for (int i = 0; i < count; i+= 2) {
5075 canvas->drawRect({x, bounds[0], intervals[i], bounds[1]}, paint);
5076 x = intervals[i + 1];
5077 }
5078 canvas->drawRect({intervals[count - 1], bounds[0], 180, bounds[1]}, paint);
5079 }
5080 ##
5081
5082##
5083
5084
5085#Method int getTextBlobIntercepts(const SkTextBlob* blob, const SkScalar bounds[2],
5086 SkScalar* intervals) const
5087
5088 Returns the number of intervals that intersect bounds.
5089 bounds describes a pair of lines parallel to the text advance.
Cary Clarkce101242017-09-01 15:51:02 -04005090 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 -04005091 the string.
5092 Uses Text_Encoding to decode text, Typeface to get the glyph paths,
5093 and Text_Size, Fake_Bold, and Path_Effect to scale and modify the glyph paths.
Cary Clarkce101242017-09-01 15:51:02 -04005094 Uses run array and Text_Align to position intervals.
Cary Clark8032b982017-07-28 11:04:54 -04005095
5096 Pass nullptr for intervals to determine the size of the interval array.
5097
5098 intervals are cached to improve performance for multiple calls.
5099
Cary Clarkce101242017-09-01 15:51:02 -04005100 #Param blob Glyphs, positions, and text paint attributes ##
Cary Clark8032b982017-07-28 11:04:54 -04005101 #Param bounds lower and upper line parallel to the advance ##
5102 #Param intervals returned intersections; may be nullptr ##
5103
5104 #Return number of intersections; may be zero ##
5105
5106 #Example
5107 #Height 143
5108 void draw(SkCanvas* canvas) {
5109 SkPaint paint;
5110 paint.setTextSize(120);
5111 SkPoint textPos = { 20, 110 };
5112 int len = 3;
5113 SkTextBlobBuilder textBlobBuilder;
5114 const SkTextBlobBuilder::RunBuffer& run =
5115 textBlobBuilder.allocRun(paint, len, textPos.fX, textPos.fY);
5116 run.glyphs[0] = 10;
5117 run.glyphs[1] = 20;
5118 run.glyphs[2] = 30;
5119 sk_sp<const SkTextBlob> blob = textBlobBuilder.make();
5120 canvas->drawTextBlob(blob.get(), textPos.fX, textPos.fY, paint);
5121 SkScalar bounds[] = { 116, 134 };
5122 int count = paint.getTextBlobIntercepts(blob.get(), bounds, nullptr);
5123 std::vector<SkScalar> intervals;
5124 intervals.resize(count);
5125 (void) paint.getTextBlobIntercepts(blob.get(), bounds, &intervals.front());
5126 canvas->drawTextBlob(blob.get(), 0, 0, paint);
5127 paint.setColor(0xFFFF7777);
5128 SkScalar x = textPos.fX;
5129 for (int i = 0; i < count; i+= 2) {
5130 canvas->drawRect({x, bounds[0], intervals[i], bounds[1]}, paint);
5131 x = intervals[i + 1];
5132 }
5133 canvas->drawRect({intervals[count - 1], bounds[0], 180, bounds[1]}, paint);
5134 }
5135 ##
5136
5137##
5138
5139#Topic ##
5140# ------------------------------------------------------------------------------
5141
5142#Method bool nothingToDraw() const
5143
Cary Clark579985c2017-07-31 11:48:27 -04005144 Returns true if Paint prevents all drawing;
5145 otherwise, the Paint may or may not allow drawing.
Cary Clark8032b982017-07-28 11:04:54 -04005146
Cary Clarkce101242017-09-01 15:51:02 -04005147 Returns true if, for example, Blend_Mode combined with Color_Alpha computes a
5148 new Alpha of zero.
Cary Clark8032b982017-07-28 11:04:54 -04005149
5150 #Return true if Paint prevents all drawing ##
5151
5152 #Example
5153 void draw(SkCanvas* canvas) {
5154 auto debugster = [](const char* prefix, const SkPaint& p) -> void {
5155 SkDebugf("%s nothing to draw: %s\n", prefix,
5156 p.nothingToDraw() ? "true" : "false");
5157 };
5158 SkPaint paint;
5159 debugster("initial", paint);
5160 paint.setBlendMode(SkBlendMode::kDst);
5161 debugster("blend dst", paint);
5162 paint.setBlendMode(SkBlendMode::kSrcOver);
5163 debugster("blend src over", paint);
5164 paint.setAlpha(0);
5165 debugster("alpha 0", paint);
5166 }
5167
5168 #StdOut
5169 initial nothing to draw: false
5170 blend dst nothing to draw: true
5171 blend src over nothing to draw: false
5172 alpha 0 nothing to draw: true
5173 #StdOut ##
5174 ##
5175
5176##
5177
5178# ------------------------------------------------------------------------------
5179#Topic Fast_Bounds
5180 #Private
5181 To be made private.
5182 ##
5183
5184Fast_Bounds methods conservatively outset a drawing bounds by additional area
5185Paint may draw to.
5186
5187#Method bool canComputeFastBounds() const
5188 #Private
5189 (to be made private)
5190 ##
5191
5192 Returns true if Paint does not include elements requiring extensive computation
5193 to compute Device bounds of drawn geometry. For instance, Paint with Path_Effect
5194 always returns false.
5195
5196 #Return true if Paint allows for fast computation of bounds ##
5197##
5198
5199#Method const SkRect& computeFastBounds(const SkRect& orig, SkRect* storage) const
5200 #Private
5201 (to be made private)
5202 ##
5203
5204 Only call this if canComputeFastBounds returned true. This takes a
5205 raw rectangle (the raw bounds of a shape), and adjusts it for stylistic
5206 effects in the paint (e.g. stroking). If needed, it uses the storage
Cary Clarkce101242017-09-01 15:51:02 -04005207 parameter. It returns the adjusted bounds that can then be used
Cary Clark8032b982017-07-28 11:04:54 -04005208 for SkCanvas::quickReject tests.
5209
Cary Clarkce101242017-09-01 15:51:02 -04005210 The returned Rect will either be orig or storage, thus the caller
Cary Clark8032b982017-07-28 11:04:54 -04005211 should not rely on storage being set to the result, but should always
Cary Clarkce101242017-09-01 15:51:02 -04005212 use the returned value. It is legal for orig and storage to be the same
5213 Rect.
Cary Clark8032b982017-07-28 11:04:54 -04005214
5215 #Private
5216 e.g.
5217 if (paint.canComputeFastBounds()) {
5218 SkRect r, storage;
5219 path.computeBounds(&r, SkPath::kFast_BoundsType);
5220 const SkRect& fastR = paint.computeFastBounds(r, &storage);
5221 if (canvas->quickReject(fastR, ...)) {
5222 // don't draw the path
5223 }
5224 }
5225 ##
5226
5227 #Param orig geometry modified by Paint when drawn ##
5228 #Param storage computed bounds of geometry; may not be nullptr ##
5229
5230 #Return fast computed bounds ##
5231##
5232
5233#Method const SkRect& computeFastStrokeBounds(const SkRect& orig,
5234 SkRect* storage) const
5235 #Private
5236 (to be made private)
5237 ##
5238
5239 #Param orig geometry modified by Paint when drawn ##
5240 #Param storage computed bounds of geometry ##
5241
5242 #Return fast computed bounds ##
5243##
5244
5245#Method const SkRect& doComputeFastBounds(const SkRect& orig, SkRect* storage,
5246 Style style) const
5247 #Private
5248 (to be made private)
5249 ##
5250
Cary Clarkce101242017-09-01 15:51:02 -04005251 Computes the bounds, overriding the Paint Style. This can be used to
5252 account for additional width required by stroking orig, without
5253 altering Style set to fill.
Cary Clark8032b982017-07-28 11:04:54 -04005254
5255 #Param orig geometry modified by Paint when drawn ##
5256 #Param storage computed bounds of geometry ##
5257 #Param style overrides Style ##
5258
5259 #Return fast computed bounds ##
5260##
5261
5262#Topic Fast_Bounds ##
5263
5264# ------------------------------------------------------------------------------
5265#Method void toString(SkString* str) const;
5266
5267#DefinedBy SK_TO_STRING_NONVIRT() ##
5268
5269#Private
5270macro expands to: void toString(SkString* str) const;
5271##
5272
Cary Clarkce101242017-09-01 15:51:02 -04005273Creates string representation of Paint. The representation is read by
5274internal debugging tools. The interface and implementation may be
5275suppressed by defining SK_IGNORE_TO_STRING.
Cary Clark8032b982017-07-28 11:04:54 -04005276
Cary Clarkce101242017-09-01 15:51:02 -04005277#Param str storage for string representation of Paint ##
Cary Clark8032b982017-07-28 11:04:54 -04005278
5279#Example
5280 SkPaint paint;
5281 SkString str;
5282 paint.toString(&str);
5283 const char textSize[] = "TextSize:";
5284 const int trailerSize = strlen("</dd><dt>");
5285 int textSizeLoc = str.find(textSize) + strlen(textSize) + trailerSize;
5286 const char* sizeStart = &str.c_str()[textSizeLoc];
5287 int textSizeEnd = SkStrFind(sizeStart, "</dd>");
5288 SkDebugf("text size = %.*s\n", textSizeEnd, sizeStart);
5289
5290 #StdOut
5291 text size = 12
5292 ##
5293
5294##
5295
5296#ToDo incomplete ##
5297
5298##
5299
5300# ------------------------------------------------------------------------------
5301
5302#Class SkPaint ##
5303
5304#Topic Paint ##