summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorThomas Deutschmann <whissi@gentoo.org>2019-10-15 12:24:12 +0200
committerThomas Deutschmann <whissi@gentoo.org>2020-08-13 11:26:55 +0200
commite088156d5b620e5e639580dacf85c6dc13823c74 (patch)
tree57f5c025e203279944da512166c20bc0521d8ccd /base/gsparam.h
downloadghostscript-gpl-patches-e088156d5b620e5e639580dacf85c6dc13823c74.tar.gz
ghostscript-gpl-patches-e088156d5b620e5e639580dacf85c6dc13823c74.tar.bz2
ghostscript-gpl-patches-e088156d5b620e5e639580dacf85c6dc13823c74.zip
Import Ghostscript 9.50ghostscript-9.50
Signed-off-by: Thomas Deutschmann <whissi@gentoo.org>
Diffstat (limited to 'base/gsparam.h')
-rw-r--r--base/gsparam.h559
1 files changed, 559 insertions, 0 deletions
diff --git a/base/gsparam.h b/base/gsparam.h
new file mode 100644
index 00000000..0f474c26
--- /dev/null
+++ b/base/gsparam.h
@@ -0,0 +1,559 @@
+/* Copyright (C) 2001-2019 Artifex Software, Inc.
+ All Rights Reserved.
+
+ This software is provided AS-IS with no warranty, either express or
+ implied.
+
+ This software is distributed under license and may not be copied,
+ modified or distributed except as expressly authorized under the terms
+ of the license contained in the file LICENSE in this distribution.
+
+ Refer to licensing information at http://www.artifex.com or contact
+ Artifex Software, Inc., 1305 Grant Avenue - Suite 200, Novato,
+ CA 94945, U.S.A., +1(415)492-9861, for further information.
+*/
+
+
+/* Client interface to parameter dictionaries */
+
+#ifndef gsparam_INCLUDED
+# define gsparam_INCLUDED
+
+#include "gsstype.h"
+
+/*
+ * Several interfaces use parameter dictionaries to communicate sets of
+ * (key, value) pairs between a client and an object with complex state.
+ * (Several of these correspond directly to similar interfaces in the
+ * PostScript language.) This file defines the API for parameter dictionaries.
+ */
+
+/* ---------------- Generic interfaces ---------------- */
+
+/* Define the abstract type for a parameter list. */
+typedef struct gs_param_list_s gs_param_list;
+
+/* Define the type for a parameter key name. */
+typedef const char *gs_param_name;
+
+/*
+ * Parameter values fall into three categories:
+ * - Scalar (null, Boolean, int, long, float);
+ * - Homogenous collection (string/name, int array, float array,
+ * string/name array);
+ * - Heterogenous collection (dictionary, int-keyed dictionary, array).
+ * Each category has its own representation and memory management issues.
+ */
+typedef enum {
+ /* Scalar */
+ gs_param_type_null, gs_param_type_bool, gs_param_type_int,
+ gs_param_type_long, gs_param_type_float,
+ /* Homogenous collection */
+ gs_param_type_string, gs_param_type_name,
+ gs_param_type_int_array, gs_param_type_float_array,
+ gs_param_type_string_array, gs_param_type_name_array,
+ /* Heterogenous collection */
+ gs_param_type_dict, gs_param_type_dict_int_keys, gs_param_type_array
+} gs_param_type;
+
+/* Define a "don't care" type for reading typed values. */
+#define gs_param_type_any ((gs_param_type)-1)
+
+/*
+ * Define the structures for homogenous collection values
+ * (string/name, integer array, or floating point array).
+ * The size is the number of elements, not the size in bytes.
+ * A value is persistent if it is defined as static const,
+ * or if it is allocated in garbage-collectable space and never freed.
+ */
+
+#define _param_array_struct(sname,etype)\
+ struct sname { const etype *data; uint size; bool persistent; }
+typedef _param_array_struct(gs_param_int_array_s, int) gs_param_int_array;
+typedef _param_array_struct(gs_param_float_array_s, float) gs_param_float_array;
+typedef _param_array_struct(gs_param_string_array_s, gs_param_string) gs_param_string_array;
+
+#define param_string_from_string(ps, str)\
+ ((ps).data = (const byte *)(str),\
+ (ps).size = strlen((const char *)(ps).data),\
+ (ps).persistent = true)
+
+#define param_string_from_transient_string(ps, str)\
+ ((ps).data = (const byte *)(str),\
+ (ps).size = strlen((const char *)(ps).data),\
+ (ps).persistent = false)
+
+/*
+ * Define the structure for heterogenous collection values (dictionaries
+ * and heterogenous arrays).
+ */
+typedef struct gs_param_collection_s {
+ gs_param_list *list;
+ uint size;
+} gs_param_collection;
+typedef gs_param_collection gs_param_dict;
+typedef gs_param_collection gs_param_array;
+
+/*
+ * Define the sizes of the various parameter value types, indexed by type.
+ */
+#define GS_PARAM_TYPE_SIZES(dict_size)\
+ 0, sizeof(bool), sizeof(int), sizeof(long), sizeof(float),\
+ sizeof(gs_param_string), sizeof(gs_param_string),\
+ sizeof(gs_param_int_array), sizeof(gs_param_float_array),\
+ sizeof(gs_param_string_array), sizeof(gs_param_string_array),\
+ (dict_size), (dict_size), (dict_size)
+/*
+ * Define the sizes of the underlying data types contained in or pointed
+ * to by the various value types.
+ */
+#define GS_PARAM_TYPE_BASE_SIZES(dict_elt_size)\
+ 0, sizeof(bool), sizeof(int), sizeof(long), sizeof(float),\
+ 1, 1, sizeof(int), sizeof(float),\
+ sizeof(gs_param_string), sizeof(gs_param_string),\
+ (dict_elt_size), (dict_elt_size), (dict_elt_size)
+
+/* Define tables with 0 for the sizes of the heterogenous collections. */
+extern const byte gs_param_type_sizes[];
+extern const byte gs_param_type_base_sizes[];
+
+/* Define a union capable of holding any parameter value. */
+#define GS_PARAM_VALUE_UNION(dict_type)\
+ bool b;\
+ int i;\
+ long l;\
+ float f;\
+ gs_param_string s;\
+ gs_param_string n;\
+ gs_param_int_array ia;\
+ gs_param_float_array fa;\
+ gs_param_string_array sa;\
+ gs_param_string_array na;\
+ dict_type d
+typedef union gs_param_value_s {
+ GS_PARAM_VALUE_UNION(gs_param_collection);
+} gs_param_value;
+
+/*
+ * Define a structure containing a dynamically typed value (a value along
+ * with its type).
+ */
+typedef struct gs_param_typed_value_s {
+ gs_param_value value;
+ gs_param_type type;
+} gs_param_typed_value;
+/*
+ * Garbage collection of gs_param_values depends on the value type and on
+ * the 'd' member of the union. We provide enum_ptrs and reloc_ptrs
+ * procedures that handle all the other cases -- i.e., cases other than
+ * heterogenous collections.
+ */
+struct_proc_enum_ptrs(gs_param_typed_value_enum_ptrs);
+struct_proc_reloc_ptrs(gs_param_typed_value_reloc_ptrs);
+#define gs_param_typed_value_max_ptrs 1
+
+/*
+ * Define the representation alternatives for heterogenous collections.
+ * _any must be 0, for Boolean testing.
+ */
+typedef enum {
+
+ /* Create or accept a general dictionary. */
+
+ gs_param_collection_dict_any = 0,
+
+ /* Create a dictionary with integer string keys ("0", "1", ...); */
+ /* accept a dictionary with integer string keys, or a heterogenous */
+ /* array. */
+
+ gs_param_collection_dict_int_keys = 1,
+
+ /* Create an array if possible, otherwise a dictionary with integer */
+ /* string keys; accept the same types as dict_int_keys. */
+
+ gs_param_collection_array = 2
+
+} gs_param_collection_type_t;
+
+/*
+ * Define the 'policies' for handling out-of-range parameter values.
+ * This is not an enum, because some parameters may recognize other values.
+ */
+#define gs_param_policy_signal_error 0
+#define gs_param_policy_ignore 1
+#define gs_param_policy_consult_user 2
+
+/*
+ * Define an enumerator used to iterate through the keys in a list.
+ *
+ * All the members of the union must be used such that memset(0) entire
+ * union means 'beginning of enumeration'.
+ */
+typedef union gs_param_enumerator_s {
+ int intval;
+ long longval;
+ void *pvoid;
+ char *pchar;
+} gs_param_enumerator_t;
+typedef gs_param_string gs_param_key_t;
+
+/*
+ * Define the object procedures. Note that the same interface is used
+ * both for getting and for setting parameter values. (This is a bit
+ * of a hack, and we might change it someday.) The procedures return
+ * as follows:
+ * - 'reading' procedures ('put' operations from the client's viewpoint)
+ * return 1 for a missing parameter, 0 for a valid parameter, <0 on error.
+ * - 'writing' procedures ('get' operations from the client's viewpoint)
+ * return 0 or 1 if successful, <0 on error.
+ *
+ * A lazy implementation can use the default procedures for scalar and
+ * homogenous collection types: these just called xmit_typed.
+ */
+
+/*
+ * Transmitting variable-size objects requires some extra care.
+ * - When writing an array, string, name, or dictionary, the
+ * implementation (not the client) sets all the fields of the value.
+ * - When reading an array, string, or name, the client must set
+ * all the fields of the value.
+ * - When reading a dictionary, the client must set the size field
+ * before calling begin_write_dict; the implementation of begin_write_dict
+ * allocates the list.
+ */
+
+/*
+ * Setting parameters must use a "two-phase commit" policy. Specifically,
+ * any put_params procedure must observe the following discipline:
+
+ 1. For each parameter known to the device, ask the parameter list if
+ there is a new value, and if so, make all necessary validity checks. If any
+ check fails, call param_signal_error for that parameter, but continue to
+ check further parameters. Normally, this step should not alter the state of
+ the device; however, if the device allows changing any parameters that are
+ read-only by default (for example, BitsPerPixel or ProcessColorModel), or if
+ it replaces the default put_params behavior for any parameter (for example,
+ if it handles MediaSize or Resolution itself to forestall the normal closing
+ of the device when these are set), step 1 of put_params must change the
+ parameters in the device state, and step 2 must undo the changes if
+ returning an error.
+
+ 2. Call the "superclass" put_params routine. For printer devices,
+ this is gdev_prn_put_params; for other devices, it is gx_default_put_params.
+ Note that this must be done even if errors were detected in step 1. If this
+ routine returns an error code, or if step 1 detected an error, undo any
+ changes that step 1 made in the device state, and return the error code.
+
+ 3. Install the new parameter values in the device. If necessary,
+ close the device first; a higher-level routine (gs_putdeviceparams) will
+ reopen the device if necessary.
+
+ */
+
+typedef struct gs_param_list_procs_s {
+
+ /* Transmit a typed value. */
+ /*
+ * Note that read/write_typed do a begin_read/write_collection
+ * if the type is one of the heterogenous collection types.
+ * Note also that even for reading, the caller must set pvalue->type
+ * to the desired type or to gs_param_type_any.
+ */
+
+#define param_proc_xmit_typed(proc)\
+ int proc(gs_param_list *, gs_param_name, gs_param_typed_value *)
+ param_proc_xmit_typed((*xmit_typed));
+ /* See below for param_read_[requested_]typed */
+#define param_write_typed(plist, pkey, pvalue)\
+ (*(plist)->procs->xmit_typed)(plist, pkey, pvalue)
+
+ /* Start transmitting a dictionary or heterogenous value. */
+
+#define param_proc_begin_xmit_collection(proc)\
+ int proc(gs_param_list *, gs_param_name, gs_param_dict *,\
+ gs_param_collection_type_t)
+ param_proc_begin_xmit_collection((*begin_xmit_collection));
+#define param_begin_read_collection(plist, pkey, pvalue, coll_type)\
+ (*(plist)->procs->begin_xmit_collection)(plist, pkey, pvalue, coll_type)
+#define param_begin_read_dict(l, k, v, int_keys)\
+ param_begin_read_collection(l, k, v,\
+ (int_keys ? gs_param_collection_dict_int_keys :\
+ gs_param_collection_dict_any))
+#define param_begin_write_collection(plist, pkey, pvalue, coll_type)\
+ (*(plist)->procs->begin_xmit_collection)(plist, pkey, pvalue, coll_type)
+#define param_begin_write_dict(l, k, v, int_keys)\
+ param_begin_write_collection(l, k, v,\
+ (int_keys ? gs_param_collection_dict_int_keys :\
+ gs_param_collection_dict_any))
+
+ /* Finish transmitting a collection value. */
+
+#define param_proc_end_xmit_collection(proc)\
+ int proc(gs_param_list *, gs_param_name, gs_param_dict *)
+ param_proc_end_xmit_collection((*end_xmit_collection));
+#define param_end_read_collection(plist, pkey, pvalue)\
+ (*(plist)->procs->end_xmit_collection)(plist, pkey, pvalue)
+#define param_end_read_dict(l, k, v) param_end_read_collection(l, k, v)
+#define param_end_write_collection(plist, pkey, pvalue)\
+ (*(plist)->procs->end_xmit_collection)(plist, pkey, pvalue)
+#define param_end_write_dict(l, k, v) param_end_write_collection(l, k, v)
+
+ /*
+ * Get the next key in sequence.
+ * (Only used when reading.)
+ * Use param_init_enumerator(...) to reset to first key.
+ */
+
+#define param_proc_next_key(proc)\
+ int proc(gs_param_list *, gs_param_enumerator_t *, gs_param_key_t *)
+ param_proc_next_key((*next_key));
+#define param_get_next_key(plist, penum, pkey)\
+ (*(plist)->procs->next_key)(plist, penum, pkey)
+
+ /*
+ * Request a specific parameter. (Only used when writing, before
+ * writing any values.) If no specific parameters are requested,
+ * param_requested always returns -1; if specific parameters
+ * are requested, param_requested will return 1 for those,
+ * and may return either 0 or 1 for others.
+ */
+
+#define param_proc_request(proc)\
+ int proc(gs_param_list *, gs_param_name)
+ param_proc_request((*request));
+
+#define param_request(plist, pkey)\
+ ((plist)->procs->request(plist, pkey))
+
+ /*
+ * Determine whether a given key has been requested. (Only used
+ * when writing.) A return value of -1 means that no specific
+ * parameters have been requested; 0 means specific parameters have
+ * been requested, but not this one; 1 means this parameter has
+ * been requested specifically.
+ */
+
+#define param_proc_requested(proc)\
+ int proc(const gs_param_list *, gs_param_name)
+ param_proc_requested((*requested));
+#define param_requested(plist, pkey)\
+ (*(plist)->procs->requested)(plist, pkey)
+
+ /* Get the 'policy' associated with an out-of-range parameter value. */
+ /* (Only used when reading.) */
+
+#define param_proc_get_policy(proc)\
+ int proc(gs_param_list *, gs_param_name)
+ param_proc_get_policy((*get_policy));
+#define param_get_policy(plist, pkey)\
+ (*(plist)->procs->get_policy)(plist, pkey)
+
+ /*
+ * Signal an error. (Only used when reading.)
+ * The procedure may return a different error code,
+ * or may return 0 indicating that the error is to be ignored.
+ */
+
+#define param_proc_signal_error(proc)\
+ int proc(gs_param_list *, gs_param_name, int)
+ param_proc_signal_error((*signal_error));
+#define param_signal_error(plist, pkey, code)\
+ (*(plist)->procs->signal_error)(plist, pkey, code)
+#define param_return_error(plist, pkey, code)\
+ return_error(param_signal_error(plist, pkey, code))
+
+ /*
+ * "Commit" a set of changes. (Only used when reading.)
+ * This is called at the end of the first phase.
+ */
+
+#define param_proc_commit(proc)\
+ int proc(gs_param_list *)
+ param_proc_commit((*commit));
+#define param_commit(plist)\
+ (*(plist)->procs->commit)(plist)
+
+} gs_param_list_procs;
+
+/* Transmit typed parameters. */
+int param_read_requested_typed(gs_param_list *, gs_param_name,
+ gs_param_typed_value *);
+
+#define param_read_typed(plist, pkey, pvalue)\
+ ((pvalue)->type = gs_param_type_any,\
+ param_read_requested_typed(plist, pkey, pvalue))
+
+/* Transmit parameters of specific types. */
+
+/*************** WARNING ********************
+ * You CANNOT use heap allocated strings as
+ * KEYS in param lists. Keys MUST be string
+ * constants.
+ * String values can be heap allocated by
+ * using param_string_from_transient_string()
+ * rather than param_string_from_string()
+ *
+ ********************************************/
+int param_read_null(gs_param_list *, gs_param_name);
+int param_write_null(gs_param_list *, gs_param_name);
+int param_read_bool(gs_param_list *, gs_param_name, bool *);
+int param_write_bool(gs_param_list *, gs_param_name, const bool *);
+int param_read_int(gs_param_list *, gs_param_name, int *);
+int param_write_int(gs_param_list *, gs_param_name, const int *);
+int param_read_long(gs_param_list *, gs_param_name, long *);
+int param_write_long(gs_param_list *, gs_param_name, const long *);
+int param_read_float(gs_param_list *, gs_param_name, float *);
+int param_write_float(gs_param_list *, gs_param_name, const float *);
+int param_read_string(gs_param_list *, gs_param_name, gs_param_string *);
+int param_write_string(gs_param_list *, gs_param_name,
+ const gs_param_string *);
+int param_read_name(gs_param_list *, gs_param_name, gs_param_string *);
+int param_write_name(gs_param_list *, gs_param_name,
+ const gs_param_string *);
+int param_read_int_array(gs_param_list *, gs_param_name,
+ gs_param_int_array *);
+int param_write_int_array(gs_param_list *, gs_param_name,
+ const gs_param_int_array *);
+int param_write_int_values(gs_param_list *, gs_param_name,
+ const int *, uint, bool);
+int param_read_float_array(gs_param_list *, gs_param_name,
+ gs_param_float_array *);
+int param_write_float_array(gs_param_list *, gs_param_name,
+ const gs_param_float_array *);
+int param_write_float_values(gs_param_list *, gs_param_name,
+ const float *, uint, bool);
+int param_read_string_array(gs_param_list *, gs_param_name,
+ gs_param_string_array *);
+int param_write_string_array(gs_param_list *, gs_param_name,
+ const gs_param_string_array *);
+int param_read_name_array(gs_param_list *, gs_param_name,
+ gs_param_string_array *);
+int param_write_name_array(gs_param_list *, gs_param_name,
+ const gs_param_string_array *);
+
+/*
+ * Define an abstract parameter list. Implementations are concrete
+ * subclasses.
+ *
+ * The persisent_keys flag allows for both statically and dynamically
+ * allocated keys. The default is static (the keys are normally C string
+ * literals).
+ */
+#define gs_param_list_common\
+ const gs_param_list_procs *procs;\
+ gs_memory_t *memory; /* for allocating coerced arrays */\
+ bool persistent_keys
+struct gs_param_list_s {
+ gs_param_list_common;
+};
+
+/* Set whether the keys for param_write_XXX are persistent. */
+/* VMS limits procedure names to 31 characters. */
+#define gs_param_list_set_persistent_keys gs_param_list_set_persist_keys
+void gs_param_list_set_persistent_keys(gs_param_list *, bool);
+
+/* Initialize a parameter list key enumerator. */
+void param_init_enumerator(gs_param_enumerator_t * penum);
+
+/*
+ * The following interface provides a convenient way to read and set
+ * collections of parameters of any type other than dictionaries.
+ */
+
+typedef struct gs_param_item_s {
+ const char *key;
+ byte /*gs_param_type */ type;
+ short offset; /* offset of value in structure */
+} gs_param_item_t;
+#define gs_param_item_end { 0 } /* list terminator */
+/*
+ * Transfer a collection of parameters.
+ * For param_write_items, if a parameter value is equal to the value in
+ * the optional default_obj, the item isn't transferred.
+ */
+int gs_param_read_items(gs_param_list * plist, void *obj,
+ const gs_param_item_t * items);
+int gs_param_write_items(gs_param_list * plist, const void *obj,
+ const void *default_obj,
+ const gs_param_item_t * items);
+
+/* Internal procedure to initialize the common part of a parameter list. */
+void gs_param_list_init(gs_param_list *, const gs_param_list_procs *,
+ gs_memory_t *);
+
+/*
+ * Internal procedure to read a value, with coercion if requested, needed,
+ * and possible. If mem != 0, we can coerce int arrays to float arrays, and
+ * possibly do other coercions later.
+ */
+int param_coerce_typed(gs_param_typed_value * pvalue,
+ gs_param_type req_type, gs_memory_t * mem);
+
+/* ---------------- Default implementation ---------------- */
+
+/*
+ * Provide default generic implementations of param_request and
+ * param_requested.
+ */
+param_proc_request(gs_param_request_default); /* does nothing */
+param_proc_requested(gs_param_requested_default); /* always returns true */
+
+/*
+ * Define a default implementation, intended to be usable easily
+ * from C code. The intended usage pattern is:
+ gs_c_param_list list;
+ [... other code here ...]
+ gs_c_param_list_write(&list, mem);
+ [As many as needed:]
+ code = param_write_XXX(&list, "ParamName", &param_value);
+ [Check code for <0]
+ gs_c_param_list_read(&list);
+ code = gs_putdeviceparams(dev, &list);
+ gs_c_param_list_release(&list);
+ [Check code for <0]
+ if ( code == 1 )
+ {
+ code = (*dev_proc(dev, open_device))(dev);
+ [Check code for <0]
+ }
+ *
+ * This implementation also has the special property that it can forward
+ * unrecognized param_read_ calls to another parameter list, called the
+ * target. This allows constructing incrementally modified parameter lists.
+ * Note that this is only relevant for put_params (reading from the
+ * parameter list).
+ */
+
+typedef struct gs_c_param_s gs_c_param; /* opaque here */
+typedef struct gs_c_param_list_s {
+ gs_param_list_common;
+ gs_c_param *head;
+ gs_param_list *target;
+ uint count;
+ bool any_requested;
+ gs_param_collection_type_t coll_type;
+} gs_c_param_list;
+#define private_st_c_param_list() /* in gsparam.c */\
+ gs_private_st_ptrs2(st_c_param_list, gs_c_param_list, "c_param_list",\
+ c_param_list_enum_ptrs, c_param_list_reloc_ptrs, head, target)
+
+/* Define a GC descriptor for gs_param_string. */
+/* This structure descriptor is only for non persistent gs_param_strings. */
+#define private_st_gs_param_string() /* in gdevdevn.c */\
+ gs_private_st_composite(st_gs_param_string, gs_param_string, "gs_param_string",\
+ param_string_enum_ptrs, param_string_reloc_ptrs)
+
+/* Set the target of a C parameter list. */
+void gs_c_param_list_set_target(gs_c_param_list *, gs_param_list *);
+
+/*
+ * Clients normally allocate the gs_c_param_list on the stack, but we
+ * provide a procedure for allocating one in memory.
+ */
+gs_c_param_list *gs_c_param_list_alloc(gs_memory_t *, client_name_t);
+void gs_c_param_list_write(gs_c_param_list *, gs_memory_t *);
+void gs_c_param_list_write_more(gs_c_param_list *); /* switch back to writing, no init */
+void gs_c_param_list_read(gs_c_param_list *); /* switch to reading */
+void gs_c_param_list_release(gs_c_param_list *);
+
+#endif /* gsparam_INCLUDED */