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-2011 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 "MagickCore/studio.h"
43 #include "MagickCore/animate.h"
44 #include "MagickCore/animate-private.h"
45 #include "MagickCore/client.h"
46 #include "MagickCore/color.h"
47 #include "MagickCore/color-private.h"
48 #include "MagickCore/colorspace.h"
49 #include "MagickCore/constitute.h"
50 #include "MagickCore/delegate.h"
51 #include "MagickCore/exception.h"
52 #include "MagickCore/exception-private.h"
53 #include "MagickCore/geometry.h"
54 #include "MagickCore/image-private.h"
55 #include "MagickCore/layer.h"
56 #include "MagickCore/list.h"
57 #include "MagickCore/log.h"
58 #include "MagickCore/image.h"
59 #include "MagickCore/memory_.h"
60 #include "MagickCore/monitor.h"
61 #include "MagickCore/monitor-private.h"
62 #include "MagickCore/option.h"
63 #include "MagickCore/pixel-accessor.h"
64 #include "MagickCore/property.h"
65 #include "MagickCore/resource_.h"
66 #include "MagickCore/string_.h"
67 #include "MagickCore/string-private.h"
68 #include "MagickCore/transform.h"
69 #include "MagickCore/utility.h"
70 #include "MagickCore/version.h"
71 #include "MagickCore/widget.h"
72 #include "MagickCore/xwindow-private.h"
74 #if defined(MAGICKCORE_X11_DELEGATE)
76 Animate state declarations.
78 #define AutoReverseAnimationState 0x0004
79 #define ForwardAnimationState 0x0008
80 #define HighlightState 0x0010
81 #define PlayAnimationState 0x0020
82 #define RepeatAnimationState 0x0040
83 #define StepAnimationState 0x0080
93 " Press any button to map or unmap the Command widget.",
96 " The Command widget lists a number of sub-menus and commands.",
114 " Browse Documentation",
119 " Menu items with a indented triangle have a sub-menu. They",
120 " are represented above as the indented items. To access a",
121 " sub-menu item, move the pointer to the appropriate menu and",
122 " press a button and drag. When you find the desired sub-menu",
123 " item, release the button and the command is executed. Move",
124 " the pointer away from the sub-menu if you decide not to",
125 " execute a particular command.",
127 "KEYBOARD ACCELERATORS",
128 " Accelerators are one or two key presses that effect a",
129 " particular command. The keyboard accelerators that",
130 " animate(1) understands is:",
132 " Ctl+O Press to open an image from a file.",
134 " space Press to display the next image in the sequence.",
136 " < Press to speed-up the display of the images. Refer to",
137 " -delay for more information.",
139 " > Press to slow the display of the images. Refer to",
140 " -delay for more information.",
142 " F1 Press to display helpful information about animate(1).",
144 " Find Press to browse documentation about ImageMagick.",
146 " ? Press to display information about the image. Press",
147 " any key or button to erase the information.",
149 " This information is printed: image name; image size;",
150 " and the total number of unique colors in the image.",
152 " Ctl-q Press to discard all images and exit program.",
157 Constant declarations.
179 static const unsigned char
182 (unsigned char) 0xaa,
183 (unsigned char) 0x55,
184 (unsigned char) 0xaa,
185 (unsigned char) 0x55,
186 (unsigned char) 0xaa,
187 (unsigned char) 0x55,
188 (unsigned char) 0xaa,
193 (unsigned char) 0x00,
194 (unsigned char) 0x00,
195 (unsigned char) 0x00,
196 (unsigned char) 0x00,
197 (unsigned char) 0x00,
198 (unsigned char) 0x00,
199 (unsigned char) 0x00,
204 Enumeration declarations.
219 BrowseDocumentationCommand,
231 #define HighlightWidth 8
232 #define HighlightHeight 8
233 #define ShadowWidth 8
234 #define ShadowHeight 8
237 Forward declarations.
240 *XMagickCommand(Display *,XResourceInfo *,XWindows *,const CommandType,
241 Image **,MagickStatusType *);
243 static MagickBooleanType
244 XSaveImage(Display *,XResourceInfo *,XWindows *,Image *);
247 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
251 % A n i m a t e I m a g e s %
255 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
257 % AnimateImages() repeatedly displays an image sequence to any X window
258 % screen. It returns a value other than 0 if successful. Check the
259 % exception member of image to determine the reason for any failure.
261 % The format of the AnimateImages method is:
263 % MagickBooleanType AnimateImages(const ImageInfo *image_info,
266 % A description of each parameter follows:
268 % o image_info: the image info.
270 % o image: the image.
273 MagickExport MagickBooleanType AnimateImages(const ImageInfo *image_info,
291 assert(image_info != (const ImageInfo *) NULL);
292 assert(image_info->signature == MagickSignature);
293 assert(images != (Image *) NULL);
294 assert(images->signature == MagickSignature);
295 if (images->debug != MagickFalse)
296 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",images->filename);
297 display=XOpenDisplay(image_info->server_name);
298 if (display == (Display *) NULL)
300 (void) ThrowMagickException(&images->exception,GetMagickModule(),
301 XServerError,"UnableToOpenXServer","`%s'",XDisplayName(
302 image_info->server_name));
305 if (images->exception.severity != UndefinedException)
306 CatchException(&images->exception);
307 (void) XSetErrorHandler(XError);
308 resource_database=XGetResourceDatabase(display,GetClientName());
309 (void) ResetMagickMemory(&resource_info,0,sizeof(XResourceInfo));
310 XGetResourceInfo(image_info,resource_database,GetClientName(),&resource_info);
311 if (image_info->page != (char *) NULL)
312 resource_info.image_geometry=AcquireString(image_info->page);
313 resource_info.immutable=MagickTrue;
314 argv[0]=AcquireString(GetClientName());
315 (void) XAnimateImages(display,&resource_info,argv,1,images);
316 argv[0]=DestroyString(argv[0]);
317 (void) XCloseDisplay(display);
318 XDestroyResourceInfo(&resource_info);
319 status=images->exception.severity == UndefinedException ?
320 MagickTrue : MagickFalse;
321 return(status != 0 ? MagickTrue : MagickFalse);
325 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
329 + X M a g i c k C o m m a n d %
333 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
335 % XMagickCommand() makes a transform to the image or Image window as specified
336 % by a user menu button or keyboard command.
338 % The format of the XMagickCommand method is:
340 % Image *XMagickCommand(Display *display,XResourceInfo *resource_info,
341 % XWindows *windows,const CommandType command_type,Image **image,
342 % MagickStatusType *state)
344 % A description of each parameter follows:
346 % o display: Specifies a connection to an X server; returned from
349 % o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
351 % o windows: Specifies a pointer to a XWindows structure.
353 % o image: the image; XMagickCommand
354 % may transform the image and return a new image pointer.
356 % o state: Specifies a MagickStatusType; XMagickCommand may return a
361 static Image *XMagickCommand(Display *display,XResourceInfo *resource_info,
362 XWindows *windows,const CommandType command_type,Image **image,
363 MagickStatusType *state)
378 Process user command.
380 nexus=NewImageList();
381 switch (command_type)
405 filenames[MaxTextExtent] = "*";
407 if (resource_info->immutable != MagickFalse)
410 Request file name from user.
412 XFileBrowserWidget(display,windows,"Animate",filenames);
413 if (*filenames == '\0')
414 return((Image *) NULL);
416 Expand the filenames.
418 filelist=(char **) AcquireMagickMemory(sizeof(char *));
419 if (filelist == (char **) NULL)
421 ThrowXWindowException(ResourceLimitError,"MemoryAllocationFailed",
423 return((Image *) NULL);
426 filelist[0]=filenames;
427 status=ExpandFilenames(&number_files,&filelist);
428 if ((status == MagickFalse) || (number_files == 0))
430 if (number_files == 0)
432 ThrowXWindowException(ImageError,"NoImagesWereLoaded",filenames);
433 return((Image *) NULL);
435 ThrowXWindowException(ResourceLimitError,"MemoryAllocationFailed",
437 return((Image *) NULL);
439 read_info=CloneImageInfo(resource_info->image_info);
440 exception=AcquireExceptionInfo();
441 images=NewImageList();
442 XSetCursorState(display,windows,MagickTrue);
443 XCheckRefreshWindows(display,windows);
444 for (i=0; i < number_files; i++)
446 (void) CopyMagickString(read_info->filename,filelist[i],MaxTextExtent);
447 filelist[i]=DestroyString(filelist[i]);
448 *read_info->magick='\0';
449 next=ReadImage(read_info,exception);
450 CatchException(exception);
451 if (next != (Image *) NULL)
452 AppendImageToList(&images,next);
453 if (number_files <= 5)
455 proceed=SetImageProgress(images,LoadImageTag,i,(MagickSizeType)
457 if (proceed == MagickFalse)
460 filelist=(char **) RelinquishMagickMemory(filelist);
461 exception=DestroyExceptionInfo(exception);
462 read_info=DestroyImageInfo(read_info);
463 if (images == (Image *) NULL)
465 XSetCursorState(display,windows,MagickFalse);
466 ThrowXWindowException(ImageError,"NoImagesWereLoaded",filenames);
467 return((Image *) NULL);
469 nexus=GetFirstImageInList(images);
476 basename[MaxTextExtent];
482 Window name is the base of the filename.
484 *state|=PlayAnimationState;
485 *state&=(~AutoReverseAnimationState);
486 GetPathComponent((*image)->magick_filename,BasePath,basename);
487 (void) FormatLocaleString(windows->image.name,MaxTextExtent,
488 "%s: %s",MagickPackageName,basename);
489 if (resource_info->title != (char *) NULL)
494 title=InterpretImageProperties(resource_info->image_info,*image,
495 resource_info->title);
496 (void) CopyMagickString(windows->image.name,title,MaxTextExtent);
497 title=DestroyString(title);
499 status=XStringListToTextProperty(&windows->image.name,1,&window_name);
502 XSetWMName(display,windows->image.id,&window_name);
503 (void) XFree((void *) window_name.value);
507 case StepBackwardCommand:
508 case StepForwardCommand:
510 *state|=StepAnimationState;
511 *state&=(~PlayAnimationState);
512 if (command_type == StepBackwardCommand)
513 *state&=(~ForwardAnimationState);
514 if (command_type == StepForwardCommand)
515 *state|=ForwardAnimationState;
516 if (resource_info->title != (char *) NULL)
522 *state|=RepeatAnimationState;
523 *state&=(~AutoReverseAnimationState);
524 *state|=PlayAnimationState;
527 case AutoReverseCommand:
529 *state|=AutoReverseAnimationState;
530 *state&=(~RepeatAnimationState);
531 *state|=PlayAnimationState;
539 status=XSaveImage(display,resource_info,windows,*image);
540 if (status == MagickFalse)
542 XNoticeWidget(display,windows,"Unable to write X image:",
550 resource_info->delay++;
555 if (resource_info->delay == 0)
557 resource_info->delay--;
562 *state=ForwardAnimationState;
563 *state&=(~AutoReverseAnimationState);
568 *state&=(~ForwardAnimationState);
569 *state&=(~AutoReverseAnimationState);
574 XDisplayImageInfo(display,resource_info,windows,(Image *) NULL,*image);
582 XTextViewWidget(display,resource_info,windows,MagickFalse,
583 "Help Viewer - Animate",AnimateHelp);
586 case BrowseDocumentationCommand:
596 Browse the ImageMagick documentation.
598 root_window=XRootWindow(display,XDefaultScreen(display));
599 mozilla_atom=XInternAtom(display,"_MOZILLA_VERSION",MagickFalse);
600 mozilla_window=XWindowByProperty(display,root_window,mozilla_atom);
601 if (mozilla_window != (Window) NULL)
604 command[MaxTextExtent],
608 Display documentation using Netscape remote control.
610 url=GetMagickHomeURL();
611 (void) FormatLocaleString(command,MaxTextExtent,
612 "openurl(%s,new-tab)",url);
613 url=DestroyString(url);
614 mozilla_atom=XInternAtom(display,"_MOZILLA_COMMAND",MagickFalse);
615 (void) XChangeProperty(display,mozilla_window,mozilla_atom,
616 XA_STRING,8,PropModeReplace,(unsigned char *) command,
617 (int) strlen(command));
618 XSetCursorState(display,windows,MagickFalse);
621 XSetCursorState(display,windows,MagickTrue);
622 XCheckRefreshWindows(display,windows);
623 status=InvokeDelegate(resource_info->image_info,*image,"browse",
624 (char *) NULL,&(*image)->exception);
625 if (status == MagickFalse)
626 XNoticeWidget(display,windows,"Unable to browse documentation",
628 XDelay(display,1500);
629 XSetCursorState(display,windows,MagickFalse);
634 XNoticeWidget(display,windows,GetMagickVersion((size_t *) NULL),
635 GetMagickCopyright());
643 if (resource_info->confirm_exit == MagickFalse)
644 XClientMessage(display,windows->image.id,windows->im_protocols,
645 windows->im_exit,CurrentTime);
652 Confirm program exit.
654 status=XConfirmWidget(display,windows,"Do you really want to exit",
655 resource_info->client_name);
657 XClientMessage(display,windows->image.id,windows->im_protocols,
658 windows->im_exit,CurrentTime);
669 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
673 + X A n i m a t e B a c k g r o u n d I m a g e %
677 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
679 % XAnimateBackgroundImage() animates an image sequence in the background of
682 % The format of the XAnimateBackgroundImage method is:
684 % void XAnimateBackgroundImage(Display *display,
685 % XResourceInfo *resource_info,Image *images)
687 % A description of each parameter follows:
689 % o display: Specifies a connection to an X server; returned from
692 % o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
694 % o images: the image list.
698 static inline ssize_t MagickMax(const ssize_t x,const ssize_t y)
705 #if defined(__cplusplus) || defined(c_plusplus)
709 static int SceneCompare(const void *x,const void *y)
715 image_1=(const Image **) x;
716 image_2=(const Image **) y;
717 return((int) ((*image_1)->scene-(*image_2)->scene));
720 #if defined(__cplusplus) || defined(c_plusplus)
724 MagickExport void XAnimateBackgroundImage(Display *display,
725 XResourceInfo *resource_info,Image *images)
728 geometry[MaxTextExtent],
729 visual_type[MaxTextExtent];
754 static XStandardColormap
758 *visual_info = (XVisualInfo *) NULL;
786 Determine target window.
788 assert(images != (Image *) NULL);
789 assert(images->signature == MagickSignature);
790 if (images->debug != MagickFalse)
791 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",images->filename);
792 resources=(*resource_info);
793 window_info.id=(Window) NULL;
794 root_window=XRootWindow(display,XDefaultScreen(display));
795 if (LocaleCompare(resources.window_id,"root") == 0)
796 window_info.id=root_window;
799 if (isdigit((int) ((unsigned char) *resources.window_id)) != 0)
800 window_info.id=XWindowByID(display,root_window,
801 (Window) strtol((char *) resources.window_id,(char **) NULL,0));
802 if (window_info.id == (Window) NULL)
804 XWindowByName(display,root_window,resources.window_id);
806 if (window_info.id == (Window) NULL)
808 ThrowXWindowException(XServerError,"NoWindowWithSpecifiedIDExists",
809 resources.window_id);
813 Determine window visual id.
815 window_attributes.width=XDisplayWidth(display,XDefaultScreen(display));
816 window_attributes.height=XDisplayHeight(display,XDefaultScreen(display));
817 (void) CopyMagickString(visual_type,"default",MaxTextExtent);
818 status=XGetWindowAttributes(display,window_info.id,&window_attributes) != 0 ?
819 MagickTrue : MagickFalse;
820 if (status != MagickFalse)
821 (void) FormatLocaleString(visual_type,MaxTextExtent,"0x%lx",
822 XVisualIDFromVisual(window_attributes.visual));
823 if (visual_info == (XVisualInfo *) NULL)
826 Allocate standard colormap.
828 map_info=XAllocStandardColormap();
829 if (map_info == (XStandardColormap *) NULL)
830 ThrowXWindowFatalException(ResourceLimitError,"MemoryAllocationFailed",
832 map_info->colormap=(Colormap) NULL;
833 pixel.pixels=(unsigned long *) NULL;
835 Initialize visual info.
837 resources.map_type=(char *) NULL;
838 resources.visual_type=visual_type;
839 visual_info=XBestVisualInfo(display,map_info,&resources);
840 if (visual_info == (XVisualInfo *) NULL)
841 ThrowXWindowFatalException(XServerFatalError,"UnableToGetVisual",
844 Initialize window info.
846 window_info.ximage=(XImage *) NULL;
847 window_info.matte_image=(XImage *) NULL;
848 window_info.pixmap=(Pixmap) NULL;
849 window_info.matte_pixmap=(Pixmap) NULL;
852 Free previous root colors.
854 if (window_info.id == root_window)
855 XDestroyWindowColors(display,root_window);
856 coalesce_image=CoalesceImages(images,&images->exception);
857 if (coalesce_image == (Image *) NULL)
858 ThrowXWindowFatalException(ResourceLimitError,"MemoryAllocationFailed",
860 images=coalesce_image;
861 if (resources.map_type == (char *) NULL)
862 if ((visual_info->klass != TrueColor) &&
863 (visual_info->klass != DirectColor))
869 Determine if the sequence of images has the identical colormap.
871 for (next=images; next != (Image *) NULL; )
873 next->matte=MagickFalse;
874 if ((next->storage_class == DirectClass) ||
875 (next->colors != images->colors) ||
876 (next->colors > (size_t) visual_info->colormap_size))
878 for (i=0; i < (ssize_t) images->colors; i++)
879 if (IsPixelPacketEquivalent(next->colormap+i,images->colormap+i) == MagickFalse)
881 if (i < (ssize_t) images->colors)
883 next=GetNextImageInList(next);
885 if (next != (Image *) NULL)
886 (void) RemapImages(resources.quantize_info,images,(Image *) NULL);
889 Sort images by increasing scene number.
891 number_scenes=GetImageListLength(images);
892 image_list=ImageListToArray(images,&images->exception);
893 if (image_list == (Image **) NULL)
894 ThrowXWindowFatalException(ResourceLimitFatalError,
895 "MemoryAllocationFailed",images->filename);
896 for (i=0; i < (ssize_t) number_scenes; i++)
897 if (image_list[i]->scene == 0)
899 if (i == (ssize_t) number_scenes)
900 qsort((void *) image_list,number_scenes,sizeof(Image *),SceneCompare);
902 Initialize Standard Colormap.
904 resources.colormap=SharedColormap;
905 display_image=image_list[0];
906 for (scene=0; scene < (int) number_scenes; scene++)
908 if ((resource_info->map_type != (char *) NULL) ||
909 (visual_info->klass == TrueColor) ||
910 (visual_info->klass == DirectColor))
911 (void) SetImageType(image_list[scene],image_list[scene]->matte ==
912 MagickFalse ? TrueColorType : TrueColorMatteType);
913 if ((display_image->columns < image_list[scene]->columns) &&
914 (display_image->rows < image_list[scene]->rows))
915 display_image=image_list[scene];
917 if ((resource_info->map_type != (char *) NULL) ||
918 (visual_info->klass == TrueColor) || (visual_info->klass == DirectColor))
919 (void) SetImageType(display_image,display_image->matte == MagickFalse ?
920 TrueColorType : TrueColorMatteType);
921 XMakeStandardColormap(display,visual_info,&resources,display_image,map_info,
924 Graphic context superclass.
926 context_values.background=pixel.background_color.pixel;
927 context_values.foreground=pixel.foreground_color.pixel;
928 pixel.annotate_context=XCreateGC(display,window_info.id,(unsigned long)
929 (GCBackground | GCForeground),&context_values);
930 if (pixel.annotate_context == (GC) NULL)
931 ThrowXWindowFatalException(XServerFatalError,"UnableToCreateGraphicContext",
934 Initialize Image window attributes.
936 XGetWindowInfo(display,visual_info,map_info,&pixel,(XFontStruct *) NULL,
937 &resources,&window_info);
941 window_info.width=(unsigned int) image_list[0]->columns;
942 window_info.height=(unsigned int) image_list[0]->rows;
943 if ((image_list[0]->columns != window_info.width) ||
944 (image_list[0]->rows != window_info.height))
945 ThrowXWindowFatalException(XServerFatalError,"UnableToCreateXImage",
946 image_list[0]->filename);
947 (void) FormatLocaleString(geometry,MaxTextExtent,"%ux%u+0+0>",
948 window_attributes.width,window_attributes.height);
949 geometry_info.width=window_info.width;
950 geometry_info.height=window_info.height;
951 geometry_info.x=(ssize_t) window_info.x;
952 geometry_info.y=(ssize_t) window_info.y;
953 (void) ParseMetaGeometry(geometry,&geometry_info.x,&geometry_info.y,
954 &geometry_info.width,&geometry_info.height);
955 window_info.width=(unsigned int) geometry_info.width;
956 window_info.height=(unsigned int) geometry_info.height;
957 window_info.x=(int) geometry_info.x;
958 window_info.y=(int) geometry_info.y;
959 status=XMakeImage(display,&resources,&window_info,image_list[0],
960 window_info.width,window_info.height);
961 if (status == MagickFalse)
962 ThrowXWindowFatalException(XServerFatalError,"UnableToCreateXImage",
966 if (display_image->debug != MagickFalse)
968 (void) LogMagickEvent(X11Event,GetMagickModule(),
969 "Image: %s[%.20g] %.20gx%.20g ",image_list[0]->filename,(double)
970 image_list[0]->scene,(double) image_list[0]->columns,(double)
971 image_list[0]->rows);
972 if (image_list[0]->colors != 0)
973 (void) LogMagickEvent(X11Event,GetMagickModule(),"%.20gc ",(double)
974 image_list[0]->colors);
975 (void) LogMagickEvent(X11Event,GetMagickModule(),"%s",
976 image_list[0]->magick);
979 Adjust image dimensions as specified by backdrop or geometry options.
981 width=window_info.width;
982 height=window_info.height;
983 if (resources.backdrop != MagickFalse)
986 Center image on window.
988 window_info.x=(int) (window_attributes.width/2)-
989 (window_info.ximage->width/2);
990 window_info.y=(int) (window_attributes.height/2)-
991 (window_info.ximage->height/2);
992 width=(unsigned int) window_attributes.width;
993 height=(unsigned int) window_attributes.height;
995 if (resources.image_geometry != (char *) NULL)
998 default_geometry[MaxTextExtent];
1008 User specified geometry.
1010 size_hints=XAllocSizeHints();
1011 if (size_hints == (XSizeHints *) NULL)
1012 ThrowXWindowFatalException(ResourceLimitFatalError,
1013 "MemoryAllocationFailed",images->filename);
1014 size_hints->flags=0L;
1015 (void) FormatLocaleString(default_geometry,MaxTextExtent,"%ux%u",width,
1017 flags=XWMGeometry(display,visual_info->screen,resources.image_geometry,
1018 default_geometry,window_info.border_width,size_hints,&window_info.x,
1019 &window_info.y,(int *) &width,(int *) &height,&gravity);
1020 if (((flags & (XValue | YValue))) != 0)
1022 width=(unsigned int) window_attributes.width;
1023 height=(unsigned int) window_attributes.height;
1025 (void) XFree((void *) size_hints);
1028 Create the X pixmap.
1030 window_info.pixmap=XCreatePixmap(display,window_info.id,(unsigned int) width,
1031 (unsigned int) height,window_info.depth);
1032 if (window_info.pixmap == (Pixmap) NULL)
1033 ThrowXWindowFatalException(XServerFatalError,"UnableToCreateXPixmap",
1036 Display pixmap on the window.
1038 if (((unsigned int) width > window_info.width) ||
1039 ((unsigned int) height > window_info.height))
1040 (void) XFillRectangle(display,window_info.pixmap,
1041 window_info.annotate_context,0,0,(unsigned int) width,
1042 (unsigned int) height);
1043 (void) XPutImage(display,window_info.pixmap,window_info.annotate_context,
1044 window_info.ximage,0,0,window_info.x,window_info.y,window_info.width,
1045 window_info.height);
1046 (void) XSetWindowBackgroundPixmap(display,window_info.id,window_info.pixmap);
1047 (void) XClearWindow(display,window_info.id);
1049 Initialize image pixmaps structure.
1051 window_info.pixmaps=(Pixmap *) AcquireQuantumMemory(number_scenes,
1052 sizeof(*window_info.pixmaps));
1053 window_info.matte_pixmaps=(Pixmap *) AcquireQuantumMemory(number_scenes,
1054 sizeof(*window_info.matte_pixmaps));
1055 if ((window_info.pixmaps == (Pixmap *) NULL) ||
1056 (window_info.matte_pixmaps == (Pixmap *) NULL))
1057 ThrowXWindowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed",
1059 window_info.pixmaps[0]=window_info.pixmap;
1060 window_info.matte_pixmaps[0]=window_info.pixmap;
1061 for (scene=1; scene < (int) number_scenes; scene++)
1070 window_info.pixmap=(Pixmap) NULL;
1071 window_info.matte_pixmap=(Pixmap) NULL;
1072 if ((resources.map_type != (char *) NULL) ||
1073 (visual_info->klass == TrueColor) ||
1074 (visual_info->klass == DirectColor))
1075 if (image_list[scene]->storage_class == PseudoClass)
1076 XGetPixelInfo(display,visual_info,map_info,&resources,
1077 image_list[scene],window_info.pixel_info);
1078 columns=(unsigned int) image_list[scene]->columns;
1079 rows=(unsigned int) image_list[scene]->rows;
1080 if ((image_list[scene]->columns != columns) ||
1081 (image_list[scene]->rows != rows))
1082 ThrowXWindowFatalException(XServerFatalError,"UnableToCreateXImage",
1083 image_list[scene]->filename);
1084 status=XMakeImage(display,&resources,&window_info,image_list[scene],
1086 if (status == MagickFalse)
1087 ThrowXWindowFatalException(XServerFatalError,"UnableToCreateXImage",
1089 if (display_image->debug != MagickFalse)
1091 (void) LogMagickEvent(X11Event,GetMagickModule(),
1092 "Image: [%.20g] %s %.20gx%.20g ",(double) image_list[scene]->scene,
1093 image_list[scene]->filename,(double) columns,(double) rows);
1094 if (image_list[scene]->colors != 0)
1095 (void) LogMagickEvent(X11Event,GetMagickModule(),"%.20gc ",(double)
1096 image_list[scene]->colors);
1097 (void) LogMagickEvent(X11Event,GetMagickModule(),"%s",
1098 image_list[scene]->magick);
1101 Create the X pixmap.
1103 window_info.pixmap=XCreatePixmap(display,window_info.id,width,height,
1105 if (window_info.pixmap == (Pixmap) NULL)
1106 ThrowXWindowFatalException(XServerFatalError,"UnableToCreateXPixmap",
1109 Display pixmap on the window.
1111 if ((width > window_info.width) || (height > window_info.height))
1112 (void) XFillRectangle(display,window_info.pixmap,
1113 window_info.annotate_context,0,0,width,height);
1114 (void) XPutImage(display,window_info.pixmap,window_info.annotate_context,
1115 window_info.ximage,0,0,window_info.x,window_info.y,window_info.width,
1116 window_info.height);
1117 (void) XSetWindowBackgroundPixmap(display,window_info.id,
1118 window_info.pixmap);
1119 (void) XClearWindow(display,window_info.id);
1120 window_info.pixmaps[scene]=window_info.pixmap;
1121 window_info.matte_pixmaps[scene]=window_info.matte_pixmap;
1122 if (image_list[scene]->matte)
1123 (void) XClearWindow(display,window_info.id);
1124 delay=1000*image_list[scene]->delay/MagickMax(
1125 image_list[scene]->ticks_per_second,1L);
1126 XDelay(display,resources.delay*(delay == 0 ? 10 : delay));
1128 window_info.pixel_info=(&pixel);
1130 Display pixmap on the window.
1132 (void) XSelectInput(display,window_info.id,SubstructureNotifyMask);
1136 for (scene=0; scene < (int) number_scenes; scene++)
1138 if (XEventsQueued(display,QueuedAfterFlush) > 0)
1140 (void) XNextEvent(display,&event);
1141 if (event.type == DestroyNotify)
1144 window_info.pixmap=window_info.pixmaps[scene];
1145 window_info.matte_pixmap=window_info.matte_pixmaps[scene];
1146 (void) XSetWindowBackgroundPixmap(display,window_info.id,
1147 window_info.pixmap);
1148 (void) XClearWindow(display,window_info.id);
1149 (void) XSync(display,MagickFalse);
1150 delay=1000*image_list[scene]->delay/MagickMax(
1151 image_list[scene]->ticks_per_second,1L);
1152 XDelay(display,resources.delay*(delay == 0 ? 10 : delay));
1154 } while (event.type != DestroyNotify);
1155 (void) XSync(display,MagickFalse);
1156 image_list=(Image **) RelinquishMagickMemory(image_list);
1157 images=DestroyImageList(images);
1161 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1165 + X A n i m a t e I m a g e s %
1169 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1171 % XAnimateImages() displays an image via X11.
1173 % The format of the XAnimateImages method is:
1175 % Image *XAnimateImages(Display *display,XResourceInfo *resource_info,
1176 % char **argv,const int argc,Image *images)
1178 % A description of each parameter follows:
1180 % o display: Specifies a connection to an X server; returned from
1183 % o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
1185 % o argv: Specifies the application's argument list.
1187 % o argc: Specifies the number of arguments.
1189 % o images: the image list.
1192 MagickExport Image *XAnimateImages(Display *display,
1193 XResourceInfo *resource_info,char **argv,const int argc,Image *images)
1195 #define MagickMenus 4
1196 #define MaXWindows 8
1197 #define MagickTitle "Commands"
1235 "Browse Documentation",
1241 **Menus[MagickMenus]=
1249 static const CommandType
1273 DirectionCommands[]=
1281 BrowseDocumentationCommand,
1285 static const CommandType
1286 *Commands[MagickMenus]=
1295 command[MaxTextExtent],
1297 geometry[MaxTextExtent],
1298 resource_name[MaxTextExtent];
1335 working_directory[MaxTextExtent];
1341 *magick_windows[MaXWindows];
1395 assert(images != (Image *) NULL);
1396 assert(images->signature == MagickSignature);
1397 if (images->debug != MagickFalse)
1398 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",images->filename);
1399 warning_handler=(WarningHandler) NULL;
1400 windows=XSetWindows((XWindows *) ~0);
1401 if (windows != (XWindows *) NULL)
1406 status=chdir(working_directory);
1408 (void) ThrowMagickException(&images->exception,GetMagickModule(),
1409 FileOpenError,"UnableToOpenFile","%s",working_directory);
1410 warning_handler=resource_info->display_warnings ?
1411 SetErrorHandler(XWarning) : SetErrorHandler((ErrorHandler) NULL);
1412 warning_handler=resource_info->display_warnings ?
1413 SetWarningHandler(XWarning) : SetWarningHandler((WarningHandler) NULL);
1421 Initialize window structure.
1423 for (p=images; p != (Image *) NULL; p=GetNextImageInList(p))
1425 if (p->storage_class == DirectClass)
1427 resource_info->colors=0;
1430 if (p->colors > resource_info->colors)
1431 resource_info->colors=p->colors;
1433 windows=XSetWindows(XInitializeWindows(display,resource_info));
1434 if (windows == (XWindows *) NULL)
1435 ThrowXWindowFatalException(XServerFatalError,"MemoryAllocationFailed",
1438 Initialize window id's.
1441 magick_windows[number_windows++]=(&windows->icon);
1442 magick_windows[number_windows++]=(&windows->backdrop);
1443 magick_windows[number_windows++]=(&windows->image);
1444 magick_windows[number_windows++]=(&windows->info);
1445 magick_windows[number_windows++]=(&windows->command);
1446 magick_windows[number_windows++]=(&windows->widget);
1447 magick_windows[number_windows++]=(&windows->popup);
1448 for (i=0; i < (ssize_t) number_windows; i++)
1449 magick_windows[i]->id=(Window) NULL;
1452 Initialize font info.
1454 if (windows->font_info != (XFontStruct *) NULL)
1455 (void) XFreeFont(display,windows->font_info);
1456 windows->font_info=XBestFont(display,resource_info,MagickFalse);
1457 if (windows->font_info == (XFontStruct *) NULL)
1458 ThrowXWindowFatalException(XServerFatalError,"UnableToLoadFont",
1459 resource_info->font);
1461 Initialize Standard Colormap.
1463 map_info=windows->map_info;
1464 icon_map=windows->icon_map;
1465 visual_info=windows->visual_info;
1466 icon_visual=windows->icon_visual;
1467 pixel=windows->pixel_info;
1468 icon_pixel=windows->icon_pixel;
1469 font_info=windows->font_info;
1470 icon_resources=windows->icon_resources;
1471 class_hints=windows->class_hints;
1472 manager_hints=windows->manager_hints;
1473 root_window=XRootWindow(display,visual_info->screen);
1474 coalesce_image=CoalesceImages(images,&images->exception);
1475 if (coalesce_image == (Image *) NULL)
1476 ThrowXWindowFatalException(XServerFatalError,"MemoryAllocationFailed",
1478 images=coalesce_image;
1479 if (resource_info->map_type == (char *) NULL)
1480 if ((visual_info->klass != TrueColor) &&
1481 (visual_info->klass != DirectColor))
1487 Determine if the sequence of images has the identical colormap.
1489 for (next=images; next != (Image *) NULL; )
1491 next->matte=MagickFalse;
1492 if ((next->storage_class == DirectClass) ||
1493 (next->colors != images->colors) ||
1494 (next->colors > (size_t) visual_info->colormap_size))
1496 for (i=0; i < (ssize_t) images->colors; i++)
1497 if (IsPixelPacketEquivalent(next->colormap+i,images->colormap+i) == MagickFalse)
1499 if (i < (ssize_t) images->colors)
1501 next=GetNextImageInList(next);
1503 if (next != (Image *) NULL)
1504 (void) RemapImages(resource_info->quantize_info,images,
1508 Sort images by increasing scene number.
1510 number_scenes=GetImageListLength(images);
1511 image_list=ImageListToArray(images,&images->exception);
1512 if (image_list == (Image **) NULL)
1513 ThrowXWindowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed",
1515 for (scene=0; scene < (ssize_t) number_scenes; scene++)
1516 if (image_list[scene]->scene == 0)
1518 if (scene == (ssize_t) number_scenes)
1519 qsort((void *) image_list,number_scenes,sizeof(Image *),SceneCompare);
1521 Initialize Standard Colormap.
1523 nexus=NewImageList();
1524 display_image=image_list[0];
1525 for (scene=0; scene < (ssize_t) number_scenes; scene++)
1527 if ((resource_info->map_type != (char *) NULL) ||
1528 (visual_info->klass == TrueColor) ||
1529 (visual_info->klass == DirectColor))
1530 (void) SetImageType(image_list[scene],image_list[scene]->matte ==
1531 MagickFalse ? TrueColorType : TrueColorMatteType);
1532 if ((display_image->columns < image_list[scene]->columns) &&
1533 (display_image->rows < image_list[scene]->rows))
1534 display_image=image_list[scene];
1536 if (display_image->debug != MagickFalse)
1538 (void) LogMagickEvent(X11Event,GetMagickModule(),
1539 "Image: %s[%.20g] %.20gx%.20g ",display_image->filename,(double)
1540 display_image->scene,(double) display_image->columns,(double)
1541 display_image->rows);
1542 if (display_image->colors != 0)
1543 (void) LogMagickEvent(X11Event,GetMagickModule(),"%.20gc ",(double)
1544 display_image->colors);
1545 (void) LogMagickEvent(X11Event,GetMagickModule(),"%s",
1546 display_image->magick);
1548 XMakeStandardColormap(display,visual_info,resource_info,display_image,
1551 Initialize graphic context.
1553 windows->context.id=(Window) NULL;
1554 XGetWindowInfo(display,visual_info,map_info,pixel,font_info,
1555 resource_info,&windows->context);
1556 (void) CloneString(&class_hints->res_name,resource_info->client_name);
1557 (void) CloneString(&class_hints->res_class,resource_info->client_name);
1558 class_hints->res_class[0]=(char) toupper((int) class_hints->res_class[0]);
1559 manager_hints->flags=InputHint | StateHint;
1560 manager_hints->input=MagickFalse;
1561 manager_hints->initial_state=WithdrawnState;
1562 XMakeWindow(display,root_window,argv,argc,class_hints,manager_hints,
1564 if (display_image->debug != MagickFalse)
1565 (void) LogMagickEvent(X11Event,GetMagickModule(),
1566 "Window id: 0x%lx (context)",windows->context.id);
1567 context_values.background=pixel->background_color.pixel;
1568 context_values.font=font_info->fid;
1569 context_values.foreground=pixel->foreground_color.pixel;
1570 context_values.graphics_exposures=MagickFalse;
1571 context_mask=(MagickStatusType)
1572 (GCBackground | GCFont | GCForeground | GCGraphicsExposures);
1573 if (pixel->annotate_context != (GC) NULL)
1574 (void) XFreeGC(display,pixel->annotate_context);
1575 pixel->annotate_context=
1576 XCreateGC(display,windows->context.id,context_mask,&context_values);
1577 if (pixel->annotate_context == (GC) NULL)
1578 ThrowXWindowFatalException(XServerFatalError,"UnableToCreateGraphicContext",
1580 context_values.background=pixel->depth_color.pixel;
1581 if (pixel->widget_context != (GC) NULL)
1582 (void) XFreeGC(display,pixel->widget_context);
1583 pixel->widget_context=
1584 XCreateGC(display,windows->context.id,context_mask,&context_values);
1585 if (pixel->widget_context == (GC) NULL)
1586 ThrowXWindowFatalException(XServerFatalError,"UnableToCreateGraphicContext",
1588 context_values.background=pixel->foreground_color.pixel;
1589 context_values.foreground=pixel->background_color.pixel;
1590 context_values.plane_mask=
1591 context_values.background ^ context_values.foreground;
1592 if (pixel->highlight_context != (GC) NULL)
1593 (void) XFreeGC(display,pixel->highlight_context);
1594 pixel->highlight_context=XCreateGC(display,windows->context.id,
1595 (size_t) (context_mask | GCPlaneMask),&context_values);
1596 if (pixel->highlight_context == (GC) NULL)
1597 ThrowXWindowFatalException(XServerFatalError,"UnableToCreateGraphicContext",
1599 (void) XDestroyWindow(display,windows->context.id);
1601 Initialize icon window.
1603 XGetWindowInfo(display,icon_visual,icon_map,icon_pixel,(XFontStruct *) NULL,
1604 icon_resources,&windows->icon);
1605 windows->icon.geometry=resource_info->icon_geometry;
1606 XBestIconSize(display,&windows->icon,display_image);
1607 windows->icon.attributes.colormap=
1608 XDefaultColormap(display,icon_visual->screen);
1609 windows->icon.attributes.event_mask=ExposureMask | StructureNotifyMask;
1610 manager_hints->flags=InputHint | StateHint;
1611 manager_hints->input=MagickFalse;
1612 manager_hints->initial_state=IconicState;
1613 XMakeWindow(display,root_window,argv,argc,class_hints,manager_hints,
1615 if (display_image->debug != MagickFalse)
1616 (void) LogMagickEvent(X11Event,GetMagickModule(),"Window id: 0x%lx (icon)",
1619 Initialize graphic context for icon window.
1621 if (icon_pixel->annotate_context != (GC) NULL)
1622 (void) XFreeGC(display,icon_pixel->annotate_context);
1623 context_values.background=icon_pixel->background_color.pixel;
1624 context_values.foreground=icon_pixel->foreground_color.pixel;
1625 icon_pixel->annotate_context=XCreateGC(display,windows->icon.id,
1626 (size_t) (GCBackground | GCForeground),&context_values);
1627 if (icon_pixel->annotate_context == (GC) NULL)
1628 ThrowXWindowFatalException(XServerFatalError,"UnableToCreateGraphicContext",
1630 windows->icon.annotate_context=icon_pixel->annotate_context;
1632 Initialize Image window.
1634 XGetWindowInfo(display,visual_info,map_info,pixel,font_info,
1635 resource_info,&windows->image);
1636 windows->image.shape=MagickTrue; /* non-rectangular shape hint */
1637 if (resource_info->use_shared_memory == MagickFalse)
1638 windows->image.shared_memory=MagickFalse;
1639 if (resource_info->title != (char *) NULL)
1644 title=InterpretImageProperties(resource_info->image_info,display_image,
1645 resource_info->title);
1646 (void) CopyMagickString(windows->image.name,title,MaxTextExtent);
1647 (void) CopyMagickString(windows->image.icon_name,title,MaxTextExtent);
1648 title=DestroyString(title);
1653 filename[MaxTextExtent];
1656 Window name is the base of the filename.
1658 GetPathComponent(display_image->magick_filename,TailPath,filename);
1659 (void) FormatLocaleString(windows->image.name,MaxTextExtent,
1660 "%s: %s[scene: %.20g frames: %.20g]",MagickPackageName,filename,(double)
1661 display_image->scene,(double) number_scenes);
1662 (void) CopyMagickString(windows->image.icon_name,filename,MaxTextExtent);
1664 if (resource_info->immutable != MagickFalse)
1665 windows->image.immutable=MagickTrue;
1666 windows->image.shape=MagickTrue;
1667 windows->image.geometry=resource_info->image_geometry;
1668 (void) FormatLocaleString(geometry,MaxTextExtent,"%ux%u+0+0>!",
1669 XDisplayWidth(display,visual_info->screen),
1670 XDisplayHeight(display,visual_info->screen));
1671 geometry_info.width=display_image->columns;
1672 geometry_info.height=display_image->rows;
1675 (void) ParseMetaGeometry(geometry,&geometry_info.x,&geometry_info.y,
1676 &geometry_info.width,&geometry_info.height);
1677 windows->image.width=(unsigned int) geometry_info.width;
1678 windows->image.height=(unsigned int) geometry_info.height;
1679 windows->image.attributes.event_mask=ButtonMotionMask | ButtonPressMask |
1680 ButtonReleaseMask | EnterWindowMask | ExposureMask | KeyPressMask |
1681 KeyReleaseMask | LeaveWindowMask | OwnerGrabButtonMask |
1682 PropertyChangeMask | StructureNotifyMask | SubstructureNotifyMask;
1683 XGetWindowInfo(display,visual_info,map_info,pixel,font_info,
1684 resource_info,&windows->backdrop);
1685 if ((resource_info->backdrop) || (windows->backdrop.id != (Window) NULL))
1688 Initialize backdrop window.
1690 windows->backdrop.x=0;
1691 windows->backdrop.y=0;
1692 (void) CloneString(&windows->backdrop.name,"ImageMagick Backdrop");
1693 windows->backdrop.flags=(size_t) (USSize | USPosition);
1694 windows->backdrop.width=(unsigned int)
1695 XDisplayWidth(display,visual_info->screen);
1696 windows->backdrop.height=(unsigned int)
1697 XDisplayHeight(display,visual_info->screen);
1698 windows->backdrop.border_width=0;
1699 windows->backdrop.immutable=MagickTrue;
1700 windows->backdrop.attributes.do_not_propagate_mask=ButtonPressMask |
1702 windows->backdrop.attributes.event_mask=ButtonPressMask | KeyPressMask |
1703 StructureNotifyMask;
1704 manager_hints->flags=IconWindowHint | InputHint | StateHint;
1705 manager_hints->icon_window=windows->icon.id;
1706 manager_hints->input=MagickTrue;
1707 manager_hints->initial_state=
1708 resource_info->iconic ? IconicState : NormalState;
1709 XMakeWindow(display,root_window,argv,argc,class_hints,manager_hints,
1710 &windows->backdrop);
1711 if (display_image->debug != MagickFalse)
1712 (void) LogMagickEvent(X11Event,GetMagickModule(),
1713 "Window id: 0x%lx (backdrop)",windows->backdrop.id);
1714 (void) XMapWindow(display,windows->backdrop.id);
1715 (void) XClearWindow(display,windows->backdrop.id);
1716 if (windows->image.id != (Window) NULL)
1718 (void) XDestroyWindow(display,windows->image.id);
1719 windows->image.id=(Window) NULL;
1722 Position image in the center the backdrop.
1724 windows->image.flags|=USPosition;
1725 windows->image.x=(XDisplayWidth(display,visual_info->screen)/2)-
1726 (windows->image.width/2);
1727 windows->image.y=(XDisplayHeight(display,visual_info->screen)/2)-
1728 (windows->image.height/2);
1730 manager_hints->flags=IconWindowHint | InputHint | StateHint;
1731 manager_hints->icon_window=windows->icon.id;
1732 manager_hints->input=MagickTrue;
1733 manager_hints->initial_state=
1734 resource_info->iconic ? IconicState : NormalState;
1735 if (windows->group_leader.id != (Window) NULL)
1740 manager_hints->flags|=(MagickStatusType) WindowGroupHint;
1741 manager_hints->window_group=windows->group_leader.id;
1742 (void) XSelectInput(display,windows->group_leader.id,StructureNotifyMask);
1743 if (display_image->debug != MagickFalse)
1744 (void) LogMagickEvent(X11Event,GetMagickModule(),
1745 "Window id: 0x%lx (group leader)",windows->group_leader.id);
1747 XMakeWindow(display,
1748 (Window) (resource_info->backdrop ? windows->backdrop.id : root_window),
1749 argv,argc,class_hints,manager_hints,&windows->image);
1750 (void) XChangeProperty(display,windows->image.id,windows->im_protocols,
1751 XA_STRING,8,PropModeReplace,(unsigned char *) NULL,0);
1752 if (windows->group_leader.id != (Window) NULL)
1753 (void) XSetTransientForHint(display,windows->image.id,
1754 windows->group_leader.id);
1755 if (display_image->debug != MagickFalse)
1756 (void) LogMagickEvent(X11Event,GetMagickModule(),"Window id: 0x%lx (image)",
1759 Initialize Info widget.
1761 XGetWindowInfo(display,visual_info,map_info,pixel,font_info,
1762 resource_info,&windows->info);
1763 (void) CloneString(&windows->info.name,"Info");
1764 (void) CloneString(&windows->info.icon_name,"Info");
1765 windows->info.border_width=1;
1768 windows->info.flags|=PPosition;
1769 windows->info.attributes.win_gravity=UnmapGravity;
1770 windows->info.attributes.event_mask=ButtonPressMask | ExposureMask |
1771 StructureNotifyMask;
1772 manager_hints->flags=InputHint | StateHint | WindowGroupHint;
1773 manager_hints->input=MagickFalse;
1774 manager_hints->initial_state=NormalState;
1775 manager_hints->window_group=windows->image.id;
1776 XMakeWindow(display,windows->image.id,argv,argc,class_hints,manager_hints,
1778 windows->info.highlight_stipple=XCreateBitmapFromData(display,
1779 windows->info.id,(char *) HighlightBitmap,HighlightWidth,HighlightHeight);
1780 windows->info.shadow_stipple=XCreateBitmapFromData(display,
1781 windows->info.id,(char *) ShadowBitmap,ShadowWidth,ShadowHeight);
1782 (void) XSetTransientForHint(display,windows->info.id,windows->image.id);
1783 if (windows->image.mapped)
1784 (void) XWithdrawWindow(display,windows->info.id,windows->info.screen);
1785 if (display_image->debug != MagickFalse)
1786 (void) LogMagickEvent(X11Event,GetMagickModule(),"Window id: 0x%lx (info)",
1789 Initialize Command widget.
1791 XGetWindowInfo(display,visual_info,map_info,pixel,font_info,
1792 resource_info,&windows->command);
1793 windows->command.data=MagickMenus;
1794 (void) XCommandWidget(display,windows,CommandMenu,(XEvent *) NULL);
1795 (void) FormatLocaleString(resource_name,MaxTextExtent,"%s.command",
1796 resource_info->client_name);
1797 windows->command.geometry=XGetResourceClass(resource_info->resource_database,
1798 resource_name,"geometry",(char *) NULL);
1799 (void) CloneString(&windows->command.name,MagickTitle);
1800 windows->command.border_width=0;
1801 windows->command.flags|=PPosition;
1802 windows->command.attributes.event_mask=ButtonMotionMask | ButtonPressMask |
1803 ButtonReleaseMask | EnterWindowMask | ExposureMask | LeaveWindowMask |
1804 OwnerGrabButtonMask | StructureNotifyMask;
1805 manager_hints->flags=InputHint | StateHint | WindowGroupHint;
1806 manager_hints->input=MagickTrue;
1807 manager_hints->initial_state=NormalState;
1808 manager_hints->window_group=windows->image.id;
1809 XMakeWindow(display,root_window,argv,argc,class_hints,manager_hints,
1811 windows->command.highlight_stipple=XCreateBitmapFromData(display,
1812 windows->command.id,(char *) HighlightBitmap,HighlightWidth,
1814 windows->command.shadow_stipple=XCreateBitmapFromData(display,
1815 windows->command.id,(char *) ShadowBitmap,ShadowWidth,ShadowHeight);
1816 (void) XSetTransientForHint(display,windows->command.id,windows->image.id);
1817 if (display_image->debug != MagickFalse)
1818 (void) LogMagickEvent(X11Event,GetMagickModule(),
1819 "Window id: 0x%lx (command)",windows->command.id);
1821 Initialize Widget window.
1823 XGetWindowInfo(display,visual_info,map_info,pixel,font_info,
1824 resource_info,&windows->widget);
1825 (void) FormatLocaleString(resource_name,MaxTextExtent,"%s.widget",
1826 resource_info->client_name);
1827 windows->widget.geometry=XGetResourceClass(resource_info->resource_database,
1828 resource_name,"geometry",(char *) NULL);
1829 windows->widget.border_width=0;
1830 windows->widget.flags|=PPosition;
1831 windows->widget.attributes.event_mask=ButtonMotionMask | ButtonPressMask |
1832 ButtonReleaseMask | EnterWindowMask | ExposureMask | KeyPressMask |
1833 KeyReleaseMask | LeaveWindowMask | OwnerGrabButtonMask |
1834 StructureNotifyMask;
1835 manager_hints->flags=InputHint | StateHint | WindowGroupHint;
1836 manager_hints->input=MagickTrue;
1837 manager_hints->initial_state=NormalState;
1838 manager_hints->window_group=windows->image.id;
1839 XMakeWindow(display,root_window,argv,argc,class_hints,manager_hints,
1841 windows->widget.highlight_stipple=XCreateBitmapFromData(display,
1842 windows->widget.id,(char *) HighlightBitmap,HighlightWidth,HighlightHeight);
1843 windows->widget.shadow_stipple=XCreateBitmapFromData(display,
1844 windows->widget.id,(char *) ShadowBitmap,ShadowWidth,ShadowHeight);
1845 (void) XSetTransientForHint(display,windows->widget.id,windows->image.id);
1846 if (display_image->debug != MagickFalse)
1847 (void) LogMagickEvent(X11Event,GetMagickModule(),
1848 "Window id: 0x%lx (widget)",windows->widget.id);
1850 Initialize popup window.
1852 XGetWindowInfo(display,visual_info,map_info,pixel,font_info,
1853 resource_info,&windows->popup);
1854 windows->popup.border_width=0;
1855 windows->popup.flags|=PPosition;
1856 windows->popup.attributes.event_mask=ButtonMotionMask | ButtonPressMask |
1857 ButtonReleaseMask | EnterWindowMask | ExposureMask | KeyPressMask |
1858 KeyReleaseMask | LeaveWindowMask | StructureNotifyMask;
1859 manager_hints->flags=InputHint | StateHint | WindowGroupHint;
1860 manager_hints->input=MagickTrue;
1861 manager_hints->initial_state=NormalState;
1862 manager_hints->window_group=windows->image.id;
1863 XMakeWindow(display,root_window,argv,argc,class_hints,manager_hints,
1865 windows->popup.highlight_stipple=XCreateBitmapFromData(display,
1866 windows->popup.id,(char *) HighlightBitmap,HighlightWidth,HighlightHeight);
1867 windows->popup.shadow_stipple=XCreateBitmapFromData(display,
1868 windows->popup.id,(char *) ShadowBitmap,ShadowWidth,ShadowHeight);
1869 (void) XSetTransientForHint(display,windows->popup.id,windows->image.id);
1870 if (display_image->debug != MagickFalse)
1871 (void) LogMagickEvent(X11Event,GetMagickModule(),
1872 "Window id: 0x%lx (pop up)",windows->popup.id);
1874 Set out progress and warning handlers.
1876 if (warning_handler == (WarningHandler) NULL)
1878 warning_handler=resource_info->display_warnings ?
1879 SetErrorHandler(XWarning) : SetErrorHandler((ErrorHandler) NULL);
1880 warning_handler=resource_info->display_warnings ?
1881 SetWarningHandler(XWarning) : SetWarningHandler((WarningHandler) NULL);
1884 Initialize X image structure.
1889 Initialize image pixmaps structure.
1891 window_changes.width=(int) windows->image.width;
1892 window_changes.height=(int) windows->image.height;
1893 (void) XReconfigureWMWindow(display,windows->image.id,windows->command.screen,
1894 (unsigned int) (CWWidth | CWHeight),&window_changes);
1895 windows->image.pixmaps=(Pixmap *) AcquireQuantumMemory(number_scenes,
1896 sizeof(*windows->image.pixmaps));
1897 windows->image.matte_pixmaps=(Pixmap *) AcquireQuantumMemory(number_scenes,
1898 sizeof(*windows->image.pixmaps));
1899 if ((windows->image.pixmaps == (Pixmap *) NULL) ||
1900 (windows->image.matte_pixmaps == (Pixmap *) NULL))
1901 ThrowXWindowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed",
1903 if ((windows->image.mapped == MagickFalse) ||
1904 (windows->backdrop.id != (Window) NULL))
1905 (void) XMapWindow(display,windows->image.id);
1906 XSetCursorState(display,windows,MagickTrue);
1907 for (scene=0; scene < (ssize_t) number_scenes; scene++)
1916 (void) TransformImageColorspace(image_list[scene],RGBColorspace);
1917 windows->image.pixmap=(Pixmap) NULL;
1918 windows->image.matte_pixmap=(Pixmap) NULL;
1919 if ((resource_info->map_type != (char *) NULL) ||
1920 (visual_info->klass == TrueColor) ||
1921 (visual_info->klass == DirectColor))
1922 if (image_list[scene]->storage_class == PseudoClass)
1923 XGetPixelInfo(display,visual_info,map_info,resource_info,
1924 image_list[scene],windows->image.pixel_info);
1925 columns=(unsigned int) image_list[scene]->columns;
1926 rows=(unsigned int) image_list[scene]->rows;
1927 if ((image_list[scene]->columns != columns) ||
1928 (image_list[scene]->rows != rows))
1929 ThrowXWindowFatalException(XServerFatalError,"UnableToCreateXImage",
1930 image_list[scene]->filename);
1931 status=XMakeImage(display,resource_info,&windows->image,image_list[scene],
1933 if (status == MagickFalse)
1934 ThrowXWindowFatalException(XServerFatalError,"UnableToCreateXImage",
1936 if (image_list[scene]->debug != MagickFalse)
1938 (void) LogMagickEvent(X11Event,GetMagickModule(),
1939 "Image: [%.20g] %s %.20gx%.20g ",(double) image_list[scene]->scene,
1940 image_list[scene]->filename,(double) columns,(double) rows);
1941 if (image_list[scene]->colors != 0)
1942 (void) LogMagickEvent(X11Event,GetMagickModule(),"%.20gc ",(double)
1943 image_list[scene]->colors);
1944 (void) LogMagickEvent(X11Event,GetMagickModule(),"%s",
1945 image_list[scene]->magick);
1948 Window name is the base of the filename.
1950 if (resource_info->title != (char *) NULL)
1955 title=InterpretImageProperties(resource_info->image_info,
1956 image_list[scene],resource_info->title);
1957 (void) CopyMagickString(windows->image.name,title,MaxTextExtent);
1958 title=DestroyString(title);
1962 p=image_list[scene]->magick_filename+
1963 strlen(image_list[scene]->magick_filename)-1;
1964 while ((p > image_list[scene]->magick_filename) && (*(p-1) != '/'))
1966 (void) FormatLocaleString(windows->image.name,MaxTextExtent,
1967 "%s: %s[%.20g of %.20g]",MagickPackageName,p,(double) scene+1,
1968 (double) number_scenes);
1970 status=XStringListToTextProperty(&windows->image.name,1,&window_name);
1971 if (status != Success)
1973 XSetWMName(display,windows->image.id,&window_name);
1974 (void) XFree((void *) window_name.value);
1976 windows->image.pixmaps[scene]=windows->image.pixmap;
1977 windows->image.matte_pixmaps[scene]=windows->image.matte_pixmap;
1982 event.xexpose.width=(int) image_list[scene]->columns;
1983 event.xexpose.height=(int) image_list[scene]->rows;
1984 XRefreshWindow(display,&windows->image,&event);
1985 (void) XSync(display,MagickFalse);
1988 XSetCursorState(display,windows,MagickFalse);
1989 if (windows->command.mapped)
1990 (void) XMapRaised(display,windows->command.id);
1994 nexus=NewImageList();
1998 image=image_list[0];
1999 state=(MagickStatusType) (ForwardAnimationState | RepeatAnimationState);
2000 (void) XMagickCommand(display,resource_info,windows,PlayCommand,&images,
2004 if (XEventsQueued(display,QueuedAfterFlush) == 0)
2005 if ((state & PlayAnimationState) || (state & StepAnimationState))
2011 delay=1000*image->delay/MagickMax(image->ticks_per_second,1L);
2012 XDelay(display,resource_info->delay*(delay == 0 ? 10 : delay));
2013 if (state & ForwardAnimationState)
2016 Forward animation: increment scene number.
2018 if (scene < ((ssize_t) number_scenes-1))
2023 if (iterations == (ssize_t) image_list[0]->iterations)
2028 if ((state & AutoReverseAnimationState) != 0)
2030 state&=(~ForwardAnimationState);
2035 if ((state & RepeatAnimationState) == 0)
2036 state&=(~PlayAnimationState);
2045 Reverse animation: decrement scene number.
2047 if (scene > first_scene)
2052 if (iterations == (ssize_t) image_list[0]->iterations)
2055 state&=(~RepeatAnimationState);
2057 if (state & AutoReverseAnimationState)
2059 state|=ForwardAnimationState;
2065 if ((state & RepeatAnimationState) == MagickFalse)
2066 state&=(~PlayAnimationState);
2067 scene=(ssize_t) number_scenes-1;
2071 scene=MagickMax(scene,0);
2072 image=image_list[scene];
2073 if ((image != (Image *) NULL) && (image->start_loop != 0))
2075 if ((state & StepAnimationState) ||
2076 (resource_info->title != (char *) NULL))
2079 Update window title.
2081 p=image_list[scene]->filename+
2082 strlen(image_list[scene]->filename)-1;
2083 while ((p > image_list[scene]->filename) && (*(p-1) != '/'))
2085 (void) FormatLocaleString(windows->image.name,MaxTextExtent,
2086 "%s: %s[%.20g of %.20g]",MagickPackageName,p,(double)
2087 scene+1,(double) number_scenes);
2088 if (resource_info->title != (char *) NULL)
2093 title=InterpretImageProperties(resource_info->image_info,
2094 image,resource_info->title);
2095 (void) CopyMagickString(windows->image.name,title,
2097 title=DestroyString(title);
2099 status=XStringListToTextProperty(&windows->image.name,1,
2101 if (status != Success)
2103 XSetWMName(display,windows->image.id,&window_name);
2104 (void) XFree((void *) window_name.value);
2108 Copy X pixmap to Image window.
2110 XGetPixelInfo(display,visual_info,map_info,resource_info,
2111 image_list[scene],windows->image.pixel_info);
2112 windows->image.ximage->width=(int) image->columns;
2113 windows->image.ximage->height=(int) image->rows;
2114 windows->image.pixmap=windows->image.pixmaps[scene];
2115 windows->image.matte_pixmap=windows->image.matte_pixmaps[scene];
2118 event.xexpose.width=(int) image->columns;
2119 event.xexpose.height=(int) image->rows;
2120 if ((state & ExitState) == 0)
2122 XRefreshWindow(display,&windows->image,&event);
2123 (void) XSync(display,MagickFalse);
2125 state&=(~StepAnimationState);
2126 if (pause != MagickFalse)
2127 for (i=0; i < (ssize_t) resource_info->pause; i++)
2132 status=XCheckTypedWindowEvent(display,windows->image.id,KeyPress,
2139 length=XLookupString((XKeyEvent *) &event.xkey,command,(int)
2140 sizeof(command),&key_symbol,(XComposeStatus *) NULL);
2141 *(command+length)='\0';
2142 if ((key_symbol == XK_q) || (key_symbol == XK_Escape))
2144 XClientMessage(display,windows->image.id,
2145 windows->im_protocols,windows->im_exit,CurrentTime);
2154 Handle a window event.
2156 timestamp=time((time_t *) NULL);
2157 (void) XNextEvent(display,&event);
2158 if (windows->image.stasis == MagickFalse)
2159 windows->image.stasis=(time((time_t *) NULL)-timestamp) > 0 ?
2160 MagickTrue : MagickFalse;
2161 if (event.xany.window == windows->command.id)
2167 Select a command from the Command widget.
2169 id=XCommandWidget(display,windows,CommandMenu,&event);
2172 (void) CopyMagickString(command,CommandMenu[id],MaxTextExtent);
2173 command_type=CommandMenus[id];
2174 if (id < MagickMenus)
2180 Select a command from a pop-up menu.
2182 entry=XMenuWidget(display,windows,CommandMenu[id],Menus[id],
2186 (void) CopyMagickString(command,Menus[id][entry],MaxTextExtent);
2187 command_type=Commands[id][entry];
2189 if (command_type != NullCommand)
2190 nexus=XMagickCommand(display,resource_info,windows,
2191 command_type,&image,&state);
2198 if (display_image->debug != MagickFalse)
2199 (void) LogMagickEvent(X11Event,GetMagickModule(),
2200 "Button Press: 0x%lx %u +%d+%d",event.xbutton.window,
2201 event.xbutton.button,event.xbutton.x,event.xbutton.y);
2202 if ((event.xbutton.button == Button3) &&
2203 (event.xbutton.state & Mod1Mask))
2206 Convert Alt-Button3 to Button2.
2208 event.xbutton.button=Button2;
2209 event.xbutton.state&=(~Mod1Mask);
2211 if (event.xbutton.window == windows->backdrop.id)
2213 (void) XSetInputFocus(display,event.xbutton.window,RevertToParent,
2214 event.xbutton.time);
2217 if (event.xbutton.window == windows->image.id)
2219 if (resource_info->immutable != MagickFalse)
2225 Map/unmap Command widget.
2227 if (windows->command.mapped)
2228 (void) XWithdrawWindow(display,windows->command.id,
2229 windows->command.screen);
2232 (void) XCommandWidget(display,windows,CommandMenu,
2234 (void) XMapRaised(display,windows->command.id);
2241 if (display_image->debug != MagickFalse)
2242 (void) LogMagickEvent(X11Event,GetMagickModule(),
2243 "Button Release: 0x%lx %u +%d+%d",event.xbutton.window,
2244 event.xbutton.button,event.xbutton.x,event.xbutton.y);
2249 if (display_image->debug != MagickFalse)
2250 (void) LogMagickEvent(X11Event,GetMagickModule(),
2251 "Client Message: 0x%lx 0x%lx %d 0x%lx",(unsigned long)
2252 event.xclient.window,(unsigned long) event.xclient.message_type,
2253 event.xclient.format,(unsigned long) event.xclient.data.l[0]);
2254 if (event.xclient.message_type == windows->im_protocols)
2256 if (*event.xclient.data.l == (long) windows->im_update_colormap)
2259 Update graphic context and window colormap.
2261 for (i=0; i < (ssize_t) number_windows; i++)
2263 if (magick_windows[i]->id == windows->icon.id)
2265 context_values.background=pixel->background_color.pixel;
2266 context_values.foreground=pixel->foreground_color.pixel;
2267 (void) XChangeGC(display,magick_windows[i]->annotate_context,
2268 context_mask,&context_values);
2269 (void) XChangeGC(display,magick_windows[i]->widget_context,
2270 context_mask,&context_values);
2271 context_values.background=pixel->foreground_color.pixel;
2272 context_values.foreground=pixel->background_color.pixel;
2273 context_values.plane_mask=
2274 context_values.background ^ context_values.foreground;
2275 (void) XChangeGC(display,magick_windows[i]->highlight_context,
2276 (size_t) (context_mask | GCPlaneMask),
2278 magick_windows[i]->attributes.background_pixel=
2279 pixel->background_color.pixel;
2280 magick_windows[i]->attributes.border_pixel=
2281 pixel->border_color.pixel;
2282 magick_windows[i]->attributes.colormap=map_info->colormap;
2283 (void) XChangeWindowAttributes(display,magick_windows[i]->id,
2284 (unsigned long) magick_windows[i]->mask,
2285 &magick_windows[i]->attributes);
2287 if (windows->backdrop.id != (Window) NULL)
2288 (void) XInstallColormap(display,map_info->colormap);
2291 if (*event.xclient.data.l == (long) windows->im_exit)
2298 if (event.xclient.message_type == windows->dnd_protocols)
2316 Display image named by the Drag-and-Drop selection.
2318 if ((*event.xclient.data.l != 2) && (*event.xclient.data.l != 128))
2320 selection=XInternAtom(display,"DndSelection",MagickFalse);
2321 status=XGetWindowProperty(display,root_window,selection,0L,2047L,
2322 MagickFalse,(Atom) AnyPropertyType,&type,&format,&length,&after,
2324 if ((status != Success) || (length == 0))
2326 if (*event.xclient.data.l == 2)
2331 (void) CopyMagickString(resource_info->image_info->filename,
2332 (char *) data,MaxTextExtent);
2339 if (LocaleNCompare((char *) data,"file:",5) != 0)
2341 (void) XFree((void *) data);
2344 (void) CopyMagickString(resource_info->image_info->filename,
2345 ((char *) data)+5,MaxTextExtent);
2347 nexus=ReadImage(resource_info->image_info,&image->exception);
2348 CatchException(&image->exception);
2349 if (nexus != (Image *) NULL)
2351 (void) XFree((void *) data);
2355 If client window delete message, exit.
2357 if (event.xclient.message_type != windows->wm_protocols)
2359 if (*event.xclient.data.l == (long) windows->wm_take_focus)
2361 (void) XSetInputFocus(display,event.xclient.window,RevertToParent,
2362 (Time) event.xclient.data.l[1]);
2365 if (*event.xclient.data.l != (long) windows->wm_delete_window)
2367 (void) XWithdrawWindow(display,event.xclient.window,
2368 visual_info->screen);
2369 if (event.xclient.window == windows->image.id)
2376 case ConfigureNotify:
2378 if (display_image->debug != MagickFalse)
2379 (void) LogMagickEvent(X11Event,GetMagickModule(),
2380 "Configure Notify: 0x%lx %dx%d+%d+%d %d",event.xconfigure.window,
2381 event.xconfigure.width,event.xconfigure.height,event.xconfigure.x,
2382 event.xconfigure.y,event.xconfigure.send_event);
2383 if (event.xconfigure.window == windows->image.id)
2385 if (event.xconfigure.send_event != 0)
2391 Position the transient windows relative of the Image window.
2393 if (windows->command.geometry == (char *) NULL)
2394 if (windows->command.mapped == MagickFalse)
2397 event.xconfigure.x-windows->command.width-25;
2398 windows->command.y=event.xconfigure.y;
2399 XConstrainWindowPosition(display,&windows->command);
2400 window_changes.x=windows->command.x;
2401 window_changes.y=windows->command.y;
2402 (void) XReconfigureWMWindow(display,windows->command.id,
2403 windows->command.screen,(unsigned int) (CWX | CWY),
2406 if (windows->widget.geometry == (char *) NULL)
2407 if (windows->widget.mapped == MagickFalse)
2410 event.xconfigure.x+event.xconfigure.width/10;
2412 event.xconfigure.y+event.xconfigure.height/10;
2413 XConstrainWindowPosition(display,&windows->widget);
2414 window_changes.x=windows->widget.x;
2415 window_changes.y=windows->widget.y;
2416 (void) XReconfigureWMWindow(display,windows->widget.id,
2417 windows->widget.screen,(unsigned int) (CWX | CWY),
2422 Image window has a new configuration.
2424 windows->image.width=(unsigned int) event.xconfigure.width;
2425 windows->image.height=(unsigned int) event.xconfigure.height;
2428 if (event.xconfigure.window == windows->icon.id)
2431 Icon window has a new configuration.
2433 windows->icon.width=(unsigned int) event.xconfigure.width;
2434 windows->icon.height=(unsigned int) event.xconfigure.height;
2442 Group leader has exited.
2444 if (display_image->debug != MagickFalse)
2445 (void) LogMagickEvent(X11Event,GetMagickModule(),
2446 "Destroy Notify: 0x%lx",event.xdestroywindow.window);
2447 if (event.xdestroywindow.window == windows->group_leader.id)
2457 Selectively install colormap.
2459 if (map_info->colormap != XDefaultColormap(display,visual_info->screen))
2460 if (event.xcrossing.mode != NotifyUngrab)
2461 XInstallColormap(display,map_info->colormap);
2466 if (display_image->debug != MagickFalse)
2467 (void) LogMagickEvent(X11Event,GetMagickModule(),
2468 "Expose: 0x%lx %dx%d+%d+%d",event.xexpose.window,
2469 event.xexpose.width,event.xexpose.height,event.xexpose.x,
2472 Repaint windows that are now exposed.
2474 if (event.xexpose.window == windows->image.id)
2476 windows->image.pixmap=windows->image.pixmaps[scene];
2477 windows->image.matte_pixmap=windows->image.matte_pixmaps[scene];
2478 XRefreshWindow(display,&windows->image,&event);
2481 if (event.xexpose.window == windows->icon.id)
2482 if (event.xexpose.count == 0)
2484 XRefreshWindow(display,&windows->icon,&event);
2495 Respond to a user key press.
2497 length=XLookupString((XKeyEvent *) &event.xkey,command,(int)
2498 sizeof(command),&key_symbol,(XComposeStatus *) NULL);
2499 *(command+length)='\0';
2500 if (display_image->debug != MagickFalse)
2501 (void) LogMagickEvent(X11Event,GetMagickModule(),
2502 "Key press: 0x%lx (%c)",(unsigned long) key_symbol,*command);
2503 command_type=NullCommand;
2508 if ((event.xkey.state & ControlMask) == MagickFalse)
2510 command_type=OpenCommand;
2515 command_type=StepBackwardCommand;
2520 command_type=StepForwardCommand;
2525 command_type=FasterCommand;
2530 command_type=SlowerCommand;
2535 command_type=HelpCommand;
2540 command_type=BrowseDocumentationCommand;
2545 command_type=InfoCommand;
2551 command_type=QuitCommand;
2557 if (command_type != NullCommand)
2558 nexus=XMagickCommand(display,resource_info,windows,
2559 command_type,&image,&state);
2565 Respond to a user key release.
2567 (void) XLookupString((XKeyEvent *) &event.xkey,command,(int)
2568 sizeof(command),&key_symbol,(XComposeStatus *) NULL);
2569 if (display_image->debug != MagickFalse)
2570 (void) LogMagickEvent(X11Event,GetMagickModule(),
2571 "Key release: 0x%lx (%c)",(unsigned long) key_symbol,*command);
2577 Selectively uninstall colormap.
2579 if (map_info->colormap != XDefaultColormap(display,visual_info->screen))
2580 if (event.xcrossing.mode != NotifyUngrab)
2581 XUninstallColormap(display,map_info->colormap);
2586 if (display_image->debug != MagickFalse)
2587 (void) LogMagickEvent(X11Event,GetMagickModule(),"Map Notify: 0x%lx",
2589 if (event.xmap.window == windows->backdrop.id)
2591 (void) XSetInputFocus(display,event.xmap.window,RevertToParent,
2593 windows->backdrop.mapped=MagickTrue;
2596 if (event.xmap.window == windows->image.id)
2598 if (windows->backdrop.id != (Window) NULL)
2599 (void) XInstallColormap(display,map_info->colormap);
2600 if (LocaleCompare(image_list[0]->magick,"LOGO") == 0)
2602 if (LocaleCompare(display_image->filename,"LOGO") == 0)
2603 nexus=XMagickCommand(display,resource_info,windows,
2604 OpenCommand,&image,&state);
2608 windows->image.mapped=MagickTrue;
2611 if (event.xmap.window == windows->info.id)
2613 windows->info.mapped=MagickTrue;
2616 if (event.xmap.window == windows->icon.id)
2619 Create an icon image.
2621 XMakeStandardColormap(display,icon_visual,icon_resources,
2622 display_image,icon_map,icon_pixel);
2623 (void) XMakeImage(display,icon_resources,&windows->icon,
2624 display_image,windows->icon.width,windows->icon.height);
2625 (void) XSetWindowBackgroundPixmap(display,windows->icon.id,
2626 windows->icon.pixmap);
2627 (void) XClearWindow(display,windows->icon.id);
2628 (void) XWithdrawWindow(display,windows->info.id,
2629 windows->info.screen);
2630 windows->icon.mapped=MagickTrue;
2633 if (event.xmap.window == windows->command.id)
2635 windows->command.mapped=MagickTrue;
2638 if (event.xmap.window == windows->popup.id)
2640 windows->popup.mapped=MagickTrue;
2643 if (event.xmap.window == windows->widget.id)
2645 windows->widget.mapped=MagickTrue;
2652 (void) XRefreshKeyboardMapping(&event.xmapping);
2657 case PropertyNotify:
2673 if (display_image->debug != MagickFalse)
2674 (void) LogMagickEvent(X11Event,GetMagickModule(),
2675 "Property Notify: 0x%lx 0x%lx %d",(unsigned long)
2676 event.xproperty.window,(unsigned long) event.xproperty.atom,
2677 event.xproperty.state);
2678 if (event.xproperty.atom != windows->im_remote_command)
2681 Display image named by the remote command protocol.
2683 status=XGetWindowProperty(display,event.xproperty.window,
2684 event.xproperty.atom,0L,(long) MaxTextExtent,MagickFalse,(Atom)
2685 AnyPropertyType,&type,&format,&length,&after,&data);
2686 if ((status != Success) || (length == 0))
2688 (void) CopyMagickString(resource_info->image_info->filename,
2689 (char *) data,MaxTextExtent);
2690 nexus=ReadImage(resource_info->image_info,&image->exception);
2691 CatchException(&image->exception);
2692 if (nexus != (Image *) NULL)
2694 (void) XFree((void *) data);
2697 case ReparentNotify:
2699 if (display_image->debug != MagickFalse)
2700 (void) LogMagickEvent(X11Event,GetMagickModule(),
2701 "Reparent Notify: 0x%lx=>0x%lx",event.xreparent.parent,
2702 event.xreparent.window);
2707 if (display_image->debug != MagickFalse)
2708 (void) LogMagickEvent(X11Event,GetMagickModule(),
2709 "Unmap Notify: 0x%lx",event.xunmap.window);
2710 if (event.xunmap.window == windows->backdrop.id)
2712 windows->backdrop.mapped=MagickFalse;
2715 if (event.xunmap.window == windows->image.id)
2717 windows->image.mapped=MagickFalse;
2720 if (event.xunmap.window == windows->info.id)
2722 windows->info.mapped=MagickFalse;
2725 if (event.xunmap.window == windows->icon.id)
2727 if (map_info->colormap == icon_map->colormap)
2728 XConfigureImageColormap(display,resource_info,windows,
2730 (void) XFreeStandardColormap(display,icon_visual,icon_map,
2732 windows->icon.mapped=MagickFalse;
2735 if (event.xunmap.window == windows->command.id)
2737 windows->command.mapped=MagickFalse;
2740 if (event.xunmap.window == windows->popup.id)
2742 if (windows->backdrop.id != (Window) NULL)
2743 (void) XSetInputFocus(display,windows->image.id,RevertToParent,
2745 windows->popup.mapped=MagickFalse;
2748 if (event.xunmap.window == windows->widget.id)
2750 if (windows->backdrop.id != (Window) NULL)
2751 (void) XSetInputFocus(display,windows->image.id,RevertToParent,
2753 windows->widget.mapped=MagickFalse;
2760 if (display_image->debug != MagickFalse)
2761 (void) LogMagickEvent(X11Event,GetMagickModule(),"Event type: %d",
2767 while (!(state & ExitState));
2768 image_list=(Image **) RelinquishMagickMemory(image_list);
2769 images=DestroyImageList(images);
2770 if ((windows->visual_info->klass == GrayScale) ||
2771 (windows->visual_info->klass == PseudoColor) ||
2772 (windows->visual_info->klass == DirectColor))
2777 if (windows->info.mapped)
2778 (void) XWithdrawWindow(display,windows->info.id,windows->info.screen);
2779 if (windows->command.mapped)
2780 (void) XWithdrawWindow(display,windows->command.id,
2781 windows->command.screen);
2783 if (resource_info->backdrop == MagickFalse)
2784 if (windows->backdrop.mapped)
2786 (void) XWithdrawWindow(display,windows->backdrop.id,\
2787 windows->backdrop.screen);
2788 (void) XDestroyWindow(display,windows->backdrop.id);
2789 windows->backdrop.id=(Window) NULL;
2790 (void) XWithdrawWindow(display,windows->image.id,windows->image.screen);
2791 (void) XDestroyWindow(display,windows->image.id);
2792 windows->image.id=(Window) NULL;
2794 XSetCursorState(display,windows,MagickTrue);
2795 XCheckRefreshWindows(display,windows);
2796 for (scene=1; scene < (ssize_t) number_scenes; scene++)
2798 if (windows->image.pixmaps[scene] != (Pixmap) NULL)
2799 (void) XFreePixmap(display,windows->image.pixmaps[scene]);
2800 windows->image.pixmaps[scene]=(Pixmap) NULL;
2801 if (windows->image.matte_pixmaps[scene] != (Pixmap) NULL)
2802 (void) XFreePixmap(display,windows->image.matte_pixmaps[scene]);
2803 windows->image.matte_pixmaps[scene]=(Pixmap) NULL;
2805 XSetCursorState(display,windows,MagickFalse);
2806 windows->image.pixmaps=(Pixmap *)
2807 RelinquishMagickMemory(windows->image.pixmaps);
2808 windows->image.matte_pixmaps=(Pixmap *)
2809 RelinquishMagickMemory(windows->image.matte_pixmaps);
2810 if (nexus == (Image *) NULL)
2815 if (windows->image.mapped != MagickFalse)
2816 (void) XWithdrawWindow(display,windows->image.id,windows->image.screen); XDelay(display,SuspendTime);
2817 (void) XFreeStandardColormap(display,icon_visual,icon_map,icon_pixel);
2818 if (resource_info->map_type == (char *) NULL)
2819 (void) XFreeStandardColormap(display,visual_info,map_info,pixel);
2820 DestroyXResources();
2822 (void) XSync(display,MagickFalse);
2824 Restore our progress monitor and warning handlers.
2826 (void) SetErrorHandler(warning_handler);
2827 (void) SetWarningHandler(warning_handler);
2829 Change to home directory.
2831 directory=getcwd(working_directory,MaxTextExtent);
2833 status=chdir(resource_info->home_directory);
2835 (void) ThrowMagickException(&images->exception,GetMagickModule(),
2836 FileOpenError,"UnableToOpenFile","%s",resource_info->home_directory);
2841 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2845 + X S a v e I m a g e %
2849 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2851 % XSaveImage() saves an image to a file.
2853 % The format of the XSaveImage method is:
2855 % MagickBooleanType XSaveImage(Display *display,
2856 % XResourceInfo *resource_info,XWindows *windows,Image *image)
2858 % A description of each parameter follows:
2860 % o status: Method XSaveImage return True if the image is
2861 % written. False is returned is there is a memory shortage or if the
2862 % image fails to write.
2864 % o display: Specifies a connection to an X server; returned from
2867 % o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
2869 % o windows: Specifies a pointer to a XWindows structure.
2871 % o image: the image.
2874 static MagickBooleanType XSaveImage(Display *display,
2875 XResourceInfo *resource_info,XWindows *windows,Image *image)
2878 filename[MaxTextExtent];
2887 Request file name from user.
2889 if (resource_info->write_filename != (char *) NULL)
2890 (void) CopyMagickString(filename,resource_info->write_filename,
2895 path[MaxTextExtent];
2900 GetPathComponent(image->filename,HeadPath,path);
2901 GetPathComponent(image->filename,TailPath,filename);
2904 (void) ThrowMagickException(&image->exception,GetMagickModule(),
2905 FileOpenError,"UnableToOpenFile","%s",path);
2907 XFileBrowserWidget(display,windows,"Save",filename);
2908 if (*filename == '\0')
2910 if (IsPathAccessible(filename) != MagickFalse)
2916 File exists-- seek user's permission before overwriting.
2918 status=XConfirmWidget(display,windows,"Overwrite",filename);
2922 image_info=CloneImageInfo(resource_info->image_info);
2923 (void) CopyMagickString(image_info->filename,filename,MaxTextExtent);
2924 (void) SetImageInfo(image_info,1,&image->exception);
2925 if ((LocaleCompare(image_info->magick,"JPEG") == 0) ||
2926 (LocaleCompare(image_info->magick,"JPG") == 0))
2929 quality[MaxTextExtent];
2935 Request JPEG quality from user.
2937 (void) FormatLocaleString(quality,MaxTextExtent,"%.20g",(double)
2938 image_info->quality);
2939 status=XDialogWidget(display,windows,"Save","Enter JPEG quality:",
2941 if (*quality == '\0')
2943 image->quality=StringToUnsignedLong(quality);
2944 image_info->interlace=status != MagickFalse ? NoInterlace :
2947 if ((LocaleCompare(image_info->magick,"EPS") == 0) ||
2948 (LocaleCompare(image_info->magick,"PDF") == 0) ||
2949 (LocaleCompare(image_info->magick,"PS") == 0) ||
2950 (LocaleCompare(image_info->magick,"PS2") == 0))
2953 geometry[MaxTextExtent];
2956 Request page geometry from user.
2958 (void) CopyMagickString(geometry,PSPageGeometry,MaxTextExtent);
2959 if (LocaleCompare(image_info->magick,"PDF") == 0)
2960 (void) CopyMagickString(geometry,PSPageGeometry,MaxTextExtent);
2961 if (image_info->page != (char *) NULL)
2962 (void) CopyMagickString(geometry,image_info->page,MaxTextExtent);
2963 XListBrowserWidget(display,windows,&windows->widget,PageSizes,"Select",
2964 "Select page geometry:",geometry);
2965 if (*geometry != '\0')
2966 image_info->page=GetPageGeometry(geometry);
2971 image=GetFirstImageInList(image);
2972 status=WriteImages(image_info,image,filename,&image->exception);
2973 if (status != MagickFalse)
2974 image->taint=MagickFalse;
2975 image_info=DestroyImageInfo(image_info);
2976 XSetCursorState(display,windows,MagickFalse);
2977 return(status != 0 ? MagickTrue : MagickFalse);
2982 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2986 + A n i m a t e I m a g e s %
2990 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2992 % AnimateImages() repeatedly displays an image sequence to any X window
2993 % screen. It returns a value other than 0 if successful. Check the
2994 % exception member of image to determine the reason for any failure.
2996 % The format of the AnimateImages method is:
2998 % MagickBooleanType AnimateImages(const ImageInfo *image_info,
3001 % A description of each parameter follows:
3003 % o image_info: the image info.
3005 % o image: the image.
3008 MagickExport MagickBooleanType AnimateImages(const ImageInfo *image_info,
3011 assert(image_info != (const ImageInfo *) NULL);
3012 assert(image_info->signature == MagickSignature);
3013 assert(image != (Image *) NULL);
3014 assert(image->signature == MagickSignature);
3015 if (image->debug != MagickFalse)
3016 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
3017 (void) ThrowMagickException(&image->exception,GetMagickModule(),
3018 MissingDelegateError,"DelegateLibrarySupportNotBuiltIn","`%s' (X11)",
3020 return(MagickFalse);