コード例 #1
0
        private void ForEachGlyph <T>(ref StringProxy text, ref Vector2 fontSize, GlyphAction <T> action, ref T parameters, TextAlignment scanOrder, bool updateGpuResources, Vector2?elementsize = null)
        {
            if (scanOrder == TextAlignment.Left)
            {
                // scan the whole text only one time following the text letter order
                ForGlyph(ref text, ref fontSize, action, ref parameters, 0, text.Length, updateGpuResources);
            }
            else // scan the text line by line incrementing y start position
            {
                // measure the whole string in order to be able to determine xStart
                var wholeSize = elementsize.HasValue ? elementsize.Value : MeasureString(ref text, ref fontSize);

                // scan the text line by line
                var yStart     = 0f;
                var startIndex = 0;
                var endIndex   = FindCariageReturn(ref text, 0);
                while (startIndex < text.Length)
                {
                    // measure the size of the current line
                    var lineSize = Vector2.Zero;
                    ForGlyph(ref text, ref fontSize, MeasureStringGlyph, ref lineSize, startIndex, endIndex, updateGpuResources);

                    // scan the line
                    var xStart = (scanOrder == TextAlignment.Center) ? (wholeSize.X - lineSize.X) / 2 : wholeSize.X - lineSize.X;
                    ForGlyph(ref text, ref fontSize, action, ref parameters, startIndex, endIndex, updateGpuResources, xStart, yStart);

                    // update variable before going to next line
                    yStart    += GetTotalLineSpacing(fontSize.Y);
                    startIndex = endIndex + 1;
                    endIndex   = FindCariageReturn(ref text, startIndex);
                }
            }
        }
コード例 #2
0
        private void ForGlyph <T>(ref StringProxy text, ref Vector2 fontSize, GlyphAction <T> action, ref T parameters, int forStart, int forEnd, bool updateGpuResources, float startX = 0, float startY = 0)
        {
            var key = 0;
            var x   = startX;
            var y   = startY;

            for (var i = forStart; i < forEnd; i++)
            {
                char character = text[i];

                switch (character)
                {
                case '\r':
                    // Skip carriage returns.
                    key |= character;
                    continue;

                case '\n':
                    // New line.
                    x    = 0;
                    y   += GetTotalLineSpacing(fontSize.Y);
                    key |= character;
                    break;

                default:
                    // Output this character.
                    var glyph = GetGlyph(character, ref fontSize, updateGpuResources);
                    if (glyph == null && !IgnoreUnkownCharacters && DefaultCharacter.HasValue)
                    {
                        glyph = GetGlyph(DefaultCharacter.Value, ref fontSize, updateGpuResources);
                    }
                    if (glyph == null)
                    {
                        continue;
                    }

                    key |= character;

                    float dx = glyph.Offset.X;

                    float kerningOffset;
                    if (KerningMap != null && KerningMap.TryGetValue(key, out kerningOffset))
                    {
                        dx += kerningOffset;
                    }

                    float nextX = x + glyph.XAdvance + GetExtraSpacing(fontSize.X);
                    action(ref parameters, ref fontSize, ref glyph, x + dx, y, nextX);
                    x = nextX;
                    break;
                }

                // Shift the kerning key
                key = (key << 16);
            }
        }
コード例 #3
0
        private void ForEachGlyph <T>(ref StringProxy text, ref Vector2 fontSize, GlyphAction <T> action, ref T parameters, TextAlignment scanOrder, bool updateGpuResources, Vector2?elementsize = null)
        {
            if (scanOrder == TextAlignment.Left)
            {
                // scan the whole text only one time following the text letter order
                ForGlyph(ref text, ref fontSize, action, ref parameters, 0, text.Length, updateGpuResources);
            }
            else // scan the text line by line incrementing y start position
            {
                // measure the whole string in order to be able to determine xStart
                var wholeSize = elementsize ?? MeasureString(ref text, ref fontSize);

                // scan the text line by line
                var yStart     = 0f;
                var startIndex = 0;
                var endIndex   = FindCariageReturn(ref text, 0);
                while (startIndex < text.Length)
                {
                    // measure the size of the current line
                    var lineSize = Vector2.Zero;
                    ForGlyph(ref text, ref fontSize, MeasureStringGlyph, ref lineSize, startIndex, endIndex, updateGpuResources);

                    // Determine the start position of the line along the x axis
                    // We round this value to the closest integer to force alignment of all characters to the same pixels
                    // Otherwise the starting offset can fall just in between two pixels and due to float imprecision
                    // some characters can be aligned to the pixel before and others to the pixel after, resulting in gaps and character overlapping
                    var xStart = (scanOrder == TextAlignment.Center) ? (wholeSize.X - lineSize.X) / 2 : wholeSize.X - lineSize.X;
                    xStart = (float)Math.Round(xStart);

                    // scan the line
                    ForGlyph(ref text, ref fontSize, action, ref parameters, startIndex, endIndex, updateGpuResources, xStart, yStart);

                    // update variable before going to next line
                    yStart    += GetTotalLineSpacing(fontSize.Y);
                    startIndex = endIndex + 1;
                    endIndex   = FindCariageReturn(ref text, startIndex);
                }
            }
        }
コード例 #4
0
ファイル: SpriteFont.cs プロジェクト: skapunch/xenko
 protected internal SpriteFont()
 {
     internalDrawGlyphAction   = InternalDrawGlyph;
     internalUIDrawGlyphAction = InternalUIDrawGlyph;
     measureStringGlyphAction  = MeasureStringGlyph;
 }
コード例 #5
0
        private unsafe void ForEachGlyph <T>(ref StringProxy text, GlyphAction <T> action, ref T parameters)
        {
            float x = 0;
            float y = 0;

            // TODO: Not sure how to handle globalBaseOffsetY from AngelCode BMFont

            fixed(void *pGlyph = glyphs)
            {
                var key = 0;

                for (int i = 0; i < text.Length; i++)
                {
                    char character = text[i];

                    switch (character)
                    {
                    case '\r':
                        // Skip carriage returns.
                        key |= character;
                        continue;

                    case '\n':
                        // New line.
                        x    = 0;
                        y   += LineSpacing;
                        key |= character;
                        break;

                    default:
                        // Output this character.
                        int glyphIndex;
                        if (!characterMap.TryGetValue(character, out glyphIndex))
                        {
                            if (IgnoreUnkownCharacters)
                            {
                                continue;
                            }

                            if (DefaultCharacter.HasValue && defaultGlyphIndex >= 0)
                            {
                                character  = DefaultCharacter.Value;
                                glyphIndex = defaultGlyphIndex;
                            }
                            else
                            {
                                throw new ArgumentException(string.Format("Character '{0}' is not available in the SpriteFont character map", character), "text");
                            }
                        }
                        key |= character;

                        var glyph = (SpriteFontData.Glyph *)pGlyph + glyphIndex;

                        // do not offset the first character, otherwise it is impossible to compute correct alignment
                        // using MeasureString results
                        if (x > 0f)
                        {
                            x += glyph->Offset.X;
                        }

                        // reset negative offset (it can happen only for first character)
                        if (x < 0f)
                        {
                            x = 0f;
                        }

                        // Offset the kerning
                        float kerningOffset;
                        if (kerningMap != null && kerningMap.TryGetValue(key, out kerningOffset))
                        {
                            x += kerningOffset;
                        }

                        if (!char.IsWhiteSpace(character))
                        {
                            action(ref parameters, ref *glyph, x, y);
                        }

                        x += glyph->XAdvance + Spacing;
                        break;
                    }

                    // Shift the kerning key
                    key = (key << 16);
                }
            }
        }
コード例 #6
0
        internal SpriteFont(GraphicsDevice device, SpriteFontData spriteFontData, bool disposeSpriteFontDataResources)
            : base(device)
        {
            drawGlyphDelegate    = InternalDrawGlyph;
            measureGlyphDelegate = MeasureStringGlyph;

            // Read the glyph data.
            globalBaseOffsetY = spriteFontData.BaseOffset;
            glyphs            = spriteFontData.Glyphs;
            characterMap      = new Dictionary <char, int>(glyphs.Length * 2);

            // Prebuild the character map
            var characterList = new List <char>(glyphs.Length);

            for (int i = 0; i < glyphs.Length; i++)
            {
                var charItem = (char)glyphs[i].Character;
                characterMap.Add(charItem, i);
                characterList.Add(charItem);
            }

            // Prepare kernings if they are available.
            var kernings = spriteFontData.Kernings;

            if (kernings != null)
            {
                kerningMap = new Dictionary <int, float>(spriteFontData.Kernings.Length);
                for (int i = 0; i < kernings.Length; i++)
                {
                    int key = (kernings[i].First << 16) | kernings[i].Second;
                    kerningMap.Add(key, kernings[i].Offset);
                }
            }

            Characters = new ReadOnlyCollection <char>(characterList);

            // Read font properties.
            LineSpacing = spriteFontData.LineSpacing;

            if (spriteFontData.DefaultCharacter > 0)
            {
                DefaultCharacter = (char)spriteFontData.DefaultCharacter;
                if (!characterMap.TryGetValue(DefaultCharacter.Value, out defaultGlyphIndex))
                {
                    defaultGlyphIndex = -1;
                }
            }

            // Read the texture data.
            textures = new Texture2D[spriteFontData.Bitmaps.Length];
            for (int i = 0; i < textures.Length; i++)
            {
                var bitmap = spriteFontData.Bitmaps[i];
                if (bitmap.Data is SpriteFontData.BitmapData)
                {
                    var image = (SpriteFontData.BitmapData)bitmap.Data;
                    textures[i] = ToDispose(Texture2D.New(device, image.Width, image.Height, image.PixelFormat, image.Data));
                }
                else if (bitmap.Data is Texture2D)
                {
                    textures[i] = (Texture2D)bitmap.Data;
                    if (disposeSpriteFontDataResources)
                    {
                        ToDispose(textures[i]);
                    }
                }
                else
                {
                    throw new NotSupportedException(string.Format("SpriteFontData.Bitmap of type [{0}] is not supported. Only SpriteFontData.BitmapData or Texture2D", bitmap == null ? "null" : bitmap.GetType().Name));
                }
            }
        }
コード例 #7
0
ファイル: SpriteFont.cs プロジェクト: CriDos/xenko
        private void ForGlyph <T>(CommandList commandList, ref StringProxy text, ref Vector2 fontSize, GlyphAction <T> action,
                                  ref T parameters, int forStart, int forEnd, bool updateGpuResources, float startX = 0, float startY = 0,
                                  TextVerticalAlignment vertAlign = TextVerticalAlignment.Top, float fontSizeY = 0f)
        {
            var key = 0;
            var x   = startX;
            var y   = startY;

            // tag management
            var escaping = false;

            colorStack.Clear();
            for (var i = forStart; i < forEnd; i++)
            {
                var character = text[i];

                if (!escaping && character == '<')
                {
                    // check tags
                    if (CheckAndProcessColorTag(ref text, ref i, out Color4 color))
                    {
                        colorStack.Push(color);
                    }
                    else if (colorStack.Count > 0 && EndsTag("</color>", ref text, ref i))
                    {
                        colorStack.Pop();
                    }
                }
コード例 #8
0
ファイル: SpriteFont.cs プロジェクト: CriDos/xenko
        private void ForEachGlyph <T>(CommandList commandList, ref StringProxy text, ref Vector2 requestedFontSize, GlyphAction <T> action, ref T parameters,
                                      TextAlignment scanOrder, TextVerticalAlignment vertAlign, bool updateGpuResources, Vector2?textBoxSize = null, float lineSpaceAdjustment = 0f)
        {
            float rawYSpacing = GetTotalLineSpacing(requestedFontSize.Y);
            float yStart, ySpacing = rawYSpacing + lineSpaceAdjustment;

            if (textBoxSize.HasValue && vertAlign != TextVerticalAlignment.Top)
            {
                int   extraLines = text.LineCount - 1;
                float lineHeight = rawYSpacing + extraLines * ySpacing;
                switch (vertAlign)
                {
                default:
                case TextVerticalAlignment.Center:
                    yStart = textBoxSize.Value.Y * 0.5f - (lineHeight * 0.5f);
                    break;

                case TextVerticalAlignment.Bottom:
                    yStart = textBoxSize.Value.Y - lineHeight;
                    break;
                }
            }
            else
            {
                yStart = 0f;
            }

            if (scanOrder == TextAlignment.Left)
            {
                // scan the whole text only one time following the text letter order
                ForGlyph(commandList, ref text, ref requestedFontSize, action, ref parameters, 0, text.Length, updateGpuResources, 0f, yStart, vertAlign, ySpacing);
            }
            else
            {
                // scan the text line by line incrementing y start position

                // measure the whole string in order to be able to determine xStart
                var wholeSize = textBoxSize ?? MeasureString(ref text, ref requestedFontSize);

                // scan the text line by line
                var startIndex = 0;
                var endIndex   = FindCariageReturn(ref text, 0);
                while (startIndex < text.Length)
                {
                    // measure the size of the current line
                    var lineSize = Vector2.Zero;
                    ForGlyph(commandList, ref text, ref requestedFontSize, MeasureStringGlyph, ref lineSize, startIndex, endIndex, updateGpuResources, 0f, 0f, vertAlign, ySpacing);

                    // Determine the start position of the line along the x axis
                    // We round this value to the closest integer to force alignment of all characters to the same pixels
                    // Otherwise the starting offset can fall just in between two pixels and due to float imprecision
                    // some characters can be aligned to the pixel before and others to the pixel after, resulting in gaps and character overlapping
                    var xStart = (scanOrder == TextAlignment.Center) ? (wholeSize.X - lineSize.X) / 2 : wholeSize.X - lineSize.X;
                    xStart = (float)Math.Round(xStart);

                    // scan the line
                    ForGlyph(commandList, ref text, ref requestedFontSize, action, ref parameters, startIndex, endIndex, updateGpuResources, xStart, yStart, vertAlign, ySpacing);

                    // update variable before going to next line
                    yStart    += ySpacing;
                    startIndex = endIndex + 1;
                    endIndex   = FindCariageReturn(ref text, startIndex);
                }
            }
        }
コード例 #9
0
ファイル: SpriteFont.cs プロジェクト: neojijon/SharpDX
        private unsafe void ForEachGlyph <T>(ref StringProxy text, GlyphAction <T> action, ref T parameters)
        {
            float x = 0;
            float y = 0;

            // TODO: Not sure how to handle globalBaseOffsetY from AngelCode BMFont

            fixed(void *pGlyph = glyphs)
            {
                var key = 0;

                for (int i = 0; i < text.Length; i++)
                {
                    char character = text[i];

                    switch (character)
                    {
                    case '\r':
                        // Skip carriage returns.
                        key |= character;
                        continue;

                    case '\n':
                        // New line.
                        x   = 0;
                        y  += LineSpacing;
                        key = 0;
                        break;

                    default:
                        // Output this character.
                        int glyphIndex;
                        if (!characterMap.TryGetValue(character, out glyphIndex))
                        {
                            if (IgnoreUnkownCharacters)
                            {
                                continue;
                            }

                            if (DefaultCharacter.HasValue && defaultGlyphIndex >= 0)
                            {
                                character  = DefaultCharacter.Value;
                                glyphIndex = defaultGlyphIndex;
                            }
                            else
                            {
                                throw new ArgumentException(string.Format("Character '{0}' is not available in the SpriteFont character map", character), "text");
                            }
                        }
                        key |= character;

                        var glyph = (SpriteFontData.Glyph *)pGlyph + glyphIndex;

                        float dx = glyph->Offset.X;

                        float kerningOffset;
                        if (kerningMap != null && kerningMap.TryGetValue(key, out kerningOffset))
                        {
                            dx += kerningOffset;
                        }

                        float nextX = x + glyph->XAdvance + Spacing;
                        action(ref parameters, ref *glyph, x + dx, y, nextX);
                        x = nextX;

                        break;
                    }

                    // Shift the kerning key
                    key = (key << 16);
                }
            }
        }
コード例 #10
0
ファイル: SpriteFont.cs プロジェクト: s33m3/SharpDX
        private unsafe void ForEachGlyph(ref StringProxy text, GlyphAction action)
        {
            float x = 0;
            float y = 0;
            // TODO: Not sure how to handle globalBaseOffsetY from AngelCode BMFont

            fixed (void* pGlyph = glyphs)
            {
                var key = 0;
                for (int i =  0; i < text.Length; i++)
                {
                    char character = text[i];					

                    switch (character)
                    {
                        case '\r':
                            // Skip carriage returns.
                            key |= character;
                            continue;

                        case '\n':
                            // New line.
                            x = 0;
                            y += LineSpacing;
                            key |= character;
                            break;

                        default:
                            // Output this character.
                            int glyphIndex;
                            if (!characterMap.TryGetValue(character, out glyphIndex))
                            {
                                if(DefaultCharacter.HasValue && defaultGlyphIndex >= 0)
                                {
                                    character = DefaultCharacter.Value;
                                    glyphIndex = defaultGlyphIndex;
                                }
                                else
                                {
                                    throw new ArgumentException(string.Format("Character '{0}' is not available in the SpriteFont character map", character), "text");
                                }
                            }
                            key |= character;

                            var glyph = (SpriteFontData.Glyph*) pGlyph + glyphIndex;


                            x += glyph->Offset.X;

                            if (x < 0)
                                x = 0;

                            // Offset the kerning
                            float kerningOffset;
                            if (kerningMap != null && kerningMap.TryGetValue(key, out kerningOffset))
                                x += kerningOffset;

                            if (!char.IsWhiteSpace(character))
                            {
                                action(ref *glyph, x, y);
                            }

                            x += glyph->XAdvance;
                            break;
                    }

                    // Shift the kerning key
                    key  =  (key << 16);
                }
            }
        }
コード例 #11
0
        private void ForGlyph <T>(CommandList commandList, ref StringProxy text, ref Vector2 fontSize, GlyphAction <T> action,
                                  ref T parameters, int forStart, int forEnd, bool updateGpuResources, float startX = 0, float startY = 0,
                                  TextVerticalAlignment vertAlign = TextVerticalAlignment.Top, float fontSizeY = 0f)
        {
            var key = 0;
            var x   = startX;
            var y   = startY;

            // color tags
            var escaping = false;
            var tagStack = new List <Color4>();

            for (var i = forStart; i < forEnd; i++)
            {
                var character = text[i];

                if (StartsColorTag(ref text, ref i, out Color4 color) && !escaping)
                {
                    tagStack.Add(color);
                }