support non-scalable fonts
This commit is contained in:
parent
235cd02cb7
commit
d70a1f25cb
|
|
@ -98,6 +98,7 @@ DynamicTextFont(const Filename &font_filename, int face_index) {
|
|||
}
|
||||
set_name(name);
|
||||
|
||||
/*
|
||||
if (!FT_IS_SCALABLE(_face)) {
|
||||
text_cat.error()
|
||||
<< "Unable to read font " << get_name()
|
||||
|
|
@ -106,7 +107,7 @@ DynamicTextFont(const Filename &font_filename, int face_index) {
|
|||
// haven't bothered to write the few lines of glue code that
|
||||
// would do it.
|
||||
|
||||
} else {
|
||||
} else */ {
|
||||
text_cat.info()
|
||||
<< "Loaded font " << get_name() << "\n";
|
||||
_is_valid = true;
|
||||
|
|
@ -298,6 +299,37 @@ reset_scale() {
|
|||
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)(_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";
|
||||
|
||||
_pixels_per_unit = pixel_height * points_per_unit / _point_size;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (error) {
|
||||
text_cat.warning()
|
||||
<< "Unable to set " << get_name()
|
||||
|
|
@ -306,11 +338,7 @@ reset_scale() {
|
|||
return false;
|
||||
}
|
||||
|
||||
// The face's height is only relevant for scalable fonts,
|
||||
// according to FreeType. How should we determine whether we
|
||||
// have a scalable font or otherwise?
|
||||
float pixel_size = _point_size * (_pixels_per_unit / points_per_unit);
|
||||
_line_height = (float)_face->height * pixel_size / ((float)_face->units_per_EM * 64.0f);
|
||||
_line_height = _face->size->metrics.height / (_pixels_per_unit * 64.0f);
|
||||
|
||||
// Determine the correct width for a space.
|
||||
error = FT_Load_Char(_face, ' ', FT_LOAD_DEFAULT);
|
||||
|
|
@ -354,29 +382,64 @@ make_glyph(int glyph_index) {
|
|||
return glyph;
|
||||
|
||||
} else {
|
||||
if (bitmap.pixel_mode != ft_pixel_mode_grays) {
|
||||
DynamicTextGlyph *glyph = slot_glyph(bitmap.width, bitmap.rows);
|
||||
|
||||
if (bitmap.pixel_mode == ft_pixel_mode_grays && bitmap.num_grays == 256) {
|
||||
// This is the easy case: we can memcpy the rendered glyph
|
||||
// directly into our texture image, one row at a time.
|
||||
unsigned char *buffer_row = bitmap.buffer;
|
||||
for (int yi = 0; yi < bitmap.rows; yi++) {
|
||||
unsigned char *texture_row = glyph->get_row(yi);
|
||||
nassertr(texture_row != (unsigned char *)NULL, (DynamicTextGlyph *)NULL);
|
||||
memcpy(texture_row, buffer_row, bitmap.width);
|
||||
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 texture.
|
||||
unsigned char *buffer_row = bitmap.buffer;
|
||||
for (int yi = 0; yi < bitmap.rows; yi++) {
|
||||
unsigned char *texture_row = glyph->get_row(yi);
|
||||
nassertr(texture_row != (unsigned char *)NULL, (DynamicTextGlyph *)NULL);
|
||||
|
||||
int bit = 0x80;
|
||||
unsigned char *b = buffer_row;
|
||||
for (int xi = 0; xi < bitmap.width; xi++) {
|
||||
if (*b & bit) {
|
||||
texture_row[xi] = 0xff;
|
||||
} else {
|
||||
texture_row[xi] = 0x00;
|
||||
}
|
||||
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++) {
|
||||
unsigned char *texture_row = glyph->get_row(yi);
|
||||
nassertr(texture_row != (unsigned char *)NULL, (DynamicTextGlyph *)NULL);
|
||||
for (int xi = 0; xi < bitmap.width; xi++) {
|
||||
texture_row[xi] = (int)(buffer_row[xi] * 255) / (bitmap.num_grays - 1);
|
||||
}
|
||||
buffer_row += bitmap.pitch;
|
||||
}
|
||||
|
||||
} else {
|
||||
text_cat.error()
|
||||
<< "Unexpected pixel mode in bitmap: " << (int)bitmap.pixel_mode << "\n";
|
||||
return (DynamicTextGlyph *)NULL;
|
||||
}
|
||||
|
||||
if (bitmap.num_grays != 256) {
|
||||
// We expect 256 levels of grayscale to come back from FreeType,
|
||||
// since that's what we asked for.
|
||||
text_cat.warning()
|
||||
<< "Expected 256 levels of gray, got " << bitmap.num_grays << "\n";
|
||||
}
|
||||
|
||||
DynamicTextGlyph *glyph = slot_glyph(bitmap.width, bitmap.rows);
|
||||
|
||||
// Now copy the rendered glyph into the texture.
|
||||
unsigned char *buffer_row = bitmap.buffer;
|
||||
for (int yi = 0; yi < bitmap.rows; yi++) {
|
||||
unsigned char *texture_row = glyph->get_row(yi);
|
||||
nassertr(texture_row != (unsigned char *)NULL, (DynamicTextGlyph *)NULL);
|
||||
memcpy(texture_row, buffer_row, bitmap.width);
|
||||
buffer_row += bitmap.pitch;
|
||||
}
|
||||
|
||||
glyph->_page->mark_dirty(Texture::DF_image);
|
||||
|
||||
glyph->make_geom(slot->bitmap_top, slot->bitmap_left, advance,
|
||||
|
|
|
|||
Loading…
Reference in New Issue