diff --git a/.vs/Toolbox/v15/.suo b/.vs/Toolbox/v15/.suo index 269b13d0..ac58fbab 100644 Binary files a/.vs/Toolbox/v15/.suo and b/.vs/Toolbox/v15/.suo differ diff --git a/File_Format_Library/FileFormats/Font/BFFNT.cs b/File_Format_Library/FileFormats/Font/BFFNT.cs index ef10d952..d0ab5cf5 100644 --- a/File_Format_Library/FileFormats/Font/BFFNT.cs +++ b/File_Format_Library/FileFormats/Font/BFFNT.cs @@ -203,8 +203,11 @@ namespace FirstPlugin switch (BlockSignature) { case "FFNT": - case "CMAP": + case "FFNA": + case "FCPX": case "CWDH": + case "CGLP": + case "CMAP": case "TGLP": case "FINF": break; @@ -212,6 +215,9 @@ namespace FirstPlugin KerningTable = new FontKerningTable(); KerningTable.Read(reader, this); break; + case "GLGR": + case "HTGL": + break; default: throw new Exception("Unknown block found! " + BlockSignature); } @@ -270,6 +276,9 @@ namespace FirstPlugin public class KerningFirstTable { + public uint FirstWordCount { get; set; } + public uint Offset { get; set; } + public void Read(FileReader reader, FFNT Header) { if (Header.Platform == FFNT.PlatformType.NX) @@ -561,6 +570,9 @@ namespace FirstPlugin public CMAP CodeMap; public CWDH CharacterWidth; + public List CharacterWidths { get; set; } + public List CodeMaps { get; set; } + public enum FontType : byte { Glyph = 1, @@ -577,6 +589,9 @@ namespace FirstPlugin public void Read(FileReader reader, FFNT Header) { + CharacterWidths = new List(); + CodeMaps = new List(); + string Signature = reader.ReadString(4, Encoding.ASCII); if (Signature != "FINF") throw new Exception($"Invalid signature {Signature}! Expected FINF."); @@ -600,12 +615,14 @@ namespace FirstPlugin TextureGlyph.Read(reader); CharacterWidth = new CWDH(); + CharacterWidths.Add(CharacterWidth); using (reader.TemporarySeek(cwdhOffset - 8, SeekOrigin.Begin)) - CharacterWidth.Read(reader, Header); + CharacterWidth.Read(reader, Header, CharacterWidths); CodeMap = new CMAP(); + CodeMaps.Add(CodeMap); using (reader.TemporarySeek(cmapOffset - 8, SeekOrigin.Begin)) - CodeMap.Read(reader, Header); + CodeMap.Read(reader, Header, CodeMaps); } public void Write(FileWriter writer) @@ -630,6 +647,23 @@ namespace FirstPlugin long _ofsCMAP = writer.Position; writer.Write(uint.MaxValue); } + + public CWDH GetCharacterWidth(int index) + { + if (index == -1) + return null; + + for (int i = 0; i < CharacterWidths.Count; i++) + { + if (CharacterWidths[i].StartIndex <= index && CharacterWidths[i].EndIndex >= index) + { + int CharaIndex = index - CharacterWidths[i].StartIndex; + return CharacterWidths[CharaIndex]; + } + } + + throw new Exception("Failed to get valid character index!"); + } } public class TGLP { @@ -728,6 +762,24 @@ namespace FirstPlugin } } + public interface CharMapping { } + + public class CMAPIndexTable : CharMapping + { + public short[] Table { get; set; } + } + + public class CMAPDirect : CharMapping + { + public ushort Offset { get; set; } + } + + public class CMAPScanMapping : CharMapping + { + public uint[] Codes { get; set; } + public short[] Indexes { get; set; } + } + public class CMAP { public uint SectionSize; @@ -739,6 +791,8 @@ namespace FirstPlugin private ushort Padding; + public CharMapping MappingData; + public enum Mapping : ushort { Direct, @@ -748,7 +802,7 @@ namespace FirstPlugin public CMAP NextCodeMapSection { get; set; } - public void Read(FileReader reader, FFNT header) + public void Read(FileReader reader, FFNT header, List CodeMaps) { uint CodeBegin = 0; uint CodeEnd = 0; @@ -788,13 +842,22 @@ namespace FirstPlugin int idx = i - CharacterCodeBegin + charOffset; header.FontSection.CodeMapDictionary[i] = idx < ushort.MaxValue ? idx : 0; } + + MappingData = new CMAPDirect(); + ((CMAPDirect)MappingData).Offset = charOffset; break; case Mapping.Table: + List table = new List(); for (char i = CharacterCodeBegin; i <= CharacterCodeEnd; i++) { short idx = reader.ReadInt16(); if (idx != -1) header.FontSection.CodeMapDictionary[i] = idx; + + table.Add(idx); } + + MappingData = new CMAPIndexTable(); + ((CMAPIndexTable)MappingData).Table = table.ToArray(); break; case Mapping.Scan: var CharEntryCount = reader.ReadUInt16(); @@ -802,23 +865,35 @@ namespace FirstPlugin if (header.Platform == FFNT.PlatformType.NX) reader.ReadUInt16(); //Padding + uint[] codes = new uint[CharEntryCount]; + short[] indexes = new short[CharEntryCount]; + for (int i = 0; i < CharEntryCount; i++) { if (header.Platform == FFNT.PlatformType.NX) { - //Seems to have a spacing of a ushort for each entry - uint charCode = reader.ReadUInt16(); + uint charCode = reader.ReadUInt32(); short index = reader.ReadInt16(); short padding = reader.ReadInt16(); if (index != -1) header.FontSection.CodeMapDictionary[(char)charCode] = index; + + codes[i] = charCode; + indexes[i] = index; } else { char charCode = reader.ReadChar(); short index = reader.ReadInt16(); if (index != -1) header.FontSection.CodeMapDictionary[charCode] = index; + + codes[i] = charCode; + indexes[i] = index; } } + + MappingData = new CMAPScanMapping(); + ((CMAPScanMapping)MappingData).Codes = codes; + ((CMAPScanMapping)MappingData).Indexes = indexes; break; } @@ -826,12 +901,31 @@ namespace FirstPlugin { reader.SeekBegin(NextMapOffset - 8); NextCodeMapSection = new CMAP(); - NextCodeMapSection.Read(reader, header); + NextCodeMapSection.Read(reader, header, CodeMaps); + CodeMaps.Add(NextCodeMapSection); } else reader.SeekBegin(pos + SectionSize); } + //From https://github.com/dnasdw/3dsfont/blob/79e6f4ab6676d82fdcd6c0f79d9b0d7a343f82b5/src/bcfnt2charset/bcfnt2charset.cpp#L3 + //Todo add the rest of the encoding types + public char CodeToU16Code(FINF.CharacterCode characterCode, ushort code) + { + if (code < 0x20) + { + return (char)0; + } + + switch (characterCode) + { + case FINF.CharacterCode.Unicode: + return (char)code; + } + + return (char)code; + } + public void Write() { @@ -840,8 +934,8 @@ namespace FirstPlugin public class CWDH { - public ushort GlobalIndexFirstWidthEntry { get; set; } - public ushort GlobalIndexLastWidthEntry { get; set; } + public ushort StartIndex { get; set; } + public ushort EndIndex { get; set; } public List WidthEntries = new List(); @@ -849,25 +943,26 @@ namespace FirstPlugin public ushort EntryCount { - get { return (ushort)(GlobalIndexLastWidthEntry - GlobalIndexFirstWidthEntry + 1); } + get { return (ushort)(EndIndex - StartIndex + 1); } } public uint SectionSize; - public void Read(FileReader reader, FFNT header) + public void Read(FileReader reader, FFNT header, List CharacterWidths) { long pos = reader.Position; reader.ReadSignature(4, "CWDH"); SectionSize = reader.ReadUInt32(); - GlobalIndexFirstWidthEntry = reader.ReadUInt16(); - GlobalIndexLastWidthEntry = reader.ReadUInt16(); + EndIndex = reader.ReadUInt16(); + StartIndex = reader.ReadUInt16(); uint NextWidthSectionOffset = reader.ReadUInt32(); if (NextWidthSectionOffset != 0) { reader.SeekBegin((int)NextWidthSectionOffset - 8); NextWidthSection = new CWDH(); - NextWidthSection.Read(reader, header); + NextWidthSection.Read(reader, header, CharacterWidths); + CharacterWidths.Add(NextWidthSection); } else reader.SeekBegin(pos + SectionSize); diff --git a/File_Format_Library/GUI/BFFNT/BffntEditor.Designer.cs b/File_Format_Library/GUI/BFFNT/BffntEditor.Designer.cs index a919643d..f73dbeec 100644 --- a/File_Format_Library/GUI/BFFNT/BffntEditor.Designer.cs +++ b/File_Format_Library/GUI/BFFNT/BffntEditor.Designer.cs @@ -29,7 +29,6 @@ private void InitializeComponent() { this.components = new System.ComponentModel.Container(); - System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(BffntEditor)); this.stPanel1 = new Toolbox.Library.Forms.STPanel(); this.lineFeedUD = new Toolbox.Library.Forms.NumericUpDownUint(); this.stLabel13 = new Toolbox.Library.Forms.STLabel(); @@ -56,13 +55,21 @@ this.splitter1 = new System.Windows.Forms.Splitter(); this.splitter2 = new System.Windows.Forms.Splitter(); this.stPanel3 = new Toolbox.Library.Forms.STPanel(); + this.imageMenuStrip = new Toolbox.Library.Forms.STContextMenuStrip(this.components); + this.exportToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.copyToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); this.imagesCB = new Toolbox.Library.Forms.STComboBox(); this.stLabel3 = new Toolbox.Library.Forms.STLabel(); this.stPanel4 = new Toolbox.Library.Forms.STPanel(); - this.imageMenuStrip = new Toolbox.Library.Forms.STContextMenuStrip(this.components); - this.pictureBoxCustom1 = new Toolbox.Library.Forms.PictureBoxCustom(); - this.exportToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); - this.copyToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.characterCodeCB = new Toolbox.Library.Forms.STComboBox(); + this.stLabel14 = new Toolbox.Library.Forms.STLabel(); + this.numericUpDownUint1 = new Toolbox.Library.Forms.NumericUpDownUint(); + this.stLabel15 = new Toolbox.Library.Forms.STLabel(); + this.numericUpDownUint2 = new Toolbox.Library.Forms.NumericUpDownUint(); + this.stLabel16 = new Toolbox.Library.Forms.STLabel(); + this.numericUpDownUint3 = new Toolbox.Library.Forms.NumericUpDownUint(); + this.stLabel17 = new Toolbox.Library.Forms.STLabel(); + this.imagePanel = new Toolbox.Library.Forms.STPanel(); this.stPanel1.SuspendLayout(); ((System.ComponentModel.ISupportInitialize)(this.lineFeedUD)).BeginInit(); ((System.ComponentModel.ISupportInitialize)(this.leftSpacingUD)).BeginInit(); @@ -73,9 +80,11 @@ ((System.ComponentModel.ISupportInitialize)(this.ascentUD)).BeginInit(); this.stPanel2.SuspendLayout(); this.stPanel3.SuspendLayout(); - this.stPanel4.SuspendLayout(); this.imageMenuStrip.SuspendLayout(); - ((System.ComponentModel.ISupportInitialize)(this.pictureBoxCustom1)).BeginInit(); + this.stPanel4.SuspendLayout(); + ((System.ComponentModel.ISupportInitialize)(this.numericUpDownUint1)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.numericUpDownUint2)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.numericUpDownUint3)).BeginInit(); this.SuspendLayout(); // // stPanel1 @@ -315,6 +324,14 @@ // // stPanel2 // + this.stPanel2.Controls.Add(this.numericUpDownUint3); + this.stPanel2.Controls.Add(this.stLabel17); + this.stPanel2.Controls.Add(this.numericUpDownUint2); + this.stPanel2.Controls.Add(this.stLabel16); + this.stPanel2.Controls.Add(this.numericUpDownUint1); + this.stPanel2.Controls.Add(this.stLabel15); + this.stPanel2.Controls.Add(this.stLabel14); + this.stPanel2.Controls.Add(this.characterCodeCB); this.stPanel2.Controls.Add(this.stLabel2); this.stPanel2.Dock = System.Windows.Forms.DockStyle.Right; this.stPanel2.Location = new System.Drawing.Point(619, 0); @@ -350,7 +367,7 @@ // // stPanel3 // - this.stPanel3.Controls.Add(this.pictureBoxCustom1); + this.stPanel3.Controls.Add(this.imagePanel); this.stPanel3.Controls.Add(this.imagesCB); this.stPanel3.Controls.Add(this.stLabel3); this.stPanel3.Dock = System.Windows.Forms.DockStyle.Fill; @@ -359,6 +376,28 @@ this.stPanel3.Size = new System.Drawing.Size(412, 438); this.stPanel3.TabIndex = 4; // + // imageMenuStrip + // + this.imageMenuStrip.Items.AddRange(new System.Windows.Forms.ToolStripItem[] { + this.exportToolStripMenuItem, + this.copyToolStripMenuItem}); + this.imageMenuStrip.Name = "stContextMenuStrip1"; + this.imageMenuStrip.Size = new System.Drawing.Size(108, 48); + // + // exportToolStripMenuItem + // + this.exportToolStripMenuItem.Name = "exportToolStripMenuItem"; + this.exportToolStripMenuItem.Size = new System.Drawing.Size(107, 22); + this.exportToolStripMenuItem.Text = "Export"; + this.exportToolStripMenuItem.Click += new System.EventHandler(this.exportToolStripMenuItem_Click); + // + // copyToolStripMenuItem + // + this.copyToolStripMenuItem.Name = "copyToolStripMenuItem"; + this.copyToolStripMenuItem.Size = new System.Drawing.Size(107, 22); + this.copyToolStripMenuItem.Text = "Copy"; + this.copyToolStripMenuItem.Click += new System.EventHandler(this.copyToolStripMenuItem_Click); + // // imagesCB // this.imagesCB.BorderColor = System.Drawing.Color.Empty; @@ -396,42 +435,101 @@ this.stPanel4.Size = new System.Drawing.Size(819, 438); this.stPanel4.TabIndex = 2; // - // imageMenuStrip + // characterCodeCB // - this.imageMenuStrip.Items.AddRange(new System.Windows.Forms.ToolStripItem[] { - this.exportToolStripMenuItem, - this.copyToolStripMenuItem}); - this.imageMenuStrip.Name = "stContextMenuStrip1"; - this.imageMenuStrip.Size = new System.Drawing.Size(181, 70); + this.characterCodeCB.BorderColor = System.Drawing.Color.Empty; + this.characterCodeCB.BorderStyle = System.Windows.Forms.ButtonBorderStyle.Solid; + this.characterCodeCB.ButtonColor = System.Drawing.Color.Empty; + this.characterCodeCB.Font = new System.Drawing.Font("Microsoft Sans Serif", 20.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); + this.characterCodeCB.FormattingEnabled = true; + this.characterCodeCB.Location = new System.Drawing.Point(103, 27); + this.characterCodeCB.Name = "characterCodeCB"; + this.characterCodeCB.ReadOnly = true; + this.characterCodeCB.Size = new System.Drawing.Size(72, 39); + this.characterCodeCB.TabIndex = 2; // - // pictureBoxCustom1 + // stLabel14 // - this.pictureBoxCustom1.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) + this.stLabel14.AutoSize = true; + this.stLabel14.Location = new System.Drawing.Point(13, 45); + this.stLabel14.Name = "stLabel14"; + this.stLabel14.Size = new System.Drawing.Size(84, 13); + this.stLabel14.TabIndex = 3; + this.stLabel14.Text = "Character Code:"; + // + // numericUpDownUint1 + // + this.numericUpDownUint1.Location = new System.Drawing.Point(100, 118); + this.numericUpDownUint1.Maximum = new decimal(new int[] { + 255, + 0, + 0, + 0}); + this.numericUpDownUint1.Name = "numericUpDownUint1"; + this.numericUpDownUint1.Size = new System.Drawing.Size(97, 20); + this.numericUpDownUint1.TabIndex = 21; + // + // stLabel15 + // + this.stLabel15.AutoSize = true; + this.stLabel15.Location = new System.Drawing.Point(13, 120); + this.stLabel15.Name = "stLabel15"; + this.stLabel15.Size = new System.Drawing.Size(77, 13); + this.stLabel15.TabIndex = 20; + this.stLabel15.Text = "Texture Width:"; + // + // numericUpDownUint2 + // + this.numericUpDownUint2.Location = new System.Drawing.Point(100, 80); + this.numericUpDownUint2.Maximum = new decimal(new int[] { + 255, + 0, + 0, + 0}); + this.numericUpDownUint2.Name = "numericUpDownUint2"; + this.numericUpDownUint2.Size = new System.Drawing.Size(97, 20); + this.numericUpDownUint2.TabIndex = 23; + // + // stLabel16 + // + this.stLabel16.AutoSize = true; + this.stLabel16.Location = new System.Drawing.Point(13, 82); + this.stLabel16.Name = "stLabel16"; + this.stLabel16.Size = new System.Drawing.Size(73, 13); + this.stLabel16.TabIndex = 22; + this.stLabel16.Text = "Left Spacing::"; + // + // numericUpDownUint3 + // + this.numericUpDownUint3.Location = new System.Drawing.Point(100, 154); + this.numericUpDownUint3.Maximum = new decimal(new int[] { + 255, + 0, + 0, + 0}); + this.numericUpDownUint3.Name = "numericUpDownUint3"; + this.numericUpDownUint3.Size = new System.Drawing.Size(97, 20); + this.numericUpDownUint3.TabIndex = 25; + // + // stLabel17 + // + this.stLabel17.AutoSize = true; + this.stLabel17.Location = new System.Drawing.Point(13, 156); + this.stLabel17.Name = "stLabel17"; + this.stLabel17.Size = new System.Drawing.Size(79, 13); + this.stLabel17.TabIndex = 24; + this.stLabel17.Text = "Effictive Width:"; + // + // imagePanel + // + this.imagePanel.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) | System.Windows.Forms.AnchorStyles.Left) | System.Windows.Forms.AnchorStyles.Right))); - this.pictureBoxCustom1.BackColor = System.Drawing.Color.Transparent; - this.pictureBoxCustom1.BackgroundImage = ((System.Drawing.Image)(resources.GetObject("pictureBoxCustom1.BackgroundImage"))); - this.pictureBoxCustom1.ContextMenuStrip = this.imageMenuStrip; - this.pictureBoxCustom1.Location = new System.Drawing.Point(6, 36); - this.pictureBoxCustom1.Name = "pictureBoxCustom1"; - this.pictureBoxCustom1.Size = new System.Drawing.Size(400, 399); - this.pictureBoxCustom1.SizeMode = System.Windows.Forms.PictureBoxSizeMode.Zoom; - this.pictureBoxCustom1.TabIndex = 2; - this.pictureBoxCustom1.TabStop = false; - // - // exportToolStripMenuItem - // - this.exportToolStripMenuItem.Name = "exportToolStripMenuItem"; - this.exportToolStripMenuItem.Size = new System.Drawing.Size(180, 22); - this.exportToolStripMenuItem.Text = "Export"; - this.exportToolStripMenuItem.Click += new System.EventHandler(this.exportToolStripMenuItem_Click); - // - // copyToolStripMenuItem - // - this.copyToolStripMenuItem.Name = "copyToolStripMenuItem"; - this.copyToolStripMenuItem.Size = new System.Drawing.Size(180, 22); - this.copyToolStripMenuItem.Text = "Copy"; - this.copyToolStripMenuItem.Click += new System.EventHandler(this.copyToolStripMenuItem_Click); + this.imagePanel.Location = new System.Drawing.Point(6, 33); + this.imagePanel.Name = "imagePanel"; + this.imagePanel.Size = new System.Drawing.Size(400, 402); + this.imagePanel.TabIndex = 2; + this.imagePanel.Paint += new System.Windows.Forms.PaintEventHandler(this.imagePanel_Paint); // // BffntEditor // @@ -453,9 +551,11 @@ this.stPanel2.PerformLayout(); this.stPanel3.ResumeLayout(false); this.stPanel3.PerformLayout(); - this.stPanel4.ResumeLayout(false); this.imageMenuStrip.ResumeLayout(false); - ((System.ComponentModel.ISupportInitialize)(this.pictureBoxCustom1)).EndInit(); + this.stPanel4.ResumeLayout(false); + ((System.ComponentModel.ISupportInitialize)(this.numericUpDownUint1)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.numericUpDownUint2)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.numericUpDownUint3)).EndInit(); this.ResumeLayout(false); } @@ -491,9 +591,17 @@ private Toolbox.Library.Forms.STPanel stPanel4; private Toolbox.Library.Forms.NumericUpDownUint lineFeedUD; private Toolbox.Library.Forms.STLabel stLabel13; - private Toolbox.Library.Forms.PictureBoxCustom pictureBoxCustom1; private Toolbox.Library.Forms.STContextMenuStrip imageMenuStrip; private System.Windows.Forms.ToolStripMenuItem exportToolStripMenuItem; private System.Windows.Forms.ToolStripMenuItem copyToolStripMenuItem; + private Toolbox.Library.Forms.STComboBox characterCodeCB; + private Toolbox.Library.Forms.STLabel stLabel14; + private Toolbox.Library.Forms.NumericUpDownUint numericUpDownUint3; + private Toolbox.Library.Forms.STLabel stLabel17; + private Toolbox.Library.Forms.NumericUpDownUint numericUpDownUint2; + private Toolbox.Library.Forms.STLabel stLabel16; + private Toolbox.Library.Forms.NumericUpDownUint numericUpDownUint1; + private Toolbox.Library.Forms.STLabel stLabel15; + private Toolbox.Library.Forms.STPanel imagePanel; } } \ No newline at end of file diff --git a/File_Format_Library/GUI/BFFNT/BffntEditor.cs b/File_Format_Library/GUI/BFFNT/BffntEditor.cs index 018688a9..5262f30c 100644 --- a/File_Format_Library/GUI/BFFNT/BffntEditor.cs +++ b/File_Format_Library/GUI/BFFNT/BffntEditor.cs @@ -18,6 +18,8 @@ namespace FirstPlugin.Forms InitializeComponent(); } + private Image PanelImage { get; set; } + private FFNT ActiveFile; public void LoadFontFile(BFFNT fontFile) { @@ -37,9 +39,19 @@ namespace FirstPlugin.Forms fontWidthUD.Bind(ActiveFile.FontSection, "Width"); fontHeightUD.Bind(ActiveFile.FontSection, "Height"); + ReloadCharacterCodes(); ReloadTextures(); } + private void ReloadCharacterCodes() + { + foreach (char entry in ActiveFile.FontSection.CodeMapDictionary.Keys) + characterCodeCB.Items.Add(entry); + + if (ActiveFile.FontSection.CodeMapDictionary.Count > 0) + characterCodeCB.SelectedIndex = 0; + } + private void ReloadTextures() { imagesCB.Items.Clear(); @@ -61,15 +73,24 @@ namespace FirstPlugin.Forms if (IsBntx) { - pictureBoxCustom1.Image = image.GetBitmap(ImageIndex); + PanelImage = image.GetBitmap(ImageIndex); } else { - pictureBoxCustom1.Image = image.GetBitmap(); + PanelImage = image.GetBitmap(); } } } + private void pictureBox1_Paint(object sender, PaintEventArgs e) + { + Rectangle ee = new Rectangle(10, 10, 30, 30); + using (Pen pen = new Pen(Color.Red, 2)) + { + e.Graphics.DrawRectangle(pen, ee); + } + } + private void exportToolStripMenuItem_Click(object sender, EventArgs e) { int ImageIndex = imagesCB.SelectedIndex; @@ -85,10 +106,60 @@ namespace FirstPlugin.Forms } } + public class FontCell + { + public Rectangle DrawnRectangle; + + public Color Color { get; set; } + + public FontCell() + { + Color = Color.Cyan; + } + } + + private FontCell[] FontCells; + + private void imagePanel_Paint(object sender, PaintEventArgs e) + { + Graphics graphics = e.Graphics; + graphics.DrawImage(PanelImage, 0.0f, 0.0f); + + if (ActiveFile == null) + return; + + var textureGlyph = ActiveFile.FontSection.TextureGlyph; + + FontCells = new FontCell[textureGlyph.ColumnCount * textureGlyph.RowCount]; + + int CellPosY = 0; + for (int c = 0; c < (int)textureGlyph.ColumnCount; c++) + { + int CellPosX = 0; + for (int r = 0; r < (int)textureGlyph.RowCount; r++) + { + int Index = c + r; + + FontCells[Index] = new FontCell(); + FontCells[Index].DrawnRectangle = new Rectangle() + { + X = CellPosX, + Y = CellPosY, + Width = (int)textureGlyph.CellWidth, + Height = (int)textureGlyph.CellHeight, + }; + + graphics.DrawRectangle(new Pen(FontCells[Index].Color), FontCells[Index].DrawnRectangle); + CellPosX += (int)textureGlyph.CellWidth; + } + CellPosY += (int)textureGlyph.CellHeight; + } + } + private void copyToolStripMenuItem_Click(object sender, EventArgs e) { - if (pictureBoxCustom1.Image != null) - Clipboard.SetImage(pictureBoxCustom1.Image); + if (PanelImage != null) + Clipboard.SetImage(PanelImage); } } } diff --git a/File_Format_Library/GUI/BFFNT/BffntEditor.resx b/File_Format_Library/GUI/BFFNT/BffntEditor.resx index 4b04e0f9..647b29d3 100644 --- a/File_Format_Library/GUI/BFFNT/BffntEditor.resx +++ b/File_Format_Library/GUI/BFFNT/BffntEditor.resx @@ -117,214 +117,6 @@ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - - iVBORw0KGgoAAAANSUhEUgAAAlgAAAJYCAMAAACJuGjuAAAABGdBTUEAALGPC/xhBQAAACBjSFJNAAB6 - JgAAgIQAAPoAAACA6AAAdTAAAOpgAAA6mAAAF3CculE8AAADAFBMVEXMzMzNzc3Ozs7Pz8/Q0NDR0dHS - 0tLT09PU1NTV1dXW1tbX19fY2NjZ2dna2trb29vc3Nzd3d3e3t7f39/g4ODh4eHi4uLj4+Pk5OTl5eXm - 5ubn5+fo6Ojp6enq6urr6+vs7Ozt7e3u7u7v7+/w8PDx8fHy8vLz8/P09PT19fX29vb39/f4+Pj5+fn6 - +vr7+/v8/Pz9/f3+/v7///8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACDTbOhAAAACXBIWXMAAA7DAAAOwwHHb6hkAAAAGXRF - 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 - - 17, 17