示例#1
0
文件: Xf.cs 项目: obluda3/Kuriimu2
        private Bitmap GetGlyphBitmap(Image fontImage, XfCharMap charMap, XfCharSizeInfo charSizeInfo)
        {
            // Destination points
            var destPoints = new[]
            {
                new PointF(charSizeInfo.offsetX, charSizeInfo.offsetY),
                new PointF(charSizeInfo.glyphWidth + charSizeInfo.offsetX, charSizeInfo.offsetY),
                new PointF(charSizeInfo.offsetX, charSizeInfo.glyphHeight + charSizeInfo.offsetY)
            };

            // Source rectangle
            var srcRect = new RectangleF(
                charMap.imageInformation.imageOffsetX,
                charMap.imageInformation.imageOffsetY,
                charSizeInfo.glyphWidth,
                charSizeInfo.glyphHeight);

            // Color matrix
            var imageAttributes = new ImageAttributes();

            imageAttributes.SetColorMatrix(_colorMatrices[charMap.imageInformation.colorChannel]);

            // Draw the glyph from the master texture
            var glyph = new Bitmap(
                Math.Max(1, Math.Max(charMap.charInformation.charWidth, charSizeInfo.glyphWidth + charSizeInfo.offsetX)),
                Math.Max(1, charSizeInfo.glyphHeight + charSizeInfo.offsetY));
            var gfx = Graphics.FromImage(glyph);

            gfx.DrawImage(fontImage, destPoints, srcRect, GraphicsUnit.Pixel, imageAttributes);

            return(glyph);
        }
示例#2
0
文件: Xf.cs 项目: obluda3/Kuriimu2
        public (Stream fontStream, Image fontImage) Save(List <CharacterInfo> characterInfos, Size imageSize)
        {
            // Generating font textures
            var adjustedGlyphs = FontMeasurement.MeasureWhiteSpace(characterInfos.Select(x => (Bitmap)x.Glyph)).ToList();

            // Adjust image size for at least the biggest letter
            var height = Math.Max(adjustedGlyphs.Max(x => x.WhiteSpaceAdjustment.GlyphSize.Height), imageSize.Height);
            var width  = Math.Max(adjustedGlyphs.Max(x => x.WhiteSpaceAdjustment.GlyphSize.Width), imageSize.Width);

            imageSize = new Size(width, height);

            var generator    = new FontTextureGenerator(imageSize, 0);
            var textureInfos = generator.GenerateFontTextures(adjustedGlyphs, 3).ToList();

            // Join important lists
            var joinedCharacters = characterInfos.OrderBy(x => x.CodePoint).Join(adjustedGlyphs, c => c.Glyph, ag => ag.Glyph,
                                                                                 (c, ag) => new { character = c, adjustedGlyph = ag })
                                   .Select(cag => new
            {
                cag.character,
                cag.adjustedGlyph,
                textureIndex    = textureInfos.FindIndex(x => x.Glyphs.Any(y => y.Item1 == cag.adjustedGlyph.Glyph)),
                texturePosition = textureInfos.SelectMany(x => x.Glyphs).FirstOrDefault(x => x.Item1 == cag.adjustedGlyph.Glyph).Item2
            });

            // Create character information
            var charMaps      = new List <(AdjustedGlyph, XfCharMap)>(adjustedGlyphs.Count);
            var charSizeInfos = new List <XfCharSizeInfo>();

            foreach (var joinedCharacter in joinedCharacters)
            {
                if (joinedCharacter.textureIndex == -1)
                {
                    continue;
                }

                var charSizeInfo = new XfCharSizeInfo
                {
                    offsetX     = (sbyte)joinedCharacter.adjustedGlyph.WhiteSpaceAdjustment.GlyphPosition.X,
                    offsetY     = (sbyte)joinedCharacter.adjustedGlyph.WhiteSpaceAdjustment.GlyphPosition.Y,
                    glyphWidth  = (byte)joinedCharacter.adjustedGlyph.WhiteSpaceAdjustment.GlyphSize.Width,
                    glyphHeight = (byte)joinedCharacter.adjustedGlyph.WhiteSpaceAdjustment.GlyphSize.Height
                };
                if (!charSizeInfos.Contains(charSizeInfo))
                {
                    charSizeInfos.Add(charSizeInfo);
                }

                // Only used for Time Travelers
                var codePoint = ConvertChar(joinedCharacter.character.CodePoint);
                //var codePoint = joinedCharacter.character.CodePoint;

                var charInformation = new XfCharInformation
                {
                    charSizeInfoIndex = charSizeInfos.IndexOf(charSizeInfo),
                    charWidth         = char.IsWhiteSpace((char)codePoint) ?
                                        joinedCharacter.character.CharacterSize.Width :
                                        joinedCharacter.character.CharacterSize.Width - charSizeInfo.offsetX
                };

                charMaps.Add((joinedCharacter.adjustedGlyph, new XfCharMap
                {
                    codePoint = (ushort)codePoint,
                    charInformation = charInformation,
                    imageInformation = new XfImageInformation
                    {
                        colorChannel = joinedCharacter.textureIndex,
                        imageOffsetX = joinedCharacter.texturePosition.X,
                        imageOffsetY = joinedCharacter.texturePosition.Y
                    }
                }));

                if (codePoint != joinedCharacter.character.CodePoint)
                {
                    charInformation = new XfCharInformation
                    {
                        charSizeInfoIndex = charSizeInfos.IndexOf(charSizeInfo),
                        charWidth         = char.IsWhiteSpace((char)joinedCharacter.character.CodePoint)
                            ? joinedCharacter.character.CharacterSize.Width
                            : joinedCharacter.character.CharacterSize.Width - charSizeInfo.offsetX
                    };

                    charMaps.Add((joinedCharacter.adjustedGlyph, new XfCharMap
                    {
                        codePoint = (ushort)joinedCharacter.character.CodePoint,
                        charInformation = charInformation,
                        imageInformation = new XfImageInformation
                        {
                            colorChannel = joinedCharacter.textureIndex,
                            imageOffsetX = joinedCharacter.texturePosition.X,
                            imageOffsetY = joinedCharacter.texturePosition.Y
                        }
                    }));
                }
            }

            // Set escape characters
            var escapeIndex = charMaps.FindIndex(x => x.Item2.codePoint == '?');

            Header.largeEscapeCharacter = escapeIndex < 0 ? (short)0 : (short)escapeIndex;
            Header.smallEscapeCharacter = 0;

            // Minimize top value and line height
            Header.largeCharHeight = (short)charSizeInfos.Max(x => x.glyphHeight + x.offsetY);
            Header.smallCharHeight = 0;

            // Draw textures
            var img = new Bitmap(imageSize.Width, imageSize.Height);
            var gfx = Graphics.FromImage(img);

            for (var i = 0; i < textureInfos.Count; i++)
            {
                var destPoints = new[]
                {
                    new PointF(0, 0),
                    new PointF(textureInfos[i].FontTexture.Width, 0),
                    new PointF(0, textureInfos[i].FontTexture.Height)
                };
                var rect = new RectangleF(0, 0, textureInfos[i].FontTexture.Width, textureInfos[i].FontTexture.Height);
                var attr = new ImageAttributes();
                attr.SetColorMatrix(_inverseColorMatrices[i]);
                gfx.DrawImage(textureInfos[i].FontTexture, destPoints, rect, GraphicsUnit.Pixel, attr);
            }

            // Save fnt.bin
            var savedFntBin = new MemoryStream();

            using (var bw = new BinaryWriterX(savedFntBin, true))
            {
                //Table0
                bw.BaseStream.Position = 0x28;
                Header.charSizeCount   = (short)charSizeInfos.Count;
                WriteMultipleCompressed(bw, charSizeInfos, _t0Comp);
                bw.WriteAlignment(4);

                //Table1
                Header.largeCharOffset = (short)(bw.BaseStream.Position >> 2);
                Header.largeCharCount  = (short)charMaps.Count;
                WriteMultipleCompressed(bw, charMaps.OrderBy(x => x.Item2.codePoint).Select(x => x.Item2).ToArray(), _t1Comp);
                bw.WriteAlignment(4);

                //Table2
                Header.smallCharOffset = (short)(bw.BaseStream.Position >> 2);
                Header.smallCharCount  = 0;
                WriteMultipleCompressed(bw, Array.Empty <XfCharMap>(), _t2Comp);
                bw.WriteAlignment(4);

                //Header
                bw.BaseStream.Position = 0;
                bw.WriteType(Header);
            }

            return(savedFntBin, img);
        }