From 7421fe3e055560e0f3a1ae495276b3b290dfec92 Mon Sep 17 00:00:00 2001 From: David Rose Date: Fri, 31 Jan 2003 23:55:33 +0000 Subject: [PATCH] faster text generation --- panda/src/text/dynamicTextGlyph.cxx | 6 +-- panda/src/text/textGlyph.cxx | 10 ++++- panda/src/text/textNode.I | 22 +++++++++- panda/src/text/textNode.cxx | 66 +++++++++++++++++------------ panda/src/text/textNode.h | 5 ++- 5 files changed, 75 insertions(+), 34 deletions(-) diff --git a/panda/src/text/dynamicTextGlyph.cxx b/panda/src/text/dynamicTextGlyph.cxx index d6bbc58c5e..902dba5dde 100644 --- a/panda/src/text/dynamicTextGlyph.cxx +++ b/panda/src/text/dynamicTextGlyph.cxx @@ -53,7 +53,7 @@ get_geom() const { //////////////////////////////////////////////////////////////////// // Function: DynamicTextGlyph::get_row -// Access: Publiic +// Access: Public // Description: Returns a pointer to the first byte in the pixel // buffer associated with the leftmost pixel in the // indicated row, where 0 is the topmost row and _y_size @@ -79,7 +79,7 @@ get_row(int y) { //////////////////////////////////////////////////////////////////// // Function: DynamicTextGlyph::erase -// Access: Publiic +// Access: Public // Description: Erases the glyph from the texture map. //////////////////////////////////////////////////////////////////// void DynamicTextGlyph:: @@ -99,7 +99,7 @@ erase() { //////////////////////////////////////////////////////////////////// // Function: DynamicTextGlyph::make_geom -// Access: Publiic +// Access: Public // Description: Creates the actual geometry for the glyph. The // parameters bitmap_top and bitmap_left are from // FreeType, and indicate the position of the top left diff --git a/panda/src/text/textGlyph.cxx b/panda/src/text/textGlyph.cxx index ea7ee6c73f..3d6088f1de 100644 --- a/panda/src/text/textGlyph.cxx +++ b/panda/src/text/textGlyph.cxx @@ -34,5 +34,13 @@ TextGlyph:: //////////////////////////////////////////////////////////////////// PT(Geom) TextGlyph:: get_geom() const { - return _geom; + if (_geom == (Geom *)NULL) { + return _geom; + } + + // We always return a copy of the geom. That will allow the caller + // to modify its vertices without fear of stomping on other copies; + // it is also critical for the DynamicTextGlyph, which depends on + // this behavior to properly count references to this glyph. + return _geom->make_copy(); } diff --git a/panda/src/text/textNode.I b/panda/src/text/textNode.I index 72cf9f390b..787ca0e518 100644 --- a/panda/src/text/textNode.I +++ b/panda/src/text/textNode.I @@ -194,7 +194,12 @@ get_expand_amp() const { //////////////////////////////////////////////////////////////////// INLINE float TextNode:: get_line_height() const { - return (_font == (TextFont *)NULL) ? 0.0 : _font->get_line_height(); + if (_font != (TextFont *)NULL) { + return _font->get_line_height(); + } else if (get_default_font() != (TextFont *)NULL) { + return _default_font->get_line_height(); + } + return 0.0f; } //////////////////////////////////////////////////////////////////// @@ -1305,6 +1310,21 @@ update() { check_rebuild(); } +//////////////////////////////////////////////////////////////////// +// Function: TextNode::force_update +// Access: Published +// Description: Forces the TextNode to recompute itself now, even if +// it believes nothing has changed. Normally, this +// should not need to be called, but it may be useful if +// some properties change outside of the TextNode's +// knowledge (for instance, within the font). +//////////////////////////////////////////////////////////////////// +INLINE void TextNode:: +force_update() { + invalidate_with_measure(); + check_rebuild(); +} + //////////////////////////////////////////////////////////////////// // Function: TextNode::set_wtext // Access: Public diff --git a/panda/src/text/textNode.cxx b/panda/src/text/textNode.cxx index 56e849f690..934bb7d0cb 100644 --- a/panda/src/text/textNode.cxx +++ b/panda/src/text/textNode.cxx @@ -294,7 +294,8 @@ generate() { assemble_text(wtext.begin(), wtext.end(), font, ul, lr, num_rows); - // Parent the text in. + // Parent the text in. We create an intermediate node so we can + // choose to reinstance the text_root as the shadow, below. PT(PandaNode) text = new PandaNode("text"); root->add_child(text, _draw_order + 2); text->add_child(text_root); @@ -883,7 +884,7 @@ do_measure() { //////////////////////////////////////////////////////////////////// float TextNode:: assemble_row(wstring::iterator &si, const wstring::iterator &send, - TextFont *font, PandaNode *dest) { + TextFont *font, GeomNode *dest, const LMatrix4f &mat) { float xpos = 0.0f; while (si != send && (*si) != '\n') { wchar_t character = *si; @@ -914,14 +915,26 @@ assemble_row(wstring::iterator &si, const wstring::iterator &send, const RenderState *state = glyph->get_state(); if (char_geom != (Geom *)NULL) { - LMatrix4f mat = LMatrix4f::scale_mat(glyph_scale); - mat.set_row(3, LVector3f(xpos, 0.0f, 0.0f)); + LMatrix4f mat2 = LMatrix4f::scale_mat(glyph_scale); + mat2.set_row(3, LVector3f(xpos, 0.0f, 0.0f)); + LMatrix4f xform = mat2 * mat; - string ch(1, (char)character); - PT(GeomNode) geode = new GeomNode(ch); - geode->add_geom(char_geom, state); - dest->add_child(geode); - geode->set_transform(TransformState::make_mat(mat)); + // Transform the vertices of the geom appropriately. We + // assume the geom is non-indexed. + PTA_Vertexf coords; + PTA_ushort index; + char_geom->get_coords(coords, index); + PTA_Vertexf new_coords; + new_coords.reserve(coords.size()); + PTA_Vertexf::const_iterator vi; + for (vi = coords.begin(); vi != coords.end(); ++vi) { + new_coords.push_back((*vi) * xform); + } + nassertr(new_coords.size() == coords.size(), false); + char_geom->set_coords(new_coords); + + // Now add the geom to the destination node. + dest->add_geom(char_geom, state); } xpos += glyph->get_advance() * glyph_scale; @@ -943,27 +956,21 @@ assemble_row(wstring::iterator &si, const wstring::iterator &send, PT(PandaNode) TextNode:: assemble_text(wstring::iterator si, const wstring::iterator &send, TextFont *font, LVector2f &ul, LVector2f &lr, int &num_rows) { - float line_height = get_line_height(); + float line_height = font->get_line_height(); ul.set(0.0f, 0.8f * line_height); lr.set(0.0f, 0.0f); - // Make a group node to hold our formatted text geometry. - PT(PandaNode) root_node = new PandaNode("text"); + // Make a geom node to hold our formatted text geometry. + PT(GeomNode) root_node = new GeomNode("text"); float posy = 0.0f; - int row_index = 0; while (si != send) { - char numstr[20]; - sprintf(numstr, "row%d", row_index); - nassertr(strlen(numstr) < 20, root_node); - - PT(PandaNode) row = new PandaNode(numstr); - float row_width = assemble_row(si, send, font, row); - if (si != send) { - // Skip past the newline. - ++si; - } + // First, just measure the row, so we know how wide it is. + // (Centered or right-justified text will require us to know this + // up front.) + wstring::iterator tsi = si; + float row_width = measure_row(tsi, send, font); LMatrix4f mat = LMatrix4f::ident_mat(); if (_align == A_left) { @@ -991,8 +998,13 @@ assemble_text(wstring::iterator si, const wstring::iterator &send, mat = shear * mat; } - row->set_transform(TransformState::make_mat(mat)); - root_node->add_child(row); + // Now that we've computed the row's transform matrix, generate + // the actual geoms for the row. + assemble_row(si, send, font, root_node, mat); + if (si != send) { + // Skip past the newline. + ++si; + } posy -= line_height; num_rows++; @@ -1000,7 +1012,7 @@ assemble_text(wstring::iterator si, const wstring::iterator &send, lr[1] = posy + 0.8f * line_height; - return root_node; + return root_node.p(); } //////////////////////////////////////////////////////////////////// @@ -1046,7 +1058,7 @@ measure_row(wstring::iterator &si, const wstring::iterator &send, void TextNode:: measure_text(wstring::iterator si, const wstring::iterator &send, TextFont *font, LVector2f &ul, LVector2f &lr, int &num_rows) { - float line_height = get_line_height(); + float line_height = font->get_line_height(); ul.set(0.0f, 0.8f * line_height); lr.set(0.0f, 0.0f); diff --git a/panda/src/text/textNode.h b/panda/src/text/textNode.h index 44eb6ce358..5c9947188f 100644 --- a/panda/src/text/textNode.h +++ b/panda/src/text/textNode.h @@ -206,6 +206,7 @@ PUBLISHED: PT(PandaNode) generate(); INLINE void update(); + INLINE void force_update(); public: // Direct support for wide-character strings. @@ -249,8 +250,8 @@ private: void do_measure(); #ifndef CPPPARSER // interrogate has a bit of trouble with wstring. - float assemble_row(wstring::iterator &si, const wstring::iterator &send, - TextFont *font, PandaNode *dest); + float assemble_row(wstring::iterator &si, const wstring::iterator &send, + TextFont *font, GeomNode *dest, const LMatrix4f &mat); PT(PandaNode) assemble_text(wstring::iterator si, const wstring::iterator &send, TextFont *font, LVector2f &ul, LVector2f &lr, int &num_rows);