-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathFontV2.cs
140 lines (130 loc) · 4.52 KB
/
FontV2.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
using System;
using System.IO;
namespace Nevosoft
{
/// <summary>
/// Glyph data from <see cref="FontV2"/>
/// </summary>
public struct GlyphData
{
/// <summary>
/// Glyph width in pixels
/// </summary>
public ushort GlyphWidth;
/// <summary>
/// Symbol that denotes this glyph
/// </summary>
public char Glyph;
}
/// <summary>
/// Font class from Nevosoft games after 2007. Has the ".dat" extension<br/>
/// In addition should have an image with characters, but there is no method to create it
/// </summary>
public class FontV2
{
/// <summary>
/// Width of additional texture
/// </summary>
public ushort TextureWidth;
/// <summary>
/// Height of additional texture
/// </summary>
public ushort TextureHeight;
/// <summary>
/// Number of glyphs in each row
/// </summary>
public uint GlyphsPerRow;
/// <summary>
/// Array of <see cref="GlyphData"/> in the class (maximum 1024)
/// </summary>
/// <returns>
/// <see cref="GlyphData"/> at the given index
/// </returns>
public GlyphData[] Glyphs = new GlyphData[1024];
/// <summary>
/// Create object of class
/// </summary>
public FontV2() { }
/// <summary>
/// Open font from file
/// </summary>
public FontV2(string filename) => Load(filename);
/// <summary>
/// Open font from <see cref="Stream"/>
/// </summary>
public FontV2(Stream stream) => Load(stream);
/// <summary>
/// Create object of class from the given file
/// </summary>
public FontV2 FromFile(string filename) => new FontV2(filename);
/// <summary>
/// Create object of class from <see cref="Stream"/>
/// </summary>
public FontV2 FromStream(Stream stream) => new FontV2(stream);
/// <summary>
/// Save font to file
/// </summary>
public void Save(string filename)
{
using (FileStream fs = new FileStream(filename,
FileMode.Create, FileAccess.Write, FileShare.None))
Save(fs);
}
private void Load(string filename)
{
if (!File.Exists(filename))
throw new FileNotFoundException("File \"" + filename + "\" not found!");
using (FileStream FS = new FileStream(filename, FileMode.Open))
Load(FS);
}
private void Load(Stream stream)
{
if (stream == null)
throw new ArgumentNullException();
if (!(stream.CanRead && stream.CanSeek))
throw new FileLoadException("Stream reading or seeking is not avaiable!");
if (stream.Length != 4104)
throw new Exception("This file is not a font file");
stream.Seek(0, SeekOrigin.Begin);
using (BinaryReader br = new BinaryReader(stream))
{
TextureWidth = br.ReadUInt16();
TextureHeight = br.ReadUInt16();
GlyphsPerRow = br.ReadUInt32();
uint glyphsPerColumn = GlyphsPerRow;
if (TextureWidth > TextureHeight)
glyphsPerColumn /= 2;
uint glyphCount = GlyphsPerRow * glyphsPerColumn;
for (uint i = 0; i < glyphCount; i++)
{
Glyphs[i].GlyphWidth = br.ReadUInt16();
Glyphs[i].Glyph = (char)br.ReadUInt16();
}
}
}
/// <summary>
/// Save font to <see cref="Stream"/>
/// </summary>
public void Save(Stream stream)
{
if (stream == null)
throw new ArgumentNullException();
if (!(stream.CanWrite && stream.CanSeek))
throw new FileLoadException("Stream writing or seeking is not avaiable!");
stream.Seek(0, SeekOrigin.Begin);
using (BinaryWriter bw = new BinaryWriter(stream))
{
bw.Write(TextureWidth);
bw.Write(TextureHeight);
bw.Write(GlyphsPerRow);
foreach (GlyphData i in Glyphs)
{
bw.Write(i.GlyphWidth);
bw.Write((ushort)i.Glyph);
}
bw.Seek(1023 * 4 + 8, SeekOrigin.Begin);
bw.Write(0);
}
}
}
}