LCOV - code coverage report
Current view: directory - gfx/cairo/cairo/src - cairo-ft-font.c (source / functions) Found Hit Coverage
Test: app.info Lines: 1252 8 0.6 %
Date: 2012-06-02 Functions: 56 2 3.6 %

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

Generated by: LCOV version 1.7