|
|
ac1da3 |
From 97f6e2005d9cbc9c9dd7cc21445df7c08e084c83 Mon Sep 17 00:00:00 2001
|
|
|
ac1da3 |
From: Marek Kasik <mkasik@redhat.com>
|
|
|
ac1da3 |
Date: Thu, 9 Jan 2014 17:28:32 +0100
|
|
|
ac1da3 |
Subject: [PATCH] font: Generate PDFs with correct font names
|
|
|
ac1da3 |
|
|
|
ac1da3 |
Escape PostScript names of loaded fonts. These can not
|
|
|
ac1da3 |
contain white spaces and delimiter characters when saving
|
|
|
ac1da3 |
them to a PostScript file or a PDF file.
|
|
|
ac1da3 |
---
|
|
|
ac1da3 |
src/cairo-cff-subset.c | 2 ++
|
|
|
ac1da3 |
src/cairo-scaled-font-subsets-private.h | 15 +++++++++++++
|
|
|
ac1da3 |
src/cairo-scaled-font-subsets.c | 40 +++++++++++++++++++++++++++++++++
|
|
|
ac1da3 |
src/cairo-truetype-subset.c | 35 +++--------------------------
|
|
|
ac1da3 |
src/cairo-type1-subset.c | 9 +++-----
|
|
|
ac1da3 |
5 files changed, 63 insertions(+), 38 deletions(-)
|
|
|
ac1da3 |
|
|
|
ac1da3 |
diff --git a/src/cairo-cff-subset.c b/src/cairo-cff-subset.c
|
|
|
ac1da3 |
index c420bd4..1ae032c 100644
|
|
|
ac1da3 |
--- a/src/cairo-cff-subset.c
|
|
|
ac1da3 |
+++ b/src/cairo-cff-subset.c
|
|
|
ac1da3 |
@@ -899,6 +899,8 @@ cairo_cff_font_read_name (cairo_cff_font_t *font)
|
|
|
ac1da3 |
|
|
|
ac1da3 |
memcpy (font->ps_name, p, len);
|
|
|
ac1da3 |
font->ps_name[len] = 0;
|
|
|
ac1da3 |
+
|
|
|
ac1da3 |
+ status = _cairo_escape_ps_name (&font->ps_name);
|
|
|
ac1da3 |
}
|
|
|
ac1da3 |
cff_index_fini (&index);
|
|
|
ac1da3 |
|
|
|
ac1da3 |
diff --git a/src/cairo-scaled-font-subsets-private.h b/src/cairo-scaled-font-subsets-private.h
|
|
|
ac1da3 |
index dd19962..866e63d 100644
|
|
|
ac1da3 |
--- a/src/cairo-scaled-font-subsets-private.h
|
|
|
ac1da3 |
+++ b/src/cairo-scaled-font-subsets-private.h
|
|
|
ac1da3 |
@@ -715,6 +715,21 @@ _cairo_truetype_get_style (cairo_scaled_font_t *scaled_font,
|
|
|
ac1da3 |
cairo_bool_t *bold,
|
|
|
ac1da3 |
cairo_bool_t *italic);
|
|
|
ac1da3 |
|
|
|
ac1da3 |
+/**
|
|
|
ac1da3 |
+ * _cairo_escape_ps_name:
|
|
|
ac1da3 |
+ * @ps_name: returns the PostScript name with all invalid characters escaped
|
|
|
ac1da3 |
+ *
|
|
|
ac1da3 |
+ * Ensure that PostSript name is a valid PDF/PostSript name object.
|
|
|
ac1da3 |
+ * In PDF names are treated as UTF8 and non ASCII bytes, ' ',
|
|
|
ac1da3 |
+ * and '#' are encoded as '#' followed by 2 hex digits that
|
|
|
ac1da3 |
+ * encode the byte.
|
|
|
ac1da3 |
+ *
|
|
|
ac1da3 |
+ * Return value: %CAIRO_STATUS_SUCCESS if successful. Possible errors include
|
|
|
ac1da3 |
+ * %CAIRO_STATUS_NO_MEMORY.
|
|
|
ac1da3 |
+ **/
|
|
|
ac1da3 |
+cairo_private cairo_int_status_t
|
|
|
ac1da3 |
+_cairo_escape_ps_name (char **ps_name);
|
|
|
ac1da3 |
+
|
|
|
ac1da3 |
#endif /* CAIRO_HAS_FONT_SUBSET */
|
|
|
ac1da3 |
|
|
|
ac1da3 |
#endif /* CAIRO_SCALED_FONT_SUBSETS_PRIVATE_H */
|
|
|
ac1da3 |
diff --git a/src/cairo-scaled-font-subsets.c b/src/cairo-scaled-font-subsets.c
|
|
|
ac1da3 |
index e78e0c2..2121761 100644
|
|
|
ac1da3 |
--- a/src/cairo-scaled-font-subsets.c
|
|
|
ac1da3 |
+++ b/src/cairo-scaled-font-subsets.c
|
|
|
ac1da3 |
@@ -1256,4 +1256,44 @@ CLEANUP_HASH:
|
|
|
ac1da3 |
return status;
|
|
|
ac1da3 |
}
|
|
|
ac1da3 |
|
|
|
ac1da3 |
+cairo_int_status_t
|
|
|
ac1da3 |
+_cairo_escape_ps_name (char **ps_name)
|
|
|
ac1da3 |
+{
|
|
|
ac1da3 |
+ cairo_status_t status = CAIRO_STATUS_SUCCESS;
|
|
|
ac1da3 |
+
|
|
|
ac1da3 |
+ /* Ensure PS name is a valid PDF/PS name object. In PDF names are
|
|
|
ac1da3 |
+ * treated as UTF8 and non ASCII bytes, ' ', and '#' are encoded
|
|
|
ac1da3 |
+ * as '#' followed by 2 hex digits that encode the byte. By also
|
|
|
ac1da3 |
+ * encoding the characters in the reserved string we ensure the
|
|
|
ac1da3 |
+ * name is also PS compatible. */
|
|
|
ac1da3 |
+ if (*ps_name) {
|
|
|
ac1da3 |
+ static const char *reserved = "()<>[]{}/%#\\";
|
|
|
ac1da3 |
+ char buf[128]; /* max name length is 127 bytes */
|
|
|
ac1da3 |
+ char *src = *ps_name;
|
|
|
ac1da3 |
+ char *dst = buf;
|
|
|
ac1da3 |
+
|
|
|
ac1da3 |
+ while (*src && dst < buf + 127) {
|
|
|
ac1da3 |
+ unsigned char c = *src;
|
|
|
ac1da3 |
+ if (c < 0x21 || c > 0x7e || strchr (reserved, c)) {
|
|
|
ac1da3 |
+ if (dst + 4 > buf + 127)
|
|
|
ac1da3 |
+ break;
|
|
|
ac1da3 |
+
|
|
|
ac1da3 |
+ snprintf (dst, 4, "#%02X", c);
|
|
|
ac1da3 |
+ src++;
|
|
|
ac1da3 |
+ dst += 3;
|
|
|
ac1da3 |
+ } else {
|
|
|
ac1da3 |
+ *dst++ = *src++;
|
|
|
ac1da3 |
+ }
|
|
|
ac1da3 |
+ }
|
|
|
ac1da3 |
+ *dst = 0;
|
|
|
ac1da3 |
+ free (*ps_name);
|
|
|
ac1da3 |
+ *ps_name = strdup (buf);
|
|
|
ac1da3 |
+ if (*ps_name == NULL) {
|
|
|
ac1da3 |
+ status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
|
|
|
ac1da3 |
+ }
|
|
|
ac1da3 |
+ }
|
|
|
ac1da3 |
+
|
|
|
ac1da3 |
+ return status;
|
|
|
ac1da3 |
+}
|
|
|
ac1da3 |
+
|
|
|
ac1da3 |
#endif /* CAIRO_HAS_FONT_SUBSET */
|
|
|
ac1da3 |
diff --git a/src/cairo-truetype-subset.c b/src/cairo-truetype-subset.c
|
|
|
ac1da3 |
index 18ee685..3d55fef 100644
|
|
|
ac1da3 |
--- a/src/cairo-truetype-subset.c
|
|
|
ac1da3 |
+++ b/src/cairo-truetype-subset.c
|
|
|
ac1da3 |
@@ -1566,38 +1566,9 @@ _cairo_truetype_read_font_name (cairo_scaled_font_t *scaled_font,
|
|
|
ac1da3 |
|
|
|
ac1da3 |
free (name);
|
|
|
ac1da3 |
|
|
|
ac1da3 |
- /* Ensure PS name is a valid PDF/PS name object. In PDF names are
|
|
|
ac1da3 |
- * treated as UTF8 and non ASCII bytes, ' ', and '#' are encoded
|
|
|
ac1da3 |
- * as '#' followed by 2 hex digits that encode the byte. By also
|
|
|
ac1da3 |
- * encoding the characters in the reserved string we ensure the
|
|
|
ac1da3 |
- * name is also PS compatible. */
|
|
|
ac1da3 |
- if (ps_name) {
|
|
|
ac1da3 |
- static const char *reserved = "()<>[]{}/%#\\";
|
|
|
ac1da3 |
- char buf[128]; /* max name length is 127 bytes */
|
|
|
ac1da3 |
- char *src = ps_name;
|
|
|
ac1da3 |
- char *dst = buf;
|
|
|
ac1da3 |
-
|
|
|
ac1da3 |
- while (*src && dst < buf + 127) {
|
|
|
ac1da3 |
- unsigned char c = *src;
|
|
|
ac1da3 |
- if (c < 0x21 || c > 0x7e || strchr (reserved, c)) {
|
|
|
ac1da3 |
- if (dst + 4 > buf + 127)
|
|
|
ac1da3 |
- break;
|
|
|
ac1da3 |
-
|
|
|
ac1da3 |
- snprintf (dst, 4, "#%02X", c);
|
|
|
ac1da3 |
- src++;
|
|
|
ac1da3 |
- dst += 3;
|
|
|
ac1da3 |
- } else {
|
|
|
ac1da3 |
- *dst++ = *src++;
|
|
|
ac1da3 |
- }
|
|
|
ac1da3 |
- }
|
|
|
ac1da3 |
- *dst = 0;
|
|
|
ac1da3 |
- free (ps_name);
|
|
|
ac1da3 |
- ps_name = strdup (buf);
|
|
|
ac1da3 |
- if (ps_name == NULL) {
|
|
|
ac1da3 |
- status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
|
|
|
ac1da3 |
- goto fail;
|
|
|
ac1da3 |
- }
|
|
|
ac1da3 |
- }
|
|
|
ac1da3 |
+ status = _cairo_escape_ps_name (&ps_name);
|
|
|
ac1da3 |
+ if (unlikely(status))
|
|
|
ac1da3 |
+ goto fail;
|
|
|
ac1da3 |
|
|
|
ac1da3 |
*ps_name_out = ps_name;
|
|
|
ac1da3 |
*font_name_out = family_name;
|
|
|
ac1da3 |
diff --git a/src/cairo-type1-subset.c b/src/cairo-type1-subset.c
|
|
|
ac1da3 |
index 99830b4..3b2cc0a 100644
|
|
|
ac1da3 |
--- a/src/cairo-type1-subset.c
|
|
|
ac1da3 |
+++ b/src/cairo-type1-subset.c
|
|
|
ac1da3 |
@@ -407,6 +407,7 @@ cairo_type1_font_subset_get_fontname (cairo_type1_font_subset_t *font)
|
|
|
ac1da3 |
const char *start, *end, *segment_end;
|
|
|
ac1da3 |
char *s;
|
|
|
ac1da3 |
int i;
|
|
|
ac1da3 |
+ cairo_status_t status;
|
|
|
ac1da3 |
|
|
|
ac1da3 |
segment_end = font->header_segment + font->header_segment_size;
|
|
|
ac1da3 |
start = find_token (font->header_segment, segment_end, "/FontName");
|
|
|
ac1da3 |
@@ -447,13 +448,9 @@ cairo_type1_font_subset_get_fontname (cairo_type1_font_subset_t *font)
|
|
|
ac1da3 |
if (unlikely (font->base.base_font == NULL))
|
|
|
ac1da3 |
return _cairo_error (CAIRO_STATUS_NO_MEMORY);
|
|
|
ac1da3 |
|
|
|
ac1da3 |
- s = font->base.base_font;
|
|
|
ac1da3 |
- while (*s && !is_ps_delimiter(*s))
|
|
|
ac1da3 |
- s++;
|
|
|
ac1da3 |
-
|
|
|
ac1da3 |
- *s = 0;
|
|
|
ac1da3 |
+ status = _cairo_escape_ps_name (&font->base.base_font);
|
|
|
ac1da3 |
|
|
|
ac1da3 |
- return CAIRO_STATUS_SUCCESS;
|
|
|
ac1da3 |
+ return status;
|
|
|
ac1da3 |
}
|
|
|
ac1da3 |
|
|
|
ac1da3 |
static cairo_status_t
|
|
|
ac1da3 |
--
|
|
|
ac1da3 |
1.8.4.2
|
|
|
ac1da3 |
|