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 */
43 #include <lzo/lzo2a.h>
46 #define CHUNK_SIZE 32768
48 #define OWN_STREAM 0x1
51 csi_file_new (csi_t *ctx,
53 const char *path, const char *mode)
57 file = _csi_slab_alloc (ctx, sizeof (csi_file_t));
59 return _csi_error (CAIRO_STATUS_NO_MEMORY);
61 file->base.type = CSI_OBJECT_TYPE_FILE;
66 file->flags = OWN_STREAM;
67 file->src = fopen (path, mode);
68 if (file->src == NULL) {
69 _csi_slab_free (ctx, file, sizeof (csi_file_t));
70 return _csi_error (CAIRO_STATUS_FILE_NOT_FOUND);
73 file->data = _csi_alloc (ctx, CHUNK_SIZE);
74 if (file->data == NULL) {
75 _csi_slab_free (ctx, file, sizeof (csi_file_t));
76 return _csi_error (CAIRO_STATUS_NO_MEMORY);
78 file->bp = file->data;
81 obj->type = CSI_OBJECT_TYPE_FILE;
82 obj->datum.file = file;
83 return CAIRO_STATUS_SUCCESS;
87 csi_file_new_for_stream (csi_t *ctx,
93 file = _csi_slab_alloc (ctx, sizeof (csi_file_t));
95 return _csi_error (CAIRO_STATUS_NO_MEMORY);
97 file->base.type = CSI_OBJECT_TYPE_FILE;
104 if (file->src == NULL) {
105 _csi_slab_free (ctx, file, sizeof (csi_file_t));
106 return _csi_error (CAIRO_STATUS_FILE_NOT_FOUND);
109 file->data = _csi_alloc (ctx, CHUNK_SIZE);
110 if (file->data == NULL) {
111 _csi_slab_free (ctx, file, sizeof (csi_file_t));
112 return _csi_error (CAIRO_STATUS_NO_MEMORY);
114 file->bp = file->data;
117 obj->type = CSI_OBJECT_TYPE_FILE;
118 obj->datum.file = file;
119 return CAIRO_STATUS_SUCCESS;
123 csi_file_new_for_bytes (csi_t *ctx,
130 file = _csi_slab_alloc (ctx, sizeof (csi_file_t));
132 return _csi_error (CAIRO_STATUS_NO_MEMORY);
134 file->base.type = CSI_OBJECT_TYPE_FILE;
138 file->src = (uint8_t *) bytes;
139 file->data = (uint8_t *) bytes;
140 file->bp = (uint8_t *) bytes;
143 obj->type = CSI_OBJECT_TYPE_FILE;
144 obj->datum.file = file;
145 return CAIRO_STATUS_SUCCESS;
149 csi_file_new_from_string (csi_t *ctx,
155 file = _csi_slab_alloc (ctx, sizeof (csi_file_t));
156 if (_csi_unlikely (file == NULL))
157 return _csi_error (CAIRO_STATUS_NO_MEMORY);
159 file->base.type = CSI_OBJECT_TYPE_FILE;
163 uLongf len = src->deflate;
164 csi_object_t tmp_obj;
165 csi_string_t *tmp_str;
168 status = csi_string_new (ctx, &tmp_obj, NULL, src->deflate);
169 if (_csi_unlikely (status))
172 tmp_str = tmp_obj.datum.string;
173 switch (src->method) {
176 status = _csi_error (CAIRO_STATUS_NO_MEMORY);
181 if (uncompress ((Bytef *) tmp_str->string, &len,
182 (Bytef *) src->string, src->len) != Z_OK)
183 status = _csi_error (CAIRO_STATUS_NO_MEMORY);
188 if (lzo2a_decompress ((lzo_bytep) src->string, src->len,
189 (lzo_bytep) tmp_str->string, &len,
191 status = _csi_error (CAIRO_STATUS_NO_MEMORY);
195 if (_csi_unlikely (status)) {
196 csi_string_free (ctx, tmp_str);
197 _csi_slab_free (ctx, file, sizeof (csi_file_t));
202 file->data = tmp_str->string;
203 file->rem = tmp_str->len;
205 file->src = src; src->base.ref++;
206 file->data = src->string;
207 file->rem = src->len;
210 file->bp = file->data;
212 obj->type = CSI_OBJECT_TYPE_FILE;
213 obj->datum.file = file;
214 return CAIRO_STATUS_SUCCESS;
218 _csi_file_new_filter (csi_t *ctx,
221 const csi_filter_funcs_t *funcs,
225 csi_object_t src_file;
228 file = _csi_slab_alloc (ctx, sizeof (csi_file_t));
230 return _csi_error (CAIRO_STATUS_NO_MEMORY);
232 obj->type = CSI_OBJECT_TYPE_FILE;
233 obj->datum.file = file;
235 file->base.type = CSI_OBJECT_TYPE_FILE;
240 file->filter = funcs;
241 status = csi_object_as_file (ctx, src, &src_file);
243 csi_object_free (ctx, obj);
246 file->src = src_file.datum.file;
248 return CAIRO_STATUS_SUCCESS;
254 csi_file_new_from_stream (csi_t *ctx,
260 obj = (csi_file_t *) _csi_object_new (ctx, CSI_OBJECT_TYPE_FILE);
262 return _csi_error (CAIRO_STATUS_NO_MEMORY);
266 obj->data = _csi_alloc (ctx, CHUNK_SIZE);
267 if (obj->data == NULL) {
268 csi_object_free (&obj->base);
269 return _csi_error (CAIRO_STATUS_UNDEFINED_FILENAME_ERROR);
275 return CAIRO_STATUS_SUCCESS;
278 static csi_object_t *
279 _csi_file_new_from_procedure (csi_t *ctx, csi_object_t *src)
283 obj = (csi_file_t *) _csi_object_new (ctx, CSI_OBJECT_TYPE_FILE);
287 obj->type = PROCEDURE;
288 obj->src = csi_object_reference (src);
295 typedef struct _ascii85_decode_data {
296 uint8_t buf[CHUNK_SIZE];
298 short bytes_available;
300 } _ascii85_decode_data_t;
303 _getc_skip_whitespace (csi_file_t *src)
307 do switch ((c = csi_file_getc (src))) {
324 _ascii85_decode (csi_file_t *file)
326 _ascii85_decode_data_t *data = file->data;
332 data->bp = data->buf;
336 unsigned int v = _getc_skip_whitespace (file->src);
342 } else if (v == '~') {
343 _getc_skip_whitespace (file->src); /* == '>' || IO_ERROR */
346 } else if (v < '!' || v > 'u') {
354 for (i = 1; i < 5; i++) {
355 int c = _getc_skip_whitespace (file->src);
356 if (c == '~') { /* short tuple */
357 _getc_skip_whitespace (file->src); /* == '>' || IO_ERROR */
365 v = v * (85*85*85) + 85*85*85 -1;
368 v = v * (85*85) + 85*85 -1;
372 data->buf[n+2] = v >> 8 & 0xff;
374 data->buf[n+1] = v >> 16 & 0xff;
376 data->buf[n+0] = v >> 24 & 0xff;
377 data->bytes_available = n + i - 1;
385 data->buf[n+0] = v >> 24 & 0xff;
386 data->buf[n+1] = v >> 16 & 0xff;
387 data->buf[n+2] = v >> 8 & 0xff;
388 data->buf[n+3] = v >> 0 & 0xff;
391 } while (n < sizeof (data->buf) && data->eod == FALSE);
393 data->bytes_available = n;
397 _ascii85_decode_getc (csi_file_t *file)
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 data->bytes_available--;
413 _ascii85_decode_putc (csi_file_t *file, int c)
415 _ascii85_decode_data_t *data = file->data;
416 data->bytes_available++;
421 _ascii85_decode_read (csi_file_t *file, uint8_t *buf, int len)
423 _ascii85_decode_data_t *data = file->data;
425 if (data->bytes_available == 0) {
426 _ascii85_decode (file);
428 if (data->bytes_available == 0)
432 if (len > data->bytes_available)
433 len = data->bytes_available;
434 memcpy (buf, data->bp, len);
436 data->bytes_available -= len;
441 csi_file_new_ascii85_decode (csi_t *ctx,
443 csi_dictionary_t *dict,
446 static const csi_filter_funcs_t funcs = {
447 _ascii85_decode_getc,
448 _ascii85_decode_putc,
449 _ascii85_decode_read,
452 _ascii85_decode_data_t *data;
454 data = _csi_alloc0 (ctx, sizeof (_ascii85_decode_data_t));
456 return _csi_error (CAIRO_STATUS_NO_MEMORY);
458 return _csi_file_new_filter (ctx, obj, src, &funcs, data);
464 typedef struct _deflate_decode_data {
465 z_stream zlib_stream;
467 uint8_t in[CHUNK_SIZE];
468 uint8_t out[CHUNK_SIZE];
472 } _deflate_decode_data_t;
475 _deflate_decode (csi_file_t *file)
477 _deflate_decode_data_t *data = file->data;
481 data->zlib_stream.next_out = data->out;
482 data->zlib_stream.avail_out = sizeof (data->out);
485 len = sizeof (data->in);
486 if (data->zlib_stream.avail_in) {
488 data->zlib_stream.next_in,
489 data->zlib_stream.avail_in);
490 len -= data->zlib_stream.avail_in;
491 bp += data->zlib_stream.avail_in;
494 len = csi_file_read (file->src, bp, len);
496 data->zlib_stream.next_in = data->in;
497 data->zlib_stream.avail_in += len;
499 inflate (&data->zlib_stream, len == 0 ? Z_FINISH : Z_NO_FLUSH);
501 data->bytes_available = data->zlib_stream.next_out - data->out;
502 data->bp = data->out;
506 _deflate_decode_getc (csi_file_t *file)
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 data->bytes_available--;
522 _deflate_decode_putc (csi_file_t *file, int c)
524 _deflate_decode_data_t *data = file->data;
525 data->bytes_available++;
530 _deflate_decode_read (csi_file_t *file, uint8_t *buf, int len)
532 _deflate_decode_data_t *data = file->data;
534 if (data->bytes_available == 0) {
535 _deflate_decode (file);
537 if (data->bytes_available == 0)
541 if (len > (int) data->bytes_available)
542 len = data->bytes_available;
543 memcpy (buf, data->bp, len);
545 data->bytes_available -= len;
550 _deflate_destroy (csi_t *ctx, void *closure)
552 _deflate_decode_data_t *data;
556 inflateEnd (&data->zlib_stream);
558 _csi_free (ctx, data);
562 csi_file_new_deflate_decode (csi_t *ctx,
564 csi_dictionary_t *dict,
567 static const csi_filter_funcs_t funcs = {
568 _deflate_decode_getc,
569 _deflate_decode_putc,
570 _deflate_decode_read,
573 _deflate_decode_data_t *data;
575 data = _csi_alloc (ctx, sizeof (_deflate_decode_data_t));
577 return _csi_error (CAIRO_STATUS_NO_MEMORY);
579 data->zlib_stream.zalloc = Z_NULL;
580 data->zlib_stream.zfree = Z_NULL;
581 data->zlib_stream.opaque = Z_NULL;
582 data->zlib_stream.next_in = data->in;
583 data->zlib_stream.avail_in = 0;
584 data->zlib_stream.next_out = data->out;
585 data->zlib_stream.avail_out = sizeof (data->out);
586 data->bytes_available = 0;
588 if (inflateInit (&data->zlib_stream) != Z_OK) {
589 _csi_free (ctx, data);
590 return _csi_error (CAIRO_STATUS_NO_MEMORY);
593 return _csi_file_new_filter (ctx, obj, src, &funcs, data);
609 return c - 'a' + 0xa;
613 /* Adobe Type 1 Font Format book: p63 */
614 typedef struct _decrypt_data {
617 csi_bool_t is_hexadecimal;
623 _decrypt (unsigned short *R, uint8_t cypher)
629 plain = cypher ^ (*R >> 8);
630 *R = (cypher + *R) * c1 + c2;
637 csi_decrypt (uint8_t *in, int length,
638 unsigned short salt, int binary,
641 const uint8_t * const end = in + length;
648 int c_hi = -1, c_lo = 0;
650 while (in < end && (c_hi = *in++)) {
667 while (in < end && (c_lo = *in++)) {
682 c = (hex_value (c_hi) << 4) | hex_value (c_lo);
686 *out++ = _decrypt (&salt, c);
693 _encrypt (unsigned short *R, uint8_t plain)
699 cypher = plain ^ (*R >> 8);
700 *R = (cypher + *R) * c1 + c2;
707 csi_encrypt (uint8_t *in, int length,
708 unsigned short salt, int discard, int binary,
711 const char hex[]="0123456789abcdef";
712 const uint8_t * const end = in + length;
718 int c = _encrypt (&salt, ' ');
719 *out++ = hex[(c >> 4) & 0xf];
720 *out++ = hex[(c >> 0) & 0xf];
722 *out++ = _encrypt (&salt, 0);
728 c = _encrypt (&salt, *in++);
734 *out++ = hex[(c >> 4) & 0xf];
735 *out++ = hex[(c >> 0) & 0xf];
745 _decrypt_getc (csi_file_t *file)
747 _decrypt_data_t *data = file->data;
751 return data->putback[--data->nputback];
753 if (data->is_hexadecimal) {
756 c_hi = _getc_skip_whitespace (file->src);
757 c_lo = _getc_skip_whitespace (file->src);
758 c = (hex_value (c_hi) << 4) | hex_value (c_lo);
760 c = csi_file_getc (file->src);
765 return _decrypt (&data->R, c);
769 _decrypt_putc (csi_file_t *file, int c)
771 _decrypt_data_t *data;
775 data->putback[data->nputback++] = c;
779 csi_file_new_decrypt (csi_t *ctx, csi_object_t *src, int salt, int discard)
782 _decrypt_data_t *data;
785 data = _csi_alloc0 (ctx, sizeof (_decrypt_data_t));
791 obj = _csi_file_new_filter (ctx, src,
800 /* XXX determine encoding, eexec only? */
801 data->is_hexadecimal = salt != 4330;
802 for (n = 0; n < discard; n++) {
804 c = csi_file_getc (obj);
814 _csi_file_execute (csi_t *ctx, csi_file_t *obj)
816 return _csi_scan_file (ctx, obj);
820 csi_file_getc (csi_file_t *file)
824 if (_csi_unlikely (file->src == NULL))
827 switch (file->type) {
829 if (_csi_likely (file->rem)) {
833 file->rem = fread (file->bp = file->data, 1, CHUNK_SIZE, file->src);
835 if (_csi_likely (file->rem)) {
845 if (file->data == NULL) {
847 csi_object_t *string;
850 status = csi_object_execute (file->src);
854 string = csi_pop_operand (file->base.ctx);
857 file->data = csi_object_as_file (file->base.ctx, string);
858 csi_object_free (string);
859 if (file->data == NULL)
862 c = csi_file_getc (file->data);
864 csi_object_free (file->data);
866 goto RERUN_PROCEDURE;
874 c = file->filter->filter_getc (file);
886 csi_file_read (csi_file_t *file, void *buf, int len)
890 if (file->src == NULL)
893 switch (file->type) {
899 memcpy (buf, file->bp, ret);
903 ret = fread (buf, 1, len, file->src);
911 memcpy (buf, file->bp, ret);
920 if (file->data == NULL) {
922 csi_object_t *string;
925 status = csi_object_execute (file->src);
929 string = csi_pop_operand (file->base.ctx);
932 file->data = csi_object_as_file (file->base.ctx, string);
933 csi_object_free (string);
934 if (file->data == NULL)
937 ret = csi_file_read (file->data, buf, len);
939 csi_object_free (file->data);
941 goto RERUN_PROCEDURE;
949 ret = file->filter->filter_read (file, buf, len);
961 csi_file_putc (csi_file_t *file, int c)
963 if (file->src == NULL)
966 switch ((int) file->type) {
973 file->filter->filter_putc (file, c);
981 csi_file_flush (csi_file_t *file)
983 if (file->src == NULL)
986 switch ((int) file->type) {
987 case FILTER: /* need to eat EOD */
988 while (csi_file_getc (file) != EOF)
997 csi_file_close (csi_t *ctx, csi_file_t *file)
999 if (file->src == NULL)
1002 switch (file->type) {
1004 if (file->flags & OWN_STREAM)
1008 if (file->src != file->data) {
1009 csi_string_t *src = file->src;
1010 if (src != NULL && --src->base.ref == 0)
1011 csi_string_free (ctx, src);
1016 csi_file_t *src = file->src;
1017 if (src != NULL && --src->base.ref == 0)
1018 _csi_file_free (ctx, src);
1029 _csi_file_free (csi_t *ctx, csi_file_t *file)
1031 csi_file_flush (file);
1033 csi_file_close (ctx, file);
1035 switch (file->type) {
1040 csi_object_free (ctx, file->data);
1044 _csi_free (ctx, file->data);
1047 file->filter->filter_destroy (ctx, file->data);
1053 _csi_slab_free (ctx, file, sizeof (csi_file_t));
1057 _csi_file_as_string (csi_t *ctx,
1063 unsigned int allocated;
1064 csi_status_t status;
1068 bytes = _csi_alloc (ctx, allocated);
1070 return _csi_error (CAIRO_STATUS_NO_MEMORY);
1076 ret = csi_file_read (file, bytes + len, allocated - len);
1081 if (len + 1 > allocated / 2) {
1085 if (_csi_unlikely (allocated > INT_MAX / 2))
1086 return _csi_error (CAIRO_STATUS_NO_MEMORY);
1088 newlen = allocated * 2;
1089 newbytes = _csi_realloc (ctx, bytes, newlen);
1090 if (_csi_unlikely (newbytes == NULL)) {
1091 _csi_free (ctx, bytes);
1092 return _csi_error (CAIRO_STATUS_NO_MEMORY);
1099 bytes[len] = '\0'; /* better safe than sorry! */
1100 status = csi_string_new_from_bytes (ctx, obj, bytes, len);
1102 _csi_free (ctx, bytes);
1106 return CAIRO_STATUS_SUCCESS;