// Filename: textAssembler.I // Created by: drose (06Apr04) // //////////////////////////////////////////////////////////////////// // // PANDA 3D SOFTWARE // Copyright (c) Carnegie Mellon University. All rights reserved. // // All use of this software is subject to the terms of the revised BSD // license. You should have received a copy of this license along // with this source code in a file named "LICENSE." // //////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////// // Function: TextAssembler::set_usage_hint // Access: Published // Description: Specifies the UsageHint that will be applied to // generated geometry. The default is UH_static, which // is probably the right setting, but if you know the // TextNode's geometry will have a short lifespan, it // may be better to set it to UH_stream. See // geomEnums.h. //////////////////////////////////////////////////////////////////// INLINE void TextAssembler:: set_usage_hint(Geom::UsageHint usage_hint) { _usage_hint = usage_hint; } //////////////////////////////////////////////////////////////////// // Function: TextAssembler::get_usage_hint // Access: Published // Description: Returns the UsageHint that will be applied to // generated geometry. See set_usage_hint(). //////////////////////////////////////////////////////////////////// INLINE Geom::UsageHint TextAssembler:: get_usage_hint() const { return _usage_hint; } //////////////////////////////////////////////////////////////////// // Function: TextAssembler::set_max_rows // Access: Published // Description: If max_rows is greater than zero, no more than // max_rows will be accepted. Text beyond that will be // truncated. // // Setting this will not truncate text immediately. You // must follow this up with a call to set_wtext() to // truncate the existing text. //////////////////////////////////////////////////////////////////// INLINE void TextAssembler:: set_max_rows(int max_rows) { _max_rows = max_rows; } //////////////////////////////////////////////////////////////////// // Function: TextAssembler::get_max_rows // Access: Published // Description: If max_rows is greater than zero, no more than // max_rows will be accepted. Text beyond that will be // truncated. //////////////////////////////////////////////////////////////////// INLINE int TextAssembler:: get_max_rows() const { return _max_rows; } //////////////////////////////////////////////////////////////////// // Function: TextAssembler::set_dynamic_merge // Access: Published // Description: Sets the dynamic_merge flag. See // TextNode::set_flatten_flags(). //////////////////////////////////////////////////////////////////// INLINE void TextAssembler:: set_dynamic_merge(bool dynamic_merge) { _dynamic_merge = dynamic_merge; } //////////////////////////////////////////////////////////////////// // Function: TextAssembler::get_dynamic_merge // Access: Published // Description: Returns the dynamic_merge flag. See // TextNode::set_flatten_flags(). //////////////////////////////////////////////////////////////////// INLINE bool TextAssembler:: get_dynamic_merge() const { return _dynamic_merge; } //////////////////////////////////////////////////////////////////// // Function: TextAssembler::set_multiline_mode // Access: Published // Description: Sets the multiline mode flag. Set the multiline // mode to allow text to wrap. It defaults to true. //////////////////////////////////////////////////////////////////// INLINE void TextAssembler:: set_multiline_mode(bool flag) { _multiline_mode = flag; } //////////////////////////////////////////////////////////////////// // Function: TextAssembler::get_multiline_mode // Access: Published // Description: Returns the multline_mode flag. See // TextNode::set_multiline_mode(). //////////////////////////////////////////////////////////////////// INLINE bool TextAssembler:: get_multiline_mode() const { return _multiline_mode; } //////////////////////////////////////////////////////////////////// // Function: TextAssembler::set_properties // Access: Published // Description: Specifies the default TextProperties that are applied // to the text in the absence of any nested property // change sequences. //////////////////////////////////////////////////////////////////// INLINE void TextAssembler:: set_properties(const TextProperties &properties) { _initial_cprops = new ComputedProperties(properties); } //////////////////////////////////////////////////////////////////// // Function: TextAssembler::get_properties // Access: Published // Description: Returns the default TextProperties that are applied // to the text in the absence of any nested property // change sequences. //////////////////////////////////////////////////////////////////// INLINE const TextProperties &TextAssembler:: get_properties() const { return _initial_cprops->_properties; } //////////////////////////////////////////////////////////////////// // Function: TextAssembler::get_ul // Access: Published // Description: Returns the upper-left corner of the assembled text, // in 2-d text coordinates. //////////////////////////////////////////////////////////////////// INLINE const LVector2f &TextAssembler:: get_ul() const { return _ul; } //////////////////////////////////////////////////////////////////// // Function: TextAssembler::get_lr // Access: Published // Description: Returns the lower-right corner of the assembled text, // in 2-d text coordinates. //////////////////////////////////////////////////////////////////// INLINE const LVector2f &TextAssembler:: get_lr() const { return _lr; } //////////////////////////////////////////////////////////////////// // Function: TextAssembler::calc_r // Access: Published // Description: Computes the row index of the nth character or // graphic object in the text and returns it. // // If the nth character is not a normal printable // character with a position in the wordwrapped string, // returns -1 (for instance, a soft-hyphen character, or // a newline character, may not have a corresponding // position). //////////////////////////////////////////////////////////////////// int TextAssembler:: calc_r(int n) const { int r, c; if (calc_r_c(r, c, n)) { return r; } return -1; } //////////////////////////////////////////////////////////////////// // Function: TextAssembler::calc_c // Access: Published // Description: Computes the column index of the nth character or // graphic object in the text and returns it. // // If the nth character is not a normal printable // character with a position in the wordwrapped string, // returns -1 (for instance, a soft-hyphen character, or // a newline character, may not have a corresponding // position). //////////////////////////////////////////////////////////////////// int TextAssembler:: calc_c(int n) const { int r, c; if (calc_r_c(r, c, n)) { return c; } return -1; } //////////////////////////////////////////////////////////////////// // Function: TextAssembler::get_num_characters // Access: Published // Description: Returns the number of characters of text, before // wordwrapping. //////////////////////////////////////////////////////////////////// INLINE int TextAssembler:: get_num_characters() const { return _text_string.size(); } //////////////////////////////////////////////////////////////////// // Function: TextAssembler::get_character // Access: Published // Description: Returns the character at the indicated position in // the pre-wordwrapped string. If the object at this // position is a graphic object instead of a character, // returns 0. //////////////////////////////////////////////////////////////////// INLINE wchar_t TextAssembler:: get_character(int n) const { nassertr(n >= 0 && n < (int)_text_string.size(), 0); return _text_string[n]._character; } //////////////////////////////////////////////////////////////////// // Function: TextAssembler::get_graphic // Access: Published // Description: Returns the graphic object at the indicated position // in the pre-wordwrapped string. If the object at this // position is a character instead of a graphic object, // returns NULL. //////////////////////////////////////////////////////////////////// INLINE const TextGraphic *TextAssembler:: get_graphic(int n) const { nassertr(n >= 0 && n < (int)_text_string.size(), 0); return _text_string[n]._graphic; } //////////////////////////////////////////////////////////////////// // Function: TextAssembler::get_properties // Access: Published // Description: Returns the TextProperties in effect for the object // at the indicated position in the pre-wordwrapped // string. //////////////////////////////////////////////////////////////////// INLINE const TextProperties &TextAssembler:: get_properties(int n) const { nassertr(n >= 0 && n < (int)_text_string.size(), *(new TextProperties())); return _text_string[n]._cprops->_properties; } //////////////////////////////////////////////////////////////////// // Function: TextAssembler::get_width // Access: Published // Description: Returns the width of the character or object at the // indicated position in the pre-wordwrapped string. //////////////////////////////////////////////////////////////////// INLINE float TextAssembler:: get_width(int n) const { nassertr(n >= 0 && n < (int)_text_string.size(), 0.0f); return calc_width(_text_string[n]); } //////////////////////////////////////////////////////////////////// // Function: TextAssembler::get_num_rows // Access: Published // Description: Returns the number of rows of text after it has all // been wordwrapped and assembled. //////////////////////////////////////////////////////////////////// INLINE int TextAssembler:: get_num_rows() const { return _text_block.size(); } //////////////////////////////////////////////////////////////////// // Function: TextAssembler::get_num_cols // Access: Published // Description: Returns the number of characters and/or graphic // objects in the nth row. //////////////////////////////////////////////////////////////////// INLINE int TextAssembler:: get_num_cols(int r) const { nassertr(r >= 0 && r <= (int)_text_block.size(), 0); if (r == (int)_text_block.size()) { return 0; } return _text_block[r]._string.size(); } //////////////////////////////////////////////////////////////////// // Function: TextAssembler::get_character // Access: Published // Description: Returns the character at the indicated position in // the indicated row. If the object at this position is // a graphic object instead of a character, returns 0. //////////////////////////////////////////////////////////////////// INLINE wchar_t TextAssembler:: get_character(int r, int c) const { nassertr(r >= 0 && r < (int)_text_block.size(), 0); nassertr(c >= 0 && c < (int)_text_block[r]._string.size(), 0); return _text_block[r]._string[c]._character; } //////////////////////////////////////////////////////////////////// // Function: TextAssembler::get_graphic // Access: Published // Description: Returns the graphic object at the indicated position // in the indicated row. If the object at this position // is a character instead of a graphic object, returns // NULL. //////////////////////////////////////////////////////////////////// INLINE const TextGraphic *TextAssembler:: get_graphic(int r, int c) const { nassertr(r >= 0 && r < (int)_text_block.size(), 0); nassertr(c >= 0 && c < (int)_text_block[r]._string.size(), 0); return _text_block[r]._string[c]._graphic; } //////////////////////////////////////////////////////////////////// // Function: TextAssembler::get_properties // Access: Published // Description: Returns the TextProperties in effect for the object // at the indicated position in the indicated row. //////////////////////////////////////////////////////////////////// INLINE const TextProperties &TextAssembler:: get_properties(int r, int c) const { nassertr(r >= 0 && r < (int)_text_block.size(), *(new TextProperties())); nassertr(c >= 0 && c < (int)_text_block[r]._string.size(), *(new TextProperties())); return _text_block[r]._string[c]._cprops->_properties; } //////////////////////////////////////////////////////////////////// // Function: TextAssembler::get_width // Access: Published // Description: Returns the width of the character or object at the // indicated position in the indicated row. //////////////////////////////////////////////////////////////////// INLINE float TextAssembler:: get_width(int r, int c) const { nassertr(r >= 0 && r < (int)_text_block.size(), 0.0f); nassertr(c >= 0 && c < (int)_text_block[r]._string.size(), 0.0f); return calc_width(_text_block[r]._string[c]); } //////////////////////////////////////////////////////////////////// // Function: TextAssembler::get_ypos // Access: Published // Description: Returns the y position of the origin of all of the // characters or graphic objects in the indicated row. // // It is legal for r to exceed the index number of the // last row by 1. The value of c is presently ignored. //////////////////////////////////////////////////////////////////// INLINE float TextAssembler:: get_ypos(int r, int) const { nassertr(r >= 0 && r <= (int)_text_block.size(), 0.0f); if (r == (int)_text_block.size()) { return _next_row_ypos; } else { return _text_block[r]._ypos; } } //////////////////////////////////////////////////////////////////// // Function: TextAssembler::calc_width // Access: Private, Static // Description: Returns the width of a single character, according to // its associated font. //////////////////////////////////////////////////////////////////// INLINE float TextAssembler:: calc_width(const TextCharacter &tch) { if (tch._graphic != (TextGraphic *)NULL) { return calc_width(tch._graphic, tch._cprops->_properties); } else { return calc_width(tch._character, tch._cprops->_properties); } } //////////////////////////////////////////////////////////////////// // Function: TextAssembler::TextCharacter::Constructor // Access: Public // Description: //////////////////////////////////////////////////////////////////// INLINE TextAssembler::TextCharacter:: TextCharacter(wchar_t character, TextAssembler::ComputedProperties *cprops) : _character(character), _graphic(NULL), _cprops(cprops) { } //////////////////////////////////////////////////////////////////// // Function: TextAssembler::TextCharacter::Constructor // Access: Public // Description: //////////////////////////////////////////////////////////////////// INLINE TextAssembler::TextCharacter:: TextCharacter(const TextGraphic *graphic, const wstring &graphic_wname, TextAssembler::ComputedProperties *cprops) : _character(0), _graphic(graphic), _graphic_wname(graphic_wname), _cprops(cprops) { } //////////////////////////////////////////////////////////////////// // Function: TextAssembler::TextCharacter::Copy Constructor // Access: Public // Description: //////////////////////////////////////////////////////////////////// INLINE TextAssembler::TextCharacter:: TextCharacter(const TextAssembler::TextCharacter ©) : _character(copy._character), _graphic(copy._graphic), _graphic_wname(copy._graphic_wname), _cprops(copy._cprops) { } //////////////////////////////////////////////////////////////////// // Function: TextAssembler::TextCharacter::Copy Assignment // Access: Public // Description: //////////////////////////////////////////////////////////////////// INLINE void TextAssembler::TextCharacter:: operator = (const TextAssembler::TextCharacter ©) { _character = copy._character; _graphic = copy._graphic; _graphic_wname = copy._graphic_wname; _cprops = copy._cprops; } //////////////////////////////////////////////////////////////////// // Function: TextAssembler::TextRow::Constructor // Access: Public // Description: //////////////////////////////////////////////////////////////////// INLINE TextAssembler::TextRow:: TextRow(int row_start) : _row_start(row_start), _got_soft_hyphens(false), _xpos(0.0f), _ypos(0.0f) { } //////////////////////////////////////////////////////////////////// // Function: TextAssembler::TextRow::Copy Constructor // Access: Public // Description: //////////////////////////////////////////////////////////////////// INLINE TextAssembler::TextRow:: TextRow(const TextAssembler::TextRow ©) : _string(copy._string), _row_start(copy._row_start), _got_soft_hyphens(copy._got_soft_hyphens), _xpos(copy._xpos), _ypos(copy._ypos), _eol_cprops(copy._eol_cprops) { } //////////////////////////////////////////////////////////////////// // Function: TextAssembler::TextRow::Copy Assignment // Access: Public // Description: //////////////////////////////////////////////////////////////////// INLINE void TextAssembler::TextRow:: operator = (const TextAssembler::TextRow ©) { _string = copy._string; _row_start = copy._row_start; _got_soft_hyphens = copy._got_soft_hyphens; _xpos = copy._xpos; _ypos = copy._ypos; _eol_cprops = copy._eol_cprops; } //////////////////////////////////////////////////////////////////// // Function: TextAssembler::ComputedProperties::Constructor // Access: Public // Description: //////////////////////////////////////////////////////////////////// INLINE TextAssembler::ComputedProperties:: ComputedProperties(const TextProperties &orig_properties) : _based_on(NULL), _depth(0), _properties(orig_properties) { } //////////////////////////////////////////////////////////////////// // Function: TextAssembler::ComputedProperties::Constructor // Access: Public // Description: //////////////////////////////////////////////////////////////////// INLINE TextAssembler::ComputedProperties:: ComputedProperties(ComputedProperties *based_on, const wstring &wname, TextEncoder *encoder) : _based_on(based_on), _depth(_based_on->_depth + 1), _wname(wname), _properties(based_on->_properties) { TextPropertiesManager *manager = TextPropertiesManager::get_global_ptr(); // Now we have to encode the wstring into a string, for lookup // in the TextPropertiesManager. string name = encoder->encode_wtext(wname); const TextProperties *named_props = manager->get_properties_ptr(name); if (named_props != (TextProperties *)NULL) { _properties.add_properties(*named_props); } else { text_cat.warning() << "Unknown TextProperties: " << name << "\n"; } } //////////////////////////////////////////////////////////////////// // Function: TextAssembler::GlyphPlacement::add_piece // Access: Public // Description: Adds a piece of the glyph, consisting of a single // Geom and an associated RenderState. Typically, a // glyph will have exactly one piece; there will only be // multiple pieces in the case of cheesy accent marks or // ligatures. //////////////////////////////////////////////////////////////////// INLINE void TextAssembler::GlyphPlacement:: add_piece(Geom *geom, const RenderState *state) { Piece piece; piece._geom = geom; piece._state = state; _pieces.push_back(piece); } //////////////////////////////////////////////////////////////////// // Function: TextAssembler::GeomCollectorKey::Constructor // Access: Public // Description: //////////////////////////////////////////////////////////////////// INLINE TextAssembler::GeomCollectorKey:: GeomCollectorKey(const RenderState *state, const GeomVertexFormat *format) : _state(state), _format(format) { } //////////////////////////////////////////////////////////////////// // Function: TextAssembler::GeomCollectorKey::operator < // Access: Public // Description: //////////////////////////////////////////////////////////////////// INLINE bool TextAssembler::GeomCollectorKey:: operator < (const TextAssembler::GeomCollectorKey &other) const { if (_state != other._state) { return _state < other._state; } return _format < other._format; } //////////////////////////////////////////////////////////////////// // Function: TextAssembler::GeomCollector::count_geom // Access: Public // Description: If the indicated Geom is a GeomTextGlyph, increments // its reference count and adds it into this geom. This // is necessary to keep references to outstanding // glyphs, so we know when it's safe to recycle // no-longer-used glyphs. // // If the indicated Geom is an ordinary Geom, does // nothing. //////////////////////////////////////////////////////////////////// INLINE void TextAssembler::GeomCollector:: count_geom(const Geom *geom) { #ifdef HAVE_FREETYPE _geom->count_geom(geom); #endif }