Use PS font name in CFF and TrueType PDF font subsets

James Cloos found that the font name in embedded fonts should be the
PostScript font name (nameID=6 in the name table).

http://lists.cairographics.org/archives/cairo/2008-December/015919.html
This commit is contained in:
Adrian Johnson 2008-12-03 23:57:38 +10:30
parent 2ed08f7801
commit 6f2db9a4b0
4 changed files with 136 additions and 66 deletions

View file

@ -108,6 +108,7 @@ typedef struct _cairo_cff_font {
unsigned char *data_end;
cff_header_t *header;
char *font_name;
char *ps_name;
cairo_hash_table_t *top_dict;
cairo_hash_table_t *private_dict;
cairo_array_t strings_index;
@ -1749,10 +1750,8 @@ _cairo_cff_font_create (cairo_scaled_font_subset_t *scaled_font_subset,
return status;
font = malloc (sizeof (cairo_cff_font_t));
if (unlikely (font == NULL)) {
status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
goto fail1;
}
if (unlikely (font == NULL))
return _cairo_error (CAIRO_STATUS_NO_MEMORY);
font->backend = backend;
font->scaled_font_subset = scaled_font_subset;
@ -1775,19 +1774,20 @@ _cairo_cff_font_create (cairo_scaled_font_subset_t *scaled_font_subset,
font->descent = (int16_t) be16_to_cpu (hhea.descender);
status = _cairo_truetype_read_font_name (scaled_font_subset->scaled_font,
&font->ps_name,
&font->font_name);
if (_cairo_status_is_error (status))
goto fail3;
/* If the font name is not found, create a CairoFont-x-y name. */
if (font->font_name == NULL) {
font->font_name = malloc (30);
if (unlikely (font->font_name == NULL)) {
status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
/* If the PS name is not found, create a CairoFont-x-y name. */
if (font->ps_name == NULL) {
font->ps_name = malloc (30);
if (unlikely (font->ps_name == NULL)) {
status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
goto fail3;
}
snprintf(font->font_name, 30, "CairoFont-%u-%u",
snprintf(font->ps_name, 30, "CairoFont-%u-%u",
scaled_font_subset->font_id,
scaled_font_subset->subset_id);
}
@ -1849,7 +1849,8 @@ fail6:
fail5:
free (font->widths);
fail4:
free (font->font_name);
if (font->font_name)
free (font->font_name);
fail3:
free (font->subset_font_name);
fail2:
@ -1865,7 +1866,8 @@ cairo_cff_font_destroy (cairo_cff_font_t *font)
unsigned int i;
free (font->widths);
free (font->font_name);
if (font->font_name)
free (font->font_name);
free (font->subset_font_name);
_cairo_array_fini (&font->output);
cff_dict_fini (font->top_dict);
@ -1935,16 +1937,26 @@ _cairo_cff_subset_init (cairo_cff_subset_t *cff_subset,
if (unlikely (status))
goto fail1;
cff_subset->base_font = strdup (font->font_name);
if (unlikely (cff_subset->base_font == NULL)) {
cff_subset->ps_name = strdup (font->ps_name);
if (unlikely (cff_subset->ps_name == NULL)) {
status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
goto fail1;
}
if (font->font_name) {
cff_subset->font_name = strdup (font->font_name);
if (cff_subset->font_name == NULL) {
status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
goto fail2;
}
} else {
cff_subset->font_name = NULL;
}
cff_subset->widths = calloc (sizeof (int), font->scaled_font_subset->num_glyphs);
if (unlikely (cff_subset->widths == NULL)) {
status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
goto fail2;
goto fail3;
}
for (i = 0; i < font->scaled_font_subset->num_glyphs; i++)
cff_subset->widths[i] = font->widths[i];
@ -1959,7 +1971,7 @@ _cairo_cff_subset_init (cairo_cff_subset_t *cff_subset,
cff_subset->data = malloc (length);
if (unlikely (cff_subset->data == NULL)) {
status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
goto fail3;
goto fail4;
}
memcpy (cff_subset->data, data, length);
@ -1969,10 +1981,13 @@ _cairo_cff_subset_init (cairo_cff_subset_t *cff_subset,
return CAIRO_STATUS_SUCCESS;
fail3:
fail4:
free (cff_subset->widths);
fail3:
if (cff_subset->font_name)
free (cff_subset->font_name);
fail2:
free (cff_subset->base_font);
free (cff_subset->ps_name);
fail1:
cairo_cff_font_destroy (font);
@ -1982,7 +1997,9 @@ _cairo_cff_subset_init (cairo_cff_subset_t *cff_subset,
void
_cairo_cff_subset_fini (cairo_cff_subset_t *subset)
{
free (subset->base_font);
free (subset->ps_name);
if (subset->font_name)
free (subset->font_name);
free (subset->widths);
free (subset->data);
}
@ -2013,11 +2030,12 @@ _cairo_cff_font_fallback_create (cairo_scaled_font_subset_t *scaled_font_subset
goto fail1;
}
font->font_name = strdup (subset_name);
font->ps_name = strdup (subset_name);
if (unlikely (font->subset_font_name == NULL)) {
status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
goto fail2;
}
font->font_name = NULL;
font->x_min = 0;
font->y_min = 0;
@ -2067,7 +2085,8 @@ fail5:
fail4:
free (font->widths);
fail3:
free (font->font_name);
if (font->font_name)
free (font->font_name);
fail2:
free (font->subset_font_name);
fail1:
@ -2183,8 +2202,8 @@ _cairo_cff_fallback_init (cairo_cff_subset_t *cff_subset,
if (unlikely (status))
goto fail2;
cff_subset->base_font = strdup (font->font_name);
if (unlikely (cff_subset->base_font == NULL)) {
cff_subset->ps_name = strdup (font->ps_name);
if (unlikely (cff_subset->ps_name == NULL)) {
status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
goto fail2;
}
@ -2194,6 +2213,7 @@ _cairo_cff_fallback_init (cairo_cff_subset_t *cff_subset,
status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
goto fail3;
}
for (i = 0; i < font->scaled_font_subset->num_glyphs; i++)
cff_subset->widths[i] = type2_subset.widths[i];
@ -2222,7 +2242,7 @@ _cairo_cff_fallback_init (cairo_cff_subset_t *cff_subset,
fail4:
free (cff_subset->widths);
fail3:
free (cff_subset->base_font);
free (cff_subset->ps_name);
fail2:
_cairo_type2_charstrings_fini (&type2_subset);
fail1:
@ -2234,7 +2254,7 @@ _cairo_cff_fallback_init (cairo_cff_subset_t *cff_subset,
void
_cairo_cff_fallback_fini (cairo_cff_subset_t *subset)
{
free (subset->base_font);
free (subset->ps_name);
free (subset->widths);
free (subset->data);
}

View file

@ -3387,7 +3387,7 @@ _cairo_pdf_surface_emit_cff_font (cairo_pdf_surface_t *surface,
cairo_status_t status;
char tag[10];
_create_font_subset_tag (font_subset, subset->base_font, tag);
_create_font_subset_tag (font_subset, subset->ps_name, tag);
subset_resource = _cairo_pdf_surface_get_font_resource (surface,
font_subset->font_id,
@ -3436,7 +3436,7 @@ _cairo_pdf_surface_emit_cff_font (cairo_pdf_surface_t *surface,
"endobj\n",
descriptor.id,
tag,
subset->base_font,
subset->ps_name,
subset->x_min,
subset->y_min,
subset->x_max,
@ -3463,7 +3463,7 @@ _cairo_pdf_surface_emit_cff_font (cairo_pdf_surface_t *surface,
" /W [0 [",
cidfont_dict.id,
tag,
subset->base_font,
subset->ps_name,
descriptor.id);
for (i = 0; i < font_subset->num_glyphs; i++)
@ -3486,7 +3486,7 @@ _cairo_pdf_surface_emit_cff_font (cairo_pdf_surface_t *surface,
" /DescendantFonts [ %d 0 R]\n",
subset_resource.id,
tag,
subset->base_font,
subset->ps_name,
cidfont_dict.id);
if (to_unicode_stream.id != 0)
@ -3728,7 +3728,7 @@ _cairo_pdf_surface_emit_truetype_font_subset (cairo_pdf_surface_t *surface,
if (unlikely (status))
return status;
_create_font_subset_tag (font_subset, subset.base_font, tag);
_create_font_subset_tag (font_subset, subset.ps_name, tag);
status = _cairo_pdf_surface_open_stream (surface,
NULL,
@ -3780,7 +3780,7 @@ _cairo_pdf_surface_emit_truetype_font_subset (cairo_pdf_surface_t *surface,
"endobj\n",
descriptor.id,
tag,
subset.base_font,
subset.ps_name,
(long)(subset.x_min*PDF_UNITS_PER_EM),
(long)(subset.y_min*PDF_UNITS_PER_EM),
(long)(subset.x_max*PDF_UNITS_PER_EM),
@ -3810,7 +3810,7 @@ _cairo_pdf_surface_emit_truetype_font_subset (cairo_pdf_surface_t *surface,
" /W [0 [",
cidfont_dict.id,
tag,
subset.base_font,
subset.ps_name,
descriptor.id);
for (i = 0; i < font_subset->num_glyphs; i++)
@ -3833,7 +3833,7 @@ _cairo_pdf_surface_emit_truetype_font_subset (cairo_pdf_surface_t *surface,
" /DescendantFonts [ %d 0 R]\n",
subset_resource.id,
tag,
subset.base_font,
subset.ps_name,
cidfont_dict.id);
if (to_unicode_stream.id != 0)

View file

@ -332,7 +332,8 @@ cairo_private cairo_int_status_t
_cairo_scaled_font_subset_create_glyph_names (cairo_scaled_font_subset_t *subset);
typedef struct _cairo_cff_subset {
char *base_font;
char *font_name;
char *ps_name;
int *widths;
long x_min, y_min, x_max, y_max;
long ascent, descent;
@ -404,7 +405,8 @@ cairo_private void
_cairo_cff_fallback_fini (cairo_cff_subset_t *cff_subset);
typedef struct _cairo_truetype_subset {
char *base_font;
char *font_name;
char *ps_name;
double *widths;
double x_min, y_min, x_max, y_max;
double ascent, descent;
@ -638,11 +640,17 @@ _cairo_truetype_index_to_ucs4 (cairo_scaled_font_t *scaled_font,
/**
* _cairo_truetype_read_font_name:
* @scaled_font: the #cairo_scaled_font_t
* @ps_name: returns the PostScript name of the font or NULL if the name could not be found.
* @font_name: returns the font name or NULL if the name could not be found.
*
* If possible (depending on the format of the underlying
* #cairo_scaled_font_t and the font backend in use) read the
* font name from a TrueType/OpenType font.
* PostScript and Font names from a TrueType/OpenType font.
*
* The font name is the full name of the font eg "DejaVu Sans Bold".
* The PostScript name is a shortened name with spaces removed
* suitable for use as the font name in a PS or PDF file eg
* "DejaVuSans-Bold".
*
* Return value: %CAIRO_STATUS_SUCCESS if successful,
* %CAIRO_INT_STATUS_UNSUPPORTED if the font is not TrueType/OpenType
@ -650,8 +658,9 @@ _cairo_truetype_index_to_ucs4 (cairo_scaled_font_t *scaled_font,
* %CAIRO_STATUS_NO_MEMORY.
**/
cairo_private cairo_int_status_t
_cairo_truetype_read_font_name (cairo_scaled_font_t *scaled_font,
char **font_name);
_cairo_truetype_read_font_name (cairo_scaled_font_t *scaled_font,
char **ps_name,
char **font_name);
#endif /* CAIRO_HAS_FONT_SUBSET */

View file

@ -72,7 +72,8 @@ struct _cairo_truetype_font {
int num_tables;
struct {
char *base_font;
char *font_name;
char *ps_name;
unsigned int num_glyphs;
int *widths;
long x_min, y_min, x_max, y_max;
@ -201,19 +202,20 @@ _cairo_truetype_font_create (cairo_scaled_font_subset_t *scaled_font_subset,
font->base.units_per_em = 2048;
status = _cairo_truetype_read_font_name (scaled_font_subset->scaled_font,
&font->base.base_font);
&font->base.ps_name,
&font->base.font_name);
if (_cairo_status_is_error (status))
goto fail3;
/* If the font name is not found, create a CairoFont-x-y name. */
if (font->base.base_font == NULL) {
font->base.base_font = malloc (30);
if (unlikely (font->base.base_font == NULL)) {
/* If the PS name is not found, create a CairoFont-x-y name. */
if (font->base.ps_name == NULL) {
font->base.ps_name = malloc (30);
if (unlikely (font->base.ps_name == NULL)) {
status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
goto fail3;
}
snprintf(font->base.base_font, 30, "CairoFont-%u-%u",
snprintf(font->base.ps_name, 30, "CairoFont-%u-%u",
scaled_font_subset->font_id,
scaled_font_subset->subset_id);
}
@ -239,9 +241,11 @@ _cairo_truetype_font_create (cairo_scaled_font_subset_t *scaled_font_subset,
_cairo_array_fini (&font->string_offsets);
free (font->base.widths);
fail4:
free (font->base.base_font);
free (font->base.ps_name);
fail3:
free (font->parent_to_subset);
if (font->base.font_name)
free (font->base.font_name);
fail2:
free (font->glyphs);
fail1:
@ -256,7 +260,9 @@ cairo_truetype_font_destroy (cairo_truetype_font_t *font)
{
_cairo_array_fini (&font->string_offsets);
free (font->base.widths);
free (font->base.base_font);
free (font->base.ps_name);
if (font->base.font_name)
free (font->base.font_name);
free (font->parent_to_subset);
free (font->glyphs);
_cairo_array_fini (&font->output);
@ -1043,12 +1049,22 @@ _cairo_truetype_subset_init (cairo_truetype_subset_t *truetype_subset,
if (unlikely (status))
goto fail1;
truetype_subset->base_font = strdup (font->base.base_font);
if (unlikely (truetype_subset->base_font == NULL)) {
truetype_subset->ps_name = strdup (font->base.ps_name);
if (unlikely (truetype_subset->ps_name == NULL)) {
status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
goto fail1;
}
if (font->base.font_name != NULL) {
truetype_subset->font_name = strdup (font->base.font_name);
if (unlikely (truetype_subset->font_name == NULL)) {
status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
goto fail2;
}
} else {
truetype_subset->font_name = NULL;
}
/* The widths array returned must contain only widths for the
* glyphs in font_subset. Any subglyphs appended after
* font_subset->num_glyphs are omitted. */
@ -1056,7 +1072,7 @@ _cairo_truetype_subset_init (cairo_truetype_subset_t *truetype_subset,
font->scaled_font_subset->num_glyphs);
if (unlikely (truetype_subset->widths == NULL)) {
status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
goto fail2;
goto fail3;
}
for (i = 0; i < font->scaled_font_subset->num_glyphs; i++)
truetype_subset->widths[i] = (double)font->base.widths[i]/font->base.units_per_em;
@ -1072,7 +1088,7 @@ _cairo_truetype_subset_init (cairo_truetype_subset_t *truetype_subset,
truetype_subset->data = malloc (length);
if (unlikely (truetype_subset->data == NULL)) {
status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
goto fail3;
goto fail4;
}
memcpy (truetype_subset->data, data, length);
@ -1085,7 +1101,7 @@ _cairo_truetype_subset_init (cairo_truetype_subset_t *truetype_subset,
truetype_subset->string_offsets = malloc (offsets_length);
if (unlikely (truetype_subset->string_offsets == NULL)) {
status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
goto fail4;
goto fail5;
}
memcpy (truetype_subset->string_offsets, string_offsets, offsets_length);
@ -1099,12 +1115,15 @@ _cairo_truetype_subset_init (cairo_truetype_subset_t *truetype_subset,
return CAIRO_STATUS_SUCCESS;
fail4:
fail5:
free (truetype_subset->data);
fail3:
fail4:
free (truetype_subset->widths);
fail3:
if (truetype_subset->font_name)
free (truetype_subset->font_name);
fail2:
free (truetype_subset->base_font);
free (truetype_subset->ps_name);
fail1:
cairo_truetype_font_destroy (font);
@ -1114,7 +1133,7 @@ _cairo_truetype_subset_init (cairo_truetype_subset_t *truetype_subset,
void
_cairo_truetype_subset_fini (cairo_truetype_subset_t *subset)
{
free (subset->base_font);
free (subset->ps_name);
free (subset->widths);
free (subset->data);
free (subset->string_offsets);
@ -1283,6 +1302,7 @@ cleanup:
cairo_int_status_t
_cairo_truetype_read_font_name (cairo_scaled_font_t *scaled_font,
char **ps_name_out,
char **font_name_out)
{
cairo_status_t status;
@ -1291,6 +1311,7 @@ _cairo_truetype_read_font_name (cairo_scaled_font_t *scaled_font,
tt_name_record_t *record;
unsigned long size;
int i, j;
char *ps_name;
char *font_name;
backend = scaled_font->backend;
@ -1309,7 +1330,7 @@ _cairo_truetype_read_font_name (cairo_scaled_font_t *scaled_font,
if (name == NULL)
return _cairo_error (CAIRO_STATUS_NO_MEMORY);
status = backend->load_truetype_table (scaled_font,
status = backend->load_truetype_table (scaled_font,
TT_TAG_name, 0,
(unsigned char *) name,
&size);
@ -1321,12 +1342,14 @@ _cairo_truetype_read_font_name (cairo_scaled_font_t *scaled_font,
* name. It should be extended to use any suitable font name in
* the name table.
*/
ps_name = NULL;
font_name = NULL;
for (i = 0; i < be16_to_cpu(name->num_records); i++) {
record = &(name->records[i]);
if ((be16_to_cpu (record->platform) == 1) &&
(be16_to_cpu (record->encoding) == 0) &&
(be16_to_cpu (record->name) == 4)) {
(be16_to_cpu (record->encoding) == 0)) {
if (be16_to_cpu (record->name) == 4) {
font_name = malloc (be16_to_cpu(record->length) + 1);
if (font_name == NULL) {
status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
@ -1336,28 +1359,46 @@ _cairo_truetype_read_font_name (cairo_scaled_font_t *scaled_font,
((char*)name) + be16_to_cpu (name->strings_offset) + be16_to_cpu (record->offset),
be16_to_cpu (record->length));
font_name[be16_to_cpu (record->length)] = 0;
}
if (be16_to_cpu (record->name) == 6) {
ps_name = malloc (be16_to_cpu(record->length) + 1);
if (ps_name == NULL) {
status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
goto fail;
}
strncpy(ps_name,
((char*)name) + be16_to_cpu (name->strings_offset) + be16_to_cpu (record->offset),
be16_to_cpu (record->length));
ps_name[be16_to_cpu (record->length)] = 0;
}
if (font_name && ps_name)
break;
}
}
}
free (name);
/* Ensure font name does not contain any spaces */
if (font_name) {
for (i = 0, j = 0; font_name[j]; j++) {
if (font_name[j] == ' ')
/* Ensure PS name does not contain any spaces */
if (ps_name) {
for (i = 0, j = 0; ps_name[j]; j++) {
if (ps_name[j] == ' ')
continue;
font_name[i++] = font_name[j];
ps_name[i++] = ps_name[j];
}
font_name[i] = '\0';
ps_name[i] = '\0';
}
*ps_name_out = ps_name;
*font_name_out = font_name;
return CAIRO_STATUS_SUCCESS;
fail:
free (name);
*ps_name_out = NULL;
*font_name_out = NULL;
return status;
}