LCOV - code coverage report
Current view: directory - gfx/cairo/cairo/src - cairo-user-font.c (source / functions) Found Hit Coverage
Test: app.info Lines: 258 0 0.0 %
Date: 2012-06-02 Functions: 21 0 0.0 %

       1                 : /* cairo - a vector graphics library with display and print output
       2                 :  *
       3                 :  * Copyright © 2006, 2008 Red Hat, Inc
       4                 :  *
       5                 :  * This library is free software; you can redistribute it and/or
       6                 :  * modify it either under the terms of the GNU Lesser General Public
       7                 :  * License version 2.1 as published by the Free Software Foundation
       8                 :  * (the "LGPL") or, at your option, under the terms of the Mozilla
       9                 :  * Public License Version 1.1 (the "MPL"). If you do not alter this
      10                 :  * notice, a recipient may use your version of this file under either
      11                 :  * the MPL or the LGPL.
      12                 :  *
      13                 :  * You should have received a copy of the LGPL along with this library
      14                 :  * in the file COPYING-LGPL-2.1; if not, write to the Free Software
      15                 :  * Foundation, Inc., 51 Franklin Street, Suite 500, Boston, MA 02110-1335, USA
      16                 :  * You should have received a copy of the MPL along with this library
      17                 :  * in the file COPYING-MPL-1.1
      18                 :  *
      19                 :  * The contents of this file are subject to the Mozilla Public License
      20                 :  * Version 1.1 (the "License"); you may not use this file except in
      21                 :  * compliance with the License. You may obtain a copy of the License at
      22                 :  * http://www.mozilla.org/MPL/
      23                 :  *
      24                 :  * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
      25                 :  * OF ANY KIND, either express or implied. See the LGPL or the MPL for
      26                 :  * the specific language governing rights and limitations.
      27                 :  *
      28                 :  * The Original Code is the cairo graphics library.
      29                 :  *
      30                 :  * The Initial Developer of the Original Code is Red Hat, Inc.
      31                 :  *
      32                 :  * Contributor(s):
      33                 :  *      Kristian Høgsberg <krh@redhat.com>
      34                 :  *      Behdad Esfahbod <behdad@behdad.org>
      35                 :  */
      36                 : 
      37                 : #include "cairoint.h"
      38                 : #include "cairo-user-font-private.h"
      39                 : #include "cairo-recording-surface-private.h"
      40                 : #include "cairo-analysis-surface-private.h"
      41                 : #include "cairo-error-private.h"
      42                 : 
      43                 : /**
      44                 :  * SECTION:cairo-user-fonts
      45                 :  * @Title:User Fonts
      46                 :  * @Short_Description: Font support with font data provided by the user
      47                 :  * 
      48                 :  * The user-font feature allows the cairo user to provide drawings for glyphs
      49                 :  * in a font.  This is most useful in implementing fonts in non-standard
      50                 :  * formats, like SVG fonts and Flash fonts, but can also be used by games and
      51                 :  * other application to draw "funky" fonts.
      52                 :  */
      53                 : 
      54                 : /**
      55                 :  * CAIRO_HAS_USER_FONT:
      56                 :  *
      57                 :  * Defined if the user font backend is available.
      58                 :  * This macro can be used to conditionally compile backend-specific code.
      59                 :  * The user font backend is always built in versions of cairo that support
      60                 :  * this feature (1.8 and later).
      61                 :  *
      62                 :  * @Since: 1.8
      63                 :  */
      64                 : 
      65                 : typedef struct _cairo_user_scaled_font_methods {
      66                 :     cairo_user_scaled_font_init_func_t                  init;
      67                 :     cairo_user_scaled_font_render_glyph_func_t          render_glyph;
      68                 :     cairo_user_scaled_font_unicode_to_glyph_func_t      unicode_to_glyph;
      69                 :     cairo_user_scaled_font_text_to_glyphs_func_t        text_to_glyphs;
      70                 : } cairo_user_scaled_font_methods_t;
      71                 : 
      72                 : typedef struct _cairo_user_font_face {
      73                 :     cairo_font_face_t                base;
      74                 : 
      75                 :     /* Set to true after first scaled font is created.  At that point,
      76                 :      * the scaled_font_methods cannot change anymore. */
      77                 :     cairo_bool_t                     immutable;
      78                 : 
      79                 :     cairo_user_scaled_font_methods_t scaled_font_methods;
      80                 : } cairo_user_font_face_t;
      81                 : 
      82                 : typedef struct _cairo_user_scaled_font {
      83                 :     cairo_scaled_font_t  base;
      84                 : 
      85                 :     cairo_text_extents_t default_glyph_extents;
      86                 : 
      87                 :     /* space to compute extents in, and factors to convert back to user space */
      88                 :     cairo_matrix_t extent_scale;
      89                 :     double extent_x_scale;
      90                 :     double extent_y_scale;
      91                 : 
      92                 :     /* multiplier for metrics hinting */
      93                 :     double snap_x_scale;
      94                 :     double snap_y_scale;
      95                 : 
      96                 : } cairo_user_scaled_font_t;
      97                 : 
      98                 : /* #cairo_user_scaled_font_t */
      99                 : 
     100                 : static cairo_surface_t *
     101               0 : _cairo_user_scaled_font_create_recording_surface (const cairo_user_scaled_font_t *scaled_font)
     102                 : {
     103                 :     cairo_content_t content;
     104                 : 
     105               0 :     content = scaled_font->base.options.antialias == CAIRO_ANTIALIAS_SUBPIXEL ?
     106                 :                                                      CAIRO_CONTENT_COLOR_ALPHA :
     107                 :                                                      CAIRO_CONTENT_ALPHA;
     108                 : 
     109               0 :     return cairo_recording_surface_create (content, NULL);
     110                 : }
     111                 : 
     112                 : 
     113                 : static cairo_t *
     114               0 : _cairo_user_scaled_font_create_recording_context (const cairo_user_scaled_font_t *scaled_font,
     115                 :                                                   cairo_surface_t                *recording_surface)
     116                 : {
     117                 :     cairo_t *cr;
     118                 : 
     119               0 :     cr = cairo_create (recording_surface);
     120                 : 
     121               0 :     if (!_cairo_matrix_is_scale_0 (&scaled_font->base.scale)) {
     122                 :         cairo_matrix_t scale;
     123               0 :         scale = scaled_font->base.scale;
     124               0 :         scale.x0 = scale.y0 = 0.;
     125               0 :         cairo_set_matrix (cr, &scale);
     126                 :     }
     127                 : 
     128               0 :     cairo_set_font_size (cr, 1.0);
     129               0 :     cairo_set_font_options (cr, &scaled_font->base.options);
     130               0 :     cairo_set_source_rgb (cr, 1., 1., 1.);
     131                 : 
     132               0 :     return cr;
     133                 : }
     134                 : 
     135                 : static cairo_int_status_t
     136               0 : _cairo_user_scaled_glyph_init (void                      *abstract_font,
     137                 :                                cairo_scaled_glyph_t      *scaled_glyph,
     138                 :                                cairo_scaled_glyph_info_t  info)
     139                 : {
     140               0 :     cairo_int_status_t status = CAIRO_STATUS_SUCCESS;
     141               0 :     cairo_user_scaled_font_t *scaled_font = abstract_font;
     142               0 :     cairo_surface_t *recording_surface = scaled_glyph->recording_surface;
     143                 : 
     144               0 :     if (!scaled_glyph->recording_surface) {
     145               0 :         cairo_user_font_face_t *face =
     146               0 :             (cairo_user_font_face_t *) scaled_font->base.font_face;
     147               0 :         cairo_text_extents_t extents = scaled_font->default_glyph_extents;
     148                 :         cairo_t *cr;
     149                 : 
     150               0 :         if (!face->scaled_font_methods.render_glyph)
     151               0 :             return CAIRO_STATUS_USER_FONT_NOT_IMPLEMENTED;
     152                 : 
     153               0 :         recording_surface = _cairo_user_scaled_font_create_recording_surface (scaled_font);
     154                 : 
     155                 :         /* special case for 0 rank matrix (as in _cairo_scaled_font_init): empty surface */
     156               0 :         if (!_cairo_matrix_is_scale_0 (&scaled_font->base.scale)) {
     157               0 :             cr = _cairo_user_scaled_font_create_recording_context (scaled_font, recording_surface);
     158               0 :             status = face->scaled_font_methods.render_glyph ((cairo_scaled_font_t *)scaled_font,
     159                 :                                                              _cairo_scaled_glyph_index(scaled_glyph),
     160                 :                                                              cr, &extents);
     161               0 :             if (status == CAIRO_STATUS_SUCCESS)
     162               0 :                 status = cairo_status (cr);
     163                 : 
     164               0 :             cairo_destroy (cr);
     165                 : 
     166               0 :             if (unlikely (status)) {
     167               0 :                 cairo_surface_destroy (recording_surface);
     168               0 :                 return status;
     169                 :             }
     170                 :         }
     171                 : 
     172               0 :         _cairo_scaled_glyph_set_recording_surface (scaled_glyph,
     173                 :                                                    &scaled_font->base,
     174                 :                                                    recording_surface);
     175                 : 
     176                 : 
     177                 :         /* set metrics */
     178                 : 
     179               0 :         if (extents.width == 0.) {
     180                 :             cairo_box_t bbox;
     181                 :             double x1, y1, x2, y2;
     182                 :             double x_scale, y_scale;
     183                 : 
     184                 :             /* Compute extents.x/y/width/height from recording_surface,
     185                 :              * in font space.
     186                 :              */
     187               0 :             status = _cairo_recording_surface_get_bbox ((cairo_recording_surface_t *) recording_surface,
     188                 :                                                         &bbox,
     189               0 :                                                         &scaled_font->extent_scale);
     190               0 :             if (unlikely (status))
     191               0 :                 return status;
     192                 : 
     193               0 :             _cairo_box_to_doubles (&bbox, &x1, &y1, &x2, &y2);
     194                 : 
     195               0 :             x_scale = scaled_font->extent_x_scale;
     196               0 :             y_scale = scaled_font->extent_y_scale;
     197               0 :             extents.x_bearing = x1 * x_scale;
     198               0 :             extents.y_bearing = y1 * y_scale;
     199               0 :             extents.width     = (x2 - x1) * x_scale;
     200               0 :             extents.height    = (y2 - y1) * y_scale;
     201                 :         }
     202                 : 
     203               0 :         if (scaled_font->base.options.hint_metrics != CAIRO_HINT_METRICS_OFF) {
     204               0 :             extents.x_advance = _cairo_lround (extents.x_advance / scaled_font->snap_x_scale) * scaled_font->snap_x_scale;
     205               0 :             extents.y_advance = _cairo_lround (extents.y_advance / scaled_font->snap_y_scale) * scaled_font->snap_y_scale;
     206                 :         }
     207                 : 
     208               0 :         _cairo_scaled_glyph_set_metrics (scaled_glyph,
     209                 :                                          &scaled_font->base,
     210                 :                                          &extents);
     211                 :     }
     212                 : 
     213               0 :     if (info & CAIRO_SCALED_GLYPH_INFO_SURFACE) {
     214                 :         cairo_surface_t *surface;
     215                 :         cairo_format_t format;
     216                 :         int width, height;
     217                 : 
     218                 :         /* TODO
     219                 :          * extend the glyph cache to support argb glyphs.
     220                 :          * need to figure out the semantics and interaction with subpixel
     221                 :          * rendering first.
     222                 :          */
     223                 : 
     224               0 :         width = _cairo_fixed_integer_ceil (scaled_glyph->bbox.p2.x) -
     225               0 :           _cairo_fixed_integer_floor (scaled_glyph->bbox.p1.x);
     226               0 :         height = _cairo_fixed_integer_ceil (scaled_glyph->bbox.p2.y) -
     227               0 :           _cairo_fixed_integer_floor (scaled_glyph->bbox.p1.y);
     228                 : 
     229               0 :         switch (scaled_font->base.options.antialias) {
     230                 :         default:
     231                 :         case CAIRO_ANTIALIAS_DEFAULT:
     232               0 :         case CAIRO_ANTIALIAS_GRAY:      format = CAIRO_FORMAT_A8;       break;
     233               0 :         case CAIRO_ANTIALIAS_NONE:      format = CAIRO_FORMAT_A1;       break;
     234               0 :         case CAIRO_ANTIALIAS_SUBPIXEL:  format = CAIRO_FORMAT_ARGB32;   break;
     235                 :         }
     236               0 :         surface = cairo_image_surface_create (format, width, height);
     237                 : 
     238               0 :         cairo_surface_set_device_offset (surface,
     239               0 :                                          - _cairo_fixed_integer_floor (scaled_glyph->bbox.p1.x),
     240               0 :                                          - _cairo_fixed_integer_floor (scaled_glyph->bbox.p1.y));
     241               0 :         status = _cairo_recording_surface_replay (recording_surface, surface);
     242                 : 
     243               0 :         if (unlikely (status)) {
     244               0 :             cairo_surface_destroy(surface);
     245               0 :             return status;
     246                 :         }
     247                 : 
     248               0 :         _cairo_scaled_glyph_set_surface (scaled_glyph,
     249                 :                                          &scaled_font->base,
     250                 :                                          (cairo_image_surface_t *) surface);
     251                 :     }
     252                 : 
     253               0 :     if (info & CAIRO_SCALED_GLYPH_INFO_PATH) {
     254               0 :         cairo_path_fixed_t *path = _cairo_path_fixed_create ();
     255               0 :         if (!path)
     256               0 :             return _cairo_error (CAIRO_STATUS_NO_MEMORY);
     257                 : 
     258               0 :         status = _cairo_recording_surface_get_path (recording_surface, path);
     259               0 :         if (unlikely (status)) {
     260               0 :             _cairo_path_fixed_destroy (path);
     261               0 :             return status;
     262                 :         }
     263                 : 
     264               0 :         _cairo_scaled_glyph_set_path (scaled_glyph,
     265                 :                                       &scaled_font->base,
     266                 :                                       path);
     267                 :     }
     268                 : 
     269               0 :     return status;
     270                 : }
     271                 : 
     272                 : static unsigned long
     273               0 : _cairo_user_ucs4_to_index (void     *abstract_font,
     274                 :                            uint32_t  ucs4)
     275                 : {
     276               0 :     cairo_user_scaled_font_t *scaled_font = abstract_font;
     277               0 :     cairo_user_font_face_t *face =
     278               0 :         (cairo_user_font_face_t *) scaled_font->base.font_face;
     279               0 :     unsigned long glyph = 0;
     280                 : 
     281               0 :     if (face->scaled_font_methods.unicode_to_glyph) {
     282                 :         cairo_status_t status;
     283                 : 
     284               0 :         status = face->scaled_font_methods.unicode_to_glyph (&scaled_font->base,
     285                 :                                                              ucs4, &glyph);
     286                 : 
     287               0 :         if (status == CAIRO_STATUS_USER_FONT_NOT_IMPLEMENTED)
     288               0 :             goto not_implemented;
     289                 : 
     290               0 :         if (status != CAIRO_STATUS_SUCCESS) {
     291               0 :             status = _cairo_scaled_font_set_error (&scaled_font->base, status);
     292               0 :             glyph = 0;
     293                 :         }
     294                 : 
     295                 :     } else {
     296                 : not_implemented:
     297               0 :         glyph = ucs4;
     298                 :     }
     299                 : 
     300               0 :     return glyph;
     301                 : }
     302                 : 
     303                 : static cairo_int_status_t
     304               0 : _cairo_user_text_to_glyphs (void                      *abstract_font,
     305                 :                             double                     x,
     306                 :                             double                     y,
     307                 :                             const char                *utf8,
     308                 :                             int                        utf8_len,
     309                 :                             cairo_glyph_t            **glyphs,
     310                 :                             int                        *num_glyphs,
     311                 :                             cairo_text_cluster_t      **clusters,
     312                 :                             int                        *num_clusters,
     313                 :                             cairo_text_cluster_flags_t *cluster_flags)
     314                 : {
     315               0 :     cairo_int_status_t status = CAIRO_INT_STATUS_UNSUPPORTED;
     316                 : 
     317               0 :     cairo_user_scaled_font_t *scaled_font = abstract_font;
     318               0 :     cairo_user_font_face_t *face =
     319               0 :         (cairo_user_font_face_t *) scaled_font->base.font_face;
     320                 : 
     321               0 :     if (face->scaled_font_methods.text_to_glyphs) {
     322                 :         int i;
     323               0 :         cairo_glyph_t *orig_glyphs = *glyphs;
     324               0 :         int orig_num_glyphs = *num_glyphs;
     325                 : 
     326               0 :         status = face->scaled_font_methods.text_to_glyphs (&scaled_font->base,
     327                 :                                                            utf8, utf8_len,
     328                 :                                                            glyphs, num_glyphs,
     329                 :                                                            clusters, num_clusters, cluster_flags);
     330                 : 
     331               0 :         if (status != CAIRO_STATUS_SUCCESS &&
     332                 :             status != CAIRO_STATUS_USER_FONT_NOT_IMPLEMENTED)
     333               0 :             return status;
     334                 : 
     335               0 :         if (status == CAIRO_STATUS_USER_FONT_NOT_IMPLEMENTED || *num_glyphs < 0) {
     336               0 :             if (orig_glyphs != *glyphs) {
     337               0 :                 cairo_glyph_free (*glyphs);
     338               0 :                 *glyphs = orig_glyphs;
     339                 :             }
     340               0 :             *num_glyphs = orig_num_glyphs;
     341               0 :             return CAIRO_INT_STATUS_UNSUPPORTED;
     342                 :         }
     343                 : 
     344                 :         /* Convert from font space to user space and add x,y */
     345               0 :         for (i = 0; i < *num_glyphs; i++) {
     346               0 :             double gx = (*glyphs)[i].x;
     347               0 :             double gy = (*glyphs)[i].y;
     348                 : 
     349               0 :             cairo_matrix_transform_point (&scaled_font->base.font_matrix,
     350                 :                                           &gx, &gy);
     351                 : 
     352               0 :             (*glyphs)[i].x = gx + x;
     353               0 :             (*glyphs)[i].y = gy + y;
     354                 :         }
     355                 :     }
     356                 : 
     357               0 :     return status;
     358                 : }
     359                 : 
     360                 : static cairo_status_t
     361                 : _cairo_user_font_face_scaled_font_create (void                        *abstract_face,
     362                 :                                           const cairo_matrix_t        *font_matrix,
     363                 :                                           const cairo_matrix_t        *ctm,
     364                 :                                           const cairo_font_options_t  *options,
     365                 :                                           cairo_scaled_font_t        **scaled_font);
     366                 : 
     367                 : static cairo_status_t
     368               0 : _cairo_user_font_face_create_for_toy (cairo_toy_font_face_t   *toy_face,
     369                 :                                       cairo_font_face_t      **font_face)
     370                 : {
     371               0 :     return _cairo_font_face_twin_create_for_toy (toy_face, font_face);
     372                 : }
     373                 : 
     374                 : static const cairo_scaled_font_backend_t _cairo_user_scaled_font_backend = {
     375                 :     CAIRO_FONT_TYPE_USER,
     376                 :     NULL,       /* scaled_font_fini */
     377                 :     _cairo_user_scaled_glyph_init,
     378                 :     _cairo_user_text_to_glyphs,
     379                 :     _cairo_user_ucs4_to_index,
     380                 :     NULL,       /* show_glyphs */
     381                 :     NULL,       /* load_truetype_table */
     382                 :     NULL        /* index_to_ucs4 */
     383                 : };
     384                 : 
     385                 : /* #cairo_user_font_face_t */
     386                 : 
     387                 : static cairo_status_t
     388               0 : _cairo_user_font_face_scaled_font_create (void                        *abstract_face,
     389                 :                                           const cairo_matrix_t        *font_matrix,
     390                 :                                           const cairo_matrix_t        *ctm,
     391                 :                                           const cairo_font_options_t  *options,
     392                 :                                           cairo_scaled_font_t        **scaled_font)
     393                 : {
     394               0 :     cairo_status_t status = CAIRO_STATUS_SUCCESS;
     395               0 :     cairo_user_font_face_t *font_face = abstract_face;
     396               0 :     cairo_user_scaled_font_t *user_scaled_font = NULL;
     397               0 :     cairo_font_extents_t font_extents = {1., 0., 1., 1., 0.};
     398                 : 
     399               0 :     font_face->immutable = TRUE;
     400                 : 
     401               0 :     user_scaled_font = malloc (sizeof (cairo_user_scaled_font_t));
     402               0 :     if (unlikely (user_scaled_font == NULL))
     403               0 :         return _cairo_error (CAIRO_STATUS_NO_MEMORY);
     404                 : 
     405               0 :     status = _cairo_scaled_font_init (&user_scaled_font->base,
     406                 :                                       &font_face->base,
     407                 :                                       font_matrix, ctm, options,
     408                 :                                       &_cairo_user_scaled_font_backend);
     409                 : 
     410               0 :     if (unlikely (status)) {
     411               0 :         free (user_scaled_font);
     412               0 :         return status;
     413                 :     }
     414                 : 
     415                 :     /* XXX metrics hinting? */
     416                 : 
     417                 :     /* compute a normalized version of font scale matrix to compute
     418                 :      * extents in.  This is to minimize error caused by the cairo_fixed_t
     419                 :      * representation. */
     420                 :     {
     421                 :         double fixed_scale, x_scale, y_scale;
     422                 : 
     423               0 :         user_scaled_font->extent_scale = user_scaled_font->base.scale_inverse;
     424               0 :         status = _cairo_matrix_compute_basis_scale_factors (&user_scaled_font->extent_scale,
     425                 :                                                       &x_scale, &y_scale,
     426                 :                                                       1);
     427               0 :         if (status == CAIRO_STATUS_SUCCESS) {
     428                 : 
     429               0 :             if (x_scale == 0) x_scale = 1.;
     430               0 :             if (y_scale == 0) y_scale = 1.;
     431                 : 
     432               0 :             user_scaled_font->snap_x_scale = x_scale;
     433               0 :             user_scaled_font->snap_y_scale = y_scale;
     434                 : 
     435                 :             /* since glyphs are pretty much 1.0x1.0, we can reduce error by
     436                 :              * scaling to a larger square.  say, 1024.x1024. */
     437               0 :             fixed_scale = 1024.;
     438               0 :             x_scale /= fixed_scale;
     439               0 :             y_scale /= fixed_scale;
     440                 : 
     441               0 :             cairo_matrix_scale (&user_scaled_font->extent_scale, 1. / x_scale, 1. / y_scale);
     442                 : 
     443               0 :             user_scaled_font->extent_x_scale = x_scale;
     444               0 :             user_scaled_font->extent_y_scale = y_scale;
     445                 :         }
     446                 :     }
     447                 : 
     448               0 :     if (status == CAIRO_STATUS_SUCCESS &&
     449               0 :         font_face->scaled_font_methods.init != NULL)
     450                 :     {
     451                 :         /* Lock the scaled_font mutex such that user doesn't accidentally try
     452                 :          * to use it just yet. */
     453                 :         CAIRO_MUTEX_LOCK (user_scaled_font->base.mutex);
     454                 : 
     455                 :         /* Give away fontmap lock such that user-font can use other fonts */
     456               0 :         status = _cairo_scaled_font_register_placeholder_and_unlock_font_map (&user_scaled_font->base);
     457               0 :         if (status == CAIRO_STATUS_SUCCESS) {
     458                 :             cairo_surface_t *recording_surface;
     459                 :             cairo_t *cr;
     460                 : 
     461               0 :             recording_surface = _cairo_user_scaled_font_create_recording_surface (user_scaled_font);
     462               0 :             cr = _cairo_user_scaled_font_create_recording_context (user_scaled_font, recording_surface);
     463               0 :             cairo_surface_destroy (recording_surface);
     464                 : 
     465               0 :             status = font_face->scaled_font_methods.init (&user_scaled_font->base,
     466                 :                                                           cr,
     467                 :                                                           &font_extents);
     468                 : 
     469               0 :             if (status == CAIRO_STATUS_USER_FONT_NOT_IMPLEMENTED)
     470               0 :                 status = CAIRO_STATUS_SUCCESS;
     471                 : 
     472               0 :             if (status == CAIRO_STATUS_SUCCESS)
     473               0 :                 status = cairo_status (cr);
     474                 : 
     475               0 :             cairo_destroy (cr);
     476                 : 
     477               0 :             _cairo_scaled_font_unregister_placeholder_and_lock_font_map (&user_scaled_font->base);
     478                 :         }
     479                 : 
     480                 :         CAIRO_MUTEX_UNLOCK (user_scaled_font->base.mutex);
     481                 :     }
     482                 : 
     483               0 :     if (status == CAIRO_STATUS_SUCCESS)
     484               0 :         status = _cairo_scaled_font_set_metrics (&user_scaled_font->base, &font_extents);
     485                 : 
     486               0 :     if (status != CAIRO_STATUS_SUCCESS) {
     487               0 :         _cairo_scaled_font_fini (&user_scaled_font->base);
     488               0 :         free (user_scaled_font);
     489                 :     } else {
     490               0 :         user_scaled_font->default_glyph_extents.x_bearing = 0.;
     491               0 :         user_scaled_font->default_glyph_extents.y_bearing = -font_extents.ascent;
     492               0 :         user_scaled_font->default_glyph_extents.width = 0.;
     493               0 :         user_scaled_font->default_glyph_extents.height = font_extents.ascent + font_extents.descent;
     494               0 :         user_scaled_font->default_glyph_extents.x_advance = font_extents.max_x_advance;
     495               0 :         user_scaled_font->default_glyph_extents.y_advance = 0.;
     496                 : 
     497               0 :         *scaled_font = &user_scaled_font->base;
     498                 :     }
     499                 : 
     500               0 :     return status;
     501                 : }
     502                 : 
     503                 : const cairo_font_face_backend_t _cairo_user_font_face_backend = {
     504                 :     CAIRO_FONT_TYPE_USER,
     505                 :     _cairo_user_font_face_create_for_toy,
     506                 :     NULL,       /* destroy */
     507                 :     _cairo_user_font_face_scaled_font_create
     508                 : };
     509                 : 
     510                 : 
     511                 : cairo_bool_t
     512               0 : _cairo_font_face_is_user (cairo_font_face_t *font_face)
     513                 : {
     514               0 :     return font_face->backend == &_cairo_user_font_face_backend;
     515                 : }
     516                 : 
     517                 : /* Implement the public interface */
     518                 : 
     519                 : /**
     520                 :  * cairo_user_font_face_create:
     521                 :  *
     522                 :  * Creates a new user font-face.
     523                 :  *
     524                 :  * Use the setter functions to associate callbacks with the returned
     525                 :  * user font.  The only mandatory callback is render_glyph.
     526                 :  *
     527                 :  * After the font-face is created, the user can attach arbitrary data
     528                 :  * (the actual font data) to it using cairo_font_face_set_user_data()
     529                 :  * and access it from the user-font callbacks by using
     530                 :  * cairo_scaled_font_get_font_face() followed by
     531                 :  * cairo_font_face_get_user_data().
     532                 :  *
     533                 :  * Return value: a newly created #cairo_font_face_t. Free with
     534                 :  *  cairo_font_face_destroy() when you are done using it.
     535                 :  *
     536                 :  * Since: 1.8
     537                 :  **/
     538                 : cairo_font_face_t *
     539               0 : cairo_user_font_face_create (void)
     540                 : {
     541                 :     cairo_user_font_face_t *font_face;
     542                 : 
     543               0 :     font_face = malloc (sizeof (cairo_user_font_face_t));
     544               0 :     if (!font_face) {
     545               0 :         _cairo_error_throw (CAIRO_STATUS_NO_MEMORY);
     546               0 :         return (cairo_font_face_t *)&_cairo_font_face_nil;
     547                 :     }
     548                 : 
     549               0 :     _cairo_font_face_init (&font_face->base, &_cairo_user_font_face_backend);
     550                 : 
     551               0 :     font_face->immutable = FALSE;
     552               0 :     memset (&font_face->scaled_font_methods, 0, sizeof (font_face->scaled_font_methods));
     553                 : 
     554               0 :     return &font_face->base;
     555                 : }
     556                 : slim_hidden_def(cairo_user_font_face_create);
     557                 : 
     558                 : /* User-font method setters */
     559                 : 
     560                 : 
     561                 : /**
     562                 :  * cairo_user_font_face_set_init_func:
     563                 :  * @font_face: A user font face
     564                 :  * @init_func: The init callback, or %NULL
     565                 :  *
     566                 :  * Sets the scaled-font initialization function of a user-font.
     567                 :  * See #cairo_user_scaled_font_init_func_t for details of how the callback
     568                 :  * works.
     569                 :  *
     570                 :  * The font-face should not be immutable or a %CAIRO_STATUS_USER_FONT_IMMUTABLE
     571                 :  * error will occur.  A user font-face is immutable as soon as a scaled-font
     572                 :  * is created from it.
     573                 :  *
     574                 :  * Since: 1.8
     575                 :  **/
     576                 : void
     577               0 : cairo_user_font_face_set_init_func (cairo_font_face_t                  *font_face,
     578                 :                                     cairo_user_scaled_font_init_func_t  init_func)
     579                 : {
     580                 :     cairo_user_font_face_t *user_font_face;
     581                 : 
     582               0 :     if (font_face->status)
     583               0 :         return;
     584                 : 
     585               0 :     if (! _cairo_font_face_is_user (font_face)) {
     586               0 :         if (_cairo_font_face_set_error (font_face, CAIRO_STATUS_FONT_TYPE_MISMATCH))
     587               0 :             return;
     588                 :     }
     589                 : 
     590               0 :     user_font_face = (cairo_user_font_face_t *) font_face;
     591               0 :     if (user_font_face->immutable) {
     592               0 :         if (_cairo_font_face_set_error (font_face, CAIRO_STATUS_USER_FONT_IMMUTABLE))
     593               0 :             return;
     594                 :     }
     595               0 :     user_font_face->scaled_font_methods.init = init_func;
     596                 : }
     597                 : slim_hidden_def(cairo_user_font_face_set_init_func);
     598                 : 
     599                 : /**
     600                 :  * cairo_user_font_face_set_render_glyph_func:
     601                 :  * @font_face: A user font face
     602                 :  * @render_glyph_func: The render_glyph callback, or %NULL
     603                 :  *
     604                 :  * Sets the glyph rendering function of a user-font.
     605                 :  * See #cairo_user_scaled_font_render_glyph_func_t for details of how the callback
     606                 :  * works.
     607                 :  *
     608                 :  * The font-face should not be immutable or a %CAIRO_STATUS_USER_FONT_IMMUTABLE
     609                 :  * error will occur.  A user font-face is immutable as soon as a scaled-font
     610                 :  * is created from it.
     611                 :  *
     612                 :  * The render_glyph callback is the only mandatory callback of a user-font.
     613                 :  * If the callback is %NULL and a glyph is tried to be rendered using
     614                 :  * @font_face, a %CAIRO_STATUS_USER_FONT_ERROR will occur.
     615                 :  *
     616                 :  * Since: 1.8
     617                 :  **/
     618                 : void
     619               0 : cairo_user_font_face_set_render_glyph_func (cairo_font_face_t                          *font_face,
     620                 :                                             cairo_user_scaled_font_render_glyph_func_t  render_glyph_func)
     621                 : {
     622                 :     cairo_user_font_face_t *user_font_face;
     623                 : 
     624               0 :     if (font_face->status)
     625               0 :         return;
     626                 : 
     627               0 :     if (! _cairo_font_face_is_user (font_face)) {
     628               0 :         if (_cairo_font_face_set_error (font_face, CAIRO_STATUS_FONT_TYPE_MISMATCH))
     629               0 :             return;
     630                 :     }
     631                 : 
     632               0 :     user_font_face = (cairo_user_font_face_t *) font_face;
     633               0 :     if (user_font_face->immutable) {
     634               0 :         if (_cairo_font_face_set_error (font_face, CAIRO_STATUS_USER_FONT_IMMUTABLE))
     635               0 :             return;
     636                 :     }
     637               0 :     user_font_face->scaled_font_methods.render_glyph = render_glyph_func;
     638                 : }
     639                 : slim_hidden_def(cairo_user_font_face_set_render_glyph_func);
     640                 : 
     641                 : /**
     642                 :  * cairo_user_font_face_set_text_to_glyphs_func:
     643                 :  * @font_face: A user font face
     644                 :  * @text_to_glyphs_func: The text_to_glyphs callback, or %NULL
     645                 :  *
     646                 :  * Sets th text-to-glyphs conversion function of a user-font.
     647                 :  * See #cairo_user_scaled_font_text_to_glyphs_func_t for details of how the callback
     648                 :  * works.
     649                 :  *
     650                 :  * The font-face should not be immutable or a %CAIRO_STATUS_USER_FONT_IMMUTABLE
     651                 :  * error will occur.  A user font-face is immutable as soon as a scaled-font
     652                 :  * is created from it.
     653                 :  *
     654                 :  * Since: 1.8
     655                 :  **/
     656                 : void
     657               0 : cairo_user_font_face_set_text_to_glyphs_func (cairo_font_face_t                            *font_face,
     658                 :                                               cairo_user_scaled_font_text_to_glyphs_func_t  text_to_glyphs_func)
     659                 : {
     660                 :     cairo_user_font_face_t *user_font_face;
     661                 : 
     662               0 :     if (font_face->status)
     663               0 :         return;
     664                 : 
     665               0 :     if (! _cairo_font_face_is_user (font_face)) {
     666               0 :         if (_cairo_font_face_set_error (font_face, CAIRO_STATUS_FONT_TYPE_MISMATCH))
     667               0 :             return;
     668                 :     }
     669                 : 
     670               0 :     user_font_face = (cairo_user_font_face_t *) font_face;
     671               0 :     if (user_font_face->immutable) {
     672               0 :         if (_cairo_font_face_set_error (font_face, CAIRO_STATUS_USER_FONT_IMMUTABLE))
     673               0 :             return;
     674                 :     }
     675               0 :     user_font_face->scaled_font_methods.text_to_glyphs = text_to_glyphs_func;
     676                 : }
     677                 : 
     678                 : /**
     679                 :  * cairo_user_font_face_set_unicode_to_glyph_func:
     680                 :  * @font_face: A user font face
     681                 :  * @unicode_to_glyph_func: The unicode_to_glyph callback, or %NULL
     682                 :  *
     683                 :  * Sets the unicode-to-glyph conversion function of a user-font.
     684                 :  * See #cairo_user_scaled_font_unicode_to_glyph_func_t for details of how the callback
     685                 :  * works.
     686                 :  *
     687                 :  * The font-face should not be immutable or a %CAIRO_STATUS_USER_FONT_IMMUTABLE
     688                 :  * error will occur.  A user font-face is immutable as soon as a scaled-font
     689                 :  * is created from it.
     690                 :  *
     691                 :  * Since: 1.8
     692                 :  **/
     693                 : void
     694               0 : cairo_user_font_face_set_unicode_to_glyph_func (cairo_font_face_t                              *font_face,
     695                 :                                                 cairo_user_scaled_font_unicode_to_glyph_func_t  unicode_to_glyph_func)
     696                 : {
     697                 :     cairo_user_font_face_t *user_font_face;
     698               0 :     if (font_face->status)
     699               0 :         return;
     700                 : 
     701               0 :     if (! _cairo_font_face_is_user (font_face)) {
     702               0 :         if (_cairo_font_face_set_error (font_face, CAIRO_STATUS_FONT_TYPE_MISMATCH))
     703               0 :             return;
     704                 :     }
     705                 : 
     706               0 :     user_font_face = (cairo_user_font_face_t *) font_face;
     707               0 :     if (user_font_face->immutable) {
     708               0 :         if (_cairo_font_face_set_error (font_face, CAIRO_STATUS_USER_FONT_IMMUTABLE))
     709               0 :             return;
     710                 :     }
     711               0 :     user_font_face->scaled_font_methods.unicode_to_glyph = unicode_to_glyph_func;
     712                 : }
     713                 : slim_hidden_def(cairo_user_font_face_set_unicode_to_glyph_func);
     714                 : 
     715                 : /* User-font method getters */
     716                 : 
     717                 : /**
     718                 :  * cairo_user_font_face_get_init_func:
     719                 :  * @font_face: A user font face
     720                 :  *
     721                 :  * Gets the scaled-font initialization function of a user-font.
     722                 :  *
     723                 :  * Return value: The init callback of @font_face
     724                 :  * or %NULL if none set or an error has occurred.
     725                 :  *
     726                 :  * Since: 1.8
     727                 :  **/
     728                 : cairo_user_scaled_font_init_func_t
     729               0 : cairo_user_font_face_get_init_func (cairo_font_face_t *font_face)
     730                 : {
     731                 :     cairo_user_font_face_t *user_font_face;
     732                 : 
     733               0 :     if (font_face->status)
     734               0 :         return NULL;
     735                 : 
     736               0 :     if (! _cairo_font_face_is_user (font_face)) {
     737               0 :         if (_cairo_font_face_set_error (font_face, CAIRO_STATUS_FONT_TYPE_MISMATCH))
     738               0 :             return NULL;
     739                 :     }
     740                 : 
     741               0 :     user_font_face = (cairo_user_font_face_t *) font_face;
     742               0 :     return user_font_face->scaled_font_methods.init;
     743                 : }
     744                 : 
     745                 : /**
     746                 :  * cairo_user_font_face_get_render_glyph_func:
     747                 :  * @font_face: A user font face
     748                 :  *
     749                 :  * Gets the glyph rendering function of a user-font.
     750                 :  *
     751                 :  * Return value: The render_glyph callback of @font_face
     752                 :  * or %NULL if none set or an error has occurred.
     753                 :  *
     754                 :  * Since: 1.8
     755                 :  **/
     756                 : cairo_user_scaled_font_render_glyph_func_t
     757               0 : cairo_user_font_face_get_render_glyph_func (cairo_font_face_t *font_face)
     758                 : {
     759                 :     cairo_user_font_face_t *user_font_face;
     760                 : 
     761               0 :     if (font_face->status)
     762               0 :         return NULL;
     763                 : 
     764               0 :     if (! _cairo_font_face_is_user (font_face)) {
     765               0 :         if (_cairo_font_face_set_error (font_face, CAIRO_STATUS_FONT_TYPE_MISMATCH))
     766               0 :             return NULL;
     767                 :     }
     768                 : 
     769               0 :     user_font_face = (cairo_user_font_face_t *) font_face;
     770               0 :     return user_font_face->scaled_font_methods.render_glyph;
     771                 : }
     772                 : 
     773                 : /**
     774                 :  * cairo_user_font_face_get_text_to_glyphs_func:
     775                 :  * @font_face: A user font face
     776                 :  *
     777                 :  * Gets the text-to-glyphs conversion function of a user-font.
     778                 :  *
     779                 :  * Return value: The text_to_glyphs callback of @font_face
     780                 :  * or %NULL if none set or an error occurred.
     781                 :  *
     782                 :  * Since: 1.8
     783                 :  **/
     784                 : cairo_user_scaled_font_text_to_glyphs_func_t
     785               0 : cairo_user_font_face_get_text_to_glyphs_func (cairo_font_face_t *font_face)
     786                 : {
     787                 :     cairo_user_font_face_t *user_font_face;
     788                 : 
     789               0 :     if (font_face->status)
     790               0 :         return NULL;
     791                 : 
     792               0 :     if (! _cairo_font_face_is_user (font_face)) {
     793               0 :         if (_cairo_font_face_set_error (font_face, CAIRO_STATUS_FONT_TYPE_MISMATCH))
     794               0 :             return NULL;
     795                 :     }
     796                 : 
     797               0 :     user_font_face = (cairo_user_font_face_t *) font_face;
     798               0 :     return user_font_face->scaled_font_methods.text_to_glyphs;
     799                 : }
     800                 : 
     801                 : /**
     802                 :  * cairo_user_font_face_get_unicode_to_glyph_func:
     803                 :  * @font_face: A user font face
     804                 :  *
     805                 :  * Gets the unicode-to-glyph conversion function of a user-font.
     806                 :  *
     807                 :  * Return value: The unicode_to_glyph callback of @font_face
     808                 :  * or %NULL if none set or an error occurred.
     809                 :  *
     810                 :  * Since: 1.8
     811                 :  **/
     812                 : cairo_user_scaled_font_unicode_to_glyph_func_t
     813               0 : cairo_user_font_face_get_unicode_to_glyph_func (cairo_font_face_t *font_face)
     814                 : {
     815                 :     cairo_user_font_face_t *user_font_face;
     816                 : 
     817               0 :     if (font_face->status)
     818               0 :         return NULL;
     819                 : 
     820               0 :     if (! _cairo_font_face_is_user (font_face)) {
     821               0 :         if (_cairo_font_face_set_error (font_face, CAIRO_STATUS_FONT_TYPE_MISMATCH))
     822               0 :             return NULL;
     823                 :     }
     824                 : 
     825               0 :     user_font_face = (cairo_user_font_face_t *) font_face;
     826               0 :     return user_font_face->scaled_font_methods.unicode_to_glyph;
     827                 : }

Generated by: LCOV version 1.7