示例#1
0
 public TextCharacters(ReadOnlySlice <char> text, int offsetToFirstCharacter, int length,
                       TextRunProperties properties)
 {
     Text             = text.Skip(offsetToFirstCharacter).Take(length);
     TextSourceLength = length;
     Properties       = properties;
 }
示例#2
0
        private static IType MakeRecursiveGenericTypeImpl(
            IType type,
            IReadOnlyList <IType> recursiveGenericArguments,
            ref int offset)
        {
            var parentType = type.Parent.TypeOrNull;

            if (parentType != null)
            {
                parentType = MakeRecursiveGenericTypeImpl(
                    parentType,
                    recursiveGenericArguments,
                    ref offset);

                if (parentType is TypeSpecialization)
                {
                    type = IndirectTypeSpecialization.Create(type, (TypeSpecialization)parentType);
                }
            }

            if (offset >= recursiveGenericArguments.Count)
            {
                return(type);
            }
            else
            {
                var parameterCount = type.GenericParameters.Count;
                var slice          = new ReadOnlySlice <IType>(
                    recursiveGenericArguments,
                    offset,
                    parameterCount);
                offset += parameterCount;
                return(type.MakeGenericType(slice.ToArray()));
            }
        }
示例#3
0
        /// <summary>
        /// Initializes a new instance of the <see cref="TextLayout" /> class.
        /// </summary>
        /// <param name="text">The text.</param>
        /// <param name="typeface">The typeface.</param>
        /// <param name="fontSize">Size of the font.</param>
        /// <param name="foreground">The foreground.</param>
        /// <param name="textAlignment">The text alignment.</param>
        /// <param name="textWrapping">The text wrapping.</param>
        /// <param name="textTrimming">The text trimming.</param>
        /// <param name="textDecorations">The text decorations.</param>
        /// <param name="maxWidth">The maximum width.</param>
        /// <param name="maxHeight">The maximum height.</param>
        /// <param name="lineHeight">The height of each line of text.</param>
        /// <param name="maxLines">The maximum number of text lines.</param>
        /// <param name="textStyleOverrides">The text style overrides.</param>
        public TextLayout(
            string text,
            Typeface typeface,
            double fontSize,
            IBrush foreground,
            TextAlignment textAlignment = TextAlignment.Left,
            TextWrapping textWrapping   = TextWrapping.NoWrap,
            TextTrimming textTrimming   = TextTrimming.None,
            TextDecorationCollection textDecorations = null,
            double maxWidth   = double.PositiveInfinity,
            double maxHeight  = double.PositiveInfinity,
            double lineHeight = double.NaN,
            int maxLines      = 0,
            IReadOnlyList <ValueSpan <TextRunProperties> > textStyleOverrides = null)
        {
            _text = string.IsNullOrEmpty(text) ?
                    new ReadOnlySlice <char>() :
                    new ReadOnlySlice <char>(text.AsMemory());

            _paragraphProperties =
                CreateTextParagraphProperties(typeface, fontSize, foreground, textAlignment, textWrapping, textTrimming,
                                              textDecorations, lineHeight);

            _textStyleOverrides = textStyleOverrides;

            LineHeight = lineHeight;

            MaxWidth = maxWidth;

            MaxHeight = maxHeight;

            MaxLines = maxLines;

            UpdateLayout();
        }
示例#4
0
        /// <summary>
        ///     Initializes a new instance of the <see cref="GlyphRun"/> class by specifying properties of the class.
        /// </summary>
        /// <param name="glyphTypeface">The glyph typeface.</param>
        /// <param name="fontRenderingEmSize">The rendering em size.</param>
        /// <param name="glyphIndices">The glyph indices.</param>
        /// <param name="glyphAdvances">The glyph advances.</param>
        /// <param name="glyphOffsets">The glyph offsets.</param>
        /// <param name="characters">The characters.</param>
        /// <param name="glyphClusters">The glyph clusters.</param>
        /// <param name="biDiLevel">The bidi level.</param>
        public GlyphRun(
            GlyphTypeface glyphTypeface,
            double fontRenderingEmSize,
            ReadOnlySlice <char> characters,
            IReadOnlyList <ushort> glyphIndices,
            IReadOnlyList <double>?glyphAdvances = null,
            IReadOnlyList <Vector>?glyphOffsets  = null,
            IReadOnlyList <int>?glyphClusters    = null,
            int biDiLevel = 0)
        {
            _glyphTypeface = glyphTypeface;

            FontRenderingEmSize = fontRenderingEmSize;

            Characters = characters;

            _glyphIndices = glyphIndices;

            GlyphAdvances = glyphAdvances;

            GlyphOffsets = glyphOffsets;

            GlyphClusters = glyphClusters;

            BiDiLevel = biDiLevel;
        }
示例#5
0
 public FormattedTextSource(ReadOnlySlice <char> text, TextStyle defaultStyle,
                            IReadOnlyList <TextStyleRun> textStyleOverrides)
 {
     _text               = text;
     _defaultStyle       = defaultStyle;
     _textStyleOverrides = textStyleOverrides;
 }
 public ShapeableTextCharacters(ReadOnlySlice <char> text, TextRunProperties properties, sbyte biDiLevel)
 {
     TextSourceLength = text.Length;
     Text             = text;
     Properties       = properties;
     BidiLevel        = biDiLevel;
 }
示例#7
0
 public FormattedTextSource(ReadOnlySlice <char> text, TextRunProperties defaultProperties,
                            IReadOnlyList <ValueSpan <TextRunProperties> > textModifier)
 {
     _text = text;
     _defaultProperties = defaultProperties;
     _textModifier      = textModifier;
 }
示例#8
0
        internal static IReadOnlyList <string> CheckArgumentTypes(
            ReadOnlySlice <ValueTag> arguments,
            IReadOnlyList <Parameter> parameters,
            MethodBody body)
        {
            var errors = new List <string>();

            int paramCount = parameters.Count;

            for (int i = 0; i < paramCount; i++)
            {
                var paramType = parameters[i].Type;
                var argType   = body.Implementation.GetValueType(arguments[i]);

                if (!paramType.Equals(argType))
                {
                    errors.Add(
                        string.Format(
                            "Argument of type '{0}' was provided where an " +
                            "argument of type '{1}' was expected.",
                            paramType.FullName,
                            argType.FullName));
                }
            }

            return(errors);
        }
示例#9
0
        /// <summary>
        ///     Initializes a new instance of the <see cref="GlyphRun"/> class by specifying properties of the class.
        /// </summary>
        /// <param name="glyphTypeface">The glyph typeface.</param>
        /// <param name="fontRenderingEmSize">The rendering em size.</param>
        /// <param name="glyphIndices">The glyph indices.</param>
        /// <param name="glyphAdvances">The glyph advances.</param>
        /// <param name="glyphOffsets">The glyph offsets.</param>
        /// <param name="characters">The characters.</param>
        /// <param name="glyphClusters">The glyph clusters.</param>
        /// <param name="biDiLevel">The bidi level.</param>
        /// <param name="bounds">The bound.</param>
        public GlyphRun(
            GlyphTypeface glyphTypeface,
            double fontRenderingEmSize,
            ReadOnlySlice <ushort> glyphIndices,
            ReadOnlySlice <double> glyphAdvances = default,
            ReadOnlySlice <Vector> glyphOffsets  = default,
            ReadOnlySlice <char> characters      = default,
            ReadOnlySlice <ushort> glyphClusters = default,
            int biDiLevel = 0,
            Rect?bounds   = null)
        {
            GlyphTypeface = glyphTypeface;

            FontRenderingEmSize = fontRenderingEmSize;

            GlyphIndices = glyphIndices;

            GlyphAdvances = glyphAdvances;

            GlyphOffsets = glyphOffsets;

            Characters = characters;

            GlyphClusters = glyphClusters;

            BiDiLevel = biDiLevel;

            Initialize(bounds);
        }
示例#10
0
        public ShapedBuffer ShapeText(ReadOnlySlice <char> text, TextShaperOptions options)
        {
            var typeface            = options.Typeface;
            var fontRenderingEmSize = options.FontRenderingEmSize;
            var bidiLevel           = options.BidLevel;
            var culture             = options.Culture;

            using (var buffer = new Buffer())
            {
                buffer.AddUtf16(text.Buffer.Span, text.Start, text.Length);

                MergeBreakPair(buffer);

                buffer.GuessSegmentProperties();

                buffer.Direction = (bidiLevel & 1) == 0 ? Direction.LeftToRight : Direction.RightToLeft;

                buffer.Language = new Language(culture ?? CultureInfo.CurrentCulture);

                var font = ((HarfBuzzGlyphTypefaceImpl)typeface.PlatformImpl).Font;

                font.Shape(buffer);

                if (buffer.Direction == Direction.RightToLeft)
                {
                    buffer.Reverse();
                }

                font.GetScale(out var scaleX, out _);

                var textScale = fontRenderingEmSize / scaleX;

                var bufferLength = buffer.Length;

                var shapedBuffer = new ShapedBuffer(text, bufferLength, typeface, fontRenderingEmSize, bidiLevel);

                var glyphInfos = buffer.GetGlyphInfoSpan();

                var glyphPositions = buffer.GetGlyphPositionSpan();

                for (var i = 0; i < bufferLength; i++)
                {
                    var sourceInfo = glyphInfos[i];

                    var glyphIndex = (ushort)sourceInfo.Codepoint;

                    var glyphCluster = (int)sourceInfo.Cluster;

                    var glyphAdvance = GetGlyphAdvance(glyphPositions, i, textScale);

                    var glyphOffset = GetGlyphOffset(glyphPositions, i, textScale);

                    var targetInfo = new Media.TextFormatting.GlyphInfo(glyphIndex, glyphCluster, glyphAdvance, glyphOffset);

                    shapedBuffer[i] = targetInfo;
                }

                return(shapedBuffer);
            }
        }
示例#11
0
        public GlyphRun ShapeText(ReadOnlySlice <char> text, TextFormat textFormat)
        {
            var glyphTypeface = textFormat.Typeface.GlyphTypeface;
            var glyphIndices  = new ushort[text.Length];
            var height        = textFormat.FontMetrics.LineHeight;
            var width         = 0.0;

            for (var i = 0; i < text.Length;)
            {
                var index = i;

                var codepoint = Codepoint.ReadAt(text, i, out var count);

                i += count;

                var glyph = glyphTypeface.GetGlyph(codepoint);

                glyphIndices[index] = glyph;

                width += glyphTypeface.GetGlyphAdvance(glyph);
            }

            return(new GlyphRun(glyphTypeface, textFormat.FontRenderingEmSize, glyphIndices, characters: text,
                                bounds: new Rect(0, 0, width, height)));
        }
示例#12
0
 internal ShapedBuffer(ReadOnlySlice <char> text, ArraySlice <GlyphInfo> glyphInfos, GlyphTypeface glyphTypeface, double fontRenderingEmSize, sbyte bidiLevel)
 {
     Text                = text;
     GlyphInfos          = glyphInfos;
     GlyphTypeface       = glyphTypeface;
     FontRenderingEmSize = fontRenderingEmSize;
     BidiLevel           = bidiLevel;
 }
 internal Processor(ReadOnlySlice <char> buffer)
 {
     _buffer = buffer;
     _codeUnitLengthOfCurrentScalar = 0;
     CurrentCodepoint      = Codepoint.ReplacementCodepoint;
     CurrentType           = GraphemeBreakClass.Other;
     CurrentCodeUnitOffset = 0;
 }
示例#14
0
        public ShapedBuffer ShapeText(ReadOnlySlice <char> text, TextShaperOptions options)
        {
            var typeface            = options.Typeface;
            var fontRenderingEmSize = options.FontRenderingEmSize;
            var bidiLevel           = options.BidiLevel;

            return(new ShapedBuffer(text, text.Length, typeface, fontRenderingEmSize, bidiLevel));
        }
            public FormattableTextSource(string text, TextStyle defaultStyle, ReadOnlySlice <TextStyleRun> textStyleRuns)
            {
                _text = text.AsMemory();

                _defaultStyle = defaultStyle;

                _textStyleRuns = textStyleRuns;
            }
示例#16
0
        public GlyphRun ShapeText(ReadOnlySlice <char> text, Typeface typeface, double fontRenderingEmSize,
                                  CultureInfo culture)
        {
            using (var buffer = new Buffer())
            {
                FillBuffer(buffer, text);

                buffer.Language = new Language(culture ?? CultureInfo.CurrentCulture);

                buffer.GuessSegmentProperties();

                var glyphTypeface = typeface.GlyphTypeface;

                var font = ((HarfBuzzGlyphTypefaceImpl)glyphTypeface.PlatformImpl).Font;

                font.Shape(buffer);

                font.GetScale(out var scaleX, out _);

                var textScale = fontRenderingEmSize / scaleX;

                var bufferLength = buffer.Length;

                var glyphInfos = buffer.GetGlyphInfoSpan();

                var glyphPositions = buffer.GetGlyphPositionSpan();

                var glyphIndices = new ushort[bufferLength];

                var clusters = new ushort[bufferLength];

                double[] glyphAdvances = null;

                Vector[] glyphOffsets = null;

                for (var i = 0; i < bufferLength; i++)
                {
                    glyphIndices[i] = (ushort)glyphInfos[i].Codepoint;

                    clusters[i] = (ushort)glyphInfos[i].Cluster;

                    if (!glyphTypeface.IsFixedPitch)
                    {
                        SetAdvance(glyphPositions, i, textScale, ref glyphAdvances);
                    }

                    SetOffset(glyphPositions, i, textScale, ref glyphOffsets);
                }

                return(new GlyphRun(glyphTypeface, fontRenderingEmSize,
                                    new ReadOnlySlice <ushort>(glyphIndices),
                                    new ReadOnlySlice <double>(glyphAdvances),
                                    new ReadOnlySlice <Vector>(glyphOffsets),
                                    text,
                                    new ReadOnlySlice <ushort>(clusters),
                                    buffer.Direction == Direction.LeftToRight ? 0 : 1));
            }
        }
示例#17
0
 public LineBreakEnumerator(ReadOnlySlice <char> text)
 {
     _text      = text;
     _pos       = 0;
     _lastPos   = 0;
     _curClass  = null;
     _nextClass = null;
     Current    = default;
 }
示例#18
0
        /// <summary>
        /// Reads the <see cref="Codepoint"/> at specified position.
        /// </summary>
        /// <param name="text">The buffer to read from.</param>
        /// <param name="index">The index to read at.</param>
        /// <param name="count">The count of character that were read.</param>
        /// <returns></returns>
        public static Codepoint ReadAt(ReadOnlySlice <char> text, int index, out int count)
        {
            count = 1;

            if (index > text.End)
            {
                return(ReplacementCodepoint);
            }

            var code = text[index];

            ushort hi, low;

            //# High surrogate
            if (0xD800 <= code && code <= 0xDBFF)
            {
                hi = code;

                if (index + 1 == text.Length)
                {
                    return(ReplacementCodepoint);
                }

                low = text[index + 1];

                if (0xDC00 <= low && low <= 0xDFFF)
                {
                    count = 2;
                    return(new Codepoint((hi - 0xD800) * 0x400 + (low - 0xDC00) + 0x10000));
                }

                return(ReplacementCodepoint);
            }

            //# Low surrogate
            if (0xDC00 <= code && code <= 0xDFFF)
            {
                if (index == 0)
                {
                    return(ReplacementCodepoint);
                }

                hi = text[index - 1];

                low = code;

                if (0xD800 <= hi && hi <= 0xDBFF)
                {
                    count = 2;
                    return(new Codepoint((hi - 0xD800) * 0x400 + (low - 0xDC00) + 0x10000));
                }

                return(ReplacementCodepoint);
            }

            return(new Codepoint(code));
        }
示例#19
0
 /// <summary>
 /// Construct a text trailing word ellipsis collapsing properties.
 /// </summary>
 /// <param name="ellipsis">Text used as collapsing symbol.</param>
 /// <param name="width">width in which collapsing is constrained to.</param>
 /// <param name="textRunProperties">text run properties of ellipsis symbol.</param>
 public TextTrailingWordEllipsis(
     ReadOnlySlice <char> ellipsis,
     double width,
     TextRunProperties textRunProperties
     )
 {
     Width  = width;
     Symbol = new TextCharacters(ellipsis, textRunProperties);
 }
示例#20
0
 public GlyphRun ShapeText(ReadOnlySlice <char> text, Typeface typeface, double fontRenderingEmSize, CultureInfo culture)
 {
     return(new GlyphRun(new GlyphTypeface(typeface), 10,
                         new ReadOnlySlice <ushort>(new ushort[] { 1, 2, 3 }),
                         new ReadOnlySlice <double>(new double[] { 1, 2, 3 }),
                         new ReadOnlySlice <Vector>(new Vector[] { new Vector(1, 1), new Vector(2, 2), new Vector(3, 3) }),
                         text,
                         new ReadOnlySlice <ushort>(new ushort[] { 1, 2, 3 })));
 }
        public FormattableTextSource(string text, TextRunProperties defaultStyle,
                                     ReadOnlySlice <ValueSpan <TextRunProperties> > styleSpans)
        {
            _text = text.AsMemory();

            _defaultStyle = defaultStyle;

            _styleSpans = styleSpans;
        }
示例#22
0
        /// <summary>
        /// Tries to get a shapeable length that is supported by the specified typeface.
        /// </summary>
        /// <param name="text">The text.</param>
        /// <param name="typeface">The typeface that is used to find matching characters.</param>
        /// <param name="defaultTypeface"></param>
        /// <param name="length">The shapeable length.</param>
        /// <param name="script"></param>
        /// <returns></returns>
        protected static bool TryGetShapeableLength(
            ReadOnlySlice <char> text,
            Typeface typeface,
            Typeface?defaultTypeface,
            out int length,
            out Script script)
        {
            length = 0;
            script = Script.Unknown;

            if (text.Length == 0)
            {
                return(false);
            }

            var font        = typeface.GlyphTypeface;
            var defaultFont = defaultTypeface?.GlyphTypeface;

            var enumerator = new GraphemeEnumerator(text);

            while (enumerator.MoveNext())
            {
                var currentGrapheme = enumerator.Current;

                var currentScript = currentGrapheme.FirstCodepoint.Script;

                if (currentScript != Script.Common && defaultFont != null && defaultFont.TryGetGlyph(currentGrapheme.FirstCodepoint, out _))
                {
                    break;
                }

                //Stop at the first missing glyph
                if (!currentGrapheme.FirstCodepoint.IsBreakChar && !font.TryGetGlyph(currentGrapheme.FirstCodepoint, out _))
                {
                    break;
                }

                if (currentScript != script)
                {
                    if (script is Script.Unknown || currentScript != Script.Common &&
                        script is Script.Common or Script.Inherited)
                    {
                        script = currentScript;
                    }
                    else
                    {
                        if (currentScript != Script.Inherited && currentScript != Script.Common)
                        {
                            break;
                        }
                    }
                }

                length += currentGrapheme.Text.Length;
            }
        public void Should_Skip()
        {
            var buffer = new[] { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };

            var slice = new ReadOnlySlice <int>(buffer);

            var skipped = slice.Skip(2);

            var expected = buffer.Skip(2);

            Assert.Equal(expected, skipped);
        }
        public void Should_Take()
        {
            var buffer = new[] { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };

            var slice = new ReadOnlySlice <int>(buffer);

            var taken = slice.Take(8);

            var expected = buffer.Take(8);

            Assert.Equal(expected, taken);
        }
示例#25
0
        private static GlyphRun CreateGlyphRun(double[] glyphAdvances, ushort[] glyphClusters, int bidiLevel = 0)
        {
            var count        = glyphAdvances.Length;
            var glyphIndices = new ushort[count];

            var start = bidiLevel == 0 ? glyphClusters[0] : glyphClusters[glyphClusters.Length - 1];

            var characters = new ReadOnlySlice <char>(new char[count], start, count);

            return(new GlyphRun(new GlyphTypeface(new MockGlyphTypeface()), 10, glyphIndices, glyphAdvances,
                                glyphClusters: glyphClusters, characters: characters, biDiLevel: bidiLevel));
        }
示例#26
0
        /// <summary>
        /// Creates a shapeable text run with unique properties.
        /// </summary>
        /// <param name="text">The text to create text runs from.</param>
        /// <param name="defaultProperties">The default text run properties.</param>
        /// <returns>A list of shapeable text runs.</returns>
        private ShapeableTextCharacters CreateShapeableRun(ReadOnlySlice <char> text, TextRunProperties defaultProperties)
        {
            var defaultTypeface = defaultProperties.Typeface;

            var currentTypeface = defaultTypeface;

            if (TryGetRunProperties(text, currentTypeface, defaultTypeface, out var count))
            {
                return(new ShapeableTextCharacters(text.Take(count),
                                                   new GenericTextRunProperties(currentTypeface, defaultProperties.FontRenderingEmSize,
                                                                                defaultProperties.TextDecorations, defaultProperties.ForegroundBrush)));
            }

            var codepoint = Codepoint.ReadAt(text, count, out _);

            //ToDo: Fix FontFamily fallback
            var matchFound =
                FontManager.Current.TryMatchCharacter(codepoint, defaultTypeface.Style, defaultTypeface.Weight,
                                                      defaultTypeface.FontFamily, defaultProperties.CultureInfo, out currentTypeface);

            if (matchFound && TryGetRunProperties(text, currentTypeface, defaultTypeface, out count))
            {
                //Fallback found
                return(new ShapeableTextCharacters(text.Take(count),
                                                   new GenericTextRunProperties(currentTypeface, defaultProperties.FontRenderingEmSize,
                                                                                defaultProperties.TextDecorations, defaultProperties.ForegroundBrush)));
            }

            // no fallback found
            currentTypeface = defaultTypeface;

            var glyphTypeface = currentTypeface.GlyphTypeface;

            var enumerator = new GraphemeEnumerator(text);

            while (enumerator.MoveNext())
            {
                var grapheme = enumerator.Current;

                if (!grapheme.FirstCodepoint.IsWhiteSpace && glyphTypeface.TryGetGlyph(grapheme.FirstCodepoint, out _))
                {
                    break;
                }

                count += grapheme.Text.Length;
            }

            return(new ShapeableTextCharacters(text.Take(count),
                                               new GenericTextRunProperties(currentTypeface, defaultProperties.FontRenderingEmSize,
                                                                            defaultProperties.TextDecorations, defaultProperties.ForegroundBrush)));
        }
        public TextRun GetTextRun(int textSourceIndex)
        {
            if (_styleSpans.IsEmpty)
            {
                return(new TextEndOfParagraph());
            }

            var currentSpan = _styleSpans[0];

            _styleSpans = _styleSpans.Skip(1);

            return(new TextCharacters(_text.AsSlice(currentSpan.Start, currentSpan.Length),
                                      _defaultStyle));
        }
            public TextRun GetTextRun(int textSourceIndex)
            {
                if (_textStyleRuns.IsEmpty)
                {
                    return(new TextEndOfParagraph());
                }

                var styleRun = _textStyleRuns[0];

                _textStyleRuns = _textStyleRuns.Skip(1);

                return(new TextCharacters(_text.AsSlice(styleRun.TextPointer.Start, styleRun.TextPointer.Length),
                                          _defaultStyle));
            }
示例#29
0
        /// <summary>
        /// Creates a text style run with unique properties.
        /// </summary>
        /// <param name="text">The text to create text runs from.</param>
        /// <param name="defaultStyle"></param>
        /// <returns>A list of text runs.</returns>
        protected TextStyleRun CreateShapableTextStyleRun(ReadOnlySlice <char> text, TextStyle defaultStyle)
        {
            var defaultTypeface = defaultStyle.TextFormat.Typeface;

            var currentTypeface = defaultTypeface;

            if (TryGetRunProperties(text, currentTypeface, defaultTypeface, out var count))
            {
                return(new TextStyleRun(new TextPointer(text.Start, count), new TextStyle(currentTypeface,
                                                                                          defaultStyle.TextFormat.FontRenderingEmSize,
                                                                                          defaultStyle.Foreground, defaultStyle.TextDecorations)));
            }

            var codepoint = Codepoint.ReadAt(text, count, out _);

            //ToDo: Fix FontFamily fallback
            currentTypeface =
                FontManager.Current.MatchCharacter(codepoint, defaultTypeface.Weight, defaultTypeface.Style);

            if (currentTypeface != null && TryGetRunProperties(text, currentTypeface, defaultTypeface, out count))
            {
                //Fallback found
                return(new TextStyleRun(new TextPointer(text.Start, count), new TextStyle(currentTypeface,
                                                                                          defaultStyle.TextFormat.FontRenderingEmSize,
                                                                                          defaultStyle.Foreground, defaultStyle.TextDecorations)));
            }

            // no fallback found
            currentTypeface = defaultTypeface;

            var glyphTypeface = currentTypeface.GlyphTypeface;

            var enumerator = new GraphemeEnumerator(text);

            while (enumerator.MoveNext())
            {
                var grapheme = enumerator.Current;

                if (!grapheme.FirstCodepoint.IsWhiteSpace && glyphTypeface.TryGetGlyph(grapheme.FirstCodepoint, out _))
                {
                    break;
                }

                count += grapheme.Text.Length;
            }

            return(new TextStyleRun(new TextPointer(text.Start, count),
                                    new TextStyle(currentTypeface, defaultStyle.TextFormat.FontRenderingEmSize,
                                                  defaultStyle.Foreground, defaultStyle.TextDecorations)));
        }
示例#30
0
        /// <summary>
        /// Moves to the next <see cref="Codepoint"/>.
        /// </summary>
        /// <returns></returns>
        public bool MoveNext()
        {
            if (_text.IsEmpty)
            {
                Current = Codepoint.ReplacementCodepoint;

                return(false);
            }

            Current = Codepoint.ReadAt(_text, 0, out var count);

            _text = _text.Skip(count);

            return(true);
        }