aboutsummaryrefslogtreecommitdiff
path: root/generic/Window.c
diff options
context:
space:
mode:
Diffstat (limited to 'generic/Window.c')
-rw-r--r--generic/Window.c169
1 files changed, 147 insertions, 22 deletions
diff --git a/generic/Window.c b/generic/Window.c
index 4486af9..de12103 100644
--- a/generic/Window.c
+++ b/generic/Window.c
@@ -321,6 +321,54 @@ Query(ZnItem item,
return TCL_OK;
}
+/*
+ * Compute the transformation to be used and the origin
+ * of the window (upper left point in item coordinates).
+ */
+static ZnTransfo *
+ComputeTransfoAndOrigin(ZnItem item,
+ ZnPoint *origin)
+{
+ WindowItem wind = (WindowItem) item;
+ ZnTransfo *t;
+
+ /*
+ * The connected item support anchors, this is checked by configure.
+ */
+ if (item->connected_item != ZN_NO_ITEM) {
+ ZnTransfo inv;
+
+ item->connected_item->class->GetAnchor(item->connected_item,
+ wind->connection_anchor,
+ origin);
+
+ /* GetAnchor return a position in device coordinates not in
+ * the item coordinate space. To compute the icon origin
+ * (upper left corner), we must apply the inverse transform
+ * to the ref point before calling anchor2origin.
+ */
+ ZnTransfoInvert(item->transfo, &inv);
+ ZnTransformPoint(&inv, origin, origin);
+ /*
+ * The relevant transform in case of an attachment is the item
+ * transform alone. This is case of local coordinate space where
+ * only the translation is a function of the whole transform
+ * stack, scale and rotation are reset.
+ */
+ t = item->transfo;
+ }
+ else {
+ origin->x = origin->y = 0;
+ t = item->wi->current_transfo;
+ }
+
+ ZnAnchor2Origin(origin, (ZnReal) wind->real_width, (ZnReal) wind->real_height,
+ wind->anchor, origin);
+ //origin->x = ZnNearestInt(origin->x);
+ //origin->y = ZnNearestInt(origin->y);
+
+ return t;
+}
/*
**********************************************************************************
@@ -333,8 +381,10 @@ static void
ComputeCoordinates(ZnItem item,
ZnBool force)
{
- ZnWInfo *wi = item->wi;
- WindowItem wind = (WindowItem) item;
+ ZnWInfo *wi = item->wi;
+ WindowItem wind = (WindowItem) item;
+ ZnPoint origin;
+ ZnTransfo *t;
ZnResetBBox(&item->item_bounding_box);
@@ -357,23 +407,8 @@ ComputeCoordinates(ZnItem item,
}
}
- /*
- * The connected item support anchors, this is checked by
- * configure.
- */
- if (item->connected_item != ZN_NO_ITEM) {
- item->connected_item->class->GetAnchor(item->connected_item,
- wind->connection_anchor,
- &wind->pos_dev);
- }
- else {
- ZnPoint pos;
- pos.x = pos.y = 0.0;
- ZnTransformPoint(wi->current_transfo, &pos, &wind->pos_dev);
- }
-
- ZnAnchor2Origin(&wind->pos_dev, (ZnReal) wind->real_width, (ZnReal) wind->real_height,
- wind->anchor, &wind->pos_dev);
+ t = ComputeTransfoAndOrigin(item, &origin);
+ ZnTransformPoint(wi->current_transfo, &origin, &wind->pos_dev);
wind->pos_dev.x = ZnNearestInt(wind->pos_dev.x);
wind->pos_dev.y = ZnNearestInt(wind->pos_dev.y);
@@ -533,10 +568,100 @@ Pick(ZnItem item,
*
**********************************************************************************
*/
-static void
-PostScript(ZnItem item,
- ZnBool prepass)
+#ifdef X_GetImage
+static int
+xerrorhandler(ClientData client_data,
+ XErrorEvent *e)
{
+ return 0;
+}
+#endif
+
+static int
+PostScript(ZnItem item,
+ ZnBool prepass,
+ ZnBBox *area)
+{
+ ZnWInfo *wi = item->wi;
+ WindowItem wind = (WindowItem) item;
+ char path[256];
+ XImage *ximage;
+ int result;
+ ZnPoint origin;
+ Tcl_DString buffer1, buffer2;
+#ifdef X_GetImage
+ Tk_ErrorHandler handle;
+#endif
+
+ sprintf(path, "\n%%%% %s item (%s, %d x %d)\n%.15g %.15g translate\n",
+ Tk_Class(wind->win), Tk_PathName(wind->win), wind->real_width, wind->real_height,
+ wind->pos_dev.x, wind->pos_dev.y);
+ Tcl_AppendResult(wi->interp, path, NULL);
+
+ ComputeTransfoAndOrigin(item, &origin);
+
+ sprintf(path, "/InitialTransform load setmatrix\n"
+ "%.15g %.15g translate\n"
+ "1 -1 scale\n",
+ wind->pos_dev.x, wind->pos_dev.y + wind->real_height);
+ Tcl_AppendResult(wi->interp, path, NULL);
+
+ /* first try if the widget has its own "postscript" command. If it
+ * exists, this will produce much better postscript than
+ * when a pixmap is used.
+ */
+ Tcl_DStringInit(&buffer1);
+ Tcl_DStringInit(&buffer2);
+ Tcl_DStringGetResult(wi->interp, &buffer2);
+ sprintf(path, "%s postscript -prolog 0\n", Tk_PathName(wind->win));
+ result = Tcl_Eval(wi->interp, path);
+ Tcl_DStringGetResult(wi->interp, &buffer1);
+ Tcl_DStringResult(wi->interp, &buffer2);
+ Tcl_DStringFree(&buffer2);
+
+ if (result == TCL_OK) {
+ Tcl_AppendResult(wi->interp, "50 dict begin\nsave\ngsave\n", NULL);
+ sprintf (path, "0 %d moveto %d 0 rlineto 0 -%d rlineto -%d",
+ wind->real_height, wind->real_width, wind->real_height, wind->real_width);
+ Tcl_AppendResult(wi->interp, path, NULL);
+ Tcl_AppendResult(wi->interp, " 0 rlineto closepath\n",
+ "1.000 1.000 1.000 setrgbcolor AdjustColor\nfill\ngrestore\n",
+ Tcl_DStringValue(&buffer1), "\nrestore\nend\n\n\n", NULL);
+ Tcl_DStringFree(&buffer1);
+
+ return result;
+ }
+ Tcl_DStringFree(&buffer1);
+
+ /*
+ * If the window is off the screen it will generate an BadMatch/XError
+ * We catch any BadMatch errors here
+ */
+#ifdef X_GetImage
+ handle = Tk_CreateErrorHandler(wi->dpy, BadMatch, X_GetImage, -1,
+ xerrorhandler, (ClientData) wind->win);
+#endif
+
+ /*
+ * Generate an XImage from the window. We can then read pixel
+ * values out of the XImage.
+ */
+ ximage = XGetImage(wi->dpy, Tk_WindowId(wind->win), 0, 0, (unsigned int) wind->real_width,
+ (unsigned int) wind->real_height, AllPlanes, ZPixmap);
+
+#ifdef X_GetImage
+ Tk_DeleteErrorHandler(handle);
+#endif
+
+ if (ximage == NULL) {
+ return TCL_OK;
+ }
+
+ result = ZnPostscriptXImage(wi->interp, wind->win, wi->ps_info, ximage,
+ 0, 0, wind->real_width, wind->real_height);
+ XDestroyImage(ximage);
+
+ return result;
}