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

          Line data    Source code
       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           0 :                                                      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             :             (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             :         (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             :         (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           0 :         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           0 :         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.13