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

          Line data    Source code
       1             : /* cairo - a vector graphics library with display and print output
       2             :  *
       3             :  * Copyright © 2006 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 :                 if (unlikely (sp < 5))
     874           0 :                     return CAIRO_INT_STATUS_UNSUPPORTED;
     875             : 
     876           0 :                 status = use_standard_encoding_glyph (font, stack[3]);
     877           0 :                 if (unlikely (status))
     878           0 :                     return status;
     879             : 
     880           0 :                 status = use_standard_encoding_glyph (font, stack[4]);
     881           0 :                 if (unlikely (status))
     882           0 :                     return status;
     883             : 
     884           0 :                 sp = 0;
     885           0 :                 break;
     886             : 
     887             :             default:
     888           0 :                 sp = 0;
     889           0 :                 break;
     890             :             }
     891             :         } else {
     892             :             /* integer argument */
     893           0 :             p = cairo_type1_font_subset_decode_integer (p, &value);
     894           0 :             if (sp < 5)
     895           0 :                 stack[sp++] = value;
     896             :         }
     897             :     }
     898             : 
     899           0 :     free (charstring);
     900             : 
     901           0 :     return CAIRO_STATUS_SUCCESS;
     902             : }
     903             : 
     904             : static cairo_status_t
     905           0 : write_used_glyphs (cairo_type1_font_subset_t *font,
     906             :                    const char *name, int name_length,
     907             :                    const char *charstring, int charstring_length)
     908             : {
     909             :     cairo_status_t status;
     910             :     char buffer[256];
     911             :     int length;
     912             : 
     913           0 :     length = snprintf (buffer, sizeof buffer,
     914             :                        "/%.*s %d %s ",
     915             :                        name_length, name, charstring_length, font->rd);
     916           0 :     status = cairo_type1_font_subset_write_encrypted (font, buffer, length);
     917           0 :     if (unlikely (status))
     918           0 :         return status;
     919             : 
     920           0 :     status = cairo_type1_font_subset_write_encrypted (font,
     921             :                                                       charstring,
     922             :                                                       charstring_length);
     923           0 :     if (unlikely (status))
     924           0 :         return status;
     925             : 
     926           0 :     length = snprintf (buffer, sizeof buffer, "%s\n", font->nd);
     927           0 :     status = cairo_type1_font_subset_write_encrypted (font, buffer, length);
     928           0 :     if (unlikely (status))
     929           0 :         return status;
     930             : 
     931           0 :     return CAIRO_STATUS_SUCCESS;
     932             : }
     933             : 
     934             : typedef cairo_status_t (*glyph_func_t) (cairo_type1_font_subset_t *font,
     935             :                                         const char *name, int name_length,
     936             :                                         const char *charstring, int charstring_length);
     937             : 
     938             : static cairo_status_t
     939           0 : cairo_type1_font_subset_for_each_glyph (cairo_type1_font_subset_t *font,
     940             :                                         const char *dict_start,
     941             :                                         const char *dict_end,
     942             :                                         glyph_func_t func,
     943             :                                         const char **dict_out)
     944             : {
     945             :     int charstring_length, name_length, glyph_index;
     946             :     const char *p, *charstring, *name;
     947             :     char *end;
     948             : 
     949             :     /* We're looking at '/' in the name of the first glyph.  The glyph
     950             :      * definitions are on the form:
     951             :      *
     952             :      *   /name 23 RD <23 binary bytes> ND
     953             :      *
     954             :      * or alternatively using -| and |- instead of RD and ND.
     955             :      *
     956             :      * We parse the glyph name and see if it is in the subset.  If it
     957             :      * is, we call the specified callback with the glyph name and
     958             :      * glyph data, otherwise we just skip it.  We need to parse
     959             :      * through a glyph definition; we can't just find the next '/',
     960             :      * since the binary data could contain a '/'.
     961             :      */
     962             : 
     963           0 :     p = dict_start;
     964             : 
     965           0 :     while (*p == '/') {
     966           0 :         name = p + 1;
     967           0 :         p = skip_token (p, dict_end);
     968           0 :         name_length = p - name;
     969             : 
     970           0 :         charstring_length = strtol (p, &end, 10);
     971           0 :         if (p == end)
     972           0 :             return CAIRO_INT_STATUS_UNSUPPORTED;
     973             : 
     974             :         /* Skip past -| or RD to binary data.  There is exactly one space
     975             :          * between the -| or RD token and the encrypted data, thus '+ 1'. */
     976           0 :         charstring = skip_token (end, dict_end) + 1;
     977             : 
     978             :         /* Skip binary data and |- or ND token. */
     979           0 :         p = skip_token (charstring + charstring_length, dict_end);
     980           0 :         while (p < dict_end && _cairo_isspace(*p))
     981           0 :             p++;
     982             : 
     983             :         /* In case any of the skip_token() calls above reached EOF, p will
     984             :          * be equal to dict_end. */
     985           0 :         if (p == dict_end)
     986           0 :             return CAIRO_INT_STATUS_UNSUPPORTED;
     987             : 
     988           0 :         glyph_index = cairo_type1_font_subset_lookup_glyph (font,
     989             :                                                             name, name_length);
     990           0 :         if (font->glyphs[glyph_index].subset_index >= 0) {
     991           0 :             cairo_status_t status = func (font,
     992             :                                           name, name_length,
     993             :                                           charstring, charstring_length);
     994           0 :             if (unlikely (status))
     995           0 :                 return status;
     996             :         }
     997             :     }
     998             : 
     999           0 :     *dict_out = p;
    1000             : 
    1001           0 :     return CAIRO_STATUS_SUCCESS;
    1002             : }
    1003             : 
    1004             : 
    1005             : static cairo_status_t
    1006           0 : cairo_type1_font_subset_write_private_dict (cairo_type1_font_subset_t *font,
    1007             :                                             const char                *name)
    1008             : {
    1009             :     cairo_status_t status;
    1010             :     const char *p, *charstrings, *dict_start;
    1011             :     const char *closefile_token;
    1012             :     char buffer[32], *glyph_count_end;
    1013             :     int num_charstrings, length;
    1014             : 
    1015             :     /* The private dict holds hint information, common subroutines and
    1016             :      * the actual glyph definitions (charstrings).
    1017             :      *
    1018             :      * FIXME: update this comment.
    1019             :      *
    1020             :      * What we do here is scan directly the /CharString token, which
    1021             :      * marks the beginning of the glyph definitions.  Then we parse
    1022             :      * through the glyph definitions and weed out the glyphs not in
    1023             :      * our subset.  Everything else before and after the glyph
    1024             :      * definitions is copied verbatim to the output.  It might be
    1025             :      * worthwile to figure out which of the common subroutines are
    1026             :      * used by the glyphs in the subset and get rid of the rest. */
    1027             : 
    1028             :     /* FIXME: The /Subrs array contains binary data and could
    1029             :      * conceivably have "/CharStrings" in it, so we might need to skip
    1030             :      * this more cleverly. */
    1031           0 :     charstrings = find_token (font->cleartext, font->cleartext_end, "/CharStrings");
    1032           0 :     if (charstrings == NULL)
    1033           0 :         return CAIRO_INT_STATUS_UNSUPPORTED;
    1034             : 
    1035             :     /* Scan past /CharStrings and the integer following it. */
    1036           0 :     p = charstrings + strlen ("/CharStrings");
    1037           0 :     num_charstrings = strtol (p, &glyph_count_end, 10);
    1038           0 :     if (p == glyph_count_end)
    1039           0 :         return CAIRO_INT_STATUS_UNSUPPORTED;
    1040             : 
    1041             :     /* Look for a '/' which marks the beginning of the first glyph
    1042             :      * definition. */
    1043           0 :     for (p = glyph_count_end; p < font->cleartext_end; p++)
    1044           0 :         if (*p == '/')
    1045           0 :             break;
    1046           0 :     if (p == font->cleartext_end)
    1047           0 :         return CAIRO_INT_STATUS_UNSUPPORTED;
    1048           0 :     dict_start = p;
    1049             : 
    1050           0 :     status = cairo_type1_font_subset_get_glyph_names_and_widths (font);
    1051           0 :     if (unlikely (status))
    1052           0 :         return status;
    1053             : 
    1054             :     /* Now that we have the private dictionary broken down in
    1055             :      * sections, do the first pass through the glyph definitions to
    1056             :      * figure out which subrs and othersubrs are use and which extra
    1057             :      * glyphs may be required by the seac operator. */
    1058           0 :     status = cairo_type1_font_subset_for_each_glyph (font,
    1059             :                                                      dict_start,
    1060           0 :                                                      font->cleartext_end,
    1061             :                                                      cairo_type1_font_subset_look_for_seac,
    1062             :                                                      &p);
    1063           0 :     if (unlikely (status))
    1064           0 :         return status;
    1065             : 
    1066           0 :     closefile_token = find_token (p, font->cleartext_end, "closefile");
    1067           0 :     if (closefile_token == NULL)
    1068           0 :         return CAIRO_INT_STATUS_UNSUPPORTED;
    1069             : 
    1070           0 :     status = cairo_type1_font_subset_get_glyph_names_and_widths (font);
    1071           0 :     if (unlikely (status))
    1072           0 :         return status;
    1073             : 
    1074             :     /* We're ready to start outputting. First write the header,
    1075             :      * i.e. the public part of the font dict.*/
    1076           0 :     status = cairo_type1_font_subset_write_header (font, name);
    1077           0 :     if (unlikely (status))
    1078           0 :         return status;
    1079             : 
    1080           0 :     font->base.header_size = _cairo_output_stream_get_position (font->output);
    1081             : 
    1082             : 
    1083             :     /* Start outputting the private dict.  First output everything up
    1084             :      * to the /CharStrings token. */
    1085           0 :     status = cairo_type1_font_subset_write_encrypted (font, font->cleartext,
    1086           0 :                                                  charstrings - font->cleartext);
    1087           0 :     if (unlikely (status))
    1088           0 :         return status;
    1089             : 
    1090             :     /* Write out new charstring count */
    1091           0 :     length = snprintf (buffer, sizeof buffer,
    1092             :                        "/CharStrings %d", font->num_glyphs);
    1093           0 :     status = cairo_type1_font_subset_write_encrypted (font, buffer, length);
    1094           0 :     if (unlikely (status))
    1095           0 :         return status;
    1096             : 
    1097             :     /* Write out text between the charstring count and the first
    1098             :      * charstring definition */
    1099           0 :     status = cairo_type1_font_subset_write_encrypted (font, glyph_count_end,
    1100           0 :                                                   dict_start - glyph_count_end);
    1101           0 :     if (unlikely (status))
    1102           0 :         return status;
    1103             : 
    1104             :     /* Write out the charstring definitions for each of the glyphs in
    1105             :      * the subset. */
    1106           0 :     status = cairo_type1_font_subset_for_each_glyph (font,
    1107             :                                                      dict_start,
    1108           0 :                                                      font->cleartext_end,
    1109             :                                                      write_used_glyphs,
    1110             :                                                      &p);
    1111           0 :     if (unlikely (status))
    1112           0 :         return status;
    1113             : 
    1114             :     /* Output what's left between the end of the glyph definitions and
    1115             :      * the end of the private dict to the output. */
    1116           0 :     status = cairo_type1_font_subset_write_encrypted (font, p,
    1117           0 :                                 closefile_token - p + strlen ("closefile") + 1);
    1118           0 :     if (unlikely (status))
    1119           0 :         return status;
    1120             : 
    1121           0 :     if (font->hex_encode)
    1122           0 :         _cairo_output_stream_write (font->output, "\n", 1);
    1123             : 
    1124           0 :     return CAIRO_STATUS_SUCCESS;
    1125             : }
    1126             : 
    1127             : static cairo_status_t
    1128           0 : cairo_type1_font_subset_write_trailer(cairo_type1_font_subset_t *font)
    1129             : {
    1130             :     const char *cleartomark_token;
    1131             :     int i;
    1132             :     static const char zeros[65] =
    1133             :         "0000000000000000000000000000000000000000000000000000000000000000\n";
    1134             : 
    1135             : 
    1136           0 :     for (i = 0; i < 8; i++)
    1137           0 :         _cairo_output_stream_write (font->output, zeros, sizeof zeros);
    1138             : 
    1139           0 :     cleartomark_token = find_token (font->type1_data, font->type1_end, "cleartomark");
    1140           0 :     if (cleartomark_token) {
    1141             :         /* Some fonts have conditional save/restore around the entire
    1142             :          * font dict, so we need to retain whatever postscript code
    1143             :          * that may come after 'cleartomark'. */
    1144             : 
    1145           0 :         _cairo_output_stream_write (font->output, cleartomark_token,
    1146           0 :                                     font->type1_end - cleartomark_token);
    1147           0 :     } else if (!font->eexec_segment_is_ascii) {
    1148             :         /* Fonts embedded in PDF may omit the fixed-content portion
    1149             :          * that includes the 'cleartomark' operator. Type 1 in PDF is
    1150             :          * always binary. */
    1151             : 
    1152           0 :         _cairo_output_stream_printf (font->output, "cleartomark");
    1153             :     } else {
    1154           0 :         return CAIRO_INT_STATUS_UNSUPPORTED;
    1155             :     }
    1156             : 
    1157             :     /* some fonts do not have a newline at the end of the last line */
    1158           0 :     _cairo_output_stream_printf (font->output, "\n");
    1159             : 
    1160           0 :     return CAIRO_STATUS_SUCCESS;
    1161             : }
    1162             : 
    1163             : static cairo_status_t
    1164           0 : type1_font_write (void *closure, const unsigned char *data, unsigned int length)
    1165             : {
    1166           0 :     cairo_type1_font_subset_t *font = closure;
    1167             : 
    1168           0 :     return _cairo_array_append_multiple (&font->contents, data, length);
    1169             : }
    1170             : 
    1171             : static cairo_status_t
    1172           0 : cairo_type1_font_subset_write (cairo_type1_font_subset_t *font,
    1173             :                                const char *name)
    1174             : {
    1175             :     cairo_status_t status;
    1176             : 
    1177           0 :     status = cairo_type1_font_subset_find_segments (font);
    1178           0 :     if (unlikely (status))
    1179           0 :         return status;
    1180             : 
    1181           0 :     status = cairo_type1_font_subset_decrypt_eexec_segment (font);
    1182           0 :     if (unlikely (status))
    1183           0 :         return status;
    1184             : 
    1185             :     /* Determine which glyph definition delimiters to use. */
    1186           0 :     if (find_token (font->cleartext, font->cleartext_end, "/-|") != NULL) {
    1187           0 :         font->rd = "-|";
    1188           0 :         font->nd = "|-";
    1189           0 :     } else if (find_token (font->cleartext, font->cleartext_end, "/RD") != NULL) {
    1190           0 :         font->rd = "RD";
    1191           0 :         font->nd = "ND";
    1192             :     } else {
    1193             :         /* Don't know *what* kind of font this is... */
    1194           0 :         return CAIRO_INT_STATUS_UNSUPPORTED;
    1195             :     }
    1196             : 
    1197           0 :     font->eexec_key = CAIRO_TYPE1_PRIVATE_DICT_KEY;
    1198           0 :     font->hex_column = 0;
    1199             : 
    1200           0 :     status = cairo_type1_font_subset_write_private_dict (font, name);
    1201           0 :     if (unlikely (status))
    1202           0 :         return status;
    1203             : 
    1204           0 :     font->base.data_size = _cairo_output_stream_get_position (font->output) -
    1205           0 :         font->base.header_size;
    1206             : 
    1207           0 :     status = cairo_type1_font_subset_write_trailer (font);
    1208           0 :     if (unlikely (status))
    1209           0 :         return status;
    1210             : 
    1211           0 :     font->base.trailer_size =
    1212           0 :         _cairo_output_stream_get_position (font->output) -
    1213           0 :         font->base.header_size - font->base.data_size;
    1214             : 
    1215           0 :     return CAIRO_STATUS_SUCCESS;
    1216             : }
    1217             : 
    1218             : static cairo_status_t
    1219           0 : cairo_type1_font_subset_generate (void       *abstract_font,
    1220             :                                   const char *name)
    1221             : 
    1222             : {
    1223           0 :     cairo_type1_font_subset_t *font = abstract_font;
    1224             :     cairo_ft_unscaled_font_t *ft_unscaled_font;
    1225             :     unsigned long ret;
    1226             :     cairo_status_t status;
    1227             : 
    1228           0 :     ft_unscaled_font = (cairo_ft_unscaled_font_t *) font->base.unscaled_font;
    1229           0 :     font->face = _cairo_ft_unscaled_font_lock_face (ft_unscaled_font);
    1230           0 :     if (unlikely (font->face == NULL))
    1231           0 :         return _cairo_error (CAIRO_STATUS_NO_MEMORY);
    1232             : 
    1233           0 :     font->type1_length = font->face->stream->size;
    1234           0 :     font->type1_data = malloc (font->type1_length);
    1235           0 :     if (unlikely (font->type1_data == NULL)) {
    1236           0 :         status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
    1237           0 :         goto fail;
    1238             :     }
    1239             : 
    1240           0 :     if (font->face->stream->read != NULL) {
    1241             :         /* Note that read() may be implemented as a macro, thanks POSIX!, so we
    1242             :          * need to wrap the following usage in parentheses in order to
    1243             :          * disambiguate it for the pre-processor - using the verbose function
    1244             :          * pointer dereference for clarity.
    1245             :          */
    1246           0 :         ret = (* font->face->stream->read) (font->face->stream, 0,
    1247           0 :                                             (unsigned char *) font->type1_data,
    1248           0 :                                             font->type1_length);
    1249           0 :         if (ret != font->type1_length) {
    1250           0 :             status = _cairo_error (CAIRO_STATUS_READ_ERROR);
    1251           0 :             goto fail;
    1252             :         }
    1253             :     } else {
    1254           0 :         memcpy (font->type1_data,
    1255           0 :                 font->face->stream->base, font->type1_length);
    1256             :     }
    1257             : 
    1258           0 :     status = _cairo_array_grow_by (&font->contents, 4096);
    1259           0 :     if (unlikely (status))
    1260           0 :         goto fail;
    1261             : 
    1262           0 :     font->output = _cairo_output_stream_create (type1_font_write, NULL, font);
    1263           0 :     if (unlikely ((status = font->output->status)))
    1264           0 :         goto fail;
    1265             : 
    1266           0 :     status = cairo_type1_font_subset_write (font, name);
    1267           0 :     if (unlikely (status))
    1268           0 :         goto fail;
    1269             : 
    1270           0 :     font->base.data = _cairo_array_index (&font->contents, 0);
    1271             : 
    1272             :  fail:
    1273           0 :     _cairo_ft_unscaled_font_unlock_face (ft_unscaled_font);
    1274             : 
    1275           0 :     return status;
    1276             : }
    1277             : 
    1278             : static cairo_status_t
    1279           0 : _cairo_type1_font_subset_fini (cairo_type1_font_subset_t *font)
    1280             : {
    1281           0 :     cairo_status_t status = CAIRO_STATUS_SUCCESS;
    1282             :     unsigned int i;
    1283             : 
    1284             :     /* If the subset generation failed, some of the pointers below may
    1285             :      * be NULL depending on at which point the error occurred. */
    1286             : 
    1287           0 :     _cairo_array_fini (&font->contents);
    1288             : 
    1289           0 :     free (font->type1_data);
    1290           0 :     if (font->glyphs != NULL) {
    1291           0 :         for (i = 0; i < font->base.num_glyphs; i++)
    1292           0 :             free (font->glyphs[i].name);
    1293             :     }
    1294             : 
    1295           0 :     _cairo_unscaled_font_destroy (font->base.unscaled_font);
    1296             : 
    1297           0 :     if (font->output != NULL)
    1298           0 :         status = _cairo_output_stream_destroy (font->output);
    1299             : 
    1300           0 :     if (font->base.base_font)
    1301           0 :         free (font->base.base_font);
    1302           0 :     free (font->glyphs);
    1303             : 
    1304           0 :     return status;
    1305             : }
    1306             : 
    1307             : cairo_status_t
    1308           0 : _cairo_type1_subset_init (cairo_type1_subset_t          *type1_subset,
    1309             :                           const char                    *name,
    1310             :                           cairo_scaled_font_subset_t    *scaled_font_subset,
    1311             :                           cairo_bool_t                   hex_encode)
    1312             : {
    1313             :     cairo_type1_font_subset_t font;
    1314             :     cairo_status_t status, status_ignored;
    1315             :     unsigned long parent_glyph, length;
    1316             :     unsigned int i;
    1317             :     cairo_unscaled_font_t *unscaled_font;
    1318             :     char buf[30];
    1319             : 
    1320             :     /* XXX: Need to fix this to work with a general cairo_unscaled_font_t. */
    1321           0 :     if (!_cairo_scaled_font_is_ft (scaled_font_subset->scaled_font))
    1322           0 :         return CAIRO_INT_STATUS_UNSUPPORTED;
    1323             : 
    1324           0 :     if (_cairo_ft_scaled_font_is_vertical (scaled_font_subset->scaled_font))
    1325           0 :         return CAIRO_INT_STATUS_UNSUPPORTED;
    1326             : 
    1327           0 :     unscaled_font = _cairo_ft_scaled_font_get_unscaled_font (scaled_font_subset->scaled_font);
    1328             : 
    1329           0 :     status = _cairo_type1_font_subset_init (&font, unscaled_font, hex_encode);
    1330           0 :     if (unlikely (status))
    1331           0 :         return status;
    1332             : 
    1333           0 :     for (i = 0; i < scaled_font_subset->num_glyphs; i++) {
    1334           0 :         parent_glyph = scaled_font_subset->glyphs[i];
    1335           0 :         cairo_type1_font_subset_use_glyph (&font, parent_glyph);
    1336             :     }
    1337             : 
    1338           0 :     status = cairo_type1_font_subset_generate (&font, name);
    1339           0 :     if (unlikely (status))
    1340           0 :         goto fail1;
    1341             : 
    1342           0 :     if (font.base.base_font) {
    1343           0 :         type1_subset->base_font = strdup (font.base.base_font);
    1344             :     } else {
    1345           0 :         snprintf(buf, sizeof (buf), "CairoFont-%u-%u",
    1346             :                  scaled_font_subset->font_id, scaled_font_subset->subset_id);
    1347           0 :         type1_subset->base_font = strdup (buf);
    1348             :     }
    1349           0 :     if (unlikely (type1_subset->base_font == NULL))
    1350           0 :         goto fail1;
    1351             : 
    1352           0 :     type1_subset->widths = calloc (sizeof (double), font.num_glyphs);
    1353           0 :     if (unlikely (type1_subset->widths == NULL))
    1354           0 :         goto fail2;
    1355           0 :     for (i = 0; i < font.base.num_glyphs; i++) {
    1356           0 :         if (font.glyphs[i].subset_index < 0)
    1357           0 :             continue;
    1358           0 :         type1_subset->widths[font.glyphs[i].subset_index] =
    1359           0 :             font.glyphs[i].width;
    1360             :     }
    1361             : 
    1362           0 :     type1_subset->x_min = font.base.x_min/1000.0;
    1363           0 :     type1_subset->y_min = font.base.y_min/1000.0;
    1364           0 :     type1_subset->x_max = font.base.x_max/1000.0;
    1365           0 :     type1_subset->y_max = font.base.y_max/1000.0;
    1366           0 :     type1_subset->ascent = font.base.ascent/1000.0;
    1367           0 :     type1_subset->descent = font.base.descent/1000.0;
    1368             : 
    1369           0 :     length = font.base.header_size +
    1370           0 :              font.base.data_size +
    1371           0 :              font.base.trailer_size;
    1372           0 :     type1_subset->data = malloc (length);
    1373           0 :     if (unlikely (type1_subset->data == NULL))
    1374           0 :         goto fail3;
    1375             : 
    1376           0 :     memcpy (type1_subset->data,
    1377           0 :             _cairo_array_index (&font.contents, 0), length);
    1378             : 
    1379           0 :     type1_subset->header_length = font.base.header_size;
    1380           0 :     type1_subset->data_length = font.base.data_size;
    1381           0 :     type1_subset->trailer_length = font.base.trailer_size;
    1382             : 
    1383           0 :     return _cairo_type1_font_subset_fini (&font);
    1384             : 
    1385             :  fail3:
    1386           0 :     free (type1_subset->widths);
    1387             :  fail2:
    1388           0 :     free (type1_subset->base_font);
    1389             :  fail1:
    1390           0 :     status_ignored = _cairo_type1_font_subset_fini (&font);
    1391             : 
    1392           0 :     return status;
    1393             : }
    1394             : 
    1395             : void
    1396           0 : _cairo_type1_subset_fini (cairo_type1_subset_t *subset)
    1397             : {
    1398           0 :     free (subset->base_font);
    1399           0 :     free (subset->widths);
    1400           0 :     free (subset->data);
    1401           0 : }
    1402             : 
    1403             : cairo_bool_t
    1404           0 : _cairo_type1_scaled_font_is_type1 (cairo_scaled_font_t *scaled_font)
    1405             : {
    1406             :     cairo_ft_unscaled_font_t *unscaled;
    1407             :     FT_Face face;
    1408             :     PS_FontInfoRec font_info;
    1409           0 :     cairo_bool_t is_type1 = FALSE;
    1410             : 
    1411           0 :     if (!_cairo_scaled_font_is_ft (scaled_font))
    1412           0 :        return FALSE;
    1413           0 :     unscaled = (cairo_ft_unscaled_font_t *) _cairo_ft_scaled_font_get_unscaled_font (scaled_font);
    1414           0 :     face = _cairo_ft_unscaled_font_lock_face (unscaled);
    1415           0 :     if (!face)
    1416           0 :         return FALSE;
    1417             : 
    1418           0 :     if (FT_Get_PS_Font_Info(face, &font_info) == 0)
    1419           0 :         is_type1 = TRUE;
    1420             : 
    1421             :     /* OpenType/CFF fonts also have a PS_FontInfoRec */
    1422             : #if HAVE_FT_LOAD_SFNT_TABLE
    1423           0 :     if (FT_IS_SFNT (face))
    1424           0 :         is_type1 = FALSE;
    1425             : #endif
    1426             : 
    1427           0 :     _cairo_ft_unscaled_font_unlock_face (unscaled);
    1428             : 
    1429           0 :     return is_type1;
    1430             : }
    1431             : 
    1432             : #endif /* CAIRO_HAS_FT_FONT */
    1433             : 
    1434             : #endif /* CAIRO_HAS_FONT_SUBSET */

Generated by: LCOV version 1.13