2 * Copyright © 2008 Chris Wilson <chris@chris-wilson.co.uk>
4 * This library is free software; you can redistribute it and/or
5 * modify it either under the terms of the GNU Lesser General Public
6 * License version 2.1 as published by the Free Software Foundation
7 * (the "LGPL") or, at your option, under the terms of the Mozilla
8 * Public License Version 1.1 (the "MPL"). If you do not alter this
9 * notice, a recipient may use your version of this file under either
10 * the MPL or the LGPL.
12 * You should have received a copy of the LGPL along with this library
13 * in the file COPYING-LGPL-2.1; if not, write to the Free Software
14 * Foundation, Inc., 51 Franklin Street, Suite 500, Boston, MA 02110-1335, USA
15 * You should have received a copy of the MPL along with this library
16 * in the file COPYING-MPL-1.1
18 * The contents of this file are subject to the Mozilla Public License
19 * Version 1.1 (the "License"); you may not use this file except in
20 * compliance with the License. You may obtain a copy of the License at
21 * http://www.mozilla.org/MPL/
23 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
24 * OF ANY KIND, either express or implied. See the LGPL or the MPL for
25 * the specific language governing rights and limitations.
27 * The Original Code is the cairo graphics library.
29 * The Initial Developer of the Original Code is Chris Wilson.
32 * Chris Wilson <chris@chris-wilson.co.uk>
35 #include "cairo-script-private.h"
38 #include <limits.h> /* INT_MAX */
42 #define CHUNK_SIZE 32768
44 #define OWN_STREAM 0x1
47 csi_file_new (csi_t *ctx,
49 const char *path, const char *mode)
53 file = _csi_slab_alloc (ctx, sizeof (csi_file_t));
55 return _csi_error (CAIRO_STATUS_NO_MEMORY);
57 file->base.type = CSI_OBJECT_TYPE_FILE;
62 file->flags = OWN_STREAM;
63 file->src = fopen (path, mode);
64 if (file->src == NULL) {
65 _csi_slab_free (ctx, file, sizeof (csi_file_t));
66 return _csi_error (CAIRO_STATUS_FILE_NOT_FOUND);
69 file->data = _csi_alloc (ctx, CHUNK_SIZE);
70 if (file->data == NULL) {
71 _csi_slab_free (ctx, file, sizeof (csi_file_t));
72 return _csi_error (CAIRO_STATUS_NO_MEMORY);
74 file->bp = file->data;
77 obj->type = CSI_OBJECT_TYPE_FILE;
78 obj->datum.file = file;
79 return CAIRO_STATUS_SUCCESS;
83 csi_file_new_for_stream (csi_t *ctx,
89 file = _csi_slab_alloc (ctx, sizeof (csi_file_t));
91 return _csi_error (CAIRO_STATUS_NO_MEMORY);
93 file->base.type = CSI_OBJECT_TYPE_FILE;
100 if (file->src == NULL) {
101 _csi_slab_free (ctx, file, sizeof (csi_file_t));
102 return _csi_error (CAIRO_STATUS_FILE_NOT_FOUND);
105 file->data = _csi_alloc (ctx, CHUNK_SIZE);
106 if (file->data == NULL) {
107 _csi_slab_free (ctx, file, sizeof (csi_file_t));
108 return _csi_error (CAIRO_STATUS_NO_MEMORY);
110 file->bp = file->data;
113 obj->type = CSI_OBJECT_TYPE_FILE;
114 obj->datum.file = file;
115 return CAIRO_STATUS_SUCCESS;
119 csi_file_new_for_bytes (csi_t *ctx,
126 file = _csi_slab_alloc (ctx, sizeof (csi_file_t));
128 return _csi_error (CAIRO_STATUS_NO_MEMORY);
130 file->base.type = CSI_OBJECT_TYPE_FILE;
134 file->src = (uint8_t *) bytes;
135 file->data = (uint8_t *) bytes;
136 file->bp = (uint8_t *) bytes;
139 obj->type = CSI_OBJECT_TYPE_FILE;
140 obj->datum.file = file;
141 return CAIRO_STATUS_SUCCESS;
145 csi_file_new_from_string (csi_t *ctx,
151 file = _csi_slab_alloc (ctx, sizeof (csi_file_t));
152 if (_csi_unlikely (file == NULL))
153 return _csi_error (CAIRO_STATUS_NO_MEMORY);
155 file->base.type = CSI_OBJECT_TYPE_FILE;
159 uLongf len = src->deflate;
160 csi_object_t tmp_obj;
161 csi_string_t *tmp_str;
164 status = csi_string_new (ctx, &tmp_obj, NULL, src->deflate);
165 if (_csi_unlikely (status))
168 tmp_str = tmp_obj.datum.string;
169 if (uncompress ((Bytef *) tmp_str->string, &len,
170 (Bytef *) src->string, src->len) != Z_OK)
172 csi_string_free (ctx, tmp_str);
173 _csi_slab_free (ctx, file, sizeof (csi_file_t));
174 return _csi_error (CAIRO_STATUS_NO_MEMORY);
178 file->data = tmp_str->string;
179 file->rem = tmp_str->len;
181 file->src = src; src->base.ref++;
182 file->data = src->string;
183 file->rem = src->len;
186 file->bp = file->data;
188 obj->type = CSI_OBJECT_TYPE_FILE;
189 obj->datum.file = file;
190 return CAIRO_STATUS_SUCCESS;
194 _csi_file_new_filter (csi_t *ctx,
197 const csi_filter_funcs_t *funcs,
201 csi_object_t src_file;
204 file = _csi_slab_alloc (ctx, sizeof (csi_file_t));
206 return _csi_error (CAIRO_STATUS_NO_MEMORY);
208 obj->type = CSI_OBJECT_TYPE_FILE;
209 obj->datum.file = file;
211 file->base.type = CSI_OBJECT_TYPE_FILE;
216 file->filter = funcs;
217 status = csi_object_as_file (ctx, src, &src_file);
219 csi_object_free (ctx, obj);
222 file->src = src_file.datum.file;
224 return CAIRO_STATUS_SUCCESS;
230 csi_file_new_from_stream (csi_t *ctx,
236 obj = (csi_file_t *) _csi_object_new (ctx, CSI_OBJECT_TYPE_FILE);
238 return _csi_error (CAIRO_STATUS_NO_MEMORY);
242 obj->data = _csi_alloc (ctx, CHUNK_SIZE);
243 if (obj->data == NULL) {
244 csi_object_free (&obj->base);
245 return _csi_error (CAIRO_STATUS_UNDEFINED_FILENAME_ERROR);
251 return CAIRO_STATUS_SUCCESS;
254 static csi_object_t *
255 _csi_file_new_from_procedure (csi_t *ctx, csi_object_t *src)
259 obj = (csi_file_t *) _csi_object_new (ctx, CSI_OBJECT_TYPE_FILE);
263 obj->type = PROCEDURE;
264 obj->src = csi_object_reference (src);
271 typedef struct _ascii85_decode_data {
272 uint8_t buf[CHUNK_SIZE];
274 short bytes_available;
276 } _ascii85_decode_data_t;
279 _getc_skip_whitespace (csi_file_t *src)
283 do switch ((c = csi_file_getc (src))) {
300 _ascii85_decode (csi_file_t *file)
302 _ascii85_decode_data_t *data = file->data;
308 data->bp = data->buf;
312 unsigned int v = _getc_skip_whitespace (file->src);
318 } else if (v == '~') {
319 _getc_skip_whitespace (file->src); /* == '>' || IO_ERROR */
322 } else if (v < '!' || v > 'u') {
330 for (i = 1; i < 5; i++) {
331 int c = _getc_skip_whitespace (file->src);
332 if (c == '~') { /* short tuple */
333 _getc_skip_whitespace (file->src); /* == '>' || IO_ERROR */
341 v = v * (85*85*85) + 85*85*85 -1;
344 v = v * (85*85) + 85*85 -1;
348 data->buf[n+2] = v >> 8 & 0xff;
350 data->buf[n+1] = v >> 16 & 0xff;
352 data->buf[n+0] = v >> 24 & 0xff;
353 data->bytes_available = n + i - 1;
361 data->buf[n+0] = v >> 24 & 0xff;
362 data->buf[n+1] = v >> 16 & 0xff;
363 data->buf[n+2] = v >> 8 & 0xff;
364 data->buf[n+3] = v >> 0 & 0xff;
367 } while (n < sizeof (data->buf) && data->eod == FALSE);
369 data->bytes_available = n;
373 _ascii85_decode_getc (csi_file_t *file)
375 _ascii85_decode_data_t *data = file->data;
377 if (data->bytes_available == 0) {
378 _ascii85_decode (file);
380 if (data->bytes_available == 0)
384 data->bytes_available--;
389 _ascii85_decode_putc (csi_file_t *file, int c)
391 _ascii85_decode_data_t *data = file->data;
392 data->bytes_available++;
397 _ascii85_decode_read (csi_file_t *file, uint8_t *buf, int len)
399 _ascii85_decode_data_t *data = file->data;
401 if (data->bytes_available == 0) {
402 _ascii85_decode (file);
404 if (data->bytes_available == 0)
408 if (len > data->bytes_available)
409 len = data->bytes_available;
410 memcpy (buf, data->bp, len);
412 data->bytes_available -= len;
417 csi_file_new_ascii85_decode (csi_t *ctx,
419 csi_dictionary_t *dict,
422 static const csi_filter_funcs_t funcs = {
423 _ascii85_decode_getc,
424 _ascii85_decode_putc,
425 _ascii85_decode_read,
428 _ascii85_decode_data_t *data;
430 data = _csi_alloc0 (ctx, sizeof (_ascii85_decode_data_t));
432 return _csi_error (CAIRO_STATUS_NO_MEMORY);
434 return _csi_file_new_filter (ctx, obj, src, &funcs, data);
440 typedef struct _deflate_decode_data {
441 z_stream zlib_stream;
443 uint8_t in[CHUNK_SIZE];
444 uint8_t out[CHUNK_SIZE];
448 } _deflate_decode_data_t;
451 _deflate_decode (csi_file_t *file)
453 _deflate_decode_data_t *data = file->data;
457 data->zlib_stream.next_out = data->out;
458 data->zlib_stream.avail_out = sizeof (data->out);
461 len = sizeof (data->in);
462 if (data->zlib_stream.avail_in) {
464 data->zlib_stream.next_in,
465 data->zlib_stream.avail_in);
466 len -= data->zlib_stream.avail_in;
467 bp += data->zlib_stream.avail_in;
470 len = csi_file_read (file->src, bp, len);
472 data->zlib_stream.next_in = data->in;
473 data->zlib_stream.avail_in += len;
475 inflate (&data->zlib_stream, len == 0 ? Z_FINISH : Z_NO_FLUSH);
477 data->bytes_available = data->zlib_stream.next_out - data->out;
478 data->bp = data->out;
482 _deflate_decode_getc (csi_file_t *file)
484 _deflate_decode_data_t *data = file->data;
486 if (data->bytes_available == 0) {
487 _deflate_decode (file);
489 if (data->bytes_available == 0)
493 data->bytes_available--;
498 _deflate_decode_putc (csi_file_t *file, int c)
500 _deflate_decode_data_t *data = file->data;
501 data->bytes_available++;
506 _deflate_decode_read (csi_file_t *file, uint8_t *buf, int len)
508 _deflate_decode_data_t *data = file->data;
510 if (data->bytes_available == 0) {
511 _deflate_decode (file);
513 if (data->bytes_available == 0)
517 if (len > (int) data->bytes_available)
518 len = data->bytes_available;
519 memcpy (buf, data->bp, len);
521 data->bytes_available -= len;
526 _deflate_destroy (csi_t *ctx, void *closure)
528 _deflate_decode_data_t *data;
532 inflateEnd (&data->zlib_stream);
534 _csi_free (ctx, data);
538 csi_file_new_deflate_decode (csi_t *ctx,
540 csi_dictionary_t *dict,
543 static const csi_filter_funcs_t funcs = {
544 _deflate_decode_getc,
545 _deflate_decode_putc,
546 _deflate_decode_read,
549 _deflate_decode_data_t *data;
551 data = _csi_alloc (ctx, sizeof (_deflate_decode_data_t));
553 return _csi_error (CAIRO_STATUS_NO_MEMORY);
555 data->zlib_stream.zalloc = Z_NULL;
556 data->zlib_stream.zfree = Z_NULL;
557 data->zlib_stream.opaque = Z_NULL;
558 data->zlib_stream.next_in = data->in;
559 data->zlib_stream.avail_in = 0;
560 data->zlib_stream.next_out = data->out;
561 data->zlib_stream.avail_out = sizeof (data->out);
562 data->bytes_available = 0;
564 if (inflateInit (&data->zlib_stream) != Z_OK) {
565 _csi_free (ctx, data);
566 return _csi_error (CAIRO_STATUS_NO_MEMORY);
569 return _csi_file_new_filter (ctx, obj, src, &funcs, data);
585 return c - 'a' + 0xa;
589 /* Adobe Type 1 Font Format book: p63 */
590 typedef struct _decrypt_data {
593 csi_bool_t is_hexadecimal;
599 _decrypt (unsigned short *R, uint8_t cypher)
605 plain = cypher ^ (*R >> 8);
606 *R = (cypher + *R) * c1 + c2;
613 csi_decrypt (uint8_t *in, int length,
614 unsigned short salt, int binary,
617 const uint8_t * const end = in + length;
624 int c_hi = -1, c_lo = 0;
626 while (in < end && (c_hi = *in++)) {
643 while (in < end && (c_lo = *in++)) {
658 c = (hex_value (c_hi) << 4) | hex_value (c_lo);
662 *out++ = _decrypt (&salt, c);
669 _encrypt (unsigned short *R, uint8_t plain)
675 cypher = plain ^ (*R >> 8);
676 *R = (cypher + *R) * c1 + c2;
683 csi_encrypt (uint8_t *in, int length,
684 unsigned short salt, int discard, int binary,
687 const char hex[]="0123456789abcdef";
688 const uint8_t * const end = in + length;
694 int c = _encrypt (&salt, ' ');
695 *out++ = hex[(c >> 4) & 0xf];
696 *out++ = hex[(c >> 0) & 0xf];
698 *out++ = _encrypt (&salt, 0);
704 c = _encrypt (&salt, *in++);
710 *out++ = hex[(c >> 4) & 0xf];
711 *out++ = hex[(c >> 0) & 0xf];
721 _decrypt_getc (csi_file_t *file)
723 _decrypt_data_t *data = file->data;
727 return data->putback[--data->nputback];
729 if (data->is_hexadecimal) {
732 c_hi = _getc_skip_whitespace (file->src);
733 c_lo = _getc_skip_whitespace (file->src);
734 c = (hex_value (c_hi) << 4) | hex_value (c_lo);
736 c = csi_file_getc (file->src);
741 return _decrypt (&data->R, c);
745 _decrypt_putc (csi_file_t *file, int c)
747 _decrypt_data_t *data;
751 data->putback[data->nputback++] = c;
755 csi_file_new_decrypt (csi_t *ctx, csi_object_t *src, int salt, int discard)
758 _decrypt_data_t *data;
761 data = _csi_alloc0 (ctx, sizeof (_decrypt_data_t));
767 obj = _csi_file_new_filter (ctx, src,
776 /* XXX determine encoding, eexec only? */
777 data->is_hexadecimal = salt != 4330;
778 for (n = 0; n < discard; n++) {
780 c = csi_file_getc (obj);
790 _csi_file_execute (csi_t *ctx, csi_file_t *obj)
792 return _csi_scan_file (ctx, obj);
796 csi_file_getc (csi_file_t *file)
800 if (_csi_unlikely (file->src == NULL))
803 switch (file->type) {
805 if (_csi_likely (file->rem)) {
809 file->rem = fread (file->bp = file->data, 1, CHUNK_SIZE, file->src);
811 if (_csi_likely (file->rem)) {
821 if (file->data == NULL) {
823 csi_object_t *string;
826 status = csi_object_execute (file->src);
830 string = csi_pop_operand (file->base.ctx);
833 file->data = csi_object_as_file (file->base.ctx, string);
834 csi_object_free (string);
835 if (file->data == NULL)
838 c = csi_file_getc (file->data);
840 csi_object_free (file->data);
842 goto RERUN_PROCEDURE;
850 c = file->filter->filter_getc (file);
862 csi_file_read (csi_file_t *file, void *buf, int len)
866 if (file->src == NULL)
869 switch (file->type) {
875 memcpy (buf, file->bp, ret);
879 ret = fread (buf, 1, len, file->src);
887 memcpy (buf, file->bp, ret);
896 if (file->data == NULL) {
898 csi_object_t *string;
901 status = csi_object_execute (file->src);
905 string = csi_pop_operand (file->base.ctx);
908 file->data = csi_object_as_file (file->base.ctx, string);
909 csi_object_free (string);
910 if (file->data == NULL)
913 ret = csi_file_read (file->data, buf, len);
915 csi_object_free (file->data);
917 goto RERUN_PROCEDURE;
925 ret = file->filter->filter_read (file, buf, len);
937 csi_file_putc (csi_file_t *file, int c)
939 if (file->src == NULL)
942 switch ((int) file->type) {
949 file->filter->filter_putc (file, c);
957 csi_file_flush (csi_file_t *file)
959 if (file->src == NULL)
962 switch ((int) file->type) {
963 case FILTER: /* need to eat EOD */
964 while (csi_file_getc (file) != EOF)
973 csi_file_close (csi_t *ctx, csi_file_t *file)
975 if (file->src == NULL)
978 switch (file->type) {
980 if (file->flags & OWN_STREAM)
984 if (file->src != file->data) {
985 csi_string_t *src = file->src;
986 if (src != NULL && --src->base.ref == 0)
987 csi_string_free (ctx, src);
992 csi_file_t *src = file->src;
993 if (src != NULL && --src->base.ref == 0)
994 _csi_file_free (ctx, src);
1005 _csi_file_free (csi_t *ctx, csi_file_t *file)
1007 csi_file_flush (file);
1009 csi_file_close (ctx, file);
1011 switch (file->type) {
1016 csi_object_free (ctx, file->data);
1020 _csi_free (ctx, file->data);
1023 file->filter->filter_destroy (ctx, file->data);
1029 _csi_slab_free (ctx, file, sizeof (csi_file_t));
1033 _csi_file_as_string (csi_t *ctx,
1039 unsigned int allocated;
1040 csi_status_t status;
1044 bytes = _csi_alloc (ctx, allocated);
1046 return _csi_error (CAIRO_STATUS_NO_MEMORY);
1052 ret = csi_file_read (file, bytes + len, allocated - len);
1057 if (len + 1 > allocated / 2) {
1061 if (_csi_unlikely (allocated > INT_MAX / 2))
1062 return _csi_error (CAIRO_STATUS_NO_MEMORY);
1064 newlen = allocated * 2;
1065 newbytes = _csi_realloc (ctx, bytes, newlen);
1066 if (_csi_unlikely (newbytes == NULL)) {
1067 _csi_free (ctx, bytes);
1068 return _csi_error (CAIRO_STATUS_NO_MEMORY);
1075 bytes[len] = '\0'; /* better safe than sorry! */
1076 status = csi_string_new_from_bytes (ctx, obj, bytes, len);
1078 _csi_free (ctx, bytes);
1082 return CAIRO_STATUS_SUCCESS;