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