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

       1                 : /* cairo - a vector graphics library with display and print output
       2                 :  *
       3                 :  * Copyright © 2006 Red Hat, Inc
       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 Red Hat, Inc.
      31                 :  *
      32                 :  * Contributor(s):
      33                 :  *      Kristian Høgsberg <krh@redhat.com>
      34                 :  */
      35                 : 
      36                 : /*
      37                 :  * Useful links:
      38                 :  * http://partners.adobe.com/public/developer/en/font/T1_SPEC.PDF
      39                 :  */
      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-type1-private.h"
      49                 : #include "cairo-scaled-font-subsets-private.h"
      50                 : #include "cairo-output-stream-private.h"
      51                 : 
      52                 : /* XXX: Eventually, we need to handle other font backends */
      53                 : #if CAIRO_HAS_FT_FONT
      54                 : 
      55                 : #include "cairo-ft-private.h"
      56                 : 
      57                 : #include <ft2build.h>
      58                 : #include FT_FREETYPE_H
      59                 : #include FT_OUTLINE_H
      60                 : #include FT_TYPE1_TABLES_H
      61                 : 
      62                 : #include <ctype.h>
      63                 : 
      64                 : typedef struct _cairo_type1_font_subset {
      65                 :     cairo_scaled_font_subset_t *scaled_font_subset;
      66                 : 
      67                 :     struct {
      68                 :         cairo_unscaled_font_t *unscaled_font;
      69                 :         unsigned int font_id;
      70                 :         char *base_font;
      71                 :         unsigned int num_glyphs;
      72                 :         double x_min, y_min, x_max, y_max;
      73                 :         double ascent, descent;
      74                 : 
      75                 :         const char    *data;
      76                 :         unsigned long  header_size;
      77                 :         unsigned long  data_size;
      78                 :         unsigned long  trailer_size;
      79                 :     } base;
      80                 : 
      81                 :     FT_Face face;
      82                 :     int num_glyphs;
      83                 : 
      84                 :     struct {
      85                 :         int subset_index;
      86                 :         double width;
      87                 :         char *name;
      88                 :     } *glyphs;
      89                 : 
      90                 :     cairo_output_stream_t *output;
      91                 :     cairo_array_t contents;
      92                 : 
      93                 :     const char *rd, *nd;
      94                 : 
      95                 :     char *type1_data;
      96                 :     unsigned int type1_length;
      97                 :     char *type1_end;
      98                 : 
      99                 :     char *header_segment;
     100                 :     int header_segment_size;
     101                 :     char *eexec_segment;
     102                 :     int eexec_segment_size;
     103                 :     cairo_bool_t eexec_segment_is_ascii;
     104                 : 
     105                 :     char *cleartext;
     106                 :     char *cleartext_end;
     107                 : 
     108                 :     int header_size;
     109                 : 
     110                 :     unsigned short eexec_key;
     111                 :     cairo_bool_t hex_encode;
     112                 :     int hex_column;
     113                 : } cairo_type1_font_subset_t;
     114                 : 
     115                 : 
     116                 : static cairo_status_t
     117               0 : _cairo_type1_font_subset_init (cairo_type1_font_subset_t  *font,
     118                 :                                cairo_unscaled_font_t      *unscaled_font,
     119                 :                                cairo_bool_t                hex_encode)
     120                 : {
     121                 :     cairo_ft_unscaled_font_t *ft_unscaled_font;
     122                 :     cairo_status_t status;
     123                 :     FT_Face face;
     124                 :     PS_FontInfoRec font_info;
     125                 :     int i, j;
     126                 : 
     127               0 :     ft_unscaled_font = (cairo_ft_unscaled_font_t *) unscaled_font;
     128                 : 
     129               0 :     face = _cairo_ft_unscaled_font_lock_face (ft_unscaled_font);
     130               0 :     if (unlikely (face == NULL))
     131               0 :         return _cairo_error (CAIRO_STATUS_NO_MEMORY);
     132                 : 
     133               0 :     if (FT_Get_PS_Font_Info(face, &font_info) != 0) {
     134               0 :         status = CAIRO_INT_STATUS_UNSUPPORTED;
     135               0 :         goto fail1;
     136                 :     }
     137                 : 
     138                 :     /* OpenType/CFF fonts also have a PS_FontInfoRec */
     139                 : #if HAVE_FT_LOAD_SFNT_TABLE
     140               0 :     if (FT_IS_SFNT (face)) {
     141               0 :         status = CAIRO_INT_STATUS_UNSUPPORTED;
     142               0 :         goto fail1;
     143                 :     }
     144                 : #endif
     145                 : 
     146               0 :     memset (font, 0, sizeof (*font));
     147               0 :     font->base.unscaled_font = _cairo_unscaled_font_reference (unscaled_font);
     148               0 :     font->base.num_glyphs = face->num_glyphs;
     149               0 :     font->base.x_min = face->bbox.xMin / (double)face->units_per_EM;
     150               0 :     font->base.y_min = face->bbox.yMin / (double)face->units_per_EM;
     151               0 :     font->base.x_max = face->bbox.xMax / (double)face->units_per_EM;
     152               0 :     font->base.y_max = face->bbox.yMax / (double)face->units_per_EM;
     153               0 :     font->base.ascent = face->ascender / (double)face->units_per_EM;
     154               0 :     font->base.descent = face->descender / (double)face->units_per_EM;
     155                 : 
     156               0 :     if (face->family_name) {
     157               0 :         font->base.base_font = strdup (face->family_name);
     158               0 :         if (unlikely (font->base.base_font == NULL)) {
     159               0 :             status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
     160               0 :             goto fail2;
     161                 :         }
     162               0 :         for (i = 0, j = 0; font->base.base_font[j]; j++) {
     163               0 :             if (font->base.base_font[j] == ' ')
     164               0 :                 continue;
     165               0 :             font->base.base_font[i++] = font->base.base_font[j];
     166                 :         }
     167               0 :         font->base.base_font[i] = '\0';
     168                 :     }
     169                 : 
     170               0 :     font->glyphs = calloc (face->num_glyphs, sizeof font->glyphs[0]);
     171               0 :     if (unlikely (font->glyphs == NULL)) {
     172               0 :         status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
     173               0 :         goto fail3;
     174                 :     }
     175                 : 
     176               0 :     font->hex_encode = hex_encode;
     177               0 :     font->num_glyphs = 0;
     178               0 :     for (i = 0; i < face->num_glyphs; i++)
     179               0 :         font->glyphs[i].subset_index = -1;
     180                 : 
     181               0 :     _cairo_array_init (&font->contents, sizeof (char));
     182                 : 
     183               0 :     _cairo_ft_unscaled_font_unlock_face (ft_unscaled_font);
     184                 : 
     185               0 :     return CAIRO_STATUS_SUCCESS;
     186                 : 
     187                 :  fail3:
     188               0 :     if (font->base.base_font)
     189               0 :         free (font->base.base_font);
     190                 :  fail2:
     191               0 :     _cairo_unscaled_font_destroy (unscaled_font);
     192                 :  fail1:
     193               0 :     _cairo_ft_unscaled_font_unlock_face (ft_unscaled_font);
     194                 : 
     195               0 :     return status;
     196                 : }
     197                 : 
     198                 : static void
     199               0 : cairo_type1_font_subset_use_glyph (cairo_type1_font_subset_t *font, int glyph)
     200                 : {
     201               0 :     if (font->glyphs[glyph].subset_index >= 0)
     202               0 :         return;
     203                 : 
     204               0 :     font->glyphs[glyph].subset_index = font->num_glyphs++;
     205                 : }
     206                 : 
     207                 : static cairo_bool_t
     208               0 : is_ps_delimiter(int c)
     209                 : {
     210                 :     static const char delimiters[] = "()[]{}<>/% \t\r\n";
     211                 : 
     212               0 :     return strchr (delimiters, c) != NULL;
     213                 : }
     214                 : 
     215                 : static const char *
     216               0 : find_token (const char *buffer, const char *end, const char *token)
     217                 : {
     218                 :     int i, length;
     219                 :     /* FIXME: find substring really must be find_token */
     220                 : 
     221               0 :     if (buffer == NULL)
     222               0 :         return NULL;
     223                 : 
     224               0 :     length = strlen (token);
     225               0 :     for (i = 0; buffer + i < end - length + 1; i++)
     226               0 :         if (memcmp (buffer + i, token, length) == 0)
     227               0 :             if ((i == 0 || token[0] == '/' || is_ps_delimiter(buffer[i - 1])) &&
     228               0 :                 (buffer + i == end - length || is_ps_delimiter(buffer[i + length])))
     229               0 :                 return buffer + i;
     230                 : 
     231               0 :     return NULL;
     232                 : }
     233                 : 
     234                 : static cairo_status_t
     235               0 : cairo_type1_font_subset_find_segments (cairo_type1_font_subset_t *font)
     236                 : {
     237                 :     unsigned char *p;
     238                 :     const char *eexec_token;
     239                 :     int size, i;
     240                 : 
     241               0 :     p = (unsigned char *) font->type1_data;
     242               0 :     font->type1_end = font->type1_data + font->type1_length;
     243               0 :     if (p[0] == 0x80 && p[1] == 0x01) {
     244               0 :         font->header_segment_size =
     245               0 :             p[2] | (p[3] << 8) | (p[4] << 16) | (p[5] << 24);
     246               0 :         font->header_segment = (char *) p + 6;
     247                 : 
     248               0 :         p += 6 + font->header_segment_size;
     249               0 :         font->eexec_segment_size =
     250               0 :             p[2] | (p[3] << 8) | (p[4] << 16) | (p[5] << 24);
     251               0 :         font->eexec_segment = (char *) p + 6;
     252               0 :         font->eexec_segment_is_ascii = (p[1] == 1);
     253                 : 
     254               0 :         p += 6 + font->eexec_segment_size;
     255               0 :         while (p < (unsigned char *) (font->type1_end) && p[1] != 0x03) {
     256               0 :             size = p[2] | (p[3] << 8) | (p[4] << 16) | (p[5] << 24);
     257               0 :             p += 6 + size;
     258                 :         }
     259               0 :         font->type1_end = (char *) p;
     260                 :     } else {
     261               0 :         eexec_token = find_token ((char *) p, font->type1_end, "eexec");
     262               0 :         if (eexec_token == NULL)
     263               0 :             return CAIRO_INT_STATUS_UNSUPPORTED;
     264                 : 
     265               0 :         font->header_segment_size = eexec_token - (char *) p + strlen ("eexec\n");
     266               0 :         font->header_segment = (char *) p;
     267               0 :         font->eexec_segment_size = font->type1_length - font->header_segment_size;
     268               0 :         font->eexec_segment = (char *) p + font->header_segment_size;
     269               0 :         font->eexec_segment_is_ascii = TRUE;
     270               0 :         for (i = 0; i < 4; i++) {
     271               0 :             if (!isxdigit(font->eexec_segment[i]))
     272               0 :                 font->eexec_segment_is_ascii = FALSE;
     273                 :         }
     274                 :     }
     275                 : 
     276               0 :     return CAIRO_STATUS_SUCCESS;
     277                 : }
     278                 : 
     279                 : /* Search for the definition of key and erase it by overwriting with spaces.
     280                 :  * This function is looks for definitions of the form:
     281                 :  *
     282                 :  * /key1 1234 def
     283                 :  * /key2 [12 34 56] def
     284                 :  *
     285                 :  * ie a key defined as an integer or array of integers.
     286                 :  *
     287                 :  */
     288                 : static void
     289               0 : cairo_type1_font_erase_dict_key (cairo_type1_font_subset_t *font,
     290                 :                                  const char *key)
     291                 : {
     292                 :     const char *start, *p, *segment_end;
     293                 : 
     294               0 :     segment_end = font->header_segment + font->header_segment_size;
     295                 : 
     296               0 :     start = font->header_segment;
     297                 :     do {
     298               0 :         start = find_token (start, segment_end, key);
     299               0 :         if (start) {
     300               0 :             p = start + strlen(key);
     301                 :             /* skip integers or array of integers */
     302               0 :             while (p < segment_end &&
     303               0 :                    (_cairo_isspace(*p) ||
     304               0 :                     _cairo_isdigit(*p) ||
     305               0 :                     *p == '[' ||
     306               0 :                     *p == ']'))
     307                 :             {
     308               0 :                 p++;
     309                 :             }
     310                 : 
     311               0 :             if (p + 3 < segment_end && memcmp(p, "def", 3) == 0) {
     312                 :                 /* erase definition of the key */
     313               0 :                 memset((char *) start, ' ', p + 3 - start);
     314                 :             }
     315               0 :             start += strlen(key);
     316                 :         }
     317               0 :     } while (start);
     318               0 : }
     319                 : 
     320                 : static cairo_status_t
     321               0 : cairo_type1_font_subset_write_header (cairo_type1_font_subset_t *font,
     322                 :                                          const char *name)
     323                 : {
     324                 :     const char *start, *end, *segment_end;
     325                 :     unsigned int i;
     326                 : 
     327                 :     /* FIXME:
     328                 :      * This function assumes that /FontName always appears
     329                 :      * before /Encoding. This appears to always be the case with Type1
     330                 :      * fonts.
     331                 :      *
     332                 :      * The more recently added code for removing the UniqueID and XUID
     333                 :      * keys can not make any assumptions about the position of the
     334                 :      * keys in the dictionary so it is implemented by overwriting the
     335                 :      * key definition with spaces before we start copying the font to
     336                 :      * the output.
     337                 :      *
     338                 :      * This code should be rewritten to not make any assumptions about
     339                 :      * the order of dictionary keys. This will allow UniqueID to be
     340                 :      * stripped out instead of leaving a bunch of spaces in the
     341                 :      * output.
     342                 :      */
     343               0 :     cairo_type1_font_erase_dict_key (font, "/UniqueID");
     344               0 :     cairo_type1_font_erase_dict_key (font, "/XUID");
     345                 : 
     346               0 :     segment_end = font->header_segment + font->header_segment_size;
     347                 : 
     348                 :     /* Type 1 fonts created by Fontforge have some PostScript code at
     349                 :      * the start of the font that skips the font if the printer has a
     350                 :      * cached copy of the font with the same unique id. This breaks
     351                 :      * our subsetted font so we disable it by searching for the
     352                 :      * PostScript operator "known" when used to check for the
     353                 :      * "/UniqueID" dictionary key. We append " pop false " after it to
     354                 :      * pop the result of this check off the stack and replace it with
     355                 :      * "false" to make the PostScript code think "/UniqueID" does not
     356                 :      * exist.
     357                 :      */
     358               0 :     end = font->header_segment;
     359               0 :     start = find_token (font->header_segment, segment_end, "/UniqueID");
     360               0 :     if (start) {
     361               0 :         start += 9;
     362               0 :         while (start < segment_end && _cairo_isspace (*start))
     363               0 :             start++;
     364               0 :         if (start + 5 < segment_end && memcmp(start, "known", 5) == 0) {
     365               0 :             _cairo_output_stream_write (font->output, font->header_segment,
     366               0 :                                         start + 5 - font->header_segment);
     367               0 :             _cairo_output_stream_printf (font->output, " pop false ");
     368               0 :             end = start + 5;
     369                 :         }
     370                 :     }
     371                 : 
     372               0 :     start = find_token (end, segment_end, "/FontName");
     373               0 :     if (start == NULL)
     374               0 :         return CAIRO_INT_STATUS_UNSUPPORTED;
     375                 : 
     376               0 :     _cairo_output_stream_write (font->output, end,
     377               0 :                                 start - end);
     378                 : 
     379               0 :     _cairo_output_stream_printf (font->output, "/FontName /%s def", name);
     380                 : 
     381               0 :     end = find_token (start, segment_end, "def");
     382               0 :     if (end == NULL)
     383               0 :         return CAIRO_INT_STATUS_UNSUPPORTED;
     384               0 :     end += 3;
     385                 : 
     386               0 :     start = find_token (end, segment_end, "/Encoding");
     387               0 :     if (start == NULL)
     388               0 :         return CAIRO_INT_STATUS_UNSUPPORTED;
     389               0 :     _cairo_output_stream_write (font->output, end, start - end);
     390                 : 
     391               0 :     _cairo_output_stream_printf (font->output,
     392                 :                                  "/Encoding 256 array\n"
     393                 :                                  "0 1 255 {1 index exch /.notdef put} for\n");
     394               0 :     for (i = 1; i < font->base.num_glyphs; i++) {
     395               0 :         if (font->glyphs[i].subset_index < 0)
     396               0 :             continue;
     397               0 :         _cairo_output_stream_printf (font->output,
     398                 :                                      "dup %d /%s put\n",
     399               0 :                                      font->glyphs[i].subset_index,
     400               0 :                                      font->glyphs[i].name);
     401                 :     }
     402               0 :     _cairo_output_stream_printf (font->output, "readonly def");
     403                 : 
     404               0 :     end = find_token (start, segment_end, "def");
     405               0 :     if (end == NULL)
     406               0 :         return CAIRO_INT_STATUS_UNSUPPORTED;
     407               0 :     end += 3;
     408                 : 
     409               0 :     _cairo_output_stream_write (font->output, end, segment_end - end);
     410                 : 
     411               0 :     return font->output->status;
     412                 : }
     413                 : 
     414                 : static int
     415               0 : hex_to_int (int ch)
     416                 : {
     417               0 :     if (ch <= '9')
     418               0 :         return ch - '0';
     419               0 :     else if (ch <= 'F')
     420               0 :         return ch - 'A' + 10;
     421                 :     else
     422               0 :         return ch - 'a' + 10;
     423                 : }
     424                 : 
     425                 : static cairo_status_t
     426               0 : cairo_type1_font_subset_write_encrypted (cairo_type1_font_subset_t *font,
     427                 :                                          const char *data, unsigned int length)
     428                 : {
     429                 :     const unsigned char *in, *end;
     430                 :     int c, p;
     431                 :     static const char hex_digits[16] = "0123456789abcdef";
     432                 :     char digits[3];
     433                 : 
     434               0 :     in = (const unsigned char *) data;
     435               0 :     end = (const unsigned char *) data + length;
     436               0 :     while (in < end) {
     437               0 :         p = *in++;
     438               0 :         c = p ^ (font->eexec_key >> 8);
     439               0 :         font->eexec_key = (c + font->eexec_key) * CAIRO_TYPE1_ENCRYPT_C1 + CAIRO_TYPE1_ENCRYPT_C2;
     440                 : 
     441               0 :         if (font->hex_encode) {
     442               0 :             digits[0] = hex_digits[c >> 4];
     443               0 :             digits[1] = hex_digits[c & 0x0f];
     444               0 :             digits[2] = '\n';
     445               0 :             font->hex_column += 2;
     446                 : 
     447               0 :             if (font->hex_column == 78) {
     448               0 :                 _cairo_output_stream_write (font->output, digits, 3);
     449               0 :                 font->hex_column = 0;
     450                 :             } else {
     451               0 :                 _cairo_output_stream_write (font->output, digits, 2);
     452                 :             }
     453                 :         } else {
     454               0 :             digits[0] = c;
     455               0 :             _cairo_output_stream_write (font->output, digits, 1);
     456                 :         }
     457                 :     }
     458                 : 
     459               0 :     return font->output->status;
     460                 : }
     461                 : 
     462                 : static cairo_status_t
     463               0 : cairo_type1_font_subset_decrypt_eexec_segment (cairo_type1_font_subset_t *font)
     464                 : {
     465               0 :     unsigned short r = CAIRO_TYPE1_PRIVATE_DICT_KEY;
     466                 :     unsigned char *in, *end;
     467                 :     char *out;
     468                 :     int c, p;
     469                 :     int i;
     470                 : 
     471               0 :     in = (unsigned char *) font->eexec_segment;
     472               0 :     end = (unsigned char *) in + font->eexec_segment_size;
     473                 : 
     474               0 :     font->cleartext = malloc (font->eexec_segment_size);
     475               0 :     if (unlikely (font->cleartext == NULL))
     476               0 :         return _cairo_error (CAIRO_STATUS_NO_MEMORY);
     477                 : 
     478               0 :     out = font->cleartext;
     479               0 :     while (in < end) {
     480               0 :         if (font->eexec_segment_is_ascii) {
     481               0 :             c = *in++;
     482               0 :             if (_cairo_isspace (c))
     483               0 :                 continue;
     484               0 :             c = (hex_to_int (c) << 4) | hex_to_int (*in++);
     485                 :         } else {
     486               0 :             c = *in++;
     487                 :         }
     488               0 :         p = c ^ (r >> 8);
     489               0 :         r = (c + r) * CAIRO_TYPE1_ENCRYPT_C1 + CAIRO_TYPE1_ENCRYPT_C2;
     490                 : 
     491               0 :         *out++ = p;
     492                 :     }
     493               0 :     font->cleartext_end = out;
     494                 : 
     495                 :     /* Overwrite random bytes with spaces.
     496                 :      *
     497                 :      * The first 4 bytes of the cleartext are the random bytes
     498                 :      * required by the encryption algorithm. When encrypting the
     499                 :      * cleartext, the first ciphertext byte must not be a white space
     500                 :      * character and the first 4 bytes must not be an ASCII Hex
     501                 :      * character. Some fonts do not check that their randomly chosen
     502                 :      * bytes results in ciphertext that complies with this
     503                 :      * restriction. This may cause problems for some PDF consumers. By
     504                 :      * replacing the random bytes with spaces, the first four bytes of
     505                 :      * ciphertext will always be 0xf9, 0x83, 0xef, 0x00 which complies
     506                 :      * with this restriction. Using spaces also means we don't have to
     507                 :      * skip over the random bytes when parsing the cleartext.
     508                 :      */
     509               0 :     for (i = 0; i < 4 && i < font->eexec_segment_size; i++)
     510               0 :         font->cleartext[i] = ' ';
     511                 : 
     512               0 :     return CAIRO_STATUS_SUCCESS;
     513                 : }
     514                 : 
     515                 : static const char *
     516               0 : skip_token (const char *p, const char *end)
     517                 : {
     518               0 :     while (p < end && _cairo_isspace(*p))
     519               0 :         p++;
     520                 : 
     521               0 :     while (p < end && !_cairo_isspace(*p))
     522               0 :         p++;
     523                 : 
     524               0 :     if (p == end)
     525               0 :         return NULL;
     526                 : 
     527               0 :     return p;
     528                 : }
     529                 : 
     530                 : static int
     531               0 : cairo_type1_font_subset_lookup_glyph (cairo_type1_font_subset_t *font,
     532                 :                                       const char *glyph_name, int length)
     533                 : {
     534                 :     unsigned int i;
     535                 : 
     536               0 :     for (i = 0; i < font->base.num_glyphs; i++) {
     537               0 :         if (font->glyphs[i].name &&
     538               0 :             strncmp (font->glyphs[i].name, glyph_name, length) == 0 &&
     539               0 :             font->glyphs[i].name[length] == '\0')
     540               0 :             return i;
     541                 :     }
     542                 : 
     543               0 :     return -1;
     544                 : }
     545                 : 
     546                 : static cairo_status_t
     547               0 : cairo_type1_font_subset_get_glyph_names_and_widths (cairo_type1_font_subset_t *font)
     548                 : {
     549                 :     unsigned int i;
     550                 :     char buffer[256];
     551                 :     FT_Error error;
     552                 : 
     553                 :     /* Get glyph names and width using the freetype API */
     554               0 :     for (i = 0; i < font->base.num_glyphs; i++) {
     555               0 :         if (font->glyphs[i].name != NULL)
     556               0 :             continue;
     557                 : 
     558               0 :         error = FT_Load_Glyph (font->face, i,
     559                 :                                FT_LOAD_NO_SCALE | FT_LOAD_NO_HINTING |
     560                 :                                FT_LOAD_NO_BITMAP | FT_LOAD_IGNORE_TRANSFORM);
     561               0 :         if (error != FT_Err_Ok) {
     562                 :             /* propagate fatal errors from FreeType */
     563               0 :             if (error == FT_Err_Out_Of_Memory)
     564               0 :                 return _cairo_error (CAIRO_STATUS_NO_MEMORY);
     565                 : 
     566               0 :             return CAIRO_INT_STATUS_UNSUPPORTED;
     567                 :         }
     568                 : 
     569               0 :         font->glyphs[i].width = font->face->glyph->metrics.horiAdvance / (double)font->face->units_per_EM;
     570                 : 
     571               0 :         error = FT_Get_Glyph_Name(font->face, i, buffer, sizeof buffer);
     572               0 :         if (error != FT_Err_Ok) {
     573                 :             /* propagate fatal errors from FreeType */
     574               0 :             if (error == FT_Err_Out_Of_Memory)
     575               0 :                 return _cairo_error (CAIRO_STATUS_NO_MEMORY);
     576                 : 
     577               0 :             return CAIRO_INT_STATUS_UNSUPPORTED;
     578                 :         }
     579                 : 
     580               0 :         font->glyphs[i].name = strdup (buffer);
     581               0 :         if (unlikely (font->glyphs[i].name == NULL))
     582               0 :             return _cairo_error (CAIRO_STATUS_NO_MEMORY);
     583                 :     }
     584                 : 
     585               0 :     return CAIRO_STATUS_SUCCESS;
     586                 : }
     587                 : 
     588                 : static void
     589               0 : cairo_type1_font_subset_decrypt_charstring (const unsigned char *in, int size, unsigned char *out)
     590                 : {
     591               0 :     unsigned short r = CAIRO_TYPE1_CHARSTRING_KEY;
     592                 :     int c, p, i;
     593                 : 
     594               0 :     for (i = 0; i < size; i++) {
     595               0 :         c = *in++;
     596               0 :         p = c ^ (r >> 8);
     597               0 :         r = (c + r) * CAIRO_TYPE1_ENCRYPT_C1 + CAIRO_TYPE1_ENCRYPT_C2;
     598               0 :         *out++ = p;
     599                 :     }
     600               0 : }
     601                 : 
     602                 : static const unsigned char *
     603               0 : cairo_type1_font_subset_decode_integer (const unsigned char *p, int *integer)
     604                 : {
     605               0 :     if (*p <= 246) {
     606               0 :         *integer = *p++ - 139;
     607               0 :     } else if (*p <= 250) {
     608               0 :         *integer = (p[0] - 247) * 256 + p[1] + 108;
     609               0 :         p += 2;
     610               0 :     } else if (*p <= 254) {
     611               0 :         *integer = -(p[0] - 251) * 256 - p[1] - 108;
     612               0 :         p += 2;
     613                 :     } else {
     614               0 :         *integer = (p[1] << 24) | (p[2] << 16) | (p[3] << 8) | p[4];
     615               0 :         p += 5;
     616                 :     }
     617                 : 
     618               0 :     return p;
     619                 : }
     620                 : 
     621                 : #if 0
     622                 : /*
     623                 :  * The two tables that follow are generated using this perl code:
     624                 :  */
     625                 : 
     626                 : @encoding = (
     627                 :         /*   0 */
     628                 :         NULL,           NULL,           NULL,           NULL,
     629                 :         NULL,           NULL,           NULL,           NULL,
     630                 :         NULL,           NULL,           NULL,           NULL,
     631                 :         NULL,           NULL,           NULL,           NULL,
     632                 :         /*  16 */
     633                 :         NULL,           NULL,           NULL,           NULL,
     634                 :         NULL,           NULL,           NULL,           NULL,
     635                 :         NULL,           NULL,           NULL,           NULL,
     636                 :         NULL,           NULL,           NULL,           NULL,
     637                 :         /*  32 */
     638                 :         "space",      "exclam",     "quotedbl",   "numbersign",
     639                 :         "dollar",     "percent",    "ampersand",  "quoteright",
     640                 :         "parenleft",  "parenright", "asterisk",   "plus",
     641                 :         "comma",      "hyphen",     "period",     "slash",
     642                 :         /*  48 */
     643                 :         "zero",               "one",                "two",                "three",
     644                 :         "four",               "five",               "six",                "seven",
     645                 :         "eight",      "nine",               "colon",      "semicolon",
     646                 :         "less",               "equal",      "greater",    "question",
     647                 :         /*  64 */
     648                 :         "at",         "A",          "B",          "C",
     649                 :         "D",          "E",          "F",          "G",
     650                 :         "H",          "I",          "J",          "K",
     651                 :         "L",          "M",          "N",          "O",
     652                 :         /*  80 */
     653                 :         "P",          "Q",          "R",          "S",
     654                 :         "T",          "U",          "V",          "W",
     655                 :         "X",          "Y",          "Z",          "bracketleft",
     656                 :         "backslash",  "bracketright",       "asciicircum",        "underscore",
     657                 :         /*  96 */
     658                 :         "quoteleft",  "a",          "b",          "c",
     659                 :         "d",          "e",          "f",          "g",
     660                 :         "h",          "i",          "j",          "k",
     661                 :         "l",          "m",          "n",          "o",
     662                 :         /* 112 */
     663                 :         "p",          "q",          "r",          "s",
     664                 :         "t",          "u",          "v",          "w",
     665                 :         "x",          "y",          "z",          "braceleft",
     666                 :         "bar",                "braceright", "asciitilde", NULL,
     667                 :         /* 128 */
     668                 :         NULL,           NULL,           NULL,           NULL,
     669                 :         NULL,           NULL,           NULL,           NULL,
     670                 :         NULL,           NULL,           NULL,           NULL,
     671                 :         NULL,           NULL,           NULL,           NULL,
     672                 :         /* 144 */
     673                 :         NULL,           NULL,           NULL,           NULL,
     674                 :         NULL,           NULL,           NULL,           NULL,
     675                 :         NULL,           NULL,           NULL,           NULL,
     676                 :         NULL,           NULL,           NULL,           NULL,
     677                 :         /* 160 */
     678                 :         NULL,           "exclamdown", "cent",               "sterling",
     679                 :         "fraction",   "yen",                "florin",     "section",
     680                 :         "currency",   "quotesingle",        "quotedblleft",       "guillemotleft",
     681                 :         "guilsinglleft","guilsinglright","fi",            "fl",
     682                 :         /* 176 */
     683                 :         NULL,           "endash",     "dagger",     "daggerdbl",
     684                 :         "periodcentered",NULL,                "paragraph",  "bullet",
     685                 :         "quotesinglbase","quotedblbase","quotedblright","guillemotright",
     686                 :         "ellipsis",   "perthousand",        NULL,           "questiondown",
     687                 :         /* 192 */
     688                 :         NULL,           "grave",      "acute",      "circumflex",
     689                 :         "tilde",      "macron",     "breve",      "dotaccent",
     690                 :         "dieresis",   NULL,           "ring",               "cedilla",
     691                 :         NULL,           "hungarumlaut",       "ogonek",     "caron",
     692                 :         /* 208 */
     693                 :         "emdash",     NULL,           NULL,           NULL,
     694                 :         NULL,           NULL,           NULL,           NULL,
     695                 :         NULL,           NULL,           NULL,           NULL,
     696                 :         NULL,           NULL,           NULL,           NULL,
     697                 :         /* 224 */
     698                 :         NULL,           "AE",         NULL,           "ordfeminine",
     699                 :         NULL,           NULL,           NULL,           NULL,
     700                 :         "Lslash",     "Oslash",     "OE",         "ordmasculine",
     701                 :         NULL,           NULL,           NULL,           NULL,
     702                 :         /* 240 */
     703                 :         NULL,           "ae",         NULL,           NULL,
     704                 :         NULL,           "dotlessi",   NULL,           NULL,
     705                 :         "lslash",     "oslash",     "oe",         "germandbls",
     706                 :         NULL,           NULL,           NULL,           NULL
     707                 :         );
     708                 : 
     709                 : print "static const char ps_standard_encoding_symbol[] = {\n";
     710                 : $s = qq( "\\0");
     711                 : for $sym (@encoding) {
     712                 :     if (! ($sym eq NULL)) {
     713                 :         $ss = qq( "$sym\\0");
     714                 :         if (length($s) + length($ss) > 78) {
     715                 :           print qq( $s\n);
     716                 :           $s = "";
     717                 :         }
     718                 :         $s .= $ss;
     719                 :     }
     720                 : }
     721                 : print qq( $s\n);
     722                 : print "};\n\n";
     723                 : print "static const int16_t ps_standard_encoding_offset[256] = {\n";
     724                 : $offset = 1;
     725                 : $s = qq();
     726                 : for $sym (@encoding) {
     727                 :     if (! ($sym eq NULL)) {
     728                 :         $ss = qq( $offset/*$sym*/,);
     729                 :         $offset += length($sym) + 1;
     730                 :     } else {
     731                 :         $ss = qq( 0,);
     732                 :     }
     733                 :     if (length($s) + length($ss) > 78) {
     734                 :       print qq( $s\n);
     735                 :       $s = "";
     736                 :     }
     737                 :     $s .= $ss;
     738                 : }
     739                 : print qq( $s\n);
     740                 : print "};\n";
     741                 : exit;
     742                 : #endif
     743                 : 
     744                 : static const char ps_standard_encoding_symbol[] = {
     745                 :   "\0" "space\0" "exclam\0" "quotedbl\0" "numbersign\0" "dollar\0" "percent\0"
     746                 :   "ampersand\0" "quoteright\0" "parenleft\0" "parenright\0" "asterisk\0"
     747                 :   "plus\0" "comma\0" "hyphen\0" "period\0" "slash\0" "zero\0" "one\0" "two\0"
     748                 :   "three\0" "four\0" "five\0" "six\0" "seven\0" "eight\0" "nine\0" "colon\0"
     749                 :   "semicolon\0" "less\0" "equal\0" "greater\0" "question\0" "at\0" "A\0" "B\0"
     750                 :   "C\0" "D\0" "E\0" "F\0" "G\0" "H\0" "I\0" "J\0" "K\0" "L\0" "M\0" "N\0" "O\0"
     751                 :   "P\0" "Q\0" "R\0" "S\0" "T\0" "U\0" "V\0" "W\0" "X\0" "Y\0" "Z\0"
     752                 :   "bracketleft\0" "backslash\0" "bracketright\0" "asciicircum\0" "underscore\0"
     753                 :   "quoteleft\0" "a\0" "b\0" "c\0" "d\0" "e\0" "f\0" "g\0" "h\0" "i\0" "j\0"
     754                 :   "k\0" "l\0" "m\0" "n\0" "o\0" "p\0" "q\0" "r\0" "s\0" "t\0" "u\0" "v\0" "w\0"
     755                 :   "x\0" "y\0" "z\0" "braceleft\0" "bar\0" "braceright\0" "asciitilde\0"
     756                 :   "exclamdown\0" "cent\0" "sterling\0" "fraction\0" "yen\0" "florin\0"
     757                 :   "section\0" "currency\0" "quotesingle\0" "quotedblleft\0" "guillemotleft\0"
     758                 :   "guilsinglleft\0" "guilsinglright\0" "fi\0" "fl\0" "endash\0" "dagger\0"
     759                 :   "daggerdbl\0" "periodcentered\0" "paragraph\0" "bullet\0" "quotesinglbase\0"
     760                 :   "quotedblbase\0" "quotedblright\0" "guillemotright\0" "ellipsis\0"
     761                 :   "perthousand\0" "questiondown\0" "grave\0" "acute\0" "circumflex\0" "tilde\0"
     762                 :   "macron\0" "breve\0" "dotaccent\0" "dieresis\0" "ring\0" "cedilla\0"
     763                 :   "hungarumlaut\0" "ogonek\0" "caron\0" "emdash\0" "AE\0" "ordfeminine\0"
     764                 :   "Lslash\0" "Oslash\0" "OE\0" "ordmasculine\0" "ae\0" "dotlessi\0" "lslash\0"
     765                 :   "oslash\0" "oe\0" "germandbls\0"
     766                 : };
     767                 : 
     768                 : static const int16_t ps_standard_encoding_offset[256] = {
     769                 :   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
     770                 :   0, 0, 0, 0, 0, 0, 1/*space*/, 7/*exclam*/, 14/*quotedbl*/, 23/*numbersign*/,
     771                 :   34/*dollar*/, 41/*percent*/, 49/*ampersand*/, 59/*quoteright*/,
     772                 :   70/*parenleft*/, 80/*parenright*/, 91/*asterisk*/, 100/*plus*/, 105/*comma*/,
     773                 :   111/*hyphen*/, 118/*period*/, 125/*slash*/, 131/*zero*/, 136/*one*/,
     774                 :   140/*two*/, 144/*three*/, 150/*four*/, 155/*five*/, 160/*six*/, 164/*seven*/,
     775                 :   170/*eight*/, 176/*nine*/, 181/*colon*/, 187/*semicolon*/, 197/*less*/,
     776                 :   202/*equal*/, 208/*greater*/, 216/*question*/, 225/*at*/, 228/*A*/, 230/*B*/,
     777                 :   232/*C*/, 234/*D*/, 236/*E*/, 238/*F*/, 240/*G*/, 242/*H*/, 244/*I*/,
     778                 :   246/*J*/, 248/*K*/, 250/*L*/, 252/*M*/, 254/*N*/, 256/*O*/, 258/*P*/,
     779                 :   260/*Q*/, 262/*R*/, 264/*S*/, 266/*T*/, 268/*U*/, 270/*V*/, 272/*W*/,
     780                 :   274/*X*/, 276/*Y*/, 278/*Z*/, 280/*bracketleft*/, 292/*backslash*/,
     781                 :   302/*bracketright*/, 315/*asciicircum*/, 327/*underscore*/, 338/*quoteleft*/,
     782                 :   348/*a*/, 350/*b*/, 352/*c*/, 354/*d*/, 356/*e*/, 358/*f*/, 360/*g*/,
     783                 :   362/*h*/, 364/*i*/, 366/*j*/, 368/*k*/, 370/*l*/, 372/*m*/, 374/*n*/,
     784                 :   376/*o*/, 378/*p*/, 380/*q*/, 382/*r*/, 384/*s*/, 386/*t*/, 388/*u*/,
     785                 :   390/*v*/, 392/*w*/, 394/*x*/, 396/*y*/, 398/*z*/, 400/*braceleft*/,
     786                 :   410/*bar*/, 414/*braceright*/, 425/*asciitilde*/, 0, 0, 0, 0, 0, 0, 0, 0, 0,
     787                 :   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
     788                 :   436/*exclamdown*/, 447/*cent*/, 452/*sterling*/, 461/*fraction*/, 470/*yen*/,
     789                 :   474/*florin*/, 481/*section*/, 489/*currency*/, 498/*quotesingle*/,
     790                 :   510/*quotedblleft*/, 523/*guillemotleft*/, 537/*guilsinglleft*/,
     791                 :   551/*guilsinglright*/, 566/*fi*/, 569/*fl*/, 0, 572/*endash*/, 579/*dagger*/,
     792                 :   586/*daggerdbl*/, 596/*periodcentered*/, 0, 611/*paragraph*/, 621/*bullet*/,
     793                 :   628/*quotesinglbase*/, 643/*quotedblbase*/, 656/*quotedblright*/,
     794                 :   670/*guillemotright*/, 685/*ellipsis*/, 694/*perthousand*/, 0,
     795                 :   706/*questiondown*/, 0, 719/*grave*/, 725/*acute*/, 731/*circumflex*/,
     796                 :   742/*tilde*/, 748/*macron*/, 755/*breve*/, 761/*dotaccent*/, 771/*dieresis*/,
     797                 :   0, 780/*ring*/, 785/*cedilla*/, 0, 793/*hungarumlaut*/, 806/*ogonek*/,
     798                 :   813/*caron*/, 819/*emdash*/, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
     799                 :   826/*AE*/, 0, 829/*ordfeminine*/, 0, 0, 0, 0, 841/*Lslash*/, 848/*Oslash*/,
     800                 :   855/*OE*/, 858/*ordmasculine*/, 0, 0, 0, 0, 0, 871/*ae*/, 0, 0, 0,
     801                 :   874/*dotlessi*/, 0, 0, 883/*lslash*/, 890/*oslash*/, 897/*oe*/,
     802                 :   900/*germandbls*/, 0, 0, 0, 0,
     803                 : };
     804                 : 
     805                 : #define ps_standard_encoding(index) ((index) ? ps_standard_encoding_symbol+ps_standard_encoding_offset[(index)] : NULL)
     806                 : 
     807                 : static cairo_status_t
     808               0 : use_standard_encoding_glyph (cairo_type1_font_subset_t *font, int index)
     809                 : {
     810                 :     const char *glyph_name;
     811                 : 
     812               0 :     if (index < 0 || index > 255)
     813               0 :         return CAIRO_STATUS_SUCCESS;
     814                 : 
     815               0 :     glyph_name = ps_standard_encoding(index);
     816               0 :     if (glyph_name == NULL)
     817               0 :         return CAIRO_STATUS_SUCCESS;
     818                 : 
     819               0 :     index = cairo_type1_font_subset_lookup_glyph (font,
     820                 :                                                   glyph_name,
     821               0 :                                                   strlen(glyph_name));
     822               0 :     if (index < 0)
     823               0 :         return CAIRO_INT_STATUS_UNSUPPORTED;
     824                 : 
     825               0 :     cairo_type1_font_subset_use_glyph (font, index);
     826                 : 
     827               0 :     return CAIRO_STATUS_SUCCESS;
     828                 : }
     829                 : 
     830                 : #define TYPE1_CHARSTRING_COMMAND_ESCAPE         (12)
     831                 : #define TYPE1_CHARSTRING_COMMAND_SEAC           (32 + 6)
     832                 : 
     833                 : static cairo_status_t
     834               0 : cairo_type1_font_subset_look_for_seac(cairo_type1_font_subset_t *font,
     835                 :                                       const char *name, int name_length,
     836                 :                                       const char *encrypted_charstring, int encrypted_charstring_length)
     837                 : {
     838                 :     cairo_status_t status;
     839                 :     unsigned char *charstring;
     840                 :     const unsigned char *end;
     841                 :     const unsigned char *p;
     842                 :     int stack[5], sp, value;
     843                 :     int command;
     844                 : 
     845               0 :     charstring = malloc (encrypted_charstring_length);
     846               0 :     if (unlikely (charstring == NULL))
     847               0 :         return _cairo_error (CAIRO_STATUS_NO_MEMORY);
     848                 : 
     849               0 :     cairo_type1_font_subset_decrypt_charstring ((const unsigned char *)
     850                 :                                                 encrypted_charstring,
     851                 :                                                 encrypted_charstring_length,
     852                 :                                                 charstring);
     853               0 :     end = charstring + encrypted_charstring_length;
     854                 : 
     855               0 :     p = charstring + 4;
     856               0 :     sp = 0;
     857                 : 
     858               0 :     while (p < end) {
     859               0 :         if (*p < 32) {
     860               0 :             command = *p++;
     861                 : 
     862               0 :             if (command == TYPE1_CHARSTRING_COMMAND_ESCAPE)
     863               0 :                 command = 32 + *p++;
     864                 : 
     865               0 :             switch (command) {
     866                 :             case TYPE1_CHARSTRING_COMMAND_SEAC:
     867                 :                 /* The seac command takes five integer arguments.  The
     868                 :                  * last two are glyph indices into the PS standard
     869                 :                  * encoding give the names of the glyphs that this
     870                 :                  * glyph is composed from.  All we need to do is to
     871                 :                  * make sure those glyphs are present in the subset
     872                 :                  * under their standard names. */
     873               0 :                 status = use_standard_encoding_glyph (font, stack[3]);
     874               0 :                 if (unlikely (status))
     875               0 :                     return status;
     876                 : 
     877               0 :                 status = use_standard_encoding_glyph (font, stack[4]);
     878               0 :                 if (unlikely (status))
     879               0 :                     return status;
     880                 : 
     881               0 :                 sp = 0;
     882               0 :                 break;
     883                 : 
     884                 :             default:
     885               0 :                 sp = 0;
     886               0 :                 break;
     887                 :             }
     888                 :         } else {
     889                 :             /* integer argument */
     890               0 :             p = cairo_type1_font_subset_decode_integer (p, &value);
     891               0 :             if (sp < 5)
     892               0 :                 stack[sp++] = value;
     893                 :         }
     894                 :     }
     895                 : 
     896               0 :     free (charstring);
     897                 : 
     898               0 :     return CAIRO_STATUS_SUCCESS;
     899                 : }
     900                 : 
     901                 : static cairo_status_t
     902               0 : write_used_glyphs (cairo_type1_font_subset_t *font,
     903                 :                    const char *name, int name_length,
     904                 :                    const char *charstring, int charstring_length)
     905                 : {
     906                 :     cairo_status_t status;
     907                 :     char buffer[256];
     908                 :     int length;
     909                 : 
     910               0 :     length = snprintf (buffer, sizeof buffer,
     911                 :                        "/%.*s %d %s ",
     912                 :                        name_length, name, charstring_length, font->rd);
     913               0 :     status = cairo_type1_font_subset_write_encrypted (font, buffer, length);
     914               0 :     if (unlikely (status))
     915               0 :         return status;
     916                 : 
     917               0 :     status = cairo_type1_font_subset_write_encrypted (font,
     918                 :                                                       charstring,
     919                 :                                                       charstring_length);
     920               0 :     if (unlikely (status))
     921               0 :         return status;
     922                 : 
     923               0 :     length = snprintf (buffer, sizeof buffer, "%s\n", font->nd);
     924               0 :     status = cairo_type1_font_subset_write_encrypted (font, buffer, length);
     925               0 :     if (unlikely (status))
     926               0 :         return status;
     927                 : 
     928               0 :     return CAIRO_STATUS_SUCCESS;
     929                 : }
     930                 : 
     931                 : typedef cairo_status_t (*glyph_func_t) (cairo_type1_font_subset_t *font,
     932                 :                                         const char *name, int name_length,
     933                 :                                         const char *charstring, int charstring_length);
     934                 : 
     935                 : static cairo_status_t
     936               0 : cairo_type1_font_subset_for_each_glyph (cairo_type1_font_subset_t *font,
     937                 :                                         const char *dict_start,
     938                 :                                         const char *dict_end,
     939                 :                                         glyph_func_t func,
     940                 :                                         const char **dict_out)
     941                 : {
     942                 :     int charstring_length, name_length, glyph_index;
     943                 :     const char *p, *charstring, *name;
     944                 :     char *end;
     945                 : 
     946                 :     /* We're looking at '/' in the name of the first glyph.  The glyph
     947                 :      * definitions are on the form:
     948                 :      *
     949                 :      *   /name 23 RD <23 binary bytes> ND
     950                 :      *
     951                 :      * or alternatively using -| and |- instead of RD and ND.
     952                 :      *
     953                 :      * We parse the glyph name and see if it is in the subset.  If it
     954                 :      * is, we call the specified callback with the glyph name and
     955                 :      * glyph data, otherwise we just skip it.  We need to parse
     956                 :      * through a glyph definition; we can't just find the next '/',
     957                 :      * since the binary data could contain a '/'.
     958                 :      */
     959                 : 
     960               0 :     p = dict_start;
     961                 : 
     962               0 :     while (*p == '/') {
     963               0 :         name = p + 1;
     964               0 :         p = skip_token (p, dict_end);
     965               0 :         name_length = p - name;
     966                 : 
     967               0 :         charstring_length = strtol (p, &end, 10);
     968               0 :         if (p == end)
     969               0 :             return CAIRO_INT_STATUS_UNSUPPORTED;
     970                 : 
     971                 :         /* Skip past -| or RD to binary data.  There is exactly one space
     972                 :          * between the -| or RD token and the encrypted data, thus '+ 1'. */
     973               0 :         charstring = skip_token (end, dict_end) + 1;
     974                 : 
     975                 :         /* Skip binary data and |- or ND token. */
     976               0 :         p = skip_token (charstring + charstring_length, dict_end);
     977               0 :         while (p < dict_end && _cairo_isspace(*p))
     978               0 :             p++;
     979                 : 
     980                 :         /* In case any of the skip_token() calls above reached EOF, p will
     981                 :          * be equal to dict_end. */
     982               0 :         if (p == dict_end)
     983               0 :             return CAIRO_INT_STATUS_UNSUPPORTED;
     984                 : 
     985               0 :         glyph_index = cairo_type1_font_subset_lookup_glyph (font,
     986                 :                                                             name, name_length);
     987               0 :         if (font->glyphs[glyph_index].subset_index >= 0) {
     988               0 :             cairo_status_t status = func (font,
     989                 :                                           name, name_length,
     990                 :                                           charstring, charstring_length);
     991               0 :             if (unlikely (status))
     992               0 :                 return status;
     993                 :         }
     994                 :     }
     995                 : 
     996               0 :     *dict_out = p;
     997                 : 
     998               0 :     return CAIRO_STATUS_SUCCESS;
     999                 : }
    1000                 : 
    1001                 : 
    1002                 : static cairo_status_t
    1003               0 : cairo_type1_font_subset_write_private_dict (cairo_type1_font_subset_t *font,
    1004                 :                                             const char                *name)
    1005                 : {
    1006                 :     cairo_status_t status;
    1007                 :     const char *p, *charstrings, *dict_start;
    1008                 :     const char *closefile_token;
    1009                 :     char buffer[32], *glyph_count_end;
    1010                 :     int num_charstrings, length;
    1011                 : 
    1012                 :     /* The private dict holds hint information, common subroutines and
    1013                 :      * the actual glyph definitions (charstrings).
    1014                 :      *
    1015                 :      * FIXME: update this comment.
    1016                 :      *
    1017                 :      * What we do here is scan directly the /CharString token, which
    1018                 :      * marks the beginning of the glyph definitions.  Then we parse
    1019                 :      * through the glyph definitions and weed out the glyphs not in
    1020                 :      * our subset.  Everything else before and after the glyph
    1021                 :      * definitions is copied verbatim to the output.  It might be
    1022                 :      * worthwile to figure out which of the common subroutines are
    1023                 :      * used by the glyphs in the subset and get rid of the rest. */
    1024                 : 
    1025                 :     /* FIXME: The /Subrs array contains binary data and could
    1026                 :      * conceivably have "/CharStrings" in it, so we might need to skip
    1027                 :      * this more cleverly. */
    1028               0 :     charstrings = find_token (font->cleartext, font->cleartext_end, "/CharStrings");
    1029               0 :     if (charstrings == NULL)
    1030               0 :         return CAIRO_INT_STATUS_UNSUPPORTED;
    1031                 : 
    1032                 :     /* Scan past /CharStrings and the integer following it. */
    1033               0 :     p = charstrings + strlen ("/CharStrings");
    1034               0 :     num_charstrings = strtol (p, &glyph_count_end, 10);
    1035               0 :     if (p == glyph_count_end)
    1036               0 :         return CAIRO_INT_STATUS_UNSUPPORTED;
    1037                 : 
    1038                 :     /* Look for a '/' which marks the beginning of the first glyph
    1039                 :      * definition. */
    1040               0 :     for (p = glyph_count_end; p < font->cleartext_end; p++)
    1041               0 :         if (*p == '/')
    1042               0 :             break;
    1043               0 :     if (p == font->cleartext_end)
    1044               0 :         return CAIRO_INT_STATUS_UNSUPPORTED;
    1045               0 :     dict_start = p;
    1046                 : 
    1047               0 :     status = cairo_type1_font_subset_get_glyph_names_and_widths (font);
    1048               0 :     if (unlikely (status))
    1049               0 :         return status;
    1050                 : 
    1051                 :     /* Now that we have the private dictionary broken down in
    1052                 :      * sections, do the first pass through the glyph definitions to
    1053                 :      * figure out which subrs and othersubrs are use and which extra
    1054                 :      * glyphs may be required by the seac operator. */
    1055               0 :     status = cairo_type1_font_subset_for_each_glyph (font,
    1056                 :                                                      dict_start,
    1057               0 :                                                      font->cleartext_end,
    1058                 :                                                      cairo_type1_font_subset_look_for_seac,
    1059                 :                                                      &p);
    1060               0 :     if (unlikely (status))
    1061               0 :         return status;
    1062                 : 
    1063               0 :     closefile_token = find_token (p, font->cleartext_end, "closefile");
    1064               0 :     if (closefile_token == NULL)
    1065               0 :         return CAIRO_INT_STATUS_UNSUPPORTED;
    1066                 : 
    1067               0 :     status = cairo_type1_font_subset_get_glyph_names_and_widths (font);
    1068               0 :     if (unlikely (status))
    1069               0 :         return status;
    1070                 : 
    1071                 :     /* We're ready to start outputting. First write the header,
    1072                 :      * i.e. the public part of the font dict.*/
    1073               0 :     status = cairo_type1_font_subset_write_header (font, name);
    1074               0 :     if (unlikely (status))
    1075               0 :         return status;
    1076                 : 
    1077               0 :     font->base.header_size = _cairo_output_stream_get_position (font->output);
    1078                 : 
    1079                 : 
    1080                 :     /* Start outputting the private dict.  First output everything up
    1081                 :      * to the /CharStrings token. */
    1082               0 :     status = cairo_type1_font_subset_write_encrypted (font, font->cleartext,
    1083               0 :                                                  charstrings - font->cleartext);
    1084               0 :     if (unlikely (status))
    1085               0 :         return status;
    1086                 : 
    1087                 :     /* Write out new charstring count */
    1088               0 :     length = snprintf (buffer, sizeof buffer,
    1089                 :                        "/CharStrings %d", font->num_glyphs);
    1090               0 :     status = cairo_type1_font_subset_write_encrypted (font, buffer, length);
    1091               0 :     if (unlikely (status))
    1092               0 :         return status;
    1093                 : 
    1094                 :     /* Write out text between the charstring count and the first
    1095                 :      * charstring definition */
    1096               0 :     status = cairo_type1_font_subset_write_encrypted (font, glyph_count_end,
    1097               0 :                                                   dict_start - glyph_count_end);
    1098               0 :     if (unlikely (status))
    1099               0 :         return status;
    1100                 : 
    1101                 :     /* Write out the charstring definitions for each of the glyphs in
    1102                 :      * the subset. */
    1103               0 :     status = cairo_type1_font_subset_for_each_glyph (font,
    1104                 :                                                      dict_start,
    1105               0 :                                                      font->cleartext_end,
    1106                 :                                                      write_used_glyphs,
    1107                 :                                                      &p);
    1108               0 :     if (unlikely (status))
    1109               0 :         return status;
    1110                 : 
    1111                 :     /* Output what's left between the end of the glyph definitions and
    1112                 :      * the end of the private dict to the output. */
    1113               0 :     status = cairo_type1_font_subset_write_encrypted (font, p,
    1114               0 :                                 closefile_token - p + strlen ("closefile") + 1);
    1115               0 :     if (unlikely (status))
    1116               0 :         return status;
    1117                 : 
    1118               0 :     if (font->hex_encode)
    1119               0 :         _cairo_output_stream_write (font->output, "\n", 1);
    1120                 : 
    1121               0 :     return CAIRO_STATUS_SUCCESS;
    1122                 : }
    1123                 : 
    1124                 : static cairo_status_t
    1125               0 : cairo_type1_font_subset_write_trailer(cairo_type1_font_subset_t *font)
    1126                 : {
    1127                 :     const char *cleartomark_token;
    1128                 :     int i;
    1129                 :     static const char zeros[65] =
    1130                 :         "0000000000000000000000000000000000000000000000000000000000000000\n";
    1131                 : 
    1132                 : 
    1133               0 :     for (i = 0; i < 8; i++)
    1134               0 :         _cairo_output_stream_write (font->output, zeros, sizeof zeros);
    1135                 : 
    1136               0 :     cleartomark_token = find_token (font->type1_data, font->type1_end, "cleartomark");
    1137               0 :     if (cleartomark_token) {
    1138                 :         /* Some fonts have conditional save/restore around the entire
    1139                 :          * font dict, so we need to retain whatever postscript code
    1140                 :          * that may come after 'cleartomark'. */
    1141                 : 
    1142               0 :         _cairo_output_stream_write (font->output, cleartomark_token,
    1143               0 :                                     font->type1_end - cleartomark_token);
    1144               0 :     } else if (!font->eexec_segment_is_ascii) {
    1145                 :         /* Fonts embedded in PDF may omit the fixed-content portion
    1146                 :          * that includes the 'cleartomark' operator. Type 1 in PDF is
    1147                 :          * always binary. */
    1148                 : 
    1149               0 :         _cairo_output_stream_printf (font->output, "cleartomark");
    1150                 :     } else {
    1151               0 :         return CAIRO_INT_STATUS_UNSUPPORTED;
    1152                 :     }
    1153                 : 
    1154                 :     /* some fonts do not have a newline at the end of the last line */
    1155               0 :     _cairo_output_stream_printf (font->output, "\n");
    1156                 : 
    1157               0 :     return CAIRO_STATUS_SUCCESS;
    1158                 : }
    1159                 : 
    1160                 : static cairo_status_t
    1161               0 : type1_font_write (void *closure, const unsigned char *data, unsigned int length)
    1162                 : {
    1163               0 :     cairo_type1_font_subset_t *font = closure;
    1164                 : 
    1165               0 :     return _cairo_array_append_multiple (&font->contents, data, length);
    1166                 : }
    1167                 : 
    1168                 : static cairo_status_t
    1169               0 : cairo_type1_font_subset_write (cairo_type1_font_subset_t *font,
    1170                 :                                const char *name)
    1171                 : {
    1172                 :     cairo_status_t status;
    1173                 : 
    1174               0 :     status = cairo_type1_font_subset_find_segments (font);
    1175               0 :     if (unlikely (status))
    1176               0 :         return status;
    1177                 : 
    1178               0 :     status = cairo_type1_font_subset_decrypt_eexec_segment (font);
    1179               0 :     if (unlikely (status))
    1180               0 :         return status;
    1181                 : 
    1182                 :     /* Determine which glyph definition delimiters to use. */
    1183               0 :     if (find_token (font->cleartext, font->cleartext_end, "/-|") != NULL) {
    1184               0 :         font->rd = "-|";
    1185               0 :         font->nd = "|-";
    1186               0 :     } else if (find_token (font->cleartext, font->cleartext_end, "/RD") != NULL) {
    1187               0 :         font->rd = "RD";
    1188               0 :         font->nd = "ND";
    1189                 :     } else {
    1190                 :         /* Don't know *what* kind of font this is... */
    1191               0 :         return CAIRO_INT_STATUS_UNSUPPORTED;
    1192                 :     }
    1193                 : 
    1194               0 :     font->eexec_key = CAIRO_TYPE1_PRIVATE_DICT_KEY;
    1195               0 :     font->hex_column = 0;
    1196                 : 
    1197               0 :     status = cairo_type1_font_subset_write_private_dict (font, name);
    1198               0 :     if (unlikely (status))
    1199               0 :         return status;
    1200                 : 
    1201               0 :     font->base.data_size = _cairo_output_stream_get_position (font->output) -
    1202               0 :         font->base.header_size;
    1203                 : 
    1204               0 :     status = cairo_type1_font_subset_write_trailer (font);
    1205               0 :     if (unlikely (status))
    1206               0 :         return status;
    1207                 : 
    1208               0 :     font->base.trailer_size =
    1209               0 :         _cairo_output_stream_get_position (font->output) -
    1210               0 :         font->base.header_size - font->base.data_size;
    1211                 : 
    1212               0 :     return CAIRO_STATUS_SUCCESS;
    1213                 : }
    1214                 : 
    1215                 : static cairo_status_t
    1216               0 : cairo_type1_font_subset_generate (void       *abstract_font,
    1217                 :                                   const char *name)
    1218                 : 
    1219                 : {
    1220               0 :     cairo_type1_font_subset_t *font = abstract_font;
    1221                 :     cairo_ft_unscaled_font_t *ft_unscaled_font;
    1222                 :     unsigned long ret;
    1223                 :     cairo_status_t status;
    1224                 : 
    1225               0 :     ft_unscaled_font = (cairo_ft_unscaled_font_t *) font->base.unscaled_font;
    1226               0 :     font->face = _cairo_ft_unscaled_font_lock_face (ft_unscaled_font);
    1227               0 :     if (unlikely (font->face == NULL))
    1228               0 :         return _cairo_error (CAIRO_STATUS_NO_MEMORY);
    1229                 : 
    1230               0 :     font->type1_length = font->face->stream->size;
    1231               0 :     font->type1_data = malloc (font->type1_length);
    1232               0 :     if (unlikely (font->type1_data == NULL)) {
    1233               0 :         status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
    1234               0 :         goto fail;
    1235                 :     }
    1236                 : 
    1237               0 :     if (font->face->stream->read != NULL) {
    1238                 :         /* Note that read() may be implemented as a macro, thanks POSIX!, so we
    1239                 :          * need to wrap the following usage in parentheses in order to
    1240                 :          * disambiguate it for the pre-processor - using the verbose function
    1241                 :          * pointer dereference for clarity.
    1242                 :          */
    1243               0 :         ret = (* font->face->stream->read) (font->face->stream, 0,
    1244               0 :                                             (unsigned char *) font->type1_data,
    1245               0 :                                             font->type1_length);
    1246               0 :         if (ret != font->type1_length) {
    1247               0 :             status = _cairo_error (CAIRO_STATUS_READ_ERROR);
    1248               0 :             goto fail;
    1249                 :         }
    1250                 :     } else {
    1251               0 :         memcpy (font->type1_data,
    1252               0 :                 font->face->stream->base, font->type1_length);
    1253                 :     }
    1254                 : 
    1255               0 :     status = _cairo_array_grow_by (&font->contents, 4096);
    1256               0 :     if (unlikely (status))
    1257               0 :         goto fail;
    1258                 : 
    1259               0 :     font->output = _cairo_output_stream_create (type1_font_write, NULL, font);
    1260               0 :     if (unlikely ((status = font->output->status)))
    1261               0 :         goto fail;
    1262                 : 
    1263               0 :     status = cairo_type1_font_subset_write (font, name);
    1264               0 :     if (unlikely (status))
    1265               0 :         goto fail;
    1266                 : 
    1267               0 :     font->base.data = _cairo_array_index (&font->contents, 0);
    1268                 : 
    1269                 :  fail:
    1270               0 :     _cairo_ft_unscaled_font_unlock_face (ft_unscaled_font);
    1271                 : 
    1272               0 :     return status;
    1273                 : }
    1274                 : 
    1275                 : static cairo_status_t
    1276               0 : _cairo_type1_font_subset_fini (cairo_type1_font_subset_t *font)
    1277                 : {
    1278               0 :     cairo_status_t status = CAIRO_STATUS_SUCCESS;
    1279                 :     unsigned int i;
    1280                 : 
    1281                 :     /* If the subset generation failed, some of the pointers below may
    1282                 :      * be NULL depending on at which point the error occurred. */
    1283                 : 
    1284               0 :     _cairo_array_fini (&font->contents);
    1285                 : 
    1286               0 :     free (font->type1_data);
    1287               0 :     if (font->glyphs != NULL) {
    1288               0 :         for (i = 0; i < font->base.num_glyphs; i++)
    1289               0 :             free (font->glyphs[i].name);
    1290                 :     }
    1291                 : 
    1292               0 :     _cairo_unscaled_font_destroy (font->base.unscaled_font);
    1293                 : 
    1294               0 :     if (font->output != NULL)
    1295               0 :         status = _cairo_output_stream_destroy (font->output);
    1296                 : 
    1297               0 :     if (font->base.base_font)
    1298               0 :         free (font->base.base_font);
    1299               0 :     free (font->glyphs);
    1300                 : 
    1301               0 :     return status;
    1302                 : }
    1303                 : 
    1304                 : cairo_status_t
    1305               0 : _cairo_type1_subset_init (cairo_type1_subset_t          *type1_subset,
    1306                 :                           const char                    *name,
    1307                 :                           cairo_scaled_font_subset_t    *scaled_font_subset,
    1308                 :                           cairo_bool_t                   hex_encode)
    1309                 : {
    1310                 :     cairo_type1_font_subset_t font;
    1311                 :     cairo_status_t status, status_ignored;
    1312                 :     unsigned long parent_glyph, length;
    1313                 :     unsigned int i;
    1314                 :     cairo_unscaled_font_t *unscaled_font;
    1315                 :     char buf[30];
    1316                 : 
    1317                 :     /* XXX: Need to fix this to work with a general cairo_unscaled_font_t. */
    1318               0 :     if (!_cairo_scaled_font_is_ft (scaled_font_subset->scaled_font))
    1319               0 :         return CAIRO_INT_STATUS_UNSUPPORTED;
    1320                 : 
    1321               0 :     if (_cairo_ft_scaled_font_is_vertical (scaled_font_subset->scaled_font))
    1322               0 :         return CAIRO_INT_STATUS_UNSUPPORTED;
    1323                 : 
    1324               0 :     unscaled_font = _cairo_ft_scaled_font_get_unscaled_font (scaled_font_subset->scaled_font);
    1325                 : 
    1326               0 :     status = _cairo_type1_font_subset_init (&font, unscaled_font, hex_encode);
    1327               0 :     if (unlikely (status))
    1328               0 :         return status;
    1329                 : 
    1330               0 :     for (i = 0; i < scaled_font_subset->num_glyphs; i++) {
    1331               0 :         parent_glyph = scaled_font_subset->glyphs[i];
    1332               0 :         cairo_type1_font_subset_use_glyph (&font, parent_glyph);
    1333                 :     }
    1334                 : 
    1335               0 :     status = cairo_type1_font_subset_generate (&font, name);
    1336               0 :     if (unlikely (status))
    1337               0 :         goto fail1;
    1338                 : 
    1339               0 :     if (font.base.base_font) {
    1340               0 :         type1_subset->base_font = strdup (font.base.base_font);
    1341                 :     } else {
    1342               0 :         snprintf(buf, sizeof (buf), "CairoFont-%u-%u",
    1343                 :                  scaled_font_subset->font_id, scaled_font_subset->subset_id);
    1344               0 :         type1_subset->base_font = strdup (buf);
    1345                 :     }
    1346               0 :     if (unlikely (type1_subset->base_font == NULL))
    1347               0 :         goto fail1;
    1348                 : 
    1349               0 :     type1_subset->widths = calloc (sizeof (double), font.num_glyphs);
    1350               0 :     if (unlikely (type1_subset->widths == NULL))
    1351               0 :         goto fail2;
    1352               0 :     for (i = 0; i < font.base.num_glyphs; i++) {
    1353               0 :         if (font.glyphs[i].subset_index < 0)
    1354               0 :             continue;
    1355               0 :         type1_subset->widths[font.glyphs[i].subset_index] =
    1356               0 :             font.glyphs[i].width;
    1357                 :     }
    1358                 : 
    1359               0 :     type1_subset->x_min = font.base.x_min/1000.0;
    1360               0 :     type1_subset->y_min = font.base.y_min/1000.0;
    1361               0 :     type1_subset->x_max = font.base.x_max/1000.0;
    1362               0 :     type1_subset->y_max = font.base.y_max/1000.0;
    1363               0 :     type1_subset->ascent = font.base.ascent/1000.0;
    1364               0 :     type1_subset->descent = font.base.descent/1000.0;
    1365                 : 
    1366               0 :     length = font.base.header_size +
    1367               0 :              font.base.data_size +
    1368               0 :              font.base.trailer_size;
    1369               0 :     type1_subset->data = malloc (length);
    1370               0 :     if (unlikely (type1_subset->data == NULL))
    1371               0 :         goto fail3;
    1372                 : 
    1373               0 :     memcpy (type1_subset->data,
    1374               0 :             _cairo_array_index (&font.contents, 0), length);
    1375                 : 
    1376               0 :     type1_subset->header_length = font.base.header_size;
    1377               0 :     type1_subset->data_length = font.base.data_size;
    1378               0 :     type1_subset->trailer_length = font.base.trailer_size;
    1379                 : 
    1380               0 :     return _cairo_type1_font_subset_fini (&font);
    1381                 : 
    1382                 :  fail3:
    1383               0 :     free (type1_subset->widths);
    1384                 :  fail2:
    1385               0 :     free (type1_subset->base_font);
    1386                 :  fail1:
    1387               0 :     status_ignored = _cairo_type1_font_subset_fini (&font);
    1388                 : 
    1389               0 :     return status;
    1390                 : }
    1391                 : 
    1392                 : void
    1393               0 : _cairo_type1_subset_fini (cairo_type1_subset_t *subset)
    1394                 : {
    1395               0 :     free (subset->base_font);
    1396               0 :     free (subset->widths);
    1397               0 :     free (subset->data);
    1398               0 : }
    1399                 : 
    1400                 : cairo_bool_t
    1401               0 : _cairo_type1_scaled_font_is_type1 (cairo_scaled_font_t *scaled_font)
    1402                 : {
    1403                 :     cairo_ft_unscaled_font_t *unscaled;
    1404                 :     FT_Face face;
    1405                 :     PS_FontInfoRec font_info;
    1406               0 :     cairo_bool_t is_type1 = FALSE;
    1407                 : 
    1408               0 :     if (!_cairo_scaled_font_is_ft (scaled_font))
    1409               0 :        return FALSE;
    1410               0 :     unscaled = (cairo_ft_unscaled_font_t *) _cairo_ft_scaled_font_get_unscaled_font (scaled_font);
    1411               0 :     face = _cairo_ft_unscaled_font_lock_face (unscaled);
    1412               0 :     if (!face)
    1413               0 :         return FALSE;
    1414                 : 
    1415               0 :     if (FT_Get_PS_Font_Info(face, &font_info) == 0)
    1416               0 :         is_type1 = TRUE;
    1417                 : 
    1418                 :     /* OpenType/CFF fonts also have a PS_FontInfoRec */
    1419                 : #if HAVE_FT_LOAD_SFNT_TABLE
    1420               0 :     if (FT_IS_SFNT (face))
    1421               0 :         is_type1 = FALSE;
    1422                 : #endif
    1423                 : 
    1424               0 :     _cairo_ft_unscaled_font_unlock_face (unscaled);
    1425                 : 
    1426               0 :     return is_type1;
    1427                 : }
    1428                 : 
    1429                 : #endif /* CAIRO_HAS_FT_FONT */
    1430                 : 
    1431                 : #endif /* CAIRO_HAS_FONT_SUBSET */

Generated by: LCOV version 1.7