nux-1.14.0
FontRenderer.cpp
00001 /*
00002  * Copyright 2010 Inalogic® Inc.
00003  *
00004  * This program is free software: you can redistribute it and/or modify it
00005  * under the terms of the GNU Lesser General Public License, as
00006  * published by the  Free Software Foundation; either version 2.1 or 3.0
00007  * of the License.
00008  *
00009  * This program is distributed in the hope that it will be useful, but
00010  * WITHOUT ANY WARRANTY; without even the implied warranties of
00011  * MERCHANTABILITY, SATISFACTORY QUALITY or FITNESS FOR A PARTICULAR
00012  * PURPOSE.  See the applicable version of the GNU Lesser General Public
00013  * License for more details.
00014  *
00015  * You should have received a copy of both the GNU Lesser General Public
00016  * License along with this program. If not, see <http://www.gnu.org/licenses/>
00017  *
00018  * Authored by: Jay Taoko <jaytaoko@inalogic.com>
00019  *
00020  */
00021 
00022 
00023 #include "GLResource.h"
00024 #include "IOpenGLResource.h"
00025 #include "GLResourceManager.h"
00026 #include "IOpenGLBaseTexture.h"
00027 #include "GpuDevice.h"
00028 #include "GLTextureResourceManager.h"
00029 
00030 #include "GraphicsEngine.h"
00031 
00032 #include "FontRenderer.h"
00033 
00034 namespace nux
00035 {
00036 
00037   const int CURSOR_OFFSET = 0;
00038   static int CURSOR_SIZE = 2;
00039 
00040   // On NVidia system:
00041   //  - declare the vertex attribute name before any other attribute.
00042   //  - Give the vertex attribute a name that comes before any other attribute name. For instance prefix the vertex attribute name with "_".
00043 
00044   NString gFontVtxShader = TEXT ("#version 110      \n\
00045   attribute vec4 _Position;                         \n\
00046   attribute vec4 iOffset;                           \n\
00047   attribute vec4 iScale;                            \n\
00048   attribute vec4 iTexUV;                            \n\
00049   uniform mat4 ViewProjectionMatrix;                \n\
00050   varying vec4 oTexCoord0;                          \n\
00051   void main()                                       \n\
00052   {                                                 \n\
00053   oTexCoord0   = iTexUV;                            \n\
00054   vec4 myvertex = _Position * iScale + iOffset;     \n\
00055   gl_Position  = ViewProjectionMatrix * myvertex;   \n\
00056   }");
00057 
00058   NString gFontFragShader = TEXT ("#version 110                             \n\
00059   #extension GL_ARB_texture_rectangle : enable                              \n\
00060   uniform sampler2DRect FontTexture;                                        \n\
00061   uniform vec4 TextColor;                                                   \n\
00062   varying vec4 oTexCoord0;                                                  \n\
00063   void main()                                                               \n\
00064   {                                                                         \n\
00065     vec4 diffuse = texture2DRect(FontTexture, oTexCoord0.st);               \n\
00066     gl_FragColor = vec4(TextColor.x, TextColor.y, TextColor.z, diffuse.w);  \n\
00067   }");
00068 
00069   NString FontAsmVtx = TEXT ("!!ARBvp1.0          \n\
00070   ATTRIB iScale       = vertex.attrib[9];         \n\
00071   ATTRIB iOffset      = vertex.attrib[10];        \n\
00072   OUTPUT oPos         = result.position;          \n\
00073   OUTPUT oTexCoord0   = result.texcoord[0];       \n\
00074   # Transform the vertex to clip coordinates.     \n\
00075   TEMP temp;                                      \n\
00076   MAD   temp, vertex.position, iScale, iOffset;   \n\
00077   DP4   oPos.x, state.matrix.mvp.row[0], temp;    \n\
00078   DP4   oPos.y, state.matrix.mvp.row[1], temp;    \n\
00079   DP4   oPos.z, state.matrix.mvp.row[2], temp;    \n\
00080   DP4   oPos.w, state.matrix.mvp.row[3], temp;    \n\
00081   MOV   oTexCoord0, vertex.attrib[8];             \n\
00082   END");
00083 
00084   NString FontAsmFrg = TEXT ("!!ARBfp1.0            \n\
00085   PARAM color = program.local[0];                   \n\
00086   TEMP temp;                                        \n\
00087   TEMP tex0;                                        \n\
00088   TEX tex0, fragment.texcoord[0], texture[0], 2D;   \n\
00089   MOV temp, color;                                  \n\
00090   MUL temp.w, color, tex0;                          \n\
00091   MOV result.color, temp;                           \n\
00092   END");
00093 
00094   NString FontAsmFrgRect = TEXT ("!!ARBfp1.0        \n\
00095   PARAM color = program.local[0];                   \n\
00096   TEMP temp;                                        \n\
00097   TEMP tex0;                                        \n\
00098   TEX tex0, fragment.texcoord[0], texture[0], RECT; \n\
00099   MOV temp, color;                                  \n\
00100   MUL temp.w, color, tex0;                          \n\
00101   MOV result.color, temp;                           \n\
00102   END");
00103 
00104 
00105   FontRenderer::FontRenderer (GraphicsEngine &graphics_engine)
00106     :   _graphics_engine (graphics_engine)
00107   {
00108     if(_graphics_engine.UsingGLSLCodePath())
00109     {
00110       _pixel_shader_prog = GetGraphicsDisplay()->GetGpuDevice()->CreatePixelShader();
00111       _vertex_shader_prog = GetGraphicsDisplay()->GetGpuDevice()->CreateVertexShader();
00112       _shader_prog = GetGraphicsDisplay()->GetGpuDevice()->CreateShaderProgram();
00113 
00114       _vertex_shader_prog->SetShaderCode (TCHAR_TO_ANSI (*gFontVtxShader) );
00115       _pixel_shader_prog->SetShaderCode (TCHAR_TO_ANSI (*gFontFragShader) );
00116 
00117       _shader_prog->ClearShaderObjects();
00118       _shader_prog->AddShaderObject (_vertex_shader_prog);
00119       _shader_prog->AddShaderObject (_pixel_shader_prog);
00120       //CHECKGL (glBindAttribLocation(_shader_prog->GetOpenGLID(), 0, "_Position"));
00121       _shader_prog->Link();
00122     }
00123     else
00124     {
00125       _asm_shader_prog = GetGraphicsDisplay()->GetGpuDevice()->CreateAsmShaderProgram();
00126 
00127       _asm_shader_prog->LoadVertexShader (TCHAR_TO_ANSI (*FontAsmVtx) );
00128       _asm_shader_prog->LoadPixelShader (TCHAR_TO_ANSI (*FontAsmFrg) );
00129       _asm_shader_prog->Link();
00130 
00131       _asm_font_texture_rect_prog = GetGraphicsDisplay()->GetGpuDevice()->CreateAsmShaderProgram();
00132       _asm_font_texture_rect_prog->LoadVertexShader (TCHAR_TO_ANSI (*FontAsmVtx) );
00133       _asm_font_texture_rect_prog->LoadPixelShader (TCHAR_TO_ANSI (*FontAsmFrgRect) );
00134       _asm_font_texture_rect_prog->Link();
00135     }
00136   }
00137 
00138   FontRenderer::~FontRenderer()
00139   {
00140   }
00141 
00142   int FontRenderer::DrawColorString (ObjectPtr<FontTexture> Font, int x, int y, const NString &str, const Color &color, bool WriteAlphaChannel, int SkipFirstNCharacters, int NumCharacter)
00143   {
00144     return RenderText (Font, x, y, str, color, WriteAlphaChannel, SkipFirstNCharacters, NumCharacter);
00145   }
00146 
00147   void FontRenderer::PositionString (ObjectPtr<FontTexture> Font, const NString &str, const PageBBox &pageBBox, StringBBox &strBBox, TextAlignment alignment, int NumCharacter)
00148   {
00149     int x, y;
00150     int xmin, ymin, xmax, ymax;
00151     xmin = pageBBox.xmin + pageBBox.x_margin;
00152     xmax = pageBBox.xmax - pageBBox.x_margin;
00153     ymin = pageBBox.ymin + pageBBox.y_margin;
00154     ymax = pageBBox.ymax - pageBBox.y_margin;
00155 
00156     int NumChar = 0;
00157 
00158     if (NumCharacter == 0)
00159       NumChar = str.Size();
00160     else
00161       NumChar = Min ((int) str.Size(), NumCharacter);
00162 
00163     strBBox.width = Font->GetStringWidth(str, NumChar);
00164     strBBox.height = Font->GetLineHeight();
00165 
00166     switch (alignment)
00167     {
00168       case eAlignTextCenter:
00169 
00170         if (strBBox.width > xmax - xmin)
00171           x = xmin; // the text is larger than the box: default to eAlignTextLeft for x.
00172         else
00173           x = xmin + ( (float) (xmax - xmin) - (float) (strBBox.width) ) / 2.0f;
00174 
00175         y = ymin + ( (float) (ymax - ymin) - (float) (strBBox.height) ) / 2.0f;
00176         break;
00177 
00178       case eAlignTextRight:
00179         x = xmin + ( (float) (xmax - xmin) - (float) (strBBox.width) );
00180         y = ymin + ( (float) (ymax - ymin) - (float) (strBBox.height) ) / 2.0f;
00181         break;
00182 
00183       case eAlignTextLeft:
00184       default:
00185         x = xmin;
00186         y = ymin + ( (float) (ymax - ymin) - (float) (strBBox.height) ) / 2.0f;
00187         break;
00188     }
00189 
00190     strBBox.x = x;
00191     strBBox.y = y;
00192   }
00193 
00194   int FontRenderer::RenderColorText (ObjectPtr<FontTexture> Font, int x, int y, const NString &Str, const Color &color,
00195                                      bool WriteAlphaChannel, int NumCharacter)
00196   {
00197     int off = DrawColorString (Font, x, y, Str, color, WriteAlphaChannel, 0, NumCharacter);
00198     return off;
00199   }
00200 
00201   int FontRenderer::RenderColorTextLineStatic (ObjectPtr<FontTexture> Font, const PageBBox &pageSize, const NString &Str, const Color &color,
00202       bool WriteAlphaChannel, TextAlignment alignment)
00203   {
00204     StringBBox stringBBox;
00205 
00206     _graphics_engine.PushClippingRectangle (Rect (pageSize.xmin, pageSize.ymin, pageSize.xmax - pageSize.xmin, pageSize.ymax - pageSize.ymin) );
00207     PositionString (Font, Str, pageSize, stringBBox, alignment);
00208     int off = DrawColorString (Font, stringBBox.x, stringBBox.y, Str, color, WriteAlphaChannel, 0, Str.Size() );
00209 
00210     _graphics_engine.PopClippingRectangle();
00211     return off;
00212   }
00213 
00214   int FontRenderer::RenderColorTextLineEdit (ObjectPtr<FontTexture> Font, const PageBBox &pageSize, const NString &Str,
00215       const Color &TextColor,
00216       bool WriteAlphaChannel,
00217       const Color &SelectedTextColor,
00218       const Color &SelectedTextBackgroundColor,
00219       const Color &TextBlinkColor,
00220       const Color &CursorColor,
00221       bool ShowCursor, unsigned int CursorPosition, int offset, int selection_start, int selection_end)
00222   {
00223     StringBBox stringBBox;
00224     Color selection_color (0xFF888888);
00225 
00226     NString substring = Str.GetSubString (selection_start, selection_end - selection_start);
00227     unsigned int substring_width = Font->GetStringWidth (substring);
00228     int substring_pos = Font->GetStringWidth (Str, selection_start);
00229 
00230     _graphics_engine.PushClippingRectangle (Rect (pageSize.xmin, pageSize.ymin, pageSize.xmax - pageSize.xmin, pageSize.ymax - pageSize.ymin) );
00231 
00232     if (substring_width > 0)
00233       _graphics_engine.QRP_Color (pageSize.xmin + offset + substring_pos, pageSize.ymin, substring_width, pageSize.ymax - pageSize.ymin, SelectedTextBackgroundColor);
00234 
00235     _graphics_engine.PopClippingRectangle();
00236 
00237     _graphics_engine.PushClippingRectangle (Rect (pageSize.xmin, pageSize.ymin, pageSize.xmax - pageSize.xmin, pageSize.ymax - pageSize.ymin) );
00238 
00239     PositionString (Font, Str, pageSize, stringBBox, eAlignTextLeft);
00240     //ComputeGlyphString(stringBBox.x + offset, stringBBox.y, Str.c_str());
00241 
00242     // Part before selected text
00243     int off = DrawColorString (Font, stringBBox.x + offset, stringBBox.y, Str, TextColor, WriteAlphaChannel, 0, selection_start);
00244     // Selection part
00245     off = DrawColorString (Font, stringBBox.x + offset, stringBBox.y, Str, SelectedTextColor, WriteAlphaChannel, selection_start, selection_end - selection_start);
00246     // Part after selected text
00247     off = DrawColorString (Font, stringBBox.x + offset, stringBBox.y, Str, TextColor, WriteAlphaChannel, selection_end, Str.Size() - selection_end);
00248 
00249     _graphics_engine.PopClippingRectangle();
00250 
00251     // Render Cursor
00252     NString temp = Str.GetSubString (0, CursorPosition);
00253     int w = Font->GetStringWidth (temp.GetTCharPtr() );
00254 
00255 
00256     if (ShowCursor)
00257     {
00258       int x = pageSize.xmin + w + offset + CURSOR_OFFSET;
00259       x = (x >= pageSize.xmax) ? pageSize.xmax - 1 : x;
00260       _graphics_engine.PushClippingRectangle (Rect (x, pageSize.ymin, CURSOR_SIZE, pageSize.ymax - pageSize.ymin) );
00261 
00262       _graphics_engine.QRP_Color (x, pageSize.ymin, CURSOR_SIZE, pageSize.ymax - pageSize.ymin, CursorColor);
00263       
00264       DrawColorString (Font, stringBBox.x + offset, stringBBox.y, Str, TextBlinkColor, WriteAlphaChannel, CursorPosition, 1);
00265       _graphics_engine.PopClippingRectangle();
00266     }
00267 
00268     return off;
00269   }
00270 
00271   int FontRenderer::RenderText (ObjectPtr<FontTexture> Font, int x, int y, const NString &str, const Color &color, bool WriteAlphaChannel, int StartCharacter, int NumCharacter)
00272   {
00273     // !WARNING This call works if all the glyph of the font are in a single texture.
00274 
00275     int StrLength = str.Size();
00276 
00277     if (StrLength <= 0)
00278       return 0;
00279 
00280     nuxAssertMsg (NumCharacter >= 0, TEXT ("[FontRenderer::RenderText] Incorrect value for NumCharacter.") );
00281     nuxAssertMsg (StartCharacter >= 0, TEXT ("[FontRenderer::RenderText] Incorrect value for StartCharacter.") );
00282     nuxAssertMsg (StartCharacter <= StrLength, TEXT ("[FontRenderer::RenderText] Incorrect value for StartCharacter.") );
00283 
00284     //     if(NumCharacter == 0)
00285     //         NumCharacter = str.Size();
00286 
00287     int NumCharToDraw = Min<int> (StrLength - StartCharacter, NumCharacter);
00288 
00289     //nuxAssertMsg(NumCharToDraw > 0, TEXT("[FontRenderer::RenderText] Incorrect value for NumCharToDraw."));
00290     if (NumCharToDraw <= 0)
00291       return 0;
00292 
00293     CHECKGL ( glDisable (GL_CULL_FACE) );
00294     int CurX = x;
00295     int CurY = y;
00296     _graphics_engine.GetRenderStates().SetBlend (TRUE, GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
00297     _graphics_engine.GetRenderStates().SetColorMask (TRUE, TRUE, TRUE, WriteAlphaChannel); // Do not write the alpha of characters
00298 
00299     Vector4 *Position = new Vector4[StrLength*4];
00300     Vector4 *UV = new Vector4[StrLength*4];
00301     Vector4 *Offset = new Vector4[StrLength*4];
00302     Vector4 *Scale = new Vector4[StrLength*4];
00303 
00304     ObjectPtr<CachedBaseTexture> glTexture = _graphics_engine.ResourceCache.GetCachedResource (Font->TextureArray[0]);
00305 
00306     float tex_width = (float) glTexture->m_Texture->GetWidth();
00307     float tex_height = (float) glTexture->m_Texture->GetHeight();
00308 
00309     for (int i = 0; i < StrLength; ++i)
00310     {
00311       unsigned char c = static_cast<unsigned char> (str[i]);
00312       unsigned int CharX = Font->m_Charset.Chars[c /*Str[i]*/].x;
00313       unsigned int CharY = Font->m_Charset.Chars[c /*Str[i]*/].y;
00314       unsigned int Width = Font->m_Charset.Chars[c /*Str[i]*/].Width;
00315       unsigned int Height = Font->m_Charset.Chars[c /*Str[i]*/].Height;
00316       //int OffsetX = Font->m_Charset.Chars[c /*Str[i]*/].XOffset;
00317       //int OffsetY = Font->m_Charset.Chars[c /*Str[i]*/].YOffset;
00318       int abcA = Font->m_Charset.Chars[c /*Str[i]*/].abcA;
00319       int abcB = Font->m_Charset.Chars[c /*Str[i]*/].abcB;
00320       int abcC = Font->m_Charset.Chars[c /*Str[i]*/].abcC;
00321       //int page = Font->m_Charset.Chars[c /*Str[i]*/].page;
00322 
00323       if ( (i >= StartCharacter) && (i < StartCharacter + NumCharToDraw) )
00324       {
00325         int II = i - StartCharacter;
00326         Position[II*4 + 0].x = 0;      // x
00327         Position[II*4 + 0].y = 0;      // y
00328         Position[II*4 + 0].z = 0;      // z
00329         Position[II*4 + 0].w = 1.0f;   // w
00330 
00331         Position[II*4 + 1].x = 1.0f;   // x
00332         Position[II*4 + 1].y = 0;      // y
00333         Position[II*4 + 1].z = 0;      // z
00334         Position[II*4 + 1].w = 1;      // w
00335 
00336         Position[II*4 + 2].x = 1.0f;   // x
00337         Position[II*4 + 2].y = 1.0f;   // y
00338         Position[II*4 + 2].z = 0;      // z
00339         Position[II*4 + 2].w = 1;      // w
00340 
00341         Position[II*4 + 3].x = 0;      // x
00342         Position[II*4 + 3].y = 1.0f;   // y
00343         Position[II*4 + 3].z = 0;      // z
00344         Position[II*4 + 3].w = 1;      // w
00345 
00346         for (int j = 0; j < 4; j++)
00347         {
00348           Offset[II*4 + j].x = CurX + abcA;
00349           Offset[II*4 + j].y = CurY;
00350           Offset[II*4 + j].z = 0.0f;
00351           Offset[II*4 + j].w = 0.0f;
00352 
00353           Scale[II*4 + j].x = Width;
00354           Scale[II*4 + j].y = Height;
00355           Scale[II*4 + j].z = 1.0f;
00356           Scale[II*4 + j].w = 1.0f;
00357         }
00358 
00359         if(glTexture->m_Texture->Type().IsDerivedFromType(IOpenGLRectangleTexture::StaticObjectType))
00360         {
00361           //upper left
00362           UV[II*4 + 0].x = CharX;
00363           UV[II*4 + 0].y = CharY;
00364           UV[II*4 + 0].z = 0.0f;
00365           UV[II*4 + 0].w = 0.0f;
00366 
00367           //upper right
00368           UV[II*4 + 1].x = (CharX + Width);
00369           UV[II*4 + 1].y = CharY;
00370           UV[II*4 + 1].z = 0.0f;
00371           UV[II*4 + 1].w = 0.0f;
00372 
00373           //lower right
00374           UV[II*4 + 2].x = (CharX + Width);
00375           UV[II*4 + 2].y = (CharY + Height);
00376           UV[II*4 + 2].z = 0.0f;
00377           UV[II*4 + 2].w = 0.0f;
00378 
00379           //lower left
00380           UV[II*4 + 3].x = CharX;
00381           UV[II*4 + 3].y = (CharY + Height);
00382           UV[II*4 + 3].z = 0.0f;
00383           UV[II*4 + 3].w = 0.0f;
00384         }
00385         else
00386         {
00387           //upper left
00388           UV[II*4 + 0].x = CharX / tex_width;
00389           UV[II*4 + 0].y = CharY / tex_height;
00390           UV[II*4 + 0].z = 0.0f;
00391           UV[II*4 + 0].w = 0.0f;
00392 
00393           //upper right
00394           UV[II*4 + 1].x = (CharX + Width) / tex_width;
00395           UV[II*4 + 1].y = CharY / tex_height;
00396           UV[II*4 + 1].z = 0.0f;
00397           UV[II*4 + 1].w = 0.0f;
00398 
00399           //lower right
00400           UV[II*4 + 2].x = (CharX + Width) / tex_width;
00401           UV[II*4 + 2].y = (CharY + Height) / tex_height;
00402           UV[II*4 + 2].z = 0.0f;
00403           UV[II*4 + 2].w = 0.0f;
00404 
00405           //lower left
00406           UV[II*4 + 3].x = CharX / tex_width;
00407           UV[II*4 + 3].y = (CharY + Height) / tex_height;
00408           UV[II*4 + 3].z = 0.0f;
00409           UV[II*4 + 3].w = 0.0f;
00410         }
00411       }
00412 
00413       CurX += abcA + abcB + abcC;
00414     }
00415 
00416     CHECKGL (glBindBufferARB (GL_ARRAY_BUFFER_ARB, 0) );
00417     CHECKGL (glBindBufferARB (GL_ELEMENT_ARRAY_BUFFER_ARB, 0) );
00418 
00419     int in_attrib_position = 0;
00420     int in_attrib_tex_uv = 0;
00421     int in_attrib_scale = 0;
00422     int in_attrib_offset = 0;
00423 
00424     ObjectPtr<IOpenGLAsmShaderProgram> shader_program;
00425     if(_graphics_engine.UsingGLSLCodePath())
00426     {
00427       _shader_prog->Begin();
00428       int ViewProjectionMatrix = _shader_prog->GetUniformLocationARB ("ViewProjectionMatrix");
00429       Matrix4 mat = _graphics_engine.GetOpenGLModelViewProjectionMatrix();
00430 
00431       _shader_prog->SetUniformLocMatrix4fv (ViewProjectionMatrix, 1, false, (float *) &mat);
00432 
00433       in_attrib_position = _shader_prog->GetAttributeLocation("_Position");
00434       in_attrib_tex_uv   = _shader_prog->GetAttributeLocation("iTexUV");
00435       in_attrib_scale    = _shader_prog->GetAttributeLocation("iScale");
00436       in_attrib_offset   = _shader_prog->GetAttributeLocation("iOffset");
00437 
00438       int FontTexture    = _shader_prog->GetUniformLocationARB("FontTexture");
00439       int TextColor      = _shader_prog->GetUniformLocationARB("TextColor");
00440 
00441       _graphics_engine.SetTexture(GL_TEXTURE0, glTexture->m_Texture);
00442 
00443       if(FontTexture != -1)
00444       {
00445         CHECKGL(glUniform1iARB(FontTexture, 0));
00446       }
00447 
00448       if(TextColor != -1)
00449       {
00450         CHECKGL(glUniform4fARB(TextColor, color.red, color.green, color.blue, color.alpha));
00451       }
00452     }
00453     else
00454     {
00455       shader_program = _asm_shader_prog;
00456       if(glTexture->m_Texture->Type().IsDerivedFromType(IOpenGLRectangleTexture::StaticObjectType))
00457       {
00458         shader_program = _asm_font_texture_rect_prog;
00459       }
00460       shader_program->Begin();
00461 
00462       CHECKGL (glMatrixMode(GL_MODELVIEW));
00463       CHECKGL (glLoadIdentity());
00464       Matrix4 model_view_matrix = _graphics_engine.GetModelViewMatrix ();
00465       model_view_matrix.Transpose();
00466       CHECKGL (glLoadMatrixf((float *) model_view_matrix.m));
00467 
00468       CHECKGL (glMatrixMode(GL_PROJECTION));
00469       CHECKGL (glLoadIdentity());
00470       Matrix4 projection_matrix = GetGraphicsDisplay()->GetGraphicsEngine()->GetProjectionMatrix ();
00471       projection_matrix.Transpose ();
00472       CHECKGL (glLoadMatrixf ((float *) projection_matrix.m));
00473 
00474       in_attrib_position   = VTXATTRIB_POSITION;
00475       in_attrib_tex_uv      = VTXATTRIB_TEXCOORD0;
00476       in_attrib_scale      = VTXATTRIB_TEXCOORD1;
00477       in_attrib_offset     = VTXATTRIB_TEXCOORD2;
00478 
00479       CHECKGL ( glProgramLocalParameter4fARB (GL_FRAGMENT_PROGRAM_ARB, 0, color.red, color.green, color.blue, color.alpha ) );
00480 
00481       _graphics_engine.SetTexture (GL_TEXTURE0, glTexture->m_Texture);
00482     }
00483 
00484     if (in_attrib_offset != -1)
00485     {
00486       CHECKGL ( glEnableVertexAttribArrayARB (in_attrib_offset) );
00487       CHECKGL ( glVertexAttribPointerARB (in_attrib_offset, 4, GL_FLOAT, GL_FALSE, 16, Offset) );
00488     }
00489 
00490     if (in_attrib_position != -1)
00491     {
00492       CHECKGL ( glEnableVertexAttribArrayARB (in_attrib_position) );
00493       CHECKGL ( glVertexAttribPointerARB (in_attrib_position, 4, GL_FLOAT, GL_FALSE, 16, Position) );
00494     }
00495 
00496     if (in_attrib_scale != -1)
00497     {
00498       CHECKGL ( glEnableVertexAttribArrayARB (in_attrib_scale) );
00499       CHECKGL ( glVertexAttribPointerARB (in_attrib_scale, 4, GL_FLOAT, GL_FALSE, 16, Scale) );
00500     }
00501 
00502     if (in_attrib_tex_uv != -1)
00503     {
00504       CHECKGL ( glEnableVertexAttribArrayARB (in_attrib_tex_uv) );
00505       CHECKGL ( glVertexAttribPointerARB (in_attrib_tex_uv, 4, GL_FLOAT, GL_FALSE, 16, UV) );
00506     }
00507 
00508     if (NumCharToDraw > 0)
00509       CHECKGL ( glDrawArrays ( GL_QUADS, 0, NumCharToDraw * 4 ) );
00510 
00511     if (in_attrib_position != -1)
00512       CHECKGL ( glDisableVertexAttribArrayARB (in_attrib_position) );
00513 
00514     if (in_attrib_offset != -1)
00515       CHECKGL ( glDisableVertexAttribArrayARB (in_attrib_offset) );
00516 
00517     if (in_attrib_scale != -1)
00518       CHECKGL ( glDisableVertexAttribArrayARB (in_attrib_scale) );
00519 
00520     if (in_attrib_tex_uv != -1)
00521       CHECKGL ( glDisableVertexAttribArrayARB (in_attrib_tex_uv) );
00522 
00523     if(_graphics_engine.UsingGLSLCodePath())
00524     {
00525       _shader_prog->End();
00526     }
00527     else
00528     {
00529       shader_program->End();
00530     }
00531 
00532     _graphics_engine.GetRenderStates().SetColorMask (TRUE, TRUE, TRUE, TRUE);
00533     _graphics_engine.GetRenderStates().SetBlend (FALSE);
00534 
00535     CurX -= x + CURSOR_OFFSET;
00536 
00537     delete [] Position;
00538     delete [] UV;
00539     delete [] Scale;
00540     delete [] Offset;
00541 
00542     return CurX; // number of pixel to offset before writing the next string.
00543   }
00544 
00545   int FontRenderer::RenderTextToBuffer (float *VertexBuffer, int VBSize,
00546                                         ObjectPtr<FontTexture> Font, Rect geo, const NString &str, const Color &color, TextAlignment alignment, int NumCharacter)
00547   {
00548     nuxAssertMsg (NumCharacter >= 0, TEXT ("[FontRenderer::RenderTextToBuffer] Number of char to draw must be positive.") );
00549     int NumCharToDraw = 0;
00550 
00551     if (NumCharacter == 0)
00552       NumCharToDraw = str.Size();
00553     else
00554       NumCharToDraw = Min ( (int) str.Size(), NumCharacter);
00555 
00556     nuxAssertMsg (3 * NumCharToDraw * 16 <= VBSize, TEXT ("[FontRenderer::RenderTextToBuffer] VertexBuffer not large enough.") );
00557 
00558     if (3 * NumCharToDraw * 16 > VBSize)
00559       return 0;
00560 
00561     StringBBox stringBBox;
00562     PageBBox pageBox;
00563     pageBox.xmin = geo.x;
00564     pageBox.xmax = geo.x + geo.GetWidth();
00565     pageBox.ymin = geo.y;
00566     pageBox.ymax = geo.y + geo.GetHeight();
00567     pageBox.x_margin = 0;
00568     pageBox.y_margin = 0;
00569 
00570     PositionString (Font, str, pageBox, stringBBox, alignment);
00571 
00572     int CurX = stringBBox.x;
00573     int CurY = stringBBox.y;
00574 
00575     Vector4 *Position = (Vector4 *) VertexBuffer;
00576 
00577     for (int i = 0; i < NumCharToDraw; ++i)
00578     {
00579       unsigned char c = static_cast<unsigned char> (str[i]);
00580       unsigned int CharX = Font->m_Charset.Chars[c /*Str[i]*/].x;
00581       unsigned int CharY = Font->m_Charset.Chars[c /*Str[i]*/].y;
00582       unsigned int Width = Font->m_Charset.Chars[c /*Str[i]*/].Width;
00583       unsigned int Height = Font->m_Charset.Chars[c /*Str[i]*/].Height;
00584       //int OffsetX = Font->m_Charset.Chars[c /*Str[i]*/].XOffset;
00585       //int OffsetY = Font->m_Charset.Chars[c /*Str[i]*/].YOffset;
00586       int abcA = Font->m_Charset.Chars[c /*Str[i]*/].abcA;
00587       int abcB = Font->m_Charset.Chars[c /*Str[i]*/].abcB;
00588       int abcC = Font->m_Charset.Chars[c /*Str[i]*/].abcC;
00589       //int page = Font->m_Charset.Chars[c /*Str[i]*/].page;
00590 
00591       // Position upper left
00592       //                            Scale       Offset
00593       Position[i*12 + 0].x = 0.0f  * Width     + (CurX + abcA);    // x
00594       Position[i*12 + 0].y = 0.0f  * Height    + (CurY);           // y
00595       Position[i*12 + 0].z = 0.0f  * 1.0f      + 0.0f;             // z
00596       Position[i*12 + 0].w = 1.0f  * 1.0f      + 0.0f;             // w
00597       // texture coord
00598       Position[i*12 + 1].x = CharX;
00599       Position[i*12 + 1].y = CharY;
00600       Position[i*12 + 1].z = 0.0f;
00601       Position[i*12 + 1].w = 1.0f;
00602       // color
00603       Position[i*12 + 2].x = color.red;
00604       Position[i*12 + 2].y = color.green;
00605       Position[i*12 + 2].z = color.blue;
00606       Position[i*12 + 2].w = color.alpha;
00607 
00608       // Position lower left
00609       Position[i*12 + 9].x = 0.0f  * Width     + (CurX + abcA);    // x
00610       Position[i*12 + 9].y = 1.0f  * Height    + (CurY);           // y
00611       Position[i*12 + 9].z = 0.0f  * 1.0f      + 0.0f;             // z
00612       Position[i*12 + 9].w = 1.0f  * 1.0f      + 0.0f;             // w
00613       // texture coord
00614       Position[i*12 + 10].x = CharX;
00615       Position[i*12 + 10].y = CharY + Height;
00616       Position[i*12 + 10].z = 0.0f;
00617       Position[i*12 + 10].w = 1.0f;
00618       // color
00619       Position[i*12 + 11].x = color.red;
00620       Position[i*12 + 11].y = color.green;
00621       Position[i*12 + 11].z = color.blue;
00622       Position[i*12 + 11].w = color.alpha;
00623 
00624       // Position lower right
00625       Position[i*12 + 6].x = 1.0f  * Width     + (CurX + abcA);    // x
00626       Position[i*12 + 6].y = 1.0f  * Height    + (CurY);           // y
00627       Position[i*12 + 6].z = 0.0f  * 1.0f      + 0.0f;             // z
00628       Position[i*12 + 6].w = 1.0f  * 1.0f      + 0.0f;             // w
00629       // texture coord
00630       Position[i*12 + 7].x = CharX + Width;
00631       Position[i*12 + 7].y = CharY + Height;
00632       Position[i*12 + 7].z = 0.0f;
00633       Position[i*12 + 7].w = 1.0f;
00634       // color
00635       Position[i*12 + 8].x = color.red;
00636       Position[i*12 + 8].y = color.green;
00637       Position[i*12 + 8].z = color.blue;
00638       Position[i*12 + 8].w = color.alpha;
00639 
00640       // Position upper right
00641       Position[i*12 + 3].x = 1.0f  * Width     + (CurX + abcA);    // x
00642       Position[i*12 + 3].y = 0.0f  * Height    + (CurY);           // y
00643       Position[i*12 + 3].z = 0.0f  * 1.0f      + 0.0f;             // z
00644       Position[i*12 + 3].w = 1.0f  * 1.0f      + 0.0f;             // w
00645       // texture coord
00646       Position[i*12 + 4].x = CharX + Width;
00647       Position[i*12 + 4].y = CharY;
00648       Position[i*12 + 4].z = 0.0f;
00649       Position[i*12 + 4].w = 1.0f;
00650       // color
00651       Position[i*12 + 5].x = color.red;
00652       Position[i*12 + 5].y = color.green;
00653       Position[i*12 + 5].z = color.blue;
00654       Position[i*12 + 5].w = color.alpha;
00655 
00656       CurX += abcA + abcB + abcC;
00657     }
00658 
00659     CurX -= stringBBox.x + CURSOR_OFFSET;
00660     return NumCharToDraw;
00661   }
00662 
00663 }
 All Classes Namespaces Functions Variables Typedefs Enumerations Enumerator Friends