|
1 //******************************************************************* |
|
2 // glfont2.cpp -- glFont Version 2.0 implementation |
|
3 // Copyright (c) 1998-2002 Brad Fish |
|
4 // See glfont.html for terms of use |
|
5 // May 14, 2002 |
|
6 // |
|
7 // Symbian OS port - June 2007 |
|
8 // Luis Valente - lpvalente@gmail.com |
|
9 // |
|
10 //******************************************************************* |
|
11 |
|
12 /* |
|
13 This font class is intended to render 2D text. So, it is important to set up the |
|
14 required orthographic projection before rendering. The following code is an |
|
15 example of how to do this: |
|
16 |
|
17 // Rect() is a method that returns the current drawing rectangle. |
|
18 // The (0,0) point will be the on bottom-left corner. |
|
19 |
|
20 glViewport (0, 0, Rect().Width(), Rect().Height()); |
|
21 |
|
22 glMatrixMode (GL_PROJECTION); |
|
23 glLoadIdentity (); |
|
24 glOrthox (0, IntToFixed (Rect().Width()), 0, IntToFixed (Rect().Height()), -1, 1); |
|
25 |
|
26 glMatrixMode (GL_MODELVIEW); |
|
27 glLoadIdentity ();Also, the BeginDraw() and EndDraw() methods (or equivalent code) should be called |
|
28 to set up required states for rendering. For example, if alpha blending is not enabled, the quad |
|
29 corresponding to the character becomes noticeable. |
|
30 |
|
31 Currently, this class supports 8 bit descriptors only. The class should be extended to support 16 bits |
|
32 descriptors and resource strings. |
|
33 |
|
34 */ |
|
35 |
|
36 // Symbian OS headers |
|
37 #include <s32file.h> |
|
38 #include <eikenv.h> |
|
39 #include <eikappui.h> |
|
40 #include <eikapp.h> |
|
41 #include "glfont2.h" |
|
42 #include "FixedMath.h" |
|
43 |
|
44 |
|
45 // GLFontChar structure as stored in file |
|
46 struct GLFontCharFile |
|
47 { |
|
48 TReal32 dx, dy; |
|
49 TReal32 tx1, ty1; |
|
50 TReal32 tx2, ty2; |
|
51 }; |
|
52 |
|
53 // GLFontHeaderFile structure as stored in file |
|
54 struct GLFontHeaderFile |
|
55 { |
|
56 TInt32 tex; |
|
57 TInt32 texWidth, texHeight; |
|
58 TInt32 startChar, endChar; |
|
59 TUint32 chars; |
|
60 }; |
|
61 |
|
62 |
|
63 |
|
64 //_____________________________________________________________________________ |
|
65 // |
|
66 // Default constructor. |
|
67 // |
|
68 |
|
69 GLFont::GLFont () |
|
70 { |
|
71 // Initialize iHeader to safe state |
|
72 iHeader.tex = 0; |
|
73 iHeader.texWidth = 0; |
|
74 iHeader.texHeight = 0; |
|
75 iHeader.startChar = 0; |
|
76 iHeader.endChar = 0; |
|
77 iHeader.chars = NULL; |
|
78 |
|
79 // OpenGL texture |
|
80 glGenTextures (1, &iHeader.tex); |
|
81 } |
|
82 |
|
83 //_____________________________________________________________________________ |
|
84 // |
|
85 // Destructor. |
|
86 // |
|
87 |
|
88 GLFont::~GLFont () |
|
89 { |
|
90 // Destroy the font |
|
91 Destroy(); |
|
92 |
|
93 // delete texture |
|
94 glDeleteTextures (1, &iHeader.tex); |
|
95 } |
|
96 |
|
97 //_____________________________________________________________________________ |
|
98 // |
|
99 // Factory-method. |
|
100 // |
|
101 |
|
102 GLFont * GLFont::NewL (const TDesC & aFilename) |
|
103 { |
|
104 GLFont* f = new (ELeave) GLFont(); |
|
105 CleanupStack::PushL (f); |
|
106 |
|
107 f->ConstructL (aFilename); |
|
108 |
|
109 CleanupStack::Pop (); |
|
110 return f; |
|
111 } |
|
112 |
|
113 //_____________________________________________________________________________ |
|
114 // |
|
115 // Second part of the two-phase construction. |
|
116 // |
|
117 |
|
118 void GLFont::ConstructL (const TDesC & aFilename) |
|
119 { |
|
120 // Destroy the old font if there was one, just to be safe |
|
121 Destroy(); |
|
122 |
|
123 // Open file session with server |
|
124 RFs session; |
|
125 User::LeaveIfError (session.Connect()); |
|
126 CleanupClosePushL (session); |
|
127 |
|
128 // retrieve private application folder |
|
129 TFileName path; |
|
130 session.PrivatePath (path); |
|
131 |
|
132 // retrieve full application path on device |
|
133 #ifndef __WINS__ |
|
134 TFileName appFullName = |
|
135 CEikonEnv::Static()->EikAppUi()->Application()->AppFullName(); |
|
136 |
|
137 TParse parse; |
|
138 parse.Set (appFullName, NULL, NULL); |
|
139 path.Insert (0, parse.Drive()); |
|
140 #endif |
|
141 |
|
142 // update filename with full path |
|
143 TFileName fullFilename (path); |
|
144 fullFilename.Append (aFilename); |
|
145 |
|
146 // load file |
|
147 LoadFileL (session, fullFilename); |
|
148 |
|
149 // close server session |
|
150 CleanupStack::PopAndDestroy(); |
|
151 |
|
152 } |
|
153 |
|
154 //_____________________________________________________________________________ |
|
155 // |
|
156 // Loads the font file. |
|
157 // |
|
158 |
|
159 void GLFont::LoadFileL (RFs & aFs, const TDesC & aFilename) |
|
160 { |
|
161 // Open input file |
|
162 RFileReadStream readStream; |
|
163 |
|
164 User::LeaveIfError (readStream.Open (aFs, aFilename, EFileRead)); |
|
165 readStream.PushL(); |
|
166 |
|
167 // Read the iHeader from file |
|
168 GLFontHeaderFile headerFile; |
|
169 |
|
170 headerFile.tex = readStream.ReadInt32L (); |
|
171 headerFile.texWidth = readStream.ReadInt32L(); |
|
172 headerFile.texHeight = readStream.ReadInt32L(); |
|
173 headerFile.startChar = readStream.ReadInt32L(); |
|
174 headerFile.endChar = readStream.ReadInt32L(); |
|
175 headerFile.chars = readStream.ReadUint32L(); |
|
176 |
|
177 // copy iHeader file to actual iHeader |
|
178 iHeader.texWidth = headerFile.texWidth; |
|
179 iHeader.texHeight = headerFile.texHeight; |
|
180 iHeader.startChar = headerFile.startChar; |
|
181 iHeader.endChar = headerFile.endChar; |
|
182 |
|
183 // Allocate space for character array |
|
184 TInt numChars = iHeader.endChar - iHeader.startChar + 1; |
|
185 iHeader.chars = new (ELeave) GLFontChar [numChars]; |
|
186 |
|
187 // Read character array |
|
188 for (TInt i = 0; i < numChars; ++i) |
|
189 { |
|
190 iHeader.chars [i].dx = FloatToFixed (readStream.ReadReal32L () ); |
|
191 iHeader.chars [i].dy = FloatToFixed (readStream.ReadReal32L () ); |
|
192 iHeader.chars [i].tx1 = FloatToFixed (readStream.ReadReal32L () ); |
|
193 iHeader.chars [i].ty1 = FloatToFixed (readStream.ReadReal32L () ); |
|
194 iHeader.chars [i].tx2 = FloatToFixed (readStream.ReadReal32L () ); |
|
195 iHeader.chars [i].ty2 = FloatToFixed (readStream.ReadReal32L () ); |
|
196 } |
|
197 |
|
198 |
|
199 // Read texture pixel data |
|
200 TInt numTexBytes = iHeader.texWidth * iHeader.texHeight * 2; |
|
201 TUint8 * texBytes = new (ELeave) TUint8 [numTexBytes]; CleanupStack::PushL (texBytes); |
|
202 |
|
203 readStream.ReadL (texBytes, numTexBytes); |
|
204 |
|
205 // Create OpenGL texture |
|
206 glBindTexture (GL_TEXTURE_2D, iHeader.tex); |
|
207 glTexParameterf (GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); |
|
208 glTexParameterf (GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); |
|
209 glTexParameterf (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); |
|
210 glTexParameterf (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); |
|
211 glTexEnvf (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); |
|
212 |
|
213 glTexImage2D (GL_TEXTURE_2D, |
|
214 0, |
|
215 GL_LUMINANCE_ALPHA, |
|
216 iHeader.texWidth, |
|
217 iHeader.texHeight, |
|
218 0, |
|
219 GL_LUMINANCE_ALPHA, |
|
220 GL_UNSIGNED_BYTE, |
|
221 (GLvoid *)texBytes); |
|
222 |
|
223 // Free texture pixels memory |
|
224 CleanupStack::Pop (); |
|
225 delete [] texBytes; |
|
226 |
|
227 // Close input file |
|
228 readStream.Close(); |
|
229 readStream.Pop(); |
|
230 } |
|
231 |
|
232 //_____________________________________________________________________________ |
|
233 // |
|
234 // Font destruction. |
|
235 // |
|
236 |
|
237 void GLFont::Destroy () |
|
238 { |
|
239 //Delete the character array if necessary |
|
240 if (iHeader.chars) |
|
241 { |
|
242 delete [] iHeader.chars; |
|
243 iHeader.chars = 0; |
|
244 } |
|
245 } |
|
246 |
|
247 //_____________________________________________________________________________ |
|
248 // |
|
249 // Retrieves the texture dimensions. |
|
250 // |
|
251 |
|
252 void GLFont::GetTexSize (TInt & aWidth, TInt & aHeight) |
|
253 { |
|
254 aWidth = iHeader.texWidth; |
|
255 aHeight = iHeader.texHeight; |
|
256 } |
|
257 |
|
258 //_____________________________________________________________________________ |
|
259 // |
|
260 // Retrieves the character interval. |
|
261 // |
|
262 |
|
263 void GLFont::GetCharInterval (TInt & aStart, TInt & aEnd) |
|
264 { |
|
265 aStart = iHeader.startChar; |
|
266 aEnd = iHeader.endChar; |
|
267 } |
|
268 |
|
269 //_____________________________________________________________________________ |
|
270 // |
|
271 // Retrieves the dimensions of a character. |
|
272 // |
|
273 |
|
274 void GLFont::GetCharSize (TText8 aChar, TInt & aWidth, TInt aHeight) |
|
275 { |
|
276 // Make sure character is in range |
|
277 if (aChar < iHeader.startChar || aChar > iHeader.endChar) |
|
278 { |
|
279 // Not a valid character, so it obviously has no size |
|
280 aWidth = 0; |
|
281 aHeight = 0; |
|
282 } |
|
283 else |
|
284 { |
|
285 GLFontChar* fontChar; |
|
286 |
|
287 // Retrieve character size |
|
288 fontChar = & iHeader.chars [aChar - iHeader.startChar]; |
|
289 aWidth = FixedToInt (MultiplyFixed (fontChar->dx, IntToFixed (iHeader.texWidth) ) ); |
|
290 aHeight = FixedToInt (MultiplyFixed (fontChar->dy, IntToFixed (iHeader.texHeight) ) ); |
|
291 } |
|
292 } |
|
293 |
|
294 //_____________________________________________________________________________ |
|
295 // |
|
296 // Retrieves the dimensions of a string. |
|
297 // |
|
298 |
|
299 void GLFont::GetStringSize (const TDesC8 & aText, TInt & aWidth, TInt & aHeight) |
|
300 { |
|
301 // Height is the same for now...might change in future |
|
302 aHeight = FixedToInt (MultiplyFixed (iHeader.chars [iHeader.startChar].dy, IntToFixed (iHeader.texHeight) ) ); |
|
303 |
|
304 // texWidth as fixed |
|
305 const GLfixed texWidthx = IntToFixed (iHeader.texWidth); |
|
306 |
|
307 // Calculate width of string |
|
308 GLfixed widthx = 0; |
|
309 for (TInt i = 0; i < aText.Length(); i++) |
|
310 { |
|
311 // Make sure character is in range |
|
312 const TText8 c = aText [i]; |
|
313 if (c < iHeader.startChar || c > iHeader.endChar) |
|
314 continue; |
|
315 |
|
316 // Get pointer to glFont character |
|
317 const GLFontChar* fontChar = & iHeader.chars [c - iHeader.startChar]; |
|
318 |
|
319 // Get width and height |
|
320 widthx += MultiplyFixed (fontChar->dx, texWidthx); |
|
321 } |
|
322 |
|
323 // Save width |
|
324 aWidth = FixedToInt (widthx); |
|
325 } |
|
326 |
|
327 //_____________________________________________________________________________ |
|
328 // |
|
329 // Renders a string. Reference point is top-left. |
|
330 // |
|
331 |
|
332 void GLFont::DrawString (const TDesC8 & aText, GLfixed aX, GLfixed aY) |
|
333 { |
|
334 // vertex arrays to render the string |
|
335 GLfixed vertices [4*2]; |
|
336 GLfixed texCoords [4*2]; |
|
337 const GLubyte indices [] = {1, 2, 0, 3}; |
|
338 |
|
339 glVertexPointer (2, GL_FIXED, 0, vertices); |
|
340 glTexCoordPointer (2, GL_FIXED, 0, texCoords); |
|
341 |
|
342 // Bind texture |
|
343 glBindTexture (GL_TEXTURE_2D, iHeader.tex); |
|
344 |
|
345 // Loop through characters |
|
346 for (TInt i = 0; i < aText.Length(); i++) |
|
347 { |
|
348 // Make sure character is in range |
|
349 TText8 c = aText [i]; |
|
350 if (c < iHeader.startChar || c > iHeader.endChar) |
|
351 continue; |
|
352 |
|
353 // Get pointer to glFont character |
|
354 GLFontChar* fontChar = &iHeader.chars [c - iHeader.startChar]; |
|
355 |
|
356 // Get width and height |
|
357 GLfixed width = MultiplyFixed (fontChar->dx, IntToFixed (iHeader.texWidth) ); |
|
358 GLfixed height = MultiplyFixed (fontChar->dy, IntToFixed (iHeader.texHeight) ); |
|
359 |
|
360 // Specify texture coordinates |
|
361 texCoords [0] = fontChar->tx1; texCoords [1] = fontChar->ty1; |
|
362 texCoords [2] = fontChar->tx1; texCoords [3] = fontChar->ty2; |
|
363 |
|
364 texCoords [4] = fontChar->tx2; texCoords [5] = fontChar->ty2; |
|
365 texCoords [6] = fontChar->tx2; texCoords [7] = fontChar->ty1; |
|
366 |
|
367 // and vertices |
|
368 vertices [0] = aX; vertices [1] = aY; |
|
369 vertices [2] = aX; vertices [3] = aY - height; |
|
370 |
|
371 vertices [4] = aX + width; vertices [5] = aY - height; |
|
372 vertices [6] = aX + width; vertices [7] = aY; |
|
373 |
|
374 // draw |
|
375 glDrawElements (GL_TRIANGLE_STRIP, 4, GL_UNSIGNED_BYTE, indices); |
|
376 |
|
377 // Move to next character |
|
378 aX += width; |
|
379 } |
|
380 |
|
381 } |