public void GetGlyphKerningInfo( GlyphInfo glyph )
		{
			if( !FontContainsChar( glyph.Character ) )
			{
				glyph.ABCKernLeading = 0;
				glyph.ABCKernWidth = glyph.Size.Width;
				glyph.ABCKernTrailing = 0;

				return;
			}

			ABCFloat abc;
			GetCharABCWidthsFloatW( dc, (uint)glyph.Character, (uint)glyph.Character, out abc );

			glyph.ABCKernLeading = abc.A;
			glyph.ABCKernWidth = abc.B;
			glyph.ABCKernTrailing = abc.C;
		}
Exemple #2
0
        public void WriteData(Stream stream)
        {
            if (stream == null)
            {
                throw new ArgumentNullException("stream");
            }

            int[] kernMap = new int[glyphs.Count];
            List <KeyValuePair <char, int> > allKernings = new List <KeyValuePair <char, int> >();

            for (int i = 0; i < glyphs.Count; i++)
            {
                if (glyphs[i].Kernings.Count == 0)
                {
                    kernMap[i] = -1;
                    continue;
                }

                kernMap[i] = allKernings.Count;
                allKernings.AddRange(glyphs[i].Kernings);
            }

            BinaryWriter writer = new BinaryWriter(stream);

            writer.Write(FontIdent);
            writer.Write(FontVersion);
            writer.Write(fontName.Length);
            for (int i = 0; i < fontName.Length; i++)
            {
                writer.Write((int)fontName[i]);
            }
            writer.Write((int)style);
            writer.Write(size);
            writer.Write(lineHeight);
            writer.Write((int)glyphs.Count);
            writer.Write((int)sheets.Count);
            writer.Write((int)allKernings.Count);

            for (int i = 0; i < glyphs.Count; i++)
            {
                GlyphInfo g = glyphs[i];
                writer.Write((int)g.Character);
            }

            for (int i = 0; i < glyphs.Count; i++)
            {
                GlyphInfo g = glyphs[i];
                writer.Write(sheets.IndexOf(g.Sheet));
                writer.Write(g.Size.Width);
                writer.Write(g.Size.Height);
                writer.Write(g.GlyphOffset.X);
                writer.Write(g.GlyphOffset.Y);
                writer.Write(g.SheetRectangle.X);
                writer.Write(g.SheetRectangle.Y);
                writer.Write(g.SheetRectangle.Width);
                writer.Write(g.SheetRectangle.Height);
                writer.Write(g.ABCKernLeading);
                writer.Write(g.ABCKernWidth);
                writer.Write(g.ABCKernTrailing);
                writer.Write(kernMap[i]);
                writer.Write(g.Kernings.Count);
                writer.Write(glyphs.IndexOf(g.SmallCap));
            }

            for (int i = 0; i < allKernings.Count; i++)
            {
                writer.Write((int)allKernings[i].Key);
                writer.Write(allKernings[i].Value);
            }

            for (int i = 0; i < sheets.Count; i++)
            {
                writer.Write(sheets[i].SheetDataSize.Width);
                writer.Write(sheets[i].SheetDataSize.Height);
                for (int y = 0; y < sheets[i].SheetDataSize.Height; y++)
                {
                    writer.Write(sheets[i].SheetData[y], 0, sheets[i].SheetDataSize.Width);
                }
            }

            writer.Flush();
        }
        private List <GlyphSheet> LayoutSheets(Queue <GlyphInfo> glyphs)
        {
            List <GlyphSheet> ret = new List <GlyphSheet>();

            //ToDo: sort?

            while (glyphs.Count != 0)
            {
                GlyphSheet currSheet = new GlyphSheet(imageSize);

                int y;
                for (y = 0; glyphs.Count != 0 && y < imageSize.Height;)
                {
                    int availY = imageSize.Height - y;
                    int maxY   = 0;

                    for (int x = 0; glyphs.Count != 0 && x < imageSize.Width;)
                    {
                        GlyphInfo glyph = glyphs.Peek();

                        //see if we have room to add anything height-wise
                        if (glyph.GlyphDataSize.Height > availY)
                        {
                            //no, break out
                            break;
                        }

                        //find out where we'll be
                        int newX = x + glyph.GlyphDataSize.Width;

                        if (newX > imageSize.Width)
                        {
                            //no room, break on to the next room
                            break;
                        }

                        //don't let the next row stomp on this
                        if (glyph.GlyphDataSize.Height > maxY)
                        {
                            maxY = glyph.GlyphDataSize.Height;
                        }

                        glyph.Sheet          = currSheet;
                        glyph.SheetRectangle = new Rectangle(x, y, glyph.GlyphDataSize.Width, glyph.GlyphDataSize.Height);
                        currSheet.Glyphs.Add(glyph);

                        //advance to the next character
                        glyphs.Dequeue();
                        x = newX + padding;
                    }

                    y += maxY + padding;
                }

                if (y == 0)
                {
                    continue;
                }

                //see if we can cut off the bottom of the image
                if (y < currSheet.SheetDataSize.Height / 2)
                {
                    int targetH = currSheet.SheetDataSize.Height / 2;
                    while (y < targetH / 2)
                    {
                        targetH /= 2;
                    }

                    GlyphSheet newSheet = new GlyphSheet(new Size(currSheet.SheetDataSize.Width, targetH));

                    newSheet.Glyphs.AddRange(currSheet.Glyphs);
                    foreach (GlyphInfo glyph in newSheet.Glyphs)
                    {
                        glyph.Sheet = newSheet;
                    }

                    currSheet = newSheet;
                }

                ret.Add(currSheet);
            }

            return(ret);
        }