LCOV - code coverage report
Current view: top level - gfx/cairo/cairo/src - cairo-toy-font-face.c (source / functions) Hit Total Coverage
Test: output.info Lines: 0 164 0.0 %
Date: 2017-07-14 16:53:18 Functions: 0 16 0.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* -*- Mode: c; c-basic-offset: 4; indent-tabs-mode: t; tab-width: 8; -*- */
       2             : /* cairo - a vector graphics library with display and print output
       3             :  *
       4             :  * Copyright © 2002 University of Southern California
       5             :  * Copyright © 2005,2008 Red Hat Inc.
       6             :  *
       7             :  * This library is free software; you can redistribute it and/or
       8             :  * modify it either under the terms of the GNU Lesser General Public
       9             :  * License version 2.1 as published by the Free Software Foundation
      10             :  * (the "LGPL") or, at your option, under the terms of the Mozilla
      11             :  * Public License Version 1.1 (the "MPL"). If you do not alter this
      12             :  * notice, a recipient may use your version of this file under either
      13             :  * the MPL or the LGPL.
      14             :  *
      15             :  * You should have received a copy of the LGPL along with this library
      16             :  * in the file COPYING-LGPL-2.1; if not, write to the Free Software
      17             :  * Foundation, Inc., 51 Franklin Street, Suite 500, Boston, MA 02110-1335, USA
      18             :  * You should have received a copy of the MPL along with this library
      19             :  * in the file COPYING-MPL-1.1
      20             :  *
      21             :  * The contents of this file are subject to the Mozilla Public License
      22             :  * Version 1.1 (the "License"); you may not use this file except in
      23             :  * compliance with the License. You may obtain a copy of the License at
      24             :  * http://www.mozilla.org/MPL/
      25             :  *
      26             :  * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
      27             :  * OF ANY KIND, either express or implied. See the LGPL or the MPL for
      28             :  * the specific language governing rights and limitations.
      29             :  *
      30             :  * The Original Code is the cairo graphics library.
      31             :  *
      32             :  * The Initial Developer of the Original Code is University of Southern
      33             :  * California.
      34             :  *
      35             :  * Contributor(s):
      36             :  *      Carl D. Worth <cworth@cworth.org>
      37             :  *      Graydon Hoare <graydon@redhat.com>
      38             :  *      Owen Taylor <otaylor@redhat.com>
      39             :  *      Behdad Esfahbod <behdad@behdad.org>
      40             :  */
      41             : 
      42             : #define _BSD_SOURCE /* for strdup() */
      43             : #include "cairoint.h"
      44             : #include "cairo-error-private.h"
      45             : 
      46             : 
      47             : static const cairo_font_face_t _cairo_font_face_null_pointer = {
      48             :     { 0 },                              /* hash_entry */
      49             :     CAIRO_STATUS_NULL_POINTER,          /* status */
      50             :     CAIRO_REFERENCE_COUNT_INVALID,      /* ref_count */
      51             :     { 0, 0, 0, NULL },                  /* user_data */
      52             :     NULL
      53             : };
      54             : 
      55             : static const cairo_font_face_t _cairo_font_face_invalid_string = {
      56             :     { 0 },                              /* hash_entry */
      57             :     CAIRO_STATUS_INVALID_STRING,        /* status */
      58             :     CAIRO_REFERENCE_COUNT_INVALID,      /* ref_count */
      59             :     { 0, 0, 0, NULL },                  /* user_data */
      60             :     NULL
      61             : };
      62             : 
      63             : static const cairo_font_face_t _cairo_font_face_invalid_slant = {
      64             :     { 0 },                              /* hash_entry */
      65             :     CAIRO_STATUS_INVALID_SLANT,         /* status */
      66             :     CAIRO_REFERENCE_COUNT_INVALID,      /* ref_count */
      67             :     { 0, 0, 0, NULL },                  /* user_data */
      68             :     NULL
      69             : };
      70             : 
      71             : static const cairo_font_face_t _cairo_font_face_invalid_weight = {
      72             :     { 0 },                              /* hash_entry */
      73             :     CAIRO_STATUS_INVALID_WEIGHT,        /* status */
      74             :     CAIRO_REFERENCE_COUNT_INVALID,      /* ref_count */
      75             :     { 0, 0, 0, NULL },                  /* user_data */
      76             :     NULL
      77             : };
      78             : 
      79             : 
      80             : static const cairo_font_face_backend_t _cairo_toy_font_face_backend;
      81             : 
      82             : static int
      83             : _cairo_toy_font_face_keys_equal (const void *key_a,
      84             :                                  const void *key_b);
      85             : 
      86             : /* We maintain a hash table from family/weight/slant =>
      87             :  * #cairo_font_face_t for #cairo_toy_font_t. The primary purpose of
      88             :  * this mapping is to provide unique #cairo_font_face_t values so that
      89             :  * our cache and mapping from #cairo_font_face_t => #cairo_scaled_font_t
      90             :  * works. Once the corresponding #cairo_font_face_t objects fall out of
      91             :  * downstream caches, we don't need them in this hash table anymore.
      92             :  *
      93             :  * Modifications to this hash table are protected by
      94             :  * _cairo_toy_font_face_mutex.
      95             :  */
      96             : static cairo_hash_table_t *cairo_toy_font_face_hash_table = NULL;
      97             : 
      98             : static cairo_hash_table_t *
      99           0 : _cairo_toy_font_face_hash_table_lock (void)
     100             : {
     101           0 :     CAIRO_MUTEX_LOCK (_cairo_toy_font_face_mutex);
     102             : 
     103           0 :     if (cairo_toy_font_face_hash_table == NULL)
     104             :     {
     105           0 :         cairo_toy_font_face_hash_table =
     106           0 :             _cairo_hash_table_create (_cairo_toy_font_face_keys_equal);
     107             : 
     108           0 :         if (cairo_toy_font_face_hash_table == NULL) {
     109           0 :             CAIRO_MUTEX_UNLOCK (_cairo_toy_font_face_mutex);
     110           0 :             return NULL;
     111             :         }
     112             :     }
     113             : 
     114           0 :     return cairo_toy_font_face_hash_table;
     115             : }
     116             : 
     117             : static void
     118           0 : _cairo_toy_font_face_hash_table_unlock (void)
     119             : {
     120           0 :     CAIRO_MUTEX_UNLOCK (_cairo_toy_font_face_mutex);
     121           0 : }
     122             : 
     123             : /**
     124             :  * _cairo_toy_font_face_init_key:
     125             :  *
     126             :  * Initialize those portions of #cairo_toy_font_face_t needed to use
     127             :  * it as a hash table key, including the hash code buried away in
     128             :  * font_face->base.hash_entry. No memory allocation is performed here
     129             :  * so that no fini call is needed. We do this to make it easier to use
     130             :  * an automatic #cairo_toy_font_face_t variable as a key.
     131             :  **/
     132             : static void
     133           0 : _cairo_toy_font_face_init_key (cairo_toy_font_face_t *key,
     134             :                                const char            *family,
     135             :                                cairo_font_slant_t     slant,
     136             :                                cairo_font_weight_t    weight)
     137             : {
     138             :     unsigned long hash;
     139             : 
     140           0 :     key->family = family;
     141           0 :     key->owns_family = FALSE;
     142             : 
     143           0 :     key->slant = slant;
     144           0 :     key->weight = weight;
     145             : 
     146             :     /* 1607 and 1451 are just a couple of arbitrary primes. */
     147           0 :     hash = _cairo_hash_string (family);
     148           0 :     hash += ((unsigned long) slant) * 1607;
     149           0 :     hash += ((unsigned long) weight) * 1451;
     150             : 
     151           0 :     assert (hash != 0);
     152           0 :     key->base.hash_entry.hash = hash;
     153           0 : }
     154             : 
     155             : static cairo_status_t
     156           0 : _cairo_toy_font_face_create_impl_face (cairo_toy_font_face_t *font_face,
     157             :                                        cairo_font_face_t **impl_font_face)
     158             : {
     159           0 :     const cairo_font_face_backend_t * backend = CAIRO_FONT_FACE_BACKEND_DEFAULT;
     160           0 :     cairo_int_status_t status = CAIRO_INT_STATUS_UNSUPPORTED;
     161             : 
     162           0 :     if (unlikely (font_face->base.status))
     163           0 :         return font_face->base.status;
     164             : 
     165           0 :     if (backend->create_for_toy != NULL &&
     166           0 :         0 != strncmp (font_face->family, CAIRO_USER_FONT_FAMILY_DEFAULT,
     167             :                       strlen (CAIRO_USER_FONT_FAMILY_DEFAULT)))
     168             :     {
     169           0 :         status = backend->create_for_toy (font_face, impl_font_face);
     170             :     }
     171             : 
     172           0 :     if (status == CAIRO_INT_STATUS_UNSUPPORTED) {
     173           0 :         backend = &_cairo_user_font_face_backend;
     174           0 :         status = backend->create_for_toy (font_face, impl_font_face);
     175             :     }
     176             : 
     177           0 :     return status;
     178             : }
     179             : 
     180             : static cairo_status_t
     181           0 : _cairo_toy_font_face_init (cairo_toy_font_face_t *font_face,
     182             :                            const char            *family,
     183             :                            cairo_font_slant_t     slant,
     184             :                            cairo_font_weight_t    weight)
     185             : {
     186             :     char *family_copy;
     187             :     cairo_status_t status;
     188             : 
     189           0 :     family_copy = strdup (family);
     190           0 :     if (unlikely (family_copy == NULL))
     191           0 :         return _cairo_error (CAIRO_STATUS_NO_MEMORY);
     192             : 
     193           0 :     _cairo_toy_font_face_init_key (font_face, family_copy, slant, weight);
     194           0 :     font_face->owns_family = TRUE;
     195             : 
     196           0 :     _cairo_font_face_init (&font_face->base, &_cairo_toy_font_face_backend);
     197             : 
     198           0 :     status = _cairo_toy_font_face_create_impl_face (font_face,
     199             :                                                     &font_face->impl_face);
     200           0 :     if (unlikely (status)) {
     201           0 :         free (family_copy);
     202           0 :         return status;
     203             :     }
     204             : 
     205           0 :     return CAIRO_STATUS_SUCCESS;
     206             : }
     207             : 
     208             : static void
     209           0 : _cairo_toy_font_face_fini (cairo_toy_font_face_t *font_face)
     210             : {
     211             :     /* We assert here that we own font_face->family before casting
     212             :      * away the const qualifer. */
     213           0 :     assert (font_face->owns_family);
     214           0 :     free ((char*) font_face->family);
     215             : 
     216           0 :     if (font_face->impl_face)
     217           0 :         cairo_font_face_destroy (font_face->impl_face);
     218           0 : }
     219             : 
     220             : static int
     221           0 : _cairo_toy_font_face_keys_equal (const void *key_a,
     222             :                                  const void *key_b)
     223             : {
     224           0 :     const cairo_toy_font_face_t *face_a = key_a;
     225           0 :     const cairo_toy_font_face_t *face_b = key_b;
     226             : 
     227           0 :     return (strcmp (face_a->family, face_b->family) == 0 &&
     228           0 :             face_a->slant == face_b->slant &&
     229           0 :             face_a->weight == face_b->weight);
     230             : }
     231             : 
     232             : /**
     233             :  * cairo_toy_font_face_create:
     234             :  * @family: a font family name, encoded in UTF-8
     235             :  * @slant: the slant for the font
     236             :  * @weight: the weight for the font
     237             :  *
     238             :  * Creates a font face from a triplet of family, slant, and weight.
     239             :  * These font faces are used in implementation of the the #cairo_t "toy"
     240             :  * font API.
     241             :  *
     242             :  * If @family is the zero-length string "", the platform-specific default
     243             :  * family is assumed.  The default family then can be queried using
     244             :  * cairo_toy_font_face_get_family().
     245             :  *
     246             :  * The cairo_select_font_face() function uses this to create font faces.
     247             :  * See that function for limitations and other details of toy font faces.
     248             :  *
     249             :  * Return value: a newly created #cairo_font_face_t. Free with
     250             :  *  cairo_font_face_destroy() when you are done using it.
     251             :  *
     252             :  * Since: 1.8
     253             :  **/
     254             : cairo_font_face_t *
     255           0 : cairo_toy_font_face_create (const char          *family,
     256             :                             cairo_font_slant_t   slant,
     257             :                             cairo_font_weight_t  weight)
     258             : {
     259             :     cairo_status_t status;
     260             :     cairo_toy_font_face_t key, *font_face;
     261             :     cairo_hash_table_t *hash_table;
     262             : 
     263           0 :     if (family == NULL)
     264           0 :         return (cairo_font_face_t*) &_cairo_font_face_null_pointer;
     265             : 
     266             :     /* Make sure we've got valid UTF-8 for the family */
     267           0 :     status = _cairo_utf8_to_ucs4 (family, -1, NULL, NULL);
     268           0 :     if (unlikely (status)) {
     269           0 :         if (status == CAIRO_STATUS_INVALID_STRING)
     270           0 :             return (cairo_font_face_t*) &_cairo_font_face_invalid_string;
     271             : 
     272           0 :         return (cairo_font_face_t*) &_cairo_font_face_nil;
     273             :     }
     274             : 
     275           0 :     switch (slant) {
     276             :         case CAIRO_FONT_SLANT_NORMAL:
     277             :         case CAIRO_FONT_SLANT_ITALIC:
     278             :         case CAIRO_FONT_SLANT_OBLIQUE:
     279           0 :             break;
     280             :         default:
     281           0 :             return (cairo_font_face_t*) &_cairo_font_face_invalid_slant;
     282             :     }
     283             : 
     284           0 :     switch (weight) {
     285             :         case CAIRO_FONT_WEIGHT_NORMAL:
     286             :         case CAIRO_FONT_WEIGHT_BOLD:
     287           0 :             break;
     288             :         default:
     289           0 :             return (cairo_font_face_t*) &_cairo_font_face_invalid_weight;
     290             :     }
     291             : 
     292           0 :     if (*family == '\0')
     293           0 :         family = CAIRO_FONT_FAMILY_DEFAULT;
     294             : 
     295           0 :     hash_table = _cairo_toy_font_face_hash_table_lock ();
     296           0 :     if (unlikely (hash_table == NULL))
     297           0 :         goto UNWIND;
     298             : 
     299           0 :     _cairo_toy_font_face_init_key (&key, family, slant, weight);
     300             : 
     301             :     /* Return existing font_face if it exists in the hash table. */
     302           0 :     font_face = _cairo_hash_table_lookup (hash_table,
     303             :                                           &key.base.hash_entry);
     304           0 :     if (font_face != NULL) {
     305           0 :         if (font_face->base.status == CAIRO_STATUS_SUCCESS) {
     306             :             /* We increment the reference count here manually to avoid
     307             :                double-locking. */
     308           0 :             _cairo_reference_count_inc (&font_face->base.ref_count);
     309           0 :             _cairo_toy_font_face_hash_table_unlock ();
     310           0 :             return &font_face->base;
     311             :         }
     312             : 
     313             :         /* remove the bad font from the hash table */
     314           0 :         _cairo_hash_table_remove (hash_table, &font_face->base.hash_entry);
     315           0 :         font_face->base.hash_entry.hash = 0;
     316             :     }
     317             : 
     318             :     /* Otherwise create it and insert into hash table. */
     319           0 :     font_face = malloc (sizeof (cairo_toy_font_face_t));
     320           0 :     if (unlikely (font_face == NULL)) {
     321           0 :         status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
     322           0 :         goto UNWIND_HASH_TABLE_LOCK;
     323             :     }
     324             : 
     325           0 :     status = _cairo_toy_font_face_init (font_face, family, slant, weight);
     326           0 :     if (unlikely (status))
     327           0 :         goto UNWIND_FONT_FACE_MALLOC;
     328             : 
     329           0 :     assert (font_face->base.hash_entry.hash == key.base.hash_entry.hash);
     330           0 :     status = _cairo_hash_table_insert (hash_table, &font_face->base.hash_entry);
     331           0 :     if (unlikely (status))
     332           0 :         goto UNWIND_FONT_FACE_INIT;
     333             : 
     334           0 :     _cairo_toy_font_face_hash_table_unlock ();
     335             : 
     336           0 :     return &font_face->base;
     337             : 
     338             :  UNWIND_FONT_FACE_INIT:
     339           0 :     _cairo_toy_font_face_fini (font_face);
     340             :  UNWIND_FONT_FACE_MALLOC:
     341           0 :     free (font_face);
     342             :  UNWIND_HASH_TABLE_LOCK:
     343           0 :     _cairo_toy_font_face_hash_table_unlock ();
     344             :  UNWIND:
     345           0 :     return (cairo_font_face_t*) &_cairo_font_face_nil;
     346             : }
     347             : slim_hidden_def (cairo_toy_font_face_create);
     348             : 
     349             : static void
     350           0 : _cairo_toy_font_face_destroy (void *abstract_face)
     351             : {
     352           0 :     cairo_toy_font_face_t *font_face = abstract_face;
     353             :     cairo_hash_table_t *hash_table;
     354             : 
     355           0 :     if (font_face == NULL ||
     356           0 :             CAIRO_REFERENCE_COUNT_IS_INVALID (&font_face->base.ref_count))
     357           0 :         return;
     358             : 
     359           0 :     hash_table = _cairo_toy_font_face_hash_table_lock ();
     360             :     /* All created objects must have been mapped in the hash table. */
     361           0 :     assert (hash_table != NULL);
     362             : 
     363           0 :     if (CAIRO_REFERENCE_COUNT_HAS_REFERENCE (&font_face->base.ref_count)) {
     364             :         /* somebody recreated the font whilst we waited for the lock */
     365           0 :         _cairo_toy_font_face_hash_table_unlock ();
     366           0 :         return;
     367             :     }
     368             : 
     369           0 :     if (font_face->base.hash_entry.hash != 0)
     370           0 :         _cairo_hash_table_remove (hash_table, &font_face->base.hash_entry);
     371             : 
     372           0 :     _cairo_toy_font_face_hash_table_unlock ();
     373             : 
     374           0 :     _cairo_toy_font_face_fini (font_face);
     375             : }
     376             : 
     377             : static cairo_status_t
     378           0 : _cairo_toy_font_face_scaled_font_create (void                *abstract_font_face,
     379             :                                          const cairo_matrix_t       *font_matrix,
     380             :                                          const cairo_matrix_t       *ctm,
     381             :                                          const cairo_font_options_t *options,
     382             :                                          cairo_scaled_font_t       **scaled_font)
     383             : {
     384           0 :     cairo_toy_font_face_t *font_face = (cairo_toy_font_face_t *) abstract_font_face;
     385             : 
     386           0 :     ASSERT_NOT_REACHED;
     387             : 
     388             :     return _cairo_font_face_set_error (&font_face->base, CAIRO_STATUS_FONT_TYPE_MISMATCH);
     389             : }
     390             : 
     391             : static cairo_font_face_t *
     392           0 : _cairo_toy_font_face_get_implementation (void                *abstract_font_face,
     393             :                                          const cairo_matrix_t       *font_matrix,
     394             :                                          const cairo_matrix_t       *ctm,
     395             :                                          const cairo_font_options_t *options)
     396             : {
     397           0 :     cairo_toy_font_face_t *font_face = abstract_font_face;
     398             : 
     399           0 :     if (font_face->impl_face) {
     400           0 :         cairo_font_face_t *impl = font_face->impl_face;
     401             : 
     402           0 :         if (impl->backend->get_implementation != NULL) {
     403           0 :             return impl->backend->get_implementation (impl,
     404             :                                                       font_matrix,
     405             :                                                       ctm,
     406             :                                                       options);
     407             :         }
     408             : 
     409           0 :         return cairo_font_face_reference (impl);
     410             :     }
     411             : 
     412           0 :     return abstract_font_face;
     413             : }
     414             : 
     415             : static cairo_bool_t
     416           0 : _cairo_font_face_is_toy (cairo_font_face_t *font_face)
     417             : {
     418           0 :     return font_face->backend == &_cairo_toy_font_face_backend;
     419             : }
     420             : 
     421             : /**
     422             :  * cairo_toy_font_face_get_family:
     423             :  * @font_face: A toy font face
     424             :  *
     425             :  * Gets the familly name of a toy font.
     426             :  *
     427             :  * Return value: The family name.  This string is owned by the font face
     428             :  * and remains valid as long as the font face is alive (referenced).
     429             :  *
     430             :  * Since: 1.8
     431             :  **/
     432             : const char *
     433           0 : cairo_toy_font_face_get_family (cairo_font_face_t *font_face)
     434             : {
     435             :     cairo_toy_font_face_t *toy_font_face;
     436             : 
     437           0 :     if (font_face->status)
     438           0 :         return CAIRO_FONT_FAMILY_DEFAULT;
     439             : 
     440           0 :     toy_font_face = (cairo_toy_font_face_t *) font_face;
     441           0 :     if (! _cairo_font_face_is_toy (font_face)) {
     442           0 :         if (_cairo_font_face_set_error (font_face, CAIRO_STATUS_FONT_TYPE_MISMATCH))
     443           0 :             return CAIRO_FONT_FAMILY_DEFAULT;
     444             :     }
     445           0 :     assert (toy_font_face->owns_family);
     446           0 :     return toy_font_face->family;
     447             : }
     448             : 
     449             : /**
     450             :  * cairo_toy_font_face_get_slant:
     451             :  * @font_face: A toy font face
     452             :  *
     453             :  * Gets the slant a toy font.
     454             :  *
     455             :  * Return value: The slant value
     456             :  *
     457             :  * Since: 1.8
     458             :  **/
     459             : cairo_font_slant_t
     460           0 : cairo_toy_font_face_get_slant (cairo_font_face_t *font_face)
     461             : {
     462             :     cairo_toy_font_face_t *toy_font_face;
     463             : 
     464           0 :     if (font_face->status)
     465           0 :         return CAIRO_FONT_SLANT_DEFAULT;
     466             : 
     467           0 :     toy_font_face = (cairo_toy_font_face_t *) font_face;
     468           0 :     if (! _cairo_font_face_is_toy (font_face)) {
     469           0 :         if (_cairo_font_face_set_error (font_face, CAIRO_STATUS_FONT_TYPE_MISMATCH))
     470           0 :             return CAIRO_FONT_SLANT_DEFAULT;
     471             :     }
     472           0 :     return toy_font_face->slant;
     473             : }
     474             : slim_hidden_def (cairo_toy_font_face_get_slant);
     475             : 
     476             : /**
     477             :  * cairo_toy_font_face_get_weight:
     478             :  * @font_face: A toy font face
     479             :  *
     480             :  * Gets the weight a toy font.
     481             :  *
     482             :  * Return value: The weight value
     483             :  *
     484             :  * Since: 1.8
     485             :  **/
     486             : cairo_font_weight_t
     487           0 : cairo_toy_font_face_get_weight (cairo_font_face_t *font_face)
     488             : {
     489             :     cairo_toy_font_face_t *toy_font_face;
     490             : 
     491           0 :     if (font_face->status)
     492           0 :         return CAIRO_FONT_WEIGHT_DEFAULT;
     493             : 
     494           0 :     toy_font_face = (cairo_toy_font_face_t *) font_face;
     495           0 :     if (! _cairo_font_face_is_toy (font_face)) {
     496           0 :         if (_cairo_font_face_set_error (font_face, CAIRO_STATUS_FONT_TYPE_MISMATCH))
     497           0 :             return CAIRO_FONT_WEIGHT_DEFAULT;
     498             :     }
     499           0 :     return toy_font_face->weight;
     500             : }
     501             : slim_hidden_def (cairo_toy_font_face_get_weight);
     502             : 
     503             : static const cairo_font_face_backend_t _cairo_toy_font_face_backend = {
     504             :     CAIRO_FONT_TYPE_TOY,
     505             :     NULL,                                       /* create_for_toy */
     506             :     _cairo_toy_font_face_destroy,
     507             :     _cairo_toy_font_face_scaled_font_create,
     508             :     _cairo_toy_font_face_get_implementation
     509             : };
     510             : 
     511             : void
     512           0 : _cairo_toy_font_face_reset_static_data (void)
     513             : {
     514             :     cairo_hash_table_t *hash_table;
     515             : 
     516             :     /* We manually acquire the lock rather than calling
     517             :      * cairo_toy_font_face_hash_table_lock simply to avoid
     518             :      * creating the table only to destroy it again. */
     519           0 :     CAIRO_MUTEX_LOCK (_cairo_toy_font_face_mutex);
     520           0 :     hash_table = cairo_toy_font_face_hash_table;
     521           0 :     cairo_toy_font_face_hash_table = NULL;
     522           0 :     CAIRO_MUTEX_UNLOCK (_cairo_toy_font_face_mutex);
     523             : 
     524           0 :     if (hash_table != NULL)
     525           0 :         _cairo_hash_table_destroy (hash_table);
     526           0 : }

Generated by: LCOV version 1.13