/* gdkDPS.c * Copyright (C) 1997, 1998, 1999 GYVE Development Team * * Author: Terumoto 'tel' HAYAKAWA * Created: * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Library General Public License for more details. * * You should have received a copy of the GNU Library General Public * License along with this library; if not, write to the Free * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #include "config.h" #include #include #include #include #if HAVE_DPS_NXAGENT #include #endif /* HAVE_DPS_NXAGENT */ #include #include #include #include #include #include "gdkDPS.h" #include "dps_raw.h" static GdkDPSAgentProduct gdk_dps_get_product_from_string(const gchar *); static gboolean gdk_dps_initialized = FALSE; static gboolean gdk_dps_finalized = FALSE; static const GDebugKey gdk_dps_debug_keys[] = { {"context", GDK_DPS_DEBUG_CONTEXT}, {"font", GDK_DPS_DEBUG_FONT}, {"line", GDK_DPS_DEBUG_LINE}, {"geometry", GDK_DPS_DEBUG_GEOMETRY}, {"intersect", GDK_DPS_DEBUG_INTERSECT}, {"misc", GDK_DPS_DEBUG_MISC}, }; static const int gdk_dps_ndebug_keys = sizeof(gdk_dps_debug_keys)/sizeof(GDebugKey); gint gdk_dps_debug_flags; void gdk_dps_init (int *argc, char ***argv) { gint i, j, k; gchar * dpsnxover = "--dpsnxover"; gchar * dpsnxhost = "--dpsnxhost"; gchar * psresourcepath = "--psresourcepath"; gchar * gdk_dps_debug = "--gdk-dps-debug"; gchar * gdk_dps_no_debug = "--gdk-dps-no-debug"; Bool extension_present; gboolean auto_launch; g_return_if_fail(gdk_dps_initialized == FALSE); #ifdef G_ENABLE_DEBUG { gchar *debug_string = getenv("GDK_DPS_DEBUG"); if (debug_string != NULL) gdk_dps_debug_flags = g_parse_debug_string (debug_string, (GDebugKey *) gdk_dps_debug_keys, gdk_dps_ndebug_keys); } #endif /* G_ENABLE_DEBUG */ for (i = 1; i< *argc;) { if (0 == strcmp (gdk_dps_debug, (*argv)[i])) { if ((i + 1) < *argc && (*argv)[i + 1]) { (*argv)[i++] = NULL; gdk_dps_debug_flags |= g_parse_debug_string ((*argv)[i], (GDebugKey *) gdk_dps_debug_keys, gdk_dps_ndebug_keys); (*argv)[i] = NULL; } else g_warning ("The argument for the option \"%s\" " "is required.\n", gdk_dps_debug); } else if (0 == strcmp (gdk_dps_no_debug, (*argv)[i])) { if ((i + 1) < *argc && (*argv)[i + 1]) { (*argv)[i++] = NULL; gdk_dps_debug_flags &= ~g_parse_debug_string ((*argv)[i], (GDebugKey *) gdk_dps_debug_keys, gdk_dps_ndebug_keys); (*argv)[i] = NULL; } else g_warning ("The argument for the option \"%s\" " "is required.\n", gdk_dps_no_debug); } else if (0 == strcmp (dpsnxover, (*argv)[i])) { if ((i + 1) < *argc && (*argv)[i + 1]) { (*argv)[i++] = NULL; if (0 == strcmp((*argv)[i], "yes")) g_return_if_fail(putenv("DPSNXOVER=True") == 0); else if (0 == strcmp((*argv)[i], "no")) g_return_if_fail(putenv("DPSNXOVER=False") == 0); else g_warning ("The argument for the option \"%s\" " "must be \"yes\" or \"no\".\n", dpsnxover); (*argv)[i] = NULL; } else g_warning ("The argument for the option \"%s\" " "is required.\n", dpsnxover); } else if (0 == strcmp (dpsnxhost, (*argv)[i])) { if ((i + 1) < *argc && (*argv)[i + 1]) { gchar * tmp; int result; (*argv)[i++] = NULL; tmp = g_strdup_printf("DPSNXHOST=%s", (*argv)[i]); result = putenv(tmp); /* g_free(tmp); */ g_return_if_fail(result == 0); (*argv)[i] = NULL; } else g_warning ("The argument for the option \"%s\" " "is required.\n", dpsnxover); } else if (0 == strcmp (psresourcepath, (*argv)[i])) { if ((i + 1) < *argc && (*argv)[i + 1]) { gchar * tmp; int result; (*argv)[i++] = NULL; tmp = g_strdup_printf("PSRESOURCEPATH=%s", (*argv)[i]); result = putenv(tmp); /* g_free(tmp); */ g_return_if_fail(result == 0); (*argv)[i] = NULL; } else g_warning ("The argument for the option \"%s\" " "is required.\n", psresourcepath); } i += 1; } for (i = 1; i < *argc; i++) { for (k = i; k < *argc; k++) if ((*argv)[k] != NULL) break; if (k > i) { k -= i; for (j = i + k; j < *argc; j++) (*argv)[j-k] = (*argv)[j]; *argc -= k; } } #if HAVE_DPS_NXAGENT auto_launch = True; #else auto_launch = False; #endif /* HAVE_DPS_NXAGENT */ extension_present = XDPSExtensionPresent(GDK_DISPLAY()); if (!extension_present) { if (auto_launch) { #if HAVE_DPS_NXAGENT XDPSNXSetClientArg(XDPSNX_AUTO_LAUNCH, (void *)True); #endif } else { g_warning("DPS Extension is not presented"); return ; } } /* TODO: Is next line needed? */ XDPSSetEventDelivery(GDK_DISPLAY(), dps_event_pass_through); gdk_dps_initialized = TRUE; return; } void gdk_dps_exit (void) { g_return_if_fail ( gdk_dps_finalized == FALSE); gdk_dps_finalized = TRUE; } GdkDPSAgentProduct gdk_dps_get_agent_product() { static GdkDPSAgentProduct gdk_dps_product = 0; if (gdk_dps_product != 0) return gdk_dps_product; g_return_val_if_fail(gdk_dps_context_get_shared (), 0); gdk_dps_context_begin(NULL); { gchar * product_name; int length; PSWProductStringLength(raw_ctxt, &length); product_name = g_new(gchar, length+1); product_name[length] = '\0'; PSWProductString(raw_ctxt, product_name); gdk_dps_product = gdk_dps_get_product_from_string(product_name); g_free(product_name); } gdk_dps_context_end(NULL); return gdk_dps_product; } static GdkDPSAgentProduct gdk_dps_get_product_from_string(const gchar * product_name) { const gchar *aladdin_product_name = "Aladdin Ghostscript"; int aladdin_product_name_prefix_length = strlen (aladdin_product_name); g_assert(product_name != NULL); if (!strncmp (aladdin_product_name, product_name, aladdin_product_name_prefix_length)) return GDK_DPS_AGENT_PRODUCT_ALADDIN_DGS; else if (!strcmp("GNU DGS", product_name)) return GDK_DPS_AGENT_PRODUCT_GNU_DGS; else return GDK_DPS_AGENT_PRODUCT_ADOBE_DPS; } GdkDPSAgentRevision gdk_dps_get_agent_revision() { g_return_val_if_fail(gdk_dps_context_get_shared (), 0); return GDK_DPS_AGENT_REVISION_5; } /* * Create context */ GdkDPSContext* gdk_dps_context_get_shared (void) { return gdk_dps_context_new(NULL); } /* Drawable */ GdkDrawable * gdk_dps_context_get_drawable(GdkDPSContext * ctxt) { g_return_val_if_fail(ctxt, NULL); return ctxt->drawable; } void gdk_dps_context_set_drawable(GdkDPSContext * ctxt, GdkDrawable * drawable) { Window x_window; gint width_dumy, height; g_return_if_fail ( ctxt ); g_return_if_fail ( drawable ); x_window = GDK_WINDOW_XWINDOW(drawable); gdk_window_get_size(drawable, &width_dumy, &height); gdk_dps_context_begin(ctxt); { if (gdk_dps_debug_flags & GDK_DPS_DEBUG_CONTEXT) g_message("Set new Xdrawable: %ld (old Xdrawable: %ld) for context: %p", x_window, GDK_WINDOW_XWINDOW(ctxt->drawable), raw_ctxt); XDPSSetContextDrawable(raw_ctxt, x_window, height); } gdk_dps_context_end(ctxt); /* * TODO, ref, unfre */ ctxt->drawable = drawable; } /* Flush & Wait */ void gdk_dps_context_flush(GdkDPSContext * ctxt) { g_return_if_fail(ctxt); gdk_dps_context_begin(ctxt); { if (gdk_dps_debug_flags & GDK_DPS_DEBUG_CONTEXT) g_message("Flush context: %p", raw_ctxt); DPSflush(raw_ctxt); if (gdk_dps_debug_flags & GDK_DPS_DEBUG_CONTEXT) g_message("Wait context: %p", raw_ctxt); DPSWaitContext(raw_ctxt); } gdk_dps_context_end(ctxt); } /* Query */ gboolean gdk_dps_context_is_shared (GdkDPSContext* ctxt) { if (ctxt == gdk_dps_context_get_shared()) return TRUE; else return FALSE; } GdkDPSContext* gdk_dps_context_new (GdkDrawable *gdk_drawable) { static GdkDPSContext* gdk_dps_shared_context = NULL; GdkDPSContext *gdk_dps_context; GdkGC *gc; DPSContext raw_ctxt; Display *x_display; Window x_window; gint width, height; if (gdk_drawable == NULL && gdk_dps_shared_context) return gdk_dps_shared_context; gdk_dps_context = g_new(GdkDPSContext, 1); if (gdk_drawable) { x_display = GDK_WINDOW_XDISPLAY(gdk_drawable); x_window = GDK_WINDOW_XWINDOW(gdk_drawable); gc = gdk_gc_new(gdk_drawable); gdk_window_get_size(gdk_drawable, &width, &height); raw_ctxt = XDPSCreateSimpleContext(x_display, x_window, GDK_GC_XGC(gc), 0, height, DPSDefaultTextBackstop, /* TextProc */ DPSDefaultErrorProc, /* ErrorProc */ NULL); /* space */ if (gdk_dps_debug_flags & GDK_DPS_DEBUG_CONTEXT) g_message("Create context: %p", raw_ctxt); } else { x_display = GDK_DISPLAY(); raw_ctxt = XDPSGetSharedContext(x_display); gc = NULL; if (raw_ctxt == NULL) { raw_ctxt = XDPSCreateSimpleContext(x_display, None, None, 0, 0, DPSDefaultTextBackstop, DPSDefaultErrorProc, NULL); if (raw_ctxt) { XDPSRegisterContext (raw_ctxt, True); if (gdk_dps_debug_flags & GDK_DPS_DEBUG_CONTEXT) g_message("Register shared context: %p", raw_ctxt); } } else if (gdk_dps_debug_flags & GDK_DPS_DEBUG_CONTEXT) g_message("Get shared context: %p", raw_ctxt); } if (!raw_ctxt) { g_free (gdk_dps_context); g_return_val_if_fail(raw_ctxt, NULL); } gdk_dps_context->raw_ctxt = raw_ctxt; gdk_dps_context->drawable= gdk_drawable; /* TODO ref, unref */ gdk_dps_context->gc = gc; if (gdk_drawable == NULL) gdk_dps_shared_context = gdk_dps_context; return gdk_dps_context; } /* * Destroy context */ void gdk_dps_context_free(GdkDPSContext *gdk_dps_context) { DPSContext raw_ctxt; GdkGC* gc; if (gdk_dps_context == NULL) gdk_dps_context = gdk_dps_context_get_shared(); g_return_if_fail(gdk_dps_context); raw_ctxt = gdk_dps_context_get_raw_context(gdk_dps_context); gc = gdk_dps_context_get_gc(gdk_dps_context); if (gdk_dps_debug_flags & GDK_DPS_DEBUG_CONTEXT) g_message("Free context: %p", raw_ctxt); if (gdk_dps_context == gdk_dps_context_get_shared()) XDPSDestroySharedContext(raw_ctxt); else DPSDestroyContext(raw_ctxt); gdk_dps_context->raw_ctxt = NULL; /* TODO: Space */ if (gc) gdk_gc_unref(gc); /* TODO: destroy? */ g_free(gdk_dps_context); } /* * Access struct internal variables */ GdkGC* gdk_dps_context_get_gc (GdkDPSContext * ctxt) { if (ctxt == NULL) ctxt = gdk_dps_context_get_shared(); g_return_val_if_fail(ctxt, 0); return ctxt->gc; } DPSContext gdk_dps_context_get_raw_context(GdkDPSContext * ctxt) { if (ctxt == NULL) ctxt = gdk_dps_context_get_shared(); g_return_val_if_fail(ctxt, 0); return ctxt->raw_ctxt; } /* * Coord */ void gdk_dps_context_update_coordtr(GdkDPSContext * ctxt, GdkDPSCoordtr * coordtr) { g_return_if_fail(ctxt); g_return_if_fail(coordtr); gdk_dps_context_begin(ctxt); { PSWGetCoordtr(raw_ctxt, coordtr->ctm, coordtr->invctm, &(coordtr->x_offset), &(coordtr->y_offset)); } gdk_dps_context_end(ctxt); gdk_dps_coordtr_make_clean(coordtr); } gboolean gdk_dps_context_try_update_coordtr(GdkDPSContext * ctxt, GdkDPSCoordtr * coordtr) { GdkDPSCoordtr backup; g_return_val_if_fail(ctxt, FALSE); g_return_val_if_fail(coordtr, FALSE); if (TRUE == gdk_dps_coordtr_is_dirty(coordtr)) { gdk_dps_coordtr_copy(coordtr, &backup); gdk_dps_context_update_coordtr(ctxt, coordtr); if (TRUE == gdk_dps_coordtr_equal(coordtr, &backup)) return FALSE; else return TRUE; } else return FALSE; }