From aa81f3077e288dd9da90f8bab5e0c9fe19d9afe1 Mon Sep 17 00:00:00 2001 From: David Rose Date: Sat, 22 Nov 2008 02:33:17 +0000 Subject: [PATCH] ensure invalid glyphs are rendered --- panda/src/text/dynamicTextFont.cxx | 17 +++++++++- panda/src/text/staticTextFont.cxx | 2 +- panda/src/text/textFont.cxx | 50 ++++++++++++++++++++++++++++++ panda/src/text/textFont.h | 5 +++ 4 files changed, 72 insertions(+), 2 deletions(-) diff --git a/panda/src/text/dynamicTextFont.cxx b/panda/src/text/dynamicTextFont.cxx index 484423fb01..81ca7dcc4d 100644 --- a/panda/src/text/dynamicTextFont.cxx +++ b/panda/src/text/dynamicTextFont.cxx @@ -246,7 +246,12 @@ get_glyph(int character, const TextGlyph *&glyph) { glyph = dynamic_glyph; } - return (glyph_index != 0 && glyph != (DynamicTextGlyph *)NULL); + if (glyph == (DynamicTextGlyph *)NULL) { + glyph = get_invalid_glyph(); + glyph_index = 0; + } + + return (glyph_index != 0); } @@ -315,6 +320,15 @@ make_glyph(int character, int glyph_index) { FT_GlyphSlot slot = _face->glyph; FT_Bitmap &bitmap = slot->bitmap; + if ((bitmap.width == 0 || bitmap.rows == 0) && (glyph_index == 0)) { + // Here's a special case: a glyph_index of 0 means an invalid + // glyph. Some fonts define a symbol to represent an invalid + // glyph, but if that symbol is the empty bitmap, we return NULL, + // and use Panda's invalid glyph in its place. We do this to + // guarantee that every invalid glyph is visible as *something*. + return NULL; + } + float advance = slot->advance.x / 64.0; if (_render_mode != RM_texture && @@ -406,6 +420,7 @@ make_glyph(int character, int glyph_index) { if (bitmap.width == 0 || bitmap.rows == 0) { // If we got an empty bitmap, it's a special case. + PT(DynamicTextGlyph) glyph = new DynamicTextGlyph(character, advance / _font_pixels_per_unit); _empty_glyphs.push_back(glyph); diff --git a/panda/src/text/staticTextFont.cxx b/panda/src/text/staticTextFont.cxx index de33d6a405..2c8c47063e 100644 --- a/panda/src/text/staticTextFont.cxx +++ b/panda/src/text/staticTextFont.cxx @@ -180,7 +180,7 @@ get_glyph(int character, const TextGlyph *&glyph) { Glyphs::const_iterator gi = _glyphs.find(character); if (gi == _glyphs.end()) { // No definition for this character. - glyph = (TextGlyph *)NULL; + glyph = get_invalid_glyph(); return false; } diff --git a/panda/src/text/textFont.cxx b/panda/src/text/textFont.cxx index 1b6bbbf1aa..091ae42448 100644 --- a/panda/src/text/textFont.cxx +++ b/panda/src/text/textFont.cxx @@ -15,6 +15,11 @@ #include "textFont.h" #include "config_text.h" #include "string_utils.h" +#include "geomVertexData.h" +#include "geomVertexFormat.h" +#include "geomVertexWriter.h" +#include "geomLinestrips.h" +#include "geom.h" #include TypeHandle TextFont::_type_handle; @@ -51,6 +56,20 @@ write(ostream &out, int indent_level) const { << "TextFont " << get_name() << "\n"; } +//////////////////////////////////////////////////////////////////// +// Function: TextFont::get_invalid_glyph +// Access: Public +// Description: Returns a special glyph that should be used as a +// placeholder for any character not in the font. +//////////////////////////////////////////////////////////////////// +TextGlyph *TextFont:: +get_invalid_glyph() { + if (_invalid_glyph == (TextGlyph *)NULL) { + make_invalid_glyph(); + } + return _invalid_glyph; +} + //////////////////////////////////////////////////////////////////// // Function: TextFont::string_render_mode // Access: Public @@ -95,6 +114,37 @@ string_winding_order(const string &string) { } } +//////////////////////////////////////////////////////////////////// +// Function: TextFont::make_invalid_glyph +// Access: Private +// Description: Constructs the special glyph used to represent a +// character not in the font. +//////////////////////////////////////////////////////////////////// +void TextFont:: +make_invalid_glyph() { + CPT(GeomVertexFormat) vformat = GeomVertexFormat::get_v3(); + PT(GeomVertexData) vdata = + new GeomVertexData("invalid_glyph", vformat, GeomEnums::UH_static); + + GeomVertexWriter vertex(vdata, InternalName::get_vertex()); + vertex.add_data3f(_line_height * 0.2f, 0.0f, _line_height * 0.1f); + vertex.add_data3f(_line_height * 0.5f, 0.0f, _line_height * 0.1f); + vertex.add_data3f(_line_height * 0.5f, 0.0f, _line_height * 0.7f); + vertex.add_data3f(_line_height * 0.2f, 0.0f, _line_height * 0.7f); + + PT(GeomPrimitive) prim = new GeomLinestrips(GeomEnums::UH_static); + prim->add_consecutive_vertices(0, 4); + prim->add_vertex(0); + prim->close_primitive(); + + PT(Geom) geom = new Geom(vdata); + geom->add_primitive(prim); + + _invalid_glyph = new TextGlyph(0, geom, RenderState::make_empty(), + _line_height * 0.7f); + cerr << "made invalid glyph: " << _invalid_glyph << "\n"; +} + //////////////////////////////////////////////////////////////////// // Function: TextFont::RenderMode output operator // Description: diff --git a/panda/src/text/textFont.h b/panda/src/text/textFont.h index dee9099e50..de2b345048 100644 --- a/panda/src/text/textFont.h +++ b/panda/src/text/textFont.h @@ -81,14 +81,19 @@ PUBLISHED: public: virtual bool get_glyph(int character, const TextGlyph *&glyph)=0; + TextGlyph *get_invalid_glyph(); static RenderMode string_render_mode(const string &string); static WindingOrder string_winding_order(const string &string); +private: + void make_invalid_glyph(); + protected: bool _is_valid; float _line_height; float _space_advance; + PT(TextGlyph) _invalid_glyph; public: static TypeHandle get_class_type() {