1 /*
  2  * Copyright 2010 Inalogic�� Inc.
  3  *
  4  * This program is free software: you can redistribute it and/or modify it
  5  * under the terms of the GNU Lesser General Public License, as
  6  * published by the  Free Software Foundation; either version 2.1 or 3.0
  7  * of the License.
  8  *
  9  * This program is distributed in the hope that it will be useful, but
 10  * WITHOUT ANY WARRANTY; without even the implied warranties of
 11  * MERCHANTABILITY, SATISFACTORY QUALITY or FITNESS FOR A PARTICULAR
 12  * PURPOSE.  See the applicable version of the GNU Lesser General Public
 13  * License for more details.
 14  *
 15  * You should have received a copy of both the GNU Lesser General Public
 16  * License along with this program. If not, see <http://www.gnu.org/licenses/>
 17  *
 18  * Authored by: Jay Taoko <jaytaoko@inalogic.com>
 19  *
 20  */
 21 
 22 
 23 #include "GLResource.h"
 24 #include "GLResourceManager.h"
 25 #include "GLTextureResourceManager.h"
 26 #include "GraphicsEngine.h"
 27 #include "FontTexture.h"
 28 
 29 namespace nux
 30 {
 31 
 32   NUX_IMPLEMENT_OBJECT_TYPE(FontTexture);
 33 
 34   const int CURSOR_OFFSET = 0;
 35 
 36   FontTexture::FontTexture(const char *FontFile, NUX_FILE_LINE_DECL)
 37     :   Object(true, NUX_FILE_LINE_PARAM)
 38   {
 39     NString FontPath = GNuxGraphicsResources.FindResourceLocation(FontFile);
 40 
 41     std::filebuf fb;
 42     fb.open(FontPath.GetTCharPtr(), std::ios::in);
 43     std::istream is(&fb);
 44 
 45     BMFontParseFNT(is);
 46   }
 47 
 48   FontTexture::FontTexture(int width, int height, BYTE *Texture)
 49   {
 50 
 51   }
 52 
 53   FontTexture::~FontTexture()
 54   {
 55     std::vector<BaseTexture*>::iterator it;
 56     for (it = TextureArray.begin(); it != TextureArray.end(); it++)
 57     {
 58       (*it)->UnReference();
 59     }
 60     TextureArray.clear();
 61   }
 62 
 63   int FontTexture::GetCharWidth(const char &c) const
 64   {
 65     int ascii = c & 0xff;
 66     nuxAssert(ascii < m_Charset.NumChar);
 67 
 68     if (ascii >= m_Charset.NumChar)
 69       return 0;
 70 
 71     // XAdvance = abcA + abcB + abcC
 72     return m_Charset.Chars[ascii].XAdvance;
 73   }
 74 
 75   int FontTexture::GetStringWidth(const NString &str) const
 76   {
 77 //     unsigned int total = 0;
 78 //     for (unsigned int i = 0; i != (unsigned int)str.size(); ++i)
 79 //     {
 80 //         total += GetCharWidth(str[i]);
 81 //     }
 82 //     return total;
 83     return GetCharStringWidth(str.GetTCharPtr());
 84   }
 85 
 86   int FontTexture::GetCharStringWidth(const char *str) const
 87   {
 88     if ((str == 0) || (NString(str) == NString("")))
 89       return 0;
 90 
 91     unsigned int total = 0;
 92 
 93     for (int i = 0; ; ++i)
 94     {
 95       if (str[i] == 0)
 96         return total;
 97 
 98       total += GetCharWidth(str[i]);
 99     }
100 
101     return total;
102   }
103 
104   int FontTexture::GetStringWidth(const NString &str, int num_char_to_compute) const
105   {
106     return GetCharStringWidth(str.GetTCharPtr(), num_char_to_compute);
107   }
108 
109   int FontTexture::GetCharStringWidth(const char *str, int num_char_to_compute) const
110   {
111     if ((str == 0) || (NString(str) == NString("")))
112       return 0;
113 
114     int num_chars = num_char_to_compute;
115 
116     if (num_chars <= 0)
117     {
118       return 0;
119     }
120 
121     int total = 0;
122 
123     for (int i = 0; i < num_chars; ++i)
124     {
125       if (str[i] == 0)
126         return total;
127 
128       total += GetCharWidth(str[i]);
129     }
130 
131     return total;
132   }
133 
134   int FontTexture::GetFontHeight()
135   {
136     return m_Charset.FontHeight;
137   }
138 
139   bool FontTexture::BMFontParseFNT( std::istream &Stream )
140   {
141     std::string Line;
142     int KerningIndex = 0;
143 
144     while ( !Stream.eof())
145     {
146       std::getline( Stream, Line );
147 
148       unsigned int line_size = (unsigned int) Line.length();
149       char *tc = new char[line_size+1];
CID 10652 - PW.PARAMETER_HIDDEN
declaration hides parameter "Stream" (declared at line 139)
150       const char *Stream = tc;
151       Memcpy(tc, Line.c_str(), line_size + 1);
152       tc[line_size] = 0;
153 
154       if ( ParseCommand(&Stream, "common") /*Read == "common"*/)
155       {
156         Parse_bool(tc, "Bold=",        m_Charset.bold);
157         Parse_bool(tc, "Italic=",      m_Charset.italic);
158         Parse_u16(tc, "base=",        m_Charset.Base);
159         Parse_u16(tc, "scaleW=",      m_Charset.Width);
160         Parse_u16(tc, "scaleH=",      m_Charset.Height);
161         Parse_u16(tc, "NumPages=",    m_Charset.Pages);
162         Parse_u16(tc, "FontHeight=",  m_Charset.FontHeight);
163         Parse_u16(tc, "Ascent=",      m_Charset.Ascent);
164         Parse_u16(tc, "Descent=",     m_Charset.Descent);
165         Parse_int(tc, "AvgCharWidth=",     m_Charset.AvgCharWidth);
166         Parse_int(tc, "MaxCharWidth=",     m_Charset.MaxCharWidth);
167         Parse_int(tc, "InternalLeading=",     m_Charset.InternalLeading);
168         Parse_int(tc, "ExternalLeading=",     m_Charset.ExternalLeading);
169         // Constant for now... Should be read from the font file
170         m_Charset.NumChar = 256;
171       }
172       else if (ParseCommand(&Stream, "char"))
173       {
174 
175         unsigned short CharID = 0;
176 
177         Parse_u16(tc, "id=", CharID);
178         Parse_u16(tc, "x=", m_Charset.Chars[CharID].x);
179         Parse_u16(tc, "y=", m_Charset.Chars[CharID].y);
180         Parse_u16(tc, "width=", m_Charset.Chars[CharID].Width);
181         Parse_u16(tc, "height=", m_Charset.Chars[CharID].Height);
182         Parse_s16(tc, "xoffset=", m_Charset.Chars[CharID].XOffset);
183         Parse_s16(tc, "yoffset=", m_Charset.Chars[CharID].YOffset);
184         Parse_s16(tc, "xadvance=", m_Charset.Chars[CharID].XAdvance);
185         Parse_s16(tc, "abcA=", m_Charset.Chars[CharID].abcA);
186         Parse_s16(tc, "abcB=", m_Charset.Chars[CharID].abcB);
187         Parse_s16(tc, "abcC=", m_Charset.Chars[CharID].abcC);
188         Parse_u16(tc, "page=", m_Charset.Chars[CharID].page);
189       }
190       else if ( ParseCommand(&Stream, "Kerning"))
191       {
192         Parse_u16(tc, "count=", m_Charset.NumKerningPairs);
193 
194         if (m_Charset.NumKerningPairs > 0)
195           m_Charset.Kerning = new KerningPair[m_Charset.NumKerningPairs];
196       }
197       else if ( ParseCommand(&Stream, "KerningPair"))
198       {
199         if (KerningIndex < m_Charset.NumKerningPairs)
200         {
201           Parse_u16(tc, "first=", m_Charset.Kerning[KerningIndex].first);
202           Parse_u16(tc, "second=", m_Charset.Kerning[KerningIndex].second);
203           Parse_s16(tc, "amount=", m_Charset.Kerning[KerningIndex].amount);
204           KerningIndex++;
205         }
206       }
207       else if ( ParseCommand(&Stream, "Texture"))
208       {
209         char texture[256];
210 
211         if (ParseLine(&Stream, texture, 256))
212         {
213 //                 FilePath FontPath;
214 //                 FontPath.AddSearchPath(""); // for case where fully qualified path is given
215 //                 FontPath.AddSearchPath(".");
216 //                 FontPath.AddSearchPath("../Fonts");
217 
218 #ifdef UNICODE
219           NString font_texture_file = GNuxGraphicsResources.FindResourceLocation(texture);
220 #else
221           NString font_texture_file = GNuxGraphicsResources.FindResourceLocation(texture);
222 #endif
223 
224 #ifdef NUX_OPENGLES_20
225           Texture2D *Texture = new Texture2D(NUX_TRACKER_LOCATION);
226 #else
227           TextureRectangle *Texture = new TextureRectangle(NUX_TRACKER_LOCATION);
228 #endif
229 
230           NBitmapData* bitmap_data = LoadImageFile(font_texture_file.GetTCharPtr());
231 
232           if (bitmap_data)
233             Texture->Update(bitmap_data, false);
234 
235           delete bitmap_data;
236           TextureArray.push_back(Texture);
237         }
238       }
239 
240       delete [] tc;
241     }
242 
243     return true;
244   }
245 
246 //    CursorPosToX(similar to ScriptStringCPtoX from Microsoft UniScript)
247 //        The CursorPosToX function returns the x-coordinate for the leading or trailing edge of a character position.
248 
249 //        Parameters
250 //        icp
251 //          [in] Character position in the string.
252 //        fTrailing
253 //          [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.
254 //        pX
255 //          [out] Pointer to a variable that receives the corresponding x coordinate for the icp.
256 //
257 //        Return Values
258 //          If the function succeeds, it returns S_OK.
259 //          If the function fails, it returns an HRESULT.
260 //          The return value can be tested with the SUCCEEDED and FAILED macros.
261   bool FontTexture::CursorPosToX(const NString &Str,
262                                   int icp,
263                                   bool fTrailing,
264                                   int *pX)
265   {
266     if (icp > (int) Str.Size())
267       return false;
268 
269     if (fTrailing)
270       // get pX at the right of the character at position icp
271       *pX = GetStringWidth(Str, icp + 1);
272     else
273       // get pX at the left of the character at position icp
274       *pX = GetStringWidth(Str, icp);
275 
276     return true;
277   }
278 
279 //    XToCursorPosition(similar to ScriptStringXtoCP from Microsoft UniScript)
280 //        The XToCursorPosition function converts an x-coordinate to a character position.
281 //
282 //    Parameters
283 //        iX
284 //          [in] Specifies the x coordinate.
285 //        FirstVisibleCharIndex,
286 //          [in] Index of the first visible character in the text box
287 //        piCh
288 //          [out] Pointer to a variable that receives the character position corresponding to iX.
289 //        piTrailing
290 //          [out] Pointer to a variable that receives an indicator whether the position is the leading or trailing edge of the character.
291 //
292 //        Return Values
293 //          If the function is successful, it returns S_OK.
294 //          If the function fails, it returns an HRESULT.
295 //          The return value can be tested with the SUCCEEDED and FAILED macros.
296   bool FontTexture::XToCursorPosition(const NString &Str,
297                                        int iX,
298                                        unsigned int FirstVisibleCharIndex,
299                                        int *piCh,
300                                        int *piTrailing)
301   {
302     unsigned int num_chars;
303     num_chars = (unsigned int) Str.Size();
304     nuxAssert(FirstVisibleCharIndex < num_chars);
305 
306     *piCh = 0;
307     *piTrailing = 0;
308 
309     unsigned int total = 0;
310 
311     if (iX == 0)
312     {
313       *piCh = 0;
314       *piTrailing = 0;
315       return true;
316     }
317 
318 
319     unsigned int X = iX;
320 
321     for (unsigned int i = 0; i < FirstVisibleCharIndex; ++i)
322     {
323       X += GetCharWidth(Str[i]);
324     }
325 
326     for (unsigned int i = 0; i < num_chars; ++i)
327     {
328       unsigned int s = GetCharWidth(Str[i]);
329 
330       if (i >= FirstVisibleCharIndex)
331       {
332         if (total == X)
333         {
334           *piCh = i;
335           *piTrailing = 0;
336           return true;
337         }
338         else if (total + s / 2 > X)
339         {
340           *piCh = i;
341           *piTrailing = 0;
342           return true;
343         }
344 
345         else if (total + GetCharWidth(Str[i+1]) / 2 > X)
346         {
347           *piCh = i + 1;
348           *piTrailing = 0;
349           return true;
350         }
351       }
352 
353       total += s;
354     }
355 
356     return false;
357   }
358 
359   const Charset &FontTexture::GetFontInfo() const
360   {
361     return m_Charset;
362   }
363 
364 }