Subversion Repositories AndroidProjects

Rev

Rev 1456 | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
1454 chris 1
using System;
2
using System.Collections.Generic;
3
using System.Linq;
4
using System.Text;
5
using System.Threading.Tasks;
6
 
7
using BauzoidNET.math;
8
using BauzoidNET.graphics.sprite;
9
using BauzoidNET.graphics.texture;
10
 
11
namespace BauzoidNET.graphics
12
{
13
    public class Font : GraphicsObject
14
    {
15
        public static readonly Vector4 DEFAULT_COLOR = new Vector4(1, 1, 1, 1);
16
 
17
            public class KerningPair
18
            {
19
                    public char first;
20
                    public char second;
21
 
22
                    public KerningPair(char a, char b)
23
                    {
24
                            first = a;
25
                            second = b;
26
                    }
27
 
28
                    public override bool Equals(Object other)
29
                    {
30
                        // Not strictly necessary, but often a good optimization
31
                        if (this == other)
32
                          return true;
33
 
34
                        if (!(other is KerningPair))
35
                          return false;
36
 
37
                        KerningPair p = (KerningPair)other;
38
 
39
                        return ((first == p.first) && (second == p.second));
40
                    }
41
 
42
                    public override int GetHashCode()
43
                    {
44
                            return (first * 256) + second;                     
45
                    }
46
            }
47
 
48
            public class CharacterInfo
49
            {
50
                    private char mCharacter;
51
                    public SpriteInstance mSpriteInstance = null;
52
 
53
                    public float offsetX = 0;
54
                    public float offsetY = 0;
55
 
56
                    public float width;
57
 
58
                    public CharacterInfo(char c)
59
                    {
60
                            mCharacter = c;
61
                    }
62
 
63
                    public char getCharacter()
64
                    {
65
                            return mCharacter;
66
                    }
67
 
68
                    public void setSpriteInstance(SpriteInstance instance)
69
                    {
70
                            mSpriteInstance = instance;
71
                    }
72
 
73
                    public SpriteInstance getSpriteInstance()
74
                    {
75
                            return mSpriteInstance;
76
                    }
77
 
78
                    public void render()
79
                    {
80
                            if (mSpriteInstance == null)
81
                                    return;
82
 
83
                            mSpriteInstance.render();
84
                    }
85
            }
86
 
87
            private CharacterInfo[] mCharacters = null;
88
            private float mAscent = 0.0f;
89
            private float mGlobalMultiplier = 2.0f;
90
            private Sprite mSprite = null;
91
 
92
            //private Hashtable<KerningPair, Integer> mKernings = new Hashtable<KerningPair, Integer>();
93
        private Dictionary<KerningPair, int> mKernings = new Dictionary<KerningPair, int>();
94
 
95
            /** The y difference of a line break in multiples of line height. */
96
            private float mLineBreakFactor = 1.0f;
97
 
98
            public Font(Graphics graphics) :
99
            base(graphics)
100
            {
101
            }
102
 
103
            public void dispose()
104
            {
105
                    mCharacters = null;        
106
            }
107
 
108
            public void setAscent(float ascent)
109
            {
110
                    mAscent = ascent;
111
            }
112
 
113
            public void setCharacters(CharacterInfo[] characters)
114
            {
115
                    mCharacters = characters;
116
            }
117
 
118
            public void setSprite(Sprite sprite)
119
            {
120
                    mSprite = sprite;
121
            }
122
 
123
            public void setGlobalMultiplier(float multiplier)
124
            {
125
                    mGlobalMultiplier = multiplier;
126
            }
127
 
128
            public void drawText(string text, float x, float y, float scale)
129
            {
130
                    drawText(text, x, y, DEFAULT_COLOR, scale);
131
            }
132
 
133
            public void drawText(string text, float x, float y)
134
            {
135
                    drawText(text, x, y, DEFAULT_COLOR);
136
            }
137
 
138
            public void drawText(string text, float x, float y, Vector4 color)
139
            {
140
                    drawText(text, x, y, color, 1.0f);
141
            }
142
 
143
            public void drawTextDirect(string text, float x, float y, Vector4 color, float scale)
144
            {
145
                    float posX = x;
146
                    float posY = y;
147
 
148
                    for (int i = 0; i < text.Length; i++)
149
                    {
150
                            if (text[i] == '\n')
151
                            {
152
                                    posY += mAscent * mLineBreakFactor * scale;
153
                                    posX = x;
154
                                    continue;
155
                            }
156
 
157
                            int n = getCharacterIndexNoCase(text[i]);
158
                            if (n == -1)
159
                            {
160
                                    continue;
161
                            }
162
 
163
                            CharacterInfo c = mCharacters[n];
164
 
165
                            int kerning = 0;
166
                            if (i < (text.Length-1))
167
                            {
168
                                    // apply kerning if any
169
                                    char first = c.getCharacter();
170
                                    char second = text[i+1];
171
 
172
                                    kerning = getKerning(first, second);
173
                            }
174
                            if (c.mSpriteInstance != null)
175
                            {                  
176
                                    c.mSpriteInstance.transform.x = posX;
177
                                    c.mSpriteInstance.transform.y = posY;
178
                                    c.mSpriteInstance.color = color;
1458 chris 179
                                    c.mSpriteInstance.transform.w = c.mSpriteInstance.getSpriteRegion().getWidth() * scale * mGlobalMultiplier * c.mSpriteInstance.getSprite().getTextureWidth();
180
                    c.mSpriteInstance.transform.h = c.mSpriteInstance.getSpriteRegion().getHeight() * scale * mGlobalMultiplier * c.mSpriteInstance.getSprite().getTextureHeight();
1454 chris 181
                                    //c.mSpriteInstance.param.w = mSprite.getRegionWidth(c.mSpriteInstance.getRegionIndex()) * scale * mGlobalMultiplier;
182
                                    //c.mSpriteInstance.param.h = mSprite.getRegionHeight(c.mSpriteInstance.getRegionIndex()) * scale * mGlobalMultiplier;
183
                                    c.mSpriteInstance.transform.pivotX = 0;
184
                                    c.mSpriteInstance.transform.pivotY = 0;
185
                                    c.mSpriteInstance.render();
186
                            }
187
 
188
                            posX += c.width * scale + kerning - c.offsetX;
189
                    }
190
            }
191
 
192
            public void drawText(string text, float x, float y, Vector4 color, float scale)
193
            {
194
                    float posX = x;
195
                    float posY = y;
196
 
197
                    TileBatch batch = getGraphics().getBatch();
198
 
199
                    batch.begin();
200
 
201
                    for (int i = 0; i < text.Length; i++)
202
                    {
203
                            if (text[i] == '\n')
204
                            {
205
                                    posY += mAscent * mLineBreakFactor * scale;
206
                                    posX = x;
207
                                    continue;
208
                            }
209
 
210
                            int n = getCharacterIndexNoCase(text[i]);
211
                            if (n == -1)
212
                            {
213
                                    continue;
214
                            }
215
 
216
                            CharacterInfo c = mCharacters[n];
217
 
218
                            int kerning = 0;
219
                            if (i < (text.Length-1))
220
                            {
221
                                    // apply kerning if any
222
                                    char first = c.getCharacter();
223
                                    char second = text[i+1];
224
 
225
                                    kerning = getKerning(first, second);
226
                            }
227
                            if (c.mSpriteInstance != null)
228
                            {                  
229
                                    c.mSpriteInstance.transform.x = posX;
230
                                    c.mSpriteInstance.transform.y = posY;
231
                                    c.mSpriteInstance.color = color;
1458 chris 232
                    c.mSpriteInstance.transform.w = c.mSpriteInstance.getSpriteRegion().getWidth() * scale * mGlobalMultiplier * c.mSpriteInstance.getSprite().getTextureWidth();
233
                    c.mSpriteInstance.transform.h = c.mSpriteInstance.getSpriteRegion().getHeight() * scale * mGlobalMultiplier * c.mSpriteInstance.getSprite().getTextureHeight();
1454 chris 234
                                    //c.mSpriteInstance.param.w = mSprite.getRegionWidth(c.mSpriteInstance.getRegionIndex()) * scale * mGlobalMultiplier;
235
                                    //c.mSpriteInstance.param.h = mSprite.getRegionHeight(c.mSpriteInstance.getRegionIndex()) * scale * mGlobalMultiplier;
236
                                    c.mSpriteInstance.transform.pivotX = 0;
237
                                    c.mSpriteInstance.transform.pivotY = 0;
238
 
239
                                    batch.drawSprite(c.mSpriteInstance);
240
                            }
241
 
242
                            posX += c.width * scale + kerning - c.offsetX;
243
                    }
244
 
245
                    batch.end();
246
            }
247
 
248
            public float getTextWidth(string text, float scale)
249
            {
250
                    float maxWidth = 0;
251
                    float width = 0;
252
                    float posX = 0;
253
 
254
                    for (int i = 0; i < text.Length; i++)
255
                    {
256
                            if (text[i] == '\n')
257
                            {
258
                                    posX = 0;
259
                                    continue;
260
                            }
261
 
262
                            int n = getCharacterIndexNoCase(text[i]);
263
                            if (n == -1)
264
                            {
265
                                    continue;
266
                            }
267
 
268
                            CharacterInfo c = mCharacters[n];
269
                            int kerning = 0;
270
                            if (i < (text.Length-1))
271
                            {
272
                                    // apply kerning if any
273
                                    char first = c.getCharacter();
274
                                    char second = text[i+1];
275
 
276
                                    kerning = getKerning(first, second);
277
                            }
278
 
279
                            width = posX + c.width * scale;
280
 
281
                            if (maxWidth < width)
282
                            {
283
                                    maxWidth = width;
284
                            }
285
 
286
                            posX += c.width * scale + kerning - c.offsetX;
287
                    }
288
 
289
                    return maxWidth;
290
            }
291
 
292
            public float getTextHeight(string text, float scale)
293
            {
294
                    float maxHeight = 0;
295
                    float posY = 0;
296
 
297
 
298
 
299
                    for (int i = 0; i < text.Length; i++)
300
                    {
301
                            if (text[i] == '\n')
302
                            {
303
                                    posY += mAscent * mLineBreakFactor * scale;
304
                                    continue;
305
                            }
306
 
307
                            int n = getCharacterIndexNoCase(text[i]);
308
                            if (n == -1)
309
                            {
310
                                    continue;
311
                            }
312
 
313
                            float charHeight = this.mAscent * scale;
314
 
315
                            if ((posY + charHeight) > maxHeight)
316
                            {
317
                                    maxHeight = posY + charHeight;
318
                            }
319
                    }
320
 
321
                    return maxHeight;
322
            }
323
 
324
            public int getCharacterIndex(char c)
325
            {
326
                    for (int i = 0; i < mCharacters.Length; i++)
327
                    {
328
                            if (mCharacters[i].getCharacter() == c)
329
                                    return i;
330
                    }
331
 
332
                    return -1;
333
            }
334
 
335
            public int getCharacterIndexNoCase(char c)
336
            {
337
                    int n = getCharacterIndex(c);
338
                    if (n == -1)
339
                    {
340
                            n = getCharacterIndex(char.ToLower(c));
341
                            if (n == -1)
342
                            {
343
                                    n = getCharacterIndex(char.ToUpper(c));
344
                            }
345
                    }
346
                    return n;
347
            }
348
 
349
            public CharacterInfo getCharacter(char c)
350
            {
351
                    int i = getCharacterIndex(c);
352
 
353
                    if (i != -1)
354
                            return mCharacters[i];
355
 
356
                    return null;
357
            }
358
 
359
            public void setKerning(char first, char second, int value)
360
            {
361
                    //mKernings.put(new KerningPair(first, second), value);
362
            mKernings.Add(new KerningPair(first, second), value);
363
            }
364
 
365
            public int getKerning(char first, char second)
366
            {
1456 chris 367
                    //int value = mKernings[new KerningPair(first, second)];
368
            KerningPair key = new KerningPair(first, second);
369
            if (!mKernings.ContainsKey(key))
370
                return 0;
1454 chris 371
 
1456 chris 372
                    return mKernings[key];
1454 chris 373
            }
374
 
375
            public void setFiltering(bool filter)
376
            {
377
                    /*
378
                    // HACK: should use own texture class
379
                    if (filter)
380
                            getGraphics().renderStates.getTextureStage(0).setTextureFilter(mSprite.getTexture(), TextureFilter.Linear, TextureFilter.Linear);
381
                    else
382
                            getGraphics().renderStates.getTextureStage(0).setTextureFilter(mSprite.getTexture(), TextureFilter.Nearest, TextureFilter.Nearest);*/
383
 
384
                    if (filter)
385
                mSprite.getTexture().setFilter(Texture.Filter.LINEAR, Texture.Filter.LINEAR);
386
                    else
387
                mSprite.getTexture().setFilter(Texture.Filter.NEAREST, Texture.Filter.NEAREST);
388
            }
389
 
390
            public void setLineBreak(float multiple) { mLineBreakFactor = multiple; }
391
            public float getLineBreak() { return mLineBreakFactor; }
392
 
393
    }
394
}