aboutsummaryrefslogtreecommitdiffhomepage
path: root/include/core/SkPaint.h
blob: 883e5c610e0552d7985d2f9e2aa961eb5de9f43e (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308
1309
1310
1311
1312
1313
1314
1315
1316
1317
1318
1319
1320
1321
1322
1323
1324
1325
1326
1327
1328
1329
1330
1331
1332
1333
1334
1335
1336
1337
1338
1339
1340
1341
1342
1343
1344
1345
1346
1347
1348
1349
1350
1351
1352
1353
1354
1355
1356
1357
1358
1359
1360
1361
1362
1363
1364
1365
1366
1367
1368
1369
1370
1371
1372
1373
1374
1375
1376
1377
1378
1379
1380
1381
1382
1383
1384
1385
1386
1387
1388
1389
1390
1391
1392
1393
1394
1395
1396
1397
1398
1399
1400
1401
1402
1403
1404
1405
1406
1407
1408
1409
1410
1411
1412
1413
1414
1415
1416
1417
1418
1419
1420
1421
1422
1423
1424
1425
1426
1427
1428
1429
1430
1431
1432
1433
1434
1435
1436
1437
1438
1439
1440
1441
1442
1443
1444
1445
1446
1447
1448
1449
1450
1451
1452
1453
1454
1455
1456
1457
1458
1459
1460
1461
1462
1463
1464
1465
1466
1467
1468
1469
1470
1471
1472
1473
1474
1475
1476
1477
1478
1479
1480
1481
1482
1483
1484
1485
1486
1487
1488
1489
1490
1491
1492
1493
1494
1495
1496
1497
1498
1499
1500
1501
1502
1503
1504
1505
1506
1507
1508
1509
1510
1511
1512
1513
1514
1515
1516
1517
1518
1519
1520
1521
1522
1523
1524
1525
1526
1527
1528
1529
1530
1531
1532
1533
1534
1535
1536
1537
1538
1539
1540
/*
 * Copyright 2006 The Android Open Source Project
 *
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */

#ifndef SkPaint_DEFINED
#define SkPaint_DEFINED

#include "SkBlendMode.h"
#include "SkColor.h"
#include "SkFilterQuality.h"
#include "SkMatrix.h"
#include "SkRefCnt.h"

class SkAutoDescriptor;
class SkColorFilter;
class SkData;
class SkDescriptor;
class SkDrawLooper;
class SkGlyph;
struct SkRect;
class SkGlyphCache;
class SkImageFilter;
class SkMaskFilter;
class SkPath;
class SkPathEffect;
struct SkPoint;
class SkShader;
class SkSurfaceProps;
class SkTextBlob;
class SkTypeface;

/** \class SkPaint
    SkPaint controls options applied when drawing and measuring. SkPaint collects all
    options outside of the SkCanvas clip and SkCanvas matrix.

    Various options apply to text, strokes and fills, and images.

    Some options may not be implemented on all platforms; in these cases, setting
    the option has no effect. Some options are conveniences that duplicate SkCanvas
    functionality; for instance, text size is identical to matrix scale.

    SkPaint options are rarely exclusive; each option modifies a stage of the drawing
    pipeline and multiple pipeline stages may be affected by a single SkPaint.

    SkPaint collects effects and filters that describe single-pass and multiple-pass
    algorithms that alter the drawing geometry, color, and transparency. For instance,
    SkPaint does not directly implement dashing or blur, but contains the objects that do so.

    The objects contained by SkPaint are opaque, and cannot be edited outside of the SkPaint
    to affect it. The implementation is free to defer computations associated with the
    SkPaint, or ignore them altogether. For instance, some GPU implementations draw all
    SkPath geometries with anti-aliasing, regardless of how SkPaint::kAntiAlias_Flag
    is set in SkPaint.

    SkPaint describes a single color, a single font, a single image quality, and so on.
    Multiple colors are drawn either by using multiple paints or with objects like
    SkShader attached to SkPaint.
*/
class SK_API SkPaint {
public:

    /** Constructs SkPaint with default values.

        @return  default initialized SkPaint
    */
    SkPaint();

    /** Makes a shallow copy of SkPaint. SkTypeface, SkPathEffect, SkShader,
        SkMaskFilter, SkColorFilter, SkDrawLooper, and SkImageFilter are shared
        between the original paint and the copy. Objects containing SkRefCnt increment
        their references by one.

        The referenced objects SkPathEffect, SkShader, SkMaskFilter, SkColorFilter,
        SkDrawLooper, and SkImageFilter cannot be modified after they are created.
        This prevents objects with SkRefCnt from being modified once SkPaint refers to them.

        @param paint  original to copy
        @return       shallow copy of paint
    */
    SkPaint(const SkPaint& paint);

    /** Implements a move constructor to avoid increasing the reference counts
        of objects referenced by the paint.

        After the call, paint is undefined, and can be safely destructed.

        @param paint  original to move
        @return       content of paint
    */
    SkPaint(SkPaint&& paint);

    /** Decreases SkPaint SkRefCnt of owned objects: SkTypeface, SkPathEffect, SkShader,
        SkMaskFilter, SkColorFilter, SkDrawLooper, and SkImageFilter. If the
        objects containing SkRefCnt go to zero, they are deleted.
    */
    ~SkPaint();

    /** Makes a shallow copy of SkPaint. SkTypeface, SkPathEffect, SkShader,
        SkMaskFilter, SkColorFilter, SkDrawLooper, and SkImageFilter are shared
        between the original paint and the copy. Objects containing SkRefCnt in the
        prior destination are decreased by one, and the referenced objects are deleted if the
        resulting count is zero. Objects containing SkRefCnt in the parameter paint
        are increased by one. paint is unmodified.

        @param paint  original to copy
        @return       content of paint
    */
    SkPaint& operator=(const SkPaint& paint);

    /** Moves the paint to avoid increasing the reference counts
        of objects referenced by the paint parameter. Objects containing SkRefCnt in the
        prior destination are decreased by one; those objects are deleted if the resulting count
        is zero.

        After the call, paint is undefined, and can be safely destructed.

        @param paint  original to move
        @return       content of paint
    */
    SkPaint& operator=(SkPaint&& paint);

    /** Compares a and b, and returns true if a and b are equivalent. May return false
        if SkTypeface, SkPathEffect, SkShader, SkMaskFilter, SkColorFilter,
        SkDrawLooper, or SkImageFilter have identical contents but different pointers.

        @param a  SkPaint to compare
        @param b  SkPaint to compare
        @return   true if SkPaint pair are equivalent
    */
    SK_API friend bool operator==(const SkPaint& a, const SkPaint& b);

    /** Compares a and b, and returns true if a and b are not equivalent. May return true
        if SkTypeface, SkPathEffect, SkShader, SkMaskFilter, SkColorFilter,
        SkDrawLooper, or SkImageFilter have identical contents but different pointers.

        @param a  SkPaint to compare
        @param b  SkPaint to compare
        @return   true if SkPaint pair are not equivalent
    */
    friend bool operator!=(const SkPaint& a, const SkPaint& b) {
        return !(a == b);
    }

    /** Returns a hash generated from SkPaint values and pointers.
        Identical hashes guarantee that the paints are
        equivalent, but differing hashes do not guarantee that the paints have differing
        contents.

        If operator==(const SkPaint& a, const SkPaint& b) returns true for two paints,
        their hashes are also equal.

        The hash returned is platform and implementation specific.

        @return  a shallow hash
    */
    uint32_t getHash() const;

    /** Sets all SkPaint contents to their initial values. This is equivalent to replacing
        SkPaint with the result of SkPaint().
    */
    void reset();

    /** \enum SkPaint::Hinting
        Hinting adjusts the glyph outlines so that the shape provides a uniform
        look at a given point size on font engines that support it. Hinting may have a
        muted effect or no effect at all depending on the platform.

        The four levels roughly control corresponding features on platforms that use FreeType
        as the font engine.
    */
    enum Hinting {
        kNo_Hinting     = 0, //!< glyph outlines unchanged
        kSlight_Hinting = 1, //!< minimal modification to improve constrast
        kNormal_Hinting = 2, //!< glyph outlines modified to improve constrast
        kFull_Hinting   = 3, //!< modifies glyph outlines for maximum constrast
    };

    /** Returns level of glyph outline adjustment.

        @return  one of: kNo_Hinting, kSlight_Hinting, kNormal_Hinting, kFull_Hinting
    */
    Hinting getHinting() const {
        return static_cast<Hinting>(fBitfields.fHinting);
    }

    /** Sets level of glyph outline adjustment.
        Does not check for valid values of hintingLevel.

        @param hintingLevel  one of: kNo_Hinting, kSlight_Hinting, kNormal_Hinting, kFull_Hinting
    */
    void setHinting(Hinting hintingLevel);

    /** \enum SkPaint::Flags
        The bit values stored in Flags.
        The default value for Flags, normally zero, can be changed at compile time
        with a custom definition of SkPaintDefaults_Flags.
        All flags can be read and written explicitly; Flags allows manipulating
        multiple settings at once.
    */
    enum Flags {
        kAntiAlias_Flag          = 0x01,   //!< mask for setting anti-alias
        kDither_Flag             = 0x04,   //!< mask for setting dither
        kFakeBoldText_Flag       = 0x20,   //!< mask for setting fake bold
        kLinearText_Flag         = 0x40,   //!< mask for setting linear text
        kSubpixelText_Flag       = 0x80,   //!< mask for setting subpixel text
        kLCDRenderText_Flag      = 0x200,  //!< mask for setting LCD text
        kEmbeddedBitmapText_Flag = 0x400,  //!< mask for setting font embedded bitmaps
        kAutoHinting_Flag        = 0x800,  //!< mask for setting auto-hinting
        kVerticalText_Flag       = 0x1000, //!< mask for setting vertical text
        kAllFlags                = 0xFFFF, //!< mask of all Flags
    };

    #ifdef SK_BUILD_FOR_ANDROID_FRAMEWORK
    enum ReserveFlags {
        kUnderlineText_ReserveFlag  = 0x08, //!< to be deprecated soon
        kStrikeThruText_ReserveFlag = 0x10, //!< to be deprecated soon
    };
    #endif

    /** Returns paint settings described by SkPaint::Flags. Each setting uses one
        bit, and can be tested with SkPaint::Flags members.

        @return  zero, one, or more bits described by SkPaint::Flags
    */
    uint32_t getFlags() const { return fBitfields.fFlags; }

    /** Replaces SkPaint::Flags with flags, the union of the SkPaint::Flags members.
        All SkPaint::Flags members may be cleared, or one or more may be set.

        @param flags  union of SkPaint::Flags for SkPaint
    */
    void setFlags(uint32_t flags);

    /** If true, pixels on the active edges of SkPath may be drawn with partial transparency.

        Equivalent to getFlags() masked with kAntiAlias_Flag.

        @return  kAntiAlias_Flag state
    */
    bool isAntiAlias() const {
        return SkToBool(this->getFlags() & kAntiAlias_Flag);
    }

    /** Requests, but does not require, that SkPath edge pixels draw opaque or with
        partial transparency.

        Sets kAntiAlias_Flag if aa is true.
        Clears kAntiAlias_Flag if aa is false.

        @param aa  setting for kAntiAlias_Flag
    */
    void setAntiAlias(bool aa);

    /** If true, color error may be distributed to smooth color transition.

        Equivalent to getFlags() masked with kDither_Flag.

        @return  kDither_Flag state
    */
    bool isDither() const {
        return SkToBool(this->getFlags() & kDither_Flag);
    }

    /** Requests, but does not require, to distribute color error.

        Sets kDither_Flag if dither is true.
        Clears kDither_Flag if dither is false.

        @param dither  setting for kDither_Flag
    */
    void setDither(bool dither);

    /** If true, text is converted to SkPath before drawing and measuring.

        Equivalent to getFlags() masked with kLinearText_Flag.

        @return  kLinearText_Flag state
    */
    bool isLinearText() const {
        return SkToBool(this->getFlags() & kLinearText_Flag);
    }

    /** If true, text is converted to SkPath before drawing and measuring.
        By default, kLinearText_Flag is clear.

        Sets kLinearText_Flag if linearText is true.
        Clears kLinearText_Flag if linearText is false.

        @param linearText  setting for kLinearText_Flag
    */
    void setLinearText(bool linearText);

    /** If true, glyphs at different sub-pixel positions may differ on pixel edge coverage.

        Equivalent to getFlags() masked with kSubpixelText_Flag.

        @return  kSubpixelText_Flag state
    */
    bool isSubpixelText() const {
        return SkToBool(this->getFlags() & kSubpixelText_Flag);
    }

    /** Requests, but does not require, that glyphs respect sub-pixel positioning.

        Sets kSubpixelText_Flag if subpixelText is true.
        Clears kSubpixelText_Flag if subpixelText is false.

        @param subpixelText  setting for kSubpixelText_Flag
    */
    void setSubpixelText(bool subpixelText);

    /** If true, glyphs may use LCD striping to improve glyph edges.

        Returns true if SkPaint::Flags kLCDRenderText_Flag is set.

        @return  kLCDRenderText_Flag state
    */
    bool isLCDRenderText() const {
        return SkToBool(this->getFlags() & kLCDRenderText_Flag);
    }

    /** Requests, but does not require, that glyphs use LCD striping for glyph edges.

        Sets kLCDRenderText_Flag if lcdText is true.
        Clears kLCDRenderText_Flag if lcdText is false.

        @param lcdText  setting for kLCDRenderText_Flag
    */
    void setLCDRenderText(bool lcdText);

    /** If true, font engine may return glyphs from font bitmaps instead of from outlines.

        Equivalent to getFlags() masked with kEmbeddedBitmapText_Flag.

        @return  kEmbeddedBitmapText_Flag state
    */
    bool isEmbeddedBitmapText() const {
        return SkToBool(this->getFlags() & kEmbeddedBitmapText_Flag);
    }

    /** Requests, but does not require, to use bitmaps in fonts instead of outlines.

        Sets kEmbeddedBitmapText_Flag if useEmbeddedBitmapText is true.
        Clears kEmbeddedBitmapText_Flag if useEmbeddedBitmapText is false.

        @param useEmbeddedBitmapText  setting for kEmbeddedBitmapText_Flag
    */
    void setEmbeddedBitmapText(bool useEmbeddedBitmapText);

    /** If true, and if SkPaint::Hinting is set to kNormal_Hinting or kFull_Hinting, and if
        platform uses FreeType as the font manager, instruct the font manager to always hint
        glyphs.

        Equivalent to getFlags() masked with kAutoHinting_Flag.

        @return  kAutoHinting_Flag state
    */
    bool isAutohinted() const {
        return SkToBool(this->getFlags() & kAutoHinting_Flag);
    }

    /** If SkPaint::Hinting is set to kNormal_Hinting or kFull_Hinting and useAutohinter is set,
        instruct the font manager to always hint glyphs.
        auto-hinting has no effect if SkPaint::Hinting is set to kNo_Hinting or
        kSlight_Hinting.

        Only affects platforms that use FreeType as the font manager.

        Sets kAutoHinting_Flag if useAutohinter is true.
        Clears kAutoHinting_Flag if useAutohinter is false.

        @param useAutohinter  setting for kAutoHinting_Flag
    */
    void setAutohinted(bool useAutohinter);

    /** If true, glyphs are drawn top to bottom instead of left to right.

        Equivalent to getFlags() masked with kVerticalText_Flag.

        @return  kVerticalText_Flag state
    */
    bool isVerticalText() const {
        return SkToBool(this->getFlags() & kVerticalText_Flag);
    }

    /** If true, text advance positions the next glyph below the previous glyph instead of to the
        right of previous glyph.

        Sets kVerticalText_Flag if vertical is true.
        Clears kVerticalText_Flag if vertical is false.

        @param verticalText  setting for kVerticalText_Flag
    */
    void setVerticalText(bool verticalText);

    /** If true, approximate bold by increasing the stroke width when creating glyph bitmaps
        from outlines.

        Equivalent to getFlags() masked with kFakeBoldText_Flag.

        @return  kFakeBoldText_Flag state
    */
    bool isFakeBoldText() const {
        return SkToBool(this->getFlags() & kFakeBoldText_Flag);
    }

    /** Use increased stroke width when creating glyph bitmaps to approximate a bold typeface.

        Sets kFakeBoldText_Flag if fakeBoldText is true.
        Clears kFakeBoldText_Flag if fakeBoldText is false.

        @param fakeBoldText  setting for kFakeBoldText_Flag
    */
    void setFakeBoldText(bool fakeBoldText);

    /** Deprecated.
    */
    bool isDevKernText() const { return false; }

    /** Deprecated.
    */
    void setDevKernText(bool) { }

    /** Returns SkFilterQuality, the image filtering level. A lower setting
        draws faster; a higher setting looks better when the image is scaled.

        @return  one of: kNone_SkFilterQuality, kLow_SkFilterQuality,
                 kMedium_SkFilterQuality, kHigh_SkFilterQuality
    */
    SkFilterQuality getFilterQuality() const {
        return (SkFilterQuality)fBitfields.fFilterQuality;
    }

    /** Sets SkFilterQuality, the image filtering level. A lower setting
        draws faster; a higher setting looks better when the image is scaled.
        Does not check to see if quality is valid.

        @param quality  one of: kNone_SkFilterQuality, kLow_SkFilterQuality,
                        kMedium_SkFilterQuality, kHigh_SkFilterQuality
    */
    void setFilterQuality(SkFilterQuality quality);

    /** \enum SkPaint::Style
        Set Style to fill, stroke, or both fill and stroke geometry.
        The stroke and fill
        share all paint attributes; for instance, they are drawn with the same color.

        Use kStrokeAndFill_Style to avoid hitting the same pixels twice with a stroke draw and
        a fill draw.
    */
    enum Style {
        kFill_Style,          //!< set to fill geometry
        kStroke_Style,        //!< set to stroke geometry
        kStrokeAndFill_Style, //!< sets to stroke and fill geometry
    };

    /** May be used to verify that SkPaint::Style is a legal value.
    */
    static constexpr int kStyleCount = kStrokeAndFill_Style + 1;

    /** Whether the geometry is filled, stroked, or filled and stroked.

        @return  one of:kFill_Style, kStroke_Style, kStrokeAndFill_Style
    */
    Style getStyle() const { return (Style)fBitfields.fStyle; }

    /** Sets whether the geometry is filled, stroked, or filled and stroked.
        Has no effect if style is not a legal SkPaint::Style value.

        @param style  one of: kFill_Style, kStroke_Style, kStrokeAndFill_Style
    */
    void setStyle(Style style);

    /** Retrieves alpha and RGB, unpremultiplied, packed into 32 bits.
        Use helpers SkColorGetA(), SkColorGetR(), SkColorGetG(), and SkColorGetB() to extract
        a color component.

        @return  unpremultiplied ARGB
    */
    SkColor getColor() const { return fColor; }

    /** Sets alpha and RGB used when stroking and filling. The color is a 32-bit value,
        unpremultiplied, packing 8-bit components for alpha, red, blue, and green.

        @param color  unpremultiplied ARGB
    */
    void setColor(SkColor color);

    /** Retrieves alpha from the color used when stroking and filling.

        @return  alpha ranging from zero, fully transparent, to 255, fully opaque
    */
    uint8_t getAlpha() const { return SkToU8(SkColorGetA(fColor)); }

    /** Replaces alpha, leaving RGB
        unchanged. An out of range value triggers an assert in the debug
        build. a is a value from zero to 255.
        a set to zero makes color fully transparent; a set to 255 makes color
        fully opaque.

        @param a  alpha component of color
    */
    void setAlpha(U8CPU a);

    /** Sets color used when drawing solid fills. The color components range from 0 to 255.
        The color is unpremultiplied; alpha sets the transparency independent of RGB.

        @param a  amount of alpha, from fully transparent (0) to fully opaque (255)
        @param r  amount of red, from no red (0) to full red (255)
        @param g  amount of green, from no green (0) to full green (255)
        @param b  amount of blue, from no blue (0) to full blue (255)
    */
    void setARGB(U8CPU a, U8CPU r, U8CPU g, U8CPU b);

    /** Returns the thickness of the pen used by SkPaint to
        outline the shape.

        @return  zero for hairline, greater than zero for pen thickness
    */
    SkScalar getStrokeWidth() const { return fWidth; }

    /** Sets the thickness of the pen used by the paint to
        outline the shape.
        Has no effect if width is less than zero.

        @param width  zero thickness for hairline; greater than zero for pen thickness
    */
    void setStrokeWidth(SkScalar width);

    /** The limit at which a sharp corner is drawn beveled.

        @return  zero and greater miter limit
    */
    SkScalar getStrokeMiter() const { return fMiterLimit; }

    /** The limit at which a sharp corner is drawn beveled.
        Valid values are zero and greater.
        Has no effect if miter is less than zero.

        @param miter  zero and greater miter limit
    */
    void setStrokeMiter(SkScalar miter);

    /** \enum SkPaint::Cap
        Cap draws at the beginning and end of an open path contour.
    */
    enum Cap {
        kButt_Cap,                  //!< no stroke extension
        kRound_Cap,                 //!< adds circle
        kSquare_Cap,                //!< adds square
        kLast_Cap    = kSquare_Cap, //!< largest Cap value
        kDefault_Cap = kButt_Cap,   //!< equivalent to kButt_Cap
    };

    /** May be used to verify that SkPaint::Cap is a legal value.
    */
    static constexpr int kCapCount = kLast_Cap + 1;

    /** \enum SkPaint::Join
        Join specifies how corners are drawn when a shape is stroked. Join
        affects the four corners of a stroked rectangle, and the connected segments in a
        stroked path.

        Choose miter join to draw sharp corners. Choose round join to draw a circle with a
        radius equal to the stroke width on top of the corner. Choose bevel join to minimally
        connect the thick strokes.

        The fill path constructed to describe the stroked path respects the join setting but may
        not contain the actual join. For instance, a fill path constructed with round joins does
        not necessarily include circles at each connected segment.
    */
    enum Join {
        kMiter_Join,                 //!< extends to miter limit
        kRound_Join,                 //!< adds circle
        kBevel_Join,                 //!< connects outside edges
        kLast_Join    = kBevel_Join, //!< equivalent to the largest value for Join
        kDefault_Join = kMiter_Join, //!< equivalent to kMiter_Join
    };

    /** May be used to verify that SkPaint::Join is a legal value.
    */
    static constexpr int kJoinCount = kLast_Join + 1;

    /** The geometry drawn at the beginning and end of strokes.

        @return  one of: kButt_Cap, kRound_Cap, kSquare_Cap
    */
    Cap getStrokeCap() const { return (Cap)fBitfields.fCapType; }

    /** The geometry drawn at the beginning and end of strokes.

        @param cap  one of: kButt_Cap, kRound_Cap, kSquare_Cap;
                    has no effect if cap is not valid
    */
    void setStrokeCap(Cap cap);

    /** The geometry drawn at the corners of strokes.

        @return  one of: kMiter_Join, kRound_Join, kBevel_Join
    */
    Join getStrokeJoin() const { return (Join)fBitfields.fJoinType; }

    /** The geometry drawn at the corners of strokes.

        @param join  one of: kMiter_Join, kRound_Join, kBevel_Join;
                     otherwise, has no effect
    */
    void setStrokeJoin(Join join);

    /** The filled equivalent of the stroked path.

        @param src       SkPath read to create a filled version
        @param dst       resulting SkPath; may be the same as src, but may not be nullptr
        @param cullRect  optional limit passed to SkPathEffect
        @param resScale  if > 1, increase precision, else if (0 < res < 1) reduce precision
                         to favor speed and size
        @return          true if the path represents style fill, or false if it represents hairline
    */
    bool getFillPath(const SkPath& src, SkPath* dst, const SkRect* cullRect,
                     SkScalar resScale = 1) const;

    /** The filled equivalent of the stroked path.

        Replaces dst with the src path modified by SkPathEffect and style stroke.
        SkPathEffect, if any, is not culled. stroke width is created with default precision.

        @param src  SkPath read to create a filled version
        @param dst  resulting SkPath dst may be the same as src, but may not be nullptr
        @return     true if the path represents style fill, or false if it represents hairline
    */
    bool getFillPath(const SkPath& src, SkPath* dst) const {
        return this->getFillPath(src, dst, nullptr, 1);
    }

    /** Optional colors used when filling a path, such as a gradient.

        Does not alter SkShader SkRefCnt.

        @return  SkShader if previously set, nullptr otherwise
    */
    SkShader* getShader() const { return fShader.get(); }

    /** Optional colors used when filling a path, such as a gradient.

        Increases SkShader SkRefCnt by one.

        @return  SkShader if previously set, nullptr otherwise
    */
    sk_sp<SkShader> refShader() const;

    /** Optional colors used when filling a path, such as a gradient.

        Sets SkShader to shader, decreasing SkRefCnt of the previous SkShader.
        Increments shader SkRefCnt by one.

        @param shader  how geometry is filled with color; if nullptr, color is used instead
    */
    void setShader(sk_sp<SkShader> shader);

    /** Returns SkColorFilter if set, or nullptr.
        Does not alter SkColorFilter SkRefCnt.

        @return  SkColorFilter if previously set, nullptr otherwise
    */
    SkColorFilter* getColorFilter() const { return fColorFilter.get(); }

    /** Returns SkColorFilter if set, or nullptr.
        Increases SkColorFilter SkRefCnt by one.

        @return  SkColorFilter if set, or nullptr
    */
    sk_sp<SkColorFilter> refColorFilter() const;

    /** Sets SkColorFilter to filter, decreasing SkRefCnt of the previous
        SkColorFilter. Pass nullptr to clear SkColorFilter.

        Increments filter SkRefCnt by one.

        @param colorFilter  SkColorFilter to apply to subsequent draw
    */
    void setColorFilter(sk_sp<SkColorFilter> colorFilter);

    /** Returns SkBlendMode.
        By default, returns SkBlendMode::kSrcOver.

        @return  mode used to combine source color with destination color
    */
    SkBlendMode getBlendMode() const { return (SkBlendMode)fBlendMode; }

    /** Returns true if SkBlendMode is SkBlendMode::kSrcOver, the default.

        @return  true if SkBlendMode is SkBlendMode::kSrcOver
    */
    bool isSrcOver() const { return (SkBlendMode)fBlendMode == SkBlendMode::kSrcOver; }

    /** Sets SkBlendMode to mode.
        Does not check for valid input.

        @param mode  SkBlendMode used to combine source color and destination
    */
    void setBlendMode(SkBlendMode mode) { fBlendMode = (unsigned)mode; }

    /** Returns SkPathEffect if set, or nullptr.
        Does not alter SkPathEffect SkRefCnt.

        @return  SkPathEffect if previously set, nullptr otherwise
    */
    SkPathEffect* getPathEffect() const { return fPathEffect.get(); }

    /** Returns SkPathEffect if set, or nullptr.
        Increases SkPathEffect SkRefCnt by one.

        @return  SkPathEffect if previously set, nullptr otherwise
    */
    sk_sp<SkPathEffect> refPathEffect() const;

    /** Sets SkPathEffect to pathEffect, decreasing SkRefCnt of the previous
        SkPathEffect. Pass nullptr to leave the path geometry unaltered.

        Increments pathEffect SkRefCnt by one.

        @param pathEffect  replace SkPath with a modification when drawn
    */
    void setPathEffect(sk_sp<SkPathEffect> pathEffect);

    /** Returns SkMaskFilter if set, or nullptr.
        Does not alter SkMaskFilter SkRefCnt.

        @return  SkMaskFilter if previously set, nullptr otherwise
    */
    SkMaskFilter* getMaskFilter() const { return fMaskFilter.get(); }

    /** Returns SkMaskFilter if set, or nullptr.

        Increases SkMaskFilter SkRefCnt by one.

        @return  SkMaskFilter if previously set, nullptr otherwise
    */
    sk_sp<SkMaskFilter> refMaskFilter() const;

    /** Sets SkMaskFilter to maskFilter, decreasing SkRefCnt of the previous
        SkMaskFilter. Pass nullptr to clear SkMaskFilter and leave SkMaskFilter effect on
        mask alpha unaltered.

        Increments maskFilter SkRefCnt by one.

        @param maskFilter  modifies clipping mask generated from drawn geometry
    */
    void setMaskFilter(sk_sp<SkMaskFilter> maskFilter);

    /** Returns SkTypeface if set, or nullptr.
        Increments SkTypeface SkRefCnt by one.

        @return  SkTypeface if previously set, nullptr otherwise
    */
    SkTypeface* getTypeface() const { return fTypeface.get(); }

    /** Increases SkTypeface SkRefCnt by one.

        @return  SkTypeface if previously set, nullptr otherwise
    */
    sk_sp<SkTypeface> refTypeface() const;

    /** Sets SkTypeface to typeface, decreasing SkRefCnt of the previous SkTypeface.
        Pass nullptr to clear SkTypeface and use the default typeface. Increments
        typeface SkRefCnt by one.

        @param typeface  font and style used to draw text
    */
    void setTypeface(sk_sp<SkTypeface> typeface);

    /** Returns SkImageFilter if set, or nullptr.
        Does not alter SkImageFilter SkRefCnt.

        @return  SkImageFilter if previously set, nullptr otherwise
    */
    SkImageFilter* getImageFilter() const { return fImageFilter.get(); }

    /** Returns SkImageFilter if set, or nullptr.
        Increases SkImageFilter SkRefCnt by one.

        @return  SkImageFilter if previously set, nullptr otherwise
    */
    sk_sp<SkImageFilter> refImageFilter() const;

    /** Sets SkImageFilter to imageFilter, decreasing SkRefCnt of the previous
        SkImageFilter. Pass nullptr to clear SkImageFilter, and remove SkImageFilter effect
        on drawing.

        Increments imageFilter SkRefCnt by one.

        @param imageFilter  how SkImage is sampled when transformed
    */
    void setImageFilter(sk_sp<SkImageFilter> imageFilter);

    /** Returns SkDrawLooper if set, or nullptr.
        Does not alter SkDrawLooper SkRefCnt.

        @return  SkDrawLooper if previously set, nullptr otherwise
    */
    SkDrawLooper* getDrawLooper() const { return fDrawLooper.get(); }

    /** Returns SkDrawLooper if set, or nullptr.
        Increases SkDrawLooper SkRefCnt by one.

        @return  SkDrawLooper if previously set, nullptr otherwise
    */
    sk_sp<SkDrawLooper> refDrawLooper() const;

    /** Deprecated.
        (see skbug.com/6259)
    */
    SkDrawLooper* getLooper() const { return fDrawLooper.get(); }

    /** Sets SkDrawLooper to drawLooper, decreasing SkRefCnt of the previous
        drawLooper.  Pass nullptr to clear SkDrawLooper and leave SkDrawLooper effect on
        drawing unaltered.

        Increments drawLooper SkRefCnt by one.

        @param drawLooper  iterates through drawing one or more time, altering SkPaint
    */
    void setDrawLooper(sk_sp<SkDrawLooper> drawLooper);

    /** Deprecated.
        (see skbug.com/6259)
    */
    void setLooper(sk_sp<SkDrawLooper> drawLooper);

    /** \enum SkPaint::Align
        Align adjusts the text relative to the text position.
        Align affects glyphs drawn with: SkCanvas::drawText, SkCanvas::drawPosText,
        SkCanvas::drawPosTextH, SkCanvas::drawTextOnPath,
        SkCanvas::drawTextOnPathHV, SkCanvas::drawTextRSXform, SkCanvas::drawTextBlob,
        and SkCanvas::drawString;
        as well as calls that place text glyphs like getTextWidths() and getTextPath().

        The text position is set by the font for both horizontal and vertical text.
        Typically, for horizontal text, the position is to the left side of the glyph on the
        base line; and for vertical text, the position is the horizontal center of the glyph
        at the caps height.

        Align adjusts the glyph position to center it or move it to abut the position
        using the metrics returned by the font.

        Align defaults to kLeft_Align.
    */
    enum Align {
        kLeft_Align,   //!< positions glyph by computed font offset
        kCenter_Align, //!< centers line of glyphs by its width or height
        kRight_Align,  //!< moves lines of glyphs by its width or height
    };

    /** May be used to verify that align is a legal value.
    */
    static constexpr int kAlignCount = 3;

    /** Returns SkPaint::Align.
        Returns kLeft_Align if SkPaint::Align has not been set.

        @return  text placement relative to position
    */
    Align   getTextAlign() const { return (Align)fBitfields.fTextAlign; }

    /** Sets SkPaint::Align to align.
        Has no effect if align is an invalid value.

        @param align  text placement relative to position
    */
    void    setTextAlign(Align align);

    /** Returns text size in points.

        @return  typographic height of text
    */
    SkScalar getTextSize() const { return fTextSize; }

    /** Sets text size in points.
        Has no effect if textSize is not greater than or equal to zero.

        @param textSize  typographic height of text
    */
    void setTextSize(SkScalar textSize);

    /** Returns text scale x.
        Default value is 1.

        @return  text horizontal scale
    */
    SkScalar getTextScaleX() const { return fTextScaleX; }

    /** Sets text scale x.
        Default value is 1.

        @param scaleX  text horizontal scale
    */
    void setTextScaleX(SkScalar scaleX);

    /** Returns text skew x.
        Default value is zero.

        @return  additional shear in x-axis relative to y-axis
    */
    SkScalar getTextSkewX() const { return fTextSkewX; }

    /** Sets text skew x.
        Default value is zero.

        @param skewX  additional shear in x-axis relative to y-axis
    */
    void setTextSkewX(SkScalar skewX);

    /** \enum SkPaint::TextEncoding
        TextEncoding determines whether text specifies character codes and their encoded
        size, or glyph indices. Characters are encoded as specified by the Unicode standard.

        Character codes encoded size are specified by UTF-8, UTF-16, or UTF-32.
        All character code formats are able to represent all of Unicode, differing only
        in the total storage required.

        UTF-8 (RFC 3629) encodes each character as one or more 8-bit bytes.

        UTF-16 (RFC 2781) encodes each character as one or two 16-bit words.

        UTF-32 encodes each character as one 32-bit word.

        font manager uses font data to convert character code points into glyph indices.
        A glyph index is a 16-bit word.

        TextEncoding is set to kUTF8_TextEncoding by default.
    */
    enum TextEncoding {
        kUTF8_TextEncoding,    //!< uses bytes to represent UTF-8 or ASCII
        kUTF16_TextEncoding,   //!< uses two byte words to represent most of Unicode
        kUTF32_TextEncoding,   //!< uses four byte words to represent all of Unicode
        kGlyphID_TextEncoding, //!< uses two byte words to represent glyph indices
    };

    /** Returns SkPaint::TextEncoding.
        SkPaint::TextEncoding determines how character code points are mapped to font glyph indices.

        @return  one of: kUTF8_TextEncoding, kUTF16_TextEncoding, kUTF32_TextEncoding, or
                 kGlyphID_TextEncoding
    */
    TextEncoding getTextEncoding() const {
      return (TextEncoding)fBitfields.fTextEncoding;
    }

    /** Sets SkPaint::TextEncoding to encoding.
        SkPaint::TextEncoding determines how character code points are mapped to font glyph indices.
        Invalid values for encoding are ignored.

        @param encoding  one of: kUTF8_TextEncoding, kUTF16_TextEncoding, kUTF32_TextEncoding, or
                         kGlyphID_TextEncoding
    */
    void setTextEncoding(TextEncoding encoding);

    /** \struct SkPaint::FontMetrics
        FontMetrics is filled out by getFontMetrics(). FontMetrics contents reflect the values
        computed by font manager using SkTypeface. Values are set to zero if they are
        not available.

        All vertical values relative to the baseline are given y-down. As such, zero is on the
        baseline, negative values are above the baseline, and positive values are below the
        baseline.

        fUnderlineThickness and fUnderlinePosition have a bit set in fFlags if their values
        are valid, since their value may be zero.

        fStrikeoutThickness and fStrikeoutPosition have a bit set in fFlags if their values
        are valid, since their value may be zero.
    */
    struct FontMetrics {

        /** \enum SkPaint::FontMetrics::FontMetricsFlags
            FontMetricsFlags are set in fFlags when underline and strikeout metrics are valid;
            the underline or strikeout metric may be valid and zero.
            Fonts with embedded bitmaps may not have valid underline or strikeout metrics.
        */
        enum FontMetricsFlags {
            kUnderlineThicknessIsValid_Flag = 1 << 0, //!< set if fUnderlineThickness is valid
            kUnderlinePositionIsValid_Flag  = 1 << 1, //!< set if fUnderlinePosition is valid
            kStrikeoutThicknessIsValid_Flag = 1 << 2, //!< set if fStrikeoutThickness is valid
            kStrikeoutPositionIsValid_Flag  = 1 << 3, //!< set if fStrikeoutPosition is valid
        };

        uint32_t fFlags;              //!< is set to FontMetricsFlags when metrics are valid
        SkScalar fTop;                //!< extent above baseline
        SkScalar fAscent;             //!< distance to reserve above baseline
        SkScalar fDescent;            //!< distance to reserve below baseline
        SkScalar fBottom;             //!< extent below baseline
        SkScalar fLeading;            //!< distance to add between lines
        SkScalar fAvgCharWidth;       //!< average character width
        SkScalar fMaxCharWidth;       //!< maximum character width
        SkScalar fXMin;               //!< minimum x
        SkScalar fXMax;               //!< maximum x
        SkScalar fXHeight;            //!< height of lower-case 'x'
        SkScalar fCapHeight;          //!< height of an upper-case letter
        SkScalar fUnderlineThickness; //!< underline thickness
        SkScalar fUnderlinePosition;  //!< underline position relative to baseline
        SkScalar fStrikeoutThickness; //!< strikeout thickness
        SkScalar fStrikeoutPosition;  //!< strikeout position relative to baseline

        /** If SkPaint::FontMetrics has a valid underline thickness, return true, and set
            thickness to that value. If the underline thickness is not valid,
            return false, and ignore thickness.

            @param thickness  storage for underline width
            @return           true if font specifies underline width
        */
        bool hasUnderlineThickness(SkScalar* thickness) const {
            if (SkToBool(fFlags & kUnderlineThicknessIsValid_Flag)) {
                *thickness = fUnderlineThickness;
                return true;
            }
            return false;
        }

        /** If SkPaint::FontMetrics has a valid underline position, return true, and set
            position to that value. If the underline position is not valid,
            return false, and ignore position.

            @param position  storage for underline position
            @return          true if font specifies underline position
        */
        bool hasUnderlinePosition(SkScalar* position) const {
            if (SkToBool(fFlags & kUnderlinePositionIsValid_Flag)) {
                *position = fUnderlinePosition;
                return true;
            }
            return false;
        }

        /** If SkPaint::FontMetrics has a valid strikeout thickness, return true, and set
            thickness to that value. If the underline thickness is not valid,
            return false, and ignore thickness.

            @param thickness  storage for strikeout width
            @return           true if font specifies strikeout width
        */
        bool hasStrikeoutThickness(SkScalar* thickness) const {
            if (SkToBool(fFlags & kStrikeoutThicknessIsValid_Flag)) {
                *thickness = fStrikeoutThickness;
                return true;
            }
            return false;
        }

        /** If SkPaint::FontMetrics has a valid strikeout position, return true, and set
            position to that value. If the underline position is not valid,
            return false, and ignore position.

            @param position  storage for strikeout position
            @return          true if font specifies strikeout position
        */
        bool hasStrikeoutPosition(SkScalar* position) const {
            if (SkToBool(fFlags & kStrikeoutPositionIsValid_Flag)) {
                *position = fStrikeoutPosition;
                return true;
            }
            return false;
        }

    };

    /** Returns SkPaint::FontMetrics associated with SkTypeface.
        The return value is the recommended spacing between lines: the sum of metrics
        descent, ascent, and leading.
        If metrics is not nullptr, SkPaint::FontMetrics is copied to metrics.
        Results are scaled by text size but does not take into account
        dimensions required by text scale x, text skew x, fake bold,
        style stroke, and SkPathEffect.
        Results can be additionally scaled by scale; a scale of zero
        is ignored.

        @param metrics  storage for SkPaint::FontMetrics from SkTypeface; may be nullptr
        @param scale    additional multiplier for returned values
        @return         recommended spacing between lines
    */
    SkScalar getFontMetrics(FontMetrics* metrics, SkScalar scale = 0) const;

    /** Returns the recommended spacing between lines: the sum of metrics
        descent, ascent, and leading.
        Result is scaled by text size but does not take into account
        dimensions required by stroking and SkPathEffect.
        Returns the same result as getFontMetrics().

        @return  recommended spacing between lines
    */
    SkScalar getFontSpacing() const { return this->getFontMetrics(nullptr, 0); }

    /** Converts text into glyph indices.
        Returns the number of glyph indices represented by text.
        SkPaint::TextEncoding specifies how text represents characters or glyphs.
        glyphs may be nullptr, to compute the glyph count.

        Does not check text for valid character codes or valid glyph indices.

        If byteLength equals zero, returns zero.
        If byteLength includes a partial character, the partial character is ignored.

        If SkPaint::TextEncoding is kUTF8_TextEncoding and
        text contains an invalid UTF-8 sequence, zero is returned.

        @param text        character storage encoded with SkPaint::TextEncoding
        @param byteLength  length of character storage in bytes
        @param glyphs      storage for glyph indices; may be nullptr
        @return            number of glyphs represented by text of length byteLength
    */
    int textToGlyphs(const void* text, size_t byteLength,
                     SkGlyphID glyphs[]) const;

    /** Returns true if all text corresponds to a non-zero glyph index.
        Returns false if any characters in text are not supported in
        SkTypeface.

        If SkPaint::TextEncoding is kGlyphID_TextEncoding,
        returns true if all glyph indices in text are non-zero;
        does not check to see if text contains valid glyph indices for SkTypeface.

        Returns true if byteLength is zero.

        @param text        array of characters or glyphs
        @param byteLength  number of bytes in text array
        @return            true if all text corresponds to a non-zero glyph index
    */
    bool containsText(const void* text, size_t byteLength) const;

    /** Converts glyphs into text if possible.
        Glyph values without direct Unicode equivalents are mapped to zero.
        Uses the SkTypeface, but is unaffected
        by SkPaint::TextEncoding; the text values returned are equivalent to kUTF32_TextEncoding.

        Only supported on platforms that use FreeType as the font engine.

        @param glyphs  array of indices into font
        @param count   length of glyph array
        @param text    storage for character codes, one per glyph
    */
    void glyphsToUnichars(const SkGlyphID glyphs[], int count, SkUnichar text[]) const;

    /** Returns the number of glyphs in text.
        Uses SkPaint::TextEncoding to count the glyphs.
        Returns the same result as textToGlyphs().

        @param text        character storage encoded with SkPaint::TextEncoding
        @param byteLength  length of character storage in bytes
        @return            number of glyphs represented by text of length byteLength
    */
    int countText(const void* text, size_t byteLength) const;

    /** Returns the advance width of text if kVerticalText_Flag is clear,
        and the height of text if kVerticalText_Flag is set.
        The advance is the normal distance to move before drawing additional text.
        Uses SkPaint::TextEncoding to decode text, SkTypeface to get the font metrics,
        and text size, text scale x, text skew x, stroke width, and
        SkPathEffect to scale the metrics and bounds.
        Returns the bounding box of text if bounds is not nullptr.
        The bounding box is computed as if the text was drawn at the origin.

        @param text    character codes or glyph indices to be measured
        @param length  number of bytes of text to measure
        @param bounds  returns bounding box relative to (0, 0) if not nullptr
        @return        advance width or height
    */
    SkScalar measureText(const void* text, size_t length, SkRect* bounds) const;

    /** Returns the advance width of text if kVerticalText_Flag is clear,
        and the height of text if kVerticalText_Flag is set.
        The advance is the normal distance to move before drawing additional text.
        Uses SkPaint::TextEncoding to decode text, SkTypeface to get the font metrics,
        and text size to scale the metrics.
        Does not scale the advance or bounds by fake bold or SkPathEffect.

        @param text    character codes or glyph indices to be measured
        @param length  number of bytes of text to measure
        @return        advance width or height
    */
    SkScalar measureText(const void* text, size_t length) const {
        return this->measureText(text, length, nullptr);
    }

    /** Returns the bytes of text that fit within maxWidth.
        If kVerticalText_Flag is clear, the text fragment fits if its advance width is less than or
        equal to maxWidth.
        If kVerticalText_Flag is set, the text fragment fits if its advance height is less than or
        equal to maxWidth.
        Measures only while the advance is less than or equal to maxWidth.
        Returns the advance or the text fragment in measuredWidth if it not nullptr.
        Uses SkPaint::TextEncoding to decode text, SkTypeface to get the font metrics,
        and text size to scale the metrics.
        Does not scale the advance or bounds by fake bold or SkPathEffect.

        @param text           character codes or glyph indices to be measured
        @param length         number of bytes of text to measure
        @param maxWidth       advance limit; text is measured while advance is less than maxWidth
        @param measuredWidth  returns the width of the text less than or equal to maxWidth
        @return               bytes of text that fit, always less than or equal to length
    */
    size_t  breakText(const void* text, size_t length, SkScalar maxWidth,
                      SkScalar* measuredWidth = nullptr) const;

    /** Retrieves the advance and bounds for each glyph in text, and returns
        the glyph count in text.
        Both widths and bounds may be nullptr.
        If widths is not nullptr, widths must be an array of glyph count entries.
        if bounds is not nullptr, bounds must be an array of glyph count entries.
        If kVerticalText_Flag is clear, widths returns the horizontal advance.
        If kVerticalText_Flag is set, widths returns the vertical advance.
        Uses SkPaint::TextEncoding to decode text, SkTypeface to get the font metrics,
        and text size to scale the widths and bounds.
        Does not scale the advance by fake bold or SkPathEffect.
        Does include fake bold and SkPathEffect in the bounds.

        @param text        character codes or glyph indices to be measured
        @param byteLength  number of bytes of text to measure
        @param widths      returns text advances for each glyph; may be nullptr
        @param bounds      returns bounds for each glyph relative to (0, 0); may be nullptr
        @return            glyph count in text
    */
    int getTextWidths(const void* text, size_t byteLength, SkScalar widths[],
                      SkRect bounds[] = nullptr) const;

    /** Returns the geometry as SkPath equivalent to the drawn text.
        Uses SkPaint::TextEncoding to decode text, SkTypeface to get the glyph paths,
        and text size, fake bold, and SkPathEffect to scale and modify the glyph paths.
        All of the glyph paths are stored in path.
        Uses x, y, and SkPaint::Align to position path.

        @param text    character codes or glyph indices
        @param length  number of bytes of text
        @param x       x-coordinate of the origin of the text
        @param y       y-coordinate of the origin of the text
        @param path    geometry of the glyphs
    */
    void getTextPath(const void* text, size_t length, SkScalar x, SkScalar y,
                     SkPath* path) const;

    /** Returns the geometry as SkPath equivalent to the drawn text.
        Uses SkPaint::TextEncoding to decode text, SkTypeface to get the glyph paths,
        and text size, fake bold, and SkPathEffect to scale and modify the glyph paths.
        All of the glyph paths are stored in path.
        Uses pos array and SkPaint::Align to position path.
        pos contains a position for each glyph.

        @param text    character codes or glyph indices
        @param length  number of bytes of text
        @param pos     positions of each glyph
        @param path    geometry of the glyphs
    */
    void getPosTextPath(const void* text, size_t length,
                        const SkPoint pos[], SkPath* path) const;

    /** Returns the number of intervals that intersect bounds.
        bounds describes a pair of lines parallel to the text advance.
        The return count is zero or a multiple of two, and is at most twice the number of glyphs in
        the string.
        Uses SkPaint::TextEncoding to decode text, SkTypeface to get the glyph paths,
        and text size, fake bold, and SkPathEffect to scale and modify the glyph paths.
        Uses x, y, and SkPaint::Align to position intervals.

        Pass nullptr for intervals to determine the size of the interval array.

        intervals are cached to improve performance for multiple calls.

        @param text       character codes or glyph indices
        @param length     number of bytes of text
        @param x          x-coordinate of the origin of the text
        @param y          y-coordinate of the origin of the text
        @param bounds     lower and upper line parallel to the advance
        @param intervals  returned intersections; may be nullptr
        @return           number of intersections; may be zero
    */
    int getTextIntercepts(const void* text, size_t length, SkScalar x, SkScalar y,
                          const SkScalar bounds[2], SkScalar* intervals) const;

    /** Returns the number of intervals that intersect bounds.
        bounds describes a pair of lines parallel to the text advance.
        The return count is zero or a multiple of two, and is at most twice the number of glyphs in
        the string.
        Uses SkPaint::TextEncoding to decode text, SkTypeface to get the glyph paths,
        and text size, fake bold, and SkPathEffect to scale and modify the glyph paths.
        Uses pos array and SkPaint::Align to position intervals.

        Pass nullptr for intervals to determine the size of the interval array.

        intervals are cached to improve performance for multiple calls.

        @param text       character codes or glyph indices
        @param length     number of bytes of text
        @param pos        positions of each glyph
        @param bounds     lower and upper line parallel to the advance
        @param intervals  returned intersections; may be nullptr
        @return           number of intersections; may be zero
    */
    int getPosTextIntercepts(const void* text, size_t length, const SkPoint pos[],
                             const SkScalar bounds[2], SkScalar* intervals) const;

    /** Returns the number of intervals that intersect bounds.
        bounds describes a pair of lines parallel to the text advance.
        The return count is zero or a multiple of two, and is at most twice the number of glyphs in
        the string.
        Uses SkPaint::TextEncoding to decode text, SkTypeface to get the glyph paths,
        and text size, fake bold, and SkPathEffect to scale and modify the glyph paths.
        Uses xpos array, constY, and SkPaint::Align to position intervals.

        Pass nullptr for intervals to determine the size of the interval array.

        intervals are cached to improve performance for multiple calls.

        @param text       character codes or glyph indices
        @param length     number of bytes of text
        @param xpos       positions of each glyph in x
        @param constY     position of each glyph in y
        @param bounds     lower and upper line parallel to the advance
        @param intervals  returned intersections; may be nullptr
        @return           number of intersections; may be zero
    */
    int getPosTextHIntercepts(const void* text, size_t length, const SkScalar xpos[],
                              SkScalar constY, const SkScalar bounds[2], SkScalar* intervals) const;

    /** Returns the number of intervals that intersect bounds.
        bounds describes a pair of lines parallel to the text advance.
        The return count is zero or a multiple of two, and is at most twice the number of glyphs in
        the string.
        Uses SkTypeface to get the glyph paths,
        and text size, fake bold, and SkPathEffect to scale and modify the glyph paths.
        Uses run array and SkPaint::Align to position intervals.

        SkPaint::TextEncoding must be set to SkPaint::kGlyphID_TextEncoding.

        Pass nullptr for intervals to determine the size of the interval array.

        intervals are cached to improve performance for multiple calls.

        @param blob       glyphs, positions, and text paint attributes
        @param bounds     lower and upper line parallel to the advance
        @param intervals  returned intersections; may be nullptr
        @return           number of intersections; may be zero
    */
    int getTextBlobIntercepts(const SkTextBlob* blob, const SkScalar bounds[2],
                              SkScalar* intervals) const;

    /** Returns the union of bounds of all glyphs.
        Returned dimensions are computed by font manager from font data,
        ignoring SkPaint::Hinting. Includes text size, text scale x,
        and text skew x, but not fake bold or SkPathEffect.

        If text size is large, text scale x is one, and text skew x is zero,
        returns the same bounds as SkPaint::FontMetrics { FontMetrics::fXMin,
        FontMetrics::fTop, FontMetrics::fXMax, FontMetrics::fBottom }.

        @return  union of bounds of all glyphs
    */
    SkRect getFontBounds() const;

    /** Returns true if SkPaint prevents all drawing;
        otherwise, the SkPaint may or may not allow drawing.

        Returns true if, for example, SkBlendMode combined with alpha computes a
        new alpha of zero.

        @return  true if SkPaint prevents all drawing
    */
    bool nothingToDraw() const;

    /**     (to be made private)
        Returns true if SkPaint does not include elements requiring extensive computation
        to compute SkBaseDevice bounds of drawn geometry. For instance, SkPaint with SkPathEffect
        always returns false.

        @return  true if SkPaint allows for fast computation of bounds
    */
    bool canComputeFastBounds() const;

    /**     (to be made private)
        Only call this if canComputeFastBounds() returned true. This takes a
        raw rectangle (the raw bounds of a shape), and adjusts it for stylistic
        effects in the paint (e.g. stroking). If needed, it uses the storage
        parameter. It returns the adjusted bounds that can then be used
        for SkCanvas::quickReject tests.

        The returned SkRect will either be orig or storage, thus the caller
        should not rely on storage being set to the result, but should always
        use the returned value. It is legal for orig and storage to be the same
        SkRect.
            For example:
            if (!path.isInverseFillType() && paint.canComputeFastBounds()) {
                SkRect storage;
                if (canvas->quickReject(paint.computeFastBounds(path.getBounds(), &storage))) {
                    return; // do not draw the path
                }
            }
            // draw the path

        @param orig     geometry modified by SkPaint when drawn
        @param storage  computed bounds of geometry; may not be nullptr
        @return         fast computed bounds
    */
    const SkRect& computeFastBounds(const SkRect& orig, SkRect* storage) const {
        // Things like stroking, etc... will do math on the bounds rect, assuming that it's sorted.
        SkASSERT(orig.isSorted());
        SkPaint::Style style = this->getStyle();
        // ultra fast-case: filling with no effects that affect geometry
        if (kFill_Style == style) {
            uintptr_t effects = reinterpret_cast<uintptr_t>(this->getLooper());
            effects |= reinterpret_cast<uintptr_t>(this->getMaskFilter());
            effects |= reinterpret_cast<uintptr_t>(this->getPathEffect());
            effects |= reinterpret_cast<uintptr_t>(this->getImageFilter());
            if (!effects) {
                return orig;
            }
        }

        return this->doComputeFastBounds(orig, storage, style);
    }

    /**     (to be made private)

        @param orig     geometry modified by SkPaint when drawn
        @param storage  computed bounds of geometry
        @return         fast computed bounds
    */
    const SkRect& computeFastStrokeBounds(const SkRect& orig,
                                          SkRect* storage) const {
        return this->doComputeFastBounds(orig, storage, kStroke_Style);
    }

    /**     (to be made private)
        Computes the bounds, overriding the SkPaint SkPaint::Style. This can be used to
        account for additional width required by stroking orig, without
        altering SkPaint::Style set to fill.

        @param orig     geometry modified by SkPaint when drawn
        @param storage  computed bounds of geometry
        @param style    overrides SkPaint::Style
        @return         fast computed bounds
    */
    const SkRect& doComputeFastBounds(const SkRect& orig, SkRect* storage,
                                      Style style) const;

    /** Creates string representation of SkPaint. The representation is read by
        internal debugging tools.

        @param str  storage for string representation of SkPaint
    */
    void toString(SkString* str) const;

private:
    typedef const SkGlyph& (*GlyphCacheProc)(SkGlyphCache*, const char**);

    sk_sp<SkTypeface>     fTypeface;
    sk_sp<SkPathEffect>   fPathEffect;
    sk_sp<SkShader>       fShader;
    sk_sp<SkMaskFilter>   fMaskFilter;
    sk_sp<SkColorFilter>  fColorFilter;
    sk_sp<SkDrawLooper>   fDrawLooper;
    sk_sp<SkImageFilter>  fImageFilter;

    SkScalar        fTextSize;
    SkScalar        fTextScaleX;
    SkScalar        fTextSkewX;
    SkColor         fColor;
    SkScalar        fWidth;
    SkScalar        fMiterLimit;
    uint32_t        fBlendMode; // just need 5-6 bits
    union {
        struct {
            // all of these bitfields should add up to 32
            unsigned        fFlags : 16;
            unsigned        fTextAlign : 2;
            unsigned        fCapType : 2;
            unsigned        fJoinType : 2;
            unsigned        fStyle : 2;
            unsigned        fTextEncoding : 2;  // 3 values
            unsigned        fHinting : 2;
            unsigned        fFilterQuality : 2;
            //unsigned      fFreeBits : 2;
        } fBitfields;
        uint32_t fBitfieldsUInt;
    };

    static GlyphCacheProc GetGlyphCacheProc(TextEncoding encoding,
                                            bool needFullMetrics);

    SkScalar measure_text(SkGlyphCache*, const char* text, size_t length,
                          int* count, SkRect* bounds) const;

    /*
     * The luminance color is used to determine which Gamma Canonical color to map to.  This is
     * really only used by backends which want to cache glyph masks, and need some way to know if
     * they need to generate new masks based off a given color.
     */
    SkColor computeLuminanceColor() const;

    /*  This is the size we use when we ask for a glyph's path. We then
     *  post-transform it as we draw to match the request.
     *  This is done to try to re-use cache entries for the path.
     *
     *  This value is somewhat arbitrary. In theory, it could be 1, since
     *  we store paths as floats. However, we get the path from the font
     *  scaler, and it may represent its paths as fixed-point (or 26.6),
     *  so we shouldn't ask for something too big (might overflow 16.16)
     *  or too small (underflow 26.6).
     *
     *  This value could track kMaxSizeForGlyphCache, assuming the above
     *  constraints, but since we ask for unhinted paths, the two values
     *  need not match per-se.
     */
    static constexpr int kCanonicalTextSizeForPaths  = 64;

    static bool TooBigToUseCache(const SkMatrix& ctm, const SkMatrix& textM, SkScalar maxLimit);

    // Set flags/hinting/textSize up to use for drawing text as paths.
    // Returns scale factor to restore the original textSize, since will will
    // have change it to kCanonicalTextSizeForPaths.
    SkScalar setupForAsPaths();

    static SkScalar MaxCacheSize2(SkScalar maxLimit);

    friend class GrAtlasTextBlob;
    friend class GrTextContext;
    friend class GrGLPathRendering;
    friend class GrPathRendering;
    friend class GrTextUtils;
    friend class SkAutoGlyphCacheNoGamma;
    friend class SkCanonicalizePaint;
    friend class SkCanvas;
    friend class SkDraw;
    friend class SkPaintPriv;
    friend class SkPDFDevice;
    friend class SkScalerContext;  // for computeLuminanceColor()
    friend class SkTextBaseIter;
    friend class SkTextBlobCacheDiffCanvas;
};

#endif