mirror of
https://gitlab.freedesktop.org/cairo/cairo.git
synced 2026-05-03 14:48:06 +02:00
font: Generate PDFs with correct font names
Escape PostScript names of loaded fonts. These can not contain white spaces and delimiter characters when saving them to a PostScript file or a PDF file.
This commit is contained in:
parent
f81b140675
commit
97f6e2005d
5 changed files with 63 additions and 38 deletions
|
|
@ -899,6 +899,8 @@ cairo_cff_font_read_name (cairo_cff_font_t *font)
|
|||
|
||||
memcpy (font->ps_name, p, len);
|
||||
font->ps_name[len] = 0;
|
||||
|
||||
status = _cairo_escape_ps_name (&font->ps_name);
|
||||
}
|
||||
cff_index_fini (&index);
|
||||
|
||||
|
|
|
|||
|
|
@ -715,6 +715,21 @@ _cairo_truetype_get_style (cairo_scaled_font_t *scaled_font,
|
|||
cairo_bool_t *bold,
|
||||
cairo_bool_t *italic);
|
||||
|
||||
/**
|
||||
* _cairo_escape_ps_name:
|
||||
* @ps_name: returns the PostScript name with all invalid characters escaped
|
||||
*
|
||||
* Ensure that PostSript name is a valid PDF/PostSript name object.
|
||||
* In PDF names are treated as UTF8 and non ASCII bytes, ' ',
|
||||
* and '#' are encoded as '#' followed by 2 hex digits that
|
||||
* encode the byte.
|
||||
*
|
||||
* Return value: %CAIRO_STATUS_SUCCESS if successful. Possible errors include
|
||||
* %CAIRO_STATUS_NO_MEMORY.
|
||||
**/
|
||||
cairo_private cairo_int_status_t
|
||||
_cairo_escape_ps_name (char **ps_name);
|
||||
|
||||
#endif /* CAIRO_HAS_FONT_SUBSET */
|
||||
|
||||
#endif /* CAIRO_SCALED_FONT_SUBSETS_PRIVATE_H */
|
||||
|
|
|
|||
|
|
@ -1256,4 +1256,44 @@ CLEANUP_HASH:
|
|||
return status;
|
||||
}
|
||||
|
||||
cairo_int_status_t
|
||||
_cairo_escape_ps_name (char **ps_name)
|
||||
{
|
||||
cairo_status_t status = CAIRO_STATUS_SUCCESS;
|
||||
|
||||
/* Ensure PS name is a valid PDF/PS name object. In PDF names are
|
||||
* treated as UTF8 and non ASCII bytes, ' ', and '#' are encoded
|
||||
* as '#' followed by 2 hex digits that encode the byte. By also
|
||||
* encoding the characters in the reserved string we ensure the
|
||||
* name is also PS compatible. */
|
||||
if (*ps_name) {
|
||||
static const char *reserved = "()<>[]{}/%#\\";
|
||||
char buf[128]; /* max name length is 127 bytes */
|
||||
char *src = *ps_name;
|
||||
char *dst = buf;
|
||||
|
||||
while (*src && dst < buf + 127) {
|
||||
unsigned char c = *src;
|
||||
if (c < 0x21 || c > 0x7e || strchr (reserved, c)) {
|
||||
if (dst + 4 > buf + 127)
|
||||
break;
|
||||
|
||||
snprintf (dst, 4, "#%02X", c);
|
||||
src++;
|
||||
dst += 3;
|
||||
} else {
|
||||
*dst++ = *src++;
|
||||
}
|
||||
}
|
||||
*dst = 0;
|
||||
free (*ps_name);
|
||||
*ps_name = strdup (buf);
|
||||
if (*ps_name == NULL) {
|
||||
status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
|
||||
}
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
#endif /* CAIRO_HAS_FONT_SUBSET */
|
||||
|
|
|
|||
|
|
@ -1566,38 +1566,9 @@ _cairo_truetype_read_font_name (cairo_scaled_font_t *scaled_font,
|
|||
|
||||
free (name);
|
||||
|
||||
/* Ensure PS name is a valid PDF/PS name object. In PDF names are
|
||||
* treated as UTF8 and non ASCII bytes, ' ', and '#' are encoded
|
||||
* as '#' followed by 2 hex digits that encode the byte. By also
|
||||
* encoding the characters in the reserved string we ensure the
|
||||
* name is also PS compatible. */
|
||||
if (ps_name) {
|
||||
static const char *reserved = "()<>[]{}/%#\\";
|
||||
char buf[128]; /* max name length is 127 bytes */
|
||||
char *src = ps_name;
|
||||
char *dst = buf;
|
||||
|
||||
while (*src && dst < buf + 127) {
|
||||
unsigned char c = *src;
|
||||
if (c < 0x21 || c > 0x7e || strchr (reserved, c)) {
|
||||
if (dst + 4 > buf + 127)
|
||||
break;
|
||||
|
||||
snprintf (dst, 4, "#%02X", c);
|
||||
src++;
|
||||
dst += 3;
|
||||
} else {
|
||||
*dst++ = *src++;
|
||||
}
|
||||
}
|
||||
*dst = 0;
|
||||
free (ps_name);
|
||||
ps_name = strdup (buf);
|
||||
if (ps_name == NULL) {
|
||||
status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
status = _cairo_escape_ps_name (&ps_name);
|
||||
if (unlikely(status))
|
||||
goto fail;
|
||||
|
||||
*ps_name_out = ps_name;
|
||||
*font_name_out = family_name;
|
||||
|
|
|
|||
|
|
@ -407,6 +407,7 @@ cairo_type1_font_subset_get_fontname (cairo_type1_font_subset_t *font)
|
|||
const char *start, *end, *segment_end;
|
||||
char *s;
|
||||
int i;
|
||||
cairo_status_t status;
|
||||
|
||||
segment_end = font->header_segment + font->header_segment_size;
|
||||
start = find_token (font->header_segment, segment_end, "/FontName");
|
||||
|
|
@ -447,13 +448,9 @@ cairo_type1_font_subset_get_fontname (cairo_type1_font_subset_t *font)
|
|||
if (unlikely (font->base.base_font == NULL))
|
||||
return _cairo_error (CAIRO_STATUS_NO_MEMORY);
|
||||
|
||||
s = font->base.base_font;
|
||||
while (*s && !is_ps_delimiter(*s))
|
||||
s++;
|
||||
status = _cairo_escape_ps_name (&font->base.base_font);
|
||||
|
||||
*s = 0;
|
||||
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
return status;
|
||||
}
|
||||
|
||||
static cairo_status_t
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue