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