| // 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. |
| // Synced 2019-05-30T14:20:57.833907. |
| |
| // @dart = 2.6 |
| part of ui; |
| |
| /// Whether to slant the glyphs in the font |
| enum FontStyle { |
| /// Use the upright glyphs |
| normal, |
| |
| /// Use glyphs designed for slanting |
| italic, |
| } |
| |
| /// Where to vertically align the placeholder relative to the surrounding text. |
| /// |
| /// Used by [ParagraphBuilder.addPlaceholder]. |
| enum PlaceholderAlignment { |
| /// Match the baseline of the placeholder with the baseline. |
| /// |
| /// The [TextBaseline] to use must be specified and non-null when using this |
| /// alignment mode. |
| baseline, |
| |
| /// Align the bottom edge of the placeholder with the baseline such that the |
| /// placeholder sits on top of the baseline. |
| /// |
| /// The [TextBaseline] to use must be specified and non-null when using this |
| /// alignment mode. |
| aboveBaseline, |
| |
| /// Align the top edge of the placeholder with the baseline specified |
| /// such that the placeholder hangs below the baseline. |
| /// |
| /// The [TextBaseline] to use must be specified and non-null when using this |
| /// alignment mode. |
| belowBaseline, |
| |
| /// Align the top edge of the placeholder with the top edge of the font. |
| /// |
| /// When the placeholder is very tall, the extra space will hang from |
| /// the top and extend through the bottom of the line. |
| top, |
| |
| /// Align the bottom edge of the placeholder with the top edge of the font. |
| /// |
| /// When the placeholder is very tall, the extra space will rise from the |
| /// bottom and extend through the top of the line. |
| bottom, |
| |
| /// Align the middle of the placeholder with the middle of the text. |
| /// |
| /// When the placeholder is very tall, the extra space will grow equally |
| /// from the top and bottom of the line. |
| middle, |
| } |
| |
| /// The thickness of the glyphs used to draw the text |
| class FontWeight { |
| const FontWeight._(this.index); |
| |
| /// The encoded integer value of this font weight. |
| final int index; |
| |
| /// Thin, the least thick |
| static const FontWeight w100 = FontWeight._(0); |
| |
| /// Extra-light |
| static const FontWeight w200 = FontWeight._(1); |
| |
| /// Light |
| static const FontWeight w300 = FontWeight._(2); |
| |
| /// Normal / regular / plain |
| static const FontWeight w400 = FontWeight._(3); |
| |
| /// Medium |
| static const FontWeight w500 = FontWeight._(4); |
| |
| /// Semi-bold |
| static const FontWeight w600 = FontWeight._(5); |
| |
| /// Bold |
| static const FontWeight w700 = FontWeight._(6); |
| |
| /// Extra-bold |
| static const FontWeight w800 = FontWeight._(7); |
| |
| /// Black, the most thick |
| static const FontWeight w900 = FontWeight._(8); |
| |
| /// 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. |
| /// |
| /// 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) { |
| assert(t != null); |
| return values[ |
| lerpDouble(a?.index ?? normal.index, b?.index ?? 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. |
| 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 != null), |
| assert(feature.length == 4), |
| assert(value != null), |
| assert(value >= 0); |
| |
| /// 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); |
| |
| /// Randomize the alternate forms used in text. |
| /// |
| /// 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. |
| /// |
| /// See also: |
| /// |
| /// * <https://docs.microsoft.com/en-us/typography/opentype/spec/features_pt#rand> |
| const FontFeature.randomize() |
| : feature = 'rand', |
| value = 1; |
| |
| /// Select a stylistic set. |
| /// |
| /// Fonts may have up to 20 stylistic sets, numbered 1 through 20. |
| /// |
| /// See also: |
| /// |
| /// * <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")}'); |
| } |
| |
| /// Use the slashed 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]. |
| /// |
| /// See also: |
| /// |
| /// * <https://docs.microsoft.com/en-us/typography/opentype/spec/features_uz#zero> |
| const FontFeature.slashedZero() |
| : feature = 'zero', |
| value = 1; |
| |
| /// Use oldstyle figures. |
| /// |
| /// 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. |
| /// |
| /// This overrides [FontFeature.slashedZero]. |
| /// |
| /// See also: |
| /// |
| /// * <https://docs.microsoft.com/en-us/typography/opentype/spec/features_ko#onum> |
| const FontFeature.oldstyleFigures() |
| : feature = 'onum', |
| value = 1; |
| |
| /// Use proportional (varying width) figures. |
| /// |
| /// 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. |
| /// |
| /// See also: |
| /// |
| /// * <https://docs.microsoft.com/en-us/typography/opentype/spec/features_pt#pnum> |
| const FontFeature.proportionalFigures() |
| : feature = 'pnum', |
| value = 1; |
| |
| /// Use tabular (monospace) figures. |
| /// |
| /// For fonts that have both proportional (varying width) and tabular figures, |
| /// this enables the tabular figures. |
| /// |
| /// This is mutually exclusive with [FontFeature.proportionalFigures]. |
| /// |
| /// The default behavior varies from font to font. |
| /// |
| /// See also: |
| /// |
| /// * <https://docs.microsoft.com/en-us/typography/opentype/spec/features_pt#tnum> |
| const FontFeature.tabularFigures() |
| : feature = 'tnum', |
| value = 1; |
| |
| /// The tag that identifies the effect of this feature. Must consist of 4 |
| /// ASCII characters (typically lowercase letters). |
| /// |
| /// See <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). |
| final int value; |
| |
| @override |
| bool operator ==(dynamic other) { |
| if (identical(this, other)) { |
| return true; |
| } |
| if (other.runtimeType != runtimeType) { |
| return false; |
| } |
| final FontFeature typedOther = other; |
| return feature == typedOther.feature && value == typedOther.value; |
| } |
| |
| @override |
| int get hashCode => hashValues(feature, value); |
| |
| @override |
| String toString() => 'FontFeature($feature, $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, |
| |
| /// Align the text on the right edge of the container. |
| right, |
| |
| /// Align the text in the center of the container. |
| center, |
| |
| /// Stretch lines of text that end with a soft line break to fill the width of |
| /// the container. |
| /// |
| /// Lines that end with hard line breaks are aligned towards the [start] edge. |
| justify, |
| |
| /// Align the text on the leading edge of the container. |
| /// |
| /// For left-to-right text ([TextDirection.ltr]), this is the left edge. |
| /// |
| /// For right-to-left text ([TextDirection.rtl]), this is the right edge. |
| start, |
| |
| /// Align the text on the trailing edge of the container. |
| /// |
| /// For left-to-right text ([TextDirection.ltr]), this is the right edge. |
| /// |
| /// For right-to-left text ([TextDirection.rtl]), this is the left edge. |
| end, |
| } |
| |
| /// A horizontal line used for aligning text. |
| enum TextBaseline { |
| /// The horizontal line used to align the bottom of glyphs for alphabetic characters. |
| alphabetic, |
| |
| /// The horizontal line used to align ideographic characters. |
| ideographic, |
| } |
| |
| /// A linear decoration to draw near the text. |
| class TextDecoration { |
| const TextDecoration._(this._mask); |
| |
| /// Creates a decoration that paints the union of all the given decorations. |
| factory TextDecoration.combine(List<TextDecoration> decorations) { |
| int mask = 0; |
| for (TextDecoration decoration in decorations) { |
| mask |= decoration._mask; |
| } |
| return TextDecoration._(mask); |
| } |
| |
| final int _mask; |
| |
| /// Whether this decoration will paint at least as much decoration as the given decoration. |
| bool contains(TextDecoration other) { |
| return (_mask | other._mask) == _mask; |
| } |
| |
| /// Do not draw a decoration |
| static const TextDecoration none = TextDecoration._(0x0); |
| |
| /// Draw a line underneath each line of text |
| static const TextDecoration underline = TextDecoration._(0x1); |
| |
| /// Draw a line above each line of text |
| static const TextDecoration overline = TextDecoration._(0x2); |
| |
| /// Draw a line through each line of text |
| static const TextDecoration lineThrough = TextDecoration._(0x4); |
| |
| @override |
| bool operator ==(dynamic other) { |
| if (other is! TextDecoration) { |
| return false; |
| } |
| final TextDecoration typedOther = other; |
| return _mask == typedOther._mask; |
| } |
| |
| @override |
| int get hashCode => _mask.hashCode; |
| |
| @override |
| String toString() { |
| if (_mask == 0) { |
| return 'TextDecoration.none'; |
| } |
| final List<String> values = <String>[]; |
| if (_mask & underline._mask != 0) { |
| values.add('underline'); |
| } |
| if (_mask & overline._mask != 0) { |
| values.add('overline'); |
| } |
| if (_mask & lineThrough._mask != 0) { |
| values.add('lineThrough'); |
| } |
| if (values.length == 1) { |
| return 'TextDecoration.${values[0]}'; |
| } |
| return 'TextDecoration.combine([${values.join(", ")}])'; |
| } |
| } |
| |
| /// The style in which to draw a text decoration |
| enum TextDecorationStyle { |
| /// Draw a solid line |
| solid, |
| |
| /// Draw two lines |
| double, |
| |
| /// Draw a dotted line |
| dotted, |
| |
| /// Draw a dashed line |
| dashed, |
| |
| /// Draw a sinusoidal line |
| wavy |
| } |
| |
| /// Defines how the paragraph will apply [TextStyle.height] the ascent of the |
| /// first line and descent of the last line. |
| /// |
| /// The boolean value represents whether the [TextStyle.height] modifier will |
| /// be applied to the corresponding metric. By default, all properties are true, |
| /// and [TextStyle.height] is applied as normal. When set to false, the font's |
| /// default ascent will be used. |
| class TextHeightBehavior { |
| |
| /// Creates a new TextHeightBehavior object. |
| /// |
| /// * applyHeightToFirstAscent: When true, the [TextStyle.height] modifier |
| /// will be applied to the ascent of the first line. When false, the font's |
| /// default ascent will be used. |
| /// * applyHeightToLastDescent: When true, the [TextStyle.height] modifier |
| /// will be applied to the descent of the last line. When false, the font's |
| /// default descent will be used. |
| /// |
| /// All properties default to true (height modifications applied as normal). |
| const TextHeightBehavior({ |
| this.applyHeightToFirstAscent = true, |
| this.applyHeightToLastDescent = true, |
| }); |
| |
| /// Creates a new TextHeightBehavior object from an encoded form. |
| /// |
| /// See [encode] for the creation of the encoded form. |
| const TextHeightBehavior.fromEncoded(int encoded) : applyHeightToFirstAscent = (encoded & 0x1) == 0, |
| applyHeightToLastDescent = (encoded & 0x2) == 0; |
| |
| |
| /// Whether to apply the [TextStyle.height] modifier to the ascent of the first |
| /// line in the paragraph. |
| /// |
| /// When true, the [TextStyle.height] modifier will be applied to to the ascent |
| /// of the first line. When false, the font's default ascent will be used and |
| /// the [TextStyle.height] will have no effect on the ascent of the first line. |
| /// |
| /// This property only has effect if a non-null [TextStyle.height] is specified. |
| /// |
| /// Defaults to true (height modifications applied as normal). |
| final bool applyHeightToFirstAscent; |
| |
| /// Whether to apply the [TextStyle.height] modifier to the descent of the last |
| /// line in the paragraph. |
| /// |
| /// When true, the [TextStyle.height] modifier will be applied to to the descent |
| /// of the last line. When false, the font's default descent will be used and |
| /// the [TextStyle.height] will have no effect on the descent of the last line. |
| /// |
| /// This property only has effect if a non-null [TextStyle.height] is specified. |
| /// |
| /// Defaults to true (height modifications applied as normal). |
| final bool applyHeightToLastDescent; |
| |
| /// Returns an encoded int representation of this object. |
| int encode() { |
| return (applyHeightToFirstAscent ? 0 : 1 << 0) | (applyHeightToLastDescent ? 0 : 1 << 1); |
| } |
| |
| @override |
| bool operator ==(dynamic other) { |
| if (other.runtimeType != runtimeType) |
| return false; |
| return other is TextHeightBehavior |
| && other.applyHeightToFirstAscent == applyHeightToFirstAscent |
| && other.applyHeightToLastDescent == applyHeightToLastDescent; |
| } |
| |
| @override |
| int get hashCode { |
| return hashValues( |
| applyHeightToFirstAscent, |
| applyHeightToLastDescent, |
| ); |
| } |
| |
| @override |
| String toString() { |
| return 'TextHeightBehavior(' |
| 'applyHeightToFirstAscent: $applyHeightToFirstAscent, ' |
| 'applyHeightToLastDescent: $applyHeightToLastDescent' |
| ')'; |
| } |
| } |
| |
| /// An opaque object that determines the size, position, and rendering of text. |
| abstract class TextStyle { |
| /// Creates a new TextStyle object. |
| /// |
| /// * `color`: The color to use when painting the text. If this is specified, `foreground` must be null. |
| /// * `decoration`: The decorations to paint near the text (e.g., an underline). |
| /// * `decorationColor`: The color in which to paint the text decorations. |
| /// * `decorationStyle`: The style in which to paint the text decorations (e.g., dashed). |
| /// * `fontWeight`: The typeface thickness to use when painting the text (e.g., bold). |
| /// * `fontStyle`: The typeface variant to use when drawing the letters (e.g., italics). |
| /// * `fontFamily`: The name of the font to use when painting the text (e.g., Roboto). If a `fontFamilyFallback` is |
| /// provided and `fontFamily` is not, then the first font family in `fontFamilyFallback` will take the postion of |
| /// the preferred font family. When a higher priority font cannot be found or does not contain a glyph, a lower |
| /// priority font will be used. |
| /// * `fontFamilyFallback`: An ordered list of the names of the fonts to fallback on when a glyph cannot |
| /// be found in a higher priority font. When the `fontFamily` is null, the first font family in this list |
| /// is used as the preferred font. Internally, the 'fontFamily` is concatenated to the front of this list. |
| /// When no font family is provided through 'fontFamilyFallback' (null or empty) or `fontFamily`, then the |
| /// platform default font will be used. |
| /// * `fontSize`: The size of glyphs (in logical pixels) to use when painting the text. |
| /// * `letterSpacing`: The amount of space (in logical pixels) to add between each letter. |
| /// * `wordSpacing`: The amount of space (in logical pixels) to add at each sequence of white-space (i.e. between each word). |
| /// * `textBaseline`: The common baseline that should be aligned between this text span and its parent text span, or, for the root text spans, with the line box. |
| /// * `height`: The height of this text span, as a multiple of the font size. |
| /// * `locale`: The locale used to select region-specific glyphs. |
| /// * `background`: The paint drawn as a background for the text. |
| /// * `foreground`: The paint used to draw the text. If this is specified, `color` must be null. |
| factory TextStyle({ |
| Color color, |
| TextDecoration decoration, |
| Color decorationColor, |
| TextDecorationStyle decorationStyle, |
| double decorationThickness, |
| FontWeight fontWeight, |
| FontStyle fontStyle, |
| TextBaseline textBaseline, |
| String fontFamily, |
| List<String> fontFamilyFallback, |
| double fontSize, |
| double letterSpacing, |
| double wordSpacing, |
| double height, |
| Locale locale, |
| Paint background, |
| Paint foreground, |
| List<Shadow> shadows, |
| List<FontFeature> fontFeatures, |
| }) { |
| if (engine.experimentalUseSkia) { |
| return engine.SkTextStyle( |
| color: color, |
| decoration: decoration, |
| decorationColor: decorationColor, |
| decorationStyle: decorationStyle, |
| decorationThickness: decorationThickness, |
| fontWeight: fontWeight, |
| fontStyle: fontStyle, |
| textBaseline: textBaseline, |
| fontFamily: fontFamily, |
| fontFamilyFallback: fontFamilyFallback, |
| fontSize: fontSize, |
| letterSpacing: letterSpacing, |
| wordSpacing: wordSpacing, |
| height: height, |
| locale: locale, |
| background: background, |
| foreground: foreground, |
| shadows: shadows, |
| fontFeatures: fontFeatures, |
| ); |
| } else { |
| return engine.EngineTextStyle( |
| color: color, |
| decoration: decoration, |
| decorationColor: decorationColor, |
| decorationStyle: decorationStyle, |
| decorationThickness: decorationThickness, |
| fontWeight: fontWeight, |
| fontStyle: fontStyle, |
| textBaseline: textBaseline, |
| fontFamily: fontFamily, |
| fontFamilyFallback: fontFamilyFallback, |
| fontSize: fontSize, |
| letterSpacing: letterSpacing, |
| wordSpacing: wordSpacing, |
| height: height, |
| locale: locale, |
| background: background, |
| foreground: foreground, |
| shadows: shadows, |
| fontFeatures: fontFeatures, |
| ); |
| } |
| } |
| } |
| |
| /// An opaque object that determines the configuration used by |
| /// [ParagraphBuilder] to position lines within a [Paragraph] of text. |
| abstract class ParagraphStyle { |
| /// Creates a new ParagraphStyle object. |
| /// |
| /// * `textAlign`: The alignment of the text within the lines of the |
| /// paragraph. If the last line is ellipsized (see `ellipsis` below), the |
| /// alignment is applied to that line after it has been truncated but before |
| /// the ellipsis has been added. |
| // See: https://github.com/flutter/flutter/issues/9819 |
| /// |
| /// * `textDirection`: The directionality of the text, left-to-right (e.g. |
| /// Norwegian) or right-to-left (e.g. Hebrew). This controls the overall |
| /// directionality of the paragraph, as well as the meaning of |
| /// [TextAlign.start] and [TextAlign.end] in the `textAlign` field. |
| /// |
| /// * `maxLines`: The maximum number of lines painted. Lines beyond this |
| /// number are silently dropped. For example, if `maxLines` is 1, then only |
| /// one line is rendered. If `maxLines` is null, but `ellipsis` is not null, |
| /// then lines after the first one that overflows the width constraints are |
| /// dropped. The width constraints are those set in the |
| /// [ParagraphConstraints] object passed to the [Paragraph.layout] method. |
| /// |
| /// * `fontFamily`: The name of the font to use when painting the text (e.g., |
| /// Roboto). |
| /// |
| /// * `fontSize`: The size of glyphs (in logical pixels) to use when painting |
| /// the text. |
| /// |
| /// * `height`: The minimum height of the line boxes, as a multiple of the |
| /// font size. The lines of the paragraph will be at least |
| /// `(height + leading) * fontSize` tall when fontSize |
| /// is not null. When fontSize is null, there is no minimum line height. Tall |
| /// glyphs due to baseline alignment or large [TextStyle.fontSize] may cause |
| /// the actual line height after layout to be taller than specified here. |
| /// [fontSize] must be provided for this property to take effect. |
| /// |
| /// * `fontWeight`: The typeface thickness to use when painting the text |
| /// (e.g., bold). |
| /// |
| /// * `fontStyle`: The typeface variant to use when drawing the letters (e.g., |
| /// italics). |
| /// |
| /// * `strutStyle`: The properties of the strut. Strut defines a set of minimum |
| /// vertical line height related metrics and can be used to obtain more |
| /// advanced line spacing behavior. |
| /// |
| /// * `ellipsis`: String used to ellipsize overflowing text. If `maxLines` is |
| /// not null, then the `ellipsis`, if any, is applied to the last rendered |
| /// line, if that line overflows the width constraints. If `maxLines` is |
| /// null, then the `ellipsis` is applied to the first line that overflows |
| /// the width constraints, and subsequent lines are dropped. The width |
| /// constraints are those set in the [ParagraphConstraints] object passed to |
| /// the [Paragraph.layout] method. The empty string and the null value are |
| /// considered equivalent and turn off this behavior. |
| /// |
| /// * `locale`: The locale used to select region-specific glyphs. |
| factory ParagraphStyle({ |
| TextAlign textAlign, |
| TextDirection textDirection, |
| int maxLines, |
| String fontFamily, |
| double fontSize, |
| double height, |
| TextHeightBehavior textHeightBehavior, |
| FontWeight fontWeight, |
| FontStyle fontStyle, |
| StrutStyle strutStyle, |
| String ellipsis, |
| Locale locale, |
| }) { |
| if (engine.experimentalUseSkia) { |
| return engine.SkParagraphStyle( |
| textAlign: textAlign, |
| textDirection: textDirection, |
| maxLines: maxLines, |
| fontFamily: fontFamily, |
| fontSize: fontSize, |
| height: height, |
| textHeightBehavior: textHeightBehavior, |
| fontWeight: fontWeight, |
| fontStyle: fontStyle, |
| strutStyle: strutStyle, |
| ellipsis: ellipsis, |
| locale: locale, |
| ); |
| } else { |
| return engine.EngineParagraphStyle( |
| textAlign: textAlign, |
| textDirection: textDirection, |
| maxLines: maxLines, |
| fontFamily: fontFamily, |
| fontSize: fontSize, |
| height: height, |
| textHeightBehavior: textHeightBehavior, |
| fontWeight: fontWeight, |
| fontStyle: fontStyle, |
| strutStyle: strutStyle, |
| ellipsis: ellipsis, |
| locale: locale, |
| ); |
| } |
| } |
| } |
| |
| abstract class StrutStyle { |
| /// Creates a new StrutStyle object. |
| /// |
| /// * `fontFamily`: The name of the font to use when painting the text (e.g., |
| /// Roboto). |
| /// |
| /// * `fontFamilyFallback`: An ordered list of font family names that will be searched for when |
| /// the font in `fontFamily` cannot be found. |
| /// |
| /// * `fontSize`: The size of glyphs (in logical pixels) to use when painting |
| /// the text. |
| /// |
| /// * `lineHeight`: The minimum height of the line boxes, as a multiple of the |
| /// font size. The lines of the paragraph will be at least |
| /// `(lineHeight + leading) * fontSize` tall when fontSize |
| /// is not null. When fontSize is null, there is no minimum line height. Tall |
| /// glyphs due to baseline alignment or large [TextStyle.fontSize] may cause |
| /// the actual line height after layout to be taller than specified here. |
| /// [fontSize] must be provided for this property to take effect. |
| /// |
| /// * `leading`: The minimum amount of leading between lines as a multiple of |
| /// the font size. [fontSize] must be provided for this property to take effect. |
| /// |
| /// * `fontWeight`: The typeface thickness to use when painting the text |
| /// (e.g., bold). |
| /// |
| /// * `fontStyle`: The typeface variant to use when drawing the letters (e.g., |
| /// italics). |
| /// |
| /// * `forceStrutHeight`: When true, the paragraph will force all lines to be exactly |
| /// `(lineHeight + leading) * fontSize` tall from baseline to baseline. |
| /// [TextStyle] is no longer able to influence the line height, and any tall |
| /// glyphs may overlap with lines above. If a [fontFamily] is specified, the |
| /// total ascent of the first line will be the min of the `Ascent + half-leading` |
| /// of the [fontFamily] and `(lineHeight + leading) * fontSize`. Otherwise, it |
| /// will be determined by the Ascent + half-leading of the first text. |
| factory StrutStyle({ |
| String fontFamily, |
| List<String> fontFamilyFallback, |
| double fontSize, |
| double height, |
| double leading, |
| FontWeight fontWeight, |
| FontStyle fontStyle, |
| bool forceStrutHeight, |
| }) = engine.EngineStrutStyle; |
| } |
| |
| /// A direction in which text flows. |
| /// |
| /// Some languages are written from the left to the right (for example, English, |
| /// Tamil, or Chinese), while others are written from the right to the left (for |
| /// example Aramaic, Hebrew, or Urdu). Some are also written in a mixture, for |
| /// example Arabic is mostly written right-to-left, with numerals written |
| /// left-to-right. |
| /// |
| /// The text direction must be provided to APIs that render text or lay out |
| /// boxes horizontally, so that they can determine which direction to start in: |
| /// either right-to-left, [TextDirection.rtl]; or left-to-right, |
| /// [TextDirection.ltr]. |
| /// |
| /// ## Design discussion |
| /// |
| /// Flutter is designed to address the needs of applications written in any of |
| /// the world's currently-used languages, whether they use a right-to-left or |
| /// left-to-right writing direction. Flutter does not support other writing |
| /// modes, such as vertical text or boustrophedon text, as these are rarely used |
| /// in computer programs. |
| /// |
| /// It is common when developing user interface frameworks to pick a default |
| /// text direction — typically left-to-right, the direction most familiar to the |
| /// engineers working on the framework — because this simplifies the development |
| /// of applications on the platform. Unfortunately, this frequently results in |
| /// the platform having unexpected left-to-right biases or assumptions, as |
| /// engineers will typically miss places where they need to support |
| /// right-to-left text. This then results in bugs that only manifest in |
| /// right-to-left environments. |
| /// |
| /// In an effort to minimize the extent to which Flutter experiences this |
| /// category of issues, the lowest levels of the Flutter framework do not have a |
| /// default text reading direction. Any time a reading direction is necessary, |
| /// for example when text is to be displayed, or when a |
| /// writing-direction-dependent value is to be interpreted, the reading |
| /// direction must be explicitly specified. Where possible, such as in `switch` |
| /// statements, the right-to-left case is listed first, to avoid the impression |
| /// that it is an afterthought. |
| /// |
| /// At the higher levels (specifically starting at the widgets library), an |
| /// ambient [Directionality] is introduced, which provides a default. Thus, for |
| /// instance, a [Text] widget in the scope of a [MaterialApp] widget does not |
| /// need to be given an explicit writing direction. The [Directionality.of] |
| /// static method can be used to obtain the ambient text direction for a |
| /// particular [BuildContext]. |
| /// |
| /// ### Known left-to-right biases in Flutter |
| /// |
| /// Despite the design intent described above, certain left-to-right biases have |
| /// nonetheless crept into Flutter's design. These include: |
| /// |
| /// * The [Canvas] origin is at the top left, and the x-axis increases in a |
| /// left-to-right direction. |
| /// |
| /// * The default localization in the widgets and material libraries is |
| /// American English, which is left-to-right. |
| /// |
| /// ### Visual properties vs directional properties |
| /// |
| /// Many classes in the Flutter framework are offered in two versions, a |
| /// visually-oriented variant, and a text-direction-dependent variant. For |
| /// example, [EdgeInsets] is described in terms of top, left, right, and bottom, |
| /// while [EdgeInsetsDirectional] is described in terms of top, start, end, and |
| /// bottom, where start and end correspond to right and left in right-to-left |
| /// text and left and right in left-to-right text. |
| /// |
| /// There are distinct use cases for each of these variants. |
| /// |
| /// Text-direction-dependent variants are useful when developing user interfaces |
| /// that should "flip" with the text direction. For example, a paragraph of text |
| /// in English will typically be left-aligned and a quote will be indented from |
| /// the left, while in Arabic it will be right-aligned and indented from the |
| /// right. Both of these cases are described by the direction-dependent |
| /// [TextAlign.start] and [EdgeInsetsDirectional.start]. |
| /// |
| /// In contrast, the visual variants are useful when the text direction is known |
| /// and not affected by the reading direction. For example, an application |
| /// giving driving directions might show a "turn left" arrow on the left and a |
| /// "turn right" arrow on the right — and would do so whether the application |
| /// was localized to French (left-to-right) or Hebrew (right-to-left). |
| /// |
| /// In practice, it is also expected that many developers will only be |
| /// targeting one language, and in that case it may be simpler to think in |
| /// visual terms. |
| // The order of this enum must match the order of the values in TextDirection.h's TextDirection. |
| enum TextDirection { |
| /// The text flows from right to left (e.g. Arabic, Hebrew). |
| rtl, |
| |
| /// The text flows from left to right (e.g., English, French). |
| ltr, |
| } |
| |
| /// A rectangle enclosing a run of text. |
| /// |
| /// This is similar to [Rect] but includes an inherent [TextDirection]. |
| class TextBox { |
| /// Creates an object that describes a box containing text. |
| const TextBox.fromLTRBD( |
| this.left, |
| this.top, |
| this.right, |
| this.bottom, |
| this.direction, |
| ); |
| |
| /// The left edge of the text box, irrespective of direction. |
| /// |
| /// To get the leading edge (which may depend on the [direction]), consider [start]. |
| final double left; |
| |
| /// The top edge of the text box. |
| final double top; |
| |
| /// The right edge of the text box, irrespective of direction. |
| /// |
| /// To get the trailing edge (which may depend on the [direction]), consider [end]. |
| final double right; |
| |
| /// The bottom edge of the text box. |
| final double bottom; |
| |
| /// The direction in which text inside this box flows. |
| final TextDirection direction; |
| |
| /// Returns a rect of the same size as this box. |
| Rect toRect() => Rect.fromLTRB(left, top, right, bottom); |
| |
| /// The [left] edge of the box for left-to-right text; the [right] edge of the box for right-to-left text. |
| /// |
| /// See also: |
| /// |
| /// * [direction], which specifies the text direction. |
| double get start { |
| return (direction == TextDirection.ltr) ? left : right; |
| } |
| |
| /// The [right] edge of the box for left-to-right text; the [left] edge of the box for right-to-left text. |
| /// |
| /// See also: |
| /// |
| /// * [direction], which specifies the text direction. |
| double get end { |
| return (direction == TextDirection.ltr) ? right : left; |
| } |
| |
| @override |
| bool operator ==(dynamic other) { |
| if (identical(this, other)) { |
| return true; |
| } |
| if (other.runtimeType != runtimeType) { |
| return false; |
| } |
| final TextBox typedOther = other; |
| return typedOther.left == left && |
| typedOther.top == top && |
| typedOther.right == right && |
| typedOther.bottom == bottom && |
| typedOther.direction == direction; |
| } |
| |
| @override |
| int get hashCode => hashValues(left, top, right, bottom, direction); |
| |
| @override |
| String toString() { |
| return 'TextBox.fromLTRBD(${left.toStringAsFixed(1)}, ${top.toStringAsFixed(1)}, ${right.toStringAsFixed(1)}, ${bottom.toStringAsFixed(1)}, $direction)'; |
| } |
| } |
| |
| /// A way to disambiguate a [TextPosition] when its offset could match two |
| /// different locations in the rendered string. |
| /// |
| /// For example, at an offset where the rendered text wraps, there are two |
| /// visual positions that the offset could represent: one prior to the line |
| /// break (at the end of the first line) and one after the line break (at the |
| /// start of the second line). A text affinity disambiguates between these two |
| /// cases. |
| /// |
| /// This affects only line breaks caused by wrapping, not explicit newline |
| /// characters. For newline characters, the position is fully specified by the |
| /// offset alone, and there is no ambiguity. |
| /// |
| /// [TextAffinity] also affects bidirectional text at the interface between LTR |
| /// and RTL text. Consider the following string, where the lowercase letters |
| /// will be displayed as LTR and the uppercase letters RTL: "helloHELLO". When |
| /// rendered, the string would appear visually as "helloOLLEH". An offset of 5 |
| /// would be ambiguous without a corresponding [TextAffinity]. Looking at the |
| /// string in code, the offset represents the position just after the "o" and |
| /// just before the "H". When rendered, this offset could be either in the |
| /// middle of the string to the right of the "o" or at the end of the string to |
| /// the right of the "H". |
| enum TextAffinity { |
| /// The position has affinity for the upstream side of the text position, i.e. |
| /// in the direction of the beginning of the string. |
| /// |
| /// In the example of an offset at the place where text is wrapping, upstream |
| /// indicates the end of the first line. |
| /// |
| /// In the bidirectional text example "helloHELLO", an offset of 5 with |
| /// [TextAffinity] upstream would appear in the middle of the rendered text, |
| /// just to the right of the "o". See the definition of [TextAffinity] for the |
| /// full example. |
| upstream, |
| |
| /// The position has affinity for the downstream side of the text position, |
| /// i.e. in the direction of the end of the string. |
| /// |
| /// In the example of an offset at the place where text is wrapping, |
| /// downstream indicates the beginning of the second line. |
| /// |
| /// In the bidirectional text example "helloHELLO", an offset of 5 with |
| /// [TextAffinity] downstream would appear at the end of the rendered text, |
| /// just to the right of the "H". See the definition of [TextAffinity] for the |
| /// full example. |
| downstream, |
| } |
| |
| /// A position in a string of text. |
| /// |
| /// A TextPosition can be used to locate a position in a string in code (using |
| /// the [offset] property), and it can also be used to locate the same position |
| /// visually in a rendered string of text (using [offset] and, when needed to |
| /// resolve ambiguity, [affinity]). |
| /// |
| /// The location of an offset in a rendered string is ambiguous in two cases. |
| /// One happens when rendered text is forced to wrap. In this case, the offset |
| /// where the wrap occurs could visually appear either at the end of the first |
| /// line or the beginning of the second line. The second way is with |
| /// bidirectional text. An offset at the interface between two different text |
| /// directions could have one of two locations in the rendered text. |
| /// |
| /// See the documentation for [TextAffinity] for more information on how |
| /// TextAffinity disambiguates situations like these. |
| class TextPosition { |
| /// Creates an object representing a particular position in a string. |
| /// |
| /// The arguments must not be null (so the [offset] argument is required). |
| const TextPosition({ |
| this.offset, |
| this.affinity = TextAffinity.downstream, |
| }) : assert(offset != null), |
| assert(affinity != null); |
| |
| /// The index of the character that immediately follows the position in the |
| /// string representation of the text. |
| /// |
| /// For example, given the string `'Hello'`, offset 0 represents the cursor |
| /// being before the `H`, while offset 5 represents the cursor being just |
| /// after the `o`. |
| final int offset; |
| |
| /// Disambiguates cases where the position in the string given by [offset] |
| /// could represent two different visual positions in the rendered text. For |
| /// example, this can happen when text is forced to wrap, or when one string |
| /// of text is rendered with multiple text directions. |
| /// |
| /// See the documentation for [TextAffinity] for more information on how |
| /// TextAffinity disambiguates situations like these. |
| final TextAffinity affinity; |
| |
| @override |
| bool operator ==(dynamic other) { |
| if (other.runtimeType != runtimeType) { |
| return false; |
| } |
| final TextPosition typedOther = other; |
| return typedOther.offset == offset && typedOther.affinity == affinity; |
| } |
| |
| @override |
| int get hashCode => hashValues(offset, affinity); |
| |
| @override |
| String toString() { |
| return '$runtimeType(offset: $offset, affinity: $affinity)'; |
| } |
| } |
| |
| /// A range of characters in a string of text. |
| class TextRange { |
| /// Creates a text range. |
| /// |
| /// The [start] and [end] arguments must not be null. Both the [start] and |
| /// [end] must either be greater than or equal to zero or both exactly -1. |
| /// |
| /// Instead of creating an empty text range, consider using the [empty] |
| /// constant. |
| const TextRange({ |
| this.start, |
| this.end, |
| }) : assert(start != null && start >= -1), |
| assert(end != null && end >= -1); |
| |
| /// A text range that starts and ends at offset. |
| /// |
| /// The [offset] argument must be non-null and greater than or equal to -1. |
| const TextRange.collapsed(int offset) |
| : assert(offset != null && offset >= -1), |
| start = offset, |
| end = offset; |
| |
| /// A text range that contains nothing and is not in the text. |
| static const TextRange empty = TextRange(start: -1, end: -1); |
| |
| /// The index of the first character in the range. |
| /// |
| /// If [start] and [end] are both -1, the text range is empty. |
| final int start; |
| |
| /// The next index after the characters in this range. |
| /// |
| /// If [start] and [end] are both -1, the text range is empty. |
| final int end; |
| |
| /// Whether this range represents a valid position in the text. |
| bool get isValid => start >= 0 && end >= 0; |
| |
| /// Whether this range is empty (but still potentially placed inside the text). |
| bool get isCollapsed => start == end; |
| |
| /// Whether the start of this range precedes the end. |
| bool get isNormalized => end >= start; |
| |
| /// The text before this range. |
| String textBefore(String text) { |
| assert(isNormalized); |
| return text.substring(0, start); |
| } |
| |
| /// The text after this range. |
| String textAfter(String text) { |
| assert(isNormalized); |
| return text.substring(end); |
| } |
| |
| /// The text inside this range. |
| String textInside(String text) { |
| assert(isNormalized); |
| return text.substring(start, end); |
| } |
| |
| @override |
| bool operator ==(dynamic other) { |
| if (identical(this, other)) { |
| return true; |
| } |
| if (other is! TextRange) { |
| return false; |
| } |
| final TextRange typedOther = other; |
| return typedOther.start == start && typedOther.end == end; |
| } |
| |
| @override |
| int get hashCode => hashValues( |
| start.hashCode, |
| end.hashCode, |
| ); |
| |
| @override |
| String toString() => 'TextRange(start: $start, end: $end)'; |
| } |
| |
| /// Layout constraints for [Paragraph] objects. |
| /// |
| /// Instances of this class are typically used with [Paragraph.layout]. |
| /// |
| /// The only constraint that can be specified is the [width]. See the discussion |
| /// at [width] for more details. |
| class ParagraphConstraints { |
| /// Creates constraints for laying out a pargraph. |
| /// |
| /// The [width] argument must not be null. |
| const ParagraphConstraints({ |
| this.width, |
| }) : assert(width != null); |
| |
| /// The width the paragraph should use whey computing the positions of glyphs. |
| /// |
| /// If possible, the paragraph will select a soft line break prior to reaching |
| /// this width. If no soft line break is available, the paragraph will select |
| /// a hard line break prior to reaching this width. If that would force a line |
| /// break without any characters having been placed (i.e. if the next |
| /// character to be laid out does not fit within the given width constraint) |
| /// then the next character is allowed to overflow the width constraint and a |
| /// forced line break is placed after it (even if an explicit line break |
| /// follows). |
| /// |
| /// The width influences how ellipses are applied. See the discussion at [new |
| /// ParagraphStyle] for more details. |
| /// |
| /// This width is also used to position glyphs according to the [TextAlign] |
| /// alignment described in the [ParagraphStyle] used when building the |
| /// [Paragraph] with a [ParagraphBuilder]. |
| final double width; |
| |
| @override |
| bool operator ==(dynamic other) { |
| if (other.runtimeType != runtimeType) { |
| return false; |
| } |
| final ParagraphConstraints typedOther = other; |
| return typedOther.width == width; |
| } |
| |
| @override |
| int get hashCode => width.hashCode; |
| |
| @override |
| String toString() => '$runtimeType(width: $width)'; |
| } |
| |
| /// Defines various ways to vertically bound the boxes returned by |
| /// [Paragraph.getBoxesForRange]. |
| enum BoxHeightStyle { |
| /// Provide tight bounding boxes that fit heights per run. This style may result |
| /// in uneven bounding boxes that do not nicely connect with adjacent boxes. |
| tight, |
| |
| /// The height of the boxes will be the maximum height of all runs in the |
| /// line. All boxes in the same line will be the same height. This does not |
| /// guarantee that the boxes will cover the entire vertical height of the line |
| /// when there is additional line spacing. |
| /// |
| /// See [BoxHeightStyle.includeLineSpacingTop], [BoxHeightStyle.includeLineSpacingMiddle], |
| /// and [BoxHeightStyle.includeLineSpacingBottom] for styles that will cover |
| /// the entire line. |
| max, |
| |
| /// Extends the top and bottom edge of the bounds to fully cover any line |
| /// spacing. |
| /// |
| /// The top and bottom of each box will cover half of the |
| /// space above and half of the space below the line. |
| /// |
| /// {@template flutter.dart:ui.boxHeightStyle.includeLineSpacing} |
| /// The top edge of each line should be the same as the bottom edge |
| /// of the line above. There should be no gaps in vertical coverage given any |
| /// amount of line spacing. Line spacing is not included above the first line |
| /// and below the last line due to no additional space present there. |
| /// {@endtemplate} |
| includeLineSpacingMiddle, |
| |
| /// Extends the top edge of the bounds to fully cover any line spacing. |
| /// |
| /// The line spacing will be added to the top of the box. |
| /// |
| /// {@macro flutter.dart:ui.boxHeightStyle.includeLineSpacing} |
| includeLineSpacingTop, |
| |
| /// Extends the bottom edge of the bounds to fully cover any line spacing. |
| /// |
| /// The line spacing will be added to the bottom of the box. |
| /// |
| /// {@macro flutter.dart:ui.boxHeightStyle.includeLineSpacing} |
| includeLineSpacingBottom, |
| |
| /// Calculate box heights based on the metrics of this paragraph's [StrutStyle]. |
| /// |
| /// Boxes based on the strut will have consistent heights throughout the |
| /// entire paragraph. The top edge of each line will align with the bottom |
| /// edge of the previous line. It is possible for glyphs to extend outside |
| /// these boxes. |
| strut, |
| } |
| |
| /// Defines various ways to horizontally bound the boxes returned by |
| /// [Paragraph.getBoxesForRange]. |
| enum BoxWidthStyle { |
| // Provide tight bounding boxes that fit widths to the runs of each line |
| // independently. |
| tight, |
| |
| /// Adds up to two additional boxes as needed at the beginning and/or end |
| /// of each line so that the widths of the boxes in line are the same width |
| /// as the widest line in the paragraph. The additional boxes on each line |
| /// are only added when the relevant box at the relevant edge of that line |
| /// does not span the maximum width of the paragraph. |
| max, |
| } |
| |
| abstract class LineMetrics { |
| factory LineMetrics({ |
| bool hardBreak, |
| double ascent, |
| double descent, |
| double unscaledAscent, |
| double height, |
| double width, |
| double left, |
| double baseline, |
| int lineNumber, |
| }) = engine.EngineLineMetrics; |
| |
| /// {@template dart.ui.LineMetrics.hardBreak} |
| /// True if this line ends with an explicit line break (e.g. '\n') or is the end |
| /// of the paragraph. False otherwise. |
| /// {@endtemplate} |
| final bool hardBreak; |
| |
| /// {@template dart.ui.LineMetrics.ascent} |
| /// The rise from the [baseline] as calculated from the font and style for this line. |
| /// |
| /// This is the final computed ascent and can be impacted by the strut, height, scaling, |
| /// as well as outlying runs that are very tall. |
| /// |
| /// The [ascent] is provided as a positive value, even though it is typically defined |
| /// in fonts as negative. This is to ensure the signage of operations with these |
| /// metrics directly reflects the intended signage of the value. For example, |
| /// the y coordinate of the top edge of the line is `baseline - ascent`. |
| /// {@endtemplate} |
| final double ascent; |
| |
| /// {@template dart.ui.LineMetrics.descent} |
| /// The drop from the [baseline] as calculated from the font and style for this line. |
| /// |
| /// This is the final computed ascent and can be impacted by the strut, height, scaling, |
| /// as well as outlying runs that are very tall. |
| /// |
| /// The y coordinate of the bottom edge of the line is `baseline + descent`. |
| /// {@endtemplate} |
| final double descent; |
| |
| /// {@template dart.ui.LineMetrics.unscaledAscent} |
| /// The rise from the [baseline] as calculated from the font and style for this line |
| /// ignoring the [TextStyle.height]. |
| /// |
| /// The [unscaledAscent] is provided as a positive value, even though it is typically |
| /// defined in fonts as negative. This is to ensure the signage of operations with |
| /// these metrics directly reflects the intended signage of the value. |
| /// {@endtemplate} |
| final double unscaledAscent; |
| |
| /// {@template dart.ui.LineMetrics.height} |
| /// Total height of the line from the top edge to the bottom edge. |
| /// |
| /// This is equivalent to `round(ascent + descent)`. This value is provided |
| /// separately due to rounding causing sub-pixel differences from the unrounded |
| /// values. |
| /// {@endtemplate} |
| final double height; |
| |
| /// {@template dart.ui.LineMetrics.width} |
| /// Width of the line from the left edge of the leftmost glyph to the right |
| /// edge of the rightmost glyph. |
| /// |
| /// This is not the same as the width of the pargraph. |
| /// |
| /// See also: |
| /// |
| /// * [Paragraph.width], the max width passed in during layout. |
| /// * [Paragraph.longestLine], the width of the longest line in the paragraph. |
| /// {@endtemplate} |
| final double width; |
| |
| /// {@template dart.ui.LineMetrics.left} |
| /// The x coordinate of left edge of the line. |
| /// |
| /// The right edge can be obtained with `left + width`. |
| /// {@endtemplate} |
| final double left; |
| |
| /// {@template dart.ui.LineMetrics.baseline} |
| /// The y coordinate of the baseline for this line from the top of the paragraph. |
| /// |
| /// The bottom edge of the paragraph up to and including this line may be obtained |
| /// through `baseline + descent`. |
| /// {@endtemplate} |
| final double baseline; |
| |
| /// {@template dart.ui.LineMetrics.lineNumber} |
| /// The number of this line in the overall paragraph, with the first line being |
| /// index zero. |
| /// |
| /// For example, the first line is line 0, second line is line 1. |
| /// {@endtemplate} |
| final int lineNumber; |
| } |
| |
| /// A paragraph of text. |
| /// |
| /// A paragraph retains the size and position of each glyph in the text and can |
| /// be efficiently resized and painted. |
| /// |
| /// To create a [Paragraph] object, use a [ParagraphBuilder]. |
| /// |
| /// Paragraphs can be displayed on a [Canvas] using the [Canvas.drawParagraph] |
| /// method. |
| abstract class Paragraph { |
| /// The amount of horizontal space this paragraph occupies. |
| /// |
| /// Valid only after [layout] has been called. |
| double get width; |
| |
| /// The amount of vertical space this paragraph occupies. |
| /// |
| /// Valid only after [layout] has been called. |
| double get height; |
| |
| /// The distance from the left edge of the leftmost glyph to the right edge of |
| /// the rightmost glyph in the paragraph. |
| /// |
| /// Valid only after [layout] has been called. |
| double get longestLine; |
| |
| /// {@template dart.ui.paragraph.minIntrinsicWidth} |
| /// The minimum width that this paragraph could be without failing to paint |
| /// its contents within itself. |
| /// {@endtemplate} |
| /// |
| /// Valid only after [layout] has been called. |
| double get minIntrinsicWidth; |
| |
| /// {@template dart.ui.paragraph.maxIntrinsicWidth} |
| /// Returns the smallest width beyond which increasing the width never |
| /// decreases the height. |
| /// {@endtemplate} |
| /// |
| /// Valid only after [layout] has been called. |
| double get maxIntrinsicWidth; |
| |
| /// {@template dart.ui.paragraph.alphabeticBaseline} |
| /// The distance from the top of the paragraph to the alphabetic |
| /// baseline of the first line, in logical pixels. |
| /// {@endtemplate} |
| /// |
| /// Valid only after [layout] has been called. |
| double get alphabeticBaseline; |
| |
| /// {@template dart.ui.paragraph.ideographicBaseline} |
| /// The distance from the top of the paragraph to the ideographic |
| /// baseline of the first line, in logical pixels. |
| /// {@endtemplate} |
| /// |
| /// Valid only after [layout] has been called. |
| double get ideographicBaseline; |
| |
| /// True if there is more vertical content, but the text was truncated, either |
| /// because we reached `maxLines` lines of text or because the `maxLines` was |
| /// null, `ellipsis` was not null, and one of the lines exceeded the width |
| /// constraint. |
| /// |
| /// See the discussion of the `maxLines` and `ellipsis` arguments at [new |
| /// ParagraphStyle]. |
| bool get didExceedMaxLines; |
| |
| /// Computes the size and position of each glyph in the paragraph. |
| /// |
| /// The [ParagraphConstraints] control how wide the text is allowed to be. |
| void layout(ParagraphConstraints constraints); |
| |
| /// Returns a list of text boxes that enclose the given text range. |
| /// |
| /// The [boxHeightStyle] and [boxWidthStyle] parameters allow customization |
| /// of how the boxes are bound vertically and horizontally. Both style |
| /// parameters default to the tight option, which will provide close-fitting |
| /// boxes and will not account for any line spacing. |
| /// |
| /// The [boxHeightStyle] and [boxWidthStyle] parameters must not be null. |
| /// |
| /// See [BoxHeightStyle] and [BoxWidthStyle] for full descriptions of each option. |
| List<TextBox> getBoxesForRange(int start, int end, |
| {BoxHeightStyle boxHeightStyle = BoxHeightStyle.tight, |
| BoxWidthStyle boxWidthStyle = BoxWidthStyle.tight}); |
| |
| /// Returns the text position closest to the given offset. |
| /// |
| /// It does so by performing a binary search to find where the tap occurred |
| /// within the text. |
| TextPosition getPositionForOffset(Offset offset); |
| |
| /// Returns the [TextRange] of the word at the given [TextPosition]. |
| /// |
| /// Characters not part of a word, such as spaces, symbols, and punctuation, |
| /// have word breaks on both sides. In such cases, this method will return |
| /// [offset, offset+1]. Word boundaries are defined more precisely in Unicode |
| /// Standard Annex #29 http://www.unicode.org/reports/tr29/#Word_Boundaries |
| TextRange getWordBoundary(TextPosition position); |
| |
| /// Returns the [TextRange] of the line at the given [TextPosition]. |
| /// |
| /// The newline (if any) is returned as part of the range. |
| /// |
| /// Not valid until after layout. |
| /// |
| /// This can potentially be expensive, since it needs to compute the line |
| /// metrics, so use it sparingly. |
| TextRange getLineBoundary(TextPosition position); |
| |
| /// Returns a list of text boxes that enclose all placeholders in the paragraph. |
| /// |
| /// The order of the boxes are in the same order as passed in through [addPlaceholder]. |
| /// |
| /// Coordinates of the [TextBox] are relative to the upper-left corner of the paragraph, |
| /// where positive y values indicate down. |
| List<TextBox> getBoxesForPlaceholders(); |
| |
| /// Returns the full list of [LineMetrics] that describe in detail the various |
| /// metrics of each laid out line. |
| /// |
| /// Not valid until after layout. |
| /// |
| /// This can potentially return a large amount of data, so it is not recommended |
| /// to repeatedly call this. Instead, cache the results. |
| List<LineMetrics> computeLineMetrics(); |
| } |
| |
| /// Builds a [Paragraph] containing text with the given styling information. |
| /// |
| /// To set the paragraph's alignment, truncation, and ellipsising behavior, pass |
| /// an appropriately-configured [ParagraphStyle] object to the [new |
| /// ParagraphBuilder] constructor. |
| /// |
| /// Then, call combinations of [pushStyle], [addText], and [pop] to add styled |
| /// text to the object. |
| /// |
| /// Finally, call [build] to obtain the constructed [Paragraph] object. After |
| /// this point, the builder is no longer usable. |
| /// |
| /// After constructing a [Paragraph], call [Paragraph.layout] on it and then |
| /// paint it with [Canvas.drawParagraph]. |
| abstract class ParagraphBuilder { |
| /// Creates a [ParagraphBuilder] object, which is used to create a |
| /// [Paragraph]. |
| factory ParagraphBuilder(ParagraphStyle style) { |
| if (engine.experimentalUseSkia) { |
| return engine.SkParagraphBuilder(style); |
| } else { |
| return engine.EngineParagraphBuilder(style); |
| } |
| } |
| |
| /// Applies the given style to the added text until [pop] is called. |
| /// |
| /// See [pop] for details. |
| void pushStyle(TextStyle style); |
| |
| /// Ends the effect of the most recent call to [pushStyle]. |
| /// |
| /// Internally, the paragraph builder maintains a stack of text styles. Text |
| /// added to the paragraph is affected by all the styles in the stack. Calling |
| /// [pop] removes the topmost style in the stack, leaving the remaining styles |
| /// in effect. |
| void pop(); |
| |
| /// Adds the given text to the paragraph. |
| /// |
| /// The text will be styled according to the current stack of text styles. |
| void addText(String text); |
| |
| /// Applies the given paragraph style and returns a [Paragraph] containing the |
| /// added text and associated styling. |
| /// |
| /// After calling this function, the paragraph builder object is invalid and |
| /// cannot be used further. |
| Paragraph build(); |
| |
| /// The number of placeholders currently in the paragraph. |
| int get placeholderCount; |
| |
| /// The scales of the placeholders in the paragraph. |
| List<double> get placeholderScales; |
| |
| /// Adds an inline placeholder space to the paragraph. |
| /// |
| /// The paragraph will contain a rectangular space with no text of the dimensions |
| /// specified. |
| /// |
| /// The `width` and `height` parameters specify the size of the placeholder rectangle. |
| /// |
| /// The `alignment` parameter specifies how the placeholder rectangle will be vertically |
| /// aligned with the surrounding text. When [PlaceholderAlignment.baseline], |
| /// [PlaceholderAlignment.aboveBaseline], and [PlaceholderAlignment.belowBaseline] |
| /// alignment modes are used, the baseline needs to be set with the `baseline`. |
| /// When using [PlaceholderAlignment.baseline], `baselineOffset` indicates the distance |
| /// of the baseline down from the top of of the rectangle. The default `baselineOffset` |
| /// is the `height`. |
| /// |
| /// Examples: |
| /// |
| /// * For a 30x50 placeholder with the bottom edge aligned with the bottom of the text, use: |
| /// `addPlaceholder(30, 50, PlaceholderAlignment.bottom);` |
| /// * For a 30x50 placeholder that is vertically centered around the text, use: |
| /// `addPlaceholder(30, 50, PlaceholderAlignment.middle);`. |
| /// * For a 30x50 placeholder that sits completely on top of the alphabetic baseline, use: |
| /// `addPlaceholder(30, 50, PlaceholderAlignment.aboveBaseline, baseline: TextBaseline.alphabetic)`. |
| /// * For a 30x50 placeholder with 40 pixels above and 10 pixels below the alphabetic baseline, use: |
| /// `addPlaceholder(30, 50, PlaceholderAlignment.baseline, baseline: TextBaseline.alphabetic, baselineOffset: 40)`. |
| /// |
| /// Lines are permitted to break around each placeholder. |
| /// |
| /// Decorations will be drawn based on the font defined in the most recently |
| /// pushed [TextStyle]. The decorations are drawn as if unicode text were present |
| /// in the placeholder space, and will draw the same regardless of the height and |
| /// alignment of the placeholder. To hide or manually adjust decorations to fit, |
| /// a text style with the desired decoration behavior should be pushed before |
| /// adding a placeholder. |
| /// |
| /// Any decorations drawn through a placeholder will exist on the same canvas/layer |
| /// as the text. This means any content drawn on top of the space reserved by |
| /// the placeholder will be drawn over the decoration, possibly obscuring the |
| /// decoration. |
| /// |
| /// Placeholders are represented by a unicode 0xFFFC "object replacement character" |
| /// in the text buffer. For each placeholder, one object replacement character is |
| /// added on to the text buffer. |
| void addPlaceholder( |
| double width, |
| double height, |
| PlaceholderAlignment alignment, { |
| double scale, |
| double baselineOffset, |
| TextBaseline baseline, |
| }); |
| } |
| |
| /// Loads a font from a buffer and makes it available for rendering text. |
| /// |
| /// * `list`: A list of bytes containing the font file. |
| /// * `fontFamily`: The family name used to identify the font in text styles. |
| /// If this is not provided, then the family name will be extracted from the font file. |
| Future<void> loadFontFromList(Uint8List list, {String fontFamily}) { |
| if (engine.experimentalUseSkia) { |
| return engine.skiaFontCollection.loadFontFromList(list, fontFamily: fontFamily).then( |
| (_) => engine.sendFontChangeMessage() |
| ); |
| } else { |
| return _fontCollection.loadFontFromList(list, fontFamily: fontFamily).then( |
| (_) => engine.sendFontChangeMessage() |
| ); |
| } |
| } |