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;
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 ();
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)
.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
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))
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++;
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;
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