aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorYAMAMOTO Mitsuharu2019-04-20 12:43:45 +0900
committerYAMAMOTO Mitsuharu2019-04-20 12:43:45 +0900
commitd1dde7d04e5244179735592adc11d2a6f0af64ac (patch)
tree474c1999fd436600d77c20b41c8edab0b8929555 /src
parent69771b4e6acfe2998e4c3c30e07fb4600d42515d (diff)
downloademacs-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.c100
-rw-r--r--src/ftfont.c44
-rw-r--r--src/ftfont.h4
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
213static int 266static int
267ftcrfont_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
278static int
279ftcrfont_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
290static Lisp_Object
291ftcrfont_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
303static int
214ftcrfont_draw (struct glyph_string *s, 304ftcrfont_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
1235void 1269void
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