Esempio n. 1
0
        public void GetQuad(Font font, int prevGlyphIndex, FontGlyph *glyph, float scale, float spacing, ref float x,
                            ref float y, FontGlyphSquad *q)
        {
            float rx   = 0;
            float ry   = 0;
            float xoff = 0;
            float yoff = 0;
            float x0   = 0;
            float y0   = 0;
            float x1   = 0;
            float y1   = 0;

            if (prevGlyphIndex != -1)
            {
                var adv = font.FontInfo.__tt_getGlyphKernAdvance(prevGlyphIndex, glyph->Index) * scale;
                x += (int)(adv + spacing + 0.5f);
            }

            xoff = (short)(glyph->XOffset + 1);
            yoff = (short)(glyph->YOffset + 1);
            x0   = glyph->X0 + 1;
            y0   = glyph->Y0 + 1;
            x1   = glyph->X1 - 1;
            y1   = glyph->Y1 - 1;
            if ((_params_.Flags & FONS_ZERO_TOPLEFT) != 0)
            {
                rx    = (int)(x + xoff);
                ry    = (int)(y + yoff);
                q->X0 = rx;
                q->Y0 = ry;
                q->X1 = rx + x1 - x0;
                q->Y1 = ry + y1 - y0;
                q->S0 = x0 * _itw;
                q->T0 = y0 * _ith;
                q->S1 = x1 * _itw;
                q->T1 = y1 * _ith;
            }
            else
            {
                rx    = (int)(x + xoff);
                ry    = (int)(y - yoff);
                q->X0 = rx;
                q->Y0 = ry;
                q->X1 = rx + x1 - x0;
                q->Y1 = ry - y1 + y0;
                q->S0 = x0 * _itw;
                q->T0 = y0 * _ith;
                q->S1 = x1 * _itw;
                q->T1 = y1 * _ith;
            }

            x += (int)(glyph->XAdvance / 10.0f + 0.5f);
        }
Esempio n. 2
0
        public float TextBounds(float x, float y, StringSegment str, ref Bounds bounds)
        {
            var        state          = GetState();
            var        q              = new FontGlyphSquad();
            FontGlyph *glyph          = null;
            var        prevGlyphIndex = -1;
            var        isize          = (short)(state.Size * 10.0f);
            var        iblur          = (short)state.Blur;
            float      scale          = 0;
            Font       font;
            float      startx  = 0;
            float      advance = 0;
            float      minx    = 0;
            float      miny    = 0;
            float      maxx    = 0;
            float      maxy    = 0;

            if (state.Font < 0 || state.Font >= _fontsNumber)
            {
                return(0);
            }
            font = _fonts[state.Font];
            if (font.Data == null)
            {
                return(0);
            }
            scale  = font.FontInfo.__tt_getPixelHeightScale(isize / 10.0f);
            y     += GetVertAlign(font, state.Align, isize);
            minx   = maxx = x;
            miny   = maxy = y;
            startx = x;
            for (int i = 0; i < str.Length; i += Char.IsSurrogatePair(str.String, i + str.Location) ? 2 : 1)
            {
                var codepoint = Char.ConvertToUtf32(str.String, i + str.Location);
                glyph = GetGlyph(font, codepoint, isize, iblur, FONS_GLYPH_BITMAP_OPTIONAL);
                if (glyph != null)
                {
                    GetQuad(font, prevGlyphIndex, glyph, scale, state.Spacing, ref x, ref y, &q);
                    if (q.X0 < minx)
                    {
                        minx = q.X0;
                    }
                    if (q.X1 > maxx)
                    {
                        maxx = q.X1;
                    }
                    if ((_params_.Flags & FONS_ZERO_TOPLEFT) != 0)
                    {
                        if (q.Y0 < miny)
                        {
                            miny = q.Y0;
                        }
                        if (q.Y1 > maxy)
                        {
                            maxy = q.Y1;
                        }
                    }
                    else
                    {
                        if (q.Y1 < miny)
                        {
                            miny = q.Y1;
                        }
                        if (q.Y0 > maxy)
                        {
                            maxy = q.Y0;
                        }
                    }
                }

                prevGlyphIndex = glyph != null ? glyph->Index : -1;
            }

            advance = x - startx;
            if ((state.Align & Alignment.Left) != 0)
            {
            }
            else if ((state.Align & Alignment.Right) != 0)
            {
                minx -= advance;
                maxx -= advance;
            }
            else if ((state.Align & Alignment.Center) != 0)
            {
                minx -= advance * 0.5f;
                maxx -= advance * 0.5f;
            }

            bounds.b1 = minx;
            bounds.b2 = miny;
            bounds.b3 = maxx;
            bounds.b4 = maxy;

            return(advance);
        }
Esempio n. 3
0
        public FontGlyph *GetGlyph(Font font, int codepoint, short isize, short iblur, int bitmapOption)
        {
            var        i          = 0;
            var        g          = 0;
            var        advance    = 0;
            var        lsb        = 0;
            var        x0         = 0;
            var        y0         = 0;
            var        x1         = 0;
            var        y1         = 0;
            var        gw         = 0;
            var        gh         = 0;
            var        gx         = 0;
            var        gy         = 0;
            var        x          = 0;
            var        y          = 0;
            float      scale      = 0;
            FontGlyph *glyph      = null;
            int        h          = 0;
            var        size       = isize / 10.0f;
            var        pad        = 0;
            var        added      = 0;
            var        renderFont = font;

            if (isize < 2)
            {
                return(null);
            }
            if (iblur > 20)
            {
                iblur = 20;
            }
            pad           = iblur + 2;
            _scratchCount = 0;
            h             = HashInt(codepoint) & (256 - 1);
            i             = font.Lut[h];
            while (i != -1)
            {
                if (font.Glyphs[i].Codepoint == codepoint && font.Glyphs[i].Size == isize &&
                    font.Glyphs[i].Blur == iblur)
                {
                    glyph = &font.Glyphs[i];
                    if (bitmapOption == FONS_GLYPH_BITMAP_OPTIONAL || glyph->X0 >= 0 && glyph->Y0 >= 0)
                    {
                        return(glyph);
                    }
                    break;
                }

                i = font.Glyphs[i].Next;
            }

            g = font.FontInfo.__tt_getGlyphIndex((int)codepoint);
            if (g == 0)
            {
                for (i = 0; i < font.FallbacksCount; ++i)
                {
                    var fallbackFont  = _fonts[font.Fallbacks[i]];
                    var fallbackIndex = fallbackFont.FontInfo.__tt_getGlyphIndex((int)codepoint);
                    if (fallbackIndex != 0)
                    {
                        g          = fallbackIndex;
                        renderFont = fallbackFont;
                        break;
                    }
                }
            }

            scale = renderFont.FontInfo.__tt_getPixelHeightScale(size);
            renderFont.FontInfo.__tt_buildGlyphBitmap(g, size, scale, &advance, &lsb, &x0, &y0, &x1, &y1);
            gw = x1 - x0 + pad * 2;
            gh = y1 - y0 + pad * 2;
            if (bitmapOption == FONS_GLYPH_BITMAP_REQUIRED)
            {
                added = atlas.AddRect(gw, gh, &gx, &gy);
                if (added == 0)
                {
                    throw new Exception("FONS_ATLAS_FULL");
                }
            }
            else
            {
                gx = -1;
                gy = -1;
            }

            if (glyph == null)
            {
                glyph            = AllocGlyph(font);
                glyph->Codepoint = codepoint;
                glyph->Size      = isize;
                glyph->Blur      = iblur;
                glyph->Next      = 0;
                glyph->Next      = font.Lut[h];
                font.Lut[h]      = font.GlyphsNumber - 1;
            }

            glyph->Index    = g;
            glyph->X0       = (short)gx;
            glyph->Y0       = (short)gy;
            glyph->X1       = (short)(glyph->X0 + gw);
            glyph->Y1       = (short)(glyph->Y0 + gh);
            glyph->XAdvance = (short)(scale * advance * 10.0f);
            glyph->XOffset  = (short)(x0 - pad);
            glyph->YOffset  = (short)(y0 - pad);
            if (bitmapOption == FONS_GLYPH_BITMAP_OPTIONAL)
            {
                return(glyph);

                fixed(byte *dst = &_texData[glyph->X0 + pad + (glyph->Y0 + pad) * _params_.Width])
                {
                    renderFont.FontInfo.__tt_renderGlyphBitmap(dst, gw - pad * 2, gh - pad * 2, _params_.Width, scale,
                                                               scale, g);
                }

                fixed(byte *dst = &_texData[glyph->X0 + glyph->Y0 *_params_.Width])
                {
                    for (y = 0; y < gh; y++)
                    {
                        dst[y * _params_.Width]          = 0;
                        dst[gw - 1 + y * _params_.Width] = 0;
                    }

                    for (x = 0; x < gw; x++)
                    {
                        dst[x] = 0;
                        dst[x + (gh - 1) * _params_.Width] = 0;
                    }
                }

                if (iblur > 0)
                {
                    _scratchCount = 0;
                    fixed(byte *bdst = &_texData[glyph->X0 + glyph->Y0 *_params_.Width])
                    {
                        Blur(bdst, gw, gh, _params_.Width, iblur);
                    }
                }

                _dirtyRect[0] = Mini(_dirtyRect[0], glyph->X0);
                _dirtyRect[1] = Mini(_dirtyRect[1], glyph->Y0);
                _dirtyRect[2] = Maxi(_dirtyRect[2], glyph->X1);
                _dirtyRect[3] = Maxi(_dirtyRect[3], glyph->Y1);
                return(glyph);
        }