LCOV - code coverage report
Current view: top level - gfx/cairo/cairo/src - cairo-ft-font.c (source / functions) Hit Total Coverage
Test: output.info Lines: 337 1301 25.9 %
Date: 2017-07-14 16:53:18 Functions: 23 56 41.1 %
Legend: Lines: hit not hit

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

Generated by: LCOV version 1.13