Coverage Report

Created: 2025-09-27 07:50

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/cairo/src/cairo-user-font.c
Line
Count
Source
1
/* -*- Mode: c; tab-width: 8; c-basic-offset: 4; indent-tabs-mode: t; -*- */
2
/* cairo - a vector graphics library with display and print output
3
 *
4
 * Copyright © 2006, 2008 Red Hat, Inc
5
 *
6
 * This library is free software; you can redistribute it and/or
7
 * modify it either under the terms of the GNU Lesser General Public
8
 * License version 2.1 as published by the Free Software Foundation
9
 * (the "LGPL") or, at your option, under the terms of the Mozilla
10
 * Public License Version 1.1 (the "MPL"). If you do not alter this
11
 * notice, a recipient may use your version of this file under either
12
 * the MPL or the LGPL.
13
 *
14
 * You should have received a copy of the LGPL along with this library
15
 * in the file COPYING-LGPL-2.1; if not, write to the Free Software
16
 * Foundation, Inc., 51 Franklin Street, Suite 500, Boston, MA 02110-1335, USA
17
 * You should have received a copy of the MPL along with this library
18
 * in the file COPYING-MPL-1.1
19
 *
20
 * The contents of this file are subject to the Mozilla Public License
21
 * Version 1.1 (the "License"); you may not use this file except in
22
 * compliance with the License. You may obtain a copy of the License at
23
 * http://www.mozilla.org/MPL/
24
 *
25
 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
26
 * OF ANY KIND, either express or implied. See the LGPL or the MPL for
27
 * the specific language governing rights and limitations.
28
 *
29
 * The Original Code is the cairo graphics library.
30
 *
31
 * The Initial Developer of the Original Code is Red Hat, Inc.
32
 *
33
 * Contributor(s):
34
 *      Kristian Høgsberg <krh@redhat.com>
35
 *      Behdad Esfahbod <behdad@behdad.org>
36
 */
37
38
#include "cairoint.h"
39
#include "cairo-user-font-private.h"
40
#include "cairo-recording-surface-private.h"
41
#include "cairo-analysis-surface-private.h"
42
#include "cairo-error-private.h"
43
44
/**
45
 * SECTION:cairo-user-fonts
46
 * @Title:User Fonts
47
 * @Short_Description: Font support with font data provided by the user
48
 *
49
 * The user-font feature allows the cairo user to provide drawings for glyphs
50
 * in a font.  This is most useful in implementing fonts in non-standard
51
 * formats, like SVG fonts and Flash fonts, but can also be used by games and
52
 * other application to draw "funky" fonts.
53
 **/
54
55
/**
56
 * CAIRO_HAS_USER_FONT:
57
 *
58
 * Defined if the user font backend is available.
59
 * This macro can be used to conditionally compile backend-specific code.
60
 * The user font backend is always built in versions of cairo that support
61
 * this feature (1.8 and later).
62
 *
63
 * Since: 1.8
64
 **/
65
66
typedef struct _cairo_user_scaled_font_methods {
67
    cairo_user_scaled_font_init_func_t      init;
68
    cairo_user_scaled_font_render_glyph_func_t    render_color_glyph;
69
    cairo_user_scaled_font_render_glyph_func_t    render_glyph;
70
    cairo_user_scaled_font_unicode_to_glyph_func_t  unicode_to_glyph;
71
    cairo_user_scaled_font_text_to_glyphs_func_t  text_to_glyphs;
72
} cairo_user_scaled_font_methods_t;
73
74
typedef struct _cairo_user_font_face {
75
    cairo_font_face_t              base;
76
77
    /* Set to true after first scaled font is created.  At that point,
78
     * the scaled_font_methods cannot change anymore. */
79
    cairo_bool_t         immutable;
80
    cairo_bool_t                     has_color;
81
    cairo_user_scaled_font_methods_t scaled_font_methods;
82
} cairo_user_font_face_t;
83
84
typedef struct _cairo_user_scaled_font {
85
    cairo_scaled_font_t  base;
86
87
    cairo_text_extents_t default_glyph_extents;
88
89
    /* space to compute extents in, and factors to convert back to user space */
90
    cairo_matrix_t extent_scale;
91
    double extent_x_scale;
92
    double extent_y_scale;
93
94
    /* multiplier for metrics hinting */
95
    double snap_x_scale;
96
    double snap_y_scale;
97
98
    cairo_pattern_t *foreground_marker;
99
    cairo_pattern_t *foreground_pattern;
100
    cairo_bool_t foreground_marker_used;
101
    cairo_bool_t foreground_colors_used;
102
103
} cairo_user_scaled_font_t;
104
105
/* #cairo_user_scaled_font_t */
106
107
static cairo_surface_t *
108
_cairo_user_scaled_font_create_recording_surface (cairo_user_scaled_font_t *scaled_font,
109
              cairo_bool_t              color,
110
              const cairo_color_t      *foreground_color)
111
0
{
112
0
    cairo_content_t content;
113
114
0
    if (color) {
115
0
  content = CAIRO_CONTENT_COLOR_ALPHA;
116
0
    } else {
117
0
  content = scaled_font->base.options.antialias == CAIRO_ANTIALIAS_SUBPIXEL ?
118
0
                     CAIRO_CONTENT_COLOR_ALPHA :
119
0
                     CAIRO_CONTENT_ALPHA;
120
0
    }
121
122
0
    if (scaled_font->foreground_pattern)
123
0
  cairo_pattern_destroy (scaled_font->foreground_pattern);
124
125
0
    scaled_font->foreground_marker_used = FALSE;
126
0
    scaled_font->foreground_colors_used = FALSE;
127
0
    if (foreground_color) {
128
0
  scaled_font->foreground_pattern = _cairo_pattern_create_solid (foreground_color);
129
0
    } else {
130
0
  scaled_font->foreground_pattern = cairo_pattern_create_rgb (0, 0, 0);
131
0
    }
132
133
0
    return cairo_recording_surface_create (content, NULL);
134
0
}
135
136
static cairo_t *
137
_cairo_user_scaled_font_create_recording_context (const cairo_user_scaled_font_t *scaled_font,
138
              cairo_surface_t                *recording_surface,
139
              cairo_bool_t                    color)
140
0
{
141
0
    cairo_t *cr;
142
143
0
    cr = cairo_create (recording_surface);
144
145
0
    if (!_cairo_matrix_is_scale_0 (&scaled_font->base.scale)) {
146
0
        cairo_matrix_t scale;
147
0
  scale = scaled_font->base.scale;
148
0
  scale.x0 = scale.y0 = 0.;
149
0
  cairo_set_matrix (cr, &scale);
150
0
    }
151
152
0
    cairo_set_font_size (cr, 1.0);
153
0
    cairo_set_font_options (cr, &scaled_font->base.options);
154
0
    if (!color)
155
0
  cairo_set_source_rgb (cr, 1., 1., 1.);
156
157
0
    return cr;
158
0
}
159
160
static cairo_int_status_t
161
_cairo_user_scaled_glyph_init_record_glyph (cairo_user_scaled_font_t *scaled_font,
162
              cairo_scaled_glyph_t     *scaled_glyph,
163
              const cairo_color_t      *foreground_color)
164
0
{
165
0
    cairo_user_font_face_t *face =
166
0
  (cairo_user_font_face_t *) scaled_font->base.font_face;
167
0
    cairo_text_extents_t extents = scaled_font->default_glyph_extents;
168
0
    cairo_surface_t *recording_surface = NULL;
169
0
    cairo_int_status_t status = CAIRO_STATUS_SUCCESS;
170
0
    cairo_t *cr;
171
0
    cairo_bool_t foreground_used = FALSE;
172
173
0
    if (!face->scaled_font_methods.render_color_glyph && !face->scaled_font_methods.render_glyph)
174
0
  return CAIRO_STATUS_USER_FONT_NOT_IMPLEMENTED;
175
176
    /* special case for 0 rank matrix (as in _cairo_scaled_font_init): empty surface */
177
0
    if (_cairo_matrix_is_scale_0 (&scaled_font->base.scale)) {
178
0
  recording_surface = _cairo_user_scaled_font_create_recording_surface (scaled_font, FALSE, foreground_color);
179
0
  _cairo_scaled_glyph_set_recording_surface (scaled_glyph,
180
0
               &scaled_font->base,
181
0
               recording_surface,
182
0
               NULL);
183
0
    } else {
184
0
  status = CAIRO_STATUS_USER_FONT_NOT_IMPLEMENTED;
185
186
0
  if (face->scaled_font_methods.render_color_glyph &&
187
0
      scaled_font->base.options.color_mode != CAIRO_COLOR_MODE_NO_COLOR)
188
0
  {
189
0
      recording_surface = _cairo_user_scaled_font_create_recording_surface (scaled_font, TRUE, foreground_color);
190
191
0
      cr = _cairo_user_scaled_font_create_recording_context (scaled_font, recording_surface, TRUE);
192
0
      status = face->scaled_font_methods.render_color_glyph ((cairo_scaled_font_t *)scaled_font,
193
0
                   _cairo_scaled_glyph_index(scaled_glyph),
194
0
                   cr, &extents);
195
0
      if (status == CAIRO_INT_STATUS_SUCCESS) {
196
0
    status = cairo_status (cr);
197
0
    scaled_glyph->color_glyph = TRUE;
198
0
    scaled_glyph->color_glyph_set = TRUE;
199
0
      }
200
201
0
      cairo_destroy (cr);
202
0
      foreground_used = scaled_font->foreground_marker_used || scaled_font->foreground_colors_used;
203
0
  }
204
205
0
  if (status == (cairo_int_status_t)CAIRO_STATUS_USER_FONT_NOT_IMPLEMENTED &&
206
0
      face->scaled_font_methods.render_glyph) {
207
0
      if (recording_surface)
208
0
    cairo_surface_destroy (recording_surface);
209
0
      recording_surface = _cairo_user_scaled_font_create_recording_surface (scaled_font, FALSE, foreground_color);
210
0
      recording_surface->device_transform.x0 = .25 * _cairo_scaled_glyph_xphase (scaled_glyph);
211
0
      recording_surface->device_transform.y0 = .25 * _cairo_scaled_glyph_yphase (scaled_glyph);
212
213
0
      cr = _cairo_user_scaled_font_create_recording_context (scaled_font, recording_surface, FALSE);
214
215
0
      status = face->scaled_font_methods.render_glyph ((cairo_scaled_font_t *)scaled_font,
216
0
                   _cairo_scaled_glyph_index(scaled_glyph),
217
0
                   cr, &extents);
218
0
      if (status == CAIRO_INT_STATUS_SUCCESS) {
219
0
    status = cairo_status (cr);
220
0
    scaled_glyph->color_glyph = FALSE;
221
0
    scaled_glyph->color_glyph_set = TRUE;
222
0
      }
223
224
0
      cairo_destroy (cr);
225
0
      foreground_used = FALSE;
226
0
  }
227
228
0
  if (status != CAIRO_INT_STATUS_SUCCESS) {
229
0
      if (recording_surface)
230
0
    cairo_surface_destroy (recording_surface);
231
0
      return status;
232
0
  }
233
234
0
  _cairo_scaled_glyph_set_recording_surface (scaled_glyph,
235
0
               &scaled_font->base,
236
0
               recording_surface,
237
0
               foreground_used ? foreground_color : NULL);
238
0
    }
239
240
    /* set metrics */
241
242
0
    if (extents.width == 0.) {
243
0
  cairo_box_t bbox;
244
0
  double x1, y1, x2, y2;
245
0
  double x_scale, y_scale;
246
247
  /* Compute extents.x/y/width/height from recording_surface,
248
   * in font space.
249
   */
250
0
  status = _cairo_recording_surface_get_bbox ((cairo_recording_surface_t *) recording_surface,
251
0
                &bbox,
252
0
                &scaled_font->extent_scale);
253
0
  if (unlikely (status))
254
0
      return status;
255
256
0
  _cairo_box_to_doubles (&bbox, &x1, &y1, &x2, &y2);
257
258
0
  x_scale = scaled_font->extent_x_scale;
259
0
  y_scale = scaled_font->extent_y_scale;
260
0
  extents.x_bearing = x1 * x_scale;
261
0
  extents.y_bearing = y1 * y_scale;
262
0
  extents.width     = (x2 - x1) * x_scale;
263
0
  extents.height    = (y2 - y1) * y_scale;
264
0
    }
265
266
0
    if (scaled_font->base.options.hint_metrics != CAIRO_HINT_METRICS_OFF) {
267
0
  extents.x_advance = _cairo_lround (extents.x_advance / scaled_font->snap_x_scale) * scaled_font->snap_x_scale;
268
0
  extents.y_advance = _cairo_lround (extents.y_advance / scaled_font->snap_y_scale) * scaled_font->snap_y_scale;
269
0
    }
270
271
0
    _cairo_scaled_glyph_set_metrics (scaled_glyph,
272
0
             &scaled_font->base,
273
0
             &extents);
274
275
0
    return status;
276
0
}
277
278
static cairo_int_status_t
279
_cairo_user_scaled_glyph_init_surface (cairo_user_scaled_font_t  *scaled_font,
280
               cairo_scaled_glyph_t  *scaled_glyph,
281
               cairo_scaled_glyph_info_t  info,
282
               const cairo_color_t       *foreground_color)
283
0
{
284
0
    cairo_surface_t *surface;
285
0
    cairo_format_t format;
286
0
    int width, height;
287
0
    cairo_int_status_t status = CAIRO_STATUS_SUCCESS;
288
0
    cairo_bool_t foreground_used;
289
290
    /* TODO
291
     * extend the glyph cache to support argb glyphs.
292
     * need to figure out the semantics and interaction with subpixel
293
     * rendering first.
294
     */
295
296
    /* Only one info type at a time handled in this function */
297
0
    assert (info == CAIRO_SCALED_GLYPH_INFO_COLOR_SURFACE || info == CAIRO_SCALED_GLYPH_INFO_SURFACE);
298
299
0
    width = _cairo_fixed_integer_ceil (scaled_glyph->bbox.p2.x) -
300
0
  _cairo_fixed_integer_floor (scaled_glyph->bbox.p1.x);
301
0
    height = _cairo_fixed_integer_ceil (scaled_glyph->bbox.p2.y) -
302
0
  _cairo_fixed_integer_floor (scaled_glyph->bbox.p1.y);
303
304
0
    if (info == CAIRO_SCALED_GLYPH_INFO_COLOR_SURFACE) {
305
0
  format = CAIRO_FORMAT_ARGB32;
306
0
    } else {
307
0
  switch (scaled_font->base.options.antialias) {
308
0
      default:
309
0
      case CAIRO_ANTIALIAS_DEFAULT:
310
0
      case CAIRO_ANTIALIAS_FAST:
311
0
      case CAIRO_ANTIALIAS_GOOD:
312
0
      case CAIRO_ANTIALIAS_GRAY:
313
0
    format = CAIRO_FORMAT_A8;
314
0
    break;
315
0
      case CAIRO_ANTIALIAS_NONE:
316
0
    format = CAIRO_FORMAT_A1;
317
0
    break;
318
0
      case CAIRO_ANTIALIAS_BEST:
319
0
      case CAIRO_ANTIALIAS_SUBPIXEL:
320
0
    format = CAIRO_FORMAT_ARGB32;
321
0
    break;
322
0
  }
323
0
    }
324
0
    surface = cairo_image_surface_create (format, width, height);
325
326
0
    cairo_surface_set_device_offset (surface,
327
0
             - _cairo_fixed_integer_floor (scaled_glyph->bbox.p1.x),
328
0
             - _cairo_fixed_integer_floor (scaled_glyph->bbox.p1.y));
329
330
0
    if (info == CAIRO_SCALED_GLYPH_INFO_COLOR_SURFACE) {
331
0
  status = _cairo_recording_surface_replay_with_foreground_color (scaled_glyph->recording_surface,
332
0
                  surface,
333
0
                  foreground_color,
334
0
                  &foreground_used);
335
  
336
0
    } else {
337
0
  status = _cairo_recording_surface_replay (scaled_glyph->recording_surface, surface);
338
0
  foreground_used = FALSE;
339
0
    }
340
0
    if (unlikely (status)) {
341
0
  cairo_surface_destroy(surface);
342
0
  return status;
343
0
    }
344
345
0
    foreground_used = foreground_used || scaled_glyph->recording_uses_foreground_color;
346
    
347
0
    if (info == CAIRO_SCALED_GLYPH_INFO_COLOR_SURFACE) {
348
0
  _cairo_scaled_glyph_set_color_surface (scaled_glyph,
349
0
                 &scaled_font->base,
350
0
                 (cairo_image_surface_t *)surface,
351
0
                 foreground_used ? foreground_color : NULL);
352
0
  surface = NULL;
353
0
    } else {
354
0
  _cairo_scaled_glyph_set_surface (scaled_glyph,
355
0
           &scaled_font->base,
356
0
           (cairo_image_surface_t *) surface);
357
0
  surface = NULL;
358
0
    }
359
360
0
    if (surface)
361
0
  cairo_surface_destroy (surface);
362
363
0
    return status;
364
0
}
365
366
static void
367
_cairo_user_scaled_glyph_fini (void      *abstract_font)
368
0
{
369
0
    cairo_user_scaled_font_t *scaled_font = abstract_font;
370
371
0
    if (scaled_font->foreground_pattern)
372
0
  cairo_pattern_destroy (scaled_font->foreground_pattern);
373
374
0
    if (scaled_font->foreground_marker)
375
0
  cairo_pattern_destroy (scaled_font->foreground_marker);
376
0
}
377
378
static cairo_int_status_t
379
_cairo_user_scaled_glyph_init (void      *abstract_font,
380
             cairo_scaled_glyph_t  *scaled_glyph,
381
             cairo_scaled_glyph_info_t  info,
382
             const cairo_color_t       *foreground_color)
383
0
{
384
0
    cairo_int_status_t status = CAIRO_STATUS_SUCCESS;
385
0
    cairo_user_scaled_font_t *scaled_font = abstract_font;
386
387
0
    if (!scaled_glyph->recording_surface || (info & CAIRO_SCALED_GLYPH_INFO_RECORDING_SURFACE)) {
388
0
  status = _cairo_user_scaled_glyph_init_record_glyph (scaled_font, scaled_glyph, foreground_color);
389
0
  if (status)
390
0
      return status;
391
0
    }
392
393
0
    if (info & CAIRO_SCALED_GLYPH_INFO_COLOR_SURFACE) {
394
0
  if (!scaled_glyph->color_glyph )
395
0
      return CAIRO_INT_STATUS_UNSUPPORTED;
396
397
0
  status = _cairo_user_scaled_glyph_init_surface (scaled_font,
398
0
              scaled_glyph,
399
0
              CAIRO_SCALED_GLYPH_INFO_COLOR_SURFACE,
400
0
              foreground_color);
401
0
  if (status)
402
0
      return status;
403
0
    }
404
405
0
    if (info & CAIRO_SCALED_GLYPH_INFO_SURFACE) {
406
0
  status = _cairo_user_scaled_glyph_init_surface (scaled_font,
407
0
              scaled_glyph,
408
0
              CAIRO_SCALED_GLYPH_INFO_SURFACE,
409
0
              NULL);
410
0
  if (status)
411
0
      return status;
412
0
    }
413
414
0
    if (info & CAIRO_SCALED_GLYPH_INFO_PATH) {
415
0
  cairo_path_fixed_t *path = _cairo_path_fixed_create ();
416
0
  if (!path)
417
0
      return _cairo_error (CAIRO_STATUS_NO_MEMORY);
418
419
0
  status = _cairo_recording_surface_get_path (scaled_glyph->recording_surface, path);
420
0
  if (unlikely (status)) {
421
0
      _cairo_path_fixed_destroy (path);
422
0
      return status;
423
0
  }
424
425
0
  _cairo_scaled_glyph_set_path (scaled_glyph,
426
0
              &scaled_font->base,
427
0
              path);
428
0
    }
429
430
0
    return status;
431
0
}
432
433
static unsigned long
434
_cairo_user_ucs4_to_index (void     *abstract_font,
435
         uint32_t  ucs4)
436
0
{
437
0
    cairo_user_scaled_font_t *scaled_font = abstract_font;
438
0
    cairo_user_font_face_t *face =
439
0
  (cairo_user_font_face_t *) scaled_font->base.font_face;
440
0
    unsigned long glyph = 0;
441
442
0
    if (face->scaled_font_methods.unicode_to_glyph) {
443
0
  cairo_status_t status;
444
445
0
  status = face->scaled_font_methods.unicode_to_glyph (&scaled_font->base,
446
0
                   ucs4, &glyph);
447
448
0
  if (status == CAIRO_STATUS_USER_FONT_NOT_IMPLEMENTED)
449
0
      goto not_implemented;
450
451
0
  if (status != CAIRO_STATUS_SUCCESS) {
452
0
      status = _cairo_scaled_font_set_error (&scaled_font->base, status);
453
0
      glyph = 0;
454
0
  }
455
456
0
    } else {
457
0
not_implemented:
458
0
  glyph = ucs4;
459
0
    }
460
461
0
    return glyph;
462
0
}
463
464
static cairo_bool_t
465
_cairo_user_has_color_glyphs (void         *abstract_font)
466
0
{
467
0
    cairo_user_scaled_font_t *scaled_font = abstract_font;
468
0
    cairo_user_font_face_t *face =
469
0
  (cairo_user_font_face_t *) scaled_font->base.font_face;
470
471
0
    return face->has_color;
472
0
}
473
474
static cairo_int_status_t
475
_cairo_user_text_to_glyphs (void          *abstract_font,
476
          double           x,
477
          double           y,
478
          const char          *utf8,
479
          int            utf8_len,
480
          cairo_glyph_t      **glyphs,
481
          int            *num_glyphs,
482
          cairo_text_cluster_t      **clusters,
483
          int            *num_clusters,
484
          cairo_text_cluster_flags_t *cluster_flags)
485
0
{
486
0
    cairo_int_status_t status = CAIRO_INT_STATUS_UNSUPPORTED;
487
488
0
    cairo_user_scaled_font_t *scaled_font = abstract_font;
489
0
    cairo_user_font_face_t *face =
490
0
  (cairo_user_font_face_t *) scaled_font->base.font_face;
491
492
0
    if (face->scaled_font_methods.text_to_glyphs) {
493
0
  int i;
494
0
  cairo_glyph_t *orig_glyphs = *glyphs;
495
0
  int orig_num_glyphs = *num_glyphs;
496
497
0
  status = face->scaled_font_methods.text_to_glyphs (&scaled_font->base,
498
0
                 utf8, utf8_len,
499
0
                 glyphs, num_glyphs,
500
0
                 clusters, num_clusters, cluster_flags);
501
502
0
  if (status != CAIRO_INT_STATUS_SUCCESS &&
503
0
      status != CAIRO_INT_STATUS_USER_FONT_NOT_IMPLEMENTED)
504
0
      return status;
505
506
0
  if (status == CAIRO_INT_STATUS_USER_FONT_NOT_IMPLEMENTED ||
507
0
      *num_glyphs < 0) {
508
0
      if (orig_glyphs != *glyphs) {
509
0
    cairo_glyph_free (*glyphs);
510
0
    *glyphs = orig_glyphs;
511
0
      }
512
0
      *num_glyphs = orig_num_glyphs;
513
0
      return CAIRO_INT_STATUS_UNSUPPORTED;
514
0
  }
515
516
  /* Convert from font space to user space and add x,y */
517
0
  for (i = 0; i < *num_glyphs; i++) {
518
0
      double gx = (*glyphs)[i].x;
519
0
      double gy = (*glyphs)[i].y;
520
521
0
      cairo_matrix_transform_point (&scaled_font->base.font_matrix,
522
0
            &gx, &gy);
523
524
0
      (*glyphs)[i].x = gx + x;
525
0
      (*glyphs)[i].y = gy + y;
526
0
  }
527
0
    }
528
529
0
    return status;
530
0
}
531
532
static cairo_status_t
533
_cairo_user_font_face_scaled_font_create (void                        *abstract_face,
534
            const cairo_matrix_t        *font_matrix,
535
            const cairo_matrix_t        *ctm,
536
            const cairo_font_options_t  *options,
537
            cairo_scaled_font_t        **scaled_font);
538
539
static cairo_status_t
540
_cairo_user_font_face_create_for_toy (cairo_toy_font_face_t   *toy_face,
541
              cairo_font_face_t      **font_face)
542
0
{
543
0
    return _cairo_font_face_twin_create_for_toy (toy_face, font_face);
544
0
}
545
546
static const cairo_scaled_font_backend_t _cairo_user_scaled_font_backend = {
547
    CAIRO_FONT_TYPE_USER,
548
    _cairo_user_scaled_glyph_fini,
549
    _cairo_user_scaled_glyph_init,
550
    _cairo_user_text_to_glyphs,
551
    _cairo_user_ucs4_to_index,
552
    NULL, /* load_truetype_table */
553
    NULL, /* index_to_ucs4 */
554
    NULL,       /* is_synthetic */
555
    NULL,       /* index_to_glyph_name */
556
    NULL,       /* load_type1_data */
557
    _cairo_user_has_color_glyphs,
558
};
559
560
/* #cairo_user_font_face_t */
561
562
static cairo_status_t
563
_cairo_user_font_face_scaled_font_create (void                        *abstract_face,
564
            const cairo_matrix_t        *font_matrix,
565
            const cairo_matrix_t        *ctm,
566
            const cairo_font_options_t  *options,
567
            cairo_scaled_font_t        **scaled_font)
568
0
{
569
0
    cairo_status_t status = CAIRO_STATUS_SUCCESS;
570
0
    cairo_user_font_face_t *font_face = abstract_face;
571
0
    cairo_user_scaled_font_t *user_scaled_font = NULL;
572
0
    cairo_font_extents_t font_extents = {1., 0., 1., 1., 0.};
573
574
0
    font_face->immutable = TRUE;
575
576
0
    user_scaled_font = _cairo_calloc (sizeof (cairo_user_scaled_font_t));
577
0
    if (unlikely (user_scaled_font == NULL))
578
0
  return _cairo_error (CAIRO_STATUS_NO_MEMORY);
579
580
0
    status = _cairo_scaled_font_init (&user_scaled_font->base,
581
0
              &font_face->base,
582
0
              font_matrix, ctm, options,
583
0
              &_cairo_user_scaled_font_backend);
584
585
0
    if (unlikely (status)) {
586
0
  free (user_scaled_font);
587
0
  return status;
588
0
    }
589
590
0
    user_scaled_font->foreground_pattern = NULL;
591
0
    user_scaled_font->foreground_marker = _cairo_pattern_create_foreground_marker ();
592
593
    /* XXX metrics hinting? */
594
595
    /* compute a normalized version of font scale matrix to compute
596
     * extents in.  This is to minimize error caused by the cairo_fixed_t
597
     * representation. */
598
0
    {
599
0
  double fixed_scale, x_scale, y_scale;
600
601
0
  user_scaled_font->snap_x_scale = 1.0;
602
0
  user_scaled_font->snap_y_scale = 1.0;
603
0
  user_scaled_font->extent_scale = user_scaled_font->base.scale_inverse;
604
0
  status = _cairo_matrix_compute_basis_scale_factors (&user_scaled_font->extent_scale,
605
0
                  &x_scale, &y_scale,
606
0
                  1);
607
0
  if (status == CAIRO_STATUS_SUCCESS) {
608
609
0
      if (x_scale == 0) x_scale = 1.;
610
0
      if (y_scale == 0) y_scale = 1.;
611
612
0
      user_scaled_font->snap_x_scale = x_scale;
613
0
      user_scaled_font->snap_y_scale = y_scale;
614
615
      /* since glyphs are pretty much 1.0x1.0, we can reduce error by
616
       * scaling to a larger square.  say, 1024.x1024. */
617
0
      fixed_scale = 1024.;
618
0
      x_scale /= fixed_scale;
619
0
      y_scale /= fixed_scale;
620
621
0
      cairo_matrix_scale (&user_scaled_font->extent_scale, 1. / x_scale, 1. / y_scale);
622
623
0
      user_scaled_font->extent_x_scale = x_scale;
624
0
      user_scaled_font->extent_y_scale = y_scale;
625
0
  }
626
0
    }
627
628
0
    if (status == CAIRO_STATUS_SUCCESS &&
629
0
  font_face->scaled_font_methods.init != NULL)
630
0
    {
631
  /* Lock the scaled_font mutex such that user doesn't accidentally try
632
         * to use it just yet. */
633
0
  CAIRO_MUTEX_LOCK (user_scaled_font->base.mutex);
634
635
  /* Give away fontmap lock such that user-font can use other fonts */
636
0
  status = _cairo_scaled_font_register_placeholder_and_unlock_font_map (&user_scaled_font->base);
637
0
  if (status == CAIRO_STATUS_SUCCESS) {
638
0
      cairo_surface_t *recording_surface;
639
0
      cairo_t *cr;
640
641
0
      recording_surface = _cairo_user_scaled_font_create_recording_surface (user_scaled_font, FALSE, NULL);
642
0
      cr = _cairo_user_scaled_font_create_recording_context (user_scaled_font, recording_surface, FALSE);
643
0
      cairo_surface_destroy (recording_surface);
644
645
0
      status = font_face->scaled_font_methods.init (&user_scaled_font->base,
646
0
                cr,
647
0
                &font_extents);
648
649
0
      if (status == CAIRO_STATUS_USER_FONT_NOT_IMPLEMENTED)
650
0
    status = CAIRO_STATUS_SUCCESS;
651
652
0
      if (status == CAIRO_STATUS_SUCCESS)
653
0
    status = cairo_status (cr);
654
655
0
      cairo_destroy (cr);
656
657
0
      _cairo_scaled_font_unregister_placeholder_and_lock_font_map (&user_scaled_font->base);
658
0
  }
659
660
0
  CAIRO_MUTEX_UNLOCK (user_scaled_font->base.mutex);
661
0
    }
662
663
0
    if (status == CAIRO_STATUS_SUCCESS)
664
0
  status = _cairo_scaled_font_set_metrics (&user_scaled_font->base, &font_extents);
665
666
0
    if (status != CAIRO_STATUS_SUCCESS) {
667
0
        _cairo_scaled_font_fini (&user_scaled_font->base);
668
0
  free (user_scaled_font);
669
0
    } else {
670
0
        user_scaled_font->default_glyph_extents.x_bearing = 0.;
671
0
        user_scaled_font->default_glyph_extents.y_bearing = -font_extents.ascent;
672
0
        user_scaled_font->default_glyph_extents.width = 0.;
673
0
        user_scaled_font->default_glyph_extents.height = font_extents.ascent + font_extents.descent;
674
0
        user_scaled_font->default_glyph_extents.x_advance = font_extents.max_x_advance;
675
0
        user_scaled_font->default_glyph_extents.y_advance = 0.;
676
677
0
  *scaled_font = &user_scaled_font->base;
678
0
    }
679
680
0
    return status;
681
0
}
682
683
const cairo_font_face_backend_t _cairo_user_font_face_backend = {
684
    CAIRO_FONT_TYPE_USER,
685
    _cairo_user_font_face_create_for_toy,
686
    _cairo_font_face_destroy,
687
    _cairo_user_font_face_scaled_font_create
688
};
689
690
691
cairo_bool_t
692
_cairo_font_face_is_user (cairo_font_face_t *font_face)
693
814k
{
694
814k
    return font_face->backend == &_cairo_user_font_face_backend;
695
814k
}
696
697
/* Implement the public interface */
698
699
/**
700
 * cairo_user_font_face_create:
701
 *
702
 * Creates a new user font-face.
703
 *
704
 * Use the setter functions to associate callbacks with the returned
705
 * user font.  The only mandatory callback is render_glyph.
706
 *
707
 * After the font-face is created, the user can attach arbitrary data
708
 * (the actual font data) to it using cairo_font_face_set_user_data()
709
 * and access it from the user-font callbacks by using
710
 * cairo_scaled_font_get_font_face() followed by
711
 * cairo_font_face_get_user_data().
712
 *
713
 * Return value: a newly created #cairo_font_face_t. Free with
714
 *  cairo_font_face_destroy() when you are done using it.
715
 *
716
 * Since: 1.8
717
 **/
718
cairo_font_face_t *
719
cairo_user_font_face_create (void)
720
2
{
721
2
    cairo_user_font_face_t *font_face;
722
723
2
    font_face = _cairo_calloc (sizeof (cairo_user_font_face_t));
724
2
    if (!font_face) {
725
0
  _cairo_error_throw (CAIRO_STATUS_NO_MEMORY);
726
0
  return (cairo_font_face_t *)&_cairo_font_face_nil;
727
0
    }
728
729
2
    _cairo_font_face_init (&font_face->base, &_cairo_user_font_face_backend);
730
731
2
    font_face->immutable = FALSE;
732
2
    font_face->has_color = FALSE;
733
2
    memset (&font_face->scaled_font_methods, 0, sizeof (font_face->scaled_font_methods));
734
735
2
    return &font_face->base;
736
2
}
737
738
/* User-font method setters */
739
740
741
/**
742
 * cairo_user_font_face_set_init_func:
743
 * @font_face: A user font face
744
 * @init_func: The init callback, or %NULL
745
 *
746
 * Sets the scaled-font initialization function of a user-font.
747
 * See #cairo_user_scaled_font_init_func_t for details of how the callback
748
 * works.
749
 *
750
 * The font-face should not be immutable or a %CAIRO_STATUS_USER_FONT_IMMUTABLE
751
 * error will occur.  A user font-face is immutable as soon as a scaled-font
752
 * is created from it.
753
 *
754
 * Since: 1.8
755
 **/
756
void
757
cairo_user_font_face_set_init_func (cairo_font_face_t                  *font_face,
758
            cairo_user_scaled_font_init_func_t  init_func)
759
2
{
760
2
    cairo_user_font_face_t *user_font_face;
761
762
2
    if (font_face->status)
763
0
  return;
764
765
2
    if (! _cairo_font_face_is_user (font_face)) {
766
0
  if (_cairo_font_face_set_error (font_face, CAIRO_STATUS_FONT_TYPE_MISMATCH))
767
0
      return;
768
0
    }
769
770
2
    user_font_face = (cairo_user_font_face_t *) font_face;
771
2
    if (user_font_face->immutable) {
772
0
  if (_cairo_font_face_set_error (font_face, CAIRO_STATUS_USER_FONT_IMMUTABLE))
773
0
      return;
774
0
    }
775
2
    user_font_face->scaled_font_methods.init = init_func;
776
2
}
777
778
/**
779
 * cairo_user_font_face_set_render_color_glyph_func:
780
 * @font_face: A user font face
781
 * @render_glyph_func: The render_glyph callback, or %NULL
782
 *
783
 * Sets the color glyph rendering function of a user-font.
784
 * See #cairo_user_scaled_font_render_glyph_func_t for details of how the callback
785
 * works.
786
 *
787
 * The font-face should not be immutable or a %CAIRO_STATUS_USER_FONT_IMMUTABLE
788
 * error will occur.  A user font-face is immutable as soon as a scaled-font
789
 * is created from it.
790
 *
791
 * The render_glyph callback is the only mandatory callback of a
792
 * user-font. At least one of
793
 * cairo_user_font_face_set_render_color_glyph_func() or
794
 * cairo_user_font_face_set_render_glyph_func() must be called to set
795
 * a render callback. If both callbacks are set, the color glyph
796
 * render callback is invoked first. If the color glyph render
797
 * callback returns %CAIRO_STATUS_USER_FONT_NOT_IMPLEMENTED, the
798
 * non-color version of the callback is invoked.
799
 *
800
 * If the callback is %NULL and a glyph is tried to be rendered using
801
 * @font_face, a %CAIRO_STATUS_USER_FONT_ERROR will occur.
802
 *
803
 * Since: 1.18
804
 **/
805
void
806
cairo_user_font_face_set_render_color_glyph_func (cairo_font_face_t                          *font_face,
807
                                                  cairo_user_scaled_font_render_glyph_func_t  render_glyph_func)
808
2
{
809
2
    cairo_user_font_face_t *user_font_face;
810
811
2
    if (font_face->status)
812
0
  return;
813
814
2
    if (! _cairo_font_face_is_user (font_face)) {
815
0
  if (_cairo_font_face_set_error (font_face, CAIRO_STATUS_FONT_TYPE_MISMATCH))
816
0
      return;
817
0
    }
818
819
2
    user_font_face = (cairo_user_font_face_t *) font_face;
820
2
    if (user_font_face->immutable) {
821
0
  if (_cairo_font_face_set_error (font_face, CAIRO_STATUS_USER_FONT_IMMUTABLE))
822
0
      return;
823
0
    }
824
2
    user_font_face->scaled_font_methods.render_color_glyph = render_glyph_func;
825
2
    user_font_face->has_color = render_glyph_func ? TRUE : FALSE;
826
2
}
827
828
/**
829
 * cairo_user_font_face_set_render_glyph_func:
830
 * @font_face: A user font face
831
 * @render_glyph_func: The render_glyph callback, or %NULL
832
 *
833
 * Sets the glyph rendering function of a user-font.
834
 * See #cairo_user_scaled_font_render_glyph_func_t for details of how the callback
835
 * works.
836
 *
837
 * The font-face should not be immutable or a %CAIRO_STATUS_USER_FONT_IMMUTABLE
838
 * error will occur.  A user font-face is immutable as soon as a scaled-font
839
 * is created from it.
840
 *
841
 * The render_glyph callback is the only mandatory callback of a
842
 * user-font. At least one of
843
 * cairo_user_font_face_set_render_color_glyph_func() or
844
 * cairo_user_font_face_set_render_glyph_func() must be called to set
845
 * a render callback. If both callbacks are set, the color glyph
846
 * render callback is invoked first. If the color glyph render
847
 * callback returns %CAIRO_STATUS_USER_FONT_NOT_IMPLEMENTED, the
848
 * non-color version of the callback is invoked.
849
 *
850
 * If the callback is %NULL and a glyph is tried to be rendered using
851
 * @font_face, a %CAIRO_STATUS_USER_FONT_ERROR will occur.
852
 *
853
 * Since: 1.8
854
 **/
855
void
856
cairo_user_font_face_set_render_glyph_func (cairo_font_face_t                          *font_face,
857
              cairo_user_scaled_font_render_glyph_func_t  render_glyph_func)
858
2
{
859
2
    cairo_user_font_face_t *user_font_face;
860
861
2
    if (font_face->status)
862
0
  return;
863
864
2
    if (! _cairo_font_face_is_user (font_face)) {
865
0
  if (_cairo_font_face_set_error (font_face, CAIRO_STATUS_FONT_TYPE_MISMATCH))
866
0
      return;
867
0
    }
868
869
2
    user_font_face = (cairo_user_font_face_t *) font_face;
870
2
    if (user_font_face->immutable) {
871
0
  if (_cairo_font_face_set_error (font_face, CAIRO_STATUS_USER_FONT_IMMUTABLE))
872
0
      return;
873
0
    }
874
2
    user_font_face->scaled_font_methods.render_glyph = render_glyph_func;
875
2
}
876
877
/**
878
 * cairo_user_font_face_set_text_to_glyphs_func:
879
 * @font_face: A user font face
880
 * @text_to_glyphs_func: The text_to_glyphs callback, or %NULL
881
 *
882
 * Sets th text-to-glyphs conversion function of a user-font.
883
 * See #cairo_user_scaled_font_text_to_glyphs_func_t for details of how the callback
884
 * works.
885
 *
886
 * The font-face should not be immutable or a %CAIRO_STATUS_USER_FONT_IMMUTABLE
887
 * error will occur.  A user font-face is immutable as soon as a scaled-font
888
 * is created from it.
889
 *
890
 * Since: 1.8
891
 **/
892
void
893
cairo_user_font_face_set_text_to_glyphs_func (cairo_font_face_t                            *font_face,
894
                cairo_user_scaled_font_text_to_glyphs_func_t  text_to_glyphs_func)
895
0
{
896
0
    cairo_user_font_face_t *user_font_face;
897
898
0
    if (font_face->status)
899
0
  return;
900
901
0
    if (! _cairo_font_face_is_user (font_face)) {
902
0
  if (_cairo_font_face_set_error (font_face, CAIRO_STATUS_FONT_TYPE_MISMATCH))
903
0
      return;
904
0
    }
905
906
0
    user_font_face = (cairo_user_font_face_t *) font_face;
907
0
    if (user_font_face->immutable) {
908
0
  if (_cairo_font_face_set_error (font_face, CAIRO_STATUS_USER_FONT_IMMUTABLE))
909
0
      return;
910
0
    }
911
0
    user_font_face->scaled_font_methods.text_to_glyphs = text_to_glyphs_func;
912
0
}
913
914
/**
915
 * cairo_user_font_face_set_unicode_to_glyph_func:
916
 * @font_face: A user font face
917
 * @unicode_to_glyph_func: The unicode_to_glyph callback, or %NULL
918
 *
919
 * Sets the unicode-to-glyph conversion function of a user-font.
920
 * See #cairo_user_scaled_font_unicode_to_glyph_func_t for details of how the callback
921
 * works.
922
 *
923
 * The font-face should not be immutable or a %CAIRO_STATUS_USER_FONT_IMMUTABLE
924
 * error will occur.  A user font-face is immutable as soon as a scaled-font
925
 * is created from it.
926
 *
927
 * Since: 1.8
928
 **/
929
void
930
cairo_user_font_face_set_unicode_to_glyph_func (cairo_font_face_t                              *font_face,
931
            cairo_user_scaled_font_unicode_to_glyph_func_t  unicode_to_glyph_func)
932
0
{
933
0
    cairo_user_font_face_t *user_font_face;
934
0
    if (font_face->status)
935
0
  return;
936
937
0
    if (! _cairo_font_face_is_user (font_face)) {
938
0
  if (_cairo_font_face_set_error (font_face, CAIRO_STATUS_FONT_TYPE_MISMATCH))
939
0
      return;
940
0
    }
941
942
0
    user_font_face = (cairo_user_font_face_t *) font_face;
943
0
    if (user_font_face->immutable) {
944
0
  if (_cairo_font_face_set_error (font_face, CAIRO_STATUS_USER_FONT_IMMUTABLE))
945
0
      return;
946
0
    }
947
0
    user_font_face->scaled_font_methods.unicode_to_glyph = unicode_to_glyph_func;
948
0
}
949
950
/* User-font method getters */
951
952
/**
953
 * cairo_user_font_face_get_init_func:
954
 * @font_face: A user font face
955
 *
956
 * Gets the scaled-font initialization function of a user-font.
957
 *
958
 * Return value: The init callback of @font_face
959
 * or %NULL if none set or an error has occurred.
960
 *
961
 * Since: 1.8
962
 **/
963
cairo_user_scaled_font_init_func_t
964
cairo_user_font_face_get_init_func (cairo_font_face_t *font_face)
965
0
{
966
0
    cairo_user_font_face_t *user_font_face;
967
968
0
    if (font_face->status)
969
0
  return NULL;
970
971
0
    if (! _cairo_font_face_is_user (font_face)) {
972
0
  if (_cairo_font_face_set_error (font_face, CAIRO_STATUS_FONT_TYPE_MISMATCH))
973
0
      return NULL;
974
0
    }
975
976
0
    user_font_face = (cairo_user_font_face_t *) font_face;
977
0
    return user_font_face->scaled_font_methods.init;
978
0
}
979
980
/**
981
 * cairo_user_font_face_get_render_color_glyph_func:
982
 * @font_face: A user font face
983
 *
984
 * Gets the color glyph rendering function of a user-font.
985
 *
986
 * Return value: The render_glyph callback of @font_face
987
 * or %NULL if none set or an error has occurred.
988
 *
989
 * Since: 1.18
990
 **/
991
cairo_user_scaled_font_render_glyph_func_t
992
cairo_user_font_face_get_render_color_glyph_func (cairo_font_face_t *font_face)
993
0
{
994
0
    cairo_user_font_face_t *user_font_face;
995
996
0
    if (font_face->status)
997
0
  return NULL;
998
999
0
    if (! _cairo_font_face_is_user (font_face)) {
1000
0
  if (_cairo_font_face_set_error (font_face, CAIRO_STATUS_FONT_TYPE_MISMATCH))
1001
0
      return NULL;
1002
0
    }
1003
1004
0
    user_font_face = (cairo_user_font_face_t *) font_face;
1005
0
    return user_font_face->scaled_font_methods.render_color_glyph;
1006
0
}
1007
1008
/**
1009
 * cairo_user_font_face_get_render_glyph_func:
1010
 * @font_face: A user font face
1011
 *
1012
 * Gets the glyph rendering function of a user-font.
1013
 *
1014
 * Return value: The render_glyph callback of @font_face
1015
 * or %NULL if none set or an error has occurred.
1016
 *
1017
 * Since: 1.8
1018
 **/
1019
cairo_user_scaled_font_render_glyph_func_t
1020
cairo_user_font_face_get_render_glyph_func (cairo_font_face_t *font_face)
1021
0
{
1022
0
    cairo_user_font_face_t *user_font_face;
1023
1024
0
    if (font_face->status)
1025
0
  return NULL;
1026
1027
0
    if (! _cairo_font_face_is_user (font_face)) {
1028
0
  if (_cairo_font_face_set_error (font_face, CAIRO_STATUS_FONT_TYPE_MISMATCH))
1029
0
      return NULL;
1030
0
    }
1031
1032
0
    user_font_face = (cairo_user_font_face_t *) font_face;
1033
0
    return user_font_face->scaled_font_methods.render_glyph;
1034
0
}
1035
1036
/**
1037
 * cairo_user_font_face_get_text_to_glyphs_func:
1038
 * @font_face: A user font face
1039
 *
1040
 * Gets the text-to-glyphs conversion function of a user-font.
1041
 *
1042
 * Return value: The text_to_glyphs callback of @font_face
1043
 * or %NULL if none set or an error occurred.
1044
 *
1045
 * Since: 1.8
1046
 **/
1047
cairo_user_scaled_font_text_to_glyphs_func_t
1048
cairo_user_font_face_get_text_to_glyphs_func (cairo_font_face_t *font_face)
1049
0
{
1050
0
    cairo_user_font_face_t *user_font_face;
1051
1052
0
    if (font_face->status)
1053
0
  return NULL;
1054
1055
0
    if (! _cairo_font_face_is_user (font_face)) {
1056
0
  if (_cairo_font_face_set_error (font_face, CAIRO_STATUS_FONT_TYPE_MISMATCH))
1057
0
      return NULL;
1058
0
    }
1059
1060
0
    user_font_face = (cairo_user_font_face_t *) font_face;
1061
0
    return user_font_face->scaled_font_methods.text_to_glyphs;
1062
0
}
1063
1064
/**
1065
 * cairo_user_font_face_get_unicode_to_glyph_func:
1066
 * @font_face: A user font face
1067
 *
1068
 * Gets the unicode-to-glyph conversion function of a user-font.
1069
 *
1070
 * Return value: The unicode_to_glyph callback of @font_face
1071
 * or %NULL if none set or an error occurred.
1072
 *
1073
 * Since: 1.8
1074
 **/
1075
cairo_user_scaled_font_unicode_to_glyph_func_t
1076
cairo_user_font_face_get_unicode_to_glyph_func (cairo_font_face_t *font_face)
1077
0
{
1078
0
    cairo_user_font_face_t *user_font_face;
1079
1080
0
    if (font_face->status)
1081
0
  return NULL;
1082
1083
0
    if (! _cairo_font_face_is_user (font_face)) {
1084
0
  if (_cairo_font_face_set_error (font_face, CAIRO_STATUS_FONT_TYPE_MISMATCH))
1085
0
      return NULL;
1086
0
    }
1087
1088
0
    user_font_face = (cairo_user_font_face_t *) font_face;
1089
0
    return user_font_face->scaled_font_methods.unicode_to_glyph;
1090
0
}
1091
1092
/**
1093
 * cairo_user_scaled_font_get_foreground_marker:
1094
 * @scaled_font: A user scaled font
1095
 *
1096
 * Gets the foreground pattern of the glyph currently being
1097
 * rendered. A #cairo_user_scaled_font_render_glyph_func_t function
1098
 * that has been set with
1099
 * cairo_user_font_face_set_render_color_glyph_func() may call this
1100
 * function to retrieve the current foreground pattern for the glyph
1101
 * being rendered. The function should not be called outside of a
1102
 * cairo_user_font_face_set_render_color_glyph_func() callback.
1103
 *
1104
 * The foreground marker pattern contains an internal marker to
1105
 * indicate that it is to be substituted with the current source when
1106
 * rendered to a surface. Querying the foreground marker will reveal a
1107
 * solid black color, however this is not representative of the color
1108
 * that will actually be used. Similarly, setting a solid black color
1109
 * will render black, not the foreground pattern when the glyph is
1110
 * painted to a surface. Using the foreground marker as the source
1111
 * instead of cairo_user_scaled_font_get_foreground_source() in a
1112
 * color render callback has the following benefits:
1113
 *
1114
 * 1. Cairo only needs to call the render callback once as it can
1115
 * cache the recording. Cairo will substitute the actual foreground
1116
 * color when rendering the recording.
1117
 *
1118
 * 2. On backends that have the concept of a foreground color in fonts such as
1119
 * PDF, PostScript, and SVG, cairo can generate more optimal
1120
 * output. The glyph can be included in an embedded font.
1121
 *
1122
 * The one drawback of the using foreground marker is the render
1123
 * callback can not access the color components of the pattern as the
1124
 * actual foreground pattern is not available at the time the render
1125
 * callback is invoked. If the render callback needs to query the
1126
 * foreground pattern, use
1127
 * cairo_user_scaled_font_get_foreground_source().
1128
 *
1129
 * If the render callback simply wants to call cairo_set_source() with
1130
 * the foreground pattern,
1131
 * cairo_user_scaled_font_get_foreground_marker() is the preferred
1132
 * function to use as it results in better performance than
1133
 * cairo_user_scaled_font_get_foreground_source().
1134
 *
1135
 * Return value: the current foreground source marker pattern. This
1136
 * object is owned by cairo. This object must not be modified or used
1137
 * outside of a color render callback. To keep a reference to it,
1138
 * you must call cairo_pattern_reference().
1139
 *
1140
 * Since: 1.18
1141
 **/
1142
cairo_pattern_t *
1143
cairo_user_scaled_font_get_foreground_marker (cairo_scaled_font_t *scaled_font)
1144
0
{
1145
0
    cairo_user_scaled_font_t *user_scaled_font;
1146
1147
0
    if (scaled_font->backend != &_cairo_user_scaled_font_backend)
1148
0
  return _cairo_pattern_create_in_error (CAIRO_STATUS_FONT_TYPE_MISMATCH);
1149
1150
0
    user_scaled_font = (cairo_user_scaled_font_t *)scaled_font;
1151
0
    return user_scaled_font->foreground_marker;
1152
0
}
1153
1154
/**
1155
 * cairo_user_scaled_font_get_foreground_source:
1156
 * @scaled_font: A user scaled font
1157
 *
1158
 * Gets the foreground pattern of the glyph currently being
1159
 * rendered. A #cairo_user_scaled_font_render_glyph_func_t function
1160
 * that has been set with
1161
 * cairo_user_font_face_set_render_color_glyph_func() may call this
1162
 * function to retrieve the current foreground pattern for the glyph
1163
 * being rendered. The function should not be called outside of a
1164
 * cairo_user_font_face_set_render_color_glyph_func() callback.
1165
 *
1166
 * This function returns the current source at the time the glyph is
1167
 * rendered. Compared with
1168
 * cairo_user_scaled_font_get_foreground_marker(), this function
1169
 * returns the actual source pattern that will be used to render the
1170
 * glyph.  The render callback is free to query the pattern and
1171
 * extract color components or other pattern data. For example if the
1172
 * render callback wants to create a gradient stop based on colors in
1173
 * the foreground source pattern, it will need to use this function in
1174
 * order to be able to query the colors in the foreground pattern.
1175
 *
1176
 * While this function does not have the restrictions on using the
1177
 * pattern that cairo_user_scaled_font_get_foreground_marker() has, it
1178
 * does incur a performance penalty. If a render callback calls this
1179
 * function:
1180
 *
1181
 * 1. Cairo will call the render callback whenever the current pattern
1182
 * of the context in which the glyph is rendered changes.
1183
 *
1184
 * 2. On backends that support font embedding (PDF, PostScript, and
1185
 * SVG), cairo can not embed this glyph in a font. Instead the glyph
1186
 * will be emitted as an image or sequence of drawing operations each
1187
 * time it is used.
1188
 *
1189
 * Return value: the current foreground source pattern. This object is
1190
 * owned by cairo. To keep a reference to it, you must call
1191
 * cairo_pattern_reference().
1192
 *
1193
 * Since: 1.18
1194
 **/
1195
cairo_pattern_t *
1196
cairo_user_scaled_font_get_foreground_source (cairo_scaled_font_t *scaled_font)
1197
0
{
1198
0
    cairo_user_scaled_font_t *user_scaled_font;
1199
1200
0
    if (scaled_font->backend != &_cairo_user_scaled_font_backend)
1201
0
  return _cairo_pattern_create_in_error (CAIRO_STATUS_FONT_TYPE_MISMATCH);
1202
1203
0
    user_scaled_font = (cairo_user_scaled_font_t *)scaled_font;
1204
0
    user_scaled_font->foreground_colors_used = TRUE;
1205
0
    return user_scaled_font->foreground_pattern;
1206
0
}