LCOV - code coverage report
Current view: top level - gfx/cairo/cairo/src - cairo-cff-subset.c (source / functions) Hit Total Coverage
Test: output.info Lines: 0 1172 0.0 %
Date: 2017-07-14 16:53:18 Functions: 0 68 0.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* cairo - a vector graphics library with display and print output
       2             :  *
       3             :  * Copyright © 2006 Adrian Johnson
       4             :  *
       5             :  * This library is free software; you can redistribute it and/or
       6             :  * modify it either under the terms of the GNU Lesser General Public
       7             :  * License version 2.1 as published by the Free Software Foundation
       8             :  * (the "LGPL") or, at your option, under the terms of the Mozilla
       9             :  * Public License Version 1.1 (the "MPL"). If you do not alter this
      10             :  * notice, a recipient may use your version of this file under either
      11             :  * the MPL or the LGPL.
      12             :  *
      13             :  * You should have received a copy of the LGPL along with this library
      14             :  * in the file COPYING-LGPL-2.1; if not, write to the Free Software
      15             :  * Foundation, Inc., 51 Franklin Street, Suite 500, Boston, MA 02110-1335, USA
      16             :  * You should have received a copy of the MPL along with this library
      17             :  * in the file COPYING-MPL-1.1
      18             :  *
      19             :  * The contents of this file are subject to the Mozilla Public License
      20             :  * Version 1.1 (the "License"); you may not use this file except in
      21             :  * compliance with the License. You may obtain a copy of the License at
      22             :  * http://www.mozilla.org/MPL/
      23             :  *
      24             :  * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
      25             :  * OF ANY KIND, either express or implied. See the LGPL or the MPL for
      26             :  * the specific language governing rights and limitations.
      27             :  *
      28             :  * The Original Code is the cairo graphics library.
      29             :  *
      30             :  * The Initial Developer of the Original Code is Adrian Johnson.
      31             :  *
      32             :  * Contributor(s):
      33             :  *      Adrian Johnson <ajohnson@redneon.com>
      34             :  *      Eugeniy Meshcheryakov <eugen@debian.org>
      35             :  */
      36             : 
      37             : /*
      38             :  * Useful links:
      39             :  * http://www.adobe.com/devnet/font/pdfs/5176.CFF.pdf
      40             :  */
      41             : 
      42             : #define _BSD_SOURCE /* for snprintf(), strdup() */
      43             : #include "cairoint.h"
      44             : #include "cairo-error-private.h"
      45             : 
      46             : #if CAIRO_HAS_FONT_SUBSET
      47             : 
      48             : #include "cairo-scaled-font-subsets-private.h"
      49             : #include "cairo-truetype-subset-private.h"
      50             : #include <string.h>
      51             : 
      52             : /* CFF Dict Operators. If the high byte is 0 the command is encoded
      53             :  * with a single byte. */
      54             : #define BASEFONTNAME_OP  0x0c16
      55             : #define CIDCOUNT_OP      0x0c22
      56             : #define CHARSET_OP       0x000f
      57             : #define CHARSTRINGS_OP   0x0011
      58             : #define COPYRIGHT_OP     0x0c00
      59             : #define ENCODING_OP      0x0010
      60             : #define FAMILYNAME_OP    0x0003
      61             : #define FDARRAY_OP       0x0c24
      62             : #define FDSELECT_OP      0x0c25
      63             : #define FONTBBOX_OP      0x0005
      64             : #define FONTNAME_OP      0x0c26
      65             : #define FULLNAME_OP      0x0002
      66             : #define LOCAL_SUB_OP     0x0013
      67             : #define NOTICE_OP        0x0001
      68             : #define POSTSCRIPT_OP    0x0c15
      69             : #define PRIVATE_OP       0x0012
      70             : #define ROS_OP           0x0c1e
      71             : #define UNIQUEID_OP      0x000d
      72             : #define VERSION_OP       0x0000
      73             : #define WEIGHT_OP        0x0004
      74             : #define XUID_OP          0x000e
      75             : 
      76             : #define NUM_STD_STRINGS 391
      77             : 
      78             : typedef struct _cff_header {
      79             :     uint8_t major;
      80             :     uint8_t minor;
      81             :     uint8_t header_size;
      82             :     uint8_t offset_size;
      83             : } cff_header_t;
      84             : 
      85             : typedef struct _cff_index_element {
      86             :     cairo_bool_t   is_copy;
      87             :     unsigned char *data;
      88             :     int            length;
      89             : } cff_index_element_t;
      90             : 
      91             : typedef struct _cff_dict_operator {
      92             :     cairo_hash_entry_t base;
      93             : 
      94             :     unsigned short operator;
      95             :     unsigned char *operand;
      96             :     int            operand_length;
      97             :     int            operand_offset;
      98             : } cff_dict_operator_t;
      99             : 
     100             : typedef struct _cairo_cff_font {
     101             : 
     102             :     cairo_scaled_font_subset_t *scaled_font_subset;
     103             :     const cairo_scaled_font_backend_t *backend;
     104             : 
     105             :     /* Font Data */
     106             :     unsigned char       *data;
     107             :     unsigned long        data_length;
     108             :     unsigned char       *current_ptr;
     109             :     unsigned char       *data_end;
     110             :     cff_header_t        *header;
     111             :     char                *font_name;
     112             :     char                *ps_name;
     113             :     cairo_hash_table_t  *top_dict;
     114             :     cairo_hash_table_t  *private_dict;
     115             :     cairo_array_t        strings_index;
     116             :     cairo_array_t        charstrings_index;
     117             :     cairo_array_t        global_sub_index;
     118             :     cairo_array_t        local_sub_index;
     119             :     int                  num_glyphs;
     120             :     cairo_bool_t         is_cid;
     121             :     int                  units_per_em;
     122             : 
     123             :     /* CID Font Data */
     124             :     int                 *fdselect;
     125             :     unsigned int         num_fontdicts;
     126             :     cairo_hash_table_t **fd_dict;
     127             :     cairo_hash_table_t **fd_private_dict;
     128             :     cairo_array_t       *fd_local_sub_index;
     129             : 
     130             :     /* Subsetted Font Data */
     131             :     char                *subset_font_name;
     132             :     cairo_array_t        charstrings_subset_index;
     133             :     cairo_array_t        strings_subset_index;
     134             :     int                 *fdselect_subset;
     135             :     unsigned int         num_subset_fontdicts;
     136             :     int                 *fd_subset_map;
     137             :     int                 *private_dict_offset;
     138             :     cairo_array_t        output;
     139             : 
     140             :     /* Subset Metrics */
     141             :     int                 *widths;
     142             :     int                  x_min, y_min, x_max, y_max;
     143             :     int                  ascent, descent;
     144             : 
     145             : } cairo_cff_font_t;
     146             : 
     147             : /* Encoded integer using maximum sized encoding. This is required for
     148             :  * operands that are later modified after encoding. */
     149             : static unsigned char *
     150           0 : encode_integer_max (unsigned char *p, int i)
     151             : {
     152           0 :     *p++ = 29;
     153           0 :     *p++ = i >> 24;
     154           0 :     *p++ = (i >> 16) & 0xff;
     155           0 :     *p++ = (i >> 8)  & 0xff;
     156           0 :     *p++ = i & 0xff;
     157           0 :     return p;
     158             : }
     159             : 
     160             : static unsigned char *
     161           0 : encode_integer (unsigned char *p, int i)
     162             : {
     163           0 :     if (i >= -107 && i <= 107) {
     164           0 :         *p++ = i + 139;
     165           0 :     } else if (i >= 108 && i <= 1131) {
     166           0 :         i -= 108;
     167           0 :         *p++ = (i >> 8)+ 247;
     168           0 :         *p++ = i & 0xff;
     169           0 :     } else if (i >= -1131 && i <= -108) {
     170           0 :         i = -i - 108;
     171           0 :         *p++ = (i >> 8)+ 251;
     172           0 :         *p++ = i & 0xff;
     173           0 :     } else if (i >= -32768 && i <= 32767) {
     174           0 :         *p++ = 28;
     175           0 :         *p++ = (i >> 8)  & 0xff;
     176           0 :         *p++ = i & 0xff;
     177             :     } else {
     178           0 :         p = encode_integer_max (p, i);
     179             :     }
     180           0 :     return p;
     181             : }
     182             : 
     183             : static unsigned char *
     184           0 : decode_integer (unsigned char *p, int *integer)
     185             : {
     186           0 :     if (*p == 28) {
     187           0 :         *integer = (int)(p[1]<<8 | p[2]);
     188           0 :         p += 3;
     189           0 :     } else if (*p == 29) {
     190           0 :         *integer = (int)((p[1] << 24) | (p[2] << 16) | (p[3] << 8) | p[4]);
     191           0 :         p += 5;
     192           0 :     } else if (*p >= 32 && *p <= 246) {
     193           0 :         *integer = *p++ - 139;
     194           0 :     } else if (*p <= 250) {
     195           0 :         *integer = (p[0] - 247) * 256 + p[1] + 108;
     196           0 :         p += 2;
     197           0 :     } else if (*p <= 254) {
     198           0 :         *integer = -(p[0] - 251) * 256 - p[1] - 108;
     199           0 :         p += 2;
     200             :     } else {
     201           0 :         *integer = 0;
     202           0 :         p += 1;
     203             :     }
     204           0 :     return p;
     205             : }
     206             : 
     207             : static unsigned char *
     208           0 : decode_operator (unsigned char *p, unsigned short *operator)
     209             : {
     210           0 :     unsigned short op = 0;
     211             : 
     212           0 :     op = *p++;
     213           0 :     if (op == 12) {
     214           0 :         op <<= 8;
     215           0 :         op |= *p++;
     216             :     }
     217           0 :     *operator = op;
     218           0 :     return p;
     219             : }
     220             : 
     221             : /* return 0 if not an operand */
     222             : static int
     223           0 : operand_length (unsigned char *p)
     224             : {
     225           0 :     unsigned char *begin = p;
     226             : 
     227           0 :     if (*p == 28)
     228           0 :         return 3;
     229             : 
     230           0 :     if (*p == 29)
     231           0 :         return 5;
     232             : 
     233           0 :     if (*p >= 32 && *p <= 246)
     234           0 :         return 1;
     235             : 
     236           0 :     if (*p >= 247 && *p <= 254)
     237           0 :         return 2;
     238             : 
     239           0 :     if (*p == 30) {
     240           0 :         while ((*p & 0x0f) != 0x0f)
     241           0 :             p++;
     242           0 :         return p - begin + 1;
     243             :     }
     244             : 
     245           0 :     return 0;
     246             : }
     247             : 
     248             : static unsigned char *
     249           0 : encode_index_offset (unsigned char *p, int offset_size, unsigned long offset)
     250             : {
     251           0 :     while (--offset_size >= 0) {
     252           0 :         p[offset_size] = (unsigned char) (offset & 0xff);
     253           0 :         offset >>= 8;
     254             :     }
     255           0 :     return p + offset_size;
     256             : }
     257             : 
     258             : static unsigned long
     259           0 : decode_index_offset(unsigned char *p, int off_size)
     260             : {
     261           0 :     unsigned long offset = 0;
     262             : 
     263           0 :     while (off_size-- > 0)
     264           0 :         offset = offset*256 + *p++;
     265           0 :     return offset;
     266             : }
     267             : 
     268             : static void
     269           0 : cff_index_init (cairo_array_t *index)
     270             : {
     271           0 :     _cairo_array_init (index, sizeof (cff_index_element_t));
     272           0 : }
     273             : 
     274             : static cairo_int_status_t
     275           0 : cff_index_read (cairo_array_t *index, unsigned char **ptr, unsigned char *end_ptr)
     276             : {
     277             :     cff_index_element_t element;
     278             :     unsigned char *data, *p;
     279             :     cairo_status_t status;
     280             :     int offset_size, count, start, i;
     281           0 :     int end = 0;
     282             : 
     283           0 :     p = *ptr;
     284           0 :     if (p + 2 > end_ptr)
     285           0 :         return CAIRO_INT_STATUS_UNSUPPORTED;
     286           0 :     count = be16_to_cpu( *((uint16_t *)p) );
     287           0 :     p += 2;
     288           0 :     if (count > 0) {
     289           0 :         offset_size = *p++;
     290           0 :         if (p + (count + 1)*offset_size > end_ptr)
     291           0 :             return CAIRO_INT_STATUS_UNSUPPORTED;
     292           0 :         data = p + offset_size*(count + 1) - 1;
     293           0 :         start = decode_index_offset (p, offset_size);
     294           0 :         p += offset_size;
     295           0 :         for (i = 0; i < count; i++) {
     296           0 :             end = decode_index_offset (p, offset_size);
     297           0 :             p += offset_size;
     298           0 :             if (p > end_ptr)
     299           0 :                 return CAIRO_INT_STATUS_UNSUPPORTED;
     300           0 :             element.length = end - start;
     301           0 :             element.is_copy = FALSE;
     302           0 :             element.data = data + start;
     303           0 :             status = _cairo_array_append (index, &element);
     304           0 :             if (unlikely (status))
     305           0 :                 return status;
     306           0 :             start = end;
     307             :         }
     308           0 :         p = data + end;
     309             :     }
     310           0 :     *ptr = p;
     311             : 
     312           0 :     return CAIRO_STATUS_SUCCESS;
     313             : }
     314             : 
     315             : static cairo_status_t
     316           0 : cff_index_write (cairo_array_t *index, cairo_array_t *output)
     317             : {
     318             :     int offset_size;
     319             :     int offset;
     320             :     int num_elem;
     321             :     int i;
     322             :     cff_index_element_t *element;
     323             :     uint16_t count;
     324             :     unsigned char buf[5];
     325             :     cairo_status_t status;
     326             : 
     327           0 :     num_elem = _cairo_array_num_elements (index);
     328           0 :     count = cpu_to_be16 ((uint16_t) num_elem);
     329           0 :     status = _cairo_array_append_multiple (output, &count, 2);
     330           0 :     if (unlikely (status))
     331           0 :         return status;
     332             : 
     333           0 :     if (num_elem == 0)
     334           0 :         return CAIRO_STATUS_SUCCESS;
     335             : 
     336             :     /* Find maximum offset to determine offset size */
     337           0 :     offset = 1;
     338           0 :     for (i = 0; i < num_elem; i++) {
     339           0 :         element = _cairo_array_index (index, i);
     340           0 :         offset += element->length;
     341             :     }
     342           0 :     if (offset < 0x100)
     343           0 :         offset_size = 1;
     344           0 :     else if (offset < 0x10000)
     345           0 :         offset_size = 2;
     346           0 :     else if (offset < 0x1000000)
     347           0 :         offset_size = 3;
     348             :     else
     349           0 :         offset_size = 4;
     350             : 
     351           0 :     buf[0] = (unsigned char) offset_size;
     352           0 :     status = _cairo_array_append (output, buf);
     353           0 :     if (unlikely (status))
     354           0 :         return status;
     355             : 
     356           0 :     offset = 1;
     357           0 :     encode_index_offset (buf, offset_size, offset);
     358           0 :     status = _cairo_array_append_multiple (output, buf, offset_size);
     359           0 :     if (unlikely (status))
     360           0 :         return status;
     361             : 
     362           0 :     for (i = 0; i < num_elem; i++) {
     363           0 :         element = _cairo_array_index (index, i);
     364           0 :         offset += element->length;
     365           0 :         encode_index_offset (buf, offset_size, offset);
     366           0 :         status = _cairo_array_append_multiple (output, buf, offset_size);
     367           0 :         if (unlikely (status))
     368           0 :             return status;
     369             :     }
     370             : 
     371           0 :     for (i = 0; i < num_elem; i++) {
     372           0 :         element = _cairo_array_index (index, i);
     373           0 :         status = _cairo_array_append_multiple (output,
     374           0 :                                                element->data,
     375             :                                                element->length);
     376           0 :         if (unlikely (status))
     377           0 :             return status;
     378             :     }
     379           0 :     return CAIRO_STATUS_SUCCESS;
     380             : }
     381             : 
     382             : static cairo_status_t
     383           0 : cff_index_append (cairo_array_t *index, unsigned char *object , int length)
     384             : {
     385             :     cff_index_element_t element;
     386             : 
     387           0 :     element.length = length;
     388           0 :     element.is_copy = FALSE;
     389           0 :     element.data = object;
     390             : 
     391           0 :     return _cairo_array_append (index, &element);
     392             : }
     393             : 
     394             : static cairo_status_t
     395           0 : cff_index_append_copy (cairo_array_t *index,
     396             :                        const unsigned char *object,
     397             :                        unsigned int length)
     398             : {
     399             :     cff_index_element_t element;
     400             :     cairo_status_t status;
     401             : 
     402           0 :     element.length = length;
     403           0 :     element.is_copy = TRUE;
     404           0 :     element.data = malloc (element.length);
     405           0 :     if (unlikely (element.data == NULL))
     406           0 :         return _cairo_error (CAIRO_STATUS_NO_MEMORY);
     407             : 
     408           0 :     memcpy (element.data, object, element.length);
     409             : 
     410           0 :     status = _cairo_array_append (index, &element);
     411           0 :     if (unlikely (status)) {
     412           0 :         free (element.data);
     413           0 :         return status;
     414             :     }
     415             : 
     416           0 :     return CAIRO_STATUS_SUCCESS;
     417             : }
     418             : 
     419             : static void
     420           0 : cff_index_fini (cairo_array_t *index)
     421             : {
     422             :     cff_index_element_t *element;
     423             :     int i;
     424             : 
     425           0 :     for (i = 0; i < _cairo_array_num_elements (index); i++) {
     426           0 :         element = _cairo_array_index (index, i);
     427           0 :         if (element->is_copy)
     428           0 :             free (element->data);
     429             :     }
     430           0 :     _cairo_array_fini (index);
     431           0 : }
     432             : 
     433             : static cairo_bool_t
     434           0 : _cairo_cff_dict_equal (const void *key_a, const void *key_b)
     435             : {
     436           0 :     const cff_dict_operator_t *op_a = key_a;
     437           0 :     const cff_dict_operator_t *op_b = key_b;
     438             : 
     439           0 :     return op_a->operator == op_b->operator;
     440             : }
     441             : 
     442             : static cairo_status_t
     443           0 : cff_dict_init (cairo_hash_table_t **dict)
     444             : {
     445           0 :     *dict = _cairo_hash_table_create (_cairo_cff_dict_equal);
     446           0 :     if (unlikely (*dict == NULL))
     447           0 :         return _cairo_error (CAIRO_STATUS_NO_MEMORY);
     448             : 
     449           0 :     return CAIRO_STATUS_SUCCESS;
     450             : }
     451             : 
     452             : static void
     453           0 : _cairo_dict_init_key (cff_dict_operator_t *key, int operator)
     454             : {
     455           0 :     key->base.hash = (unsigned long) operator;
     456           0 :     key->operator = operator;
     457           0 : }
     458             : 
     459             : static cairo_status_t
     460           0 : cff_dict_create_operator (int            operator,
     461             :                           unsigned char *operand,
     462             :                           int            size,
     463             :                           cff_dict_operator_t **out)
     464             : {
     465             :     cff_dict_operator_t *op;
     466             : 
     467           0 :     op = malloc (sizeof (cff_dict_operator_t));
     468           0 :     if (unlikely (op == NULL))
     469           0 :         return _cairo_error (CAIRO_STATUS_NO_MEMORY);
     470             : 
     471           0 :     _cairo_dict_init_key (op, operator);
     472           0 :     op->operand = malloc (size);
     473           0 :     if (unlikely (op->operand == NULL)) {
     474           0 :         free (op);
     475           0 :         return _cairo_error (CAIRO_STATUS_NO_MEMORY);
     476             :     }
     477             : 
     478           0 :     memcpy (op->operand, operand, size);
     479           0 :     op->operand_length = size;
     480           0 :     op->operand_offset = -1;
     481             : 
     482           0 :     *out = op;
     483           0 :     return CAIRO_STATUS_SUCCESS;
     484             : }
     485             : 
     486             : static cairo_status_t
     487           0 : cff_dict_read (cairo_hash_table_t *dict, unsigned char *p, int dict_size)
     488             : {
     489             :     unsigned char *end;
     490             :     cairo_array_t operands;
     491             :     cff_dict_operator_t *op;
     492             :     unsigned short operator;
     493           0 :     cairo_status_t status = CAIRO_STATUS_SUCCESS;
     494             :     int size;
     495             : 
     496           0 :     end = p + dict_size;
     497           0 :     _cairo_array_init (&operands, 1);
     498           0 :     while (p < end) {
     499           0 :         size = operand_length (p);
     500           0 :         if (size != 0) {
     501           0 :             status = _cairo_array_append_multiple (&operands, p, size);
     502           0 :             if (unlikely (status))
     503           0 :                 goto fail;
     504             : 
     505           0 :             p += size;
     506             :         } else {
     507           0 :             p = decode_operator (p, &operator);
     508           0 :             status = cff_dict_create_operator (operator,
     509           0 :                                           _cairo_array_index (&operands, 0),
     510             :                                           _cairo_array_num_elements (&operands),
     511             :                                           &op);
     512           0 :             if (unlikely (status))
     513           0 :                 goto fail;
     514             : 
     515           0 :             status = _cairo_hash_table_insert (dict, &op->base);
     516           0 :             if (unlikely (status))
     517           0 :                 goto fail;
     518             : 
     519           0 :             _cairo_array_truncate (&operands, 0);
     520             :         }
     521             :     }
     522             : 
     523             : fail:
     524           0 :     _cairo_array_fini (&operands);
     525             : 
     526           0 :     return status;
     527             : }
     528             : 
     529             : static void
     530           0 : cff_dict_remove (cairo_hash_table_t *dict, unsigned short operator)
     531             : {
     532             :     cff_dict_operator_t key, *op;
     533             : 
     534           0 :     _cairo_dict_init_key (&key, operator);
     535           0 :     op = _cairo_hash_table_lookup (dict, &key.base);
     536           0 :     if (op != NULL) {
     537           0 :         free (op->operand);
     538           0 :         _cairo_hash_table_remove (dict, (cairo_hash_entry_t *) op);
     539           0 :         free (op);
     540             :     }
     541           0 : }
     542             : 
     543             : static unsigned char *
     544           0 : cff_dict_get_operands (cairo_hash_table_t *dict,
     545             :                        unsigned short      operator,
     546             :                        int                *size)
     547             : {
     548             :     cff_dict_operator_t key, *op;
     549             : 
     550           0 :     _cairo_dict_init_key (&key, operator);
     551           0 :     op = _cairo_hash_table_lookup (dict, &key.base);
     552           0 :     if (op != NULL) {
     553           0 :         *size = op->operand_length;
     554           0 :         return op->operand;
     555             :     }
     556             : 
     557           0 :     return NULL;
     558             : }
     559             : 
     560             : static cairo_status_t
     561           0 : cff_dict_set_operands (cairo_hash_table_t *dict,
     562             :                        unsigned short      operator,
     563             :                        unsigned char      *operand,
     564             :                        int                 size)
     565             : {
     566             :     cff_dict_operator_t key, *op;
     567             :     cairo_status_t status;
     568             : 
     569           0 :     _cairo_dict_init_key (&key, operator);
     570           0 :     op = _cairo_hash_table_lookup (dict, &key.base);
     571           0 :     if (op != NULL) {
     572           0 :         free (op->operand);
     573           0 :         op->operand = malloc (size);
     574           0 :         if (unlikely (op->operand == NULL))
     575           0 :             return _cairo_error (CAIRO_STATUS_NO_MEMORY);
     576             : 
     577           0 :         memcpy (op->operand, operand, size);
     578           0 :         op->operand_length = size;
     579             :     }
     580             :     else
     581             :     {
     582           0 :         status = cff_dict_create_operator (operator, operand, size, &op);
     583           0 :         if (unlikely (status))
     584           0 :             return status;
     585             : 
     586           0 :         status = _cairo_hash_table_insert (dict, &op->base);
     587           0 :         if (unlikely (status))
     588           0 :             return status;
     589             :     }
     590             : 
     591           0 :     return CAIRO_STATUS_SUCCESS;
     592             : }
     593             : 
     594             : static int
     595           0 : cff_dict_get_location (cairo_hash_table_t *dict,
     596             :                        unsigned short      operator,
     597             :                        int                *size)
     598             : {
     599             :     cff_dict_operator_t key, *op;
     600             : 
     601           0 :     _cairo_dict_init_key (&key, operator);
     602           0 :     op = _cairo_hash_table_lookup (dict, &key.base);
     603           0 :     if (op != NULL) {
     604           0 :         *size = op->operand_length;
     605           0 :         return op->operand_offset;
     606             :     }
     607             : 
     608           0 :     return -1;
     609             : }
     610             : 
     611             : typedef struct _dict_write_info {
     612             :     cairo_array_t *output;
     613             :     cairo_status_t status;
     614             : } dict_write_info_t;
     615             : 
     616             : static void
     617           0 : cairo_dict_write_operator (cff_dict_operator_t *op, dict_write_info_t *write_info)
     618             : {
     619             :     unsigned char data;
     620             : 
     621           0 :     op->operand_offset = _cairo_array_num_elements (write_info->output);
     622           0 :     write_info->status = _cairo_array_append_multiple (write_info->output, op->operand, op->operand_length);
     623           0 :     if (write_info->status)
     624           0 :         return;
     625             : 
     626           0 :     if (op->operator & 0xff00) {
     627           0 :         data = op->operator >> 8;
     628           0 :         write_info->status = _cairo_array_append (write_info->output, &data);
     629           0 :         if (write_info->status)
     630           0 :             return;
     631             :     }
     632           0 :     data = op->operator & 0xff;
     633           0 :     write_info->status = _cairo_array_append (write_info->output, &data);
     634             : }
     635             : 
     636             : static void
     637           0 : _cairo_dict_collect (void *entry, void *closure)
     638             : {
     639           0 :     dict_write_info_t   *write_info = closure;
     640           0 :     cff_dict_operator_t *op = entry;
     641             : 
     642           0 :     if (write_info->status)
     643           0 :         return;
     644             : 
     645             :     /* The ROS operator is handled separately in cff_dict_write() */
     646           0 :     if (op->operator != ROS_OP)
     647           0 :         cairo_dict_write_operator (op, write_info);
     648             : }
     649             : 
     650             : static cairo_status_t
     651           0 : cff_dict_write (cairo_hash_table_t *dict, cairo_array_t *output)
     652             : {
     653             :     dict_write_info_t write_info;
     654             :     cff_dict_operator_t key, *op;
     655             : 
     656           0 :     write_info.output = output;
     657           0 :     write_info.status = CAIRO_STATUS_SUCCESS;
     658             : 
     659             :     /* The CFF specification requires that the Top Dict of CID fonts
     660             :      * begin with the ROS operator. */
     661           0 :     _cairo_dict_init_key (&key, ROS_OP);
     662           0 :     op = _cairo_hash_table_lookup (dict, &key.base);
     663           0 :     if (op != NULL)
     664           0 :         cairo_dict_write_operator (op, &write_info);
     665             : 
     666           0 :     _cairo_hash_table_foreach (dict, _cairo_dict_collect, &write_info);
     667             : 
     668           0 :     return write_info.status;
     669             : }
     670             : 
     671             : static void
     672           0 : _cff_dict_entry_pluck (void *_entry, void *dict)
     673             : {
     674           0 :     cff_dict_operator_t *entry = _entry;
     675             : 
     676           0 :     _cairo_hash_table_remove (dict, &entry->base);
     677           0 :     free (entry->operand);
     678           0 :     free (entry);
     679           0 : }
     680             : 
     681             : static void
     682           0 : cff_dict_fini (cairo_hash_table_t *dict)
     683             : {
     684           0 :     _cairo_hash_table_foreach (dict, _cff_dict_entry_pluck, dict);
     685           0 :     _cairo_hash_table_destroy (dict);
     686           0 : }
     687             : 
     688             : static cairo_int_status_t
     689           0 : cairo_cff_font_read_header (cairo_cff_font_t *font)
     690             : {
     691           0 :     if (font->data_length < sizeof (cff_header_t))
     692           0 :         return CAIRO_INT_STATUS_UNSUPPORTED;
     693             : 
     694           0 :     font->header = (cff_header_t *) font->data;
     695           0 :     font->current_ptr = font->data + font->header->header_size;
     696             : 
     697           0 :     return CAIRO_STATUS_SUCCESS;
     698             : }
     699             : 
     700             : static cairo_int_status_t
     701           0 : cairo_cff_font_read_name (cairo_cff_font_t *font)
     702             : {
     703             :     cairo_array_t index;
     704             :     cairo_int_status_t status;
     705             : 
     706             :     /* The original font name is not used in the subset. Read the name
     707             :      * index to skip over it. */
     708           0 :     cff_index_init (&index);
     709           0 :     status = cff_index_read (&index, &font->current_ptr, font->data_end);
     710           0 :     cff_index_fini (&index);
     711             : 
     712           0 :     return status;
     713             : }
     714             : 
     715             : static cairo_int_status_t
     716           0 : cairo_cff_font_read_private_dict (cairo_cff_font_t   *font,
     717             :                                   cairo_hash_table_t *private_dict,
     718             :                                   cairo_array_t      *local_sub_index,
     719             :                                   unsigned char      *ptr,
     720             :                                   int                 size)
     721             : {
     722             :     cairo_int_status_t status;
     723             :     unsigned char buf[10];
     724             :     unsigned char *end_buf;
     725             :     int offset;
     726             :     int i;
     727             :     unsigned char *operand;
     728             :     unsigned char *p;
     729             : 
     730           0 :     status = cff_dict_read (private_dict, ptr, size);
     731           0 :     if (unlikely (status))
     732           0 :         return status;
     733             : 
     734           0 :     operand = cff_dict_get_operands (private_dict, LOCAL_SUB_OP, &i);
     735           0 :     if (operand) {
     736           0 :         decode_integer (operand, &offset);
     737           0 :         p = ptr + offset;
     738           0 :         status = cff_index_read (local_sub_index, &p, font->data_end);
     739           0 :         if (unlikely (status))
     740           0 :             return status;
     741             : 
     742             :         /* Use maximum sized encoding to reserve space for later modification. */
     743           0 :         end_buf = encode_integer_max (buf, 0);
     744           0 :         status = cff_dict_set_operands (private_dict, LOCAL_SUB_OP, buf, end_buf - buf);
     745           0 :         if (unlikely (status))
     746           0 :             return status;
     747             :     }
     748             : 
     749           0 :     return CAIRO_STATUS_SUCCESS;
     750             : }
     751             : 
     752             : static cairo_int_status_t
     753           0 : cairo_cff_font_read_fdselect (cairo_cff_font_t *font, unsigned char *p)
     754             : {
     755             :     int type, num_ranges, first, last, fd, i, j;
     756             : 
     757           0 :     font->fdselect = calloc (font->num_glyphs, sizeof (int));
     758           0 :     if (unlikely (font->fdselect == NULL))
     759           0 :         return _cairo_error (CAIRO_STATUS_NO_MEMORY);
     760             : 
     761           0 :     type = *p++;
     762           0 :     if (type == 0)
     763             :     {
     764           0 :         for (i = 0; i < font->num_glyphs; i++)
     765           0 :             font->fdselect[i] = *p++;
     766           0 :     } else if (type == 3) {
     767           0 :         num_ranges = be16_to_cpu( *((uint16_t *)p) );
     768           0 :         p += 2;
     769           0 :         for  (i = 0; i < num_ranges; i++)
     770             :         {
     771           0 :             first = be16_to_cpu( *((uint16_t *)p) );
     772           0 :             p += 2;
     773           0 :             fd = *p++;
     774           0 :             last = be16_to_cpu( *((uint16_t *)p) );
     775           0 :             for (j = first; j < last; j++)
     776           0 :                 font->fdselect[j] = fd;
     777             :         }
     778             :     } else {
     779           0 :         return CAIRO_INT_STATUS_UNSUPPORTED;
     780             :     }
     781             : 
     782           0 :     return CAIRO_STATUS_SUCCESS;
     783             : }
     784             : 
     785             : static cairo_int_status_t
     786           0 : cairo_cff_font_read_cid_fontdict (cairo_cff_font_t *font, unsigned char *ptr)
     787             : {
     788             :     cairo_array_t index;
     789             :     cff_index_element_t *element;
     790             :     unsigned int i;
     791             :     int size;
     792             :     unsigned char *operand;
     793             :     int offset;
     794             :     cairo_int_status_t status;
     795             :     unsigned char buf[100];
     796             :     unsigned char *end_buf;
     797             : 
     798           0 :     cff_index_init (&index);
     799           0 :     status = cff_index_read (&index, &ptr, font->data_end);
     800           0 :     if (unlikely (status))
     801           0 :         goto fail;
     802             : 
     803           0 :     font->num_fontdicts = _cairo_array_num_elements (&index);
     804             : 
     805           0 :     font->fd_dict = calloc (sizeof (cairo_hash_table_t *), font->num_fontdicts);
     806           0 :     if (unlikely (font->fd_dict == NULL)) {
     807           0 :         status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
     808           0 :         goto fail;
     809             :     }
     810             : 
     811           0 :     font->fd_private_dict = calloc (sizeof (cairo_hash_table_t *), font->num_fontdicts);
     812           0 :     if (unlikely (font->fd_private_dict == NULL)) {
     813           0 :         status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
     814           0 :         goto fail;
     815             :     }
     816             : 
     817           0 :     font->fd_local_sub_index = calloc (sizeof (cairo_array_t), font->num_fontdicts);
     818           0 :     if (unlikely (font->fd_local_sub_index == NULL)) {
     819           0 :         status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
     820           0 :         goto fail;
     821             :     }
     822             : 
     823           0 :     for (i = 0; i < font->num_fontdicts; i++) {
     824           0 :         status = cff_dict_init (&font->fd_dict[i]);
     825           0 :         if (unlikely (status))
     826           0 :             goto fail;
     827             : 
     828           0 :         element = _cairo_array_index (&index, i);
     829           0 :         status = cff_dict_read (font->fd_dict[i], element->data, element->length);
     830           0 :         if (unlikely (status))
     831           0 :             goto fail;
     832             : 
     833           0 :         operand = cff_dict_get_operands (font->fd_dict[i], PRIVATE_OP, &size);
     834           0 :         if (operand == NULL) {
     835           0 :             status = CAIRO_INT_STATUS_UNSUPPORTED;
     836           0 :             goto fail;
     837             :         }
     838           0 :         operand = decode_integer (operand, &size);
     839           0 :         decode_integer (operand, &offset);
     840           0 :         status = cff_dict_init (&font->fd_private_dict[i]);
     841           0 :         if (unlikely (status))
     842           0 :             goto fail;
     843             : 
     844           0 :         cff_index_init (&font->fd_local_sub_index[i]);
     845           0 :         status = cairo_cff_font_read_private_dict (font,
     846           0 :                                                    font->fd_private_dict[i],
     847           0 :                                                    &font->fd_local_sub_index[i],
     848           0 :                                                    font->data + offset,
     849             :                                                    size);
     850           0 :         if (unlikely (status))
     851           0 :             goto fail;
     852             : 
     853             :         /* Set integer operand to max value to use max size encoding to reserve
     854             :          * space for any value later */
     855           0 :         end_buf = encode_integer_max (buf, 0);
     856           0 :         end_buf = encode_integer_max (end_buf, 0);
     857           0 :         status = cff_dict_set_operands (font->fd_dict[i], PRIVATE_OP, buf, end_buf - buf);
     858           0 :         if (unlikely (status))
     859           0 :             goto fail;
     860             :     }
     861             : 
     862           0 :     return CAIRO_STATUS_SUCCESS;
     863             : 
     864             : fail:
     865           0 :     cff_index_fini (&index);
     866             : 
     867           0 :     return status;
     868             : }
     869             : 
     870             : static cairo_int_status_t
     871           0 : cairo_cff_font_read_top_dict (cairo_cff_font_t *font)
     872             : {
     873             :     cairo_array_t index;
     874             :     cff_index_element_t *element;
     875             :     unsigned char buf[20];
     876             :     unsigned char *end_buf;
     877             :     unsigned char *operand;
     878             :     cairo_int_status_t status;
     879             :     unsigned char *p;
     880             :     int size;
     881             :     int offset;
     882             : 
     883           0 :     cff_index_init (&index);
     884           0 :     status = cff_index_read (&index, &font->current_ptr, font->data_end);
     885           0 :     if (unlikely (status))
     886           0 :         goto fail;
     887             : 
     888           0 :     element = _cairo_array_index (&index, 0);
     889           0 :     status = cff_dict_read (font->top_dict, element->data, element->length);
     890           0 :     if (unlikely (status))
     891           0 :         goto fail;
     892             : 
     893           0 :     if (cff_dict_get_operands (font->top_dict, ROS_OP, &size) != NULL)
     894           0 :         font->is_cid = TRUE;
     895             :     else
     896           0 :         font->is_cid = FALSE;
     897             : 
     898           0 :     operand = cff_dict_get_operands (font->top_dict, CHARSTRINGS_OP, &size);
     899           0 :     decode_integer (operand, &offset);
     900           0 :     p = font->data + offset;
     901           0 :     status = cff_index_read (&font->charstrings_index, &p, font->data_end);
     902           0 :     if (unlikely (status))
     903           0 :         goto fail;
     904           0 :     font->num_glyphs = _cairo_array_num_elements (&font->charstrings_index);
     905             : 
     906           0 :     if (font->is_cid) {
     907           0 :         operand = cff_dict_get_operands (font->top_dict, FDSELECT_OP, &size);
     908           0 :         decode_integer (operand, &offset);
     909           0 :         status = cairo_cff_font_read_fdselect (font, font->data + offset);
     910           0 :         if (unlikely (status))
     911           0 :             goto fail;
     912             : 
     913           0 :         operand = cff_dict_get_operands (font->top_dict, FDARRAY_OP, &size);
     914           0 :         decode_integer (operand, &offset);
     915           0 :         status = cairo_cff_font_read_cid_fontdict (font, font->data + offset);
     916           0 :         if (unlikely (status))
     917           0 :             goto fail;
     918             :     } else {
     919           0 :         operand = cff_dict_get_operands (font->top_dict, PRIVATE_OP, &size);
     920           0 :         operand = decode_integer (operand, &size);
     921           0 :         decode_integer (operand, &offset);
     922           0 :         status = cairo_cff_font_read_private_dict (font,
     923             :                                                    font->private_dict,
     924             :                                                    &font->local_sub_index,
     925           0 :                                                    font->data + offset,
     926             :                                                    size);
     927           0 :         if (unlikely (status))
     928           0 :             goto fail;
     929             :     }
     930             : 
     931             :     /* Use maximum sized encoding to reserve space for later modification. */
     932           0 :     end_buf = encode_integer_max (buf, 0);
     933           0 :     status = cff_dict_set_operands (font->top_dict,
     934           0 :                                     CHARSTRINGS_OP, buf, end_buf - buf);
     935           0 :     if (unlikely (status))
     936           0 :         goto fail;
     937             : 
     938           0 :     status = cff_dict_set_operands (font->top_dict,
     939           0 :                                     FDSELECT_OP, buf, end_buf - buf);
     940           0 :     if (unlikely (status))
     941           0 :         goto fail;
     942             : 
     943           0 :     status = cff_dict_set_operands (font->top_dict,
     944           0 :                                     FDARRAY_OP, buf, end_buf - buf);
     945           0 :     if (unlikely (status))
     946           0 :         goto fail;
     947             : 
     948           0 :     status = cff_dict_set_operands (font->top_dict,
     949           0 :                                     CHARSET_OP, buf, end_buf - buf);
     950           0 :     if (unlikely (status))
     951           0 :         goto fail;
     952             : 
     953           0 :     cff_dict_remove (font->top_dict, ENCODING_OP);
     954           0 :     cff_dict_remove (font->top_dict, PRIVATE_OP);
     955             : 
     956             :     /* Remove the unique identifier operators as the subsetted font is
     957             :      * not the same is the original font. */
     958           0 :     cff_dict_remove (font->top_dict, UNIQUEID_OP);
     959           0 :     cff_dict_remove (font->top_dict, XUID_OP);
     960             : 
     961             : fail:
     962           0 :     cff_index_fini (&index);
     963             : 
     964           0 :     return status;
     965             : }
     966             : 
     967             : static cairo_int_status_t
     968           0 : cairo_cff_font_read_strings (cairo_cff_font_t *font)
     969             : {
     970           0 :     return cff_index_read (&font->strings_index, &font->current_ptr, font->data_end);
     971             : }
     972             : 
     973             : static cairo_int_status_t
     974           0 : cairo_cff_font_read_global_subroutines (cairo_cff_font_t *font)
     975             : {
     976           0 :     return cff_index_read (&font->global_sub_index, &font->current_ptr, font->data_end);
     977             : }
     978             : 
     979             : typedef cairo_int_status_t
     980             : (*font_read_t) (cairo_cff_font_t *font);
     981             : 
     982             : static const font_read_t font_read_funcs[] = {
     983             :     cairo_cff_font_read_header,
     984             :     cairo_cff_font_read_name,
     985             :     cairo_cff_font_read_top_dict,
     986             :     cairo_cff_font_read_strings,
     987             :     cairo_cff_font_read_global_subroutines,
     988             : };
     989             : 
     990             : static cairo_int_status_t
     991           0 : cairo_cff_font_read_font (cairo_cff_font_t *font)
     992             : {
     993             :     cairo_int_status_t status;
     994             :     unsigned int i;
     995             : 
     996           0 :     for (i = 0; i < ARRAY_LENGTH (font_read_funcs); i++) {
     997           0 :         status = font_read_funcs[i] (font);
     998           0 :         if (unlikely (status))
     999           0 :             return status;
    1000             :     }
    1001             : 
    1002           0 :     return CAIRO_STATUS_SUCCESS;
    1003             : }
    1004             : 
    1005             : static cairo_status_t
    1006           0 : cairo_cff_font_set_ros_strings (cairo_cff_font_t *font)
    1007             : {
    1008             :     cairo_status_t status;
    1009             :     unsigned char buf[30];
    1010             :     unsigned char *p;
    1011             :     int sid1, sid2;
    1012           0 :     const char *registry = "Adobe";
    1013           0 :     const char *ordering = "Identity";
    1014             : 
    1015           0 :     sid1 = NUM_STD_STRINGS + _cairo_array_num_elements (&font->strings_subset_index);
    1016           0 :     status = cff_index_append_copy (&font->strings_subset_index,
    1017             :                                     (unsigned char *)registry,
    1018           0 :                                     strlen(registry));
    1019           0 :     if (unlikely (status))
    1020           0 :         return status;
    1021             : 
    1022           0 :     sid2 = NUM_STD_STRINGS + _cairo_array_num_elements (&font->strings_subset_index);
    1023           0 :     status = cff_index_append_copy (&font->strings_subset_index,
    1024             :                                     (unsigned char *)ordering,
    1025           0 :                                     strlen(ordering));
    1026           0 :     if (unlikely (status))
    1027           0 :         return status;
    1028             : 
    1029           0 :     p = encode_integer (buf, sid1);
    1030           0 :     p = encode_integer (p, sid2);
    1031           0 :     p = encode_integer (p, 0);
    1032           0 :     status = cff_dict_set_operands (font->top_dict, ROS_OP, buf, p - buf);
    1033           0 :     if (unlikely (status))
    1034           0 :         return status;
    1035             : 
    1036           0 :     p = encode_integer (buf, font->scaled_font_subset->num_glyphs);
    1037           0 :     status = cff_dict_set_operands (font->top_dict, CIDCOUNT_OP, buf, p - buf);
    1038           0 :     if (unlikely (status))
    1039           0 :         return status;
    1040             : 
    1041           0 :     return CAIRO_STATUS_SUCCESS;
    1042             : }
    1043             : 
    1044             : static cairo_status_t
    1045           0 : cairo_cff_font_subset_dict_string(cairo_cff_font_t   *font,
    1046             :                                   cairo_hash_table_t *dict,
    1047             :                                   int                 operator)
    1048             : {
    1049             :     int size;
    1050             :     unsigned char *p;
    1051             :     int sid;
    1052             :     unsigned char buf[100];
    1053             :     cff_index_element_t *element;
    1054             :     cairo_status_t status;
    1055             : 
    1056           0 :     p = cff_dict_get_operands (dict, operator, &size);
    1057           0 :     if (!p)
    1058           0 :         return CAIRO_STATUS_SUCCESS;
    1059             : 
    1060           0 :     decode_integer (p, &sid);
    1061           0 :     if (sid < NUM_STD_STRINGS)
    1062           0 :         return CAIRO_STATUS_SUCCESS;
    1063             : 
    1064           0 :     element = _cairo_array_index (&font->strings_index, sid - NUM_STD_STRINGS);
    1065           0 :     sid = NUM_STD_STRINGS + _cairo_array_num_elements (&font->strings_subset_index);
    1066           0 :     status = cff_index_append (&font->strings_subset_index, element->data, element->length);
    1067           0 :     if (unlikely (status))
    1068           0 :         return status;
    1069             : 
    1070           0 :     p = encode_integer (buf, sid);
    1071           0 :     status = cff_dict_set_operands (dict, operator, buf, p - buf);
    1072           0 :     if (unlikely (status))
    1073           0 :         return status;
    1074             : 
    1075           0 :     return CAIRO_STATUS_SUCCESS;
    1076             : }
    1077             : 
    1078             : static const int dict_strings[] = {
    1079             :     VERSION_OP,
    1080             :     NOTICE_OP,
    1081             :     COPYRIGHT_OP,
    1082             :     FULLNAME_OP,
    1083             :     FAMILYNAME_OP,
    1084             :     WEIGHT_OP,
    1085             :     POSTSCRIPT_OP,
    1086             :     BASEFONTNAME_OP,
    1087             :     FONTNAME_OP,
    1088             : };
    1089             : 
    1090             : static cairo_status_t
    1091           0 : cairo_cff_font_subset_dict_strings (cairo_cff_font_t   *font,
    1092             :                                     cairo_hash_table_t *dict)
    1093             : {
    1094             :     cairo_status_t status;
    1095             :     unsigned int i;
    1096             : 
    1097           0 :     for (i = 0; i < ARRAY_LENGTH (dict_strings); i++) {
    1098           0 :         status = cairo_cff_font_subset_dict_string (font, dict, dict_strings[i]);
    1099           0 :         if (unlikely (status))
    1100           0 :             return status;
    1101             :     }
    1102             : 
    1103           0 :     return CAIRO_STATUS_SUCCESS;
    1104             : }
    1105             : 
    1106             : static cairo_status_t
    1107           0 : cairo_cff_font_subset_charstrings (cairo_cff_font_t  *font)
    1108             : {
    1109             :     cff_index_element_t *element;
    1110             :     unsigned int i;
    1111             :     cairo_status_t status;
    1112             : 
    1113           0 :     for (i = 0; i < font->scaled_font_subset->num_glyphs; i++) {
    1114           0 :         element = _cairo_array_index (&font->charstrings_index,
    1115           0 :                                       font->scaled_font_subset->glyphs[i]);
    1116           0 :         status = cff_index_append (&font->charstrings_subset_index,
    1117             :                                    element->data,
    1118             :                                    element->length);
    1119           0 :         if (unlikely (status))
    1120           0 :             return status;
    1121             :     }
    1122             : 
    1123           0 :     return CAIRO_STATUS_SUCCESS;
    1124             : }
    1125             : 
    1126             : static cairo_status_t
    1127           0 : cairo_cff_font_subset_fontdict (cairo_cff_font_t  *font)
    1128             : {
    1129             :     unsigned int i;
    1130             :     int fd;
    1131             :     int *reverse_map;
    1132             : 
    1133           0 :     font->fdselect_subset = calloc (font->scaled_font_subset->num_glyphs,
    1134             :                                      sizeof (int));
    1135           0 :     if (unlikely (font->fdselect_subset == NULL))
    1136           0 :         return _cairo_error (CAIRO_STATUS_NO_MEMORY);
    1137             : 
    1138           0 :     font->fd_subset_map = calloc (font->num_fontdicts, sizeof (int));
    1139           0 :     if (unlikely (font->fd_subset_map == NULL))
    1140           0 :         return _cairo_error (CAIRO_STATUS_NO_MEMORY);
    1141             : 
    1142           0 :     font->private_dict_offset = calloc (font->num_fontdicts, sizeof (int));
    1143           0 :     if (unlikely (font->private_dict_offset == NULL))
    1144           0 :         return _cairo_error (CAIRO_STATUS_NO_MEMORY);
    1145             : 
    1146           0 :     reverse_map = calloc (font->num_fontdicts, sizeof (int));
    1147           0 :     if (unlikely (reverse_map == NULL))
    1148           0 :         return _cairo_error (CAIRO_STATUS_NO_MEMORY);
    1149             : 
    1150           0 :     for (i = 0; i < font->num_fontdicts; i++)
    1151           0 :         reverse_map[i] = -1;
    1152             : 
    1153           0 :     font->num_subset_fontdicts = 0;
    1154           0 :     for (i = 0; i < font->scaled_font_subset->num_glyphs; i++) {
    1155           0 :         fd = font->fdselect[font->scaled_font_subset->glyphs[i]];
    1156           0 :         if (reverse_map[fd] < 0) {
    1157           0 :             font->fd_subset_map[font->num_subset_fontdicts] = fd;
    1158           0 :             reverse_map[fd] = font->num_subset_fontdicts++;
    1159             :         }
    1160           0 :         font->fdselect_subset[i] = reverse_map[fd];
    1161             :     }
    1162             : 
    1163           0 :     free (reverse_map);
    1164             : 
    1165           0 :     return CAIRO_STATUS_SUCCESS;
    1166             : }
    1167             : 
    1168             : static cairo_status_t
    1169           0 : cairo_cff_font_create_cid_fontdict (cairo_cff_font_t *font)
    1170             : {
    1171             :     unsigned char buf[100];
    1172             :     unsigned char *end_buf;
    1173             :     cairo_status_t status;
    1174             : 
    1175           0 :     font->num_fontdicts = 1;
    1176           0 :     font->fd_dict = malloc (sizeof (cairo_hash_table_t *));
    1177           0 :     if (unlikely (font->fd_dict == NULL))
    1178           0 :         return _cairo_error (CAIRO_STATUS_NO_MEMORY);
    1179             : 
    1180           0 :     if (cff_dict_init (&font->fd_dict[0])) {
    1181           0 :         free (font->fd_dict);
    1182           0 :         font->fd_dict = NULL;
    1183           0 :         font->num_fontdicts = 0;
    1184           0 :         return _cairo_error (CAIRO_STATUS_NO_MEMORY);
    1185             :     }
    1186             : 
    1187           0 :     font->fd_subset_map = malloc (sizeof (int));
    1188           0 :     if (unlikely (font->fd_subset_map == NULL))
    1189           0 :         return _cairo_error (CAIRO_STATUS_NO_MEMORY);
    1190             : 
    1191           0 :     font->private_dict_offset = malloc (sizeof (int));
    1192           0 :     if (unlikely (font->private_dict_offset == NULL))
    1193           0 :         return _cairo_error (CAIRO_STATUS_NO_MEMORY);
    1194             : 
    1195           0 :     font->fd_subset_map[0] = 0;
    1196           0 :     font->num_subset_fontdicts = 1;
    1197             : 
    1198             :     /* Set integer operand to max value to use max size encoding to reserve
    1199             :      * space for any value later */
    1200           0 :     end_buf = encode_integer_max (buf, 0);
    1201           0 :     end_buf = encode_integer_max (end_buf, 0);
    1202           0 :     status = cff_dict_set_operands (font->fd_dict[0], PRIVATE_OP, buf, end_buf - buf);
    1203           0 :     if (unlikely (status))
    1204           0 :         return status;
    1205             : 
    1206           0 :     return CAIRO_STATUS_SUCCESS;
    1207             : }
    1208             : 
    1209             : static cairo_status_t
    1210           0 : cairo_cff_font_subset_strings (cairo_cff_font_t *font)
    1211             : {
    1212             :     cairo_status_t status;
    1213             :     unsigned int i;
    1214             : 
    1215           0 :     status = cairo_cff_font_subset_dict_strings (font, font->top_dict);
    1216           0 :     if (unlikely (status))
    1217           0 :         return status;
    1218             : 
    1219           0 :     if (font->is_cid) {
    1220           0 :         for (i = 0; i < font->num_subset_fontdicts; i++) {
    1221           0 :             status = cairo_cff_font_subset_dict_strings (font, font->fd_dict[font->fd_subset_map[i]]);
    1222           0 :             if (unlikely (status))
    1223           0 :                 return status;
    1224             : 
    1225           0 :             status = cairo_cff_font_subset_dict_strings (font, font->fd_private_dict[font->fd_subset_map[i]]);
    1226           0 :             if (unlikely (status))
    1227           0 :                 return status;
    1228             :         }
    1229             :     } else {
    1230           0 :         status = cairo_cff_font_subset_dict_strings (font, font->private_dict);
    1231             :     }
    1232             : 
    1233           0 :     return status;
    1234             : }
    1235             : 
    1236             : static cairo_status_t
    1237           0 : cairo_cff_font_subset_font (cairo_cff_font_t  *font)
    1238             : {
    1239             :     cairo_status_t status;
    1240             : 
    1241           0 :     status = cairo_cff_font_set_ros_strings (font);
    1242           0 :     if (unlikely (status))
    1243           0 :         return status;
    1244             : 
    1245           0 :     status = cairo_cff_font_subset_charstrings (font);
    1246           0 :     if (unlikely (status))
    1247           0 :         return status;
    1248             : 
    1249           0 :     if (font->is_cid)
    1250           0 :         status = cairo_cff_font_subset_fontdict (font);
    1251             :     else
    1252           0 :         status = cairo_cff_font_create_cid_fontdict (font);
    1253           0 :     if (unlikely (status))
    1254           0 :         return status;
    1255             : 
    1256           0 :     status = cairo_cff_font_subset_strings (font);
    1257           0 :     if (unlikely (status))
    1258           0 :         return status;
    1259             : 
    1260           0 :     return status;
    1261             : }
    1262             : 
    1263             : /* Set the operand of the specified operator in the (already written)
    1264             :  * top dict to point to the current position in the output
    1265             :  * array. Operands updated with this function must have previously
    1266             :  * been encoded with the 5-byte (max) integer encoding. */
    1267             : static void
    1268           0 : cairo_cff_font_set_topdict_operator_to_cur_pos (cairo_cff_font_t  *font,
    1269             :                                                 int                operator)
    1270             : {
    1271             :     int cur_pos;
    1272             :     int offset;
    1273             :     int size;
    1274             :     unsigned char buf[10];
    1275             :     unsigned char *buf_end;
    1276             :     unsigned char *op_ptr;
    1277             : 
    1278           0 :     cur_pos = _cairo_array_num_elements (&font->output);
    1279           0 :     buf_end = encode_integer_max (buf, cur_pos);
    1280           0 :     offset = cff_dict_get_location (font->top_dict, operator, &size);
    1281           0 :     assert (offset > 0);
    1282           0 :     op_ptr = _cairo_array_index (&font->output, offset);
    1283           0 :     memcpy (op_ptr, buf, buf_end - buf);
    1284           0 : }
    1285             : 
    1286             : static cairo_status_t
    1287           0 : cairo_cff_font_write_header (cairo_cff_font_t *font)
    1288             : {
    1289           0 :     return _cairo_array_append_multiple (&font->output,
    1290           0 :                                          font->header,
    1291           0 :                                          font->header->header_size);
    1292             : }
    1293             : 
    1294             : static cairo_status_t
    1295           0 : cairo_cff_font_write_name (cairo_cff_font_t *font)
    1296             : {
    1297           0 :     cairo_status_t status = CAIRO_STATUS_SUCCESS;
    1298             :     cairo_array_t index;
    1299             : 
    1300           0 :     cff_index_init (&index);
    1301             : 
    1302           0 :     status = cff_index_append_copy (&index,
    1303           0 :                                     (unsigned char *) font->subset_font_name,
    1304           0 :                                     strlen(font->subset_font_name));
    1305           0 :     if (unlikely (status))
    1306           0 :         goto FAIL;
    1307             : 
    1308           0 :     status = cff_index_write (&index, &font->output);
    1309           0 :     if (unlikely (status))
    1310           0 :         goto FAIL;
    1311             : 
    1312             : FAIL:
    1313           0 :     cff_index_fini (&index);
    1314             : 
    1315           0 :     return status;
    1316             : }
    1317             : 
    1318             : static cairo_status_t
    1319           0 : cairo_cff_font_write_top_dict (cairo_cff_font_t *font)
    1320             : {
    1321             :     uint16_t count;
    1322             :     unsigned char buf[10];
    1323             :     unsigned char *p;
    1324             :     int offset_index;
    1325             :     int dict_start, dict_size;
    1326           0 :     int offset_size = 4;
    1327             :     cairo_status_t status;
    1328             : 
    1329             :     /* Write an index containing the top dict */
    1330             : 
    1331           0 :     count = cpu_to_be16 (1);
    1332           0 :     status = _cairo_array_append_multiple (&font->output, &count, 2);
    1333           0 :     if (unlikely (status))
    1334           0 :         return status;
    1335           0 :     buf[0] = offset_size;
    1336           0 :     status = _cairo_array_append (&font->output, buf);
    1337           0 :     if (unlikely (status))
    1338           0 :         return status;
    1339           0 :     encode_index_offset (buf, offset_size, 1);
    1340           0 :     status = _cairo_array_append_multiple (&font->output, buf, offset_size);
    1341           0 :     if (unlikely (status))
    1342           0 :         return status;
    1343             : 
    1344             :     /* Reserve space for last element of offset array and update after
    1345             :      * dict is written */
    1346           0 :     offset_index = _cairo_array_num_elements (&font->output);
    1347           0 :     status = _cairo_array_append_multiple (&font->output, buf, offset_size);
    1348           0 :     if (unlikely (status))
    1349           0 :         return status;
    1350             : 
    1351           0 :     dict_start = _cairo_array_num_elements (&font->output);
    1352           0 :     status = cff_dict_write (font->top_dict, &font->output);
    1353           0 :     if (unlikely (status))
    1354           0 :         return status;
    1355           0 :     dict_size = _cairo_array_num_elements (&font->output) - dict_start;
    1356             : 
    1357           0 :     encode_index_offset (buf, offset_size, dict_size + 1);
    1358           0 :     p = _cairo_array_index (&font->output, offset_index);
    1359           0 :     memcpy (p, buf, offset_size);
    1360             : 
    1361           0 :     return CAIRO_STATUS_SUCCESS;
    1362             : }
    1363             : 
    1364             : static cairo_status_t
    1365           0 : cairo_cff_font_write_strings (cairo_cff_font_t  *font)
    1366             : {
    1367           0 :     return cff_index_write (&font->strings_subset_index, &font->output);
    1368             : }
    1369             : 
    1370             : static cairo_status_t
    1371           0 : cairo_cff_font_write_global_subrs (cairo_cff_font_t  *font)
    1372             : {
    1373           0 :     return cff_index_write (&font->global_sub_index, &font->output);
    1374             : }
    1375             : 
    1376             : static cairo_status_t
    1377           0 : cairo_cff_font_write_fdselect (cairo_cff_font_t  *font)
    1378             : {
    1379             :     unsigned char data;
    1380             :     unsigned int i;
    1381             :     cairo_int_status_t status;
    1382             : 
    1383           0 :     cairo_cff_font_set_topdict_operator_to_cur_pos (font, FDSELECT_OP);
    1384             : 
    1385           0 :     if (font->is_cid) {
    1386           0 :         data = 0;
    1387           0 :         status = _cairo_array_append (&font->output, &data);
    1388           0 :         if (unlikely (status))
    1389           0 :             return status;
    1390             : 
    1391           0 :         for (i = 0; i < font->scaled_font_subset->num_glyphs; i++) {
    1392           0 :             data = font->fdselect_subset[i];
    1393           0 :             status = _cairo_array_append (&font->output, &data);
    1394           0 :             if (unlikely (status))
    1395           0 :                 return status;
    1396             :         }
    1397             :     } else {
    1398             :         unsigned char byte;
    1399             :         uint16_t word;
    1400             : 
    1401           0 :         status = _cairo_array_grow_by (&font->output, 9);
    1402           0 :         if (unlikely (status))
    1403           0 :             return status;
    1404             : 
    1405           0 :         byte = 3;
    1406           0 :         status = _cairo_array_append (&font->output, &byte);
    1407           0 :         assert (status == CAIRO_STATUS_SUCCESS);
    1408             : 
    1409           0 :         word = cpu_to_be16 (1);
    1410           0 :         status = _cairo_array_append_multiple (&font->output, &word, 2);
    1411           0 :         assert (status == CAIRO_STATUS_SUCCESS);
    1412             : 
    1413           0 :         word = cpu_to_be16 (0);
    1414           0 :         status = _cairo_array_append_multiple (&font->output, &word, 2);
    1415           0 :         assert (status == CAIRO_STATUS_SUCCESS);
    1416             : 
    1417           0 :         byte = 0;
    1418           0 :         status = _cairo_array_append (&font->output, &byte);
    1419           0 :         assert (status == CAIRO_STATUS_SUCCESS);
    1420             : 
    1421           0 :         word = cpu_to_be16 (font->scaled_font_subset->num_glyphs);
    1422           0 :         status = _cairo_array_append_multiple (&font->output, &word, 2);
    1423           0 :         assert (status == CAIRO_STATUS_SUCCESS);
    1424             :     }
    1425             : 
    1426           0 :     return CAIRO_STATUS_SUCCESS;
    1427             : }
    1428             : 
    1429             : static cairo_status_t
    1430           0 : cairo_cff_font_write_charset (cairo_cff_font_t  *font)
    1431             : {
    1432             :     unsigned char byte;
    1433             :     uint16_t word;
    1434             :     cairo_status_t status;
    1435             : 
    1436           0 :     cairo_cff_font_set_topdict_operator_to_cur_pos (font, CHARSET_OP);
    1437           0 :     status = _cairo_array_grow_by (&font->output, 5);
    1438           0 :     if (unlikely (status))
    1439           0 :         return status;
    1440             : 
    1441           0 :     byte = 2;
    1442           0 :     status = _cairo_array_append (&font->output, &byte);
    1443           0 :     assert (status == CAIRO_STATUS_SUCCESS);
    1444             : 
    1445           0 :     word = cpu_to_be16 (1);
    1446           0 :     status = _cairo_array_append_multiple (&font->output, &word, 2);
    1447           0 :     assert (status == CAIRO_STATUS_SUCCESS);
    1448             : 
    1449           0 :     word = cpu_to_be16 (font->scaled_font_subset->num_glyphs - 2);
    1450           0 :     status = _cairo_array_append_multiple (&font->output, &word, 2);
    1451           0 :     assert (status == CAIRO_STATUS_SUCCESS);
    1452             : 
    1453           0 :     return CAIRO_STATUS_SUCCESS;
    1454             : }
    1455             : 
    1456             : static cairo_status_t
    1457           0 : cairo_cff_font_write_charstrings (cairo_cff_font_t  *font)
    1458             : {
    1459           0 :     cairo_cff_font_set_topdict_operator_to_cur_pos (font, CHARSTRINGS_OP);
    1460             : 
    1461           0 :     return cff_index_write (&font->charstrings_subset_index, &font->output);
    1462             : }
    1463             : 
    1464             : static cairo_status_t
    1465           0 : cairo_cff_font_write_cid_fontdict (cairo_cff_font_t *font)
    1466             : {
    1467             :     unsigned int i;
    1468             :     cairo_int_status_t status;
    1469             :     unsigned int offset_array;
    1470             :     uint32_t *offset_array_ptr;
    1471             :     int offset_base;
    1472             :     uint16_t count;
    1473           0 :     uint8_t offset_size = 4;
    1474             : 
    1475           0 :     cairo_cff_font_set_topdict_operator_to_cur_pos (font, FDARRAY_OP);
    1476           0 :     count = cpu_to_be16 (font->num_subset_fontdicts);
    1477           0 :     status = _cairo_array_append_multiple (&font->output, &count, sizeof (uint16_t));
    1478           0 :     if (unlikely (status))
    1479           0 :         return status;
    1480           0 :     status = _cairo_array_append (&font->output, &offset_size);
    1481           0 :     if (unlikely (status))
    1482           0 :         return status;
    1483             : 
    1484           0 :     offset_array = _cairo_array_num_elements (&font->output);
    1485           0 :     status = _cairo_array_allocate (&font->output,
    1486           0 :                                     (font->num_subset_fontdicts + 1)*offset_size,
    1487             :                                     (void **) &offset_array_ptr);
    1488           0 :     if (unlikely (status))
    1489           0 :         return status;
    1490           0 :     offset_base = _cairo_array_num_elements (&font->output) - 1;
    1491           0 :     *offset_array_ptr = cpu_to_be32(1);
    1492           0 :     offset_array += sizeof(uint32_t);
    1493           0 :     for (i = 0; i < font->num_subset_fontdicts; i++) {
    1494           0 :         status = cff_dict_write (font->fd_dict[font->fd_subset_map[i]],
    1495             :                                  &font->output);
    1496           0 :         if (unlikely (status))
    1497           0 :             return status;
    1498             : 
    1499           0 :         offset_array_ptr = (uint32_t *) _cairo_array_index (&font->output, offset_array);
    1500           0 :         *offset_array_ptr = cpu_to_be32(_cairo_array_num_elements (&font->output) - offset_base);
    1501           0 :         offset_array += sizeof(uint32_t);
    1502             :     }
    1503             : 
    1504           0 :     return CAIRO_STATUS_SUCCESS;
    1505             : }
    1506             : 
    1507             : static cairo_status_t
    1508           0 : cairo_cff_font_write_private_dict (cairo_cff_font_t   *font,
    1509             :                                    int                 dict_num,
    1510             :                                    cairo_hash_table_t *parent_dict,
    1511             :                                    cairo_hash_table_t *private_dict)
    1512             : {
    1513             :     int offset;
    1514             :     int size;
    1515             :     unsigned char buf[10];
    1516             :     unsigned char *buf_end;
    1517             :     unsigned char *p;
    1518             :     cairo_status_t status;
    1519             : 
    1520             :     /* Write private dict and update offset and size in top dict */
    1521           0 :     font->private_dict_offset[dict_num] = _cairo_array_num_elements (&font->output);
    1522           0 :     status = cff_dict_write (private_dict, &font->output);
    1523           0 :     if (unlikely (status))
    1524           0 :         return status;
    1525             : 
    1526           0 :     size = _cairo_array_num_elements (&font->output) - font->private_dict_offset[dict_num];
    1527             :     /* private entry has two operands - size and offset */
    1528           0 :     buf_end = encode_integer_max (buf, size);
    1529           0 :     buf_end = encode_integer_max (buf_end, font->private_dict_offset[dict_num]);
    1530           0 :     offset = cff_dict_get_location (parent_dict, PRIVATE_OP, &size);
    1531           0 :     assert (offset > 0);
    1532           0 :     p = _cairo_array_index (&font->output, offset);
    1533           0 :     memcpy (p, buf, buf_end - buf);
    1534             : 
    1535           0 :     return CAIRO_STATUS_SUCCESS;
    1536             : }
    1537             : 
    1538             : static cairo_status_t
    1539           0 : cairo_cff_font_write_local_sub (cairo_cff_font_t   *font,
    1540             :                                 int                 dict_num,
    1541             :                                 cairo_hash_table_t *private_dict,
    1542             :                                 cairo_array_t      *local_sub_index)
    1543             : {
    1544             :     int offset;
    1545             :     int size;
    1546             :     unsigned char buf[10];
    1547             :     unsigned char *buf_end;
    1548             :     unsigned char *p;
    1549             :     cairo_status_t status;
    1550             : 
    1551           0 :     if (_cairo_array_num_elements (local_sub_index) > 0) {
    1552             :         /* Write local subroutines and update offset in private
    1553             :          * dict. Local subroutines offset is relative to start of
    1554             :          * private dict */
    1555           0 :         offset = _cairo_array_num_elements (&font->output) - font->private_dict_offset[dict_num];
    1556           0 :         buf_end = encode_integer_max (buf, offset);
    1557           0 :         offset = cff_dict_get_location (private_dict, LOCAL_SUB_OP, &size);
    1558           0 :         assert (offset > 0);
    1559           0 :         p = _cairo_array_index (&font->output, offset);
    1560           0 :         memcpy (p, buf, buf_end - buf);
    1561           0 :         status = cff_index_write (local_sub_index, &font->output);
    1562           0 :         if (unlikely (status))
    1563           0 :             return status;
    1564             :     }
    1565             : 
    1566           0 :     return CAIRO_STATUS_SUCCESS;
    1567             : }
    1568             : 
    1569             : 
    1570             : static cairo_status_t
    1571           0 : cairo_cff_font_write_cid_private_dict_and_local_sub (cairo_cff_font_t  *font)
    1572             : {
    1573             :     unsigned int i;
    1574             :     cairo_int_status_t status;
    1575             : 
    1576           0 :     if (font->is_cid) {
    1577           0 :         for (i = 0; i < font->num_subset_fontdicts; i++) {
    1578           0 :             status = cairo_cff_font_write_private_dict (
    1579             :                             font,
    1580             :                             i,
    1581           0 :                             font->fd_dict[font->fd_subset_map[i]],
    1582           0 :                             font->fd_private_dict[font->fd_subset_map[i]]);
    1583           0 :             if (unlikely (status))
    1584           0 :                 return status;
    1585             :         }
    1586             : 
    1587           0 :         for (i = 0; i < font->num_subset_fontdicts; i++) {
    1588           0 :             status = cairo_cff_font_write_local_sub (
    1589             :                             font,
    1590             :                             i,
    1591           0 :                             font->fd_private_dict[font->fd_subset_map[i]],
    1592           0 :                            &font->fd_local_sub_index[font->fd_subset_map[i]]);
    1593           0 :             if (unlikely (status))
    1594           0 :                 return status;
    1595             :         }
    1596             :     } else {
    1597           0 :         status = cairo_cff_font_write_private_dict (font,
    1598             :                                                     0,
    1599           0 :                                                     font->fd_dict[0],
    1600             :                                                     font->private_dict);
    1601           0 :         if (unlikely (status))
    1602           0 :             return status;
    1603             : 
    1604           0 :         status = cairo_cff_font_write_local_sub (font,
    1605             :                                                  0,
    1606             :                                                  font->private_dict,
    1607             :                                                  &font->local_sub_index);
    1608           0 :         if (unlikely (status))
    1609           0 :             return status;
    1610             :     }
    1611             : 
    1612           0 :     return CAIRO_STATUS_SUCCESS;
    1613             : }
    1614             : 
    1615             : typedef cairo_status_t
    1616             : (*font_write_t) (cairo_cff_font_t *font);
    1617             : 
    1618             : static const font_write_t font_write_funcs[] = {
    1619             :     cairo_cff_font_write_header,
    1620             :     cairo_cff_font_write_name,
    1621             :     cairo_cff_font_write_top_dict,
    1622             :     cairo_cff_font_write_strings,
    1623             :     cairo_cff_font_write_global_subrs,
    1624             :     cairo_cff_font_write_charset,
    1625             :     cairo_cff_font_write_fdselect,
    1626             :     cairo_cff_font_write_charstrings,
    1627             :     cairo_cff_font_write_cid_fontdict,
    1628             :     cairo_cff_font_write_cid_private_dict_and_local_sub,
    1629             : };
    1630             : 
    1631             : static cairo_status_t
    1632           0 : cairo_cff_font_write_subset (cairo_cff_font_t *font)
    1633             : {
    1634             :     cairo_int_status_t status;
    1635             :     unsigned int i;
    1636             : 
    1637           0 :     for (i = 0; i < ARRAY_LENGTH (font_write_funcs); i++) {
    1638           0 :         status = font_write_funcs[i] (font);
    1639           0 :         if (unlikely (status))
    1640           0 :             return status;
    1641             :     }
    1642             : 
    1643           0 :     return CAIRO_STATUS_SUCCESS;
    1644             : }
    1645             : 
    1646             : static cairo_int_status_t
    1647           0 : cairo_cff_font_generate (cairo_cff_font_t  *font,
    1648             :                          const char       **data,
    1649             :                          unsigned long     *length)
    1650             : {
    1651             :     cairo_int_status_t status;
    1652             : 
    1653           0 :     status = cairo_cff_font_read_font (font);
    1654           0 :     if (unlikely (status))
    1655           0 :         return status;
    1656             : 
    1657           0 :     status = cairo_cff_font_subset_font (font);
    1658           0 :     if (unlikely (status))
    1659           0 :         return status;
    1660             : 
    1661           0 :     status = cairo_cff_font_write_subset (font);
    1662           0 :     if (unlikely (status))
    1663           0 :         return status;
    1664             : 
    1665           0 :     *data = _cairo_array_index (&font->output, 0);
    1666           0 :     *length = _cairo_array_num_elements (&font->output);
    1667             : 
    1668           0 :     return CAIRO_STATUS_SUCCESS;
    1669             : }
    1670             : 
    1671             : static cairo_int_status_t
    1672           0 : cairo_cff_font_create_set_widths (cairo_cff_font_t *font)
    1673             : {
    1674             :     unsigned long size;
    1675             :     unsigned long long_entry_size;
    1676             :     unsigned long short_entry_size;
    1677             :     unsigned int i;
    1678             :     tt_hhea_t hhea;
    1679             :     int num_hmetrics;
    1680             :     unsigned char buf[10];
    1681             :     int glyph_index;
    1682             :     cairo_int_status_t status;
    1683             : 
    1684           0 :     size = sizeof (tt_hhea_t);
    1685           0 :     status = font->backend->load_truetype_table (font->scaled_font_subset->scaled_font,
    1686             :                                                  TT_TAG_hhea, 0,
    1687             :                                                  (unsigned char*) &hhea, &size);
    1688           0 :     if (unlikely (status))
    1689           0 :         return status;
    1690           0 :     num_hmetrics = be16_to_cpu (hhea.num_hmetrics);
    1691             : 
    1692           0 :     for (i = 1; i < font->scaled_font_subset->num_glyphs; i++) {
    1693           0 :         glyph_index = font->scaled_font_subset->glyphs[i];
    1694           0 :         long_entry_size = 2 * sizeof (int16_t);
    1695           0 :         short_entry_size = sizeof (int16_t);
    1696           0 :         if (glyph_index < num_hmetrics) {
    1697           0 :             status = font->backend->load_truetype_table (font->scaled_font_subset->scaled_font,
    1698             :                                                          TT_TAG_hmtx,
    1699           0 :                                                          glyph_index * long_entry_size,
    1700             :                                                          buf, &short_entry_size);
    1701           0 :             if (unlikely (status))
    1702           0 :                 return status;
    1703             :         }
    1704             :         else
    1705             :         {
    1706           0 :             status = font->backend->load_truetype_table (font->scaled_font_subset->scaled_font,
    1707             :                                                          TT_TAG_hmtx,
    1708           0 :                                                          (num_hmetrics - 1) * long_entry_size,
    1709             :                                                          buf, &short_entry_size);
    1710           0 :             if (unlikely (status))
    1711           0 :                 return status;
    1712             :         }
    1713           0 :         font->widths[i] = be16_to_cpu (*((int16_t*)buf));
    1714             :     }
    1715             : 
    1716           0 :     return CAIRO_STATUS_SUCCESS;
    1717             : }
    1718             : 
    1719             : static cairo_int_status_t
    1720           0 : _cairo_cff_font_create (cairo_scaled_font_subset_t  *scaled_font_subset,
    1721             :                         cairo_cff_font_t           **font_return,
    1722             :                         const char                  *subset_name)
    1723             : {
    1724             :     const cairo_scaled_font_backend_t *backend;
    1725             :     cairo_status_t status;
    1726             :     cairo_cff_font_t *font;
    1727             :     tt_head_t head;
    1728             :     tt_hhea_t hhea;
    1729             :     unsigned long size, data_length;
    1730             : 
    1731           0 :     backend = scaled_font_subset->scaled_font->backend;
    1732           0 :     if (!backend->load_truetype_table)
    1733           0 :         return CAIRO_INT_STATUS_UNSUPPORTED;
    1734             : 
    1735           0 :     data_length = 0;
    1736           0 :     status = backend->load_truetype_table( scaled_font_subset->scaled_font,
    1737             :                                            TT_TAG_CFF, 0, NULL, &data_length);
    1738           0 :     if (unlikely (status))
    1739           0 :         return status;
    1740             : 
    1741           0 :     size = sizeof (tt_head_t);
    1742           0 :     status = backend->load_truetype_table (scaled_font_subset->scaled_font,
    1743             :                                            TT_TAG_head, 0,
    1744             :                                            (unsigned char *) &head, &size);
    1745           0 :     if (unlikely (status))
    1746           0 :         return status;
    1747             : 
    1748           0 :     size = sizeof (tt_hhea_t);
    1749           0 :     status = backend->load_truetype_table (scaled_font_subset->scaled_font,
    1750             :                                            TT_TAG_hhea, 0,
    1751             :                                            (unsigned char *) &hhea, &size);
    1752           0 :     if (unlikely (status))
    1753           0 :         return status;
    1754             : 
    1755           0 :     size = 0;
    1756           0 :     status = backend->load_truetype_table (scaled_font_subset->scaled_font,
    1757             :                                            TT_TAG_hmtx, 0, NULL, &size);
    1758           0 :     if (unlikely (status))
    1759           0 :         return status;
    1760             : 
    1761           0 :     font = malloc (sizeof (cairo_cff_font_t));
    1762           0 :     if (unlikely (font == NULL))
    1763           0 :         return _cairo_error (CAIRO_STATUS_NO_MEMORY);
    1764             : 
    1765           0 :     font->backend = backend;
    1766           0 :     font->scaled_font_subset = scaled_font_subset;
    1767             : 
    1768           0 :     _cairo_array_init (&font->output, sizeof (char));
    1769           0 :     status = _cairo_array_grow_by (&font->output, 4096);
    1770           0 :     if (unlikely (status))
    1771           0 :         goto fail2;
    1772             : 
    1773           0 :     font->subset_font_name = strdup (subset_name);
    1774           0 :     if (unlikely (font->subset_font_name == NULL)) {
    1775           0 :         status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
    1776           0 :         goto fail2;
    1777             :     }
    1778           0 :     font->x_min = (int16_t) be16_to_cpu (head.x_min);
    1779           0 :     font->y_min = (int16_t) be16_to_cpu (head.y_min);
    1780           0 :     font->x_max = (int16_t) be16_to_cpu (head.x_max);
    1781           0 :     font->y_max = (int16_t) be16_to_cpu (head.y_max);
    1782           0 :     font->ascent = (int16_t) be16_to_cpu (hhea.ascender);
    1783           0 :     font->descent = (int16_t) be16_to_cpu (hhea.descender);
    1784           0 :     font->units_per_em = (int16_t) be16_to_cpu (head.units_per_em);
    1785           0 :     if (font->units_per_em == 0)
    1786           0 :         font->units_per_em = 1000;
    1787             : 
    1788           0 :     font->font_name = NULL;
    1789           0 :     status = _cairo_truetype_read_font_name (scaled_font_subset->scaled_font,
    1790             :                                              &font->ps_name,
    1791             :                                              &font->font_name);
    1792           0 :     if (_cairo_status_is_error (status))
    1793           0 :         goto fail3;
    1794             : 
    1795             :     /* If the PS name is not found, create a CairoFont-x-y name. */
    1796           0 :     if (font->ps_name == NULL) {
    1797           0 :         font->ps_name = malloc (30);
    1798           0 :         if (unlikely (font->ps_name == NULL)) {
    1799           0 :             status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
    1800           0 :             goto fail3;
    1801             :         }
    1802             : 
    1803           0 :         snprintf(font->ps_name, 30, "CairoFont-%u-%u",
    1804             :                  scaled_font_subset->font_id,
    1805             :                  scaled_font_subset->subset_id);
    1806             :     }
    1807             : 
    1808           0 :     font->widths = calloc (font->scaled_font_subset->num_glyphs, sizeof (int));
    1809           0 :     if (unlikely (font->widths == NULL)) {
    1810           0 :         status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
    1811           0 :         goto fail4;
    1812             :     }
    1813             : 
    1814           0 :     status = cairo_cff_font_create_set_widths (font);
    1815           0 :     if (unlikely (status))
    1816           0 :         goto fail5;
    1817             : 
    1818           0 :     font->data_length = data_length;
    1819           0 :     font->data = malloc (data_length);
    1820           0 :     if (unlikely (font->data == NULL)) {
    1821           0 :         status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
    1822           0 :         goto fail5;
    1823             :     }
    1824           0 :     status = font->backend->load_truetype_table ( font->scaled_font_subset->scaled_font,
    1825             :                                                   TT_TAG_CFF, 0, font->data,
    1826             :                                                   &font->data_length);
    1827           0 :     if (unlikely (status))
    1828           0 :         goto fail6;
    1829             : 
    1830           0 :     font->data_end = font->data + font->data_length;
    1831             : 
    1832           0 :     status = cff_dict_init (&font->top_dict);
    1833           0 :     if (unlikely (status))
    1834           0 :         goto fail6;
    1835             : 
    1836           0 :     status = cff_dict_init (&font->private_dict);
    1837           0 :     if (unlikely (status))
    1838           0 :         goto fail7;
    1839             : 
    1840           0 :     cff_index_init (&font->strings_index);
    1841           0 :     cff_index_init (&font->charstrings_index);
    1842           0 :     cff_index_init (&font->global_sub_index);
    1843           0 :     cff_index_init (&font->local_sub_index);
    1844           0 :     cff_index_init (&font->charstrings_subset_index);
    1845           0 :     cff_index_init (&font->strings_subset_index);
    1846           0 :     font->fdselect = NULL;
    1847           0 :     font->fd_dict = NULL;
    1848           0 :     font->fd_private_dict = NULL;
    1849           0 :     font->fd_local_sub_index = NULL;
    1850           0 :     font->fdselect_subset = NULL;
    1851           0 :     font->fd_subset_map = NULL;
    1852           0 :     font->private_dict_offset = NULL;
    1853             : 
    1854           0 :     *font_return = font;
    1855             : 
    1856           0 :     return CAIRO_STATUS_SUCCESS;
    1857             : 
    1858             : fail7:
    1859           0 :     _cairo_hash_table_destroy (font->top_dict);
    1860             : fail6:
    1861           0 :     free (font->data);
    1862             : fail5:
    1863           0 :     free (font->widths);
    1864             : fail4:
    1865           0 :     if (font->font_name)
    1866           0 :         free (font->font_name);
    1867             : fail3:
    1868           0 :     free (font->subset_font_name);
    1869             : fail2:
    1870           0 :     _cairo_array_fini (&font->output);
    1871           0 :     free (font);
    1872             : 
    1873           0 :     return status;
    1874             : }
    1875             : 
    1876             : static void
    1877           0 : cairo_cff_font_destroy (cairo_cff_font_t *font)
    1878             : {
    1879             :     unsigned int i;
    1880             : 
    1881           0 :     free (font->widths);
    1882           0 :     if (font->font_name)
    1883           0 :         free (font->font_name);
    1884           0 :     free (font->ps_name);
    1885           0 :     free (font->subset_font_name);
    1886           0 :     _cairo_array_fini (&font->output);
    1887           0 :     cff_dict_fini (font->top_dict);
    1888           0 :     cff_dict_fini (font->private_dict);
    1889           0 :     cff_index_fini (&font->strings_index);
    1890           0 :     cff_index_fini (&font->charstrings_index);
    1891           0 :     cff_index_fini (&font->global_sub_index);
    1892           0 :     cff_index_fini (&font->local_sub_index);
    1893           0 :     cff_index_fini (&font->charstrings_subset_index);
    1894           0 :     cff_index_fini (&font->strings_subset_index);
    1895             : 
    1896             :     /* If we bailed out early as a result of an error some of the
    1897             :      * following cairo_cff_font_t members may still be NULL */
    1898           0 :     if (font->fd_dict) {
    1899           0 :         for (i = 0; i < font->num_fontdicts; i++) {
    1900           0 :             if (font->fd_dict[i])
    1901           0 :                 cff_dict_fini (font->fd_dict[i]);
    1902             :         }
    1903           0 :         free (font->fd_dict);
    1904             :     }
    1905           0 :     if (font->fd_subset_map)
    1906           0 :         free (font->fd_subset_map);
    1907           0 :     if (font->private_dict_offset)
    1908           0 :         free (font->private_dict_offset);
    1909             : 
    1910           0 :     if (font->is_cid) {
    1911           0 :         if (font->fdselect)
    1912           0 :             free (font->fdselect);
    1913           0 :         if (font->fdselect_subset)
    1914           0 :             free (font->fdselect_subset);
    1915           0 :         if (font->fd_private_dict) {
    1916           0 :             for (i = 0; i < font->num_fontdicts; i++) {
    1917           0 :                 if (font->fd_private_dict[i])
    1918           0 :                     cff_dict_fini (font->fd_private_dict[i]);
    1919             :             }
    1920           0 :             free (font->fd_private_dict);
    1921             :         }
    1922           0 :         if (font->fd_local_sub_index) {
    1923           0 :             for (i = 0; i < font->num_fontdicts; i++)
    1924           0 :                 cff_index_fini (&font->fd_local_sub_index[i]);
    1925           0 :             free (font->fd_local_sub_index);
    1926             :         }
    1927             :     }
    1928             : 
    1929           0 :     if (font->data)
    1930           0 :         free (font->data);
    1931             : 
    1932           0 :     free (font);
    1933           0 : }
    1934             : 
    1935             : cairo_status_t
    1936           0 : _cairo_cff_subset_init (cairo_cff_subset_t          *cff_subset,
    1937             :                         const char                  *subset_name,
    1938             :                         cairo_scaled_font_subset_t  *font_subset)
    1939             : {
    1940           0 :     cairo_cff_font_t *font = NULL; /* squelch bogus compiler warning */
    1941             :     cairo_status_t status;
    1942           0 :     const char *data = NULL; /* squelch bogus compiler warning */
    1943           0 :     unsigned long length = 0; /* squelch bogus compiler warning */
    1944             :     unsigned int i;
    1945             : 
    1946           0 :     status = _cairo_cff_font_create (font_subset, &font, subset_name);
    1947           0 :     if (unlikely (status))
    1948           0 :         return status;
    1949             : 
    1950           0 :     status = cairo_cff_font_generate (font, &data, &length);
    1951           0 :     if (unlikely (status))
    1952           0 :         goto fail1;
    1953             : 
    1954           0 :     cff_subset->ps_name = strdup (font->ps_name);
    1955           0 :     if (unlikely (cff_subset->ps_name == NULL)) {
    1956           0 :         status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
    1957           0 :         goto fail1;
    1958             :     }
    1959             : 
    1960           0 :     if (font->font_name) {
    1961           0 :         cff_subset->font_name = strdup (font->font_name);
    1962           0 :         if (cff_subset->font_name == NULL) {
    1963           0 :             status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
    1964           0 :             goto fail2;
    1965             :         }
    1966             :     } else {
    1967           0 :         cff_subset->font_name = NULL;
    1968             :     }
    1969             : 
    1970           0 :     cff_subset->widths = calloc (sizeof (double), font->scaled_font_subset->num_glyphs);
    1971           0 :     if (unlikely (cff_subset->widths == NULL)) {
    1972           0 :         status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
    1973           0 :         goto fail3;
    1974             :     }
    1975           0 :     for (i = 0; i < font->scaled_font_subset->num_glyphs; i++)
    1976           0 :         cff_subset->widths[i] = (double)font->widths[i]/font->units_per_em;
    1977             : 
    1978           0 :     cff_subset->x_min = (double)font->x_min/font->units_per_em;
    1979           0 :     cff_subset->y_min = (double)font->y_min/font->units_per_em;
    1980           0 :     cff_subset->x_max = (double)font->x_max/font->units_per_em;
    1981           0 :     cff_subset->y_max = (double)font->y_max/font->units_per_em;
    1982           0 :     cff_subset->ascent = (double)font->ascent/font->units_per_em;
    1983           0 :     cff_subset->descent = (double)font->descent/font->units_per_em;
    1984             : 
    1985           0 :     cff_subset->data = malloc (length);
    1986           0 :     if (unlikely (cff_subset->data == NULL)) {
    1987           0 :         status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
    1988           0 :         goto fail4;
    1989             :     }
    1990             : 
    1991           0 :     memcpy (cff_subset->data, data, length);
    1992           0 :     cff_subset->data_length = length;
    1993             : 
    1994           0 :     cairo_cff_font_destroy (font);
    1995             : 
    1996           0 :     return CAIRO_STATUS_SUCCESS;
    1997             : 
    1998             :  fail4:
    1999           0 :     free (cff_subset->widths);
    2000             :  fail3:
    2001           0 :     if (cff_subset->font_name)
    2002           0 :         free (cff_subset->font_name);
    2003             :  fail2:
    2004           0 :     free (cff_subset->ps_name);
    2005             :  fail1:
    2006           0 :     cairo_cff_font_destroy (font);
    2007             : 
    2008           0 :     return status;
    2009             : }
    2010             : 
    2011             : void
    2012           0 : _cairo_cff_subset_fini (cairo_cff_subset_t *subset)
    2013             : {
    2014           0 :     free (subset->ps_name);
    2015           0 :     if (subset->font_name)
    2016           0 :         free (subset->font_name);
    2017           0 :     free (subset->widths);
    2018           0 :     free (subset->data);
    2019           0 : }
    2020             : 
    2021             : static cairo_int_status_t
    2022           0 : _cairo_cff_font_fallback_create (cairo_scaled_font_subset_t  *scaled_font_subset,
    2023             :                                  cairo_cff_font_t           **font_return,
    2024             :                                  const char                  *subset_name)
    2025             : {
    2026             :     cairo_status_t status;
    2027             :     cairo_cff_font_t *font;
    2028             : 
    2029           0 :     font = malloc (sizeof (cairo_cff_font_t));
    2030           0 :     if (unlikely (font == NULL))
    2031           0 :         return _cairo_error (CAIRO_STATUS_NO_MEMORY);
    2032             : 
    2033           0 :     font->backend = NULL;
    2034           0 :     font->scaled_font_subset = scaled_font_subset;
    2035             : 
    2036           0 :     _cairo_array_init (&font->output, sizeof (char));
    2037           0 :     status = _cairo_array_grow_by (&font->output, 4096);
    2038           0 :     if (unlikely (status))
    2039           0 :         goto fail1;
    2040             : 
    2041           0 :     font->subset_font_name = strdup (subset_name);
    2042           0 :     if (unlikely (font->subset_font_name == NULL)) {
    2043           0 :         status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
    2044           0 :         goto fail1;
    2045             :     }
    2046             : 
    2047           0 :     font->ps_name = strdup (subset_name);
    2048           0 :     if (unlikely (font->ps_name == NULL)) {
    2049           0 :         status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
    2050           0 :         goto fail2;
    2051             :     }
    2052           0 :     font->font_name = NULL;
    2053             : 
    2054           0 :     font->x_min = 0;
    2055           0 :     font->y_min = 0;
    2056           0 :     font->x_max = 0;
    2057           0 :     font->y_max = 0;
    2058           0 :     font->ascent = 0;
    2059           0 :     font->descent = 0;
    2060             : 
    2061           0 :     font->widths = calloc (font->scaled_font_subset->num_glyphs, sizeof (int));
    2062           0 :     if (unlikely (font->widths == NULL)) {
    2063           0 :         status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
    2064           0 :         goto fail3;
    2065             :     }
    2066             : 
    2067           0 :     font->data_length = 0;
    2068           0 :     font->data = NULL;
    2069           0 :     font->data_end = NULL;
    2070             : 
    2071           0 :     status = cff_dict_init (&font->top_dict);
    2072           0 :     if (unlikely (status))
    2073           0 :         goto fail4;
    2074             : 
    2075           0 :     status = cff_dict_init (&font->private_dict);
    2076           0 :     if (unlikely (status))
    2077           0 :         goto fail5;
    2078             : 
    2079           0 :     cff_index_init (&font->strings_index);
    2080           0 :     cff_index_init (&font->charstrings_index);
    2081           0 :     cff_index_init (&font->global_sub_index);
    2082           0 :     cff_index_init (&font->local_sub_index);
    2083           0 :     cff_index_init (&font->charstrings_subset_index);
    2084           0 :     cff_index_init (&font->strings_subset_index);
    2085           0 :     font->fdselect = NULL;
    2086           0 :     font->fd_dict = NULL;
    2087           0 :     font->fd_private_dict = NULL;
    2088           0 :     font->fd_local_sub_index = NULL;
    2089           0 :     font->fdselect_subset = NULL;
    2090           0 :     font->fd_subset_map = NULL;
    2091           0 :     font->private_dict_offset = NULL;
    2092             : 
    2093           0 :     *font_return = font;
    2094             : 
    2095           0 :     return CAIRO_STATUS_SUCCESS;
    2096             : 
    2097             : fail5:
    2098           0 :     _cairo_hash_table_destroy (font->top_dict);
    2099             : fail4:
    2100           0 :     free (font->widths);
    2101             : fail3:
    2102           0 :     if (font->font_name)
    2103           0 :         free (font->font_name);
    2104           0 :     free (font->ps_name);
    2105             : fail2:
    2106           0 :     free (font->subset_font_name);
    2107             : fail1:
    2108           0 :     _cairo_array_fini (&font->output);
    2109           0 :     free (font);
    2110           0 :     return status;
    2111             : }
    2112             : 
    2113             : static cairo_int_status_t
    2114           0 : cairo_cff_font_fallback_generate (cairo_cff_font_t           *font,
    2115             :                                   cairo_type2_charstrings_t  *type2_subset,
    2116             :                                   const char                **data,
    2117             :                                   unsigned long              *length)
    2118             : {
    2119             :     cairo_int_status_t status;
    2120             :     cff_header_t header;
    2121             :     cairo_array_t *charstring;
    2122             :     unsigned char buf[40];
    2123             :     unsigned char *end_buf;
    2124             :     unsigned int i;
    2125             : 
    2126             :     /* Create header */
    2127           0 :     header.major = 1;
    2128           0 :     header.minor = 0;
    2129           0 :     header.header_size = 4;
    2130           0 :     header.offset_size = 4;
    2131           0 :     font->header = &header;
    2132             : 
    2133             :     /* Create Top Dict */
    2134           0 :     font->is_cid = FALSE;
    2135           0 :     end_buf = encode_integer (buf, type2_subset->x_min);
    2136           0 :     end_buf = encode_integer (end_buf, type2_subset->y_min);
    2137           0 :     end_buf = encode_integer (end_buf, type2_subset->x_max);
    2138           0 :     end_buf = encode_integer (end_buf, type2_subset->y_max);
    2139           0 :     status = cff_dict_set_operands (font->top_dict,
    2140           0 :                                     FONTBBOX_OP, buf, end_buf - buf);
    2141           0 :     if (unlikely (status))
    2142           0 :         return status;
    2143             : 
    2144           0 :     end_buf = encode_integer_max (buf, 0);
    2145           0 :     status = cff_dict_set_operands (font->top_dict,
    2146           0 :                                     CHARSTRINGS_OP, buf, end_buf - buf);
    2147           0 :     if (unlikely (status))
    2148           0 :         return status;
    2149             : 
    2150           0 :     status = cff_dict_set_operands (font->top_dict,
    2151           0 :                                     FDSELECT_OP, buf, end_buf - buf);
    2152           0 :     if (unlikely (status))
    2153           0 :         return status;
    2154             : 
    2155           0 :     status = cff_dict_set_operands (font->top_dict,
    2156           0 :                                     FDARRAY_OP, buf, end_buf - buf);
    2157           0 :     if (unlikely (status))
    2158           0 :         return status;
    2159             : 
    2160           0 :     status = cff_dict_set_operands (font->top_dict,
    2161           0 :                                     CHARSET_OP, buf, end_buf - buf);
    2162           0 :     if (unlikely (status))
    2163           0 :         return status;
    2164             : 
    2165           0 :     status = cairo_cff_font_set_ros_strings (font);
    2166           0 :     if (unlikely (status))
    2167           0 :         return status;
    2168             : 
    2169             :     /* Create CID FD dictionary */
    2170           0 :     status = cairo_cff_font_create_cid_fontdict (font);
    2171           0 :     if (unlikely (status))
    2172           0 :         return status;
    2173             : 
    2174             :     /* Create charstrings */
    2175           0 :     for (i = 0; i < font->scaled_font_subset->num_glyphs; i++) {
    2176           0 :         charstring = _cairo_array_index(&type2_subset->charstrings, i);
    2177             : 
    2178           0 :         status = cff_index_append (&font->charstrings_subset_index,
    2179           0 :                                    _cairo_array_index (charstring, 0),
    2180             :                                    _cairo_array_num_elements (charstring));
    2181             : 
    2182           0 :         if (unlikely (status))
    2183           0 :             return status;
    2184             :     }
    2185             : 
    2186           0 :     status = cairo_cff_font_write_subset (font);
    2187           0 :     if (unlikely (status))
    2188           0 :         return status;
    2189             : 
    2190           0 :     *data = _cairo_array_index (&font->output, 0);
    2191           0 :     *length = _cairo_array_num_elements (&font->output);
    2192             : 
    2193           0 :     return CAIRO_STATUS_SUCCESS;
    2194             : }
    2195             : 
    2196             : cairo_status_t
    2197           0 : _cairo_cff_fallback_init (cairo_cff_subset_t          *cff_subset,
    2198             :                           const char                  *subset_name,
    2199             :                           cairo_scaled_font_subset_t  *font_subset)
    2200             : {
    2201           0 :     cairo_cff_font_t *font = NULL; /* squelch bogus compiler warning */
    2202             :     cairo_status_t status;
    2203           0 :     const char *data = NULL; /* squelch bogus compiler warning */
    2204           0 :     unsigned long length = 0; /* squelch bogus compiler warning */
    2205             :     unsigned int i;
    2206             :     cairo_type2_charstrings_t type2_subset;
    2207             : 
    2208           0 :     status = _cairo_cff_font_fallback_create (font_subset, &font, subset_name);
    2209           0 :     if (unlikely (status))
    2210           0 :         return status;
    2211             : 
    2212           0 :     status = _cairo_type2_charstrings_init (&type2_subset, font_subset);
    2213           0 :     if (unlikely (status))
    2214           0 :         goto fail1;
    2215             : 
    2216           0 :     status = cairo_cff_font_fallback_generate (font, &type2_subset, &data, &length);
    2217           0 :     if (unlikely (status))
    2218           0 :         goto fail2;
    2219             : 
    2220           0 :     cff_subset->font_name = NULL;
    2221           0 :     cff_subset->ps_name = strdup (font->ps_name);
    2222           0 :     if (unlikely (cff_subset->ps_name == NULL)) {
    2223           0 :         status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
    2224           0 :         goto fail2;
    2225             :     }
    2226             : 
    2227           0 :     cff_subset->widths = calloc (sizeof (double), font->scaled_font_subset->num_glyphs);
    2228           0 :     if (unlikely (cff_subset->widths == NULL)) {
    2229           0 :         status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
    2230           0 :         goto fail3;
    2231             :     }
    2232             : 
    2233           0 :     for (i = 0; i < font->scaled_font_subset->num_glyphs; i++)
    2234           0 :         cff_subset->widths[i] = (double)type2_subset.widths[i]/1000;
    2235             : 
    2236           0 :     cff_subset->x_min = (double)type2_subset.x_min/1000;
    2237           0 :     cff_subset->y_min = (double)type2_subset.y_min/1000;
    2238           0 :     cff_subset->x_max = (double)type2_subset.x_max/1000;
    2239           0 :     cff_subset->y_max = (double)type2_subset.y_max/1000;
    2240           0 :     cff_subset->ascent = (double)type2_subset.y_max/1000;
    2241           0 :     cff_subset->descent = (double)type2_subset.y_min/1000;
    2242             : 
    2243           0 :     cff_subset->data = malloc (length);
    2244           0 :     if (unlikely (cff_subset->data == NULL)) {
    2245           0 :         status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
    2246           0 :         goto fail4;
    2247             :     }
    2248             : 
    2249           0 :     memcpy (cff_subset->data, data, length);
    2250           0 :     cff_subset->data_length = length;
    2251           0 :     cff_subset->data_length = length;
    2252             : 
    2253           0 :     _cairo_type2_charstrings_fini (&type2_subset);
    2254           0 :     cairo_cff_font_destroy (font);
    2255             : 
    2256           0 :     return CAIRO_STATUS_SUCCESS;
    2257             : 
    2258             :  fail4:
    2259           0 :     free (cff_subset->widths);
    2260             :  fail3:
    2261           0 :     free (cff_subset->ps_name);
    2262             :  fail2:
    2263           0 :     _cairo_type2_charstrings_fini (&type2_subset);
    2264             :  fail1:
    2265           0 :     cairo_cff_font_destroy (font);
    2266             : 
    2267           0 :     return status;
    2268             : }
    2269             : 
    2270             : void
    2271           0 : _cairo_cff_fallback_fini (cairo_cff_subset_t *subset)
    2272             : {
    2273           0 :     free (subset->ps_name);
    2274           0 :     free (subset->widths);
    2275           0 :     free (subset->data);
    2276           0 : }
    2277             : 
    2278             : #endif /* CAIRO_HAS_FONT_SUBSET */

Generated by: LCOV version 1.13