faster text generation

This commit is contained in:
David Rose 2003-01-31 23:55:33 +00:00
parent c37acce234
commit 7421fe3e05
5 changed files with 75 additions and 34 deletions

View File

@ -53,7 +53,7 @@ get_geom() const {
//////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////
// Function: DynamicTextGlyph::get_row // Function: DynamicTextGlyph::get_row
// Access: Publiic // Access: Public
// Description: Returns a pointer to the first byte in the pixel // Description: Returns a pointer to the first byte in the pixel
// buffer associated with the leftmost pixel in the // buffer associated with the leftmost pixel in the
// indicated row, where 0 is the topmost row and _y_size // indicated row, where 0 is the topmost row and _y_size
@ -79,7 +79,7 @@ get_row(int y) {
//////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////
// Function: DynamicTextGlyph::erase // Function: DynamicTextGlyph::erase
// Access: Publiic // Access: Public
// Description: Erases the glyph from the texture map. // Description: Erases the glyph from the texture map.
//////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////
void DynamicTextGlyph:: void DynamicTextGlyph::
@ -99,7 +99,7 @@ erase() {
//////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////
// Function: DynamicTextGlyph::make_geom // Function: DynamicTextGlyph::make_geom
// Access: Publiic // Access: Public
// Description: Creates the actual geometry for the glyph. The // Description: Creates the actual geometry for the glyph. The
// parameters bitmap_top and bitmap_left are from // parameters bitmap_top and bitmap_left are from
// FreeType, and indicate the position of the top left // FreeType, and indicate the position of the top left

View File

@ -34,5 +34,13 @@ TextGlyph::
//////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////
PT(Geom) TextGlyph:: PT(Geom) TextGlyph::
get_geom() const { 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();
} }

View File

@ -194,7 +194,12 @@ get_expand_amp() const {
//////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////
INLINE float TextNode:: INLINE float TextNode::
get_line_height() const { 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(); 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 // Function: TextNode::set_wtext
// Access: Public // Access: Public

View File

@ -294,7 +294,8 @@ generate() {
assemble_text(wtext.begin(), wtext.end(), font, assemble_text(wtext.begin(), wtext.end(), font,
ul, lr, num_rows); 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"); PT(PandaNode) text = new PandaNode("text");
root->add_child(text, _draw_order + 2); root->add_child(text, _draw_order + 2);
text->add_child(text_root); text->add_child(text_root);
@ -883,7 +884,7 @@ do_measure() {
//////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////
float TextNode:: float TextNode::
assemble_row(wstring::iterator &si, const wstring::iterator &send, assemble_row(wstring::iterator &si, const wstring::iterator &send,
TextFont *font, PandaNode *dest) { TextFont *font, GeomNode *dest, const LMatrix4f &mat) {
float xpos = 0.0f; float xpos = 0.0f;
while (si != send && (*si) != '\n') { while (si != send && (*si) != '\n') {
wchar_t character = *si; wchar_t character = *si;
@ -914,14 +915,26 @@ assemble_row(wstring::iterator &si, const wstring::iterator &send,
const RenderState *state = glyph->get_state(); const RenderState *state = glyph->get_state();
if (char_geom != (Geom *)NULL) { if (char_geom != (Geom *)NULL) {
LMatrix4f mat = LMatrix4f::scale_mat(glyph_scale); LMatrix4f mat2 = LMatrix4f::scale_mat(glyph_scale);
mat.set_row(3, LVector3f(xpos, 0.0f, 0.0f)); mat2.set_row(3, LVector3f(xpos, 0.0f, 0.0f));
LMatrix4f xform = mat2 * mat;
string ch(1, (char)character); // Transform the vertices of the geom appropriately. We
PT(GeomNode) geode = new GeomNode(ch); // assume the geom is non-indexed.
geode->add_geom(char_geom, state); PTA_Vertexf coords;
dest->add_child(geode); PTA_ushort index;
geode->set_transform(TransformState::make_mat(mat)); 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; xpos += glyph->get_advance() * glyph_scale;
@ -943,27 +956,21 @@ assemble_row(wstring::iterator &si, const wstring::iterator &send,
PT(PandaNode) TextNode:: PT(PandaNode) TextNode::
assemble_text(wstring::iterator si, const wstring::iterator &send, assemble_text(wstring::iterator si, const wstring::iterator &send,
TextFont *font, LVector2f &ul, LVector2f &lr, int &num_rows) { 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); ul.set(0.0f, 0.8f * line_height);
lr.set(0.0f, 0.0f); lr.set(0.0f, 0.0f);
// Make a group node to hold our formatted text geometry. // Make a geom node to hold our formatted text geometry.
PT(PandaNode) root_node = new PandaNode("text"); PT(GeomNode) root_node = new GeomNode("text");
float posy = 0.0f; float posy = 0.0f;
int row_index = 0;
while (si != send) { while (si != send) {
char numstr[20]; // First, just measure the row, so we know how wide it is.
sprintf(numstr, "row%d", row_index); // (Centered or right-justified text will require us to know this
nassertr(strlen(numstr) < 20, root_node); // up front.)
wstring::iterator tsi = si;
PT(PandaNode) row = new PandaNode(numstr); float row_width = measure_row(tsi, send, font);
float row_width = assemble_row(si, send, font, row);
if (si != send) {
// Skip past the newline.
++si;
}
LMatrix4f mat = LMatrix4f::ident_mat(); LMatrix4f mat = LMatrix4f::ident_mat();
if (_align == A_left) { if (_align == A_left) {
@ -991,8 +998,13 @@ assemble_text(wstring::iterator si, const wstring::iterator &send,
mat = shear * mat; mat = shear * mat;
} }
row->set_transform(TransformState::make_mat(mat)); // Now that we've computed the row's transform matrix, generate
root_node->add_child(row); // 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; posy -= line_height;
num_rows++; num_rows++;
@ -1000,7 +1012,7 @@ assemble_text(wstring::iterator si, const wstring::iterator &send,
lr[1] = posy + 0.8f * line_height; 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:: void TextNode::
measure_text(wstring::iterator si, const wstring::iterator &send, measure_text(wstring::iterator si, const wstring::iterator &send,
TextFont *font, LVector2f &ul, LVector2f &lr, int &num_rows) { 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); ul.set(0.0f, 0.8f * line_height);
lr.set(0.0f, 0.0f); lr.set(0.0f, 0.0f);

View File

@ -206,6 +206,7 @@ PUBLISHED:
PT(PandaNode) generate(); PT(PandaNode) generate();
INLINE void update(); INLINE void update();
INLINE void force_update();
public: public:
// Direct support for wide-character strings. // Direct support for wide-character strings.
@ -249,8 +250,8 @@ private:
void do_measure(); void do_measure();
#ifndef CPPPARSER // interrogate has a bit of trouble with wstring. #ifndef CPPPARSER // interrogate has a bit of trouble with wstring.
float assemble_row(wstring::iterator &si, const wstring::iterator &send, float assemble_row(wstring::iterator &si, const wstring::iterator &send,
TextFont *font, PandaNode *dest); TextFont *font, GeomNode *dest, const LMatrix4f &mat);
PT(PandaNode) assemble_text(wstring::iterator si, const wstring::iterator &send, PT(PandaNode) assemble_text(wstring::iterator si, const wstring::iterator &send,
TextFont *font, TextFont *font,
LVector2f &ul, LVector2f &lr, int &num_rows); LVector2f &ul, LVector2f &lr, int &num_rows);