internal static CharLocation Create(BitmapChar bitmapChar, float scale = 1, float x = 0, float y = 0)
        {
            CharLocation charLocation = (CharLocation)_pool.GetObject();

            charLocation.Char  = bitmapChar;
            charLocation.Scale = scale;
            charLocation.X     = x;
            charLocation.Y     = y;

            return(charLocation);
        }
Exemple #2
0
 /** Adds a bitmap char with a certain character ID. */
 public void AddChar(int charID, BitmapChar bitmapChar)
 {
     _chars.Add(charID, bitmapChar);
 }
Exemple #3
0
        private List <CharLocation> ArrangeChars(float width, float height, string text, TextFormat format, TextOptions options)
        {
            if (text.Length == 0)
            {
                return(new List <CharLocation>());
            }
            if (options == null)
            {
                options = sDefaultOptions;
            }

            bool   kerning   = format.Kerning;
            float  leading   = format.Leading;
            HAlign hAlign    = format.HorizontalAlign;
            VAlign vAlign    = format.VerticalAlign;
            float  fontSize  = format.Size;
            bool   autoScale = options.AutoScale;
            bool   wordWrap  = options.WordWrap;

            bool         finished = false;
            CharLocation charLocation;
            int          numChars;
            float        containerWidth  = 0;
            float        containerHeight = 0;
            float        scale           = 0;
            int          i;

            if (fontSize < 0f)
            {
                fontSize *= -Size;
            }

            float currentY = 0;

            while (!finished)
            {
                sLines.Clear();
                scale           = fontSize / Size;
                containerWidth  = (width - 2 * Padding) / scale;
                containerHeight = (height - 2 * Padding) / scale;

                if (LineHeight <= containerHeight)
                {
                    int   lastWhiteSpace = -1;
                    int   lastCharId     = -1;
                    float currentX       = 0;
                    currentY = 0;
                    List <CharLocation> currentLine = new List <CharLocation>();

                    numChars = text.Length;
                    for (i = 0; i < numChars; i++)
                    {
                        bool       lineFull   = false;
                        int        charId     = text[i]; // casting to int automatically returns the ASCII value
                        BitmapChar bitmapChar = GetChar(charId);

                        if (charId == CHAR_NEWLINE || charId == CHAR_CARRIAGE_RETURN)
                        {
                            lineFull = true;
                        }
                        else if (bitmapChar == null)
                        {
                            Debug.WriteLine("font " + Name + " missing character: " + text[i] + " ID:" + charId);
                        }
                        else
                        {
                            if (charId == CHAR_SPACE || charId == CHAR_TAB)
                            {
                                lastWhiteSpace = i;
                            }

                            if (kerning)
                            {
                                currentX += bitmapChar.GetKerning(lastCharId);
                            }
                            charLocation = CharLocation.Create(bitmapChar, 1.0f, currentX + bitmapChar.XOffset, currentY + bitmapChar.YOffset);
                            currentLine.Add(charLocation);

                            currentX  += bitmapChar.XAdvance;
                            lastCharId = charId;

                            if (charLocation.X + bitmapChar.Width > containerWidth)
                            {
                                if (wordWrap)
                                {
                                    // when autoscaling, we must not split a word in half -> restart
                                    if (autoScale && lastWhiteSpace == -1)
                                    {
                                        break;
                                    }

                                    // remove characters and add them again to next line
                                    int numCharsToRemove = lastWhiteSpace == -1 ? 1 : i - lastWhiteSpace;

                                    currentLine.RemoveRange(currentLine.Count - numCharsToRemove, numCharsToRemove);

                                    if (currentLine.Count == 0)
                                    {
                                        break;
                                    }
                                    i -= numCharsToRemove;
                                }
                                else
                                {
                                    if (autoScale)
                                    {
                                        break;
                                    }
                                    currentLine.RemoveAt(currentLine.Count - 1);

                                    // continue with next line, if there is one
                                    while (i < numChars - 1 && text[i] != CHAR_NEWLINE)
                                    {
                                        ++i;
                                    }
                                }

                                lineFull = true;
                            }
                        }

                        if (i == numChars - 1)
                        {
                            sLines.Add(currentLine);
                            finished = true;
                        }
                        else if (lineFull)
                        {
                            sLines.Add(currentLine);

                            if (lastWhiteSpace == i)
                            {
                                currentLine.RemoveAt(currentLine.Count - 1);
                            }

                            if (currentY + leading + 2 * LineHeight <= containerHeight)
                            {
                                currentLine    = new List <CharLocation>();
                                currentX       = 0;
                                currentY      += LineHeight + leading;
                                lastWhiteSpace = -1;
                                lastCharId     = -1;
                            }
                            else
                            {
                                break;
                            }
                        }
                    }
                }

                if (autoScale && !finished && fontSize > 3)
                {
                    fontSize -= 1;
                }
                else
                {
                    finished = true;
                }
            }

            List <CharLocation> finalLocations = new List <CharLocation>();
            int   numLines = sLines.Count;
            float bottom   = currentY + LineHeight;
            int   yOffset  = 0;

            if (vAlign == VAlign.Bottom)
            {
                yOffset = (int)(containerHeight - bottom);
            }
            else if (vAlign == VAlign.Center)
            {
                yOffset = (int)((containerHeight - bottom) / 2);
            }

            for (int lineId = 0; lineId < numLines; ++lineId)
            {
                var line = sLines[lineId];
                numChars = line.Count;
                if (numChars == 0)
                {
                    continue;
                }

                int          xOffset      = 0;
                CharLocation lastLocation = line[line.Count - 1];
                float        right        = lastLocation.X - lastLocation.Char.XOffset + lastLocation.Char.XAdvance;

                if (hAlign == HAlign.Right)
                {
                    xOffset = (int)(containerWidth - right);
                }
                else if (hAlign == HAlign.Center)
                {
                    xOffset = (int)((containerWidth - right) / 2);
                }

                for (int c = 0; c < numChars; ++c)
                {
                    charLocation       = line[c];
                    charLocation.X     = scale * (charLocation.X + xOffset + OffsetX) + Padding;
                    charLocation.Y     = scale * (charLocation.Y + yOffset + OffsetY) + Padding;
                    charLocation.Scale = scale;

                    if (charLocation.Char.Width > 0 && charLocation.Char.Height > 0)
                    {
                        finalLocations.Add(charLocation);
                    }
                }
            }

            return(finalLocations);
        }
Exemple #4
0
        private void ParseFontXml(XmlDocument xml)
        {
            float     scale  = _texture.Scale;
            Rectangle frame  = _texture.Frame;
            float     frameX = frame != null ? frame.X : 0f;
            float     frameY = frame != null ? frame.Y : 0f;

            // parse info
            XmlNodeList infoNodes = xml.GetElementsByTagName("info");

            if (infoNodes.Count > 0)
            {
                XmlAttributeCollection attributes = infoNodes[0].Attributes;
                Name = attributes["face"].Value;
                Size = Convert.ToSingle(attributes["size"].Value) / scale;
                if (attributes["smooth"].Value == "0")
                {
                    Smoothing = TextureSmoothing.None;
                }
            }

            // parse common
            XmlNodeList commonNode = xml.GetElementsByTagName("common");

            if (commonNode.Count > 0)
            {
                XmlAttributeCollection attributes = commonNode[0].Attributes;
                LineHeight = Convert.ToSingle(attributes["lineHeight"].Value) / scale;
                Baseline   = Convert.ToSingle(attributes["base"].Value) / scale;
            }

            if (Size <= 0)
            {
                Debug.WriteLine("[Sparrow] Warning: invalid font size in '" + Name + "' font.");
                Size = (Size == 0.0f ? 16.0f : Size * -1.0f);
            }

            // parse chars
            XmlNodeList charNodes = xml.GetElementsByTagName("char");

            for (int i = 0; i < charNodes.Count; i++)
            {
                XmlAttributeCollection attributes = charNodes[i].Attributes;

                int   charId   = Convert.ToInt32(attributes["id"].Value);
                float xOffset  = Convert.ToSingle(attributes["xoffset"].Value) / scale;
                float yOffset  = Convert.ToSingle(attributes["yoffset"].Value) / scale;
                float xAdvance = Convert.ToSingle(attributes["xadvance"].Value) / scale;

                Rectangle region = Rectangle.Create();
                region.X      = Convert.ToSingle(attributes["x"].Value) / scale + frameX;
                region.Y      = Convert.ToSingle(attributes["y"].Value) / scale + frameY;
                region.Width  = Convert.ToSingle(attributes["width"].Value) / scale;
                region.Height = Convert.ToSingle(attributes["height"].Value) / scale;

                Texture texture = Texture.FromTexture(_texture, region);

                BitmapChar bitmapChar = new BitmapChar(charId, texture, xOffset, yOffset, xAdvance);
                AddChar(charId, bitmapChar);
            }

            //kerning
            XmlNodeList kerningNodes = xml.GetElementsByTagName("kerning");

            for (int i = 0; i < kerningNodes.Count; i++)
            {
                XmlAttributeCollection attributes = kerningNodes[i].Attributes;

                int   first  = Convert.ToInt32(attributes["first"].Value);
                int   second = Convert.ToInt32(attributes["second"].Value);
                float amount = Convert.ToSingle(attributes["ammount"].Value) / scale;

                BitmapChar sec = GetChar(second);
                if (sec != null)
                {
                    sec.AddKerning(amount, first);
                }
            }
        }