/[dtapublic]/projs/dtats/trunk/shared_source/c_tk_base_7_5_w_mods/tkimage.c
ViewVC logotype

Contents of /projs/dtats/trunk/shared_source/c_tk_base_7_5_w_mods/tkimage.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 98 - (show annotations) (download)
Sun Dec 18 00:57:31 2016 UTC (7 years, 11 months ago) by dashley
File MIME type: text/plain
File size: 28637 byte(s)
Reorganization.
1 /* $Header$ */
2
3 /*
4 * tkImage.c --
5 *
6 * This module implements the image protocol, which allows lots
7 * of different kinds of images to be used in lots of different
8 * widgets.
9 *
10 * Copyright (c) 1994 The Regents of the University of California.
11 * Copyright (c) 1994-1997 Sun Microsystems, Inc.
12 *
13 * See the file "license.terms" for information on usage and redistribution
14 * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
15 *
16 * RCS: @(#) $Id: tkimage.c,v 1.1.1.1 2001/06/13 05:02:12 dtashley Exp $
17 */
18
19 #include "tkInt.h"
20 #include "tkPort.h"
21
22 /*
23 * Each call to Tk_GetImage returns a pointer to one of the following
24 * structures, which is used as a token by clients (widgets) that
25 * display images.
26 */
27
28 typedef struct Image {
29 Tk_Window tkwin; /* Window passed to Tk_GetImage (needed to
30 * "re-get" the image later if the manager
31 * changes). */
32 Display *display; /* Display for tkwin. Needed because when
33 * the image is eventually freed tkwin may
34 * not exist anymore. */
35 struct ImageMaster *masterPtr;
36 /* Master for this image (identifiers image
37 * manager, for example). */
38 ClientData instanceData;
39 /* One word argument to pass to image manager
40 * when dealing with this image instance. */
41 Tk_ImageChangedProc *changeProc;
42 /* Code in widget to call when image changes
43 * in a way that affects redisplay. */
44 ClientData widgetClientData;
45 /* Argument to pass to changeProc. */
46 struct Image *nextPtr; /* Next in list of all image instances
47 * associated with the same name. */
48
49 } Image;
50
51 /*
52 * For each image master there is one of the following structures,
53 * which represents a name in the image table and all of the images
54 * instantiated from it. Entries in mainPtr->imageTable point to
55 * these structures.
56 */
57
58 typedef struct ImageMaster {
59 Tk_ImageType *typePtr; /* Information about image type. NULL means
60 * that no image manager owns this image: the
61 * image was deleted. */
62 ClientData masterData; /* One-word argument to pass to image mgr
63 * when dealing with the master, as opposed
64 * to instances. */
65 int width, height; /* Last known dimensions for image. */
66 Tcl_HashTable *tablePtr; /* Pointer to hash table containing image
67 * (the imageTable field in some TkMainInfo
68 * structure). */
69 Tcl_HashEntry *hPtr; /* Hash entry in mainPtr->imageTable for
70 * this structure (used to delete the hash
71 * entry). */
72 Image *instancePtr; /* Pointer to first in list of instances
73 * derived from this name. */
74 } ImageMaster;
75
76 typedef struct ThreadSpecificData {
77 Tk_ImageType *imageTypeList;/* First in a list of all known image
78 * types. */
79 Tk_ImageType *oldImageTypeList;/* First in a list of all known old-style image
80 * types. */
81 } ThreadSpecificData;
82 static Tcl_ThreadDataKey dataKey;
83
84 /*
85 * Prototypes for local procedures:
86 */
87
88 static void DeleteImage _ANSI_ARGS_((ImageMaster *masterPtr));
89
90 /*
91 *----------------------------------------------------------------------
92 *
93 * Tk_CreateOldImageType, Tk_CreateImageType --
94 *
95 * This procedure is invoked by an image manager to tell Tk about
96 * a new kind of image and the procedures that manage the new type.
97 * The procedure is typically invoked during Tcl_AppInit.
98 *
99 * Results:
100 * None.
101 *
102 * Side effects:
103 * The new image type is entered into a table used in the "image
104 * create" command.
105 *
106 *----------------------------------------------------------------------
107 */
108
109 void
110 Tk_CreateOldImageType(typePtr)
111 Tk_ImageType *typePtr; /* Structure describing the type. All of
112 * the fields except "nextPtr" must be filled
113 * in by caller. Must not have been passed
114 * to Tk_CreateImageType previously. */
115 {
116 ThreadSpecificData *tsdPtr = (ThreadSpecificData *)
117 Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));
118
119 typePtr->nextPtr = tsdPtr->oldImageTypeList;
120 tsdPtr->oldImageTypeList = typePtr;
121 }
122
123 void
124 Tk_CreateImageType(typePtr)
125 Tk_ImageType *typePtr; /* Structure describing the type. All of
126 * the fields except "nextPtr" must be filled
127 * in by caller. Must not have been passed
128 * to Tk_CreateImageType previously. */
129 {
130 ThreadSpecificData *tsdPtr = (ThreadSpecificData *)
131 Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));
132
133 typePtr->nextPtr = tsdPtr->imageTypeList;
134 tsdPtr->imageTypeList = typePtr;
135 }
136
137 /*
138 *----------------------------------------------------------------------
139 *
140 * Tk_ImageObjCmd --
141 *
142 * This procedure is invoked to process the "image" Tcl command.
143 * See the user documentation for details on what it does.
144 *
145 * Results:
146 * A standard Tcl result.
147 *
148 * Side effects:
149 * See the user documentation.
150 *
151 *----------------------------------------------------------------------
152 */
153
154 int
155 Tk_ImageObjCmd(clientData, interp, objc, objv)
156 ClientData clientData; /* Main window associated with interpreter. */
157 Tcl_Interp *interp; /* Current interpreter. */
158 int objc; /* Number of arguments. */
159 Tcl_Obj *CONST objv[]; /* Argument strings. */
160 {
161 static char *imageOptions[] = {
162 "create", "delete", "height", "names", "type", "types", "width",
163 (char *) NULL
164 };
165 enum options {
166 IMAGE_CREATE, IMAGE_DELETE, IMAGE_HEIGHT, IMAGE_NAMES,
167 IMAGE_TYPE, IMAGE_TYPES, IMAGE_WIDTH
168 };
169 TkWindow *winPtr = (TkWindow *) clientData;
170 int i, new, firstOption, index;
171 Tk_ImageType *typePtr;
172 ImageMaster *masterPtr;
173 Image *imagePtr;
174 Tcl_HashEntry *hPtr;
175 Tcl_HashSearch search;
176 char idString[16 + TCL_INTEGER_SPACE], *name;
177 TkDisplay *dispPtr = winPtr->dispPtr;
178 ThreadSpecificData *tsdPtr = (ThreadSpecificData *)
179 Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));
180
181 if (objc < 2) {
182 Tcl_WrongNumArgs(interp, 1, objv, "option ?args?");
183 return TCL_ERROR;
184 }
185
186 if (Tcl_GetIndexFromObj(interp, objv[1], imageOptions, "option", 0,
187 &index) != TCL_OK) {
188 return TCL_ERROR;
189 }
190 switch ((enum options) index) {
191 case IMAGE_CREATE: {
192 char *arg;
193 Tcl_Obj **args;
194 int oldimage = 0;
195 if (objc < 3) {
196 Tcl_WrongNumArgs(interp, 2, objv, "type ?name? ?options?");
197 return TCL_ERROR;
198 }
199
200 /*
201 * Look up the image type.
202 */
203
204 arg = Tcl_GetString(objv[2]);
205 for (typePtr = tsdPtr->imageTypeList; typePtr != NULL;
206 typePtr = typePtr->nextPtr) {
207 if ((*arg == typePtr->name[0])
208 && (strcmp(arg, typePtr->name) == 0)) {
209 break;
210 }
211 }
212 if (typePtr == NULL) {
213 oldimage = 1;
214 for (typePtr = tsdPtr->oldImageTypeList; typePtr != NULL;
215 typePtr = typePtr->nextPtr) {
216 if ((*arg == typePtr->name[0])
217 && (strcmp(arg, typePtr->name) == 0)) {
218 break;
219 }
220 }
221 }
222 if (typePtr == NULL) {
223 Tcl_AppendResult(interp, "image type \"", arg,
224 "\" doesn't exist", (char *) NULL);
225 return TCL_ERROR;
226 }
227
228 /*
229 * Figure out a name to use for the new image.
230 */
231
232 if ((objc == 3) || (*(arg = Tcl_GetString(objv[3])) == '-')) {
233 dispPtr->imageId++;
234 sprintf(idString, "image%d", dispPtr->imageId);
235 name = idString;
236 firstOption = 3;
237 } else {
238 name = arg;
239 firstOption = 4;
240 }
241
242 /*
243 * Create the data structure for the new image.
244 */
245
246 hPtr = Tcl_CreateHashEntry(&winPtr->mainPtr->imageTable,
247 name, &new);
248 if (new) {
249 masterPtr = (ImageMaster *) ckalloc(sizeof(ImageMaster));
250 masterPtr->typePtr = NULL;
251 masterPtr->masterData = NULL;
252 masterPtr->width = masterPtr->height = 1;
253 masterPtr->tablePtr = &winPtr->mainPtr->imageTable;
254 masterPtr->hPtr = hPtr;
255 masterPtr->instancePtr = NULL;
256 Tcl_SetHashValue(hPtr, masterPtr);
257 } else {
258 /*
259 * An image already exists by this name. Disconnect the
260 * instances from the master.
261 */
262
263 masterPtr = (ImageMaster *) Tcl_GetHashValue(hPtr);
264 if (masterPtr->typePtr != NULL) {
265 for (imagePtr = masterPtr->instancePtr; imagePtr != NULL;
266 imagePtr = imagePtr->nextPtr) {
267 (*masterPtr->typePtr->freeProc)(
268 imagePtr->instanceData, imagePtr->display);
269 (*imagePtr->changeProc)(imagePtr->widgetClientData,
270 0, 0, masterPtr->width, masterPtr->height,
271 masterPtr->width, masterPtr->height);
272 }
273 (*masterPtr->typePtr->deleteProc)(masterPtr->masterData);
274 masterPtr->typePtr = NULL;
275 }
276 }
277
278 /*
279 * Call the image type manager so that it can perform its own
280 * initialization, then re-"get" for any existing instances of
281 * the image.
282 */
283
284 objv += firstOption;
285 objc -= firstOption;
286 args = (Tcl_Obj **) objv;
287 if (oldimage) {
288 int i;
289 args = (Tcl_Obj **) ckalloc((objc+1) * sizeof(char *));
290 for (i = 0; i < objc; i++) {
291 args[i] = (Tcl_Obj *) Tcl_GetString(objv[i]);
292 }
293 args[objc] = NULL;
294 }
295 if ((*typePtr->createProc)(interp, name, objc,
296 args, typePtr, (Tk_ImageMaster) masterPtr,
297 &masterPtr->masterData) != TCL_OK) {
298 DeleteImage(masterPtr);
299 if (oldimage) {
300 ckfree((char *) args);
301 }
302 return TCL_ERROR;
303 }
304 if (oldimage) {
305 ckfree((char *) args);
306 }
307 masterPtr->typePtr = typePtr;
308 for (imagePtr = masterPtr->instancePtr; imagePtr != NULL;
309 imagePtr = imagePtr->nextPtr) {
310 imagePtr->instanceData = (*typePtr->getProc)(
311 imagePtr->tkwin, masterPtr->masterData);
312 }
313 Tcl_SetResult(interp,
314 Tcl_GetHashKey(&winPtr->mainPtr->imageTable, hPtr),
315 TCL_STATIC);
316 break;
317 }
318 case IMAGE_DELETE: {
319 for (i = 2; i < objc; i++) {
320 char *arg = Tcl_GetString(objv[i]);
321 hPtr = Tcl_FindHashEntry(&winPtr->mainPtr->imageTable, arg);
322 if (hPtr == NULL) {
323 Tcl_AppendResult(interp, "image \"", arg,
324 "\" doesn't exist", (char *) NULL);
325 return TCL_ERROR;
326 }
327 masterPtr = (ImageMaster *) Tcl_GetHashValue(hPtr);
328 DeleteImage(masterPtr);
329 }
330 break;
331 }
332 case IMAGE_HEIGHT: {
333 char *arg;
334 if (objc != 3) {
335 Tcl_WrongNumArgs(interp, 2, objv, "name");
336 return TCL_ERROR;
337 }
338 arg = Tcl_GetString(objv[2]);
339 hPtr = Tcl_FindHashEntry(&winPtr->mainPtr->imageTable, arg);
340 if (hPtr == NULL) {
341 Tcl_AppendResult(interp, "image \"", arg,
342 "\" doesn't exist", (char *) NULL);
343 return TCL_ERROR;
344 }
345 masterPtr = (ImageMaster *) Tcl_GetHashValue(hPtr);
346 Tcl_SetIntObj(Tcl_GetObjResult(interp), masterPtr->height);
347 break;
348 }
349 case IMAGE_NAMES: {
350 if (objc != 2) {
351 Tcl_WrongNumArgs(interp, 2, objv, NULL);
352 return TCL_ERROR;
353 }
354 for (hPtr = Tcl_FirstHashEntry(&winPtr->mainPtr->imageTable, &search);
355 hPtr != NULL; hPtr = Tcl_NextHashEntry(&search)) {
356 Tcl_AppendElement(interp, Tcl_GetHashKey(
357 &winPtr->mainPtr->imageTable, hPtr));
358 }
359 break;
360 }
361 case IMAGE_TYPE: {
362 char *arg;
363 if (objc != 3) {
364 Tcl_WrongNumArgs(interp, 2, objv, "name");
365 return TCL_ERROR;
366 }
367 arg = Tcl_GetString(objv[2]);
368 hPtr = Tcl_FindHashEntry(&winPtr->mainPtr->imageTable, arg);
369 if (hPtr == NULL) {
370 Tcl_AppendResult(interp, "image \"", arg,
371 "\" doesn't exist", (char *) NULL);
372 return TCL_ERROR;
373 }
374 masterPtr = (ImageMaster *) Tcl_GetHashValue(hPtr);
375 if (masterPtr->typePtr != NULL) {
376 Tcl_SetResult(interp, masterPtr->typePtr->name, TCL_STATIC);
377 }
378 break;
379 }
380 case IMAGE_TYPES: {
381 if (objc != 2) {
382 Tcl_WrongNumArgs(interp, 2, objv, NULL);
383 return TCL_ERROR;
384 }
385 for (typePtr = tsdPtr->imageTypeList; typePtr != NULL;
386 typePtr = typePtr->nextPtr) {
387 Tcl_AppendElement(interp, typePtr->name);
388 }
389 for (typePtr = tsdPtr->oldImageTypeList; typePtr != NULL;
390 typePtr = typePtr->nextPtr) {
391 Tcl_AppendElement(interp, typePtr->name);
392 }
393 break;
394 }
395 case IMAGE_WIDTH: {
396 char *arg;
397 if (objc != 3) {
398 Tcl_WrongNumArgs(interp, 2, objv, "name");
399 return TCL_ERROR;
400 }
401 arg = Tcl_GetString(objv[2]);
402 hPtr = Tcl_FindHashEntry(&winPtr->mainPtr->imageTable, arg);
403 if (hPtr == NULL) {
404 Tcl_AppendResult(interp, "image \"", arg,
405 "\" doesn't exist", (char *) NULL);
406 return TCL_ERROR;
407 }
408 masterPtr = (ImageMaster *) Tcl_GetHashValue(hPtr);
409 Tcl_SetIntObj(Tcl_GetObjResult(interp), masterPtr->width);
410 break;
411 }
412 }
413 return TCL_OK;
414 }
415
416 /*
417 *----------------------------------------------------------------------
418 *
419 * Tk_ImageChanged --
420 *
421 * This procedure is called by an image manager whenever something
422 * has happened that requires the image to be redrawn (some of its
423 * pixels have changed, or its size has changed).
424 *
425 * Results:
426 * None.
427 *
428 * Side effects:
429 * Any widgets that display the image are notified so that they
430 * can redisplay themselves as appropriate.
431 *
432 *----------------------------------------------------------------------
433 */
434
435 void
436 Tk_ImageChanged(imageMaster, x, y, width, height, imageWidth,
437 imageHeight)
438 Tk_ImageMaster imageMaster; /* Image that needs redisplay. */
439 int x, y; /* Coordinates of upper-left pixel of
440 * region of image that needs to be
441 * redrawn. */
442 int width, height; /* Dimensions (in pixels) of region of
443 * image to redraw. If either dimension
444 * is zero then the image doesn't need to
445 * be redrawn (perhaps all that happened is
446 * that its size changed). */
447 int imageWidth, imageHeight;/* New dimensions of image. */
448 {
449 ImageMaster *masterPtr = (ImageMaster *) imageMaster;
450 Image *imagePtr;
451
452 masterPtr->width = imageWidth;
453 masterPtr->height = imageHeight;
454 for (imagePtr = masterPtr->instancePtr; imagePtr != NULL;
455 imagePtr = imagePtr->nextPtr) {
456 (*imagePtr->changeProc)(imagePtr->widgetClientData, x, y,
457 width, height, imageWidth, imageHeight);
458 }
459 }
460
461 /*
462 *----------------------------------------------------------------------
463 *
464 * Tk_NameOfImage --
465 *
466 * Given a token for an image master, this procedure returns
467 * the name of the image.
468 *
469 * Results:
470 * The return value is the string name for imageMaster.
471 *
472 * Side effects:
473 * None.
474 *
475 *----------------------------------------------------------------------
476 */
477
478 char *
479 Tk_NameOfImage(imageMaster)
480 Tk_ImageMaster imageMaster; /* Token for image. */
481 {
482 ImageMaster *masterPtr = (ImageMaster *) imageMaster;
483
484 return Tcl_GetHashKey(masterPtr->tablePtr, masterPtr->hPtr);
485 }
486
487 /*
488 *----------------------------------------------------------------------
489 *
490 * Tk_GetImage --
491 *
492 * This procedure is invoked by a widget when it wants to use
493 * a particular image in a particular window.
494 *
495 * Results:
496 * The return value is a token for the image. If there is no image
497 * by the given name, then NULL is returned and an error message is
498 * left in the interp's result.
499 *
500 * Side effects:
501 * Tk records the fact that the widget is using the image, and
502 * it will invoke changeProc later if the widget needs redisplay
503 * (i.e. its size changes or some of its pixels change). The
504 * caller must eventually invoke Tk_FreeImage when it no longer
505 * needs the image.
506 *
507 *----------------------------------------------------------------------
508 */
509
510 Tk_Image
511 Tk_GetImage(interp, tkwin, name, changeProc, clientData)
512 Tcl_Interp *interp; /* Place to leave error message if image
513 * can't be found. */
514 Tk_Window tkwin; /* Token for window in which image will
515 * be used. */
516 char *name; /* Name of desired image. */
517 Tk_ImageChangedProc *changeProc;
518 /* Procedure to invoke when redisplay is
519 * needed because image's pixels or size
520 * changed. */
521 ClientData clientData; /* One-word argument to pass to damageProc. */
522 {
523 Tcl_HashEntry *hPtr;
524 ImageMaster *masterPtr;
525 Image *imagePtr;
526
527 hPtr = Tcl_FindHashEntry(&((TkWindow *) tkwin)->mainPtr->imageTable, name);
528 if (hPtr == NULL) {
529 goto noSuchImage;
530 }
531 masterPtr = (ImageMaster *) Tcl_GetHashValue(hPtr);
532 if (masterPtr->typePtr == NULL) {
533 goto noSuchImage;
534 }
535 imagePtr = (Image *) ckalloc(sizeof(Image));
536 imagePtr->tkwin = tkwin;
537 imagePtr->display = Tk_Display(tkwin);
538 imagePtr->masterPtr = masterPtr;
539 imagePtr->instanceData =
540 (*masterPtr->typePtr->getProc)(tkwin, masterPtr->masterData);
541 imagePtr->changeProc = changeProc;
542 imagePtr->widgetClientData = clientData;
543 imagePtr->nextPtr = masterPtr->instancePtr;
544 masterPtr->instancePtr = imagePtr;
545 return (Tk_Image) imagePtr;
546
547 noSuchImage:
548 Tcl_AppendResult(interp, "image \"", name, "\" doesn't exist",
549 (char *) NULL);
550 return NULL;
551 }
552
553 /*
554 *----------------------------------------------------------------------
555 *
556 * Tk_FreeImage --
557 *
558 * This procedure is invoked by a widget when it no longer needs
559 * an image acquired by a previous call to Tk_GetImage. For each
560 * call to Tk_GetImage there must be exactly one call to Tk_FreeImage.
561 *
562 * Results:
563 * None.
564 *
565 * Side effects:
566 * The association between the image and the widget is removed.
567 *
568 *----------------------------------------------------------------------
569 */
570
571 void
572 Tk_FreeImage(image)
573 Tk_Image image; /* Token for image that is no longer
574 * needed by a widget. */
575 {
576 Image *imagePtr = (Image *) image;
577 ImageMaster *masterPtr = imagePtr->masterPtr;
578 Image *prevPtr;
579
580 /*
581 * Clean up the particular instance.
582 */
583
584 if (masterPtr->typePtr != NULL) {
585 (*masterPtr->typePtr->freeProc)(imagePtr->instanceData,
586 imagePtr->display);
587 }
588 prevPtr = masterPtr->instancePtr;
589 if (prevPtr == imagePtr) {
590 masterPtr->instancePtr = imagePtr->nextPtr;
591 } else {
592 while (prevPtr->nextPtr != imagePtr) {
593 prevPtr = prevPtr->nextPtr;
594 }
595 prevPtr->nextPtr = imagePtr->nextPtr;
596 }
597 ckfree((char *) imagePtr);
598
599 /*
600 * If there are no more instances left for the master, and if the
601 * master image has been deleted, then delete the master too.
602 */
603
604 if ((masterPtr->typePtr == NULL) && (masterPtr->instancePtr == NULL)) {
605 Tcl_DeleteHashEntry(masterPtr->hPtr);
606 ckfree((char *) masterPtr);
607 }
608 }
609
610 /*
611 *----------------------------------------------------------------------
612 *
613 * Tk_PostscriptImage --
614 *
615 * This procedure is called by widgets that contain images in order
616 * to redisplay an image on the screen or an off-screen pixmap.
617 *
618 * Results:
619 * None.
620 *
621 * Side effects:
622 * The image's manager is notified, and it redraws the desired
623 * portion of the image before returning.
624 *
625 *----------------------------------------------------------------------
626 */
627
628 int
629 Tk_PostscriptImage(image, interp, tkwin, psinfo, x, y, width, height, prepass)
630 Tk_Image image; /* Token for image to redisplay. */
631 Tcl_Interp *interp;
632 Tk_Window tkwin;
633 Tk_PostscriptInfo psinfo; /* postscript info */
634 int x, y; /* Upper-left pixel of region in image that
635 * needs to be redisplayed. */
636 int width, height; /* Dimensions of region to redraw. */
637 int prepass;
638 {
639 Image *imagePtr = (Image *) image;
640 int result;
641 XImage *ximage;
642 Pixmap pmap;
643 GC newGC;
644 XGCValues gcValues;
645
646 if (imagePtr->masterPtr->typePtr == NULL) {
647 /*
648 * No master for image, so nothing to display on postscript.
649 */
650 return TCL_OK;
651 }
652
653 /*
654 * Check if an image specific postscript-generation function
655 * exists; otherwise go on with generic code.
656 */
657
658 if (imagePtr->masterPtr->typePtr->postscriptProc != NULL) {
659 return (*imagePtr->masterPtr->typePtr->postscriptProc)(
660 imagePtr->masterPtr->masterData, interp, tkwin, psinfo,
661 x, y, width, height, prepass);
662 }
663
664 if (prepass) {
665 return TCL_OK;
666 }
667
668 /*
669 * Create a Pixmap, tell the image to redraw itself there, and then
670 * generate an XImage from the Pixmap. We can then read pixel
671 * values out of the XImage.
672 */
673
674 pmap = Tk_GetPixmap(Tk_Display(tkwin), Tk_WindowId(tkwin),
675 width, height, Tk_Depth(tkwin));
676
677 gcValues.foreground = WhitePixelOfScreen(Tk_Screen(tkwin));
678 newGC = Tk_GetGC(tkwin, GCForeground, &gcValues);
679 if (newGC != None) {
680 XFillRectangle(Tk_Display(tkwin), pmap, newGC,
681 0, 0, (unsigned int)width, (unsigned int)height);
682 Tk_FreeGC(Tk_Display(tkwin), newGC);
683 }
684
685 Tk_RedrawImage(image, x, y, width, height, pmap, 0, 0);
686
687 ximage = XGetImage(Tk_Display(tkwin), pmap, 0, 0,
688 (unsigned int)width, (unsigned int)height, AllPlanes, ZPixmap);
689
690 Tk_FreePixmap(Tk_Display(tkwin), pmap);
691
692 if (ximage == NULL) {
693 /* The XGetImage() function is apparently not
694 * implemented on this system. Just ignore it.
695 */
696 return TCL_OK;
697 }
698 result = TkPostscriptImage(interp, tkwin, psinfo, ximage, x, y,
699 width, height);
700
701 XDestroyImage(ximage);
702 return result;
703 }
704
705 /*
706 *----------------------------------------------------------------------
707 *
708 * Tk_RedrawImage --
709 *
710 * This procedure is called by widgets that contain images in order
711 * to redisplay an image on the screen or an off-screen pixmap.
712 *
713 * Results:
714 * None.
715 *
716 * Side effects:
717 * The image's manager is notified, and it redraws the desired
718 * portion of the image before returning.
719 *
720 *----------------------------------------------------------------------
721 */
722
723 void
724 Tk_RedrawImage(image, imageX, imageY, width, height, drawable,
725 drawableX, drawableY)
726 Tk_Image image; /* Token for image to redisplay. */
727 int imageX, imageY; /* Upper-left pixel of region in image that
728 * needs to be redisplayed. */
729 int width, height; /* Dimensions of region to redraw. */
730 Drawable drawable; /* Drawable in which to display image
731 * (window or pixmap). If this is a pixmap,
732 * it must have the same depth as the window
733 * used in the Tk_GetImage call for the
734 * image. */
735 int drawableX, drawableY; /* Coordinates in drawable that correspond
736 * to imageX and imageY. */
737 {
738 Image *imagePtr = (Image *) image;
739
740 if (imagePtr->masterPtr->typePtr == NULL) {
741 /*
742 * No master for image, so nothing to display.
743 */
744
745 return;
746 }
747
748 /*
749 * Clip the redraw area to the area of the image.
750 */
751
752 if (imageX < 0) {
753 width += imageX;
754 drawableX -= imageX;
755 imageX = 0;
756 }
757 if (imageY < 0) {
758 height += imageY;
759 drawableY -= imageY;
760 imageY = 0;
761 }
762 if ((imageX + width) > imagePtr->masterPtr->width) {
763 width = imagePtr->masterPtr->width - imageX;
764 }
765 if ((imageY + height) > imagePtr->masterPtr->height) {
766 height = imagePtr->masterPtr->height - imageY;
767 }
768 (*imagePtr->masterPtr->typePtr->displayProc)(
769 imagePtr->instanceData, imagePtr->display, drawable,
770 imageX, imageY, width, height, drawableX, drawableY);
771 }
772
773 /*
774 *----------------------------------------------------------------------
775 *
776 * Tk_SizeOfImage --
777 *
778 * This procedure returns the current dimensions of an image.
779 *
780 * Results:
781 * The width and height of the image are returned in *widthPtr
782 * and *heightPtr.
783 *
784 * Side effects:
785 * None.
786 *
787 *----------------------------------------------------------------------
788 */
789
790 void
791 Tk_SizeOfImage(image, widthPtr, heightPtr)
792 Tk_Image image; /* Token for image whose size is wanted. */
793 int *widthPtr; /* Return width of image here. */
794 int *heightPtr; /* Return height of image here. */
795 {
796 Image *imagePtr = (Image *) image;
797
798 *widthPtr = imagePtr->masterPtr->width;
799 *heightPtr = imagePtr->masterPtr->height;
800 }
801
802 /*
803 *----------------------------------------------------------------------
804 *
805 * Tk_DeleteImage --
806 *
807 * Given the name of an image, this procedure destroys the
808 * image.
809 *
810 * Results:
811 * None.
812 *
813 * Side effects:
814 * The image is destroyed; existing instances will display as
815 * blank areas. If no such image exists then the procedure does
816 * nothing.
817 *
818 *----------------------------------------------------------------------
819 */
820
821 void
822 Tk_DeleteImage(interp, name)
823 Tcl_Interp *interp; /* Interpreter in which the image was
824 * created. */
825 char *name; /* Name of image. */
826 {
827 Tcl_HashEntry *hPtr;
828 TkWindow *winPtr;
829
830 winPtr = (TkWindow *) Tk_MainWindow(interp);
831 if (winPtr == NULL) {
832 return;
833 }
834 hPtr = Tcl_FindHashEntry(&winPtr->mainPtr->imageTable, name);
835 if (hPtr == NULL) {
836 return;
837 }
838 DeleteImage((ImageMaster *) Tcl_GetHashValue(hPtr));
839 }
840
841 /*
842 *----------------------------------------------------------------------
843 *
844 * DeleteImage --
845 *
846 * This procedure is responsible for deleting an image.
847 *
848 * Results:
849 * None.
850 *
851 * Side effects:
852 * The connection is dropped between instances of this image and
853 * an image master. Image instances will redisplay themselves
854 * as empty areas, but existing instances will not be deleted.
855 *
856 *----------------------------------------------------------------------
857 */
858
859 static void
860 DeleteImage(masterPtr)
861 ImageMaster *masterPtr; /* Pointer to main data structure for image. */
862 {
863 Image *imagePtr;
864 Tk_ImageType *typePtr;
865
866 typePtr = masterPtr->typePtr;
867 masterPtr->typePtr = NULL;
868 if (typePtr != NULL) {
869 for (imagePtr = masterPtr->instancePtr; imagePtr != NULL;
870 imagePtr = imagePtr->nextPtr) {
871 (*typePtr->freeProc)(imagePtr->instanceData,
872 imagePtr->display);
873 (*imagePtr->changeProc)(imagePtr->widgetClientData, 0, 0,
874 masterPtr->width, masterPtr->height, masterPtr->width,
875 masterPtr->height);
876 }
877 (*typePtr->deleteProc)(masterPtr->masterData);
878 }
879 if (masterPtr->instancePtr == NULL) {
880 Tcl_DeleteHashEntry(masterPtr->hPtr);
881 ckfree((char *) masterPtr);
882 }
883 }
884
885 /*
886 *----------------------------------------------------------------------
887 *
888 * TkDeleteAllImages --
889 *
890 * This procedure is called when an application is deleted. It
891 * calls back all of the managers for all images so that they
892 * can cleanup, then it deletes all of Tk's internal information
893 * about images.
894 *
895 * Results:
896 * None.
897 *
898 * Side effects:
899 * All information for all images gets deleted.
900 *
901 *----------------------------------------------------------------------
902 */
903
904 void
905 TkDeleteAllImages(mainPtr)
906 TkMainInfo *mainPtr; /* Structure describing application that is
907 * going away. */
908 {
909 Tcl_HashSearch search;
910 Tcl_HashEntry *hPtr;
911 ImageMaster *masterPtr;
912
913 for (hPtr = Tcl_FirstHashEntry(&mainPtr->imageTable, &search);
914 hPtr != NULL; hPtr = Tcl_NextHashEntry(&search)) {
915 masterPtr = (ImageMaster *) Tcl_GetHashValue(hPtr);
916 DeleteImage(masterPtr);
917 }
918 Tcl_DeleteHashTable(&mainPtr->imageTable);
919 }
920
921 /*
922 *----------------------------------------------------------------------
923 *
924 * Tk_GetImageMasterData --
925 *
926 * Given the name of an image, this procedure returns the type
927 * of the image and the clientData associated with its master.
928 *
929 * Results:
930 * If there is no image by the given name, then NULL is returned
931 * and a NULL value is stored at *typePtrPtr. Otherwise the return
932 * value is the clientData returned by the createProc when the
933 * image was created and a pointer to the type structure for the
934 * image is stored at *typePtrPtr.
935 *
936 * Side effects:
937 * None.
938 *
939 *----------------------------------------------------------------------
940 */
941
942 ClientData
943 Tk_GetImageMasterData(interp, name, typePtrPtr)
944 Tcl_Interp *interp; /* Interpreter in which the image was
945 * created. */
946 char *name; /* Name of image. */
947 Tk_ImageType **typePtrPtr; /* Points to location to fill in with
948 * pointer to type information for image. */
949 {
950 Tcl_HashEntry *hPtr;
951 TkWindow *winPtr;
952 ImageMaster *masterPtr;
953
954 winPtr = (TkWindow *) Tk_MainWindow(interp);
955 hPtr = Tcl_FindHashEntry(&winPtr->mainPtr->imageTable, name);
956 if (hPtr == NULL) {
957 *typePtrPtr = NULL;
958 return NULL;
959 }
960 masterPtr = (ImageMaster *) Tcl_GetHashValue(hPtr);
961 *typePtrPtr = masterPtr->typePtr;
962 return masterPtr->masterData;
963 }
964
965 /*
966 *----------------------------------------------------------------------
967 *
968 * Tk_SetTSOrigin --
969 *
970 * Set the pattern origin of the tile to a common point (i.e. the
971 * origin (0,0) of the top level window) so that tiles from two
972 * different widgets will match up. This done by setting the
973 * GCTileStipOrigin field is set to the translated origin of the
974 * toplevel window in the hierarchy.
975 *
976 * Results:
977 * None.
978 *
979 * Side Effects:
980 * The GCTileStipOrigin is reset in the GC. This will cause the
981 * tile origin to change when the GC is used for drawing.
982 *
983 *----------------------------------------------------------------------
984 */
985 /*ARGSUSED*/
986 void
987 Tk_SetTSOrigin(tkwin, gc, x, y)
988 Tk_Window tkwin;
989 GC gc;
990 int x, y;
991 {
992 while (!Tk_IsTopLevel(tkwin)) {
993 x -= Tk_X(tkwin) + Tk_Changes(tkwin)->border_width;
994 y -= Tk_Y(tkwin) + Tk_Changes(tkwin)->border_width;
995 tkwin = Tk_Parent(tkwin);
996 }
997 XSetTSOrigin(Tk_Display(tkwin), gc, x, y);
998 }
999
1000 /* End of tkimage.c */

Properties

Name Value
svn:eol-style native
svn:keywords Header

dashley@gmail.com
ViewVC Help
Powered by ViewVC 1.1.25