2 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
6 % AAA N N IIIII M M AAA TTTTT EEEEE %
7 % A A NN N I MM MM A A T E %
8 % AAAAA N N N I M M M AAAAA T EEE %
9 % A A N NN I M M A A T E %
10 % A A N N IIIII M M A A T EEEEE %
13 % Methods to Interactively Animate an Image Sequence %
20 % Copyright 1999-2010 ImageMagick Studio LLC, a non-profit organization %
21 % dedicated to making software imaging solutions freely available. %
23 % You may not use this file except in compliance with the License. You may %
24 % obtain a copy of the License at %
26 % http://www.imagemagick.org/script/license.php %
28 % Unless required by applicable law or agreed to in writing, software %
29 % distributed under the License is distributed on an "AS IS" BASIS, %
30 % WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. %
31 % See the License for the specific language governing permissions and %
32 % limitations under the License. %
34 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
42 #include "magick/studio.h"
43 #include "magick/animate.h"
44 #include "magick/animate-private.h"
45 #include "magick/client.h"
46 #include "magick/color.h"
47 #include "magick/color-private.h"
48 #include "magick/colorspace.h"
49 #include "magick/constitute.h"
50 #include "magick/delegate.h"
51 #include "magick/exception.h"
52 #include "magick/exception-private.h"
53 #include "magick/geometry.h"
54 #include "magick/image-private.h"
55 #include "magick/layer.h"
56 #include "magick/list.h"
57 #include "magick/log.h"
58 #include "magick/image.h"
59 #include "magick/memory_.h"
60 #include "magick/monitor.h"
61 #include "magick/monitor-private.h"
62 #include "magick/option.h"
63 #include "magick/property.h"
64 #include "magick/resource_.h"
65 #include "magick/string_.h"
66 #include "magick/string-private.h"
67 #include "magick/transform.h"
68 #include "magick/utility.h"
69 #include "magick/version.h"
70 #include "magick/widget.h"
71 #include "magick/xwindow-private.h"
73 #if defined(MAGICKCORE_X11_DELEGATE)
75 Animate state declarations.
77 #define AutoReverseAnimationState 0x0004
78 #define ForwardAnimationState 0x0008
79 #define HighlightState 0x0010
80 #define PlayAnimationState 0x0020
81 #define RepeatAnimationState 0x0040
82 #define StepAnimationState 0x0080
92 " Press any button to map or unmap the Command widget.",
95 " The Command widget lists a number of sub-menus and commands.",
113 " Browse Documentation",
118 " Menu items with a indented triangle have a sub-menu. They",
119 " are represented above as the indented items. To access a",
120 " sub-menu item, move the pointer to the appropriate menu and",
121 " press a button and drag. When you find the desired sub-menu",
122 " item, release the button and the command is executed. Move",
123 " the pointer away from the sub-menu if you decide not to",
124 " execute a particular command.",
126 "KEYBOARD ACCELERATORS",
127 " Accelerators are one or two key presses that effect a",
128 " particular command. The keyboard accelerators that",
129 " animate(1) understands is:",
131 " Ctl+O Press to open an image from a file.",
133 " space Press to display the next image in the sequence.",
135 " < Press to speed-up the display of the images. Refer to",
136 " -delay for more information.",
138 " > Press to slow the display of the images. Refer to",
139 " -delay for more information.",
141 " F1 Press to display helpful information about animate(1).",
143 " Find Press to browse documentation about ImageMagick.",
145 " ? Press to display information about the image. Press",
146 " any key or button to erase the information.",
148 " This information is printed: image name; image size;",
149 " and the total number of unique colors in the image.",
151 " Ctl-q Press to discard all images and exit program.",
156 Constant declarations.
178 static const unsigned char
181 (unsigned char) 0xaa,
182 (unsigned char) 0x55,
183 (unsigned char) 0xaa,
184 (unsigned char) 0x55,
185 (unsigned char) 0xaa,
186 (unsigned char) 0x55,
187 (unsigned char) 0xaa,
192 (unsigned char) 0x00,
193 (unsigned char) 0x00,
194 (unsigned char) 0x00,
195 (unsigned char) 0x00,
196 (unsigned char) 0x00,
197 (unsigned char) 0x00,
198 (unsigned char) 0x00,
203 Enumeration declarations.
218 BrowseDocumentationCommand,
230 #define HighlightWidth 8
231 #define HighlightHeight 8
232 #define ShadowWidth 8
233 #define ShadowHeight 8
236 Forward declarations.
239 *XMagickCommand(Display *,XResourceInfo *,XWindows *,const CommandType,
240 Image **,MagickStatusType *);
242 static MagickBooleanType
243 XSaveImage(Display *,XResourceInfo *,XWindows *,Image *);
246 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
250 % A n i m a t e I m a g e s %
254 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
256 % AnimateImages() repeatedly displays an image sequence to any X window
257 % screen. It returns a value other than 0 if successful. Check the
258 % exception member of image to determine the reason for any failure.
260 % The format of the AnimateImages method is:
262 % MagickBooleanType AnimateImages(const ImageInfo *image_info,
265 % A description of each parameter follows:
267 % o image_info: the image info.
269 % o image: the image.
272 MagickExport MagickBooleanType AnimateImages(const ImageInfo *image_info,
290 assert(image_info != (const ImageInfo *) NULL);
291 assert(image_info->signature == MagickSignature);
292 assert(images != (Image *) NULL);
293 assert(images->signature == MagickSignature);
294 if (images->debug != MagickFalse)
295 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",images->filename);
296 display=XOpenDisplay(image_info->server_name);
297 if (display == (Display *) NULL)
299 (void) ThrowMagickException(&images->exception,GetMagickModule(),
300 XServerError,"UnableToOpenXServer","`%s'",XDisplayName(
301 image_info->server_name));
304 if (images->exception.severity != UndefinedException)
305 CatchException(&images->exception);
306 (void) XSetErrorHandler(XError);
307 resource_database=XGetResourceDatabase(display,GetClientName());
308 (void) ResetMagickMemory(&resource_info,0,sizeof(XResourceInfo));
309 XGetResourceInfo(image_info,resource_database,GetClientName(),&resource_info);
310 if (image_info->page != (char *) NULL)
311 resource_info.image_geometry=AcquireString(image_info->page);
312 resource_info.immutable=MagickTrue;
313 argv[0]=AcquireString(GetClientName());
314 (void) XAnimateImages(display,&resource_info,argv,1,images);
315 argv[0]=DestroyString(argv[0]);
316 (void) XCloseDisplay(display);
317 XDestroyResourceInfo(&resource_info);
318 status=images->exception.severity == UndefinedException ?
319 MagickTrue : MagickFalse;
320 return(status != 0 ? MagickTrue : MagickFalse);
324 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
328 + X M a g i c k C o m m a n d %
332 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
334 % XMagickCommand() makes a transform to the image or Image window as specified
335 % by a user menu button or keyboard command.
337 % The format of the XMagickCommand method is:
339 % Image *XMagickCommand(Display *display,XResourceInfo *resource_info,
340 % XWindows *windows,const CommandType command_type,Image **image,
341 % MagickStatusType *state)
343 % A description of each parameter follows:
345 % o display: Specifies a connection to an X server; returned from
348 % o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
350 % o windows: Specifies a pointer to a XWindows structure.
352 % o image: the image; XMagickCommand
353 % may transform the image and return a new image pointer.
355 % o state: Specifies a MagickStatusType; XMagickCommand may return a
360 static Image *XMagickCommand(Display *display,XResourceInfo *resource_info,
361 XWindows *windows,const CommandType command_type,Image **image,
362 MagickStatusType *state)
377 Process user command.
379 nexus=NewImageList();
380 switch (command_type)
404 filenames[MaxTextExtent] = "*";
406 if (resource_info->immutable != MagickFalse)
409 Request file name from user.
411 XFileBrowserWidget(display,windows,"Animate",filenames);
412 if (*filenames == '\0')
413 return((Image *) NULL);
415 Expand the filenames.
417 filelist=(char **) AcquireMagickMemory(sizeof(char *));
418 if (filelist == (char **) NULL)
420 ThrowXWindowException(ResourceLimitError,"MemoryAllocationFailed",
422 return((Image *) NULL);
425 filelist[0]=filenames;
426 status=ExpandFilenames(&number_files,&filelist);
427 if ((status == MagickFalse) || (number_files == 0))
429 if (number_files == 0)
431 ThrowXWindowException(ImageError,"NoImagesWereLoaded",filenames);
432 return((Image *) NULL);
434 ThrowXWindowException(ResourceLimitError,"MemoryAllocationFailed",
436 return((Image *) NULL);
438 read_info=CloneImageInfo(resource_info->image_info);
439 exception=AcquireExceptionInfo();
440 images=NewImageList();
441 XSetCursorState(display,windows,MagickTrue);
442 XCheckRefreshWindows(display,windows);
443 for (i=0; i < number_files; i++)
445 (void) CopyMagickString(read_info->filename,filelist[i],MaxTextExtent);
446 filelist[i]=DestroyString(filelist[i]);
447 *read_info->magick='\0';
448 next=ReadImage(read_info,exception);
449 CatchException(exception);
450 if (next != (Image *) NULL)
451 AppendImageToList(&images,next);
452 if (number_files <= 5)
454 proceed=SetImageProgress(images,LoadImageTag,i,(MagickSizeType)
456 if (proceed == MagickFalse)
459 filelist=(char **) RelinquishMagickMemory(filelist);
460 exception=DestroyExceptionInfo(exception);
461 read_info=DestroyImageInfo(read_info);
462 if (images == (Image *) NULL)
464 XSetCursorState(display,windows,MagickFalse);
465 ThrowXWindowException(ImageError,"NoImagesWereLoaded",filenames);
466 return((Image *) NULL);
468 nexus=GetFirstImageInList(images);
475 basename[MaxTextExtent];
481 Window name is the base of the filename.
483 *state|=PlayAnimationState;
484 *state&=(~AutoReverseAnimationState);
485 GetPathComponent((*image)->magick_filename,BasePath,basename);
486 (void) FormatMagickString(windows->image.name,MaxTextExtent,
487 "%s: %s",MagickPackageName,basename);
488 if (resource_info->title != (char *) NULL)
493 title=InterpretImageProperties(resource_info->image_info,*image,
494 resource_info->title);
495 (void) CopyMagickString(windows->image.name,title,MaxTextExtent);
496 title=DestroyString(title);
498 status=XStringListToTextProperty(&windows->image.name,1,&window_name);
501 XSetWMName(display,windows->image.id,&window_name);
502 (void) XFree((void *) window_name.value);
506 case StepBackwardCommand:
507 case StepForwardCommand:
509 *state|=StepAnimationState;
510 *state&=(~PlayAnimationState);
511 if (command_type == StepBackwardCommand)
512 *state&=(~ForwardAnimationState);
513 if (command_type == StepForwardCommand)
514 *state|=ForwardAnimationState;
515 if (resource_info->title != (char *) NULL)
521 *state|=RepeatAnimationState;
522 *state&=(~AutoReverseAnimationState);
523 *state|=PlayAnimationState;
526 case AutoReverseCommand:
528 *state|=AutoReverseAnimationState;
529 *state&=(~RepeatAnimationState);
530 *state|=PlayAnimationState;
538 status=XSaveImage(display,resource_info,windows,*image);
539 if (status == MagickFalse)
541 XNoticeWidget(display,windows,"Unable to write X image:",
549 resource_info->delay++;
554 if (resource_info->delay == 0)
556 resource_info->delay--;
561 *state=ForwardAnimationState;
562 *state&=(~AutoReverseAnimationState);
567 *state&=(~ForwardAnimationState);
568 *state&=(~AutoReverseAnimationState);
573 XDisplayImageInfo(display,resource_info,windows,(Image *) NULL,*image);
581 XTextViewWidget(display,resource_info,windows,MagickFalse,
582 "Help Viewer - Animate",AnimateHelp);
585 case BrowseDocumentationCommand:
595 Browse the ImageMagick documentation.
597 root_window=XRootWindow(display,XDefaultScreen(display));
598 mozilla_atom=XInternAtom(display,"_MOZILLA_VERSION",MagickFalse);
599 mozilla_window=XWindowByProperty(display,root_window,mozilla_atom);
600 if (mozilla_window != (Window) NULL)
603 command[MaxTextExtent],
607 Display documentation using Netscape remote control.
609 url=GetMagickHomeURL();
610 (void) FormatMagickString(command,MaxTextExtent,
611 "openurl(%s,new-tab)",url);
612 url=DestroyString(url);
613 mozilla_atom=XInternAtom(display,"_MOZILLA_COMMAND",MagickFalse);
614 (void) XChangeProperty(display,mozilla_window,mozilla_atom,
615 XA_STRING,8,PropModeReplace,(unsigned char *) command,
616 (int) strlen(command));
617 XSetCursorState(display,windows,MagickFalse);
620 XSetCursorState(display,windows,MagickTrue);
621 XCheckRefreshWindows(display,windows);
622 status=InvokeDelegate(resource_info->image_info,*image,"browse",
623 (char *) NULL,&(*image)->exception);
624 if (status == MagickFalse)
625 XNoticeWidget(display,windows,"Unable to browse documentation",
627 XDelay(display,1500);
628 XSetCursorState(display,windows,MagickFalse);
633 XNoticeWidget(display,windows,GetMagickVersion((size_t *) NULL),
634 GetMagickCopyright());
642 if (resource_info->confirm_exit == MagickFalse)
643 XClientMessage(display,windows->image.id,windows->im_protocols,
644 windows->im_exit,CurrentTime);
651 Confirm program exit.
653 status=XConfirmWidget(display,windows,"Do you really want to exit",
654 resource_info->client_name);
656 XClientMessage(display,windows->image.id,windows->im_protocols,
657 windows->im_exit,CurrentTime);
668 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
672 + X A n i m a t e B a c k g r o u n d I m a g e %
676 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
678 % XAnimateBackgroundImage() animates an image sequence in the background of
681 % The format of the XAnimateBackgroundImage method is:
683 % void XAnimateBackgroundImage(Display *display,
684 % XResourceInfo *resource_info,Image *images)
686 % A description of each parameter follows:
688 % o display: Specifies a connection to an X server; returned from
691 % o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
693 % o images: the image list.
697 static inline ssize_t MagickMax(const ssize_t x,const ssize_t y)
704 #if defined(__cplusplus) || defined(c_plusplus)
708 static int SceneCompare(const void *x,const void *y)
714 image_1=(const Image **) x;
715 image_2=(const Image **) y;
716 return((int) ((*image_1)->scene-(*image_2)->scene));
719 #if defined(__cplusplus) || defined(c_plusplus)
723 MagickExport void XAnimateBackgroundImage(Display *display,
724 XResourceInfo *resource_info,Image *images)
727 geometry[MaxTextExtent],
728 visual_type[MaxTextExtent];
753 static XStandardColormap
757 *visual_info = (XVisualInfo *) NULL;
785 Determine target window.
787 assert(images != (Image *) NULL);
788 assert(images->signature == MagickSignature);
789 if (images->debug != MagickFalse)
790 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",images->filename);
791 resources=(*resource_info);
792 window_info.id=(Window) NULL;
793 root_window=XRootWindow(display,XDefaultScreen(display));
794 if (LocaleCompare(resources.window_id,"root") == 0)
795 window_info.id=root_window;
798 if (isdigit((int) ((unsigned char) *resources.window_id)) != 0)
799 window_info.id=XWindowByID(display,root_window,
800 (Window) strtol((char *) resources.window_id,(char **) NULL,0));
801 if (window_info.id == (Window) NULL)
803 XWindowByName(display,root_window,resources.window_id);
805 if (window_info.id == (Window) NULL)
807 ThrowXWindowException(XServerError,"NoWindowWithSpecifiedIDExists",
808 resources.window_id);
812 Determine window visual id.
814 window_attributes.width=XDisplayWidth(display,XDefaultScreen(display));
815 window_attributes.height=XDisplayHeight(display,XDefaultScreen(display));
816 (void) CopyMagickString(visual_type,"default",MaxTextExtent);
817 status=XGetWindowAttributes(display,window_info.id,&window_attributes) != 0 ?
818 MagickTrue : MagickFalse;
819 if (status != MagickFalse)
820 (void) FormatMagickString(visual_type,MaxTextExtent,"0x%lx",
821 XVisualIDFromVisual(window_attributes.visual));
822 if (visual_info == (XVisualInfo *) NULL)
825 Allocate standard colormap.
827 map_info=XAllocStandardColormap();
828 if (map_info == (XStandardColormap *) NULL)
829 ThrowXWindowFatalException(ResourceLimitError,"MemoryAllocationFailed",
831 map_info->colormap=(Colormap) NULL;
832 pixel.pixels=(unsigned long *) NULL;
834 Initialize visual info.
836 resources.map_type=(char *) NULL;
837 resources.visual_type=visual_type;
838 visual_info=XBestVisualInfo(display,map_info,&resources);
839 if (visual_info == (XVisualInfo *) NULL)
840 ThrowXWindowFatalException(XServerFatalError,"UnableToGetVisual",
843 Initialize window info.
845 window_info.ximage=(XImage *) NULL;
846 window_info.matte_image=(XImage *) NULL;
847 window_info.pixmap=(Pixmap) NULL;
848 window_info.matte_pixmap=(Pixmap) NULL;
851 Free previous root colors.
853 if (window_info.id == root_window)
854 XDestroyWindowColors(display,root_window);
855 coalesce_image=CoalesceImages(images,&images->exception);
856 if (coalesce_image == (Image *) NULL)
857 ThrowXWindowFatalException(ResourceLimitError,"MemoryAllocationFailed",
859 images=coalesce_image;
860 if (resources.map_type == (char *) NULL)
861 if ((visual_info->klass != TrueColor) &&
862 (visual_info->klass != DirectColor))
868 Determine if the sequence of images has the identical colormap.
870 for (next=images; next != (Image *) NULL; )
872 next->matte=MagickFalse;
873 if ((next->storage_class == DirectClass) ||
874 (next->colors != images->colors) ||
875 (next->colors > (size_t) visual_info->colormap_size))
877 for (i=0; i < (ssize_t) images->colors; i++)
878 if (IsColorEqual(next->colormap+i,images->colormap+i) == MagickFalse)
880 if (i < (ssize_t) images->colors)
882 next=GetNextImageInList(next);
884 if (next != (Image *) NULL)
885 (void) RemapImages(resources.quantize_info,images,(Image *) NULL);
888 Sort images by increasing scene number.
890 number_scenes=GetImageListLength(images);
891 image_list=ImageListToArray(images,&images->exception);
892 if (image_list == (Image **) NULL)
893 ThrowXWindowFatalException(ResourceLimitFatalError,
894 "MemoryAllocationFailed",images->filename);
895 for (i=0; i < (ssize_t) number_scenes; i++)
896 if (image_list[i]->scene == 0)
898 if (i == (ssize_t) number_scenes)
899 qsort((void *) image_list,number_scenes,sizeof(Image *),SceneCompare);
901 Initialize Standard Colormap.
903 resources.colormap=SharedColormap;
904 display_image=image_list[0];
905 for (scene=0; scene < (int) number_scenes; scene++)
907 if ((resource_info->map_type != (char *) NULL) ||
908 (visual_info->klass == TrueColor) ||
909 (visual_info->klass == DirectColor))
910 (void) SetImageType(image_list[scene],image_list[scene]->matte ==
911 MagickFalse ? TrueColorType : TrueColorMatteType);
912 if ((display_image->columns < image_list[scene]->columns) &&
913 (display_image->rows < image_list[scene]->rows))
914 display_image=image_list[scene];
916 if ((resource_info->map_type != (char *) NULL) ||
917 (visual_info->klass == TrueColor) || (visual_info->klass == DirectColor))
918 (void) SetImageType(display_image,display_image->matte == MagickFalse ?
919 TrueColorType : TrueColorMatteType);
920 XMakeStandardColormap(display,visual_info,&resources,display_image,map_info,
923 Graphic context superclass.
925 context_values.background=pixel.background_color.pixel;
926 context_values.foreground=pixel.foreground_color.pixel;
927 pixel.annotate_context=XCreateGC(display,window_info.id,(unsigned long)
928 (GCBackground | GCForeground),&context_values);
929 if (pixel.annotate_context == (GC) NULL)
930 ThrowXWindowFatalException(XServerFatalError,"UnableToCreateGraphicContext",
933 Initialize Image window attributes.
935 XGetWindowInfo(display,visual_info,map_info,&pixel,(XFontStruct *) NULL,
936 &resources,&window_info);
940 window_info.width=(unsigned int) image_list[0]->columns;
941 window_info.height=(unsigned int) image_list[0]->rows;
942 if ((image_list[0]->columns != window_info.width) ||
943 (image_list[0]->rows != window_info.height))
944 ThrowXWindowFatalException(XServerFatalError,"UnableToCreateXImage",
945 image_list[0]->filename);
946 (void) FormatMagickString(geometry,MaxTextExtent,"%ux%u+0+0>",
947 window_attributes.width,window_attributes.height);
948 geometry_info.width=window_info.width;
949 geometry_info.height=window_info.height;
950 geometry_info.x=(ssize_t) window_info.x;
951 geometry_info.y=(ssize_t) window_info.y;
952 (void) ParseMetaGeometry(geometry,&geometry_info.x,&geometry_info.y,
953 &geometry_info.width,&geometry_info.height);
954 window_info.width=(unsigned int) geometry_info.width;
955 window_info.height=(unsigned int) geometry_info.height;
956 window_info.x=(int) geometry_info.x;
957 window_info.y=(int) geometry_info.y;
958 status=XMakeImage(display,&resources,&window_info,image_list[0],
959 window_info.width,window_info.height);
960 if (status == MagickFalse)
961 ThrowXWindowFatalException(XServerFatalError,"UnableToCreateXImage",
965 if (display_image->debug != MagickFalse)
967 (void) LogMagickEvent(X11Event,GetMagickModule(),
968 "Image: %s[%.20g] %.20gx%.20g ",image_list[0]->filename,(double)
969 image_list[0]->scene,(double) image_list[0]->columns,(double)
970 image_list[0]->rows);
971 if (image_list[0]->colors != 0)
972 (void) LogMagickEvent(X11Event,GetMagickModule(),"%.20gc ",(double)
973 image_list[0]->colors);
974 (void) LogMagickEvent(X11Event,GetMagickModule(),"%s",
975 image_list[0]->magick);
978 Adjust image dimensions as specified by backdrop or geometry options.
980 width=window_info.width;
981 height=window_info.height;
982 if (resources.backdrop != MagickFalse)
985 Center image on window.
987 window_info.x=(int) (window_attributes.width/2)-
988 (window_info.ximage->width/2);
989 window_info.y=(int) (window_attributes.height/2)-
990 (window_info.ximage->height/2);
991 width=(unsigned int) window_attributes.width;
992 height=(unsigned int) window_attributes.height;
994 if (resources.image_geometry != (char *) NULL)
997 default_geometry[MaxTextExtent];
1007 User specified geometry.
1009 size_hints=XAllocSizeHints();
1010 if (size_hints == (XSizeHints *) NULL)
1011 ThrowXWindowFatalException(ResourceLimitFatalError,
1012 "MemoryAllocationFailed",images->filename);
1013 size_hints->flags=0L;
1014 (void) FormatMagickString(default_geometry,MaxTextExtent,"%ux%u",width,
1016 flags=XWMGeometry(display,visual_info->screen,resources.image_geometry,
1017 default_geometry,window_info.border_width,size_hints,&window_info.x,
1018 &window_info.y,(int *) &width,(int *) &height,&gravity);
1019 if (((flags & (XValue | YValue))) != 0)
1021 width=(unsigned int) window_attributes.width;
1022 height=(unsigned int) window_attributes.height;
1024 (void) XFree((void *) size_hints);
1027 Create the X pixmap.
1029 window_info.pixmap=XCreatePixmap(display,window_info.id,(unsigned int) width,
1030 (unsigned int) height,window_info.depth);
1031 if (window_info.pixmap == (Pixmap) NULL)
1032 ThrowXWindowFatalException(XServerFatalError,"UnableToCreateXPixmap",
1035 Display pixmap on the window.
1037 if (((unsigned int) width > window_info.width) ||
1038 ((unsigned int) height > window_info.height))
1039 (void) XFillRectangle(display,window_info.pixmap,
1040 window_info.annotate_context,0,0,(unsigned int) width,
1041 (unsigned int) height);
1042 (void) XPutImage(display,window_info.pixmap,window_info.annotate_context,
1043 window_info.ximage,0,0,window_info.x,window_info.y,window_info.width,
1044 window_info.height);
1045 (void) XSetWindowBackgroundPixmap(display,window_info.id,window_info.pixmap);
1046 (void) XClearWindow(display,window_info.id);
1048 Initialize image pixmaps structure.
1050 window_info.pixmaps=(Pixmap *) AcquireQuantumMemory(number_scenes,
1051 sizeof(*window_info.pixmaps));
1052 window_info.matte_pixmaps=(Pixmap *) AcquireQuantumMemory(number_scenes,
1053 sizeof(*window_info.matte_pixmaps));
1054 if ((window_info.pixmaps == (Pixmap *) NULL) ||
1055 (window_info.matte_pixmaps == (Pixmap *) NULL))
1056 ThrowXWindowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed",
1058 window_info.pixmaps[0]=window_info.pixmap;
1059 window_info.matte_pixmaps[0]=window_info.pixmap;
1060 for (scene=1; scene < (int) number_scenes; scene++)
1069 window_info.pixmap=(Pixmap) NULL;
1070 window_info.matte_pixmap=(Pixmap) NULL;
1071 if ((resources.map_type != (char *) NULL) ||
1072 (visual_info->klass == TrueColor) ||
1073 (visual_info->klass == DirectColor))
1074 if (image_list[scene]->storage_class == PseudoClass)
1075 XGetPixelPacket(display,visual_info,map_info,&resources,
1076 image_list[scene],window_info.pixel_info);
1077 columns=(unsigned int) image_list[scene]->columns;
1078 rows=(unsigned int) image_list[scene]->rows;
1079 if ((image_list[scene]->columns != columns) ||
1080 (image_list[scene]->rows != rows))
1081 ThrowXWindowFatalException(XServerFatalError,"UnableToCreateXImage",
1082 image_list[scene]->filename);
1083 status=XMakeImage(display,&resources,&window_info,image_list[scene],
1085 if (status == MagickFalse)
1086 ThrowXWindowFatalException(XServerFatalError,"UnableToCreateXImage",
1088 if (display_image->debug != MagickFalse)
1090 (void) LogMagickEvent(X11Event,GetMagickModule(),
1091 "Image: [%.20g] %s %.20gx%.20g ",(double) image_list[scene]->scene,
1092 image_list[scene]->filename,(double) columns,(double) rows);
1093 if (image_list[scene]->colors != 0)
1094 (void) LogMagickEvent(X11Event,GetMagickModule(),"%.20gc ",(double)
1095 image_list[scene]->colors);
1096 (void) LogMagickEvent(X11Event,GetMagickModule(),"%s",
1097 image_list[scene]->magick);
1100 Create the X pixmap.
1102 window_info.pixmap=XCreatePixmap(display,window_info.id,width,height,
1104 if (window_info.pixmap == (Pixmap) NULL)
1105 ThrowXWindowFatalException(XServerFatalError,"UnableToCreateXPixmap",
1108 Display pixmap on the window.
1110 if ((width > window_info.width) || (height > window_info.height))
1111 (void) XFillRectangle(display,window_info.pixmap,
1112 window_info.annotate_context,0,0,width,height);
1113 (void) XPutImage(display,window_info.pixmap,window_info.annotate_context,
1114 window_info.ximage,0,0,window_info.x,window_info.y,window_info.width,
1115 window_info.height);
1116 (void) XSetWindowBackgroundPixmap(display,window_info.id,
1117 window_info.pixmap);
1118 (void) XClearWindow(display,window_info.id);
1119 window_info.pixmaps[scene]=window_info.pixmap;
1120 window_info.matte_pixmaps[scene]=window_info.matte_pixmap;
1121 if (image_list[scene]->matte)
1122 (void) XClearWindow(display,window_info.id);
1123 delay=1000*image_list[scene]->delay/MagickMax(
1124 image_list[scene]->ticks_per_second,1L);
1125 XDelay(display,resources.delay*(delay == 0 ? 10 : delay));
1127 window_info.pixel_info=(&pixel);
1129 Display pixmap on the window.
1131 (void) XSelectInput(display,window_info.id,SubstructureNotifyMask);
1135 for (scene=0; scene < (int) number_scenes; scene++)
1137 if (XEventsQueued(display,QueuedAfterFlush) > 0)
1139 (void) XNextEvent(display,&event);
1140 if (event.type == DestroyNotify)
1143 window_info.pixmap=window_info.pixmaps[scene];
1144 window_info.matte_pixmap=window_info.matte_pixmaps[scene];
1145 (void) XSetWindowBackgroundPixmap(display,window_info.id,
1146 window_info.pixmap);
1147 (void) XClearWindow(display,window_info.id);
1148 (void) XSync(display,MagickFalse);
1149 delay=1000*image_list[scene]->delay/MagickMax(
1150 image_list[scene]->ticks_per_second,1L);
1151 XDelay(display,resources.delay*(delay == 0 ? 10 : delay));
1153 } while (event.type != DestroyNotify);
1154 (void) XSync(display,MagickFalse);
1155 image_list=(Image **) RelinquishMagickMemory(image_list);
1156 images=DestroyImageList(images);
1160 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1164 + X A n i m a t e I m a g e s %
1168 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1170 % XAnimateImages() displays an image via X11.
1172 % The format of the XAnimateImages method is:
1174 % Image *XAnimateImages(Display *display,XResourceInfo *resource_info,
1175 % char **argv,const int argc,Image *images)
1177 % A description of each parameter follows:
1179 % o display: Specifies a connection to an X server; returned from
1182 % o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
1184 % o argv: Specifies the application's argument list.
1186 % o argc: Specifies the number of arguments.
1188 % o images: the image list.
1191 MagickExport Image *XAnimateImages(Display *display,
1192 XResourceInfo *resource_info,char **argv,const int argc,Image *images)
1194 #define MagickMenus 4
1195 #define MaXWindows 8
1196 #define MagickTitle "Commands"
1234 "Browse Documentation",
1240 **Menus[MagickMenus]=
1248 static const CommandType
1272 DirectionCommands[]=
1280 BrowseDocumentationCommand,
1284 static const CommandType
1285 *Commands[MagickMenus]=
1294 command[MaxTextExtent],
1296 geometry[MaxTextExtent],
1297 resource_name[MaxTextExtent];
1334 working_directory[MaxTextExtent];
1340 *magick_windows[MaXWindows];
1394 assert(images != (Image *) NULL);
1395 assert(images->signature == MagickSignature);
1396 if (images->debug != MagickFalse)
1397 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",images->filename);
1398 warning_handler=(WarningHandler) NULL;
1399 windows=XSetWindows((XWindows *) ~0);
1400 if (windows != (XWindows *) NULL)
1405 status=chdir(working_directory);
1407 (void) ThrowMagickException(&images->exception,GetMagickModule(),
1408 FileOpenError,"UnableToOpenFile","%s",working_directory);
1409 warning_handler=resource_info->display_warnings ?
1410 SetErrorHandler(XWarning) : SetErrorHandler((ErrorHandler) NULL);
1411 warning_handler=resource_info->display_warnings ?
1412 SetWarningHandler(XWarning) : SetWarningHandler((WarningHandler) NULL);
1420 Initialize window structure.
1422 for (p=images; p != (Image *) NULL; p=GetNextImageInList(p))
1424 if (p->storage_class == DirectClass)
1426 resource_info->colors=0;
1429 if (p->colors > resource_info->colors)
1430 resource_info->colors=p->colors;
1432 windows=XSetWindows(XInitializeWindows(display,resource_info));
1433 if (windows == (XWindows *) NULL)
1434 ThrowXWindowFatalException(XServerFatalError,"MemoryAllocationFailed",
1437 Initialize window id's.
1440 magick_windows[number_windows++]=(&windows->icon);
1441 magick_windows[number_windows++]=(&windows->backdrop);
1442 magick_windows[number_windows++]=(&windows->image);
1443 magick_windows[number_windows++]=(&windows->info);
1444 magick_windows[number_windows++]=(&windows->command);
1445 magick_windows[number_windows++]=(&windows->widget);
1446 magick_windows[number_windows++]=(&windows->popup);
1447 for (i=0; i < (ssize_t) number_windows; i++)
1448 magick_windows[i]->id=(Window) NULL;
1451 Initialize font info.
1453 if (windows->font_info != (XFontStruct *) NULL)
1454 (void) XFreeFont(display,windows->font_info);
1455 windows->font_info=XBestFont(display,resource_info,MagickFalse);
1456 if (windows->font_info == (XFontStruct *) NULL)
1457 ThrowXWindowFatalException(XServerFatalError,"UnableToLoadFont",
1458 resource_info->font);
1460 Initialize Standard Colormap.
1462 map_info=windows->map_info;
1463 icon_map=windows->icon_map;
1464 visual_info=windows->visual_info;
1465 icon_visual=windows->icon_visual;
1466 pixel=windows->pixel_info;
1467 icon_pixel=windows->icon_pixel;
1468 font_info=windows->font_info;
1469 icon_resources=windows->icon_resources;
1470 class_hints=windows->class_hints;
1471 manager_hints=windows->manager_hints;
1472 root_window=XRootWindow(display,visual_info->screen);
1473 coalesce_image=CoalesceImages(images,&images->exception);
1474 if (coalesce_image == (Image *) NULL)
1475 ThrowXWindowFatalException(XServerFatalError,"MemoryAllocationFailed",
1477 images=coalesce_image;
1478 if (resource_info->map_type == (char *) NULL)
1479 if ((visual_info->klass != TrueColor) &&
1480 (visual_info->klass != DirectColor))
1486 Determine if the sequence of images has the identical colormap.
1488 for (next=images; next != (Image *) NULL; )
1490 next->matte=MagickFalse;
1491 if ((next->storage_class == DirectClass) ||
1492 (next->colors != images->colors) ||
1493 (next->colors > (size_t) visual_info->colormap_size))
1495 for (i=0; i < (ssize_t) images->colors; i++)
1496 if (IsColorEqual(next->colormap+i,images->colormap+i) == MagickFalse)
1498 if (i < (ssize_t) images->colors)
1500 next=GetNextImageInList(next);
1502 if (next != (Image *) NULL)
1503 (void) RemapImages(resource_info->quantize_info,images,
1507 Sort images by increasing scene number.
1509 number_scenes=GetImageListLength(images);
1510 image_list=ImageListToArray(images,&images->exception);
1511 if (image_list == (Image **) NULL)
1512 ThrowXWindowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed",
1514 for (scene=0; scene < (ssize_t) number_scenes; scene++)
1515 if (image_list[scene]->scene == 0)
1517 if (scene == (ssize_t) number_scenes)
1518 qsort((void *) image_list,number_scenes,sizeof(Image *),SceneCompare);
1520 Initialize Standard Colormap.
1522 nexus=NewImageList();
1523 display_image=image_list[0];
1524 for (scene=0; scene < (ssize_t) number_scenes; scene++)
1526 if ((resource_info->map_type != (char *) NULL) ||
1527 (visual_info->klass == TrueColor) ||
1528 (visual_info->klass == DirectColor))
1529 (void) SetImageType(image_list[scene],image_list[scene]->matte ==
1530 MagickFalse ? TrueColorType : TrueColorMatteType);
1531 if ((display_image->columns < image_list[scene]->columns) &&
1532 (display_image->rows < image_list[scene]->rows))
1533 display_image=image_list[scene];
1535 if (display_image->debug != MagickFalse)
1537 (void) LogMagickEvent(X11Event,GetMagickModule(),
1538 "Image: %s[%.20g] %.20gx%.20g ",display_image->filename,(double)
1539 display_image->scene,(double) display_image->columns,(double)
1540 display_image->rows);
1541 if (display_image->colors != 0)
1542 (void) LogMagickEvent(X11Event,GetMagickModule(),"%.20gc ",(double)
1543 display_image->colors);
1544 (void) LogMagickEvent(X11Event,GetMagickModule(),"%s",
1545 display_image->magick);
1547 XMakeStandardColormap(display,visual_info,resource_info,display_image,
1550 Initialize graphic context.
1552 windows->context.id=(Window) NULL;
1553 XGetWindowInfo(display,visual_info,map_info,pixel,font_info,
1554 resource_info,&windows->context);
1555 (void) CloneString(&class_hints->res_name,resource_info->client_name);
1556 (void) CloneString(&class_hints->res_class,resource_info->client_name);
1557 class_hints->res_class[0]=(char) toupper((int) class_hints->res_class[0]);
1558 manager_hints->flags=InputHint | StateHint;
1559 manager_hints->input=MagickFalse;
1560 manager_hints->initial_state=WithdrawnState;
1561 XMakeWindow(display,root_window,argv,argc,class_hints,manager_hints,
1563 if (display_image->debug != MagickFalse)
1564 (void) LogMagickEvent(X11Event,GetMagickModule(),
1565 "Window id: 0x%lx (context)",windows->context.id);
1566 context_values.background=pixel->background_color.pixel;
1567 context_values.font=font_info->fid;
1568 context_values.foreground=pixel->foreground_color.pixel;
1569 context_values.graphics_exposures=MagickFalse;
1570 context_mask=(MagickStatusType)
1571 (GCBackground | GCFont | GCForeground | GCGraphicsExposures);
1572 if (pixel->annotate_context != (GC) NULL)
1573 (void) XFreeGC(display,pixel->annotate_context);
1574 pixel->annotate_context=
1575 XCreateGC(display,windows->context.id,context_mask,&context_values);
1576 if (pixel->annotate_context == (GC) NULL)
1577 ThrowXWindowFatalException(XServerFatalError,"UnableToCreateGraphicContext",
1579 context_values.background=pixel->depth_color.pixel;
1580 if (pixel->widget_context != (GC) NULL)
1581 (void) XFreeGC(display,pixel->widget_context);
1582 pixel->widget_context=
1583 XCreateGC(display,windows->context.id,context_mask,&context_values);
1584 if (pixel->widget_context == (GC) NULL)
1585 ThrowXWindowFatalException(XServerFatalError,"UnableToCreateGraphicContext",
1587 context_values.background=pixel->foreground_color.pixel;
1588 context_values.foreground=pixel->background_color.pixel;
1589 context_values.plane_mask=
1590 context_values.background ^ context_values.foreground;
1591 if (pixel->highlight_context != (GC) NULL)
1592 (void) XFreeGC(display,pixel->highlight_context);
1593 pixel->highlight_context=XCreateGC(display,windows->context.id,
1594 (size_t) (context_mask | GCPlaneMask),&context_values);
1595 if (pixel->highlight_context == (GC) NULL)
1596 ThrowXWindowFatalException(XServerFatalError,"UnableToCreateGraphicContext",
1598 (void) XDestroyWindow(display,windows->context.id);
1600 Initialize icon window.
1602 XGetWindowInfo(display,icon_visual,icon_map,icon_pixel,(XFontStruct *) NULL,
1603 icon_resources,&windows->icon);
1604 windows->icon.geometry=resource_info->icon_geometry;
1605 XBestIconSize(display,&windows->icon,display_image);
1606 windows->icon.attributes.colormap=
1607 XDefaultColormap(display,icon_visual->screen);
1608 windows->icon.attributes.event_mask=ExposureMask | StructureNotifyMask;
1609 manager_hints->flags=InputHint | StateHint;
1610 manager_hints->input=MagickFalse;
1611 manager_hints->initial_state=IconicState;
1612 XMakeWindow(display,root_window,argv,argc,class_hints,manager_hints,
1614 if (display_image->debug != MagickFalse)
1615 (void) LogMagickEvent(X11Event,GetMagickModule(),"Window id: 0x%lx (icon)",
1618 Initialize graphic context for icon window.
1620 if (icon_pixel->annotate_context != (GC) NULL)
1621 (void) XFreeGC(display,icon_pixel->annotate_context);
1622 context_values.background=icon_pixel->background_color.pixel;
1623 context_values.foreground=icon_pixel->foreground_color.pixel;
1624 icon_pixel->annotate_context=XCreateGC(display,windows->icon.id,
1625 (size_t) (GCBackground | GCForeground),&context_values);
1626 if (icon_pixel->annotate_context == (GC) NULL)
1627 ThrowXWindowFatalException(XServerFatalError,"UnableToCreateGraphicContext",
1629 windows->icon.annotate_context=icon_pixel->annotate_context;
1631 Initialize Image window.
1633 XGetWindowInfo(display,visual_info,map_info,pixel,font_info,
1634 resource_info,&windows->image);
1635 windows->image.shape=MagickTrue; /* non-rectangular shape hint */
1636 if (resource_info->use_shared_memory == MagickFalse)
1637 windows->image.shared_memory=MagickFalse;
1638 if (resource_info->title != (char *) NULL)
1643 title=InterpretImageProperties(resource_info->image_info,display_image,
1644 resource_info->title);
1645 (void) CopyMagickString(windows->image.name,title,MaxTextExtent);
1646 (void) CopyMagickString(windows->image.icon_name,title,MaxTextExtent);
1647 title=DestroyString(title);
1652 filename[MaxTextExtent];
1655 Window name is the base of the filename.
1657 GetPathComponent(display_image->magick_filename,TailPath,filename);
1658 (void) FormatMagickString(windows->image.name,MaxTextExtent,
1659 "%s: %s[%.20g of %.20g]",MagickPackageName,filename,(double)
1660 display_image->scene,(double) number_scenes);
1661 (void) CopyMagickString(windows->image.icon_name,filename,MaxTextExtent);
1663 if (resource_info->immutable != MagickFalse)
1664 windows->image.immutable=MagickTrue;
1665 windows->image.shape=MagickTrue;
1666 windows->image.geometry=resource_info->image_geometry;
1667 (void) FormatMagickString(geometry,MaxTextExtent,"%ux%u+0+0>!",
1668 XDisplayWidth(display,visual_info->screen),
1669 XDisplayHeight(display,visual_info->screen));
1670 geometry_info.width=display_image->columns;
1671 geometry_info.height=display_image->rows;
1674 (void) ParseMetaGeometry(geometry,&geometry_info.x,&geometry_info.y,
1675 &geometry_info.width,&geometry_info.height);
1676 windows->image.width=(unsigned int) geometry_info.width;
1677 windows->image.height=(unsigned int) geometry_info.height;
1678 windows->image.attributes.event_mask=ButtonMotionMask | ButtonPressMask |
1679 ButtonReleaseMask | EnterWindowMask | ExposureMask | KeyPressMask |
1680 KeyReleaseMask | LeaveWindowMask | OwnerGrabButtonMask |
1681 PropertyChangeMask | StructureNotifyMask | SubstructureNotifyMask;
1682 XGetWindowInfo(display,visual_info,map_info,pixel,font_info,
1683 resource_info,&windows->backdrop);
1684 if ((resource_info->backdrop) || (windows->backdrop.id != (Window) NULL))
1687 Initialize backdrop window.
1689 windows->backdrop.x=0;
1690 windows->backdrop.y=0;
1691 (void) CloneString(&windows->backdrop.name,"ImageMagick Backdrop");
1692 windows->backdrop.flags=(size_t) (USSize | USPosition);
1693 windows->backdrop.width=(unsigned int)
1694 XDisplayWidth(display,visual_info->screen);
1695 windows->backdrop.height=(unsigned int)
1696 XDisplayHeight(display,visual_info->screen);
1697 windows->backdrop.border_width=0;
1698 windows->backdrop.immutable=MagickTrue;
1699 windows->backdrop.attributes.do_not_propagate_mask=ButtonPressMask |
1701 windows->backdrop.attributes.event_mask=ButtonPressMask | KeyPressMask |
1702 StructureNotifyMask;
1703 manager_hints->flags=IconWindowHint | InputHint | StateHint;
1704 manager_hints->icon_window=windows->icon.id;
1705 manager_hints->input=MagickTrue;
1706 manager_hints->initial_state=
1707 resource_info->iconic ? IconicState : NormalState;
1708 XMakeWindow(display,root_window,argv,argc,class_hints,manager_hints,
1709 &windows->backdrop);
1710 if (display_image->debug != MagickFalse)
1711 (void) LogMagickEvent(X11Event,GetMagickModule(),
1712 "Window id: 0x%lx (backdrop)",windows->backdrop.id);
1713 (void) XMapWindow(display,windows->backdrop.id);
1714 (void) XClearWindow(display,windows->backdrop.id);
1715 if (windows->image.id != (Window) NULL)
1717 (void) XDestroyWindow(display,windows->image.id);
1718 windows->image.id=(Window) NULL;
1721 Position image in the center the backdrop.
1723 windows->image.flags|=USPosition;
1724 windows->image.x=(XDisplayWidth(display,visual_info->screen)/2)-
1725 (windows->image.width/2);
1726 windows->image.y=(XDisplayHeight(display,visual_info->screen)/2)-
1727 (windows->image.height/2);
1729 manager_hints->flags=IconWindowHint | InputHint | StateHint;
1730 manager_hints->icon_window=windows->icon.id;
1731 manager_hints->input=MagickTrue;
1732 manager_hints->initial_state=
1733 resource_info->iconic ? IconicState : NormalState;
1734 if (windows->group_leader.id != (Window) NULL)
1739 manager_hints->flags|=(MagickStatusType) WindowGroupHint;
1740 manager_hints->window_group=windows->group_leader.id;
1741 (void) XSelectInput(display,windows->group_leader.id,StructureNotifyMask);
1742 if (display_image->debug != MagickFalse)
1743 (void) LogMagickEvent(X11Event,GetMagickModule(),
1744 "Window id: 0x%lx (group leader)",windows->group_leader.id);
1746 XMakeWindow(display,
1747 (Window) (resource_info->backdrop ? windows->backdrop.id : root_window),
1748 argv,argc,class_hints,manager_hints,&windows->image);
1749 (void) XChangeProperty(display,windows->image.id,windows->im_protocols,
1750 XA_STRING,8,PropModeReplace,(unsigned char *) NULL,0);
1751 if (windows->group_leader.id != (Window) NULL)
1752 (void) XSetTransientForHint(display,windows->image.id,
1753 windows->group_leader.id);
1754 if (display_image->debug != MagickFalse)
1755 (void) LogMagickEvent(X11Event,GetMagickModule(),"Window id: 0x%lx (image)",
1758 Initialize Info widget.
1760 XGetWindowInfo(display,visual_info,map_info,pixel,font_info,
1761 resource_info,&windows->info);
1762 (void) CloneString(&windows->info.name,"Info");
1763 (void) CloneString(&windows->info.icon_name,"Info");
1764 windows->info.border_width=1;
1767 windows->info.flags|=PPosition;
1768 windows->info.attributes.win_gravity=UnmapGravity;
1769 windows->info.attributes.event_mask=ButtonPressMask | ExposureMask |
1770 StructureNotifyMask;
1771 manager_hints->flags=InputHint | StateHint | WindowGroupHint;
1772 manager_hints->input=MagickFalse;
1773 manager_hints->initial_state=NormalState;
1774 manager_hints->window_group=windows->image.id;
1775 XMakeWindow(display,windows->image.id,argv,argc,class_hints,manager_hints,
1777 windows->info.highlight_stipple=XCreateBitmapFromData(display,
1778 windows->info.id,(char *) HighlightBitmap,HighlightWidth,HighlightHeight);
1779 windows->info.shadow_stipple=XCreateBitmapFromData(display,
1780 windows->info.id,(char *) ShadowBitmap,ShadowWidth,ShadowHeight);
1781 (void) XSetTransientForHint(display,windows->info.id,windows->image.id);
1782 if (windows->image.mapped)
1783 (void) XWithdrawWindow(display,windows->info.id,windows->info.screen);
1784 if (display_image->debug != MagickFalse)
1785 (void) LogMagickEvent(X11Event,GetMagickModule(),"Window id: 0x%lx (info)",
1788 Initialize Command widget.
1790 XGetWindowInfo(display,visual_info,map_info,pixel,font_info,
1791 resource_info,&windows->command);
1792 windows->command.data=MagickMenus;
1793 (void) XCommandWidget(display,windows,CommandMenu,(XEvent *) NULL);
1794 (void) FormatMagickString(resource_name,MaxTextExtent,"%s.command",
1795 resource_info->client_name);
1796 windows->command.geometry=XGetResourceClass(resource_info->resource_database,
1797 resource_name,"geometry",(char *) NULL);
1798 (void) CloneString(&windows->command.name,MagickTitle);
1799 windows->command.border_width=0;
1800 windows->command.flags|=PPosition;
1801 windows->command.attributes.event_mask=ButtonMotionMask | ButtonPressMask |
1802 ButtonReleaseMask | EnterWindowMask | ExposureMask | LeaveWindowMask |
1803 OwnerGrabButtonMask | StructureNotifyMask;
1804 manager_hints->flags=InputHint | StateHint | WindowGroupHint;
1805 manager_hints->input=MagickTrue;
1806 manager_hints->initial_state=NormalState;
1807 manager_hints->window_group=windows->image.id;
1808 XMakeWindow(display,root_window,argv,argc,class_hints,manager_hints,
1810 windows->command.highlight_stipple=XCreateBitmapFromData(display,
1811 windows->command.id,(char *) HighlightBitmap,HighlightWidth,
1813 windows->command.shadow_stipple=XCreateBitmapFromData(display,
1814 windows->command.id,(char *) ShadowBitmap,ShadowWidth,ShadowHeight);
1815 (void) XSetTransientForHint(display,windows->command.id,windows->image.id);
1816 if (display_image->debug != MagickFalse)
1817 (void) LogMagickEvent(X11Event,GetMagickModule(),
1818 "Window id: 0x%lx (command)",windows->command.id);
1820 Initialize Widget window.
1822 XGetWindowInfo(display,visual_info,map_info,pixel,font_info,
1823 resource_info,&windows->widget);
1824 (void) FormatMagickString(resource_name,MaxTextExtent,"%s.widget",
1825 resource_info->client_name);
1826 windows->widget.geometry=XGetResourceClass(resource_info->resource_database,
1827 resource_name,"geometry",(char *) NULL);
1828 windows->widget.border_width=0;
1829 windows->widget.flags|=PPosition;
1830 windows->widget.attributes.event_mask=ButtonMotionMask | ButtonPressMask |
1831 ButtonReleaseMask | EnterWindowMask | ExposureMask | KeyPressMask |
1832 KeyReleaseMask | LeaveWindowMask | OwnerGrabButtonMask |
1833 StructureNotifyMask;
1834 manager_hints->flags=InputHint | StateHint | WindowGroupHint;
1835 manager_hints->input=MagickTrue;
1836 manager_hints->initial_state=NormalState;
1837 manager_hints->window_group=windows->image.id;
1838 XMakeWindow(display,root_window,argv,argc,class_hints,manager_hints,
1840 windows->widget.highlight_stipple=XCreateBitmapFromData(display,
1841 windows->widget.id,(char *) HighlightBitmap,HighlightWidth,HighlightHeight);
1842 windows->widget.shadow_stipple=XCreateBitmapFromData(display,
1843 windows->widget.id,(char *) ShadowBitmap,ShadowWidth,ShadowHeight);
1844 (void) XSetTransientForHint(display,windows->widget.id,windows->image.id);
1845 if (display_image->debug != MagickFalse)
1846 (void) LogMagickEvent(X11Event,GetMagickModule(),
1847 "Window id: 0x%lx (widget)",windows->widget.id);
1849 Initialize popup window.
1851 XGetWindowInfo(display,visual_info,map_info,pixel,font_info,
1852 resource_info,&windows->popup);
1853 windows->popup.border_width=0;
1854 windows->popup.flags|=PPosition;
1855 windows->popup.attributes.event_mask=ButtonMotionMask | ButtonPressMask |
1856 ButtonReleaseMask | EnterWindowMask | ExposureMask | KeyPressMask |
1857 KeyReleaseMask | LeaveWindowMask | StructureNotifyMask;
1858 manager_hints->flags=InputHint | StateHint | WindowGroupHint;
1859 manager_hints->input=MagickTrue;
1860 manager_hints->initial_state=NormalState;
1861 manager_hints->window_group=windows->image.id;
1862 XMakeWindow(display,root_window,argv,argc,class_hints,manager_hints,
1864 windows->popup.highlight_stipple=XCreateBitmapFromData(display,
1865 windows->popup.id,(char *) HighlightBitmap,HighlightWidth,HighlightHeight);
1866 windows->popup.shadow_stipple=XCreateBitmapFromData(display,
1867 windows->popup.id,(char *) ShadowBitmap,ShadowWidth,ShadowHeight);
1868 (void) XSetTransientForHint(display,windows->popup.id,windows->image.id);
1869 if (display_image->debug != MagickFalse)
1870 (void) LogMagickEvent(X11Event,GetMagickModule(),
1871 "Window id: 0x%lx (pop up)",windows->popup.id);
1873 Set out progress and warning handlers.
1875 if (warning_handler == (WarningHandler) NULL)
1877 warning_handler=resource_info->display_warnings ?
1878 SetErrorHandler(XWarning) : SetErrorHandler((ErrorHandler) NULL);
1879 warning_handler=resource_info->display_warnings ?
1880 SetWarningHandler(XWarning) : SetWarningHandler((WarningHandler) NULL);
1883 Initialize X image structure.
1888 Initialize image pixmaps structure.
1890 window_changes.width=(int) windows->image.width;
1891 window_changes.height=(int) windows->image.height;
1892 (void) XReconfigureWMWindow(display,windows->image.id,windows->command.screen,
1893 (unsigned int) (CWWidth | CWHeight),&window_changes);
1894 windows->image.pixmaps=(Pixmap *) AcquireQuantumMemory(number_scenes,
1895 sizeof(*windows->image.pixmaps));
1896 windows->image.matte_pixmaps=(Pixmap *) AcquireQuantumMemory(number_scenes,
1897 sizeof(*windows->image.pixmaps));
1898 if ((windows->image.pixmaps == (Pixmap *) NULL) ||
1899 (windows->image.matte_pixmaps == (Pixmap *) NULL))
1900 ThrowXWindowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed",
1902 if ((windows->image.mapped == MagickFalse) ||
1903 (windows->backdrop.id != (Window) NULL))
1904 (void) XMapWindow(display,windows->image.id);
1905 XSetCursorState(display,windows,MagickTrue);
1906 for (scene=0; scene < (ssize_t) number_scenes; scene++)
1915 (void) TransformImageColorspace(image_list[scene],RGBColorspace);
1916 windows->image.pixmap=(Pixmap) NULL;
1917 windows->image.matte_pixmap=(Pixmap) NULL;
1918 if ((resource_info->map_type != (char *) NULL) ||
1919 (visual_info->klass == TrueColor) ||
1920 (visual_info->klass == DirectColor))
1921 if (image_list[scene]->storage_class == PseudoClass)
1922 XGetPixelPacket(display,visual_info,map_info,resource_info,
1923 image_list[scene],windows->image.pixel_info);
1924 columns=(unsigned int) image_list[scene]->columns;
1925 rows=(unsigned int) image_list[scene]->rows;
1926 if ((image_list[scene]->columns != columns) ||
1927 (image_list[scene]->rows != rows))
1928 ThrowXWindowFatalException(XServerFatalError,"UnableToCreateXImage",
1929 image_list[scene]->filename);
1930 status=XMakeImage(display,resource_info,&windows->image,image_list[scene],
1932 if (status == MagickFalse)
1933 ThrowXWindowFatalException(XServerFatalError,"UnableToCreateXImage",
1935 if (image_list[scene]->debug != MagickFalse)
1937 (void) LogMagickEvent(X11Event,GetMagickModule(),
1938 "Image: [%.20g] %s %.20gx%.20g ",(double) image_list[scene]->scene,
1939 image_list[scene]->filename,(double) columns,(double) rows);
1940 if (image_list[scene]->colors != 0)
1941 (void) LogMagickEvent(X11Event,GetMagickModule(),"%.20gc ",(double)
1942 image_list[scene]->colors);
1943 (void) LogMagickEvent(X11Event,GetMagickModule(),"%s",
1944 image_list[scene]->magick);
1947 Window name is the base of the filename.
1949 if (resource_info->title != (char *) NULL)
1954 title=InterpretImageProperties(resource_info->image_info,
1955 image_list[scene],resource_info->title);
1956 (void) CopyMagickString(windows->image.name,title,MaxTextExtent);
1957 title=DestroyString(title);
1961 p=image_list[scene]->magick_filename+
1962 strlen(image_list[scene]->magick_filename)-1;
1963 while ((p > image_list[scene]->magick_filename) && (*(p-1) != '/'))
1965 (void) FormatMagickString(windows->image.name,MaxTextExtent,
1966 "%s: %s[%.20g of %.20g]",MagickPackageName,p,(double) scene+1,
1967 (double) number_scenes);
1969 status=XStringListToTextProperty(&windows->image.name,1,&window_name);
1970 if (status != Success)
1972 XSetWMName(display,windows->image.id,&window_name);
1973 (void) XFree((void *) window_name.value);
1975 windows->image.pixmaps[scene]=windows->image.pixmap;
1976 windows->image.matte_pixmaps[scene]=windows->image.matte_pixmap;
1981 event.xexpose.width=(int) image_list[scene]->columns;
1982 event.xexpose.height=(int) image_list[scene]->rows;
1983 XRefreshWindow(display,&windows->image,&event);
1984 (void) XSync(display,MagickFalse);
1987 XSetCursorState(display,windows,MagickFalse);
1988 if (windows->command.mapped)
1989 (void) XMapRaised(display,windows->command.id);
1993 nexus=NewImageList();
1997 image=image_list[0];
1998 state=(MagickStatusType) (ForwardAnimationState | RepeatAnimationState);
1999 (void) XMagickCommand(display,resource_info,windows,PlayCommand,&images,
2003 if (XEventsQueued(display,QueuedAfterFlush) == 0)
2004 if ((state & PlayAnimationState) || (state & StepAnimationState))
2010 delay=1000*image->delay/MagickMax(image->ticks_per_second,1L);
2011 XDelay(display,resource_info->delay*(delay == 0 ? 10 : delay));
2012 if (state & ForwardAnimationState)
2015 Forward animation: increment scene number.
2017 if (scene < ((ssize_t) number_scenes-1))
2022 if (iterations == (ssize_t) image_list[0]->iterations)
2027 if ((state & AutoReverseAnimationState) != 0)
2029 state&=(~ForwardAnimationState);
2034 if ((state & RepeatAnimationState) == 0)
2035 state&=(~PlayAnimationState);
2044 Reverse animation: decrement scene number.
2046 if (scene > first_scene)
2051 if (iterations == (ssize_t) image_list[0]->iterations)
2054 state&=(~RepeatAnimationState);
2056 if (state & AutoReverseAnimationState)
2058 state|=ForwardAnimationState;
2064 if ((state & RepeatAnimationState) == MagickFalse)
2065 state&=(~PlayAnimationState);
2066 scene=(ssize_t) number_scenes-1;
2070 scene=MagickMax(scene,0);
2071 image=image_list[scene];
2072 if ((image != (Image *) NULL) && (image->start_loop != 0))
2074 if ((state & StepAnimationState) ||
2075 (resource_info->title != (char *) NULL))
2078 Update window title.
2080 p=image_list[scene]->filename+
2081 strlen(image_list[scene]->filename)-1;
2082 while ((p > image_list[scene]->filename) && (*(p-1) != '/'))
2084 (void) FormatMagickString(windows->image.name,MaxTextExtent,
2085 "%s: %s[%.20g of %.20g]",MagickPackageName,p,(double)
2086 scene+1,(double) number_scenes);
2087 if (resource_info->title != (char *) NULL)
2092 title=InterpretImageProperties(resource_info->image_info,
2093 image,resource_info->title);
2094 (void) CopyMagickString(windows->image.name,title,
2096 title=DestroyString(title);
2098 status=XStringListToTextProperty(&windows->image.name,1,
2100 if (status != Success)
2102 XSetWMName(display,windows->image.id,&window_name);
2103 (void) XFree((void *) window_name.value);
2107 Copy X pixmap to Image window.
2109 XGetPixelPacket(display,visual_info,map_info,resource_info,
2110 image_list[scene],windows->image.pixel_info);
2111 windows->image.ximage->width=(int) image->columns;
2112 windows->image.ximage->height=(int) image->rows;
2113 windows->image.pixmap=windows->image.pixmaps[scene];
2114 windows->image.matte_pixmap=windows->image.matte_pixmaps[scene];
2117 event.xexpose.width=(int) image->columns;
2118 event.xexpose.height=(int) image->rows;
2119 if ((state & ExitState) == 0)
2121 XRefreshWindow(display,&windows->image,&event);
2122 (void) XSync(display,MagickFalse);
2124 state&=(~StepAnimationState);
2125 if (pause != MagickFalse)
2126 for (i=0; i < (ssize_t) resource_info->pause; i++)
2131 status=XCheckTypedWindowEvent(display,windows->image.id,KeyPress,
2138 length=XLookupString((XKeyEvent *) &event.xkey,command,(int)
2139 sizeof(command),&key_symbol,(XComposeStatus *) NULL);
2140 *(command+length)='\0';
2141 if ((key_symbol == XK_q) || (key_symbol == XK_Escape))
2143 XClientMessage(display,windows->image.id,
2144 windows->im_protocols,windows->im_exit,CurrentTime);
2153 Handle a window event.
2155 timestamp=time((time_t *) NULL);
2156 (void) XNextEvent(display,&event);
2157 if (windows->image.stasis == MagickFalse)
2158 windows->image.stasis=(time((time_t *) NULL)-timestamp) > 0 ?
2159 MagickTrue : MagickFalse;
2160 if (event.xany.window == windows->command.id)
2166 Select a command from the Command widget.
2168 id=XCommandWidget(display,windows,CommandMenu,&event);
2171 (void) CopyMagickString(command,CommandMenu[id],MaxTextExtent);
2172 command_type=CommandMenus[id];
2173 if (id < MagickMenus)
2179 Select a command from a pop-up menu.
2181 entry=XMenuWidget(display,windows,CommandMenu[id],Menus[id],
2185 (void) CopyMagickString(command,Menus[id][entry],MaxTextExtent);
2186 command_type=Commands[id][entry];
2188 if (command_type != NullCommand)
2189 nexus=XMagickCommand(display,resource_info,windows,
2190 command_type,&image,&state);
2197 if (display_image->debug != MagickFalse)
2198 (void) LogMagickEvent(X11Event,GetMagickModule(),
2199 "Button Press: 0x%lx %u +%d+%d",event.xbutton.window,
2200 event.xbutton.button,event.xbutton.x,event.xbutton.y);
2201 if ((event.xbutton.button == Button3) &&
2202 (event.xbutton.state & Mod1Mask))
2205 Convert Alt-Button3 to Button2.
2207 event.xbutton.button=Button2;
2208 event.xbutton.state&=(~Mod1Mask);
2210 if (event.xbutton.window == windows->backdrop.id)
2212 (void) XSetInputFocus(display,event.xbutton.window,RevertToParent,
2213 event.xbutton.time);
2216 if (event.xbutton.window == windows->image.id)
2218 if (resource_info->immutable != MagickFalse)
2224 Map/unmap Command widget.
2226 if (windows->command.mapped)
2227 (void) XWithdrawWindow(display,windows->command.id,
2228 windows->command.screen);
2231 (void) XCommandWidget(display,windows,CommandMenu,
2233 (void) XMapRaised(display,windows->command.id);
2240 if (display_image->debug != MagickFalse)
2241 (void) LogMagickEvent(X11Event,GetMagickModule(),
2242 "Button Release: 0x%lx %u +%d+%d",event.xbutton.window,
2243 event.xbutton.button,event.xbutton.x,event.xbutton.y);
2248 if (display_image->debug != MagickFalse)
2249 (void) LogMagickEvent(X11Event,GetMagickModule(),
2250 "Client Message: 0x%lx 0x%lx %d 0x%lx",(unsigned long)
2251 event.xclient.window,(unsigned long) event.xclient.message_type,
2252 event.xclient.format,(unsigned long) event.xclient.data.l[0]);
2253 if (event.xclient.message_type == windows->im_protocols)
2255 if (*event.xclient.data.l == (long) windows->im_update_colormap)
2258 Update graphic context and window colormap.
2260 for (i=0; i < (ssize_t) number_windows; i++)
2262 if (magick_windows[i]->id == windows->icon.id)
2264 context_values.background=pixel->background_color.pixel;
2265 context_values.foreground=pixel->foreground_color.pixel;
2266 (void) XChangeGC(display,magick_windows[i]->annotate_context,
2267 context_mask,&context_values);
2268 (void) XChangeGC(display,magick_windows[i]->widget_context,
2269 context_mask,&context_values);
2270 context_values.background=pixel->foreground_color.pixel;
2271 context_values.foreground=pixel->background_color.pixel;
2272 context_values.plane_mask=
2273 context_values.background ^ context_values.foreground;
2274 (void) XChangeGC(display,magick_windows[i]->highlight_context,
2275 (size_t) (context_mask | GCPlaneMask),
2277 magick_windows[i]->attributes.background_pixel=
2278 pixel->background_color.pixel;
2279 magick_windows[i]->attributes.border_pixel=
2280 pixel->border_color.pixel;
2281 magick_windows[i]->attributes.colormap=map_info->colormap;
2282 (void) XChangeWindowAttributes(display,magick_windows[i]->id,
2283 magick_windows[i]->mask,&magick_windows[i]->attributes);
2285 if (windows->backdrop.id != (Window) NULL)
2286 (void) XInstallColormap(display,map_info->colormap);
2289 if (*event.xclient.data.l == (long) windows->im_exit)
2296 if (event.xclient.message_type == windows->dnd_protocols)
2314 Display image named by the Drag-and-Drop selection.
2316 if ((*event.xclient.data.l != 2) && (*event.xclient.data.l != 128))
2318 selection=XInternAtom(display,"DndSelection",MagickFalse);
2319 status=XGetWindowProperty(display,root_window,selection,0L,2047L,
2320 MagickFalse,(Atom) AnyPropertyType,&type,&format,&length,&after,
2322 if ((status != Success) || (length == 0))
2324 if (*event.xclient.data.l == 2)
2329 (void) CopyMagickString(resource_info->image_info->filename,
2330 (char *) data,MaxTextExtent);
2337 if (LocaleNCompare((char *) data,"file:",5) != 0)
2339 (void) XFree((void *) data);
2342 (void) CopyMagickString(resource_info->image_info->filename,
2343 ((char *) data)+5,MaxTextExtent);
2345 nexus=ReadImage(resource_info->image_info,&image->exception);
2346 CatchException(&image->exception);
2347 if (nexus != (Image *) NULL)
2349 (void) XFree((void *) data);
2353 If client window delete message, exit.
2355 if (event.xclient.message_type != windows->wm_protocols)
2357 if (*event.xclient.data.l == (long) windows->wm_take_focus)
2359 (void) XSetInputFocus(display,event.xclient.window,RevertToParent,
2360 (Time) event.xclient.data.l[1]);
2363 if (*event.xclient.data.l != (long) windows->wm_delete_window)
2365 (void) XWithdrawWindow(display,event.xclient.window,
2366 visual_info->screen);
2367 if (event.xclient.window == windows->image.id)
2374 case ConfigureNotify:
2376 if (display_image->debug != MagickFalse)
2377 (void) LogMagickEvent(X11Event,GetMagickModule(),
2378 "Configure Notify: 0x%lx %dx%d+%d+%d %d",event.xconfigure.window,
2379 event.xconfigure.width,event.xconfigure.height,event.xconfigure.x,
2380 event.xconfigure.y,event.xconfigure.send_event);
2381 if (event.xconfigure.window == windows->image.id)
2383 if (event.xconfigure.send_event != 0)
2389 Position the transient windows relative of the Image window.
2391 if (windows->command.geometry == (char *) NULL)
2392 if (windows->command.mapped == MagickFalse)
2395 event.xconfigure.x-windows->command.width-25;
2396 windows->command.y=event.xconfigure.y;
2397 XConstrainWindowPosition(display,&windows->command);
2398 window_changes.x=windows->command.x;
2399 window_changes.y=windows->command.y;
2400 (void) XReconfigureWMWindow(display,windows->command.id,
2401 windows->command.screen,(unsigned int) (CWX | CWY),
2404 if (windows->widget.geometry == (char *) NULL)
2405 if (windows->widget.mapped == MagickFalse)
2408 event.xconfigure.x+event.xconfigure.width/10;
2410 event.xconfigure.y+event.xconfigure.height/10;
2411 XConstrainWindowPosition(display,&windows->widget);
2412 window_changes.x=windows->widget.x;
2413 window_changes.y=windows->widget.y;
2414 (void) XReconfigureWMWindow(display,windows->widget.id,
2415 windows->widget.screen,(unsigned int) (CWX | CWY),
2420 Image window has a new configuration.
2422 windows->image.width=(unsigned int) event.xconfigure.width;
2423 windows->image.height=(unsigned int) event.xconfigure.height;
2426 if (event.xconfigure.window == windows->icon.id)
2429 Icon window has a new configuration.
2431 windows->icon.width=(unsigned int) event.xconfigure.width;
2432 windows->icon.height=(unsigned int) event.xconfigure.height;
2440 Group leader has exited.
2442 if (display_image->debug != MagickFalse)
2443 (void) LogMagickEvent(X11Event,GetMagickModule(),
2444 "Destroy Notify: 0x%lx",event.xdestroywindow.window);
2445 if (event.xdestroywindow.window == windows->group_leader.id)
2455 Selectively install colormap.
2457 if (map_info->colormap != XDefaultColormap(display,visual_info->screen))
2458 if (event.xcrossing.mode != NotifyUngrab)
2459 XInstallColormap(display,map_info->colormap);
2464 if (display_image->debug != MagickFalse)
2465 (void) LogMagickEvent(X11Event,GetMagickModule(),
2466 "Expose: 0x%lx %dx%d+%d+%d",event.xexpose.window,
2467 event.xexpose.width,event.xexpose.height,event.xexpose.x,
2470 Repaint windows that are now exposed.
2472 if (event.xexpose.window == windows->image.id)
2474 windows->image.pixmap=windows->image.pixmaps[scene];
2475 windows->image.matte_pixmap=windows->image.matte_pixmaps[scene];
2476 XRefreshWindow(display,&windows->image,&event);
2479 if (event.xexpose.window == windows->icon.id)
2480 if (event.xexpose.count == 0)
2482 XRefreshWindow(display,&windows->icon,&event);
2493 Respond to a user key press.
2495 length=XLookupString((XKeyEvent *) &event.xkey,command,(int)
2496 sizeof(command),&key_symbol,(XComposeStatus *) NULL);
2497 *(command+length)='\0';
2498 if (display_image->debug != MagickFalse)
2499 (void) LogMagickEvent(X11Event,GetMagickModule(),
2500 "Key press: 0x%lx (%c)",(unsigned long) key_symbol,*command);
2501 command_type=NullCommand;
2506 if ((event.xkey.state & ControlMask) == MagickFalse)
2508 command_type=OpenCommand;
2513 command_type=StepBackwardCommand;
2518 command_type=StepForwardCommand;
2523 command_type=FasterCommand;
2528 command_type=SlowerCommand;
2533 command_type=HelpCommand;
2538 command_type=BrowseDocumentationCommand;
2543 command_type=InfoCommand;
2549 command_type=QuitCommand;
2555 if (command_type != NullCommand)
2556 nexus=XMagickCommand(display,resource_info,windows,
2557 command_type,&image,&state);
2563 Respond to a user key release.
2565 (void) XLookupString((XKeyEvent *) &event.xkey,command,(int)
2566 sizeof(command),&key_symbol,(XComposeStatus *) NULL);
2567 if (display_image->debug != MagickFalse)
2568 (void) LogMagickEvent(X11Event,GetMagickModule(),
2569 "Key release: 0x%lx (%c)",(unsigned long) key_symbol,*command);
2575 Selectively uninstall colormap.
2577 if (map_info->colormap != XDefaultColormap(display,visual_info->screen))
2578 if (event.xcrossing.mode != NotifyUngrab)
2579 XUninstallColormap(display,map_info->colormap);
2584 if (display_image->debug != MagickFalse)
2585 (void) LogMagickEvent(X11Event,GetMagickModule(),"Map Notify: 0x%lx",
2587 if (event.xmap.window == windows->backdrop.id)
2589 (void) XSetInputFocus(display,event.xmap.window,RevertToParent,
2591 windows->backdrop.mapped=MagickTrue;
2594 if (event.xmap.window == windows->image.id)
2596 if (windows->backdrop.id != (Window) NULL)
2597 (void) XInstallColormap(display,map_info->colormap);
2598 if (LocaleCompare(image_list[0]->magick,"LOGO") == 0)
2600 if (LocaleCompare(display_image->filename,"LOGO") == 0)
2601 nexus=XMagickCommand(display,resource_info,windows,
2602 OpenCommand,&image,&state);
2606 windows->image.mapped=MagickTrue;
2609 if (event.xmap.window == windows->info.id)
2611 windows->info.mapped=MagickTrue;
2614 if (event.xmap.window == windows->icon.id)
2617 Create an icon image.
2619 XMakeStandardColormap(display,icon_visual,icon_resources,
2620 display_image,icon_map,icon_pixel);
2621 (void) XMakeImage(display,icon_resources,&windows->icon,
2622 display_image,windows->icon.width,windows->icon.height);
2623 (void) XSetWindowBackgroundPixmap(display,windows->icon.id,
2624 windows->icon.pixmap);
2625 (void) XClearWindow(display,windows->icon.id);
2626 (void) XWithdrawWindow(display,windows->info.id,
2627 windows->info.screen);
2628 windows->icon.mapped=MagickTrue;
2631 if (event.xmap.window == windows->command.id)
2633 windows->command.mapped=MagickTrue;
2636 if (event.xmap.window == windows->popup.id)
2638 windows->popup.mapped=MagickTrue;
2641 if (event.xmap.window == windows->widget.id)
2643 windows->widget.mapped=MagickTrue;
2650 (void) XRefreshKeyboardMapping(&event.xmapping);
2655 case PropertyNotify:
2671 if (display_image->debug != MagickFalse)
2672 (void) LogMagickEvent(X11Event,GetMagickModule(),
2673 "Property Notify: 0x%lx 0x%lx %d",(unsigned long)
2674 event.xproperty.window,(unsigned long) event.xproperty.atom,
2675 event.xproperty.state);
2676 if (event.xproperty.atom != windows->im_remote_command)
2679 Display image named by the remote command protocol.
2681 status=XGetWindowProperty(display,event.xproperty.window,
2682 event.xproperty.atom,0L,(long) MaxTextExtent,MagickFalse,(Atom)
2683 AnyPropertyType,&type,&format,&length,&after,&data);
2684 if ((status != Success) || (length == 0))
2686 (void) CopyMagickString(resource_info->image_info->filename,
2687 (char *) data,MaxTextExtent);
2688 nexus=ReadImage(resource_info->image_info,&image->exception);
2689 CatchException(&image->exception);
2690 if (nexus != (Image *) NULL)
2692 (void) XFree((void *) data);
2695 case ReparentNotify:
2697 if (display_image->debug != MagickFalse)
2698 (void) LogMagickEvent(X11Event,GetMagickModule(),
2699 "Reparent Notify: 0x%lx=>0x%lx",event.xreparent.parent,
2700 event.xreparent.window);
2705 if (display_image->debug != MagickFalse)
2706 (void) LogMagickEvent(X11Event,GetMagickModule(),
2707 "Unmap Notify: 0x%lx",event.xunmap.window);
2708 if (event.xunmap.window == windows->backdrop.id)
2710 windows->backdrop.mapped=MagickFalse;
2713 if (event.xunmap.window == windows->image.id)
2715 windows->image.mapped=MagickFalse;
2718 if (event.xunmap.window == windows->info.id)
2720 windows->info.mapped=MagickFalse;
2723 if (event.xunmap.window == windows->icon.id)
2725 if (map_info->colormap == icon_map->colormap)
2726 XConfigureImageColormap(display,resource_info,windows,
2728 (void) XFreeStandardColormap(display,icon_visual,icon_map,
2730 windows->icon.mapped=MagickFalse;
2733 if (event.xunmap.window == windows->command.id)
2735 windows->command.mapped=MagickFalse;
2738 if (event.xunmap.window == windows->popup.id)
2740 if (windows->backdrop.id != (Window) NULL)
2741 (void) XSetInputFocus(display,windows->image.id,RevertToParent,
2743 windows->popup.mapped=MagickFalse;
2746 if (event.xunmap.window == windows->widget.id)
2748 if (windows->backdrop.id != (Window) NULL)
2749 (void) XSetInputFocus(display,windows->image.id,RevertToParent,
2751 windows->widget.mapped=MagickFalse;
2758 if (display_image->debug != MagickFalse)
2759 (void) LogMagickEvent(X11Event,GetMagickModule(),"Event type: %d",
2765 while (!(state & ExitState));
2766 image_list=(Image **) RelinquishMagickMemory(image_list);
2767 images=DestroyImageList(images);
2768 if ((windows->visual_info->klass == GrayScale) ||
2769 (windows->visual_info->klass == PseudoColor) ||
2770 (windows->visual_info->klass == DirectColor))
2775 if (windows->info.mapped)
2776 (void) XWithdrawWindow(display,windows->info.id,windows->info.screen);
2777 if (windows->command.mapped)
2778 (void) XWithdrawWindow(display,windows->command.id,
2779 windows->command.screen);
2781 if (resource_info->backdrop == MagickFalse)
2782 if (windows->backdrop.mapped)
2784 (void) XWithdrawWindow(display,windows->backdrop.id,\
2785 windows->backdrop.screen);
2786 (void) XDestroyWindow(display,windows->backdrop.id);
2787 windows->backdrop.id=(Window) NULL;
2788 (void) XWithdrawWindow(display,windows->image.id,windows->image.screen);
2789 (void) XDestroyWindow(display,windows->image.id);
2790 windows->image.id=(Window) NULL;
2792 XSetCursorState(display,windows,MagickTrue);
2793 XCheckRefreshWindows(display,windows);
2794 for (scene=1; scene < (ssize_t) number_scenes; scene++)
2796 if (windows->image.pixmaps[scene] != (Pixmap) NULL)
2797 (void) XFreePixmap(display,windows->image.pixmaps[scene]);
2798 windows->image.pixmaps[scene]=(Pixmap) NULL;
2799 if (windows->image.matte_pixmaps[scene] != (Pixmap) NULL)
2800 (void) XFreePixmap(display,windows->image.matte_pixmaps[scene]);
2801 windows->image.matte_pixmaps[scene]=(Pixmap) NULL;
2803 XSetCursorState(display,windows,MagickFalse);
2804 windows->image.pixmaps=(Pixmap *)
2805 RelinquishMagickMemory(windows->image.pixmaps);
2806 windows->image.matte_pixmaps=(Pixmap *)
2807 RelinquishMagickMemory(windows->image.matte_pixmaps);
2808 if (nexus == (Image *) NULL)
2813 if (windows->image.mapped != MagickFalse)
2814 (void) XWithdrawWindow(display,windows->image.id,windows->image.screen); XDelay(display,SuspendTime);
2815 (void) XFreeStandardColormap(display,icon_visual,icon_map,icon_pixel);
2816 if (resource_info->map_type == (char *) NULL)
2817 (void) XFreeStandardColormap(display,visual_info,map_info,pixel);
2818 DestroyXResources();
2820 (void) XSync(display,MagickFalse);
2822 Restore our progress monitor and warning handlers.
2824 (void) SetErrorHandler(warning_handler);
2825 (void) SetWarningHandler(warning_handler);
2827 Change to home directory.
2829 cwd=getcwd(working_directory,MaxTextExtent);
2830 status=chdir(resource_info->home_directory);
2832 (void) ThrowMagickException(&images->exception,GetMagickModule(),
2833 FileOpenError,"UnableToOpenFile","%s",resource_info->home_directory);
2838 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2842 + X S a v e I m a g e %
2846 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2848 % XSaveImage() saves an image to a file.
2850 % The format of the XSaveImage method is:
2852 % MagickBooleanType XSaveImage(Display *display,
2853 % XResourceInfo *resource_info,XWindows *windows,Image *image)
2855 % A description of each parameter follows:
2857 % o status: Method XSaveImage return True if the image is
2858 % written. False is returned is there is a memory shortage or if the
2859 % image fails to write.
2861 % o display: Specifies a connection to an X server; returned from
2864 % o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
2866 % o windows: Specifies a pointer to a XWindows structure.
2868 % o image: the image.
2871 static MagickBooleanType XSaveImage(Display *display,
2872 XResourceInfo *resource_info,XWindows *windows,Image *image)
2875 filename[MaxTextExtent];
2884 Request file name from user.
2886 if (resource_info->write_filename != (char *) NULL)
2887 (void) CopyMagickString(filename,resource_info->write_filename,
2892 path[MaxTextExtent];
2897 GetPathComponent(image->filename,HeadPath,path);
2898 GetPathComponent(image->filename,TailPath,filename);
2901 (void) ThrowMagickException(&image->exception,GetMagickModule(),
2902 FileOpenError,"UnableToOpenFile","%s",path);
2904 XFileBrowserWidget(display,windows,"Save",filename);
2905 if (*filename == '\0')
2907 if (IsPathAccessible(filename) != MagickFalse)
2913 File exists-- seek user's permission before overwriting.
2915 status=XConfirmWidget(display,windows,"Overwrite",filename);
2919 image_info=CloneImageInfo(resource_info->image_info);
2920 (void) CopyMagickString(image_info->filename,filename,MaxTextExtent);
2921 (void) SetImageInfo(image_info,1,&image->exception);
2922 if ((LocaleCompare(image_info->magick,"JPEG") == 0) ||
2923 (LocaleCompare(image_info->magick,"JPG") == 0))
2926 quality[MaxTextExtent];
2932 Request JPEG quality from user.
2934 (void) FormatMagickString(quality,MaxTextExtent,"%.20g",(double)
2935 image_info->quality);
2936 status=XDialogWidget(display,windows,"Save","Enter JPEG quality:",
2938 if (*quality == '\0')
2940 image->quality=StringToUnsignedLong(quality);
2941 image_info->interlace=status != MagickFalse ? NoInterlace :
2944 if ((LocaleCompare(image_info->magick,"EPS") == 0) ||
2945 (LocaleCompare(image_info->magick,"PDF") == 0) ||
2946 (LocaleCompare(image_info->magick,"PS") == 0) ||
2947 (LocaleCompare(image_info->magick,"PS2") == 0))
2950 geometry[MaxTextExtent];
2953 Request page geometry from user.
2955 (void) CopyMagickString(geometry,PSPageGeometry,MaxTextExtent);
2956 if (LocaleCompare(image_info->magick,"PDF") == 0)
2957 (void) CopyMagickString(geometry,PSPageGeometry,MaxTextExtent);
2958 if (image_info->page != (char *) NULL)
2959 (void) CopyMagickString(geometry,image_info->page,MaxTextExtent);
2960 XListBrowserWidget(display,windows,&windows->widget,PageSizes,"Select",
2961 "Select page geometry:",geometry);
2962 if (*geometry != '\0')
2963 image_info->page=GetPageGeometry(geometry);
2968 image=GetFirstImageInList(image);
2969 status=WriteImages(image_info,image,filename,&image->exception);
2970 if (status != MagickFalse)
2971 image->taint=MagickFalse;
2972 image_info=DestroyImageInfo(image_info);
2973 XSetCursorState(display,windows,MagickFalse);
2974 return(status != 0 ? MagickTrue : MagickFalse);
2979 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2983 + A n i m a t e I m a g e s %
2987 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2989 % AnimateImages() repeatedly displays an image sequence to any X window
2990 % screen. It returns a value other than 0 if successful. Check the
2991 % exception member of image to determine the reason for any failure.
2993 % The format of the AnimateImages method is:
2995 % MagickBooleanType AnimateImages(const ImageInfo *image_info,
2998 % A description of each parameter follows:
3000 % o image_info: the image info.
3002 % o image: the image.
3005 MagickExport MagickBooleanType AnimateImages(const ImageInfo *image_info,
3008 assert(image_info != (const ImageInfo *) NULL);
3009 assert(image_info->signature == MagickSignature);
3010 assert(image != (Image *) NULL);
3011 assert(image->signature == MagickSignature);
3012 if (image->debug != MagickFalse)
3013 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
3014 (void) ThrowMagickException(&image->exception,GetMagickModule(),
3015 MissingDelegateError,"DelegateLibrarySupportNotBuiltIn","`%s' (X11)",
3017 return(MagickFalse);