forked from flutter/engine
-
Notifications
You must be signed in to change notification settings - Fork 1
/
text.dart
3361 lines (3082 loc) · 128 KB
/
text.dart
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
// Copyright 2013 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
part of dart.ui;
/// Whether to slant the glyphs in the font
enum FontStyle {
/// Use the upright glyphs
normal,
/// Use glyphs designed for slanting
italic,
}
/// The thickness of the glyphs used to draw the text
class FontWeight {
const FontWeight._(this.index, this.value);
/// The encoded integer value of this font weight.
final int index;
/// The thickness value of this font weight.
final int value;
/// Thin, the least thick
static const FontWeight w100 = FontWeight._(0, 100);
/// Extra-light
static const FontWeight w200 = FontWeight._(1, 200);
/// Light
static const FontWeight w300 = FontWeight._(2, 300);
/// Normal / regular / plain
static const FontWeight w400 = FontWeight._(3, 400);
/// Medium
static const FontWeight w500 = FontWeight._(4, 500);
/// Semi-bold
static const FontWeight w600 = FontWeight._(5, 600);
/// Bold
static const FontWeight w700 = FontWeight._(6, 700);
/// Extra-bold
static const FontWeight w800 = FontWeight._(7, 800);
/// Black, the most thick
static const FontWeight w900 = FontWeight._(8, 900);
/// The default font weight.
static const FontWeight normal = w400;
/// A commonly used font weight that is heavier than normal.
static const FontWeight bold = w700;
/// A list of all the font weights.
static const List<FontWeight> values = <FontWeight>[
w100, w200, w300, w400, w500, w600, w700, w800, w900
];
/// Linearly interpolates between two font weights.
///
/// Rather than using fractional weights, the interpolation rounds to the
/// nearest weight.
///
/// If both `a` and `b` are null, then this method will return null. Otherwise,
/// any null values for `a` or `b` are interpreted as equivalent to [normal]
/// (also known as [w400]).
///
/// The `t` argument represents position on the timeline, with 0.0 meaning
/// that the interpolation has not started, returning `a` (or something
/// equivalent to `a`), 1.0 meaning that the interpolation has finished,
/// returning `b` (or something equivalent to `b`), and values in between
/// meaning that the interpolation is at the relevant point on the timeline
/// between `a` and `b`. The interpolation can be extrapolated beyond 0.0 and
/// 1.0, so negative values and values greater than 1.0 are valid (and can
/// easily be generated by curves such as [Curves.elasticInOut]). The result
/// is clamped to the range [w100]–[w900].
///
/// Values for `t` are usually obtained from an [Animation<double>], such as
/// an [AnimationController].
static FontWeight? lerp(FontWeight? a, FontWeight? b, double t) {
if (a == null && b == null) {
return null;
}
return values[_lerpInt((a ?? normal).index, (b ?? normal).index, t).round().clamp(0, 8)];
}
@override
String toString() {
return const <int, String>{
0: 'FontWeight.w100',
1: 'FontWeight.w200',
2: 'FontWeight.w300',
3: 'FontWeight.w400',
4: 'FontWeight.w500',
5: 'FontWeight.w600',
6: 'FontWeight.w700',
7: 'FontWeight.w800',
8: 'FontWeight.w900',
}[index]!;
}
}
/// A feature tag and value that affect the selection of glyphs in a font.
///
/// Different fonts support different features. Consider using a tool
/// such as <https://wakamaifondue.com/> to examine your fonts to
/// determine what features are available.
///
/// {@tool sample}
/// This example shows usage of several OpenType font features,
/// including Small Caps (selected manually using the "smcp" code),
/// old-style figures, fractional ligatures, and stylistic sets.
///
/// ** See code in examples/api/lib/ui/text/font_feature.0.dart **
/// {@end-tool}
///
/// See also:
///
/// * <https://en.wikipedia.org/wiki/List_of_typographic_features>,
/// Wikipedia's description of these typographic features.
///
/// * <https://docs.microsoft.com/en-us/typography/opentype/spec/featuretags>,
/// Microsoft's registry of these features.
class FontFeature {
/// Creates a [FontFeature] object, which can be added to a [TextStyle] to
/// change how the engine selects glyphs when rendering text.
///
/// `feature` is the four-character tag that identifies the feature.
/// These tags are specified by font formats such as OpenType.
///
/// `value` is the value that the feature will be set to. The behavior
/// of the value depends on the specific feature. Many features are
/// flags whose value can be 1 (when enabled) or 0 (when disabled).
///
/// See <https://docs.microsoft.com/en-us/typography/opentype/spec/featuretags>
const FontFeature(
this.feature,
[ this.value = 1 ]
) : assert(feature.length == 4, 'Feature tag must be exactly four characters long.'),
assert(value >= 0, 'Feature value must be zero or a positive integer.');
/// Create a [FontFeature] object that enables the feature with the given tag.
const FontFeature.enable(String feature) : this(feature, 1);
/// Create a [FontFeature] object that disables the feature with the given tag.
const FontFeature.disable(String feature) : this(feature, 0);
// Features below should be alphabetic by feature tag. This makes it
// easier to determine when a feature is missing so that we avoid
// adding duplicates.
//
// The full list is extremely long, and many of the features are
// language-specific, or indeed force-enabled for particular locales
// by HarfBuzz, so we don't even attempt to be comprehensive here.
// Features listed below are those we deemed "interesting enough" to
// have their own constructor, mostly on the basis of whether we
// could find a font where the feature had a useful effect that
// could be demonstrated.
// Start of feature tag list.
// ------------------------------------------------------------------------
/// Access alternative glyphs. (`aalt`)
///
/// This feature selects the given glyph variant for glyphs in the span.
///
/// {@tool sample}
/// The Raleway font supports several alternate glyphs. The code
/// below shows how specific glyphs can be selected. With `aalt` set
/// to zero, the default, the normal glyphs are used. With a
/// non-zero value, Raleway substitutes small caps for lower case
/// letters. With value 2, the lowercase "a" changes to a stemless
/// "a", whereas the lowercase "t" changes to a vertical bar instead
/// of having a curve. By targeting specific letters in the text
/// (using [widgets.Text.rich]), the desired rendering for each glyph can be
/// achieved.
///
/// ![](https://flutter.github.io/assets-for-api-docs/assets/dart-ui/font_feature_aalt.png)
///
/// ** See code in examples/api/lib/ui/text/font_feature.font_feature_alternative.0.dart **
/// {@end-tool}
///
/// See also:
///
/// * <https://docs.microsoft.com/en-us/typography/opentype/spec/features_ae#aalt>
const FontFeature.alternative(this.value) : feature = 'aalt';
/// Use alternative ligatures to represent fractions. (`afrc`)
///
/// When this feature is enabled (and the font supports it),
/// sequences of digits separated by U+002F SOLIDUS character (/) or
/// U+2044 FRACTION SLASH (⁄) are replaced by ligatures that
/// represent the corresponding fraction. These ligatures may differ
/// from those used by the [FontFeature.fractions] feature.
///
/// This feature overrides all other features.
///
/// {@tool sample}
/// The Ubuntu Mono font supports the `afrc` feature. It causes digits
/// before slashes to become superscripted and digits after slashes to become
/// subscripted. This contrasts to the effect seen with [FontFeature.fractions].
///
/// ![](https://flutter.github.io/assets-for-api-docs/assets/dart-ui/font_feature_afrc.png)
///
/// ** See code in examples/api/lib/ui/text/font_feature.font_feature_alternative_fractions.0.dart **
/// {@end-tool}
///
/// See also:
///
/// * [FontFeature.fractions], which has a similar (but different) effect.
/// * <https://docs.microsoft.com/en-us/typography/opentype/spec/features_ae#afrc>
const FontFeature.alternativeFractions() : feature = 'afrc', value = 1;
/// Enable contextual alternates. (`calt`)
///
/// With this feature enabled, specific glyphs may be replaced by
/// alternatives based on nearby text.
///
/// {@tool sample}
/// The Barriecito font supports the `calt` feature. It causes some
/// letters in close proximity to other instances of themselves to
/// use different glyphs, to give the appearance of more variation
/// in the glyphs, rather than having each letter always use a
/// particular glyph.
///
/// ![](https://flutter.github.io/assets-for-api-docs/assets/dart-ui/font_feature_calt.png)
///
/// ** See code in examples/api/lib/ui/text/font_feature.font_feature_contextual_alternates.0.dart **
/// {@end-tool}
///
/// See also:
///
/// * [FontFeature.randomize], which is more a rarely supported but more
/// powerful way to get a similar effect.
/// * <https://docs.microsoft.com/en-us/typography/opentype/spec/features_ae#calt>
const FontFeature.contextualAlternates() : feature = 'calt', value = 1;
/// Enable case-sensitive forms. (`case`)
///
/// Some glyphs, for example parentheses or operators, are typically
/// designed to fit nicely with mixed case, or even predominantly
/// lowercase, text. When these glyphs are placed near strings of
/// capital letters, they appear a little off-center.
///
/// This feature, when supported by the font, causes these glyphs to
/// be shifted slightly, or otherwise adjusted, so as to form a more
/// aesthetically pleasing combination with capital letters.
///
/// {@tool sample}
/// The Piazzolla font supports the `case` feature. It causes
/// parentheses, brackets, braces, guillemets, slashes, bullets, and
/// some other glyphs (not shown below) to be shifted up slightly so
/// that capital letters appear centered in comparison. When the
/// feature is disabled, those glyphs are optimized for use with
/// lowercase letters, and so capital letters appear to ride higher
/// relative to the punctuation marks.
///
/// The difference is very subtle. It may be most obvious when
/// examining the square brackets compared to the capital A.
///
/// ![](https://flutter.github.io/assets-for-api-docs/assets/dart-ui/font_feature_case.png)
///
/// ** See code in examples/api/lib/ui/text/font_feature.font_feature_case_sensitive_forms.0.dart **
/// {@end-tool}
///
/// See also:
///
/// * <https://docs.microsoft.com/en-us/typography/opentype/spec/features_ae#case>
const FontFeature.caseSensitiveForms() : feature = 'case', value = 1;
/// Select a character variant. (`cv01` through `cv99`)
///
/// Fonts may have up to 99 character variant sets, numbered 1
/// through 99, each of which can be independently enabled or
/// disabled.
///
/// Related character variants are typically grouped into stylistic
/// sets, controlled by the [FontFeature.stylisticSet] feature
/// (`ssXX`).
///
/// {@tool sample}
/// The Source Code Pro font supports the `cvXX` feature for several
/// characters. In the example below, variants 1 (`cv01`), 2
/// (`cv02`), and 4 (`cv04`) are selected. Variant 1 changes the
/// rendering of the "a" character, variant 2 changes the lowercase
/// "g" character, and variant 4 changes the lowercase "i" and "l"
/// characters. There are also variants (not shown here) that
/// control the rendering of various greek characters such as beta
/// and theta.
///
/// Notably, this can be contrasted with the stylistic sets, where
/// the set which affects the "a" character also affects beta, and
/// the set which affects the "g" character also affects theta and
/// delta.
///
/// ![](https://flutter.github.io/assets-for-api-docs/assets/dart-ui/font_feature_cvXX.png)
///
/// ** See code in examples/api/lib/ui/text/font_feature.font_feature_character_variant.0.dart **
/// {@end-tool}
///
/// See also:
///
/// * [FontFeature.stylisticSet], which allows for groups of characters
/// variants to be selected at once, as opposed to individual character variants.
/// * <https://docs.microsoft.com/en-us/typography/opentype/spec/features_ae#cv01-cv99>
factory FontFeature.characterVariant(int value) {
assert(value >= 1);
assert(value <= 99);
return FontFeature('cv${value.toString().padLeft(2, "0")}');
}
/// Display digits as denominators. (`dnom`)
///
/// This is typically used automatically by the font rendering
/// system as part of the implementation of `frac` for the denominator
/// part of fractions (see [FontFeature.fractions]).
///
/// {@tool sample}
/// The Piazzolla font supports the `dnom` feature. It causes
/// the digits to be rendered smaller and near the bottom of the EM box.
///
/// ![](https://flutter.github.io/assets-for-api-docs/assets/dart-ui/font_feature_dnom.png)
///
/// ** See code in examples/api/lib/ui/text/font_feature.font_feature_denominator.0.dart **
/// {@end-tool}
///
/// See also:
///
/// * <https://docs.microsoft.com/en-us/typography/opentype/spec/features_ae#dnom>
const FontFeature.denominator() : feature = 'dnom', value = 1;
/// Use ligatures to represent fractions. (`afrc`)
///
/// When this feature is enabled (and the font supports it),
/// sequences of digits separated by U+002F SOLIDUS character (/) or
/// U+2044 FRACTION SLASH (⁄) are replaced by ligatures that
/// represent the corresponding fraction.
///
/// This feature may imply the [FontFeature.numerators] and
/// [FontFeature.denominator] features.
///
/// {@tool sample}
/// The Ubuntu Mono font supports the `frac` feature. It causes
/// digits around slashes to be turned into dedicated fraction
/// glyphs. This contrasts to the effect seen with
/// [FontFeature.alternativeFractions].
///
/// ![](https://flutter.github.io/assets-for-api-docs/assets/dart-ui/font_feature_frac.png)
///
/// ** See code in examples/api/lib/ui/text/font_feature.font_feature_fractions.0.dart **
/// {@end-tool}
///
/// See also:
///
/// * [FontFeature.alternativeFractions], which has a similar (but different) effect.
/// * <https://docs.microsoft.com/en-us/typography/opentype/spec/features_fj#frac>
const FontFeature.fractions() : feature = 'frac', value = 1;
/// Use historical forms. (`hist`)
///
/// Some fonts have alternatives for letters whose forms have changed
/// through the ages. In the Latin alphabet, this is common for
/// example with the long-form "s" or the Fraktur "k". This feature enables
/// those alternative glyphs.
///
/// This does not enable legacy ligatures, only single-character alternatives.
/// To enable historical ligatures, use [FontFeature.historicalLigatures].
///
/// This feature may override other glyph-substitution features.
///
/// {@tool sample}
/// The Cardo font supports the `hist` feature specifically for the
/// letter "s": it changes occurrences of that letter for the glyph
/// used by U+017F LATIN SMALL LETTER LONG S.
///
/// ![](https://flutter.github.io/assets-for-api-docs/assets/dart-ui/font_feature_historical.png)
///
/// ** See code in examples/api/lib/ui/text/font_feature.font_feature_historical_forms.0.dart **
/// {@end-tool}
///
/// See also:
///
/// * <https://docs.microsoft.com/en-us/typography/opentype/spec/features_fj#hist>
const FontFeature.historicalForms() : feature = 'hist', value = 1;
/// Use historical ligatures. (`hlig`)
///
/// Some fonts support ligatures that have fallen out of favor today,
/// but were historically in common use. This feature enables those
/// ligatures.
///
/// For example, the "long s" glyph was historically typeset with
/// characters such as "t" and "h" as a single ligature.
///
/// This does not enable the legacy forms, only ligatures. See
/// [FontFeature.historicalForms] to enable single characters to be
/// replaced with their historical alternatives. Combining both is
/// usually desired since the ligatures typically apply specifically
/// to characters that have historical forms as well. For example,
/// the historical forms feature might replace the "s" character
/// with the "long s" (ſ) character, while the historical ligatures
/// feature might specifically apply to cases where "long s" is
/// followed by other characters such as "t". In such cases, without
/// the historical forms being enabled, the ligatures would only
/// apply when the "long s" is used explicitly.
///
/// This feature may override other glyph-substitution features.
///
/// {@tool sample}
/// The Cardo font supports the `hlig` feature. It has legacy
/// ligatures for "VI" and "NT", and various ligatures involving the
/// "long s". In the example below, both historical forms (`hist 1`)
/// and historical ligatures (`hlig 1`) are enabled, so, for
/// instance, "fish" becomes "fiſh" which is then rendered using a
/// ligature for the last two characters.
///
/// Similarly, the word "business" is turned into "buſineſſ" by
/// `hist`, and the `ſi` and `ſſ` pairs are ligated by `hlig`.
/// Observe in particular the position of the dot of the "i" in
/// "business" in the various combinations of these features.
///
/// ![](https://flutter.github.io/assets-for-api-docs/assets/dart-ui/font_feature_historical.png)
///
/// ** See code in examples/api/lib/ui/text/font_feature.font_feature_historical_ligatures.0.dart **
/// {@end-tool}
///
/// See also:
///
/// * <https://docs.microsoft.com/en-us/typography/opentype/spec/features_fj#hlig>
const FontFeature.historicalLigatures() : feature = 'hlig', value = 1;
/// Use lining figures. (`lnum`)
///
/// Some fonts have digits that, like lowercase latin letters, have
/// both descenders and ascenders. In some situations, especially in
/// conjunction with capital letters, this leads to an aesthetically
/// questionable irregularity. Lining figures, on the other hand,
/// have a uniform height, and align with the baseline and the
/// height of capital letters. Conceptually, they can be thought of
/// as "capital digits".
///
/// This feature may conflict with [FontFeature.oldstyleFigures].
///
/// {@tool sample}
/// The Sorts Mill Goudy font supports the `lnum` feature. It causes
/// digits to fit more seamlessly with capital letters.
///
/// ![](https://flutter.github.io/assets-for-api-docs/assets/dart-ui/font_feature_lnum.png)
///
/// ** See code in examples/api/lib/ui/text/font_feature.font_feature_lining_figures.0.dart **
/// {@end-tool}
///
/// See also:
///
/// * <https://docs.microsoft.com/en-us/typography/opentype/spec/features_ko#lnum>
const FontFeature.liningFigures() : feature = 'lnum', value = 1;
/// Use locale-specific glyphs. (`locl`)
///
/// Some characters, most notably those in the Unicode Han
/// Unification blocks, vary in presentation based on the locale in
/// use. For example, the ideograph for "grass" (U+8349, 草) has a
/// broken top line in Traditional Chinese, but a solid top line in
/// Simplified Chinese, Japanese, Korean, and Vietnamese. This kind
/// of variation also exists with other alphabets, for example
/// Cyrillic characters as used in the Bulgarian and Serbian
/// alphabets vary from their Russian counterparts.
///
/// A particular font may default to the forms for the locale for
/// which it was constructed, but still support alternative forms
/// for other locales. When this feature is enabled, the locale (as
/// specified using [painting.TextStyle.locale], for instance) is
/// used to determine which glyphs to use when locale-specific
/// alternatives exist. Disabling this feature causes the font
/// rendering to ignore locale information and only use the default
/// glyphs.
///
/// This feature is enabled by default. Using
/// `FontFeature.localeAware(enable: false)` disables the
/// locale-awareness. (So does not specifying the locale in the
/// first place, of course.)
///
/// {@tool sample}
/// The Noto Sans CJK font supports the `locl` feature for CJK characters.
/// In this example, the `localeAware` feature is not explicitly used, as it is
/// enabled by default. This example instead shows how to set the locale,
/// thus demonstrating how Noto Sans adapts the glyph shapes to the locale.
///
/// ![](https://flutter.github.io/assets-for-api-docs/assets/dart-ui/font_feature_locl.png)
///
/// ** See code in examples/api/lib/ui/text/font_feature.font_feature_locale_aware.0.dart **
/// {@end-tool}
///
/// See also:
///
/// * <https://docs.microsoft.com/en-us/typography/opentype/spec/features_ko#locl>
/// * <https://en.wikipedia.org/wiki/Han_unification>
/// * <https://en.wikipedia.org/wiki/Cyrillic_script>
const FontFeature.localeAware({ bool enable = true }) : feature = 'locl', value = enable ? 1 : 0;
/// Display alternative glyphs for numerals (alternate annotation forms). (`nalt`)
///
/// Replaces glyphs used in numbering lists (e.g. 1, 2, 3...; or a, b, c...) with notational
/// variants that might be more typographically interesting.
///
/// Fonts sometimes support multiple alternatives, and the argument
/// selects the set to use (a positive integer, or 0 to disable the
/// feature). The default set if none is specified is 1.
///
/// {@tool sample}
/// The Gothic A1 font supports several notational variant sets via
/// the `nalt` feature.
///
/// Set 1 changes the spacing of the glyphs. Set 2 parenthesizes the
/// latin letters and reduces the numerals to subscripts. Set 3
/// circles the glyphs. Set 4 parenthesizes the digits. Set 5 uses
/// reverse-video circles for the digits. Set 7 superscripts the
/// digits.
///
/// The code below shows how to select set 3.
///
/// ![](https://flutter.github.io/assets-for-api-docs/assets/dart-ui/font_feature_nalt.png)
///
/// ** See code in examples/api/lib/ui/text/font_feature.font_feature_notational_forms.0.dart **
/// {@end-tool}
///
/// See also:
///
/// * <https://docs.microsoft.com/en-us/typography/opentype/spec/features_ko#nalt>
const FontFeature.notationalForms([this.value = 1]) : feature = 'nalt', assert(value >= 0);
/// Display digits as numerators. (`numr`)
///
/// This is typically used automatically by the font rendering
/// system as part of the implementation of `frac` for the numerator
/// part of fractions (see [FontFeature.fractions]).
///
/// {@tool sample}
/// The Piazzolla font supports the `numr` feature. It causes
/// the digits to be rendered smaller and near the top of the EM box.
///
/// ![](https://flutter.github.io/assets-for-api-docs/assets/dart-ui/font_feature_numr.png)
///
/// ** See code in examples/api/lib/ui/text/font_feature.font_feature_numerators.0.dart **
/// {@end-tool}
///
/// See also:
///
/// * <https://docs.microsoft.com/en-us/typography/opentype/spec/features_ko#numr>
const FontFeature.numerators() : feature = 'numr', value = 1;
/// Use old style figures. (`onum`)
///
/// Some fonts have variants of the figures (e.g. the digit 9) that,
/// when this feature is enabled, render with descenders under the
/// baseline instead of being entirely above the baseline. If the
/// default digits are lining figures, this allows the selection of
/// digits that fit better with mixed case (uppercase and lowercase)
/// text.
///
/// This overrides [FontFeature.slashedZero] and may conflict with
/// [FontFeature.liningFigures].
///
/// {@tool sample}
/// The Piazzolla font supports the `onum` feature. It causes
/// digits to extend below the baseline.
///
/// ![](https://flutter.github.io/assets-for-api-docs/assets/dart-ui/font_feature_onum.png)
///
/// ** See code in examples/api/lib/ui/text/font_feature.font_feature_oldstyle_figures.0.dart **
/// {@end-tool}
///
/// See also:
///
/// * <https://docs.microsoft.com/en-us/typography/opentype/spec/features_ko#onum>
/// * <https://en.wikipedia.org/wiki/Text_figures>
const FontFeature.oldstyleFigures() : feature = 'onum', value = 1;
/// Use ordinal forms for alphabetic glyphs. (`ordn`)
///
/// Some fonts have variants of the alphabetic glyphs intended for
/// use after numbers when expressing ordinals, as in "1st", "2nd",
/// "3rd". This feature enables those alternative glyphs.
///
/// This may override other features that substitute glyphs.
///
/// {@tool sample}
/// The Piazzolla font supports the `ordn` feature. It causes
/// alphabetic glyphs to become smaller and superscripted.
///
/// ![](https://flutter.github.io/assets-for-api-docs/assets/dart-ui/font_feature_ordn.png)
///
/// ** See code in examples/api/lib/ui/text/font_feature.font_feature_ordinal_forms.0.dart **
/// {@end-tool}
///
/// See also:
///
/// * <https://docs.microsoft.com/en-us/typography/opentype/spec/features_ko#ordn>
const FontFeature.ordinalForms() : feature = 'ordn', value = 1;
/// Use proportional (varying width) figures. (`pnum`)
///
/// For fonts that have both proportional and tabular (monospace) figures,
/// this enables the proportional figures.
///
/// This is mutually exclusive with [FontFeature.tabularFigures].
///
/// The default behavior varies from font to font.
///
/// {@tool sample}
/// The Kufam font supports the `pnum` feature. It causes the digits
/// to become proportionally-sized, rather than all being the same
/// width. In this font this is especially noticeable with the digit
/// "1": normally, the 1 has very noticeable serifs in this
/// sans-serif font, but with the proportionally figures enabled,
/// the digit becomes much narrower.
///
/// ![](https://flutter.github.io/assets-for-api-docs/assets/dart-ui/font_feature_pnum.png)
///
/// ** See code in examples/api/lib/ui/text/font_feature.font_feature_proportional_figures.0.dart **
/// {@end-tool}
///
/// See also:
///
/// * <https://docs.microsoft.com/en-us/typography/opentype/spec/features_pt#pnum>
const FontFeature.proportionalFigures() : feature = 'pnum', value = 1;
/// Randomize the alternate forms used in text. (`rand`)
///
/// For example, this can be used with suitably-prepared handwriting fonts to
/// vary the forms used for each character, so that, for instance, the word
/// "cross-section" would be rendered with two different "c"s, two different "o"s,
/// and three different "s"s.
///
/// Contextual alternates ([FontFeature.contextualAlternates])
/// provide a similar effect in some fonts, without using
/// randomness.
///
/// See also:
///
/// * <https://docs.microsoft.com/en-us/typography/opentype/spec/features_pt#rand>
const FontFeature.randomize() : feature = 'rand', value = 1;
/// Enable stylistic alternates. (`salt`)
///
/// Some fonts have alternative forms that are not tied to a
/// particular purpose (such as being historical forms, or
/// contextually relevant alternatives, or ligatures, etc). This
/// font feature enables these purely stylistic alternatives.
///
/// This may override other features that substitute glyphs.
///
/// {@tool sample}
/// The Source Code Pro font supports the `salt` feature. It causes
/// some glyphs to be rendered differently, for example the "a" and
/// "g" glyphs change from their typographically common
/// double-storey forms to simpler single-storey forms, the dollar
/// sign's line changes from discontinuous to continuous (and is
/// angled), and the "0" rendering changes from a center dot to a
/// slash.
///
/// ![](https://flutter.github.io/assets-for-api-docs/assets/dart-ui/font_feature_salt.png)
///
/// ** See code in examples/api/lib/ui/text/font_feature.font_feature_stylistic_alternates.0.dart **
/// {@end-tool}
///
/// See also:
///
/// * [FontFeature.contextualAlternates], which is enables alternates specific to certain contexts.
/// * <https://docs.microsoft.com/en-us/typography/opentype/spec/features_pt#salt>
const FontFeature.stylisticAlternates() : feature = 'salt', value = 1;
/// Use scientific inferiors. (`sinf`)
///
/// Some fonts have variants of the figures (e.g. the digit 2) that,
/// when this feature is enabled, render in a manner more
/// appropriate for subscripted digits ("inferiors") used in
/// scientific contexts, e.g. the subscripts in chemical formulae.
///
/// This may override other features that substitute glyphs.
///
/// {@tool sample}
/// The Piazzolla font supports the `sinf` feature. It causes
/// digits to be smaller and subscripted.
///
/// ![](https://flutter.github.io/assets-for-api-docs/assets/dart-ui/font_feature_sinf.png)
///
/// ** See code in examples/api/lib/ui/text/font_feature.font_feature_scientific_inferiors.0.dart **
/// {@end-tool}
///
/// See also:
///
/// * <https://docs.microsoft.com/en-us/typography/opentype/spec/features_pt#sinf>
const FontFeature.scientificInferiors() : feature = 'sinf', value = 1;
/// Select a stylistic set. (`ss01` through `ss20`)
///
/// Fonts may have up to 20 stylistic sets, numbered 1 through 20,
/// each of which can be independently enabled or disabled.
///
/// For more fine-grained control, in some fonts individual
/// character variants can also be controlled by the
/// [FontFeature.characterVariant] feature (`cvXX`).
///
/// {@tool sample}
/// The Source Code Pro font supports the `ssXX` feature for several
/// sets. In the example below, stylistic sets 2 (`ss02`), 3
/// (`ss03`), and 4 (`ss04`) are selected. Stylistic set 2 changes
/// the rendering of the "a" character and the beta character,
/// stylistic set 3 changes the lowercase "g", theta, and delta
/// characters, and stylistic set 4 changes the lowercase "i" and
/// "l" characters.
///
/// This font also supports character variants (see
/// [FontFeature.characterVariant]).
///
/// ![](https://flutter.github.io/assets-for-api-docs/assets/dart-ui/font_feature_ssXX_1.png)
///
/// ** See code in examples/api/lib/ui/text/font_feature.font_feature_stylistic_set.0.dart **
/// {@end-tool}
///
/// {@tool sample}
/// The Piazzolla font supports the `ssXX` feature for more
/// elaborate stylistic effects. Set 1 turns some Latin characters
/// into Roman numerals, set 2 enables some ASCII characters to be
/// used to create pretty arrows, and so forth.
///
/// _These_ stylistic sets do _not_ correspond to character variants.
///
/// ![](https://flutter.github.io/assets-for-api-docs/assets/dart-ui/font_feature_ssXX_2.png)
///
/// ** See code in examples/api/lib/ui/text/font_feature.font_feature_stylistic_set.1.dart **
/// {@end-tool}
///
/// See also:
///
/// * [FontFeature.characterVariant], which allows for individual character
/// variants to be selected, as opposed to entire sets.
/// * <https://docs.microsoft.com/en-us/typography/opentype/spec/features_pt#ssxx>
factory FontFeature.stylisticSet(int value) {
assert(value >= 1);
assert(value <= 20);
return FontFeature('ss${value.toString().padLeft(2, "0")}');
}
/// Enable subscripts. (`subs`)
///
/// This feature causes some fonts to change some glyphs to their subscripted form.
///
/// It typically does not affect all glyphs, and so is not appropriate for generally causing
/// all text to be subscripted.
///
/// This may override other features that substitute glyphs.
///
/// {@tool sample}
/// The Piazzolla font supports the `subs` feature. It causes
/// digits to be smaller and subscripted.
///
/// ![](https://flutter.github.io/assets-for-api-docs/assets/dart-ui/font_feature_subs.png)
///
/// ** See code in examples/api/lib/ui/text/font_feature.font_feature_subscripts.0.dart **
/// {@end-tool}
///
/// See also:
///
/// * <https://docs.microsoft.com/en-us/typography/opentype/spec/features_pt#subs>
/// * [FontFeature.scientificInferiors], which is similar but intended specifically for
/// subscripts used in scientific contexts.
/// * [FontFeature.superscripts], which is similar but for subscripting.
const FontFeature.subscripts() : feature = 'subs', value = 1;
/// Enable superscripts. (`sups`)
///
/// This feature causes some fonts to change some glyphs to their
/// superscripted form. This may be more than just changing their
/// position. For example, digits might change to lining figures
/// (see [FontFeature.liningFigures]) in addition to being raised
/// and shrunk.
///
/// It typically does not affect all glyphs, and so is not
/// appropriate for generally causing all text to be superscripted.
///
/// This may override other features that substitute glyphs.
///
/// {@tool sample}
/// The Sorts Mill Goudy font supports the `sups` feature. It causes
/// digits to be smaller, superscripted, and changes them to lining
/// figures (so they are all the same height).
///
/// ![](https://flutter.github.io/assets-for-api-docs/assets/dart-ui/font_feature_sups.png)
///
/// ** See code in examples/api/lib/ui/text/font_feature.font_feature_superscripts.0.dart **
/// {@end-tool}
///
/// See also:
///
/// * <https://docs.microsoft.com/en-us/typography/opentype/spec/features_pt#sups>
/// * [FontFeature.subscripts], which is similar but for subscripting.
const FontFeature.superscripts() : feature = 'sups', value = 1;
/// Enable swash glyphs. (`swsh`)
///
/// Some fonts have beautiful flourishes on some characters. These
/// come in many forms, such as exaggerated serifs, long tails, long
/// entry strokes, or other forms of decorative extensions to the
/// base character.
///
/// This feature enables the rendering of these flourishes. Some
/// fonts have many swashes per character; the argument, if
/// specified, selects which swash to use (0 disables them
/// altogether).
///
/// Some fonts have an absurd number of alternative swashes. For
/// example, Adobe's Poetica famously has 63 different ampersand
/// forms available through this feature!
///
/// {@tool sample}
/// The BioRhyme Expanded font supports the `swsh` feature specifically
/// for the capital "Q" and "R" glyphs and the ampersand.
///
/// ![](https://flutter.github.io/assets-for-api-docs/assets/dart-ui/font_feature_swsh.png)
///
/// ** See code in examples/api/lib/ui/text/font_feature.font_feature_swash.0.dart **
/// {@end-tool}
///
/// See also:
///
/// * <https://docs.microsoft.com/en-us/typography/opentype/spec/features_pt#swsh>
/// * <https://en.wikipedia.org/wiki/Swash_(typography)>
const FontFeature.swash([this.value = 1]) : feature = 'swsh', assert(value >= 0);
/// Use tabular (monospace) figures. (`tnum`)
///
/// For fonts that have both proportional (varying width) and tabular figures,
/// this enables the tabular figures. Tabular figures are monospaced (all the
/// same width), so that they align in tables of figures.
///
/// This is mutually exclusive with [FontFeature.proportionalFigures].
///
/// The default behavior varies from font to font.
///
/// {@tool sample}
/// The Piazzolla font supports the `tnum` feature. It causes the
/// digits to become uniformly-sized, rather than having variable
/// widths. In this font this is especially noticeable with the
/// digit "1"; with tabular figures enabled, the "1" digit is more
/// widely spaced.
///
/// ![](https://flutter.github.io/assets-for-api-docs/assets/dart-ui/font_feature_tnum.png)
///
/// ** See code in examples/api/lib/ui/text/font_feature.font_feature_tabular_figures.0.dart **
/// {@end-tool}
///
/// See also:
///
/// * <https://docs.microsoft.com/en-us/typography/opentype/spec/features_pt#tnum>
const FontFeature.tabularFigures() : feature = 'tnum', value = 1;
/// Use the slashed zero. (`zero`)
///
/// Some fonts contain both a circular zero and a zero with a slash. This
/// enables the use of the latter form.
///
/// This is overridden by [FontFeature.oldstyleFigures].
///
/// {@tool sample}
/// The Source Code Pro font supports the `zero` feature. It causes the
/// zero digit to be drawn with a slash rather than the default rendering,
/// which in this case has a dot through the zero rather than a slash.
///
/// ![](https://flutter.github.io/assets-for-api-docs/assets/dart-ui/font_feature_zero.png)
///
/// ** See code in examples/api/lib/ui/text/font_feature.font_feature_slashed_zero.0.dart **
/// {@end-tool}
///
/// See also:
///
/// * <https://docs.microsoft.com/en-us/typography/opentype/spec/features_uz#zero>
const FontFeature.slashedZero() : feature = 'zero', value = 1;
// ------------------------------------------------------------------------
// End of feature tags list.
/// The tag that identifies the effect of this feature. Must consist of 4
/// ASCII characters (typically lowercase letters).
///
/// These features are defined in a registry maintained by Microsoft:
/// <https://docs.microsoft.com/en-us/typography/opentype/spec/featuretags>
final String feature;
/// The value assigned to this feature.
///
/// Must be a positive integer. Many features are Boolean values that accept
/// values of either 0 (feature is disabled) or 1 (feature is enabled). Other
/// features have a bound range of values (which may be documented in these
/// API docs for features that have dedicated constructors, and are generally
/// documented in the official registry). In some cases the precise supported
/// range depends on the font.
///
/// See also:
///
/// * <https://docs.microsoft.com/en-us/typography/opentype/spec/featurelist>
final int value;
static const int _kEncodedSize = 8;
void _encode(ByteData byteData) {
assert(feature.codeUnits.every((int c) => c >= 0x20 && c <= 0x7F));
for (int i = 0; i < 4; i++) {
byteData.setUint8(i, feature.codeUnitAt(i));
}
byteData.setInt32(4, value, _kFakeHostEndian);
}
@override
bool operator ==(Object other) {
if (other.runtimeType != runtimeType) {
return false;
}
return other is FontFeature
&& other.feature == feature
&& other.value == value;
}
@override
int get hashCode => Object.hash(feature, value);
@override
String toString() => "FontFeature('$feature', $value)";
}
/// An axis tag and value that can be used to customize variable fonts.
///
/// Some fonts are variable fonts that can generate a range of different
/// font faces by altering the values of the font's design axes.
///
/// See https://docs.microsoft.com/en-us/typography/opentype/spec/otvaroverview
///
/// Example:
/// `TextStyle(fontVariations: <FontVariation>[FontVariation('wght', 800.0)])`
class FontVariation {
/// Creates a [FontVariation] object, which can be added to a [TextStyle] to
/// change the variable attributes of a font.
///
/// `axis` is the four-character tag that identifies the design axis.
/// These tags are specified by font formats such as OpenType.
/// See https://docs.microsoft.com/en-us/typography/opentype/spec/dvaraxisreg
///
/// `value` is the value that the axis will be set to. The behavior
/// depends on how the font implements the axis.
const FontVariation(
this.axis,
this.value,
) : assert(axis.length == 4, 'Axis tag must be exactly four characters long.');
/// The tag that identifies the design axis. Must consist of 4 ASCII
/// characters.
final String axis;
/// The value assigned to this design axis.
///
/// The range of usable values depends on the specification of the axis.
final double value;
static const int _kEncodedSize = 8;
void _encode(ByteData byteData) {
assert(axis.codeUnits.every((int c) => c >= 0x20 && c <= 0x7F));
for (int i = 0; i < 4; i++) {
byteData.setUint8(i, axis.codeUnitAt(i));
}
byteData.setFloat32(4, value, _kFakeHostEndian);
}
@override
bool operator ==(Object other) {
if (other.runtimeType != runtimeType) {
return false;
}
return other is FontVariation
&& other.axis == axis
&& other.value == value;
}
@override
int get hashCode => Object.hash(axis, value);
@override
String toString() => "FontVariation('$axis', $value)";
}
/// Whether and how to align text horizontally.
// The order of this enum must match the order of the values in RenderStyleConstants.h's ETextAlign.
enum TextAlign {
/// Align the text on the left edge of the container.
left,