nux-1.14.0
FontTexture.cpp
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 "GLResourceManager.h"
00025 #include "GLTextureResourceManager.h"
00026 #include "GraphicsEngine.h"
00027 #include "FontTexture.h"
00028 
00029 namespace nux
00030 {
00031 
00032   NUX_IMPLEMENT_OBJECT_TYPE (FontTexture);
00033 
00034   const int CURSOR_OFFSET = 0;
00035 
00036   FontTexture::FontTexture (const TCHAR *FontFile, NUX_FILE_LINE_DECL)
00037     :   Object (true, NUX_FILE_LINE_PARAM)
00038   {
00039     NString FontPath = GNuxGraphicsResources.FindResourceLocation (FontFile);
00040 
00041     std::filebuf fb;
00042     fb.open (FontPath.GetTCharPtr(), std::ios::in);
00043     std::istream is (&fb);
00044 
00045     BMFontParseFNT (is);
00046   }
00047 
00048   FontTexture::FontTexture (int width, int height, BYTE *Texture)
00049   {
00050 
00051   }
00052 
00053   FontTexture::~FontTexture()
00054   {
00055     std::vector<BaseTexture*>::iterator it;
00056     for(it = TextureArray.begin(); it != TextureArray.end(); it++)
00057     {
00058       (*it)->UnReference ();
00059     }
00060     TextureArray.clear();
00061   }
00062 
00063   int FontTexture::GetCharWidth (const TCHAR &c) const
00064   {
00065     int ascii = c & 0xff;
00066     nuxAssert (ascii < m_Charset.NumChar);
00067 
00068     if (ascii >= m_Charset.NumChar)
00069       return 0;
00070 
00071     // XAdvance = abcA + abcB + abcC
00072     return m_Charset.Chars[ascii].XAdvance;
00073   }
00074 
00075   int FontTexture::GetStringWidth (const NString &str) const
00076   {
00077 //     unsigned int total = 0;
00078 //     for (unsigned int i = 0; i != (unsigned int)str.size(); ++i)
00079 //     {
00080 //         total += GetCharWidth(str[i]);
00081 //     }
00082 //     return total;
00083     return GetCharStringWidth (str.GetTCharPtr() );
00084   }
00085 
00086   int FontTexture::GetCharStringWidth (const TCHAR *str) const
00087   {
00088     if ( (str == 0) || (NString (str) == NString (TEXT ("") ) ) )
00089       return 0;
00090 
00091     unsigned int total = 0;
00092 
00093     for (int i = 0; ; ++i)
00094     {
00095       if (str[i] == 0)
00096         return total;
00097 
00098       total += GetCharWidth (str[i]);
00099     }
00100 
00101     return total;
00102   }
00103 
00104   int FontTexture::GetStringWidth (const NString &str, int num_char_to_compute) const
00105   {
00106     return GetCharStringWidth (str.GetTCharPtr(), num_char_to_compute);
00107   }
00108 
00109   int FontTexture::GetCharStringWidth (const TCHAR *str, int num_char_to_compute) const
00110   {
00111     if ( (str == 0) || (NString (str) == NString (TEXT ("") ) ) )
00112       return 0;
00113 
00114     int num_chars = num_char_to_compute;
00115 
00116     if (num_chars <= 0)
00117     {
00118       return 0;
00119     }
00120 
00121     int total = 0;
00122 
00123     for (int i = 0; i < num_chars; ++i)
00124     {
00125       if (str[i] == 0)
00126         return total;
00127 
00128       total += GetCharWidth (str[i]);
00129     }
00130 
00131     return total;
00132   }
00133 
00134   int FontTexture::GetFontHeight()
00135   {
00136     return m_Charset.FontHeight;
00137   }
00138 
00139   bool FontTexture::BMFontParseFNT ( std::istream &Stream )
00140   {
00141     std::string Line;
00142     int KerningIndex = 0;
00143 
00144     while ( !Stream.eof() )
00145     {
00146       std::getline ( Stream, Line );
00147 
00148       unsigned int line_size = (unsigned int) Line.length();
00149       TCHAR *tc = new TCHAR[line_size+1];
00150       const TCHAR *Stream = tc;
00151       Memcpy (tc, Line.c_str(), line_size + 1);
00152       tc[line_size] = 0;
00153 
00154       if ( ParseCommand (&Stream, TEXT ("common") ) /*Read == "common"*/)
00155       {
00156         Parse_bool (tc, TEXT ("Bold="),        m_Charset.bold);
00157         Parse_bool (tc, TEXT ("Italic="),      m_Charset.italic);
00158         Parse_u16 (tc, TEXT ("base="),        m_Charset.Base);
00159         Parse_u16 (tc, TEXT ("scaleW="),      m_Charset.Width);
00160         Parse_u16 (tc, TEXT ("scaleH="),      m_Charset.Height);
00161         Parse_u16 (tc, TEXT ("NumPages="),    m_Charset.Pages);
00162         Parse_u16 (tc, TEXT ("FontHeight="),  m_Charset.FontHeight);
00163         Parse_u16 (tc, TEXT ("Ascent="),      m_Charset.Ascent);
00164         Parse_u16 (tc, TEXT ("Descent="),     m_Charset.Descent);
00165         Parse_int (tc, TEXT ("AvgCharWidth="),     m_Charset.AvgCharWidth);
00166         Parse_int (tc, TEXT ("MaxCharWidth="),     m_Charset.MaxCharWidth);
00167         Parse_int (tc, TEXT ("InternalLeading="),     m_Charset.InternalLeading);
00168         Parse_int (tc, TEXT ("ExternalLeading="),     m_Charset.ExternalLeading);
00169         // Constant for now... Should be read from the font file
00170         m_Charset.NumChar = 256;
00171       }
00172       else if (ParseCommand (&Stream, TEXT ("char") ) )
00173       {
00174 
00175         unsigned short CharID = 0;
00176 
00177         Parse_u16 (tc, TEXT ("id="), CharID);
00178         Parse_u16 (tc, TEXT ("x="), m_Charset.Chars[CharID].x);
00179         Parse_u16 (tc, TEXT ("y="), m_Charset.Chars[CharID].y);
00180         Parse_u16 (tc, TEXT ("width="), m_Charset.Chars[CharID].Width);
00181         Parse_u16 (tc, TEXT ("height="), m_Charset.Chars[CharID].Height);
00182         Parse_s16 (tc, TEXT ("xoffset="), m_Charset.Chars[CharID].XOffset);
00183         Parse_s16 (tc, TEXT ("yoffset="), m_Charset.Chars[CharID].YOffset);
00184         Parse_s16 (tc, TEXT ("xadvance="), m_Charset.Chars[CharID].XAdvance);
00185         Parse_s16 (tc, TEXT ("abcA="), m_Charset.Chars[CharID].abcA);
00186         Parse_s16 (tc, TEXT ("abcB="), m_Charset.Chars[CharID].abcB);
00187         Parse_s16 (tc, TEXT ("abcC="), m_Charset.Chars[CharID].abcC);
00188         Parse_u16 (tc, TEXT ("page="), m_Charset.Chars[CharID].page);
00189       }
00190       else if ( ParseCommand (&Stream, TEXT ("Kerning") ) )
00191       {
00192         Parse_u16 (tc, "count=", m_Charset.NumKerningPairs);
00193 
00194         if (m_Charset.NumKerningPairs > 0)
00195           m_Charset.Kerning = new KerningPair[m_Charset.NumKerningPairs];
00196       }
00197       else if ( ParseCommand (&Stream, TEXT ("KerningPair") ) )
00198       {
00199         if (KerningIndex < m_Charset.NumKerningPairs)
00200         {
00201           Parse_u16 (tc, "first=", m_Charset.Kerning[KerningIndex].first);
00202           Parse_u16 (tc, "second=", m_Charset.Kerning[KerningIndex].second);
00203           Parse_s16 (tc, "amount=", m_Charset.Kerning[KerningIndex].amount);
00204           KerningIndex++;
00205         }
00206       }
00207       else if ( ParseCommand (&Stream, TEXT ("Texture") ) )
00208       {
00209         TCHAR texture[256];
00210 
00211         if (ParseLine (&Stream, texture, 256) )
00212         {
00213 //                 FilePath FontPath;
00214 //                 FontPath.AddSearchPath(""); // for case where fully qualified path is given
00215 //                 FontPath.AddSearchPath(".");
00216 //                 FontPath.AddSearchPath("../Fonts");
00217 
00218 #ifdef UNICODE
00219           NString font_texture_file = GNuxGraphicsResources.FindResourceLocation (texture);
00220 #else
00221           NString font_texture_file = GNuxGraphicsResources.FindResourceLocation (texture);
00222 #endif
00223 
00224           TextureRectangle *Texture = new TextureRectangle (NUX_TRACKER_LOCATION);
00225           NBitmapData* bitmap_data = LoadImageFile(font_texture_file.GetTCharPtr ());
00226 
00227           if (bitmap_data)
00228             Texture->Update (bitmap_data, false);
00229 
00230           delete bitmap_data;
00231           TextureArray.push_back (Texture);
00232         }
00233       }
00234 
00235       delete [] tc;
00236     }
00237 
00238     return true;
00239   }
00240 
00241 //    CursorPosToX (similar to ScriptStringCPtoX from Microsoft UniScript)
00242 //        The CursorPosToX function returns the x-coordinate for the leading or trailing edge of a character position.
00243 
00244 //        Parameters
00245 //        icp
00246 //          [in] Character position in the string.
00247 //        fTrailing
00248 //          [in] Indicates the edge of the icp that corresponds to the x coordinate. If TRUE, it indicates the trailing edge. If FALSE, it indicates the leading edge.
00249 //        pX
00250 //          [out] Pointer to a variable that receives the corresponding x coordinate for the icp.
00251 //
00252 //        Return Values
00253 //          If the function succeeds, it returns S_OK.
00254 //          If the function fails, it returns an HRESULT.
00255 //          The return value can be tested with the SUCCEEDED and FAILED macros.
00256   bool FontTexture::CursorPosToX (const NString &Str,
00257                                   int icp,
00258                                   bool fTrailing,
00259                                   int *pX)
00260   {
00261     if (icp > (int) Str.Size() )
00262       return false;
00263 
00264     if (fTrailing)
00265       // get pX at the right of the character at position icp
00266       *pX = GetStringWidth (Str, icp + 1);
00267     else
00268       // get pX at the left of the character at position icp
00269       *pX = GetStringWidth (Str, icp);
00270 
00271     return true;
00272   }
00273 
00274 //    XToCursorPosition (similar to ScriptStringXtoCP from Microsoft UniScript)
00275 //        The XToCursorPosition function converts an x-coordinate to a character position.
00276 //
00277 //    Parameters
00278 //        iX
00279 //          [in] Specifies the x coordinate.
00280 //        FirstVisibleCharIndex,
00281 //          [in] Index of the first visible character in the text box
00282 //        piCh
00283 //          [out] Pointer to a variable that receives the character position corresponding to iX.
00284 //        piTrailing
00285 //          [out] Pointer to a variable that receives an indicator whether the position is the leading or trailing edge of the character.
00286 //
00287 //        Return Values
00288 //          If the function is successful, it returns S_OK.
00289 //          If the function fails, it returns an HRESULT.
00290 //          The return value can be tested with the SUCCEEDED and FAILED macros.
00291   bool FontTexture::XToCursorPosition (const NString &Str,
00292                                        int iX,
00293                                        unsigned int FirstVisibleCharIndex,
00294                                        int *piCh,
00295                                        int *piTrailing)
00296   {
00297     unsigned int num_chars;
00298     num_chars = (unsigned int) Str.Size();
00299     nuxAssert (FirstVisibleCharIndex < num_chars);
00300 
00301     *piCh = 0;
00302     *piTrailing = 0;
00303 
00304     unsigned int total = 0;
00305 
00306     if (iX == 0)
00307     {
00308       *piCh = 0;
00309       *piTrailing = 0;
00310       return true;
00311     }
00312 
00313 
00314     unsigned int X = iX;
00315 
00316     for (unsigned int i = 0; i < FirstVisibleCharIndex; ++i)
00317     {
00318       X += GetCharWidth (Str[i]);
00319     }
00320 
00321     for (unsigned int i = 0; i < num_chars; ++i)
00322     {
00323       unsigned int s = GetCharWidth (Str[i]);
00324 
00325       if (i >= FirstVisibleCharIndex)
00326       {
00327         if (total == X)
00328         {
00329           *piCh = i;
00330           *piTrailing = 0;
00331           return true;
00332         }
00333         else if (total + s / 2 > X)
00334         {
00335           *piCh = i;
00336           *piTrailing = 0;
00337           return true;
00338         }
00339 
00340         else if (total + GetCharWidth (Str[i+1]) / 2 > X)
00341         {
00342           *piCh = i + 1;
00343           *piTrailing = 0;
00344           return true;
00345         }
00346       }
00347 
00348       total += s;
00349     }
00350 
00351     return false;
00352   }
00353 
00354   const Charset &FontTexture::GetFontInfo() const
00355   {
00356     return m_Charset;
00357   }
00358 
00359 }
 All Classes Namespaces Functions Variables Typedefs Enumerations Enumerator Friends