Esempio n. 1
0
        /// <summary>
        /// Constructor.
        /// </summary>
        /// <param name="glyph">The glyph being constructed.</param>
        /// <param name="local">Local subroutines.</param>
        /// <param name="global">Global subroutines.</param>
        public ExecContext(
            Font.Glyph glyph,
            Dictionary <int, Type2Charstring> local,
            Dictionary <int, Type2Charstring> global)
        {
            this.atStart = true;

            this.glyph   = glyph;
            this.contour = null;

            this.pos = Vector2.zero;

            this.local            = local;
            this.global           = global;
            this.ended            = false;
            this.processedFirstMT = false;
            this.width            = 0.0f;

            this.hstems = new List <float>();
            this.vstems = new List <float>();

            this.hintMasks = null;
            this.cntrMasks = null;

            this.stack = new List <Operand>();
        }
Esempio n. 2
0
        public Text(string text, string font, float textSize, Color color)
        {
            Vertices       = new Vec2[4 * text.Length];
            Colors         = new Color[4 * text.Length];
            TextureOffsets = new Vec2[text.Length, 4];
            Font currentFont = TextureManager.Instance.GetFont(font);

            Texture = currentFont.Texture;

            // Get start center
            float xStartCenter = -((text.Length * textSize) / 2);

            for (int i = 0; i < text.Length; i++)
            {
                Font.Glyph curGlyph = currentFont.GetGlyph(text[i]);

                // Get glyph position in texture
                float xpos, ypos, xff, yff;
                if (curGlyph.xpos == 0)
                {
                    xpos = 0;
                }
                else
                {
                    xpos = curGlyph.xpos / (float)Tao.LayerWidth;
                }

                if (curGlyph.ypos == 0)
                {
                    ypos = 1.0f;
                }
                else
                {
                    ypos = 1.0f - (curGlyph.ypos / (float)Tao.LayerHeight);
                }

                xff = (float)curGlyph.xsize / (float)Tao.LayerWidth;
                yff = (float)curGlyph.ysize / ((float)Tao.LayerHeight + currentFont.FreeYSpace);

                Colors[i * 4 + 0] = color;
                Colors[i * 4 + 1] = color;
                Colors[i * 4 + 2] = color;
                Colors[i * 4 + 3] = color;

                Vertices[i * 4 + 0] = new Vec2(-textSize + (textSize * i) + xStartCenter, -textSize);
                Vertices[i * 4 + 1] = new Vec2(textSize + (textSize * i) + xStartCenter, -textSize);
                Vertices[i * 4 + 2] = new Vec2(textSize + (textSize * i) + xStartCenter, textSize);
                Vertices[i * 4 + 3] = new Vec2(-textSize + (textSize * i) + xStartCenter, textSize);

                TextureOffsets[i, 0] = new Vec2(xpos, ypos - yff);
                TextureOffsets[i, 1] = new Vec2(xpos + xff, ypos - yff);
                TextureOffsets[i, 2] = new Vec2(xpos + xff, ypos);
                TextureOffsets[i, 3] = new Vec2(xpos, ypos);
            }
        }
Esempio n. 3
0
        public unsafe bool DrawNext(uint *bmpAddress, int bmpWidth, int bmpHeight, int count)
        {
            int i = 0;

            while (i < count && _index < _str.Length)
            {
                int        curX  = _startX + _nextXOffset;
                int        curY  = _startY + _nextYOffset;
                Font.Glyph glyph = _font.GetGlyph(_str, ref _index, ref _nextXOffset, ref _nextYOffset);
                if (glyph != null)
                {
                    _font.DrawGlyph(bmpAddress, bmpWidth, bmpHeight, curX, curY, glyph, _fontColors);
                    i++;
                }
            }
            return(_index >= _str.Length);
        }
Esempio n. 4
0
        public void DrawText(string text, Vector2 position, float size)
        {
            float xpos        = position.X;
            float scaleFactor = size / font.Size;

            scale = Matrix4.CreateScale(scaleFactor); //this is for all text we draw and counts the last DrawText call
            foreach (var c in text)
            {
                if (!font.Characters.ContainsKey(c))
                {
                    continue;
                }

                Font.Glyph glyph = font.Characters[c];

                // Find the texture coordinates for this glyph
                float u1 = (float)(glyph.X + glyph.OriginX) / font.Width;
                float u2 = (float)(glyph.X + glyph.OriginX + glyph.Width) / font.Width;
                float v1 = (float)glyph.Y / font.Height;
                float v2 = (float)(glyph.Y + glyph.Height) / font.Height;

                // calculate y position for glyphs that are below baseline
                float ypos = position.Y - (glyph.Height - glyph.OriginY);

                // add 4 vertices for each corner to draw the glyph as a texture
                // Use of indices below to tell the triangles
                // NOTE  Try to add the last 2 for each glyph and use the last 2 of the previous as the start for the next
                vertices.Add(new VertexTexture(xpos, ypos, -1.0f, u1, v2));
                vertices.Add(new VertexTexture(xpos, ypos + glyph.Height, -1.0f, u1, v1));
                vertices.Add(new VertexTexture(xpos + glyph.Width, ypos, -1.0f, u2, v2));
                vertices.Add(new VertexTexture(xpos + glyph.Width, ypos + glyph.Height, -1.0f, u2, v1));

                //Advance to the next position a glyph can be drawn, add padding(defaults to 1.0f)
                xpos += glyph.Advance;

                // Indices for the above vertices to create the 2 triangles for the quad
                int last = vertices.Count - 1;
                indices.AddRange(new ushort[] { (ushort)(last - 3), (ushort)(last - 1), (ushort)(last - 2) });
                indices.AddRange(new ushort[] { (ushort)(last - 2), (ushort)(last - 1), (ushort)(last) });
            }
        }
Esempio n. 5
0
        public Button(Vec2 size, Color quadColor, string font, string text, Color textColor)
        {
            int totalVertices = 4 + (text.Length * 4);

            size = size / 2;

            Vertices       = new Vec2[totalVertices];
            Colors         = new Color[totalVertices];
            TextureOffsets = new Vec2[text.Length + 4, 4];
            Font currentFont = TextureManager.Instance.GetFont(font);

            Texture = currentFont.Texture;

            // Make Quad
            Vertices[0] = new Vec2(-size.X, -size.Y);
            Vertices[1] = new Vec2(size.X, -size.Y);
            Vertices[2] = new Vec2(size.X, size.Y);
            Vertices[3] = new Vec2(-size.X, size.Y);

            Colors[0] = quadColor;
            Colors[1] = quadColor;
            Colors[2] = quadColor;
            Colors[3] = quadColor;

            TextureOffsets[0, 0] = new Vec2(-1, -1);
            TextureOffsets[0, 1] = new Vec2(-1, -1);
            TextureOffsets[0, 2] = new Vec2(-1, -1);
            TextureOffsets[0, 3] = new Vec2(-1, -1);

            // Generate text
            // Get start center
            float xStartCenter = -size.X;
            float textSize     = (size.X * 2) / (text.Length + 1);

            for (int i = 1; i < text.Length + 1; i++)
            {
                Font.Glyph curGlyph = currentFont.GetGlyph(text[i - 1]);

                // Get glyph position in texture
                float xpos, ypos, xff, yff;
                if (curGlyph.xpos == 0)
                {
                    xpos = 0;
                }
                else
                {
                    xpos = curGlyph.xpos / (float)Tao.LayerWidth;
                }

                if (curGlyph.ypos == 0)
                {
                    ypos = 1.0f;
                }
                else
                {
                    ypos = 1.0f - (curGlyph.ypos / (float)Tao.LayerHeight);
                }

                xff = (float)curGlyph.xsize / (float)Tao.LayerWidth;
                yff = (float)curGlyph.ysize / ((float)Tao.LayerHeight + currentFont.FreeYSpace);

                Colors[i * 4 + 0] = textColor;
                Colors[i * 4 + 1] = textColor;
                Colors[i * 4 + 2] = textColor;
                Colors[i * 4 + 3] = textColor;

                Vertices[i * 4 + 0] = new Vec2(-textSize + (textSize * i) + xStartCenter, -textSize);
                Vertices[i * 4 + 1] = new Vec2(textSize + (textSize * i) + xStartCenter, -textSize);
                Vertices[i * 4 + 2] = new Vec2(textSize + (textSize * i) + xStartCenter, textSize);
                Vertices[i * 4 + 3] = new Vec2(-textSize + (textSize * i) + xStartCenter, textSize);

                TextureOffsets[i, 0] = new Vec2(xpos, ypos - yff);
                TextureOffsets[i, 1] = new Vec2(xpos + xff, ypos - yff);
                TextureOffsets[i, 2] = new Vec2(xpos + xff, ypos);
                TextureOffsets[i, 3] = new Vec2(xpos, ypos);
            }
        }
Esempio n. 6
0
        /// <summary>
        /// Given a font glyph, generate a formal path for it.
        /// </summary>
        /// <param name="glyph">The glyph to turn into a path.</param>
        /// <param name="l">The layer to create the shape in.</param>
        /// <param name="offset">The offset to translate the glyph.</param>
        /// <param name="scale">The scale of the glyph, with 1.0 being the
        /// default size.</param>
        /// <returns>The created path. If the glyph has multiple
        /// contours, they will be created as individual loops.</returns>
        public static BShape GenerateGlyph(
            Font.Glyph glyph,
            Layer l,
            Vector2 offset,
            float scale)
        {
            BShape shapeLetter = new BShape(Vector2.zero, 0.0f);

            shapeLetter.layer = l;

            if (l != null)
            {
                l.shapes.Add(shapeLetter);
            }

            // Generate each contour in the glyph. When we're iterating through the glyph points,
            // we need to remember we're dealing with two possible conventions at once - TTF/OTF and
            // CFF.
            //
            // Remember TTF/OTF uses quadratic Beziers and the control flags.
            //
            // While CCF uses cubic Beziers and the point tangents and tangent flags.
            for (int j = 0; j < glyph.contours.Count; ++j)
            {
                BLoop loopCont = new BLoop(shapeLetter);

                //https://stackoverflow.com/questions/20733790/truetype-fonts-glyph-are-made-of-quadratic-bezier-why-do-more-than-one-consecu
                Font.Contour cont = glyph.contours[j];

                for (int k = 0; k < cont.points.Count; ++k)
                {
                    int nextId = (k + 1) % cont.points.Count;
                    // If two control points are next to each other, there's an implied
                    // point in between them at their average. The easiest way to handle
                    // that is to make a representation where we manually inserted them
                    // to define them explicitly.
                    //
                    // NOTE: We should probably just directly "sanitize" this information
                    // when it's first loaded.
                    if (cont.points[k].isControl == true && cont.points[nextId].isControl == true)
                    {
                        Font.Point pt = new Font.Point();
                        pt.isControl = false;
                        pt.position  = (cont.points[k].position + cont.points[nextId].position) * 0.5f;

                        // Things that process this data may want to know it's implied, especially
                        // diagnostic tools.
                        pt.implied = true;

                        cont.points.Insert(nextId, pt);
                        ++k;
                    }
                }

                BNode   firstNode = null;   // Used to know what to link the last node to when we're done looping.
                BNode   prevNode  = null;   // Used to have a record of the last node when we're done looping.
                Vector2?lastTan   = null;   // The last used tangent when dealing with control points.

                // Point are now either points, or curve controls surrounded by points -
                // or it's a CFF and we don't actually care about control points since we have
                // explicitly defined tangents.
                //
                // The code is written to handle both without explicitly knowing which system is being used.
                for (int k = 0; k < cont.points.Count; ++k)
                {
                    Vector2 ptpos = cont.points[k].position * scale + offset;

                    if (cont.points[k].isControl == false)
                    {
                        BNode node = new BNode(loopCont, ptpos);
                        loopCont.nodes.Add(node);

                        if (lastTan.HasValue == true)
                        {
                            node.UseTanIn = true;
                            node.TanIn    = (lastTan.Value - ptpos) * (2.0f / 3.0f) * scale;
                        }

                        lastTan = null;
                        if (prevNode != null)
                        {
                            node.prev     = prevNode;
                            prevNode.next = node;
                        }

                        if (firstNode == null)
                        {
                            firstNode = node;
                        }

                        int kPrev = (k - 1 + cont.points.Count) % cont.points.Count;

                        if (k != 0 && cont.points[kPrev].isControl == false && cont.points[kPrev].useTangentOut == false)
                        {
                            prevNode.UseTanOut = false;
                            node.UseTanIn      = false;
                        }

                        if (cont.points[k].useTangentIn == true)
                        {
                            node.UseTanIn = true;
                            node.TanIn    = cont.points[k].tangentIn;
                        }

                        if (cont.points[k].useTangentOut == true)
                        {
                            node.UseTanOut = true;
                            node.TanOut    = cont.points[k].tangentOut;
                        }

                        node.FlagDirty();
                        prevNode = node;
                    }
                    else // if (cont.points[k].control == true)
                    {
                        lastTan = ptpos;

                        if (prevNode != null)
                        {
                            prevNode.UseTanOut = true;
                            prevNode.TanOut    = (ptpos - prevNode.Pos) * (2.0f / 3.0f) * scale;
                        }
                    }
                }

                if (firstNode != null)
                {
                    prevNode.next  = firstNode;
                    firstNode.prev = prevNode;

                    if (
                        cont.points[0].isControl == false &&
                        cont.points[0].useTangentIn == false &&
                        cont.points[cont.points.Count - 1].isControl == false &&
                        cont.points[cont.points.Count - 1].useTangentOut == false)
                    {
                        firstNode.UseTanIn = false;
                        prevNode.UseTanOut = false;
                    }

                    if (lastTan.HasValue == true)
                    {
                        firstNode.UseTanIn = true;
                        firstNode.TanIn    = (lastTan.Value - firstNode.Pos) * (2.0f / 3.0f) * scale;
                    }
                }
            }

            return(shapeLetter);
        }