Browse Source

refinements to DynamicText

David Rose 24 years ago
parent
commit
c037a890dd

+ 101 - 7
panda/src/text/dynamicTextFont.I

@@ -18,7 +18,72 @@
 
 
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
-//     Function: DynamicTextFont::set_margin
+//     Function: DynamicTextFont::set_point_size
+//       Access: Published
+//  Description: Sets the point size of the font.  This controls the
+//               apparent size of the font onscreen.  By convention, a
+//               10 point font is about 1 screen unit high.
+//
+//               This should only be called before any characters have
+//               been requested out of the font, or immediately after
+//               calling clear().
+////////////////////////////////////////////////////////////////////
+INLINE bool DynamicTextFont::
+set_point_size(float point_size) {
+  // If this assertion fails, you didn't call clear() first.  RTFM.
+  nassertr(get_num_pages() == 0, false);
+
+  _point_size = point_size;
+  return reset_scale();
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: DynamicTextFont::get_point_size
+//       Access: Published
+//  Description: Returns the point size of the font.
+////////////////////////////////////////////////////////////////////
+INLINE float DynamicTextFont::
+get_point_size() const {
+  return _point_size;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: DynamicTextFont::set_pixels_per_unit
+//       Access: Published
+//  Description: Set the resolution of the texture map, and hence the
+//               clarity of the resulting font.  This sets the number
+//               of pixels in the texture map that are used for each
+//               onscreen unit.
+//
+//               Setting this number larger results in an easier to
+//               read font, but at the cost of more texture memory.
+//
+//               This should only be called before any characters have
+//               been requested out of the font, or immediately after
+//               calling clear().
+////////////////////////////////////////////////////////////////////
+INLINE bool DynamicTextFont::
+set_pixels_per_unit(float pixels_per_unit) {
+  // If this assertion fails, you didn't call clear() first.  RTFM.
+  nassertr(get_num_pages() == 0, false);
+
+  _pixels_per_unit = pixels_per_unit;
+  return reset_scale();
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: DynamicTextFont::get_pixels_per_unit
+//       Access: Published
+//  Description: Returns the resolution of the texture map.  See
+//               set_pixels_per_unit().
+////////////////////////////////////////////////////////////////////
+INLINE float DynamicTextFont::
+get_pixels_per_unit() const {
+  return _pixels_per_unit;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: DynamicTextFont::set_texture_margin
 //       Access: Published
 //       Access: Published
 //  Description: Sets the number of pixels of padding that is added
 //  Description: Sets the number of pixels of padding that is added
 //               around the border of each glyph before adding it to
 //               around the border of each glyph before adding it to
@@ -26,19 +91,48 @@
 //               neighboring glyphs in the texture map.
 //               neighboring glyphs in the texture map.
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 INLINE void DynamicTextFont::
 INLINE void DynamicTextFont::
-set_margin(int margin) {
-  _margin = margin;
+set_texture_margin(int texture_margin) {
+  _texture_margin = texture_margin;
 }
 }
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
-//     Function: DynamicTextFont::get_margin
+//     Function: DynamicTextFont::get_texture_margin
 //       Access: Published
 //       Access: Published
 //  Description: Returns the number of pixels of padding that is added
 //  Description: Returns the number of pixels of padding that is added
-//               around the border of each glyph.  See set_margin().
+//               around the border of each glyph in the texture map.
+//               See set_texture_margin().
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 INLINE int DynamicTextFont::
 INLINE int DynamicTextFont::
-get_margin() const {
-  return _margin;
+get_texture_margin() const {
+  return _texture_margin;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: DynamicTextFont::set_poly_margin
+//       Access: Published
+//  Description: Sets the number of pixels of padding that is included
+//               around each glyph in the generated polygons.  This
+//               helps prevent the edges of the glyphs from being cut
+//               off at small minifications.  It is not related to the
+//               amount of extra pixels reserved in the texture map
+//               (but it should be no larger than this number, which
+//               is controlled by set_texture_margin()).
+////////////////////////////////////////////////////////////////////
+INLINE void DynamicTextFont::
+set_poly_margin(float poly_margin) {
+  _poly_margin = poly_margin;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: DynamicTextFont::get_poly_margin
+//       Access: Published
+//  Description: Returns the number of pixels of padding that is
+//               included around each glyph in the generated polygons.
+//               See set_poly_margin().
+////////////////////////////////////////////////////////////////////
+INLINE float DynamicTextFont::
+get_poly_margin() const {
+  return _poly_margin;
 }
 }
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////

+ 74 - 32
panda/src/text/dynamicTextFont.cxx

@@ -43,23 +43,16 @@ static const float points_per_inch = 72.0f;
 //  Description: The constructor expects the name of some font file
 //  Description: The constructor expects the name of some font file
 //               that FreeType can read, along with face_index,
 //               that FreeType can read, along with face_index,
 //               indicating which font within the file to load
 //               indicating which font within the file to load
-//               (usually 0), the point size of the font, and the
-//               resolution at which to generate the font.  
-//
-//               The choice of point size affects the apparent size of
-//               the generated characters (as well as the clarity),
-//               while the pixels_per_unit affects only the clarity.
+//               (usually 0).
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 DynamicTextFont::
 DynamicTextFont::
-DynamicTextFont(const Filename &font_filename, int face_index,
-                float point_size, float pixels_per_unit) {
-  _margin = 2;
+DynamicTextFont(const Filename &font_filename, int face_index) {
+  _texture_margin = 2;
+  _poly_margin = 1.0f;
   _page_x_size = 256;
   _page_x_size = 256;
   _page_y_size = 256;
   _page_y_size = 256;
-  _pixels_per_unit = pixels_per_unit;
-
-  float units_per_inch = (points_per_inch / points_per_unit);
-  int dpi = (int)(_pixels_per_unit * units_per_inch);
+  _point_size = 10.0f;
+  _pixels_per_unit = 40.0f;
 
 
   if (!_ft_initialized) {
   if (!_ft_initialized) {
     initialize_ft_library();
     initialize_ft_library();
@@ -90,23 +83,16 @@ DynamicTextFont(const Filename &font_filename, int face_index,
 
 
     } else {
     } else {
       string name = _face->family_name;
       string name = _face->family_name;
-      name += " ";
-      name += _face->style_name;
-
-      _is_valid = true;
+      if (_face->style_name != NULL) {
+        name += " ";
+        name += _face->style_name;
+      }
       set_name(name);
       set_name(name);
 
 
       text_cat.info()
       text_cat.info()
         << "Loaded font " << get_name() << "\n";
         << "Loaded font " << get_name() << "\n";
-
-      error = FT_Set_Char_Size(_face,
-                               (int)(point_size * 64), (int)(point_size * 64),
-                               dpi, dpi);
-      if (error) {
-        text_cat.warning()
-          << "Unable to set point size of " << get_name() 
-          << " to " << point_size << " at " << dpi << " dots per inch.\n";
-      }
+      _is_valid = true;
+      reset_scale();
     }
     }
   }
   }
 }
 }
@@ -142,6 +128,25 @@ get_page(int n) const {
   return _pages[n];
   return _pages[n];
 }
 }
 
 
+////////////////////////////////////////////////////////////////////
+//     Function: DynamicTextFont::clear
+//       Access: Published
+//  Description: Drops all the glyphs out of the cache and frees any
+//               association with any previously-generated pages.
+//
+//               Calling this frequently can result in wasted texture
+//               memory, as any previously rendered text will still
+//               keep a pointer to the old, previously-generated
+//               pages.  As long as the previously rendered text
+//               remains around, the old pages will also remain
+//               around.
+////////////////////////////////////////////////////////////////////
+void DynamicTextFont::
+clear() {
+  _pages.clear();
+  _cache.clear();
+}
+
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 //     Function: DynamicTextFont::write
 //     Function: DynamicTextFont::write
 //       Access: Published, Virtual
 //       Access: Published, Virtual
@@ -150,7 +155,9 @@ get_page(int n) const {
 void DynamicTextFont::
 void DynamicTextFont::
 write(ostream &out, int indent_level) const {
 write(ostream &out, int indent_level) const {
   indent(out, indent_level)
   indent(out, indent_level)
-    << "DynamicTextFont " << get_name() << ".\n";
+    << "DynamicTextFont " << get_name() << ", " 
+    << _cache.size() << " glyphs, "
+    << get_num_pages() << " pages.\n";
 }
 }
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
@@ -165,10 +172,45 @@ get_glyph(int character) {
   if (ci != _cache.end()) {
   if (ci != _cache.end()) {
     return (*ci).second;
     return (*ci).second;
   }
   }
+  if (!_is_valid) {
+    return (TextGlyph *)NULL;
+  }
+
   DynamicTextGlyph *glyph = make_glyph(character);
   DynamicTextGlyph *glyph = make_glyph(character);
   _cache.insert(Cache::value_type(character, glyph));
   _cache.insert(Cache::value_type(character, glyph));
   return glyph;
   return glyph;
 }
 }
+ 
+////////////////////////////////////////////////////////////////////
+//     Function: DynamicTextFont::reset_scale
+//       Access: Private
+//  Description: Resets the font to use the current _point_size and
+//               _pixels_per_unit.  Returns true if successful, false
+//               otherwise.
+////////////////////////////////////////////////////////////////////
+bool DynamicTextFont::
+reset_scale() {
+  float units_per_inch = (points_per_inch / points_per_unit);
+  int dpi = (int)(_pixels_per_unit * units_per_inch);
+  
+  int error = FT_Set_Char_Size(_face,
+                               (int)(_point_size * 64), (int)(_point_size * 64),
+                               dpi, dpi);
+  if (error) {
+    text_cat.warning()
+      << "Unable to set " << get_name() 
+      << " to " << _point_size << "pt at " << dpi << " dpi.\n";
+    _line_height = 1.0f;
+    return false;
+  }
+
+  // The face's height is only relevant for scalable fonts,
+  // according to FreeType.  How should we determine whether we
+  // have a scalable font or otherwise?
+  float pixel_size = _point_size * (_pixels_per_unit / points_per_unit);
+  _line_height = (float)_face->height * pixel_size / ((float)_face->units_per_EM * 64.0f);
+  return true;
+}
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 //     Function: DynamicTextFont::make_glyph
 //     Function: DynamicTextFont::make_glyph
@@ -217,7 +259,7 @@ make_glyph(int character) {
 
 
   float advance = slot->advance.x / 64.0;
   float advance = slot->advance.x / 64.0;
   glyph->make_geom(slot->bitmap_top, slot->bitmap_left, advance,
   glyph->make_geom(slot->bitmap_top, slot->bitmap_left, advance,
-                   _pixels_per_unit);
+                   _poly_margin, _pixels_per_unit);
   return glyph;
   return glyph;
 }
 }
 
 
@@ -233,14 +275,14 @@ make_glyph(int character) {
 DynamicTextGlyph *DynamicTextFont::
 DynamicTextGlyph *DynamicTextFont::
 slot_glyph(int x_size, int y_size) {
 slot_glyph(int x_size, int y_size) {
   // Increase the indicated size by the current margin.
   // Increase the indicated size by the current margin.
-  x_size += _margin * 2;
-  y_size += _margin * 2;
+  x_size += _texture_margin * 2;
+  y_size += _texture_margin * 2;
 
 
   Pages::iterator pi;
   Pages::iterator pi;
   for (pi = _pages.begin(); pi != _pages.end(); ++pi) {
   for (pi = _pages.begin(); pi != _pages.end(); ++pi) {
     DynamicTextPage *page = (*pi);
     DynamicTextPage *page = (*pi);
 
 
-    DynamicTextGlyph *glyph = page->slot_glyph(x_size, y_size, _margin);
+    DynamicTextGlyph *glyph = page->slot_glyph(x_size, y_size, _texture_margin);
     if (glyph != (DynamicTextGlyph *)NULL) {
     if (glyph != (DynamicTextGlyph *)NULL) {
       return glyph;
       return glyph;
     }
     }
@@ -257,7 +299,7 @@ slot_glyph(int x_size, int y_size) {
   // We need to make a new page.
   // We need to make a new page.
   PT(DynamicTextPage) page = new DynamicTextPage(this);
   PT(DynamicTextPage) page = new DynamicTextPage(this);
   _pages.push_back(page);
   _pages.push_back(page);
-  return page->slot_glyph(x_size, y_size, _margin);
+  return page->slot_glyph(x_size, y_size, _texture_margin);
 }
 }
 
 
 
 

+ 18 - 6
panda/src/text/dynamicTextFont.h

@@ -44,11 +44,18 @@
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 class EXPCL_PANDA DynamicTextFont : public TextFont {
 class EXPCL_PANDA DynamicTextFont : public TextFont {
 PUBLISHED:
 PUBLISHED:
-  DynamicTextFont(const Filename &font_filename, int face_index,
-                  float point_size, float pixels_per_unit);
+  DynamicTextFont(const Filename &font_filename, int face_index = 0);
 
 
-  INLINE void set_margin(int margin);
-  INLINE int get_margin() const;
+  INLINE bool set_point_size(float point_size);
+  INLINE float get_point_size() const;
+
+  INLINE bool set_pixels_per_unit(float pixels_per_unit);
+  INLINE float get_pixels_per_unit() const;
+
+  INLINE void set_texture_margin(int texture_margin);
+  INLINE int get_texture_margin() const;
+  INLINE void set_poly_margin(float poly_margin);
+  INLINE float get_poly_margin() const;
 
 
   INLINE void set_page_size(int x_size, int y_size);
   INLINE void set_page_size(int x_size, int y_size);
   INLINE int get_page_x_size() const;
   INLINE int get_page_x_size() const;
@@ -57,20 +64,25 @@ PUBLISHED:
   int get_num_pages() const;
   int get_num_pages() const;
   DynamicTextPage *get_page(int n) const;
   DynamicTextPage *get_page(int n) const;
 
 
+  void clear();
+
   virtual void write(ostream &out, int indent_level) const;
   virtual void write(ostream &out, int indent_level) const;
 
 
 public:
 public:
   virtual const TextGlyph *get_glyph(int character);
   virtual const TextGlyph *get_glyph(int character);
 
 
 private:
 private:
+  bool reset_scale();
   DynamicTextGlyph *make_glyph(int character);
   DynamicTextGlyph *make_glyph(int character);
   DynamicTextGlyph *slot_glyph(int x_size, int y_size);
   DynamicTextGlyph *slot_glyph(int x_size, int y_size);
 
 
   static void initialize_ft_library();
   static void initialize_ft_library();
 
 
-  int _margin;
-  int _page_x_size, _page_y_size;
+  float _point_size;
   float _pixels_per_unit;
   float _pixels_per_unit;
+  int _texture_margin;
+  float _poly_margin;
+  int _page_x_size, _page_y_size;
 
 
   typedef pvector< PT(DynamicTextPage) > Pages;
   typedef pvector< PT(DynamicTextPage) > Pages;
   Pages _pages;
   Pages _pages;

+ 9 - 9
panda/src/text/dynamicTextGlyph.cxx

@@ -63,18 +63,18 @@ get_row(int y) {
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 void DynamicTextGlyph::
 void DynamicTextGlyph::
 make_geom(int bitmap_top, int bitmap_left, 
 make_geom(int bitmap_top, int bitmap_left, 
-          float advance, float pixels_per_unit) {
+          float advance, float poly_margin, float pixels_per_unit) {
   // Determine the corners of the rectangle in geometric units.
   // Determine the corners of the rectangle in geometric units.
-  float top = (bitmap_top + _margin) / pixels_per_unit;
-  float left = (bitmap_left - _margin) / pixels_per_unit;
-  float bottom = (bitmap_top - _y_size - _margin) / pixels_per_unit;
-  float right = (bitmap_left + _x_size + _margin) / pixels_per_unit;
+  float top = (bitmap_top + poly_margin) / pixels_per_unit;
+  float left = (bitmap_left - poly_margin) / pixels_per_unit;
+  float bottom = (bitmap_top - _y_size - poly_margin) / pixels_per_unit;
+  float right = (bitmap_left + _x_size + poly_margin) / pixels_per_unit;
 
 
   // And the corresponding corners in UV units.
   // And the corresponding corners in UV units.
-  float uv_top = 1.0f - (float)_y / _page->get_y_size();
-  float uv_left = (float)_x / _page->get_x_size();
-  float uv_bottom = 1.0f - (float)(_y + _y_size) / _page->get_y_size();
-  float uv_right = (float)(_x + _x_size) / _page->get_x_size();
+  float uv_top = 1.0f - (float)(_y - poly_margin) / _page->get_y_size();
+  float uv_left = (float)(_x - poly_margin) / _page->get_x_size();
+  float uv_bottom = 1.0f - (float)(_y + _y_size + poly_margin) / _page->get_y_size();
+  float uv_right = (float)(_x + _x_size + poly_margin) / _page->get_x_size();
 
 
   // Create a corresponding tristrip.
   // Create a corresponding tristrip.
   _geom = new GeomTristrip;
   _geom = new GeomTristrip;

+ 2 - 1
panda/src/text/dynamicTextGlyph.h

@@ -41,7 +41,8 @@ public:
 
 
   INLINE bool intersects(int x, int y, int x_size, int y_size) const;
   INLINE bool intersects(int x, int y, int x_size, int y_size) const;
   unsigned char *get_row(int y);
   unsigned char *get_row(int y);
-  void make_geom(int top, int left, float advance, float pixels_per_unit);
+  void make_geom(int top, int left, float advance, float poly_margin,
+                 float pixels_per_unit);
 
 
   DynamicTextPage *_page;
   DynamicTextPage *_page;