diff options
Diffstat (limited to 'src/font.c')
-rw-r--r-- | src/font.c | 303 |
1 files changed, 274 insertions, 29 deletions
diff --git a/src/font.c b/src/font.c index 7a3206a169a..0a0ac5f8030 100644 --- a/src/font.c +++ b/src/font.c @@ -177,9 +177,35 @@ font_make_entity (void) allocate_pseudovector (VECSIZE (struct font_entity), FONT_ENTITY_MAX, FONT_ENTITY_MAX, PVEC_FONT)); XSETFONT (font_entity, entity); + +#if defined HAVE_ANDROID && !defined ANDROID_STUBIFY + entity->is_android = false; +#endif + return font_entity; } +#ifdef HAVE_ANDROID + +Lisp_Object +font_make_entity_android (int size) +{ + Lisp_Object font_entity; + struct font_entity *entity + = ((struct font_entity *) + allocate_pseudovector (size, FONT_ENTITY_MAX, FONT_ENTITY_MAX, + PVEC_FONT)); + +#if defined HAVE_ANDROID && !defined ANDROID_STUBIFY + entity->is_android = true; +#endif + + XSETFONT (font_entity, entity); + return font_entity; +} + +#endif + /* Create a font-object whose structure size is SIZE. If ENTITY is not nil, copy properties from ENTITY to the font-object. If PIXELSIZE is positive, set the `size' property to PIXELSIZE. */ @@ -226,12 +252,20 @@ font_build_object (int vectorsize, Lisp_Object type, { int len; char name[256]; - Lisp_Object font_object = font_make_object (vectorsize, entity, pixelsize); + char *xlfd_name; + Lisp_Object font_object; + + font_object = font_make_object (vectorsize, entity, pixelsize); ASET (font_object, FONT_TYPE_INDEX, type); - len = font_unparse_xlfd (entity, pixelsize, name, sizeof name); - if (len > 0) - ASET (font_object, FONT_NAME_INDEX, make_string (name, len)); + xlfd_name = font_dynamic_unparse_xlfd (entity, pixelsize); + + if (xlfd_name) + { + ASET (font_object, FONT_NAME_INDEX, build_string (xlfd_name)); + xfree (xlfd_name); + } + len = font_unparse_fcname (entity, pixelsize, name, sizeof name); if (len > 0) ASET (font_object, FONT_FULLNAME_INDEX, make_string (name, len)); @@ -279,7 +313,7 @@ font_intern_prop (const char *str, ptrdiff_t len, bool force_symbol) { if (i == len) return make_fixnum (n); - if (INT_MULTIPLY_WRAPV (n, 10, &n)) + if (ckd_mul (&n, n, 10)) break; } @@ -322,7 +356,7 @@ font_pixel_size (struct frame *f, Lisp_Object spec) if (FIXNUMP (val)) dpi = XFIXNUM (val); else - dpi = FRAME_RES_Y (f); + dpi = FRAME_RES (f); pixel_size = POINT_TO_PIXEL (point_size, dpi); return pixel_size; } @@ -1041,8 +1075,8 @@ font_parse_xlfd_1 (char *name, ptrdiff_t len, Lisp_Object font, int segments) Lisp_Object val; char *p; - if (len > 255 || !len) - /* Maximum XLFD name length is 255. */ + /* Reject empty XLFDs. */ + if (!len) return -1; /* Accept "*-.." as a fully specified XLFD. */ @@ -1250,6 +1284,167 @@ font_parse_xlfd (char *name, ptrdiff_t len, Lisp_Object font) return -1; } +/* Return the XLFD name of FONT as a NULL terminated string, or NULL + if the font is invalid. If FONT is a scalable font, return + PIXEL_SIZE as the XLFD's pixel size in lieu of its + FONT_SIZE_INDEX. */ + +char * +font_dynamic_unparse_xlfd (Lisp_Object font, int pixel_size) +{ + char *p; + const char *f[XLFD_REGISTRY_INDEX + 1]; + Lisp_Object val; + int i, j; + char *name; + USE_SAFE_ALLOCA; + + eassert (FONTP (font)); + + for (i = FONT_FOUNDRY_INDEX, j = XLFD_FOUNDRY_INDEX; i <= FONT_REGISTRY_INDEX; + i++, j++) + { + if (i == FONT_ADSTYLE_INDEX) + j = XLFD_ADSTYLE_INDEX; + else if (i == FONT_REGISTRY_INDEX) + j = XLFD_REGISTRY_INDEX; + val = AREF (font, i); + if (NILP (val)) + { + if (j == XLFD_REGISTRY_INDEX) + f[j] = "*-*"; + else + f[j] = "*"; + } + else + { + if (SYMBOLP (val)) + val = SYMBOL_NAME (val); + if (j == XLFD_REGISTRY_INDEX + && ! strchr (SSDATA (val), '-')) + { + ptrdiff_t alloc = SBYTES (val) + 4; + + /* Change "jisx0208*" and "jisx0208" to "jisx0208*-*". */ + f[j] = p = SAFE_ALLOCA (alloc); + sprintf (p, "%s%s-*", SDATA (val), + &"*"[SDATA (val)[SBYTES (val) - 1] == '*']); + } + else + f[j] = SSDATA (val); + } + } + + for (i = FONT_WEIGHT_INDEX, j = XLFD_WEIGHT_INDEX; i <= FONT_WIDTH_INDEX; + i++, j++) + { + val = font_style_symbolic (font, i, 0); + if (NILP (val)) + f[j] = "*"; + else + { + int c, k, l; + ptrdiff_t alloc; + + val = SYMBOL_NAME (val); + alloc = SBYTES (val) + 1; + f[j] = p = SAFE_ALLOCA (alloc); + /* Copy the name while excluding '-', '?', ',', and '"'. */ + for (k = l = 0; k < alloc; k++) + { + c = SREF (val, k); + if (c != '-' && c != '?' && c != ',' && c != '"') + p[l++] = c; + } + } + } + + val = AREF (font, FONT_SIZE_INDEX); + eassert (NUMBERP (val) || NILP (val)); + char font_size_index_buf[sizeof "-*" + + max (INT_STRLEN_BOUND (EMACS_INT), + 1 + DBL_MAX_10_EXP + 1)]; + if (INTEGERP (val)) + { + intmax_t v; + if (! (integer_to_intmax (val, &v) && 0 < v)) + v = pixel_size; + if (v > 0) + { + f[XLFD_PIXEL_INDEX] = p = font_size_index_buf; + sprintf (p, "%"PRIdMAX"-*", v); + } + else + f[XLFD_PIXEL_INDEX] = "*-*"; + } + else if (FLOATP (val)) + { + double v = XFLOAT_DATA (val) * 10; + f[XLFD_PIXEL_INDEX] = p = font_size_index_buf; + sprintf (p, "*-%.0f", v); + } + else + f[XLFD_PIXEL_INDEX] = "*-*"; + + char dpi_index_buf[sizeof "-" + 2 * INT_STRLEN_BOUND (EMACS_INT)]; + if (FIXNUMP (AREF (font, FONT_DPI_INDEX))) + { + EMACS_INT v = XFIXNUM (AREF (font, FONT_DPI_INDEX)); + f[XLFD_RESX_INDEX] = p = dpi_index_buf; + sprintf (p, "%"pI"d-%"pI"d", v, v); + } + else + f[XLFD_RESX_INDEX] = "*-*"; + + if (FIXNUMP (AREF (font, FONT_SPACING_INDEX))) + { + EMACS_INT spacing = XFIXNUM (AREF (font, FONT_SPACING_INDEX)); + + f[XLFD_SPACING_INDEX] = (spacing <= FONT_SPACING_PROPORTIONAL ? "p" + : spacing <= FONT_SPACING_DUAL ? "d" + : spacing <= FONT_SPACING_MONO ? "m" + : "c"); + } + else + f[XLFD_SPACING_INDEX] = "*"; + + char avgwidth_index_buf[INT_BUFSIZE_BOUND (EMACS_INT)]; + if (FIXNUMP (AREF (font, FONT_AVGWIDTH_INDEX))) + { + f[XLFD_AVGWIDTH_INDEX] = p = avgwidth_index_buf; + sprintf (p, "%"pI"d", XFIXNUM (AREF (font, FONT_AVGWIDTH_INDEX))); + } + else + f[XLFD_AVGWIDTH_INDEX] = "*"; + + /* Allocate a buffer large enough to accommodate the entire + XLFD. */ + + name = xmalloc (strlen (f[XLFD_FOUNDRY_INDEX]) + + strlen (f[XLFD_FAMILY_INDEX]) + + strlen (f[XLFD_WEIGHT_INDEX]) + + strlen (f[XLFD_SLANT_INDEX]) + + strlen (f[XLFD_SWIDTH_INDEX]) + + strlen (f[XLFD_ADSTYLE_INDEX]) + + strlen (f[XLFD_PIXEL_INDEX]) + + strlen (f[XLFD_RESX_INDEX]) + + strlen (f[XLFD_SPACING_INDEX]) + + strlen (f[XLFD_AVGWIDTH_INDEX]) + + strlen (f[XLFD_REGISTRY_INDEX]) + + sizeof "-----------"); + + /* Return the XLFD. */ + + sprintf (name, "-%s-%s-%s-%s-%s-%s-%s-%s-%s-%s-%s", + f[XLFD_FOUNDRY_INDEX], f[XLFD_FAMILY_INDEX], + f[XLFD_WEIGHT_INDEX], f[XLFD_SLANT_INDEX], + f[XLFD_SWIDTH_INDEX], f[XLFD_ADSTYLE_INDEX], + f[XLFD_PIXEL_INDEX], f[XLFD_RESX_INDEX], + f[XLFD_SPACING_INDEX], f[XLFD_AVGWIDTH_INDEX], + f[XLFD_REGISTRY_INDEX]); + SAFE_FREE (); + return name; +} /* Store XLFD name of FONT (font-spec or font-entity) in NAME (NBYTES length), and return the name length. If FONT_SIZE_INDEX of FONT is @@ -1852,8 +2047,12 @@ font_rescale_ratio (Lisp_Object font_entity) if (STRINGP (XCAR (elt))) { if (NILP (name)) - name = Ffont_xlfd_name (font_entity, Qnil); - if (fast_string_match_ignore_case (XCAR (elt), name) >= 0) + name = Ffont_xlfd_name (font_entity, Qnil, Qt); + + /* N.B. that `name' is set to nil if the resulting XLFD + is too long. */ + if (!NILP (name) + && fast_string_match_ignore_case (XCAR (elt), name) >= 0) return XFLOAT_DATA (XCDR (elt)); } else if (FONT_SPEC_P (XCAR (elt))) @@ -2460,12 +2659,30 @@ font_delete_unmatched (Lisp_Object vec, Lisp_Object spec, int size) entity = AREF (vec, i); if (! NILP (Vface_ignored_fonts)) { - char name[256]; + char name[256], *xlfd; ptrdiff_t namelen; namelen = font_unparse_xlfd (entity, 0, name, 256); + if (namelen >= 0) - if (font_is_ignored (name, namelen)) + { + if (font_is_ignored (name, namelen)) continue; + } + else + { + /* The font family or foundry is too long for a 256 + character xlfd to accommodate. */ + + xlfd = font_dynamic_unparse_xlfd (entity, 0); + + if (xlfd && font_is_ignored (xlfd, sizeof (xlfd))) + { + xfree (xlfd); + continue; + } + + xfree (xlfd); + } } if (NILP (spec)) { @@ -2997,7 +3214,7 @@ font_find_for_lface (struct frame *f, Lisp_Object *attrs, Lisp_Object spec, int { double pt = XFIXNUM (attrs[LFACE_HEIGHT_INDEX]); - pixel_size = POINT_TO_PIXEL (pt / 10, FRAME_RES_Y (f)); + pixel_size = POINT_TO_PIXEL (pt / 10, FRAME_RES (f)); if (pixel_size < 1) pixel_size = 1; } @@ -3149,13 +3366,13 @@ font_open_for_lface (struct frame *f, Lisp_Object entity, Lisp_Object *attrs, Li } pt /= 10; - size = POINT_TO_PIXEL (pt, FRAME_RES_Y (f)); + size = POINT_TO_PIXEL (pt, FRAME_RES (f)); #ifdef HAVE_NS if (size == 0) { Lisp_Object ffsize = get_frame_param (f, Qfontsize); size = (NUMBERP (ffsize) - ? POINT_TO_PIXEL (XFLOATINT (ffsize), FRAME_RES_Y (f)) + ? POINT_TO_PIXEL (XFLOATINT (ffsize), FRAME_RES (f)) : 0); } #endif @@ -4056,7 +4273,7 @@ are to be displayed on. If omitted, the selected frame is used. */) if (FIXNUMP (val)) { Lisp_Object font_dpi = AREF (font, FONT_DPI_INDEX); - int dpi = FIXNUMP (font_dpi) ? XFIXNUM (font_dpi) : FRAME_RES_Y (f); + int dpi = FIXNUMP (font_dpi) ? XFIXNUM (font_dpi) : FRAME_RES (f); plist[n++] = QCheight; plist[n++] = make_fixnum (PIXEL_TO_POINT (XFIXNUM (val) * 10, dpi)); } @@ -4209,16 +4426,20 @@ Optional 2nd argument FRAME, if non-nil, specifies the target frame. */) return val; } -DEFUN ("font-xlfd-name", Ffont_xlfd_name, Sfont_xlfd_name, 1, 2, 0, +DEFUN ("font-xlfd-name", Ffont_xlfd_name, Sfont_xlfd_name, 1, 3, 0, doc: /* Return XLFD name of FONT. FONT is a font-spec, font-entity, or font-object. -If the name is too long for XLFD (maximum 255 chars), return nil. + +If the name is too long to be represented as an XLFD (maximum 255 +chars) and LONG_XLFDS is nil, return nil. + If the 2nd optional arg FOLD-WILDCARDS is non-nil, the consecutive wildcards are folded into one. */) - (Lisp_Object font, Lisp_Object fold_wildcards) + (Lisp_Object font, Lisp_Object fold_wildcards, Lisp_Object long_xlfds) { - char name[256]; + char name_buffer[256], *name; int namelen, pixel_size = 0; + Lisp_Object string; CHECK_FONT (font); @@ -4231,15 +4452,32 @@ the consecutive wildcards are folded into one. */) { if (NILP (fold_wildcards)) return font_name; + name = name_buffer; lispstpcpy (name, font_name); namelen = SBYTES (font_name); goto done; } pixel_size = XFONT_OBJECT (font)->pixel_size; } - namelen = font_unparse_xlfd (font, pixel_size, name, 256); - if (namelen < 0) - return Qnil; + + if (NILP (long_xlfds)) + { + name = name_buffer; + namelen = font_unparse_xlfd (font, pixel_size, name, 256); + if (namelen < 0) + return Qnil; + } + else + { + /* Dynamically allocate the XLFD. */ + name = font_dynamic_unparse_xlfd (font, pixel_size); + + if (!name) + return Qnil; + + namelen = strlen (name); + } + done: if (! NILP (fold_wildcards)) { @@ -4253,7 +4491,14 @@ the consecutive wildcards are folded into one. */) } } - return make_string (name, namelen); + /* If NAME is dynamically allocated, free it. */ + + string = make_string (name, namelen); + + if (name != name_buffer) + xfree (name); + + return string; } void @@ -4960,7 +5205,7 @@ DEFUN ("open-font", Fopen_font, Sopen_font, 1, 3, 0, { CHECK_NUMBER (size); if (FLOATP (size)) - isize = POINT_TO_PIXEL (XFLOAT_DATA (size), FRAME_RES_Y (f)); + isize = POINT_TO_PIXEL (XFLOAT_DATA (size), FRAME_RES (f)); else if (! integer_to_intmax (size, &isize)) args_out_of_range (font_entity, size); if (! (INT_MIN <= isize && isize <= INT_MAX)) @@ -5457,7 +5702,7 @@ font_add_log (const char *action, Lisp_Object arg, Lisp_Object result) Lisp_Object tail, elt; AUTO_STRING (equal, "="); - val = Ffont_xlfd_name (arg, Qt); + val = Ffont_xlfd_name (arg, Qt, Qt); for (tail = AREF (arg, FONT_EXTRA_INDEX); CONSP (tail); tail = XCDR (tail)) { @@ -5485,7 +5730,7 @@ font_add_log (const char *action, Lisp_Object arg, Lisp_Object result) result = font_vconcat_entity_vectors (result); if (FONTP (result)) { - val = Ffont_xlfd_name (result, Qt); + val = Ffont_xlfd_name (result, Qt, Qt); if (! FONT_SPEC_P (result)) { AUTO_STRING (colon, ":"); @@ -5502,7 +5747,7 @@ font_add_log (const char *action, Lisp_Object arg, Lisp_Object result) { val = XCAR (tail); if (FONTP (val)) - val = Ffont_xlfd_name (val, Qt); + val = Ffont_xlfd_name (val, Qt, Qt); XSETCAR (tail, val); } } @@ -5513,7 +5758,7 @@ font_add_log (const char *action, Lisp_Object arg, Lisp_Object result) { val = AREF (result, i); if (FONTP (val)) - val = Ffont_xlfd_name (val, Qt); + val = Ffont_xlfd_name (val, Qt, Qt); ASET (result, i, val); } } |