Core commit. Compile and run on the OpenPandora
[mupen64plus-pandora.git] / source / mupen64plus-core / src / osd / OGLFT.cpp
1 /*
2  * OGLFT: A library for drawing text with OpenGL using the FreeType library
3  * Copyright (C) 2002 lignum Computing, Inc. <oglft@lignumcomputing.com>
4  * $Id: OGLFT.cpp,v 1.11 2003/10/01 14:21:18 allen Exp $
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 2.1 of the License, or (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with this library; if not, write
18  * Free Software Foundation, Inc.,
19  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
20  */
21
22 #include <iostream>
23 #include <iomanip>
24 #include <string.h>
25 #include "OGLFT.h"
26
27 int wstrlen(const wchar_t * s) 
28 {
29     int r = 0;
30     while (*s++) r++;
31     return r;
32 }
33
34 namespace OGLFT 
35 {
36     FT_Library ft_library;
37     bool Init_FT(void)
38     {
39         FT_Error error = FT_Init_FreeType(&ft_library);
40         if(error != 0) std::cerr << "[OGLFT] Could not initialize the FreeType library." << std::endl;
41         return (error == 0);
42     }
43     bool Uninit_FT(void)
44     {
45         FT_Error error = FT_Done_FreeType(ft_library);
46         if(error != 0) std::cerr << "[OGLFT] Could not terminate the FreeType library." << std::endl;
47         return (error == 0);
48     }
49
50     // Load a new face
51     Face::Face (const char* filename, float point_size, FT_UInt resolution)
52         : point_size_(point_size), resolution_(resolution)
53     {
54         valid_ = true;
55         FT_Face ft_face;
56         FT_Error error = FT_New_Face(ft_library, filename, 0, &ft_face);
57         if(error != 0) 
58         {
59             valid_ = false;
60             return;
61         }
62
63         // As of FreeType 2.1: only a UNICODE charmap is automatically activated.
64         // If no charmap is activated automatically, just use the first one.
65         if(ft_face->charmap == 0 && ft_face->num_charmaps > 0) FT_Select_Charmap(ft_face, ft_face->charmaps[0]->encoding);
66
67         faces_.push_back(FaceData(ft_face));
68
69         init();
70     }
71
72     // Go with a face that the user has already opened.
73     Face::Face (FT_Face face, float point_size, FT_UInt resolution)
74         : point_size_(point_size), resolution_(resolution)
75     {
76         valid_ = true;
77
78         // As of FreeType 2.1: only a UNICODE charmap is automatically activated.
79         // If no charmap is activated automatically, just use the first one.
80         if(face->charmap == 0 && face->num_charmaps > 0) FT_Select_Charmap(face, face->charmaps[0]->encoding);
81
82         faces_.push_back(FaceData(face, false));
83
84         init();
85     }
86
87     // Standard initialization behavior once the font file is opened.
88     void Face::init (void)
89     {
90         // By default, each glyph is compiled into a display list the first
91         // time it is encountered
92         compile_mode_ = COMPILE;
93
94         // By default, all drawing is wrapped with push/pop matrix so that the
95         // MODELVIEW matrix is not modified. If advance_ is set, then subsequent
96         // drawings follow from the advance of the last glyph rendered.
97         advance_ = false;
98
99         // Initialize the default colors
100         foreground_color_[R] = 0.; foreground_color_[G] = 0.; foreground_color_[B] = 0.; foreground_color_[A] = 1.;
101         background_color_[R] = 1.; background_color_[G] = 1.; background_color_[B] = 1.; background_color_[A] = 0.;
102
103         // The default positioning of the text is at the origin of the first glyph
104         horizontal_justification_ = ORIGIN;
105         vertical_justification_ = BASELINE;
106
107         // By default, strings are rendered in their nominal direction
108         string_rotation_ = 0;
109
110         // setCharacterRotationReference calls the virtual function clearCaches()
111         // so it is up to a subclass to set the real default
112         rotation_reference_glyph_ = 0;
113         rotation_reference_face_ = 0;
114         rotation_offset_y_ = 0.;
115     }
116
117     Face::~Face (void)
118     {
119         for(unsigned int i=0; i<faces_.size(); i++)
120             if(faces_[i].free_on_exit_)
121                 FT_Done_Face(faces_[i].face_);
122     }
123
124     // Add another Face to select characters from
125     bool Face::addAuxiliaryFace (const char* filename)
126     {
127         FT_Face ft_face;
128
129         FT_Error error = FT_New_Face(ft_library, filename, 0, &ft_face);
130
131         if(error != 0) return false;
132
133         faces_.push_back(FaceData(ft_face));
134         setCharSize();
135
136         return true;
137     }
138
139     // Add another Face to select characters from
140     bool Face::addAuxiliaryFace (FT_Face face)
141     {
142         faces_.push_back(FaceData(face, false));
143
144         setCharSize();
145
146         return true;
147     }
148
149     // Note: Changing the point size also clears the display list cache
150     void Face::setPointSize (float point_size)
151     {
152         if(point_size != point_size_) 
153         {
154             point_size_ = point_size;
155             clearCaches();
156             setCharSize();
157         }
158     }
159
160      // Note: Changing the resolution also clears the display list cache
161     void Face::setResolution (FT_UInt resolution)
162     {
163         if(resolution != resolution_) 
164         {
165             resolution_ = resolution;
166             clearCaches();
167             setCharSize();
168         }
169     }
170
171     // Note: Changing the background color also clears the display list cache.
172     void Face::setBackgroundColor (GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha)
173     {
174         if(background_color_[R] != red||background_color_[G] != green||background_color_[B] != blue||background_color_[A] != alpha) 
175         {
176             background_color_[R] = red;
177             background_color_[G] = green;
178             background_color_[B] = blue;
179             background_color_[A] = alpha;
180         }
181     }
182
183     // Note: Changing the foreground color also clears the display list cache.
184     void Face::setForegroundColor (GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha)
185     {
186         if(foreground_color_[R] != red||foreground_color_[G] != green||foreground_color_[B] != blue||foreground_color_[A] != alpha) 
187         {
188             foreground_color_[R] = red;
189             foreground_color_[G] = green;
190             foreground_color_[B] = blue;
191             foreground_color_[A] = alpha;
192         }
193     }
194
195     // Note: Changing the foreground color also clears the display list cache.
196     void Face::setForegroundColor (const GLfloat foreground_color[4])
197     {
198         foreground_color_[R] = foreground_color[R];
199         foreground_color_[G] = foreground_color[G];
200         foreground_color_[B] = foreground_color[B];
201         foreground_color_[A] = foreground_color[A];
202     }
203
204     // Note: Changing the background color also clears the display list cache.
205     void Face::setBackgroundColor (const GLfloat background_color[4])
206     {
207         background_color_[R] = background_color[R];
208         background_color_[G] = background_color[G];
209         background_color_[B] = background_color[B];
210         background_color_[A] = background_color[A];
211     }
212
213     // Note: Changing the string rotation angle clears the display list cache
214     void Face::setStringRotation (GLfloat string_rotation)
215     {
216         if(string_rotation != string_rotation_) 
217         {
218             string_rotation_ = string_rotation;
219
220             clearCaches();
221
222             // Note that this affects ALL glyphs accessed through
223             // the Face, both the vector and the raster glyphs. Very nice!
224             if (string_rotation_ != 0) 
225             {
226                 float angle;
227                 if (string_rotation_<0) 
228                     angle = 360.0f - fmod(fabs(string_rotation_), 360.f);
229                 else 
230                     angle = fmod(string_rotation_, 360.f);
231
232                 FT_Matrix rotation_matrix;
233                 FT_Vector sinus;
234
235                 FT_Vector_Unit(&sinus, (FT_Angle)(angle * 0x10000L));
236
237                 rotation_matrix.xx = sinus.x;
238                 rotation_matrix.xy = -sinus.y;
239                 rotation_matrix.yx = sinus.y;
240                 rotation_matrix.yy = sinus.x;
241
242                 for(unsigned int i=0; i<faces_.size(); i++) FT_Set_Transform(faces_[i].face_, &rotation_matrix, 0);
243             }
244             else for(unsigned int i=0; i<faces_.size(); i++) FT_Set_Transform(faces_[i].face_, 0, 0);
245         }
246     }
247
248     // Note: Changing the rotation reference character clears the display list cache.
249     void Face::setCharacterRotationReference (unsigned char c)
250     {
251         unsigned int f;
252         FT_UInt glyph_index = 0;
253
254         for(f=0; f<faces_.size(); f++) 
255         {
256             glyph_index = FT_Get_Char_Index(faces_[f].face_, c);
257             if(glyph_index != 0) break;
258         }
259
260         if(f<faces_.size() && glyph_index != rotation_reference_glyph_) 
261         {
262             FT_Error error = FT_Load_Glyph(faces_[f].face_, glyph_index, FT_LOAD_DEFAULT);
263
264             if(error != 0) return;
265
266             rotation_reference_glyph_ = glyph_index;
267             rotation_reference_face_ = faces_[f].face_;
268             setRotationOffset();
269             
270             clearCaches();
271         }
272     }
273
274     BBox Face::measure (const char* s)
275     {
276         BBox bbox;
277         char c;
278
279         if((c = *s++) != 0) 
280         {
281             bbox = measure((unsigned char)c);
282
283             for(c = *s; c != 0; c = *++s) 
284             {
285                 BBox char_bbox = measure((unsigned char)c);
286                 bbox += char_bbox;
287             }
288         }
289         // make sure the origin is at 0,0
290         if (bbox.x_min_ != 0)
291         {
292             bbox.x_max_ -= bbox.x_min_;
293             bbox.x_min_ = 0;
294         }
295         if (bbox.y_min_ != 0)
296         {
297             bbox.y_max_ -= bbox.y_min_;
298             bbox.y_min_ = 0;
299         }
300
301         return bbox;
302     }
303
304     BBox Face::measureRaw (const char* s)
305     {
306         BBox bbox;
307
308         for(char c = *s; c != 0; c = *++s) 
309         {
310             BBox char_bbox;
311
312             unsigned int f;
313             FT_UInt glyph_index = 0;
314
315             for(f=0; f<faces_.size(); f++) 
316             {
317                 glyph_index = FT_Get_Char_Index(faces_[f].face_, c);
318                 if(glyph_index != 0) break;
319             }
320
321             if(glyph_index == 0) continue;
322
323             FT_Error error = FT_Load_Glyph(faces_[f].face_, glyph_index, FT_LOAD_DEFAULT);
324             if(error != 0) continue;
325
326             FT_Glyph glyph;
327             error = FT_Get_Glyph(faces_[f].face_->glyph, &glyph);
328             if(error != 0) continue;
329
330             FT_BBox ft_bbox;
331             FT_Glyph_Get_CBox(glyph, ft_glyph_bbox_unscaled, &ft_bbox);
332
333             FT_Done_Glyph(glyph);
334
335             char_bbox = ft_bbox;
336             char_bbox.advance_ = faces_[f].face_->glyph->advance;
337
338             bbox += char_bbox;
339         }
340
341         return bbox;
342     }
343
344     BBox Face::measure (const wchar_t* s)
345     {
346         BBox bbox;
347         int i;
348
349         if(wstrlen(s) > 0) 
350         {
351             bbox = measure(s[0]);
352             for(i = 1; i < wstrlen(s); i++)
353             {
354                 BBox char_bbox = measure(s[i]);
355                 bbox += char_bbox;
356             }
357         }
358         // make sure the origin is at 0,0
359         if (bbox.x_min_ != 0)
360         {
361             bbox.x_max_ -= bbox.x_min_;
362             bbox.x_min_ = 0;
363         }
364         if (bbox.y_min_ != 0)
365         {
366             bbox.y_max_ -= bbox.y_min_;
367             bbox.y_min_ = 0;
368         }
369         return bbox;
370     }
371
372     BBox Face::measure (const wchar_t* format, double number)
373     {
374         return measure(format, number);
375     }
376
377     BBox Face::measureRaw (const wchar_t* s)
378     {
379         BBox bbox;
380         int i;
381
382         for(i = 0; i < wstrlen(s); i++)
383         {
384             BBox char_bbox;
385
386             unsigned int f;
387             FT_UInt glyph_index = 0;
388
389             for(f=0; f<faces_.size(); f++) 
390             {
391                 glyph_index = FT_Get_Char_Index(faces_[f].face_, s[i]);
392                 if(glyph_index != 0) break;
393             }
394
395             if(glyph_index == 0) 
396             {
397                 continue;
398             }
399
400             FT_Error error = FT_Load_Glyph(faces_[f].face_, glyph_index, FT_LOAD_DEFAULT);
401             if(error != 0) continue;
402
403             FT_Glyph glyph;
404             error = FT_Get_Glyph(faces_[f].face_->glyph, &glyph);
405             if(error != 0) continue;
406
407             FT_BBox ft_bbox;
408             FT_Glyph_Get_CBox(glyph, ft_glyph_bbox_unscaled, &ft_bbox);
409
410             FT_Done_Glyph(glyph);
411
412             char_bbox = ft_bbox;
413             char_bbox.advance_ = faces_[f].face_->glyph->advance;
414
415             bbox += char_bbox;
416         }
417
418         return bbox;
419     }
420     
421     // Measure the bounding box as if the (latin1) string were not rotated
422     BBox Face::measure_nominal (const char* s)
423     {
424         if(string_rotation_ == 0.) return measure(s);
425     
426         for(unsigned int f=0; f<faces_.size(); f++) FT_Set_Transform(faces_[f].face_, 0, 0);
427
428         BBox bbox = measure(s);
429
430         float angle;
431         if(string_rotation_<0.)
432             angle = 360.0f - fmod(fabs(string_rotation_), 360.f);
433         else 
434             angle = fmod(string_rotation_, 360.f);
435
436         FT_Matrix rotation_matrix;
437         FT_Vector sinus;
438
439         FT_Vector_Unit(&sinus, (FT_Angle)(angle * 0x10000L));
440
441         rotation_matrix.xx = sinus.x;
442         rotation_matrix.xy = -sinus.y;
443         rotation_matrix.yx = sinus.y;
444         rotation_matrix.yy = sinus.x;
445
446         for(unsigned int f=0; f<faces_.size(); f++) FT_Set_Transform(faces_[f].face_, &rotation_matrix, 0);
447
448         return bbox;
449     }
450
451     // Measure the bounding box as if the (UNICODE) string were not rotated
452     BBox Face::measure_nominal (const wchar_t* s)
453     {
454         if(string_rotation_ == 0.)return measure(s);
455
456         for(unsigned int f=0; f<faces_.size(); f++)FT_Set_Transform(faces_[f].face_, 0, 0);
457
458         BBox bbox = measure(s);
459
460         float angle;
461         if(string_rotation_<0.0) 
462             angle = 360.0f - fmod(fabs(string_rotation_), 360.f);
463         else 
464             angle = fmod(string_rotation_, 360.f);
465
466         FT_Matrix rotation_matrix;
467         FT_Vector sinus;
468
469         FT_Vector_Unit(&sinus, (FT_Angle)(angle * 0x10000L));
470
471         rotation_matrix.xx = sinus.x;
472         rotation_matrix.xy = -sinus.y;
473         rotation_matrix.yx = sinus.y;
474         rotation_matrix.yy = sinus.x;
475
476         for(unsigned int f=0; f<faces_.size(); f++)FT_Set_Transform(faces_[f].face_, &rotation_matrix, 0);
477
478         return bbox;
479     }
480
481     // Compile a (latin1) character glyph into a display list and cache
482     // it for later
483
484     GLuint Face::compile (unsigned char c)
485     {
486         // See if we've done it already
487         GDLCI fgi = glyph_dlists_.find(c);
488
489         if(fgi != glyph_dlists_.end())return fgi->second;
490
491         unsigned int f;
492         FT_UInt glyph_index = 0;
493
494         for(f=0; f<faces_.size(); f++)
495         {
496             glyph_index = FT_Get_Char_Index(faces_[f].face_, c);
497             if(glyph_index != 0) break;
498         }
499
500         if(glyph_index == 0)return 0;
501
502         GLuint dlist = compileGlyph(faces_[f].face_, glyph_index);
503         glyph_dlists_[ c ] = dlist;
504
505         return dlist;
506     }
507
508
509     // Compile a (UNICODE) character glyph into a display list and cache
510     // it for later
511     GLuint Face::compile (const wchar_t c)
512     {
513         // See if we've done it already
514         GDLCI fgi = glyph_dlists_.find(c);
515
516         if(fgi != glyph_dlists_.end())return fgi->second;
517
518         unsigned int f;
519         FT_UInt glyph_index = 0;
520
521         for(f=0; f<faces_.size(); f++)
522         {
523             glyph_index = FT_Get_Char_Index(faces_[f].face_, c);
524             if(glyph_index != 0) break;
525         }
526
527         if(glyph_index == 0)return 0;
528
529         GLuint dlist = compileGlyph(faces_[f].face_, glyph_index);
530
531         glyph_dlists_[ c ] = dlist;
532
533         return dlist;
534     }
535
536     // Assume the MODELVIEW matrix is already set and draw the (latin1)
537     // string.  Note: this routine now ignores almost all settings:
538     // including the position (both modelview and raster), color,
539     // justification and advance settings. Consider this to be the raw
540     // drawing routine for which you are responsible for most of the
541     // setup.
542     void Face::draw (const char* s)
543     {
544         DLCI character_display_list = character_display_lists_.begin();
545
546         for(char c = *s; c != 0; c = *++s)
547         {
548             if(character_display_list != character_display_lists_.end())
549             {
550                 glCallList(*character_display_list);
551                 character_display_list++;
552             }
553             draw((unsigned char)c);
554         }
555     }
556
557     // Assume the MODELVIEW matrix is already set and draw the (UNICODE)
558     // string.  Note: this routine now ignores almost all settings:
559     // including the position (both modelview and raster), color,
560     // justification and advance settings. Consider this to be the raw
561     // drawing routine for which you are responsible for most of the
562     // setup.
563     void Face::draw (const wchar_t* s)
564     {
565         DLCI character_display_list = character_display_lists_.begin();
566         int i;
567
568         for(i = 0; i < wstrlen(s); i++)
569         {
570             if(character_display_list != character_display_lists_.end())
571             {
572                 glCallList(*character_display_list);
573                 character_display_list++;
574             }
575             draw(s[i]);
576         }
577     }
578
579     // Assume the MODELVIEW matrix is already setup and draw the
580     // (latin1) character.
581     void Face::draw (unsigned char c)
582     {
583         // See if we've done it already
584         GDLCI fgi = glyph_dlists_.find(c);
585
586         if(fgi != glyph_dlists_.end()) 
587         {
588             glCallList(fgi->second);
589             return;
590         }
591
592         unsigned int f;
593         FT_UInt glyph_index = 0;
594
595         for(f=0; f<faces_.size(); f++)
596         {
597             glyph_index = FT_Get_Char_Index(faces_[f].face_, c);
598             if(glyph_index != 0) break;
599         }
600
601         if(glyph_index == 0) return;
602
603         if(compile_mode_ == COMPILE)
604         {
605             GLuint dlist = compile(c);
606             glCallList(dlist);
607         }
608         else renderGlyph(faces_[f].face_, glyph_index);
609     }
610
611     // Assume the MODELVIEW matrix is already setup and draw the
612     // (UNICODE) character.
613
614     void Face::draw (const wchar_t c)
615     {
616         // See if we've done it already
617         GDLCI fgi = glyph_dlists_.find(c);
618
619         if(fgi != glyph_dlists_.end()) 
620         {
621             glCallList(fgi->second);
622             return;
623         }
624
625         unsigned int f;
626         FT_UInt glyph_index = 0;
627
628         for(f=0; f<faces_.size(); f++)
629         {
630             glyph_index = FT_Get_Char_Index(faces_[f].face_, c);
631             if(glyph_index != 0) break;
632         }
633
634         if(glyph_index == 0) return;
635
636         if(compile_mode_ == COMPILE)
637         {
638             GLuint dlist = compile(c);
639             glCallList(dlist);
640         }
641         else renderGlyph(faces_[f].face_, glyph_index);
642     }
643
644     // Draw the (latin1) character at the given position. The MODELVIEW
645     // matrix is modified by the glyph advance.
646     void Face::draw (GLfloat x, GLfloat y, unsigned char c)
647     {
648         glTranslatef(x, y, 0.);
649
650         glColor4f(foreground_color_[R], foreground_color_[G], foreground_color_[B], foreground_color_[A]);
651
652         glRasterPos3i(0, 0, 0);
653
654         draw(c);
655     }
656
657     // Draw the (latin1) character at the given position. The MODELVIEW
658     // matrix is modified by the glyph advance.
659     void Face::draw (GLfloat x, GLfloat y, GLfloat z, unsigned char c)
660     {
661         glTranslatef(x, y, z);
662
663         glColor4f(foreground_color_[R], foreground_color_[G], foreground_color_[B], foreground_color_[A]);
664
665         glRasterPos3i(0, 0, 0);
666
667         draw(c);
668     }
669
670     // Draw the (UNICODE) character at the given position. The MODELVIEW
671     // matrix is modified by the glyph advance.
672     void Face::draw (GLfloat x, GLfloat y, wchar_t c)
673     {
674         glTranslatef(x, y, 0.);
675
676         glColor4f(foreground_color_[R], foreground_color_[G], foreground_color_[B],
677                 foreground_color_[A]);
678
679         glRasterPos3i(0, 0, 0);
680
681         draw(c);
682     }
683
684     // Draw the (UNICODE) character at the given position. The MODELVIEW
685     // matrix is modified by the glyph advance.
686     void Face::draw (GLfloat x, GLfloat y, GLfloat z, wchar_t c)
687     {
688         glTranslatef(x, y, z);
689
690         glColor4f(foreground_color_[R], foreground_color_[G], foreground_color_[B], foreground_color_[A]);
691
692         glRasterPos3i(0, 0, 0);
693
694         draw(c);
695     }
696
697
698     // Draw the (latin1) string at the given position.
699     void Face::draw (GLfloat x, GLfloat y, const char* s, float *sizebox)
700     {
701         // sizebox is xmin,ymin, xmax,ymax
702         if(!advance_) glPushMatrix();
703
704         if(horizontal_justification_ != ORIGIN || vertical_justification_ != BASELINE)
705         {
706             glPushMatrix();
707
708             GLfloat dx = 0, dy = 0;
709
710             switch (horizontal_justification_)
711             {
712                 case LEFT:   dx = -sizebox[0] + 1; break;
713                 case CENTER: dx = -(sizebox[0] + sizebox[2])/ 2.0f; break;
714                 case RIGHT:  dx = -sizebox[2] - 1; break;
715                 default: break;
716             }
717             switch (vertical_justification_)
718             {
719                 case BOTTOM: dy = -sizebox[1] + 1; break;
720                 case MIDDLE: dy = -(sizebox[1] + sizebox[3])/ 2.0f; break;
721                 case TOP: dy = -sizebox[3] - 1; break;
722                 default: break;
723             }
724
725             // There is probably a less expensive way to compute this
726             glRotatef(string_rotation_, 0., 0., 1.);
727             glTranslatef(dx, dy, 0);
728             glRotatef(-string_rotation_, 0., 0., 1.);
729         }
730
731         glTranslatef(x, y, 0.);
732
733         glColor4f(foreground_color_[R], foreground_color_[G], foreground_color_[B], foreground_color_[A]);
734
735         glRasterPos3i(0, 0, 0);
736
737         draw(s);
738
739         if(horizontal_justification_ != ORIGIN || vertical_justification_ != BASELINE) glPopMatrix();
740
741         if(!advance_) glPopMatrix();
742     }
743
744     // Draw the (latin1) string at the given position.
745     void Face::draw (GLfloat x, GLfloat y, GLfloat z, const char* s)
746     {
747         if(!advance_) glPushMatrix();
748
749         if(horizontal_justification_ != ORIGIN || vertical_justification_ != BASELINE)
750         {
751             glPushMatrix();
752
753             BBox bbox = measure_nominal(s);
754
755             GLfloat dx = 0, dy = 0;
756
757             switch (horizontal_justification_)
758             {
759                 case LEFT:   dx = -bbox.x_min_; break;
760                 case CENTER: dx = -(bbox.x_min_ + bbox.x_max_)/ 2.0f; break;
761                 case RIGHT: dx = -bbox.x_max_; break;
762                 default: break;
763             }
764             switch (vertical_justification_)
765             {
766                 case BOTTOM: dy = -bbox.y_min_; break;
767                 case MIDDLE: dy = -(bbox.y_min_ + bbox.y_max_)/ 2.0f; break;
768                 case TOP:    dy = -bbox.y_max_; break;
769                 default: break;
770             }
771
772             // There is probably a less expensive way to compute this
773             glRotatef(string_rotation_, 0., 0., 1.);
774             glTranslatef(dx, dy, 0);
775             glRotatef(-string_rotation_, 0., 0., 1.);
776         }
777
778         glTranslatef(x, y, z);
779
780         glColor4f(foreground_color_[R], foreground_color_[G], foreground_color_[B], foreground_color_[A]);
781
782         glRasterPos3i(0, 0, 0);
783
784         draw(s);
785
786         if(horizontal_justification_ != ORIGIN || vertical_justification_ != BASELINE) glPopMatrix();
787
788         if(!advance_) glPopMatrix();
789     }
790
791     // Draw the (UNICODE) string at the given position.
792     void Face::draw (GLfloat x, GLfloat y, const wchar_t* s)
793     {
794         if(!advance_)
795             glPushMatrix();
796
797         if(horizontal_justification_!=ORIGIN||vertical_justification_!=BASELINE)
798             {
799             glPushMatrix();
800
801             BBox bbox = measure_nominal(s);
802
803             GLfloat dx = 0, dy = 0;
804
805             switch (horizontal_justification_)
806                 {
807                 case LEFT:
808                     dx = -bbox.x_min_; break;
809                 case CENTER:
810                     dx = -(bbox.x_min_ + bbox.x_max_)/ 2.0f; break;
811                 case RIGHT:
812                     dx = -bbox.x_max_; break;
813                 default:
814                     break;
815                 }
816             switch (vertical_justification_)
817                 {
818                 case BOTTOM:
819                     dy = -bbox.y_min_; break;
820                 case MIDDLE:
821                     dy = -(bbox.y_min_ + bbox.y_max_)/ 2.0f; break;
822                 case TOP:
823                     dy = -bbox.y_max_; break;
824                 default:
825                     break;
826                 }
827
828             // There is probably a less expensive way to compute this
829             glRotatef(string_rotation_, 0., 0., 1.);
830             glTranslatef(dx, dy, 0);
831             glRotatef(-string_rotation_, 0., 0., 1.);
832             }
833
834             glTranslatef(x, y, 0.);
835
836             glColor4f(foreground_color_[R], foreground_color_[G], foreground_color_[B],
837                         foreground_color_[A]);
838
839             glRasterPos3i(0, 0, 0);
840
841             draw(s);
842
843             if(horizontal_justification_ != ORIGIN ||
844                 vertical_justification_ != BASELINE)
845                 glPopMatrix();
846
847             if(!advance_)
848                 glPopMatrix();
849     }
850
851     // Draw the (UNICODE) string at the given position.
852     void Face::draw (GLfloat x, GLfloat y, GLfloat z, const wchar_t* s)
853     {
854         if(!advance_) glPushMatrix();
855
856         if(horizontal_justification_!= ORIGIN||vertical_justification_!= BASELINE)
857             {
858             glPushMatrix();
859
860             // In 3D, we need to exert more care in the computation of the
861             // bounding box of the text. NOTE: Needs to be fixed up for
862             // polygonal faces, too...
863
864             BBox bbox;
865             // Code from measure_nominal, but changed to use measureRaw instead
866             if(string_rotation_ == 0.)  bbox = measureRaw(s);
867             else
868                 {
869                 for(unsigned int f=0; f<faces_.size(); f++)
870                     FT_Set_Transform(faces_[f].face_, 0, 0);
871
872                 bbox = measureRaw(s);
873
874                 float angle;
875                 if(string_rotation_<0.0)
876                     angle = 360.0f - fmod(fabs(string_rotation_), 360.f);
877                 else
878                     angle = fmod(string_rotation_, 360.f);
879
880                 FT_Matrix rotation_matrix;
881                 FT_Vector sinus;
882
883                 FT_Vector_Unit(&sinus, (FT_Angle)(angle * 0x10000L));
884
885                 rotation_matrix.xx = sinus.x;
886                 rotation_matrix.xy = -sinus.y;
887                 rotation_matrix.yx = sinus.y;
888                 rotation_matrix.yy = sinus.x;
889
890                 for(unsigned int f=0; f<faces_.size(); f++)
891                     FT_Set_Transform(faces_[f].face_, &rotation_matrix, 0);
892                 }
893
894             GLfloat dx = 0, dy = 0;
895
896             switch (horizontal_justification_)
897                 {
898                 case LEFT:
899                     dx = bbox.x_min_; break;
900                 case CENTER:
901                     dx = (bbox.x_min_ + bbox.x_max_)/ 2; break;
902                 case RIGHT:
903                     dx = bbox.x_max_; break;
904                 default:
905                     break;
906                 }
907             switch (vertical_justification_)
908                 {
909                 case BOTTOM:
910                     dy = bbox.y_min_; break;
911                 case MIDDLE:
912                     dy = (bbox.y_min_ + bbox.y_max_)/2; break;
913                 case TOP:
914                     dy = bbox.y_max_; break;
915                 default:
916                     break;
917                 }
918
919             GLint viewport[4];
920             GLdouble modelview[16], projection[16];
921
922             glGetIntegerv(GL_VIEWPORT, viewport);
923             glGetDoublev(GL_MODELVIEW_MATRIX, modelview);
924             glGetDoublev(GL_PROJECTION_MATRIX, projection);
925
926             GLdouble x0, y0, z0;
927             gluUnProject(0, 0, 0, modelview, projection, viewport, &x0, &y0, &z0);
928
929             GLdouble dx_m, dy_m, dz_m;
930             gluUnProject(dx, dy, 0., modelview, projection, viewport,&dx_m,&dy_m,&dz_m);
931
932             glTranslated(x0-dx_m, y0-dy_m, z0-dz_m);
933             }
934
935         glTranslatef(x, y, z);
936         glColor4f(foreground_color_[R], foreground_color_[G], foreground_color_[B], foreground_color_[A]);
937         glRasterPos3i(0, 0, 0);
938         draw(s);
939
940         if(horizontal_justification_!=ORIGIN||vertical_justification_!= BASELINE)
941             glPopMatrix();
942
943         if(!advance_)
944             glPopMatrix();
945     }
946
947     Raster::Raster (const char* filename, float point_size, FT_UInt resolution)
948         : Face(filename, point_size, resolution)
949     {
950         if(!isValid()) return;
951
952         init();
953     }
954
955     Raster::Raster (FT_Face face, float point_size, FT_UInt resolution)
956         : Face(face, point_size, resolution)
957     {
958         init();
959     }
960
961     void Raster::init (void)
962     {
963         character_rotation_z_ = 0;
964         setCharSize();
965         setCharacterRotationReference('o');
966     }
967
968     Raster::~Raster (void)
969     {
970         clearCaches();
971     }
972
973     void Raster::setCharacterRotationZ (GLfloat character_rotation_z)
974     {
975         if(character_rotation_z != character_rotation_z_)
976         {
977             character_rotation_z_ = character_rotation_z;
978             clearCaches();
979         }
980     }
981
982     double Raster::height (void)const
983     {
984         if(faces_[0].face_->height > 0) return faces_[0].face_->height / 64.;
985         else return faces_[0].face_->size->metrics.y_ppem;
986     }
987
988     BBox Raster::measure (unsigned char c)
989     {
990         BBox bbox;
991         
992         // For starters, just get the unscaled glyph bounding box
993         unsigned int f;
994         FT_UInt glyph_index = 0;
995
996         for(f=0; f<faces_.size(); f++)
997         {
998             glyph_index = FT_Get_Char_Index(faces_[f].face_, c);
999             if(glyph_index != 0) break;
1000         }
1001
1002         if(glyph_index == 0) return bbox;
1003
1004         FT_Error error = FT_Load_Glyph(faces_[f].face_, glyph_index, FT_LOAD_DEFAULT);
1005         if(error != 0) return bbox;
1006
1007         FT_Glyph glyph;
1008         error = FT_Get_Glyph(faces_[f].face_->glyph, &glyph);
1009         if(error != 0) return bbox;
1010
1011         FT_BBox ft_bbox;
1012         FT_Glyph_Get_CBox(glyph, ft_glyph_bbox_unscaled, &ft_bbox);
1013
1014         FT_Done_Glyph(glyph);
1015
1016         bbox = ft_bbox;
1017         bbox.advance_ = faces_[f].face_->glyph->advance;
1018     
1019         // In order to be accurate regarding the placement of text not
1020         // aligned at the glyph's origin (CENTER/MIDDLE), the bounding box
1021         // of the raster format has to be projected back into the
1022         // view's coordinates
1023         GLint viewport[4];
1024         GLdouble modelview[16], projection[16];
1025
1026         glGetIntegerv(GL_VIEWPORT, viewport);
1027         glGetDoublev(GL_MODELVIEW_MATRIX, modelview);
1028         glGetDoublev(GL_PROJECTION_MATRIX, projection);
1029
1030         // Well, first we have to get the Origin, since that is the basis
1031         // of the bounding box
1032         GLdouble x0, y0, z0;
1033         gluUnProject(0., 0., 0., modelview, projection, viewport, &x0, &y0, &z0);
1034
1035         GLdouble x, y, z;
1036         gluUnProject(bbox.x_min_, bbox.y_min_, 0., modelview, projection, viewport, &x, &y, &z);
1037         bbox.x_min_ = (float) (x - x0);
1038         bbox.y_min_ = (float) (y - y0);
1039
1040         gluUnProject(bbox.x_max_, bbox.y_max_, 0., modelview, projection, viewport, &x, &y, &z);
1041         bbox.x_max_ = (float) (x - x0);
1042         bbox.y_max_ = (float) (y - y0);
1043
1044         gluUnProject(bbox.advance_.dx_, bbox.advance_.dy_, 0., modelview, projection, viewport, &x, &y, &z);
1045         bbox.advance_.dx_ = (float) (x - x0);
1046         bbox.advance_.dy_ = (float) (y - y0);
1047
1048         return bbox;
1049     }
1050
1051     BBox Raster::measure (wchar_t c)
1052     {
1053         BBox bbox;
1054         
1055         // For starters, just get the unscaled glyph bounding box
1056         unsigned int f;
1057         FT_UInt glyph_index = 0;
1058
1059         for(f=0; f<faces_.size(); f++)
1060         {
1061             glyph_index = FT_Get_Char_Index(faces_[f].face_, c);
1062             if(glyph_index != 0) break;
1063         }
1064
1065         if(glyph_index == 0) return bbox;
1066
1067         FT_Error error = FT_Load_Glyph(faces_[f].face_, glyph_index,
1068                                         FT_LOAD_DEFAULT);
1069         if(error != 0) return bbox;
1070
1071         FT_Glyph glyph;
1072         error = FT_Get_Glyph(faces_[f].face_->glyph, &glyph);
1073         if(error != 0) return bbox;
1074
1075         FT_BBox ft_bbox;
1076         FT_Glyph_Get_CBox(glyph, ft_glyph_bbox_unscaled, &ft_bbox);
1077
1078         FT_Done_Glyph(glyph);
1079
1080         bbox = ft_bbox;
1081         bbox.advance_ = faces_[f].face_->glyph->advance;
1082
1083         // In order to be accurate regarding the placement of text not
1084         // aligned at the glyph's origin (CENTER/MIDDLE), the bounding box
1085         // of the raster format has to be projected back into the
1086         // view's coordinates
1087         GLint viewport[4];
1088         GLdouble modelview[16], projection[16];
1089
1090         glGetIntegerv(GL_VIEWPORT, viewport);
1091         glGetDoublev(GL_MODELVIEW_MATRIX, modelview);
1092         glGetDoublev(GL_PROJECTION_MATRIX, projection);
1093
1094         // Well, first we have to get the Origin, since that is the basis
1095         // of the bounding box
1096         GLdouble x0, y0, z0;
1097         gluUnProject(0., 0., 0., modelview, projection, viewport, &x0, &y0, &z0);
1098
1099         GLdouble x, y, z;
1100         gluUnProject(bbox.x_min_, bbox.y_min_, 0., modelview, projection, viewport, &x, &y, &z);
1101         bbox.x_min_ = (float) (x - x0);
1102         bbox.y_min_ = (float) (y - y0);
1103
1104         gluUnProject(bbox.x_max_, bbox.y_max_, 0., modelview, projection, viewport, &x, &y, &z);
1105         bbox.x_max_ = (float) (x - x0);
1106         bbox.y_max_ = (float) (y - y0);
1107
1108         gluUnProject(bbox.advance_.dx_, bbox.advance_.dy_, 0., modelview, projection, viewport, &x, &y, &z);
1109         bbox.advance_.dx_ = (float) (x - x0);
1110         bbox.advance_.dy_ = (float) (y - y0);
1111
1112         return bbox;
1113     }
1114
1115     GLuint Raster::compileGlyph (FT_Face face, FT_UInt glyph_index)
1116     {
1117         GLuint dlist = glGenLists(1);
1118         glNewList(dlist, GL_COMPILE);
1119
1120         renderGlyph(face, glyph_index);
1121
1122         glEndList();
1123
1124         return dlist;
1125     }
1126
1127     void Raster::setCharSize (void)
1128     {
1129         FT_Error error;
1130         for(unsigned int i=0; i<faces_.size(); i++)
1131         {
1132             error = FT_Set_Char_Size(faces_[i].face_,(FT_F26Dot6)(point_size_ * 64),(FT_F26Dot6)(point_size_ * 64),resolution_,resolution_);
1133             if(error != 0) return;
1134         }
1135
1136         if(rotation_reference_glyph_ != 0) setRotationOffset();
1137     }
1138
1139     void Raster::setRotationOffset (void)
1140     {
1141         FT_Error error = FT_Load_Glyph(rotation_reference_face_, rotation_reference_glyph_, FT_LOAD_RENDER);
1142
1143         if(error != 0) return;
1144
1145         rotation_offset_y_ = rotation_reference_face_->glyph->bitmap.rows / 2.0f;
1146     }
1147
1148     void Raster::clearCaches (void)
1149     {
1150         GDLI fgi = glyph_dlists_.begin();
1151
1152         for(; fgi != glyph_dlists_.end(); ++fgi)
1153         {
1154             glDeleteLists(fgi->second, 1);
1155         }
1156
1157         glyph_dlists_.clear();
1158     }
1159
1160     Monochrome::Monochrome (const char* filename, float point_size, FT_UInt resolution)
1161         : Raster(filename, point_size, resolution)
1162     {
1163         return;
1164     }
1165
1166     Monochrome::Monochrome (FT_Face face, float point_size, FT_UInt resolution)
1167     : Raster(face, point_size, resolution)
1168     {
1169         return;
1170     }
1171
1172     Monochrome::~Monochrome (void)
1173     {
1174         return;
1175     }
1176
1177     GLubyte* Monochrome::invertBitmap (const FT_Bitmap& bitmap)
1178     {
1179         // In FreeType 2.0.9, the pitch of bitmaps was rounded up to an
1180         // even number. In general, this disagrees with what we had been
1181         // using for OpenGL.
1182         int width = bitmap.width / 8 + ((bitmap.width & 7)> 0 ? 1 : 0);
1183
1184         GLubyte* inverse = new GLubyte[ bitmap.rows * width ];
1185         GLubyte* inverse_ptr = inverse;
1186
1187         for(int r=0; r<bitmap.rows; r++)
1188         {
1189             GLubyte* bitmap_ptr = &bitmap.buffer[bitmap.pitch * (bitmap.rows - r - 1)];
1190
1191             memmove(inverse_ptr, bitmap_ptr, width);
1192             inverse_ptr += width;
1193             bitmap_ptr += width;
1194         }
1195
1196         return inverse;
1197     }
1198
1199     void Monochrome::renderGlyph (FT_Face face, FT_UInt glyph_index)
1200     {
1201         // Start by retrieving the glyph's data.
1202         FT_Error error = FT_Load_Glyph(face, glyph_index, FT_LOAD_DEFAULT);
1203
1204         if(error != 0) return;
1205
1206         FT_Glyph original_glyph;
1207         FT_Glyph glyph;
1208
1209         error = FT_Get_Glyph(face->glyph, &original_glyph);
1210
1211         if(error != 0) return;
1212
1213         error = FT_Glyph_Copy(original_glyph, &glyph);
1214
1215         FT_Done_Glyph(original_glyph);
1216
1217         if(error != 0) return;
1218
1219         // If the individual characters are rotated (as distinct from string
1220         // rotation), then apply that extra rotation here. This is equivalent
1221         // to the sequence
1222         // glTranslate(x_center,y_center);
1223         // glRotate(angle);
1224         // glTranslate(-x_center,-y_center);
1225         // which is used for the polygonal styles. The deal with the raster
1226         // styles is that you must retain the advance from the string rotation
1227         // so that the glyphs are laid out properly. So, we make a copy of
1228         // the string rotated glyph, and then rotate that and add back an
1229         // additional offset to (in effect) restore the proper origin and
1230         // advance of the glyph.
1231
1232         if(character_rotation_z_ != 0.)
1233         {
1234             FT_Matrix rotation_matrix;
1235             FT_Vector sinus;
1236
1237             FT_Vector_Unit(&sinus, (FT_Angle)(character_rotation_z_ * 0x10000L));
1238
1239             rotation_matrix.xx = sinus.x;
1240             rotation_matrix.xy = -sinus.y;
1241             rotation_matrix.yx = sinus.y;
1242             rotation_matrix.yy = sinus.x;
1243
1244             FT_Vector original_offset, rotation_offset;
1245
1246             original_offset.x = (face->glyph->metrics.width / 2 + face->glyph->metrics.horiBearingX)/ 64 * 0x10000L;
1247             original_offset.y = (FT_Pos)(rotation_offset_y_ * 0x10000L);
1248
1249             rotation_offset = original_offset;
1250
1251             FT_Vector_Rotate(&rotation_offset, (FT_Angle)(character_rotation_z_ * 0x10000L));
1252
1253             rotation_offset.x = original_offset.x - rotation_offset.x;
1254             rotation_offset.y = original_offset.y - rotation_offset.y;
1255
1256             rotation_offset.x /= 1024;
1257             rotation_offset.y /= 1024;
1258
1259             error = FT_Glyph_Transform(glyph, &rotation_matrix, &rotation_offset);
1260         }
1261
1262         error = FT_Glyph_To_Bitmap(&glyph, FT_RENDER_MODE_MONO, 0, 1);
1263
1264         if(error != 0)
1265         {
1266             FT_Done_Glyph(glyph);
1267             return;
1268         }
1269
1270         FT_BitmapGlyph bitmap_glyph = (FT_BitmapGlyph) glyph;
1271
1272         // Evidently, in FreeType2, you can only get "upside-down" bitmaps and
1273         // OpenGL won't invert a bitmap with PixelZoom, so we have to invert the
1274         // glyph's bitmap ourselves.
1275
1276         GLubyte* inverted_bitmap = invertBitmap(bitmap_glyph->bitmap);
1277
1278         glBitmap(bitmap_glyph->bitmap.width, bitmap_glyph->bitmap.rows,
1279                  (GLfloat) -bitmap_glyph->left,
1280                  (GLfloat) (bitmap_glyph->bitmap.rows - bitmap_glyph->top),
1281                  face->glyph->advance.x / 64.0f,
1282                  face->glyph->advance.y / 64.0f,
1283                  inverted_bitmap);
1284
1285         FT_Done_Glyph(glyph);
1286
1287         delete[] inverted_bitmap;
1288     }
1289
1290 } // close OGLFT namespace
1291