Coverage Report

Created: 2025-11-16 09:57

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/work/workdir/UnpackedTarball/cairo/src/cairo-ft-font.c
Line
Count
Source
1
/* -*- Mode: c; c-basic-offset: 4; indent-tabs-mode: t; tab-width: 8; -*- */
2
/* cairo - a vector graphics library with display and print output
3
 *
4
 * Copyright © 2000 Keith Packard
5
 * Copyright © 2005 Red Hat, Inc
6
 *
7
 * This library is free software; you can redistribute it and/or
8
 * modify it either under the terms of the GNU Lesser General Public
9
 * License version 2.1 as published by the Free Software Foundation
10
 * (the "LGPL") or, at your option, under the terms of the Mozilla
11
 * Public License Version 1.1 (the "MPL"). If you do not alter this
12
 * notice, a recipient may use your version of this file under either
13
 * the MPL or the LGPL.
14
 *
15
 * You should have received a copy of the LGPL along with this library
16
 * in the file COPYING-LGPL-2.1; if not, write to the Free Software
17
 * Foundation, Inc., 51 Franklin Street, Suite 500, Boston, MA 02110-1335, USA
18
 * You should have received a copy of the MPL along with this library
19
 * in the file COPYING-MPL-1.1
20
 *
21
 * The contents of this file are subject to the Mozilla Public License
22
 * Version 1.1 (the "License"); you may not use this file except in
23
 * compliance with the License. You may obtain a copy of the License at
24
 * http://www.mozilla.org/MPL/
25
 *
26
 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
27
 * OF ANY KIND, either express or implied. See the LGPL or the MPL for
28
 * the specific language governing rights and limitations.
29
 *
30
 * The Original Code is the cairo graphics library.
31
 *
32
 * The Initial Developer of the Original Code is Red Hat, Inc.
33
 *
34
 * Contributor(s):
35
 *      Graydon Hoare <graydon@redhat.com>
36
 *  Owen Taylor <otaylor@redhat.com>
37
 *      Keith Packard <keithp@keithp.com>
38
 *      Carl Worth <cworth@cworth.org>
39
 */
40
41
#define _DEFAULT_SOURCE /* for strdup() */
42
#include "cairoint.h"
43
44
#include "cairo-error-private.h"
45
#include "cairo-image-surface-private.h"
46
#include "cairo-ft-private.h"
47
#include "cairo-list-inline.h"
48
#include "cairo-path-private.h"
49
#include "cairo-pattern-private.h"
50
#include "cairo-pixman-private.h"
51
#include "cairo-recording-surface-private.h"
52
53
#include <float.h>
54
55
#include "cairo-fontconfig-private.h"
56
57
#include <ft2build.h>
58
#include FT_FREETYPE_H
59
#include FT_OUTLINE_H
60
#include FT_IMAGE_H
61
#include FT_BITMAP_H
62
#include FT_TRUETYPE_TABLES_H
63
#include FT_FONT_FORMATS_H
64
#include FT_MULTIPLE_MASTERS_H
65
#include FT_SYNTHESIS_H
66
#include FT_LCD_FILTER_H
67
68
#if HAVE_FT_SVG_DOCUMENT
69
#include FT_OTSVG_H
70
#endif
71
72
#if HAVE_UNISTD_H
73
#include <unistd.h>
74
#elif !defined(access)
75
#define access(p, m) 0
76
#endif
77
78
/*  FreeType version older than 2.11 does not have the FT_RENDER_MODE_SDF enum value in FT_Render_Mode */
79
#if FREETYPE_MAJOR > 2 || (FREETYPE_MAJOR == 2 && FREETYPE_MINOR >= 11)
80
#define HAVE_FT_RENDER_MODE_SDF 1
81
#endif
82
83
0
#define DOUBLE_FROM_26_6(t) ((double)(t) / 64.0)
84
450k
#define DOUBLE_TO_16_16(d) ((FT_Fixed)((d) * 65536.0))
85
#define DOUBLE_FROM_16_16(t) ((double)(t) / 65536.0)
86
87
/* SCALE() mimics code from commit 399b00a99b2bbc1c56a05974c936aa69a08021f5
88
 * concerning a potential division by 0, but instead of doing a * (1/b), it
89
 * does a/b, thus improving the accuracy. With a * (1/b), for a bitmap font
90
 * of size 13, the computed -y_bearing was 0x1.6000000000001p+3 instead of
91
 * 0x1.6p+3 (= 11). This triggered a bug in GNU Emacs (when built against
92
 * cairo), which rounded the value to an integer with ceil().
93
 * Details:
94
 *   https://gitlab.freedesktop.org/cairo/cairo/-/issues/503
95
 *   https://debbugs.gnu.org/cgi/bugreport.cgi?bug=44284
96
 *
97
 * Note that rounding errors are not necessarily expected by applications
98
 * in simple cases like the GNU Emacs one (an identity transformation,
99
 * which should normally leave the inputs unchanged). However, with the
100
 * current cairo code, due to the scaling, there is no guarantee that
101
 * rounding errors will always be avoided at the end. For instance,
102
 * (a/b)*b may be different from a, but this is still better than doing
103
 * (a*(1/b))*b.
104
 *
105
 * According to the commit mentioned above, avoiding a division by zero
106
 * was an attempt to fix
107
 *   https://bugzilla.gnome.org/show_bug.cgi?id=311299
108
 * but this did not actually solve the problem. So it might be possible
109
 * to change SCALE() to just do (a) / (b).
110
 */
111
304k
#define SCALE(a,b) ((b) == 0 ? 0.0 : (a) / (b))
112
113
/* This is the max number of FT_face objects we keep open at once
114
 */
115
5
#define MAX_OPEN_FACES 10
116
117
/**
118
 * SECTION:cairo-ft
119
 * @Title: FreeType Fonts
120
 * @Short_Description: Font support for FreeType
121
 * @See_Also: #cairo_font_face_t
122
 *
123
 * The FreeType font backend is primarily used to render text on GNU/Linux
124
 * systems, but can be used on other platforms too.
125
 **/
126
127
/**
128
 * CAIRO_HAS_FT_FONT:
129
 *
130
 * Defined if the FreeType font backend is available.
131
 * This macro can be used to conditionally compile backend-specific code.
132
 *
133
 * Since: 1.0
134
 **/
135
136
/**
137
 * CAIRO_HAS_FC_FONT:
138
 *
139
 * Defined if the Fontconfig-specific functions of the FreeType font backend
140
 * are available.
141
 * This macro can be used to conditionally compile backend-specific code.
142
 *
143
 * Since: 1.10
144
 **/
145
146
/*
147
 * The simple 2x2 matrix is converted into separate scale and shape
148
 * factors so that hinting works right
149
 */
150
151
typedef struct _cairo_ft_font_transform {
152
    double  x_scale, y_scale;
153
    double  shape[2][2];
154
} cairo_ft_font_transform_t;
155
156
/*
157
 * We create an object that corresponds to a single font on the disk;
158
 * (identified by a filename/id pair) these are shared between all
159
 * fonts using that file.  For cairo_ft_font_face_create_for_ft_face(), we
160
 * just create a one-off version with a permanent face value.
161
 */
162
163
typedef struct _cairo_ft_font_face cairo_ft_font_face_t;
164
165
struct _cairo_ft_unscaled_font {
166
    cairo_unscaled_font_t base;
167
168
    cairo_bool_t from_face; /* was the FT_Face provided by user? */
169
    FT_Face face;     /* provided or cached face */
170
171
    /* only set if from_face is false */
172
    char *filename;
173
    int id;
174
175
    /* We temporarily scale the unscaled font as needed */
176
    cairo_bool_t have_scale;
177
    cairo_matrix_t current_scale;
178
    double x_scale;   /* Extracted X scale factor */
179
    double y_scale;             /* Extracted Y scale factor */
180
    cairo_bool_t have_shape;  /* true if the current scale has a non-scale component*/
181
    cairo_matrix_t current_shape;
182
    FT_Matrix Current_Shape;
183
184
    unsigned int have_color_set  : 1;
185
    unsigned int have_color      : 1;  /* true if the font contains color glyphs */
186
    FT_Fixed *variations;              /* variation settings that FT_Face came */
187
    unsigned int num_palettes;
188
189
    cairo_mutex_t mutex;
190
    int lock_count;
191
192
    cairo_ft_font_face_t *faces;  /* Linked list of faces for this font */
193
};
194
195
static int
196
_cairo_ft_unscaled_font_keys_equal (const void *key_a,
197
            const void *key_b);
198
199
static void
200
_cairo_ft_unscaled_font_fini (cairo_ft_unscaled_font_t *unscaled);
201
202
typedef struct _cairo_ft_options {
203
    cairo_font_options_t base;
204
    unsigned int load_flags; /* flags for FT_Load_Glyph */
205
    unsigned int synth_flags;
206
} cairo_ft_options_t;
207
208
static void
209
_cairo_ft_options_init_copy (cairo_ft_options_t       *options,
210
                             const cairo_ft_options_t *other)
211
5
{
212
5
    _cairo_font_options_init_copy (&options->base, &other->base);
213
5
    options->load_flags = other->load_flags;
214
5
    options->synth_flags = other->synth_flags;
215
5
}
216
217
static void
218
_cairo_ft_options_fini (cairo_ft_options_t *options)
219
2.11k
{
220
2.11k
    _cairo_font_options_fini (&options->base);
221
2.11k
}
222
223
struct _cairo_ft_font_face {
224
    cairo_font_face_t base;
225
226
    cairo_ft_unscaled_font_t *unscaled;
227
    cairo_ft_options_t ft_options;
228
    cairo_ft_font_face_t *next;
229
230
#if CAIRO_HAS_FC_FONT
231
    FcPattern *pattern; /* if pattern is set, the above fields will be NULL */
232
    cairo_font_face_t *resolved_font_face;
233
    FcConfig *resolved_config;
234
#endif
235
};
236
237
static const cairo_unscaled_font_backend_t cairo_ft_unscaled_font_backend;
238
239
#if CAIRO_HAS_FC_FONT
240
static cairo_status_t
241
_cairo_ft_font_options_substitute (const cairo_font_options_t *options,
242
           FcPattern                  *pattern);
243
244
static cairo_font_face_t *
245
_cairo_ft_resolve_pattern (FcPattern          *pattern,
246
         const cairo_matrix_t       *font_matrix,
247
         const cairo_matrix_t       *ctm,
248
         const cairo_font_options_t *options);
249
250
#endif
251
252
cairo_status_t
253
_cairo_ft_to_cairo_error (FT_Error error)
254
0
{
255
  /* Currently we don't get many (any?) useful statuses here.
256
   * Populate as needed. */
257
0
  switch (error)
258
0
  {
259
0
      case FT_Err_Ok:
260
0
    return CAIRO_STATUS_SUCCESS;
261
0
      case FT_Err_Out_Of_Memory:
262
0
    return CAIRO_STATUS_NO_MEMORY;
263
0
      default:
264
0
    return CAIRO_STATUS_FREETYPE_ERROR;
265
0
  }
266
0
}
267
268
/*
269
 * We maintain a hash table to map file/id => #cairo_ft_unscaled_font_t.
270
 * The hash table itself isn't limited in size. However, we limit the
271
 * number of FT_Face objects we keep around; when we've exceeded that
272
 * limit and need to create a new FT_Face, we dump the FT_Face from a
273
 * random #cairo_ft_unscaled_font_t which has an unlocked FT_Face, (if
274
 * there are any).
275
 */
276
277
typedef struct _cairo_ft_unscaled_font_map {
278
    cairo_hash_table_t *hash_table;
279
    FT_Library ft_library;
280
    int num_open_faces;
281
} cairo_ft_unscaled_font_map_t;
282
283
static cairo_ft_unscaled_font_map_t *cairo_ft_unscaled_font_map = NULL;
284
285
286
static FT_Face
287
_cairo_ft_unscaled_font_lock_face (cairo_ft_unscaled_font_t *unscaled);
288
289
static void
290
_cairo_ft_unscaled_font_unlock_face (cairo_ft_unscaled_font_t *unscaled);
291
292
static cairo_bool_t
293
_cairo_ft_scaled_font_is_vertical (cairo_scaled_font_t *scaled_font);
294
295
296
static void
297
_font_map_release_face_lock_held (cairo_ft_unscaled_font_map_t *font_map,
298
          cairo_ft_unscaled_font_t *unscaled)
299
0
{
300
0
    if (unscaled->face) {
301
0
  FT_Done_Face (unscaled->face);
302
0
  unscaled->face = NULL;
303
0
  unscaled->have_scale = FALSE;
304
305
0
  font_map->num_open_faces--;
306
0
    }
307
0
}
308
309
static cairo_status_t
310
_cairo_ft_unscaled_font_map_create (void)
311
2
{
312
2
    cairo_ft_unscaled_font_map_t *font_map;
313
314
    /* This function is only intended to be called from
315
     * _cairo_ft_unscaled_font_map_lock. So we'll crash if we can
316
     * detect some other call path. */
317
2
    assert (cairo_ft_unscaled_font_map == NULL);
318
319
2
    font_map = _cairo_calloc (sizeof (cairo_ft_unscaled_font_map_t));
320
2
    if (unlikely (font_map == NULL))
321
0
  return _cairo_error (CAIRO_STATUS_NO_MEMORY);
322
323
2
    font_map->hash_table =
324
2
  _cairo_hash_table_create (_cairo_ft_unscaled_font_keys_equal);
325
326
2
    if (unlikely (font_map->hash_table == NULL))
327
0
  goto FAIL;
328
329
2
    if (unlikely (FT_Init_FreeType (&font_map->ft_library)))
330
0
  goto FAIL;
331
332
2
    font_map->num_open_faces = 0;
333
334
2
    cairo_ft_unscaled_font_map = font_map;
335
2
    return CAIRO_STATUS_SUCCESS;
336
337
0
FAIL:
338
0
    if (font_map->hash_table)
339
0
  _cairo_hash_table_destroy (font_map->hash_table);
340
0
    free (font_map);
341
342
0
    return _cairo_error (CAIRO_STATUS_NO_MEMORY);
343
2
}
344
345
346
static void
347
_cairo_ft_unscaled_font_map_pluck_entry (void *entry, void *closure)
348
0
{
349
0
    cairo_ft_unscaled_font_t *unscaled = entry;
350
0
    cairo_ft_unscaled_font_map_t *font_map = closure;
351
352
0
    _cairo_hash_table_remove (font_map->hash_table,
353
0
            &unscaled->base.hash_entry);
354
355
0
    if (! unscaled->from_face)
356
0
  _font_map_release_face_lock_held (font_map, unscaled);
357
358
0
    _cairo_ft_unscaled_font_fini (unscaled);
359
0
    free (unscaled);
360
0
}
361
362
static void
363
_cairo_ft_unscaled_font_map_destroy (void)
364
0
{
365
0
    cairo_ft_unscaled_font_map_t *font_map;
366
367
0
    CAIRO_MUTEX_LOCK (_cairo_ft_unscaled_font_map_mutex);
368
0
    font_map = cairo_ft_unscaled_font_map;
369
0
    cairo_ft_unscaled_font_map = NULL;
370
0
    CAIRO_MUTEX_UNLOCK (_cairo_ft_unscaled_font_map_mutex);
371
372
0
    if (font_map != NULL) {
373
0
  _cairo_hash_table_foreach (font_map->hash_table,
374
0
           _cairo_ft_unscaled_font_map_pluck_entry,
375
0
           font_map);
376
0
  assert (font_map->num_open_faces == 0);
377
378
0
  FT_Done_FreeType (font_map->ft_library);
379
380
0
  _cairo_hash_table_destroy (font_map->hash_table);
381
382
0
  free (font_map);
383
0
    }
384
0
}
385
386
static cairo_ft_unscaled_font_map_t *
387
_cairo_ft_unscaled_font_map_lock (void)
388
2.12k
{
389
2.12k
    CAIRO_MUTEX_INITIALIZE ();
390
391
2.12k
    CAIRO_MUTEX_LOCK (_cairo_ft_unscaled_font_map_mutex);
392
393
2.12k
    if (unlikely (cairo_ft_unscaled_font_map == NULL)) {
394
2
  if (unlikely (_cairo_ft_unscaled_font_map_create ())) {
395
0
      CAIRO_MUTEX_UNLOCK (_cairo_ft_unscaled_font_map_mutex);
396
0
      return NULL;
397
0
  }
398
2
    }
399
400
2.12k
    return cairo_ft_unscaled_font_map;
401
2.12k
}
402
403
static void
404
_cairo_ft_unscaled_font_map_unlock (void)
405
2.12k
{
406
2.12k
    CAIRO_MUTEX_UNLOCK (_cairo_ft_unscaled_font_map_mutex);
407
2.12k
}
408
409
static void
410
_cairo_ft_unscaled_font_init_key (cairo_ft_unscaled_font_t *key,
411
          cairo_bool_t              from_face,
412
          char         *filename,
413
          int         id,
414
          FT_Face       face)
415
2.12k
{
416
2.12k
    uintptr_t hash;
417
418
2.12k
    key->from_face = from_face;
419
2.12k
    key->filename = filename;
420
2.12k
    key->id = id;
421
2.12k
    key->face = face;
422
423
2.12k
    hash = _cairo_hash_string (filename);
424
    /* the constants are just arbitrary primes */
425
2.12k
    hash += ((uintptr_t) id) * 1607;
426
2.12k
    hash += ((uintptr_t) face) * 2137;
427
428
2.12k
    key->base.hash_entry.hash = hash;
429
2.12k
}
430
431
/**
432
 * _cairo_ft_unscaled_font_init:
433
 *
434
 * Initialize a #cairo_ft_unscaled_font_t.
435
 *
436
 * There are two basic flavors of #cairo_ft_unscaled_font_t, one
437
 * created from an FT_Face and the other created from a filename/id
438
 * pair. These two flavors are identified as from_face and !from_face.
439
 *
440
 * To initialize a from_face font, pass filename==%NULL, id=0 and the
441
 * desired face.
442
 *
443
 * To initialize a !from_face font, pass the filename/id as desired
444
 * and face==%NULL.
445
 *
446
 * Note that the code handles these two flavors in very distinct
447
 * ways. For example there is a hash_table mapping
448
 * filename/id->#cairo_unscaled_font_t in the !from_face case, but no
449
 * parallel in the from_face case, (where the calling code would have
450
 * to do its own mapping to ensure similar sharing).
451
 **/
452
static cairo_status_t
453
_cairo_ft_unscaled_font_init (cairo_ft_unscaled_font_t *unscaled,
454
            cairo_bool_t              from_face,
455
            const char         *filename,
456
            int     id,
457
            FT_Face     face)
458
5
{
459
5
    _cairo_unscaled_font_init (&unscaled->base,
460
5
             &cairo_ft_unscaled_font_backend);
461
462
5
    unscaled->variations = NULL;
463
464
5
    if (from_face) {
465
0
  FT_MM_Var *ft_mm_var;
466
0
  unscaled->from_face = TRUE;
467
0
  _cairo_ft_unscaled_font_init_key (unscaled, TRUE, NULL, id, face);
468
469
470
0
        unscaled->have_color = FT_HAS_COLOR (face) != 0;
471
0
        unscaled->have_color_set = TRUE;
472
0
  if (FT_Get_MM_Var (face, &ft_mm_var) == 0) {
473
0
      unscaled->variations = _cairo_calloc_ab (ft_mm_var->num_axis, sizeof (FT_Fixed));
474
0
      if (unscaled->variations)
475
0
    FT_Get_Var_Design_Coordinates (face, ft_mm_var->num_axis, unscaled->variations);
476
0
      FT_Done_MM_Var (face->glyph->library, ft_mm_var);
477
0
  }
478
5
    } else {
479
5
  char *filename_copy;
480
481
5
  unscaled->from_face = FALSE;
482
5
  unscaled->face = NULL;
483
484
5
  filename_copy = strdup (filename);
485
5
  if (unlikely (filename_copy == NULL))
486
0
      return _cairo_error (CAIRO_STATUS_NO_MEMORY);
487
488
5
  _cairo_ft_unscaled_font_init_key (unscaled, FALSE, filename_copy, id, NULL);
489
490
5
  unscaled->have_color_set = FALSE;
491
5
    }
492
493
5
    unscaled->have_scale = FALSE;
494
5
    CAIRO_MUTEX_INIT (unscaled->mutex);
495
5
    unscaled->lock_count = 0;
496
497
5
    unscaled->faces = NULL;
498
499
5
    return CAIRO_STATUS_SUCCESS;
500
5
}
501
502
/**
503
 * _cairo_ft_unscaled_font_fini:
504
 *
505
 * Free all data associated with a #cairo_ft_unscaled_font_t.
506
 *
507
 * CAUTION: The unscaled->face field must be %NULL before calling this
508
 * function. This is because the #cairo_ft_unscaled_font_t_map keeps a
509
 * count of these faces (font_map->num_open_faces) so it maintains the
510
 * unscaled->face field while it has its lock held. See
511
 * _font_map_release_face_lock_held().
512
 **/
513
static void
514
_cairo_ft_unscaled_font_fini (cairo_ft_unscaled_font_t *unscaled)
515
0
{
516
0
    assert (unscaled->face == NULL);
517
518
0
    free (unscaled->filename);
519
0
    unscaled->filename = NULL;
520
521
0
    free (unscaled->variations);
522
523
0
    CAIRO_MUTEX_FINI (unscaled->mutex);
524
0
}
525
526
static int
527
_cairo_ft_unscaled_font_keys_equal (const void *key_a,
528
            const void *key_b)
529
2.11k
{
530
2.11k
    const cairo_ft_unscaled_font_t *unscaled_a = key_a;
531
2.11k
    const cairo_ft_unscaled_font_t *unscaled_b = key_b;
532
533
2.11k
    if (unscaled_a->id == unscaled_b->id &&
534
2.11k
  unscaled_a->from_face == unscaled_b->from_face)
535
2.11k
     {
536
2.11k
        if (unscaled_a->from_face)
537
0
      return unscaled_a->face == unscaled_b->face;
538
539
2.11k
  if (unscaled_a->filename == NULL && unscaled_b->filename == NULL)
540
0
      return TRUE;
541
2.11k
  else if (unscaled_a->filename == NULL || unscaled_b->filename == NULL)
542
0
      return FALSE;
543
2.11k
  else
544
2.11k
      return (strcmp (unscaled_a->filename, unscaled_b->filename) == 0);
545
2.11k
    }
546
547
0
    return FALSE;
548
2.11k
}
549
550
/* Finds or creates a #cairo_ft_unscaled_font_t for the filename/id from
551
 * pattern.  Returns a new reference to the unscaled font.
552
 */
553
static cairo_status_t
554
_cairo_ft_unscaled_font_create_internal (cairo_bool_t from_face,
555
           char *filename,
556
           int id,
557
           FT_Face font_face,
558
           cairo_ft_unscaled_font_t **out)
559
2.11k
{
560
2.11k
    cairo_ft_unscaled_font_t key, *unscaled;
561
2.11k
    cairo_ft_unscaled_font_map_t *font_map;
562
2.11k
    cairo_status_t status;
563
564
2.11k
    font_map = _cairo_ft_unscaled_font_map_lock ();
565
2.11k
    if (unlikely (font_map == NULL))
566
0
  return _cairo_error (CAIRO_STATUS_NO_MEMORY);
567
568
2.11k
    _cairo_ft_unscaled_font_init_key (&key, from_face, filename, id, font_face);
569
570
    /* Return existing unscaled font if it exists in the hash table. */
571
2.11k
    unscaled = _cairo_hash_table_lookup (font_map->hash_table,
572
2.11k
           &key.base.hash_entry);
573
2.11k
    if (unscaled != NULL) {
574
2.11k
  _cairo_unscaled_font_reference (&unscaled->base);
575
2.11k
  goto DONE;
576
2.11k
    }
577
578
    /* Otherwise create it and insert into hash table. */
579
5
    unscaled = _cairo_calloc (sizeof (cairo_ft_unscaled_font_t));
580
5
    if (unlikely (unscaled == NULL)) {
581
0
  status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
582
0
  goto UNWIND_FONT_MAP_LOCK;
583
0
    }
584
585
5
    status = _cairo_ft_unscaled_font_init (unscaled, from_face, filename, id, font_face);
586
5
    if (unlikely (status))
587
0
  goto UNWIND_UNSCALED_MALLOC;
588
589
5
    assert (unscaled->base.hash_entry.hash == key.base.hash_entry.hash);
590
5
    status = _cairo_hash_table_insert (font_map->hash_table,
591
5
               &unscaled->base.hash_entry);
592
5
    if (unlikely (status))
593
0
  goto UNWIND_UNSCALED_FONT_INIT;
594
595
2.11k
DONE:
596
2.11k
    _cairo_ft_unscaled_font_map_unlock ();
597
2.11k
    *out = unscaled;
598
2.11k
    return CAIRO_STATUS_SUCCESS;
599
600
0
UNWIND_UNSCALED_FONT_INIT:
601
0
    _cairo_ft_unscaled_font_fini (unscaled);
602
0
UNWIND_UNSCALED_MALLOC:
603
0
    free (unscaled);
604
0
UNWIND_FONT_MAP_LOCK:
605
0
    _cairo_ft_unscaled_font_map_unlock ();
606
0
    return status;
607
0
}
608
609
610
#if CAIRO_HAS_FC_FONT
611
static cairo_status_t
612
_cairo_ft_unscaled_font_create_for_pattern (FcPattern *pattern,
613
              cairo_ft_unscaled_font_t **out)
614
2.11k
{
615
2.11k
    FT_Face font_face = NULL;
616
2.11k
    char *filename = NULL;
617
2.11k
    int id = 0;
618
2.11k
    FcResult ret;
619
620
2.11k
    ret = FcPatternGetFTFace (pattern, FC_FT_FACE, 0, &font_face);
621
2.11k
    if (ret == FcResultMatch)
622
0
  goto DONE;
623
2.11k
    if (ret == FcResultOutOfMemory)
624
0
  return _cairo_error (CAIRO_STATUS_NO_MEMORY);
625
626
2.11k
    ret = FcPatternGetString (pattern, FC_FILE, 0, (FcChar8 **) &filename);
627
2.11k
    if (ret == FcResultOutOfMemory)
628
0
  return _cairo_error (CAIRO_STATUS_NO_MEMORY);
629
2.11k
    if (ret == FcResultMatch) {
630
2.11k
       int nFD = -1;
631
2.11k
       int n;
632
2.11k
       if ((sscanf (filename, "/:FD:/%d%n", &nFD, &n) == 1 && filename[n] == '\0') ||
633
2.11k
      access (filename, R_OK) == 0) {
634
      /* If FC_INDEX is not set, we just use 0 */
635
2.11k
      ret = FcPatternGetInteger (pattern, FC_INDEX, 0, &id);
636
2.11k
      if (ret == FcResultOutOfMemory)
637
0
    return _cairo_error (CAIRO_STATUS_NO_MEMORY);
638
639
2.11k
      goto DONE;
640
2.11k
  } else
641
0
      return _cairo_error (CAIRO_STATUS_FILE_NOT_FOUND);
642
2.11k
    }
643
644
    /* The pattern contains neither a face nor a filename, resolve it later. */
645
0
    *out = NULL;
646
0
    return CAIRO_STATUS_SUCCESS;
647
648
2.11k
DONE:
649
2.11k
    return _cairo_ft_unscaled_font_create_internal (font_face != NULL,
650
2.11k
                filename, id, font_face,
651
2.11k
                out);
652
2.11k
}
653
#endif
654
655
static cairo_status_t
656
_cairo_ft_unscaled_font_create_from_face (FT_Face face,
657
            cairo_ft_unscaled_font_t **out)
658
0
{
659
0
    return _cairo_ft_unscaled_font_create_internal (TRUE, NULL, face->face_index, face, out);
660
0
}
661
662
static cairo_bool_t
663
_cairo_ft_unscaled_font_destroy (void *abstract_font)
664
0
{
665
0
    cairo_ft_unscaled_font_t *unscaled  = abstract_font;
666
0
    cairo_ft_unscaled_font_map_t *font_map;
667
668
0
    font_map = _cairo_ft_unscaled_font_map_lock ();
669
    /* All created objects must have been mapped in the font map. */
670
0
    assert (font_map != NULL);
671
672
0
    if (! _cairo_reference_count_dec_and_test (&unscaled->base.ref_count)) {
673
  /* somebody recreated the font whilst we waited for the lock */
674
0
  _cairo_ft_unscaled_font_map_unlock ();
675
0
  return FALSE;
676
0
    }
677
678
0
    _cairo_hash_table_remove (font_map->hash_table,
679
0
            &unscaled->base.hash_entry);
680
681
0
    if (unscaled->from_face) {
682
  /* See comments in _ft_font_face_destroy about the "zombie" state
683
   * for a _ft_font_face.
684
   */
685
0
  if (unscaled->faces && unscaled->faces->unscaled == NULL) {
686
0
      assert (unscaled->faces->next == NULL);
687
0
      cairo_font_face_destroy (&unscaled->faces->base);
688
0
  }
689
0
    } else {
690
0
  _font_map_release_face_lock_held (font_map, unscaled);
691
0
    }
692
0
    unscaled->face = NULL;
693
694
0
    _cairo_ft_unscaled_font_map_unlock ();
695
696
0
    _cairo_ft_unscaled_font_fini (unscaled);
697
0
    return TRUE;
698
0
}
699
700
static cairo_bool_t
701
_has_unlocked_face (const void *entry)
702
0
{
703
0
    const cairo_ft_unscaled_font_t *unscaled = entry;
704
705
0
    return (!unscaled->from_face && unscaled->lock_count == 0 && unscaled->face);
706
0
}
707
708
/* Ensures that an unscaled font has a face object. If we exceed
709
 * MAX_OPEN_FACES, try to close some.
710
 *
711
 * This differs from _cairo_ft_scaled_font_lock_face in that it doesn't
712
 * set the scale on the face, but just returns it at the last scale.
713
 */
714
static cairo_warn FT_Face
715
_cairo_ft_unscaled_font_lock_face (cairo_ft_unscaled_font_t *unscaled)
716
73.6k
{
717
73.6k
    cairo_ft_unscaled_font_map_t *font_map;
718
73.6k
    FT_Face face = NULL;
719
73.6k
    FT_Error error;
720
721
73.6k
    CAIRO_MUTEX_LOCK (unscaled->mutex);
722
73.6k
    unscaled->lock_count++;
723
724
73.6k
    if (unscaled->face)
725
73.5k
  return unscaled->face;
726
727
    /* If this unscaled font was created from an FT_Face then we just
728
     * returned it above. */
729
73.6k
    assert (!unscaled->from_face);
730
731
5
    font_map = _cairo_ft_unscaled_font_map_lock ();
732
5
    {
733
5
  assert (font_map != NULL);
734
735
5
  while (font_map->num_open_faces >= MAX_OPEN_FACES)
736
0
  {
737
0
      cairo_ft_unscaled_font_t *entry;
738
739
0
      entry = _cairo_hash_table_random_entry (font_map->hash_table,
740
0
                _has_unlocked_face);
741
0
      if (entry == NULL)
742
0
    break;
743
744
0
      _font_map_release_face_lock_held (font_map, entry);
745
0
  }
746
5
    }
747
5
    _cairo_ft_unscaled_font_map_unlock ();
748
749
5
    error = FT_New_Face (font_map->ft_library,
750
5
       unscaled->filename,
751
5
       unscaled->id,
752
5
       &face);
753
5
    if (error)
754
0
    {
755
0
  unscaled->lock_count--;
756
0
  CAIRO_MUTEX_UNLOCK (unscaled->mutex);
757
0
  _cairo_error_throw (_cairo_ft_to_cairo_error (error));
758
0
  return NULL;
759
0
    }
760
761
5
    unscaled->face = face;
762
763
5
    unscaled->have_color = FT_HAS_COLOR (face) != 0;
764
5
    unscaled->have_color_set = TRUE;
765
766
5
    font_map->num_open_faces++;
767
768
5
    return face;
769
5
}
770
771
772
/* Unlock unscaled font locked with _cairo_ft_unscaled_font_lock_face
773
 */
774
static void
775
_cairo_ft_unscaled_font_unlock_face (cairo_ft_unscaled_font_t *unscaled)
776
73.6k
{
777
73.6k
    assert (unscaled->lock_count > 0);
778
779
73.6k
    unscaled->lock_count--;
780
781
73.6k
    CAIRO_MUTEX_UNLOCK (unscaled->mutex);
782
73.6k
}
783
784
785
static cairo_status_t
786
_compute_transform (cairo_ft_font_transform_t *sf,
787
        cairo_matrix_t      *scale,
788
        cairo_ft_unscaled_font_t *unscaled)
789
112k
{
790
112k
    cairo_status_t status;
791
112k
    double x_scale, y_scale;
792
112k
    cairo_matrix_t normalized = *scale;
793
794
    /* The font matrix has x and y "scale" components which we extract and
795
     * use as character scale values. These influence the way freetype
796
     * chooses hints, as well as selecting different bitmaps in
797
     * hand-rendered fonts. We also copy the normalized matrix to
798
     * freetype's transformation.
799
     */
800
801
112k
    status = _cairo_matrix_compute_basis_scale_factors (scale,
802
112k
              &x_scale, &y_scale,
803
112k
              1);
804
112k
    if (unlikely (status))
805
0
  return status;
806
807
    /* FreeType docs say this about x_scale and y_scale:
808
     * "A character width or height smaller than 1pt is set to 1pt;"
809
     * So, we cap them from below at 1.0 and let the FT transform
810
     * take care of sub-1.0 scaling. */
811
112k
    if (x_scale < 1.0)
812
87
      x_scale = 1.0;
813
112k
    if (y_scale < 1.0)
814
790
      y_scale = 1.0;
815
816
112k
    if (unscaled && (unscaled->face->face_flags & FT_FACE_FLAG_SCALABLE) == 0) {
817
0
  double min_distance = DBL_MAX;
818
0
  cairo_bool_t magnify = TRUE;
819
0
  int i;
820
0
  double best_x_size = 0;
821
0
  double best_y_size = 0;
822
823
0
  for (i = 0; i < unscaled->face->num_fixed_sizes; i++) {
824
0
      double x_size = unscaled->face->available_sizes[i].x_ppem / 64.;
825
0
      double y_size = unscaled->face->available_sizes[i].y_ppem / 64.;
826
0
      double distance = y_size - y_scale;
827
828
      /*
829
       * distance is positive if current strike is larger than desired
830
       * size, and negative if smaller.
831
       *
832
       * We like to prefer down-scaling to upscaling.
833
       */
834
835
0
      if ((magnify && distance >= 0) || fabs (distance) <= min_distance) {
836
0
    magnify = distance < 0;
837
0
    min_distance = fabs (distance);
838
0
    best_x_size = x_size;
839
0
    best_y_size = y_size;
840
0
      }
841
0
  }
842
843
0
  x_scale = best_x_size;
844
0
  y_scale = best_y_size;
845
0
    }
846
847
112k
    sf->x_scale = x_scale;
848
112k
    sf->y_scale = y_scale;
849
850
112k
    cairo_matrix_scale (&normalized, 1.0 / x_scale, 1.0 / y_scale);
851
852
112k
    _cairo_matrix_get_affine (&normalized,
853
112k
            &sf->shape[0][0], &sf->shape[0][1],
854
112k
            &sf->shape[1][0], &sf->shape[1][1],
855
112k
            NULL, NULL);
856
857
112k
    return CAIRO_STATUS_SUCCESS;
858
112k
}
859
860
/* Temporarily scales an unscaled font to the give scale. We catch
861
 * scaling to the same size, since changing a FT_Face is expensive.
862
 */
863
static cairo_status_t
864
_cairo_ft_unscaled_font_set_scale (cairo_ft_unscaled_font_t *unscaled,
865
           cairo_matrix_t       *scale)
866
161k
{
867
161k
    cairo_status_t status;
868
161k
    cairo_ft_font_transform_t sf;
869
161k
    FT_Matrix mat;
870
161k
    FT_Error error;
871
872
161k
    assert (unscaled->face != NULL);
873
874
161k
    if (unscaled->have_scale &&
875
161k
  scale->xx == unscaled->current_scale.xx &&
876
48.7k
  scale->yx == unscaled->current_scale.yx &&
877
48.7k
  scale->xy == unscaled->current_scale.xy &&
878
48.7k
  scale->yy == unscaled->current_scale.yy)
879
48.7k
  return CAIRO_STATUS_SUCCESS;
880
881
112k
    unscaled->have_scale = TRUE;
882
112k
    unscaled->current_scale = *scale;
883
884
112k
    status = _compute_transform (&sf, scale, unscaled);
885
112k
    if (unlikely (status))
886
0
  return status;
887
888
112k
    unscaled->x_scale = sf.x_scale;
889
112k
    unscaled->y_scale = sf.y_scale;
890
891
112k
    mat.xx = DOUBLE_TO_16_16(sf.shape[0][0]);
892
112k
    mat.yx = - DOUBLE_TO_16_16(sf.shape[0][1]);
893
112k
    mat.xy = - DOUBLE_TO_16_16(sf.shape[1][0]);
894
112k
    mat.yy = DOUBLE_TO_16_16(sf.shape[1][1]);
895
896
112k
    unscaled->have_shape = (mat.xx != 0x10000 ||
897
91.4k
          mat.yx != 0x00000 ||
898
91.4k
          mat.xy != 0x00000 ||
899
91.4k
          mat.yy != 0x10000);
900
901
112k
    unscaled->Current_Shape = mat;
902
112k
    cairo_matrix_init (&unscaled->current_shape,
903
112k
           sf.shape[0][0], sf.shape[0][1],
904
112k
           sf.shape[1][0], sf.shape[1][1],
905
112k
           0.0, 0.0);
906
907
112k
    FT_Set_Transform(unscaled->face, &mat, NULL);
908
909
112k
    error = FT_Set_Char_Size (unscaled->face,
910
112k
            sf.x_scale * 64.0 + .5,
911
112k
            sf.y_scale * 64.0 + .5,
912
112k
            0, 0);
913
112k
    if (error)
914
0
      return _cairo_error (_cairo_ft_to_cairo_error (error));
915
916
112k
    return CAIRO_STATUS_SUCCESS;
917
112k
}
918
919
/* we sometimes need to convert the glyph bitmap in a FT_GlyphSlot
920
 * into a different format. For example, we want to convert a
921
 * FT_PIXEL_MODE_LCD or FT_PIXEL_MODE_LCD_V bitmap into a 32-bit
922
 * ARGB or ABGR bitmap.
923
 *
924
 * this function prepares a target descriptor for this operation.
925
 *
926
 * input :: target bitmap descriptor. The function will set its
927
 *          'width', 'rows' and 'pitch' fields, and only these
928
 *
929
 * slot  :: the glyph slot containing the source bitmap. this
930
 *          function assumes that slot->format == FT_GLYPH_FORMAT_BITMAP
931
 *
932
 * mode  :: the requested final rendering mode. supported values are
933
 *          MONO, NORMAL (i.e. gray), LCD and LCD_V
934
 *
935
 * the function returns the size in bytes of the corresponding buffer,
936
 * it's up to the caller to allocate the corresponding memory block
937
 * before calling _fill_xrender_bitmap
938
 *
939
 * it also returns -1 in case of error (e.g. incompatible arguments,
940
 * like trying to convert a gray bitmap into a monochrome one)
941
 */
942
static int
943
_compute_xrender_bitmap_size(FT_Bitmap      *target,
944
           FT_GlyphSlot    slot,
945
           FT_Render_Mode  mode)
946
43.4k
{
947
43.4k
    FT_Bitmap *ftbit;
948
43.4k
    int width, height, pitch;
949
950
43.4k
    if (slot->format != FT_GLYPH_FORMAT_BITMAP)
951
0
  return -1;
952
953
    /* compute the size of the final bitmap */
954
43.4k
    ftbit = &slot->bitmap;
955
956
43.4k
    width = ftbit->width;
957
43.4k
    height = ftbit->rows;
958
43.4k
    pitch = (width + 3) & ~3;
959
960
43.4k
    switch (ftbit->pixel_mode) {
961
0
    case FT_PIXEL_MODE_MONO:
962
0
  if (mode == FT_RENDER_MODE_MONO) {
963
0
      pitch = (((width + 31) & ~31) >> 3);
964
0
      break;
965
0
  }
966
  /* fall-through */
967
968
43.4k
    case FT_PIXEL_MODE_GRAY:
969
43.4k
  if (mode == FT_RENDER_MODE_LCD ||
970
43.4k
      mode == FT_RENDER_MODE_LCD_V)
971
0
  {
972
      /* each pixel is replicated into a 32-bit ARGB value */
973
0
      pitch = width * 4;
974
0
  }
975
43.4k
  break;
976
977
0
    case FT_PIXEL_MODE_LCD:
978
0
  if (mode != FT_RENDER_MODE_LCD)
979
0
      return -1;
980
981
  /* horz pixel triplets are packed into 32-bit ARGB values */
982
0
  width /= 3;
983
0
  pitch = width * 4;
984
0
  break;
985
986
0
    case FT_PIXEL_MODE_LCD_V:
987
0
  if (mode != FT_RENDER_MODE_LCD_V)
988
0
      return -1;
989
990
  /* vert pixel triplets are packed into 32-bit ARGB values */
991
0
  height /= 3;
992
0
  pitch = width * 4;
993
0
  break;
994
995
0
    case FT_PIXEL_MODE_BGRA:
996
  /* each pixel is replicated into a 32-bit ARGB value */
997
0
  pitch = width * 4;
998
0
  break;
999
1000
0
    default:  /* unsupported source format */
1001
0
  return -1;
1002
43.4k
    }
1003
1004
43.4k
    target->width = width;
1005
43.4k
    target->rows = height;
1006
43.4k
    target->pitch = pitch;
1007
43.4k
    target->buffer = NULL;
1008
1009
43.4k
    return pitch * height;
1010
43.4k
}
1011
1012
/* this functions converts the glyph bitmap found in a FT_GlyphSlot
1013
 * into a different format (see _compute_xrender_bitmap_size)
1014
 *
1015
 * you should call this function after _compute_xrender_bitmap_size
1016
 *
1017
 * target :: target bitmap descriptor. Note that its 'buffer' pointer
1018
 *           must point to memory allocated by the caller
1019
 *
1020
 * slot   :: the glyph slot containing the source bitmap
1021
 *
1022
 * mode   :: the requested final rendering mode
1023
 *
1024
 * bgr    :: boolean, set if BGR or VBGR pixel ordering is needed
1025
 */
1026
static void
1027
_fill_xrender_bitmap(FT_Bitmap      *target,
1028
         FT_GlyphSlot    slot,
1029
         FT_Render_Mode  mode,
1030
         int             bgr)
1031
43.4k
{
1032
43.4k
    FT_Bitmap *ftbit = &slot->bitmap;
1033
43.4k
    unsigned char *srcLine = ftbit->buffer;
1034
43.4k
    unsigned char *dstLine = target->buffer;
1035
43.4k
    int src_pitch = ftbit->pitch;
1036
43.4k
    int width = target->width;
1037
43.4k
    int height = target->rows;
1038
43.4k
    int pitch = target->pitch;
1039
43.4k
    int subpixel;
1040
43.4k
    int h;
1041
1042
43.4k
    subpixel = (mode == FT_RENDER_MODE_LCD ||
1043
43.4k
    mode == FT_RENDER_MODE_LCD_V);
1044
1045
43.4k
    if (src_pitch < 0)
1046
0
  srcLine -= src_pitch * (ftbit->rows - 1);
1047
1048
43.4k
    target->pixel_mode = ftbit->pixel_mode;
1049
1050
43.4k
    switch (ftbit->pixel_mode) {
1051
0
    case FT_PIXEL_MODE_MONO:
1052
0
  if (subpixel) {
1053
      /* convert mono to ARGB32 values */
1054
1055
0
      for (h = height; h > 0; h--, srcLine += src_pitch, dstLine += pitch) {
1056
0
    int x;
1057
1058
0
    for (x = 0; x < width; x++) {
1059
0
        if (srcLine[(x >> 3)] & (0x80 >> (x & 7)))
1060
0
      ((unsigned int *) dstLine)[x] = 0xffffffffU;
1061
0
    }
1062
0
      }
1063
0
      target->pixel_mode = FT_PIXEL_MODE_LCD;
1064
1065
0
  } else if (mode == FT_RENDER_MODE_NORMAL) {
1066
      /* convert mono to 8-bit gray */
1067
1068
0
      for (h = height; h > 0; h--, srcLine += src_pitch, dstLine += pitch) {
1069
0
    int x;
1070
1071
0
    for (x = 0; x < width; x++) {
1072
0
        if (srcLine[(x >> 3)] & (0x80 >> (x & 7)))
1073
0
      dstLine[x] = 0xff;
1074
0
    }
1075
0
      }
1076
0
      target->pixel_mode = FT_PIXEL_MODE_GRAY;
1077
1078
0
  } else {
1079
      /* copy mono to mono */
1080
1081
0
      int  bytes = (width + 7) >> 3;
1082
1083
0
      for (h = height; h > 0; h--, srcLine += src_pitch, dstLine += pitch)
1084
0
    memcpy (dstLine, srcLine, bytes);
1085
0
  }
1086
0
  break;
1087
1088
43.4k
    case FT_PIXEL_MODE_GRAY:
1089
43.4k
  if (subpixel) {
1090
      /* convert gray to ARGB32 values */
1091
1092
0
      for (h = height; h > 0; h--, srcLine += src_pitch, dstLine += pitch) {
1093
0
    int x;
1094
0
    unsigned int *dst = (unsigned int *) dstLine;
1095
1096
0
    for (x = 0; x < width; x++) {
1097
0
        unsigned int pix = srcLine[x];
1098
1099
0
        pix |= (pix << 8);
1100
0
        pix |= (pix << 16);
1101
1102
0
        dst[x] = pix;
1103
0
    }
1104
0
      }
1105
0
      target->pixel_mode = FT_PIXEL_MODE_LCD;
1106
43.4k
        } else {
1107
            /* copy gray into gray */
1108
1109
4.74M
            for (h = height; h > 0; h--, srcLine += src_pitch, dstLine += pitch)
1110
4.69M
                memcpy (dstLine, srcLine, width);
1111
43.4k
        }
1112
43.4k
        break;
1113
1114
0
    case FT_PIXEL_MODE_LCD:
1115
0
  if (!bgr) {
1116
      /* convert horizontal RGB into ARGB32 */
1117
1118
0
      for (h = height; h > 0; h--, srcLine += src_pitch, dstLine += pitch) {
1119
0
    int x;
1120
0
    unsigned char *src = srcLine;
1121
0
    unsigned int *dst = (unsigned int *) dstLine;
1122
1123
0
    for (x = 0; x < width; x++, src += 3) {
1124
0
        unsigned int  pix;
1125
1126
0
        pix = ((unsigned int)src[0] << 16) |
1127
0
        ((unsigned int)src[1] <<  8) |
1128
0
        ((unsigned int)src[2]      ) |
1129
0
        ((unsigned int)src[1] << 24) ;
1130
1131
0
        dst[x] = pix;
1132
0
    }
1133
0
      }
1134
0
  } else {
1135
      /* convert horizontal BGR into ARGB32 */
1136
1137
0
      for (h = height; h > 0; h--, srcLine += src_pitch, dstLine += pitch) {
1138
1139
0
    int x;
1140
0
    unsigned char *src = srcLine;
1141
0
    unsigned int *dst = (unsigned int *) dstLine;
1142
1143
0
    for (x = 0; x < width; x++, src += 3) {
1144
0
        unsigned int  pix;
1145
1146
0
        pix = ((unsigned int)src[2] << 16) |
1147
0
        ((unsigned int)src[1] <<  8) |
1148
0
        ((unsigned int)src[0]      ) |
1149
0
        ((unsigned int)src[1] << 24) ;
1150
1151
0
        dst[x] = pix;
1152
0
    }
1153
0
      }
1154
0
  }
1155
0
  break;
1156
1157
0
    case FT_PIXEL_MODE_LCD_V:
1158
  /* convert vertical RGB into ARGB32 */
1159
0
  if (!bgr) {
1160
1161
0
      for (h = height; h > 0; h--, srcLine += 3 * src_pitch, dstLine += pitch) {
1162
0
    int x;
1163
0
    unsigned char* src = srcLine;
1164
0
    unsigned int*  dst = (unsigned int *) dstLine;
1165
1166
0
    for (x = 0; x < width; x++, src += 1) {
1167
0
        unsigned int pix;
1168
0
        pix = ((unsigned int)src[0]           << 16) |
1169
0
        ((unsigned int)src[src_pitch]   <<  8) |
1170
0
        ((unsigned int)src[src_pitch*2]      ) |
1171
0
        ((unsigned int)src[src_pitch]   << 24) ;
1172
0
        dst[x] = pix;
1173
0
    }
1174
0
      }
1175
0
  } else {
1176
1177
0
      for (h = height; h > 0; h--, srcLine += 3*src_pitch, dstLine += pitch) {
1178
0
    int x;
1179
0
    unsigned char *src = srcLine;
1180
0
    unsigned int *dst = (unsigned int *) dstLine;
1181
1182
0
    for (x = 0; x < width; x++, src += 1) {
1183
0
        unsigned int  pix;
1184
1185
0
        pix = ((unsigned int)src[src_pitch * 2] << 16) |
1186
0
        ((unsigned int)src[src_pitch]     <<  8) |
1187
0
        ((unsigned int)src[0]                  ) |
1188
0
        ((unsigned int)src[src_pitch]     << 24) ;
1189
1190
0
        dst[x] = pix;
1191
0
    }
1192
0
      }
1193
0
  }
1194
0
  break;
1195
1196
0
    case FT_PIXEL_MODE_BGRA:
1197
0
  for (h = height; h > 0; h--, srcLine += src_pitch, dstLine += pitch)
1198
0
      memcpy (dstLine, srcLine, (size_t)width * 4);
1199
0
  break;
1200
1201
0
    default:
1202
0
  assert (0);
1203
43.4k
    }
1204
43.4k
}
1205
1206
1207
/* Fills in val->image with an image surface created from @bitmap
1208
 */
1209
static cairo_status_t
1210
_get_bitmap_surface (FT_Bitmap         *bitmap,
1211
         FT_Library         library,
1212
         cairo_bool_t       own_buffer,
1213
         cairo_font_options_t    *font_options,
1214
         cairo_image_surface_t  **surface)
1215
43.4k
{
1216
43.4k
    unsigned int width, height;
1217
43.4k
    unsigned char *data;
1218
43.4k
    int format = CAIRO_FORMAT_A8;
1219
43.4k
    int stride;
1220
43.4k
    cairo_image_surface_t *image;
1221
43.4k
    cairo_bool_t component_alpha = FALSE;
1222
1223
43.4k
    width = bitmap->width;
1224
43.4k
    height = bitmap->rows;
1225
1226
43.4k
    if (width == 0 || height == 0) {
1227
0
  *surface = (cairo_image_surface_t *)
1228
0
      cairo_image_surface_create_for_data (NULL, format, 0, 0, 0);
1229
0
  return (*surface)->base.status;
1230
0
    }
1231
1232
43.4k
    switch (bitmap->pixel_mode) {
1233
0
    case FT_PIXEL_MODE_MONO:
1234
0
  stride = (((width + 31) & ~31) >> 3);
1235
0
  if (own_buffer) {
1236
0
      data = bitmap->buffer;
1237
0
      assert (stride == bitmap->pitch);
1238
0
  } else {
1239
0
      data = _cairo_malloc_ab (height, stride);
1240
0
      if (!data)
1241
0
    return _cairo_error (CAIRO_STATUS_NO_MEMORY);
1242
1243
0
      if (stride == bitmap->pitch) {
1244
0
    memcpy (data, bitmap->buffer, (size_t)stride * height);
1245
0
      } else {
1246
0
    int i;
1247
0
    unsigned char *source, *dest;
1248
1249
0
    source = bitmap->buffer;
1250
0
    dest = data;
1251
0
    for (i = height; i; i--) {
1252
0
        memcpy (dest, source, bitmap->pitch);
1253
0
        memset (dest + bitmap->pitch, '\0', stride - bitmap->pitch);
1254
1255
0
        source += bitmap->pitch;
1256
0
        dest += stride;
1257
0
    }
1258
0
      }
1259
0
  }
1260
1261
0
#ifndef WORDS_BIGENDIAN
1262
0
  {
1263
0
      uint8_t *d = data;
1264
0
      int count = stride * height;
1265
1266
0
      while (count--) {
1267
0
    *d = CAIRO_BITSWAP8 (*d);
1268
0
    d++;
1269
0
      }
1270
0
  }
1271
0
#endif
1272
0
  format = CAIRO_FORMAT_A1;
1273
0
  break;
1274
1275
0
    case FT_PIXEL_MODE_LCD:
1276
0
    case FT_PIXEL_MODE_LCD_V:
1277
43.4k
    case FT_PIXEL_MODE_GRAY:
1278
43.4k
  if (font_options->antialias != CAIRO_ANTIALIAS_SUBPIXEL ||
1279
0
      bitmap->pixel_mode == FT_PIXEL_MODE_GRAY)
1280
43.4k
  {
1281
43.4k
      stride = bitmap->pitch;
1282
1283
      /* We don't support stride not multiple of 4. */
1284
43.4k
      if (stride & 3)
1285
0
      {
1286
0
    assert (!own_buffer);
1287
0
    goto convert;
1288
0
      }
1289
1290
43.4k
      if (own_buffer) {
1291
43.4k
    data = bitmap->buffer;
1292
43.4k
      } else {
1293
0
    data = _cairo_malloc_ab (height, stride);
1294
0
    if (!data)
1295
0
        return _cairo_error (CAIRO_STATUS_NO_MEMORY);
1296
1297
0
    memcpy (data, bitmap->buffer, (size_t)stride * height);
1298
0
      }
1299
1300
43.4k
      format = CAIRO_FORMAT_A8;
1301
43.4k
  } else {
1302
0
      data = bitmap->buffer;
1303
0
      stride = bitmap->pitch;
1304
0
      format = CAIRO_FORMAT_ARGB32;
1305
0
      component_alpha = TRUE;
1306
0
  }
1307
43.4k
  break;
1308
43.4k
    case FT_PIXEL_MODE_BGRA:
1309
0
  stride = width * 4;
1310
0
  if (own_buffer) {
1311
0
      data = bitmap->buffer;
1312
0
  } else {
1313
0
      data = _cairo_malloc_ab (height, stride);
1314
0
      if (!data)
1315
0
    return _cairo_error (CAIRO_STATUS_NO_MEMORY);
1316
1317
0
      memcpy (data, bitmap->buffer, (size_t)stride * height);
1318
0
  }
1319
1320
0
  if (!_cairo_is_little_endian ())
1321
0
  {
1322
      /* Byteswap. */
1323
0
      unsigned int i, count = height * width;
1324
0
      uint32_t *p = (uint32_t *) data;
1325
0
      for (i = 0; i < count; i++)
1326
0
    p[i] = bswap_32 (p[i]);
1327
0
  }
1328
0
  format = CAIRO_FORMAT_ARGB32;
1329
0
  break;
1330
0
    case FT_PIXEL_MODE_GRAY2:
1331
0
    case FT_PIXEL_MODE_GRAY4:
1332
0
    convert:
1333
0
  if (!own_buffer && library)
1334
0
  {
1335
      /* This is pretty much the only case that we can get in here. */
1336
      /* Convert to 8bit grayscale. */
1337
1338
0
      FT_Bitmap  tmp;
1339
0
      FT_Int     align;
1340
0
      FT_Error   error;
1341
1342
0
      format = CAIRO_FORMAT_A8;
1343
1344
0
      align = cairo_format_stride_for_width (format, bitmap->width);
1345
1346
0
      FT_Bitmap_New( &tmp );
1347
1348
0
      error = FT_Bitmap_Convert( library, bitmap, &tmp, align );
1349
0
      if (error)
1350
0
    return _cairo_error (_cairo_ft_to_cairo_error (error));
1351
1352
0
      FT_Bitmap_Done( library, bitmap );
1353
0
      *bitmap = tmp;
1354
1355
0
      stride = bitmap->pitch;
1356
0
      data = _cairo_malloc_ab (height, stride);
1357
0
      if (!data)
1358
0
    return _cairo_error (CAIRO_STATUS_NO_MEMORY);
1359
1360
0
      if (bitmap->num_grays != 256)
1361
0
      {
1362
0
        unsigned int x, y;
1363
0
        unsigned int mul = 255 / (bitmap->num_grays - 1);
1364
0
        FT_Byte *p = bitmap->buffer;
1365
0
        for (y = 0; y < height; y++) {
1366
0
          for (x = 0; x < width; x++)
1367
0
      p[x] *= mul;
1368
0
    p += bitmap->pitch;
1369
0
        }
1370
0
      }
1371
1372
0
      memcpy (data, bitmap->buffer, (size_t)stride * height);
1373
0
      break;
1374
0
  }
1375
  /* fall through */
1376
  /* These could be triggered by very rare types of TrueType fonts */
1377
0
    default:
1378
0
  if (own_buffer)
1379
0
      free (bitmap->buffer);
1380
0
  return _cairo_error (CAIRO_STATUS_INVALID_FORMAT);
1381
43.4k
    }
1382
1383
    /* XXX */
1384
43.4k
    *surface = image = (cairo_image_surface_t *)
1385
43.4k
  cairo_image_surface_create_for_data (data,
1386
43.4k
               format,
1387
43.4k
               width, height, stride);
1388
43.4k
    if (image->base.status) {
1389
0
  free (data);
1390
0
  return (*surface)->base.status;
1391
0
    }
1392
1393
43.4k
    if (component_alpha)
1394
0
  pixman_image_set_component_alpha (image->pixman_image, TRUE);
1395
1396
43.4k
    _cairo_image_surface_assume_ownership_of_data (image);
1397
1398
43.4k
    _cairo_debug_check_image_surface_is_defined (&image->base);
1399
1400
43.4k
    return CAIRO_STATUS_SUCCESS;
1401
43.4k
}
1402
1403
/* Converts an outline FT_GlyphSlot into an image
1404
 *
1405
 * This could go through _render_glyph_bitmap as well, letting
1406
 * FreeType convert the outline to a bitmap, but doing it ourselves
1407
 * has two minor advantages: first, we save a copy of the bitmap
1408
 * buffer: we can directly use the buffer that FreeType renders
1409
 * into.
1410
 *
1411
 * Second, it may help when we add support for subpixel
1412
 * rendering: the Xft code does it this way. (Keith thinks that
1413
 * it may also be possible to get the subpixel rendering with
1414
 * FT_Render_Glyph: something worth looking into in more detail
1415
 * when we add subpixel support. If so, we may want to eliminate
1416
 * this version of the code path entirely.
1417
 */
1418
static cairo_status_t
1419
_render_glyph_outline (FT_Face                    face,
1420
           cairo_font_options_t  *font_options,
1421
           cairo_image_surface_t  **surface)
1422
44.5k
{
1423
44.5k
    cairo_subpixel_order_t rgba = CAIRO_SUBPIXEL_ORDER_DEFAULT;
1424
44.5k
    int lcd_filter = FT_LCD_FILTER_DEFAULT;
1425
44.5k
    FT_GlyphSlot glyphslot = face->glyph;
1426
44.5k
    FT_Outline *outline = &glyphslot->outline;
1427
44.5k
    FT_Bitmap bitmap;
1428
44.5k
    FT_BBox cbox;
1429
44.5k
    unsigned int width, height;
1430
44.5k
    cairo_status_t status;
1431
44.5k
    FT_Error error;
1432
44.5k
    FT_Library library = glyphslot->library;
1433
44.5k
    FT_Render_Mode render_mode = FT_RENDER_MODE_NORMAL;
1434
1435
44.5k
    switch (font_options->antialias) {
1436
0
    case CAIRO_ANTIALIAS_NONE:
1437
0
  render_mode = FT_RENDER_MODE_MONO;
1438
0
  break;
1439
1440
0
    case CAIRO_ANTIALIAS_SUBPIXEL:
1441
0
    case CAIRO_ANTIALIAS_BEST:
1442
0
  switch (font_options->subpixel_order) {
1443
0
      case CAIRO_SUBPIXEL_ORDER_DEFAULT:
1444
0
      case CAIRO_SUBPIXEL_ORDER_RGB:
1445
0
      case CAIRO_SUBPIXEL_ORDER_BGR:
1446
0
    render_mode = FT_RENDER_MODE_LCD;
1447
0
    break;
1448
1449
0
      case CAIRO_SUBPIXEL_ORDER_VRGB:
1450
0
      case CAIRO_SUBPIXEL_ORDER_VBGR:
1451
0
    render_mode = FT_RENDER_MODE_LCD_V;
1452
0
    break;
1453
0
  }
1454
1455
0
  switch (font_options->lcd_filter) {
1456
0
  case CAIRO_LCD_FILTER_NONE:
1457
0
      lcd_filter = FT_LCD_FILTER_NONE;
1458
0
      break;
1459
0
  case CAIRO_LCD_FILTER_INTRA_PIXEL:
1460
0
      lcd_filter = FT_LCD_FILTER_LEGACY;
1461
0
      break;
1462
0
  case CAIRO_LCD_FILTER_FIR3:
1463
0
      lcd_filter = FT_LCD_FILTER_LIGHT;
1464
0
      break;
1465
0
  case CAIRO_LCD_FILTER_DEFAULT:
1466
0
  case CAIRO_LCD_FILTER_FIR5:
1467
0
      lcd_filter = FT_LCD_FILTER_DEFAULT;
1468
0
      break;
1469
0
  }
1470
1471
0
  break;
1472
1473
0
    case CAIRO_ANTIALIAS_DEFAULT:
1474
44.5k
    case CAIRO_ANTIALIAS_GRAY:
1475
44.5k
    case CAIRO_ANTIALIAS_GOOD:
1476
44.5k
    case CAIRO_ANTIALIAS_FAST:
1477
44.5k
  render_mode = FT_RENDER_MODE_NORMAL;
1478
44.5k
    }
1479
1480
44.5k
    FT_Outline_Get_CBox (outline, &cbox);
1481
1482
44.5k
    cbox.xMin &= -64;
1483
44.5k
    cbox.yMin &= -64;
1484
44.5k
    cbox.xMax = (cbox.xMax + 63) & -64;
1485
44.5k
    cbox.yMax = (cbox.yMax + 63) & -64;
1486
1487
44.5k
    width = (unsigned int) ((cbox.xMax - cbox.xMin) >> 6);
1488
44.5k
    height = (unsigned int) ((cbox.yMax - cbox.yMin) >> 6);
1489
1490
44.5k
    if (width * height == 0) {
1491
1.10k
  cairo_format_t format;
1492
  /* Looks like fb handles zero-sized images just fine */
1493
1.10k
  switch (render_mode) {
1494
0
  case FT_RENDER_MODE_MONO:
1495
0
      format = CAIRO_FORMAT_A1;
1496
0
      break;
1497
0
  case FT_RENDER_MODE_LCD:
1498
0
  case FT_RENDER_MODE_LCD_V:
1499
0
      format= CAIRO_FORMAT_ARGB32;
1500
0
      break;
1501
0
  case FT_RENDER_MODE_LIGHT:
1502
1.10k
  case FT_RENDER_MODE_NORMAL:
1503
1.10k
  case FT_RENDER_MODE_MAX:
1504
1.10k
#if HAVE_FT_RENDER_MODE_SDF
1505
1.10k
  case FT_RENDER_MODE_SDF:
1506
1.10k
#endif
1507
1.10k
  default:
1508
1.10k
      format = CAIRO_FORMAT_A8;
1509
1.10k
      break;
1510
1.10k
  }
1511
1512
1.10k
  (*surface) = (cairo_image_surface_t *)
1513
1.10k
      cairo_image_surface_create_for_data (NULL, format, 0, 0, 0);
1514
1.10k
  pixman_image_set_component_alpha ((*surface)->pixman_image, TRUE);
1515
1.10k
  if ((*surface)->base.status)
1516
0
      return (*surface)->base.status;
1517
43.4k
    } else {
1518
1519
43.4k
  int bitmap_size;
1520
1521
43.4k
  switch (render_mode) {
1522
0
  case FT_RENDER_MODE_LCD:
1523
0
      if (font_options->subpixel_order == CAIRO_SUBPIXEL_ORDER_BGR)
1524
0
    rgba = CAIRO_SUBPIXEL_ORDER_BGR;
1525
0
      else
1526
0
    rgba = CAIRO_SUBPIXEL_ORDER_RGB;
1527
0
      break;
1528
1529
0
  case FT_RENDER_MODE_LCD_V:
1530
0
      if (font_options->subpixel_order == CAIRO_SUBPIXEL_ORDER_VBGR)
1531
0
    rgba = CAIRO_SUBPIXEL_ORDER_VBGR;
1532
0
      else
1533
0
    rgba = CAIRO_SUBPIXEL_ORDER_VRGB;
1534
0
      break;
1535
1536
0
  case FT_RENDER_MODE_MONO:
1537
0
  case FT_RENDER_MODE_LIGHT:
1538
43.4k
  case FT_RENDER_MODE_NORMAL:
1539
43.4k
  case FT_RENDER_MODE_MAX:
1540
43.4k
#if HAVE_FT_RENDER_MODE_SDF
1541
43.4k
  case FT_RENDER_MODE_SDF:
1542
43.4k
#endif
1543
43.4k
  default:
1544
43.4k
      break;
1545
43.4k
  }
1546
1547
43.4k
  FT_Library_SetLcdFilter (library, lcd_filter);
1548
43.4k
  error = FT_Render_Glyph (face->glyph, render_mode);
1549
1550
43.4k
  FT_Library_SetLcdFilter (library, FT_LCD_FILTER_NONE);
1551
43.4k
  if (error)
1552
0
      return _cairo_error (_cairo_ft_to_cairo_error (error));
1553
1554
43.4k
  bitmap_size = _compute_xrender_bitmap_size (&bitmap,
1555
43.4k
                face->glyph,
1556
43.4k
                render_mode);
1557
43.4k
  if (bitmap_size < 0)
1558
0
      return _cairo_error (CAIRO_STATUS_INVALID_FORMAT);
1559
1560
43.4k
  bitmap.buffer = _cairo_calloc (bitmap_size);
1561
43.4k
  if (bitmap.buffer == NULL)
1562
0
    return _cairo_error (CAIRO_STATUS_NO_MEMORY);
1563
1564
43.4k
  _fill_xrender_bitmap (&bitmap, face->glyph, render_mode,
1565
43.4k
            (rgba == CAIRO_SUBPIXEL_ORDER_BGR || rgba == CAIRO_SUBPIXEL_ORDER_VBGR));
1566
1567
  /* Note:
1568
   * _get_bitmap_surface will free bitmap.buffer if there is an error
1569
   */
1570
43.4k
  status = _get_bitmap_surface (&bitmap, NULL, TRUE, font_options, surface);
1571
43.4k
  if (unlikely (status))
1572
0
      return status;
1573
1574
  /* Note: the font's coordinate system is upside down from ours, so the
1575
   * Y coordinate of the control box needs to be negated.  Moreover, device
1576
   * offsets are position of glyph origin relative to top left while xMin
1577
   * and yMax are offsets of top left relative to origin.  Another negation.
1578
   */
1579
43.4k
  cairo_surface_set_device_offset (&(*surface)->base,
1580
43.4k
           (double)-glyphslot->bitmap_left,
1581
43.4k
           (double)+glyphslot->bitmap_top);
1582
43.4k
    }
1583
1584
44.5k
    return CAIRO_STATUS_SUCCESS;
1585
44.5k
}
1586
1587
/* Converts a bitmap (or other) FT_GlyphSlot into an image */
1588
static cairo_status_t
1589
_render_glyph_bitmap (FT_Face         face,
1590
          cairo_font_options_t   *font_options,
1591
          cairo_image_surface_t **surface)
1592
0
{
1593
0
    FT_GlyphSlot glyphslot = face->glyph;
1594
0
    cairo_status_t status;
1595
0
    FT_Error error;
1596
1597
    /* According to the FreeType docs, glyphslot->format could be
1598
     * something other than FT_GLYPH_FORMAT_OUTLINE or
1599
     * FT_GLYPH_FORMAT_BITMAP. Calling FT_Render_Glyph gives FreeType
1600
     * the opportunity to convert such to
1601
     * bitmap. FT_GLYPH_FORMAT_COMPOSITE will not be encountered since
1602
     * we avoid the FT_LOAD_NO_RECURSE flag.
1603
     */
1604
0
    error = FT_Render_Glyph (glyphslot, FT_RENDER_MODE_NORMAL);
1605
    /* XXX ignoring all other errors for now.  They are not fatal, typically
1606
     * just a glyph-not-found. */
1607
0
    if (error == FT_Err_Out_Of_Memory)
1608
0
  return _cairo_error (CAIRO_STATUS_NO_MEMORY);
1609
1610
0
    status = _get_bitmap_surface (&glyphslot->bitmap,
1611
0
          glyphslot->library,
1612
0
          FALSE, font_options,
1613
0
          surface);
1614
0
    if (unlikely (status))
1615
0
  return status;
1616
1617
    /*
1618
     * Note: the font's coordinate system is upside down from ours, so the
1619
     * Y coordinate of the control box needs to be negated.  Moreover, device
1620
     * offsets are position of glyph origin relative to top left while
1621
     * bitmap_left and bitmap_top are offsets of top left relative to origin.
1622
     * Another negation.
1623
     */
1624
0
    cairo_surface_set_device_offset (&(*surface)->base,
1625
0
             -glyphslot->bitmap_left,
1626
0
             +glyphslot->bitmap_top);
1627
1628
0
    return CAIRO_STATUS_SUCCESS;
1629
0
}
1630
1631
static cairo_status_t
1632
_transform_glyph_bitmap (cairo_matrix_t         * shape,
1633
       cairo_image_surface_t ** surface)
1634
0
{
1635
0
    cairo_matrix_t original_to_transformed;
1636
0
    cairo_matrix_t transformed_to_original;
1637
0
    cairo_image_surface_t *old_image;
1638
0
    cairo_surface_t *image;
1639
0
    double x[4], y[4];
1640
0
    double origin_x, origin_y;
1641
0
    int orig_width, orig_height;
1642
0
    int i;
1643
0
    int x_min, y_min, x_max, y_max;
1644
0
    int width, height;
1645
0
    cairo_status_t status;
1646
0
    cairo_surface_pattern_t pattern;
1647
1648
    /* We want to compute a transform that takes the origin
1649
     * (device_x_offset, device_y_offset) to 0,0, then applies
1650
     * the "shape" portion of the font transform
1651
     */
1652
0
    original_to_transformed = *shape;
1653
1654
0
    cairo_surface_get_device_offset (&(*surface)->base, &origin_x, &origin_y);
1655
0
    orig_width = (*surface)->width;
1656
0
    orig_height = (*surface)->height;
1657
1658
0
    cairo_matrix_translate (&original_to_transformed,
1659
0
          -origin_x, -origin_y);
1660
1661
    /* Find the bounding box of the original bitmap under that
1662
     * transform
1663
     */
1664
0
    x[0] = 0;          y[0] = 0;
1665
0
    x[1] = orig_width; y[1] = 0;
1666
0
    x[2] = orig_width; y[2] = orig_height;
1667
0
    x[3] = 0;          y[3] = orig_height;
1668
1669
0
    for (i = 0; i < 4; i++)
1670
0
      cairo_matrix_transform_point (&original_to_transformed,
1671
0
            &x[i], &y[i]);
1672
1673
0
    x_min = floor (x[0]);   y_min = floor (y[0]);
1674
0
    x_max =  ceil (x[0]);   y_max =  ceil (y[0]);
1675
1676
0
    for (i = 1; i < 4; i++) {
1677
0
  if (x[i] < x_min)
1678
0
      x_min = floor (x[i]);
1679
0
  else if (x[i] > x_max)
1680
0
      x_max = ceil (x[i]);
1681
0
  if (y[i] < y_min)
1682
0
      y_min = floor (y[i]);
1683
0
  else if (y[i] > y_max)
1684
0
      y_max = ceil (y[i]);
1685
0
    }
1686
1687
    /* Adjust the transform so that the bounding box starts at 0,0 ...
1688
     * this gives our final transform from original bitmap to transformed
1689
     * bitmap.
1690
     */
1691
0
    original_to_transformed.x0 -= x_min;
1692
0
    original_to_transformed.y0 -= y_min;
1693
1694
    /* Create the transformed bitmap */
1695
0
    width  = x_max - x_min;
1696
0
    height = y_max - y_min;
1697
1698
0
    transformed_to_original = original_to_transformed;
1699
0
    status = cairo_matrix_invert (&transformed_to_original);
1700
0
    if (unlikely (status))
1701
0
  return status;
1702
1703
0
    if ((*surface)->format == CAIRO_FORMAT_ARGB32 &&
1704
0
        !pixman_image_get_component_alpha ((*surface)->pixman_image))
1705
0
      image = cairo_image_surface_create (CAIRO_FORMAT_ARGB32, width, height);
1706
0
    else
1707
0
      image = cairo_image_surface_create (CAIRO_FORMAT_A8, width, height);
1708
0
    if (unlikely (image->status))
1709
0
  return image->status;
1710
1711
    /* Draw the original bitmap transformed into the new bitmap
1712
     */
1713
0
    _cairo_pattern_init_for_surface (&pattern, &(*surface)->base);
1714
0
    cairo_pattern_set_matrix (&pattern.base, &transformed_to_original);
1715
1716
0
    status = _cairo_surface_paint (image,
1717
0
           CAIRO_OPERATOR_SOURCE,
1718
0
           &pattern.base,
1719
0
           NULL);
1720
1721
0
    _cairo_pattern_fini (&pattern.base);
1722
1723
0
    if (unlikely (status)) {
1724
0
  cairo_surface_destroy (image);
1725
0
  return status;
1726
0
    }
1727
1728
    /* Now update the cache entry for the new bitmap, recomputing
1729
     * the origin based on the final transform.
1730
     */
1731
0
    cairo_matrix_transform_point (&original_to_transformed,
1732
0
          &origin_x, &origin_y);
1733
1734
0
    old_image = (*surface);
1735
0
    (*surface) = (cairo_image_surface_t *)image;
1736
1737
    /* Note: we converted subpixel-rendered RGBA images to grayscale,
1738
     * so, no need to copy component alpha to new image. */
1739
1740
0
    cairo_surface_destroy (&old_image->base);
1741
1742
0
    cairo_surface_set_device_offset (&(*surface)->base,
1743
0
             _cairo_lround (origin_x),
1744
0
             _cairo_lround (origin_y));
1745
0
    return CAIRO_STATUS_SUCCESS;
1746
0
}
1747
1748
static const cairo_unscaled_font_backend_t cairo_ft_unscaled_font_backend = {
1749
    _cairo_ft_unscaled_font_destroy,
1750
#if 0
1751
    _cairo_ft_unscaled_font_create_glyph
1752
#endif
1753
};
1754
1755
/* #cairo_ft_scaled_font_t */
1756
1757
typedef struct _cairo_ft_scaled_font {
1758
    cairo_scaled_font_t base;
1759
    cairo_ft_unscaled_font_t *unscaled;
1760
    cairo_ft_options_t ft_options;
1761
} cairo_ft_scaled_font_t;
1762
1763
static const cairo_scaled_font_backend_t _cairo_ft_scaled_font_backend;
1764
1765
#if CAIRO_HAS_FC_FONT
1766
/* The load flags passed to FT_Load_Glyph control aspects like hinting and
1767
 * antialiasing. Here we compute them from the fields of a FcPattern.
1768
 */
1769
static void
1770
_get_pattern_ft_options (FcPattern *pattern, cairo_ft_options_t *ret)
1771
2.11k
{
1772
2.11k
    FcBool antialias, vertical_layout, hinting, autohint, bitmap, embolden;
1773
2.11k
    cairo_ft_options_t ft_options;
1774
2.11k
    int rgba;
1775
2.11k
    int hintstyle;
1776
2.11k
    char *variations;
1777
1778
2.11k
    _cairo_font_options_init_default (&ft_options.base);
1779
2.11k
    ft_options.load_flags = FT_LOAD_DEFAULT;
1780
2.11k
    ft_options.synth_flags = 0;
1781
1782
    /* Check whether to force use of embedded bitmaps */
1783
2.11k
    if (FcPatternGetBool (pattern,
1784
2.11k
        FC_EMBEDDED_BITMAP, 0, &bitmap) != FcResultMatch)
1785
0
  bitmap = FcFalse;
1786
1787
    /* disable antialiasing if requested */
1788
2.11k
    if (FcPatternGetBool (pattern,
1789
2.11k
        FC_ANTIALIAS, 0, &antialias) != FcResultMatch)
1790
0
  antialias = FcTrue;
1791
1792
2.11k
    if (antialias) {
1793
2.11k
  cairo_subpixel_order_t subpixel_order;
1794
2.11k
  int lcd_filter;
1795
1796
  /* disable hinting if requested */
1797
2.11k
  if (FcPatternGetBool (pattern,
1798
2.11k
            FC_HINTING, 0, &hinting) != FcResultMatch)
1799
0
      hinting = FcTrue;
1800
1801
2.11k
  if (FcPatternGetInteger (pattern,
1802
2.11k
         FC_RGBA, 0, &rgba) != FcResultMatch)
1803
0
      rgba = FC_RGBA_UNKNOWN;
1804
1805
2.11k
  switch (rgba) {
1806
0
  case FC_RGBA_RGB:
1807
0
      subpixel_order = CAIRO_SUBPIXEL_ORDER_RGB;
1808
0
      break;
1809
0
  case FC_RGBA_BGR:
1810
0
      subpixel_order = CAIRO_SUBPIXEL_ORDER_BGR;
1811
0
      break;
1812
0
  case FC_RGBA_VRGB:
1813
0
      subpixel_order = CAIRO_SUBPIXEL_ORDER_VRGB;
1814
0
      break;
1815
0
  case FC_RGBA_VBGR:
1816
0
      subpixel_order = CAIRO_SUBPIXEL_ORDER_VBGR;
1817
0
      break;
1818
0
  case FC_RGBA_UNKNOWN:
1819
2.11k
  case FC_RGBA_NONE:
1820
2.11k
  default:
1821
2.11k
      subpixel_order = CAIRO_SUBPIXEL_ORDER_DEFAULT;
1822
2.11k
      break;
1823
2.11k
  }
1824
1825
2.11k
  if (subpixel_order != CAIRO_SUBPIXEL_ORDER_DEFAULT) {
1826
0
      ft_options.base.subpixel_order = subpixel_order;
1827
0
      ft_options.base.antialias = CAIRO_ANTIALIAS_SUBPIXEL;
1828
0
  }
1829
1830
2.11k
  if (FcPatternGetInteger (pattern,
1831
2.11k
         FC_LCD_FILTER, 0, &lcd_filter) == FcResultMatch)
1832
0
  {
1833
0
      switch (lcd_filter) {
1834
0
      case FC_LCD_NONE:
1835
0
    ft_options.base.lcd_filter = CAIRO_LCD_FILTER_NONE;
1836
0
    break;
1837
0
      case FC_LCD_DEFAULT:
1838
0
    ft_options.base.lcd_filter = CAIRO_LCD_FILTER_FIR5;
1839
0
    break;
1840
0
      case FC_LCD_LIGHT:
1841
0
    ft_options.base.lcd_filter = CAIRO_LCD_FILTER_FIR3;
1842
0
    break;
1843
0
      case FC_LCD_LEGACY:
1844
0
    ft_options.base.lcd_filter = CAIRO_LCD_FILTER_INTRA_PIXEL;
1845
0
    break;
1846
0
      }
1847
0
  }
1848
1849
2.11k
  if (FcPatternGetInteger (pattern,
1850
2.11k
         FC_HINT_STYLE, 0, &hintstyle) != FcResultMatch)
1851
0
      hintstyle = FC_HINT_FULL;
1852
1853
2.11k
  if (!hinting)
1854
0
      hintstyle = FC_HINT_NONE;
1855
1856
2.11k
  switch (hintstyle) {
1857
0
  case FC_HINT_NONE:
1858
0
      ft_options.base.hint_style = CAIRO_HINT_STYLE_NONE;
1859
0
      break;
1860
0
  case FC_HINT_SLIGHT:
1861
0
      ft_options.base.hint_style = CAIRO_HINT_STYLE_SLIGHT;
1862
0
      break;
1863
0
  case FC_HINT_MEDIUM:
1864
0
  default:
1865
0
      ft_options.base.hint_style = CAIRO_HINT_STYLE_MEDIUM;
1866
0
      break;
1867
2.11k
  case FC_HINT_FULL:
1868
2.11k
      ft_options.base.hint_style = CAIRO_HINT_STYLE_FULL;
1869
2.11k
      break;
1870
2.11k
  }
1871
1872
  /* Force embedded bitmaps off if no hinting requested */
1873
2.11k
  if (ft_options.base.hint_style == CAIRO_HINT_STYLE_NONE)
1874
0
    bitmap = FcFalse;
1875
1876
2.11k
  if (!bitmap)
1877
0
      ft_options.load_flags |= FT_LOAD_NO_BITMAP;
1878
1879
2.11k
    } else {
1880
0
  ft_options.base.antialias = CAIRO_ANTIALIAS_NONE;
1881
0
    }
1882
1883
    /* force autohinting if requested */
1884
2.11k
    if (FcPatternGetBool (pattern,
1885
2.11k
        FC_AUTOHINT, 0, &autohint) != FcResultMatch)
1886
0
  autohint = FcFalse;
1887
1888
2.11k
    if (autohint)
1889
0
  ft_options.load_flags |= FT_LOAD_FORCE_AUTOHINT;
1890
1891
2.11k
    if (FcPatternGetBool (pattern,
1892
2.11k
        FC_VERTICAL_LAYOUT, 0, &vertical_layout) != FcResultMatch)
1893
0
  vertical_layout = FcFalse;
1894
1895
2.11k
    if (vertical_layout)
1896
0
  ft_options.load_flags |= FT_LOAD_VERTICAL_LAYOUT;
1897
1898
2.11k
    if (FcPatternGetBool (pattern,
1899
2.11k
        FC_EMBOLDEN, 0, &embolden) != FcResultMatch)
1900
0
  embolden = FcFalse;
1901
1902
2.11k
    if (embolden)
1903
0
  ft_options.synth_flags |= CAIRO_FT_SYNTHESIZE_BOLD;
1904
1905
2.11k
    if (FcPatternGetString (pattern, FC_FONT_VARIATIONS, 0, (FcChar8 **) &variations) == FcResultMatch) {
1906
0
      ft_options.base.variations = strdup (variations);
1907
0
    }
1908
1909
2.11k
    *ret = ft_options;
1910
2.11k
}
1911
#endif
1912
1913
static void
1914
_cairo_ft_options_merge (cairo_ft_options_t *options,
1915
       cairo_ft_options_t *other)
1916
556
{
1917
556
    int load_flags = other->load_flags;
1918
556
    int load_target = FT_LOAD_TARGET_NORMAL;
1919
1920
    /* clear load target mode */
1921
556
    load_flags &= ~(FT_LOAD_TARGET_(FT_LOAD_TARGET_MODE(other->load_flags)));
1922
1923
556
    if (load_flags & FT_LOAD_NO_HINTING)
1924
0
  other->base.hint_style = CAIRO_HINT_STYLE_NONE;
1925
1926
556
    if (other->base.antialias == CAIRO_ANTIALIAS_NONE ||
1927
556
  options->base.antialias == CAIRO_ANTIALIAS_NONE) {
1928
0
  options->base.antialias = CAIRO_ANTIALIAS_NONE;
1929
0
  options->base.subpixel_order = CAIRO_SUBPIXEL_ORDER_DEFAULT;
1930
0
    }
1931
1932
556
    if (other->base.antialias == CAIRO_ANTIALIAS_SUBPIXEL &&
1933
0
  options->base.antialias == CAIRO_ANTIALIAS_DEFAULT) {
1934
0
  options->base.antialias = CAIRO_ANTIALIAS_SUBPIXEL;
1935
0
  options->base.subpixel_order = other->base.subpixel_order;
1936
0
    }
1937
1938
556
    if (options->base.hint_style == CAIRO_HINT_STYLE_DEFAULT)
1939
245
  options->base.hint_style = other->base.hint_style;
1940
1941
556
    if (other->base.hint_style == CAIRO_HINT_STYLE_NONE)
1942
0
  options->base.hint_style = CAIRO_HINT_STYLE_NONE;
1943
1944
556
    if (options->base.lcd_filter == CAIRO_LCD_FILTER_DEFAULT)
1945
556
  options->base.lcd_filter = other->base.lcd_filter;
1946
1947
556
    if (other->base.lcd_filter == CAIRO_LCD_FILTER_NONE)
1948
0
  options->base.lcd_filter = CAIRO_LCD_FILTER_NONE;
1949
1950
556
    if (options->base.antialias == CAIRO_ANTIALIAS_NONE) {
1951
0
  if (options->base.hint_style == CAIRO_HINT_STYLE_NONE)
1952
0
      load_flags |= FT_LOAD_NO_HINTING;
1953
0
  else
1954
0
      load_target = FT_LOAD_TARGET_MONO;
1955
0
  load_flags |= FT_LOAD_MONOCHROME;
1956
556
    } else {
1957
556
  switch (options->base.hint_style) {
1958
0
  case CAIRO_HINT_STYLE_NONE:
1959
0
      load_flags |= FT_LOAD_NO_HINTING;
1960
0
      break;
1961
311
  case CAIRO_HINT_STYLE_SLIGHT:
1962
311
      load_target = FT_LOAD_TARGET_LIGHT;
1963
311
      break;
1964
0
  case CAIRO_HINT_STYLE_MEDIUM:
1965
0
      break;
1966
245
  case CAIRO_HINT_STYLE_FULL:
1967
245
  case CAIRO_HINT_STYLE_DEFAULT:
1968
245
      if (options->base.antialias == CAIRO_ANTIALIAS_SUBPIXEL) {
1969
0
    switch (options->base.subpixel_order) {
1970
0
    case CAIRO_SUBPIXEL_ORDER_DEFAULT:
1971
0
    case CAIRO_SUBPIXEL_ORDER_RGB:
1972
0
    case CAIRO_SUBPIXEL_ORDER_BGR:
1973
0
        load_target = FT_LOAD_TARGET_LCD;
1974
0
        break;
1975
0
    case CAIRO_SUBPIXEL_ORDER_VRGB:
1976
0
    case CAIRO_SUBPIXEL_ORDER_VBGR:
1977
0
        load_target = FT_LOAD_TARGET_LCD_V;
1978
0
    break;
1979
0
    }
1980
0
      }
1981
245
      break;
1982
556
  }
1983
556
    }
1984
1985
556
    if (other->base.variations) {
1986
0
      if (options->base.variations) {
1987
0
        char *p;
1988
1989
        /* 'merge' variations by concatenating - later entries win */
1990
0
        p = malloc (strlen (other->base.variations) + strlen (options->base.variations) + 2);
1991
0
        p[0] = 0;
1992
0
        strcat (p, other->base.variations);
1993
0
        strcat (p, ",");
1994
0
        strcat (p, options->base.variations);
1995
0
        free (options->base.variations);
1996
0
        options->base.variations = p;
1997
0
      }
1998
0
      else {
1999
0
        options->base.variations = strdup (other->base.variations);
2000
0
      }
2001
0
    }
2002
2003
556
    options->load_flags = load_flags | load_target;
2004
556
    options->synth_flags = other->synth_flags;
2005
556
}
2006
2007
static cairo_status_t
2008
_cairo_ft_font_face_scaled_font_create (void        *abstract_font_face,
2009
          const cairo_matrix_t   *font_matrix,
2010
          const cairo_matrix_t   *ctm,
2011
          const cairo_font_options_t *options,
2012
          cairo_scaled_font_t       **font_out)
2013
556
{
2014
556
    cairo_ft_font_face_t *font_face = abstract_font_face;
2015
556
    cairo_ft_scaled_font_t *scaled_font;
2016
556
    FT_Face face;
2017
556
    FT_Size_Metrics *metrics;
2018
556
    cairo_font_extents_t fs_metrics;
2019
556
    cairo_status_t status;
2020
556
    cairo_ft_unscaled_font_t *unscaled;
2021
2022
556
    assert (font_face->unscaled);
2023
2024
556
    face = _cairo_ft_unscaled_font_lock_face (font_face->unscaled);
2025
556
    if (unlikely (face == NULL)) /* backend error */
2026
0
  return _cairo_error (CAIRO_STATUS_NO_MEMORY);
2027
2028
556
    scaled_font = _cairo_calloc (sizeof (cairo_ft_scaled_font_t));
2029
556
    if (unlikely (scaled_font == NULL)) {
2030
0
  status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
2031
0
  goto FAIL;
2032
0
    }
2033
2034
556
    scaled_font->unscaled = unscaled = font_face->unscaled;
2035
556
    _cairo_unscaled_font_reference (&unscaled->base);
2036
2037
556
    _cairo_font_options_init_copy (&scaled_font->ft_options.base, options);
2038
556
    _cairo_ft_options_merge (&scaled_font->ft_options, &font_face->ft_options);
2039
2040
556
    status = _cairo_scaled_font_init (&scaled_font->base,
2041
556
                    &font_face->base,
2042
556
              font_matrix, ctm, options,
2043
556
              &_cairo_ft_scaled_font_backend);
2044
556
    if (unlikely (status))
2045
0
  goto CLEANUP_SCALED_FONT;
2046
2047
556
    status = _cairo_ft_unscaled_font_set_scale (unscaled,
2048
556
                        &scaled_font->base.scale);
2049
556
    if (unlikely (status)) {
2050
  /* This can only fail if we encounter an error with the underlying
2051
   * font, so propagate the error back to the font-face. */
2052
0
  _cairo_ft_unscaled_font_unlock_face (unscaled);
2053
0
  _cairo_unscaled_font_destroy (&unscaled->base);
2054
0
  free (scaled_font);
2055
0
  return status;
2056
0
    }
2057
2058
2059
556
    metrics = &face->size->metrics;
2060
2061
    /*
2062
     * Get to unscaled metrics so that the upper level can get back to
2063
     * user space
2064
     *
2065
     * Also use this path for bitmap-only fonts.  The other branch uses
2066
     * face members that are only relevant for scalable fonts.  This is
2067
     * detected by simply checking for units_per_EM==0.
2068
     */
2069
556
    if (scaled_font->base.options.hint_metrics != CAIRO_HINT_METRICS_OFF ||
2070
311
  face->units_per_EM == 0) {
2071
245
  fs_metrics.ascent =        SCALE (DOUBLE_FROM_26_6 (metrics->ascender), unscaled->y_scale);
2072
245
  fs_metrics.descent =       SCALE (DOUBLE_FROM_26_6 (- metrics->descender), unscaled->y_scale);
2073
245
  fs_metrics.height =        SCALE (DOUBLE_FROM_26_6 (metrics->height), unscaled->y_scale);
2074
245
  if (!_cairo_ft_scaled_font_is_vertical (&scaled_font->base)) {
2075
245
      fs_metrics.max_x_advance = SCALE (DOUBLE_FROM_26_6 (metrics->max_advance), unscaled->x_scale);
2076
245
      fs_metrics.max_y_advance = 0;
2077
245
  } else {
2078
0
      fs_metrics.max_x_advance = 0;
2079
0
      fs_metrics.max_y_advance = SCALE (DOUBLE_FROM_26_6 (metrics->max_advance), unscaled->y_scale);
2080
0
  }
2081
311
    } else {
2082
311
  double scale = face->units_per_EM;
2083
2084
311
  fs_metrics.ascent =        face->ascender / scale;
2085
311
  fs_metrics.descent =       - face->descender / scale;
2086
311
  fs_metrics.height =        face->height / scale;
2087
311
  if (!_cairo_ft_scaled_font_is_vertical (&scaled_font->base)) {
2088
311
      fs_metrics.max_x_advance = face->max_advance_width / scale;
2089
311
      fs_metrics.max_y_advance = 0;
2090
311
  } else {
2091
0
      fs_metrics.max_x_advance = 0;
2092
0
      fs_metrics.max_y_advance = face->max_advance_height / scale;
2093
0
  }
2094
311
    }
2095
2096
556
    status = _cairo_scaled_font_set_metrics (&scaled_font->base, &fs_metrics);
2097
556
    if (unlikely (status))
2098
0
  goto CLEANUP_SCALED_FONT;
2099
2100
556
    _cairo_ft_unscaled_font_unlock_face (unscaled);
2101
2102
556
    *font_out = &scaled_font->base;
2103
556
    return CAIRO_STATUS_SUCCESS;
2104
2105
0
  CLEANUP_SCALED_FONT:
2106
0
    _cairo_unscaled_font_destroy (&unscaled->base);
2107
0
    free (scaled_font);
2108
0
  FAIL:
2109
0
    _cairo_ft_unscaled_font_unlock_face (font_face->unscaled);
2110
0
    *font_out = _cairo_scaled_font_create_in_error (status);
2111
0
    return CAIRO_STATUS_SUCCESS; /* non-backend error */
2112
0
}
2113
2114
cairo_bool_t
2115
_cairo_scaled_font_is_ft (cairo_scaled_font_t *scaled_font)
2116
556
{
2117
556
    return scaled_font->backend == &_cairo_ft_scaled_font_backend;
2118
556
}
2119
2120
static void
2121
_cairo_ft_scaled_font_fini (void *abstract_font)
2122
298
{
2123
298
    cairo_ft_scaled_font_t *scaled_font = abstract_font;
2124
2125
298
    if (scaled_font == NULL)
2126
0
        return;
2127
2128
298
    _cairo_font_options_fini (&scaled_font->ft_options.base);
2129
298
    _cairo_unscaled_font_destroy (&scaled_font->unscaled->base);
2130
298
}
2131
2132
static int
2133
_move_to (FT_Vector *to, void *closure)
2134
0
{
2135
0
    cairo_path_fixed_t *path = closure;
2136
0
    cairo_fixed_t x, y;
2137
2138
0
    x = _cairo_fixed_from_26_6 (to->x);
2139
0
    y = _cairo_fixed_from_26_6 (to->y);
2140
2141
0
    if (_cairo_path_fixed_close_path (path) != CAIRO_STATUS_SUCCESS)
2142
0
  return 1;
2143
0
    if (_cairo_path_fixed_move_to (path, x, y) != CAIRO_STATUS_SUCCESS)
2144
0
  return 1;
2145
2146
0
    return 0;
2147
0
}
2148
2149
static int
2150
_line_to (FT_Vector *to, void *closure)
2151
0
{
2152
0
    cairo_path_fixed_t *path = closure;
2153
0
    cairo_fixed_t x, y;
2154
2155
0
    x = _cairo_fixed_from_26_6 (to->x);
2156
0
    y = _cairo_fixed_from_26_6 (to->y);
2157
2158
0
    if (_cairo_path_fixed_line_to (path, x, y) != CAIRO_STATUS_SUCCESS)
2159
0
  return 1;
2160
2161
0
    return 0;
2162
0
}
2163
2164
static int
2165
_conic_to (FT_Vector *control, FT_Vector *to, void *closure)
2166
0
{
2167
0
    cairo_path_fixed_t *path = closure;
2168
2169
0
    cairo_fixed_t x0, y0;
2170
0
    cairo_fixed_t x1, y1;
2171
0
    cairo_fixed_t x2, y2;
2172
0
    cairo_fixed_t x3, y3;
2173
0
    cairo_point_t conic;
2174
2175
0
    if (! _cairo_path_fixed_get_current_point (path, &x0, &y0))
2176
0
  return 1;
2177
2178
0
    conic.x = _cairo_fixed_from_26_6 (control->x);
2179
0
    conic.y = _cairo_fixed_from_26_6 (control->y);
2180
2181
0
    x3 = _cairo_fixed_from_26_6 (to->x);
2182
0
    y3 = _cairo_fixed_from_26_6 (to->y);
2183
2184
0
    x1 = x0 + 2.0/3.0 * (conic.x - x0);
2185
0
    y1 = y0 + 2.0/3.0 * (conic.y - y0);
2186
2187
0
    x2 = x3 + 2.0/3.0 * (conic.x - x3);
2188
0
    y2 = y3 + 2.0/3.0 * (conic.y - y3);
2189
2190
0
    if (_cairo_path_fixed_curve_to (path,
2191
0
            x1, y1,
2192
0
            x2, y2,
2193
0
            x3, y3) != CAIRO_STATUS_SUCCESS)
2194
0
  return 1;
2195
2196
0
    return 0;
2197
0
}
2198
2199
static int
2200
_cubic_to (FT_Vector *control1, FT_Vector *control2,
2201
     FT_Vector *to, void *closure)
2202
0
{
2203
0
    cairo_path_fixed_t *path = closure;
2204
0
    cairo_fixed_t x0, y0;
2205
0
    cairo_fixed_t x1, y1;
2206
0
    cairo_fixed_t x2, y2;
2207
2208
0
    x0 = _cairo_fixed_from_26_6 (control1->x);
2209
0
    y0 = _cairo_fixed_from_26_6 (control1->y);
2210
2211
0
    x1 = _cairo_fixed_from_26_6 (control2->x);
2212
0
    y1 = _cairo_fixed_from_26_6 (control2->y);
2213
2214
0
    x2 = _cairo_fixed_from_26_6 (to->x);
2215
0
    y2 = _cairo_fixed_from_26_6 (to->y);
2216
2217
0
    if (_cairo_path_fixed_curve_to (path,
2218
0
            x0, y0,
2219
0
            x1, y1,
2220
0
            x2, y2) != CAIRO_STATUS_SUCCESS)
2221
0
  return 1;
2222
2223
0
    return 0;
2224
0
}
2225
2226
cairo_status_t
2227
_cairo_ft_face_decompose_glyph_outline (FT_Face        face,
2228
          cairo_path_fixed_t **pathp)
2229
0
{
2230
0
    static const FT_Outline_Funcs outline_funcs = {
2231
0
  (FT_Outline_MoveToFunc)_move_to,
2232
0
  (FT_Outline_LineToFunc)_line_to,
2233
0
  (FT_Outline_ConicToFunc)_conic_to,
2234
0
  (FT_Outline_CubicToFunc)_cubic_to,
2235
0
  0, /* shift */
2236
0
  0, /* delta */
2237
0
    };
2238
0
    static const FT_Matrix invert_y = {
2239
0
  DOUBLE_TO_16_16 (1.0), 0,
2240
0
  0, DOUBLE_TO_16_16 (-1.0),
2241
0
    };
2242
2243
0
    FT_GlyphSlot glyph;
2244
0
    cairo_path_fixed_t *path;
2245
0
    cairo_status_t status;
2246
2247
0
    path = _cairo_path_fixed_create ();
2248
0
    if (!path)
2249
0
  return _cairo_error (CAIRO_STATUS_NO_MEMORY);
2250
2251
0
    glyph = face->glyph;
2252
2253
    /* Font glyphs have an inverted Y axis compared to cairo. */
2254
0
    FT_Outline_Transform (&glyph->outline, &invert_y);
2255
0
    if (FT_Outline_Decompose (&glyph->outline, &outline_funcs, path)) {
2256
0
  _cairo_path_fixed_destroy (path);
2257
0
  return _cairo_error (CAIRO_STATUS_NO_MEMORY);
2258
0
    }
2259
2260
0
    status = _cairo_path_fixed_close_path (path);
2261
0
    if (unlikely (status)) {
2262
0
  _cairo_path_fixed_destroy (path);
2263
0
  return status;
2264
0
    }
2265
2266
0
    *pathp = path;
2267
2268
0
    return CAIRO_STATUS_SUCCESS;
2269
0
}
2270
2271
/*
2272
 * Translate glyph to match its metrics.
2273
 */
2274
static void
2275
_cairo_ft_scaled_glyph_vertical_layout_bearing_fix (void        *abstract_font,
2276
                FT_GlyphSlot glyph)
2277
0
{
2278
0
    cairo_ft_scaled_font_t *scaled_font = abstract_font;
2279
0
    FT_Vector vector;
2280
2281
0
    vector.x = glyph->metrics.vertBearingX - glyph->metrics.horiBearingX;
2282
0
    vector.y = -glyph->metrics.vertBearingY - glyph->metrics.horiBearingY;
2283
2284
0
    if (glyph->format == FT_GLYPH_FORMAT_OUTLINE) {
2285
0
  FT_Vector_Transform (&vector, &scaled_font->unscaled->Current_Shape);
2286
0
  FT_Outline_Translate(&glyph->outline, vector.x, vector.y);
2287
0
    } else if (glyph->format == FT_GLYPH_FORMAT_BITMAP) {
2288
0
  glyph->bitmap_left += vector.x / 64;
2289
0
  glyph->bitmap_top  += vector.y / 64;
2290
0
    }
2291
0
}
2292
2293
static void
2294
cairo_ft_apply_variations (FT_Face                 face,
2295
         cairo_ft_scaled_font_t *scaled_font)
2296
160k
{
2297
160k
    FT_MM_Var *ft_mm_var;
2298
160k
    FT_Error ret;
2299
160k
    unsigned int instance_id = scaled_font->unscaled->id >> 16;
2300
2301
160k
    ret = FT_Get_MM_Var (face, &ft_mm_var);
2302
160k
    if (ret == 0) {
2303
0
        FT_Fixed *current_coords;
2304
0
        FT_Fixed *coords;
2305
0
        unsigned int i;
2306
0
        const char *p;
2307
2308
0
        coords = malloc (sizeof (FT_Fixed) * ft_mm_var->num_axis);
2309
  /* FIXME check coords. */
2310
2311
0
  if (scaled_font->unscaled->variations)
2312
0
  {
2313
0
      memcpy (coords, scaled_font->unscaled->variations, ft_mm_var->num_axis * sizeof (*coords));
2314
0
  }
2315
0
  else if (instance_id && instance_id <= ft_mm_var->num_namedstyles)
2316
0
  {
2317
0
      FT_Var_Named_Style *instance = &ft_mm_var->namedstyle[instance_id - 1];
2318
0
      memcpy (coords, instance->coords, ft_mm_var->num_axis * sizeof (*coords));
2319
0
  }
2320
0
  else
2321
0
      for (i = 0; i < ft_mm_var->num_axis; i++)
2322
0
    coords[i] = ft_mm_var->axis[i].def;
2323
2324
0
        p = scaled_font->ft_options.base.variations;
2325
0
        while (p && *p) {
2326
0
            const char *start;
2327
0
            const char *end, *end2;
2328
0
            FT_ULong tag;
2329
0
            double value;
2330
2331
0
            while (_cairo_isspace (*p)) p++;
2332
2333
0
            start = p;
2334
0
            end = strchr (p, ',');
2335
0
            if (end && (end - p < 6))
2336
0
                goto skip;
2337
2338
0
            tag = FT_MAKE_TAG(p[0], p[1], p[2], p[3]);
2339
2340
0
            p += 4;
2341
0
            while (_cairo_isspace (*p)) p++;
2342
0
            if (*p == '=') p++;
2343
2344
0
            if (p - start < 5)
2345
0
                goto skip;
2346
2347
0
            value = _cairo_strtod (p, (char **) &end2);
2348
2349
0
            while (end2 && _cairo_isspace (*end2)) end2++;
2350
2351
0
            if (end2 && (*end2 != ',' && *end2 != '\0'))
2352
0
                goto skip;
2353
2354
0
            for (i = 0; i < ft_mm_var->num_axis; i++) {
2355
0
                if (ft_mm_var->axis[i].tag == tag) {
2356
0
                    coords[i] = (FT_Fixed)(value*65536);
2357
0
                    break;
2358
0
                }
2359
0
            }
2360
2361
0
skip:
2362
0
            p = end ? end + 1 : NULL;
2363
0
        }
2364
2365
0
        current_coords = malloc (sizeof (FT_Fixed) * ft_mm_var->num_axis);
2366
0
        ret = FT_Get_Var_Design_Coordinates (face, ft_mm_var->num_axis, current_coords);
2367
0
        if (ret == 0) {
2368
0
            for (i = 0; i < ft_mm_var->num_axis; i++) {
2369
0
              if (coords[i] != current_coords[i])
2370
0
                break;
2371
0
            }
2372
0
            if (i == ft_mm_var->num_axis)
2373
0
              goto done;
2374
0
        }
2375
2376
0
        FT_Set_Var_Design_Coordinates (face, ft_mm_var->num_axis, coords);
2377
0
done:
2378
0
        free (coords);
2379
0
        free (current_coords);
2380
0
        FT_Done_MM_Var (face->glyph->library, ft_mm_var);
2381
0
    }
2382
160k
}
2383
2384
typedef enum {
2385
    CAIRO_FT_GLYPH_TYPE_BITMAP,
2386
    CAIRO_FT_GLYPH_TYPE_OUTLINE,
2387
    CAIRO_FT_GLYPH_TYPE_SVG,
2388
    CAIRO_FT_GLYPH_TYPE_COLR_V0,
2389
    CAIRO_FT_GLYPH_TYPE_COLR_V1,
2390
} cairo_ft_glyph_format_t;
2391
2392
typedef struct {
2393
    cairo_scaled_glyph_private_t base;
2394
2395
    cairo_ft_glyph_format_t format;
2396
} cairo_ft_glyph_private_t;
2397
2398
static const int ft_glyph_private_key;
2399
2400
static cairo_int_status_t
2401
_cairo_ft_scaled_glyph_load_glyph (cairo_ft_scaled_font_t *scaled_font,
2402
           cairo_scaled_glyph_t   *scaled_glyph,
2403
           FT_Face                 face,
2404
           int                     load_flags,
2405
           cairo_bool_t            use_em_size,
2406
           cairo_bool_t            vertical_layout)
2407
160k
{
2408
160k
    FT_Error error;
2409
160k
    cairo_status_t status;
2410
160k
    cairo_ft_glyph_private_t *glyph_priv;
2411
2412
160k
    glyph_priv = (cairo_ft_glyph_private_t *) _cairo_scaled_glyph_find_private (scaled_glyph,
2413
160k
                                                                                &ft_glyph_private_key);
2414
160k
    assert (glyph_priv != NULL);
2415
2416
160k
    if (use_em_size) {
2417
55.6k
  cairo_matrix_t em_size;
2418
55.6k
  cairo_matrix_init_scale (&em_size, face->units_per_EM, face->units_per_EM);
2419
55.6k
  status = _cairo_ft_unscaled_font_set_scale (scaled_font->unscaled, &em_size);
2420
105k
    } else {
2421
105k
  status = _cairo_ft_unscaled_font_set_scale (scaled_font->unscaled,
2422
105k
                &scaled_font->base.scale);
2423
105k
    }
2424
160k
    if (unlikely (status))
2425
0
  return status;
2426
2427
160k
    cairo_ft_apply_variations (face, scaled_font);
2428
2429
160k
#if defined(HAVE_FT_LOAD_NO_SVG)
2430
160k
    if (load_flags & FT_LOAD_COLOR && glyph_priv->format == CAIRO_FT_GLYPH_TYPE_COLR_V1)
2431
0
        load_flags |= FT_LOAD_NO_SVG;
2432
160k
#endif
2433
2434
160k
    error = FT_Load_Glyph (face,
2435
160k
         _cairo_scaled_glyph_index(scaled_glyph),
2436
160k
         load_flags);
2437
    /* XXX ignoring all other errors for now.  They are not fatal, typically
2438
     * just a glyph-not-found. */
2439
160k
    if (error == FT_Err_Out_Of_Memory)
2440
0
  return  _cairo_error (CAIRO_STATUS_NO_MEMORY);
2441
2442
    /*
2443
     * synthesize glyphs if requested
2444
     */
2445
160k
    if (scaled_font->ft_options.synth_flags & CAIRO_FT_SYNTHESIZE_BOLD)
2446
0
  FT_GlyphSlot_Embolden (face->glyph);
2447
2448
160k
    if (scaled_font->ft_options.synth_flags & CAIRO_FT_SYNTHESIZE_OBLIQUE)
2449
0
  FT_GlyphSlot_Oblique (face->glyph);
2450
2451
160k
    if (vertical_layout)
2452
0
  _cairo_ft_scaled_glyph_vertical_layout_bearing_fix (scaled_font, face->glyph);
2453
2454
160k
    if (face->glyph->format == FT_GLYPH_FORMAT_OUTLINE) {
2455
160k
        FT_Pos xshift, yshift;
2456
2457
160k
        xshift = _cairo_scaled_glyph_xphase (scaled_glyph) << 4;
2458
160k
        yshift = _cairo_scaled_glyph_yphase (scaled_glyph) << 4;
2459
2460
160k
        FT_Outline_Translate (&face->glyph->outline, xshift, -yshift);
2461
160k
    }
2462
2463
160k
    return CAIRO_STATUS_SUCCESS;
2464
160k
}
2465
2466
static void
2467
_cairo_ft_glyph_fini (cairo_scaled_glyph_private_t *glyph_private,
2468
          cairo_scaled_glyph_t *glyph,
2469
          cairo_scaled_font_t  *font)
2470
45.1k
{
2471
45.1k
    cairo_list_del (&glyph_private->link);
2472
45.1k
    free (glyph_private);
2473
45.1k
}
2474
2475
2476
static void
2477
_cairo_ft_scaled_glyph_set_palette (cairo_ft_scaled_font_t  *scaled_font,
2478
            FT_Face                  face,
2479
            unsigned int            *num_entries_ret,
2480
            FT_Color               **entries_ret)
2481
0
{
2482
0
    unsigned int num_entries = 0;
2483
0
    FT_Color *entries = NULL;
2484
2485
0
    FT_Palette_Data palette_data;
2486
2487
0
    if (FT_Palette_Data_Get (face, &palette_data) == 0 && palette_data.num_palettes > 0) {
2488
0
  FT_UShort palette_index = CAIRO_COLOR_PALETTE_DEFAULT;
2489
0
  if (scaled_font->base.options.palette_index < palette_data.num_palettes)
2490
0
      palette_index = scaled_font->base.options.palette_index;
2491
2492
0
  if (FT_Palette_Select (face, palette_index, &entries) == 0) {
2493
0
      num_entries = palette_data.num_palette_entries;
2494
2495
            /* Overlay custom colors */
2496
0
            for (unsigned int i = 0; i < scaled_font->base.options.custom_palette_size; i++) {
2497
0
                cairo_palette_color_t *entry = &scaled_font->base.options.custom_palette[i];
2498
0
                if (entry->index < num_entries) {
2499
0
                    entries[entry->index].red = 255 * entry->red;
2500
0
                    entries[entry->index].green = 255 * entry->green;
2501
0
                    entries[entry->index].blue = 255 * entry->blue;
2502
0
                    entries[entry->index].alpha = 255 * entry->alpha;
2503
0
                }
2504
0
            }
2505
0
        }
2506
0
    }
2507
2508
0
    if (num_entries_ret)
2509
0
  *num_entries_ret = num_entries;
2510
2511
0
    if (entries_ret)
2512
0
  *entries_ret = entries;
2513
0
}
2514
2515
/* returns TRUE if foreground color used */
2516
static cairo_bool_t
2517
_cairo_ft_scaled_glyph_set_foreground_color (cairo_ft_scaled_font_t *scaled_font,
2518
               cairo_scaled_glyph_t   *scaled_glyph,
2519
               FT_Face                 face,
2520
               const cairo_color_t    *foreground_color)
2521
0
{
2522
0
    cairo_bool_t uses_foreground_color = FALSE;
2523
0
    FT_LayerIterator  iterator;
2524
0
    FT_UInt layer_glyph_index;
2525
0
    FT_UInt layer_color_index;
2526
0
    FT_Color color;
2527
2528
    /* Check if there is a layer that uses the foreground color */
2529
0
    iterator.p  = NULL;
2530
0
    while (FT_Get_Color_Glyph_Layer(face,
2531
0
            _cairo_scaled_glyph_index (scaled_glyph),
2532
0
            &layer_glyph_index,
2533
0
            &layer_color_index,
2534
0
            &iterator)) {
2535
0
  if (layer_color_index == 0xFFFF) {
2536
0
      uses_foreground_color = TRUE;
2537
0
      break;
2538
0
  }
2539
0
    }
2540
2541
0
    if (uses_foreground_color) {
2542
0
  color.red = (FT_Byte)(foreground_color->red * 0xFF);
2543
0
  color.green = (FT_Byte)(foreground_color->green * 0xFF);
2544
0
  color.blue = (FT_Byte)(foreground_color->blue * 0xFF);
2545
0
  color.alpha = (FT_Byte)(foreground_color->alpha * 0xFF);
2546
0
  FT_Palette_Set_Foreground_Color (face, color);
2547
0
    }
2548
2549
0
    return uses_foreground_color;
2550
0
}
2551
2552
static cairo_int_status_t
2553
_cairo_ft_scaled_glyph_init_surface (cairo_ft_scaled_font_t     *scaled_font,
2554
             cairo_scaled_glyph_t *scaled_glyph,
2555
             cairo_ft_glyph_private_t   *glyph_priv,
2556
             cairo_scaled_glyph_info_t   info,
2557
             FT_Face face,
2558
             const cairo_color_t        *foreground_color,
2559
             cairo_bool_t vertical_layout,
2560
             int load_flags)
2561
44.5k
{
2562
44.5k
    cairo_ft_unscaled_font_t *unscaled = scaled_font->unscaled;
2563
44.5k
    FT_GlyphSlot glyph;
2564
44.5k
    cairo_status_t status;
2565
44.5k
    cairo_image_surface_t *surface;
2566
44.5k
    cairo_bool_t uses_foreground_color = FALSE;
2567
2568
    /* Only one info type at a time handled in this function */
2569
44.5k
    assert (info == CAIRO_SCALED_GLYPH_INFO_COLOR_SURFACE || info == CAIRO_SCALED_GLYPH_INFO_SURFACE);
2570
2571
44.5k
    if (info == CAIRO_SCALED_GLYPH_INFO_COLOR_SURFACE) {
2572
0
  if (!unscaled->have_color) {
2573
0
      scaled_glyph->color_glyph = FALSE;
2574
0
      scaled_glyph->color_glyph_set = TRUE;
2575
0
      return CAIRO_INT_STATUS_UNSUPPORTED;
2576
0
  }
2577
2578
0
  uses_foreground_color = _cairo_ft_scaled_glyph_set_foreground_color (scaled_font,
2579
0
                       scaled_glyph,
2580
0
                       face,
2581
0
                       foreground_color);
2582
0
  _cairo_ft_scaled_glyph_set_palette (scaled_font, face, NULL, NULL);
2583
2584
0
        load_flags &= ~FT_LOAD_MONOCHROME;
2585
  /* clear load target mode */
2586
0
  load_flags &= ~(FT_LOAD_TARGET_(FT_LOAD_TARGET_MODE(load_flags)));
2587
0
  load_flags |= FT_LOAD_TARGET_NORMAL;
2588
0
  load_flags |= FT_LOAD_COLOR;
2589
44.5k
    } else { /* info == CAIRO_SCALED_GLYPH_INFO_SURFACE */
2590
44.5k
        load_flags &= ~FT_LOAD_COLOR;
2591
44.5k
    }
2592
2593
44.5k
    status = _cairo_ft_scaled_glyph_load_glyph (scaled_font,
2594
44.5k
            scaled_glyph,
2595
44.5k
            face,
2596
44.5k
            load_flags,
2597
44.5k
            FALSE,
2598
44.5k
            vertical_layout);
2599
44.5k
    if (unlikely (status))
2600
0
  return status;
2601
2602
44.5k
    glyph = face->glyph;
2603
2604
44.5k
    if (glyph_priv->format == CAIRO_FT_GLYPH_TYPE_OUTLINE) {
2605
2606
44.5k
  status = _render_glyph_outline (face, &scaled_font->ft_options.base,
2607
44.5k
              &surface);
2608
44.5k
    } else {
2609
0
  status = _render_glyph_bitmap (face, &scaled_font->ft_options.base,
2610
0
             &surface);
2611
0
  if (likely (status == CAIRO_STATUS_SUCCESS) && unscaled->have_shape) {
2612
0
      status = _transform_glyph_bitmap (&unscaled->current_shape,
2613
0
                &surface);
2614
0
      if (unlikely (status))
2615
0
    cairo_surface_destroy (&surface->base);
2616
0
  }
2617
0
    }
2618
2619
44.5k
    if (unlikely (status))
2620
0
  return status;
2621
2622
44.5k
    if (info == CAIRO_SCALED_GLYPH_INFO_COLOR_SURFACE) {
2623
  /* We tried loading a color glyph and can now check if we got
2624
   * a color glyph and set scaled_glyph->color_glyph
2625
   * accordingly */
2626
0
  if (pixman_image_get_format (surface->pixman_image) == PIXMAN_a8r8g8b8 &&
2627
0
      !pixman_image_get_component_alpha (surface->pixman_image))
2628
0
  {
2629
0
      _cairo_scaled_glyph_set_color_surface (scaled_glyph,
2630
0
               &scaled_font->base,
2631
0
               surface,
2632
0
               uses_foreground_color ? foreground_color : NULL);
2633
2634
0
      scaled_glyph->color_glyph = TRUE;
2635
0
  } else {
2636
      /* We didn't ask for a non-color surface, but store it
2637
       * anyway so we don't have to load it again. */
2638
0
      _cairo_scaled_glyph_set_surface (scaled_glyph,
2639
0
               &scaled_font->base,
2640
0
               surface);
2641
0
      scaled_glyph->color_glyph = FALSE;
2642
0
      status = CAIRO_INT_STATUS_UNSUPPORTED;
2643
0
  }
2644
0
  scaled_glyph->color_glyph_set = TRUE;
2645
44.5k
    } else { /* info == CAIRO_SCALED_GLYPH_INFO_SURFACE */
2646
44.5k
  _cairo_scaled_glyph_set_surface (scaled_glyph,
2647
44.5k
           &scaled_font->base,
2648
44.5k
           surface);
2649
44.5k
    }
2650
2651
44.5k
    return status;
2652
44.5k
}
2653
2654
static cairo_int_status_t
2655
_cairo_ft_scaled_glyph_init_record_colr_v0_glyph (cairo_ft_scaled_font_t *scaled_font,
2656
              cairo_scaled_glyph_t   *scaled_glyph,
2657
              FT_Face                 face,
2658
              cairo_bool_t            vertical_layout,
2659
              int                     load_flags)
2660
0
{
2661
0
    cairo_surface_t *recording_surface;
2662
0
    cairo_t *cr;
2663
0
    cairo_status_t status;
2664
0
    FT_Color *palette;
2665
0
    unsigned int num_palette_entries;
2666
0
    FT_LayerIterator iterator;
2667
0
    FT_UInt layer_glyph_index;
2668
0
    FT_UInt layer_color_index;
2669
0
    cairo_path_fixed_t *path_fixed;
2670
0
    cairo_path_t *path;
2671
2672
0
    _cairo_ft_scaled_glyph_set_palette (scaled_font, face, &num_palette_entries, &palette);
2673
2674
0
    load_flags &= ~FT_LOAD_MONOCHROME;
2675
    /* clear load target mode */
2676
0
    load_flags &= ~(FT_LOAD_TARGET_(FT_LOAD_TARGET_MODE(load_flags)));
2677
0
    load_flags |= FT_LOAD_TARGET_NORMAL;
2678
0
    load_flags |= FT_LOAD_COLOR;
2679
2680
0
    recording_surface =
2681
0
  cairo_recording_surface_create (CAIRO_CONTENT_COLOR_ALPHA, NULL);
2682
2683
0
    cr = cairo_create (recording_surface);
2684
2685
0
    if (!_cairo_matrix_is_scale_0 (&scaled_font->base.scale)) {
2686
0
        cairo_matrix_t scale;
2687
0
  scale = scaled_font->base.scale;
2688
0
  scale.x0 = scale.y0 = 0.;
2689
0
  cairo_set_matrix (cr, &scale);
2690
0
    }
2691
2692
0
    iterator.p  = NULL;
2693
0
    while (FT_Get_Color_Glyph_Layer(face,
2694
0
            _cairo_scaled_glyph_index (scaled_glyph),
2695
0
            &layer_glyph_index,
2696
0
            &layer_color_index,
2697
0
            &iterator))
2698
0
    {
2699
0
  cairo_pattern_t *pattern;
2700
0
  if (layer_color_index == 0xFFFF) {
2701
0
      pattern = _cairo_pattern_create_foreground_marker ();
2702
0
  } else {
2703
0
      double r = 0, g = 0, b = 0, a = 1;
2704
0
      if (layer_color_index <  num_palette_entries) {
2705
0
    FT_Color *color = &palette[layer_color_index];
2706
0
    r = color->red / 255.0;
2707
0
    g = color->green/ 255.0;
2708
0
    b = color->blue / 255.0;
2709
0
    a = color->alpha / 255.0;
2710
0
      }
2711
0
      pattern = cairo_pattern_create_rgba (r, g, b, a);
2712
0
  }
2713
0
  cairo_set_source (cr, pattern);
2714
0
  cairo_pattern_destroy (pattern);
2715
2716
0
  if (FT_Load_Glyph (face, layer_glyph_index, load_flags) != 0) {
2717
0
      status = CAIRO_INT_STATUS_UNSUPPORTED;
2718
0
      goto cleanup;
2719
0
  }
2720
2721
0
  status = _cairo_ft_face_decompose_glyph_outline (face, &path_fixed);
2722
0
  if (unlikely (status))
2723
0
      return status;
2724
2725
0
  path = _cairo_path_create (path_fixed, cr);
2726
0
  _cairo_path_fixed_destroy (path_fixed);
2727
0
  cairo_append_path(cr, path);
2728
0
  cairo_path_destroy (path);
2729
0
  cairo_fill (cr);
2730
0
    }
2731
2732
0
  cleanup:
2733
0
    cairo_destroy (cr);
2734
2735
0
    if (status) {
2736
0
  cairo_surface_destroy (recording_surface);
2737
0
  return status;
2738
0
    }
2739
2740
0
    _cairo_scaled_glyph_set_recording_surface (scaled_glyph,
2741
0
                 &scaled_font->base,
2742
0
                 recording_surface,
2743
0
                 NULL);
2744
0
    return status;
2745
0
}
2746
2747
static cairo_int_status_t
2748
_cairo_ft_scaled_glyph_init_record_colr_v1_glyph (cairo_ft_scaled_font_t *scaled_font,
2749
              cairo_scaled_glyph_t   *scaled_glyph,
2750
              FT_Face                 face,
2751
              const cairo_color_t    *foreground_color,
2752
              cairo_text_extents_t   *extents)
2753
0
{
2754
0
#if HAVE_FT_COLR_V1
2755
0
    cairo_status_t status = CAIRO_STATUS_SUCCESS;
2756
0
    cairo_surface_t *recording_surface;
2757
0
    cairo_t *cr;
2758
0
    FT_Color *palette;
2759
0
    unsigned int num_palette_entries;
2760
0
    cairo_bool_t foreground_source_used = FALSE;
2761
2762
0
    recording_surface =
2763
0
  cairo_recording_surface_create (CAIRO_CONTENT_COLOR_ALPHA, NULL);
2764
2765
0
    cairo_surface_set_device_scale (recording_surface, 1, -1);
2766
2767
0
    cr = cairo_create (recording_surface);
2768
2769
0
    cairo_set_font_size (cr, 1.0);
2770
0
    cairo_set_font_options (cr, &scaled_font->base.options);
2771
2772
0
    extents->x_bearing = DOUBLE_FROM_26_6(face->bbox.xMin);
2773
0
    extents->y_bearing = DOUBLE_FROM_26_6(face->bbox.yMin);
2774
0
    extents->width = DOUBLE_FROM_26_6(face->bbox.xMax) - extents->x_bearing;
2775
0
    extents->height = DOUBLE_FROM_26_6(face->bbox.yMax) - extents->y_bearing;
2776
2777
0
    _cairo_ft_scaled_glyph_set_palette (scaled_font, face, &num_palette_entries, &palette);
2778
2779
0
    if (!_cairo_matrix_is_scale_0 (&scaled_font->base.scale)) {
2780
0
  cairo_pattern_t *foreground_pattern = _cairo_pattern_create_solid (foreground_color);
2781
0
  status = _cairo_render_colr_v1_glyph (face,
2782
0
                _cairo_scaled_glyph_index (scaled_glyph),
2783
0
                                              palette,
2784
0
                                              num_palette_entries,
2785
0
                cr,
2786
0
                foreground_pattern,
2787
0
                &foreground_source_used);
2788
0
  cairo_pattern_destroy (foreground_pattern);
2789
0
  if (status == CAIRO_STATUS_SUCCESS)
2790
0
      status = cairo_status (cr);
2791
0
    }
2792
2793
0
    cairo_destroy (cr);
2794
2795
0
    if (status) {
2796
0
  cairo_surface_destroy (recording_surface);
2797
0
  scaled_glyph->color_glyph = FALSE;
2798
0
  scaled_glyph->color_glyph_set = TRUE;
2799
0
  return status;
2800
0
    }
2801
2802
0
    _cairo_scaled_glyph_set_recording_surface (scaled_glyph,
2803
0
                 &scaled_font->base,
2804
0
                 recording_surface,
2805
0
                 foreground_source_used ? foreground_color : NULL);
2806
2807
0
    scaled_glyph->color_glyph = TRUE;
2808
0
    scaled_glyph->color_glyph_set = TRUE;
2809
2810
    /* get metrics */
2811
2812
    /* Copied from cairo-user-font.c */
2813
0
    cairo_matrix_t extent_scale;
2814
0
    double extent_x_scale = 1.0;
2815
0
    double extent_y_scale = 1.0;
2816
0
    double snap_x_scale;
2817
0
    double snap_y_scale;
2818
0
    double fixed_scale, x_scale, y_scale;
2819
2820
0
    extent_scale = scaled_font->base.scale_inverse;
2821
0
    snap_x_scale = 1.0;
2822
0
    snap_y_scale = 1.0;
2823
0
    status = _cairo_matrix_compute_basis_scale_factors (&extent_scale,
2824
0
              &x_scale, &y_scale,
2825
0
              1);
2826
0
    if (status == CAIRO_STATUS_SUCCESS) {
2827
0
  if (x_scale == 0)
2828
0
      x_scale = 1;
2829
0
  if (y_scale == 0)
2830
0
      y_scale = 1;
2831
2832
0
  snap_x_scale = x_scale;
2833
0
  snap_y_scale = y_scale;
2834
2835
  /* since glyphs are pretty much 1.0x1.0, we can reduce error by
2836
   * scaling to a larger square.  say, 1024.x1024. */
2837
0
  fixed_scale = 1024;
2838
0
  x_scale /= fixed_scale;
2839
0
  y_scale /= fixed_scale;
2840
2841
0
  cairo_matrix_scale (&extent_scale, 1.0 / x_scale, 1.0 / y_scale);
2842
2843
0
  extent_x_scale = x_scale;
2844
0
  extent_y_scale = y_scale;
2845
0
    }
2846
2847
0
    {
2848
  /* compute width / height */
2849
0
  cairo_box_t bbox;
2850
0
  double x1, y1, x2, y2;
2851
0
  double x_scale, y_scale;
2852
2853
  /* Compute extents.x/y/width/height from recording_surface,
2854
   * in font space.
2855
   */
2856
0
  status = _cairo_recording_surface_get_bbox ((cairo_recording_surface_t *) recording_surface,
2857
0
                &bbox,
2858
0
                &extent_scale);
2859
0
  if (unlikely (status))
2860
0
      return status;
2861
2862
0
  _cairo_box_to_doubles (&bbox, &x1, &y1, &x2, &y2);
2863
2864
0
  x_scale = extent_x_scale;
2865
0
  y_scale = extent_y_scale;
2866
0
  extents->x_bearing = x1 * x_scale;
2867
0
  extents->y_bearing = y1 * y_scale;
2868
0
  extents->width     = (x2 - x1) * x_scale;
2869
0
  extents->height    = (y2 - y1) * y_scale;
2870
0
    }
2871
2872
0
    if (scaled_font->base.options.hint_metrics != CAIRO_HINT_METRICS_OFF) {
2873
0
  extents->x_advance = _cairo_lround (extents->x_advance / snap_x_scale) * snap_x_scale;
2874
0
  extents->y_advance = _cairo_lround (extents->y_advance / snap_y_scale) * snap_y_scale;
2875
0
    }
2876
2877
0
    return status;
2878
#else
2879
    return CAIRO_INT_STATUS_UNSUPPORTED;
2880
#endif
2881
0
}
2882
2883
static cairo_int_status_t
2884
_cairo_ft_scaled_glyph_init_record_svg_glyph (cairo_ft_scaled_font_t *scaled_font,
2885
                cairo_scaled_glyph_t   *scaled_glyph,
2886
                FT_Face                 face,
2887
                const cairo_color_t    *foreground_color,
2888
                cairo_text_extents_t   *extents)
2889
0
{
2890
0
#if HAVE_FT_SVG_DOCUMENT
2891
0
    cairo_status_t status = CAIRO_STATUS_SUCCESS;
2892
0
    cairo_surface_t *recording_surface;
2893
0
    cairo_t *cr;
2894
0
    FT_SVG_Document svg_doc = face->glyph->other;
2895
0
    char *svg_document;
2896
0
    FT_Color *palette;
2897
0
    unsigned int num_palette_entries;
2898
0
    cairo_bool_t foreground_source_used = FALSE;
2899
2900
    /* Create NULL terminated SVG document */
2901
0
    svg_document = _cairo_strndup ((const char*)svg_doc->svg_document, svg_doc->svg_document_length);
2902
2903
0
    recording_surface =
2904
0
  cairo_recording_surface_create (CAIRO_CONTENT_COLOR_ALPHA, NULL);
2905
2906
0
    cr = cairo_create (recording_surface);
2907
2908
0
    if (!_cairo_matrix_is_scale_0 (&scaled_font->base.scale)) {
2909
0
        cairo_matrix_t scale;
2910
0
  scale = scaled_font->base.scale;
2911
0
  scale.x0 = scale.y0 = 0.;
2912
0
  cairo_set_matrix (cr, &scale);
2913
0
    }
2914
2915
0
    cairo_set_font_size (cr, 1.0);
2916
0
    cairo_set_font_options (cr, &scaled_font->base.options);
2917
2918
0
    extents->x_bearing = DOUBLE_FROM_26_6(face->bbox.xMin);
2919
0
    extents->y_bearing = DOUBLE_FROM_26_6(face->bbox.yMin);
2920
0
    extents->width = DOUBLE_FROM_26_6(face->bbox.xMax) - extents->x_bearing;
2921
0
    extents->height = DOUBLE_FROM_26_6(face->bbox.yMax) - extents->y_bearing;
2922
2923
0
    _cairo_ft_scaled_glyph_set_palette (scaled_font, face, &num_palette_entries, &palette);
2924
2925
0
    if (!_cairo_matrix_is_scale_0 (&scaled_font->base.scale)) {
2926
0
  cairo_pattern_t *foreground_pattern = _cairo_pattern_create_solid (foreground_color);
2927
0
  status = _cairo_render_svg_glyph (svg_document,
2928
0
            svg_doc->start_glyph_id,
2929
0
            svg_doc->end_glyph_id,
2930
0
            _cairo_scaled_glyph_index(scaled_glyph),
2931
0
            svg_doc->units_per_EM,
2932
0
            palette,
2933
0
            num_palette_entries,
2934
0
            cr,
2935
0
            foreground_pattern,
2936
0
            &foreground_source_used);
2937
0
  cairo_pattern_destroy (foreground_pattern);
2938
0
  if (status == CAIRO_STATUS_SUCCESS)
2939
0
      status = cairo_status (cr);
2940
0
    }
2941
2942
0
    cairo_destroy (cr);
2943
0
    free (svg_document);
2944
2945
0
    if (status) {
2946
0
  cairo_surface_destroy (recording_surface);
2947
0
  scaled_glyph->color_glyph = FALSE;
2948
0
  scaled_glyph->color_glyph_set = TRUE;
2949
0
  return status;
2950
0
    }
2951
2952
0
    _cairo_scaled_glyph_set_recording_surface (scaled_glyph,
2953
0
                 &scaled_font->base,
2954
0
                 recording_surface,
2955
0
                 foreground_source_used ? foreground_color : NULL);
2956
2957
0
    scaled_glyph->color_glyph = TRUE;
2958
0
    scaled_glyph->color_glyph_set = TRUE;
2959
2960
    /* get metrics */
2961
2962
    /* Copied from cairo-user-font.c */
2963
0
    cairo_matrix_t extent_scale;
2964
0
    double extent_x_scale;
2965
0
    double extent_y_scale;
2966
0
    double snap_x_scale;
2967
0
    double snap_y_scale;
2968
0
    double fixed_scale, x_scale, y_scale;
2969
2970
0
    extent_scale = scaled_font->base.scale_inverse;
2971
0
    snap_x_scale = 1.0;
2972
0
    snap_y_scale = 1.0;
2973
0
    status = _cairo_matrix_compute_basis_scale_factors (&extent_scale,
2974
0
              &x_scale, &y_scale,
2975
0
              1);
2976
0
    if (status == CAIRO_STATUS_SUCCESS) {
2977
0
  if (x_scale == 0)
2978
0
      x_scale = 1;
2979
0
  if (y_scale == 0)
2980
0
      y_scale = 1;
2981
2982
0
  snap_x_scale = x_scale;
2983
0
  snap_y_scale = y_scale;
2984
2985
  /* since glyphs are pretty much 1.0x1.0, we can reduce error by
2986
   * scaling to a larger square.  say, 1024.x1024. */
2987
0
  fixed_scale = 1024;
2988
0
  x_scale /= fixed_scale;
2989
0
  y_scale /= fixed_scale;
2990
2991
0
  cairo_matrix_scale (&extent_scale, 1.0 / x_scale, 1.0 / y_scale);
2992
2993
0
  extent_x_scale = x_scale;
2994
0
  extent_y_scale = y_scale;
2995
0
    }
2996
2997
0
    {
2998
  /* compute width / height */
2999
0
  cairo_box_t bbox;
3000
0
  double x1, y1, x2, y2;
3001
0
  double x_scale, y_scale;
3002
3003
  /* Compute extents.x/y/width/height from recording_surface,
3004
   * in font space.
3005
   */
3006
0
  status = _cairo_recording_surface_get_bbox ((cairo_recording_surface_t *) recording_surface,
3007
0
                &bbox,
3008
0
                &extent_scale);
3009
0
  if (unlikely (status))
3010
0
      return status;
3011
3012
0
  _cairo_box_to_doubles (&bbox, &x1, &y1, &x2, &y2);
3013
3014
0
  x_scale = extent_x_scale;
3015
0
  y_scale = extent_y_scale;
3016
0
  extents->x_bearing = x1 * x_scale;
3017
0
  extents->y_bearing = y1 * y_scale;
3018
0
  extents->width     = (x2 - x1) * x_scale;
3019
0
  extents->height    = (y2 - y1) * y_scale;
3020
0
    }
3021
3022
0
    if (scaled_font->base.options.hint_metrics != CAIRO_HINT_METRICS_OFF) {
3023
0
  extents->x_advance = _cairo_lround (extents->x_advance / snap_x_scale) * snap_x_scale;
3024
0
  extents->y_advance = _cairo_lround (extents->y_advance / snap_y_scale) * snap_y_scale;
3025
0
    }
3026
3027
0
    return status;
3028
#else
3029
    return CAIRO_INT_STATUS_UNSUPPORTED;
3030
#endif
3031
0
}
3032
3033
static cairo_int_status_t
3034
_cairo_ft_scaled_glyph_init_surface_for_recording_surface (cairo_ft_scaled_font_t *scaled_font,
3035
                 cairo_scaled_glyph_t   *scaled_glyph,
3036
                 const cairo_color_t    *foreground_color)
3037
0
{
3038
0
    cairo_surface_t *surface;
3039
0
    int width, height;
3040
0
    cairo_int_status_t status = CAIRO_STATUS_SUCCESS;
3041
0
    cairo_bool_t foreground_used;
3042
3043
0
    width = _cairo_fixed_integer_ceil (scaled_glyph->bbox.p2.x) -
3044
0
  _cairo_fixed_integer_floor (scaled_glyph->bbox.p1.x);
3045
0
    height = _cairo_fixed_integer_ceil (scaled_glyph->bbox.p2.y) -
3046
0
  _cairo_fixed_integer_floor (scaled_glyph->bbox.p1.y);
3047
3048
0
    surface = cairo_image_surface_create (CAIRO_FORMAT_ARGB32, width, height);
3049
3050
0
    cairo_surface_set_device_offset (surface,
3051
0
             - _cairo_fixed_integer_floor (scaled_glyph->bbox.p1.x),
3052
0
             - _cairo_fixed_integer_floor (scaled_glyph->bbox.p1.y));
3053
3054
0
    status = _cairo_recording_surface_replay_with_foreground_color (scaled_glyph->recording_surface,
3055
0
                    surface,
3056
0
                    foreground_color,
3057
0
                    &foreground_used);
3058
0
    if (unlikely (status)) {
3059
0
  cairo_surface_destroy(surface);
3060
0
  return status;
3061
0
    }
3062
3063
0
    _cairo_scaled_glyph_set_color_surface (scaled_glyph,
3064
0
             &scaled_font->base,
3065
0
             (cairo_image_surface_t *)surface,
3066
0
             foreground_used ? foreground_color : NULL);
3067
0
    surface = NULL;
3068
3069
0
    if (surface)
3070
0
  cairo_surface_destroy (surface);
3071
3072
0
    return status;
3073
0
}
3074
3075
static void
3076
_cairo_ft_scaled_glyph_get_metrics (cairo_ft_scaled_font_t     *scaled_font,
3077
            FT_Face face,
3078
            cairo_bool_t vertical_layout,
3079
            int load_flags,
3080
            cairo_text_extents_t *fs_metrics)
3081
60.6k
{
3082
60.6k
    FT_Glyph_Metrics *metrics;
3083
60.6k
    cairo_ft_unscaled_font_t *unscaled = scaled_font->unscaled;
3084
60.6k
    cairo_bool_t hint_metrics = scaled_font->base.options.hint_metrics != CAIRO_HINT_METRICS_OFF;
3085
60.6k
    FT_GlyphSlot glyph = face->glyph;
3086
3087
    /*
3088
     * Compute font-space metrics
3089
     */
3090
60.6k
    metrics = &glyph->metrics;
3091
3092
    /*
3093
     * Note: Y coordinates of the horizontal bearing need to be negated.
3094
     *
3095
     * Scale metrics back to glyph space from the scaled glyph space returned
3096
     * by FreeType
3097
     *
3098
     * If we want hinted metrics but aren't asking for hinted glyphs from
3099
     * FreeType, then we need to do the metric hinting ourselves.
3100
     */
3101
3102
60.6k
    if (hint_metrics && (load_flags & FT_LOAD_NO_HINTING))
3103
0
    {
3104
0
  FT_Pos x1, x2;
3105
0
  FT_Pos y1, y2;
3106
0
  FT_Pos advance;
3107
3108
0
  if (!vertical_layout) {
3109
0
      x1 = (metrics->horiBearingX) & -64;
3110
0
      x2 = (metrics->horiBearingX + metrics->width + 63) & -64;
3111
0
      y1 = (-metrics->horiBearingY) & -64;
3112
0
      y2 = (-metrics->horiBearingY + metrics->height + 63) & -64;
3113
3114
0
      advance = ((metrics->horiAdvance + 32) & -64);
3115
3116
0
      fs_metrics->x_bearing = SCALE (DOUBLE_FROM_26_6 (x1), unscaled->x_scale);
3117
0
      fs_metrics->y_bearing = SCALE (DOUBLE_FROM_26_6 (y1), unscaled->y_scale);
3118
3119
0
      fs_metrics->width  = SCALE (DOUBLE_FROM_26_6 (x2 - x1), unscaled->x_scale);
3120
0
      fs_metrics->height  = SCALE (DOUBLE_FROM_26_6 (y2 - y1), unscaled->y_scale);
3121
3122
0
      fs_metrics->x_advance = SCALE (DOUBLE_FROM_26_6 (advance), unscaled->x_scale);
3123
0
      fs_metrics->y_advance = 0;
3124
0
  } else {
3125
0
      x1 = (metrics->vertBearingX) & -64;
3126
0
      x2 = (metrics->vertBearingX + metrics->width + 63) & -64;
3127
0
      y1 = (metrics->vertBearingY) & -64;
3128
0
      y2 = (metrics->vertBearingY + metrics->height + 63) & -64;
3129
3130
0
      advance = ((metrics->vertAdvance + 32) & -64);
3131
3132
0
      fs_metrics->x_bearing = SCALE (DOUBLE_FROM_26_6 (x1), unscaled->x_scale);
3133
0
      fs_metrics->y_bearing = SCALE (DOUBLE_FROM_26_6 (y1), unscaled->y_scale);
3134
3135
0
      fs_metrics->width  = SCALE (DOUBLE_FROM_26_6 (x2 - x1), unscaled->x_scale);
3136
0
      fs_metrics->height  = SCALE (DOUBLE_FROM_26_6 (y2 - y1), unscaled->y_scale);
3137
3138
0
      fs_metrics->x_advance = 0;
3139
0
      fs_metrics->y_advance = SCALE (DOUBLE_FROM_26_6 (advance), unscaled->y_scale);
3140
0
  }
3141
60.6k
    } else {
3142
60.6k
  fs_metrics->width  = SCALE (DOUBLE_FROM_26_6 (metrics->width), unscaled->x_scale);
3143
60.6k
  fs_metrics->height = SCALE (DOUBLE_FROM_26_6 (metrics->height), unscaled->y_scale);
3144
3145
60.6k
  if (!vertical_layout) {
3146
60.6k
      fs_metrics->x_bearing = SCALE (DOUBLE_FROM_26_6 (metrics->horiBearingX), unscaled->x_scale);
3147
60.6k
      fs_metrics->y_bearing = SCALE (DOUBLE_FROM_26_6 (-metrics->horiBearingY), unscaled->y_scale);
3148
3149
60.6k
      if (hint_metrics || glyph->format != FT_GLYPH_FORMAT_OUTLINE)
3150
4.97k
    fs_metrics->x_advance = SCALE (DOUBLE_FROM_26_6 (metrics->horiAdvance), unscaled->x_scale);
3151
55.6k
      else
3152
55.6k
    fs_metrics->x_advance = SCALE (DOUBLE_FROM_16_16 (glyph->linearHoriAdvance), unscaled->x_scale);
3153
60.6k
      fs_metrics->y_advance = 0;
3154
60.6k
  } else {
3155
0
      fs_metrics->x_bearing = SCALE (DOUBLE_FROM_26_6 (metrics->vertBearingX), unscaled->x_scale);
3156
0
      fs_metrics->y_bearing = SCALE (DOUBLE_FROM_26_6 (metrics->vertBearingY), unscaled->y_scale);
3157
3158
0
      fs_metrics->x_advance = 0;
3159
0
      if (hint_metrics || glyph->format != FT_GLYPH_FORMAT_OUTLINE)
3160
0
    fs_metrics->y_advance = SCALE (DOUBLE_FROM_26_6 (metrics->vertAdvance), unscaled->y_scale);
3161
0
      else
3162
0
    fs_metrics->y_advance = SCALE (DOUBLE_FROM_16_16 (glyph->linearVertAdvance), unscaled->y_scale);
3163
0
  }
3164
60.6k
    }
3165
60.6k
}
3166
3167
static cairo_bool_t
3168
_cairo_ft_scaled_glyph_is_colr_v0 (cairo_ft_scaled_font_t *scaled_font,
3169
           cairo_scaled_glyph_t   *scaled_glyph,
3170
           FT_Face                 face)
3171
0
{
3172
0
    FT_LayerIterator  iterator;
3173
0
    FT_UInt layer_glyph_index;
3174
0
    FT_UInt layer_color_index;
3175
3176
0
    iterator.p  = NULL;
3177
0
    if (FT_Get_Color_Glyph_Layer(face,
3178
0
                                 _cairo_scaled_glyph_index (scaled_glyph),
3179
0
                                 &layer_glyph_index,
3180
0
                                 &layer_color_index,
3181
0
         &iterator) == 1)
3182
0
    {
3183
0
  return TRUE;
3184
0
    }
3185
3186
0
    return FALSE;
3187
0
}
3188
3189
static cairo_bool_t
3190
_cairo_ft_scaled_glyph_is_colr_v1 (cairo_ft_scaled_font_t *scaled_font,
3191
           cairo_scaled_glyph_t   *scaled_glyph,
3192
           FT_Face                 face)
3193
0
{
3194
0
#if HAVE_FT_COLR_V1
3195
0
    FT_OpaquePaint paint = { NULL, 0 };
3196
3197
0
    if (FT_Get_Color_Glyph_Paint (face,
3198
0
          _cairo_scaled_glyph_index (scaled_glyph),
3199
0
          FT_COLOR_INCLUDE_ROOT_TRANSFORM,
3200
0
          &paint) == 1)
3201
0
    {
3202
0
  return TRUE;
3203
0
    }
3204
0
#endif
3205
0
    return FALSE;
3206
0
}
3207
3208
static cairo_int_status_t
3209
_cairo_ft_scaled_glyph_init_metrics (cairo_ft_scaled_font_t  *scaled_font,
3210
             cairo_scaled_glyph_t    *scaled_glyph,
3211
             FT_Face                  face,
3212
             cairo_bool_t             vertical_layout,
3213
             int                      load_flags,
3214
             const cairo_color_t     *foreground_color)
3215
60.6k
{
3216
60.6k
    cairo_int_status_t status = CAIRO_INT_STATUS_SUCCESS;
3217
60.6k
    cairo_text_extents_t fs_metrics;
3218
60.6k
    cairo_ft_glyph_private_t *glyph_priv;
3219
3220
60.6k
    cairo_bool_t hint_metrics = scaled_font->base.options.hint_metrics != CAIRO_HINT_METRICS_OFF;
3221
3222
    /* _cairo_ft_scaled_glyph_init_metrics() is called once the first
3223
     * time a cairo_scaled_glyph_t is created. We first allocate the
3224
     * cairo_ft_glyph_private_t struct and determine the glyph type.
3225
     */
3226
3227
60.6k
    glyph_priv = _cairo_calloc (sizeof (*glyph_priv));
3228
60.6k
    if (unlikely (glyph_priv == NULL))
3229
0
  return _cairo_error (CAIRO_STATUS_NO_MEMORY);
3230
3231
60.6k
    _cairo_scaled_glyph_attach_private (scaled_glyph, &glyph_priv->base,
3232
60.6k
          &ft_glyph_private_key,
3233
60.6k
          _cairo_ft_glyph_fini);
3234
3235
    /* We need to load color to determine if this is a color format. */
3236
60.6k
    int color_flag = 0;
3237
3238
60.6k
    if (scaled_font->unscaled->have_color && scaled_font->base.options.color_mode != CAIRO_COLOR_MODE_NO_COLOR)
3239
0
  color_flag = FT_LOAD_COLOR;
3240
3241
    /* Ensure use_em_size = FALSE as the format (bitmap or outline)
3242
     * may change with the size. */
3243
60.6k
    status = _cairo_ft_scaled_glyph_load_glyph (scaled_font,
3244
60.6k
            scaled_glyph,
3245
60.6k
            face,
3246
60.6k
            load_flags | color_flag,
3247
60.6k
            FALSE,
3248
60.6k
            vertical_layout);
3249
60.6k
    if (unlikely (status))
3250
0
  return status;
3251
3252
60.6k
    cairo_bool_t is_svg_format = FALSE;
3253
60.6k
#if HAVE_FT_SVG_DOCUMENT
3254
60.6k
    if (face->glyph->format == FT_GLYPH_FORMAT_SVG)
3255
0
  is_svg_format = TRUE;
3256
60.6k
#endif
3257
3258
60.6k
    if (is_svg_format) {
3259
0
        glyph_priv->format = CAIRO_FT_GLYPH_TYPE_SVG;
3260
3261
0
#if defined(HAVE_FT_COLR_V1) && defined(HAVE_FT_LOAD_NO_SVG)
3262
        /* Prefer COLRv1 table over SVG table due to performance reasons for now */
3263
0
        if (_cairo_ft_scaled_glyph_is_colr_v1 (scaled_font, scaled_glyph, face)) {
3264
0
            glyph_priv->format = CAIRO_FT_GLYPH_TYPE_COLR_V1;
3265
0
        }
3266
0
#endif
3267
3268
60.6k
    } else if (face->glyph->format == FT_GLYPH_FORMAT_OUTLINE) {
3269
60.6k
  glyph_priv->format = CAIRO_FT_GLYPH_TYPE_OUTLINE;
3270
60.6k
  if (color_flag) {
3271
0
      if (_cairo_ft_scaled_glyph_is_colr_v1 (scaled_font, scaled_glyph, face))
3272
0
    glyph_priv->format = CAIRO_FT_GLYPH_TYPE_COLR_V1;
3273
0
      else if (_cairo_ft_scaled_glyph_is_colr_v0 (scaled_font, scaled_glyph, face))
3274
0
    glyph_priv->format = CAIRO_FT_GLYPH_TYPE_COLR_V0;
3275
0
  }
3276
60.6k
    } else {
3277
  /* For anything else we let FreeType render a bitmap. */
3278
0
   glyph_priv->format =  CAIRO_FT_GLYPH_TYPE_BITMAP;
3279
0
    }
3280
3281
    /* If hinting is off, load the glyph with font size set the the em size. */
3282
60.6k
    if (!hint_metrics) {
3283
55.6k
  status = _cairo_ft_scaled_glyph_load_glyph (scaled_font,
3284
55.6k
                scaled_glyph,
3285
55.6k
                face,
3286
55.6k
                load_flags | color_flag,
3287
55.6k
                TRUE,
3288
55.6k
                vertical_layout);
3289
55.6k
  if (unlikely (status))
3290
0
      return status;
3291
55.6k
    }
3292
3293
60.6k
    _cairo_ft_scaled_glyph_get_metrics (scaled_font,
3294
60.6k
          face,
3295
60.6k
          vertical_layout,
3296
60.6k
          load_flags,
3297
60.6k
          &fs_metrics);
3298
3299
3300
    /* SVG and COLRv1 glyphs require the bounding box to be obtained
3301
     * from the ink extents of the rendering. We need to render glyph
3302
     * to a recording surface to obtain these extents. But we also
3303
     * need the advance from _cairo_ft_scaled_glyph_get_metrics()
3304
     * before calling this function.
3305
     */
3306
3307
60.6k
    if (glyph_priv->format == CAIRO_FT_GLYPH_TYPE_SVG) {
3308
0
  status = (cairo_int_status_t)_cairo_ft_scaled_glyph_init_record_svg_glyph (scaled_font,
3309
0
                       scaled_glyph,
3310
0
                       face,
3311
0
                       foreground_color,
3312
0
                       &fs_metrics);
3313
0
  if (unlikely (status))
3314
0
      return status;
3315
0
    }
3316
3317
60.6k
    if (glyph_priv->format == CAIRO_FT_GLYPH_TYPE_COLR_V1) {
3318
  /* Restore font size if previously loaded at em_size. */
3319
0
  if (!hint_metrics) {
3320
0
      status = _cairo_ft_scaled_glyph_load_glyph (scaled_font,
3321
0
              scaled_glyph,
3322
0
              face,
3323
0
              load_flags | color_flag,
3324
0
              FALSE,
3325
0
              vertical_layout);
3326
0
      if (unlikely (status))
3327
0
    return status;
3328
0
  }
3329
3330
0
  status = (cairo_int_status_t)_cairo_ft_scaled_glyph_init_record_colr_v1_glyph (scaled_font,
3331
0
                           scaled_glyph,
3332
0
                           face,
3333
0
                           foreground_color,
3334
0
                           &fs_metrics);
3335
0
  if (unlikely (status))
3336
0
      return status;
3337
0
    }
3338
3339
60.6k
    _cairo_scaled_glyph_set_metrics (scaled_glyph,
3340
60.6k
             &scaled_font->base,
3341
60.6k
             &fs_metrics);
3342
3343
60.6k
    return status;
3344
60.6k
}
3345
3346
static cairo_int_status_t
3347
_cairo_ft_scaled_glyph_init (void     *abstract_font,
3348
           cairo_scaled_glyph_t *scaled_glyph,
3349
           cairo_scaled_glyph_info_t   info,
3350
           const cairo_color_t        *foreground_color)
3351
73.0k
{
3352
73.0k
    cairo_ft_scaled_font_t *scaled_font = abstract_font;
3353
73.0k
    cairo_ft_unscaled_font_t *unscaled = scaled_font->unscaled;
3354
73.0k
    FT_Face face;
3355
73.0k
    int load_flags = scaled_font->ft_options.load_flags;
3356
73.0k
    cairo_bool_t vertical_layout = FALSE;
3357
73.0k
    cairo_status_t status = CAIRO_STATUS_SUCCESS;
3358
73.0k
    cairo_ft_glyph_private_t *glyph_priv;
3359
3360
73.0k
    face = _cairo_ft_unscaled_font_lock_face (unscaled);
3361
73.0k
    if (!face)
3362
0
  return _cairo_error (CAIRO_STATUS_NO_MEMORY);
3363
3364
    /* Ignore global advance unconditionally */
3365
73.0k
    load_flags |= FT_LOAD_IGNORE_GLOBAL_ADVANCE_WIDTH;
3366
3367
73.0k
    if ((info & CAIRO_SCALED_GLYPH_INFO_PATH) != 0 &&
3368
0
  (info & (CAIRO_SCALED_GLYPH_INFO_SURFACE |
3369
0
                 CAIRO_SCALED_GLYPH_INFO_COLOR_SURFACE)) == 0) {
3370
0
  load_flags |= FT_LOAD_NO_BITMAP;
3371
0
    }
3372
3373
    /*
3374
     * Don't pass FT_LOAD_VERTICAL_LAYOUT to FT_Load_Glyph here as
3375
     * suggested by freetype people.
3376
     */
3377
73.0k
    if (load_flags & FT_LOAD_VERTICAL_LAYOUT) {
3378
0
  load_flags &= ~FT_LOAD_VERTICAL_LAYOUT;
3379
0
  vertical_layout = TRUE;
3380
0
    }
3381
3382
    /* Metrics will always be requested when a scaled glyph is created */
3383
73.0k
    if (info & CAIRO_SCALED_GLYPH_INFO_METRICS) {
3384
60.6k
  status = _cairo_ft_scaled_glyph_init_metrics (scaled_font,
3385
60.6k
                  scaled_glyph,
3386
60.6k
                  face,
3387
60.6k
                  vertical_layout,
3388
60.6k
                  load_flags,
3389
60.6k
                  foreground_color);
3390
60.6k
  if (unlikely (status))
3391
0
      goto FAIL;
3392
60.6k
    }
3393
3394
73.0k
    glyph_priv = (cairo_ft_glyph_private_t *) _cairo_scaled_glyph_find_private (scaled_glyph,
3395
73.0k
                    &ft_glyph_private_key);
3396
73.0k
    assert (glyph_priv != NULL);
3397
3398
73.0k
    if (info & CAIRO_SCALED_GLYPH_INFO_RECORDING_SURFACE) {
3399
0
  status = CAIRO_INT_STATUS_UNSUPPORTED;
3400
0
  if (glyph_priv->format == CAIRO_FT_GLYPH_TYPE_SVG ||
3401
0
      glyph_priv->format == CAIRO_FT_GLYPH_TYPE_COLR_V0 ||
3402
0
      glyph_priv->format == CAIRO_FT_GLYPH_TYPE_COLR_V1)
3403
0
  {
3404
0
      status = _cairo_ft_scaled_glyph_load_glyph (scaled_font,
3405
0
              scaled_glyph,
3406
0
              face,
3407
0
              load_flags | FT_LOAD_COLOR,
3408
0
              FALSE,
3409
0
              vertical_layout);
3410
0
      if (unlikely (status))
3411
0
    goto FAIL;
3412
3413
0
      if (glyph_priv->format == CAIRO_FT_GLYPH_TYPE_SVG) {
3414
0
    status = _cairo_ft_scaled_glyph_init_record_svg_glyph (scaled_font,
3415
0
                       scaled_glyph,
3416
0
                       face,
3417
0
                       foreground_color,
3418
0
                       &scaled_glyph->fs_metrics);
3419
0
      } else if (glyph_priv->format == CAIRO_FT_GLYPH_TYPE_COLR_V1) {
3420
0
    status = _cairo_ft_scaled_glyph_init_record_colr_v1_glyph (scaled_font,
3421
0
                     scaled_glyph,
3422
0
                     face,
3423
0
                     foreground_color,
3424
0
                     &scaled_glyph->fs_metrics);
3425
0
      } else if (glyph_priv->format == CAIRO_FT_GLYPH_TYPE_COLR_V0) {
3426
0
    status = _cairo_ft_scaled_glyph_init_record_colr_v0_glyph (scaled_font,
3427
0
                     scaled_glyph,
3428
0
                     face,
3429
0
                     vertical_layout,
3430
0
                     load_flags);
3431
0
      }
3432
0
  }
3433
0
  if (status)
3434
0
      goto FAIL;
3435
0
    }
3436
3437
73.0k
    if ((info & CAIRO_SCALED_GLYPH_INFO_COLOR_SURFACE) && scaled_font->base.options.color_mode != CAIRO_COLOR_MODE_NO_COLOR) {
3438
0
  if (glyph_priv->format == CAIRO_FT_GLYPH_TYPE_SVG ||
3439
0
      glyph_priv->format == CAIRO_FT_GLYPH_TYPE_COLR_V1)
3440
0
  {
3441
0
      status = _cairo_ft_scaled_glyph_init_surface_for_recording_surface (scaled_font,
3442
0
                    scaled_glyph,
3443
0
                    foreground_color);
3444
0
  } else {
3445
0
      status = _cairo_ft_scaled_glyph_init_surface (scaled_font,
3446
0
                scaled_glyph,
3447
0
                glyph_priv,
3448
0
                CAIRO_SCALED_GLYPH_INFO_COLOR_SURFACE,
3449
0
                face,
3450
0
                foreground_color,
3451
0
                vertical_layout,
3452
0
                load_flags);
3453
0
  }
3454
0
  if (unlikely (status))
3455
0
      goto FAIL;
3456
0
    }
3457
3458
73.0k
    if (info & CAIRO_SCALED_GLYPH_INFO_SURFACE) {
3459
44.5k
  status = _cairo_ft_scaled_glyph_init_surface (scaled_font,
3460
44.5k
                  scaled_glyph,
3461
44.5k
                  glyph_priv,
3462
44.5k
                  CAIRO_SCALED_GLYPH_INFO_SURFACE,
3463
44.5k
                  face,
3464
44.5k
                  NULL, /* foreground color */
3465
44.5k
                  vertical_layout,
3466
44.5k
                  load_flags);
3467
44.5k
  if (unlikely (status))
3468
0
      goto FAIL;
3469
44.5k
    }
3470
3471
73.0k
    if (info & CAIRO_SCALED_GLYPH_INFO_PATH) {
3472
0
  cairo_path_fixed_t *path = NULL; /* hide compiler warning */
3473
3474
  /* Load non-color glyph */
3475
0
  status = _cairo_ft_scaled_glyph_load_glyph (scaled_font,
3476
0
                scaled_glyph,
3477
0
                face,
3478
0
                load_flags,
3479
0
                FALSE,
3480
0
                vertical_layout);
3481
0
  if (unlikely (status))
3482
0
      goto FAIL;
3483
3484
0
  if (face->glyph->format == FT_GLYPH_FORMAT_OUTLINE)
3485
0
      status = _cairo_ft_face_decompose_glyph_outline (face, &path);
3486
0
  else
3487
0
      status = CAIRO_INT_STATUS_UNSUPPORTED;
3488
3489
0
  if (unlikely (status))
3490
0
      goto FAIL;
3491
3492
0
  _cairo_scaled_glyph_set_path (scaled_glyph,
3493
0
              &scaled_font->base,
3494
0
              path);
3495
0
    }
3496
73.0k
 FAIL:
3497
73.0k
    _cairo_ft_unscaled_font_unlock_face (unscaled);
3498
3499
73.0k
    return status;
3500
73.0k
}
3501
3502
static unsigned long
3503
_cairo_ft_ucs4_to_index (void     *abstract_font,
3504
       uint32_t    ucs4)
3505
0
{
3506
0
    cairo_ft_scaled_font_t *scaled_font = abstract_font;
3507
0
    cairo_ft_unscaled_font_t *unscaled = scaled_font->unscaled;
3508
0
    FT_Face face;
3509
0
    FT_UInt index;
3510
3511
0
    face = _cairo_ft_unscaled_font_lock_face (unscaled);
3512
0
    if (!face)
3513
0
  return 0;
3514
3515
0
#if CAIRO_HAS_FC_FONT
3516
0
    index = FcFreeTypeCharIndex (face, ucs4);
3517
#else
3518
    index = FT_Get_Char_Index (face, ucs4);
3519
#endif
3520
3521
0
    _cairo_ft_unscaled_font_unlock_face (unscaled);
3522
0
    return index;
3523
0
}
3524
3525
static cairo_int_status_t
3526
_cairo_ft_load_truetype_table (void        *abstract_font,
3527
                              unsigned long     tag,
3528
                              long              offset,
3529
                              unsigned char    *buffer,
3530
                              unsigned long    *length)
3531
0
{
3532
0
    cairo_ft_scaled_font_t *scaled_font = abstract_font;
3533
0
    cairo_ft_unscaled_font_t *unscaled = scaled_font->unscaled;
3534
0
    FT_Face face;
3535
0
    cairo_status_t status = CAIRO_INT_STATUS_UNSUPPORTED;
3536
3537
    /* We don't support the FreeType feature of loading a table
3538
     * without specifying the size since this may overflow our
3539
     * buffer. */
3540
0
    assert (length != NULL);
3541
3542
0
    if (_cairo_ft_scaled_font_is_vertical (&scaled_font->base))
3543
0
        return CAIRO_INT_STATUS_UNSUPPORTED;
3544
3545
0
    face = _cairo_ft_unscaled_font_lock_face (unscaled);
3546
0
    if (!face)
3547
0
  return _cairo_error (CAIRO_STATUS_NO_MEMORY);
3548
3549
0
    if (FT_IS_SFNT (face)) {
3550
0
  if (buffer == NULL)
3551
0
      *length = 0;
3552
3553
0
  if (FT_Load_Sfnt_Table (face, tag, offset, buffer, length) == 0)
3554
0
      status = CAIRO_STATUS_SUCCESS;
3555
0
    }
3556
3557
0
    _cairo_ft_unscaled_font_unlock_face (unscaled);
3558
3559
0
    return status;
3560
0
}
3561
3562
static cairo_int_status_t
3563
_cairo_ft_index_to_ucs4(void          *abstract_font,
3564
      unsigned long    index,
3565
      uint32_t  *ucs4)
3566
0
{
3567
0
    cairo_ft_scaled_font_t *scaled_font = abstract_font;
3568
0
    cairo_ft_unscaled_font_t *unscaled = scaled_font->unscaled;
3569
0
    FT_Face face;
3570
0
    FT_ULong  charcode;
3571
0
    FT_UInt   gindex;
3572
3573
0
    face = _cairo_ft_unscaled_font_lock_face (unscaled);
3574
0
    if (!face)
3575
0
  return _cairo_error (CAIRO_STATUS_NO_MEMORY);
3576
3577
0
    *ucs4 = (uint32_t) -1;
3578
0
    charcode = FT_Get_First_Char(face, &gindex);
3579
0
    while (gindex != 0) {
3580
0
  if (gindex == index) {
3581
0
      *ucs4 = charcode;
3582
0
      break;
3583
0
  }
3584
0
  charcode = FT_Get_Next_Char (face, charcode, &gindex);
3585
0
    }
3586
3587
0
    _cairo_ft_unscaled_font_unlock_face (unscaled);
3588
3589
0
    return CAIRO_STATUS_SUCCESS;
3590
0
}
3591
3592
static cairo_int_status_t
3593
_cairo_ft_is_synthetic (void          *abstract_font,
3594
      cairo_bool_t    *is_synthetic)
3595
0
{
3596
0
    cairo_int_status_t status = CAIRO_STATUS_SUCCESS;
3597
0
    cairo_ft_scaled_font_t *scaled_font = abstract_font;
3598
0
    cairo_ft_unscaled_font_t *unscaled = scaled_font->unscaled;
3599
0
    FT_Face face;
3600
0
    FT_Error error;
3601
3602
0
    if (scaled_font->ft_options.synth_flags != 0) {
3603
0
  *is_synthetic = TRUE;
3604
0
  return status;
3605
0
    }
3606
3607
0
    *is_synthetic = FALSE;
3608
0
    face = _cairo_ft_unscaled_font_lock_face (unscaled);
3609
0
    if (!face)
3610
0
  return _cairo_error (CAIRO_STATUS_NO_MEMORY);
3611
3612
0
    if (face->face_flags & FT_FACE_FLAG_MULTIPLE_MASTERS) {
3613
0
  FT_MM_Var *mm_var = NULL;
3614
0
  FT_Fixed *coords = NULL;
3615
0
  int num_axis;
3616
0
  int i;
3617
3618
  /* If this is an MM or variable font we can't assume the current outlines
3619
   * are the same as the font tables */
3620
0
  *is_synthetic = TRUE;
3621
3622
0
  error = FT_Get_MM_Var (face, &mm_var);
3623
0
  if (error) {
3624
0
      status = _cairo_error (_cairo_ft_to_cairo_error (error));
3625
0
      goto cleanup;
3626
0
  }
3627
3628
0
  num_axis = mm_var->num_axis;
3629
0
  coords = _cairo_malloc_ab (num_axis, sizeof(FT_Fixed));
3630
0
  if (!coords) {
3631
0
      status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
3632
0
      goto cleanup;
3633
0
  }
3634
3635
  /* Check if the current design coordinates are the default
3636
   * coordinates. In this case the current outlines match the
3637
   * font tables.
3638
   */
3639
0
  FT_Get_Var_Blend_Coordinates (face, num_axis, coords);
3640
0
  *is_synthetic = FALSE;
3641
0
  for (i = 0; i < num_axis; i++) {
3642
0
      if (coords[i]) {
3643
0
    *is_synthetic = TRUE;
3644
0
    break;
3645
0
      }
3646
0
  }
3647
3648
0
      cleanup:
3649
0
  free (coords);
3650
0
  FT_Done_MM_Var (face->glyph->library, mm_var);
3651
0
    }
3652
3653
0
    _cairo_ft_unscaled_font_unlock_face (unscaled);
3654
3655
0
    return status;
3656
0
}
3657
3658
static cairo_int_status_t
3659
_cairo_index_to_glyph_name (void           *abstract_font,
3660
          char                **glyph_names,
3661
          int                   num_glyph_names,
3662
          unsigned long         glyph_index,
3663
          unsigned long        *glyph_array_index)
3664
0
{
3665
0
    cairo_ft_scaled_font_t *scaled_font = abstract_font;
3666
0
    cairo_ft_unscaled_font_t *unscaled = scaled_font->unscaled;
3667
0
    FT_Face face;
3668
0
    char buffer[256]; /* PLRM specifies max name length of 127 */
3669
0
    FT_Error error;
3670
0
    int i;
3671
3672
0
    face = _cairo_ft_unscaled_font_lock_face (unscaled);
3673
0
    if (!face)
3674
0
  return _cairo_error (CAIRO_STATUS_NO_MEMORY);
3675
3676
0
    error = FT_Get_Glyph_Name (face, glyph_index, buffer, sizeof buffer);
3677
3678
0
    _cairo_ft_unscaled_font_unlock_face (unscaled);
3679
3680
0
    if (error != FT_Err_Ok) {
3681
  /* propagate fatal errors from FreeType */
3682
0
  if (error == FT_Err_Out_Of_Memory)
3683
0
      return _cairo_error (CAIRO_STATUS_NO_MEMORY);
3684
3685
0
  return CAIRO_INT_STATUS_UNSUPPORTED;
3686
0
    }
3687
3688
    /* FT first numbers the glyphs in the order they are read from the
3689
     * Type 1 font. Then if .notdef is not the first glyph, the first
3690
     * glyph is swapped with .notdef to ensure that .notdef is at
3691
     * glyph index 0.
3692
     *
3693
     * As all but two glyphs in glyph_names already have the same
3694
     * index as the FT glyph index, we first check if
3695
     * glyph_names[glyph_index] is the name we are looking for. If not
3696
     * we fall back to searching the entire array.
3697
     */
3698
3699
0
    if ((long)glyph_index < num_glyph_names &&
3700
0
  strcmp (glyph_names[glyph_index], buffer) == 0)
3701
0
    {
3702
0
  *glyph_array_index = glyph_index;
3703
3704
0
  return CAIRO_STATUS_SUCCESS;
3705
0
    }
3706
3707
0
    for (i = 0; i < num_glyph_names; i++) {
3708
0
  if (strcmp (glyph_names[i], buffer) == 0) {
3709
0
      *glyph_array_index = i;
3710
3711
0
      return CAIRO_STATUS_SUCCESS;
3712
0
  }
3713
0
    }
3714
3715
0
    return CAIRO_INT_STATUS_UNSUPPORTED;
3716
0
}
3717
3718
static cairo_bool_t
3719
_ft_is_type1 (FT_Face face)
3720
0
{
3721
0
    const char *font_format = FT_Get_Font_Format (face);
3722
0
    if (font_format &&
3723
0
  (strcmp (font_format, "Type 1") == 0 ||
3724
0
   strcmp (font_format, "CFF") == 0))
3725
0
    {
3726
0
  return TRUE;
3727
0
    }
3728
3729
0
    return FALSE;
3730
0
}
3731
3732
static cairo_int_status_t
3733
_cairo_ft_load_type1_data (void             *abstract_font,
3734
         long              offset,
3735
         unsigned char    *buffer,
3736
         unsigned long    *length)
3737
0
{
3738
0
    cairo_ft_scaled_font_t *scaled_font = abstract_font;
3739
0
    cairo_ft_unscaled_font_t *unscaled = scaled_font->unscaled;
3740
0
    FT_Face face;
3741
0
    cairo_status_t status = CAIRO_STATUS_SUCCESS;
3742
0
    unsigned long available_length;
3743
0
    unsigned long ret;
3744
3745
0
    assert (length != NULL);
3746
3747
0
    if (_cairo_ft_scaled_font_is_vertical (&scaled_font->base))
3748
0
        return CAIRO_INT_STATUS_UNSUPPORTED;
3749
3750
0
    face = _cairo_ft_unscaled_font_lock_face (unscaled);
3751
0
    if (!face)
3752
0
  return _cairo_error (CAIRO_STATUS_NO_MEMORY);
3753
3754
0
    if (FT_IS_SFNT (face)) {
3755
0
  status = CAIRO_INT_STATUS_UNSUPPORTED;
3756
0
  goto unlock;
3757
0
    }
3758
3759
0
    if (! _ft_is_type1 (face)) {
3760
0
        status = CAIRO_INT_STATUS_UNSUPPORTED;
3761
0
  goto unlock;
3762
0
    }
3763
3764
0
    available_length = MAX (face->stream->size - offset, 0);
3765
0
    if (!buffer) {
3766
0
  *length = available_length;
3767
0
    } else {
3768
0
  if (*length > available_length) {
3769
0
      status = CAIRO_INT_STATUS_UNSUPPORTED;
3770
0
  } else if (face->stream->read != NULL) {
3771
      /* Note that read() may be implemented as a macro, thanks POSIX!, so we
3772
       * need to wrap the following usage in parentheses in order to
3773
       * disambiguate it for the pre-processor - using the verbose function
3774
       * pointer dereference for clarity.
3775
       */
3776
0
      ret = (* face->stream->read) (face->stream,
3777
0
            offset,
3778
0
            buffer,
3779
0
            *length);
3780
0
      if (ret != *length)
3781
0
    status = _cairo_error (CAIRO_STATUS_READ_ERROR);
3782
0
  } else {
3783
0
      memcpy (buffer, face->stream->base + offset, *length);
3784
0
  }
3785
0
    }
3786
3787
0
  unlock:
3788
0
    _cairo_ft_unscaled_font_unlock_face (unscaled);
3789
3790
0
    return status;
3791
0
}
3792
3793
static cairo_bool_t
3794
_cairo_ft_has_color_glyphs (void *scaled)
3795
859k
{
3796
859k
    cairo_ft_unscaled_font_t *unscaled = ((cairo_ft_scaled_font_t *)scaled)->unscaled;
3797
3798
859k
    if (!unscaled->have_color_set) {
3799
0
  FT_Face face;
3800
0
  face = _cairo_ft_unscaled_font_lock_face (unscaled);
3801
0
  if (unlikely (face == NULL))
3802
0
      return FALSE;
3803
0
  _cairo_ft_unscaled_font_unlock_face (unscaled);
3804
0
    }
3805
3806
859k
    return unscaled->have_color;
3807
859k
}
3808
3809
static const cairo_scaled_font_backend_t _cairo_ft_scaled_font_backend = {
3810
    CAIRO_FONT_TYPE_FT,
3811
    _cairo_ft_scaled_font_fini,
3812
    _cairo_ft_scaled_glyph_init,
3813
    NULL,     /* text_to_glyphs */
3814
    _cairo_ft_ucs4_to_index,
3815
    _cairo_ft_load_truetype_table,
3816
    _cairo_ft_index_to_ucs4,
3817
    _cairo_ft_is_synthetic,
3818
    _cairo_index_to_glyph_name,
3819
    _cairo_ft_load_type1_data,
3820
    _cairo_ft_has_color_glyphs
3821
};
3822
3823
/* #cairo_ft_font_face_t */
3824
3825
#if CAIRO_HAS_FC_FONT
3826
static cairo_font_face_t *
3827
_cairo_ft_font_face_create_for_pattern (FcPattern *pattern);
3828
3829
static cairo_status_t
3830
_cairo_ft_font_face_create_for_toy (cairo_toy_font_face_t *toy_face,
3831
            cairo_font_face_t **font_face_out)
3832
0
{
3833
0
    cairo_font_face_t *font_face = (cairo_font_face_t *) &_cairo_font_face_nil;
3834
0
    FcPattern *pattern;
3835
0
    int fcslant;
3836
0
    int fcweight;
3837
3838
0
    pattern = FcPatternCreate ();
3839
0
    if (!pattern) {
3840
0
  _cairo_error_throw (CAIRO_STATUS_NO_MEMORY);
3841
0
  return font_face->status;
3842
0
    }
3843
3844
0
    if (!FcPatternAddString (pattern,
3845
0
                 FC_FAMILY, (unsigned char *) toy_face->family))
3846
0
    {
3847
0
  _cairo_error_throw (CAIRO_STATUS_NO_MEMORY);
3848
0
  goto FREE_PATTERN;
3849
0
    }
3850
3851
0
    switch (toy_face->slant)
3852
0
    {
3853
0
    case CAIRO_FONT_SLANT_ITALIC:
3854
0
        fcslant = FC_SLANT_ITALIC;
3855
0
        break;
3856
0
    case CAIRO_FONT_SLANT_OBLIQUE:
3857
0
  fcslant = FC_SLANT_OBLIQUE;
3858
0
        break;
3859
0
    case CAIRO_FONT_SLANT_NORMAL:
3860
0
    default:
3861
0
        fcslant = FC_SLANT_ROMAN;
3862
0
        break;
3863
0
    }
3864
3865
0
    if (!FcPatternAddInteger (pattern, FC_SLANT, fcslant)) {
3866
0
  _cairo_error_throw (CAIRO_STATUS_NO_MEMORY);
3867
0
  goto FREE_PATTERN;
3868
0
    }
3869
3870
0
    switch (toy_face->weight)
3871
0
    {
3872
0
    case CAIRO_FONT_WEIGHT_BOLD:
3873
0
        fcweight = FC_WEIGHT_BOLD;
3874
0
        break;
3875
0
    case CAIRO_FONT_WEIGHT_NORMAL:
3876
0
    default:
3877
0
        fcweight = FC_WEIGHT_MEDIUM;
3878
0
        break;
3879
0
    }
3880
3881
0
    if (!FcPatternAddInteger (pattern, FC_WEIGHT, fcweight)) {
3882
0
  _cairo_error_throw (CAIRO_STATUS_NO_MEMORY);
3883
0
  goto FREE_PATTERN;
3884
0
    }
3885
3886
0
    font_face = _cairo_ft_font_face_create_for_pattern (pattern);
3887
3888
0
 FREE_PATTERN:
3889
0
    FcPatternDestroy (pattern);
3890
3891
0
    *font_face_out = font_face;
3892
0
    return font_face->status;
3893
0
}
3894
#endif
3895
3896
static cairo_bool_t
3897
_cairo_ft_font_face_destroy (void *abstract_face)
3898
0
{
3899
0
    cairo_ft_font_face_t *font_face = abstract_face;
3900
3901
    /* When destroying a face created by cairo_ft_font_face_create_for_ft_face,
3902
     * we have a special "zombie" state for the face when the unscaled font
3903
     * is still alive but there are no other references to a font face with
3904
     * the same FT_Face.
3905
     *
3906
     * We go from:
3907
     *
3908
     *   font_face ------> unscaled
3909
     *        <-....weak....../
3910
     *
3911
     * To:
3912
     *
3913
     *    font_face <------- unscaled
3914
     */
3915
3916
0
    if (font_face->unscaled &&
3917
0
  font_face->unscaled->from_face &&
3918
0
  font_face->next == NULL &&
3919
0
  font_face->unscaled->faces == font_face &&
3920
0
  CAIRO_REFERENCE_COUNT_GET_VALUE (&font_face->unscaled->base.ref_count) > 1)
3921
0
    {
3922
0
  _cairo_unscaled_font_destroy (&font_face->unscaled->base);
3923
0
  font_face->unscaled = NULL;
3924
3925
0
  return FALSE;
3926
0
    }
3927
3928
0
    if (font_face->unscaled) {
3929
0
  cairo_ft_font_face_t *tmp_face = NULL;
3930
0
  cairo_ft_font_face_t *last_face = NULL;
3931
3932
  /* Remove face from linked list */
3933
0
  for (tmp_face = font_face->unscaled->faces;
3934
0
       tmp_face;
3935
0
       tmp_face = tmp_face->next)
3936
0
  {
3937
0
      if (tmp_face == font_face) {
3938
0
    if (last_face)
3939
0
        last_face->next = tmp_face->next;
3940
0
    else
3941
0
        font_face->unscaled->faces = tmp_face->next;
3942
0
      }
3943
3944
0
      last_face = tmp_face;
3945
0
  }
3946
3947
0
  _cairo_unscaled_font_destroy (&font_face->unscaled->base);
3948
0
  font_face->unscaled = NULL;
3949
0
    }
3950
3951
0
    _cairo_ft_options_fini (&font_face->ft_options);
3952
3953
0
#if CAIRO_HAS_FC_FONT
3954
0
    if (font_face->pattern) {
3955
0
  FcPatternDestroy (font_face->pattern);
3956
0
  cairo_font_face_destroy (font_face->resolved_font_face);
3957
0
    }
3958
0
#endif
3959
3960
0
    return TRUE;
3961
0
}
3962
3963
static cairo_font_face_t *
3964
_cairo_ft_font_face_get_implementation (void                     *abstract_face,
3965
          const cairo_matrix_t       *font_matrix,
3966
          const cairo_matrix_t       *ctm,
3967
          const cairo_font_options_t *options)
3968
556
{
3969
    /* The handling of font options is different depending on how the
3970
     * font face was created. When the user creates a font face with
3971
     * cairo_ft_font_face_create_for_ft_face(), then the load flags
3972
     * passed in augment the load flags for the options.  But for
3973
     * cairo_ft_font_face_create_for_pattern(), the load flags are
3974
     * derived from a pattern where the user has called
3975
     * cairo_ft_font_options_substitute(), so *just* use those load
3976
     * flags and ignore the options.
3977
     */
3978
3979
556
#if CAIRO_HAS_FC_FONT
3980
556
    cairo_ft_font_face_t      *font_face = abstract_face;
3981
3982
    /* If we have an unresolved pattern, resolve it and create
3983
     * unscaled font.  Otherwise, use the ones stored in font_face.
3984
     */
3985
556
    if (font_face->pattern) {
3986
0
  cairo_font_face_t *resolved;
3987
3988
  /* Cache the resolved font whilst the FcConfig remains consistent. */
3989
0
  resolved = font_face->resolved_font_face;
3990
0
  if (resolved != NULL) {
3991
0
      if (! FcInitBringUptoDate ()) {
3992
0
    _cairo_error_throw (CAIRO_STATUS_NO_MEMORY);
3993
0
    return (cairo_font_face_t *) &_cairo_font_face_nil;
3994
0
      }
3995
3996
0
      if (font_face->resolved_config == FcConfigGetCurrent ())
3997
0
    return cairo_font_face_reference (resolved);
3998
3999
0
      cairo_font_face_destroy (resolved);
4000
0
      font_face->resolved_font_face = NULL;
4001
0
  }
4002
4003
0
  resolved = _cairo_ft_resolve_pattern (font_face->pattern,
4004
0
                font_matrix,
4005
0
                ctm,
4006
0
                options);
4007
0
  if (unlikely (resolved->status))
4008
0
      return resolved;
4009
4010
0
  font_face->resolved_font_face = cairo_font_face_reference (resolved);
4011
0
  font_face->resolved_config = FcConfigGetCurrent ();
4012
4013
0
  return resolved;
4014
0
    }
4015
556
#endif
4016
4017
556
    return abstract_face;
4018
556
}
4019
4020
const cairo_font_face_backend_t _cairo_ft_font_face_backend = {
4021
    CAIRO_FONT_TYPE_FT,
4022
#if CAIRO_HAS_FC_FONT
4023
    _cairo_ft_font_face_create_for_toy,
4024
#else
4025
    NULL,
4026
#endif
4027
    _cairo_ft_font_face_destroy,
4028
    _cairo_ft_font_face_scaled_font_create,
4029
    _cairo_ft_font_face_get_implementation
4030
};
4031
4032
#if CAIRO_HAS_FC_FONT
4033
static cairo_font_face_t *
4034
_cairo_ft_font_face_create_for_pattern (FcPattern *pattern)
4035
0
{
4036
0
    cairo_ft_font_face_t *font_face;
4037
4038
0
    font_face = _cairo_calloc (sizeof (cairo_ft_font_face_t));
4039
0
    if (unlikely (font_face == NULL)) {
4040
0
  _cairo_error_throw (CAIRO_STATUS_NO_MEMORY);
4041
0
  return (cairo_font_face_t *) &_cairo_font_face_nil;
4042
0
    }
4043
4044
0
    font_face->unscaled = NULL;
4045
4046
0
    _get_pattern_ft_options (pattern, &font_face->ft_options);
4047
4048
0
    font_face->next = NULL;
4049
4050
0
    font_face->pattern = FcPatternDuplicate (pattern);
4051
0
    if (unlikely (font_face->pattern == NULL)) {
4052
0
  free (font_face);
4053
0
  _cairo_error_throw (CAIRO_STATUS_NO_MEMORY);
4054
0
  return (cairo_font_face_t *) &_cairo_font_face_nil;
4055
0
    }
4056
4057
0
    font_face->resolved_font_face = NULL;
4058
0
    font_face->resolved_config = NULL;
4059
4060
0
    _cairo_font_face_init (&font_face->base, &_cairo_ft_font_face_backend);
4061
4062
0
    return &font_face->base;
4063
0
}
4064
#endif
4065
4066
static cairo_font_face_t *
4067
_cairo_ft_font_face_create (cairo_ft_unscaled_font_t *unscaled,
4068
          cairo_ft_options_t       *ft_options)
4069
2.11k
{
4070
2.11k
    cairo_ft_font_face_t *font_face, **prev_font_face;
4071
4072
    /* Looked for an existing matching font face */
4073
2.11k
    for (font_face = unscaled->faces, prev_font_face = &unscaled->faces;
4074
2.11k
   font_face;
4075
2.11k
   prev_font_face = &font_face->next, font_face = font_face->next)
4076
2.11k
    {
4077
2.11k
  if (font_face->ft_options.load_flags == ft_options->load_flags &&
4078
2.11k
      font_face->ft_options.synth_flags == ft_options->synth_flags &&
4079
2.11k
      cairo_font_options_equal (&font_face->ft_options.base, &ft_options->base))
4080
2.11k
  {
4081
2.11k
      if (font_face->base.status) {
4082
    /* The font_face has been left in an error state, abandon it. */
4083
0
    *prev_font_face = font_face->next;
4084
0
    break;
4085
0
      }
4086
4087
2.11k
      if (font_face->unscaled == NULL) {
4088
    /* Resurrect this "zombie" font_face (from
4089
     * _cairo_ft_font_face_destroy), switching its unscaled_font
4090
     * from owner to ownee. */
4091
0
    font_face->unscaled = unscaled;
4092
0
    _cairo_unscaled_font_reference (&unscaled->base);
4093
0
    return &font_face->base;
4094
0
      } else
4095
2.11k
    return cairo_font_face_reference (&font_face->base);
4096
2.11k
  }
4097
2.11k
    }
4098
4099
    /* No match found, create a new one */
4100
5
    font_face = _cairo_calloc (sizeof (cairo_ft_font_face_t));
4101
5
    if (unlikely (!font_face)) {
4102
0
  _cairo_error_throw (CAIRO_STATUS_NO_MEMORY);
4103
0
  return (cairo_font_face_t *)&_cairo_font_face_nil;
4104
0
    }
4105
4106
5
    font_face->unscaled = unscaled;
4107
5
    _cairo_unscaled_font_reference (&unscaled->base);
4108
4109
5
    _cairo_ft_options_init_copy (&font_face->ft_options, ft_options);
4110
4111
5
    if (unscaled->faces && unscaled->faces->unscaled == NULL) {
4112
  /* This "zombie" font_face (from _cairo_ft_font_face_destroy)
4113
   * is no longer needed. */
4114
0
  assert (unscaled->from_face && unscaled->faces->next == NULL);
4115
0
  cairo_font_face_destroy (&unscaled->faces->base);
4116
0
  unscaled->faces = NULL;
4117
0
    }
4118
4119
5
    font_face->next = unscaled->faces;
4120
5
    unscaled->faces = font_face;
4121
4122
5
#if CAIRO_HAS_FC_FONT
4123
5
    font_face->pattern = NULL;
4124
5
#endif
4125
4126
5
    _cairo_font_face_init (&font_face->base, &_cairo_ft_font_face_backend);
4127
4128
5
    return &font_face->base;
4129
5
}
4130
4131
/* implement the platform-specific interface */
4132
4133
#if CAIRO_HAS_FC_FONT
4134
static cairo_status_t
4135
_cairo_ft_font_options_substitute (const cairo_font_options_t *options,
4136
           FcPattern                  *pattern)
4137
654
{
4138
654
    FcValue v;
4139
4140
654
    if (options->antialias != CAIRO_ANTIALIAS_DEFAULT)
4141
654
    {
4142
654
  if (FcPatternGet (pattern, FC_ANTIALIAS, 0, &v) == FcResultNoMatch)
4143
654
  {
4144
654
      if (! FcPatternAddBool (pattern,
4145
654
                  FC_ANTIALIAS,
4146
654
            options->antialias != CAIRO_ANTIALIAS_NONE))
4147
0
    return _cairo_error (CAIRO_STATUS_NO_MEMORY);
4148
4149
654
      if (options->antialias != CAIRO_ANTIALIAS_SUBPIXEL) {
4150
654
    FcPatternDel (pattern, FC_RGBA);
4151
654
    if (! FcPatternAddInteger (pattern, FC_RGBA, FC_RGBA_NONE))
4152
0
        return _cairo_error (CAIRO_STATUS_NO_MEMORY);
4153
654
      }
4154
654
  }
4155
654
    }
4156
4157
654
    if (options->antialias != CAIRO_ANTIALIAS_DEFAULT)
4158
654
    {
4159
654
  if (FcPatternGet (pattern, FC_RGBA, 0, &v) == FcResultNoMatch)
4160
0
  {
4161
0
      int rgba;
4162
4163
0
      if (options->antialias == CAIRO_ANTIALIAS_SUBPIXEL) {
4164
0
    switch (options->subpixel_order) {
4165
0
    case CAIRO_SUBPIXEL_ORDER_DEFAULT:
4166
0
    case CAIRO_SUBPIXEL_ORDER_RGB:
4167
0
    default:
4168
0
        rgba = FC_RGBA_RGB;
4169
0
        break;
4170
0
    case CAIRO_SUBPIXEL_ORDER_BGR:
4171
0
        rgba = FC_RGBA_BGR;
4172
0
        break;
4173
0
    case CAIRO_SUBPIXEL_ORDER_VRGB:
4174
0
        rgba = FC_RGBA_VRGB;
4175
0
        break;
4176
0
    case CAIRO_SUBPIXEL_ORDER_VBGR:
4177
0
        rgba = FC_RGBA_VBGR;
4178
0
        break;
4179
0
    }
4180
0
      } else {
4181
0
    rgba = FC_RGBA_NONE;
4182
0
      }
4183
4184
0
      if (! FcPatternAddInteger (pattern, FC_RGBA, rgba))
4185
0
    return _cairo_error (CAIRO_STATUS_NO_MEMORY);
4186
0
  }
4187
654
    }
4188
4189
654
    if (options->lcd_filter != CAIRO_LCD_FILTER_DEFAULT)
4190
0
    {
4191
0
  if (FcPatternGet (pattern, FC_LCD_FILTER, 0, &v) == FcResultNoMatch)
4192
0
  {
4193
0
      int lcd_filter;
4194
4195
0
      switch (options->lcd_filter) {
4196
0
      case CAIRO_LCD_FILTER_NONE:
4197
0
    lcd_filter = FT_LCD_FILTER_NONE;
4198
0
    break;
4199
0
      case CAIRO_LCD_FILTER_INTRA_PIXEL:
4200
0
    lcd_filter = FT_LCD_FILTER_LEGACY;
4201
0
    break;
4202
0
      case CAIRO_LCD_FILTER_FIR3:
4203
0
    lcd_filter = FT_LCD_FILTER_LIGHT;
4204
0
    break;
4205
0
      default:
4206
0
      case CAIRO_LCD_FILTER_DEFAULT:
4207
0
      case CAIRO_LCD_FILTER_FIR5:
4208
0
    lcd_filter = FT_LCD_FILTER_DEFAULT;
4209
0
    break;
4210
0
      }
4211
4212
0
      if (! FcPatternAddInteger (pattern, FC_LCD_FILTER, lcd_filter))
4213
0
    return _cairo_error (CAIRO_STATUS_NO_MEMORY);
4214
0
  }
4215
0
    }
4216
4217
654
    if (options->hint_style != CAIRO_HINT_STYLE_DEFAULT)
4218
0
    {
4219
0
  if (FcPatternGet (pattern, FC_HINTING, 0, &v) == FcResultNoMatch)
4220
0
  {
4221
0
      if (! FcPatternAddBool (pattern,
4222
0
                  FC_HINTING,
4223
0
            options->hint_style != CAIRO_HINT_STYLE_NONE))
4224
0
    return _cairo_error (CAIRO_STATUS_NO_MEMORY);
4225
0
  }
4226
4227
0
  if (FcPatternGet (pattern, FC_HINT_STYLE, 0, &v) == FcResultNoMatch)
4228
0
  {
4229
0
      int hint_style;
4230
4231
0
      switch (options->hint_style) {
4232
0
      case CAIRO_HINT_STYLE_NONE:
4233
0
    hint_style = FC_HINT_NONE;
4234
0
    break;
4235
0
      case CAIRO_HINT_STYLE_SLIGHT:
4236
0
    hint_style = FC_HINT_SLIGHT;
4237
0
    break;
4238
0
      case CAIRO_HINT_STYLE_MEDIUM:
4239
0
    hint_style = FC_HINT_MEDIUM;
4240
0
    break;
4241
0
      case CAIRO_HINT_STYLE_FULL:
4242
0
      case CAIRO_HINT_STYLE_DEFAULT:
4243
0
      default:
4244
0
    hint_style = FC_HINT_FULL;
4245
0
    break;
4246
0
      }
4247
4248
0
      if (! FcPatternAddInteger (pattern, FC_HINT_STYLE, hint_style))
4249
0
    return _cairo_error (CAIRO_STATUS_NO_MEMORY);
4250
0
  }
4251
0
    }
4252
4253
654
    return CAIRO_STATUS_SUCCESS;
4254
654
}
4255
4256
/**
4257
 * cairo_ft_font_options_substitute:
4258
 * @options: a #cairo_font_options_t object
4259
 * @pattern: an existing #FcPattern
4260
 *
4261
 * Add options to a #FcPattern based on a #cairo_font_options_t font
4262
 * options object. Options that are already in the pattern, are not overridden,
4263
 * so you should call this function after calling FcConfigSubstitute() (the
4264
 * user's settings should override options based on the surface type), but
4265
 * before calling FcDefaultSubstitute().
4266
 *
4267
 * Since: 1.0
4268
 **/
4269
void
4270
cairo_ft_font_options_substitute (const cairo_font_options_t *options,
4271
          FcPattern                  *pattern)
4272
654
{
4273
654
    if (cairo_font_options_status ((cairo_font_options_t *) options))
4274
0
  return;
4275
4276
654
    _cairo_ft_font_options_substitute (options, pattern);
4277
654
}
4278
4279
static cairo_font_face_t *
4280
_cairo_ft_resolve_pattern (FcPattern          *pattern,
4281
         const cairo_matrix_t       *font_matrix,
4282
         const cairo_matrix_t       *ctm,
4283
         const cairo_font_options_t *font_options)
4284
0
{
4285
0
    cairo_status_t status;
4286
4287
0
    cairo_matrix_t scale;
4288
0
    FcPattern *resolved;
4289
0
    cairo_ft_font_transform_t sf;
4290
0
    FcResult result;
4291
0
    cairo_ft_unscaled_font_t *unscaled;
4292
0
    cairo_ft_options_t ft_options;
4293
0
    cairo_font_face_t *font_face;
4294
4295
0
    scale = *ctm;
4296
0
    scale.x0 = scale.y0 = 0;
4297
0
    cairo_matrix_multiply (&scale,
4298
0
                           font_matrix,
4299
0
                           &scale);
4300
4301
0
    status = _compute_transform (&sf, &scale, NULL);
4302
0
    if (unlikely (status))
4303
0
  return (cairo_font_face_t *)&_cairo_font_face_nil;
4304
4305
0
    pattern = FcPatternDuplicate (pattern);
4306
0
    if (pattern == NULL)
4307
0
  return (cairo_font_face_t *)&_cairo_font_face_nil;
4308
4309
0
    if (! FcPatternAddDouble (pattern, FC_PIXEL_SIZE, sf.y_scale)) {
4310
0
  font_face = (cairo_font_face_t *)&_cairo_font_face_nil;
4311
0
  goto FREE_PATTERN;
4312
0
    }
4313
4314
0
    if (! FcConfigSubstitute (NULL, pattern, FcMatchPattern)) {
4315
0
  font_face = (cairo_font_face_t *)&_cairo_font_face_nil;
4316
0
  goto FREE_PATTERN;
4317
0
    }
4318
4319
0
    status = _cairo_ft_font_options_substitute (font_options, pattern);
4320
0
    if (status) {
4321
0
  font_face = (cairo_font_face_t *)&_cairo_font_face_nil;
4322
0
  goto FREE_PATTERN;
4323
0
    }
4324
4325
0
    FcDefaultSubstitute (pattern);
4326
4327
0
    status = _cairo_ft_unscaled_font_create_for_pattern (pattern, &unscaled);
4328
0
    if (unlikely (status)) {
4329
0
  font_face = (cairo_font_face_t *)&_cairo_font_face_nil;
4330
0
  goto FREE_PATTERN;
4331
0
    }
4332
4333
0
    if (unscaled == NULL) {
4334
0
  resolved = FcFontMatch (NULL, pattern, &result);
4335
0
  if (!resolved) {
4336
      /* We failed to find any font. Substitute twin so that the user can
4337
       * see something (and hopefully recognise that the font is missing)
4338
       * and not just receive a NO_MEMORY error during rendering.
4339
       */
4340
0
      font_face = _cairo_font_face_twin_create_fallback ();
4341
0
      goto FREE_PATTERN;
4342
0
  }
4343
4344
0
  status = _cairo_ft_unscaled_font_create_for_pattern (resolved, &unscaled);
4345
0
  if (unlikely (status || unscaled == NULL)) {
4346
0
      font_face = (cairo_font_face_t *)&_cairo_font_face_nil;
4347
0
      goto FREE_RESOLVED;
4348
0
  }
4349
0
    } else
4350
0
  resolved = pattern;
4351
4352
0
    _get_pattern_ft_options (resolved, &ft_options);
4353
0
    font_face = _cairo_ft_font_face_create (unscaled, &ft_options);
4354
0
     _cairo_ft_options_fini (&ft_options);
4355
0
    _cairo_unscaled_font_destroy (&unscaled->base);
4356
4357
0
FREE_RESOLVED:
4358
0
    if (resolved != pattern)
4359
0
  FcPatternDestroy (resolved);
4360
4361
0
FREE_PATTERN:
4362
0
    FcPatternDestroy (pattern);
4363
4364
0
    return font_face;
4365
0
}
4366
4367
/**
4368
 * cairo_ft_font_face_create_for_pattern:
4369
 * @pattern: A fontconfig pattern.  Cairo makes a copy of the pattern
4370
 * if it needs to.  You are free to modify or free @pattern after this call.
4371
 *
4372
 * Creates a new font face for the FreeType font backend based on a
4373
 * fontconfig pattern. This font can then be used with
4374
 * cairo_set_font_face() or cairo_scaled_font_create(). The
4375
 * #cairo_scaled_font_t returned from cairo_scaled_font_create() is
4376
 * also for the FreeType backend and can be used with functions such
4377
 * as cairo_ft_scaled_font_lock_face().
4378
 *
4379
 * Font rendering options are represented both here and when you
4380
 * call cairo_scaled_font_create(). Font options that have a representation
4381
 * in a #FcPattern must be passed in here; to modify #FcPattern
4382
 * appropriately to reflect the options in a #cairo_font_options_t, call
4383
 * cairo_ft_font_options_substitute().
4384
 *
4385
 * The pattern's FC_FT_FACE element is inspected first and if that is set,
4386
 * that will be the FreeType font face associated with the returned cairo
4387
 * font face.  Otherwise the FC_FILE element is checked.  If it's set,
4388
 * that and the value of the FC_INDEX element (defaults to zero) of @pattern
4389
 * are used to load a font face from file.
4390
 *
4391
 * If both steps from the previous paragraph fails, @pattern will be passed
4392
 * to FcConfigSubstitute, FcDefaultSubstitute, and finally FcFontMatch,
4393
 * and the resulting font pattern is used.
4394
 *
4395
 * If the FC_FT_FACE element of @pattern is set, the user is responsible
4396
 * for making sure that the referenced FT_Face remains valid for the life
4397
 * time of the returned #cairo_font_face_t.  See
4398
 * cairo_ft_font_face_create_for_ft_face() for an example of how to couple
4399
 * the life time of the FT_Face to that of the cairo font-face.
4400
 *
4401
 * Return value: a newly created #cairo_font_face_t. Free with
4402
 *  cairo_font_face_destroy() when you are done using it.
4403
 *
4404
 * Since: 1.0
4405
 **/
4406
cairo_font_face_t *
4407
cairo_ft_font_face_create_for_pattern (FcPattern *pattern)
4408
2.11k
{
4409
2.11k
    cairo_ft_unscaled_font_t *unscaled;
4410
2.11k
    cairo_font_face_t *font_face;
4411
2.11k
    cairo_ft_options_t ft_options;
4412
2.11k
    cairo_status_t status;
4413
4414
2.11k
    status = _cairo_ft_unscaled_font_create_for_pattern (pattern, &unscaled);
4415
2.11k
    if (unlikely (status)) {
4416
0
      if (status == CAIRO_STATUS_FILE_NOT_FOUND)
4417
0
  return (cairo_font_face_t *) &_cairo_font_face_nil_file_not_found;
4418
0
      else
4419
0
  return (cairo_font_face_t *) &_cairo_font_face_nil;
4420
0
    }
4421
2.11k
    if (unlikely (unscaled == NULL)) {
4422
  /* Store the pattern.  We will resolve it and create unscaled
4423
   * font when creating scaled fonts */
4424
0
  return _cairo_ft_font_face_create_for_pattern (pattern);
4425
0
    }
4426
4427
2.11k
    _get_pattern_ft_options (pattern, &ft_options);
4428
2.11k
    font_face = _cairo_ft_font_face_create (unscaled, &ft_options);
4429
2.11k
    _cairo_ft_options_fini (&ft_options);
4430
2.11k
    _cairo_unscaled_font_destroy (&unscaled->base);
4431
4432
2.11k
    return font_face;
4433
2.11k
}
4434
#endif
4435
4436
/**
4437
 * cairo_ft_font_face_create_for_ft_face:
4438
 * @face: A FreeType face object, already opened. This must
4439
 *   be kept around until the face's ref_count drops to
4440
 *   zero and it is freed. Since the face may be referenced
4441
 *   internally to Cairo, the best way to determine when it
4442
 *   is safe to free the face is to pass a
4443
 *   #cairo_destroy_func_t to cairo_font_face_set_user_data()
4444
 * @load_flags: flags to pass to FT_Load_Glyph when loading
4445
 *   glyphs from the font. These flags are OR'ed together with
4446
 *   the flags derived from the #cairo_font_options_t passed
4447
 *   to cairo_scaled_font_create(), so only a few values such
4448
 *   as %FT_LOAD_VERTICAL_LAYOUT, and %FT_LOAD_FORCE_AUTOHINT
4449
 *   are useful. You should not pass any of the flags affecting
4450
 *   the load target, such as %FT_LOAD_TARGET_LIGHT.
4451
 *
4452
 * Creates a new font face for the FreeType font backend from a
4453
 * pre-opened FreeType face. This font can then be used with
4454
 * cairo_set_font_face() or cairo_scaled_font_create(). The
4455
 * #cairo_scaled_font_t returned from cairo_scaled_font_create() is
4456
 * also for the FreeType backend and can be used with functions such
4457
 * as cairo_ft_scaled_font_lock_face(). Note that Cairo may keep a reference
4458
 * to the FT_Face alive in a font-cache and the exact lifetime of the reference
4459
 * depends highly upon the exact usage pattern and is subject to external
4460
 * factors. You must not call FT_Done_Face() before the last reference to the
4461
 * #cairo_font_face_t has been dropped.
4462
 *
4463
 * As an example, below is how one might correctly couple the lifetime of
4464
 * the FreeType face object to the #cairo_font_face_t.
4465
 *
4466
 * <informalexample><programlisting>
4467
 * static const cairo_user_data_key_t key;
4468
 *
4469
 * font_face = cairo_ft_font_face_create_for_ft_face (ft_face, 0);
4470
 * status = cairo_font_face_set_user_data (font_face, &key,
4471
 *                                ft_face, (cairo_destroy_func_t) FT_Done_Face);
4472
 * if (status) {
4473
 *    cairo_font_face_destroy (font_face);
4474
 *    FT_Done_Face (ft_face);
4475
 *    return ERROR;
4476
 * }
4477
 * </programlisting></informalexample>
4478
 *
4479
 * Return value: a newly created #cairo_font_face_t. Free with
4480
 *  cairo_font_face_destroy() when you are done using it.
4481
 *
4482
 * Since: 1.0
4483
 **/
4484
cairo_font_face_t *
4485
cairo_ft_font_face_create_for_ft_face (FT_Face         face,
4486
               int             load_flags)
4487
0
{
4488
0
    cairo_ft_unscaled_font_t *unscaled;
4489
0
    cairo_font_face_t *font_face;
4490
0
    cairo_ft_options_t ft_options;
4491
0
    cairo_status_t status;
4492
4493
0
    status = _cairo_ft_unscaled_font_create_from_face (face, &unscaled);
4494
0
    if (unlikely (status))
4495
0
  return (cairo_font_face_t *)&_cairo_font_face_nil;
4496
4497
0
    ft_options.load_flags = load_flags;
4498
0
    ft_options.synth_flags = 0;
4499
0
    _cairo_font_options_init_default (&ft_options.base);
4500
4501
0
    font_face = _cairo_ft_font_face_create (unscaled, &ft_options);
4502
0
    _cairo_unscaled_font_destroy (&unscaled->base);
4503
4504
0
    return font_face;
4505
0
}
4506
4507
/**
4508
 * cairo_ft_font_face_set_synthesize:
4509
 * @font_face: The #cairo_ft_font_face_t object to modify
4510
 * @synth_flags: the set of synthesis options to enable
4511
 *
4512
 * FreeType provides the ability to synthesize different glyphs from a base
4513
 * font, which is useful if you lack those glyphs from a true bold or oblique
4514
 * font. See also #cairo_ft_synthesize_t.
4515
 *
4516
 * Since: 1.12
4517
 **/
4518
void
4519
cairo_ft_font_face_set_synthesize (cairo_font_face_t *font_face,
4520
           unsigned int synth_flags)
4521
0
{
4522
0
    cairo_ft_font_face_t *ft;
4523
4524
0
    if (font_face->backend->type != CAIRO_FONT_TYPE_FT)
4525
0
  return;
4526
4527
0
    ft = (cairo_ft_font_face_t *) font_face;
4528
0
    ft->ft_options.synth_flags |= synth_flags;
4529
0
}
4530
4531
/**
4532
 * cairo_ft_font_face_unset_synthesize:
4533
 * @font_face: The #cairo_ft_font_face_t object to modify
4534
 * @synth_flags: the set of synthesis options to disable
4535
 *
4536
 * See cairo_ft_font_face_set_synthesize().
4537
 *
4538
 * Since: 1.12
4539
 **/
4540
void
4541
cairo_ft_font_face_unset_synthesize (cairo_font_face_t *font_face,
4542
             unsigned int synth_flags)
4543
0
{
4544
0
    cairo_ft_font_face_t *ft;
4545
4546
0
    if (font_face->backend->type != CAIRO_FONT_TYPE_FT)
4547
0
  return;
4548
4549
0
    ft = (cairo_ft_font_face_t *) font_face;
4550
0
    ft->ft_options.synth_flags &= ~synth_flags;
4551
0
}
4552
4553
/**
4554
 * cairo_ft_font_face_get_synthesize:
4555
 * @font_face: The #cairo_ft_font_face_t object to query
4556
 *
4557
 * See #cairo_ft_synthesize_t.
4558
 *
4559
 * Returns: the current set of synthesis options.
4560
 *
4561
 * Since: 1.12
4562
 **/
4563
unsigned int
4564
cairo_ft_font_face_get_synthesize (cairo_font_face_t *font_face)
4565
0
{
4566
0
    cairo_ft_font_face_t *ft;
4567
4568
0
    if (font_face->backend->type != CAIRO_FONT_TYPE_FT)
4569
0
  return 0;
4570
4571
0
    ft = (cairo_ft_font_face_t *) font_face;
4572
0
    return ft->ft_options.synth_flags;
4573
0
}
4574
4575
/**
4576
 * cairo_ft_scaled_font_lock_face:
4577
 * @scaled_font: A #cairo_scaled_font_t from the FreeType font backend. Such an
4578
 *   object can be created by calling cairo_scaled_font_create() on a
4579
 *   FreeType backend font face (see cairo_ft_font_face_create_for_pattern(),
4580
 *   cairo_ft_font_face_create_for_ft_face()).
4581
 *
4582
 * cairo_ft_scaled_font_lock_face() gets the #FT_Face object from a FreeType
4583
 * backend font and scales it appropriately for the font and applies OpenType
4584
 * font variations if applicable. You must
4585
 * release the face with cairo_ft_scaled_font_unlock_face()
4586
 * when you are done using it.  Since the #FT_Face object can be
4587
 * shared between multiple #cairo_scaled_font_t objects, you must not
4588
 * lock any other font objects until you unlock this one. A count is
4589
 * kept of the number of times cairo_ft_scaled_font_lock_face() is
4590
 * called. cairo_ft_scaled_font_unlock_face() must be called the same number
4591
 * of times.
4592
 *
4593
 * You must be careful when using this function in a library or in a
4594
 * threaded application, because freetype's design makes it unsafe to
4595
 * call freetype functions simultaneously from multiple threads, (even
4596
 * if using distinct FT_Face objects). Because of this, application
4597
 * code that acquires an FT_Face object with this call must add its
4598
 * own locking to protect any use of that object, (and which also must
4599
 * protect any other calls into cairo as almost any cairo function
4600
 * might result in a call into the freetype library).
4601
 *
4602
 * Return value: The #FT_Face object for @font, scaled appropriately,
4603
 * or %NULL if @scaled_font is in an error state (see
4604
 * cairo_scaled_font_status()) or there is insufficient memory.
4605
 *
4606
 * Since: 1.0
4607
 **/
4608
FT_Face
4609
cairo_ft_scaled_font_lock_face (cairo_scaled_font_t *abstract_font)
4610
0
{
4611
0
    cairo_ft_scaled_font_t *scaled_font = (cairo_ft_scaled_font_t *) abstract_font;
4612
0
    FT_Face face;
4613
0
    cairo_status_t status;
4614
4615
0
    if (! _cairo_scaled_font_is_ft (abstract_font)) {
4616
0
  _cairo_error_throw (CAIRO_STATUS_FONT_TYPE_MISMATCH);
4617
0
  return NULL;
4618
0
    }
4619
4620
0
    if (scaled_font->base.status)
4621
0
  return NULL;
4622
4623
0
    face = _cairo_ft_unscaled_font_lock_face (scaled_font->unscaled);
4624
0
    if (unlikely (face == NULL)) {
4625
0
  status = _cairo_scaled_font_set_error (&scaled_font->base, CAIRO_STATUS_NO_MEMORY);
4626
0
  return NULL;
4627
0
    }
4628
4629
0
    status = _cairo_ft_unscaled_font_set_scale (scaled_font->unscaled,
4630
0
                        &scaled_font->base.scale);
4631
0
    if (unlikely (status)) {
4632
0
  _cairo_ft_unscaled_font_unlock_face (scaled_font->unscaled);
4633
0
  status = _cairo_scaled_font_set_error (&scaled_font->base, status);
4634
0
  return NULL;
4635
0
    }
4636
4637
0
    cairo_ft_apply_variations (face, scaled_font);
4638
4639
    /* Note: We deliberately release the unscaled font's mutex here,
4640
     * so that we are not holding a lock across two separate calls to
4641
     * cairo function, (which would give the application some
4642
     * opportunity for creating deadlock. This is obviously unsafe,
4643
     * but as documented, the user must add manual locking when using
4644
     * this function. */
4645
0
     CAIRO_MUTEX_UNLOCK (scaled_font->unscaled->mutex);
4646
4647
0
    return face;
4648
0
}
4649
4650
/**
4651
 * cairo_ft_scaled_font_unlock_face:
4652
 * @scaled_font: A #cairo_scaled_font_t from the FreeType font backend. Such an
4653
 *   object can be created by calling cairo_scaled_font_create() on a
4654
 *   FreeType backend font face (see cairo_ft_font_face_create_for_pattern(),
4655
 *   cairo_ft_font_face_create_for_ft_face()).
4656
 *
4657
 * Releases a face obtained with cairo_ft_scaled_font_lock_face().
4658
 *
4659
 * Since: 1.0
4660
 **/
4661
void
4662
cairo_ft_scaled_font_unlock_face (cairo_scaled_font_t *abstract_font)
4663
0
{
4664
0
    cairo_ft_scaled_font_t *scaled_font = (cairo_ft_scaled_font_t *) abstract_font;
4665
4666
0
    if (! _cairo_scaled_font_is_ft (abstract_font)) {
4667
0
  _cairo_error_throw (CAIRO_STATUS_FONT_TYPE_MISMATCH);
4668
0
  return;
4669
0
    }
4670
4671
0
    if (scaled_font->base.status)
4672
0
  return;
4673
4674
    /* Note: We released the unscaled font's mutex at the end of
4675
     * cairo_ft_scaled_font_lock_face, so we have to acquire it again
4676
     * as _cairo_ft_unscaled_font_unlock_face expects it to be held
4677
     * when we call into it. */
4678
0
    CAIRO_MUTEX_LOCK (scaled_font->unscaled->mutex);
4679
4680
0
    _cairo_ft_unscaled_font_unlock_face (scaled_font->unscaled);
4681
0
}
4682
4683
static cairo_bool_t
4684
_cairo_ft_scaled_font_is_vertical (cairo_scaled_font_t *scaled_font)
4685
556
{
4686
556
    cairo_ft_scaled_font_t *ft_scaled_font;
4687
4688
556
    if (!_cairo_scaled_font_is_ft (scaled_font))
4689
0
  return FALSE;
4690
4691
556
    ft_scaled_font = (cairo_ft_scaled_font_t *) scaled_font;
4692
556
    if (ft_scaled_font->ft_options.load_flags & FT_LOAD_VERTICAL_LAYOUT)
4693
0
  return TRUE;
4694
556
    return FALSE;
4695
556
}
4696
4697
unsigned int
4698
_cairo_ft_scaled_font_get_load_flags (cairo_scaled_font_t *scaled_font)
4699
0
{
4700
0
    cairo_ft_scaled_font_t *ft_scaled_font;
4701
4702
0
    if (! _cairo_scaled_font_is_ft (scaled_font))
4703
0
  return 0;
4704
4705
0
    ft_scaled_font = (cairo_ft_scaled_font_t *) scaled_font;
4706
0
    return ft_scaled_font->ft_options.load_flags;
4707
0
}
4708
4709
void
4710
_cairo_ft_font_reset_static_data (void)
4711
0
{
4712
0
    _cairo_ft_unscaled_font_map_destroy ();
4713
0
}