예제 #1
0
        // OnRender
        protected override void OnRender()
        {
            if ((Size.Y <= 0.0f) || (!ColorFinal.HasAlpha() && ((RenderState.BlendState == E_BlendState.AlphaBlend) || (RenderState.BlendState == E_BlendState.NonPremultiplied))))
            {
                return;
            }

            if (FontStyle == null)
            {
                return;
            }

            if ((_String == null) && (StringUI == null))
            {
                return;
            }

            using (new AutoTransform(this))
            {
                if (FontEffects.Count > 0)
                {
                    _UI.Font.DoFontEffectsNext(FontEffects);
                }

                if (Cache && CacheValid)
                {
                    FontStyle.Render(SpriteListCache, RenderSizeY);
                }
                else
                {
                    Vector2 stringSize = new Vector2();

                    if (StringUI != null)
                    {
                        stringSize = _UI.Font.Draw(StringUI, FontStyle, RenderPass, Layer, ref Position, RenderSizeY, Align, ref ColorFinal, RenderSizeX);
                    }
                    else
                    {
                        stringSize = _UI.Font.Draw(_String, FontStyle, RenderPass, Layer, ref Position, RenderSizeY, Align, ref ColorFinal, RenderSizeX);
                    }

                    // slag lag - are we bothered? We'll see ...
                    Size.X = stringSize.X;
                    Size.Y = stringSize.Y;

                    if (Cache)
                    {
                        CacheValid = true;
                        _UI.Font.SpriteList.CopyTo(SpriteListCache);
                    }
                }

                for (int i = 0; i < FontEffects.Count; ++i)
                {
                    FontEffects[i].Update(FrameTime); // meh - but need to update here to make sure the letter count is correct
                }
            }                                         // auto transform
        }
예제 #2
0
        private unsafe Vector2 Process( ref StringProxy text, FontStyle fontStyle, float height, float wrapSizeX, E_FontProcessType processType )
        {
            if ( text.Length == 0 )
            return new Vector2();

            SpriteList.Reset();

            SpriteList.RenderPass = RenderPass;
            SpriteList.Layer = Layer;

            FontData fontData = fontStyle.Font.FontData;

            float startX = Position.X;
            float x = startX;
            float y = Position.Y;

            float scale = height / fontData.FontHeight;
            float charHeight = fontData.LineHeight * scale;
            float lineHeight = charHeight * fontStyle.HeightPercentage;
            float multY = _UI.Sprite.IsRenderPass3D( RenderPass ) ? -1.0f : 1.0f;

            int numLines = 1;

            fixed ( char* pString = text.String )
            fixed ( FontSprite* pSpriteStart = &SpriteList.Sprites[ 0 ] )
            fixed ( FontDataChar* pCharDataStart = &fontData.Characters[ 0 ] )
            {
            char* s = ( pString != null ) ? pString : text.StringUI;

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

                if ( c == '\n' )
                {
                    ++numLines;
                    y += ( lineHeight * multY );
                    x = startX;

                    ( pSpriteStart + SpriteList.RenderEnd - 1 )->BreakType = E_LetterBreakType.Line;

                    continue;
                }

                int characterIndex = fontData.GetCharacterIndex( c );
                FontDataChar* pCharData = ( pCharDataStart + characterIndex );

                if ( c == ' ' )
                {
                    // mark as potential wrap point unless we've already wrapped here
                    FontSprite* pSpriteEnd = ( pSpriteStart + SpriteList.RenderEnd - 1 );

                    if ( ( SpriteList.RenderEnd != 0 ) && ( pSpriteEnd->BreakType != E_LetterBreakType.Line ) )
                        pSpriteEnd->BreakType = E_LetterBreakType.Wrap;

                    // advance
                    x += ( pCharData->AdvanceX * scale );
                }
                else
                {
                    // check for icons
                    if ( ( ( i + 5 ) <= text.Length ) && ( c == '[' ) && ( s[ i + 1 ] == '[' ) )
                    {
                        int j = i + 2;

                        StringUI.Clear();

                        while ( ( j < text.Length ) && ( s[ j ] != ']' ) )
                            StringUI.Add( s[ j++ ] );

                        if ( ( ( j + 1 ) < text.Length ) && ( s[ j + 1 ] == ']' ) )
                        {
                            // valid format
                            int fontIconIndex = _UI.Store_FontIcon.Get( StringUI );

                            if ( fontIconIndex != -1 )
                            {
                                // add to list
                                FontIcon fontIcon = _UI.Store_FontIcon.Get( fontIconIndex );

                                FontSprite* pSprite = ( pSpriteStart + SpriteList.RenderEnd++ );

                                pSprite->Character = (char)0xffff;

                                pSprite->Position.X = x;
                                pSprite->Position.Y = y - ( ( ( charHeight * fontIcon.Scale ) - charHeight ) * 0.5f ) * multY;
                                pSprite->Position.Z = Position.Z;

                                float heightScaled = charHeight * fontIcon.Scale;
                                pSprite->Size.X = heightScaled * fontIcon.AspectRatio;
                                pSprite->Size.Y = heightScaled;

                                fixed ( SpriteColor* pColor = &fontIcon.Color )
                                {
                                    pSprite->Colors.CopyA( ref Colors );
                                    pSprite->Colors.MultA( pColor->A );

                                    pSprite->Colors.R( pColor->R );
                                    pSprite->Colors.G( pColor->G );
                                    pSprite->Colors.B( pColor->B );

                                    if ( Colors.PreMultipliedAlpha )
                                        pSprite->Colors.ToPremultiplied();
                                }

                                // set base texture
                                pSprite->Texture.TextureIndex = fontIcon.Texture.TextureIndex;
                                pSprite->Texture.PUV = fontIcon.Texture.PUV;
                                pSprite->Texture.SUV = fontIcon.Texture.SUV;

                                pSprite->BreakType = E_LetterBreakType.None;

                                pSprite->IconIndex = fontIconIndex;

                                // advance
                                x += pSprite->Size.X;

                                // advance string past the icon characters
                                i += ( 4 + StringUI.Length - 1 );
                            }
                        }
                    }
                    else
                    {
                        // add to list
                        FontSprite* pSprite = ( pSpriteStart + SpriteList.RenderEnd++ );

                        pSprite->Character = c;

                        pSprite->Position.X = x + ( pCharData->OffsetX * scale );
                        pSprite->Position.Y = y + ( pCharData->OffsetY * scale ) * multY;
                        pSprite->Position.Z = Position.Z;

                        pSprite->Size.X = pCharData->Width * scale;
                        pSprite->Size.Y = pCharData->Height * scale;

                        pSprite->Colors = Colors;

                        // set base texture
                        pSprite->Texture.TextureIndex = fontStyle.Font.TextureIndex;
                        pSprite->Texture.PUV.X = (float)pCharData->X / fontData.TextureWidth;
                        pSprite->Texture.PUV.Y = (float)pCharData->Y / fontData.TextureHeight;
                        pSprite->Texture.SUV.X = (float)pCharData->Width / fontData.TextureWidth;
                        pSprite->Texture.SUV.Y = (float)pCharData->Height / fontData.TextureHeight;

                        // second (optional) texture is set through the FontStyle when rendering

                        pSprite->BreakType = E_LetterBreakType.None;

                        pSprite->IconIndex = -1;

                        // advance
                        x += ( pCharData->AdvanceX * scale );

                        // kerning
                        if ( i != ( text.Length - 1 ) )
                            x += ( fontData.GetKerningAmount( c, s[ i + 1 ] ) * scale );
                    }
                }

                // check for wrapping
                if ( ( c != ' ' ) && ( wrapSizeX != 0.0f ) && ( ( x - startX ) > wrapSizeX ) )
                {
                    int iWrap = SpriteList.RenderEnd - 1;
                    FontSprite* pSpriteWrap = ( pSpriteStart + iWrap );

                    // search backwards until we find a place to wrap
                    while ( ( iWrap >= 0 ) && ( pSpriteWrap->BreakType != E_LetterBreakType.Wrap ) && ( pSpriteWrap->BreakType != E_LetterBreakType.Line ) )
                        pSpriteWrap = ( pSpriteStart + --iWrap );

                    bool wrapOnLine = false;

                    if ( iWrap != -1 )
                    {
                        if ( pSpriteWrap->BreakType == E_LetterBreakType.Line )
                            wrapOnLine = true; // word is longer than the wrap size
                        else
                            pSpriteWrap->BreakType = E_LetterBreakType.Line;
                    }
                    else
                    {
                        if ( SpriteList.RenderEnd > 1 )
                            wrapOnLine = true; // long first word with leading spaces, wtf
                    }

                    ++pSpriteWrap;

                    float diffX = pSpriteWrap->Position.X - startX;
                    float offsetX = x - pSpriteWrap->Position.X;

                    // shift the characters after the break point
                    for ( int j = ( iWrap + 1 ); j < SpriteList.RenderEnd; ++j )
                    {
                        pSpriteWrap->Position.X -= diffX;

                        if ( !wrapOnLine )
                            pSpriteWrap->Position.Y += ( lineHeight * multY );

                        ++pSpriteWrap;
                    }

                    ++numLines;

                    if ( !wrapOnLine )
                        y += ( lineHeight * multY );

                    x = startX + offsetX;
                }

                // tracking
                x += ( height * fontStyle.TrackingPercentage );
            }

            ( pSpriteStart + SpriteList.RenderEnd - 1 )->BreakType = E_LetterBreakType.Line;

            float totalHeight = ( ( numLines - 1 ) * lineHeight ) + charHeight;

            if ( processType == E_FontProcessType.Draw )
            {
                // align
                if ( ( Align != E_Align.TopLeft ) && ( Align != E_Align.None ) )
                {
                    Vector2 offset = _UI.Sprite.GetVertexOffsetAligned( 0, Align );

                    if ( ( Align == E_Align.MiddleLeft ) || ( Align == E_Align.BottomLeft ) )
                    {
                        // only just need to offset y
                        FontSprite* pSpriteToOffset = pSpriteStart;

                        for ( int i = 0; i < SpriteList.RenderEnd; ++i, ++pSpriteToOffset )
                            pSpriteToOffset->Position.Y -= ( totalHeight * offset.Y ) * multY;
                    }
                    else
                    {
                        // need to offset both x and y
                        int iLineStart = 0;

                        FontSprite* pSpriteLineEnd = pSpriteStart;

                        for ( int i = 0; i < SpriteList.RenderEnd; ++i, ++pSpriteLineEnd )
                        {
                            if ( pSpriteLineEnd->BreakType != E_LetterBreakType.Line )
                                continue;

                            float lineWidth = ( pSpriteLineEnd->Position.X + pSpriteLineEnd->Size.X ) - startX;

                            // offset every sprite on this line
                            FontSprite* pSpriteToOffset = ( pSpriteStart + iLineStart );

                            for ( int j = iLineStart; j <= i; ++j, ++pSpriteToOffset )
                            {
                                pSpriteToOffset->Position.X -= ( lineWidth * offset.X );
                                pSpriteToOffset->Position.Y -= ( totalHeight * offset.Y ) * multY;
                            }

                            iLineStart = i + 1;
                        }
                    }
                }

                // pre-render
                if ( FontEffects != null )
                {
                    for ( int i = 0; i < FontEffects.Count; ++i )
                        FontEffects[ i ].Process( SpriteList );

                    FontEffects = null;
                }

                // actual render
                fontStyle.Render( SpriteList, height );
            }

            return new Vector2( ( numLines == 1 ) ? ( x - startX ) : wrapSizeX, totalHeight );
            }
        }
예제 #3
0
        private unsafe Vector2 Process(ref StringProxy text, FontStyle fontStyle, float height, float wrapSizeX, E_FontProcessType processType)
        {
            if (text.Length == 0)
            {
                return(new Vector2());
            }

            SpriteList.Reset();

            SpriteList.RenderPass = RenderPass;
            SpriteList.Layer      = Layer;

            FontData fontData = fontStyle.Font.FontData;

            float startX = Position.X;
            float x      = startX;
            float y      = Position.Y;

            float scale      = height / fontData.FontHeight;
            float charHeight = fontData.LineHeight * scale;
            float lineHeight = charHeight * fontStyle.HeightPercentage;
            float multY      = _UI.Sprite.IsRenderPass3D(RenderPass) ? -1.0f : 1.0f;

            int numLines = 1;

            fixed(char *pString = text.String)
            fixed(FontSprite * pSpriteStart     = &SpriteList.Sprites[0])
            fixed(FontDataChar * pCharDataStart = &fontData.Characters[0])
            {
                char *s = (pString != null) ? pString : text.StringUI;

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

                    if (c == '\n')
                    {
                        ++numLines;
                        y += (lineHeight * multY);
                        x  = startX;

                        (pSpriteStart + SpriteList.RenderEnd - 1)->BreakType = E_LetterBreakType.Line;

                        continue;
                    }

                    int           characterIndex = fontData.GetCharacterIndex(c);
                    FontDataChar *pCharData      = (pCharDataStart + characterIndex);

                    if (c == ' ')
                    {
                        // mark as potential wrap point unless we've already wrapped here
                        FontSprite *pSpriteEnd = (pSpriteStart + SpriteList.RenderEnd - 1);

                        if ((SpriteList.RenderEnd != 0) && (pSpriteEnd->BreakType != E_LetterBreakType.Line))
                        {
                            pSpriteEnd->BreakType = E_LetterBreakType.Wrap;
                        }

                        // advance
                        x += (pCharData->AdvanceX * scale);
                    }
                    else
                    {
                        // check for icons
                        if (((i + 5) <= text.Length) && (c == '[') && (s[i + 1] == '['))
                        {
                            int j = i + 2;

                            StringUI.Clear();

                            while ((j < text.Length) && (s[j] != ']'))
                            {
                                StringUI.Add(s[j++]);
                            }

                            if (((j + 1) < text.Length) && (s[j + 1] == ']'))
                            {
                                // valid format
                                int fontIconIndex = _UI.Store_FontIcon.Get(StringUI);

                                if (fontIconIndex != -1)
                                {
                                    // add to list
                                    FontIcon fontIcon = _UI.Store_FontIcon.Get(fontIconIndex);

                                    FontSprite *pSprite = (pSpriteStart + SpriteList.RenderEnd++);

                                    pSprite->Character = (char)0xffff;

                                    pSprite->Position.X = x;
                                    pSprite->Position.Y = y - (((charHeight * fontIcon.Scale) - charHeight) * 0.5f) * multY;
                                    pSprite->Position.Z = Position.Z;

                                    float heightScaled = charHeight * fontIcon.Scale;
                                    pSprite->Size.X = heightScaled * fontIcon.AspectRatio;
                                    pSprite->Size.Y = heightScaled;

                                    fixed(SpriteColor *pColor = &fontIcon.Color)
                                    {
                                        pSprite->Colors.CopyA(ref Colors);
                                        pSprite->Colors.MultA(pColor->A);

                                        pSprite->Colors.R(pColor->R);
                                        pSprite->Colors.G(pColor->G);
                                        pSprite->Colors.B(pColor->B);

                                        if (Colors.PreMultipliedAlpha)
                                        {
                                            pSprite->Colors.ToPremultiplied();
                                        }
                                    }

                                    // set base texture
                                    pSprite->Texture.TextureIndex = fontIcon.Texture.TextureIndex;
                                    pSprite->Texture.PUV          = fontIcon.Texture.PUV;
                                    pSprite->Texture.SUV          = fontIcon.Texture.SUV;

                                    pSprite->BreakType = E_LetterBreakType.None;

                                    pSprite->IconIndex = fontIconIndex;

                                    // advance
                                    x += pSprite->Size.X;

                                    // advance string past the icon characters
                                    i += (4 + StringUI.Length - 1);
                                }
                            }
                        }
                        else
                        {
                            // add to list
                            FontSprite *pSprite = (pSpriteStart + SpriteList.RenderEnd++);

                            pSprite->Character = c;

                            pSprite->Position.X = x + (pCharData->OffsetX * scale);
                            pSprite->Position.Y = y + (pCharData->OffsetY * scale) * multY;
                            pSprite->Position.Z = Position.Z;

                            pSprite->Size.X = pCharData->Width * scale;
                            pSprite->Size.Y = pCharData->Height * scale;

                            pSprite->Colors = Colors;

                            // set base texture
                            pSprite->Texture.TextureIndex = fontStyle.Font.TextureIndex;
                            pSprite->Texture.PUV.X        = (float)pCharData->X / fontData.TextureWidth;
                            pSprite->Texture.PUV.Y        = (float)pCharData->Y / fontData.TextureHeight;
                            pSprite->Texture.SUV.X        = (float)pCharData->Width / fontData.TextureWidth;
                            pSprite->Texture.SUV.Y        = (float)pCharData->Height / fontData.TextureHeight;

                            // second (optional) texture is set through the FontStyle when rendering

                            pSprite->BreakType = E_LetterBreakType.None;

                            pSprite->IconIndex = -1;

                            // advance
                            x += (pCharData->AdvanceX * scale);

                            // kerning
                            if (i != (text.Length - 1))
                            {
                                x += (fontData.GetKerningAmount(c, s[i + 1]) * scale);
                            }
                        }
                    }

                    // check for wrapping
                    if ((c != ' ') && (wrapSizeX != 0.0f) && ((x - startX) > wrapSizeX))
                    {
                        int         iWrap       = SpriteList.RenderEnd - 1;
                        FontSprite *pSpriteWrap = (pSpriteStart + iWrap);

                        // search backwards until we find a place to wrap
                        while ((iWrap >= 0) && (pSpriteWrap->BreakType != E_LetterBreakType.Wrap) && (pSpriteWrap->BreakType != E_LetterBreakType.Line))
                        {
                            pSpriteWrap = (pSpriteStart + --iWrap);
                        }

                        bool wrapOnLine = false;

                        if (iWrap != -1)
                        {
                            if (pSpriteWrap->BreakType == E_LetterBreakType.Line)
                            {
                                wrapOnLine = true;                         // word is longer than the wrap size
                            }
                            else
                            {
                                pSpriteWrap->BreakType = E_LetterBreakType.Line;
                            }
                        }
                        else
                        {
                            if (SpriteList.RenderEnd > 1)
                            {
                                wrapOnLine = true;                         // long first word with leading spaces, wtf
                            }
                        }

                        ++pSpriteWrap;

                        float diffX   = pSpriteWrap->Position.X - startX;
                        float offsetX = x - pSpriteWrap->Position.X;

                        // shift the characters after the break point
                        for (int j = (iWrap + 1); j < SpriteList.RenderEnd; ++j)
                        {
                            pSpriteWrap->Position.X -= diffX;

                            if (!wrapOnLine)
                            {
                                pSpriteWrap->Position.Y += (lineHeight * multY);
                            }

                            ++pSpriteWrap;
                        }

                        ++numLines;

                        if (!wrapOnLine)
                        {
                            y += (lineHeight * multY);
                        }

                        x = startX + offsetX;
                    }

                    // tracking
                    x += (height * fontStyle.TrackingPercentage);
                }

                (pSpriteStart + SpriteList.RenderEnd - 1)->BreakType = E_LetterBreakType.Line;

                float totalHeight = ((numLines - 1) * lineHeight) + charHeight;

                if (processType == E_FontProcessType.Draw)
                {
                    // align
                    if ((Align != E_Align.TopLeft) && (Align != E_Align.None))
                    {
                        Vector2 offset = _UI.Sprite.GetVertexOffsetAligned(0, Align);

                        if ((Align == E_Align.MiddleLeft) || (Align == E_Align.BottomLeft))
                        {
                            // only just need to offset y
                            FontSprite *pSpriteToOffset = pSpriteStart;

                            for (int i = 0; i < SpriteList.RenderEnd; ++i, ++pSpriteToOffset)
                            {
                                pSpriteToOffset->Position.Y -= (totalHeight * offset.Y) * multY;
                            }
                        }
                        else
                        {
                            // need to offset both x and y
                            int iLineStart = 0;

                            FontSprite *pSpriteLineEnd = pSpriteStart;

                            for (int i = 0; i < SpriteList.RenderEnd; ++i, ++pSpriteLineEnd)
                            {
                                if (pSpriteLineEnd->BreakType != E_LetterBreakType.Line)
                                {
                                    continue;
                                }

                                float lineWidth = (pSpriteLineEnd->Position.X + pSpriteLineEnd->Size.X) - startX;

                                // offset every sprite on this line
                                FontSprite *pSpriteToOffset = (pSpriteStart + iLineStart);

                                for (int j = iLineStart; j <= i; ++j, ++pSpriteToOffset)
                                {
                                    pSpriteToOffset->Position.X -= (lineWidth * offset.X);
                                    pSpriteToOffset->Position.Y -= (totalHeight * offset.Y) * multY;
                                }

                                iLineStart = i + 1;
                            }
                        }
                    }

                    // pre-render
                    if (FontEffects != null)
                    {
                        for (int i = 0; i < FontEffects.Count; ++i)
                        {
                            FontEffects[i].Process(SpriteList);
                        }

                        FontEffects = null;
                    }

                    // actual render
                    fontStyle.Render(SpriteList, height);
                }

                return(new Vector2((numLines == 1) ? (x - startX) : wrapSizeX, totalHeight));
            }
        }