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

       1                 : /* cairo - a vector graphics library with display and print output
       2                 :  *
       3                 :  * Copyright © 2006 Red Hat, Inc
       4                 :  *
       5                 :  * This library is free software; you can redistribute it and/or
       6                 :  * modify it either under the terms of the GNU Lesser General Public
       7                 :  * License version 2.1 as published by the Free Software Foundation
       8                 :  * (the "LGPL") or, at your option, under the terms of the Mozilla
       9                 :  * Public License Version 1.1 (the "MPL"). If you do not alter this
      10                 :  * notice, a recipient may use your version of this file under either
      11                 :  * the MPL or the LGPL.
      12                 :  *
      13                 :  * You should have received a copy of the LGPL along with this library
      14                 :  * in the file COPYING-LGPL-2.1; if not, write to the Free Software
      15                 :  * Foundation, Inc., 51 Franklin Street, Suite 500, Boston, MA 02110-1335, USA
      16                 :  * You should have received a copy of the MPL along with this library
      17                 :  * in the file COPYING-MPL-1.1
      18                 :  *
      19                 :  * The contents of this file are subject to the Mozilla Public License
      20                 :  * Version 1.1 (the "License"); you may not use this file except in
      21                 :  * compliance with the License. You may obtain a copy of the License at
      22                 :  * http://www.mozilla.org/MPL/
      23                 :  *
      24                 :  * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
      25                 :  * OF ANY KIND, either express or implied. See the LGPL or the MPL for
      26                 :  * the specific language governing rights and limitations.
      27                 :  *
      28                 :  * The Original Code is the cairo graphics library.
      29                 :  *
      30                 :  * The Initial Developer of the Original Code is Red Hat, Inc.
      31                 :  *
      32                 :  * Contributor(s):
      33                 :  *      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.7