LCOV - app.info - gfx/cairo/cairo/src/cairo-user-font.c

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-07-07 | 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