예제 #1
0
        void GetQuad(FontGlyph glyph, FontGlyph prevGlyph, GlyphCollection collection, float spacing, ref float x, ref float y, FontGlyphSquad *q)
        {
            if (prevGlyph != null)
            {
                float adv = 0;
                if (UseKernings && glyph.Font == prevGlyph.Font)
                {
                    adv = prevGlyph.Font.GetGlyphKernAdvance(prevGlyph.Index, glyph.Index) * glyph.Font.Scale;
                }

                x += (int)(adv + spacing + 0.5f);
            }

            float rx = 0;
            float ry = 0;

            rx    = x + glyph.XOffset;
            ry    = y + glyph.YOffset;
            q->X0 = rx;
            q->Y0 = ry;
            q->X1 = rx + glyph.Bounds.Width;
            q->Y1 = ry + glyph.Bounds.Height;
            q->S0 = glyph.Bounds.X * _itw;
            q->T0 = glyph.Bounds.Y * _ith;
            q->S1 = glyph.Bounds.Right * _itw;
            q->T1 = glyph.Bounds.Bottom * _ith;

            x += (int)(glyph.XAdvance / 10.0f + 0.5f);
        }
예제 #2
0
        FontGlyph GetGlyphWithoutBitmap(GlyphCollection collection, int codepoint)
        {
            FontGlyph glyph = null;

            if (collection.Glyphs.TryGetValue(codepoint, out glyph))
            {
                return(glyph);
            }

            Font font;
            var  g = GetCodepointIndex(codepoint, out font);

            if (g == 0)
            {
                collection.Glyphs[codepoint] = null;
                return(null);
            }

            int advance, lsb, x0, y0, x1, y1;

            font.BuildGlyphBitmap(g, FontSize, font.Scale, &advance, &lsb, &x0, &y0, &x1, &y1);

            var pad    = Math.Max(FontGlyph.PadFromBlur(BlurAmount), FontGlyph.PadFromBlur(StrokeAmount));
            var gw     = x1 - x0 + pad * 2;
            var gh     = y1 - y0 + pad * 2;
            var offset = FontGlyph.PadFromBlur(BlurAmount);

            glyph = new FontGlyph {
                Font      = font,
                Codepoint = codepoint,
                Size      = FontSize,
                Index     = g,
                Bounds    = new Rectangle(0, 0, gw, gh),
                XAdvance  = (int)(font.Scale * advance * 10.0f),
                XOffset   = x0 - offset,
                YOffset   = y0 - offset
            };

            collection.Glyphs[codepoint] = glyph;

            return(glyph);
        }
예제 #3
0
        public void RenderGlyph(GraphicsDevice device, FontGlyph glyph, int blurAmount, int strokeAmount)
        {
            var pad = Math.Max(FontGlyph.PadFromBlur(blurAmount), FontGlyph.PadFromBlur(strokeAmount));

            // Render glyph to byte buffer
            var bufferSize = glyph.Bounds.Width * glyph.Bounds.Height;
            var buffer     = _byteBuffer;

            if ((buffer == null) || (buffer.Length < bufferSize))
            {
                buffer      = new byte[bufferSize];
                _byteBuffer = buffer;
            }
            Array.Clear(buffer, 0, bufferSize);

            var g           = glyph.Index;
            var colorSize   = glyph.Bounds.Width * glyph.Bounds.Height;
            var colorBuffer = _colorBuffer;

            if ((colorBuffer == null) || (colorBuffer.Length < colorSize))
            {
                colorBuffer  = new Color[colorSize];
                _colorBuffer = colorBuffer;
            }

            fixed(byte *dst = &buffer[pad + pad *glyph.Bounds.Width])
            {
                glyph.Font.RenderGlyphBitmap(dst,
                                             glyph.Bounds.Width - pad * 2,
                                             glyph.Bounds.Height - pad * 2,
                                             glyph.Bounds.Width,
                                             g);
            }

            if (strokeAmount > 0)
            {
                var width  = glyph.Bounds.Width;
                var top    = width * strokeAmount;
                var bottom = (glyph.Bounds.Height - strokeAmount) * glyph.Bounds.Width;
                var right  = glyph.Bounds.Width - strokeAmount;
                var left   = strokeAmount;

                byte d;
                for (var i = 0; i < colorSize; ++i)
                {
                    var col   = buffer[i];
                    var black = 0;
                    if (col == 255)
                    {
                        colorBuffer[i].R = colorBuffer[i].G = colorBuffer[i].B = colorBuffer[i].A = 255;
                        continue;
                    }

                    if (i >= top)
                    {
                        black = buffer[i - top];
                    }
                    if (i < bottom)
                    {
                        d     = buffer[i + top];
                        black = ((255 - d) * black + 255 * d) / 255;
                    }
                    if (i % width >= left)
                    {
                        d     = buffer[i - strokeAmount];
                        black = ((255 - d) * black + 255 * d) / 255;
                    }
                    if (i % width < right)
                    {
                        d     = buffer[i + strokeAmount];
                        black = ((255 - d) * black + 255 * d) / 255;
                    }

                    if (black == 0)
                    {
                        if (col == 0)
                        {
                            colorBuffer[i].R = colorBuffer[i].G = colorBuffer[i].B = colorBuffer[i].A = 0; //black transparency to suit stroke
                            continue;
                        }
#if PREMULTIPLIEDALPHA
                        colorBuffer[i].R = colorBuffer[i].G = colorBuffer[i].B = colorBuffer[i].A = col;
#else
                        colorBuffer[i].R = colorBuffer[i].G = colorBuffer[i].B = 255;
                        colorBuffer[i].A = col;
#endif
                    }
                    else
                    {
                        if (col == 0)
                        {
                            colorBuffer[i].R = colorBuffer[i].G = colorBuffer[i].B = 0;
                            colorBuffer[i].A = (byte)black;
                            continue;
                        }

#if PREMULTIPLIEDALPHA
                        var alpha = ((255 - col) * black + 255 * col) / 255;
                        colorBuffer[i].R = colorBuffer[i].G = colorBuffer[i].B = (byte)((alpha * col) / 255);
                        colorBuffer[i].A = (byte)alpha;
#else
                        colorBuffer[i].R = colorBuffer[i].G = colorBuffer[i].B = col;
                        colorBuffer[i].A = (byte)(((255 - col) * black + 255 * col) / 255);
#endif
                    }
                }
            }
            else
            {
                if (blurAmount > 0)
                {
                    fixed(byte *bdst = &buffer[0])
                    {
                        Blur(bdst, glyph.Bounds.Width, glyph.Bounds.Height, glyph.Bounds.Width, blurAmount);
                    }
                }

                for (var i = 0; i < colorSize; ++i)
                {
                    var c = buffer[i];
#if PREMULTIPLIEDALPHA
                    colorBuffer[i].R = colorBuffer[i].G = colorBuffer[i].B = colorBuffer[i].A = c;
#else
                    colorBuffer[i].R = colorBuffer[i].G = colorBuffer[i].B = 255;
                    colorBuffer[i].A = c;
#endif
                }
            }

            // Write to texture
            if (Texture == null)
            {
                Texture = new Texture2D(device, Width, Height);
            }
#if TEXTURESETDATAEXT
            fixed(Color *p = colorBuffer)
#if FNA
            Texture.SetDataPointerEXT(0, glyph.Bounds, (IntPtr)p, colorSize * sizeof(Color));
#else
            Texture.SetDataEXT(0, 0, glyph.Bounds, (IntPtr)p, colorSize * sizeof(Color));
#endif
#else
            Texture.SetData(0, 0, glyph.Bounds, colorBuffer, 0, colorSize);
#endif
        }
예제 #4
0
        public float TextBounds(float x, float y, StringBuilder str, ref Bounds bounds)
        {
            if (str == null || str.Length <= 0)
            {
                return(0.0f);
            }

            var collection = GetGlyphsCollection(FontSize);

            // Determine ascent and lineHeight from first character
            float ascent = 0, lineHeight = 0;

            for (var i = 0; i < str.Length; i += StringBuilderIsSurrogatePair(str, i) ? 2 : 1)
            {
                var codepoint = StringBuilderConvertToUtf32(str, i);

                var glyph = GetGlyph(null, collection, codepoint);
                if (glyph == null)
                {
                    continue;
                }

                ascent     = glyph.Font.Ascent;
                lineHeight = glyph.Font.LineHeight;
                break;
            }


            var   q       = new FontGlyphSquad();
            float startx  = 0;
            float advance = 0;

            y += ascent;

            float minx, maxx, miny, maxy;

            minx   = maxx = x;
            miny   = maxy = y;
            startx = x;

            FontGlyph prevGlyph = null;

            for (var i = 0; i < str.Length; i += StringBuilderIsSurrogatePair(str, i) ? 2 : 1)
            {
                var codepoint = StringBuilderConvertToUtf32(str, i);

                if (codepoint == '\n')
                {
                    x         = startx;
                    y        += lineHeight;
                    prevGlyph = null;
                    continue;
                }

                var glyph = GetGlyph(null, collection, codepoint);
                if (glyph == null)
                {
                    continue;
                }

                GetQuad(glyph, prevGlyph, collection, Spacing, ref x, ref y, &q);
                if (q.X0 < minx)
                {
                    minx = q.X0;
                }
                if (x > maxx)
                {
                    maxx = x;
                }
                if (q.Y0 < miny)
                {
                    miny = q.Y0;
                }
                if (q.Y1 > maxy)
                {
                    maxy = q.Y1;
                }

                prevGlyph = glyph;
            }

            advance = x - startx;

            bounds.X  = minx;
            bounds.Y  = miny;
            bounds.X2 = maxx;
            bounds.Y2 = maxy;

            return(advance);
        }
예제 #5
0
        public float DrawText(SpriteBatch batch, float x, float y, string str, float depth, Color color, Vector2 origin, float scaleX, float scaleY, SpriteEffects spriteEffects)
        {
            if (string.IsNullOrEmpty(str))
            {
                return(0.0f);
            }

            var collection = GetGlyphsCollection(FontSize);

            // Determine ascent and lineHeight from first character
            float ascent = 0, lineHeight = 0;

            for (var i = 0; i < str.Length; i += char.IsSurrogatePair(str, i) ? 2 : 1)
            {
                var codepoint = char.ConvertToUtf32(str, i);

                var glyph = GetGlyph(batch.GraphicsDevice, collection, codepoint);
                if (glyph == null)
                {
                    continue;
                }

                ascent     = glyph.Font.Ascent;
                lineHeight = glyph.Font.LineHeight;
                break;
            }

            var q = new FontGlyphSquad();

            var originX = -origin.X;
            var originY = -origin.Y;

            originY += ascent;

            FontGlyph prevGlyph = null;

            for (var i = 0; i < str.Length; i += char.IsSurrogatePair(str, i) ? 2 : 1)
            {
                var codepoint = char.ConvertToUtf32(str, i);

                if (codepoint == '\n')
                {
                    originX   = 0.0f;
                    originY  += lineHeight;
                    prevGlyph = null;
                    continue;
                }

                var glyph = GetGlyph(batch.GraphicsDevice, collection, codepoint);
                if (glyph == null)
                {
                    continue;
                }

                GetQuad(glyph, prevGlyph, collection, Spacing, ref originX, ref originY, &q);

                var sourceRect = new Rectangle((int)(q.S0 * _size.X),
                                               (int)(q.T0 * _size.Y),
                                               (int)((q.S1 - q.S0) * _size.X),
                                               (int)((q.T1 - q.T0) * _size.Y));

                batch.Draw(glyph.Atlas.Texture,
                           new Vector2(x + q.X0 * scaleX, y + q.Y0 * scaleY),
                           sourceRect,
                           color,
                           0f,
                           Vector2.Zero,
                           new Vector2(scaleX, scaleY),
                           spriteEffects,
                           depth);

                prevGlyph = glyph;
            }

            return(x);
        }
예제 #6
0
        public float DrawText(SpriteBatch batch, float x, float y, StringBuilder str, float depth)
        {
            if (str.Length == 0)
            {
                return(0.0f);
            }

            var collection = GetGlyphsCollection(FontSize);

            // Determine ascent and lineHeight from first character
            float ascent = 0, lineHeight = 0;

            for (var i = 0; i < str.Length; i += StringBuilderIsSurrogatePair(str, i) ? 2 : 1)
            {
                var codepoint = StringBuilderConvertToUtf32(str, i);

                var glyph = GetGlyph(batch.GraphicsDevice, collection, codepoint);
                if (glyph == null)
                {
                    continue;
                }

                ascent     = glyph.Font.Ascent;
                lineHeight = glyph.Font.LineHeight;
                break;
            }

            var q = new FontGlyphSquad();

            var originX = 0.0f;
            var originY = 0.0f;

            originY += ascent;

            FontGlyph prevGlyph = null;

            for (var i = 0; i < str.Length; i += StringBuilderIsSurrogatePair(str, i) ? 2 : 1)
            {
                var codepoint = StringBuilderConvertToUtf32(str, i);

                if (codepoint == '\n')
                {
                    originX   = 0.0f;
                    originY  += lineHeight;
                    prevGlyph = null;
                    continue;
                }

                var glyph = GetGlyph(batch.GraphicsDevice, collection, codepoint);
                if (glyph == null)
                {
                    continue;
                }

                GetQuad(glyph, prevGlyph, collection, Spacing, ref originX, ref originY, &q);

                q.X0 = (int)(q.X0 * Scale.X);
                q.X1 = (int)(q.X1 * Scale.X);
                q.Y0 = (int)(q.Y0 * Scale.Y);
                q.Y1 = (int)(q.Y1 * Scale.Y);

                var destRect = new Rectangle((int)(x + q.X0),
                                             (int)(y + q.Y0),
                                             (int)(q.X1 - q.X0),
                                             (int)(q.Y1 - q.Y0));

                var sourceRect = new Rectangle((int)(q.S0 * _size.X),
                                               (int)(q.T0 * _size.Y),
                                               (int)((q.S1 - q.S0) * _size.X),
                                               (int)((q.T1 - q.T0) * _size.Y));

                batch.Draw(glyph.Atlas.Texture,
                           destRect,
                           sourceRect,
                           Color,
                           0f,
                           Vector2.Zero,
                           SpriteEffects.None,
                           depth);

                prevGlyph = glyph;
            }

            return(x);
        }