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

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

Generated by: LCOV version 1.13