wg_renderedstring.cpp

00001 // wg_renderedstring.cpp
00002 //
00003 // CRenderedString implementation
00004 //
00005 //
00006 // Copyright (c) 2002-2004 Rob Wiskow
00007 // rob-dev@boxedchaos.com
00008 //
00009 // This library is free software; you can redistribute it and/or
00010 // modify it under the terms of the GNU Lesser General Public
00011 // License as published by the Free Software Foundation; either
00012 // version 2.1 of the License, or (at your option) any later version.
00013 //
00014 // This library is distributed in the hope that it will be useful,
00015 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00016 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
00017 // Lesser General Public License for more details.
00018 //
00019 // You should have received a copy of the GNU Lesser General Public
00020 // License along with this library; if not, write to the Free Software
00021 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
00022 //
00023 
00024 
00025 #include "wgui_include_config.h"
00026 #include "wg_renderedstring.h"
00027 #include "wg_painter.h"
00028 #include "wg_error.h"
00029 #include <algorithm>
00030 
00031 namespace wGui
00032 {
00033 
00034 CRenderedString::CRenderedString(CFontEngine* pFontEngine, const std::wstring& sString, EVAlign eVertAlign, EHAlign eHorzAlign) :
00035      m_pFontEngine(pFontEngine),
00036      m_sString(sString),
00037      m_eVertAlign(eVertAlign),
00038      m_eHorzAlign(eHorzAlign),
00039      m_bCachedMetricsValid(false),
00040      m_MaskChar(L' '),
00041      m_MaxFontHeight(-1),
00042      m_MaxFontWidth(-1)
00043 {
00044      if (! m_pFontEngine)
00045      {
00046           throw(Wg_Ex_App(L"CRenderedString::CRenderedString : Bad pFontEngine pointer! (This is usually the result of the wgui.conf file missing or misconfigured.  See the Global Config section of the docs.)"));
00047      }
00048 }
00049 
00050 
00051 void CRenderedString::Draw(SDL_Surface* pSurface, const CRect& BoundingRect, const CPoint& OriginPoint, const CRGBColor& FontColor) const
00052 {
00053      CPoint OriginOffset;
00054      std::vector<CRect> CharacterRects;
00055      GetMetrics(0, &OriginOffset, &CharacterRects);
00056      for (unsigned int i = 0; i < m_sString.size(); ++i)
00057      {
00058           FT_BitmapGlyphRec* pGlyph;
00059           if (m_MaskChar == L' ')
00060           {
00061                pGlyph = m_pFontEngine->RenderGlyph(m_sString[i]);
00062           }
00063           else
00064           {
00065                pGlyph = m_pFontEngine->RenderGlyph(m_MaskChar);
00066           }
00067           CPainter Painter(pSurface, CPainter::PAINT_NORMAL);
00068           for (int y = 0; y < pGlyph->bitmap.rows; ++y)
00069           {
00070                for (int x = 0; x < pGlyph->bitmap.width; ++x)
00071                {
00072                     unsigned char* PixelOffset = pGlyph->bitmap.buffer + y * pGlyph->bitmap.width + x;
00073                     if (*PixelOffset != 0x00)
00074                     {
00075                          CRGBColor PixelColor(FontColor.red, FontColor.green, FontColor.blue, *PixelOffset);
00076                          CPoint PixelPoint(CPoint(x + pGlyph->left, y) + OriginPoint + OriginOffset + CharacterRects.at(i).TopLeft());
00077                          if (BoundingRect.HitTest(PixelPoint) == CRect::RELPOS_INSIDE)
00078                          {
00079                               Painter.DrawPoint(PixelPoint, PixelColor);
00080                          }
00081                     }
00082                }
00083           }
00084      }
00085 }
00086 
00087 
00088 unsigned int CRenderedString::GetMaxFontHeight(void)
00089 {
00090      if (m_MaxFontHeight < 0)
00091      {
00092           int maxHeight = 0;
00093           FT_Glyph_Metrics* pMetrics;
00094           for(int i = 0; i < 256; i++)
00095           {
00096                pMetrics = m_pFontEngine->GetMetrics(static_cast<char>(i));
00097                if ((pMetrics->height >> 6) > maxHeight)
00098                {
00099                     maxHeight = (pMetrics->height >> 6);
00100                }
00101           }
00102           m_MaxFontHeight = maxHeight;
00103      }
00104      return m_MaxFontHeight;
00105 }
00106 
00107 
00108 unsigned int CRenderedString::GetMaxFontWidth(void)
00109 {
00110      if (m_MaxFontWidth < 0)
00111      {
00112           int maxWidth = 0;
00113           FT_Glyph_Metrics* pMetrics;
00114           for(int i = 0; i < 256; i++)
00115           {
00116                pMetrics = m_pFontEngine->GetMetrics(static_cast<char>(i));
00117                if ((pMetrics->width >> 6) > maxWidth)
00118                {
00119                     maxWidth = (pMetrics->width >> 6);
00120                }
00121           }
00122           m_MaxFontWidth = maxWidth;
00123      }
00124      return m_MaxFontWidth;
00125 }
00126 
00127 
00128 void CRenderedString::GetMetrics(CPoint* pBoundedDimensions, CPoint* pOriginOffset, std::vector<CRect>* pCharacterRects) const
00129 {
00130      if (! m_bCachedMetricsValid)
00131      {
00132           m_CachedCharacterRects.clear();
00133 
00134           int iMinY = 0;
00135           int iMaxY = 0;
00136           int iLength = 0;
00137           for (unsigned int i = 0; i < m_sString.size(); ++i)
00138           {
00139                FT_Glyph_Metrics* pMetrics;
00140                if (m_MaskChar == L' ')
00141                {
00142                     pMetrics = m_pFontEngine->GetMetrics(m_sString[i]);
00143                }
00144                else
00145                {
00146                     pMetrics = m_pFontEngine->GetMetrics(m_MaskChar);
00147                }
00148 
00149                if ((pMetrics->horiBearingY - pMetrics->height) < iMinY)
00150                {
00151                     iMinY = pMetrics->horiBearingY - pMetrics->height;
00152                }
00153                if (pMetrics->horiBearingY > iMaxY)
00154                {
00155                     iMaxY = pMetrics->horiBearingY;
00156                }
00157                iLength += (pMetrics->horiAdvance);
00158                // 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
00159                m_CachedCharacterRects.push_back(
00160                     CRect((iLength - pMetrics->horiAdvance) >> 6, pMetrics->horiBearingY >> 6, iLength >> 6, pMetrics->height >> 6));
00161           }
00162 
00163           iMinY = iMinY >> 6;
00164           iMaxY = iMaxY >> 6;
00165           iLength = iLength >> 6;
00166 
00167           // now fix the top and bottom values of the rects
00168           for(std::vector<CRect>::iterator iter = m_CachedCharacterRects.begin(); iter != m_CachedCharacterRects.end(); ++iter)
00169           {
00170                iter->SetTop(iMaxY - iter->Top());
00171                iter->SetBottom(iter->Top() + iter->Bottom());
00172           }
00173 
00174           // Tack an empty rect on the end
00175           m_CachedCharacterRects.push_back(CRect(iLength, iMaxY, iLength, iMinY));
00176 
00177           m_CachedBoundedDimensions = CPoint(iLength, iMaxY - iMinY);
00178 
00179           switch (m_eHorzAlign)
00180           {
00181           case HALIGN_CENTER:
00182                m_OriginOffset.SetX(-iLength / 2);
00183                break;
00184           case HALIGN_RIGHT:
00185                m_OriginOffset.SetX(-iLength);
00186                break;
00187           case HALIGN_LEFT:
00188           default:
00189                m_OriginOffset.SetX(0);
00190                break;
00191           }
00192 
00193           switch (m_eVertAlign)
00194           {
00195           case VALIGN_TOP:
00196                m_OriginOffset.SetY(0);
00197                break;
00198           case VALIGN_BOTTOM:
00199                m_OriginOffset.SetY(iMinY - iMaxY);
00200                break;
00201           case VALIGN_CENTER:
00202                m_OriginOffset.SetY((iMinY - iMaxY) / 2);
00203                break;
00204           case VALIGN_NORMAL:
00205           default:
00206                m_OriginOffset.SetY(-iMaxY);
00207                break;
00208           }
00209 
00210           m_bCachedMetricsValid = true;
00211      }
00212 
00213      if (pBoundedDimensions)
00214      {
00215           *pBoundedDimensions = m_CachedBoundedDimensions;
00216      }
00217 
00218      if (pOriginOffset)
00219      {
00220           *pOriginOffset = m_OriginOffset;
00221      }
00222 
00223      if (pCharacterRects)
00224      {
00225           *pCharacterRects = m_CachedCharacterRects;
00226      }
00227 }
00228 
00229 }
00230 

Generated on Wed May 16 23:11:26 2007 for wGui by  doxygen 1.5.1