diff options
| author | Khaled Hosny | 2018-06-05 12:13:35 +0200 |
|---|---|---|
| committer | Khaled Hosny | 2018-12-10 00:08:50 +0200 |
| commit | a2bea377c7d7fc39d664802aab7633d325b97927 (patch) | |
| tree | ae890b6d9336f5c0425d87d379fef6cc604c6459 /src | |
| parent | ab93444cbbd06096cdf33a7a76d8e6ee6c37c04a (diff) | |
| download | emacs-a2bea377c7d7fc39d664802aab7633d325b97927.tar.gz emacs-a2bea377c7d7fc39d664802aab7633d325b97927.zip | |
First attempt at HarfBuzz shaping
Barely works, and unoptimized!
Diffstat (limited to 'src')
| -rw-r--r-- | src/ftcrfont.c | 2 | ||||
| -rw-r--r-- | src/ftfont.c | 217 | ||||
| -rw-r--r-- | src/ftfont.h | 5 | ||||
| -rw-r--r-- | src/ftxfont.c | 2 | ||||
| -rw-r--r-- | src/xftfont.c | 4 |
5 files changed, 195 insertions, 35 deletions
diff --git a/src/ftcrfont.c b/src/ftcrfont.c index dc1a389c607..e2f84d44fc2 100644 --- a/src/ftcrfont.c +++ b/src/ftcrfont.c | |||
| @@ -299,7 +299,7 @@ struct font_driver const ftcrfont_driver = | |||
| 299 | #ifdef HAVE_LIBOTF | 299 | #ifdef HAVE_LIBOTF |
| 300 | .otf_capability = ftfont_otf_capability, | 300 | .otf_capability = ftfont_otf_capability, |
| 301 | #endif | 301 | #endif |
| 302 | #if defined HAVE_M17N_FLT && defined HAVE_LIBOTF | 302 | #if defined HAVE_M17N_FLT || defined HAVE_HARFBUZZ |
| 303 | .shape = ftfont_shape, | 303 | .shape = ftfont_shape, |
| 304 | #endif | 304 | #endif |
| 305 | #ifdef HAVE_OTF_GET_VARIATION_GLYPHS | 305 | #ifdef HAVE_OTF_GET_VARIATION_GLYPHS |
diff --git a/src/ftfont.c b/src/ftfont.c index e83eff3ad08..eb7c5d10e15 100644 --- a/src/ftfont.c +++ b/src/ftfont.c | |||
| @@ -1310,6 +1310,24 @@ ftfont_encode_char (struct font *font, int c) | |||
| 1310 | return (code > 0 ? code : FONT_INVALID_CODE); | 1310 | return (code > 0 ? code : FONT_INVALID_CODE); |
| 1311 | } | 1311 | } |
| 1312 | 1312 | ||
| 1313 | static bool | ||
| 1314 | ftfont_glyph_metrics (FT_Face ft_face, int c, int *advance, int *lbearing, | ||
| 1315 | int *rbearing, int *ascent, int *descent) | ||
| 1316 | { | ||
| 1317 | if (FT_Load_Glyph (ft_face, c, FT_LOAD_DEFAULT) == 0) | ||
| 1318 | { | ||
| 1319 | FT_Glyph_Metrics *m = &ft_face->glyph->metrics; | ||
| 1320 | *advance = m->horiAdvance >> 6; | ||
| 1321 | *lbearing = m->horiBearingX >> 6; | ||
| 1322 | *rbearing = (m->horiBearingX + m->width) >> 6; | ||
| 1323 | *ascent = m->horiBearingY >> 6; | ||
| 1324 | *descent = (m->height - m->horiBearingY) >> 6; | ||
| 1325 | return true; | ||
| 1326 | } | ||
| 1327 | |||
| 1328 | return false; | ||
| 1329 | } | ||
| 1330 | |||
| 1313 | void | 1331 | void |
| 1314 | ftfont_text_extents (struct font *font, unsigned int *code, | 1332 | ftfont_text_extents (struct font *font, unsigned int *code, |
| 1315 | int nglyphs, struct font_metrics *metrics) | 1333 | int nglyphs, struct font_metrics *metrics) |
| @@ -1324,29 +1342,27 @@ ftfont_text_extents (struct font *font, unsigned int *code, | |||
| 1324 | 1342 | ||
| 1325 | for (i = 0, first = 1; i < nglyphs; i++) | 1343 | for (i = 0, first = 1; i < nglyphs; i++) |
| 1326 | { | 1344 | { |
| 1327 | if (FT_Load_Glyph (ft_face, code[i], FT_LOAD_DEFAULT) == 0) | 1345 | int advance, lbearing, rbearing, ascent, descent; |
| 1346 | if (ftfont_glyph_metrics (ft_face, code[i], &advance, &lbearing, | ||
| 1347 | &rbearing, &ascent, &descent)) | ||
| 1328 | { | 1348 | { |
| 1329 | FT_Glyph_Metrics *m = &ft_face->glyph->metrics; | ||
| 1330 | |||
| 1331 | if (first) | 1349 | if (first) |
| 1332 | { | 1350 | { |
| 1333 | metrics->lbearing = m->horiBearingX >> 6; | 1351 | metrics->lbearing = lbearing; |
| 1334 | metrics->rbearing = (m->horiBearingX + m->width) >> 6; | 1352 | metrics->rbearing = rbearing; |
| 1335 | metrics->ascent = m->horiBearingY >> 6; | 1353 | metrics->ascent = ascent; |
| 1336 | metrics->descent = (m->height - m->horiBearingY) >> 6; | 1354 | metrics->descent = descent; |
| 1337 | first = 0; | 1355 | first = 0; |
| 1338 | } | 1356 | } |
| 1339 | if (metrics->lbearing > width + (m->horiBearingX >> 6)) | 1357 | if (metrics->lbearing > width + lbearing) |
| 1340 | metrics->lbearing = width + (m->horiBearingX >> 6); | 1358 | metrics->lbearing = width + lbearing; |
| 1341 | if (metrics->rbearing | 1359 | if (metrics->rbearing < width + rbearing) |
| 1342 | < width + ((m->horiBearingX + m->width) >> 6)) | 1360 | metrics->rbearing = width + rbearing; |
| 1343 | metrics->rbearing | 1361 | if (metrics->ascent < ascent) |
| 1344 | = width + ((m->horiBearingX + m->width) >> 6); | 1362 | metrics->ascent = ascent; |
| 1345 | if (metrics->ascent < (m->horiBearingY >> 6)) | 1363 | if (metrics->descent > descent) |
| 1346 | metrics->ascent = m->horiBearingY >> 6; | 1364 | metrics->descent = descent; |
| 1347 | if (metrics->descent > ((m->height - m->horiBearingY) >> 6)) | 1365 | width += advance; |
| 1348 | metrics->descent = (m->height - m->horiBearingY) >> 6; | ||
| 1349 | width += m->horiAdvance >> 6; | ||
| 1350 | } | 1366 | } |
| 1351 | else | 1367 | else |
| 1352 | width += font->space_width; | 1368 | width += font->space_width; |
| @@ -2612,17 +2628,6 @@ ftfont_shape_by_flt (Lisp_Object lgstring, struct font *font, | |||
| 2612 | return make_fixnum (i); | 2628 | return make_fixnum (i); |
| 2613 | } | 2629 | } |
| 2614 | 2630 | ||
| 2615 | Lisp_Object | ||
| 2616 | ftfont_shape (Lisp_Object lgstring) | ||
| 2617 | { | ||
| 2618 | struct font *font = CHECK_FONT_GET_OBJECT (LGSTRING_FONT (lgstring)); | ||
| 2619 | struct ftfont_info *ftfont_info = (struct ftfont_info *) font; | ||
| 2620 | OTF *otf = ftfont_get_otf (ftfont_info); | ||
| 2621 | |||
| 2622 | return ftfont_shape_by_flt (lgstring, font, ftfont_info->ft_size->face, otf, | ||
| 2623 | &ftfont_info->matrix); | ||
| 2624 | } | ||
| 2625 | |||
| 2626 | #endif /* HAVE_M17N_FLT */ | 2631 | #endif /* HAVE_M17N_FLT */ |
| 2627 | 2632 | ||
| 2628 | #ifdef HAVE_OTF_GET_VARIATION_GLYPHS | 2633 | #ifdef HAVE_OTF_GET_VARIATION_GLYPHS |
| @@ -2641,6 +2646,156 @@ ftfont_variation_glyphs (struct font *font, int c, unsigned variations[256]) | |||
| 2641 | #endif /* HAVE_OTF_GET_VARIATION_GLYPHS */ | 2646 | #endif /* HAVE_OTF_GET_VARIATION_GLYPHS */ |
| 2642 | #endif /* HAVE_LIBOTF */ | 2647 | #endif /* HAVE_LIBOTF */ |
| 2643 | 2648 | ||
| 2649 | #ifdef HAVE_HARFBUZZ | ||
| 2650 | |||
| 2651 | #ifndef HAVE_HB_FT_FONT_CREATE_REFERENCED | ||
| 2652 | static void | ||
| 2653 | ft_face_destroy (void *data) | ||
| 2654 | { | ||
| 2655 | FT_Done_Face ((FT_Face) data); | ||
| 2656 | } | ||
| 2657 | #endif | ||
| 2658 | |||
| 2659 | static Lisp_Object | ||
| 2660 | ftfont_shape_by_hb (Lisp_Object lgstring, | ||
| 2661 | FT_Face ft_face, FT_Matrix *matrix) | ||
| 2662 | { | ||
| 2663 | ptrdiff_t glyph_len = 0, text_len = LGSTRING_GLYPH_LEN (lgstring); | ||
| 2664 | ptrdiff_t i; | ||
| 2665 | |||
| 2666 | hb_glyph_info_t *info; | ||
| 2667 | hb_glyph_position_t *pos; | ||
| 2668 | |||
| 2669 | /* FIXME: cache the buffer and the font */ | ||
| 2670 | hb_buffer_t *hb_buffer = hb_buffer_create (); | ||
| 2671 | #ifdef HAVE_HB_FT_FONT_CREATE_REFERENCED | ||
| 2672 | hb_font_t *hb_font = hb_ft_font_create_referenced (ft_face); | ||
| 2673 | #else | ||
| 2674 | FT_Reference_Face (ft_face); | ||
| 2675 | hb_font_t *hb_font = hb_ft_font_create (ft_face, ft_face_destroy); | ||
| 2676 | #endif | ||
| 2677 | |||
| 2678 | hb_buffer_pre_allocate (hb_buffer, text_len); | ||
| 2679 | |||
| 2680 | for (i = 0; i < text_len; i++) | ||
| 2681 | { | ||
| 2682 | Lisp_Object g = LGSTRING_GLYPH (lgstring, i); | ||
| 2683 | int c; | ||
| 2684 | |||
| 2685 | if (NILP (g)) | ||
| 2686 | break; | ||
| 2687 | c = LGLYPH_CHAR (g); | ||
| 2688 | hb_buffer_add (hb_buffer, c, i); | ||
| 2689 | } | ||
| 2690 | |||
| 2691 | text_len = i; | ||
| 2692 | if (!text_len) | ||
| 2693 | goto done; | ||
| 2694 | |||
| 2695 | hb_buffer_set_content_type (hb_buffer, HB_BUFFER_CONTENT_TYPE_UNICODE); | ||
| 2696 | |||
| 2697 | /* FIXME: guess_segment_properties is BAD BAD BAD. | ||
| 2698 | * we need to get these properties with the LGSTRING. */ | ||
| 2699 | #if 1 | ||
| 2700 | hb_buffer_guess_segment_properties (hb_buffer); | ||
| 2701 | #else | ||
| 2702 | hb_buffer_set_direction (hb_buffer, XXX); | ||
| 2703 | hb_buffer_set_script (hb_buffer, XXX); | ||
| 2704 | hb_buffer_set_language (hb_buffer, XXX); | ||
| 2705 | #endif | ||
| 2706 | |||
| 2707 | if (!hb_shape_full (hb_font, hb_buffer, NULL, 0, NULL)) | ||
| 2708 | goto done; | ||
| 2709 | |||
| 2710 | glyph_len = hb_buffer_get_length (hb_buffer); | ||
| 2711 | /* FIXME: number of output glyphs can legitimately be larger than number of | ||
| 2712 | * output characters, what to do in this case? */ | ||
| 2713 | if (glyph_len > LGSTRING_GLYPH_LEN (lgstring)) | ||
| 2714 | return Qnil; | ||
| 2715 | |||
| 2716 | /* FIXME: Emacs wants the buffer reversed, WHY! */ | ||
| 2717 | if (HB_DIRECTION_IS_BACKWARD (hb_buffer_get_direction (hb_buffer))) | ||
| 2718 | hb_buffer_reverse_clusters (hb_buffer); | ||
| 2719 | |||
| 2720 | info = hb_buffer_get_glyph_infos (hb_buffer, NULL); | ||
| 2721 | pos = hb_buffer_get_glyph_positions (hb_buffer, NULL); | ||
| 2722 | for (i = 0; i < glyph_len; i++) | ||
| 2723 | { | ||
| 2724 | Lisp_Object lglyph = LGSTRING_GLYPH (lgstring, i); | ||
| 2725 | EMACS_INT from, to; | ||
| 2726 | int advance = 0, lbearing, rbearing, ascent, descent; | ||
| 2727 | ptrdiff_t j = i; | ||
| 2728 | |||
| 2729 | if (NILP (lglyph)) | ||
| 2730 | { | ||
| 2731 | lglyph = LGLYPH_NEW (); | ||
| 2732 | LGSTRING_SET_GLYPH (lgstring, i, lglyph); | ||
| 2733 | } | ||
| 2734 | |||
| 2735 | from = to = info[i].cluster; | ||
| 2736 | /* FIXME: what does “from” mean here? */ | ||
| 2737 | LGLYPH_SET_FROM (lglyph, from); | ||
| 2738 | |||
| 2739 | /* FIXME: what does “to” mean here? */ | ||
| 2740 | for (j = i; j < glyph_len && info[j].cluster == info[i].cluster; j++) | ||
| 2741 | ; | ||
| 2742 | to = (j == glyph_len) ? text_len - 1 : info[j].cluster - 1; | ||
| 2743 | LGLYPH_SET_TO (lglyph, to); | ||
| 2744 | |||
| 2745 | /* FIXME: is this really needed? Not all glyphs map directly to a single character */ | ||
| 2746 | LGLYPH_SET_CHAR (lglyph, LGLYPH_CHAR (LGSTRING_GLYPH (lgstring, from))); | ||
| 2747 | LGLYPH_SET_CODE (lglyph, info[i].codepoint); | ||
| 2748 | |||
| 2749 | if (ftfont_glyph_metrics (ft_face, info[i].codepoint, &advance, &lbearing, | ||
| 2750 | &rbearing, &ascent, &descent)) | ||
| 2751 | { | ||
| 2752 | LGLYPH_SET_WIDTH (lglyph, advance); | ||
| 2753 | LGLYPH_SET_LBEARING (lglyph, lbearing); | ||
| 2754 | LGLYPH_SET_RBEARING (lglyph, rbearing); | ||
| 2755 | LGLYPH_SET_ASCENT (lglyph, ascent); | ||
| 2756 | LGLYPH_SET_DESCENT (lglyph, descent); | ||
| 2757 | } | ||
| 2758 | |||
| 2759 | if (pos[i].x_offset || pos[i].y_offset || | ||
| 2760 | (pos[i].x_advance >> 6) != advance) | ||
| 2761 | { | ||
| 2762 | Lisp_Object vec = make_uninit_vector (3); | ||
| 2763 | ASET (vec, 0, make_fixnum (pos[i].x_offset >> 6)); | ||
| 2764 | ASET (vec, 1, make_fixnum (-(pos[i].y_offset >> 6))); | ||
| 2765 | ASET (vec, 2, make_fixnum (pos[i].x_advance >> 6)); | ||
| 2766 | LGLYPH_SET_ADJUSTMENT (lglyph, vec); | ||
| 2767 | } | ||
| 2768 | } | ||
| 2769 | |||
| 2770 | done: | ||
| 2771 | hb_font_destroy (hb_font); | ||
| 2772 | hb_buffer_destroy (hb_buffer); | ||
| 2773 | |||
| 2774 | return make_fixnum (glyph_len); | ||
| 2775 | } | ||
| 2776 | |||
| 2777 | #endif /* HAVE_HARFBUZZ */ | ||
| 2778 | |||
| 2779 | #if defined HAVE_M17N_FLT || defined HAVE_HARFBUZZ | ||
| 2780 | |||
| 2781 | Lisp_Object | ||
| 2782 | ftfont_shape (Lisp_Object lgstring) | ||
| 2783 | { | ||
| 2784 | struct font *font = CHECK_FONT_GET_OBJECT (LGSTRING_FONT (lgstring)); | ||
| 2785 | struct ftfont_info *ftfont_info = (struct ftfont_info *) font; | ||
| 2786 | #ifdef HAVE_HARFBUZZ | ||
| 2787 | return ftfont_shape_by_hb (lgstring, ftfont_info->ft_size->face, | ||
| 2788 | &ftfont_info->matrix); | ||
| 2789 | #else | ||
| 2790 | OTF *otf = ftfont_get_otf (ftfont_info); | ||
| 2791 | |||
| 2792 | return ftfont_shape_by_flt (lgstring, font, ftfont_info->ft_size->face, otf, | ||
| 2793 | &ftfont_info->matrix); | ||
| 2794 | #endif | ||
| 2795 | } | ||
| 2796 | |||
| 2797 | #endif /* defined HAVE_M17N_FLT || defined HAVE_HARFBUZZ */ | ||
| 2798 | |||
| 2644 | static const char *const ftfont_booleans [] = { | 2799 | static const char *const ftfont_booleans [] = { |
| 2645 | ":antialias", | 2800 | ":antialias", |
| 2646 | ":hinting", | 2801 | ":hinting", |
| @@ -2695,7 +2850,7 @@ ftfont_filter_properties (Lisp_Object font, Lisp_Object alist) | |||
| 2695 | Lisp_Object | 2850 | Lisp_Object |
| 2696 | ftfont_combining_capability (struct font *font) | 2851 | ftfont_combining_capability (struct font *font) |
| 2697 | { | 2852 | { |
| 2698 | #ifdef HAVE_M17N_FLT | 2853 | #if defined HAVE_M17N_FLT || defined HAVE_HARFBUZZ |
| 2699 | return Qt; | 2854 | return Qt; |
| 2700 | #else | 2855 | #else |
| 2701 | return Qnil; | 2856 | return Qnil; |
| @@ -2720,7 +2875,7 @@ static struct font_driver const ftfont_driver = | |||
| 2720 | #ifdef HAVE_LIBOTF | 2875 | #ifdef HAVE_LIBOTF |
| 2721 | .otf_capability = ftfont_otf_capability, | 2876 | .otf_capability = ftfont_otf_capability, |
| 2722 | #endif | 2877 | #endif |
| 2723 | #if defined HAVE_M17N_FLT && defined HAVE_LIBOTF | 2878 | #if defined HAVE_M17N_FLT || defined HAVE_HARFBUZZ |
| 2724 | .shape = ftfont_shape, | 2879 | .shape = ftfont_shape, |
| 2725 | #endif | 2880 | #endif |
| 2726 | #ifdef HAVE_OTF_GET_VARIATION_GLYPHS | 2881 | #ifdef HAVE_OTF_GET_VARIATION_GLYPHS |
diff --git a/src/ftfont.h b/src/ftfont.h index 4201b2c2d67..d856c106183 100644 --- a/src/ftfont.h +++ b/src/ftfont.h | |||
| @@ -29,6 +29,11 @@ along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */ | |||
| 29 | #include FT_BDF_H | 29 | #include FT_BDF_H |
| 30 | #endif | 30 | #endif |
| 31 | 31 | ||
| 32 | #ifdef HAVE_HARFBUZZ | ||
| 33 | #include <hb.h> | ||
| 34 | #include <hb-ft.h> | ||
| 35 | #endif /* HAVE_HARFBUZZ */ | ||
| 36 | |||
| 32 | #ifdef HAVE_LIBOTF | 37 | #ifdef HAVE_LIBOTF |
| 33 | #include <otf.h> | 38 | #include <otf.h> |
| 34 | #ifdef HAVE_M17N_FLT | 39 | #ifdef HAVE_M17N_FLT |
diff --git a/src/ftxfont.c b/src/ftxfont.c index bf3f1090499..4d4ff6ee0c5 100644 --- a/src/ftxfont.c +++ b/src/ftxfont.c | |||
| @@ -359,7 +359,7 @@ struct font_driver const ftxfont_driver = | |||
| 359 | .otf_capability = ftfont_otf_capability, | 359 | .otf_capability = ftfont_otf_capability, |
| 360 | #endif | 360 | #endif |
| 361 | .end_for_frame = ftxfont_end_for_frame, | 361 | .end_for_frame = ftxfont_end_for_frame, |
| 362 | #if defined HAVE_M17N_FLT && defined HAVE_LIBOTF | 362 | #if defined HAVE_M17N_FLT || defined HAVE_HARFBUZZ |
| 363 | .shape = ftfont_shape, | 363 | .shape = ftfont_shape, |
| 364 | #endif | 364 | #endif |
| 365 | #ifdef HAVE_OTF_GET_VARIATION_GLYPHS | 365 | #ifdef HAVE_OTF_GET_VARIATION_GLYPHS |
diff --git a/src/xftfont.c b/src/xftfont.c index 85df0d857a2..7650de3a779 100644 --- a/src/xftfont.c +++ b/src/xftfont.c | |||
| @@ -659,7 +659,7 @@ xftfont_draw (struct glyph_string *s, int from, int to, int x, int y, | |||
| 659 | return len; | 659 | return len; |
| 660 | } | 660 | } |
| 661 | 661 | ||
| 662 | #if defined HAVE_M17N_FLT && defined HAVE_LIBOTF | 662 | #if defined HAVE_M17N_FLT || defined HAVE_HARFBUZZ |
| 663 | static Lisp_Object | 663 | static Lisp_Object |
| 664 | xftfont_shape (Lisp_Object lgstring) | 664 | xftfont_shape (Lisp_Object lgstring) |
| 665 | { | 665 | { |
| @@ -771,7 +771,7 @@ struct font_driver const xftfont_driver = | |||
| 771 | .otf_capability = ftfont_otf_capability, | 771 | .otf_capability = ftfont_otf_capability, |
| 772 | #endif | 772 | #endif |
| 773 | .end_for_frame = xftfont_end_for_frame, | 773 | .end_for_frame = xftfont_end_for_frame, |
| 774 | #if defined HAVE_M17N_FLT && defined HAVE_LIBOTF | 774 | #if defined HAVE_M17N_FLT || defined HAVE_HARFBUZZ |
| 775 | .shape = xftfont_shape, | 775 | .shape = xftfont_shape, |
| 776 | #endif | 776 | #endif |
| 777 | #ifdef HAVE_OTF_GET_VARIATION_GLYPHS | 777 | #ifdef HAVE_OTF_GET_VARIATION_GLYPHS |