blob: b19feb29ed8cad9a50d136c7c652a0a3bc852ecc [file] [log] [blame]
Cary Clark0c5f5462017-12-15 11:21:51 -05001#Topic Paint
Cary Clark12799e12017-07-28 15:18:29 -04002#Alias Paint_Reference
Cary Clark8032b982017-07-28 11:04:54 -04003
Cary Clarke4aa3712017-09-15 02:56:12 -04004#Class SkPaint
5
Cary Clark8032b982017-07-28 11:04:54 -04006Paint controls options applied when drawing and measuring. Paint collects all
7options outside of the Canvas_Clip and Canvas_Matrix.
8
9Various options apply to text, strokes and fills, and images.
10
11Some options may not be implemented on all platforms; in these cases, setting
12the option has no effect. Some options are conveniences that duplicate Canvas
13functionality; for instance, text size is identical to matrix scale.
14
15Paint options are rarely exclusive; each option modifies a stage of the drawing
16pipeline and multiple pipeline stages may be affected by a single Paint.
17
18Paint collects effects and filters that describe single-pass and multiple-pass
19algorithms that alter the drawing geometry, color, and transparency. For instance,
20Paint does not directly implement dashing or blur, but contains the objects that do so.
21
22The objects contained by Paint are opaque, and cannot be edited outside of the Paint
23to affect it. The implementation is free to defer computations associated with the
24Paint, or ignore them altogether. For instance, some GPU implementations draw all
Cary Clarkce101242017-09-01 15:51:02 -040025Path geometries with Anti-aliasing, regardless of how SkPaint::kAntiAlias_Flag
Cary Clarkbad5ad72017-08-03 17:14:08 -040026is set in Paint.
Cary Clark8032b982017-07-28 11:04:54 -040027
28Paint describes a single color, a single font, a single image quality, and so on.
29Multiple colors are drawn either by using multiple paints or with objects like
30Shader attached to Paint.
31
Cary Clark8032b982017-07-28 11:04:54 -040032#Topic Overview
33
34#Subtopic Subtopics
35#ToDo not all methods are in topics ##
36#ToDo subtopics are not in topics ##
37#Table
38#Legend
39# topics # description ##
40#Legend ##
41# Initializers # Constructors and initialization. ##
42# Destructor # Paint termination. ##
43# Management # Paint copying, moving, comparing. ##
44# Hinting # Glyph outline adjustment. ##
45# Flags # Attributes represented by single bits. ##
46# Anti-alias # Approximating coverage with transparency. ##
47# Dither # Distributing color error. ##
48# Device_Text # Increase precision of glyph position. ##
Cary Clarkce101242017-09-01 15:51:02 -040049# Font_Embedded_Bitmaps # Custom sized bitmap Glyphs. ##
Cary Clark8032b982017-07-28 11:04:54 -040050# Automatic_Hinting # Always adjust glyph paths. ##
51# Vertical_Text # Orient text from top to bottom. ##
52# Fake_Bold # Approximate font styles. ##
53# Full_Hinting_Spacing # Glyph spacing affected by hinting. ##
54# Filter_Quality_Methods # Get and set Filter_Quality. ##
55# Color_Methods # Get and set Color. ##
56# Style # Geometry filling, stroking. ##
57# Stroke_Width # Thickness perpendicular to geometry. ##
58# Miter_Limit # Maximum length of stroked corners. ##
59# Stroke_Cap # Decorations at ends of open strokes. ##
60# Stroke_Join # Decoration at corners of strokes. ##
61# Fill_Path # Make Path from Path_Effect, stroking. ##
62# Shader_Methods # Get and set Shader. ##
63# Color_Filter_Methods # Get and set Color_Filter. ##
64# Blend_Mode_Methods # Get and set Blend_Mode. ##
65# Path_Effect_Methods # Get and set Path_Effect. ##
66# Mask_Filter_Methods # Get and set Mask_Filter. ##
67# Typeface_Methods # Get and set Typeface. ##
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
Cary Clark61ca7c52018-01-02 11:34:14 -0500570# why is flatten() public?
571#Bug 6172 ##
Cary Clark8032b982017-07-28 11:04:54 -0400572
Cary Clark61ca7c52018-01-02 11:34:14 -0500573#NoExample
Cary Clark8032b982017-07-28 11:04:54 -0400574##
575
576##
577
578# ------------------------------------------------------------------------------
579
580#Method void unflatten(SkReadBuffer& buffer)
581
582Populates Paint, typically from a serialized stream, created by calling
583flatten() at an earlier time.
584
585SkReadBuffer class is not public, so unflatten() cannot be meaningfully called
586by the client.
587
Cary Clarkce101242017-09-01 15:51:02 -0400588#Param buffer serialized data describing Paint content ##
Cary Clark8032b982017-07-28 11:04:54 -0400589
590# why is unflatten() public?
591#Bug 6172 ##
592
593#NoExample
594##
595
Cary Clark2ade9972017-11-02 17:49:34 -0400596#SeeAlso SkReadBuffer
Cary Clark8032b982017-07-28 11:04:54 -0400597
598##
599
600#Topic Management ##
601
602# ------------------------------------------------------------------------------
603#Topic Hinting
604
605#Enum Hinting
606
607#Code
608 enum Hinting {
609 kNo_Hinting = 0,
610 kSlight_Hinting = 1,
611 kNormal_Hinting = 2,
Cary Clarkbad5ad72017-08-03 17:14:08 -0400612 kFull_Hinting = 3,
Cary Clark8032b982017-07-28 11:04:54 -0400613 };
614##
615
616Hinting adjusts the glyph outlines so that the shape provides a uniform
617look at a given point size on font engines that support it. Hinting may have a
618muted effect or no effect at all depending on the platform.
619
620The four levels roughly control corresponding features on platforms that use FreeType
621as the Font_Engine.
622
623#Const kNo_Hinting 0
624 Leaves glyph outlines unchanged from their native representation.
625 With FreeType, this is equivalent to the FT_LOAD_NO_HINTING
626 bit-field constant supplied to FT_Load_Glyph, which indicates that the vector
627 outline being loaded should not be fitted to the pixel grid but simply scaled
628 to 26.6 fractional pixels.
629##
630#Const kSlight_Hinting 1
631 Modifies glyph outlines minimally to improve constrast.
632 With FreeType, this is equivalent in spirit to the
633 FT_LOAD_TARGET_LIGHT value supplied to FT_Load_Glyph. It chooses a
634 lighter hinting algorithm for non-monochrome modes.
Cary Clarkce101242017-09-01 15:51:02 -0400635 Generated Glyphs may be fuzzy but better resemble their original shape.
Cary Clark8032b982017-07-28 11:04:54 -0400636##
637#Const kNormal_Hinting 2
638 Modifies glyph outlines to improve constrast. This is the default.
Cary Clark6fc50412017-09-21 12:31:06 -0400639 With FreeType, this supplies FT_LOAD_TARGET_NORMAL to FT_Load_Glyph,
Cary Clark8032b982017-07-28 11:04:54 -0400640 choosing the default hinting algorithm, which is optimized for standard
641 gray-level rendering.
642##
643#Const kFull_Hinting 3
Cary Clark6fc50412017-09-21 12:31:06 -0400644 Modifies glyph outlines for maxiumum constrast. With FreeType, this selects
645 FT_LOAD_TARGET_LCD or FT_LOAD_TARGET_LCD_V if kLCDRenderText_Flag is set.
646 FT_LOAD_TARGET_LCD is a variant of FT_LOAD_TARGET_NORMAL optimized for
647 horizontally decimated LCD displays; FT_LOAD_TARGET_LCD_V is a
Cary Clark8032b982017-07-28 11:04:54 -0400648 variant of FT_LOAD_TARGET_NORMAL optimized for vertically decimated LCD displays.
649##
650
651#Track
652#File SkFontHost_mac.cpp:1777,1806
653#Time 2013-03-03 07:16:29 +0000
654#Bug 915 ##
655On OS_X and iOS, hinting controls whether Core_Graphics dilates the font outlines
656to account for LCD text. No hinting uses Core_Text gray scale output.
657Normal hinting uses Core_Text LCD output. If kLCDRenderText_Flag is clear,
658the LCD output is reduced to a single grayscale channel.
659#Track ##
660
661On Windows with DirectWrite, Hinting has no effect.
662
663Hinting defaults to kNormal_Hinting.
664Set SkPaintDefaults_Hinting at compile time to change the default setting.
665
666#ToDo add an illustration? linux running GM:typefacerendering is best for this
667 the hinting variations are every other character horizontally
668#ToDo ##
669
670#Enum ##
671
672#Method Hinting getHinting() const
673
674 Returns level of glyph outline adjustment.
675
676 #Return one of: kNo_Hinting, kSlight_Hinting, kNormal_Hinting, kFull_Hinting ##
677
678 #Example
679 SkPaint paint;
680 SkDebugf("SkPaint::kNormal_Hinting %c= paint.getHinting()\n",
681 SkPaint::kNormal_Hinting == paint.getHinting() ? '=' : ':');
682
683 #StdOut
684 SkPaint::kNormal_Hinting == paint.getHinting()
685 ##
686 ##
687##
688
689#Method void setHinting(Hinting hintingLevel)
690
691 Sets level of glyph outline adjustment.
692 Does not check for valid values of hintingLevel.
693
694 #Table
695 #Legend
696 # Hinting # value # effect on generated glyph outlines ##
697 ##
698 # kNo_Hinting # 0 # leaves glyph outlines unchanged from their native representation ##
Cary Clarkce101242017-09-01 15:51:02 -0400699 # kSlight_Hinting # 1 # modifies glyph outlines minimally to improve contrast ##
700 # kNormal_Hinting # 2 # modifies glyph outlines to improve contrast ##
701 # kFull_Hinting # 3 # modifies glyph outlines for maximum contrast ##
Cary Clark8032b982017-07-28 11:04:54 -0400702 ##
703
704 #Param hintingLevel one of: kNo_Hinting, kSlight_Hinting, kNormal_Hinting, kFull_Hinting ##
705
706 #Example
707 SkPaint paint1, paint2;
708 paint2.setHinting(SkPaint::kNormal_Hinting);
709 SkDebugf("paint1 %c= paint2\n", paint1 == paint2 ? '=' : ':');
710
711 #StdOut
712 paint1 == paint2
713 ##
714 ##
715##
716
717#Topic ##
718# ------------------------------------------------------------------------------
719#Topic Flags
720
721#Enum Flags
722
723#Code
724 enum Flags {
725 kAntiAlias_Flag = 0x01,
726 kDither_Flag = 0x04,
727 kFakeBoldText_Flag = 0x20,
728 kLinearText_Flag = 0x40,
729 kSubpixelText_Flag = 0x80,
730 kDevKernText_Flag = 0x100,
731 kLCDRenderText_Flag = 0x200,
732 kEmbeddedBitmapText_Flag = 0x400,
733 kAutoHinting_Flag = 0x800,
734 kVerticalText_Flag = 0x1000,
735 kGenA8FromLCD_Flag = 0x2000,
736
737 kAllFlags = 0xFFFF,
738 };
739
740##
741
742The bit values stored in Flags.
743The default value for Flags, normally zero, can be changed at compile time
744with a custom definition of SkPaintDefaults_Flags.
745All flags can be read and written explicitly; Flags allows manipulating
746multiple settings at once.
747
748 #Const kAntiAlias_Flag 0x0001
749 mask for setting Anti-alias
750 ##
751 #Const kDither_Flag 0x0004
752 mask for setting Dither
753 ##
754
755 #Const kFakeBoldText_Flag 0x0020
756 mask for setting Fake_Bold
757 ##
758 #Const kLinearText_Flag 0x0040
759 mask for setting Linear_Text
760 ##
761 #Const kSubpixelText_Flag 0x0080
762 mask for setting Subpixel_Text
763 ##
764 #Const kDevKernText_Flag 0x0100
765 mask for setting Full_Hinting_Spacing
766 ##
767 #Const kLCDRenderText_Flag 0x0200
768 mask for setting LCD_Text
769 ##
770 #Const kEmbeddedBitmapText_Flag 0x0400
771 mask for setting Font_Embedded_Bitmaps
772 ##
773 #Const kAutoHinting_Flag 0x0800
774 mask for setting Automatic_Hinting
775 ##
776 #Const kVerticalText_Flag 0x1000
777 mask for setting Vertical_Text
778 ##
779 #Const kGenA8FromLCD_Flag 0x2000
780 #Private
781 Hack for GDI -- do not use if you can help it
782 ##
783 not intended for public use
784 ##
785 #Const kAllFlags 0xFFFF
786 mask of all Flags, including private flags and flags reserved for future use
787 ##
788
789Flags default to all flags clear, disabling the associated feature.
790
791#Enum ##
792
793#Enum ReserveFlags
794
795#Private
796To be deprecated; only valid for Android framework.
797##
798
799#Code
800 enum ReserveFlags {
801 kUnderlineText_ReserveFlag = 0x08,
802 kStrikeThruText_ReserveFlag = 0x10,
803 };
804##
805
806 #Const kUnderlineText_ReserveFlag 0x0008
807 mask for underline text
808 ##
809 #Const kStrikeThruText_ReserveFlag 0x0010
810 mask for strike-thru text
811 ##
812
Cary Clark2ade9972017-11-02 17:49:34 -0400813#SeeAlso Flags getFlags
Cary Clark8032b982017-07-28 11:04:54 -0400814
815#Enum ##
816
817#Method uint32_t getFlags() const
818
819Returns paint settings described by Flags. Each setting uses one
820bit, and can be tested with Flags members.
821
822#Return zero, one, or more bits described by Flags ##
823
824#Example
825 SkPaint paint;
826 paint.setAntiAlias(true);
827 SkDebugf("(SkPaint::kAntiAlias_Flag & paint.getFlags()) %c= 0\n",
828 SkPaint::kAntiAlias_Flag & paint.getFlags() ? '!' : '=');
829
830 #StdOut
831 (SkPaint::kAntiAlias_Flag & paint.getFlags()) != 0
832 ##
833##
834
835##
836
837#Method void setFlags(uint32_t flags)
838
839Replaces Flags with flags, the union of the Flags members.
840All Flags members may be cleared, or one or more may be set.
841
842#Param flags union of Flags for Paint ##
843
844#Example
845 SkPaint paint;
846 paint.setFlags((uint32_t) (SkPaint::kAntiAlias_Flag | SkPaint::kDither_Flag));
847 SkDebugf("paint.isAntiAlias()\n", paint.isAntiAlias() ? '!' : '=');
848 SkDebugf("paint.isDither()\n", paint.isDither() ? '!' : '=');
849
850 #StdOut
851 paint.isAntiAlias()
852 paint.isDither()
853 ##
854##
855
856##
857
858#Topic ##
859# ------------------------------------------------------------------------------
860#Topic Anti-alias
861#Alias Anti-alias # permit hyphen in topic name, should probably not substitute hyphen with _
862
863Anti-alias drawing approximates partial pixel coverage with transparency.
864If kAntiAlias_Flag is clear, pixel centers contained by the shape edge are drawn opaque.
865If kAntiAlias_Flag is set, pixels are drawn with Color_Alpha equal to their coverage.
866
Cary Clarkce101242017-09-01 15:51:02 -0400867The rule for Aliased pixels is inconsistent across platforms. A shape edge
Cary Clark8032b982017-07-28 11:04:54 -0400868passing through the pixel center may, but is not required to, draw the pixel.
869
Cary Clarkce101242017-09-01 15:51:02 -0400870Raster_Engine draws Aliased pixels whose centers are on or to the right of the start of an
Cary Clark8032b982017-07-28 11:04:54 -0400871active Path edge, and whose center is to the left of the end of the active Path edge.
872
873#ToDo add illustration of raster pixels ##
874
Cary Clarkce101242017-09-01 15:51:02 -0400875A platform may only support Anti-aliased drawing. Some GPU-backed platforms use
876Supersampling to Anti-alias all drawing, and have no mechanism to selectively
877Alias.
Cary Clark8032b982017-07-28 11:04:54 -0400878
Cary Clarkce101242017-09-01 15:51:02 -0400879The amount of coverage computed for Anti-aliased pixels also varies across platforms.
Cary Clark8032b982017-07-28 11:04:54 -0400880
881Anti-alias is disabled by default.
882Anti-alias can be enabled by default by setting SkPaintDefaults_Flags to kAntiAlias_Flag
883at compile time.
884
885 #Example
886 #Width 512
887 #Description
888 A red line is drawn with transparency on the edges to make it look smoother.
889 A blue line draws only where the pixel centers are contained.
Cary Clarkce101242017-09-01 15:51:02 -0400890 The lines are drawn into Bitmap, then drawn magnified to make the
891 Aliasing easier to see.
Cary Clark8032b982017-07-28 11:04:54 -0400892 ##
893
894 void draw(SkCanvas* canvas) {
895 SkBitmap bitmap;
896 bitmap.allocN32Pixels(50, 50);
897 SkCanvas offscreen(bitmap);
898 SkPaint paint;
899 paint.setStyle(SkPaint::kStroke_Style);
900 paint.setStrokeWidth(10);
901 for (bool antialias : { false, true }) {
902 paint.setColor(antialias ? SK_ColorRED : SK_ColorBLUE);
903 paint.setAntiAlias(antialias);
904 bitmap.eraseColor(0);
905 offscreen.drawLine(5, 5, 15, 30, paint);
906 canvas->drawLine(5, 5, 15, 30, paint);
907 canvas->save();
908 canvas->scale(10, 10);
909 canvas->drawBitmap(bitmap, antialias ? 12 : 0, 0);
910 canvas->restore();
911 canvas->translate(15, 0);
912 }
913 }
914 ##
915
916#Method bool isAntiAlias() const
917
918 If true, pixels on the active edges of Path may be drawn with partial transparency.
919
920 Equivalent to getFlags masked with kAntiAlias_Flag.
921
922 #Return kAntiAlias_Flag state ##
923
924 #Example
925 SkPaint paint;
926 SkDebugf("paint.isAntiAlias() %c= !!(paint.getFlags() & SkPaint::kAntiAlias_Flag)\n",
927 paint.isAntiAlias() == !!(paint.getFlags() & SkPaint::kAntiAlias_Flag) ? '=' : '!');
928 paint.setAntiAlias(true);
929 SkDebugf("paint.isAntiAlias() %c= !!(paint.getFlags() & SkPaint::kAntiAlias_Flag)\n",
930 paint.isAntiAlias() == !!(paint.getFlags() & SkPaint::kAntiAlias_Flag) ? '=' : '!');
931
932 #StdOut
933 paint.isAntiAlias() == !!(paint.getFlags() & SkPaint::kAntiAlias_Flag)
934 paint.isAntiAlias() == !!(paint.getFlags() & SkPaint::kAntiAlias_Flag)
935 ##
936 ##
937##
938
939#Method void setAntiAlias(bool aa)
940
941 Requests, but does not require, that Path edge pixels draw opaque or with
942 partial transparency.
943
944 Sets kAntiAlias_Flag if aa is true.
945 Clears kAntiAlias_Flag if aa is false.
946
947 #Param aa setting for kAntiAlias_Flag ##
948
949 #Example
950 SkPaint paint1, paint2;
951 paint1.setAntiAlias(true);
952 paint2.setFlags(paint2.getFlags() | SkPaint::kAntiAlias_Flag);
953 SkDebugf("paint1 %c= paint2\n", paint1 == paint2 ? '=' : '!');
954
955 #StdOut
956 paint1 == paint2
957 ##
958 ##
959
960##
961
962#Topic ##
963# ------------------------------------------------------------------------------
964#Topic Dither
965
Cary Clarkce101242017-09-01 15:51:02 -0400966Dither increases fidelity by adjusting the color of adjacent pixels.
Cary Clark8032b982017-07-28 11:04:54 -0400967This can help to smooth color transitions and reducing banding in gradients.
968Dithering lessens visible banding from kRGB_565_SkColorType
969and kRGBA_8888_SkColorType gradients,
970and improves rendering into a kRGB_565_SkColorType Surface.
971
972Dithering is always enabled for linear gradients drawing into
973kRGB_565_SkColorType Surface and kRGBA_8888_SkColorType Surface.
974Dither cannot be enabled for kAlpha_8_SkColorType Surface and
975kRGBA_F16_SkColorType Surface.
976
977Dither is disabled by default.
978Dither can be enabled by default by setting SkPaintDefaults_Flags to kDither_Flag
979at compile time.
980
981Some platform implementations may ignore dithering. Set
982
983#Define SK_IGNORE_GPU_DITHER
984
985to ignore Dither on GPU_Surface.
986
987#Example
988#Description
989Dithering in the bottom half more closely approximates the requested color by
990alternating nearby colors from pixel to pixel.
991##
992void draw(SkCanvas* canvas) {
993 SkBitmap bm16;
994 bm16.allocPixels(SkImageInfo::Make(32, 32, kRGB_565_SkColorType, kOpaque_SkAlphaType));
995 SkCanvas c16(bm16);
996 SkPaint colorPaint;
997 for (auto dither : { false, true } ) {
998 colorPaint.setDither(dither);
999 for (auto colors : { 0xFF333333, 0xFF666666, 0xFF999999, 0xFFCCCCCC } ) {
1000 for (auto mask : { 0xFFFF0000, 0xFF00FF00, 0xFF0000FF, 0xFFFFFFFF } ) {
1001 colorPaint.setColor(colors & mask);
1002 c16.drawRect({0, 0, 8, 4}, colorPaint);
1003 c16.translate(8, 0);
1004 }
1005 c16.translate(-32, 4);
1006 }
1007 }
1008 canvas->scale(8, 8);
1009 canvas->drawBitmap(bm16, 0, 0);
1010}
1011##
1012
1013#Example
1014#Description
1015Dithering introduces subtle adjustments to color to smooth gradients.
1016Drawing the gradient repeatedly with SkBlendMode::kPlus exaggerates the
1017dither, making it easier to see.
1018##
1019void draw(SkCanvas* canvas) {
1020 canvas->clear(0);
1021 SkBitmap bm32;
1022 bm32.allocPixels(SkImageInfo::Make(20, 10, kN32_SkColorType, kPremul_SkAlphaType));
1023 SkCanvas c32(bm32);
1024 SkPoint points[] = {{0, 0}, {20, 0}};
1025 SkColor colors[] = {0xFF334455, 0xFF662211 };
1026 SkPaint paint;
1027 paint.setShader(SkGradientShader::MakeLinear(
1028 points, colors, nullptr, SK_ARRAY_COUNT(colors),
1029 SkShader::kClamp_TileMode, 0, nullptr));
1030 paint.setDither(true);
1031 c32.drawPaint(paint);
1032 canvas->scale(12, 12);
1033 canvas->drawBitmap(bm32, 0, 0);
1034 paint.setBlendMode(SkBlendMode::kPlus);
1035 canvas->drawBitmap(bm32, 0, 11, &paint);
1036 canvas->drawBitmap(bm32, 0, 11, &paint);
1037 canvas->drawBitmap(bm32, 0, 11, &paint);
1038}
1039##
1040
1041#Method bool isDither() const
1042
1043 If true, color error may be distributed to smooth color transition.
1044
1045 Equivalent to getFlags masked with kDither_Flag.
1046
1047 #Return kDither_Flag state ##
1048
1049 #Example
1050 SkPaint paint;
1051 SkDebugf("paint.isDither() %c= !!(paint.getFlags() & SkPaint::kDither_Flag)\n",
1052 paint.isDither() == !!(paint.getFlags() & SkPaint::kDither_Flag) ? '=' : '!');
1053 paint.setDither(true);
1054 SkDebugf("paint.isDither() %c= !!(paint.getFlags() & SkPaint::kDither_Flag)\n",
1055 paint.isDither() == !!(paint.getFlags() & SkPaint::kDither_Flag) ? '=' : '!');
1056
1057 #StdOut
1058 paint.isDither() == !!(paint.getFlags() & SkPaint::kDither_Flag)
1059 paint.isDither() == !!(paint.getFlags() & SkPaint::kDither_Flag)
1060 ##
1061 ##
1062
1063##
1064
1065#Method void setDither(bool dither)
1066
1067 Requests, but does not require, to distribute color error.
1068
1069 Sets kDither_Flag if dither is true.
1070 Clears kDither_Flag if dither is false.
1071
1072 #Param dither setting for kDither_Flag ##
1073
1074 #Example
1075 SkPaint paint1, paint2;
1076 paint1.setDither(true);
1077 paint2.setFlags(paint2.getFlags() | SkPaint::kDither_Flag);
1078 SkDebugf("paint1 %c= paint2\n", paint1 == paint2 ? '=' : '!');
1079
1080 #StdOut
1081 paint1 == paint2
1082 ##
1083 ##
1084
1085 #SeeAlso kRGB_565_SkColorType
1086
1087##
1088
1089#SeeAlso Gradient Color_RGB-565
1090
1091#Topic ##
1092# ------------------------------------------------------------------------------
1093#Topic Device_Text
1094
1095LCD_Text and Subpixel_Text increase the precision of glyph position.
1096
1097When set, Flags kLCDRenderText_Flag takes advantage of the organization of Color_RGB stripes that
1098create a color, and relies
Cary Clarkce101242017-09-01 15:51:02 -04001099on the small size of the stripe and visual perception to make the color fringing imperceptible.
Cary Clark8032b982017-07-28 11:04:54 -04001100LCD_Text can be enabled on devices that orient stripes horizontally or vertically, and that order
1101the color components as Color_RGB or Color_RBG.
1102
1103Flags kSubpixelText_Flag uses the pixel transparency to represent a fractional offset.
1104As the opaqueness
1105of the color increases, the edge of the glyph appears to move towards the outside of the pixel.
1106
1107Either or both techniques can be enabled.
1108kLCDRenderText_Flag and kSubpixelText_Flag are clear by default.
1109LCD_Text or Subpixel_Text can be enabled by default by setting SkPaintDefaults_Flags to
1110kLCDRenderText_Flag or kSubpixelText_Flag (or both) at compile time.
1111
1112#Example
1113 #Description
1114 Four commas are drawn normally and with combinations of LCD_Text and Subpixel_Text.
Cary Clarkce101242017-09-01 15:51:02 -04001115 When Subpixel_Text is disabled, the comma Glyphs are identical, but not evenly spaced.
1116 When Subpixel_Text is enabled, the comma Glyphs are unique, but appear evenly spaced.
Cary Clark8032b982017-07-28 11:04:54 -04001117 ##
1118
1119 SkBitmap bitmap;
1120 bitmap.allocN32Pixels(24, 33);
1121 SkCanvas offscreen(bitmap);
1122 offscreen.clear(SK_ColorWHITE);
1123 SkPaint paint;
1124 paint.setAntiAlias(true);
1125 paint.setTextSize(20);
1126 for (bool lcd : { false, true }) {
1127 paint.setLCDRenderText(lcd);
1128 for (bool subpixel : { false, true }) {
1129 paint.setSubpixelText(subpixel);
1130 offscreen.drawString(",,,,", 0, 4, paint);
1131 offscreen.translate(0, 7);
1132 }
1133 }
1134 canvas->drawBitmap(bitmap, 4, 12);
1135 canvas->scale(9, 9);
1136 canvas->drawBitmap(bitmap, 4, -1);
1137##
1138
1139#Subtopic Linear_Text
1140#Alias Linear_Text # makes this a top level name, since it is under subtopic Device_Text
1141
1142Linear_Text selects whether text is rendered as a Glyph or as a Path.
1143If kLinearText_Flag is set, it has the same effect as setting Hinting to kNormal_Hinting.
Cary Clarkd0530ba2017-09-14 11:25:39 -04001144If kLinearText_Flag is clear, it is the same as setting Hinting to kNo_Hinting.
Cary Clark8032b982017-07-28 11:04:54 -04001145
1146#Method bool isLinearText() const
1147
1148 If true, text is converted to Path before drawing and measuring.
1149
1150 Equivalent to getFlags masked with kLinearText_Flag.
1151
1152 #Return kLinearText_Flag state ##
1153
1154 #Example
1155 #Height 128
1156 void draw(SkCanvas* canvas) {
1157 SkPaint paint;
1158 paint.setAntiAlias(true);
1159 const char testStr[] = "xxxx xxxx";
1160 for (auto linearText : { false, true } ) {
1161 paint.setLinearText(linearText);
1162 paint.setTextSize(24);
1163 canvas->drawString(paint.isLinearText() ? "linear" : "hinted", 128, 30, paint);
1164 for (SkScalar textSize = 8; textSize < 30; textSize *= 1.22f) {
1165 paint.setTextSize(textSize);
1166 canvas->translate(0, textSize);
1167 canvas->drawString(testStr, 10, 0, paint);
1168 }
1169 }
1170 }
1171 ##
1172
1173 #SeeAlso setLinearText Hinting
1174##
1175
1176#Method void setLinearText(bool linearText)
1177
1178 If true, text is converted to Path before drawing and measuring.
1179 By default, kLinearText_Flag is clear.
1180
1181 Sets kLinearText_Flag if linearText is true.
1182 Clears kLinearText_Flag if linearText is false.
1183
1184 #Param linearText setting for kLinearText_Flag ##
1185
1186 #Example
1187 #Height 128
1188 void draw(SkCanvas* canvas) {
1189 SkPaint paint;
1190 paint.setAntiAlias(true);
1191 const char testStr[] = "abcd efgh";
1192 for (int textSize : { 12, 24 } ) {
1193 paint.setTextSize(textSize);
1194 for (auto linearText : { false, true } ) {
1195 paint.setLinearText(linearText);
1196 SkString width;
1197 width.appendScalar(paint.measureText(testStr, SK_ARRAY_COUNT(testStr), nullptr));
1198 canvas->translate(0, textSize + 4);
1199 canvas->drawString(testStr, 10, 0, paint);
1200 canvas->drawString(width, 128, 0, paint);
1201 }
1202 }
1203 }
1204 ##
1205
1206 #SeeAlso isLinearText Hinting
1207##
1208
1209#Subtopic ##
1210
1211#Subtopic Subpixel_Text
1212#Alias Subpixel_Text # makes this a top level name, since it is under subtopic Device_Text
1213
1214Flags kSubpixelText_Flag uses the pixel transparency to represent a fractional offset.
1215As the opaqueness
1216of the color increases, the edge of the glyph appears to move towards the outside of the pixel.
1217
1218#Method bool isSubpixelText() const
1219
Cary Clarkce101242017-09-01 15:51:02 -04001220 If true, Glyphs at different sub-pixel positions may differ on pixel edge coverage.
Cary Clark8032b982017-07-28 11:04:54 -04001221
1222 Equivalent to getFlags masked with kSubpixelText_Flag.
1223
1224 #Return kSubpixelText_Flag state ##
1225
1226 #Example
1227SkPaint paint;
1228SkDebugf("paint.isSubpixelText() %c= !!(paint.getFlags() & SkPaint::kSubpixelText_Flag)\n",
1229 paint.isSubpixelText() == !!(paint.getFlags() & SkPaint::kSubpixelText_Flag) ? '=' : '!');
1230paint.setSubpixelText(true);
1231SkDebugf("paint.isSubpixelText() %c= !!(paint.getFlags() & SkPaint::kSubpixelText_Flag)\n",
1232 paint.isSubpixelText() == !!(paint.getFlags() & SkPaint::kSubpixelText_Flag) ? '=' : '!');
1233
1234 #StdOut
1235 paint.isSubpixelText() == !!(paint.getFlags() & SkPaint::kSubpixelText_Flag)
1236 paint.isSubpixelText() == !!(paint.getFlags() & SkPaint::kSubpixelText_Flag)
1237 ##
1238 ##
1239
1240##
1241
1242#Method void setSubpixelText(bool subpixelText)
1243
Cary Clarkce101242017-09-01 15:51:02 -04001244 Requests, but does not require, that Glyphs respect sub-pixel positioning.
Cary Clark8032b982017-07-28 11:04:54 -04001245
1246 Sets kSubpixelText_Flag if subpixelText is true.
1247 Clears kSubpixelText_Flag if subpixelText is false.
1248
1249 #Param subpixelText setting for kSubpixelText_Flag ##
1250
1251 #Example
1252 SkPaint paint1, paint2;
1253 paint1.setSubpixelText(true);
1254 paint2.setFlags(paint2.getFlags() | SkPaint::kSubpixelText_Flag);
1255 SkDebugf("paint1 %c= paint2\n", paint1 == paint2 ? '=' : '!');
1256
1257 #StdOut
1258 paint1 == paint2
1259 ##
1260 ##
1261
1262##
1263
1264#Subtopic ##
1265
1266#Subtopic LCD_Text
1267#Alias LCD_Text # makes this a top level name, since it is under subtopic Device_Text
1268
1269When set, Flags kLCDRenderText_Flag takes advantage of the organization of Color_RGB stripes that
1270create a color, and relies
Cary Clarkce101242017-09-01 15:51:02 -04001271on the small size of the stripe and visual perception to make the color fringing imperceptible.
Cary Clark8032b982017-07-28 11:04:54 -04001272LCD_Text can be enabled on devices that orient stripes horizontally or vertically, and that order
1273the color components as Color_RGB or Color_RBG.
1274
1275#Method bool isLCDRenderText() const
1276
Cary Clarkce101242017-09-01 15:51:02 -04001277 If true, Glyphs may use LCD striping to improve glyph edges.
Cary Clark8032b982017-07-28 11:04:54 -04001278
1279 Returns true if Flags kLCDRenderText_Flag is set.
1280
1281 #Return kLCDRenderText_Flag state ##
1282
1283 #Example
1284SkPaint paint;
1285SkDebugf("paint.isLCDRenderText() %c= !!(paint.getFlags() & SkPaint::kLCDRenderText_Flag)\n",
1286 paint.isLCDRenderText() == !!(paint.getFlags() & SkPaint::kLCDRenderText_Flag) ? '=' : '!');
1287paint.setLCDRenderText(true);
1288SkDebugf("paint.isLCDRenderText() %c= !!(paint.getFlags() & SkPaint::kLCDRenderText_Flag)\n",
1289 paint.isLCDRenderText() == !!(paint.getFlags() & SkPaint::kLCDRenderText_Flag) ? '=' : '!');
1290
1291 #StdOut
1292 paint.isLCDRenderText() == !!(paint.getFlags() & SkPaint::kLCDRenderText_Flag)
1293 paint.isLCDRenderText() == !!(paint.getFlags() & SkPaint::kLCDRenderText_Flag)
1294 ##
1295 ##
1296
1297##
1298
1299#Method void setLCDRenderText(bool lcdText)
1300
Cary Clarkce101242017-09-01 15:51:02 -04001301 Requests, but does not require, that Glyphs use LCD striping for glyph edges.
Cary Clark8032b982017-07-28 11:04:54 -04001302
1303 Sets kLCDRenderText_Flag if lcdText is true.
1304 Clears kLCDRenderText_Flag if lcdText is false.
1305
1306 #Param lcdText setting for kLCDRenderText_Flag ##
1307
1308 #Example
1309 SkPaint paint1, paint2;
1310 paint1.setLCDRenderText(true);
1311 paint2.setFlags(paint2.getFlags() | SkPaint::kLCDRenderText_Flag);
1312 SkDebugf("paint1 %c= paint2\n", paint1 == paint2 ? '=' : '!');
1313
1314 #StdOut
1315 paint1 == paint2
1316 ##
1317 ##
1318
1319
1320##
1321
1322#Subtopic ##
1323
1324#Topic ##
1325# ------------------------------------------------------------------------------
1326#Topic Font_Embedded_Bitmaps
1327#Alias Font_Embedded_Bitmaps # long-winded enough, alias so I don't type Paint_Font_...
1328
Cary Clarkce101242017-09-01 15:51:02 -04001329Font_Embedded_Bitmaps allows selecting custom sized bitmap Glyphs.
Cary Clark8032b982017-07-28 11:04:54 -04001330Flags kEmbeddedBitmapText_Flag when set chooses an embedded bitmap glyph over an outline contained
1331in a font if the platform supports this option.
1332
1333FreeType selects the bitmap glyph if available when kEmbeddedBitmapText_Flag is set, and selects
1334the outline glyph if kEmbeddedBitmapText_Flag is clear.
1335Windows may select the bitmap glyph but is not required to do so.
1336OS_X and iOS do not support this option.
1337
1338Font_Embedded_Bitmaps is disabled by default.
1339Font_Embedded_Bitmaps can be enabled by default by setting SkPaintDefaults_Flags to
1340kEmbeddedBitmapText_Flag at compile time.
1341
1342#Example
1343 #ToDo image will only output on Ubuntu ... how to handle that in fiddle? ##
1344 #Platform !fiddle
1345 #Description
Cary Clarkce101242017-09-01 15:51:02 -04001346 The "hintgasp" TrueType font in the Skia resources/fonts directory
1347 includes an embedded bitmap Glyph at odd font sizes. This example works
1348 on platforms that use FreeType as their Font_Engine.
1349 Windows may, but is not required to, return a bitmap glyph if
1350 kEmbeddedBitmapText_Flag is set.
Cary Clark8032b982017-07-28 11:04:54 -04001351 ##
1352 #Image embeddedbitmap.png
1353
1354 SkBitmap bitmap;
1355 bitmap.allocN32Pixels(30, 15);
1356 bitmap.eraseColor(0);
1357 SkCanvas offscreen(bitmap);
1358 SkPaint paint;
1359 paint.setAntiAlias(true);
1360 paint.setTextSize(13);
Hal Canary53e5e7d2017-12-08 14:25:14 -05001361 paint.setTypeface(MakeResourceAsTypeface("fonts/hintgasp.ttf"));
Cary Clark8032b982017-07-28 11:04:54 -04001362 for (bool embedded : { false, true}) {
1363 paint.setEmbeddedBitmapText(embedded);
1364 offscreen.drawString("A", embedded ? 5 : 15, 15, paint);
1365 }
1366 canvas->drawBitmap(bitmap, 0, 0);
1367 canvas->scale(10, 10);
1368 canvas->drawBitmap(bitmap, -2, 1);
1369##
1370
1371#Method bool isEmbeddedBitmapText() const
1372
Cary Clarkce101242017-09-01 15:51:02 -04001373 If true, Font_Engine may return Glyphs from font bitmaps instead of from outlines.
Cary Clark8032b982017-07-28 11:04:54 -04001374
1375 Equivalent to getFlags masked with kEmbeddedBitmapText_Flag.
1376
1377 #Return kEmbeddedBitmapText_Flag state ##
1378
1379 #Example
1380 SkPaint paint;
1381 SkDebugf("paint.isEmbeddedBitmapText() %c="
1382 " !!(paint.getFlags() & SkPaint::kEmbeddedBitmapText_Flag)\n",
1383 paint.isEmbeddedBitmapText() ==
1384 !!(paint.getFlags() & SkPaint::kEmbeddedBitmapText_Flag) ? '=' : '!');
1385 paint.setEmbeddedBitmapText(true);
1386 SkDebugf("paint.isEmbeddedBitmapText() %c="
1387 " !!(paint.getFlags() & SkPaint::kEmbeddedBitmapText_Flag)\n",
1388 paint.isEmbeddedBitmapText() ==
1389 !!(paint.getFlags() & SkPaint::kEmbeddedBitmapText_Flag) ? '=' : '!');
1390
1391 #StdOut
1392 paint.isEmbeddedBitmapText() == !!(paint.getFlags() & SkPaint::kEmbeddedBitmapText_Flag)
1393 paint.isEmbeddedBitmapText() == !!(paint.getFlags() & SkPaint::kEmbeddedBitmapText_Flag)
1394 ##
1395 ##
1396
1397##
1398
1399#Method void setEmbeddedBitmapText(bool useEmbeddedBitmapText)
1400
1401 Requests, but does not require, to use bitmaps in fonts instead of outlines.
1402
1403 Sets kEmbeddedBitmapText_Flag if useEmbeddedBitmapText is true.
1404 Clears kEmbeddedBitmapText_Flag if useEmbeddedBitmapText is false.
1405
1406 #Param useEmbeddedBitmapText setting for kEmbeddedBitmapText_Flag ##
1407
1408 #Example
1409 SkPaint paint1, paint2;
1410 paint1.setEmbeddedBitmapText(true);
1411 paint2.setFlags(paint2.getFlags() | SkPaint::kEmbeddedBitmapText_Flag);
1412 SkDebugf("paint1 %c= paint2\n", paint1 == paint2 ? '=' : '!');
1413
1414 #StdOut
1415 paint1 == paint2
1416 ##
1417 ##
1418
1419##
1420
1421#Topic ##
1422# ------------------------------------------------------------------------------
1423#Topic Automatic_Hinting
1424#Substitute auto-hinting
1425
1426If Hinting is set to kNormal_Hinting or kFull_Hinting, Automatic_Hinting
Cary Clarkce101242017-09-01 15:51:02 -04001427instructs the Font_Manager to always hint Glyphs.
Cary Clark8032b982017-07-28 11:04:54 -04001428Automatic_Hinting has no effect if Hinting is set to kNo_Hinting or
1429kSlight_Hinting.
1430
1431Automatic_Hinting only affects platforms that use FreeType as the Font_Manager.
1432
1433#Method bool isAutohinted() const
1434
1435 If true, and if Hinting is set to kNormal_Hinting or kFull_Hinting, and if
1436 platform uses FreeType as the Font_Manager, instruct the Font_Manager to always hint
Cary Clarkce101242017-09-01 15:51:02 -04001437 Glyphs.
Cary Clark8032b982017-07-28 11:04:54 -04001438
1439 Equivalent to getFlags masked with kAutoHinting_Flag.
1440
1441 #Return kAutoHinting_Flag state ##
1442
1443 #Example
1444 SkPaint paint;
1445 for (auto forceAutoHinting : { false, true} ) {
1446 paint.setAutohinted(forceAutoHinting);
1447 SkDebugf("paint.isAutohinted() %c="
1448 " !!(paint.getFlags() & SkPaint::kAutoHinting_Flag)\n",
1449 paint.isAutohinted() ==
1450 !!(paint.getFlags() & SkPaint::kAutoHinting_Flag) ? '=' : '!');
1451 }
1452 #StdOut
1453 paint.isAutohinted() == !!(paint.getFlags() & SkPaint::kAutoHinting_Flag)
1454 paint.isAutohinted() == !!(paint.getFlags() & SkPaint::kAutoHinting_Flag)
1455 ##
1456 ##
1457
1458 #SeeAlso setAutohinted Hinting
1459
1460##
1461
1462#Method void setAutohinted(bool useAutohinter)
1463
1464 If Hinting is set to kNormal_Hinting or kFull_Hinting and useAutohinter is set,
Cary Clarkce101242017-09-01 15:51:02 -04001465 instruct the Font_Manager to always hint Glyphs.
Cary Clark8032b982017-07-28 11:04:54 -04001466 Automatic_Hinting has no effect if Hinting is set to kNo_Hinting or
1467 kSlight_Hinting.
1468
Cary Clark579985c2017-07-31 11:48:27 -04001469 Only affects platforms that use FreeType as the Font_Manager.
Cary Clark8032b982017-07-28 11:04:54 -04001470
1471 Sets kAutoHinting_Flag if useAutohinter is true.
1472 Clears kAutoHinting_Flag if useAutohinter is false.
1473
1474 #Param useAutohinter setting for kAutoHinting_Flag ##
1475
1476 #Example
1477 void draw(SkCanvas* canvas) {
1478 SkPaint paint;
1479 paint.setAntiAlias(true);
1480 const char testStr[] = "xxxx xxxx";
1481 for (auto forceAutoHinting : { false, true} ) {
1482 paint.setAutohinted(forceAutoHinting);
1483 paint.setTextSize(24);
1484 canvas->drawString(paint.isAutohinted() ? "auto-hinted" : "default", 108, 30, paint);
1485 for (SkScalar textSize = 8; textSize < 30; textSize *= 1.22f) {
1486 paint.setTextSize(textSize);
1487 canvas->translate(0, textSize);
1488 canvas->drawString(testStr, 10, 0, paint);
1489 }
1490 }
1491 }
1492 ##
1493
1494 #SeeAlso isAutohinted Hinting
1495
1496##
1497
1498#Topic ##
1499# ------------------------------------------------------------------------------
1500#Topic Vertical_Text
1501
1502Text may be drawn by positioning each glyph, or by positioning the first glyph and
Cary Clarkce101242017-09-01 15:51:02 -04001503using Font_Advance to position subsequent Glyphs. By default, each successive glyph
1504is positioned to the right of the preceding glyph. Vertical_Text sets successive
1505Glyphs to position below the preceding glyph.
Cary Clark8032b982017-07-28 11:04:54 -04001506
Cary Clarkce101242017-09-01 15:51:02 -04001507Skia can translate text character codes as a series of Glyphs, but does not implement
Cary Clark8032b982017-07-28 11:04:54 -04001508font substitution,
Cary Clarkce101242017-09-01 15:51:02 -04001509textual substitution, line layout, or contextual spacing like Kerning pairs. Use
Cary Clark6fc50412017-09-21 12:31:06 -04001510a text shaping engine like
1511#A HarfBuzz # http://harfbuzz.org/ ##
1512 to translate text runs
Cary Clark8032b982017-07-28 11:04:54 -04001513into glyph series.
1514
1515Vertical_Text is clear if text is drawn left to right or set if drawn from top to bottom.
1516
1517Flags kVerticalText_Flag if clear draws text left to right.
1518Flags kVerticalText_Flag if set draws text top to bottom.
1519
1520Vertical_Text is clear by default.
1521Vertical_Text can be set by default by setting SkPaintDefaults_Flags to
1522kVerticalText_Flag at compile time.
1523
1524#Example
1525
1526void draw(SkCanvas* canvas) {
1527 SkPaint paint;
1528 paint.setAntiAlias(true);
1529 paint.setTextSize(50);
1530 for (bool vertical : { false, true } ) {
1531 paint.setVerticalText(vertical);
1532 canvas->drawString("aAlL", 25, 50, paint);
1533 }
1534}
1535
1536##
1537
1538#Method bool isVerticalText() const
1539
Cary Clarkce101242017-09-01 15:51:02 -04001540 If true, Glyphs are drawn top to bottom instead of left to right.
Cary Clark8032b982017-07-28 11:04:54 -04001541
1542 Equivalent to getFlags masked with kVerticalText_Flag.
1543
1544 #Return kVerticalText_Flag state ##
1545
1546 #Example
1547 SkPaint paint;
1548 SkDebugf("paint.isVerticalText() %c= !!(paint.getFlags() & SkPaint::kVerticalText_Flag)\n",
1549 paint.isVerticalText() == !!(paint.getFlags() & SkPaint::kVerticalText_Flag) ? '=' : '!');
1550 paint.setVerticalText(true);
1551 SkDebugf("paint.isVerticalText() %c= !!(paint.getFlags() & SkPaint::kVerticalText_Flag)\n",
1552 paint.isVerticalText() == !!(paint.getFlags() & SkPaint::kVerticalText_Flag) ? '=' : '!');
1553
1554 #StdOut
1555 paint.isVerticalText() == !!(paint.getFlags() & SkPaint::kVerticalText_Flag)
1556 paint.isVerticalText() == !!(paint.getFlags() & SkPaint::kVerticalText_Flag)
1557 ##
1558 ##
1559
1560##
1561
1562#Method void setVerticalText(bool verticalText)
1563
1564 If true, text advance positions the next glyph below the previous glyph instead of to the
1565 right of previous glyph.
1566
1567 Sets kVerticalText_Flag if vertical is true.
1568 Clears kVerticalText_Flag if vertical is false.
1569
1570 #Param verticalText setting for kVerticalText_Flag ##
1571
1572 #Example
1573 SkPaint paint1, paint2;
1574 paint1.setVerticalText(true);
1575 paint2.setFlags(paint2.getFlags() | SkPaint::kVerticalText_Flag);
1576 SkDebugf("paint1 %c= paint2\n", paint1 == paint2 ? '=' : '!');
1577
1578 #StdOut
1579 paint1 == paint2
1580 ##
1581 ##
1582
1583##
1584
1585#Topic ##
1586# ------------------------------------------------------------------------------
1587
1588#Topic Fake_Bold
1589
1590Fake_Bold approximates the bold font style accompanying a normal font when a bold font face
1591is not available. Skia does not provide font substitution; it is up to the client to find the
Cary Clarkbc5697d2017-10-04 14:31:33 -04001592bold font face using the platform Font_Manager.
Cary Clark8032b982017-07-28 11:04:54 -04001593
1594Use Text_Skew_X to approximate an italic font style when the italic font face
1595is not available.
1596
Cary Clarkce101242017-09-01 15:51:02 -04001597A FreeType based port may define SK_USE_FREETYPE_EMBOLDEN at compile time to direct
1598the font engine to create the bold Glyphs. Otherwise, the extra bold is computed
Cary Clark8032b982017-07-28 11:04:54 -04001599by increasing the stroke width and setting the Style to kStrokeAndFill_Style as needed.
1600
1601Fake_Bold is disabled by default.
1602
1603#Example
1604#Height 128
1605void draw(SkCanvas* canvas) {
1606 SkPaint paint;
1607 paint.setAntiAlias(true);
1608 paint.setTextSize(40);
1609 canvas->drawString("OjYy_-", 10, 35, paint);
1610 paint.setFakeBoldText(true);
1611 canvas->drawString("OjYy_-", 10, 75, paint);
1612 // create a custom fake bold by varying the stroke width
1613 paint.setFakeBoldText(false);
1614 paint.setStyle(SkPaint::kStrokeAndFill_Style);
1615 paint.setStrokeWidth(40.f / 48);
1616 canvas->drawString("OjYy_-", 10, 115, paint);
1617}
1618##
1619
1620#Method bool isFakeBoldText() const
1621
1622 If true, approximate bold by increasing the stroke width when creating glyph bitmaps
1623 from outlines.
1624
1625 Equivalent to getFlags masked with kFakeBoldText_Flag.
1626
1627 #Return kFakeBoldText_Flag state ##
1628
1629 #Example
1630 SkPaint paint;
1631 SkDebugf("paint.isFakeBoldText() %c= !!(paint.getFlags() & SkPaint::kFakeBoldText_Flag)\n",
1632 paint.isFakeBoldText() == !!(paint.getFlags() & SkPaint::kFakeBoldText_Flag) ? '=' : '!');
1633 paint.setFakeBoldText(true);
1634 SkDebugf("paint.isFakeBoldText() %c= !!(paint.getFlags() & SkPaint::kFakeBoldText_Flag)\n",
1635 paint.isFakeBoldText() == !!(paint.getFlags() & SkPaint::kFakeBoldText_Flag) ? '=' : '!');
1636
1637 #StdOut
1638 paint.isFakeBoldText() == !!(paint.getFlags() & SkPaint::kFakeBoldText_Flag)
1639 paint.isFakeBoldText() == !!(paint.getFlags() & SkPaint::kFakeBoldText_Flag)
1640 ##
1641 ##
1642
1643##
1644
1645#Method void setFakeBoldText(bool fakeBoldText)
1646
Cary Clarkce101242017-09-01 15:51:02 -04001647 Use increased stroke width when creating glyph bitmaps to approximate a bold typeface.
Cary Clark8032b982017-07-28 11:04:54 -04001648
1649 Sets kFakeBoldText_Flag if fakeBoldText is true.
1650 Clears kFakeBoldText_Flag if fakeBoldText is false.
1651
1652 #Param fakeBoldText setting for kFakeBoldText_Flag ##
1653
1654 #Example
1655 SkPaint paint1, paint2;
1656 paint1.setFakeBoldText(true);
1657 paint2.setFlags(paint2.getFlags() | SkPaint::kFakeBoldText_Flag);
1658 SkDebugf("paint1 %c= paint2\n", paint1 == paint2 ? '=' : '!');
1659
1660 #StdOut
1661 paint1 == paint2
1662 ##
1663 ##
1664
1665##
1666
1667#Topic ##
1668
1669# ------------------------------------------------------------------------------
1670#Topic Full_Hinting_Spacing
1671#Alias Full_Hinting_Spacing # long winded enough -- maybe things with two underscores auto-aliased?
1672
Cary Clarkce101242017-09-01 15:51:02 -04001673if Hinting is set to kFull_Hinting, Full_Hinting_Spacing adjusts the character
1674spacing by the difference of the hinted and Unhinted Left_Side_Bearing and
1675Right_Side_Bearing. Full_Hinting_Spacing only applies to platforms that use
1676FreeType as their Font_Engine.
Cary Clark8032b982017-07-28 11:04:54 -04001677
Cary Clarkce101242017-09-01 15:51:02 -04001678Full_Hinting_Spacing is not related to text Kerning, where the space between
Cary Clarkbc5697d2017-10-04 14:31:33 -04001679a specific pair of characters is adjusted using data in the font Kerning tables.
Cary Clark8032b982017-07-28 11:04:54 -04001680
1681#Method bool isDevKernText() const
1682
1683 Returns if character spacing may be adjusted by the hinting difference.
1684
1685 Equivalent to getFlags masked with kDevKernText_Flag.
1686
1687 #Return kDevKernText_Flag state ##
1688
1689 #Example
1690 SkPaint paint;
1691 SkDebugf("paint.isDevKernText() %c= !!(paint.getFlags() & SkPaint::kDevKernText_Flag)\n",
1692 paint.isDevKernText() == !!(paint.getFlags() & SkPaint::kDevKernText_Flag) ? '=' : '!');
1693 paint.setDevKernText(true);
1694 SkDebugf("paint.isDevKernText() %c= !!(paint.getFlags() & SkPaint::kDevKernText_Flag)\n",
1695 paint.isDevKernText() == !!(paint.getFlags() & SkPaint::kDevKernText_Flag) ? '=' : '!');
1696 ##
1697
1698##
1699
1700#Method void setDevKernText(bool devKernText)
1701
1702 Requests, but does not require, to use hinting to adjust glyph spacing.
1703
1704 Sets kDevKernText_Flag if devKernText is true.
1705 Clears kDevKernText_Flag if devKernText is false.
1706
1707 #Param devKernText setting for devKernText ##
1708
1709 #Example
1710 SkPaint paint1, paint2;
1711 paint1.setDevKernText(true);
1712 paint2.setFlags(paint2.getFlags() | SkPaint::kDevKernText_Flag);
1713 SkDebugf("paint1 %c= paint2\n", paint1 == paint2 ? '=' : '!');
1714
1715 #StdOut
1716 paint1 == paint2
1717 ##
1718 ##
1719
1720##
1721
1722#Topic ##
1723# ------------------------------------------------------------------------------
1724#Topic Filter_Quality_Methods
1725
1726Filter_Quality trades speed for image filtering when the image is scaled.
1727A lower Filter_Quality draws faster, but has less fidelity.
1728A higher Filter_Quality draws slower, but looks better.
Cary Clarkce101242017-09-01 15:51:02 -04001729If the image is drawn without scaling, the Filter_Quality choice will not result
1730in a noticeable difference.
Cary Clark8032b982017-07-28 11:04:54 -04001731
1732Filter_Quality is used in Paint passed as a parameter to
1733#List
1734# SkCanvas::drawBitmap ##
1735# SkCanvas::drawBitmapRect ##
1736# SkCanvas::drawImage ##
1737# SkCanvas::drawImageRect ##
1738 #ToDo probably more... ##
1739#List ##
1740and when Paint has a Shader specialization that uses Image or Bitmap.
1741
1742Filter_Quality is kNone_SkFilterQuality by default.
1743
1744#Example
1745#Image 3
1746void draw(SkCanvas* canvas) {
1747 SkPaint paint;
1748 canvas->scale(.2f, .2f);
1749 for (SkFilterQuality q : { kNone_SkFilterQuality, kLow_SkFilterQuality,
1750 kMedium_SkFilterQuality, kHigh_SkFilterQuality } ) {
1751 paint.setFilterQuality(q);
1752 canvas->drawImage(image.get(), 0, 0, &paint);
1753 canvas->translate(550, 0);
1754 if (kLow_SkFilterQuality == q) canvas->translate(-1100, 550);
1755 }
1756}
1757##
1758
1759#Method SkFilterQuality getFilterQuality() const
1760
1761Returns Filter_Quality, the image filtering level. A lower setting
1762draws faster; a higher setting looks better when the image is scaled.
1763
1764#Return one of: kNone_SkFilterQuality, kLow_SkFilterQuality,
1765 kMedium_SkFilterQuality, kHigh_SkFilterQuality
1766#Return ##
1767
1768#Example
1769 SkPaint paint;
1770 SkDebugf("kNone_SkFilterQuality %c= paint.getFilterQuality()\n",
1771 kNone_SkFilterQuality == paint.getFilterQuality() ? '=' : '!');
1772
1773 #StdOut
1774 kNone_SkFilterQuality == paint.getFilterQuality()
1775 ##
1776##
1777
1778##
1779
1780
1781#Method void setFilterQuality(SkFilterQuality quality)
1782
1783Sets Filter_Quality, the image filtering level. A lower setting
1784draws faster; a higher setting looks better when the image is scaled.
Cary Clark579985c2017-07-31 11:48:27 -04001785Does not check to see if quality is valid.
Cary Clark8032b982017-07-28 11:04:54 -04001786
1787#Param quality one of: kNone_SkFilterQuality, kLow_SkFilterQuality,
1788 kMedium_SkFilterQuality, kHigh_SkFilterQuality
1789##
1790
1791#Example
1792 SkPaint paint;
1793 paint.setFilterQuality(kHigh_SkFilterQuality);
1794 SkDebugf("kHigh_SkFilterQuality %c= paint.getFilterQuality()\n",
1795 kHigh_SkFilterQuality == paint.getFilterQuality() ? '=' : '!');
1796
1797 #StdOut
1798 kHigh_SkFilterQuality == paint.getFilterQuality()
1799 ##
1800##
1801
1802#SeeAlso SkFilterQuality Image_Scaling
1803
1804##
1805
1806#Topic ##
1807# ------------------------------------------------------------------------------
1808#Topic Color_Methods
1809
1810Color specifies the Color_RGB_Red, Color_RGB_Blue, Color_RGB_Green, and Color_Alpha values used to draw a filled
1811or stroked shape in a
181232-bit value. Each component occupies 8-bits, ranging from zero: no contribution;
1813to 255: full intensity. All values in any combination are valid.
1814
Cary Clarkce101242017-09-01 15:51:02 -04001815Color is not Premultiplied;
Cary Clark8032b982017-07-28 11:04:54 -04001816Color_Alpha sets the transparency independent of Color_RGB: Color_RGB_Red, Color_RGB_Blue, and Color_RGB_Green.
1817
1818The bit positions of Color_Alpha and Color_RGB are independent of the bit positions
1819on the output device, which may have more or fewer bits, and may have a different arrangement.
1820
1821#Table
1822#Legend
1823# bit positions # Color_Alpha # Color_RGB_Red # Color_RGB_Blue # Color_RGB_Green ##
1824#Legend ##
1825# # 31 - 24 # 23 - 16 # 15 - 8 # 7 - 0 ##
1826#Table ##
1827
1828#Example
1829#Height 128
1830 void draw(SkCanvas* canvas) {
1831 SkPaint paint;
1832 paint.setColor(0x8000FF00); // transparent green
1833 canvas->drawCircle(50, 50, 40, paint);
1834 paint.setARGB(128, 255, 0, 0); // transparent red
1835 canvas->drawCircle(80, 50, 40, paint);
1836 paint.setColor(SK_ColorBLUE);
1837 paint.setAlpha(0x80);
1838 canvas->drawCircle(65, 65, 40, paint);
1839 }
1840##
1841
1842#Method SkColor getColor() const
1843
Cary Clarkce101242017-09-01 15:51:02 -04001844 Retrieves Alpha and Color_RGB, Unpremultiplied, packed into 32 bits.
Cary Clark8032b982017-07-28 11:04:54 -04001845 Use helpers SkColorGetA, SkColorGetR, SkColorGetG, and SkColorGetB to extract
1846 a color component.
1847
1848 #Return Unpremultiplied Color_ARGB ##
1849
1850 #Example
1851 SkPaint paint;
1852 paint.setColor(SK_ColorYELLOW);
1853 SkColor y = paint.getColor();
1854 SkDebugf("Yellow is %d%% red, %d%% green, and %d%% blue.\n", (int) (SkColorGetR(y) / 2.55f),
1855 (int) (SkColorGetG(y) / 2.55f), (int) (SkColorGetB(y) / 2.55f));
1856
1857 #StdOut
1858 Yellow is 100% red, 100% green, and 0% blue.
1859 ##
1860 ##
1861
1862 #SeeAlso SkColor
1863
1864##
1865
1866#Method void setColor(SkColor color)
1867
Cary Clarkce101242017-09-01 15:51:02 -04001868 Sets Alpha and Color_RGB used when stroking and filling. The color is a 32-bit value,
1869 Unpremultiplied, packing 8-bit components for Alpha, Red, Blue, and Green.
Cary Clark8032b982017-07-28 11:04:54 -04001870
1871 #Param color Unpremultiplied Color_ARGB ##
Cary Clark0c5f5462017-12-15 11:21:51 -05001872
1873 #Example
Cary Clark8032b982017-07-28 11:04:54 -04001874 SkPaint green1, green2;
1875 unsigned a = 255;
1876 unsigned r = 0;
1877 unsigned g = 255;
1878 unsigned b = 0;
1879 green1.setColor((a << 24) + (r << 16) + (g << 8) + (b << 0));
1880 green2.setColor(0xFF00FF00);
1881 SkDebugf("green1 %c= green2\n", green1 == green2 ? '=' : '!');
1882
1883 #StdOut
1884 green1 == green2
1885 ##
1886 ##
1887
1888 #SeeAlso SkColor setARGB SkColorSetARGB
1889
1890##
1891
1892#Subtopic Alpha_Methods
1893
1894Color_Alpha sets the transparency independent of Color_RGB: Color_RGB_Red, Color_RGB_Blue, and Color_RGB_Green.
1895
1896#Method uint8_t getAlpha() const
1897
Cary Clarkce101242017-09-01 15:51:02 -04001898 Retrieves Alpha from the Color used when stroking and filling.
Cary Clark8032b982017-07-28 11:04:54 -04001899
Cary Clarkce101242017-09-01 15:51:02 -04001900 #Return Alpha ranging from zero, fully transparent, to 255, fully opaque ##
Cary Clark8032b982017-07-28 11:04:54 -04001901
1902 #Example
1903 SkPaint paint;
1904 SkDebugf("255 %c= paint.getAlpha()\n", 255 == paint.getAlpha() ? '=' : '!');
1905
1906 #StdOut
1907 255 == paint.getAlpha()
1908 ##
1909 ##
1910
1911##
1912
1913#Method void setAlpha(U8CPU a)
1914
Cary Clarkce101242017-09-01 15:51:02 -04001915 Replaces Alpha, leaving Color_RGB
Cary Clark8032b982017-07-28 11:04:54 -04001916 unchanged. An out of range value triggers an assert in the debug
1917 build. a is a value from zero to 255.
1918 a set to zero makes Color fully transparent; a set to 255 makes Color
1919 fully opaque.
1920
Cary Clarkce101242017-09-01 15:51:02 -04001921 #Param a Alpha component of Color ##
Cary Clark8032b982017-07-28 11:04:54 -04001922
1923 #Example
1924 SkPaint paint;
1925 paint.setColor(0x00112233);
1926 paint.setAlpha(0x44);
1927 SkDebugf("0x44112233 %c= paint.getColor()\n", 0x44112233 == paint.getColor() ? '=' : '!');
1928
1929 #StdOut
1930 0x44112233 == paint.getColor()
1931 ##
1932 ##
1933
1934##
1935
1936#Subtopic ##
1937
1938#Method void setARGB(U8CPU a, U8CPU r, U8CPU g, U8CPU b)
1939
1940 Sets Color used when drawing solid fills. The color components range from 0 to 255.
Cary Clarkce101242017-09-01 15:51:02 -04001941 The color is Unpremultiplied; Alpha sets the transparency independent of Color_RGB.
Cary Clark8032b982017-07-28 11:04:54 -04001942
1943 #Param a amount of Color_Alpha, from fully transparent (0) to fully opaque (255) ##
1944 #Param r amount of Color_RGB_Red, from no red (0) to full red (255) ##
1945 #Param g amount of Color_RGB_Green, from no green (0) to full green (255) ##
1946 #Param b amount of Color_RGB_Blue, from no blue (0) to full blue (255) ##
1947
1948 #Example
1949 SkPaint transRed1, transRed2;
1950 transRed1.setARGB(255 / 2, 255, 0, 0);
1951 transRed2.setColor(SkColorSetARGB(255 / 2, 255, 0, 0));
1952 SkDebugf("transRed1 %c= transRed2", transRed1 == transRed2 ? '=' : '!');
1953
1954 #StdOut
1955 transRed1 == transRed2
1956 ##
1957 ##
1958
1959 #SeeAlso setColor SkColorSetARGB
1960
1961##
1962
1963#Topic Color_Methods ##
1964
1965# ------------------------------------------------------------------------------
1966#Topic Style
1967
1968Style specifies if the geometry is filled, stroked, or both filled and stroked.
1969Some shapes ignore Style and are always drawn filled or stroked.
1970
1971Set Style to kFill_Style to fill the shape.
1972The fill covers the area inside the geometry for most shapes.
1973
1974Set Style to kStroke_Style to stroke the shape.
1975
1976# ------------------------------------------------------------------------------
1977#Subtopic Fill
1978
1979#ToDo write up whatever generalities make sense to describe filling ##
1980
1981#SeeAlso Path_Fill_Type
1982#Subtopic ##
1983
1984#Subtopic Stroke
Cary Clarkbc5697d2017-10-04 14:31:33 -04001985The stroke covers the area described by following the shape edge with a pen or brush of
Cary Clark8032b982017-07-28 11:04:54 -04001986Stroke_Width. The area covered where the shape starts and stops is described by Stroke_Cap.
1987The area covered where the shape turns a corner is described by Stroke_Join.
Cary Clarkbc5697d2017-10-04 14:31:33 -04001988The stroke is centered on the shape; it extends equally on either side of the shape edge.
Cary Clark8032b982017-07-28 11:04:54 -04001989
1990As Stroke_Width gets smaller, the drawn path frame is thinner. Stroke_Width less than one
1991may have gaps, and if kAntiAlias_Flag is set, Color_Alpha will increase to visually decrease coverage.
1992#Subtopic ##
1993
1994#Subtopic Hairline
1995#Alias Hairline # maybe should be Stroke_Hairline ?
1996
1997Stroke_Width of zero has a special meaning and switches drawing to use Hairline.
1998Hairline draws the thinnest continuous frame. If kAntiAlias_Flag is clear, adjacent pixels
1999flow horizontally, vertically,or diagonally.
2000
Cary Clarkce101242017-09-01 15:51:02 -04002001#ToDo what is the description of Anti-aliased hairlines? ##
Cary Clark8032b982017-07-28 11:04:54 -04002002
2003Path drawing with Hairline may hit the same pixel more than once. For instance, Path containing
2004two lines in one Path_Contour will draw the corner point once, but may both lines may draw the adjacent
2005pixel. If kAntiAlias_Flag is set, transparency is applied twice, resulting in a darker pixel. Some
2006GPU-backed implementations apply transparency at a later drawing stage, avoiding double hit pixels
2007while stroking.
2008
2009#Subtopic ##
2010
2011#Enum Style
2012
2013#Code
2014 enum Style {
2015 kFill_Style,
2016 kStroke_Style,
2017 kStrokeAndFill_Style,
2018 };
2019##
2020
2021Set Style to fill, stroke, or both fill and stroke geometry.
2022The stroke and fill
2023share all paint attributes; for instance, they are drawn with the same color.
2024
2025Use kStrokeAndFill_Style to avoid hitting the same pixels twice with a stroke draw and
2026a fill draw.
2027
2028#Const kFill_Style 0
2029 Set to fill geometry.
Cary Clarkce101242017-09-01 15:51:02 -04002030 Applies to Rect, Region, Round_Rect, Circles, Ovals, Path, and Text.
2031 Bitmap, Image, Patches, Region, Sprites, and Vertices are painted as if
Cary Clark8032b982017-07-28 11:04:54 -04002032 kFill_Style is set, and ignore the set Style.
2033 The Path_Fill_Type specifies additional rules to fill the area outside the path edge,
2034 and to create an unfilled hole inside the shape.
2035 Style is set to kFill_Style by default.
2036##
2037
2038#Const kStroke_Style 1
2039 Set to stroke geometry.
Cary Clarkce101242017-09-01 15:51:02 -04002040 Applies to Rect, Region, Round_Rect, Arcs, Circles, Ovals, Path, and Text.
2041 Arcs, Lines, and Points, are always drawn as if kStroke_Style is set,
Cary Clark8032b982017-07-28 11:04:54 -04002042 and ignore the set Style.
2043 The stroke construction is unaffected by the Path_Fill_Type.
2044##
2045
2046#Const kStrokeAndFill_Style 2
2047 Set to stroke and fill geometry.
Cary Clarkce101242017-09-01 15:51:02 -04002048 Applies to Rect, Region, Round_Rect, Circles, Ovals, Path, and Text.
Cary Clark8032b982017-07-28 11:04:54 -04002049 Path is treated as if it is set to SkPath::kWinding_FillType,
2050 and the set Path_Fill_Type is ignored.
2051##
2052
2053#Enum ##
2054
2055#Enum
2056
2057#Code
2058 enum {
Cary Clarkbad5ad72017-08-03 17:14:08 -04002059 kStyleCount = kStrokeAndFill_Style + 1,
Cary Clark8032b982017-07-28 11:04:54 -04002060 };
2061##
2062
2063#Const kStyleCount 3
2064The number of different Style values defined.
2065May be used to verify that Style is a legal value.
2066##
2067
2068#Enum ##
2069
2070#Method Style getStyle() const
2071
2072 Whether the geometry is filled, stroked, or filled and stroked.
2073
2074 #Return one of:kFill_Style, kStroke_Style, kStrokeAndFill_Style ##
2075
2076 #Example
2077 SkPaint paint;
2078 SkDebugf("SkPaint::kFill_Style %c= paint.getStyle()\n",
2079 SkPaint::kFill_Style == paint.getStyle() ? '=' : '!');
2080
2081 #StdOut
2082 SkPaint::kFill_Style == paint.getStyle()
2083 ##
2084 ##
2085
2086#SeeAlso Style setStyle
2087##
2088
2089#Method void setStyle(Style style)
2090
2091 Sets whether the geometry is filled, stroked, or filled and stroked.
2092 Has no effect if style is not a legal Style value.
2093
2094 #Param style one of: kFill_Style, kStroke_Style, kStrokeAndFill_Style
2095 ##
2096
2097 #Example
2098 void draw(SkCanvas* canvas) {
2099 SkPaint paint;
2100 paint.setStrokeWidth(5);
2101 SkRegion region;
2102 region.op(140, 10, 160, 30, SkRegion::kUnion_Op);
2103 region.op(170, 40, 190, 60, SkRegion::kUnion_Op);
2104 SkBitmap bitmap;
2105 bitmap.setInfo(SkImageInfo::MakeA8(50, 50), 50);
2106 uint8_t pixels[50][50];
2107 for (int x = 0; x < 50; ++x) {
2108 for (int y = 0; y < 50; ++y) {
2109 pixels[y][x] = (x + y) % 5 ? 0xFF : 0x00;
2110 }
2111 }
2112 bitmap.setPixels(pixels);
2113 for (auto style : { SkPaint::kFill_Style,
2114 SkPaint::kStroke_Style,
2115 SkPaint::kStrokeAndFill_Style }) {
2116 paint.setStyle(style);
2117 canvas->drawLine(10, 10, 60, 60, paint);
2118 canvas->drawRect({80, 10, 130, 60}, paint);
2119 canvas->drawRegion(region, paint);
2120 canvas->drawBitmap(bitmap, 200, 10, &paint);
2121 canvas->translate(0, 80);
2122 }
2123 }
2124 ##
2125
2126#SeeAlso Style getStyle
2127##
2128
2129#SeeAlso Path_Fill_Type Path_Effect Style_Fill Style_Stroke
2130#Topic Style ##
2131
2132# ------------------------------------------------------------------------------
2133#Topic Stroke_Width
2134
2135Stroke_Width sets the width for stroking. The width is the thickness
Cary Clarkbc5697d2017-10-04 14:31:33 -04002136of the stroke perpendicular to the path direction when the paint style is
Cary Clark8032b982017-07-28 11:04:54 -04002137set to kStroke_Style or kStrokeAndFill_Style.
2138
2139When width is greater than zero, the stroke encompasses as many pixels partially
2140or fully as needed. When the width equals zero, the paint enables hairlines;
2141the stroke is always one pixel wide.
2142
Cary Clarkbc5697d2017-10-04 14:31:33 -04002143The stroke dimensions are scaled by the canvas matrix, but Hairline stroke
Cary Clark8032b982017-07-28 11:04:54 -04002144remains one pixel wide regardless of scaling.
2145
2146The default width for the paint is zero.
2147
2148#Example
2149#Height 170
2150 #Platform raster gpu
2151 #Description
2152 The pixels hit to represent thin lines vary with the angle of the
Cary Clarkbc5697d2017-10-04 14:31:33 -04002153 line and the platform implementation.
Cary Clark8032b982017-07-28 11:04:54 -04002154 ##
2155 void draw(SkCanvas* canvas) {
2156 SkPaint paint;
2157 for (bool antialias : { false, true }) {
2158 paint.setAntiAlias(antialias);
2159 for (int width = 0; width <= 4; ++width) {
2160 SkScalar offset = antialias * 100 + width * 20;
2161 paint.setStrokeWidth(width * 0.25f);
2162 canvas->drawLine(10 + offset, 10, 20 + offset, 60, paint);
2163 canvas->drawLine(10 + offset, 110, 60 + offset, 160, paint);
2164 }
2165 }
2166 }
2167##
2168
2169#Method SkScalar getStrokeWidth() const
2170
2171 Returns the thickness of the pen used by Paint to
2172 outline the shape.
2173
2174 #Return zero for Hairline, greater than zero for pen thickness ##
2175
2176 #Example
2177 SkPaint paint;
2178 SkDebugf("0 %c= paint.getStrokeWidth()\n", 0 == paint.getStrokeWidth() ? '=' : '!');
2179
2180 #StdOut
2181 0 == paint.getStrokeWidth()
2182 ##
2183 ##
2184
2185##
2186
2187#Method void setStrokeWidth(SkScalar width)
2188
2189 Sets the thickness of the pen used by the paint to
2190 outline the shape.
2191 Has no effect if width is less than zero.
2192
2193 #Param width zero thickness for Hairline; greater than zero for pen thickness
2194 ##
2195
2196 #Example
2197 SkPaint paint;
2198 paint.setStrokeWidth(5);
2199 paint.setStrokeWidth(-1);
2200 SkDebugf("5 %c= paint.getStrokeWidth()\n", 5 == paint.getStrokeWidth() ? '=' : '!');
2201
2202 #StdOut
2203 5 == paint.getStrokeWidth()
2204 ##
2205 ##
2206
2207##
2208
2209#Topic ##
2210# ------------------------------------------------------------------------------
2211#Topic Miter_Limit
2212
2213Miter_Limit specifies the maximum miter length,
2214relative to the stroke width.
2215
2216Miter_Limit is used when the Stroke_Join
2217is set to kMiter_Join, and the Style is either kStroke_Style
2218or kStrokeAndFill_Style.
2219
2220If the miter at a corner exceeds this limit, kMiter_Join
2221is replaced with kBevel_Join.
2222
2223Miter_Limit can be computed from the corner angle:
2224
2225#Formula
2226 miter limit = 1 / sin ( angle / 2 )
2227#Formula ##
2228
2229Miter_Limit default value is 4.
2230The default may be changed at compile time by setting SkPaintDefaults_MiterLimit
Cary Clarkce101242017-09-01 15:51:02 -04002231in "SkUserConfig.h" or as a define supplied by the build environment.
Cary Clark8032b982017-07-28 11:04:54 -04002232
2233Here are some miter limits and the angles that triggers them.
2234#Table
2235#Legend
2236 # miter limit # angle in degrees ##
2237#Legend ##
2238 # 10 # 11.48 ##
2239 # 9 # 12.76 ##
2240 # 8 # 14.36 ##
2241 # 7 # 16.43 ##
2242 # 6 # 19.19 ##
2243 # 5 # 23.07 ##
2244 # 4 # 28.96 ##
2245 # 3 # 38.94 ##
2246 # 2 # 60 ##
2247 # 1 # 180 ##
2248#Table ##
2249
2250#Example
2251 #Height 170
2252 #Width 384
2253 #Description
2254 This example draws a stroked corner and the miter length beneath.
2255 When the miter limit is decreased slightly, the miter join is replaced
2256 by a bevel join.
2257 ##
2258 void draw(SkCanvas* canvas) {
2259 SkPoint pts[] = {{ 10, 50 }, { 110, 80 }, { 10, 110 }};
2260 SkVector v[] = { pts[0] - pts[1], pts[2] - pts[1] };
2261 SkScalar angle1 = SkScalarATan2(v[0].fY, v[0].fX);
2262 SkScalar angle2 = SkScalarATan2(v[1].fY, v[1].fX);
2263 const SkScalar strokeWidth = 20;
2264 SkScalar miterLimit = 1 / SkScalarSin((angle2 - angle1) / 2);
2265 SkScalar miterLength = strokeWidth * miterLimit;
2266 SkPath path;
2267 path.moveTo(pts[0]);
2268 path.lineTo(pts[1]);
2269 path.lineTo(pts[2]);
2270 SkPaint paint; // set to default kMiter_Join
2271 paint.setAntiAlias(true);
2272 paint.setStyle(SkPaint::kStroke_Style);
2273 paint.setStrokeMiter(miterLimit);
2274 paint.setStrokeWidth(strokeWidth);
2275 canvas->drawPath(path, paint);
2276 paint.setStrokeWidth(1);
2277 canvas->drawLine(pts[1].fX - miterLength / 2, pts[1].fY + 50,
2278 pts[1].fX + miterLength / 2, pts[1].fY + 50, paint);
2279 canvas->translate(200, 0);
2280 miterLimit *= 0.99f;
2281 paint.setStrokeMiter(miterLimit);
2282 paint.setStrokeWidth(strokeWidth);
2283 canvas->drawPath(path, paint);
2284 paint.setStrokeWidth(1);
2285 canvas->drawLine(pts[1].fX - miterLength / 2, pts[1].fY + 50,
2286 pts[1].fX + miterLength / 2, pts[1].fY + 50, paint);
2287 }
2288##
2289
2290#Method SkScalar getStrokeMiter() const
2291
2292 The limit at which a sharp corner is drawn beveled.
2293
2294 #Return zero and greater Miter_Limit ##
2295
2296 #Example
2297 SkPaint paint;
2298 SkDebugf("default miter limit == %g\n", paint.getStrokeMiter());
2299
2300 #StdOut
2301 default miter limit == 4
2302 ##
2303 ##
2304
2305 #SeeAlso Miter_Limit setStrokeMiter Join
2306
2307##
2308
2309#Method void setStrokeMiter(SkScalar miter)
2310
2311 The limit at which a sharp corner is drawn beveled.
2312 Valid values are zero and greater.
2313 Has no effect if miter is less than zero.
2314
2315 #Param miter zero and greater Miter_Limit
2316 ##
2317
2318 #Example
2319 SkPaint paint;
2320 paint.setStrokeMiter(8);
2321 paint.setStrokeMiter(-1);
2322 SkDebugf("default miter limit == %g\n", paint.getStrokeMiter());
2323
2324 #StdOut
2325 default miter limit == 8
2326 ##
2327 ##
2328
2329 #SeeAlso Miter_Limit getStrokeMiter Join
2330
2331##
2332
2333#Topic ##
2334# ------------------------------------------------------------------------------
2335#Topic Stroke_Cap
2336
2337#Enum Cap
2338
2339#Code
2340 enum Cap {
2341 kButt_Cap,
2342 kRound_Cap,
2343 kSquare_Cap,
2344
2345 kLast_Cap = kSquare_Cap,
Cary Clarkbad5ad72017-08-03 17:14:08 -04002346 kDefault_Cap = kButt_Cap,
Cary Clark8032b982017-07-28 11:04:54 -04002347 };
Cary Clark6fc50412017-09-21 12:31:06 -04002348
Cary Clark8032b982017-07-28 11:04:54 -04002349 static constexpr int kCapCount = kLast_Cap + 1;
2350##
2351
2352Stroke_Cap draws at the beginning and end of an open Path_Contour.
2353
2354 #Const kButt_Cap 0
2355 Does not extend the stroke past the beginning or the end.
2356 ##
2357 #Const kRound_Cap 1
2358 Adds a circle with a diameter equal to Stroke_Width at the beginning
2359 and end.
2360 ##
2361 #Const kSquare_Cap 2
2362 Adds a square with sides equal to Stroke_Width at the beginning
2363 and end. The square sides are parallel to the initial and final direction
2364 of the stroke.
2365 ##
2366 #Const kLast_Cap 2
2367 Equivalent to the largest value for Stroke_Cap.
2368 ##
2369 #Const kDefault_Cap 0
2370 Equivalent to kButt_Cap.
2371 Stroke_Cap is set to kButt_Cap by default.
2372 ##
2373
2374 #Const kCapCount 3
2375 The number of different Stroke_Cap values defined.
2376 May be used to verify that Stroke_Cap is a legal value.
2377 ##
2378#Enum ##
2379
2380Stroke describes the area covered by a pen of Stroke_Width as it
Cary Clarkbc5697d2017-10-04 14:31:33 -04002381follows the Path_Contour, moving parallel to the contour direction.
Cary Clark8032b982017-07-28 11:04:54 -04002382
2383If the Path_Contour is not terminated by SkPath::kClose_Verb, the contour has a
2384visible beginning and end.
2385
2386Path_Contour may start and end at the same point; defining Zero_Length_Contour.
2387
2388kButt_Cap and Zero_Length_Contour is not drawn.
2389kRound_Cap and Zero_Length_Contour draws a circle of diameter Stroke_Width
2390at the contour point.
2391kSquare_Cap and Zero_Length_Contour draws an upright square with a side of
2392Stroke_Width at the contour point.
2393
2394Stroke_Cap is kButt_Cap by default.
2395
2396#Example
Cary Clark2ade9972017-11-02 17:49:34 -04002397#Height 200
Cary Clark8032b982017-07-28 11:04:54 -04002398 SkPaint paint;
2399 paint.setStyle(SkPaint::kStroke_Style);
2400 paint.setStrokeWidth(20);
2401 SkPath path;
2402 path.moveTo(30, 30);
2403 path.lineTo(30, 30);
2404 path.moveTo(70, 30);
2405 path.lineTo(90, 40);
2406 for (SkPaint::Cap c : { SkPaint::kButt_Cap, SkPaint::kRound_Cap, SkPaint::kSquare_Cap } ) {
2407 paint.setStrokeCap(c);
2408 canvas->drawPath(path, paint);
2409 canvas->translate(0, 70);
2410 }
2411##
2412
2413#Method Cap getStrokeCap() const
2414
2415 The geometry drawn at the beginning and end of strokes.
2416
2417 #Return one of: kButt_Cap, kRound_Cap, kSquare_Cap ##
2418
2419 #Example
2420 SkPaint paint;
2421 SkDebugf("kButt_Cap %c= default stroke cap\n",
2422 SkPaint::kButt_Cap == paint.getStrokeCap() ? '=' : '!');
2423
2424 #StdOut
2425 kButt_Cap == default stroke cap
2426 ##
2427 ##
2428
2429 #SeeAlso Stroke_Cap setStrokeCap
2430##
2431
2432#Method void setStrokeCap(Cap cap)
2433
2434 The geometry drawn at the beginning and end of strokes.
2435
2436 #Param cap one of: kButt_Cap, kRound_Cap, kSquare_Cap;
2437 has no effect if cap is not valid
2438 ##
2439
2440 #Example
2441 SkPaint paint;
2442 paint.setStrokeCap(SkPaint::kRound_Cap);
2443 paint.setStrokeCap((SkPaint::Cap) SkPaint::kCapCount);
2444 SkDebugf("kRound_Cap %c= paint.getStrokeCap()\n",
2445 SkPaint::kRound_Cap == paint.getStrokeCap() ? '=' : '!');
2446
2447 #StdOut
2448 kRound_Cap == paint.getStrokeCap()
2449 ##
2450 ##
2451
2452 #SeeAlso Stroke_Cap getStrokeCap
2453##
2454
2455#Topic ##
2456# ------------------------------------------------------------------------------
2457#Topic Stroke_Join
2458
2459Stroke_Join draws at the sharp corners of an open or closed Path_Contour.
2460
2461Stroke describes the area covered by a pen of Stroke_Width as it
Cary Clarkbc5697d2017-10-04 14:31:33 -04002462follows the Path_Contour, moving parallel to the contour direction.
Cary Clark8032b982017-07-28 11:04:54 -04002463
2464If the contour direction changes abruptly, because the tangent direction leading
2465to the end of a curve within the contour does not match the tangent direction of
2466the following curve, the pair of curves meet at Stroke_Join.
2467
2468#Example
Cary Clark2ade9972017-11-02 17:49:34 -04002469#Height 200
Cary Clarka560c472017-11-27 10:44:06 -05002470 SkPaint paint;
2471 paint.setStyle(SkPaint::kStroke_Style);
2472 paint.setStrokeWidth(20);
2473 SkPath path;
2474 path.moveTo(30, 20);
2475 path.lineTo(40, 40);
2476 path.conicTo(70, 20, 100, 20, .707f);
2477 for (SkPaint::Join j : { SkPaint::kMiter_Join, SkPaint::kRound_Join, SkPaint::kBevel_Join } ) {
2478 paint.setStrokeJoin(j);
2479 canvas->drawPath(path, paint);
2480 canvas->translate(0, 70);
2481 }
Cary Clark8032b982017-07-28 11:04:54 -04002482##
2483
2484#Enum Join
2485#Code
2486 enum Join {
2487 kMiter_Join,
2488 kRound_Join,
2489 kBevel_Join,
2490
2491 kLast_Join = kBevel_Join,
Cary Clarkbad5ad72017-08-03 17:14:08 -04002492 kDefault_Join = kMiter_Join,
Cary Clark8032b982017-07-28 11:04:54 -04002493 };
Cary Clark6fc50412017-09-21 12:31:06 -04002494
Cary Clark8032b982017-07-28 11:04:54 -04002495 static constexpr int kJoinCount = kLast_Join + 1;
2496##
2497
Cary Clark1eace2d2017-07-31 07:52:43 -04002498Join specifies how corners are drawn when a shape is stroked. Join
Cary Clark8032b982017-07-28 11:04:54 -04002499affects the four corners of a stroked rectangle, and the connected segments in a
2500stroked path.
2501
2502Choose miter join to draw sharp corners. Choose round join to draw a circle with a
2503radius equal to the stroke width on top of the corner. Choose bevel join to minimally
2504connect the thick strokes.
2505
2506The fill path constructed to describe the stroked path respects the join setting but may
2507not contain the actual join. For instance, a fill path constructed with round joins does
2508not necessarily include circles at each connected segment.
2509
2510#Const kMiter_Join 0
2511 Extends the outside corner to the extent allowed by Miter_Limit.
2512 If the extension exceeds Miter_Limit, kBevel_Join is used instead.
2513##
2514
2515#Const kRound_Join 1
2516 Adds a circle with a diameter of Stroke_Width at the sharp corner.
2517##
2518
2519#Const kBevel_Join 2
2520 Connects the outside edges of the sharp corner.
2521##
2522
2523#Const kLast_Join 2
2524 Equivalent to the largest value for Stroke_Join.
2525##
2526
2527#Const kDefault_Join 1
2528 Equivalent to kMiter_Join.
2529 Stroke_Join is set to kMiter_Join by default.
2530##
2531
2532#Const kJoinCount 3
2533 The number of different Stroke_Join values defined.
2534 May be used to verify that Stroke_Join is a legal value.
2535##
2536
2537#Example
2538#Width 462
2539void draw(SkCanvas* canvas) {
2540 SkPath path;
2541 path.moveTo(10, 50);
2542 path.quadTo(35, 110, 60, 210);
2543 path.quadTo(105, 110, 130, 10);
2544 SkPaint paint; // set to default kMiter_Join
2545 paint.setAntiAlias(true);
2546 paint.setStyle(SkPaint::kStroke_Style);
2547 paint.setStrokeWidth(20);
2548 canvas->drawPath(path, paint);
2549 canvas->translate(150, 0);
2550 paint.setStrokeJoin(SkPaint::kBevel_Join);
2551 canvas->drawPath(path, paint);
2552 canvas->translate(150, 0);
2553 paint.setStrokeJoin(SkPaint::kRound_Join);
2554 canvas->drawPath(path, paint);
2555}
2556##
2557
2558#SeeAlso setStrokeJoin getStrokeJoin setStrokeMiter getStrokeMiter
2559
2560#Enum ##
2561
2562#Method Join getStrokeJoin() const
2563
Cary Clark0c5f5462017-12-15 11:21:51 -05002564 The geometry drawn at the corners of strokes.
Cary Clark8032b982017-07-28 11:04:54 -04002565
2566 #Return one of: kMiter_Join, kRound_Join, kBevel_Join ##
2567
2568 #Example
2569 SkPaint paint;
2570 SkDebugf("kMiter_Join %c= default stroke join\n",
2571 SkPaint::kMiter_Join == paint.getStrokeJoin() ? '=' : '!');
2572
2573 #StdOut
2574 kMiter_Join == default stroke join
2575 ##
2576 ##
2577
2578 #SeeAlso Stroke_Join setStrokeJoin
2579##
2580
2581#Method void setStrokeJoin(Join join)
2582
Cary Clark0c5f5462017-12-15 11:21:51 -05002583 The geometry drawn at the corners of strokes.
Cary Clark8032b982017-07-28 11:04:54 -04002584
2585 #Param join one of: kMiter_Join, kRound_Join, kBevel_Join;
Cary Clark579985c2017-07-31 11:48:27 -04002586 otherwise, has no effect
Cary Clark8032b982017-07-28 11:04:54 -04002587 ##
2588
2589 #Example
2590 SkPaint paint;
2591 paint.setStrokeJoin(SkPaint::kMiter_Join);
2592 paint.setStrokeJoin((SkPaint::Join) SkPaint::kJoinCount);
2593 SkDebugf("kMiter_Join %c= paint.getStrokeJoin()\n",
2594 SkPaint::kMiter_Join == paint.getStrokeJoin() ? '=' : '!');
2595
2596 #StdOut
2597 kMiter_Join == paint.getStrokeJoin()
2598 ##
2599 ##
2600
2601 #SeeAlso Stroke_Join getStrokeJoin
2602##
2603
2604#SeeAlso Miter_Limit
2605
2606#Topic Stroke_Join ##
2607# ------------------------------------------------------------------------------
2608#Topic Fill_Path
2609
2610Fill_Path creates a Path by applying the Path_Effect, followed by the Style_Stroke.
2611
2612If Paint contains Path_Effect, Path_Effect operates on the source Path; the result
2613replaces the destination Path. Otherwise, the source Path is replaces the
2614destination Path.
2615
2616Fill Path can request the Path_Effect to restrict to a culling rectangle, but
2617the Path_Effect is not required to do so.
2618
2619If Style is kStroke_Style or kStrokeAndFill_Style,
2620and Stroke_Width is greater than zero, the Stroke_Width, Stroke_Cap, Stroke_Join,
2621and Miter_Limit operate on the destination Path, replacing it.
2622
2623Fill Path can specify the precision used by Stroke_Width to approximate the stroke geometry.
2624
2625If the Style is kStroke_Style and the Stroke_Width is zero, getFillPath
2626returns false since Hairline has no filled equivalent.
2627
2628#Method bool getFillPath(const SkPath& src, SkPath* dst, const SkRect* cullRect,
2629 SkScalar resScale = 1) const
2630
2631 The filled equivalent of the stroked path.
2632
2633 #Param src Path read to create a filled version ##
2634 #Param dst resulting Path; may be the same as src, but may not be nullptr ##
2635 #Param cullRect optional limit passed to Path_Effect ##
2636 #Param resScale if > 1, increase precision, else if (0 < res < 1) reduce precision
2637 to favor speed and size
2638 ##
2639 #Return true if the path represents Style_Fill, or false if it represents Hairline ##
2640
2641 #Example
2642 #Height 192
2643 #Description
Cary Clarkce101242017-09-01 15:51:02 -04002644 A very small Quad stroke is turned into a filled path with increasing levels of precision.
2645 At the lowest precision, the Quad stroke is approximated by a rectangle.
Cary Clark8032b982017-07-28 11:04:54 -04002646 At the highest precision, the filled path has high fidelity compared to the original stroke.
2647 ##
2648 void draw(SkCanvas* canvas) {
2649 SkPaint strokePaint;
2650 strokePaint.setAntiAlias(true);
2651 strokePaint.setStyle(SkPaint::kStroke_Style);
2652 strokePaint.setStrokeWidth(.1f);
2653 SkPath strokePath;
2654 strokePath.moveTo(.08f, .08f);
2655 strokePath.quadTo(.09f, .08f, .17f, .17f);
2656 SkPath fillPath;
2657 SkPaint outlinePaint(strokePaint);
2658 outlinePaint.setStrokeWidth(2);
2659 SkMatrix scale = SkMatrix::MakeScale(300, 300);
2660 for (SkScalar precision : { 0.01f, .1f, 1.f, 10.f, 100.f } ) {
2661 strokePaint.getFillPath(strokePath, &fillPath, nullptr, precision);
2662 fillPath.transform(scale);
2663 canvas->drawPath(fillPath, outlinePaint);
2664 canvas->translate(60, 0);
2665 if (1.f == precision) canvas->translate(-180, 100);
2666 }
2667 strokePath.transform(scale);
2668 strokePaint.setStrokeWidth(30);
2669 canvas->drawPath(strokePath, strokePaint);
2670 }
2671 ##
2672
2673##
2674
2675#Method bool getFillPath(const SkPath& src, SkPath* dst) const
2676
2677 The filled equivalent of the stroked path.
2678
2679 Replaces dst with the src path modified by Path_Effect and Style_Stroke.
2680 Path_Effect, if any, is not culled. Stroke_Width is created with default precision.
2681
2682 #Param src Path read to create a filled version ##
2683 #Param dst resulting Path dst may be the same as src, but may not be nullptr ##
2684 #Return true if the path represents Style_Fill, or false if it represents Hairline ##
2685
2686 #Example
2687 #Height 128
2688 void draw(SkCanvas* canvas) {
2689 SkPaint paint;
2690 paint.setStyle(SkPaint::kStroke_Style);
2691 paint.setStrokeWidth(10);
2692 SkPath strokePath;
2693 strokePath.moveTo(20, 20);
2694 strokePath.lineTo(100, 100);
2695 canvas->drawPath(strokePath, paint);
2696 SkPath fillPath;
2697 paint.getFillPath(strokePath, &fillPath);
2698 paint.setStrokeWidth(2);
2699 canvas->translate(40, 0);
2700 canvas->drawPath(fillPath, paint);
2701 }
2702 ##
2703
2704##
2705
2706#SeeAlso Style_Stroke Stroke_Width Path_Effect
2707
2708#Topic ##
2709# ------------------------------------------------------------------------------
2710#Topic Shader_Methods
2711
2712Shader defines the colors used when drawing a shape.
2713Shader may be an image, a gradient, or a computed fill.
2714If Paint has no Shader, then Color fills the shape.
2715
2716Shader is modulated by Color_Alpha component of Color.
2717If Shader object defines only Color_Alpha, then Color modulated by Color_Alpha describes
2718the fill.
2719
2720The drawn transparency can be modified without altering Shader, by changing Color_Alpha.
2721
2722#Example
2723void draw(SkCanvas* canvas) {
2724 SkPaint paint;
2725 SkPoint center = { 50, 50 };
2726 SkScalar radius = 50;
2727 const SkColor colors[] = { 0xFFFFFFFF, 0xFF000000 };
2728 paint.setShader(SkGradientShader::MakeRadial(center, radius, colors,
2729 nullptr, SK_ARRAY_COUNT(colors), SkShader::kClamp_TileMode));
2730 for (SkScalar a : { 0.3f, 0.6f, 1.0f } ) {
2731 paint.setAlpha((int) (a * 255));
2732 canvas->drawCircle(center.fX, center.fY, radius, paint);
2733 canvas->translate(70, 70);
2734 }
2735}
2736##
2737
2738If Shader generates only Color_Alpha then all components of Color modulate the output.
2739
2740#Example
2741void draw(SkCanvas* canvas) {
2742 SkPaint paint;
2743 SkBitmap bitmap;
2744 bitmap.setInfo(SkImageInfo::MakeA8(5, 1), 5); // bitmap only contains alpha
2745 uint8_t pixels[5] = { 0x22, 0x55, 0x88, 0xBB, 0xFF };
2746 bitmap.setPixels(pixels);
2747 paint.setShader(SkShader::MakeBitmapShader(bitmap,
2748 SkShader::kMirror_TileMode, SkShader::kMirror_TileMode));
2749 for (SkColor c : { SK_ColorRED, SK_ColorBLUE, SK_ColorGREEN } ) {
2750 paint.setColor(c); // all components in color affect shader
2751 canvas->drawCircle(50, 50, 50, paint);
2752 canvas->translate(70, 70);
2753 }
2754}
2755##
2756
2757#Method SkShader* getShader() const
2758
2759 Optional colors used when filling a path, such as a gradient.
2760
2761 Does not alter Shader Reference_Count.
2762
2763 #Return Shader if previously set, nullptr otherwise ##
2764
2765 #Example
2766 void draw(SkCanvas* canvas) {
2767 SkPaint paint;
2768 SkDebugf("nullptr %c= shader\n", paint.getShader() ? '!' : '=');
2769 paint.setShader(SkShader::MakeEmptyShader());
2770 SkDebugf("nullptr %c= shader\n", paint.getShader() ? '!' : '=');
2771 }
2772
2773 #StdOut
2774 nullptr == shader
2775 nullptr != shader
2776 ##
2777 ##
2778
2779##
2780
2781#Method sk_sp<SkShader> refShader() const
2782
2783 Optional colors used when filling a path, such as a gradient.
2784
2785 Increases Shader Reference_Count by one.
2786
2787 #Return Shader if previously set, nullptr otherwise ##
2788
2789 #Example
2790 void draw(SkCanvas* canvas) {
2791 SkPaint paint1, paint2;
2792 paint1.setShader(SkShader::MakeEmptyShader());
2793 SkDebugf("shader unique: %s\n", paint1.getShader()->unique() ? "true" : "false");
2794 paint2.setShader(paint1.refShader());
2795 SkDebugf("shader unique: %s\n", paint1.getShader()->unique() ? "true" : "false");
2796 }
2797
2798 #StdOut
2799 shader unique: true
2800 shader unique: false
2801 ##
2802 ##
2803
2804##
2805
2806#Method void setShader(sk_sp<SkShader> shader)
2807
2808 Optional colors used when filling a path, such as a gradient.
2809
Cary Clarkd0530ba2017-09-14 11:25:39 -04002810 Sets Shader to shader, decreasing Reference_Count of the previous Shader.
Cary Clark6fc50412017-09-21 12:31:06 -04002811 Increments shader Reference_Count by one.
Cary Clark8032b982017-07-28 11:04:54 -04002812
2813 #Param shader how geometry is filled with color; if nullptr, Color is used instead ##
2814
2815 #Example
2816 #Height 64
2817 void draw(SkCanvas* canvas) {
2818 SkPaint paint;
2819 paint.setColor(SK_ColorBLUE);
2820 paint.setShader(SkShader::MakeColorShader(SK_ColorRED));
2821 canvas->drawRect(SkRect::MakeWH(40, 40), paint);
2822 paint.setShader(nullptr);
2823 canvas->translate(50, 0);
2824 canvas->drawRect(SkRect::MakeWH(40, 40), paint);
2825 }
2826 ##
2827
2828##
2829
2830#Topic ##
2831# ------------------------------------------------------------------------------
2832#Topic Color_Filter_Methods
2833
2834Color_Filter alters the color used when drawing a shape.
2835Color_Filter may apply Blend_Mode, transform the color through a matrix, or composite multiple filters.
2836If Paint has no Color_Filter, the color is unaltered.
2837
2838The drawn transparency can be modified without altering Color_Filter, by changing Color_Alpha.
2839
2840#Example
2841#Height 128
2842void draw(SkCanvas* canvas) {
2843 SkPaint paint;
2844 paint.setColorFilter(SkColorMatrixFilter::MakeLightingFilter(0xFFFFFF, 0xFF0000));
2845 for (SkColor c : { SK_ColorBLACK, SK_ColorGREEN } ) {
2846 paint.setColor(c);
2847 canvas->drawRect(SkRect::MakeXYWH(10, 10, 50, 50), paint);
2848 paint.setAlpha(0x80);
2849 canvas->drawRect(SkRect::MakeXYWH(60, 60, 50, 50), paint);
2850 canvas->translate(100, 0);
2851 }
2852}
2853##
2854
2855#Method SkColorFilter* getColorFilter() const
2856
2857 Returns Color_Filter if set, or nullptr.
2858 Does not alter Color_Filter Reference_Count.
2859
2860 #Return Color_Filter if previously set, nullptr otherwise ##
2861
2862 #Example
2863 void draw(SkCanvas* canvas) {
2864 SkPaint paint;
2865 SkDebugf("nullptr %c= color filter\n", paint.getColorFilter() ? '!' : '=');
2866 paint.setColorFilter(SkColorFilter::MakeModeFilter(SK_ColorLTGRAY, SkBlendMode::kSrcIn));
2867 SkDebugf("nullptr %c= color filter\n", paint.getColorFilter() ? '!' : '=');
2868 }
2869
2870 #StdOut
2871 nullptr == color filter
2872 nullptr != color filter
2873 ##
2874 ##
2875##
2876
2877#Method sk_sp<SkColorFilter> refColorFilter() const
2878
2879 Returns Color_Filter if set, or nullptr.
2880 Increases Color_Filter Reference_Count by one.
2881
2882 #Return Color_Filter if set, or nullptr ##
2883
2884 #Example
2885 void draw(SkCanvas* canvas) {
2886 SkPaint paint1, paint2;
2887 paint1.setColorFilter(SkColorFilter::MakeModeFilter(0xFFFF0000, SkBlendMode::kSrcATop));
2888 SkDebugf("color filter unique: %s\n", paint1.getColorFilter()->unique() ? "true" : "false");
2889 paint2.setColorFilter(paint1.refColorFilter());
2890 SkDebugf("color filter unique: %s\n", paint1.getColorFilter()->unique() ? "true" : "false");
2891 }
2892
2893 #StdOut
2894 color filter unique: true
2895 color filter unique: false
2896 ##
2897 ##
2898##
2899
2900#Method void setColorFilter(sk_sp<SkColorFilter> colorFilter)
2901
Cary Clark6fc50412017-09-21 12:31:06 -04002902Sets Color_Filter to filter, decreasing Reference_Count of the previous
2903Color_Filter. Pass nullptr to clear Color_Filter.
2904
2905Increments filter Reference_Count by one.
Cary Clark8032b982017-07-28 11:04:54 -04002906
2907 #Param colorFilter Color_Filter to apply to subsequent draw ##
2908
2909 #Example
2910 #Height 64
2911 void draw(SkCanvas* canvas) {
2912 SkPaint paint;
2913 paint.setColorFilter(SkColorFilter::MakeModeFilter(SK_ColorLTGRAY, SkBlendMode::kSrcIn));
2914 canvas->drawRect(SkRect::MakeWH(50, 50), paint);
2915 paint.setColorFilter(nullptr);
2916 canvas->translate(70, 0);
2917 canvas->drawRect(SkRect::MakeWH(50, 50), paint);
2918 }
2919 ##
2920
2921##
2922
2923#Topic ##
2924# ------------------------------------------------------------------------------
2925#Topic Blend_Mode_Methods
2926
2927Blend_Mode describes how Color combines with the destination color.
2928The default setting, SkBlendMode::kSrcOver, draws the source color
2929over the destination color.
2930
2931#Example
2932void draw(SkCanvas* canvas) {
2933 SkPaint normal, blender;
2934 normal.setColor(0xFF58a889);
2935 blender.setColor(0xFF8958a8);
2936 canvas->clear(0);
2937 for (SkBlendMode m : { SkBlendMode::kSrcOver, SkBlendMode::kSrcIn, SkBlendMode::kSrcOut } ) {
2938 normal.setBlendMode(SkBlendMode::kSrcOver);
2939 canvas->drawOval(SkRect::MakeXYWH(30, 30, 30, 80), normal);
2940 blender.setBlendMode(m);
2941 canvas->drawOval(SkRect::MakeXYWH(10, 50, 80, 30), blender);
2942 canvas->translate(70, 70);
2943 }
2944}
2945##
2946
2947#SeeAlso Blend_Mode
2948
2949#Method SkBlendMode getBlendMode() const
2950
2951 Returns Blend_Mode.
Cary Clark579985c2017-07-31 11:48:27 -04002952 By default, returns SkBlendMode::kSrcOver.
Cary Clark8032b982017-07-28 11:04:54 -04002953
2954 #Return mode used to combine source color with destination color ##
2955
2956 #Example
2957 void draw(SkCanvas* canvas) {
2958 SkPaint paint;
2959 SkDebugf("kSrcOver %c= getBlendMode\n",
2960 SkBlendMode::kSrcOver == paint.getBlendMode() ? '=' : '!');
2961 paint.setBlendMode(SkBlendMode::kSrc);
2962 SkDebugf("kSrcOver %c= getBlendMode\n",
2963 SkBlendMode::kSrcOver == paint.getBlendMode() ? '=' : '!');
2964 }
2965
2966 #StdOut
2967 kSrcOver == getBlendMode
2968 kSrcOver != getBlendMode
2969 ##
2970 ##
2971
2972##
2973
2974#Method bool isSrcOver() const
2975
2976 Returns true if Blend_Mode is SkBlendMode::kSrcOver, the default.
2977
2978 #Return true if Blend_Mode is SkBlendMode::kSrcOver ##
2979
2980 #Example
2981 void draw(SkCanvas* canvas) {
2982 SkPaint paint;
2983 SkDebugf("isSrcOver %c= true\n", paint.isSrcOver() ? '=' : '!');
2984 paint.setBlendMode(SkBlendMode::kSrc);
2985 SkDebugf("isSrcOver %c= true\n", paint.isSrcOver() ? '=' : '!');
2986 }
2987
2988 #StdOut
2989 isSrcOver == true
2990 isSrcOver != true
2991 ##
2992 ##
2993
2994##
2995
2996#Method void setBlendMode(SkBlendMode mode)
2997
2998 Sets Blend_Mode to mode.
2999 Does not check for valid input.
3000
3001 #Param mode SkBlendMode used to combine source color and destination ##
3002
3003 #Example
3004 void draw(SkCanvas* canvas) {
3005 SkPaint paint;
3006 SkDebugf("isSrcOver %c= true\n", paint.isSrcOver() ? '=' : '!');
3007 paint.setBlendMode(SkBlendMode::kSrc);
3008 SkDebugf("isSrcOver %c= true\n", paint.isSrcOver() ? '=' : '!');
3009 }
3010
3011 #StdOut
3012 isSrcOver == true
3013 isSrcOver != true
3014 ##
3015 ##
3016
3017##
3018
3019#Topic ##
3020# ------------------------------------------------------------------------------
3021#Topic Path_Effect_Methods
3022
3023Path_Effect modifies the path geometry before drawing it.
3024Path_Effect may implement dashing, custom fill effects and custom stroke effects.
3025If Paint has no Path_Effect, the path geometry is unaltered when filled or stroked.
3026
3027#Example
3028#Height 160
3029 void draw(SkCanvas* canvas) {
3030 SkPaint paint;
3031 paint.setStyle(SkPaint::kStroke_Style);
3032 paint.setStrokeWidth(16);
3033 SkScalar intervals[] = {30, 10};
3034 paint.setPathEffect(SkDashPathEffect::Make(intervals, SK_ARRAY_COUNT(intervals), 1));
3035 canvas->drawRoundRect({20, 20, 120, 120}, 20, 20, paint);
3036 }
3037##
3038
3039#SeeAlso Path_Effect
3040
3041#Method SkPathEffect* getPathEffect() const
3042
3043 Returns Path_Effect if set, or nullptr.
3044 Does not alter Path_Effect Reference_Count.
3045
3046 #Return Path_Effect if previously set, nullptr otherwise ##
3047
3048 #Example
3049 void draw(SkCanvas* canvas) {
3050 SkPaint paint;
3051 SkDebugf("nullptr %c= path effect\n", paint.getPathEffect() ? '!' : '=');
3052 paint.setPathEffect(SkCornerPathEffect::Make(10));
3053 SkDebugf("nullptr %c= path effect\n", paint.getPathEffect() ? '!' : '=');
3054 }
3055
3056 #StdOut
3057 nullptr == path effect
3058 nullptr != path effect
3059 ##
3060 ##
3061
3062##
3063
3064
3065#Method sk_sp<SkPathEffect> refPathEffect() const
3066
3067 Returns Path_Effect if set, or nullptr.
3068 Increases Path_Effect Reference_Count by one.
3069
3070 #Return Path_Effect if previously set, nullptr otherwise ##
3071
3072 #Example
3073 void draw(SkCanvas* canvas) {
3074 SkPaint paint1, paint2;
Cary Clarka560c472017-11-27 10:44:06 -05003075 SkScalar intervals[] = {1, 2};
3076 paint1.setPathEffect(SkDashPathEffect::Make(intervals, SK_ARRAY_COUNT(intervals), 10));
Cary Clark8032b982017-07-28 11:04:54 -04003077 SkDebugf("path effect unique: %s\n", paint1.getPathEffect()->unique() ? "true" : "false");
3078 paint2.setPathEffect(paint1.refPathEffect());
3079 SkDebugf("path effect unique: %s\n", paint1.getPathEffect()->unique() ? "true" : "false");
3080 }
3081
3082 #StdOut
3083 path effect unique: true
3084 path effect unique: false
3085 ##
3086 ##
3087
3088##
3089
3090
3091#Method void setPathEffect(sk_sp<SkPathEffect> pathEffect)
3092
Cary Clark6fc50412017-09-21 12:31:06 -04003093Sets Path_Effect to pathEffect, decreasing Reference_Count of the previous
3094Path_Effect. Pass nullptr to leave the path geometry unaltered.
3095
3096Increments pathEffect Reference_Count by one.
Cary Clark8032b982017-07-28 11:04:54 -04003097
3098 #Param pathEffect replace Path with a modification when drawn ##
3099
3100 #Example
3101 void draw(SkCanvas* canvas) {
3102 SkPaint paint;
3103 paint.setPathEffect(SkDiscretePathEffect::Make(3, 5));
3104 canvas->drawRect(SkRect::MakeXYWH(40, 40, 175, 175), paint);
3105 }
3106 ##
3107
3108##
3109
3110#Topic ##
3111# ------------------------------------------------------------------------------
3112#Topic Mask_Filter_Methods
3113
Cary Clarkce101242017-09-01 15:51:02 -04003114Mask_Filter uses coverage of the shape drawn to create Mask_Alpha.
Cary Clark8032b982017-07-28 11:04:54 -04003115Mask_Filter operates at a lower level than Rasterizer; Mask_Filter takes a Mask,
3116and returns a Mask.
Cary Clark6fc50412017-09-21 12:31:06 -04003117
3118Mask_Filter may change the geometry and transparency of the shape, such as
3119creating a blur effect. Set Mask_Filter to nullptr to prevent Mask_Filter from
3120modifying the draw.
Cary Clark8032b982017-07-28 11:04:54 -04003121
3122#Example
3123 void draw(SkCanvas* canvas) {
3124 SkPaint paint;
3125 paint.setMaskFilter(SkBlurMaskFilter::Make(kSolid_SkBlurStyle, 3));
3126 canvas->drawRect(SkRect::MakeXYWH(40, 40, 175, 175), paint);
3127 }
3128##
3129
3130#Method SkMaskFilter* getMaskFilter() const
3131
3132 Returns Mask_Filter if set, or nullptr.
3133 Does not alter Mask_Filter Reference_Count.
3134
3135 #Return Mask_Filter if previously set, nullptr otherwise ##
3136
3137 #Example
3138 void draw(SkCanvas* canvas) {
3139 SkPaint paint;
3140 SkDebugf("nullptr %c= mask filter\n", paint.getMaskFilter() ? '!' : '=');
3141 paint.setMaskFilter(SkBlurMaskFilter::Make(kOuter_SkBlurStyle, 3));
3142 SkDebugf("nullptr %c= mask filter\n", paint.getMaskFilter() ? '!' : '=');
3143 }
3144
3145 #StdOut
3146 nullptr == mask filter
3147 nullptr != mask filter
3148 ##
3149 ##
3150
3151##
3152
3153#Method sk_sp<SkMaskFilter> refMaskFilter() const
3154
3155 Returns Mask_Filter if set, or nullptr.
Cary Clark6fc50412017-09-21 12:31:06 -04003156
Cary Clark8032b982017-07-28 11:04:54 -04003157 Increases Mask_Filter Reference_Count by one.
3158
3159 #Return Mask_Filter if previously set, nullptr otherwise ##
3160
3161 #Example
3162 void draw(SkCanvas* canvas) {
3163 SkPaint paint1, paint2;
3164 paint1.setMaskFilter(SkBlurMaskFilter::Make(kNormal_SkBlurStyle, 1));
3165 SkDebugf("mask filter unique: %s\n", paint1.getMaskFilter()->unique() ? "true" : "false");
3166 paint2.setMaskFilter(paint1.refMaskFilter());
3167 SkDebugf("mask filter unique: %s\n", paint1.getMaskFilter()->unique() ? "true" : "false");
3168 }
3169
3170 #StdOut
3171 mask filter unique: true
3172 mask filter unique: false
3173 ##
3174 ##
3175
3176##
3177
3178#Method void setMaskFilter(sk_sp<SkMaskFilter> maskFilter)
3179
Cary Clark6fc50412017-09-21 12:31:06 -04003180Sets Mask_Filter to maskFilter, decreasing Reference_Count of the previous
3181Mask_Filter. Pass nullptr to clear Mask_Filter and leave Mask_Filter effect on
3182Mask_Alpha unaltered.
3183
3184Does not affect Rasterizer.
3185Increments maskFilter Reference_Count by one.
Cary Clark8032b982017-07-28 11:04:54 -04003186
3187 #Param maskFilter modifies clipping mask generated from drawn geometry ##
3188
3189 #Example
3190 void draw(SkCanvas* canvas) {
3191 SkPaint paint;
3192 paint.setStyle(SkPaint::kStroke_Style);
3193 paint.setStrokeWidth(10);
3194 paint.setMaskFilter(SkBlurMaskFilter::Make(kNormal_SkBlurStyle, 10));
3195 canvas->drawRect(SkRect::MakeXYWH(40, 40, 175, 175), paint);
3196 }
3197 ##
3198
3199##
3200
3201#Topic ##
3202# ------------------------------------------------------------------------------
3203#Topic Typeface_Methods
3204
3205Typeface identifies the font used when drawing and measuring text.
3206Typeface may be specified by name, from a file, or from a data stream.
3207The default Typeface defers to the platform-specific default font
3208implementation.
3209
3210#Example
3211#Height 100
3212 void draw(SkCanvas* canvas) {
3213 SkPaint paint;
Ben Wagner700ff172017-11-08 15:37:22 -05003214 paint.setTypeface(SkTypeface::MakeFromName(nullptr, SkFontStyle()));
Cary Clark8032b982017-07-28 11:04:54 -04003215 paint.setAntiAlias(true);
3216 paint.setTextSize(36);
3217 canvas->drawString("A Big Hello!", 10, 40, paint);
3218 paint.setTypeface(nullptr);
3219 paint.setFakeBoldText(true);
3220 canvas->drawString("A Big Hello!", 10, 80, paint);
3221 }
3222##
3223
3224#Method SkTypeface* getTypeface() const
3225
3226 Returns Typeface if set, or nullptr.
Cary Clark6fc50412017-09-21 12:31:06 -04003227 Increments Typeface Reference_Count by one.
Cary Clark8032b982017-07-28 11:04:54 -04003228
3229 #Return Typeface if previously set, nullptr otherwise ##
3230
3231 #Example
3232 void draw(SkCanvas* canvas) {
3233 SkPaint paint;
3234 SkDebugf("nullptr %c= typeface\n", paint.getTypeface() ? '!' : '=');
Cary Clark71961fb2018-01-05 14:21:59 -05003235 paint.setTypeface(SkTypeface::MakeFromName("monospace", SkFontStyle()));
Cary Clark8032b982017-07-28 11:04:54 -04003236 SkDebugf("nullptr %c= typeface\n", paint.getTypeface() ? '!' : '=');
3237 }
3238
3239 #StdOut
3240 nullptr == typeface
3241 nullptr != typeface
3242 ##
3243 ##
3244
3245##
3246
3247#Method sk_sp<SkTypeface> refTypeface() const
3248
3249 Increases Typeface Reference_Count by one.
3250
3251 #Return Typeface if previously set, nullptr otherwise ##
3252
3253 #Example
3254 void draw(SkCanvas* canvas) {
3255 SkPaint paint1, paint2;
Cary Clark71961fb2018-01-05 14:21:59 -05003256 paint1.setTypeface(SkTypeface::MakeFromName("monospace",
Cary Clark8032b982017-07-28 11:04:54 -04003257 SkFontStyle(SkFontStyle::kNormal_Weight, SkFontStyle::kNormal_Width,
3258 SkFontStyle::kItalic_Slant)));
3259 SkDebugf("typeface1 %c= typeface2\n",
3260 paint1.getTypeface() == paint2.getTypeface() ? '=' : '!');
3261 paint2.setTypeface(paint1.refTypeface());
3262 SkDebugf("typeface1 %c= typeface2\n",
3263 paint1.getTypeface() == paint2.getTypeface() ? '=' : '!');
3264 }
3265
3266 #StdOut
3267 typeface1 != typeface2
3268 typeface1 == typeface2
3269 ##
3270 ##
3271
3272##
3273
3274#Method void setTypeface(sk_sp<SkTypeface> typeface)
3275
Cary Clark6fc50412017-09-21 12:31:06 -04003276Sets Typeface to typeface, decreasing Reference_Count of the previous Typeface.
3277Pass nullptr to clear Typeface and use the default typeface. Increments
3278typeface Reference_Count by one.
Cary Clark8032b982017-07-28 11:04:54 -04003279
3280 #Param typeface font and style used to draw text ##
3281
3282 #Example
3283 #Height 64
3284 void draw(SkCanvas* canvas) {
3285 SkPaint paint;
Cary Clark71961fb2018-01-05 14:21:59 -05003286 paint.setTypeface(SkTypeface::MakeFromName("monospace", SkFontStyle()));
3287 canvas->drawString("hamburgerfons", 10, 30, paint);
Cary Clark8032b982017-07-28 11:04:54 -04003288 paint.setTypeface(nullptr);
Cary Clark71961fb2018-01-05 14:21:59 -05003289 canvas->drawString("hamburgerfons", 10, 50, paint);
Cary Clark8032b982017-07-28 11:04:54 -04003290 }
3291 ##
3292
3293##
3294
3295#Topic ##
3296# ------------------------------------------------------------------------------
3297#Topic Rasterizer_Methods
3298
3299Rasterizer controls how shapes are converted to Mask_Alpha.
3300Rasterizer operates at a higher level than Mask_Filter; Rasterizer takes a Path,
3301and returns a Mask.
Cary Clark6fc50412017-09-21 12:31:06 -04003302
Cary Clark8032b982017-07-28 11:04:54 -04003303Rasterizer may change the geometry and transparency of the shape, such as
3304creating a shadow effect. Rasterizer forms the base of Rasterizer_Layer, which
3305creates effects like embossing and outlining.
Cary Clark6fc50412017-09-21 12:31:06 -04003306
Cary Clarkce101242017-09-01 15:51:02 -04003307Rasterizer applies to Rect, Region, Round_Rect, Arcs, Circles, Ovals,
Cary Clark8032b982017-07-28 11:04:54 -04003308Path, and Text.
3309
3310#Example
3311#Height 64
3312 void draw(SkCanvas* canvas) {
3313 SkLayerRasterizer::Builder layerBuilder;
3314 SkPaint paint;
3315 paint.setAntiAlias(true);
3316 paint.setStyle(SkPaint::kStroke_Style);
3317 paint.setStrokeWidth(1);
3318 layerBuilder.addLayer(paint);
3319 paint.setAlpha(0x10);
3320 paint.setStyle(SkPaint::kFill_Style);
3321 paint.setBlendMode(SkBlendMode::kSrc);
3322 layerBuilder.addLayer(paint);
3323 paint.reset();
3324 paint.setAntiAlias(true);
3325 paint.setTextSize(50);
3326 paint.setRasterizer(layerBuilder.detach());
3327 canvas->drawString("outline", 10, 50, paint);
3328 }
3329##
3330
3331#Method SkRasterizer* getRasterizer() const
3332
3333 Returns Rasterizer if set, or nullptr.
3334 Does not alter Rasterizer Reference_Count.
3335
3336 #Return Rasterizer if previously set, nullptr otherwise ##
3337
3338 #Example
3339 #Function
3340 class DummyRasterizer : public SkRasterizer {
3341 public:
3342 SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(DummyRasterizer)
3343 };
3344
3345 sk_sp<SkFlattenable> DummyRasterizer::CreateProc(SkReadBuffer&) {
3346 return sk_make_sp<DummyRasterizer>();
3347 }
3348
3349 #Function ##
3350 void draw(SkCanvas* canvas) {
3351 SkPaint paint;
3352 DummyRasterizer dummy;
3353 SkDebugf("nullptr %c= rasterizer\n", paint.getRasterizer() ? '!' : '=');
3354 paint.setRasterizer(sk_make_sp<DummyRasterizer>());
3355 SkDebugf("nullptr %c= rasterizer\n", paint.getRasterizer() ? '!' : '=');
3356 }
3357
3358 #StdOut
3359 nullptr == rasterizer
3360 nullptr != rasterizer
3361 ##
3362 ##
3363
3364##
3365
3366#Method sk_sp<SkRasterizer> refRasterizer() const
3367
3368 Returns Rasterizer if set, or nullptr.
3369 Increases Rasterizer Reference_Count by one.
3370
3371 #Return Rasterizer if previously set, nullptr otherwise ##
3372
3373 #Example
3374 void draw(SkCanvas* canvas) {
3375 SkLayerRasterizer::Builder layerBuilder;
3376 SkPaint paint1, paint2;
3377 layerBuilder.addLayer(paint2);
3378 paint1.setRasterizer(layerBuilder.detach());
3379 SkDebugf("rasterizer unique: %s\n", paint1.getRasterizer()->unique() ? "true" : "false");
3380 paint2.setRasterizer(paint1.refRasterizer());
3381 SkDebugf("rasterizer unique: %s\n", paint1.getRasterizer()->unique() ? "true" : "false");
3382 }
3383
3384 #StdOut
3385 rasterizer unique: true
3386 rasterizer unique: false
3387 ##
3388 ##
3389
3390##
3391
3392#Method void setRasterizer(sk_sp<SkRasterizer> rasterizer)
3393
Cary Clark6fc50412017-09-21 12:31:06 -04003394Sets Rasterizer to rasterizer, decreasing Reference_Count of the previous
3395Rasterizer. Pass nullptr to clear Rasterizer and leave Rasterizer effect on
3396Mask_Alpha unaltered.
3397
3398Does not affect Mask_Filter.
3399Increments rasterizer Reference_Count by one.
Cary Clark8032b982017-07-28 11:04:54 -04003400
3401 #Param rasterizer how geometry is converted to Mask_Alpha ##
3402
3403 #Example
3404 #Height 64
3405 SkLayerRasterizer::Builder layerBuilder;
3406 SkPaint paint;
3407 paint.setAntiAlias(true);
3408 paint.setStyle(SkPaint::kStroke_Style);
3409 paint.setStrokeWidth(2);
3410 layerBuilder.addLayer(paint);
3411 paint.reset();
3412 paint.setAntiAlias(true);
3413 paint.setTextSize(50);
3414 paint.setMaskFilter(SkBlurMaskFilter::Make(kNormal_SkBlurStyle, 3));
3415 paint.setRasterizer(layerBuilder.detach());
3416 canvas->drawString("blurry out", 0, 50, paint);
3417 ##
3418
3419##
3420
3421#Topic ##
3422# ------------------------------------------------------------------------------
3423#Topic Image_Filter_Methods
3424
3425Image_Filter operates on the pixel representation of the shape, as modified by Paint
3426with Blend_Mode set to SkBlendMode::kSrcOver. Image_Filter creates a new bitmap,
3427which is drawn to the device using the set Blend_Mode.
Cary Clark6fc50412017-09-21 12:31:06 -04003428
Cary Clark8032b982017-07-28 11:04:54 -04003429Image_Filter is higher level than Mask_Filter; for instance, an Image_Filter
Cary Clarkce101242017-09-01 15:51:02 -04003430can operate on all channels of Color, while Mask_Filter generates Alpha only.
Cary Clark8032b982017-07-28 11:04:54 -04003431Image_Filter operates independently of and can be used in combination with
3432Mask_Filter and Rasterizer.
3433
3434#Example
3435 #ToDo explain why the two draws are so different ##
3436 void draw(SkCanvas* canvas) {
3437 SkPaint paint;
3438 paint.setStyle(SkPaint::kStroke_Style);
3439 paint.setStrokeWidth(2);
3440 SkRegion region;
3441 region.op( 10, 10, 50, 50, SkRegion::kUnion_Op);
3442 region.op( 10, 50, 90, 90, SkRegion::kUnion_Op);
Cary Clarka560c472017-11-27 10:44:06 -05003443 paint.setImageFilter(SkBlurImageFilter::Make(5.0f, 5.0f, nullptr));
Cary Clark8032b982017-07-28 11:04:54 -04003444 canvas->drawRegion(region, paint);
3445 paint.setImageFilter(nullptr);
3446 paint.setMaskFilter(SkBlurMaskFilter::Make(kNormal_SkBlurStyle, 5));
3447 canvas->translate(100, 100);
3448 canvas->drawRegion(region, paint);
3449 }
3450##
3451
3452#Method SkImageFilter* getImageFilter() const
3453
3454 Returns Image_Filter if set, or nullptr.
3455 Does not alter Image_Filter Reference_Count.
3456
3457 #Return Image_Filter if previously set, nullptr otherwise ##
3458
3459 #Example
3460 void draw(SkCanvas* canvas) {
3461 SkPaint paint;
3462 SkDebugf("nullptr %c= image filter\n", paint.getImageFilter() ? '!' : '=');
Cary Clarka560c472017-11-27 10:44:06 -05003463 paint.setImageFilter(SkBlurImageFilter::Make(kOuter_SkBlurStyle, 3, nullptr, nullptr));
Cary Clark8032b982017-07-28 11:04:54 -04003464 SkDebugf("nullptr %c= image filter\n", paint.getImageFilter() ? '!' : '=');
3465 }
3466
3467 #StdOut
3468 nullptr == image filter
3469 nullptr != image filter
3470 ##
3471 ##
3472
3473##
3474
3475#Method sk_sp<SkImageFilter> refImageFilter() const
3476
3477 Returns Image_Filter if set, or nullptr.
3478 Increases Image_Filter Reference_Count by one.
3479
3480 #Return Image_Filter if previously set, nullptr otherwise ##
3481
3482 #Example
3483 void draw(SkCanvas* canvas) {
3484 SkPaint paint1, paint2;
3485 paint1.setImageFilter(SkOffsetImageFilter::Make(25, 25, nullptr));
3486 SkDebugf("image filter unique: %s\n", paint1.getImageFilter()->unique() ? "true" : "false");
3487 paint2.setImageFilter(paint1.refImageFilter());
3488 SkDebugf("image filter unique: %s\n", paint1.getImageFilter()->unique() ? "true" : "false");
3489 }
3490
3491 #StdOut
3492 image filter unique: true
3493 image filter unique: false
3494 ##
3495 ##
3496
3497##
3498
3499#Method void setImageFilter(sk_sp<SkImageFilter> imageFilter)
3500
Cary Clark6fc50412017-09-21 12:31:06 -04003501Sets Image_Filter to imageFilter, decreasing Reference_Count of the previous
3502Image_Filter. Pass nullptr to clear Image_Filter, and remove Image_Filter effect
3503on drawing.
3504
3505Does not affect Rasterizer or Mask_Filter.
3506Increments imageFilter Reference_Count by one.
Cary Clark8032b982017-07-28 11:04:54 -04003507
3508 #Param imageFilter how Image is sampled when transformed ##
3509
3510 #Example
3511 #Height 160
3512 void draw(SkCanvas* canvas) {
3513 SkBitmap bitmap;
3514 bitmap.allocN32Pixels(100, 100);
3515 SkCanvas offscreen(bitmap);
3516 SkPaint paint;
3517 paint.setAntiAlias(true);
3518 paint.setColor(SK_ColorWHITE);
3519 paint.setTextSize(96);
3520 offscreen.clear(0);
3521 offscreen.drawString("e", 20, 70, paint);
3522 paint.setImageFilter(
3523 SkLightingImageFilter::MakePointLitDiffuse(SkPoint3::Make(80, 100, 10),
3524 SK_ColorWHITE, 1, 2, nullptr, nullptr));
3525 canvas->drawBitmap(bitmap, 0, 0, &paint);
3526 }
3527 ##
3528
3529##
3530
3531#Topic ##
3532# ------------------------------------------------------------------------------
3533#Topic Draw_Looper_Methods
3534
3535Draw_Looper sets a modifier that communicates state from one Draw_Layer
3536to another to construct the draw.
Cary Clark6fc50412017-09-21 12:31:06 -04003537
Cary Clark8032b982017-07-28 11:04:54 -04003538Draw_Looper draws one or more times, modifying the canvas and paint each time.
3539Draw_Looper may be used to draw multiple colors or create a colored shadow.
3540Set Draw_Looper to nullptr to prevent Draw_Looper from modifying the draw.
3541
3542#Example
3543#Height 128
3544 void draw(SkCanvas* canvas) {
3545 SkLayerDrawLooper::LayerInfo info;
3546 info.fPaintBits = (SkLayerDrawLooper::BitFlags) SkLayerDrawLooper::kColorFilter_Bit;
3547 info.fColorMode = SkBlendMode::kSrc;
3548 SkLayerDrawLooper::Builder looperBuilder;
3549 SkPaint* loopPaint = looperBuilder.addLayer(info);
3550 loopPaint->setColor(SK_ColorRED);
3551 info.fOffset.set(20, 20);
3552 loopPaint = looperBuilder.addLayer(info);
3553 loopPaint->setColor(SK_ColorBLUE);
3554 SkPaint paint;
3555 paint.setDrawLooper(looperBuilder.detach());
3556 canvas->drawCircle(50, 50, 50, paint);
3557 }
3558
3559##
3560
3561#Method SkDrawLooper* getDrawLooper() const
3562
3563 Returns Draw_Looper if set, or nullptr.
3564 Does not alter Draw_Looper Reference_Count.
3565
3566 #Return Draw_Looper if previously set, nullptr otherwise ##
3567
3568 #Example
3569 void draw(SkCanvas* canvas) {
3570 SkPaint paint;
3571 SkDebugf("nullptr %c= draw looper\n", paint.getDrawLooper() ? '!' : '=');
3572 SkLayerDrawLooper::Builder looperBuilder;
3573 paint.setDrawLooper(looperBuilder.detach());
3574 SkDebugf("nullptr %c= draw looper\n", paint.getDrawLooper() ? '!' : '=');
3575 }
3576
3577 #StdOut
3578 nullptr == draw looper
3579 nullptr != draw looper
3580 ##
3581 ##
3582
3583##
3584
3585#Method sk_sp<SkDrawLooper> refDrawLooper() const
3586
3587 Returns Draw_Looper if set, or nullptr.
3588 Increases Draw_Looper Reference_Count by one.
3589
3590 #Return Draw_Looper if previously set, nullptr otherwise ##
3591
3592 #Example
3593 void draw(SkCanvas* canvas) {
3594 SkPaint paint1, paint2;
3595 SkLayerDrawLooper::Builder looperBuilder;
3596 paint1.setDrawLooper(looperBuilder.detach());
3597 SkDebugf("draw looper unique: %s\n", paint1.getDrawLooper()->unique() ? "true" : "false");
3598 paint2.setDrawLooper(paint1.refDrawLooper());
3599 SkDebugf("draw looper unique: %s\n", paint1.getDrawLooper()->unique() ? "true" : "false");
3600 }
3601
3602 #StdOut
3603 draw looper unique: true
3604 draw looper unique: false
3605 ##
3606 ##
3607
3608##
3609
3610#Method SkDrawLooper* getLooper() const
3611
3612Deprecated.
3613
3614#Deprecated
3615(see bug.skia.org/6259)
3616#Deprecated ##
3617
3618#Return Draw_Looper if previously set, nullptr otherwise ##
3619##
3620
3621#Method void setDrawLooper(sk_sp<SkDrawLooper> drawLooper)
3622
Cary Clark6fc50412017-09-21 12:31:06 -04003623Sets Draw_Looper to drawLooper, decreasing Reference_Count of the previous
3624drawLooper. Pass nullptr to clear Draw_Looper and leave Draw_Looper effect on
3625drawing unaltered.
3626
3627Increments drawLooper Reference_Count by one.
Cary Clark8032b982017-07-28 11:04:54 -04003628
Cary Clarka523d2d2017-08-30 08:58:10 -04003629 #Param drawLooper iterates through drawing one or more time, altering Paint ##
Cary Clark8032b982017-07-28 11:04:54 -04003630
3631 #Example
3632 #Height 128
3633 void draw(SkCanvas* canvas) {
3634 SkPaint paint;
3635 paint.setDrawLooper(SkBlurDrawLooper::Make(0x7FFF0000, 4, -5, -10));
3636 paint.setStyle(SkPaint::kStroke_Style);
3637 paint.setStrokeWidth(10);
3638 paint.setAntiAlias(true);
3639 paint.setColor(0x7f0000ff);
3640 canvas->drawCircle(70, 70, 50, paint);
3641 }
3642 ##
3643
3644##
3645
3646#Method void setLooper(sk_sp<SkDrawLooper> drawLooper)
3647
3648Deprecated.
3649
3650#Deprecated
3651(see bug.skia.org/6259)
3652#Deprecated ##
3653
3654#Param drawLooper sets Draw_Looper to drawLooper ##
3655
3656##
3657
3658#Topic ##
3659# ------------------------------------------------------------------------------
3660#Topic Text_Align
3661
3662#Enum Align
3663#Code
3664 enum Align {
3665 kLeft_Align,
3666 kCenter_Align,
3667 kRight_Align,
3668 };
3669##
3670
3671Align adjusts the text relative to the text position.
Cary Clarkce101242017-09-01 15:51:02 -04003672Align affects Glyphs drawn with: SkCanvas::drawText, SkCanvas::drawPosText,
Cary Clark8032b982017-07-28 11:04:54 -04003673SkCanvas::drawPosTextH, SkCanvas::drawTextOnPath,
3674SkCanvas::drawTextOnPathHV, SkCanvas::drawTextRSXform, SkCanvas::drawTextBlob,
3675and SkCanvas::drawString;
Cary Clarkce101242017-09-01 15:51:02 -04003676as well as calls that place text Glyphs like getTextWidths and getTextPath.
Cary Clark8032b982017-07-28 11:04:54 -04003677
3678The text position is set by the font for both horizontal and vertical text.
3679Typically, for horizontal text, the position is to the left side of the glyph on the
3680base line; and for vertical text, the position is the horizontal center of the glyph
3681at the caps height.
3682
3683Align adjusts the glyph position to center it or move it to abut the position
3684using the metrics returned by the font.
3685
3686Align defaults to kLeft_Align.
3687
3688#Const kLeft_Align 0
3689 Leaves the glyph at the position computed by the font offset by the text position.
3690##
3691
3692#Const kCenter_Align 1
3693 Moves the glyph half its width if Flags has kVerticalText_Flag clear, and
3694 half its height if Flags has kVerticalText_Flag set.
3695##
3696
3697#Const kRight_Align 2
3698 Moves the glyph by its width if Flags has kVerticalText_Flag clear,
3699 and by its height if Flags has kVerticalText_Flag set.
3700##
3701
3702#Enum ##
3703
3704#Enum
3705
3706#Code
3707 enum {
Cary Clarkbad5ad72017-08-03 17:14:08 -04003708 kAlignCount = 3,
Cary Clark8032b982017-07-28 11:04:54 -04003709 };
3710##
3711
3712#Const kAlignCount 3
3713 The number of different Text_Align values defined.
3714##
3715
3716#Enum ##
3717
3718#Example
3719 #Height 160
3720 #Description
3721 Each position separately moves the glyph in drawPosText.
3722 ##
3723 void draw(SkCanvas* canvas) {
3724 SkPaint paint;
3725 paint.setTextSize(40);
3726 SkPoint position[] = {{100, 50}, {150, 40}};
3727 for (SkPaint::Align a : { SkPaint::kLeft_Align,
3728 SkPaint::kCenter_Align,
3729 SkPaint::kRight_Align}) {
3730 paint.setTextAlign(a);
3731 canvas->drawPosText("Aa", 2, position, paint);
3732 canvas->translate(0, 50);
3733 }
3734 }
3735##
3736
3737#Example
3738 #Height 160
3739 #Description
3740 Vertical_Text treats kLeft_Align as top align, and kRight_Align as bottom align.
3741 ##
3742 void draw(SkCanvas* canvas) {
3743 SkPaint paint;
3744 paint.setTextSize(40);
3745 paint.setVerticalText(true);
3746 for (SkPaint::Align a : { SkPaint::kLeft_Align,
3747 SkPaint::kCenter_Align,
3748 SkPaint::kRight_Align }) {
3749 paint.setTextAlign(a);
3750 canvas->drawString("Aa", 50, 80, paint);
3751 canvas->translate(50, 0);
3752 }
3753 }
3754##
3755
3756#Method Align getTextAlign() const
3757
3758 Returns Text_Align.
3759 Returns kLeft_Align if Text_Align has not been set.
3760
3761 #Return text placement relative to position ##
3762
3763 #Example
3764 SkPaint paint;
3765 SkDebugf("kLeft_Align %c= default\n", SkPaint::kLeft_Align == paint.getTextAlign() ? '=' : '!');
3766
3767 #StdOut
3768 kLeft_Align == default
3769 ##
3770 ##
3771##
3772
3773#Method void setTextAlign(Align align)
3774
3775 Sets Text_Align to align.
3776 Has no effect if align is an invalid value.
3777
3778 #Param align text placement relative to position ##
3779
3780 #Example
3781 #Height 160
3782 #Description
3783 Text is left-aligned by default, and then set to center. Setting the
3784 alignment out of range has no effect.
3785 ##
3786 void draw(SkCanvas* canvas) {
3787 SkPaint paint;
3788 paint.setTextSize(40);
3789 canvas->drawString("Aa", 100, 50, paint);
3790 paint.setTextAlign(SkPaint::kCenter_Align);
3791 canvas->drawString("Aa", 100, 100, paint);
3792 paint.setTextAlign((SkPaint::Align) SkPaint::kAlignCount);
3793 canvas->drawString("Aa", 100, 150, paint);
3794 }
3795 ##
3796
3797##
3798
3799#Topic ##
3800# ------------------------------------------------------------------------------
3801#Topic Text_Size
3802
3803Text_Size adjusts the overall text size in points.
3804Text_Size can be set to any positive value or zero.
3805Text_Size defaults to 12.
3806Set SkPaintDefaults_TextSize at compile time to change the default setting.
3807
3808#Example
3809#Height 135
3810 void draw(SkCanvas* canvas) {
3811 SkPaint paint;
3812 canvas->drawString("12 point", 10, 20, paint);
3813 paint.setTextSize(24);
3814 canvas->drawString("24 point", 10, 60, paint);
3815 paint.setTextSize(48);
3816 canvas->drawString("48 point", 10, 120, paint);
3817 }
3818##
3819
3820#Method SkScalar getTextSize() const
3821
3822 Returns Text_Size in points.
3823
3824 #Return typographic height of text ##
3825
3826 #Example
3827 SkPaint paint;
3828 SkDebugf("12 %c= default text size\n", 12 == paint.getTextSize() ? '=' : '!');
3829 ##
3830
3831##
3832
3833#Method void setTextSize(SkScalar textSize)
3834
3835 Sets Text_Size in points.
3836 Has no effect if textSize is not greater than or equal to zero.
3837
3838 #Param textSize typographic height of text ##
3839
3840 #Example
3841 SkPaint paint;
3842 SkDebugf("12 %c= text size\n", 12 == paint.getTextSize() ? '=' : '!');
3843 paint.setTextSize(-20);
3844 SkDebugf("12 %c= text size\n", 12 == paint.getTextSize() ? '=' : '!');
3845 ##
3846
3847##
3848
3849#Topic ##
3850# ------------------------------------------------------------------------------
3851#Topic Text_Scale_X
3852
3853Text_Scale_X adjusts the text horizontal scale.
3854Text scaling approximates condensed and expanded type faces when the actual face
3855is not available.
3856Text_Scale_X can be set to any value.
3857Text_Scale_X defaults to 1.
3858
3859#Example
3860#Height 128
3861 void draw(SkCanvas* canvas) {
3862 SkPaint paint;
3863 paint.setAntiAlias(true);
3864 paint.setTextSize(24);
3865 paint.setTextScaleX(.8f);
3866 canvas->drawString("narrow", 10, 20, paint);
3867 paint.setTextScaleX(1);
3868 canvas->drawString("normal", 10, 60, paint);
3869 paint.setTextScaleX(1.2f);
3870 canvas->drawString("wide", 10, 100, paint);
3871 }
3872##
3873
3874#Method SkScalar getTextScaleX() const
3875
3876 Returns Text_Scale_X.
3877 Default value is 1.
3878
3879 #Return text horizontal scale ##
3880
3881 #Example
3882 SkPaint paint;
3883 SkDebugf("1 %c= default text scale x\n", 1 == paint.getTextScaleX() ? '=' : '!');
3884 ##
3885
3886##
3887
3888
3889#Method void setTextScaleX(SkScalar scaleX)
3890
3891 Sets Text_Scale_X.
3892 Default value is 1.
3893
3894 #Param scaleX text horizontal scale ##
3895
3896 #Example
3897 SkPaint paint;
3898 paint.setTextScaleX(0.f / 0.f);
3899 SkDebugf("text scale %s-a-number\n", SkScalarIsNaN(paint.getTextScaleX()) ? "not" : "is");
3900 ##
3901
3902##
3903
3904#Topic ##
3905
3906#Topic Text_Skew_X
3907
3908
3909Text_Skew_X adjusts the text horizontal slant.
3910Text skewing approximates italic and oblique type faces when the actual face
3911is not available.
3912Text_Skew_X can be set to any value.
3913Text_Skew_X defaults to 0.
3914
3915#Example
3916#Height 128
3917 void draw(SkCanvas* canvas) {
3918 SkPaint paint;
3919 paint.setAntiAlias(true);
3920 paint.setTextSize(24);
3921 paint.setTextSkewX(-.25f);
3922 canvas->drawString("right-leaning", 10, 100, paint);
3923 paint.setTextSkewX(0);
3924 canvas->drawString("normal", 10, 60, paint);
3925 paint.setTextSkewX(.25f);
3926 canvas->drawString("left-leaning", 10, 20, paint);
3927 }
3928##
3929
3930#Method SkScalar getTextSkewX() const
3931
3932 Returns Text_Skew_X.
3933 Default value is zero.
3934
3935 #Return additional shear in x-axis relative to y-axis ##
3936
3937 #Example
3938 SkPaint paint;
3939 SkDebugf("0 %c= default text skew x\n", 0 == paint.getTextSkewX() ? '=' : '!');
3940 ##
3941
3942##
3943
3944#Method void setTextSkewX(SkScalar skewX)
3945
3946 Sets Text_Skew_X.
3947 Default value is zero.
3948
3949 #Param skewX additional shear in x-axis relative to y-axis ##
3950
3951 #Example
3952 SkPaint paint;
3953 paint.setTextScaleX(1.f / 0.f);
3954 SkDebugf("text scale %s-finite\n", SkScalarIsFinite(paint.getTextScaleX()) ? "is" : "not");
3955 ##
3956
3957##
3958
3959#Topic ##
3960
3961# ------------------------------------------------------------------------------
3962#Topic Text_Encoding
3963
3964#Enum TextEncoding
3965
3966#Code
3967 enum TextEncoding {
3968 kUTF8_TextEncoding,
3969 kUTF16_TextEncoding,
3970 kUTF32_TextEncoding,
Cary Clarkbad5ad72017-08-03 17:14:08 -04003971 kGlyphID_TextEncoding,
Cary Clark8032b982017-07-28 11:04:54 -04003972 };
3973##
3974
Cary Clark6fc50412017-09-21 12:31:06 -04003975TextEncoding determines whether text specifies character codes and their encoded
Cary Clarkbc5697d2017-10-04 14:31:33 -04003976size, or glyph indices. Characters are encoded as specified by the
Cary Clark6fc50412017-09-21 12:31:06 -04003977#A Unicode standard # http://unicode.org/standard/standard.html ##
3978.
3979
Cary Clark8032b982017-07-28 11:04:54 -04003980Character codes encoded size are specified by UTF-8, UTF-16, or UTF-32.
Cary Clarkbc5697d2017-10-04 14:31:33 -04003981All character code formats are able to represent all of Unicode, differing only
Cary Clark8032b982017-07-28 11:04:54 -04003982in the total storage required.
3983
Cary Clark6fc50412017-09-21 12:31:06 -04003984#A UTF-8 (RFC 3629) # https://tools.ietf.org/html/rfc3629 ##
3985 encodes each character as one or more 8-bit bytes.
3986
3987#A UTF-16 (RFC 2781) # https://tools.ietf.org/html/rfc2781 ##
3988 encodes each character as one or two 16-bit words.
3989
3990#A UTF-32 # http://www.unicode.org/versions/Unicode5.0.0/ch03.pdf ##
3991 encodes each character as one 32-bit word.
Cary Clark8032b982017-07-28 11:04:54 -04003992
3993Font_Manager uses font data to convert character code points into glyph indices.
3994A glyph index is a 16-bit word.
3995
3996TextEncoding is set to kUTF8_TextEncoding by default.
3997
3998#Const kUTF8_TextEncoding 0
3999Uses bytes to represent UTF-8 or ASCII.
4000##
4001#Const kUTF16_TextEncoding 1
4002Uses two byte words to represent most of Unicode.
4003##
4004#Const kUTF32_TextEncoding 2
4005Uses four byte words to represent all of Unicode.
4006##
4007#Const kGlyphID_TextEncoding 3
4008Uses two byte words to represent glyph indices.
4009##
4010
4011#Enum ##
4012
4013#Example
4014#Height 128
4015#Description
Cary Clarkbc5697d2017-10-04 14:31:33 -04004016First line is encoded in UTF-8.
4017Second line is encoded in UTF-16.
4018Third line is encoded in UTF-32.
Cary Clark8032b982017-07-28 11:04:54 -04004019Fourth line has 16 bit glyph indices.
4020##
4021void draw(SkCanvas* canvas) {
4022 SkPaint paint;
4023 const char hello8[] = "Hello" "\xE2" "\x98" "\xBA";
4024 const uint16_t hello16[] = { 'H', 'e', 'l', 'l', 'o', 0x263A };
4025 const uint32_t hello32[] = { 'H', 'e', 'l', 'l', 'o', 0x263A };
4026 paint.setTextSize(24);
4027 canvas->drawText(hello8, sizeof(hello8) - 1, 10, 30, paint);
4028 paint.setTextEncoding(SkPaint::kUTF16_TextEncoding);
4029 canvas->drawText(hello16, sizeof(hello16), 10, 60, paint);
4030 paint.setTextEncoding(SkPaint::kUTF32_TextEncoding);
4031 canvas->drawText(hello32, sizeof(hello32), 10, 90, paint);
4032 uint16_t glyphs[SK_ARRAY_COUNT(hello32)];
4033 paint.textToGlyphs(hello32, sizeof(hello32), glyphs);
4034 paint.setTextEncoding(SkPaint::kGlyphID_TextEncoding);
4035 canvas->drawText(glyphs, sizeof(glyphs), 10, 120, paint);
4036}
4037##
4038
4039#Method TextEncoding getTextEncoding() const
4040
4041 Returns Text_Encoding.
4042 Text_Encoding determines how character code points are mapped to font glyph indices.
4043
4044 #Return one of: kUTF8_TextEncoding, kUTF16_TextEncoding, kUTF32_TextEncoding, or
4045 kGlyphID_TextEncoding
4046 ##
4047
4048 #Example
4049 SkPaint paint;
4050 SkDebugf("kUTF8_TextEncoding %c= text encoding\n",
4051 SkPaint::kUTF8_TextEncoding == paint.getTextEncoding() ? '=' : '!');
4052 paint.setTextEncoding(SkPaint::kGlyphID_TextEncoding);
4053 SkDebugf("kGlyphID_TextEncoding %c= text encoding\n",
4054 SkPaint::kGlyphID_TextEncoding == paint.getTextEncoding() ? '=' : '!');
4055
4056 #StdOut
4057 kUTF8_TextEncoding == text encoding
4058 kGlyphID_TextEncoding == text encoding
4059 ##
4060 ##
4061
4062##
4063
4064
4065#Method void setTextEncoding(TextEncoding encoding)
4066
4067 Sets Text_Encoding to encoding.
4068 Text_Encoding determines how character code points are mapped to font glyph indices.
4069 Invalid values for encoding are ignored.
4070
4071 #Param encoding one of: kUTF8_TextEncoding, kUTF16_TextEncoding, kUTF32_TextEncoding, or
Cary Clark579985c2017-07-31 11:48:27 -04004072 kGlyphID_TextEncoding
4073 #Param ##
Cary Clark8032b982017-07-28 11:04:54 -04004074
4075 #Example
4076 SkPaint paint;
4077 paint.setTextEncoding((SkPaint::TextEncoding) 4);
4078 SkDebugf("4 %c= text encoding\n", 4 == paint.getTextEncoding() ? '=' : '!');
4079
4080 #StdOut
4081 4 != text encoding
4082 ##
4083 ##
4084
4085##
4086
4087#Topic ##
4088# ------------------------------------------------------------------------------
4089#Topic Font_Metrics
4090
Cary Clarkce101242017-09-01 15:51:02 -04004091Font_Metrics describe dimensions common to the Glyphs in Typeface.
Cary Clark8032b982017-07-28 11:04:54 -04004092The dimensions are computed by Font_Manager from font data and do not take
4093Paint settings other than Text_Size into account.
4094
4095Font dimensions specify the anchor to the left of the glyph at baseline as the origin.
4096X-axis values to the left of the glyph are negative, and to the right of the left glyph edge
4097are positive.
4098Y-axis values above the baseline are negative, and below the baseline are positive.
Ben Wagnere5806492017-11-09 12:08:31 -05004099
Cary Clark8032b982017-07-28 11:04:54 -04004100#Example
4101#Width 512
4102void draw(SkCanvas* canvas) {
4103 SkPaint paint;
4104 paint.setAntiAlias(true);
4105 paint.setTextSize(120);
4106 SkPaint::FontMetrics fm;
4107 SkScalar lineHeight = paint.getFontMetrics(&fm);
4108 SkPoint pt = { 70, 180 };
4109 canvas->drawString("M", pt.fX, pt.fY, paint);
4110 canvas->drawLine(pt.fX, pt.fY, pt.fX, pt.fY + fm.fTop, paint);
4111 SkScalar ascent = pt.fY + fm.fAscent;
4112 canvas->drawLine(pt.fX - 25, ascent, pt.fX - 25, ascent + lineHeight, paint);
4113 canvas->drawLine(pt.fX - 50, pt.fY, pt.fX - 50, pt.fY + fm.fDescent, paint);
4114 canvas->drawLine(pt.fX + 100, pt.fY, pt.fX + 100, pt.fY + fm.fAscent, paint);
4115 canvas->drawLine(pt.fX + 125, pt.fY, pt.fX + 125, pt.fY - fm.fXHeight, paint);
4116 canvas->drawLine(pt.fX + 150, pt.fY, pt.fX + 150, pt.fY - fm.fCapHeight, paint);
4117 canvas->drawLine(pt.fX + 5, pt.fY, pt.fX + 5, pt.fY + fm.fBottom, paint);
4118 SkScalar xmin = pt.fX + fm.fXMin;
4119 canvas->drawLine(xmin, pt.fY + 60, xmin + fm.fMaxCharWidth, pt.fY + 60, paint);
4120 canvas->drawLine(xmin, pt.fY - 145, pt.fX, pt.fY - 145, paint);
4121 canvas->drawLine(pt.fX + fm.fXMax, pt.fY - 160, pt.fX, pt.fY - 160, paint);
4122 SkScalar upos = pt.fY + fm.fUnderlinePosition;
Ben Wagnere5806492017-11-09 12:08:31 -05004123 canvas->drawLine(pt.fX + 25, upos, pt.fX + 160, upos, paint);
4124 SkScalar ut = fm.fUnderlineThickness;
4125 canvas->drawLine(pt.fX + 130, upos + ut, pt.fX + 160, upos + ut, paint);
Cary Clark8032b982017-07-28 11:04:54 -04004126 paint.setTextSize(12);
4127 canvas->drawString("x-min", pt.fX - 50, pt.fY - 148, paint);
4128 canvas->drawString("x-max", pt.fX + 140, pt.fY - 150, paint);
4129 canvas->drawString("max char width", pt.fX + 120, pt.fY + 57, paint);
4130 canvas->drawString("underline position", pt.fX + 30, pt.fY + 22, paint);
4131 canvas->drawString("underline thickness", pt.fX + 162, pt.fY + 13, paint);
4132 canvas->rotate(-90);
4133 canvas->drawString("descent", -pt.fY - 30, pt.fX - 54, paint);
4134 canvas->drawString("line height", -pt.fY, pt.fX - 29, paint);
4135 canvas->drawString("top", -pt.fY + 30, pt.fX - 4, paint);
4136 canvas->drawString("ascent", -pt.fY, pt.fX + 110, paint);
4137 canvas->drawString("x-height", -pt.fY, pt.fX + 135, paint);
4138 canvas->drawString("cap-height", -pt.fY, pt.fX + 160, paint);
4139 canvas->drawString("bottom", -pt.fY - 50, pt.fX + 15, paint);
4140}
4141##
4142
4143#Struct FontMetrics
4144
4145#Code
4146 struct FontMetrics {
4147 enum FontMetricsFlags {
4148 kUnderlineThicknessIsValid_Flag = 1 << 0,
4149 kUnderlinePositionIsValid_Flag = 1 << 1,
4150 kStrikeoutThicknessIsValid_Flag = 1 << 2,
4151 kStrikeoutPositionIsValid_Flag = 1 << 3,
4152 };
4153
4154 uint32_t fFlags;
4155 SkScalar fTop;
4156 SkScalar fAscent;
4157 SkScalar fDescent;
4158 SkScalar fBottom;
4159 SkScalar fLeading;
4160 SkScalar fAvgCharWidth;
4161 SkScalar fMaxCharWidth;
4162 SkScalar fXMin;
4163 SkScalar fXMax;
4164 SkScalar fXHeight;
4165 SkScalar fCapHeight;
4166 SkScalar fUnderlineThickness;
4167 SkScalar fUnderlinePosition;
4168 SkScalar fStrikeoutThickness;
4169 SkScalar fStrikeoutPosition;
4170
4171 bool hasUnderlineThickness(SkScalar* thickness) const;
4172 bool hasUnderlinePosition(SkScalar* position) const;
4173 bool hasStrikeoutThickness(SkScalar* thickness) const;
4174 bool hasStrikeoutPosition(SkScalar* position) const;
4175 };
4176##
4177
Cary Clark154beea2017-10-26 07:58:48 -04004178 FontMetrics is filled out by getFontMetrics. FontMetrics contents reflect the values
4179 computed by Font_Manager using Typeface. Values are set to zero if they are
4180 not available.
Cary Clarke4aa3712017-09-15 02:56:12 -04004181
Ben Wagnere5806492017-11-09 12:08:31 -05004182 All vertical values relative to the baseline are given y-down. As such, zero is on the
4183 baseline, negative values are above the baseline, and positive values are below the
4184 baseline.
4185
Cary Clark154beea2017-10-26 07:58:48 -04004186 fUnderlineThickness and fUnderlinePosition have a bit set in fFlags if their values
4187 are valid, since their value may be zero.
Ben Wagnere5806492017-11-09 12:08:31 -05004188
Cary Clark154beea2017-10-26 07:58:48 -04004189 fStrikeoutThickness and fStrikeoutPosition have a bit set in fFlags if their values
4190 are valid, since their value may be zero.
4191
4192 #Enum FontMetricsFlags
Cary Clarke4aa3712017-09-15 02:56:12 -04004193
Cary Clark8032b982017-07-28 11:04:54 -04004194 #Code
4195 enum FontMetricsFlags {
4196 kUnderlineThicknessIsValid_Flag = 1 << 0,
4197 kUnderlinePositionIsValid_Flag = 1 << 1,
4198 kStrikeoutThicknessIsValid_Flag = 1 << 2,
4199 kStrikeoutPositionIsValid_Flag = 1 << 3,
4200 };
4201 ##
4202
Cary Clark154beea2017-10-26 07:58:48 -04004203 FontMetricsFlags are set in fFlags when underline and strikeout metrics are valid;
4204 the underline or strikeout metric may be valid and zero.
4205 Fonts with embedded bitmaps may not have valid underline or strikeout metrics.
4206
Cary Clark8032b982017-07-28 11:04:54 -04004207 #Const kUnderlineThicknessIsValid_Flag 0x0001
4208 Set if fUnderlineThickness is valid.
4209 ##
4210 #Const kUnderlinePositionIsValid_Flag 0x0002
4211 Set if fUnderlinePosition is valid.
4212 ##
4213 #Const kStrikeoutThicknessIsValid_Flag 0x0004
4214 Set if fStrikeoutThickness is valid.
4215 ##
4216 #Const kStrikeoutPositionIsValid_Flag 0x0008
4217 Set if fStrikeoutPosition is valid.
4218 ##
4219
4220 #Enum ##
4221
4222 #Member uint32_t fFlags
4223 fFlags is set when underline metrics are valid.
4224 ##
Ben Wagnere5806492017-11-09 12:08:31 -05004225
Cary Clark8032b982017-07-28 11:04:54 -04004226 #Member SkScalar fTop
Ben Wagnere5806492017-11-09 12:08:31 -05004227 Greatest extent above the baseline for any glyph.
4228 Typically less than zero.
Cary Clark8032b982017-07-28 11:04:54 -04004229 ##
Ben Wagnere5806492017-11-09 12:08:31 -05004230
Cary Clark8032b982017-07-28 11:04:54 -04004231 #Member SkScalar fAscent
4232 Recommended distance above the baseline to reserve for a line of text.
Ben Wagnere5806492017-11-09 12:08:31 -05004233 Typically less than zero.
Cary Clark8032b982017-07-28 11:04:54 -04004234 ##
Ben Wagnere5806492017-11-09 12:08:31 -05004235
Cary Clark8032b982017-07-28 11:04:54 -04004236 #Member SkScalar fDescent
4237 Recommended distance below the baseline to reserve for a line of text.
Ben Wagnere5806492017-11-09 12:08:31 -05004238 Typically greater than zero.
Cary Clark8032b982017-07-28 11:04:54 -04004239 ##
Ben Wagnere5806492017-11-09 12:08:31 -05004240
Cary Clark8032b982017-07-28 11:04:54 -04004241 #Member SkScalar fBottom
Ben Wagnere5806492017-11-09 12:08:31 -05004242 Greatest extent below the baseline for any glyph.
4243 Typically greater than zero.
Cary Clark8032b982017-07-28 11:04:54 -04004244 ##
Ben Wagnere5806492017-11-09 12:08:31 -05004245
Cary Clark8032b982017-07-28 11:04:54 -04004246 #Member SkScalar fLeading
4247 Recommended distance to add between lines of text.
Ben Wagnere5806492017-11-09 12:08:31 -05004248 Typically greater than or equal to zero.
Cary Clark8032b982017-07-28 11:04:54 -04004249 ##
Ben Wagnere5806492017-11-09 12:08:31 -05004250
Cary Clark8032b982017-07-28 11:04:54 -04004251 #Member SkScalar fAvgCharWidth
4252 Average character width, if it is available.
4253 Zero if no average width is stored in the font.
4254 ##
Ben Wagnere5806492017-11-09 12:08:31 -05004255
Cary Clark8032b982017-07-28 11:04:54 -04004256 #Member SkScalar fMaxCharWidth
4257 Maximum character width.
4258 ##
Ben Wagnere5806492017-11-09 12:08:31 -05004259
Cary Clark8032b982017-07-28 11:04:54 -04004260 #Member SkScalar fXMin
Ben Wagnere5806492017-11-09 12:08:31 -05004261 Minimum bounding box x value for all Glyphs.
Cary Clark8032b982017-07-28 11:04:54 -04004262 Typically less than zero.
4263 ##
Ben Wagnere5806492017-11-09 12:08:31 -05004264
Cary Clark8032b982017-07-28 11:04:54 -04004265 #Member SkScalar fXMax
Cary Clarkce101242017-09-01 15:51:02 -04004266 Maximum bounding box x value for all Glyphs.
Cary Clark8032b982017-07-28 11:04:54 -04004267 Typically greater than zero.
4268 ##
Ben Wagnere5806492017-11-09 12:08:31 -05004269
Cary Clark8032b982017-07-28 11:04:54 -04004270 #Member SkScalar fXHeight
4271 Height of a lower-case 'x'.
4272 May be zero if no lower-case height is stored in the font.
4273 ##
Ben Wagnere5806492017-11-09 12:08:31 -05004274
Cary Clark8032b982017-07-28 11:04:54 -04004275 #Member SkScalar fCapHeight
4276 Height of an upper-case letter.
4277 May be zero if no upper-case height is stored in the font.
4278 ##
Ben Wagnere5806492017-11-09 12:08:31 -05004279
Cary Clark8032b982017-07-28 11:04:54 -04004280 #Member SkScalar fUnderlineThickness
Ben Wagnere5806492017-11-09 12:08:31 -05004281 Underline thickness.
4282
4283 If the metric is valid, the kUnderlineThicknessIsValid_Flag is set in fFlags.
Cary Clark8032b982017-07-28 11:04:54 -04004284 If kUnderlineThicknessIsValid_Flag is clear, fUnderlineThickness is zero.
4285 ##
Ben Wagnere5806492017-11-09 12:08:31 -05004286
Cary Clark8032b982017-07-28 11:04:54 -04004287 #Member SkScalar fUnderlinePosition
Ben Wagnere5806492017-11-09 12:08:31 -05004288 Position of the top of the underline stroke relative to the baseline.
4289 Typically positive when valid.
Cary Clark8032b982017-07-28 11:04:54 -04004290
4291 If the metric is valid, the kUnderlinePositionIsValid_Flag is set in fFlags.
4292 If kUnderlinePositionIsValid_Flag is clear, fUnderlinePosition is zero.
4293 ##
4294
4295 #Member SkScalar fStrikeoutThickness
Ben Wagnere5806492017-11-09 12:08:31 -05004296 Strikeout thickness.
4297
4298 If the metric is valid, the kStrikeoutThicknessIsValid_Flag is set in fFlags.
Cary Clark8032b982017-07-28 11:04:54 -04004299 If kStrikeoutThicknessIsValid_Flag is clear, fStrikeoutThickness is zero.
4300 ##
4301
4302 #Member SkScalar fStrikeoutPosition
Ben Wagnere5806492017-11-09 12:08:31 -05004303 Position of the bottom of the strikeout stroke relative to the baseline.
4304 Typically negative when valid.
Cary Clark8032b982017-07-28 11:04:54 -04004305
Ben Wagnere5806492017-11-09 12:08:31 -05004306 If the metric is valid, the kStrikeoutPositionIsValid_Flag is set in fFlags.
4307 If kStrikeoutPositionIsValid_Flag is clear, fStrikeoutPosition is zero.
Cary Clark8032b982017-07-28 11:04:54 -04004308 ##
4309
4310 #Method bool hasUnderlineThickness(SkScalar* thickness) const
4311
Ben Wagnere5806492017-11-09 12:08:31 -05004312 If Font_Metrics has a valid underline thickness, return true, and set
Cary Clarkce101242017-09-01 15:51:02 -04004313 thickness to that value. If the underline thickness is not valid,
4314 return false, and ignore thickness.
Cary Clark8032b982017-07-28 11:04:54 -04004315
4316 #Param thickness storage for underline width ##
4317
4318 #Return true if font specifies underline width ##
4319
4320 #NoExample
4321 ##
4322 ##
4323
4324 #Method bool hasUnderlinePosition(SkScalar* position) const
4325
Ben Wagnere5806492017-11-09 12:08:31 -05004326 If Font_Metrics has a valid underline position, return true, and set
Cary Clarkce101242017-09-01 15:51:02 -04004327 position to that value. If the underline position is not valid,
4328 return false, and ignore position.
Cary Clark8032b982017-07-28 11:04:54 -04004329
4330 #Param position storage for underline position ##
4331
4332 #Return true if font specifies underline position ##
4333
4334 #NoExample
4335 ##
4336 ##
4337
4338 #Method bool hasStrikeoutThickness(SkScalar* thickness) const
4339
Ben Wagnere5806492017-11-09 12:08:31 -05004340 If Font_Metrics has a valid strikeout thickness, return true, and set
Cary Clarkce101242017-09-01 15:51:02 -04004341 thickness to that value. If the underline thickness is not valid,
4342 return false, and ignore thickness.
Cary Clark8032b982017-07-28 11:04:54 -04004343
4344 #Param thickness storage for strikeout width ##
4345
4346 #Return true if font specifies strikeout width ##
4347
4348 #NoExample
4349 ##
4350 ##
4351
4352 #Method bool hasStrikeoutPosition(SkScalar* position) const
4353
Ben Wagnere5806492017-11-09 12:08:31 -05004354 If Font_Metrics has a valid strikeout position, return true, and set
Cary Clarkce101242017-09-01 15:51:02 -04004355 position to that value. If the underline position is not valid,
4356 return false, and ignore position.
Cary Clark8032b982017-07-28 11:04:54 -04004357
4358 #Param position storage for strikeout position ##
4359
4360 #Return true if font specifies strikeout position ##
4361
4362 #NoExample
4363 ##
4364 ##
4365
4366#Struct ##
4367
4368#Method SkScalar getFontMetrics(FontMetrics* metrics, SkScalar scale = 0) const
4369
4370 Returns Font_Metrics associated with Typeface.
4371 The return value is the recommended spacing between lines: the sum of metrics
4372 descent, ascent, and leading.
4373 If metrics is not nullptr, Font_Metrics is copied to metrics.
4374 Results are scaled by Text_Size but does not take into account
4375 dimensions required by Text_Scale_X, Text_Skew_X, Fake_Bold,
4376 Style_Stroke, and Path_Effect.
4377 Results can be additionally scaled by scale; a scale of zero
4378 is ignored.
4379
4380 #Param metrics storage for Font_Metrics from Typeface; may be nullptr ##
4381 #Param scale additional multiplier for returned values ##
4382
4383 #Return recommended spacing between lines ##
4384
4385 #Example
4386 #Height 128
4387 void draw(SkCanvas* canvas) {
4388 SkPaint paint;
4389 paint.setTextSize(32);
4390 SkScalar lineHeight = paint.getFontMetrics(nullptr);
4391 canvas->drawString("line 1", 10, 40, paint);
4392 canvas->drawString("line 2", 10, 40 + lineHeight, paint);
4393 paint.setStyle(SkPaint::kStroke_Style);
4394 paint.setStrokeWidth(10);
4395 lineHeight = paint.getFontMetrics(nullptr, 1.10f); // account for stroke height
4396 canvas->drawString("line 3", 120, 40, paint);
4397 canvas->drawString("line 4", 120, 40 + lineHeight, paint);
4398 }
4399 ##
4400
4401 #SeeAlso Text_Size Typeface Typeface_Methods
4402
4403##
4404
4405
4406#Method SkScalar getFontSpacing() const
4407
4408 Returns the recommended spacing between lines: the sum of metrics
4409 descent, ascent, and leading.
4410 Result is scaled by Text_Size but does not take into account
4411 dimensions required by stroking and Path_Effect.
Cary Clark579985c2017-07-31 11:48:27 -04004412 Returns the same result as getFontMetrics.
Cary Clark8032b982017-07-28 11:04:54 -04004413
Cary Clark0c5f5462017-12-15 11:21:51 -05004414 #Return recommended spacing between lines ##
Cary Clark8032b982017-07-28 11:04:54 -04004415
4416 #Example
4417 SkPaint paint;
4418 for (SkScalar textSize : { 12, 18, 24, 32 } ) {
4419 paint.setTextSize(textSize);
4420 SkDebugf("textSize: %g fontSpacing: %g\n", textSize, paint.getFontSpacing());
4421 }
4422
4423 #StdOut
4424 textSize: 12 fontSpacing: 13.9688
4425 textSize: 18 fontSpacing: 20.9531
4426 textSize: 24 fontSpacing: 27.9375
4427 textSize: 32 fontSpacing: 37.25
4428 ##
4429 ##
4430
4431##
4432
4433
4434#Method SkRect getFontBounds() const
4435
Cary Clarkce101242017-09-01 15:51:02 -04004436Returns the union of bounds of all Glyphs.
Cary Clark8032b982017-07-28 11:04:54 -04004437Returned dimensions are computed by Font_Manager from font data,
Cary Clark579985c2017-07-31 11:48:27 -04004438ignoring Hinting. Includes Text_Size, Text_Scale_X,
Cary Clark8032b982017-07-28 11:04:54 -04004439and Text_Skew_X, but not Fake_Bold or Path_Effect.
4440
4441If Text_Size is large, Text_Scale_X is one, and Text_Skew_X is zero,
Cary Clark579985c2017-07-31 11:48:27 -04004442returns the same bounds as Font_Metrics { FontMetrics::fXMin,
Cary Clark8032b982017-07-28 11:04:54 -04004443FontMetrics::fTop, FontMetrics::fXMax, FontMetrics::fBottom }.
4444
Cary Clarkce101242017-09-01 15:51:02 -04004445#Return union of bounds of all Glyphs ##
Cary Clark8032b982017-07-28 11:04:54 -04004446
4447#Example
4448 SkPaint paint;
4449 SkPaint::FontMetrics fm;
4450 paint.getFontMetrics(&fm);
4451 SkRect fb = paint.getFontBounds();
4452 SkDebugf("metrics bounds = { %g, %g, %g, %g }\n", fm.fXMin, fm.fTop, fm.fXMax, fm.fBottom );
4453 SkDebugf("font bounds = { %g, %g, %g, %g }\n", fb.fLeft, fb.fTop, fb.fRight, fm.fBottom );
4454
4455 #StdOut
4456 metrics bounds = { -12.2461, -14.7891, 21.5215, 5.55469 }
4457 font bounds = { -12.2461, -14.7891, 21.5215, 5.55469 }
4458 ##
4459##
4460
4461##
4462
4463#Topic ##
4464# ------------------------------------------------------------------------------
4465
4466#Method int textToGlyphs(const void* text, size_t byteLength,
4467 SkGlyphID glyphs[]) const
4468
4469Converts text into glyph indices.
4470Returns the number of glyph indices represented by text.
4471Text_Encoding specifies how text represents characters or glyphs.
4472glyphs may be nullptr, to compute the glyph count.
4473
Cary Clarkbc5697d2017-10-04 14:31:33 -04004474Does not check text for valid character codes or valid glyph indices.
Cary Clark8032b982017-07-28 11:04:54 -04004475
Cary Clark579985c2017-07-31 11:48:27 -04004476If byteLength equals zero, returns zero.
Cary Clark8032b982017-07-28 11:04:54 -04004477If byteLength includes a partial character, the partial character is ignored.
4478
4479If Text_Encoding is kUTF8_TextEncoding and
4480text contains an invalid UTF-8 sequence, zero is returned.
4481
Cary Clarkce101242017-09-01 15:51:02 -04004482#Param text character storage encoded with Text_Encoding ##
Cary Clark8032b982017-07-28 11:04:54 -04004483#Param byteLength length of character storage in bytes ##
4484#Param glyphs storage for glyph indices; may be nullptr ##
4485
4486#Return number of glyphs represented by text of length byteLength ##
4487
4488 #Example
4489 #Height 64
4490 void draw(SkCanvas* canvas) {
4491 SkPaint paint;
4492 const uint8_t utf8[] = { 0x24, 0xC2, 0xA2, 0xE2, 0x82, 0xAC, 0xC2, 0xA5, 0xC2, 0xA3 };
4493 std::vector<SkGlyphID> glyphs;
4494 int count = paint.textToGlyphs(utf8, sizeof(utf8), nullptr);
4495 glyphs.resize(count);
4496 (void) paint.textToGlyphs(utf8, sizeof(utf8), &glyphs.front());
4497 paint.setTextEncoding(SkPaint::kGlyphID_TextEncoding);
4498 paint.setTextSize(32);
4499 canvas->drawText(&glyphs.front(), glyphs.size() * sizeof(SkGlyphID), 10, 40, paint);
4500 }
4501 ##
4502
4503##
4504
4505#Method int countText(const void* text, size_t byteLength) const
4506
Cary Clarkce101242017-09-01 15:51:02 -04004507 Returns the number of Glyphs in text.
4508 Uses Text_Encoding to count the Glyphs.
Cary Clark8032b982017-07-28 11:04:54 -04004509 Returns the same result as textToGlyphs.
4510
Cary Clarkce101242017-09-01 15:51:02 -04004511#Param text character storage encoded with Text_Encoding ##
Cary Clark8032b982017-07-28 11:04:54 -04004512#Param byteLength length of character storage in bytes ##
4513
Cary Clarkce101242017-09-01 15:51:02 -04004514#Return number of Glyphs represented by text of length byteLength ##
Cary Clark8032b982017-07-28 11:04:54 -04004515
4516 #Example
4517 SkPaint paint;
4518 const uint8_t utf8[] = { 0x24, 0xC2, 0xA2, 0xE2, 0x82, 0xAC, 0xC2, 0xA5, 0xC2, 0xA3 };
4519 SkDebugf("count = %d\n", paint.countText(utf8, sizeof(utf8)));
4520
4521 #StdOut
4522 count = 5
4523 ##
4524 ##
4525##
4526
4527# ------------------------------------------------------------------------------
4528
4529#Method bool containsText(const void* text, size_t byteLength) const
4530
4531 Returns true if all text corresponds to a non-zero glyph index.
4532 Returns false if any characters in text are not supported in
4533 Typeface.
4534
Cary Clark579985c2017-07-31 11:48:27 -04004535 If Text_Encoding is kGlyphID_TextEncoding,
4536 returns true if all glyph indices in text are non-zero;
Cary Clark8032b982017-07-28 11:04:54 -04004537 does not check to see if text contains valid glyph indices for Typeface.
4538
Cary Clarkce101242017-09-01 15:51:02 -04004539 Returns true if byteLength is zero.
Cary Clark8032b982017-07-28 11:04:54 -04004540
Cary Clarkce101242017-09-01 15:51:02 -04004541 #Param text array of characters or Glyphs ##
Cary Clark8032b982017-07-28 11:04:54 -04004542 #Param byteLength number of bytes in text array ##
4543
4544 #Return true if all text corresponds to a non-zero glyph index ##
4545
4546 #Example
4547 #Description
4548 containsText succeeds for degree symbol, but cannot find a glyph index
4549 corresponding to the Unicode surrogate code point.
4550 ##
4551 SkPaint paint;
4552 const uint16_t goodChar = 0x00B0; // degree symbol
4553 const uint16_t badChar = 0xD800; // Unicode surrogate
4554 paint.setTextEncoding(SkPaint::kUTF16_TextEncoding);
4555 SkDebugf("0x%04x %c= has char\n", goodChar,
4556 paint.containsText(&goodChar, 2) ? '=' : '!');
4557 SkDebugf("0x%04x %c= has char\n", badChar,
4558 paint.containsText(&badChar, 2) ? '=' : '!');
4559
4560 #StdOut
4561 0x00b0 == has char
4562 0xd800 != has char
4563 ##
4564 ##
4565
4566 #Example
4567 #Description
4568 containsText returns true that glyph index is greater than zero, not
4569 that it corresponds to an entry in Typeface.
4570 ##
4571 SkPaint paint;
4572 const uint16_t goodGlyph = 511;
4573 const uint16_t zeroGlyph = 0;
4574 const uint16_t badGlyph = 65535; // larger than glyph count in font
4575 paint.setTextEncoding(SkPaint::kGlyphID_TextEncoding);
4576 SkDebugf("0x%04x %c= has glyph\n", goodGlyph,
4577 paint.containsText(&goodGlyph, 2) ? '=' : '!');
4578 SkDebugf("0x%04x %c= has glyph\n", zeroGlyph,
4579 paint.containsText(&zeroGlyph, 2) ? '=' : '!');
4580 SkDebugf("0x%04x %c= has glyph\n", badGlyph,
4581 paint.containsText(&badGlyph, 2) ? '=' : '!');
4582
4583 #StdOut
4584 0x01ff == has glyph
4585 0x0000 != has glyph
4586 0xffff == has glyph
4587 ##
4588 ##
4589
4590#SeeAlso setTextEncoding Typeface
4591
4592##
4593
4594# ------------------------------------------------------------------------------
4595
4596#Method void glyphsToUnichars(const SkGlyphID glyphs[],
4597 int count, SkUnichar text[]) const
4598
4599 Converts glyphs into text if possible.
4600 Glyph values without direct Unicode equivalents are mapped to zero.
4601 Uses the Typeface, but is unaffected
4602 by Text_Encoding; the text values returned are equivalent to kUTF32_TextEncoding.
4603
4604 Only supported on platforms that use FreeType as the Font_Engine.
4605
4606 #Param glyphs array of indices into font ##
4607 #Param count length of glyph array ##
4608 #Param text storage for character codes, one per glyph ##
4609
4610 #Example
4611 #Height 64
4612 #Description
4613 Convert UTF-8 text to glyphs; then convert glyphs to Unichar code points.
4614 ##
4615 void draw(SkCanvas* canvas) {
4616 SkPaint paint;
4617 const char hello[] = "Hello!";
4618 const int count = sizeof(hello) - 1;
4619 SkGlyphID glyphs[count];
4620 if (count != paint.textToGlyphs(hello, count, glyphs)) {
4621 return;
4622 }
4623 SkUnichar unichars[count];
4624 paint.glyphsToUnichars(glyphs, count, unichars);
4625 paint.setTextEncoding(SkPaint::kUTF32_TextEncoding);
4626 canvas->drawText(unichars, sizeof(unichars), 10, 30, paint);
4627 }
4628 ##
4629
4630##
4631
4632# ------------------------------------------------------------------------------
4633#Topic Measure_Text
4634
4635#Method SkScalar measureText(const void* text, size_t length, SkRect* bounds) const
4636
4637 Returns the advance width of text if kVerticalText_Flag is clear,
4638 and the height of text if kVerticalText_Flag is set.
4639 The advance is the normal distance to move before drawing additional text.
4640 Uses Text_Encoding to decode text, Typeface to get the font metrics,
4641 and Text_Size, Text_Scale_X, Text_Skew_X, Stroke_Width, and
4642 Path_Effect to scale the metrics and bounds.
4643 Returns the bounding box of text if bounds is not nullptr.
4644 The bounding box is computed as if the text was drawn at the origin.
4645
4646 #Param text character codes or glyph indices to be measured ##
4647 #Param length number of bytes of text to measure ##
4648 #Param bounds returns bounding box relative to (0, 0) if not nullptr ##
4649
4650 #Return advance width or height ##
4651
4652 #Example
4653 #Height 64
4654 void draw(SkCanvas* canvas) {
4655 SkPaint paint;
4656 paint.setAntiAlias(true);
4657 paint.setTextSize(50);
4658 const char str[] = "ay^jZ";
4659 const int count = sizeof(str) - 1;
4660 canvas->drawText(str, count, 25, 50, paint);
4661 SkRect bounds;
4662 paint.measureText(str, count, &bounds);
4663 canvas->translate(25, 50);
4664 paint.setStyle(SkPaint::kStroke_Style);
4665 canvas->drawRect(bounds, paint);
4666 }
4667 ##
4668
4669##
4670
4671#Method SkScalar measureText(const void* text, size_t length) const
4672
4673 Returns the advance width of text if kVerticalText_Flag is clear,
4674 and the height of text if kVerticalText_Flag is set.
4675 The advance is the normal distance to move before drawing additional text.
4676 Uses Text_Encoding to decode text, Typeface to get the font metrics,
4677 and Text_Size to scale the metrics.
4678 Does not scale the advance or bounds by Fake_Bold or Path_Effect.
4679
4680 #Param text character codes or glyph indices to be measured ##
4681 #Param length number of bytes of text to measure ##
4682
4683 #Return advance width or height ##
4684
4685 #Example
4686 SkPaint paint;
4687 SkDebugf("default width = %g\n", paint.measureText("!", 1));
4688 paint.setTextSize(paint.getTextSize() * 2);
4689 SkDebugf("double width = %g\n", paint.measureText("!", 1));
4690
4691 #StdOut
4692 default width = 5
4693 double width = 10
4694 ##
4695 ##
4696
4697##
4698
4699#Method size_t breakText(const void* text, size_t length, SkScalar maxWidth,
Cary Clark73fa9722017-08-29 17:36:51 -04004700 SkScalar* measuredWidth = nullptr) const
Cary Clark8032b982017-07-28 11:04:54 -04004701
4702 Returns the bytes of text that fit within maxWidth.
4703 If kVerticalText_Flag is clear, the text fragment fits if its advance width is less than or
4704 equal to maxWidth.
4705 If kVerticalText_Flag is set, the text fragment fits if its advance height is less than or
4706 equal to maxWidth.
4707 Measures only while the advance is less than or equal to maxWidth.
4708 Returns the advance or the text fragment in measuredWidth if it not nullptr.
4709 Uses Text_Encoding to decode text, Typeface to get the font metrics,
4710 and Text_Size to scale the metrics.
4711 Does not scale the advance or bounds by Fake_Bold or Path_Effect.
4712
4713 #Param text character codes or glyph indices to be measured ##
4714 #Param length number of bytes of text to measure ##
4715 #Param maxWidth advance limit; text is measured while advance is less than maxWidth ##
4716 #Param measuredWidth returns the width of the text less than or equal to maxWidth ##
4717 #Return bytes of text that fit, always less than or equal to length ##
4718
4719 #Example
4720 #Description
4721 Line under "Breakfast" shows desired width, shorter than available characters.
4722 Line under "Bre" shows measured width after breaking text.
4723 ##
4724 #Height 128
4725 #Width 280
4726 void draw(SkCanvas* canvas) {
4727 SkPaint paint;
4728 paint.setAntiAlias(true);
4729 paint.setTextSize(50);
4730 const char str[] = "Breakfast";
4731 const int count = sizeof(str) - 1;
4732 canvas->drawText(str, count, 25, 50, paint);
4733 SkScalar measuredWidth;
4734 int partialBytes = paint.breakText(str, count, 100, &measuredWidth);
4735 canvas->drawText(str, partialBytes, 25, 100, paint);
4736 canvas->drawLine(25, 60, 25 + 100, 60, paint);
4737 canvas->drawLine(25, 110, 25 + measuredWidth, 110, paint);
4738 }
4739 ##
4740
4741##
4742
4743#Method int getTextWidths(const void* text, size_t byteLength, SkScalar widths[],
Cary Clark73fa9722017-08-29 17:36:51 -04004744 SkRect bounds[] = nullptr) const
Cary Clark8032b982017-07-28 11:04:54 -04004745
4746 Retrieves the advance and bounds for each glyph in text, and returns
4747 the glyph count in text.
4748 Both widths and bounds may be nullptr.
4749 If widths is not nullptr, widths must be an array of glyph count entries.
4750 if bounds is not nullptr, bounds must be an array of glyph count entries.
4751 If kVerticalText_Flag is clear, widths returns the horizontal advance.
4752 If kVerticalText_Flag is set, widths returns the vertical advance.
4753 Uses Text_Encoding to decode text, Typeface to get the font metrics,
4754 and Text_Size to scale the widths and bounds.
4755 Does not scale the advance by Fake_Bold or Path_Effect.
4756 Does include Fake_Bold and Path_Effect in the bounds.
4757
4758 #Param text character codes or glyph indices to be measured ##
4759 #Param byteLength number of bytes of text to measure ##
4760 #Param widths returns text advances for each glyph; may be nullptr ##
4761 #Param bounds returns bounds for each glyph relative to (0, 0); may be nullptr ##
4762
4763 #Return glyph count in text ##
4764
4765 #Example
4766 #Height 160
4767 #Description
Cary Clarkce101242017-09-01 15:51:02 -04004768 Bounds of Glyphs increase for stroked text, but text advance remains the same.
Cary Clark8032b982017-07-28 11:04:54 -04004769 The underlines show the text advance, spaced to keep them distinct.
4770 ##
4771 void draw(SkCanvas* canvas) {
4772 SkPaint paint;
4773 paint.setAntiAlias(true);
4774 paint.setTextSize(50);
4775 const char str[] = "abc";
4776 const int bytes = sizeof(str) - 1;
4777 int count = paint.getTextWidths(str, bytes, nullptr);
4778 std::vector<SkScalar> widths;
4779 std::vector<SkRect> bounds;
4780 widths.resize(count);
4781 bounds.resize(count);
4782 for (int loop = 0; loop < 2; ++loop) {
4783 (void) paint.getTextWidths(str, count, &widths.front(), &bounds.front());
4784 SkPoint loc = { 25, 50 };
4785 canvas->drawText(str, bytes, loc.fX, loc.fY, paint);
4786 paint.setStyle(SkPaint::kStroke_Style);
4787 paint.setStrokeWidth(0);
4788 SkScalar advanceY = loc.fY + 10;
4789 for (int index = 0; index < count; ++index) {
4790 bounds[index].offset(loc.fX, loc.fY);
4791 canvas->drawRect(bounds[index], paint);
4792 canvas->drawLine(loc.fX, advanceY, loc.fX + widths[index], advanceY, paint);
4793 loc.fX += widths[index];
4794 advanceY += 5;
4795 }
4796 canvas->translate(0, 80);
4797 paint.setStrokeWidth(3);
4798 }
4799 }
4800 ##
4801
4802##
4803
4804#Topic ##
4805# ------------------------------------------------------------------------------
4806#Topic Text_Path
4807
Cary Clarkce101242017-09-01 15:51:02 -04004808Text_Path describes the geometry of Glyphs used to draw text.
Cary Clark8032b982017-07-28 11:04:54 -04004809
4810#Method void getTextPath(const void* text, size_t length, SkScalar x, SkScalar y,
4811 SkPath* path) const
4812
4813Returns the geometry as Path equivalent to the drawn text.
4814Uses Text_Encoding to decode text, Typeface to get the glyph paths,
4815and Text_Size, Fake_Bold, and Path_Effect to scale and modify the glyph paths.
4816All of the glyph paths are stored in path.
Cary Clark579985c2017-07-31 11:48:27 -04004817Uses x, y, and Text_Align to position path.
Cary Clark8032b982017-07-28 11:04:54 -04004818
4819 #Param text character codes or glyph indices ##
4820 #Param length number of bytes of text ##
4821 #Param x x-coordinate of the origin of the text ##
4822 #Param y y-coordinate of the origin of the text ##
Cary Clarkce101242017-09-01 15:51:02 -04004823 #Param path geometry of the Glyphs ##
Cary Clark8032b982017-07-28 11:04:54 -04004824
4825 #Example
4826 #Description
4827 Text is added to Path, offset, and subtracted from Path, then added at
4828 the offset location. The result is rendered with one draw call.
4829 ##
4830 #Height 128
4831 void draw(SkCanvas* canvas) {
4832 SkPaint paint;
4833 paint.setTextSize(80);
4834 SkPath path, path2;
4835 paint.getTextPath("ABC", 3, 20, 80, &path);
4836 path.offset(20, 20, &path2);
4837 Op(path, path2, SkPathOp::kDifference_SkPathOp, &path);
4838 path.addPath(path2);
4839 paint.setStyle(SkPaint::kStroke_Style);
4840 canvas->drawPath(path, paint);
4841 }
4842 ##
4843
4844##
4845
4846#Method void getPosTextPath(const void* text, size_t length,
4847 const SkPoint pos[], SkPath* path) const
4848
4849Returns the geometry as Path equivalent to the drawn text.
4850Uses Text_Encoding to decode text, Typeface to get the glyph paths,
4851and Text_Size, Fake_Bold, and Path_Effect to scale and modify the glyph paths.
4852All of the glyph paths are stored in path.
4853Uses pos array and Text_Align to position path.
4854pos contains a position for each glyph.
4855
4856 #Param text character codes or glyph indices ##
4857 #Param length number of bytes of text ##
4858 #Param pos positions of each glyph ##
Cary Clarkce101242017-09-01 15:51:02 -04004859 #Param path geometry of the Glyphs ##
Cary Clark8032b982017-07-28 11:04:54 -04004860
4861 #Example
4862 #Height 85
4863 #Description
Cary Clarkce101242017-09-01 15:51:02 -04004864 Simplifies three Glyphs to eliminate overlaps, and strokes the result.
Cary Clark8032b982017-07-28 11:04:54 -04004865 ##
4866 void draw(SkCanvas* canvas) {
4867 SkPaint paint;
4868 paint.setTextSize(80);
4869 SkPath path, path2;
4870 SkPoint pos[] = {{20, 60}, {30, 70}, {40, 80}};
4871 paint.getPosTextPath("ABC", 3, pos, &path);
4872 Simplify(path, &path);
4873 paint.setStyle(SkPaint::kStroke_Style);
4874 canvas->drawPath(path, paint);
4875 }
4876 ##
4877
4878##
4879
4880#Topic ##
4881# ------------------------------------------------------------------------------
4882#Topic Text_Intercepts
4883
Cary Clarkce101242017-09-01 15:51:02 -04004884Text_Intercepts describe the intersection of drawn text Glyphs with a pair
Cary Clark8032b982017-07-28 11:04:54 -04004885of lines parallel to the text advance. Text_Intercepts permits creating a
Cary Clarkce101242017-09-01 15:51:02 -04004886underline that skips Descenders.
Cary Clark8032b982017-07-28 11:04:54 -04004887
4888#Method int getTextIntercepts(const void* text, size_t length, SkScalar x, SkScalar y,
4889 const SkScalar bounds[2], SkScalar* intervals) const
4890
4891 Returns the number of intervals that intersect bounds.
4892 bounds describes a pair of lines parallel to the text advance.
Cary Clarkce101242017-09-01 15:51:02 -04004893 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 -04004894 the string.
4895 Uses Text_Encoding to decode text, Typeface to get the glyph paths,
4896 and Text_Size, Fake_Bold, and Path_Effect to scale and modify the glyph paths.
4897 Uses x, y, and Text_Align to position intervals.
4898
4899 Pass nullptr for intervals to determine the size of the interval array.
4900
4901 intervals are cached to improve performance for multiple calls.
4902
4903 #Param text character codes or glyph indices ##
4904 #Param length number of bytes of text ##
4905 #Param x x-coordinate of the origin of the text ##
4906 #Param y y-coordinate of the origin of the text ##
4907 #Param bounds lower and upper line parallel to the advance ##
4908 #Param intervals returned intersections; may be nullptr ##
4909
4910 #Return number of intersections; may be zero ##
4911
4912#Example
4913#Height 128
4914#Description
Cary Clarkce101242017-09-01 15:51:02 -04004915Underline uses intercepts to draw on either side of the glyph Descender.
Cary Clark8032b982017-07-28 11:04:54 -04004916##
4917void draw(SkCanvas* canvas) {
4918 SkPaint paint;
4919 paint.setTextSize(120);
4920 SkPoint textOrigin = { 20, 100 };
4921 SkScalar bounds[] = { 100, 108 };
4922 int count = paint.getTextIntercepts("y", 1, textOrigin.fX, textOrigin.fY, bounds, nullptr);
4923 std::vector<SkScalar> intervals;
4924 intervals.resize(count);
4925 (void) paint.getTextIntercepts("y", 1, textOrigin.fX, textOrigin.fY, bounds,
4926 &intervals.front());
4927 canvas->drawString("y", textOrigin.fX, textOrigin.fY, paint);
4928 paint.setColor(SK_ColorRED);
4929 SkScalar x = textOrigin.fX;
4930 for (int i = 0; i < count; i += 2) {
4931 canvas->drawRect({x, bounds[0], intervals[i], bounds[1]}, paint);
4932 x = intervals[i + 1];
4933 }
4934 canvas->drawRect({intervals[count - 1], bounds[0],
4935 textOrigin.fX + paint.measureText("y", 1), bounds[1]}, paint);
4936}
4937##
4938
4939##
4940
4941#Method int getPosTextIntercepts(const void* text, size_t length, const SkPoint pos[],
4942 const SkScalar bounds[2], SkScalar* intervals) const
4943
4944 Returns the number of intervals that intersect bounds.
4945 bounds describes a pair of lines parallel to the text advance.
Cary Clarkce101242017-09-01 15:51:02 -04004946 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 -04004947 the string.
4948 Uses Text_Encoding to decode text, Typeface to get the glyph paths,
4949 and Text_Size, Fake_Bold, and Path_Effect to scale and modify the glyph paths.
4950 Uses pos array and Text_Align to position intervals.
4951
4952 Pass nullptr for intervals to determine the size of the interval array.
4953
4954 intervals are cached to improve performance for multiple calls.
4955
4956 #Param text character codes or glyph indices ##
4957 #Param length number of bytes of text ##
4958 #Param pos positions of each glyph ##
4959 #Param bounds lower and upper line parallel to the advance ##
4960 #Param intervals returned intersections; may be nullptr ##
4961
Cary Clarka523d2d2017-08-30 08:58:10 -04004962 #Return number of intersections; may be zero ##
Cary Clark8032b982017-07-28 11:04:54 -04004963
4964 #Example
4965 #Description
Cary Clarkce101242017-09-01 15:51:02 -04004966 Text intercepts draw on either side of, but not inside, Glyphs in a run.
Cary Clark8032b982017-07-28 11:04:54 -04004967 ##
4968 void draw(SkCanvas* canvas) {
4969 SkPaint paint;
4970 paint.setTextSize(120);
4971 paint.setVerticalText(true);
4972 SkPoint textPos[] = {{ 60, 40 }, { 60, 140 }};
4973 SkScalar bounds[] = { 56, 64 };
4974 const char str[] = "A-";
4975 int len = sizeof(str) - 1;
4976 int count = paint.getPosTextIntercepts(str, len, textPos, bounds, nullptr);
4977 std::vector<SkScalar> intervals;
4978 intervals.resize(count);
4979 (void) paint.getPosTextIntercepts(str, len, textPos, bounds, &intervals.front());
4980 canvas->drawPosText(str, len, textPos, paint);
4981 paint.setColor(SK_ColorRED);
4982 SkScalar y = textPos[0].fY;
4983 for (int i = 0; i < count; i+= 2) {
4984 canvas->drawRect({bounds[0], y, bounds[1], intervals[i]}, paint);
4985 y = intervals[i + 1];
4986 }
4987 canvas->drawRect({bounds[0], intervals[count - 1], bounds[1], 240}, paint);
4988 }
4989 ##
4990
4991##
4992
4993#Method int getPosTextHIntercepts(const void* text, size_t length, const SkScalar xpos[],
4994 SkScalar constY, const SkScalar bounds[2],
4995 SkScalar* intervals) const
4996
4997 Returns the number of intervals that intersect bounds.
4998 bounds describes a pair of lines parallel to the text advance.
Cary Clarkce101242017-09-01 15:51:02 -04004999 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 -04005000 the string.
5001 Uses Text_Encoding to decode text, Typeface to get the glyph paths,
5002 and Text_Size, Fake_Bold, and Path_Effect to scale and modify the glyph paths.
5003 Uses xpos array, constY, and Text_Align to position intervals.
5004
5005 Pass nullptr for intervals to determine the size of the interval array.
5006
5007 intervals are cached to improve performance for multiple calls.
5008
5009 #Param text character codes or glyph indices ##
5010 #Param length number of bytes of text ##
5011 #Param xpos positions of each glyph in x ##
5012 #Param constY position of each glyph in y ##
5013 #Param bounds lower and upper line parallel to the advance ##
5014 #Param intervals returned intersections; may be nullptr ##
5015
5016 #Return number of intersections; may be zero ##
5017
5018 #Example
5019 #Height 128
5020 #Description
5021 Text intercepts do not take stroke thickness into consideration.
5022 ##
5023 void draw(SkCanvas* canvas) {
5024 SkPaint paint;
5025 paint.setTextSize(120);
5026 paint.setStyle(SkPaint::kStroke_Style);
5027 paint.setStrokeWidth(4);
5028 SkScalar textPosH[] = { 20, 80, 140 };
5029 SkScalar y = 100;
5030 SkScalar bounds[] = { 56, 78 };
5031 const char str[] = "\\-/";
5032 int len = sizeof(str) - 1;
5033 int count = paint.getPosTextHIntercepts(str, len, textPosH, y, bounds, nullptr);
5034 std::vector<SkScalar> intervals;
5035 intervals.resize(count);
5036 (void) paint.getPosTextHIntercepts(str, len, textPosH, y, bounds, &intervals.front());
5037 canvas->drawPosTextH(str, len, textPosH, y, paint);
5038 paint.setColor(0xFFFF7777);
5039 paint.setStyle(SkPaint::kFill_Style);
5040 SkScalar x = textPosH[0];
5041 for (int i = 0; i < count; i+= 2) {
5042 canvas->drawRect({x, bounds[0], intervals[i], bounds[1]}, paint);
5043 x = intervals[i + 1];
5044 }
5045 canvas->drawRect({intervals[count - 1], bounds[0], 180, bounds[1]}, paint);
5046 }
5047 ##
5048
5049##
5050
5051
5052#Method int getTextBlobIntercepts(const SkTextBlob* blob, const SkScalar bounds[2],
5053 SkScalar* intervals) const
5054
5055 Returns the number of intervals that intersect bounds.
5056 bounds describes a pair of lines parallel to the text advance.
Cary Clarkce101242017-09-01 15:51:02 -04005057 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 -04005058 the string.
Cary Clark3cd22cc2017-12-01 11:49:58 -05005059 Uses Typeface to get the glyph paths,
Cary Clark8032b982017-07-28 11:04:54 -04005060 and Text_Size, Fake_Bold, and Path_Effect to scale and modify the glyph paths.
Cary Clarkce101242017-09-01 15:51:02 -04005061 Uses run array and Text_Align to position intervals.
Cary Clark8032b982017-07-28 11:04:54 -04005062
Cary Clark3cd22cc2017-12-01 11:49:58 -05005063 Text_Encoding must be set to SkPaint::kGlyphID_TextEncoding.
5064
Cary Clark8032b982017-07-28 11:04:54 -04005065 Pass nullptr for intervals to determine the size of the interval array.
5066
5067 intervals are cached to improve performance for multiple calls.
5068
Cary Clarkce101242017-09-01 15:51:02 -04005069 #Param blob Glyphs, positions, and text paint attributes ##
Cary Clark8032b982017-07-28 11:04:54 -04005070 #Param bounds lower and upper line parallel to the advance ##
5071 #Param intervals returned intersections; may be nullptr ##
5072
5073 #Return number of intersections; may be zero ##
5074
5075 #Example
5076 #Height 143
5077 void draw(SkCanvas* canvas) {
5078 SkPaint paint;
Cary Clark3cd22cc2017-12-01 11:49:58 -05005079 paint.setTextEncoding(SkPaint::kGlyphID_TextEncoding);
Cary Clark8032b982017-07-28 11:04:54 -04005080 paint.setTextSize(120);
5081 SkPoint textPos = { 20, 110 };
5082 int len = 3;
5083 SkTextBlobBuilder textBlobBuilder;
5084 const SkTextBlobBuilder::RunBuffer& run =
5085 textBlobBuilder.allocRun(paint, len, textPos.fX, textPos.fY);
5086 run.glyphs[0] = 10;
5087 run.glyphs[1] = 20;
5088 run.glyphs[2] = 30;
5089 sk_sp<const SkTextBlob> blob = textBlobBuilder.make();
5090 canvas->drawTextBlob(blob.get(), textPos.fX, textPos.fY, paint);
5091 SkScalar bounds[] = { 116, 134 };
5092 int count = paint.getTextBlobIntercepts(blob.get(), bounds, nullptr);
5093 std::vector<SkScalar> intervals;
5094 intervals.resize(count);
5095 (void) paint.getTextBlobIntercepts(blob.get(), bounds, &intervals.front());
5096 canvas->drawTextBlob(blob.get(), 0, 0, paint);
5097 paint.setColor(0xFFFF7777);
5098 SkScalar x = textPos.fX;
5099 for (int i = 0; i < count; i+= 2) {
5100 canvas->drawRect({x, bounds[0], intervals[i], bounds[1]}, paint);
5101 x = intervals[i + 1];
5102 }
5103 canvas->drawRect({intervals[count - 1], bounds[0], 180, bounds[1]}, paint);
5104 }
5105 ##
5106
5107##
5108
5109#Topic ##
5110# ------------------------------------------------------------------------------
5111
5112#Method bool nothingToDraw() const
5113
Cary Clark579985c2017-07-31 11:48:27 -04005114 Returns true if Paint prevents all drawing;
5115 otherwise, the Paint may or may not allow drawing.
Cary Clark8032b982017-07-28 11:04:54 -04005116
Cary Clarkce101242017-09-01 15:51:02 -04005117 Returns true if, for example, Blend_Mode combined with Color_Alpha computes a
5118 new Alpha of zero.
Cary Clark8032b982017-07-28 11:04:54 -04005119
5120 #Return true if Paint prevents all drawing ##
5121
5122 #Example
5123 void draw(SkCanvas* canvas) {
5124 auto debugster = [](const char* prefix, const SkPaint& p) -> void {
5125 SkDebugf("%s nothing to draw: %s\n", prefix,
5126 p.nothingToDraw() ? "true" : "false");
5127 };
5128 SkPaint paint;
5129 debugster("initial", paint);
5130 paint.setBlendMode(SkBlendMode::kDst);
5131 debugster("blend dst", paint);
5132 paint.setBlendMode(SkBlendMode::kSrcOver);
5133 debugster("blend src over", paint);
5134 paint.setAlpha(0);
5135 debugster("alpha 0", paint);
5136 }
5137
5138 #StdOut
5139 initial nothing to draw: false
5140 blend dst nothing to draw: true
5141 blend src over nothing to draw: false
5142 alpha 0 nothing to draw: true
5143 #StdOut ##
5144 ##
5145
5146##
5147
5148# ------------------------------------------------------------------------------
5149#Topic Fast_Bounds
5150 #Private
5151 To be made private.
5152 ##
5153
5154Fast_Bounds methods conservatively outset a drawing bounds by additional area
5155Paint may draw to.
5156
5157#Method bool canComputeFastBounds() const
5158 #Private
5159 (to be made private)
5160 ##
5161
5162 Returns true if Paint does not include elements requiring extensive computation
5163 to compute Device bounds of drawn geometry. For instance, Paint with Path_Effect
5164 always returns false.
5165
5166 #Return true if Paint allows for fast computation of bounds ##
5167##
5168
5169#Method const SkRect& computeFastBounds(const SkRect& orig, SkRect* storage) const
5170 #Private
5171 (to be made private)
5172 ##
5173
5174 Only call this if canComputeFastBounds returned true. This takes a
5175 raw rectangle (the raw bounds of a shape), and adjusts it for stylistic
5176 effects in the paint (e.g. stroking). If needed, it uses the storage
Cary Clarkce101242017-09-01 15:51:02 -04005177 parameter. It returns the adjusted bounds that can then be used
Cary Clark8032b982017-07-28 11:04:54 -04005178 for SkCanvas::quickReject tests.
5179
Cary Clarkce101242017-09-01 15:51:02 -04005180 The returned Rect will either be orig or storage, thus the caller
Cary Clark8032b982017-07-28 11:04:54 -04005181 should not rely on storage being set to the result, but should always
Cary Clarkce101242017-09-01 15:51:02 -04005182 use the returned value. It is legal for orig and storage to be the same
5183 Rect.
Cary Clark8032b982017-07-28 11:04:54 -04005184
5185 #Private
5186 e.g.
5187 if (paint.canComputeFastBounds()) {
5188 SkRect r, storage;
5189 path.computeBounds(&r, SkPath::kFast_BoundsType);
5190 const SkRect& fastR = paint.computeFastBounds(r, &storage);
5191 if (canvas->quickReject(fastR, ...)) {
5192 // don't draw the path
5193 }
5194 }
5195 ##
5196
5197 #Param orig geometry modified by Paint when drawn ##
5198 #Param storage computed bounds of geometry; may not be nullptr ##
5199
5200 #Return fast computed bounds ##
5201##
5202
5203#Method const SkRect& computeFastStrokeBounds(const SkRect& orig,
5204 SkRect* storage) const
5205 #Private
5206 (to be made private)
5207 ##
5208
5209 #Param orig geometry modified by Paint when drawn ##
5210 #Param storage computed bounds of geometry ##
5211
5212 #Return fast computed bounds ##
5213##
5214
5215#Method const SkRect& doComputeFastBounds(const SkRect& orig, SkRect* storage,
5216 Style style) const
5217 #Private
5218 (to be made private)
5219 ##
5220
Cary Clarkce101242017-09-01 15:51:02 -04005221 Computes the bounds, overriding the Paint Style. This can be used to
5222 account for additional width required by stroking orig, without
5223 altering Style set to fill.
Cary Clark8032b982017-07-28 11:04:54 -04005224
5225 #Param orig geometry modified by Paint when drawn ##
5226 #Param storage computed bounds of geometry ##
5227 #Param style overrides Style ##
5228
5229 #Return fast computed bounds ##
5230##
5231
5232#Topic Fast_Bounds ##
5233
5234# ------------------------------------------------------------------------------
5235#Method void toString(SkString* str) const;
5236
5237#DefinedBy SK_TO_STRING_NONVIRT() ##
5238
5239#Private
5240macro expands to: void toString(SkString* str) const;
5241##
5242
Cary Clarkce101242017-09-01 15:51:02 -04005243Creates string representation of Paint. The representation is read by
5244internal debugging tools. The interface and implementation may be
5245suppressed by defining SK_IGNORE_TO_STRING.
Cary Clark8032b982017-07-28 11:04:54 -04005246
Cary Clarkce101242017-09-01 15:51:02 -04005247#Param str storage for string representation of Paint ##
Cary Clark8032b982017-07-28 11:04:54 -04005248
5249#Example
5250 SkPaint paint;
5251 SkString str;
5252 paint.toString(&str);
5253 const char textSize[] = "TextSize:";
5254 const int trailerSize = strlen("</dd><dt>");
5255 int textSizeLoc = str.find(textSize) + strlen(textSize) + trailerSize;
5256 const char* sizeStart = &str.c_str()[textSizeLoc];
5257 int textSizeEnd = SkStrFind(sizeStart, "</dd>");
5258 SkDebugf("text size = %.*s\n", textSizeEnd, sizeStart);
5259
5260 #StdOut
5261 text size = 12
5262 ##
5263
5264##
5265
Cary Clark2ade9972017-11-02 17:49:34 -04005266#SeeAlso SkPathEffect::toString SkMaskFilter::toString SkColorFilter::toString SkImageFilter::toString
Cary Clark8032b982017-07-28 11:04:54 -04005267
5268##
5269
5270# ------------------------------------------------------------------------------
5271
5272#Class SkPaint ##
5273
5274#Topic Paint ##