Panda3D
Loading...
Searching...
No Matches
textProperties.cxx
Go to the documentation of this file.
1/**
2 * PANDA 3D SOFTWARE
3 * Copyright (c) Carnegie Mellon University. All rights reserved.
4 *
5 * All use of this software is subject to the terms of the revised BSD
6 * license. You should have received a copy of this license along
7 * with this source code in a file named "LICENSE."
8 *
9 * @file textProperties.cxx
10 * @author drose
11 * @date 2004-04-06
12 */
13
14#include "textProperties.h"
15#include "config_text.h"
16#include "default_font.h"
17#include "dynamicTextFont.h"
18#include "staticTextFont.h"
19#include "bamFile.h"
20#include "fontPool.h"
21#include "colorAttrib.h"
22#include "cullBinAttrib.h"
23#include "transparencyAttrib.h"
24
25PT(TextFont) TextProperties::_default_font;
26bool TextProperties::_loaded_default_font = false;
27
28TypeHandle TextProperties::_type_handle;
29
30/**
31 *
32 */
33TextProperties::
34TextProperties() :
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(1.0f, 1.0f, 1.0f, 1.0f),
47 _shadow_color(0.0f, 0.0f, 0.0f, 1.0f),
48 _shadow_offset(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 _direction(D_rtl) {
55}
56
57/**
58 *
59 */
60TextProperties::
61TextProperties(const TextProperties &copy) {
62 (*this) = copy;
63 _text_state = copy._text_state;
64 _shadow_state = copy._shadow_state;
65}
66
67/**
68 *
69 */
70void TextProperties::
71operator = (const TextProperties &copy) {
72 _specified = copy._specified;
73
74 _font = copy._font;
75 _small_caps = copy._small_caps;
76 _small_caps_scale = copy._small_caps_scale;
77 _slant = copy._slant;
78 _underscore = copy._underscore;
79 _underscore_height = copy._underscore_height;
80 _align = copy._align;
81 _indent_width = copy._indent_width;
82 _wordwrap_width = copy._wordwrap_width;
83 _preserve_trailing_whitespace = copy._preserve_trailing_whitespace;
84 _text_color = copy._text_color;
85 _shadow_color = copy._shadow_color;
86 _shadow_offset = copy._shadow_offset;
87 _bin = copy._bin;
88 _draw_order = copy._draw_order;
89 _tab_width = copy._tab_width;
90 _glyph_scale = copy._glyph_scale;
91 _glyph_shift = copy._glyph_shift;
92 _text_scale = copy._text_scale;
93 _direction = copy._direction;
94
95 _text_state.clear();
96 _shadow_state.clear();
97}
98
99/**
100 *
101 */
102bool TextProperties::
103operator == (const TextProperties &other) const {
104 if (_specified != other._specified) {
105 return false;
106 }
107
108 if ((_specified & F_has_font) && _font != other._font) {
109 return false;
110 }
111 if ((_specified & F_has_small_caps) && _small_caps != other._small_caps) {
112 return false;
113 }
114 if ((_specified & F_has_small_caps_scale) && _small_caps_scale != other._small_caps_scale) {
115 return false;
116 }
117 if ((_specified & F_has_slant) && _slant != other._slant) {
118 return false;
119 }
120 if ((_specified & F_has_underscore) && _underscore != other._underscore) {
121 return false;
122 }
123 if ((_specified & F_has_underscore_height) && _underscore_height != other._underscore_height) {
124 return false;
125 }
126 if ((_specified & F_has_align) && _align != other._align) {
127 return false;
128 }
129 if ((_specified & F_has_indent) && _indent_width != other._indent_width) {
130 return false;
131 }
132 if ((_specified & F_has_wordwrap) && _wordwrap_width != other._wordwrap_width) {
133 return false;
134 }
135 if ((_specified & F_has_preserve_trailing_whitespace) && _preserve_trailing_whitespace != other._preserve_trailing_whitespace) {
136 return false;
137 }
138 if ((_specified & F_has_text_color) && _text_color != other._text_color) {
139 return false;
140 }
141 if ((_specified & F_has_text_color) && _text_color != other._text_color) {
142 return false;
143 }
144 if ((_specified & F_has_shadow_color) && _shadow_color != other._shadow_color) {
145 return false;
146 }
147 if ((_specified & F_has_shadow) && _shadow_offset != other._shadow_offset) {
148 return false;
149 }
150 if ((_specified & F_has_bin) && _bin != other._bin) {
151 return false;
152 }
153 if ((_specified & F_has_draw_order) && _draw_order != other._draw_order) {
154 return false;
155 }
156 if ((_specified & F_has_tab_width) && _tab_width != other._tab_width) {
157 return false;
158 }
159 if ((_specified & F_has_glyph_scale) && _glyph_scale != other._glyph_scale) {
160 return false;
161 }
162 if ((_specified & F_has_glyph_shift) && _glyph_shift != other._glyph_shift) {
163 return false;
164 }
165 if ((_specified & F_has_text_scale) && _text_scale != other._text_scale) {
166 return false;
167 }
168 if ((_specified & F_has_direction) && _direction != other._direction) {
169 return false;
170 }
171 return true;
172}
173
174/**
175 * Unsets all properties that have been specified so far, and resets the
176 * TextProperties structure to its initial empty state.
177 */
179clear() {
180 (*this) = TextProperties();
181}
182
183/**
184 * Sets any properties that are explicitly specified in other on this object.
185 * Leaves other properties unchanged.
186 */
188add_properties(const TextProperties &other) {
189 if (other.has_font()) {
190 set_font(other.get_font());
191 }
192 if (other.has_small_caps()) {
195 }
196 if (other.has_slant()) {
197 set_slant(other.get_slant());
198 }
199 if (other.has_underscore()) {
201 }
202 if (other.has_underscore_height()) {
204 }
205 if (other.has_align()) {
206 set_align(other.get_align());
207 }
208 if (other.has_indent()) {
209 set_indent(other.get_indent());
210 }
211 if (other.has_wordwrap()) {
212 set_wordwrap(other.get_wordwrap());
213 }
214 if (other.has_text_color()) {
215 set_text_color(other.get_text_color());
216 }
217 if (other.has_shadow_color()) {
218 set_shadow_color(other.get_shadow_color());
219 }
220 if (other.has_shadow()) {
221 set_shadow(other.get_shadow());
222 }
223 if (other.has_bin()) {
224 set_bin(other.get_bin());
225 }
226 if (other.has_draw_order()) {
228 }
229 if (other.has_tab_width()) {
231 }
232
233 // The glyph scale and shift are a special case: rather than replacing the
234 // previous value, they modify it, so that they apply cumulatively to nested
235 // TextProperties.
236 if (other.has_glyph_shift()) {
238 }
239 if (other.has_glyph_scale()) {
241 }
242
243 if (other.has_text_scale()) {
245 }
246 if (other.has_direction()) {
248 }
249}
250
251
252/**
253 *
254 */
255void TextProperties::
256write(std::ostream &out, int indent_level) const {
257 if (!is_any_specified()) {
258 indent(out, indent_level)
259 << "default properties\n";
260 }
261 if (has_font()) {
262 if (get_font() != nullptr) {
263 indent(out, indent_level)
264 << "with font " << _font->get_name() << "\n";
265 } else {
266 indent(out, indent_level)
267 << "with NULL font\n";
268 }
269 }
270 if (has_small_caps()) {
271 indent(out, indent_level)
272 << "small caps = " << get_small_caps() << "\n";
273 }
274 if (has_small_caps_scale()) {
275 indent(out, indent_level)
276 << "small caps scale = " << get_small_caps_scale() << "\n";
277 }
278 if (has_slant()) {
279 indent(out, indent_level)
280 << "slant = " << get_slant() << "\n";
281 }
282 if (has_underscore()) {
283 indent(out, indent_level)
284 << "underscore = " << get_underscore() << "\n";
285 }
286 if (has_underscore_height()) {
287 indent(out, indent_level)
288 << "underscore_height = " << get_underscore_height() << "\n";
289 }
290
291 if (has_align()) {
292 indent(out, indent_level)
293 << "alignment is ";
294 switch (get_align()) {
295 case A_left:
296 out << "A_left\n";
297 break;
298
299 case A_right:
300 out << "A_right\n";
301 break;
302
303 case A_center:
304 out << "A_center\n";
305 break;
306
307 case A_boxed_left:
308 out << "A_boxed_left\n";
309 break;
310
311 case A_boxed_right:
312 out << "A_boxed_right\n";
313 break;
314
315 case A_boxed_center:
316 out << "A_boxed_center\n";
317 break;
318 }
319 }
320
321 if (has_indent()) {
322 indent(out, indent_level)
323 << "indent at " << get_indent() << " units.\n";
324 }
325
326 if (has_wordwrap()) {
327 indent(out, indent_level)
328 << "word-wrapping at " << get_wordwrap() << " units.\n";
329 }
330
331 if (has_text_color()) {
332 indent(out, indent_level)
333 << "text color is " << get_text_color() << "\n";
334 }
335
336 if (has_shadow()) {
337 indent(out, indent_level)
338 << "shadow at " << get_shadow() << "\n";
339 }
340 if (has_shadow_color()) {
341 indent(out, indent_level)
342 << "shadow color is " << get_shadow_color() << "\n";
343 }
344
345 if (has_bin()) {
346 indent(out, indent_level)
347 << "bin is " << get_bin() << "\n";
348 }
349 if (has_draw_order()) {
350 indent(out, indent_level)
351 << "draw order is " << get_draw_order() << "\n";
352 }
353
354 if (has_tab_width()) {
355 indent(out, indent_level)
356 << "tab width is " << get_tab_width() << "\n";
357 }
358
359 if (has_glyph_scale()) {
360 indent(out, indent_level)
361 << "glyph scale is " << get_glyph_scale() << "\n";
362 }
363 if (has_glyph_shift()) {
364 indent(out, indent_level)
365 << "glyph shift is " << get_glyph_shift() << "\n";
366 }
367
368 if (has_text_scale()) {
369 indent(out, indent_level)
370 << "text scale is " << get_text_scale() << "\n";
371 }
372
373 if (has_direction()) {
374 indent(out, indent_level)
375 << "direction is ";
376 switch (get_direction()) {
377 case D_ltr:
378 out << "D_ltr\n";
379 break;
380
381 case D_rtl:
382 out << "D_rtl\n";
383 break;
384 }
385 }
386}
387
388/**
389 * Returns a RenderState object suitable for rendering text with these
390 * properties.
391 */
393get_text_state() const {
394 if (!_text_state.is_null()) {
395 return _text_state;
396 }
397
398 CPT(RenderState) state = RenderState::make_empty();
399
400 if (has_text_color()) {
401 state = state->add_attrib(ColorAttrib::make_flat(get_text_color()));
402 if (get_text_color()[3] != 1.0) {
403 state = state->add_attrib(TransparencyAttrib::make(TransparencyAttrib::M_alpha));
404 }
405 }
406
407 if (has_bin()) {
408 state = state->add_attrib(CullBinAttrib::make(get_bin(), get_draw_order() + 2));
409 }
410
411 std::swap(_text_state, state);
412 return _text_state;
413}
414
415/**
416 * Returns a RenderState object suitable for rendering the shadow of this text
417 * with these properties.
418 */
420get_shadow_state() const {
421 if (!_shadow_state.is_null()) {
422 return _shadow_state;
423 }
424
425 CPT(RenderState) state = RenderState::make_empty();
426
427 state = state->add_attrib(ColorAttrib::make_flat(get_shadow_color()));
428 if (get_shadow_color()[3] != 1.0) {
429 state = state->add_attrib(TransparencyAttrib::make(TransparencyAttrib::M_alpha));
430 }
431
432 if (has_bin()) {
433 state = state->add_attrib(CullBinAttrib::make(get_bin(), get_draw_order() + 1));
434 }
435
436 std::swap(_shadow_state, state);
437 return _shadow_state;
438}
439
440/**
441 * This function is called once (or never), the first time someone attempts to
442 * render a TextNode using the default font. It should attempt to load the
443 * default font, using the compiled-in version if it is available, or whatever
444 * system file may be named in Configrc.
445 */
446void TextProperties::
447load_default_font() {
448 _loaded_default_font = true;
449
450 if (!text_default_font.empty()) {
451 // First, attempt to load the user-specified filename.
452 _default_font = FontPool::load_font(text_default_font.get_value());
453 if (_default_font != nullptr && _default_font->is_valid()) {
454 return;
455 }
456 }
457
458 // Then, attempt to load the compiled-in font, if we have one.
459#ifdef COMPILE_IN_DEFAULT_FONT
460#ifdef HAVE_FREETYPE
461 // Loading the compiled-in FreeType font is relatively easy.
462 _default_font = new DynamicTextFont((const char *)default_font_data,
463 default_font_size, 0);
464 // The compiled-in font seems to confuse FreeType about its winding order.
465 ((DynamicTextFont *)_default_font.p())->set_winding_order(DynamicTextFont::WO_left);
466
467#else
468 // The compiled-in Bam font requires creating a BamFile object to decode it.
469 std::string data((const char *)default_font_data, default_font_size);
470
471#ifdef HAVE_ZLIB
472 // The font data is stored compressed; decompress it on-the-fly.
473 std::istringstream inz(data);
474 IDecompressStream in(&inz, false);
475
476#else
477 // The font data is stored uncompressed, so just load it.
478 std::istringstream in(data);
479#endif // HAVE_ZLIB
480
481 BamFile bam_file;
482 if (bam_file.open_read(in, "default font stream")) {
483 PT(PandaNode) node = bam_file.read_node();
484 if (node != nullptr) {
485 _default_font = new StaticTextFont(node);
486 }
487 }
488
489#endif // HAVE_FREETYPE
490#endif // COMPILE_IN_DEFAULT_FONT
491}
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
The principle public interface to reading and writing Bam disk files.
Definition bamFile.h:41
bool open_read(const Filename &bam_filename, bool report_errors=true)
Attempts to open the indicated filename for reading.
Definition bamFile.cxx:51
get_value
Returns the variable's value.
static TextFont * load_font(const std::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:40
A basic node of the scene graph or data graph.
Definition pandaNode.h:65
This represents a unique collection of RenderAttrib objects that correspond to a particular renderabl...
Definition renderState.h:47
A StaticTextFont is loaded up from a model that was previously generated via egg-mkfont,...
An encapsulation of a font; i.e.
Definition textFont.h:32
This defines the set of visual properties that may be assigned to the individual characters of the te...
set_glyph_shift
Specifies a vertical amount to shift each letter of the text as it is placed.
const RenderState * get_shadow_state() const
Returns a RenderState object suitable for rendering the shadow of this text with these properties.
set_underscore_height
Specifies the vertical height of the underscore, relative to the text baseline.
get_slant
Returns the factor by which the text is specified to slant to the right.
set_shadow
Specifies that the text should be drawn with a shadow, by creating a second copy of the text and offs...
get_draw_order
Returns the drawing order set with set_draw_order().
set_align
Specifies the alignment of the text within its margins.
get_underscore_height
Returns the vertical height of the underscore; see set_underscore_height().
get_small_caps
Returns the small_caps flag.
get_glyph_shift
Returns the vertical shift of each letter as specified by set_glyph_shift().
const RenderState * get_text_state() const
Returns a RenderState object suitable for rendering text with these properties.
set_draw_order
Sets the drawing order of text created by the TextNode.
set_wordwrap
Sets the text up to automatically wordwrap when it exceeds the indicated width.
get_glyph_scale
Returns the scale factor of each letter as specified by set_glyph_scale().
set_underscore
Sets the underscore flag.
set_font
Sets the font that will be used when making text.
set_small_caps_scale
Sets the scale factor applied to lowercase letters from their uppercase equivalents,...
set_tab_width
Sets the width of each tab stop, in screen units.
get_shadow
Returns the offset of the shadow as set by set_shadow().
get_bin
Returns the drawing bin set with set_bin(), or empty string if no bin has been set.
set_glyph_scale
Specifies the factor by which to scale each letter of the text as it is placed, in addition to any sc...
get_font
Returns the font currently in use, if any.
get_small_caps_scale
Returns the scale factor applied to lowercase letters from their uppercase equivalents,...
get_underscore
Returns the underscore flag.
bool is_any_specified() const
Returns true if any properties have been specified, false otherwise.
set_indent
Specifies the amount of extra space that is inserted before the first character of each line.
get_direction
Returns the direction of the text as specified by set_direction().
void add_properties(const TextProperties &other)
Sets any properties that are explicitly specified in other on this object.
get_tab_width
Returns the width set via set_tab_width().
void clear()
Unsets all properties that have been specified so far, and resets the TextProperties structure to its...
has_bin
Returns true if an explicit drawing bin has been set via set_bin(), false otherwise.
set_direction
Specifies the text direction.
set_text_scale
Specifies the factor by which to scale the text, in addition to any scalings imposed by the node,...
get_text_scale
Returns the scale factor of the text as specified by set_text_scale().
set_small_caps
Sets the small_caps flag.
set_slant
Specifies the factor by which the text slants to the right.
set_bin
Names the CullBin that the text geometry should be assigned to.
TypeHandle is the identifier used to differentiate C++ class types.
Definition typeHandle.h:81
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
std::ostream & indent(std::ostream &out, int indent_level)
A handy function for doing text formatting.
Definition indent.cxx:20
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.