1 |
/* $Header$ */ |
2 |
|
3 |
/* |
4 |
* tkCanvBmap.c -- |
5 |
* |
6 |
* This file implements bitmap items for canvas widgets. |
7 |
* |
8 |
* Copyright (c) 1992-1994 The Regents of the University of California. |
9 |
* Copyright (c) 1994-1997 Sun Microsystems, Inc. |
10 |
* |
11 |
* See the file "license.terms" for information on usage and redistribution |
12 |
* of this file, and for a DISCLAIMER OF ALL WARRANTIES. |
13 |
* |
14 |
* RCS: @(#) $Id: tkcanvbmap.c,v 1.1.1.1 2001/06/13 04:56:16 dtashley Exp $ |
15 |
*/ |
16 |
|
17 |
#include <stdio.h> |
18 |
#include "tkInt.h" |
19 |
#include "tkPort.h" |
20 |
#include "tkCanvas.h" |
21 |
|
22 |
/* |
23 |
* The structure below defines the record for each bitmap item. |
24 |
*/ |
25 |
|
26 |
typedef struct BitmapItem { |
27 |
Tk_Item header; /* Generic stuff that's the same for all |
28 |
* types. MUST BE FIRST IN STRUCTURE. */ |
29 |
double x, y; /* Coordinates of positioning point for |
30 |
* bitmap. */ |
31 |
Tk_Anchor anchor; /* Where to anchor bitmap relative to |
32 |
* (x,y). */ |
33 |
Pixmap bitmap; /* Bitmap to display in window. */ |
34 |
Pixmap activeBitmap; /* Bitmap to display in window. */ |
35 |
Pixmap disabledBitmap; /* Bitmap to display in window. */ |
36 |
XColor *fgColor; /* Foreground color to use for bitmap. */ |
37 |
XColor *activeFgColor; /* Foreground color to use for bitmap. */ |
38 |
XColor *disabledFgColor; /* Foreground color to use for bitmap. */ |
39 |
XColor *bgColor; /* Background color to use for bitmap. */ |
40 |
XColor *activeBgColor; /* Background color to use for bitmap. */ |
41 |
XColor *disabledBgColor; /* Background color to use for bitmap. */ |
42 |
GC gc; /* Graphics context to use for drawing |
43 |
* bitmap on screen. */ |
44 |
} BitmapItem; |
45 |
|
46 |
/* |
47 |
* Information used for parsing configuration specs: |
48 |
*/ |
49 |
|
50 |
static Tk_CustomOption stateOption = { |
51 |
(Tk_OptionParseProc *) TkStateParseProc, |
52 |
TkStatePrintProc, (ClientData) 2 |
53 |
}; |
54 |
static Tk_CustomOption tagsOption = { |
55 |
(Tk_OptionParseProc *) Tk_CanvasTagsParseProc, |
56 |
Tk_CanvasTagsPrintProc, (ClientData) NULL |
57 |
}; |
58 |
|
59 |
static Tk_ConfigSpec configSpecs[] = { |
60 |
{TK_CONFIG_COLOR, "-activebackground", (char *) NULL, (char *) NULL, |
61 |
(char *) NULL, Tk_Offset(BitmapItem, activeBgColor), TK_CONFIG_NULL_OK}, |
62 |
{TK_CONFIG_BITMAP, "-activebitmap", (char *) NULL, (char *) NULL, |
63 |
(char *) NULL, Tk_Offset(BitmapItem, activeBitmap), TK_CONFIG_NULL_OK}, |
64 |
{TK_CONFIG_COLOR, "-activeforeground", (char *) NULL, (char *) NULL, |
65 |
(char *) NULL, Tk_Offset(BitmapItem, activeFgColor), TK_CONFIG_NULL_OK}, |
66 |
{TK_CONFIG_ANCHOR, "-anchor", (char *) NULL, (char *) NULL, |
67 |
"center", Tk_Offset(BitmapItem, anchor), TK_CONFIG_DONT_SET_DEFAULT}, |
68 |
{TK_CONFIG_COLOR, "-background", (char *) NULL, (char *) NULL, |
69 |
(char *) NULL, Tk_Offset(BitmapItem, bgColor), TK_CONFIG_NULL_OK}, |
70 |
{TK_CONFIG_BITMAP, "-bitmap", (char *) NULL, (char *) NULL, |
71 |
(char *) NULL, Tk_Offset(BitmapItem, bitmap), TK_CONFIG_NULL_OK}, |
72 |
{TK_CONFIG_COLOR, "-disabledbackground", (char *) NULL, (char *) NULL, |
73 |
(char *) NULL, Tk_Offset(BitmapItem, disabledBgColor), |
74 |
TK_CONFIG_NULL_OK}, |
75 |
{TK_CONFIG_BITMAP, "-disabledbitmap", (char *) NULL, (char *) NULL, |
76 |
(char *) NULL, Tk_Offset(BitmapItem, disabledBitmap), |
77 |
TK_CONFIG_NULL_OK}, |
78 |
{TK_CONFIG_COLOR, "-disabledforeground", (char *) NULL, (char *) NULL, |
79 |
(char *) NULL, Tk_Offset(BitmapItem, disabledFgColor), |
80 |
TK_CONFIG_NULL_OK}, |
81 |
{TK_CONFIG_COLOR, "-foreground", (char *) NULL, (char *) NULL, |
82 |
"black", Tk_Offset(BitmapItem, fgColor), 0}, |
83 |
{TK_CONFIG_CUSTOM, "-state", (char *) NULL, (char *) NULL, |
84 |
(char *) NULL, Tk_Offset(Tk_Item, state), TK_CONFIG_NULL_OK, |
85 |
&stateOption}, |
86 |
{TK_CONFIG_CUSTOM, "-tags", (char *) NULL, (char *) NULL, |
87 |
(char *) NULL, 0, TK_CONFIG_NULL_OK, &tagsOption}, |
88 |
{TK_CONFIG_END, (char *) NULL, (char *) NULL, (char *) NULL, |
89 |
(char *) NULL, 0, 0} |
90 |
}; |
91 |
|
92 |
/* |
93 |
* Prototypes for procedures defined in this file: |
94 |
*/ |
95 |
|
96 |
static int BitmapCoords _ANSI_ARGS_((Tcl_Interp *interp, |
97 |
Tk_Canvas canvas, Tk_Item *itemPtr, int argc, |
98 |
Tcl_Obj *CONST argv[])); |
99 |
static int BitmapToArea _ANSI_ARGS_((Tk_Canvas canvas, |
100 |
Tk_Item *itemPtr, double *rectPtr)); |
101 |
static double BitmapToPoint _ANSI_ARGS_((Tk_Canvas canvas, |
102 |
Tk_Item *itemPtr, double *coordPtr)); |
103 |
static int BitmapToPostscript _ANSI_ARGS_((Tcl_Interp *interp, |
104 |
Tk_Canvas canvas, Tk_Item *itemPtr, int prepass)); |
105 |
static void ComputeBitmapBbox _ANSI_ARGS_((Tk_Canvas canvas, |
106 |
BitmapItem *bmapPtr)); |
107 |
static int ConfigureBitmap _ANSI_ARGS_((Tcl_Interp *interp, |
108 |
Tk_Canvas canvas, Tk_Item *itemPtr, int argc, |
109 |
Tcl_Obj *CONST argv[], int flags)); |
110 |
static int CreateBitmap _ANSI_ARGS_((Tcl_Interp *interp, |
111 |
Tk_Canvas canvas, struct Tk_Item *itemPtr, |
112 |
int argc, Tcl_Obj *CONST argv[])); |
113 |
static void DeleteBitmap _ANSI_ARGS_((Tk_Canvas canvas, |
114 |
Tk_Item *itemPtr, Display *display)); |
115 |
static void DisplayBitmap _ANSI_ARGS_((Tk_Canvas canvas, |
116 |
Tk_Item *itemPtr, Display *display, Drawable dst, |
117 |
int x, int y, int width, int height)); |
118 |
static void ScaleBitmap _ANSI_ARGS_((Tk_Canvas canvas, |
119 |
Tk_Item *itemPtr, double originX, double originY, |
120 |
double scaleX, double scaleY)); |
121 |
static void TranslateBitmap _ANSI_ARGS_((Tk_Canvas canvas, |
122 |
Tk_Item *itemPtr, double deltaX, double deltaY)); |
123 |
|
124 |
/* |
125 |
* The structures below defines the bitmap item type in terms of |
126 |
* procedures that can be invoked by generic item code. |
127 |
*/ |
128 |
|
129 |
Tk_ItemType tkBitmapType = { |
130 |
"bitmap", /* name */ |
131 |
sizeof(BitmapItem), /* itemSize */ |
132 |
CreateBitmap, /* createProc */ |
133 |
configSpecs, /* configSpecs */ |
134 |
ConfigureBitmap, /* configureProc */ |
135 |
BitmapCoords, /* coordProc */ |
136 |
DeleteBitmap, /* deleteProc */ |
137 |
DisplayBitmap, /* displayProc */ |
138 |
TK_CONFIG_OBJS, /* flags */ |
139 |
BitmapToPoint, /* pointProc */ |
140 |
BitmapToArea, /* areaProc */ |
141 |
BitmapToPostscript, /* postscriptProc */ |
142 |
ScaleBitmap, /* scaleProc */ |
143 |
TranslateBitmap, /* translateProc */ |
144 |
(Tk_ItemIndexProc *) NULL, /* indexProc */ |
145 |
(Tk_ItemCursorProc *) NULL, /* icursorProc */ |
146 |
(Tk_ItemSelectionProc *) NULL, /* selectionProc */ |
147 |
(Tk_ItemInsertProc *) NULL, /* insertProc */ |
148 |
(Tk_ItemDCharsProc *) NULL, /* dTextProc */ |
149 |
(Tk_ItemType *) NULL, /* nextPtr */ |
150 |
}; |
151 |
|
152 |
/* |
153 |
*-------------------------------------------------------------- |
154 |
* |
155 |
* CreateBitmap -- |
156 |
* |
157 |
* This procedure is invoked to create a new bitmap |
158 |
* item in a canvas. |
159 |
* |
160 |
* Results: |
161 |
* A standard Tcl return value. If an error occurred in |
162 |
* creating the item, then an error message is left in |
163 |
* the interp's result; in this case itemPtr is left uninitialized, |
164 |
* so it can be safely freed by the caller. |
165 |
* |
166 |
* Side effects: |
167 |
* A new bitmap item is created. |
168 |
* |
169 |
*-------------------------------------------------------------- |
170 |
*/ |
171 |
|
172 |
static int |
173 |
CreateBitmap(interp, canvas, itemPtr, argc, argv) |
174 |
Tcl_Interp *interp; /* Interpreter for error reporting. */ |
175 |
Tk_Canvas canvas; /* Canvas to hold new item. */ |
176 |
Tk_Item *itemPtr; /* Record to hold new item; header |
177 |
* has been initialized by caller. */ |
178 |
int argc; /* Number of arguments in argv. */ |
179 |
Tcl_Obj *CONST argv[]; /* Arguments describing rectangle. */ |
180 |
{ |
181 |
BitmapItem *bmapPtr = (BitmapItem *) itemPtr; |
182 |
int i; |
183 |
|
184 |
if (argc==1) { |
185 |
i = 1; |
186 |
} else { |
187 |
char *arg = Tcl_GetStringFromObj(argv[1], NULL); |
188 |
if (((argc>1) && (arg[0] == '-') |
189 |
&& (arg[1] >= 'a') && (arg[1] <= 'z'))) { |
190 |
i = 1; |
191 |
} else { |
192 |
i = 2; |
193 |
} |
194 |
} |
195 |
|
196 |
if (argc < i) { |
197 |
Tcl_AppendResult(interp, "wrong # args: should be \"", |
198 |
Tk_PathName(Tk_CanvasTkwin(canvas)), " create ", |
199 |
itemPtr->typePtr->name, " x y ?options?\"", |
200 |
(char *) NULL); |
201 |
return TCL_ERROR; |
202 |
} |
203 |
|
204 |
/* |
205 |
* Initialize item's record. |
206 |
*/ |
207 |
|
208 |
bmapPtr->anchor = TK_ANCHOR_CENTER; |
209 |
bmapPtr->bitmap = None; |
210 |
bmapPtr->activeBitmap = None; |
211 |
bmapPtr->disabledBitmap = None; |
212 |
bmapPtr->fgColor = NULL; |
213 |
bmapPtr->activeFgColor = NULL; |
214 |
bmapPtr->disabledFgColor = NULL; |
215 |
bmapPtr->bgColor = NULL; |
216 |
bmapPtr->activeBgColor = NULL; |
217 |
bmapPtr->disabledBgColor = NULL; |
218 |
bmapPtr->gc = None; |
219 |
|
220 |
/* |
221 |
* Process the arguments to fill in the item record. |
222 |
*/ |
223 |
|
224 |
if ((BitmapCoords(interp, canvas, itemPtr, i, argv) != TCL_OK)) { |
225 |
goto error; |
226 |
} |
227 |
if (ConfigureBitmap(interp, canvas, itemPtr, argc-i, argv+i, 0) == TCL_OK) { |
228 |
return TCL_OK; |
229 |
} |
230 |
|
231 |
error: |
232 |
DeleteBitmap(canvas, itemPtr, Tk_Display(Tk_CanvasTkwin(canvas))); |
233 |
return TCL_ERROR; |
234 |
} |
235 |
|
236 |
/* |
237 |
*-------------------------------------------------------------- |
238 |
* |
239 |
* BitmapCoords -- |
240 |
* |
241 |
* This procedure is invoked to process the "coords" widget |
242 |
* command on bitmap items. See the user documentation for |
243 |
* details on what it does. |
244 |
* |
245 |
* Results: |
246 |
* Returns TCL_OK or TCL_ERROR, and sets the interp's result. |
247 |
* |
248 |
* Side effects: |
249 |
* The coordinates for the given item may be changed. |
250 |
* |
251 |
*-------------------------------------------------------------- |
252 |
*/ |
253 |
|
254 |
static int |
255 |
BitmapCoords(interp, canvas, itemPtr, argc, argv) |
256 |
Tcl_Interp *interp; /* Used for error reporting. */ |
257 |
Tk_Canvas canvas; /* Canvas containing item. */ |
258 |
Tk_Item *itemPtr; /* Item whose coordinates are to be |
259 |
* read or modified. */ |
260 |
int argc; /* Number of coordinates supplied in |
261 |
* argv. */ |
262 |
Tcl_Obj *CONST argv[]; /* Array of coordinates: x1, y1, |
263 |
* x2, y2, ... */ |
264 |
{ |
265 |
BitmapItem *bmapPtr = (BitmapItem *) itemPtr; |
266 |
|
267 |
if (argc == 0) { |
268 |
Tcl_Obj *obj = Tcl_NewObj(); |
269 |
Tcl_Obj *subobj = Tcl_NewDoubleObj(bmapPtr->x); |
270 |
Tcl_ListObjAppendElement(interp, obj, subobj); |
271 |
subobj = Tcl_NewDoubleObj(bmapPtr->y); |
272 |
Tcl_ListObjAppendElement(interp, obj, subobj); |
273 |
Tcl_SetObjResult(interp, obj); |
274 |
} else if (argc <3) { |
275 |
if (argc==1) { |
276 |
if (Tcl_ListObjGetElements(interp, argv[0], &argc, |
277 |
(Tcl_Obj ***) &argv) != TCL_OK) { |
278 |
return TCL_ERROR; |
279 |
} else if (argc != 2) { |
280 |
char buf[64 + TCL_INTEGER_SPACE]; |
281 |
|
282 |
sprintf(buf, "wrong # coordinates: expected 2, got %d", argc); |
283 |
Tcl_SetResult(interp, buf, TCL_VOLATILE); |
284 |
return TCL_ERROR; |
285 |
} |
286 |
} |
287 |
if ((Tk_CanvasGetCoordFromObj(interp, canvas, argv[0], &bmapPtr->x) != TCL_OK) |
288 |
|| (Tk_CanvasGetCoordFromObj(interp, canvas, argv[1], &bmapPtr->y) |
289 |
!= TCL_OK)) { |
290 |
return TCL_ERROR; |
291 |
} |
292 |
ComputeBitmapBbox(canvas, bmapPtr); |
293 |
} else { |
294 |
char buf[64 + TCL_INTEGER_SPACE]; |
295 |
|
296 |
sprintf(buf, "wrong # coordinates: expected 0 or 2, got %d", argc); |
297 |
Tcl_SetResult(interp, buf, TCL_VOLATILE); |
298 |
return TCL_ERROR; |
299 |
} |
300 |
return TCL_OK; |
301 |
} |
302 |
|
303 |
/* |
304 |
*-------------------------------------------------------------- |
305 |
* |
306 |
* ConfigureBitmap -- |
307 |
* |
308 |
* This procedure is invoked to configure various aspects |
309 |
* of a bitmap item, such as its anchor position. |
310 |
* |
311 |
* Results: |
312 |
* A standard Tcl result code. If an error occurs, then |
313 |
* an error message is left in the interp's result. |
314 |
* |
315 |
* Side effects: |
316 |
* Configuration information may be set for itemPtr. |
317 |
* |
318 |
*-------------------------------------------------------------- |
319 |
*/ |
320 |
|
321 |
static int |
322 |
ConfigureBitmap(interp, canvas, itemPtr, argc, argv, flags) |
323 |
Tcl_Interp *interp; /* Used for error reporting. */ |
324 |
Tk_Canvas canvas; /* Canvas containing itemPtr. */ |
325 |
Tk_Item *itemPtr; /* Bitmap item to reconfigure. */ |
326 |
int argc; /* Number of elements in argv. */ |
327 |
Tcl_Obj *CONST argv[]; /* Arguments describing things to configure. */ |
328 |
int flags; /* Flags to pass to Tk_ConfigureWidget. */ |
329 |
{ |
330 |
BitmapItem *bmapPtr = (BitmapItem *) itemPtr; |
331 |
XGCValues gcValues; |
332 |
GC newGC; |
333 |
Tk_Window tkwin; |
334 |
unsigned long mask; |
335 |
XColor *fgColor; |
336 |
XColor *bgColor; |
337 |
Pixmap bitmap; |
338 |
Tk_State state; |
339 |
|
340 |
tkwin = Tk_CanvasTkwin(canvas); |
341 |
if (Tk_ConfigureWidget(interp, tkwin, configSpecs, argc, (char **) argv, |
342 |
(char *) bmapPtr, flags|TK_CONFIG_OBJS) != TCL_OK) { |
343 |
return TCL_ERROR; |
344 |
} |
345 |
|
346 |
/* |
347 |
* A few of the options require additional processing, such as those |
348 |
* that determine the graphics context. |
349 |
*/ |
350 |
|
351 |
state = itemPtr->state; |
352 |
|
353 |
if (bmapPtr->activeFgColor!=NULL || |
354 |
bmapPtr->activeBgColor!=NULL || |
355 |
bmapPtr->activeBitmap!=None) { |
356 |
itemPtr->redraw_flags |= TK_ITEM_STATE_DEPENDANT; |
357 |
} else { |
358 |
itemPtr->redraw_flags &= ~TK_ITEM_STATE_DEPENDANT; |
359 |
} |
360 |
|
361 |
if(state == TK_STATE_NULL) { |
362 |
state = ((TkCanvas *)canvas)->canvas_state; |
363 |
} |
364 |
if (state==TK_STATE_HIDDEN) { |
365 |
ComputeBitmapBbox(canvas, bmapPtr); |
366 |
return TCL_OK; |
367 |
} |
368 |
fgColor = bmapPtr->fgColor; |
369 |
bgColor = bmapPtr->bgColor; |
370 |
bitmap = bmapPtr->bitmap; |
371 |
if (((TkCanvas *)canvas)->currentItemPtr == itemPtr) { |
372 |
if (bmapPtr->activeFgColor!=NULL) { |
373 |
fgColor = bmapPtr->activeFgColor; |
374 |
} |
375 |
if (bmapPtr->activeBgColor!=NULL) { |
376 |
bgColor = bmapPtr->activeBgColor; |
377 |
} |
378 |
if (bmapPtr->activeBitmap!=None) { |
379 |
bitmap = bmapPtr->activeBitmap; |
380 |
} |
381 |
} else if (state==TK_STATE_DISABLED) { |
382 |
if (bmapPtr->disabledFgColor!=NULL) { |
383 |
fgColor = bmapPtr->disabledFgColor; |
384 |
} |
385 |
if (bmapPtr->disabledBgColor!=NULL) { |
386 |
bgColor = bmapPtr->disabledBgColor; |
387 |
} |
388 |
if (bmapPtr->disabledBitmap!=None) { |
389 |
bitmap = bmapPtr->disabledBitmap; |
390 |
} |
391 |
} |
392 |
|
393 |
if (state==TK_STATE_DISABLED || bitmap == None) { |
394 |
ComputeBitmapBbox(canvas, bmapPtr); |
395 |
return TCL_OK; |
396 |
} |
397 |
|
398 |
gcValues.foreground = fgColor->pixel; |
399 |
mask = GCForeground; |
400 |
if (bgColor != NULL) { |
401 |
gcValues.background = bgColor->pixel; |
402 |
mask |= GCBackground; |
403 |
} else { |
404 |
gcValues.clip_mask = bitmap; |
405 |
mask |= GCClipMask; |
406 |
} |
407 |
if (bitmap == None) { |
408 |
newGC = None; |
409 |
} else { |
410 |
newGC = Tk_GetGC(tkwin, mask, &gcValues); |
411 |
} |
412 |
if (bmapPtr->gc != None) { |
413 |
Tk_FreeGC(Tk_Display(tkwin), bmapPtr->gc); |
414 |
} |
415 |
bmapPtr->gc = newGC; |
416 |
|
417 |
ComputeBitmapBbox(canvas, bmapPtr); |
418 |
|
419 |
return TCL_OK; |
420 |
} |
421 |
|
422 |
/* |
423 |
*-------------------------------------------------------------- |
424 |
* |
425 |
* DeleteBitmap -- |
426 |
* |
427 |
* This procedure is called to clean up the data structure |
428 |
* associated with a bitmap item. |
429 |
* |
430 |
* Results: |
431 |
* None. |
432 |
* |
433 |
* Side effects: |
434 |
* Resources associated with itemPtr are released. |
435 |
* |
436 |
*-------------------------------------------------------------- |
437 |
*/ |
438 |
|
439 |
static void |
440 |
DeleteBitmap(canvas, itemPtr, display) |
441 |
Tk_Canvas canvas; /* Info about overall canvas widget. */ |
442 |
Tk_Item *itemPtr; /* Item that is being deleted. */ |
443 |
Display *display; /* Display containing window for |
444 |
* canvas. */ |
445 |
{ |
446 |
BitmapItem *bmapPtr = (BitmapItem *) itemPtr; |
447 |
|
448 |
if (bmapPtr->bitmap != None) { |
449 |
Tk_FreeBitmap(display, bmapPtr->bitmap); |
450 |
} |
451 |
if (bmapPtr->activeBitmap != None) { |
452 |
Tk_FreeBitmap(display, bmapPtr->activeBitmap); |
453 |
} |
454 |
if (bmapPtr->disabledBitmap != None) { |
455 |
Tk_FreeBitmap(display, bmapPtr->disabledBitmap); |
456 |
} |
457 |
if (bmapPtr->fgColor != NULL) { |
458 |
Tk_FreeColor(bmapPtr->fgColor); |
459 |
} |
460 |
if (bmapPtr->activeFgColor != NULL) { |
461 |
Tk_FreeColor(bmapPtr->activeFgColor); |
462 |
} |
463 |
if (bmapPtr->disabledFgColor != NULL) { |
464 |
Tk_FreeColor(bmapPtr->disabledFgColor); |
465 |
} |
466 |
if (bmapPtr->bgColor != NULL) { |
467 |
Tk_FreeColor(bmapPtr->bgColor); |
468 |
} |
469 |
if (bmapPtr->activeBgColor != NULL) { |
470 |
Tk_FreeColor(bmapPtr->activeBgColor); |
471 |
} |
472 |
if (bmapPtr->disabledBgColor != NULL) { |
473 |
Tk_FreeColor(bmapPtr->disabledBgColor); |
474 |
} |
475 |
if (bmapPtr->gc != NULL) { |
476 |
Tk_FreeGC(display, bmapPtr->gc); |
477 |
} |
478 |
} |
479 |
|
480 |
/* |
481 |
*-------------------------------------------------------------- |
482 |
* |
483 |
* ComputeBitmapBbox -- |
484 |
* |
485 |
* This procedure is invoked to compute the bounding box of |
486 |
* all the pixels that may be drawn as part of a bitmap item. |
487 |
* This procedure is where the child bitmap's placement is |
488 |
* computed. |
489 |
* |
490 |
* Results: |
491 |
* None. |
492 |
* |
493 |
* Side effects: |
494 |
* The fields x1, y1, x2, and y2 are updated in the header |
495 |
* for itemPtr. |
496 |
* |
497 |
*-------------------------------------------------------------- |
498 |
*/ |
499 |
|
500 |
/* ARGSUSED */ |
501 |
static void |
502 |
ComputeBitmapBbox(canvas, bmapPtr) |
503 |
Tk_Canvas canvas; /* Canvas that contains item. */ |
504 |
BitmapItem *bmapPtr; /* Item whose bbox is to be |
505 |
* recomputed. */ |
506 |
{ |
507 |
int width, height; |
508 |
int x, y; |
509 |
Pixmap bitmap; |
510 |
Tk_State state = bmapPtr->header.state; |
511 |
|
512 |
if(state == TK_STATE_NULL) { |
513 |
state = ((TkCanvas *)canvas)->canvas_state; |
514 |
} |
515 |
bitmap = bmapPtr->bitmap; |
516 |
if (((TkCanvas *)canvas)->currentItemPtr == (Tk_Item *)bmapPtr) { |
517 |
if (bmapPtr->activeBitmap!=None) { |
518 |
bitmap = bmapPtr->activeBitmap; |
519 |
} |
520 |
} else if (state==TK_STATE_DISABLED) { |
521 |
if (bmapPtr->disabledBitmap!=None) { |
522 |
bitmap = bmapPtr->disabledBitmap; |
523 |
} |
524 |
} |
525 |
|
526 |
x = (int) (bmapPtr->x + ((bmapPtr->x >= 0) ? 0.5 : - 0.5)); |
527 |
y = (int) (bmapPtr->y + ((bmapPtr->y >= 0) ? 0.5 : - 0.5)); |
528 |
|
529 |
if (state==TK_STATE_HIDDEN || bitmap == None) { |
530 |
bmapPtr->header.x1 = bmapPtr->header.x2 = x; |
531 |
bmapPtr->header.y1 = bmapPtr->header.y2 = y; |
532 |
return; |
533 |
} |
534 |
|
535 |
/* |
536 |
* Compute location and size of bitmap, using anchor information. |
537 |
*/ |
538 |
|
539 |
Tk_SizeOfBitmap(Tk_Display(Tk_CanvasTkwin(canvas)), bmapPtr->bitmap, |
540 |
&width, &height); |
541 |
switch (bmapPtr->anchor) { |
542 |
case TK_ANCHOR_N: |
543 |
x -= width/2; |
544 |
break; |
545 |
case TK_ANCHOR_NE: |
546 |
x -= width; |
547 |
break; |
548 |
case TK_ANCHOR_E: |
549 |
x -= width; |
550 |
y -= height/2; |
551 |
break; |
552 |
case TK_ANCHOR_SE: |
553 |
x -= width; |
554 |
y -= height; |
555 |
break; |
556 |
case TK_ANCHOR_S: |
557 |
x -= width/2; |
558 |
y -= height; |
559 |
break; |
560 |
case TK_ANCHOR_SW: |
561 |
y -= height; |
562 |
break; |
563 |
case TK_ANCHOR_W: |
564 |
y -= height/2; |
565 |
break; |
566 |
case TK_ANCHOR_NW: |
567 |
break; |
568 |
case TK_ANCHOR_CENTER: |
569 |
x -= width/2; |
570 |
y -= height/2; |
571 |
break; |
572 |
} |
573 |
|
574 |
/* |
575 |
* Store the information in the item header. |
576 |
*/ |
577 |
|
578 |
bmapPtr->header.x1 = x; |
579 |
bmapPtr->header.y1 = y; |
580 |
bmapPtr->header.x2 = x + width; |
581 |
bmapPtr->header.y2 = y + height; |
582 |
} |
583 |
|
584 |
/* |
585 |
*-------------------------------------------------------------- |
586 |
* |
587 |
* DisplayBitmap -- |
588 |
* |
589 |
* This procedure is invoked to draw a bitmap item in a given |
590 |
* drawable. |
591 |
* |
592 |
* Results: |
593 |
* None. |
594 |
* |
595 |
* Side effects: |
596 |
* ItemPtr is drawn in drawable using the transformation |
597 |
* information in canvas. |
598 |
* |
599 |
*-------------------------------------------------------------- |
600 |
*/ |
601 |
|
602 |
static void |
603 |
DisplayBitmap(canvas, itemPtr, display, drawable, x, y, width, height) |
604 |
Tk_Canvas canvas; /* Canvas that contains item. */ |
605 |
Tk_Item *itemPtr; /* Item to be displayed. */ |
606 |
Display *display; /* Display on which to draw item. */ |
607 |
Drawable drawable; /* Pixmap or window in which to draw |
608 |
* item. */ |
609 |
int x, y, width, height; /* Describes region of canvas that |
610 |
* must be redisplayed (not used). */ |
611 |
{ |
612 |
BitmapItem *bmapPtr = (BitmapItem *) itemPtr; |
613 |
int bmapX, bmapY, bmapWidth, bmapHeight; |
614 |
short drawableX, drawableY; |
615 |
XColor *fgColor; |
616 |
XColor *bgColor; |
617 |
Pixmap bitmap; |
618 |
Tk_State state = itemPtr->state; |
619 |
|
620 |
/* |
621 |
* If the area being displayed doesn't cover the whole bitmap, |
622 |
* then only redisplay the part of the bitmap that needs |
623 |
* redisplay. |
624 |
*/ |
625 |
|
626 |
if(state == TK_STATE_NULL) { |
627 |
state = ((TkCanvas *)canvas)->canvas_state; |
628 |
} |
629 |
fgColor = bmapPtr->fgColor; |
630 |
bgColor = bmapPtr->bgColor; |
631 |
bitmap = bmapPtr->bitmap; |
632 |
if (((TkCanvas *)canvas)->currentItemPtr == itemPtr) { |
633 |
if (bmapPtr->activeFgColor!=NULL) { |
634 |
fgColor = bmapPtr->activeFgColor; |
635 |
} |
636 |
if (bmapPtr->activeBgColor!=NULL) { |
637 |
bgColor = bmapPtr->activeBgColor; |
638 |
} |
639 |
if (bmapPtr->activeBitmap!=None) { |
640 |
bitmap = bmapPtr->activeBitmap; |
641 |
} |
642 |
} else if (state==TK_STATE_DISABLED) { |
643 |
if (bmapPtr->disabledFgColor!=NULL) { |
644 |
fgColor = bmapPtr->disabledFgColor; |
645 |
} |
646 |
if (bmapPtr->disabledBgColor!=NULL) { |
647 |
bgColor = bmapPtr->disabledBgColor; |
648 |
} |
649 |
if (bmapPtr->disabledBitmap!=None) { |
650 |
bitmap = bmapPtr->disabledBitmap; |
651 |
} |
652 |
} |
653 |
|
654 |
if (bitmap != None) { |
655 |
if (x > bmapPtr->header.x1) { |
656 |
bmapX = x - bmapPtr->header.x1; |
657 |
bmapWidth = bmapPtr->header.x2 - x; |
658 |
} else { |
659 |
bmapX = 0; |
660 |
if ((x+width) < bmapPtr->header.x2) { |
661 |
bmapWidth = x + width - bmapPtr->header.x1; |
662 |
} else { |
663 |
bmapWidth = bmapPtr->header.x2 - bmapPtr->header.x1; |
664 |
} |
665 |
} |
666 |
if (y > bmapPtr->header.y1) { |
667 |
bmapY = y - bmapPtr->header.y1; |
668 |
bmapHeight = bmapPtr->header.y2 - y; |
669 |
} else { |
670 |
bmapY = 0; |
671 |
if ((y+height) < bmapPtr->header.y2) { |
672 |
bmapHeight = y + height - bmapPtr->header.y1; |
673 |
} else { |
674 |
bmapHeight = bmapPtr->header.y2 - bmapPtr->header.y1; |
675 |
} |
676 |
} |
677 |
Tk_CanvasDrawableCoords(canvas, |
678 |
(double) (bmapPtr->header.x1 + bmapX), |
679 |
(double) (bmapPtr->header.y1 + bmapY), |
680 |
&drawableX, &drawableY); |
681 |
|
682 |
/* |
683 |
* Must modify the mask origin within the graphics context |
684 |
* to line up with the bitmap's origin (in order to make |
685 |
* bitmaps with "-background {}" work right). |
686 |
*/ |
687 |
|
688 |
XSetClipOrigin(display, bmapPtr->gc, drawableX - bmapX, |
689 |
drawableY - bmapY); |
690 |
XCopyPlane(display, bitmap, drawable, |
691 |
bmapPtr->gc, bmapX, bmapY, (unsigned int) bmapWidth, |
692 |
(unsigned int) bmapHeight, drawableX, drawableY, 1); |
693 |
XSetClipOrigin(display, bmapPtr->gc, 0, 0); |
694 |
} |
695 |
} |
696 |
|
697 |
/* |
698 |
*-------------------------------------------------------------- |
699 |
* |
700 |
* BitmapToPoint -- |
701 |
* |
702 |
* Computes the distance from a given point to a given |
703 |
* rectangle, in canvas units. |
704 |
* |
705 |
* Results: |
706 |
* The return value is 0 if the point whose x and y coordinates |
707 |
* are coordPtr[0] and coordPtr[1] is inside the bitmap. If the |
708 |
* point isn't inside the bitmap then the return value is the |
709 |
* distance from the point to the bitmap. |
710 |
* |
711 |
* Side effects: |
712 |
* None. |
713 |
* |
714 |
*-------------------------------------------------------------- |
715 |
*/ |
716 |
|
717 |
/* ARGSUSED */ |
718 |
static double |
719 |
BitmapToPoint(canvas, itemPtr, coordPtr) |
720 |
Tk_Canvas canvas; /* Canvas containing item. */ |
721 |
Tk_Item *itemPtr; /* Item to check against point. */ |
722 |
double *coordPtr; /* Pointer to x and y coordinates. */ |
723 |
{ |
724 |
BitmapItem *bmapPtr = (BitmapItem *) itemPtr; |
725 |
double x1, x2, y1, y2, xDiff, yDiff; |
726 |
|
727 |
x1 = bmapPtr->header.x1; |
728 |
y1 = bmapPtr->header.y1; |
729 |
x2 = bmapPtr->header.x2; |
730 |
y2 = bmapPtr->header.y2; |
731 |
|
732 |
/* |
733 |
* Point is outside rectangle. |
734 |
*/ |
735 |
|
736 |
if (coordPtr[0] < x1) { |
737 |
xDiff = x1 - coordPtr[0]; |
738 |
} else if (coordPtr[0] > x2) { |
739 |
xDiff = coordPtr[0] - x2; |
740 |
} else { |
741 |
xDiff = 0; |
742 |
} |
743 |
|
744 |
if (coordPtr[1] < y1) { |
745 |
yDiff = y1 - coordPtr[1]; |
746 |
} else if (coordPtr[1] > y2) { |
747 |
yDiff = coordPtr[1] - y2; |
748 |
} else { |
749 |
yDiff = 0; |
750 |
} |
751 |
|
752 |
return hypot(xDiff, yDiff); |
753 |
} |
754 |
|
755 |
/* |
756 |
*-------------------------------------------------------------- |
757 |
* |
758 |
* BitmapToArea -- |
759 |
* |
760 |
* This procedure is called to determine whether an item |
761 |
* lies entirely inside, entirely outside, or overlapping |
762 |
* a given rectangle. |
763 |
* |
764 |
* Results: |
765 |
* -1 is returned if the item is entirely outside the area |
766 |
* given by rectPtr, 0 if it overlaps, and 1 if it is entirely |
767 |
* inside the given area. |
768 |
* |
769 |
* Side effects: |
770 |
* None. |
771 |
* |
772 |
*-------------------------------------------------------------- |
773 |
*/ |
774 |
|
775 |
/* ARGSUSED */ |
776 |
static int |
777 |
BitmapToArea(canvas, itemPtr, rectPtr) |
778 |
Tk_Canvas canvas; /* Canvas containing item. */ |
779 |
Tk_Item *itemPtr; /* Item to check against rectangle. */ |
780 |
double *rectPtr; /* Pointer to array of four coordinates |
781 |
* (x1, y1, x2, y2) describing rectangular |
782 |
* area. */ |
783 |
{ |
784 |
BitmapItem *bmapPtr = (BitmapItem *) itemPtr; |
785 |
|
786 |
if ((rectPtr[2] <= bmapPtr->header.x1) |
787 |
|| (rectPtr[0] >= bmapPtr->header.x2) |
788 |
|| (rectPtr[3] <= bmapPtr->header.y1) |
789 |
|| (rectPtr[1] >= bmapPtr->header.y2)) { |
790 |
return -1; |
791 |
} |
792 |
if ((rectPtr[0] <= bmapPtr->header.x1) |
793 |
&& (rectPtr[1] <= bmapPtr->header.y1) |
794 |
&& (rectPtr[2] >= bmapPtr->header.x2) |
795 |
&& (rectPtr[3] >= bmapPtr->header.y2)) { |
796 |
return 1; |
797 |
} |
798 |
return 0; |
799 |
} |
800 |
|
801 |
/* |
802 |
*-------------------------------------------------------------- |
803 |
* |
804 |
* ScaleBitmap -- |
805 |
* |
806 |
* This procedure is invoked to rescale a bitmap item in a |
807 |
* canvas. It is one of the standard item procedures for |
808 |
* bitmap items, and is invoked by the generic canvas code. |
809 |
* |
810 |
* Results: |
811 |
* None. |
812 |
* |
813 |
* Side effects: |
814 |
* The item referred to by itemPtr is rescaled so that the |
815 |
* following transformation is applied to all point coordinates: |
816 |
* x' = originX + scaleX*(x-originX) |
817 |
* y' = originY + scaleY*(y-originY) |
818 |
* |
819 |
*-------------------------------------------------------------- |
820 |
*/ |
821 |
|
822 |
static void |
823 |
ScaleBitmap(canvas, itemPtr, originX, originY, scaleX, scaleY) |
824 |
Tk_Canvas canvas; /* Canvas containing rectangle. */ |
825 |
Tk_Item *itemPtr; /* Rectangle to be scaled. */ |
826 |
double originX, originY; /* Origin about which to scale item. */ |
827 |
double scaleX; /* Amount to scale in X direction. */ |
828 |
double scaleY; /* Amount to scale in Y direction. */ |
829 |
{ |
830 |
BitmapItem *bmapPtr = (BitmapItem *) itemPtr; |
831 |
|
832 |
bmapPtr->x = originX + scaleX*(bmapPtr->x - originX); |
833 |
bmapPtr->y = originY + scaleY*(bmapPtr->y - originY); |
834 |
ComputeBitmapBbox(canvas, bmapPtr); |
835 |
} |
836 |
|
837 |
/* |
838 |
*-------------------------------------------------------------- |
839 |
* |
840 |
* TranslateBitmap -- |
841 |
* |
842 |
* This procedure is called to move an item by a given amount. |
843 |
* |
844 |
* Results: |
845 |
* None. |
846 |
* |
847 |
* Side effects: |
848 |
* The position of the item is offset by (xDelta, yDelta), and |
849 |
* the bounding box is updated in the generic part of the item |
850 |
* structure. |
851 |
* |
852 |
*-------------------------------------------------------------- |
853 |
*/ |
854 |
|
855 |
static void |
856 |
TranslateBitmap(canvas, itemPtr, deltaX, deltaY) |
857 |
Tk_Canvas canvas; /* Canvas containing item. */ |
858 |
Tk_Item *itemPtr; /* Item that is being moved. */ |
859 |
double deltaX, deltaY; /* Amount by which item is to be |
860 |
* moved. */ |
861 |
{ |
862 |
BitmapItem *bmapPtr = (BitmapItem *) itemPtr; |
863 |
|
864 |
bmapPtr->x += deltaX; |
865 |
bmapPtr->y += deltaY; |
866 |
ComputeBitmapBbox(canvas, bmapPtr); |
867 |
} |
868 |
|
869 |
/* |
870 |
*-------------------------------------------------------------- |
871 |
* |
872 |
* BitmapToPostscript -- |
873 |
* |
874 |
* This procedure is called to generate Postscript for |
875 |
* bitmap items. |
876 |
* |
877 |
* Results: |
878 |
* The return value is a standard Tcl result. If an error |
879 |
* occurs in generating Postscript then an error message is |
880 |
* left in the interp's result, replacing whatever used to be there. |
881 |
* If no error occurs, then Postscript for the item is appended |
882 |
* to the result. |
883 |
* |
884 |
* Side effects: |
885 |
* None. |
886 |
* |
887 |
*-------------------------------------------------------------- |
888 |
*/ |
889 |
|
890 |
static int |
891 |
BitmapToPostscript(interp, canvas, itemPtr, prepass) |
892 |
Tcl_Interp *interp; /* Leave Postscript or error message |
893 |
* here. */ |
894 |
Tk_Canvas canvas; /* Information about overall canvas. */ |
895 |
Tk_Item *itemPtr; /* Item for which Postscript is |
896 |
* wanted. */ |
897 |
int prepass; /* 1 means this is a prepass to |
898 |
* collect font information; 0 means |
899 |
* final Postscript is being created. */ |
900 |
{ |
901 |
BitmapItem *bmapPtr = (BitmapItem *) itemPtr; |
902 |
double x, y; |
903 |
int width, height, rowsAtOnce, rowsThisTime; |
904 |
int curRow; |
905 |
char buffer[100 + TCL_DOUBLE_SPACE * 2 + TCL_INTEGER_SPACE * 4]; |
906 |
|
907 |
if (bmapPtr->bitmap == None) { |
908 |
return TCL_OK; |
909 |
} |
910 |
|
911 |
/* |
912 |
* Compute the coordinates of the lower-left corner of the bitmap, |
913 |
* taking into account the anchor position for the bitmp. |
914 |
*/ |
915 |
|
916 |
x = bmapPtr->x; |
917 |
y = Tk_CanvasPsY(canvas, bmapPtr->y); |
918 |
Tk_SizeOfBitmap(Tk_Display(Tk_CanvasTkwin(canvas)), bmapPtr->bitmap, |
919 |
&width, &height); |
920 |
switch (bmapPtr->anchor) { |
921 |
case TK_ANCHOR_NW: y -= height; break; |
922 |
case TK_ANCHOR_N: x -= width/2.0; y -= height; break; |
923 |
case TK_ANCHOR_NE: x -= width; y -= height; break; |
924 |
case TK_ANCHOR_E: x -= width; y -= height/2.0; break; |
925 |
case TK_ANCHOR_SE: x -= width; break; |
926 |
case TK_ANCHOR_S: x -= width/2.0; break; |
927 |
case TK_ANCHOR_SW: break; |
928 |
case TK_ANCHOR_W: y -= height/2.0; break; |
929 |
case TK_ANCHOR_CENTER: x -= width/2.0; y -= height/2.0; break; |
930 |
} |
931 |
|
932 |
/* |
933 |
* Color the background, if there is one. |
934 |
*/ |
935 |
|
936 |
if (bmapPtr->bgColor != NULL) { |
937 |
sprintf(buffer, |
938 |
"%.15g %.15g moveto %d 0 rlineto 0 %d rlineto %d %s\n", |
939 |
x, y, width, height, -width, "0 rlineto closepath"); |
940 |
Tcl_AppendResult(interp, buffer, (char *) NULL); |
941 |
if (Tk_CanvasPsColor(interp, canvas, bmapPtr->bgColor) != TCL_OK) { |
942 |
return TCL_ERROR; |
943 |
} |
944 |
Tcl_AppendResult(interp, "fill\n", (char *) NULL); |
945 |
} |
946 |
|
947 |
/* |
948 |
* Draw the bitmap, if there is a foreground color. If the bitmap |
949 |
* is very large, then chop it up into multiple bitmaps, each |
950 |
* consisting of one or more rows. This is needed because Postscript |
951 |
* can't handle single strings longer than 64 KBytes long. |
952 |
*/ |
953 |
|
954 |
if (bmapPtr->fgColor != NULL) { |
955 |
if (Tk_CanvasPsColor(interp, canvas, bmapPtr->fgColor) != TCL_OK) { |
956 |
return TCL_ERROR; |
957 |
} |
958 |
if (width > 60000) { |
959 |
Tcl_ResetResult(interp); |
960 |
Tcl_AppendResult(interp, "can't generate Postscript", |
961 |
" for bitmaps more than 60000 pixels wide", |
962 |
(char *) NULL); |
963 |
return TCL_ERROR; |
964 |
} |
965 |
rowsAtOnce = 60000/width; |
966 |
if (rowsAtOnce < 1) { |
967 |
rowsAtOnce = 1; |
968 |
} |
969 |
sprintf(buffer, "%.15g %.15g translate\n", x, y+height); |
970 |
Tcl_AppendResult(interp, buffer, (char *) NULL); |
971 |
for (curRow = 0; curRow < height; curRow += rowsAtOnce) { |
972 |
rowsThisTime = rowsAtOnce; |
973 |
if (rowsThisTime > (height - curRow)) { |
974 |
rowsThisTime = height - curRow; |
975 |
} |
976 |
sprintf(buffer, "0 -%.15g translate\n%d %d true matrix {\n", |
977 |
(double) rowsThisTime, width, rowsThisTime); |
978 |
Tcl_AppendResult(interp, buffer, (char *) NULL); |
979 |
if (Tk_CanvasPsBitmap(interp, canvas, bmapPtr->bitmap, |
980 |
0, curRow, width, rowsThisTime) != TCL_OK) { |
981 |
return TCL_ERROR; |
982 |
} |
983 |
Tcl_AppendResult(interp, "\n} imagemask\n", (char *) NULL); |
984 |
} |
985 |
} |
986 |
return TCL_OK; |
987 |
} |
988 |
|
989 |
/* End of tkcanvbmap.c */ |