Coverage Report

Created: 2025-07-07 10:01

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