Main Page | Namespace List | Class Hierarchy | Alphabetical List | Data Structures | File List | Namespace Members | Data Fields | Globals

xrenderstring.cpp

Go to the documentation of this file.
00001 #include "SdlArs.h"
00002 
00003 namespace Ars
00004 {
00005 
00006 XRenderedString::XRenderedString( CFontEngine* pFontEngine , EVAlign eVertAlign , EHAlign eHorzAlign )
00007 : m_pFontEngine(pFontEngine), m_eVertAlign(eVertAlign), m_eHorzAlign(eHorzAlign)
00008 , m_bCachedMetricsValid(false), m_MaskChar(' '), m_MaxFontHeight(-1)
00009 {
00010 }
00011 
00012 void XRenderedString::_TextOut( SDL_Surface* pSurface , CRect &drawRect , CPoint &OriginPoint , const std::string &str , const CRGBColor &FontColor , CPainter::EPaintMode eMode ) 
00013 {
00014         m_bCachedMetricsValid = false;
00015         CPoint OriginOffset , linebox;
00016         std::vector<CRect> CharacterRects;
00017         GetMetrics( str , &linebox , &OriginOffset , &CharacterRects );
00018 
00019         textSize.SetX( max( textSize.XPos() , linebox.XPos() ) );
00020         switch( m_eVertAlign  )
00021         {
00022                 case VALIGN_TOP :       OriginPoint = CPoint( OriginPoint.XPos() , drawRect.Top() );    break;
00023                 case VALIGN_BOTTOM :    OriginPoint = CPoint( OriginPoint.XPos() , drawRect.Bottom() ); break;
00024         }
00025 
00026         switch( m_eHorzAlign )
00027         {
00028                 case HALIGN_LEFT : OriginPoint = CPoint( drawRect.Left() , OriginPoint.YPos() );        break;
00029                 case HALIGN_CENTER : OriginPoint = CPoint( drawRect.Left() + drawRect.Width() / 2 , OriginPoint.YPos() );       break;
00030                 case HALIGN_RIGHT : OriginPoint = CPoint( drawRect.Right() , OriginPoint.YPos() );      break;
00031         }
00032 
00033         for( unsigned int i = 0 ; i < str.size() ; ++i )
00034         {
00035                 FT_BitmapGlyphRec *pGlyph;
00036                 if( m_MaskChar == ' ' )
00037                         pGlyph = m_pFontEngine->RenderGlyph( str[i] );
00038                 else
00039                         pGlyph = m_pFontEngine->RenderGlyph( m_MaskChar );
00040 
00041                 CPainter Painter( pSurface , eMode );
00042 
00043                 for (int y = 0; y < pGlyph->bitmap.rows; ++y )
00044                 {
00045                         for (int x = 0; x < pGlyph->bitmap.width; ++x )
00046                         {
00047                                 unsigned char *PixelOffset = pGlyph->bitmap.buffer + y * pGlyph->bitmap.width + x;
00048                                 if( *PixelOffset != 0x00 )
00049                                 {
00050                                         CRGBColor PixelColor(FontColor.red, FontColor.green, FontColor.blue, *PixelOffset);
00051 
00052                                         CPoint PixelPoint( CPoint( x + pGlyph->left, y ) + OriginPoint + OriginOffset + CharacterRects[i].TopLeft() );
00053                                         
00054                                         if( drawRect.HitTest( PixelPoint ) == RELPOS_INSIDE)
00055                                                 Painter.DrawPoint(PixelPoint, PixelColor);
00056                                 }
00057                         }
00058                 }
00059         }
00060 }
00061 
00062 void XRenderedString::TextOut( SDL_Surface* pSurface, const CRect &BoundingRect, const std::string &str , const CRGBColor &FontColor , CPainter::EPaintMode eMode )
00063 {
00064         m_bCachedMetricsValid = false;
00065         textSize = CPoint( 0 , 0 );
00066 
00067         CPoint  OriginPoint = BoundingRect.TopLeft();
00068         CRect   drawRect = BoundingRect;
00069         
00070         int     nrlines = 1;
00071         string  s = str;
00072         string::size_type       n0 = 0 , n1 = s.find( '\n' , n0 );
00073         while( n1 != string::npos )
00074         {
00075                 n0 = n1 + 1;
00076                 n1 = s.find( '\n' , n0 );
00077                 nrlines += 1;
00078         }
00079         if( m_eVertAlign == VALIGN_CENTER )
00080                 OriginPoint = CPoint( OriginPoint.XPos() , OriginPoint.YPos() + (drawRect.Height() - (GetMaxFontHeight() * (nrlines - 1))) / 2 );
00081 
00082         textSize.SetY( GetMaxFontHeight() * nrlines );
00083         n0 = 0 , n1 = s.find( '\n' , n0 );
00084         while( n1 != string::npos )
00085         {
00086                 _TextOut( pSurface , drawRect , OriginPoint , s.substr( n0 , n1 - n0 ) , FontColor , eMode );
00087 
00088                 n0 = n1 + 1;
00089                 n1 = s.find( '\n' , n0 );
00090                 if( m_eVertAlign == VALIGN_CENTER )
00091                         OriginPoint = CPoint( OriginPoint.XPos() , OriginPoint.YPos() + GetMaxFontHeight() );
00092                 else
00093                         drawRect.SetTop( drawRect.Top() + GetMaxFontHeight() );
00094         }
00095 
00096         _TextOut( pSurface , drawRect , OriginPoint , s.substr( n0 ) , FontColor , eMode );
00097 }
00098 
00099 CPoint XRenderedString::GetTextSize( const string &str )
00100 {
00101         CPoint  ans( 0 , 0 );
00102 
00103         int     nrlines = 1;
00104         string  s = str;
00105         string::size_type       n0 = 0 , n1 = s.find( '\n' , n0 );
00106         while( n1 != string::npos )
00107         {
00108                 CPoint  lineBox( 0 , 0 );
00109 
00110                 m_bCachedMetricsValid = false;
00111                 GetMetrics( s.substr( n0 , n1 - n0 ) , &lineBox , 0 , 0 );
00112                 ans.SetX( max( ans.XPos() , lineBox.XPos() ) );
00113                 n0 = n1 + 1;
00114                 n1 = s.find( '\n' , n0 );
00115                 nrlines += 1;
00116         }
00117         CPoint  lineBox( 0 , 0 );
00118         m_bCachedMetricsValid = false;
00119         GetMetrics( s.substr( n0 ) , &lineBox , 0 , 0 );
00120         ans.SetX( max( ans.XPos() , lineBox.XPos() ) );
00121 
00122         ans.SetY( GetMaxFontHeight() * nrlines );
00123 
00124         return ans;
00125 }
00126 
00127 unsigned int XRenderedString::GetMaxFontHeight()
00128 {
00129         if (m_MaxFontHeight < 0)
00130         {
00131                 int maxHeight=0;
00132                 FT_Glyph_Metrics* pMetrics;
00133                 for(int i=0; i < 256; i++)
00134                 {
00135                         pMetrics = m_pFontEngine->GetMetrics((char)i);
00136                         if ((pMetrics->height >> 6) > maxHeight)
00137                         {
00138                                 maxHeight = (pMetrics->height >> 6);
00139                         }
00140                         //maxHeight = std::max(maxHeight, pMetrics->height);
00141                 }
00142                 m_MaxFontHeight = maxHeight + 2;
00143         }
00144         return m_MaxFontHeight;
00145 }
00146 
00147 void XRenderedString::GetMetrics( const std::string &str , CPoint* pBoundedDimensions, CPoint* pOriginOffset, std::vector<CRect>* pCharacterRects) const
00148 {
00149         if (! m_bCachedMetricsValid )
00150         {
00151                 m_CachedCharacterRects.clear();
00152 
00153                 int iMinY = 0;
00154                 int iMaxY = 0;
00155                 int iLength = 0;
00156                 for (unsigned int i = 0; i < str.size(); ++i)
00157                 {
00158                         FT_Glyph_Metrics* pMetrics;
00159                         if (m_MaskChar == ' ')
00160                         {
00161                                 pMetrics = m_pFontEngine->GetMetrics(str[i]);
00162                         }
00163                         else
00164                         {
00165                                 pMetrics = m_pFontEngine->GetMetrics(m_MaskChar);
00166                         }
00167                                 
00168                         //FT_Glyph_Metrics* pMetrics = m_pFontEngine->GetMetrics(str[i]);
00169                         if ((pMetrics->horiBearingY - pMetrics->height) < iMinY)
00170                         {
00171                                 iMinY = pMetrics->horiBearingY - pMetrics->height;
00172                         }
00173                         if (pMetrics->horiBearingY > iMaxY)
00174                         {
00175                                 iMaxY = pMetrics->horiBearingY;
00176                         }
00177                         iLength += (pMetrics->horiAdvance);
00178                         // The top and bottom values of the rect are not actually in rect coordinates at this point, since iMaxY and iMinY are not yet know
00179                         m_CachedCharacterRects.push_back(
00180                                 CRect((iLength - pMetrics->horiAdvance) >> 6, pMetrics->horiBearingY >> 6, iLength >> 6, pMetrics->height >> 6));
00181                 }
00182 
00183                 iMinY = iMinY >> 6;
00184                 iMaxY = iMaxY >> 6;
00185                 iLength = iLength >> 6;
00186 
00187                 // now fix the top and bottom values of the rects
00188                 for(std::vector<CRect>::iterator iter = m_CachedCharacterRects.begin(); iter != m_CachedCharacterRects.end(); ++iter)
00189                 {
00190                         iter->SetTop(iMaxY - iter->Top());
00191                         iter->SetBottom(iter->Top() + iter->Bottom());
00192                 }
00193 
00194                 // Tack an empty rect on the end
00195                 m_CachedCharacterRects.push_back(CRect(iLength, iMaxY, iLength, iMinY));
00196 
00197                 m_CachedBoundedDimensions = CPoint(iLength, iMaxY - iMinY);
00198 
00199                 switch (m_eHorzAlign)
00200                 {
00201                 case HALIGN_CENTER:
00202                         m_OriginOffset.SetX(-iLength / 2);
00203                         break;
00204                 case HALIGN_RIGHT:
00205                         m_OriginOffset.SetX(-iLength);
00206                         break;
00207                 case HALIGN_LEFT:
00208                 default:
00209                         m_OriginOffset.SetX(0);
00210                         break;
00211                 }
00212 
00213                 switch (m_eVertAlign)
00214                 {
00215                 case VALIGN_TOP:
00216                         m_OriginOffset.SetY(0);
00217                         break;
00218                 case VALIGN_BOTTOM:
00219                         m_OriginOffset.SetY(iMinY - iMaxY);
00220                         break;
00221                 case VALIGN_CENTER:
00222                         m_OriginOffset.SetY((iMinY - iMaxY) / 2);
00223                         break;
00224                 case VALIGN_NORMAL:
00225                 default:
00226                         m_OriginOffset.SetY(-iMaxY);
00227                         break;
00228                 }
00229 
00230                 m_bCachedMetricsValid = true;
00231         }
00232 
00233         if (pBoundedDimensions)
00234         {
00235                 *pBoundedDimensions = m_CachedBoundedDimensions;
00236         }
00237 
00238         if (pOriginOffset)
00239         {
00240                 *pOriginOffset = m_OriginOffset;
00241         }
00242 
00243         if (pCharacterRects)
00244         {
00245                 *pCharacterRects = m_CachedCharacterRects;
00246         }
00247 }
00248 
00249 }

Generated on Fri Dec 5 04:06:01 2003 for Borqueror by doxygen 1.3.3