aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorYAMAMOTO Mitsuharu2019-06-02 13:02:09 +0900
committerYAMAMOTO Mitsuharu2019-06-02 13:17:11 +0900
commitab1d5d400536f83a43b65c9bcc347a900f6008b4 (patch)
treeb0a4ee4d142be9b3c171f933c43233ae303d6c0f /src
parentfd380b4f5503a1d7b9d98fa4e69be61e93b52758 (diff)
downloademacs-ab1d5d400536f83a43b65c9bcc347a900f6008b4.tar.gz
emacs-ab1d5d400536f83a43b65c9bcc347a900f6008b4.zip
Make fthbfont and derivatives use common HarfBuzz code in hbfont.c
* src/font.h (fthbfont_shape, fthbfont_combining_capability) [HAVE_HARFBUZZ]: Remove prototypes. * src/ftfont.c: Don't include math.h. (uni_combining, uni_general, uni_mirroring, get_hb_unicode_funcs) (fthbfont_shape_by_hb, fthbfont_combining_capability, fthbfont_shape) [HAVE_HARFBUZZ]: Remove functions. * src/ftfont.c (syms_of_ftfont_for_pdumper) [HAVE_HARFBUZZ]: * src/xftfont.c (syms_of_xftfont_for_pdumper) [HAVE_HARFBUZZ]: * src/ftcrfont.c (syms_of_ftcrfont_for_pdumper) [HAVE_HARFBUZZ]: Use hbfont_shape and hbfont_combining_capability instead of fthbfont_shape and fthbfont_combining_capability, respectively.
Diffstat (limited to 'src')
-rw-r--r--src/font.h2
-rw-r--r--src/ftcrfont.c4
-rw-r--r--src/ftfont.c295
-rw-r--r--src/xftfont.c4
4 files changed, 6 insertions, 299 deletions
diff --git a/src/font.h b/src/font.h
index 99b95836d7a..1f35744642b 100644
--- a/src/font.h
+++ b/src/font.h
@@ -928,9 +928,7 @@ extern void ftfont_filter_properties (Lisp_Object, Lisp_Object);
928extern void ftfont_text_extents (struct font *, const unsigned *, int, 928extern void ftfont_text_extents (struct font *, const unsigned *, int,
929 struct font_metrics *); 929 struct font_metrics *);
930#ifdef HAVE_HARFBUZZ 930#ifdef HAVE_HARFBUZZ
931extern Lisp_Object fthbfont_combining_capability (struct font *);
932extern hb_font_t *fthbfont_begin_hb_font (struct font *, double *); 931extern hb_font_t *fthbfont_begin_hb_font (struct font *, double *);
933extern Lisp_Object fthbfont_shape (Lisp_Object, Lisp_Object);
934#endif /* HAVE_HARFBUZZ */ 932#endif /* HAVE_HARFBUZZ */
935extern void syms_of_ftfont (void); 933extern void syms_of_ftfont (void);
936#endif /* HAVE_FREETYPE */ 934#endif /* HAVE_FREETYPE */
diff --git a/src/ftcrfont.c b/src/ftcrfont.c
index 79bf68141dc..0c3b74ff289 100644
--- a/src/ftcrfont.c
+++ b/src/ftcrfont.c
@@ -612,8 +612,8 @@ syms_of_ftcrfont_for_pdumper (void)
612 ftcrhbfont_driver.type = Qftcrhb; 612 ftcrhbfont_driver.type = Qftcrhb;
613 ftcrhbfont_driver.list = ftcrhbfont_list; 613 ftcrhbfont_driver.list = ftcrhbfont_list;
614 ftcrhbfont_driver.match = ftcrhbfont_match; 614 ftcrhbfont_driver.match = ftcrhbfont_match;
615 ftcrhbfont_driver.shape = fthbfont_shape; 615 ftcrhbfont_driver.shape = hbfont_shape;
616 ftcrhbfont_driver.combining_capability = fthbfont_combining_capability; 616 ftcrhbfont_driver.combining_capability = hbfont_combining_capability;
617 ftcrhbfont_driver.begin_hb_font = ftcrhbfont_begin_hb_font; 617 ftcrhbfont_driver.begin_hb_font = ftcrhbfont_begin_hb_font;
618 ftcrhbfont_driver.end_hb_font = ftcrhbfont_end_hb_font; 618 ftcrhbfont_driver.end_hb_font = ftcrhbfont_end_hb_font;
619 register_font_driver (&ftcrhbfont_driver, NULL); 619 register_font_driver (&ftcrhbfont_driver, NULL);
diff --git a/src/ftfont.c b/src/ftfont.c
index 5694c49aaf9..97ab4d0e377 100644
--- a/src/ftfont.c
+++ b/src/ftfont.c
@@ -21,7 +21,6 @@ along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */
21 21
22#include <config.h> 22#include <config.h>
23#include <stdio.h> 23#include <stdio.h>
24#include <math.h>
25#include <fontconfig/fontconfig.h> 24#include <fontconfig/fontconfig.h>
26#include <fontconfig/fcfreetype.h> 25#include <fontconfig/fcfreetype.h>
27 26
@@ -2851,296 +2850,6 @@ fthbfont_begin_hb_font (struct font *font, double *position_unit)
2851 return ftfont_info->hb_font; 2850 return ftfont_info->hb_font;
2852} 2851}
2853 2852
2854static hb_unicode_combining_class_t
2855uni_combining (hb_unicode_funcs_t *funcs, hb_codepoint_t ch, void *user_data)
2856{
2857 Lisp_Object table, combining;
2858
2859 /* FIXME: Is it efficient to load the table each time? */
2860 table = Funicode_property_table_internal (intern ("canonical-combining-class"));
2861 combining = Fget_unicode_property_internal (table, make_fixnum (ch));
2862
2863 if (INTEGERP (combining))
2864 return (hb_unicode_combining_class_t) XFIXNUM (combining);
2865
2866 return HB_UNICODE_COMBINING_CLASS_NOT_REORDERED;
2867}
2868
2869static hb_unicode_general_category_t
2870uni_general (hb_unicode_funcs_t *funcs, hb_codepoint_t ch, void *user_data)
2871{
2872 Lisp_Object category = CHAR_TABLE_REF (Vunicode_category_table, ch);
2873
2874 if (INTEGERP (category))
2875 {
2876 switch (XFIXNUM (category))
2877 {
2878 case UNICODE_CATEGORY_Cc:
2879 return HB_UNICODE_GENERAL_CATEGORY_CONTROL;
2880 case UNICODE_CATEGORY_Cf:
2881 return HB_UNICODE_GENERAL_CATEGORY_FORMAT;
2882 case UNICODE_CATEGORY_Cn:
2883 return HB_UNICODE_GENERAL_CATEGORY_UNASSIGNED;
2884 case UNICODE_CATEGORY_Co:
2885 return HB_UNICODE_GENERAL_CATEGORY_PRIVATE_USE;
2886 case UNICODE_CATEGORY_Cs:
2887 return HB_UNICODE_GENERAL_CATEGORY_SURROGATE;
2888 case UNICODE_CATEGORY_Ll:
2889 return HB_UNICODE_GENERAL_CATEGORY_LOWERCASE_LETTER;
2890 case UNICODE_CATEGORY_Lm:
2891 return HB_UNICODE_GENERAL_CATEGORY_MODIFIER_LETTER;
2892 case UNICODE_CATEGORY_Lo:
2893 return HB_UNICODE_GENERAL_CATEGORY_OTHER_LETTER;
2894 case UNICODE_CATEGORY_Lt:
2895 return HB_UNICODE_GENERAL_CATEGORY_TITLECASE_LETTER;
2896 case UNICODE_CATEGORY_Lu:
2897 return HB_UNICODE_GENERAL_CATEGORY_UPPERCASE_LETTER;
2898 case UNICODE_CATEGORY_Mc:
2899 return HB_UNICODE_GENERAL_CATEGORY_SPACING_MARK;
2900 case UNICODE_CATEGORY_Me:
2901 return HB_UNICODE_GENERAL_CATEGORY_ENCLOSING_MARK;
2902 case UNICODE_CATEGORY_Mn:
2903 return HB_UNICODE_GENERAL_CATEGORY_NON_SPACING_MARK;
2904 case UNICODE_CATEGORY_Nd:
2905 return HB_UNICODE_GENERAL_CATEGORY_DECIMAL_NUMBER;
2906 case UNICODE_CATEGORY_Nl:
2907 return HB_UNICODE_GENERAL_CATEGORY_LETTER_NUMBER;
2908 case UNICODE_CATEGORY_No:
2909 return HB_UNICODE_GENERAL_CATEGORY_OTHER_NUMBER;
2910 case UNICODE_CATEGORY_Pc:
2911 return HB_UNICODE_GENERAL_CATEGORY_CONNECT_PUNCTUATION;
2912 case UNICODE_CATEGORY_Pd:
2913 return HB_UNICODE_GENERAL_CATEGORY_DASH_PUNCTUATION;
2914 case UNICODE_CATEGORY_Pe:
2915 return HB_UNICODE_GENERAL_CATEGORY_CLOSE_PUNCTUATION;
2916 case UNICODE_CATEGORY_Pf:
2917 return HB_UNICODE_GENERAL_CATEGORY_FINAL_PUNCTUATION;
2918 case UNICODE_CATEGORY_Pi:
2919 return HB_UNICODE_GENERAL_CATEGORY_INITIAL_PUNCTUATION;
2920 case UNICODE_CATEGORY_Po:
2921 return HB_UNICODE_GENERAL_CATEGORY_OTHER_PUNCTUATION;
2922 case UNICODE_CATEGORY_Ps:
2923 return HB_UNICODE_GENERAL_CATEGORY_OPEN_PUNCTUATION;
2924 case UNICODE_CATEGORY_Sc:
2925 return HB_UNICODE_GENERAL_CATEGORY_CURRENCY_SYMBOL;
2926 case UNICODE_CATEGORY_Sk:
2927 return HB_UNICODE_GENERAL_CATEGORY_MODIFIER_SYMBOL;
2928 case UNICODE_CATEGORY_Sm:
2929 return HB_UNICODE_GENERAL_CATEGORY_MATH_SYMBOL;
2930 case UNICODE_CATEGORY_So:
2931 return HB_UNICODE_GENERAL_CATEGORY_OTHER_SYMBOL;
2932 case UNICODE_CATEGORY_Zl:
2933 return HB_UNICODE_GENERAL_CATEGORY_LINE_SEPARATOR;
2934 case UNICODE_CATEGORY_Zp:
2935 return HB_UNICODE_GENERAL_CATEGORY_PARAGRAPH_SEPARATOR;
2936 case UNICODE_CATEGORY_Zs:
2937 return HB_UNICODE_GENERAL_CATEGORY_SPACE_SEPARATOR;
2938 case UNICODE_CATEGORY_UNKNOWN:
2939 return HB_UNICODE_GENERAL_CATEGORY_UNASSIGNED;
2940 }
2941 }
2942
2943 return HB_UNICODE_GENERAL_CATEGORY_UNASSIGNED;
2944}
2945
2946static hb_codepoint_t
2947uni_mirroring (hb_unicode_funcs_t *funcs, hb_codepoint_t ch, void *user_data)
2948{
2949 return bidi_mirror_char (ch);
2950}
2951
2952static hb_unicode_funcs_t *
2953get_hb_unicode_funcs (void)
2954{
2955 /* Subclass HarfBuzz's default Unicode functions and override functions that
2956 * use data Emacs can provide. This way changing Emacs data is reflected in
2957 * the shaped output. */
2958 hb_unicode_funcs_t *funcs = hb_unicode_funcs_create (hb_unicode_funcs_get_default ());
2959
2960 hb_unicode_funcs_set_combining_class_func (funcs, uni_combining, NULL, NULL);
2961 hb_unicode_funcs_set_general_category_func (funcs, uni_general, NULL, NULL);
2962 hb_unicode_funcs_set_mirroring_func (funcs, uni_mirroring, NULL, NULL);
2963
2964 /* Use default implmentation for Unicode composition/decomposition, we might
2965 * want to revisit this later.
2966 hb_unicode_funcs_set_compose_func (funcs, uni_compose, NULL, NULL);
2967 hb_unicode_funcs_set_decompose_func (funcs, uni_decompose, NULL, NULL);
2968 */
2969
2970 /* Emacs own script mapping for characters differs from Unicode, so we want
2971 * to keep the default HarfBuzz's implementation here.
2972 hb_unicode_funcs_set_script_func (funcs, uni_script, NULL, NULL);
2973 */
2974
2975 return funcs;
2976}
2977
2978static Lisp_Object
2979fthbfont_shape_by_hb (Lisp_Object lgstring, struct font *font,
2980 Lisp_Object direction)
2981{
2982 ptrdiff_t glyph_len = 0, text_len = LGSTRING_GLYPH_LEN (lgstring);
2983 ptrdiff_t i;
2984
2985 hb_glyph_info_t *info;
2986 hb_glyph_position_t *pos;
2987
2988 /* Cache the HarfBuzz buffer for better performance and less allocations.
2989 * We intentionally never destroy the buffer. */
2990 static hb_buffer_t *hb_buffer = NULL;
2991 if (! hb_buffer)
2992 {
2993 hb_buffer = hb_buffer_create ();
2994 hb_unicode_funcs_t* ufuncs = get_hb_unicode_funcs();
2995 hb_buffer_set_unicode_funcs(hb_buffer, ufuncs);
2996 }
2997
2998 hb_buffer_clear_contents (hb_buffer);
2999 hb_buffer_pre_allocate (hb_buffer, text_len);
3000
3001 for (i = 0; i < text_len; i++)
3002 {
3003 Lisp_Object g = LGSTRING_GLYPH (lgstring, i);
3004 int c;
3005
3006 if (NILP (g))
3007 break;
3008 c = LGLYPH_CHAR (g);
3009 hb_buffer_add (hb_buffer, c, i);
3010 }
3011
3012 text_len = i;
3013 if (!text_len)
3014 return Qnil;
3015
3016 hb_buffer_set_content_type (hb_buffer, HB_BUFFER_CONTENT_TYPE_UNICODE);
3017 hb_buffer_set_cluster_level (hb_buffer, HB_BUFFER_CLUSTER_LEVEL_MONOTONE_CHARACTERS);
3018
3019 /* If the caller didn't provide a meaningful DIRECTION, default to L2R. */
3020 hb_direction_t dir = HB_DIRECTION_LTR;
3021 if (EQ (direction, QL2R))
3022 dir = HB_DIRECTION_LTR;
3023 else if (EQ (direction, QR2L))
3024 dir = HB_DIRECTION_RTL;
3025 hb_buffer_set_direction (hb_buffer, dir);
3026
3027 /* Leave the script determination to HarfBuzz, until Emacs has a
3028 better idea of the script of LGSTRING. FIXME. */
3029#if 0
3030 hb_buffer_set_script (hb_buffer, XXX);
3031#endif
3032
3033 /* FIXME: This can only handle the single global language, which
3034 normally comes from the locale. In addition, if
3035 current-iso639-language is a list, we arbitrarily use the first
3036 one. We should instead have a notion of the language of the text
3037 being shaped. */
3038 Lisp_Object lang = Vcurrent_iso639_language;
3039 if (CONSP (Vcurrent_iso639_language))
3040 lang = XCAR (Vcurrent_iso639_language);
3041 if (SYMBOLP (lang))
3042 {
3043 Lisp_Object lang_str = SYMBOL_NAME (lang);
3044 hb_buffer_set_language (hb_buffer,
3045 hb_language_from_string (SSDATA (lang_str),
3046 SBYTES (lang_str)));
3047 }
3048
3049 /* Guess the default properties for when they cannot be determined
3050 above. FIXME: drop once script handling is fixed above. */
3051 hb_buffer_guess_segment_properties (hb_buffer);
3052
3053 double position_unit;
3054 hb_font_t *hb_font = font->driver->begin_hb_font (font, &position_unit);
3055 if (!hb_font)
3056 return make_fixnum (0);
3057
3058 hb_bool_t success = hb_shape_full (hb_font, hb_buffer, NULL, 0, NULL);
3059 if (font->driver->end_hb_font)
3060 font->driver->end_hb_font (font, hb_font);
3061 if (!success)
3062 return Qnil;
3063
3064 glyph_len = hb_buffer_get_length (hb_buffer);
3065 /* FIXME: can't we just grew the lgstring in this case? Givving up is an
3066 * overly heavy handed solution. */
3067 if (glyph_len > LGSTRING_GLYPH_LEN (lgstring))
3068 return Qnil;
3069
3070 /* Somewhere up the pipeline wants the glyphs in logical order, while keeping
3071 * clusters in visual order. I don't know where exactly, but lets satisfy
3072 * that. */
3073 if (HB_DIRECTION_IS_BACKWARD (hb_buffer_get_direction (hb_buffer)))
3074 hb_buffer_reverse_clusters (hb_buffer);
3075
3076 info = hb_buffer_get_glyph_infos (hb_buffer, NULL);
3077 pos = hb_buffer_get_glyph_positions (hb_buffer, NULL);
3078 for (i = 0; i < glyph_len; i++)
3079 {
3080 Lisp_Object lglyph = LGSTRING_GLYPH (lgstring, i);
3081 EMACS_INT from, to;
3082 struct font_metrics metrics = {.width = 0};
3083 int xoff, yoff, wadjust;
3084 ptrdiff_t j = i;
3085
3086 if (NILP (lglyph))
3087 {
3088 lglyph = LGLYPH_NEW ();
3089 LGSTRING_SET_GLYPH (lgstring, i, lglyph);
3090 }
3091
3092 from = to = info[i].cluster;
3093 /* FIXME: what does “from” mean here? */
3094 LGLYPH_SET_FROM (lglyph, from);
3095
3096 /* FIXME: what does “to” mean here? */
3097 for (j = i; j < glyph_len && info[j].cluster == info[i].cluster; j++)
3098 ;
3099 to = (j == glyph_len) ? text_len - 1 : info[j].cluster - 1;
3100 LGLYPH_SET_TO (lglyph, to);
3101
3102 /* FIXME: is this really needed? Not all glyphs map directly to a single character */
3103 LGLYPH_SET_CHAR (lglyph, LGLYPH_CHAR (LGSTRING_GLYPH (lgstring, from)));
3104 LGLYPH_SET_CODE (lglyph, info[i].codepoint);
3105
3106 unsigned code = info[i].codepoint;
3107 font->driver->text_extents (font, &code, 1, &metrics);
3108 LGLYPH_SET_WIDTH (lglyph, metrics.width);
3109 LGLYPH_SET_LBEARING (lglyph, metrics.lbearing);
3110 LGLYPH_SET_RBEARING (lglyph, metrics.rbearing);
3111 LGLYPH_SET_ASCENT (lglyph, metrics.ascent);
3112 LGLYPH_SET_DESCENT (lglyph, metrics.descent);
3113
3114 xoff = lround (pos[i].x_offset * position_unit);
3115 yoff = - lround (pos[i].y_offset * position_unit);
3116 wadjust = lround (pos[i].x_advance * position_unit);
3117 if (xoff || yoff || wadjust != metrics.width)
3118 {
3119 Lisp_Object vec = make_uninit_vector (3);
3120 ASET (vec, 0, make_fixnum (xoff));
3121 ASET (vec, 1, make_fixnum (yoff));
3122 ASET (vec, 2, make_fixnum (wadjust));
3123 LGLYPH_SET_ADJUSTMENT (lglyph, vec);
3124 }
3125 }
3126
3127 return make_fixnum (glyph_len);
3128}
3129
3130Lisp_Object
3131fthbfont_combining_capability (struct font *font)
3132{
3133 return Qt;
3134}
3135
3136Lisp_Object
3137fthbfont_shape (Lisp_Object lgstring, Lisp_Object direction)
3138{
3139 struct font *font = CHECK_FONT_GET_OBJECT (LGSTRING_FONT (lgstring));
3140
3141 return fthbfont_shape_by_hb (lgstring, font, direction);
3142}
3143
3144#endif /* HAVE_HARFBUZZ */ 2853#endif /* HAVE_HARFBUZZ */
3145 2854
3146static const char *const ftfont_booleans [] = { 2855static const char *const ftfont_booleans [] = {
@@ -3282,8 +2991,8 @@ syms_of_ftfont_for_pdumper (void)
3282#ifdef HAVE_HARFBUZZ 2991#ifdef HAVE_HARFBUZZ
3283 fthbfont_driver = ftfont_driver; 2992 fthbfont_driver = ftfont_driver;
3284 fthbfont_driver.type = Qfreetypehb; 2993 fthbfont_driver.type = Qfreetypehb;
3285 fthbfont_driver.shape = fthbfont_shape; 2994 fthbfont_driver.shape = hbfont_shape;
3286 fthbfont_driver.combining_capability = fthbfont_combining_capability; 2995 fthbfont_driver.combining_capability = hbfont_combining_capability;
3287 fthbfont_driver.begin_hb_font = fthbfont_begin_hb_font; 2996 fthbfont_driver.begin_hb_font = fthbfont_begin_hb_font;
3288 register_font_driver (&fthbfont_driver, NULL); 2997 register_font_driver (&fthbfont_driver, NULL);
3289#endif /* HAVE_HARFBUZZ */ 2998#endif /* HAVE_HARFBUZZ */
diff --git a/src/xftfont.c b/src/xftfont.c
index 08e4edb535a..c1b93b76f57 100644
--- a/src/xftfont.c
+++ b/src/xftfont.c
@@ -699,8 +699,8 @@ syms_of_xftfont_for_pdumper (void)
699 xfthbfont_driver.type = Qxfthb; 699 xfthbfont_driver.type = Qxfthb;
700 xfthbfont_driver.list = xfthbfont_list; 700 xfthbfont_driver.list = xfthbfont_list;
701 xfthbfont_driver.match = xfthbfont_match; 701 xfthbfont_driver.match = xfthbfont_match;
702 xfthbfont_driver.shape = fthbfont_shape; 702 xfthbfont_driver.shape = hbfont_shape;
703 xfthbfont_driver.combining_capability = fthbfont_combining_capability; 703 xfthbfont_driver.combining_capability = hbfont_combining_capability;
704 xfthbfont_driver.begin_hb_font = xfthbfont_begin_hb_font; 704 xfthbfont_driver.begin_hb_font = xfthbfont_begin_hb_font;
705 xfthbfont_driver.end_hb_font = xfthbfont_end_hb_font; 705 xfthbfont_driver.end_hb_font = xfthbfont_end_hb_font;
706 register_font_driver (&xfthbfont_driver, NULL); 706 register_font_driver (&xfthbfont_driver, NULL);