Panda3D
textProperties.cxx
1 // Filename: textProperties.cxx
2 // Created by: drose (06Apr04)
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 "textProperties.h"
16 #include "config_text.h"
17 #include "default_font.h"
18 #include "dynamicTextFont.h"
19 #include "staticTextFont.h"
20 #include "bamFile.h"
21 #include "fontPool.h"
22 
23 PT(TextFont) TextProperties::_default_font;
24 bool TextProperties::_loaded_default_font = false;
25 
26 TypeHandle TextProperties::_type_handle;
27 
28 ////////////////////////////////////////////////////////////////////
29 // Function: TextProperties::Constructor
30 // Access: Published
31 // Description:
32 ////////////////////////////////////////////////////////////////////
33 TextProperties::
34 TextProperties() {
35  _specified = 0;
36 
37  _small_caps = text_small_caps;
38  _small_caps_scale = text_small_caps_scale;
39  _slant = 0.0f;
40  _underscore = false;
41  _underscore_height = 0.0f;
42  _align = A_left;
43  _indent_width = 0.0f;
44  _wordwrap_width = 0.0f;
45  _preserve_trailing_whitespace = false;
46  _text_color.set(1.0f, 1.0f, 1.0f, 1.0f);
47  _shadow_color.set(0.0f, 0.0f, 0.0f, 1.0f);
48  _shadow_offset.set(0.0f, 0.0f);
49  _draw_order = 1;
50  _tab_width = text_tab_width;
51  _glyph_scale = 1.0f;
52  _glyph_shift = 0.0f;
53  _text_scale = 1.0f;
54 }
55 
56 ////////////////////////////////////////////////////////////////////
57 // Function: TextProperties::Copy Constructor
58 // Access: Published
59 // Description:
60 ////////////////////////////////////////////////////////////////////
61 TextProperties::
62 TextProperties(const TextProperties &copy) {
63  (*this) = copy;
64 }
65 
66 ////////////////////////////////////////////////////////////////////
67 // Function: TextProperties::Copy Assignment Operator
68 // Access: Published
69 // Description:
70 ////////////////////////////////////////////////////////////////////
71 void TextProperties::
72 operator = (const TextProperties &copy) {
73  _specified = copy._specified;
74 
75  _font = copy._font;
76  _small_caps = copy._small_caps;
77  _small_caps_scale = copy._small_caps_scale;
78  _slant = copy._slant;
79  _underscore = copy._underscore;
80  _underscore_height = copy._underscore_height;
81  _align = copy._align;
82  _indent_width = copy._indent_width;
83  _wordwrap_width = copy._wordwrap_width;
84  _preserve_trailing_whitespace = copy._preserve_trailing_whitespace;
85  _text_color = copy._text_color;
86  _shadow_color = copy._shadow_color;
87  _shadow_offset = copy._shadow_offset;
88  _bin = copy._bin;
89  _draw_order = copy._draw_order;
90  _tab_width = copy._tab_width;
91  _glyph_scale = copy._glyph_scale;
92  _glyph_shift = copy._glyph_shift;
93  _text_scale = copy._text_scale;
94 }
95 
96 ////////////////////////////////////////////////////////////////////
97 // Function: TextProperties::operator ==
98 // Access: Published
99 // Description:
100 ////////////////////////////////////////////////////////////////////
101 bool TextProperties::
102 operator == (const TextProperties &other) const {
103  if (_specified != other._specified) {
104  return false;
105  }
106 
107  if ((_specified & F_has_font) && _font != other._font) {
108  return false;
109  }
110  if ((_specified & F_has_small_caps) && _small_caps != other._small_caps) {
111  return false;
112  }
113  if ((_specified & F_has_small_caps_scale) && _small_caps_scale != other._small_caps_scale) {
114  return false;
115  }
116  if ((_specified & F_has_slant) && _slant != other._slant) {
117  return false;
118  }
119  if ((_specified & F_has_underscore) && _underscore != other._underscore) {
120  return false;
121  }
122  if ((_specified & F_has_underscore_height) && _underscore_height != other._underscore_height) {
123  return false;
124  }
125  if ((_specified & F_has_align) && _align != other._align) {
126  return false;
127  }
128  if ((_specified & F_has_indent) && _indent_width != other._indent_width) {
129  return false;
130  }
131  if ((_specified & F_has_wordwrap) && _wordwrap_width != other._wordwrap_width) {
132  return false;
133  }
134  if ((_specified & F_has_preserve_trailing_whitespace) && _preserve_trailing_whitespace != other._preserve_trailing_whitespace) {
135  return false;
136  }
137  if ((_specified & F_has_text_color) && _text_color != other._text_color) {
138  return false;
139  }
140  if ((_specified & F_has_text_color) && _text_color != other._text_color) {
141  return false;
142  }
143  if ((_specified & F_has_shadow_color) && _shadow_color != other._shadow_color) {
144  return false;
145  }
146  if ((_specified & F_has_shadow) && _shadow_offset != other._shadow_offset) {
147  return false;
148  }
149  if ((_specified & F_has_bin) && _bin != other._bin) {
150  return false;
151  }
152  if ((_specified & F_has_draw_order) && _draw_order != other._draw_order) {
153  return false;
154  }
155  if ((_specified & F_has_tab_width) && _tab_width != other._tab_width) {
156  return false;
157  }
158  if ((_specified & F_has_glyph_scale) && _glyph_scale != other._glyph_scale) {
159  return false;
160  }
161  if ((_specified & F_has_glyph_shift) && _glyph_shift != other._glyph_shift) {
162  return false;
163  }
164  if ((_specified & F_has_text_scale) && _text_scale != other._text_scale) {
165  return false;
166  }
167  return true;
168 }
169 
170 ////////////////////////////////////////////////////////////////////
171 // Function: TextProperties::clear
172 // Access: Published
173 // Description: Unsets all properties that have been specified so
174 // far, and resets the TextProperties structure to its
175 // initial empty state.
176 ////////////////////////////////////////////////////////////////////
177 void TextProperties::
178 clear() {
179  (*this) = TextProperties();
180 }
181 
182 ////////////////////////////////////////////////////////////////////
183 // Function: TextProperties::add_properties
184 // Access: Published
185 // Description: Sets any properties that are explicitly specified in
186 // other on this object. Leaves other properties
187 // unchanged.
188 ////////////////////////////////////////////////////////////////////
189 void TextProperties::
191  if (other.has_font()) {
192  set_font(other.get_font());
193  }
194  if (other.has_small_caps()) {
197  }
198  if (other.has_slant()) {
199  set_slant(other.get_slant());
200  }
201  if (other.has_underscore()) {
203  }
204  if (other.has_underscore_height()) {
206  }
207  if (other.has_align()) {
208  set_align(other.get_align());
209  }
210  if (other.has_indent()) {
211  set_indent(other.get_indent());
212  }
213  if (other.has_wordwrap()) {
214  set_wordwrap(other.get_wordwrap());
215  }
216  if (other.has_text_color()) {
217  set_text_color(other.get_text_color());
218  }
219  if (other.has_shadow_color()) {
220  set_shadow_color(other.get_shadow_color());
221  }
222  if (other.has_shadow()) {
223  set_shadow(other.get_shadow());
224  }
225  if (other.has_bin()) {
226  set_bin(other.get_bin());
227  }
228  if (other.has_draw_order()) {
230  }
231  if (other.has_tab_width()) {
232  set_tab_width(other.get_tab_width());
233  }
234 
235  // The glyph scale and shift are a special case: rather than
236  // replacing the previous value, they modify it, so that they apply
237  // cumulatively to nested TextProperties.
238  if (other.has_glyph_shift()) {
240  }
241  if (other.has_glyph_scale()) {
243  }
244 
245  if (other.has_text_scale()) {
247  }
248 }
249 
250 
251 ////////////////////////////////////////////////////////////////////
252 // Function: TextProperties::write
253 // Access: Published
254 // Description:
255 ////////////////////////////////////////////////////////////////////
256 void TextProperties::
257 write(ostream &out, int indent_level) const {
258  if (!is_any_specified()) {
259  indent(out, indent_level)
260  << "default properties\n";
261  }
262  if (has_font()) {
263  if (get_font() != (TextFont *)NULL) {
264  indent(out, indent_level)
265  << "with font " << _font->get_name() << "\n";
266  } else {
267  indent(out, indent_level)
268  << "with NULL font\n";
269  }
270  }
271  if (has_small_caps()) {
272  indent(out, indent_level)
273  << "small caps = " << get_small_caps() << "\n";
274  }
275  if (has_small_caps_scale()) {
276  indent(out, indent_level)
277  << "small caps scale = " << get_small_caps_scale() << "\n";
278  }
279  if (has_slant()) {
280  indent(out, indent_level)
281  << "slant = " << get_slant() << "\n";
282  }
283  if (has_underscore()) {
284  indent(out, indent_level)
285  << "underscore = " << get_underscore() << "\n";
286  }
287  if (has_underscore_height()) {
288  indent(out, indent_level)
289  << "underscore_height = " << get_underscore_height() << "\n";
290  }
291 
292  if (has_align()) {
293  indent(out, indent_level)
294  << "alignment is ";
295  switch (get_align()) {
296  case A_left:
297  out << "A_left\n";
298  break;
299 
300  case A_right:
301  out << "A_right\n";
302  break;
303 
304  case A_center:
305  out << "A_center\n";
306  break;
307 
308  case A_boxed_left:
309  out << "A_boxed_left\n";
310  break;
311 
312  case A_boxed_right:
313  out << "A_boxed_right\n";
314  break;
315 
316  case A_boxed_center:
317  out << "A_boxed_center\n";
318  break;
319  }
320  }
321 
322  if (has_indent()) {
323  indent(out, indent_level)
324  << "indent at " << get_indent() << " units.\n";
325  }
326 
327  if (has_wordwrap()) {
328  indent(out, indent_level)
329  << "word-wrapping at " << get_wordwrap() << " units.\n";
330  }
331 
332  if (has_text_color()) {
333  indent(out, indent_level)
334  << "text color is " << get_text_color() << "\n";
335  }
336 
337  if (has_shadow()) {
338  indent(out, indent_level)
339  << "shadow at " << get_shadow() << "\n";
340  }
341  if (has_shadow_color()) {
342  indent(out, indent_level)
343  << "shadow color is " << get_shadow_color() << "\n";
344  }
345 
346  if (has_bin()) {
347  indent(out, indent_level)
348  << "bin is " << get_bin() << "\n";
349  }
350  if (has_draw_order()) {
351  indent(out, indent_level)
352  << "draw order is " << get_draw_order() << "\n";
353  }
354 
355  if (has_tab_width()) {
356  indent(out, indent_level)
357  << "tab width is " << get_tab_width() << "\n";
358  }
359 
360  if (has_glyph_scale()) {
361  indent(out, indent_level)
362  << "glyph scale is " << get_glyph_scale() << "\n";
363  }
364  if (has_glyph_shift()) {
365  indent(out, indent_level)
366  << "glyph shift is " << get_glyph_shift() << "\n";
367  }
368 
369  if (has_text_scale()) {
370  indent(out, indent_level)
371  << "text scale is " << get_text_scale() << "\n";
372  }
373 }
374 
375 ////////////////////////////////////////////////////////////////////
376 // Function: TextProperties::load_default_font
377 // Access: Private, Static
378 // Description: This function is called once (or never), the first
379 // time someone attempts to render a TextNode using the
380 // default font. It should attempt to load the default
381 // font, using the compiled-in version if it is
382 // available, or whatever system file may be named in
383 // Configrc.
384 ////////////////////////////////////////////////////////////////////
385 void TextProperties::
386 load_default_font() {
387  _loaded_default_font = true;
388 
389  if (!text_default_font.empty()) {
390  // First, attempt to load the user-specified filename.
391  _default_font = FontPool::load_font(text_default_font.get_value());
392  if (_default_font != (TextFont *)NULL && _default_font->is_valid()) {
393  return;
394  }
395  }
396 
397  // Then, attempt to load the compiled-in font, if we have one.
398 #ifdef COMPILE_IN_DEFAULT_FONT
399 #ifdef HAVE_FREETYPE
400  // Loading the compiled-in FreeType font is relatively easy.
401  _default_font = new DynamicTextFont((const char *)default_font_data,
402  default_font_size, 0);
403  // The compiled-in font seems to confuse FreeType about its winding order.
404  ((DynamicTextFont *)_default_font.p())->set_winding_order(DynamicTextFont::WO_left);
405 
406 #else
407  // The compiled-in Bam font requires creating a BamFile object to
408  // decode it.
409  string data((const char *)default_font_data, default_font_size);
410 
411 #ifdef HAVE_ZLIB
412  // The font data is stored compressed; decompress it on-the-fly.
413  istringstream inz(data);
414  IDecompressStream in(&inz, false);
415 
416 #else
417  // The font data is stored uncompressed, so just load it.
418  istringstream in(data);
419 #endif // HAVE_ZLIB
420 
421  BamFile bam_file;
422  if (bam_file.open_read(in, "default font stream")) {
423  PT(PandaNode) node = bam_file.read_node();
424  if (node != (PandaNode *)NULL) {
425  _default_font = new StaticTextFont(node);
426  }
427  }
428 
429 #endif // HAVE_FREETYPE
430 #endif // COMPILE_IN_DEFAULT_FONT
431 }
bool is_any_specified() const
Returns true if any properties have been specified, false otherwise.
The principle public interface to reading and writing Bam disk files.
Definition: bamFile.h:45
Filename get_value() const
Returns the variable&#39;s value.
A basic node of the scene graph or data graph.
Definition: pandaNode.h:72
void set_shadow(PN_stdfloat xoffset, PN_stdfloat yoffset)
Specifies that the text should be drawn with a shadow, by creating a second copy of the text and offs...
bool open_read(const Filename &bam_filename, bool report_errors=true)
Attempts to open the indicated filename for reading.
Definition: bamFile.cxx:56
PN_stdfloat get_underscore_height() const
Returns the vertical height of the underscore; see set_underscore_height().
void set_font(TextFont *font)
Sets the font that will be used when making text.
void add_properties(const TextProperties &other)
Sets any properties that are explicitly specified in other on this object.
void set_align(Alignment align_type)
Specifies the alignment of the text within its margins.
void set_underscore_height(PN_stdfloat underscore_height)
Specifies the vertical height of the underscore, relative to the text baseline.
void set_glyph_scale(PN_stdfloat glyph_scale)
Specifies the factor by which to scale each letter of the text as it is placed, in addition to any sc...
TextFont * get_font() const
Returns the font currently in use, if any.
PN_stdfloat get_slant() const
Returns the factor by which the text is specified to slant to the right.
void set_bin(const string &bin)
Names the CullBin that the text geometry should be assigned to.
PN_stdfloat get_tab_width() const
Returns the width set via set_tab_width().
bool get_small_caps() const
Returns the small_caps flag.
bool get_underscore() const
Returns the underscore flag.
void set_text_scale(PN_stdfloat text_scale)
Specifies the factor by which to scale the text, in addition to any scalings imposed by the node...
void set_small_caps(bool small_caps)
Sets the small_caps flag.
An encapsulation of a font; i.e.
Definition: textFont.h:36
A StaticTextFont is loaded up from a model that was previously generated via egg-mkfont, and contains all of its glyphs already generated and available for use.
PN_stdfloat get_glyph_scale() const
Returns the scale factor of each letter as specified by set_glyph_scale().
void set_wordwrap(PN_stdfloat wordwrap)
Sets the text up to automatically wordwrap when it exceeds the indicated width.
void set_small_caps_scale(PN_stdfloat small_caps_scale)
Sets the scale factor applied to lowercase letters from their uppercase equivalents, when the small_caps flag is in effect.
int get_draw_order() const
Returns the drawing order set with set_draw_order().
void set_slant(PN_stdfloat slant)
Specifies the factor by which the text slants to the right.
int set_draw_order(int draw_order)
Sets the drawing order of text created by the TextNode.
void set_indent(PN_stdfloat indent)
Specifies the amount of extra space that is inserted before the first character of each line...
void set_underscore(bool underscore)
Sets the underscore flag.
static TextFont * load_font(const string &filename)
Loads the given filename up into a font, if it has not already been loaded, and returns the new font...
Definition: fontPool.I:52
void clear()
Unsets all properties that have been specified so far, and resets the TextProperties structure to its...
This defines the set of visual properties that may be assigned to the individual characters of the te...
const string & get_bin() const
Returns the drawing bin set with set_bin(), or empty string if no bin has been set.
PN_stdfloat get_glyph_shift() const
Returns the vertical shift of each letter as specified by set_glyph_shift().
TypeHandle is the identifier used to differentiate C++ class types.
Definition: typeHandle.h:85
PN_stdfloat get_small_caps_scale() const
Returns the scale factor applied to lowercase letters from their uppercase equivalents, when the small_caps flag is in effect.
void set_glyph_shift(PN_stdfloat glyph_shift)
Specifies a vertical amount to shift each letter of the text as it is placed.
void set_tab_width(PN_stdfloat tab_width)
Sets the width of each tab stop, in screen units.
bool has_bin() const
Returns true if an explicit drawing bin has been set via set_bin(), false otherwise.
PN_stdfloat get_text_scale() const
Returns the scale factor of the text as specified by set_text_scale().
LVector2 get_shadow() const
Returns the offset of the shadow as set by set_shadow().