# Visualization Library

A lightweight C++ OpenGL middleware for 2D/3D graphics

[Home] [Tutorials] [All Classes] [Grouped Classes]

- Main Page
- Related Pages
- Namespaces
- Classes
- Files

- File List
- File Members

# D:/VL/BuildSystem/VL_DISTRO/Visualization_Library_SDK/src/vlGraphics/CoreText.cpp

Go to the documentation of this file.

    00001 /**************************************************************************************/
    00002 /*                                                                                    */
    00003 /*  Visualization Library                                                             */
    00004 /*  http://www.visualizationlibrary.org                                               */
    00005 /*                                                                                    */
    00006 /*  Copyright (c) 2005-2010, Michele Bosi                                             */
    00007 /*  All rights reserved.                                                              */
    00008 /*                                                                                    */
    00009 /*  Redistribution and use in source and binary forms, with or without modification,  */
    00010 /*  are permitted provided that the following conditions are met:                     */
    00011 /*                                                                                    */
    00012 /*  - Redistributions of source code must retain the above copyright notice, this     */
    00013 /*  list of conditions and the following disclaimer.                                  */
    00014 /*                                                                                    */
    00015 /*  - Redistributions in binary form must reproduce the above copyright notice, this  */
    00016 /*  list of conditions and the following disclaimer in the documentation and/or       */
    00017 /*  other materials provided with the distribution.                                   */
    00018 /*                                                                                    */
    00019 /*  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND   */
    00020 /*  ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED     */
    00021 /*  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE            */
    00022 /*  DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR  */
    00023 /*  ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES    */
    00024 /*  (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;      */
    00025 /*  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON    */
    00026 /*  ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT           */
    00027 /*  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS     */
    00028 /*  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.                      */
    00029 /*                                                                                    */
    00030 /**************************************************************************************/
    00031
    00032 #include <vlGraphics/CoreText.hpp>
    00033 #include <vlGraphics/OpenGLContext.hpp>
    00034 #include <vlGraphics/Actor.hpp>
    00035 #include <vlCore/Log.hpp>
    00036
    00037 #include <ft2build.h>
    00038 #include FT_FREETYPE_H
    00039
    00040 using namespace vl;
    00041
    00042 // mic fixme: implement me.
    00043
    00044 // Goals:
    00045 // - Run on OpenGL Core/ES.
    00046 // - Achieve a much greater rendering speed.
    00047 // - In order to do this we might sacrifice some of the usability of vl::Text
    00048
    00049 // Guidelines:
    00050 // - Viewport alignment, text transformation, transform tracking done externally.
    00051 // - Does not manipulate the GL_PROJECTION and GL_MODELVIEW matrices.
    00052 // - Text geometry and bounding boxes should be pre-computed on text change.
    00053 // - Line splitting should not be done at rendering time.
    00054 // - Should use only OpenGL Core routines.
    00055 // - Should use texture atlases and perform lazy texture binding.
    00056 // - Cleaner left to right / right to left text reversing.
    00057 // - Outline rendering should use 2 pass with enlarged glyphs instead of 5 passes or precompute an high quality outline texture.
    00058 // - Avoid using doubles and floats if possible, use integer and Rect rather floats and AABBs.
    00059
    00060 //-----------------------------------------------------------------------------
    00061 void CoreText::render_Implementation(const Actor* actor, const Shader*, const Camera* camera, OpenGLContext* gl_context) const
    00062 {
    00063   gl_context->bindVAS(NULL, false, false);
    00064
    00065   VL_CHECK(font())
    00066
    00067   if (!font() || !font()->mFT_Face)
    00068     return;
    00069
    00070   if ( text().empty() )
    00071     return;
    00072
    00073   // Lighting can be enabled or disabled.
    00074   // glDisable(GL_LIGHTING);
    00075
    00076   // Blending must be enabled explicity by the vl::Shader, also to perform z-sort.
    00077   // glEnable(GL_BLEND);
    00078
    00079   // Trucchetto che usiamo per evitare z-fighting:
    00080   // Pass #1 - fill color and stencil
    00081   // - disable depth write mask
    00082   // - depth test can be enabled or not by the user
    00083   // - depth func can be choosen by the user
    00084   // - render in the order: background, border, shadow, outline, text
    00085   // Pass #2 - fill z-buffer
    00086   // - enable depth write mask
    00087   // - disable color mask
    00088   // - disable stencil
    00089   // - drawing background and border
    00090
    00091   // Pass #1
    00092
    00093   // disable z-writing
    00094   GLboolean depth_mask=0;
    00095   glGetBooleanv(GL_DEPTH_WRITEMASK, &depth_mask);
    00096   glDepthMask(GL_FALSE);
    00097
    00098   // background
    00099   if (backgroundEnabled())
    00100     renderBackground( actor, camera );
    00101
    00102   // border
    00103   if (borderEnabled())
    00104     renderBorder( actor, camera );
    00105
    00106   // to have the most correct results we should render the text twice one for color and stencil, the other for the z-buffer
    00107
    00108   // shadow render
    00109   if (shadowEnabled())
    00110     renderText( actor, camera, shadowColor(), shadowVector() );
    00111   // outline render
    00112   if (outlineEnabled())
    00113   {
    00114     renderText( actor, camera, outlineColor(), fvec2(-1,0) );
    00115     renderText( actor, camera, outlineColor(), fvec2(+1,0) );
    00116     renderText( actor, camera, outlineColor(), fvec2(0,-1) );
    00117     renderText( actor, camera, outlineColor(), fvec2(0,+1) );
    00118   }
    00119   // text render
    00120   renderText( actor, camera, color(), fvec2(0,0) );
    00121
    00122   // Pass #2
    00123   // fills the z-buffer (not the stencil buffer): approximated to the text bbox
    00124
    00125   // restores depth mask
    00126   glDepthMask(depth_mask);
    00127
    00128   if (depth_mask)
    00129   {
    00130     // disables writing to the color buffer
    00131     GLboolean color_mask[4];
    00132     glGetBooleanv(GL_COLOR_WRITEMASK, color_mask);
    00133     glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);
    00134
    00135     // disable writing to the stencil buffer
    00136     int stencil_front_mask=0;
    00137     glGetIntegerv(GL_STENCIL_WRITEMASK, &stencil_front_mask);
    00138     int stencil_back_mask=0;
    00139     if (Has_GL_Version_2_0)
    00140       glGetIntegerv(GL_STENCIL_BACK_WRITEMASK, &stencil_back_mask);
    00141     glStencilMask(0);
    00142
    00143     // background
    00144     renderBackground( actor, camera );
    00145
    00146     // border
    00147     renderBorder( actor, camera );
    00148
    00149     // restores color writing
    00150     glColorMask(color_mask[0],color_mask[1],color_mask[2],color_mask[3]);
    00151
    00152     // restore the stencil masks
    00153     glStencilMask(stencil_front_mask);
    00154     if (Has_GL_Version_2_0)
    00155       glStencilMaskSeparate(GL_BACK, stencil_back_mask);
    00156   }
    00157 }
    00158 //-----------------------------------------------------------------------------
    00159 void CoreText::renderText(const Actor*, const Camera*, const fvec4& color, const fvec2& offset) const
    00160 {
    00161   if(!mFont)
    00162   {
    00163     Log::error("CoreText::renderText() error: no Font assigned to the CoreText object.\n");
    00164     VL_TRAP()
    00165     return;
    00166   }
    00167
    00168   if (!font()->mFT_Face)
    00169   {
    00170     Log::error("CoreText::renderText() error: invalid FT_Face: probably you tried to load an unsupported font format.\n");
    00171     VL_TRAP()
    00172     return;
    00173   }
    00174
    00175   // mic fixme: these should be pre-computed when the text is set!!!
    00176
    00177   AABB rbbox = rawboundingRect( text() ); // for text alignment
    00178   VL_CHECK(rbbox.maxCorner().z() == 0)
    00179   VL_CHECK(rbbox.minCorner().z() == 0)
    00180   AABB bbox = rbbox;
    00181   bbox.setMaxCorner( bbox.maxCorner() + vec3(2.0f*margin(), 2.0f*margin(), 0) );
    00182   VL_CHECK(bbox.maxCorner().z() == 0)
    00183   VL_CHECK(bbox.minCorner().z() == 0)
    00184
    00185   // basic render states
    00186
    00187   // mic fixme: detect GLSLProgram and use VertexAttribPointer if present.
    00188
    00189   float texc[] = { 0,0,0,0,0,0,0,0 };
    00190   VL_glActiveTexture( GL_TEXTURE0 );
    00191   VL_glClientActiveTexture( GL_TEXTURE0 );
    00192   glEnable(GL_TEXTURE_2D);
    00193   glEnableClientState( GL_TEXTURE_COORD_ARRAY );
    00194   glTexCoordPointer(2, GL_FLOAT, 0, texc);
    00195
    00196   // color
    00197   glColor4fv(color.ptr());
    00198
    00199   // Constant normal
    00200   glNormal3fv( fvec3(0,0,1).ptr() );
    00201
    00202   fvec3 vect[4];
    00203   glEnableClientState( GL_VERTEX_ARRAY );
    00204   glVertexPointer(3, GL_FLOAT, 0, vect[0].ptr());
    00205
    00206   FT_Long use_kerning = FT_HAS_KERNING( font()->mFT_Face );
    00207   FT_UInt previous = 0;
    00208
    00209   fvec2 pen(0,0);
    00210
    00211   // mic fixme:
    00212   // - lines split and lines dimensions (linebox) should be precomputed on text set!
    00213   // - or convert this function to generate a pre-computed rendering-list!
    00214
    00215   // split the text in different lines
    00216
    00217   VL_CHECK(text().length())
    00218
    00219   std::vector< String > lines;
    00220   lines.push_back( String() );
    00221   for(int i=0; i<text().length(); ++i)
    00222   {
    00223     if (text()[i] == '\n')
    00224     {
    00225       // start new line
    00226       lines.push_back( String() );
    00227     }
    00228     else
    00229       lines.back() += text()[i];
    00230   }
    00231
    00232   for(unsigned iline=0; iline<lines.size(); iline++)
    00233   {
    00234     // strip spaces at the beginning and at the end of the line
    00235     if (textAlignment() == TextAlignJustify)
    00236       lines[iline].trim();
    00237
    00238     AABB linebox = rawboundingRect( lines[iline] );
    00239     int horz_text_align = 0;
    00240     int just_space = 0;
    00241     int just_remained_space = 0;
    00242     int space_count = 0;
    00243     for(int c=0; c<(int)lines[iline].length(); c++)
    00244       if ( lines[iline][c] == ' ' )
    00245         space_count++;
    00246
    00247     if (space_count && textAlignment() == TextAlignJustify)
    00248     {
    00249       just_space          = int(rbbox.width() - linebox.width()) / space_count;
    00250       just_remained_space = int(rbbox.width() - linebox.width()) % space_count;
    00251     }
    00252
    00253     if (layout() == RightToLeftText)
    00254     {
    00255       if (textAlignment() == TextAlignRight)
    00256         horz_text_align = 0;
    00257       else
    00258       if (textAlignment() == TextAlignLeft)
    00259         horz_text_align = - int(rbbox.width() - linebox.width());
    00260       else
    00261       if (textAlignment() == TextAlignCenter)
    00262         horz_text_align = - int((rbbox.width() - linebox.width()) / 2.0f);
    00263     }
    00264     if (layout() == LeftToRightText)
    00265     {
    00266       if (textAlignment() == TextAlignRight)
    00267         horz_text_align = int(rbbox.width() - linebox.width());
    00268       else
    00269       if (textAlignment() == TextAlignLeft)
    00270         horz_text_align = 0;
    00271       else
    00272       if (textAlignment() == TextAlignCenter)
    00273         horz_text_align = + int((rbbox.width() - linebox.width()) / 2.0f);
    00274     }
    00275
    00276     // this is needed so that empty strings generate empty lines
    00277     // note that puttig '\n\n\n\n' at the beginning of a text generates
    00278     // a wrong rendering (see it with background box activated).
    00279     if (iline != 0 && !lines[iline].length())
    00280     {
    00281       pen.y() -= mFont->mHeight;
    00282       pen.x()  = 0;
    00283     }
    00284     else
    00285     for(int c=0; c<(int)lines[iline].length(); c++)
    00286     {
    00287       if (c == 0 && iline != 0)
    00288       {
    00289         pen.y() -= mFont->mHeight;
    00290         pen.x()  = 0;
    00291       }
    00292
    00293       const Glyph* glyph = mFont->glyph( lines[iline][c] );
    00294
    00295       if (!glyph)
    00296         continue;
    00297
    00298       if ( kerningEnabled() && use_kerning && previous && glyph->glyphIndex() )
    00299       {
    00300         FT_Vector delta; delta.y = 0;
    00301         if (layout() == LeftToRightText)
    00302         {
    00303           FT_Get_Kerning( font()->mFT_Face, previous, glyph->glyphIndex(), FT_KERNING_DEFAULT, &delta );
    00304           pen.x() += delta.x / 64.0f;
    00305         }
    00306         else
    00307         if (layout() == RightToLeftText)
    00308         {
    00309           FT_Get_Kerning( font()->mFT_Face, glyph->glyphIndex(), previous, FT_KERNING_DEFAULT, &delta );
    00310           pen.x() -= delta.x / 64.0f;
    00311         }
    00312         pen.y() += delta.y / 64.0f;
    00313       }
    00314       previous = glyph->glyphIndex();
    00315
    00316       if (glyph->textureHandle())
    00317       {
    00318         glBindTexture( GL_TEXTURE_2D, glyph->textureHandle() );
    00319
    00320         texc[0] = glyph->s0();
    00321         texc[1] = glyph->t1();
    00322         texc[2] = glyph->s1();
    00323         texc[3] = glyph->t1();
    00324         texc[4] = glyph->s1();
    00325         texc[5] = glyph->t0();
    00326         texc[6] = glyph->s0();
    00327         texc[7] = glyph->t0();
    00328
    00329         int left = layout() == RightToLeftText ? -glyph->left() : +glyph->left();
    00330
    00331         vect[0].x() = pen.x() + glyph->width()*0 + left -1;
    00332         vect[0].y() = pen.y() + glyph->height()*0 + glyph->top() - glyph->height() -1;
    00333
    00334         vect[1].x() = pen.x() + glyph->width()*1 + left +1;
    00335         vect[1].y() = pen.y() + glyph->height()*0 + glyph->top() - glyph->height() -1;
    00336
    00337         vect[2].x() = pen.x() + glyph->width()*1 + left +1;
    00338         vect[2].y() = pen.y() + glyph->height()*1 + glyph->top() - glyph->height() +1;
    00339
    00340         vect[3].x() = pen.x() + glyph->width()*0 + left -1;
    00341         vect[3].y() = pen.y() + glyph->height()*1 + glyph->top() - glyph->height() +1;
    00342
    00343         if (layout() == RightToLeftText)
    00344         {
    00345           vect[0].x() -= glyph->width()-1 +2;
    00346           vect[1].x() -= glyph->width()-1 +2;
    00347           vect[2].x() -= glyph->width()-1 +2;
    00348           vect[3].x() -= glyph->width()-1 +2;
    00349         }
    00350
    00351         vect[0].y() -= mFont->mHeight;
    00352         vect[1].y() -= mFont->mHeight;
    00353         vect[2].y() -= mFont->mHeight;
    00354         vect[3].y() -= mFont->mHeight;
    00355
    00356         // normalize coordinate orgin to the bottom/left corner
    00357         vect[0] -= (fvec3)bbox.minCorner();
    00358         vect[1] -= (fvec3)bbox.minCorner();
    00359         vect[2] -= (fvec3)bbox.minCorner();
    00360         vect[3] -= (fvec3)bbox.minCorner();
    00361
    00362         // margin & horz_text_align
    00363         vect[0].x() += margin() + horz_text_align;
    00364         vect[0].y() += margin();
    00365         vect[1].x() += margin() + horz_text_align;
    00366         vect[1].y() += margin();
    00367         vect[2].x() += margin() + horz_text_align;
    00368         vect[2].y() += margin();
    00369         vect[3].x() += margin() + horz_text_align;
    00370         vect[3].y() += margin();
    00371
    00372         // apply offset for outline rendering
    00373         vect[0].x() += offset.x();
    00374         vect[0].y() += offset.y();
    00375         vect[1].x() += offset.x();
    00376         vect[1].y() += offset.y();
    00377         vect[2].x() += offset.x();
    00378         vect[2].y() += offset.y();
    00379         vect[3].x() += offset.x();
    00380         vect[3].y() += offset.y();
    00381
    00382         // text pivot
    00383         for(int i=0; i<4; ++i)
    00384         {
    00385           if (textOrigin() & AlignHCenter)
    00386           {
    00387             VL_CHECK( !(textOrigin() & AlignRight) )
    00388             VL_CHECK( !(textOrigin() & AlignLeft) )
    00389             vect[i].x() -= (int)(bbox.width() / 2.0f);
    00390           }
    00391
    00392           if (textOrigin() & AlignRight)
    00393           {
    00394             VL_CHECK( !(textOrigin() & AlignHCenter) )
    00395             VL_CHECK( !(textOrigin() & AlignLeft) )
    00396             vect[i].x() -= (int)bbox.width();
    00397           }
    00398
    00399           if (textOrigin() & AlignTop)
    00400           {
    00401             VL_CHECK( !(textOrigin() & AlignBottom) )
    00402             VL_CHECK( !(textOrigin() & AlignVCenter) )
    00403             vect[i].y() -= (int)bbox.height();
    00404           }
    00405
    00406           if (textOrigin() & AlignVCenter)
    00407           {
    00408             VL_CHECK( !(textOrigin() & AlignTop) )
    00409             VL_CHECK( !(textOrigin() & AlignBottom) )
    00410             vect[i].y() -= int(bbox.height() / 2.0);
    00411           }
    00412         }
    00413
    00414         glDrawArrays(GL_QUADS, 0, 4);
    00415
    00416         #if (0)
    00417           glDisable(GL_TEXTURE_2D);
    00418           glColor3fv(vec3(1,0,0).ptr());
    00419           glDrawArrays(GL_LINE_LOOP, 0, 4);
    00420           glColor4fv(color.ptr());
    00421           glEnable(GL_TEXTURE_2D);
    00422         #endif
    00423       }
    00424
    00425       if (just_space && lines[iline][c] == ' ' && iline != lines.size()-1)
    00426       {
    00427         if (layout() == LeftToRightText)
    00428         {
    00429           pen.x() += just_space + (just_remained_space?1:0);
    00430           // pen.y() += glyph->advance().y();
    00431         }
    00432         else
    00433         if (layout() == RightToLeftText)
    00434         {
    00435           pen.x() -= just_space + (just_remained_space?1:0);
    00436           // pen.y() -= glyph->advance().y();
    00437         }
    00438         if(just_remained_space)
    00439           just_remained_space--;
    00440       }
    00441
    00442       if (layout() == LeftToRightText)
    00443       {
    00444         pen.x() += glyph->advance().x();
    00445         // pen.y() += glyph->advance().y();
    00446       }
    00447       else
    00448       if (layout() == RightToLeftText)
    00449       {
    00450         pen.x() -= glyph->advance().x();
    00451         // pen.y() -= glyph->advance().y();
    00452       }
    00453
    00454     }
    00455   }
    00456
    00457   glDisableClientState( GL_VERTEX_ARRAY );
    00458   glDisableClientState( GL_TEXTURE_COORD_ARRAY );
    00459
    00460   VL_CHECK_OGL();
    00461
    00462   glDisable(GL_TEXTURE_2D);
    00463   glBindTexture(GL_TEXTURE_2D, 0);
    00464 }
    00465 //-----------------------------------------------------------------------------
    00466 // returns the raw bounding box of the string, i.e. without alignment, margin and matrix transform.
    00467 AABB CoreText::rawboundingRect(const String& text) const
    00468 {
    00469   AABB aabb;
    00470
    00471   if(!font())
    00472   {
    00473     Log::error("CoreText::rawboundingRect() error: no Font assigned to the CoreText object.\n");
    00474     VL_TRAP()
    00475     return aabb;
    00476   }
    00477
    00478   if (!font()->mFT_Face)
    00479   {
    00480     Log::error("CoreText::rawboundingRect() error: invalid FT_Face: probably you tried to load an unsupported font format.\n");
    00481     VL_TRAP()
    00482     return aabb;
    00483   }
    00484
    00485   fvec2 pen(0,0);
    00486   fvec3 vect[4];
    00487
    00488   FT_Long use_kerning = FT_HAS_KERNING( font()->mFT_Face );
    00489   FT_UInt previous = 0;
    00490
    00491   for(int c=0; c<(int)text.length(); c++)
    00492   {
    00493     if (text[c] == '\n')
    00494     {
    00495       pen.y() -= mFont->mHeight ? mFont->mHeight : mFont->mSize;
    00496       pen.x()  = 0;
    00497       continue;
    00498     }
    00499
    00500     const ref<Glyph>& glyph = mFont->glyph(text[c]);
    00501
    00502     // if glyph == NULL there was an error during its creation...
    00503     if (glyph.get() == NULL)
    00504       continue;
    00505
    00506     if ( kerningEnabled() && use_kerning && previous && glyph->glyphIndex())
    00507     {
    00508       FT_Vector delta; delta.y = 0;
    00509       if (layout() == LeftToRightText)
    00510       {
    00511         FT_Get_Kerning( font()->mFT_Face, previous, glyph->glyphIndex(), FT_KERNING_DEFAULT, &delta );
    00512         pen.x() += delta.x / 64.0f;
    00513       }
    00514       else
    00515       if (layout() == RightToLeftText)
    00516       {
    00517         FT_Get_Kerning( font()->mFT_Face, glyph->glyphIndex(), previous, FT_KERNING_DEFAULT, &delta );
    00518         pen.x() -= delta.x / 64.0f;
    00519       }
    00520       pen.y() += delta.y / 64.0f;
    00521     }
    00522     previous = glyph->glyphIndex();
    00523
    00524     if ( glyph->textureHandle() )
    00525     {
    00526       int left = layout() == RightToLeftText ? -glyph->left() : +glyph->left();
    00527
    00528       vect[0].x() = pen.x() + glyph->width()*0 + left -1;
    00529       vect[0].y() = pen.y() + glyph->height()*0 + glyph->top() - glyph->height() -1;
    00530
    00531       vect[1].x() = pen.x() + glyph->width()*1 + left +1;
    00532       vect[1].y() = pen.y() + glyph->height()*0 + glyph->top() - glyph->height() -1;
    00533
    00534       vect[2].x() = pen.x() + glyph->width()*1 + left +1;
    00535       vect[2].y() = pen.y() + glyph->height()*1 + glyph->top() - glyph->height() +1;
    00536
    00537       vect[3].x() = pen.x() + glyph->width()*0 + left -1;
    00538       vect[3].y() = pen.y() + glyph->height()*1 + glyph->top() - glyph->height() +1;
    00539
    00540       if (layout() == RightToLeftText)
    00541       {
    00542         vect[0].x() -= glyph->width()-1 +2;
    00543         vect[1].x() -= glyph->width()-1 +2;
    00544         vect[2].x() -= glyph->width()-1 +2;
    00545         vect[3].x() -= glyph->width()-1 +2;
    00546       }
    00547
    00548       vect[0].y() -= mFont->mHeight;
    00549       vect[1].y() -= mFont->mHeight;
    00550       vect[2].y() -= mFont->mHeight;
    00551       vect[3].y() -= mFont->mHeight;
    00552     }
    00553
    00554     aabb.addPoint( (vec3)vect[0] );
    00555     aabb.addPoint( (vec3)vect[1] );
    00556     aabb.addPoint( (vec3)vect[2] );
    00557     aabb.addPoint( (vec3)vect[3] );
    00558
    00559     if (layout() == LeftToRightText)
    00560       pen += glyph->advance();
    00561     else
    00562     if (layout() == RightToLeftText)
    00563       pen -= glyph->advance();
    00564   }
    00565
    00566   return aabb;
    00567 }
    00568 //-----------------------------------------------------------------------------
    00569 void CoreText::renderBackground(const Actor*, const Camera*) const
    00570 {
    00571   // mic fixme:
    00572   // rendering of border and background follows different rules in 3D compared from 2D: lines and polygons follow different rasterization rules!
    00573
    00574   // Background color
    00575   glColor4fv(mBackgroundColor.ptr());
    00576
    00577   // Constant normal
    00578   glNormal3fv( fvec3(0,0,1).ptr() );
    00579
    00580   vec3 a,b,c,d;
    00581   AABB bbox = boundingRect(); // mic fixme: this guy recomputes the bounds again instead of using the precomputed one!!
    00582   a = bbox.minCorner();
    00583   b.x() = (float)bbox.maxCorner().x();
    00584   b.y() = (float)bbox.minCorner().y();
    00585   c = bbox.maxCorner();
    00586   d.x() = (float)bbox.minCorner().x();
    00587   d.y() = (float)bbox.maxCorner().y();
    00588   // set z to 0
    00589   a.z() = b.z() = c.z() = d.z() = 0;
    00590
    00591   fvec3 vect[] = { (fvec3)a, (fvec3)b, (fvec3)c, (fvec3)d };
    00592   glEnableClientState( GL_VERTEX_ARRAY );
    00593   glVertexPointer(3, GL_FLOAT, 0, vect);
    00594
    00595   glDrawArrays(GL_QUADS,0,4);
    00596
    00597   glDisableClientState( GL_VERTEX_ARRAY );
    00598 }
    00599 //-----------------------------------------------------------------------------
    00600 void CoreText::renderBorder(const Actor*, const Camera*) const
    00601 {
    00602   // mic fixme:
    00603   // rendering of border and background follows different rules in 3D compared from 2D: lines and polygons follow different rasterization rules!
    00604
    00605   // Border color
    00606   glColor4fv(mBorderColor.ptr());
    00607
    00608   // Constant normal
    00609   glNormal3fv( fvec3(0,0,1).ptr() );
    00610
    00611   vec3 a,b,c,d;
    00612   AABB bbox = boundingRect(); // mic fixme: this guy recomputes the bounds again instead of using the precomputed one!!
    00613   a = bbox.minCorner();
    00614   b.x() = (float)bbox.maxCorner().x();
    00615   b.y() = (float)bbox.minCorner().y();
    00616   c = bbox.maxCorner();
    00617   d.x() = (float)bbox.minCorner().x();
    00618   d.y() = (float)bbox.maxCorner().y();
    00619   // set z to 0
    00620   a.z() = b.z() = c.z() = d.z() = 0;
    00621
    00622   fvec3 vect[] = { (fvec3)a, (fvec3)b, (fvec3)c, (fvec3)d };
    00623   glEnableClientState( GL_VERTEX_ARRAY );
    00624   glVertexPointer(3, GL_FLOAT, 0, vect);
    00625
    00626   glDrawArrays(GL_LINE_LOOP,0,4);
    00627
    00628   glDisableClientState( GL_VERTEX_ARRAY );
    00629 }
    00630 //-----------------------------------------------------------------------------
    00631 AABB CoreText::boundingRect() const
    00632 {
    00633   return boundingRect(text());
    00634 }
    00635 //-----------------------------------------------------------------------------
    00636 AABB CoreText::boundingRect(const String& text) const
    00637 {
    00638   AABB bbox = rawboundingRect( text );
    00639   bbox.setMaxCorner( bbox.maxCorner() + vec3(2.0f*margin(), 2.0f*margin(), 0) );
    00640
    00641   // normalize coordinate orgin to the bottom/left corner
    00642   vec3 min = bbox.minCorner() - bbox.minCorner();
    00643   vec3 max = bbox.maxCorner() - bbox.minCorner();
    00644
    00645   // text pivot
    00646
    00647   if (textOrigin() & AlignHCenter)
    00648   {
    00649     VL_CHECK( !(textOrigin() & AlignRight) )
    00650     VL_CHECK( !(textOrigin() & AlignLeft) )
    00651     min.x() -= int(bbox.width() / 2.0);
    00652     max.x() -= int(bbox.width() / 2.0);
    00653   }
    00654
    00655   if (textOrigin() & AlignRight)
    00656   {
    00657     VL_CHECK( !(textOrigin() & AlignHCenter) )
    00658     VL_CHECK( !(textOrigin() & AlignLeft) )
    00659     min.x() -= (int)bbox.width();
    00660     max.x() -= (int)bbox.width();
    00661   }
    00662
    00663   if (textOrigin() & AlignTop)
    00664   {
    00665     VL_CHECK( !(textOrigin() & AlignBottom) )
    00666     VL_CHECK( !(textOrigin() & AlignVCenter) )
    00667     min.y() -= (int)bbox.height();
    00668     max.y() -= (int)bbox.height();
    00669   }
    00670
    00671   if (textOrigin() & AlignVCenter)
    00672   {
    00673     VL_CHECK( !(textOrigin() & AlignTop) )
    00674     VL_CHECK( !(textOrigin() & AlignBottom) )
    00675     min.y() -= int(bbox.height() / 2.0);
    00676     max.y() -= int(bbox.height() / 2.0);
    00677   }
    00678
    00679   AABB aabb;
    00680   aabb.setMinCorner(min);
    00681   aabb.setMaxCorner(max);
    00682   return aabb;
    00683 }
    00684 //-----------------------------------------------------------------------------

Visualization Library v2011.09.1162 Reference Documentation
Copyright 2005-2011 Michele Bosi. All rights reserved.
Updated on Thu Jan 26 2012 00:43:36.
Permission is granted to use this page to write and publish articles regarding Visualization Library.