blob: cfb432a1dd276c7df6ace964de26d2fa088c57f1 [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 Clarkbad5ad72017-08-03 17:14:08 -040023Path geometries with anti-aliasing, regardless of how SkPaint::kAntiAlias_Flag
24is 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. ##
49# Font_Embedded_Bitmaps # Custom-sized bitmap glyphs. ##
50# 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. ##
75# Text_Encoding # Text encoded as characters or glyphs. ##
76# Font_Metrics # Common glyph dimensions. ##
77# Measure_Text # Width, height, bounds of text. ##
78# Text_Path # Geometry of glyphs. ##
79# Text_Intercepts # Advanced underline, strike through. ##
80# Fast_Bounds # Appproxiate area required by Paint. ##
81#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. ##
142# containsText # Returns if all text corresponds to glyphs. ##
143# countText # Returns number of glyphs in text. ##
144# doComputeFastBounds # Returns bounds for quick reject tests. ##
145# flatten() # Serializes into a buffer. ##
146# getAlpha # Returns Color_Alpha, color opacity. ##
147# getBlendMode # Returns Blend_Mode, how colors combine with dest. ##
148# 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. ##
182# glyphsToUnichars # Converts glyphs into text. ##
183# isAntiAlias # Returns true if Anti-alias is set. ##
184# isAutohinted # Returns true if glyphs are always hinted. ##
185# 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. ##
207# setAutohinted # Sets glyphs to always be hinted. ##
208# 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. ##
239# toString # Converts Paint to machine parsable form (Developer_Mode) ##
240# 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 ##
258# Blend_Mode # SkBlendMode::kSrcOver ##
259# 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
293paint default values. The overrides may be included in SkUserConfig.h or predefined by the
294build 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
351 Implements a move constructor to avoid incrementing the reference counts
352 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
446Moves the paint to avoid incrementing 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
625#Param buffer serialized data to unflatten ##
626
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.
672 Generated glyphs may be fuzzy but better resemble their original shape.
673##
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 ##
736 # kSlight_Hinting # 1 # modifies glyph outlines minimally to improve constrast ##
737 # kNormal_Hinting # 2 # modifies glyph outlines to improve constrast ##
738 # kFull_Hinting # 3 # modifies glyph outlines for maxiumum constrast ##
739 ##
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
904The rule for aliased pixels is inconsistent across platforms. A shape edge
905passing through the pixel center may, but is not required to, draw the pixel.
906
907Raster_Engine draws aliased pixels whose centers are on or to the right of the start of an
908active 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
912A 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.
915
916The amount of coverage computed for anti-aliased pixels also varies across platforms.
917
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.
927 The lines are drawn into an offscreen bitmap, then drawn magified to make the
928 aliasing easier to see.
929 ##
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
1003Dither increases fidelity by adjusting the color of adjcent pixels.
1004This 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
1136on the small size of the stripe and visual perception to make the color fringing inperceptible.
1137LCD_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.
1152 When Subpixel_Text is disabled, the comma glyphs are indentical, but not evenly spaced.
1153 When Subpixel_Text is enabled, the comma glyphs are unique, but appear evenly spaced.
1154 ##
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.
1181If kLinearText_Flag is clear, it's the same as setting Hinting to kNo_Hinting.
1182
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
1257 If true, glyphs at different sub-pixel positions may differ on pixel edge coverage.
1258
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
1281 Requests, but does not require, that glyphs respect sub-pixel positioning.
1282
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
1308on the small size of the stripe and visual perception to make the color fringing inperceptible.
1309LCD_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
1314 If true, glyphs may use LCD striping to improve glyph edges.
1315
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
1338 Requests, but does not require, that glyphs use LCD striping for glyph edges.
1339
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
1366Font_Embedded_Bitmaps allows selecting custom-sized bitmap glyphs.
1367Flags 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
1383 The hintgasp TrueType font in the Skia resources/fonts directory includes an embedded
1384 bitmap glyph at odd font sizes. This example works on platforms that use FreeType
1385 as their Font_Engine.
1386 Windows may, but is not required to, return a bitmap glyph if kEmbeddedBitmapText_Flag is set.
1387 ##
1388 #Image embeddedbitmap.png
1389
1390 SkBitmap bitmap;
1391 bitmap.allocN32Pixels(30, 15);
1392 bitmap.eraseColor(0);
1393 SkCanvas offscreen(bitmap);
1394 SkPaint paint;
1395 paint.setAntiAlias(true);
1396 paint.setTextSize(13);
1397 paint.setTypeface(MakeResourceAsTypeface("/fonts/hintgasp.ttf"));
1398 for (bool embedded : { false, true}) {
1399 paint.setEmbeddedBitmapText(embedded);
1400 offscreen.drawString("A", embedded ? 5 : 15, 15, paint);
1401 }
1402 canvas->drawBitmap(bitmap, 0, 0);
1403 canvas->scale(10, 10);
1404 canvas->drawBitmap(bitmap, -2, 1);
1405##
1406
1407#Method bool isEmbeddedBitmapText() const
1408
1409 If true, Font_Engine may return glyphs from font bitmaps instead of from outlines.
1410
1411 Equivalent to getFlags masked with kEmbeddedBitmapText_Flag.
1412
1413 #Return kEmbeddedBitmapText_Flag state ##
1414
1415 #Example
1416 SkPaint paint;
1417 SkDebugf("paint.isEmbeddedBitmapText() %c="
1418 " !!(paint.getFlags() & SkPaint::kEmbeddedBitmapText_Flag)\n",
1419 paint.isEmbeddedBitmapText() ==
1420 !!(paint.getFlags() & SkPaint::kEmbeddedBitmapText_Flag) ? '=' : '!');
1421 paint.setEmbeddedBitmapText(true);
1422 SkDebugf("paint.isEmbeddedBitmapText() %c="
1423 " !!(paint.getFlags() & SkPaint::kEmbeddedBitmapText_Flag)\n",
1424 paint.isEmbeddedBitmapText() ==
1425 !!(paint.getFlags() & SkPaint::kEmbeddedBitmapText_Flag) ? '=' : '!');
1426
1427 #StdOut
1428 paint.isEmbeddedBitmapText() == !!(paint.getFlags() & SkPaint::kEmbeddedBitmapText_Flag)
1429 paint.isEmbeddedBitmapText() == !!(paint.getFlags() & SkPaint::kEmbeddedBitmapText_Flag)
1430 ##
1431 ##
1432
1433##
1434
1435#Method void setEmbeddedBitmapText(bool useEmbeddedBitmapText)
1436
1437 Requests, but does not require, to use bitmaps in fonts instead of outlines.
1438
1439 Sets kEmbeddedBitmapText_Flag if useEmbeddedBitmapText is true.
1440 Clears kEmbeddedBitmapText_Flag if useEmbeddedBitmapText is false.
1441
1442 #Param useEmbeddedBitmapText setting for kEmbeddedBitmapText_Flag ##
1443
1444 #Example
1445 SkPaint paint1, paint2;
1446 paint1.setEmbeddedBitmapText(true);
1447 paint2.setFlags(paint2.getFlags() | SkPaint::kEmbeddedBitmapText_Flag);
1448 SkDebugf("paint1 %c= paint2\n", paint1 == paint2 ? '=' : '!');
1449
1450 #StdOut
1451 paint1 == paint2
1452 ##
1453 ##
1454
1455##
1456
1457#Topic ##
1458# ------------------------------------------------------------------------------
1459#Topic Automatic_Hinting
1460#Substitute auto-hinting
1461
1462If Hinting is set to kNormal_Hinting or kFull_Hinting, Automatic_Hinting
Cary Clark1eace2d2017-07-31 07:52:43 -04001463instructs the Font_Manager to always hint glyphs.
Cary Clark8032b982017-07-28 11:04:54 -04001464Automatic_Hinting has no effect if Hinting is set to kNo_Hinting or
1465kSlight_Hinting.
1466
1467Automatic_Hinting only affects platforms that use FreeType as the Font_Manager.
1468
1469#Method bool isAutohinted() const
1470
1471 If true, and if Hinting is set to kNormal_Hinting or kFull_Hinting, and if
1472 platform uses FreeType as the Font_Manager, instruct the Font_Manager to always hint
Cary Clark1eace2d2017-07-31 07:52:43 -04001473 glyphs.
Cary Clark8032b982017-07-28 11:04:54 -04001474
1475 Equivalent to getFlags masked with kAutoHinting_Flag.
1476
1477 #Return kAutoHinting_Flag state ##
1478
1479 #Example
1480 SkPaint paint;
1481 for (auto forceAutoHinting : { false, true} ) {
1482 paint.setAutohinted(forceAutoHinting);
1483 SkDebugf("paint.isAutohinted() %c="
1484 " !!(paint.getFlags() & SkPaint::kAutoHinting_Flag)\n",
1485 paint.isAutohinted() ==
1486 !!(paint.getFlags() & SkPaint::kAutoHinting_Flag) ? '=' : '!');
1487 }
1488 #StdOut
1489 paint.isAutohinted() == !!(paint.getFlags() & SkPaint::kAutoHinting_Flag)
1490 paint.isAutohinted() == !!(paint.getFlags() & SkPaint::kAutoHinting_Flag)
1491 ##
1492 ##
1493
1494 #SeeAlso setAutohinted Hinting
1495
1496##
1497
1498#Method void setAutohinted(bool useAutohinter)
1499
1500 If Hinting is set to kNormal_Hinting or kFull_Hinting and useAutohinter is set,
Cary Clark1eace2d2017-07-31 07:52:43 -04001501 instruct the Font_Manager to always hint glyphs.
Cary Clark8032b982017-07-28 11:04:54 -04001502 Automatic_Hinting has no effect if Hinting is set to kNo_Hinting or
1503 kSlight_Hinting.
1504
Cary Clark579985c2017-07-31 11:48:27 -04001505 Only affects platforms that use FreeType as the Font_Manager.
Cary Clark8032b982017-07-28 11:04:54 -04001506
1507 Sets kAutoHinting_Flag if useAutohinter is true.
1508 Clears kAutoHinting_Flag if useAutohinter is false.
1509
1510 #Param useAutohinter setting for kAutoHinting_Flag ##
1511
1512 #Example
1513 void draw(SkCanvas* canvas) {
1514 SkPaint paint;
1515 paint.setAntiAlias(true);
1516 const char testStr[] = "xxxx xxxx";
1517 for (auto forceAutoHinting : { false, true} ) {
1518 paint.setAutohinted(forceAutoHinting);
1519 paint.setTextSize(24);
1520 canvas->drawString(paint.isAutohinted() ? "auto-hinted" : "default", 108, 30, paint);
1521 for (SkScalar textSize = 8; textSize < 30; textSize *= 1.22f) {
1522 paint.setTextSize(textSize);
1523 canvas->translate(0, textSize);
1524 canvas->drawString(testStr, 10, 0, paint);
1525 }
1526 }
1527 }
1528 ##
1529
1530 #SeeAlso isAutohinted Hinting
1531
1532##
1533
1534#Topic ##
1535# ------------------------------------------------------------------------------
1536#Topic Vertical_Text
1537
1538Text may be drawn by positioning each glyph, or by positioning the first glyph and
1539using Font_Advance to position subsequent glyphs. By default, each successive glyph
1540is positioned to the right of the preceeding glyph. Vertical_Text sets successive
1541glyphs to position below the preceeding glyph.
1542
1543Skia can translate text character codes as a series of glyphs, but does not implement
1544font substitution,
1545textual substitution, line layout, or contextual spacing like kerning pairs. Use
1546a text shaping engine like #A HarfBuzz # http://harfbuzz.org/ ## to translate text runs
1547into glyph series.
1548
1549Vertical_Text is clear if text is drawn left to right or set if drawn from top to bottom.
1550
1551Flags kVerticalText_Flag if clear draws text left to right.
1552Flags kVerticalText_Flag if set draws text top to bottom.
1553
1554Vertical_Text is clear by default.
1555Vertical_Text can be set by default by setting SkPaintDefaults_Flags to
1556kVerticalText_Flag at compile time.
1557
1558#Example
1559
1560void draw(SkCanvas* canvas) {
1561 SkPaint paint;
1562 paint.setAntiAlias(true);
1563 paint.setTextSize(50);
1564 for (bool vertical : { false, true } ) {
1565 paint.setVerticalText(vertical);
1566 canvas->drawString("aAlL", 25, 50, paint);
1567 }
1568}
1569
1570##
1571
1572#Method bool isVerticalText() const
1573
1574 If true, glyphs are drawn top to bottom instead of left to right.
1575
1576 Equivalent to getFlags masked with kVerticalText_Flag.
1577
1578 #Return kVerticalText_Flag state ##
1579
1580 #Example
1581 SkPaint paint;
1582 SkDebugf("paint.isVerticalText() %c= !!(paint.getFlags() & SkPaint::kVerticalText_Flag)\n",
1583 paint.isVerticalText() == !!(paint.getFlags() & SkPaint::kVerticalText_Flag) ? '=' : '!');
1584 paint.setVerticalText(true);
1585 SkDebugf("paint.isVerticalText() %c= !!(paint.getFlags() & SkPaint::kVerticalText_Flag)\n",
1586 paint.isVerticalText() == !!(paint.getFlags() & SkPaint::kVerticalText_Flag) ? '=' : '!');
1587
1588 #StdOut
1589 paint.isVerticalText() == !!(paint.getFlags() & SkPaint::kVerticalText_Flag)
1590 paint.isVerticalText() == !!(paint.getFlags() & SkPaint::kVerticalText_Flag)
1591 ##
1592 ##
1593
1594##
1595
1596#Method void setVerticalText(bool verticalText)
1597
1598 If true, text advance positions the next glyph below the previous glyph instead of to the
1599 right of previous glyph.
1600
1601 Sets kVerticalText_Flag if vertical is true.
1602 Clears kVerticalText_Flag if vertical is false.
1603
1604 #Param verticalText setting for kVerticalText_Flag ##
1605
1606 #Example
1607 SkPaint paint1, paint2;
1608 paint1.setVerticalText(true);
1609 paint2.setFlags(paint2.getFlags() | SkPaint::kVerticalText_Flag);
1610 SkDebugf("paint1 %c= paint2\n", paint1 == paint2 ? '=' : '!');
1611
1612 #StdOut
1613 paint1 == paint2
1614 ##
1615 ##
1616
1617##
1618
1619#Topic ##
1620# ------------------------------------------------------------------------------
1621
1622#Topic Fake_Bold
1623
1624Fake_Bold approximates the bold font style accompanying a normal font when a bold font face
1625is not available. Skia does not provide font substitution; it is up to the client to find the
1626bold font face using the platform's Font_Manager.
1627
1628Use Text_Skew_X to approximate an italic font style when the italic font face
1629is not available.
1630
1631A FreeType-based port may define SK_USE_FREETYPE_EMBOLDEN at compile time to direct
1632the font engine to create the bold glyphs. Otherwise, the extra bold is computed
1633by increasing the stroke width and setting the Style to kStrokeAndFill_Style as needed.
1634
1635Fake_Bold is disabled by default.
1636
1637#Example
1638#Height 128
1639void draw(SkCanvas* canvas) {
1640 SkPaint paint;
1641 paint.setAntiAlias(true);
1642 paint.setTextSize(40);
1643 canvas->drawString("OjYy_-", 10, 35, paint);
1644 paint.setFakeBoldText(true);
1645 canvas->drawString("OjYy_-", 10, 75, paint);
1646 // create a custom fake bold by varying the stroke width
1647 paint.setFakeBoldText(false);
1648 paint.setStyle(SkPaint::kStrokeAndFill_Style);
1649 paint.setStrokeWidth(40.f / 48);
1650 canvas->drawString("OjYy_-", 10, 115, paint);
1651}
1652##
1653
1654#Method bool isFakeBoldText() const
1655
1656 If true, approximate bold by increasing the stroke width when creating glyph bitmaps
1657 from outlines.
1658
1659 Equivalent to getFlags masked with kFakeBoldText_Flag.
1660
1661 #Return kFakeBoldText_Flag state ##
1662
1663 #Example
1664 SkPaint paint;
1665 SkDebugf("paint.isFakeBoldText() %c= !!(paint.getFlags() & SkPaint::kFakeBoldText_Flag)\n",
1666 paint.isFakeBoldText() == !!(paint.getFlags() & SkPaint::kFakeBoldText_Flag) ? '=' : '!');
1667 paint.setFakeBoldText(true);
1668 SkDebugf("paint.isFakeBoldText() %c= !!(paint.getFlags() & SkPaint::kFakeBoldText_Flag)\n",
1669 paint.isFakeBoldText() == !!(paint.getFlags() & SkPaint::kFakeBoldText_Flag) ? '=' : '!');
1670
1671 #StdOut
1672 paint.isFakeBoldText() == !!(paint.getFlags() & SkPaint::kFakeBoldText_Flag)
1673 paint.isFakeBoldText() == !!(paint.getFlags() & SkPaint::kFakeBoldText_Flag)
1674 ##
1675 ##
1676
1677##
1678
1679#Method void setFakeBoldText(bool fakeBoldText)
1680
1681 Use increased stroke width when creating glyph bitmaps to approximate bolding.
1682
1683 Sets kFakeBoldText_Flag if fakeBoldText is true.
1684 Clears kFakeBoldText_Flag if fakeBoldText is false.
1685
1686 #Param fakeBoldText setting for kFakeBoldText_Flag ##
1687
1688 #Example
1689 SkPaint paint1, paint2;
1690 paint1.setFakeBoldText(true);
1691 paint2.setFlags(paint2.getFlags() | SkPaint::kFakeBoldText_Flag);
1692 SkDebugf("paint1 %c= paint2\n", paint1 == paint2 ? '=' : '!');
1693
1694 #StdOut
1695 paint1 == paint2
1696 ##
1697 ##
1698
1699##
1700
1701#Topic ##
1702
1703# ------------------------------------------------------------------------------
1704#Topic Full_Hinting_Spacing
1705#Alias Full_Hinting_Spacing # long winded enough -- maybe things with two underscores auto-aliased?
1706
1707Full_Hinting_Spacing adjusts the character spacing by the difference of the
1708hinted and unhinted left and right side bearings,
1709if Hinting is set to kFull_Hinting. Full_Hinting_Spacing only
1710applies to platforms that use FreeType as their Font_Engine.
1711
1712Full_Hinting_Spacing is not related to text kerning, where the space between
1713a specific pair of characters is adjusted using data in the font's kerning tables.
1714
1715#Method bool isDevKernText() const
1716
1717 Returns if character spacing may be adjusted by the hinting difference.
1718
1719 Equivalent to getFlags masked with kDevKernText_Flag.
1720
1721 #Return kDevKernText_Flag state ##
1722
1723 #Example
1724 SkPaint paint;
1725 SkDebugf("paint.isDevKernText() %c= !!(paint.getFlags() & SkPaint::kDevKernText_Flag)\n",
1726 paint.isDevKernText() == !!(paint.getFlags() & SkPaint::kDevKernText_Flag) ? '=' : '!');
1727 paint.setDevKernText(true);
1728 SkDebugf("paint.isDevKernText() %c= !!(paint.getFlags() & SkPaint::kDevKernText_Flag)\n",
1729 paint.isDevKernText() == !!(paint.getFlags() & SkPaint::kDevKernText_Flag) ? '=' : '!');
1730 ##
1731
1732##
1733
1734#Method void setDevKernText(bool devKernText)
1735
1736 Requests, but does not require, to use hinting to adjust glyph spacing.
1737
1738 Sets kDevKernText_Flag if devKernText is true.
1739 Clears kDevKernText_Flag if devKernText is false.
1740
1741 #Param devKernText setting for devKernText ##
1742
1743 #Example
1744 SkPaint paint1, paint2;
1745 paint1.setDevKernText(true);
1746 paint2.setFlags(paint2.getFlags() | SkPaint::kDevKernText_Flag);
1747 SkDebugf("paint1 %c= paint2\n", paint1 == paint2 ? '=' : '!');
1748
1749 #StdOut
1750 paint1 == paint2
1751 ##
1752 ##
1753
1754##
1755
1756#Topic ##
1757# ------------------------------------------------------------------------------
1758#Topic Filter_Quality_Methods
1759
1760Filter_Quality trades speed for image filtering when the image is scaled.
1761A lower Filter_Quality draws faster, but has less fidelity.
1762A higher Filter_Quality draws slower, but looks better.
1763If the image is unscaled, the Filter_Quality choice will not result in a noticable
1764difference.
1765
1766Filter_Quality is used in Paint passed as a parameter to
1767#List
1768# SkCanvas::drawBitmap ##
1769# SkCanvas::drawBitmapRect ##
1770# SkCanvas::drawImage ##
1771# SkCanvas::drawImageRect ##
1772 #ToDo probably more... ##
1773#List ##
1774and when Paint has a Shader specialization that uses Image or Bitmap.
1775
1776Filter_Quality is kNone_SkFilterQuality by default.
1777
1778#Example
1779#Image 3
1780void draw(SkCanvas* canvas) {
1781 SkPaint paint;
1782 canvas->scale(.2f, .2f);
1783 for (SkFilterQuality q : { kNone_SkFilterQuality, kLow_SkFilterQuality,
1784 kMedium_SkFilterQuality, kHigh_SkFilterQuality } ) {
1785 paint.setFilterQuality(q);
1786 canvas->drawImage(image.get(), 0, 0, &paint);
1787 canvas->translate(550, 0);
1788 if (kLow_SkFilterQuality == q) canvas->translate(-1100, 550);
1789 }
1790}
1791##
1792
1793#Method SkFilterQuality getFilterQuality() const
1794
1795Returns Filter_Quality, the image filtering level. A lower setting
1796draws faster; a higher setting looks better when the image is scaled.
1797
1798#Return one of: kNone_SkFilterQuality, kLow_SkFilterQuality,
1799 kMedium_SkFilterQuality, kHigh_SkFilterQuality
1800#Return ##
1801
1802#Example
1803 SkPaint paint;
1804 SkDebugf("kNone_SkFilterQuality %c= paint.getFilterQuality()\n",
1805 kNone_SkFilterQuality == paint.getFilterQuality() ? '=' : '!');
1806
1807 #StdOut
1808 kNone_SkFilterQuality == paint.getFilterQuality()
1809 ##
1810##
1811
1812##
1813
1814
1815#Method void setFilterQuality(SkFilterQuality quality)
1816
1817Sets Filter_Quality, the image filtering level. A lower setting
1818draws faster; a higher setting looks better when the image is scaled.
Cary Clark579985c2017-07-31 11:48:27 -04001819Does not check to see if quality is valid.
Cary Clark8032b982017-07-28 11:04:54 -04001820
1821#Param quality one of: kNone_SkFilterQuality, kLow_SkFilterQuality,
1822 kMedium_SkFilterQuality, kHigh_SkFilterQuality
1823##
1824
1825#Example
1826 SkPaint paint;
1827 paint.setFilterQuality(kHigh_SkFilterQuality);
1828 SkDebugf("kHigh_SkFilterQuality %c= paint.getFilterQuality()\n",
1829 kHigh_SkFilterQuality == paint.getFilterQuality() ? '=' : '!');
1830
1831 #StdOut
1832 kHigh_SkFilterQuality == paint.getFilterQuality()
1833 ##
1834##
1835
1836#SeeAlso SkFilterQuality Image_Scaling
1837
1838##
1839
1840#Topic ##
1841# ------------------------------------------------------------------------------
1842#Topic Color_Methods
1843
1844Color specifies the Color_RGB_Red, Color_RGB_Blue, Color_RGB_Green, and Color_Alpha values used to draw a filled
1845or stroked shape in a
184632-bit value. Each component occupies 8-bits, ranging from zero: no contribution;
1847to 255: full intensity. All values in any combination are valid.
1848
1849Color is not premultiplied;
1850Color_Alpha sets the transparency independent of Color_RGB: Color_RGB_Red, Color_RGB_Blue, and Color_RGB_Green.
1851
1852The bit positions of Color_Alpha and Color_RGB are independent of the bit positions
1853on the output device, which may have more or fewer bits, and may have a different arrangement.
1854
1855#Table
1856#Legend
1857# bit positions # Color_Alpha # Color_RGB_Red # Color_RGB_Blue # Color_RGB_Green ##
1858#Legend ##
1859# # 31 - 24 # 23 - 16 # 15 - 8 # 7 - 0 ##
1860#Table ##
1861
1862#Example
1863#Height 128
1864 void draw(SkCanvas* canvas) {
1865 SkPaint paint;
1866 paint.setColor(0x8000FF00); // transparent green
1867 canvas->drawCircle(50, 50, 40, paint);
1868 paint.setARGB(128, 255, 0, 0); // transparent red
1869 canvas->drawCircle(80, 50, 40, paint);
1870 paint.setColor(SK_ColorBLUE);
1871 paint.setAlpha(0x80);
1872 canvas->drawCircle(65, 65, 40, paint);
1873 }
1874##
1875
1876#Method SkColor getColor() const
1877
1878 Retrieves Color_Alpha and Color_RGB, unpremultiplied, packed into 32 bits.
1879 Use helpers SkColorGetA, SkColorGetR, SkColorGetG, and SkColorGetB to extract
1880 a color component.
1881
1882 #Return Unpremultiplied Color_ARGB ##
1883
1884 #Example
1885 SkPaint paint;
1886 paint.setColor(SK_ColorYELLOW);
1887 SkColor y = paint.getColor();
1888 SkDebugf("Yellow is %d%% red, %d%% green, and %d%% blue.\n", (int) (SkColorGetR(y) / 2.55f),
1889 (int) (SkColorGetG(y) / 2.55f), (int) (SkColorGetB(y) / 2.55f));
1890
1891 #StdOut
1892 Yellow is 100% red, 100% green, and 0% blue.
1893 ##
1894 ##
1895
1896 #SeeAlso SkColor
1897
1898##
1899
1900#Method void setColor(SkColor color)
1901
1902 Sets Color_Alpha and Color_RGB used when stroking and filling. The color is a 32-bit value,
1903 unpremutiplied, packing 8-bit components for Color_Alpha, Color_RGB_Red, Color_RGB_Blue, and Color_RGB_Green.
1904
1905 #Param color Unpremultiplied Color_ARGB ##
1906
1907 #Example
1908 SkPaint green1, green2;
1909 unsigned a = 255;
1910 unsigned r = 0;
1911 unsigned g = 255;
1912 unsigned b = 0;
1913 green1.setColor((a << 24) + (r << 16) + (g << 8) + (b << 0));
1914 green2.setColor(0xFF00FF00);
1915 SkDebugf("green1 %c= green2\n", green1 == green2 ? '=' : '!');
1916
1917 #StdOut
1918 green1 == green2
1919 ##
1920 ##
1921
1922 #SeeAlso SkColor setARGB SkColorSetARGB
1923
1924##
1925
1926#Subtopic Alpha_Methods
1927
1928Color_Alpha sets the transparency independent of Color_RGB: Color_RGB_Red, Color_RGB_Blue, and Color_RGB_Green.
1929
1930#Method uint8_t getAlpha() const
1931
1932 Retrieves Color_Alpha from the Color used when stroking and filling.
1933
1934 #Return Color_Alpha ranging from zero, fully transparent, to 255, fully opaque ##
1935
1936 #Example
1937 SkPaint paint;
1938 SkDebugf("255 %c= paint.getAlpha()\n", 255 == paint.getAlpha() ? '=' : '!');
1939
1940 #StdOut
1941 255 == paint.getAlpha()
1942 ##
1943 ##
1944
1945##
1946
1947#Method void setAlpha(U8CPU a)
1948
1949 Replaces Color_Alpha, leaving Color_RGB
1950 unchanged. An out of range value triggers an assert in the debug
1951 build. a is a value from zero to 255.
1952 a set to zero makes Color fully transparent; a set to 255 makes Color
1953 fully opaque.
1954
1955 #Param a Color_Alpha component of Color ##
1956
1957 #Example
1958 SkPaint paint;
1959 paint.setColor(0x00112233);
1960 paint.setAlpha(0x44);
1961 SkDebugf("0x44112233 %c= paint.getColor()\n", 0x44112233 == paint.getColor() ? '=' : '!');
1962
1963 #StdOut
1964 0x44112233 == paint.getColor()
1965 ##
1966 ##
1967
1968##
1969
1970#Subtopic ##
1971
1972#Method void setARGB(U8CPU a, U8CPU r, U8CPU g, U8CPU b)
1973
1974 Sets Color used when drawing solid fills. The color components range from 0 to 255.
1975 The color is unpremultiplied;
1976 Color_Alpha sets the transparency independent of Color_RGB.
1977
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
2036#ToDo what is the description of anti-aliased hairlines? ##
2037
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.
2065 Applies to Rect, Region, Round_Rect, Circle, Oval, Path, and Text.
2066 Bitmap, Image, Patch, Region, Sprite, and Vertices are painted as if
2067 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.
2075 Applies to Rect, Region, Round_Rect, Arc, Circle, Oval,
2076 Path, and Text.
2077 Arc, Line, Point, and Point_Array are always drawn as if kStroke_Style is set,
2078 and ignore the set Style.
2079 The stroke construction is unaffected by the Path_Fill_Type.
2080##
2081
2082#Const kStrokeAndFill_Style 2
2083 Set to stroke and fill geometry.
2084 Applies to Rect, Region, Round_Rect, Circle, Oval, Path, and Text.
2085 Path is treated as if it is set to SkPath::kWinding_FillType,
2086 and the set Path_Fill_Type is ignored.
2087##
2088
2089#Enum ##
2090
2091#Enum
2092
2093#Code
2094 enum {
Cary Clarkbad5ad72017-08-03 17:14:08 -04002095 kStyleCount = kStrokeAndFill_Style + 1,
Cary Clark8032b982017-07-28 11:04:54 -04002096 };
2097##
2098
2099#Const kStyleCount 3
2100The number of different Style values defined.
2101May be used to verify that Style is a legal value.
2102##
2103
2104#Enum ##
2105
2106#Method Style getStyle() const
2107
2108 Whether the geometry is filled, stroked, or filled and stroked.
2109
2110 #Return one of:kFill_Style, kStroke_Style, kStrokeAndFill_Style ##
2111
2112 #Example
2113 SkPaint paint;
2114 SkDebugf("SkPaint::kFill_Style %c= paint.getStyle()\n",
2115 SkPaint::kFill_Style == paint.getStyle() ? '=' : '!');
2116
2117 #StdOut
2118 SkPaint::kFill_Style == paint.getStyle()
2119 ##
2120 ##
2121
2122#SeeAlso Style setStyle
2123##
2124
2125#Method void setStyle(Style style)
2126
2127 Sets whether the geometry is filled, stroked, or filled and stroked.
2128 Has no effect if style is not a legal Style value.
2129
2130 #Param style one of: kFill_Style, kStroke_Style, kStrokeAndFill_Style
2131 ##
2132
2133 #Example
2134 void draw(SkCanvas* canvas) {
2135 SkPaint paint;
2136 paint.setStrokeWidth(5);
2137 SkRegion region;
2138 region.op(140, 10, 160, 30, SkRegion::kUnion_Op);
2139 region.op(170, 40, 190, 60, SkRegion::kUnion_Op);
2140 SkBitmap bitmap;
2141 bitmap.setInfo(SkImageInfo::MakeA8(50, 50), 50);
2142 uint8_t pixels[50][50];
2143 for (int x = 0; x < 50; ++x) {
2144 for (int y = 0; y < 50; ++y) {
2145 pixels[y][x] = (x + y) % 5 ? 0xFF : 0x00;
2146 }
2147 }
2148 bitmap.setPixels(pixels);
2149 for (auto style : { SkPaint::kFill_Style,
2150 SkPaint::kStroke_Style,
2151 SkPaint::kStrokeAndFill_Style }) {
2152 paint.setStyle(style);
2153 canvas->drawLine(10, 10, 60, 60, paint);
2154 canvas->drawRect({80, 10, 130, 60}, paint);
2155 canvas->drawRegion(region, paint);
2156 canvas->drawBitmap(bitmap, 200, 10, &paint);
2157 canvas->translate(0, 80);
2158 }
2159 }
2160 ##
2161
2162#SeeAlso Style getStyle
2163##
2164
2165#SeeAlso Path_Fill_Type Path_Effect Style_Fill Style_Stroke
2166#Topic Style ##
2167
2168# ------------------------------------------------------------------------------
2169#Topic Stroke_Width
2170
2171Stroke_Width sets the width for stroking. The width is the thickness
2172of the stroke perpendicular to the path's direction when the paint's style is
2173set to kStroke_Style or kStrokeAndFill_Style.
2174
2175When width is greater than zero, the stroke encompasses as many pixels partially
2176or fully as needed. When the width equals zero, the paint enables hairlines;
2177the stroke is always one pixel wide.
2178
2179The stroke's dimensions are scaled by the canvas matrix, but Hairline stroke
2180remains one pixel wide regardless of scaling.
2181
2182The default width for the paint is zero.
2183
2184#Example
2185#Height 170
2186 #Platform raster gpu
2187 #Description
2188 The pixels hit to represent thin lines vary with the angle of the
2189 line and the platform's implementation.
2190 ##
2191 void draw(SkCanvas* canvas) {
2192 SkPaint paint;
2193 for (bool antialias : { false, true }) {
2194 paint.setAntiAlias(antialias);
2195 for (int width = 0; width <= 4; ++width) {
2196 SkScalar offset = antialias * 100 + width * 20;
2197 paint.setStrokeWidth(width * 0.25f);
2198 canvas->drawLine(10 + offset, 10, 20 + offset, 60, paint);
2199 canvas->drawLine(10 + offset, 110, 60 + offset, 160, paint);
2200 }
2201 }
2202 }
2203##
2204
2205#Method SkScalar getStrokeWidth() const
2206
2207 Returns the thickness of the pen used by Paint to
2208 outline the shape.
2209
2210 #Return zero for Hairline, greater than zero for pen thickness ##
2211
2212 #Example
2213 SkPaint paint;
2214 SkDebugf("0 %c= paint.getStrokeWidth()\n", 0 == paint.getStrokeWidth() ? '=' : '!');
2215
2216 #StdOut
2217 0 == paint.getStrokeWidth()
2218 ##
2219 ##
2220
2221##
2222
2223#Method void setStrokeWidth(SkScalar width)
2224
2225 Sets the thickness of the pen used by the paint to
2226 outline the shape.
2227 Has no effect if width is less than zero.
2228
2229 #Param width zero thickness for Hairline; greater than zero for pen thickness
2230 ##
2231
2232 #Example
2233 SkPaint paint;
2234 paint.setStrokeWidth(5);
2235 paint.setStrokeWidth(-1);
2236 SkDebugf("5 %c= paint.getStrokeWidth()\n", 5 == paint.getStrokeWidth() ? '=' : '!');
2237
2238 #StdOut
2239 5 == paint.getStrokeWidth()
2240 ##
2241 ##
2242
2243##
2244
2245#Topic ##
2246# ------------------------------------------------------------------------------
2247#Topic Miter_Limit
2248
2249Miter_Limit specifies the maximum miter length,
2250relative to the stroke width.
2251
2252Miter_Limit is used when the Stroke_Join
2253is set to kMiter_Join, and the Style is either kStroke_Style
2254or kStrokeAndFill_Style.
2255
2256If the miter at a corner exceeds this limit, kMiter_Join
2257is replaced with kBevel_Join.
2258
2259Miter_Limit can be computed from the corner angle:
2260
2261#Formula
2262 miter limit = 1 / sin ( angle / 2 )
2263#Formula ##
2264
2265Miter_Limit default value is 4.
2266The default may be changed at compile time by setting SkPaintDefaults_MiterLimit
2267in SkUserConfig.h or as a define supplied by the build environment.
2268
2269Here are some miter limits and the angles that triggers them.
2270#Table
2271#Legend
2272 # miter limit # angle in degrees ##
2273#Legend ##
2274 # 10 # 11.48 ##
2275 # 9 # 12.76 ##
2276 # 8 # 14.36 ##
2277 # 7 # 16.43 ##
2278 # 6 # 19.19 ##
2279 # 5 # 23.07 ##
2280 # 4 # 28.96 ##
2281 # 3 # 38.94 ##
2282 # 2 # 60 ##
2283 # 1 # 180 ##
2284#Table ##
2285
2286#Example
2287 #Height 170
2288 #Width 384
2289 #Description
2290 This example draws a stroked corner and the miter length beneath.
2291 When the miter limit is decreased slightly, the miter join is replaced
2292 by a bevel join.
2293 ##
2294 void draw(SkCanvas* canvas) {
2295 SkPoint pts[] = {{ 10, 50 }, { 110, 80 }, { 10, 110 }};
2296 SkVector v[] = { pts[0] - pts[1], pts[2] - pts[1] };
2297 SkScalar angle1 = SkScalarATan2(v[0].fY, v[0].fX);
2298 SkScalar angle2 = SkScalarATan2(v[1].fY, v[1].fX);
2299 const SkScalar strokeWidth = 20;
2300 SkScalar miterLimit = 1 / SkScalarSin((angle2 - angle1) / 2);
2301 SkScalar miterLength = strokeWidth * miterLimit;
2302 SkPath path;
2303 path.moveTo(pts[0]);
2304 path.lineTo(pts[1]);
2305 path.lineTo(pts[2]);
2306 SkPaint paint; // set to default kMiter_Join
2307 paint.setAntiAlias(true);
2308 paint.setStyle(SkPaint::kStroke_Style);
2309 paint.setStrokeMiter(miterLimit);
2310 paint.setStrokeWidth(strokeWidth);
2311 canvas->drawPath(path, paint);
2312 paint.setStrokeWidth(1);
2313 canvas->drawLine(pts[1].fX - miterLength / 2, pts[1].fY + 50,
2314 pts[1].fX + miterLength / 2, pts[1].fY + 50, paint);
2315 canvas->translate(200, 0);
2316 miterLimit *= 0.99f;
2317 paint.setStrokeMiter(miterLimit);
2318 paint.setStrokeWidth(strokeWidth);
2319 canvas->drawPath(path, paint);
2320 paint.setStrokeWidth(1);
2321 canvas->drawLine(pts[1].fX - miterLength / 2, pts[1].fY + 50,
2322 pts[1].fX + miterLength / 2, pts[1].fY + 50, paint);
2323 }
2324##
2325
2326#Method SkScalar getStrokeMiter() const
2327
2328 The limit at which a sharp corner is drawn beveled.
2329
2330 #Return zero and greater Miter_Limit ##
2331
2332 #Example
2333 SkPaint paint;
2334 SkDebugf("default miter limit == %g\n", paint.getStrokeMiter());
2335
2336 #StdOut
2337 default miter limit == 4
2338 ##
2339 ##
2340
2341 #SeeAlso Miter_Limit setStrokeMiter Join
2342
2343##
2344
2345#Method void setStrokeMiter(SkScalar miter)
2346
2347 The limit at which a sharp corner is drawn beveled.
2348 Valid values are zero and greater.
2349 Has no effect if miter is less than zero.
2350
2351 #Param miter zero and greater Miter_Limit
2352 ##
2353
2354 #Example
2355 SkPaint paint;
2356 paint.setStrokeMiter(8);
2357 paint.setStrokeMiter(-1);
2358 SkDebugf("default miter limit == %g\n", paint.getStrokeMiter());
2359
2360 #StdOut
2361 default miter limit == 8
2362 ##
2363 ##
2364
2365 #SeeAlso Miter_Limit getStrokeMiter Join
2366
2367##
2368
2369#Topic ##
2370# ------------------------------------------------------------------------------
2371#Topic Stroke_Cap
2372
2373#Enum Cap
2374
2375#Code
2376 enum Cap {
2377 kButt_Cap,
2378 kRound_Cap,
2379 kSquare_Cap,
2380
2381 kLast_Cap = kSquare_Cap,
Cary Clarkbad5ad72017-08-03 17:14:08 -04002382 kDefault_Cap = kButt_Cap,
Cary Clark8032b982017-07-28 11:04:54 -04002383 };
2384 static constexpr int kCapCount = kLast_Cap + 1;
2385##
2386
2387Stroke_Cap draws at the beginning and end of an open Path_Contour.
2388
2389 #Const kButt_Cap 0
2390 Does not extend the stroke past the beginning or the end.
2391 ##
2392 #Const kRound_Cap 1
2393 Adds a circle with a diameter equal to Stroke_Width at the beginning
2394 and end.
2395 ##
2396 #Const kSquare_Cap 2
2397 Adds a square with sides equal to Stroke_Width at the beginning
2398 and end. The square sides are parallel to the initial and final direction
2399 of the stroke.
2400 ##
2401 #Const kLast_Cap 2
2402 Equivalent to the largest value for Stroke_Cap.
2403 ##
2404 #Const kDefault_Cap 0
2405 Equivalent to kButt_Cap.
2406 Stroke_Cap is set to kButt_Cap by default.
2407 ##
2408
2409 #Const kCapCount 3
2410 The number of different Stroke_Cap values defined.
2411 May be used to verify that Stroke_Cap is a legal value.
2412 ##
2413#Enum ##
2414
2415Stroke describes the area covered by a pen of Stroke_Width as it
2416follows the Path_Contour, moving parallel to the contours's direction.
2417
2418If the Path_Contour is not terminated by SkPath::kClose_Verb, the contour has a
2419visible beginning and end.
2420
2421Path_Contour may start and end at the same point; defining Zero_Length_Contour.
2422
2423kButt_Cap and Zero_Length_Contour is not drawn.
2424kRound_Cap and Zero_Length_Contour draws a circle of diameter Stroke_Width
2425at the contour point.
2426kSquare_Cap and Zero_Length_Contour draws an upright square with a side of
2427Stroke_Width at the contour point.
2428
2429Stroke_Cap is kButt_Cap by default.
2430
2431#Example
2432 SkPaint paint;
2433 paint.setStyle(SkPaint::kStroke_Style);
2434 paint.setStrokeWidth(20);
2435 SkPath path;
2436 path.moveTo(30, 30);
2437 path.lineTo(30, 30);
2438 path.moveTo(70, 30);
2439 path.lineTo(90, 40);
2440 for (SkPaint::Cap c : { SkPaint::kButt_Cap, SkPaint::kRound_Cap, SkPaint::kSquare_Cap } ) {
2441 paint.setStrokeCap(c);
2442 canvas->drawPath(path, paint);
2443 canvas->translate(0, 70);
2444 }
2445##
2446
2447#Method Cap getStrokeCap() const
2448
2449 The geometry drawn at the beginning and end of strokes.
2450
2451 #Return one of: kButt_Cap, kRound_Cap, kSquare_Cap ##
2452
2453 #Example
2454 SkPaint paint;
2455 SkDebugf("kButt_Cap %c= default stroke cap\n",
2456 SkPaint::kButt_Cap == paint.getStrokeCap() ? '=' : '!');
2457
2458 #StdOut
2459 kButt_Cap == default stroke cap
2460 ##
2461 ##
2462
2463 #SeeAlso Stroke_Cap setStrokeCap
2464##
2465
2466#Method void setStrokeCap(Cap cap)
2467
2468 The geometry drawn at the beginning and end of strokes.
2469
2470 #Param cap one of: kButt_Cap, kRound_Cap, kSquare_Cap;
2471 has no effect if cap is not valid
2472 ##
2473
2474 #Example
2475 SkPaint paint;
2476 paint.setStrokeCap(SkPaint::kRound_Cap);
2477 paint.setStrokeCap((SkPaint::Cap) SkPaint::kCapCount);
2478 SkDebugf("kRound_Cap %c= paint.getStrokeCap()\n",
2479 SkPaint::kRound_Cap == paint.getStrokeCap() ? '=' : '!');
2480
2481 #StdOut
2482 kRound_Cap == paint.getStrokeCap()
2483 ##
2484 ##
2485
2486 #SeeAlso Stroke_Cap getStrokeCap
2487##
2488
2489#Topic ##
2490# ------------------------------------------------------------------------------
2491#Topic Stroke_Join
2492
2493Stroke_Join draws at the sharp corners of an open or closed Path_Contour.
2494
2495Stroke describes the area covered by a pen of Stroke_Width as it
2496follows the Path_Contour, moving parallel to the contours's direction.
2497
2498If the contour direction changes abruptly, because the tangent direction leading
2499to the end of a curve within the contour does not match the tangent direction of
2500the following curve, the pair of curves meet at Stroke_Join.
2501
2502#Example
2503 SkPaint paint;
2504 paint.setStyle(SkPaint::kStroke_Style);
2505 paint.setStrokeWidth(20);
2506 SkPath path;
2507 path.moveTo(30, 30);
2508 path.lineTo(40, 50);
2509 path.conicTo(70, 30, 100, 30, .707f);
2510 for (SkPaint::Join j : { SkPaint::kMiter_Join, SkPaint::kRound_Join, SkPaint::kBevel_Join } ) {
2511 paint.setStrokeJoin(j);
2512 canvas->drawPath(path, paint);
2513 canvas->translate(0, 70);
2514 }
2515##
2516
2517#Enum Join
2518#Code
2519 enum Join {
2520 kMiter_Join,
2521 kRound_Join,
2522 kBevel_Join,
2523
2524 kLast_Join = kBevel_Join,
Cary Clarkbad5ad72017-08-03 17:14:08 -04002525 kDefault_Join = kMiter_Join,
Cary Clark8032b982017-07-28 11:04:54 -04002526 };
2527 static constexpr int kJoinCount = kLast_Join + 1;
2528##
2529
Cary Clark1eace2d2017-07-31 07:52:43 -04002530Join specifies how corners are drawn when a shape is stroked. Join
Cary Clark8032b982017-07-28 11:04:54 -04002531affects the four corners of a stroked rectangle, and the connected segments in a
2532stroked path.
2533
2534Choose miter join to draw sharp corners. Choose round join to draw a circle with a
2535radius equal to the stroke width on top of the corner. Choose bevel join to minimally
2536connect the thick strokes.
2537
2538The fill path constructed to describe the stroked path respects the join setting but may
2539not contain the actual join. For instance, a fill path constructed with round joins does
2540not necessarily include circles at each connected segment.
2541
2542#Const kMiter_Join 0
2543 Extends the outside corner to the extent allowed by Miter_Limit.
2544 If the extension exceeds Miter_Limit, kBevel_Join is used instead.
2545##
2546
2547#Const kRound_Join 1
2548 Adds a circle with a diameter of Stroke_Width at the sharp corner.
2549##
2550
2551#Const kBevel_Join 2
2552 Connects the outside edges of the sharp corner.
2553##
2554
2555#Const kLast_Join 2
2556 Equivalent to the largest value for Stroke_Join.
2557##
2558
2559#Const kDefault_Join 1
2560 Equivalent to kMiter_Join.
2561 Stroke_Join is set to kMiter_Join by default.
2562##
2563
2564#Const kJoinCount 3
2565 The number of different Stroke_Join values defined.
2566 May be used to verify that Stroke_Join is a legal value.
2567##
2568
2569#Example
2570#Width 462
2571void draw(SkCanvas* canvas) {
2572 SkPath path;
2573 path.moveTo(10, 50);
2574 path.quadTo(35, 110, 60, 210);
2575 path.quadTo(105, 110, 130, 10);
2576 SkPaint paint; // set to default kMiter_Join
2577 paint.setAntiAlias(true);
2578 paint.setStyle(SkPaint::kStroke_Style);
2579 paint.setStrokeWidth(20);
2580 canvas->drawPath(path, paint);
2581 canvas->translate(150, 0);
2582 paint.setStrokeJoin(SkPaint::kBevel_Join);
2583 canvas->drawPath(path, paint);
2584 canvas->translate(150, 0);
2585 paint.setStrokeJoin(SkPaint::kRound_Join);
2586 canvas->drawPath(path, paint);
2587}
2588##
2589
2590#SeeAlso setStrokeJoin getStrokeJoin setStrokeMiter getStrokeMiter
2591
2592#Enum ##
2593
2594#Method Join getStrokeJoin() const
2595
2596 The geometry drawn at the corners of strokes.
2597
2598 #Return one of: kMiter_Join, kRound_Join, kBevel_Join ##
2599
2600 #Example
2601 SkPaint paint;
2602 SkDebugf("kMiter_Join %c= default stroke join\n",
2603 SkPaint::kMiter_Join == paint.getStrokeJoin() ? '=' : '!');
2604
2605 #StdOut
2606 kMiter_Join == default stroke join
2607 ##
2608 ##
2609
2610 #SeeAlso Stroke_Join setStrokeJoin
2611##
2612
2613#Method void setStrokeJoin(Join join)
2614
2615 The geometry drawn at the corners of strokes.
2616
2617 #Param join one of: kMiter_Join, kRound_Join, kBevel_Join;
Cary Clark579985c2017-07-31 11:48:27 -04002618 otherwise, has no effect
Cary Clark8032b982017-07-28 11:04:54 -04002619 ##
2620
2621 #Example
2622 SkPaint paint;
2623 paint.setStrokeJoin(SkPaint::kMiter_Join);
2624 paint.setStrokeJoin((SkPaint::Join) SkPaint::kJoinCount);
2625 SkDebugf("kMiter_Join %c= paint.getStrokeJoin()\n",
2626 SkPaint::kMiter_Join == paint.getStrokeJoin() ? '=' : '!');
2627
2628 #StdOut
2629 kMiter_Join == paint.getStrokeJoin()
2630 ##
2631 ##
2632
2633 #SeeAlso Stroke_Join getStrokeJoin
2634##
2635
2636#SeeAlso Miter_Limit
2637
2638#Topic Stroke_Join ##
2639# ------------------------------------------------------------------------------
2640#Topic Fill_Path
2641
2642Fill_Path creates a Path by applying the Path_Effect, followed by the Style_Stroke.
2643
2644If Paint contains Path_Effect, Path_Effect operates on the source Path; the result
2645replaces the destination Path. Otherwise, the source Path is replaces the
2646destination Path.
2647
2648Fill Path can request the Path_Effect to restrict to a culling rectangle, but
2649the Path_Effect is not required to do so.
2650
2651If Style is kStroke_Style or kStrokeAndFill_Style,
2652and Stroke_Width is greater than zero, the Stroke_Width, Stroke_Cap, Stroke_Join,
2653and Miter_Limit operate on the destination Path, replacing it.
2654
2655Fill Path can specify the precision used by Stroke_Width to approximate the stroke geometry.
2656
2657If the Style is kStroke_Style and the Stroke_Width is zero, getFillPath
2658returns false since Hairline has no filled equivalent.
2659
2660#Method bool getFillPath(const SkPath& src, SkPath* dst, const SkRect* cullRect,
2661 SkScalar resScale = 1) const
2662
2663 The filled equivalent of the stroked path.
2664
2665 #Param src Path read to create a filled version ##
2666 #Param dst resulting Path; may be the same as src, but may not be nullptr ##
2667 #Param cullRect optional limit passed to Path_Effect ##
2668 #Param resScale if > 1, increase precision, else if (0 < res < 1) reduce precision
2669 to favor speed and size
2670 ##
2671 #Return true if the path represents Style_Fill, or false if it represents Hairline ##
2672
2673 #Example
2674 #Height 192
2675 #Description
2676 A very small quad stroke is turned into a filled path with increasing levels of precision.
2677 At the lowest precision, the quad stroke is approximated by a rectangle.
2678 At the highest precision, the filled path has high fidelity compared to the original stroke.
2679 ##
2680 void draw(SkCanvas* canvas) {
2681 SkPaint strokePaint;
2682 strokePaint.setAntiAlias(true);
2683 strokePaint.setStyle(SkPaint::kStroke_Style);
2684 strokePaint.setStrokeWidth(.1f);
2685 SkPath strokePath;
2686 strokePath.moveTo(.08f, .08f);
2687 strokePath.quadTo(.09f, .08f, .17f, .17f);
2688 SkPath fillPath;
2689 SkPaint outlinePaint(strokePaint);
2690 outlinePaint.setStrokeWidth(2);
2691 SkMatrix scale = SkMatrix::MakeScale(300, 300);
2692 for (SkScalar precision : { 0.01f, .1f, 1.f, 10.f, 100.f } ) {
2693 strokePaint.getFillPath(strokePath, &fillPath, nullptr, precision);
2694 fillPath.transform(scale);
2695 canvas->drawPath(fillPath, outlinePaint);
2696 canvas->translate(60, 0);
2697 if (1.f == precision) canvas->translate(-180, 100);
2698 }
2699 strokePath.transform(scale);
2700 strokePaint.setStrokeWidth(30);
2701 canvas->drawPath(strokePath, strokePaint);
2702 }
2703 ##
2704
2705##
2706
2707#Method bool getFillPath(const SkPath& src, SkPath* dst) const
2708
2709 The filled equivalent of the stroked path.
2710
2711 Replaces dst with the src path modified by Path_Effect and Style_Stroke.
2712 Path_Effect, if any, is not culled. Stroke_Width is created with default precision.
2713
2714 #Param src Path read to create a filled version ##
2715 #Param dst resulting Path dst may be the same as src, but may not be nullptr ##
2716 #Return true if the path represents Style_Fill, or false if it represents Hairline ##
2717
2718 #Example
2719 #Height 128
2720 void draw(SkCanvas* canvas) {
2721 SkPaint paint;
2722 paint.setStyle(SkPaint::kStroke_Style);
2723 paint.setStrokeWidth(10);
2724 SkPath strokePath;
2725 strokePath.moveTo(20, 20);
2726 strokePath.lineTo(100, 100);
2727 canvas->drawPath(strokePath, paint);
2728 SkPath fillPath;
2729 paint.getFillPath(strokePath, &fillPath);
2730 paint.setStrokeWidth(2);
2731 canvas->translate(40, 0);
2732 canvas->drawPath(fillPath, paint);
2733 }
2734 ##
2735
2736##
2737
2738#SeeAlso Style_Stroke Stroke_Width Path_Effect
2739
2740#Topic ##
2741# ------------------------------------------------------------------------------
2742#Topic Shader_Methods
2743
2744Shader defines the colors used when drawing a shape.
2745Shader may be an image, a gradient, or a computed fill.
2746If Paint has no Shader, then Color fills the shape.
2747
2748Shader is modulated by Color_Alpha component of Color.
2749If Shader object defines only Color_Alpha, then Color modulated by Color_Alpha describes
2750the fill.
2751
2752The drawn transparency can be modified without altering Shader, by changing Color_Alpha.
2753
2754#Example
2755void draw(SkCanvas* canvas) {
2756 SkPaint paint;
2757 SkPoint center = { 50, 50 };
2758 SkScalar radius = 50;
2759 const SkColor colors[] = { 0xFFFFFFFF, 0xFF000000 };
2760 paint.setShader(SkGradientShader::MakeRadial(center, radius, colors,
2761 nullptr, SK_ARRAY_COUNT(colors), SkShader::kClamp_TileMode));
2762 for (SkScalar a : { 0.3f, 0.6f, 1.0f } ) {
2763 paint.setAlpha((int) (a * 255));
2764 canvas->drawCircle(center.fX, center.fY, radius, paint);
2765 canvas->translate(70, 70);
2766 }
2767}
2768##
2769
2770If Shader generates only Color_Alpha then all components of Color modulate the output.
2771
2772#Example
2773void draw(SkCanvas* canvas) {
2774 SkPaint paint;
2775 SkBitmap bitmap;
2776 bitmap.setInfo(SkImageInfo::MakeA8(5, 1), 5); // bitmap only contains alpha
2777 uint8_t pixels[5] = { 0x22, 0x55, 0x88, 0xBB, 0xFF };
2778 bitmap.setPixels(pixels);
2779 paint.setShader(SkShader::MakeBitmapShader(bitmap,
2780 SkShader::kMirror_TileMode, SkShader::kMirror_TileMode));
2781 for (SkColor c : { SK_ColorRED, SK_ColorBLUE, SK_ColorGREEN } ) {
2782 paint.setColor(c); // all components in color affect shader
2783 canvas->drawCircle(50, 50, 50, paint);
2784 canvas->translate(70, 70);
2785 }
2786}
2787##
2788
2789#Method SkShader* getShader() const
2790
2791 Optional colors used when filling a path, such as a gradient.
2792
2793 Does not alter Shader Reference_Count.
2794
2795 #Return Shader if previously set, nullptr otherwise ##
2796
2797 #Example
2798 void draw(SkCanvas* canvas) {
2799 SkPaint paint;
2800 SkDebugf("nullptr %c= shader\n", paint.getShader() ? '!' : '=');
2801 paint.setShader(SkShader::MakeEmptyShader());
2802 SkDebugf("nullptr %c= shader\n", paint.getShader() ? '!' : '=');
2803 }
2804
2805 #StdOut
2806 nullptr == shader
2807 nullptr != shader
2808 ##
2809 ##
2810
2811##
2812
2813#Method sk_sp<SkShader> refShader() const
2814
2815 Optional colors used when filling a path, such as a gradient.
2816
2817 Increases Shader Reference_Count by one.
2818
2819 #Return Shader if previously set, nullptr otherwise ##
2820
2821 #Example
2822 void draw(SkCanvas* canvas) {
2823 SkPaint paint1, paint2;
2824 paint1.setShader(SkShader::MakeEmptyShader());
2825 SkDebugf("shader unique: %s\n", paint1.getShader()->unique() ? "true" : "false");
2826 paint2.setShader(paint1.refShader());
2827 SkDebugf("shader unique: %s\n", paint1.getShader()->unique() ? "true" : "false");
2828 }
2829
2830 #StdOut
2831 shader unique: true
2832 shader unique: false
2833 ##
2834 ##
2835
2836##
2837
2838#Method void setShader(sk_sp<SkShader> shader)
2839
2840 Optional colors used when filling a path, such as a gradient.
2841
2842 Sets Shader to shader, decrementing Reference_Count of the previous Shader.
2843 Does not alter shader Reference_Count.
2844
2845 #Param shader how geometry is filled with color; if nullptr, Color is used instead ##
2846
2847 #Example
2848 #Height 64
2849 void draw(SkCanvas* canvas) {
2850 SkPaint paint;
2851 paint.setColor(SK_ColorBLUE);
2852 paint.setShader(SkShader::MakeColorShader(SK_ColorRED));
2853 canvas->drawRect(SkRect::MakeWH(40, 40), paint);
2854 paint.setShader(nullptr);
2855 canvas->translate(50, 0);
2856 canvas->drawRect(SkRect::MakeWH(40, 40), paint);
2857 }
2858 ##
2859
2860##
2861
2862#Topic ##
2863# ------------------------------------------------------------------------------
2864#Topic Color_Filter_Methods
2865
2866Color_Filter alters the color used when drawing a shape.
2867Color_Filter may apply Blend_Mode, transform the color through a matrix, or composite multiple filters.
2868If Paint has no Color_Filter, the color is unaltered.
2869
2870The drawn transparency can be modified without altering Color_Filter, by changing Color_Alpha.
2871
2872#Example
2873#Height 128
2874void draw(SkCanvas* canvas) {
2875 SkPaint paint;
2876 paint.setColorFilter(SkColorMatrixFilter::MakeLightingFilter(0xFFFFFF, 0xFF0000));
2877 for (SkColor c : { SK_ColorBLACK, SK_ColorGREEN } ) {
2878 paint.setColor(c);
2879 canvas->drawRect(SkRect::MakeXYWH(10, 10, 50, 50), paint);
2880 paint.setAlpha(0x80);
2881 canvas->drawRect(SkRect::MakeXYWH(60, 60, 50, 50), paint);
2882 canvas->translate(100, 0);
2883 }
2884}
2885##
2886
2887#Method SkColorFilter* getColorFilter() const
2888
2889 Returns Color_Filter if set, or nullptr.
2890 Does not alter Color_Filter Reference_Count.
2891
2892 #Return Color_Filter if previously set, nullptr otherwise ##
2893
2894 #Example
2895 void draw(SkCanvas* canvas) {
2896 SkPaint paint;
2897 SkDebugf("nullptr %c= color filter\n", paint.getColorFilter() ? '!' : '=');
2898 paint.setColorFilter(SkColorFilter::MakeModeFilter(SK_ColorLTGRAY, SkBlendMode::kSrcIn));
2899 SkDebugf("nullptr %c= color filter\n", paint.getColorFilter() ? '!' : '=');
2900 }
2901
2902 #StdOut
2903 nullptr == color filter
2904 nullptr != color filter
2905 ##
2906 ##
2907##
2908
2909#Method sk_sp<SkColorFilter> refColorFilter() const
2910
2911 Returns Color_Filter if set, or nullptr.
2912 Increases Color_Filter Reference_Count by one.
2913
2914 #Return Color_Filter if set, or nullptr ##
2915
2916 #Example
2917 void draw(SkCanvas* canvas) {
2918 SkPaint paint1, paint2;
2919 paint1.setColorFilter(SkColorFilter::MakeModeFilter(0xFFFF0000, SkBlendMode::kSrcATop));
2920 SkDebugf("color filter unique: %s\n", paint1.getColorFilter()->unique() ? "true" : "false");
2921 paint2.setColorFilter(paint1.refColorFilter());
2922 SkDebugf("color filter unique: %s\n", paint1.getColorFilter()->unique() ? "true" : "false");
2923 }
2924
2925 #StdOut
2926 color filter unique: true
2927 color filter unique: false
2928 ##
2929 ##
2930##
2931
2932#Method void setColorFilter(sk_sp<SkColorFilter> colorFilter)
2933
2934 Sets Color_Filter to filter, decrementing Reference_Count of the previous Color_Filter.
2935 Pass nullptr to clear Color_Filter.
2936 Does not alter filter Reference_Count.
2937
2938 #Param colorFilter Color_Filter to apply to subsequent draw ##
2939
2940 #Example
2941 #Height 64
2942 void draw(SkCanvas* canvas) {
2943 SkPaint paint;
2944 paint.setColorFilter(SkColorFilter::MakeModeFilter(SK_ColorLTGRAY, SkBlendMode::kSrcIn));
2945 canvas->drawRect(SkRect::MakeWH(50, 50), paint);
2946 paint.setColorFilter(nullptr);
2947 canvas->translate(70, 0);
2948 canvas->drawRect(SkRect::MakeWH(50, 50), paint);
2949 }
2950 ##
2951
2952##
2953
2954#Topic ##
2955# ------------------------------------------------------------------------------
2956#Topic Blend_Mode_Methods
2957
2958Blend_Mode describes how Color combines with the destination color.
2959The default setting, SkBlendMode::kSrcOver, draws the source color
2960over the destination color.
2961
2962#Example
2963void draw(SkCanvas* canvas) {
2964 SkPaint normal, blender;
2965 normal.setColor(0xFF58a889);
2966 blender.setColor(0xFF8958a8);
2967 canvas->clear(0);
2968 for (SkBlendMode m : { SkBlendMode::kSrcOver, SkBlendMode::kSrcIn, SkBlendMode::kSrcOut } ) {
2969 normal.setBlendMode(SkBlendMode::kSrcOver);
2970 canvas->drawOval(SkRect::MakeXYWH(30, 30, 30, 80), normal);
2971 blender.setBlendMode(m);
2972 canvas->drawOval(SkRect::MakeXYWH(10, 50, 80, 30), blender);
2973 canvas->translate(70, 70);
2974 }
2975}
2976##
2977
2978#SeeAlso Blend_Mode
2979
2980#Method SkBlendMode getBlendMode() const
2981
2982 Returns Blend_Mode.
Cary Clark579985c2017-07-31 11:48:27 -04002983 By default, returns SkBlendMode::kSrcOver.
Cary Clark8032b982017-07-28 11:04:54 -04002984
2985 #Return mode used to combine source color with destination color ##
2986
2987 #Example
2988 void draw(SkCanvas* canvas) {
2989 SkPaint paint;
2990 SkDebugf("kSrcOver %c= getBlendMode\n",
2991 SkBlendMode::kSrcOver == paint.getBlendMode() ? '=' : '!');
2992 paint.setBlendMode(SkBlendMode::kSrc);
2993 SkDebugf("kSrcOver %c= getBlendMode\n",
2994 SkBlendMode::kSrcOver == paint.getBlendMode() ? '=' : '!');
2995 }
2996
2997 #StdOut
2998 kSrcOver == getBlendMode
2999 kSrcOver != getBlendMode
3000 ##
3001 ##
3002
3003##
3004
3005#Method bool isSrcOver() const
3006
3007 Returns true if Blend_Mode is SkBlendMode::kSrcOver, the default.
3008
3009 #Return true if Blend_Mode is SkBlendMode::kSrcOver ##
3010
3011 #Example
3012 void draw(SkCanvas* canvas) {
3013 SkPaint paint;
3014 SkDebugf("isSrcOver %c= true\n", paint.isSrcOver() ? '=' : '!');
3015 paint.setBlendMode(SkBlendMode::kSrc);
3016 SkDebugf("isSrcOver %c= true\n", paint.isSrcOver() ? '=' : '!');
3017 }
3018
3019 #StdOut
3020 isSrcOver == true
3021 isSrcOver != true
3022 ##
3023 ##
3024
3025##
3026
3027#Method void setBlendMode(SkBlendMode mode)
3028
3029 Sets Blend_Mode to mode.
3030 Does not check for valid input.
3031
3032 #Param mode SkBlendMode used to combine source color and destination ##
3033
3034 #Example
3035 void draw(SkCanvas* canvas) {
3036 SkPaint paint;
3037 SkDebugf("isSrcOver %c= true\n", paint.isSrcOver() ? '=' : '!');
3038 paint.setBlendMode(SkBlendMode::kSrc);
3039 SkDebugf("isSrcOver %c= true\n", paint.isSrcOver() ? '=' : '!');
3040 }
3041
3042 #StdOut
3043 isSrcOver == true
3044 isSrcOver != true
3045 ##
3046 ##
3047
3048##
3049
3050#Topic ##
3051# ------------------------------------------------------------------------------
3052#Topic Path_Effect_Methods
3053
3054Path_Effect modifies the path geometry before drawing it.
3055Path_Effect may implement dashing, custom fill effects and custom stroke effects.
3056If Paint has no Path_Effect, the path geometry is unaltered when filled or stroked.
3057
3058#Example
3059#Height 160
3060 void draw(SkCanvas* canvas) {
3061 SkPaint paint;
3062 paint.setStyle(SkPaint::kStroke_Style);
3063 paint.setStrokeWidth(16);
3064 SkScalar intervals[] = {30, 10};
3065 paint.setPathEffect(SkDashPathEffect::Make(intervals, SK_ARRAY_COUNT(intervals), 1));
3066 canvas->drawRoundRect({20, 20, 120, 120}, 20, 20, paint);
3067 }
3068##
3069
3070#SeeAlso Path_Effect
3071
3072#Method SkPathEffect* getPathEffect() const
3073
3074 Returns Path_Effect if set, or nullptr.
3075 Does not alter Path_Effect Reference_Count.
3076
3077 #Return Path_Effect if previously set, nullptr otherwise ##
3078
3079 #Example
3080 void draw(SkCanvas* canvas) {
3081 SkPaint paint;
3082 SkDebugf("nullptr %c= path effect\n", paint.getPathEffect() ? '!' : '=');
3083 paint.setPathEffect(SkCornerPathEffect::Make(10));
3084 SkDebugf("nullptr %c= path effect\n", paint.getPathEffect() ? '!' : '=');
3085 }
3086
3087 #StdOut
3088 nullptr == path effect
3089 nullptr != path effect
3090 ##
3091 ##
3092
3093##
3094
3095
3096#Method sk_sp<SkPathEffect> refPathEffect() const
3097
3098 Returns Path_Effect if set, or nullptr.
3099 Increases Path_Effect Reference_Count by one.
3100
3101 #Return Path_Effect if previously set, nullptr otherwise ##
3102
3103 #Example
3104 void draw(SkCanvas* canvas) {
3105 SkPaint paint1, paint2;
3106 paint1.setPathEffect(SkArcToPathEffect::Make(10));
3107 SkDebugf("path effect unique: %s\n", paint1.getPathEffect()->unique() ? "true" : "false");
3108 paint2.setPathEffect(paint1.refPathEffect());
3109 SkDebugf("path effect unique: %s\n", paint1.getPathEffect()->unique() ? "true" : "false");
3110 }
3111
3112 #StdOut
3113 path effect unique: true
3114 path effect unique: false
3115 ##
3116 ##
3117
3118##
3119
3120
3121#Method void setPathEffect(sk_sp<SkPathEffect> pathEffect)
3122
3123 Sets Path_Effect to pathEffect,
3124 decrementing Reference_Count of the previous Path_Effect.
3125 Pass nullptr to leave the path geometry unaltered.
3126 Does not alter pathEffect Reference_Count.
3127
3128 #Param pathEffect replace Path with a modification when drawn ##
3129
3130 #Example
3131 void draw(SkCanvas* canvas) {
3132 SkPaint paint;
3133 paint.setPathEffect(SkDiscretePathEffect::Make(3, 5));
3134 canvas->drawRect(SkRect::MakeXYWH(40, 40, 175, 175), paint);
3135 }
3136 ##
3137
3138##
3139
3140#Topic ##
3141# ------------------------------------------------------------------------------
3142#Topic Mask_Filter_Methods
3143
3144Mask_Filter uses Color_Alpha of the shape drawn to create Mask_Alpha.
3145Mask_Filter operates at a lower level than Rasterizer; Mask_Filter takes a Mask,
3146and returns a Mask.
3147Mask_Filter may change the geometry and transparency of the shape, such as creating a blur effect.
3148Set Mask_Filter to nullptr to prevent Mask_Filter from modifying the draw.
3149
3150#Example
3151 void draw(SkCanvas* canvas) {
3152 SkPaint paint;
3153 paint.setMaskFilter(SkBlurMaskFilter::Make(kSolid_SkBlurStyle, 3));
3154 canvas->drawRect(SkRect::MakeXYWH(40, 40, 175, 175), paint);
3155 }
3156##
3157
3158#Method SkMaskFilter* getMaskFilter() const
3159
3160 Returns Mask_Filter if set, or nullptr.
3161 Does not alter Mask_Filter Reference_Count.
3162
3163 #Return Mask_Filter if previously set, nullptr otherwise ##
3164
3165 #Example
3166 void draw(SkCanvas* canvas) {
3167 SkPaint paint;
3168 SkDebugf("nullptr %c= mask filter\n", paint.getMaskFilter() ? '!' : '=');
3169 paint.setMaskFilter(SkBlurMaskFilter::Make(kOuter_SkBlurStyle, 3));
3170 SkDebugf("nullptr %c= mask filter\n", paint.getMaskFilter() ? '!' : '=');
3171 }
3172
3173 #StdOut
3174 nullptr == mask filter
3175 nullptr != mask filter
3176 ##
3177 ##
3178
3179##
3180
3181#Method sk_sp<SkMaskFilter> refMaskFilter() const
3182
3183 Returns Mask_Filter if set, or nullptr.
3184 Increases Mask_Filter Reference_Count by one.
3185
3186 #Return Mask_Filter if previously set, nullptr otherwise ##
3187
3188 #Example
3189 void draw(SkCanvas* canvas) {
3190 SkPaint paint1, paint2;
3191 paint1.setMaskFilter(SkBlurMaskFilter::Make(kNormal_SkBlurStyle, 1));
3192 SkDebugf("mask filter unique: %s\n", paint1.getMaskFilter()->unique() ? "true" : "false");
3193 paint2.setMaskFilter(paint1.refMaskFilter());
3194 SkDebugf("mask filter unique: %s\n", paint1.getMaskFilter()->unique() ? "true" : "false");
3195 }
3196
3197 #StdOut
3198 mask filter unique: true
3199 mask filter unique: false
3200 ##
3201 ##
3202
3203##
3204
3205#Method void setMaskFilter(sk_sp<SkMaskFilter> maskFilter)
3206
3207 Sets Mask_Filter to maskFilter,
3208 decrementing Reference_Count of the previous Mask_Filter.
3209 Pass nullptr to clear Mask_Filter and leave Mask_Filter effect on Mask_Alpha unaltered.
3210 Does not affect Rasterizer.
3211 Does not alter maskFilter Reference_Count.
3212
3213 #Param maskFilter modifies clipping mask generated from drawn geometry ##
3214
3215 #Example
3216 void draw(SkCanvas* canvas) {
3217 SkPaint paint;
3218 paint.setStyle(SkPaint::kStroke_Style);
3219 paint.setStrokeWidth(10);
3220 paint.setMaskFilter(SkBlurMaskFilter::Make(kNormal_SkBlurStyle, 10));
3221 canvas->drawRect(SkRect::MakeXYWH(40, 40, 175, 175), paint);
3222 }
3223 ##
3224
3225##
3226
3227#Topic ##
3228# ------------------------------------------------------------------------------
3229#Topic Typeface_Methods
3230
3231Typeface identifies the font used when drawing and measuring text.
3232Typeface may be specified by name, from a file, or from a data stream.
3233The default Typeface defers to the platform-specific default font
3234implementation.
3235
3236#Example
3237#Height 100
3238 void draw(SkCanvas* canvas) {
3239 SkPaint paint;
3240 paint.setTypeface(SkTypeface::MakeDefault(SkTypeface::kBold));
3241 paint.setAntiAlias(true);
3242 paint.setTextSize(36);
3243 canvas->drawString("A Big Hello!", 10, 40, paint);
3244 paint.setTypeface(nullptr);
3245 paint.setFakeBoldText(true);
3246 canvas->drawString("A Big Hello!", 10, 80, paint);
3247 }
3248##
3249
3250#Method SkTypeface* getTypeface() const
3251
3252 Returns Typeface if set, or nullptr.
3253 Does not alter Typeface Reference_Count.
3254
3255 #Return Typeface if previously set, nullptr otherwise ##
3256
3257 #Example
3258 void draw(SkCanvas* canvas) {
3259 SkPaint paint;
3260 SkDebugf("nullptr %c= typeface\n", paint.getTypeface() ? '!' : '=');
3261 paint.setTypeface(SkTypeface::MakeFromName("Times New Roman", SkFontStyle()));
3262 SkDebugf("nullptr %c= typeface\n", paint.getTypeface() ? '!' : '=');
3263 }
3264
3265 #StdOut
3266 nullptr == typeface
3267 nullptr != typeface
3268 ##
3269 ##
3270
3271##
3272
3273#Method sk_sp<SkTypeface> refTypeface() const
3274
3275 Increases Typeface Reference_Count by one.
3276
3277 #Return Typeface if previously set, nullptr otherwise ##
3278
3279 #Example
3280 void draw(SkCanvas* canvas) {
3281 SkPaint paint1, paint2;
3282 paint1.setTypeface(SkTypeface::MakeFromName("Times New Roman",
3283 SkFontStyle(SkFontStyle::kNormal_Weight, SkFontStyle::kNormal_Width,
3284 SkFontStyle::kItalic_Slant)));
3285 SkDebugf("typeface1 %c= typeface2\n",
3286 paint1.getTypeface() == paint2.getTypeface() ? '=' : '!');
3287 paint2.setTypeface(paint1.refTypeface());
3288 SkDebugf("typeface1 %c= typeface2\n",
3289 paint1.getTypeface() == paint2.getTypeface() ? '=' : '!');
3290 }
3291
3292 #StdOut
3293 typeface1 != typeface2
3294 typeface1 == typeface2
3295 ##
3296 ##
3297
3298##
3299
3300#Method void setTypeface(sk_sp<SkTypeface> typeface)
3301
3302 Sets Typeface to typeface,
3303 decrementing Reference_Count of the previous Typeface.
3304 Pass nullptr to clear Typeface and use the default typeface.
3305 Does not alter typeface Reference_Count.
3306
3307 #Param typeface font and style used to draw text ##
3308
3309 #Example
3310 #Height 64
3311 void draw(SkCanvas* canvas) {
3312 SkPaint paint;
3313 paint.setTypeface(SkTypeface::MakeFromName("Courier New", SkFontStyle()));
3314 canvas->drawString("Courier New", 10, 30, paint);
3315 paint.setTypeface(nullptr);
3316 canvas->drawString("default", 10, 50, paint);
3317 }
3318 ##
3319
3320##
3321
3322#Topic ##
3323# ------------------------------------------------------------------------------
3324#Topic Rasterizer_Methods
3325
3326Rasterizer controls how shapes are converted to Mask_Alpha.
3327Rasterizer operates at a higher level than Mask_Filter; Rasterizer takes a Path,
3328and returns a Mask.
3329Rasterizer may change the geometry and transparency of the shape, such as
3330creating a shadow effect. Rasterizer forms the base of Rasterizer_Layer, which
3331creates effects like embossing and outlining.
3332Rasterizer applies to Rect, Region, Round_Rect, Arc, Circle, Oval,
3333Path, and Text.
3334
3335#Example
3336#Height 64
3337 void draw(SkCanvas* canvas) {
3338 SkLayerRasterizer::Builder layerBuilder;
3339 SkPaint paint;
3340 paint.setAntiAlias(true);
3341 paint.setStyle(SkPaint::kStroke_Style);
3342 paint.setStrokeWidth(1);
3343 layerBuilder.addLayer(paint);
3344 paint.setAlpha(0x10);
3345 paint.setStyle(SkPaint::kFill_Style);
3346 paint.setBlendMode(SkBlendMode::kSrc);
3347 layerBuilder.addLayer(paint);
3348 paint.reset();
3349 paint.setAntiAlias(true);
3350 paint.setTextSize(50);
3351 paint.setRasterizer(layerBuilder.detach());
3352 canvas->drawString("outline", 10, 50, paint);
3353 }
3354##
3355
3356#Method SkRasterizer* getRasterizer() const
3357
3358 Returns Rasterizer if set, or nullptr.
3359 Does not alter Rasterizer Reference_Count.
3360
3361 #Return Rasterizer if previously set, nullptr otherwise ##
3362
3363 #Example
3364 #Function
3365 class DummyRasterizer : public SkRasterizer {
3366 public:
3367 SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(DummyRasterizer)
3368 };
3369
3370 sk_sp<SkFlattenable> DummyRasterizer::CreateProc(SkReadBuffer&) {
3371 return sk_make_sp<DummyRasterizer>();
3372 }
3373
3374 #Function ##
3375 void draw(SkCanvas* canvas) {
3376 SkPaint paint;
3377 DummyRasterizer dummy;
3378 SkDebugf("nullptr %c= rasterizer\n", paint.getRasterizer() ? '!' : '=');
3379 paint.setRasterizer(sk_make_sp<DummyRasterizer>());
3380 SkDebugf("nullptr %c= rasterizer\n", paint.getRasterizer() ? '!' : '=');
3381 }
3382
3383 #StdOut
3384 nullptr == rasterizer
3385 nullptr != rasterizer
3386 ##
3387 ##
3388
3389##
3390
3391#Method sk_sp<SkRasterizer> refRasterizer() const
3392
3393 Returns Rasterizer if set, or nullptr.
3394 Increases Rasterizer Reference_Count by one.
3395
3396 #Return Rasterizer if previously set, nullptr otherwise ##
3397
3398 #Example
3399 void draw(SkCanvas* canvas) {
3400 SkLayerRasterizer::Builder layerBuilder;
3401 SkPaint paint1, paint2;
3402 layerBuilder.addLayer(paint2);
3403 paint1.setRasterizer(layerBuilder.detach());
3404 SkDebugf("rasterizer unique: %s\n", paint1.getRasterizer()->unique() ? "true" : "false");
3405 paint2.setRasterizer(paint1.refRasterizer());
3406 SkDebugf("rasterizer unique: %s\n", paint1.getRasterizer()->unique() ? "true" : "false");
3407 }
3408
3409 #StdOut
3410 rasterizer unique: true
3411 rasterizer unique: false
3412 ##
3413 ##
3414
3415##
3416
3417#Method void setRasterizer(sk_sp<SkRasterizer> rasterizer)
3418
3419 Sets Rasterizer to rasterizer,
3420 decrementing Reference_Count of the previous Rasterizer.
3421 Pass nullptr to clear Rasterizer and leave Rasterizer effect on Mask_Alpha unaltered.
3422 Does not affect Mask_Filter.
3423 Does not alter rasterizer Reference_Count.
3424
3425 #Param rasterizer how geometry is converted to Mask_Alpha ##
3426
3427 #Example
3428 #Height 64
3429 SkLayerRasterizer::Builder layerBuilder;
3430 SkPaint paint;
3431 paint.setAntiAlias(true);
3432 paint.setStyle(SkPaint::kStroke_Style);
3433 paint.setStrokeWidth(2);
3434 layerBuilder.addLayer(paint);
3435 paint.reset();
3436 paint.setAntiAlias(true);
3437 paint.setTextSize(50);
3438 paint.setMaskFilter(SkBlurMaskFilter::Make(kNormal_SkBlurStyle, 3));
3439 paint.setRasterizer(layerBuilder.detach());
3440 canvas->drawString("blurry out", 0, 50, paint);
3441 ##
3442
3443##
3444
3445#Topic ##
3446# ------------------------------------------------------------------------------
3447#Topic Image_Filter_Methods
3448
3449Image_Filter operates on the pixel representation of the shape, as modified by Paint
3450with Blend_Mode set to SkBlendMode::kSrcOver. Image_Filter creates a new bitmap,
3451which is drawn to the device using the set Blend_Mode.
3452Image_Filter is higher level than Mask_Filter; for instance, an Image_Filter
3453can operate on all channels of Color, while Mask_Filter generates Color_Alpha only.
3454Image_Filter operates independently of and can be used in combination with
3455Mask_Filter and Rasterizer.
3456
3457#Example
3458 #ToDo explain why the two draws are so different ##
3459 void draw(SkCanvas* canvas) {
3460 SkPaint paint;
3461 paint.setStyle(SkPaint::kStroke_Style);
3462 paint.setStrokeWidth(2);
3463 SkRegion region;
3464 region.op( 10, 10, 50, 50, SkRegion::kUnion_Op);
3465 region.op( 10, 50, 90, 90, SkRegion::kUnion_Op);
3466 paint.setImageFilter(SkImageFilter::MakeBlur(5.0f, 5.0f, nullptr));
3467 canvas->drawRegion(region, paint);
3468 paint.setImageFilter(nullptr);
3469 paint.setMaskFilter(SkBlurMaskFilter::Make(kNormal_SkBlurStyle, 5));
3470 canvas->translate(100, 100);
3471 canvas->drawRegion(region, paint);
3472 }
3473##
3474
3475#Method SkImageFilter* getImageFilter() const
3476
3477 Returns Image_Filter if set, or nullptr.
3478 Does not alter Image_Filter Reference_Count.
3479
3480 #Return Image_Filter if previously set, nullptr otherwise ##
3481
3482 #Example
3483 void draw(SkCanvas* canvas) {
3484 SkPaint paint;
3485 SkDebugf("nullptr %c= image filter\n", paint.getImageFilter() ? '!' : '=');
3486 paint.setImageFilter(SkImageFilter::MakeBlur(kOuter_SkBlurStyle, 3, nullptr, nullptr));
3487 SkDebugf("nullptr %c= image filter\n", paint.getImageFilter() ? '!' : '=');
3488 }
3489
3490 #StdOut
3491 nullptr == image filter
3492 nullptr != image filter
3493 ##
3494 ##
3495
3496##
3497
3498#Method sk_sp<SkImageFilter> refImageFilter() const
3499
3500 Returns Image_Filter if set, or nullptr.
3501 Increases Image_Filter Reference_Count by one.
3502
3503 #Return Image_Filter if previously set, nullptr otherwise ##
3504
3505 #Example
3506 void draw(SkCanvas* canvas) {
3507 SkPaint paint1, paint2;
3508 paint1.setImageFilter(SkOffsetImageFilter::Make(25, 25, nullptr));
3509 SkDebugf("image filter unique: %s\n", paint1.getImageFilter()->unique() ? "true" : "false");
3510 paint2.setImageFilter(paint1.refImageFilter());
3511 SkDebugf("image filter unique: %s\n", paint1.getImageFilter()->unique() ? "true" : "false");
3512 }
3513
3514 #StdOut
3515 image filter unique: true
3516 image filter unique: false
3517 ##
3518 ##
3519
3520##
3521
3522#Method void setImageFilter(sk_sp<SkImageFilter> imageFilter)
3523
3524 Sets Image_Filter to imageFilter,
3525 decrementing Reference_Count of the previous Image_Filter.
3526 Pass nullptr to clear Image_Filter, and remove Image_Filter effect
3527 on drawing.
3528 Does not affect Rasterizer or Mask_Filter.
3529 Does not alter imageFilter Reference_Count.
3530
3531 #Param imageFilter how Image is sampled when transformed ##
3532
3533 #Example
3534 #Height 160
3535 void draw(SkCanvas* canvas) {
3536 SkBitmap bitmap;
3537 bitmap.allocN32Pixels(100, 100);
3538 SkCanvas offscreen(bitmap);
3539 SkPaint paint;
3540 paint.setAntiAlias(true);
3541 paint.setColor(SK_ColorWHITE);
3542 paint.setTextSize(96);
3543 offscreen.clear(0);
3544 offscreen.drawString("e", 20, 70, paint);
3545 paint.setImageFilter(
3546 SkLightingImageFilter::MakePointLitDiffuse(SkPoint3::Make(80, 100, 10),
3547 SK_ColorWHITE, 1, 2, nullptr, nullptr));
3548 canvas->drawBitmap(bitmap, 0, 0, &paint);
3549 }
3550 ##
3551
3552##
3553
3554#Topic ##
3555# ------------------------------------------------------------------------------
3556#Topic Draw_Looper_Methods
3557
3558Draw_Looper sets a modifier that communicates state from one Draw_Layer
3559to another to construct the draw.
3560Draw_Looper draws one or more times, modifying the canvas and paint each time.
3561Draw_Looper may be used to draw multiple colors or create a colored shadow.
3562Set Draw_Looper to nullptr to prevent Draw_Looper from modifying the draw.
3563
3564#Example
3565#Height 128
3566 void draw(SkCanvas* canvas) {
3567 SkLayerDrawLooper::LayerInfo info;
3568 info.fPaintBits = (SkLayerDrawLooper::BitFlags) SkLayerDrawLooper::kColorFilter_Bit;
3569 info.fColorMode = SkBlendMode::kSrc;
3570 SkLayerDrawLooper::Builder looperBuilder;
3571 SkPaint* loopPaint = looperBuilder.addLayer(info);
3572 loopPaint->setColor(SK_ColorRED);
3573 info.fOffset.set(20, 20);
3574 loopPaint = looperBuilder.addLayer(info);
3575 loopPaint->setColor(SK_ColorBLUE);
3576 SkPaint paint;
3577 paint.setDrawLooper(looperBuilder.detach());
3578 canvas->drawCircle(50, 50, 50, paint);
3579 }
3580
3581##
3582
3583#Method SkDrawLooper* getDrawLooper() const
3584
3585 Returns Draw_Looper if set, or nullptr.
3586 Does not alter Draw_Looper Reference_Count.
3587
3588 #Return Draw_Looper if previously set, nullptr otherwise ##
3589
3590 #Example
3591 void draw(SkCanvas* canvas) {
3592 SkPaint paint;
3593 SkDebugf("nullptr %c= draw looper\n", paint.getDrawLooper() ? '!' : '=');
3594 SkLayerDrawLooper::Builder looperBuilder;
3595 paint.setDrawLooper(looperBuilder.detach());
3596 SkDebugf("nullptr %c= draw looper\n", paint.getDrawLooper() ? '!' : '=');
3597 }
3598
3599 #StdOut
3600 nullptr == draw looper
3601 nullptr != draw looper
3602 ##
3603 ##
3604
3605##
3606
3607#Method sk_sp<SkDrawLooper> refDrawLooper() const
3608
3609 Returns Draw_Looper if set, or nullptr.
3610 Increases Draw_Looper Reference_Count by one.
3611
3612 #Return Draw_Looper if previously set, nullptr otherwise ##
3613
3614 #Example
3615 void draw(SkCanvas* canvas) {
3616 SkPaint paint1, paint2;
3617 SkLayerDrawLooper::Builder looperBuilder;
3618 paint1.setDrawLooper(looperBuilder.detach());
3619 SkDebugf("draw looper unique: %s\n", paint1.getDrawLooper()->unique() ? "true" : "false");
3620 paint2.setDrawLooper(paint1.refDrawLooper());
3621 SkDebugf("draw looper unique: %s\n", paint1.getDrawLooper()->unique() ? "true" : "false");
3622 }
3623
3624 #StdOut
3625 draw looper unique: true
3626 draw looper unique: false
3627 ##
3628 ##
3629
3630##
3631
3632#Method SkDrawLooper* getLooper() const
3633
3634Deprecated.
3635
3636#Deprecated
3637(see bug.skia.org/6259)
3638#Deprecated ##
3639
3640#Return Draw_Looper if previously set, nullptr otherwise ##
3641##
3642
3643#Method void setDrawLooper(sk_sp<SkDrawLooper> drawLooper)
3644
3645 Sets Draw_Looper to drawLooper,
3646 decrementing Reference_Count of the previous drawLooper.
3647 Pass nullptr to clear Draw_Looper and leave Draw_Looper effect on drawing unaltered.
Cary Clark579985c2017-07-31 11:48:27 -04003648 Does not alter drawLooper Reference_Count.
Cary Clark8032b982017-07-28 11:04:54 -04003649
3650 #Param drawLooper Iterates through drawing one or more time, altering Paint ##
3651
3652 #Example
3653 #Height 128
3654 void draw(SkCanvas* canvas) {
3655 SkPaint paint;
3656 paint.setDrawLooper(SkBlurDrawLooper::Make(0x7FFF0000, 4, -5, -10));
3657 paint.setStyle(SkPaint::kStroke_Style);
3658 paint.setStrokeWidth(10);
3659 paint.setAntiAlias(true);
3660 paint.setColor(0x7f0000ff);
3661 canvas->drawCircle(70, 70, 50, paint);
3662 }
3663 ##
3664
3665##
3666
3667#Method void setLooper(sk_sp<SkDrawLooper> drawLooper)
3668
3669Deprecated.
3670
3671#Deprecated
3672(see bug.skia.org/6259)
3673#Deprecated ##
3674
3675#Param drawLooper sets Draw_Looper to drawLooper ##
3676
3677##
3678
3679#Topic ##
3680# ------------------------------------------------------------------------------
3681#Topic Text_Align
3682
3683#Enum Align
3684#Code
3685 enum Align {
3686 kLeft_Align,
3687 kCenter_Align,
3688 kRight_Align,
3689 };
3690##
3691
3692Align adjusts the text relative to the text position.
3693Align affects glyphs drawn with: SkCanvas::drawText, SkCanvas::drawPosText,
3694SkCanvas::drawPosTextH, SkCanvas::drawTextOnPath,
3695SkCanvas::drawTextOnPathHV, SkCanvas::drawTextRSXform, SkCanvas::drawTextBlob,
3696and SkCanvas::drawString;
3697as well as calls that place text glyphs like getTextWidths and getTextPath.
3698
3699The text position is set by the font for both horizontal and vertical text.
3700Typically, for horizontal text, the position is to the left side of the glyph on the
3701base line; and for vertical text, the position is the horizontal center of the glyph
3702at the caps height.
3703
3704Align adjusts the glyph position to center it or move it to abut the position
3705using the metrics returned by the font.
3706
3707Align defaults to kLeft_Align.
3708
3709#Const kLeft_Align 0
3710 Leaves the glyph at the position computed by the font offset by the text position.
3711##
3712
3713#Const kCenter_Align 1
3714 Moves the glyph half its width if Flags has kVerticalText_Flag clear, and
3715 half its height if Flags has kVerticalText_Flag set.
3716##
3717
3718#Const kRight_Align 2
3719 Moves the glyph by its width if Flags has kVerticalText_Flag clear,
3720 and by its height if Flags has kVerticalText_Flag set.
3721##
3722
3723#Enum ##
3724
3725#Enum
3726
3727#Code
3728 enum {
Cary Clarkbad5ad72017-08-03 17:14:08 -04003729 kAlignCount = 3,
Cary Clark8032b982017-07-28 11:04:54 -04003730 };
3731##
3732
3733#Const kAlignCount 3
3734 The number of different Text_Align values defined.
3735##
3736
3737#Enum ##
3738
3739#Example
3740 #Height 160
3741 #Description
3742 Each position separately moves the glyph in drawPosText.
3743 ##
3744 void draw(SkCanvas* canvas) {
3745 SkPaint paint;
3746 paint.setTextSize(40);
3747 SkPoint position[] = {{100, 50}, {150, 40}};
3748 for (SkPaint::Align a : { SkPaint::kLeft_Align,
3749 SkPaint::kCenter_Align,
3750 SkPaint::kRight_Align}) {
3751 paint.setTextAlign(a);
3752 canvas->drawPosText("Aa", 2, position, paint);
3753 canvas->translate(0, 50);
3754 }
3755 }
3756##
3757
3758#Example
3759 #Height 160
3760 #Description
3761 Vertical_Text treats kLeft_Align as top align, and kRight_Align as bottom align.
3762 ##
3763 void draw(SkCanvas* canvas) {
3764 SkPaint paint;
3765 paint.setTextSize(40);
3766 paint.setVerticalText(true);
3767 for (SkPaint::Align a : { SkPaint::kLeft_Align,
3768 SkPaint::kCenter_Align,
3769 SkPaint::kRight_Align }) {
3770 paint.setTextAlign(a);
3771 canvas->drawString("Aa", 50, 80, paint);
3772 canvas->translate(50, 0);
3773 }
3774 }
3775##
3776
3777#Method Align getTextAlign() const
3778
3779 Returns Text_Align.
3780 Returns kLeft_Align if Text_Align has not been set.
3781
3782 #Return text placement relative to position ##
3783
3784 #Example
3785 SkPaint paint;
3786 SkDebugf("kLeft_Align %c= default\n", SkPaint::kLeft_Align == paint.getTextAlign() ? '=' : '!');
3787
3788 #StdOut
3789 kLeft_Align == default
3790 ##
3791 ##
3792##
3793
3794#Method void setTextAlign(Align align)
3795
3796 Sets Text_Align to align.
3797 Has no effect if align is an invalid value.
3798
3799 #Param align text placement relative to position ##
3800
3801 #Example
3802 #Height 160
3803 #Description
3804 Text is left-aligned by default, and then set to center. Setting the
3805 alignment out of range has no effect.
3806 ##
3807 void draw(SkCanvas* canvas) {
3808 SkPaint paint;
3809 paint.setTextSize(40);
3810 canvas->drawString("Aa", 100, 50, paint);
3811 paint.setTextAlign(SkPaint::kCenter_Align);
3812 canvas->drawString("Aa", 100, 100, paint);
3813 paint.setTextAlign((SkPaint::Align) SkPaint::kAlignCount);
3814 canvas->drawString("Aa", 100, 150, paint);
3815 }
3816 ##
3817
3818##
3819
3820#Topic ##
3821# ------------------------------------------------------------------------------
3822#Topic Text_Size
3823
3824Text_Size adjusts the overall text size in points.
3825Text_Size can be set to any positive value or zero.
3826Text_Size defaults to 12.
3827Set SkPaintDefaults_TextSize at compile time to change the default setting.
3828
3829#Example
3830#Height 135
3831 void draw(SkCanvas* canvas) {
3832 SkPaint paint;
3833 canvas->drawString("12 point", 10, 20, paint);
3834 paint.setTextSize(24);
3835 canvas->drawString("24 point", 10, 60, paint);
3836 paint.setTextSize(48);
3837 canvas->drawString("48 point", 10, 120, paint);
3838 }
3839##
3840
3841#Method SkScalar getTextSize() const
3842
3843 Returns Text_Size in points.
3844
3845 #Return typographic height of text ##
3846
3847 #Example
3848 SkPaint paint;
3849 SkDebugf("12 %c= default text size\n", 12 == paint.getTextSize() ? '=' : '!');
3850 ##
3851
3852##
3853
3854#Method void setTextSize(SkScalar textSize)
3855
3856 Sets Text_Size in points.
3857 Has no effect if textSize is not greater than or equal to zero.
3858
3859 #Param textSize typographic height of text ##
3860
3861 #Example
3862 SkPaint paint;
3863 SkDebugf("12 %c= text size\n", 12 == paint.getTextSize() ? '=' : '!');
3864 paint.setTextSize(-20);
3865 SkDebugf("12 %c= text size\n", 12 == paint.getTextSize() ? '=' : '!');
3866 ##
3867
3868##
3869
3870#Topic ##
3871# ------------------------------------------------------------------------------
3872#Topic Text_Scale_X
3873
3874Text_Scale_X adjusts the text horizontal scale.
3875Text scaling approximates condensed and expanded type faces when the actual face
3876is not available.
3877Text_Scale_X can be set to any value.
3878Text_Scale_X defaults to 1.
3879
3880#Example
3881#Height 128
3882 void draw(SkCanvas* canvas) {
3883 SkPaint paint;
3884 paint.setAntiAlias(true);
3885 paint.setTextSize(24);
3886 paint.setTextScaleX(.8f);
3887 canvas->drawString("narrow", 10, 20, paint);
3888 paint.setTextScaleX(1);
3889 canvas->drawString("normal", 10, 60, paint);
3890 paint.setTextScaleX(1.2f);
3891 canvas->drawString("wide", 10, 100, paint);
3892 }
3893##
3894
3895#Method SkScalar getTextScaleX() const
3896
3897 Returns Text_Scale_X.
3898 Default value is 1.
3899
3900 #Return text horizontal scale ##
3901
3902 #Example
3903 SkPaint paint;
3904 SkDebugf("1 %c= default text scale x\n", 1 == paint.getTextScaleX() ? '=' : '!');
3905 ##
3906
3907##
3908
3909
3910#Method void setTextScaleX(SkScalar scaleX)
3911
3912 Sets Text_Scale_X.
3913 Default value is 1.
3914
3915 #Param scaleX text horizontal scale ##
3916
3917 #Example
3918 SkPaint paint;
3919 paint.setTextScaleX(0.f / 0.f);
3920 SkDebugf("text scale %s-a-number\n", SkScalarIsNaN(paint.getTextScaleX()) ? "not" : "is");
3921 ##
3922
3923##
3924
3925#Topic ##
3926
3927#Topic Text_Skew_X
3928
3929
3930Text_Skew_X adjusts the text horizontal slant.
3931Text skewing approximates italic and oblique type faces when the actual face
3932is not available.
3933Text_Skew_X can be set to any value.
3934Text_Skew_X defaults to 0.
3935
3936#Example
3937#Height 128
3938 void draw(SkCanvas* canvas) {
3939 SkPaint paint;
3940 paint.setAntiAlias(true);
3941 paint.setTextSize(24);
3942 paint.setTextSkewX(-.25f);
3943 canvas->drawString("right-leaning", 10, 100, paint);
3944 paint.setTextSkewX(0);
3945 canvas->drawString("normal", 10, 60, paint);
3946 paint.setTextSkewX(.25f);
3947 canvas->drawString("left-leaning", 10, 20, paint);
3948 }
3949##
3950
3951#Method SkScalar getTextSkewX() const
3952
3953 Returns Text_Skew_X.
3954 Default value is zero.
3955
3956 #Return additional shear in x-axis relative to y-axis ##
3957
3958 #Example
3959 SkPaint paint;
3960 SkDebugf("0 %c= default text skew x\n", 0 == paint.getTextSkewX() ? '=' : '!');
3961 ##
3962
3963##
3964
3965#Method void setTextSkewX(SkScalar skewX)
3966
3967 Sets Text_Skew_X.
3968 Default value is zero.
3969
3970 #Param skewX additional shear in x-axis relative to y-axis ##
3971
3972 #Example
3973 SkPaint paint;
3974 paint.setTextScaleX(1.f / 0.f);
3975 SkDebugf("text scale %s-finite\n", SkScalarIsFinite(paint.getTextScaleX()) ? "is" : "not");
3976 ##
3977
3978##
3979
3980#Topic ##
3981
3982# ------------------------------------------------------------------------------
3983#Topic Text_Encoding
3984
3985#Enum TextEncoding
3986
3987#Code
3988 enum TextEncoding {
3989 kUTF8_TextEncoding,
3990 kUTF16_TextEncoding,
3991 kUTF32_TextEncoding,
Cary Clarkbad5ad72017-08-03 17:14:08 -04003992 kGlyphID_TextEncoding,
Cary Clark8032b982017-07-28 11:04:54 -04003993 };
3994##
3995
3996TextEncoding determines whether text specifies character codes and their encoded size,
3997or glyph indices. Character codes use the encoding specified by the
3998#A Unicode standard # http://unicode.org/standard/standard.html ##.
3999Character codes encoded size are specified by UTF-8, UTF-16, or UTF-32.
4000All character encoding are able to represent all of Unicode, differing only
4001in the total storage required.
4002
4003#A UTF-8 (RFC 3629) # https://tools.ietf.org/html/rfc3629 ## is made up of 8-bit bytes,
4004and is a superset of ASCII.
4005#A UTF-16 (RFC 2781) # https://tools.ietf.org/html/rfc2781 ## is made up of 16-bit words,
4006and is a superset of Unicode ranges 0x0000 to 0xD7FF and 0xE000 to 0xFFFF.
4007#A UTF-32 # http://www.unicode.org/versions/Unicode5.0.0/ch03.pdf ## is
4008made up of 32-bit words, and is a superset of Unicode.
4009
4010Font_Manager uses font data to convert character code points into glyph indices.
4011A glyph index is a 16-bit word.
4012
4013TextEncoding is set to kUTF8_TextEncoding by default.
4014
4015#Const kUTF8_TextEncoding 0
4016Uses bytes to represent UTF-8 or ASCII.
4017##
4018#Const kUTF16_TextEncoding 1
4019Uses two byte words to represent most of Unicode.
4020##
4021#Const kUTF32_TextEncoding 2
4022Uses four byte words to represent all of Unicode.
4023##
4024#Const kGlyphID_TextEncoding 3
4025Uses two byte words to represent glyph indices.
4026##
4027
4028#Enum ##
4029
4030#Example
4031#Height 128
4032#Description
4033First line has UTF-8 encoding.
4034Second line has UTF-16 encoding.
4035Third line has UTF-32 encoding.
4036Fourth line has 16 bit glyph indices.
4037##
4038void draw(SkCanvas* canvas) {
4039 SkPaint paint;
4040 const char hello8[] = "Hello" "\xE2" "\x98" "\xBA";
4041 const uint16_t hello16[] = { 'H', 'e', 'l', 'l', 'o', 0x263A };
4042 const uint32_t hello32[] = { 'H', 'e', 'l', 'l', 'o', 0x263A };
4043 paint.setTextSize(24);
4044 canvas->drawText(hello8, sizeof(hello8) - 1, 10, 30, paint);
4045 paint.setTextEncoding(SkPaint::kUTF16_TextEncoding);
4046 canvas->drawText(hello16, sizeof(hello16), 10, 60, paint);
4047 paint.setTextEncoding(SkPaint::kUTF32_TextEncoding);
4048 canvas->drawText(hello32, sizeof(hello32), 10, 90, paint);
4049 uint16_t glyphs[SK_ARRAY_COUNT(hello32)];
4050 paint.textToGlyphs(hello32, sizeof(hello32), glyphs);
4051 paint.setTextEncoding(SkPaint::kGlyphID_TextEncoding);
4052 canvas->drawText(glyphs, sizeof(glyphs), 10, 120, paint);
4053}
4054##
4055
4056#Method TextEncoding getTextEncoding() const
4057
4058 Returns Text_Encoding.
4059 Text_Encoding determines how character code points are mapped to font glyph indices.
4060
4061 #Return one of: kUTF8_TextEncoding, kUTF16_TextEncoding, kUTF32_TextEncoding, or
4062 kGlyphID_TextEncoding
4063 ##
4064
4065 #Example
4066 SkPaint paint;
4067 SkDebugf("kUTF8_TextEncoding %c= text encoding\n",
4068 SkPaint::kUTF8_TextEncoding == paint.getTextEncoding() ? '=' : '!');
4069 paint.setTextEncoding(SkPaint::kGlyphID_TextEncoding);
4070 SkDebugf("kGlyphID_TextEncoding %c= text encoding\n",
4071 SkPaint::kGlyphID_TextEncoding == paint.getTextEncoding() ? '=' : '!');
4072
4073 #StdOut
4074 kUTF8_TextEncoding == text encoding
4075 kGlyphID_TextEncoding == text encoding
4076 ##
4077 ##
4078
4079##
4080
4081
4082#Method void setTextEncoding(TextEncoding encoding)
4083
4084 Sets Text_Encoding to encoding.
4085 Text_Encoding determines how character code points are mapped to font glyph indices.
4086 Invalid values for encoding are ignored.
4087
4088 #Param encoding one of: kUTF8_TextEncoding, kUTF16_TextEncoding, kUTF32_TextEncoding, or
Cary Clark579985c2017-07-31 11:48:27 -04004089 kGlyphID_TextEncoding
4090 #Param ##
Cary Clark8032b982017-07-28 11:04:54 -04004091
4092 #Example
4093 SkPaint paint;
4094 paint.setTextEncoding((SkPaint::TextEncoding) 4);
4095 SkDebugf("4 %c= text encoding\n", 4 == paint.getTextEncoding() ? '=' : '!');
4096
4097 #StdOut
4098 4 != text encoding
4099 ##
4100 ##
4101
4102##
4103
4104#Topic ##
4105# ------------------------------------------------------------------------------
4106#Topic Font_Metrics
4107
4108Font_Metrics describe dimensions common to the glyphs in Typeface.
4109The dimensions are computed by Font_Manager from font data and do not take
4110Paint settings other than Text_Size into account.
4111
4112Font dimensions specify the anchor to the left of the glyph at baseline as the origin.
4113X-axis values to the left of the glyph are negative, and to the right of the left glyph edge
4114are positive.
4115Y-axis values above the baseline are negative, and below the baseline are positive.
4116
4117#Example
4118#Width 512
4119void draw(SkCanvas* canvas) {
4120 SkPaint paint;
4121 paint.setAntiAlias(true);
4122 paint.setTextSize(120);
4123 SkPaint::FontMetrics fm;
4124 SkScalar lineHeight = paint.getFontMetrics(&fm);
4125 SkPoint pt = { 70, 180 };
4126 canvas->drawString("M", pt.fX, pt.fY, paint);
4127 canvas->drawLine(pt.fX, pt.fY, pt.fX, pt.fY + fm.fTop, paint);
4128 SkScalar ascent = pt.fY + fm.fAscent;
4129 canvas->drawLine(pt.fX - 25, ascent, pt.fX - 25, ascent + lineHeight, paint);
4130 canvas->drawLine(pt.fX - 50, pt.fY, pt.fX - 50, pt.fY + fm.fDescent, paint);
4131 canvas->drawLine(pt.fX + 100, pt.fY, pt.fX + 100, pt.fY + fm.fAscent, paint);
4132 canvas->drawLine(pt.fX + 125, pt.fY, pt.fX + 125, pt.fY - fm.fXHeight, paint);
4133 canvas->drawLine(pt.fX + 150, pt.fY, pt.fX + 150, pt.fY - fm.fCapHeight, paint);
4134 canvas->drawLine(pt.fX + 5, pt.fY, pt.fX + 5, pt.fY + fm.fBottom, paint);
4135 SkScalar xmin = pt.fX + fm.fXMin;
4136 canvas->drawLine(xmin, pt.fY + 60, xmin + fm.fMaxCharWidth, pt.fY + 60, paint);
4137 canvas->drawLine(xmin, pt.fY - 145, pt.fX, pt.fY - 145, paint);
4138 canvas->drawLine(pt.fX + fm.fXMax, pt.fY - 160, pt.fX, pt.fY - 160, paint);
4139 SkScalar upos = pt.fY + fm.fUnderlinePosition;
4140 canvas->drawLine(pt.fX + 25, upos, pt.fX + 130, upos, paint);
4141 SkScalar urad = fm.fUnderlineThickness / 2;
4142 canvas->drawLine(pt.fX + 130, upos - urad, pt.fX + 160, upos - urad, paint);
4143 canvas->drawLine(pt.fX + 130, upos + urad, pt.fX + 160, upos + urad, paint);
4144 paint.setTextSize(12);
4145 canvas->drawString("x-min", pt.fX - 50, pt.fY - 148, paint);
4146 canvas->drawString("x-max", pt.fX + 140, pt.fY - 150, paint);
4147 canvas->drawString("max char width", pt.fX + 120, pt.fY + 57, paint);
4148 canvas->drawString("underline position", pt.fX + 30, pt.fY + 22, paint);
4149 canvas->drawString("underline thickness", pt.fX + 162, pt.fY + 13, paint);
4150 canvas->rotate(-90);
4151 canvas->drawString("descent", -pt.fY - 30, pt.fX - 54, paint);
4152 canvas->drawString("line height", -pt.fY, pt.fX - 29, paint);
4153 canvas->drawString("top", -pt.fY + 30, pt.fX - 4, paint);
4154 canvas->drawString("ascent", -pt.fY, pt.fX + 110, paint);
4155 canvas->drawString("x-height", -pt.fY, pt.fX + 135, paint);
4156 canvas->drawString("cap-height", -pt.fY, pt.fX + 160, paint);
4157 canvas->drawString("bottom", -pt.fY - 50, pt.fX + 15, paint);
4158}
4159##
4160
4161#Struct FontMetrics
4162
4163#Code
4164 struct FontMetrics {
4165 enum FontMetricsFlags {
4166 kUnderlineThicknessIsValid_Flag = 1 << 0,
4167 kUnderlinePositionIsValid_Flag = 1 << 1,
4168 kStrikeoutThicknessIsValid_Flag = 1 << 2,
4169 kStrikeoutPositionIsValid_Flag = 1 << 3,
4170 };
4171
4172 uint32_t fFlags;
4173 SkScalar fTop;
4174 SkScalar fAscent;
4175 SkScalar fDescent;
4176 SkScalar fBottom;
4177 SkScalar fLeading;
4178 SkScalar fAvgCharWidth;
4179 SkScalar fMaxCharWidth;
4180 SkScalar fXMin;
4181 SkScalar fXMax;
4182 SkScalar fXHeight;
4183 SkScalar fCapHeight;
4184 SkScalar fUnderlineThickness;
4185 SkScalar fUnderlinePosition;
4186 SkScalar fStrikeoutThickness;
4187 SkScalar fStrikeoutPosition;
4188
4189 bool hasUnderlineThickness(SkScalar* thickness) const;
4190 bool hasUnderlinePosition(SkScalar* position) const;
4191 bool hasStrikeoutThickness(SkScalar* thickness) const;
4192 bool hasStrikeoutPosition(SkScalar* position) const;
4193 };
4194##
4195
4196 FontMetrics is filled out by getFontMetrics. FontMetrics contents reflect the values
4197 computed by Font_Manager using Typeface. Values are set to zero if they are
4198 not availble.
4199
4200 fUnderlineThickness and fUnderlinePosition have a bit set in fFlags if their values
4201 are valid, since their value may be zero.
4202
4203 fStrikeoutThickness and fStrikeoutPosition have a bit set in fFlags if their values
4204 are valid, since their value may be zero.
4205
4206 #Enum FontMetricsFlags
4207 #Code
4208 enum FontMetricsFlags {
4209 kUnderlineThicknessIsValid_Flag = 1 << 0,
4210 kUnderlinePositionIsValid_Flag = 1 << 1,
4211 kStrikeoutThicknessIsValid_Flag = 1 << 2,
4212 kStrikeoutPositionIsValid_Flag = 1 << 3,
4213 };
4214 ##
4215
4216 FontMetricsFlags are set in fFlags when underline and strikeout metrics are valid;
4217 the underline or strikeout metric may be valid and zero.
4218 Fonts with embedded bitmaps may not have valid underline or strikeout metrics.
4219
4220 #Const kUnderlineThicknessIsValid_Flag 0x0001
4221 Set if fUnderlineThickness is valid.
4222 ##
4223 #Const kUnderlinePositionIsValid_Flag 0x0002
4224 Set if fUnderlinePosition is valid.
4225 ##
4226 #Const kStrikeoutThicknessIsValid_Flag 0x0004
4227 Set if fStrikeoutThickness is valid.
4228 ##
4229 #Const kStrikeoutPositionIsValid_Flag 0x0008
4230 Set if fStrikeoutPosition is valid.
4231 ##
4232
4233 #Enum ##
4234
4235 #Member uint32_t fFlags
4236 fFlags is set when underline metrics are valid.
4237 ##
4238
4239 #Member SkScalar fTop
4240 Largest height for any glyph.
4241 A measure from the baseline, and is less than or equal to zero.
4242 ##
4243
4244 #Member SkScalar fAscent
4245 Recommended distance above the baseline to reserve for a line of text.
4246 A measure from the baseline, and is less than or equal to zero.
4247 ##
4248
4249 #Member SkScalar fDescent
4250 Recommended distance below the baseline to reserve for a line of text.
4251 A measure from the baseline, and is greater than or equal to zero.
4252 ##
4253
4254 #Member SkScalar fBottom
4255 Greatest extent below the baseline for any glyph.
4256 A measure from the baseline, and is greater than or equal to zero.
4257 ##
4258
4259 #Member SkScalar fLeading
4260 Recommended distance to add between lines of text.
4261 Greater than or equal to zero.
4262 ##
4263
4264 #Member SkScalar fAvgCharWidth
4265 Average character width, if it is available.
4266 Zero if no average width is stored in the font.
4267 ##
4268
4269 #Member SkScalar fMaxCharWidth
4270 Maximum character width.
4271 ##
4272
4273 #Member SkScalar fXMin
4274 Minimum bounding box x value for all glyphs.
4275 Typically less than zero.
4276 ##
4277
4278 #Member SkScalar fXMax
4279 Maximum bounding box x value for all glyphs.
4280 Typically greater than zero.
4281 ##
4282
4283 #Member SkScalar fXHeight
4284 Height of a lower-case 'x'.
4285 May be zero if no lower-case height is stored in the font.
4286 ##
4287
4288 #Member SkScalar fCapHeight
4289 Height of an upper-case letter.
4290 May be zero if no upper-case height is stored in the font.
4291 ##
4292
4293 #Member SkScalar fUnderlineThickness
4294 Underline thickness. If the metric
4295 is valid, the kUnderlineThicknessIsValid_Flag is set in fFlags.
4296 If kUnderlineThicknessIsValid_Flag is clear, fUnderlineThickness is zero.
4297 ##
4298
4299 #Member SkScalar fUnderlinePosition
4300 Underline position relative to the baseline.
4301 It may be negative, to draw the underline above the baseline, zero
4302 to draw the underline on the baseline, or positive to draw the underline
4303 below the baseline.
4304
4305 If the metric is valid, the kUnderlinePositionIsValid_Flag is set in fFlags.
4306 If kUnderlinePositionIsValid_Flag is clear, fUnderlinePosition is zero.
4307 ##
4308
4309 #Member SkScalar fStrikeoutThickness
4310 Strikeout thickness. If the metric
4311 is valid, the kStrikeoutThicknessIsValid_Flag is set in fFlags.
4312 If kStrikeoutThicknessIsValid_Flag is clear, fStrikeoutThickness is zero.
4313 ##
4314
4315 #Member SkScalar fStrikeoutPosition
4316 Strikeout position relative to the baseline.
4317 It may be negative, to draw the strikeout above the baseline, zero
4318 to draw the strikeout on the baseline, or positive to draw the strikeout
4319 below the baseline.
4320
4321 If the metric is valid, the kStrikeoutPositionIsValid_Flag is set in fFlags.
4322 If kStrikeoutPositionIsValid_Flag is clear, fStrikeoutPosition is zero.
4323 ##
4324
4325 #Method bool hasUnderlineThickness(SkScalar* thickness) const
4326
4327 If Font_Metrics has a valid underline thickness, return true, and set
4328 thickness to that value. If it doesn't, return false, and ignore
4329 thickness.
4330
4331 #Param thickness storage for underline width ##
4332
4333 #Return true if font specifies underline width ##
4334
4335 #NoExample
4336 ##
4337 ##
4338
4339 #Method bool hasUnderlinePosition(SkScalar* position) const
4340
4341 If Font_Metrics has a valid underline position, return true, and set
4342 position to that value. If it doesn't, return false, and ignore
4343 position.
4344
4345 #Param position storage for underline position ##
4346
4347 #Return true if font specifies underline position ##
4348
4349 #NoExample
4350 ##
4351 ##
4352
4353 #Method bool hasStrikeoutThickness(SkScalar* thickness) const
4354
4355 If Font_Metrics has a valid strikeout thickness, return true, and set
4356 thickness to that value. If it doesn't, return false, and ignore
4357 thickness.
4358
4359 #Param thickness storage for strikeout width ##
4360
4361 #Return true if font specifies strikeout width ##
4362
4363 #NoExample
4364 ##
4365 ##
4366
4367 #Method bool hasStrikeoutPosition(SkScalar* position) const
4368
4369 If Font_Metrics has a valid strikeout position, return true, and set
4370 position to that value. If it doesn't, return false, and ignore
4371 position.
4372
4373 #Param position storage for strikeout position ##
4374
4375 #Return true if font specifies strikeout position ##
4376
4377 #NoExample
4378 ##
4379 ##
4380
4381#Struct ##
4382
4383#Method SkScalar getFontMetrics(FontMetrics* metrics, SkScalar scale = 0) const
4384
4385 Returns Font_Metrics associated with Typeface.
4386 The return value is the recommended spacing between lines: the sum of metrics
4387 descent, ascent, and leading.
4388 If metrics is not nullptr, Font_Metrics is copied to metrics.
4389 Results are scaled by Text_Size but does not take into account
4390 dimensions required by Text_Scale_X, Text_Skew_X, Fake_Bold,
4391 Style_Stroke, and Path_Effect.
4392 Results can be additionally scaled by scale; a scale of zero
4393 is ignored.
4394
4395 #Param metrics storage for Font_Metrics from Typeface; may be nullptr ##
4396 #Param scale additional multiplier for returned values ##
4397
4398 #Return recommended spacing between lines ##
4399
4400 #Example
4401 #Height 128
4402 void draw(SkCanvas* canvas) {
4403 SkPaint paint;
4404 paint.setTextSize(32);
4405 SkScalar lineHeight = paint.getFontMetrics(nullptr);
4406 canvas->drawString("line 1", 10, 40, paint);
4407 canvas->drawString("line 2", 10, 40 + lineHeight, paint);
4408 paint.setStyle(SkPaint::kStroke_Style);
4409 paint.setStrokeWidth(10);
4410 lineHeight = paint.getFontMetrics(nullptr, 1.10f); // account for stroke height
4411 canvas->drawString("line 3", 120, 40, paint);
4412 canvas->drawString("line 4", 120, 40 + lineHeight, paint);
4413 }
4414 ##
4415
4416 #SeeAlso Text_Size Typeface Typeface_Methods
4417
4418##
4419
4420
4421#Method SkScalar getFontSpacing() const
4422
4423 Returns the recommended spacing between lines: the sum of metrics
4424 descent, ascent, and leading.
4425 Result is scaled by Text_Size but does not take into account
4426 dimensions required by stroking and Path_Effect.
Cary Clark579985c2017-07-31 11:48:27 -04004427 Returns the same result as getFontMetrics.
Cary Clark8032b982017-07-28 11:04:54 -04004428
4429 #Return recommended spacing between lines ##
4430
4431 #Example
4432 SkPaint paint;
4433 for (SkScalar textSize : { 12, 18, 24, 32 } ) {
4434 paint.setTextSize(textSize);
4435 SkDebugf("textSize: %g fontSpacing: %g\n", textSize, paint.getFontSpacing());
4436 }
4437
4438 #StdOut
4439 textSize: 12 fontSpacing: 13.9688
4440 textSize: 18 fontSpacing: 20.9531
4441 textSize: 24 fontSpacing: 27.9375
4442 textSize: 32 fontSpacing: 37.25
4443 ##
4444 ##
4445
4446##
4447
4448
4449#Method SkRect getFontBounds() const
4450
4451Returns the union of bounds of all glyphs.
4452Returned dimensions are computed by Font_Manager from font data,
Cary Clark579985c2017-07-31 11:48:27 -04004453ignoring Hinting. Includes Text_Size, Text_Scale_X,
Cary Clark8032b982017-07-28 11:04:54 -04004454and Text_Skew_X, but not Fake_Bold or Path_Effect.
4455
4456If Text_Size is large, Text_Scale_X is one, and Text_Skew_X is zero,
Cary Clark579985c2017-07-31 11:48:27 -04004457returns the same bounds as Font_Metrics { FontMetrics::fXMin,
Cary Clark8032b982017-07-28 11:04:54 -04004458FontMetrics::fTop, FontMetrics::fXMax, FontMetrics::fBottom }.
4459
4460#Return union of bounds of all glyphs ##
4461
4462#Example
4463 SkPaint paint;
4464 SkPaint::FontMetrics fm;
4465 paint.getFontMetrics(&fm);
4466 SkRect fb = paint.getFontBounds();
4467 SkDebugf("metrics bounds = { %g, %g, %g, %g }\n", fm.fXMin, fm.fTop, fm.fXMax, fm.fBottom );
4468 SkDebugf("font bounds = { %g, %g, %g, %g }\n", fb.fLeft, fb.fTop, fb.fRight, fm.fBottom );
4469
4470 #StdOut
4471 metrics bounds = { -12.2461, -14.7891, 21.5215, 5.55469 }
4472 font bounds = { -12.2461, -14.7891, 21.5215, 5.55469 }
4473 ##
4474##
4475
4476##
4477
4478#Topic ##
4479# ------------------------------------------------------------------------------
4480
4481#Method int textToGlyphs(const void* text, size_t byteLength,
4482 SkGlyphID glyphs[]) const
4483
4484Converts text into glyph indices.
4485Returns the number of glyph indices represented by text.
4486Text_Encoding specifies how text represents characters or glyphs.
4487glyphs may be nullptr, to compute the glyph count.
4488
4489Does not check text for valid character encoding or valid
4490glyph indices.
4491
Cary Clark579985c2017-07-31 11:48:27 -04004492If byteLength equals zero, returns zero.
Cary Clark8032b982017-07-28 11:04:54 -04004493If byteLength includes a partial character, the partial character is ignored.
4494
4495If Text_Encoding is kUTF8_TextEncoding and
4496text contains an invalid UTF-8 sequence, zero is returned.
4497
4498#Param text character stroage encoded with Text_Encoding ##
4499#Param byteLength length of character storage in bytes ##
4500#Param glyphs storage for glyph indices; may be nullptr ##
4501
4502#Return number of glyphs represented by text of length byteLength ##
4503
4504 #Example
4505 #Height 64
4506 void draw(SkCanvas* canvas) {
4507 SkPaint paint;
4508 const uint8_t utf8[] = { 0x24, 0xC2, 0xA2, 0xE2, 0x82, 0xAC, 0xC2, 0xA5, 0xC2, 0xA3 };
4509 std::vector<SkGlyphID> glyphs;
4510 int count = paint.textToGlyphs(utf8, sizeof(utf8), nullptr);
4511 glyphs.resize(count);
4512 (void) paint.textToGlyphs(utf8, sizeof(utf8), &glyphs.front());
4513 paint.setTextEncoding(SkPaint::kGlyphID_TextEncoding);
4514 paint.setTextSize(32);
4515 canvas->drawText(&glyphs.front(), glyphs.size() * sizeof(SkGlyphID), 10, 40, paint);
4516 }
4517 ##
4518
4519##
4520
4521#Method int countText(const void* text, size_t byteLength) const
4522
4523 Returns the number of glyphs in text.
4524 Uses Text_Encoding to count the glyphs.
4525 Returns the same result as textToGlyphs.
4526
4527#Param text character stroage encoded with Text_Encoding ##
4528#Param byteLength length of character storage in bytes ##
4529
4530#Return number of glyphs represented by text of length byteLength ##
4531
4532 #Example
4533 SkPaint paint;
4534 const uint8_t utf8[] = { 0x24, 0xC2, 0xA2, 0xE2, 0x82, 0xAC, 0xC2, 0xA5, 0xC2, 0xA3 };
4535 SkDebugf("count = %d\n", paint.countText(utf8, sizeof(utf8)));
4536
4537 #StdOut
4538 count = 5
4539 ##
4540 ##
4541##
4542
4543# ------------------------------------------------------------------------------
4544
4545#Method bool containsText(const void* text, size_t byteLength) const
4546
4547 Returns true if all text corresponds to a non-zero glyph index.
4548 Returns false if any characters in text are not supported in
4549 Typeface.
4550
Cary Clark579985c2017-07-31 11:48:27 -04004551 If Text_Encoding is kGlyphID_TextEncoding,
4552 returns true if all glyph indices in text are non-zero;
Cary Clark8032b982017-07-28 11:04:54 -04004553 does not check to see if text contains valid glyph indices for Typeface.
4554
4555 Returns true if bytelength is zero.
4556
4557 #Param text array of characters or glyphs ##
4558 #Param byteLength number of bytes in text array ##
4559
4560 #Return true if all text corresponds to a non-zero glyph index ##
4561
4562 #Example
4563 #Description
4564 containsText succeeds for degree symbol, but cannot find a glyph index
4565 corresponding to the Unicode surrogate code point.
4566 ##
4567 SkPaint paint;
4568 const uint16_t goodChar = 0x00B0; // degree symbol
4569 const uint16_t badChar = 0xD800; // Unicode surrogate
4570 paint.setTextEncoding(SkPaint::kUTF16_TextEncoding);
4571 SkDebugf("0x%04x %c= has char\n", goodChar,
4572 paint.containsText(&goodChar, 2) ? '=' : '!');
4573 SkDebugf("0x%04x %c= has char\n", badChar,
4574 paint.containsText(&badChar, 2) ? '=' : '!');
4575
4576 #StdOut
4577 0x00b0 == has char
4578 0xd800 != has char
4579 ##
4580 ##
4581
4582 #Example
4583 #Description
4584 containsText returns true that glyph index is greater than zero, not
4585 that it corresponds to an entry in Typeface.
4586 ##
4587 SkPaint paint;
4588 const uint16_t goodGlyph = 511;
4589 const uint16_t zeroGlyph = 0;
4590 const uint16_t badGlyph = 65535; // larger than glyph count in font
4591 paint.setTextEncoding(SkPaint::kGlyphID_TextEncoding);
4592 SkDebugf("0x%04x %c= has glyph\n", goodGlyph,
4593 paint.containsText(&goodGlyph, 2) ? '=' : '!');
4594 SkDebugf("0x%04x %c= has glyph\n", zeroGlyph,
4595 paint.containsText(&zeroGlyph, 2) ? '=' : '!');
4596 SkDebugf("0x%04x %c= has glyph\n", badGlyph,
4597 paint.containsText(&badGlyph, 2) ? '=' : '!');
4598
4599 #StdOut
4600 0x01ff == has glyph
4601 0x0000 != has glyph
4602 0xffff == has glyph
4603 ##
4604 ##
4605
4606#SeeAlso setTextEncoding Typeface
4607
4608##
4609
4610# ------------------------------------------------------------------------------
4611
4612#Method void glyphsToUnichars(const SkGlyphID glyphs[],
4613 int count, SkUnichar text[]) const
4614
4615 Converts glyphs into text if possible.
4616 Glyph values without direct Unicode equivalents are mapped to zero.
4617 Uses the Typeface, but is unaffected
4618 by Text_Encoding; the text values returned are equivalent to kUTF32_TextEncoding.
4619
4620 Only supported on platforms that use FreeType as the Font_Engine.
4621
4622 #Param glyphs array of indices into font ##
4623 #Param count length of glyph array ##
4624 #Param text storage for character codes, one per glyph ##
4625
4626 #Example
4627 #Height 64
4628 #Description
4629 Convert UTF-8 text to glyphs; then convert glyphs to Unichar code points.
4630 ##
4631 void draw(SkCanvas* canvas) {
4632 SkPaint paint;
4633 const char hello[] = "Hello!";
4634 const int count = sizeof(hello) - 1;
4635 SkGlyphID glyphs[count];
4636 if (count != paint.textToGlyphs(hello, count, glyphs)) {
4637 return;
4638 }
4639 SkUnichar unichars[count];
4640 paint.glyphsToUnichars(glyphs, count, unichars);
4641 paint.setTextEncoding(SkPaint::kUTF32_TextEncoding);
4642 canvas->drawText(unichars, sizeof(unichars), 10, 30, paint);
4643 }
4644 ##
4645
4646##
4647
4648# ------------------------------------------------------------------------------
4649#Topic Measure_Text
4650
4651#Method SkScalar measureText(const void* text, size_t length, SkRect* bounds) const
4652
4653 Returns the advance width of text if kVerticalText_Flag is clear,
4654 and the height of text if kVerticalText_Flag is set.
4655 The advance is the normal distance to move before drawing additional text.
4656 Uses Text_Encoding to decode text, Typeface to get the font metrics,
4657 and Text_Size, Text_Scale_X, Text_Skew_X, Stroke_Width, and
4658 Path_Effect to scale the metrics and bounds.
4659 Returns the bounding box of text if bounds is not nullptr.
4660 The bounding box is computed as if the text was drawn at the origin.
4661
4662 #Param text character codes or glyph indices to be measured ##
4663 #Param length number of bytes of text to measure ##
4664 #Param bounds returns bounding box relative to (0, 0) if not nullptr ##
4665
4666 #Return advance width or height ##
4667
4668 #Example
4669 #Height 64
4670 void draw(SkCanvas* canvas) {
4671 SkPaint paint;
4672 paint.setAntiAlias(true);
4673 paint.setTextSize(50);
4674 const char str[] = "ay^jZ";
4675 const int count = sizeof(str) - 1;
4676 canvas->drawText(str, count, 25, 50, paint);
4677 SkRect bounds;
4678 paint.measureText(str, count, &bounds);
4679 canvas->translate(25, 50);
4680 paint.setStyle(SkPaint::kStroke_Style);
4681 canvas->drawRect(bounds, paint);
4682 }
4683 ##
4684
4685##
4686
4687#Method SkScalar measureText(const void* text, size_t length) const
4688
4689 Returns the advance width of text if kVerticalText_Flag is clear,
4690 and the height of text if kVerticalText_Flag is set.
4691 The advance is the normal distance to move before drawing additional text.
4692 Uses Text_Encoding to decode text, Typeface to get the font metrics,
4693 and Text_Size to scale the metrics.
4694 Does not scale the advance or bounds by Fake_Bold or Path_Effect.
4695
4696 #Param text character codes or glyph indices to be measured ##
4697 #Param length number of bytes of text to measure ##
4698
4699 #Return advance width or height ##
4700
4701 #Example
4702 SkPaint paint;
4703 SkDebugf("default width = %g\n", paint.measureText("!", 1));
4704 paint.setTextSize(paint.getTextSize() * 2);
4705 SkDebugf("double width = %g\n", paint.measureText("!", 1));
4706
4707 #StdOut
4708 default width = 5
4709 double width = 10
4710 ##
4711 ##
4712
4713##
4714
4715#Method size_t breakText(const void* text, size_t length, SkScalar maxWidth,
4716 SkScalar* measuredWidth = NULL) const
4717
4718 Returns the bytes of text that fit within maxWidth.
4719 If kVerticalText_Flag is clear, the text fragment fits if its advance width is less than or
4720 equal to maxWidth.
4721 If kVerticalText_Flag is set, the text fragment fits if its advance height is less than or
4722 equal to maxWidth.
4723 Measures only while the advance is less than or equal to maxWidth.
4724 Returns the advance or the text fragment in measuredWidth if it not nullptr.
4725 Uses Text_Encoding to decode text, Typeface to get the font metrics,
4726 and Text_Size to scale the metrics.
4727 Does not scale the advance or bounds by Fake_Bold or Path_Effect.
4728
4729 #Param text character codes or glyph indices to be measured ##
4730 #Param length number of bytes of text to measure ##
4731 #Param maxWidth advance limit; text is measured while advance is less than maxWidth ##
4732 #Param measuredWidth returns the width of the text less than or equal to maxWidth ##
4733 #Return bytes of text that fit, always less than or equal to length ##
4734
4735 #Example
4736 #Description
4737 Line under "Breakfast" shows desired width, shorter than available characters.
4738 Line under "Bre" shows measured width after breaking text.
4739 ##
4740 #Height 128
4741 #Width 280
4742 void draw(SkCanvas* canvas) {
4743 SkPaint paint;
4744 paint.setAntiAlias(true);
4745 paint.setTextSize(50);
4746 const char str[] = "Breakfast";
4747 const int count = sizeof(str) - 1;
4748 canvas->drawText(str, count, 25, 50, paint);
4749 SkScalar measuredWidth;
4750 int partialBytes = paint.breakText(str, count, 100, &measuredWidth);
4751 canvas->drawText(str, partialBytes, 25, 100, paint);
4752 canvas->drawLine(25, 60, 25 + 100, 60, paint);
4753 canvas->drawLine(25, 110, 25 + measuredWidth, 110, paint);
4754 }
4755 ##
4756
4757##
4758
4759#Method int getTextWidths(const void* text, size_t byteLength, SkScalar widths[],
4760 SkRect bounds[] = NULL) const
4761
4762 Retrieves the advance and bounds for each glyph in text, and returns
4763 the glyph count in text.
4764 Both widths and bounds may be nullptr.
4765 If widths is not nullptr, widths must be an array of glyph count entries.
4766 if bounds is not nullptr, bounds must be an array of glyph count entries.
4767 If kVerticalText_Flag is clear, widths returns the horizontal advance.
4768 If kVerticalText_Flag is set, widths returns the vertical advance.
4769 Uses Text_Encoding to decode text, Typeface to get the font metrics,
4770 and Text_Size to scale the widths and bounds.
4771 Does not scale the advance by Fake_Bold or Path_Effect.
4772 Does include Fake_Bold and Path_Effect in the bounds.
4773
4774 #Param text character codes or glyph indices to be measured ##
4775 #Param byteLength number of bytes of text to measure ##
4776 #Param widths returns text advances for each glyph; may be nullptr ##
4777 #Param bounds returns bounds for each glyph relative to (0, 0); may be nullptr ##
4778
4779 #Return glyph count in text ##
4780
4781 #Example
4782 #Height 160
4783 #Description
4784 Bounds of glyphs increase for stroked text, but text advance remains the same.
4785 The underlines show the text advance, spaced to keep them distinct.
4786 ##
4787 void draw(SkCanvas* canvas) {
4788 SkPaint paint;
4789 paint.setAntiAlias(true);
4790 paint.setTextSize(50);
4791 const char str[] = "abc";
4792 const int bytes = sizeof(str) - 1;
4793 int count = paint.getTextWidths(str, bytes, nullptr);
4794 std::vector<SkScalar> widths;
4795 std::vector<SkRect> bounds;
4796 widths.resize(count);
4797 bounds.resize(count);
4798 for (int loop = 0; loop < 2; ++loop) {
4799 (void) paint.getTextWidths(str, count, &widths.front(), &bounds.front());
4800 SkPoint loc = { 25, 50 };
4801 canvas->drawText(str, bytes, loc.fX, loc.fY, paint);
4802 paint.setStyle(SkPaint::kStroke_Style);
4803 paint.setStrokeWidth(0);
4804 SkScalar advanceY = loc.fY + 10;
4805 for (int index = 0; index < count; ++index) {
4806 bounds[index].offset(loc.fX, loc.fY);
4807 canvas->drawRect(bounds[index], paint);
4808 canvas->drawLine(loc.fX, advanceY, loc.fX + widths[index], advanceY, paint);
4809 loc.fX += widths[index];
4810 advanceY += 5;
4811 }
4812 canvas->translate(0, 80);
4813 paint.setStrokeWidth(3);
4814 }
4815 }
4816 ##
4817
4818##
4819
4820#Topic ##
4821# ------------------------------------------------------------------------------
4822#Topic Text_Path
4823
4824Text_Path describes the geometry of glyphs used to draw text.
4825
4826#Method void getTextPath(const void* text, size_t length, SkScalar x, SkScalar y,
4827 SkPath* path) const
4828
4829Returns the geometry as Path equivalent to the drawn text.
4830Uses Text_Encoding to decode text, Typeface to get the glyph paths,
4831and Text_Size, Fake_Bold, and Path_Effect to scale and modify the glyph paths.
4832All of the glyph paths are stored in path.
Cary Clark579985c2017-07-31 11:48:27 -04004833Uses x, y, and Text_Align to position path.
Cary Clark8032b982017-07-28 11:04:54 -04004834
4835 #Param text character codes or glyph indices ##
4836 #Param length number of bytes of text ##
4837 #Param x x-coordinate of the origin of the text ##
4838 #Param y y-coordinate of the origin of the text ##
4839 #Param path geometry of the glyphs ##
4840
4841 #Example
4842 #Description
4843 Text is added to Path, offset, and subtracted from Path, then added at
4844 the offset location. The result is rendered with one draw call.
4845 ##
4846 #Height 128
4847 void draw(SkCanvas* canvas) {
4848 SkPaint paint;
4849 paint.setTextSize(80);
4850 SkPath path, path2;
4851 paint.getTextPath("ABC", 3, 20, 80, &path);
4852 path.offset(20, 20, &path2);
4853 Op(path, path2, SkPathOp::kDifference_SkPathOp, &path);
4854 path.addPath(path2);
4855 paint.setStyle(SkPaint::kStroke_Style);
4856 canvas->drawPath(path, paint);
4857 }
4858 ##
4859
4860##
4861
4862#Method void getPosTextPath(const void* text, size_t length,
4863 const SkPoint pos[], SkPath* path) const
4864
4865Returns the geometry as Path equivalent to the drawn text.
4866Uses Text_Encoding to decode text, Typeface to get the glyph paths,
4867and Text_Size, Fake_Bold, and Path_Effect to scale and modify the glyph paths.
4868All of the glyph paths are stored in path.
4869Uses pos array and Text_Align to position path.
4870pos contains a position for each glyph.
4871
4872 #Param text character codes or glyph indices ##
4873 #Param length number of bytes of text ##
4874 #Param pos positions of each glyph ##
4875 #Param path geometry of the glyphs ##
4876
4877 #Example
4878 #Height 85
4879 #Description
4880 Simplifies three glyphs to eliminate overlaps, and strokes the result.
4881 ##
4882 void draw(SkCanvas* canvas) {
4883 SkPaint paint;
4884 paint.setTextSize(80);
4885 SkPath path, path2;
4886 SkPoint pos[] = {{20, 60}, {30, 70}, {40, 80}};
4887 paint.getPosTextPath("ABC", 3, pos, &path);
4888 Simplify(path, &path);
4889 paint.setStyle(SkPaint::kStroke_Style);
4890 canvas->drawPath(path, paint);
4891 }
4892 ##
4893
4894##
4895
4896#Topic ##
4897# ------------------------------------------------------------------------------
4898#Topic Text_Intercepts
4899
4900Text_Intercepts describe the intersection of drawn text glyphs with a pair
4901of lines parallel to the text advance. Text_Intercepts permits creating a
4902underline that skips descenders.
4903
4904#Method int getTextIntercepts(const void* text, size_t length, SkScalar x, SkScalar y,
4905 const SkScalar bounds[2], SkScalar* intervals) const
4906
4907 Returns the number of intervals that intersect bounds.
4908 bounds describes a pair of lines parallel to the text advance.
4909 The return count is zero or a multiple of two, and is at most twice the number of glyphs in
4910 the string.
4911 Uses Text_Encoding to decode text, Typeface to get the glyph paths,
4912 and Text_Size, Fake_Bold, and Path_Effect to scale and modify the glyph paths.
4913 Uses x, y, and Text_Align to position intervals.
4914
4915 Pass nullptr for intervals to determine the size of the interval array.
4916
4917 intervals are cached to improve performance for multiple calls.
4918
4919 #Param text character codes or glyph indices ##
4920 #Param length number of bytes of text ##
4921 #Param x x-coordinate of the origin of the text ##
4922 #Param y y-coordinate of the origin of the text ##
4923 #Param bounds lower and upper line parallel to the advance ##
4924 #Param intervals returned intersections; may be nullptr ##
4925
4926 #Return number of intersections; may be zero ##
4927
4928#Example
4929#Height 128
4930#Description
4931Underline uses intercepts to draw on either side of the glyph descender.
4932##
4933void draw(SkCanvas* canvas) {
4934 SkPaint paint;
4935 paint.setTextSize(120);
4936 SkPoint textOrigin = { 20, 100 };
4937 SkScalar bounds[] = { 100, 108 };
4938 int count = paint.getTextIntercepts("y", 1, textOrigin.fX, textOrigin.fY, bounds, nullptr);
4939 std::vector<SkScalar> intervals;
4940 intervals.resize(count);
4941 (void) paint.getTextIntercepts("y", 1, textOrigin.fX, textOrigin.fY, bounds,
4942 &intervals.front());
4943 canvas->drawString("y", textOrigin.fX, textOrigin.fY, paint);
4944 paint.setColor(SK_ColorRED);
4945 SkScalar x = textOrigin.fX;
4946 for (int i = 0; i < count; i += 2) {
4947 canvas->drawRect({x, bounds[0], intervals[i], bounds[1]}, paint);
4948 x = intervals[i + 1];
4949 }
4950 canvas->drawRect({intervals[count - 1], bounds[0],
4951 textOrigin.fX + paint.measureText("y", 1), bounds[1]}, paint);
4952}
4953##
4954
4955##
4956
4957#Method int getPosTextIntercepts(const void* text, size_t length, const SkPoint pos[],
4958 const SkScalar bounds[2], SkScalar* intervals) const
4959
4960 Returns the number of intervals that intersect bounds.
4961 bounds describes a pair of lines parallel to the text advance.
4962 The return count is zero or a multiple of two, and is at most twice the number of glyphs in
4963 the string.
4964 Uses Text_Encoding to decode text, Typeface to get the glyph paths,
4965 and Text_Size, Fake_Bold, and Path_Effect to scale and modify the glyph paths.
4966 Uses pos array and Text_Align to position intervals.
4967
4968 Pass nullptr for intervals to determine the size of the interval array.
4969
4970 intervals are cached to improve performance for multiple calls.
4971
4972 #Param text character codes or glyph indices ##
4973 #Param length number of bytes of text ##
4974 #Param pos positions of each glyph ##
4975 #Param bounds lower and upper line parallel to the advance ##
4976 #Param intervals returned intersections; may be nullptr ##
4977
4978 #Return The number of intersections; may be zero ##
4979
4980 #Example
4981 #Description
4982 Text intercepts draw on either side of, but not inside, glyphs in a run.
4983 ##
4984 void draw(SkCanvas* canvas) {
4985 SkPaint paint;
4986 paint.setTextSize(120);
4987 paint.setVerticalText(true);
4988 SkPoint textPos[] = {{ 60, 40 }, { 60, 140 }};
4989 SkScalar bounds[] = { 56, 64 };
4990 const char str[] = "A-";
4991 int len = sizeof(str) - 1;
4992 int count = paint.getPosTextIntercepts(str, len, textPos, bounds, nullptr);
4993 std::vector<SkScalar> intervals;
4994 intervals.resize(count);
4995 (void) paint.getPosTextIntercepts(str, len, textPos, bounds, &intervals.front());
4996 canvas->drawPosText(str, len, textPos, paint);
4997 paint.setColor(SK_ColorRED);
4998 SkScalar y = textPos[0].fY;
4999 for (int i = 0; i < count; i+= 2) {
5000 canvas->drawRect({bounds[0], y, bounds[1], intervals[i]}, paint);
5001 y = intervals[i + 1];
5002 }
5003 canvas->drawRect({bounds[0], intervals[count - 1], bounds[1], 240}, paint);
5004 }
5005 ##
5006
5007##
5008
5009#Method int getPosTextHIntercepts(const void* text, size_t length, const SkScalar xpos[],
5010 SkScalar constY, const SkScalar bounds[2],
5011 SkScalar* intervals) const
5012
5013 Returns the number of intervals that intersect bounds.
5014 bounds describes a pair of lines parallel to the text advance.
5015 The return count is zero or a multiple of two, and is at most twice the number of glyphs in
5016 the string.
5017 Uses Text_Encoding to decode text, Typeface to get the glyph paths,
5018 and Text_Size, Fake_Bold, and Path_Effect to scale and modify the glyph paths.
5019 Uses xpos array, constY, and Text_Align to position intervals.
5020
5021 Pass nullptr for intervals to determine the size of the interval array.
5022
5023 intervals are cached to improve performance for multiple calls.
5024
5025 #Param text character codes or glyph indices ##
5026 #Param length number of bytes of text ##
5027 #Param xpos positions of each glyph in x ##
5028 #Param constY position of each glyph in y ##
5029 #Param bounds lower and upper line parallel to the advance ##
5030 #Param intervals returned intersections; may be nullptr ##
5031
5032 #Return number of intersections; may be zero ##
5033
5034 #Example
5035 #Height 128
5036 #Description
5037 Text intercepts do not take stroke thickness into consideration.
5038 ##
5039 void draw(SkCanvas* canvas) {
5040 SkPaint paint;
5041 paint.setTextSize(120);
5042 paint.setStyle(SkPaint::kStroke_Style);
5043 paint.setStrokeWidth(4);
5044 SkScalar textPosH[] = { 20, 80, 140 };
5045 SkScalar y = 100;
5046 SkScalar bounds[] = { 56, 78 };
5047 const char str[] = "\\-/";
5048 int len = sizeof(str) - 1;
5049 int count = paint.getPosTextHIntercepts(str, len, textPosH, y, bounds, nullptr);
5050 std::vector<SkScalar> intervals;
5051 intervals.resize(count);
5052 (void) paint.getPosTextHIntercepts(str, len, textPosH, y, bounds, &intervals.front());
5053 canvas->drawPosTextH(str, len, textPosH, y, paint);
5054 paint.setColor(0xFFFF7777);
5055 paint.setStyle(SkPaint::kFill_Style);
5056 SkScalar x = textPosH[0];
5057 for (int i = 0; i < count; i+= 2) {
5058 canvas->drawRect({x, bounds[0], intervals[i], bounds[1]}, paint);
5059 x = intervals[i + 1];
5060 }
5061 canvas->drawRect({intervals[count - 1], bounds[0], 180, bounds[1]}, paint);
5062 }
5063 ##
5064
5065##
5066
5067
5068#Method int getTextBlobIntercepts(const SkTextBlob* blob, const SkScalar bounds[2],
5069 SkScalar* intervals) const
5070
5071 Returns the number of intervals that intersect bounds.
5072 bounds describes a pair of lines parallel to the text advance.
5073 The return count is zero or a multiple of two, and is at most twice the number of glyphs in
5074 the string.
5075 Uses Text_Encoding to decode text, Typeface to get the glyph paths,
5076 and Text_Size, Fake_Bold, and Path_Effect to scale and modify the glyph paths.
5077 Uses pos array and Text_Align to position intervals.
5078
5079 Pass nullptr for intervals to determine the size of the interval array.
5080
5081 intervals are cached to improve performance for multiple calls.
5082
5083 #Param blob glyphs, positions, and text paint attributes ##
5084 #Param bounds lower and upper line parallel to the advance ##
5085 #Param intervals returned intersections; may be nullptr ##
5086
5087 #Return number of intersections; may be zero ##
5088
5089 #Example
5090 #Height 143
5091 void draw(SkCanvas* canvas) {
5092 SkPaint paint;
5093 paint.setTextSize(120);
5094 SkPoint textPos = { 20, 110 };
5095 int len = 3;
5096 SkTextBlobBuilder textBlobBuilder;
5097 const SkTextBlobBuilder::RunBuffer& run =
5098 textBlobBuilder.allocRun(paint, len, textPos.fX, textPos.fY);
5099 run.glyphs[0] = 10;
5100 run.glyphs[1] = 20;
5101 run.glyphs[2] = 30;
5102 sk_sp<const SkTextBlob> blob = textBlobBuilder.make();
5103 canvas->drawTextBlob(blob.get(), textPos.fX, textPos.fY, paint);
5104 SkScalar bounds[] = { 116, 134 };
5105 int count = paint.getTextBlobIntercepts(blob.get(), bounds, nullptr);
5106 std::vector<SkScalar> intervals;
5107 intervals.resize(count);
5108 (void) paint.getTextBlobIntercepts(blob.get(), bounds, &intervals.front());
5109 canvas->drawTextBlob(blob.get(), 0, 0, paint);
5110 paint.setColor(0xFFFF7777);
5111 SkScalar x = textPos.fX;
5112 for (int i = 0; i < count; i+= 2) {
5113 canvas->drawRect({x, bounds[0], intervals[i], bounds[1]}, paint);
5114 x = intervals[i + 1];
5115 }
5116 canvas->drawRect({intervals[count - 1], bounds[0], 180, bounds[1]}, paint);
5117 }
5118 ##
5119
5120##
5121
5122#Topic ##
5123# ------------------------------------------------------------------------------
5124
5125#Method bool nothingToDraw() const
5126
Cary Clark579985c2017-07-31 11:48:27 -04005127 Returns true if Paint prevents all drawing;
5128 otherwise, the Paint may or may not allow drawing.
Cary Clark8032b982017-07-28 11:04:54 -04005129
5130 Returns true if Blend_Mode and Color_Alpha are enabled,
5131 and computed Color_Alpha is zero.
5132
5133 #Return true if Paint prevents all drawing ##
5134
5135 #Example
5136 void draw(SkCanvas* canvas) {
5137 auto debugster = [](const char* prefix, const SkPaint& p) -> void {
5138 SkDebugf("%s nothing to draw: %s\n", prefix,
5139 p.nothingToDraw() ? "true" : "false");
5140 };
5141 SkPaint paint;
5142 debugster("initial", paint);
5143 paint.setBlendMode(SkBlendMode::kDst);
5144 debugster("blend dst", paint);
5145 paint.setBlendMode(SkBlendMode::kSrcOver);
5146 debugster("blend src over", paint);
5147 paint.setAlpha(0);
5148 debugster("alpha 0", paint);
5149 }
5150
5151 #StdOut
5152 initial nothing to draw: false
5153 blend dst nothing to draw: true
5154 blend src over nothing to draw: false
5155 alpha 0 nothing to draw: true
5156 #StdOut ##
5157 ##
5158
5159##
5160
5161# ------------------------------------------------------------------------------
5162#Topic Fast_Bounds
5163 #Private
5164 To be made private.
5165 ##
5166
5167Fast_Bounds methods conservatively outset a drawing bounds by additional area
5168Paint may draw to.
5169
5170#Method bool canComputeFastBounds() const
5171 #Private
5172 (to be made private)
5173 ##
5174
5175 Returns true if Paint does not include elements requiring extensive computation
5176 to compute Device bounds of drawn geometry. For instance, Paint with Path_Effect
5177 always returns false.
5178
5179 #Return true if Paint allows for fast computation of bounds ##
5180##
5181
5182#Method const SkRect& computeFastBounds(const SkRect& orig, SkRect* storage) const
5183 #Private
5184 (to be made private)
5185 ##
5186
5187 Only call this if canComputeFastBounds returned true. This takes a
5188 raw rectangle (the raw bounds of a shape), and adjusts it for stylistic
5189 effects in the paint (e.g. stroking). If needed, it uses the storage
5190 rect parameter. It returns the adjusted bounds that can then be used
5191 for SkCanvas::quickReject tests.
5192
5193 The returned rect will either be orig or storage, thus the caller
5194 should not rely on storage being set to the result, but should always
5195 use the retured value. It is legal for orig and storage to be the same
5196 rect.
5197
5198 #Private
5199 e.g.
5200 if (paint.canComputeFastBounds()) {
5201 SkRect r, storage;
5202 path.computeBounds(&r, SkPath::kFast_BoundsType);
5203 const SkRect& fastR = paint.computeFastBounds(r, &storage);
5204 if (canvas->quickReject(fastR, ...)) {
5205 // don't draw the path
5206 }
5207 }
5208 ##
5209
5210 #Param orig geometry modified by Paint when drawn ##
5211 #Param storage computed bounds of geometry; may not be nullptr ##
5212
5213 #Return fast computed bounds ##
5214##
5215
5216#Method const SkRect& computeFastStrokeBounds(const SkRect& orig,
5217 SkRect* storage) const
5218 #Private
5219 (to be made private)
5220 ##
5221
5222 #Param orig geometry modified by Paint when drawn ##
5223 #Param storage computed bounds of geometry ##
5224
5225 #Return fast computed bounds ##
5226##
5227
5228#Method const SkRect& doComputeFastBounds(const SkRect& orig, SkRect* storage,
5229 Style style) const
5230 #Private
5231 (to be made private)
5232 ##
5233
5234 Take the style explicitly, so the caller can force us to be stroked
5235 without having to make a copy of the paint just to change that field.
5236
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
5255Converts Paint to machine parsable form in developer mode.
5256
5257#Param str storage for string containing parsable Paint ##
5258
5259#Example
5260 SkPaint paint;
5261 SkString str;
5262 paint.toString(&str);
5263 const char textSize[] = "TextSize:";
5264 const int trailerSize = strlen("</dd><dt>");
5265 int textSizeLoc = str.find(textSize) + strlen(textSize) + trailerSize;
5266 const char* sizeStart = &str.c_str()[textSizeLoc];
5267 int textSizeEnd = SkStrFind(sizeStart, "</dd>");
5268 SkDebugf("text size = %.*s\n", textSizeEnd, sizeStart);
5269
5270 #StdOut
5271 text size = 12
5272 ##
5273
5274##
5275
5276#ToDo incomplete ##
5277
5278##
5279
5280# ------------------------------------------------------------------------------
5281
5282#Class SkPaint ##
5283
5284#Topic Paint ##