ensure invalid glyphs are rendered

This commit is contained in:
David Rose 2008-11-22 02:33:17 +00:00
parent 2db915af4d
commit aa81f3077e
4 changed files with 72 additions and 2 deletions

View File

@ -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);

View File

@ -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;
}

View File

@ -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 <ctype.h>
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:

View File

@ -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() {