add pnmtext library
This commit is contained in:
parent
276ab8bfb9
commit
6409ff6b7f
|
|
@ -17,7 +17,7 @@
|
|||
gsgmisc light linmath mathutil net \
|
||||
parametrics pnm \
|
||||
pnmimagetypes pnmimage sgattrib sgmanip sgraph sgraphutil \
|
||||
switchnode text tform tiff lerp loader putil \
|
||||
switchnode pnmtext text tform tiff lerp loader putil \
|
||||
audio pgui pandabase
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,188 @@
|
|||
// Filename: freetypeFont.I
|
||||
// Created by: drose (07Sep03)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// PANDA 3D SOFTWARE
|
||||
// Copyright (c) 2001, Disney Enterprises, Inc. All rights reserved
|
||||
//
|
||||
// All use of this software is subject to the terms of the Panda 3d
|
||||
// Software license. You should have received a copy of this license
|
||||
// along with this source code; you will also find a current copy of
|
||||
// the license at http://www.panda3d.org/license.txt .
|
||||
//
|
||||
// To contact the maintainers of this program write to
|
||||
// panda3d@yahoogroups.com .
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: FreetypeFont::Destructor
|
||||
// Access: Public
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE FreetypeFont::
|
||||
~FreetypeFont() {
|
||||
unload_font();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: FreetypeFont::set_point_size
|
||||
// Access: Public
|
||||
// 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 FreetypeFont::
|
||||
set_point_size(float point_size) {
|
||||
_point_size = point_size;
|
||||
return reset_scale();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: FreetypeFont::get_point_size
|
||||
// Access: Public
|
||||
// Description: Returns the point size of the font.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE float FreetypeFont::
|
||||
get_point_size() const {
|
||||
return _point_size;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: FreetypeFont::set_pixels_per_unit
|
||||
// Access: Public
|
||||
// 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 FreetypeFont::
|
||||
set_pixels_per_unit(float pixels_per_unit) {
|
||||
_tex_pixels_per_unit = pixels_per_unit;
|
||||
return reset_scale();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: FreetypeFont::get_pixels_per_unit
|
||||
// Access: Public
|
||||
// Description: Returns the resolution of the texture map. See
|
||||
// set_pixels_per_unit().
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE float FreetypeFont::
|
||||
get_pixels_per_unit() const {
|
||||
return _tex_pixels_per_unit;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: FreetypeFont::set_pixel_size
|
||||
// Access: Public
|
||||
// Description: Computes the appropriate pixels_per_unit value to set
|
||||
// the size of the font in the texture to the indicated
|
||||
// number of pixels. This is just another way to
|
||||
// specify pixels_per_unit().
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE bool FreetypeFont::
|
||||
set_pixel_size(float pixel_size) {
|
||||
return set_pixels_per_unit(pixel_size * _points_per_unit / _point_size);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: FreetypeFont::get_pixel_size
|
||||
// Access: Public
|
||||
// Description: Returns the size of the font in pixels, as it appears
|
||||
// in the texture.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE float FreetypeFont::
|
||||
get_pixel_size() const {
|
||||
return _tex_pixels_per_unit * _point_size / _points_per_unit;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: FreetypeFont::set_scale_factor
|
||||
// Access: Public
|
||||
// Description: Sets the factor by which the font is rendered larger
|
||||
// by the FreeType library before being filtered down to
|
||||
// its actual size in the texture as specified by
|
||||
// set_pixels_per_unit(). This may be set to a number
|
||||
// larger than 1.0 to improve the font's antialiasing
|
||||
// (since FreeType doesn't really do a swell job of
|
||||
// antialiasing by itself). There is some performance
|
||||
// implication for setting this different than 1.0.
|
||||
//
|
||||
// This should only be called before any characters have
|
||||
// been requested out of the font, or immediately after
|
||||
// calling clear().
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE bool FreetypeFont::
|
||||
set_scale_factor(float scale_factor) {
|
||||
_scale_factor = scale_factor;
|
||||
return reset_scale();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: FreetypeFont::get_scale_factor
|
||||
// Access: Public
|
||||
// Description: Returns the antialiasing scale factor. See
|
||||
// set_scale_factor().
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE float FreetypeFont::
|
||||
get_scale_factor() const {
|
||||
return _scale_factor;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: FreetypeFont::get_line_height
|
||||
// Access: Public
|
||||
// Description: Returns the number of units high each line of text
|
||||
// is.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE float FreetypeFont::
|
||||
get_line_height() const {
|
||||
return _line_height;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: FreetypeFont::get_space_advance
|
||||
// Access: Public
|
||||
// Description: Returns the number of units wide a space is.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE float FreetypeFont::
|
||||
get_space_advance() const {
|
||||
return _space_advance;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: FreetypeFont::get_points_per_unit
|
||||
// Access: Public, Static
|
||||
// Description: Returns the point size of the font that is one Panda
|
||||
// unit high. This is an arbitrary Panda convention for
|
||||
// text, and is set to 10.0.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE float FreetypeFont::
|
||||
get_points_per_unit() {
|
||||
return _points_per_unit;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: FreetypeFont::get_points_per_inch
|
||||
// Access: Public, Static
|
||||
// Description: Returns the number of points in one inch. This is a
|
||||
// universal typographic convention.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE float FreetypeFont::
|
||||
get_points_per_inch() {
|
||||
return _points_per_inch;
|
||||
}
|
||||
|
|
@ -0,0 +1,379 @@
|
|||
// Filename: freetypeFont.cxx
|
||||
// Created by: drose (07Sep03)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// PANDA 3D SOFTWARE
|
||||
// Copyright (c) 2001, Disney Enterprises, Inc. All rights reserved
|
||||
//
|
||||
// All use of this software is subject to the terms of the Panda 3d
|
||||
// Software license. You should have received a copy of this license
|
||||
// along with this source code; you will also find a current copy of
|
||||
// the license at http://www.panda3d.org/license.txt .
|
||||
//
|
||||
// To contact the maintainers of this program write to
|
||||
// panda3d@yahoogroups.com .
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "freetypeFont.h"
|
||||
|
||||
#ifdef HAVE_FREETYPE
|
||||
|
||||
#include "config_pnmtext.h"
|
||||
#include "config_util.h"
|
||||
#include "config_express.h"
|
||||
#include "virtualFileSystem.h"
|
||||
|
||||
FT_Library FreetypeFont::_ft_library;
|
||||
bool FreetypeFont::_ft_initialized = false;
|
||||
bool FreetypeFont::_ft_ok = false;
|
||||
|
||||
// This constant determines how big a particular point size font
|
||||
// appears to be. By convention, 10 points is 1 unit (e.g. 1 foot)
|
||||
// high.
|
||||
const float FreetypeFont::_points_per_unit = 10.0f;
|
||||
|
||||
// A universal typographic convention.
|
||||
const float FreetypeFont::_points_per_inch = 72.0f;
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: FreetypeFont::Constructor
|
||||
// Access: Protected
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
FreetypeFont::
|
||||
FreetypeFont() {
|
||||
_font_loaded = false;
|
||||
|
||||
_point_size = text_point_size;
|
||||
_tex_pixels_per_unit = text_pixels_per_unit;
|
||||
_scale_factor = text_scale_factor;
|
||||
|
||||
_line_height = 1.0f;
|
||||
_space_advance = 0.25f;
|
||||
|
||||
if (!_ft_initialized) {
|
||||
initialize_ft_library();
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: FreetypeFont::load_font
|
||||
// Access: Protected
|
||||
// Description: This method accepts the name of some font file
|
||||
// that FreeType can read, along with face_index,
|
||||
// indicating which font within the file to load
|
||||
// (usually 0).
|
||||
////////////////////////////////////////////////////////////////////
|
||||
bool FreetypeFont::
|
||||
load_font(const Filename &font_filename, int face_index) {
|
||||
if (!_ft_ok) {
|
||||
pnmtext_cat.error()
|
||||
<< "Unable to read font " << font_filename
|
||||
<< ": FreeType library not initialized properly.\n";
|
||||
return false;
|
||||
}
|
||||
|
||||
unload_font();
|
||||
|
||||
bool exists = false;
|
||||
int error;
|
||||
Filename path(font_filename);
|
||||
if (use_vfs) {
|
||||
VirtualFileSystem *vfs = VirtualFileSystem::get_global_ptr();
|
||||
vfs->resolve_filename(path, get_model_path());
|
||||
exists = vfs->read_file(path, _raw_font_data);
|
||||
if (exists) {
|
||||
error = FT_New_Memory_Face(_ft_library,
|
||||
(const FT_Byte *)_raw_font_data.data(),
|
||||
_raw_font_data.length(),
|
||||
face_index, &_face);
|
||||
}
|
||||
} else {
|
||||
path.resolve_filename(get_model_path());
|
||||
exists = path.exists();
|
||||
if (exists) {
|
||||
string os_specific = path.to_os_specific();
|
||||
error = FT_New_Face(_ft_library, os_specific.c_str(),
|
||||
face_index, &_face);
|
||||
}
|
||||
}
|
||||
|
||||
if (!exists) {
|
||||
pnmtext_cat.error()
|
||||
<< "Unable to find font file " << font_filename << "\n";
|
||||
} else {
|
||||
if (error == FT_Err_Unknown_File_Format) {
|
||||
pnmtext_cat.error()
|
||||
<< "Unable to read font " << font_filename << ": unknown file format.\n";
|
||||
} else if (error) {
|
||||
pnmtext_cat.error()
|
||||
<< "Unable to read font " << font_filename << ": invalid.\n";
|
||||
|
||||
} else {
|
||||
return font_loaded();
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: FreetypeFont::load_font
|
||||
// Access: Protected
|
||||
// Description: This method accepts a table of data representing
|
||||
// the font file, loaded from some source other than a
|
||||
// filename on disk.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
bool FreetypeFont::
|
||||
load_font(const char *font_data, int data_length, int face_index) {
|
||||
if (!_ft_ok) {
|
||||
pnmtext_cat.error()
|
||||
<< "Unable to read font: FreeType library not initialized properly.\n";
|
||||
return false;
|
||||
}
|
||||
|
||||
unload_font();
|
||||
|
||||
int error;
|
||||
error = FT_New_Memory_Face(_ft_library,
|
||||
(const FT_Byte *)font_data, data_length,
|
||||
face_index, &_face);
|
||||
|
||||
if (error == FT_Err_Unknown_File_Format) {
|
||||
pnmtext_cat.error()
|
||||
<< "Unable to read font: unknown file format.\n";
|
||||
} else if (error) {
|
||||
pnmtext_cat.error()
|
||||
<< "Unable to read font: invalid.\n";
|
||||
|
||||
} else {
|
||||
return font_loaded();
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: FreetypeFont::unload_font
|
||||
// Access: Protected
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void FreetypeFont::
|
||||
unload_font() {
|
||||
if (_font_loaded) {
|
||||
FT_Done_Face(_face);
|
||||
_font_loaded = false;
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: FreetypeFont::copy_bitmap_to_pnmimage
|
||||
// Access: Protected
|
||||
// Description: Copies a bitmap as rendered by FreeType into a
|
||||
// PNMImage, so it can be rescaled.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void FreetypeFont::
|
||||
copy_bitmap_to_pnmimage(const FT_Bitmap &bitmap, PNMImage &image) {
|
||||
if (bitmap.pixel_mode == ft_pixel_mode_grays &&
|
||||
bitmap.num_grays == (int)image.get_maxval() + 1) {
|
||||
// This is the easy case: we can copy the rendered glyph
|
||||
// directly into our image, one pixel at a time.
|
||||
unsigned char *buffer_row = bitmap.buffer;
|
||||
for (int yi = 0; yi < bitmap.rows; yi++) {
|
||||
for (int xi = 0; xi < bitmap.width; xi++) {
|
||||
image.set_gray_val(xi, yi, buffer_row[xi]);
|
||||
}
|
||||
buffer_row += bitmap.pitch;
|
||||
}
|
||||
|
||||
} else if (bitmap.pixel_mode == ft_pixel_mode_mono) {
|
||||
// This is a little bit more work: we have to expand the
|
||||
// one-bit-per-pixel bitmap into a one-byte-per-pixel image.
|
||||
unsigned char *buffer_row = bitmap.buffer;
|
||||
for (int yi = 0; yi < bitmap.rows; yi++) {
|
||||
xelval maxval = image.get_maxval();
|
||||
int bit = 0x80;
|
||||
unsigned char *b = buffer_row;
|
||||
for (int xi = 0; xi < bitmap.width; xi++) {
|
||||
if (*b & bit) {
|
||||
image.set_gray_val(xi, yi, maxval);
|
||||
} else {
|
||||
image.set_gray_val(xi, yi, 0);
|
||||
}
|
||||
bit >>= 1;
|
||||
if (bit == 0) {
|
||||
++b;
|
||||
bit = 0x80;
|
||||
}
|
||||
}
|
||||
|
||||
buffer_row += bitmap.pitch;
|
||||
}
|
||||
|
||||
|
||||
} else if (bitmap.pixel_mode == ft_pixel_mode_grays) {
|
||||
// Here we must expand a grayscale pixmap with n levels of gray
|
||||
// into our 256-level texture.
|
||||
unsigned char *buffer_row = bitmap.buffer;
|
||||
for (int yi = 0; yi < bitmap.rows; yi++) {
|
||||
for (int xi = 0; xi < bitmap.width; xi++) {
|
||||
image.set_gray(xi, yi, (float)buffer_row[xi] / (bitmap.num_grays - 1));
|
||||
}
|
||||
buffer_row += bitmap.pitch;
|
||||
}
|
||||
|
||||
} else {
|
||||
pnmtext_cat.error()
|
||||
<< "Unexpected pixel mode in bitmap: " << (int)bitmap.pixel_mode << "\n";
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: FreetypeFont::font_loaded
|
||||
// Access: Private
|
||||
// Description: Called after a font has been successfully loaded,
|
||||
// either from disk or from memory image.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
bool FreetypeFont::
|
||||
font_loaded() {
|
||||
string name = _face->family_name;
|
||||
if (_face->style_name != NULL) {
|
||||
name += " ";
|
||||
name += _face->style_name;
|
||||
}
|
||||
set_name(name);
|
||||
|
||||
pnmtext_cat.info()
|
||||
<< "Loaded font " << name << "\n";
|
||||
_font_loaded = true;
|
||||
reset_scale();
|
||||
|
||||
if (pnmtext_cat.is_debug()) {
|
||||
pnmtext_cat.debug()
|
||||
<< name << " has " << _face->num_charmaps << " charmaps:\n";
|
||||
for (int i = 0; i < _face->num_charmaps; i++) {
|
||||
pnmtext_cat.debug(false) << " " << (void *)_face->charmaps[i];
|
||||
}
|
||||
pnmtext_cat.debug(false) << "\n";
|
||||
pnmtext_cat.debug()
|
||||
<< "default charmap is " << (void *)_face->charmap << "\n";
|
||||
}
|
||||
if (_face->charmap == NULL) {
|
||||
// If for some reason FreeType didn't set us up a charmap,
|
||||
// then set it up ourselves.
|
||||
if (_face->num_charmaps == 0) {
|
||||
pnmtext_cat.warning()
|
||||
<< name << " has no charmaps available.\n";
|
||||
} else {
|
||||
pnmtext_cat.warning()
|
||||
<< name << " has no default Unicode charmap.\n";
|
||||
if (_face->num_charmaps > 1) {
|
||||
pnmtext_cat.warning()
|
||||
<< "Arbitrarily choosing first of "
|
||||
<< _face->num_charmaps << " charmaps.\n";
|
||||
}
|
||||
FT_Set_Charmap(_face, _face->charmaps[0]);
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: FreetypeFont::reset_scale
|
||||
// Access: Private
|
||||
// Description: Resets the font based on the current values for
|
||||
// _point_size, _tex_pixels_per_unit, and _scale_factor.
|
||||
// Returns true if successful, false otherwise.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
bool FreetypeFont::
|
||||
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.
|
||||
_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);
|
||||
|
||||
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.
|
||||
int desired_height = (int)(_font_pixels_per_unit * _point_size / _points_per_unit + 0.5f);
|
||||
int best_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) {
|
||||
best_size = i;
|
||||
best_diff = diff;
|
||||
}
|
||||
}
|
||||
}
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (error) {
|
||||
pnmtext_cat.warning()
|
||||
<< "Unable to set " << get_name()
|
||||
<< " to " << _point_size << "pt at " << dpi << " dpi.\n";
|
||||
_line_height = 1.0f;
|
||||
return false;
|
||||
}
|
||||
|
||||
_line_height = _face->size->metrics.height / (_font_pixels_per_unit * 64.0f);
|
||||
|
||||
// Determine the correct width for a space.
|
||||
error = FT_Load_Char(_face, ' ', FT_LOAD_DEFAULT);
|
||||
if (error) {
|
||||
// Space isn't defined. Oh well.
|
||||
_space_advance = 0.25f * _line_height;
|
||||
|
||||
} else {
|
||||
_space_advance = _face->glyph->advance.x / (_font_pixels_per_unit * 64.0f);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: FreetypeFont::initialize_ft_library
|
||||
// Access: Private, Static
|
||||
// Description: Should be called exactly once to initialize the
|
||||
// FreeType library.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void FreetypeFont::
|
||||
initialize_ft_library() {
|
||||
if (!_ft_initialized) {
|
||||
int error = FT_Init_FreeType(&_ft_library);
|
||||
_ft_initialized = true;
|
||||
if (error) {
|
||||
pnmtext_cat.error()
|
||||
<< "Unable to initialize FreeType; dynamic fonts will not load.\n";
|
||||
} else {
|
||||
_ft_ok = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif // HAVE_FREETYPE
|
||||
|
|
@ -0,0 +1,111 @@
|
|||
// Filename: freetypeFont.h
|
||||
// Created by: drose (07Sep03)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// PANDA 3D SOFTWARE
|
||||
// Copyright (c) 2001, Disney Enterprises, Inc. All rights reserved
|
||||
//
|
||||
// All use of this software is subject to the terms of the Panda 3d
|
||||
// Software license. You should have received a copy of this license
|
||||
// along with this source code; you will also find a current copy of
|
||||
// the license at http://www.panda3d.org/license.txt .
|
||||
//
|
||||
// To contact the maintainers of this program write to
|
||||
// panda3d@yahoogroups.com .
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef FREETYPEFONT_H
|
||||
#define FREETYPEFONT_H
|
||||
|
||||
#include "pandabase.h"
|
||||
|
||||
#ifdef HAVE_FREETYPE
|
||||
|
||||
#include "config_text.h"
|
||||
#include "filename.h"
|
||||
#include "pvector.h"
|
||||
#include "pmap.h"
|
||||
#include "namable.h"
|
||||
|
||||
#include <ft2build.h>
|
||||
#include FT_FREETYPE_H
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Class : FreetypeFont
|
||||
// Description : This is a common base class for both DynamicTextFont
|
||||
// and PNMTextMaker. Both of these are utility classes
|
||||
// that use the FreeType library to generate glyphs from
|
||||
// fonts; this class abstracts out that common wrapper
|
||||
// around FreeType.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
class EXPCL_PANDA FreetypeFont : public Namable {
|
||||
protected:
|
||||
FreetypeFont();
|
||||
|
||||
bool load_font(const Filename &font_filename, int face_index);
|
||||
bool load_font(const char *font_data, int data_length, int face_index);
|
||||
void unload_font();
|
||||
|
||||
public:
|
||||
INLINE ~FreetypeFont();
|
||||
|
||||
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 bool set_pixel_size(float pixel_size);
|
||||
INLINE float get_pixel_size() const;
|
||||
|
||||
INLINE bool set_scale_factor(float scale_factor);
|
||||
INLINE float get_scale_factor() const;
|
||||
|
||||
INLINE float get_line_height() const;
|
||||
INLINE float get_space_advance() const;
|
||||
|
||||
INLINE static float get_points_per_unit();
|
||||
INLINE static float get_points_per_inch();
|
||||
|
||||
protected:
|
||||
void copy_bitmap_to_pnmimage(const FT_Bitmap &bitmap, PNMImage &image);
|
||||
|
||||
private:
|
||||
bool font_loaded();
|
||||
bool reset_scale();
|
||||
static void initialize_ft_library();
|
||||
|
||||
protected:
|
||||
float _point_size;
|
||||
float _tex_pixels_per_unit;
|
||||
float _scale_factor;
|
||||
float _font_pixels_per_unit;
|
||||
|
||||
float _line_height;
|
||||
float _space_advance;
|
||||
|
||||
FT_Face _face;
|
||||
|
||||
private:
|
||||
bool _font_loaded;
|
||||
|
||||
// This string is used to hold the data read from the font file in
|
||||
// vfs mode. Since the FreeType library keeps pointers into this
|
||||
// data, we have to keep it around.
|
||||
string _raw_font_data;
|
||||
|
||||
static FT_Library _ft_library;
|
||||
static bool _ft_initialized;
|
||||
static bool _ft_ok;
|
||||
|
||||
static const float _points_per_unit;
|
||||
static const float _points_per_inch;
|
||||
};
|
||||
|
||||
#include "freetypeFont.I"
|
||||
|
||||
#endif // HAVE_FREETYPE
|
||||
|
||||
#endif
|
||||
|
|
@ -189,6 +189,27 @@ trim_right(const string &str) {
|
|||
return str.substr(begin, end - begin);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: trim
|
||||
// Description: Returns a new string representing the contents of the
|
||||
// given string with both leading and trailing
|
||||
// whitespace removed.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
string
|
||||
trim(const string &str) {
|
||||
size_t begin = 0;
|
||||
while (begin < str.size() && isspace((unsigned int)str[begin])) {
|
||||
begin++;
|
||||
}
|
||||
|
||||
size_t end = str.size();
|
||||
while (end > begin && isspace((unsigned int)str[end - 1])) {
|
||||
end--;
|
||||
}
|
||||
|
||||
return str.substr(begin, end - begin);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: string_to_int
|
||||
// Description: A string-interface wrapper around the C library
|
||||
|
|
|
|||
|
|
@ -47,6 +47,7 @@ EXPCL_PANDA void tokenize(const string &str, vector_string &words,
|
|||
// Trims leading and/or trailing whitespace from the string.
|
||||
EXPCL_PANDA string trim_left(const string &str);
|
||||
EXPCL_PANDA string trim_right(const string &str);
|
||||
EXPCL_PANDA string trim(const string &str);
|
||||
|
||||
// Functions to parse numeric values out of a string.
|
||||
EXPCL_PANDA int string_to_int(const string &str, string &tail);
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@
|
|||
#define TARGET text
|
||||
#define LOCAL_LIBS \
|
||||
putil gobj pgraph linmath \
|
||||
pnmimage gsgbase mathutil
|
||||
pnmtext pnmimage gsgbase mathutil
|
||||
|
||||
#define COMBINED_SOURCES $[TARGET]_composite1.cxx
|
||||
|
||||
|
|
|
|||
|
|
@ -42,9 +42,6 @@ const int text_texture_margin = config_text.GetInt("text-texture-margin", 2);
|
|||
const float text_poly_margin = config_text.GetFloat("text-poly-margin", 0.0f);
|
||||
const int text_page_x_size = config_text.GetInt("text-page-x-size", 256);
|
||||
const int text_page_y_size = config_text.GetInt("text-page-y-size", 256);
|
||||
const float text_point_size = config_text.GetFloat("text-point-size", 10.0f);
|
||||
const float text_pixels_per_unit = config_text.GetFloat("text-pixels-per-unit", 30.0f);
|
||||
const float text_scale_factor = config_text.GetFloat("text-scale-factor", 2.0f);
|
||||
const bool text_small_caps = config_text.GetBool("text-small-caps", false);
|
||||
const float text_small_caps_scale = config_text.GetFloat("text-small-caps-scale", 0.8f);
|
||||
const string text_default_font = config_text.GetString("text-default-font", "");
|
||||
|
|
|
|||
|
|
@ -34,9 +34,6 @@ extern const int text_texture_margin;
|
|||
extern const float text_poly_margin;
|
||||
extern const int text_page_x_size;
|
||||
extern const int text_page_y_size;
|
||||
extern const float text_point_size;
|
||||
extern const float text_pixels_per_unit;
|
||||
extern const float text_scale_factor;
|
||||
extern const bool text_small_caps;
|
||||
extern const float text_small_caps_scale;
|
||||
extern const string text_default_font;
|
||||
|
|
|
|||
|
|
@ -17,6 +17,18 @@
|
|||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: DynamicTextFont::get_name
|
||||
// Access: Public
|
||||
// Description: Disambiguates the get_name() method between that
|
||||
// inherited from TextFont and that inherited from
|
||||
// FreetypeFont.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE const string &DynamicTextFont::
|
||||
get_name() const {
|
||||
return TextFont::get_name();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: DynamicTextFont::set_point_size
|
||||
// Access: Published
|
||||
|
|
@ -33,8 +45,7 @@ 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();
|
||||
return FreetypeFont::set_point_size(point_size);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
|
@ -44,7 +55,7 @@ set_point_size(float point_size) {
|
|||
////////////////////////////////////////////////////////////////////
|
||||
INLINE float DynamicTextFont::
|
||||
get_point_size() const {
|
||||
return _point_size;
|
||||
return FreetypeFont::get_point_size();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
|
@ -67,8 +78,7 @@ 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);
|
||||
|
||||
_tex_pixels_per_unit = pixels_per_unit;
|
||||
return reset_scale();
|
||||
return FreetypeFont::set_pixels_per_unit(pixels_per_unit);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
|
@ -79,7 +89,7 @@ set_pixels_per_unit(float pixels_per_unit) {
|
|||
////////////////////////////////////////////////////////////////////
|
||||
INLINE float DynamicTextFont::
|
||||
get_pixels_per_unit() const {
|
||||
return _tex_pixels_per_unit;
|
||||
return FreetypeFont::get_pixels_per_unit();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
|
@ -103,8 +113,7 @@ set_scale_factor(float scale_factor) {
|
|||
// If this assertion fails, you didn't call clear() first. RTFM.
|
||||
nassertr(get_num_pages() == 0, false);
|
||||
|
||||
_scale_factor = scale_factor;
|
||||
return reset_scale();
|
||||
return FreetypeFont::set_scale_factor(scale_factor);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
|
@ -115,7 +124,28 @@ set_scale_factor(float scale_factor) {
|
|||
////////////////////////////////////////////////////////////////////
|
||||
INLINE float DynamicTextFont::
|
||||
get_scale_factor() const {
|
||||
return _scale_factor;
|
||||
return FreetypeFont::get_scale_factor();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: DynamicTextFont::get_line_height
|
||||
// Access: Public
|
||||
// Description: Returns the number of units high each line of text
|
||||
// is.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE float DynamicTextFont::
|
||||
get_line_height() const {
|
||||
return TextFont::get_line_height();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: DynamicTextFont::get_space_advance
|
||||
// Access: Public
|
||||
// Description: Returns the number of units wide a space is.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE float DynamicTextFont::
|
||||
get_space_advance() const {
|
||||
return TextFont::get_space_advance();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
|
@ -314,3 +344,8 @@ INLINE bool DynamicTextFont::
|
|||
get_update_cleared_glyphs() {
|
||||
return _update_cleared_glyphs;
|
||||
}
|
||||
|
||||
INLINE ostream &
|
||||
operator << (ostream &out, const DynamicTextFont &dtf) {
|
||||
return out << dtf.get_name();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -27,21 +27,9 @@
|
|||
|
||||
bool DynamicTextFont::_update_cleared_glyphs = text_update_cleared_glyphs;
|
||||
|
||||
FT_Library DynamicTextFont::_ft_library;
|
||||
bool DynamicTextFont::_ft_initialized = false;
|
||||
bool DynamicTextFont::_ft_ok = false;
|
||||
|
||||
TypeHandle DynamicTextFont::_type_handle;
|
||||
|
||||
|
||||
// This constant determines how big a particular point size font
|
||||
// appears to be. By convention, 10 points is 1 unit (e.g. 1 foot)
|
||||
// high.
|
||||
static const float points_per_unit = 10.0f;
|
||||
|
||||
// A universal typographic convention.
|
||||
static const float points_per_inch = 72.0f;
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: DynamicTextFont::Constructor
|
||||
// Access: Published
|
||||
|
|
@ -53,90 +41,10 @@ static const float points_per_inch = 72.0f;
|
|||
DynamicTextFont::
|
||||
DynamicTextFont(const Filename &font_filename, int face_index) {
|
||||
initialize();
|
||||
|
||||
if (!_ft_ok) {
|
||||
text_cat.error()
|
||||
<< "Unable to read font " << font_filename
|
||||
<< ": FreeType library not initialized properly.\n";
|
||||
return;
|
||||
}
|
||||
|
||||
bool exists = false;
|
||||
int error;
|
||||
Filename path(font_filename);
|
||||
if (use_vfs) {
|
||||
VirtualFileSystem *vfs = VirtualFileSystem::get_global_ptr();
|
||||
vfs->resolve_filename(path, get_model_path());
|
||||
exists = vfs->read_file(path, _raw_font_data);
|
||||
if (exists) {
|
||||
error = FT_New_Memory_Face(_ft_library,
|
||||
(const FT_Byte *)_raw_font_data.data(),
|
||||
_raw_font_data.length(),
|
||||
face_index, &_face);
|
||||
}
|
||||
} else {
|
||||
path.resolve_filename(get_model_path());
|
||||
exists = path.exists();
|
||||
if (exists) {
|
||||
string os_specific = path.to_os_specific();
|
||||
error = FT_New_Face(_ft_library, os_specific.c_str(),
|
||||
face_index, &_face);
|
||||
}
|
||||
}
|
||||
|
||||
if (!exists) {
|
||||
text_cat.error()
|
||||
<< "Unable to find font file " << font_filename << "\n";
|
||||
} else {
|
||||
if (error == FT_Err_Unknown_File_Format) {
|
||||
text_cat.error()
|
||||
<< "Unable to read font " << font_filename << ": unknown file format.\n";
|
||||
} else if (error) {
|
||||
text_cat.error()
|
||||
<< "Unable to read font " << font_filename << ": invalid.\n";
|
||||
|
||||
} else {
|
||||
string name = _face->family_name;
|
||||
if (_face->style_name != NULL) {
|
||||
name += " ";
|
||||
name += _face->style_name;
|
||||
}
|
||||
set_name(name);
|
||||
|
||||
text_cat.info()
|
||||
<< "Loaded font " << get_name() << "\n";
|
||||
_is_valid = true;
|
||||
reset_scale();
|
||||
|
||||
if (text_cat.is_debug()) {
|
||||
text_cat.debug()
|
||||
<< *this << " has " << _face->num_charmaps << " charmaps:\n";
|
||||
for (int i = 0; i < _face->num_charmaps; i++) {
|
||||
text_cat.debug(false) << " " << (void *)_face->charmaps[i];
|
||||
}
|
||||
text_cat.debug(false) << "\n";
|
||||
text_cat.debug()
|
||||
<< "default charmap is " << (void *)_face->charmap << "\n";
|
||||
}
|
||||
if (_face->charmap == NULL) {
|
||||
// If for some reason FreeType didn't set us up a charmap,
|
||||
// then set it up ourselves.
|
||||
if (_face->num_charmaps == 0) {
|
||||
text_cat.warning()
|
||||
<< *this << " has no charmaps available.\n";
|
||||
} else {
|
||||
text_cat.warning()
|
||||
<< *this << " has no default Unicode charmap.\n";
|
||||
if (_face->num_charmaps > 1) {
|
||||
text_cat.warning()
|
||||
<< "Arbitrarily choosing first of "
|
||||
<< _face->num_charmaps << " charmaps.\n";
|
||||
}
|
||||
FT_Set_Charmap(_face, _face->charmaps[0]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
_is_valid = load_font(font_filename, face_index);
|
||||
TextFont::set_name(FreetypeFont::get_name());
|
||||
TextFont::_line_height = FreetypeFont::get_line_height();
|
||||
TextFont::_space_advance = FreetypeFont::get_space_advance();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
|
@ -149,51 +57,19 @@ DynamicTextFont(const Filename &font_filename, int face_index) {
|
|||
DynamicTextFont::
|
||||
DynamicTextFont(const char *font_data, int data_length, int face_index) {
|
||||
initialize();
|
||||
|
||||
if (!_ft_ok) {
|
||||
text_cat.error()
|
||||
<< "Unable to read font: FreeType library not initialized properly.\n";
|
||||
return;
|
||||
}
|
||||
|
||||
int error;
|
||||
error = FT_New_Memory_Face(_ft_library,
|
||||
(const FT_Byte *)font_data, data_length,
|
||||
face_index, &_face);
|
||||
|
||||
if (error == FT_Err_Unknown_File_Format) {
|
||||
text_cat.error()
|
||||
<< "Unable to read font: unknown file format.\n";
|
||||
} else if (error) {
|
||||
text_cat.error()
|
||||
<< "Unable to read font: invalid.\n";
|
||||
|
||||
} else {
|
||||
string name = _face->family_name;
|
||||
if (_face->style_name != NULL) {
|
||||
name += " ";
|
||||
name += _face->style_name;
|
||||
}
|
||||
set_name(name);
|
||||
|
||||
text_cat.info()
|
||||
<< "Loaded font " << get_name() << "\n";
|
||||
_is_valid = true;
|
||||
reset_scale();
|
||||
}
|
||||
_is_valid = load_font(font_data, data_length, face_index);
|
||||
TextFont::set_name(FreetypeFont::get_name());
|
||||
TextFont::_line_height = FreetypeFont::_line_height;
|
||||
TextFont::_space_advance = FreetypeFont::_space_advance;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: DynamicTextFont::Constructor
|
||||
// Function: DynamicTextFont::Destructor
|
||||
// Access: Published, Virtual
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
DynamicTextFont::
|
||||
~DynamicTextFont() {
|
||||
if (_is_valid) {
|
||||
FT_Done_Face(_face);
|
||||
_is_valid = false;
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
|
@ -380,8 +256,8 @@ get_glyph(int character, const TextGlyph *&glyph) {
|
|||
////////////////////////////////////////////////////////////////////
|
||||
// Function: DynamicTextFont::initialize
|
||||
// Access: Private
|
||||
// Description: Called from both constructors to set up some internal
|
||||
// structures.
|
||||
// Description: Called from both constructors to set up some initial
|
||||
// values.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void DynamicTextFont::
|
||||
initialize() {
|
||||
|
|
@ -389,9 +265,6 @@ initialize() {
|
|||
_poly_margin = text_poly_margin;
|
||||
_page_x_size = text_page_x_size;
|
||||
_page_y_size = text_page_y_size;
|
||||
_point_size = text_point_size;
|
||||
_tex_pixels_per_unit = text_pixels_per_unit;
|
||||
_scale_factor = text_scale_factor;
|
||||
|
||||
// We don't necessarily want to use mipmaps, since we don't want to
|
||||
// regenerate those every time the texture changes, but we probably
|
||||
|
|
@ -404,12 +277,7 @@ initialize() {
|
|||
// require generating mipmaps, but does require hardware support.
|
||||
_anisotropic_degree = text_anisotropic_degree;
|
||||
|
||||
|
||||
_preferred_page = 0;
|
||||
|
||||
if (!_ft_initialized) {
|
||||
initialize_ft_library();
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
|
@ -429,81 +297,6 @@ update_filters() {
|
|||
page->set_anisotropic_degree(_anisotropic_degree);
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: DynamicTextFont::reset_scale
|
||||
// Access: Private
|
||||
// Description: Resets the font based on the current values for
|
||||
// _point_size, _tex_pixels_per_unit, and _scale_factor.
|
||||
// Returns true if successful, false otherwise.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
bool DynamicTextFont::
|
||||
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 aned _tex_pixels_per_unit.
|
||||
_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);
|
||||
|
||||
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.
|
||||
int desired_height = (int)(_font_pixels_per_unit * _point_size / points_per_unit + 0.5f);
|
||||
int best_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) {
|
||||
best_size = i;
|
||||
best_diff = diff;
|
||||
}
|
||||
}
|
||||
}
|
||||
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) {
|
||||
text_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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (error) {
|
||||
text_cat.warning()
|
||||
<< "Unable to set " << get_name()
|
||||
<< " to " << _point_size << "pt at " << dpi << " dpi.\n";
|
||||
_line_height = 1.0f;
|
||||
return false;
|
||||
}
|
||||
|
||||
_line_height = _face->size->metrics.height / (_font_pixels_per_unit * 64.0f);
|
||||
|
||||
// Determine the correct width for a space.
|
||||
error = FT_Load_Char(_face, ' ', FT_LOAD_DEFAULT);
|
||||
if (error) {
|
||||
// Space isn't defined. Oh well.
|
||||
_space_advance = 0.25f * _line_height;
|
||||
|
||||
} else {
|
||||
_space_advance = _face->glyph->advance.x / (_font_pixels_per_unit * 64.0f);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: DynamicTextFont::make_glyph
|
||||
|
|
@ -643,68 +436,6 @@ copy_bitmap_to_texture(const FT_Bitmap &bitmap, DynamicTextGlyph *glyph) {
|
|||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: DynamicTextFont::copy_bitmap_to_pnmimage
|
||||
// Access: Private
|
||||
// Description: Copies a bitmap as rendered by FreeType into a
|
||||
// PNMImage, so it can be rescaled.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void DynamicTextFont::
|
||||
copy_bitmap_to_pnmimage(const FT_Bitmap &bitmap, PNMImage &image) {
|
||||
if (bitmap.pixel_mode == ft_pixel_mode_grays &&
|
||||
bitmap.num_grays == (int)image.get_maxval() + 1) {
|
||||
// This is the easy case: we can copy the rendered glyph
|
||||
// directly into our image, one pixel at a time.
|
||||
unsigned char *buffer_row = bitmap.buffer;
|
||||
for (int yi = 0; yi < bitmap.rows; yi++) {
|
||||
for (int xi = 0; xi < bitmap.width; xi++) {
|
||||
image.set_gray_val(xi, yi, buffer_row[xi]);
|
||||
}
|
||||
buffer_row += bitmap.pitch;
|
||||
}
|
||||
|
||||
} else if (bitmap.pixel_mode == ft_pixel_mode_mono) {
|
||||
// This is a little bit more work: we have to expand the
|
||||
// one-bit-per-pixel bitmap into a one-byte-per-pixel image.
|
||||
unsigned char *buffer_row = bitmap.buffer;
|
||||
for (int yi = 0; yi < bitmap.rows; yi++) {
|
||||
xelval maxval = image.get_maxval();
|
||||
int bit = 0x80;
|
||||
unsigned char *b = buffer_row;
|
||||
for (int xi = 0; xi < bitmap.width; xi++) {
|
||||
if (*b & bit) {
|
||||
image.set_gray_val(xi, yi, maxval);
|
||||
} else {
|
||||
image.set_gray_val(xi, yi, 0);
|
||||
}
|
||||
bit >>= 1;
|
||||
if (bit == 0) {
|
||||
++b;
|
||||
bit = 0x80;
|
||||
}
|
||||
}
|
||||
|
||||
buffer_row += bitmap.pitch;
|
||||
}
|
||||
|
||||
|
||||
} else if (bitmap.pixel_mode == ft_pixel_mode_grays) {
|
||||
// Here we must expand a grayscale pixmap with n levels of gray
|
||||
// into our 256-level texture.
|
||||
unsigned char *buffer_row = bitmap.buffer;
|
||||
for (int yi = 0; yi < bitmap.rows; yi++) {
|
||||
for (int xi = 0; xi < bitmap.width; xi++) {
|
||||
image.set_gray(xi, yi, (float)buffer_row[xi] / (bitmap.num_grays - 1));
|
||||
}
|
||||
buffer_row += bitmap.pitch;
|
||||
}
|
||||
|
||||
} else {
|
||||
text_cat.error()
|
||||
<< "Unexpected pixel mode in bitmap: " << (int)bitmap.pixel_mode << "\n";
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: DynamicTextFont::copy_pnmimage_to_texture
|
||||
// Access: Private
|
||||
|
|
@ -783,25 +514,4 @@ slot_glyph(int x_size, int y_size) {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: DynamicTextFont::initialize_ft_library
|
||||
// Access: Private, Static
|
||||
// Description: Should be called exactly once to initialize the
|
||||
// FreeType library.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void DynamicTextFont::
|
||||
initialize_ft_library() {
|
||||
if (!_ft_initialized) {
|
||||
int error = FT_Init_FreeType(&_ft_library);
|
||||
_ft_initialized = true;
|
||||
if (error) {
|
||||
text_cat.error()
|
||||
<< "Unable to initialize FreeType; DynamicTextFonts will not load.\n";
|
||||
} else {
|
||||
_ft_ok = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif // HAVE_FREETYPE
|
||||
|
|
|
|||
|
|
@ -25,6 +25,7 @@
|
|||
|
||||
#include "config_text.h"
|
||||
#include "textFont.h"
|
||||
#include "freetypeFont.h"
|
||||
#include "dynamicTextGlyph.h"
|
||||
#include "dynamicTextPage.h"
|
||||
#include "filename.h"
|
||||
|
|
@ -42,12 +43,14 @@
|
|||
// FreeType 2.0 library (or any higher,
|
||||
// backward-compatible version).
|
||||
////////////////////////////////////////////////////////////////////
|
||||
class EXPCL_PANDA DynamicTextFont : public TextFont {
|
||||
class EXPCL_PANDA DynamicTextFont : public TextFont, public FreetypeFont {
|
||||
PUBLISHED:
|
||||
DynamicTextFont(const Filename &font_filename, int face_index = 0);
|
||||
DynamicTextFont(const char *font_data, int data_length, int face_index);
|
||||
virtual ~DynamicTextFont();
|
||||
|
||||
INLINE const string &get_name() const;
|
||||
|
||||
INLINE bool set_point_size(float point_size);
|
||||
INLINE float get_point_size() const;
|
||||
|
||||
|
|
@ -57,6 +60,9 @@ PUBLISHED:
|
|||
INLINE bool set_scale_factor(float scale_factor);
|
||||
INLINE float get_scale_factor() const;
|
||||
|
||||
INLINE float get_line_height() const;
|
||||
INLINE float get_space_advance() const;
|
||||
|
||||
INLINE void set_texture_margin(int texture_margin);
|
||||
INLINE int get_texture_margin() const;
|
||||
INLINE void set_poly_margin(float poly_margin);
|
||||
|
|
@ -91,19 +97,11 @@ public:
|
|||
private:
|
||||
void initialize();
|
||||
void update_filters();
|
||||
bool reset_scale();
|
||||
DynamicTextGlyph *make_glyph(int glyph_index);
|
||||
void copy_bitmap_to_texture(const FT_Bitmap &bitmap, DynamicTextGlyph *glyph);
|
||||
void copy_bitmap_to_pnmimage(const FT_Bitmap &bitmap, PNMImage &image);
|
||||
void copy_pnmimage_to_texture(const PNMImage &image, DynamicTextGlyph *glyph);
|
||||
DynamicTextGlyph *slot_glyph(int x_size, int y_size);
|
||||
|
||||
static void initialize_ft_library();
|
||||
|
||||
float _point_size;
|
||||
float _tex_pixels_per_unit;
|
||||
float _scale_factor;
|
||||
float _font_pixels_per_unit;
|
||||
int _texture_margin;
|
||||
float _poly_margin;
|
||||
int _page_x_size, _page_y_size;
|
||||
|
|
@ -129,17 +127,6 @@ private:
|
|||
typedef pvector< PT(DynamicTextGlyph) > EmptyGlyphs;
|
||||
EmptyGlyphs _empty_glyphs;
|
||||
|
||||
FT_Face _face;
|
||||
|
||||
// This string is used to hold the data read from the font file in
|
||||
// vfs mode. Since the FreeType library keeps pointers into this
|
||||
// data, we have to keep it around.
|
||||
string _raw_font_data;
|
||||
|
||||
static FT_Library _ft_library;
|
||||
static bool _ft_initialized;
|
||||
static bool _ft_ok;
|
||||
|
||||
public:
|
||||
static TypeHandle get_class_type() {
|
||||
return _type_handle;
|
||||
|
|
@ -160,6 +147,8 @@ private:
|
|||
friend class TextNode;
|
||||
};
|
||||
|
||||
INLINE ostream &operator << (ostream &out, const DynamicTextFont &dtf);
|
||||
|
||||
#include "dynamicTextFont.I"
|
||||
|
||||
#endif // HAVE_FREETYPE
|
||||
|
|
|
|||
Loading…
Reference in New Issue