Panda3D
freetypeFace.cxx
1 // Filename: freetypeFace.cxx
2 // Created by: gogg (16Nov09)
3 //
4 ////////////////////////////////////////////////////////////////////
5 //
6 // PANDA 3D SOFTWARE
7 // Copyright (c) Carnegie Mellon University. All rights reserved.
8 //
9 // All use of this software is subject to the terms of the revised BSD
10 // license. You should have received a copy of this license along
11 // with this source code in a file named "LICENSE."
12 //
13 ////////////////////////////////////////////////////////////////////
14 
15 #include "freetypeFace.h"
16 
17 #ifdef HAVE_FREETYPE
18 
19 #include "config_pnmtext.h"
20 
21 FT_Library FreetypeFace::_ft_library;
22 bool FreetypeFace::_ft_initialized = false;
23 bool FreetypeFace::_ft_ok = false;
24 
25 TypeHandle FreetypeFace::_type_handle;
26 
27 ////////////////////////////////////////////////////////////////////
28 // Function: FreetypeFace::Constructor
29 // Access: Public
30 // Description:
31 ////////////////////////////////////////////////////////////////////
32 FreetypeFace::
33 FreetypeFace() : _lock("FreetypeFace::_lock") {
34  _face = NULL;
35  _char_size = 0;
36  _dpi = 0;
37  _pixel_width = 0;
38  _pixel_height = 0;
39 
40  if (!_ft_initialized) {
41  initialize_ft_library();
42  }
43 }
44 
45 ////////////////////////////////////////////////////////////////////
46 // Function: FreetypeFace::Destructor
47 // Access: Public
48 // Description:
49 ////////////////////////////////////////////////////////////////////
50 FreetypeFace::
51 ~FreetypeFace() {
52  if (_face != NULL){
53  FT_Done_Face(_face);
54  }
55 }
56 
57 ////////////////////////////////////////////////////////////////////
58 // Function: FreetypeFace::acquire_face
59 // Access: Public
60 // Description: Retrieves the internal freetype face, and also
61 // acquires the lock. The freetype face is set to the
62 // indicated size, either as a char_size and dpi, or as
63 // a specific pixel_width and height, before returning.
64 //
65 // You must call release_face() when you are done using
66 // it, to release the lock.
67 ////////////////////////////////////////////////////////////////////
68 FT_Face FreetypeFace::
69 acquire_face(int char_size, int dpi, int pixel_width, int pixel_height) {
70  _lock.acquire();
71 
72  if (pixel_height != 0) {
73  if (pixel_height != _pixel_height || pixel_width != _pixel_width) {
74  _char_size = 0;
75  _dpi = 0;
76  _pixel_height = pixel_height;
77  _pixel_width = pixel_width;
78  FT_Set_Pixel_Sizes(_face, _pixel_width, _pixel_height);
79  }
80  } else {
81  if (char_size != _char_size || dpi != _dpi) {
82  _char_size = char_size;
83  _dpi = dpi;
84  _pixel_height = 0;
85  _pixel_width = 0;
86  if (_char_size != 0) {
87  FT_Set_Char_Size(_face, _char_size, _char_size, _dpi, _dpi);
88  }
89  }
90  }
91 
92  return _face;
93 }
94 
95 ////////////////////////////////////////////////////////////////////
96 // Function: FreetypeFace::release_face
97 // Access: Public
98 // Description: Releases the lock acquired by a previous call to
99 // acquire_face(), and allows another thread to use the
100 // face.
101 ////////////////////////////////////////////////////////////////////
102 void FreetypeFace::
103 release_face(FT_Face face) {
104  nassertv(_face == face);
105  _lock.release();
106 }
107 
108 ////////////////////////////////////////////////////////////////////
109 // Function: FreetypeFace::set_face
110 // Access: Public
111 // Description: Replaces the internal freetype face.
112 ////////////////////////////////////////////////////////////////////
113 void FreetypeFace::
114 set_face(FT_Face face) {
115  MutexHolder holder(_lock);
116 
117  if (_face != NULL){
118  FT_Done_Face(_face);
119  }
120  _face = face;
121  _char_size = 0;
122  _dpi = 0;
123  _pixel_width = 0;
124  _pixel_height = 0;
125 
126  _name = _face->family_name;
127  if (_face->style_name != NULL) {
128  _name += " ";
129  _name += _face->style_name;
130  }
131 
132  pnmtext_cat.info()
133  << "Loaded font " << _name << "\n";
134 
135  if (pnmtext_cat.is_debug()) {
136  pnmtext_cat.debug()
137  << _name << " has " << _face->num_charmaps << " charmaps:\n";
138  for (int i = 0; i < _face->num_charmaps; i++) {
139  pnmtext_cat.debug(false) << " " << (void *)_face->charmaps[i];
140  }
141  pnmtext_cat.debug(false) << "\n";
142  pnmtext_cat.debug()
143  << "default charmap is " << (void *)_face->charmap << "\n";
144  }
145  if (_face->charmap == NULL) {
146  // If for some reason FreeType didn't set us up a charmap,
147  // then set it up ourselves.
148  if (_face->num_charmaps == 0) {
149  pnmtext_cat.warning()
150  << _name << " has no charmaps available.\n";
151  } else {
152  pnmtext_cat.warning()
153  << _name << " has no default Unicode charmap.\n";
154  if (_face->num_charmaps > 1) {
155  pnmtext_cat.warning()
156  << "Arbitrarily choosing first of "
157  << _face->num_charmaps << " charmaps.\n";
158  }
159  FT_Set_Charmap(_face, _face->charmaps[0]);
160  }
161  }
162 }
163 
164 ////////////////////////////////////////////////////////////////////
165 // Function: FreetypeFace::initialize_ft_library
166 // Access: Private, Static
167 // Description: Should be called exactly once to initialize the
168 // FreeType library.
169 ////////////////////////////////////////////////////////////////////
170 void FreetypeFace::
171 initialize_ft_library() {
172  if (!_ft_initialized) {
173  int error = FT_Init_FreeType(&_ft_library);
174  _ft_initialized = true;
175  if (error) {
176  pnmtext_cat.error()
177  << "Unable to initialize FreeType; dynamic fonts will not load.\n";
178  } else {
179  _ft_ok = true;
180  }
181  }
182 }
183 
184 #endif // HAVE_FREETYPE
A lightweight C++ object whose constructor calls acquire() and whose destructor calls release() on a ...
Definition: mutexHolder.h:29
TypeHandle is the identifier used to differentiate C++ class types.
Definition: typeHandle.h:85