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-2017 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 % https://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/attribute.h"
46 #include "MagickCore/client.h"
47 #include "MagickCore/color.h"
48 #include "MagickCore/color-private.h"
49 #include "MagickCore/colorspace.h"
50 #include "MagickCore/colorspace-private.h"
51 #include "MagickCore/constitute.h"
52 #include "MagickCore/delegate.h"
53 #include "MagickCore/exception.h"
54 #include "MagickCore/exception-private.h"
55 #include "MagickCore/geometry.h"
56 #include "MagickCore/image-private.h"
57 #include "MagickCore/layer.h"
58 #include "MagickCore/list.h"
59 #include "MagickCore/log.h"
60 #include "MagickCore/image.h"
61 #include "MagickCore/memory_.h"
62 #include "MagickCore/monitor.h"
63 #include "MagickCore/monitor-private.h"
64 #include "MagickCore/option.h"
65 #include "MagickCore/pixel-accessor.h"
66 #include "MagickCore/property.h"
67 #include "MagickCore/resource_.h"
68 #include "MagickCore/string_.h"
69 #include "MagickCore/string-private.h"
70 #include "MagickCore/transform.h"
71 #include "MagickCore/utility.h"
72 #include "MagickCore/utility-private.h"
73 #include "MagickCore/version.h"
74 #include "MagickCore/widget.h"
75 #include "MagickCore/widget-private.h"
76 #include "MagickCore/xwindow.h"
77 #include "MagickCore/xwindow-private.h"
79 #if defined(MAGICKCORE_X11_DELEGATE)
81 Animate state declarations.
83 #define AutoReverseAnimationState 0x0004
84 #define ForwardAnimationState 0x0008
85 #define HighlightState 0x0010
86 #define PlayAnimationState 0x0020
87 #define RepeatAnimationState 0x0040
88 #define StepAnimationState 0x0080
98 " Press any button to map or unmap the Command widget.",
101 " The Command widget lists a number of sub-menus and commands.",
119 " Browse Documentation",
124 " Menu items with a indented triangle have a sub-menu. They",
125 " are represented above as the indented items. To access a",
126 " sub-menu item, move the pointer to the appropriate menu and",
127 " press a button and drag. When you find the desired sub-menu",
128 " item, release the button and the command is executed. Move",
129 " the pointer away from the sub-menu if you decide not to",
130 " execute a particular command.",
132 "KEYBOARD ACCELERATORS",
133 " Accelerators are one or two key presses that effect a",
134 " particular command. The keyboard accelerators that",
135 " animate(1) understands is:",
137 " Ctl+O Press to open an image from a file.",
139 " space Press to display the next image in the sequence.",
141 " < Press to speed-up the display of the images. Refer to",
142 " -delay for more information.",
144 " > Press to slow the display of the images. Refer to",
145 " -delay for more information.",
147 " F1 Press to display helpful information about animate(1).",
149 " Find Press to browse documentation about ImageMagick.",
151 " ? Press to display information about the image. Press",
152 " any key or button to erase the information.",
154 " This information is printed: image name; image size;",
155 " and the total number of unique colors in the image.",
157 " Ctl-q Press to discard all images and exit program.",
162 Constant declarations.
184 static const unsigned char
187 (unsigned char) 0xaa,
188 (unsigned char) 0x55,
189 (unsigned char) 0xaa,
190 (unsigned char) 0x55,
191 (unsigned char) 0xaa,
192 (unsigned char) 0x55,
193 (unsigned char) 0xaa,
198 (unsigned char) 0x00,
199 (unsigned char) 0x00,
200 (unsigned char) 0x00,
201 (unsigned char) 0x00,
202 (unsigned char) 0x00,
203 (unsigned char) 0x00,
204 (unsigned char) 0x00,
209 Enumeration declarations.
224 BrowseDocumentationCommand,
236 #define HighlightWidth 8
237 #define HighlightHeight 8
238 #define ShadowWidth 8
239 #define ShadowHeight 8
242 Forward declarations.
245 *XMagickCommand(Display *,XResourceInfo *,XWindows *,const CommandType,
246 Image **,MagickStatusType *,ExceptionInfo *);
248 static MagickBooleanType
249 XSaveImage(Display *,XResourceInfo *,XWindows *,Image *,ExceptionInfo *);
252 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
256 % A n i m a t e I m a g e s %
260 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
262 % AnimateImages() repeatedly displays an image sequence to any X window
263 % screen. It returns a value other than 0 if successful. Check the
264 % exception member of image to determine the reason for any failure.
266 % The format of the AnimateImages method is:
268 % MagickBooleanType AnimateImages(const ImageInfo *image_info,
269 % Image *images,ExceptionInfo *exception)
271 % A description of each parameter follows:
273 % o image_info: the image info.
275 % o image: the image.
277 % o exception: return any errors or warnings in this structure.
280 MagickExport MagickBooleanType AnimateImages(const ImageInfo *image_info,
281 Image *images,ExceptionInfo *exception)
298 assert(image_info != (const ImageInfo *) NULL);
299 assert(image_info->signature == MagickCoreSignature);
300 assert(images != (Image *) NULL);
301 assert(images->signature == MagickCoreSignature);
302 if (images->debug != MagickFalse)
303 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",images->filename);
304 display=XOpenDisplay(image_info->server_name);
305 if (display == (Display *) NULL)
307 (void) ThrowMagickException(exception,GetMagickModule(),XServerError,
308 "UnableToOpenXServer","`%s'",XDisplayName(image_info->server_name));
311 if (exception->severity != UndefinedException)
312 CatchException(exception);
313 (void) XSetErrorHandler(XError);
314 resource_database=XGetResourceDatabase(display,GetClientName());
315 (void) ResetMagickMemory(&resource_info,0,sizeof(XResourceInfo));
316 XGetResourceInfo(image_info,resource_database,GetClientName(),&resource_info);
317 if (image_info->page != (char *) NULL)
318 resource_info.image_geometry=AcquireString(image_info->page);
319 resource_info.immutable=MagickTrue;
320 argv[0]=AcquireString(GetClientName());
321 (void) XAnimateImages(display,&resource_info,argv,1,images,exception);
322 (void) SetErrorHandler((ErrorHandler) NULL);
323 (void) SetWarningHandler((WarningHandler) NULL);
324 argv[0]=DestroyString(argv[0]);
325 (void) XCloseDisplay(display);
326 XDestroyResourceInfo(&resource_info);
327 status=exception->severity == UndefinedException ? MagickTrue : MagickFalse;
328 return(status != 0 ? MagickTrue : MagickFalse);
332 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
336 + X M a g i c k C o m m a n d %
340 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
342 % XMagickCommand() makes a transform to the image or Image window as specified
343 % by a user menu button or keyboard command.
345 % The format of the XMagickCommand method is:
347 % Image *XMagickCommand(Display *display,XResourceInfo *resource_info,
348 % XWindows *windows,const CommandType command_type,Image **image,
349 % MagickStatusType *state,ExceptionInfo *exception)
351 % A description of each parameter follows:
353 % o display: Specifies a connection to an X server; returned from
356 % o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
358 % o windows: Specifies a pointer to a XWindows structure.
360 % o image: the image; XMagickCommand
361 % may transform the image and return a new image pointer.
363 % o state: Specifies a MagickStatusType; XMagickCommand may return a
366 % o exception: return any errors or warnings in this structure.
370 static Image *XMagickCommand(Display *display,XResourceInfo *resource_info,
371 XWindows *windows,const CommandType command_type,Image **image,
372 MagickStatusType *state,ExceptionInfo *exception)
387 Process user command.
389 nexus=NewImageList();
390 switch (command_type)
411 filenames[MagickPathExtent] = "*";
413 if (resource_info->immutable != MagickFalse)
416 Request file name from user.
418 XFileBrowserWidget(display,windows,"Animate",filenames);
419 if (*filenames == '\0')
420 return((Image *) NULL);
422 Expand the filenames.
424 filelist=(char **) AcquireMagickMemory(sizeof(char *));
425 if (filelist == (char **) NULL)
427 ThrowXWindowException(ResourceLimitError,"MemoryAllocationFailed",
429 return((Image *) NULL);
432 filelist[0]=filenames;
433 status=ExpandFilenames(&number_files,&filelist);
434 if ((status == MagickFalse) || (number_files == 0))
436 if (number_files == 0)
438 ThrowXWindowException(ImageError,"NoImagesWereLoaded",filenames);
439 return((Image *) NULL);
441 ThrowXWindowException(ResourceLimitError,"MemoryAllocationFailed",
443 return((Image *) NULL);
445 read_info=CloneImageInfo(resource_info->image_info);
446 images=NewImageList();
447 XSetCursorState(display,windows,MagickTrue);
448 XCheckRefreshWindows(display,windows);
449 for (i=0; i < number_files; i++)
451 (void) CopyMagickString(read_info->filename,filelist[i],MagickPathExtent);
452 filelist[i]=DestroyString(filelist[i]);
453 *read_info->magick='\0';
454 next=ReadImage(read_info,exception);
455 CatchException(exception);
456 if (next != (Image *) NULL)
457 AppendImageToList(&images,next);
458 if (number_files <= 5)
460 proceed=SetImageProgress(images,LoadImageTag,i,(MagickSizeType)
462 if (proceed == MagickFalse)
465 filelist=(char **) RelinquishMagickMemory(filelist);
466 read_info=DestroyImageInfo(read_info);
467 if (images == (Image *) NULL)
469 XSetCursorState(display,windows,MagickFalse);
470 ThrowXWindowException(ImageError,"NoImagesWereLoaded",filenames);
471 return((Image *) NULL);
473 nexus=GetFirstImageInList(images);
480 basename[MagickPathExtent];
486 Window name is the base of the filename.
488 *state|=PlayAnimationState;
489 *state&=(~AutoReverseAnimationState);
490 GetPathComponent((*image)->magick_filename,BasePath,basename);
491 (void) FormatLocaleString(windows->image.name,MagickPathExtent,
492 "%s: %s",MagickPackageName,basename);
493 if (resource_info->title != (char *) NULL)
498 title=InterpretImageProperties(resource_info->image_info,*image,
499 resource_info->title,exception);
500 (void) CopyMagickString(windows->image.name,title,MagickPathExtent);
501 title=DestroyString(title);
503 status=XStringListToTextProperty(&windows->image.name,1,&window_name);
506 XSetWMName(display,windows->image.id,&window_name);
507 (void) XFree((void *) window_name.value);
511 case StepBackwardCommand:
512 case StepForwardCommand:
514 *state|=StepAnimationState;
515 *state&=(~PlayAnimationState);
516 if (command_type == StepBackwardCommand)
517 *state&=(~ForwardAnimationState);
518 if (command_type == StepForwardCommand)
519 *state|=ForwardAnimationState;
520 if (resource_info->title != (char *) NULL)
526 *state|=RepeatAnimationState;
527 *state&=(~AutoReverseAnimationState);
528 *state|=PlayAnimationState;
531 case AutoReverseCommand:
533 *state|=AutoReverseAnimationState;
534 *state&=(~RepeatAnimationState);
535 *state|=PlayAnimationState;
543 status=XSaveImage(display,resource_info,windows,*image,exception);
544 if (status == MagickFalse)
547 message[MagickPathExtent];
549 (void) FormatLocaleString(message,MagickPathExtent,"%s:%s",
550 exception->reason != (char *) NULL ? exception->reason : "",
551 exception->description != (char *) NULL ? exception->description :
553 XNoticeWidget(display,windows,"Unable to save file:",message);
560 resource_info->delay++;
565 if (resource_info->delay == 0)
567 resource_info->delay--;
572 *state=ForwardAnimationState;
573 *state&=(~AutoReverseAnimationState);
578 *state&=(~ForwardAnimationState);
579 *state&=(~AutoReverseAnimationState);
584 XDisplayImageInfo(display,resource_info,windows,(Image *) NULL,*image,
593 XTextViewWidget(display,resource_info,windows,MagickFalse,
594 "Help Viewer - Animate",AnimateHelp);
597 case BrowseDocumentationCommand:
607 Browse the ImageMagick documentation.
609 root_window=XRootWindow(display,XDefaultScreen(display));
610 mozilla_atom=XInternAtom(display,"_MOZILLA_VERSION",MagickFalse);
611 mozilla_window=XWindowByProperty(display,root_window,mozilla_atom);
612 if (mozilla_window != (Window) NULL)
615 command[MagickPathExtent],
619 Display documentation using Netscape remote control.
621 url=GetMagickHomeURL();
622 (void) FormatLocaleString(command,MagickPathExtent,
623 "openurl(%s,new-tab)",url);
624 url=DestroyString(url);
625 mozilla_atom=XInternAtom(display,"_MOZILLA_COMMAND",MagickFalse);
626 (void) XChangeProperty(display,mozilla_window,mozilla_atom,
627 XA_STRING,8,PropModeReplace,(unsigned char *) command,
628 (int) strlen(command));
629 XSetCursorState(display,windows,MagickFalse);
632 XSetCursorState(display,windows,MagickTrue);
633 XCheckRefreshWindows(display,windows);
634 status=InvokeDelegate(resource_info->image_info,*image,"browse",
635 (char *) NULL,exception);
636 if (status == MagickFalse)
637 XNoticeWidget(display,windows,"Unable to browse documentation",
639 XDelay(display,1500);
640 XSetCursorState(display,windows,MagickFalse);
645 XNoticeWidget(display,windows,GetMagickVersion((size_t *) NULL),
646 GetMagickCopyright());
654 if (resource_info->confirm_exit == MagickFalse)
655 XClientMessage(display,windows->image.id,windows->im_protocols,
656 windows->im_exit,CurrentTime);
663 Confirm program exit.
665 status=XConfirmWidget(display,windows,"Do you really want to exit",
666 resource_info->client_name);
668 XClientMessage(display,windows->image.id,windows->im_protocols,
669 windows->im_exit,CurrentTime);
680 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
684 + X A n i m a t e B a c k g r o u n d I m a g e %
688 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
690 % XAnimateBackgroundImage() animates an image sequence in the background of
693 % The format of the XAnimateBackgroundImage method is:
695 % void XAnimateBackgroundImage(Display *display,
696 % XResourceInfo *resource_info,Image *images,ExceptionInfo *exception)
698 % A description of each parameter follows:
700 % o display: Specifies a connection to an X server; returned from
703 % o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
705 % o images: the image list.
707 % o exception: return any errors or warnings in this structure.
711 #if defined(__cplusplus) || defined(c_plusplus)
715 static int SceneCompare(const void *x,const void *y)
721 image_1=(const Image **) x;
722 image_2=(const Image **) y;
723 return((int) ((*image_1)->scene-(*image_2)->scene));
726 #if defined(__cplusplus) || defined(c_plusplus)
730 MagickExport void XAnimateBackgroundImage(Display *display,
731 XResourceInfo *resource_info,Image *images,ExceptionInfo *exception)
734 geometry[MagickPathExtent],
735 visual_type[MagickPathExtent];
764 static XStandardColormap
768 *visual_info = (XVisualInfo *) NULL;
793 Determine target window.
795 assert(images != (Image *) NULL);
796 assert(images->signature == MagickCoreSignature);
797 if (images->debug != MagickFalse)
798 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",images->filename);
799 resources=(*resource_info);
800 window_info.id=(Window) NULL;
801 root_window=XRootWindow(display,XDefaultScreen(display));
802 if (LocaleCompare(resources.window_id,"root") == 0)
803 window_info.id=root_window;
806 if (isdigit((int) ((unsigned char) *resources.window_id)) != 0)
807 window_info.id=XWindowByID(display,root_window,
808 (Window) strtol((char *) resources.window_id,(char **) NULL,0));
809 if (window_info.id == (Window) NULL)
811 XWindowByName(display,root_window,resources.window_id);
813 if (window_info.id == (Window) NULL)
815 ThrowXWindowException(XServerError,"NoWindowWithSpecifiedIDExists",
816 resources.window_id);
820 Determine window visual id.
822 window_attributes.width=XDisplayWidth(display,XDefaultScreen(display));
823 window_attributes.height=XDisplayHeight(display,XDefaultScreen(display));
824 (void) CopyMagickString(visual_type,"default",MagickPathExtent);
825 status=XGetWindowAttributes(display,window_info.id,&window_attributes) != 0 ?
826 MagickTrue : MagickFalse;
827 if (status != MagickFalse)
828 (void) FormatLocaleString(visual_type,MagickPathExtent,"0x%lx",
829 XVisualIDFromVisual(window_attributes.visual));
830 if (visual_info == (XVisualInfo *) NULL)
833 Allocate standard colormap.
835 map_info=XAllocStandardColormap();
836 if (map_info == (XStandardColormap *) NULL)
837 ThrowXWindowFatalException(ResourceLimitFatalError,
838 "MemoryAllocationFailed",images->filename);
839 map_info->colormap=(Colormap) NULL;
840 pixel.pixels=(unsigned long *) NULL;
842 Initialize visual info.
844 resources.map_type=(char *) NULL;
845 resources.visual_type=visual_type;
846 visual_info=XBestVisualInfo(display,map_info,&resources);
847 if (visual_info == (XVisualInfo *) NULL)
848 ThrowXWindowFatalException(XServerFatalError,"UnableToGetVisual",
851 Initialize window info.
853 window_info.ximage=(XImage *) NULL;
854 window_info.matte_image=(XImage *) NULL;
855 window_info.pixmap=(Pixmap) NULL;
856 window_info.matte_pixmap=(Pixmap) NULL;
859 Free previous root colors.
861 if (window_info.id == root_window)
862 XDestroyWindowColors(display,root_window);
863 coalesce_image=CoalesceImages(images,exception);
864 if (coalesce_image == (Image *) NULL)
865 ThrowXWindowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed",
867 images=coalesce_image;
868 if (resources.map_type == (char *) NULL)
869 if ((visual_info->klass != TrueColor) &&
870 (visual_info->klass != DirectColor))
876 Determine if the sequence of images has the identical colormap.
878 for (next=images; next != (Image *) NULL; )
880 next->alpha_trait=UndefinedPixelTrait;
881 if ((next->storage_class == DirectClass) ||
882 (next->colors != images->colors) ||
883 (next->colors > (size_t) visual_info->colormap_size))
885 for (i=0; i < (ssize_t) images->colors; i++)
886 if (IsPixelInfoEquivalent(next->colormap+i,images->colormap+i) == MagickFalse)
888 if (i < (ssize_t) images->colors)
890 next=GetNextImageInList(next);
892 if (next != (Image *) NULL)
893 (void) RemapImages(resources.quantize_info,images,(Image *) NULL,
897 Sort images by increasing scene number.
899 number_scenes=GetImageListLength(images);
900 image_list=ImageListToArray(images,exception);
901 if (image_list == (Image **) NULL)
902 ThrowXWindowFatalException(ResourceLimitFatalError,
903 "MemoryAllocationFailed",images->filename);
904 for (i=0; i < (ssize_t) number_scenes; i++)
905 if (image_list[i]->scene == 0)
907 if (i == (ssize_t) number_scenes)
908 qsort((void *) image_list,number_scenes,sizeof(Image *),SceneCompare);
910 Initialize Standard Colormap.
912 resources.colormap=SharedColormap;
913 display_image=image_list[0];
914 for (scene=0; scene < (int) number_scenes; scene++)
916 if ((resource_info->map_type != (char *) NULL) ||
917 (visual_info->klass == TrueColor) ||
918 (visual_info->klass == DirectColor))
919 (void) SetImageType(image_list[scene],image_list[scene]->alpha_trait ==
920 BlendPixelTrait ? TrueColorType : TrueColorAlphaType,exception);
921 if ((display_image->columns < image_list[scene]->columns) &&
922 (display_image->rows < image_list[scene]->rows))
923 display_image=image_list[scene];
925 if ((resource_info->map_type != (char *) NULL) ||
926 (visual_info->klass == TrueColor) || (visual_info->klass == DirectColor))
927 (void) SetImageType(display_image,display_image->alpha_trait !=
928 BlendPixelTrait ? TrueColorType : TrueColorAlphaType,exception);
929 XMakeStandardColormap(display,visual_info,&resources,display_image,map_info,
932 Graphic context superclass.
934 context_values.background=pixel.background_color.pixel;
935 context_values.foreground=pixel.foreground_color.pixel;
936 pixel.annotate_context=XCreateGC(display,window_info.id,(unsigned long)
937 (GCBackground | GCForeground),&context_values);
938 if (pixel.annotate_context == (GC) NULL)
939 ThrowXWindowFatalException(XServerFatalError,"UnableToCreateGraphicContext",
942 Initialize Image window attributes.
944 XGetWindowInfo(display,visual_info,map_info,&pixel,(XFontStruct *) NULL,
945 &resources,&window_info);
949 window_info.width=(unsigned int) image_list[0]->columns;
950 window_info.height=(unsigned int) image_list[0]->rows;
951 if ((image_list[0]->columns != window_info.width) ||
952 (image_list[0]->rows != window_info.height))
953 ThrowXWindowFatalException(XServerFatalError,"UnableToCreateXImage",
954 image_list[0]->filename);
955 (void) FormatLocaleString(geometry,MagickPathExtent,"%ux%u+0+0>",
956 window_attributes.width,window_attributes.height);
957 geometry_info.width=window_info.width;
958 geometry_info.height=window_info.height;
959 geometry_info.x=(ssize_t) window_info.x;
960 geometry_info.y=(ssize_t) window_info.y;
961 (void) ParseMetaGeometry(geometry,&geometry_info.x,&geometry_info.y,
962 &geometry_info.width,&geometry_info.height);
963 window_info.width=(unsigned int) geometry_info.width;
964 window_info.height=(unsigned int) geometry_info.height;
965 window_info.x=(int) geometry_info.x;
966 window_info.y=(int) geometry_info.y;
967 status=XMakeImage(display,&resources,&window_info,image_list[0],
968 window_info.width,window_info.height,exception);
969 if (status == MagickFalse)
970 ThrowXWindowFatalException(XServerFatalError,"UnableToCreateXImage",
974 if (display_image->debug != MagickFalse)
976 (void) LogMagickEvent(X11Event,GetMagickModule(),
977 "Image: %s[%.20g] %.20gx%.20g ",image_list[0]->filename,(double)
978 image_list[0]->scene,(double) image_list[0]->columns,(double)
979 image_list[0]->rows);
980 if (image_list[0]->colors != 0)
981 (void) LogMagickEvent(X11Event,GetMagickModule(),"%.20gc ",(double)
982 image_list[0]->colors);
983 (void) LogMagickEvent(X11Event,GetMagickModule(),"%s",
984 image_list[0]->magick);
987 Adjust image dimensions as specified by backdrop or geometry options.
989 width=window_info.width;
990 height=window_info.height;
991 if (resources.backdrop != MagickFalse)
994 Center image on window.
996 window_info.x=(int) (window_attributes.width/2)-
997 (window_info.ximage->width/2);
998 window_info.y=(int) (window_attributes.height/2)-
999 (window_info.ximage->height/2);
1000 width=(unsigned int) window_attributes.width;
1001 height=(unsigned int) window_attributes.height;
1003 if (resources.image_geometry != (char *) NULL)
1006 default_geometry[MagickPathExtent];
1016 User specified geometry.
1018 size_hints=XAllocSizeHints();
1019 if (size_hints == (XSizeHints *) NULL)
1020 ThrowXWindowFatalException(ResourceLimitFatalError,
1021 "MemoryAllocationFailed",images->filename);
1022 size_hints->flags=0L;
1023 (void) FormatLocaleString(default_geometry,MagickPathExtent,"%ux%u",width,
1025 flags=XWMGeometry(display,visual_info->screen,resources.image_geometry,
1026 default_geometry,window_info.border_width,size_hints,&window_info.x,
1027 &window_info.y,(int *) &width,(int *) &height,&gravity);
1028 if (((flags & (XValue | YValue))) != 0)
1030 width=(unsigned int) window_attributes.width;
1031 height=(unsigned int) window_attributes.height;
1033 (void) XFree((void *) size_hints);
1036 Create the X pixmap.
1038 window_info.pixmap=XCreatePixmap(display,window_info.id,(unsigned int) width,
1039 (unsigned int) height,window_info.depth);
1040 if (window_info.pixmap == (Pixmap) NULL)
1041 ThrowXWindowFatalException(XServerFatalError,"UnableToCreateXPixmap",
1044 Display pixmap on the window.
1046 if (((unsigned int) width > window_info.width) ||
1047 ((unsigned int) height > window_info.height))
1048 (void) XFillRectangle(display,window_info.pixmap,
1049 window_info.annotate_context,0,0,(unsigned int) width,
1050 (unsigned int) height);
1051 (void) XPutImage(display,window_info.pixmap,window_info.annotate_context,
1052 window_info.ximage,0,0,window_info.x,window_info.y,window_info.width,
1053 window_info.height);
1054 (void) XSetWindowBackgroundPixmap(display,window_info.id,window_info.pixmap);
1055 (void) XClearWindow(display,window_info.id);
1057 Initialize image pixmaps structure.
1059 window_info.pixmaps=(Pixmap *) AcquireQuantumMemory(number_scenes,
1060 sizeof(*window_info.pixmaps));
1061 window_info.matte_pixmaps=(Pixmap *) AcquireQuantumMemory(number_scenes,
1062 sizeof(*window_info.matte_pixmaps));
1063 if ((window_info.pixmaps == (Pixmap *) NULL) ||
1064 (window_info.matte_pixmaps == (Pixmap *) NULL))
1065 ThrowXWindowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed",
1067 window_info.pixmaps[0]=window_info.pixmap;
1068 window_info.matte_pixmaps[0]=window_info.pixmap;
1069 for (scene=1; scene < (int) number_scenes; scene++)
1078 window_info.pixmap=(Pixmap) NULL;
1079 window_info.matte_pixmap=(Pixmap) NULL;
1080 if ((resources.map_type != (char *) NULL) ||
1081 (visual_info->klass == TrueColor) ||
1082 (visual_info->klass == DirectColor))
1083 if (image_list[scene]->storage_class == PseudoClass)
1084 XGetPixelInfo(display,visual_info,map_info,&resources,
1085 image_list[scene],window_info.pixel_info);
1086 columns=(unsigned int) image_list[scene]->columns;
1087 rows=(unsigned int) image_list[scene]->rows;
1088 if ((image_list[scene]->columns != columns) ||
1089 (image_list[scene]->rows != rows))
1090 ThrowXWindowFatalException(XServerFatalError,"UnableToCreateXImage",
1091 image_list[scene]->filename);
1092 status=XMakeImage(display,&resources,&window_info,image_list[scene],
1093 columns,rows,exception);
1094 if (status == MagickFalse)
1095 ThrowXWindowFatalException(XServerFatalError,"UnableToCreateXImage",
1097 if (display_image->debug != MagickFalse)
1099 (void) LogMagickEvent(X11Event,GetMagickModule(),
1100 "Image: [%.20g] %s %.20gx%.20g ",(double) image_list[scene]->scene,
1101 image_list[scene]->filename,(double) columns,(double) rows);
1102 if (image_list[scene]->colors != 0)
1103 (void) LogMagickEvent(X11Event,GetMagickModule(),"%.20gc ",(double)
1104 image_list[scene]->colors);
1105 (void) LogMagickEvent(X11Event,GetMagickModule(),"%s",
1106 image_list[scene]->magick);
1109 Create the X pixmap.
1111 window_info.pixmap=XCreatePixmap(display,window_info.id,width,height,
1113 if (window_info.pixmap == (Pixmap) NULL)
1114 ThrowXWindowFatalException(XServerFatalError,"UnableToCreateXPixmap",
1117 Display pixmap on the window.
1119 if ((width > window_info.width) || (height > window_info.height))
1120 (void) XFillRectangle(display,window_info.pixmap,
1121 window_info.annotate_context,0,0,width,height);
1122 (void) XPutImage(display,window_info.pixmap,window_info.annotate_context,
1123 window_info.ximage,0,0,window_info.x,window_info.y,window_info.width,
1124 window_info.height);
1125 (void) XSetWindowBackgroundPixmap(display,window_info.id,
1126 window_info.pixmap);
1127 (void) XClearWindow(display,window_info.id);
1128 window_info.pixmaps[scene]=window_info.pixmap;
1129 window_info.matte_pixmaps[scene]=window_info.matte_pixmap;
1130 if (image_list[scene]->alpha_trait)
1131 (void) XClearWindow(display,window_info.id);
1132 delay=1000*image_list[scene]->delay/MagickMax(
1133 image_list[scene]->ticks_per_second,1L);
1134 XDelay(display,resources.delay*(delay == 0 ? 10 : delay));
1136 window_info.pixel_info=(&pixel);
1138 Display pixmap on the window.
1140 (void) XSelectInput(display,window_info.id,SubstructureNotifyMask);
1145 for (scene=0; scene < (int) number_scenes; scene++)
1147 if (XEventsQueued(display,QueuedAfterFlush) > 0)
1149 (void) XNextEvent(display,&event);
1150 if (event.type == DestroyNotify)
1153 window_info.pixmap=window_info.pixmaps[scene];
1154 window_info.matte_pixmap=window_info.matte_pixmaps[scene];
1155 (void) XSetWindowBackgroundPixmap(display,window_info.id,
1156 window_info.pixmap);
1157 (void) XClearWindow(display,window_info.id);
1158 (void) XSync(display,MagickFalse);
1159 delay=1000*image_list[scene]->delay/MagickMax(
1160 image_list[scene]->ticks_per_second,1L);
1161 XDelay(display,resources.delay*(delay == 0 ? 10 : delay));
1164 if (iterations == (ssize_t) image_list[0]->iterations)
1166 } while (event.type != DestroyNotify);
1167 (void) XSync(display,MagickFalse);
1168 image_list=(Image **) RelinquishMagickMemory(image_list);
1169 images=DestroyImageList(images);
1173 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1177 + X A n i m a t e I m a g e s %
1181 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1183 % XAnimateImages() displays an image via X11.
1185 % The format of the XAnimateImages method is:
1187 % Image *XAnimateImages(Display *display,XResourceInfo *resource_info,
1188 % char **argv,const int argc,Image *images,ExceptionInfo *exception)
1190 % A description of each parameter follows:
1192 % o display: Specifies a connection to an X server; returned from
1195 % o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
1197 % o argv: Specifies the application's argument list.
1199 % o argc: Specifies the number of arguments.
1201 % o images: the image list.
1203 % o exception: return any errors or warnings in this structure.
1206 MagickExport Image *XAnimateImages(Display *display,
1207 XResourceInfo *resource_info,char **argv,const int argc,Image *images,
1208 ExceptionInfo *exception)
1210 #define MagickMenus 4
1211 #define MaXWindows 8
1212 #define MagickTitle "Commands"
1250 "Browse Documentation",
1256 **Menus[MagickMenus]=
1264 static const CommandType
1288 DirectionCommands[]=
1296 BrowseDocumentationCommand,
1300 static const CommandType
1301 *Commands[MagickMenus]=
1310 command[MagickPathExtent],
1312 geometry[MagickPathExtent],
1313 resource_name[MagickPathExtent];
1350 working_directory[MagickPathExtent];
1356 *magick_windows[MaXWindows];
1410 assert(images != (Image *) NULL);
1411 assert(images->signature == MagickCoreSignature);
1412 if (images->debug != MagickFalse)
1413 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",images->filename);
1414 warning_handler=(WarningHandler) NULL;
1415 windows=XSetWindows((XWindows *) ~0);
1416 if (windows != (XWindows *) NULL)
1421 if (*working_directory == '\0')
1422 (void) CopyMagickString(working_directory,".",MagickPathExtent);
1423 status=chdir(working_directory);
1425 (void) ThrowMagickException(exception,GetMagickModule(),FileOpenError,
1426 "UnableToOpenFile","%s",working_directory);
1427 warning_handler=resource_info->display_warnings ?
1428 SetErrorHandler(XWarning) : SetErrorHandler((ErrorHandler) NULL);
1429 warning_handler=resource_info->display_warnings ?
1430 SetWarningHandler(XWarning) : SetWarningHandler((WarningHandler) NULL);
1438 Initialize window structure.
1440 for (p=images; p != (Image *) NULL; p=GetNextImageInList(p))
1442 if (p->storage_class == DirectClass)
1444 resource_info->colors=0;
1447 if (p->colors > resource_info->colors)
1448 resource_info->colors=p->colors;
1450 windows=XSetWindows(XInitializeWindows(display,resource_info));
1451 if (windows == (XWindows *) NULL)
1452 ThrowXWindowFatalException(XServerFatalError,"MemoryAllocationFailed",
1455 Initialize window id's.
1458 magick_windows[number_windows++]=(&windows->icon);
1459 magick_windows[number_windows++]=(&windows->backdrop);
1460 magick_windows[number_windows++]=(&windows->image);
1461 magick_windows[number_windows++]=(&windows->info);
1462 magick_windows[number_windows++]=(&windows->command);
1463 magick_windows[number_windows++]=(&windows->widget);
1464 magick_windows[number_windows++]=(&windows->popup);
1465 for (i=0; i < (ssize_t) number_windows; i++)
1466 magick_windows[i]->id=(Window) NULL;
1469 Initialize font info.
1471 if (windows->font_info != (XFontStruct *) NULL)
1472 (void) XFreeFont(display,windows->font_info);
1473 windows->font_info=XBestFont(display,resource_info,MagickFalse);
1474 if (windows->font_info == (XFontStruct *) NULL)
1475 ThrowXWindowFatalException(XServerFatalError,"UnableToLoadFont",
1476 resource_info->font);
1478 Initialize Standard Colormap.
1480 map_info=windows->map_info;
1481 icon_map=windows->icon_map;
1482 visual_info=windows->visual_info;
1483 icon_visual=windows->icon_visual;
1484 pixel=windows->pixel_info;
1485 icon_pixel=windows->icon_pixel;
1486 font_info=windows->font_info;
1487 icon_resources=windows->icon_resources;
1488 class_hints=windows->class_hints;
1489 manager_hints=windows->manager_hints;
1490 root_window=XRootWindow(display,visual_info->screen);
1491 coalesce_image=CoalesceImages(images,exception);
1492 if (coalesce_image == (Image *) NULL)
1493 ThrowXWindowFatalException(XServerFatalError,"MemoryAllocationFailed",
1495 images=coalesce_image;
1496 if (resource_info->map_type == (char *) NULL)
1497 if ((visual_info->klass != TrueColor) &&
1498 (visual_info->klass != DirectColor))
1504 Determine if the sequence of images has the identical colormap.
1506 for (next=images; next != (Image *) NULL; )
1508 next->alpha_trait=UndefinedPixelTrait;
1509 if ((next->storage_class == DirectClass) ||
1510 (next->colors != images->colors) ||
1511 (next->colors > (size_t) visual_info->colormap_size))
1513 for (i=0; i < (ssize_t) images->colors; i++)
1514 if (IsPixelInfoEquivalent(next->colormap+i,images->colormap+i) == MagickFalse)
1516 if (i < (ssize_t) images->colors)
1518 next=GetNextImageInList(next);
1520 if (next != (Image *) NULL)
1521 (void) RemapImages(resource_info->quantize_info,images,
1522 (Image *) NULL,exception);
1525 Sort images by increasing scene number.
1527 number_scenes=GetImageListLength(images);
1528 image_list=ImageListToArray(images,exception);
1529 if (image_list == (Image **) NULL)
1530 ThrowXWindowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed",
1532 for (scene=0; scene < (ssize_t) number_scenes; scene++)
1533 if (image_list[scene]->scene == 0)
1535 if (scene == (ssize_t) number_scenes)
1536 qsort((void *) image_list,number_scenes,sizeof(Image *),SceneCompare);
1538 Initialize Standard Colormap.
1540 nexus=NewImageList();
1541 display_image=image_list[0];
1542 for (scene=0; scene < (ssize_t) number_scenes; scene++)
1544 if ((resource_info->map_type != (char *) NULL) ||
1545 (visual_info->klass == TrueColor) ||
1546 (visual_info->klass == DirectColor))
1547 (void) SetImageType(image_list[scene],image_list[scene]->alpha_trait ==
1548 BlendPixelTrait ? TrueColorType : TrueColorAlphaType,exception);
1549 if ((display_image->columns < image_list[scene]->columns) &&
1550 (display_image->rows < image_list[scene]->rows))
1551 display_image=image_list[scene];
1553 if (display_image->debug != MagickFalse)
1555 (void) LogMagickEvent(X11Event,GetMagickModule(),
1556 "Image: %s[%.20g] %.20gx%.20g ",display_image->filename,(double)
1557 display_image->scene,(double) display_image->columns,(double)
1558 display_image->rows);
1559 if (display_image->colors != 0)
1560 (void) LogMagickEvent(X11Event,GetMagickModule(),"%.20gc ",(double)
1561 display_image->colors);
1562 (void) LogMagickEvent(X11Event,GetMagickModule(),"%s",
1563 display_image->magick);
1565 XMakeStandardColormap(display,visual_info,resource_info,display_image,
1566 map_info,pixel,exception);
1568 Initialize graphic context.
1570 windows->context.id=(Window) NULL;
1571 XGetWindowInfo(display,visual_info,map_info,pixel,font_info,
1572 resource_info,&windows->context);
1573 (void) CloneString(&class_hints->res_name,resource_info->client_name);
1574 (void) CloneString(&class_hints->res_class,resource_info->client_name);
1575 class_hints->res_class[0]=(char) toupper((int) class_hints->res_class[0]);
1576 manager_hints->flags=InputHint | StateHint;
1577 manager_hints->input=MagickFalse;
1578 manager_hints->initial_state=WithdrawnState;
1579 XMakeWindow(display,root_window,argv,argc,class_hints,manager_hints,
1581 if (display_image->debug != MagickFalse)
1582 (void) LogMagickEvent(X11Event,GetMagickModule(),
1583 "Window id: 0x%lx (context)",windows->context.id);
1584 context_values.background=pixel->background_color.pixel;
1585 context_values.font=font_info->fid;
1586 context_values.foreground=pixel->foreground_color.pixel;
1587 context_values.graphics_exposures=MagickFalse;
1588 context_mask=(MagickStatusType)
1589 (GCBackground | GCFont | GCForeground | GCGraphicsExposures);
1590 if (pixel->annotate_context != (GC) NULL)
1591 (void) XFreeGC(display,pixel->annotate_context);
1592 pixel->annotate_context=
1593 XCreateGC(display,windows->context.id,context_mask,&context_values);
1594 if (pixel->annotate_context == (GC) NULL)
1595 ThrowXWindowFatalException(XServerFatalError,"UnableToCreateGraphicContext",
1597 context_values.background=pixel->depth_color.pixel;
1598 if (pixel->widget_context != (GC) NULL)
1599 (void) XFreeGC(display,pixel->widget_context);
1600 pixel->widget_context=
1601 XCreateGC(display,windows->context.id,context_mask,&context_values);
1602 if (pixel->widget_context == (GC) NULL)
1603 ThrowXWindowFatalException(XServerFatalError,"UnableToCreateGraphicContext",
1605 context_values.background=pixel->foreground_color.pixel;
1606 context_values.foreground=pixel->background_color.pixel;
1607 context_values.plane_mask=
1608 context_values.background ^ context_values.foreground;
1609 if (pixel->highlight_context != (GC) NULL)
1610 (void) XFreeGC(display,pixel->highlight_context);
1611 pixel->highlight_context=XCreateGC(display,windows->context.id,
1612 (size_t) (context_mask | GCPlaneMask),&context_values);
1613 if (pixel->highlight_context == (GC) NULL)
1614 ThrowXWindowFatalException(XServerFatalError,"UnableToCreateGraphicContext",
1616 (void) XDestroyWindow(display,windows->context.id);
1618 Initialize icon window.
1620 XGetWindowInfo(display,icon_visual,icon_map,icon_pixel,(XFontStruct *) NULL,
1621 icon_resources,&windows->icon);
1622 windows->icon.geometry=resource_info->icon_geometry;
1623 XBestIconSize(display,&windows->icon,display_image);
1624 windows->icon.attributes.colormap=
1625 XDefaultColormap(display,icon_visual->screen);
1626 windows->icon.attributes.event_mask=ExposureMask | StructureNotifyMask;
1627 manager_hints->flags=InputHint | StateHint;
1628 manager_hints->input=MagickFalse;
1629 manager_hints->initial_state=IconicState;
1630 XMakeWindow(display,root_window,argv,argc,class_hints,manager_hints,
1632 if (display_image->debug != MagickFalse)
1633 (void) LogMagickEvent(X11Event,GetMagickModule(),"Window id: 0x%lx (icon)",
1636 Initialize graphic context for icon window.
1638 if (icon_pixel->annotate_context != (GC) NULL)
1639 (void) XFreeGC(display,icon_pixel->annotate_context);
1640 context_values.background=icon_pixel->background_color.pixel;
1641 context_values.foreground=icon_pixel->foreground_color.pixel;
1642 icon_pixel->annotate_context=XCreateGC(display,windows->icon.id,
1643 (size_t) (GCBackground | GCForeground),&context_values);
1644 if (icon_pixel->annotate_context == (GC) NULL)
1645 ThrowXWindowFatalException(XServerFatalError,"UnableToCreateGraphicContext",
1647 windows->icon.annotate_context=icon_pixel->annotate_context;
1649 Initialize Image window.
1651 XGetWindowInfo(display,visual_info,map_info,pixel,font_info,
1652 resource_info,&windows->image);
1653 windows->image.shape=MagickTrue; /* non-rectangular shape hint */
1654 if (resource_info->use_shared_memory == MagickFalse)
1655 windows->image.shared_memory=MagickFalse;
1656 if (resource_info->title != (char *) NULL)
1661 title=InterpretImageProperties(resource_info->image_info,display_image,
1662 resource_info->title,exception);
1663 (void) CopyMagickString(windows->image.name,title,MagickPathExtent);
1664 (void) CopyMagickString(windows->image.icon_name,title,MagickPathExtent);
1665 title=DestroyString(title);
1670 filename[MagickPathExtent];
1673 Window name is the base of the filename.
1675 GetPathComponent(display_image->magick_filename,TailPath,filename);
1676 (void) FormatLocaleString(windows->image.name,MagickPathExtent,
1677 "%s: %s[scene: %.20g frames: %.20g]",MagickPackageName,filename,(double)
1678 display_image->scene,(double) number_scenes);
1679 (void) CopyMagickString(windows->image.icon_name,filename,MagickPathExtent);
1681 if (resource_info->immutable != MagickFalse)
1682 windows->image.immutable=MagickTrue;
1683 windows->image.shape=MagickTrue;
1684 windows->image.geometry=resource_info->image_geometry;
1685 (void) FormatLocaleString(geometry,MagickPathExtent,"%ux%u+0+0>!",
1686 XDisplayWidth(display,visual_info->screen),
1687 XDisplayHeight(display,visual_info->screen));
1688 geometry_info.width=display_image->columns;
1689 geometry_info.height=display_image->rows;
1692 (void) ParseMetaGeometry(geometry,&geometry_info.x,&geometry_info.y,
1693 &geometry_info.width,&geometry_info.height);
1694 windows->image.width=(unsigned int) geometry_info.width;
1695 windows->image.height=(unsigned int) geometry_info.height;
1696 windows->image.attributes.event_mask=ButtonMotionMask | ButtonPressMask |
1697 ButtonReleaseMask | EnterWindowMask | ExposureMask | KeyPressMask |
1698 KeyReleaseMask | LeaveWindowMask | OwnerGrabButtonMask |
1699 PropertyChangeMask | StructureNotifyMask | SubstructureNotifyMask;
1700 XGetWindowInfo(display,visual_info,map_info,pixel,font_info,
1701 resource_info,&windows->backdrop);
1702 if ((resource_info->backdrop) || (windows->backdrop.id != (Window) NULL))
1705 Initialize backdrop window.
1707 windows->backdrop.x=0;
1708 windows->backdrop.y=0;
1709 (void) CloneString(&windows->backdrop.name,"ImageMagick Backdrop");
1710 windows->backdrop.flags=(size_t) (USSize | USPosition);
1711 windows->backdrop.width=(unsigned int)
1712 XDisplayWidth(display,visual_info->screen);
1713 windows->backdrop.height=(unsigned int)
1714 XDisplayHeight(display,visual_info->screen);
1715 windows->backdrop.border_width=0;
1716 windows->backdrop.immutable=MagickTrue;
1717 windows->backdrop.attributes.do_not_propagate_mask=ButtonPressMask |
1719 windows->backdrop.attributes.event_mask=ButtonPressMask | KeyPressMask |
1720 StructureNotifyMask;
1721 manager_hints->flags=IconWindowHint | InputHint | StateHint;
1722 manager_hints->icon_window=windows->icon.id;
1723 manager_hints->input=MagickTrue;
1724 manager_hints->initial_state=
1725 resource_info->iconic ? IconicState : NormalState;
1726 XMakeWindow(display,root_window,argv,argc,class_hints,manager_hints,
1727 &windows->backdrop);
1728 if (display_image->debug != MagickFalse)
1729 (void) LogMagickEvent(X11Event,GetMagickModule(),
1730 "Window id: 0x%lx (backdrop)",windows->backdrop.id);
1731 (void) XMapWindow(display,windows->backdrop.id);
1732 (void) XClearWindow(display,windows->backdrop.id);
1733 if (windows->image.id != (Window) NULL)
1735 (void) XDestroyWindow(display,windows->image.id);
1736 windows->image.id=(Window) NULL;
1739 Position image in the center the backdrop.
1741 windows->image.flags|=USPosition;
1742 windows->image.x=(XDisplayWidth(display,visual_info->screen)/2)-
1743 (windows->image.width/2);
1744 windows->image.y=(XDisplayHeight(display,visual_info->screen)/2)-
1745 (windows->image.height/2);
1747 manager_hints->flags=IconWindowHint | InputHint | StateHint;
1748 manager_hints->icon_window=windows->icon.id;
1749 manager_hints->input=MagickTrue;
1750 manager_hints->initial_state=
1751 resource_info->iconic ? IconicState : NormalState;
1752 if (windows->group_leader.id != (Window) NULL)
1757 manager_hints->flags|=(MagickStatusType) WindowGroupHint;
1758 manager_hints->window_group=windows->group_leader.id;
1759 (void) XSelectInput(display,windows->group_leader.id,StructureNotifyMask);
1760 if (display_image->debug != MagickFalse)
1761 (void) LogMagickEvent(X11Event,GetMagickModule(),
1762 "Window id: 0x%lx (group leader)",windows->group_leader.id);
1764 XMakeWindow(display,
1765 (Window) (resource_info->backdrop ? windows->backdrop.id : root_window),
1766 argv,argc,class_hints,manager_hints,&windows->image);
1767 (void) XChangeProperty(display,windows->image.id,windows->im_protocols,
1768 XA_STRING,8,PropModeReplace,(unsigned char *) NULL,0);
1769 if (windows->group_leader.id != (Window) NULL)
1770 (void) XSetTransientForHint(display,windows->image.id,
1771 windows->group_leader.id);
1772 if (display_image->debug != MagickFalse)
1773 (void) LogMagickEvent(X11Event,GetMagickModule(),"Window id: 0x%lx (image)",
1776 Initialize Info widget.
1778 XGetWindowInfo(display,visual_info,map_info,pixel,font_info,
1779 resource_info,&windows->info);
1780 (void) CloneString(&windows->info.name,"Info");
1781 (void) CloneString(&windows->info.icon_name,"Info");
1782 windows->info.border_width=1;
1785 windows->info.flags|=PPosition;
1786 windows->info.attributes.win_gravity=UnmapGravity;
1787 windows->info.attributes.event_mask=ButtonPressMask | ExposureMask |
1788 StructureNotifyMask;
1789 manager_hints->flags=InputHint | StateHint | WindowGroupHint;
1790 manager_hints->input=MagickFalse;
1791 manager_hints->initial_state=NormalState;
1792 manager_hints->window_group=windows->image.id;
1793 XMakeWindow(display,windows->image.id,argv,argc,class_hints,manager_hints,
1795 windows->info.highlight_stipple=XCreateBitmapFromData(display,
1796 windows->info.id,(char *) HighlightBitmap,HighlightWidth,HighlightHeight);
1797 windows->info.shadow_stipple=XCreateBitmapFromData(display,
1798 windows->info.id,(char *) ShadowBitmap,ShadowWidth,ShadowHeight);
1799 (void) XSetTransientForHint(display,windows->info.id,windows->image.id);
1800 if (windows->image.mapped)
1801 (void) XWithdrawWindow(display,windows->info.id,windows->info.screen);
1802 if (display_image->debug != MagickFalse)
1803 (void) LogMagickEvent(X11Event,GetMagickModule(),"Window id: 0x%lx (info)",
1806 Initialize Command widget.
1808 XGetWindowInfo(display,visual_info,map_info,pixel,font_info,
1809 resource_info,&windows->command);
1810 windows->command.data=MagickMenus;
1811 (void) XCommandWidget(display,windows,CommandMenu,(XEvent *) NULL);
1812 (void) FormatLocaleString(resource_name,MagickPathExtent,"%s.command",
1813 resource_info->client_name);
1814 windows->command.geometry=XGetResourceClass(resource_info->resource_database,
1815 resource_name,"geometry",(char *) NULL);
1816 (void) CloneString(&windows->command.name,MagickTitle);
1817 windows->command.border_width=0;
1818 windows->command.flags|=PPosition;
1819 windows->command.attributes.event_mask=ButtonMotionMask | ButtonPressMask |
1820 ButtonReleaseMask | EnterWindowMask | ExposureMask | LeaveWindowMask |
1821 OwnerGrabButtonMask | StructureNotifyMask;
1822 manager_hints->flags=InputHint | StateHint | WindowGroupHint;
1823 manager_hints->input=MagickTrue;
1824 manager_hints->initial_state=NormalState;
1825 manager_hints->window_group=windows->image.id;
1826 XMakeWindow(display,root_window,argv,argc,class_hints,manager_hints,
1828 windows->command.highlight_stipple=XCreateBitmapFromData(display,
1829 windows->command.id,(char *) HighlightBitmap,HighlightWidth,
1831 windows->command.shadow_stipple=XCreateBitmapFromData(display,
1832 windows->command.id,(char *) ShadowBitmap,ShadowWidth,ShadowHeight);
1833 (void) XSetTransientForHint(display,windows->command.id,windows->image.id);
1834 if (display_image->debug != MagickFalse)
1835 (void) LogMagickEvent(X11Event,GetMagickModule(),
1836 "Window id: 0x%lx (command)",windows->command.id);
1838 Initialize Widget window.
1840 XGetWindowInfo(display,visual_info,map_info,pixel,font_info,
1841 resource_info,&windows->widget);
1842 (void) FormatLocaleString(resource_name,MagickPathExtent,"%s.widget",
1843 resource_info->client_name);
1844 windows->widget.geometry=XGetResourceClass(resource_info->resource_database,
1845 resource_name,"geometry",(char *) NULL);
1846 windows->widget.border_width=0;
1847 windows->widget.flags|=PPosition;
1848 windows->widget.attributes.event_mask=ButtonMotionMask | ButtonPressMask |
1849 ButtonReleaseMask | EnterWindowMask | ExposureMask | KeyPressMask |
1850 KeyReleaseMask | LeaveWindowMask | OwnerGrabButtonMask |
1851 StructureNotifyMask;
1852 manager_hints->flags=InputHint | StateHint | WindowGroupHint;
1853 manager_hints->input=MagickTrue;
1854 manager_hints->initial_state=NormalState;
1855 manager_hints->window_group=windows->image.id;
1856 XMakeWindow(display,root_window,argv,argc,class_hints,manager_hints,
1858 windows->widget.highlight_stipple=XCreateBitmapFromData(display,
1859 windows->widget.id,(char *) HighlightBitmap,HighlightWidth,HighlightHeight);
1860 windows->widget.shadow_stipple=XCreateBitmapFromData(display,
1861 windows->widget.id,(char *) ShadowBitmap,ShadowWidth,ShadowHeight);
1862 (void) XSetTransientForHint(display,windows->widget.id,windows->image.id);
1863 if (display_image->debug != MagickFalse)
1864 (void) LogMagickEvent(X11Event,GetMagickModule(),
1865 "Window id: 0x%lx (widget)",windows->widget.id);
1867 Initialize popup window.
1869 XGetWindowInfo(display,visual_info,map_info,pixel,font_info,
1870 resource_info,&windows->popup);
1871 windows->popup.border_width=0;
1872 windows->popup.flags|=PPosition;
1873 windows->popup.attributes.event_mask=ButtonMotionMask | ButtonPressMask |
1874 ButtonReleaseMask | EnterWindowMask | ExposureMask | KeyPressMask |
1875 KeyReleaseMask | LeaveWindowMask | StructureNotifyMask;
1876 manager_hints->flags=InputHint | StateHint | WindowGroupHint;
1877 manager_hints->input=MagickTrue;
1878 manager_hints->initial_state=NormalState;
1879 manager_hints->window_group=windows->image.id;
1880 XMakeWindow(display,root_window,argv,argc,class_hints,manager_hints,
1882 windows->popup.highlight_stipple=XCreateBitmapFromData(display,
1883 windows->popup.id,(char *) HighlightBitmap,HighlightWidth,HighlightHeight);
1884 windows->popup.shadow_stipple=XCreateBitmapFromData(display,
1885 windows->popup.id,(char *) ShadowBitmap,ShadowWidth,ShadowHeight);
1886 (void) XSetTransientForHint(display,windows->popup.id,windows->image.id);
1887 if (display_image->debug != MagickFalse)
1888 (void) LogMagickEvent(X11Event,GetMagickModule(),
1889 "Window id: 0x%lx (pop up)",windows->popup.id);
1891 Set out progress and warning handlers.
1893 if (warning_handler == (WarningHandler) NULL)
1895 warning_handler=resource_info->display_warnings ?
1896 SetErrorHandler(XWarning) : SetErrorHandler((ErrorHandler) NULL);
1897 warning_handler=resource_info->display_warnings ?
1898 SetWarningHandler(XWarning) : SetWarningHandler((WarningHandler) NULL);
1901 Initialize X image structure.
1906 Initialize image pixmaps structure.
1908 window_changes.width=(int) windows->image.width;
1909 window_changes.height=(int) windows->image.height;
1910 (void) XReconfigureWMWindow(display,windows->image.id,windows->command.screen,
1911 (unsigned int) (CWWidth | CWHeight),&window_changes);
1912 windows->image.pixmaps=(Pixmap *) AcquireQuantumMemory(number_scenes,
1913 sizeof(*windows->image.pixmaps));
1914 windows->image.matte_pixmaps=(Pixmap *) AcquireQuantumMemory(number_scenes,
1915 sizeof(*windows->image.pixmaps));
1916 if ((windows->image.pixmaps == (Pixmap *) NULL) ||
1917 (windows->image.matte_pixmaps == (Pixmap *) NULL))
1918 ThrowXWindowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed",
1920 if ((windows->image.mapped == MagickFalse) ||
1921 (windows->backdrop.id != (Window) NULL))
1922 (void) XMapWindow(display,windows->image.id);
1923 XSetCursorState(display,windows,MagickTrue);
1924 for (scene=0; scene < (ssize_t) number_scenes; scene++)
1933 windows->image.pixmap=(Pixmap) NULL;
1934 windows->image.matte_pixmap=(Pixmap) NULL;
1935 if ((resource_info->map_type != (char *) NULL) ||
1936 (visual_info->klass == TrueColor) ||
1937 (visual_info->klass == DirectColor))
1938 if (image_list[scene]->storage_class == PseudoClass)
1939 XGetPixelInfo(display,visual_info,map_info,resource_info,
1940 image_list[scene],windows->image.pixel_info);
1941 columns=(unsigned int) image_list[scene]->columns;
1942 rows=(unsigned int) image_list[scene]->rows;
1943 if ((image_list[scene]->columns != columns) ||
1944 (image_list[scene]->rows != rows))
1945 ThrowXWindowFatalException(XServerFatalError,"UnableToCreateXImage",
1946 image_list[scene]->filename);
1947 status=XMakeImage(display,resource_info,&windows->image,image_list[scene],
1948 columns,rows,exception);
1949 if (status == MagickFalse)
1950 ThrowXWindowFatalException(XServerFatalError,"UnableToCreateXImage",
1952 if (image_list[scene]->debug != MagickFalse)
1954 (void) LogMagickEvent(X11Event,GetMagickModule(),
1955 "Image: [%.20g] %s %.20gx%.20g ",(double) image_list[scene]->scene,
1956 image_list[scene]->filename,(double) columns,(double) rows);
1957 if (image_list[scene]->colors != 0)
1958 (void) LogMagickEvent(X11Event,GetMagickModule(),"%.20gc ",(double)
1959 image_list[scene]->colors);
1960 (void) LogMagickEvent(X11Event,GetMagickModule(),"%s",
1961 image_list[scene]->magick);
1964 Window name is the base of the filename.
1966 if (resource_info->title != (char *) NULL)
1971 title=InterpretImageProperties(resource_info->image_info,
1972 image_list[scene],resource_info->title,exception);
1973 (void) CopyMagickString(windows->image.name,title,MagickPathExtent);
1974 title=DestroyString(title);
1978 p=image_list[scene]->magick_filename+
1979 strlen(image_list[scene]->magick_filename)-1;
1980 while ((p > image_list[scene]->magick_filename) && (*(p-1) != '/'))
1982 (void) FormatLocaleString(windows->image.name,MagickPathExtent,
1983 "%s: %s[%.20g of %.20g]",MagickPackageName,p,(double) scene+1,
1984 (double) number_scenes);
1986 status=XStringListToTextProperty(&windows->image.name,1,&window_name);
1987 if (status != Success)
1989 XSetWMName(display,windows->image.id,&window_name);
1990 (void) XFree((void *) window_name.value);
1992 windows->image.pixmaps[scene]=windows->image.pixmap;
1993 windows->image.matte_pixmaps[scene]=windows->image.matte_pixmap;
1998 event.xexpose.width=(int) image_list[scene]->columns;
1999 event.xexpose.height=(int) image_list[scene]->rows;
2000 XRefreshWindow(display,&windows->image,&event);
2001 (void) XSync(display,MagickFalse);
2004 XSetCursorState(display,windows,MagickFalse);
2005 if (windows->command.mapped)
2006 (void) XMapRaised(display,windows->command.id);
2010 nexus=NewImageList();
2014 image=image_list[0];
2015 state=(MagickStatusType) (ForwardAnimationState | RepeatAnimationState);
2016 (void) XMagickCommand(display,resource_info,windows,PlayCommand,&images,
2020 if (XEventsQueued(display,QueuedAfterFlush) == 0)
2021 if ((state & PlayAnimationState) || (state & StepAnimationState))
2027 delay=1000*image->delay/MagickMax(image->ticks_per_second,1L);
2028 XDelay(display,resource_info->delay*(delay == 0 ? 10 : delay));
2029 if (state & ForwardAnimationState)
2032 Forward animation: increment scene number.
2034 if (scene < ((ssize_t) number_scenes-1))
2039 if (iterations == (ssize_t) image_list[0]->iterations)
2044 if ((state & AutoReverseAnimationState) != 0)
2046 state&=(~ForwardAnimationState);
2051 if ((state & RepeatAnimationState) == 0)
2052 state&=(~PlayAnimationState);
2061 Reverse animation: decrement scene number.
2063 if (scene > first_scene)
2068 if (iterations == (ssize_t) image_list[0]->iterations)
2071 state&=(~RepeatAnimationState);
2073 if (state & AutoReverseAnimationState)
2075 state|=ForwardAnimationState;
2081 if ((state & RepeatAnimationState) == MagickFalse)
2082 state&=(~PlayAnimationState);
2083 scene=(ssize_t) number_scenes-1;
2087 scene=MagickMax(scene,0);
2088 image=image_list[scene];
2089 if ((image != (Image *) NULL) && (image->start_loop != 0))
2091 if ((state & StepAnimationState) ||
2092 (resource_info->title != (char *) NULL))
2095 Update window title.
2097 p=image_list[scene]->filename+
2098 strlen(image_list[scene]->filename)-1;
2099 while ((p > image_list[scene]->filename) && (*(p-1) != '/'))
2101 (void) FormatLocaleString(windows->image.name,MagickPathExtent,
2102 "%s: %s[%.20g of %.20g]",MagickPackageName,p,(double)
2103 scene+1,(double) number_scenes);
2104 if (resource_info->title != (char *) NULL)
2109 title=InterpretImageProperties(resource_info->image_info,
2110 image,resource_info->title,exception);
2111 (void) CopyMagickString(windows->image.name,title,
2113 title=DestroyString(title);
2115 status=XStringListToTextProperty(&windows->image.name,1,
2117 if (status != Success)
2119 XSetWMName(display,windows->image.id,&window_name);
2120 (void) XFree((void *) window_name.value);
2124 Copy X pixmap to Image window.
2126 XGetPixelInfo(display,visual_info,map_info,resource_info,
2127 image_list[scene],windows->image.pixel_info);
2128 windows->image.ximage->width=(int) image->columns;
2129 windows->image.ximage->height=(int) image->rows;
2130 windows->image.pixmap=windows->image.pixmaps[scene];
2131 windows->image.matte_pixmap=windows->image.matte_pixmaps[scene];
2134 event.xexpose.width=(int) image->columns;
2135 event.xexpose.height=(int) image->rows;
2136 if ((state & ExitState) == 0)
2138 XRefreshWindow(display,&windows->image,&event);
2139 (void) XSync(display,MagickFalse);
2141 state&=(~StepAnimationState);
2142 if (pause != MagickFalse)
2143 for (i=0; i < (ssize_t) resource_info->pause; i++)
2148 status=XCheckTypedWindowEvent(display,windows->image.id,KeyPress,
2155 length=XLookupString((XKeyEvent *) &event.xkey,command,(int)
2156 sizeof(command),&key_symbol,(XComposeStatus *) NULL);
2157 *(command+length)='\0';
2158 if ((key_symbol == XK_q) || (key_symbol == XK_Escape))
2160 XClientMessage(display,windows->image.id,
2161 windows->im_protocols,windows->im_exit,CurrentTime);
2170 Handle a window event.
2172 timestamp=time((time_t *) NULL);
2173 (void) XNextEvent(display,&event);
2174 if (windows->image.stasis == MagickFalse)
2175 windows->image.stasis=(time((time_t *) NULL)-timestamp) > 0 ?
2176 MagickTrue : MagickFalse;
2177 if (event.xany.window == windows->command.id)
2183 Select a command from the Command widget.
2185 id=XCommandWidget(display,windows,CommandMenu,&event);
2188 (void) CopyMagickString(command,CommandMenu[id],MagickPathExtent);
2189 command_type=CommandMenus[id];
2190 if (id < MagickMenus)
2196 Select a command from a pop-up menu.
2198 entry=XMenuWidget(display,windows,CommandMenu[id],Menus[id],
2202 (void) CopyMagickString(command,Menus[id][entry],MagickPathExtent);
2203 command_type=Commands[id][entry];
2205 if (command_type != NullCommand)
2206 nexus=XMagickCommand(display,resource_info,windows,
2207 command_type,&image,&state,exception);
2214 if (display_image->debug != MagickFalse)
2215 (void) LogMagickEvent(X11Event,GetMagickModule(),
2216 "Button Press: 0x%lx %u +%d+%d",event.xbutton.window,
2217 event.xbutton.button,event.xbutton.x,event.xbutton.y);
2218 if ((event.xbutton.button == Button3) &&
2219 (event.xbutton.state & Mod1Mask))
2222 Convert Alt-Button3 to Button2.
2224 event.xbutton.button=Button2;
2225 event.xbutton.state&=(~Mod1Mask);
2227 if (event.xbutton.window == windows->backdrop.id)
2229 (void) XSetInputFocus(display,event.xbutton.window,RevertToParent,
2230 event.xbutton.time);
2233 if (event.xbutton.window == windows->image.id)
2235 if (resource_info->immutable != MagickFalse)
2241 Map/unmap Command widget.
2243 if (windows->command.mapped)
2244 (void) XWithdrawWindow(display,windows->command.id,
2245 windows->command.screen);
2248 (void) XCommandWidget(display,windows,CommandMenu,
2250 (void) XMapRaised(display,windows->command.id);
2257 if (display_image->debug != MagickFalse)
2258 (void) LogMagickEvent(X11Event,GetMagickModule(),
2259 "Button Release: 0x%lx %u +%d+%d",event.xbutton.window,
2260 event.xbutton.button,event.xbutton.x,event.xbutton.y);
2265 if (display_image->debug != MagickFalse)
2266 (void) LogMagickEvent(X11Event,GetMagickModule(),
2267 "Client Message: 0x%lx 0x%lx %d 0x%lx",(unsigned long)
2268 event.xclient.window,(unsigned long) event.xclient.message_type,
2269 event.xclient.format,(unsigned long) event.xclient.data.l[0]);
2270 if (event.xclient.message_type == windows->im_protocols)
2272 if (*event.xclient.data.l == (long) windows->im_update_colormap)
2275 Update graphic context and window colormap.
2277 for (i=0; i < (ssize_t) number_windows; i++)
2279 if (magick_windows[i]->id == windows->icon.id)
2281 context_values.background=pixel->background_color.pixel;
2282 context_values.foreground=pixel->foreground_color.pixel;
2283 (void) XChangeGC(display,magick_windows[i]->annotate_context,
2284 context_mask,&context_values);
2285 (void) XChangeGC(display,magick_windows[i]->widget_context,
2286 context_mask,&context_values);
2287 context_values.background=pixel->foreground_color.pixel;
2288 context_values.foreground=pixel->background_color.pixel;
2289 context_values.plane_mask=
2290 context_values.background ^ context_values.foreground;
2291 (void) XChangeGC(display,magick_windows[i]->highlight_context,
2292 (size_t) (context_mask | GCPlaneMask),
2294 magick_windows[i]->attributes.background_pixel=
2295 pixel->background_color.pixel;
2296 magick_windows[i]->attributes.border_pixel=
2297 pixel->border_color.pixel;
2298 magick_windows[i]->attributes.colormap=map_info->colormap;
2299 (void) XChangeWindowAttributes(display,magick_windows[i]->id,
2300 (unsigned long) magick_windows[i]->mask,
2301 &magick_windows[i]->attributes);
2303 if (windows->backdrop.id != (Window) NULL)
2304 (void) XInstallColormap(display,map_info->colormap);
2307 if (*event.xclient.data.l == (long) windows->im_exit)
2314 if (event.xclient.message_type == windows->dnd_protocols)
2332 Display image named by the Drag-and-Drop selection.
2334 if ((*event.xclient.data.l != 2) && (*event.xclient.data.l != 128))
2336 selection=XInternAtom(display,"DndSelection",MagickFalse);
2337 status=XGetWindowProperty(display,root_window,selection,0L,2047L,
2338 MagickFalse,(Atom) AnyPropertyType,&type,&format,&length,&after,
2340 if ((status != Success) || (length == 0))
2342 if (*event.xclient.data.l == 2)
2347 (void) CopyMagickString(resource_info->image_info->filename,
2348 (char *) data,MagickPathExtent);
2355 if (LocaleNCompare((char *) data,"file:",5) != 0)
2357 (void) XFree((void *) data);
2360 (void) CopyMagickString(resource_info->image_info->filename,
2361 ((char *) data)+5,MagickPathExtent);
2363 nexus=ReadImage(resource_info->image_info,exception);
2364 CatchException(exception);
2365 if (nexus != (Image *) NULL)
2367 (void) XFree((void *) data);
2371 If client window delete message, exit.
2373 if (event.xclient.message_type != windows->wm_protocols)
2375 if (*event.xclient.data.l == (long) windows->wm_take_focus)
2377 (void) XSetInputFocus(display,event.xclient.window,RevertToParent,
2378 (Time) event.xclient.data.l[1]);
2381 if (*event.xclient.data.l != (long) windows->wm_delete_window)
2383 (void) XWithdrawWindow(display,event.xclient.window,
2384 visual_info->screen);
2385 if (event.xclient.window == windows->image.id)
2392 case ConfigureNotify:
2394 if (display_image->debug != MagickFalse)
2395 (void) LogMagickEvent(X11Event,GetMagickModule(),
2396 "Configure Notify: 0x%lx %dx%d+%d+%d %d",event.xconfigure.window,
2397 event.xconfigure.width,event.xconfigure.height,event.xconfigure.x,
2398 event.xconfigure.y,event.xconfigure.send_event);
2399 if (event.xconfigure.window == windows->image.id)
2401 if (event.xconfigure.send_event != 0)
2407 Position the transient windows relative of the Image window.
2409 if (windows->command.geometry == (char *) NULL)
2410 if (windows->command.mapped == MagickFalse)
2413 event.xconfigure.x-windows->command.width-25;
2414 windows->command.y=event.xconfigure.y;
2415 XConstrainWindowPosition(display,&windows->command);
2416 window_changes.x=windows->command.x;
2417 window_changes.y=windows->command.y;
2418 (void) XReconfigureWMWindow(display,windows->command.id,
2419 windows->command.screen,(unsigned int) (CWX | CWY),
2422 if (windows->widget.geometry == (char *) NULL)
2423 if (windows->widget.mapped == MagickFalse)
2426 event.xconfigure.x+event.xconfigure.width/10;
2428 event.xconfigure.y+event.xconfigure.height/10;
2429 XConstrainWindowPosition(display,&windows->widget);
2430 window_changes.x=windows->widget.x;
2431 window_changes.y=windows->widget.y;
2432 (void) XReconfigureWMWindow(display,windows->widget.id,
2433 windows->widget.screen,(unsigned int) (CWX | CWY),
2438 Image window has a new configuration.
2440 windows->image.width=(unsigned int) event.xconfigure.width;
2441 windows->image.height=(unsigned int) event.xconfigure.height;
2444 if (event.xconfigure.window == windows->icon.id)
2447 Icon window has a new configuration.
2449 windows->icon.width=(unsigned int) event.xconfigure.width;
2450 windows->icon.height=(unsigned int) event.xconfigure.height;
2458 Group leader has exited.
2460 if (display_image->debug != MagickFalse)
2461 (void) LogMagickEvent(X11Event,GetMagickModule(),
2462 "Destroy Notify: 0x%lx",event.xdestroywindow.window);
2463 if (event.xdestroywindow.window == windows->group_leader.id)
2473 Selectively install colormap.
2475 if (map_info->colormap != XDefaultColormap(display,visual_info->screen))
2476 if (event.xcrossing.mode != NotifyUngrab)
2477 XInstallColormap(display,map_info->colormap);
2482 if (display_image->debug != MagickFalse)
2483 (void) LogMagickEvent(X11Event,GetMagickModule(),
2484 "Expose: 0x%lx %dx%d+%d+%d",event.xexpose.window,
2485 event.xexpose.width,event.xexpose.height,event.xexpose.x,
2488 Repaint windows that are now exposed.
2490 if (event.xexpose.window == windows->image.id)
2492 windows->image.pixmap=windows->image.pixmaps[scene];
2493 windows->image.matte_pixmap=windows->image.matte_pixmaps[scene];
2494 XRefreshWindow(display,&windows->image,&event);
2497 if (event.xexpose.window == windows->icon.id)
2498 if (event.xexpose.count == 0)
2500 XRefreshWindow(display,&windows->icon,&event);
2511 Respond to a user key press.
2513 length=XLookupString((XKeyEvent *) &event.xkey,command,(int)
2514 sizeof(command),&key_symbol,(XComposeStatus *) NULL);
2515 *(command+length)='\0';
2516 if (display_image->debug != MagickFalse)
2517 (void) LogMagickEvent(X11Event,GetMagickModule(),
2518 "Key press: 0x%lx (%c)",(unsigned long) key_symbol,*command);
2519 command_type=NullCommand;
2524 if ((event.xkey.state & ControlMask) == MagickFalse)
2526 command_type=OpenCommand;
2531 command_type=StepBackwardCommand;
2536 command_type=StepForwardCommand;
2541 command_type=FasterCommand;
2546 command_type=SlowerCommand;
2551 command_type=HelpCommand;
2556 command_type=BrowseDocumentationCommand;
2561 command_type=InfoCommand;
2567 command_type=QuitCommand;
2573 if (command_type != NullCommand)
2574 nexus=XMagickCommand(display,resource_info,windows,
2575 command_type,&image,&state,exception);
2581 Respond to a user key release.
2583 (void) XLookupString((XKeyEvent *) &event.xkey,command,(int)
2584 sizeof(command),&key_symbol,(XComposeStatus *) NULL);
2585 if (display_image->debug != MagickFalse)
2586 (void) LogMagickEvent(X11Event,GetMagickModule(),
2587 "Key release: 0x%lx (%c)",(unsigned long) key_symbol,*command);
2593 Selectively uninstall colormap.
2595 if (map_info->colormap != XDefaultColormap(display,visual_info->screen))
2596 if (event.xcrossing.mode != NotifyUngrab)
2597 XUninstallColormap(display,map_info->colormap);
2602 if (display_image->debug != MagickFalse)
2603 (void) LogMagickEvent(X11Event,GetMagickModule(),"Map Notify: 0x%lx",
2605 if (event.xmap.window == windows->backdrop.id)
2607 (void) XSetInputFocus(display,event.xmap.window,RevertToParent,
2609 windows->backdrop.mapped=MagickTrue;
2612 if (event.xmap.window == windows->image.id)
2614 if (windows->backdrop.id != (Window) NULL)
2615 (void) XInstallColormap(display,map_info->colormap);
2616 if (LocaleCompare(image_list[0]->magick,"LOGO") == 0)
2618 if (LocaleCompare(display_image->filename,"LOGO") == 0)
2619 nexus=XMagickCommand(display,resource_info,windows,
2620 OpenCommand,&image,&state,exception);
2624 windows->image.mapped=MagickTrue;
2627 if (event.xmap.window == windows->info.id)
2629 windows->info.mapped=MagickTrue;
2632 if (event.xmap.window == windows->icon.id)
2635 Create an icon image.
2637 XMakeStandardColormap(display,icon_visual,icon_resources,
2638 display_image,icon_map,icon_pixel,exception);
2639 (void) XMakeImage(display,icon_resources,&windows->icon,
2640 display_image,windows->icon.width,windows->icon.height,
2642 (void) XSetWindowBackgroundPixmap(display,windows->icon.id,
2643 windows->icon.pixmap);
2644 (void) XClearWindow(display,windows->icon.id);
2645 (void) XWithdrawWindow(display,windows->info.id,
2646 windows->info.screen);
2647 windows->icon.mapped=MagickTrue;
2650 if (event.xmap.window == windows->command.id)
2652 windows->command.mapped=MagickTrue;
2655 if (event.xmap.window == windows->popup.id)
2657 windows->popup.mapped=MagickTrue;
2660 if (event.xmap.window == windows->widget.id)
2662 windows->widget.mapped=MagickTrue;
2669 (void) XRefreshKeyboardMapping(&event.xmapping);
2674 case PropertyNotify:
2690 if (display_image->debug != MagickFalse)
2691 (void) LogMagickEvent(X11Event,GetMagickModule(),
2692 "Property Notify: 0x%lx 0x%lx %d",(unsigned long)
2693 event.xproperty.window,(unsigned long) event.xproperty.atom,
2694 event.xproperty.state);
2695 if (event.xproperty.atom != windows->im_remote_command)
2698 Display image named by the remote command protocol.
2700 status=XGetWindowProperty(display,event.xproperty.window,
2701 event.xproperty.atom,0L,(long) MagickPathExtent,MagickFalse,(Atom)
2702 AnyPropertyType,&type,&format,&length,&after,&data);
2703 if ((status != Success) || (length == 0))
2705 (void) CopyMagickString(resource_info->image_info->filename,
2706 (char *) data,MagickPathExtent);
2707 nexus=ReadImage(resource_info->image_info,exception);
2708 CatchException(exception);
2709 if (nexus != (Image *) NULL)
2711 (void) XFree((void *) data);
2714 case ReparentNotify:
2716 if (display_image->debug != MagickFalse)
2717 (void) LogMagickEvent(X11Event,GetMagickModule(),
2718 "Reparent Notify: 0x%lx=>0x%lx",event.xreparent.parent,
2719 event.xreparent.window);
2724 if (display_image->debug != MagickFalse)
2725 (void) LogMagickEvent(X11Event,GetMagickModule(),
2726 "Unmap Notify: 0x%lx",event.xunmap.window);
2727 if (event.xunmap.window == windows->backdrop.id)
2729 windows->backdrop.mapped=MagickFalse;
2732 if (event.xunmap.window == windows->image.id)
2734 windows->image.mapped=MagickFalse;
2737 if (event.xunmap.window == windows->info.id)
2739 windows->info.mapped=MagickFalse;
2742 if (event.xunmap.window == windows->icon.id)
2744 if (map_info->colormap == icon_map->colormap)
2745 XConfigureImageColormap(display,resource_info,windows,
2746 display_image,exception);
2747 (void) XFreeStandardColormap(display,icon_visual,icon_map,
2749 windows->icon.mapped=MagickFalse;
2752 if (event.xunmap.window == windows->command.id)
2754 windows->command.mapped=MagickFalse;
2757 if (event.xunmap.window == windows->popup.id)
2759 if (windows->backdrop.id != (Window) NULL)
2760 (void) XSetInputFocus(display,windows->image.id,RevertToParent,
2762 windows->popup.mapped=MagickFalse;
2765 if (event.xunmap.window == windows->widget.id)
2767 if (windows->backdrop.id != (Window) NULL)
2768 (void) XSetInputFocus(display,windows->image.id,RevertToParent,
2770 windows->widget.mapped=MagickFalse;
2777 if (display_image->debug != MagickFalse)
2778 (void) LogMagickEvent(X11Event,GetMagickModule(),"Event type: %d",
2784 while (!(state & ExitState));
2785 image_list=(Image **) RelinquishMagickMemory(image_list);
2786 images=DestroyImageList(images);
2787 if ((windows->visual_info->klass == GrayScale) ||
2788 (windows->visual_info->klass == PseudoColor) ||
2789 (windows->visual_info->klass == DirectColor))
2794 if (windows->info.mapped)
2795 (void) XWithdrawWindow(display,windows->info.id,windows->info.screen);
2796 if (windows->command.mapped)
2797 (void) XWithdrawWindow(display,windows->command.id,
2798 windows->command.screen);
2800 if (resource_info->backdrop == MagickFalse)
2801 if (windows->backdrop.mapped)
2803 (void) XWithdrawWindow(display,windows->backdrop.id,\
2804 windows->backdrop.screen);
2805 (void) XDestroyWindow(display,windows->backdrop.id);
2806 windows->backdrop.id=(Window) NULL;
2807 (void) XWithdrawWindow(display,windows->image.id,windows->image.screen);
2808 (void) XDestroyWindow(display,windows->image.id);
2809 windows->image.id=(Window) NULL;
2811 XSetCursorState(display,windows,MagickTrue);
2812 XCheckRefreshWindows(display,windows);
2813 for (scene=1; scene < (ssize_t) number_scenes; scene++)
2815 if (windows->image.pixmaps[scene] != (Pixmap) NULL)
2816 (void) XFreePixmap(display,windows->image.pixmaps[scene]);
2817 windows->image.pixmaps[scene]=(Pixmap) NULL;
2818 if (windows->image.matte_pixmaps[scene] != (Pixmap) NULL)
2819 (void) XFreePixmap(display,windows->image.matte_pixmaps[scene]);
2820 windows->image.matte_pixmaps[scene]=(Pixmap) NULL;
2822 XSetCursorState(display,windows,MagickFalse);
2823 windows->image.pixmaps=(Pixmap *)
2824 RelinquishMagickMemory(windows->image.pixmaps);
2825 windows->image.matte_pixmaps=(Pixmap *)
2826 RelinquishMagickMemory(windows->image.matte_pixmaps);
2827 if (nexus == (Image *) NULL)
2832 if (windows->image.mapped != MagickFalse)
2833 (void) XWithdrawWindow(display,windows->image.id,windows->image.screen);
2834 XDelay(display,SuspendTime);
2835 (void) XFreeStandardColormap(display,icon_visual,icon_map,icon_pixel);
2836 if (resource_info->map_type == (char *) NULL)
2837 (void) XFreeStandardColormap(display,visual_info,map_info,pixel);
2838 DestroyXResources();
2840 (void) XSync(display,MagickFalse);
2842 Restore our progress monitor and warning handlers.
2844 (void) SetErrorHandler(warning_handler);
2845 (void) SetWarningHandler(warning_handler);
2847 Change to home directory.
2849 directory=getcwd(working_directory,MagickPathExtent);
2851 if (*resource_info->home_directory == '\0')
2852 (void) CopyMagickString(resource_info->home_directory,".",MagickPathExtent);
2853 status=chdir(resource_info->home_directory);
2855 (void) ThrowMagickException(exception,GetMagickModule(),FileOpenError,
2856 "UnableToOpenFile","%s",resource_info->home_directory);
2861 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2865 + X S a v e I m a g e %
2869 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2871 % XSaveImage() saves an image to a file.
2873 % The format of the XSaveImage method is:
2875 % MagickBooleanType XSaveImage(Display *display,
2876 % XResourceInfo *resource_info,XWindows *windows,Image *image,
2877 % ExceptionInfo *exception)
2879 % A description of each parameter follows:
2881 % o status: Method XSaveImage return True if the image is
2882 % written. False is returned is there is a memory shortage or if the
2883 % image fails to write.
2885 % o display: Specifies a connection to an X server; returned from
2888 % o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
2890 % o windows: Specifies a pointer to a XWindows structure.
2892 % o image: the image.
2895 static MagickBooleanType XSaveImage(Display *display,
2896 XResourceInfo *resource_info,XWindows *windows,Image *image,
2897 ExceptionInfo *exception)
2900 filename[MagickPathExtent];
2909 Request file name from user.
2911 if (resource_info->write_filename != (char *) NULL)
2912 (void) CopyMagickString(filename,resource_info->write_filename,
2917 path[MagickPathExtent];
2922 GetPathComponent(image->filename,HeadPath,path);
2923 GetPathComponent(image->filename,TailPath,filename);
2925 (void) CopyMagickString(path,".",MagickPathExtent);
2928 (void) ThrowMagickException(exception,GetMagickModule(),FileOpenError,
2929 "UnableToOpenFile","%s",path);
2931 XFileBrowserWidget(display,windows,"Save",filename);
2932 if (*filename == '\0')
2934 if (IsPathAccessible(filename) != MagickFalse)
2940 File exists-- seek user's permission before overwriting.
2942 status=XConfirmWidget(display,windows,"Overwrite",filename);
2946 image_info=CloneImageInfo(resource_info->image_info);
2947 (void) CopyMagickString(image_info->filename,filename,MagickPathExtent);
2948 (void) SetImageInfo(image_info,1,exception);
2949 if ((LocaleCompare(image_info->magick,"JPEG") == 0) ||
2950 (LocaleCompare(image_info->magick,"JPG") == 0))
2953 quality[MagickPathExtent];
2959 Request JPEG quality from user.
2961 (void) FormatLocaleString(quality,MagickPathExtent,"%.20g",(double)
2962 image_info->quality);
2963 status=XDialogWidget(display,windows,"Save","Enter JPEG quality:",
2965 if (*quality == '\0')
2967 image->quality=StringToUnsignedLong(quality);
2968 image_info->interlace=status != MagickFalse ? NoInterlace :
2971 if ((LocaleCompare(image_info->magick,"EPS") == 0) ||
2972 (LocaleCompare(image_info->magick,"PDF") == 0) ||
2973 (LocaleCompare(image_info->magick,"PS") == 0) ||
2974 (LocaleCompare(image_info->magick,"PS2") == 0))
2977 geometry[MagickPathExtent];
2980 Request page geometry from user.
2982 (void) CopyMagickString(geometry,PSPageGeometry,MagickPathExtent);
2983 if (LocaleCompare(image_info->magick,"PDF") == 0)
2984 (void) CopyMagickString(geometry,PSPageGeometry,MagickPathExtent);
2985 if (image_info->page != (char *) NULL)
2986 (void) CopyMagickString(geometry,image_info->page,MagickPathExtent);
2987 XListBrowserWidget(display,windows,&windows->widget,PageSizes,"Select",
2988 "Select page geometry:",geometry);
2989 if (*geometry != '\0')
2990 image_info->page=GetPageGeometry(geometry);
2995 image=GetFirstImageInList(image);
2996 status=WriteImages(image_info,image,filename,exception);
2997 if (status != MagickFalse)
2998 image->taint=MagickFalse;
2999 image_info=DestroyImageInfo(image_info);
3000 XSetCursorState(display,windows,MagickFalse);
3001 return(status != 0 ? MagickTrue : MagickFalse);
3006 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3010 + A n i m a t e I m a g e s %
3014 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3016 % AnimateImages() repeatedly displays an image sequence to any X window
3017 % screen. It returns a value other than 0 if successful. Check the
3018 % exception member of image to determine the reason for any failure.
3020 % The format of the AnimateImages method is:
3022 % MagickBooleanType AnimateImages(const ImageInfo *image_info,
3025 % A description of each parameter follows:
3027 % o image_info: the image info.
3029 % o image: the image.
3031 % o exception: return any errors or warnings in this structure.
3034 MagickExport MagickBooleanType AnimateImages(const ImageInfo *image_info,
3035 Image *image,ExceptionInfo *exception)
3037 assert(image_info != (const ImageInfo *) NULL);
3038 assert(image_info->signature == MagickCoreSignature);
3040 assert(image != (Image *) NULL);
3041 assert(image->signature == MagickCoreSignature);
3042 if (image->debug != MagickFalse)
3043 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
3044 (void) ThrowMagickException(exception,GetMagickModule(),MissingDelegateError,
3045 "DelegateLibrarySupportNotBuiltIn","'%s' (X11)",image->filename);
3046 return(MagickFalse);