blob: aa388d3b09a7a83c791cebe71d41d54869d1f406 [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
Cary Clark2ade9972017-11-02 17:49:34 -0400633#SeeAlso SkReadBuffer
Cary Clark8032b982017-07-28 11:04:54 -0400634
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
Cary Clark2ade9972017-11-02 17:49:34 -0400850#SeeAlso Flags getFlags
Cary Clark8032b982017-07-28 11:04:54 -0400851
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
Cary Clark2ade9972017-11-02 17:49:34 -04002434#Height 200
Cary Clark8032b982017-07-28 11:04:54 -04002435 SkPaint paint;
2436 paint.setStyle(SkPaint::kStroke_Style);
2437 paint.setStrokeWidth(20);
2438 SkPath path;
2439 path.moveTo(30, 30);
2440 path.lineTo(30, 30);
2441 path.moveTo(70, 30);
2442 path.lineTo(90, 40);
2443 for (SkPaint::Cap c : { SkPaint::kButt_Cap, SkPaint::kRound_Cap, SkPaint::kSquare_Cap } ) {
2444 paint.setStrokeCap(c);
2445 canvas->drawPath(path, paint);
2446 canvas->translate(0, 70);
2447 }
2448##
2449
2450#Method Cap getStrokeCap() const
2451
2452 The geometry drawn at the beginning and end of strokes.
2453
2454 #Return one of: kButt_Cap, kRound_Cap, kSquare_Cap ##
2455
2456 #Example
2457 SkPaint paint;
2458 SkDebugf("kButt_Cap %c= default stroke cap\n",
2459 SkPaint::kButt_Cap == paint.getStrokeCap() ? '=' : '!');
2460
2461 #StdOut
2462 kButt_Cap == default stroke cap
2463 ##
2464 ##
2465
2466 #SeeAlso Stroke_Cap setStrokeCap
2467##
2468
2469#Method void setStrokeCap(Cap cap)
2470
2471 The geometry drawn at the beginning and end of strokes.
2472
2473 #Param cap one of: kButt_Cap, kRound_Cap, kSquare_Cap;
2474 has no effect if cap is not valid
2475 ##
2476
2477 #Example
2478 SkPaint paint;
2479 paint.setStrokeCap(SkPaint::kRound_Cap);
2480 paint.setStrokeCap((SkPaint::Cap) SkPaint::kCapCount);
2481 SkDebugf("kRound_Cap %c= paint.getStrokeCap()\n",
2482 SkPaint::kRound_Cap == paint.getStrokeCap() ? '=' : '!');
2483
2484 #StdOut
2485 kRound_Cap == paint.getStrokeCap()
2486 ##
2487 ##
2488
2489 #SeeAlso Stroke_Cap getStrokeCap
2490##
2491
2492#Topic ##
2493# ------------------------------------------------------------------------------
2494#Topic Stroke_Join
2495
2496Stroke_Join draws at the sharp corners of an open or closed Path_Contour.
2497
2498Stroke describes the area covered by a pen of Stroke_Width as it
Cary Clarkbc5697d2017-10-04 14:31:33 -04002499follows the Path_Contour, moving parallel to the contour direction.
Cary Clark8032b982017-07-28 11:04:54 -04002500
2501If the contour direction changes abruptly, because the tangent direction leading
2502to the end of a curve within the contour does not match the tangent direction of
2503the following curve, the pair of curves meet at Stroke_Join.
2504
2505#Example
Cary Clark2ade9972017-11-02 17:49:34 -04002506#Height 200
2507 SkPaint paint;
2508 paint.setStyle(SkPaint::kStroke_Style);
2509 paint.setStrokeWidth(20);
2510 SkPath path;
2511 path.moveTo(30, 20);
2512 path.lineTo(40, 40);
2513 path.conicTo(70, 20, 100, 20, .707f);
2514 for (SkPaint::Join j : { SkPaint::kMiter_Join, SkPaint::kRound_Join, SkPaint::kBevel_Join } ) {
2515 paint.setStrokeJoin(j);
2516 canvas->drawPath(path, paint);
2517 canvas->translate(0, 70);
2518 }
Cary Clark8032b982017-07-28 11:04:54 -04002519##
2520
2521#Enum Join
2522#Code
2523 enum Join {
2524 kMiter_Join,
2525 kRound_Join,
2526 kBevel_Join,
2527
2528 kLast_Join = kBevel_Join,
Cary Clarkbad5ad72017-08-03 17:14:08 -04002529 kDefault_Join = kMiter_Join,
Cary Clark8032b982017-07-28 11:04:54 -04002530 };
Cary Clark6fc50412017-09-21 12:31:06 -04002531
Cary Clark8032b982017-07-28 11:04:54 -04002532 static constexpr int kJoinCount = kLast_Join + 1;
2533##
2534
Cary Clark1eace2d2017-07-31 07:52:43 -04002535Join specifies how corners are drawn when a shape is stroked. Join
Cary Clark8032b982017-07-28 11:04:54 -04002536affects the four corners of a stroked rectangle, and the connected segments in a
2537stroked path.
2538
2539Choose miter join to draw sharp corners. Choose round join to draw a circle with a
2540radius equal to the stroke width on top of the corner. Choose bevel join to minimally
2541connect the thick strokes.
2542
2543The fill path constructed to describe the stroked path respects the join setting but may
2544not contain the actual join. For instance, a fill path constructed with round joins does
2545not necessarily include circles at each connected segment.
2546
2547#Const kMiter_Join 0
2548 Extends the outside corner to the extent allowed by Miter_Limit.
2549 If the extension exceeds Miter_Limit, kBevel_Join is used instead.
2550##
2551
2552#Const kRound_Join 1
2553 Adds a circle with a diameter of Stroke_Width at the sharp corner.
2554##
2555
2556#Const kBevel_Join 2
2557 Connects the outside edges of the sharp corner.
2558##
2559
2560#Const kLast_Join 2
2561 Equivalent to the largest value for Stroke_Join.
2562##
2563
2564#Const kDefault_Join 1
2565 Equivalent to kMiter_Join.
2566 Stroke_Join is set to kMiter_Join by default.
2567##
2568
2569#Const kJoinCount 3
2570 The number of different Stroke_Join values defined.
2571 May be used to verify that Stroke_Join is a legal value.
2572##
2573
2574#Example
2575#Width 462
2576void draw(SkCanvas* canvas) {
2577 SkPath path;
2578 path.moveTo(10, 50);
2579 path.quadTo(35, 110, 60, 210);
2580 path.quadTo(105, 110, 130, 10);
2581 SkPaint paint; // set to default kMiter_Join
2582 paint.setAntiAlias(true);
2583 paint.setStyle(SkPaint::kStroke_Style);
2584 paint.setStrokeWidth(20);
2585 canvas->drawPath(path, paint);
2586 canvas->translate(150, 0);
2587 paint.setStrokeJoin(SkPaint::kBevel_Join);
2588 canvas->drawPath(path, paint);
2589 canvas->translate(150, 0);
2590 paint.setStrokeJoin(SkPaint::kRound_Join);
2591 canvas->drawPath(path, paint);
2592}
2593##
2594
2595#SeeAlso setStrokeJoin getStrokeJoin setStrokeMiter getStrokeMiter
2596
2597#Enum ##
2598
2599#Method Join getStrokeJoin() const
2600
2601 The geometry drawn at the corners of strokes.
2602
2603 #Return one of: kMiter_Join, kRound_Join, kBevel_Join ##
2604
2605 #Example
2606 SkPaint paint;
2607 SkDebugf("kMiter_Join %c= default stroke join\n",
2608 SkPaint::kMiter_Join == paint.getStrokeJoin() ? '=' : '!');
2609
2610 #StdOut
2611 kMiter_Join == default stroke join
2612 ##
2613 ##
2614
2615 #SeeAlso Stroke_Join setStrokeJoin
2616##
2617
2618#Method void setStrokeJoin(Join join)
2619
2620 The geometry drawn at the corners of strokes.
2621
2622 #Param join one of: kMiter_Join, kRound_Join, kBevel_Join;
Cary Clark579985c2017-07-31 11:48:27 -04002623 otherwise, has no effect
Cary Clark8032b982017-07-28 11:04:54 -04002624 ##
2625
2626 #Example
2627 SkPaint paint;
2628 paint.setStrokeJoin(SkPaint::kMiter_Join);
2629 paint.setStrokeJoin((SkPaint::Join) SkPaint::kJoinCount);
2630 SkDebugf("kMiter_Join %c= paint.getStrokeJoin()\n",
2631 SkPaint::kMiter_Join == paint.getStrokeJoin() ? '=' : '!');
2632
2633 #StdOut
2634 kMiter_Join == paint.getStrokeJoin()
2635 ##
2636 ##
2637
2638 #SeeAlso Stroke_Join getStrokeJoin
2639##
2640
2641#SeeAlso Miter_Limit
2642
2643#Topic Stroke_Join ##
2644# ------------------------------------------------------------------------------
2645#Topic Fill_Path
2646
2647Fill_Path creates a Path by applying the Path_Effect, followed by the Style_Stroke.
2648
2649If Paint contains Path_Effect, Path_Effect operates on the source Path; the result
2650replaces the destination Path. Otherwise, the source Path is replaces the
2651destination Path.
2652
2653Fill Path can request the Path_Effect to restrict to a culling rectangle, but
2654the Path_Effect is not required to do so.
2655
2656If Style is kStroke_Style or kStrokeAndFill_Style,
2657and Stroke_Width is greater than zero, the Stroke_Width, Stroke_Cap, Stroke_Join,
2658and Miter_Limit operate on the destination Path, replacing it.
2659
2660Fill Path can specify the precision used by Stroke_Width to approximate the stroke geometry.
2661
2662If the Style is kStroke_Style and the Stroke_Width is zero, getFillPath
2663returns false since Hairline has no filled equivalent.
2664
2665#Method bool getFillPath(const SkPath& src, SkPath* dst, const SkRect* cullRect,
2666 SkScalar resScale = 1) const
2667
2668 The filled equivalent of the stroked path.
2669
2670 #Param src Path read to create a filled version ##
2671 #Param dst resulting Path; may be the same as src, but may not be nullptr ##
2672 #Param cullRect optional limit passed to Path_Effect ##
2673 #Param resScale if > 1, increase precision, else if (0 < res < 1) reduce precision
2674 to favor speed and size
2675 ##
2676 #Return true if the path represents Style_Fill, or false if it represents Hairline ##
2677
2678 #Example
2679 #Height 192
2680 #Description
Cary Clarkce101242017-09-01 15:51:02 -04002681 A very small Quad stroke is turned into a filled path with increasing levels of precision.
2682 At the lowest precision, the Quad stroke is approximated by a rectangle.
Cary Clark8032b982017-07-28 11:04:54 -04002683 At the highest precision, the filled path has high fidelity compared to the original stroke.
2684 ##
2685 void draw(SkCanvas* canvas) {
2686 SkPaint strokePaint;
2687 strokePaint.setAntiAlias(true);
2688 strokePaint.setStyle(SkPaint::kStroke_Style);
2689 strokePaint.setStrokeWidth(.1f);
2690 SkPath strokePath;
2691 strokePath.moveTo(.08f, .08f);
2692 strokePath.quadTo(.09f, .08f, .17f, .17f);
2693 SkPath fillPath;
2694 SkPaint outlinePaint(strokePaint);
2695 outlinePaint.setStrokeWidth(2);
2696 SkMatrix scale = SkMatrix::MakeScale(300, 300);
2697 for (SkScalar precision : { 0.01f, .1f, 1.f, 10.f, 100.f } ) {
2698 strokePaint.getFillPath(strokePath, &fillPath, nullptr, precision);
2699 fillPath.transform(scale);
2700 canvas->drawPath(fillPath, outlinePaint);
2701 canvas->translate(60, 0);
2702 if (1.f == precision) canvas->translate(-180, 100);
2703 }
2704 strokePath.transform(scale);
2705 strokePaint.setStrokeWidth(30);
2706 canvas->drawPath(strokePath, strokePaint);
2707 }
2708 ##
2709
2710##
2711
2712#Method bool getFillPath(const SkPath& src, SkPath* dst) const
2713
2714 The filled equivalent of the stroked path.
2715
2716 Replaces dst with the src path modified by Path_Effect and Style_Stroke.
2717 Path_Effect, if any, is not culled. Stroke_Width is created with default precision.
2718
2719 #Param src Path read to create a filled version ##
2720 #Param dst resulting Path dst may be the same as src, but may not be nullptr ##
2721 #Return true if the path represents Style_Fill, or false if it represents Hairline ##
2722
2723 #Example
2724 #Height 128
2725 void draw(SkCanvas* canvas) {
2726 SkPaint paint;
2727 paint.setStyle(SkPaint::kStroke_Style);
2728 paint.setStrokeWidth(10);
2729 SkPath strokePath;
2730 strokePath.moveTo(20, 20);
2731 strokePath.lineTo(100, 100);
2732 canvas->drawPath(strokePath, paint);
2733 SkPath fillPath;
2734 paint.getFillPath(strokePath, &fillPath);
2735 paint.setStrokeWidth(2);
2736 canvas->translate(40, 0);
2737 canvas->drawPath(fillPath, paint);
2738 }
2739 ##
2740
2741##
2742
2743#SeeAlso Style_Stroke Stroke_Width Path_Effect
2744
2745#Topic ##
2746# ------------------------------------------------------------------------------
2747#Topic Shader_Methods
2748
2749Shader defines the colors used when drawing a shape.
2750Shader may be an image, a gradient, or a computed fill.
2751If Paint has no Shader, then Color fills the shape.
2752
2753Shader is modulated by Color_Alpha component of Color.
2754If Shader object defines only Color_Alpha, then Color modulated by Color_Alpha describes
2755the fill.
2756
2757The drawn transparency can be modified without altering Shader, by changing Color_Alpha.
2758
2759#Example
2760void draw(SkCanvas* canvas) {
2761 SkPaint paint;
2762 SkPoint center = { 50, 50 };
2763 SkScalar radius = 50;
2764 const SkColor colors[] = { 0xFFFFFFFF, 0xFF000000 };
2765 paint.setShader(SkGradientShader::MakeRadial(center, radius, colors,
2766 nullptr, SK_ARRAY_COUNT(colors), SkShader::kClamp_TileMode));
2767 for (SkScalar a : { 0.3f, 0.6f, 1.0f } ) {
2768 paint.setAlpha((int) (a * 255));
2769 canvas->drawCircle(center.fX, center.fY, radius, paint);
2770 canvas->translate(70, 70);
2771 }
2772}
2773##
2774
2775If Shader generates only Color_Alpha then all components of Color modulate the output.
2776
2777#Example
2778void draw(SkCanvas* canvas) {
2779 SkPaint paint;
2780 SkBitmap bitmap;
2781 bitmap.setInfo(SkImageInfo::MakeA8(5, 1), 5); // bitmap only contains alpha
2782 uint8_t pixels[5] = { 0x22, 0x55, 0x88, 0xBB, 0xFF };
2783 bitmap.setPixels(pixels);
2784 paint.setShader(SkShader::MakeBitmapShader(bitmap,
2785 SkShader::kMirror_TileMode, SkShader::kMirror_TileMode));
2786 for (SkColor c : { SK_ColorRED, SK_ColorBLUE, SK_ColorGREEN } ) {
2787 paint.setColor(c); // all components in color affect shader
2788 canvas->drawCircle(50, 50, 50, paint);
2789 canvas->translate(70, 70);
2790 }
2791}
2792##
2793
2794#Method SkShader* getShader() const
2795
2796 Optional colors used when filling a path, such as a gradient.
2797
2798 Does not alter Shader Reference_Count.
2799
2800 #Return Shader if previously set, nullptr otherwise ##
2801
2802 #Example
2803 void draw(SkCanvas* canvas) {
2804 SkPaint paint;
2805 SkDebugf("nullptr %c= shader\n", paint.getShader() ? '!' : '=');
2806 paint.setShader(SkShader::MakeEmptyShader());
2807 SkDebugf("nullptr %c= shader\n", paint.getShader() ? '!' : '=');
2808 }
2809
2810 #StdOut
2811 nullptr == shader
2812 nullptr != shader
2813 ##
2814 ##
2815
2816##
2817
2818#Method sk_sp<SkShader> refShader() const
2819
2820 Optional colors used when filling a path, such as a gradient.
2821
2822 Increases Shader Reference_Count by one.
2823
2824 #Return Shader if previously set, nullptr otherwise ##
2825
2826 #Example
2827 void draw(SkCanvas* canvas) {
2828 SkPaint paint1, paint2;
2829 paint1.setShader(SkShader::MakeEmptyShader());
2830 SkDebugf("shader unique: %s\n", paint1.getShader()->unique() ? "true" : "false");
2831 paint2.setShader(paint1.refShader());
2832 SkDebugf("shader unique: %s\n", paint1.getShader()->unique() ? "true" : "false");
2833 }
2834
2835 #StdOut
2836 shader unique: true
2837 shader unique: false
2838 ##
2839 ##
2840
2841##
2842
2843#Method void setShader(sk_sp<SkShader> shader)
2844
2845 Optional colors used when filling a path, such as a gradient.
2846
Cary Clarkd0530ba2017-09-14 11:25:39 -04002847 Sets Shader to shader, decreasing Reference_Count of the previous Shader.
Cary Clark6fc50412017-09-21 12:31:06 -04002848 Increments shader Reference_Count by one.
Cary Clark8032b982017-07-28 11:04:54 -04002849
2850 #Param shader how geometry is filled with color; if nullptr, Color is used instead ##
2851
2852 #Example
2853 #Height 64
2854 void draw(SkCanvas* canvas) {
2855 SkPaint paint;
2856 paint.setColor(SK_ColorBLUE);
2857 paint.setShader(SkShader::MakeColorShader(SK_ColorRED));
2858 canvas->drawRect(SkRect::MakeWH(40, 40), paint);
2859 paint.setShader(nullptr);
2860 canvas->translate(50, 0);
2861 canvas->drawRect(SkRect::MakeWH(40, 40), paint);
2862 }
2863 ##
2864
2865##
2866
2867#Topic ##
2868# ------------------------------------------------------------------------------
2869#Topic Color_Filter_Methods
2870
2871Color_Filter alters the color used when drawing a shape.
2872Color_Filter may apply Blend_Mode, transform the color through a matrix, or composite multiple filters.
2873If Paint has no Color_Filter, the color is unaltered.
2874
2875The drawn transparency can be modified without altering Color_Filter, by changing Color_Alpha.
2876
2877#Example
2878#Height 128
2879void draw(SkCanvas* canvas) {
2880 SkPaint paint;
2881 paint.setColorFilter(SkColorMatrixFilter::MakeLightingFilter(0xFFFFFF, 0xFF0000));
2882 for (SkColor c : { SK_ColorBLACK, SK_ColorGREEN } ) {
2883 paint.setColor(c);
2884 canvas->drawRect(SkRect::MakeXYWH(10, 10, 50, 50), paint);
2885 paint.setAlpha(0x80);
2886 canvas->drawRect(SkRect::MakeXYWH(60, 60, 50, 50), paint);
2887 canvas->translate(100, 0);
2888 }
2889}
2890##
2891
2892#Method SkColorFilter* getColorFilter() const
2893
2894 Returns Color_Filter if set, or nullptr.
2895 Does not alter Color_Filter Reference_Count.
2896
2897 #Return Color_Filter if previously set, nullptr otherwise ##
2898
2899 #Example
2900 void draw(SkCanvas* canvas) {
2901 SkPaint paint;
2902 SkDebugf("nullptr %c= color filter\n", paint.getColorFilter() ? '!' : '=');
2903 paint.setColorFilter(SkColorFilter::MakeModeFilter(SK_ColorLTGRAY, SkBlendMode::kSrcIn));
2904 SkDebugf("nullptr %c= color filter\n", paint.getColorFilter() ? '!' : '=');
2905 }
2906
2907 #StdOut
2908 nullptr == color filter
2909 nullptr != color filter
2910 ##
2911 ##
2912##
2913
2914#Method sk_sp<SkColorFilter> refColorFilter() const
2915
2916 Returns Color_Filter if set, or nullptr.
2917 Increases Color_Filter Reference_Count by one.
2918
2919 #Return Color_Filter if set, or nullptr ##
2920
2921 #Example
2922 void draw(SkCanvas* canvas) {
2923 SkPaint paint1, paint2;
2924 paint1.setColorFilter(SkColorFilter::MakeModeFilter(0xFFFF0000, SkBlendMode::kSrcATop));
2925 SkDebugf("color filter unique: %s\n", paint1.getColorFilter()->unique() ? "true" : "false");
2926 paint2.setColorFilter(paint1.refColorFilter());
2927 SkDebugf("color filter unique: %s\n", paint1.getColorFilter()->unique() ? "true" : "false");
2928 }
2929
2930 #StdOut
2931 color filter unique: true
2932 color filter unique: false
2933 ##
2934 ##
2935##
2936
2937#Method void setColorFilter(sk_sp<SkColorFilter> colorFilter)
2938
Cary Clark6fc50412017-09-21 12:31:06 -04002939Sets Color_Filter to filter, decreasing Reference_Count of the previous
2940Color_Filter. Pass nullptr to clear Color_Filter.
2941
2942Increments filter Reference_Count by one.
Cary Clark8032b982017-07-28 11:04:54 -04002943
2944 #Param colorFilter Color_Filter to apply to subsequent draw ##
2945
2946 #Example
2947 #Height 64
2948 void draw(SkCanvas* canvas) {
2949 SkPaint paint;
2950 paint.setColorFilter(SkColorFilter::MakeModeFilter(SK_ColorLTGRAY, SkBlendMode::kSrcIn));
2951 canvas->drawRect(SkRect::MakeWH(50, 50), paint);
2952 paint.setColorFilter(nullptr);
2953 canvas->translate(70, 0);
2954 canvas->drawRect(SkRect::MakeWH(50, 50), paint);
2955 }
2956 ##
2957
2958##
2959
2960#Topic ##
2961# ------------------------------------------------------------------------------
2962#Topic Blend_Mode_Methods
2963
2964Blend_Mode describes how Color combines with the destination color.
2965The default setting, SkBlendMode::kSrcOver, draws the source color
2966over the destination color.
2967
2968#Example
2969void draw(SkCanvas* canvas) {
2970 SkPaint normal, blender;
2971 normal.setColor(0xFF58a889);
2972 blender.setColor(0xFF8958a8);
2973 canvas->clear(0);
2974 for (SkBlendMode m : { SkBlendMode::kSrcOver, SkBlendMode::kSrcIn, SkBlendMode::kSrcOut } ) {
2975 normal.setBlendMode(SkBlendMode::kSrcOver);
2976 canvas->drawOval(SkRect::MakeXYWH(30, 30, 30, 80), normal);
2977 blender.setBlendMode(m);
2978 canvas->drawOval(SkRect::MakeXYWH(10, 50, 80, 30), blender);
2979 canvas->translate(70, 70);
2980 }
2981}
2982##
2983
2984#SeeAlso Blend_Mode
2985
2986#Method SkBlendMode getBlendMode() const
2987
2988 Returns Blend_Mode.
Cary Clark579985c2017-07-31 11:48:27 -04002989 By default, returns SkBlendMode::kSrcOver.
Cary Clark8032b982017-07-28 11:04:54 -04002990
2991 #Return mode used to combine source color with destination color ##
2992
2993 #Example
2994 void draw(SkCanvas* canvas) {
2995 SkPaint paint;
2996 SkDebugf("kSrcOver %c= getBlendMode\n",
2997 SkBlendMode::kSrcOver == paint.getBlendMode() ? '=' : '!');
2998 paint.setBlendMode(SkBlendMode::kSrc);
2999 SkDebugf("kSrcOver %c= getBlendMode\n",
3000 SkBlendMode::kSrcOver == paint.getBlendMode() ? '=' : '!');
3001 }
3002
3003 #StdOut
3004 kSrcOver == getBlendMode
3005 kSrcOver != getBlendMode
3006 ##
3007 ##
3008
3009##
3010
3011#Method bool isSrcOver() const
3012
3013 Returns true if Blend_Mode is SkBlendMode::kSrcOver, the default.
3014
3015 #Return true if Blend_Mode is SkBlendMode::kSrcOver ##
3016
3017 #Example
3018 void draw(SkCanvas* canvas) {
3019 SkPaint paint;
3020 SkDebugf("isSrcOver %c= true\n", paint.isSrcOver() ? '=' : '!');
3021 paint.setBlendMode(SkBlendMode::kSrc);
3022 SkDebugf("isSrcOver %c= true\n", paint.isSrcOver() ? '=' : '!');
3023 }
3024
3025 #StdOut
3026 isSrcOver == true
3027 isSrcOver != true
3028 ##
3029 ##
3030
3031##
3032
3033#Method void setBlendMode(SkBlendMode mode)
3034
3035 Sets Blend_Mode to mode.
3036 Does not check for valid input.
3037
3038 #Param mode SkBlendMode used to combine source color and destination ##
3039
3040 #Example
3041 void draw(SkCanvas* canvas) {
3042 SkPaint paint;
3043 SkDebugf("isSrcOver %c= true\n", paint.isSrcOver() ? '=' : '!');
3044 paint.setBlendMode(SkBlendMode::kSrc);
3045 SkDebugf("isSrcOver %c= true\n", paint.isSrcOver() ? '=' : '!');
3046 }
3047
3048 #StdOut
3049 isSrcOver == true
3050 isSrcOver != true
3051 ##
3052 ##
3053
3054##
3055
3056#Topic ##
3057# ------------------------------------------------------------------------------
3058#Topic Path_Effect_Methods
3059
3060Path_Effect modifies the path geometry before drawing it.
3061Path_Effect may implement dashing, custom fill effects and custom stroke effects.
3062If Paint has no Path_Effect, the path geometry is unaltered when filled or stroked.
3063
3064#Example
3065#Height 160
3066 void draw(SkCanvas* canvas) {
3067 SkPaint paint;
3068 paint.setStyle(SkPaint::kStroke_Style);
3069 paint.setStrokeWidth(16);
3070 SkScalar intervals[] = {30, 10};
3071 paint.setPathEffect(SkDashPathEffect::Make(intervals, SK_ARRAY_COUNT(intervals), 1));
3072 canvas->drawRoundRect({20, 20, 120, 120}, 20, 20, paint);
3073 }
3074##
3075
3076#SeeAlso Path_Effect
3077
3078#Method SkPathEffect* getPathEffect() const
3079
3080 Returns Path_Effect if set, or nullptr.
3081 Does not alter Path_Effect Reference_Count.
3082
3083 #Return Path_Effect if previously set, nullptr otherwise ##
3084
3085 #Example
3086 void draw(SkCanvas* canvas) {
3087 SkPaint paint;
3088 SkDebugf("nullptr %c= path effect\n", paint.getPathEffect() ? '!' : '=');
3089 paint.setPathEffect(SkCornerPathEffect::Make(10));
3090 SkDebugf("nullptr %c= path effect\n", paint.getPathEffect() ? '!' : '=');
3091 }
3092
3093 #StdOut
3094 nullptr == path effect
3095 nullptr != path effect
3096 ##
3097 ##
3098
3099##
3100
3101
3102#Method sk_sp<SkPathEffect> refPathEffect() const
3103
3104 Returns Path_Effect if set, or nullptr.
3105 Increases Path_Effect Reference_Count by one.
3106
3107 #Return Path_Effect if previously set, nullptr otherwise ##
3108
3109 #Example
3110 void draw(SkCanvas* canvas) {
3111 SkPaint paint1, paint2;
3112 paint1.setPathEffect(SkArcToPathEffect::Make(10));
3113 SkDebugf("path effect unique: %s\n", paint1.getPathEffect()->unique() ? "true" : "false");
3114 paint2.setPathEffect(paint1.refPathEffect());
3115 SkDebugf("path effect unique: %s\n", paint1.getPathEffect()->unique() ? "true" : "false");
3116 }
3117
3118 #StdOut
3119 path effect unique: true
3120 path effect unique: false
3121 ##
3122 ##
3123
3124##
3125
3126
3127#Method void setPathEffect(sk_sp<SkPathEffect> pathEffect)
3128
Cary Clark6fc50412017-09-21 12:31:06 -04003129Sets Path_Effect to pathEffect, decreasing Reference_Count of the previous
3130Path_Effect. Pass nullptr to leave the path geometry unaltered.
3131
3132Increments pathEffect Reference_Count by one.
Cary Clark8032b982017-07-28 11:04:54 -04003133
3134 #Param pathEffect replace Path with a modification when drawn ##
3135
3136 #Example
3137 void draw(SkCanvas* canvas) {
3138 SkPaint paint;
3139 paint.setPathEffect(SkDiscretePathEffect::Make(3, 5));
3140 canvas->drawRect(SkRect::MakeXYWH(40, 40, 175, 175), paint);
3141 }
3142 ##
3143
3144##
3145
3146#Topic ##
3147# ------------------------------------------------------------------------------
3148#Topic Mask_Filter_Methods
3149
Cary Clarkce101242017-09-01 15:51:02 -04003150Mask_Filter uses coverage of the shape drawn to create Mask_Alpha.
Cary Clark8032b982017-07-28 11:04:54 -04003151Mask_Filter operates at a lower level than Rasterizer; Mask_Filter takes a Mask,
3152and returns a Mask.
Cary Clark6fc50412017-09-21 12:31:06 -04003153
3154Mask_Filter may change the geometry and transparency of the shape, such as
3155creating a blur effect. Set Mask_Filter to nullptr to prevent Mask_Filter from
3156modifying the draw.
Cary Clark8032b982017-07-28 11:04:54 -04003157
3158#Example
3159 void draw(SkCanvas* canvas) {
3160 SkPaint paint;
3161 paint.setMaskFilter(SkBlurMaskFilter::Make(kSolid_SkBlurStyle, 3));
3162 canvas->drawRect(SkRect::MakeXYWH(40, 40, 175, 175), paint);
3163 }
3164##
3165
3166#Method SkMaskFilter* getMaskFilter() const
3167
3168 Returns Mask_Filter if set, or nullptr.
3169 Does not alter Mask_Filter Reference_Count.
3170
3171 #Return Mask_Filter if previously set, nullptr otherwise ##
3172
3173 #Example
3174 void draw(SkCanvas* canvas) {
3175 SkPaint paint;
3176 SkDebugf("nullptr %c= mask filter\n", paint.getMaskFilter() ? '!' : '=');
3177 paint.setMaskFilter(SkBlurMaskFilter::Make(kOuter_SkBlurStyle, 3));
3178 SkDebugf("nullptr %c= mask filter\n", paint.getMaskFilter() ? '!' : '=');
3179 }
3180
3181 #StdOut
3182 nullptr == mask filter
3183 nullptr != mask filter
3184 ##
3185 ##
3186
3187##
3188
3189#Method sk_sp<SkMaskFilter> refMaskFilter() const
3190
3191 Returns Mask_Filter if set, or nullptr.
Cary Clark6fc50412017-09-21 12:31:06 -04003192
Cary Clark8032b982017-07-28 11:04:54 -04003193 Increases Mask_Filter Reference_Count by one.
3194
3195 #Return Mask_Filter if previously set, nullptr otherwise ##
3196
3197 #Example
3198 void draw(SkCanvas* canvas) {
3199 SkPaint paint1, paint2;
3200 paint1.setMaskFilter(SkBlurMaskFilter::Make(kNormal_SkBlurStyle, 1));
3201 SkDebugf("mask filter unique: %s\n", paint1.getMaskFilter()->unique() ? "true" : "false");
3202 paint2.setMaskFilter(paint1.refMaskFilter());
3203 SkDebugf("mask filter unique: %s\n", paint1.getMaskFilter()->unique() ? "true" : "false");
3204 }
3205
3206 #StdOut
3207 mask filter unique: true
3208 mask filter unique: false
3209 ##
3210 ##
3211
3212##
3213
3214#Method void setMaskFilter(sk_sp<SkMaskFilter> maskFilter)
3215
Cary Clark6fc50412017-09-21 12:31:06 -04003216Sets Mask_Filter to maskFilter, decreasing Reference_Count of the previous
3217Mask_Filter. Pass nullptr to clear Mask_Filter and leave Mask_Filter effect on
3218Mask_Alpha unaltered.
3219
3220Does not affect Rasterizer.
3221Increments maskFilter Reference_Count by one.
Cary Clark8032b982017-07-28 11:04:54 -04003222
3223 #Param maskFilter modifies clipping mask generated from drawn geometry ##
3224
3225 #Example
3226 void draw(SkCanvas* canvas) {
3227 SkPaint paint;
3228 paint.setStyle(SkPaint::kStroke_Style);
3229 paint.setStrokeWidth(10);
3230 paint.setMaskFilter(SkBlurMaskFilter::Make(kNormal_SkBlurStyle, 10));
3231 canvas->drawRect(SkRect::MakeXYWH(40, 40, 175, 175), paint);
3232 }
3233 ##
3234
3235##
3236
3237#Topic ##
3238# ------------------------------------------------------------------------------
3239#Topic Typeface_Methods
3240
3241Typeface identifies the font used when drawing and measuring text.
3242Typeface may be specified by name, from a file, or from a data stream.
3243The default Typeface defers to the platform-specific default font
3244implementation.
3245
3246#Example
3247#Height 100
3248 void draw(SkCanvas* canvas) {
3249 SkPaint paint;
3250 paint.setTypeface(SkTypeface::MakeDefault(SkTypeface::kBold));
3251 paint.setAntiAlias(true);
3252 paint.setTextSize(36);
3253 canvas->drawString("A Big Hello!", 10, 40, paint);
3254 paint.setTypeface(nullptr);
3255 paint.setFakeBoldText(true);
3256 canvas->drawString("A Big Hello!", 10, 80, paint);
3257 }
3258##
3259
3260#Method SkTypeface* getTypeface() const
3261
3262 Returns Typeface if set, or nullptr.
Cary Clark6fc50412017-09-21 12:31:06 -04003263 Increments Typeface Reference_Count by one.
Cary Clark8032b982017-07-28 11:04:54 -04003264
3265 #Return Typeface if previously set, nullptr otherwise ##
3266
3267 #Example
3268 void draw(SkCanvas* canvas) {
3269 SkPaint paint;
3270 SkDebugf("nullptr %c= typeface\n", paint.getTypeface() ? '!' : '=');
3271 paint.setTypeface(SkTypeface::MakeFromName("Times New Roman", SkFontStyle()));
3272 SkDebugf("nullptr %c= typeface\n", paint.getTypeface() ? '!' : '=');
3273 }
3274
3275 #StdOut
3276 nullptr == typeface
3277 nullptr != typeface
3278 ##
3279 ##
3280
3281##
3282
3283#Method sk_sp<SkTypeface> refTypeface() const
3284
3285 Increases Typeface Reference_Count by one.
3286
3287 #Return Typeface if previously set, nullptr otherwise ##
3288
3289 #Example
3290 void draw(SkCanvas* canvas) {
3291 SkPaint paint1, paint2;
3292 paint1.setTypeface(SkTypeface::MakeFromName("Times New Roman",
3293 SkFontStyle(SkFontStyle::kNormal_Weight, SkFontStyle::kNormal_Width,
3294 SkFontStyle::kItalic_Slant)));
3295 SkDebugf("typeface1 %c= typeface2\n",
3296 paint1.getTypeface() == paint2.getTypeface() ? '=' : '!');
3297 paint2.setTypeface(paint1.refTypeface());
3298 SkDebugf("typeface1 %c= typeface2\n",
3299 paint1.getTypeface() == paint2.getTypeface() ? '=' : '!');
3300 }
3301
3302 #StdOut
3303 typeface1 != typeface2
3304 typeface1 == typeface2
3305 ##
3306 ##
3307
3308##
3309
3310#Method void setTypeface(sk_sp<SkTypeface> typeface)
3311
Cary Clark6fc50412017-09-21 12:31:06 -04003312Sets Typeface to typeface, decreasing Reference_Count of the previous Typeface.
3313Pass nullptr to clear Typeface and use the default typeface. Increments
3314typeface Reference_Count by one.
Cary Clark8032b982017-07-28 11:04:54 -04003315
3316 #Param typeface font and style used to draw text ##
3317
3318 #Example
3319 #Height 64
3320 void draw(SkCanvas* canvas) {
3321 SkPaint paint;
3322 paint.setTypeface(SkTypeface::MakeFromName("Courier New", SkFontStyle()));
3323 canvas->drawString("Courier New", 10, 30, paint);
3324 paint.setTypeface(nullptr);
3325 canvas->drawString("default", 10, 50, paint);
3326 }
3327 ##
3328
3329##
3330
3331#Topic ##
3332# ------------------------------------------------------------------------------
3333#Topic Rasterizer_Methods
3334
3335Rasterizer controls how shapes are converted to Mask_Alpha.
3336Rasterizer operates at a higher level than Mask_Filter; Rasterizer takes a Path,
3337and returns a Mask.
Cary Clark6fc50412017-09-21 12:31:06 -04003338
Cary Clark8032b982017-07-28 11:04:54 -04003339Rasterizer may change the geometry and transparency of the shape, such as
3340creating a shadow effect. Rasterizer forms the base of Rasterizer_Layer, which
3341creates effects like embossing and outlining.
Cary Clark6fc50412017-09-21 12:31:06 -04003342
Cary Clarkce101242017-09-01 15:51:02 -04003343Rasterizer applies to Rect, Region, Round_Rect, Arcs, Circles, Ovals,
Cary Clark8032b982017-07-28 11:04:54 -04003344Path, and Text.
3345
3346#Example
3347#Height 64
3348 void draw(SkCanvas* canvas) {
3349 SkLayerRasterizer::Builder layerBuilder;
3350 SkPaint paint;
3351 paint.setAntiAlias(true);
3352 paint.setStyle(SkPaint::kStroke_Style);
3353 paint.setStrokeWidth(1);
3354 layerBuilder.addLayer(paint);
3355 paint.setAlpha(0x10);
3356 paint.setStyle(SkPaint::kFill_Style);
3357 paint.setBlendMode(SkBlendMode::kSrc);
3358 layerBuilder.addLayer(paint);
3359 paint.reset();
3360 paint.setAntiAlias(true);
3361 paint.setTextSize(50);
3362 paint.setRasterizer(layerBuilder.detach());
3363 canvas->drawString("outline", 10, 50, paint);
3364 }
3365##
3366
3367#Method SkRasterizer* getRasterizer() const
3368
3369 Returns Rasterizer if set, or nullptr.
3370 Does not alter Rasterizer Reference_Count.
3371
3372 #Return Rasterizer if previously set, nullptr otherwise ##
3373
3374 #Example
3375 #Function
3376 class DummyRasterizer : public SkRasterizer {
3377 public:
3378 SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(DummyRasterizer)
3379 };
3380
3381 sk_sp<SkFlattenable> DummyRasterizer::CreateProc(SkReadBuffer&) {
3382 return sk_make_sp<DummyRasterizer>();
3383 }
3384
3385 #Function ##
3386 void draw(SkCanvas* canvas) {
3387 SkPaint paint;
3388 DummyRasterizer dummy;
3389 SkDebugf("nullptr %c= rasterizer\n", paint.getRasterizer() ? '!' : '=');
3390 paint.setRasterizer(sk_make_sp<DummyRasterizer>());
3391 SkDebugf("nullptr %c= rasterizer\n", paint.getRasterizer() ? '!' : '=');
3392 }
3393
3394 #StdOut
3395 nullptr == rasterizer
3396 nullptr != rasterizer
3397 ##
3398 ##
3399
3400##
3401
3402#Method sk_sp<SkRasterizer> refRasterizer() const
3403
3404 Returns Rasterizer if set, or nullptr.
3405 Increases Rasterizer Reference_Count by one.
3406
3407 #Return Rasterizer if previously set, nullptr otherwise ##
3408
3409 #Example
3410 void draw(SkCanvas* canvas) {
3411 SkLayerRasterizer::Builder layerBuilder;
3412 SkPaint paint1, paint2;
3413 layerBuilder.addLayer(paint2);
3414 paint1.setRasterizer(layerBuilder.detach());
3415 SkDebugf("rasterizer unique: %s\n", paint1.getRasterizer()->unique() ? "true" : "false");
3416 paint2.setRasterizer(paint1.refRasterizer());
3417 SkDebugf("rasterizer unique: %s\n", paint1.getRasterizer()->unique() ? "true" : "false");
3418 }
3419
3420 #StdOut
3421 rasterizer unique: true
3422 rasterizer unique: false
3423 ##
3424 ##
3425
3426##
3427
3428#Method void setRasterizer(sk_sp<SkRasterizer> rasterizer)
3429
Cary Clark6fc50412017-09-21 12:31:06 -04003430Sets Rasterizer to rasterizer, decreasing Reference_Count of the previous
3431Rasterizer. Pass nullptr to clear Rasterizer and leave Rasterizer effect on
3432Mask_Alpha unaltered.
3433
3434Does not affect Mask_Filter.
3435Increments rasterizer Reference_Count by one.
Cary Clark8032b982017-07-28 11:04:54 -04003436
3437 #Param rasterizer how geometry is converted to Mask_Alpha ##
3438
3439 #Example
3440 #Height 64
3441 SkLayerRasterizer::Builder layerBuilder;
3442 SkPaint paint;
3443 paint.setAntiAlias(true);
3444 paint.setStyle(SkPaint::kStroke_Style);
3445 paint.setStrokeWidth(2);
3446 layerBuilder.addLayer(paint);
3447 paint.reset();
3448 paint.setAntiAlias(true);
3449 paint.setTextSize(50);
3450 paint.setMaskFilter(SkBlurMaskFilter::Make(kNormal_SkBlurStyle, 3));
3451 paint.setRasterizer(layerBuilder.detach());
3452 canvas->drawString("blurry out", 0, 50, paint);
3453 ##
3454
3455##
3456
3457#Topic ##
3458# ------------------------------------------------------------------------------
3459#Topic Image_Filter_Methods
3460
3461Image_Filter operates on the pixel representation of the shape, as modified by Paint
3462with Blend_Mode set to SkBlendMode::kSrcOver. Image_Filter creates a new bitmap,
3463which is drawn to the device using the set Blend_Mode.
Cary Clark6fc50412017-09-21 12:31:06 -04003464
Cary Clark8032b982017-07-28 11:04:54 -04003465Image_Filter is higher level than Mask_Filter; for instance, an Image_Filter
Cary Clarkce101242017-09-01 15:51:02 -04003466can operate on all channels of Color, while Mask_Filter generates Alpha only.
Cary Clark8032b982017-07-28 11:04:54 -04003467Image_Filter operates independently of and can be used in combination with
3468Mask_Filter and Rasterizer.
3469
3470#Example
3471 #ToDo explain why the two draws are so different ##
3472 void draw(SkCanvas* canvas) {
3473 SkPaint paint;
3474 paint.setStyle(SkPaint::kStroke_Style);
3475 paint.setStrokeWidth(2);
3476 SkRegion region;
3477 region.op( 10, 10, 50, 50, SkRegion::kUnion_Op);
3478 region.op( 10, 50, 90, 90, SkRegion::kUnion_Op);
3479 paint.setImageFilter(SkImageFilter::MakeBlur(5.0f, 5.0f, nullptr));
3480 canvas->drawRegion(region, paint);
3481 paint.setImageFilter(nullptr);
3482 paint.setMaskFilter(SkBlurMaskFilter::Make(kNormal_SkBlurStyle, 5));
3483 canvas->translate(100, 100);
3484 canvas->drawRegion(region, paint);
3485 }
3486##
3487
3488#Method SkImageFilter* getImageFilter() const
3489
3490 Returns Image_Filter if set, or nullptr.
3491 Does not alter Image_Filter Reference_Count.
3492
3493 #Return Image_Filter if previously set, nullptr otherwise ##
3494
3495 #Example
3496 void draw(SkCanvas* canvas) {
3497 SkPaint paint;
3498 SkDebugf("nullptr %c= image filter\n", paint.getImageFilter() ? '!' : '=');
3499 paint.setImageFilter(SkImageFilter::MakeBlur(kOuter_SkBlurStyle, 3, nullptr, nullptr));
3500 SkDebugf("nullptr %c= image filter\n", paint.getImageFilter() ? '!' : '=');
3501 }
3502
3503 #StdOut
3504 nullptr == image filter
3505 nullptr != image filter
3506 ##
3507 ##
3508
3509##
3510
3511#Method sk_sp<SkImageFilter> refImageFilter() const
3512
3513 Returns Image_Filter if set, or nullptr.
3514 Increases Image_Filter Reference_Count by one.
3515
3516 #Return Image_Filter if previously set, nullptr otherwise ##
3517
3518 #Example
3519 void draw(SkCanvas* canvas) {
3520 SkPaint paint1, paint2;
3521 paint1.setImageFilter(SkOffsetImageFilter::Make(25, 25, nullptr));
3522 SkDebugf("image filter unique: %s\n", paint1.getImageFilter()->unique() ? "true" : "false");
3523 paint2.setImageFilter(paint1.refImageFilter());
3524 SkDebugf("image filter unique: %s\n", paint1.getImageFilter()->unique() ? "true" : "false");
3525 }
3526
3527 #StdOut
3528 image filter unique: true
3529 image filter unique: false
3530 ##
3531 ##
3532
3533##
3534
3535#Method void setImageFilter(sk_sp<SkImageFilter> imageFilter)
3536
Cary Clark6fc50412017-09-21 12:31:06 -04003537Sets Image_Filter to imageFilter, decreasing Reference_Count of the previous
3538Image_Filter. Pass nullptr to clear Image_Filter, and remove Image_Filter effect
3539on drawing.
3540
3541Does not affect Rasterizer or Mask_Filter.
3542Increments imageFilter Reference_Count by one.
Cary Clark8032b982017-07-28 11:04:54 -04003543
3544 #Param imageFilter how Image is sampled when transformed ##
3545
3546 #Example
3547 #Height 160
3548 void draw(SkCanvas* canvas) {
3549 SkBitmap bitmap;
3550 bitmap.allocN32Pixels(100, 100);
3551 SkCanvas offscreen(bitmap);
3552 SkPaint paint;
3553 paint.setAntiAlias(true);
3554 paint.setColor(SK_ColorWHITE);
3555 paint.setTextSize(96);
3556 offscreen.clear(0);
3557 offscreen.drawString("e", 20, 70, paint);
3558 paint.setImageFilter(
3559 SkLightingImageFilter::MakePointLitDiffuse(SkPoint3::Make(80, 100, 10),
3560 SK_ColorWHITE, 1, 2, nullptr, nullptr));
3561 canvas->drawBitmap(bitmap, 0, 0, &paint);
3562 }
3563 ##
3564
3565##
3566
3567#Topic ##
3568# ------------------------------------------------------------------------------
3569#Topic Draw_Looper_Methods
3570
3571Draw_Looper sets a modifier that communicates state from one Draw_Layer
3572to another to construct the draw.
Cary Clark6fc50412017-09-21 12:31:06 -04003573
Cary Clark8032b982017-07-28 11:04:54 -04003574Draw_Looper draws one or more times, modifying the canvas and paint each time.
3575Draw_Looper may be used to draw multiple colors or create a colored shadow.
3576Set Draw_Looper to nullptr to prevent Draw_Looper from modifying the draw.
3577
3578#Example
3579#Height 128
3580 void draw(SkCanvas* canvas) {
3581 SkLayerDrawLooper::LayerInfo info;
3582 info.fPaintBits = (SkLayerDrawLooper::BitFlags) SkLayerDrawLooper::kColorFilter_Bit;
3583 info.fColorMode = SkBlendMode::kSrc;
3584 SkLayerDrawLooper::Builder looperBuilder;
3585 SkPaint* loopPaint = looperBuilder.addLayer(info);
3586 loopPaint->setColor(SK_ColorRED);
3587 info.fOffset.set(20, 20);
3588 loopPaint = looperBuilder.addLayer(info);
3589 loopPaint->setColor(SK_ColorBLUE);
3590 SkPaint paint;
3591 paint.setDrawLooper(looperBuilder.detach());
3592 canvas->drawCircle(50, 50, 50, paint);
3593 }
3594
3595##
3596
3597#Method SkDrawLooper* getDrawLooper() const
3598
3599 Returns Draw_Looper if set, or nullptr.
3600 Does not alter Draw_Looper Reference_Count.
3601
3602 #Return Draw_Looper if previously set, nullptr otherwise ##
3603
3604 #Example
3605 void draw(SkCanvas* canvas) {
3606 SkPaint paint;
3607 SkDebugf("nullptr %c= draw looper\n", paint.getDrawLooper() ? '!' : '=');
3608 SkLayerDrawLooper::Builder looperBuilder;
3609 paint.setDrawLooper(looperBuilder.detach());
3610 SkDebugf("nullptr %c= draw looper\n", paint.getDrawLooper() ? '!' : '=');
3611 }
3612
3613 #StdOut
3614 nullptr == draw looper
3615 nullptr != draw looper
3616 ##
3617 ##
3618
3619##
3620
3621#Method sk_sp<SkDrawLooper> refDrawLooper() const
3622
3623 Returns Draw_Looper if set, or nullptr.
3624 Increases Draw_Looper Reference_Count by one.
3625
3626 #Return Draw_Looper if previously set, nullptr otherwise ##
3627
3628 #Example
3629 void draw(SkCanvas* canvas) {
3630 SkPaint paint1, paint2;
3631 SkLayerDrawLooper::Builder looperBuilder;
3632 paint1.setDrawLooper(looperBuilder.detach());
3633 SkDebugf("draw looper unique: %s\n", paint1.getDrawLooper()->unique() ? "true" : "false");
3634 paint2.setDrawLooper(paint1.refDrawLooper());
3635 SkDebugf("draw looper unique: %s\n", paint1.getDrawLooper()->unique() ? "true" : "false");
3636 }
3637
3638 #StdOut
3639 draw looper unique: true
3640 draw looper unique: false
3641 ##
3642 ##
3643
3644##
3645
3646#Method SkDrawLooper* getLooper() const
3647
3648Deprecated.
3649
3650#Deprecated
3651(see bug.skia.org/6259)
3652#Deprecated ##
3653
3654#Return Draw_Looper if previously set, nullptr otherwise ##
3655##
3656
3657#Method void setDrawLooper(sk_sp<SkDrawLooper> drawLooper)
3658
Cary Clark6fc50412017-09-21 12:31:06 -04003659Sets Draw_Looper to drawLooper, decreasing Reference_Count of the previous
3660drawLooper. Pass nullptr to clear Draw_Looper and leave Draw_Looper effect on
3661drawing unaltered.
3662
3663Increments drawLooper Reference_Count by one.
Cary Clark8032b982017-07-28 11:04:54 -04003664
Cary Clarka523d2d2017-08-30 08:58:10 -04003665 #Param drawLooper iterates through drawing one or more time, altering Paint ##
Cary Clark8032b982017-07-28 11:04:54 -04003666
3667 #Example
3668 #Height 128
3669 void draw(SkCanvas* canvas) {
3670 SkPaint paint;
3671 paint.setDrawLooper(SkBlurDrawLooper::Make(0x7FFF0000, 4, -5, -10));
3672 paint.setStyle(SkPaint::kStroke_Style);
3673 paint.setStrokeWidth(10);
3674 paint.setAntiAlias(true);
3675 paint.setColor(0x7f0000ff);
3676 canvas->drawCircle(70, 70, 50, paint);
3677 }
3678 ##
3679
3680##
3681
3682#Method void setLooper(sk_sp<SkDrawLooper> drawLooper)
3683
3684Deprecated.
3685
3686#Deprecated
3687(see bug.skia.org/6259)
3688#Deprecated ##
3689
3690#Param drawLooper sets Draw_Looper to drawLooper ##
3691
3692##
3693
3694#Topic ##
3695# ------------------------------------------------------------------------------
3696#Topic Text_Align
3697
3698#Enum Align
3699#Code
3700 enum Align {
3701 kLeft_Align,
3702 kCenter_Align,
3703 kRight_Align,
3704 };
3705##
3706
3707Align adjusts the text relative to the text position.
Cary Clarkce101242017-09-01 15:51:02 -04003708Align affects Glyphs drawn with: SkCanvas::drawText, SkCanvas::drawPosText,
Cary Clark8032b982017-07-28 11:04:54 -04003709SkCanvas::drawPosTextH, SkCanvas::drawTextOnPath,
3710SkCanvas::drawTextOnPathHV, SkCanvas::drawTextRSXform, SkCanvas::drawTextBlob,
3711and SkCanvas::drawString;
Cary Clarkce101242017-09-01 15:51:02 -04003712as well as calls that place text Glyphs like getTextWidths and getTextPath.
Cary Clark8032b982017-07-28 11:04:54 -04003713
3714The text position is set by the font for both horizontal and vertical text.
3715Typically, for horizontal text, the position is to the left side of the glyph on the
3716base line; and for vertical text, the position is the horizontal center of the glyph
3717at the caps height.
3718
3719Align adjusts the glyph position to center it or move it to abut the position
3720using the metrics returned by the font.
3721
3722Align defaults to kLeft_Align.
3723
3724#Const kLeft_Align 0
3725 Leaves the glyph at the position computed by the font offset by the text position.
3726##
3727
3728#Const kCenter_Align 1
3729 Moves the glyph half its width if Flags has kVerticalText_Flag clear, and
3730 half its height if Flags has kVerticalText_Flag set.
3731##
3732
3733#Const kRight_Align 2
3734 Moves the glyph by its width if Flags has kVerticalText_Flag clear,
3735 and by its height if Flags has kVerticalText_Flag set.
3736##
3737
3738#Enum ##
3739
3740#Enum
3741
3742#Code
3743 enum {
Cary Clarkbad5ad72017-08-03 17:14:08 -04003744 kAlignCount = 3,
Cary Clark8032b982017-07-28 11:04:54 -04003745 };
3746##
3747
3748#Const kAlignCount 3
3749 The number of different Text_Align values defined.
3750##
3751
3752#Enum ##
3753
3754#Example
3755 #Height 160
3756 #Description
3757 Each position separately moves the glyph in drawPosText.
3758 ##
3759 void draw(SkCanvas* canvas) {
3760 SkPaint paint;
3761 paint.setTextSize(40);
3762 SkPoint position[] = {{100, 50}, {150, 40}};
3763 for (SkPaint::Align a : { SkPaint::kLeft_Align,
3764 SkPaint::kCenter_Align,
3765 SkPaint::kRight_Align}) {
3766 paint.setTextAlign(a);
3767 canvas->drawPosText("Aa", 2, position, paint);
3768 canvas->translate(0, 50);
3769 }
3770 }
3771##
3772
3773#Example
3774 #Height 160
3775 #Description
3776 Vertical_Text treats kLeft_Align as top align, and kRight_Align as bottom align.
3777 ##
3778 void draw(SkCanvas* canvas) {
3779 SkPaint paint;
3780 paint.setTextSize(40);
3781 paint.setVerticalText(true);
3782 for (SkPaint::Align a : { SkPaint::kLeft_Align,
3783 SkPaint::kCenter_Align,
3784 SkPaint::kRight_Align }) {
3785 paint.setTextAlign(a);
3786 canvas->drawString("Aa", 50, 80, paint);
3787 canvas->translate(50, 0);
3788 }
3789 }
3790##
3791
3792#Method Align getTextAlign() const
3793
3794 Returns Text_Align.
3795 Returns kLeft_Align if Text_Align has not been set.
3796
3797 #Return text placement relative to position ##
3798
3799 #Example
3800 SkPaint paint;
3801 SkDebugf("kLeft_Align %c= default\n", SkPaint::kLeft_Align == paint.getTextAlign() ? '=' : '!');
3802
3803 #StdOut
3804 kLeft_Align == default
3805 ##
3806 ##
3807##
3808
3809#Method void setTextAlign(Align align)
3810
3811 Sets Text_Align to align.
3812 Has no effect if align is an invalid value.
3813
3814 #Param align text placement relative to position ##
3815
3816 #Example
3817 #Height 160
3818 #Description
3819 Text is left-aligned by default, and then set to center. Setting the
3820 alignment out of range has no effect.
3821 ##
3822 void draw(SkCanvas* canvas) {
3823 SkPaint paint;
3824 paint.setTextSize(40);
3825 canvas->drawString("Aa", 100, 50, paint);
3826 paint.setTextAlign(SkPaint::kCenter_Align);
3827 canvas->drawString("Aa", 100, 100, paint);
3828 paint.setTextAlign((SkPaint::Align) SkPaint::kAlignCount);
3829 canvas->drawString("Aa", 100, 150, paint);
3830 }
3831 ##
3832
3833##
3834
3835#Topic ##
3836# ------------------------------------------------------------------------------
3837#Topic Text_Size
3838
3839Text_Size adjusts the overall text size in points.
3840Text_Size can be set to any positive value or zero.
3841Text_Size defaults to 12.
3842Set SkPaintDefaults_TextSize at compile time to change the default setting.
3843
3844#Example
3845#Height 135
3846 void draw(SkCanvas* canvas) {
3847 SkPaint paint;
3848 canvas->drawString("12 point", 10, 20, paint);
3849 paint.setTextSize(24);
3850 canvas->drawString("24 point", 10, 60, paint);
3851 paint.setTextSize(48);
3852 canvas->drawString("48 point", 10, 120, paint);
3853 }
3854##
3855
3856#Method SkScalar getTextSize() const
3857
3858 Returns Text_Size in points.
3859
3860 #Return typographic height of text ##
3861
3862 #Example
3863 SkPaint paint;
3864 SkDebugf("12 %c= default text size\n", 12 == paint.getTextSize() ? '=' : '!');
3865 ##
3866
3867##
3868
3869#Method void setTextSize(SkScalar textSize)
3870
3871 Sets Text_Size in points.
3872 Has no effect if textSize is not greater than or equal to zero.
3873
3874 #Param textSize typographic height of text ##
3875
3876 #Example
3877 SkPaint paint;
3878 SkDebugf("12 %c= text size\n", 12 == paint.getTextSize() ? '=' : '!');
3879 paint.setTextSize(-20);
3880 SkDebugf("12 %c= text size\n", 12 == paint.getTextSize() ? '=' : '!');
3881 ##
3882
3883##
3884
3885#Topic ##
3886# ------------------------------------------------------------------------------
3887#Topic Text_Scale_X
3888
3889Text_Scale_X adjusts the text horizontal scale.
3890Text scaling approximates condensed and expanded type faces when the actual face
3891is not available.
3892Text_Scale_X can be set to any value.
3893Text_Scale_X defaults to 1.
3894
3895#Example
3896#Height 128
3897 void draw(SkCanvas* canvas) {
3898 SkPaint paint;
3899 paint.setAntiAlias(true);
3900 paint.setTextSize(24);
3901 paint.setTextScaleX(.8f);
3902 canvas->drawString("narrow", 10, 20, paint);
3903 paint.setTextScaleX(1);
3904 canvas->drawString("normal", 10, 60, paint);
3905 paint.setTextScaleX(1.2f);
3906 canvas->drawString("wide", 10, 100, paint);
3907 }
3908##
3909
3910#Method SkScalar getTextScaleX() const
3911
3912 Returns Text_Scale_X.
3913 Default value is 1.
3914
3915 #Return text horizontal scale ##
3916
3917 #Example
3918 SkPaint paint;
3919 SkDebugf("1 %c= default text scale x\n", 1 == paint.getTextScaleX() ? '=' : '!');
3920 ##
3921
3922##
3923
3924
3925#Method void setTextScaleX(SkScalar scaleX)
3926
3927 Sets Text_Scale_X.
3928 Default value is 1.
3929
3930 #Param scaleX text horizontal scale ##
3931
3932 #Example
3933 SkPaint paint;
3934 paint.setTextScaleX(0.f / 0.f);
3935 SkDebugf("text scale %s-a-number\n", SkScalarIsNaN(paint.getTextScaleX()) ? "not" : "is");
3936 ##
3937
3938##
3939
3940#Topic ##
3941
3942#Topic Text_Skew_X
3943
3944
3945Text_Skew_X adjusts the text horizontal slant.
3946Text skewing approximates italic and oblique type faces when the actual face
3947is not available.
3948Text_Skew_X can be set to any value.
3949Text_Skew_X defaults to 0.
3950
3951#Example
3952#Height 128
3953 void draw(SkCanvas* canvas) {
3954 SkPaint paint;
3955 paint.setAntiAlias(true);
3956 paint.setTextSize(24);
3957 paint.setTextSkewX(-.25f);
3958 canvas->drawString("right-leaning", 10, 100, paint);
3959 paint.setTextSkewX(0);
3960 canvas->drawString("normal", 10, 60, paint);
3961 paint.setTextSkewX(.25f);
3962 canvas->drawString("left-leaning", 10, 20, paint);
3963 }
3964##
3965
3966#Method SkScalar getTextSkewX() const
3967
3968 Returns Text_Skew_X.
3969 Default value is zero.
3970
3971 #Return additional shear in x-axis relative to y-axis ##
3972
3973 #Example
3974 SkPaint paint;
3975 SkDebugf("0 %c= default text skew x\n", 0 == paint.getTextSkewX() ? '=' : '!');
3976 ##
3977
3978##
3979
3980#Method void setTextSkewX(SkScalar skewX)
3981
3982 Sets Text_Skew_X.
3983 Default value is zero.
3984
3985 #Param skewX additional shear in x-axis relative to y-axis ##
3986
3987 #Example
3988 SkPaint paint;
3989 paint.setTextScaleX(1.f / 0.f);
3990 SkDebugf("text scale %s-finite\n", SkScalarIsFinite(paint.getTextScaleX()) ? "is" : "not");
3991 ##
3992
3993##
3994
3995#Topic ##
3996
3997# ------------------------------------------------------------------------------
3998#Topic Text_Encoding
3999
4000#Enum TextEncoding
4001
4002#Code
4003 enum TextEncoding {
4004 kUTF8_TextEncoding,
4005 kUTF16_TextEncoding,
4006 kUTF32_TextEncoding,
Cary Clarkbad5ad72017-08-03 17:14:08 -04004007 kGlyphID_TextEncoding,
Cary Clark8032b982017-07-28 11:04:54 -04004008 };
4009##
4010
Cary Clark6fc50412017-09-21 12:31:06 -04004011TextEncoding determines whether text specifies character codes and their encoded
Cary Clarkbc5697d2017-10-04 14:31:33 -04004012size, or glyph indices. Characters are encoded as specified by the
Cary Clark6fc50412017-09-21 12:31:06 -04004013#A Unicode standard # http://unicode.org/standard/standard.html ##
4014.
4015
Cary Clark8032b982017-07-28 11:04:54 -04004016Character codes encoded size are specified by UTF-8, UTF-16, or UTF-32.
Cary Clarkbc5697d2017-10-04 14:31:33 -04004017All character code formats are able to represent all of Unicode, differing only
Cary Clark8032b982017-07-28 11:04:54 -04004018in the total storage required.
4019
Cary Clark6fc50412017-09-21 12:31:06 -04004020#A UTF-8 (RFC 3629) # https://tools.ietf.org/html/rfc3629 ##
4021 encodes each character as one or more 8-bit bytes.
4022
4023#A UTF-16 (RFC 2781) # https://tools.ietf.org/html/rfc2781 ##
4024 encodes each character as one or two 16-bit words.
4025
4026#A UTF-32 # http://www.unicode.org/versions/Unicode5.0.0/ch03.pdf ##
4027 encodes each character as one 32-bit word.
Cary Clark8032b982017-07-28 11:04:54 -04004028
4029Font_Manager uses font data to convert character code points into glyph indices.
4030A glyph index is a 16-bit word.
4031
4032TextEncoding is set to kUTF8_TextEncoding by default.
4033
4034#Const kUTF8_TextEncoding 0
4035Uses bytes to represent UTF-8 or ASCII.
4036##
4037#Const kUTF16_TextEncoding 1
4038Uses two byte words to represent most of Unicode.
4039##
4040#Const kUTF32_TextEncoding 2
4041Uses four byte words to represent all of Unicode.
4042##
4043#Const kGlyphID_TextEncoding 3
4044Uses two byte words to represent glyph indices.
4045##
4046
4047#Enum ##
4048
4049#Example
4050#Height 128
4051#Description
Cary Clarkbc5697d2017-10-04 14:31:33 -04004052First line is encoded in UTF-8.
4053Second line is encoded in UTF-16.
4054Third line is encoded in UTF-32.
Cary Clark8032b982017-07-28 11:04:54 -04004055Fourth line has 16 bit glyph indices.
4056##
4057void draw(SkCanvas* canvas) {
4058 SkPaint paint;
4059 const char hello8[] = "Hello" "\xE2" "\x98" "\xBA";
4060 const uint16_t hello16[] = { 'H', 'e', 'l', 'l', 'o', 0x263A };
4061 const uint32_t hello32[] = { 'H', 'e', 'l', 'l', 'o', 0x263A };
4062 paint.setTextSize(24);
4063 canvas->drawText(hello8, sizeof(hello8) - 1, 10, 30, paint);
4064 paint.setTextEncoding(SkPaint::kUTF16_TextEncoding);
4065 canvas->drawText(hello16, sizeof(hello16), 10, 60, paint);
4066 paint.setTextEncoding(SkPaint::kUTF32_TextEncoding);
4067 canvas->drawText(hello32, sizeof(hello32), 10, 90, paint);
4068 uint16_t glyphs[SK_ARRAY_COUNT(hello32)];
4069 paint.textToGlyphs(hello32, sizeof(hello32), glyphs);
4070 paint.setTextEncoding(SkPaint::kGlyphID_TextEncoding);
4071 canvas->drawText(glyphs, sizeof(glyphs), 10, 120, paint);
4072}
4073##
4074
4075#Method TextEncoding getTextEncoding() const
4076
4077 Returns Text_Encoding.
4078 Text_Encoding determines how character code points are mapped to font glyph indices.
4079
4080 #Return one of: kUTF8_TextEncoding, kUTF16_TextEncoding, kUTF32_TextEncoding, or
4081 kGlyphID_TextEncoding
4082 ##
4083
4084 #Example
4085 SkPaint paint;
4086 SkDebugf("kUTF8_TextEncoding %c= text encoding\n",
4087 SkPaint::kUTF8_TextEncoding == paint.getTextEncoding() ? '=' : '!');
4088 paint.setTextEncoding(SkPaint::kGlyphID_TextEncoding);
4089 SkDebugf("kGlyphID_TextEncoding %c= text encoding\n",
4090 SkPaint::kGlyphID_TextEncoding == paint.getTextEncoding() ? '=' : '!');
4091
4092 #StdOut
4093 kUTF8_TextEncoding == text encoding
4094 kGlyphID_TextEncoding == text encoding
4095 ##
4096 ##
4097
4098##
4099
4100
4101#Method void setTextEncoding(TextEncoding encoding)
4102
4103 Sets Text_Encoding to encoding.
4104 Text_Encoding determines how character code points are mapped to font glyph indices.
4105 Invalid values for encoding are ignored.
4106
4107 #Param encoding one of: kUTF8_TextEncoding, kUTF16_TextEncoding, kUTF32_TextEncoding, or
Cary Clark579985c2017-07-31 11:48:27 -04004108 kGlyphID_TextEncoding
4109 #Param ##
Cary Clark8032b982017-07-28 11:04:54 -04004110
4111 #Example
4112 SkPaint paint;
4113 paint.setTextEncoding((SkPaint::TextEncoding) 4);
4114 SkDebugf("4 %c= text encoding\n", 4 == paint.getTextEncoding() ? '=' : '!');
4115
4116 #StdOut
4117 4 != text encoding
4118 ##
4119 ##
4120
4121##
4122
4123#Topic ##
4124# ------------------------------------------------------------------------------
4125#Topic Font_Metrics
4126
Cary Clarkce101242017-09-01 15:51:02 -04004127Font_Metrics describe dimensions common to the Glyphs in Typeface.
Cary Clark8032b982017-07-28 11:04:54 -04004128The dimensions are computed by Font_Manager from font data and do not take
4129Paint settings other than Text_Size into account.
4130
4131Font dimensions specify the anchor to the left of the glyph at baseline as the origin.
4132X-axis values to the left of the glyph are negative, and to the right of the left glyph edge
4133are positive.
4134Y-axis values above the baseline are negative, and below the baseline are positive.
4135
4136#Example
4137#Width 512
4138void draw(SkCanvas* canvas) {
4139 SkPaint paint;
4140 paint.setAntiAlias(true);
4141 paint.setTextSize(120);
4142 SkPaint::FontMetrics fm;
4143 SkScalar lineHeight = paint.getFontMetrics(&fm);
4144 SkPoint pt = { 70, 180 };
4145 canvas->drawString("M", pt.fX, pt.fY, paint);
4146 canvas->drawLine(pt.fX, pt.fY, pt.fX, pt.fY + fm.fTop, paint);
4147 SkScalar ascent = pt.fY + fm.fAscent;
4148 canvas->drawLine(pt.fX - 25, ascent, pt.fX - 25, ascent + lineHeight, paint);
4149 canvas->drawLine(pt.fX - 50, pt.fY, pt.fX - 50, pt.fY + fm.fDescent, paint);
4150 canvas->drawLine(pt.fX + 100, pt.fY, pt.fX + 100, pt.fY + fm.fAscent, paint);
4151 canvas->drawLine(pt.fX + 125, pt.fY, pt.fX + 125, pt.fY - fm.fXHeight, paint);
4152 canvas->drawLine(pt.fX + 150, pt.fY, pt.fX + 150, pt.fY - fm.fCapHeight, paint);
4153 canvas->drawLine(pt.fX + 5, pt.fY, pt.fX + 5, pt.fY + fm.fBottom, paint);
4154 SkScalar xmin = pt.fX + fm.fXMin;
4155 canvas->drawLine(xmin, pt.fY + 60, xmin + fm.fMaxCharWidth, pt.fY + 60, paint);
4156 canvas->drawLine(xmin, pt.fY - 145, pt.fX, pt.fY - 145, paint);
4157 canvas->drawLine(pt.fX + fm.fXMax, pt.fY - 160, pt.fX, pt.fY - 160, paint);
4158 SkScalar upos = pt.fY + fm.fUnderlinePosition;
4159 canvas->drawLine(pt.fX + 25, upos, pt.fX + 130, upos, paint);
4160 SkScalar urad = fm.fUnderlineThickness / 2;
4161 canvas->drawLine(pt.fX + 130, upos - urad, pt.fX + 160, upos - urad, paint);
4162 canvas->drawLine(pt.fX + 130, upos + urad, pt.fX + 160, upos + urad, paint);
4163 paint.setTextSize(12);
4164 canvas->drawString("x-min", pt.fX - 50, pt.fY - 148, paint);
4165 canvas->drawString("x-max", pt.fX + 140, pt.fY - 150, paint);
4166 canvas->drawString("max char width", pt.fX + 120, pt.fY + 57, paint);
4167 canvas->drawString("underline position", pt.fX + 30, pt.fY + 22, paint);
4168 canvas->drawString("underline thickness", pt.fX + 162, pt.fY + 13, paint);
4169 canvas->rotate(-90);
4170 canvas->drawString("descent", -pt.fY - 30, pt.fX - 54, paint);
4171 canvas->drawString("line height", -pt.fY, pt.fX - 29, paint);
4172 canvas->drawString("top", -pt.fY + 30, pt.fX - 4, paint);
4173 canvas->drawString("ascent", -pt.fY, pt.fX + 110, paint);
4174 canvas->drawString("x-height", -pt.fY, pt.fX + 135, paint);
4175 canvas->drawString("cap-height", -pt.fY, pt.fX + 160, paint);
4176 canvas->drawString("bottom", -pt.fY - 50, pt.fX + 15, paint);
4177}
4178##
4179
4180#Struct FontMetrics
4181
4182#Code
4183 struct FontMetrics {
4184 enum FontMetricsFlags {
4185 kUnderlineThicknessIsValid_Flag = 1 << 0,
4186 kUnderlinePositionIsValid_Flag = 1 << 1,
4187 kStrikeoutThicknessIsValid_Flag = 1 << 2,
4188 kStrikeoutPositionIsValid_Flag = 1 << 3,
4189 };
4190
4191 uint32_t fFlags;
4192 SkScalar fTop;
4193 SkScalar fAscent;
4194 SkScalar fDescent;
4195 SkScalar fBottom;
4196 SkScalar fLeading;
4197 SkScalar fAvgCharWidth;
4198 SkScalar fMaxCharWidth;
4199 SkScalar fXMin;
4200 SkScalar fXMax;
4201 SkScalar fXHeight;
4202 SkScalar fCapHeight;
4203 SkScalar fUnderlineThickness;
4204 SkScalar fUnderlinePosition;
4205 SkScalar fStrikeoutThickness;
4206 SkScalar fStrikeoutPosition;
4207
4208 bool hasUnderlineThickness(SkScalar* thickness) const;
4209 bool hasUnderlinePosition(SkScalar* position) const;
4210 bool hasStrikeoutThickness(SkScalar* thickness) const;
4211 bool hasStrikeoutPosition(SkScalar* position) const;
4212 };
4213##
4214
Cary Clark154beea2017-10-26 07:58:48 -04004215 FontMetrics is filled out by getFontMetrics. FontMetrics contents reflect the values
4216 computed by Font_Manager using Typeface. Values are set to zero if they are
4217 not available.
Cary Clarke4aa3712017-09-15 02:56:12 -04004218
Cary Clark154beea2017-10-26 07:58:48 -04004219 fUnderlineThickness and fUnderlinePosition have a bit set in fFlags if their values
4220 are valid, since their value may be zero.
4221
4222 fStrikeoutThickness and fStrikeoutPosition have a bit set in fFlags if their values
4223 are valid, since their value may be zero.
4224
4225 #Enum FontMetricsFlags
Cary Clarke4aa3712017-09-15 02:56:12 -04004226
Cary Clark8032b982017-07-28 11:04:54 -04004227 #Code
4228 enum FontMetricsFlags {
4229 kUnderlineThicknessIsValid_Flag = 1 << 0,
4230 kUnderlinePositionIsValid_Flag = 1 << 1,
4231 kStrikeoutThicknessIsValid_Flag = 1 << 2,
4232 kStrikeoutPositionIsValid_Flag = 1 << 3,
4233 };
4234 ##
4235
Cary Clark154beea2017-10-26 07:58:48 -04004236 FontMetricsFlags are set in fFlags when underline and strikeout metrics are valid;
4237 the underline or strikeout metric may be valid and zero.
4238 Fonts with embedded bitmaps may not have valid underline or strikeout metrics.
4239
Cary Clark8032b982017-07-28 11:04:54 -04004240 #Const kUnderlineThicknessIsValid_Flag 0x0001
4241 Set if fUnderlineThickness is valid.
4242 ##
4243 #Const kUnderlinePositionIsValid_Flag 0x0002
4244 Set if fUnderlinePosition is valid.
4245 ##
4246 #Const kStrikeoutThicknessIsValid_Flag 0x0004
4247 Set if fStrikeoutThickness is valid.
4248 ##
4249 #Const kStrikeoutPositionIsValid_Flag 0x0008
4250 Set if fStrikeoutPosition is valid.
4251 ##
4252
4253 #Enum ##
4254
4255 #Member uint32_t fFlags
4256 fFlags is set when underline metrics are valid.
4257 ##
4258
4259 #Member SkScalar fTop
4260 Largest height for any glyph.
4261 A measure from the baseline, and is less than or equal to zero.
4262 ##
4263
4264 #Member SkScalar fAscent
4265 Recommended distance above the baseline to reserve for a line of text.
4266 A measure from the baseline, and is less than or equal to zero.
4267 ##
4268
4269 #Member SkScalar fDescent
4270 Recommended distance below the baseline to reserve for a line of text.
4271 A measure from the baseline, and is greater than or equal to zero.
4272 ##
4273
4274 #Member SkScalar fBottom
4275 Greatest extent below the baseline for any glyph.
4276 A measure from the baseline, and is greater than or equal to zero.
4277 ##
4278
4279 #Member SkScalar fLeading
4280 Recommended distance to add between lines of text.
4281 Greater than or equal to zero.
4282 ##
4283
4284 #Member SkScalar fAvgCharWidth
4285 Average character width, if it is available.
4286 Zero if no average width is stored in the font.
4287 ##
4288
4289 #Member SkScalar fMaxCharWidth
4290 Maximum character width.
4291 ##
4292
4293 #Member SkScalar fXMin
Cary Clarkce101242017-09-01 15:51:02 -04004294 Minimum bounding box x value for all Glyphs.
Cary Clark8032b982017-07-28 11:04:54 -04004295 Typically less than zero.
4296 ##
4297
4298 #Member SkScalar fXMax
Cary Clarkce101242017-09-01 15:51:02 -04004299 Maximum bounding box x value for all Glyphs.
Cary Clark8032b982017-07-28 11:04:54 -04004300 Typically greater than zero.
4301 ##
4302
4303 #Member SkScalar fXHeight
4304 Height of a lower-case 'x'.
4305 May be zero if no lower-case height is stored in the font.
4306 ##
4307
4308 #Member SkScalar fCapHeight
4309 Height of an upper-case letter.
4310 May be zero if no upper-case height is stored in the font.
4311 ##
4312
4313 #Member SkScalar fUnderlineThickness
4314 Underline thickness. If the metric
4315 is valid, the kUnderlineThicknessIsValid_Flag is set in fFlags.
4316 If kUnderlineThicknessIsValid_Flag is clear, fUnderlineThickness is zero.
4317 ##
4318
4319 #Member SkScalar fUnderlinePosition
4320 Underline position relative to the baseline.
4321 It may be negative, to draw the underline above the baseline, zero
4322 to draw the underline on the baseline, or positive to draw the underline
4323 below the baseline.
4324
4325 If the metric is valid, the kUnderlinePositionIsValid_Flag is set in fFlags.
4326 If kUnderlinePositionIsValid_Flag is clear, fUnderlinePosition is zero.
4327 ##
4328
4329 #Member SkScalar fStrikeoutThickness
4330 Strikeout thickness. If the metric
4331 is valid, the kStrikeoutThicknessIsValid_Flag is set in fFlags.
4332 If kStrikeoutThicknessIsValid_Flag is clear, fStrikeoutThickness is zero.
4333 ##
4334
4335 #Member SkScalar fStrikeoutPosition
4336 Strikeout position relative to the baseline.
4337 It may be negative, to draw the strikeout above the baseline, zero
4338 to draw the strikeout on the baseline, or positive to draw the strikeout
4339 below the baseline.
4340
4341 If the metric is valid, the kStrikeoutPositionIsValid_Flag is set in fFlags.
4342 If kStrikeoutPositionIsValid_Flag is clear, fStrikeoutPosition is zero.
4343 ##
4344
4345 #Method bool hasUnderlineThickness(SkScalar* thickness) const
4346
4347 If Font_Metrics has a valid underline thickness, return true, and set
Cary Clarkce101242017-09-01 15:51:02 -04004348 thickness to that value. If the underline thickness is not valid,
4349 return false, and ignore thickness.
Cary Clark8032b982017-07-28 11:04:54 -04004350
4351 #Param thickness storage for underline width ##
4352
4353 #Return true if font specifies underline width ##
4354
4355 #NoExample
4356 ##
4357 ##
4358
4359 #Method bool hasUnderlinePosition(SkScalar* position) const
4360
4361 If Font_Metrics has a valid underline position, return true, and set
Cary Clarkce101242017-09-01 15:51:02 -04004362 position to that value. If the underline position is not valid,
4363 return false, and ignore position.
Cary Clark8032b982017-07-28 11:04:54 -04004364
4365 #Param position storage for underline position ##
4366
4367 #Return true if font specifies underline position ##
4368
4369 #NoExample
4370 ##
4371 ##
4372
4373 #Method bool hasStrikeoutThickness(SkScalar* thickness) const
4374
4375 If Font_Metrics has a valid strikeout thickness, return true, and set
Cary Clarkce101242017-09-01 15:51:02 -04004376 thickness to that value. If the underline thickness is not valid,
4377 return false, and ignore thickness.
Cary Clark8032b982017-07-28 11:04:54 -04004378
4379 #Param thickness storage for strikeout width ##
4380
4381 #Return true if font specifies strikeout width ##
4382
4383 #NoExample
4384 ##
4385 ##
4386
4387 #Method bool hasStrikeoutPosition(SkScalar* position) const
4388
4389 If Font_Metrics has a valid strikeout position, return true, and set
Cary Clarkce101242017-09-01 15:51:02 -04004390 position to that value. If the underline position is not valid,
4391 return false, and ignore position.
Cary Clark8032b982017-07-28 11:04:54 -04004392
4393 #Param position storage for strikeout position ##
4394
4395 #Return true if font specifies strikeout position ##
4396
4397 #NoExample
4398 ##
4399 ##
4400
4401#Struct ##
4402
4403#Method SkScalar getFontMetrics(FontMetrics* metrics, SkScalar scale = 0) const
4404
4405 Returns Font_Metrics associated with Typeface.
4406 The return value is the recommended spacing between lines: the sum of metrics
4407 descent, ascent, and leading.
4408 If metrics is not nullptr, Font_Metrics is copied to metrics.
4409 Results are scaled by Text_Size but does not take into account
4410 dimensions required by Text_Scale_X, Text_Skew_X, Fake_Bold,
4411 Style_Stroke, and Path_Effect.
4412 Results can be additionally scaled by scale; a scale of zero
4413 is ignored.
4414
4415 #Param metrics storage for Font_Metrics from Typeface; may be nullptr ##
4416 #Param scale additional multiplier for returned values ##
4417
4418 #Return recommended spacing between lines ##
4419
4420 #Example
4421 #Height 128
4422 void draw(SkCanvas* canvas) {
4423 SkPaint paint;
4424 paint.setTextSize(32);
4425 SkScalar lineHeight = paint.getFontMetrics(nullptr);
4426 canvas->drawString("line 1", 10, 40, paint);
4427 canvas->drawString("line 2", 10, 40 + lineHeight, paint);
4428 paint.setStyle(SkPaint::kStroke_Style);
4429 paint.setStrokeWidth(10);
4430 lineHeight = paint.getFontMetrics(nullptr, 1.10f); // account for stroke height
4431 canvas->drawString("line 3", 120, 40, paint);
4432 canvas->drawString("line 4", 120, 40 + lineHeight, paint);
4433 }
4434 ##
4435
4436 #SeeAlso Text_Size Typeface Typeface_Methods
4437
4438##
4439
4440
4441#Method SkScalar getFontSpacing() const
4442
4443 Returns the recommended spacing between lines: the sum of metrics
4444 descent, ascent, and leading.
4445 Result is scaled by Text_Size but does not take into account
4446 dimensions required by stroking and Path_Effect.
Cary Clark579985c2017-07-31 11:48:27 -04004447 Returns the same result as getFontMetrics.
Cary Clark8032b982017-07-28 11:04:54 -04004448
4449 #Return recommended spacing between lines ##
4450
4451 #Example
4452 SkPaint paint;
4453 for (SkScalar textSize : { 12, 18, 24, 32 } ) {
4454 paint.setTextSize(textSize);
4455 SkDebugf("textSize: %g fontSpacing: %g\n", textSize, paint.getFontSpacing());
4456 }
4457
4458 #StdOut
4459 textSize: 12 fontSpacing: 13.9688
4460 textSize: 18 fontSpacing: 20.9531
4461 textSize: 24 fontSpacing: 27.9375
4462 textSize: 32 fontSpacing: 37.25
4463 ##
4464 ##
4465
4466##
4467
4468
4469#Method SkRect getFontBounds() const
4470
Cary Clarkce101242017-09-01 15:51:02 -04004471Returns the union of bounds of all Glyphs.
Cary Clark8032b982017-07-28 11:04:54 -04004472Returned dimensions are computed by Font_Manager from font data,
Cary Clark579985c2017-07-31 11:48:27 -04004473ignoring Hinting. Includes Text_Size, Text_Scale_X,
Cary Clark8032b982017-07-28 11:04:54 -04004474and Text_Skew_X, but not Fake_Bold or Path_Effect.
4475
4476If Text_Size is large, Text_Scale_X is one, and Text_Skew_X is zero,
Cary Clark579985c2017-07-31 11:48:27 -04004477returns the same bounds as Font_Metrics { FontMetrics::fXMin,
Cary Clark8032b982017-07-28 11:04:54 -04004478FontMetrics::fTop, FontMetrics::fXMax, FontMetrics::fBottom }.
4479
Cary Clarkce101242017-09-01 15:51:02 -04004480#Return union of bounds of all Glyphs ##
Cary Clark8032b982017-07-28 11:04:54 -04004481
4482#Example
4483 SkPaint paint;
4484 SkPaint::FontMetrics fm;
4485 paint.getFontMetrics(&fm);
4486 SkRect fb = paint.getFontBounds();
4487 SkDebugf("metrics bounds = { %g, %g, %g, %g }\n", fm.fXMin, fm.fTop, fm.fXMax, fm.fBottom );
4488 SkDebugf("font bounds = { %g, %g, %g, %g }\n", fb.fLeft, fb.fTop, fb.fRight, fm.fBottom );
4489
4490 #StdOut
4491 metrics bounds = { -12.2461, -14.7891, 21.5215, 5.55469 }
4492 font bounds = { -12.2461, -14.7891, 21.5215, 5.55469 }
4493 ##
4494##
4495
4496##
4497
4498#Topic ##
4499# ------------------------------------------------------------------------------
4500
4501#Method int textToGlyphs(const void* text, size_t byteLength,
4502 SkGlyphID glyphs[]) const
4503
4504Converts text into glyph indices.
4505Returns the number of glyph indices represented by text.
4506Text_Encoding specifies how text represents characters or glyphs.
4507glyphs may be nullptr, to compute the glyph count.
4508
Cary Clarkbc5697d2017-10-04 14:31:33 -04004509Does not check text for valid character codes or valid glyph indices.
Cary Clark8032b982017-07-28 11:04:54 -04004510
Cary Clark579985c2017-07-31 11:48:27 -04004511If byteLength equals zero, returns zero.
Cary Clark8032b982017-07-28 11:04:54 -04004512If byteLength includes a partial character, the partial character is ignored.
4513
4514If Text_Encoding is kUTF8_TextEncoding and
4515text contains an invalid UTF-8 sequence, zero is returned.
4516
Cary Clarkce101242017-09-01 15:51:02 -04004517#Param text character storage encoded with Text_Encoding ##
Cary Clark8032b982017-07-28 11:04:54 -04004518#Param byteLength length of character storage in bytes ##
4519#Param glyphs storage for glyph indices; may be nullptr ##
4520
4521#Return number of glyphs represented by text of length byteLength ##
4522
4523 #Example
4524 #Height 64
4525 void draw(SkCanvas* canvas) {
4526 SkPaint paint;
4527 const uint8_t utf8[] = { 0x24, 0xC2, 0xA2, 0xE2, 0x82, 0xAC, 0xC2, 0xA5, 0xC2, 0xA3 };
4528 std::vector<SkGlyphID> glyphs;
4529 int count = paint.textToGlyphs(utf8, sizeof(utf8), nullptr);
4530 glyphs.resize(count);
4531 (void) paint.textToGlyphs(utf8, sizeof(utf8), &glyphs.front());
4532 paint.setTextEncoding(SkPaint::kGlyphID_TextEncoding);
4533 paint.setTextSize(32);
4534 canvas->drawText(&glyphs.front(), glyphs.size() * sizeof(SkGlyphID), 10, 40, paint);
4535 }
4536 ##
4537
4538##
4539
4540#Method int countText(const void* text, size_t byteLength) const
4541
Cary Clarkce101242017-09-01 15:51:02 -04004542 Returns the number of Glyphs in text.
4543 Uses Text_Encoding to count the Glyphs.
Cary Clark8032b982017-07-28 11:04:54 -04004544 Returns the same result as textToGlyphs.
4545
Cary Clarkce101242017-09-01 15:51:02 -04004546#Param text character storage encoded with Text_Encoding ##
Cary Clark8032b982017-07-28 11:04:54 -04004547#Param byteLength length of character storage in bytes ##
4548
Cary Clarkce101242017-09-01 15:51:02 -04004549#Return number of Glyphs represented by text of length byteLength ##
Cary Clark8032b982017-07-28 11:04:54 -04004550
4551 #Example
4552 SkPaint paint;
4553 const uint8_t utf8[] = { 0x24, 0xC2, 0xA2, 0xE2, 0x82, 0xAC, 0xC2, 0xA5, 0xC2, 0xA3 };
4554 SkDebugf("count = %d\n", paint.countText(utf8, sizeof(utf8)));
4555
4556 #StdOut
4557 count = 5
4558 ##
4559 ##
4560##
4561
4562# ------------------------------------------------------------------------------
4563
4564#Method bool containsText(const void* text, size_t byteLength) const
4565
4566 Returns true if all text corresponds to a non-zero glyph index.
4567 Returns false if any characters in text are not supported in
4568 Typeface.
4569
Cary Clark579985c2017-07-31 11:48:27 -04004570 If Text_Encoding is kGlyphID_TextEncoding,
4571 returns true if all glyph indices in text are non-zero;
Cary Clark8032b982017-07-28 11:04:54 -04004572 does not check to see if text contains valid glyph indices for Typeface.
4573
Cary Clarkce101242017-09-01 15:51:02 -04004574 Returns true if byteLength is zero.
Cary Clark8032b982017-07-28 11:04:54 -04004575
Cary Clarkce101242017-09-01 15:51:02 -04004576 #Param text array of characters or Glyphs ##
Cary Clark8032b982017-07-28 11:04:54 -04004577 #Param byteLength number of bytes in text array ##
4578
4579 #Return true if all text corresponds to a non-zero glyph index ##
4580
4581 #Example
4582 #Description
4583 containsText succeeds for degree symbol, but cannot find a glyph index
4584 corresponding to the Unicode surrogate code point.
4585 ##
4586 SkPaint paint;
4587 const uint16_t goodChar = 0x00B0; // degree symbol
4588 const uint16_t badChar = 0xD800; // Unicode surrogate
4589 paint.setTextEncoding(SkPaint::kUTF16_TextEncoding);
4590 SkDebugf("0x%04x %c= has char\n", goodChar,
4591 paint.containsText(&goodChar, 2) ? '=' : '!');
4592 SkDebugf("0x%04x %c= has char\n", badChar,
4593 paint.containsText(&badChar, 2) ? '=' : '!');
4594
4595 #StdOut
4596 0x00b0 == has char
4597 0xd800 != has char
4598 ##
4599 ##
4600
4601 #Example
4602 #Description
4603 containsText returns true that glyph index is greater than zero, not
4604 that it corresponds to an entry in Typeface.
4605 ##
4606 SkPaint paint;
4607 const uint16_t goodGlyph = 511;
4608 const uint16_t zeroGlyph = 0;
4609 const uint16_t badGlyph = 65535; // larger than glyph count in font
4610 paint.setTextEncoding(SkPaint::kGlyphID_TextEncoding);
4611 SkDebugf("0x%04x %c= has glyph\n", goodGlyph,
4612 paint.containsText(&goodGlyph, 2) ? '=' : '!');
4613 SkDebugf("0x%04x %c= has glyph\n", zeroGlyph,
4614 paint.containsText(&zeroGlyph, 2) ? '=' : '!');
4615 SkDebugf("0x%04x %c= has glyph\n", badGlyph,
4616 paint.containsText(&badGlyph, 2) ? '=' : '!');
4617
4618 #StdOut
4619 0x01ff == has glyph
4620 0x0000 != has glyph
4621 0xffff == has glyph
4622 ##
4623 ##
4624
4625#SeeAlso setTextEncoding Typeface
4626
4627##
4628
4629# ------------------------------------------------------------------------------
4630
4631#Method void glyphsToUnichars(const SkGlyphID glyphs[],
4632 int count, SkUnichar text[]) const
4633
4634 Converts glyphs into text if possible.
4635 Glyph values without direct Unicode equivalents are mapped to zero.
4636 Uses the Typeface, but is unaffected
4637 by Text_Encoding; the text values returned are equivalent to kUTF32_TextEncoding.
4638
4639 Only supported on platforms that use FreeType as the Font_Engine.
4640
4641 #Param glyphs array of indices into font ##
4642 #Param count length of glyph array ##
4643 #Param text storage for character codes, one per glyph ##
4644
4645 #Example
4646 #Height 64
4647 #Description
4648 Convert UTF-8 text to glyphs; then convert glyphs to Unichar code points.
4649 ##
4650 void draw(SkCanvas* canvas) {
4651 SkPaint paint;
4652 const char hello[] = "Hello!";
4653 const int count = sizeof(hello) - 1;
4654 SkGlyphID glyphs[count];
4655 if (count != paint.textToGlyphs(hello, count, glyphs)) {
4656 return;
4657 }
4658 SkUnichar unichars[count];
4659 paint.glyphsToUnichars(glyphs, count, unichars);
4660 paint.setTextEncoding(SkPaint::kUTF32_TextEncoding);
4661 canvas->drawText(unichars, sizeof(unichars), 10, 30, paint);
4662 }
4663 ##
4664
4665##
4666
4667# ------------------------------------------------------------------------------
4668#Topic Measure_Text
4669
4670#Method SkScalar measureText(const void* text, size_t length, SkRect* bounds) const
4671
4672 Returns the advance width of text if kVerticalText_Flag is clear,
4673 and the height of text if kVerticalText_Flag is set.
4674 The advance is the normal distance to move before drawing additional text.
4675 Uses Text_Encoding to decode text, Typeface to get the font metrics,
4676 and Text_Size, Text_Scale_X, Text_Skew_X, Stroke_Width, and
4677 Path_Effect to scale the metrics and bounds.
4678 Returns the bounding box of text if bounds is not nullptr.
4679 The bounding box is computed as if the text was drawn at the origin.
4680
4681 #Param text character codes or glyph indices to be measured ##
4682 #Param length number of bytes of text to measure ##
4683 #Param bounds returns bounding box relative to (0, 0) if not nullptr ##
4684
4685 #Return advance width or height ##
4686
4687 #Example
4688 #Height 64
4689 void draw(SkCanvas* canvas) {
4690 SkPaint paint;
4691 paint.setAntiAlias(true);
4692 paint.setTextSize(50);
4693 const char str[] = "ay^jZ";
4694 const int count = sizeof(str) - 1;
4695 canvas->drawText(str, count, 25, 50, paint);
4696 SkRect bounds;
4697 paint.measureText(str, count, &bounds);
4698 canvas->translate(25, 50);
4699 paint.setStyle(SkPaint::kStroke_Style);
4700 canvas->drawRect(bounds, paint);
4701 }
4702 ##
4703
4704##
4705
4706#Method SkScalar measureText(const void* text, size_t length) const
4707
4708 Returns the advance width of text if kVerticalText_Flag is clear,
4709 and the height of text if kVerticalText_Flag is set.
4710 The advance is the normal distance to move before drawing additional text.
4711 Uses Text_Encoding to decode text, Typeface to get the font metrics,
4712 and Text_Size to scale the metrics.
4713 Does not scale the advance or bounds by Fake_Bold or Path_Effect.
4714
4715 #Param text character codes or glyph indices to be measured ##
4716 #Param length number of bytes of text to measure ##
4717
4718 #Return advance width or height ##
4719
4720 #Example
4721 SkPaint paint;
4722 SkDebugf("default width = %g\n", paint.measureText("!", 1));
4723 paint.setTextSize(paint.getTextSize() * 2);
4724 SkDebugf("double width = %g\n", paint.measureText("!", 1));
4725
4726 #StdOut
4727 default width = 5
4728 double width = 10
4729 ##
4730 ##
4731
4732##
4733
4734#Method size_t breakText(const void* text, size_t length, SkScalar maxWidth,
Cary Clark73fa9722017-08-29 17:36:51 -04004735 SkScalar* measuredWidth = nullptr) const
Cary Clark8032b982017-07-28 11:04:54 -04004736
4737 Returns the bytes of text that fit within maxWidth.
4738 If kVerticalText_Flag is clear, the text fragment fits if its advance width is less than or
4739 equal to maxWidth.
4740 If kVerticalText_Flag is set, the text fragment fits if its advance height is less than or
4741 equal to maxWidth.
4742 Measures only while the advance is less than or equal to maxWidth.
4743 Returns the advance or the text fragment in measuredWidth if it not nullptr.
4744 Uses Text_Encoding to decode text, Typeface to get the font metrics,
4745 and Text_Size to scale the metrics.
4746 Does not scale the advance or bounds by Fake_Bold or Path_Effect.
4747
4748 #Param text character codes or glyph indices to be measured ##
4749 #Param length number of bytes of text to measure ##
4750 #Param maxWidth advance limit; text is measured while advance is less than maxWidth ##
4751 #Param measuredWidth returns the width of the text less than or equal to maxWidth ##
4752 #Return bytes of text that fit, always less than or equal to length ##
4753
4754 #Example
4755 #Description
4756 Line under "Breakfast" shows desired width, shorter than available characters.
4757 Line under "Bre" shows measured width after breaking text.
4758 ##
4759 #Height 128
4760 #Width 280
4761 void draw(SkCanvas* canvas) {
4762 SkPaint paint;
4763 paint.setAntiAlias(true);
4764 paint.setTextSize(50);
4765 const char str[] = "Breakfast";
4766 const int count = sizeof(str) - 1;
4767 canvas->drawText(str, count, 25, 50, paint);
4768 SkScalar measuredWidth;
4769 int partialBytes = paint.breakText(str, count, 100, &measuredWidth);
4770 canvas->drawText(str, partialBytes, 25, 100, paint);
4771 canvas->drawLine(25, 60, 25 + 100, 60, paint);
4772 canvas->drawLine(25, 110, 25 + measuredWidth, 110, paint);
4773 }
4774 ##
4775
4776##
4777
4778#Method int getTextWidths(const void* text, size_t byteLength, SkScalar widths[],
Cary Clark73fa9722017-08-29 17:36:51 -04004779 SkRect bounds[] = nullptr) const
Cary Clark8032b982017-07-28 11:04:54 -04004780
4781 Retrieves the advance and bounds for each glyph in text, and returns
4782 the glyph count in text.
4783 Both widths and bounds may be nullptr.
4784 If widths is not nullptr, widths must be an array of glyph count entries.
4785 if bounds is not nullptr, bounds must be an array of glyph count entries.
4786 If kVerticalText_Flag is clear, widths returns the horizontal advance.
4787 If kVerticalText_Flag is set, widths returns the vertical advance.
4788 Uses Text_Encoding to decode text, Typeface to get the font metrics,
4789 and Text_Size to scale the widths and bounds.
4790 Does not scale the advance by Fake_Bold or Path_Effect.
4791 Does include Fake_Bold and Path_Effect in the bounds.
4792
4793 #Param text character codes or glyph indices to be measured ##
4794 #Param byteLength number of bytes of text to measure ##
4795 #Param widths returns text advances for each glyph; may be nullptr ##
4796 #Param bounds returns bounds for each glyph relative to (0, 0); may be nullptr ##
4797
4798 #Return glyph count in text ##
4799
4800 #Example
4801 #Height 160
4802 #Description
Cary Clarkce101242017-09-01 15:51:02 -04004803 Bounds of Glyphs increase for stroked text, but text advance remains the same.
Cary Clark8032b982017-07-28 11:04:54 -04004804 The underlines show the text advance, spaced to keep them distinct.
4805 ##
4806 void draw(SkCanvas* canvas) {
4807 SkPaint paint;
4808 paint.setAntiAlias(true);
4809 paint.setTextSize(50);
4810 const char str[] = "abc";
4811 const int bytes = sizeof(str) - 1;
4812 int count = paint.getTextWidths(str, bytes, nullptr);
4813 std::vector<SkScalar> widths;
4814 std::vector<SkRect> bounds;
4815 widths.resize(count);
4816 bounds.resize(count);
4817 for (int loop = 0; loop < 2; ++loop) {
4818 (void) paint.getTextWidths(str, count, &widths.front(), &bounds.front());
4819 SkPoint loc = { 25, 50 };
4820 canvas->drawText(str, bytes, loc.fX, loc.fY, paint);
4821 paint.setStyle(SkPaint::kStroke_Style);
4822 paint.setStrokeWidth(0);
4823 SkScalar advanceY = loc.fY + 10;
4824 for (int index = 0; index < count; ++index) {
4825 bounds[index].offset(loc.fX, loc.fY);
4826 canvas->drawRect(bounds[index], paint);
4827 canvas->drawLine(loc.fX, advanceY, loc.fX + widths[index], advanceY, paint);
4828 loc.fX += widths[index];
4829 advanceY += 5;
4830 }
4831 canvas->translate(0, 80);
4832 paint.setStrokeWidth(3);
4833 }
4834 }
4835 ##
4836
4837##
4838
4839#Topic ##
4840# ------------------------------------------------------------------------------
4841#Topic Text_Path
4842
Cary Clarkce101242017-09-01 15:51:02 -04004843Text_Path describes the geometry of Glyphs used to draw text.
Cary Clark8032b982017-07-28 11:04:54 -04004844
4845#Method void getTextPath(const void* text, size_t length, SkScalar x, SkScalar y,
4846 SkPath* path) const
4847
4848Returns the geometry as Path equivalent to the drawn text.
4849Uses Text_Encoding to decode text, Typeface to get the glyph paths,
4850and Text_Size, Fake_Bold, and Path_Effect to scale and modify the glyph paths.
4851All of the glyph paths are stored in path.
Cary Clark579985c2017-07-31 11:48:27 -04004852Uses x, y, and Text_Align to position path.
Cary Clark8032b982017-07-28 11:04:54 -04004853
4854 #Param text character codes or glyph indices ##
4855 #Param length number of bytes of text ##
4856 #Param x x-coordinate of the origin of the text ##
4857 #Param y y-coordinate of the origin of the text ##
Cary Clarkce101242017-09-01 15:51:02 -04004858 #Param path geometry of the Glyphs ##
Cary Clark8032b982017-07-28 11:04:54 -04004859
4860 #Example
4861 #Description
4862 Text is added to Path, offset, and subtracted from Path, then added at
4863 the offset location. The result is rendered with one draw call.
4864 ##
4865 #Height 128
4866 void draw(SkCanvas* canvas) {
4867 SkPaint paint;
4868 paint.setTextSize(80);
4869 SkPath path, path2;
4870 paint.getTextPath("ABC", 3, 20, 80, &path);
4871 path.offset(20, 20, &path2);
4872 Op(path, path2, SkPathOp::kDifference_SkPathOp, &path);
4873 path.addPath(path2);
4874 paint.setStyle(SkPaint::kStroke_Style);
4875 canvas->drawPath(path, paint);
4876 }
4877 ##
4878
4879##
4880
4881#Method void getPosTextPath(const void* text, size_t length,
4882 const SkPoint pos[], SkPath* path) const
4883
4884Returns the geometry as Path equivalent to the drawn text.
4885Uses Text_Encoding to decode text, Typeface to get the glyph paths,
4886and Text_Size, Fake_Bold, and Path_Effect to scale and modify the glyph paths.
4887All of the glyph paths are stored in path.
4888Uses pos array and Text_Align to position path.
4889pos contains a position for each glyph.
4890
4891 #Param text character codes or glyph indices ##
4892 #Param length number of bytes of text ##
4893 #Param pos positions of each glyph ##
Cary Clarkce101242017-09-01 15:51:02 -04004894 #Param path geometry of the Glyphs ##
Cary Clark8032b982017-07-28 11:04:54 -04004895
4896 #Example
4897 #Height 85
4898 #Description
Cary Clarkce101242017-09-01 15:51:02 -04004899 Simplifies three Glyphs to eliminate overlaps, and strokes the result.
Cary Clark8032b982017-07-28 11:04:54 -04004900 ##
4901 void draw(SkCanvas* canvas) {
4902 SkPaint paint;
4903 paint.setTextSize(80);
4904 SkPath path, path2;
4905 SkPoint pos[] = {{20, 60}, {30, 70}, {40, 80}};
4906 paint.getPosTextPath("ABC", 3, pos, &path);
4907 Simplify(path, &path);
4908 paint.setStyle(SkPaint::kStroke_Style);
4909 canvas->drawPath(path, paint);
4910 }
4911 ##
4912
4913##
4914
4915#Topic ##
4916# ------------------------------------------------------------------------------
4917#Topic Text_Intercepts
4918
Cary Clarkce101242017-09-01 15:51:02 -04004919Text_Intercepts describe the intersection of drawn text Glyphs with a pair
Cary Clark8032b982017-07-28 11:04:54 -04004920of lines parallel to the text advance. Text_Intercepts permits creating a
Cary Clarkce101242017-09-01 15:51:02 -04004921underline that skips Descenders.
Cary Clark8032b982017-07-28 11:04:54 -04004922
4923#Method int getTextIntercepts(const void* text, size_t length, SkScalar x, SkScalar y,
4924 const SkScalar bounds[2], SkScalar* intervals) const
4925
4926 Returns the number of intervals that intersect bounds.
4927 bounds describes a pair of lines parallel to the text advance.
Cary Clarkce101242017-09-01 15:51:02 -04004928 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 -04004929 the string.
4930 Uses Text_Encoding to decode text, Typeface to get the glyph paths,
4931 and Text_Size, Fake_Bold, and Path_Effect to scale and modify the glyph paths.
4932 Uses x, y, and Text_Align to position intervals.
4933
4934 Pass nullptr for intervals to determine the size of the interval array.
4935
4936 intervals are cached to improve performance for multiple calls.
4937
4938 #Param text character codes or glyph indices ##
4939 #Param length number of bytes of text ##
4940 #Param x x-coordinate of the origin of the text ##
4941 #Param y y-coordinate of the origin of the text ##
4942 #Param bounds lower and upper line parallel to the advance ##
4943 #Param intervals returned intersections; may be nullptr ##
4944
4945 #Return number of intersections; may be zero ##
4946
4947#Example
4948#Height 128
4949#Description
Cary Clarkce101242017-09-01 15:51:02 -04004950Underline uses intercepts to draw on either side of the glyph Descender.
Cary Clark8032b982017-07-28 11:04:54 -04004951##
4952void draw(SkCanvas* canvas) {
4953 SkPaint paint;
4954 paint.setTextSize(120);
4955 SkPoint textOrigin = { 20, 100 };
4956 SkScalar bounds[] = { 100, 108 };
4957 int count = paint.getTextIntercepts("y", 1, textOrigin.fX, textOrigin.fY, bounds, nullptr);
4958 std::vector<SkScalar> intervals;
4959 intervals.resize(count);
4960 (void) paint.getTextIntercepts("y", 1, textOrigin.fX, textOrigin.fY, bounds,
4961 &intervals.front());
4962 canvas->drawString("y", textOrigin.fX, textOrigin.fY, paint);
4963 paint.setColor(SK_ColorRED);
4964 SkScalar x = textOrigin.fX;
4965 for (int i = 0; i < count; i += 2) {
4966 canvas->drawRect({x, bounds[0], intervals[i], bounds[1]}, paint);
4967 x = intervals[i + 1];
4968 }
4969 canvas->drawRect({intervals[count - 1], bounds[0],
4970 textOrigin.fX + paint.measureText("y", 1), bounds[1]}, paint);
4971}
4972##
4973
4974##
4975
4976#Method int getPosTextIntercepts(const void* text, size_t length, const SkPoint pos[],
4977 const SkScalar bounds[2], SkScalar* intervals) const
4978
4979 Returns the number of intervals that intersect bounds.
4980 bounds describes a pair of lines parallel to the text advance.
Cary Clarkce101242017-09-01 15:51:02 -04004981 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 -04004982 the string.
4983 Uses Text_Encoding to decode text, Typeface to get the glyph paths,
4984 and Text_Size, Fake_Bold, and Path_Effect to scale and modify the glyph paths.
4985 Uses pos array and Text_Align to position intervals.
4986
4987 Pass nullptr for intervals to determine the size of the interval array.
4988
4989 intervals are cached to improve performance for multiple calls.
4990
4991 #Param text character codes or glyph indices ##
4992 #Param length number of bytes of text ##
4993 #Param pos positions of each glyph ##
4994 #Param bounds lower and upper line parallel to the advance ##
4995 #Param intervals returned intersections; may be nullptr ##
4996
Cary Clarka523d2d2017-08-30 08:58:10 -04004997 #Return number of intersections; may be zero ##
Cary Clark8032b982017-07-28 11:04:54 -04004998
4999 #Example
5000 #Description
Cary Clarkce101242017-09-01 15:51:02 -04005001 Text intercepts draw on either side of, but not inside, Glyphs in a run.
Cary Clark8032b982017-07-28 11:04:54 -04005002 ##
5003 void draw(SkCanvas* canvas) {
5004 SkPaint paint;
5005 paint.setTextSize(120);
5006 paint.setVerticalText(true);
5007 SkPoint textPos[] = {{ 60, 40 }, { 60, 140 }};
5008 SkScalar bounds[] = { 56, 64 };
5009 const char str[] = "A-";
5010 int len = sizeof(str) - 1;
5011 int count = paint.getPosTextIntercepts(str, len, textPos, bounds, nullptr);
5012 std::vector<SkScalar> intervals;
5013 intervals.resize(count);
5014 (void) paint.getPosTextIntercepts(str, len, textPos, bounds, &intervals.front());
5015 canvas->drawPosText(str, len, textPos, paint);
5016 paint.setColor(SK_ColorRED);
5017 SkScalar y = textPos[0].fY;
5018 for (int i = 0; i < count; i+= 2) {
5019 canvas->drawRect({bounds[0], y, bounds[1], intervals[i]}, paint);
5020 y = intervals[i + 1];
5021 }
5022 canvas->drawRect({bounds[0], intervals[count - 1], bounds[1], 240}, paint);
5023 }
5024 ##
5025
5026##
5027
5028#Method int getPosTextHIntercepts(const void* text, size_t length, const SkScalar xpos[],
5029 SkScalar constY, const SkScalar bounds[2],
5030 SkScalar* intervals) const
5031
5032 Returns the number of intervals that intersect bounds.
5033 bounds describes a pair of lines parallel to the text advance.
Cary Clarkce101242017-09-01 15:51:02 -04005034 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 -04005035 the string.
5036 Uses Text_Encoding to decode text, Typeface to get the glyph paths,
5037 and Text_Size, Fake_Bold, and Path_Effect to scale and modify the glyph paths.
5038 Uses xpos array, constY, and Text_Align to position intervals.
5039
5040 Pass nullptr for intervals to determine the size of the interval array.
5041
5042 intervals are cached to improve performance for multiple calls.
5043
5044 #Param text character codes or glyph indices ##
5045 #Param length number of bytes of text ##
5046 #Param xpos positions of each glyph in x ##
5047 #Param constY position of each glyph in y ##
5048 #Param bounds lower and upper line parallel to the advance ##
5049 #Param intervals returned intersections; may be nullptr ##
5050
5051 #Return number of intersections; may be zero ##
5052
5053 #Example
5054 #Height 128
5055 #Description
5056 Text intercepts do not take stroke thickness into consideration.
5057 ##
5058 void draw(SkCanvas* canvas) {
5059 SkPaint paint;
5060 paint.setTextSize(120);
5061 paint.setStyle(SkPaint::kStroke_Style);
5062 paint.setStrokeWidth(4);
5063 SkScalar textPosH[] = { 20, 80, 140 };
5064 SkScalar y = 100;
5065 SkScalar bounds[] = { 56, 78 };
5066 const char str[] = "\\-/";
5067 int len = sizeof(str) - 1;
5068 int count = paint.getPosTextHIntercepts(str, len, textPosH, y, bounds, nullptr);
5069 std::vector<SkScalar> intervals;
5070 intervals.resize(count);
5071 (void) paint.getPosTextHIntercepts(str, len, textPosH, y, bounds, &intervals.front());
5072 canvas->drawPosTextH(str, len, textPosH, y, paint);
5073 paint.setColor(0xFFFF7777);
5074 paint.setStyle(SkPaint::kFill_Style);
5075 SkScalar x = textPosH[0];
5076 for (int i = 0; i < count; i+= 2) {
5077 canvas->drawRect({x, bounds[0], intervals[i], bounds[1]}, paint);
5078 x = intervals[i + 1];
5079 }
5080 canvas->drawRect({intervals[count - 1], bounds[0], 180, bounds[1]}, paint);
5081 }
5082 ##
5083
5084##
5085
5086
5087#Method int getTextBlobIntercepts(const SkTextBlob* blob, const SkScalar bounds[2],
5088 SkScalar* intervals) const
5089
5090 Returns the number of intervals that intersect bounds.
5091 bounds describes a pair of lines parallel to the text advance.
Cary Clarkce101242017-09-01 15:51:02 -04005092 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 -04005093 the string.
5094 Uses Text_Encoding to decode text, Typeface to get the glyph paths,
5095 and Text_Size, Fake_Bold, and Path_Effect to scale and modify the glyph paths.
Cary Clarkce101242017-09-01 15:51:02 -04005096 Uses run array and Text_Align to position intervals.
Cary Clark8032b982017-07-28 11:04:54 -04005097
5098 Pass nullptr for intervals to determine the size of the interval array.
5099
5100 intervals are cached to improve performance for multiple calls.
5101
Cary Clarkce101242017-09-01 15:51:02 -04005102 #Param blob Glyphs, positions, and text paint attributes ##
Cary Clark8032b982017-07-28 11:04:54 -04005103 #Param bounds lower and upper line parallel to the advance ##
5104 #Param intervals returned intersections; may be nullptr ##
5105
5106 #Return number of intersections; may be zero ##
5107
5108 #Example
5109 #Height 143
5110 void draw(SkCanvas* canvas) {
5111 SkPaint paint;
5112 paint.setTextSize(120);
5113 SkPoint textPos = { 20, 110 };
5114 int len = 3;
5115 SkTextBlobBuilder textBlobBuilder;
5116 const SkTextBlobBuilder::RunBuffer& run =
5117 textBlobBuilder.allocRun(paint, len, textPos.fX, textPos.fY);
5118 run.glyphs[0] = 10;
5119 run.glyphs[1] = 20;
5120 run.glyphs[2] = 30;
5121 sk_sp<const SkTextBlob> blob = textBlobBuilder.make();
5122 canvas->drawTextBlob(blob.get(), textPos.fX, textPos.fY, paint);
5123 SkScalar bounds[] = { 116, 134 };
5124 int count = paint.getTextBlobIntercepts(blob.get(), bounds, nullptr);
5125 std::vector<SkScalar> intervals;
5126 intervals.resize(count);
5127 (void) paint.getTextBlobIntercepts(blob.get(), bounds, &intervals.front());
5128 canvas->drawTextBlob(blob.get(), 0, 0, paint);
5129 paint.setColor(0xFFFF7777);
5130 SkScalar x = textPos.fX;
5131 for (int i = 0; i < count; i+= 2) {
5132 canvas->drawRect({x, bounds[0], intervals[i], bounds[1]}, paint);
5133 x = intervals[i + 1];
5134 }
5135 canvas->drawRect({intervals[count - 1], bounds[0], 180, bounds[1]}, paint);
5136 }
5137 ##
5138
5139##
5140
5141#Topic ##
5142# ------------------------------------------------------------------------------
5143
5144#Method bool nothingToDraw() const
5145
Cary Clark579985c2017-07-31 11:48:27 -04005146 Returns true if Paint prevents all drawing;
5147 otherwise, the Paint may or may not allow drawing.
Cary Clark8032b982017-07-28 11:04:54 -04005148
Cary Clarkce101242017-09-01 15:51:02 -04005149 Returns true if, for example, Blend_Mode combined with Color_Alpha computes a
5150 new Alpha of zero.
Cary Clark8032b982017-07-28 11:04:54 -04005151
5152 #Return true if Paint prevents all drawing ##
5153
5154 #Example
5155 void draw(SkCanvas* canvas) {
5156 auto debugster = [](const char* prefix, const SkPaint& p) -> void {
5157 SkDebugf("%s nothing to draw: %s\n", prefix,
5158 p.nothingToDraw() ? "true" : "false");
5159 };
5160 SkPaint paint;
5161 debugster("initial", paint);
5162 paint.setBlendMode(SkBlendMode::kDst);
5163 debugster("blend dst", paint);
5164 paint.setBlendMode(SkBlendMode::kSrcOver);
5165 debugster("blend src over", paint);
5166 paint.setAlpha(0);
5167 debugster("alpha 0", paint);
5168 }
5169
5170 #StdOut
5171 initial nothing to draw: false
5172 blend dst nothing to draw: true
5173 blend src over nothing to draw: false
5174 alpha 0 nothing to draw: true
5175 #StdOut ##
5176 ##
5177
5178##
5179
5180# ------------------------------------------------------------------------------
5181#Topic Fast_Bounds
5182 #Private
5183 To be made private.
5184 ##
5185
5186Fast_Bounds methods conservatively outset a drawing bounds by additional area
5187Paint may draw to.
5188
5189#Method bool canComputeFastBounds() const
5190 #Private
5191 (to be made private)
5192 ##
5193
5194 Returns true if Paint does not include elements requiring extensive computation
5195 to compute Device bounds of drawn geometry. For instance, Paint with Path_Effect
5196 always returns false.
5197
5198 #Return true if Paint allows for fast computation of bounds ##
5199##
5200
5201#Method const SkRect& computeFastBounds(const SkRect& orig, SkRect* storage) const
5202 #Private
5203 (to be made private)
5204 ##
5205
5206 Only call this if canComputeFastBounds returned true. This takes a
5207 raw rectangle (the raw bounds of a shape), and adjusts it for stylistic
5208 effects in the paint (e.g. stroking). If needed, it uses the storage
Cary Clarkce101242017-09-01 15:51:02 -04005209 parameter. It returns the adjusted bounds that can then be used
Cary Clark8032b982017-07-28 11:04:54 -04005210 for SkCanvas::quickReject tests.
5211
Cary Clarkce101242017-09-01 15:51:02 -04005212 The returned Rect will either be orig or storage, thus the caller
Cary Clark8032b982017-07-28 11:04:54 -04005213 should not rely on storage being set to the result, but should always
Cary Clarkce101242017-09-01 15:51:02 -04005214 use the returned value. It is legal for orig and storage to be the same
5215 Rect.
Cary Clark8032b982017-07-28 11:04:54 -04005216
5217 #Private
5218 e.g.
5219 if (paint.canComputeFastBounds()) {
5220 SkRect r, storage;
5221 path.computeBounds(&r, SkPath::kFast_BoundsType);
5222 const SkRect& fastR = paint.computeFastBounds(r, &storage);
5223 if (canvas->quickReject(fastR, ...)) {
5224 // don't draw the path
5225 }
5226 }
5227 ##
5228
5229 #Param orig geometry modified by Paint when drawn ##
5230 #Param storage computed bounds of geometry; may not be nullptr ##
5231
5232 #Return fast computed bounds ##
5233##
5234
5235#Method const SkRect& computeFastStrokeBounds(const SkRect& orig,
5236 SkRect* storage) const
5237 #Private
5238 (to be made private)
5239 ##
5240
5241 #Param orig geometry modified by Paint when drawn ##
5242 #Param storage computed bounds of geometry ##
5243
5244 #Return fast computed bounds ##
5245##
5246
5247#Method const SkRect& doComputeFastBounds(const SkRect& orig, SkRect* storage,
5248 Style style) const
5249 #Private
5250 (to be made private)
5251 ##
5252
Cary Clarkce101242017-09-01 15:51:02 -04005253 Computes the bounds, overriding the Paint Style. This can be used to
5254 account for additional width required by stroking orig, without
5255 altering Style set to fill.
Cary Clark8032b982017-07-28 11:04:54 -04005256
5257 #Param orig geometry modified by Paint when drawn ##
5258 #Param storage computed bounds of geometry ##
5259 #Param style overrides Style ##
5260
5261 #Return fast computed bounds ##
5262##
5263
5264#Topic Fast_Bounds ##
5265
5266# ------------------------------------------------------------------------------
5267#Method void toString(SkString* str) const;
5268
5269#DefinedBy SK_TO_STRING_NONVIRT() ##
5270
5271#Private
5272macro expands to: void toString(SkString* str) const;
5273##
5274
Cary Clarkce101242017-09-01 15:51:02 -04005275Creates string representation of Paint. The representation is read by
5276internal debugging tools. The interface and implementation may be
5277suppressed by defining SK_IGNORE_TO_STRING.
Cary Clark8032b982017-07-28 11:04:54 -04005278
Cary Clarkce101242017-09-01 15:51:02 -04005279#Param str storage for string representation of Paint ##
Cary Clark8032b982017-07-28 11:04:54 -04005280
5281#Example
5282 SkPaint paint;
5283 SkString str;
5284 paint.toString(&str);
5285 const char textSize[] = "TextSize:";
5286 const int trailerSize = strlen("</dd><dt>");
5287 int textSizeLoc = str.find(textSize) + strlen(textSize) + trailerSize;
5288 const char* sizeStart = &str.c_str()[textSizeLoc];
5289 int textSizeEnd = SkStrFind(sizeStart, "</dd>");
5290 SkDebugf("text size = %.*s\n", textSizeEnd, sizeStart);
5291
5292 #StdOut
5293 text size = 12
5294 ##
5295
5296##
5297
Cary Clark2ade9972017-11-02 17:49:34 -04005298#SeeAlso SkPathEffect::toString SkMaskFilter::toString SkColorFilter::toString SkImageFilter::toString
Cary Clark8032b982017-07-28 11:04:54 -04005299
5300##
5301
5302# ------------------------------------------------------------------------------
5303
5304#Class SkPaint ##
5305
5306#Topic Paint ##