Subversion Repositories Kolibri OS

Rev

Go to most recent revision | Blame | Last modification | View Log | Download | RSS feed

  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. _cairo_user_scaled_font_create_recording_surface (const cairo_user_scaled_font_t *scaled_font)
  102. {
  103.     cairo_content_t content;
  104.  
  105.     content = scaled_font->base.options.antialias == CAIRO_ANTIALIAS_SUBPIXEL ?
  106.                                                      CAIRO_CONTENT_COLOR_ALPHA :
  107.                                                      CAIRO_CONTENT_ALPHA;
  108.  
  109.     return cairo_recording_surface_create (content, NULL);
  110. }
  111.  
  112.  
  113. static cairo_t *
  114. _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.     cr = cairo_create (recording_surface);
  120.  
  121.     if (!_cairo_matrix_is_scale_0 (&scaled_font->base.scale)) {
  122.         cairo_matrix_t scale;
  123.         scale = scaled_font->base.scale;
  124.         scale.x0 = scale.y0 = 0.;
  125.         cairo_set_matrix (cr, &scale);
  126.     }
  127.  
  128.     cairo_set_font_size (cr, 1.0);
  129.     cairo_set_font_options (cr, &scaled_font->base.options);
  130.     cairo_set_source_rgb (cr, 1., 1., 1.);
  131.  
  132.     return cr;
  133. }
  134.  
  135. static cairo_int_status_t
  136. _cairo_user_scaled_glyph_init (void                      *abstract_font,
  137.                                cairo_scaled_glyph_t      *scaled_glyph,
  138.                                cairo_scaled_glyph_info_t  info)
  139. {
  140.     cairo_int_status_t status = CAIRO_STATUS_SUCCESS;
  141.     cairo_user_scaled_font_t *scaled_font = abstract_font;
  142.     cairo_surface_t *recording_surface = scaled_glyph->recording_surface;
  143.  
  144.     if (!scaled_glyph->recording_surface) {
  145.         cairo_user_font_face_t *face =
  146.             (cairo_user_font_face_t *) scaled_font->base.font_face;
  147.         cairo_text_extents_t extents = scaled_font->default_glyph_extents;
  148.         cairo_t *cr;
  149.  
  150.         if (!face->scaled_font_methods.render_glyph)
  151.             return CAIRO_STATUS_USER_FONT_NOT_IMPLEMENTED;
  152.  
  153.         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.         if (!_cairo_matrix_is_scale_0 (&scaled_font->base.scale)) {
  157.             cr = _cairo_user_scaled_font_create_recording_context (scaled_font, recording_surface);
  158.             status = face->scaled_font_methods.render_glyph ((cairo_scaled_font_t *)scaled_font,
  159.                                                              _cairo_scaled_glyph_index(scaled_glyph),
  160.                                                              cr, &extents);
  161.             if (status == CAIRO_STATUS_SUCCESS)
  162.                 status = cairo_status (cr);
  163.  
  164.             cairo_destroy (cr);
  165.  
  166.             if (unlikely (status)) {
  167.                 cairo_surface_destroy (recording_surface);
  168.                 return status;
  169.             }
  170.         }
  171.  
  172.         _cairo_scaled_glyph_set_recording_surface (scaled_glyph,
  173.                                                    &scaled_font->base,
  174.                                                    recording_surface);
  175.  
  176.  
  177.         /* set metrics */
  178.  
  179.         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.             status = _cairo_recording_surface_get_bbox ((cairo_recording_surface_t *) recording_surface,
  188.                                                         &bbox,
  189.                                                         &scaled_font->extent_scale);
  190.             if (unlikely (status))
  191.                 return status;
  192.  
  193.             _cairo_box_to_doubles (&bbox, &x1, &y1, &x2, &y2);
  194.  
  195.             x_scale = scaled_font->extent_x_scale;
  196.             y_scale = scaled_font->extent_y_scale;
  197.             extents.x_bearing = x1 * x_scale;
  198.             extents.y_bearing = y1 * y_scale;
  199.             extents.width     = (x2 - x1) * x_scale;
  200.             extents.height    = (y2 - y1) * y_scale;
  201.         }
  202.  
  203.         if (scaled_font->base.options.hint_metrics != CAIRO_HINT_METRICS_OFF) {
  204.             extents.x_advance = _cairo_lround (extents.x_advance / scaled_font->snap_x_scale) * scaled_font->snap_x_scale;
  205.             extents.y_advance = _cairo_lround (extents.y_advance / scaled_font->snap_y_scale) * scaled_font->snap_y_scale;
  206.         }
  207.  
  208.         _cairo_scaled_glyph_set_metrics (scaled_glyph,
  209.                                          &scaled_font->base,
  210.                                          &extents);
  211.     }
  212.  
  213.     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.         width = _cairo_fixed_integer_ceil (scaled_glyph->bbox.p2.x) -
  225.           _cairo_fixed_integer_floor (scaled_glyph->bbox.p1.x);
  226.         height = _cairo_fixed_integer_ceil (scaled_glyph->bbox.p2.y) -
  227.           _cairo_fixed_integer_floor (scaled_glyph->bbox.p1.y);
  228.  
  229.         switch (scaled_font->base.options.antialias) {
  230.         default:
  231.         case CAIRO_ANTIALIAS_DEFAULT:
  232.         case CAIRO_ANTIALIAS_GRAY:      format = CAIRO_FORMAT_A8;       break;
  233.         case CAIRO_ANTIALIAS_NONE:      format = CAIRO_FORMAT_A1;       break;
  234.         case CAIRO_ANTIALIAS_SUBPIXEL:  format = CAIRO_FORMAT_ARGB32;   break;
  235.         }
  236.         surface = cairo_image_surface_create (format, width, height);
  237.  
  238.         cairo_surface_set_device_offset (surface,
  239.                                          - _cairo_fixed_integer_floor (scaled_glyph->bbox.p1.x),
  240.                                          - _cairo_fixed_integer_floor (scaled_glyph->bbox.p1.y));
  241.         status = _cairo_recording_surface_replay (recording_surface, surface);
  242.  
  243.         if (unlikely (status)) {
  244.             cairo_surface_destroy(surface);
  245.             return status;
  246.         }
  247.  
  248.         _cairo_scaled_glyph_set_surface (scaled_glyph,
  249.                                          &scaled_font->base,
  250.                                          (cairo_image_surface_t *) surface);
  251.     }
  252.  
  253.     if (info & CAIRO_SCALED_GLYPH_INFO_PATH) {
  254.         cairo_path_fixed_t *path = _cairo_path_fixed_create ();
  255.         if (!path)
  256.             return _cairo_error (CAIRO_STATUS_NO_MEMORY);
  257.  
  258.         status = _cairo_recording_surface_get_path (recording_surface, path);
  259.         if (unlikely (status)) {
  260.             _cairo_path_fixed_destroy (path);
  261.             return status;
  262.         }
  263.  
  264.         _cairo_scaled_glyph_set_path (scaled_glyph,
  265.                                       &scaled_font->base,
  266.                                       path);
  267.     }
  268.  
  269.     return status;
  270. }
  271.  
  272. static unsigned long
  273. _cairo_user_ucs4_to_index (void     *abstract_font,
  274.                            uint32_t  ucs4)
  275. {
  276.     cairo_user_scaled_font_t *scaled_font = abstract_font;
  277.     cairo_user_font_face_t *face =
  278.         (cairo_user_font_face_t *) scaled_font->base.font_face;
  279.     unsigned long glyph = 0;
  280.  
  281.     if (face->scaled_font_methods.unicode_to_glyph) {
  282.         cairo_status_t status;
  283.  
  284.         status = face->scaled_font_methods.unicode_to_glyph (&scaled_font->base,
  285.                                                              ucs4, &glyph);
  286.  
  287.         if (status == CAIRO_STATUS_USER_FONT_NOT_IMPLEMENTED)
  288.             goto not_implemented;
  289.  
  290.         if (status != CAIRO_STATUS_SUCCESS) {
  291.             status = _cairo_scaled_font_set_error (&scaled_font->base, status);
  292.             glyph = 0;
  293.         }
  294.  
  295.     } else {
  296. not_implemented:
  297.         glyph = ucs4;
  298.     }
  299.  
  300.     return glyph;
  301. }
  302.  
  303. static cairo_int_status_t
  304. _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.     cairo_int_status_t status = CAIRO_INT_STATUS_UNSUPPORTED;
  316.  
  317.     cairo_user_scaled_font_t *scaled_font = abstract_font;
  318.     cairo_user_font_face_t *face =
  319.         (cairo_user_font_face_t *) scaled_font->base.font_face;
  320.  
  321.     if (face->scaled_font_methods.text_to_glyphs) {
  322.         int i;
  323.         cairo_glyph_t *orig_glyphs = *glyphs;
  324.         int orig_num_glyphs = *num_glyphs;
  325.  
  326.         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.         if (status != CAIRO_STATUS_SUCCESS &&
  332.             status != CAIRO_STATUS_USER_FONT_NOT_IMPLEMENTED)
  333.             return status;
  334.  
  335.         if (status == CAIRO_STATUS_USER_FONT_NOT_IMPLEMENTED || *num_glyphs < 0) {
  336.             if (orig_glyphs != *glyphs) {
  337.                 cairo_glyph_free (*glyphs);
  338.                 *glyphs = orig_glyphs;
  339.             }
  340.             *num_glyphs = orig_num_glyphs;
  341.             return CAIRO_INT_STATUS_UNSUPPORTED;
  342.         }
  343.  
  344.         /* Convert from font space to user space and add x,y */
  345.         for (i = 0; i < *num_glyphs; i++) {
  346.             double gx = (*glyphs)[i].x;
  347.             double gy = (*glyphs)[i].y;
  348.  
  349.             cairo_matrix_transform_point (&scaled_font->base.font_matrix,
  350.                                           &gx, &gy);
  351.  
  352.             (*glyphs)[i].x = gx + x;
  353.             (*glyphs)[i].y = gy + y;
  354.         }
  355.     }
  356.  
  357.     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. _cairo_user_font_face_create_for_toy (cairo_toy_font_face_t   *toy_face,
  369.                                       cairo_font_face_t      **font_face)
  370. {
  371.     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. _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.     cairo_status_t status = CAIRO_STATUS_SUCCESS;
  395.     cairo_user_font_face_t *font_face = abstract_face;
  396.     cairo_user_scaled_font_t *user_scaled_font = NULL;
  397.     cairo_font_extents_t font_extents = {1., 0., 1., 1., 0.};
  398.  
  399.     font_face->immutable = TRUE;
  400.  
  401.     user_scaled_font = malloc (sizeof (cairo_user_scaled_font_t));
  402.     if (unlikely (user_scaled_font == NULL))
  403.         return _cairo_error (CAIRO_STATUS_NO_MEMORY);
  404.  
  405.     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.     if (unlikely (status)) {
  411.         free (user_scaled_font);
  412.         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.         user_scaled_font->extent_scale = user_scaled_font->base.scale_inverse;
  424.         status = _cairo_matrix_compute_basis_scale_factors (&user_scaled_font->extent_scale,
  425.                                                       &x_scale, &y_scale,
  426.                                                       1);
  427.         if (status == CAIRO_STATUS_SUCCESS) {
  428.  
  429.             if (x_scale == 0) x_scale = 1.;
  430.             if (y_scale == 0) y_scale = 1.;
  431.  
  432.             user_scaled_font->snap_x_scale = x_scale;
  433.             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.             fixed_scale = 1024.;
  438.             x_scale /= fixed_scale;
  439.             y_scale /= fixed_scale;
  440.  
  441.             cairo_matrix_scale (&user_scaled_font->extent_scale, 1. / x_scale, 1. / y_scale);
  442.  
  443.             user_scaled_font->extent_x_scale = x_scale;
  444.             user_scaled_font->extent_y_scale = y_scale;
  445.         }
  446.     }
  447.  
  448.     if (status == CAIRO_STATUS_SUCCESS &&
  449.         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.         status = _cairo_scaled_font_register_placeholder_and_unlock_font_map (&user_scaled_font->base);
  457.         if (status == CAIRO_STATUS_SUCCESS) {
  458.             cairo_surface_t *recording_surface;
  459.             cairo_t *cr;
  460.  
  461.             recording_surface = _cairo_user_scaled_font_create_recording_surface (user_scaled_font);
  462.             cr = _cairo_user_scaled_font_create_recording_context (user_scaled_font, recording_surface);
  463.             cairo_surface_destroy (recording_surface);
  464.  
  465.             status = font_face->scaled_font_methods.init (&user_scaled_font->base,
  466.                                                           cr,
  467.                                                           &font_extents);
  468.  
  469.             if (status == CAIRO_STATUS_USER_FONT_NOT_IMPLEMENTED)
  470.                 status = CAIRO_STATUS_SUCCESS;
  471.  
  472.             if (status == CAIRO_STATUS_SUCCESS)
  473.                 status = cairo_status (cr);
  474.  
  475.             cairo_destroy (cr);
  476.  
  477.             _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.     if (status == CAIRO_STATUS_SUCCESS)
  484.         status = _cairo_scaled_font_set_metrics (&user_scaled_font->base, &font_extents);
  485.  
  486.     if (status != CAIRO_STATUS_SUCCESS) {
  487.         _cairo_scaled_font_fini (&user_scaled_font->base);
  488.         free (user_scaled_font);
  489.     } else {
  490.         user_scaled_font->default_glyph_extents.x_bearing = 0.;
  491.         user_scaled_font->default_glyph_extents.y_bearing = -font_extents.ascent;
  492.         user_scaled_font->default_glyph_extents.width = 0.;
  493.         user_scaled_font->default_glyph_extents.height = font_extents.ascent + font_extents.descent;
  494.         user_scaled_font->default_glyph_extents.x_advance = font_extents.max_x_advance;
  495.         user_scaled_font->default_glyph_extents.y_advance = 0.;
  496.  
  497.         *scaled_font = &user_scaled_font->base;
  498.     }
  499.  
  500.     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. _cairo_font_face_is_user (cairo_font_face_t *font_face)
  513. {
  514.     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. cairo_user_font_face_create (void)
  540. {
  541.     cairo_user_font_face_t *font_face;
  542.  
  543.     font_face = malloc (sizeof (cairo_user_font_face_t));
  544.     if (!font_face) {
  545.         _cairo_error_throw (CAIRO_STATUS_NO_MEMORY);
  546.         return (cairo_font_face_t *)&_cairo_font_face_nil;
  547.     }
  548.  
  549.     _cairo_font_face_init (&font_face->base, &_cairo_user_font_face_backend);
  550.  
  551.     font_face->immutable = FALSE;
  552.     memset (&font_face->scaled_font_methods, 0, sizeof (font_face->scaled_font_methods));
  553.  
  554.     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. 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.     if (font_face->status)
  583.         return;
  584.  
  585.     if (! _cairo_font_face_is_user (font_face)) {
  586.         if (_cairo_font_face_set_error (font_face, CAIRO_STATUS_FONT_TYPE_MISMATCH))
  587.             return;
  588.     }
  589.  
  590.     user_font_face = (cairo_user_font_face_t *) font_face;
  591.     if (user_font_face->immutable) {
  592.         if (_cairo_font_face_set_error (font_face, CAIRO_STATUS_USER_FONT_IMMUTABLE))
  593.             return;
  594.     }
  595.     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. 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.     if (font_face->status)
  625.         return;
  626.  
  627.     if (! _cairo_font_face_is_user (font_face)) {
  628.         if (_cairo_font_face_set_error (font_face, CAIRO_STATUS_FONT_TYPE_MISMATCH))
  629.             return;
  630.     }
  631.  
  632.     user_font_face = (cairo_user_font_face_t *) font_face;
  633.     if (user_font_face->immutable) {
  634.         if (_cairo_font_face_set_error (font_face, CAIRO_STATUS_USER_FONT_IMMUTABLE))
  635.             return;
  636.     }
  637.     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. 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.     if (font_face->status)
  663.         return;
  664.  
  665.     if (! _cairo_font_face_is_user (font_face)) {
  666.         if (_cairo_font_face_set_error (font_face, CAIRO_STATUS_FONT_TYPE_MISMATCH))
  667.             return;
  668.     }
  669.  
  670.     user_font_face = (cairo_user_font_face_t *) font_face;
  671.     if (user_font_face->immutable) {
  672.         if (_cairo_font_face_set_error (font_face, CAIRO_STATUS_USER_FONT_IMMUTABLE))
  673.             return;
  674.     }
  675.     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. 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.     if (font_face->status)
  699.         return;
  700.  
  701.     if (! _cairo_font_face_is_user (font_face)) {
  702.         if (_cairo_font_face_set_error (font_face, CAIRO_STATUS_FONT_TYPE_MISMATCH))
  703.             return;
  704.     }
  705.  
  706.     user_font_face = (cairo_user_font_face_t *) font_face;
  707.     if (user_font_face->immutable) {
  708.         if (_cairo_font_face_set_error (font_face, CAIRO_STATUS_USER_FONT_IMMUTABLE))
  709.             return;
  710.     }
  711.     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. 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.     if (font_face->status)
  734.         return NULL;
  735.  
  736.     if (! _cairo_font_face_is_user (font_face)) {
  737.         if (_cairo_font_face_set_error (font_face, CAIRO_STATUS_FONT_TYPE_MISMATCH))
  738.             return NULL;
  739.     }
  740.  
  741.     user_font_face = (cairo_user_font_face_t *) font_face;
  742.     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. 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.     if (font_face->status)
  762.         return NULL;
  763.  
  764.     if (! _cairo_font_face_is_user (font_face)) {
  765.         if (_cairo_font_face_set_error (font_face, CAIRO_STATUS_FONT_TYPE_MISMATCH))
  766.             return NULL;
  767.     }
  768.  
  769.     user_font_face = (cairo_user_font_face_t *) font_face;
  770.     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. 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.     if (font_face->status)
  790.         return NULL;
  791.  
  792.     if (! _cairo_font_face_is_user (font_face)) {
  793.         if (_cairo_font_face_set_error (font_face, CAIRO_STATUS_FONT_TYPE_MISMATCH))
  794.             return NULL;
  795.     }
  796.  
  797.     user_font_face = (cairo_user_font_face_t *) font_face;
  798.     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. 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.     if (font_face->status)
  818.         return NULL;
  819.  
  820.     if (! _cairo_font_face_is_user (font_face)) {
  821.         if (_cairo_font_face_set_error (font_face, CAIRO_STATUS_FONT_TYPE_MISMATCH))
  822.             return NULL;
  823.     }
  824.  
  825.     user_font_face = (cairo_user_font_face_t *) font_face;
  826.     return user_font_face->scaled_font_methods.unicode_to_glyph;
  827. }
  828.