Back to index

nux  3.0.0
FontTexture.cpp
Go to the documentation of this file.
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 char *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 char &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 char *str) const
00087   {
00088     if ((str == 0) || (NString(str) == NString("")))
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 char *str, int num_char_to_compute) const
00110   {
00111     if ((str == 0) || (NString(str) == NString("")))
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       char *tc = new char[line_size+1];
00150       const char *stream = tc;
00151       Memcpy(tc, Line.c_str(), line_size + 1);
00152       tc[line_size] = 0;
00153 
00154       if ( ParseCommand(&stream, "common") /*Read == "common"*/)
00155       {
00156         Parse_bool(tc, "Bold=",        m_Charset.bold);
00157         Parse_bool(tc, "Italic=",      m_Charset.italic);
00158         Parse_u16(tc, "base=",        m_Charset.Base);
00159         Parse_u16(tc, "scaleW=",      m_Charset.Width);
00160         Parse_u16(tc, "scaleH=",      m_Charset.Height);
00161         Parse_u16(tc, "NumPages=",    m_Charset.Pages);
00162         Parse_u16(tc, "FontHeight=",  m_Charset.FontHeight);
00163         Parse_u16(tc, "Ascent=",      m_Charset.Ascent);
00164         Parse_u16(tc, "Descent=",     m_Charset.Descent);
00165         Parse_int(tc, "AvgCharWidth=",     m_Charset.AvgCharWidth);
00166         Parse_int(tc, "MaxCharWidth=",     m_Charset.MaxCharWidth);
00167         Parse_int(tc, "InternalLeading=",     m_Charset.InternalLeading);
00168         Parse_int(tc, "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, "char"))
00173       {
00174 
00175         unsigned short CharID = 0;
00176 
00177         Parse_u16(tc, "id=", CharID);
00178         Parse_u16(tc, "x=", m_Charset.Chars[CharID].x);
00179         Parse_u16(tc, "y=", m_Charset.Chars[CharID].y);
00180         Parse_u16(tc, "width=", m_Charset.Chars[CharID].Width);
00181         Parse_u16(tc, "height=", m_Charset.Chars[CharID].Height);
00182         Parse_s16(tc, "xoffset=", m_Charset.Chars[CharID].XOffset);
00183         Parse_s16(tc, "yoffset=", m_Charset.Chars[CharID].YOffset);
00184         Parse_s16(tc, "xadvance=", m_Charset.Chars[CharID].XAdvance);
00185         Parse_s16(tc, "abcA=", m_Charset.Chars[CharID].abcA);
00186         Parse_s16(tc, "abcB=", m_Charset.Chars[CharID].abcB);
00187         Parse_s16(tc, "abcC=", m_Charset.Chars[CharID].abcC);
00188         Parse_u16(tc, "page=", m_Charset.Chars[CharID].page);
00189       }
00190       else if ( ParseCommand(&stream, "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, "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, "Texture"))
00208       {
00209         char 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 #ifdef NUX_OPENGLES_20
00225           Texture2D *Texture = new Texture2D(NUX_TRACKER_LOCATION);
00226 #else
00227           TextureRectangle *Texture = new TextureRectangle(NUX_TRACKER_LOCATION);
00228 #endif
00229 
00230           NBitmapData* bitmap_data = LoadImageFile(font_texture_file.GetTCharPtr());
00231 
00232           if (bitmap_data)
00233             Texture->Update(bitmap_data, false);
00234 
00235           delete bitmap_data;
00236           TextureArray.push_back(Texture);
00237         }
00238       }
00239 
00240       delete [] tc;
00241     }
00242 
00243     return true;
00244   }
00245 
00246 //    CursorPosToX(similar to ScriptStringCPtoX from Microsoft UniScript)
00247 //        The CursorPosToX function returns the x-coordinate for the leading or trailing edge of a character position.
00248 
00249 //        Parameters
00250 //        icp
00251 //          [in] Character position in the string.
00252 //        fTrailing
00253 //          [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.
00254 //        pX
00255 //          [out] Pointer to a variable that receives the corresponding x coordinate for the icp.
00256 //
00257 //        Return Values
00258 //          If the function succeeds, it returns S_OK.
00259 //          If the function fails, it returns an HRESULT.
00260 //          The return value can be tested with the SUCCEEDED and FAILED macros.
00261   bool FontTexture::CursorPosToX(const NString &Str,
00262                                   int icp,
00263                                   bool fTrailing,
00264                                   int *pX)
00265   {
00266     if (icp > (int) Str.Size())
00267       return false;
00268 
00269     if (fTrailing)
00270       // get pX at the right of the character at position icp
00271       *pX = GetStringWidth(Str, icp + 1);
00272     else
00273       // get pX at the left of the character at position icp
00274       *pX = GetStringWidth(Str, icp);
00275 
00276     return true;
00277   }
00278 
00279 //    XToCursorPosition(similar to ScriptStringXtoCP from Microsoft UniScript)
00280 //        The XToCursorPosition function converts an x-coordinate to a character position.
00281 //
00282 //    Parameters
00283 //        iX
00284 //          [in] Specifies the x coordinate.
00285 //        FirstVisibleCharIndex,
00286 //          [in] Index of the first visible character in the text box
00287 //        piCh
00288 //          [out] Pointer to a variable that receives the character position corresponding to iX.
00289 //        piTrailing
00290 //          [out] Pointer to a variable that receives an indicator whether the position is the leading or trailing edge of the character.
00291 //
00292 //        Return Values
00293 //          If the function is successful, it returns S_OK.
00294 //          If the function fails, it returns an HRESULT.
00295 //          The return value can be tested with the SUCCEEDED and FAILED macros.
00296   bool FontTexture::XToCursorPosition(const NString &Str,
00297                                        int iX,
00298                                        unsigned int FirstVisibleCharIndex,
00299                                        int *piCh,
00300                                        int *piTrailing)
00301   {
00302     unsigned int num_chars;
00303     num_chars = (unsigned int) Str.Size();
00304     nuxAssert(FirstVisibleCharIndex < num_chars);
00305 
00306     *piCh = 0;
00307     *piTrailing = 0;
00308 
00309     unsigned int total = 0;
00310 
00311     if (iX == 0)
00312     {
00313       *piCh = 0;
00314       *piTrailing = 0;
00315       return true;
00316     }
00317 
00318 
00319     unsigned int X = iX;
00320 
00321     for (unsigned int i = 0; i < FirstVisibleCharIndex; ++i)
00322     {
00323       X += GetCharWidth(Str[i]);
00324     }
00325 
00326     for (unsigned int i = 0; i < num_chars; ++i)
00327     {
00328       unsigned int s = GetCharWidth(Str[i]);
00329 
00330       if (i >= FirstVisibleCharIndex)
00331       {
00332         if (total == X)
00333         {
00334           *piCh = i;
00335           *piTrailing = 0;
00336           return true;
00337         }
00338         else if (total + s / 2 > X)
00339         {
00340           *piCh = i;
00341           *piTrailing = 0;
00342           return true;
00343         }
00344 
00345         else if (total + GetCharWidth(Str[i+1]) / 2 > X)
00346         {
00347           *piCh = i + 1;
00348           *piTrailing = 0;
00349           return true;
00350         }
00351       }
00352 
00353       total += s;
00354     }
00355 
00356     return false;
00357   }
00358 
00359   const Charset &FontTexture::GetFontInfo() const
00360   {
00361     return m_Charset;
00362   }
00363 
00364 }