Subversion Repositories AndroidProjects

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
1051 chris 1
package com.gebauz.bauzoid.graphics;
2
 
3
import java.io.IOException;
4
import java.util.Vector;
5
 
6
import com.badlogic.gdx.Gdx;
7
import com.badlogic.gdx.files.FileHandle;
8
import com.gebauz.bauzoid.app.Consts;
9
import com.gebauz.bauzoid.file.File;
10
import com.gebauz.bauzoid.file.FileUtil;
11
import com.gebauz.bauzoid.graphics.sprite.Sprite;
12
import com.gebauz.bauzoid.graphics.sprite.SpriteRegion;
13
import com.gebauz.bauzoid.parser.ScanException;
14
import com.gebauz.bauzoid.parser.Tokenizer;
15
 
16
public class FontUtil
17
{
18
        public static final String LOG_TAG = Consts.LOG_TAG + ":FontUtil";
19
        public static boolean verbose = true;
20
 
21
        private static class CharacterRect
22
        {
23
                public float x;
24
                public float y;
25
                public float w;
26
                public float h;
27
 
28
                public CharacterRect(float _x, float _y, float _w, float _h)
29
                {
30
                        x = _x;
31
                        y = _y;
32
                        w = _w;
33
                        h = _h;
34
                }
35
        }
36
 
37
        private static class CharacterOffset
38
        {
39
                public float x;
40
                public float y;
41
 
42
                public CharacterOffset(float _x, float _y)
43
                {
44
                        x = _x;
45
                        y = _y;
46
                }
47
        }
48
 
49
        private static class KerningPair
50
        {
51
                public char first;
52
                public char second;
53
                public int value;
54
 
55
                public KerningPair(char a, char b, int n)
56
                {
57
                        first = a;
58
                        second = b;
59
                        value = n;
60
                }
61
        }
62
 
63
 
64
        private FontUtil() {}
65
 
66
        public static void log(String tag, String msg)
67
        {
68
                if (verbose)
69
                        Gdx.app.log(tag, msg);                 
70
        }
71
 
72
        public static Font createFontFromBinaryFile(Graphics graphics, FileHandle file)
73
        {
74
                Vector<Character> charList = new Vector<Character>();
75
                Vector<Float> widthList = new Vector<Float>();
76
                Vector<CharacterRect> rectList = new Vector<CharacterRect>();
77
                Vector<CharacterOffset> offsetList = new Vector<CharacterOffset>();
78
                Vector<KerningPair> kerningPairs = new Vector<KerningPair>();
79
 
80
                //Font font = new Font(graphics);
81
                //Texture texture = null;
82
                String textureFileFull = null;
83
 
84
                float multiplier = 1.0f;
85
                float ascent = 10.0f;
86
 
87
                try
88
                {
89
                        File f = new File(file.read());
90
 
91
                        int version = f.readInt();
92
                        if (version != 100)
93
                        {
94
                                Gdx.app.log(LOG_TAG, "Version mismatch: 100 != " + version);
95
                                return null;
96
                        }                      
97
 
98
                        String textureFile = f.readString();
99
                        textureFileFull = FileUtil.extractPath(file.path()) + "/" + textureFile;
100
                        //texture = new Texture(Gdx.files.internal(filename));
101
 
102
                        ascent = f.readFloat();
103
                        multiplier = f.readFloat();
104
 
105
                        // Read character list (char * num)
106
                        int numChars = f.readInt(); // number of characters
107
                        for (int i = 0; i < numChars; i++)
108
                        {
109
                                Character c = f.readChar();
110
                                charList.add(c);                               
111
                        }
112
 
113
                        // Read width list (float * num)
114
                        int numWidths = f.readInt(); // number of widths
115
                        for (int i = 0; i < numWidths; i++)
116
                        {
117
                                Float width = f.readFloat();
118
                                widthList.add(width);
119
                        }
120
 
121
                        // Read rect list (CharRect * num)
122
                        int numRects = f.readInt(); // number of rects
123
                        for (int i = 0; i < numRects; i++)
124
                        {
125
                                float x = f.readFloat();
126
                                float y = f.readFloat();
127
                                float w = f.readFloat();
128
                                float h = f.readFloat();
129
 
130
                                rectList.add(new CharacterRect(x, y, w, h));
131
                        }
132
 
133
                        // Read offset list (CharOffset * num)
134
                        int numOffsets = f.readInt(); // number of offsets
135
                        for (int i = 0; i < numOffsets; i++)
136
                        {
137
                                float x = f.readFloat();
138
                                float y = f.readFloat();
139
 
140
                                offsetList.add(new CharacterOffset(x, y));                             
141
                        }
142
 
143
                        // number of kerning pairs
144
                        int numKerning = f.readInt();
145
 
146
                        // Read kerning pairs + values
147
                        for (int i = 0; i < numKerning; i++)
148
                        {
149
                                char a = f.readChar();
150
                                char b = f.readChar();
151
                                int v = f.readInt();
152
 
153
                                kerningPairs.add(new KerningPair(a, b, v));                            
154
                        }
155
 
156
                        f.close();
157
                }
158
                catch (IOException e)
159
                {
160
                        Gdx.app.log(LOG_TAG, "Could not read font!");          
161
                }
162
 
163
                return buildFont(graphics, charList, widthList, rectList, offsetList, textureFileFull, multiplier, ascent, kerningPairs);
164
        }
165
 
166
        public static Font createFontFromFile(Graphics graphics, FileHandle file)
167
        {
168
                String fileContents = file.readString();
169
 
170
                Vector<Character> charList = null;
171
                Vector<Float> widthList = null;
172
                Vector<CharacterRect> rectList = null;
173
                Vector<CharacterOffset> offsetList = null;
174
                Vector<KerningPair> kerningPairs = null;
175
                Vector<Integer> kerningValues = null;
176
 
177
                //Texture texture = null;
178
                String textureFile = null;
179
 
180
                float ascent = 10.0f;          
181
                float multiplier = 1.0f;
182
 
183
                try
184
                {
185
                        Tokenizer tokenizer = new Tokenizer(fileContents);
186
                        tokenizer.setStringDelimiter(new char[] {'\'', '"'} );
187
 
188
                        while (!tokenizer.checkNoMoreTokens())
189
                        {
190
                                String identifier = tokenizer.readIdentifier();
191
 
192
                                if (identifier.equalsIgnoreCase("Define"))
193
                                {
194
                                        // Define
195
                                        String define = tokenizer.readIdentifier();
196
 
197
                                        if (define.equalsIgnoreCase("CharList"))
198
                                        {
199
                                                charList = parseCharList(tokenizer);
200
                                        }
201
                                        else if (define.equalsIgnoreCase("WidthList"))
202
                                        {
203
                                                widthList = parseWidthList(tokenizer);
204
                                        }
205
                                        else if (define.equalsIgnoreCase("RectList"))
206
                                        {
207
                                                rectList = parseRectList(tokenizer);
208
                                        }
209
                                        else if (define.equalsIgnoreCase("OffsetList"))
210
                                        {
211
                                                offsetList = parseOffsetList(tokenizer);
212
                                        }
213
                                        else if (define.equalsIgnoreCase("KerningPairs"))
214
                                        {
215
                                                kerningPairs = parseKerningPairs(tokenizer);                                           
216
                                        }
217
                                        else if (define.equalsIgnoreCase("KerningValues"))
218
                                        {
219
                                                kerningValues = parseKerningValues(tokenizer);
220
                                        }
221
                                        tokenizer.readToken(";");
222
                                }
223
                                else if (identifier.equalsIgnoreCase("CreateLayer"))
224
                                {
225
                                        tokenizer.readIdentifier();
226
                                        tokenizer.readToken(";");
227
                                }
228
                                else if (identifier.equalsIgnoreCase("LayerSetImage"))
229
                                {
230
                                        tokenizer.readIdentifier();
231
                                        //String filename = FileUtil.extractPath(file.path()) + "/" + tokenizer.readString() + ".png";
232
                                        textureFile = FileUtil.extractPath(file.path()) + "/" + tokenizer.readString() + ".png";
233
 
234
                                        //texture = new Texture(Gdx.files.internal(filename));
235
 
236
                                        tokenizer.readToken(";");
237
                                }
238
                                else if (identifier.equalsIgnoreCase("LayerRegionMultiplier"))
239
                                {
240
                                        tokenizer.readIdentifier();
241
 
242
                                        multiplier = tokenizer.readNumber();
243
                                        tokenizer.readToken(";");
244
                                }
245
                                else if (identifier.equalsIgnoreCase("LayerSetAscent"))
246
                                {
247
                                        tokenizer.readIdentifier();
248
                                        ascent = tokenizer.readNumber();
249
                                        tokenizer.readToken(";");
250
                                }
251
                                else if (identifier.equalsIgnoreCase("LayerSetCharWidths"))
252
                                {
253
                                        tokenizer.readIdentifier();
254
                                        if (tokenizer.checkIdentifier())
255
                                        {
256
                                                tokenizer.readIdentifier();
257
                                                tokenizer.readIdentifier();
258
                                        }
259
                                        else if (tokenizer.checkToken("("))
260
                                        {
261
                                                Vector<Character> charListExtra = parseCharList(tokenizer);
262
                                                Vector<Float> widthListExtra = parseWidthList(tokenizer);
263
 
264
                                                charList.addAll(charListExtra);
265
                                                widthList.addAll(widthListExtra);
266
                                        }
267
                                        tokenizer.readToken(";");
268
                                }
269
                                else if (identifier.equalsIgnoreCase("LayerSetImageMap"))
270
                                {
271
                                        tokenizer.readIdentifier();
272
                                        tokenizer.readIdentifier();
273
                                        tokenizer.readIdentifier();
274
                                        tokenizer.readToken(";");
275
                                }
276
                                else if (identifier.equalsIgnoreCase("LayerSetCharOffsets"))
277
                                {
278
                                        tokenizer.readIdentifier();
279
                                        tokenizer.readIdentifier();
280
                                        tokenizer.readIdentifier();
281
                                        tokenizer.readToken(";");
282
                                }              
283
                                else if (identifier.equalsIgnoreCase("LayerSetAscentPadding"))
284
                                {
285
                                        tokenizer.readIdentifier();
286
                                        tokenizer.readNumber();
287
                                        tokenizer.readToken(";");
288
                                }              
289
                                else if (identifier.equalsIgnoreCase("LayerSetLineSpacingOffset"))
290
                                {
291
                                        tokenizer.readIdentifier();
292
                                        tokenizer.readNumber();
293
                                        tokenizer.readToken(";");
294
                                }              
295
                                else if (identifier.equalsIgnoreCase("LayerSetPointSize"))
296
                                {
297
                                        tokenizer.readIdentifier();
298
                                        tokenizer.readNumber();
299
                                        tokenizer.readToken(";");
300
                                }              
301
                                else if (identifier.equalsIgnoreCase("SetDefaultPointSize"))
302
                                {
303
                                        tokenizer.readNumber();
304
                                        tokenizer.readToken(";");
305
                                }
306
                                else if (identifier.equalsIgnoreCase("LayerSetKerningPairs"))
307
                                {
308
                                        tokenizer.readIdentifier();
309
                                        tokenizer.readIdentifier();
310
                                        tokenizer.readIdentifier();
311
                                        tokenizer.readToken(";");
312
 
313
                                        // set kerning values
314
                                        for (int i = 0; i < kerningPairs.size(); i++)
315
                                        {
316
                                                kerningPairs.elementAt(i).value = kerningValues.elementAt(i);
317
                                        }
318
                                }
319
                                else if (identifier.equalsIgnoreCase("ConvertGreyScaleToAlpha"))
320
                                {
321
                                        tokenizer.readNumber();
322
                                        tokenizer.readToken(";");
323
                                }
324
                        }
325
 
326
                }
327
                catch (ScanException ex)
328
                {
329
                        ex.log(LOG_TAG);
330
                }
331
 
332
                return buildFont(graphics, charList, widthList, rectList, offsetList, textureFile, multiplier, ascent, kerningPairs);
333
        }
334
 
335
        private static Font buildFont(Graphics graphics, Vector<Character> charList, Vector<Float> widthList, Vector<CharacterRect> rectList, Vector<CharacterOffset> offsetList,
336
                        String textureFile, float multiplier, float ascent, Vector<KerningPair> kerningPairs)
337
        {
338
                // Build font
339
                if (textureFile == null)
340
                {
341
                        Gdx.app.log(LOG_TAG, "No font file specified!");
342
                        return null;
343
                }
344
 
345
                Font font = new Font(graphics);
346
 
347
                Font.CharacterInfo[] characters = new Font.CharacterInfo[charList.size()];
348
                SpriteRegion[] regions = new SpriteRegion[rectList.size()];
349
 
350
                Sprite sprite = new Sprite(graphics, textureFile);
351
                sprite.init();
352
 
353
                for (int i = 0; i < characters.length; i++)
354
                {
355
                        characters[i] = new Font.CharacterInfo(charList.elementAt(i));
356
 
357
                        characters[i].width = widthList.elementAt(i);
358
 
359
                        if (i < offsetList.size())
360
                        {
361
                                characters[i].offsetX = offsetList.elementAt(i).x;
362
                                characters[i].offsetY = offsetList.elementAt(i).y;
363
                        }
364
 
365
                        if (i < rectList.size())
366
                        {
367
                                CharacterRect rect = rectList.elementAt(i);
368
 
369
                                /*characters[i].texX = rectList.elementAt(i).x;
370
                                characters[i].texY = rectList.elementAt(i).y;
371
                                characters[i].texW = rectList.elementAt(i).w;
372
                                characters[i].texH = rectList.elementAt(i).h;*/
373
                                regions[i] = new SpriteRegion(sprite, i, rect.x / multiplier, rect.y / multiplier, rect.w / multiplier, rect.h / multiplier, true);
374
                        }
375
                }
376
                sprite.setRegions(regions);
377
 
378
                //AtlasSprite sprite = new AtlasSprite(graphics, texture, regions);
379
 
380
                for (int i = 0; i < regions.length; i++)
381
                {
382
                        characters[i].setSpriteInstance(sprite.createSpriteInstance(i));
383
                }
384
 
385
                font.setCharacters(characters);
386
                font.setSprite(sprite);        
387
                font.setAscent(ascent);
388
                font.setGlobalMultiplier(multiplier);
389
 
390
                for (int i = 0; i < kerningPairs.size(); i++)
391
                {
392
                        KerningPair pair = kerningPairs.elementAt(i);
393
                        font.setKerning(pair.first, pair.second, pair.value);
394
                }
395
 
396
                return font;
397
        }
398
 
399
        private static Vector<Character> parseCharList(Tokenizer t) throws ScanException
400
        {
401
                Vector<Character> charList = new Vector<Character>();
402
 
403
                t.readToken("(");
404
 
405
                while (!t.checkToken(")"))
406
                {
407
                        String character = t.readString();
408
 
409
                        if (character.length() > 1)
410
                                throw new ScanException("Character can only have length 1!", t.getSurroundings());
411
 
412
                        charList.add(character.charAt(0));
413
 
414
                        if (t.checkToken(")"))
415
                                break;
416
 
417
                        t.readToken(",");
418
                }                              
419
 
420
                t.readToken(")");
421
 
422
                return charList;
423
        }
424
 
425
        private static Vector<Float> parseWidthList(Tokenizer t) throws ScanException
426
        {
427
                Vector<Float> widthList = new Vector<Float>();
428
 
429
                t.readToken("(");
430
 
431
                while (!t.checkToken(")"))
432
                {
433
                        float width = t.readNumber();
434
 
435
                        widthList.add(width);
436
 
437
                        if (t.checkToken(")"))
438
                                break;
439
 
440
                        //Gdx.app.log(LOG_TAG, "[" + width + "]");
441
 
442
                        t.readToken(",");
443
                }                              
444
 
445
                t.readToken(")");
446
 
447
                return widthList;
448
        }
449
 
450
        private static Vector<CharacterRect> parseRectList(Tokenizer t) throws ScanException
451
        {
452
                Vector<CharacterRect> rectList = new Vector<CharacterRect>();
453
 
454
                t.readToken("(");
455
 
456
                while (t.checkToken("("))
457
                {
458
                        t.readToken("(");
459
 
460
                        float x = t.readNumber();
461
                        t.readToken(",");
462
                        float y = t.readNumber();
463
                        t.readToken(",");
464
                        float w = t.readNumber();
465
                        t.readToken(",");
466
                        float h = t.readNumber();
467
 
468
                        rectList.add(new CharacterRect(x, y, w, h));
469
 
470
                        t.readToken(")");
471
 
472
                        if (!t.checkToken(","))
473
                                break;
474
 
475
                        t.readToken(",");
476
                }              
477
 
478
                if (!t.checkToken(")"))
479
                        throw new ScanException("Syntax error in RectList!", t.getSurroundings());
480
 
481
                t.readToken(")");
482
 
483
                return rectList;
484
        }
485
 
486
        private static Vector<CharacterOffset> parseOffsetList(Tokenizer t) throws ScanException
487
        {
488
                Vector<CharacterOffset> offsetList = new Vector<CharacterOffset>();
489
 
490
                t.readToken("(");
491
 
492
                while (t.checkToken("("))
493
                {
494
                        t.readToken("(");
495
 
496
                        float x = t.readNumber();
497
                        t.readToken(",");
498
                        float y = t.readNumber();
499
 
500
                        offsetList.add(new CharacterOffset(x, y));
501
 
502
                        t.readToken(")");
503
 
504
                        if (!t.checkToken(","))
505
                                break;
506
 
507
                        t.readToken(",");
508
                }              
509
 
510
                if (!t.checkToken(")"))
511
                        throw new ScanException("Syntax error in OffsetList!", t.getSurroundings());
512
 
513
                t.readToken(")");
514
 
515
                return offsetList;
516
        }
517
 
518
        private static Vector<KerningPair> parseKerningPairs(Tokenizer t) throws ScanException
519
        {
520
                Vector<KerningPair> kerningPairs = new Vector<KerningPair>();
521
 
522
                t.readToken("(");
523
 
524
                while (!t.checkToken(")"))
525
                {
526
                        String pair = t.readString();
527
 
528
                        kerningPairs.add(new KerningPair(pair.charAt(0), pair.charAt(1), 0));
529
 
530
                        if (t.checkToken(")"))
531
                                break;
532
 
533
                        //Gdx.app.log(LOG_TAG, "[" + width + "]");
534
 
535
                        t.readToken(",");
536
                }                              
537
 
538
                t.readToken(")");
539
 
540
                return kerningPairs;
541
        }
542
 
543
        private static Vector<Integer> parseKerningValues(Tokenizer t) throws ScanException
544
        {
545
                Vector<Integer> kerningValues = new Vector<Integer>();
546
 
547
                t.readToken("(");
548
 
549
                while (!t.checkToken(")"))
550
                {
551
                        int value = (int)t.readNumber();
552
 
553
                        kerningValues.add(value);
554
 
555
                        if (t.checkToken(")"))
556
                                break;
557
 
558
                        //Gdx.app.log(LOG_TAG, "[" + width + "]");
559
 
560
                        t.readToken(",");
561
                }                              
562
 
563
                t.readToken(")");
564
 
565
                return kerningValues;
566
        }
567
}