~ubuntu-branches/debian/sid/astromenace/sid

« back to all changes in this revision

Viewing changes to AstroMenaceSource/Core/Font/Font.cpp

  • Committer: Package Import Robot
  • Author(s): Boris Pek
  • Date: 2013-04-09 02:04:25 UTC
  • Revision ID: package-import@ubuntu.com-20130409020425-a7fl9xk4diamw6di
Tags: upstream-1.3.1+repack
Import upstream version 1.3.1+repack

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/************************************************************************************
 
2
 
 
3
        AstroMenace (Hardcore 3D space shooter with spaceship upgrade possibilities)
 
4
        Copyright © 2006-2012 Michael Kurinnoy, Viewizard
 
5
 
 
6
 
 
7
        AstroMenace is free software: you can redistribute it and/or modify
 
8
        it under the terms of the GNU General Public License as published by
 
9
        the Free Software Foundation, either version 3 of the License, or
 
10
        (at your option) any later version.
 
11
 
 
12
        AstroMenace is distributed in the hope that it will be useful,
 
13
        but WITHOUT ANY WARRANTY; without even the implied warranty of
 
14
        MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 
15
        GNU General Public License for more details.
 
16
 
 
17
        You should have received a copy of the GNU General Public License
 
18
        along with AstroMenace. If not, see <http://www.gnu.org/licenses/>.
 
19
 
 
20
 
 
21
        Web Site: http://www.viewizard.com/
 
22
        Project: http://sourceforge.net/projects/openastromenace/
 
23
        E-mail: viewizard@viewizard.com
 
24
 
 
25
*************************************************************************************/
 
26
 
 
27
 
 
28
#include "Font.h"
 
29
 
 
30
 
 
31
 
 
32
void vw_AttachFontChar(eFontChar* FontChar);
 
33
void vw_DetachFontChar(eFontChar* FontChar);
 
34
extern FT_Face InternalFace;
 
35
extern int InternalFontSize;
 
36
 
 
37
 
 
38
 
 
39
//------------------------------------------------------------------------------------
 
40
// загрузка и генерация всех необходимых данных для символа (utf32)
 
41
//------------------------------------------------------------------------------------
 
42
eFontChar* vw_LoadFontChar(unsigned UTF32)
 
43
{
 
44
        // прежде всего, пытаемся загрузить символ, а уже потом создаем структуру
 
45
 
 
46
 
 
47
        // загрузка глифа нужного нам символа
 
48
        if (FT_Load_Char( InternalFace, UTF32, FT_LOAD_RENDER | FT_LOAD_NO_HINTING | FT_LOAD_NO_AUTOHINT))
 
49
        {
 
50
                fprintf(stderr, "Can't load Char: %u\n", UTF32);
 
51
                return 0;
 
52
        }
 
53
 
 
54
 
 
55
        // создаем структуру FontChar
 
56
        eFontChar* NewChar;
 
57
        NewChar = new eFontChar;
 
58
 
 
59
        NewChar->UTF32 = UTF32;
 
60
        NewChar->CharTexture = 0;
 
61
        NewChar->TexturePositionLeft = 0;
 
62
        NewChar->TexturePositionRight = InternalFace->glyph->bitmap.width; // в случае одной текстуры совпадают с шириной
 
63
        NewChar->TexturePositionTop = 0;
 
64
        NewChar->TexturePositionBottom = InternalFace->glyph->bitmap.rows; // в случае одной текстуры совпадают с высотой
 
65
        NewChar->Width = InternalFace->glyph->bitmap.width;
 
66
        NewChar->Height = InternalFace->glyph->bitmap.rows;
 
67
        NewChar->Left = InternalFace->glyph->bitmap_left;
 
68
        NewChar->Top = InternalFace->glyph->bitmap_top;
 
69
        NewChar->Prev = 0;
 
70
        NewChar->Next = 0;
 
71
 
 
72
        BYTE * pixels;
 
73
        pixels = new BYTE[NewChar->Width*NewChar->Height*4];
 
74
 
 
75
        // битмап идет в 1 канале градаций серого, делаем 32бита rgba
 
76
        int k=0;
 
77
        BYTE ColorRGB[3]={255,255,255};
 
78
        for (int j=0; j<NewChar->Height; j++)
 
79
        {
 
80
                for (int i=0; i<NewChar->Width; i++)
 
81
                {
 
82
                        // RGB составляющую заполняем белым
 
83
                        memcpy(pixels + k, ColorRGB, 3);
 
84
                        k+=3;
 
85
                        memcpy(pixels + k, InternalFace->glyph->bitmap.buffer+(NewChar->Height-j-1)*NewChar->Width+i, 1);
 
86
                        k++;
 
87
                }
 
88
        }
 
89
 
 
90
        // называем текстуру номером символа в утф32
 
91
        char texturefilename[MAX_PATH];
 
92
        sprintf(texturefilename, "%i", UTF32);
 
93
 
 
94
        vw_SetTextureProp(RI_MAGFILTER_LINEAR | RI_MINFILTER_LINEAR | RI_MIPFILTER_NONE, RI_CLAMP_TO_EDGE, true, TX_ALPHA_GREYSC, false);
 
95
        NewChar->CharTexture = vw_CreateTextureFromMemory(texturefilename, pixels, NewChar->Width, NewChar->Height, 4, false);
 
96
        // очищаем память
 
97
        delete [] pixels;
 
98
 
 
99
        // подключаем к менеджеру
 
100
        vw_AttachFontChar(NewChar);
 
101
        return NewChar;
 
102
}
 
103
 
 
104
 
 
105
//-----------------------------------------------------------------------------
 
106
// делаем генерацию нужных символов по списку генерируя одну текстуру
 
107
//-----------------------------------------------------------------------------
 
108
void vw_GenerateFontChars(int FontTextureWidth, int FontTextureHeight, const char * CharsList)
 
109
{
 
110
 
 
111
        printf("Font characters generation start.\n");
 
112
 
 
113
        // будем использовать последовательность как имя текстуры
 
114
        const char *TextureName = CharsList;
 
115
        // временный массив
 
116
        BYTE * DIB;
 
117
        DIB = new BYTE[FontTextureWidth*FontTextureHeight*4]; // всегда делаем rgba
 
118
        // устанавливаем 0 везде, чтобы потом не краcить rgb, а только формировать альфу
 
119
        memset(DIB, 0, FontTextureWidth*FontTextureHeight*4);
 
120
 
 
121
        // данные для работы с вклеиванием в текстуру
 
122
        int CurrentDIBX = 0;
 
123
        int CurrentDIBY = 0;
 
124
        int EdgingSpace = 2;
 
125
        int MaxHeightInCurrentLine = 0;
 
126
 
 
127
 
 
128
        // первый проход, формируем одну большую текстуру
 
129
        const char *CharsList2 = CharsList;
 
130
        while (strlen(CharsList) > 0)
 
131
        {
 
132
                unsigned CurrentChar;
 
133
                // преобразуем в утф32 и "сдвигаемся" на следующий символ в строке
 
134
                CharsList = utf8_to_utf32(CharsList, &CurrentChar);
 
135
 
 
136
 
 
137
                // загрузка глифа нужного нам символа
 
138
                if (FT_Load_Char( InternalFace, CurrentChar, FT_LOAD_RENDER | FT_LOAD_NO_HINTING | FT_LOAD_NO_AUTOHINT))
 
139
                {
 
140
                        fprintf(stderr, "Can't load Char: %u\n", CurrentChar);
 
141
                        return;
 
142
                }
 
143
 
 
144
                // создаем структуру FontChar
 
145
                eFontChar* NewChar;
 
146
                NewChar = new eFontChar;
 
147
 
 
148
                NewChar->UTF32 = CurrentChar;
 
149
                NewChar->CharTexture = 0;
 
150
                NewChar->TexturePositionLeft = 0;
 
151
                NewChar->TexturePositionRight = 0;
 
152
                NewChar->TexturePositionTop = 0;
 
153
                NewChar->TexturePositionBottom = 0;
 
154
                NewChar->Width = InternalFace->glyph->bitmap.width;
 
155
                NewChar->Height = InternalFace->glyph->bitmap.rows;
 
156
                NewChar->Left = InternalFace->glyph->bitmap_left;
 
157
                NewChar->Top = InternalFace->glyph->bitmap_top;
 
158
                NewChar->Prev = 0;
 
159
                NewChar->Next = 0;
 
160
 
 
161
                // делаем установку параметров для вклеивания
 
162
 
 
163
                // если в текущую строку символов уже не можем вписывать - смещаемся на новую, ниже
 
164
                if (CurrentDIBX + NewChar->Width > FontTextureWidth)
 
165
                {
 
166
                        CurrentDIBX = 0;
 
167
                        CurrentDIBY += MaxHeightInCurrentLine + EdgingSpace;
 
168
                        MaxHeightInCurrentLine = 0;
 
169
                }
 
170
                // если в текущую строку не влазит уже по высоте - значит это фейл... кричим чтоб дали больше текстуру
 
171
                if (CurrentDIBY + NewChar->Height > FontTextureHeight)
 
172
                {
 
173
                        fprintf(stderr, "!!! Can't generate all font chars in one texture. Too many chars or too small texture size!\n");
 
174
                        delete NewChar;
 
175
                        break;
 
176
                }
 
177
 
 
178
                // "вклеиваем" новый символ в массив
 
179
                BYTE ColorRGB[3]={255,255,255};
 
180
                for (int j=0; j<NewChar->Height; j++)
 
181
                for (int i=0; i<NewChar->Width; i++)
 
182
                {
 
183
                        memcpy(DIB + (FontTextureHeight-CurrentDIBY-j-1)*FontTextureWidth*4 + (CurrentDIBX+i)*4,
 
184
                                        ColorRGB,
 
185
                                        3);
 
186
                        memcpy(DIB + (FontTextureHeight-CurrentDIBY-j-1)*FontTextureWidth*4 + (CurrentDIBX+i)*4 + 3,
 
187
                                        InternalFace->glyph->bitmap.buffer+j*NewChar->Width+i,
 
188
                                        1);
 
189
                }
 
190
 
 
191
                // устанавливаем параметры текстуры для прорисовки нашему символу
 
192
                NewChar->TexturePositionLeft = CurrentDIBX;
 
193
                NewChar->TexturePositionRight = CurrentDIBX + NewChar->Width;
 
194
                NewChar->TexturePositionTop = CurrentDIBY;
 
195
                NewChar->TexturePositionBottom = CurrentDIBY + NewChar->Height;
 
196
 
 
197
                // выбираем наибольшую высоту символов
 
198
                if (MaxHeightInCurrentLine < NewChar->Height) MaxHeightInCurrentLine = NewChar->Height;
 
199
                // смещаем указатель
 
200
                CurrentDIBX += NewChar->Width + EdgingSpace;
 
201
 
 
202
                // подключаем к менеджеру
 
203
                vw_AttachFontChar(NewChar);
 
204
        }
 
205
 
 
206
 
 
207
/////////////////////////////////
 
208
/*
 
209
                // выводим в bmp файл сгенерированный DIB, если нужно проверить
 
210
 
 
211
        SDL_Surface *temp;
 
212
        temp = SDL_CreateRGBSurface(SDL_SWSURFACE, FontTextureWidth, FontTextureHeight, 32,
 
213
#if SDL_BYTEORDER == SDL_LIL_ENDIAN
 
214
        0x000000FF, 0x0000FF00, 0x00FF0000, 0
 
215
#else
 
216
        0x00FF0000, 0x0000FF00, 0x000000FF, 0
 
217
#endif
 
218
        );
 
219
                memcpy(temp->pixels, DIB, FontTextureWidth*FontTextureHeight*4);
 
220
        SDL_SaveBMP(temp, "fontgenerationtest.bmp");
 
221
        SDL_FreeSurface(temp);
 
222
*/
 
223
/////////////////////////////////
 
224
 
 
225
 
 
226
        // создаем текстуру
 
227
        vw_SetTextureProp(RI_MAGFILTER_LINEAR | RI_MINFILTER_LINEAR | RI_MIPFILTER_NONE, RI_CLAMP_TO_EDGE, true, TX_ALPHA_GREYSC, false);
 
228
        eTexture* FontTexture = vw_CreateTextureFromMemory(TextureName, DIB, FontTextureWidth, FontTextureHeight, 4, false);
 
229
        // освобождаем память
 
230
        delete [] DIB;
 
231
        if (FontTexture == 0)
 
232
        {
 
233
                fprintf(stderr, "Can't create font texture.\n");
 
234
                return;
 
235
        }
 
236
 
 
237
 
 
238
        // второй проход, всем FontChars из списка, присваиваем сгенерированную текстуру
 
239
        while (strlen(CharsList2) > 0)
 
240
        {
 
241
                unsigned CurrentChar;
 
242
                // преобразуем в утф32 и "сдвигаемся" на следующий символ в строке
 
243
                CharsList2 = utf8_to_utf32(CharsList2, &CurrentChar);
 
244
                // ставим нашу общую текстуру
 
245
                eFontChar* TMPChar = vw_FindFontCharByUTF32(CurrentChar);
 
246
                if (TMPChar != 0) TMPChar->CharTexture = FontTexture;
 
247
        }
 
248
 
 
249
 
 
250
        printf("Font characters generation end.\n\n");
 
251
}
 
252
 
 
253
 
 
254
 
 
255
 
 
256
 
 
257
 
 
258
//------------------------------------------------------------------------------------
 
259
// прорисовка фонта
 
260
//------------------------------------------------------------------------------------
 
261
void vw_DrawFont(int X, int Y, float FlattenWidth, float MaxWidth, float FontScale, float R, float G, float B, float Transp, const char *Text, ...)
 
262
{
 
263
        if (Text == 0) return;
 
264
 
 
265
        // учитываем аспект рейшен
 
266
        float AW;
 
267
        float AH;
 
268
        bool ASpresent=false;
 
269
        ASpresent = vw_GetAspectWH(&AW, &AH);
 
270
        // получаем данные текущего вьюпорта
 
271
        int W, H;
 
272
        vw_GetViewport(0, 0, &W, &H);
 
273
        float AHw = H*1.0f;
 
274
 
 
275
        float RealTextYPos = AHw - 2*Y + 4 + InternalFontSize*FontScale;
 
276
        if (ASpresent) RealTextYPos = AH - 2*Y + 4 + InternalFontSize*FontScale;
 
277
 
 
278
 
 
279
        // если текст ниже чем ширина нашего окна - не рисуем
 
280
        if (ASpresent){ if (Y > AH) return;}
 
281
        else {if (Y > H) return;}
 
282
        // если текст выше чем ноль - тоже рисовать его смысла нет
 
283
        if (Y+InternalFontSize*FontScale < 0) return;
 
284
 
 
285
 
 
286
// FlattenWidth - выравнивать по ширине
 
287
// если FlattenWidth отрицателен, выравниваем по значению, "сжимая" буквы, если нужно
 
288
// MaxWidth - рисовать до ширины
 
289
 
 
290
 
 
291
        // смотрим значения параметров в строке
 
292
        char    text[1024];
 
293
        va_list         ap;
 
294
        va_start(ap, Text);
 
295
        vsprintf(text, Text, ap);
 
296
        va_end(ap);
 
297
        // в text уже полная строка
 
298
        if (strlen(text) == 0) return;
 
299
 
 
300
        float Xstart = X;
 
301
        // делаем пробел в 2/3 от размера фонта
 
302
        float SpaceWidth = InternalFontSize * 2 / 3;
 
303
        // коэф. изменения букв по ширине
 
304
        float FontWidthScale = 1.0f;
 
305
 
 
306
        if (Transp >= 1.0f) Transp = 1.0f;
 
307
 
 
308
 
 
309
        // если нужно выравнивать, считаем данные пробелов
 
310
        if (FlattenWidth > 0)
 
311
        {
 
312
                float LineWidth = 0;
 
313
                int SpaceCount = 0;
 
314
 
 
315
                const char *CountCheck = text;
 
316
                while (strlen(CountCheck) > 0)
 
317
                {
 
318
                        unsigned UTF32;
 
319
                        // преобразуем в утф32 и "сдвигаемся" на следующий символ в строке
 
320
                        CountCheck = utf8_to_utf32(CountCheck, &UTF32);
 
321
                        // находим наш текущий символ
 
322
                        eFontChar* DrawChar = vw_FindFontCharByUTF32(UTF32);
 
323
                        if (DrawChar == 0) DrawChar = vw_LoadFontChar(UTF32);
 
324
 
 
325
                        // считаем кол-во пробелов
 
326
                        if (UTF32 == 0x020)
 
327
                                SpaceCount++;
 
328
                        else
 
329
                                LineWidth += DrawChar->Width + DrawChar->Left;
 
330
                }
 
331
 
 
332
                if (FlattenWidth > LineWidth)
 
333
                        if (SpaceCount!=0) SpaceWidth = (FlattenWidth - LineWidth)/SpaceCount;
 
334
        }
 
335
        // если нужно сжать, считаем коэф. сжатия букв
 
336
        if (FlattenWidth < 0)
 
337
        {
 
338
                float LineWidth = 0;
 
339
 
 
340
                const char *CountCheck = text;
 
341
                while (strlen(CountCheck) > 0)
 
342
                {
 
343
                        unsigned UTF32;
 
344
                        // преобразуем в утф32 и "сдвигаемся" на следующий символ в строке
 
345
                        CountCheck = utf8_to_utf32(CountCheck, &UTF32);
 
346
                        // находим наш текущий символ
 
347
                        eFontChar* DrawChar = vw_FindFontCharByUTF32(UTF32);
 
348
                        if (DrawChar == 0) DrawChar = vw_LoadFontChar(UTF32);
 
349
 
 
350
                        // считаем длину символов с пробелами
 
351
                        if (UTF32 != 0x020)
 
352
                                LineWidth += DrawChar->Width + DrawChar->Left;
 
353
                        else
 
354
                                LineWidth += SpaceWidth;
 
355
                }
 
356
 
 
357
                if (FlattenWidth*(-1.0f) < LineWidth) FontWidthScale = FlattenWidth/LineWidth*(-1.0f);
 
358
        }
 
359
 
 
360
 
 
361
        float LineWidth = 0;
 
362
 
 
363
        // установка свойств текстуры
 
364
        vw_SetTextureBlend(true, RI_BLEND_SRCALPHA, RI_BLEND_INVSRCALPHA);
 
365
        // ставим цвет
 
366
        vw_SetColor(R, G, B, Transp);
 
367
 
 
368
        // для отрисовки
 
369
        eTexture* CurrentTexture = 0;
 
370
        int k=0;
 
371
        // буфер для последовательности RI_QUADS
 
372
        // войдет RI_2f_XYZ | RI_2f_TEX
 
373
        float *tmp = 0;
 
374
        tmp = new float[(2+2)*4*strlen(text)]; if (tmp == 0) return;
 
375
 
 
376
        // чтобы меньше делать операций умножения, включаем коэф. один в другой сразу для ширины символов
 
377
        FontWidthScale = FontScale*FontWidthScale;
 
378
 
 
379
 
 
380
        // прорисовка текста
 
381
        const char *textdraw = text;
 
382
        // прорисовываем все символы
 
383
        while (strlen(textdraw) > 0)
 
384
        {
 
385
                unsigned UTF32;
 
386
                // преобразуем в утф32 и "сдвигаемся" на следующий символ в строке
 
387
                textdraw = utf8_to_utf32(textdraw, &UTF32);
 
388
                // находим наш текущий символ
 
389
                eFontChar* DrawChar = vw_FindFontCharByUTF32(UTF32);
 
390
                if (DrawChar == 0) DrawChar = vw_LoadFontChar(UTF32);
 
391
                // первый символ - запоминаем его текстуру
 
392
                if (CurrentTexture == 0) CurrentTexture = DrawChar->CharTexture;
 
393
 
 
394
 
 
395
                // проверка на текстуру, если текстура поменялась - отрисовываем все что есть в буфере, если там что-то есть
 
396
                if (CurrentTexture != DrawChar->CharTexture)
 
397
                {
 
398
                        // если что-то было в буфере - выводим
 
399
                        if (k > 0)
 
400
                        {
 
401
                                // Установка текстуры
 
402
                                vw_SetTexture(0, CurrentTexture);
 
403
                                // отрисовываем все что есть в буфере
 
404
                                vw_SendVertices(RI_QUADS, 4*(k/16), RI_2f_XY | RI_1_TEX, tmp, 4*sizeof(float));
 
405
                        }
 
406
 
 
407
 
 
408
                        // запоминаем новую текстуру
 
409
                        CurrentTexture = DrawChar->CharTexture;
 
410
                        // сбрасываем счетчики
 
411
                        k=0;
 
412
                }
 
413
 
 
414
                // если не пробел - рисуем
 
415
                if (UTF32 != 0x020)
 
416
                {
 
417
 
 
418
                        float DrawX = Xstart + DrawChar->Left*FontWidthScale;
 
419
                        float DrawY = Y + 2 + (InternalFontSize - DrawChar->Top)*FontScale; // 2 доп смещение ("привет" от старого фонта)
 
420
 
 
421
                        // Вычисление поправки по У в зависимости от DrawCorner
 
422
                        // - расположения угла начала координат
 
423
                        float tmpPosY = 0;
 
424
                        // изменяем только в случае RI_UL_CORNER
 
425
                        if (ASpresent) tmpPosY = (AH - DrawY - DrawY - DrawChar->Height*FontScale);
 
426
                        else tmpPosY = (AHw - DrawY - DrawY - DrawChar->Height*FontScale);
 
427
 
 
428
                        float ImageHeight = DrawChar->CharTexture->Height*1.0f;
 
429
                        float ImageWidth = DrawChar->CharTexture->Width*1.0f;
 
430
 
 
431
                        float FrameHeight = (DrawChar->TexturePositionBottom*1.0f )/ImageHeight;
 
432
                        float FrameWidth = (DrawChar->TexturePositionRight*1.0f )/ImageWidth;
 
433
 
 
434
                        float Yst = (DrawChar->TexturePositionTop*1.0f)/ImageHeight;
 
435
                        float Xst = (DrawChar->TexturePositionLeft*1.0f)/ImageWidth;
 
436
 
 
437
                        tmp[k++] = DrawX;
 
438
                        tmp[k++] = DrawY +tmpPosY + DrawChar->Height*FontScale;
 
439
                        tmp[k++] = Xst;
 
440
                        tmp[k++] = 1.0f-Yst;
 
441
 
 
442
                        tmp[k++] = DrawX;
 
443
                        tmp[k++] = DrawY +tmpPosY;
 
444
                        tmp[k++] = Xst;
 
445
                        tmp[k++] = 1.0f-FrameHeight;
 
446
 
 
447
                        tmp[k++] = DrawX + DrawChar->Width*FontWidthScale;
 
448
                        tmp[k++] = DrawY +tmpPosY;
 
449
                        tmp[k++] = FrameWidth;
 
450
                        tmp[k++] = 1.0f-FrameHeight;
 
451
 
 
452
                        tmp[k++] = DrawX + DrawChar->Width*FontWidthScale;
 
453
                        tmp[k++] = DrawY +tmpPosY + DrawChar->Height*FontScale;
 
454
                        tmp[k++] = FrameWidth;
 
455
                        tmp[k++] = 1.0f-Yst;
 
456
 
 
457
 
 
458
                        Xstart += (DrawChar->Width + DrawChar->Left)*FontWidthScale;
 
459
                        LineWidth += (DrawChar->Width + DrawChar->Left)*FontWidthScale;
 
460
                }
 
461
                else
 
462
                {
 
463
                        Xstart += SpaceWidth*FontWidthScale;
 
464
                        LineWidth += SpaceWidth*FontWidthScale;
 
465
                }
 
466
 
 
467
                // если нужно прорисовывать с ограничением по длине
 
468
                if (MaxWidth != 0.0f)
 
469
                        if (LineWidth >= MaxWidth) break;
 
470
        }
 
471
 
 
472
 
 
473
        // если что-то было в буфере - выводим
 
474
        if (k > 0)
 
475
        {
 
476
                // Установка текстуры
 
477
                vw_SetTexture(0, CurrentTexture);
 
478
                // отрисовываем все что есть в буфере
 
479
                vw_SendVertices(RI_QUADS, 4*(k/16), RI_2f_XY | RI_1_TEX, tmp, 4*sizeof(float));
 
480
        }
 
481
 
 
482
 
 
483
 
 
484
        if (tmp != 0){delete [] tmp; tmp = 0;}
 
485
        vw_SetColor(1.0f, 1.0f, 1.0f, 1.0f);
 
486
        vw_SetTextureBlend(false, 0, 0);
 
487
        vw_BindTexture(0, 0);
 
488
}
 
489
 
 
490
 
 
491
 
 
492
//------------------------------------------------------------------------------------
 
493
// получаем размер строки
 
494
//------------------------------------------------------------------------------------
 
495
int vw_FontSize(const char *Text, ...)
 
496
{
 
497
        if (Text == 0) return 0;
 
498
 
 
499
        // смотрим значения параметров в строке
 
500
        char    text[1024];
 
501
        va_list         ap;
 
502
 
 
503
        va_start(ap, Text);
 
504
        vsprintf(text, Text, ap);
 
505
        va_end(ap);
 
506
        // в text уже полная строка
 
507
        if (strlen(text) == 0) return 0;
 
508
 
 
509
        const char *textdraw = text;
 
510
        // делаем пробел в 2/3 от размера фонта
 
511
        float SpaceWidth = InternalFontSize * 2 / 3;
 
512
        float LineWidth = 0;
 
513
 
 
514
        while (strlen(textdraw) > 0)
 
515
        {
 
516
                unsigned UTF32;
 
517
                // преобразуем в утф32 и "сдвигаемся" на следующий символ в строке
 
518
                textdraw = utf8_to_utf32(textdraw, &UTF32);
 
519
                // находим наш текущий символ
 
520
                eFontChar* DrawChar = vw_FindFontCharByUTF32(UTF32);
 
521
                if (DrawChar == 0) DrawChar = vw_LoadFontChar(UTF32);
 
522
 
 
523
                // считаем кол-во пробелов
 
524
                if (UTF32 == 0x020)
 
525
                        LineWidth += SpaceWidth;
 
526
                else
 
527
                        LineWidth += DrawChar->Width + DrawChar->Left;
 
528
        }
 
529
 
 
530
 
 
531
        return (int)LineWidth;
 
532
}
 
533
 
 
534
 
 
535
 
 
536
 
 
537
 
 
538
//------------------------------------------------------------------------------------
 
539
// прорисовка фонта в 3д пространстве
 
540
//------------------------------------------------------------------------------------
 
541
void vw_DrawFont3D(float X, float Y, float Z, const char *Text, ...)
 
542
{
 
543
 
 
544
        if (Text == 0) return;
 
545
 
 
546
        // смотрим значения параметров в строке
 
547
        char    text[1024];
 
548
        va_list         ap;
 
549
        va_start(ap, Text);
 
550
        vsprintf(text, Text, ap);
 
551
        va_end(ap);
 
552
        // в text уже полная строка
 
553
        if (strlen(text) == 0) return;
 
554
        // прорисовка текста
 
555
        const char *textdraw = text;
 
556
 
 
557
 
 
558
        float Xstart = 0.0f;
 
559
        // делаем пробел в 2/3 от размера фонта
 
560
        float SpaceWidth = InternalFontSize * 2 / 3;
 
561
 
 
562
        textdraw = text;
 
563
 
 
564
 
 
565
        // для отрисовки
 
566
        eTexture* CurrentTexture = 0;
 
567
        int k=0;
 
568
        // буфер для последовательности RI_QUADS
 
569
        // войдет RI_2f_XY | RI_2f_TEX
 
570
        float *tmp = 0;
 
571
        tmp = new float[(2+2)*4*strlen(textdraw)]; if (tmp == 0) return;
 
572
 
 
573
        // установка свойств текстуры
 
574
        vw_SetTextureBlend(true, RI_BLEND_SRCALPHA, RI_BLEND_INVSRCALPHA);
 
575
        // всегда стаим белый цвет
 
576
        vw_SetColor(1.0f, 1.0f, 1.0f, 1.0f);
 
577
 
 
578
        vw_PushMatrix();
 
579
 
 
580
        vw_Translate(VECTOR3D(X, Y, Z));
 
581
        VECTOR3D CurrentCameraRotation;
 
582
        vw_GetCameraRotation(&CurrentCameraRotation);
 
583
 
 
584
        // поворачиваем к камере
 
585
        vw_Rotate(CurrentCameraRotation.y, 0.0f, 1.0f, 0.0f);
 
586
        vw_Rotate(CurrentCameraRotation.x, 1.0f, 0.0f, 0.0f);
 
587
 
 
588
 
 
589
        // прорисовываем все символы
 
590
        while (strlen(textdraw) > 0)
 
591
        {
 
592
                unsigned UTF32;
 
593
                // преобразуем в утф32 и "сдвигаемся" на следующий символ в строке
 
594
                textdraw = utf8_to_utf32(textdraw, &UTF32);
 
595
                // находим наш текущий символ
 
596
                eFontChar* DrawChar = vw_FindFontCharByUTF32(UTF32);
 
597
                if (DrawChar == 0) DrawChar = vw_LoadFontChar(UTF32);
 
598
                // первый символ - запоминаем его текстуру
 
599
                if (CurrentTexture == 0) CurrentTexture = DrawChar->CharTexture;
 
600
 
 
601
 
 
602
                // проверка на текстуру, если текстура поменялась - отрисовываем все что есть в буфере, если там что-то есть
 
603
                if (CurrentTexture != DrawChar->CharTexture)
 
604
                {
 
605
                        // если что-то было в буфере - выводим
 
606
                        if (k > 0)
 
607
                        {
 
608
                                // Установка текстуры
 
609
                                vw_SetTexture(0, CurrentTexture);
 
610
                                // отрисовываем все что есть в буфере
 
611
                                vw_SendVertices(RI_QUADS, 4*(k/16), RI_2f_XY | RI_1_TEX, tmp, 4*sizeof(float));
 
612
                        }
 
613
 
 
614
 
 
615
                        // запоминаем новую текстуру
 
616
                        CurrentTexture = DrawChar->CharTexture;
 
617
                        // сбрасываем счетчики
 
618
                        k=0;
 
619
                }
 
620
 
 
621
 
 
622
                // если не пробел - рисуем
 
623
                if (UTF32 != 0x020)
 
624
                {
 
625
                        float DrawX = Xstart + DrawChar->Left;
 
626
                        float DrawY = InternalFontSize - DrawChar->Top;
 
627
 
 
628
 
 
629
                        float ImageHeight = DrawChar->CharTexture->Height*1.0f;
 
630
                        float ImageWidth = DrawChar->CharTexture->Width*1.0f;
 
631
 
 
632
                        float FrameHeight = (DrawChar->TexturePositionBottom*1.0f )/ImageHeight;
 
633
                        float FrameWidth = (DrawChar->TexturePositionRight*1.0f )/ImageWidth;
 
634
 
 
635
                        float Yst = (DrawChar->TexturePositionTop*1.0f)/ImageHeight;
 
636
                        float Xst = (DrawChar->TexturePositionLeft*1.0f)/ImageWidth;
 
637
 
 
638
                        tmp[k++] = DrawX/10.0f;
 
639
                        tmp[k++] = (DrawY + DrawChar->Height)/10.0f;
 
640
                        tmp[k++] = Xst;
 
641
                        tmp[k++] = 1.0f-Yst;
 
642
 
 
643
                        tmp[k++] = DrawX/10.0f;
 
644
                        tmp[k++] = DrawY/10.0f;
 
645
                        tmp[k++] = Xst;
 
646
                        tmp[k++] = 1.0f-FrameHeight;
 
647
 
 
648
                        tmp[k++] = (DrawX + DrawChar->Width)/10.0f;
 
649
                        tmp[k++] = DrawY/10.0f;
 
650
                        tmp[k++] = FrameWidth;
 
651
                        tmp[k++] = 1.0f-FrameHeight;
 
652
 
 
653
                        tmp[k++] = (DrawX + DrawChar->Width)/10.0f;
 
654
                        tmp[k++] = (DrawY + DrawChar->Height)/10.0f;
 
655
                        tmp[k++] = FrameWidth;
 
656
                        tmp[k++] = 1.0f-Yst;
 
657
 
 
658
 
 
659
                        Xstart += DrawChar->Width + DrawChar->Left;
 
660
                }
 
661
                else
 
662
                {
 
663
                        Xstart += SpaceWidth;
 
664
                }
 
665
 
 
666
        }
 
667
 
 
668
 
 
669
        // если что-то было в буфере - выводим
 
670
        if (k > 0)
 
671
        {
 
672
                // Установка текстуры
 
673
                vw_SetTexture(0, CurrentTexture);
 
674
                // отрисовываем все что есть в буфере
 
675
                vw_SendVertices(RI_QUADS, 4*(k/16), RI_2f_XY | RI_1_TEX, tmp, 4*sizeof(float));
 
676
        }
 
677
 
 
678
 
 
679
        vw_PopMatrix();
 
680
 
 
681
 
 
682
 
 
683
        if (tmp != 0){delete [] tmp; tmp = 0;};
 
684
        vw_SetTextureBlend(false, 0, 0);
 
685
        vw_BindTexture(0, 0);
 
686
 
 
687
}
 
688