summaryrefslogtreecommitdiff
path: root/psi
diff options
context:
space:
mode:
authorRobin Watts <Robin.Watts@artifex.com>2020-06-04 19:27:15 +0100
committerRobin Watts <Robin.Watts@artifex.com>2020-06-25 00:19:12 +0100
commit4438e3e5bc4dfc9e46fc86d86d912171ec582a4e (patch)
treec2cbc61774320346337f2311876f4bc9de46d011 /psi
parent7e427246abb151cde9154783775acfaa776b502e (diff)
downloadghostpdl-4438e3e5bc4dfc9e46fc86d86d912171ec582a4e.tar.gz
Rework display device "DisplayHandle" passing.
Add gsapi_{,de}register_callout API. This allows integrators to register handlers for "callouts" from gs devices. The first example of such a callout is the display device. Previously, this has relied on the gsapi_set_display_callback API to pass a pointer to a structure into the core, from where it was hackily poked into the display device structure. Instead, we now have the display device "callout" to registered handlers to get the structure and the handle to use. The legacy API is maintained by the API level implementing a handler to return the display callback in response to the devices callout. The code to do the 'poking' of the display device has therefore been removed, and replaced by code that checks to see if an opened device needs reopening after init, if so, opens/closes it.
Diffstat (limited to 'psi')
-rw-r--r--psi/gsdll2.def2
-rw-r--r--psi/gsdll32.def2
-rw-r--r--psi/gsdll32metro.def3
-rw-r--r--psi/gsdll64.def2
-rw-r--r--psi/gsdll64metro.def2
-rw-r--r--psi/gsdllARM32metro.def2
-rw-r--r--psi/iapi.c62
-rw-r--r--psi/iapi.h33
-rw-r--r--psi/idisp.c70
-rw-r--r--psi/idisp.h5
-rw-r--r--psi/imain.c6
-rw-r--r--psi/int.mak2
12 files changed, 132 insertions, 59 deletions
diff --git a/psi/gsdll2.def b/psi/gsdll2.def
index d69b60c6e..175e22163 100644
--- a/psi/gsdll2.def
+++ b/psi/gsdll2.def
@@ -18,6 +18,8 @@ EXPORTS
gsapi_set_poll
gsapi_set_poll_with_handle
gsapi_set_display_callback
+ gsapi_register_callout
+ gsapi_deregister_callout
gsapi_set_arg_encoding
gsapi_set_default_device_list
gsapi_get_default_device_list
diff --git a/psi/gsdll32.def b/psi/gsdll32.def
index bef2fe92b..c21b24a8d 100644
--- a/psi/gsdll32.def
+++ b/psi/gsdll32.def
@@ -30,6 +30,8 @@ EXPORTS
gsapi_set_poll
gsapi_set_poll_with_handle
gsapi_set_display_callback
+ gsapi_register_callout
+ gsapi_deregister_callout
gsapi_set_arg_encoding
gsapi_set_default_device_list
gsapi_get_default_device_list
diff --git a/psi/gsdll32metro.def b/psi/gsdll32metro.def
index 49f38c8b4..4d014e193 100644
--- a/psi/gsdll32metro.def
+++ b/psi/gsdll32metro.def
@@ -30,6 +30,9 @@ EXPORTS
gsapi_set_poll
gsapi_set_poll_with_handle
gsapi_set_display_callback
+ gsapi_set_display_callback_with_handle
+ gsapi_register_callout
+ gsapi_deregister_callout
gsapi_set_arg_encoding
gsapi_set_default_device_list
gsapi_get_default_device_list
diff --git a/psi/gsdll64.def b/psi/gsdll64.def
index 44289e923..edc6bb311 100644
--- a/psi/gsdll64.def
+++ b/psi/gsdll64.def
@@ -30,6 +30,8 @@ EXPORTS
gsapi_set_poll
gsapi_set_poll_with_handle
gsapi_set_display_callback
+ gsapi_register_callout
+ gsapi_deregister_callout
gsapi_set_arg_encoding
gsapi_set_default_device_list
gsapi_get_default_device_list
diff --git a/psi/gsdll64metro.def b/psi/gsdll64metro.def
index cc05cf0bf..9991270fe 100644
--- a/psi/gsdll64metro.def
+++ b/psi/gsdll64metro.def
@@ -30,6 +30,8 @@ EXPORTS
gsapi_set_poll
gsapi_set_poll_with_handle
gsapi_set_display_callback
+ gsapi_register_callout
+ gsapi_deregister_callout
gsapi_set_arg_encoding
gsapi_set_default_device_list
gsapi_get_default_device_list
diff --git a/psi/gsdllARM32metro.def b/psi/gsdllARM32metro.def
index 0ff322ea0..c54be9a5b 100644
--- a/psi/gsdllARM32metro.def
+++ b/psi/gsdllARM32metro.def
@@ -30,6 +30,8 @@ EXPORTS
gsapi_set_poll
gsapi_set_poll_with_handle
gsapi_set_display_callback
+ gsapi_register_callout
+ gsapi_deregister_callout
gsapi_set_arg_encoding
gsapi_set_default_device_list
gsapi_get_default_device_list
diff --git a/psi/iapi.c b/psi/iapi.c
index f47fe1531..36d3d0150 100644
--- a/psi/iapi.c
+++ b/psi/iapi.c
@@ -33,6 +33,7 @@
#include "gslibctx.h"
#include "gp.h"
#include "gsargs.h"
+#include "gdevdsp.h"
typedef struct { int a[(int)GS_ARG_ENCODING_LOCAL == (int)PS_ARG_ENCODING_LOCAL ? 1 : -1]; } compile_time_assert_0;
typedef struct { int a[(int)GS_ARG_ENCODING_UTF8 == (int)PS_ARG_ENCODING_UTF8 ? 1 : -1]; } compile_time_assert_1;
@@ -131,18 +132,77 @@ gsapi_set_poll_with_handle(void *instance,
return 0;
}
+static int
+legacy_display_callout(void *instance,
+ void *handle,
+ const char *dev_name,
+ int id,
+ int size,
+ void *data)
+{
+ gs_main_instance *inst = (gs_main_instance *)instance;
+
+ if (dev_name == NULL)
+ return -1;
+ if (strcmp(dev_name, "display") != 0)
+ return -1;
+
+ if (id == DISPLAY_CALLOUT_GET_CALLBACK_LEGACY) {
+ /* get display callbacks */
+ gs_display_get_callback_t *cb = (gs_display_get_callback_t *)data;
+ cb->callback = inst->display;
+ return 0;
+ }
+ return -1;
+}
+
/* Set the display callback structure */
GSDLLEXPORT int GSDLLAPI
gsapi_set_display_callback(void *instance, display_callback *callback)
{
gs_lib_ctx_t *ctx = (gs_lib_ctx_t *)instance;
+ gs_main_instance *minst;
+ int code;
if (instance == NULL)
return gs_error_Fatal;
- get_minst_from_memory(ctx->memory)->display = callback;
+ minst = get_minst_from_memory(ctx->memory);
+ if (minst->display == NULL && callback != NULL) {
+ /* First registration. */
+ code = gs_lib_ctx_register_callout(minst->heap,
+ legacy_display_callout,
+ minst);
+ if (code < 0)
+ return code;
+ }
+ if (minst->display != NULL && callback == NULL) {
+ /* Deregistered. */
+ gs_lib_ctx_deregister_callout(minst->heap,
+ legacy_display_callout,
+ minst);
+ }
+ minst->display = callback;
/* not in a language switched build */
return 0;
}
+GSDLLEXPORT int GSDLLAPI
+gsapi_register_callout(void *instance, gs_callout fn, void *handle)
+{
+ gs_lib_ctx_t *ctx = (gs_lib_ctx_t *)instance;
+ if (instance == NULL)
+ return gs_error_Fatal;
+ return gs_lib_ctx_register_callout(ctx->memory, fn, handle);
+}
+
+GSDLLEXPORT void GSDLLAPI
+gsapi_deregister_callout(void *instance, gs_callout fn, void *handle)
+{
+ gs_lib_ctx_t *ctx = (gs_lib_ctx_t *)instance;
+ if (instance == NULL)
+ return;
+ gs_lib_ctx_deregister_callout(ctx->memory, fn, handle);
+}
+
/* Set/Get the default device list string */
GSDLLEXPORT int GSDLLAPI
gsapi_set_default_device_list(void *instance, const char *list, int listlen)
diff --git a/psi/iapi.h b/psi/iapi.h
index 2eb992a4b..605b2f50a 100644
--- a/psi/iapi.h
+++ b/psi/iapi.h
@@ -226,10 +226,43 @@ GSDLLEXPORT int GSDLLAPI gsapi_set_poll_with_handle(void *instance,
* If the display device is used, this must be called
* after gsapi_new_instance() and before gsapi_init_with_args().
* See gdevdisp.h for more details.
+ * DEPRECATED: Use the gsapi_register_callback mechanism instead.
*/
GSDLLEXPORT int GSDLLAPI gsapi_set_display_callback(
void *instance, display_callback *callback);
+/* The callout mechanism allows devices to query "callers" (users of the
+ * DLL) in device specific ways. The callout function pointer type will
+ * be called with:
+ * callout_handle = the value given at registration
+ * device_name = the name of the current device
+ * id = An integer, guaranteed to be unique within the
+ * callouts from a given device, identifying the
+ * purpose of this call.
+ * size = device/id specific, but typically the size of 'data'.
+ * data = device/id specific, but typically the pointer to
+ * an in/out data block.
+ * Returns an error code (gs_error_unknownerror (-1) if unclaimed,
+ * non-negative on success, standard gs error numbers recommended).
+ */
+typedef int (*gs_callout)(void *instance,
+ void *callout_handle,
+ const char *device_name,
+ int id,
+ int size,
+ void *data);
+
+/* Register a handler for gs callouts.
+ * This must be called after gsapi_new_instance() and (typically)
+ * before gsapi_init_with_args().
+ */
+GSDLLEXPORT int GSDLLAPI gsapi_register_callout(
+ void *instance, gs_callout callout, void *callout_handle);
+
+/* Deregister a handler for gs callouts. */
+GSDLLEXPORT void GSDLLAPI gsapi_deregister_callout(
+ void *instance, gs_callout callout, void *callout_handle);
+
/* Set the string containing the list of default device names
* for example "display x11alpha x11 bbox". Allows the calling
* application to influence which device(s) gs will try in order
diff --git a/psi/idisp.c b/psi/idisp.c
index d1efcbc16..ab8d070cd 100644
--- a/psi/idisp.c
+++ b/psi/idisp.c
@@ -47,70 +47,36 @@
#include "gsequivc.h"
#include "gdevdsp.h"
#include "gdevdsp2.h"
+#include "gxgstate.h"
+#include "gxdevsop.h"
int
-display_set_callback(gs_main_instance *minst, display_callback *callback)
+reopen_device_if_required(gs_main_instance *minst)
{
i_ctx_t *i_ctx_p;
- bool was_open;
int code;
- int exit_code = 0;
- os_ptr op;
gx_device *dev;
- gx_device_display *ddev;
-
- /* If display device exists, copy prototype if needed and return
- * device true
- * If it doesn't exist, return
- * false
- */
- const char getdisplay[] =
- "devicedict /display known dup { /display finddevice exch } if";
- code = gs_main_run_string(minst, getdisplay, 0, &exit_code,
- &minst->error_object);
- if (code < 0)
- return code;
i_ctx_p = minst->i_ctx_p; /* run_string may change i_ctx_p if GC */
- op = osp;
- check_type(*op, t_boolean);
- if (op->value.boolval) {
- /* display device was included in Ghostscript so we need
- * to set the callback structure pointer within it.
- * If the device is already open, close it before
- * setting callback, then reopen it.
- */
- check_read_type(op[-1], t_device);
- if (op[-1].value.pdevice == NULL)
- /* This can happen if we invalidated devices on the stack by calling nulldevice after they were pushed */
- return_error(gs_error_undefined);
-
- dev = op[-1].value.pdevice;
+ dev = gs_currentdevice_inline(i_ctx_p->pgs);
+ if (dev == NULL)
+ /* This can happen if we invalidated devices on the stack by calling nulldevice after they were pushed */
+ return_error(gs_error_undefined);
- was_open = dev->is_open;
- if (was_open) {
- code = gs_closedevice(dev);
- if (code < 0)
- return code;
- }
+ if (!dev->is_open)
+ return 0;
- ddev = (gx_device_display *) dev;
+ if (dev_proc(dev, dev_spec_op)(dev, gxdso_reopen_after_init, NULL, 0) != 1)
+ return 0;
- /* Deal with the case where we subclassed the device before we got here */
- while (ddev->child)
- ddev = (gx_device_display *)ddev->child;
-
- ddev->callback = callback;
+ code = gs_closedevice(dev);
+ if (code < 0)
+ return code;
- if (was_open) {
- code = gs_opendevice(dev);
- if (code < 0) {
- dmprintf(dev->memory, "**** Unable to open the display device, quitting.\n");
- return code;
- }
- }
- pop(1); /* device */
+ code = gs_opendevice(dev);
+ if (code < 0) {
+ dmprintf(dev->memory, "**** Unable to reopen the device, quitting.\n");
+ return code;
}
- pop(1); /* boolean */
return 0;
}
diff --git a/psi/idisp.h b/psi/idisp.h
index 4b9eeee94..215d915bd 100644
--- a/psi/idisp.h
+++ b/psi/idisp.h
@@ -25,7 +25,8 @@
typedef struct display_callback_s display_callback;
#endif
-/* Called from imain.c to set the display callback in the device instance. */
-int display_set_callback(gs_main_instance *minst, display_callback *callback);
+/* Called from imain.c to reopen the device after initialisation if the.
+ * device requires this. This gives it a chance to refetch any callbacks. */
+int reopen_device_if_required(gs_main_instance *minst);
#endif /* idisp_INCLUDED */
diff --git a/psi/imain.c b/psi/imain.c
index ed97d06a8..6d012e2a8 100644
--- a/psi/imain.c
+++ b/psi/imain.c
@@ -306,11 +306,11 @@ int gs_main_init2aux(gs_main_instance * minst) {
if (code < 0)
return code;
minst->init_done = 2;
+
/* NB this is to be done with device parameters
* both minst->display and display_set_callback() are going away
*/
- if (minst->display)
- if ((code = display_set_callback(minst, minst->display)) < 0)
+ if ((code = reopen_device_if_required(minst)) < 0)
return code;
if ((code = gs_main_run_string(minst,
@@ -344,7 +344,7 @@ gs_main_init2(gs_main_instance * minst)
if (code < 0)
goto fail;
- i_ctx_p = minst->i_ctx_p; /* display_set_callback or run_string may change it */
+ i_ctx_p = minst->i_ctx_p; /* reopen_device_if_display or run_string may change it */
/* Now process the initial saved-pages=... argument, if any as well as saved-pages-test */
{
diff --git a/psi/int.mak b/psi/int.mak
index ec562169d..e6cf79b1e 100644
--- a/psi/int.mak
+++ b/psi/int.mak
@@ -1897,7 +1897,7 @@ gdevdsp2_h=$(DEVSRCDIR)$(D)gdevdsp2.h
$(PSOBJ)idisp.$(OBJ) : $(PSSRC)idisp.c $(OP) $(stdio__h) $(gp_h)\
$(stdpre_h) $(gscdefs_h) $(gsdevice_h) $(gsmemory_h) $(gstypes_h)\
- $(iapi_h) $(iref_h)\
+ $(iapi_h) $(iref_h) $(gxgstate_h) $(gxdevsop_h)\
$(imain_h) $(iminst_h) $(idisp_h) $(ostack_h)\
$(gx_h) $(gxdevice_h) $(gxdevmem_h) $(gdevdsp_h) $(gdevdsp2_h)\
$(INT_MAK) $(MAKEDIRS)