[cairo-commit] 3 commits - src/cairo-cff-subset.c src/cairoint.h src/cairo-misc.c src/cairo-output-stream.c src/cairo-truetype-subset.c src/cairo-type1-subset.c

Adrian Johnson ajohnson at kemper.freedesktop.org
Fri Sep 22 11:01:03 UTC 2017


 src/cairo-cff-subset.c      |   27 ++-----------------
 src/cairo-misc.c            |   60 ++++++++++++++++++++++++++++++++++++++++++--
 src/cairo-output-stream.c   |    2 -
 src/cairo-truetype-subset.c |   59 +++++++++++++++++++++++--------------------
 src/cairo-type1-subset.c    |    2 -
 src/cairoint.h              |    5 ++-
 6 files changed, 99 insertions(+), 56 deletions(-)

New commits:
commit dccbed7d78d32bd3b912e8810379451dd94e6a1f
Author: Adrian Johnson <ajohnson at redneon.com>
Date:   Fri Sep 22 20:24:45 2017 +0930

    truetype: clarify glyph count variables
    
    - move num_glyphs_in_face to base struct as it is the number in the font
    - move num_glyphs to the subset variables as it is the num glyphs in the subset
    - move widths to subset variables as it uses the subset id as the array index

diff --git a/src/cairo-truetype-subset.c b/src/cairo-truetype-subset.c
index c4e550c7..e934689a 100644
--- a/src/cairo-truetype-subset.c
+++ b/src/cairo-truetype-subset.c
@@ -77,22 +77,22 @@ struct _cairo_truetype_font {
     struct {
 	char *font_name;
 	char *ps_name;
-	unsigned int num_glyphs;
-	int *widths;
+	int num_glyphs_in_face; /* glyphs in font */
 	long x_min, y_min, x_max, y_max;
 	long ascent, descent;
         int  units_per_em;
     } base;
 
-    subset_glyph_t *glyphs;
+    subset_glyph_t *glyphs; /* array size: num_glyphs_in_face + 2 */
     const cairo_scaled_font_backend_t *backend;
-    int num_glyphs_in_face;
+    unsigned int num_glyphs; /* glyphs used */
+    int *widths; /* array size: num_glyphs_in_face  + 1 */
     int checksum_index;
     cairo_array_t output;
     cairo_array_t string_offsets;
     unsigned long last_offset;
     unsigned long last_boundary;
-    int *parent_to_subset;
+    int *parent_to_subset; /* array size: num_glyphs_in_face + 1 */
     cairo_status_t status;
     cairo_bool_t is_pdf;
 };
@@ -198,7 +198,7 @@ _cairo_truetype_font_create (cairo_scaled_font_subset_t  *scaled_font_subset,
 	return _cairo_error (CAIRO_STATUS_NO_MEMORY);
 
     font->backend = backend;
-    font->num_glyphs_in_face = be16_to_cpu (maxp.num_glyphs);
+    font->base.num_glyphs_in_face = be16_to_cpu (maxp.num_glyphs);
     font->scaled_font_subset = scaled_font_subset;
 
     font->last_offset = 0;
@@ -211,21 +211,21 @@ _cairo_truetype_font_create (cairo_scaled_font_subset_t  *scaled_font_subset,
     /* Add 2: +1 case font does not contain .notdef, and +1 because an extra
      * entry is required to contain the end location of the last glyph.
      */
-    font->glyphs = calloc (font->num_glyphs_in_face + 2, sizeof (subset_glyph_t));
+    font->glyphs = calloc (font->base.num_glyphs_in_face + 2, sizeof (subset_glyph_t));
     if (unlikely (font->glyphs == NULL)) {
 	status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
 	goto fail1;
     }
 
     /* Add 1 in case font does not contain .notdef */
-    font->parent_to_subset = calloc (font->num_glyphs_in_face + 1, sizeof (int));
+    font->parent_to_subset = calloc (font->base.num_glyphs_in_face + 1, sizeof (int));
     if (unlikely (font->parent_to_subset == NULL)) {
 	status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
 	goto fail2;
     }
 
     font->is_pdf = is_pdf;
-    font->base.num_glyphs = 0;
+    font->num_glyphs = 0;
     font->base.x_min = (int16_t) be16_to_cpu (head.x_min);
     font->base.y_min = (int16_t) be16_to_cpu (head.y_min);
     font->base.x_max = (int16_t) be16_to_cpu (head.x_max);
@@ -258,8 +258,8 @@ _cairo_truetype_font_create (cairo_scaled_font_subset_t  *scaled_font_subset,
     }
 
     /* Add 1 in case font does not contain .notdef */
-    font->base.widths = calloc (font->num_glyphs_in_face + 1, sizeof (int));
-    if (unlikely (font->base.widths == NULL)) {
+    font->widths = calloc (font->base.num_glyphs_in_face + 1, sizeof (int));
+    if (unlikely (font->widths == NULL)) {
 	status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
 	goto fail4;
     }
@@ -277,7 +277,7 @@ _cairo_truetype_font_create (cairo_scaled_font_subset_t  *scaled_font_subset,
 
  fail5:
     _cairo_array_fini (&font->string_offsets);
-    free (font->base.widths);
+    free (font->widths);
  fail4:
     free (font->base.ps_name);
  fail3:
@@ -296,7 +296,7 @@ static void
 cairo_truetype_font_destroy (cairo_truetype_font_t *font)
 {
     _cairo_array_fini (&font->string_offsets);
-    free (font->base.widths);
+    free (font->widths);
     free (font->base.ps_name);
     free (font->base.font_name);
     free (font->parent_to_subset);
@@ -618,9 +618,9 @@ cairo_truetype_font_write_glyf_table (cairo_truetype_font_t *font,
 	return _cairo_truetype_font_set_error (font, status);
 
     if (be16_to_cpu (header.index_to_loc_format) == 0)
-	size = sizeof (int16_t) * (font->num_glyphs_in_face + 1);
+	size = sizeof (int16_t) * (font->base.num_glyphs_in_face + 1);
     else
-	size = sizeof (int32_t) * (font->num_glyphs_in_face + 1);
+	size = sizeof (int32_t) * (font->base.num_glyphs_in_face + 1);
 
     u.bytes = malloc (size);
     if (unlikely (u.bytes == NULL))
@@ -632,7 +632,7 @@ cairo_truetype_font_write_glyf_table (cairo_truetype_font_t *font,
 	return _cairo_truetype_font_set_error (font, status);
 
     start_offset = _cairo_array_num_elements (&font->output);
-    for (i = 0; i < font->base.num_glyphs; i++) {
+    for (i = 0; i < font->num_glyphs; i++) {
 	index = font->glyphs[i].parent_index;
 	if (be16_to_cpu (header.index_to_loc_format) == 0) {
 	    begin = be16_to_cpu (u.short_offsets[index]) * 2;
@@ -760,7 +760,7 @@ cairo_truetype_font_write_hhea_table (cairo_truetype_font_t *font, unsigned long
     if (unlikely (status))
 	return _cairo_truetype_font_set_error (font, status);
 
-    hhea->num_hmetrics = cpu_to_be16 ((uint16_t)(font->base.num_glyphs));
+    hhea->num_hmetrics = cpu_to_be16 ((uint16_t)(font->num_glyphs));
 
     return CAIRO_STATUS_SUCCESS;
 }
@@ -790,7 +790,7 @@ cairo_truetype_font_write_hmtx_table (cairo_truetype_font_t *font,
 
     num_hmetrics = be16_to_cpu(hhea.num_hmetrics);
 
-    for (i = 0; i < font->base.num_glyphs; i++) {
+    for (i = 0; i < font->num_glyphs; i++) {
         long_entry_size = 2 * sizeof (int16_t);
         short_entry_size = sizeof (int16_t);
         status = cairo_truetype_font_allocate_write_buffer (font,
@@ -824,7 +824,7 @@ cairo_truetype_font_write_hmtx_table (cairo_truetype_font_t *font,
 	    if (unlikely (status))
 		return _cairo_truetype_font_set_error (font, status);
         }
-        font->base.widths[i] = be16_to_cpu (p[0]);
+        font->widths[i] = be16_to_cpu (p[0]);
     }
 
     return CAIRO_STATUS_SUCCESS;
@@ -851,10 +851,10 @@ cairo_truetype_font_write_loca_table (cairo_truetype_font_t *font,
 
     if (be16_to_cpu (header.index_to_loc_format) == 0)
     {
-	for (i = 0; i < font->base.num_glyphs + 1; i++)
+	for (i = 0; i < font->num_glyphs + 1; i++)
 	    cairo_truetype_font_write_be16 (font, font->glyphs[i].location / 2);
     } else {
-	for (i = 0; i < font->base.num_glyphs + 1; i++)
+	for (i = 0; i < font->num_glyphs + 1; i++)
 	    cairo_truetype_font_write_be32 (font, font->glyphs[i].location);
     }
 
@@ -882,7 +882,7 @@ cairo_truetype_font_write_maxp_table (cairo_truetype_font_t *font,
     if (unlikely (status))
 	return _cairo_truetype_font_set_error (font, status);
 
-    maxp->num_glyphs = cpu_to_be16 (font->base.num_glyphs);
+    maxp->num_glyphs = cpu_to_be16 (font->num_glyphs);
 
     return CAIRO_STATUS_SUCCESS;
 }
@@ -1026,13 +1026,13 @@ cairo_truetype_font_use_glyph (cairo_truetype_font_t	    *font,
 	                       unsigned short		     glyph,
 			       unsigned short		    *out)
 {
-    if (glyph >= font->num_glyphs_in_face)
+    if (glyph >= font->base.num_glyphs_in_face)
 	return CAIRO_INT_STATUS_UNSUPPORTED;
 
     if (font->parent_to_subset[glyph] == 0) {
-	font->parent_to_subset[glyph] = font->base.num_glyphs;
-	font->glyphs[font->base.num_glyphs].parent_index = glyph;
-	font->base.num_glyphs++;
+	font->parent_to_subset[glyph] = font->num_glyphs;
+	font->glyphs[font->num_glyphs].parent_index = glyph;
+	font->num_glyphs++;
     }
 
     *out = font->parent_to_subset[glyph];
@@ -1185,7 +1185,7 @@ cairo_truetype_subset_init_internal (cairo_truetype_subset_t     *truetype_subse
 	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;
+	truetype_subset->widths[i] = (double)font->widths[i]/font->base.units_per_em;
 
     truetype_subset->x_min = (double)font->base.x_min/font->base.units_per_em;
     truetype_subset->y_min = (double)font->base.y_min/font->base.units_per_em;
commit 52cbf42b74785c3c3c2d15effe7bdb416ff9c8b2
Author: Adrian Johnson <ajohnson at redneon.com>
Date:   Fri Sep 22 20:10:10 2017 +0930

    truetype: reserve space in subset arrays for .notdef
    
    Subset array sizes are allocated based on the number of glyphs in the
    font. In this bug the fonts did not contain the mandatory .notdef
    glyph, hence the subset arrays were not large enough.
    
    https://bugs.freedesktop.org/show_bug.cgi?id=102922

diff --git a/src/cairo-truetype-subset.c b/src/cairo-truetype-subset.c
index 86593bc7..c4e550c7 100644
--- a/src/cairo-truetype-subset.c
+++ b/src/cairo-truetype-subset.c
@@ -208,13 +208,17 @@ _cairo_truetype_font_create (cairo_scaled_font_subset_t  *scaled_font_subset,
     if (unlikely (status))
 	goto fail1;
 
-    font->glyphs = calloc (font->num_glyphs_in_face + 1, sizeof (subset_glyph_t));
+    /* Add 2: +1 case font does not contain .notdef, and +1 because an extra
+     * entry is required to contain the end location of the last glyph.
+     */
+    font->glyphs = calloc (font->num_glyphs_in_face + 2, sizeof (subset_glyph_t));
     if (unlikely (font->glyphs == NULL)) {
 	status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
 	goto fail1;
     }
 
-    font->parent_to_subset = calloc (font->num_glyphs_in_face, sizeof (int));
+    /* Add 1 in case font does not contain .notdef */
+    font->parent_to_subset = calloc (font->num_glyphs_in_face + 1, sizeof (int));
     if (unlikely (font->parent_to_subset == NULL)) {
 	status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
 	goto fail2;
@@ -253,7 +257,8 @@ _cairo_truetype_font_create (cairo_scaled_font_subset_t  *scaled_font_subset,
                  scaled_font_subset->subset_id);
     }
 
-    font->base.widths = calloc (font->num_glyphs_in_face, sizeof (int));
+    /* Add 1 in case font does not contain .notdef */
+    font->base.widths = calloc (font->num_glyphs_in_face + 1, sizeof (int));
     if (unlikely (font->base.widths == NULL)) {
 	status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
 	goto fail4;
commit e773dd744e88dc871fdc549132f07760f1be94c7
Author: Adrian Johnson <ajohnson at redneon.com>
Date:   Sun Sep 17 14:15:25 2017 +0930

    factor out ascii to double code in cff-subset into _cairo_strtod

diff --git a/src/cairo-cff-subset.c b/src/cairo-cff-subset.c
index 49d98119..13fee505 100644
--- a/src/cairo-cff-subset.c
+++ b/src/cairo-cff-subset.c
@@ -295,20 +295,11 @@ decode_nibble (int n, char *buf)
 static unsigned char *
 decode_real (unsigned char *p, double *real)
 {
-    const char *decimal_point;
-    int decimal_point_len;
-    int n;
     char buffer[100];
-    char buffer2[200];
-    char *q;
     char *buf = buffer;
     char *buf_end = buffer + sizeof (buffer);
-
-    decimal_point = cairo_get_locale_decimal_point ();
-    decimal_point_len = strlen (decimal_point);
-
-    assert (decimal_point_len != 0);
-    assert (sizeof(buffer) + decimal_point_len < sizeof(buffer2));
+    char *end;
+    int n;
 
     p++;
     while (buf + 2 < buf_end) {
@@ -324,19 +315,7 @@ decode_real (unsigned char *p, double *real)
     };
     *buf = 0;
 
-    buf = buffer;
-    if (strchr (buffer, '.')) {
-	 q = strchr (buffer, '.');
-	 strncpy (buffer2, buffer, q - buffer);
-	 buf = buffer2 + (q - buffer);
-	 strncpy (buf, decimal_point, decimal_point_len);
-	 buf += decimal_point_len;
-	 strcpy (buf, q + 1);
-	 buf = buffer2;
-    }
-
-    if (sscanf(buf, "%lf", real) != 1)
-        *real = 0.0;
+    *real = _cairo_strtod (buffer, &end);
 
     return p;
 }
diff --git a/src/cairo-misc.c b/src/cairo-misc.c
index e9b0ab6b..19629fec 100644
--- a/src/cairo-misc.c
+++ b/src/cairo-misc.c
@@ -771,7 +771,7 @@ _cairo_half_from_float (float f)
 # include <locale.h>
 
 const char *
-cairo_get_locale_decimal_point (void)
+_cairo_get_locale_decimal_point (void)
 {
     struct lconv *locale_data = localeconv ();
     return locale_data->decimal_point;
@@ -780,12 +780,68 @@ cairo_get_locale_decimal_point (void)
 #else
 /* Android's Bionic libc doesn't provide decimal_point */
 const char *
-cairo_get_locale_decimal_point (void)
+_cairo_get_locale_decimal_point (void)
 {
     return ".";
 }
 #endif
 
+/* strtod replacement that ignores locale and only accepts decimal points */
+double
+_cairo_strtod (const char *nptr, char **endptr)
+{
+    const char *decimal_point;
+    int decimal_point_len;
+    const char *p;
+    char buf[100];
+    char *bufptr;
+    char *bufend = buf + sizeof(buf) - 1;
+    double value;
+    char *end;
+    int delta;
+    cairo_bool_t have_dp;
+
+    decimal_point = _cairo_get_locale_decimal_point ();
+    decimal_point_len = strlen (decimal_point);
+    assert (decimal_point_len != 0);
+
+    p = nptr;
+    bufptr = buf;
+    delta = 0;
+    have_dp = FALSE;
+    while (*p && _cairo_isspace (*p)) {
+	p++;
+	delta++;
+    }
+
+    while (*p && (bufptr + decimal_point_len < bufend)) {
+	if (_cairo_isdigit (*p)) {
+	    *bufptr++ = *p;
+	} else if (*p == '.') {
+	    if (have_dp)
+		break;
+	    strncpy (bufptr, decimal_point, decimal_point_len);
+	    bufptr += decimal_point_len;
+	    delta -= decimal_point_len - 1;
+	    have_dp = TRUE;
+	} else {
+	    break;
+	}
+	p++;
+    }
+    *bufptr = 0;
+
+    value = strtod (buf, &end);
+    if (endptr) {
+	if (end == buf)
+	    *endptr = (char*)(nptr);
+	else
+	    *endptr = (char*)(nptr + (end - buf) + delta);
+    }
+
+    return value;
+}
+
 #ifdef _WIN32
 
 #define WIN32_LEAN_AND_MEAN
diff --git a/src/cairo-output-stream.c b/src/cairo-output-stream.c
index 07991703..76d718aa 100644
--- a/src/cairo-output-stream.c
+++ b/src/cairo-output-stream.c
@@ -312,7 +312,7 @@ _cairo_dtostr (char *buffer, size_t size, double d, cairo_bool_t limited_precisi
     if (d == 0.0)
 	d = 0.0;
 
-    decimal_point = cairo_get_locale_decimal_point ();
+    decimal_point = _cairo_get_locale_decimal_point ();
     decimal_point_len = strlen (decimal_point);
 
     assert (decimal_point_len != 0);
diff --git a/src/cairo-type1-subset.c b/src/cairo-type1-subset.c
index 810dc9f7..4dd7ac17 100644
--- a/src/cairo-type1-subset.c
+++ b/src/cairo-type1-subset.c
@@ -311,7 +311,7 @@ cairo_type1_font_subset_get_matrix (cairo_type1_font_subset_t *font,
     const char *decimal_point;
     int decimal_point_len;
 
-    decimal_point = cairo_get_locale_decimal_point ();
+    decimal_point = _cairo_get_locale_decimal_point ();
     decimal_point_len = strlen (decimal_point);
 
     assert (decimal_point_len != 0);
diff --git a/src/cairoint.h b/src/cairoint.h
index f6435592..8573ae61 100644
--- a/src/cairoint.h
+++ b/src/cairoint.h
@@ -913,7 +913,10 @@ cairo_private void
 _cairo_intern_string_reset_static_data (void);
 
 cairo_private const char *
-cairo_get_locale_decimal_point (void);
+_cairo_get_locale_decimal_point (void);
+
+cairo_private double
+_cairo_strtod (const char *nptr, char **endptr);
 
 /* cairo-path-fixed.c */
 cairo_private cairo_path_fixed_t *


More information about the cairo-commit mailing list