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"
37 #include <limits.h> /* INT_MAX */
41 csi_array_new (csi_t *ctx,
42 csi_integer_t initial_size,
48 if (ctx->free_array == NULL ||
49 ctx->free_array->stack.size <= initial_size)
53 array = _csi_slab_alloc (ctx, sizeof (csi_array_t));
54 if (_csi_unlikely (array == NULL))
55 return _csi_error (CSI_STATUS_NO_MEMORY);
57 status = _csi_stack_init (ctx, &array->stack,
58 initial_size ? initial_size : 32);
59 if (_csi_unlikely (status)) {
60 _csi_slab_free (ctx, array, sizeof (csi_array_t));
64 array = ctx->free_array;
65 ctx->free_array = NULL;
68 array->base.type = CSI_OBJECT_TYPE_ARRAY;
71 obj->type = CSI_OBJECT_TYPE_ARRAY;
72 obj->datum.array = array;
74 return CSI_STATUS_SUCCESS;
78 csi_array_put (csi_t *ctx,
83 if (_csi_unlikely (elem < 0))
84 return _csi_error (CSI_STATUS_INVALID_SCRIPT);
86 if (_csi_unlikely (elem >= array->stack.len)) {
89 status = _csi_stack_grow (ctx, &array->stack, elem + 1);
90 if (_csi_unlikely (status))
93 memset (array->stack.objects + array->stack.len,
94 0, (elem - array->stack.len + 1) * sizeof (csi_object_t));
95 array->stack.len = elem + 1;
98 csi_object_free (ctx, &array->stack.objects[elem]);
99 array->stack.objects[elem] = *csi_object_reference (value);
101 return CSI_STATUS_SUCCESS;
105 csi_array_get (csi_t *ctx,
110 if (_csi_unlikely (elem < 0))
111 return _csi_error (CSI_STATUS_INVALID_SCRIPT);
113 if (_csi_unlikely (elem > array->stack.len))
114 return _csi_error (CSI_STATUS_INVALID_SCRIPT);
116 *value = array->stack.objects[elem];
117 return CSI_STATUS_SUCCESS;
121 csi_array_append (csi_t *ctx,
125 return _csi_stack_push (ctx, &array->stack, csi_object_reference (obj));
129 _csi_array_execute (csi_t *ctx, csi_array_t *array)
134 if (_csi_unlikely (array->stack.len == 0))
135 return CSI_STATUS_SUCCESS;
137 for (i = 0; i < array->stack.len; i++) {
138 csi_object_t *obj = &array->stack.objects[i];
140 if (obj->type & CSI_OBJECT_ATTR_EXECUTABLE) {
141 if (obj->type == (CSI_OBJECT_TYPE_ARRAY |
142 CSI_OBJECT_ATTR_EXECUTABLE))
144 status = _csi_push_ostack_copy (ctx, &array->stack.objects[i]);
147 status = csi_object_execute (ctx, &array->stack.objects[i]);
149 status = _csi_push_ostack_copy (ctx, &array->stack.objects[i]);
150 if (_csi_unlikely (status))
154 return CSI_STATUS_SUCCESS;
158 csi_array_free (csi_t *ctx, csi_array_t *array)
161 _csi_stack_fini (ctx, &array->stack);
162 _csi_slab_free (ctx, array, sizeof (csi_array_t));
166 for (n = 0; n < array->stack.len; n++)
167 csi_object_free (ctx, &array->stack.objects[n]);
168 array->stack.len = 0;
170 if (ctx->free_array != NULL) {
171 if (array->stack.size > ctx->free_array->stack.size) {
172 csi_array_t *tmp = ctx->free_array;
173 ctx->free_array = array;
177 _csi_stack_fini (ctx, &array->stack);
178 _csi_slab_free (ctx, array, sizeof (csi_array_t));
180 ctx->free_array = array;
185 _dictionary_name_equal (const void *_a, const void *_b)
191 csi_dictionary_new (csi_t *ctx,
195 csi_dictionary_t *dict;
197 if (ctx->free_dictionary != NULL) {
198 dict = ctx->free_dictionary;
199 ctx->free_dictionary = NULL;
203 dict = _csi_slab_alloc (ctx, sizeof (csi_dictionary_t));
204 if (_csi_unlikely (dict == NULL))
205 return _csi_error (CSI_STATUS_NO_MEMORY);
207 status = _csi_hash_table_init (&dict->hash_table,
208 _dictionary_name_equal);
209 if (_csi_unlikely (status)) {
210 _csi_slab_free (ctx, dict, sizeof (csi_dictionary_t));
215 dict->base.type = CSI_OBJECT_TYPE_DICTIONARY;
218 obj->type = CSI_OBJECT_TYPE_DICTIONARY;
219 obj->datum.dictionary = dict;
221 return CSI_STATUS_SUCCESS;
224 struct _dictionary_entry_pluck {
226 csi_hash_table_t *hash_table;
230 _dictionary_entry_pluck (void *entry, void *data)
232 csi_dictionary_entry_t *dict_entry;
233 struct _dictionary_entry_pluck *pluck_data;
238 _csi_hash_table_remove (pluck_data->hash_table, entry);
239 csi_object_free (pluck_data->ctx, &dict_entry->value);
240 _csi_slab_free (pluck_data->ctx, entry, sizeof (csi_dictionary_entry_t));
244 csi_dictionary_free (csi_t *ctx,
245 csi_dictionary_t *dict)
247 struct _dictionary_entry_pluck data;
250 data.hash_table = &dict->hash_table;
251 _csi_hash_table_foreach (&dict->hash_table,
252 _dictionary_entry_pluck,
256 _csi_hash_table_fini (&dict->hash_table);
257 _csi_slab_free (ctx, dict, sizeof (csi_dictionary_t));
259 if (ctx->free_dictionary != NULL) {
260 _csi_hash_table_fini (&dict->hash_table);
261 _csi_slab_free (ctx, dict, sizeof (csi_dictionary_t));
263 ctx->free_dictionary = dict;
268 csi_dictionary_put (csi_t *ctx,
269 csi_dictionary_t *dict,
273 csi_dictionary_entry_t *entry;
276 entry = _csi_hash_table_lookup (&dict->hash_table,
277 (csi_hash_entry_t *) &name);
279 /* replace the existing entry */
280 csi_object_free (ctx, &entry->value);
281 entry->value = *csi_object_reference (value);
282 return CSI_STATUS_SUCCESS;
285 entry = _csi_slab_alloc (ctx, sizeof (*entry));
286 if (_csi_unlikely (entry == NULL))
287 return _csi_error (CSI_STATUS_NO_MEMORY);
289 entry->hash_entry.hash = name;
290 status = _csi_hash_table_insert (&dict->hash_table, &entry->hash_entry);
291 if (_csi_unlikely (status)) {
292 _csi_slab_free (ctx, entry, sizeof (*entry));
296 entry->value = *csi_object_reference (value);
298 return CSI_STATUS_SUCCESS;
302 csi_dictionary_get (csi_t *ctx,
303 csi_dictionary_t *dict,
307 csi_dictionary_entry_t *entry;
309 entry = _csi_hash_table_lookup (&dict->hash_table,
310 (csi_hash_entry_t *) &name);
311 if (_csi_unlikely (entry == NULL))
312 return _csi_error (CSI_STATUS_INVALID_SCRIPT);
314 *value = entry->value;
315 return CSI_STATUS_SUCCESS;
319 csi_dictionary_has (csi_dictionary_t *dict,
322 return _csi_hash_table_lookup (&dict->hash_table,
323 (csi_hash_entry_t *) &name) != NULL;
327 csi_dictionary_remove (csi_t *ctx,
328 csi_dictionary_t *dict,
331 csi_dictionary_entry_t *entry;
333 entry = _csi_hash_table_lookup (&dict->hash_table,
334 (csi_hash_entry_t *) &name);
336 _csi_hash_table_remove (&dict->hash_table, &entry->hash_entry);
337 csi_object_free (ctx, &entry->value);
338 _csi_slab_free (ctx, entry, sizeof (csi_dictionary_entry_t));
343 csi_matrix_new (csi_t *ctx,
346 csi_matrix_t *matrix;
348 matrix = _csi_slab_alloc (ctx, sizeof (csi_matrix_t));
349 if (_csi_unlikely (matrix == NULL))
350 return _csi_error (CSI_STATUS_NO_MEMORY);
352 matrix->base.type = CSI_OBJECT_TYPE_MATRIX;
353 matrix->base.ref = 1;
354 cairo_matrix_init_identity (&matrix->matrix);
356 obj->type = CSI_OBJECT_TYPE_MATRIX;
357 obj->datum.matrix = matrix;
359 return CSI_STATUS_SUCCESS;
363 csi_matrix_new_from_array (csi_t *ctx,
367 csi_matrix_t *matrix;
369 if (_csi_unlikely (array->stack.len != 6))
370 return _csi_error (CSI_STATUS_INVALID_SCRIPT);
372 matrix = _csi_slab_alloc (ctx, sizeof (csi_matrix_t));
373 if (_csi_unlikely (matrix == NULL))
374 return _csi_error (CSI_STATUS_NO_MEMORY);
376 matrix->base.type = CSI_OBJECT_TYPE_MATRIX;
377 matrix->base.ref = 1;
378 cairo_matrix_init (&matrix->matrix,
379 csi_number_get_value (&array->stack.objects[0]),
380 csi_number_get_value (&array->stack.objects[1]),
381 csi_number_get_value (&array->stack.objects[2]),
382 csi_number_get_value (&array->stack.objects[3]),
383 csi_number_get_value (&array->stack.objects[4]),
384 csi_number_get_value (&array->stack.objects[5]));
386 obj->type = CSI_OBJECT_TYPE_MATRIX;
387 obj->datum.matrix = matrix;
389 return CSI_STATUS_SUCCESS;
393 csi_matrix_new_from_matrix (csi_t *ctx,
395 const cairo_matrix_t *m)
397 csi_matrix_t *matrix;
399 matrix = _csi_slab_alloc (ctx, sizeof (csi_matrix_t));
400 if (_csi_unlikely (matrix == NULL))
401 return _csi_error (CSI_STATUS_NO_MEMORY);
403 matrix->base.type = CSI_OBJECT_TYPE_MATRIX;
404 matrix->base.ref = 1;
407 obj->type = CSI_OBJECT_TYPE_MATRIX;
408 obj->datum.matrix = matrix;
410 return CSI_STATUS_SUCCESS;
414 csi_matrix_new_from_values (csi_t *ctx,
418 csi_matrix_t *matrix;
420 matrix = _csi_slab_alloc (ctx, sizeof (csi_matrix_t));
421 if (_csi_unlikely (matrix == NULL))
422 return _csi_error (CSI_STATUS_NO_MEMORY);
424 matrix->base.type = CSI_OBJECT_TYPE_MATRIX;
425 matrix->base.ref = 1;
426 cairo_matrix_init (&matrix->matrix, v[0], v[1], v[2], v[3], v[4], v[5]);
428 obj->type = CSI_OBJECT_TYPE_MATRIX;
429 obj->datum.matrix = matrix;
431 return CSI_STATUS_SUCCESS;
435 csi_matrix_free (csi_t *ctx,
438 _csi_slab_free (ctx, obj, sizeof (csi_matrix_t));
443 csi_name_new (csi_t *ctx,
450 status = _csi_intern_string (ctx, &str, len);
451 if (_csi_unlikely (status))
454 obj->type = CSI_OBJECT_TYPE_NAME;
455 obj->datum.name = (csi_name_t) str;
457 return CSI_STATUS_SUCCESS;
461 csi_name_new_static (csi_t *ctx,
467 status = _csi_intern_string (ctx, &str, strlen (str));
468 if (_csi_unlikely (status))
471 obj->type = CSI_OBJECT_TYPE_NAME;
472 obj->datum.name = (csi_name_t) str;
474 return CSI_STATUS_SUCCESS;
478 csi_string_new (csi_t *ctx,
483 csi_string_t *string;
487 if (_csi_unlikely (len >= INT_MAX))
488 return _csi_error (CSI_STATUS_NO_MEMORY);
490 if (ctx->free_string == NULL || ctx->free_string->len <= len) {
491 string = _csi_slab_alloc (ctx, sizeof (csi_string_t));
492 if (_csi_unlikely (string == NULL))
493 return _csi_error (CSI_STATUS_NO_MEMORY);
495 string->string = _csi_alloc (ctx, len + 1);
496 if (_csi_unlikely (string->string == NULL)) {
497 _csi_slab_free (ctx, string, sizeof (csi_string_t));
498 return _csi_error (CSI_STATUS_NO_MEMORY);
501 string = ctx->free_string;
502 ctx->free_string = NULL;
506 memcpy (string->string, str, len);
507 string->string[len] = '\0';
511 string->method = NONE;
513 string->base.type = CSI_OBJECT_TYPE_STRING;
514 string->base.ref = 1;
516 obj->type = CSI_OBJECT_TYPE_STRING;
517 obj->datum.string = string;
519 return CSI_STATUS_SUCCESS;
523 csi_string_deflate_new (csi_t *ctx,
530 csi_string_t *string;
532 status = csi_string_new (ctx, obj, bytes, in_len);
533 if (_csi_unlikely (status))
536 string = obj->datum.string;
537 string->deflate = out_len;
538 string->method = ZLIB;
540 return CSI_STATUS_SUCCESS;
544 csi_string_new_from_bytes (csi_t *ctx,
549 csi_string_t *string;
551 if (_csi_unlikely (len >= INT_MAX))
552 return _csi_error (CSI_STATUS_NO_MEMORY);
554 string = _csi_slab_alloc (ctx, sizeof (csi_string_t));
555 if (_csi_unlikely (string == NULL))
556 return _csi_error (CSI_STATUS_NO_MEMORY);
558 string->string = bytes;
561 string->method = NONE;
563 string->base.type = CSI_OBJECT_TYPE_STRING;
564 string->base.ref = 1;
566 obj->type = CSI_OBJECT_TYPE_STRING;
567 obj->datum.string = string;
569 return CSI_STATUS_SUCCESS;
572 static inline csi_status_t
573 _csi_string_execute (csi_t *ctx, csi_string_t *string)
578 if (_csi_unlikely (string->len == 0))
579 return CSI_STATUS_SUCCESS;
581 status = csi_file_new_for_bytes (ctx, &obj, string->string, string->len);
582 if (_csi_unlikely (status))
585 status = _csi_scan_file (ctx, obj.datum.file);
586 csi_object_free (ctx, &obj);
592 csi_string_free (csi_t *ctx, csi_string_t *string)
595 _csi_free (ctx, string->string);
596 _csi_slab_free (ctx, string, sizeof (csi_string_t));
598 if (ctx->free_string != NULL) {
599 if (string->len > ctx->free_string->len) {
600 csi_string_t *tmp = ctx->free_string;
601 ctx->free_string = string;
605 _csi_free (ctx, string->string);
606 _csi_slab_free (ctx, string, sizeof (csi_string_t));
608 ctx->free_string = string;
613 csi_object_execute (csi_t *ctx, csi_object_t *obj)
616 csi_object_t indirect;
619 switch (obj->type & CSI_OBJECT_TYPE_MASK) {
620 case CSI_OBJECT_TYPE_NAME:
621 status = _csi_name_lookup (ctx, obj->datum.name, &indirect);
622 if (_csi_unlikely (status))
624 if (indirect.type & CSI_OBJECT_ATTR_EXECUTABLE) {
628 return _csi_push_ostack_copy (ctx, &indirect);
630 case CSI_OBJECT_TYPE_OPERATOR:
631 return obj->datum.op (ctx);
633 case CSI_OBJECT_TYPE_ARRAY:
634 return _csi_array_execute (ctx, obj->datum.array);
635 case CSI_OBJECT_TYPE_FILE:
636 return _csi_file_execute (ctx, obj->datum.file);
637 case CSI_OBJECT_TYPE_STRING:
638 return _csi_string_execute (ctx, obj->datum.string);
641 return _csi_push_ostack_copy (ctx, obj);
646 csi_object_reference (csi_object_t *obj)
648 if (CSI_OBJECT_IS_CAIRO (obj)) {
649 switch (obj->type & CSI_OBJECT_TYPE_MASK) {
650 case CSI_OBJECT_TYPE_CONTEXT:
651 cairo_reference (obj->datum.cr);
653 case CSI_OBJECT_TYPE_FONT:
654 cairo_font_face_reference (obj->datum.font_face);
656 case CSI_OBJECT_TYPE_PATTERN:
657 cairo_pattern_reference (obj->datum.pattern);
659 case CSI_OBJECT_TYPE_SCALED_FONT:
660 cairo_scaled_font_reference (obj->datum.scaled_font);
662 case CSI_OBJECT_TYPE_SURFACE:
663 cairo_surface_reference (obj->datum.surface);
666 } else if (CSI_OBJECT_IS_COMPOUND (obj)) {
667 obj->datum.object->ref++;
674 csi_object_free (csi_t *ctx,
677 if (CSI_OBJECT_IS_CAIRO (obj)) {
678 switch (obj->type & CSI_OBJECT_TYPE_MASK) {
679 case CSI_OBJECT_TYPE_CONTEXT:
680 cairo_destroy (obj->datum.cr);
682 case CSI_OBJECT_TYPE_FONT:
683 cairo_font_face_destroy (obj->datum.font_face);
685 case CSI_OBJECT_TYPE_PATTERN:
686 cairo_pattern_destroy (obj->datum.pattern);
688 case CSI_OBJECT_TYPE_SCALED_FONT:
689 cairo_scaled_font_destroy (obj->datum.scaled_font);
691 case CSI_OBJECT_TYPE_SURFACE:
692 cairo_surface_destroy (obj->datum.surface);
695 } else if (CSI_OBJECT_IS_COMPOUND (obj)) {
696 if (--obj->datum.object->ref)
699 switch (obj->type & CSI_OBJECT_TYPE_MASK) {
700 case CSI_OBJECT_TYPE_ARRAY:
701 csi_array_free (ctx, obj->datum.array);
703 case CSI_OBJECT_TYPE_DICTIONARY:
704 csi_dictionary_free (ctx, obj->datum.dictionary);
706 case CSI_OBJECT_TYPE_FILE:
707 _csi_file_free (ctx, obj->datum.file);
709 case CSI_OBJECT_TYPE_MATRIX:
710 csi_matrix_free (ctx, obj->datum.matrix);
712 case CSI_OBJECT_TYPE_STRING:
713 csi_string_free (ctx, obj->datum.string);
722 csi_object_as_file (csi_t *ctx,
726 int type = csi_object_get_type (src);
728 case CSI_OBJECT_TYPE_FILE:
729 *file = *csi_object_reference (src);
730 return CSI_STATUS_SUCCESS;
731 case CSI_OBJECT_TYPE_STRING:
732 return csi_file_new_from_string (ctx, file, src->datum.string);
733 case CSI_OBJECT_TYPE_ARRAY:
735 if (src->type & CSI_OBJECT_ATTR_EXECUTABLE)
736 return _csi_file_new_from_procedure (cs, src);
739 return _csi_error (CSI_STATUS_INVALID_SCRIPT);
744 lexcmp (void const *a, size_t alen,
745 void const *b, size_t blen)
747 size_t len = alen < blen ? alen : blen;
748 int cmp = memcmp (a, b, len);
753 return alen < blen ? -1 : +1;
757 csi_object_eq (csi_object_t *a,
760 csi_object_type_t atype = csi_object_get_type (a);
761 csi_object_type_t btype = csi_object_get_type (b);
763 if (atype == btype) {
765 case CSI_OBJECT_TYPE_BOOLEAN:
766 return a->datum.boolean == b->datum.boolean;
767 case CSI_OBJECT_TYPE_INTEGER:
768 return a->datum.integer == b->datum.integer;
769 case CSI_OBJECT_TYPE_REAL:
770 return a->datum.real == b->datum.real;
771 case CSI_OBJECT_TYPE_NAME:
772 return a->datum.name == b->datum.name;
773 case CSI_OBJECT_TYPE_STRING:
774 return 0 == lexcmp (a->datum.string->string,
775 a->datum.string->len,
776 b->datum.string->string,
777 b->datum.string->len);
778 case CSI_OBJECT_TYPE_NULL:
779 case CSI_OBJECT_TYPE_MARK:
781 case CSI_OBJECT_TYPE_OPERATOR:
782 return a->datum.op == b->datum.op;
783 case CSI_OBJECT_TYPE_ARRAY:
784 case CSI_OBJECT_TYPE_DICTIONARY:
785 case CSI_OBJECT_TYPE_FILE:
786 case CSI_OBJECT_TYPE_MATRIX:
787 case CSI_OBJECT_TYPE_CONTEXT:
788 case CSI_OBJECT_TYPE_FONT:
789 case CSI_OBJECT_TYPE_PATTERN:
790 case CSI_OBJECT_TYPE_SCALED_FONT:
791 case CSI_OBJECT_TYPE_SURFACE:
792 return a->datum.ptr == b->datum.ptr;
798 csi_object_type_t ctype;
800 ctype = atype; atype = btype; btype = ctype;
803 switch ((int) atype) {
804 case CSI_OBJECT_TYPE_INTEGER:
805 if (btype == CSI_OBJECT_TYPE_BOOLEAN) {
806 return a->datum.integer == b->datum.boolean;
809 case CSI_OBJECT_TYPE_REAL:
810 if (btype == CSI_OBJECT_TYPE_INTEGER) {
811 return a->datum.real == b->datum.integer;
813 else if (btype == CSI_OBJECT_TYPE_BOOLEAN) {
814 return a->datum.real == b->datum.boolean;
818 case CSI_OBJECT_TYPE_STRING:
819 if (btype == CSI_OBJECT_TYPE_NAME) {
820 const char *bstr = (const char *) b->datum.name;
821 return 0 == lexcmp (a->datum.string->string,
822 a->datum.string->len,
836 csi_object_compare (csi_object_t *a,
840 csi_object_type_t atype = csi_object_get_type (a);
841 csi_object_type_t btype = csi_object_get_type (b);
844 if (csi_object_eq (a, b)){
846 return CSI_STATUS_SUCCESS;
849 #define CMP(x,y) ((x) < (y) ? -1 : +1)
851 if (atype == btype) {
853 case CSI_OBJECT_TYPE_BOOLEAN:
854 *out = CMP (a->datum.boolean, b->datum.boolean);
855 return CSI_STATUS_SUCCESS;
856 case CSI_OBJECT_TYPE_INTEGER:
857 *out = CMP (a->datum.integer, b->datum.integer);
858 return CSI_STATUS_SUCCESS;
859 case CSI_OBJECT_TYPE_REAL:
860 *out = CMP (a->datum.real, b->datum.real);
861 return CSI_STATUS_SUCCESS;
862 case CSI_OBJECT_TYPE_NAME: {
863 const char *x = (char const *) a->datum.name;
864 const char *y = (char const *) b->datum.name;
865 *out = lexcmp (x, strlen(x), y, strlen (y));
866 return CSI_STATUS_SUCCESS;
868 case CSI_OBJECT_TYPE_STRING:
869 *out = lexcmp (a->datum.string->string,
870 a->datum.string->len,
871 b->datum.string->string,
872 b->datum.string->len);
873 return CSI_STATUS_SUCCESS;
874 case CSI_OBJECT_TYPE_NULL:
875 case CSI_OBJECT_TYPE_MARK:
876 case CSI_OBJECT_TYPE_OPERATOR:
877 case CSI_OBJECT_TYPE_ARRAY:
878 case CSI_OBJECT_TYPE_DICTIONARY:
879 case CSI_OBJECT_TYPE_FILE:
880 case CSI_OBJECT_TYPE_MATRIX:
881 case CSI_OBJECT_TYPE_CONTEXT:
882 case CSI_OBJECT_TYPE_FONT:
883 case CSI_OBJECT_TYPE_PATTERN:
884 case CSI_OBJECT_TYPE_SCALED_FONT:
885 case CSI_OBJECT_TYPE_SURFACE:
886 goto TYPE_CHECK_ERROR;
893 csi_object_type_t ctype;
895 ctype = atype; atype = btype; btype = ctype;
899 switch ((int) atype) {
900 case CSI_OBJECT_TYPE_INTEGER:
901 if (btype == CSI_OBJECT_TYPE_BOOLEAN) {
902 *out = sign * CMP (a->datum.integer, !!b->datum.boolean);
903 return CSI_STATUS_SUCCESS;
906 case CSI_OBJECT_TYPE_REAL:
907 if (btype == CSI_OBJECT_TYPE_INTEGER) {
908 *out = sign * CMP (a->datum.real, b->datum.integer);
909 return CSI_STATUS_SUCCESS;
911 else if (btype == CSI_OBJECT_TYPE_BOOLEAN) {
912 *out = sign * CMP (a->datum.real, !!b->datum.boolean);
913 return CSI_STATUS_SUCCESS;
917 case CSI_OBJECT_TYPE_STRING:
918 if (btype == CSI_OBJECT_TYPE_NAME) {
919 const char *bstr = (const char *) b->datum.name;
920 *out = sign * lexcmp (a->datum.string->string,
921 a->datum.string->len,
924 return CSI_STATUS_SUCCESS;
935 return _csi_error (CSI_STATUS_SCRIPT_INVALID_TYPE);