~thumper/nux/next-changes

« back to all changes in this revision

Viewing changes to NuxGraphics/FontTexture.cpp

  • Committer: Neil Jagdish Patel
  • Date: 2010-09-01 21:15:42 UTC
  • Revision ID: neil.patel@canonical.com-20100901211542-cw2ce3ak28unouwb
Add NuxGraphics with licensing

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * Copyright 2010 Inalogic Inc.
 
3
 *
 
4
 * This program is free software: you can redistribute it and/or modify it 
 
5
 * under the terms of the GNU Lesser General Public License version 3, as
 
6
 * published by the  Free Software Foundation.
 
7
 *
 
8
 * This program is distributed in the hope that it will be useful, but 
 
9
 * WITHOUT ANY WARRANTY; without even the implied warranties of 
 
10
 * MERCHANTABILITY, SATISFACTORY QUALITY or FITNESS FOR A PARTICULAR 
 
11
 * PURPOSE.  See the applicable version of the GNU Lesser General Public 
 
12
 * License for more details.
 
13
 * 
 
14
 * You should have received a copy of both the GNU Lesser General Public 
 
15
 * License version 3 along with this program.  If not, see 
 
16
 * <http://www.gnu.org/licenses/>
 
17
 *
 
18
 * Authored by: Jay Taoko <jay.taoko_AT_gmail_DOT_com>
 
19
 *
 
20
 */
 
21
 
 
22
 
 
23
#include "GLResource.h"
 
24
#include "IOpenGLResource.h"
 
25
#include "GLResourceManager.h"
 
26
#include "IOpenGLBaseTexture.h"
 
27
#include "GLDeviceFactory.h"
 
28
#include "GLTextureResourceManager.h"
 
29
 
 
30
#include "OpenGLEngine.h"
 
31
 
 
32
#include "FontTexture.h"
 
33
 
 
34
NAMESPACE_BEGIN_OGL
 
35
 
 
36
extern bool USE_ARB_SHADERS;
 
37
 
 
38
const int CURSOR_OFFSET = 0;
 
39
 
 
40
NString gFontVtxShader = TEXT("#version 110                                       \n\
 
41
                             attribute vec4 iOffset;                            \n\
 
42
                             attribute vec4 iPosition;                          \n\
 
43
                             attribute vec4 iScale;                             \n\
 
44
                             attribute vec4 iTexUV;                             \n\
 
45
                             uniform mat4 ViewProjectionMatrix;                 \n\
 
46
                             varying vec4 oTexCoord0;                           \n\
 
47
                             void main()                                        \n\
 
48
                             {                                                  \n\
 
49
                             oTexCoord0   = iTexUV;                             \n\
 
50
                             vec4 myvertex = iPosition * iScale + iOffset;      \n\
 
51
                             gl_Position  = ViewProjectionMatrix * myvertex;    \n\
 
52
                             }");
 
53
 
 
54
NString gFontFragShader = TEXT("#version 110                                            \n\
 
55
                              #extension GL_ARB_texture_rectangle : enable              \n\
 
56
                              uniform sampler2D FontTexture;                            \n\
 
57
                              uniform vec4 TextColor;                                   \n\
 
58
                              varying vec4 oTexCoord0;                                  \n\
 
59
                              void main()                                               \n\
 
60
                              {                                                         \n\
 
61
                              vec4 diffuse = texture2D(FontTexture, oTexCoord0.st);     \n\
 
62
                              gl_FragColor = vec4(TextColor.x, TextColor.y, TextColor.z, TextColor.w*diffuse.w);  \n\
 
63
                              }");
 
64
 
 
65
NString FontAsmVtx = TEXT(
 
66
                        "!!ARBvp1.0                                 \n\
 
67
                        ATTRIB iScale       = vertex.attrib[9];   \n\
 
68
                        ATTRIB iOffset      = vertex.attrib[10];   \n\
 
69
                        OUTPUT oPos         = result.position;      \n\
 
70
                        OUTPUT oTexCoord0   = result.texcoord[0];   \n\
 
71
                        # Transform the vertex to clip coordinates. \n\
 
72
                        TEMP temp;                                  \n\
 
73
                        MAD   temp, vertex.position, iScale, iOffset;     \n\
 
74
                        DP4   oPos.x, state.matrix.mvp.row[0], temp;      \n\
 
75
                        DP4   oPos.y, state.matrix.mvp.row[1], temp;      \n\
 
76
                        DP4   oPos.z, state.matrix.mvp.row[2], temp;      \n\
 
77
                        DP4   oPos.w, state.matrix.mvp.row[3], temp;      \n\
 
78
                        MOV   oTexCoord0, vertex.attrib[8];             \n\
 
79
                        END");
 
80
 
 
81
NString FontAsmFrg = TEXT(
 
82
                        "!!ARBfp1.0                                       \n\
 
83
                        PARAM color = program.local[0];                   \n\
 
84
                        TEMP temp;                                        \n\
 
85
                        TEMP tex0;                                        \n\
 
86
                        TEX tex0, fragment.texcoord[0], texture[0], 2D;   \n\
 
87
                        MOV temp, color;                                  \n\
 
88
                        MUL temp.w, color, tex0;                          \n\
 
89
                        MOV result.color, temp;                           \n\
 
90
                        END");
 
91
 
 
92
FontTexture::FontTexture(const TCHAR* FontFile)
 
93
{
 
94
    m_FontSearchPath.AddSearchPath(GetThreadGLWindow()->GetFontSearchPath());
 
95
    NString FontPath = m_FontSearchPath.GetFile(FontFile);
 
96
    
 
97
    std::filebuf fb;
 
98
    fb.open (FontPath.GetTCharPtr(), std::ios::in);
 
99
    std::istream is(&fb);
 
100
 
 
101
    BMFontParseFNT(is);
 
102
}
 
103
 
 
104
FontTexture::FontTexture(int width, int height, BYTE *Texture)
 
105
{
 
106
 
 
107
}
 
108
 
 
109
FontTexture::~FontTexture()
 
110
{
 
111
}
 
112
 
 
113
int FontTexture::GetCharWidth(const TCHAR& c) const
 
114
{
 
115
    int ascii = c & 0xff;
 
116
    nuxAssert(ascii < m_Charset.NumChar);
 
117
    if(ascii >= m_Charset.NumChar)
 
118
        return 0;
 
119
 
 
120
    // XAdvance = abcA + abcB + abcC
 
121
    return m_Charset.Chars[ascii].XAdvance;
 
122
}
 
123
 
 
124
int FontTexture::GetStringWidth(const NString& str) const
 
125
{
 
126
//     unsigned int total = 0;
 
127
//     for (unsigned int i = 0; i != (unsigned int)str.size(); ++i)
 
128
//     {
 
129
//         total += GetCharWidth(str[i]);
 
130
//     }
 
131
//     return total;
 
132
    return GetCharStringWidth(str.GetTCharPtr());
 
133
}
 
134
 
 
135
int FontTexture::GetCharStringWidth(const TCHAR* str) const
 
136
{
 
137
    if((str == TEXT("")) || (str == 0))
 
138
        return 0;
 
139
    unsigned int total = 0;
 
140
    for(int i = 0; ; ++i)
 
141
    {
 
142
        if(str[i] == 0)
 
143
            return total;
 
144
        total += GetCharWidth(str[i]);
 
145
    }
 
146
    return total;
 
147
}
 
148
 
 
149
int FontTexture::GetStringWidth(const NString& str, int num_char_to_compute) const
 
150
{
 
151
    return GetCharStringWidth(str.GetTCharPtr(), num_char_to_compute);
 
152
}
 
153
 
 
154
int FontTexture::GetCharStringWidth(const TCHAR* str, int num_char_to_compute) const
 
155
{
 
156
    if((str == TEXT("")) || (str == 0))
 
157
        return 0;
 
158
 
 
159
    int num_chars = num_char_to_compute;
 
160
    if(num_chars <= 0)
 
161
    {
 
162
        return 0;
 
163
    }
 
164
    int total = 0;
 
165
    for(int i = 0; i < num_chars; ++i)
 
166
    {
 
167
        if(str[i] == 0)
 
168
            return total;
 
169
        total += GetCharWidth(str[i]);
 
170
    }
 
171
    return total;
 
172
}
 
173
 
 
174
int FontTexture::GetFontHeight()
 
175
{
 
176
    return m_Charset.FontHeight;
 
177
}
 
178
 
 
179
bool FontTexture::BMFontParseFNT( std::istream& Stream )
 
180
{
 
181
    std::string Line;
 
182
    int KerningIndex = 0;
 
183
    while( !Stream.eof() )
 
184
    {
 
185
        std::getline( Stream, Line );
 
186
 
 
187
        unsigned int line_size = (unsigned int)Line.length();
 
188
        TCHAR* tc = new TCHAR[line_size+1];
 
189
        const TCHAR* Stream = tc;
 
190
        Memcpy(tc, Line.c_str(), line_size+1);
 
191
        tc[line_size] = 0;
 
192
        if( ParseCommand(&Stream, TEXT("common")) /*Read == "common"*/)
 
193
        {
 
194
            ParseUBOOL(tc, TEXT("Bold="),        m_Charset.bold);
 
195
            ParseUBOOL(tc, TEXT("Italic="),      m_Charset.italic);
 
196
            ParseWORD(tc, TEXT("base="),        m_Charset.Base);
 
197
            ParseWORD(tc, TEXT("scaleW="),      m_Charset.Width);
 
198
            ParseWORD(tc, TEXT("scaleH="),      m_Charset.Height);
 
199
            ParseWORD(tc, TEXT("NumPages="),    m_Charset.Pages);
 
200
            ParseWORD(tc, TEXT("FontHeight="),  m_Charset.FontHeight);
 
201
            ParseWORD(tc, TEXT("Ascent="),      m_Charset.Ascent);
 
202
            ParseWORD(tc, TEXT("Descent="),     m_Charset.Descent);
 
203
            ParseINT(tc, TEXT("AvgCharWidth="),     m_Charset.AvgCharWidth);
 
204
            ParseINT(tc, TEXT("MaxCharWidth="),     m_Charset.MaxCharWidth);
 
205
            ParseINT(tc, TEXT("InternalLeading="),     m_Charset.InternalLeading);
 
206
            ParseINT(tc, TEXT("ExternalLeading="),     m_Charset.ExternalLeading);
 
207
            // Constant for now... Should be read from the font file
 
208
            m_Charset.NumChar = 256;
 
209
        }
 
210
        else if(ParseCommand(&Stream, TEXT("char")))
 
211
        {
 
212
 
 
213
            unsigned short CharID = 0;
 
214
 
 
215
            ParseWORD(tc, TEXT("id="), CharID);
 
216
            ParseWORD(tc, TEXT("x="), m_Charset.Chars[CharID].x);
 
217
            ParseWORD(tc, TEXT("y="), m_Charset.Chars[CharID].y);
 
218
            ParseWORD(tc, TEXT("width="), m_Charset.Chars[CharID].Width);
 
219
            ParseWORD(tc, TEXT("height="), m_Charset.Chars[CharID].Height);
 
220
            ParseSWORD(tc, TEXT("xoffset="), m_Charset.Chars[CharID].XOffset);
 
221
            ParseSWORD(tc, TEXT("yoffset="), m_Charset.Chars[CharID].YOffset);
 
222
            ParseSWORD(tc, TEXT("xadvance="), m_Charset.Chars[CharID].XAdvance);
 
223
            ParseSWORD(tc, TEXT("abcA="), m_Charset.Chars[CharID].abcA);
 
224
            ParseSWORD(tc, TEXT("abcB="), m_Charset.Chars[CharID].abcB);
 
225
            ParseSWORD(tc, TEXT("abcC="), m_Charset.Chars[CharID].abcC);
 
226
            ParseWORD(tc, TEXT("page="), m_Charset.Chars[CharID].page);
 
227
        }
 
228
        else if( ParseCommand(&Stream, TEXT("Kerning")) )
 
229
        {
 
230
            ParseWORD(tc, "count=", m_Charset.NumKerningPairs);
 
231
            if(m_Charset.NumKerningPairs > 0)
 
232
                m_Charset.Kerning = new KerningPair[m_Charset.NumKerningPairs];
 
233
        }
 
234
        else if( ParseCommand(&Stream, TEXT("KerningPair")) )
 
235
        {
 
236
            if(KerningIndex < m_Charset.NumKerningPairs)
 
237
            {
 
238
                ParseWORD(tc, "first=", m_Charset.Kerning[KerningIndex].first);
 
239
                ParseWORD(tc, "second=", m_Charset.Kerning[KerningIndex].second);
 
240
                ParseSWORD(tc, "amount=", m_Charset.Kerning[KerningIndex].amount);
 
241
                KerningIndex++;
 
242
            }
 
243
        }
 
244
        else if( ParseCommand(&Stream, TEXT("Texture")) )
 
245
        {
 
246
 
 
247
            unsigned short CharID = 0;
 
248
            TCHAR texture[256];
 
249
            if(ParseLine(&Stream, texture, 256))
 
250
            {
 
251
//                 FilePath FontPath;
 
252
//                 FontPath.AddSearchPath(""); // for case where fully qualified path is given
 
253
//                 FontPath.AddSearchPath(".");
 
254
//                 FontPath.AddSearchPath("../Fonts");
 
255
 
 
256
#ifdef UNICODE
 
257
                NString font_texture_file = m_FontSearchPath.GetFile(texture);
 
258
#else
 
259
                NString font_texture_file = m_FontSearchPath.GetFile(texture);
 
260
#endif
 
261
 
 
262
                NTexture2D* Texture = new NTexture2D;
 
263
                NBitmapData* BitmapData = LoadImageFile(font_texture_file.GetTCharPtr());
 
264
                if(BitmapData)
 
265
                    Texture->Update(BitmapData);
 
266
                INL_SAFE_DELETE(BitmapData);
 
267
                TextureArray.push_back(Texture);
 
268
            }
 
269
        }
 
270
        delete [] tc;
 
271
    }
 
272
 
 
273
    return true;
 
274
}
 
275
 
 
276
//    CursorPosToX (similar to ScriptStringCPtoX from Microsoft UniScript)
 
277
//        The CursorPosToX function returns the x-coordinate for the leading or trailing edge of a character position.
 
278
 
 
279
//        Parameters
 
280
//        icp
 
281
//          [in] Character position in the string.
 
282
//        fTrailing
 
283
//          [in] Indicates the edge of the icp that corresponds to the x coordinate. If TRUE, it indicates the trailing edge. If FALSE, it indicates the leading edge. 
 
284
//        pX
 
285
//          [out] Pointer to a variable that receives the corresponding x coordinate for the icp. 
 
286
//
 
287
//        Return Values
 
288
//          If the function succeeds, it returns S_OK.
 
289
//          If the function fails, it returns an HRESULT.
 
290
//          The return value can be tested with the SUCCEEDED and FAILED macros.
 
291
bool FontTexture::CursorPosToX(const NString& Str,
 
292
                               int icp, 
 
293
                               bool fTrailing, 
 
294
                               int *pX)
 
295
{
 
296
    if(icp > (int)Str.Size())
 
297
        return false;
 
298
 
 
299
    if(fTrailing)
 
300
        // get pX at the right of the character at position icp
 
301
        *pX = GetStringWidth(Str, icp+1); 
 
302
    else
 
303
        // get pX at the left of the character at position icp
 
304
        *pX = GetStringWidth(Str, icp);
 
305
 
 
306
    return true;
 
307
}
 
308
 
 
309
//    XToCursorPosition (similar to ScriptStringXtoCP from Microsoft UniScript)
 
310
//        The XToCursorPosition function converts an x-coordinate to a character position.
 
311
//
 
312
//    Parameters
 
313
//        iX
 
314
//          [in] Specifies the x coordinate.
 
315
//        FirstVisibleCharIndex,
 
316
//          [in] Index of the first visible character in the text box
 
317
//        piCh
 
318
//          [out] Pointer to a variable that receives the character position corresponding to iX.
 
319
//        piTrailing
 
320
//          [out] Pointer to a variable that receives an indicator whether the position is the leading or trailing edge of the character. 
 
321
//
 
322
//        Return Values
 
323
//          If the function is successful, it returns S_OK.
 
324
//          If the function fails, it returns an HRESULT.
 
325
//          The return value can be tested with the SUCCEEDED and FAILED macros.
 
326
bool FontTexture::XToCursorPosition(const NString& Str,
 
327
                                    int iX,
 
328
                                    unsigned int FirstVisibleCharIndex,
 
329
                                    int *piCh,
 
330
                                    int *piTrailing)
 
331
{
 
332
    unsigned int num_chars;
 
333
    num_chars = (unsigned int)Str.Size();
 
334
    nuxAssert(FirstVisibleCharIndex < num_chars);
 
335
    
 
336
    *piCh = 0;
 
337
    *piTrailing = 0;
 
338
 
 
339
    unsigned int total = 0;
 
340
    if(iX == 0)
 
341
    {
 
342
        *piCh = 0;
 
343
        *piTrailing = 0;
 
344
        return true;
 
345
    }
 
346
 
 
347
    
 
348
    unsigned int X = iX;
 
349
    for (unsigned int i = 0; i < FirstVisibleCharIndex; ++i)
 
350
    {
 
351
        X += GetCharWidth(Str[i]);
 
352
    }
 
353
 
 
354
    for (unsigned int i = 0; i < num_chars; ++i)
 
355
    {
 
356
        unsigned int s = GetCharWidth(Str[i]);
 
357
        if(i >= FirstVisibleCharIndex)
 
358
        {
 
359
            if(total == X)
 
360
            {
 
361
                *piCh = i;
 
362
                *piTrailing = 0;
 
363
                return true;
 
364
            }
 
365
            else if(total + s/2 > X)
 
366
            {
 
367
                *piCh = i;
 
368
                *piTrailing = 0;
 
369
                return true;
 
370
            }
 
371
 
 
372
            else if(total + GetCharWidth(Str[i+1])/2 > X)
 
373
            {
 
374
                *piCh = i+1;
 
375
                *piTrailing = 0;
 
376
                return true;
 
377
            }
 
378
        }
 
379
        total += s;
 
380
    }
 
381
    return false;
 
382
}
 
383
 
 
384
const Charset& FontTexture::GetFontInfo() const
 
385
{
 
386
    return m_Charset;
 
387
}
 
388
 
 
389
/////////////////////////////////////////////////////////////////////////////////////////////////
 
390
 
 
391
FontRenderer::FontRenderer(GraphicsContext& OpenGLEngine)
 
392
:   m_OpenGLEngine(OpenGLEngine)
 
393
{
 
394
    //m_QuadBuffer = new TemplateQuadBuffer(GetThreadGLDeviceFactory(), SHADER_TYPE_GLSL);
 
395
    if(!USE_ARB_SHADERS)
 
396
    {
 
397
        m_PixelShaderProg   = GetThreadGLDeviceFactory()->CreatePixelShader();
 
398
        m_VertexShaderProg  = GetThreadGLDeviceFactory()->CreateVertexShader();
 
399
        m_ShaderProg        = GetThreadGLDeviceFactory()->CreateShaderProgram();
 
400
 
 
401
        m_VertexShaderProg->SetShaderCode(TCHAR_TO_ANSI(*gFontVtxShader));
 
402
        m_PixelShaderProg->SetShaderCode(TCHAR_TO_ANSI(*gFontFragShader));
 
403
 
 
404
        m_ShaderProg->ClearShaderObjects();
 
405
        m_ShaderProg->AddShaderObject(m_VertexShaderProg);
 
406
        m_ShaderProg->AddShaderObject(m_PixelShaderProg);
 
407
        m_ShaderProg->Link();
 
408
    }
 
409
    else
 
410
    {
 
411
        m_AsmVertexShaderProg  = GetThreadGLDeviceFactory()->CreateAsmVertexShader();
 
412
        m_AsmPixelShaderProg   = GetThreadGLDeviceFactory()->CreateAsmPixelShader();
 
413
        m_AsmShaderProg        = GetThreadGLDeviceFactory()->CreateAsmShaderProgram();
 
414
 
 
415
        m_AsmShaderProg->LoadVertexShader(TCHAR_TO_ANSI(*FontAsmVtx));
 
416
        m_AsmShaderProg->LoadPixelShader(TCHAR_TO_ANSI(*FontAsmFrg));
 
417
        m_AsmShaderProg->Link();
 
418
    }
 
419
}
 
420
 
 
421
FontRenderer::~FontRenderer()
 
422
{
 
423
    //delete m_QuadBuffer;
 
424
}
 
425
 
 
426
int FontRenderer::DrawColorString(const NFontPtr& Font, int x, int y, const NString& str, const Color& color, bool WriteAlphaChannel, int SkipFirstNCharacters, int NumCharacter)
 
427
{
 
428
    return RenderText(Font, x, y, str, color, WriteAlphaChannel, SkipFirstNCharacters, NumCharacter);
 
429
}
 
430
 
 
431
void FontRenderer::PositionString(const NFontPtr& Font, const NString& str, const PageBBox& pageBBox, StringBBox& strBBox, TextAlignment alignment, int NumCharacter)
 
432
{
 
433
    int x, y;
 
434
    int xmin, ymin, xmax, ymax;
 
435
    xmin = pageBBox.xmin + pageBBox.x_margin;
 
436
    xmax = pageBBox.xmax - pageBBox.x_margin;
 
437
    ymin = pageBBox.ymin + pageBBox.y_margin;
 
438
    ymax = pageBBox.ymax - pageBBox.y_margin;
 
439
 
 
440
    int NumChar = 0;
 
441
    if(NumCharacter == 0)
 
442
        NumChar = str.Size();
 
443
    else
 
444
        NumChar = Min((int)str.Size(), NumCharacter);
 
445
 
 
446
    strBBox.width = Font->GetStringWidth(str, NumChar);
 
447
    strBBox.height = Font->GetLineHeight();
 
448
 
 
449
    switch(alignment)
 
450
    {
 
451
    case eAlignTextCenter:
 
452
        if(strBBox.width > xmax - xmin)
 
453
            x = xmin; // the text is larger than the box: default to eAlignTextLeft for x.
 
454
        else
 
455
            x = xmin + ((float)(xmax - xmin) - (float)(strBBox.width))/2.0f;
 
456
        y = ymin + ((float)(ymax - ymin) - (float)(strBBox.height))/2.0f;
 
457
        break;
 
458
    
 
459
    case eAlignTextRight:
 
460
        x = xmin + ((float)(xmax - xmin) - (float)(strBBox.width));
 
461
        y = ymin + ((float)(ymax - ymin) - (float)(strBBox.height))/2.0f;
 
462
        break;
 
463
 
 
464
    case eAlignTextLeft:
 
465
    default:
 
466
        x = xmin;
 
467
        y = ymin + ((float)(ymax - ymin) - (float)(strBBox.height))/2.0f;
 
468
        break;
 
469
    }
 
470
 
 
471
    strBBox.x = x;
 
472
    strBBox.y = y;
 
473
}
 
474
 
 
475
int FontRenderer::RenderColorText(const NFontPtr& Font, int x, int y, const NString& Str, const Color& color,
 
476
                                  bool WriteAlphaChannel, int NumCharacter)
 
477
{
 
478
    int off = DrawColorString(Font, x, y, Str, color, WriteAlphaChannel, 0, NumCharacter);
 
479
    return off;
 
480
}
 
481
 
 
482
int FontRenderer::RenderColorTextLineStatic(const NFontPtr& Font, const PageBBox& pageSize, const NString& Str, const Color& color,
 
483
                                            bool WriteAlphaChannel, TextAlignment alignment)
 
484
{
 
485
    StringBBox stringBBox;
 
486
 
 
487
    m_OpenGLEngine.PushClippingRectangle(Rect(pageSize.xmin, pageSize.ymin, pageSize.xmax - pageSize.xmin, pageSize.ymax - pageSize.ymin));
 
488
    PositionString(Font, Str, pageSize, stringBBox, alignment);
 
489
    int off = DrawColorString(Font, stringBBox.x, stringBBox.y, Str, color, WriteAlphaChannel, 0, Str.Size());
 
490
 
 
491
    m_OpenGLEngine.PopClippingRectangle();
 
492
    return off;
 
493
}
 
494
 
 
495
int FontRenderer::RenderColorTextLineEdit(const NFontPtr& Font, const PageBBox& pageSize, const NString& Str,
 
496
                                          const Color& TextColor,
 
497
                                          bool WriteAlphaChannel,
 
498
                                          const Color& SelectedTextColor,
 
499
                                          const Color& SelectedTextBackgroundColor,
 
500
                                          const Color& TextBlinkColor,
 
501
                                          const Color& CursorColor,
 
502
                                          bool ShowCursor, unsigned int CursorPosition, int offset, int selection_start, int selection_end)
 
503
{
 
504
    StringBBox stringBBox;
 
505
    Color selection_color(0xFF888888);
 
506
 
 
507
    NString substring = Str.GetSubString(selection_start, selection_end - selection_start);
 
508
    unsigned int substring_width = Font->GetStringWidth(substring);
 
509
    int substring_pos = Font->GetStringWidth(Str, selection_start);
 
510
 
 
511
    m_OpenGLEngine.PushClippingRectangle(Rect(pageSize.xmin, pageSize.ymin, pageSize.xmax - pageSize.xmin, pageSize.ymax - pageSize.ymin));
 
512
    if(substring_width > 0)
 
513
        m_OpenGLEngine.QRP_GLSL_Color(pageSize.xmin + offset + substring_pos, pageSize.ymin, substring_width, pageSize.ymax - pageSize.ymin, SelectedTextBackgroundColor);
 
514
    m_OpenGLEngine.PopClippingRectangle();
 
515
 
 
516
    m_OpenGLEngine.PushClippingRectangle(Rect(pageSize.xmin, pageSize.ymin, pageSize.xmax - pageSize.xmin, pageSize.ymax - pageSize.ymin));
 
517
 
 
518
    PositionString(Font, Str, pageSize, stringBBox, eAlignTextLeft);
 
519
    //ComputeGlyphString(stringBBox.x + offset, stringBBox.y, Str.c_str());
 
520
 
 
521
    // Part before selected text
 
522
    int off = DrawColorString(Font, stringBBox.x + offset, stringBBox.y, Str, TextColor, WriteAlphaChannel, 0, selection_start);
 
523
    // Selection part
 
524
    off = DrawColorString(Font, stringBBox.x + offset, stringBBox.y, Str, SelectedTextColor, WriteAlphaChannel, selection_start, selection_end - selection_start);
 
525
    // Part after selected text
 
526
    off = DrawColorString(Font, stringBBox.x + offset, stringBBox.y, Str, TextColor, WriteAlphaChannel, selection_end, Str.Size() - selection_end);
 
527
 
 
528
    m_OpenGLEngine.PopClippingRectangle();
 
529
 
 
530
    // Render Cursor
 
531
    NString temp = Str.GetSubString(0, CursorPosition);
 
532
    int w = Font->GetStringWidth(temp.GetTCharPtr());
 
533
    int h = Font->GetLineHeight();
 
534
 
 
535
    glDisable(GL_TEXTURE_2D);
 
536
 
 
537
    if(ShowCursor)
 
538
    {
 
539
        glColor4f(CursorColor.R(), CursorColor.G(), CursorColor.B(), CursorColor.A());
 
540
    //     glBegin(GL_LINES);
 
541
    //     {
 
542
    //         // make sure the isn't drawn outside of the area.
 
543
    //         int x = pageSize.xmin + w + offset + CURSOR_OFFSET;
 
544
    //         x = (x >= pageSize.xmax) ? pageSize.xmax - 1 : x;
 
545
    //         glVertex3i(x, pageSize.ymin, 1);
 
546
    //         glVertex3i(x, pageSize.ymax, 1);
 
547
    //     }
 
548
 
 
549
        int x = pageSize.xmin + w + offset + CURSOR_OFFSET;
 
550
        x = (x >= pageSize.xmax) ? pageSize.xmax - 1 : x;
 
551
        m_OpenGLEngine.PushClippingRectangle(Rect(x, pageSize.ymin, 2, pageSize.ymax - pageSize.ymin));
 
552
        glBegin(GL_QUADS);
 
553
        {
 
554
            // make sure the isn't drawn outside of the area.
 
555
            glVertex3i(x, pageSize.ymin, 1);
 
556
            glVertex3i(x, pageSize.ymax, 1);
 
557
            glVertex3i(x+2, pageSize.ymax, 1);
 
558
            glVertex3i(x+2, pageSize.ymin, 1);
 
559
        }
 
560
        glEnd();
 
561
        DrawColorString(Font, stringBBox.x + offset, stringBBox.y, Str, TextBlinkColor, WriteAlphaChannel, CursorPosition, 1);
 
562
        m_OpenGLEngine.PopClippingRectangle();
 
563
    }
 
564
    return off;
 
565
}
 
566
 
 
567
int FontRenderer::RenderText(const NFontPtr& Font, int x, int y, const NString& str, const Color& color, bool WriteAlphaChannel, int StartCharacter, int NumCharacter)
 
568
{
 
569
    // !WARNING This call works if all the glyph of the font are in a single texture.
 
570
 
 
571
    int StrLength = str.Size();
 
572
    if(StrLength <= 0)
 
573
        return 0;
 
574
 
 
575
    nuxAssertMsg(NumCharacter >= 0, TEXT("[FontRenderer::RenderText] Incorrect value for NumCharacter."));
 
576
    nuxAssertMsg(StartCharacter >= 0, TEXT("[FontRenderer::RenderText] Incorrect value for StartCharacter."));
 
577
    nuxAssertMsg(StartCharacter <= StrLength, TEXT("[FontRenderer::RenderText] Incorrect value for StartCharacter."));
 
578
 
 
579
    //     if(NumCharacter == 0)
 
580
    //         NumCharacter = str.Size();
 
581
 
 
582
    int NumCharToDraw = Min<int>(StrLength - StartCharacter, NumCharacter);
 
583
    //nuxAssertMsg(NumCharToDraw > 0, TEXT("[FontRenderer::RenderText] Incorrect value for NumCharToDraw."));
 
584
    if(NumCharToDraw <= 0)
 
585
        return 0;
 
586
 
 
587
    unsigned int CurrentPage = 0;
 
588
    CHECKGL( glDisable(GL_CULL_FACE) );
 
589
    int CurX = x;// + CURSOR_OFFSET;
 
590
    int CurY = y;
 
591
    GetThreadGraphicsContext()->GetRenderStates().SetBlend(TRUE, GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
 
592
    GetThreadGraphicsContext()->GetRenderStates().SetColorMask(TRUE, TRUE, TRUE, WriteAlphaChannel); // Do not write the alpha of characters
 
593
 
 
594
    Vector4* Position = new Vector4[StrLength*4];
 
595
    Vector4* UV = new Vector4[StrLength*4];
 
596
    Vector4* Offset = new Vector4[StrLength*4];
 
597
    Vector4* Scale = new Vector4[StrLength*4];
 
598
    
 
599
    TRefGL<NGLTexture2D> glTexture = m_OpenGLEngine.ResourceCache.GetCachedResource(Font->TextureArray[0]);
 
600
    
 
601
    float tex_width = (float)glTexture->m_Texture->GetWidth();
 
602
    float tex_height = (float)glTexture->m_Texture->GetHeight();
 
603
 
 
604
    int I = 0;
 
605
    for(int i = 0; i < StrLength; ++i)
 
606
    {
 
607
        unsigned char c = static_cast<unsigned char>(str[i]);
 
608
        unsigned int CharX = Font->m_Charset.Chars[c /*Str[i]*/].x;
 
609
        unsigned int CharY = Font->m_Charset.Chars[c /*Str[i]*/].y;
 
610
        unsigned int Width = Font->m_Charset.Chars[c /*Str[i]*/].Width;
 
611
        unsigned int Height = Font->m_Charset.Chars[c /*Str[i]*/].Height;
 
612
        int OffsetX = Font->m_Charset.Chars[c /*Str[i]*/].XOffset;
 
613
        int OffsetY = Font->m_Charset.Chars[c /*Str[i]*/].YOffset;
 
614
        int abcA = Font->m_Charset.Chars[c /*Str[i]*/].abcA;
 
615
        int abcB = Font->m_Charset.Chars[c /*Str[i]*/].abcB;
 
616
        int abcC = Font->m_Charset.Chars[c /*Str[i]*/].abcC;
 
617
        int page = Font->m_Charset.Chars[c /*Str[i]*/].page;
 
618
 
 
619
        if((i >= StartCharacter) && (i < StartCharacter + NumCharToDraw))
 
620
        {
 
621
            int II = i - StartCharacter;
 
622
            Position[II*4 + 0].x = 0;      // x
 
623
            Position[II*4 + 0].y = 0;      // y
 
624
            Position[II*4 + 0].z = 0;      // z
 
625
            Position[II*4 + 0].w = 1.0f;   // w
 
626
 
 
627
            Position[II*4 + 1].x = 1.0f;   // x
 
628
            Position[II*4 + 1].y = 0;      // y
 
629
            Position[II*4 + 1].z = 0;      // z
 
630
            Position[II*4 + 1].w = 1;      // w
 
631
 
 
632
            Position[II*4 + 2].x = 1.0f;   // x
 
633
            Position[II*4 + 2].y = 1.0f;   // y
 
634
            Position[II*4 + 2].z = 0;      // z
 
635
            Position[II*4 + 2].w = 1;      // w
 
636
 
 
637
            Position[II*4 + 3].x = 0;      // x
 
638
            Position[II*4 + 3].y = 1.0f;   // y
 
639
            Position[II*4 + 3].z = 0;      // z
 
640
            Position[II*4 + 3].w = 1;      // w
 
641
 
 
642
            for(int j = 0; j < 4; j++)
 
643
            {
 
644
                Offset[II*4 + j].x = CurX + abcA;
 
645
                Offset[II*4 + j].y = CurY;
 
646
                Offset[II*4 + j].z = 0.0f;
 
647
                Offset[II*4 + j].w = 0.0f;
 
648
 
 
649
                Scale[II*4 + j].x = Width;
 
650
                Scale[II*4 + j].y = Height;
 
651
                Scale[II*4 + j].z = 1.0f;
 
652
                Scale[II*4 + j].w = 1.0f;
 
653
            }
 
654
            //upper left
 
655
            UV[II*4 + 0].x = CharX/tex_width;
 
656
            UV[II*4 + 0].y = CharY/tex_height;
 
657
            UV[II*4 + 0].z = 0.0f;
 
658
            UV[II*4 + 0].w = 0.0f;
 
659
 
 
660
            //upper right
 
661
            UV[II*4 + 1].x = (CharX+Width)/tex_width;
 
662
            UV[II*4 + 1].y = CharY/tex_height;
 
663
            UV[II*4 + 1].z = 0.0f;
 
664
            UV[II*4 + 1].w = 0.0f;
 
665
 
 
666
            //lower right
 
667
            UV[II*4 + 2].x = (CharX+Width)/tex_width;
 
668
            UV[II*4 + 2].y = (CharY+Height)/tex_height;
 
669
            UV[II*4 + 2].z = 0.0f;
 
670
            UV[II*4 + 2].w = 0.0f;
 
671
 
 
672
            //lower left
 
673
            UV[II*4 + 3].x = CharX/tex_width;
 
674
            UV[II*4 + 3].y = (CharY+Height)/tex_height;
 
675
            UV[II*4 + 3].z = 0.0f;
 
676
            UV[II*4 + 3].w = 0.0f;
 
677
        }
 
678
        CurX += abcA + abcB + abcC;
 
679
    }
 
680
 
 
681
    CHECKGL(glBindBufferARB(GL_ARRAY_BUFFER_ARB, 0));
 
682
    CHECKGL(glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, 0));
 
683
 
 
684
    int iPosition = 0;
 
685
    int iTexUV = 0;
 
686
    int iScale = 0;
 
687
    int iOffset = 0;
 
688
 
 
689
    if(!USE_ARB_SHADERS)
 
690
    {
 
691
        m_ShaderProg->Begin();
 
692
        int ViewProjectionMatrix = m_ShaderProg->GetUniformLocationARB("ViewProjectionMatrix");
 
693
        Matrix4 mat = GetThreadGraphicsContext()->GetModelViewProjectionMatrix();
 
694
 
 
695
        m_ShaderProg->SetUniformLocMatrix4fv(ViewProjectionMatrix, 1, false, (float*)&mat);
 
696
 
 
697
        iPosition       = m_ShaderProg->GetAttributeLocation("iPosition");
 
698
        iTexUV          = m_ShaderProg->GetAttributeLocation("iTexUV");
 
699
        iScale          = m_ShaderProg->GetAttributeLocation("iScale");
 
700
        iOffset         = m_ShaderProg->GetAttributeLocation("iOffset");
 
701
 
 
702
        int FontTexture     = m_ShaderProg->GetUniformLocationARB("FontTexture");
 
703
        int TextColor       = m_ShaderProg->GetUniformLocationARB("TextColor");
 
704
 
 
705
        GetThreadGraphicsContext()->SetTexture(GL_TEXTURE0, glTexture->m_Texture);
 
706
 
 
707
        if(FontTexture != -1)
 
708
        {
 
709
            CHECKGL( glUniform1iARB(FontTexture, 0) );
 
710
        }
 
711
 
 
712
        if(TextColor != -1)
 
713
        {
 
714
            CHECKGL( glUniform4fARB(TextColor, color.R(), color.G(), color.B(), color.A()) );
 
715
        }
 
716
    }
 
717
    else
 
718
    {
 
719
        m_AsmShaderProg->Begin();
 
720
        CHECKGL( glMatrixMode(GL_MODELVIEW) );
 
721
        CHECKGL( glLoadIdentity() );
 
722
        CHECKGL( glLoadMatrixf((FLOAT*) GetThreadGraphicsContext()->GetModelViewMatrix().m) );
 
723
        CHECKGL( glMatrixMode(GL_PROJECTION) );
 
724
        CHECKGL( glLoadIdentity() );
 
725
        CHECKGL( glLoadMatrixf((FLOAT*) GetThreadGraphicsContext()->GetProjectionMatrix().m) );
 
726
 
 
727
        iPosition   = VTXATTRIB_POSITION;
 
728
        iTexUV      = VTXATTRIB_TEXCOORD0;
 
729
        iScale      = VTXATTRIB_TEXCOORD1;
 
730
        iOffset     = VTXATTRIB_TEXCOORD2;
 
731
 
 
732
        CHECKGL( glProgramLocalParameter4fARB(GL_FRAGMENT_PROGRAM_ARB, 0, color.R(), color.G(), color.B(), color.A()) );
 
733
 
 
734
        GetThreadGraphicsContext()->SetTexture(GL_TEXTURE0, glTexture->m_Texture);
 
735
    }
 
736
 
 
737
    if(iOffset != -1)
 
738
    {
 
739
        CHECKGL( glEnableVertexAttribArrayARB(iOffset) );
 
740
        CHECKGL( glVertexAttribPointerARB(iOffset, 4, GL_FLOAT, GL_FALSE, 16, Offset) );
 
741
    }
 
742
 
 
743
    if(iPosition != -1)
 
744
    {
 
745
        CHECKGL( glEnableVertexAttribArrayARB(iPosition) );
 
746
        CHECKGL( glVertexAttribPointerARB(iPosition, 4, GL_FLOAT, GL_FALSE, 16, Position) );
 
747
    }
 
748
 
 
749
    if(iScale != -1)
 
750
    {
 
751
        CHECKGL( glEnableVertexAttribArrayARB(iScale) );
 
752
        CHECKGL( glVertexAttribPointerARB(iScale, 4, GL_FLOAT, GL_FALSE, 16, Scale) );
 
753
    }
 
754
 
 
755
    if(iTexUV != -1)
 
756
    {
 
757
        CHECKGL( glEnableVertexAttribArrayARB(iTexUV) );
 
758
        CHECKGL( glVertexAttribPointerARB(iTexUV, 4, GL_FLOAT, GL_FALSE, 16, UV) );
 
759
    }
 
760
 
 
761
    if(NumCharToDraw > 0)
 
762
        CHECKGL( glDrawArrays( GL_QUADS, 0, NumCharToDraw*4 ) );
 
763
 
 
764
    if(iPosition != -1)
 
765
        CHECKGL( glDisableVertexAttribArrayARB(iPosition) );
 
766
    if(iOffset != -1)
 
767
        CHECKGL( glDisableVertexAttribArrayARB(iOffset) );
 
768
    if(iScale != -1)
 
769
        CHECKGL( glDisableVertexAttribArrayARB(iScale) );
 
770
    if(iTexUV != -1)
 
771
        CHECKGL( glDisableVertexAttribArrayARB(iTexUV) );
 
772
 
 
773
    if(!USE_ARB_SHADERS)
 
774
    {
 
775
        m_ShaderProg->End();
 
776
    }
 
777
    else
 
778
    {
 
779
        m_AsmShaderProg->End();
 
780
    }
 
781
 
 
782
    GetThreadGraphicsContext()->GetRenderStates().SetColorMask(TRUE, TRUE, TRUE, TRUE);
 
783
    GetThreadGraphicsContext()->GetRenderStates().SetBlend(FALSE);
 
784
 
 
785
    CHECKGL( glDisable(GL_TEXTURE_RECTANGLE_ARB) );
 
786
 
 
787
    CurX -= x + CURSOR_OFFSET;
 
788
 
 
789
    delete [] Position;
 
790
    delete [] UV;
 
791
    delete [] Scale;
 
792
    delete [] Offset;
 
793
 
 
794
    return CurX; // number of pixel to offset before writing the next string.
 
795
}
 
796
 
 
797
int FontRenderer::RenderTextToBuffer(float* VertexBuffer, int VBSize,
 
798
                                     const NFontPtr& Font, Rect geo, const NString& str, const Color& color, TextAlignment alignment, int NumCharacter)
 
799
{
 
800
    nuxAssertMsg(NumCharacter >= 0, TEXT("[FontRenderer::RenderTextToBuffer] Number of char to draw must be positive."));
 
801
    int NumCharToDraw = 0;
 
802
    if(NumCharacter == 0)
 
803
        NumCharToDraw = str.Size();
 
804
    else
 
805
        NumCharToDraw = Min((int)str.Size(), NumCharacter);
 
806
 
 
807
    nuxAssertMsg(3*NumCharToDraw*16 <= VBSize, TEXT("[FontRenderer::RenderTextToBuffer] VertexBuffer not large enough."));
 
808
    if(3*NumCharToDraw*16 > VBSize)
 
809
        return 0;
 
810
 
 
811
    StringBBox stringBBox;
 
812
    PageBBox pageBox;
 
813
    pageBox.xmin = geo.x;
 
814
    pageBox.xmax = geo.x + geo.GetWidth();
 
815
    pageBox.ymin = geo.y;
 
816
    pageBox.ymax = geo.y + geo.GetHeight();
 
817
    pageBox.x_margin = 0;
 
818
    pageBox.y_margin = 0;
 
819
 
 
820
    unsigned int CurrentPage = 0;
 
821
 
 
822
    PositionString(Font, str, pageBox, stringBBox, alignment);
 
823
 
 
824
    int CurX = stringBBox.x;
 
825
    int CurY = stringBBox.y;
 
826
 
 
827
    Vector4* Position = (Vector4*)VertexBuffer;
 
828
 
 
829
    for(int i = 0; i < NumCharToDraw; ++i)
 
830
    {
 
831
        unsigned char c = static_cast<unsigned char>(str[i]);
 
832
        unsigned int CharX = Font->m_Charset.Chars[c /*Str[i]*/].x;
 
833
        unsigned int CharY = Font->m_Charset.Chars[c /*Str[i]*/].y;
 
834
        unsigned int Width = Font->m_Charset.Chars[c /*Str[i]*/].Width;
 
835
        unsigned int Height = Font->m_Charset.Chars[c /*Str[i]*/].Height;
 
836
        int OffsetX = Font->m_Charset.Chars[c /*Str[i]*/].XOffset;
 
837
        int OffsetY = Font->m_Charset.Chars[c /*Str[i]*/].YOffset;
 
838
        int abcA = Font->m_Charset.Chars[c /*Str[i]*/].abcA;
 
839
        int abcB = Font->m_Charset.Chars[c /*Str[i]*/].abcB;
 
840
        int abcC = Font->m_Charset.Chars[c /*Str[i]*/].abcC;
 
841
        int page = Font->m_Charset.Chars[c /*Str[i]*/].page;
 
842
 
 
843
        // Position upper left
 
844
        //                            Scale       Offset
 
845
        Position[i*12 + 0].x = 0.0f  * Width     + (CurX + abcA);    // x
 
846
        Position[i*12 + 0].y = 0.0f  * Height    + (CurY);           // y
 
847
        Position[i*12 + 0].z = 0.0f  * 1.0f      + 0.0f;             // z
 
848
        Position[i*12 + 0].w = 1.0f  * 1.0f      + 0.0f;             // w
 
849
        // texture coord
 
850
        Position[i*12 + 1].x = CharX;
 
851
        Position[i*12 + 1].y = CharY;
 
852
        Position[i*12 + 1].z = 0.0f;
 
853
        Position[i*12 + 1].w = 1.0f;
 
854
        // color
 
855
        Position[i*12 + 2].x = color.R();
 
856
        Position[i*12 + 2].y = color.G();
 
857
        Position[i*12 + 2].z = color.B();
 
858
        Position[i*12 + 2].w = color.A();
 
859
 
 
860
        // Position lower left
 
861
        Position[i*12 + 9].x = 0.0f  * Width     + (CurX + abcA);    // x
 
862
        Position[i*12 + 9].y = 1.0f  * Height    + (CurY);           // y
 
863
        Position[i*12 + 9].z = 0.0f  * 1.0f      + 0.0f;             // z
 
864
        Position[i*12 + 9].w = 1.0f  * 1.0f      + 0.0f;             // w
 
865
        // texture coord
 
866
        Position[i*12 + 10].x = CharX;
 
867
        Position[i*12 + 10].y = CharY+Height;
 
868
        Position[i*12 + 10].z = 0.0f;
 
869
        Position[i*12 + 10].w = 1.0f;
 
870
        // color
 
871
        Position[i*12 + 11].x = color.R();
 
872
        Position[i*12 + 11].y = color.G();
 
873
        Position[i*12 + 11].z = color.B();
 
874
        Position[i*12 + 11].w = color.A();
 
875
 
 
876
        // Position lower right
 
877
        Position[i*12 + 6].x = 1.0f  * Width     + (CurX + abcA);    // x
 
878
        Position[i*12 + 6].y = 1.0f  * Height    + (CurY);           // y
 
879
        Position[i*12 + 6].z = 0.0f  * 1.0f      + 0.0f;             // z
 
880
        Position[i*12 + 6].w = 1.0f  * 1.0f      + 0.0f;             // w
 
881
        // texture coord
 
882
        Position[i*12 + 7].x = CharX+Width;
 
883
        Position[i*12 + 7].y = CharY+Height;
 
884
        Position[i*12 + 7].z = 0.0f;
 
885
        Position[i*12 + 7].w = 1.0f;
 
886
        // color
 
887
        Position[i*12 + 8].x = color.R();
 
888
        Position[i*12 + 8].y = color.G();
 
889
        Position[i*12 + 8].z = color.B();
 
890
        Position[i*12 + 8].w = color.A();
 
891
 
 
892
        // Position upper right
 
893
        Position[i*12 + 3].x = 1.0f  * Width     + (CurX + abcA);    // x
 
894
        Position[i*12 + 3].y = 0.0f  * Height    + (CurY);           // y
 
895
        Position[i*12 + 3].z = 0.0f  * 1.0f      + 0.0f;             // z
 
896
        Position[i*12 + 3].w = 1.0f  * 1.0f      + 0.0f;             // w
 
897
        // texture coord
 
898
        Position[i*12 + 4].x = CharX+Width;
 
899
        Position[i*12 + 4].y = CharY;
 
900
        Position[i*12 + 4].z = 0.0f;
 
901
        Position[i*12 + 4].w = 1.0f;
 
902
        // color
 
903
        Position[i*12 + 5].x = color.R();
 
904
        Position[i*12 + 5].y = color.G();
 
905
        Position[i*12 + 5].z = color.B();
 
906
        Position[i*12 + 5].w = color.A();
 
907
 
 
908
 
 
909
 
 
910
 
 
911
 
 
912
        CurX += abcA + abcB + abcC;
 
913
    }
 
914
 
 
915
    CurX -= stringBBox.x + CURSOR_OFFSET;
 
916
    return NumCharToDraw;
 
917
}
 
918
 
 
919
NAMESPACE_END_OGL