Ejemplo n.º 1
0
    float GetStringWidth(string str)
    {
        TGlyph prevGlyph = null;
        float  width     = 0f;

        foreach (char c in str)
        {
            int    charCode = (int)c;
            TGlyph glyph    = Font.Glyphs.Get(charCode);

            if (glyph == null)
            {
                continue;
            }

            float kerning = 0f;

            if (prevGlyph != null)
            {
                kerning = prevGlyph.GetKerning(charCode);
            }

            width    += glyph.xAdvance * Size + Tracking + kerning;
            prevGlyph = glyph;
        }

        return(width);
    }
        void compute_string_bbox(out ANT_BBox abbox)
        {
            ANT_BBox bbox       = new ANT_BBox();
            ANT_BBox glyph_bbox = new ANT_BBox();


            //  initialize string bbox to "empty" values
            bbox.xMin = bbox.yMin = 32000;
            bbox.xMax = bbox.yMax = -32000;

            //  for each glyph image, compute its bounding box,
            //  translate it, and grow the string bbox
            for (int n = 0; n < num_glyphs; n++)
            {
                TGlyph glyph = glyphs[n];

                ANT.ANT_Glyph_Get_CBox(glyph.image, ANT_Glyph_BBox_Mode.ANT_GLYPH_BBOX_PIXELS, glyph_bbox);

                glyph_bbox.xMin += glyph.pos.x;
                glyph_bbox.xMax += glyph.pos.x;
                glyph_bbox.yMin += glyph.pos.y;
                glyph_bbox.yMax += glyph.pos.y;

                if (glyph_bbox.xMin < bbox.xMin)
                {
                    bbox.xMin = glyph_bbox.xMin;
                }

                if (glyph_bbox.yMin < bbox.yMin)
                {
                    bbox.yMin = glyph_bbox.yMin;
                }

                if (glyph_bbox.xMax > bbox.xMax)
                {
                    bbox.xMax = glyph_bbox.xMax;
                }

                if (glyph_bbox.yMax > bbox.yMax)
                {
                    bbox.yMax = glyph_bbox.yMax;
                }
            }

            //  check that we really grew the string bbox
            if (bbox.xMin > bbox.xMax)
            {
                bbox.xMin = 0;
                bbox.yMin = 0;
                bbox.xMax = 0;
                bbox.yMax = 0;
            }

            //  return string bbox
            abbox = bbox;
        }
Ejemplo n.º 3
0
    float BlitString(string str, float cursorX, float cursorY, List <int> vertexPointers = null)
    {
        TGlyph prevGlyph = null;

        foreach (char c in str)
        {
            int    charCode = (int)c;
            TGlyph glyph    = Font.Glyphs.Get(charCode);

            if (glyph == null)
            {
                continue;
            }

            if (charCode == 32)
            {
                cursorX += glyph.xAdvance * Size + Tracking;
                continue;
            }

            float kerning = 0f;

            if (prevGlyph != null)
            {
                kerning = prevGlyph.GetKerning(charCode);
            }

            if (vertexPointers != null)
            {
                vertexPointers.Add(m_Vertices.Count);
            }

            BlitQuad(
                new Rect(
                    cursorX + glyph.xOffset * Size + kerning,
                    cursorY + glyph.yOffset * Size,
                    glyph.rect.width * Size,
                    glyph.rect.height * Size
                    ),
                glyph
                );

            cursorX  += glyph.xAdvance * Size + Tracking + kerning;
            prevGlyph = glyph;
        }

        if (cursorX > Width)
        {
            Width = cursorX;
        }

        return(cursorX);
    }
Ejemplo n.º 4
0
    float GetStringWidth(string str)
    {
        TGlyph prevGlyph     = null;
        bool   inControlCode = false;
        float  width         = 0f;

        foreach (char c in str)
        {
            int charCode = (int)c;

            if (inControlCode)
            {
                inControlCode = false;

                if (charCode >= 48 && charCode <= 57)                 // 0-9
                {
                    continue;
                }
            }
            else
            {
                if (charCode == 92)                 // Backslash
                {
                    inControlCode = true;
                    continue;
                }
            }

            TGlyph glyph = Font.Glyphs.Get(charCode);

            if (glyph == null)
            {
                continue;
            }

            float kerning = 0f;

            if (prevGlyph != null)
            {
                kerning = prevGlyph.GetKerning(charCode) * Size;
            }

            width    += glyph.xAdvance * Size + Tracking + kerning;
            prevGlyph = glyph;
        }

        return(width);
    }
Ejemplo n.º 5
0
    void parseKernings(XmlNode kerningsNode)
    {
        foreach (XmlNode node in kerningsNode.ChildNodes)
        {
            int               first   = Convert.ToInt32(attribute(node, "first"));
            int               second  = Convert.ToInt32(attribute(node, "second"));
            float             amount  = Convert.ToSingle(attribute(node, "amount")) / Atlas.width * HScale;
            TGlyph            glyph   = Glyphs.Get(first);
            KerningDictionary kerning = glyph.kerning;

            if (kerning == null)
            {
                kerning       = new KerningDictionary();
                glyph.kerning = kerning;
            }

            kerning.Set(second, amount);
            KerningPairs++;
        }
    }
Ejemplo n.º 6
0
    void BlitQuad(Rect quad, TGlyph glyph)
    {
        int index = m_Vertices.Count;
        Rect uvs = glyph.rect;

        m_Vertices.Add(new Vector3(quad.x, -quad.y, 0f));
        m_Vertices.Add(new Vector3(quad.x + quad.width, -quad.y, 0f));
        m_Vertices.Add(new Vector3(quad.x + quad.width, -quad.y - quad.height, 0f));
        m_Vertices.Add(new Vector3(quad.x, -quad.y - quad.height, 0f));

        m_UVs.Add(new Vector2(uvs.x / Font.HScale, 1 - uvs.y / Font.VScale));
        m_UVs.Add(new Vector2((uvs.x + uvs.width) / Font.HScale, 1 - uvs.y / Font.VScale));
        m_UVs.Add(new Vector2((uvs.x + uvs.width) / Font.HScale, 1 - (uvs.y + uvs.height) / Font.VScale));
        m_UVs.Add(new Vector2(uvs.x / Font.HScale, 1 - (uvs.y + uvs.height) / Font.VScale));

        switch (FillMode)
        {
            case TFillMode.SingleColor:
                m_Colors.Add(ColorTopLeft);
                m_Colors.Add(ColorTopLeft);
                m_Colors.Add(ColorTopLeft);
                m_Colors.Add(ColorTopLeft);
                break;
            case TFillMode.VerticalGradient:
                m_Colors.Add(ColorTopLeft);
                m_Colors.Add(ColorTopLeft);
                m_Colors.Add(ColorBottomLeft);
                m_Colors.Add(ColorBottomLeft);
                break;
            case TFillMode.HorizontalGradient:
                m_Colors.Add(ColorTopLeft);
                m_Colors.Add(ColorBottomLeft);
                m_Colors.Add(ColorBottomLeft);
                m_Colors.Add(ColorTopLeft);
                break;
            case TFillMode.QuadGradient:
                m_Colors.Add(ColorTopLeft);
                m_Colors.Add(ColorTopRight);
                m_Colors.Add(ColorBottomRight);
                m_Colors.Add(ColorBottomLeft);
                break;
            case TFillMode.StretchedTexture:
                m_UVs2.Add(new Vector2(0f, 1f));
                m_UVs2.Add(new Vector2(1f, 1f));
                m_UVs2.Add(new Vector2(1f, 0f));
                m_UVs2.Add(new Vector2(0f, 0f));
                break;
            case TFillMode.ProjectedTexture:
                float h = uvs.height / Font.LineHeight;
                float w = uvs.width / Font.LineHeight;
                m_UVs2.Add(new Vector2(glyph.xOffset, h - glyph.yOffset));
                m_UVs2.Add(new Vector2(w - glyph.xOffset, h - glyph.yOffset));
                m_UVs2.Add(new Vector2(w - glyph.xOffset, glyph.yOffset));
                m_UVs2.Add(new Vector2(glyph.xOffset, glyph.yOffset));
                break;
            default:
                break;
        }

        m_SubmeshTriangles[_currentMaterial].Add(index);
        m_SubmeshTriangles[_currentMaterial].Add(index + 1);
        m_SubmeshTriangles[_currentMaterial].Add(index + 2);
        m_SubmeshTriangles[_currentMaterial].Add(index);
        m_SubmeshTriangles[_currentMaterial].Add(index + 2);
        m_SubmeshTriangles[_currentMaterial].Add(index + 3);
    }
Ejemplo n.º 7
0
    void BlitQuad(Rect quad, TGlyph glyph)
    {
        int  index = m_Vertices.Count;
        Rect uvs   = glyph.rect;

        m_Vertices.Add(new Vector3(quad.x, -quad.y, 0f));
        m_Vertices.Add(new Vector3(quad.x + quad.width, -quad.y, 0f));
        m_Vertices.Add(new Vector3(quad.x + quad.width, -quad.y - quad.height, 0f));
        m_Vertices.Add(new Vector3(quad.x, -quad.y - quad.height, 0f));

        m_UVs.Add(new Vector2(uvs.x / Font.HScale, 1 - uvs.y / Font.VScale));
        m_UVs.Add(new Vector2((uvs.x + uvs.width) / Font.HScale, 1 - uvs.y / Font.VScale));
        m_UVs.Add(new Vector2((uvs.x + uvs.width) / Font.HScale, 1 - (uvs.y + uvs.height) / Font.VScale));
        m_UVs.Add(new Vector2(uvs.x / Font.HScale, 1 - (uvs.y + uvs.height) / Font.VScale));

        switch (FillMode)
        {
        case TFillMode.SingleColor:
            m_Colors.Add(ColorTopLeft);
            m_Colors.Add(ColorTopLeft);
            m_Colors.Add(ColorTopLeft);
            m_Colors.Add(ColorTopLeft);
            break;

        case TFillMode.VerticalGradient:
            m_Colors.Add(ColorTopLeft);
            m_Colors.Add(ColorTopLeft);
            m_Colors.Add(ColorBottomLeft);
            m_Colors.Add(ColorBottomLeft);
            break;

        case TFillMode.HorizontalGradient:
            m_Colors.Add(ColorTopLeft);
            m_Colors.Add(ColorBottomLeft);
            m_Colors.Add(ColorBottomLeft);
            m_Colors.Add(ColorTopLeft);
            break;

        case TFillMode.QuadGradient:
            m_Colors.Add(ColorTopLeft);
            m_Colors.Add(ColorTopRight);
            m_Colors.Add(ColorBottomRight);
            m_Colors.Add(ColorBottomLeft);
            break;

        case TFillMode.StretchedTexture:
            m_UVs2.Add(new Vector2(0f, 1f));
            m_UVs2.Add(new Vector2(1f, 1f));
            m_UVs2.Add(new Vector2(1f, 0f));
            m_UVs2.Add(new Vector2(0f, 0f));
            break;

        case TFillMode.ProjectedTexture:
            float h = uvs.height / Font.LineHeight;
            float w = uvs.width / Font.LineHeight;
            m_UVs2.Add(new Vector2(glyph.xOffset, h - glyph.yOffset));
            m_UVs2.Add(new Vector2(w - glyph.xOffset, h - glyph.yOffset));
            m_UVs2.Add(new Vector2(w - glyph.xOffset, glyph.yOffset));
            m_UVs2.Add(new Vector2(glyph.xOffset, glyph.yOffset));
            break;

        default:
            break;
        }

        m_SubmeshTriangles[_currentMaterial].Add(index);
        m_SubmeshTriangles[_currentMaterial].Add(index + 1);
        m_SubmeshTriangles[_currentMaterial].Add(index + 2);
        m_SubmeshTriangles[_currentMaterial].Add(index);
        m_SubmeshTriangles[_currentMaterial].Add(index + 2);
        m_SubmeshTriangles[_currentMaterial].Add(index + 3);
    }
Ejemplo n.º 8
0
    float BlitString(string str, float cursorX, float cursorY, List <int> vertexPointers = null)
    {
        TGlyph prevGlyph = null;
        Rect   r;
        bool   inControlCode     = false;
        int    requestedMaterial = 0;

        foreach (char c in str)
        {
            int charCode = (int)c;

            if (inControlCode)
            {
                inControlCode = false;

                if (charCode >= 48 && charCode <= 57)                 // 0-9
                {
                    requestedMaterial = charCode - 48;

                    if (requestedMaterial < _materialCount)
                    {
                        _currentMaterial = requestedMaterial;
                    }
                    else
                    {
                        Debug.LogWarning(string.Format(
                                             "Requested material {0} out of range.", requestedMaterial
                                             ));
                    }

                    AddPlaceholderGlyphBounds();
                    continue;
                }
            }
            else
            {
                if (charCode == 92)                 // Backslash
                {
                    inControlCode = true;
                    AddPlaceholderGlyphBounds();
                    continue;
                }
            }

            TGlyph glyph = Font.Glyphs.Get(charCode);

            if (glyph == null)
            {
                continue;
            }

            if (charCode == 32)
            {
                // Assuming here that spaces should not be clickable.
                AddPlaceholderGlyphBounds();
                cursorX += glyph.xAdvance * Size + Tracking;
                continue;
            }

            float kerning = 0f;

            if (prevGlyph != null)
            {
                kerning = prevGlyph.GetKerning(charCode) * Size;
            }

            if (vertexPointers != null)
            {
                vertexPointers.Add(m_Vertices.Count);
            }

            r = new Rect(
                cursorX + glyph.xOffset * Size + kerning,
                cursorY + glyph.yOffset * Size,
                glyph.rect.width * Size,
                glyph.rect.height * Size
                );

            BlitQuad(r, glyph);

            // Click bounds for glyphs are based on allocated space, not rendered space.
            // Otherwise we'll end up with unclickable dead zones between glyphs.
            r.width = glyph.xAdvance * Size;
            // And Y coordinates are just not handled the same at all.
            r.y = -cursorY - r.height - glyph.yOffset * Size;

            StoreGlyphBounds(r);

            cursorX  += glyph.xAdvance * Size + Tracking + kerning;
            prevGlyph = glyph;
        }

        if (cursorX > Width)
        {
            Width = cursorX;
        }

        return(cursorX);
    }
        void DoWork()
        {
            ANT_Library library;
            ANT_Face    face;

            ANT_GlyphSlot slot;
            ANT_Error     error;

            string filename;
            string text;

            int num_chars;

            bool use_kerning;
            int  previous;
            int  pen_x, pen_y, n;


            filename  = Common.Example_AltNETType_FontFileName;
            text      = "AltNETType (transformation + centering + kerning)";// Common.Pangram;
            num_chars = text.Length;


            //  ... initialize library ...
            //  ... create face object ...
            //  ... set character size ...
            {
                //  initialize library
                error = ANT.ANT_Init_AltNETType(out library);
                //  error handling omitted

                //  create face object
                error = ANT.ANT_New_Face(library, filename, 0, out face);
                //  error handling omitted
                if (error != ANT_Error.ANT_Err_Ok)
                {
                    return;
                }

                //  use 50pt at 100dpi
                //  set character size
                error = ANT.ANT_Set_Char_Size(face, 28 * 64, 0, 96, 0);
                //  error handling omitted
            }

            //  a small shortcut
            slot = face.glyph;


            //  start at (0,0)
            pen_x = 0;
            pen_y = 0;

            num_glyphs  = 0;
            use_kerning = ANT.ANT_HAS_KERNING(face);
            previous    = 0;

            ANT_Vector delta = new ANT_Vector();

            for (n = 0; n < num_chars; n++)
            {
                glyph = glyphs[n];
                if (glyph == null)
                {
                    glyphs[n] = glyph = new TGlyph();
                }

                //  convert character code to glyph index
                glyph.index = ANT.ANT_Get_Char_Index(face, text[n]);

                //  retrieve kerning distance and move pen position
                if (use_kerning &&
                    previous != 0 &&
                    glyph.index != 0)
                {
                    ANT.ANT_Get_Kerning(face, previous, glyph.index, ANT_Kerning_Mode.ANT_KERNING_DEFAULT, delta);

                    pen_x += delta.x >> 6;
                }

                //  store current pen position
                if (glyph.pos == null)
                {
                    glyph.pos = new ANT_Vector();
                }
                glyph.pos.x = pen_x;
                glyph.pos.y = pen_y;

                //  load glyph image into the slot without rendering
                error = ANT.ANT_Load_Glyph(face, glyph.index, ANT_LOAD.ANT_LOAD_DEFAULT);
                if (error != ANT_Error.ANT_Err_Ok)
                {
                    //  ignore errors, jump to next glyph
                    continue;
                }

                //  extract glyph image and store it in our table
                error = ANT.ANT_Get_Glyph(face.glyph, out glyph.image);
                if (error != ANT_Error.ANT_Err_Ok)
                {
                    //  ignore errors, jump to next glyph
                    continue;
                }

                //  translate the glyph image now
                ANT.ANT_Glyph_Transform(glyph.image, null, glyph.pos);

                //  increment pen position
                pen_x += slot.advance.x >> 6;

                //  record current glyph index
                previous = glyph.index;

                //  increment number of glyphs
                num_glyphs++;
            }


            ANT_Vector start = new ANT_Vector();
            //  transformation matrix
            ANT_Matrix matrix = new ANT_Matrix();

            ANT_Glyph  image;
            ANT_Vector pen  = new ANT_Vector();
            ANT_BBox   bbox = new ANT_BBox();

            double angle;


            ANT_BBox string_bbox;

            compute_string_bbox(out string_bbox);


            int my_target_width  = WIDTH;
            int my_target_height = HEIGHT;


            //  compute string dimensions in integer pixels
            int string_width  = string_bbox.xMax - string_bbox.xMin;
            int string_height = string_bbox.yMax - string_bbox.yMin;


            //  use -30 degrees
            angle = (330.0 / 360) * 3.14159 * 2;

            //  compute start pen position in 26.6 cartesian pixels
            start.x = (int)(((my_target_width - string_width * Math.Cos(angle) - string_height * Math.Sin(angle)) / 2 + string_bbox.yMax * Math.Sin(angle)) * 64);
            //  start.y = ((my_target_height - string_height) / 2) * 64;
            //  need to center bitmaps (not base line)
            start.y = (int)(((my_target_height - string_height * Math.Cos(angle) - string_width * Math.Sin(angle)) / 2 - string_bbox.yMin * Math.Cos(angle)) * 64);


            //  set up transform (a rotation here)
            matrix.xx = (int)(Math.Cos(angle) * 0x10000L);
            matrix.xy = (int)(-Math.Sin(angle) * 0x10000L);
            matrix.yx = (int)(Math.Sin(angle) * 0x10000L);
            matrix.yy = (int)(Math.Cos(angle) * 0x10000L);


            pen.CopyFrom(start);

            for (n = 0; n < num_glyphs; n++)
            {
                //  create a copy of the original glyph
                error = ANT.ANT_Glyph_Copy(glyphs[n].image, out image);
                if (error != ANT_Error.ANT_Err_Ok)
                {
                    continue;
                }

                //  transform copy (this will also translate it to the
                //  correct position
                ANT.ANT_Glyph_Transform(image, matrix, pen);

                //  check bounding box; if the transformed glyph image
                //  is not in our target surface, we can avoid rendering it
                ANT.ANT_Glyph_Get_CBox(image, ANT_Glyph_BBox_Mode.ANT_GLYPH_BBOX_PIXELS, bbox);
                if (bbox.xMax <= 0 ||
                    bbox.xMin >= my_target_width ||
                    bbox.yMax <= 0 ||
                    bbox.yMin >= my_target_height)
                {
                    //continue;
                }
                else
                {
                    //  convert glyph image to bitmap (destroy the glyph copy!)
                    error = ANT.ANT_Glyph_To_Bitmap(ref image, ANT_Render_Mode.ANT_RENDER_MODE_NORMAL,
                                                    null,  //  no additional translation
                                                    true); //  destroy copy in "image"
                    if (error == ANT_Error.ANT_Err_Ok)
                    {
                        ANT_BitmapGlyph bit = (ANT_BitmapGlyph)image;

                        draw_bitmap(bit.bitmap, bit.left, my_target_height - bit.top);
                    }
                }

                //  increment pen position --
                //  we don't have access to a slot structure,
                //  so we have to use advances from glyph structure
                //  (which are in 16.16 fixed float format)
                pen.x += image.advance.x >> 10;
                pen.y += image.advance.y >> 10;

                ANT.ANT_Done_Glyph(ref image);
            }


            //
            show_image();

            ANT.ANT_Done_Face(ref face);
            ANT.ANT_Done_AltNETType(ref library);
        }
    float BlitString(string str, float cursorX, float cursorY, List <int> vertexPointers = null)
    {
        TGlyph prevGlyph = null;
        Rect   r;
        bool   inControlCode     = false;
        int    requestedMaterial = 0;

        foreach (char c in str)
        {
            int charCode = (int)c;

            if (inControlCode)
            {
                inControlCode = false;

                if (charCode >= 48 && charCode <= 57)                 // 0-9
                {
                    requestedMaterial = charCode - 48;

                    if (requestedMaterial < _materialCount)
                    {
                        _currentMaterial = requestedMaterial;
                    }
                    else
                    {
                        Debug.LogWarning(string.Format(
                                             "Requested material {0} out of range.", requestedMaterial
                                             ));
                    }

                    if (EnableClickSupport)
                    {
                        AddPlaceholderGlyphBounds();
                    }

                    continue;
                }
            }
            else
            {
                if (charCode == 92)                 // Backslash
                {
                    inControlCode = true;
                    if (EnableClickSupport)
                    {
                        AddPlaceholderGlyphBounds();
                    }
                    continue;
                }
            }

            TGlyph glyph = Font.Glyphs.Get(charCode);

            if (glyph == null)
            {
                continue;
            }

            if (charCode == 32)
            {
                // Assuming here that spaces should not be clickable.
                if (EnableClickSupport)
                {
                    AddPlaceholderGlyphBounds();
                }
                cursorX += glyph.xAdvance * Size + Tracking;
                continue;
            }

            float kerning = 0f;

            if (prevGlyph != null)
            {
                kerning = prevGlyph.GetKerning(charCode) * Size;
            }

            if (vertexPointers != null)
            {
                vertexPointers.Add(m_Vertices.Count);
            }

            r = new Rect(
                cursorX + glyph.xOffset * Size + kerning,
                cursorY + glyph.yOffset * Size,
                glyph.rect.width * Size,
                glyph.rect.height * Size
                );

            BlitQuad(r, glyph);


            // Only need to store glyph bounds if click support is enabled.
            if (EnableClickSupport)
            {
                // Click bounds for glyphs are based on allocated space, not rendered space.
                // Otherwise we'll end up with unclickable dead zones between glyphs.
                r.width = glyph.xAdvance * Size;
                // And Y coordinates are just not handled the same at all.
                r.y = -cursorY - r.height - glyph.yOffset * Size;


                // Calculate relative world-space bounds for this glyph and store them.
                Bounds b = new Bounds(
                    new Vector3(r.x + r.width / 2f, r.y + r.height / 2f, 0f),
                    new Vector3(r.width, r.height, r.height)
                    );

                if (Stationary)
                {
                    // Bake the rotation and position into the bounds so we
                    // don't have to recalculate them on the fly later.
                    b = TranslateBounds(b);
                }
                StoreGlyphBounds(b);
            }


            cursorX  += glyph.xAdvance * Size + Tracking + kerning;
            prevGlyph = glyph;
        }

        if (cursorX > Width)
        {
            Width = cursorX;
        }

        return(cursorX);
    }