cairo-ft-font.c 111 KB
Newer Older
1
/* -*- Mode: c; c-basic-offset: 4; indent-tabs-mode: t; tab-width: 8; -*- */
2
3
/* cairo - a vector graphics library with display and print output
 *
Keith Packard's avatar
Keith Packard committed
4
 * Copyright © 2000 Keith Packard
5
6
7
8
9
10
11
12
13
14
15
16
 * Copyright © 2005 Red Hat, Inc
 *
 * This library is free software; you can redistribute it and/or
 * modify it either under the terms of the GNU Lesser General Public
 * License version 2.1 as published by the Free Software Foundation
 * (the "LGPL") or, at your option, under the terms of the Mozilla
 * Public License Version 1.1 (the "MPL"). If you do not alter this
 * notice, a recipient may use your version of this file under either
 * the MPL or the LGPL.
 *
 * You should have received a copy of the LGPL along with this library
 * in the file COPYING-LGPL-2.1; if not, write to the Free Software
Andrea Canciani's avatar
Andrea Canciani committed
17
 * Foundation, Inc., 51 Franklin Street, Suite 500, Boston, MA 02110-1335, USA
18
19
 * You should have received a copy of the MPL along with this library
 * in the file COPYING-MPL-1.1
Graydon Hoare's avatar
Graydon Hoare committed
20
 *
21
22
23
24
 * The contents of this file are subject to the Mozilla Public License
 * Version 1.1 (the "License"); you may not use this file except in
 * compliance with the License. You may obtain a copy of the License at
 * http://www.mozilla.org/MPL/
Graydon Hoare's avatar
Graydon Hoare committed
25
 *
26
27
28
 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
 * OF ANY KIND, either express or implied. See the LGPL or the MPL for
 * the specific language governing rights and limitations.
Graydon Hoare's avatar
Graydon Hoare committed
29
 *
30
31
32
33
34
35
36
 * The Original Code is the cairo graphics library.
 *
 * The Initial Developer of the Original Code is Red Hat, Inc.
 *
 * Contributor(s):
 *      Graydon Hoare <graydon@redhat.com>
 *	Owen Taylor <otaylor@redhat.com>
Keith Packard's avatar
Keith Packard committed
37
38
 *      Keith Packard <keithp@keithp.com>
 *      Carl Worth <cworth@cworth.org>
Graydon Hoare's avatar
Graydon Hoare committed
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"
Chris Wilson's avatar
Chris Wilson committed
47
#include "cairo-pattern-private.h"
48
#include "cairo-pixman-private.h"
Carl Worth's avatar
Carl Worth committed
49

50
51
#include <float.h>

Andrea Canciani's avatar
Andrea Canciani committed
52
#include "cairo-fontconfig-private.h"
53
54
55
56

#include <ft2build.h>
#include FT_FREETYPE_H
#include FT_OUTLINE_H
David Reveman's avatar
David Reveman committed
57
#include FT_IMAGE_H
Behdad Esfahbod's avatar
Behdad Esfahbod committed
58
#include FT_BITMAP_H
59
#include FT_TRUETYPE_TABLES_H
60
#include FT_XFREE86_H
61
#include FT_MULTIPLE_MASTERS_H
62
63
64
#if HAVE_FT_GLYPHSLOT_EMBOLDEN
#include FT_SYNTHESIS_H
#endif
Graydon Hoare's avatar
Graydon Hoare committed
65

66
67
68
69
#if HAVE_FT_LIBRARY_SETLCDFILTER
#include FT_LCD_FILTER_H
#endif

70
71
72
73
74
75
#if HAVE_UNISTD_H
#include <unistd.h>
#else
#define access(p, m) 0
#endif

76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
/* Fontconfig version older than 2.6 didn't have these options */
#ifndef FC_LCD_FILTER
#define FC_LCD_FILTER	"lcdfilter"
#endif
/* Some Ubuntu versions defined FC_LCD_FILTER without defining the following */
#ifndef FC_LCD_NONE
#define FC_LCD_NONE	0
#define FC_LCD_DEFAULT	1
#define FC_LCD_LIGHT	2
#define FC_LCD_LEGACY	3
#endif

/* FreeType version older than 2.3.5(?) didn't have these options */
#ifndef FT_LCD_FILTER_NONE
#define FT_LCD_FILTER_NONE	0
#define FT_LCD_FILTER_DEFAULT	1
#define FT_LCD_FILTER_LIGHT	2
#define FT_LCD_FILTER_LEGACY	16
#endif

Graydon Hoare's avatar
Graydon Hoare committed
96
97
98
#define DOUBLE_FROM_26_6(t) ((double)(t) / 64.0)
#define DOUBLE_TO_16_16(d) ((FT_Fixed)((d) * 65536.0))
#define DOUBLE_FROM_16_16(t) ((double)(t) / 65536.0)
99

100
/* This is the max number of FT_face objects we keep open at once
Graydon Hoare's avatar
Graydon Hoare committed
101
 */
102
#define MAX_OPEN_FACES 10
Graydon Hoare's avatar
Graydon Hoare committed
103

104
105
106
107
108
109
110
111
/**
 * SECTION:cairo-ft
 * @Title: FreeType Fonts
 * @Short_Description: Font support for FreeType
 * @See_Also: #cairo_font_face_t
 *
 * The FreeType font backend is primarily used to render text on GNU/Linux
 * systems, but can be used on other platforms too.
112
 **/
113
114
115
116
117
118

/**
 * CAIRO_HAS_FT_FONT:
 *
 * Defined if the FreeType font backend is available.
 * This macro can be used to conditionally compile backend-specific code.
119
120
 *
 * Since: 1.0
121
 **/
122
123
124
125
126
127
128

/**
 * CAIRO_HAS_FC_FONT:
 *
 * Defined if the Fontconfig-specific functions of the FreeType font backend
 * are available.
 * This macro can be used to conditionally compile backend-specific code.
129
130
 *
 * Since: 1.10
131
 **/
132

133
134
135
136
137
/*
 * The simple 2x2 matrix is converted into separate scale and shape
 * factors so that hinting works right
 */

138
typedef struct _cairo_ft_font_transform {
139
140
    double  x_scale, y_scale;
    double  shape[2][2];
141
} cairo_ft_font_transform_t;
142

143
/*
144
145
 * We create an object that corresponds to a single font on the disk;
 * (identified by a filename/id pair) these are shared between all
146
 * fonts using that file.  For cairo_ft_font_face_create_for_ft_face(), we
147
148
 * just create a one-off version with a permanent face value.
 */
Graydon Hoare's avatar
Graydon Hoare committed
149

150
typedef struct _cairo_ft_font_face cairo_ft_font_face_t;
151

152
struct _cairo_ft_unscaled_font {
153
    cairo_unscaled_font_t base;
Graydon Hoare's avatar
Graydon Hoare committed
154

155
    cairo_bool_t from_face; /* was the FT_Face provided by user? */
156
    FT_Face face;	    /* provided or cached face */
Graydon Hoare's avatar
Graydon Hoare committed
157

158
159
160
    /* only set if from_face is false */
    char *filename;
    int id;
Graydon Hoare's avatar
Graydon Hoare committed
161

162
    /* We temporarily scale the unscaled font as needed */
163
    cairo_bool_t have_scale;
164
    cairo_matrix_t current_scale;
165
166
    double x_scale;		/* Extracted X scale factor */
    double y_scale;             /* Extracted Y scale factor */
167
    cairo_bool_t have_shape;	/* true if the current scale has a non-scale component*/
168
    cairo_matrix_t current_shape;
169
    FT_Matrix Current_Shape;
170

171
172
173
    unsigned int have_color_set  : 1;
    unsigned int have_color      : 1;  /* true if the font contains color glyphs */
    FT_Fixed *variations;              /* variation settings that FT_Face came */
174

175
    cairo_mutex_t mutex;
176
    int lock_count;
177

178
179
    cairo_ft_font_face_t *faces;	/* Linked list of faces for this font */
};
Graydon Hoare's avatar
Graydon Hoare committed
180

181
static int
182
183
_cairo_ft_unscaled_font_keys_equal (const void *key_a,
				    const void *key_b);
184
185
186
187

static void
_cairo_ft_unscaled_font_fini (cairo_ft_unscaled_font_t *unscaled);

188
typedef struct _cairo_ft_options {
189
190
    cairo_font_options_t base;
    unsigned int load_flags; /* flags for FT_Load_Glyph */
191
    unsigned int synth_flags;
192
193
} cairo_ft_options_t;

194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
static void
_cairo_ft_options_init_copy (cairo_ft_options_t       *options,
                             const cairo_ft_options_t *other)
{
    _cairo_font_options_init_copy (&options->base, &other->base);
    options->load_flags = other->load_flags;
    options->synth_flags = other->synth_flags;
}

static void
_cairo_ft_options_fini (cairo_ft_options_t *options)
{
    _cairo_font_options_fini (&options->base);
}

209
struct _cairo_ft_font_face {
210
    cairo_font_face_t base;
211

212
    cairo_ft_unscaled_font_t *unscaled;
213
    cairo_ft_options_t ft_options;
214
    cairo_ft_font_face_t *next;
215

216
#if CAIRO_HAS_FC_FONT
217
    FcPattern *pattern; /* if pattern is set, the above fields will be NULL */
218
219
    cairo_font_face_t *resolved_font_face;
    FcConfig *resolved_config;
220
#endif
221
222
};

223
static const cairo_unscaled_font_backend_t cairo_ft_unscaled_font_backend;
Graydon Hoare's avatar
Graydon Hoare committed
224

225
226
227
228
229
#if CAIRO_HAS_FC_FONT
static cairo_status_t
_cairo_ft_font_options_substitute (const cairo_font_options_t *options,
				   FcPattern                  *pattern);

230
static cairo_font_face_t *
231
232
233
_cairo_ft_resolve_pattern (FcPattern		      *pattern,
			   const cairo_matrix_t       *font_matrix,
			   const cairo_matrix_t       *ctm,
234
			   const cairo_font_options_t *options);
235

236
#endif
237

238
239
240
241
242
243
244
static cairo_status_t
_ft_to_cairo_error (FT_Error error)
{
  /* Currently we don't get many (any?) useful statuses here.
   * Populate as needed. */
  switch (error)
  {
245
246
247
248
  case FT_Err_Out_Of_Memory:
      return CAIRO_STATUS_NO_MEMORY;
  default:
      return CAIRO_STATUS_FREETYPE_ERROR;
249
250
251
  }
}

252
/*
253
 * We maintain a hash table to map file/id => #cairo_ft_unscaled_font_t.
254
 * The hash table itself isn't limited in size. However, we limit the
Behdad Esfahbod's avatar
Behdad Esfahbod committed
255
 * number of FT_Face objects we keep around; when we've exceeded that
256
 * limit and need to create a new FT_Face, we dump the FT_Face from a
257
 * random #cairo_ft_unscaled_font_t which has an unlocked FT_Face, (if
258
 * there are any).
Graydon Hoare's avatar
Graydon Hoare committed
259
260
 */

261
262
263
264
265
typedef struct _cairo_ft_unscaled_font_map {
    cairo_hash_table_t *hash_table;
    FT_Library ft_library;
    int num_open_faces;
} cairo_ft_unscaled_font_map_t;
266

267
static cairo_ft_unscaled_font_map_t *cairo_ft_unscaled_font_map = NULL;
268

269

270
271
272
273
274
275
276
277
278
279
static FT_Face
_cairo_ft_unscaled_font_lock_face (cairo_ft_unscaled_font_t *unscaled);

static void
_cairo_ft_unscaled_font_unlock_face (cairo_ft_unscaled_font_t *unscaled);

static cairo_bool_t
_cairo_ft_scaled_font_is_vertical (cairo_scaled_font_t *scaled_font);


Carl Worth's avatar
Carl Worth committed
280
281
282
283
284
285
286
287
288
289
290
291
292
static void
_font_map_release_face_lock_held (cairo_ft_unscaled_font_map_t *font_map,
				  cairo_ft_unscaled_font_t *unscaled)
{
    if (unscaled->face) {
	FT_Done_Face (unscaled->face);
	unscaled->face = NULL;
	unscaled->have_scale = FALSE;

	font_map->num_open_faces--;
    }
}

293
static cairo_status_t
294
_cairo_ft_unscaled_font_map_create (void)
Graydon Hoare's avatar
Graydon Hoare committed
295
{
296
    cairo_ft_unscaled_font_map_t *font_map;
297

298
299
300
301
    /* This function is only intended to be called from
     * _cairo_ft_unscaled_font_map_lock. So we'll crash if we can
     * detect some other call path. */
    assert (cairo_ft_unscaled_font_map == NULL);
Graydon Hoare's avatar
Graydon Hoare committed
302

303
    font_map = _cairo_malloc (sizeof (cairo_ft_unscaled_font_map_t));
304
305
    if (unlikely (font_map == NULL))
	return _cairo_error (CAIRO_STATUS_NO_MEMORY);
Graydon Hoare's avatar
Graydon Hoare committed
306

307
308
    font_map->hash_table =
	_cairo_hash_table_create (_cairo_ft_unscaled_font_keys_equal);
Graydon Hoare's avatar
Graydon Hoare committed
309

310
    if (unlikely (font_map->hash_table == NULL))
311
	goto FAIL;
312

313
    if (unlikely (FT_Init_FreeType (&font_map->ft_library)))
314
	goto FAIL;
Graydon Hoare's avatar
Graydon Hoare committed
315

316
317
318
    font_map->num_open_faces = 0;

    cairo_ft_unscaled_font_map = font_map;
319
    return CAIRO_STATUS_SUCCESS;
320
321

FAIL:
322
323
324
325
326
    if (font_map->hash_table)
	_cairo_hash_table_destroy (font_map->hash_table);
    free (font_map);

    return _cairo_error (CAIRO_STATUS_NO_MEMORY);
327
}
328

329
330
331
332
333
334
335
336
337
338

static void
_cairo_ft_unscaled_font_map_pluck_entry (void *entry, void *closure)
{
    cairo_ft_unscaled_font_t *unscaled = entry;
    cairo_ft_unscaled_font_map_t *font_map = closure;

    _cairo_hash_table_remove (font_map->hash_table,
			      &unscaled->base.hash_entry);

339
340
341
    if (! unscaled->from_face)
	_font_map_release_face_lock_held (font_map, unscaled);

342
343
344
345
    _cairo_ft_unscaled_font_fini (unscaled);
    free (unscaled);
}

346
347
static void
_cairo_ft_unscaled_font_map_destroy (void)
Graydon Hoare's avatar
Graydon Hoare committed
348
{
349
    cairo_ft_unscaled_font_map_t *font_map;
350

351
    CAIRO_MUTEX_LOCK (_cairo_ft_unscaled_font_map_mutex);
352
353
354
    font_map = cairo_ft_unscaled_font_map;
    cairo_ft_unscaled_font_map = NULL;
    CAIRO_MUTEX_UNLOCK (_cairo_ft_unscaled_font_map_mutex);
355

356
357
358
359
    if (font_map != NULL) {
	_cairo_hash_table_foreach (font_map->hash_table,
				   _cairo_ft_unscaled_font_map_pluck_entry,
				   font_map);
Carl Worth's avatar
Carl Worth committed
360
361
	assert (font_map->num_open_faces == 0);

362
363
364
365
366
367
368
	FT_Done_FreeType (font_map->ft_library);

	_cairo_hash_table_destroy (font_map->hash_table);

	free (font_map);
    }
}
369

370
371
static cairo_ft_unscaled_font_map_t *
_cairo_ft_unscaled_font_map_lock (void)
Graydon Hoare's avatar
Graydon Hoare committed
372
{
373
374
    CAIRO_MUTEX_INITIALIZE ();

375
    CAIRO_MUTEX_LOCK (_cairo_ft_unscaled_font_map_mutex);
376

377
378
    if (unlikely (cairo_ft_unscaled_font_map == NULL)) {
	if (unlikely (_cairo_ft_unscaled_font_map_create ())) {
379
	    CAIRO_MUTEX_UNLOCK (_cairo_ft_unscaled_font_map_mutex);
380
381
382
383
384
	    return NULL;
	}
    }

    return cairo_ft_unscaled_font_map;
Graydon Hoare's avatar
Graydon Hoare committed
385
386
387
}

static void
388
_cairo_ft_unscaled_font_map_unlock (void)
Graydon Hoare's avatar
Graydon Hoare committed
389
{
390
    CAIRO_MUTEX_UNLOCK (_cairo_ft_unscaled_font_map_mutex);
Graydon Hoare's avatar
Graydon Hoare committed
391
392
}

393
static void
394
_cairo_ft_unscaled_font_init_key (cairo_ft_unscaled_font_t *key,
395
				  cairo_bool_t              from_face,
396
				  char			   *filename,
397
398
				  int			    id,
				  FT_Face		    face)
Graydon Hoare's avatar
Graydon Hoare committed
399
{
400
    unsigned long hash;
Graydon Hoare's avatar
Graydon Hoare committed
401

402
    key->from_face = from_face;
403
404
    key->filename = filename;
    key->id = id;
405
    key->face = face;
406

407
    hash = _cairo_hash_string (filename);
408
    /* the constants are just arbitrary primes */
409
    hash += ((unsigned long) id) * 1607;
410
    hash += ((unsigned long) face) * 2137;
411

412
413
    key->base.hash_entry.hash = hash;
}
414

415
416
/**
 * _cairo_ft_unscaled_font_init:
417
 *
418
 * Initialize a #cairo_ft_unscaled_font_t.
419
 *
420
 * There are two basic flavors of #cairo_ft_unscaled_font_t, one
421
422
423
 * created from an FT_Face and the other created from a filename/id
 * pair. These two flavors are identified as from_face and !from_face.
 *
424
 * To initialize a from_face font, pass filename==%NULL, id=0 and the
425
426
427
 * desired face.
 *
 * To initialize a !from_face font, pass the filename/id as desired
428
 * and face==%NULL.
429
430
431
 *
 * Note that the code handles these two flavors in very distinct
 * ways. For example there is a hash_table mapping
432
 * filename/id->#cairo_unscaled_font_t in the !from_face case, but no
433
434
435
436
437
 * parallel in the from_face case, (where the calling code would have
 * to do its own mapping to ensure similar sharing).
 **/
static cairo_status_t
_cairo_ft_unscaled_font_init (cairo_ft_unscaled_font_t *unscaled,
438
			      cairo_bool_t              from_face,
439
440
441
442
			      const char	       *filename,
			      int			id,
			      FT_Face			face)
{
Carl Worth's avatar
Carl Worth committed
443
444
    _cairo_unscaled_font_init (&unscaled->base,
			       &cairo_ft_unscaled_font_backend);
445

446
447
    unscaled->variations = NULL;

448
    if (from_face) {
Carl Worth's avatar
Carl Worth committed
449
	unscaled->from_face = TRUE;
450
	_cairo_ft_unscaled_font_init_key (unscaled, TRUE, NULL, id, face);
451

452

453
454
        unscaled->have_color = FT_HAS_COLOR (face) != 0;
        unscaled->have_color_set = TRUE;
455

456
#ifdef HAVE_FT_GET_VAR_DESIGN_COORDINATES
457
458
459
460
461
462
463
	{
	    FT_MM_Var *ft_mm_var;
	    if (0 == FT_Get_MM_Var (face, &ft_mm_var))
	    {
		unscaled->variations = calloc (ft_mm_var->num_axis, sizeof (FT_Fixed));
		if (unscaled->variations)
		    FT_Get_Var_Design_Coordinates (face, ft_mm_var->num_axis, unscaled->variations);
464
465
466
467
468
#if HAVE_FT_DONE_MM_VAR
		FT_Done_MM_Var (face->glyph->library, ft_mm_var);
#else
		free (ft_mm_var);
#endif
469
470
	    }
	}
471
#endif
472
    } else {
Carl Worth's avatar
Carl Worth committed
473
474
475
	char *filename_copy;

	unscaled->from_face = FALSE;
476
	unscaled->face = NULL;
Carl Worth's avatar
Carl Worth committed
477
478

	filename_copy = strdup (filename);
479
	if (unlikely (filename_copy == NULL))
480
	    return _cairo_error (CAIRO_STATUS_NO_MEMORY);
481

482
	_cairo_ft_unscaled_font_init_key (unscaled, FALSE, filename_copy, id, NULL);
483

484
	unscaled->have_color_set = FALSE;
485
    }
486

Carl Worth's avatar
Carl Worth committed
487
    unscaled->have_scale = FALSE;
488
    CAIRO_MUTEX_INIT (unscaled->mutex);
489
    unscaled->lock_count = 0;
490

491
    unscaled->faces = NULL;
492

493
494
495
    return CAIRO_STATUS_SUCCESS;
}

Carl Worth's avatar
Carl Worth committed
496
497
/**
 * _cairo_ft_unscaled_font_fini:
498
 *
499
 * Free all data associated with a #cairo_ft_unscaled_font_t.
Carl Worth's avatar
Carl Worth committed
500
 *
501
 * CAUTION: The unscaled->face field must be %NULL before calling this
502
 * function. This is because the #cairo_ft_unscaled_font_t_map keeps a
Carl Worth's avatar
Carl Worth committed
503
504
505
506
 * count of these faces (font_map->num_open_faces) so it maintains the
 * unscaled->face field while it has its lock held. See
 * _font_map_release_face_lock_held().
 **/
507
508
509
static void
_cairo_ft_unscaled_font_fini (cairo_ft_unscaled_font_t *unscaled)
{
Carl Worth's avatar
Carl Worth committed
510
511
    assert (unscaled->face == NULL);

512
513
    free (unscaled->filename);
    unscaled->filename = NULL;
514

515
516
    free (unscaled->variations);

517
    CAIRO_MUTEX_FINI (unscaled->mutex);
518
519
520
}

static int
521
522
_cairo_ft_unscaled_font_keys_equal (const void *key_a,
				    const void *key_b)
523
{
524
525
    const cairo_ft_unscaled_font_t *unscaled_a = key_a;
    const cairo_ft_unscaled_font_t *unscaled_b = key_b;
526

527
    if (unscaled_a->id == unscaled_b->id &&
528
	unscaled_a->from_face == unscaled_b->from_face)
529
     {
530
531
532
        if (unscaled_a->from_face)
	    return unscaled_a->face == unscaled_b->face;

533
	if (unscaled_a->filename == NULL && unscaled_b->filename == NULL)
534
	    return TRUE;
535
	else if (unscaled_a->filename == NULL || unscaled_b->filename == NULL)
536
537
538
539
540
541
	    return FALSE;
	else
	    return (strcmp (unscaled_a->filename, unscaled_b->filename) == 0);
    }

    return FALSE;
Graydon Hoare's avatar
Graydon Hoare committed
542
543
}

544
/* Finds or creates a #cairo_ft_unscaled_font_t for the filename/id from
545
 * pattern.  Returns a new reference to the unscaled font.
546
 */
547
static cairo_status_t
548
549
550
_cairo_ft_unscaled_font_create_internal (cairo_bool_t from_face,
					 char *filename,
					 int id,
551
552
					 FT_Face font_face,
					 cairo_ft_unscaled_font_t **out)
553
{
554
555
    cairo_ft_unscaled_font_t key, *unscaled;
    cairo_ft_unscaled_font_map_t *font_map;
556
    cairo_status_t status;
557

558
    font_map = _cairo_ft_unscaled_font_map_lock ();
559
    if (unlikely (font_map == NULL))
560
	return _cairo_error (CAIRO_STATUS_NO_MEMORY);
561

562
    _cairo_ft_unscaled_font_init_key (&key, from_face, filename, id, font_face);
563

Christian Biesinger's avatar
Christian Biesinger committed
564
    /* Return existing unscaled font if it exists in the hash table. */
Chris Wilson's avatar
Chris Wilson committed
565
566
567
    unscaled = _cairo_hash_table_lookup (font_map->hash_table,
					 &key.base.hash_entry);
    if (unscaled != NULL) {
568
	_cairo_unscaled_font_reference (&unscaled->base);
569
	goto DONE;
570
571
    }

572
    /* Otherwise create it and insert into hash table. */
573
    unscaled = _cairo_malloc (sizeof (cairo_ft_unscaled_font_t));
574
    if (unlikely (unscaled == NULL)) {
575
	status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
576
	goto UNWIND_FONT_MAP_LOCK;
577
    }
578

579
    status = _cairo_ft_unscaled_font_init (unscaled, from_face, filename, id, font_face);
580
    if (unlikely (status))
581
	goto UNWIND_UNSCALED_MALLOC;
582

583
    assert (unscaled->base.hash_entry.hash == key.base.hash_entry.hash);
584
585
    status = _cairo_hash_table_insert (font_map->hash_table,
				       &unscaled->base.hash_entry);
586
    if (unlikely (status))
587
588
	goto UNWIND_UNSCALED_FONT_INIT;

589
DONE:
590
    _cairo_ft_unscaled_font_map_unlock ();
591
592
    *out = unscaled;
    return CAIRO_STATUS_SUCCESS;
593
594
595
596
597
598
599

UNWIND_UNSCALED_FONT_INIT:
    _cairo_ft_unscaled_font_fini (unscaled);
UNWIND_UNSCALED_MALLOC:
    free (unscaled);
UNWIND_FONT_MAP_LOCK:
    _cairo_ft_unscaled_font_map_unlock ();
600
    return status;
601
602
}

603

604
#if CAIRO_HAS_FC_FONT
605
606
607
static cairo_status_t
_cairo_ft_unscaled_font_create_for_pattern (FcPattern *pattern,
					    cairo_ft_unscaled_font_t **out)
608
{
609
610
611
    FT_Face font_face = NULL;
    char *filename = NULL;
    int id = 0;
612
    FcResult ret;
613

614
    ret = FcPatternGetFTFace (pattern, FC_FT_FACE, 0, &font_face);
615
616
617
618
619
620
621
622
623
    if (ret == FcResultMatch)
	goto DONE;
    if (ret == FcResultOutOfMemory)
	return _cairo_error (CAIRO_STATUS_NO_MEMORY);

    ret = FcPatternGetString (pattern, FC_FILE, 0, (FcChar8 **) &filename);
    if (ret == FcResultOutOfMemory)
	return _cairo_error (CAIRO_STATUS_NO_MEMORY);
    if (ret == FcResultMatch) {
624
625
626
627
628
	if (access (filename, R_OK) == 0) {
	    /* If FC_INDEX is not set, we just use 0 */
	    ret = FcPatternGetInteger (pattern, FC_INDEX, 0, &id);
	    if (ret == FcResultOutOfMemory)
		return _cairo_error (CAIRO_STATUS_NO_MEMORY);
629

630
	    goto DONE;
631
632
	} else
	    return _cairo_error (CAIRO_STATUS_FILE_NOT_FOUND);
633
634
    }

635
636
637
    /* The pattern contains neither a face nor a filename, resolve it later. */
    *out = NULL;
    return CAIRO_STATUS_SUCCESS;
638
639

DONE:
640
641
642
    return _cairo_ft_unscaled_font_create_internal (font_face != NULL,
						    filename, id, font_face,
						    out);
643
}
644
#endif
645

646
647
648
static cairo_status_t
_cairo_ft_unscaled_font_create_from_face (FT_Face face,
					  cairo_ft_unscaled_font_t **out)
649
{
650
    return _cairo_ft_unscaled_font_create_internal (TRUE, NULL, face->face_index, face, out);
651
652
}

653
static cairo_bool_t
654
655
656
_cairo_ft_unscaled_font_destroy (void *abstract_font)
{
    cairo_ft_unscaled_font_t *unscaled  = abstract_font;
657
    cairo_ft_unscaled_font_map_t *font_map;
658

659
660
661
662
    font_map = _cairo_ft_unscaled_font_map_lock ();
    /* All created objects must have been mapped in the font map. */
    assert (font_map != NULL);

663
    if (! _cairo_reference_count_dec_and_test (&unscaled->base.ref_count)) {
664
665
	/* somebody recreated the font whilst we waited for the lock */
	_cairo_ft_unscaled_font_map_unlock ();
666
	return FALSE;
667
668
    }

669
670
671
    _cairo_hash_table_remove (font_map->hash_table,
			      &unscaled->base.hash_entry);

672
673
674
675
    if (unscaled->from_face) {
	/* See comments in _ft_font_face_destroy about the "zombie" state
	 * for a _ft_font_face.
	 */
676
677
	if (unscaled->faces && unscaled->faces->unscaled == NULL) {
	    assert (unscaled->faces->next == NULL);
678
	    cairo_font_face_destroy (&unscaled->faces->base);
679
	}
680
    } else {
Carl Worth's avatar
Carl Worth committed
681
	_font_map_release_face_lock_held (font_map, unscaled);
682
    }
683
684
685
686
    unscaled->face = NULL;

    _cairo_ft_unscaled_font_map_unlock ();

687
    _cairo_ft_unscaled_font_fini (unscaled);
688
    return TRUE;
689
690
}

691
static cairo_bool_t
692
_has_unlocked_face (const void *entry)
693
{
694
    const cairo_ft_unscaled_font_t *unscaled = entry;
Graydon Hoare's avatar
Graydon Hoare committed
695

696
    return (!unscaled->from_face && unscaled->lock_count == 0 && unscaled->face);
697
698
699
700
}

/* Ensures that an unscaled font has a face object. If we exceed
 * MAX_OPEN_FACES, try to close some.
701
702
703
 *
 * This differs from _cairo_ft_scaled_font_lock_face in that it doesn't
 * set the scale on the face, but just returns it at the last scale.
704
 */
705
static cairo_warn FT_Face
706
_cairo_ft_unscaled_font_lock_face (cairo_ft_unscaled_font_t *unscaled)
707
{
708
    cairo_ft_unscaled_font_map_t *font_map;
709
    FT_Face face = NULL;
710
    FT_Error error;
711

712
    CAIRO_MUTEX_LOCK (unscaled->mutex);
713
    unscaled->lock_count++;
714

715
716
    font_map = _cairo_ft_unscaled_font_map_lock ();

717
    if (unscaled->face)
718
719
    {
        _cairo_ft_unscaled_font_map_unlock ();
720
	return unscaled->face;
721
    }
722

Carl Worth's avatar
Carl Worth committed
723
    /* If this unscaled font was created from an FT_Face then we just
724
     * returned it above. */
725
    assert (!unscaled->from_face);
726

727
    {
728
	assert (font_map != NULL);
729

730
731
732
733
734
735
736
737
	while (font_map->num_open_faces >= MAX_OPEN_FACES)
	{
	    cairo_ft_unscaled_font_t *entry;

	    entry = _cairo_hash_table_random_entry (font_map->hash_table,
						    _has_unlocked_face);
	    if (entry == NULL)
		break;
738

739
740
	    _font_map_release_face_lock_held (font_map, entry);
	}
741
    }
742
    _cairo_ft_unscaled_font_map_unlock ();
743

744
745
746
747
748
    error = FT_New_Face (font_map->ft_library,
			 unscaled->filename,
			 unscaled->id,
			 &face);
    if (error)
749
    {
750
	unscaled->lock_count--;
751
	CAIRO_MUTEX_UNLOCK (unscaled->mutex);
752
	_cairo_error_throw (_ft_to_cairo_error (error));
753
754
	return NULL;
    }
755
756

    unscaled->face = face;
757

758
759
760
    unscaled->have_color = FT_HAS_COLOR (face) != 0;
    unscaled->have_color_set = TRUE;

761
    font_map->num_open_faces++;
762
763
764

    return face;
}
765

766

767
/* Unlock unscaled font locked with _cairo_ft_unscaled_font_lock_face
768
 */
769
static void
770
_cairo_ft_unscaled_font_unlock_face (cairo_ft_unscaled_font_t *unscaled)
771
{
772
    assert (unscaled->lock_count > 0);
773

774
    unscaled->lock_count--;
775

776
    CAIRO_MUTEX_UNLOCK (unscaled->mutex);
777
}
778

779

780
static cairo_status_t
781
_compute_transform (cairo_ft_font_transform_t *sf,
782
783
		    cairo_matrix_t      *scale,
		    cairo_ft_unscaled_font_t *unscaled)
784
{
785
    cairo_status_t status;
786
    double x_scale, y_scale;
787
    cairo_matrix_t normalized = *scale;
788

789
790
791
792
793
794
795
    /* The font matrix has x and y "scale" components which we extract and
     * use as character scale values. These influence the way freetype
     * chooses hints, as well as selecting different bitmaps in
     * hand-rendered fonts. We also copy the normalized matrix to
     * freetype's transformation.
     */

796
    status = _cairo_matrix_compute_basis_scale_factors (scale,
797
						  &x_scale, &y_scale,
Behdad Esfahbod's avatar
Behdad Esfahbod committed
798
						  1);
799
    if (unlikely (status))
800
	return status;
801

802
803
804
805
806
807
808
809
    /* FreeType docs say this about x_scale and y_scale:
     * "A character width or height smaller than 1pt is set to 1pt;"
     * So, we cap them from below at 1.0 and let the FT transform
     * take care of sub-1.0 scaling. */
    if (x_scale < 1.0)
      x_scale = 1.0;
    if (y_scale < 1.0)
      y_scale = 1.0;
810

811
812
    if (unscaled && (unscaled->face->face_flags & FT_FACE_FLAG_SCALABLE) == 0) {
	double min_distance = DBL_MAX;
813
	cairo_bool_t magnify = TRUE;
814
815
816
817
818
	int i;
	double best_x_size = 0;
	double best_y_size = 0;

	for (i = 0; i < unscaled->face->num_fixed_sizes; i++) {
819
	    double x_size = unscaled->face->available_sizes[i].x_ppem / 64.;
820
	    double y_size = unscaled->face->available_sizes[i].y_ppem / 64.;
821
822
823
824
825
826
827
828
829
830
831
	    double distance = y_size - y_scale;

	    /*
	     * distance is positive if current strike is larger than desired
	     * size, and negative if smaller.
	     *
	     * We like to prefer down-scaling to upscaling.
	     */

	    if ((magnify && distance >= 0) || fabs (distance) <= min_distance) {
		magnify = distance < 0;
832
		min_distance = fabs (distance);
833
834
835
836
837
838
839
840
841
		best_x_size = x_size;
		best_y_size = y_size;
	    }
	}

	x_scale = best_x_size;
	y_scale = best_y_size;
    }