Panda3D
textNode.I
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 textNode.I
10  * @author drose
11  * @date 2002-03-13
12  */
13 
14 /**
15  * Returns the number of units high each line of text is. This is based on
16  * the font. Note that it is possible for the text to include nested font
17  * change commands, in which case the value of this method is questionable.
18  */
19 INLINE PN_stdfloat TextNode::
20 get_line_height() const {
21  TextFont *font = get_font();
22  if (font == nullptr) {
23  return 0.0f;
24  }
25 
26  return font->get_line_height();
27 }
28 
29 /**
30  * Sets the maximum number of rows that may be formatted by the TextNode. If
31  * more text than this is attempted, it will be truncated and has_overflow()
32  * will return true.
33  */
34 INLINE void TextNode::
35 set_max_rows(int max_rows) {
36  MutexHolder holder(_lock);
37  _max_rows = max_rows;
38  invalidate_with_measure();
39 }
40 
41 /**
42  * Resets the TextNode's default behavior of not limiting the number of rows
43  * of text.
44  */
45 INLINE void TextNode::
47  MutexHolder holder(_lock);
48  _max_rows = 0;
49  invalidate_with_measure();
50 }
51 
52 /**
53  * Returns true if a limit on the height of the TextNode has been set via
54  * set_max_rows(), false otherwise.
55  */
56 INLINE bool TextNode::
57 has_max_rows() const {
58  MutexHolder holder(_lock);
59  return _max_rows > 0;
60 }
61 
62 /**
63  * Returns the limit on the height of the TextNode specified by
64  * set_max_rows().
65  */
66 INLINE int TextNode::
67 get_max_rows() const {
68  MutexHolder holder(_lock);
69  return _max_rows;
70 }
71 
72 /**
73  * Returns true if the last text set on the text node exceeded the max_rows
74  * constraint, or false if it all fit.
75  */
76 INLINE bool TextNode::
77 has_overflow() const {
78  MutexHolder holder(_lock);
79  check_measure();
80  return (_flags & F_has_overflow) != 0;
81 }
82 
83 /**
84  *
85  */
86 INLINE void TextNode::
87 set_frame_color(PN_stdfloat r, PN_stdfloat g, PN_stdfloat b, PN_stdfloat a) {
88  set_frame_color(LColor(r, g, b, a));
89 }
90 
91 /**
92  *
93  */
94 INLINE void TextNode::
95 set_frame_color(const LColor &frame_color) {
96  MutexHolder holder(_lock);
97  if (_frame_color != frame_color) {
98  _frame_color = frame_color;
99  invalidate_no_measure();
100  }
101 }
102 
103 /**
104  *
105  */
106 INLINE LColor TextNode::
107 get_frame_color() const {
108  MutexHolder holder(_lock);
109  return _frame_color;
110 }
111 
112 /**
113  *
114  */
115 INLINE void TextNode::
116 set_card_border(PN_stdfloat size, PN_stdfloat uv_portion) {
117  MutexHolder holder(_lock);
118  if ((_flags & F_has_card_border) == 0 || _card_border_size != size || _card_border_uv_portion != uv_portion) {
119  _flags |= F_has_card_border;
120  _card_border_size = size;
121  _card_border_uv_portion = uv_portion;
122  invalidate_no_measure();
123  }
124 }
125 
126 /**
127  *
128  */
129 INLINE void TextNode::
130 clear_card_border() {
131  MutexHolder holder(_lock);
132  if (_flags & F_has_card_border) {
133  _flags &= ~F_has_card_border;
134  invalidate_no_measure();
135  }
136 }
137 
138 /**
139  *
140  */
141 INLINE PN_stdfloat TextNode::
142 get_card_border_size() const {
143  MutexHolder holder(_lock);
144  return _card_border_size;
145 }
146 
147 /**
148  *
149  */
150 INLINE PN_stdfloat TextNode::
151 get_card_border_uv_portion() const {
152  MutexHolder holder(_lock);
153  return _card_border_uv_portion;
154 }
155 
156 /**
157  *
158  */
159 INLINE bool TextNode::
160 has_card_border() const {
161  MutexHolder holder(_lock);
162  return (_flags & F_has_card_border) != 0;
163 }
164 
165 /**
166  *
167  */
168 INLINE void TextNode::
169 set_card_color(PN_stdfloat r, PN_stdfloat g, PN_stdfloat b, PN_stdfloat a) {
170  set_card_color(LColor(r, g, b, a));
171 }
172 
173 /**
174  *
175  */
176 INLINE void TextNode::
177 set_card_color(const LColor &card_color) {
178  MutexHolder holder(_lock);
179  if (_card_color != card_color) {
180  _card_color = card_color;
181  invalidate_no_measure();
182  }
183 }
184 
185 /**
186  *
187  */
188 INLINE LColor TextNode::
189 get_card_color() const {
190  MutexHolder holder(_lock);
191  return _card_color;
192 }
193 
194 /**
195  *
196  */
197 INLINE void TextNode::
198 set_card_texture(Texture *card_texture) {
199  if (card_texture == nullptr) {
200  clear_card_texture();
201  } else {
202  MutexHolder holder(_lock);
203  if ((_flags & F_has_card_texture) == 0 || _card_texture != card_texture) {
204  _flags |= F_has_card_texture;
205  _card_texture = card_texture;
206  invalidate_no_measure();
207  }
208  }
209 }
210 
211 /**
212  *
213  */
214 INLINE void TextNode::
215 clear_card_texture() {
216  MutexHolder holder(_lock);
217  if (_flags & F_has_card_texture) {
218  _flags &= ~F_has_card_texture;
219  _card_texture = nullptr;
220  invalidate_no_measure();
221  }
222 }
223 
224 /**
225  *
226  */
227 INLINE bool TextNode::
228 has_card_texture() const {
229  MutexHolder holder(_lock);
230  return (_flags & F_has_card_texture) != 0;
231 }
232 
233 /**
234  *
235  */
236 INLINE Texture *TextNode::
237 get_card_texture() const {
238  MutexHolder holder(_lock);
239  return _card_texture;
240 }
241 
242 /**
243  * Specifies that a border will be drawn around the text when it is next
244  * created. The parameters are the amount of additional padding to insert
245  * between the frame and the text in each dimension, and all should generally
246  * be positive.
247  */
248 INLINE void TextNode::
249 set_frame_as_margin(PN_stdfloat left, PN_stdfloat right, PN_stdfloat bottom, PN_stdfloat top) {
250  MutexHolder holder(_lock);
251  _flags |= (F_has_frame | F_frame_as_margin);
252  _frame_ul.set(left, top);
253  _frame_lr.set(right, bottom);
254  invalidate_no_measure();
255 }
256 
257 /**
258  * Similar to set_frame_as_margin, except the frame is specified in actual
259  * coordinate units (relative to the text's origin), irrespective of the size
260  * of the text. The left and bottom coordinates should generally be negative,
261  * while the right and top coordinates should generally be positive.
262  */
263 INLINE void TextNode::
264 set_frame_actual(PN_stdfloat left, PN_stdfloat right, PN_stdfloat bottom, PN_stdfloat top) {
265  MutexHolder holder(_lock);
266  _flags |= F_has_frame;
267  _flags &= ~F_frame_as_margin;
268  _frame_ul.set(left, top);
269  _frame_lr.set(right, bottom);
270  invalidate_no_measure();
271 }
272 
273 /**
274  * Specifies that a border will not be drawn around the text.
275  */
276 INLINE void TextNode::
278  MutexHolder holder(_lock);
279  _flags &= ~F_has_frame;
280  invalidate_no_measure();
281 }
282 
283 /**
284  *
285  */
286 INLINE bool TextNode::
287 has_frame() const {
288  MutexHolder holder(_lock);
289  return (_flags & F_has_frame) != 0;
290 }
291 
292 /**
293  * If this is true, the frame was set via a call to set_frame_as_margin(), and
294  * the dimension of the frame as returned by get_frame_as_set() represent a
295  * margin all around the text. If false, then the frame was set via a call to
296  * set_frame_actual(), and the dimensions of the frame as returned by
297  * get_frame_as_set() are relative to the text's origin.
298  */
299 INLINE bool TextNode::
301  MutexHolder holder(_lock);
302  nassertr((_flags & F_has_frame) != 0, false);
303  return (_flags & F_frame_as_margin) != 0;
304 }
305 
306 /**
307  * Returns the dimensions of the frame as set by set_frame_as_margin() or
308  * set_frame_actual(). Use is_frame_actual() to determine how to interpret
309  * the values returned by this function. It is an error to call this if
310  * has_frame() is false.
311  */
312 INLINE LVecBase4 TextNode::
314  MutexHolder holder(_lock);
315  nassertr((_flags & F_has_frame) != 0, LVecBase4(0.0, 0.0, 0.0, 0.0));
316  return LVecBase4(_frame_ul[0], _frame_lr[0], _frame_lr[1], _frame_ul[1]);
317 }
318 
319 /**
320  * Returns the actual dimensions of the frame around the text. If the frame
321  * was set via set_frame_as_margin(), the result returned by this function
322  * reflects the size of the current text; if the frame was set via
323  * set_frame_actual(), this returns the values actually set.
324  *
325  * If the text has no frame at all, this returns the dimensions of the text
326  * itself, as if the frame were set with a margin of 0, 0, 0, 0.
327  */
328 INLINE LVecBase4 TextNode::
330  MutexHolder holder(_lock);
331  if (_flags & F_has_frame) {
332  if (_flags & F_frame_as_margin) {
333  check_measure();
334  return LVecBase4(_text_ul[0] - _frame_ul[0],
335  _text_lr[0] + _frame_lr[0],
336  _text_lr[1] - _frame_lr[1],
337  _text_ul[1] + _frame_ul[1]);
338  } else {
339  return LVecBase4(_frame_ul[0], _frame_lr[0], _frame_lr[1], _frame_ul[1]);
340  }
341  } else {
342  check_measure();
343  return LVecBase4(_text_ul[0], _text_lr[0], _text_lr[1], _text_ul[1]);
344  }
345 }
346 
347 /**
348  * Specifies the thickness of the lines that will be used to draw the frame.
349  */
350 INLINE void TextNode::
351 set_frame_line_width(PN_stdfloat frame_width) {
352  MutexHolder holder(_lock);
353  _frame_width = frame_width;
354  invalidate_no_measure();
355 }
356 
357 /**
358  * Returns the thickness of the lines that will be used to draw the frame.
359  */
360 INLINE PN_stdfloat TextNode::
361 get_frame_line_width() const {
362  MutexHolder holder(_lock);
363  return _frame_width;
364 }
365 
366 /**
367  * Enables or disables the drawing of corners for the frame. These are extra
368  * points drawn at each of the four corners, to soften the ugly edges
369  * generated when the line width is greater than one.
370  */
371 INLINE void TextNode::
372 set_frame_corners(bool corners) {
373  MutexHolder holder(_lock);
374  if (corners) {
375  _flags |= F_frame_corners;
376  } else {
377  _flags &= ~F_frame_corners;
378  }
379  invalidate_no_measure();
380 }
381 
382 /**
383  *
384  */
385 INLINE bool TextNode::
386 get_frame_corners() const {
387  MutexHolder holder(_lock);
388  return (_flags & F_frame_corners) != 0;
389 }
390 
391 /**
392  * Specifies that a (possibly opaque or semitransparent) card will be held
393  * behind the text when it is next created. Like set_frame_as_margin, the
394  * parameters are the amount of additional padding to insert around the text
395  * in each dimension, and all should generally be positive.
396  */
397 INLINE void TextNode::
398 set_card_as_margin(PN_stdfloat left, PN_stdfloat right, PN_stdfloat bottom, PN_stdfloat top) {
399  MutexHolder holder(_lock);
400  _flags |= (F_has_card | F_card_as_margin);
401  _card_ul.set(left, top);
402  _card_lr.set(right, bottom);
403  invalidate_no_measure();
404 }
405 
406 /**
407  * Similar to set_card_as_margin, except the card is specified in actual
408  * coordinate units (relative to the text's origin), irrespective of the size
409  * of the text. The left and bottom coordinates should generally be negative,
410  * while the right and top coordinates should generally be positive.
411  */
412 INLINE void TextNode::
413 set_card_actual(PN_stdfloat left, PN_stdfloat right, PN_stdfloat bottom, PN_stdfloat top) {
414  MutexHolder holder(_lock);
415  _flags |= F_has_card;
416  _flags &= ~F_card_as_margin;
417  _card_ul.set(left, top);
418  _card_lr.set(right, bottom);
419  invalidate_no_measure();
420 }
421 
422 /**
423  * Sets the card_decal flag. When this is true, the text is decalled onto the
424  * card, which is necessary if the TextNode is to be rendered in the 3-d world
425  * without putting it in a bin.
426  */
427 INLINE void TextNode::
428 set_card_decal(bool card_decal) {
429  MutexHolder holder(_lock);
430  if (card_decal) {
431  _flags |= F_card_decal;
432  } else {
433  _flags &= ~F_card_decal;
434  }
435  invalidate_no_measure();
436 }
437 
438 /**
439  * Specifies that a card will not be drawn behind the text.
440  */
441 INLINE void TextNode::
443  MutexHolder holder(_lock);
444  _flags &= ~F_has_card;
445  invalidate_no_measure();
446 }
447 
448 /**
449  *
450  */
451 INLINE bool TextNode::
452 has_card() const {
453  MutexHolder holder(_lock);
454  return (_flags & F_has_card) != 0;
455 }
456 
457 /**
458  * Returns the card_decal flag. See set_card_decal().
459  */
460 INLINE bool TextNode::
461 get_card_decal() const {
462  MutexHolder holder(_lock);
463  return (_flags & F_card_decal) != 0;
464 }
465 
466 /**
467  * If this is true, the card was set via a call to set_card_as_margin(), and
468  * the dimension of the card as returned by get_card_as_set() represent a
469  * margin all around the text. If false, then the card was set via a call to
470  * set_card_actual(), and the dimensions of the card as returned by
471  * get_card_as_set() are relative to the text's origin.
472  */
473 INLINE bool TextNode::
475  MutexHolder holder(_lock);
476  nassertr((_flags & F_has_card) != 0, false);
477  return (_flags & F_card_as_margin) != 0;
478 }
479 
480 /**
481  * Returns the dimensions of the card as set by set_card_as_margin() or
482  * set_card_actual(). Use is_card_actual() to determine how to interpret the
483  * values returned by this function. It is an error to call this if
484  * has_card() is false.
485  */
486 INLINE LVecBase4 TextNode::
488  MutexHolder holder(_lock);
489  nassertr((_flags & F_has_card) != 0, LVecBase4(0.0, 0.0, 0.0, 0.0));
490  return LVecBase4(_card_ul[0], _card_lr[0], _card_lr[1], _card_ul[1]);
491 }
492 
493 /**
494  * Returns the actual dimensions of the card around the text. If the card was
495  * set via set_card_as_margin(), the result returned by this function reflects
496  * the size of the current text; if the card was set via set_card_actual(),
497  * this returns the values actually set.
498  *
499  * If the text has no card at all, this returns the dimensions of the text
500  * itself, as if the card were set with a margin of 0, 0, 0, 0.
501  */
502 INLINE LVecBase4 TextNode::
504  MutexHolder holder(_lock);
505  if (_flags & F_has_card) {
506  if (_flags & F_card_as_margin) {
507  check_measure();
508  return LVecBase4(_text_ul[0] - _card_ul[0],
509  _text_lr[0] + _card_lr[0],
510  _text_lr[1] - _card_lr[1],
511  _text_ul[1] + _card_ul[1]);
512  } else {
513  return LVecBase4(_card_ul[0], _card_lr[0], _card_lr[1], _card_ul[1]);
514  }
515  } else {
516  check_measure();
517  return LVecBase4(_text_ul[0], _text_lr[0], _text_lr[1], _text_ul[1]);
518  }
519 }
520 
521 /**
522  * Returns the actual card dimensions, transformed by the matrix set by
523  * set_transform(). This returns the card dimensions in actual coordinates as
524  * seen by the rest of the world. Also see get_upper_left_3d() and
525  * get_lower_right_3d().
526  */
527 INLINE LVecBase4 TextNode::
529  LVecBase4 card = get_card_actual();
530 
531  MutexHolder holder(_lock);
532  LPoint3 ul = LPoint3(card[0], 0.0, card[3]) * _transform;
533  LPoint3 lr = LPoint3(card[1], 0.0, card[2]) * _transform;
534 
535  return LVecBase4(ul[0], lr[0], lr[2], ul[2]);
536 }
537 
538 /**
539  * Sets an additional transform that is applied to the entire text paragraph.
540  */
541 INLINE void TextNode::
542 set_transform(const LMatrix4 &transform) {
543  MutexHolder holder(_lock);
544  _transform = transform;
545  invalidate_with_measure();
546 }
547 
548 /**
549  *
550  */
551 INLINE LMatrix4 TextNode::
552 get_transform() const {
553  MutexHolder holder(_lock);
554  return _transform;
555 }
556 
557 /**
558  * Specifies the coordinate system in which the text will be generated.
559  */
560 INLINE void TextNode::
561 set_coordinate_system(CoordinateSystem coordinate_system) {
562  MutexHolder holder(_lock);
563  _coordinate_system = coordinate_system;
564  invalidate_with_measure();
565 }
566 
567 /**
568  *
569  */
570 INLINE CoordinateSystem TextNode::
571 get_coordinate_system() const {
572  MutexHolder holder(_lock);
573  return _coordinate_system;
574 }
575 
576 /**
577  * Specifies the UsageHint that will be applied to generated geometry. The
578  * default is UH_static, which is probably the right setting, but if you know
579  * the TextNode's geometry will have a short lifespan, it may be better to set
580  * it to UH_stream. See geomEnums.h.
581  */
582 INLINE void TextNode::
583 set_usage_hint(Geom::UsageHint usage_hint) {
584  MutexHolder holder(_lock);
585  _usage_hint = usage_hint;
586  invalidate_no_measure();
587 }
588 
589 /**
590  * Returns the UsageHint that will be applied to generated geometry. See
591  * set_usage_hint().
592  */
593 INLINE Geom::UsageHint TextNode::
594 get_usage_hint() const {
595  MutexHolder holder(_lock);
596  return _usage_hint;
597 }
598 
599 /**
600  * Sets the flatten flags. This should be a union of the
601  * TextNode::FlattenFlags options. This controls the degree of flattening
602  * performed on the TextNode's internal geometry (i.e. the scene graph
603  * returned by generate()) each time the text is changed. In general, more
604  * flattening means a more optimal result, but it will take more time to
605  * generate.
606  *
607  * The choice may be any of these three:
608  *
609  * FF_none - No flatten operation is called. The letters are left as
610  * independent Geoms.
611  *
612  * FF_light - A flatten_light() operation is called. The attributes are
613  * applied to the vertices, but no nodes are removed.
614  *
615  * FF_medium - A flatten_medium() operation is called. The attributes are
616  * applied to the vertices, and a few trivial nodes are removed.
617  *
618  * FF_strong - A flatten_strong() operation is called. The attributes are
619  * applied to the vertices, and the resulting nodes are aggressively combined
620  * into as few nodes as possible.
621  *
622  * In addition to the above choices, you may optionally include the following
623  * flag:
624  *
625  * FF_dynamic_merge - Copy the geoms into a single GeomVertexData as we go,
626  * instead of relying on the flatten operation at the end. This pre-flattens
627  * the text considerably, and may obviate the need for flatten altogether; it
628  * also tends to improve performance considerably even if you do call flatten.
629  * However, it is not as fast as not calling flatten at all.
630  *
631  * The default is taken from the text-flatten and text-dynamic-merge config
632  * variables.
633  */
634 INLINE void TextNode::
635 set_flatten_flags(int flatten_flags) {
636  MutexHolder holder(_lock);
637  _flatten_flags = flatten_flags;
638 }
639 
640 /**
641  * Returns the flatten flags. See set_flatten_flags().
642  */
643 INLINE int TextNode::
644 get_flatten_flags() const {
645  MutexHolder holder(_lock);
646  return _flatten_flags;
647 }
648 
649 /**
650  * Sets the font that will be used when making text. If this is set to NULL,
651  * the default font will be used, which can be set via set_default_font().
652  */
653 INLINE void TextNode::
654 set_font(TextFont *font) {
655  MutexHolder holder(_lock);
657  invalidate_with_measure();
658 }
659 
660 /**
661  * Resets the font to the default font.
662  */
663 INLINE void TextNode::
664 clear_font() {
665  MutexHolder holder(_lock);
667  invalidate_with_measure();
668 }
669 
670 /**
671  * Sets the small_caps flag. When this is set, lowercase letters are
672  * generated as scaled-down versions of their uppercase equivalents. This is
673  * particularly useful to set for fonts that do not have lowercase letters.
674  *
675  * It is also a good idea to set this for a (dynamic) font that has already
676  * implemented lowercase letters as scaled-down versions of their uppercase
677  * equivalents, since without this flag the texture memory may needlessly
678  * duplicate equivalent glyphs for upper and lowercase letters. Setting this
679  * flag causes the texture memory to share the mixed-case letters.
680  *
681  * The amount by which the lowercase letters are scaled is specified by
682  * set_small_caps_scale().
683  */
684 INLINE void TextNode::
685 set_small_caps(bool small_caps) {
686  MutexHolder holder(_lock);
687  TextProperties::set_small_caps(small_caps);
688  invalidate_with_measure();
689 }
690 
691 /**
692  *
693  */
694 INLINE void TextNode::
695 clear_small_caps() {
696  MutexHolder holder(_lock);
697  TextProperties::clear_small_caps();
698  invalidate_with_measure();
699 }
700 
701 /**
702  * Sets the scale factor applied to lowercase letters from their uppercase
703  * equivalents, when the small_caps flag is in effect. See set_small_caps().
704  * Normally, this will be a number less than one.
705  */
706 INLINE void TextNode::
707 set_small_caps_scale(PN_stdfloat small_caps_scale) {
708  MutexHolder holder(_lock);
709  TextProperties::set_small_caps_scale(small_caps_scale);
710  invalidate_with_measure();
711 }
712 
713 /**
714  *
715  */
716 INLINE void TextNode::
717 clear_small_caps_scale() {
718  MutexHolder holder(_lock);
719  TextProperties::clear_small_caps_scale();
720  invalidate_with_measure();
721 }
722 
723 /**
724  *
725  */
726 INLINE void TextNode::
727 set_slant(PN_stdfloat slant) {
728  MutexHolder holder(_lock);
730  invalidate_with_measure();
731 }
732 
733 /**
734  *
735  */
736 INLINE void TextNode::
737 clear_slant() {
738  MutexHolder holder(_lock);
739  TextProperties::clear_slant();
740  invalidate_with_measure();
741 }
742 
743 /**
744  *
745  */
746 INLINE void TextNode::
747 set_align(TextNode::Alignment align_type) {
748  MutexHolder holder(_lock);
749  TextProperties::set_align(align_type);
750  invalidate_with_measure();
751 }
752 
753 /**
754  *
755  */
756 INLINE void TextNode::
757 clear_align() {
758  MutexHolder holder(_lock);
760  invalidate_with_measure();
761 }
762 
763 /**
764  * Specifies the amount of extra space that is inserted before the first
765  * character of each line. This can be thought of as a left margin.
766  */
767 INLINE void TextNode::
768 set_indent(PN_stdfloat indent) {
769  MutexHolder holder(_lock);
771  invalidate_with_measure();
772 }
773 
774 /**
775  *
776  */
777 INLINE void TextNode::
778 clear_indent() {
779  MutexHolder holder(_lock);
781  invalidate_with_measure();
782 }
783 
784 /**
785  * Sets the text up to automatically wordwrap when it exceeds the indicated
786  * width. This can be thought of as a right margin or margin width.
787  */
788 INLINE void TextNode::
789 set_wordwrap(PN_stdfloat wordwrap) {
790  MutexHolder holder(_lock);
792  invalidate_with_measure();
793 }
794 
795 /**
796  * Removes the wordwrap setting from the TextNode. Text will be as wide as it
797  * is.
798  */
799 INLINE void TextNode::
800 clear_wordwrap() {
801  MutexHolder holder(_lock);
803  invalidate_with_measure();
804 }
805 
806 /**
807  *
808  */
809 INLINE void TextNode::
810 set_text_color(const LColor &text_color) {
811  MutexHolder holder(_lock);
812  TextProperties::set_text_color(text_color);
813  invalidate_no_measure();
814 }
815 
816 /**
817  *
818  */
819 INLINE void TextNode::
820 set_text_color(PN_stdfloat r, PN_stdfloat g, PN_stdfloat b, PN_stdfloat a) {
821  set_text_color(LColor(r, g, b, a));
822 }
823 
824 /**
825  * Removes the text color specification; the text will be colored whatever it
826  * was in the source font file.
827  */
828 INLINE void TextNode::
829 clear_text_color() {
830  MutexHolder holder(_lock);
832  invalidate_no_measure();
833 }
834 
835 /**
836  *
837  */
838 INLINE void TextNode::
839 set_shadow_color(PN_stdfloat r, PN_stdfloat g, PN_stdfloat b, PN_stdfloat a) {
840  set_shadow_color(LColor(r, g, b, a));
841 }
842 
843 /**
844  *
845  */
846 INLINE void TextNode::
847 set_shadow_color(const LColor &shadow_color) {
848  MutexHolder holder(_lock);
849  TextProperties::set_shadow_color(shadow_color);
850  invalidate_no_measure();
851 }
852 
853 /**
854  *
855  */
856 INLINE void TextNode::
857 clear_shadow_color() {
858  MutexHolder holder(_lock);
860  invalidate_with_measure();
861 }
862 
863 /**
864  * Specifies that the text should be drawn with a shadow, by creating a second
865  * copy of the text and offsetting it slightly behind the first.
866  */
867 INLINE void TextNode::
868 set_shadow(PN_stdfloat xoffset, PN_stdfloat yoffset) {
869  set_shadow(LVecBase2(xoffset, yoffset));
870 }
871 
872 /**
873  * Specifies that the text should be drawn with a shadow, by creating a second
874  * copy of the text and offsetting it slightly behind the first.
875  */
876 INLINE void TextNode::
877 set_shadow(const LVecBase2 &shadow_offset) {
878  MutexHolder holder(_lock);
879  TextProperties::set_shadow(shadow_offset);
880  invalidate_no_measure();
881 }
882 
883 /**
884  * Specifies that a shadow will not be drawn behind the text.
885  */
886 INLINE void TextNode::
887 clear_shadow() {
888  MutexHolder holder(_lock);
890  invalidate_no_measure();
891 }
892 
893 /**
894  * Names the GeomBin that the TextNode geometry should be assigned to. If
895  * this is set, then a GeomBinTransition will be created to explicitly place
896  * each component in the named bin.
897  *
898  * The draw_order value will also be passed to each GeomBinTransition as
899  * appropriate; this is particularly useful if this names a GeomBinFixed, e.g.
900  * "fixed".
901  */
902 INLINE void TextNode::
903 set_bin(const std::string &bin) {
904  MutexHolder holder(_lock);
906  invalidate_no_measure();
907 }
908 
909 /**
910  * Removes the effect of a previous call to set_bin(). Text will be drawn in
911  * whatever bin it would like to be drawn in, with no explicit ordering.
912  */
913 INLINE void TextNode::
914 clear_bin() {
915  MutexHolder holder(_lock);
917  invalidate_no_measure();
918 }
919 
920 /**
921  * Sets the drawing order of text created by the TextMaker. This is actually
922  * the draw order of the card and frame. The shadow is drawn at
923  * _draw_order+1, and the text at _draw_order+2.
924  *
925  * This affects the sorting order assigned to the arcs as they are created,
926  * and also is passed to whatever bin may be assigned via set_bin().
927  *
928  * The return value is the first unused draw_order number, e.g. _draw_order +
929  * 3.
930  */
931 INLINE int TextNode::
932 set_draw_order(int draw_order) {
933  MutexHolder holder(_lock);
934  invalidate_no_measure();
935  return TextProperties::set_draw_order(draw_order);
936 }
937 
938 /**
939  *
940  */
941 INLINE void TextNode::
942 clear_draw_order() {
943  MutexHolder holder(_lock);
944  TextProperties::clear_draw_order();
945  invalidate_with_measure();
946 }
947 
948 /**
949  * Sets the width of each tab stop, in screen units. A tab character embedded
950  * in the text will advance the horizontal position to the next tab stop.
951  */
952 INLINE void TextNode::
953 set_tab_width(PN_stdfloat tab_width) {
954  MutexHolder holder(_lock);
956  invalidate_with_measure();
957 }
958 
959 /**
960  *
961  */
962 INLINE void TextNode::
963 clear_tab_width() {
964  MutexHolder holder(_lock);
965  TextProperties::clear_tab_width();
966  invalidate_with_measure();
967 }
968 
969 /**
970  * Specifies the factor by which to scale each letter of the text as it is
971  * placed. This can be used (possibly in conjunction with set_glyph_shift())
972  * to implement superscripting or subscripting.
973  */
974 INLINE void TextNode::
975 set_glyph_scale(PN_stdfloat glyph_scale) {
976  MutexHolder holder(_lock);
977  TextProperties::set_glyph_scale(glyph_scale);
978  invalidate_with_measure();
979 }
980 
981 /**
982  *
983  */
984 INLINE void TextNode::
985 clear_glyph_scale() {
986  MutexHolder holder(_lock);
987  TextProperties::clear_glyph_scale();
988  invalidate_with_measure();
989 }
990 
991 /**
992  * Specifies a vertical amount to shift each letter of the text as it is
993  * placed. This can be used (possibly in conjunction with set_glyph_scale())
994  * to implement superscripting or subscripting.
995  */
996 INLINE void TextNode::
997 set_glyph_shift(PN_stdfloat glyph_shift) {
998  MutexHolder holder(_lock);
999  TextProperties::set_glyph_shift(glyph_shift);
1000  invalidate_with_measure();
1001 }
1002 
1003 /**
1004  *
1005  */
1006 INLINE void TextNode::
1007 clear_glyph_shift() {
1008  MutexHolder holder(_lock);
1009  TextProperties::clear_glyph_shift();
1010  invalidate_with_measure();
1011 }
1012 
1013 /**
1014  * Returns a string that represents the contents of the text, as it has been
1015  * formatted by wordwrap rules.
1016  *
1017  * In earlier versions, this did not contain any embedded special characters
1018  * like \1 or \3; now it does.
1019  */
1020 INLINE std::string TextNode::
1023 }
1024 
1025 /**
1026  * Returns the width of a line of text of arbitrary characters. The line
1027  * should not include the newline character.
1028  */
1029 INLINE PN_stdfloat TextNode::
1030 calc_width(const std::string &line) const {
1031  return calc_width(decode_text(line));
1032 }
1033 
1034 /**
1035  * Returns a wstring that represents the contents of the text, as it has been
1036  * formatted by wordwrap rules.
1037  *
1038  * In earlier versions, this did not contain any embedded special characters
1039  * like \1 or \3; now it does.
1040  */
1041 INLINE std::wstring TextNode::
1043  MutexHolder holder(_lock);
1044  check_measure();
1045  return _wordwrapped_wtext;
1046 }
1047 
1048 /**
1049  * Returns the leftmost extent of the text in local 2-d coordinates,
1050  * unmodified by the set_transform() matrix.
1051  */
1052 INLINE PN_stdfloat TextNode::
1053 get_left() const {
1054  MutexHolder holder(_lock);
1055  check_measure();
1056  return _text_ul[0];
1057 }
1058 
1059 /**
1060  * Returns the rightmost extent of the text in local 2-d coordinates,
1061  * unmodified by the set_transform() matrix.
1062  */
1063 INLINE PN_stdfloat TextNode::
1064 get_right() const {
1065  MutexHolder holder(_lock);
1066  check_measure();
1067  return _text_lr[0];
1068 }
1069 
1070 /**
1071  * Returns the bottommost extent of the text in local 2-d coordinates,
1072  * unmodified by the set_transform() matrix.
1073  */
1074 INLINE PN_stdfloat TextNode::
1075 get_bottom() const {
1076  MutexHolder holder(_lock);
1077  check_measure();
1078  return _text_lr[1];
1079 }
1080 
1081 /**
1082  * Returns the topmost extent of the text in local 2-d coordinates, unmodified
1083  * by the set_transform() matrix.
1084  */
1085 INLINE PN_stdfloat TextNode::
1086 get_top() const {
1087  MutexHolder holder(_lock);
1088  check_measure();
1089  return _text_ul[1];
1090 }
1091 
1092 /**
1093  * Returns the net height of the text in local 2-d coordinates.
1094  */
1095 INLINE PN_stdfloat TextNode::
1096 get_height() const {
1097  MutexHolder holder(_lock);
1098  check_measure();
1099  return _text_ul[1] - _text_lr[1];
1100 }
1101 
1102 /**
1103  * Returns the net width of the text in local 2-d coordinates.
1104  */
1105 INLINE PN_stdfloat TextNode::
1106 get_width() const {
1107  MutexHolder holder(_lock);
1108  check_measure();
1109  return _text_lr[0] - _text_ul[0];
1110 }
1111 
1112 /**
1113  * Returns the upper-left extent of the text object, after it has been
1114  * transformed into 3-d space by applying the set_transform() matrix.
1115  */
1116 INLINE LPoint3 TextNode::
1118  MutexHolder holder(_lock);
1119  check_measure();
1120  return _ul3d;
1121 }
1122 
1123 /**
1124  * Returns the lower-right extent of the text object, after it has been
1125  * transformed into 3-d space by applying the set_transform() matrix.
1126  */
1127 INLINE LPoint3 TextNode::
1129  MutexHolder holder(_lock);
1130  check_measure();
1131  return _lr3d;
1132 }
1133 
1134 /**
1135  * Returns the number of rows of text that were generated. This counts word-
1136  * wrapped rows as well as rows generated due to embedded newlines.
1137  */
1138 INLINE int TextNode::
1139 get_num_rows() const {
1140  MutexHolder holder(_lock);
1141  check_measure();
1142  return _num_rows;
1143 }
1144 
1145 /**
1146  * Generates the text, according to the parameters indicated within the
1147  * TextNode, and returns a Node that may be parented within the tree to
1148  * represent it.
1149  */
1150 PT(PandaNode) TextNode::
1151 generate() {
1152  MutexHolder holder(_lock);
1153  return do_generate();
1154 }
1155 
1156 /**
1157  * Can be called after the TextNode has been fully configured, to force the
1158  * node to recompute its text immediately, rather than waiting for it to be
1159  * drawn. This call is optional.
1160  */
1161 INLINE void TextNode::
1163  MutexHolder holder(_lock);
1164  check_rebuild();
1165 }
1166 
1167 /**
1168  * Forces the TextNode to recompute itself now, even if it believes nothing
1169  * has changed. Normally, this should not need to be called, but it may be
1170  * useful if some properties change outside of the TextNode's knowledge (for
1171  * instance, within the font).
1172  */
1173 INLINE void TextNode::
1175  MutexHolder holder(_lock);
1176  mark_internal_bounds_stale();
1177  do_rebuild();
1178 }
1179 
1180 /**
1181  * Called internally whenever some state on the TextNode changes, requiring
1182  * the internal geometry to be recomputed, but which will not result in a
1183  * change in the size or shape of the text (for instance, the text color
1184  * changes).
1185  */
1186 INLINE void TextNode::
1187 invalidate_no_measure() {
1188  _flags |= F_needs_rebuild;
1189 }
1190 
1191 /**
1192  * Called internally whenever some state on the TextNode changes, requiring
1193  * the internal geometry to be recomputed, and which will may result in a
1194  * change in the size or shape of the text (for instance, the text scale
1195  * changes).
1196  */
1197 INLINE void TextNode::
1198 invalidate_with_measure() {
1199  _flags |= (F_needs_rebuild | F_needs_measure);
1200  mark_internal_bounds_stale();
1201 }
1202 
1203 /**
1204  * Called internally to call do_rebuild() if necessary (that is, if the
1205  * internal geometry has changed recently).
1206  */
1207 INLINE void TextNode::
1208 check_rebuild() const {
1209  if ((_flags & F_needs_rebuild) != 0) {
1210  ((TextNode *)this)->do_rebuild();
1211  }
1212 }
1213 
1214 /**
1215  * Called internally to call do_measure() if necessary; this will remeasure
1216  * the text without necessarily rebuilding it.
1217  */
1218 INLINE void TextNode::
1219 check_measure() const {
1220  if ((_flags & F_needs_measure) != 0) {
1221  ((TextNode *)this)->do_measure();
1222  }
1223 }
set_align
Specifies the alignment of the text within its margins.
set_usage_hint
Specifies the UsageHint that will be applied to generated geometry.
Definition: textNode.h:233
void clear_frame()
Specifies that a border will not be drawn around the text.
Definition: textNode.I:277
A basic node of the scene graph or data graph.
Definition: pandaNode.h:64
LVecBase4 get_card_as_set() const
Returns the dimensions of the card as set by set_card_as_margin() or set_card_actual().
Definition: textNode.I:487
set_coordinate_system
Specifies the coordinate system in which the text will be generated.
Definition: textNode.h:232
set_small_caps
Sets the small_caps flag.
Definition: textNode.h:238
void clear_max_rows()
Resets the TextNode's default behavior of not limiting the number of rows of text.
Definition: textNode.I:46
LPoint3 get_upper_left_3d() const
Returns the upper-left extent of the text object, after it has been transformed into 3-d space by app...
Definition: textNode.I:1117
void set_card_actual(PN_stdfloat left, PN_stdfloat right, PN_stdfloat bottom, PN_stdfloat top)
Similar to set_card_as_margin, except the card is specified in actual coordinate units (relative to t...
Definition: textNode.I:413
LVecBase4 get_frame_as_set() const
Returns the dimensions of the frame as set by set_frame_as_margin() or set_frame_actual().
Definition: textNode.I:313
set_tab_width
Sets the width of each tab stop, in screen units.
Definition: textNode.h:261
PN_stdfloat get_top() const
Returns the topmost extent of the text in local 2-d coordinates, unmodified by the set_transform() ma...
Definition: textNode.I:1086
void clear_card()
Specifies that a card will not be drawn behind the text.
Definition: textNode.I:442
set_glyph_scale
Specifies the factor by which to scale each letter of the text as it is placed, in addition to any sc...
bool has_overflow() const
Returns true if the last text set on the text node exceeded the max_rows constraint,...
Definition: textNode.I:77
Represents a texture object, which is typically a single 2-d image but may also represent a 1-d or 3-...
Definition: texture.h:71
PN_stdfloat get_bottom() const
Returns the bottommost extent of the text in local 2-d coordinates, unmodified by the set_transform()...
Definition: textNode.I:1075
clear_wordwrap
Removes the wordwrap setting from the text.
set_flatten_flags
Sets the flatten flags.
Definition: textNode.h:234
PN_stdfloat get_left() const
Returns the leftmost extent of the text in local 2-d coordinates, unmodified by the set_transform() m...
Definition: textNode.I:1053
set_shadow
Specifies that the text should be drawn with a shadow, by creating a second copy of the text and offs...
Definition: textNode.h:256
A lightweight C++ object whose constructor calls acquire() and whose destructor calls release() on a ...
Definition: mutexHolder.h:25
void set_frame_as_margin(PN_stdfloat left, PN_stdfloat right, PN_stdfloat bottom, PN_stdfloat top)
Specifies that a border will be drawn around the text when it is next created.
Definition: textNode.I:249
bool has_max_rows() const
Returns true if a limit on the height of the TextNode has been set via set_max_rows(),...
Definition: textNode.I:57
PN_stdfloat get_width() const
Returns the net width of the text in local 2-d coordinates.
Definition: textNode.I:1106
set_max_rows
Sets the maximum number of rows that may be formatted by the TextNode.
Definition: textNode.h:225
An encapsulation of a font; i.e.
Definition: textFont.h:32
set_tab_width
Sets the width of each tab stop, in screen units.
set_draw_order
Sets the drawing order of text created by the TextMaker.
Definition: textNode.h:259
set_shadow
Specifies that the text should be drawn with a shadow, by creating a second copy of the text and offs...
bool get_card_decal() const
Returns the card_decal flag.
Definition: textNode.I:461
void set_card_as_margin(PN_stdfloat left, PN_stdfloat right, PN_stdfloat bottom, PN_stdfloat top)
Specifies that a (possibly opaque or semitransparent) card will be held behind the text when it is ne...
Definition: textNode.I:398
LVecBase4 get_frame_actual() const
Returns the actual dimensions of the frame around the text.
Definition: textNode.I:329
set_transform
Sets an additional transform that is applied to the entire text paragraph.
Definition: textNode.h:231
PT(PandaNode) TextNode
Generates the text, according to the parameters indicated within the TextNode, and returns a Node tha...
Definition: textNode.I:1150
set_draw_order
Sets the drawing order of text created by the TextNode.
set_small_caps
Sets the small_caps flag.
std::ostream & indent(std::ostream &out, int indent_level)
A handy function for doing text formatting.
Definition: indent.cxx:20
clear_shadow_color
Removes the shadow color specification.
set_wordwrap
Sets the text up to automatically wordwrap when it exceeds the indicated width.
clear_text_color
Removes the text color specification; the text will be colored whatever it was in the source font fil...
bool is_card_as_margin() const
If this is true, the card was set via a call to set_card_as_margin(), and the dimension of the card a...
Definition: textNode.I:474
void update()
Can be called after the TextNode has been fully configured, to force the node to recompute its text i...
Definition: textNode.I:1162
set_indent
Specifies the amount of extra space that is inserted before the first character of each line.
Definition: textNode.h:247
set_wordwrap
Sets the text up to automatically wordwrap when it exceeds the indicated width.
Definition: textNode.h:248
clear_shadow
Specifies that a shadow will not be drawn behind the text.
void set_card_decal(bool card_decal)
Sets the card_decal flag.
Definition: textNode.I:428
set_frame_corners
Enables or disables the drawing of corners for the frame.
Definition: textNode.h:230
LVecBase4 get_card_actual() const
Returns the actual dimensions of the card around the text.
Definition: textNode.I:503
set_glyph_scale
Specifies the factor by which to scale each letter of the text as it is placed.
Definition: textNode.h:263
get_line_height
Returns the number of units high each line of text is.
Definition: textFont.h:69
std::string encode_wtext(const std::wstring &wtext) const
Encodes a wide-text string into a single-char string, according to the current encoding.
Definition: textEncoder.I:481
std::string get_wordwrapped_text() const
Returns a string that represents the contents of the text, as it has been formatted by wordwrap rules...
Definition: textNode.I:1021
set_glyph_shift
Specifies a vertical amount to shift each letter of the text as it is placed.
set_slant
Specifies the factor by which the text slants to the right.
std::wstring get_wordwrapped_wtext() const
Returns a wstring that represents the contents of the text, as it has been formatted by wordwrap rule...
Definition: textNode.I:1042
set_indent
Specifies the amount of extra space that is inserted before the first character of each line.
set_glyph_shift
Specifies a vertical amount to shift each letter of the text as it is placed.
Definition: textNode.h:265
LPoint3 get_lower_right_3d() const
Returns the lower-right extent of the text object, after it has been transformed into 3-d space by ap...
Definition: textNode.I:1128
set_bin
Names the CullBin that the text geometry should be assigned to.
clear_font
Restores the default font to the text.
clear_align
Restores the default alignment of the text.
The primary interface to this module.
Definition: textNode.h:48
set_bin
Names the GeomBin that the TextNode geometry should be assigned to.
Definition: textNode.h:257
PN_stdfloat get_line_height() const
Returns the number of units high each line of text is.
Definition: textNode.I:20
set_small_caps_scale
Sets the scale factor applied to lowercase letters from their uppercase equivalents,...
LVecBase4 get_card_transformed() const
Returns the actual card dimensions, transformed by the matrix set by set_transform().
Definition: textNode.I:528
PN_stdfloat get_right() const
Returns the rightmost extent of the text in local 2-d coordinates, unmodified by the set_transform() ...
Definition: textNode.I:1064
int get_num_rows() const
Returns the number of rows of text that were generated.
Definition: textNode.I:1139
set_font
Sets the font that will be used when making text.
clear_indent
Removes the indent setting from the text.
void force_update()
Forces the TextNode to recompute itself now, even if it believes nothing has changed.
Definition: textNode.I:1174
set_small_caps_scale
Sets the scale factor applied to lowercase letters from their uppercase equivalents,...
Definition: textNode.h:240
std::wstring decode_text(const std::string &text) const
Returns the given wstring decoded to a single-byte string, via the current encoding system.
Definition: textEncoder.I:490
void set_frame_actual(PN_stdfloat left, PN_stdfloat right, PN_stdfloat bottom, PN_stdfloat top)
Similar to set_frame_as_margin, except the frame is specified in actual coordinate units (relative to...
Definition: textNode.I:264
PN_stdfloat calc_width(wchar_t character) const
Returns the width of a single character of the font, or 0.0 if the character is not known.
Definition: textNode.cxx:177
set_frame_line_width
Specifies the thickness of the lines that will be used to draw the frame.
Definition: textNode.h:229
PN_stdfloat get_height() const
Returns the net height of the text in local 2-d coordinates.
Definition: textNode.I:1096
bool is_frame_as_margin() const
If this is true, the frame was set via a call to set_frame_as_margin(), and the dimension of the fram...
Definition: textNode.I:300
clear_bin
Removes the effect of a previous call to set_bin().
set_font
Sets the font that will be used when making text.
Definition: textNode.h:236