Back to index

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