LCOV - code coverage report
Current view: directory - gfx/cairo/cairo/src - cairo-cff-subset.c (source / functions) Found Hit Coverage
Test: app.info Lines: 1157 0 0.0 %
Date: 2012-06-02 Functions: 68 0 0.0 %

       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                 :                                     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                 :                                     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                 :                                     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                 :                                     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                 :                                     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                 :                                     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                 :     uint32_t *offset_array;
    1470                 :     int offset_base;
    1471                 :     uint16_t count;
    1472               0 :     uint8_t offset_size = 4;
    1473                 : 
    1474               0 :     cairo_cff_font_set_topdict_operator_to_cur_pos (font, FDARRAY_OP);
    1475               0 :     count = cpu_to_be16 (font->num_subset_fontdicts);
    1476               0 :     status = _cairo_array_append_multiple (&font->output, &count, sizeof (uint16_t));
    1477               0 :     if (unlikely (status))
    1478               0 :         return status;
    1479               0 :     status = _cairo_array_append (&font->output, &offset_size);
    1480               0 :     if (unlikely (status))
    1481               0 :         return status;
    1482               0 :     status = _cairo_array_allocate (&font->output,
    1483               0 :                                     (font->num_subset_fontdicts + 1)*offset_size,
    1484                 :                                     (void **) &offset_array);
    1485               0 :     if (unlikely (status))
    1486               0 :         return status;
    1487               0 :     offset_base = _cairo_array_num_elements (&font->output) - 1;
    1488               0 :     *offset_array++ = cpu_to_be32(1);
    1489               0 :     for (i = 0; i < font->num_subset_fontdicts; i++) {
    1490               0 :         status = cff_dict_write (font->fd_dict[font->fd_subset_map[i]],
    1491                 :                                  &font->output);
    1492               0 :         if (unlikely (status))
    1493               0 :             return status;
    1494               0 :         *offset_array++ = cpu_to_be32(_cairo_array_num_elements (&font->output) - offset_base);
    1495                 :     }
    1496                 : 
    1497               0 :     return CAIRO_STATUS_SUCCESS;
    1498                 : }
    1499                 : 
    1500                 : static cairo_status_t
    1501               0 : cairo_cff_font_write_private_dict (cairo_cff_font_t   *font,
    1502                 :                                    int                 dict_num,
    1503                 :                                    cairo_hash_table_t *parent_dict,
    1504                 :                                    cairo_hash_table_t *private_dict)
    1505                 : {
    1506                 :     int offset;
    1507                 :     int size;
    1508                 :     unsigned char buf[10];
    1509                 :     unsigned char *buf_end;
    1510                 :     unsigned char *p;
    1511                 :     cairo_status_t status;
    1512                 : 
    1513                 :     /* Write private dict and update offset and size in top dict */
    1514               0 :     font->private_dict_offset[dict_num] = _cairo_array_num_elements (&font->output);
    1515               0 :     status = cff_dict_write (private_dict, &font->output);
    1516               0 :     if (unlikely (status))
    1517               0 :         return status;
    1518                 : 
    1519               0 :     size = _cairo_array_num_elements (&font->output) - font->private_dict_offset[dict_num];
    1520                 :     /* private entry has two operands - size and offset */
    1521               0 :     buf_end = encode_integer_max (buf, size);
    1522               0 :     buf_end = encode_integer_max (buf_end, font->private_dict_offset[dict_num]);
    1523               0 :     offset = cff_dict_get_location (parent_dict, PRIVATE_OP, &size);
    1524               0 :     assert (offset > 0);
    1525               0 :     p = _cairo_array_index (&font->output, offset);
    1526               0 :     memcpy (p, buf, buf_end - buf);
    1527                 : 
    1528               0 :     return CAIRO_STATUS_SUCCESS;
    1529                 : }
    1530                 : 
    1531                 : static cairo_status_t
    1532               0 : cairo_cff_font_write_local_sub (cairo_cff_font_t   *font,
    1533                 :                                 int                 dict_num,
    1534                 :                                 cairo_hash_table_t *private_dict,
    1535                 :                                 cairo_array_t      *local_sub_index)
    1536                 : {
    1537                 :     int offset;
    1538                 :     int size;
    1539                 :     unsigned char buf[10];
    1540                 :     unsigned char *buf_end;
    1541                 :     unsigned char *p;
    1542                 :     cairo_status_t status;
    1543                 : 
    1544               0 :     if (_cairo_array_num_elements (local_sub_index) > 0) {
    1545                 :         /* Write local subroutines and update offset in private
    1546                 :          * dict. Local subroutines offset is relative to start of
    1547                 :          * private dict */
    1548               0 :         offset = _cairo_array_num_elements (&font->output) - font->private_dict_offset[dict_num];
    1549               0 :         buf_end = encode_integer_max (buf, offset);
    1550               0 :         offset = cff_dict_get_location (private_dict, LOCAL_SUB_OP, &size);
    1551               0 :         assert (offset > 0);
    1552               0 :         p = _cairo_array_index (&font->output, offset);
    1553               0 :         memcpy (p, buf, buf_end - buf);
    1554               0 :         status = cff_index_write (local_sub_index, &font->output);
    1555               0 :         if (unlikely (status))
    1556               0 :             return status;
    1557                 :     }
    1558                 : 
    1559               0 :     return CAIRO_STATUS_SUCCESS;
    1560                 : }
    1561                 : 
    1562                 : 
    1563                 : static cairo_status_t
    1564               0 : cairo_cff_font_write_cid_private_dict_and_local_sub (cairo_cff_font_t  *font)
    1565                 : {
    1566                 :     unsigned int i;
    1567                 :     cairo_int_status_t status;
    1568                 : 
    1569               0 :     if (font->is_cid) {
    1570               0 :         for (i = 0; i < font->num_subset_fontdicts; i++) {
    1571               0 :             status = cairo_cff_font_write_private_dict (
    1572                 :                             font,
    1573                 :                             i,
    1574               0 :                             font->fd_dict[font->fd_subset_map[i]],
    1575               0 :                             font->fd_private_dict[font->fd_subset_map[i]]);
    1576               0 :             if (unlikely (status))
    1577               0 :                 return status;
    1578                 :         }
    1579                 : 
    1580               0 :         for (i = 0; i < font->num_subset_fontdicts; i++) {
    1581               0 :             status = cairo_cff_font_write_local_sub (
    1582                 :                             font,
    1583                 :                             i,
    1584               0 :                             font->fd_private_dict[font->fd_subset_map[i]],
    1585               0 :                            &font->fd_local_sub_index[font->fd_subset_map[i]]);
    1586               0 :             if (unlikely (status))
    1587               0 :                 return status;
    1588                 :         }
    1589                 :     } else {
    1590               0 :         status = cairo_cff_font_write_private_dict (font,
    1591                 :                                                     0,
    1592               0 :                                                     font->fd_dict[0],
    1593                 :                                                     font->private_dict);
    1594               0 :         if (unlikely (status))
    1595               0 :             return status;
    1596                 : 
    1597               0 :         status = cairo_cff_font_write_local_sub (font,
    1598                 :                                                  0,
    1599                 :                                                  font->private_dict,
    1600                 :                                                  &font->local_sub_index);
    1601               0 :         if (unlikely (status))
    1602               0 :             return status;
    1603                 :     }
    1604                 : 
    1605               0 :     return CAIRO_STATUS_SUCCESS;
    1606                 : }
    1607                 : 
    1608                 : typedef cairo_status_t
    1609                 : (*font_write_t) (cairo_cff_font_t *font);
    1610                 : 
    1611                 : static const font_write_t font_write_funcs[] = {
    1612                 :     cairo_cff_font_write_header,
    1613                 :     cairo_cff_font_write_name,
    1614                 :     cairo_cff_font_write_top_dict,
    1615                 :     cairo_cff_font_write_strings,
    1616                 :     cairo_cff_font_write_global_subrs,
    1617                 :     cairo_cff_font_write_charset,
    1618                 :     cairo_cff_font_write_fdselect,
    1619                 :     cairo_cff_font_write_charstrings,
    1620                 :     cairo_cff_font_write_cid_fontdict,
    1621                 :     cairo_cff_font_write_cid_private_dict_and_local_sub,
    1622                 : };
    1623                 : 
    1624                 : static cairo_status_t
    1625               0 : cairo_cff_font_write_subset (cairo_cff_font_t *font)
    1626                 : {
    1627                 :     cairo_int_status_t status;
    1628                 :     unsigned int i;
    1629                 : 
    1630               0 :     for (i = 0; i < ARRAY_LENGTH (font_write_funcs); i++) {
    1631               0 :         status = font_write_funcs[i] (font);
    1632               0 :         if (unlikely (status))
    1633               0 :             return status;
    1634                 :     }
    1635                 : 
    1636               0 :     return CAIRO_STATUS_SUCCESS;
    1637                 : }
    1638                 : 
    1639                 : static cairo_int_status_t
    1640               0 : cairo_cff_font_generate (cairo_cff_font_t  *font,
    1641                 :                          const char       **data,
    1642                 :                          unsigned long     *length)
    1643                 : {
    1644                 :     cairo_int_status_t status;
    1645                 : 
    1646               0 :     status = cairo_cff_font_read_font (font);
    1647               0 :     if (unlikely (status))
    1648               0 :         return status;
    1649                 : 
    1650               0 :     status = cairo_cff_font_subset_font (font);
    1651               0 :     if (unlikely (status))
    1652               0 :         return status;
    1653                 : 
    1654               0 :     status = cairo_cff_font_write_subset (font);
    1655               0 :     if (unlikely (status))
    1656               0 :         return status;
    1657                 : 
    1658               0 :     *data = _cairo_array_index (&font->output, 0);
    1659               0 :     *length = _cairo_array_num_elements (&font->output);
    1660                 : 
    1661               0 :     return CAIRO_STATUS_SUCCESS;
    1662                 : }
    1663                 : 
    1664                 : static cairo_int_status_t
    1665               0 : cairo_cff_font_create_set_widths (cairo_cff_font_t *font)
    1666                 : {
    1667                 :     unsigned long size;
    1668                 :     unsigned long long_entry_size;
    1669                 :     unsigned long short_entry_size;
    1670                 :     unsigned int i;
    1671                 :     tt_hhea_t hhea;
    1672                 :     int num_hmetrics;
    1673                 :     unsigned char buf[10];
    1674                 :     int glyph_index;
    1675                 :     cairo_int_status_t status;
    1676                 : 
    1677               0 :     size = sizeof (tt_hhea_t);
    1678               0 :     status = font->backend->load_truetype_table (font->scaled_font_subset->scaled_font,
    1679                 :                                                  TT_TAG_hhea, 0,
    1680                 :                                                  (unsigned char*) &hhea, &size);
    1681               0 :     if (unlikely (status))
    1682               0 :         return status;
    1683               0 :     num_hmetrics = be16_to_cpu (hhea.num_hmetrics);
    1684                 : 
    1685               0 :     for (i = 1; i < font->scaled_font_subset->num_glyphs; i++) {
    1686               0 :         glyph_index = font->scaled_font_subset->glyphs[i];
    1687               0 :         long_entry_size = 2 * sizeof (int16_t);
    1688               0 :         short_entry_size = sizeof (int16_t);
    1689               0 :         if (glyph_index < num_hmetrics) {
    1690               0 :             status = font->backend->load_truetype_table (font->scaled_font_subset->scaled_font,
    1691                 :                                                          TT_TAG_hmtx,
    1692               0 :                                                          glyph_index * long_entry_size,
    1693                 :                                                          buf, &short_entry_size);
    1694               0 :             if (unlikely (status))
    1695               0 :                 return status;
    1696                 :         }
    1697                 :         else
    1698                 :         {
    1699               0 :             status = font->backend->load_truetype_table (font->scaled_font_subset->scaled_font,
    1700                 :                                                          TT_TAG_hmtx,
    1701               0 :                                                          (num_hmetrics - 1) * long_entry_size,
    1702                 :                                                          buf, &short_entry_size);
    1703               0 :             if (unlikely (status))
    1704               0 :                 return status;
    1705                 :         }
    1706               0 :         font->widths[i] = be16_to_cpu (*((int16_t*)buf));
    1707                 :     }
    1708                 : 
    1709               0 :     return CAIRO_STATUS_SUCCESS;
    1710                 : }
    1711                 : 
    1712                 : static cairo_int_status_t
    1713               0 : _cairo_cff_font_create (cairo_scaled_font_subset_t  *scaled_font_subset,
    1714                 :                         cairo_cff_font_t           **font_return,
    1715                 :                         const char                  *subset_name)
    1716                 : {
    1717                 :     const cairo_scaled_font_backend_t *backend;
    1718                 :     cairo_status_t status;
    1719                 :     cairo_cff_font_t *font;
    1720                 :     tt_head_t head;
    1721                 :     tt_hhea_t hhea;
    1722                 :     unsigned long size, data_length;
    1723                 : 
    1724               0 :     backend = scaled_font_subset->scaled_font->backend;
    1725               0 :     if (!backend->load_truetype_table)
    1726               0 :         return CAIRO_INT_STATUS_UNSUPPORTED;
    1727                 : 
    1728               0 :     data_length = 0;
    1729               0 :     status = backend->load_truetype_table( scaled_font_subset->scaled_font,
    1730                 :                                            TT_TAG_CFF, 0, NULL, &data_length);
    1731               0 :     if (unlikely (status))
    1732               0 :         return status;
    1733                 : 
    1734               0 :     size = sizeof (tt_head_t);
    1735               0 :     status = backend->load_truetype_table (scaled_font_subset->scaled_font,
    1736                 :                                            TT_TAG_head, 0,
    1737                 :                                            (unsigned char *) &head, &size);
    1738               0 :     if (unlikely (status))
    1739               0 :         return status;
    1740                 : 
    1741               0 :     size = sizeof (tt_hhea_t);
    1742               0 :     status = backend->load_truetype_table (scaled_font_subset->scaled_font,
    1743                 :                                            TT_TAG_hhea, 0,
    1744                 :                                            (unsigned char *) &hhea, &size);
    1745               0 :     if (unlikely (status))
    1746               0 :         return status;
    1747                 : 
    1748               0 :     size = 0;
    1749               0 :     status = backend->load_truetype_table (scaled_font_subset->scaled_font,
    1750                 :                                            TT_TAG_hmtx, 0, NULL, &size);
    1751               0 :     if (unlikely (status))
    1752               0 :         return status;
    1753                 : 
    1754               0 :     font = malloc (sizeof (cairo_cff_font_t));
    1755               0 :     if (unlikely (font == NULL))
    1756               0 :         return _cairo_error (CAIRO_STATUS_NO_MEMORY);
    1757                 : 
    1758               0 :     font->backend = backend;
    1759               0 :     font->scaled_font_subset = scaled_font_subset;
    1760                 : 
    1761               0 :     _cairo_array_init (&font->output, sizeof (char));
    1762               0 :     status = _cairo_array_grow_by (&font->output, 4096);
    1763               0 :     if (unlikely (status))
    1764               0 :         goto fail2;
    1765                 : 
    1766               0 :     font->subset_font_name = strdup (subset_name);
    1767               0 :     if (unlikely (font->subset_font_name == NULL)) {
    1768               0 :         status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
    1769               0 :         goto fail2;
    1770                 :     }
    1771               0 :     font->x_min = (int16_t) be16_to_cpu (head.x_min);
    1772               0 :     font->y_min = (int16_t) be16_to_cpu (head.y_min);
    1773               0 :     font->x_max = (int16_t) be16_to_cpu (head.x_max);
    1774               0 :     font->y_max = (int16_t) be16_to_cpu (head.y_max);
    1775               0 :     font->ascent = (int16_t) be16_to_cpu (hhea.ascender);
    1776               0 :     font->descent = (int16_t) be16_to_cpu (hhea.descender);
    1777               0 :     font->units_per_em = (int16_t) be16_to_cpu (head.units_per_em);
    1778               0 :     if (font->units_per_em == 0)
    1779               0 :         font->units_per_em = 1000;
    1780                 : 
    1781               0 :     font->font_name = NULL;
    1782               0 :     status = _cairo_truetype_read_font_name (scaled_font_subset->scaled_font,
    1783                 :                                              &font->ps_name,
    1784                 :                                              &font->font_name);
    1785               0 :     if (_cairo_status_is_error (status))
    1786               0 :         goto fail3;
    1787                 : 
    1788                 :     /* If the PS name is not found, create a CairoFont-x-y name. */
    1789               0 :     if (font->ps_name == NULL) {
    1790               0 :         font->ps_name = malloc (30);
    1791               0 :         if (unlikely (font->ps_name == NULL)) {
    1792               0 :             status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
    1793               0 :             goto fail3;
    1794                 :         }
    1795                 : 
    1796               0 :         snprintf(font->ps_name, 30, "CairoFont-%u-%u",
    1797                 :                  scaled_font_subset->font_id,
    1798                 :                  scaled_font_subset->subset_id);
    1799                 :     }
    1800                 : 
    1801               0 :     font->widths = calloc (font->scaled_font_subset->num_glyphs, sizeof (int));
    1802               0 :     if (unlikely (font->widths == NULL)) {
    1803               0 :         status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
    1804               0 :         goto fail4;
    1805                 :     }
    1806                 : 
    1807               0 :     status = cairo_cff_font_create_set_widths (font);
    1808               0 :     if (unlikely (status))
    1809               0 :         goto fail5;
    1810                 : 
    1811               0 :     font->data_length = data_length;
    1812               0 :     font->data = malloc (data_length);
    1813               0 :     if (unlikely (font->data == NULL)) {
    1814               0 :         status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
    1815               0 :         goto fail5;
    1816                 :     }
    1817               0 :     status = font->backend->load_truetype_table ( font->scaled_font_subset->scaled_font,
    1818                 :                                                   TT_TAG_CFF, 0, font->data,
    1819                 :                                                   &font->data_length);
    1820               0 :     if (unlikely (status))
    1821               0 :         goto fail6;
    1822                 : 
    1823               0 :     font->data_end = font->data + font->data_length;
    1824                 : 
    1825               0 :     status = cff_dict_init (&font->top_dict);
    1826               0 :     if (unlikely (status))
    1827               0 :         goto fail6;
    1828                 : 
    1829               0 :     status = cff_dict_init (&font->private_dict);
    1830               0 :     if (unlikely (status))
    1831               0 :         goto fail7;
    1832                 : 
    1833               0 :     cff_index_init (&font->strings_index);
    1834               0 :     cff_index_init (&font->charstrings_index);
    1835               0 :     cff_index_init (&font->global_sub_index);
    1836               0 :     cff_index_init (&font->local_sub_index);
    1837               0 :     cff_index_init (&font->charstrings_subset_index);
    1838               0 :     cff_index_init (&font->strings_subset_index);
    1839               0 :     font->fdselect = NULL;
    1840               0 :     font->fd_dict = NULL;
    1841               0 :     font->fd_private_dict = NULL;
    1842               0 :     font->fd_local_sub_index = NULL;
    1843               0 :     font->fdselect_subset = NULL;
    1844               0 :     font->fd_subset_map = NULL;
    1845               0 :     font->private_dict_offset = NULL;
    1846                 : 
    1847               0 :     *font_return = font;
    1848                 : 
    1849               0 :     return CAIRO_STATUS_SUCCESS;
    1850                 : 
    1851                 : fail7:
    1852               0 :     _cairo_hash_table_destroy (font->top_dict);
    1853                 : fail6:
    1854               0 :     free (font->data);
    1855                 : fail5:
    1856               0 :     free (font->widths);
    1857                 : fail4:
    1858               0 :     if (font->font_name)
    1859               0 :         free (font->font_name);
    1860                 : fail3:
    1861               0 :     free (font->subset_font_name);
    1862                 : fail2:
    1863               0 :     _cairo_array_fini (&font->output);
    1864               0 :     free (font);
    1865                 : 
    1866               0 :     return status;
    1867                 : }
    1868                 : 
    1869                 : static void
    1870               0 : cairo_cff_font_destroy (cairo_cff_font_t *font)
    1871                 : {
    1872                 :     unsigned int i;
    1873                 : 
    1874               0 :     free (font->widths);
    1875               0 :     if (font->font_name)
    1876               0 :         free (font->font_name);
    1877               0 :     free (font->ps_name);
    1878               0 :     free (font->subset_font_name);
    1879               0 :     _cairo_array_fini (&font->output);
    1880               0 :     cff_dict_fini (font->top_dict);
    1881               0 :     cff_dict_fini (font->private_dict);
    1882               0 :     cff_index_fini (&font->strings_index);
    1883               0 :     cff_index_fini (&font->charstrings_index);
    1884               0 :     cff_index_fini (&font->global_sub_index);
    1885               0 :     cff_index_fini (&font->local_sub_index);
    1886               0 :     cff_index_fini (&font->charstrings_subset_index);
    1887               0 :     cff_index_fini (&font->strings_subset_index);
    1888                 : 
    1889                 :     /* If we bailed out early as a result of an error some of the
    1890                 :      * following cairo_cff_font_t members may still be NULL */
    1891               0 :     if (font->fd_dict) {
    1892               0 :         for (i = 0; i < font->num_fontdicts; i++) {
    1893               0 :             if (font->fd_dict[i])
    1894               0 :                 cff_dict_fini (font->fd_dict[i]);
    1895                 :         }
    1896               0 :         free (font->fd_dict);
    1897                 :     }
    1898               0 :     if (font->fd_subset_map)
    1899               0 :         free (font->fd_subset_map);
    1900               0 :     if (font->private_dict_offset)
    1901               0 :         free (font->private_dict_offset);
    1902                 : 
    1903               0 :     if (font->is_cid) {
    1904               0 :         if (font->fdselect)
    1905               0 :             free (font->fdselect);
    1906               0 :         if (font->fdselect_subset)
    1907               0 :             free (font->fdselect_subset);
    1908               0 :         if (font->fd_private_dict) {
    1909               0 :             for (i = 0; i < font->num_fontdicts; i++) {
    1910               0 :                 if (font->fd_private_dict[i])
    1911               0 :                     cff_dict_fini (font->fd_private_dict[i]);
    1912                 :             }
    1913               0 :             free (font->fd_private_dict);
    1914                 :         }
    1915               0 :         if (font->fd_local_sub_index) {
    1916               0 :             for (i = 0; i < font->num_fontdicts; i++)
    1917               0 :                 cff_index_fini (&font->fd_local_sub_index[i]);
    1918               0 :             free (font->fd_local_sub_index);
    1919                 :         }
    1920                 :     }
    1921                 : 
    1922               0 :     if (font->data)
    1923               0 :         free (font->data);
    1924                 : 
    1925               0 :     free (font);
    1926               0 : }
    1927                 : 
    1928                 : cairo_status_t
    1929               0 : _cairo_cff_subset_init (cairo_cff_subset_t          *cff_subset,
    1930                 :                         const char                  *subset_name,
    1931                 :                         cairo_scaled_font_subset_t  *font_subset)
    1932                 : {
    1933               0 :     cairo_cff_font_t *font = NULL; /* squelch bogus compiler warning */
    1934                 :     cairo_status_t status;
    1935               0 :     const char *data = NULL; /* squelch bogus compiler warning */
    1936               0 :     unsigned long length = 0; /* squelch bogus compiler warning */
    1937                 :     unsigned int i;
    1938                 : 
    1939               0 :     status = _cairo_cff_font_create (font_subset, &font, subset_name);
    1940               0 :     if (unlikely (status))
    1941               0 :         return status;
    1942                 : 
    1943               0 :     status = cairo_cff_font_generate (font, &data, &length);
    1944               0 :     if (unlikely (status))
    1945               0 :         goto fail1;
    1946                 : 
    1947               0 :     cff_subset->ps_name = strdup (font->ps_name);
    1948               0 :     if (unlikely (cff_subset->ps_name == NULL)) {
    1949               0 :         status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
    1950               0 :         goto fail1;
    1951                 :     }
    1952                 : 
    1953               0 :     if (font->font_name) {
    1954               0 :         cff_subset->font_name = strdup (font->font_name);
    1955               0 :         if (cff_subset->font_name == NULL) {
    1956               0 :             status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
    1957               0 :             goto fail2;
    1958                 :         }
    1959                 :     } else {
    1960               0 :         cff_subset->font_name = NULL;
    1961                 :     }
    1962                 : 
    1963               0 :     cff_subset->widths = calloc (sizeof (double), font->scaled_font_subset->num_glyphs);
    1964               0 :     if (unlikely (cff_subset->widths == NULL)) {
    1965               0 :         status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
    1966               0 :         goto fail3;
    1967                 :     }
    1968               0 :     for (i = 0; i < font->scaled_font_subset->num_glyphs; i++)
    1969               0 :         cff_subset->widths[i] = (double)font->widths[i]/font->units_per_em;
    1970                 : 
    1971               0 :     cff_subset->x_min = (double)font->x_min/font->units_per_em;
    1972               0 :     cff_subset->y_min = (double)font->y_min/font->units_per_em;
    1973               0 :     cff_subset->x_max = (double)font->x_max/font->units_per_em;
    1974               0 :     cff_subset->y_max = (double)font->y_max/font->units_per_em;
    1975               0 :     cff_subset->ascent = (double)font->ascent/font->units_per_em;
    1976               0 :     cff_subset->descent = (double)font->descent/font->units_per_em;
    1977                 : 
    1978               0 :     cff_subset->data = malloc (length);
    1979               0 :     if (unlikely (cff_subset->data == NULL)) {
    1980               0 :         status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
    1981               0 :         goto fail4;
    1982                 :     }
    1983                 : 
    1984               0 :     memcpy (cff_subset->data, data, length);
    1985               0 :     cff_subset->data_length = length;
    1986                 : 
    1987               0 :     cairo_cff_font_destroy (font);
    1988                 : 
    1989               0 :     return CAIRO_STATUS_SUCCESS;
    1990                 : 
    1991                 :  fail4:
    1992               0 :     free (cff_subset->widths);
    1993                 :  fail3:
    1994               0 :     if (cff_subset->font_name)
    1995               0 :         free (cff_subset->font_name);
    1996                 :  fail2:
    1997               0 :     free (cff_subset->ps_name);
    1998                 :  fail1:
    1999               0 :     cairo_cff_font_destroy (font);
    2000                 : 
    2001               0 :     return status;
    2002                 : }
    2003                 : 
    2004                 : void
    2005               0 : _cairo_cff_subset_fini (cairo_cff_subset_t *subset)
    2006                 : {
    2007               0 :     free (subset->ps_name);
    2008               0 :     if (subset->font_name)
    2009               0 :         free (subset->font_name);
    2010               0 :     free (subset->widths);
    2011               0 :     free (subset->data);
    2012               0 : }
    2013                 : 
    2014                 : static cairo_int_status_t
    2015               0 : _cairo_cff_font_fallback_create (cairo_scaled_font_subset_t  *scaled_font_subset,
    2016                 :                                  cairo_cff_font_t           **font_return,
    2017                 :                                  const char                  *subset_name)
    2018                 : {
    2019                 :     cairo_status_t status;
    2020                 :     cairo_cff_font_t *font;
    2021                 : 
    2022               0 :     font = malloc (sizeof (cairo_cff_font_t));
    2023               0 :     if (unlikely (font == NULL))
    2024               0 :         return _cairo_error (CAIRO_STATUS_NO_MEMORY);
    2025                 : 
    2026               0 :     font->backend = NULL;
    2027               0 :     font->scaled_font_subset = scaled_font_subset;
    2028                 : 
    2029               0 :     _cairo_array_init (&font->output, sizeof (char));
    2030               0 :     status = _cairo_array_grow_by (&font->output, 4096);
    2031               0 :     if (unlikely (status))
    2032               0 :         goto fail1;
    2033                 : 
    2034               0 :     font->subset_font_name = strdup (subset_name);
    2035               0 :     if (unlikely (font->subset_font_name == NULL)) {
    2036               0 :         status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
    2037               0 :         goto fail1;
    2038                 :     }
    2039                 : 
    2040               0 :     font->ps_name = strdup (subset_name);
    2041               0 :     if (unlikely (font->ps_name == NULL)) {
    2042               0 :         status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
    2043               0 :         goto fail2;
    2044                 :     }
    2045               0 :     font->font_name = NULL;
    2046                 : 
    2047               0 :     font->x_min = 0;
    2048               0 :     font->y_min = 0;
    2049               0 :     font->x_max = 0;
    2050               0 :     font->y_max = 0;
    2051               0 :     font->ascent = 0;
    2052               0 :     font->descent = 0;
    2053                 : 
    2054               0 :     font->widths = calloc (font->scaled_font_subset->num_glyphs, sizeof (int));
    2055               0 :     if (unlikely (font->widths == NULL)) {
    2056               0 :         status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
    2057               0 :         goto fail3;
    2058                 :     }
    2059                 : 
    2060               0 :     font->data_length = 0;
    2061               0 :     font->data = NULL;
    2062               0 :     font->data_end = NULL;
    2063                 : 
    2064               0 :     status = cff_dict_init (&font->top_dict);
    2065               0 :     if (unlikely (status))
    2066               0 :         goto fail4;
    2067                 : 
    2068               0 :     status = cff_dict_init (&font->private_dict);
    2069               0 :     if (unlikely (status))
    2070               0 :         goto fail5;
    2071                 : 
    2072               0 :     cff_index_init (&font->strings_index);
    2073               0 :     cff_index_init (&font->charstrings_index);
    2074               0 :     cff_index_init (&font->global_sub_index);
    2075               0 :     cff_index_init (&font->local_sub_index);
    2076               0 :     cff_index_init (&font->charstrings_subset_index);
    2077               0 :     cff_index_init (&font->strings_subset_index);
    2078               0 :     font->fdselect = NULL;
    2079               0 :     font->fd_dict = NULL;
    2080               0 :     font->fd_private_dict = NULL;
    2081               0 :     font->fd_local_sub_index = NULL;
    2082               0 :     font->fdselect_subset = NULL;
    2083               0 :     font->fd_subset_map = NULL;
    2084               0 :     font->private_dict_offset = NULL;
    2085                 : 
    2086               0 :     *font_return = font;
    2087                 : 
    2088               0 :     return CAIRO_STATUS_SUCCESS;
    2089                 : 
    2090                 : fail5:
    2091               0 :     _cairo_hash_table_destroy (font->top_dict);
    2092                 : fail4:
    2093               0 :     free (font->widths);
    2094                 : fail3:
    2095               0 :     if (font->font_name)
    2096               0 :         free (font->font_name);
    2097               0 :     free (font->ps_name);
    2098                 : fail2:
    2099               0 :     free (font->subset_font_name);
    2100                 : fail1:
    2101               0 :     _cairo_array_fini (&font->output);
    2102               0 :     free (font);
    2103               0 :     return status;
    2104                 : }
    2105                 : 
    2106                 : static cairo_int_status_t
    2107               0 : cairo_cff_font_fallback_generate (cairo_cff_font_t           *font,
    2108                 :                                   cairo_type2_charstrings_t  *type2_subset,
    2109                 :                                   const char                **data,
    2110                 :                                   unsigned long              *length)
    2111                 : {
    2112                 :     cairo_int_status_t status;
    2113                 :     cff_header_t header;
    2114                 :     cairo_array_t *charstring;
    2115                 :     unsigned char buf[40];
    2116                 :     unsigned char *end_buf;
    2117                 :     unsigned int i;
    2118                 : 
    2119                 :     /* Create header */
    2120               0 :     header.major = 1;
    2121               0 :     header.minor = 0;
    2122               0 :     header.header_size = 4;
    2123               0 :     header.offset_size = 4;
    2124               0 :     font->header = &header;
    2125                 : 
    2126                 :     /* Create Top Dict */
    2127               0 :     font->is_cid = FALSE;
    2128               0 :     end_buf = encode_integer (buf, type2_subset->x_min);
    2129               0 :     end_buf = encode_integer (end_buf, type2_subset->y_min);
    2130               0 :     end_buf = encode_integer (end_buf, type2_subset->x_max);
    2131               0 :     end_buf = encode_integer (end_buf, type2_subset->y_max);
    2132               0 :     status = cff_dict_set_operands (font->top_dict,
    2133                 :                                     FONTBBOX_OP, buf, end_buf - buf);
    2134               0 :     if (unlikely (status))
    2135               0 :         return status;
    2136                 : 
    2137               0 :     end_buf = encode_integer_max (buf, 0);
    2138               0 :     status = cff_dict_set_operands (font->top_dict,
    2139                 :                                     CHARSTRINGS_OP, buf, end_buf - buf);
    2140               0 :     if (unlikely (status))
    2141               0 :         return status;
    2142                 : 
    2143               0 :     status = cff_dict_set_operands (font->top_dict,
    2144                 :                                     FDSELECT_OP, buf, end_buf - buf);
    2145               0 :     if (unlikely (status))
    2146               0 :         return status;
    2147                 : 
    2148               0 :     status = cff_dict_set_operands (font->top_dict,
    2149                 :                                     FDARRAY_OP, buf, end_buf - buf);
    2150               0 :     if (unlikely (status))
    2151               0 :         return status;
    2152                 : 
    2153               0 :     status = cff_dict_set_operands (font->top_dict,
    2154                 :                                     CHARSET_OP, buf, end_buf - buf);
    2155               0 :     if (unlikely (status))
    2156               0 :         return status;
    2157                 : 
    2158               0 :     status = cairo_cff_font_set_ros_strings (font);
    2159               0 :     if (unlikely (status))
    2160               0 :         return status;
    2161                 : 
    2162                 :     /* Create CID FD dictionary */
    2163               0 :     status = cairo_cff_font_create_cid_fontdict (font);
    2164               0 :     if (unlikely (status))
    2165               0 :         return status;
    2166                 : 
    2167                 :     /* Create charstrings */
    2168               0 :     for (i = 0; i < font->scaled_font_subset->num_glyphs; i++) {
    2169               0 :         charstring = _cairo_array_index(&type2_subset->charstrings, i);
    2170                 : 
    2171               0 :         status = cff_index_append (&font->charstrings_subset_index,
    2172               0 :                                    _cairo_array_index (charstring, 0),
    2173                 :                                    _cairo_array_num_elements (charstring));
    2174                 : 
    2175               0 :         if (unlikely (status))
    2176               0 :             return status;
    2177                 :     }
    2178                 : 
    2179               0 :     status = cairo_cff_font_write_subset (font);
    2180               0 :     if (unlikely (status))
    2181               0 :         return status;
    2182                 : 
    2183               0 :     *data = _cairo_array_index (&font->output, 0);
    2184               0 :     *length = _cairo_array_num_elements (&font->output);
    2185                 : 
    2186               0 :     return CAIRO_STATUS_SUCCESS;
    2187                 : }
    2188                 : 
    2189                 : cairo_status_t
    2190               0 : _cairo_cff_fallback_init (cairo_cff_subset_t          *cff_subset,
    2191                 :                           const char                  *subset_name,
    2192                 :                           cairo_scaled_font_subset_t  *font_subset)
    2193                 : {
    2194               0 :     cairo_cff_font_t *font = NULL; /* squelch bogus compiler warning */
    2195                 :     cairo_status_t status;
    2196               0 :     const char *data = NULL; /* squelch bogus compiler warning */
    2197               0 :     unsigned long length = 0; /* squelch bogus compiler warning */
    2198                 :     unsigned int i;
    2199                 :     cairo_type2_charstrings_t type2_subset;
    2200                 : 
    2201               0 :     status = _cairo_cff_font_fallback_create (font_subset, &font, subset_name);
    2202               0 :     if (unlikely (status))
    2203               0 :         return status;
    2204                 : 
    2205               0 :     status = _cairo_type2_charstrings_init (&type2_subset, font_subset);
    2206               0 :     if (unlikely (status))
    2207               0 :         goto fail1;
    2208                 : 
    2209               0 :     status = cairo_cff_font_fallback_generate (font, &type2_subset, &data, &length);
    2210               0 :     if (unlikely (status))
    2211               0 :         goto fail2;
    2212                 : 
    2213               0 :     cff_subset->font_name = NULL;
    2214               0 :     cff_subset->ps_name = strdup (font->ps_name);
    2215               0 :     if (unlikely (cff_subset->ps_name == NULL)) {
    2216               0 :         status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
    2217               0 :         goto fail2;
    2218                 :     }
    2219                 : 
    2220               0 :     cff_subset->widths = calloc (sizeof (double), font->scaled_font_subset->num_glyphs);
    2221               0 :     if (unlikely (cff_subset->widths == NULL)) {
    2222               0 :         status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
    2223               0 :         goto fail3;
    2224                 :     }
    2225                 : 
    2226               0 :     for (i = 0; i < font->scaled_font_subset->num_glyphs; i++)
    2227               0 :         cff_subset->widths[i] = (double)type2_subset.widths[i]/1000;
    2228                 : 
    2229               0 :     cff_subset->x_min = (double)type2_subset.x_min/1000;
    2230               0 :     cff_subset->y_min = (double)type2_subset.y_min/1000;
    2231               0 :     cff_subset->x_max = (double)type2_subset.x_max/1000;
    2232               0 :     cff_subset->y_max = (double)type2_subset.y_max/1000;
    2233               0 :     cff_subset->ascent = (double)type2_subset.y_max/1000;
    2234               0 :     cff_subset->descent = (double)type2_subset.y_min/1000;
    2235                 : 
    2236               0 :     cff_subset->data = malloc (length);
    2237               0 :     if (unlikely (cff_subset->data == NULL)) {
    2238               0 :         status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
    2239               0 :         goto fail4;
    2240                 :     }
    2241                 : 
    2242               0 :     memcpy (cff_subset->data, data, length);
    2243               0 :     cff_subset->data_length = length;
    2244               0 :     cff_subset->data_length = length;
    2245                 : 
    2246               0 :     _cairo_type2_charstrings_fini (&type2_subset);
    2247               0 :     cairo_cff_font_destroy (font);
    2248                 : 
    2249               0 :     return CAIRO_STATUS_SUCCESS;
    2250                 : 
    2251                 :  fail4:
    2252               0 :     free (cff_subset->widths);
    2253                 :  fail3:
    2254               0 :     free (cff_subset->ps_name);
    2255                 :  fail2:
    2256               0 :     _cairo_type2_charstrings_fini (&type2_subset);
    2257                 :  fail1:
    2258               0 :     cairo_cff_font_destroy (font);
    2259                 : 
    2260               0 :     return status;
    2261                 : }
    2262                 : 
    2263                 : void
    2264               0 : _cairo_cff_fallback_fini (cairo_cff_subset_t *subset)
    2265                 : {
    2266               0 :     free (subset->ps_name);
    2267               0 :     free (subset->widths);
    2268               0 :     free (subset->data);
    2269               0 : }
    2270                 : 
    2271                 : #endif /* CAIRO_HAS_FONT_SUBSET */

Generated by: LCOV version 1.7