[cairo-commit] 2 commits - src/cairo.c src/cairo-font-face.c src/cairo-font-options.c src/cairo-ft-font.c src/cairo-gstate.c src/cairo-scaled-font.c src/cairo-win32-font.c test/font-options.c test/.gitignore test/Makefile.am

Chris Wilson ickle at kemper.freedesktop.org
Thu Jan 17 14:39:27 PST 2008


 src/cairo-font-face.c    |    8 ++--
 src/cairo-font-options.c |   65 +++++++++++++++++++++++++--------
 src/cairo-ft-font.c      |   16 +++++---
 src/cairo-gstate.c       |    2 -
 src/cairo-scaled-font.c  |   18 ++++++---
 src/cairo-win32-font.c   |    4 +-
 src/cairo.c              |   10 +++--
 test/.gitignore          |    1 
 test/Makefile.am         |   12 +++---
 test/font-options.c      |   91 +++++++++++++++++++++++++++++++++++++++++++++++
 10 files changed, 184 insertions(+), 43 deletions(-)

New commits:
commit 0086db893cba90dc73824d77c661d2965ad48112
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Thu Jan 17 22:31:05 2008 +0000

    [cairo-font-options] Treat NULL as a default cairo_font_options_t
    
    Interpret a NULL cairo_font_options_t as the default values - i.e
    as if it were a fresh pointer returned by cairo_font_options_create().

diff --git a/src/cairo-font-face.c b/src/cairo-font-face.c
index f729476..b944534 100644
--- a/src/cairo-font-face.c
+++ b/src/cairo-font-face.c
@@ -476,9 +476,11 @@ _cairo_toy_font_face_scaled_font_create (void                *abstract_font_face
     if (font_face->base.status)
 	return font_face->base.status;
 
-    status = cairo_font_options_status ((cairo_font_options_t *) options);
-    if (status)
-	return status;
+    if (options != NULL) {
+	status = cairo_font_options_status ((cairo_font_options_t *) options);
+	if (status)
+	    return status;
+    }
 
     return _cairo_font_face_set_error (&font_face->base,
 	                               backend->create_toy (font_face,
diff --git a/src/cairo-font-options.c b/src/cairo-font-options.c
index a2cce35..7005790 100644
--- a/src/cairo-font-options.c
+++ b/src/cairo-font-options.c
@@ -65,10 +65,13 @@ void
 _cairo_font_options_init_copy (cairo_font_options_t		*options,
 			       const cairo_font_options_t	*other)
 {
-    options->antialias = other->antialias;
-    options->subpixel_order = other->subpixel_order;
-    options->hint_style = other->hint_style;
-    options->hint_metrics = other->hint_metrics;
+    if (other != NULL) {
+	options->antialias = other->antialias;
+	options->subpixel_order = other->subpixel_order;
+	options->hint_style = other->hint_style;
+	options->hint_metrics = other->hint_metrics;
+    } else
+	_cairo_font_options_init_default (options);
 }
 
 /**
@@ -91,7 +94,7 @@ cairo_font_options_create (void)
     options = malloc (sizeof (cairo_font_options_t));
     if (!options) {
 	_cairo_error_throw (CAIRO_STATUS_NO_MEMORY);
-	return (cairo_font_options_t *)&_cairo_font_options_nil;
+	return (cairo_font_options_t *) &_cairo_font_options_nil;
     }
 
     _cairo_font_options_init_default (options);
@@ -118,13 +121,16 @@ cairo_font_options_copy (const cairo_font_options_t *original)
 {
     cairo_font_options_t *options;
 
-    if (cairo_font_options_status ((cairo_font_options_t *) original))
-	return (cairo_font_options_t *)&_cairo_font_options_nil;
+    if (original != NULL &&
+	cairo_font_options_status ((cairo_font_options_t *) original))
+    {
+	return (cairo_font_options_t *) &_cairo_font_options_nil;
+    }
 
     options = malloc (sizeof (cairo_font_options_t));
     if (!options) {
 	_cairo_error_throw (CAIRO_STATUS_NO_MEMORY);
-	return (cairo_font_options_t *)&_cairo_font_options_nil;
+	return (cairo_font_options_t *) &_cairo_font_options_nil;
     }
 
     _cairo_font_options_init_copy (options, original);
@@ -163,7 +169,7 @@ cairo_font_options_status (cairo_font_options_t *options)
 {
     if (options == NULL)
 	return CAIRO_STATUS_NULL_POINTER;
-    else if (options == (cairo_font_options_t *)&_cairo_font_options_nil)
+    else if (options == (cairo_font_options_t *) &_cairo_font_options_nil)
 	return CAIRO_STATUS_NO_MEMORY;
     else
 	return CAIRO_STATUS_SUCCESS;
@@ -187,6 +193,10 @@ cairo_font_options_merge (cairo_font_options_t       *options,
     if (cairo_font_options_status (options))
 	return;
 
+    /* A NULL other maps to the defaults and would not overwrite options */
+    if (cairo_font_options_status ((cairo_font_options_t *) other))
+	return;
+
     if (other->antialias != CAIRO_ANTIALIAS_DEFAULT)
 	options->antialias = other->antialias;
     if (other->subpixel_order != CAIRO_SUBPIXEL_ORDER_DEFAULT)
@@ -211,6 +221,14 @@ cairo_bool_t
 cairo_font_options_equal (const cairo_font_options_t *options,
 			  const cairo_font_options_t *other)
 {
+    if (options == NULL)
+	options = &_cairo_font_options_nil;
+    if (other == NULL)
+	other = &_cairo_font_options_nil;
+
+    if (options == other)
+	return TRUE;
+
     return (options->antialias == other->antialias &&
 	    options->subpixel_order == other->subpixel_order &&
 	    options->hint_style == other->hint_style &&
@@ -233,6 +251,9 @@ slim_hidden_def (cairo_font_options_equal);
 unsigned long
 cairo_font_options_hash (const cairo_font_options_t *options)
 {
+    if (options == NULL)
+	options = &_cairo_font_options_nil;
+
     return ((options->antialias) |
 	    (options->subpixel_order << 4) |
 	    (options->hint_style << 8) |
@@ -270,6 +291,9 @@ slim_hidden_def (cairo_font_options_set_antialias);
 cairo_antialias_t
 cairo_font_options_get_antialias (const cairo_font_options_t *options)
 {
+    if (cairo_font_options_status ((cairo_font_options_t *) options))
+	return CAIRO_ANTIALIAS_DEFAULT;
+
     return options->antialias;
 }
 
@@ -307,6 +331,9 @@ slim_hidden_def (cairo_font_options_set_subpixel_order);
 cairo_subpixel_order_t
 cairo_font_options_get_subpixel_order (const cairo_font_options_t *options)
 {
+    if (cairo_font_options_status ((cairo_font_options_t *) options))
+	return CAIRO_SUBPIXEL_ORDER_DEFAULT;
+
     return options->subpixel_order;
 }
 
@@ -343,6 +370,9 @@ slim_hidden_def (cairo_font_options_set_hint_style);
 cairo_hint_style_t
 cairo_font_options_get_hint_style (const cairo_font_options_t *options)
 {
+    if (cairo_font_options_status ((cairo_font_options_t *) options))
+	return CAIRO_HINT_STYLE_DEFAULT;
+
     return options->hint_style;
 }
 
@@ -379,5 +409,8 @@ slim_hidden_def (cairo_font_options_set_hint_metrics);
 cairo_hint_metrics_t
 cairo_font_options_get_hint_metrics (const cairo_font_options_t *options)
 {
+    if (cairo_font_options_status ((cairo_font_options_t *) options))
+	return CAIRO_HINT_METRICS_DEFAULT;
+
     return options->hint_metrics;
 }
diff --git a/src/cairo-ft-font.c b/src/cairo-ft-font.c
index 0db38ae..e2ebc2d 100644
--- a/src/cairo-ft-font.c
+++ b/src/cairo-ft-font.c
@@ -1454,6 +1454,8 @@ _cairo_ft_options_merge (cairo_ft_options_t *options,
 
     options->load_flags = load_flags | load_target;
     options->extra_flags = other->extra_flags;
+    if (options->base.hint_metrics != CAIRO_HINT_METRICS_OFF)
+	options->extra_flags |= CAIRO_FT_OPTIONS_HINT_METRICS;
 }
 
 static cairo_status_t
@@ -1484,9 +1486,6 @@ _cairo_ft_scaled_font_create (cairo_ft_unscaled_font_t	 *unscaled,
     _cairo_unscaled_font_reference (&unscaled->base);
     scaled_font->unscaled = unscaled;
 
-    if (options->hint_metrics != CAIRO_HINT_METRICS_OFF)
-	ft_options.extra_flags |= CAIRO_FT_OPTIONS_HINT_METRICS;
-
     _cairo_font_options_init_copy (&scaled_font->ft_options.base, options);
     _cairo_ft_options_merge (&scaled_font->ft_options, &ft_options);
 
@@ -1645,9 +1644,11 @@ _cairo_ft_scaled_font_create_toy (cairo_toy_font_face_t	      *toy_face,
 	goto FREE_PATTERN;
     }
 
-    status = _cairo_ft_font_options_substitute (font_options, pattern);
-    if (status)
-	goto FREE_PATTERN;
+    if (font_options != NULL) {
+	status = _cairo_ft_font_options_substitute (font_options, pattern);
+	if (status)
+	    goto FREE_PATTERN;
+    }
 
     FcDefaultSubstitute (pattern);
 
@@ -2433,6 +2434,9 @@ void
 cairo_ft_font_options_substitute (const cairo_font_options_t *options,
 				  FcPattern                  *pattern)
 {
+    if (cairo_font_options_status ((cairo_font_options_t *) options))
+	return;
+
     _cairo_ft_font_options_substitute (options, pattern);
 }
 
diff --git a/src/cairo-gstate.c b/src/cairo-gstate.c
index 099f7ed..3577d84 100644
--- a/src/cairo-gstate.c
+++ b/src/cairo-gstate.c
@@ -1365,7 +1365,7 @@ _cairo_gstate_set_font_options (cairo_gstate_t             *gstate,
 {
     _cairo_gstate_unset_scaled_font (gstate);
 
-    gstate->font_options = *options;
+    _cairo_font_options_init_copy (&gstate->font_options, options);
 }
 
 void
diff --git a/src/cairo-scaled-font.c b/src/cairo-scaled-font.c
index 2ea85ad..6a6412e 100644
--- a/src/cairo-scaled-font.c
+++ b/src/cairo-scaled-font.c
@@ -412,7 +412,7 @@ _cairo_scaled_font_init_key (cairo_scaled_font_t        *scaled_font,
     /* ignore translation values in the ctm */
     scaled_font->ctm.x0 = 0.;
     scaled_font->ctm.y0 = 0.;
-    scaled_font->options = *options;
+    _cairo_font_options_init_copy (&scaled_font->options, options);
 
     /* We do a bytewise hash on the font matrices */
     hash = _hash_bytes_fnv ((unsigned char *)(&scaled_font->font_matrix.xx),
@@ -466,9 +466,11 @@ _cairo_scaled_font_init (cairo_scaled_font_t               *scaled_font,
     cairo_matrix_t inverse;
     cairo_status_t status;
 
-    status = cairo_font_options_status ((cairo_font_options_t *) options);
-    if (status)
-	return status;
+    if (options != NULL) {
+	status = cairo_font_options_status ((cairo_font_options_t *) options);
+	if (status)
+	    return status;
+    }
 
     /* Initialize scaled_font->scale early for easier bail out on an
      * invalid matrix. */
@@ -580,7 +582,8 @@ _cairo_scaled_font_fini (cairo_scaled_font_t *scaled_font)
  * @ctm: user to device transformation matrix with which the font will
  *       be used.
  * @options: options to use when getting metrics for the font and
- *           rendering with it.
+ *           rendering with it. A %NULL pointer will be interpreted as
+ *           meaning the default options.
  *
  * Creates a #cairo_scaled_font_t object from a font face and matrices that
  * describe the size of the font and the environment in which it will
@@ -602,8 +605,11 @@ cairo_scaled_font_create (cairo_font_face_t          *font_face,
     if (font_face->status)
 	return (cairo_scaled_font_t *)&_cairo_scaled_font_nil;
 
-    if (cairo_font_options_status ((cairo_font_options_t *) options))
+    if (options != NULL &&
+	cairo_font_options_status ((cairo_font_options_t *) options))
+    {
 	return (cairo_scaled_font_t *)&_cairo_scaled_font_nil;
+    }
 
     if (! _cairo_matrix_is_invertible (font_matrix))
 	return (cairo_scaled_font_t *)&_cairo_scaled_font_nil;
diff --git a/src/cairo-win32-font.c b/src/cairo-win32-font.c
index 19c494d..f7ae1f0 100644
--- a/src/cairo-win32-font.c
+++ b/src/cairo-win32-font.c
@@ -273,7 +273,7 @@ _win32_scaled_font_create (LOGFONTW                   *logfont,
      * XXX: The other option we could pay attention to, but don't
      *      here is the hint_metrics options.
      */
-    if (options->antialias == CAIRO_ANTIALIAS_DEFAULT)
+    if (options == NULL || options->antialias == CAIRO_ANTIALIAS_DEFAULT)
 	f->quality = _get_system_quality ();
     else {
 	switch (options->antialias) {
@@ -300,7 +300,7 @@ _win32_scaled_font_create (LOGFONTW                   *logfont,
 
     if (f->quality == logfont->lfQuality ||
         (logfont->lfQuality == DEFAULT_QUALITY &&
-         options->antialias == CAIRO_ANTIALIAS_DEFAULT)) {
+         (options == NULL || options->antialias == CAIRO_ANTIALIAS_DEFAULT))) {
         /* If face_hfont is non-NULL, then we can use it to avoid creating our
          * own --- because the constraints on face_hfont mentioned above
          * guarantee it was created in exactly the same way that
diff --git a/src/cairo.c b/src/cairo.c
index 2eac030..4a7aec1 100644
--- a/src/cairo.c
+++ b/src/cairo.c
@@ -2666,10 +2666,12 @@ cairo_set_font_options (cairo_t                    *cr,
     if (cr->status)
 	return;
 
-    status = cairo_font_options_status ((cairo_font_options_t *) options);
-    if (status) {
-	_cairo_set_error (cr, status);
-	return;
+    if (options != NULL) {
+	status = cairo_font_options_status ((cairo_font_options_t *) options);
+	if (status) {
+	    _cairo_set_error (cr, status);
+	    return;
+	}
     }
 
     _cairo_gstate_set_font_options (cr->gstate, options);
diff --git a/test/.gitignore b/test/.gitignore
index 682b6fc..e3decc7 100644
--- a/test/.gitignore
+++ b/test/.gitignore
@@ -65,6 +65,7 @@ ft-text-vertical-layout-type1
 ft-text-vertical-layout-type3
 font-face-get-type
 font-matrix-translation
+font-options
 get-and-set
 get-clip
 get-group-target
diff --git a/test/Makefile.am b/test/Makefile.am
index 5ed76eb..81d71ba 100644
--- a/test/Makefile.am
+++ b/test/Makefile.am
@@ -50,6 +50,7 @@ fill-rule$(EXEEXT)					\
 filter-nearest-offset$(EXEEXT)				\
 font-face-get-type$(EXEEXT)				\
 font-matrix-translation$(EXEEXT)			\
+font-options$(EXEEXT)					\
 glyph-cache-pressure$(EXEEXT)				\
 get-and-set$(EXEEXT)					\
 get-clip$(EXEEXT)					\
@@ -533,13 +534,14 @@ surface-pattern-scale-up$(EXEEXT)
 
 # Any test that doesn't generate a log file goes here
 NOLOG_TESTS =			\
-user-data			\
-svg-surface			\
-svg-clip			\
+fallback-resolution		\
+font-options			\
+multi-page			\
 pdf-features			\
 ps-features			\
-multi-page			\
-fallback-resolution
+svg-clip			\
+svg-surface			\
+user-data
 
 # A hook that summarises the failures
 check: AM_MAKEFLAGS+=-k
diff --git a/test/font-options.c b/test/font-options.c
new file mode 100644
index 0000000..fdcde15
--- /dev/null
+++ b/test/font-options.c
@@ -0,0 +1,91 @@
+/*
+ * Copyright © 2008 Chris Wilson
+ *
+ * Permission to use, copy, modify, distribute, and sell this software
+ * and its documentation for any purpose is hereby granted without
+ * fee, provided that the above copyright notice appear in all copies
+ * and that both that copyright notice and this permission notice
+ * appear in supporting documentation, and that the name of
+ * Chris Wilson not be used in advertising or publicity pertaining to
+ * distribution of the software without specific, written prior
+ * permission. Chris Wilson makes no representations about the
+ * suitability of this software for any purpose.  It is provided "as
+ * is" without express or implied warranty.
+ *
+ * CHRIS WILSON DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS
+ * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS, IN NO EVENT SHALL CHRIS WILSON BE LIABLE FOR ANY SPECIAL,
+ * INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER
+ * RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR
+ * IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ * Author: Chris Wilson <chris at chris-wilson.co.uk>
+ */
+
+#include <cairo.h>
+#include <assert.h>
+#include <stdlib.h>
+
+int
+main (void)
+{
+    cairo_font_options_t *options1;
+    cairo_font_options_t *options2;
+    cairo_surface_t *surface;
+    cairo_matrix_t identity;
+    cairo_t *cr;
+    cairo_scaled_font_t *scaled_font;
+
+    /* first check NULL handling of cairo_font_options_t */
+    options1 = cairo_font_options_create ();
+    options2 = cairo_font_options_copy (NULL);
+
+    assert (cairo_font_options_equal (options1, options2));
+    assert (cairo_font_options_equal (NULL, options2));
+    assert (cairo_font_options_equal (options1, NULL));
+
+    assert (cairo_font_options_hash (options1) == cairo_font_options_hash (options2));
+    assert (cairo_font_options_hash (NULL) == cairo_font_options_hash (options2));
+    assert (cairo_font_options_hash (options1) == cairo_font_options_hash (NULL));
+
+    cairo_font_options_merge (NULL, NULL);
+    cairo_font_options_merge (options1, NULL);
+    cairo_font_options_merge (options1, options2);
+
+    cairo_font_options_destroy (NULL);
+    cairo_font_options_destroy (options1);
+    cairo_font_options_destroy (options2);
+
+    cairo_font_options_set_antialias (NULL, CAIRO_ANTIALIAS_DEFAULT);
+    cairo_font_options_get_antialias (NULL);
+
+    cairo_font_options_set_subpixel_order (NULL, CAIRO_SUBPIXEL_ORDER_DEFAULT);
+    cairo_font_options_get_subpixel_order (NULL);
+
+    cairo_font_options_set_hint_style (NULL, CAIRO_HINT_STYLE_DEFAULT);
+    cairo_font_options_get_hint_style (NULL);
+
+    cairo_font_options_set_hint_metrics (NULL, CAIRO_HINT_METRICS_DEFAULT);
+    cairo_font_options_get_hint_metrics (NULL);
+
+    /* Now try creating fonts with NULLs */
+    surface = cairo_image_surface_create (CAIRO_FORMAT_RGB24, 0, 0);
+    cr = cairo_create (surface);
+    cairo_surface_destroy (surface);
+
+    cairo_matrix_init_identity (&identity);
+    scaled_font = cairo_scaled_font_create (cairo_get_font_face (cr),
+	                                    &identity, &identity,
+					    NULL);
+    assert (cairo_scaled_font_status (scaled_font) == CAIRO_STATUS_SUCCESS);
+    cairo_scaled_font_get_font_options (scaled_font, NULL);
+    cairo_scaled_font_destroy (scaled_font);
+
+    cairo_set_font_options (cr, NULL);
+    cairo_get_font_options (cr, NULL);
+
+    cairo_destroy (cr);
+
+    return 0;
+}
commit 02d0e070638f668bf50a8ce2174c21e5614dd6c4
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Thu Jan 17 21:39:31 2008 +0000

    [cairo-font-options] Use cairo_font_options_status() rather open-coding.
    
    By switching to cairo_font_options_status() instead of checking against
    the _cairo_font_options_nil error object, the API is protected from NULL
    dereferences.

diff --git a/src/cairo-font-options.c b/src/cairo-font-options.c
index 6b2cb08..a2cce35 100644
--- a/src/cairo-font-options.c
+++ b/src/cairo-font-options.c
@@ -52,7 +52,7 @@ static const cairo_font_options_t _cairo_font_options_nil = {
 void
 _cairo_font_options_init_default (cairo_font_options_t *options)
 {
-    if (options == (cairo_font_options_t *)&_cairo_font_options_nil)
+    if (cairo_font_options_status (options))
 	return;
 
     options->antialias = CAIRO_ANTIALIAS_DEFAULT;
@@ -118,7 +118,7 @@ cairo_font_options_copy (const cairo_font_options_t *original)
 {
     cairo_font_options_t *options;
 
-    if (original == &_cairo_font_options_nil)
+    if (cairo_font_options_status ((cairo_font_options_t *) original))
 	return (cairo_font_options_t *)&_cairo_font_options_nil;
 
     options = malloc (sizeof (cairo_font_options_t));
@@ -142,7 +142,7 @@ cairo_font_options_copy (const cairo_font_options_t *original)
 void
 cairo_font_options_destroy (cairo_font_options_t *options)
 {
-    if (options == (cairo_font_options_t *)&_cairo_font_options_nil)
+    if (cairo_font_options_status (options))
 	return;
 
     free (options);
@@ -184,7 +184,7 @@ void
 cairo_font_options_merge (cairo_font_options_t       *options,
 			  const cairo_font_options_t *other)
 {
-    if (options == (cairo_font_options_t *)&_cairo_font_options_nil)
+    if (cairo_font_options_status (options))
 	return;
 
     if (other->antialias != CAIRO_ANTIALIAS_DEFAULT)
@@ -252,7 +252,7 @@ void
 cairo_font_options_set_antialias (cairo_font_options_t *options,
 				  cairo_antialias_t     antialias)
 {
-    if (options == (cairo_font_options_t *)&_cairo_font_options_nil)
+    if (cairo_font_options_status (options))
 	return;
 
     options->antialias = antialias;
@@ -288,7 +288,7 @@ void
 cairo_font_options_set_subpixel_order (cairo_font_options_t   *options,
 				       cairo_subpixel_order_t  subpixel_order)
 {
-    if (options == (cairo_font_options_t *)&_cairo_font_options_nil)
+    if (cairo_font_options_status (options))
 	return;
 
     options->subpixel_order = subpixel_order;
@@ -324,7 +324,7 @@ void
 cairo_font_options_set_hint_style (cairo_font_options_t *options,
 				   cairo_hint_style_t    hint_style)
 {
-    if (options == (cairo_font_options_t *)&_cairo_font_options_nil)
+    if (cairo_font_options_status (options))
 	return;
 
     options->hint_style = hint_style;
@@ -360,7 +360,7 @@ void
 cairo_font_options_set_hint_metrics (cairo_font_options_t *options,
 				     cairo_hint_metrics_t  hint_metrics)
 {
-    if (options == (cairo_font_options_t *)&_cairo_font_options_nil)
+    if (cairo_font_options_status (options))
 	return;
 
     options->hint_metrics = hint_metrics;


More information about the cairo-commit mailing list