mirror of
https://github.com/panda3d/panda3d.git
synced 2025-10-04 02:42:49 -04:00
TextFont::make_copy()
This commit is contained in:
parent
62889f3fa6
commit
6a7580ca45
@ -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 \
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
};
|
||||
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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 ©) :
|
||||
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
|
||||
|
@ -41,6 +41,7 @@
|
||||
class EXPCL_PANDA_PNMTEXT FreetypeFont : public Namable {
|
||||
protected:
|
||||
FreetypeFont();
|
||||
FreetypeFont(const FreetypeFont ©);
|
||||
|
||||
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;
|
||||
};
|
||||
|
@ -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 ©) :
|
||||
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;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
@ -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 ©);
|
||||
~PNMTextMaker();
|
||||
|
||||
enum Alignment {
|
||||
|
@ -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 ©) :
|
||||
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);
|
||||
|
||||
|
@ -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 ©);
|
||||
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,
|
||||
|
@ -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
|
||||
|
@ -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:
|
||||
|
@ -36,6 +36,20 @@ TextFont() {
|
||||
_space_advance = 0.25f;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: TextFont::Copy Constructor
|
||||
// Access: Public
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
TextFont::
|
||||
TextFont(const TextFont ©) :
|
||||
Namable(copy),
|
||||
_is_valid(copy._is_valid),
|
||||
_line_height(copy._line_height),
|
||||
_space_advance(copy._space_advance)
|
||||
{
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: TextFont::Destructor
|
||||
// Access: Published, Virtual
|
||||
|
@ -36,6 +36,7 @@
|
||||
class EXPCL_PANDA_TEXT TextFont : public TypedReferenceCount, public Namable {
|
||||
public:
|
||||
TextFont();
|
||||
TextFont(const TextFont ©);
|
||||
|
||||
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;
|
||||
|
Loading…
x
Reference in New Issue
Block a user