TextFont::make_copy()

This commit is contained in:
David Rose 2010-05-03 03:51:15 +00:00
parent 62889f3fa6
commit 6a7580ca45
15 changed files with 407 additions and 187 deletions

View File

@ -9,7 +9,7 @@
#define TARGET pnmtext
#define LOCAL_LIBS \
pnmimage putil linmath
pnmimage putil linmath pipeline
#define SOURCES \
config_pnmtext.cxx config_pnmtext.h \

View File

@ -12,25 +12,3 @@
//
////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////
// Function: FreetypeFace::get_face
// Access: Published
// Description: Retrieves the internal freetype face.
////////////////////////////////////////////////////////////////////
INLINE FT_Face FreetypeFace::
get_face() {
return _face;
}
////////////////////////////////////////////////////////////////////
// Function: FreetypeFace::set_face
// Access: Published
// Description: Sets the internal freetype face.
////////////////////////////////////////////////////////////////////
INLINE void FreetypeFace::
set_face(FT_Face face) {
if (_face != NULL){
FT_Done_Face(_face);
}
_face = face;
}

View File

@ -16,6 +16,12 @@
#ifdef HAVE_FREETYPE
#include "config_pnmtext.h"
FT_Library FreetypeFace::_ft_library;
bool FreetypeFace::_ft_initialized = false;
bool FreetypeFace::_ft_ok = false;
TypeHandle FreetypeFace::_type_handle;
////////////////////////////////////////////////////////////////////
@ -24,8 +30,16 @@ TypeHandle FreetypeFace::_type_handle;
// Description:
////////////////////////////////////////////////////////////////////
FreetypeFace::
FreetypeFace() {
FreetypeFace() : _lock("FreetypeFace::_lock") {
_face = NULL;
_char_size = 0;
_dpi = 0;
_pixel_width = 0;
_pixel_height = 0;
if (!_ft_initialized) {
initialize_ft_library();
}
}
////////////////////////////////////////////////////////////////////
@ -40,4 +54,131 @@ FreetypeFace::
}
}
////////////////////////////////////////////////////////////////////
// Function: FreetypeFace::acquire_face
// Access: Public
// Description: Retrieves the internal freetype face, and also
// acquires the lock. The freetype face is set to the
// indicated size, either as a char_size and dpi, or as
// a specific pixel_width and height, before returning.
//
// You must call release_face() when you are done using
// it, to release the lock.
////////////////////////////////////////////////////////////////////
FT_Face FreetypeFace::
acquire_face(int char_size, int dpi, int pixel_width, int pixel_height) {
_lock.acquire();
if (pixel_height != 0) {
if (pixel_height != _pixel_height || pixel_width != _pixel_width) {
_char_size = 0;
_dpi = 0;
_pixel_height = pixel_height;
_pixel_width = pixel_width;
FT_Set_Pixel_Sizes(_face, _pixel_width, _pixel_height);
}
} else {
if (char_size != _char_size || dpi != _dpi) {
_char_size = char_size;
_dpi = dpi;
_pixel_height = 0;
_pixel_width = 0;
if (_char_size != 0) {
FT_Set_Char_Size(_face, _char_size, _char_size, _dpi, _dpi);
}
}
}
return _face;
}
////////////////////////////////////////////////////////////////////
// Function: FreetypeFace::release_face
// Access: Public
// Description: Releases the lock acquired by a previous call to
// acquire_face(), and allows another thread to use the
// face.
////////////////////////////////////////////////////////////////////
void FreetypeFace::
release_face(FT_Face face) {
nassertv(_face == face);
_lock.release();
}
////////////////////////////////////////////////////////////////////
// Function: FreetypeFace::set_face
// Access: Public
// Description: Replaces the internal freetype face.
////////////////////////////////////////////////////////////////////
void FreetypeFace::
set_face(FT_Face face) {
MutexHolder holder(_lock);
if (_face != NULL){
FT_Done_Face(_face);
}
_face = face;
_char_size = 0;
_dpi = 0;
_pixel_width = 0;
_pixel_height = 0;
_name = _face->family_name;
if (_face->style_name != NULL) {
_name += " ";
_name += _face->style_name;
}
pnmtext_cat.info()
<< "Loaded font " << _name << "\n";
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]);
}
}
}
////////////////////////////////////////////////////////////////////
// Function: FreetypeFace::initialize_ft_library
// Access: Private, Static
// Description: Should be called exactly once to initialize the
// FreeType library.
////////////////////////////////////////////////////////////////////
void FreetypeFace::
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

View File

@ -19,13 +19,10 @@
#ifdef HAVE_FREETYPE
//#include "config_pnmtext.h"
//#include "filename.h"
//#include "pvector.h"
//#include "pmap.h"
//#include "pnmImage.h"
#include "typedReferenceCount.h"
#include "namable.h"
#include "pmutex.h"
#include "mutexHolder.h"
#include <ft2build.h>
#include FT_FREETYPE_H
@ -40,16 +37,33 @@
class EXPCL_PANDA_PNMTEXT FreetypeFace : public TypedReferenceCount, public Namable {
public:
FreetypeFace();
PUBLISHED:
~FreetypeFace();
INLINE FT_Face get_face();
INLINE void set_face(FT_Face face);
FT_Face acquire_face();
FT_Face acquire_face(int char_size, int dpi, int pixel_width, int pixel_height);
void release_face(FT_Face face);
void set_face(FT_Face face);
private:
FT_Face _face;
static void initialize_ft_library();
private:
// This is provided as a permanent storage for the raw font data, if
// needed.
string _font_data;
string _name;
FT_Face _face;
int _char_size;
int _dpi;
int _pixel_width;
int _pixel_height;
Mutex _lock;
static FT_Library _ft_library;
static bool _ft_initialized;
static bool _ft_ok;
public:
static TypeHandle get_class_type() {
@ -67,6 +81,8 @@ public:
private:
static TypeHandle _type_handle;
friend class FreetypeFont;
};

View File

@ -185,7 +185,7 @@ get_native_antialias() const {
////////////////////////////////////////////////////////////////////
INLINE int FreetypeFont::
get_font_pixel_size() const {
return _font_pixel_size;
return _pixel_height;
}
////////////////////////////////////////////////////////////////////
@ -231,3 +231,31 @@ INLINE float FreetypeFont::
get_points_per_inch() {
return _points_per_inch;
}
////////////////////////////////////////////////////////////////////
// Function: FreetypeFont::acquire_face
// Access: Protected
// Description: Retrieves the internal freetype face, and also
// acquires the lock.
//
// You must call release_face() when you are done using
// it, to release the lock.
////////////////////////////////////////////////////////////////////
INLINE FT_Face FreetypeFont::
acquire_face() const {
nassertr(_face != NULL, NULL);
return _face->acquire_face(_char_size, _dpi, _pixel_width, _pixel_height);
}
////////////////////////////////////////////////////////////////////
// Function: FreetypeFont::release_face
// Access: Protected
// Description: Releases the lock acquired by a previous call to
// acquire_face(), and allows another thread to use the
// face.
////////////////////////////////////////////////////////////////////
INLINE void FreetypeFont::
release_face(FT_Face face) const {
nassertv(_face != NULL);
_face->release_face(face);
}

View File

@ -21,10 +21,6 @@
#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.
@ -40,8 +36,6 @@ const float FreetypeFont::_points_per_inch = 72.0f;
////////////////////////////////////////////////////////////////////
FreetypeFont::
FreetypeFont() {
_font_loaded = false;
_face = NULL;
_point_size = text_point_size;
@ -51,13 +45,37 @@ FreetypeFont() {
_scale_factor = text_scale_factor;
_native_antialias = text_native_antialias;
_font_pixel_size = 0;
_line_height = 1.0f;
_space_advance = 0.25f;
if (!_ft_initialized) {
initialize_ft_library();
}
_char_size = 0;
_dpi = 0;
_pixel_width = 0;
_pixel_height = 0;
}
////////////////////////////////////////////////////////////////////
// Function: FreetypeFont::Copy Constructor
// Access: Protected
// Description:
////////////////////////////////////////////////////////////////////
FreetypeFont::
FreetypeFont(const FreetypeFont &copy) :
Namable(copy),
_face(copy._face),
_point_size(copy._point_size),
_requested_pixels_per_unit(copy._requested_pixels_per_unit),
_tex_pixels_per_unit(copy._tex_pixels_per_unit),
_requested_scale_factor(copy._requested_scale_factor),
_scale_factor(copy._scale_factor),
_native_antialias(copy._native_antialias),
_line_height(copy._line_height),
_space_advance(copy._space_advance),
_char_size(copy._char_size),
_dpi(copy._dpi),
_pixel_width(copy._pixel_width),
_pixel_height(copy._pixel_height)
{
}
////////////////////////////////////////////////////////////////////
@ -70,31 +88,32 @@ FreetypeFont() {
////////////////////////////////////////////////////////////////////
bool FreetypeFont::
load_font(const Filename &font_filename, int face_index) {
if (!_ft_ok) {
unload_font();
_face = new FreetypeFace;
if (!_face->_ft_ok) {
pnmtext_cat.error()
<< "Unable to read font " << font_filename
<< ": FreeType library not initialized properly.\n";
unload_font();
return false;
}
unload_font();
bool exists = false;
int error;
Filename path(font_filename);
VirtualFileSystem *vfs = VirtualFileSystem::get_global_ptr();
vfs->resolve_filename(path, get_model_path());
exists = vfs->read_file(path, _raw_font_data, true);
exists = vfs->read_file(path, _face->_font_data, true);
if (exists) {
FT_Face face;
error = FT_New_Memory_Face(_ft_library,
(const FT_Byte *)_raw_font_data.data(),
_raw_font_data.length(),
error = FT_New_Memory_Face(_face->_ft_library,
(const FT_Byte *)_face->_font_data.data(),
_face->_font_data.length(),
face_index, &face);
_face = new FreetypeFace();
_face->set_face(face);
}
bool okflag = false;
if (!exists) {
pnmtext_cat.error()
<< "Unable to find font file " << font_filename << "\n";
@ -107,11 +126,15 @@ load_font(const Filename &font_filename, int face_index) {
<< "Unable to read font " << font_filename << ": invalid.\n";
} else {
return font_loaded();
okflag = reset_scale();
}
}
if (!okflag) {
unload_font();
}
return false;
return okflag;
}
////////////////////////////////////////////////////////////////////
@ -123,22 +146,24 @@ load_font(const Filename &font_filename, int face_index) {
////////////////////////////////////////////////////////////////////
bool FreetypeFont::
load_font(const char *font_data, int data_length, int face_index) {
if (!_ft_ok) {
unload_font();
_face = new FreetypeFace;
if (!_face->_ft_ok) {
pnmtext_cat.error()
<< "Unable to read font: FreeType library not initialized properly.\n";
unload_font();
return false;
}
unload_font();
int error;
FT_Face face;
error = FT_New_Memory_Face(_ft_library,
error = FT_New_Memory_Face(_face->_ft_library,
(const FT_Byte *)font_data, data_length,
face_index, &face);
_face = new FreetypeFace();
_face->set_face(face);
bool okflag = false;
if (error == FT_Err_Unknown_File_Format) {
pnmtext_cat.error()
<< "Unable to read font: unknown file format.\n";
@ -147,10 +172,14 @@ load_font(const char *font_data, int data_length, int face_index) {
<< "Unable to read font: invalid.\n";
} else {
return font_loaded();
okflag = reset_scale();
}
return false;
if (!okflag) {
unload_font();
}
return okflag;
}
////////////////////////////////////////////////////////////////////
@ -160,10 +189,7 @@ load_font(const char *font_data, int data_length, int face_index) {
////////////////////////////////////////////////////////////////////
void FreetypeFont::
unload_font() {
if (_font_loaded) {
_face = NULL;
_font_loaded = false;
}
_face = NULL;
}
////////////////////////////////////////////////////////////////////
@ -174,7 +200,7 @@ unload_font() {
// false otherwise.
////////////////////////////////////////////////////////////////////
bool FreetypeFont::
load_glyph(int glyph_index, bool prerender) {
load_glyph(FT_Face face, int glyph_index, bool prerender) {
int flags = FT_LOAD_RENDER;
if (!_native_antialias) {
flags |= FT_LOAD_MONOCHROME;
@ -186,7 +212,7 @@ load_glyph(int glyph_index, bool prerender) {
flags = 0;
}
int error = FT_Load_Glyph(_face->get_face(), glyph_index, flags);
int error = FT_Load_Glyph(face, glyph_index, flags);
if (error) {
pnmtext_cat.error()
<< "Unable to render glyph " << glyph_index << "\n";
@ -256,57 +282,6 @@ copy_bitmap_to_pnmimage(const FT_Bitmap &bitmap, PNMImage &image) {
<< "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->get_face()->family_name;
if (_face->get_face()->style_name != NULL) {
name += " ";
name += _face->get_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->get_face()->num_charmaps << " charmaps:\n";
for (int i = 0; i < _face->get_face()->num_charmaps; i++) {
pnmtext_cat.debug(false) << " " << (void *)_face->get_face()->charmaps[i];
}
pnmtext_cat.debug(false) << "\n";
pnmtext_cat.debug()
<< "default charmap is " << (void *)_face->get_face()->charmap << "\n";
}
if (_face->get_face()->charmap == NULL) {
// If for some reason FreeType didn't set us up a charmap,
// then set it up ourselves.
if (_face->get_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->get_face()->num_charmaps > 1) {
pnmtext_cat.warning()
<< "Arbitrarily choosing first of "
<< _face->get_face()->num_charmaps << " charmaps.\n";
}
FT_Set_Charmap(_face->get_face(), _face->get_face()->charmaps[0]);
}
}
return true;
}
////////////////////////////////////////////////////////////////////
// Function: FreetypeFont::reset_scale
@ -317,6 +292,14 @@ font_loaded() {
////////////////////////////////////////////////////////////////////
bool FreetypeFont::
reset_scale() {
if (_face == NULL) {
return false;
}
// Get the face, without requesting a particular size yet (we'll
// figure out the size in a second).
FT_Face face = _face->acquire_face(0, 0, 0, 0);
// 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.
@ -324,13 +307,13 @@ reset_scale() {
_scale_factor = _requested_scale_factor;
_font_pixels_per_unit = _tex_pixels_per_unit * _scale_factor;
_pixel_height = 0;
_pixel_width = 0;
float units_per_inch = (_points_per_inch / _points_per_unit);
int dpi = (int)(_font_pixels_per_unit * units_per_inch);
_dpi = (int)(_font_pixels_per_unit * units_per_inch);
_char_size = (int)(_point_size * 64);
_font_pixel_size = 0;
int error = FT_Set_Char_Size(_face->get_face(),
(int)(_point_size * 64), (int)(_point_size * 64),
dpi, dpi);
int error = FT_Set_Char_Size(face, _char_size, _char_size, _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 next larger
@ -339,16 +322,16 @@ reset_scale() {
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->get_face()->num_fixed_sizes > 0) {
if (face->num_fixed_sizes > 0) {
largest_size = 0;
int best_diff = 0;
for (int i = 0; i < _face->get_face()->num_fixed_sizes; i++) {
int diff = _face->get_face()->available_sizes[i].height - desired_height;
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->get_face()->available_sizes[i].height > _face->get_face()->available_sizes[largest_size].height) {
if (face->available_sizes[i].height > face->available_sizes[largest_size].height) {
largest_size = i;
}
}
@ -358,13 +341,12 @@ reset_scale() {
}
if (best_size >= 0) {
int pixel_height = _face->get_face()->available_sizes[best_size].height;
int pixel_width = _face->get_face()->available_sizes[best_size].width;
error = FT_Set_Pixel_Sizes(_face->get_face(), pixel_width, pixel_height);
_pixel_height = face->available_sizes[best_size].height;
_pixel_width = face->available_sizes[best_size].width;
error = FT_Set_Pixel_Sizes(face, _pixel_width, _pixel_height);
if (!error) {
_font_pixels_per_unit = pixel_height * _points_per_unit / _point_size;
_font_pixels_per_unit = _pixel_height * _points_per_unit / _point_size;
_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.
@ -378,44 +360,26 @@ reset_scale() {
if (error) {
pnmtext_cat.warning()
<< "Unable to set " << get_name()
<< " to " << _point_size << "pt at " << dpi << " dpi.\n";
<< " to " << _point_size << "pt at " << _dpi << " dpi.\n";
_line_height = 1.0f;
_face->release_face(face);
return false;
}
_line_height = _face->get_face()->size->metrics.height / (_font_pixels_per_unit * 64.0f);
_line_height = face->size->metrics.height / (_font_pixels_per_unit * 64.0f);
// Determine the correct width for a space.
error = FT_Load_Char(_face->get_face(), ' ', FT_LOAD_DEFAULT);
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->get_face()->glyph->advance.x / (_font_pixels_per_unit * 64.0f);
_space_advance = face->glyph->advance.x / (_font_pixels_per_unit * 64.0f);
}
_face->release_face(face);
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

View File

@ -41,6 +41,7 @@
class EXPCL_PANDA_PNMTEXT FreetypeFont : public Namable {
protected:
FreetypeFont();
FreetypeFont(const FreetypeFont &copy);
bool load_font(const Filename &font_filename, int face_index);
bool load_font(const char *font_data, int data_length, int face_index);
@ -73,13 +74,14 @@ PUBLISHED:
INLINE static float get_points_per_inch();
protected:
bool load_glyph(int glyph_index, bool prerender = true);
INLINE FT_Face acquire_face() const;
INLINE void release_face(FT_Face face) const;
bool load_glyph(FT_Face face, int glyph_index, bool prerender = true);
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;
@ -95,19 +97,12 @@ protected:
float _space_advance;
PT(FreetypeFace) _face;
int _char_size;
int _dpi;
int _pixel_width;
int _pixel_height;
protected:
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;
};

View File

@ -43,6 +43,22 @@ PNMTextMaker(const char *font_data, int data_length, int face_index) {
_is_valid = load_font(font_data, data_length, face_index);
}
////////////////////////////////////////////////////////////////////
// Function: PNMTextMaker::Copy Constructor
// Access: Public
// Description:
////////////////////////////////////////////////////////////////////
PNMTextMaker::
PNMTextMaker(const PNMTextMaker &copy) :
FreetypeFont(copy),
_is_valid(copy._is_valid),
_align(copy._align),
_interior_flag(copy._interior_flag),
_fg(copy._fg),
_interior(copy._interior)
{
}
////////////////////////////////////////////////////////////////////
// Function: PNMTextMaker::Destructor
// Access: Public
@ -124,7 +140,9 @@ calc_width(const wstring &text) {
////////////////////////////////////////////////////////////////////
PNMTextGlyph *PNMTextMaker::
get_glyph(int character) {
int glyph_index = FT_Get_Char_Index(_face->get_face(), character);
FT_Face face = acquire_face();
int glyph_index = FT_Get_Char_Index(face, character);
release_face(face);
Glyphs::iterator gi;
gi = _glyphs.find(glyph_index);
@ -159,23 +177,25 @@ initialize() {
////////////////////////////////////////////////////////////////////
PNMTextGlyph *PNMTextMaker::
make_glyph(int glyph_index) {
if (!load_glyph(glyph_index)) {
FT_Face face = acquire_face();
if (!load_glyph(face, glyph_index)) {
release_face(face);
return (PNMTextGlyph *)NULL;
}
FT_GlyphSlot slot = _face->get_face()->glyph;
FT_GlyphSlot slot = face->glyph;
FT_Bitmap &bitmap = slot->bitmap;
double advance = slot->advance.x / 64.0;
PNMTextGlyph *glyph = new PNMTextGlyph(advance);
if (bitmap.width == 0 || bitmap.rows == 0) {
// If we got an empty bitmap, it's a special case.
PNMTextGlyph *glyph = new PNMTextGlyph(advance);
glyph->rescale(_scale_factor);
return glyph;
} else {
PNMTextGlyph *glyph = new PNMTextGlyph(advance);
PNMImage &glyph_image = glyph->_image;
glyph_image.clear(bitmap.width, bitmap.rows, 3);
copy_bitmap_to_pnmimage(bitmap, glyph_image);
@ -187,8 +207,10 @@ make_glyph(int glyph_index) {
glyph->determine_interior();
}
glyph->rescale(_scale_factor);
return glyph;
}
release_face(face);
return glyph;
}
////////////////////////////////////////////////////////////////////

View File

@ -40,6 +40,7 @@ class EXPCL_PANDA_PNMTEXT PNMTextMaker : public FreetypeFont {
PUBLISHED:
PNMTextMaker(const Filename &font_filename, int face_index);
PNMTextMaker(const char *font_data, int data_length, int face_index);
PNMTextMaker(const PNMTextMaker &copy);
~PNMTextMaker();
enum Alignment {

View File

@ -99,6 +99,36 @@ DynamicTextFont(const char *font_data, int data_length, int face_index) {
_needs_image_processing = false;
}
////////////////////////////////////////////////////////////////////
// Function: DynamicTextFont::Copy Constructor
// Access: Published
// Description:
////////////////////////////////////////////////////////////////////
DynamicTextFont::
DynamicTextFont(const DynamicTextFont &copy) :
TextFont(copy),
FreetypeFont(copy),
_texture_margin(copy._texture_margin),
_poly_margin(copy._poly_margin),
_page_x_size(copy._page_x_size),
_page_y_size(copy._page_y_size),
_minfilter(copy._minfilter),
_magfilter(copy._magfilter),
_anisotropic_degree(copy._anisotropic_degree),
_render_mode(copy._render_mode),
_winding_order(copy._winding_order),
_fg(copy._fg),
_bg(copy._bg),
_outline_color(copy._outline_color),
_outline_width(copy._outline_width),
_outline_feather(copy._outline_feather),
_has_outline(copy._has_outline),
_tex_format(copy._tex_format),
_needs_image_processing(copy._needs_image_processing),
_preferred_page(0)
{
}
////////////////////////////////////////////////////////////////////
// Function: DynamicTextFont::Destructor
// Access: Published, Virtual
@ -108,6 +138,16 @@ DynamicTextFont::
~DynamicTextFont() {
}
////////////////////////////////////////////////////////////////////
// Function: DynamicTextFont::make_copy
// Access: Published
// Description: Returns a new copy of the same font.
////////////////////////////////////////////////////////////////////
PT(TextFont) DynamicTextFont::
make_copy() const {
return new DynamicTextFont(*this);
}
////////////////////////////////////////////////////////////////////
// Function: DynamicTextFont::get_num_pages
// Access: Published
@ -216,8 +256,9 @@ write(ostream &out, int indent_level) const {
indent(out, indent_level + 2)
<< glyph_index;
if (FT_HAS_GLYPH_NAMES(_face->get_face())) {
int error = FT_Get_Glyph_Name(_face->get_face(), glyph_index,
FT_Face face = acquire_face();
if (FT_HAS_GLYPH_NAMES(face)) {
int error = FT_Get_Glyph_Name(face, glyph_index,
glyph_name, max_glyph_name);
// Some fonts, notably MS Mincho, claim to have glyph names but
@ -226,6 +267,7 @@ write(ostream &out, int indent_level) const {
out << " (" << glyph_name << ")";
}
}
release_face(face);
out << ", count = " << glyph->_geom_count << "\n";
}
@ -249,7 +291,8 @@ get_glyph(int character, const TextGlyph *&glyph) {
return false;
}
int glyph_index = FT_Get_Char_Index(_face->get_face(), character);
FT_Face face = acquire_face();
int glyph_index = FT_Get_Char_Index(face, character);
if (text_cat.is_spam()) {
text_cat.spam()
<< *this << " maps " << character << " to glyph " << glyph_index << "\n";
@ -259,7 +302,7 @@ get_glyph(int character, const TextGlyph *&glyph) {
if (ci != _cache.end()) {
glyph = (*ci).second;
} else {
DynamicTextGlyph *dynamic_glyph = make_glyph(character, glyph_index);
DynamicTextGlyph *dynamic_glyph = make_glyph(character, face, glyph_index);
_cache.insert(Cache::value_type(glyph_index, dynamic_glyph));
glyph = dynamic_glyph;
}
@ -269,6 +312,7 @@ get_glyph(int character, const TextGlyph *&glyph) {
glyph_index = 0;
}
release_face(face);
return (glyph_index != 0);
}
@ -399,12 +443,12 @@ determine_tex_format() {
// glyph cannot be created for some reason.
////////////////////////////////////////////////////////////////////
DynamicTextGlyph *DynamicTextFont::
make_glyph(int character, int glyph_index) {
if (!load_glyph(glyph_index, false)) {
make_glyph(int character, FT_Face face, int glyph_index) {
if (!load_glyph(face, glyph_index, false)) {
return (DynamicTextGlyph *)NULL;
}
FT_GlyphSlot slot = _face->get_face()->glyph;
FT_GlyphSlot slot = face->glyph;
FT_Bitmap &bitmap = slot->bitmap;
if ((bitmap.width == 0 || bitmap.rows == 0) && (glyph_index == 0)) {
@ -423,7 +467,7 @@ make_glyph(int character, int glyph_index) {
// Re-stroke the glyph to make it an outline glyph.
/*
FT_Stroker stroker;
FT_Stroker_New(_face->get_face()->memory, &stroker);
FT_Stroker_New(face->memory, &stroker);
FT_Stroker_Set(stroker, 16 * 16, FT_STROKER_LINECAP_BUTT,
FT_STROKER_LINEJOIN_ROUND, 0);

View File

@ -44,8 +44,11 @@ class EXPCL_PANDA_TEXT 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);
DynamicTextFont(const DynamicTextFont &copy);
virtual ~DynamicTextFont();
virtual PT(TextFont) make_copy() const;
INLINE const string &get_name() const;
INLINE bool set_point_size(float point_size);
@ -113,7 +116,7 @@ private:
void initialize();
void update_filters();
void determine_tex_format();
DynamicTextGlyph *make_glyph(int character, int glyph_index);
DynamicTextGlyph *make_glyph(int character, FT_Face face, int glyph_index);
void copy_bitmap_to_texture(const FT_Bitmap &bitmap, DynamicTextGlyph *glyph);
void copy_pnmimage_to_texture(const PNMImage &image, DynamicTextGlyph *glyph);
void blend_pnmimage_to_texture(const PNMImage &image, DynamicTextGlyph *glyph,

View File

@ -74,6 +74,16 @@ StaticTextFont(PandaNode *font_def) {
set_name(font_def->get_name());
}
////////////////////////////////////////////////////////////////////
// Function: StaticTextFont::make_copy
// Access: Published
// Description: Returns a new copy of the same font.
////////////////////////////////////////////////////////////////////
PT(TextFont) StaticTextFont::
make_copy() const {
return new StaticTextFont(_font);
}
////////////////////////////////////////////////////////////////////
// Function: StaticTextFont::write
// Access: Published, Virtual

View File

@ -41,6 +41,8 @@ class EXPCL_PANDA_TEXT StaticTextFont : public TextFont {
PUBLISHED:
StaticTextFont(PandaNode *font_def);
virtual PT(TextFont) make_copy() const;
virtual void write(ostream &out, int indent_level) const;
public:

View File

@ -36,6 +36,20 @@ TextFont() {
_space_advance = 0.25f;
}
////////////////////////////////////////////////////////////////////
// Function: TextFont::Copy Constructor
// Access: Public
// Description:
////////////////////////////////////////////////////////////////////
TextFont::
TextFont(const TextFont &copy) :
Namable(copy),
_is_valid(copy._is_valid),
_line_height(copy._line_height),
_space_advance(copy._space_advance)
{
}
////////////////////////////////////////////////////////////////////
// Function: TextFont::Destructor
// Access: Published, Virtual

View File

@ -36,6 +36,7 @@
class EXPCL_PANDA_TEXT TextFont : public TypedReferenceCount, public Namable {
public:
TextFont();
TextFont(const TextFont &copy);
PUBLISHED:
virtual ~TextFont();
@ -68,6 +69,7 @@ PUBLISHED:
WO_invalid,
};
virtual PT(TextFont) make_copy() const=0;
INLINE bool is_valid() const;
INLINE operator bool () const;