Use bitmap strikes as fallbacks for ftcr font backend
* src/ftfont.h (struct font_info): New member bitmap_strike_index. * src/ftfont.c (ftfont_open2): Try bitmap strikes as fallbacks. (ftfont_open): Discard bitmap strikes. * src/ftcrfont.c (ftcrfont_open): Recalculate metrics for bitmap strikes. (ftcrfont_get_bitmap, ftcrfont_anchor_point, ftcrfont_shape): New functions. (struct font_driver): Use them.
This commit is contained in:
parent
69771b4e6a
commit
d1dde7d04e
3 changed files with 137 additions and 11 deletions
100
src/ftcrfont.c
100
src/ftcrfont.c
|
@ -135,7 +135,10 @@ ftcrfont_open (struct frame *f, Lisp_Object entity, int pixel_size)
|
|||
font->driver = &ftcrfont_driver;
|
||||
FT_New_Size (ft_face, &ftcrfont_info->ft_size_draw);
|
||||
FT_Activate_Size (ftcrfont_info->ft_size_draw);
|
||||
FT_Set_Pixel_Sizes (ft_face, 0, font->pixel_size);
|
||||
if (ftcrfont_info->bitmap_strike_index < 0)
|
||||
FT_Set_Pixel_Sizes (ft_face, 0, font->pixel_size);
|
||||
else
|
||||
FT_Select_Size (ft_face, ftcrfont_info->bitmap_strike_index);
|
||||
cairo_font_face_t *font_face =
|
||||
cairo_ft_font_face_create_for_ft_face (ft_face, 0);
|
||||
cairo_matrix_t font_matrix, ctm;
|
||||
|
@ -148,6 +151,56 @@ ftcrfont_open (struct frame *f, Lisp_Object entity, int pixel_size)
|
|||
cairo_font_options_destroy (options);
|
||||
ftcrfont_info->metrics = NULL;
|
||||
ftcrfont_info->metrics_nrows = 0;
|
||||
if (ftcrfont_info->bitmap_strike_index >= 0)
|
||||
{
|
||||
/* Several members of struct font/font_info set by
|
||||
ftfont_open2 are bogus. Recalculate them with cairo
|
||||
scaled font functions. */
|
||||
cairo_font_extents_t extents;
|
||||
cairo_scaled_font_extents (ftcrfont_info->cr_scaled_font, &extents);
|
||||
font->ascent = lround (extents.ascent);
|
||||
font->descent = lround (extents.descent);
|
||||
font->height = lround (extents.height);
|
||||
|
||||
cairo_glyph_t stack_glyph;
|
||||
int n = 0;
|
||||
font->min_width = font->average_width = font->space_width = 0;
|
||||
for (char c = 32; c < 127; c++)
|
||||
{
|
||||
cairo_glyph_t *glyphs = &stack_glyph;
|
||||
int num_glyphs = 1;
|
||||
cairo_status_t status =
|
||||
cairo_scaled_font_text_to_glyphs (ftcrfont_info->cr_scaled_font,
|
||||
0, 0, &c, 1,
|
||||
&glyphs, &num_glyphs,
|
||||
NULL, NULL, NULL);
|
||||
|
||||
if (status == CAIRO_STATUS_SUCCESS)
|
||||
{
|
||||
if (glyphs != &stack_glyph)
|
||||
cairo_glyph_free (glyphs);
|
||||
else
|
||||
{
|
||||
int this_width =
|
||||
ftcrfont_glyph_extents (font, stack_glyph.index, NULL);
|
||||
|
||||
if (this_width > 0
|
||||
&& (! font->min_width
|
||||
|| font->min_width > this_width))
|
||||
font->min_width = this_width;
|
||||
if (c == 32)
|
||||
font->space_width = this_width;
|
||||
font->average_width += this_width;
|
||||
n++;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (n > 0)
|
||||
font->average_width /= n;
|
||||
|
||||
font->underline_position = -1;
|
||||
font->underline_thickness = 0;
|
||||
}
|
||||
}
|
||||
unblock_input ();
|
||||
|
||||
|
@ -210,6 +263,43 @@ ftcrfont_text_extents (struct font *font,
|
|||
metrics->width = width;
|
||||
}
|
||||
|
||||
static int
|
||||
ftcrfont_get_bitmap (struct font *font, unsigned int code,
|
||||
struct font_bitmap *bitmap, int bits_per_pixel)
|
||||
{
|
||||
struct font_info *ftcrfont_info = (struct font_info *) font;
|
||||
|
||||
if (ftcrfont_info->bitmap_strike_index < 0)
|
||||
return ftfont_get_bitmap (font, code, bitmap, bits_per_pixel);
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
static int
|
||||
ftcrfont_anchor_point (struct font *font, unsigned int code, int idx,
|
||||
int *x, int *y)
|
||||
{
|
||||
struct font_info *ftcrfont_info = (struct font_info *) font;
|
||||
|
||||
if (ftcrfont_info->bitmap_strike_index < 0)
|
||||
return ftfont_anchor_point (font, code, idx, x, y);
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
static Lisp_Object
|
||||
ftcrfont_shape (Lisp_Object lgstring)
|
||||
{
|
||||
#if defined HAVE_M17N_FLT && defined HAVE_LIBOTF
|
||||
struct font_info *ftcrfont_info = (struct font_info *) font;
|
||||
|
||||
if (ftcrfont_info->bitmap_strike_index < 0)
|
||||
return ftfont_shape (lgstring);
|
||||
#endif
|
||||
|
||||
return make_fixnum (0);
|
||||
}
|
||||
|
||||
static int
|
||||
ftcrfont_draw (struct glyph_string *s,
|
||||
int from, int to, int x, int y, bool with_background)
|
||||
|
@ -286,14 +376,12 @@ struct font_driver const ftcrfont_driver =
|
|||
.encode_char = ftfont_encode_char,
|
||||
.text_extents = ftcrfont_text_extents,
|
||||
.draw = ftcrfont_draw,
|
||||
.get_bitmap = ftfont_get_bitmap,
|
||||
.anchor_point = ftfont_anchor_point,
|
||||
.get_bitmap = ftcrfont_get_bitmap,
|
||||
.anchor_point = ftcrfont_anchor_point,
|
||||
#ifdef HAVE_LIBOTF
|
||||
.otf_capability = ftfont_otf_capability,
|
||||
#endif
|
||||
#if defined HAVE_M17N_FLT && defined HAVE_LIBOTF
|
||||
.shape = ftfont_shape,
|
||||
#endif
|
||||
.shape = ftcrfont_shape,
|
||||
#ifdef HAVE_OTF_GET_VARIATION_GLYPHS
|
||||
.get_variation_glyphs = ftfont_variation_glyphs,
|
||||
#endif
|
||||
|
|
44
src/ftfont.c
44
src/ftfont.c
|
@ -1097,6 +1097,7 @@ ftfont_open2 (struct frame *f,
|
|||
int spacing;
|
||||
int i;
|
||||
double upEM;
|
||||
FT_Int strike_index = -1;
|
||||
|
||||
val = assq_no_quit (QCfont_entity, AREF (entity, FONT_EXTRA_INDEX));
|
||||
if (! CONSP (val))
|
||||
|
@ -1126,12 +1127,32 @@ ftfont_open2 (struct frame *f,
|
|||
size = pixel_size;
|
||||
if (FT_Set_Pixel_Sizes (ft_face, size, size) != 0)
|
||||
{
|
||||
if (cache_data->face_refcount == 0)
|
||||
int min_distance = INT_MAX;
|
||||
bool magnify = true;
|
||||
|
||||
for (FT_Int i = 0; i < ft_face->num_fixed_sizes; i++)
|
||||
{
|
||||
FT_Done_Face (ft_face);
|
||||
cache_data->ft_face = NULL;
|
||||
int distance = ft_face->available_sizes[i].height - (int) size;
|
||||
|
||||
/* Prefer down-scaling to upscaling. */
|
||||
if (magnify == (distance < 0) ? abs (distance) <= min_distance
|
||||
: magnify)
|
||||
{
|
||||
magnify = distance < 0;
|
||||
min_distance = abs (distance);
|
||||
strike_index = i;
|
||||
}
|
||||
}
|
||||
|
||||
if (strike_index < 0 || FT_Select_Size (ft_face, strike_index) != 0)
|
||||
{
|
||||
if (cache_data->face_refcount == 0)
|
||||
{
|
||||
FT_Done_Face (ft_face);
|
||||
cache_data->ft_face = NULL;
|
||||
}
|
||||
return Qnil;
|
||||
}
|
||||
return Qnil;
|
||||
}
|
||||
cache_data->face_refcount++;
|
||||
|
||||
|
@ -1144,6 +1165,7 @@ ftfont_open2 (struct frame *f,
|
|||
ftfont_info->maybe_otf = (ft_face->face_flags & FT_FACE_FLAG_SFNT) != 0;
|
||||
ftfont_info->otf = NULL;
|
||||
#endif /* HAVE_LIBOTF */
|
||||
ftfont_info->bitmap_strike_index = strike_index;
|
||||
/* This means that there's no need of transformation. */
|
||||
ftfont_info->matrix.xx = 0;
|
||||
font->pixel_size = size;
|
||||
|
@ -1229,7 +1251,19 @@ ftfont_open (struct frame *f, Lisp_Object entity, int pixel_size)
|
|||
size = pixel_size;
|
||||
font_object = font_build_object (VECSIZE (struct font_info),
|
||||
Qfreetype, entity, size);
|
||||
return ftfont_open2 (f, entity, pixel_size, font_object);
|
||||
font_object = ftfont_open2 (f, entity, pixel_size, font_object);
|
||||
if (FONT_OBJECT_P (font_object))
|
||||
{
|
||||
struct font *font = XFONT_OBJECT (font_object);
|
||||
struct font_info *ftfont_info = (struct font_info *) font;
|
||||
|
||||
if (ftfont_info->bitmap_strike_index >= 0)
|
||||
{
|
||||
ftfont_close (font);
|
||||
font_object = Qnil;
|
||||
}
|
||||
}
|
||||
return font_object;
|
||||
}
|
||||
|
||||
void
|
||||
|
|
|
@ -54,6 +54,10 @@ struct font_info
|
|||
#endif /* HAVE_LIBOTF */
|
||||
FT_Size ft_size;
|
||||
int index;
|
||||
/* Index of the bitmap strike used as a fallback for
|
||||
FT_Set_Pixel_Sizes failure. If the value is non-negative, then
|
||||
ft_size is not of the requested size. Otherwise it is -1. */
|
||||
FT_Int bitmap_strike_index;
|
||||
FT_Matrix matrix;
|
||||
|
||||
#ifdef USE_CAIRO
|
||||
|
|
Loading…
Add table
Reference in a new issue