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 **) AcquireAlignedMemory(1,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 "ImageMagick: %s",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((unsigned long *) 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 long MagickMax(const long x,const long 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 > (unsigned long) visual_info->colormap_size))
877 for (i=0; i < (long) images->colors; i++)
878 if (IsColorEqual(next->colormap+i,images->colormap+i) == MagickFalse)
880 if (i < (long) 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 < (long) number_scenes; i++)
896 if (image_list[i]->scene == 0)
898 if (i == (long) 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=window_info.x;
951 geometry_info.y=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[%lu] %lux%lu ",image_list[0]->filename,
969 image_list[0]->scene,image_list[0]->columns,image_list[0]->rows);
970 if (image_list[0]->colors != 0)
971 (void) LogMagickEvent(X11Event,GetMagickModule(),"%luc ",
972 image_list[0]->colors);
973 (void) LogMagickEvent(X11Event,GetMagickModule(),"%s",
974 image_list[0]->magick);
977 Adjust image dimensions as specified by backdrop or geometry options.
979 width=window_info.width;
980 height=window_info.height;
981 if (resources.backdrop != MagickFalse)
984 Center image on window.
986 window_info.x=(int) (window_attributes.width/2)-
987 (window_info.ximage->width/2);
988 window_info.y=(int) (window_attributes.height/2)-
989 (window_info.ximage->height/2);
990 width=(unsigned int) window_attributes.width;
991 height=(unsigned int) window_attributes.height;
993 if (resources.image_geometry != (char *) NULL)
996 default_geometry[MaxTextExtent];
1006 User specified geometry.
1008 size_hints=XAllocSizeHints();
1009 if (size_hints == (XSizeHints *) NULL)
1010 ThrowXWindowFatalException(ResourceLimitFatalError,
1011 "MemoryAllocationFailed",images->filename);
1012 size_hints->flags=0L;
1013 (void) FormatMagickString(default_geometry,MaxTextExtent,"%ux%u",width,
1015 flags=XWMGeometry(display,visual_info->screen,resources.image_geometry,
1016 default_geometry,window_info.border_width,size_hints,&window_info.x,
1017 &window_info.y,(int *) &width,(int *) &height,&gravity);
1018 if (((flags & (XValue | YValue))) != 0)
1020 width=(unsigned int) window_attributes.width;
1021 height=(unsigned int) window_attributes.height;
1023 (void) XFree((void *) size_hints);
1026 Create the X pixmap.
1028 window_info.pixmap=XCreatePixmap(display,window_info.id,(unsigned int) width,
1029 (unsigned int) height,window_info.depth);
1030 if (window_info.pixmap == (Pixmap) NULL)
1031 ThrowXWindowFatalException(XServerFatalError,"UnableToCreateXPixmap",
1034 Display pixmap on the window.
1036 if (((unsigned int) width > window_info.width) ||
1037 ((unsigned int) height > window_info.height))
1038 (void) XFillRectangle(display,window_info.pixmap,
1039 window_info.annotate_context,0,0,(unsigned int) width,
1040 (unsigned int) height);
1041 (void) XPutImage(display,window_info.pixmap,window_info.annotate_context,
1042 window_info.ximage,0,0,window_info.x,window_info.y,window_info.width,
1043 window_info.height);
1044 (void) XSetWindowBackgroundPixmap(display,window_info.id,window_info.pixmap);
1045 (void) XClearWindow(display,window_info.id);
1047 Initialize image pixmaps structure.
1049 window_info.pixmaps=(Pixmap *) AcquireQuantumMemory(number_scenes,
1050 sizeof(*window_info.pixmaps));
1051 window_info.matte_pixmaps=(Pixmap *) AcquireQuantumMemory(number_scenes,
1052 sizeof(*window_info.matte_pixmaps));
1053 if ((window_info.pixmaps == (Pixmap *) NULL) ||
1054 (window_info.matte_pixmaps == (Pixmap *) NULL))
1055 ThrowXWindowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed",
1057 window_info.pixmaps[0]=window_info.pixmap;
1058 window_info.matte_pixmaps[0]=window_info.pixmap;
1059 for (scene=1; scene < (int) number_scenes; scene++)
1068 window_info.pixmap=(Pixmap) NULL;
1069 window_info.matte_pixmap=(Pixmap) NULL;
1070 if ((resources.map_type != (char *) NULL) ||
1071 (visual_info->klass == TrueColor) ||
1072 (visual_info->klass == DirectColor))
1073 if (image_list[scene]->storage_class == PseudoClass)
1074 XGetPixelPacket(display,visual_info,map_info,&resources,
1075 image_list[scene],window_info.pixel_info);
1076 columns=(unsigned int) image_list[scene]->columns;
1077 rows=(unsigned int) image_list[scene]->rows;
1078 if ((image_list[scene]->columns != columns) ||
1079 (image_list[scene]->rows != rows))
1080 ThrowXWindowFatalException(XServerFatalError,"UnableToCreateXImage",
1081 image_list[scene]->filename);
1082 status=XMakeImage(display,&resources,&window_info,image_list[scene],
1084 if (status == MagickFalse)
1085 ThrowXWindowFatalException(XServerFatalError,"UnableToCreateXImage",
1087 if (display_image->debug != MagickFalse)
1089 (void) LogMagickEvent(X11Event,GetMagickModule(),
1090 "Image: [%lu] %s %ux%u ",image_list[scene]->scene,
1091 image_list[scene]->filename,columns,rows);
1092 if (image_list[scene]->colors != 0)
1093 (void) LogMagickEvent(X11Event,GetMagickModule(),"%luc ",
1094 image_list[scene]->colors);
1095 (void) LogMagickEvent(X11Event,GetMagickModule(),"%s",
1096 image_list[scene]->magick);
1099 Create the X pixmap.
1101 window_info.pixmap=XCreatePixmap(display,window_info.id,width,height,
1103 if (window_info.pixmap == (Pixmap) NULL)
1104 ThrowXWindowFatalException(XServerFatalError,"UnableToCreateXPixmap",
1107 Display pixmap on the window.
1109 if ((width > window_info.width) || (height > window_info.height))
1110 (void) XFillRectangle(display,window_info.pixmap,
1111 window_info.annotate_context,0,0,width,height);
1112 (void) XPutImage(display,window_info.pixmap,window_info.annotate_context,
1113 window_info.ximage,0,0,window_info.x,window_info.y,window_info.width,
1114 window_info.height);
1115 (void) XSetWindowBackgroundPixmap(display,window_info.id,
1116 window_info.pixmap);
1117 (void) XClearWindow(display,window_info.id);
1118 window_info.pixmaps[scene]=window_info.pixmap;
1119 window_info.matte_pixmaps[scene]=window_info.matte_pixmap;
1120 if (image_list[scene]->matte)
1121 (void) XClearWindow(display,window_info.id);
1122 delay=1000*image_list[scene]->delay/MagickMax(
1123 image_list[scene]->ticks_per_second,1L);
1124 XDelay(display,resources.delay*(delay == 0 ? 10 : delay));
1126 window_info.pixel_info=(&pixel);
1128 Display pixmap on the window.
1130 (void) XSelectInput(display,window_info.id,SubstructureNotifyMask);
1134 for (scene=0; scene < (int) number_scenes; scene++)
1136 if (XEventsQueued(display,QueuedAfterFlush) > 0)
1138 (void) XNextEvent(display,&event);
1139 if (event.type == DestroyNotify)
1142 window_info.pixmap=window_info.pixmaps[scene];
1143 window_info.matte_pixmap=window_info.matte_pixmaps[scene];
1144 (void) XSetWindowBackgroundPixmap(display,window_info.id,
1145 window_info.pixmap);
1146 (void) XClearWindow(display,window_info.id);
1147 (void) XSync(display,MagickFalse);
1148 delay=1000*image_list[scene]->delay/MagickMax(
1149 image_list[scene]->ticks_per_second,1L);
1150 XDelay(display,resources.delay*(delay == 0 ? 10 : delay));
1152 } while (event.type != DestroyNotify);
1153 (void) XSync(display,MagickFalse);
1154 image_list=(Image **) RelinquishMagickMemory(image_list);
1155 images=DestroyImageList(images);
1159 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1163 + X A n i m a t e I m a g e s %
1167 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1169 % XAnimateImages() displays an image via X11.
1171 % The format of the XAnimateImages method is:
1173 % Image *XAnimateImages(Display *display,XResourceInfo *resource_info,
1174 % char **argv,const int argc,Image *images)
1176 % A description of each parameter follows:
1178 % o display: Specifies a connection to an X server; returned from
1181 % o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
1183 % o argv: Specifies the application's argument list.
1185 % o argc: Specifies the number of arguments.
1187 % o images: the image list.
1190 MagickExport Image *XAnimateImages(Display *display,
1191 XResourceInfo *resource_info,char **argv,const int argc,Image *images)
1193 #define MagickMenus 4
1194 #define MaXWindows 8
1195 #define MagickTitle "Commands"
1233 "Browse Documentation",
1239 **Menus[MagickMenus]=
1247 static const CommandType
1271 DirectionCommands[]=
1279 BrowseDocumentationCommand,
1283 static const CommandType
1284 *Commands[MagickMenus]=
1293 command[MaxTextExtent],
1295 geometry[MaxTextExtent],
1296 resource_name[MaxTextExtent];
1333 working_directory[MaxTextExtent];
1335 static unsigned long
1339 *magick_windows[MaXWindows];
1393 assert(images != (Image *) NULL);
1394 assert(images->signature == MagickSignature);
1395 if (images->debug != MagickFalse)
1396 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",images->filename);
1397 warning_handler=(WarningHandler) NULL;
1398 windows=XSetWindows((XWindows *) ~0);
1399 if (windows != (XWindows *) NULL)
1404 status=chdir(working_directory);
1406 (void) ThrowMagickException(&images->exception,GetMagickModule(),
1407 FileOpenError,"UnableToOpenFile","%s",working_directory);
1408 warning_handler=resource_info->display_warnings ?
1409 SetErrorHandler(XWarning) : SetErrorHandler((ErrorHandler) NULL);
1410 warning_handler=resource_info->display_warnings ?
1411 SetWarningHandler(XWarning) : SetWarningHandler((WarningHandler) NULL);
1419 Initialize window structure.
1421 for (p=images; p != (Image *) NULL; p=GetNextImageInList(p))
1423 if (p->storage_class == DirectClass)
1425 resource_info->colors=0;
1428 if (p->colors > resource_info->colors)
1429 resource_info->colors=p->colors;
1431 windows=XSetWindows(XInitializeWindows(display,resource_info));
1432 if (windows == (XWindows *) NULL)
1433 ThrowXWindowFatalException(XServerFatalError,"MemoryAllocationFailed",
1436 Initialize window id's.
1439 magick_windows[number_windows++]=(&windows->icon);
1440 magick_windows[number_windows++]=(&windows->backdrop);
1441 magick_windows[number_windows++]=(&windows->image);
1442 magick_windows[number_windows++]=(&windows->info);
1443 magick_windows[number_windows++]=(&windows->command);
1444 magick_windows[number_windows++]=(&windows->widget);
1445 magick_windows[number_windows++]=(&windows->popup);
1446 for (i=0; i < (long) number_windows; i++)
1447 magick_windows[i]->id=(Window) NULL;
1450 Initialize font info.
1452 if (windows->font_info != (XFontStruct *) NULL)
1453 (void) XFreeFont(display,windows->font_info);
1454 windows->font_info=XBestFont(display,resource_info,MagickFalse);
1455 if (windows->font_info == (XFontStruct *) NULL)
1456 ThrowXWindowFatalException(XServerFatalError,"UnableToLoadFont",
1457 resource_info->font);
1459 Initialize Standard Colormap.
1461 map_info=windows->map_info;
1462 icon_map=windows->icon_map;
1463 visual_info=windows->visual_info;
1464 icon_visual=windows->icon_visual;
1465 pixel=windows->pixel_info;
1466 icon_pixel=windows->icon_pixel;
1467 font_info=windows->font_info;
1468 icon_resources=windows->icon_resources;
1469 class_hints=windows->class_hints;
1470 manager_hints=windows->manager_hints;
1471 root_window=XRootWindow(display,visual_info->screen);
1472 coalesce_image=CoalesceImages(images,&images->exception);
1473 if (coalesce_image == (Image *) NULL)
1474 ThrowXWindowFatalException(XServerFatalError,"MemoryAllocationFailed",
1476 images=coalesce_image;
1477 if (resource_info->map_type == (char *) NULL)
1478 if ((visual_info->klass != TrueColor) &&
1479 (visual_info->klass != DirectColor))
1485 Determine if the sequence of images has the identical colormap.
1487 for (next=images; next != (Image *) NULL; )
1489 next->matte=MagickFalse;
1490 if ((next->storage_class == DirectClass) ||
1491 (next->colors != images->colors) ||
1492 (next->colors > (unsigned long) visual_info->colormap_size))
1494 for (i=0; i < (long) images->colors; i++)
1495 if (IsColorEqual(next->colormap+i,images->colormap+i) == MagickFalse)
1497 if (i < (long) images->colors)
1499 next=GetNextImageInList(next);
1501 if (next != (Image *) NULL)
1502 (void) RemapImages(resource_info->quantize_info,images,
1506 Sort images by increasing scene number.
1508 number_scenes=GetImageListLength(images);
1509 image_list=ImageListToArray(images,&images->exception);
1510 if (image_list == (Image **) NULL)
1511 ThrowXWindowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed",
1513 for (scene=0; scene < (long) number_scenes; scene++)
1514 if (image_list[scene]->scene == 0)
1516 if (scene == (long) number_scenes)
1517 qsort((void *) image_list,number_scenes,sizeof(Image *),SceneCompare);
1519 Initialize Standard Colormap.
1521 nexus=NewImageList();
1522 display_image=image_list[0];
1523 for (scene=0; scene < (long) number_scenes; scene++)
1525 if ((resource_info->map_type != (char *) NULL) ||
1526 (visual_info->klass == TrueColor) ||
1527 (visual_info->klass == DirectColor))
1528 (void) SetImageType(image_list[scene],image_list[scene]->matte ==
1529 MagickFalse ? TrueColorType : TrueColorMatteType);
1530 if ((display_image->columns < image_list[scene]->columns) &&
1531 (display_image->rows < image_list[scene]->rows))
1532 display_image=image_list[scene];
1534 if (display_image->debug != MagickFalse)
1536 (void) LogMagickEvent(X11Event,GetMagickModule(),
1537 "Image: %s[%lu] %lux%lu ",display_image->filename,
1538 display_image->scene,display_image->columns,display_image->rows);
1539 if (display_image->colors != 0)
1540 (void) LogMagickEvent(X11Event,GetMagickModule(),"%luc ",
1541 display_image->colors);
1542 (void) LogMagickEvent(X11Event,GetMagickModule(),"%s",
1543 display_image->magick);
1545 XMakeStandardColormap(display,visual_info,resource_info,display_image,
1548 Initialize graphic context.
1550 windows->context.id=(Window) NULL;
1551 XGetWindowInfo(display,visual_info,map_info,pixel,font_info,
1552 resource_info,&windows->context);
1553 (void) CloneString(&class_hints->res_name,resource_info->client_name);
1554 (void) CloneString(&class_hints->res_class,resource_info->client_name);
1555 class_hints->res_class[0]=(char) toupper((int) class_hints->res_class[0]);
1556 manager_hints->flags=InputHint | StateHint;
1557 manager_hints->input=MagickFalse;
1558 manager_hints->initial_state=WithdrawnState;
1559 XMakeWindow(display,root_window,argv,argc,class_hints,manager_hints,
1561 if (display_image->debug != MagickFalse)
1562 (void) LogMagickEvent(X11Event,GetMagickModule(),
1563 "Window id: 0x%lx (context)",windows->context.id);
1564 context_values.background=pixel->background_color.pixel;
1565 context_values.font=font_info->fid;
1566 context_values.foreground=pixel->foreground_color.pixel;
1567 context_values.graphics_exposures=MagickFalse;
1568 context_mask=(MagickStatusType)
1569 (GCBackground | GCFont | GCForeground | GCGraphicsExposures);
1570 if (pixel->annotate_context != (GC) NULL)
1571 (void) XFreeGC(display,pixel->annotate_context);
1572 pixel->annotate_context=
1573 XCreateGC(display,windows->context.id,context_mask,&context_values);
1574 if (pixel->annotate_context == (GC) NULL)
1575 ThrowXWindowFatalException(XServerFatalError,"UnableToCreateGraphicContext",
1577 context_values.background=pixel->depth_color.pixel;
1578 if (pixel->widget_context != (GC) NULL)
1579 (void) XFreeGC(display,pixel->widget_context);
1580 pixel->widget_context=
1581 XCreateGC(display,windows->context.id,context_mask,&context_values);
1582 if (pixel->widget_context == (GC) NULL)
1583 ThrowXWindowFatalException(XServerFatalError,"UnableToCreateGraphicContext",
1585 context_values.background=pixel->foreground_color.pixel;
1586 context_values.foreground=pixel->background_color.pixel;
1587 context_values.plane_mask=
1588 context_values.background ^ context_values.foreground;
1589 if (pixel->highlight_context != (GC) NULL)
1590 (void) XFreeGC(display,pixel->highlight_context);
1591 pixel->highlight_context=XCreateGC(display,windows->context.id,
1592 (unsigned long) (context_mask | GCPlaneMask),&context_values);
1593 if (pixel->highlight_context == (GC) NULL)
1594 ThrowXWindowFatalException(XServerFatalError,"UnableToCreateGraphicContext",
1596 (void) XDestroyWindow(display,windows->context.id);
1598 Initialize icon window.
1600 XGetWindowInfo(display,icon_visual,icon_map,icon_pixel,(XFontStruct *) NULL,
1601 icon_resources,&windows->icon);
1602 windows->icon.geometry=resource_info->icon_geometry;
1603 XBestIconSize(display,&windows->icon,display_image);
1604 windows->icon.attributes.colormap=
1605 XDefaultColormap(display,icon_visual->screen);
1606 windows->icon.attributes.event_mask=ExposureMask | StructureNotifyMask;
1607 manager_hints->flags=InputHint | StateHint;
1608 manager_hints->input=MagickFalse;
1609 manager_hints->initial_state=IconicState;
1610 XMakeWindow(display,root_window,argv,argc,class_hints,manager_hints,
1612 if (display_image->debug != MagickFalse)
1613 (void) LogMagickEvent(X11Event,GetMagickModule(),"Window id: 0x%lx (icon)",
1616 Initialize graphic context for icon window.
1618 if (icon_pixel->annotate_context != (GC) NULL)
1619 (void) XFreeGC(display,icon_pixel->annotate_context);
1620 context_values.background=icon_pixel->background_color.pixel;
1621 context_values.foreground=icon_pixel->foreground_color.pixel;
1622 icon_pixel->annotate_context=XCreateGC(display,windows->icon.id,
1623 (unsigned long) (GCBackground | GCForeground),&context_values);
1624 if (icon_pixel->annotate_context == (GC) NULL)
1625 ThrowXWindowFatalException(XServerFatalError,"UnableToCreateGraphicContext",
1627 windows->icon.annotate_context=icon_pixel->annotate_context;
1629 Initialize Image window.
1631 XGetWindowInfo(display,visual_info,map_info,pixel,font_info,
1632 resource_info,&windows->image);
1633 windows->image.shape=MagickTrue; /* non-rectangular shape hint */
1634 if (resource_info->use_shared_memory == MagickFalse)
1635 windows->image.shared_memory=MagickFalse;
1636 if (resource_info->title != (char *) NULL)
1641 title=InterpretImageProperties(resource_info->image_info,display_image,
1642 resource_info->title);
1643 (void) CopyMagickString(windows->image.name,title,MaxTextExtent);
1644 (void) CopyMagickString(windows->image.icon_name,title,MaxTextExtent);
1645 title=DestroyString(title);
1650 filename[MaxTextExtent];
1653 Window name is the base of the filename.
1655 GetPathComponent(display_image->magick_filename,TailPath,filename);
1656 (void) FormatMagickString(windows->image.name,MaxTextExtent,
1657 "ImageMagick: %s[%lu of %lu]",filename,display_image->scene,
1659 (void) CopyMagickString(windows->image.icon_name,filename,MaxTextExtent);
1661 if (resource_info->immutable != MagickFalse)
1662 windows->image.immutable=MagickTrue;
1663 windows->image.shape=MagickTrue;
1664 windows->image.geometry=resource_info->image_geometry;
1665 (void) FormatMagickString(geometry,MaxTextExtent,"%ux%u+0+0>!",
1666 XDisplayWidth(display,visual_info->screen),
1667 XDisplayHeight(display,visual_info->screen));
1668 geometry_info.width=display_image->columns;
1669 geometry_info.height=display_image->rows;
1672 (void) ParseMetaGeometry(geometry,&geometry_info.x,&geometry_info.y,
1673 &geometry_info.width,&geometry_info.height);
1674 windows->image.width=(unsigned int) geometry_info.width;
1675 windows->image.height=(unsigned int) geometry_info.height;
1676 windows->image.attributes.event_mask=ButtonMotionMask | ButtonPressMask |
1677 ButtonReleaseMask | EnterWindowMask | ExposureMask | KeyPressMask |
1678 KeyReleaseMask | LeaveWindowMask | OwnerGrabButtonMask |
1679 PropertyChangeMask | StructureNotifyMask | SubstructureNotifyMask;
1680 XGetWindowInfo(display,visual_info,map_info,pixel,font_info,
1681 resource_info,&windows->backdrop);
1682 if ((resource_info->backdrop) || (windows->backdrop.id != (Window) NULL))
1685 Initialize backdrop window.
1687 windows->backdrop.x=0;
1688 windows->backdrop.y=0;
1689 (void) CloneString(&windows->backdrop.name,"ImageMagick Backdrop");
1690 windows->backdrop.flags=(unsigned long) (USSize | USPosition);
1691 windows->backdrop.width=(unsigned int)
1692 XDisplayWidth(display,visual_info->screen);
1693 windows->backdrop.height=(unsigned int)
1694 XDisplayHeight(display,visual_info->screen);
1695 windows->backdrop.border_width=0;
1696 windows->backdrop.immutable=MagickTrue;
1697 windows->backdrop.attributes.do_not_propagate_mask=ButtonPressMask |
1699 windows->backdrop.attributes.event_mask=ButtonPressMask | KeyPressMask |
1700 StructureNotifyMask;
1701 manager_hints->flags=IconWindowHint | InputHint | StateHint;
1702 manager_hints->icon_window=windows->icon.id;
1703 manager_hints->input=MagickTrue;
1704 manager_hints->initial_state=
1705 resource_info->iconic ? IconicState : NormalState;
1706 XMakeWindow(display,root_window,argv,argc,class_hints,manager_hints,
1707 &windows->backdrop);
1708 if (display_image->debug != MagickFalse)
1709 (void) LogMagickEvent(X11Event,GetMagickModule(),
1710 "Window id: 0x%lx (backdrop)",windows->backdrop.id);
1711 (void) XMapWindow(display,windows->backdrop.id);
1712 (void) XClearWindow(display,windows->backdrop.id);
1713 if (windows->image.id != (Window) NULL)
1715 (void) XDestroyWindow(display,windows->image.id);
1716 windows->image.id=(Window) NULL;
1719 Position image in the center the backdrop.
1721 windows->image.flags|=USPosition;
1722 windows->image.x=(XDisplayWidth(display,visual_info->screen)/2)-
1723 (windows->image.width/2);
1724 windows->image.y=(XDisplayHeight(display,visual_info->screen)/2)-
1725 (windows->image.height/2);
1727 manager_hints->flags=IconWindowHint | InputHint | StateHint;
1728 manager_hints->icon_window=windows->icon.id;
1729 manager_hints->input=MagickTrue;
1730 manager_hints->initial_state=
1731 resource_info->iconic ? IconicState : NormalState;
1732 if (windows->group_leader.id != (Window) NULL)
1737 manager_hints->flags|=(MagickStatusType) WindowGroupHint;
1738 manager_hints->window_group=windows->group_leader.id;
1739 (void) XSelectInput(display,windows->group_leader.id,StructureNotifyMask);
1740 if (display_image->debug != MagickFalse)
1741 (void) LogMagickEvent(X11Event,GetMagickModule(),
1742 "Window id: 0x%lx (group leader)",windows->group_leader.id);
1744 XMakeWindow(display,
1745 (Window) (resource_info->backdrop ? windows->backdrop.id : root_window),
1746 argv,argc,class_hints,manager_hints,&windows->image);
1747 (void) XChangeProperty(display,windows->image.id,windows->im_protocols,
1748 XA_STRING,8,PropModeReplace,(unsigned char *) NULL,0);
1749 if (windows->group_leader.id != (Window) NULL)
1750 (void) XSetTransientForHint(display,windows->image.id,
1751 windows->group_leader.id);
1752 if (display_image->debug != MagickFalse)
1753 (void) LogMagickEvent(X11Event,GetMagickModule(),"Window id: 0x%lx (image)",
1756 Initialize Info widget.
1758 XGetWindowInfo(display,visual_info,map_info,pixel,font_info,
1759 resource_info,&windows->info);
1760 (void) CloneString(&windows->info.name,"Info");
1761 (void) CloneString(&windows->info.icon_name,"Info");
1762 windows->info.border_width=1;
1765 windows->info.flags|=PPosition;
1766 windows->info.attributes.win_gravity=UnmapGravity;
1767 windows->info.attributes.event_mask=ButtonPressMask | ExposureMask |
1768 StructureNotifyMask;
1769 manager_hints->flags=InputHint | StateHint | WindowGroupHint;
1770 manager_hints->input=MagickFalse;
1771 manager_hints->initial_state=NormalState;
1772 manager_hints->window_group=windows->image.id;
1773 XMakeWindow(display,windows->image.id,argv,argc,class_hints,manager_hints,
1775 windows->info.highlight_stipple=XCreateBitmapFromData(display,
1776 windows->info.id,(char *) HighlightBitmap,HighlightWidth,HighlightHeight);
1777 windows->info.shadow_stipple=XCreateBitmapFromData(display,
1778 windows->info.id,(char *) ShadowBitmap,ShadowWidth,ShadowHeight);
1779 (void) XSetTransientForHint(display,windows->info.id,windows->image.id);
1780 if (windows->image.mapped)
1781 (void) XWithdrawWindow(display,windows->info.id,windows->info.screen);
1782 if (display_image->debug != MagickFalse)
1783 (void) LogMagickEvent(X11Event,GetMagickModule(),"Window id: 0x%lx (info)",
1786 Initialize Command widget.
1788 XGetWindowInfo(display,visual_info,map_info,pixel,font_info,
1789 resource_info,&windows->command);
1790 windows->command.data=MagickMenus;
1791 (void) XCommandWidget(display,windows,CommandMenu,(XEvent *) NULL);
1792 (void) FormatMagickString(resource_name,MaxTextExtent,"%s.command",
1793 resource_info->client_name);
1794 windows->command.geometry=XGetResourceClass(resource_info->resource_database,
1795 resource_name,"geometry",(char *) NULL);
1796 (void) CloneString(&windows->command.name,MagickTitle);
1797 windows->command.border_width=0;
1798 windows->command.flags|=PPosition;
1799 windows->command.attributes.event_mask=ButtonMotionMask | ButtonPressMask |
1800 ButtonReleaseMask | EnterWindowMask | ExposureMask | LeaveWindowMask |
1801 OwnerGrabButtonMask | StructureNotifyMask;
1802 manager_hints->flags=InputHint | StateHint | WindowGroupHint;
1803 manager_hints->input=MagickTrue;
1804 manager_hints->initial_state=NormalState;
1805 manager_hints->window_group=windows->image.id;
1806 XMakeWindow(display,root_window,argv,argc,class_hints,manager_hints,
1808 windows->command.highlight_stipple=XCreateBitmapFromData(display,
1809 windows->command.id,(char *) HighlightBitmap,HighlightWidth,
1811 windows->command.shadow_stipple=XCreateBitmapFromData(display,
1812 windows->command.id,(char *) ShadowBitmap,ShadowWidth,ShadowHeight);
1813 (void) XSetTransientForHint(display,windows->command.id,windows->image.id);
1814 if (display_image->debug != MagickFalse)
1815 (void) LogMagickEvent(X11Event,GetMagickModule(),
1816 "Window id: 0x%lx (command)",windows->command.id);
1818 Initialize Widget window.
1820 XGetWindowInfo(display,visual_info,map_info,pixel,font_info,
1821 resource_info,&windows->widget);
1822 (void) FormatMagickString(resource_name,MaxTextExtent,"%s.widget",
1823 resource_info->client_name);
1824 windows->widget.geometry=XGetResourceClass(resource_info->resource_database,
1825 resource_name,"geometry",(char *) NULL);
1826 windows->widget.border_width=0;
1827 windows->widget.flags|=PPosition;
1828 windows->widget.attributes.event_mask=ButtonMotionMask | ButtonPressMask |
1829 ButtonReleaseMask | EnterWindowMask | ExposureMask | KeyPressMask |
1830 KeyReleaseMask | LeaveWindowMask | OwnerGrabButtonMask |
1831 StructureNotifyMask;
1832 manager_hints->flags=InputHint | StateHint | WindowGroupHint;
1833 manager_hints->input=MagickTrue;
1834 manager_hints->initial_state=NormalState;
1835 manager_hints->window_group=windows->image.id;
1836 XMakeWindow(display,root_window,argv,argc,class_hints,manager_hints,
1838 windows->widget.highlight_stipple=XCreateBitmapFromData(display,
1839 windows->widget.id,(char *) HighlightBitmap,HighlightWidth,HighlightHeight);
1840 windows->widget.shadow_stipple=XCreateBitmapFromData(display,
1841 windows->widget.id,(char *) ShadowBitmap,ShadowWidth,ShadowHeight);
1842 (void) XSetTransientForHint(display,windows->widget.id,windows->image.id);
1843 if (display_image->debug != MagickFalse)
1844 (void) LogMagickEvent(X11Event,GetMagickModule(),
1845 "Window id: 0x%lx (widget)",windows->widget.id);
1847 Initialize popup window.
1849 XGetWindowInfo(display,visual_info,map_info,pixel,font_info,
1850 resource_info,&windows->popup);
1851 windows->popup.border_width=0;
1852 windows->popup.flags|=PPosition;
1853 windows->popup.attributes.event_mask=ButtonMotionMask | ButtonPressMask |
1854 ButtonReleaseMask | EnterWindowMask | ExposureMask | KeyPressMask |
1855 KeyReleaseMask | LeaveWindowMask | StructureNotifyMask;
1856 manager_hints->flags=InputHint | StateHint | WindowGroupHint;
1857 manager_hints->input=MagickTrue;
1858 manager_hints->initial_state=NormalState;
1859 manager_hints->window_group=windows->image.id;
1860 XMakeWindow(display,root_window,argv,argc,class_hints,manager_hints,
1862 windows->popup.highlight_stipple=XCreateBitmapFromData(display,
1863 windows->popup.id,(char *) HighlightBitmap,HighlightWidth,HighlightHeight);
1864 windows->popup.shadow_stipple=XCreateBitmapFromData(display,
1865 windows->popup.id,(char *) ShadowBitmap,ShadowWidth,ShadowHeight);
1866 (void) XSetTransientForHint(display,windows->popup.id,windows->image.id);
1867 if (display_image->debug != MagickFalse)
1868 (void) LogMagickEvent(X11Event,GetMagickModule(),
1869 "Window id: 0x%lx (pop up)",windows->popup.id);
1870 if ((windows->image.mapped == MagickFalse) ||
1871 (windows->backdrop.id != (Window) NULL))
1872 (void) XMapWindow(display,windows->image.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.
1888 status=XMakeImage(display,resource_info,&windows->image,display_image,
1889 (unsigned int) display_image->columns,(unsigned int) display_image->rows);
1890 if (status == MagickFalse)
1891 ThrowXWindowFatalException(XServerFatalError,"UnableToCreateXImage",
1893 if (windows->image.mapped)
1894 XRefreshWindow(display,&windows->image,(XEvent *) NULL);
1896 Initialize image pixmaps structure.
1898 window_changes.width=(int) windows->image.width;
1899 window_changes.height=(int) windows->image.height;
1900 (void) XReconfigureWMWindow(display,windows->image.id,windows->command.screen,
1901 (unsigned int) (CWWidth | CWHeight),&window_changes);
1902 (void) XMapWindow(display,windows->image.id);
1903 windows->image.pixmaps=(Pixmap *) AcquireQuantumMemory(number_scenes,
1904 sizeof(*windows->image.pixmaps));
1905 windows->image.matte_pixmaps=(Pixmap *) AcquireQuantumMemory(number_scenes,
1906 sizeof(*windows->image.pixmaps));
1907 if ((windows->image.pixmaps == (Pixmap *) NULL) ||
1908 (windows->image.matte_pixmaps == (Pixmap *) NULL))
1909 ThrowXWindowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed",
1911 windows->image.pixmaps[0]=windows->image.pixmap;
1912 windows->image.matte_pixmaps[0]=windows->image.matte_pixmap;
1913 for (scene=1; scene < (long) number_scenes; scene++)
1922 (void) TransformImageColorspace(image_list[scene],RGBColorspace);
1923 windows->image.pixmap=(Pixmap) NULL;
1924 windows->image.matte_pixmap=(Pixmap) NULL;
1925 if ((resource_info->map_type != (char *) NULL) ||
1926 (visual_info->klass == TrueColor) ||
1927 (visual_info->klass == DirectColor))
1928 if (image_list[scene]->storage_class == PseudoClass)
1929 XGetPixelPacket(display,visual_info,map_info,resource_info,
1930 image_list[scene],windows->image.pixel_info);
1931 columns=(unsigned int) image_list[scene]->columns;
1932 rows=(unsigned int) image_list[scene]->rows;
1933 if ((image_list[scene]->columns != columns) ||
1934 (image_list[scene]->rows != rows))
1935 ThrowXWindowFatalException(XServerFatalError,"UnableToCreateXImage",
1936 image_list[scene]->filename);
1937 status=XMakeImage(display,resource_info,&windows->image,image_list[scene],
1939 if (status == MagickFalse)
1940 ThrowXWindowFatalException(XServerFatalError,"UnableToCreateXImage",
1942 if (image_list[scene]->debug != MagickFalse)
1944 (void) LogMagickEvent(X11Event,GetMagickModule(),
1945 "Image: [%lu] %s %ux%u ",image_list[scene]->scene,
1946 image_list[scene]->filename,columns,rows);
1947 if (image_list[scene]->colors != 0)
1948 (void) LogMagickEvent(X11Event,GetMagickModule(),"%luc ",
1949 image_list[scene]->colors);
1950 (void) LogMagickEvent(X11Event,GetMagickModule(),"%s",
1951 image_list[scene]->magick);
1954 Window name is the base of the filename.
1956 if (resource_info->title != (char *) NULL)
1961 title=InterpretImageProperties(resource_info->image_info,
1962 image_list[scene],resource_info->title);
1963 (void) CopyMagickString(windows->image.name,title,MaxTextExtent);
1964 title=DestroyString(title);
1968 p=image_list[scene]->magick_filename+
1969 strlen(image_list[scene]->magick_filename)-1;
1970 while ((p > image_list[scene]->magick_filename) && (*(p-1) != '/'))
1972 (void) FormatMagickString(windows->image.name,MaxTextExtent,
1973 "ImageMagick: %s[%lu of %lu]",p,scene+1,number_scenes);
1975 status=XStringListToTextProperty(&windows->image.name,1,&window_name);
1976 if (status != Success)
1978 XSetWMName(display,windows->image.id,&window_name);
1979 (void) XFree((void *) window_name.value);
1981 windows->image.pixmaps[scene]=windows->image.pixmap;
1982 windows->image.matte_pixmaps[scene]=windows->image.matte_pixmap;
1985 event.xexpose.width=(int) image_list[scene]->columns;
1986 event.xexpose.height=(int) image_list[scene]->rows;
1987 XRefreshWindow(display,&windows->image,&event);
1988 (void) XSync(display,MagickFalse);
1989 delay=1000*image_list[scene]->delay/MagickMax(images->ticks_per_second,1L);
1990 XDelay(display,resource_info->delay*(delay == 0 ? 10 : delay));
1991 if (XCheckTypedWindowEvent(display,windows->image.id,KeyPress,&event) != 0)
1996 length=XLookupString((XKeyEvent *) &event.xkey,command,(int)
1997 sizeof(command),&key_symbol,(XComposeStatus *) NULL);
1998 *(command+length)='\0';
1999 if ((key_symbol == XK_q) || (key_symbol == XK_Escape))
2001 XClientMessage(display,windows->image.id,windows->im_protocols,
2002 windows->im_exit,CurrentTime);
2007 if (windows->command.mapped)
2008 (void) XMapRaised(display,windows->command.id);
2012 nexus=NewImageList();
2016 image=image_list[0];
2017 state=(MagickStatusType) (ForwardAnimationState | RepeatAnimationState);
2018 (void) XMagickCommand(display,resource_info,windows,PlayCommand,&images,
2022 if (XEventsQueued(display,QueuedAfterFlush) == 0)
2023 if ((state & PlayAnimationState) || (state & StepAnimationState))
2029 delay=1000*image->delay/MagickMax(image->ticks_per_second,1L);
2030 XDelay(display,resource_info->delay*(delay == 0 ? 10 : delay));
2031 if (state & ForwardAnimationState)
2034 Forward animation: increment scene number.
2036 if (scene < ((long) number_scenes-1))
2041 if (iterations == (long) image_list[0]->iterations)
2046 if (state & AutoReverseAnimationState)
2048 state&=(~ForwardAnimationState);
2053 if ((state & RepeatAnimationState) == MagickFalse)
2054 state&=(~PlayAnimationState);
2063 Reverse animation: decrement scene number.
2065 if (scene > first_scene)
2070 if (iterations == (long) image_list[0]->iterations)
2073 state&=(~RepeatAnimationState);
2075 if (state & AutoReverseAnimationState)
2077 state|=ForwardAnimationState;
2083 if ((state & RepeatAnimationState) == MagickFalse)
2084 state&=(~PlayAnimationState);
2085 scene=(long) number_scenes-1;
2089 scene=MagickMax(scene,0);
2090 image=image_list[scene];
2091 if ((image != (Image *) NULL) && (image->start_loop != 0))
2093 if ((state & StepAnimationState) ||
2094 (resource_info->title != (char *) NULL))
2097 Update window title.
2099 p=image_list[scene]->filename+
2100 strlen(image_list[scene]->filename)-1;
2101 while ((p > image_list[scene]->filename) && (*(p-1) != '/'))
2103 (void) FormatMagickString(windows->image.name,MaxTextExtent,
2104 "ImageMagick: %s[%lu of %lu]",p,scene+1,number_scenes);
2105 if (resource_info->title != (char *) NULL)
2110 title=InterpretImageProperties(resource_info->image_info,
2111 image,resource_info->title);
2112 (void) CopyMagickString(windows->image.name,title,
2114 title=DestroyString(title);
2116 status=XStringListToTextProperty(&windows->image.name,1,
2118 if (status != Success)
2120 XSetWMName(display,windows->image.id,&window_name);
2121 (void) XFree((void *) window_name.value);
2125 Copy X pixmap to Image window.
2127 XGetPixelPacket(display,visual_info,map_info,resource_info,
2128 image_list[scene],windows->image.pixel_info);
2129 windows->image.ximage->width=(int) image->columns;
2130 windows->image.ximage->height=(int) image->rows;
2131 windows->image.pixmap=windows->image.pixmaps[scene];
2132 windows->image.matte_pixmap=windows->image.matte_pixmaps[scene];
2135 event.xexpose.width=(int) image->columns;
2136 event.xexpose.height=(int) image->rows;
2137 XRefreshWindow(display,&windows->image,&event);
2138 (void) XSync(display,MagickFalse);
2139 state&=(~StepAnimationState);
2140 if (pause != MagickFalse)
2141 for (i=0; i < (long) resource_info->pause; i++)
2146 status=XCheckTypedWindowEvent(display,windows->image.id,KeyPress,
2153 length=XLookupString((XKeyEvent *) &event.xkey,command,(int)
2154 sizeof(command),&key_symbol,(XComposeStatus *) NULL);
2155 *(command+length)='\0';
2156 if ((key_symbol == XK_q) || (key_symbol == XK_Escape))
2158 XClientMessage(display,windows->image.id,
2159 windows->im_protocols,windows->im_exit,CurrentTime);
2168 Handle a window event.
2170 timestamp=time((time_t *) NULL);
2171 (void) XNextEvent(display,&event);
2172 if (windows->image.stasis == MagickFalse)
2173 windows->image.stasis=(time((time_t *) NULL)-timestamp) > 0 ?
2174 MagickTrue : MagickFalse;
2175 if (event.xany.window == windows->command.id)
2181 Select a command from the Command widget.
2183 id=XCommandWidget(display,windows,CommandMenu,&event);
2186 (void) CopyMagickString(command,CommandMenu[id],MaxTextExtent);
2187 command_type=CommandMenus[id];
2188 if (id < MagickMenus)
2194 Select a command from a pop-up menu.
2196 entry=XMenuWidget(display,windows,CommandMenu[id],Menus[id],
2200 (void) CopyMagickString(command,Menus[id][entry],MaxTextExtent);
2201 command_type=Commands[id][entry];
2203 if (command_type != NullCommand)
2204 nexus=XMagickCommand(display,resource_info,windows,
2205 command_type,&image,&state);
2212 if (display_image->debug != MagickFalse)
2213 (void) LogMagickEvent(X11Event,GetMagickModule(),
2214 "Button Press: 0x%lx %u +%d+%d",event.xbutton.window,
2215 event.xbutton.button,event.xbutton.x,event.xbutton.y);
2216 if ((event.xbutton.button == Button3) &&
2217 (event.xbutton.state & Mod1Mask))
2220 Convert Alt-Button3 to Button2.
2222 event.xbutton.button=Button2;
2223 event.xbutton.state&=(~Mod1Mask);
2225 if (event.xbutton.window == windows->backdrop.id)
2227 (void) XSetInputFocus(display,event.xbutton.window,RevertToParent,
2228 event.xbutton.time);
2231 if (event.xbutton.window == windows->image.id)
2233 if (resource_info->immutable != MagickFalse)
2239 Map/unmap Command widget.
2241 if (windows->command.mapped)
2242 (void) XWithdrawWindow(display,windows->command.id,
2243 windows->command.screen);
2246 (void) XCommandWidget(display,windows,CommandMenu,
2248 (void) XMapRaised(display,windows->command.id);
2255 if (display_image->debug != MagickFalse)
2256 (void) LogMagickEvent(X11Event,GetMagickModule(),
2257 "Button Release: 0x%lx %u +%d+%d",event.xbutton.window,
2258 event.xbutton.button,event.xbutton.x,event.xbutton.y);
2263 if (display_image->debug != MagickFalse)
2264 (void) LogMagickEvent(X11Event,GetMagickModule(),
2265 "Client Message: 0x%lx 0x%lx %d 0x%lx",event.xclient.window,
2266 event.xclient.message_type,event.xclient.format,(unsigned long)
2267 event.xclient.data.l[0]);
2268 if (event.xclient.message_type == windows->im_protocols)
2270 if (*event.xclient.data.l == (long) windows->im_update_colormap)
2273 Update graphic context and window colormap.
2275 for (i=0; i < (long) number_windows; i++)
2277 if (magick_windows[i]->id == windows->icon.id)
2279 context_values.background=pixel->background_color.pixel;
2280 context_values.foreground=pixel->foreground_color.pixel;
2281 (void) XChangeGC(display,magick_windows[i]->annotate_context,
2282 context_mask,&context_values);
2283 (void) XChangeGC(display,magick_windows[i]->widget_context,
2284 context_mask,&context_values);
2285 context_values.background=pixel->foreground_color.pixel;
2286 context_values.foreground=pixel->background_color.pixel;
2287 context_values.plane_mask=
2288 context_values.background ^ context_values.foreground;
2289 (void) XChangeGC(display,magick_windows[i]->highlight_context,
2290 (unsigned long) (context_mask | GCPlaneMask),
2292 magick_windows[i]->attributes.background_pixel=
2293 pixel->background_color.pixel;
2294 magick_windows[i]->attributes.border_pixel=
2295 pixel->border_color.pixel;
2296 magick_windows[i]->attributes.colormap=map_info->colormap;
2297 (void) XChangeWindowAttributes(display,magick_windows[i]->id,
2298 magick_windows[i]->mask,&magick_windows[i]->attributes);
2300 if (windows->backdrop.id != (Window) NULL)
2301 (void) XInstallColormap(display,map_info->colormap);
2304 if (*event.xclient.data.l == (long) windows->im_exit)
2311 if (event.xclient.message_type == windows->dnd_protocols)
2329 Display image named by the Drag-and-Drop selection.
2331 if ((*event.xclient.data.l != 2) && (*event.xclient.data.l != 128))
2333 selection=XInternAtom(display,"DndSelection",MagickFalse);
2334 status=XGetWindowProperty(display,root_window,selection,0L,2047L,
2335 MagickFalse,(Atom) AnyPropertyType,&type,&format,&length,&after,
2337 if ((status != Success) || (length == 0))
2339 if (*event.xclient.data.l == 2)
2344 (void) CopyMagickString(resource_info->image_info->filename,
2345 (char *) data,MaxTextExtent);
2352 if (LocaleNCompare((char *) data,"file:",5) != 0)
2354 (void) XFree((void *) data);
2357 (void) CopyMagickString(resource_info->image_info->filename,
2358 ((char *) data)+5,MaxTextExtent);
2360 nexus=ReadImage(resource_info->image_info,&image->exception);
2361 CatchException(&image->exception);
2362 if (nexus != (Image *) NULL)
2364 (void) XFree((void *) data);
2368 If client window delete message, exit.
2370 if (event.xclient.message_type != windows->wm_protocols)
2372 if (*event.xclient.data.l == (long) windows->wm_take_focus)
2374 (void) XSetInputFocus(display,event.xclient.window,RevertToParent,
2375 (Time) event.xclient.data.l[1]);
2378 if (*event.xclient.data.l != (long) windows->wm_delete_window)
2380 (void) XWithdrawWindow(display,event.xclient.window,
2381 visual_info->screen);
2382 if (event.xclient.window == windows->image.id)
2389 case ConfigureNotify:
2391 if (display_image->debug != MagickFalse)
2392 (void) LogMagickEvent(X11Event,GetMagickModule(),
2393 "Configure Notify: 0x%lx %dx%d+%d+%d %d",event.xconfigure.window,
2394 event.xconfigure.width,event.xconfigure.height,event.xconfigure.x,
2395 event.xconfigure.y,event.xconfigure.send_event);
2396 if (event.xconfigure.window == windows->image.id)
2398 if (event.xconfigure.send_event != 0)
2404 Position the transient windows relative of the Image window.
2406 if (windows->command.geometry == (char *) NULL)
2407 if (windows->command.mapped == MagickFalse)
2410 event.xconfigure.x-windows->command.width-25;
2411 windows->command.y=event.xconfigure.y;
2412 XConstrainWindowPosition(display,&windows->command);
2413 window_changes.x=windows->command.x;
2414 window_changes.y=windows->command.y;
2415 (void) XReconfigureWMWindow(display,windows->command.id,
2416 windows->command.screen,(unsigned int) (CWX | CWY),
2419 if (windows->widget.geometry == (char *) NULL)
2420 if (windows->widget.mapped == MagickFalse)
2423 event.xconfigure.x+event.xconfigure.width/10;
2425 event.xconfigure.y+event.xconfigure.height/10;
2426 XConstrainWindowPosition(display,&windows->widget);
2427 window_changes.x=windows->widget.x;
2428 window_changes.y=windows->widget.y;
2429 (void) XReconfigureWMWindow(display,windows->widget.id,
2430 windows->widget.screen,(unsigned int) (CWX | CWY),
2435 Image window has a new configuration.
2437 windows->image.width=(unsigned int) event.xconfigure.width;
2438 windows->image.height=(unsigned int) event.xconfigure.height;
2441 if (event.xconfigure.window == windows->icon.id)
2444 Icon window has a new configuration.
2446 windows->icon.width=(unsigned int) event.xconfigure.width;
2447 windows->icon.height=(unsigned int) event.xconfigure.height;
2455 Group leader has exited.
2457 if (display_image->debug != MagickFalse)
2458 (void) LogMagickEvent(X11Event,GetMagickModule(),
2459 "Destroy Notify: 0x%lx",event.xdestroywindow.window);
2460 if (event.xdestroywindow.window == windows->group_leader.id)
2470 Selectively install colormap.
2472 if (map_info->colormap != XDefaultColormap(display,visual_info->screen))
2473 if (event.xcrossing.mode != NotifyUngrab)
2474 XInstallColormap(display,map_info->colormap);
2479 if (display_image->debug != MagickFalse)
2480 (void) LogMagickEvent(X11Event,GetMagickModule(),
2481 "Expose: 0x%lx %dx%d+%d+%d",event.xexpose.window,
2482 event.xexpose.width,event.xexpose.height,event.xexpose.x,
2485 Repaint windows that are now exposed.
2487 if (event.xexpose.window == windows->image.id)
2489 windows->image.pixmap=windows->image.pixmaps[scene];
2490 windows->image.matte_pixmap=windows->image.matte_pixmaps[scene];
2491 XRefreshWindow(display,&windows->image,&event);
2494 if (event.xexpose.window == windows->icon.id)
2495 if (event.xexpose.count == 0)
2497 XRefreshWindow(display,&windows->icon,&event);
2508 Respond to a user key press.
2510 length=XLookupString((XKeyEvent *) &event.xkey,command,(int)
2511 sizeof(command),&key_symbol,(XComposeStatus *) NULL);
2512 *(command+length)='\0';
2513 if (display_image->debug != MagickFalse)
2514 (void) LogMagickEvent(X11Event,GetMagickModule(),
2515 "Key press: 0x%lx (%c)",(unsigned long) key_symbol,*command);
2516 command_type=NullCommand;
2521 if ((event.xkey.state & ControlMask) == MagickFalse)
2523 command_type=OpenCommand;
2528 command_type=StepBackwardCommand;
2533 command_type=StepForwardCommand;
2538 command_type=FasterCommand;
2543 command_type=SlowerCommand;
2548 command_type=HelpCommand;
2553 command_type=BrowseDocumentationCommand;
2558 command_type=InfoCommand;
2564 command_type=QuitCommand;
2570 if (command_type != NullCommand)
2571 nexus=XMagickCommand(display,resource_info,windows,
2572 command_type,&image,&state);
2578 Respond to a user key release.
2580 (void) XLookupString((XKeyEvent *) &event.xkey,command,(int)
2581 sizeof(command),&key_symbol,(XComposeStatus *) NULL);
2582 if (display_image->debug != MagickFalse)
2583 (void) LogMagickEvent(X11Event,GetMagickModule(),
2584 "Key release: 0x%lx (%c)",(unsigned long) key_symbol,*command);
2590 Selectively uninstall colormap.
2592 if (map_info->colormap != XDefaultColormap(display,visual_info->screen))
2593 if (event.xcrossing.mode != NotifyUngrab)
2594 XUninstallColormap(display,map_info->colormap);
2599 if (display_image->debug != MagickFalse)
2600 (void) LogMagickEvent(X11Event,GetMagickModule(),"Map Notify: 0x%lx",
2602 if (event.xmap.window == windows->backdrop.id)
2604 (void) XSetInputFocus(display,event.xmap.window,RevertToParent,
2606 windows->backdrop.mapped=MagickTrue;
2609 if (event.xmap.window == windows->image.id)
2611 if (windows->backdrop.id != (Window) NULL)
2612 (void) XInstallColormap(display,map_info->colormap);
2613 if (LocaleCompare(image_list[0]->magick,"LOGO") == 0)
2615 if (LocaleCompare(display_image->filename,"LOGO") == 0)
2616 nexus=XMagickCommand(display,resource_info,windows,
2617 OpenCommand,&image,&state);
2621 windows->image.mapped=MagickTrue;
2624 if (event.xmap.window == windows->info.id)
2626 windows->info.mapped=MagickTrue;
2629 if (event.xmap.window == windows->icon.id)
2632 Create an icon image.
2634 XMakeStandardColormap(display,icon_visual,icon_resources,
2635 display_image,icon_map,icon_pixel);
2636 (void) XMakeImage(display,icon_resources,&windows->icon,
2637 display_image,windows->icon.width,windows->icon.height);
2638 (void) XSetWindowBackgroundPixmap(display,windows->icon.id,
2639 windows->icon.pixmap);
2640 (void) XClearWindow(display,windows->icon.id);
2641 (void) XWithdrawWindow(display,windows->info.id,
2642 windows->info.screen);
2643 windows->icon.mapped=MagickTrue;
2646 if (event.xmap.window == windows->command.id)
2648 windows->command.mapped=MagickTrue;
2651 if (event.xmap.window == windows->popup.id)
2653 windows->popup.mapped=MagickTrue;
2656 if (event.xmap.window == windows->widget.id)
2658 windows->widget.mapped=MagickTrue;
2665 (void) XRefreshKeyboardMapping(&event.xmapping);
2670 case PropertyNotify:
2686 if (display_image->debug != MagickFalse)
2687 (void) LogMagickEvent(X11Event,GetMagickModule(),
2688 "Property Notify: 0x%lx 0x%lx %d",event.xproperty.window,
2689 event.xproperty.atom,event.xproperty.state);
2690 if (event.xproperty.atom != windows->im_remote_command)
2693 Display image named by the remote command protocol.
2695 status=XGetWindowProperty(display,event.xproperty.window,
2696 event.xproperty.atom,0L,(long) MaxTextExtent,MagickFalse,(Atom)
2697 AnyPropertyType,&type,&format,&length,&after,&data);
2698 if ((status != Success) || (length == 0))
2700 (void) CopyMagickString(resource_info->image_info->filename,
2701 (char *) data,MaxTextExtent);
2702 nexus=ReadImage(resource_info->image_info,&image->exception);
2703 CatchException(&image->exception);
2704 if (nexus != (Image *) NULL)
2706 (void) XFree((void *) data);
2709 case ReparentNotify:
2711 if (display_image->debug != MagickFalse)
2712 (void) LogMagickEvent(X11Event,GetMagickModule(),
2713 "Reparent Notify: 0x%lx=>0x%lx",event.xreparent.parent,
2714 event.xreparent.window);
2719 if (display_image->debug != MagickFalse)
2720 (void) LogMagickEvent(X11Event,GetMagickModule(),
2721 "Unmap Notify: 0x%lx",event.xunmap.window);
2722 if (event.xunmap.window == windows->backdrop.id)
2724 windows->backdrop.mapped=MagickFalse;
2727 if (event.xunmap.window == windows->image.id)
2729 windows->image.mapped=MagickFalse;
2732 if (event.xunmap.window == windows->info.id)
2734 windows->info.mapped=MagickFalse;
2737 if (event.xunmap.window == windows->icon.id)
2739 if (map_info->colormap == icon_map->colormap)
2740 XConfigureImageColormap(display,resource_info,windows,
2742 (void) XFreeStandardColormap(display,icon_visual,icon_map,
2744 windows->icon.mapped=MagickFalse;
2747 if (event.xunmap.window == windows->command.id)
2749 windows->command.mapped=MagickFalse;
2752 if (event.xunmap.window == windows->popup.id)
2754 if (windows->backdrop.id != (Window) NULL)
2755 (void) XSetInputFocus(display,windows->image.id,RevertToParent,
2757 windows->popup.mapped=MagickFalse;
2760 if (event.xunmap.window == windows->widget.id)
2762 if (windows->backdrop.id != (Window) NULL)
2763 (void) XSetInputFocus(display,windows->image.id,RevertToParent,
2765 windows->widget.mapped=MagickFalse;
2772 if (display_image->debug != MagickFalse)
2773 (void) LogMagickEvent(X11Event,GetMagickModule(),"Event type: %d",
2779 while (!(state & ExitState));
2780 image_list=(Image **) RelinquishMagickMemory(image_list);
2781 images=DestroyImageList(images);
2782 if ((windows->visual_info->klass == GrayScale) ||
2783 (windows->visual_info->klass == PseudoColor) ||
2784 (windows->visual_info->klass == DirectColor))
2789 if (windows->info.mapped)
2790 (void) XWithdrawWindow(display,windows->info.id,windows->info.screen);
2791 if (windows->command.mapped)
2792 (void) XWithdrawWindow(display,windows->command.id,
2793 windows->command.screen);
2795 if (resource_info->backdrop == MagickFalse)
2796 if (windows->backdrop.mapped)
2798 (void) XWithdrawWindow(display,windows->backdrop.id,\
2799 windows->backdrop.screen);
2800 (void) XDestroyWindow(display,windows->backdrop.id);
2801 windows->backdrop.id=(Window) NULL;
2802 (void) XWithdrawWindow(display,windows->image.id,windows->image.screen);
2803 (void) XDestroyWindow(display,windows->image.id);
2804 windows->image.id=(Window) NULL;
2806 XSetCursorState(display,windows,MagickTrue);
2807 XCheckRefreshWindows(display,windows);
2808 for (scene=1; scene < (long) number_scenes; scene++)
2810 if (windows->image.pixmaps[scene] != (Pixmap) NULL)
2811 (void) XFreePixmap(display,windows->image.pixmaps[scene]);
2812 windows->image.pixmaps[scene]=(Pixmap) NULL;
2813 if (windows->image.matte_pixmaps[scene] != (Pixmap) NULL)
2814 (void) XFreePixmap(display,windows->image.matte_pixmaps[scene]);
2815 windows->image.matte_pixmaps[scene]=(Pixmap) NULL;
2817 windows->image.pixmaps=(Pixmap *)
2818 RelinquishMagickMemory(windows->image.pixmaps);
2819 windows->image.matte_pixmaps=(Pixmap *)
2820 RelinquishMagickMemory(windows->image.matte_pixmaps);
2821 if (nexus == (Image *) NULL)
2826 if (windows->image.mapped != MagickFalse)
2827 (void) XWithdrawWindow(display,windows->image.id,windows->image.screen); XDelay(display,SuspendTime);
2828 (void) XFreeStandardColormap(display,icon_visual,icon_map,icon_pixel);
2829 if (resource_info->map_type == (char *) NULL)
2830 (void) XFreeStandardColormap(display,visual_info,map_info,pixel);
2831 DestroyXResources();
2833 (void) XSync(display,MagickFalse);
2835 Restore our progress monitor and warning handlers.
2837 (void) SetErrorHandler(warning_handler);
2838 (void) SetWarningHandler(warning_handler);
2840 Change to home directory.
2842 cwd=getcwd(working_directory,MaxTextExtent);
2843 status=chdir(resource_info->home_directory);
2845 (void) ThrowMagickException(&images->exception,GetMagickModule(),
2846 FileOpenError,"UnableToOpenFile","%s",resource_info->home_directory);
2851 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2855 + X S a v e I m a g e %
2859 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2861 % XSaveImage() saves an image to a file.
2863 % The format of the XSaveImage method is:
2865 % MagickBooleanType XSaveImage(Display *display,
2866 % XResourceInfo *resource_info,XWindows *windows,Image *image)
2868 % A description of each parameter follows:
2870 % o status: Method XSaveImage return True if the image is
2871 % written. False is returned is there is a memory shortage or if the
2872 % image fails to write.
2874 % o display: Specifies a connection to an X server; returned from
2877 % o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
2879 % o windows: Specifies a pointer to a XWindows structure.
2881 % o image: the image.
2884 static MagickBooleanType XSaveImage(Display *display,
2885 XResourceInfo *resource_info,XWindows *windows,Image *image)
2888 filename[MaxTextExtent];
2897 Request file name from user.
2899 if (resource_info->write_filename != (char *) NULL)
2900 (void) CopyMagickString(filename,resource_info->write_filename,
2905 path[MaxTextExtent];
2910 GetPathComponent(image->filename,HeadPath,path);
2911 GetPathComponent(image->filename,TailPath,filename);
2914 (void) ThrowMagickException(&image->exception,GetMagickModule(),
2915 FileOpenError,"UnableToOpenFile","%s",path);
2917 XFileBrowserWidget(display,windows,"Save",filename);
2918 if (*filename == '\0')
2920 if (IsPathAccessible(filename) != MagickFalse)
2926 File exists-- seek user's permission before overwriting.
2928 status=XConfirmWidget(display,windows,"Overwrite",filename);
2932 image_info=CloneImageInfo(resource_info->image_info);
2933 (void) CopyMagickString(image_info->filename,filename,MaxTextExtent);
2934 (void) SetImageInfo(image_info,MagickFalse,&image->exception);
2935 if ((LocaleCompare(image_info->magick,"JPEG") == 0) ||
2936 (LocaleCompare(image_info->magick,"JPG") == 0))
2939 quality[MaxTextExtent];
2945 Request JPEG quality from user.
2947 (void) FormatMagickString(quality,MaxTextExtent,"%lu",
2948 image_info->quality);
2949 status=XDialogWidget(display,windows,"Save","Enter JPEG quality:",
2951 if (*quality == '\0')
2953 image->quality=(unsigned long) StringToLong(quality);
2954 image_info->interlace=status != MagickFalse ? NoInterlace :
2957 if ((LocaleCompare(image_info->magick,"EPS") == 0) ||
2958 (LocaleCompare(image_info->magick,"PDF") == 0) ||
2959 (LocaleCompare(image_info->magick,"PS") == 0) ||
2960 (LocaleCompare(image_info->magick,"PS2") == 0))
2963 geometry[MaxTextExtent];
2966 Request page geometry from user.
2968 (void) CopyMagickString(geometry,PSPageGeometry,MaxTextExtent);
2969 if (LocaleCompare(image_info->magick,"PDF") == 0)
2970 (void) CopyMagickString(geometry,PSPageGeometry,MaxTextExtent);
2971 if (image_info->page != (char *) NULL)
2972 (void) CopyMagickString(geometry,image_info->page,MaxTextExtent);
2973 XListBrowserWidget(display,windows,&windows->widget,PageSizes,"Select",
2974 "Select page geometry:",geometry);
2975 if (*geometry != '\0')
2976 image_info->page=GetPageGeometry(geometry);
2981 image=GetFirstImageInList(image);
2982 status=WriteImages(image_info,image,filename,&image->exception);
2983 if (status != MagickFalse)
2984 image->taint=MagickFalse;
2985 image_info=DestroyImageInfo(image_info);
2986 XSetCursorState(display,windows,MagickFalse);
2987 return(status != 0 ? MagickTrue : MagickFalse);
2992 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2996 + A n i m a t e I m a g e s %
3000 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3002 % AnimateImages() repeatedly displays an image sequence to any X window
3003 % screen. It returns a value other than 0 if successful. Check the
3004 % exception member of image to determine the reason for any failure.
3006 % The format of the AnimateImages method is:
3008 % MagickBooleanType AnimateImages(const ImageInfo *image_info,
3011 % A description of each parameter follows:
3013 % o image_info: the image info.
3015 % o image: the image.
3018 MagickExport MagickBooleanType AnimateImages(const ImageInfo *image_info,
3021 assert(image_info != (const ImageInfo *) NULL);
3022 assert(image_info->signature == MagickSignature);
3023 assert(image != (Image *) NULL);
3024 assert(image->signature == MagickSignature);
3025 if (image->debug != MagickFalse)
3026 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
3027 (void) ThrowMagickException(&image->exception,GetMagickModule(),
3028 MissingDelegateError,"DelegateLibrarySupportNotBuiltIn","`%s' (X11)",
3030 return(MagickFalse);