Subversion Repositories Kolibri OS

Rev

Go to most recent revision | Blame | Last modification | View Log | Download | RSS feed

  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. _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.     ft_unscaled_font = (cairo_ft_unscaled_font_t *) unscaled_font;
  128.  
  129.     face = _cairo_ft_unscaled_font_lock_face (ft_unscaled_font);
  130.     if (unlikely (face == NULL))
  131.         return _cairo_error (CAIRO_STATUS_NO_MEMORY);
  132.  
  133.     if (FT_Get_PS_Font_Info(face, &font_info) != 0) {
  134.         status = CAIRO_INT_STATUS_UNSUPPORTED;
  135.         goto fail1;
  136.     }
  137.  
  138.     /* OpenType/CFF fonts also have a PS_FontInfoRec */
  139. #if HAVE_FT_LOAD_SFNT_TABLE
  140.     if (FT_IS_SFNT (face)) {
  141.         status = CAIRO_INT_STATUS_UNSUPPORTED;
  142.         goto fail1;
  143.     }
  144. #endif
  145.  
  146.     memset (font, 0, sizeof (*font));
  147.     font->base.unscaled_font = _cairo_unscaled_font_reference (unscaled_font);
  148.     font->base.num_glyphs = face->num_glyphs;
  149.     font->base.x_min = face->bbox.xMin / (double)face->units_per_EM;
  150.     font->base.y_min = face->bbox.yMin / (double)face->units_per_EM;
  151.     font->base.x_max = face->bbox.xMax / (double)face->units_per_EM;
  152.     font->base.y_max = face->bbox.yMax / (double)face->units_per_EM;
  153.     font->base.ascent = face->ascender / (double)face->units_per_EM;
  154.     font->base.descent = face->descender / (double)face->units_per_EM;
  155.  
  156.     if (face->family_name) {
  157.         font->base.base_font = strdup (face->family_name);
  158.         if (unlikely (font->base.base_font == NULL)) {
  159.             status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
  160.             goto fail2;
  161.         }
  162.         for (i = 0, j = 0; font->base.base_font[j]; j++) {
  163.             if (font->base.base_font[j] == ' ')
  164.                 continue;
  165.             font->base.base_font[i++] = font->base.base_font[j];
  166.         }
  167.         font->base.base_font[i] = '\0';
  168.     }
  169.  
  170.     font->glyphs = calloc (face->num_glyphs, sizeof font->glyphs[0]);
  171.     if (unlikely (font->glyphs == NULL)) {
  172.         status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
  173.         goto fail3;
  174.     }
  175.  
  176.     font->hex_encode = hex_encode;
  177.     font->num_glyphs = 0;
  178.     for (i = 0; i < face->num_glyphs; i++)
  179.         font->glyphs[i].subset_index = -1;
  180.  
  181.     _cairo_array_init (&font->contents, sizeof (char));
  182.  
  183.     _cairo_ft_unscaled_font_unlock_face (ft_unscaled_font);
  184.  
  185.     return CAIRO_STATUS_SUCCESS;
  186.  
  187.  fail3:
  188.     if (font->base.base_font)
  189.         free (font->base.base_font);
  190.  fail2:
  191.     _cairo_unscaled_font_destroy (unscaled_font);
  192.  fail1:
  193.     _cairo_ft_unscaled_font_unlock_face (ft_unscaled_font);
  194.  
  195.     return status;
  196. }
  197.  
  198. static void
  199. cairo_type1_font_subset_use_glyph (cairo_type1_font_subset_t *font, int glyph)
  200. {
  201.     if (font->glyphs[glyph].subset_index >= 0)
  202.         return;
  203.  
  204.     font->glyphs[glyph].subset_index = font->num_glyphs++;
  205. }
  206.  
  207. static cairo_bool_t
  208. is_ps_delimiter(int c)
  209. {
  210.     static const char delimiters[] = "()[]{}<>/% \t\r\n";
  211.  
  212.     return strchr (delimiters, c) != NULL;
  213. }
  214.  
  215. static const char *
  216. 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.     if (buffer == NULL)
  222.         return NULL;
  223.  
  224.     length = strlen (token);
  225.     for (i = 0; buffer + i < end - length + 1; i++)
  226.         if (memcmp (buffer + i, token, length) == 0)
  227.             if ((i == 0 || token[0] == '/' || is_ps_delimiter(buffer[i - 1])) &&
  228.                 (buffer + i == end - length || is_ps_delimiter(buffer[i + length])))
  229.                 return buffer + i;
  230.  
  231.     return NULL;
  232. }
  233.  
  234. static cairo_status_t
  235. 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.     p = (unsigned char *) font->type1_data;
  242.     font->type1_end = font->type1_data + font->type1_length;
  243.     if (p[0] == 0x80 && p[1] == 0x01) {
  244.         font->header_segment_size =
  245.             p[2] | (p[3] << 8) | (p[4] << 16) | (p[5] << 24);
  246.         font->header_segment = (char *) p + 6;
  247.  
  248.         p += 6 + font->header_segment_size;
  249.         font->eexec_segment_size =
  250.             p[2] | (p[3] << 8) | (p[4] << 16) | (p[5] << 24);
  251.         font->eexec_segment = (char *) p + 6;
  252.         font->eexec_segment_is_ascii = (p[1] == 1);
  253.  
  254.         p += 6 + font->eexec_segment_size;
  255.         while (p < (unsigned char *) (font->type1_end) && p[1] != 0x03) {
  256.             size = p[2] | (p[3] << 8) | (p[4] << 16) | (p[5] << 24);
  257.             p += 6 + size;
  258.         }
  259.         font->type1_end = (char *) p;
  260.     } else {
  261.         eexec_token = find_token ((char *) p, font->type1_end, "eexec");
  262.         if (eexec_token == NULL)
  263.             return CAIRO_INT_STATUS_UNSUPPORTED;
  264.  
  265.         font->header_segment_size = eexec_token - (char *) p + strlen ("eexec\n");
  266.         font->header_segment = (char *) p;
  267.         font->eexec_segment_size = font->type1_length - font->header_segment_size;
  268.         font->eexec_segment = (char *) p + font->header_segment_size;
  269.         font->eexec_segment_is_ascii = TRUE;
  270.         for (i = 0; i < 4; i++) {
  271.             if (!isxdigit(font->eexec_segment[i]))
  272.                 font->eexec_segment_is_ascii = FALSE;
  273.         }
  274.     }
  275.  
  276.     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. 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.     segment_end = font->header_segment + font->header_segment_size;
  295.  
  296.     start = font->header_segment;
  297.     do {
  298.         start = find_token (start, segment_end, key);
  299.         if (start) {
  300.             p = start + strlen(key);
  301.             /* skip integers or array of integers */
  302.             while (p < segment_end &&
  303.                    (_cairo_isspace(*p) ||
  304.                     _cairo_isdigit(*p) ||
  305.                     *p == '[' ||
  306.                     *p == ']'))
  307.             {
  308.                 p++;
  309.             }
  310.  
  311.             if (p + 3 < segment_end && memcmp(p, "def", 3) == 0) {
  312.                 /* erase definition of the key */
  313.                 memset((char *) start, ' ', p + 3 - start);
  314.             }
  315.             start += strlen(key);
  316.         }
  317.     } while (start);
  318. }
  319.  
  320. static cairo_status_t
  321. 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.     cairo_type1_font_erase_dict_key (font, "/UniqueID");
  344.     cairo_type1_font_erase_dict_key (font, "/XUID");
  345.  
  346.     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.     end = font->header_segment;
  359.     start = find_token (font->header_segment, segment_end, "/UniqueID");
  360.     if (start) {
  361.         start += 9;
  362.         while (start < segment_end && _cairo_isspace (*start))
  363.             start++;
  364.         if (start + 5 < segment_end && memcmp(start, "known", 5) == 0) {
  365.             _cairo_output_stream_write (font->output, font->header_segment,
  366.                                         start + 5 - font->header_segment);
  367.             _cairo_output_stream_printf (font->output, " pop false ");
  368.             end = start + 5;
  369.         }
  370.     }
  371.  
  372.     start = find_token (end, segment_end, "/FontName");
  373.     if (start == NULL)
  374.         return CAIRO_INT_STATUS_UNSUPPORTED;
  375.  
  376.     _cairo_output_stream_write (font->output, end,
  377.                                 start - end);
  378.  
  379.     _cairo_output_stream_printf (font->output, "/FontName /%s def", name);
  380.  
  381.     end = find_token (start, segment_end, "def");
  382.     if (end == NULL)
  383.         return CAIRO_INT_STATUS_UNSUPPORTED;
  384.     end += 3;
  385.  
  386.     start = find_token (end, segment_end, "/Encoding");
  387.     if (start == NULL)
  388.         return CAIRO_INT_STATUS_UNSUPPORTED;
  389.     _cairo_output_stream_write (font->output, end, start - end);
  390.  
  391.     _cairo_output_stream_printf (font->output,
  392.                                  "/Encoding 256 array\n"
  393.                                  "0 1 255 {1 index exch /.notdef put} for\n");
  394.     for (i = 1; i < font->base.num_glyphs; i++) {
  395.         if (font->glyphs[i].subset_index < 0)
  396.             continue;
  397.         _cairo_output_stream_printf (font->output,
  398.                                      "dup %d /%s put\n",
  399.                                      font->glyphs[i].subset_index,
  400.                                      font->glyphs[i].name);
  401.     }
  402.     _cairo_output_stream_printf (font->output, "readonly def");
  403.  
  404.     end = find_token (start, segment_end, "def");
  405.     if (end == NULL)
  406.         return CAIRO_INT_STATUS_UNSUPPORTED;
  407.     end += 3;
  408.  
  409.     _cairo_output_stream_write (font->output, end, segment_end - end);
  410.  
  411.     return font->output->status;
  412. }
  413.  
  414. static int
  415. hex_to_int (int ch)
  416. {
  417.     if (ch <= '9')
  418.         return ch - '0';
  419.     else if (ch <= 'F')
  420.         return ch - 'A' + 10;
  421.     else
  422.         return ch - 'a' + 10;
  423. }
  424.  
  425. static cairo_status_t
  426. 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.     in = (const unsigned char *) data;
  435.     end = (const unsigned char *) data + length;
  436.     while (in < end) {
  437.         p = *in++;
  438.         c = p ^ (font->eexec_key >> 8);
  439.         font->eexec_key = (c + font->eexec_key) * CAIRO_TYPE1_ENCRYPT_C1 + CAIRO_TYPE1_ENCRYPT_C2;
  440.  
  441.         if (font->hex_encode) {
  442.             digits[0] = hex_digits[c >> 4];
  443.             digits[1] = hex_digits[c & 0x0f];
  444.             digits[2] = '\n';
  445.             font->hex_column += 2;
  446.  
  447.             if (font->hex_column == 78) {
  448.                 _cairo_output_stream_write (font->output, digits, 3);
  449.                 font->hex_column = 0;
  450.             } else {
  451.                 _cairo_output_stream_write (font->output, digits, 2);
  452.             }
  453.         } else {
  454.             digits[0] = c;
  455.             _cairo_output_stream_write (font->output, digits, 1);
  456.         }
  457.     }
  458.  
  459.     return font->output->status;
  460. }
  461.  
  462. static cairo_status_t
  463. cairo_type1_font_subset_decrypt_eexec_segment (cairo_type1_font_subset_t *font)
  464. {
  465.     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.     in = (unsigned char *) font->eexec_segment;
  472.     end = (unsigned char *) in + font->eexec_segment_size;
  473.  
  474.     font->cleartext = malloc (font->eexec_segment_size);
  475.     if (unlikely (font->cleartext == NULL))
  476.         return _cairo_error (CAIRO_STATUS_NO_MEMORY);
  477.  
  478.     out = font->cleartext;
  479.     while (in < end) {
  480.         if (font->eexec_segment_is_ascii) {
  481.             c = *in++;
  482.             if (_cairo_isspace (c))
  483.                 continue;
  484.             c = (hex_to_int (c) << 4) | hex_to_int (*in++);
  485.         } else {
  486.             c = *in++;
  487.         }
  488.         p = c ^ (r >> 8);
  489.         r = (c + r) * CAIRO_TYPE1_ENCRYPT_C1 + CAIRO_TYPE1_ENCRYPT_C2;
  490.  
  491.         *out++ = p;
  492.     }
  493.     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.     for (i = 0; i < 4 && i < font->eexec_segment_size; i++)
  510.         font->cleartext[i] = ' ';
  511.  
  512.     return CAIRO_STATUS_SUCCESS;
  513. }
  514.  
  515. static const char *
  516. skip_token (const char *p, const char *end)
  517. {
  518.     while (p < end && _cairo_isspace(*p))
  519.         p++;
  520.  
  521.     while (p < end && !_cairo_isspace(*p))
  522.         p++;
  523.  
  524.     if (p == end)
  525.         return NULL;
  526.  
  527.     return p;
  528. }
  529.  
  530. static int
  531. 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.     for (i = 0; i < font->base.num_glyphs; i++) {
  537.         if (font->glyphs[i].name &&
  538.             strncmp (font->glyphs[i].name, glyph_name, length) == 0 &&
  539.             font->glyphs[i].name[length] == '\0')
  540.             return i;
  541.     }
  542.  
  543.     return -1;
  544. }
  545.  
  546. static cairo_status_t
  547. 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.     for (i = 0; i < font->base.num_glyphs; i++) {
  555.         if (font->glyphs[i].name != NULL)
  556.             continue;
  557.  
  558.         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.         if (error != FT_Err_Ok) {
  562.             /* propagate fatal errors from FreeType */
  563.             if (error == FT_Err_Out_Of_Memory)
  564.                 return _cairo_error (CAIRO_STATUS_NO_MEMORY);
  565.  
  566.             return CAIRO_INT_STATUS_UNSUPPORTED;
  567.         }
  568.  
  569.         font->glyphs[i].width = font->face->glyph->metrics.horiAdvance / (double)font->face->units_per_EM;
  570.  
  571.         error = FT_Get_Glyph_Name(font->face, i, buffer, sizeof buffer);
  572.         if (error != FT_Err_Ok) {
  573.             /* propagate fatal errors from FreeType */
  574.             if (error == FT_Err_Out_Of_Memory)
  575.                 return _cairo_error (CAIRO_STATUS_NO_MEMORY);
  576.  
  577.             return CAIRO_INT_STATUS_UNSUPPORTED;
  578.         }
  579.  
  580.         font->glyphs[i].name = strdup (buffer);
  581.         if (unlikely (font->glyphs[i].name == NULL))
  582.             return _cairo_error (CAIRO_STATUS_NO_MEMORY);
  583.     }
  584.  
  585.     return CAIRO_STATUS_SUCCESS;
  586. }
  587.  
  588. static void
  589. cairo_type1_font_subset_decrypt_charstring (const unsigned char *in, int size, unsigned char *out)
  590. {
  591.     unsigned short r = CAIRO_TYPE1_CHARSTRING_KEY;
  592.     int c, p, i;
  593.  
  594.     for (i = 0; i < size; i++) {
  595.         c = *in++;
  596.         p = c ^ (r >> 8);
  597.         r = (c + r) * CAIRO_TYPE1_ENCRYPT_C1 + CAIRO_TYPE1_ENCRYPT_C2;
  598.         *out++ = p;
  599.     }
  600. }
  601.  
  602. static const unsigned char *
  603. cairo_type1_font_subset_decode_integer (const unsigned char *p, int *integer)
  604. {
  605.     if (*p <= 246) {
  606.         *integer = *p++ - 139;
  607.     } else if (*p <= 250) {
  608.         *integer = (p[0] - 247) * 256 + p[1] + 108;
  609.         p += 2;
  610.     } else if (*p <= 254) {
  611.         *integer = -(p[0] - 251) * 256 - p[1] - 108;
  612.         p += 2;
  613.     } else {
  614.         *integer = (p[1] << 24) | (p[2] << 16) | (p[3] << 8) | p[4];
  615.         p += 5;
  616.     }
  617.  
  618.     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. use_standard_encoding_glyph (cairo_type1_font_subset_t *font, int index)
  809. {
  810.     const char *glyph_name;
  811.  
  812.     if (index < 0 || index > 255)
  813.         return CAIRO_STATUS_SUCCESS;
  814.  
  815.     glyph_name = ps_standard_encoding(index);
  816.     if (glyph_name == NULL)
  817.         return CAIRO_STATUS_SUCCESS;
  818.  
  819.     index = cairo_type1_font_subset_lookup_glyph (font,
  820.                                                   glyph_name,
  821.                                                   strlen(glyph_name));
  822.     if (index < 0)
  823.         return CAIRO_INT_STATUS_UNSUPPORTED;
  824.  
  825.     cairo_type1_font_subset_use_glyph (font, index);
  826.  
  827.     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. 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.     charstring = malloc (encrypted_charstring_length);
  846.     if (unlikely (charstring == NULL))
  847.         return _cairo_error (CAIRO_STATUS_NO_MEMORY);
  848.  
  849.     cairo_type1_font_subset_decrypt_charstring ((const unsigned char *)
  850.                                                 encrypted_charstring,
  851.                                                 encrypted_charstring_length,
  852.                                                 charstring);
  853.     end = charstring + encrypted_charstring_length;
  854.  
  855.     p = charstring + 4;
  856.     sp = 0;
  857.  
  858.     while (p < end) {
  859.         if (*p < 32) {
  860.             command = *p++;
  861.  
  862.             if (command == TYPE1_CHARSTRING_COMMAND_ESCAPE)
  863.                 command = 32 + *p++;
  864.  
  865.             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.                 status = use_standard_encoding_glyph (font, stack[3]);
  874.                 if (unlikely (status))
  875.                     return status;
  876.  
  877.                 status = use_standard_encoding_glyph (font, stack[4]);
  878.                 if (unlikely (status))
  879.                     return status;
  880.  
  881.                 sp = 0;
  882.                 break;
  883.  
  884.             default:
  885.                 sp = 0;
  886.                 break;
  887.             }
  888.         } else {
  889.             /* integer argument */
  890.             p = cairo_type1_font_subset_decode_integer (p, &value);
  891.             if (sp < 5)
  892.                 stack[sp++] = value;
  893.         }
  894.     }
  895.  
  896.     free (charstring);
  897.  
  898.     return CAIRO_STATUS_SUCCESS;
  899. }
  900.  
  901. static cairo_status_t
  902. 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.     length = snprintf (buffer, sizeof buffer,
  911.                        "/%.*s %d %s ",
  912.                        name_length, name, charstring_length, font->rd);
  913.     status = cairo_type1_font_subset_write_encrypted (font, buffer, length);
  914.     if (unlikely (status))
  915.         return status;
  916.  
  917.     status = cairo_type1_font_subset_write_encrypted (font,
  918.                                                       charstring,
  919.                                                       charstring_length);
  920.     if (unlikely (status))
  921.         return status;
  922.  
  923.     length = snprintf (buffer, sizeof buffer, "%s\n", font->nd);
  924.     status = cairo_type1_font_subset_write_encrypted (font, buffer, length);
  925.     if (unlikely (status))
  926.         return status;
  927.  
  928.     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. 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.     p = dict_start;
  961.  
  962.     while (*p == '/') {
  963.         name = p + 1;
  964.         p = skip_token (p, dict_end);
  965.         name_length = p - name;
  966.  
  967.         charstring_length = strtol (p, &end, 10);
  968.         if (p == end)
  969.             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.         charstring = skip_token (end, dict_end) + 1;
  974.  
  975.         /* Skip binary data and |- or ND token. */
  976.         p = skip_token (charstring + charstring_length, dict_end);
  977.         while (p < dict_end && _cairo_isspace(*p))
  978.             p++;
  979.  
  980.         /* In case any of the skip_token() calls above reached EOF, p will
  981.          * be equal to dict_end. */
  982.         if (p == dict_end)
  983.             return CAIRO_INT_STATUS_UNSUPPORTED;
  984.  
  985.         glyph_index = cairo_type1_font_subset_lookup_glyph (font,
  986.                                                             name, name_length);
  987.         if (font->glyphs[glyph_index].subset_index >= 0) {
  988.             cairo_status_t status = func (font,
  989.                                           name, name_length,
  990.                                           charstring, charstring_length);
  991.             if (unlikely (status))
  992.                 return status;
  993.         }
  994.     }
  995.  
  996.     *dict_out = p;
  997.  
  998.     return CAIRO_STATUS_SUCCESS;
  999. }
  1000.  
  1001.  
  1002. static cairo_status_t
  1003. 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.     charstrings = find_token (font->cleartext, font->cleartext_end, "/CharStrings");
  1029.     if (charstrings == NULL)
  1030.         return CAIRO_INT_STATUS_UNSUPPORTED;
  1031.  
  1032.     /* Scan past /CharStrings and the integer following it. */
  1033.     p = charstrings + strlen ("/CharStrings");
  1034.     num_charstrings = strtol (p, &glyph_count_end, 10);
  1035.     if (p == glyph_count_end)
  1036.         return CAIRO_INT_STATUS_UNSUPPORTED;
  1037.  
  1038.     /* Look for a '/' which marks the beginning of the first glyph
  1039.      * definition. */
  1040.     for (p = glyph_count_end; p < font->cleartext_end; p++)
  1041.         if (*p == '/')
  1042.             break;
  1043.     if (p == font->cleartext_end)
  1044.         return CAIRO_INT_STATUS_UNSUPPORTED;
  1045.     dict_start = p;
  1046.  
  1047.     status = cairo_type1_font_subset_get_glyph_names_and_widths (font);
  1048.     if (unlikely (status))
  1049.         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.     status = cairo_type1_font_subset_for_each_glyph (font,
  1056.                                                      dict_start,
  1057.                                                      font->cleartext_end,
  1058.                                                      cairo_type1_font_subset_look_for_seac,
  1059.                                                      &p);
  1060.     if (unlikely (status))
  1061.         return status;
  1062.  
  1063.     closefile_token = find_token (p, font->cleartext_end, "closefile");
  1064.     if (closefile_token == NULL)
  1065.         return CAIRO_INT_STATUS_UNSUPPORTED;
  1066.  
  1067.     status = cairo_type1_font_subset_get_glyph_names_and_widths (font);
  1068.     if (unlikely (status))
  1069.         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.     status = cairo_type1_font_subset_write_header (font, name);
  1074.     if (unlikely (status))
  1075.         return status;
  1076.  
  1077.     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.     status = cairo_type1_font_subset_write_encrypted (font, font->cleartext,
  1083.                                                  charstrings - font->cleartext);
  1084.     if (unlikely (status))
  1085.         return status;
  1086.  
  1087.     /* Write out new charstring count */
  1088.     length = snprintf (buffer, sizeof buffer,
  1089.                        "/CharStrings %d", font->num_glyphs);
  1090.     status = cairo_type1_font_subset_write_encrypted (font, buffer, length);
  1091.     if (unlikely (status))
  1092.         return status;
  1093.  
  1094.     /* Write out text between the charstring count and the first
  1095.      * charstring definition */
  1096.     status = cairo_type1_font_subset_write_encrypted (font, glyph_count_end,
  1097.                                                   dict_start - glyph_count_end);
  1098.     if (unlikely (status))
  1099.         return status;
  1100.  
  1101.     /* Write out the charstring definitions for each of the glyphs in
  1102.      * the subset. */
  1103.     status = cairo_type1_font_subset_for_each_glyph (font,
  1104.                                                      dict_start,
  1105.                                                      font->cleartext_end,
  1106.                                                      write_used_glyphs,
  1107.                                                      &p);
  1108.     if (unlikely (status))
  1109.         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.     status = cairo_type1_font_subset_write_encrypted (font, p,
  1114.                                 closefile_token - p + strlen ("closefile") + 1);
  1115.     if (unlikely (status))
  1116.         return status;
  1117.  
  1118.     if (font->hex_encode)
  1119.         _cairo_output_stream_write (font->output, "\n", 1);
  1120.  
  1121.     return CAIRO_STATUS_SUCCESS;
  1122. }
  1123.  
  1124. static cairo_status_t
  1125. 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.     for (i = 0; i < 8; i++)
  1134.         _cairo_output_stream_write (font->output, zeros, sizeof zeros);
  1135.  
  1136.     cleartomark_token = find_token (font->type1_data, font->type1_end, "cleartomark");
  1137.     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.         _cairo_output_stream_write (font->output, cleartomark_token,
  1143.                                     font->type1_end - cleartomark_token);
  1144.     } 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.         _cairo_output_stream_printf (font->output, "cleartomark");
  1150.     } else {
  1151.         return CAIRO_INT_STATUS_UNSUPPORTED;
  1152.     }
  1153.  
  1154.     /* some fonts do not have a newline at the end of the last line */
  1155.     _cairo_output_stream_printf (font->output, "\n");
  1156.  
  1157.     return CAIRO_STATUS_SUCCESS;
  1158. }
  1159.  
  1160. static cairo_status_t
  1161. type1_font_write (void *closure, const unsigned char *data, unsigned int length)
  1162. {
  1163.     cairo_type1_font_subset_t *font = closure;
  1164.  
  1165.     return _cairo_array_append_multiple (&font->contents, data, length);
  1166. }
  1167.  
  1168. static cairo_status_t
  1169. cairo_type1_font_subset_write (cairo_type1_font_subset_t *font,
  1170.                                const char *name)
  1171. {
  1172.     cairo_status_t status;
  1173.  
  1174.     status = cairo_type1_font_subset_find_segments (font);
  1175.     if (unlikely (status))
  1176.         return status;
  1177.  
  1178.     status = cairo_type1_font_subset_decrypt_eexec_segment (font);
  1179.     if (unlikely (status))
  1180.         return status;
  1181.  
  1182.     /* Determine which glyph definition delimiters to use. */
  1183.     if (find_token (font->cleartext, font->cleartext_end, "/-|") != NULL) {
  1184.         font->rd = "-|";
  1185.         font->nd = "|-";
  1186.     } else if (find_token (font->cleartext, font->cleartext_end, "/RD") != NULL) {
  1187.         font->rd = "RD";
  1188.         font->nd = "ND";
  1189.     } else {
  1190.         /* Don't know *what* kind of font this is... */
  1191.         return CAIRO_INT_STATUS_UNSUPPORTED;
  1192.     }
  1193.  
  1194.     font->eexec_key = CAIRO_TYPE1_PRIVATE_DICT_KEY;
  1195.     font->hex_column = 0;
  1196.  
  1197.     status = cairo_type1_font_subset_write_private_dict (font, name);
  1198.     if (unlikely (status))
  1199.         return status;
  1200.  
  1201.     font->base.data_size = _cairo_output_stream_get_position (font->output) -
  1202.         font->base.header_size;
  1203.  
  1204.     status = cairo_type1_font_subset_write_trailer (font);
  1205.     if (unlikely (status))
  1206.         return status;
  1207.  
  1208.     font->base.trailer_size =
  1209.         _cairo_output_stream_get_position (font->output) -
  1210.         font->base.header_size - font->base.data_size;
  1211.  
  1212.     return CAIRO_STATUS_SUCCESS;
  1213. }
  1214.  
  1215. static cairo_status_t
  1216. cairo_type1_font_subset_generate (void       *abstract_font,
  1217.                                   const char *name)
  1218.  
  1219. {
  1220.     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.     ft_unscaled_font = (cairo_ft_unscaled_font_t *) font->base.unscaled_font;
  1226.     font->face = _cairo_ft_unscaled_font_lock_face (ft_unscaled_font);
  1227.     if (unlikely (font->face == NULL))
  1228.         return _cairo_error (CAIRO_STATUS_NO_MEMORY);
  1229.  
  1230.     font->type1_length = font->face->stream->size;
  1231.     font->type1_data = malloc (font->type1_length);
  1232.     if (unlikely (font->type1_data == NULL)) {
  1233.         status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
  1234.         goto fail;
  1235.     }
  1236.  
  1237.     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.         ret = (* font->face->stream->read) (font->face->stream, 0,
  1244.                                             (unsigned char *) font->type1_data,
  1245.                                             font->type1_length);
  1246.         if (ret != font->type1_length) {
  1247.             status = _cairo_error (CAIRO_STATUS_READ_ERROR);
  1248.             goto fail;
  1249.         }
  1250.     } else {
  1251.         memcpy (font->type1_data,
  1252.                 font->face->stream->base, font->type1_length);
  1253.     }
  1254.  
  1255.     status = _cairo_array_grow_by (&font->contents, 4096);
  1256.     if (unlikely (status))
  1257.         goto fail;
  1258.  
  1259.     font->output = _cairo_output_stream_create (type1_font_write, NULL, font);
  1260.     if (unlikely ((status = font->output->status)))
  1261.         goto fail;
  1262.  
  1263.     status = cairo_type1_font_subset_write (font, name);
  1264.     if (unlikely (status))
  1265.         goto fail;
  1266.  
  1267.     font->base.data = _cairo_array_index (&font->contents, 0);
  1268.  
  1269.  fail:
  1270.     _cairo_ft_unscaled_font_unlock_face (ft_unscaled_font);
  1271.  
  1272.     return status;
  1273. }
  1274.  
  1275. static cairo_status_t
  1276. _cairo_type1_font_subset_fini (cairo_type1_font_subset_t *font)
  1277. {
  1278.     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.     _cairo_array_fini (&font->contents);
  1285.  
  1286.     free (font->type1_data);
  1287.     if (font->glyphs != NULL) {
  1288.         for (i = 0; i < font->base.num_glyphs; i++)
  1289.             free (font->glyphs[i].name);
  1290.     }
  1291.  
  1292.     _cairo_unscaled_font_destroy (font->base.unscaled_font);
  1293.  
  1294.     if (font->output != NULL)
  1295.         status = _cairo_output_stream_destroy (font->output);
  1296.  
  1297.     if (font->base.base_font)
  1298.         free (font->base.base_font);
  1299.     free (font->glyphs);
  1300.  
  1301.     return status;
  1302. }
  1303.  
  1304. cairo_status_t
  1305. _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.     if (!_cairo_scaled_font_is_ft (scaled_font_subset->scaled_font))
  1319.         return CAIRO_INT_STATUS_UNSUPPORTED;
  1320.  
  1321.     if (_cairo_ft_scaled_font_is_vertical (scaled_font_subset->scaled_font))
  1322.         return CAIRO_INT_STATUS_UNSUPPORTED;
  1323.  
  1324.     unscaled_font = _cairo_ft_scaled_font_get_unscaled_font (scaled_font_subset->scaled_font);
  1325.  
  1326.     status = _cairo_type1_font_subset_init (&font, unscaled_font, hex_encode);
  1327.     if (unlikely (status))
  1328.         return status;
  1329.  
  1330.     for (i = 0; i < scaled_font_subset->num_glyphs; i++) {
  1331.         parent_glyph = scaled_font_subset->glyphs[i];
  1332.         cairo_type1_font_subset_use_glyph (&font, parent_glyph);
  1333.     }
  1334.  
  1335.     status = cairo_type1_font_subset_generate (&font, name);
  1336.     if (unlikely (status))
  1337.         goto fail1;
  1338.  
  1339.     if (font.base.base_font) {
  1340.         type1_subset->base_font = strdup (font.base.base_font);
  1341.     } else {
  1342.         snprintf(buf, sizeof (buf), "CairoFont-%u-%u",
  1343.                  scaled_font_subset->font_id, scaled_font_subset->subset_id);
  1344.         type1_subset->base_font = strdup (buf);
  1345.     }
  1346.     if (unlikely (type1_subset->base_font == NULL))
  1347.         goto fail1;
  1348.  
  1349.     type1_subset->widths = calloc (sizeof (double), font.num_glyphs);
  1350.     if (unlikely (type1_subset->widths == NULL))
  1351.         goto fail2;
  1352.     for (i = 0; i < font.base.num_glyphs; i++) {
  1353.         if (font.glyphs[i].subset_index < 0)
  1354.             continue;
  1355.         type1_subset->widths[font.glyphs[i].subset_index] =
  1356.             font.glyphs[i].width;
  1357.     }
  1358.  
  1359.     type1_subset->x_min = font.base.x_min;
  1360.     type1_subset->y_min = font.base.y_min;
  1361.     type1_subset->x_max = font.base.x_max;
  1362.     type1_subset->y_max = font.base.y_max;
  1363.     type1_subset->ascent = font.base.ascent;
  1364.     type1_subset->descent = font.base.descent;
  1365.  
  1366.     length = font.base.header_size +
  1367.              font.base.data_size +
  1368.              font.base.trailer_size;
  1369.     type1_subset->data = malloc (length);
  1370.     if (unlikely (type1_subset->data == NULL))
  1371.         goto fail3;
  1372.  
  1373.     memcpy (type1_subset->data,
  1374.             _cairo_array_index (&font.contents, 0), length);
  1375.  
  1376.     type1_subset->header_length = font.base.header_size;
  1377.     type1_subset->data_length = font.base.data_size;
  1378.     type1_subset->trailer_length = font.base.trailer_size;
  1379.  
  1380.     return _cairo_type1_font_subset_fini (&font);
  1381.  
  1382.  fail3:
  1383.     free (type1_subset->widths);
  1384.  fail2:
  1385.     free (type1_subset->base_font);
  1386.  fail1:
  1387.     status_ignored = _cairo_type1_font_subset_fini (&font);
  1388.  
  1389.     return status;
  1390. }
  1391.  
  1392. void
  1393. _cairo_type1_subset_fini (cairo_type1_subset_t *subset)
  1394. {
  1395.     free (subset->base_font);
  1396.     free (subset->widths);
  1397.     free (subset->data);
  1398. }
  1399.  
  1400. cairo_bool_t
  1401. _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.     cairo_bool_t is_type1 = FALSE;
  1407.  
  1408.     if (!_cairo_scaled_font_is_ft (scaled_font))
  1409.        return FALSE;
  1410.     unscaled = (cairo_ft_unscaled_font_t *) _cairo_ft_scaled_font_get_unscaled_font (scaled_font);
  1411.     face = _cairo_ft_unscaled_font_lock_face (unscaled);
  1412.     if (!face)
  1413.         return FALSE;
  1414.  
  1415.     if (FT_Get_PS_Font_Info(face, &font_info) == 0)
  1416.         is_type1 = TRUE;
  1417.  
  1418.     /* OpenType/CFF fonts also have a PS_FontInfoRec */
  1419. #if HAVE_FT_LOAD_SFNT_TABLE
  1420.     if (FT_IS_SFNT (face))
  1421.         is_type1 = FALSE;
  1422. #endif
  1423.  
  1424.     _cairo_ft_unscaled_font_unlock_face (unscaled);
  1425.  
  1426.     return is_type1;
  1427. }
  1428.  
  1429. #endif /* CAIRO_HAS_FT_FONT */
  1430.  
  1431. #endif /* CAIRO_HAS_FONT_SUBSET */
  1432.