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 }