Extract font foundry metadata from the OS/2 table
* src/sfnt.c (sfnt_table_names): Append an entry for OS/2 tables. (sfnt_read_OS_2_table): New function. (main): Introduce a new test for the OS/2 table reader. * src/sfnt.h (sfnt_read_OS_2_table): New declaration. * src/sfntfont.c (sfnt_decode_foundry_name): Delete function. (sfnt_enum_font_1): Read the font's OS/2 table and extract the foundry name from there. Use `misc' if absent. (sfntfont_desc_to_entity, sfntfont_open): Cease interning desc->designer, as that is now a symbol. (syms_of_sfntfont) <Qmisc>: New defsym Qmisc. (bug#65865)
This commit is contained in:
parent
e25ad6e2a3
commit
c465740273
3 changed files with 237 additions and 37 deletions
112
src/sfnt.c
112
src/sfnt.c
|
@ -157,6 +157,7 @@ static uint32_t sfnt_table_names[] =
|
|||
[SFNT_TABLE_GVAR] = 0x67766172,
|
||||
[SFNT_TABLE_CVAR] = 0x63766172,
|
||||
[SFNT_TABLE_AVAR] = 0x61766172,
|
||||
[SFNT_TABLE_OS_2] = 0x4f532f32,
|
||||
};
|
||||
|
||||
/* Swap values from TrueType to system byte order. */
|
||||
|
@ -15296,6 +15297,110 @@ sfnt_vary_interpreter (struct sfnt_interpreter *interpreter,
|
|||
|
||||
|
||||
|
||||
/* OS/2 metadata retrieval.
|
||||
|
||||
A font's `OS/2' table incorporates some miscellaneous information
|
||||
that is consulted by the font scaler on MS-Windows. Emacs requires
|
||||
one fragment of this information: the font foundry name. */
|
||||
|
||||
/* Read an OS/2 table from the given font FD. Use the table directory
|
||||
provided in SUBTABLE.
|
||||
|
||||
Return the OS/2 table if successful, NULL otherwise. */
|
||||
|
||||
TEST_STATIC struct sfnt_OS_2_table *
|
||||
sfnt_read_OS_2_table (int fd, struct sfnt_offset_subtable *subtable)
|
||||
{
|
||||
struct sfnt_OS_2_table *OS_2;
|
||||
struct sfnt_table_directory *directory;
|
||||
ssize_t rc;
|
||||
size_t minimum, wanted;
|
||||
|
||||
/* Search for the OS/2 table within SUBTABLE. */
|
||||
|
||||
directory = sfnt_find_table (subtable, SFNT_TABLE_OS_2);
|
||||
|
||||
if (!directory)
|
||||
return NULL;
|
||||
|
||||
/* Calculate how large the table must be. The field `panose' is the
|
||||
last field aligned to natural boundaries, and thus contents must
|
||||
be read twice: once to populate the table with information up to
|
||||
`panose', and once again to retrieve the information
|
||||
afterwards. */
|
||||
|
||||
minimum = (SFNT_ENDOF (struct sfnt_OS_2_table, panose,
|
||||
unsigned char[10])
|
||||
+ SFNT_ENDOF (struct sfnt_OS_2_table, fs_last_char_index,
|
||||
uint16_t)
|
||||
- offsetof (struct sfnt_OS_2_table, ul_unicode_range));
|
||||
|
||||
/* If the table is too short, return. */
|
||||
if (directory->length < minimum)
|
||||
return NULL;
|
||||
|
||||
/* Seek to the location given in the directory. */
|
||||
if (lseek (fd, directory->offset, SEEK_SET) == (off_t) -1)
|
||||
return NULL;
|
||||
|
||||
OS_2 = xmalloc (sizeof *OS_2);
|
||||
|
||||
/* Read data up to the end of `panose'. */
|
||||
|
||||
wanted = SFNT_ENDOF (struct sfnt_OS_2_table, panose,
|
||||
unsigned char[10]);
|
||||
rc = read (fd, OS_2, wanted);
|
||||
|
||||
if (rc != wanted)
|
||||
{
|
||||
xfree (OS_2);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Byte swap that data. */
|
||||
|
||||
sfnt_swap16 (&OS_2->version);
|
||||
sfnt_swap16 (&OS_2->x_avg_char_width);
|
||||
sfnt_swap16 (&OS_2->us_weight_class);
|
||||
sfnt_swap16 (&OS_2->us_width_class);
|
||||
sfnt_swap16 (&OS_2->fs_type);
|
||||
sfnt_swap16 (&OS_2->y_subscript_x_size);
|
||||
sfnt_swap16 (&OS_2->y_subscript_y_size);
|
||||
sfnt_swap16 (&OS_2->y_subscript_x_offset);
|
||||
sfnt_swap16 (&OS_2->y_subscript_y_offset);
|
||||
sfnt_swap16 (&OS_2->y_superscript_x_size);
|
||||
sfnt_swap16 (&OS_2->y_superscript_y_size);
|
||||
sfnt_swap16 (&OS_2->y_superscript_x_offset);
|
||||
sfnt_swap16 (&OS_2->y_superscript_y_offset);
|
||||
sfnt_swap16 (&OS_2->y_strikeout_size);
|
||||
sfnt_swap16 (&OS_2->y_strikeout_position);
|
||||
sfnt_swap16 (&OS_2->s_family_class);
|
||||
|
||||
/* Read fields between ul_unicode_range and fs_last_char_index. */
|
||||
wanted = (SFNT_ENDOF (struct sfnt_OS_2_table, fs_last_char_index,
|
||||
uint16_t)
|
||||
- offsetof (struct sfnt_OS_2_table, ul_unicode_range));
|
||||
rc = read (fd, &OS_2->ul_unicode_range, wanted);
|
||||
|
||||
if (rc != wanted)
|
||||
{
|
||||
xfree (OS_2);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Swap the remainder and return the table. */
|
||||
sfnt_swap32 (&OS_2->ul_unicode_range[0]);
|
||||
sfnt_swap32 (&OS_2->ul_unicode_range[1]);
|
||||
sfnt_swap32 (&OS_2->ul_unicode_range[2]);
|
||||
sfnt_swap32 (&OS_2->ul_unicode_range[3]);
|
||||
sfnt_swap16 (&OS_2->fs_selection);
|
||||
sfnt_swap16 (&OS_2->fs_first_char_index);
|
||||
sfnt_swap16 (&OS_2->fs_last_char_index);
|
||||
return OS_2;
|
||||
}
|
||||
|
||||
|
||||
|
||||
#ifdef TEST
|
||||
|
||||
struct sfnt_test_dcontext
|
||||
|
@ -19158,6 +19263,7 @@ main (int argc, char **argv)
|
|||
struct sfnt_gvar_table *gvar;
|
||||
struct sfnt_avar_table *avar;
|
||||
struct sfnt_cvar_table *cvar;
|
||||
struct sfnt_OS_2_table *OS_2;
|
||||
sfnt_fixed scale;
|
||||
char *fancy;
|
||||
int *advances;
|
||||
|
@ -19293,6 +19399,7 @@ main (int argc, char **argv)
|
|||
fvar = sfnt_read_fvar_table (fd, font);
|
||||
gvar = sfnt_read_gvar_table (fd, font);
|
||||
avar = sfnt_read_avar_table (fd, font);
|
||||
OS_2 = sfnt_read_OS_2_table (fd, font);
|
||||
cvar = NULL;
|
||||
hmtx = NULL;
|
||||
|
||||
|
@ -19309,6 +19416,10 @@ main (int argc, char **argv)
|
|||
loca_long = NULL;
|
||||
loca_short = NULL;
|
||||
|
||||
if (OS_2)
|
||||
fprintf (stderr, "OS/2 table found!\nach_vendor_id: %.4s\n",
|
||||
OS_2->ach_vendor_id);
|
||||
|
||||
if (fvar)
|
||||
{
|
||||
fprintf (stderr, "FVAR table found!\n"
|
||||
|
@ -19971,6 +20082,7 @@ main (int argc, char **argv)
|
|||
xfree (gvar);
|
||||
xfree (avar);
|
||||
xfree (cvar);
|
||||
xfree (OS_2);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
88
src/sfnt.h
88
src/sfnt.h
|
@ -52,6 +52,7 @@ enum sfnt_table
|
|||
SFNT_TABLE_GVAR,
|
||||
SFNT_TABLE_CVAR,
|
||||
SFNT_TABLE_AVAR,
|
||||
SFNT_TABLE_OS_2,
|
||||
};
|
||||
|
||||
#define SFNT_ENDOF(type, field, type1) \
|
||||
|
@ -1333,6 +1334,85 @@ struct sfnt_metrics_distortion
|
|||
|
||||
|
||||
|
||||
/* OS/2 font metadata. */
|
||||
|
||||
struct sfnt_OS_2_table
|
||||
{
|
||||
/* Table version number. */
|
||||
uint16_t version;
|
||||
|
||||
/* Average weighted advance width of lower case letters and
|
||||
space. */
|
||||
int16_t x_avg_char_width;
|
||||
|
||||
/* Wisual weight (degree of blackness or thickness) of stroke in
|
||||
glyphs. */
|
||||
uint16_t us_weight_class;
|
||||
|
||||
/* Relative change from the normal aspect ratio (width to height
|
||||
ratio) as specified by a font designer for the glyphs in the
|
||||
font. */
|
||||
uint16_t us_width_class;
|
||||
|
||||
/* Miscellaneous font attributes. */
|
||||
int16_t fs_type;
|
||||
|
||||
/* Recommended horizontal size in pixels for subscripts. */
|
||||
int16_t y_subscript_x_size;
|
||||
|
||||
/* Recommended vertical subscript size. */
|
||||
int16_t y_subscript_y_size;
|
||||
|
||||
/* Recommended horizontal offset for subscripts. */
|
||||
int16_t y_subscript_x_offset;
|
||||
|
||||
/* Recommended vertical offset from the baseline for subscripts. */
|
||||
int16_t y_subscript_y_offset;
|
||||
|
||||
/* Recommended horizontal size in pixels for superscripts. */
|
||||
int16_t y_superscript_x_size;
|
||||
|
||||
/* Recommended vertical superscript size. */
|
||||
int16_t y_superscript_y_size;
|
||||
|
||||
/* Recommended horizontal offset for superscripts. */
|
||||
int16_t y_superscript_x_offset;
|
||||
|
||||
/* Recommended vertical offset from the baseline for superscripts. */
|
||||
int16_t y_superscript_y_offset;
|
||||
|
||||
/* Width of the strikeout stroke. */
|
||||
int16_t y_strikeout_size;
|
||||
|
||||
/* Position of the strikeout stroke relative to the baseline. */
|
||||
int16_t y_strikeout_position;
|
||||
|
||||
/* Font family classification. */
|
||||
int16_t s_family_class;
|
||||
|
||||
/* Microsoft ``panose'' classification. */
|
||||
unsigned char panose[10];
|
||||
|
||||
/* Alignment boundary! */
|
||||
|
||||
/* Unicode range specification. */
|
||||
uint32_t ul_unicode_range[4];
|
||||
|
||||
/* Font foundry name. */
|
||||
char ach_vendor_id[4];
|
||||
|
||||
/* Two byte bitfield providing the nature of font patterns. */
|
||||
uint16_t fs_selection;
|
||||
|
||||
/* The minimum Unicode codepoint covered. */
|
||||
uint16_t fs_first_char_index;
|
||||
|
||||
/* The maximum Unicode codepoint covered. */
|
||||
uint16_t fs_last_char_index;
|
||||
};
|
||||
|
||||
|
||||
|
||||
#define SFNT_CEIL_FIXED(fixed) (((fixed) + 0177777) & 037777600000)
|
||||
#define SFNT_FLOOR_FIXED(fixed) ((fixed) & 037777600000)
|
||||
|
||||
|
@ -1500,6 +1580,14 @@ extern int sfnt_vary_compound_glyph (struct sfnt_blend *, sfnt_glyph,
|
|||
struct sfnt_glyph *,
|
||||
struct sfnt_metrics_distortion *);
|
||||
|
||||
|
||||
|
||||
#define PROTOTYPE int, struct sfnt_offset_subtable *
|
||||
|
||||
extern struct sfnt_OS_2_table *sfnt_read_OS_2_table (PROTOTYPE);
|
||||
|
||||
#undef PROTOTYPE
|
||||
|
||||
#endif /* TEST */
|
||||
|
||||
|
||||
|
|
|
@ -109,7 +109,7 @@ struct sfnt_font_desc
|
|||
/* Style name of the font. */
|
||||
Lisp_Object style;
|
||||
|
||||
/* Designer (foundry) of the font. */
|
||||
/* The font foundry name, or `misc' if not present. */
|
||||
Lisp_Object designer;
|
||||
|
||||
/* Style tokens that could not be parsed. */
|
||||
|
@ -365,28 +365,6 @@ sfnt_decode_family_style (struct sfnt_name_table *name,
|
|||
return (!NILP (*family) && !NILP (*style)) ? 0 : 1;
|
||||
}
|
||||
|
||||
/* Decode the foundry names from the name table NAME. Return the
|
||||
foundry name, or nil upon failure. */
|
||||
|
||||
static Lisp_Object
|
||||
sfnt_decode_foundry_name (struct sfnt_name_table *name)
|
||||
{
|
||||
struct sfnt_name_record designer_rec;
|
||||
unsigned char *designer_data;
|
||||
|
||||
designer_data = sfnt_find_name (name, SFNT_NAME_DESIGNER,
|
||||
&designer_rec);
|
||||
|
||||
if (!designer_data)
|
||||
return Qnil;
|
||||
|
||||
return sfnt_decode_font_string (designer_data,
|
||||
designer_rec.platform_id,
|
||||
designer_rec.platform_specific_id,
|
||||
designer_rec.language_id,
|
||||
designer_rec.length);
|
||||
}
|
||||
|
||||
/* Decode the name of the specified font INSTANCE using the given NAME
|
||||
table. Return the name of that instance, or nil upon failure. */
|
||||
|
||||
|
@ -972,9 +950,11 @@ sfnt_enum_font_1 (int fd, const char *file,
|
|||
struct sfnt_meta_table *meta;
|
||||
struct sfnt_maxp_table *maxp;
|
||||
struct sfnt_fvar_table *fvar;
|
||||
struct sfnt_OS_2_table *OS_2;
|
||||
struct sfnt_font_desc temp;
|
||||
Lisp_Object family, style, instance, style1;
|
||||
int i;
|
||||
char buffer[5];
|
||||
|
||||
/* Create the font desc and copy in the file name. */
|
||||
desc = xzalloc (sizeof *desc + strlen (file) + 1);
|
||||
|
@ -1013,10 +993,33 @@ sfnt_enum_font_1 (int fd, const char *file,
|
|||
|
||||
/* Set the family. */
|
||||
desc->family = family;
|
||||
desc->designer = sfnt_decode_foundry_name (name);
|
||||
desc->char_cache = Qnil;
|
||||
desc->subtable.platform_id = 500;
|
||||
|
||||
/* Now set the font foundry name. This information is located
|
||||
within the OS/2 table's `ach_vendor_id' field, but use `misc' as
|
||||
a recourse if it is not present. */
|
||||
|
||||
OS_2 = sfnt_read_OS_2_table (fd, subtables);
|
||||
|
||||
if (OS_2)
|
||||
{
|
||||
memcpy (buffer, OS_2->ach_vendor_id,
|
||||
sizeof OS_2->ach_vendor_id);
|
||||
buffer[sizeof OS_2->ach_vendor_id] = '\0';
|
||||
|
||||
/* If the foundry name is empty, use `misc' instead. */
|
||||
|
||||
if (!buffer[0])
|
||||
desc->designer = Qmisc;
|
||||
else
|
||||
desc->designer = intern (buffer);
|
||||
|
||||
xfree (OS_2);
|
||||
}
|
||||
else
|
||||
desc->designer = Qmisc;
|
||||
|
||||
/* Set the largest glyph identifier. */
|
||||
desc->num_glyphs = maxp->num_glyphs;
|
||||
|
||||
|
@ -1843,11 +1846,7 @@ sfntfont_desc_to_entity (struct sfnt_font_desc *desc, int instance)
|
|||
entity = font_make_entity ();
|
||||
|
||||
ASET (entity, FONT_TYPE_INDEX, sfnt_vendor_name);
|
||||
|
||||
if (!NILP (desc->designer))
|
||||
ASET (entity, FONT_FOUNDRY_INDEX,
|
||||
Fintern (desc->designer, Qnil));
|
||||
|
||||
ASET (entity, FONT_FOUNDRY_INDEX, desc->designer);
|
||||
ASET (entity, FONT_FAMILY_INDEX, Fintern (desc->family, Qnil));
|
||||
ASET (entity, FONT_ADSTYLE_INDEX, Qnil);
|
||||
ASET (entity, FONT_REGISTRY_INDEX,
|
||||
|
@ -3186,10 +3185,12 @@ sfntfont_open (struct frame *f, Lisp_Object font_entity,
|
|||
/* Figure out the font ascent and descent. */
|
||||
font->ascent
|
||||
= ceil (font_info->hhea->ascent
|
||||
* pixel_size * 1.0 / font_info->head->units_per_em);
|
||||
* pixel_size
|
||||
* (1.0 / font_info->head->units_per_em));
|
||||
font->descent
|
||||
= -floor (font_info->hhea->descent
|
||||
* pixel_size * 1.0 / font_info->head->units_per_em);
|
||||
= ceil ((-font_info->hhea->descent)
|
||||
* pixel_size
|
||||
* (1.0 / font_info->head->units_per_em));
|
||||
font->height = font->ascent + font->descent;
|
||||
|
||||
/* Set font->max_width to the maximum advance width. */
|
||||
|
@ -3198,11 +3199,7 @@ sfntfont_open (struct frame *f, Lisp_Object font_entity,
|
|||
|
||||
/* Set generic attributes such as type and style. */
|
||||
ASET (font_object, FONT_TYPE_INDEX, sfnt_vendor_name);
|
||||
|
||||
if (!NILP (desc->designer))
|
||||
ASET (font_object, FONT_FOUNDRY_INDEX,
|
||||
Fintern (desc->designer, Qnil));
|
||||
|
||||
ASET (font_object, FONT_FOUNDRY_INDEX, desc->designer);
|
||||
ASET (font_object, FONT_FAMILY_INDEX, Fintern (desc->family, Qnil));
|
||||
ASET (font_object, FONT_ADSTYLE_INDEX, Qnil);
|
||||
ASET (font_object, FONT_REGISTRY_INDEX,
|
||||
|
@ -3956,6 +3953,9 @@ syms_of_sfntfont (void)
|
|||
/* Char-table purpose. */
|
||||
DEFSYM (Qfont_lookup_cache, "font-lookup-cache");
|
||||
|
||||
/* Default foundry name. */
|
||||
DEFSYM (Qmisc, "misc");
|
||||
|
||||
/* Set up staticpros. */
|
||||
sfnt_vendor_name = Qnil;
|
||||
staticpro (&sfnt_vendor_name);
|
||||
|
|
Loading…
Add table
Reference in a new issue