diff options
| author | YAMAMOTO Mitsuharu | 2019-05-23 10:30:59 +0900 |
|---|---|---|
| committer | YAMAMOTO Mitsuharu | 2019-05-23 10:30:59 +0900 |
| commit | 03feb9376b54c489e24478954a11061e9b0d6db7 (patch) | |
| tree | 3e20c6c3295c24d0d4053a68062bcc7e9c49a224 /src | |
| parent | 72047556fa391016ab507c02c2f489c97b53f088 (diff) | |
| download | emacs-03feb9376b54c489e24478954a11061e9b0d6db7.tar.gz emacs-03feb9376b54c489e24478954a11061e9b0d6db7.zip | |
Make Cairo build obey hint-style font setting (Bug#35781)
* src/ftfont.h (ftfont_open2): Remove extern.
(ftfont_fix_match, ftfont_add_rendering_parameters)
(ftfont_entity_pattern): Add externs.
(struct font_info): Remove member bitmap_strike_index.
(struct font_info) [USE_CAIRO]: Remove member ft_size_draw. All uses removed.
Add member bitmap_position_unit.
* src/xftfont.c (xftfont_fix_match, xftfont_add_rendering_parameters): Move
functions from here ...
* src/ftfont.c (ftfont_fix_match, ftfont_add_rendering_parameters): ... to
here. All uses changed.
* src/xftfont.c (xftfont_open): Extract FcPattern creation from font entity
from here ...
* src/ftfont.c (ftfont_entity_pattern): ... to here.
* src/xftfont.c (syms_of_xftfont): Move DEFSYMs for Fontconfig's rendering
parameters from here ...
* src/ftfont.c (syms_of_ftfont): ... to here.
* src/ftfont.c (ftfont_open, ftfont_open2): Undo introduction of
bitmap_strike_index. Merge functions into ftfont_open.
* src/ftcrfont.c (ftcrfont_open): Align code with xftfont_open rather than
ftfont_open.
(ftcrfont_close): Likewise.
(ftcrfont_has_char, ftcrfont_encode_char):
(ftcrfont_otf_capability) [HAVE_LIBOTF]:
(ftcrfont_variation_glyphs) [HAVE_OTF_GET_VARIATION_GLYPHS]: New functions.
(ftcrfont_driver): Register them.
(ftcrfont_get_bitmap, ftcrfont_anchor_point):
(ftcrfont_shape) [HAVE_M17N_FLT && HAVE_LIBOTF]: Use bitmap_position_unit
instead of bitmap_strike_index to screen bitmap fonts.
(ftcrfont_get_bitmap, ftcrfont_anchor_point):
(ftcrfont_otf_capability) [HAVE_LIBOTF]:
(ftcrfont_shape) [HAVE_M17N_FLT && HAVE_LIBOTF]:
(ftcrfont_variation_glyphs) [HAVE_OTF_GET_VARIATION_GLYPHS]: Temporarily
assign ftcrfont_info->ft_size and call corresponding ftfont functions.
(ftcrfont_draw): Don't flush cairo surface when exporting.
Diffstat (limited to 'src')
| -rw-r--r-- | src/ftcrfont.c | 370 | ||||
| -rw-r--r-- | src/ftfont.c | 222 | ||||
| -rw-r--r-- | src/ftfont.h | 18 | ||||
| -rw-r--r-- | src/xftfont.c | 151 |
4 files changed, 433 insertions, 328 deletions
diff --git a/src/ftcrfont.c b/src/ftcrfont.c index 2d5a7665578..9686cec0e8c 100644 --- a/src/ftcrfont.c +++ b/src/ftcrfont.c | |||
| @@ -79,7 +79,6 @@ ftcrfont_glyph_extents (struct font *font, | |||
| 79 | cairo_glyph_t cr_glyph = {.index = glyph}; | 79 | cairo_glyph_t cr_glyph = {.index = glyph}; |
| 80 | cairo_text_extents_t extents; | 80 | cairo_text_extents_t extents; |
| 81 | 81 | ||
| 82 | FT_Activate_Size (ftcrfont_info->ft_size_draw); | ||
| 83 | cairo_scaled_font_glyph_extents (ftcrfont_info->cr_scaled_font, | 82 | cairo_scaled_font_glyph_extents (ftcrfont_info->cr_scaled_font, |
| 84 | &cr_glyph, 1, &extents); | 83 | &cr_glyph, 1, &extents); |
| 85 | cache->lbearing = floor (extents.x_bearing); | 84 | cache->lbearing = floor (extents.x_bearing); |
| @@ -118,103 +117,159 @@ ftcrfont_match (struct frame *f, Lisp_Object spec) | |||
| 118 | static Lisp_Object | 117 | static Lisp_Object |
| 119 | ftcrfont_open (struct frame *f, Lisp_Object entity, int pixel_size) | 118 | ftcrfont_open (struct frame *f, Lisp_Object entity, int pixel_size) |
| 120 | { | 119 | { |
| 121 | Lisp_Object font_object; | 120 | FcResult result; |
| 122 | 121 | Lisp_Object val, filename, font_object; | |
| 123 | FT_UInt size = XFIXNUM (AREF (entity, FONT_SIZE_INDEX)); | 122 | FcPattern *pat, *match; |
| 123 | struct font_info *ftcrfont_info; | ||
| 124 | struct font *font; | ||
| 125 | double size = 0; | ||
| 126 | cairo_font_face_t *font_face; | ||
| 127 | cairo_font_extents_t extents; | ||
| 128 | FT_Face ft_face; | ||
| 129 | FcMatrix *matrix; | ||
| 130 | |||
| 131 | val = assq_no_quit (QCfont_entity, AREF (entity, FONT_EXTRA_INDEX)); | ||
| 132 | if (! CONSP (val)) | ||
| 133 | return Qnil; | ||
| 134 | val = XCDR (val); | ||
| 135 | filename = XCAR (val); | ||
| 136 | size = XFIXNUM (AREF (entity, FONT_SIZE_INDEX)); | ||
| 124 | if (size == 0) | 137 | if (size == 0) |
| 125 | size = pixel_size; | 138 | size = pixel_size; |
| 139 | |||
| 140 | block_input (); | ||
| 141 | |||
| 142 | pat = ftfont_entity_pattern (entity, pixel_size); | ||
| 143 | FcConfigSubstitute (NULL, pat, FcMatchPattern); | ||
| 144 | FcDefaultSubstitute (pat); | ||
| 145 | match = FcFontMatch (NULL, pat, &result); | ||
| 146 | ftfont_fix_match (pat, match); | ||
| 147 | |||
| 148 | FcPatternDestroy (pat); | ||
| 149 | font_face = cairo_ft_font_face_create_for_pattern (match); | ||
| 150 | if (!font_face) | ||
| 151 | { | ||
| 152 | unblock_input (); | ||
| 153 | FcPatternDestroy (match); | ||
| 154 | return Qnil; | ||
| 155 | } | ||
| 156 | cairo_matrix_t font_matrix, ctm; | ||
| 157 | cairo_matrix_init_scale (&font_matrix, pixel_size, pixel_size); | ||
| 158 | cairo_matrix_init_identity (&ctm); | ||
| 159 | cairo_font_options_t *options = cairo_font_options_create (); | ||
| 160 | cairo_scaled_font_t *scaled_font | ||
| 161 | = cairo_scaled_font_create (font_face, &font_matrix, &ctm, options); | ||
| 162 | cairo_font_face_destroy (font_face); | ||
| 163 | cairo_font_options_destroy (options); | ||
| 164 | unblock_input (); | ||
| 165 | |||
| 126 | font_object = font_build_object (VECSIZE (struct font_info), | 166 | font_object = font_build_object (VECSIZE (struct font_info), |
| 127 | Qftcr, entity, size); | 167 | Qftcr, entity, size); |
| 168 | ASET (font_object, FONT_FILE_INDEX, filename); | ||
| 169 | font = XFONT_OBJECT (font_object); | ||
| 170 | font->pixel_size = size; | ||
| 171 | font->driver = &ftcrfont_driver; | ||
| 172 | font->encoding_charset = font->repertory_charset = -1; | ||
| 173 | |||
| 174 | ftcrfont_info = (struct font_info *) font; | ||
| 175 | ftcrfont_info->cr_scaled_font = scaled_font; | ||
| 176 | |||
| 177 | /* This means that there's no need of transformation. */ | ||
| 178 | ftcrfont_info->matrix.xx = 0; | ||
| 179 | if (FcPatternGetMatrix (match, FC_MATRIX, 0, &matrix) == FcResultMatch) | ||
| 180 | { | ||
| 181 | ftcrfont_info->matrix.xx = 0x10000L * matrix->xx; | ||
| 182 | ftcrfont_info->matrix.yy = 0x10000L * matrix->yy; | ||
| 183 | ftcrfont_info->matrix.xy = 0x10000L * matrix->xy; | ||
| 184 | ftcrfont_info->matrix.yx = 0x10000L * matrix->yx; | ||
| 185 | } | ||
| 186 | |||
| 187 | ftcrfont_info->metrics = NULL; | ||
| 188 | ftcrfont_info->metrics_nrows = 0; | ||
| 189 | |||
| 128 | block_input (); | 190 | block_input (); |
| 129 | font_object = ftfont_open2 (f, entity, pixel_size, font_object); | 191 | cairo_glyph_t stack_glyph; |
| 130 | if (FONT_OBJECT_P (font_object)) | 192 | int n = 0; |
| 193 | font->min_width = font->average_width = font->space_width = 0; | ||
| 194 | for (char c = 32; c < 127; c++) | ||
| 131 | { | 195 | { |
| 132 | struct font *font = XFONT_OBJECT (font_object); | 196 | cairo_glyph_t *glyphs = &stack_glyph; |
| 133 | struct font_info *ftcrfont_info = (struct font_info *) font; | 197 | int num_glyphs = 1; |
| 134 | FT_Face ft_face = ftcrfont_info->ft_size->face; | 198 | cairo_status_t status = |
| 135 | 199 | cairo_scaled_font_text_to_glyphs (ftcrfont_info->cr_scaled_font, | |
| 136 | font->driver = &ftcrfont_driver; | 200 | 0, 0, &c, 1, &glyphs, &num_glyphs, |
| 137 | FT_New_Size (ft_face, &ftcrfont_info->ft_size_draw); | 201 | NULL, NULL, NULL); |
| 138 | FT_Activate_Size (ftcrfont_info->ft_size_draw); | 202 | |
| 139 | if (ftcrfont_info->bitmap_strike_index < 0) | 203 | if (status == CAIRO_STATUS_SUCCESS) |
| 140 | FT_Set_Pixel_Sizes (ft_face, 0, font->pixel_size); | ||
| 141 | else | ||
| 142 | FT_Select_Size (ft_face, ftcrfont_info->bitmap_strike_index); | ||
| 143 | cairo_font_face_t *font_face = | ||
| 144 | cairo_ft_font_face_create_for_ft_face (ft_face, 0); | ||
| 145 | cairo_matrix_t font_matrix, ctm; | ||
| 146 | cairo_matrix_init_scale (&font_matrix, pixel_size, pixel_size); | ||
| 147 | cairo_matrix_init_identity (&ctm); | ||
| 148 | cairo_font_options_t *options = cairo_font_options_create (); | ||
| 149 | ftcrfont_info->cr_scaled_font = | ||
| 150 | cairo_scaled_font_create (font_face, &font_matrix, &ctm, options); | ||
| 151 | cairo_font_face_destroy (font_face); | ||
| 152 | cairo_font_options_destroy (options); | ||
| 153 | ftcrfont_info->metrics = NULL; | ||
| 154 | ftcrfont_info->metrics_nrows = 0; | ||
| 155 | if (ftcrfont_info->bitmap_strike_index >= 0) | ||
| 156 | { | 204 | { |
| 157 | /* Several members of struct font/font_info set by | 205 | if (glyphs != &stack_glyph) |
| 158 | ftfont_open2 are bogus. Recalculate them with cairo | 206 | cairo_glyph_free (glyphs); |
| 159 | scaled font functions. */ | 207 | else if (stack_glyph.index) |
| 160 | cairo_font_extents_t extents; | ||
| 161 | cairo_scaled_font_extents (ftcrfont_info->cr_scaled_font, &extents); | ||
| 162 | font->ascent = lround (extents.ascent); | ||
| 163 | Lisp_Object val = assq_no_quit (QCminspace, | ||
| 164 | AREF (entity, FONT_EXTRA_INDEX)); | ||
| 165 | if (!(CONSP (val) && NILP (XCDR (val)))) | ||
| 166 | { | ||
| 167 | font->descent = lround (extents.descent); | ||
| 168 | font->height = font->ascent + font->descent; | ||
| 169 | } | ||
| 170 | else | ||
| 171 | { | 208 | { |
| 172 | font->height = lround (extents.height); | 209 | int this_width = ftcrfont_glyph_extents (font, stack_glyph.index, |
| 173 | font->descent = font->height - font->ascent; | 210 | NULL); |
| 211 | |||
| 212 | if (this_width > 0 | ||
| 213 | && (! font->min_width | ||
| 214 | || font->min_width > this_width)) | ||
| 215 | font->min_width = this_width; | ||
| 216 | if (c == 32) | ||
| 217 | font->space_width = this_width; | ||
| 218 | font->average_width += this_width; | ||
| 219 | n++; | ||
| 174 | } | 220 | } |
| 221 | } | ||
| 222 | } | ||
| 223 | if (n > 0) | ||
| 224 | font->average_width /= n; | ||
| 175 | 225 | ||
| 176 | cairo_glyph_t stack_glyph; | 226 | cairo_scaled_font_extents (ftcrfont_info->cr_scaled_font, &extents); |
| 177 | int n = 0; | 227 | font->ascent = lround (extents.ascent); |
| 178 | font->min_width = font->average_width = font->space_width = 0; | 228 | val = assq_no_quit (QCminspace, AREF (entity, FONT_EXTRA_INDEX)); |
| 179 | for (char c = 32; c < 127; c++) | 229 | if (!(CONSP (val) && NILP (XCDR (val)))) |
| 180 | { | 230 | { |
| 181 | cairo_glyph_t *glyphs = &stack_glyph; | 231 | font->descent = lround (extents.descent); |
| 182 | int num_glyphs = 1; | 232 | font->height = font->ascent + font->descent; |
| 183 | cairo_status_t status = | 233 | } |
| 184 | cairo_scaled_font_text_to_glyphs (ftcrfont_info->cr_scaled_font, | 234 | else |
| 185 | 0, 0, &c, 1, | 235 | { |
| 186 | &glyphs, &num_glyphs, | 236 | font->height = lround (extents.height); |
| 187 | NULL, NULL, NULL); | 237 | font->descent = font->height - font->ascent; |
| 188 | 238 | } | |
| 189 | if (status == CAIRO_STATUS_SUCCESS) | ||
| 190 | { | ||
| 191 | if (glyphs != &stack_glyph) | ||
| 192 | cairo_glyph_free (glyphs); | ||
| 193 | else if (stack_glyph.index) | ||
| 194 | { | ||
| 195 | int this_width = | ||
| 196 | ftcrfont_glyph_extents (font, stack_glyph.index, NULL); | ||
| 197 | |||
| 198 | if (this_width > 0 | ||
| 199 | && (! font->min_width | ||
| 200 | || font->min_width > this_width)) | ||
| 201 | font->min_width = this_width; | ||
| 202 | if (c == 32) | ||
| 203 | font->space_width = this_width; | ||
| 204 | font->average_width += this_width; | ||
| 205 | n++; | ||
| 206 | } | ||
| 207 | } | ||
| 208 | } | ||
| 209 | if (n > 0) | ||
| 210 | font->average_width /= n; | ||
| 211 | 239 | ||
| 212 | font->underline_position = -1; | 240 | ft_face = cairo_ft_scaled_font_lock_face (scaled_font); |
| 213 | font->underline_thickness = 0; | 241 | if (XFIXNUM (AREF (entity, FONT_SIZE_INDEX)) == 0) |
| 214 | } | 242 | { |
| 243 | int upEM = ft_face->units_per_EM; | ||
| 244 | |||
| 245 | font->underline_position = -ft_face->underline_position * size / upEM; | ||
| 246 | font->underline_thickness = ft_face->underline_thickness * size / upEM; | ||
| 247 | if (font->underline_thickness > 2) | ||
| 248 | font->underline_position -= font->underline_thickness / 2; | ||
| 249 | } | ||
| 250 | else | ||
| 251 | { | ||
| 252 | font->underline_position = -1; | ||
| 253 | font->underline_thickness = 0; | ||
| 215 | } | 254 | } |
| 255 | #ifdef HAVE_LIBOTF | ||
| 256 | ftcrfont_info->maybe_otf = (ft_face->face_flags & FT_FACE_FLAG_SFNT) != 0; | ||
| 257 | ftcrfont_info->otf = NULL; | ||
| 258 | #endif /* HAVE_LIBOTF */ | ||
| 259 | if (ft_face->units_per_EM) | ||
| 260 | ftcrfont_info->bitmap_position_unit = 0; | ||
| 261 | else | ||
| 262 | ftcrfont_info->bitmap_position_unit = (extents.height | ||
| 263 | / ft_face->size->metrics.height); | ||
| 264 | cairo_ft_scaled_font_unlock_face (scaled_font); | ||
| 265 | ftcrfont_info->ft_size = NULL; | ||
| 216 | unblock_input (); | 266 | unblock_input (); |
| 217 | 267 | ||
| 268 | font->baseline_offset = 0; | ||
| 269 | font->relative_compose = 0; | ||
| 270 | font->default_ascent = 0; | ||
| 271 | font->vertical_centering = false; | ||
| 272 | |||
| 218 | return font_object; | 273 | return font_object; |
| 219 | } | 274 | } |
| 220 | 275 | ||
| @@ -225,19 +280,58 @@ ftcrfont_close (struct font *font) | |||
| 225 | return; | 280 | return; |
| 226 | 281 | ||
| 227 | struct font_info *ftcrfont_info = (struct font_info *) font; | 282 | struct font_info *ftcrfont_info = (struct font_info *) font; |
| 228 | int i; | ||
| 229 | 283 | ||
| 230 | block_input (); | 284 | block_input (); |
| 231 | for (i = 0; i < ftcrfont_info->metrics_nrows; i++) | 285 | #ifdef HAVE_LIBOTF |
| 286 | if (ftcrfont_info->otf) | ||
| 287 | { | ||
| 288 | OTF_close (ftcrfont_info->otf); | ||
| 289 | ftcrfont_info->otf = NULL; | ||
| 290 | } | ||
| 291 | #endif | ||
| 292 | for (int i = 0; i < ftcrfont_info->metrics_nrows; i++) | ||
| 232 | if (ftcrfont_info->metrics[i]) | 293 | if (ftcrfont_info->metrics[i]) |
| 233 | xfree (ftcrfont_info->metrics[i]); | 294 | xfree (ftcrfont_info->metrics[i]); |
| 234 | if (ftcrfont_info->metrics) | 295 | if (ftcrfont_info->metrics) |
| 235 | xfree (ftcrfont_info->metrics); | 296 | xfree (ftcrfont_info->metrics); |
| 236 | FT_Done_Size (ftcrfont_info->ft_size_draw); | ||
| 237 | cairo_scaled_font_destroy (ftcrfont_info->cr_scaled_font); | 297 | cairo_scaled_font_destroy (ftcrfont_info->cr_scaled_font); |
| 238 | unblock_input (); | 298 | unblock_input (); |
| 299 | } | ||
| 300 | |||
| 301 | static int | ||
| 302 | ftcrfont_has_char (Lisp_Object font, int c) | ||
| 303 | { | ||
| 304 | if (FONT_ENTITY_P (font)) | ||
| 305 | return ftfont_has_char (font, c); | ||
| 239 | 306 | ||
| 240 | ftfont_close (font); | 307 | return -1; |
| 308 | } | ||
| 309 | |||
| 310 | static unsigned | ||
| 311 | ftcrfont_encode_char (struct font *font, int c) | ||
| 312 | { | ||
| 313 | struct font_info *ftcrfont_info = (struct font_info *) font; | ||
| 314 | unsigned code = FONT_INVALID_CODE; | ||
| 315 | unsigned char utf8[MAX_MULTIBYTE_LENGTH]; | ||
| 316 | unsigned char *p = utf8; | ||
| 317 | cairo_glyph_t stack_glyph; | ||
| 318 | cairo_glyph_t *glyphs = &stack_glyph; | ||
| 319 | int num_glyphs = 1; | ||
| 320 | |||
| 321 | CHAR_STRING_ADVANCE (c, p); | ||
| 322 | if (cairo_scaled_font_text_to_glyphs (ftcrfont_info->cr_scaled_font, 0, 0, | ||
| 323 | (char *) utf8, p - utf8, | ||
| 324 | &glyphs, &num_glyphs, | ||
| 325 | NULL, NULL, NULL) | ||
| 326 | == CAIRO_STATUS_SUCCESS) | ||
| 327 | { | ||
| 328 | if (glyphs != &stack_glyph) | ||
| 329 | cairo_glyph_free (glyphs); | ||
| 330 | else if (stack_glyph.index) | ||
| 331 | code = stack_glyph.index; | ||
| 332 | } | ||
| 333 | |||
| 334 | return code; | ||
| 241 | } | 335 | } |
| 242 | 336 | ||
| 243 | static void | 337 | static void |
| @@ -280,10 +374,18 @@ ftcrfont_get_bitmap (struct font *font, unsigned int code, | |||
| 280 | { | 374 | { |
| 281 | struct font_info *ftcrfont_info = (struct font_info *) font; | 375 | struct font_info *ftcrfont_info = (struct font_info *) font; |
| 282 | 376 | ||
| 283 | if (ftcrfont_info->bitmap_strike_index < 0) | 377 | if (ftcrfont_info->bitmap_position_unit) |
| 284 | return ftfont_get_bitmap (font, code, bitmap, bits_per_pixel); | 378 | return -1; |
| 285 | 379 | ||
| 286 | return -1; | 380 | cairo_scaled_font_t *scaled_font = ftcrfont_info->cr_scaled_font; |
| 381 | FT_Face ft_face = cairo_ft_scaled_font_lock_face (scaled_font); | ||
| 382 | |||
| 383 | ftcrfont_info->ft_size = ft_face->size; | ||
| 384 | int result = ftfont_get_bitmap (font, code, bitmap, bits_per_pixel); | ||
| 385 | cairo_ft_scaled_font_unlock_face (scaled_font); | ||
| 386 | ftcrfont_info->ft_size = NULL; | ||
| 387 | |||
| 388 | return result; | ||
| 287 | } | 389 | } |
| 288 | 390 | ||
| 289 | static int | 391 | static int |
| @@ -292,25 +394,75 @@ ftcrfont_anchor_point (struct font *font, unsigned int code, int idx, | |||
| 292 | { | 394 | { |
| 293 | struct font_info *ftcrfont_info = (struct font_info *) font; | 395 | struct font_info *ftcrfont_info = (struct font_info *) font; |
| 294 | 396 | ||
| 295 | if (ftcrfont_info->bitmap_strike_index < 0) | 397 | if (ftcrfont_info->bitmap_position_unit) |
| 296 | return ftfont_anchor_point (font, code, idx, x, y); | 398 | return -1; |
| 297 | 399 | ||
| 298 | return -1; | 400 | cairo_scaled_font_t *scaled_font = ftcrfont_info->cr_scaled_font; |
| 401 | FT_Face ft_face = cairo_ft_scaled_font_lock_face (scaled_font); | ||
| 402 | |||
| 403 | ftcrfont_info->ft_size = ft_face->size; | ||
| 404 | int result = ftfont_anchor_point (font, code, idx, x, y); | ||
| 405 | cairo_ft_scaled_font_unlock_face (scaled_font); | ||
| 406 | ftcrfont_info->ft_size = NULL; | ||
| 407 | |||
| 408 | return result; | ||
| 299 | } | 409 | } |
| 300 | 410 | ||
| 411 | #ifdef HAVE_LIBOTF | ||
| 301 | static Lisp_Object | 412 | static Lisp_Object |
| 302 | ftcrfont_shape (Lisp_Object lgstring) | 413 | ftcrfont_otf_capability (struct font *font) |
| 303 | { | 414 | { |
| 415 | struct font_info *ftcrfont_info = (struct font_info *) font; | ||
| 416 | cairo_scaled_font_t *scaled_font = ftcrfont_info->cr_scaled_font; | ||
| 417 | FT_Face ft_face = cairo_ft_scaled_font_lock_face (scaled_font); | ||
| 418 | |||
| 419 | ftcrfont_info->ft_size = ft_face->size; | ||
| 420 | Lisp_Object result = ftfont_otf_capability (font); | ||
| 421 | cairo_ft_scaled_font_unlock_face (scaled_font); | ||
| 422 | ftcrfont_info->ft_size = NULL; | ||
| 423 | |||
| 424 | return result; | ||
| 425 | } | ||
| 426 | #endif | ||
| 427 | |||
| 304 | #if defined HAVE_M17N_FLT && defined HAVE_LIBOTF | 428 | #if defined HAVE_M17N_FLT && defined HAVE_LIBOTF |
| 429 | static Lisp_Object | ||
| 430 | ftcrfont_shape (Lisp_Object lgstring) | ||
| 431 | { | ||
| 305 | struct font *font = CHECK_FONT_GET_OBJECT (LGSTRING_FONT (lgstring)); | 432 | struct font *font = CHECK_FONT_GET_OBJECT (LGSTRING_FONT (lgstring)); |
| 306 | struct font_info *ftcrfont_info = (struct font_info *) font; | 433 | struct font_info *ftcrfont_info = (struct font_info *) font; |
| 307 | 434 | ||
| 308 | if (ftcrfont_info->bitmap_strike_index < 0) | 435 | if (ftcrfont_info->bitmap_position_unit) |
| 309 | return ftfont_shape (lgstring); | 436 | return make_fixnum (0); |
| 437 | |||
| 438 | cairo_scaled_font_t *scaled_font = ftcrfont_info->cr_scaled_font; | ||
| 439 | FT_Face ft_face = cairo_ft_scaled_font_lock_face (scaled_font); | ||
| 440 | |||
| 441 | ftcrfont_info->ft_size = ft_face->size; | ||
| 442 | Lisp_Object result = ftfont_shape (lgstring); | ||
| 443 | cairo_ft_scaled_font_unlock_face (scaled_font); | ||
| 444 | ftcrfont_info->ft_size = NULL; | ||
| 445 | |||
| 446 | return result; | ||
| 447 | } | ||
| 310 | #endif | 448 | #endif |
| 311 | 449 | ||
| 312 | return make_fixnum (0); | 450 | #ifdef HAVE_OTF_GET_VARIATION_GLYPHS |
| 451 | static int | ||
| 452 | ftcrfont_variation_glyphs (struct font *font, int c, unsigned variations[256]) | ||
| 453 | { | ||
| 454 | struct font_info *ftcrfont_info = (struct font_info *) font; | ||
| 455 | cairo_scaled_font_t *scaled_font = ftcrfont_info->cr_scaled_font; | ||
| 456 | FT_Face ft_face = cairo_ft_scaled_font_lock_face (scaled_font); | ||
| 457 | |||
| 458 | ftcrfont_info->ft_size = ft_face->size; | ||
| 459 | int result = ftfont_variation_glyphs (font, c, variations); | ||
| 460 | cairo_ft_scaled_font_unlock_face (scaled_font); | ||
| 461 | ftcrfont_info->ft_size = NULL; | ||
| 462 | |||
| 463 | return result; | ||
| 313 | } | 464 | } |
| 465 | #endif /* HAVE_OTF_GET_VARIATION_GLYPHS */ | ||
| 314 | 466 | ||
| 315 | static int | 467 | static int |
| 316 | ftcrfont_draw (struct glyph_string *s, | 468 | ftcrfont_draw (struct glyph_string *s, |
| @@ -321,8 +473,6 @@ ftcrfont_draw (struct glyph_string *s, | |||
| 321 | struct font_info *ftcrfont_info = (struct font_info *) s->font; | 473 | struct font_info *ftcrfont_info = (struct font_info *) s->font; |
| 322 | cairo_t *cr; | 474 | cairo_t *cr; |
| 323 | cairo_glyph_t *glyphs; | 475 | cairo_glyph_t *glyphs; |
| 324 | cairo_surface_t *surface; | ||
| 325 | cairo_surface_type_t surface_type; | ||
| 326 | int len = to - from; | 476 | int len = to - from; |
| 327 | int i; | 477 | int i; |
| 328 | 478 | ||
| @@ -351,17 +501,7 @@ ftcrfont_draw (struct glyph_string *s, | |||
| 351 | 501 | ||
| 352 | x_set_cr_source_with_gc_foreground (f, s->gc); | 502 | x_set_cr_source_with_gc_foreground (f, s->gc); |
| 353 | cairo_set_scaled_font (cr, ftcrfont_info->cr_scaled_font); | 503 | cairo_set_scaled_font (cr, ftcrfont_info->cr_scaled_font); |
| 354 | |||
| 355 | FT_Activate_Size (ftcrfont_info->ft_size_draw); | ||
| 356 | cairo_show_glyphs (cr, glyphs, len); | 504 | cairo_show_glyphs (cr, glyphs, len); |
| 357 | surface = cairo_get_target (cr); | ||
| 358 | /* XXX: It used to be necessary to flush when exporting. It might | ||
| 359 | be the case that this is no longer necessary. */ | ||
| 360 | surface_type = cairo_surface_get_type (surface); | ||
| 361 | if (surface_type != CAIRO_SURFACE_TYPE_XLIB | ||
| 362 | && (surface_type != CAIRO_SURFACE_TYPE_IMAGE | ||
| 363 | || cairo_image_surface_get_format (surface) != CAIRO_FORMAT_ARGB32)) | ||
| 364 | cairo_surface_flush (surface); | ||
| 365 | 505 | ||
| 366 | x_end_cr_clip (f); | 506 | x_end_cr_clip (f); |
| 367 | 507 | ||
| @@ -383,18 +523,20 @@ struct font_driver const ftcrfont_driver = | |||
| 383 | .list_family = ftfont_list_family, | 523 | .list_family = ftfont_list_family, |
| 384 | .open = ftcrfont_open, | 524 | .open = ftcrfont_open, |
| 385 | .close = ftcrfont_close, | 525 | .close = ftcrfont_close, |
| 386 | .has_char = ftfont_has_char, | 526 | .has_char = ftcrfont_has_char, |
| 387 | .encode_char = ftfont_encode_char, | 527 | .encode_char = ftcrfont_encode_char, |
| 388 | .text_extents = ftcrfont_text_extents, | 528 | .text_extents = ftcrfont_text_extents, |
| 389 | .draw = ftcrfont_draw, | 529 | .draw = ftcrfont_draw, |
| 390 | .get_bitmap = ftcrfont_get_bitmap, | 530 | .get_bitmap = ftcrfont_get_bitmap, |
| 391 | .anchor_point = ftcrfont_anchor_point, | 531 | .anchor_point = ftcrfont_anchor_point, |
| 392 | #ifdef HAVE_LIBOTF | 532 | #ifdef HAVE_LIBOTF |
| 393 | .otf_capability = ftfont_otf_capability, | 533 | .otf_capability = ftcrfont_otf_capability, |
| 394 | #endif | 534 | #endif |
| 535 | #if defined HAVE_M17N_FLT && defined HAVE_LIBOTF | ||
| 395 | .shape = ftcrfont_shape, | 536 | .shape = ftcrfont_shape, |
| 537 | #endif | ||
| 396 | #ifdef HAVE_OTF_GET_VARIATION_GLYPHS | 538 | #ifdef HAVE_OTF_GET_VARIATION_GLYPHS |
| 397 | .get_variation_glyphs = ftfont_variation_glyphs, | 539 | .get_variation_glyphs = ftcrfont_variation_glyphs, |
| 398 | #endif | 540 | #endif |
| 399 | .filter_properties = ftfont_filter_properties, | 541 | .filter_properties = ftfont_filter_properties, |
| 400 | .combining_capability = ftfont_combining_capability, | 542 | .combining_capability = ftfont_combining_capability, |
diff --git a/src/ftfont.c b/src/ftfont.c index f17bd9ab3f7..d8b510d7032 100644 --- a/src/ftfont.c +++ b/src/ftfont.c | |||
| @@ -1079,12 +1079,159 @@ ftfont_list_family (struct frame *f) | |||
| 1079 | return list; | 1079 | return list; |
| 1080 | } | 1080 | } |
| 1081 | 1081 | ||
| 1082 | void | ||
| 1083 | ftfont_fix_match (FcPattern *pat, FcPattern *match) | ||
| 1084 | { | ||
| 1085 | /* These values are not used for matching (except antialias), but for | ||
| 1086 | rendering, so make sure they are carried over to the match. | ||
| 1087 | We also put antialias here because most fonts are antialiased, so | ||
| 1088 | the match will have antialias true. */ | ||
| 1089 | |||
| 1090 | FcBool b = FcTrue; | ||
| 1091 | int i; | ||
| 1092 | double dpi; | ||
| 1093 | |||
| 1094 | FcPatternGetBool (pat, FC_ANTIALIAS, 0, &b); | ||
| 1095 | if (! b) | ||
| 1096 | { | ||
| 1097 | FcPatternDel (match, FC_ANTIALIAS); | ||
| 1098 | FcPatternAddBool (match, FC_ANTIALIAS, FcFalse); | ||
| 1099 | } | ||
| 1100 | FcPatternGetBool (pat, FC_HINTING, 0, &b); | ||
| 1101 | if (! b) | ||
| 1102 | { | ||
| 1103 | FcPatternDel (match, FC_HINTING); | ||
| 1104 | FcPatternAddBool (match, FC_HINTING, FcFalse); | ||
| 1105 | } | ||
| 1106 | #ifndef FC_HINT_STYLE | ||
| 1107 | # define FC_HINT_STYLE "hintstyle" | ||
| 1108 | #endif | ||
| 1109 | if (FcResultMatch == FcPatternGetInteger (pat, FC_HINT_STYLE, 0, &i)) | ||
| 1110 | { | ||
| 1111 | FcPatternDel (match, FC_HINT_STYLE); | ||
| 1112 | FcPatternAddInteger (match, FC_HINT_STYLE, i); | ||
| 1113 | } | ||
| 1114 | #ifndef FC_LCD_FILTER | ||
| 1115 | /* Older fontconfig versions don't have FC_LCD_FILTER. */ | ||
| 1116 | #define FC_LCD_FILTER "lcdfilter" | ||
| 1117 | #endif | ||
| 1118 | if (FcResultMatch == FcPatternGetInteger (pat, FC_LCD_FILTER, 0, &i)) | ||
| 1119 | { | ||
| 1120 | FcPatternDel (match, FC_LCD_FILTER); | ||
| 1121 | FcPatternAddInteger (match, FC_LCD_FILTER, i); | ||
| 1122 | } | ||
| 1123 | if (FcResultMatch == FcPatternGetInteger (pat, FC_RGBA, 0, &i)) | ||
| 1124 | { | ||
| 1125 | FcPatternDel (match, FC_RGBA); | ||
| 1126 | FcPatternAddInteger (match, FC_RGBA, i); | ||
| 1127 | } | ||
| 1128 | if (FcResultMatch == FcPatternGetDouble (pat, FC_DPI, 0, &dpi)) | ||
| 1129 | { | ||
| 1130 | FcPatternDel (match, FC_DPI); | ||
| 1131 | FcPatternAddDouble (match, FC_DPI, dpi); | ||
| 1132 | } | ||
| 1133 | } | ||
| 1134 | |||
| 1135 | void | ||
| 1136 | ftfont_add_rendering_parameters (FcPattern *pat, Lisp_Object entity) | ||
| 1137 | { | ||
| 1138 | Lisp_Object tail; | ||
| 1139 | int ival; | ||
| 1140 | |||
| 1141 | for (tail = AREF (entity, FONT_EXTRA_INDEX); CONSP (tail); tail = XCDR (tail)) | ||
| 1142 | { | ||
| 1143 | Lisp_Object key = XCAR (XCAR (tail)); | ||
| 1144 | Lisp_Object val = XCDR (XCAR (tail)); | ||
| 1145 | |||
| 1146 | if (EQ (key, QCantialias)) | ||
| 1147 | FcPatternAddBool (pat, FC_ANTIALIAS, NILP (val) ? FcFalse : FcTrue); | ||
| 1148 | else if (EQ (key, QChinting)) | ||
| 1149 | FcPatternAddBool (pat, FC_HINTING, NILP (val) ? FcFalse : FcTrue); | ||
| 1150 | else if (EQ (key, QCautohint)) | ||
| 1151 | FcPatternAddBool (pat, FC_AUTOHINT, NILP (val) ? FcFalse : FcTrue); | ||
| 1152 | else if (EQ (key, QChintstyle)) | ||
| 1153 | { | ||
| 1154 | if (FIXNUMP (val)) | ||
| 1155 | FcPatternAddInteger (pat, FC_HINT_STYLE, XFIXNUM (val)); | ||
| 1156 | else if (SYMBOLP (val) | ||
| 1157 | && FcNameConstant (SDATA (SYMBOL_NAME (val)), &ival)) | ||
| 1158 | FcPatternAddInteger (pat, FC_HINT_STYLE, ival); | ||
| 1159 | } | ||
| 1160 | else if (EQ (key, QCrgba)) | ||
| 1161 | { | ||
| 1162 | if (FIXNUMP (val)) | ||
| 1163 | FcPatternAddInteger (pat, FC_RGBA, XFIXNUM (val)); | ||
| 1164 | else if (SYMBOLP (val) | ||
| 1165 | && FcNameConstant (SDATA (SYMBOL_NAME (val)), &ival)) | ||
| 1166 | FcPatternAddInteger (pat, FC_RGBA, ival); | ||
| 1167 | } | ||
| 1168 | else if (EQ (key, QClcdfilter)) | ||
| 1169 | { | ||
| 1170 | if (FIXNUMP (val)) | ||
| 1171 | FcPatternAddInteger (pat, FC_LCD_FILTER, ival = XFIXNUM (val)); | ||
| 1172 | else if (SYMBOLP (val) | ||
| 1173 | && FcNameConstant (SDATA (SYMBOL_NAME (val)), &ival)) | ||
| 1174 | FcPatternAddInteger (pat, FC_LCD_FILTER, ival); | ||
| 1175 | } | ||
| 1176 | #ifdef FC_EMBOLDEN | ||
| 1177 | else if (EQ (key, QCembolden)) | ||
| 1178 | FcPatternAddBool (pat, FC_EMBOLDEN, NILP (val) ? FcFalse : FcTrue); | ||
| 1179 | #endif | ||
| 1180 | } | ||
| 1181 | } | ||
| 1182 | |||
| 1183 | FcPattern * | ||
| 1184 | ftfont_entity_pattern (Lisp_Object entity, int pixel_size) | ||
| 1185 | { | ||
| 1186 | Lisp_Object val, filename, idx; | ||
| 1187 | FcPattern *pat; | ||
| 1188 | int i; | ||
| 1189 | |||
| 1190 | val = assq_no_quit (QCfont_entity, AREF (entity, FONT_EXTRA_INDEX)); | ||
| 1191 | eassert (CONSP (val)); | ||
| 1192 | val = XCDR (val); | ||
| 1193 | filename = XCAR (val); | ||
| 1194 | idx = XCDR (val); | ||
| 1195 | pat = FcPatternCreate (); | ||
| 1196 | FcPatternAddInteger (pat, FC_WEIGHT, FONT_WEIGHT_NUMERIC (entity)); | ||
| 1197 | i = FONT_SLANT_NUMERIC (entity) - 100; | ||
| 1198 | if (i < 0) i = 0; | ||
| 1199 | FcPatternAddInteger (pat, FC_SLANT, i); | ||
| 1200 | FcPatternAddInteger (pat, FC_WIDTH, FONT_WIDTH_NUMERIC (entity)); | ||
| 1201 | FcPatternAddDouble (pat, FC_PIXEL_SIZE, pixel_size); | ||
| 1202 | val = AREF (entity, FONT_FAMILY_INDEX); | ||
| 1203 | if (! NILP (val)) | ||
| 1204 | FcPatternAddString (pat, FC_FAMILY, (FcChar8 *) SDATA (SYMBOL_NAME (val))); | ||
| 1205 | val = AREF (entity, FONT_FOUNDRY_INDEX); | ||
| 1206 | if (! NILP (val)) | ||
| 1207 | FcPatternAddString (pat, FC_FOUNDRY, (FcChar8 *) SDATA (SYMBOL_NAME (val))); | ||
| 1208 | val = AREF (entity, FONT_SPACING_INDEX); | ||
| 1209 | if (! NILP (val)) | ||
| 1210 | FcPatternAddInteger (pat, FC_SPACING, XFIXNUM (val)); | ||
| 1211 | val = AREF (entity, FONT_DPI_INDEX); | ||
| 1212 | if (! NILP (val)) | ||
| 1213 | { | ||
| 1214 | double dbl = XFIXNUM (val); | ||
| 1215 | |||
| 1216 | FcPatternAddDouble (pat, FC_DPI, dbl); | ||
| 1217 | } | ||
| 1218 | val = AREF (entity, FONT_AVGWIDTH_INDEX); | ||
| 1219 | if (FIXNUMP (val) && XFIXNUM (val) == 0) | ||
| 1220 | FcPatternAddBool (pat, FC_SCALABLE, FcTrue); | ||
| 1221 | /* This is necessary to identify the exact font (e.g. 10x20.pcf.gz | ||
| 1222 | over 10x20-ISO8859-1.pcf.gz). */ | ||
| 1223 | FcPatternAddCharSet (pat, FC_CHARSET, ftfont_get_fc_charset (entity)); | ||
| 1224 | |||
| 1225 | ftfont_add_rendering_parameters (pat, entity); | ||
| 1226 | |||
| 1227 | FcPatternAddString (pat, FC_FILE, (FcChar8 *) SDATA (filename)); | ||
| 1228 | FcPatternAddInteger (pat, FC_INDEX, XFIXNUM (idx)); | ||
| 1229 | |||
| 1230 | return pat; | ||
| 1231 | } | ||
| 1082 | 1232 | ||
| 1083 | Lisp_Object | 1233 | Lisp_Object |
| 1084 | ftfont_open2 (struct frame *f, | 1234 | ftfont_open (struct frame *f, Lisp_Object entity, int pixel_size) |
| 1085 | Lisp_Object entity, | ||
| 1086 | int pixel_size, | ||
| 1087 | Lisp_Object font_object) | ||
| 1088 | { | 1235 | { |
| 1089 | struct font_info *ftfont_info; | 1236 | struct font_info *ftfont_info; |
| 1090 | struct font *font; | 1237 | struct font *font; |
| @@ -1092,12 +1239,11 @@ ftfont_open2 (struct frame *f, | |||
| 1092 | FT_Face ft_face; | 1239 | FT_Face ft_face; |
| 1093 | FT_Size ft_size; | 1240 | FT_Size ft_size; |
| 1094 | FT_UInt size; | 1241 | FT_UInt size; |
| 1095 | Lisp_Object val, filename, idx, cache; | 1242 | Lisp_Object val, filename, idx, cache, font_object; |
| 1096 | bool scalable; | 1243 | bool scalable; |
| 1097 | int spacing; | 1244 | int spacing; |
| 1098 | int i; | 1245 | int i; |
| 1099 | double upEM; | 1246 | double upEM; |
| 1100 | FT_Int strike_index = -1; | ||
| 1101 | 1247 | ||
| 1102 | val = assq_no_quit (QCfont_entity, AREF (entity, FONT_EXTRA_INDEX)); | 1248 | val = assq_no_quit (QCfont_entity, AREF (entity, FONT_EXTRA_INDEX)); |
| 1103 | if (! CONSP (val)) | 1249 | if (! CONSP (val)) |
| @@ -1126,35 +1272,17 @@ ftfont_open2 (struct frame *f, | |||
| 1126 | size = pixel_size; | 1272 | size = pixel_size; |
| 1127 | if (FT_Set_Pixel_Sizes (ft_face, size, size) != 0) | 1273 | if (FT_Set_Pixel_Sizes (ft_face, size, size) != 0) |
| 1128 | { | 1274 | { |
| 1129 | int min_distance = INT_MAX; | 1275 | if (cache_data->face_refcount == 0) |
| 1130 | bool magnify = true; | ||
| 1131 | |||
| 1132 | for (FT_Int i = 0; i < ft_face->num_fixed_sizes; i++) | ||
| 1133 | { | ||
| 1134 | int distance = ft_face->available_sizes[i].height - (int) size; | ||
| 1135 | |||
| 1136 | /* Prefer down-scaling to upscaling. */ | ||
| 1137 | if (magnify == (distance < 0) ? abs (distance) <= min_distance | ||
| 1138 | : magnify) | ||
| 1139 | { | ||
| 1140 | magnify = distance < 0; | ||
| 1141 | min_distance = abs (distance); | ||
| 1142 | strike_index = i; | ||
| 1143 | } | ||
| 1144 | } | ||
| 1145 | |||
| 1146 | if (strike_index < 0 || FT_Select_Size (ft_face, strike_index) != 0) | ||
| 1147 | { | 1276 | { |
| 1148 | if (cache_data->face_refcount == 0) | 1277 | FT_Done_Face (ft_face); |
| 1149 | { | 1278 | cache_data->ft_face = NULL; |
| 1150 | FT_Done_Face (ft_face); | ||
| 1151 | cache_data->ft_face = NULL; | ||
| 1152 | } | ||
| 1153 | return Qnil; | ||
| 1154 | } | 1279 | } |
| 1280 | return Qnil; | ||
| 1155 | } | 1281 | } |
| 1156 | cache_data->face_refcount++; | 1282 | cache_data->face_refcount++; |
| 1157 | 1283 | ||
| 1284 | font_object = font_build_object (VECSIZE (struct font_info), | ||
| 1285 | Qfreetype, entity, size); | ||
| 1158 | ASET (font_object, FONT_FILE_INDEX, filename); | 1286 | ASET (font_object, FONT_FILE_INDEX, filename); |
| 1159 | font = XFONT_OBJECT (font_object); | 1287 | font = XFONT_OBJECT (font_object); |
| 1160 | ftfont_info = (struct font_info *) font; | 1288 | ftfont_info = (struct font_info *) font; |
| @@ -1164,7 +1292,6 @@ ftfont_open2 (struct frame *f, | |||
| 1164 | ftfont_info->maybe_otf = (ft_face->face_flags & FT_FACE_FLAG_SFNT) != 0; | 1292 | ftfont_info->maybe_otf = (ft_face->face_flags & FT_FACE_FLAG_SFNT) != 0; |
| 1165 | ftfont_info->otf = NULL; | 1293 | ftfont_info->otf = NULL; |
| 1166 | #endif /* HAVE_LIBOTF */ | 1294 | #endif /* HAVE_LIBOTF */ |
| 1167 | ftfont_info->bitmap_strike_index = strike_index; | ||
| 1168 | /* This means that there's no need of transformation. */ | 1295 | /* This means that there's no need of transformation. */ |
| 1169 | ftfont_info->matrix.xx = 0; | 1296 | ftfont_info->matrix.xx = 0; |
| 1170 | font->pixel_size = size; | 1297 | font->pixel_size = size; |
| @@ -1258,31 +1385,6 @@ ftfont_open2 (struct frame *f, | |||
| 1258 | return font_object; | 1385 | return font_object; |
| 1259 | } | 1386 | } |
| 1260 | 1387 | ||
| 1261 | Lisp_Object | ||
| 1262 | ftfont_open (struct frame *f, Lisp_Object entity, int pixel_size) | ||
| 1263 | { | ||
| 1264 | Lisp_Object font_object; | ||
| 1265 | FT_UInt size; | ||
| 1266 | size = XFIXNUM (AREF (entity, FONT_SIZE_INDEX)); | ||
| 1267 | if (size == 0) | ||
| 1268 | size = pixel_size; | ||
| 1269 | font_object = font_build_object (VECSIZE (struct font_info), | ||
| 1270 | Qfreetype, entity, size); | ||
| 1271 | font_object = ftfont_open2 (f, entity, pixel_size, font_object); | ||
| 1272 | if (FONT_OBJECT_P (font_object)) | ||
| 1273 | { | ||
| 1274 | struct font *font = XFONT_OBJECT (font_object); | ||
| 1275 | struct font_info *ftfont_info = (struct font_info *) font; | ||
| 1276 | |||
| 1277 | if (ftfont_info->bitmap_strike_index >= 0) | ||
| 1278 | { | ||
| 1279 | ftfont_close (font); | ||
| 1280 | font_object = Qnil; | ||
| 1281 | } | ||
| 1282 | } | ||
| 1283 | return font_object; | ||
| 1284 | } | ||
| 1285 | |||
| 1286 | void | 1388 | void |
| 1287 | ftfont_close (struct font *font) | 1389 | ftfont_close (struct font *font) |
| 1288 | { | 1390 | { |
| @@ -2789,6 +2891,14 @@ syms_of_ftfont (void) | |||
| 2789 | /* The boolean-valued font property key specifying the use of leading. */ | 2891 | /* The boolean-valued font property key specifying the use of leading. */ |
| 2790 | DEFSYM (QCminspace, ":minspace"); | 2892 | DEFSYM (QCminspace, ":minspace"); |
| 2791 | 2893 | ||
| 2894 | /* Fontconfig's rendering parameters. */ | ||
| 2895 | DEFSYM (QChinting, ":hinting"); | ||
| 2896 | DEFSYM (QCautohint, ":autohint"); | ||
| 2897 | DEFSYM (QChintstyle, ":hintstyle"); | ||
| 2898 | DEFSYM (QCrgba, ":rgba"); | ||
| 2899 | DEFSYM (QCembolden, ":embolden"); | ||
| 2900 | DEFSYM (QClcdfilter, ":lcdfilter"); | ||
| 2901 | |||
| 2792 | staticpro (&freetype_font_cache); | 2902 | staticpro (&freetype_font_cache); |
| 2793 | freetype_font_cache = list1 (Qt); | 2903 | freetype_font_cache = list1 (Qt); |
| 2794 | 2904 | ||
diff --git a/src/ftfont.h b/src/ftfont.h index adbda49ff1c..7860469491f 100644 --- a/src/ftfont.h +++ b/src/ftfont.h | |||
| @@ -37,10 +37,9 @@ along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */ | |||
| 37 | #endif /* HAVE_LIBOTF */ | 37 | #endif /* HAVE_LIBOTF */ |
| 38 | 38 | ||
| 39 | extern FcCharSet *ftfont_get_fc_charset (Lisp_Object); | 39 | extern FcCharSet *ftfont_get_fc_charset (Lisp_Object); |
| 40 | extern Lisp_Object ftfont_open2 (struct frame *f, | 40 | extern void ftfont_fix_match (FcPattern *, FcPattern *); |
| 41 | Lisp_Object entity, | 41 | extern void ftfont_add_rendering_parameters (FcPattern *, Lisp_Object); |
| 42 | int pixel_size, | 42 | extern FcPattern *ftfont_entity_pattern (Lisp_Object, int); |
| 43 | Lisp_Object font_object); | ||
| 44 | 43 | ||
| 45 | /* This struct is shared by the XFT, Freetype, and Cairo font | 44 | /* This struct is shared by the XFT, Freetype, and Cairo font |
| 46 | backends. Members up to and including 'matrix' are common, the | 45 | backends. Members up to and including 'matrix' are common, the |
| @@ -54,17 +53,14 @@ struct font_info | |||
| 54 | #endif /* HAVE_LIBOTF */ | 53 | #endif /* HAVE_LIBOTF */ |
| 55 | FT_Size ft_size; | 54 | FT_Size ft_size; |
| 56 | int index; | 55 | 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; | ||
| 61 | FT_Matrix matrix; | 56 | FT_Matrix matrix; |
| 62 | 57 | ||
| 63 | #ifdef USE_CAIRO | 58 | #ifdef USE_CAIRO |
| 64 | cairo_scaled_font_t *cr_scaled_font; | 59 | cairo_scaled_font_t *cr_scaled_font; |
| 65 | /* To prevent cairo from cluttering the activated FT_Size maintained | 60 | /* Scale factor from the bitmap strike metrics in 1/64 pixels, used |
| 66 | in ftfont.c, we activate this special FT_Size before drawing. */ | 61 | as the hb_position_t value in HarfBuzz, to those in (scaled) |
| 67 | FT_Size ft_size_draw; | 62 | pixels. The value is 0 for scalable fonts. */ |
| 63 | double bitmap_position_unit; | ||
| 68 | /* Font metrics cache. */ | 64 | /* Font metrics cache. */ |
| 69 | struct font_metrics **metrics; | 65 | struct font_metrics **metrics; |
| 70 | short metrics_nrows; | 66 | short metrics_nrows; |
diff --git a/src/xftfont.c b/src/xftfont.c index 2edc51fe356..4f0a0d81d85 100644 --- a/src/xftfont.c +++ b/src/xftfont.c | |||
| @@ -127,120 +127,18 @@ xftfont_match (struct frame *f, Lisp_Object spec) | |||
| 127 | 127 | ||
| 128 | static FcChar8 ascii_printable[95]; | 128 | static FcChar8 ascii_printable[95]; |
| 129 | 129 | ||
| 130 | static void | ||
| 131 | xftfont_fix_match (FcPattern *pat, FcPattern *match) | ||
| 132 | { | ||
| 133 | /* These values are not used for matching (except antialias), but for | ||
| 134 | rendering, so make sure they are carried over to the match. | ||
| 135 | We also put antialias here because most fonts are antialiased, so | ||
| 136 | the match will have antialias true. */ | ||
| 137 | |||
| 138 | FcBool b = FcTrue; | ||
| 139 | int i; | ||
| 140 | double dpi; | ||
| 141 | |||
| 142 | FcPatternGetBool (pat, FC_ANTIALIAS, 0, &b); | ||
| 143 | if (! b) | ||
| 144 | { | ||
| 145 | FcPatternDel (match, FC_ANTIALIAS); | ||
| 146 | FcPatternAddBool (match, FC_ANTIALIAS, FcFalse); | ||
| 147 | } | ||
| 148 | FcPatternGetBool (pat, FC_HINTING, 0, &b); | ||
| 149 | if (! b) | ||
| 150 | { | ||
| 151 | FcPatternDel (match, FC_HINTING); | ||
| 152 | FcPatternAddBool (match, FC_HINTING, FcFalse); | ||
| 153 | } | ||
| 154 | #ifndef FC_HINT_STYLE | ||
| 155 | # define FC_HINT_STYLE "hintstyle" | ||
| 156 | #endif | ||
| 157 | if (FcResultMatch == FcPatternGetInteger (pat, FC_HINT_STYLE, 0, &i)) | ||
| 158 | { | ||
| 159 | FcPatternDel (match, FC_HINT_STYLE); | ||
| 160 | FcPatternAddInteger (match, FC_HINT_STYLE, i); | ||
| 161 | } | ||
| 162 | #ifndef FC_LCD_FILTER | ||
| 163 | /* Older fontconfig versions don't have FC_LCD_FILTER. */ | ||
| 164 | #define FC_LCD_FILTER "lcdfilter" | ||
| 165 | #endif | ||
| 166 | if (FcResultMatch == FcPatternGetInteger (pat, FC_LCD_FILTER, 0, &i)) | ||
| 167 | { | ||
| 168 | FcPatternDel (match, FC_LCD_FILTER); | ||
| 169 | FcPatternAddInteger (match, FC_LCD_FILTER, i); | ||
| 170 | } | ||
| 171 | if (FcResultMatch == FcPatternGetInteger (pat, FC_RGBA, 0, &i)) | ||
| 172 | { | ||
| 173 | FcPatternDel (match, FC_RGBA); | ||
| 174 | FcPatternAddInteger (match, FC_RGBA, i); | ||
| 175 | } | ||
| 176 | if (FcResultMatch == FcPatternGetDouble (pat, FC_DPI, 0, &dpi)) | ||
| 177 | { | ||
| 178 | FcPatternDel (match, FC_DPI); | ||
| 179 | FcPatternAddDouble (match, FC_DPI, dpi); | ||
| 180 | } | ||
| 181 | } | ||
| 182 | |||
| 183 | static void | ||
| 184 | xftfont_add_rendering_parameters (FcPattern *pat, Lisp_Object entity) | ||
| 185 | { | ||
| 186 | Lisp_Object tail; | ||
| 187 | int ival; | ||
| 188 | |||
| 189 | for (tail = AREF (entity, FONT_EXTRA_INDEX); CONSP (tail); tail = XCDR (tail)) | ||
| 190 | { | ||
| 191 | Lisp_Object key = XCAR (XCAR (tail)); | ||
| 192 | Lisp_Object val = XCDR (XCAR (tail)); | ||
| 193 | |||
| 194 | if (EQ (key, QCantialias)) | ||
| 195 | FcPatternAddBool (pat, FC_ANTIALIAS, NILP (val) ? FcFalse : FcTrue); | ||
| 196 | else if (EQ (key, QChinting)) | ||
| 197 | FcPatternAddBool (pat, FC_HINTING, NILP (val) ? FcFalse : FcTrue); | ||
| 198 | else if (EQ (key, QCautohint)) | ||
| 199 | FcPatternAddBool (pat, FC_AUTOHINT, NILP (val) ? FcFalse : FcTrue); | ||
| 200 | else if (EQ (key, QChintstyle)) | ||
| 201 | { | ||
| 202 | if (FIXNUMP (val)) | ||
| 203 | FcPatternAddInteger (pat, FC_HINT_STYLE, XFIXNUM (val)); | ||
| 204 | else if (SYMBOLP (val) | ||
| 205 | && FcNameConstant (SDATA (SYMBOL_NAME (val)), &ival)) | ||
| 206 | FcPatternAddInteger (pat, FC_HINT_STYLE, ival); | ||
| 207 | } | ||
| 208 | else if (EQ (key, QCrgba)) | ||
| 209 | { | ||
| 210 | if (FIXNUMP (val)) | ||
| 211 | FcPatternAddInteger (pat, FC_RGBA, XFIXNUM (val)); | ||
| 212 | else if (SYMBOLP (val) | ||
| 213 | && FcNameConstant (SDATA (SYMBOL_NAME (val)), &ival)) | ||
| 214 | FcPatternAddInteger (pat, FC_RGBA, ival); | ||
| 215 | } | ||
| 216 | else if (EQ (key, QClcdfilter)) | ||
| 217 | { | ||
| 218 | if (FIXNUMP (val)) | ||
| 219 | FcPatternAddInteger (pat, FC_LCD_FILTER, ival = XFIXNUM (val)); | ||
| 220 | else if (SYMBOLP (val) | ||
| 221 | && FcNameConstant (SDATA (SYMBOL_NAME (val)), &ival)) | ||
| 222 | FcPatternAddInteger (pat, FC_LCD_FILTER, ival); | ||
| 223 | } | ||
| 224 | #ifdef FC_EMBOLDEN | ||
| 225 | else if (EQ (key, QCembolden)) | ||
| 226 | FcPatternAddBool (pat, FC_EMBOLDEN, NILP (val) ? FcFalse : FcTrue); | ||
| 227 | #endif | ||
| 228 | } | ||
| 229 | } | ||
| 230 | |||
| 231 | static Lisp_Object | 130 | static Lisp_Object |
| 232 | xftfont_open (struct frame *f, Lisp_Object entity, int pixel_size) | 131 | xftfont_open (struct frame *f, Lisp_Object entity, int pixel_size) |
| 233 | { | 132 | { |
| 234 | FcResult result; | 133 | FcResult result; |
| 235 | Display *display = FRAME_X_DISPLAY (f); | 134 | Display *display = FRAME_X_DISPLAY (f); |
| 236 | Lisp_Object val, filename, idx, font_object; | 135 | Lisp_Object val, filename, font_object; |
| 237 | FcPattern *pat = NULL, *match; | 136 | FcPattern *pat = NULL, *match; |
| 238 | struct font_info *xftfont_info = NULL; | 137 | struct font_info *xftfont_info = NULL; |
| 239 | struct font *font; | 138 | struct font *font; |
| 240 | double size = 0; | 139 | double size = 0; |
| 241 | XftFont *xftfont = NULL; | 140 | XftFont *xftfont = NULL; |
| 242 | int spacing; | 141 | int spacing; |
| 243 | int i; | ||
| 244 | XGlyphInfo extents; | 142 | XGlyphInfo extents; |
| 245 | FT_Face ft_face; | 143 | FT_Face ft_face; |
| 246 | FcMatrix *matrix; | 144 | FcMatrix *matrix; |
| @@ -250,52 +148,17 @@ xftfont_open (struct frame *f, Lisp_Object entity, int pixel_size) | |||
| 250 | return Qnil; | 148 | return Qnil; |
| 251 | val = XCDR (val); | 149 | val = XCDR (val); |
| 252 | filename = XCAR (val); | 150 | filename = XCAR (val); |
| 253 | idx = XCDR (val); | ||
| 254 | size = XFIXNUM (AREF (entity, FONT_SIZE_INDEX)); | 151 | size = XFIXNUM (AREF (entity, FONT_SIZE_INDEX)); |
| 255 | if (size == 0) | 152 | if (size == 0) |
| 256 | size = pixel_size; | 153 | size = pixel_size; |
| 257 | pat = FcPatternCreate (); | ||
| 258 | FcPatternAddInteger (pat, FC_WEIGHT, FONT_WEIGHT_NUMERIC (entity)); | ||
| 259 | i = FONT_SLANT_NUMERIC (entity) - 100; | ||
| 260 | if (i < 0) i = 0; | ||
| 261 | FcPatternAddInteger (pat, FC_SLANT, i); | ||
| 262 | FcPatternAddInteger (pat, FC_WIDTH, FONT_WIDTH_NUMERIC (entity)); | ||
| 263 | FcPatternAddDouble (pat, FC_PIXEL_SIZE, pixel_size); | ||
| 264 | val = AREF (entity, FONT_FAMILY_INDEX); | ||
| 265 | if (! NILP (val)) | ||
| 266 | FcPatternAddString (pat, FC_FAMILY, (FcChar8 *) SDATA (SYMBOL_NAME (val))); | ||
| 267 | val = AREF (entity, FONT_FOUNDRY_INDEX); | ||
| 268 | if (! NILP (val)) | ||
| 269 | FcPatternAddString (pat, FC_FOUNDRY, (FcChar8 *) SDATA (SYMBOL_NAME (val))); | ||
| 270 | val = AREF (entity, FONT_SPACING_INDEX); | ||
| 271 | if (! NILP (val)) | ||
| 272 | FcPatternAddInteger (pat, FC_SPACING, XFIXNUM (val)); | ||
| 273 | val = AREF (entity, FONT_DPI_INDEX); | ||
| 274 | if (! NILP (val)) | ||
| 275 | { | ||
| 276 | double dbl = XFIXNUM (val); | ||
| 277 | |||
| 278 | FcPatternAddDouble (pat, FC_DPI, dbl); | ||
| 279 | } | ||
| 280 | val = AREF (entity, FONT_AVGWIDTH_INDEX); | ||
| 281 | if (FIXNUMP (val) && XFIXNUM (val) == 0) | ||
| 282 | FcPatternAddBool (pat, FC_SCALABLE, FcTrue); | ||
| 283 | /* This is necessary to identify the exact font (e.g. 10x20.pcf.gz | ||
| 284 | over 10x20-ISO8859-1.pcf.gz). */ | ||
| 285 | FcPatternAddCharSet (pat, FC_CHARSET, ftfont_get_fc_charset (entity)); | ||
| 286 | |||
| 287 | xftfont_add_rendering_parameters (pat, entity); | ||
| 288 | |||
| 289 | FcPatternAddString (pat, FC_FILE, (FcChar8 *) SDATA (filename)); | ||
| 290 | FcPatternAddInteger (pat, FC_INDEX, XFIXNUM (idx)); | ||
| 291 | |||
| 292 | 154 | ||
| 293 | block_input (); | 155 | block_input (); |
| 294 | 156 | ||
| 157 | pat = ftfont_entity_pattern (entity, pixel_size); | ||
| 295 | /* Substitute in values from X resources and XftDefaultSet. */ | 158 | /* Substitute in values from X resources and XftDefaultSet. */ |
| 296 | XftDefaultSubstitute (display, FRAME_X_SCREEN_NUMBER (f), pat); | 159 | XftDefaultSubstitute (display, FRAME_X_SCREEN_NUMBER (f), pat); |
| 297 | match = XftFontMatch (display, FRAME_X_SCREEN_NUMBER (f), pat, &result); | 160 | match = XftFontMatch (display, FRAME_X_SCREEN_NUMBER (f), pat, &result); |
| 298 | xftfont_fix_match (pat, match); | 161 | ftfont_fix_match (pat, match); |
| 299 | 162 | ||
| 300 | FcPatternDestroy (pat); | 163 | FcPatternDestroy (pat); |
| 301 | xftfont = XftFontOpenPattern (display, match); | 164 | xftfont = XftFontOpenPattern (display, match); |
| @@ -695,7 +558,7 @@ xftfont_cached_font_ok (struct frame *f, Lisp_Object font_object, | |||
| 695 | bool ok = false; | 558 | bool ok = false; |
| 696 | int i1, i2, r1, r2; | 559 | int i1, i2, r1, r2; |
| 697 | 560 | ||
| 698 | xftfont_add_rendering_parameters (pat, entity); | 561 | ftfont_add_rendering_parameters (pat, entity); |
| 699 | XftDefaultSubstitute (display, FRAME_X_SCREEN_NUMBER (f), pat); | 562 | XftDefaultSubstitute (display, FRAME_X_SCREEN_NUMBER (f), pat); |
| 700 | 563 | ||
| 701 | r1 = FcPatternGetBool (pat, FC_ANTIALIAS, 0, &b1); | 564 | r1 = FcPatternGetBool (pat, FC_ANTIALIAS, 0, &b1); |
| @@ -768,12 +631,6 @@ void | |||
| 768 | syms_of_xftfont (void) | 631 | syms_of_xftfont (void) |
| 769 | { | 632 | { |
| 770 | DEFSYM (Qxft, "xft"); | 633 | DEFSYM (Qxft, "xft"); |
| 771 | DEFSYM (QChinting, ":hinting"); | ||
| 772 | DEFSYM (QCautohint, ":autohint"); | ||
| 773 | DEFSYM (QChintstyle, ":hintstyle"); | ||
| 774 | DEFSYM (QCrgba, ":rgba"); | ||
| 775 | DEFSYM (QCembolden, ":embolden"); | ||
| 776 | DEFSYM (QClcdfilter, ":lcdfilter"); | ||
| 777 | 634 | ||
| 778 | DEFVAR_BOOL ("xft-font-ascent-descent-override", | 635 | DEFVAR_BOOL ("xft-font-ascent-descent-override", |
| 779 | xft_font_ascent_descent_override, | 636 | xft_font_ascent_descent_override, |