aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorKhaled Hosny2018-06-05 12:13:35 +0200
committerKhaled Hosny2018-12-10 00:08:50 +0200
commita2bea377c7d7fc39d664802aab7633d325b97927 (patch)
treeae890b6d9336f5c0425d87d379fef6cc604c6459 /src
parentab93444cbbd06096cdf33a7a76d8e6ee6c37c04a (diff)
downloademacs-a2bea377c7d7fc39d664802aab7633d325b97927.tar.gz
emacs-a2bea377c7d7fc39d664802aab7633d325b97927.zip
First attempt at HarfBuzz shaping
Barely works, and unoptimized!
Diffstat (limited to 'src')
-rw-r--r--src/ftcrfont.c2
-rw-r--r--src/ftfont.c217
-rw-r--r--src/ftfont.h5
-rw-r--r--src/ftxfont.c2
-rw-r--r--src/xftfont.c4
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
1313static bool
1314ftfont_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
1313void 1331void
1314ftfont_text_extents (struct font *font, unsigned int *code, 1332ftfont_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
2615Lisp_Object
2616ftfont_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
2652static void
2653ft_face_destroy (void *data)
2654{
2655 FT_Done_Face ((FT_Face) data);
2656}
2657#endif
2658
2659static Lisp_Object
2660ftfont_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
2770done:
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
2781Lisp_Object
2782ftfont_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
2644static const char *const ftfont_booleans [] = { 2799static 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)
2695Lisp_Object 2850Lisp_Object
2696ftfont_combining_capability (struct font *font) 2851ftfont_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
663static Lisp_Object 663static Lisp_Object
664xftfont_shape (Lisp_Object lgstring) 664xftfont_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