1 
2 /*	$Id: tixUnixXpm.c,v 1.1.1.1 2000/05/17 11:08:54 idiscovery Exp $	*/
3 
4 /*
5  * tixUnixImgXpm.c --
6  *
7  *	Implement the Windows specific function calls for the pixmap
8  *	image type.
9  *
10  * Copyright (c) 1996, Expert Interface Technologies
11  *
12  * See the file "license.terms" for information on usage and redistribution
13  * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
14  *
15  */
16 
17 #include "tkInt.h"
18 #include "tixPort.h"
19 #include "tixUnixInt.h"
20 #include "tixImgXpm.h"
21 
22 typedef struct PixmapData {
23     Pixmap mask;		/* Mask: only display pixmap pixels where
24 				 * there are 1's here. */
25     GC gc;			/* Graphics context for displaying pixmap.
26 				 * None means there was an error while
27 				 * setting up the instance, so it cannot
28 				 * be displayed. */
29 } PixmapData;
30 
31 
32 /*----------------------------------------------------------------------
33  * TixpInitPixmapInstance --
34  *
35  *	Initializes the platform-specific data of a pixmap instance
36  *
37  *----------------------------------------------------------------------
38  */
39 
40 void
TixpInitPixmapInstance(masterPtr,instancePtr)41 TixpInitPixmapInstance(masterPtr, instancePtr)
42     PixmapMaster *masterPtr;	/* Pointer to master for image. */
43     PixmapInstance *instancePtr;/* The pixmap instance. */
44 {
45     PixmapData * dataPtr;
46 
47     dataPtr = (PixmapData *)ckalloc(sizeof(PixmapData));
48     dataPtr->mask = None;
49     dataPtr->gc = None;
50 
51     instancePtr->clientData = (ClientData)dataPtr;
52 }
53 
54 /*----------------------------------------------------------------------
55  * TixpXpmAllocTmpBuffer --
56  *
57  *	Allocate a temporary space to draw the image.
58  *
59  *----------------------------------------------------------------------
60  */
61 
62 void
TixpXpmAllocTmpBuffer(masterPtr,instancePtr,imagePtr,maskPtr)63 TixpXpmAllocTmpBuffer(masterPtr, instancePtr, imagePtr, maskPtr)
64     PixmapMaster * masterPtr;
65     PixmapInstance * instancePtr;
66     XImage ** imagePtr;
67     XImage ** maskPtr;
68 {
69     int pad;
70     XImage * image = NULL, * mask = NULL;
71     Display *display = Tk_Display(instancePtr->tkwin);
72     int depth;
73 
74     depth = Tk_Depth(instancePtr->tkwin);
75 
76     if (depth > 16) {
77 	pad = 32;
78     } else if (depth > 8) {
79 	pad = 16;
80     } else {
81 	pad = 8;
82     }
83 
84     /*
85      * Create the XImage structures to store the temporary image
86      */
87     image = XCreateImage(display,
88 	Tk_Visual(instancePtr->tkwin),
89 	depth, ZPixmap, 0, 0,
90 	masterPtr->size[0], masterPtr->size[1], pad, 0);
91     image->data =
92       (char *)ckalloc(image->bytes_per_line * masterPtr->size[1]);
93 
94     mask  = XCreateImage(display,
95 	Tk_Visual(instancePtr->tkwin),
96 	1, XYPixmap, 0, 0,
97 	masterPtr->size[0], masterPtr->size[1], pad, 0);
98 
99     mask->data =
100       (char *)ckalloc(mask->bytes_per_line  * masterPtr->size[1]);
101 
102     *imagePtr = image;
103     *maskPtr = mask;
104 }
105 
106 void
TixpXpmFreeTmpBuffer(masterPtr,instancePtr,image,mask)107 TixpXpmFreeTmpBuffer(masterPtr, instancePtr, image, mask)
108     PixmapMaster * masterPtr;
109     PixmapInstance * instancePtr;
110     XImage * image;
111     XImage * mask;
112 {
113     if (image) {
114 	ckfree((char*)image->data);
115 	image->data = NULL;
116 	XDestroyImage(image);
117     }
118     if (mask) {
119 	ckfree((char*)mask->data);
120 	mask->data = NULL;
121 	XDestroyImage(mask);
122     }
123 }
124 
125 /*----------------------------------------------------------------------
126  * TixpXpmSetPixel --
127  *
128  *	Sets the pixel at the given (x,y) coordinate to be the given
129  *	color.
130  *----------------------------------------------------------------------
131  */
132 void
TixpXpmSetPixel(instancePtr,image,mask,x,y,colorPtr,isTranspPtr)133 TixpXpmSetPixel(instancePtr, image, mask, x, y, colorPtr, isTranspPtr)
134     PixmapInstance * instancePtr;
135     XImage * image;
136     XImage * mask;
137     int x;
138     int y;
139     XColor * colorPtr;
140     int * isTranspPtr;
141 {
142     if (colorPtr != NULL) {
143 	XPutPixel(image, x, y, colorPtr->pixel);
144 	XPutPixel(mask,  x, y, 1);
145     } else {
146 	XPutPixel(mask,  x, y, 0);
147 	*isTranspPtr = 1;
148     }
149 }
150 
151 /*----------------------------------------------------------------------
152  * TixpXpmRealizePixmap --
153  *
154  *	On Unix: 	Create the pixmap from the buffer.
155  *	On Windows:	Free the mask if there are no transparent pixels.
156  *----------------------------------------------------------------------
157  */
158 
159 void
TixpXpmRealizePixmap(masterPtr,instancePtr,image,mask,isTransp)160 TixpXpmRealizePixmap(masterPtr, instancePtr, image, mask, isTransp)
161     PixmapMaster * masterPtr;
162     PixmapInstance * instancePtr;
163     XImage * image;
164     XImage * mask;
165     int isTransp;
166 {
167     Display *display = Tk_Display(instancePtr->tkwin);
168     int depth = Tk_Depth(instancePtr->tkwin);
169     PixmapData *dataPtr = (PixmapData*)instancePtr->clientData;
170     unsigned int gcMask;
171     XGCValues gcValues;
172     GC gc;
173 
174     instancePtr->pixmap = Tk_GetPixmap(display,
175 	Tk_WindowId(instancePtr->tkwin),
176 	masterPtr->size[0], masterPtr->size[1], depth);
177 
178     gc = Tk_GetGC(instancePtr->tkwin, 0, NULL);
179 
180     XPutImage(display, instancePtr->pixmap,
181 	gc, image, 0, 0, 0, 0, masterPtr->size[0], masterPtr->size[1]);
182 
183     Tk_FreeGC(display, gc);
184 
185     if (isTransp) {
186 	/*
187 	 * There are transparent pixels. We need a mask.
188 	 */
189 	dataPtr->mask = Tk_GetPixmap(display,
190 	    Tk_WindowId(instancePtr->tkwin),
191 	    masterPtr->size[0], masterPtr->size[1], 1);
192 	gc = XCreateGC(display, dataPtr->mask, 0, NULL);
193 	XPutImage(display, dataPtr->mask,
194 	    gc, mask,  0, 0, 0, 0, masterPtr->size[0], masterPtr->size[1]);
195 	XFreeGC(display, gc);
196     } else {
197 	dataPtr->mask = None;
198     }
199 
200     /*
201      * Allocate a GC for drawing this instance (mask is not used if there
202      * is no transparent pixels inside the image).
203      */
204     if (dataPtr->mask != None) {
205 	gcMask = GCGraphicsExposures|GCClipMask;
206     } else {
207 	gcMask = GCGraphicsExposures;
208     }
209     gcValues.graphics_exposures = False;
210     gcValues.clip_mask = dataPtr->mask;
211 
212     gc = Tk_GetGC(instancePtr->tkwin, gcMask, &gcValues);
213     dataPtr->gc = gc;
214 }
215 
216 void
TixpXpmFreeInstanceData(instancePtr,delete,display)217 TixpXpmFreeInstanceData(instancePtr, delete, display)
218     PixmapInstance *instancePtr;/* Pixmap instance. */
219     int delete;			/* Should the instance data structure
220 				 * be deleted as well? */
221     Display *display;		/* Display containing window that used image.*/
222 {
223     PixmapData *dataPtr = (PixmapData*)instancePtr->clientData;
224 
225     if (dataPtr->mask != None) {
226 	Tk_FreePixmap(display, dataPtr->mask);
227 	dataPtr->mask = None;
228     }
229     if (dataPtr->gc != None) {
230 	Tk_FreeGC(display, dataPtr->gc);
231 	dataPtr->gc = None;
232     }
233     if (delete) {
234 	ckfree((char*)dataPtr);
235 	instancePtr->clientData = NULL;
236     }
237 }
238 
239 void
TixpXpmDisplay(clientData,display,drawable,imageX,imageY,width,height,drawableX,drawableY)240 TixpXpmDisplay(clientData, display, drawable, imageX, imageY, width,
241 	height, drawableX, drawableY)
242     ClientData clientData;	/* Pointer to PixmapInstance structure for
243 				 * for instance to be displayed. */
244     Display *display;		/* Display on which to draw image. */
245     Drawable drawable;		/* Pixmap or window in which to draw image. */
246     int imageX, imageY;		/* Upper-left corner of region within image
247 				 * to draw. */
248     int width, height;		/* Dimensions of region within image to draw.*/
249     int drawableX, drawableY;	/* Coordinates within drawable that
250 				 * correspond to imageX and imageY. */
251 {
252     PixmapInstance *instancePtr = (PixmapInstance *) clientData;
253     PixmapData *dataPtr = (PixmapData*)instancePtr->clientData;
254 
255     /*
256      * If there's no graphics context, it means that an error occurred
257      * while creating the image instance so it can't be displayed.
258      */
259     if (dataPtr->gc == None) {
260 	return;
261     }
262 
263     /*
264      * We always use clipping: modify the clip origin within
265      * the graphics context to line up with the image's origin.
266      * Then draw the image and reset the clip origin.
267      */
268     XSetClipOrigin(display, dataPtr->gc, drawableX - imageX,
269 	drawableY - imageY);
270     XCopyArea(display, instancePtr->pixmap, drawable, dataPtr->gc,
271 	imageX, imageY, (unsigned) width, (unsigned) height,
272 	drawableX, drawableY);
273     XSetClipOrigin(display, dataPtr->gc, 0, 0);
274 }
275