public override Font Process(FontFile input, IResourceContext context)
        {
            if (input.Pages.Count > 1)
            {
                throw new ArgumentException("The font system can only handle fonts that are in a single page!" +
                                            string.Format(" The file {0} contains {1} pages!", this.ResourcePath, input.Pages.Count));
            }

            string face    = input.Info.Face + "-" + input.Info.Size + "-" + (input.Info.Bold == 1 ? "b" : "") + (input.Info.Italic == 1 ? "i" : "");
            var    texture = LoadTexture(input.Pages[0].File, context);

            int largest = input.Chars.Max((x) => x.ID);

            var charMap = new CharInfo[largest + 1];

            for (int i = 0; i < input.Chars.Count; i++)
            {
                FontChar c = input.Chars[i];


                var info =
                    new CharInfo(texture, new Rect(c.X - 1f, c.Y - 1f, c.Width + 1f, c.Height + 1f),
                                 new Vector2(c.XOffset, c.YOffset),
                                 c.XAdvance);

                charMap[c.ID] = info;
            }


            return(new Font(face, input.Info.Size, input.Common.LineHeight, texture, charMap));
        }
Exemple #2
0
        public void DrawString(SpriteBatch sprite, string text, Font font, Vector2 position, Color color)
        {
            string[] lines = text.Split(new string[] { Environment.NewLine }, StringSplitOptions.None);

            Vector2 cp = new Vector2(position.X, position.Y);

            foreach (string str in lines)
            {
                foreach (char c in str)
                {
                    FontChar fc = new FontChar(font, c);

                    checkChar(fc);

                    Rectangle region;
                    region = charMap[fc];

                    sprite.Draw(buffer, cp, region, color);

                    cp.X += region.Width;
                }
                cp.X  = position.X;
                cp.Y += font.gdiFont.Height;
            }
        }
Exemple #3
0
        void ParseFontCharProperty(ref FontChar fontChar, string name)
        {
            switch (name)
            {
            case "CharCode":
                fontChar.Char = (char)lexer.ParseInt();
                break;

            case "TexPosition":
                fontChar.UV0 = lexer.ParseVector2() / (Vector2)textureSize;
                break;

            case "TexSize":
                Vector2 size = lexer.ParseVector2();
                fontChar.Width  = size.X;
                fontChar.Height = size.Y;
                fontChar.UV1    = fontChar.UV0 + size / (Vector2)textureSize;
                break;

            case "ACWidths":
                fontChar.ACWidths = lexer.ParseVector2();
                break;

            case "TextureIndex":
                fontChar.TextureIndex = lexer.ParseInt();
                break;

            default:
                throw new Exception("Unknown property '{0}'. Parsing: {1}", name, fontChar);
            }
        }
Exemple #4
0
        /// <summary>
        ///
        /// </summary>
        /// <param name="ch"></param>
        /// <returns></returns>
        public FontChar GetGlyph(char ch)
        {
            FontChar glyph = null;

            _glyphs.TryGetValue(ch, out glyph);
            return(glyph);
        }
Exemple #5
0
 /// <summary>
 /// 向Buffer中存入指定的text
 /// </summary>
 /// <param name="text"></param>
 /// <param name="font"></param>
 public void PrepareBuffer(string text, Font font)
 {
     foreach (char c in text)
     {
         FontChar fc = new FontChar(font, c);
         checkChar(fc);
     }
 }
Exemple #6
0
            public override bool Equals(object obj)
            {
                if (!(obj is FontChar))
                {
                    return(false);
                }
                FontChar rhs = obj as FontChar;

                return(font.Equals(rhs.font) && c == rhs.c);
            }
Exemple #7
0
        private void checkChar(FontChar fc)
        {
            if (charMap.ContainsKey(fc))     //Cache Hit
            {
#if DEBUG
                cacheHit++;
#endif
            }
            else                             //Cache Miss
            {
#if DEBUG
                cacheMiss++;
#endif
                generateNewChar(fc);
            }
        }
Exemple #8
0
        private void Render()
        {
            using (var graphics = Graphics.FromImage(_bmp)) {
                graphics.TextRenderingHint  = TextRenderingHint.AntiAlias;
                graphics.SmoothingMode      = SmoothingMode.AntiAlias;
                graphics.CompositingQuality = CompositingQuality.HighQuality;
                graphics.InterpolationMode  = InterpolationMode.HighQualityBicubic;
                graphics.PixelOffsetMode    = PixelOffsetMode.HighQuality;
                graphics.CompositingQuality = CompositingQuality.HighQuality;
                graphics.Clear(Color.FromArgb(255, 0, 0, 0));

                var size     = Size.Empty;
                var padding  = (int)(0.1f * _fontSize);
                var location = new Point(padding, padding);

                foreach (var c in Alphabet)
                {
                    var fontChar = new FontChar();
                    _chars.Add(fontChar);
                    fontChar.Char = c;

                    if (c == ' ')
                    {
                        size = new Size(_fontSize / 3, _fontSize);
                    }
                    else
                    {
                        size = FloorSize(graphics.MeasureString(c.ToString(), _font, PointF.Empty, StringFormat.GenericTypographic));
                        if (location.X + size.Width >= ImageSize)
                        {
                            location.X  = 0;
                            location.Y += _fontSize + padding;
                        }
                    }

                    fontChar.Rectangle = new Rectangle(location, size);
                    graphics.DrawString(c.ToString(), _font, Brushes.White, location, StringFormat.GenericTypographic);
                    location.X += size.Width + padding;
                }

                graphics.Flush();
            }

            CalculateAlpha();
        }
Exemple #9
0
        FontChar ParseFontChar()
        {
            string type = lexer.ParseQuotedString();

            if (type != "Hot::FontChar")
            {
                throw new Exception("Unknown type of object '{0}'", type);
            }
            var fontChar = new FontChar();

            lexer.ParseToken('{');
            while (lexer.PeekChar() != '}')
            {
                ParseFontCharProperty(ref fontChar, lexer.ParseWord());
            }
            lexer.ParseToken('}');
            return(fontChar);
        }
        public void Add(FontChar c)
        {
            if (c.PixelCount == 0) return;

            Rectangle hash_bounds = new Rectangle(0, 0, c.Width, c.Height);
            if (hash_bounds.Width > MAX_HASH_WIDTH) hash_bounds.Width = MAX_HASH_WIDTH;

            int hash = CalculateHash(c.Bitmap, hash_bounds, c.FontColor);

            if (c.Height > max_char_height) max_char_height = c.Height;

            int max_offset = c.FontChars.MaxHeight - c.Height;
            if (max_offset > max_offset_by_height[c.Height]) max_offset_by_height[c.Height] = max_offset;

            if (!lookup_table.ContainsKey(hash))
            {
                lookup_table[hash] = new List<FontChar>();
            }

            lookup_table[hash].Add(c);
        }
Exemple #11
0
        private void generateNewChar(FontChar fc)
        {
            Font font = fc.Font;
            char c    = fc.Char;

#if DEBUG
            Console.WriteLine("Char {0}: {1} in {2}", charMap.Count, c, font.Name);
#endif
            GDI.SizeF sizeF = gdiGraphics.MeasureString(c.ToString(), font.gdiFont, BUFFER_WIDTH, stringFormat);
            GDI.Size  size  = new GDI.Size((int)(sizeF.Width + 0.5), (int)(sizeF.Height + 0.5));

            gdiGraphics.Clear(GDI.Color.Transparent);
            gdiGraphics.DrawString(c.ToString(), font.gdiFont, GDI.Brushes.White, new GDI.PointF(0, 0), GDI.StringFormat.GenericTypographic);

            Rectangle region = allocateRegion(size);

            if (region.Width > 0 && region.Height > 0)
            {
                GDI.Imaging.BitmapData bmpData = gdiBmp.LockBits(
                    new GDI.Rectangle(0, 0, size.Width, size.Height),
                    GDI.Imaging.ImageLockMode.ReadOnly,
                    gdiBmp.PixelFormat);
                IntPtr ptr = bmpData.Scan0;

                byte[] data = new byte[4 * size.Width * size.Height];
                for (int i = 0; i < size.Height; i++)
                {
                    IntPtr start = (IntPtr)((Int64)ptr + i * bmpData.Stride);
                    System.Runtime.InteropServices.Marshal.Copy(start, data, i * 4 * size.Width, size.Width * 4);
                }

                gdiBmp.UnlockBits(bmpData);

                device.Textures[0] = null;  //TODO: ??
                buffer.SetData <byte>(0, region, data, 0, data.Length, SetDataOptions.None);
            }

            charMap.Add(fc, region);
            //return region;
        }
Exemple #12
0
        void ParseFontProperty(Font font, string name)
        {
            switch (name)
            {
            case "Characters":
                lexer.ParseToken('[');
                while (lexer.PeekChar() != ']')
                {
                    (font.Chars as ICollection <FontChar>).Add(ParseFontChar());
                }
                lexer.ParseToken(']');
                break;

            case "Pairs":
                lexer.ParseToken('[');
                while (lexer.PeekChar() != ']')
                {
                    var pair = ParseFontCharPair();
                    // conforming to FontCharCollection interface which doesn't really care
                    // about height argument for this particular case of `Font`
                    FontChar c = (font.Chars as FontCharCollection).Get(pair.A, 666);
                    if (c.KerningPairs == null)
                    {
                        c.KerningPairs = new List <KerningPair>();
                    }
                    c.KerningPairs.Add(new KerningPair {
                        Char = pair.B, Kerning = pair.Kerning
                    });
                }
                lexer.ParseToken(']');
                break;

            case "About":
                font.About = lexer.ParseQuotedString();
                break;

            default:
                throw new Exception("Unknown property '{0}'. Parsing: {1}", name, font);
            }
        }
Exemple #13
0
        public override FontFile Handle(string line, FontFile fontFile)
        {
            Dictionary <string, string> dict = CreateDictionary(line, "char");

            var fontChar = new FontChar
            {
                ID       = Convert.ToInt32(dict["id"]),
                X        = Convert.ToInt32(dict["x"]),
                Y        = Convert.ToInt32(dict["y"]),
                Width    = Convert.ToInt32(dict["width"]),
                Height   = Convert.ToInt32(dict["height"]),
                XOffset  = Convert.ToInt32(dict["xoffset"]),
                YOffset  = Convert.ToInt32(dict["yoffset"]),
                XAdvance = Convert.ToInt32(dict["xadvance"]),
                Page     = Convert.ToInt32(dict["page"]),
                Channel  = Convert.ToInt32(dict["chnl"])
            };

            fontFile.Chars.Add(fontChar);

            return(fontFile);
        }
Exemple #14
0
 public FontChar this[char code]
 {
     get
     {
         var hb = (byte)(code >> 8);
         var lb = (byte)(code & 255);
         if (charMap[hb] != null)
         {
             return(charMap[hb][lb]);
         }
         return(null);
     }
     set
     {
         var hb = (byte)(code >> 8);
         var lb = (byte)(code & 255);
         if (charMap[hb] == null)
         {
             charMap[hb] = new FontChar[256];
         }
         charMap[hb][lb] = value;
     }
 }
Exemple #15
0
 public void Visit(FontChar fontChar)
 {
 }
Exemple #16
0
        /// <summary>
        /// Constrcutor
        /// </summary>
        /// <param name="device"></param>
        /// <param name="fileName"></param>
        public SpriteFont(RenderSystem rs, Stream stream)
        {
            this.rs = rs.Device;

            using (var br = new BinaryReader(stream)) {
                var      xml   = br.ReadString();
                FontFile input = FontLoader.LoadFromString(xml);

                int numGlyphs = input.Chars.Max(ch => ch.ID);

                //	create charInfo and kernings :
                fontInfo.kernings = new Dictionary <Tuple <char, char>, float>();
                fontInfo.charInfo = new SpriteFontInfo.CharInfo[numGlyphs + 1];

                //	check one-page bitmap fonts :
                if (input.Pages.Count != 1)
                {
                    throw new GraphicsException("Only one page of font image is supported");
                }

                //	create path for font-image :
                string fontImagePath = input.Pages[0].File;

                //	skip two bytes :
                var texData = stream.ReadAllBytes();
                fontTexture = new UserTexture(rs.Game.RenderSystem, texData, false);

                //	Fill structure :
                fontInfo.fontFace    = input.Info.Face;
                fontInfo.baseLine    = input.Common.Base;
                fontInfo.lineHeight  = input.Common.LineHeight;
                fontInfo.scaleWidth  = input.Common.ScaleW;
                fontInfo.scaleHeight = input.Common.ScaleH;

                float scaleWidth  = fontInfo.scaleWidth;
                float scaleHeight = fontInfo.scaleHeight;

                //	process character info :
                for (int i = 0; i < input.Chars.Count; i++)
                {
                    FontChar ch = input.Chars[i];

                    int id = ch.ID;

                    if (id < 0)
                    {
                        continue;
                    }

                    int x     = ch.X;
                    int y     = ch.Y;
                    int xoffs = ch.XOffset;
                    int yoffs = ch.YOffset;
                    int w     = ch.Width;
                    int h     = ch.Height;

                    fontInfo.charInfo[ch.ID].validChar = true;
                    fontInfo.charInfo[ch.ID].xAdvance  = ch.XAdvance;
                    fontInfo.charInfo[ch.ID].srcRect   = new RectangleF(x, y, w, h);
                    fontInfo.charInfo[ch.ID].dstRect   = new RectangleF(xoffs, yoffs, w, h);
                }


                var letterHeights = input.Chars
                                    .Where(ch1 => char.IsUpper((char)(ch1.ID)))
                                    .Select(ch2 => ch2.Height)
                                    .OrderBy(h => h)
                                    .ToList();
                CapHeight = letterHeights[letterHeights.Count / 2];



                //	process kerning info :
                for (int i = 0; i < input.Kernings.Count; i++)
                {
                    var pair    = new Tuple <char, char>((char)input.Kernings[i].First, (char)input.Kernings[i].Second);
                    int kerning = input.Kernings[i].Amount;
                    fontInfo.kernings.Add(pair, kerning);
                }

                SpaceWidth = MeasureString(" ").Width;
                LineHeight = MeasureString(" ").Height;
            }
        }
Exemple #17
0
    public static FontData LoadFontFromXmlFile(TextAsset fontLayout)
    {
        FontData font = new FontData();
        XmlDocument document = new XmlDocument();
        document.LoadXml(fontLayout.text);
        XmlNode root = document.DocumentElement;

        // load the basic attributes
        XmlNode secton = root.SelectSingleNode("info");
        font.Info.Face = ParseString(secton, "face");
        font.Info.Size = ParseInt(secton, "size");
        font.Info.Bold = ParseBool(secton, "bold");
        font.Info.Italic = ParseBool(secton, "italic");
        font.Info.Unicode = ParseBool(secton, "unicode");
        font.Info.StretchHeight = ParseInt(secton, "stretchH");
        font.Info.Charset = ParseString(secton, "charset");
        font.Info.Smooth = ParseBool(secton, "smooth");
        font.Info.SuperSampling = ParseInt(secton, "aa");
        font.Info.Padding = ParseRect(secton, "padding");
        font.Info.Spacing = ParseVector2(secton, "spacing");
        font.Info.Outline = ParseInt(secton, "outline");

        // common attributes
        secton = root.SelectSingleNode("common");
        font.Common.LineHeight = ParseInt(secton, "lineHeight");
        font.Common.Base = ParseInt(secton, "base");
        font.Common.ScaleW = ParseInt(secton, "scaleW");
        font.Common.ScaleH = ParseInt(secton, "scaleH");
        font.Common.Pages = ParseInt(secton, "pages");
        font.Common.Packed = ParseBool(secton, "packed");
        font.Common.AlphaChannel = ParseInt(secton, "alphaChnl");
        font.Common.RedChannel = ParseInt(secton, "redChnl");
        font.Common.GreenChannel = ParseInt(secton, "greenChnl");
        font.Common.BlueChannel = ParseInt(secton, "blueChnl");

        // load texture information
        font.Pages.Clear();
        foreach (XmlNode node in root.SelectNodes("pages/page"))
        {
            FontPage page = new FontPage();
            page.Id = ParseInt(node, "id");
            page.File = ParseString(node, "file");
            font.Pages.Add(page);
        }

        // load character information
        font.Chars.Clear();
        foreach (XmlNode node in root.SelectNodes("chars/char"))
        {
            FontChar ch = new FontChar();
            ch.Id = ParseInt(node, "id");
            ch.X = ParseInt(node, "x");
            ch.Y = ParseInt(node, "y");
            ch.Width = ParseInt(node, "width");
            ch.Height = ParseInt(node, "height");
            ch.XOffset = ParseInt(node, "xoffset");
            ch.YOffset = ParseInt(node, "yoffset");
            ch.XAdvance = ParseInt(node, "xadvance");
            ch.Page = ParseInt(node, "page");
            ch.Channel = ParseInt(node, "chnl");
            ch.Description = string.Format("Char: [{0}]; Code: [{1}]", (char)ch.Id, ch.Id);
            font.Chars.Add(ch);
        }

        // loading kerning information
        font.Kernings.Clear();
        foreach (XmlNode node in root.SelectNodes("kernings/kerning"))
        {
            FontKerning key = new FontKerning();
            key.First = ParseInt(node, "first");
            key.Second = ParseInt(node, "second");
            key.Amount = ParseInt(node, "amount");
            key.Description = string.Format("[{0}] [{1}] Amout: [{2}]", (char)key.First, (char)key.Second, key.Amount);
            font.Kernings.Add(key);
        }
        return font;
    }
Exemple #18
0
        private void RenderFont(Font font, Face face)
        {
            var pixels = new Color4[TextureSize * TextureSize];
            int x      = 0;
            int y      = 0;

            foreach (var @char in Characters)
            {
                uint glyphIndex = face.GetCharIndex(@char);
                face.LoadGlyph(glyphIndex, LoadFlags.Default, LoadTarget.Normal);
                if (face.Glyph.Metrics.Width == 0)
                {
                    continue;
                }
                face.Glyph.RenderGlyph(RenderMode.Normal);
                var bitmap = face.Glyph.Bitmap;
                if (x + bitmap.Width + 1 >= TextureSize)
                {
                    x  = 0;
                    y += Height + 1;
                }
                if (y + Height + 1 >= TextureSize)
                {
                    AddFontTexture(font, pixels);
                    pixels = new Color4[TextureSize * TextureSize];
                    x      = y = 0;
                }
                var verticalOffset = Height - face.Glyph.BitmapTop + face.Size.Metrics.Descender.Round();
                CopyBitmap(bitmap, pixels, x, y + verticalOffset);
                var uv0      = new Vector2(x, y) / TextureSize;
                var uv1      = new Vector2(x + bitmap.Width, y + Height) / TextureSize;
                var bearingX = (float)face.Glyph.Metrics.HorizontalBearingX;
                var fontChar = new FontChar()
                {
                    Char         = @char,
                    Width        = bitmap.Width,
                    Height       = Height,
                    TextureIndex = font.Textures.Count,
                    ACWidths     = new Vector2(
                        bearingX.Round(),
                        ((float)face.Glyph.Metrics.HorizontalAdvance - (float)face.Glyph.Metrics.Width - bearingX).Round()
                        ),
                    UV0 = uv0,
                    UV1 = uv1,
                };
                x += bitmap.Width + 1;
                // Iterate through kerning pairs
                foreach (var prevChar in Characters)
                {
                    uint prevGlyphIndex = face.GetCharIndex(prevChar);
                    var  kerning        = (float)face.GetKerning(prevGlyphIndex, glyphIndex, KerningMode.Default).X;
                    // Round kerning to prevent blurring
                    kerning = kerning.Round();
                    if (kerning != 0)
                    {
                        if (fontChar.KerningPairs == null)
                        {
                            fontChar.KerningPairs = new List <KerningPair>();
                        }
                        fontChar.KerningPairs.Add(new KerningPair()
                        {
                            Char = prevChar, Kerning = kerning
                        });
                    }
                }
                font.Chars.Add(fontChar);
            }
            AddFontTexture(font, pixels);
            // Add the whitespace character
            font.Chars.Add(new FontChar()
            {
                Char   = ' ',
                Width  = ((float)Height / 5).Round(),
                Height = Height,
            });
        }
Exemple #19
0
 /// <summary>
 /// フォントエントリを出力します
 /// </summary>
 /// <param name="idx">インデックス</param>
 /// <param name="ch">BMFont キャラクタ</param>
 private void WriteData(int idx, FontChar ch)
 {
     this.WriteData(idx, (Int16)ch.X, (Int16)ch.Y, (Int16)ch.Width, (Int16)ch.Height, (Int16)ch.XOffset, (Int16)ch.YOffset, (Int16)ch.XAdvance);
 }
Exemple #20
0
        /// <summary>
        /// Character テーブルと BMFont のデータから Font エントリを生成します
        /// </summary>
        /// <param name="chtablefile">キャラクタテーブル</param>
        /// <param name="fntfile">BMFont ファイル</param>
        private void Run(string chtablefile, string fntfile)
        {
            // Character Table 読み込み
            var chtable = this.LoadCharacterTable(chtablefile);
            // Font 情報読み込み
            var fonttable = FontLoader.Load(fntfile);
            // Font 検索 Function
            Func <char, FontChar> SearchFont = (seachch) =>
            {
                FontChar ret = NullFontChar;
                foreach (var fontch in fonttable.Chars)
                {
                    if (seachch == (char)fontch.ID)
                    {
                        ret = fontch;
                        break;
                    }
                }
                return(ret);
            };

            int idx = 0;

            foreach (var ch in chtable)
            {
                FontChar fch = null;

                /*
                 * Font の検索
                 */
                // NULL 文字
                if (ch == 0x0000)
                {
                    fch = NullFontChar;
                }// SPACE は改行区切りとして使う
                else if (ch == CHAR_SPACE)
                {
                    fch = NullFontChar;
                }
                // ^ を空白の変わりに使う
                else if (ch == CHAR_CIRCUM)
                {
                    fch = SearchFont(CHAR_SPACE);
                }

                else
                {
                    // 通常の文字
                    fch = SearchFont(ch);
                }

                // Font Character を出力
                if (fch == NullFontChar || fch == null)
                {
                    this.WriteData(idx, 0, 0, 0, 0, 0, 0, 0);
                    if (fch == null)
                    {
                        Console.Error.WriteLine("Unknown Font Character - {0}:{1}", idx, ch);
                    }
                }
                else if (fch != NullFontChar)
                {
                    this.WriteData(idx, fch);
                }

                idx++;
            }
        }
Exemple #21
0
    public static void Create()
    {
        // 프로젝트 뷰에서 선택된 텍스트 파일과 텍스처를 가져온다
        Object[] selectedTextAssets =
            Selection.GetFiltered(typeof(TextAsset), SelectionMode.DeepAssets);
        Object[] selectedTextures =
            Selection.GetFiltered(typeof(Texture2D), SelectionMode.DeepAssets);

        // 텍스트 파일이 선택돼 있지 않다면 오류가 발생한다
        if (selectedTextAssets.Length < 1)
        {
            Debug.LogWarning("No text asset selected.");
            return;
        }

        // 텍스처가 선택돼 있지 않으면 오류가 발생한다
        if (selectedTextures.Length < 1)
        {
            Debug.LogWarning("No texture selected.");
            return;
        }

        // 텍스트 파일이 들어 있는 폴더에 나중에 에셋을 저장한다
        string baseDir =
            Path.GetDirectoryName(AssetDatabase.GetAssetPath(selectedTextAssets[0]));
        // 폰트 이름은 텍스트 파일 이름과 같은 이름을 사용한다
        string fontName = selectedTextAssets[0].name;
        // 텍스트 파일의 내용을 가져온다
        string xml = ((TextAsset)selectedTextAssets[0]).text;

        // XML을 읽어 들이고 트리 구조를 FontData 클래스에 매핑한다
        XmlSerializer xmlSerializer = new XmlSerializer(typeof(FontData));
        FontData      fontData      = null;

        using (StringReader reader = new StringReader(xml))
        {
            fontData = (FontData)xmlSerializer.Deserialize(reader);
        }

        // 데이터가 적합하지 않으면 오류가 발생한다
        if (fontData == null || fontData.chars.Count < 1)
        {
            Debug.LogWarning("Invalid data.");
            return;
        }

        // 사용자 지정 폰트를 위한 머티리얼을 생성해서 현재 선택된 텍스처에 할당한다
        Material fontMaterial = new Material(Shader.Find("UI/Default"));

        fontMaterial.mainTexture = (Texture2D)selectedTextures[0];

        // 사용자 지정 폰트를 생성해서 머티리얼을 할당한다
        Font font = new Font(fontName);

        font.material = fontMaterial;

        // 사용자 지정 폰트에 문자를 추가한다
        float textureWidth  = fontData.common.scaleW;
        float textureHeight = fontData.common.scaleH;

        CharacterInfo[] characterInfos = new CharacterInfo[fontData.chars.Count];
        for (int i = 0; i < fontData.chars.Count; i++)
        {
            FontChar fontChar   = fontData.chars[i];
            float    charX      = fontChar.x;
            float    charY      = fontChar.y;
            float    charWidth  = fontChar.width;
            float    charHeight = fontChar.height;

            // 문자 정보를 설정한다[^5]
            characterInfos[i]       = new CharacterInfo();
            characterInfos[i].index = fontChar.id;
            characterInfos[i].uv    = new Rect(
                charX / textureWidth, (textureHeight - charY - charHeight) / textureHeight,
                charWidth / textureWidth, charHeight / textureHeight);
            characterInfos[i].vert = new Rect(
                fontChar.xoffset, -fontChar.yoffset,
                charWidth, -charHeight);
            characterInfos[i].width = fontChar.xadvance;
        }
        font.characterInfo = characterInfos;

        // Line Spacing 속성은 스크립트로 직접 설정할 수 없으므로
        // SerializedProperty를 사용해 설정한다
        // (이 방법은 유니티의 이후 버전에서 사용하지 못할 가능성이 있습니다)
        SerializedObject   serializedFont        = new SerializedObject(font);
        SerializedProperty serializedLineSpacing =
            serializedFont.FindProperty("m_LineSpacing");

        serializedLineSpacing.floatValue = fontData.common.lineHeight;
        serializedFont.ApplyModifiedProperties();

        // 생성한 머티리얼과 폰트를 에셋 형태로 저장한다
        SaveAsset(fontMaterial, baseDir + "/" + fontName + ".mat");
        SaveAsset(font, baseDir + "/" + fontName + ".fontsettings");
    }
Exemple #22
0
 private static float GetWidth(SpriteFont font, FontChar fontChar)
 {
     return fontChar.XAdvance + font.FontData.Info.Spacing.x;
 }
Exemple #23
0
 public static FontData LoadFontFromTextFile(TextAsset fontLayout)
 {
     FontData font = new FontData();
     string[] lines = fontLayout.text.Split('\n');
     font.Pages.Clear();
     font.Chars.Clear();
     font.Kernings.Clear();
     foreach (string line in lines)
     {
         Dictionary<string, string> table = ParseLine(line);
         if (table.Count == 0)
         {
             continue;
         }
         switch (table["section"])
         {
             case "info":
                 font.Info.Face = ParseString(table, "face");
                 font.Info.Size = ParseInt(table, "size");
                 font.Info.Bold = ParseBool(table, "bold");
                 font.Info.Italic = ParseBool(table, "italic");
                 font.Info.Charset = ParseString(table, "charset");
                 font.Info.Unicode = ParseBool(table, "unicode");
                 font.Info.StretchHeight = ParseInt(table, "stretchH");
                 font.Info.Smooth = ParseBool(table, "smooth");
                 font.Info.SuperSampling = ParseInt(table, "aa");
                 font.Info.Padding = ParseRect(table, "padding");
                 font.Info.Spacing = ParseVector2(table, "spacing");
                 font.Info.Outline = ParseInt(table, "outline");
                 break;
             case "common":
                 font.Common.LineHeight = ParseInt(table, "lineHeight");
                 font.Common.Base = ParseInt(table, "base");
                 font.Common.ScaleW = ParseInt(table, "scaleW");
                 font.Common.ScaleH = ParseInt(table, "scaleW");
                 font.Common.Pages = ParseInt(table, "pages");
                 font.Common.Packed = ParseBool(table, "packed");
                 font.Common.AlphaChannel = ParseInt(table, "alphaChnl");
                 font.Common.RedChannel = ParseInt(table, "redChnl");
                 font.Common.GreenChannel = ParseInt(table, "greenChnl");
                 font.Common.BlueChannel = ParseInt(table, "blueChnl");
                 break;
             case "page":
                 FontPage page = new FontPage();
                 page.Id = ParseInt(table, "id");
                 page.File = ParseString(table, "file");
                 font.Pages.Add(page);
                 break;
             case "char":
                 FontChar ch = new FontChar();
                 ch.Id = ParseInt(table, "id");
                 ch.X = ParseInt(table, "x");
                 ch.Y = ParseInt(table, "y");
                 ch.Width = ParseInt(table, "width");
                 ch.Height = ParseInt(table, "height");
                 ch.XOffset = ParseInt(table, "xoffset");
                 ch.YOffset = ParseInt(table, "yoffset");
                 ch.XAdvance = ParseInt(table, "xadvance");
                 ch.Page = ParseInt(table, "page");
                 ch.Channel = ParseInt(table, "chnl");
                 ch.Description = string.Format("Char: [{0}]; Code: [{1}]", (char)ch.Id, ch.Id);
                 font.Chars.Add(ch);
                 break;
             case "kerning":
                 FontKerning key = new FontKerning();
                 key.First = ParseInt(table, "first");
                 key.Second = ParseInt(table, "second");
                 key.Amount = ParseInt(table, "amount");
                 key.Description = string.Format("[{0}] [{1}] Amout: [{2}]", (char)key.First, (char)key.Second, key.Amount);
                 font.Kernings.Add(key);
                 break;
         }
     }
     return font;
 }
Exemple #24
0
        public void LowPrint(
            VertexBufferWriter vertexWriter,
            IndexBufferWriter indexWriter,
            float x,
            float y,
            float z,
            string text
            )
        {
            if (string.IsNullOrEmpty(text) == true)
            {
                return;
            }
            y += common.Base;
            FontChar fontChar = null;

            for (int i = 0; i < text.Length; ++i)
            {
                char c = text[i];

                fontChar = chars[c];
                if (fontChar == null)
                {
                    continue;
                }

                float a  = fontChar.XAdvance;
                float w  = fontChar.Width;
                float h  = fontChar.Height;
                float ox = fontChar.XOffset;
                float oy = fontChar.YOffset;

                indexWriter.Quad(
                    vertexWriter.CurrentIndex,
                    vertexWriter.CurrentIndex + 1,
                    vertexWriter.CurrentIndex + 2,
                    vertexWriter.CurrentIndex + 3
                    );
                indexWriter.CurrentIndex += 6;
                vertexWriter.Set(position, x + ox, y - oy, z);
                vertexWriter.Set(texCoord, fontChar.U, fontChar.V);
                vertexWriter.Set(color, 1.0f, 1.0f, 1.0f);
                ++vertexWriter.CurrentIndex;
                Bounds.Extend(x + ox, y - oy);

                vertexWriter.Set(position, x + w + ox, y - oy, z);
                vertexWriter.Set(texCoord, fontChar.U2, fontChar.V);
                vertexWriter.Set(color, 1.0f, 1.0f, 1.0f);
                ++vertexWriter.CurrentIndex;
                Bounds.Extend(x + w + ox, y - oy);

                vertexWriter.Set(position, x + w + ox, y - h - oy, z);
                vertexWriter.Set(texCoord, fontChar.U2, fontChar.V2);
                vertexWriter.Set(color, 1.0f, 1.0f, 1.0f);
                ++vertexWriter.CurrentIndex;
                Bounds.Extend(x + w + ox, y - h - oy);

                vertexWriter.Set(position, x + ox, y - h - oy, z);
                vertexWriter.Set(texCoord, fontChar.U, fontChar.V2);
                vertexWriter.Set(color, 1.0f, 1.0f, 1.0f);
                ++vertexWriter.CurrentIndex;
                Bounds.Extend(x + ox, y - h - oy);

                x += a;

                if (
                    (i + 1 < text.Length - 1) &&
                    (fontChar.Kernings != null)
                    )
                {
                    char next = text[i + 1];

                    FontKerning compare = new FontKerning((short)next);

                    int index = fontChar.Kernings.BinarySearch(compare);

                    if (index >= 0)
                    {
                        short amount = fontChar.Kernings[index].Amount;
                        x += (float)(amount);
                    }
                }
            }
        }
Exemple #25
0
        public FontStyle(string filename)
        {
            XmlDocument spec = new XmlDocument();

            spec.Load(filename);

            //info = new FontInfo(spec.SelectSingleNode("font/info"));
            common = new FontCommon(spec.SelectSingleNode("font/common"));

            XmlNode pagesNode = spec.SelectSingleNode("font/pages");
            XmlNode pageNode  = pagesNode.ChildNodes.Item(0);

            /*int     pageId      = */ int.Parse(pageNode.Attributes["id"].Value);
            string file  = pageNode.Attributes["file"].Value;
            var    image = new RenderStack.Graphics.Image("res/images/" + file);

            texture = new TextureGL(image, false);

            XmlNode charsNode = spec.SelectSingleNode("font/chars");

            foreach (XmlNode charNode in charsNode.ChildNodes)
            {
                int charId = int.Parse(charNode.Attributes["id"].Value);
                chars[charId] = new FontChar(charNode, common);
            }
            XmlNode kerningsNode = spec.SelectSingleNode("font/kernings");

            if (kerningsNode != null)
            {
                foreach (XmlNode kerningNode in kerningsNode.ChildNodes)
                {
                    short first  = short.Parse(kerningNode.Attributes["first"].Value);
                    short second = short.Parse(kerningNode.Attributes["second"].Value);
                    if (first >= 0 && second >= 0 && first < 256 && second < 256)
                    {
                        short amount           = short.Parse(kerningNode.Attributes["amount"].Value);
                        bool  modifiedExisting = false;
                        foreach (FontKerning existingKerning in chars[first].Kernings)
                        {
                            /*  This part is overly paranoid - if unicode wasn't used,  */
                            /*  kerning pairs are broken...  */
                            if (existingKerning.Second == second)
                            {
                                if (
                                    (existingKerning.Amount == 0) ||
                                    (System.Math.Sign(existingKerning.Amount) != System.Math.Sign(amount))
                                    )
                                {
                                    existingKerning.Amount = 0;
                                    break;
                                }
                                if (amount < 0 && amount < existingKerning.Amount)
                                {
                                    existingKerning.Amount = amount;
                                    modifiedExisting       = true;
                                    break;
                                }
                                if (amount > 0 && amount > existingKerning.Amount)
                                {
                                    existingKerning.Amount = amount;
                                    modifiedExisting       = true;
                                    break;
                                }
                            }
                        }
                        if (modifiedExisting == false)
                        {
                            chars[first].Kernings.Add(new FontKerning(second, amount));
                        }
                    }
                }
            }
            else
            {
                System.Diagnostics.Trace.TraceWarning("No kerning info");
            }
            foreach (FontChar @char in chars)
            {
                if (@char != null)
                {
                    if (@char.Kernings != null)
                    {
                        @char.Kernings.Sort();
                    }
                }
            }
        }
Exemple #26
0
 public BmpFontChar(FontChar fontCharacter)
 {
     FontChar = fontCharacter;
     SrcRect  = new Rectangle(FontChar.X, FontChar.Y, FontChar.Width, FontChar.Height);
 }
Exemple #27
0
    protected override void OnPopulateMesh(VertexHelper vh)
    {
        vh.Clear();
        if (fontAtlas == null || texture == null || text == null)
        {
            return;
        }
        UpdateText();

        /*Find the dimensions of the texture by adding the
         * maximum width of the rows and the sum of the maximum
         * height of each row plus a blank line for each line
         */
        int texWidth  = 0;
        int texHeight = 0;

        for (int i = 0; i < lines.Count; i++) //get the height of the texture
        {
            if (i < lines.Count - 1)
            {
                texHeight += 8;                  //if the line isn't the last line (line break), add 8 pixels of space
            }
            int maxCharHeight = lines[i].height; //set the max height directly in case a line only has a line break
            foreach (FontChar fontChar in lines[i].characters)
            {
                if (fontChar.size.y > maxCharHeight)
                {
                    maxCharHeight = (int)fontChar.size.y;
                }
            }
            lines[i].height = maxCharHeight;
            texHeight      += maxCharHeight;
        }
        int maxLineWidth = 0;  //get the width of the texture

        for (int i = 0; i < lines.Count; i++)
        {
            int lineWidth = 0;
            foreach (FontChar fontChar in lines[i].characters)
            {
                lineWidth += (int)fontChar.size.x; //get the line's total width
            }
            lines[i].width = lineWidth;
            if (lineWidth > maxLineWidth)
            {
                maxLineWidth = lineWidth;                          //update the highest width
            }
        }
        texWidth = maxLineWidth;
        float xStart  = 0;
        float yStart  = 0;
        float xOffset = 0;
        float yOffset = 0;

        for (int i = 0; i < lines.Count; i++)
        {
            xStart  = alignmentType == AlignmentType.Center ? -((float)lines[i].width / 2f) : 0;
            xOffset = 0;

            for (int j = 0; j < lines[i].characters.Count; j++)
            {
                FontChar currentChar = lines[i].characters[alignmentType == AlignmentType.Right ? lines[i].characters.Count - j - 1 : j];
                Vector2  uv          = currentChar.texPos;
                Vector2  size        = currentChar.size;
                Vector2  texSize     = new Vector2(texture.width, texture.height);

                float x      = xStart + (alignmentType == AlignmentType.Right ? -xOffset - (int)size.x : xOffset);
                float y      = yStart - yOffset - 8;
                int   offset = vh.currentVertCount;
                vh.AddVert(new Vector3(x, y), this.color, new Vector2(uv.x / texSize.x, uv.y / texSize.y));
                vh.AddVert(new Vector3(x + size.x, y), this.color, new Vector2((uv.x + size.x) / texSize.x, uv.y / texSize.y));
                vh.AddVert(new Vector3(x + size.x, y + size.y), this.color, new Vector2((uv.x + size.x) / texSize.x, (uv.y + size.y) / texSize.y));
                vh.AddVert(new Vector3(x, y + size.y), this.color, new Vector2(uv.x / texSize.x, (uv.y + size.y) / texSize.y));
                vh.AddTriangle(0 + offset, 2 + offset, 1 + offset);
                vh.AddTriangle(0 + offset, 3 + offset, 2 + offset);

                xOffset += (size.x);
            }
            yOffset += 8;
        }
        lines.Clear();
    }
Exemple #28
0
        /// <summary>
        /// Constrcutor
        /// </summary>
        /// <param name="device"></param>
        /// <param name="fileName"></param>
        public SpriteFont(GraphicsDevice rs, Stream stream)
        {
            this.rs = rs;

            FontFile input = FontLoader.Load(stream);

            int numGlyphs = input.Chars.Max(ch => ch.ID);

            //	create charInfo and kernings :
            fontInfo.kernings = new Dictionary <Tuple <char, char>, float>();
            fontInfo.charInfo = new SpriteFontInfo.CharInfo[numGlyphs + 1];

            //	check UNICODE :

            /*if (input.Info.Unicode!=0) {
             *      throw new SystemException("UNICODE characters are not supported (Remove UNICODE flag)");
             * } */

            //	check one-page bitmap fonts :
            if (input.Pages.Count != 1)
            {
                throw new GraphicsException("Only one page of font image is supported");
            }

            //	create path for font-image :
            string fontImagePath = input.Pages[0].File;

            fontTexture = rs.Game.Content.Load <Texture2D>(fontImagePath);

            //	Fill structure :
            fontInfo.fontFace    = input.Info.Face;
            fontInfo.baseLine    = input.Common.Base;
            fontInfo.lineHeight  = input.Common.LineHeight;
            fontInfo.scaleWidth  = input.Common.ScaleW;
            fontInfo.scaleHeight = input.Common.ScaleH;

            float scaleWidth  = fontInfo.scaleWidth;
            float scaleHeight = fontInfo.scaleHeight;

            //	process character info :
            for (int i = 0; i < input.Chars.Count; i++)
            {
                FontChar ch = input.Chars[i];

                int id    = ch.ID;
                int x     = ch.X;
                int y     = ch.Y;
                int xoffs = ch.XOffset;
                int yoffs = ch.YOffset;
                int w     = ch.Width;
                int h     = ch.Height;

                fontInfo.charInfo[ch.ID].validChar = true;
                fontInfo.charInfo[ch.ID].xAdvance  = ch.XAdvance;
                fontInfo.charInfo[ch.ID].srcRect   = new RectangleF(x, y, w, h);
                fontInfo.charInfo[ch.ID].dstRect   = new RectangleF(xoffs, yoffs, w, h);
            }


            var letterHeights = input.Chars
                                .Where(ch1 => char.IsUpper((char)(ch1.ID)))
                                .Select(ch2 => ch2.Height)
                                .OrderBy(h => h)
                                .ToList();

            CapHeight = letterHeights[letterHeights.Count / 2];



            //	process kerning info :
            for (int i = 0; i < input.Kernings.Count; i++)
            {
                var pair    = new Tuple <char, char>((char)input.Kernings[i].First, (char)input.Kernings[i].Second);
                int kerning = input.Kernings[i].Amount;
                fontInfo.kernings.Add(pair, kerning);
            }

            SpaceWidth = MeasureString(" ").Width;
            LineHeight = MeasureString(" ").Height;
        }
    public static void Create()
    {
        // Projectビューで選択されているテキストファイルとテクスチャを取得する
        Object[] selectedTextAssets =
            Selection.GetFiltered(typeof(TextAsset), SelectionMode.DeepAssets);
        Object[] selectedTextures =
            Selection.GetFiltered(typeof(Texture2D), SelectionMode.DeepAssets);

        // テキストファイルが選択されていなければエラー
        if (selectedTextAssets.Length < 1)
        {
            Debug.LogWarning("No text asset selected.");
            return;
        }

        // テクスチャが選択されていなければエラー
        if (selectedTextures.Length < 1)
        {
            Debug.LogWarning("No texture selected.");
            return;
        }

        // テキストファイルのあるフォルダに後でアセットを保存する
        string baseDir =
            Path.GetDirectoryName(AssetDatabase.GetAssetPath(selectedTextAssets[0]));
        // フォントの名前はテキストファイルの名前にする
        string fontName = selectedTextAssets[0].name;
        // テキストファイルの中身を取得する
        string xml = ((TextAsset)selectedTextAssets[0]).text;

        // XMLを読み込み、ツリー構造をFontDataクラスにマッピングする
        XmlSerializer xmlSerializer = new XmlSerializer(typeof(FontData));
        FontData      fontData      = null;

        using (StringReader reader = new StringReader(xml))
        {
            fontData = (FontData)xmlSerializer.Deserialize(reader);
        }

        // データが不正だったらエラー
        if (fontData == null || fontData.chars.Count < 1)
        {
            Debug.LogWarning("Invalid data.");
            return;
        }

        // カスタムフォント用のマテリアルを作成して、選択されたテクスチャを割り当てる
        Material fontMaterial = new Material(Shader.Find("UI/Default"));

        fontMaterial.mainTexture = (Texture2D)selectedTextures[0];

        // カスタムフォントを作成して、マテリアルを割り当てる
        Font font = new Font(fontName);

        font.material = fontMaterial;

        // カスタムフォントに文字を追加する
        float textureWidth  = fontData.common.scaleW;
        float textureHeight = fontData.common.scaleH;

        CharacterInfo[] characterInfos = new CharacterInfo[fontData.chars.Count];
        for (int i = 0; i < fontData.chars.Count; i++)
        {
            FontChar fontChar   = fontData.chars[i];
            float    charX      = fontChar.x;
            float    charY      = fontChar.y;
            float    charWidth  = fontChar.width;
            float    charHeight = fontChar.height;

            // 文字情報の設定[^5]
            characterInfos[i]       = new CharacterInfo();
            characterInfos[i].index = fontChar.id;
            characterInfos[i].uv    = new Rect(
                charX / textureWidth, (textureHeight - charY - charHeight) / textureHeight,
                charWidth / textureWidth, charHeight / textureHeight);
            characterInfos[i].vert = new Rect(
                fontChar.xoffset, -fontChar.yoffset,
                charWidth, -charHeight);
            characterInfos[i].width = fontChar.xadvance;
        }
        font.characterInfo = characterInfos;

        // Line Spacingプロパティはスクリプトから直接設定することができないため、
        // SerializedPropertyを使って設定する
        // (この方法はUnityの将来のバージョンで使えなくなる可能性があります)
        SerializedObject   serializedFont        = new SerializedObject(font);
        SerializedProperty serializedLineSpacing =
            serializedFont.FindProperty("m_LineSpacing");

        serializedLineSpacing.floatValue = fontData.common.lineHeight;
        serializedFont.ApplyModifiedProperties();

        // 作成したマテリアルとフォントをアセットとして保存する
        SaveAsset(fontMaterial, baseDir + "/" + fontName + ".mat");
        SaveAsset(font, baseDir + "/" + fontName + ".fontsettings");
    }