[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
master ecc8870981e: Ascertain font spacing from post table if present
From: |
Po Lu |
Subject: |
master ecc8870981e: Ascertain font spacing from post table if present |
Date: |
Mon, 30 Oct 2023 03:33:45 -0400 (EDT) |
branch: master
commit ecc8870981ef1a802f9504b1d0f261d19ab372b1
Author: Po Lu <luangruo@yahoo.com>
Commit: Po Lu <luangruo@yahoo.com>
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.
---
src/sfnt.c | 78 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
src/sfnt.h | 48 ++++++++++++++++++++++++++++++++++++
src/sfntfont.c | 39 +++++++++++++++++++++--------
3 files changed, 155 insertions(+), 10 deletions(-)
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. */
[Prev in Thread] |
Current Thread |
[Next in Thread] |
- master ecc8870981e: Ascertain font spacing from post table if present,
Po Lu <=