示例#1
0
        private unsafe void CreateShapedChar(hb_glyph_info_t *info, hb_glyph_position_t *position, Int32 cluster, out ShapedChar result)
        {
            var cGlyphIndex = (Int32)info->codepoint;
            var cOffsetX    = (Int16)Math.Round(position->x_offset / 64f, MidpointRounding.AwayFromZero);
            var cOffsetY    = (Int16)Math.Round(position->y_offset / 64f, MidpointRounding.AwayFromZero);
            var cAdvance    = (Int16)Math.Round((position->x_advance == 0 ? position->y_advance : position->x_advance) / 64f, MidpointRounding.AwayFromZero);

            result = new ShapedChar(cGlyphIndex, cluster, cOffsetX, cOffsetY, cAdvance);
        }
示例#2
0
        public void ShapedString_ProvidesCorrectShapingData_InEnglish()
        {
            var sstr = default(ShapedString);

            GivenAnUltravioletApplicationWithNoWindow()
            .WithPlugin(new FreeTypeFontPlugin())
            .WithContent(content =>
            {
                var font = content.Load <UltravioletFont>("Fonts/FiraSans");
                using (var textShaper = new HarfBuzzTextShaper(content.Ultraviolet))
                {
                    textShaper.SetUnicodeProperties(TextDirection.LeftToRight, TextScript.Latin, "en");
                    textShaper.Append("Hello, world!");

                    sstr = textShaper.CreateShapedString(font.Regular);
                }
            })
            .RunForOneFrame();

            var chars = new ShapedChar[sstr.Length];

            sstr.CopyTo(0, chars, 0, sstr.Length);

            var glyphIndices = chars.Select(x => x.GlyphIndex).ToArray();

            TheResultingCollection(glyphIndices)
            .ShouldBeExactly(111, 412, 514, 514, 555, 2122, 3, 696, 555, 609, 514, 393, 2125);

            var sourceIndices = chars.Select(x => x.SourceIndex).ToArray();

            TheResultingCollection(sourceIndices)
            .ShouldBeExactly(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12);

            var advances = chars.Select(x => x.Advance).ToArray();

            TheResultingCollection(advances)
            .ShouldBeExactly(11, 9, 5, 5, 9, 4, 4, 11, 9, 6, 5, 10, 4);

            var offsets_x = chars.Select(x => x.OffsetX).ToArray();

            TheResultingCollection(offsets_x)
            .ShouldContainTheSpecifiedNumberOfItems(13)
            .ShouldContainItemsSatisfyingTheCondition(x => x == 0);

            var offsets_y = chars.Select(x => x.OffsetY).ToArray();

            TheResultingCollection(offsets_y)
            .ShouldContainTheSpecifiedNumberOfItems(13)
            .ShouldContainItemsSatisfyingTheCondition(x => x == 0);
        }
示例#3
0
        public void ShapedString_ProvidesCorrectShapingData_InArabic()
        {
            var sstr = default(ShapedString);

            GivenAnUltravioletApplicationWithNoWindow()
            .WithPlugin(new FreeTypeFontPlugin())
            .WithContent(content =>
            {
                var font = content.Load <UltravioletFont>("Fonts/FiraGO-Regular");
                using (var textShaper = new HarfBuzzTextShaper(content.Ultraviolet))
                {
                    textShaper.SetUnicodeProperties(TextDirection.RightToLeft, TextScript.Arabic, "ar");
                    textShaper.Append("مرحبا بالعالم");

                    sstr = textShaper.CreateShapedString(font.Regular);
                }
            })
            .RunForOneFrame();

            var chars = new ShapedChar[sstr.Length];

            sstr.CopyTo(0, chars, 0, sstr.Length);

            var glyphIndices = chars.Select(x => x.GlyphIndex).ToArray();

            TheResultingCollection(glyphIndices)
            .ShouldBeExactly(2531, 2513, 2150, 2392, 2513, 2150, 2173, 3, 2150, 2172, 2243, 2288, 2533);

            var sourceIndices = chars.Select(x => x.SourceIndex).ToArray();

            TheResultingCollection(sourceIndices)
            .ShouldBeExactly(12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0);

            var advances = chars.Select(x => x.Advance).ToArray();

            TheResultingCollection(advances)
            .ShouldBeExactly(15, 5, 5, 13, 5, 5, 6, 6, 5, 7, 15, 9, 13);

            var offsets_x = chars.Select(x => x.OffsetX).ToArray();

            TheResultingCollection(offsets_x)
            .ShouldContainTheSpecifiedNumberOfItems(13)
            .ShouldContainItemsSatisfyingTheCondition(x => x == 0);

            var offsets_y = chars.Select(x => x.OffsetY).ToArray();

            TheResultingCollection(offsets_y)
            .ShouldContainTheSpecifiedNumberOfItems(13)
            .ShouldContainItemsSatisfyingTheCondition(x => x == 0);
        }
示例#4
0
        /// <inheritdoc/>
        public override ShapedString CreateShapedString(UltravioletFontFace fontFace, Int32 start, Int32 length, Int32 sourceIndexOffset = 0)
        {
            Contract.Require(fontFace, nameof(fontFace));
            Contract.EnsureRange(start >= 0 && start < rawstr.Length, nameof(start));
            Contract.EnsureRange(length >= 0 && start + length <= rawstr.Length, nameof(length));
            Contract.EnsureNotDisposed(this, Disposed);

            unsafe
            {
                Shape(fontFace, out var glyphInfo, out var glyphPosition, out var glyphCount);

                var end        = start + length;
                var chars      = new ShapedChar[glyphCount];
                var charsCount = 0;
                for (var i = 0; i < glyphCount; i++)
                {
                    var cluster = (Int32)glyphInfo->cluster;
                    if (cluster >= start)
                    {
                        if (cluster >= end)
                        {
                            break;
                        }

                        switch (rawstr[cluster])
                        {
                        case '\n':
                            chars[i] = new ShapedChar('\n', sourceIndexOffset + cluster, Int16.MaxValue, Int16.MaxValue, Int16.MaxValue);
                            break;

                        case '\t':
                            chars[i] = new ShapedChar('\t', sourceIndexOffset + cluster, Int16.MaxValue, Int16.MaxValue, Int16.MaxValue);
                            break;

                        default:
                            CreateShapedChar(glyphInfo, glyphPosition, sourceIndexOffset + cluster, out chars[i]);
                            break;
                        }
                        charsCount++;
                    }
                    glyphInfo++;
                    glyphPosition++;
                }

                return(new ShapedString(fontFace, GetLanguage(), GetScript(), GetDirection(), chars, 0, charsCount));
            }
        }
示例#5
0
        public void ShapedString_ProvidesCorrectSourceIndices_WhenGivenAnExplicitOffset()
        {
            var sstr1 = default(ShapedString);
            var sstr2 = default(ShapedString);

            GivenAnUltravioletApplicationWithNoWindow()
            .WithPlugin(new FreeTypeFontPlugin())
            .WithContent(content =>
            {
                var font = content.Load <UltravioletFont>("Fonts/NotoColorEmoji");
                using (var textShaper = new HarfBuzzTextShaper(content.Ultraviolet))
                {
                    textShaper.SetUnicodeProperties(TextDirection.LeftToRight, TextScript.Latin, "en");
                    textShaper.Append("Hello, world!");

                    sstr1 = textShaper.CreateShapedString(font.Regular);

                    textShaper.Clear();
                    textShaper.Append(" Goodbye, world!");

                    sstr2 = textShaper.CreateShapedString(font.Regular, "Hello, world!".Length);
                }
            })
            .RunForOneFrame();

            var chars1 = new ShapedChar[sstr1.Length];

            sstr1.CopyTo(0, chars1, 0, sstr1.Length);

            var sourceIndices1 = chars1.Select(x => x.SourceIndex).ToArray();

            TheResultingCollection(sourceIndices1)
            .ShouldBeExactly(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12);

            var chars2 = new ShapedChar[sstr2.Length];

            sstr2.CopyTo(0, chars2, 0, sstr2.Length);

            var sourceIndices2 = chars2.Select(x => x.SourceIndex).ToArray();

            TheResultingCollection(sourceIndices2)
            .ShouldBeExactly(13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28);
        }
示例#6
0
        public void ShapedString_ProvidesCorrectSourceIndices()
        {
            var sstr = default(ShapedString);

            GivenAnUltravioletApplicationWithNoWindow()
            .WithPlugin(new FreeTypeFontPlugin())
            .WithContent(content =>
            {
                var font = content.Load <UltravioletFont>("Fonts/NotoColorEmoji");
                using (var textShaper = new HarfBuzzTextShaper(content.Ultraviolet))
                {
                    textShaper.SetUnicodeProperties(TextDirection.LeftToRight, TextScript.Latin, "en");
                    textShaper.Append("Hello ");
                    textShaper.Append("👨");
                    textShaper.Append("\u200D");
                    textShaper.Append("👩");
                    textShaper.Append("\u200D");
                    textShaper.Append("👧");
                    textShaper.Append("\u200D");
                    textShaper.Append("👦");
                    textShaper.Append("!");

                    sstr = textShaper.CreateShapedString(font.Regular);
                }
            })
            .RunForOneFrame();

            var chars = new ShapedChar[sstr.Length];

            sstr.CopyTo(0, chars, 0, sstr.Length);

            var sourceIndices = chars.Select(x => x.SourceIndex).ToArray();

            TheResultingCollection(sourceIndices)
            .ShouldBeExactly(0, 1, 2, 3, 4, 5, 6, 17);
        }