AaronCameron.net
Because you all make me very, very tired.
Not a Member? - Login or Create an Account
Wednesday the 23rd of May 2012 @ 10:28am
Front Page Journal Projects Your Profile About
[]

LibN2L-4 Library Code Reference

Classes
Compounds
Files
Members
Method Index
Full Reference

cGuiTextStyle.cpp

Go to the documentation of this file.
00001 /************************************************************************
00002 Nova-2 Library (libN2L, or simply n2l) Game development C++ Library
00003 Copyright (C) 2002  Aaron Cameron
00004 
00005 This library is free software; you can redistribute it and/or
00006 modify it under the terms of the GNU Lesser General Public
00007 License as published by the Free Software Foundation; either
00008 version 2.1 of the License, or (at your option) any later version.
00009 
00010 This library is distributed in the hope that it will be useful,
00011 but WITHOUT ANY WARRANTY; without even the implied warranty of
00012 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00013 Lesser General Public License for more details.
00014 
00015 You should have received a copy of the GNU Lesser General Public
00016 License along with this library; if not, write to the Free Software
00017 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
00018 
00019 A copy of the GNU Lesser General Public License has been provided with
00020 this library in the file 'COPYING'.
00021 
00022 Contact information for the author of this library has been provided
00023 with this library in the file 'AUTHOR'.
00024 ************************************************************************/
00025 #include "gui/cGuiTextStyle.h"
00026 
00027 #include "n2l/dynVars.h"
00028 #include "n2l/resourceManagement.h"
00029 
00030 #include "gui/cGuiElement.h"
00031 
00032 /******************************************************************************/
00033 namespace n2l
00034 {
00035 
00036     /**************************************************************************/
00037     cGuiTextStyle::cGuiTextStyle() :
00038         mColourInherit(true),
00039         mColour(1.0f,1.0f,1.0f,1.0f),
00040         mFontHeight(0.0f),
00041         mFont(0),
00042         mAlign( Align_Left ),
00043         mVAlign( VAlign_Top ),
00044         mClipping( Clipping_Letter )
00045     {
00046     }
00047 
00048     /**************************************************************************/
00049     cGuiTextStyle::cGuiTextStyle( const cVfsNodeInterface & iNode ) :
00050         mColourInherit(true),
00051         mColour(1.0f,1.0f,1.0f,1.0f),
00052         mFontHeight(0.0f),
00053         mFont(0),
00054         mAlign( Align_Left ),
00055         mVAlign( VAlign_Top ),
00056         mClipping( Clipping_Letter )
00057     {
00058         load( iNode );
00059     }
00060 
00061     /**************************************************************************/
00062     cGuiTextStyle::cGuiTextStyle( const cDynVar &iDef ) :
00063         mColourInherit(true),
00064         mColour(1.0f,1.0f,1.0f,1.0f),
00065         mFontHeight(0.0f),
00066         mFont(0),
00067         mAlign( Align_Left ),
00068         mVAlign( VAlign_Top ),
00069         mClipping( Clipping_Letter )
00070     {
00071         load( iDef );
00072     }
00073 
00074     /**************************************************************************/
00075     cGuiTextStyle::~cGuiTextStyle()
00076     {
00077     }
00078 
00079     /**************************************************************************/
00080     void cGuiTextStyle::load( const cVfsNodeInterface & iNode )
00081     {
00082         cDynVar def;
00083         cGuiElement::validateAndDecode( def, iNode, "n2l::cGuiTextStyle" );
00084         load( def );
00085     }
00086 
00087 
00088     /**************************************************************************/
00089     void cGuiTextStyle::load( const cDynVar &iDef )
00090     {
00091         if (iDef.keyExists("font"))
00092             font( cResourceManager::get<cTextureFont>(iDef["font"]) );
00093 
00094         if (iDef.keyExists("fontHeight"))
00095             fontHeight( iDef["fontHeight"] );
00096 
00097         if (iDef.keyExists("colour"))
00098             colour( iDef["colour"] );
00099 
00100         if (iDef.keyExists("colourInherit"))
00101             colourInherit( iDef["colourInherit"] );
00102 
00103         if (iDef.keyExists("align"))
00104             align( tAlign(tSint(iDef["align"])) );
00105 
00106         if (iDef.keyExists("vAlign"))
00107             vAlign( tVAlign(tSint(iDef["vAlign"])) );
00108 
00109         if (iDef.keyExists("clipping"))
00110             clipping( tClipping(tSint(iDef["clipping"])) );
00111         
00112     }
00113 
00114     /**************************************************************************/
00115     void cGuiTextStyle::font( const cAutoPtr<const cFontInterface> & i_iFont )
00116     {
00117         mFont = i_iFont;
00118     }
00119 
00120     /**************************************************************************/
00121     const cAutoPtr<const cFontInterface> & cGuiTextStyle::font() const
00122     {
00123         return mFont;
00124     }
00125 
00126     /**************************************************************************/
00127     void cGuiTextStyle::fontHeight( const tFloat & iFontHeight )
00128     {
00129         mFontHeight = iFontHeight;
00130     }
00131 
00132     /**************************************************************************/
00133     const tFloat & cGuiTextStyle::fontHeight() const
00134     {
00135         return mFontHeight;
00136     }
00137 
00138     /**************************************************************************/
00139     void cGuiTextStyle::colour( const tGuiColour & iColour )
00140     {
00141         mColourInherit = false;
00142         mColour = iColour;
00143     }
00144 
00145 
00146     /**************************************************************************/
00147     void cGuiTextStyle::colourInherit( const tBool iValue )
00148     {
00149         mColourInherit = iValue;
00150     }
00151 
00152     /**************************************************************************/
00153     void cGuiTextStyle::align( const tAlign iAlign )
00154     {
00155         alignInBounds( iAlign );
00156         mAlign = iAlign;
00157     }
00158 
00159     /**************************************************************************/
00160     void cGuiTextStyle::vAlign( const tVAlign iVAlign )
00161     {
00162         vAlignInBounds( iVAlign );
00163         mVAlign = iVAlign;
00164     }
00165 
00166     /**************************************************************************/
00167     void cGuiTextStyle::clipping( const tClipping iClipping )
00168     {
00169         clippingInBounds( iClipping );
00170         mClipping = iClipping;
00171     }
00172 
00173 
00174     /**************************************************************************/
00175     const tString::size_type cGuiTextStyle::draw( const tGuiPos &iPos,
00176         const tGuiPos &iSize, const tString &iText,
00177         const tString::size_type iSPos,
00178         const tString::size_type iMaxSize ) const
00179     {
00180         if (!mFont.isSet()) return 0;
00181         if (iText.empty()) return 0;
00182 
00183         tGuiPos finalPos;
00184         tFloat glyphHeight;
00185         tString::size_type sPos,ePos, charactersDrawn;
00186         
00187         commonDraw( iPos, iSize, iText, iSPos, iMaxSize,
00188             charactersDrawn, finalPos, glyphHeight, sPos,ePos );
00189         
00190         if (!mColourInherit) mColour.glColour4();
00191 
00192         glPushAttrib( GL_ALL_ATTRIB_BITS );
00193         glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA );
00194         glEnable( GL_BLEND );
00195 //      glDisable( GL_DEPTH_TEST );
00196 
00197         glEnable( GL_TEXTURE_2D );
00198 
00199         glCullFace( GL_BACK );
00200         glEnable( GL_CULL_FACE );
00201 
00202         mFont->draw( finalPos, iText, glyphHeight, iSPos, ePos-sPos );
00203         glPopAttrib();
00204 
00205         return ePos-sPos;
00206     }
00207 
00208     /**************************************************************************/
00209     const tString::size_type cGuiTextStyle::wouldDraw(
00210         const tGuiPos & iSize, const tString & iText,
00211         const tString::size_type iSPos,
00212         const tString::size_type iMaxSize ) const
00213     {
00214         if (!mFont.isSet()) return 0;
00215 
00216         tGuiPos finalPos;
00217         tFloat glyphHeight;
00218         tString::size_type sPos,ePos, charactersDrawn;
00219         
00220         const tGuiPos AnyPos(0,0);
00221         commonDraw( AnyPos, iSize, iText, iSPos, iMaxSize,
00222                     charactersDrawn, finalPos, glyphHeight, sPos,ePos );
00223 
00224         return ePos-sPos;
00225     }
00226 
00227     /**************************************************************************/
00228     const tFloat cGuiTextStyle::calcGlyphHeight( const tGuiPos &iSize ) const
00229     {
00230         return (mFontHeight>0?mFontHeight:iSize.y());
00231     }
00232 
00233     /**************************************************************************/
00234     void cGuiTextStyle::prop( const tString &iName, const cDynVar &iVal )
00235     {
00236         if (iName == "colour")
00237             colour( iVal );
00238 
00239         else if (iName == "colourInherit")
00240             colourInherit( iVal );
00241 
00242         else if (iName == "fontHeight")
00243             fontHeight( iVal );
00244     }
00245 
00246     /**************************************************************************/
00247     const cDynVar cGuiTextStyle::prop( const tString &iName ) const
00248     {
00249         cDynVar oVal = cDynVar::Null;
00250 
00251         if (iName == "colour") {
00252             oVal = cDynVar::Array;
00253             oVal.insert(mColour.r());
00254             oVal.insert(mColour.g());
00255             oVal.insert(mColour.b());
00256             oVal.insert(mColour.a());
00257             
00258         }
00259 
00260         return oVal;
00261     }
00262 
00263 
00264     /**************************************************************************/
00265     void cGuiTextStyle::commonDraw( const tGuiPos &iPos, const tGuiPos &iSize,
00266         const tString &iText, const tString::size_type iSPos,
00267         const tString::size_type iMaxSize,
00268         tString::size_type &oCharactersDrawn, tGuiPos &oFinalPos,
00269         tFloat &oGlyphHeight, tString::size_type &oSPos,
00270         tString::size_type &oCEndPos ) const
00271     {
00272         tString::size_type strLength( iText.size() );
00273         if (iMaxSize>0)
00274             strLength = n2l_min( strLength, iSPos+iMaxSize );
00275 
00276         const tFloat GlyphHeight = (mFontHeight>0?mFontHeight:iSize.y());
00277         const tFloat GlyphSeperation = mFont->glyphSeperation(GlyphHeight);
00278 
00279         if (!mFont || !strLength || iSPos>=strLength) {
00280             oSPos = iSPos;
00281             oGlyphHeight = GlyphHeight;
00282             oCEndPos = iSPos;
00283             return;
00284         }
00285         
00286         // Calculate how many characters we're going to draw.
00287         tString::size_type cEndPos(iSPos);
00288 
00289         tFloat strWidth( 0.0f );
00290         tFloat whiteSpaceStrWidth( 0.0f );
00291 
00292         if (mClipping != Clipping_NoClip) {
00293             tString::size_type cLastWhitespace(iSPos);
00294             tBool clip = false;
00295             while (!clip && cEndPos<strLength) {
00296                 const tFloat ExtraSpace(cEndPos==iSPos?0:GlyphSeperation);
00297                 const tFloat GlyphWidth( ExtraSpace +
00298                     mFont->glyphWidth(iText[cEndPos],GlyphHeight) );
00299 
00300                 if (strWidth+GlyphWidth>iSize.x()) {
00301                     clip = true;
00302                     continue;
00303                 }
00304                 strWidth += GlyphWidth;
00305                 if (iText[cEndPos]==' ' || iText[cEndPos]=='\t' ||
00306                     iText[cEndPos]=='\n')
00307                 {
00308                     cLastWhitespace = cEndPos;
00309                     whiteSpaceStrWidth = strWidth;
00310                 }
00311                 // Up the position.
00312                 
00313                 ++cEndPos;
00314             }
00315             if (cEndPos!=strLength) {
00316                 // What to do with the values we have here.
00317                 switch (mClipping) {
00318                     case Clipping_Letter:
00319                         // We'll use the last character to fit as a clip point
00320                         // so we have nothing more to do
00321                         break;
00322 
00323                     case Clipping_Word:
00324                         if (cLastWhitespace==iSPos) {
00325                             oSPos = iSPos;
00326                             oCEndPos = iSPos;
00327                             oGlyphHeight = GlyphHeight;
00328                             return;
00329                         }
00330                         else {
00331                             cEndPos = cLastWhitespace;
00332                             strWidth = whiteSpaceStrWidth;
00333                         }
00334                         break;
00335 
00336                     case Clipping_HardWord:
00337                         if (cLastWhitespace!=iSPos) {
00338                             cEndPos = cLastWhitespace;
00339                             strWidth = whiteSpaceStrWidth;
00340                         }
00341                         // Else we leave it at the last character
00342                         // splitting pos.
00343                         break;
00344 
00345                     default:
00346                         // We shouldn't be able to get here.
00347                         //Added for completeness
00348                         cEndPos = strLength;
00349                         break;
00350                 } // switch
00351             }
00352         } else { // if (mClipping != Clipping_NoClip)
00353             cEndPos = strLength;
00354             strWidth = mFont->calcSize( iText, GlyphHeight, iSPos,
00355                 cEndPos-iSPos ).x();
00356         }
00357 
00358         // Get the final rendering positions
00359         tGuiPos finalPos(iPos);
00360         switch (mAlign)
00361         {
00362             case Align_Right:
00363                 finalPos.x( (iPos.x() + iSize.x()) - strWidth );
00364                 break;
00365             case Align_Center:
00366                 finalPos.x( (iPos.x() + iSize.x()/2.0f) - strWidth/2.0f );
00367                 break;
00368             default:
00369                 break;
00370         } // switch
00371 
00372         switch (mVAlign)
00373         {
00374             case VAlign_Middle:
00375                 finalPos.y( (iPos.y() + iSize.y()/2.0f) - GlyphHeight/2.0f );
00376                 break;
00377             case VAlign_Bottom:
00378                 finalPos.y( (iPos.y() + iSize.y()) - GlyphHeight );
00379                 break;
00380             default:
00381                 break;
00382         } // switch
00383 
00384         // Set the outgoing values.
00385         oFinalPos = finalPos;
00386         oGlyphHeight = GlyphHeight;
00387         oSPos = iSPos;
00388         oCEndPos = cEndPos;
00389     }
00390 
00391     /**************************************************************************/
00392     void cGuiTextStyle::alignInBounds( const tAlign iAlign ) const
00393     {
00394         if (iAlign<0 || iAlign>=Align_NumAligns)
00395             throw cOutOfBoundsException( "cGuiTextStyle::alignInBounds",
00396                 "Alignment value illegal" );
00397     }
00398 
00399         
00400     /**************************************************************************/
00401     void cGuiTextStyle::vAlignInBounds( const tVAlign iVAlign ) const
00402     {
00403         if (iVAlign<0 || iVAlign>=VAlign_NumVAligns)
00404             throw cOutOfBoundsException( "cGuiTextStyle::vAlignInBounds",
00405                 "Vertical Alignment value illegal" );
00406     }
00407 
00408 
00409     /**************************************************************************/
00410     void cGuiTextStyle::clippingInBounds( const tClipping iClipping ) const
00411     {
00412         if (iClipping<0 || iClipping>=Clipping_NumClippings)
00413             throw cOutOfBoundsException( "cGuiTextStyle::clippingInBounds",
00414                 "Clipping value illegal" );
00415     }
00416 
00417 
00418 } // namespace n2l
©2012 Aaron Cameron