[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. */
\f
+/* 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;
+}
+
+\f
+
#ifdef TEST
struct sfnt_test_dcontext
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;
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;
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"
xfree (gvar);
xfree (avar);
xfree (cvar);
+ xfree (OS_2);
return 0;
}
SFNT_TABLE_GVAR,
SFNT_TABLE_CVAR,
SFNT_TABLE_AVAR,
+ SFNT_TABLE_OS_2,
};
#define SFNT_ENDOF(type, field, type1) \
\f
+/* 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;
+};
+
+\f
+
#define SFNT_CEIL_FIXED(fixed) (((fixed) + 0177777) & 037777600000)
#define SFNT_FLOOR_FIXED(fixed) ((fixed) & 037777600000)
struct sfnt_glyph *,
struct sfnt_metrics_distortion *);
+\f
+
+#define PROTOTYPE int, struct sfnt_offset_subtable *
+
+extern struct sfnt_OS_2_table *sfnt_read_OS_2_table (PROTOTYPE);
+
+#undef PROTOTYPE
+
#endif /* TEST */
\f
/* 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. */
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. */
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);
/* 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;
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,
/* 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. */
/* 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,
/* 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);