소스 검색

ensure invalid glyphs are rendered

David Rose 17 년 전
부모
커밋
aa81f3077e
4개의 변경된 파일72개의 추가작업 그리고 2개의 파일을 삭제
  1. 16 1
      panda/src/text/dynamicTextFont.cxx
  2. 1 1
      panda/src/text/staticTextFont.cxx
  3. 50 0
      panda/src/text/textFont.cxx
  4. 5 0
      panda/src/text/textFont.h

+ 16 - 1
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);

+ 1 - 1
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;
   }
 

+ 50 - 0
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 <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:

+ 5 - 0
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() {