From: Po Lu Date: Mon, 30 Oct 2023 07:32:58 +0000 (+0800) Subject: Ascertain font spacing from post table if present X-Git-Url: http://git.eshelyaron.com/gitweb/?a=commitdiff_plain;h=ecc8870981ef1a802f9504b1d0f261d19ab372b1;p=emacs.git Ascertain font spacing from post table if present * src/sfnt.c (sfnt_table_names): Introduce name of post table. (sfnt_read_post_table): New function. (main): New tests. * src/sfnt.h (struct sfnt_post_table): New struct. * src/sfntfont.c (sfnt_enum_font_1): Read post table, and set spacing from its is_fixed_pitch value. (sfntfont_list_1): Compare spacing between both fonts if supplied in the font spec. (sfntfont_open): Set FONT_FILE_INDEX as well as FONT_FULLNAME_INDEX. --- diff --git a/src/sfnt.c b/src/sfnt.c index 7559055e8c2..8ec19290859 100644 --- a/src/sfnt.c +++ b/src/sfnt.c @@ -158,6 +158,7 @@ static uint32_t sfnt_table_names[] = [SFNT_TABLE_CVAR] = 0x63766172, [SFNT_TABLE_AVAR] = 0x61766172, [SFNT_TABLE_OS_2] = 0x4f532f32, + [SFNT_TABLE_POST] = 0x706f7374, }; /* Swap values from TrueType to system byte order. */ @@ -15474,6 +15475,69 @@ sfnt_read_OS_2_table (int fd, struct sfnt_offset_subtable *subtable) +/* PostScript metadata retrieval. + + TrueType fonts electively incorporate a table of miscellaneous + information concerning such matters as the underline position or + whether the font is fixed pitch. This table also assigns + human-readable names to glyphs, subject to the table format, but + these names are not read by the functions defined below. */ + +/* Read the header of a post table from the given font FD. Refer to + the table directory SUBTABLE for its location. + + Return the post table header if successful, NULL otherwise. */ + +TEST_STATIC struct sfnt_post_table * +sfnt_read_post_table (int fd, struct sfnt_offset_subtable *subtable) +{ + struct sfnt_post_table *post; + struct sfnt_table_directory *directory; + ssize_t rc; + + /* Search for the post table within SUBTABLE. */ + + directory = sfnt_find_table (subtable, SFNT_TABLE_POST); + + if (!directory) + return NULL; + + /* Although the size of the table is affected by its format, this + function is meant to read only its header; guarantee that the + directory is that large. */ + + if (directory->length < sizeof *post) + return NULL; + + /* Seek to the location given in the directory. */ + if (lseek (fd, directory->offset, SEEK_SET) == (off_t) -1) + return NULL; + + post = xmalloc (sizeof *post); + rc = read (fd, post, sizeof *post); + + if (rc == -1 || rc != sizeof *post) + { + xfree (post); + return NULL; + } + + /* Byte swap the data retrieved. */ + sfnt_swap32 (&post->format); + sfnt_swap32 (&post->italic_angle); + sfnt_swap16 (&post->underline_position); + sfnt_swap16 (&post->underline_thickness); + sfnt_swap32 (&post->is_fixed_pitch); + sfnt_swap32 (&post->min_mem_type_42); + sfnt_swap32 (&post->max_mem_type_42); + sfnt_swap32 (&post->min_mem_type_1); + sfnt_swap32 (&post->max_mem_type_1); + + return post; +} + + + #ifdef TEST struct sfnt_test_dcontext @@ -19359,6 +19423,7 @@ main (int argc, char **argv) struct sfnt_avar_table *avar; struct sfnt_cvar_table *cvar; struct sfnt_OS_2_table *OS_2; + struct sfnt_post_table *post; sfnt_fixed scale; char *fancy; int *advances; @@ -19495,6 +19560,7 @@ main (int argc, char **argv) gvar = sfnt_read_gvar_table (fd, font); avar = sfnt_read_avar_table (fd, font); OS_2 = sfnt_read_OS_2_table (fd, font); + post = sfnt_read_post_table (fd, font); cvar = NULL; hmtx = NULL; @@ -19515,6 +19581,17 @@ main (int argc, char **argv) fprintf (stderr, "OS/2 table found!\nach_vendor_id: %.4s\n", OS_2->ach_vendor_id); + if (post) + fprintf (stderr, "post table: format: %g; italic-angle: %g;\n" + "underline_position: %"PRIi16"; underline_thickness: %" + PRIi16";\n" + "is_fixed_pitch: %"PRIu32"\n", + sfnt_coerce_fixed (post->format), + sfnt_coerce_fixed (post->italic_angle), + post->underline_position, + post->underline_thickness, + post->is_fixed_pitch); + if (fvar) { fprintf (stderr, "FVAR table found!\n" @@ -20178,6 +20255,7 @@ main (int argc, char **argv) xfree (avar); xfree (cvar); xfree (OS_2); + xfree (post); return 0; } diff --git a/src/sfnt.h b/src/sfnt.h index 41c1f6f74e8..f6ab6a6eebd 100644 --- a/src/sfnt.h +++ b/src/sfnt.h @@ -53,6 +53,7 @@ enum sfnt_table SFNT_TABLE_CVAR, SFNT_TABLE_AVAR, SFNT_TABLE_OS_2, + SFNT_TABLE_POST, }; #define SFNT_ENDOF(type, field, type1) \ @@ -1413,6 +1414,45 @@ struct sfnt_OS_2_table +/* PostScript metadata. */ + +struct sfnt_post_table +{ + /* Format of this table. This is a fixed point number rather than + an integer. */ + sfnt_fixed format; + + /* Italic angle in degrees. */ + sfnt_fixed italic_angle; + + /* Underline position. */ + sfnt_fword underline_position; + + /* Underline thickness. */ + sfnt_fword underline_thickness; + + /* Whether the font is monospaced. */ + uint32_t is_fixed_pitch; + + /* Minimum memory usage (on a PostScript printer) when a TrueType + font is downloaded as a Type 42 font. */ + uint32_t min_mem_type_42; + + /* Maximum memory usage (on a PostScript printer) when a TrueType + font is downloaded as a Type 42 font. */ + uint32_t max_mem_type_42; + + /* Minimum memory usage (on a PostScript printer) when a TrueType + font is downloaded as a Type 42 font. */ + uint32_t min_mem_type_1; + + /* Maximum memory usage (on a PostScript printer) when a TrueType + font is downloaded as a Type 42 font. */ + uint32_t max_mem_type_1; +}; + + + #define SFNT_CEIL_FIXED(fixed) (((fixed) + 0177777) & 037777600000) #define SFNT_FLOOR_FIXED(fixed) ((fixed) & 037777600000) @@ -1594,6 +1634,14 @@ extern struct sfnt_OS_2_table *sfnt_read_OS_2_table (PROTOTYPE); #undef PROTOTYPE + + +#define PROTOTYPE int, struct sfnt_offset_subtable * + +extern struct sfnt_post_table *sfnt_read_post_table (PROTOTYPE); + +#undef PROTOTYPE + #endif /* TEST */ diff --git a/src/sfntfont.c b/src/sfntfont.c index 35b37396ccd..8d87df477ea 100644 --- a/src/sfntfont.c +++ b/src/sfntfont.c @@ -962,6 +962,7 @@ sfnt_enum_font_1 (int fd, const char *file, struct sfnt_maxp_table *maxp; struct sfnt_fvar_table *fvar; struct sfnt_OS_2_table *OS_2; + struct sfnt_post_table *post; struct sfnt_font_desc temp; Lisp_Object family, style, instance, style1; int i; @@ -1041,12 +1042,25 @@ sfnt_enum_font_1 (int fd, const char *file, if (meta) sfnt_parse_languages (meta, desc); - /* Figure out the spacing. Some fancy test like what Fontconfig - does is probably in order but not really necessary. */ - if (!NILP (Fstring_search (Fdowncase (family), - build_string ("mono"), - Qnil))) - desc->spacing = 100; /* FC_MONO */ + /* Check whether the font claims to be a fixed pitch font and forgo + the rudimentary detection below if so. */ + + post = sfnt_read_post_table (fd, subtables); + + if (post) + { + desc->spacing = (post->is_fixed_pitch ? 100 : 0); + xfree (post); + } + else + { + /* Figure out the spacing. Some fancy test like what Fontconfig + does is probably in order but not really necessary. */ + if (!NILP (Fstring_search (Fdowncase (family), + build_string ("mono"), + Qnil))) + desc->spacing = 100; /* FC_MONO */ + } /* Finally add mac-style flags. Allow them to override styles that have not been found. */ @@ -1654,6 +1668,12 @@ sfntfont_list_1 (struct sfnt_font_desc *desc, Lisp_Object spec, && !sfntfont_registries_compatible_p (tem, desc->registry)) return 0; + /* If the font spacings disagree, reject this font also. */ + + tem = AREF (spec, FONT_SPACING_INDEX); + if (FIXNUMP (tem) && (XFIXNUM (tem) != desc->spacing)) + return 0; + /* Check the style. If DESC is a fixed font, just check once. Otherwise, check each instance. */ @@ -1869,8 +1889,7 @@ sfntfont_desc_to_entity (struct sfnt_font_desc *desc, int instance) /* Size of 0 means the font is scalable. */ ASET (entity, FONT_SIZE_INDEX, make_fixnum (0)); ASET (entity, FONT_AVGWIDTH_INDEX, make_fixnum (0)); - ASET (entity, FONT_SPACING_INDEX, - make_fixnum (desc->spacing)); + ASET (entity, FONT_SPACING_INDEX, make_fixnum (desc->spacing)); if (instance >= 1) { @@ -3227,8 +3246,7 @@ sfntfont_open (struct frame *f, Lisp_Object font_entity, /* Size of 0 means the font is scalable. */ ASET (font_object, FONT_SIZE_INDEX, make_fixnum (0)); ASET (font_object, FONT_AVGWIDTH_INDEX, make_fixnum (0)); - ASET (font_object, FONT_SPACING_INDEX, - make_fixnum (desc->spacing)); + ASET (font_object, FONT_SPACING_INDEX, make_fixnum (desc->spacing)); /* Set the font style. */ @@ -3354,6 +3372,7 @@ sfntfont_open (struct frame *f, Lisp_Object font_entity, /* And set a reasonable full name, namely the name of the font file. */ font->props[FONT_FULLNAME_INDEX] + = font->props[FONT_FILE_INDEX] = DECODE_FILE (build_unibyte_string (desc->path)); /* All done. */