From 93384e8988d5a6376e43d3bf00a709cf2f705cbe Mon Sep 17 00:00:00 2001 From: David Rose Date: Sat, 13 Sep 2003 01:05:12 +0000 Subject: [PATCH] handle fixed-pixel-size fonts better --- panda/src/pnmtext/freetypeFont.I | 22 ++++++++- panda/src/pnmtext/freetypeFont.cxx | 42 ++++++++++++----- panda/src/pnmtext/freetypeFont.h | 5 ++ panda/src/text/dynamicTextFont.I | 58 ++++++++++++++++++++++-- panda/src/text/dynamicTextFont.h | 5 ++ pandatool/src/egg-mkfont/eggMakeFont.cxx | 29 +++++++++--- 6 files changed, 137 insertions(+), 24 deletions(-) diff --git a/panda/src/pnmtext/freetypeFont.I b/panda/src/pnmtext/freetypeFont.I index 5b87cccae4..7bfafc9872 100644 --- a/panda/src/pnmtext/freetypeFont.I +++ b/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 diff --git a/panda/src/pnmtext/freetypeFont.cxx b/panda/src/pnmtext/freetypeFont.cxx index fd96700ea0..d99b0459e6 100644 --- a/panda/src/pnmtext/freetypeFont.cxx +++ b/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; + } } } } diff --git a/panda/src/pnmtext/freetypeFont.h b/panda/src/pnmtext/freetypeFont.h index 4700a17150..9c6e691490 100644 --- a/panda/src/pnmtext/freetypeFont.h +++ b/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; diff --git a/panda/src/text/dynamicTextFont.I b/panda/src/text/dynamicTextFont.I index 50c101f38e..bbb5f8bd75 100644 --- a/panda/src/text/dynamicTextFont.I +++ b/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:: diff --git a/panda/src/text/dynamicTextFont.h b/panda/src/text/dynamicTextFont.h index d3cd25e256..5cfb36235a 100644 --- a/panda/src/text/dynamicTextFont.h +++ b/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; diff --git a/pandatool/src/egg-mkfont/eggMakeFont.cxx b/pandatool/src/egg-mkfont/eggMakeFont.cxx index ca35f63a99..36117ebb49 100644 --- a/pandatool/src/egg-mkfont/eggMakeFont.cxx +++ b/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.