aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorlecoanet2005-05-10 07:59:48 +0000
committerlecoanet2005-05-10 07:59:48 +0000
commit79f65d040d72f778f66f8eefdaffb6acd9799a38 (patch)
treed1e43508242bd9d6ba85e4147e444d12830b8d3a
parent72fd6b4d5f695731d2b6f4c553f7f9bcd0c43476 (diff)
downloadtkzinc-79f65d040d72f778f66f8eefdaffb6acd9799a38.zip
tkzinc-79f65d040d72f778f66f8eefdaffb6acd9799a38.tar.gz
tkzinc-79f65d040d72f778f66f8eefdaffb6acd9799a38.tar.bz2
tkzinc-79f65d040d72f778f66f8eefdaffb6acd9799a38.tar.xz
Merge of the newly developped postscript code (still not fully functional).
-rw-r--r--generic/Arc.c93
-rw-r--r--generic/Curve.c97
-rw-r--r--generic/Field.c235
-rw-r--r--generic/Field.h1
-rw-r--r--generic/Group.c66
-rw-r--r--generic/Icon.c129
-rw-r--r--generic/Image.c12
-rw-r--r--generic/Image.h31
-rw-r--r--generic/Item.h2
-rw-r--r--generic/Map.c8
-rw-r--r--generic/PostScript.c2223
-rw-r--r--generic/PostScript.h26
-rw-r--r--generic/Rectangle.c83
-rw-r--r--generic/Reticle.c8
-rw-r--r--generic/Tabular.c8
-rw-r--r--generic/Text.c72
-rw-r--r--generic/Track.c8
-rw-r--r--generic/Triangles.c58
-rw-r--r--generic/WidgetInfo.h3
-rw-r--r--generic/Window.c169
-rw-r--r--generic/tkZinc.c5
21 files changed, 2591 insertions, 746 deletions
diff --git a/generic/Arc.c b/generic/Arc.c
index 2b5f7fa..b6b0252 100644
--- a/generic/Arc.c
+++ b/generic/Arc.c
@@ -1184,10 +1184,97 @@ GetAnchor(ZnItem item,
*
**********************************************************************************
*/
-static void
-PostScript(ZnItem item,
- ZnBool prepass)
+static int
+PostScript(ZnItem item,
+ ZnBool prepass,
+ ZnBBox *area)
{
+ ArcItem arc = (ArcItem) item;
+ ZnWInfo *wi = item->wi;
+ ZnPoint *p;
+ int i, num_points;
+ char path[500];
+
+ if (ISCLEAR(arc->flags, FILLED_BIT) && !arc->line_width) {
+ return TCL_OK;
+ }
+
+ /*
+ * Create the arc path.
+ */
+ if (ISSET(arc->flags, USING_POLY_BIT)) {
+ p = ZnListArray(arc->render_shape);
+ num_points = ZnListSize(arc->render_shape);
+ sprintf(path, "%.15g %.15g moveto ", p[0].x, p[0].y);
+ Tcl_AppendResult(wi->interp, path, NULL);
+ for (i = 0; i < num_points; i++) {
+ sprintf(path, "%.15g %.15g lineto ", p[i].x, p[i].y);
+ Tcl_AppendResult(wi->interp, path, NULL);
+ }
+ Tcl_AppendResult(wi->interp, "closepath\n", NULL);
+ }
+ else {
+ sprintf(path,
+ "matrix currentmatrix\n%.15g %.15g translate %.15g %.15g scale 1 0 moveto 0 0 1 0 360 arc\nsetmatrix\n",
+ (arc->corner.x + arc->orig.x) / 2.0, (arc->corner.y + arc->orig.y) / 2.0,
+ (arc->corner.x - arc->orig.x) / 2.0, (arc->corner.y - arc->orig.y) / 2.0);
+ Tcl_AppendResult(wi->interp, path, NULL);
+ }
+
+ /*
+ * Emit code to draw the filled area.
+ */
+ if (ISSET(arc->flags, FILLED_BIT)) {
+ if (arc->line_width) {
+ Tcl_AppendResult(wi->interp, "gsave\n", NULL);
+ }
+ if (!ZnGradientFlat(arc->fill_color)) {
+ if (ZnPostscriptGradient(wi->interp, wi->ps_info, arc->fill_color,
+ arc->grad_geo, NULL) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ }
+ else if (arc->tile != ZnUnspecifiedImage) {
+ if (!ZnImageIsBitmap(arc->tile)) { /* Fill tiled */
+ /* TODO No support yet */
+ }
+ else { /* Fill stippled */
+ if (Tk_PostscriptColor(wi->interp, wi->ps_info,
+ ZnGetGradientColor(arc->fill_color, 0.0, NULL)) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ Tcl_AppendResult(wi->interp, "clip ", NULL);
+ if (Tk_PostscriptStipple(wi->interp, wi->win, wi->ps_info,
+ ZnImagePixmap(arc->tile, wi->win)) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ }
+ }
+ else { /* Fill solid */
+ if (Tk_PostscriptColor(wi->interp, wi->ps_info,
+ ZnGetGradientColor(arc->fill_color, 0.0, NULL)) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ Tcl_AppendResult(wi->interp, "fill\n", NULL);
+ }
+ if (arc->line_width) {
+ Tcl_AppendResult(wi->interp, "grestore\n", NULL);
+ }
+ }
+
+ /*
+ * Then emit code code to stroke the outline.
+ */
+ if (arc->line_width) {
+ Tcl_AppendResult(wi->interp, "0 setlinejoin 2 setlinecap\n", NULL);
+ if (ZnPostscriptOutline(wi->interp, wi->ps_info, wi->win,
+ arc->line_width, arc->line_style,
+ arc->line_color, arc->line_pattern) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ }
+
+ return TCL_OK;
}
diff --git a/generic/Curve.c b/generic/Curve.c
index 7054e81..c73d467 100644
--- a/generic/Curve.c
+++ b/generic/Curve.c
@@ -1578,10 +1578,101 @@ Pick(ZnItem item,
*
**********************************************************************************
*/
-static void
-PostScript(ZnItem item,
- ZnBool prepass)
+static int
+PostScript(ZnItem item,
+ ZnBool prepass,
+ ZnBBox *area)
{
+ ZnWInfo *wi = item->wi;
+ CurveItem cv = (CurveItem) item;
+ char path[500];
+ ZnContour *contours;
+ ZnPoint *points;
+ int num_contours, num_points;
+ int i, j;
+
+ num_contours = cv->outlines.num_contours;
+ contours = cv->outlines.contours;
+
+ /*
+ * Put all contours in an array on the stack
+ */
+ if (ISSET(cv->flags, FILLED_BIT) || cv->line_width) {
+ Tcl_AppendResult(wi->interp, "newpath ", NULL);
+ for (i = 0; i < num_contours; i++, contours++) {
+ num_points = contours->num_points;
+ points = contours->points;
+ sprintf(path, "%.15g %.15g moveto\n", points[0].x, points[0].y);
+ Tcl_AppendResult(wi->interp, path, NULL);
+ for (j = 1; j < num_points; j++) {
+ sprintf(path, "%.15g %.15g lineto ", points[j].x, points[j].y);
+ Tcl_AppendResult(wi->interp, path, NULL);
+ if (((j+1) % 5) == 0) {
+ Tcl_AppendResult(wi->interp, "\n", NULL);
+ }
+ }
+ }
+ }
+
+ /*
+ * Emit code to draw the filled area.
+ */
+ if (ISSET(cv->flags, FILLED_BIT)) {
+ if (cv->line_width) {
+ Tcl_AppendResult(wi->interp, "gsave\n", NULL);
+ }
+ if (!ZnGradientFlat(cv->fill_color)) {
+ if (ZnPostscriptGradient(wi->interp, wi->ps_info, cv->fill_color,
+ cv->grad_geo, NULL) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ }
+ else if (cv->tile != ZnUnspecifiedImage) {
+ if (!ZnImageIsBitmap(cv->tile)) { /* Fill tiled */
+ /* TODO No support yet */
+ }
+ else { /* Fill stippled */
+ if (Tk_PostscriptColor(wi->interp, wi->ps_info,
+ ZnGetGradientColor(cv->fill_color, 0.0, NULL)) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ Tcl_AppendResult(wi->interp, "clip ", NULL);
+ if (Tk_PostscriptStipple(wi->interp, wi->win, wi->ps_info,
+ ZnImagePixmap(cv->tile, wi->win)) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ }
+ }
+ else { /* Fill solid */
+ if (Tk_PostscriptColor(wi->interp, wi->ps_info,
+ ZnGetGradientColor(cv->fill_color, 0.0, NULL)) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ Tcl_AppendResult(wi->interp, "fill\n", NULL);
+ }
+ if (cv->line_width) {
+ Tcl_AppendResult(wi->interp, "grestore\n", NULL);
+ }
+ }
+
+ /*
+ * Then emit code code to stroke the outline.
+ */
+ if (cv->line_width) {
+ if (cv->relief != ZN_RELIEF_FLAT) {
+ /* TODO No support yet */
+ }
+ else {
+ Tcl_AppendResult(wi->interp, "0 setlinejoin 2 setlinecap\n", NULL);
+ if (ZnPostscriptOutline(wi->interp, wi->ps_info, wi->win,
+ cv->line_width, cv->line_style,
+ cv->line_color, cv->line_pattern) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ }
+ }
+
+ return TCL_OK;
}
diff --git a/generic/Field.c b/generic/Field.c
index ace5407..9f36e88 100644
--- a/generic/Field.c
+++ b/generic/Field.c
@@ -2132,14 +2132,246 @@ RenderField(ZnWInfo *wi,
}
#endif
+#ifdef GL
static void
RenderFields(ZnFieldSet field_set)
{
-#ifdef GL
/* glDisable(GL_LINE_SMOOTH);*/
FieldsEngine(field_set, RenderField);
/* glEnable(GL_LINE_SMOOTH);*/
+}
+#else
+static void
+RenderFields(ZnFieldSet field_set)
+{
+}
#endif
+
+
+/*
+ **********************************************************************************
+ *
+ * PostScriptFields --
+ *
+ **********************************************************************************
+ */
+static int
+PsField(ZnWInfo *wi,
+ ZnBool prepass,
+ Field fptr,
+ ZnBBox *bbox,
+ ZnBBox *pm_bbox,
+ ZnPoint *text_pos,
+ ZnBBox *text_bbox)
+{
+ int j;
+ char path[250];
+
+ /*
+ * Must set the clip rect for the whole field, not only for stipple fill.
+ */
+ if (ISSET(fptr->flags, FILLED_BIT)) {
+ if (fptr->tile != ZnUnspecifiedImage) {
+ if (!ZnImageIsBitmap(fptr->tile)) { /* Fill tiled */
+ /* TODO No support yet */
+ }
+ else { /* Fill stippled */
+ Tcl_AppendResult(wi->interp, "gsave\n", NULL);
+ if (Tk_PostscriptColor(wi->interp, wi->ps_info,
+ ZnGetGradientColor(fptr->fill_color, 0.0, NULL)) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ if (Tk_PostscriptStipple(wi->interp, wi->win, wi->ps_info,
+ ZnImagePixmap(fptr->tile, wi->win)) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ Tcl_AppendResult(wi->interp, "grestore\n", NULL);
+ }
+ }
+ else { /* Fill solid */
+ if (Tk_PostscriptColor(wi->interp, wi->ps_info,
+ ZnGetGradientColor(fptr->fill_color, 0.0, NULL)) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ Tcl_AppendResult(wi->interp, "fill\n", NULL);
+ }
+ }
+
+ /*
+ * Draw the image and the text, which is in back depends on
+ * the value of text_on_top.
+ */
+ for (j = 0; j < 2; j++) {
+ if ((j == 0 && ISSET(fptr->flags, TEXT_ON_TOP_BIT)) ||
+ (j == 1 && ISCLEAR(fptr->flags, TEXT_ON_TOP_BIT))) {
+ /*
+ * Draw the image.
+ */
+ if (fptr->image != ZnUnspecifiedImage) {
+ int w, h;
+
+ Tcl_AppendResult(wi->interp, "gsave\n", NULL);
+ sprintf(path, "%.15g %.15g translate 1 -1 scale\n",
+ pm_bbox->orig.x, pm_bbox->corner.y);
+ Tcl_AppendResult(wi->interp, path, NULL);
+ w = ZnNearestInt(pm_bbox->corner.x - pm_bbox->orig.x);
+ h = ZnNearestInt(pm_bbox->corner.y - pm_bbox->orig.y);
+ if (Tk_PostscriptImage(ZnImageTkImage(fptr->image), wi->interp, wi->win,
+ wi->ps_info, 0, 0, w, h, prepass) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ Tcl_AppendResult(wi->interp, "grestore\n", NULL);
+ }
+ }
+ else if (fptr->text) {
+ Tcl_AppendResult(wi->interp, "gsave\n", NULL);
+ if (Tk_PostscriptFont(wi->interp, wi->ps_info, fptr->font) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ if (Tk_PostscriptColor(wi->interp, wi->ps_info,
+ ZnGetGradientColor(fptr->color, 0.0, NULL)) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ /*
+ * TODO pourquoi la text_bbox ne donne pas un texte centré verticalement ?
+ * Apparement la fonte PostScript n'est pas centrée comme la fonte X.
+ * Il faut donc opérer le calcul dans le code PostScript de DrawText.
+ */
+ sprintf(path, "%.15g %.15g translate 1 -1 scale 0 0 [\n",
+ text_bbox->orig.x, text_bbox->orig.y);
+ Tcl_AppendResult(wi->interp, path, NULL);
+ /*
+ * strlen should do the work of counting _bytes_ in the utf8 string.
+ */
+ ZnPostscriptString(wi->interp, fptr->text, strlen(fptr->text));
+ Tcl_AppendResult(wi->interp, "] 0 0.0 0.0 0.0 false DrawText\n", NULL);
+ Tcl_AppendResult(wi->interp, "grestore\n", NULL);
+ }
+ }
+
+ /*
+ * Draw the border relief.
+ */
+ if ((fptr->relief != ZN_RELIEF_FLAT) && (fptr->relief_thickness > 1)) {
+ }
+
+ /*
+ * Draw the border line.
+ */
+ if (fptr->border_edges != ZN_NO_BORDER) {
+ if (Tk_PostscriptColor(wi->interp, wi->ps_info,
+ ZnGetGradientColor(fptr->border_color, 0.0, NULL)) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ Tcl_AppendResult(wi->interp, "1 setlinewidth 0 setlinejoin 2 setlinecap\n", NULL);
+ if (fptr->border_edges & ZN_LEFT_BORDER) {
+ sprintf(path, "%.15g %.15g moveto %.15g %.15g lineto stroke\n",
+ bbox->orig.x, bbox->orig.y, bbox->orig.x, bbox->corner.y);
+ Tcl_AppendResult(wi->interp, path, NULL);
+ }
+ if (fptr->border_edges & ZN_RIGHT_BORDER) {
+ sprintf(path, "%.15g %.15g moveto %.15g %.15g lineto stroke\n",
+ bbox->corner.x, bbox->orig.y, bbox->corner.x, bbox->corner.y);
+ Tcl_AppendResult(wi->interp, path, NULL);
+ }
+ if (fptr->border_edges & ZN_TOP_BORDER) {
+ sprintf(path, "%.15g %.15g moveto %.15g %.15g lineto stroke\n",
+ bbox->orig.x, bbox->orig.y, bbox->corner.x, bbox->orig.y);
+ Tcl_AppendResult(wi->interp, path, NULL);
+ }
+ if (fptr->border_edges & ZN_BOTTOM_BORDER) {
+ sprintf(path, "%.15g %.15g moveto %.15g %.15g lineto stroke\n",
+ bbox->orig.x, bbox->corner.y, bbox->corner.x, bbox->corner.y);
+ Tcl_AppendResult(wi->interp, path, NULL);
+ }
+ if (fptr->border_edges & ZN_OBLIQUE) {
+ sprintf(path, "%.15g %.15g moveto %.15g %.15g lineto stroke\n",
+ bbox->orig.x, bbox->orig.y, bbox->corner.x, bbox->corner.y);
+ Tcl_AppendResult(wi->interp, path, NULL);
+ }
+ if (fptr->border_edges & ZN_COUNTER_OBLIQUE) {
+ sprintf(path, "%.15g %.15g moveto %.15g %.15g lineto stroke\n",
+ bbox->corner.x, bbox->orig.y, bbox->orig.x, bbox->corner.y);
+ Tcl_AppendResult(wi->interp, path, NULL);
+ }
+ }
+
+ return TCL_OK;
+}
+
+static int
+PostScriptFields(ZnFieldSet field_set,
+ ZnBool prepass,
+ ZnBBox *area)
+{
+ ZnWInfo *wi = field_set->item->wi;
+ ZnBBox lclip_bbox, fclip_bbox;
+ ZnBBox bbox, text_bbox, pm_bbox;
+ ZnPoint text_pos;
+ int i, num_fields;
+ ZnDim lwidth, lheight;
+ Field fptr;
+ char path[250];
+
+ if (!field_set->num_fields) {
+ return TCL_OK;
+ }
+
+
+ if (field_set->label_format && ZnLFNumFields(field_set->label_format)) {
+ /*
+ * Fields are drawn with respect to a point already converted
+ * to device space, so we need to reinstate the initial transform.
+ */
+ Tcl_AppendResult(wi->interp, "/InitialTransform load setmatrix\n", NULL);
+
+ lclip_bbox.orig.x = ZnNearestInt(field_set->label_pos.x);
+ lclip_bbox.orig.y = ZnNearestInt(field_set->label_pos.y);
+ GetLabelBBox(field_set, &lwidth, &lheight);
+ lclip_bbox.corner.x = lclip_bbox.orig.x + lwidth;
+ lclip_bbox.corner.y = lclip_bbox.orig.y + lheight;
+
+ num_fields = ZnLFNumFields(field_set->label_format);
+ for (i = 0; i < num_fields; i++) {
+ fptr = &field_set->fields[i];
+
+ if (ISCLEAR(fptr->flags, FIELD_VISIBLE_BIT)) {
+ continue;
+ }
+
+ GetFieldBBox(field_set, i, &bbox);
+ ZnIntersectBBox(&lclip_bbox, &bbox, &fclip_bbox);
+ if (ZnIsEmptyBBox(&fclip_bbox)) {
+ /* The field is outside the label bbox */
+ continue;
+ }
+
+ /*
+ * Setup a clip area around the field
+ */
+ Tcl_AppendResult(wi->interp, "gsave\n", NULL);
+ sprintf(path, "%.15g %.15g moveto %.15g %.15g lineto %.15g %.15g lineto %.15g %.15g",
+ fclip_bbox.orig.x, fclip_bbox.orig.y, fclip_bbox.corner.x+1, fclip_bbox.orig.y,
+ fclip_bbox.corner.x+1, fclip_bbox.corner.y+1, fclip_bbox.orig.x,
+ fclip_bbox.corner.y+1);
+ Tcl_AppendResult(wi->interp, path, " lineto closepath clip\n", NULL);
+
+ if (fptr->text) {
+ ComputeFieldTextLocation(fptr, &bbox, &text_pos, &text_bbox);
+ }
+ if (fptr->image != ZnUnspecifiedImage) {
+ ComputeFieldImageLocation(fptr, &bbox, &pm_bbox);
+ }
+
+ if (PsField(wi, prepass, fptr, &bbox, &pm_bbox, &text_pos, &text_bbox) != TCL_OK) {
+ return TCL_ERROR;
+ }
+
+ Tcl_AppendResult(wi->interp, "grestore\n", NULL);
+ }
+ }
+
+ return TCL_OK;
}
@@ -2325,6 +2557,7 @@ struct _ZnFIELD ZnFIELD = {
QueryField,
DrawFields,
RenderFields,
+ PostScriptFields,
FieldsToArea,
IsFieldSensitive,
FieldsPick,
diff --git a/generic/Field.h b/generic/Field.h
index 88cb224..ad13663 100644
--- a/generic/Field.h
+++ b/generic/Field.h
@@ -60,6 +60,7 @@ extern struct _ZnFIELD {
int (*QueryField)(ZnFieldSet fs, int field, int argc, Tcl_Obj *CONST argv[]);
void (*DrawFields)(ZnFieldSet fs);
void (*RenderFields)(ZnFieldSet fs);
+ int (*PostScriptFields)(ZnFieldSet fs, ZnBool prepass, ZnBBox *area);
int (*FieldsToArea)(ZnFieldSet fs, ZnBBox *area);
ZnBool (*IsFieldSensitive)(ZnFieldSet fs, int part);
double (*FieldsPick)(ZnFieldSet fs, ZnPoint *p, int *part);
diff --git a/generic/Group.c b/generic/Group.c
index d569182..1f6a183 100644
--- a/generic/Group.c
+++ b/generic/Group.c
@@ -1355,10 +1355,70 @@ Coords(ZnItem item,
*
**********************************************************************************
*/
-static void
-PostScript(ZnItem item,
- ZnBool prepass)
+static int
+PostScript(ZnItem item,
+ ZnBool prepass,
+ ZnBBox *area)
{
+ GroupItem group = (GroupItem) item;
+ ZnWInfo *wi = item->wi;
+ ZnItem current_item;
+ ZnBBox bbox;
+ int result = TCL_OK;
+ char msg[500];
+
+ PushTransform(item);
+ PushClip(group, True);
+
+ for (current_item = group->tail; current_item != ZN_NO_ITEM;
+ current_item = current_item->previous) {
+ if (ISCLEAR(current_item->flags, ZN_VISIBLE_BIT)) {
+ continue;
+ }
+ //printf("area %g %g %g %g\n", area->orig.x, area->orig.y,
+ // area->corner.x, area->corner.y);
+ ZnIntersectBBox(area, &current_item->item_bounding_box, &bbox);
+ if (ZnIsEmptyBBox(&bbox)) {
+ continue;
+ }
+ if (current_item->class->PostScript == NULL) {
+ continue;
+ }
+
+ if (current_item->class != ZnGroup) {
+ PushTransform(current_item);
+ if (!prepass) {
+ Tcl_AppendResult(wi->interp, "gsave\n", NULL);
+ }
+ ZnPostscriptTrace(current_item, 1);
+ }
+ result = current_item->class->PostScript(current_item, prepass, area);
+ if (current_item->class != ZnGroup) {
+ ZnPostscriptTrace(current_item, 0);
+ if (!prepass && (result == TCL_OK)) {
+ Tcl_AppendResult(wi->interp, "grestore\n", NULL);
+ }
+ PopTransform(current_item);
+ }
+ if (result == TCL_ERROR) {
+ if (!prepass) {
+ /*
+ * Add some trace to ease the error lookup.
+ */
+ sprintf(msg, "\n (generating Postscript for item %d)", current_item->id);
+ Tcl_AddErrorInfo(wi->interp, msg);
+ break;
+ }
+ }
+ }
+
+ PopClip(group, True);
+ PopTransform(item);
+
+ if (!prepass && (result == TCL_OK)) {
+ ZnFlushPsChan(wi->interp, wi->ps_info);
+ }
+ return result;
}
diff --git a/generic/Icon.c b/generic/Icon.c
index 38c4ac9..5b9eae8 100644
--- a/generic/Icon.c
+++ b/generic/Icon.c
@@ -228,6 +228,57 @@ Query(ZnItem item,
/*
+ * Compute the transformation to be used and the origin
+ * of the icon (upper left point in item coordinates).
+ */
+static ZnTransfo *
+ComputeTransfoAndOrigin(ZnItem item,
+ ZnPoint *origin)
+{
+ IconItem icon = (IconItem) item;
+ int w, h;
+ ZnTransfo *t;
+
+ ZnSizeOfImage(icon->image, &w, &h);
+
+ /*
+ * 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,
+ icon->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) w, (ZnReal) h, icon->anchor, origin);
+ //origin->x = ZnNearestInt(origin->x);
+ //origin->y = ZnNearestInt(origin->y);
+
+ return t;
+}
+
+/*
**********************************************************************************
*
* ComputeCoordinates --
@@ -238,10 +289,11 @@ static void
ComputeCoordinates(ZnItem item,
ZnBool force)
{
- ZnWInfo *wi = item->wi;
- IconItem icon = (IconItem) item;
- int width, height, i;
- ZnPoint pos, quad[4];
+ //ZnWInfo *wi = item->wi;
+ IconItem icon = (IconItem) item;
+ int width, height, i;
+ ZnPoint quad[4];
+ ZnTransfo *t;
ZnResetBBox(&item->item_bounding_box);
@@ -252,34 +304,16 @@ ComputeCoordinates(ZnItem item,
return;
}
- if (icon->image != ZnUnspecifiedImage) {
- ZnSizeOfImage(icon->image, &width, &height);
- }
-
+ ZnSizeOfImage(icon->image, &width, &height);
+ t = ComputeTransfoAndOrigin(item, quad);
- /*
- * The connected item support anchors, this is checked by
- * configure.
- */
- if (item->connected_item != ZN_NO_ITEM) {
- ZnTransfo t;
-
- item->connected_item->class->GetAnchor(item->connected_item,
- icon->connection_anchor, quad);
- ZnTransfoInvert(wi->current_transfo, &t);
- ZnTransformPoint(&t, quad, &pos);
- }
- else {
- pos.x = pos.y = 0;
- }
- ZnAnchor2Origin(&pos, (ZnReal) width, (ZnReal) height, icon->anchor, quad);
quad[1].x = quad[0].x;
quad[1].y = quad[0].y + height;
quad[2].x = quad[0].x + width;
quad[2].y = quad[1].y;
quad[3].x = quad[2].x;
quad[3].y = quad[0].y;
- ZnTransformPoints(wi->current_transfo, quad, icon->dev, 4);
+ ZnTransformPoints(t, quad, icon->dev, 4);
for (i = 0; i < 4; i++) {
icon->dev[i].x = ZnNearestInt(icon->dev[i].x);
@@ -726,10 +760,49 @@ Pick(ZnItem item,
*
**********************************************************************************
*/
-static void
-PostScript(ZnItem item,
- ZnBool prepass)
+static int
+PostScript(ZnItem item,
+ ZnBool prepass,
+ ZnBBox *area)
{
+ ZnWInfo *wi = item->wi;
+ IconItem icon = (IconItem) item;
+ int w, h, result;
+ ZnPoint origin;
+ char path[500];
+
+ if (prepass || (icon->image == ZnUnspecifiedImage)) {
+ return TCL_OK;
+ }
+
+ ZnSizeOfImage(icon->image, &w, &h);
+
+ ComputeTransfoAndOrigin(item, &origin);
+
+ sprintf(path, "/InitialTransform load setmatrix\n"
+ "[%.15g %.15g %.15g %.15g %.15g %.15g] concat\n"
+ "1 -1 scale\n"
+ "%.15g %.15g translate\n",
+ wi->current_transfo->_[0][0], wi->current_transfo->_[0][1],
+ wi->current_transfo->_[1][0], wi->current_transfo->_[1][1],
+ wi->current_transfo->_[2][0], wi->current_transfo->_[2][1],
+ origin.x, origin.y - h);
+ Tcl_AppendResult(wi->interp, path, NULL);
+
+ if (ZnImageIsBitmap(icon->image)) {
+ if (Tk_PostscriptColor(wi->interp, wi->ps_info,
+ ZnGetGradientColor(icon->color, 0.0, NULL)) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ result = ZnPostscriptBitmap(wi->interp, wi->win, wi->ps_info,
+ icon->image, 0, 0, w, h);
+ }
+ else {
+ result = Tk_PostscriptImage(ZnImageTkImage(icon->image), wi->interp, wi->win,
+ wi->ps_info, 0, 0, w, h, prepass);
+ }
+
+ return result;
}
diff --git a/generic/Image.c b/generic/Image.c
index 10a507e..d6636e9 100644
--- a/generic/Image.c
+++ b/generic/Image.c
@@ -765,6 +765,18 @@ ZnImageRegion(ZnImage image)
}
+Tk_Image
+ZnImageTkImage(ZnImage image)
+{
+ return ((Image) image)->bits->tkimage;
+}
+
+Tk_PhotoHandle
+ZnImageTkPhoto(ZnImage image)
+{
+ return ((Image) image)->bits->tkphoto;
+}
+
/*
**********************************************************************************
*
diff --git a/generic/Image.h b/generic/Image.h
index 6e72907..426c0df 100644
--- a/generic/Image.h
+++ b/generic/Image.h
@@ -29,28 +29,21 @@ typedef void *ZnImage;
#define ZnGetBitmapPixel(bits, stride, x, y)\
(((bits)[(y)*(stride)+((x)>>3)]<<((x)&7))&0x80)
-ZnImage
-ZnGetImage(struct _ZnWInfo *wi, Tk_Uid image_name,
- void (*inv_proc)(void *cd), void *cd);
-ZnImage
-ZnGetImageByValue(ZnImage image, void (*inv_proc)(void *cd), void *cd);
-void
-ZnFreeImage(ZnImage image, void (*inv_proc)(void *cd), void *cd);
-char *
-ZnNameOfImage(ZnImage image);
-void
-ZnSizeOfImage(ZnImage image, int *width, int *height);
-Pixmap
-ZnImagePixmap(ZnImage image, Tk_Window win);
-ZnBool
-ZnImageIsBitmap(ZnImage image);
-TkRegion
-ZnImageRegion(ZnImage image);
+ZnImage ZnGetImage(struct _ZnWInfo *wi, Tk_Uid image_name,
+ void (*inv_proc)(void *cd), void *cd);
+ZnImage ZnGetImageByValue(ZnImage image, void (*inv_proc)(void *cd), void *cd);
+void ZnFreeImage(ZnImage image, void (*inv_proc)(void *cd), void *cd);
+char * ZnNameOfImage(ZnImage image);
+void ZnSizeOfImage(ZnImage image, int *width, int *height);
+Pixmap ZnImagePixmap(ZnImage image, Tk_Window win);
+ZnBool ZnImageIsBitmap(ZnImage image);
+TkRegion ZnImageRegion(ZnImage image);
+Tk_Image ZnImageTkImage(ZnImage image);
+Tk_PhotoHandle ZnImageTkPhoto(ZnImage image);
ZnBool
ZnPointInImage(ZnImage image, int x, int y);
#ifdef GL
-GLuint
-ZnImageTex(ZnImage image, ZnReal *t, ZnReal *s);
+GLuint ZnImageTex(ZnImage image, ZnReal *t, ZnReal *s);
typedef struct _ZnTexGlyphVertexInfo {
GLfloat t0x;
diff --git a/generic/Item.h b/generic/Item.h
index 83f95e9..3871bf8 100644
--- a/generic/Item.h
+++ b/generic/Item.h
@@ -241,7 +241,7 @@ typedef int (*ZnItemIndexMethod)(ZnItem item, int field, Tcl_Obj *index_spec,
typedef int (*ZnItemPartMethod)(ZnItem item, Tcl_Obj **part_spec, int *part);
typedef int (*ZnItemSelectionMethod)(ZnItem item, int field, int offset,
char *chars, int max_chars);
-typedef void (*ZnItemPostScriptMethod)(ZnItem item, ZnBool prepass);
+typedef int (*ZnItemPostScriptMethod)(ZnItem item, ZnBool prepass, ZnBBox *area);
typedef void *ZnItemClassId;
diff --git a/generic/Map.c b/generic/Map.c
index c331c67..cba3d14 100644
--- a/generic/Map.c
+++ b/generic/Map.c
@@ -1557,10 +1557,12 @@ Pick(ZnItem item,
*
**********************************************************************************
*/
-static void
-PostScript(ZnItem item,
- ZnBool prepass)
+static int
+PostScript(ZnItem item,
+ ZnBool prepass,
+ ZnBBox *area)
{
+ return TCL_OK;
}
diff --git a/generic/PostScript.c b/generic/PostScript.c
index 56737e9..eeee5f0 100644
--- a/generic/PostScript.c
+++ b/generic/PostScript.c
@@ -30,8 +30,6 @@
**********************************************************************************
*/
-#if 0
-
#ifndef _WIN32
#include <unistd.h>
#include <pwd.h>
@@ -39,7 +37,9 @@
#include <stdio.h>
#include <sys/types.h>
#include <time.h>
+#include <string.h>
+#include "Types.h"
#include "Item.h"
#include "Group.h"
#include "PostScript.h"
@@ -59,152 +59,140 @@ static const char rcsid[] = "$Id$";
static const char compile_id[]="$Compile: " __FILE__ " " __DATE__ " " __TIME__ " $";
-#define PROLOG_VERSION 1.0
-#define PROLOG_REVISION 0
-
-static char ps_prolog[] = "";
-
-
-typedef struct _ZnPostScriptInfo {
- ZnBBox area; /* Area to print, in device coordinates. */
- ZnReal page_x; /* PostScript coordinates of anchor on page */
- ZnReal page_y;
- ZnReal page_width; /* Printed width and height of output area. */
- ZnReal page_height;
- Tk_Anchor page_anchor; /* Area anchor on Postscript page. */
- ZnBool landscape; /* True means output is rotated ccw by 90 degrees
- * (landscape mode). */
- char *font_var; /* If non-NULL, gives name of global variable
- * containing font mapping information. Malloc'ed. */
- char *color_var; /* If non-NULL, give name of global variable
- * containing color mapping information. Malloc'ed. */
- int colormode; /* Tell how color show be handled: 0 for mono,
- * 1 for gray, 2 for color. */
- char *filename; /* Name of file in which to write PostScript; NULL
- * means return Postscript info as result. Malloc'ed. */
- char *channel_name; /* If -channel is specified, the name of the channel
- * to use. Malloc'ed */
- Tcl_Channel chan; /* Open channel corresponding to fileName. */
- Tcl_HashTable font_table; /* Hash table containing names of all font families
- * used in output. The table values are not used. */
- ZnBool prepass; /* True means that we're currently in
- * the pre-pass that collects font information,
- * so the PostScript generated isn't relevant. */
- ZnBool prolog; /* True means output should contain the file
- * prolog.ps in the header. */
-} ZnPostScriptInfo;
-
-
-static int ZnPsDimParse _ANSI_ARGS_((ClientData client_data, Tcl_Interp *interp,
- Tk_Window tkwin, Tcl_Obj *ovalue,
- char *widget_rec, int offset));
-static Tcl_Obj *ZnPsDimPrint _ANSI_ARGS_((ClientData client_data, Tk_Window tkwin,
- char *widget_rec, int offset,
- Tcl_FreeProc **free_proc));
-static int ZnPsColorModeParse _ANSI_ARGS_((ClientData client_data, Tcl_Interp *interp,
- Tk_Window tkwin, Tcl_Obj *ovalue,
- char *widget_rec, int offset));
-static Tcl_Obj *ZnPsColorModePrint _ANSI_ARGS_((ClientData client_data, Tk_Window tkwin,
- char *widget_rec, int offset,
- Tcl_FreeProc **free_proc));
-static int ZnBBoxParse _ANSI_ARGS_((ClientData client_data, Tcl_Interp *interp,
- Tk_Window tkwin, Tcl_Obj *ovalue,
- char *widget_rec, int offset));
-static Tcl_Obj *ZnBBoxPrint _ANSI_ARGS_((ClientData client_data, Tk_Window tkwin,
- char *widget_rec, int offset,
- Tcl_FreeProc **free_proc));
-
-static Tk_CustomOption psDimOption = {
- (Tk_OptionParseProc *) ZnPsDimParse,
- (Tk_OptionPrintProc *) ZnPsDimPrint,
- NULL
-};
-
-static Tk_CustomOption psColorModeOption = {
- (Tk_OptionParseProc *) ZnPsColorModeParse,
- (Tk_OptionPrintProc *) ZnPsColorModePrint,
- NULL
-};
-
-static Tk_CustomOption bboxOption = {
- (Tk_OptionParseProc *) ZnBBoxParse,
- (Tk_OptionPrintProc *) ZnBBoxPrint,
- NULL
-};
+/*
+ * One of the following structures is created to keep track of Postscript
+ * output being generated. It consists mostly of information provided on
+ * the widget command line.
+ * WATCH! This structure must be kept in sync with the structure in
+ * tkCanvPs.c, we share most of the code for emitting postscript and
+ * this rely on sharing the structure.
+ */
+typedef struct TkPostscriptInfo {
+ int x, y, width, height; /* Area to print, in canvas pixel
+ * coordinates. */
+ int x2, y2; /* x+width and y+height. */
+ char *pageXString; /* String value of "-pagex" option or NULL. */
+ char *pageYString; /* String value of "-pagey" option or NULL. */
+ double pageX, pageY; /* Postscript coordinates (in points)
+ * corresponding to pageXString and
+ * pageYString. Don't forget that y-values
+ * grow upwards for Postscript! */
+ char *pageWidthString; /* Printed width of output. */
+ char *pageHeightString; /* Printed height of output. */
+ double scale; /* Scale factor for conversion: each pixel
+ * maps into this many points. */
+ Tk_Anchor pageAnchor; /* How to anchor bbox on Postscript page. */
+ int rotate; /* Non-zero means output should be rotated
+ * on page (landscape mode). */
+ char *fontVar; /* If non-NULL, gives name of global variable
+ * containing font mapping information.
+ * Malloc'ed. */
+ char *colorVar; /* If non-NULL, give name of global variable
+ * containing color mapping information.
+ * Malloc'ed. */
+ char *colorMode; /* Mode for handling colors: "monochrome",
+ * "gray", or "color". Malloc'ed. */
+ int colorLevel; /* Numeric value corresponding to colorMode:
+ * 0 for mono, 1 for gray, 2 for color. */
+ char *fileName; /* Name of file in which to write Postscript;
+ * NULL means return Postscript info as
+ * result. Malloc'ed. */
+ char *channelName; /* If -channel is specified, the name of
+ * the channel to use. */
+ Tcl_Channel chan; /* Open channel corresponding to fileName. */
+ Tcl_HashTable fontTable; /* Hash table containing names of all font
+ * families used in output. The hash table
+ * values are not used. */
+ int prepass; /* Non-zero means that we're currently in
+ * the pre-pass that collects font information,
+ * so the Postscript generated isn't
+ * relevant. */
+ int prolog; /* Non-zero means output should contain
+ * the file prolog.ps in the header. */
+ /*
+ * Below are extensions for Tkzinc.
+ */
+ ZnBBox bbox;
+} TkPostscriptInfo;
/*
- * Information used for argv parsing.
+ * The table below provides a template that's used to process arguments
+ * to the "postscript" command and fill in TkPostscriptInfo structures.
*/
static Tk_ConfigSpec config_specs[] = {
- {TK_CONFIG_CUSTOM, "-area", (char *) NULL, (char *) NULL,
- "", Tk_Offset(ZnPostScriptInfo, area), 0, &bboxOption},
- {TK_CONFIG_STRING, "-colormap", (char *) NULL, (char *) NULL,
- "", Tk_Offset(ZnPostScriptInfo, color_var), 0, NULL},
- {TK_CONFIG_CUSTOM, "-colormode", (char *) NULL, (char *) NULL,
- "", Tk_Offset(ZnPostScriptInfo, colormode), 0, &psColorModeOption},
- {TK_CONFIG_STRING, "-file", (char *) NULL, (char *) NULL,
- "", Tk_Offset(ZnPostScriptInfo, filename), 0, NULL},
- {TK_CONFIG_STRING, "-channel", (char *) NULL, (char *) NULL,
- "", Tk_Offset(ZnPostScriptInfo, channel_name), 0, NULL},
- {TK_CONFIG_STRING, "-fontmap", (char *) NULL, (char *) NULL,
- "", Tk_Offset(ZnPostScriptInfo, font_var), 0, NULL},
- {TK_CONFIG_BOOLEAN, "-landscape", (char *) NULL, (char *) NULL,
- "", Tk_Offset(ZnPostScriptInfo, landscape), 0, NULL},
- {TK_CONFIG_ANCHOR, "-pageanchor", (char *) NULL, (char *) NULL,
- "", Tk_Offset(ZnPostScriptInfo, page_anchor), 0, NULL},
- {TK_CONFIG_CUSTOM, "-pageheight", (char *) NULL, (char *) NULL,
- "", Tk_Offset(ZnPostScriptInfo, page_height), 0, &psDimOption},
- {TK_CONFIG_CUSTOM, "-pagewidth", (char *) NULL, (char *) NULL,
- "", Tk_Offset(ZnPostScriptInfo, page_width), 0, &psDimOption},
- {TK_CONFIG_CUSTOM, "-pagex", (char *) NULL, (char *) NULL,
- "", Tk_Offset(ZnPostScriptInfo, page_x), 0, &psDimOption},
- {TK_CONFIG_CUSTOM, "-pagey", (char *) NULL, (char *) NULL,
- "", Tk_Offset(ZnPostScriptInfo, page_y), 0, &psDimOption},
- {TK_CONFIG_BOOLEAN, "-prolog", (char *) NULL, (char *) NULL,
- "", Tk_Offset(ZnPostScriptInfo, prolog), 0, NULL},
- {TK_CONFIG_END, (char *) NULL, (char *) NULL, (char *) NULL,
- (char *) NULL, 0, 0, NULL}
+ {TK_CONFIG_STRING, "-colormap", (char *) NULL, (char *) NULL,
+ "", Tk_Offset(TkPostscriptInfo, colorVar), 0, NULL},
+ {TK_CONFIG_STRING, "-colormode", (char *) NULL, (char *) NULL,
+ "", Tk_Offset(TkPostscriptInfo, colorMode), 0, NULL},
+ {TK_CONFIG_STRING, "-file", (char *) NULL, (char *) NULL,
+ "", Tk_Offset(TkPostscriptInfo, fileName), 0, NULL},
+ {TK_CONFIG_STRING, "-channel", (char *) NULL, (char *) NULL,
+ "", Tk_Offset(TkPostscriptInfo, channelName), 0, NULL},
+ {TK_CONFIG_STRING, "-fontmap", (char *) NULL, (char *) NULL,
+ "", Tk_Offset(TkPostscriptInfo, fontVar), 0, NULL},
+ {TK_CONFIG_PIXELS, "-height", (char *) NULL, (char *) NULL,
+ "", Tk_Offset(TkPostscriptInfo, height), 0, NULL},
+ {TK_CONFIG_ANCHOR, "-pageanchor", (char *) NULL, (char *) NULL,
+ "", Tk_Offset(TkPostscriptInfo, pageAnchor), 0, NULL},
+ {TK_CONFIG_STRING, "-pageheight", (char *) NULL, (char *) NULL,
+ "", Tk_Offset(TkPostscriptInfo, pageHeightString), 0, NULL},
+ {TK_CONFIG_STRING, "-pagewidth", (char *) NULL, (char *) NULL,
+ "", Tk_Offset(TkPostscriptInfo, pageWidthString), 0, NULL},
+ {TK_CONFIG_STRING, "-pagex", (char *) NULL, (char *) NULL,
+ "", Tk_Offset(TkPostscriptInfo, pageXString), 0, NULL},
+ {TK_CONFIG_STRING, "-pagey", (char *) NULL, (char *) NULL,
+ "", Tk_Offset(TkPostscriptInfo, pageYString), 0, NULL},
+ {TK_CONFIG_BOOLEAN, "-prolog", (char *) NULL, (char *) NULL,
+ "", Tk_Offset(TkPostscriptInfo, prolog), 0, NULL},
+ {TK_CONFIG_BOOLEAN, "-rotate", (char *) NULL, (char *) NULL,
+ "", Tk_Offset(TkPostscriptInfo, rotate), 0, NULL},
+ {TK_CONFIG_PIXELS, "-width", (char *) NULL, (char *) NULL,
+ "", Tk_Offset(TkPostscriptInfo, width), 0, NULL},
+ {TK_CONFIG_PIXELS, "-x", (char *) NULL, (char *) NULL,
+ "", Tk_Offset(TkPostscriptInfo, x), 0, NULL},
+ {TK_CONFIG_PIXELS, "-y", (char *) NULL, (char *) NULL,
+ "", Tk_Offset(TkPostscriptInfo, y), 0, NULL},
+ {TK_CONFIG_END, (char *) NULL, (char *) NULL, (char *) NULL,
+ (char *) NULL, 0, 0, NULL}
};
-
/*
- *----------------------------------------------------------------------
+ *--------------------------------------------------------------
+ *
+ * GetPostscriptPoints --
+ *
+ * Given a string, returns the number of Postscript points
+ * corresponding to that string.
*
- * ZnPsDimParse
- * ZnPsDimPrint --
- * Converter for the PostScript dimension options
- * (-pagex, -pagey, -pagewidth, -pageheight).
+ * Results:
+ * The return value is a standard Tcl return result. If
+ * TCL_OK is returned, then everything went well and the
+ * screen distance is stored at *doublePtr; otherwise
+ * TCL_ERROR is returned and an error message is left in
+ * the interp's result.
*
- *----------------------------------------------------------------------
+ * Side effects:
+ * None.
+ *
+ *--------------------------------------------------------------
*/
static int
-ZnPsDimParse(ClientData client_data,
- Tcl_Interp *interp,
- Tk_Window tkwin,
- Tcl_Obj *ovalue,
- char *widget_rec,
- int offset)
+GetPostscriptPoints(Tcl_Interp *interp,
+ char *string,
+ double *double_ptr)
{
- ZnReal *dim = (ZnReal *) (widget_rec + offset);
-#ifdef PTK
- char *value = Tcl_GetString(ovalue);
-#else
- char *value = (char *) ovalue;
-#endif
- char *end;
+ char *end;
double d;
- d = strtod(value, &end);
- if (end == value) {
- dim_error:
- Tcl_AppendResult(interp, "bad distance \"", value, "\"", NULL);
+ d = strtod(string, &end);
+ if (end == string) {
+ error:
+ Tcl_AppendResult(interp, "bad distance \"", string, "\"", (char *) NULL);
return TCL_ERROR;
}
-
while ((*end != '\0') && isspace(UCHAR(*end))) {
end++;
}
-
switch (*end) {
case 'c':
d *= 72.0/2.54;
@@ -224,413 +212,144 @@ ZnPsDimParse(ClientData client_data,
end++;
break;
default:
- goto dim_error;
+ goto error;
}
-
while ((*end != '\0') && isspace(UCHAR(*end))) {
end++;
}
if (*end != 0) {
- goto dim_error;
- }
- *dim = d;
-
- return TCL_OK;
-}
-
-static Tcl_Obj *
-ZnPsDimPrint(ClientData client_data,
- Tk_Window tkwin,
- char *widget_rec,
- int offset,
-#ifdef PTK
- Tcl_FreeProc **free_proc
-#else
- Tcl_FreeProc **free_proc
-#endif
-)
-{
- ZnReal *dim = (ZnReal *) (widget_rec + offset);
- Tcl_Obj *obj = Tcl_NewDoubleObj(*dim);
-#ifdef PTK
- return obj;
-#else
- {
- char *s1, *s2;
-
- *free_proc = TCL_DYNAMIC;
- s1 = Tcl_GetString(obj);
- s2 = ZnMalloc(strlen(s1) + 1);
- strcpy(s2, s1);
- Tcl_DecrRefCount(obj);
- return (Tcl_Obj *) s2;
- }
-#endif
-}
-
-/*
- *----------------------------------------------------------------------
- *
- * ZnPsColorModeParse
- * ZnPsColorModePrint --
- * Converter for the PostScript -colormode option.
- *
- *----------------------------------------------------------------------
- */
-static int
-ZnPsColorModeParse(ClientData client_data,
- Tcl_Interp *interp,
- Tk_Window tkwin,
- Tcl_Obj *ovalue,
- char *widget_rec,
- int offset)
-{
- int *mode = (int *) (widget_rec + offset);
-#ifdef PTK
- char *value = Tcl_GetString(ovalue);
-#else
- char *value = (char *) ovalue;
-#endif
- int result = TCL_OK;
-
- if (value != NULL) {
- if (strcmp(value, "monochrome") == 0) {
- *mode = 0;
- }
- else if (strcmp(value, "gray") == 0) {
- *mode = 1;
- }
- else if (strcmp(value, "color") == 0) {
- *mode = 2;
- }
- else {
- Tcl_AppendResult(interp, " incorrect PostScript color mode \"",
- value, "\" should be \"monochrome\", \"gray\"",
- " or \"color\"", NULL);
- result = TCL_ERROR;
- }
- }
-
- return result;
-}
-
-static Tcl_Obj *
-ZnPsColorModePrint(ClientData client_data,
- Tk_Window tkwin,
- char *widget_rec,
- int offset,
- Tcl_FreeProc **free_proc)
-{
- int *mode = (int *) (widget_rec + offset);
- char *s;
-
- switch (*mode) {
- case 0: s = "monochrome";
- break;
- case 1: s = "gray";
- break;
- case 2: s = "color";
- break;
- default: s = "PsColorModeInvalid";
- break;
- }
-#ifdef PTK
- return Tcl_NewStringObj(s, -1);
-#else
- return (Tcl_Obj *) s;
-#endif
-}
-
-/*
- *----------------------------------------------------------------------
- *
- * ZnBBoxParse
- * ZnBBoxPrint --
- * Converter for the -area option.
- *
- *----------------------------------------------------------------------
- */
-static int
-ZnBBoxParse(ClientData client_data,
- Tcl_Interp *interp,
- Tk_Window tkwin,
- Tcl_Obj *ovalue,
- char *widget_rec,
- int offset)
-{
- ZnBBox *bbox = (ZnBBox *) (widget_rec + offset);
- int i, result, num_elems;
- Tcl_Obj **elems;
- double d[4];
-
- result = Tcl_ListObjGetElements(interp, ovalue, &num_elems, &elems);
- if ((result == TCL_ERROR) ||
- (num_elems != 0) ||
- (num_elems != 4)) {
- bbox_error:
- Tcl_AppendResult(interp, " malformed area", NULL);
- return TCL_ERROR;
- }
-
- bbox->orig.x = bbox->orig.y = bbox->corner.x = bbox->corner.y = 0;
-
- if (num_elems != 0) {
- for (i = 0; i < 4; i++) {
- result = Tcl_GetDoubleFromObj(interp, elems[0], &d[0]);
- if (result == TCL_ERROR) {
- goto bbox_error;
- }
- }
- bbox->orig.x = d[0];
- bbox->orig.y = d[1];
- bbox->corner.x = d[2];
- bbox->corner.y = d[3];
+ goto error;
}
-
+ *double_ptr = d;
return TCL_OK;
}
-static Tcl_Obj *
-ZnBBoxPrint(ClientData client_data,
- Tk_Window tkwin,
- char *widget_rec,
- int offset,
-#ifdef PTK
- Tcl_FreeProc **free_proc
-#else
- Tcl_FreeProc **free_proc
-#endif
- )
-{
- ZnBBox *bbox = (ZnBBox *) (widget_rec + offset);
- Tcl_Obj *obj = NULL;
-
- obj = Tcl_NewListObj(0, NULL);
- Tcl_ListObjAppendElement(NULL, obj, Tcl_NewDoubleObj(bbox->orig.x));
- Tcl_ListObjAppendElement(NULL, obj, Tcl_NewDoubleObj(bbox->orig.y));
- Tcl_ListObjAppendElement(NULL, obj, Tcl_NewDoubleObj(bbox->corner.x));
- Tcl_ListObjAppendElement(NULL, obj, Tcl_NewDoubleObj(bbox->corner.y));
-
-#ifdef PTK
- return obj;
-#else
- {
- char *s1, *s2;
-
- s1 = Tcl_GetString(obj);
- s2 = ZnMalloc(strlen(s1) + 1);
- strcpy(s2, s1);
- Tcl_DecrRefCount(obj);
- *free_proc = TCL_DYNAMIC;
- return (Tcl_Obj *) s2;
- }
-#endif
-}
-
-
-#if 0
-/*
- **********************************************************************************
- *
- * EmitPostScript --
- *
- **********************************************************************************
- */
- /*
- * Emit Encapsulated PostScript Header.
- */
- fprintf(ps_info->file, "%%!PS-Adobe-3.0 EPSF-3.0\n");
- fprintf(ps_info->file, "%%%%Creator: Zn Widget\n");
- pwd_info = getpwuid(getuid());
- fprintf(ps_info->file, "%%%%For: %s\n", pwd_info ? pwd_info->pw_gecos : "Unknown");
- fprintf(ps_info->file, "%%%%Title: (%s)\n", ps_info->title);
- time(&now);
- fprintf(ps_info->file, "%%%%CreationDate: %s\n", ctime(&now));
- if (ps_info->landscape) {
- fprintf(ps_info->file, "%%%%BoundingBox: %d %d %d %d\n", 1, 1, 1, 1);
- }
- else {
- fprintf(ps_info->file, "%%%%BoundingBox: %d %d %d %d\n", 1, 1, 1, 1);
- }
- fprintf(ps_info->file, "%%%%Pages: 1\n");
- fprintf(ps_info->file, "%%%%DocumentData: Clean7Bit\n");
- fprintf(ps_info->file, "%%%%Orientation: %s\n",
- ps_info->landscape ? "Landscape" : "Portrait");
- fprintf(ps_info->file, "%%%%LanguageLevel: 1\n");
- fprintf(ps_info->file, "%%%%DocumentNeededResources: (atend)\n");
- fprintf(ps_info->file,
- "%%%%DocumentSuppliedResources: procset Zinc-Widget-Prolog %f %d\n",
- PROLOG_VERSION, PROLOG_REVISION);
- fprintf(ps_info->file, "%%%%EndComments\n\n\n");
-
- /*
- * Emit the prolog.
- */
- fprintf(ps_info->file, "%%%%BeginProlog\n");
- fprintf(ps_info->file, "%%%%BeginResource: procset Zinc-Widget-Prolog %f %d\n",
- PROLOG_VERSION, PROLOG_REVISION);
- fwrite(ps_prolog, 1, sizeof(ps_prolog), ps_info->file);
- fprintf(ps_info->file, "%%%%EndResource\n");
- fprintf(ps_info->file, "%%%%EndProlog\n");
-
- /*
- * Emit the document setup.
- */
- fprintf(ps_info->file, "%%%%BeginSetup\n");
- fprintf(ps_info->file, "%%%%EndSetup\n");
-
- /*
- * Emit the page setup.
- */
- fprintf(ps_info->file, "%%%%Page: 0 1\n");
- fprintf(ps_info->file, "%%%%BeginPageSetup\n");
- fprintf(ps_info->file, "%%%%EndPageSetup\n");
-
- /*
- * Iterate through all items emitting PostScript for each.
- */
-
- /*
- * Emit the page trailer.
- */
- fprintf(ps_info->file, "%%%%PageTrailer\n");
-
- /*
- * Emit the document trailer.
- */
- fprintf(ps_info->file, "%%%%Trailer\n");
- s = "%%DocumentNeededResources: font ";
- for (fs = (XFontStruct *) ZnListArray(ps_info->fonts),
- i = ZnListSize(ps_info->fonts); i > 0; i--, fs++) {
- fprintf(ps_info->file, "%s", s);
- s = "%%+ font";
- }
- fprintf(ps_info->file, "%%%%EOF\n");
-#endif
-
/*
*--------------------------------------------------------------
*
- * ZnPostScriptY --
- *
- * Given a y-coordinate in local coordinates, this procedure
- * returns a y-coordinate to use for PostScript output.
+ * ZnPostScriptCmd --
*
- *--------------------------------------------------------------
- */
-ZnReal
-ZnPostScriptY(ZnReal y,
- void *ps_info)
-{
- return ((ZnPostScriptInfo *) ps_info)->area.corner.y - y;
-}
-
-/*
- *----------------------------------------------------------------------------
+ * This procedure is invoked to process the "postscript" options
+ * of the widget command for zinc widgets. See the user
+ * documentation for details on what it does.
*
- * ZnPostScriptCmd --
+ * Results:
+ * A standard Tcl result.
*
- * This procedure process the "postscript" command for
- * zinc widgets.
+ * Side effects:
+ * See the user documentation.
*
- *----------------------------------------------------------------------------
+ *--------------------------------------------------------------
*/
int
-ZnPostScriptCmd(ZnWInfo *wi,
- int argc,
- Tcl_Obj *CONST args[])
+ZnPostScriptCmd(ZnWInfo *wi,
+ int argc,
+ Tcl_Obj *CONST argv[])
{
- ZnPostScriptInfo ps_info;
- void *old_info;
- int result;
- int delta_x = 0, delta_y = 0;
- ZnReal width, height;
- CONST char *p;
- Tcl_DString buffer;
+ TkPostscriptInfo ps_info;
+ Tk_PostscriptInfo old_info;
+ int result;
#define STRING_LENGTH 400
- char string[STRING_LENGTH+1];
- ZnBBox *area;
- time_t now;
- Tcl_HashSearch search;
- Tcl_HashEntry *entry;
-
- old_info = wi->ps_info;
- wi->ps_info = (void *) &ps_info;
-
+ char string[STRING_LENGTH+1];
+ CONST char *p;
+ time_t now;
+ size_t length;
+ Tk_Window tkwin = wi->win;
/*
- * A null area means print the currently visible area.
+ * Offset of lower-left corner of area to be marked up, measured
+ * in canvas units from the positioning point on the page (reflects
+ * anchor position). Initial values needed only to stop compiler
+ * warnings.
*/
- area = &ps_info.area;
- area->orig.x = 0;
- area->orig.y = 0;
- area->corner.x = 0;
- area->corner.y = 0;
+ int delta_x = 0, delta_y = 0;
+ Tcl_HashSearch search;
+ Tcl_HashEntry *entry;
+ Tcl_DString buffer;
+ char psenccmd[] = "::tk::ensure_psenc_is_loaded";
+
/*
- * Center the result on a letter format page
- * The size will be deduced automatically from
- * the area (default to a 1:1 scale along X axis).
+ *----------------------------------------------------------------
+ * Initialize the data structure describing Postscript generation,
+ * then process all the arguments to fill the data structure in.
+ *----------------------------------------------------------------
*/
- ps_info.page_x = 72*4.25;
- ps_info.page_y = 72*5.5;
- ps_info.page_width = -1;
- ps_info.page_height = -1;
- ps_info.page_anchor = TK_ANCHOR_CENTER;
-
- ps_info.landscape = False;
- ps_info.font_var = NULL;
- ps_info.color_var = NULL;
- ps_info.colormode = 2;
- ps_info.filename = NULL;
- ps_info.channel_name = NULL;
+ result = Tcl_EvalEx(wi->interp, psenccmd, -1, TCL_EVAL_GLOBAL);
+ if (result != TCL_OK) {
+ return result;
+ }
+ old_info = wi->ps_info;
+ wi->ps_info = (Tk_PostscriptInfo) &ps_info;
+ ps_info.x = (int) wi->origin.x;
+ ps_info.y = (int) wi->origin.y;
+ ps_info.width = -1;
+ ps_info.height = -1;
+ ps_info.pageXString = NULL;
+ ps_info.pageYString = NULL;
+ ps_info.pageX = 72*4.25;
+ ps_info.pageY = 72*5.5;
+ ps_info.pageWidthString = NULL;
+ ps_info.pageHeightString = NULL;
+ ps_info.scale = 1.0;
+ ps_info.pageAnchor = TK_ANCHOR_CENTER;
+ ps_info.rotate = 0;
+ ps_info.fontVar = NULL;
+ ps_info.colorVar = NULL;
+ ps_info.colorMode = NULL;
+ ps_info.colorLevel = 0;
+ ps_info.fileName = NULL;
+ ps_info.channelName = NULL;
ps_info.chan = NULL;
- ps_info.prepass = False;
- ps_info.prolog = True;
- Tcl_InitHashTable(&ps_info.font_table, TCL_STRING_KEYS);
- result = Tk_ConfigureWidget(wi->interp, wi->win, config_specs, argc-2,
-#ifdef PTK
- (Tcl_Obj **) args+2, (char *) &ps_info,
- TK_CONFIG_ARGV_ONLY
-#else
- (CONST char **) args+2, (char *) &ps_info,
- TK_CONFIG_ARGV_ONLY|TK_CONFIG_OBJS
-#endif
-);
+ ps_info.prepass = 0;
+ ps_info.prolog = 1;
+ Tcl_InitHashTable(&ps_info.fontTable, TCL_STRING_KEYS);
+ result = Tk_ConfigureWidget(wi->interp, wi->win, config_specs,
+ argc-2, (CONST char **) argv+2,
+ (char *) &ps_info,
+ TK_CONFIG_ARGV_ONLY|TK_CONFIG_OBJS);
if (result != TCL_OK) {
goto cleanup;
}
- if ((area->corner.x - area->orig.x) == 0) {
- area->orig.x = 0;
- area->corner.x = Tk_Width(wi->win);
+ if (ps_info.width == -1) {
+ ps_info.width = Tk_Width(tkwin);
}
- width = area->corner.x - area->orig.x;
- if ((area->corner.y - area->orig.y) == 0) {
- area->orig.y = 0;
- area->corner.y = Tk_Height(wi->win);
+ if (ps_info.height == -1) {
+ ps_info.height = Tk_Height(tkwin);
}
- height = area->corner.y - area->orig.y;
-
- if ((ps_info.page_width < 0) || (ps_info.page_height < 0)) {
- ZnReal scale;
- if (ps_info.page_width >= 0) {
- scale = ps_info.page_width / width;
- }
- else if (ps_info.page_height >= 0) {
- scale = ps_info.page_height / height;
+ ps_info.x2 = ps_info.x + ps_info.width;
+ ps_info.y2 = ps_info.y + ps_info.height;
+ ps_info.bbox.orig.x = ps_info.x;
+ ps_info.bbox.orig.y = ps_info.y;
+ ps_info.bbox.corner.x = ps_info.x2;
+ ps_info.bbox.corner.y = ps_info.y2;
+
+ if (ps_info.pageXString != NULL) {
+ if (GetPostscriptPoints(wi->interp, ps_info.pageXString, &ps_info.pageX) != TCL_OK) {
+ goto cleanup;
}
- else {
- scale = (72.0 / 25.4) * WidthMMOfScreen(Tk_Screen(wi->win));
- scale /= WidthOfScreen(Tk_Screen(wi->win));
+ }
+ if (ps_info.pageYString != NULL) {
+ if (GetPostscriptPoints(wi->interp, ps_info.pageYString, &ps_info.pageY) != TCL_OK) {
+ goto cleanup;
}
- if (ps_info.page_width < 0) {
- ps_info.page_width = width * scale;
+ }
+ if (ps_info.pageWidthString != NULL) {
+ if (GetPostscriptPoints(wi->interp, ps_info.pageWidthString, &ps_info.scale) != TCL_OK) {
+ goto cleanup;
}
- if (ps_info.page_height < 0) {
- ps_info.page_height = height * scale;
+ ps_info.scale /= ps_info.width;
+ }
+ else if (ps_info.pageHeightString != NULL) {
+ if (GetPostscriptPoints(wi->interp, ps_info.pageHeightString, &ps_info.scale) != TCL_OK) {
+ goto cleanup;
}
+ ps_info.scale /= ps_info.height;
}
-
- switch (ps_info.page_anchor) {
+ else {
+ ps_info.scale = (72.0/25.4)*WidthMMOfScreen(Tk_Screen(tkwin));
+ ps_info.scale /= WidthOfScreen(Tk_Screen(tkwin));
+ }
+ switch (ps_info.pageAnchor) {
case TK_ANCHOR_NW:
case TK_ANCHOR_W:
case TK_ANCHOR_SW:
@@ -639,24 +358,24 @@ ZnPostScriptCmd(ZnWInfo *wi,
case TK_ANCHOR_N:
case TK_ANCHOR_CENTER:
case TK_ANCHOR_S:
- delta_x = -width/2;
+ delta_x = -ps_info.width/2;
break;
case TK_ANCHOR_NE:
case TK_ANCHOR_E:
case TK_ANCHOR_SE:
- delta_x = -width;
+ delta_x = -ps_info.width;
break;
}
- switch (ps_info.page_anchor) {
+ switch (ps_info.pageAnchor) {
case TK_ANCHOR_NW:
case TK_ANCHOR_N:
case TK_ANCHOR_NE:
- delta_y = -height;
+ delta_y = - ps_info.height;
break;
case TK_ANCHOR_W:
case TK_ANCHOR_CENTER:
case TK_ANCHOR_E:
- delta_y = -height/2;
+ delta_y = -ps_info.height/2;
break;
case TK_ANCHOR_SW:
case TK_ANCHOR_S:
@@ -665,28 +384,50 @@ ZnPostScriptCmd(ZnWInfo *wi,
break;
}
- if (ps_info.filename != NULL) {
+ if (ps_info.colorMode == NULL) {
+ ps_info.colorLevel = 2;
+ }
+ else {
+ length = strlen(ps_info.colorMode);
+ if (strncmp(ps_info.colorMode, "monochrome", length) == 0) {
+ ps_info.colorLevel = 0;
+ }
+ else if (strncmp(ps_info.colorMode, "gray", length) == 0) {
+ ps_info.colorLevel = 1;
+ }
+ else if (strncmp(ps_info.colorMode, "color", length) == 0) {
+ ps_info.colorLevel = 2;
+ }
+ else {
+ Tcl_AppendResult(wi->interp, "bad color mode \"", ps_info.colorMode,
+ "\": must be monochrome, ", "gray, or color",
+ (char *) NULL);
+ goto cleanup;
+ }
+ }
+ if (ps_info.fileName != NULL) {
/*
* Check that -file and -channel are not both specified.
*/
- if (ps_info.channel_name != NULL) {
- Tcl_AppendResult(wi->interp, "can't specify both -file and -channel", NULL);
+ if (ps_info.channelName != NULL) {
+ Tcl_AppendResult(wi->interp, "can't specify both -file", " and -channel",
+ (char *) NULL);
result = TCL_ERROR;
goto cleanup;
}
-
/*
* Check that we are not in a safe interpreter. If we are, disallow
* the -file specification.
*/
if (Tcl_IsSafe(wi->interp)) {
- Tcl_AppendResult(wi->interp, "can't specify -file in a safe interpreter", NULL);
+ Tcl_AppendResult(wi->interp, "can't specify -file in a", " safe interpreter",
+ (char *) NULL);
result = TCL_ERROR;
goto cleanup;
}
-
- p = Tcl_TranslateFileName(wi->interp, ps_info.filename, &buffer);
+
+ p = Tcl_TranslateFileName(wi->interp, ps_info.fileName, &buffer);
if (p == NULL) {
goto cleanup;
}
@@ -697,21 +438,21 @@ ZnPostScriptCmd(ZnWInfo *wi,
}
}
- if (ps_info.channel_name != NULL) {
+ if (ps_info.channelName != NULL) {
int mode;
/*
* Check that the channel is found in this interpreter and that it
* is open for writing.
*/
- ps_info.chan = Tcl_GetChannel(wi->interp, ps_info.channel_name, &mode);
+ ps_info.chan = Tcl_GetChannel(wi->interp, ps_info.channelName, &mode);
if (ps_info.chan == (Tcl_Channel) NULL) {
result = TCL_ERROR;
goto cleanup;
}
if ((mode & TCL_WRITABLE) == 0) {
- Tcl_AppendResult(wi->interp, "channel \"", ps_info.channel_name,
- "\" wasn't opened for writing", NULL);
+ Tcl_AppendResult(wi->interp, "channel \"", ps_info.channelName,
+ "\" wasn't opened for writing", (char *) NULL);
result = TCL_ERROR;
goto cleanup;
}
@@ -727,10 +468,15 @@ ZnPostScriptCmd(ZnWInfo *wi,
*--------------------------------------------------------
*/
ps_info.prepass = 1;
-
- wi->top_group->class->PostScript(wi->top_group, True);
+ result = wi->top_group->class->PostScript(wi->top_group, True, &ps_info.bbox);
Tcl_ResetResult(wi->interp);
-
+ /*
+ * If an error occurred, just proceed with the main pass.
+ * There's no need to report the error now; it can be
+ * reported later (errors can happen later that don't
+ * happen now, so we still have to check for errors later
+ * anyway).
+ */
ps_info.prepass = 0;
/*
@@ -739,77 +485,57 @@ ZnPostScriptCmd(ZnWInfo *wi,
*--------------------------------------------------------
*/
if (ps_info.prolog) {
- ZnReal scale_x, scale_y;
-
- scale_x = ps_info.page_width / width;
- scale_y = ps_info.page_height/ height;
-
- Tcl_AppendResult(wi->interp,
- "%!PS-Adobe-3.0 EPSF-3.0\n",
- "%%Creator: TkZinc Widget\n",
- NULL);
+ Tcl_AppendResult(wi->interp, "%!PS-Adobe-3.0 EPSF-3.0\n",
+ "%%Creator: Tk Zinc Widget\n", (char *) NULL);
#ifdef HAVE_PW_GECOS
if (!Tcl_IsSafe(wi->interp)) {
- struct passwd *pw = getpwuid(getuid());
- Tcl_AppendResult(wi->interp,
- "%%For: ", (pw != NULL) ? pw->pw_gecos : "Unknown", "\n",
- NULL);
+ struct passwd *pwPtr = getpwuid(getuid()); /* INTL: Native. */
+ Tcl_AppendResult(wi->interp, "%%For: ",
+ (pwPtr != NULL) ? pwPtr->pw_gecos : "Unknown", "\n",
+ (char *) NULL);
endpwent();
}
#endif /* HAVE_PW_GECOS */
- Tcl_AppendResult(wi->interp,
- "%%Title: Window ", Tk_PathName(wi->win), "\n",
- NULL);
+ Tcl_AppendResult(wi->interp, "%%Title: Window ", Tk_PathName(tkwin), "\n",
+ (char *) NULL);
time(&now);
- Tcl_AppendResult(wi->interp,
- "%%CreationDate: ", ctime(&now),
- NULL);
-
- if (!ps_info.landscape) {
- sprintf(string, "%d %d %d %d",
- (int) (ps_info.page_x + scale_x*delta_x),
- (int) (ps_info.page_y + scale_y*delta_y),
- (int) (ps_info.page_x + scale_x*(delta_x + width) + 1.0),
- (int) (ps_info.page_y + scale_y*(delta_y + height) + 1.0));
- } else {
+ /* INTL: Native. */
+ Tcl_AppendResult(wi->interp, "%%CreationDate: ", ctime(&now), (char *) NULL);
+ if (!ps_info.rotate) {
+ sprintf(string, "%d %d %d %d", (int) (ps_info.pageX + ps_info.scale*delta_x),
+ (int) (ps_info.pageY + ps_info.scale*delta_y),
+ (int) (ps_info.pageX + ps_info.scale*(delta_x + ps_info.width) + 1.0),
+ (int) (ps_info.pageY + ps_info.scale*(delta_y + ps_info.height) + 1.0));
+ }
+ else {
sprintf(string, "%d %d %d %d",
- (int) (ps_info.page_x - scale_x*(delta_y + height)),
- (int) (ps_info.page_y + scale_y*delta_x),
- (int) (ps_info.page_x - scale_x*delta_y + 1.0),
- (int) (ps_info.page_y + scale_y*(delta_x + width) + 1.0));
- }
- Tcl_AppendResult(wi->interp,
- "%%BoundingBox: ", string, "\n",
- NULL);
- Tcl_AppendResult(wi->interp,
- "%%Pages: 1\n",
- "%%DocumentData: Clean7Bit\n",
- NULL);
- Tcl_AppendResult(wi->interp,
- "%%Orientation: ",
- ps_info.landscape ? "Landscape\n" : "Portrait\n",
- NULL);
+ (int) (ps_info.pageX - ps_info.scale*(delta_y + ps_info.height)),
+ (int) (ps_info.pageY + ps_info.scale*delta_x),
+ (int) (ps_info.pageX - ps_info.scale*delta_y + 1.0),
+ (int) (ps_info.pageY + ps_info.scale*(delta_x + ps_info.width) + 1.0));
+ }
+ Tcl_AppendResult(wi->interp, "%%BoundingBox: ", string, "\n", (char *) NULL);
+ Tcl_AppendResult(wi->interp, "%%Pages: 1\n", "%%DocumentData: Clean7Bit\n",
+ (char *) NULL);
+ Tcl_AppendResult(wi->interp, "%%Orientation: ",
+ ps_info.rotate ? "Landscape\n" : "Portrait\n", (char *) NULL);
p = "%%DocumentNeededResources: font ";
- for (entry = Tcl_FirstHashEntry(&ps_info.font_table, &search);
- entry != NULL; entry = Tcl_NextHashEntry(&search)) {
- Tcl_AppendResult(wi->interp,
- p, Tcl_GetHashKey(&ps_info.font_table, entry), "\n",
- NULL);
+ for (entry = Tcl_FirstHashEntry(&ps_info.fontTable, &search); entry != NULL;
+ entry = Tcl_NextHashEntry(&search)) {
+ Tcl_AppendResult(wi->interp, p, Tcl_GetHashKey(&ps_info.fontTable, entry),
+ "\n", (char *) NULL);
p = "%%+ font ";
}
- Tcl_AppendResult(wi->interp,
- "%%EndComments\n\n",
- NULL);
-
+ Tcl_AppendResult(wi->interp, "%%EndComments\n\n", (char *) NULL);
+
/*
* Insert the prolog
*/
- Tcl_AppendResult(wi->interp,
- Tcl_GetVar(wi->interp,"::tk::ps_preamable", TCL_GLOBAL_ONLY),
- NULL);
-
+ Tcl_AppendResult(wi->interp, Tcl_GetVar(wi->interp,"::tk::ps_preamable",
+ TCL_GLOBAL_ONLY), (char *) NULL);
+
if (ps_info.chan != NULL) {
- /* Tcl_Write(ps_info.chan, Tcl_GetStringResult(wi->interp), -1);*/
+ Tcl_Write(ps_info.chan, Tcl_GetStringResult(wi->interp), -1);
Tcl_ResetResult(wi->interp);
}
@@ -818,21 +544,15 @@ ZnPostScriptCmd(ZnWInfo *wi,
* Document setup: set the color level and include fonts.
*-----------------------------------------------------------
*/
- sprintf(string, "/CL %d def\n", ps_info.colormode);
- Tcl_AppendResult(wi->interp,
- "%%BeginSetup\n", string,
- NULL);
- for (entry = Tcl_FirstHashEntry(&ps_info.font_table, &search);
- entry != NULL; entry = Tcl_NextHashEntry(&search)) {
- Tcl_AppendResult(wi->interp,
- "%%IncludeResource: font ",
- Tcl_GetHashKey(&ps_info.font_table, entry), "\n",
- NULL);
- }
- Tcl_AppendResult(wi->interp,
- "%%EndSetup\n\n",
- NULL);
-
+ sprintf(string, "/CL %d def\n", ps_info.colorLevel);
+ Tcl_AppendResult(wi->interp, "%%BeginSetup\n", string, (char *) NULL);
+ for (entry = Tcl_FirstHashEntry(&ps_info.fontTable, &search); entry != NULL;
+ entry = Tcl_NextHashEntry(&search)) {
+ Tcl_AppendResult(wi->interp, "%%IncludeResource: font ",
+ Tcl_GetHashKey(&ps_info.fontTable, entry), "\n", (char *) NULL);
+ }
+ Tcl_AppendResult(wi->interp, "%%EndSetup\n\n", (char *) NULL);
+
/*
*-----------------------------------------------------------
* Page setup: move to page positioning point, rotate if
@@ -840,44 +560,43 @@ ZnPostScriptCmd(ZnWInfo *wi,
* and set clip region.
*-----------------------------------------------------------
*/
- Tcl_AppendResult(wi->interp,
- "%%Page: 1 1\n",
- "save\n",
- NULL);
- sprintf(string, "%.1f %.1f translate\n", ps_info.page_x, ps_info.page_y);
- Tcl_AppendResult(wi->interp, string, NULL);
- if (ps_info.landscape) {
- Tcl_AppendResult(wi->interp,
- "90 rotate\n",
- NULL);
- }
- sprintf(string, "%.4g %.4g scale\n", scale_x, scale_y);
- Tcl_AppendResult(wi->interp, string, NULL);
- sprintf(string, "%d %d translate\n",
- (int) (delta_x - area->orig.x), (int) delta_y);
- Tcl_AppendResult(wi->interp, string, NULL);
+ Tcl_AppendResult(wi->interp, "%%Page: 1 1\n", "save\n", (char *) NULL);
+ sprintf(string, "%.1f %.1f translate\n", ps_info.pageX, ps_info.pageY);
+ Tcl_AppendResult(wi->interp, string, (char *) NULL);
+ if (ps_info.rotate) {
+ Tcl_AppendResult(wi->interp, "90 rotate\n", (char *) NULL);
+ }
+ sprintf(string, "%.4g %.4g scale\n", ps_info.scale, -ps_info.scale);
+ Tcl_AppendResult(wi->interp, string, (char *) NULL);
+ sprintf(string, "%d %d translate\n", delta_x - ps_info.x, delta_y);
+ Tcl_AppendResult(wi->interp, string, (char *) NULL);
+ /*
+ * Save the base matrix for further reference.
+ */
+ Tcl_AppendResult(wi->interp, "/InitialTransform matrix currentmatrix def\n", NULL);
+
sprintf(string, "%d %.15g moveto %d %.15g lineto %d %.15g lineto %d %.15g",
- (int) area->orig.x, ZnPostScriptY(area->orig.y, &ps_info),
- (int) area->corner.x, ZnPostScriptY(area->orig.y, &ps_info),
- (int) area->corner.x, ZnPostScriptY(area->corner.y, &ps_info),
- (int) area->orig.x, ZnPostScriptY(area->corner.y, &ps_info));
- Tcl_AppendResult(wi->interp,
- string, " lineto closepath clip newpath\n",
- NULL);
+ ps_info.x, Tk_PostscriptY((double) ps_info.y, (Tk_PostscriptInfo) &ps_info),
+ ps_info.x2, Tk_PostscriptY((double) ps_info.y, (Tk_PostscriptInfo) &ps_info),
+ ps_info.x2, Tk_PostscriptY((double) ps_info.y2, (Tk_PostscriptInfo) &ps_info),
+ ps_info.x, Tk_PostscriptY((double) ps_info.y2, (Tk_PostscriptInfo) &ps_info));
+ Tcl_AppendResult(wi->interp, string, " lineto closepath clip newpath\n", (char *) NULL);
}
-
if (ps_info.chan != NULL) {
- /* Tcl_Write(ps_info.chan, Tcl_GetStringResult(wi->interp), -1);*/
+ Tcl_Write(ps_info.chan, Tcl_GetStringResult(wi->interp), -1);
Tcl_ResetResult(wi->interp);
}
-
+
/*
*---------------------------------------------------------------------
- * Second pass through all the items. This time PostScript is actually
- * emitted.
+ * Iterate through all the items, having each relevant one draw itself.
+ * Quit if any of the items returns an error.
*---------------------------------------------------------------------
*/
- wi->top_group->class->PostScript(wi->top_group, False);
+ result = wi->top_group->class->PostScript(wi->top_group, False, &ps_info.bbox);
+ if (result == TCL_ERROR) {
+ goto cleanup;
+ }
/*
*---------------------------------------------------------------------
@@ -886,37 +605,1263 @@ ZnPostScriptCmd(ZnWInfo *wi,
*---------------------------------------------------------------------
*/
if (ps_info.prolog) {
- Tcl_AppendResult(wi->interp,
- "restore showpage\n\n",
- "%%Trailer\nend\n%%EOF\n",
- NULL);
+ Tcl_AppendResult(wi->interp, "restore showpage\n\n", "%%Trailer\nend\n%%EOF\n",
+ (char *) NULL);
}
if (ps_info.chan != NULL) {
- /* Tcl_Write(ps_info.chan, Tcl_GetStringResult(wi->interp), -1);*/
+ Tcl_Write(ps_info.chan, Tcl_GetStringResult(wi->interp), -1);
Tcl_ResetResult(wi->interp);
}
- cleanup:
- if (ps_info.font_var != NULL) {
- ZnFree(ps_info.font_var);
+ /*
+ * Clean up ps_info to release malloc'ed stuff.
+ */
+ cleanup:
+ if (ps_info.pageXString != NULL) {
+ ckfree(ps_info.pageXString);
}
- if (ps_info.color_var != NULL) {
- ZnFree(ps_info.color_var);
+ if (ps_info.pageYString != NULL) {
+ ckfree(ps_info.pageYString);
}
- if (ps_info.filename != NULL) {
- ZnFree(ps_info.filename);
+ if (ps_info.pageWidthString != NULL) {
+ ckfree(ps_info.pageWidthString);
}
- if ((ps_info.chan != NULL) && (ps_info.channel_name == NULL)) {
- Tcl_Close(wi->interp, ps_info.chan);
+ if (ps_info.pageHeightString != NULL) {
+ ckfree(ps_info.pageHeightString);
}
- if (ps_info.channel_name != NULL) {
- ZnFree(ps_info.channel_name);
+ if (ps_info.fontVar != NULL) {
+ ckfree(ps_info.fontVar);
}
- Tcl_DeleteHashTable(&ps_info.font_table);
- wi->ps_info = old_info;
-
+ if (ps_info.colorVar != NULL) {
+ ckfree(ps_info.colorVar);
+ }
+ if (ps_info.colorMode != NULL) {
+ ckfree(ps_info.colorMode);
+ }
+ if (ps_info.fileName != NULL) {
+ ckfree(ps_info.fileName);
+ }
+ if ((ps_info.chan != NULL) && (ps_info.channelName == NULL)) {
+ Tcl_Close(wi->interp, ps_info.chan);
+ }
+ if (ps_info.channelName != NULL) {
+ ckfree(ps_info.channelName);
+ }
+ Tcl_DeleteHashTable(&ps_info.fontTable);
+ wi->ps_info = (Tk_PostscriptInfo) old_info;
return result;
}
+void
+ZnFlushPsChan(Tcl_Interp *interp,
+ Tk_PostscriptInfo ps_info) {
+ TkPostscriptInfo *psi = (TkPostscriptInfo *) ps_info;
+ if (psi->chan != NULL) {
+ Tcl_Write(psi->chan, Tcl_GetStringResult(interp), -1);
+ Tcl_ResetResult(interp);
+ }
+}
+int
+ZnPostscriptOutline(Tcl_Interp *interp,
+ Tk_PostscriptInfo ps_info,
+ Tk_Window tkwin,
+ ZnDim line_width,
+ ZnLineStyle line_style,
+ ZnGradient *line_color,
+ ZnImage line_pattern)
+{
+ char string[41];
+ char dashed[] = { 8 };
+ char dotted[] = { 2, 5 };
+ char mixed[] = { 8, 5, 2, 5 };
+ char *pattern = NULL;
+ int patlen = 0;
+
+ sprintf(string, "%.15g setlinewidth\n", (double) line_width);
+ Tcl_AppendResult(interp, string, NULL);
+ /*
+ * Setup the line style. It is dependent on the line
+ * width.
+ */
+ switch (line_style) {
+ case ZN_LINE_DOTTED:
+ pattern = dotted;
+ patlen = sizeof(dotted)/sizeof(char);
+ break;
+ case ZN_LINE_DASHED:
+ pattern = dashed;
+ patlen = sizeof(dashed)/sizeof(char);
+ break;
+ case ZN_LINE_MIXED:
+ pattern = mixed;
+ patlen = sizeof(mixed)/sizeof(char);
+ break;
+ }
+ if (pattern) {
+ sprintf(string, "[%d", ((*pattern++) * (int) line_width) & 0xff);
+ while (--patlen) {
+ sprintf(string+strlen(string), " %d", ((*pattern++) * (int) line_width) & 0xff);
+ }
+ Tcl_AppendResult(interp, string, NULL);
+ sprintf(string, "] %d setdash\n", 0 /* dash offset */);
+ Tcl_AppendResult(interp, string, NULL);
+ }
+ if (Tk_PostscriptColor(interp, ps_info,
+ ZnGetGradientColor(line_color, 0.0, NULL)) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ if (line_pattern != ZnUnspecifiedImage) {
+ Tcl_AppendResult(interp, "StrokeClip ", NULL);
+ if (Tk_PostscriptStipple(interp, tkwin, ps_info,
+ ZnImagePixmap(line_pattern, tkwin)) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ }
+ else {
+ Tcl_AppendResult(interp, "stroke\n", NULL);
+ }
+
+ return TCL_OK;
+}
+
+/*
+ * Emit PostScript to describe a bitmap as a string possibly
+ * spliting it in parts due to the limited length of PostScript
+ * strings.
+ * This function emit the common code for ZnPostscriptBitmap and
+ * ZnPostscriptStipple.
+ */
+static int
+EmitPSBitmap()
+{
+}
+
+int
+ZnPostscriptStipple(Tcl_Interp *interp,
+ Tk_Window tkwin,
+ Tk_PostscriptInfo ps_info,
+ ZnImage bitmap)
+{
+ return TCL_OK;
+}
+
+int
+ZnPostscriptBitmap(Tcl_Interp *interp,
+ Tk_Window tkwin,
+ Tk_PostscriptInfo ps_info,
+ ZnImage bitmap,
+ ZnReal x,
+ ZnReal y,
+ int width,
+ int height)
+{
+ char buffer[100 + TCL_DOUBLE_SPACE * 2 + TCL_INTEGER_SPACE * 4];
+ int rows_at_once, rows_this_time, cur_row;
+
+ if (width > 60000) {
+ Tcl_ResetResult(interp);
+ Tcl_AppendResult(interp, "can't generate Postscript",
+ " for bitmaps more than 60000 pixels wide", NULL);
+ return TCL_ERROR;
+ }
+ rows_at_once = 60000/width;
+ if (rows_at_once < 1) {
+ rows_at_once = 1;
+ }
+ sprintf(buffer, "%.15g %.15g translate\n", x, y + height);
+ Tcl_AppendResult(interp, buffer, NULL);
+ for (cur_row = 0; cur_row < height; cur_row += rows_at_once) {
+ rows_this_time = rows_at_once;
+ if (rows_this_time > (height - cur_row)) {
+ rows_this_time = height - cur_row;
+ }
+ sprintf(buffer, "0 -%.15g translate\n%d %d true matrix {\n",
+ (double) rows_this_time, width, rows_this_time);
+ Tcl_AppendResult(interp, buffer, NULL);
+ if (Tk_PostscriptBitmap(interp, tkwin, ps_info, ZnImagePixmap(bitmap, tkwin),
+ 0, cur_row, width, rows_this_time) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ Tcl_AppendResult(interp, "\n} imagemask\n", (char *) NULL);
+ }
+
+ return TCL_OK;
+}
+
+void
+ZnPostscriptString(Tcl_Interp *interp,
+ char *str,
+ int num_bytes)
+{
+ int used, len, clen;
+ int c, bytecount = 0;
+ CONST char *p, *last_p, *glyphname;
+ Tcl_UniChar ch;
+ char charbuf[5];
+#define MAXUSE 500
+ char buf[MAXUSE+30];
+
+ used = 0;
+ buf[used++] = '[';
+ buf[used++] = '(';
+ len = num_bytes;
+ p = str;
+ while (len) {
+ clen = Tcl_UtfToUniChar(p, &ch);
+ last_p = p;
+ p += clen;
+ len -= clen;
+ /*
+ * INTL: For now we just treat the characters as binary
+ * data and display the lower byte. Eventually this should
+ * be revised to handle international postscript fonts.
+ */
+ Tcl_UtfToExternal(interp, NULL, last_p, clen, 0, NULL,
+ charbuf, 4, NULL, &bytecount, NULL);
+ if (bytecount == 1) {
+ c = UCHAR(charbuf[0]);
+ if ((c == '(') || (c == ')') || (c == '\\') ||
+ (c < 0x20) || (c >= UCHAR(0x7f))) {
+ /*
+ * Tricky point: the "03" is necessary in the sprintf
+ * below, so that a full three digits of octal are
+ * always generated. Without the "03", a number
+ * following this sequence could be interpreted by
+ * Postscript as part of this sequence.
+ */
+ sprintf(buf + used, "\\%03o", c);
+ used += 4;
+ }
+ else {
+ buf[used++] = c;
+ }
+ }
+ else {
+ /* This character doesn't belong to system character set.
+ * So, we must use full glyph name */
+ sprintf(charbuf, "%04X", ch); /* endianness? */
+ if ((glyphname = Tcl_GetVar2(interp, "::tk::psglyphs", charbuf, 0))) {
+ if ((used > 0) && (buf[used-1] == '(')) {
+ --used;
+ }
+ else {
+ buf[used++] = ')';
+ }
+ if ((used + strlen(glyphname)) >= MAXUSE) {
+ buf[used] = '\0';
+ Tcl_AppendResult(interp, buf, NULL);
+ used = 0;
+ }
+ buf[used++] = '/';
+ while(*glyphname) {
+ buf[used++] = *glyphname++ ;
+ }
+ buf[used++] = '(';
+ }
+ }
+ if (used >= MAXUSE) {
+ buf[used] = '\0';
+ Tcl_AppendResult(interp, buf, NULL);
+ used = 0;
+ }
+ }
+ buf[used++] = ')';
+ buf[used++] = ']';
+ buf[used++] = '\n';
+ buf[used] = '\0';
+ Tcl_AppendResult(interp, buf, NULL);
+}
+
+int
+ZnPostscriptTile(Tcl_Interp *interp,
+ Tk_Window win,
+ Tk_PostscriptInfo ps_info,
+ ZnImage image)
+{
+ char path[150];
+ int w, h;
+
+ ZnSizeOfImage(image, &w, &h);
+ Tcl_AppendResult(interp, "<< /PatternType 1 /PaintType 1 /TilingType 1\n", NULL);
+ sprintf(path, " /BBox [%.15g %.15g %.15g %.15g] /XStep %.15g /YStep %.15g\n",
+ 0.0, (double) h, (double) w, 0.0, (double) w, (double) h);
+ Tcl_AppendResult(interp, path, " /PaintProc { begin\n", NULL);
+
+ /*
+ * On ne peut pas reprendre le code de Tk_PostscriptImage,
+ * il génère une image inline impropre à l'inclusion dans
+ * une procedure de tuilage. C'est d'ailleurs un problème :
+ * Une string postscript ne doit pas dépasser 65K.
+ */
+ if (Tk_PostscriptImage(ZnImageTkImage(image), interp, win, ps_info, 0, 0, w, h, 0) != TCL_OK) {
+ return TCL_ERROR;
+ }
+
+ Tcl_AppendResult(interp, "end } bind >> matrix makepattern setpattern fill\n", NULL);
+
+ return TCL_OK;
+}
+
+void
+ZnPostscriptTrace(ZnItem item,
+ ZnBool enter)
+{
+ ZnWInfo *wi = item->wi;
+ char buf[100];
+
+ if (wi->debug) {
+ sprintf(buf, "%%%%%%%% %s for %s %d %%%%%%%%\n",
+ enter ? "Code" : "End of code", item->class->name, item->id);
+ Tcl_AppendResult(wi->interp, buf, NULL);
+ }
+}
+
+int
+ZnPostscriptGradient(Tcl_Interp *interp,
+ Tk_PostscriptInfo ps_info,
+ ZnGradient *gradient,
+ ZnPoint *quad,
+ ZnPoly *poly)
+{
+ unsigned int i;
+ char path[150];
+ ZnPoint p, center, extent;
+ ZnGradientColor *gc1, *gc2;
+
+ if (gradient->type == ZN_CONICAL_GRADIENT || gradient->type == ZN_PATH_GRADIENT) {
+ return TCL_OK;
+ }
+
+ Tcl_AppendResult(interp, "<< /PatternType 2 /Shading\n", NULL);
+
+ switch (gradient->type) {
+ case ZN_AXIAL_GRADIENT:
+ /*
+ * Fill the rectangle defined by quad with
+ * the axial gradient.
+ */
+ switch (gradient->angle) {
+ case 0:
+ center = quad[0];
+ extent = quad[1];
+ case 90:
+ center = quad[0];
+ extent = quad[3];
+ break;
+ case 180:
+ center = quad[1];
+ extent = quad[0];
+ break;
+ case 270:
+ center = quad[3];
+ extent = quad[0];
+ break;
+ }
+ Tcl_AppendResult(interp,
+ " << /ShadingType 2 /ColorSpace /DeviceRGB /Extend [true true] ",
+ NULL);
+ sprintf(path, "/Coords [%.15g %.15g %.15g %.15g]\n",
+ quad[0].x, quad[0].y, quad[1].x, quad[1].y);
+ Tcl_AppendResult(interp, path, NULL);
+ break;
+ case ZN_RADIAL_GRADIENT:
+ /*
+ * On ne peut pas représenter un dégradé radial ou conique
+ * anamorphique si on n'inclu pas la transformation dans le
+ * PostScript résultant. PostScript ne peut décrire que des
+ * dégradés circulaires. La seule solution rapide est d'utiliser
+ * comme dans l'item Triangles une trame de triangles (Shading
+ * type 4).
+ */
+ p.x = p.y = 0;
+ ZnTransformPoint((ZnTransfo *) quad, &p, &center);
+ p.x = 1.0;
+ ZnTransformPoint((ZnTransfo *) quad, &p, &extent);
+ Tcl_AppendResult(interp,
+ " << /ShadingType 3 /ColorSpace /DeviceRGB /Extend [true true] ",
+ NULL);
+ sprintf(path, "/Coords [%.15g %.15g %.15g %.15g %.15g %.15g]\n",
+ center.x, center.y, 0.0, center.x, center.y, ABS(center.x-extent.x));
+ printf("center %g %g, radius %g\n", center.x, center.y, ABS(center.x-extent.x));
+ Tcl_AppendResult(interp, path, NULL);
+ break;
+ case ZN_CONICAL_GRADIENT:
+ break;
+ case ZN_PATH_GRADIENT:
+ break;
+ }
+
+ Tcl_AppendResult(interp, " /Function << ", NULL);
+ Tcl_AppendResult(interp, "/FunctionType 3\n", NULL);
+ Tcl_AppendResult(interp, " /Domain [0 1] /Bounds [", NULL);
+ for (i = 1; i < gradient->num_actual_colors-1; i++) {
+ sprintf(path, "%.4g ", gradient->actual_colors[i].position/100.0);
+ Tcl_AppendResult(interp, path, NULL);
+ }
+ Tcl_AppendResult(interp, "] /Encode [", NULL);
+ for (i = 0; i < gradient->num_actual_colors-1; i++) {
+ Tcl_AppendResult(interp, "0 1 ", NULL);
+ }
+ Tcl_AppendResult(interp, "]\n /Functions [\n", NULL);
+ for (i = 0, gc1 = gradient->actual_colors; i < gradient->num_actual_colors-1; i++) {
+ gc2 = gc1 + 1;
+ Tcl_AppendResult(interp, " << /FunctionType 2 /Domain [0 1] /N 1 ", NULL);
+ sprintf(path, "/C0 [%.8g %.8g %.8g] /C1 [%.8g %.8g %.8g] >>\n",
+ gc1->rgb->red/65535.0, gc1->rgb->green/65535.0, gc1->rgb->blue/65535.0,
+ gc2->rgb->red/65535.0, gc2->rgb->green/65535.0, gc2->rgb->blue/65535.0);
+ Tcl_AppendResult(interp, path, NULL);
+ gc1 = gc2;
+ }
+ Tcl_AppendResult(interp, " ] >>\n", NULL);
+ Tcl_AppendResult(interp, " >> >>\n", NULL);
+ Tcl_AppendResult(interp, "matrix makepattern setpattern fill\n", NULL);
+
+ return TCL_OK;
+}
+
+/*
+ *--------------------------------------------------------------
+ *
+ * TkImageGetColor --
+ *
+ * This procedure converts a pixel value to three floating
+ * point numbers, representing the amount of red, green, and
+ * blue in that pixel on the screen. It makes use of colormap
+ * data passed as an argument, and should work for all Visual
+ * types.
+ *
+ * This implementation is bogus on Windows because the colormap
+ * data is never filled in. Instead all postscript generated
+ * data coming through here is expected to be RGB color data.
+ * To handle lower bit-depth images properly, XQueryColors
+ * must be implemented for Windows.
+ *
+ * Results:
+ * Returns red, green, and blue color values in the range
+ * 0 to 1. There are no error returns.
+ *
+ * Side effects:
+ * None.
+ *
+ *--------------------------------------------------------------
+ */
+/*
+ * The following definition is used in generating postscript for images
+ * and windows.
+ */
+typedef struct TkColormapData { /* Hold color information for a window */
+ int separated; /* Whether to use separate color bands */
+ int color; /* Whether window is color or black/white */
+ int ncolors; /* Number of color values stored */
+ XColor *colors; /* Pixel value -> RGB mappings */
+ int red_mask, green_mask, blue_mask; /* Masks and shifts for each */
+ int red_shift, green_shift, blue_shift; /* color band */
+} TkColormapData;
+
+#ifdef WIN32
+#include <windows.h>
+
+/*
+ * We could just define these instead of pulling in windows.h.
+ #define GetRValue(rgb) ((BYTE)(rgb))
+ #define GetGValue(rgb) ((BYTE)(((WORD)(rgb)) >> 8))
+ #define GetBValue(rgb) ((BYTE)((rgb)>>16))
+*/
+#else
+#define GetRValue(rgb) ((rgb & cdata->red_mask) >> cdata->red_shift)
+#define GetGValue(rgb) ((rgb & cdata->green_mask) >> cdata->green_shift)
+#define GetBValue(rgb) ((rgb & cdata->blue_mask) >> cdata->blue_shift)
+#endif
+
+#if defined(WIN32) || defined(MAC_OSX_TK)
+static void
+TkImageGetColor(cdata, pixel, red, green, blue)
+ TkColormapData *cdata; /* Colormap data */
+ unsigned long pixel; /* Pixel value to look up */
+ double *red, *green, *blue; /* Color data to return */
+{
+ *red = (double) GetRValue(pixel) / 255.0;
+ *green = (double) GetGValue(pixel) / 255.0;
+ *blue = (double) GetBValue(pixel) / 255.0;
+}
+#else
+static void
+TkImageGetColor(cdata, pixel, red, green, blue)
+ TkColormapData *cdata; /* Colormap data */
+ unsigned long pixel; /* Pixel value to look up */
+ double *red, *green, *blue; /* Color data to return */
+{
+ if (cdata->separated) {
+ int r = GetRValue(pixel);
+ int g = GetGValue(pixel);
+ int b = GetBValue(pixel);
+ *red = cdata->colors[r].red / 65535.0;
+ *green = cdata->colors[g].green / 65535.0;
+ *blue = cdata->colors[b].blue / 65535.0;
+ } else {
+ *red = cdata->colors[pixel].red / 65535.0;
+ *green = cdata->colors[pixel].green / 65535.0;
+ *blue = cdata->colors[pixel].blue / 65535.0;
+ }
+}
#endif
+
+/*
+ *--------------------------------------------------------------
+ *
+ * ZnPostscriptXImage --
+ *
+ * This procedure is called to output the contents of an
+ * XImage in Postscript, using a format appropriate for the
+ * current color mode (i.e. one bit per pixel in monochrome,
+ * one byte per pixel in gray, and three bytes per pixel in
+ * color).
+ *
+ * Results:
+ * Returns a standard Tcl return value. If an error occurs
+ * then an error message will be left in interp->result.
+ * If no error occurs, then additional Postscript will be
+ * appended to interp->result.
+ *
+ * Side effects:
+ * None.
+ *
+ *--------------------------------------------------------------
+ */
+/* TODO beaucoup de code à partager avec photo ci dessous
+ * sans compter qu'il faut une autre fonction pour emettre
+ * du code pour les tiling patterns.
+ * Il faudrait un operateur central qui emette dans une
+ * string postscript des bandes d'image afin de respecter
+ * la taille max des strings (on peut aussi mettre les
+ * bandes dans un tableau au préalable). Cet opérateur
+ * gére le niveau de couleur (0, 1, ...) et sait gérer les
+ * bits de transparence Postscript 3 en option.
+ */
+int
+ZnPostscriptXImage(Tcl_Interp *interp,
+ Tk_Window tkwin,
+ Tk_PostscriptInfo psInfo,
+ XImage *ximage,
+ int x,
+ int y,
+ int width,
+ int height)
+{
+ TkPostscriptInfo *psi = (TkPostscriptInfo *) psInfo;
+ char buffer[256];
+ int xx, yy, band, maxRows;
+ double red, green, blue;
+ int bytesPerLine=0, maxWidth=0;
+ int level = psi->colorLevel;
+ Colormap cmap;
+ int i, ncolors;
+ Visual *visual;
+ TkColormapData cdata;
+
+ if (psi->prepass) {
+ return TCL_OK;
+ }
+
+ Tcl_AppendResult(interp, "%%%%%% Start of ZnPostscriptXImage\n", NULL);
+
+ cmap = Tk_Colormap(tkwin);
+ visual = Tk_Visual(tkwin);
+
+ /*
+ * Obtain information about the colormap, ie the mapping between
+ * pixel values and RGB values. The code below should work
+ * for all Visual types.
+ */
+ ncolors = visual->map_entries;
+ cdata.colors = (XColor *) ckalloc(sizeof(XColor) * ncolors);
+ cdata.ncolors = ncolors;
+
+ if ((visual->class == DirectColor) || (visual->class == TrueColor)) {
+ cdata.separated = 1;
+ cdata.red_mask = visual->red_mask;
+ cdata.green_mask = visual->green_mask;
+ cdata.blue_mask = visual->blue_mask;
+ cdata.red_shift = 0;
+ cdata.green_shift = 0;
+ cdata.blue_shift = 0;
+ while ((0x0001 & (cdata.red_mask >> cdata.red_shift)) == 0) {
+ cdata.red_shift ++;
+ }
+ while ((0x0001 & (cdata.green_mask >> cdata.green_shift)) == 0) {
+ cdata.green_shift ++;
+ }
+ while ((0x0001 & (cdata.blue_mask >> cdata.blue_shift)) == 0) {
+ cdata.blue_shift ++;
+ }
+ for (i = 0; i < ncolors; i ++) {
+ cdata.colors[i].pixel = ((i << cdata.red_shift) & cdata.red_mask) |
+ ((i << cdata.green_shift) & cdata.green_mask) |
+ ((i << cdata.blue_shift) & cdata.blue_mask);
+ }
+ }
+ else {
+ cdata.separated=0;
+ for (i = 0; i < ncolors; i ++) {
+ cdata.colors[i].pixel = i;
+ }
+ }
+ if ((visual->class == StaticGray) || (visual->class == GrayScale)) {
+ cdata.color = 0;
+ }
+ else {
+ cdata.color = 1;
+ }
+
+ XQueryColors(Tk_Display(tkwin), cmap, cdata.colors, ncolors);
+
+ /*
+ * Figure out which color level to use (possibly lower than the
+ * one specified by the user). For example, if the user specifies
+ * color with monochrome screen, use gray or monochrome mode instead.
+ */
+
+ if (!cdata.color && level == 2) {
+ level = 1;
+ }
+ if (!cdata.color && cdata.ncolors == 2) {
+ level = 0;
+ }
+
+ /*
+ * Check that at least one row of the image can be represented
+ * with a string less than 64 KB long (this is a limit in the
+ * Postscript interpreter).
+ */
+ switch (level) {
+ case 0: bytesPerLine = (width + 7) / 8; maxWidth = 240000; break;
+ case 1: bytesPerLine = width; maxWidth = 60000; break;
+ case 2: bytesPerLine = 3 * width; maxWidth = 20000; break;
+ }
+
+ if (bytesPerLine > 60000) {
+ Tcl_ResetResult(interp);
+ sprintf(buffer, "Can't generate Postscript for images more than %d pixels wide", maxWidth);
+ Tcl_AppendResult(interp, buffer, (char *) NULL);
+ ckfree((char *) cdata.colors);
+ return TCL_ERROR;
+ }
+
+ maxRows = 60000 / bytesPerLine;
+
+ for (band = height-1; band >= 0; band -= maxRows) {
+ int rows = (band >= maxRows) ? maxRows : band + 1;
+ int lineLen = 0;
+ switch (level) {
+ case 0:
+ sprintf(buffer, "%d %d 1 matrix {\n<", width, rows);
+ Tcl_AppendResult(interp, buffer, (char *) NULL);
+ break;
+ case 1:
+ sprintf(buffer, "%d %d 8 matrix {\n<", width, rows);
+ Tcl_AppendResult(interp, buffer, (char *) NULL);
+ break;
+ case 2:
+ sprintf(buffer, "%d %d 8 matrix {\n<", width, rows);
+ Tcl_AppendResult(interp, buffer, (char *) NULL);
+ break;
+ }
+ for (yy = band; yy > band - rows; yy--) {
+ switch (level) {
+ case 0:
+ {
+ /*
+ * Generate data for image in monochrome mode.
+ * No attempt at dithering is made--instead, just
+ * set a threshold.
+ */
+ unsigned char mask=0x80;
+ unsigned char data=0x00;
+ for (xx = x; xx< x+width; xx++) {
+ TkImageGetColor(&cdata, XGetPixel(ximage, xx, yy),
+ &red, &green, &blue);
+ if (0.30 * red + 0.59 * green + 0.11 * blue > 0.5)
+ data |= mask;
+ mask >>= 1;
+ if (mask == 0) {
+ sprintf(buffer, "%02X", data);
+ Tcl_AppendResult(interp, buffer, (char *) NULL);
+ lineLen += 2;
+ if (lineLen > 60) {
+ lineLen = 0;
+ Tcl_AppendResult(interp, "\n", (char *) NULL);
+ }
+ mask=0x80;
+ data=0x00;
+ }
+ }
+ if ((width % 8) != 0) {
+ sprintf(buffer, "%02X", data);
+ Tcl_AppendResult(interp, buffer, (char *) NULL);
+ mask=0x80;
+ data=0x00;
+ }
+ break;
+ }
+ case 1:
+ {
+ /*
+ * Generate data in gray mode--in this case, take a
+ * weighted sum of the red, green, and blue values.
+ */
+ for (xx = x; xx < x+width; xx ++) {
+ TkImageGetColor(&cdata, XGetPixel(ximage, xx, yy),
+ &red, &green, &blue);
+ sprintf(buffer, "%02X", (int) floor(0.5 + 255.0 *
+ (0.30 * red + 0.59 * green + 0.11 * blue)));
+ Tcl_AppendResult(interp, buffer, (char *) NULL);
+ lineLen += 2;
+ if (lineLen > 60) {
+ lineLen = 0;
+ Tcl_AppendResult(interp, "\n", (char *) NULL);
+ }
+ }
+ break;
+ }
+ case 2:
+ {
+ /*
+ * Finally, color mode. Here, just output the red, green,
+ * and blue values directly.
+ */
+ for (xx = x; xx < x+width; xx++) {
+ TkImageGetColor(&cdata, XGetPixel(ximage, xx, yy),
+ &red, &green, &blue);
+ sprintf(buffer, "%02X%02X%02X",
+ (int) floor(0.5 + 255.0 * red),
+ (int) floor(0.5 + 255.0 * green),
+ (int) floor(0.5 + 255.0 * blue));
+ Tcl_AppendResult(interp, buffer, (char *) NULL);
+ lineLen += 6;
+ if (lineLen > 60) {
+ lineLen = 0;
+ Tcl_AppendResult(interp, "\n", (char *) NULL);
+ }
+ }
+ break;
+ }
+ }
+ }
+ switch (level) {
+ case 0: sprintf(buffer, ">\n} image\n"); break;
+ case 1: sprintf(buffer, ">\n} image\n"); break;
+ case 2: sprintf(buffer, ">\n} false 3 colorimage\n"); break;
+ }
+ Tcl_AppendResult(interp, buffer, (char *) NULL);
+ sprintf(buffer, "0 %d translate\n", rows);
+ Tcl_AppendResult(interp, buffer, (char *) NULL);
+ }
+ ckfree((char *) cdata.colors);
+
+ Tcl_AppendResult(interp, "%%%%%% End of ZnPostscriptXImage\n", NULL);
+
+ return TCL_OK;
+}
+
+/*
+ *--------------------------------------------------------------
+ *
+ * ZnPostscriptPhoto --
+ *
+ * This procedure is called to output the contents of a
+ * photo image in Postscript, using a format appropriate for
+ * the requested postscript color mode (i.e. one byte per pixel
+ * in gray, and three bytes per pixel in color).
+ *
+ * Results:
+ * Returns a standard Tcl return value. If an error occurs
+ * then an error message will be left in interp->result.
+ * If no error occurs, then additional Postscript will be
+ * appended to the interpreter's result.
+ *
+ * Side effects:
+ * None.
+ *
+ *--------------------------------------------------------------
+ */
+int
+ZnPostscriptPhoto(Tcl_Interp *interp,
+ Tk_PhotoImageBlock *blockPtr,
+ Tk_PostscriptInfo ps_info,
+ int width,
+ int height)
+{
+ TkPostscriptInfo *psi = (TkPostscriptInfo *) ps_info;
+ static int codeIncluded = 0;
+ unsigned char *pixelPtr;
+ char buffer[256], cspace[40], decode[40];
+ int bpc;
+ int xx, yy, lineLen;
+ float red, green, blue;
+ int alpha;
+ int bytesPerLine=0, maxWidth=0;
+ unsigned char opaque = 255;
+ unsigned char *alphaPtr;
+ int alphaOffset, alphaPitch, alphaIncr;
+
+ if (psi->prepass) {
+ codeIncluded = 0;
+ return TCL_OK;
+ }
+
+ /*
+ * Define the "TkPhoto" function, which is a modified version
+ * of the original "transparentimage" function posted
+ * by ian@five-d.com (Ian Kemmish) to comp.lang.postscript.
+ * For a monochrome colorLevel this is a slightly different
+ * version that uses the imagemask command instead of image.
+ */
+ if( !codeIncluded && (psi->colorLevel != 0) ) {
+ /*
+ * Color and gray-scale code.
+ */
+ codeIncluded = !0;
+ Tcl_AppendResult(interp,
+ "/TkPhoto { \n",
+ " gsave \n",
+ " 32 dict begin \n",
+ " /tinteger exch def \n",
+ " /transparent 1 string def \n",
+ " transparent 0 tinteger put \n",
+ " /olddict exch def \n",
+ " olddict /DataSource get dup type /filetype ne { \n",
+ " olddict /DataSource 3 -1 roll \n",
+ " 0 () /SubFileDecode filter put \n",
+ " } { \n",
+ " pop \n",
+ " } ifelse \n",
+ " /newdict olddict maxlength dict def \n",
+ " olddict newdict copy pop \n",
+ " /w newdict /Width get def \n",
+ " /crpp newdict /Decode get length 2 idiv def \n",
+ " /str w string def \n",
+ " /pix w crpp mul string def \n",
+ " /substrlen 2 w log 2 log div floor exp cvi def \n",
+ " /substrs [ \n",
+ " { \n",
+ " substrlen string \n",
+ " 0 1 substrlen 1 sub { \n",
+ " 1 index exch tinteger put \n",
+ " } for \n",
+ " /substrlen substrlen 2 idiv def \n",
+ " substrlen 0 eq {exit} if \n",
+ " } loop \n",
+ " ] def \n",
+ " /h newdict /Height get def \n",
+ " 1 w div 1 h div matrix scale \n",
+ " olddict /ImageMatrix get exch matrix concatmatrix \n",
+ " matrix invertmatrix concat \n",
+ " newdict /Height 1 put \n",
+ " newdict /DataSource pix put \n",
+ " /mat [w 0 0 h 0 0] def \n",
+ " newdict /ImageMatrix mat put \n",
+ " 0 1 h 1 sub { \n",
+ " mat 5 3 -1 roll neg put \n",
+ " olddict /DataSource get str readstring pop pop \n",
+ " /tail str def \n",
+ " /x 0 def \n",
+ " olddict /DataSource get pix readstring pop pop \n",
+ " { \n",
+ " tail transparent search dup /done exch not def \n",
+ " {exch pop exch pop} if \n",
+ " /w1 exch length def \n",
+ " w1 0 ne { \n",
+ " newdict /DataSource ",
+ " pix x crpp mul w1 crpp mul getinterval put \n",
+ " newdict /Width w1 put \n",
+ " mat 4 x neg put \n",
+ " /x x w1 add def \n",
+ " newdict image \n",
+ " /tail tail w1 tail length w1 sub getinterval def \n",
+ " } if \n",
+ " done {exit} if \n",
+ " tail substrs { \n",
+ " anchorsearch {pop} if \n",
+ " } forall \n",
+ " /tail exch def \n",
+ " tail length 0 eq {exit} if \n",
+ " /x w tail length sub def \n",
+ " } loop \n",
+ " } for \n",
+ " end \n",
+ " grestore \n",
+ "} bind def \n\n\n", (char *) NULL);
+ }
+ else if (!codeIncluded && (psi->colorLevel == 0)) {
+ /*
+ * Monochrome-only code
+ */
+ codeIncluded = !0;
+ Tcl_AppendResult(interp,
+ "/TkPhoto { \n",
+ " gsave \n",
+ " 32 dict begin \n",
+ " /dummyInteger exch def \n",
+ " /olddict exch def \n",
+ " olddict /DataSource get dup type /filetype ne { \n",
+ " olddict /DataSource 3 -1 roll \n",
+ " 0 () /SubFileDecode filter put \n",
+ " } { \n",
+ " pop \n",
+ " } ifelse \n",
+ " /newdict olddict maxlength dict def \n",
+ " olddict newdict copy pop \n",
+ " /w newdict /Width get def \n",
+ " /pix w 7 add 8 idiv string def \n",
+ " /h newdict /Height get def \n",
+ " 1 w div 1 h div matrix scale \n",
+ " olddict /ImageMatrix get exch matrix concatmatrix \n",
+ " matrix invertmatrix concat \n",
+ " newdict /Height 1 put \n",
+ " newdict /DataSource pix put \n",
+ " /mat [w 0 0 h 0 0] def \n",
+ " newdict /ImageMatrix mat put \n",
+ " 0 1 h 1 sub { \n",
+ " mat 5 3 -1 roll neg put \n",
+ " 0.000 0.000 0.000 setrgbcolor \n",
+ " olddict /DataSource get pix readstring pop pop \n",
+ " newdict /DataSource pix put \n",
+ " newdict imagemask \n",
+ " 1.000 1.000 1.000 setrgbcolor \n",
+ " olddict /DataSource get pix readstring pop pop \n",
+ " newdict /DataSource pix put \n",
+ " newdict imagemask \n",
+ " } for \n",
+ " end \n",
+ " grestore \n",
+ "} bind def \n\n\n", (char *) NULL);
+ }
+
+ /*
+ * Check that at least one row of the image can be represented
+ * with a string less than 64 KB long (this is a limit in the
+ * Postscript interpreter).
+ */
+ switch (psi->colorLevel)
+ {
+ case 0: bytesPerLine = (width + 7) / 8; maxWidth = 240000; break;
+ case 1: bytesPerLine = width; maxWidth = 60000; break;
+ case 2: bytesPerLine = 3 * width; maxWidth = 20000; break;
+ }
+ if (bytesPerLine > 60000) {
+ Tcl_ResetResult(interp);
+ sprintf(buffer, "Can't generate Postscript for images more than %d pixels wide",
+ maxWidth);
+ Tcl_AppendResult(interp, buffer, (char *) NULL);
+ return TCL_ERROR;
+ }
+
+ /*
+ * Set up the postscript code except for the image-data stream.
+ */
+ switch (psi->colorLevel) {
+ case 0:
+ strcpy( cspace, "/DeviceGray");
+ strcpy( decode, "[1 0]");
+ bpc = 1;
+ break;
+ case 1:
+ strcpy( cspace, "/DeviceGray");
+ strcpy( decode, "[0 1]");
+ bpc = 8;
+ break;
+ default:
+ strcpy( cspace, "/DeviceRGB");
+ strcpy( decode, "[0 1 0 1 0 1]");
+ bpc = 8;
+ break;
+ }
+
+ Tcl_AppendResult(interp, cspace, " setcolorspace\n\n", (char *) NULL);
+ sprintf(buffer, " /Width %d\n /Height %d\n /BitsPerComponent %d\n",
+ width, height, bpc);
+ Tcl_AppendResult(interp,
+ "<<\n /ImageType 1\n", buffer,
+ " /DataSource currentfile /ASCIIHexDecode filter\n", (char *) NULL);
+ sprintf(buffer, " /ImageMatrix [1 0 0 -1 0 %d]\n", height);
+ Tcl_AppendResult(interp, buffer, " /Decode ", decode, "\n>>\n1 TkPhoto\n", (char *) NULL);
+
+ /*
+ * Check the PhotoImageBlock information.
+ * We assume that:
+ * if pixelSize is 1,2 or 4, the image is R,G,B,A;
+ * if pixelSize is 3, the image is R,G,B and offset[3] is bogus.
+ */
+ if (blockPtr->pixelSize == 3) {
+ /*
+ * No alpha information: the whole image is opaque.
+ */
+ alphaPtr = &opaque;
+ alphaPitch = alphaIncr = alphaOffset = 0;
+ }
+ else {
+ /*
+ * Set up alpha handling.
+ */
+ alphaPtr = blockPtr->pixelPtr;
+ alphaPitch = blockPtr->pitch;
+ alphaIncr = blockPtr->pixelSize;
+ alphaOffset = blockPtr->offset[3];
+ }
+
+ for (yy = 0, lineLen=0; yy < height; yy++) {
+ switch (psi->colorLevel) {
+ case 0:
+ {
+ /*
+ * Generate data for image in monochrome mode.
+ * No attempt at dithering is made--instead, just
+ * set a threshold.
+ * To handle transparencies we need to output two lines:
+ * one for the black pixels, one for the white ones.
+ */
+ unsigned char mask=0x80;
+ unsigned char data=0x00;
+ for (xx = 0; xx< width; xx ++) {
+ pixelPtr = blockPtr->pixelPtr + (yy * blockPtr->pitch) + (xx *blockPtr->pixelSize);
+
+ red = pixelPtr[blockPtr->offset[0]];
+ green = pixelPtr[blockPtr->offset[1]];
+ blue = pixelPtr[blockPtr->offset[2]];
+
+ alpha = *(alphaPtr + (yy * alphaPitch) + (xx * alphaIncr) + alphaOffset);
+
+ /*
+ * If pixel is less than threshold, then it is black.
+ */
+ if ((alpha != 0) && (0.3086 * red + 0.6094 * green + 0.082 * blue < 128)) {
+ data |= mask;
+ }
+ mask >>= 1;
+ if (mask == 0) {
+ sprintf(buffer, "%02X", data);
+ Tcl_AppendResult(interp, buffer, (char *) NULL);
+ lineLen += 2;
+ if (lineLen >= 60) {
+ lineLen = 0;
+ Tcl_AppendResult(interp, "\n", (char *) NULL);
+ }
+ mask=0x80;
+ data=0x00;
+ }
+ }
+ if ((width % 8) != 0) {
+ sprintf(buffer, "%02X", data);
+ Tcl_AppendResult(interp, buffer, (char *) NULL);
+ mask=0x80;
+ data=0x00;
+ }
+
+ mask=0x80;
+ data=0x00;
+ for (xx = 0; xx< width; xx ++) {
+ pixelPtr = blockPtr->pixelPtr + (yy * blockPtr->pitch) + (xx *blockPtr->pixelSize);
+
+ red = pixelPtr[blockPtr->offset[0]];
+ green = pixelPtr[blockPtr->offset[1]];
+ blue = pixelPtr[blockPtr->offset[2]];
+
+ alpha = *(alphaPtr + (yy * alphaPitch) + (xx * alphaIncr) + alphaOffset);
+
+ /*
+ * If pixel is greater than threshold, then it is white.
+ */
+ if ((alpha != 0) && (0.3086 * red + 0.6094 * green + 0.082 * blue >= 128)) {
+ data |= mask;
+ }
+ mask >>= 1;
+ if (mask == 0) {
+ sprintf(buffer, "%02X", data);
+ Tcl_AppendResult(interp, buffer, (char *) NULL);
+ lineLen += 2;
+ if (lineLen >= 60) {
+ lineLen = 0;
+ Tcl_AppendResult(interp, "\n", (char *) NULL);
+ }
+ mask=0x80;
+ data=0x00;
+ }
+ }
+ if ((width % 8) != 0) {
+ sprintf(buffer, "%02X", data);
+ Tcl_AppendResult(interp, buffer, (char *) NULL);
+ mask=0x80;
+ data=0x00;
+ }
+ break;
+ }
+ case 1:
+ {
+ /*
+ * Generate transparency data.
+ * We must prevent a transparent value of 0
+ * because of a bug in some HP printers.
+ */
+ for (xx = 0; xx < width; xx ++) {
+ alpha = *(alphaPtr + (yy * alphaPitch) + (xx * alphaIncr) + alphaOffset);
+ sprintf(buffer, "%02X", alpha | 0x01);
+ Tcl_AppendResult(interp, buffer, (char *) NULL);
+ lineLen += 2;
+ if (lineLen >= 60) {
+ lineLen = 0;
+ Tcl_AppendResult(interp, "\n", (char *) NULL);
+ }
+ }
+
+ /*
+ * Generate data in gray mode--in this case, take a
+ * weighted sum of the red, green, and blue values.
+ */
+ for (xx = 0; xx < width; xx ++) {
+ pixelPtr = blockPtr->pixelPtr + (yy * blockPtr->pitch) + (xx *blockPtr->pixelSize);
+
+ red = pixelPtr[blockPtr->offset[0]];
+ green = pixelPtr[blockPtr->offset[1]];
+ blue = pixelPtr[blockPtr->offset[2]];
+
+ sprintf(buffer, "%02X",
+ (int) floor(0.5 + ( 0.3086 * red + 0.6094 * green + 0.0820 * blue)));
+ Tcl_AppendResult(interp, buffer, (char *) NULL);
+ lineLen += 2;
+ if (lineLen >= 60) {
+ lineLen = 0;
+ Tcl_AppendResult(interp, "\n", (char *) NULL);
+ }
+ }
+ break;
+ }
+ default:
+ {
+ /*
+ * Generate transparency data.
+ * We must prevent a transparent value of 0
+ * because of a bug in some HP printers.
+ */
+ for (xx = 0; xx < width; xx ++) {
+ alpha = *(alphaPtr + (yy * alphaPitch) + (xx * alphaIncr) + alphaOffset);
+ sprintf(buffer, "%02X", alpha | 0x01);
+ Tcl_AppendResult(interp, buffer, (char *) NULL);
+ lineLen += 2;
+ if (lineLen >= 60) {
+ lineLen = 0;
+ Tcl_AppendResult(interp, "\n", (char *) NULL);
+ }
+ }
+
+ /*
+ * Finally, color mode. Here, just output the red, green,
+ * and blue values directly.
+ */
+ for (xx = 0; xx < width; xx ++) {
+ pixelPtr = blockPtr->pixelPtr + (yy * blockPtr->pitch) + (xx *blockPtr->pixelSize);
+
+ sprintf(buffer, "%02X%02X%02X", pixelPtr[blockPtr->offset[0]],
+ pixelPtr[blockPtr->offset[1]], pixelPtr[blockPtr->offset[2]]);
+ Tcl_AppendResult(interp, buffer, (char *) NULL);
+ lineLen += 6;
+ if (lineLen >= 60) {
+ lineLen = 0;
+ Tcl_AppendResult(interp, "\n", (char *) NULL);
+ }
+ }
+ break;
+ }
+ }
+ }
+
+ Tcl_AppendResult(interp, ">\n", (char *) NULL);
+ return TCL_OK;
+}
+
+int
+ZnPostscriptImage(Tcl_Interp *interp,
+ Tk_Window tkwin,
+ Tk_PostscriptInfo ps_info,
+ ZnImage image,
+ int x,
+ int y,
+ int w,
+ int h)
+{
+ int result;
+ XImage *ximage;
+ Tk_PhotoHandle tkphoto;
+
+ if (((TkPostscriptInfo *) ps_info)->prepass) {
+ return TCL_OK;
+ }
+
+ tkphoto = ZnImageTkPhoto(image);
+ if (tkphoto != NULL) {
+ Tk_PhotoImageBlock block;
+
+ Tk_PhotoGetImage(tkphoto, &block);
+ block.pixelPtr += y * block.pitch + x * block.pixelSize;
+
+ return ZnPostscriptPhoto(interp, &block, ps_info, w, h);
+ }
+ else {
+ Pixmap pix = ZnImagePixmap(image, tkwin);
+ XGCValues values;
+ GC gc;
+
+ if (pix == None) {
+ /*
+ * Pixmap not cached (probably working under GL).
+ * Create a temporary pixmap.
+ */
+ pix = Tk_GetPixmap(Tk_Display(tkwin), Tk_WindowId(tkwin), w, h, Tk_Depth(tkwin));
+ values.foreground = WhitePixelOfScreen(Tk_Screen(tkwin));
+ gc = Tk_GetGC(tkwin, GCForeground, &values);
+ if (gc != None) {
+ XFillRectangle(Tk_Display(tkwin), pix, gc, 0, 0, (unsigned int) w, (unsigned int) h);
+ Tk_FreeGC(Tk_Display(tkwin), gc);
+ }
+ Tk_RedrawImage(image, x, y, w, h, pix, 0, 0);
+ Tk_FreePixmap(Tk_Display(tkwin), pix);
+ }
+ else {
+ ximage = XGetImage(Tk_Display(tkwin), pix, 0, 0,
+ (unsigned int) w, (unsigned int) h, AllPlanes, ZPixmap);
+ }
+ if (ximage == NULL) {
+ /* The XGetImage() function is apparently not
+ * implemented on this system. Just ignore it.
+ */
+ return TCL_OK;
+ }
+ result = ZnPostscriptXImage(interp, tkwin, ps_info, ximage, x, y, w, h);
+ XDestroyImage(ximage);
+ }
+
+ return result;
+}
+
+void
+EmitPhotoImageData()
+{
+}
+
+
+/*
+ * TODO gradients, tuiles, reliefs, flêches, clipping.
+ * TODO la fonction DrawText est buggée dans un environnement rotation
+ * l'erreur passe par un max autour de modulo 45°
+ * TODO Bugs de placement sur le texte et les bordures des fields
+ * TODO Problème : Si on utilise les transformations PostScript on
+ * génère un code plus concis et le rendu est potentiellement
+ * plus beau (on utilise les arcs et les beziers natifs) et on
+ * peut générer des dégradés identiques à ceux de zinc mais le
+ * tuilage/stencil, les flêches, l'épaisseur des lignes suivent
+ * la transformation.
+ * TODO Le code gérant les images ne sait pas traiter le canal alpha.
+ * TODO Inclure ici le code de gestion des stipples.
+ * TODO Pour images et stipples le code doit prendre en compte le contexte
+ * X et/ou OpenGL.
+ */
diff --git a/generic/PostScript.h b/generic/PostScript.h
index cca589c..5af987e 100644
--- a/generic/PostScript.h
+++ b/generic/PostScript.h
@@ -23,15 +23,35 @@
#include "List.h"
#include "Types.h"
#include "Geo.h"
+#include "Color.h"
+#include "Image.h"
#include <stdio.h>
#include <X11/Xlib.h>
struct _ZnWInfo;
+struct _ZnItemStruct;
int ZnPostScriptCmd(struct _ZnWInfo *wi, int argc, Tcl_Obj *CONST *args);
-
-
-#endif /* _PostScript_h */
+void ZnFlushPsChan(Tcl_Interp *interp, Tk_PostscriptInfo ps_info);
+int ZnPostscriptOutline(Tcl_Interp *interp, Tk_PostscriptInfo ps_info,
+ Tk_Window tkwin, ZnDim line_width, ZnLineStyle line_style,
+ ZnGradient *line_color, ZnImage line_pattern);
+int ZnPostscriptBitmap(Tcl_Interp *interp, Tk_Window tkwin, Tk_PostscriptInfo ps_info,
+ ZnImage bitmap, ZnReal x, ZnReal y, int width, int height);
+void ZnPostscriptString(Tcl_Interp *interp, char *str, int num_bytes);
+void ZnPostscriptTrace(struct _ZnItemStruct *item, ZnBool enter);
+int ZnPostscriptGradient(Tcl_Interp *interp, Tk_PostscriptInfo ps_info,
+ ZnGradient *gradient, ZnPoint *quad, ZnPoly *poly);
+int ZnPostscriptXImage(Tcl_Interp *interp, Tk_Window tkwin, Tk_PostscriptInfo psInfo,
+ XImage *ximage, int x, int y, int width, int height);
+int ZnPostscriptStipple(Tcl_Interp *interp, Tk_Window tkwin, Tk_PostscriptInfo ps_info,
+ ZnImage bitmap);
+int ZnPostscriptTile(Tcl_Interp *interp, Tk_Window win, Tk_PostscriptInfo ps_info,
+ ZnImage image);
+int ZnPostscriptImage(Tcl_Interp *interp, Tk_Window tkwin, Tk_PostscriptInfo ps_info,
+ ZnImage image, int x, int y, int width, int height);
+
+#endif /* _PostScript_h */
diff --git a/generic/Rectangle.c b/generic/Rectangle.c
index 7cf4f8d..8afb38f 100644
--- a/generic/Rectangle.c
+++ b/generic/Rectangle.c
@@ -753,10 +753,87 @@ Pick(ZnItem item,
*
**********************************************************************************
*/
-static void
-PostScript(ZnItem item,
- ZnBool prepass)
+static int
+PostScript(ZnItem item,
+ ZnBool prepass,
+ ZnBBox *area)
{
+ ZnWInfo *wi = item->wi;
+ RectangleItem rect = (RectangleItem) item;
+ char path[500];
+
+ if (ISCLEAR(rect->flags, FILLED_BIT) && (rect->line_width == 0)) {
+ return TCL_OK;
+ }
+
+ /*
+ * Create the rectangle path.
+ */
+ sprintf(path, "%.15g %.15g moveto %.15g %.15g lineto %.15g %.15g lineto %.15g %.15g lineto closepath\n",
+ rect->dev[0].x, rect->dev[0].y, rect->dev[1].x, rect->dev[1].y,
+ rect->dev[2].x, rect->dev[2].y, rect->dev[3].x, rect->dev[3].y);
+ Tcl_AppendResult(wi->interp, path, NULL);
+
+ /*
+ * Emit code to draw the filled area.
+ */
+ if (ISSET(rect->flags, FILLED_BIT)) {
+ if (rect->line_width) {
+ Tcl_AppendResult(wi->interp, "gsave\n", NULL);
+ }
+ if (!ZnGradientFlat(rect->fill_color)) {
+ if (ZnPostscriptGradient(wi->interp, wi->ps_info, rect->fill_color,
+ rect->grad_geo ? rect->grad_geo : rect->dev, NULL) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ }
+ else if (rect->tile != ZnUnspecifiedImage) {
+ if (!ZnImageIsBitmap(rect->tile)) { /* Fill tiled */
+ if (ZnPostscriptTile(wi->interp, wi->win, wi->ps_info, rect->tile) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ }
+ else { /* Fill stippled */
+ if (Tk_PostscriptColor(wi->interp, wi->ps_info,
+ ZnGetGradientColor(rect->fill_color, 0.0, NULL)) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ Tcl_AppendResult(wi->interp, "clip ", NULL);
+ if (ZnPostscriptStipple(wi->interp, wi->win, wi->ps_info, rect->tile) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ }
+ }
+ else { /* Fill solid */
+ if (Tk_PostscriptColor(wi->interp, wi->ps_info,
+ ZnGetGradientColor(rect->fill_color, 0.0, NULL)) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ Tcl_AppendResult(wi->interp, "fill\n", NULL);
+ }
+ if (rect->line_width) {
+ Tcl_AppendResult(wi->interp, "grestore\n", NULL);
+ }
+ }
+
+ /*
+ * Then emit code code to stroke the outline.
+ */
+ if (rect->line_width) {
+ if (rect->relief != ZN_RELIEF_FLAT) {
+ /* TODO No support yet */
+ }
+ else {
+ Tcl_AppendResult(wi->interp, "0 setlinejoin 2 setlinecap\n", NULL);
+ if (ZnPostscriptOutline(wi->interp, wi->ps_info, wi->win,
+ rect->line_width, rect->line_style,
+ rect->line_color, rect->line_pattern) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ }
+ }
+
+ return TCL_OK;
}
diff --git a/generic/Reticle.c b/generic/Reticle.c
index e9c811c..cebeb98 100644
--- a/generic/Reticle.c
+++ b/generic/Reticle.c
@@ -568,10 +568,12 @@ Coords(ZnItem item,
*
**********************************************************************************
*/
-static void
-PostScript(ZnItem item,
- ZnBool prepass)
+static int
+PostScript(ZnItem item,
+ ZnBool prepass,
+ ZnBBox *area)
{
+ return TCL_OK;
}
diff --git a/generic/Tabular.c b/generic/Tabular.c
index be61e88..c0d9886 100644
--- a/generic/Tabular.c
+++ b/generic/Tabular.c
@@ -399,10 +399,12 @@ Pick(ZnItem item,
*
**********************************************************************************
*/
-static void
-PostScript(ZnItem item,
- ZnBool prepass)
+static int
+PostScript(ZnItem item,
+ ZnBool prepass,
+ ZnBBox *area)
{
+ return ZnFIELD.PostScriptFields(&((TabularItem) item)->field_set, prepass, area);
}
diff --git a/generic/Text.c b/generic/Text.c
index 5bf885f..bc7c843 100644
--- a/generic/Text.c
+++ b/generic/Text.c
@@ -1354,10 +1354,76 @@ Pick(ZnItem item,
*
**********************************************************************************
*/
-static void
-PostScript(ZnItem item,
- ZnBool prepass)
+static int
+PostScript(ZnItem item,
+ ZnBool prepass,
+ ZnBBox *area)
{
+ ZnWInfo *wi = item->wi;
+ TextItem text = (TextItem) item;
+ Tk_FontMetrics fm;
+ TextLineInfo lines, lines_ptr;
+ ZnPoint origin;
+ ZnReal alignment;
+ int i, num_lines;
+ char path[150];
+
+ lines = (TextLineInfo) ZnListArray(text->text_info);
+ num_lines = ZnListSize(text->text_info);
+
+ if (Tk_PostscriptFont(wi->interp, wi->ps_info, text->font) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ if (Tk_PostscriptColor(wi->interp, wi->ps_info,
+ ZnGetGradientColor(text->color, 0.0, NULL)) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ if (text->fill_pattern != ZnUnspecifiedImage) {
+ Tcl_AppendResult(wi->interp, "/StippleText {\n ", NULL);
+ Tk_PostscriptStipple(wi->interp, wi->win, wi->ps_info,
+ ZnImagePixmap(text->fill_pattern, wi->win));
+ Tcl_AppendResult(wi->interp, "} bind def\n", NULL);
+ }
+
+ ComputeTransfoAndOrigin(item, &origin);
+
+ sprintf(path, "/InitialTransform load setmatrix\n"
+ "[%.15g %.15g %.15g %.15g %.15g %.15g] concat\n"
+ "1 -1 scale\n",
+ wi->current_transfo->_[0][0], wi->current_transfo->_[0][1],
+ wi->current_transfo->_[1][0], wi->current_transfo->_[1][1],
+ wi->current_transfo->_[2][0], wi->current_transfo->_[2][1]);
+ Tcl_AppendResult(wi->interp, path, NULL);
+
+ sprintf(path, "%.15g %.15g [\n", origin.x, origin.y);
+ Tcl_AppendResult(wi->interp, path, NULL);
+
+ /*
+ * Emit code to draw the lines.
+ */
+ for (i = 0, lines_ptr = lines; i < num_lines; i++, lines_ptr++) {
+ ZnPostscriptString(wi->interp, lines_ptr->start, lines_ptr->num_bytes);
+ }
+
+ switch (text->alignment) {
+ default:
+ case TK_JUSTIFY_LEFT:
+ alignment = 0;
+ break;
+ case TK_JUSTIFY_CENTER:
+ alignment = 0.5;
+ break;
+ case TK_JUSTIFY_RIGHT:
+ alignment = 1;
+ break;
+ }
+ Tk_GetFontMetrics(text->font, &fm);
+ /* DrawText should not mess with anchors, they are already accounted for */
+ sprintf(path, "] %d %g %g %g %s DrawText\n", fm.linespace, 0.0, 0.0,
+ alignment, (text->fill_pattern == ZnUnspecifiedImage) ? "false" : "true");
+ Tcl_AppendResult(wi->interp, path, NULL);
+
+ return TCL_OK;
}
diff --git a/generic/Track.c b/generic/Track.c
index b1aaf40..63686c4 100644
--- a/generic/Track.c
+++ b/generic/Track.c
@@ -1767,10 +1767,12 @@ Pick(ZnItem item,
*
**********************************************************************************
*/
-static void
-PostScript(ZnItem item,
- ZnBool prepass)
+static int
+PostScript(ZnItem item,
+ ZnBool prepass,
+ ZnBBox *area)
{
+ return TCL_OK;
}
diff --git a/generic/Triangles.c b/generic/Triangles.c
index 4b3b8bb..1565b5b 100644
--- a/generic/Triangles.c
+++ b/generic/Triangles.c
@@ -573,10 +573,62 @@ Pick(ZnItem item,
*
**********************************************************************************
*/
-static void
-PostScript(ZnItem item,
- ZnBool prepass)
+static int
+PostScript(ZnItem item,
+ ZnBool prepass,
+ ZnBBox *area)
{
+ ZnWInfo *wi = item->wi;
+ TrianglesItem tr = (TrianglesItem) item;
+ ZnPoint *points;
+ int i, num_points, last_color_index;
+ int edge;
+ ZnGradient **grads;
+ XColor *color = NULL;
+ double red, green, blue;
+ ZnBBox bbox;
+ char path[150];
+
+ points = tr->dev_points.strips->points;
+ num_points = tr->dev_points.strips->num_points;
+ ZnResetBBox(&bbox);
+ ZnAddPointsToBBox(&bbox, points, num_points);
+
+ grads = ZnListArray(tr->colors);
+ last_color_index = ZnListSize(tr->colors)-1;
+
+ Tcl_AppendResult(wi->interp,
+ "/ShadingDict <<\n /ShadingType 4\n /ColorSpace /DeviceRGB\n",
+ " /DataSource [", NULL);
+ for (i = 0; i < num_points; i++) {
+ if (i <= last_color_index) {
+ color = ZnGetGradientColor(grads[i], 0.0, NULL);
+ }
+ if (i < 3) {
+ edge = 0;
+ }
+ else if (ISCLEAR(tr->flags, FAN_BIT)) {
+ edge = 1;
+ }
+ else {
+ edge = 2;
+ }
+ red = ((double) (color->red >> 8)) / 255.0;
+ green = ((double) (color->green >> 8)) / 255.0;
+ blue = ((double) (color->blue >> 8)) / 255.0;
+
+ sprintf(path, "%d %.15g %.15g %.4g %.4g %.4g ",
+ edge, points[i].x, points[i].y, red, green, blue);
+ Tcl_AppendResult(wi->interp, path, NULL);
+ }
+ Tcl_AppendResult(wi->interp, "]\n>> def\n", NULL);
+ Tcl_AppendResult(wi->interp, "<<\n /PatternType 2\n /Shading ShadingDict\n>>\n", NULL);
+ Tcl_AppendResult(wi->interp, "matrix identmatrix makepattern setpattern\n", NULL);
+ sprintf(path, "%.15g %.15g %.15g %.15g rectfill\n", bbox.orig.x, bbox.orig.y,
+ bbox.corner.x - bbox.orig.x, bbox.corner.y - bbox.orig.y);
+ Tcl_AppendResult(wi->interp, path, NULL);
+
+ return TCL_OK;
}
diff --git a/generic/WidgetInfo.h b/generic/WidgetInfo.h
index 2ef78a8..8483dca 100644
--- a/generic/WidgetInfo.h
+++ b/generic/WidgetInfo.h
@@ -233,16 +233,17 @@ typedef struct _ZnWInfo {
* viewing area past the scroll region. */
Tcl_Obj *region; /* Scroll region option string source of the
* scroll_region above. */
+ Tk_PostscriptInfo ps_info;
/* Perf measurement variables. */
#ifndef _WIN32
ZnChrono this_draw_chrono;
ZnChrono total_draw_chrono;
- void *ps_info;
#endif
int num_items;
int damaged_area_w;
int damaged_area_h;
+ int debug;
} ZnWInfo;
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;
}
diff --git a/generic/tkZinc.c b/generic/tkZinc.c
index c7af899..6e6c87b 100644
--- a/generic/tkZinc.c
+++ b/generic/tkZinc.c
@@ -289,6 +289,7 @@ static Tk_ObjCustomOption gradientOption = {
#define CONFIG_MAP_SYMBOL 1<<15
#define CONFIG_TRACK_SYMBOL 1<<16
#define CONFIG_TILE 1<<17
+#define CONFIG_DEBUG 1<<18
#endif
/*
@@ -400,6 +401,8 @@ static Tk_OptionSpec option_specs[] = {
"1", -1, Tk_Offset(ZnWInfo, confine), 0, NULL, CONFIG_SET_ORIGIN},
{TK_OPTION_CURSOR, "-cursor", "cursor", "Cursor",
"", -1, Tk_Offset(ZnWInfo, cursor), TK_CONFIG_NULL_OK, NULL, 0},
+ {TK_OPTION_INT, "-debug", "debug", "Debug",
+ "0", -1, Tk_Offset(ZnWInfo, debug), 0, NULL, 0},
{TK_OPTION_FONT, "-font", "font", "Font",
"-adobe-helvetica-bold-r-normal--*-120-*-*-*-*-*-*",
-1, Tk_Offset(ZnWInfo, font), 0, NULL, CONFIG_FONT},
@@ -5414,11 +5417,9 @@ WidgetObjCmd(ClientData client_data, /* Information about the widget.
*/
case ZN_W_POSTSCRIPT:
{
-#if 0
if (ZnPostScriptCmd(wi, argc, args) != TCL_OK) {
goto error;
}
-#endif
}
break;
/*