Bläddra i källkod

handle fixed-pixel-size fonts better

David Rose 22 år sedan
förälder
incheckning
93384e8988

+ 20 - 2
panda/src/pnmtext/freetypeFont.I

@@ -71,7 +71,7 @@ get_point_size() const {
 ////////////////////////////////////////////////////////////////////
 INLINE bool FreetypeFont::
 set_pixels_per_unit(float pixels_per_unit) {
-  _tex_pixels_per_unit = pixels_per_unit;
+  _requested_pixels_per_unit = pixels_per_unit;
   return reset_scale();
 }
 
@@ -128,7 +128,7 @@ get_pixel_size() const {
 ////////////////////////////////////////////////////////////////////
 INLINE bool FreetypeFont::
 set_scale_factor(float scale_factor) {
-  _scale_factor = scale_factor;
+  _requested_scale_factor = scale_factor;
   return reset_scale();
 }
 
@@ -174,6 +174,24 @@ get_native_antialias() const {
   return _native_antialias;
 }
 
+////////////////////////////////////////////////////////////////////
+//     Function: FreetypeFont::get_font_pixel_size
+//       Access: Public
+//  Description: This is used to report whether the requested pixel
+//               size is being only approximated by a fixed-pixel-size
+//               font.  This returns 0 in the normal case, in which a
+//               scalable font is used, or the fixed-pixel-size font
+//               has exactly the requested pixel size.
+//
+//               If this returns non-zero, it is the pixel size of the
+//               font that we are using to approximate our desired
+//               size.
+////////////////////////////////////////////////////////////////////
+INLINE int FreetypeFont::
+get_font_pixel_size() const {
+  return _font_pixel_size;
+}
+
 ////////////////////////////////////////////////////////////////////
 //     Function: FreetypeFont::get_line_height
 //       Access: Public

+ 30 - 12
panda/src/pnmtext/freetypeFont.cxx

@@ -47,10 +47,13 @@ FreetypeFont() {
   _font_loaded = false;
 
   _point_size = text_point_size;
+  _requested_pixels_per_unit = text_pixels_per_unit;
   _tex_pixels_per_unit = text_pixels_per_unit;
+  _requested_scale_factor = text_scale_factor;
   _scale_factor = text_scale_factor;
   _native_antialias = text_native_antialias;
 
+  _font_pixel_size = 0;
   _line_height = 1.0f;
   _space_advance = 0.25f;
 
@@ -317,42 +320,57 @@ reset_scale() {
   // The font may be rendered larger (by a factor of _scale_factor),
   // and then reduced into the texture.  Hence the difference between
   // _font_pixels_per_unit and _tex_pixels_per_unit.
+  _tex_pixels_per_unit = _requested_pixels_per_unit;
+  _scale_factor = _requested_scale_factor;
   _font_pixels_per_unit = _tex_pixels_per_unit * _scale_factor;
 
   float units_per_inch = (_points_per_inch / _points_per_unit);
   int dpi = (int)(_font_pixels_per_unit * units_per_inch);
   
+  _font_pixel_size = 0;
   int error = FT_Set_Char_Size(_face,
                                (int)(_point_size * 64), (int)(_point_size * 64),
                                dpi, dpi);
   if (error) {
     // If we were unable to set a particular char size, perhaps we
-    // have a non-scalable font.  Try to figure out the closest
-    // available size.
+    // have a non-scalable font.  Try to figure out the next larger
+    // available size, or the largest size available if nothing is
+    // larger.
     int desired_height = (int)(_font_pixels_per_unit * _point_size / _points_per_unit + 0.5f);
     int best_size = -1;
+    int largest_size = -1;
     if (_face->num_fixed_sizes > 0) {
-      best_size = 0;
-      int best_diff = abs(desired_height - _face->available_sizes[0].height);
-      for (int i = 1; i < _face->num_fixed_sizes; i++) {
-        int diff = abs(desired_height - _face->available_sizes[i].height);
-        if (diff < best_diff) {
+      largest_size = 0;
+      int best_diff = 0;
+      for (int i = 0; i < _face->num_fixed_sizes; i++) {
+        int diff = _face->available_sizes[i].height - desired_height;
+        if (diff > 0 && (best_size == -1 || diff < best_diff)) {
           best_size = i;
           best_diff = diff;
         }
+        if (_face->available_sizes[i].height > _face->available_sizes[largest_size].height) {
+          largest_size = i;
+        }
       }
     }
+    if (best_size < 0) {
+      best_size = largest_size;
+    }
+
     if (best_size >= 0) {
       int pixel_height = _face->available_sizes[best_size].height;
       int pixel_width = _face->available_sizes[best_size].width;
       error = FT_Set_Pixel_Sizes(_face, pixel_width, pixel_height);
       if (!error) {
-        pnmtext_cat.info()
-          << "Using " << pixel_height << "-pixel font for "
-          << get_name() << "\n";
-
         _font_pixels_per_unit = pixel_height * _points_per_unit / _point_size;
-        _tex_pixels_per_unit = _font_pixels_per_unit;
+        _scale_factor = _font_pixels_per_unit / _tex_pixels_per_unit;
+        _font_pixel_size = pixel_height;
+
+        if (_scale_factor < 1.0) {
+          // No point in enlarging a fixed-point font.
+          _scale_factor = 1.0;
+          _tex_pixels_per_unit = _font_pixels_per_unit;
+        }
       }
     }
   }

+ 5 - 0
panda/src/pnmtext/freetypeFont.h

@@ -67,6 +67,8 @@ public:
   INLINE void set_native_antialias(bool native_antialias);
   INLINE bool get_native_antialias() const;
 
+  INLINE int get_font_pixel_size() const;
+
   INLINE float get_line_height() const;
   INLINE float get_space_advance() const;
 
@@ -84,11 +86,14 @@ private:
 
 protected:
   float _point_size;
+  float _requested_pixels_per_unit;
   float _tex_pixels_per_unit;
+  float _requested_scale_factor;
   float _scale_factor;
   bool _native_antialias;
   float _font_pixels_per_unit;
 
+  int _font_pixel_size;
   float _line_height;
   float _space_advance;
 

+ 55 - 3
panda/src/text/dynamicTextFont.I

@@ -19,7 +19,7 @@
 
 ////////////////////////////////////////////////////////////////////
 //     Function: DynamicTextFont::get_name
-//       Access: Public
+//       Access: Published
 //  Description: Disambiguates the get_name() method between that
 //               inherited from TextFont and that inherited from
 //               FreetypeFont.
@@ -127,9 +127,61 @@ get_scale_factor() const {
   return FreetypeFont::get_scale_factor();
 }
 
+////////////////////////////////////////////////////////////////////
+//     Function: DynamicTextFont::set_native_antialias
+//       Access: Published
+//  Description: Sets whether the Freetype library's built-in
+//               antialias mode is enabled.  There are two unrelated
+//               ways to achieve antialiasing: with Freetype's native
+//               antialias mode, and with the use of a scale_factor
+//               greater than one.  By default, both modes are
+//               enabled.
+//
+//               At low resolutions, some fonts may do better with one
+//               mode or the other.  In general, Freetype's native
+//               antialiasing will produce less blurry results, but
+//               may introduce more artifacts.
+////////////////////////////////////////////////////////////////////
+INLINE void DynamicTextFont::
+set_native_antialias(bool native_antialias) {
+  // If this assertion fails, you didn't call clear() first.  RTFM.
+  nassertv(get_num_pages() == 0);
+
+  FreetypeFont::set_native_antialias(native_antialias);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: DynamicTextFont::get_native_antialias
+//       Access: Published
+//  Description: Returns whether Freetype's built-in antialias mode is
+//               enabled.  See set_native_antialias().
+////////////////////////////////////////////////////////////////////
+INLINE bool DynamicTextFont::
+get_native_antialias() const {
+  return FreetypeFont::get_native_antialias();
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: DynamicTextFont::get_font_pixel_size
+//       Access: Published
+//  Description: This is used to report whether the requested pixel
+//               size is being only approximated by a fixed-pixel-size
+//               font.  This returns 0 in the normal case, in which a
+//               scalable font is used, or the fixed-pixel-size font
+//               has exactly the requested pixel size.
+//
+//               If this returns non-zero, it is the pixel size of the
+//               font that we are using to approximate our desired
+//               size.
+////////////////////////////////////////////////////////////////////
+INLINE int DynamicTextFont::
+get_font_pixel_size() const {
+  return FreetypeFont::get_font_pixel_size();
+}
+
 ////////////////////////////////////////////////////////////////////
 //     Function: DynamicTextFont::get_line_height
-//       Access: Public
+//       Access: Published
 //  Description: Returns the number of units high each line of text
 //               is.
 ////////////////////////////////////////////////////////////////////
@@ -140,7 +192,7 @@ get_line_height() const {
 
 ////////////////////////////////////////////////////////////////////
 //     Function: DynamicTextFont::get_space_advance
-//       Access: Public
+//       Access: Published
 //  Description: Returns the number of units wide a space is.
 ////////////////////////////////////////////////////////////////////
 INLINE float DynamicTextFont::

+ 5 - 0
panda/src/text/dynamicTextFont.h

@@ -60,6 +60,11 @@ PUBLISHED:
   INLINE bool set_scale_factor(float scale_factor);
   INLINE float get_scale_factor() const;
 
+  INLINE void set_native_antialias(bool native_antialias);
+  INLINE bool get_native_antialias() const;
+
+  INLINE int get_font_pixel_size() const;
+
   INLINE float get_line_height() const;
   INLINE float get_space_advance() const;
 

+ 22 - 7
pandatool/src/egg-mkfont/eggMakeFont.cxx

@@ -248,8 +248,27 @@ run() {
     }
   }
 
+  _text_maker->set_point_size(_point_size);
+  _text_maker->set_native_antialias(!_no_native_aa);
+  _text_maker->set_interior_flag(_got_interior);
+  _text_maker->set_pixels_per_unit(_pixels_per_unit);
+  _text_maker->set_scale_factor(_scale_factor);
+
+  // The text_maker may have had to adjust the pixels per unit and the
+  // scale factor according to what the font supports.
+  _pixels_per_unit = _text_maker->get_pixels_per_unit();
+  _scale_factor = _text_maker->get_scale_factor();
+
+  if (_text_maker->get_font_pixel_size() != 0) {
+    nout << "Using " << _text_maker->get_font_pixel_size() << "-pixel font.\n";
+  }
+
+  // Now we may want to tweak the scale factor so that fonts will
+  // actually be generated big.  We have to do this after we have
+  // already send the current _scale_factor through the _text_maker
+  // for validation.
   _palettize_scale_factor = _scale_factor;
-  if (_no_reduce || !_no_palettize) {
+  if (_scale_factor != 1.0 && (_no_reduce || !_no_palettize)) {
     // If _no_reduce is true (-nr was specified), we want to keep the
     // glyph textures full-sized, because the user asked for that.
 
@@ -261,6 +280,8 @@ run() {
     _poly_margin *= _scale_factor;
     _pixels_per_unit *= _scale_factor;
     _scale_factor = 1.0;
+    _text_maker->set_pixels_per_unit(_pixels_per_unit);
+    _text_maker->set_scale_factor(1.0);
   }
 
   if (_no_reduce) {
@@ -272,12 +293,6 @@ run() {
     _palettize_scale_factor = 1.0;
   }
 
-  _text_maker->set_point_size(_point_size);
-  _text_maker->set_native_antialias(!_no_native_aa);
-  _text_maker->set_interior_flag(_got_interior);
-  _text_maker->set_pixels_per_unit(_pixels_per_unit);
-  _text_maker->set_scale_factor(_scale_factor);
-  
   if (_range.is_empty()) {
     // If there's no specified range, the default is the entire ASCII
     // set.