diff options
| author | YAMAMOTO Mitsuharu | 2019-04-20 12:43:45 +0900 |
|---|---|---|
| committer | YAMAMOTO Mitsuharu | 2019-04-20 12:43:45 +0900 |
| commit | d1dde7d04e5244179735592adc11d2a6f0af64ac (patch) | |
| tree | 474c1999fd436600d77c20b41c8edab0b8929555 /src | |
| parent | 69771b4e6acfe2998e4c3c30e07fb4600d42515d (diff) | |
| download | emacs-d1dde7d04e5244179735592adc11d2a6f0af64ac.tar.gz emacs-d1dde7d04e5244179735592adc11d2a6f0af64ac.zip | |
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.
Diffstat (limited to 'src')
| -rw-r--r-- | src/ftcrfont.c | 100 | ||||
| -rw-r--r-- | src/ftfont.c | 44 | ||||
| -rw-r--r-- | src/ftfont.h | 4 |
3 files changed, 137 insertions, 11 deletions
diff --git a/src/ftcrfont.c b/src/ftcrfont.c index 4845ee4cf3d..e341c409b1e 100644 --- a/src/ftcrfont.c +++ b/src/ftcrfont.c | |||
| @@ -135,7 +135,10 @@ ftcrfont_open (struct frame *f, Lisp_Object entity, int pixel_size) | |||
| 135 | font->driver = &ftcrfont_driver; | 135 | font->driver = &ftcrfont_driver; |
| 136 | FT_New_Size (ft_face, &ftcrfont_info->ft_size_draw); | 136 | FT_New_Size (ft_face, &ftcrfont_info->ft_size_draw); |
| 137 | FT_Activate_Size (ftcrfont_info->ft_size_draw); | 137 | FT_Activate_Size (ftcrfont_info->ft_size_draw); |
| 138 | FT_Set_Pixel_Sizes (ft_face, 0, font->pixel_size); | 138 | if (ftcrfont_info->bitmap_strike_index < 0) |
| 139 | FT_Set_Pixel_Sizes (ft_face, 0, font->pixel_size); | ||
| 140 | else | ||
| 141 | FT_Select_Size (ft_face, ftcrfont_info->bitmap_strike_index); | ||
| 139 | cairo_font_face_t *font_face = | 142 | cairo_font_face_t *font_face = |
| 140 | cairo_ft_font_face_create_for_ft_face (ft_face, 0); | 143 | cairo_ft_font_face_create_for_ft_face (ft_face, 0); |
| 141 | cairo_matrix_t font_matrix, ctm; | 144 | cairo_matrix_t font_matrix, ctm; |
| @@ -148,6 +151,56 @@ ftcrfont_open (struct frame *f, Lisp_Object entity, int pixel_size) | |||
| 148 | cairo_font_options_destroy (options); | 151 | cairo_font_options_destroy (options); |
| 149 | ftcrfont_info->metrics = NULL; | 152 | ftcrfont_info->metrics = NULL; |
| 150 | ftcrfont_info->metrics_nrows = 0; | 153 | ftcrfont_info->metrics_nrows = 0; |
| 154 | if (ftcrfont_info->bitmap_strike_index >= 0) | ||
| 155 | { | ||
| 156 | /* Several members of struct font/font_info set by | ||
| 157 | ftfont_open2 are bogus. Recalculate them with cairo | ||
| 158 | scaled font functions. */ | ||
| 159 | cairo_font_extents_t extents; | ||
| 160 | cairo_scaled_font_extents (ftcrfont_info->cr_scaled_font, &extents); | ||
| 161 | font->ascent = lround (extents.ascent); | ||
| 162 | font->descent = lround (extents.descent); | ||
| 163 | font->height = lround (extents.height); | ||
| 164 | |||
| 165 | cairo_glyph_t stack_glyph; | ||
| 166 | int n = 0; | ||
| 167 | font->min_width = font->average_width = font->space_width = 0; | ||
| 168 | for (char c = 32; c < 127; c++) | ||
| 169 | { | ||
| 170 | cairo_glyph_t *glyphs = &stack_glyph; | ||
| 171 | int num_glyphs = 1; | ||
| 172 | cairo_status_t status = | ||
| 173 | cairo_scaled_font_text_to_glyphs (ftcrfont_info->cr_scaled_font, | ||
| 174 | 0, 0, &c, 1, | ||
| 175 | &glyphs, &num_glyphs, | ||
| 176 | NULL, NULL, NULL); | ||
| 177 | |||
| 178 | if (status == CAIRO_STATUS_SUCCESS) | ||
| 179 | { | ||
| 180 | if (glyphs != &stack_glyph) | ||
| 181 | cairo_glyph_free (glyphs); | ||
| 182 | else | ||
| 183 | { | ||
| 184 | int this_width = | ||
| 185 | ftcrfont_glyph_extents (font, stack_glyph.index, NULL); | ||
| 186 | |||
| 187 | if (this_width > 0 | ||
| 188 | && (! font->min_width | ||
| 189 | || font->min_width > this_width)) | ||
| 190 | font->min_width = this_width; | ||
| 191 | if (c == 32) | ||
| 192 | font->space_width = this_width; | ||
| 193 | font->average_width += this_width; | ||
| 194 | n++; | ||
| 195 | } | ||
| 196 | } | ||
| 197 | } | ||
| 198 | if (n > 0) | ||
| 199 | font->average_width /= n; | ||
| 200 | |||
| 201 | font->underline_position = -1; | ||
| 202 | font->underline_thickness = 0; | ||
| 203 | } | ||
| 151 | } | 204 | } |
| 152 | unblock_input (); | 205 | unblock_input (); |
| 153 | 206 | ||
| @@ -211,6 +264,43 @@ ftcrfont_text_extents (struct font *font, | |||
| 211 | } | 264 | } |
| 212 | 265 | ||
| 213 | static int | 266 | static int |
| 267 | ftcrfont_get_bitmap (struct font *font, unsigned int code, | ||
| 268 | struct font_bitmap *bitmap, int bits_per_pixel) | ||
| 269 | { | ||
| 270 | struct font_info *ftcrfont_info = (struct font_info *) font; | ||
| 271 | |||
| 272 | if (ftcrfont_info->bitmap_strike_index < 0) | ||
| 273 | return ftfont_get_bitmap (font, code, bitmap, bits_per_pixel); | ||
| 274 | |||
| 275 | return -1; | ||
| 276 | } | ||
| 277 | |||
| 278 | static int | ||
| 279 | ftcrfont_anchor_point (struct font *font, unsigned int code, int idx, | ||
| 280 | int *x, int *y) | ||
| 281 | { | ||
| 282 | struct font_info *ftcrfont_info = (struct font_info *) font; | ||
| 283 | |||
| 284 | if (ftcrfont_info->bitmap_strike_index < 0) | ||
| 285 | return ftfont_anchor_point (font, code, idx, x, y); | ||
| 286 | |||
| 287 | return -1; | ||
| 288 | } | ||
| 289 | |||
| 290 | static Lisp_Object | ||
| 291 | ftcrfont_shape (Lisp_Object lgstring) | ||
| 292 | { | ||
| 293 | #if defined HAVE_M17N_FLT && defined HAVE_LIBOTF | ||
| 294 | struct font_info *ftcrfont_info = (struct font_info *) font; | ||
| 295 | |||
| 296 | if (ftcrfont_info->bitmap_strike_index < 0) | ||
| 297 | return ftfont_shape (lgstring); | ||
| 298 | #endif | ||
| 299 | |||
| 300 | return make_fixnum (0); | ||
| 301 | } | ||
| 302 | |||
| 303 | static int | ||
| 214 | ftcrfont_draw (struct glyph_string *s, | 304 | ftcrfont_draw (struct glyph_string *s, |
| 215 | int from, int to, int x, int y, bool with_background) | 305 | int from, int to, int x, int y, bool with_background) |
| 216 | { | 306 | { |
| @@ -286,14 +376,12 @@ struct font_driver const ftcrfont_driver = | |||
| 286 | .encode_char = ftfont_encode_char, | 376 | .encode_char = ftfont_encode_char, |
| 287 | .text_extents = ftcrfont_text_extents, | 377 | .text_extents = ftcrfont_text_extents, |
| 288 | .draw = ftcrfont_draw, | 378 | .draw = ftcrfont_draw, |
| 289 | .get_bitmap = ftfont_get_bitmap, | 379 | .get_bitmap = ftcrfont_get_bitmap, |
| 290 | .anchor_point = ftfont_anchor_point, | 380 | .anchor_point = ftcrfont_anchor_point, |
| 291 | #ifdef HAVE_LIBOTF | 381 | #ifdef HAVE_LIBOTF |
| 292 | .otf_capability = ftfont_otf_capability, | 382 | .otf_capability = ftfont_otf_capability, |
| 293 | #endif | 383 | #endif |
| 294 | #if defined HAVE_M17N_FLT && defined HAVE_LIBOTF | 384 | .shape = ftcrfont_shape, |
| 295 | .shape = ftfont_shape, | ||
| 296 | #endif | ||
| 297 | #ifdef HAVE_OTF_GET_VARIATION_GLYPHS | 385 | #ifdef HAVE_OTF_GET_VARIATION_GLYPHS |
| 298 | .get_variation_glyphs = ftfont_variation_glyphs, | 386 | .get_variation_glyphs = ftfont_variation_glyphs, |
| 299 | #endif | 387 | #endif |
diff --git a/src/ftfont.c b/src/ftfont.c index 3e820f583ff..d0078a37701 100644 --- a/src/ftfont.c +++ b/src/ftfont.c | |||
| @@ -1097,6 +1097,7 @@ ftfont_open2 (struct frame *f, | |||
| 1097 | int spacing; | 1097 | int spacing; |
| 1098 | int i; | 1098 | int i; |
| 1099 | double upEM; | 1099 | double upEM; |
| 1100 | FT_Int strike_index = -1; | ||
| 1100 | 1101 | ||
| 1101 | val = assq_no_quit (QCfont_entity, AREF (entity, FONT_EXTRA_INDEX)); | 1102 | val = assq_no_quit (QCfont_entity, AREF (entity, FONT_EXTRA_INDEX)); |
| 1102 | if (! CONSP (val)) | 1103 | if (! CONSP (val)) |
| @@ -1126,12 +1127,32 @@ ftfont_open2 (struct frame *f, | |||
| 1126 | size = pixel_size; | 1127 | size = pixel_size; |
| 1127 | if (FT_Set_Pixel_Sizes (ft_face, size, size) != 0) | 1128 | if (FT_Set_Pixel_Sizes (ft_face, size, size) != 0) |
| 1128 | { | 1129 | { |
| 1129 | if (cache_data->face_refcount == 0) | 1130 | int min_distance = INT_MAX; |
| 1131 | bool magnify = true; | ||
| 1132 | |||
| 1133 | for (FT_Int i = 0; i < ft_face->num_fixed_sizes; i++) | ||
| 1130 | { | 1134 | { |
| 1131 | FT_Done_Face (ft_face); | 1135 | int distance = ft_face->available_sizes[i].height - (int) size; |
| 1132 | cache_data->ft_face = NULL; | 1136 | |
| 1137 | /* Prefer down-scaling to upscaling. */ | ||
| 1138 | if (magnify == (distance < 0) ? abs (distance) <= min_distance | ||
| 1139 | : magnify) | ||
| 1140 | { | ||
| 1141 | magnify = distance < 0; | ||
| 1142 | min_distance = abs (distance); | ||
| 1143 | strike_index = i; | ||
| 1144 | } | ||
| 1145 | } | ||
| 1146 | |||
| 1147 | if (strike_index < 0 || FT_Select_Size (ft_face, strike_index) != 0) | ||
| 1148 | { | ||
| 1149 | if (cache_data->face_refcount == 0) | ||
| 1150 | { | ||
| 1151 | FT_Done_Face (ft_face); | ||
| 1152 | cache_data->ft_face = NULL; | ||
| 1153 | } | ||
| 1154 | return Qnil; | ||
| 1133 | } | 1155 | } |
| 1134 | return Qnil; | ||
| 1135 | } | 1156 | } |
| 1136 | cache_data->face_refcount++; | 1157 | cache_data->face_refcount++; |
| 1137 | 1158 | ||
| @@ -1144,6 +1165,7 @@ ftfont_open2 (struct frame *f, | |||
| 1144 | ftfont_info->maybe_otf = (ft_face->face_flags & FT_FACE_FLAG_SFNT) != 0; | 1165 | ftfont_info->maybe_otf = (ft_face->face_flags & FT_FACE_FLAG_SFNT) != 0; |
| 1145 | ftfont_info->otf = NULL; | 1166 | ftfont_info->otf = NULL; |
| 1146 | #endif /* HAVE_LIBOTF */ | 1167 | #endif /* HAVE_LIBOTF */ |
| 1168 | ftfont_info->bitmap_strike_index = strike_index; | ||
| 1147 | /* This means that there's no need of transformation. */ | 1169 | /* This means that there's no need of transformation. */ |
| 1148 | ftfont_info->matrix.xx = 0; | 1170 | ftfont_info->matrix.xx = 0; |
| 1149 | font->pixel_size = size; | 1171 | font->pixel_size = size; |
| @@ -1229,7 +1251,19 @@ ftfont_open (struct frame *f, Lisp_Object entity, int pixel_size) | |||
| 1229 | size = pixel_size; | 1251 | size = pixel_size; |
| 1230 | font_object = font_build_object (VECSIZE (struct font_info), | 1252 | font_object = font_build_object (VECSIZE (struct font_info), |
| 1231 | Qfreetype, entity, size); | 1253 | Qfreetype, entity, size); |
| 1232 | return ftfont_open2 (f, entity, pixel_size, font_object); | 1254 | font_object = ftfont_open2 (f, entity, pixel_size, font_object); |
| 1255 | if (FONT_OBJECT_P (font_object)) | ||
| 1256 | { | ||
| 1257 | struct font *font = XFONT_OBJECT (font_object); | ||
| 1258 | struct font_info *ftfont_info = (struct font_info *) font; | ||
| 1259 | |||
| 1260 | if (ftfont_info->bitmap_strike_index >= 0) | ||
| 1261 | { | ||
| 1262 | ftfont_close (font); | ||
| 1263 | font_object = Qnil; | ||
| 1264 | } | ||
| 1265 | } | ||
| 1266 | return font_object; | ||
| 1233 | } | 1267 | } |
| 1234 | 1268 | ||
| 1235 | void | 1269 | void |
diff --git a/src/ftfont.h b/src/ftfont.h index 327cd085acf..adbda49ff1c 100644 --- a/src/ftfont.h +++ b/src/ftfont.h | |||
| @@ -54,6 +54,10 @@ struct font_info | |||
| 54 | #endif /* HAVE_LIBOTF */ | 54 | #endif /* HAVE_LIBOTF */ |
| 55 | FT_Size ft_size; | 55 | FT_Size ft_size; |
| 56 | int index; | 56 | int index; |
| 57 | /* Index of the bitmap strike used as a fallback for | ||
| 58 | FT_Set_Pixel_Sizes failure. If the value is non-negative, then | ||
| 59 | ft_size is not of the requested size. Otherwise it is -1. */ | ||
| 60 | FT_Int bitmap_strike_index; | ||
| 57 | FT_Matrix matrix; | 61 | FT_Matrix matrix; |
| 58 | 62 | ||
| 59 | #ifdef USE_CAIRO | 63 | #ifdef USE_CAIRO |