コード例 #1
0
ファイル: TextElement.cs プロジェクト: ARLM-Attic/xna-xen
        //this is rather complex :-)
        private void Build(Vector2 pixelArea)
        {
            if (font == null)
            {
                throw new InvalidOperationException("TextElementRect.Font");
            }

            sprite.SetTextureAndClear(font.textureValue);

            Vector2 position = new Vector2();
            bool    flag     = true;
            int     index;
            int     periodIndex;
            int     beginWord       = 0;
            int     beginLine       = 0;
            int     beginWordIndex  = 0;
            int     beginWordLength = 0;
            int     spriceCount     = 0;
            int     lastIndex       = -1;
            float   beginX          = 0;

            if (!font.TryGetCharacterIndex('.', out periodIndex))
            {
                periodIndex = -1;
            }
            if (textAlign == TextHorizontalAlignment.Justified && spaces == null)
            {
                spaces = new List <int>();
            }

            StringBuilder text = this.text.value;

            uint insertedElementIndex     = children.ResetInsertIndex();
            uint lineInsertedElementCount = 0;


            if (text.Length > 0 && pixelArea.X > 1)
            {
                for (int i = 0; i < text.Length; i++)
                {
                    if (i == insertedElementIndex)
                    {
                        float width;

                        //update the inserted element
                        children.SetInsertedElementLayout(ref position, out width);
                        position.X          += width;
                        insertedElementIndex = children.GetNextInsertedIndex();
                    }

                    char c = text[i];

                    switch (c)
                    {
                    case '\r':
                        break;

                    case '\n':

                        if (textAlign == TextHorizontalAlignment.Right ||
                            textAlign == TextHorizontalAlignment.Centre)
                        {
                            Vector2 delta = new Vector2(pixelArea.X - position.X, 0);
                            if (textAlign == TextHorizontalAlignment.Centre)
                            {
                                delta.X *= 0.5f;
                            }

                            delta.X = (float)Math.Floor(delta.X);

                            for (int n = beginLine; n < sprite.InstanceCount; n++)
                            {
                                sprite.MoveSprite(n, ref delta);
                            }
                            children.MoveRange(ref delta, lineInsertedElementCount);
                        }

                        if (textAlign == TextHorizontalAlignment.Justified)
                        {
                            spaces.Clear();
                        }

                        flag        = true;
                        position.X  = 0;
                        position.Y -= font.lineSpacingF;
                        beginWord   = -1;
                        beginX      = 0;

                        beginLine = sprite.InstanceCount;
                        lineInsertedElementCount = children.GetInsertedCount();
                        break;

                    case '\t':
                        beginWord = -1;
                        if (font.TryGetCharacterIndex(' ', out index))
                        {
                            Vector3 kerning = font.kerning[index];
                            float   width   = ((kerning.Y + kerning.Z)) * 4;

                            position.X = (float)(Math.Floor(position.X / width) + 1) * width;

                            if (textAlign == TextHorizontalAlignment.Justified)
                            {
                                spaces.Add(sprite.InstanceCount);
                            }
                        }
                        break;

                    default:
                        if (c == ' ' && textAlign == TextHorizontalAlignment.Justified)
                        {
                            spaces.Add(sprite.InstanceCount);
                        }

                        if (beginWord == -1 || !(char.IsLetterOrDigit(c) || c == '_'))
                        {
                            beginWord       = lastIndex;
                            beginWordIndex  = i;
                            beginWordLength = spriceCount;
                            beginX          = position.X;
                        }

                        if (font.TryGetCharacterIndex(c, out index))
                        {
                            Vector3 kerning = font.kerning[index];
                            if (flag)
                            {
                                kerning.X = Math.Max(kerning.X, 0f);
                            }
                            position.X += (kerning.X);

                            Vector4 crop = font.croppingDataV4[index];

                            if (!char.IsWhiteSpace(c) && position.X + font.glyphWidth[index] > pixelArea.X)
                            {
                                //wrap to new line
                                bool tooLong = false;
                                if (beginWord != -1)
                                {
                                    //find out how long this word is...

                                    float length = 0;
                                    for (int n = i; n < text.Length; n++)
                                    {
                                        if (!(char.IsLetterOrDigit(text[n]) || text[n] == '_'))
                                        {
                                            break;
                                        }

                                        int nindex = 0;
                                        if (font.TryGetCharacterIndex(text[n], out nindex))
                                        {
                                            length += font.glyphWidth[nindex];

                                            if ((position.X - beginX + length) > pixelArea.X)
                                            {
                                                //word is too long to be broken onto multiple lines
                                                tooLong = true;
                                                break;
                                            }
                                        }
                                    }


                                    if (!tooLong)
                                    {
                                        sprite.RemoveLastSprite(spriceCount - beginWordLength);
                                        i           = beginWordIndex;
                                        spriceCount = beginWordLength;
                                        position.X  = beginX;
                                        if (textAlign == TextHorizontalAlignment.Justified &&
                                            spaces.Count > 0)
                                        {
                                            spaces.RemoveAt(spaces.Count - 1);
                                        }
                                    }
                                }

                                if (textAlign == TextHorizontalAlignment.Right ||
                                    textAlign == TextHorizontalAlignment.Centre)
                                {
                                    Vector2 delta = new Vector2(pixelArea.X - position.X, 0);
                                    if (textAlign == TextHorizontalAlignment.Centre)
                                    {
                                        delta.X *= 0.5f;
                                    }

                                    delta.X = (float)Math.Floor(delta.X);
                                    delta.Y = (float)Math.Floor(delta.Y);

                                    for (int n = beginLine; n < sprite.InstanceCount; n++)
                                    {
                                        sprite.MoveSprite(n, ref delta);
                                    }
                                    children.MoveRange(ref delta, lineInsertedElementCount);
                                }

                                if (textAlign == TextHorizontalAlignment.Justified && spaces.Count > 0)
                                {
                                    float   gap    = (pixelArea.X - position.X) / (spaces.Count);
                                    float   deltaf = 0;
                                    Vector2 delta  = new Vector2(0, 0);

                                    int spaceIndex;
                                    if (font.TryGetCharacterIndex(' ', out spaceIndex))
                                    {
                                        Vector3 spaceSize = font.kerning[spaceIndex];
                                        if (gap > ((spaceSize.Y + spaceSize.Z)) * 40)
                                        {
                                            gap = 0;
                                        }
                                    }

                                    spaceIndex = 0;
                                    for (int n = beginLine; n < sprite.InstanceCount; n++)
                                    {
                                        if (spaceIndex != spaces.Count &&
                                            n == spaces[spaceIndex])
                                        {
                                            spaceIndex++;
                                            deltaf += gap;
                                            delta.X = (float)Math.Floor(deltaf);
                                        }
                                        sprite.MoveSprite(n, ref delta);
                                        children.MoveRangeUptoIndex(ref delta, ref lineInsertedElementCount, n);
                                    }
                                    children.MoveRangeUptoIndex(ref delta, ref lineInsertedElementCount, i + 1);
                                    spaces.Clear();
                                }

                                beginLine   = sprite.InstanceCount;
                                position.X  = Math.Max(kerning.X, 0f);
                                position.Y -= font.lineSpacingF;
                                beginX      = 0;
                                if (!char.IsWhiteSpace(text[i]))
                                {
                                    i--;
                                }
                                lineInsertedElementCount = children.GetInsertedCount();
                                continue;
                            }

                            Vector2 pos = position;

                            if (!sizeToVertical && periodIndex != -1 &&
                                -position.Y > pixelArea.Y - font.lineSpacingF * 2 &&
                                position.X + font.glyphWidth[index] > pixelArea.X - 3 * font.glyphWidth[periodIndex])
                            {
                                if (pixelArea.X > 3 * font.glyphWidth[periodIndex])
                                {
                                    //add an elipsis ...
                                    crop    = font.croppingDataV4[periodIndex];
                                    kerning = font.kerning[periodIndex];
                                    pos.Y  -= crop.Y + font.glyphSize[periodIndex].Y;
                                    pos.X  += crop.X;

                                    for (int n = 0; n < 3; n++)
                                    {
                                        sprite.AddSprite(ref pos, ref font.glyphSize[periodIndex], ref colour, ref font.glyphDataV4[periodIndex]);
                                        spriceCount++;

                                        pos.X += kerning.X + kerning.Y + kerning.Z;
                                    }

                                    i = text.Length;
                                    break;
                                }
                            }

                            pos.X += crop.X;
                            pos.Y -= crop.Y + font.glyphSize[index].Y;


                            lastIndex = sprite.AddSprite(ref pos, ref font.glyphSize[index], ref colour, ref font.glyphDataV4[index]);
                            spriceCount++;

                            flag        = false;
                            position.X += ((kerning.Y + kerning.Z));
                        }
                        break;
                    }
                }
            }

            if (textAlign == TextHorizontalAlignment.Right ||
                textAlign == TextHorizontalAlignment.Centre)
            {
                Vector2 delta = new Vector2(pixelArea.X - position.X, 0);
                if (textAlign == TextHorizontalAlignment.Centre)
                {
                    delta.X = (float)Math.Floor(delta.X * 0.5f);
                }

                delta.X = (float)Math.Floor(delta.X);

                for (int n = beginLine; n < sprite.InstanceCount; n++)
                {
                    sprite.MoveSprite(n, ref delta);
                }
                children.MoveRange(ref delta, lineInsertedElementCount);
            }
            if (sizeToVertical)
            {
                this.Size = new Vector2(this.Size.X, font.lineSpacingF - position.Y);
            }
            else
            {
                if (textVAlign == VerticalAlignment.Centre ||
                    textVAlign == VerticalAlignment.Bottom)
                {
                    float height = pixelArea.Y - (font.lineSpacingF - position.Y);
                    if (height > 0)
                    {
                        if (textVAlign == VerticalAlignment.Centre)
                        {
                            height *= 0.5f;
                        }

                        height = (float)Math.Floor(height);
                        Vector2 delta = new Vector2(0, -height);

                        delta.Y = (float)Math.Floor(delta.Y);

                        for (int n = 0; n < sprite.InstanceCount; n++)
                        {
                            sprite.MoveSprite(n, ref delta);
                        }
                        children.MoveRange(ref delta, 0);
                    }
                }
            }
        }
コード例 #2
0
ファイル: TextElement.cs プロジェクト: ARLM-Attic/xna-xen
        private void Build()
        {
            if (this.font == null)
            {
                throw new InvalidOperationException("TextElement.Font == null");
            }

            sprite.SetTextureAndClear(font.textureValue);

            Vector2 position = new Vector2();
            bool    flag     = true;
            int     index;

            uint insertedElementIndex = children.ResetInsertIndex();

            StringBuilder text = this.text.value;

            if (text.Length > 0)
            {
                for (int i = 0; i < text.Length; i++)
                {
                    if (i == insertedElementIndex)
                    {
                        float width;

                        //update the inserted element
                        children.SetInsertedElementLayout(ref position, out width);
                        position.X          += width;
                        insertedElementIndex = children.GetNextInsertedIndex();
                    }


                    char c = text[i];

                    switch (c)
                    {
                    case '\r':
                        break;

                    case '\n':
                        flag        = true;
                        position.X  = 0;
                        position.Y -= font.lineSpacingF;
                        break;

                    case '\t':
                        if (font.TryGetCharacterIndex(' ', out index))
                        {
                            Vector3 kerning = font.kerning[index];
                            float   width   = ((kerning.Y + kerning.Z)) * 4;

                            position.X = (float)(Math.Floor(position.X / width) + 1) * width;
                        }
                        break;

                    default:
                        if (font.TryGetCharacterIndex(c, out index))
                        {
                            Vector3 kerning = font.kerning[index];
                            if (flag)
                            {
                                kerning.X = Math.Max(kerning.X, 0f);
                            }
                            position.X += (kerning.X);

                            Vector4 crop = font.croppingDataV4[index];

                            Vector2 pos = position;
                            pos.X += crop.X;
                            pos.Y -= crop.Y + font.glyphSize[index].Y;


                            sprite.AddSprite(ref pos, ref font.glyphSize[index], ref colour, ref font.glyphDataV4[index]);

                            flag        = false;
                            position.X += ((kerning.Y + kerning.Z));
                        }
                        break;
                    }
                }
            }
        }