-
Notifications
You must be signed in to change notification settings - Fork 347
/
Copy pathFont.hx
334 lines (304 loc) · 9.29 KB
/
Font.hx
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
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
package h2d;
/**
A `FontChar` kerning information as well as linked list of kernings. See `FontChar.kerning`.
**/
class Kerning {
/**
A character that should precede current character in order to apply this kerning.
**/
public var prevChar : Int;
/**
A kerning offset between the character pair in pixels.
**/
public var offset : Float;
/**
The next kerning reference.
**/
public var next : Null<Kerning>;
/**
Create a new kerning instance.
@param c The preceding character.
@param o The kerning offset.
**/
public function new(c, o) {
this.prevChar = c;
this.offset = o;
}
}
/**
A single `Font` character descriptor.
**/
class FontChar {
/**
A Tile representing position of a character on the texture.
**/
public var t : h2d.Tile;
/**
Horizontal advance value of the character.
On top of advance, letter spacing is affected by `FontChar.kerning` matches and `Text.letterSpacing`.
**/
public var width : Float;
/**
Linked list of kerning values.
In order to add new kerning values use `FontChar.addKerning` and `FontChar.getKerningOffset` to retrieve kerning offsets.
**/
@:dox(show)
var kerning : Null<Kerning>;
/**
Create a new font character.
@param t The character Tile.
@param width The horizontal advance of the character.
**/
public function new(t,w) {
this.t = t;
this.width = w;
}
/**
Adds a new kerning to the character with specified `prevChar` and `offset`.
**/
public function addKerning( prevChar : Int, offset : Int ) {
var k = new Kerning(prevChar, offset);
k.next = kerning;
kerning = k;
}
/**
Returns kerning offset for a pair `[prevChar, currentChar]` or `0` if there was no paired kerning value.
**/
public function getKerningOffset( prevChar : Int ) {
var k = kerning;
while( k != null ) {
if( k.prevChar == prevChar )
return k.offset;
k = k.next;
}
return 0;
}
/**
Clones the character instance.
**/
public function clone() {
var c = new FontChar(t.clone(), width);
// Clone entire kerning tree in case Font got resized.
var k = kerning;
if ( k != null ) {
var kc = new Kerning(k.prevChar, k.offset);
c.kerning = kc;
k = k.next;
while ( k != null ) {
var kn = new Kerning(k.prevChar, k.offset);
kc = kc.next = kn;
k = k.next;
}
}
return c;
}
}
/**
Channel reading method for `FontType.SignedDistanceField`.
**/
enum abstract SDFChannel(Int) from Int to Int {
/** Use red channel of a texture to determine distance. **/
var Red = 0;
/** Use green channel of a texture to determine distance. **/
var Green = 1;
/** Use blue channel of a texture to determine distance. **/
var Blue = 2;
/** Use alpha channel of a texture to determine distance. **/
var Alpha = 3;
/** Use RGB channels of a texture to determine distance. See here for details: https://github.com/Chlumsky/msdfgen **/
var MultiChannel = 4;
}
/**
The rendering type of the of the `Font` instance.
**/
enum FontType {
/**
A simple raster bitmap font.
**/
BitmapFont;
/**
A Signed Distance Field font data. Each glyph pixel contains the distance to the closest glyph edge instead of actual color.
To render an SDF font, `Text` utilizes `h3d.shader.SignedDistanceField` shader to produce smoothed and scalable text.
Because shader expects texture to use bilinear filtering, Text automatically enables `Drawable.smooth` on itself.
See [Text](https://github.com/HeapsIO/heaps/wiki/Text) manual and [libgdx wiki](https://github.com/libgdx/libgdx/wiki/Distance-field-fonts) for more details.
@param channel The channel that serves as distance data source.
@param alphaCutoff The distance value that is considered to be the edge. Usually should be 0.5.
@param smoothing The smoothing of edge. Lower value lead to sharper edges. Value of -1 sets it to automatic.
**/
SignedDistanceField(channel : SDFChannel, alphaCutoff : Float, smoothing : Float);
}
/**
An instance of a text font.
Heaps comes with a default Font that covers basic ASCII characters, and can be retrieved via `hxd.res.DefaultFont.get()`.
**/
class Font {
/**
The font name. Assigned on font creation and can be used to identify font instances.
**/
public var name(default, null) : String;
/**
Current font size. Font can be resized with `resizeTo`.
**/
public var size(default, null) : Int;
/**
The baseline value of the font represents the base on which characters will sit.
Used primarily with `HtmlText` to sit multiple fonts and images at the same line.
**/
public var baseLine(default, null) : Float;
/**
Font line height provides vertical offset for each new line of the text.
**/
public var lineHeight(default, null) : Float;
/**
Reference to the source Tile containing all glyphs of the Font.
**/
public var tile(default,null) : h2d.Tile;
/**
The resource path of the source Tile. Either relative to .fnt or to resources root.
**/
public var tilePath(default,null) : String;
/**
The font type. BitmapFonts rendered as-is, but SDF fonts will use an extra shader to produce scalable smooth fonts.
See `FontType.SignedDistanceField` for more details.
**/
public var type : FontType;
/**
Font charset allows to resolve specific char codes that are not directly present in glyph map as well as detect spaces.
Defaults to `hxd.Charset.getDefault()`.
**/
public var charset : hxd.Charset;
var glyphs : Map<Int,FontChar>;
var nullChar : FontChar;
var defaultChar : FontChar;
var initSize:Int;
var offsetX:Float = 0;
var offsetY:Float = 0;
/**
Creates an empty font instance with specified parameters.
@param name The name of the font.
@param size Initial size of the font.
@param type The font type.
**/
function new(name : String, size : Int, ?type : FontType) {
this.name = name;
this.size = size;
this.initSize = size;
glyphs = new Map();
defaultChar = nullChar = new FontChar(new Tile(null, 0, 0, 0, 0),0);
charset = hxd.Charset.getDefault();
if (name != null)
this.tilePath = haxe.io.Path.withExtension(name, "png");
if (type == null)
this.type = BitmapFont;
else
this.type = type;
}
/**
Returns a `FontChar` instance corresponding to the `code`.
If font char is not present in glyph list, `charset.resolveChar` is called.
Returns `null` if glyph under specified charcode does not exist.
@param code The charcode to search for.
**/
public inline function getChar( code : Int ) {
var c = glyphs.get(code);
if( c == null ) {
c = charset.resolveChar(code, glyphs);
if( c == null )
c = code == "\r".code || code == "\n".code ? nullChar : defaultChar;
}
return c;
}
/**
Offsets all glyphs by specified amount.
Affects each glyph `Tile.dx` and `Tile.dy`.
@param x The X offset of the glyphs.
@param y The Y offset of the glyphs.
**/
public function setOffset( x : Float, y :Float ) {
var dx = x - offsetX;
var dy = y - offsetY;
if( dx == 0 && dy == 0 ) return;
for( g in glyphs ) {
g.t.dx += dx;
g.t.dy += dy;
}
this.offsetX += dx;
this.offsetY += dy;
}
/**
Creates a copy of the font instance.
**/
public function clone() {
var f = new Font(name, size);
f.baseLine = baseLine;
f.lineHeight = lineHeight;
f.tile = tile.clone();
f.charset = charset;
f.defaultChar = defaultChar.clone();
f.type = type;
f.offsetX = offsetX;
f.offsetY = offsetY;
for( g in glyphs.keys() ) {
var c = glyphs.get(g);
var c2 = c.clone();
if( c == defaultChar )
f.defaultChar = c2;
f.glyphs.set(g, c2);
}
return f;
}
/**
Resizes the Font instance to specified size.
For BitmapFonts it can be used to create smoother fonts by rasterizing them with double size while still keeping the original glyph size by downscaling the font.
And SDF fonts can be resized to arbitrary sizes to produce scalable fonts of any size.
@param size The new font size.
**/
public function resizeTo( size : Int ) {
var ratio = size / this.size;
for( c in glyphs ) {
c.width *= ratio;
c.t.scaleToSize(c.t.width * ratio, c.t.height * ratio);
c.t.dx *= ratio;
c.t.dy *= ratio;
var k = @:privateAccess c.kerning;
while ( k != null ) {
k.offset *= ratio;
k = k.next;
}
}
lineHeight = Math.ceil(lineHeight * ratio);
baseLine = Math.ceil(baseLine * ratio);
this.size = size;
}
/**
Checks if character is present in glyph list.
Compared to `getChar` does not check if it exists through `Font.charset`.
@param code The charcode to look up.
**/
public function hasChar( code : Int ) : Bool {
return glyphs.get(code) != null;
}
/**
Disposes of the Font instance. Equivalent to `Tile.dispose`.
**/
public function dispose() {
tile.dispose();
}
/**
Calculate a baseLine default value based on available glyphs.
*/
public function calcBaseLine() {
var padding : Float = 0;
var space = glyphs.get(" ".code);
if( space != null )
padding = (space.t.height * .5);
var a = glyphs.get("A".code);
if( a == null )
a = glyphs.get("a".code);
if( a == null )
a = glyphs.get("0".code); // numerical only
if( a == null )
return lineHeight - 2 - padding;
return a.t.dy + a.t.height - padding;
}
}