Subversion Repositories Kolibri OS

Rev

Blame | Last modification | View Log | 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.  *      Adrian Johnson <ajohnson@redneon.com>
  34.  */
  35.  
  36. #define _BSD_SOURCE /* for snprintf(), strdup() */
  37. #include "cairoint.h"
  38.  
  39. #include "cairo-array-private.h"
  40. #include "cairo-error-private.h"
  41.  
  42. #if CAIRO_HAS_FONT_SUBSET
  43.  
  44. #include "cairo-type1-private.h"
  45. #include "cairo-scaled-font-subsets-private.h"
  46. #include "cairo-path-fixed-private.h"
  47. #include "cairo-output-stream-private.h"
  48.  
  49. typedef enum {
  50.     CAIRO_CHARSTRING_TYPE1,
  51.     CAIRO_CHARSTRING_TYPE2
  52. } cairo_charstring_type_t;
  53.  
  54. typedef struct _cairo_type1_font {
  55.     int *widths;
  56.  
  57.     cairo_scaled_font_subset_t *scaled_font_subset;
  58.     cairo_scaled_font_t        *type1_scaled_font;
  59.  
  60.     cairo_array_t contents;
  61.  
  62.     double x_min, y_min, x_max, y_max;
  63.  
  64.     const char    *data;
  65.     unsigned long  header_size;
  66.     unsigned long  data_size;
  67.     unsigned long  trailer_size;
  68.     int            bbox_position;
  69.     int            bbox_max_chars;
  70.  
  71.     cairo_output_stream_t *output;
  72.  
  73.     unsigned short eexec_key;
  74.     cairo_bool_t hex_encode;
  75.     int hex_column;
  76. } cairo_type1_font_t;
  77.  
  78. static cairo_status_t
  79. cairo_type1_font_create (cairo_scaled_font_subset_t  *scaled_font_subset,
  80.                          cairo_type1_font_t         **subset_return,
  81.                          cairo_bool_t                 hex_encode)
  82. {
  83.     cairo_type1_font_t *font;
  84.     cairo_font_face_t *font_face;
  85.     cairo_matrix_t font_matrix;
  86.     cairo_matrix_t ctm;
  87.     cairo_font_options_t font_options;
  88.     cairo_status_t status;
  89.  
  90.     font = calloc (1, sizeof (cairo_type1_font_t));
  91.     if (unlikely (font == NULL))
  92.         return _cairo_error (CAIRO_STATUS_NO_MEMORY);
  93.  
  94.     font->widths = calloc (scaled_font_subset->num_glyphs, sizeof (int));
  95.     if (unlikely (font->widths == NULL)) {
  96.         free (font);
  97.         return _cairo_error (CAIRO_STATUS_NO_MEMORY);
  98.     }
  99.  
  100.     font->scaled_font_subset = scaled_font_subset;
  101.     font->hex_encode = hex_encode;
  102.  
  103.     font_face = cairo_scaled_font_get_font_face (scaled_font_subset->scaled_font);
  104.  
  105.     cairo_matrix_init_scale (&font_matrix, 1000, -1000);
  106.     cairo_matrix_init_identity (&ctm);
  107.  
  108.     _cairo_font_options_init_default (&font_options);
  109.     cairo_font_options_set_hint_style (&font_options, CAIRO_HINT_STYLE_NONE);
  110.     cairo_font_options_set_hint_metrics (&font_options, CAIRO_HINT_METRICS_OFF);
  111.  
  112.     font->type1_scaled_font = cairo_scaled_font_create (font_face,
  113.                                                         &font_matrix,
  114.                                                         &ctm,
  115.                                                         &font_options);
  116.     status = font->type1_scaled_font->status;
  117.     if (unlikely (status))
  118.         goto fail;
  119.  
  120.     _cairo_array_init (&font->contents, sizeof (unsigned char));
  121.     font->output = NULL;
  122.  
  123.     *subset_return = font;
  124.  
  125.     return CAIRO_STATUS_SUCCESS;
  126.  
  127. fail:
  128.     free (font->widths);
  129.     free (font);
  130.  
  131.     return status;
  132. }
  133.  
  134. /* Charstring commands. If the high byte is 0 the command is encoded
  135.  * with a single byte. */
  136. #define CHARSTRING_sbw        0x0c07
  137. #define CHARSTRING_rmoveto    0x0015
  138. #define CHARSTRING_rlineto    0x0005
  139. #define CHARSTRING_rcurveto   0x0008
  140. #define CHARSTRING_closepath  0x0009
  141. #define CHARSTRING_endchar    0x000e
  142.  
  143. /* Before calling this function, the caller must allocate sufficient
  144.  * space in data (see _cairo_array_grow_by). The maximum number of
  145.  * bytes that will be used is 2.
  146.  */
  147. static void
  148. charstring_encode_command (cairo_array_t *data, int command)
  149. {
  150.     cairo_status_t status;
  151.     unsigned int orig_size;
  152.     unsigned char buf[5];
  153.     unsigned char *p = buf;
  154.  
  155.     if (command & 0xff00)
  156.         *p++ = command >> 8;
  157.     *p++ = command & 0x00ff;
  158.  
  159.     /* Ensure the array doesn't grow, which allows this function to
  160.      * have no possibility of failure. */
  161.     orig_size = _cairo_array_size (data);
  162.     status = _cairo_array_append_multiple (data, buf, p - buf);
  163.  
  164.     assert (status == CAIRO_STATUS_SUCCESS);
  165.     assert (_cairo_array_size (data) == orig_size);
  166. }
  167.  
  168. /* Before calling this function, the caller must allocate sufficient
  169.  * space in data (see _cairo_array_grow_by). The maximum number of
  170.  * bytes that will be used is 5.
  171.  */
  172. static void
  173. charstring_encode_integer (cairo_array_t *data,
  174.                            int i,
  175.                            cairo_charstring_type_t type)
  176. {
  177.     cairo_status_t status;
  178.     unsigned int orig_size;
  179.     unsigned char buf[10];
  180.     unsigned char *p = buf;
  181.  
  182.     if (i >= -107 && i <= 107) {
  183.         *p++ = i + 139;
  184.     } else if (i >= 108 && i <= 1131) {
  185.         i -= 108;
  186.         *p++ = (i >> 8)+ 247;
  187.         *p++ = i & 0xff;
  188.     } else if (i >= -1131 && i <= -108) {
  189.         i = -i - 108;
  190.         *p++ = (i >> 8)+ 251;
  191.         *p++ = i & 0xff;
  192.     } else {
  193.         if (type == CAIRO_CHARSTRING_TYPE1) {
  194.             *p++ = 0xff;
  195.             *p++ = i >> 24;
  196.             *p++ = (i >> 16) & 0xff;
  197.             *p++ = (i >> 8)  & 0xff;
  198.             *p++ = i & 0xff;
  199.         } else {
  200.             *p++ = 0xff;
  201.             *p++ = (i >> 8)  & 0xff;
  202.             *p++ = i & 0xff;
  203.             *p++ = 0;
  204.             *p++ = 0;
  205.         }
  206.     }
  207.  
  208.     /* Ensure the array doesn't grow, which allows this function to
  209.      * have no possibility of failure. */
  210.     orig_size = _cairo_array_size (data);
  211.     status = _cairo_array_append_multiple (data, buf, p - buf);
  212.  
  213.     assert (status == CAIRO_STATUS_SUCCESS);
  214.     assert (_cairo_array_size (data) == orig_size);
  215. }
  216.  
  217. typedef struct _ps_path_info {
  218.     cairo_array_t *data;
  219.     int current_x, current_y;
  220.     cairo_charstring_type_t type;
  221. } t1_path_info_t;
  222.  
  223. static cairo_status_t
  224. _charstring_move_to (void                   *closure,
  225.                      const cairo_point_t    *point)
  226. {
  227.     t1_path_info_t *path_info = (t1_path_info_t *) closure;
  228.     int dx, dy;
  229.     cairo_status_t status;
  230.  
  231.     status = _cairo_array_grow_by (path_info->data, 12);
  232.     if (unlikely (status))
  233.         return status;
  234.  
  235.     dx = _cairo_fixed_integer_part (point->x) - path_info->current_x;
  236.     dy = _cairo_fixed_integer_part (point->y) - path_info->current_y;
  237.     charstring_encode_integer (path_info->data, dx, path_info->type);
  238.     charstring_encode_integer (path_info->data, dy, path_info->type);
  239.     path_info->current_x += dx;
  240.     path_info->current_y += dy;
  241.  
  242.     charstring_encode_command (path_info->data, CHARSTRING_rmoveto);
  243.  
  244.     return CAIRO_STATUS_SUCCESS;
  245. }
  246.  
  247. static cairo_status_t
  248. _charstring_line_to (void                   *closure,
  249.                      const cairo_point_t    *point)
  250. {
  251.     t1_path_info_t *path_info = (t1_path_info_t *) closure;
  252.     int dx, dy;
  253.     cairo_status_t status;
  254.  
  255.     status = _cairo_array_grow_by (path_info->data, 12);
  256.     if (unlikely (status))
  257.         return status;
  258.  
  259.     dx = _cairo_fixed_integer_part (point->x) - path_info->current_x;
  260.     dy = _cairo_fixed_integer_part (point->y) - path_info->current_y;
  261.     charstring_encode_integer (path_info->data, dx, path_info->type);
  262.     charstring_encode_integer (path_info->data, dy, path_info->type);
  263.     path_info->current_x += dx;
  264.     path_info->current_y += dy;
  265.  
  266.     charstring_encode_command (path_info->data, CHARSTRING_rlineto);
  267.  
  268.     return CAIRO_STATUS_SUCCESS;
  269. }
  270.  
  271. static cairo_status_t
  272. _charstring_curve_to (void                  *closure,
  273.                       const cairo_point_t   *point1,
  274.                       const cairo_point_t   *point2,
  275.                       const cairo_point_t   *point3)
  276. {
  277.     t1_path_info_t *path_info = (t1_path_info_t *) closure;
  278.     int dx1, dy1, dx2, dy2, dx3, dy3;
  279.     cairo_status_t status;
  280.  
  281.     status = _cairo_array_grow_by (path_info->data, 32);
  282.     if (unlikely (status))
  283.         return status;
  284.  
  285.     dx1 = _cairo_fixed_integer_part (point1->x) - path_info->current_x;
  286.     dy1 = _cairo_fixed_integer_part (point1->y) - path_info->current_y;
  287.     dx2 = _cairo_fixed_integer_part (point2->x) - path_info->current_x - dx1;
  288.     dy2 = _cairo_fixed_integer_part (point2->y) - path_info->current_y - dy1;
  289.     dx3 = _cairo_fixed_integer_part (point3->x) - path_info->current_x - dx1 - dx2;
  290.     dy3 = _cairo_fixed_integer_part (point3->y) - path_info->current_y - dy1 - dy2;
  291.     charstring_encode_integer (path_info->data, dx1, path_info->type);
  292.     charstring_encode_integer (path_info->data, dy1, path_info->type);
  293.     charstring_encode_integer (path_info->data, dx2, path_info->type);
  294.     charstring_encode_integer (path_info->data, dy2, path_info->type);
  295.     charstring_encode_integer (path_info->data, dx3, path_info->type);
  296.     charstring_encode_integer (path_info->data, dy3, path_info->type);
  297.     path_info->current_x += dx1 + dx2 + dx3;
  298.     path_info->current_y += dy1 + dy2 + dy3;
  299.     charstring_encode_command (path_info->data, CHARSTRING_rcurveto);
  300.  
  301.     return CAIRO_STATUS_SUCCESS;
  302. }
  303.  
  304. static cairo_status_t
  305. _charstring_close_path (void *closure)
  306. {
  307.     cairo_status_t status;
  308.     t1_path_info_t *path_info = (t1_path_info_t *) closure;
  309.  
  310.     if (path_info->type == CAIRO_CHARSTRING_TYPE2)
  311.         return CAIRO_STATUS_SUCCESS;
  312.  
  313.     status = _cairo_array_grow_by (path_info->data, 2);
  314.     if (unlikely (status))
  315.         return status;
  316.  
  317.     charstring_encode_command (path_info->data, CHARSTRING_closepath);
  318.  
  319.     return CAIRO_STATUS_SUCCESS;
  320. }
  321.  
  322. static void
  323. charstring_encrypt (cairo_array_t *data)
  324. {
  325.     unsigned char *d, *end;
  326.     uint16_t c, p, r;
  327.  
  328.     r = CAIRO_TYPE1_CHARSTRING_KEY;
  329.     d = (unsigned char *) _cairo_array_index (data, 0);
  330.     end = d + _cairo_array_num_elements (data);
  331.     while (d < end) {
  332.         p = *d;
  333.         c = p ^ (r >> 8);
  334.         r = (c + r) * CAIRO_TYPE1_ENCRYPT_C1 + CAIRO_TYPE1_ENCRYPT_C2;
  335.         *d++ = c;
  336.     }
  337. }
  338.  
  339. static cairo_int_status_t
  340. cairo_type1_font_create_charstring (cairo_type1_font_t      *font,
  341.                                     int                      subset_index,
  342.                                     int                      glyph_index,
  343.                                     cairo_charstring_type_t  type,
  344.                                     cairo_array_t           *data)
  345. {
  346.     cairo_int_status_t status;
  347.     cairo_scaled_glyph_t *scaled_glyph;
  348.     t1_path_info_t path_info;
  349.     cairo_text_extents_t *metrics;
  350.     cairo_bool_t emit_path = TRUE;
  351.  
  352.     /* This call may return CAIRO_INT_STATUS_UNSUPPORTED for bitmap fonts. */
  353.     status = _cairo_scaled_glyph_lookup (font->type1_scaled_font,
  354.                                          glyph_index,
  355.                                          CAIRO_SCALED_GLYPH_INFO_METRICS|
  356.                                          CAIRO_SCALED_GLYPH_INFO_PATH,
  357.                                          &scaled_glyph);
  358.  
  359.     /* It is ok for the .notdef glyph to not have a path available. We
  360.      * just need the metrics to emit an empty glyph.  */
  361.     if (glyph_index == 0 && status == CAIRO_INT_STATUS_UNSUPPORTED) {
  362.         emit_path = FALSE;
  363.         status = _cairo_scaled_glyph_lookup (font->type1_scaled_font,
  364.                                              glyph_index,
  365.                                              CAIRO_SCALED_GLYPH_INFO_METRICS,
  366.                                              &scaled_glyph);
  367.     }
  368.     if (unlikely (status))
  369.         return status;
  370.  
  371.     metrics = &scaled_glyph->metrics;
  372.     if (subset_index == 0) {
  373.         font->x_min = metrics->x_bearing;
  374.         font->y_min = metrics->y_bearing;
  375.         font->x_max = metrics->x_bearing + metrics->width;
  376.         font->y_max = metrics->y_bearing + metrics->height;
  377.     } else {
  378.         if (metrics->x_bearing < font->x_min)
  379.             font->x_min = metrics->x_bearing;
  380.         if (metrics->y_bearing < font->y_min)
  381.             font->y_min = metrics->y_bearing;
  382.         if (metrics->x_bearing + metrics->width > font->x_max)
  383.             font->x_max = metrics->x_bearing + metrics->width;
  384.         if (metrics->y_bearing + metrics->height > font->y_max)
  385.             font->y_max = metrics->y_bearing + metrics->height;
  386.     }
  387.     font->widths[subset_index] = metrics->x_advance;
  388.  
  389.     status = _cairo_array_grow_by (data, 30);
  390.     if (unlikely (status))
  391.         return status;
  392.  
  393.     if (type == CAIRO_CHARSTRING_TYPE1) {
  394.         charstring_encode_integer (data, (int) scaled_glyph->metrics.x_bearing, type);
  395.         charstring_encode_integer (data, (int) scaled_glyph->metrics.y_bearing, type);
  396.         charstring_encode_integer (data, (int) scaled_glyph->metrics.x_advance, type);
  397.         charstring_encode_integer (data, (int) scaled_glyph->metrics.y_advance, type);
  398.         charstring_encode_command (data, CHARSTRING_sbw);
  399.  
  400.         path_info.current_x = (int) scaled_glyph->metrics.x_bearing;
  401.         path_info.current_y = (int) scaled_glyph->metrics.y_bearing;
  402.     } else {
  403.         charstring_encode_integer (data, (int) scaled_glyph->metrics.x_advance, type);
  404.  
  405.         path_info.current_x = 0;
  406.         path_info.current_y = 0;
  407.     }
  408.     path_info.data = data;
  409.     path_info.type = type;
  410.     if (emit_path) {
  411.         status = _cairo_path_fixed_interpret (scaled_glyph->path,
  412.                                               _charstring_move_to,
  413.                                               _charstring_line_to,
  414.                                               _charstring_curve_to,
  415.                                               _charstring_close_path,
  416.                                               &path_info);
  417.         if (unlikely (status))
  418.             return status;
  419.     }
  420.  
  421.     status = _cairo_array_grow_by (data, 1);
  422.     if (unlikely (status))
  423.         return status;
  424.     charstring_encode_command (path_info.data, CHARSTRING_endchar);
  425.  
  426.     return CAIRO_STATUS_SUCCESS;
  427. }
  428.  
  429. static cairo_int_status_t
  430. cairo_type1_font_write_charstrings (cairo_type1_font_t    *font,
  431.                                     cairo_output_stream_t *encrypted_output)
  432. {
  433.     cairo_status_t status;
  434.     unsigned char zeros[] = { 0, 0, 0, 0 };
  435.     cairo_array_t data;
  436.     unsigned int i;
  437.     int length;
  438.  
  439.     _cairo_array_init (&data, sizeof (unsigned char));
  440.     status = _cairo_array_grow_by (&data, 1024);
  441.     if (unlikely (status))
  442.         goto fail;
  443.  
  444.     _cairo_output_stream_printf (encrypted_output,
  445.                                  "2 index /CharStrings %d dict dup begin\n",
  446.                                  font->scaled_font_subset->num_glyphs + 1);
  447.  
  448.     _cairo_scaled_font_freeze_cache (font->type1_scaled_font);
  449.     for (i = 0; i < font->scaled_font_subset->num_glyphs; i++) {
  450.         _cairo_array_truncate (&data, 0);
  451.         /* four "random" bytes required by encryption algorithm */
  452.         status = _cairo_array_append_multiple (&data, zeros, 4);
  453.         if (unlikely (status))
  454.             break;
  455.  
  456.         status = cairo_type1_font_create_charstring (font, i,
  457.                                                      font->scaled_font_subset->glyphs[i],
  458.                                                      CAIRO_CHARSTRING_TYPE1,
  459.                                                      &data);
  460.         if (unlikely (status))
  461.             break;
  462.  
  463.         charstring_encrypt (&data);
  464.         length = _cairo_array_num_elements (&data);
  465.         if (font->scaled_font_subset->glyph_names != NULL) {
  466.             _cairo_output_stream_printf (encrypted_output, "/%s %d RD ",
  467.                                          font->scaled_font_subset->glyph_names[i],
  468.                                          length);
  469.         } else if (i == 0) {
  470.             _cairo_output_stream_printf (encrypted_output, "/.notdef %d RD ", length);
  471.         } else {
  472.             _cairo_output_stream_printf (encrypted_output, "/g%d %d RD ", i, length);
  473.         }
  474.         _cairo_output_stream_write (encrypted_output,
  475.                                     _cairo_array_index (&data, 0),
  476.                                     length);
  477.         _cairo_output_stream_printf (encrypted_output, " ND\n");
  478.     }
  479.     _cairo_scaled_font_thaw_cache (font->type1_scaled_font);
  480.  
  481. fail:
  482.     _cairo_array_fini (&data);
  483.     return status;
  484. }
  485.  
  486. static void
  487. cairo_type1_font_write_header (cairo_type1_font_t *font,
  488.                                const char         *name)
  489. {
  490.     unsigned int i;
  491.     const char spaces[50] = "                                                  ";
  492.  
  493.     _cairo_output_stream_printf (font->output,
  494.                                  "%%!FontType1-1.1 %s 1.0\n"
  495.                                  "11 dict begin\n"
  496.                                  "/FontName /%s def\n"
  497.                                  "/PaintType 0 def\n"
  498.                                  "/FontType 1 def\n"
  499.                                   "/FontMatrix [0.001 0 0 0.001 0 0] readonly def\n",
  500.                                  name,
  501.                                  name);
  502.  
  503.     /* We don't know the bbox values until after the charstrings have
  504.      * been generated.  Reserve some space and fill in the bbox
  505.      * later. */
  506.  
  507.     /* Worst case for four signed ints with spaces between each number */
  508.     font->bbox_max_chars = 50;
  509.  
  510.     _cairo_output_stream_printf (font->output, "/FontBBox {");
  511.     font->bbox_position = _cairo_output_stream_get_position (font->output);
  512.     _cairo_output_stream_write (font->output, spaces, font->bbox_max_chars);
  513.  
  514.     _cairo_output_stream_printf (font->output,
  515.                                  "} readonly def\n"
  516.                                  "/Encoding 256 array\n"
  517.                                  "0 1 255 {1 index exch /.notdef put} for\n");
  518.     if (font->scaled_font_subset->is_latin) {
  519.         for (i = 1; i < 256; i++) {
  520.             int subset_glyph = font->scaled_font_subset->latin_to_subset_glyph_index[i];
  521.  
  522.             if (subset_glyph > 0) {
  523.                 if (font->scaled_font_subset->glyph_names != NULL) {
  524.                     _cairo_output_stream_printf (font->output, "dup %d /%s put\n",
  525.                                                  i, font->scaled_font_subset->glyph_names[subset_glyph]);
  526.                 } else {
  527.                     _cairo_output_stream_printf (font->output, "dup %d /g%d put\n", i, subset_glyph);
  528.                 }
  529.             }
  530.         }
  531.     } else {
  532.         for (i = 1; i < font->scaled_font_subset->num_glyphs; i++) {
  533.             if (font->scaled_font_subset->glyph_names != NULL) {
  534.                 _cairo_output_stream_printf (font->output, "dup %d /%s put\n",
  535.                                              i, font->scaled_font_subset->glyph_names[i]);
  536.             } else {
  537.                 _cairo_output_stream_printf (font->output, "dup %d /g%d put\n", i, i);
  538.             }
  539.         }
  540.     }
  541.     _cairo_output_stream_printf (font->output,
  542.                                  "readonly def\n"
  543.                                  "currentdict end\n"
  544.                                  "currentfile eexec\n");
  545. }
  546.  
  547. static cairo_status_t
  548. cairo_type1_write_stream_encrypted (void                *closure,
  549.                                     const unsigned char *data,
  550.                                     unsigned int         length)
  551. {
  552.     const unsigned char *in, *end;
  553.     uint16_t c, p;
  554.     static const char hex_digits[16] = "0123456789abcdef";
  555.     char digits[3];
  556.     cairo_type1_font_t *font = closure;
  557.  
  558.     in = (const unsigned char *) data;
  559.     end = (const unsigned char *) data + length;
  560.     while (in < end) {
  561.         p = *in++;
  562.         c = p ^ (font->eexec_key >> 8);
  563.         font->eexec_key = (c + font->eexec_key) * CAIRO_TYPE1_ENCRYPT_C1 + CAIRO_TYPE1_ENCRYPT_C2;
  564.  
  565.         if (font->hex_encode) {
  566.             digits[0] = hex_digits[c >> 4];
  567.             digits[1] = hex_digits[c & 0x0f];
  568.             digits[2] = '\n';
  569.             font->hex_column += 2;
  570.  
  571.             if (font->hex_column == 78) {
  572.                 _cairo_output_stream_write (font->output, digits, 3);
  573.                 font->hex_column = 0;
  574.             } else {
  575.                 _cairo_output_stream_write (font->output, digits, 2);
  576.             }
  577.         } else {
  578.             digits[0] = c;
  579.             _cairo_output_stream_write (font->output, digits, 1);
  580.         }
  581.     }
  582.  
  583.     return CAIRO_STATUS_SUCCESS;
  584. }
  585.  
  586. static cairo_int_status_t
  587. cairo_type1_font_write_private_dict (cairo_type1_font_t *font,
  588.                                      const char         *name)
  589. {
  590.     cairo_int_status_t status;
  591.     cairo_status_t status2;
  592.     cairo_output_stream_t *encrypted_output;
  593.  
  594.     font->eexec_key = CAIRO_TYPE1_PRIVATE_DICT_KEY;
  595.     font->hex_column = 0;
  596.     encrypted_output = _cairo_output_stream_create (
  597.         cairo_type1_write_stream_encrypted,
  598.         NULL,
  599.         font);
  600.     if (_cairo_output_stream_get_status (encrypted_output))
  601.         return  _cairo_output_stream_destroy (encrypted_output);
  602.  
  603.     /* Note: the first four spaces at the start of this private dict
  604.      * are the four "random" bytes of plaintext required by the
  605.      * encryption algorithm */
  606.     _cairo_output_stream_printf (encrypted_output,
  607.                                  "    dup /Private 9 dict dup begin\n"
  608.                                  "/RD {string currentfile exch readstring pop}"
  609.                                  " bind executeonly def\n"
  610.                                  "/ND {noaccess def} executeonly def\n"
  611.                                  "/NP {noaccess put} executeonly def\n"
  612.                                  "/BlueValues [] def\n"
  613.                                  "/MinFeature {16 16} def\n"
  614.                                  "/lenIV 4 def\n"
  615.                                  "/password 5839 def\n");
  616.  
  617.     status = cairo_type1_font_write_charstrings (font, encrypted_output);
  618.     if (unlikely (status))
  619.         goto fail;
  620.  
  621.     _cairo_output_stream_printf (encrypted_output,
  622.                                  "end\n"
  623.                                  "end\n"
  624.                                  "readonly put\n"
  625.                                  "noaccess put\n"
  626.                                  "dup /FontName get exch definefont pop\n"
  627.                                  "mark currentfile closefile\n");
  628.  
  629.   fail:
  630.     status2 = _cairo_output_stream_destroy (encrypted_output);
  631.     if (status == CAIRO_INT_STATUS_SUCCESS)
  632.         status = status2;
  633.  
  634.     return status;
  635. }
  636.  
  637. static void
  638. cairo_type1_font_write_trailer(cairo_type1_font_t *font)
  639. {
  640.     int i;
  641.     static const char zeros[65] =
  642.         "0000000000000000000000000000000000000000000000000000000000000000\n";
  643.  
  644.     for (i = 0; i < 8; i++)
  645.         _cairo_output_stream_write (font->output, zeros, sizeof zeros);
  646.  
  647.     _cairo_output_stream_printf (font->output, "cleartomark\n");
  648. }
  649.  
  650. static cairo_status_t
  651. cairo_type1_write_stream (void *closure,
  652.                          const unsigned char *data,
  653.                          unsigned int length)
  654. {
  655.     cairo_type1_font_t *font = closure;
  656.  
  657.     return _cairo_array_append_multiple (&font->contents, data, length);
  658. }
  659.  
  660. static cairo_int_status_t
  661. cairo_type1_font_write (cairo_type1_font_t *font,
  662.                         const char *name)
  663. {
  664.     cairo_int_status_t status;
  665.  
  666.     cairo_type1_font_write_header (font, name);
  667.     font->header_size = _cairo_output_stream_get_position (font->output);
  668.  
  669.     status = cairo_type1_font_write_private_dict (font, name);
  670.     if (unlikely (status))
  671.         return status;
  672.  
  673.     font->data_size = _cairo_output_stream_get_position (font->output) -
  674.         font->header_size;
  675.  
  676.     cairo_type1_font_write_trailer (font);
  677.     font->trailer_size =
  678.         _cairo_output_stream_get_position (font->output) -
  679.         font->header_size - font->data_size;
  680.  
  681.     return CAIRO_STATUS_SUCCESS;
  682. }
  683.  
  684. static cairo_int_status_t
  685. cairo_type1_font_generate (cairo_type1_font_t *font, const char *name)
  686. {
  687.     cairo_int_status_t status;
  688.  
  689.     status = _cairo_array_grow_by (&font->contents, 4096);
  690.     if (unlikely (status))
  691.         return status;
  692.  
  693.     font->output = _cairo_output_stream_create (cairo_type1_write_stream, NULL, font);
  694.     if (_cairo_output_stream_get_status (font->output))
  695.         return _cairo_output_stream_destroy (font->output);
  696.  
  697.     status = cairo_type1_font_write (font, name);
  698.     if (unlikely (status))
  699.         return status;
  700.  
  701.     font->data = _cairo_array_index (&font->contents, 0);
  702.  
  703.     return CAIRO_STATUS_SUCCESS;
  704. }
  705.  
  706. static cairo_status_t
  707. cairo_type1_font_destroy (cairo_type1_font_t *font)
  708. {
  709.     cairo_status_t status = CAIRO_STATUS_SUCCESS;
  710.  
  711.     free (font->widths);
  712.     cairo_scaled_font_destroy (font->type1_scaled_font);
  713.     _cairo_array_fini (&font->contents);
  714.     if (font->output)
  715.         status = _cairo_output_stream_destroy (font->output);
  716.     free (font);
  717.  
  718.     return status;
  719. }
  720.  
  721. static cairo_status_t
  722. _cairo_type1_fallback_init_internal (cairo_type1_subset_t       *type1_subset,
  723.                                      const char                 *name,
  724.                                      cairo_scaled_font_subset_t *scaled_font_subset,
  725.                                      cairo_bool_t                hex_encode)
  726. {
  727.     cairo_type1_font_t *font;
  728.     cairo_status_t status;
  729.     unsigned long length;
  730.     unsigned int i, len;
  731.  
  732.     status = cairo_type1_font_create (scaled_font_subset, &font, hex_encode);
  733.     if (unlikely (status))
  734.         return status;
  735.  
  736.     status = cairo_type1_font_generate (font, name);
  737.     if (unlikely (status))
  738.         goto fail1;
  739.  
  740.     type1_subset->base_font = strdup (name);
  741.     if (unlikely (type1_subset->base_font == NULL)) {
  742.         status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
  743.         goto fail1;
  744.     }
  745.  
  746.     type1_subset->widths = calloc (sizeof (double), font->scaled_font_subset->num_glyphs);
  747.     if (unlikely (type1_subset->widths == NULL)) {
  748.         status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
  749.         goto fail2;
  750.     }
  751.     for (i = 0; i < font->scaled_font_subset->num_glyphs; i++)
  752.         type1_subset->widths[i] = (double)font->widths[i]/1000;
  753.  
  754.     type1_subset->x_min   = (double)font->x_min/1000;
  755.     type1_subset->y_min   = (double)font->y_min/1000;
  756.     type1_subset->x_max   = (double)font->x_max/1000;
  757.     type1_subset->y_max   = (double)font->y_max/1000;
  758.     type1_subset->ascent  = (double)font->y_max/1000;
  759.     type1_subset->descent = (double)font->y_min/1000;
  760.  
  761.     length = font->header_size + font->data_size +
  762.         font->trailer_size;
  763.     type1_subset->data = malloc (length);
  764.     if (unlikely (type1_subset->data == NULL)) {
  765.         status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
  766.         goto fail3;
  767.     }
  768.     memcpy (type1_subset->data,
  769.             _cairo_array_index (&font->contents, 0), length);
  770.  
  771.     len = snprintf(type1_subset->data + font->bbox_position,
  772.                    font->bbox_max_chars,
  773.                    "%d %d %d %d",
  774.                    (int)font->x_min,
  775.                    (int)font->y_min,
  776.                    (int)font->x_max,
  777.                    (int)font->y_max);
  778.     type1_subset->data[font->bbox_position + len] = ' ';
  779.  
  780.     type1_subset->header_length = font->header_size;
  781.     type1_subset->data_length = font->data_size;
  782.     type1_subset->trailer_length = font->trailer_size;
  783.  
  784.     return cairo_type1_font_destroy (font);
  785.  
  786.  fail3:
  787.     free (type1_subset->widths);
  788.  fail2:
  789.     free (type1_subset->base_font);
  790.  fail1:
  791.     /* status is already set, ignore further errors */
  792.     cairo_type1_font_destroy (font);
  793.  
  794.     return status;
  795. }
  796.  
  797. cairo_status_t
  798. _cairo_type1_fallback_init_binary (cairo_type1_subset_t       *type1_subset,
  799.                                    const char                 *name,
  800.                                    cairo_scaled_font_subset_t *scaled_font_subset)
  801. {
  802.     return _cairo_type1_fallback_init_internal (type1_subset,
  803.                                                 name,
  804.                                                 scaled_font_subset, FALSE);
  805. }
  806.  
  807. cairo_status_t
  808. _cairo_type1_fallback_init_hex (cairo_type1_subset_t       *type1_subset,
  809.                                 const char                 *name,
  810.                                 cairo_scaled_font_subset_t *scaled_font_subset)
  811. {
  812.     return _cairo_type1_fallback_init_internal (type1_subset,
  813.                                                 name,
  814.                                                 scaled_font_subset, TRUE);
  815. }
  816.  
  817. void
  818. _cairo_type1_fallback_fini (cairo_type1_subset_t *subset)
  819. {
  820.     free (subset->base_font);
  821.     free (subset->widths);
  822.     free (subset->data);
  823. }
  824.  
  825. cairo_status_t
  826. _cairo_type2_charstrings_init (cairo_type2_charstrings_t *type2_subset,
  827.                                cairo_scaled_font_subset_t *scaled_font_subset)
  828. {
  829.     cairo_type1_font_t *font;
  830.     cairo_status_t status;
  831.     unsigned int i;
  832.     cairo_array_t charstring;
  833.  
  834.     status = cairo_type1_font_create (scaled_font_subset, &font, FALSE);
  835.     if (unlikely (status))
  836.         return status;
  837.  
  838.     _cairo_array_init (&type2_subset->charstrings, sizeof (cairo_array_t));
  839.  
  840.     type2_subset->widths = calloc (sizeof (int), font->scaled_font_subset->num_glyphs);
  841.     if (unlikely (type2_subset->widths == NULL)) {
  842.         status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
  843.         goto fail1;
  844.     }
  845.  
  846.     _cairo_scaled_font_freeze_cache (font->type1_scaled_font);
  847.     for (i = 0; i < font->scaled_font_subset->num_glyphs; i++) {
  848.         _cairo_array_init (&charstring, sizeof (unsigned char));
  849.         status = _cairo_array_grow_by (&charstring, 32);
  850.         if (unlikely (status))
  851.             goto fail2;
  852.  
  853.         status = cairo_type1_font_create_charstring (font, i,
  854.                                                      font->scaled_font_subset->glyphs[i],
  855.                                                      CAIRO_CHARSTRING_TYPE2,
  856.                                                      &charstring);
  857.         if (unlikely (status))
  858.             goto fail2;
  859.  
  860.         status = _cairo_array_append (&type2_subset->charstrings, &charstring);
  861.         if (unlikely (status))
  862.             goto fail2;
  863.     }
  864.     _cairo_scaled_font_thaw_cache (font->type1_scaled_font);
  865.  
  866.     for (i = 0; i < font->scaled_font_subset->num_glyphs; i++)
  867.         type2_subset->widths[i] = font->widths[i];
  868.  
  869.     type2_subset->x_min   = (int) font->x_min;
  870.     type2_subset->y_min   = (int) font->y_min;
  871.     type2_subset->x_max   = (int) font->x_max;
  872.     type2_subset->y_max   = (int) font->y_max;
  873.     type2_subset->ascent  = (int) font->y_max;
  874.     type2_subset->descent = (int) font->y_min;
  875.  
  876.     return cairo_type1_font_destroy (font);
  877.  
  878. fail2:
  879.     _cairo_scaled_font_thaw_cache (font->type1_scaled_font);
  880.     _cairo_array_fini (&charstring);
  881.     _cairo_type2_charstrings_fini (type2_subset);
  882. fail1:
  883.     cairo_type1_font_destroy (font);
  884.     return status;
  885. }
  886.  
  887. void
  888. _cairo_type2_charstrings_fini (cairo_type2_charstrings_t *type2_subset)
  889. {
  890.     unsigned int i, num_charstrings;
  891.     cairo_array_t *charstring;
  892.  
  893.     num_charstrings = _cairo_array_num_elements (&type2_subset->charstrings);
  894.     for (i = 0; i < num_charstrings; i++) {
  895.         charstring = _cairo_array_index (&type2_subset->charstrings, i);
  896.         _cairo_array_fini (charstring);
  897.     }
  898.     _cairo_array_fini (&type2_subset->charstrings);
  899.  
  900.     free (type2_subset->widths);
  901. }
  902.  
  903. #endif /* CAIRO_HAS_FONT_SUBSET */
  904.