MagickCore  7.0.8
Convert, Edit, Or Compose Bitmap Images
animate.c
Go to the documentation of this file.
1 /*
2 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3 % %
4 % %
5 % %
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 %
11 % %
12 % %
13 % Methods to Interactively Animate an Image Sequence %
14 % %
15 % Software Design %
16 % Cristy %
17 % July 1992 %
18 % %
19 % %
20 % Copyright 1999-2018 ImageMagick Studio LLC, a non-profit organization %
21 % dedicated to making software imaging solutions freely available. %
22 % %
23 % You may not use this file except in compliance with the License. You may %
24 % obtain a copy of the License at %
25 % %
26 % https://www.imagemagick.org/script/license.php %
27 % %
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. %
33 % %
34 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
35 %
36 %
37 */
38 
39 /*
40  Include declarations.
41 */
42 #include "MagickCore/studio.h"
43 #include "MagickCore/animate.h"
45 #include "MagickCore/attribute.h"
46 #include "MagickCore/client.h"
47 #include "MagickCore/color.h"
49 #include "MagickCore/colorspace.h"
51 #include "MagickCore/constitute.h"
52 #include "MagickCore/delegate.h"
53 #include "MagickCore/exception.h"
55 #include "MagickCore/geometry.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"
64 #include "MagickCore/option.h"
66 #include "MagickCore/property.h"
67 #include "MagickCore/resource_.h"
68 #include "MagickCore/string_.h"
70 #include "MagickCore/transform.h"
71 #include "MagickCore/utility.h"
73 #include "MagickCore/version.h"
74 #include "MagickCore/widget.h"
76 #include "MagickCore/xwindow.h"
78 
79 #if defined(MAGICKCORE_X11_DELEGATE)
80 /*
81  Animate state declarations.
82 */
83 #define AutoReverseAnimationState 0x0004
84 #define ForwardAnimationState 0x0008
85 #define HighlightState 0x0010
86 #define PlayAnimationState 0x0020
87 #define RepeatAnimationState 0x0040
88 #define StepAnimationState 0x0080
89 
90 /*
91  Static declarations.
92 */
93 static const char
94  *AnimateHelp[]=
95  {
96  "BUTTONS",
97  "",
98  " Press any button to map or unmap the Command widget.",
99  "",
100  "COMMAND WIDGET",
101  " The Command widget lists a number of sub-menus and commands.",
102  " They are",
103  "",
104  " Animate",
105  " Open...",
106  " Save...",
107  " Play",
108  " Step",
109  " Repeat",
110  " Auto Reverse",
111  " Speed",
112  " Slower",
113  " Faster",
114  " Direction",
115  " Forward",
116  " Reverse",
117  " Help",
118  " Overview",
119  " Browse Documentation",
120  " About Animate",
121  " Image Info",
122  " Quit",
123  "",
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.",
131  "",
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:",
136  "",
137  " Ctl+O Press to open an image from a file.",
138  "",
139  " space Press to display the next image in the sequence.",
140  "",
141  " < Press to speed-up the display of the images. Refer to",
142  " -delay for more information.",
143  "",
144  " > Press to slow the display of the images. Refer to",
145  " -delay for more information.",
146  "",
147  " F1 Press to display helpful information about animate(1).",
148  "",
149  " Find Press to browse documentation about ImageMagick.",
150  "",
151  " ? Press to display information about the image. Press",
152  " any key or button to erase the information.",
153  "",
154  " This information is printed: image name; image size;",
155  " and the total number of unique colors in the image.",
156  "",
157  " Ctl-q Press to discard all images and exit program.",
158  (char *) NULL
159  };
160 
161 /*
162  Constant declarations.
163 */
164 static const char
165  *PageSizes[]=
166  {
167  "Letter",
168  "Tabloid",
169  "Ledger",
170  "Legal",
171  "Statement",
172  "Executive",
173  "A3",
174  "A4",
175  "A5",
176  "B4",
177  "B5",
178  "Folio",
179  "Quarto",
180  "10x14",
181  (char *) NULL
182  };
183 
184 static const unsigned char
185  HighlightBitmap[8] =
186  {
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,
194  (unsigned char) 0x55
195  },
196  ShadowBitmap[8] =
197  {
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,
205  (unsigned char) 0x00
206  };
207 
208 /*
209  Enumeration declarations.
210 */
211 typedef enum
212 {
213  OpenCommand,
214  SaveCommand,
215  PlayCommand,
216  StepCommand,
217  RepeatCommand,
218  AutoReverseCommand,
219  SlowerCommand,
220  FasterCommand,
221  ForwardCommand,
222  ReverseCommand,
223  HelpCommand,
224  BrowseDocumentationCommand,
225  VersionCommand,
226  InfoCommand,
227  QuitCommand,
228  StepBackwardCommand,
229  StepForwardCommand,
230  NullCommand
231 } CommandType;
232 
233 /*
234  Stipples.
235 */
236 #define HighlightWidth 8
237 #define HighlightHeight 8
238 #define ShadowWidth 8
239 #define ShadowHeight 8
240 
241 /*
242  Forward declarations.
243 */
244 static Image
245  *XMagickCommand(Display *,XResourceInfo *,XWindows *,const CommandType,
247 
248 static MagickBooleanType
249  XSaveImage(Display *,XResourceInfo *,XWindows *,Image *,ExceptionInfo *);
250 
251 /*
252 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
253 % %
254 % %
255 % %
256 % A n i m a t e I m a g e s %
257 % %
258 % %
259 % %
260 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
261 %
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.
265 %
266 % The format of the AnimateImages method is:
267 %
268 % MagickBooleanType AnimateImages(const ImageInfo *image_info,
269 % Image *images,ExceptionInfo *exception)
270 %
271 % A description of each parameter follows:
272 %
273 % o image_info: the image info.
274 %
275 % o image: the image.
276 %
277 % o exception: return any errors or warnings in this structure.
278 %
279 */
281  Image *images,ExceptionInfo *exception)
282 {
283  char
284  *argv[1];
285 
286  Display
287  *display;
288 
290  status;
291 
292  XrmDatabase
293  resource_database;
294 
295  XResourceInfo
297 
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)
306  {
308  "UnableToOpenXServer","`%s'",XDisplayName(image_info->server_name));
309  return(MagickFalse);
310  }
311  if (exception->severity != UndefinedException)
312  CatchException(exception);
313  (void) XSetErrorHandler(XError);
314  resource_database=XGetResourceDatabase(display,GetClientName());
315  (void) memset(&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);
329 }
330 
331 /*
332 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
333 % %
334 % %
335 % %
336 + X M a g i c k C o m m a n d %
337 % %
338 % %
339 % %
340 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
341 %
342 % XMagickCommand() makes a transform to the image or Image window as specified
343 % by a user menu button or keyboard command.
344 %
345 % The format of the XMagickCommand method is:
346 %
347 % Image *XMagickCommand(Display *display,XResourceInfo *resource_info,
348 % XWindows *windows,const CommandType command_type,Image **image,
349 % MagickStatusType *state,ExceptionInfo *exception)
350 %
351 % A description of each parameter follows:
352 %
353 % o display: Specifies a connection to an X server; returned from
354 % XOpenDisplay.
355 %
356 % o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
357 %
358 % o windows: Specifies a pointer to a XWindows structure.
359 %
360 % o image: the image; XMagickCommand
361 % may transform the image and return a new image pointer.
362 %
363 % o state: Specifies a MagickStatusType; XMagickCommand may return a
364 % modified state.
365 %
366 % o exception: return any errors or warnings in this structure.
367 %
368 %
369 */
370 static Image *XMagickCommand(Display *display,XResourceInfo *resource_info,
371  XWindows *windows,const CommandType command_type,Image **image,
372  MagickStatusType *state,ExceptionInfo *exception)
373 {
374  Image
375  *nexus;
376 
378  proceed;
379 
381  status;
382 
383  XTextProperty
384  window_name;
385 
386  /*
387  Process user command.
388  */
389  nexus=NewImageList();
390  switch (command_type)
391  {
392  case OpenCommand:
393  {
394  char
395  **filelist;
396 
397  Image
398  *images,
399  *next;
400 
401  ImageInfo
402  *read_info;
403 
404  int
405  number_files;
406 
407  register int
408  i;
409 
410  static char
411  filenames[MagickPathExtent] = "*";
412 
413  if (resource_info->immutable != MagickFalse)
414  break;
415  /*
416  Request file name from user.
417  */
418  XFileBrowserWidget(display,windows,"Animate",filenames);
419  if (*filenames == '\0')
420  return((Image *) NULL);
421  /*
422  Expand the filenames.
423  */
424  filelist=(char **) AcquireMagickMemory(sizeof(char *));
425  if (filelist == (char **) NULL)
426  {
427  ThrowXWindowException(ResourceLimitError,"MemoryAllocationFailed",
428  filenames);
429  return((Image *) NULL);
430  }
431  number_files=1;
432  filelist[0]=filenames;
433  status=ExpandFilenames(&number_files,&filelist);
434  if ((status == MagickFalse) || (number_files == 0))
435  {
436  for (i=0; i < number_files; i++)
437  filelist[i]=DestroyString(filelist[i]);
438  filelist=(char **) RelinquishMagickMemory(filelist);
439  if (number_files == 0)
440  {
441  ThrowXWindowException(ImageError,"NoImagesWereLoaded",filenames);
442  return((Image *) NULL);
443  }
444  ThrowXWindowException(ResourceLimitError,"MemoryAllocationFailed",
445  filenames);
446  return((Image *) NULL);
447  }
448  read_info=CloneImageInfo(resource_info->image_info);
449  images=NewImageList();
450  XSetCursorState(display,windows,MagickTrue);
451  XCheckRefreshWindows(display,windows);
452  for (i=0; i < number_files; i++)
453  {
454  (void) CopyMagickString(read_info->filename,filelist[i],MagickPathExtent);
455  filelist[i]=DestroyString(filelist[i]);
456  *read_info->magick='\0';
457  next=ReadImage(read_info,exception);
458  CatchException(exception);
459  if (next != (Image *) NULL)
460  AppendImageToList(&images,next);
461  if (number_files <= 5)
462  continue;
463  proceed=SetImageProgress(images,LoadImageTag,i,(MagickSizeType)
464  number_files);
465  if (proceed == MagickFalse)
466  break;
467  }
468  filelist=(char **) RelinquishMagickMemory(filelist);
469  read_info=DestroyImageInfo(read_info);
470  if (images == (Image *) NULL)
471  {
472  XSetCursorState(display,windows,MagickFalse);
473  ThrowXWindowException(ImageError,"NoImagesWereLoaded",filenames);
474  return((Image *) NULL);
475  }
476  nexus=GetFirstImageInList(images);
477  *state|=ExitState;
478  break;
479  }
480  case PlayCommand:
481  {
482  char
483  basename[MagickPathExtent];
484 
485  int
486  status;
487 
488  /*
489  Window name is the base of the filename.
490  */
491  *state|=PlayAnimationState;
492  *state&=(~AutoReverseAnimationState);
493  GetPathComponent((*image)->magick_filename,BasePath,basename);
494  (void) FormatLocaleString(windows->image.name,MagickPathExtent,
495  "%s: %s",MagickPackageName,basename);
496  if (resource_info->title != (char *) NULL)
497  {
498  char
499  *title;
500 
501  title=InterpretImageProperties(resource_info->image_info,*image,
502  resource_info->title,exception);
503  (void) CopyMagickString(windows->image.name,title,MagickPathExtent);
504  title=DestroyString(title);
505  }
506  status=XStringListToTextProperty(&windows->image.name,1,&window_name);
507  if (status == 0)
508  break;
509  XSetWMName(display,windows->image.id,&window_name);
510  (void) XFree((void *) window_name.value);
511  break;
512  }
513  case StepCommand:
514  case StepBackwardCommand:
515  case StepForwardCommand:
516  {
517  *state|=StepAnimationState;
518  *state&=(~PlayAnimationState);
519  if (command_type == StepBackwardCommand)
520  *state&=(~ForwardAnimationState);
521  if (command_type == StepForwardCommand)
522  *state|=ForwardAnimationState;
523  if (resource_info->title != (char *) NULL)
524  break;
525  break;
526  }
527  case RepeatCommand:
528  {
529  *state|=RepeatAnimationState;
530  *state&=(~AutoReverseAnimationState);
531  *state|=PlayAnimationState;
532  break;
533  }
534  case AutoReverseCommand:
535  {
536  *state|=AutoReverseAnimationState;
537  *state&=(~RepeatAnimationState);
538  *state|=PlayAnimationState;
539  break;
540  }
541  case SaveCommand:
542  {
543  /*
544  Save image.
545  */
546  status=XSaveImage(display,resource_info,windows,*image,exception);
547  if (status == MagickFalse)
548  {
549  char
550  message[MagickPathExtent];
551 
552  (void) FormatLocaleString(message,MagickPathExtent,"%s:%s",
553  exception->reason != (char *) NULL ? exception->reason : "",
554  exception->description != (char *) NULL ? exception->description :
555  "");
556  XNoticeWidget(display,windows,"Unable to save file:",message);
557  break;
558  }
559  break;
560  }
561  case SlowerCommand:
562  {
563  resource_info->delay++;
564  break;
565  }
566  case FasterCommand:
567  {
568  if (resource_info->delay == 0)
569  break;
570  resource_info->delay--;
571  break;
572  }
573  case ForwardCommand:
574  {
575  *state=ForwardAnimationState;
576  *state&=(~AutoReverseAnimationState);
577  break;
578  }
579  case ReverseCommand:
580  {
581  *state&=(~ForwardAnimationState);
582  *state&=(~AutoReverseAnimationState);
583  break;
584  }
585  case InfoCommand:
586  {
587  XDisplayImageInfo(display,resource_info,windows,(Image *) NULL,*image,
588  exception);
589  break;
590  }
591  case HelpCommand:
592  {
593  /*
594  User requested help.
595  */
596  XTextViewWidget(display,resource_info,windows,MagickFalse,
597  "Help Viewer - Animate",AnimateHelp);
598  break;
599  }
600  case BrowseDocumentationCommand:
601  {
602  Atom
603  mozilla_atom;
604 
605  Window
606  mozilla_window,
607  root_window;
608 
609  /*
610  Browse the ImageMagick documentation.
611  */
612  root_window=XRootWindow(display,XDefaultScreen(display));
613  mozilla_atom=XInternAtom(display,"_MOZILLA_VERSION",MagickFalse);
614  mozilla_window=XWindowByProperty(display,root_window,mozilla_atom);
615  if (mozilla_window != (Window) NULL)
616  {
617  char
618  command[MagickPathExtent],
619  *url;
620 
621  /*
622  Display documentation using Netscape remote control.
623  */
624  url=GetMagickHomeURL();
625  (void) FormatLocaleString(command,MagickPathExtent,
626  "openurl(%s,new-tab)",url);
627  url=DestroyString(url);
628  mozilla_atom=XInternAtom(display,"_MOZILLA_COMMAND",MagickFalse);
629  (void) XChangeProperty(display,mozilla_window,mozilla_atom,
630  XA_STRING,8,PropModeReplace,(unsigned char *) command,
631  (int) strlen(command));
632  XSetCursorState(display,windows,MagickFalse);
633  break;
634  }
635  XSetCursorState(display,windows,MagickTrue);
636  XCheckRefreshWindows(display,windows);
637  status=InvokeDelegate(resource_info->image_info,*image,"browse",
638  (char *) NULL,exception);
639  if (status == MagickFalse)
640  XNoticeWidget(display,windows,"Unable to browse documentation",
641  (char *) NULL);
642  XDelay(display,1500);
643  XSetCursorState(display,windows,MagickFalse);
644  break;
645  }
646  case VersionCommand:
647  {
648  XNoticeWidget(display,windows,GetMagickVersion((size_t *) NULL),
650  break;
651  }
652  case QuitCommand:
653  {
654  /*
655  exit program
656  */
657  if (resource_info->confirm_exit == MagickFalse)
658  XClientMessage(display,windows->image.id,windows->im_protocols,
659  windows->im_exit,CurrentTime);
660  else
661  {
662  int
663  status;
664 
665  /*
666  Confirm program exit.
667  */
668  status=XConfirmWidget(display,windows,"Do you really want to exit",
669  resource_info->client_name);
670  if (status != 0)
671  XClientMessage(display,windows->image.id,windows->im_protocols,
672  windows->im_exit,CurrentTime);
673  }
674  break;
675  }
676  default:
677  break;
678  }
679  return(nexus);
680 }
681 
682 /*
683 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
684 % %
685 % %
686 % %
687 + X A n i m a t e B a c k g r o u n d I m a g e %
688 % %
689 % %
690 % %
691 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
692 %
693 % XAnimateBackgroundImage() animates an image sequence in the background of
694 % a window.
695 %
696 % The format of the XAnimateBackgroundImage method is:
697 %
698 % void XAnimateBackgroundImage(Display *display,
699 % XResourceInfo *resource_info,Image *images,ExceptionInfo *exception)
700 %
701 % A description of each parameter follows:
702 %
703 % o display: Specifies a connection to an X server; returned from
704 % XOpenDisplay.
705 %
706 % o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
707 %
708 % o images: the image list.
709 %
710 % o exception: return any errors or warnings in this structure.
711 %
712 */
713 
714 #if defined(__cplusplus) || defined(c_plusplus)
715 extern "C" {
716 #endif
717 
718 static int SceneCompare(const void *x,const void *y)
719 {
720  const Image
721  **image_1,
722  **image_2;
723 
724  image_1=(const Image **) x;
725  image_2=(const Image **) y;
726  return((int) ((*image_1)->scene-(*image_2)->scene));
727 }
728 
729 #if defined(__cplusplus) || defined(c_plusplus)
730 }
731 #endif
732 
733 MagickExport void XAnimateBackgroundImage(Display *display,
734  XResourceInfo *resource_info,Image *images,ExceptionInfo *exception)
735 {
736  char
737  geometry[MagickPathExtent],
738  visual_type[MagickPathExtent];
739 
740  Image
741  *coalesce_image,
742  *display_image,
743  **image_list;
744 
745  int
746  scene;
747 
749  status;
750 
752  geometry_info;
753 
754  register ssize_t
755  i;
756 
757  size_t
758  delay,
759  number_scenes;
760 
761  ssize_t
762  iterations;
763 
764  static XPixelInfo
765  pixel;
766 
767  static XStandardColormap
768  *map_info;
769 
770  static XVisualInfo
771  *visual_info = (XVisualInfo *) NULL;
772 
773  static XWindowInfo
774  window_info;
775 
776  unsigned int
777  height,
778  width;
779 
780  Window
781  root_window;
782 
783  XEvent
784  event;
785 
786  XGCValues
787  context_values;
788 
789  XResourceInfo
790  resources;
791 
792  XWindowAttributes
793  window_attributes;
794 
795  /*
796  Determine target window.
797  */
798  assert(images != (Image *) NULL);
799  assert(images->signature == MagickCoreSignature);
800  if (images->debug != MagickFalse)
801  (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",images->filename);
802  resources=(*resource_info);
803  window_info.id=(Window) NULL;
804  root_window=XRootWindow(display,XDefaultScreen(display));
805  if (LocaleCompare(resources.window_id,"root") == 0)
806  window_info.id=root_window;
807  else
808  {
809  if (isdigit((int) ((unsigned char) *resources.window_id)) != 0)
810  window_info.id=XWindowByID(display,root_window,
811  (Window) strtol((char *) resources.window_id,(char **) NULL,0));
812  if (window_info.id == (Window) NULL)
813  window_info.id=
814  XWindowByName(display,root_window,resources.window_id);
815  }
816  if (window_info.id == (Window) NULL)
817  {
818  ThrowXWindowException(XServerError,"NoWindowWithSpecifiedIDExists",
819  resources.window_id);
820  return;
821  }
822  /*
823  Determine window visual id.
824  */
825  window_attributes.width=XDisplayWidth(display,XDefaultScreen(display));
826  window_attributes.height=XDisplayHeight(display,XDefaultScreen(display));
827  (void) CopyMagickString(visual_type,"default",MagickPathExtent);
828  status=XGetWindowAttributes(display,window_info.id,&window_attributes) != 0 ?
830  if (status != MagickFalse)
831  (void) FormatLocaleString(visual_type,MagickPathExtent,"0x%lx",
832  XVisualIDFromVisual(window_attributes.visual));
833  if (visual_info == (XVisualInfo *) NULL)
834  {
835  /*
836  Allocate standard colormap.
837  */
838  map_info=XAllocStandardColormap();
839  if (map_info == (XStandardColormap *) NULL)
840  ThrowXWindowFatalException(ResourceLimitFatalError,
841  "MemoryAllocationFailed",images->filename);
842  map_info->colormap=(Colormap) NULL;
843  pixel.pixels=(unsigned long *) NULL;
844  /*
845  Initialize visual info.
846  */
847  resources.map_type=(char *) NULL;
848  resources.visual_type=visual_type;
849  visual_info=XBestVisualInfo(display,map_info,&resources);
850  if (visual_info == (XVisualInfo *) NULL)
851  ThrowXWindowFatalException(XServerFatalError,"UnableToGetVisual",
852  images->filename);
853  /*
854  Initialize window info.
855  */
856  window_info.ximage=(XImage *) NULL;
857  window_info.matte_image=(XImage *) NULL;
858  window_info.pixmap=(Pixmap) NULL;
859  window_info.matte_pixmap=(Pixmap) NULL;
860  }
861  /*
862  Free previous root colors.
863  */
864  if (window_info.id == root_window)
865  XDestroyWindowColors(display,root_window);
866  coalesce_image=CoalesceImages(images,exception);
867  if (coalesce_image == (Image *) NULL)
868  ThrowXWindowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed",
869  images->filename);
870  images=coalesce_image;
871  if (resources.map_type == (char *) NULL)
872  if ((visual_info->klass != TrueColor) &&
873  (visual_info->klass != DirectColor))
874  {
875  Image
876  *next;
877 
878  /*
879  Determine if the sequence of images has the identical colormap.
880  */
881  for (next=images; next != (Image *) NULL; )
882  {
884  if ((next->storage_class == DirectClass) ||
885  (next->colors != images->colors) ||
886  (next->colors > (size_t) visual_info->colormap_size))
887  break;
888  for (i=0; i < (ssize_t) images->colors; i++)
889  if (IsPixelInfoEquivalent(next->colormap+i,images->colormap+i) == MagickFalse)
890  break;
891  if (i < (ssize_t) images->colors)
892  break;
893  next=GetNextImageInList(next);
894  }
895  if (next != (Image *) NULL)
896  (void) RemapImages(resources.quantize_info,images,(Image *) NULL,
897  exception);
898  }
899  /*
900  Sort images by increasing scene number.
901  */
902  number_scenes=GetImageListLength(images);
903  image_list=ImageListToArray(images,exception);
904  if (image_list == (Image **) NULL)
905  ThrowXWindowFatalException(ResourceLimitFatalError,
906  "MemoryAllocationFailed",images->filename);
907  for (i=0; i < (ssize_t) number_scenes; i++)
908  if (image_list[i]->scene == 0)
909  break;
910  if (i == (ssize_t) number_scenes)
911  qsort((void *) image_list,number_scenes,sizeof(Image *),SceneCompare);
912  /*
913  Initialize Standard Colormap.
914  */
915  resources.colormap=SharedColormap;
916  display_image=image_list[0];
917  for (scene=0; scene < (int) number_scenes; scene++)
918  {
919  if ((resource_info->map_type != (char *) NULL) ||
920  (visual_info->klass == TrueColor) ||
921  (visual_info->klass == DirectColor))
922  (void) SetImageType(image_list[scene],image_list[scene]->alpha_trait ==
924  if ((display_image->columns < image_list[scene]->columns) &&
925  (display_image->rows < image_list[scene]->rows))
926  display_image=image_list[scene];
927  }
928  if ((resource_info->map_type != (char *) NULL) ||
929  (visual_info->klass == TrueColor) || (visual_info->klass == DirectColor))
930  (void) SetImageType(display_image,display_image->alpha_trait !=
932  XMakeStandardColormap(display,visual_info,&resources,display_image,map_info,
933  &pixel,exception);
934  /*
935  Graphic context superclass.
936  */
937  context_values.background=pixel.background_color.pixel;
938  context_values.foreground=pixel.foreground_color.pixel;
939  pixel.annotate_context=XCreateGC(display,window_info.id,(unsigned long)
940  (GCBackground | GCForeground),&context_values);
941  if (pixel.annotate_context == (GC) NULL)
942  ThrowXWindowFatalException(XServerFatalError,"UnableToCreateGraphicContext",
943  images->filename);
944  /*
945  Initialize Image window attributes.
946  */
947  XGetWindowInfo(display,visual_info,map_info,&pixel,(XFontStruct *) NULL,
948  &resources,&window_info);
949  /*
950  Create the X image.
951  */
952  window_info.width=(unsigned int) image_list[0]->columns;
953  window_info.height=(unsigned int) image_list[0]->rows;
954  if ((image_list[0]->columns != window_info.width) ||
955  (image_list[0]->rows != window_info.height))
956  ThrowXWindowFatalException(XServerFatalError,"UnableToCreateXImage",
957  image_list[0]->filename);
958  (void) FormatLocaleString(geometry,MagickPathExtent,"%ux%u+0+0>",
959  window_attributes.width,window_attributes.height);
960  geometry_info.width=window_info.width;
961  geometry_info.height=window_info.height;
962  geometry_info.x=(ssize_t) window_info.x;
963  geometry_info.y=(ssize_t) window_info.y;
964  (void) ParseMetaGeometry(geometry,&geometry_info.x,&geometry_info.y,
965  &geometry_info.width,&geometry_info.height);
966  window_info.width=(unsigned int) geometry_info.width;
967  window_info.height=(unsigned int) geometry_info.height;
968  window_info.x=(int) geometry_info.x;
969  window_info.y=(int) geometry_info.y;
970  status=XMakeImage(display,&resources,&window_info,image_list[0],
971  window_info.width,window_info.height,exception);
972  if (status == MagickFalse)
973  ThrowXWindowFatalException(XServerFatalError,"UnableToCreateXImage",
974  images->filename);
975  window_info.x=0;
976  window_info.y=0;
977  if (display_image->debug != MagickFalse)
978  {
980  "Image: %s[%.20g] %.20gx%.20g ",image_list[0]->filename,(double)
981  image_list[0]->scene,(double) image_list[0]->columns,(double)
982  image_list[0]->rows);
983  if (image_list[0]->colors != 0)
984  (void) LogMagickEvent(X11Event,GetMagickModule(),"%.20gc ",(double)
985  image_list[0]->colors);
987  image_list[0]->magick);
988  }
989  /*
990  Adjust image dimensions as specified by backdrop or geometry options.
991  */
992  width=window_info.width;
993  height=window_info.height;
994  if (resources.backdrop != MagickFalse)
995  {
996  /*
997  Center image on window.
998  */
999  window_info.x=(int) (window_attributes.width/2)-
1000  (window_info.ximage->width/2);
1001  window_info.y=(int) (window_attributes.height/2)-
1002  (window_info.ximage->height/2);
1003  width=(unsigned int) window_attributes.width;
1004  height=(unsigned int) window_attributes.height;
1005  }
1006  if (resources.image_geometry != (char *) NULL)
1007  {
1008  char
1009  default_geometry[MagickPathExtent];
1010 
1011  int
1012  flags,
1013  gravity;
1014 
1015  XSizeHints
1016  *size_hints;
1017 
1018  /*
1019  User specified geometry.
1020  */
1021  size_hints=XAllocSizeHints();
1022  if (size_hints == (XSizeHints *) NULL)
1023  ThrowXWindowFatalException(ResourceLimitFatalError,
1024  "MemoryAllocationFailed",images->filename);
1025  size_hints->flags=0L;
1026  (void) FormatLocaleString(default_geometry,MagickPathExtent,"%ux%u",width,
1027  height);
1028  flags=XWMGeometry(display,visual_info->screen,resources.image_geometry,
1029  default_geometry,window_info.border_width,size_hints,&window_info.x,
1030  &window_info.y,(int *) &width,(int *) &height,&gravity);
1031  if (((flags & (XValue | YValue))) != 0)
1032  {
1033  width=(unsigned int) window_attributes.width;
1034  height=(unsigned int) window_attributes.height;
1035  }
1036  (void) XFree((void *) size_hints);
1037  }
1038  /*
1039  Create the X pixmap.
1040  */
1041  window_info.pixmap=XCreatePixmap(display,window_info.id,(unsigned int) width,
1042  (unsigned int) height,window_info.depth);
1043  if (window_info.pixmap == (Pixmap) NULL)
1044  ThrowXWindowFatalException(XServerFatalError,"UnableToCreateXPixmap",
1045  images->filename);
1046  /*
1047  Display pixmap on the window.
1048  */
1049  if (((unsigned int) width > window_info.width) ||
1050  ((unsigned int) height > window_info.height))
1051  (void) XFillRectangle(display,window_info.pixmap,
1052  window_info.annotate_context,0,0,(unsigned int) width,
1053  (unsigned int) height);
1054  (void) XPutImage(display,window_info.pixmap,window_info.annotate_context,
1055  window_info.ximage,0,0,window_info.x,window_info.y,window_info.width,
1056  window_info.height);
1057  (void) XSetWindowBackgroundPixmap(display,window_info.id,window_info.pixmap);
1058  (void) XClearWindow(display,window_info.id);
1059  /*
1060  Initialize image pixmaps structure.
1061  */
1062  window_info.pixmaps=(Pixmap *) AcquireQuantumMemory(number_scenes,
1063  sizeof(*window_info.pixmaps));
1064  window_info.matte_pixmaps=(Pixmap *) AcquireQuantumMemory(number_scenes,
1065  sizeof(*window_info.matte_pixmaps));
1066  if ((window_info.pixmaps == (Pixmap *) NULL) ||
1067  (window_info.matte_pixmaps == (Pixmap *) NULL))
1068  ThrowXWindowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed",
1069  images->filename);
1070  window_info.pixmaps[0]=window_info.pixmap;
1071  window_info.matte_pixmaps[0]=window_info.pixmap;
1072  for (scene=1; scene < (int) number_scenes; scene++)
1073  {
1074  unsigned int
1075  columns,
1076  rows;
1077 
1078  /*
1079  Create X image.
1080  */
1081  window_info.pixmap=(Pixmap) NULL;
1082  window_info.matte_pixmap=(Pixmap) NULL;
1083  if ((resources.map_type != (char *) NULL) ||
1084  (visual_info->klass == TrueColor) ||
1085  (visual_info->klass == DirectColor))
1086  if (image_list[scene]->storage_class == PseudoClass)
1087  XGetPixelInfo(display,visual_info,map_info,&resources,
1088  image_list[scene],window_info.pixel_info);
1089  columns=(unsigned int) image_list[scene]->columns;
1090  rows=(unsigned int) image_list[scene]->rows;
1091  if ((image_list[scene]->columns != columns) ||
1092  (image_list[scene]->rows != rows))
1093  ThrowXWindowFatalException(XServerFatalError,"UnableToCreateXImage",
1094  image_list[scene]->filename);
1095  status=XMakeImage(display,&resources,&window_info,image_list[scene],
1096  columns,rows,exception);
1097  if (status == MagickFalse)
1098  ThrowXWindowFatalException(XServerFatalError,"UnableToCreateXImage",
1099  images->filename);
1100  if (display_image->debug != MagickFalse)
1101  {
1103  "Image: [%.20g] %s %.20gx%.20g ",(double) image_list[scene]->scene,
1104  image_list[scene]->filename,(double) columns,(double) rows);
1105  if (image_list[scene]->colors != 0)
1106  (void) LogMagickEvent(X11Event,GetMagickModule(),"%.20gc ",(double)
1107  image_list[scene]->colors);
1108  (void) LogMagickEvent(X11Event,GetMagickModule(),"%s",
1109  image_list[scene]->magick);
1110  }
1111  /*
1112  Create the X pixmap.
1113  */
1114  window_info.pixmap=XCreatePixmap(display,window_info.id,width,height,
1115  window_info.depth);
1116  if (window_info.pixmap == (Pixmap) NULL)
1117  ThrowXWindowFatalException(XServerFatalError,"UnableToCreateXPixmap",
1118  images->filename);
1119  /*
1120  Display pixmap on the window.
1121  */
1122  if ((width > window_info.width) || (height > window_info.height))
1123  (void) XFillRectangle(display,window_info.pixmap,
1124  window_info.annotate_context,0,0,width,height);
1125  (void) XPutImage(display,window_info.pixmap,window_info.annotate_context,
1126  window_info.ximage,0,0,window_info.x,window_info.y,window_info.width,
1127  window_info.height);
1128  (void) XSetWindowBackgroundPixmap(display,window_info.id,
1129  window_info.pixmap);
1130  (void) XClearWindow(display,window_info.id);
1131  window_info.pixmaps[scene]=window_info.pixmap;
1132  window_info.matte_pixmaps[scene]=window_info.matte_pixmap;
1133  if (image_list[scene]->alpha_trait)
1134  (void) XClearWindow(display,window_info.id);
1135  delay=1000*image_list[scene]->delay/MagickMax(
1136  image_list[scene]->ticks_per_second,1L);
1137  XDelay(display,resources.delay*(delay == 0 ? 10 : delay));
1138  }
1139  window_info.pixel_info=(&pixel);
1140  /*
1141  Display pixmap on the window.
1142  */
1143  (void) XSelectInput(display,window_info.id,SubstructureNotifyMask);
1144  event.type=Expose;
1145  iterations=0;
1146  do
1147  {
1148  for (scene=0; scene < (int) number_scenes; scene++)
1149  {
1150  if (XEventsQueued(display,QueuedAfterFlush) > 0)
1151  {
1152  (void) XNextEvent(display,&event);
1153  if (event.type == DestroyNotify)
1154  break;
1155  }
1156  window_info.pixmap=window_info.pixmaps[scene];
1157  window_info.matte_pixmap=window_info.matte_pixmaps[scene];
1158  (void) XSetWindowBackgroundPixmap(display,window_info.id,
1159  window_info.pixmap);
1160  (void) XClearWindow(display,window_info.id);
1161  (void) XSync(display,MagickFalse);
1162  delay=1000*image_list[scene]->delay/MagickMax(
1163  image_list[scene]->ticks_per_second,1L);
1164  XDelay(display,resources.delay*(delay == 0 ? 10 : delay));
1165  }
1166  iterations++;
1167  if (iterations == (ssize_t) image_list[0]->iterations)
1168  break;
1169  } while (event.type != DestroyNotify);
1170  (void) XSync(display,MagickFalse);
1171  image_list=(Image **) RelinquishMagickMemory(image_list);
1172  images=DestroyImageList(images);
1173 }
1174 
1175 /*
1176 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1177 % %
1178 % %
1179 % %
1180 + X A n i m a t e I m a g e s %
1181 % %
1182 % %
1183 % %
1184 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1185 %
1186 % XAnimateImages() displays an image via X11.
1187 %
1188 % The format of the XAnimateImages method is:
1189 %
1190 % Image *XAnimateImages(Display *display,XResourceInfo *resource_info,
1191 % char **argv,const int argc,Image *images,ExceptionInfo *exception)
1192 %
1193 % A description of each parameter follows:
1194 %
1195 % o display: Specifies a connection to an X server; returned from
1196 % XOpenDisplay.
1197 %
1198 % o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
1199 %
1200 % o argv: Specifies the application's argument list.
1201 %
1202 % o argc: Specifies the number of arguments.
1203 %
1204 % o images: the image list.
1205 %
1206 % o exception: return any errors or warnings in this structure.
1207 %
1208 */
1209 MagickExport Image *XAnimateImages(Display *display,
1210  XResourceInfo *resource_info,char **argv,const int argc,Image *images,
1211  ExceptionInfo *exception)
1212 {
1213 #define MagickMenus 4
1214 #define MaXWindows 8
1215 #define MagickTitle "Commands"
1216 
1217  static const char
1218  *CommandMenu[]=
1219  {
1220  "Animate",
1221  "Speed",
1222  "Direction",
1223  "Help",
1224  "Image Info",
1225  "Quit",
1226  (char *) NULL
1227  },
1228  *AnimateMenu[]=
1229  {
1230  "Open...",
1231  "Play",
1232  "Step",
1233  "Repeat",
1234  "Auto Reverse",
1235  "Save...",
1236  (char *) NULL
1237  },
1238  *SpeedMenu[]=
1239  {
1240  "Faster",
1241  "Slower",
1242  (char *) NULL
1243  },
1244  *DirectionMenu[]=
1245  {
1246  "Forward",
1247  "Reverse",
1248  (char *) NULL
1249  },
1250  *HelpMenu[]=
1251  {
1252  "Overview",
1253  "Browse Documentation",
1254  "About Animate",
1255  (char *) NULL
1256  };
1257 
1258  static const char
1259  **Menus[MagickMenus]=
1260  {
1261  AnimateMenu,
1262  SpeedMenu,
1263  DirectionMenu,
1264  HelpMenu
1265  };
1266 
1267  static const CommandType
1268  CommandMenus[]=
1269  {
1270  NullCommand,
1271  NullCommand,
1272  NullCommand,
1273  NullCommand,
1274  InfoCommand,
1275  QuitCommand
1276  },
1277  CommandTypes[]=
1278  {
1279  OpenCommand,
1280  PlayCommand,
1281  StepCommand,
1282  RepeatCommand,
1283  AutoReverseCommand,
1284  SaveCommand
1285  },
1286  SpeedCommands[]=
1287  {
1288  FasterCommand,
1289  SlowerCommand
1290  },
1291  DirectionCommands[]=
1292  {
1293  ForwardCommand,
1294  ReverseCommand
1295  },
1296  HelpCommands[]=
1297  {
1298  HelpCommand,
1299  BrowseDocumentationCommand,
1300  VersionCommand
1301  };
1302 
1303  static const CommandType
1304  *Commands[MagickMenus]=
1305  {
1306  CommandTypes,
1307  SpeedCommands,
1308  DirectionCommands,
1309  HelpCommands
1310  };
1311 
1312  char
1313  command[MagickPathExtent],
1314  *directory,
1315  geometry[MagickPathExtent],
1316  resource_name[MagickPathExtent];
1317 
1318  CommandType
1319  command_type;
1320 
1321  Image
1322  *coalesce_image,
1323  *display_image,
1324  *image,
1325  **image_list,
1326  *nexus;
1327 
1328  int
1329  status;
1330 
1331  KeySym
1332  key_symbol;
1333 
1335  context_mask,
1336  state;
1337 
1339  geometry_info;
1340 
1341  register char
1342  *p;
1343 
1344  register ssize_t
1345  i;
1346 
1347  ssize_t
1348  first_scene,
1349  iterations,
1350  scene;
1351 
1352  static char
1353  working_directory[MagickPathExtent];
1354 
1355  static size_t
1356  number_windows;
1357 
1358  static XWindowInfo
1359  *magick_windows[MaXWindows];
1360 
1361  time_t
1362  timestamp;
1363 
1364  size_t
1365  delay,
1366  number_scenes;
1367 
1370 
1371  Window
1372  root_window;
1373 
1374  XClassHint
1375  *class_hints;
1376 
1377  XEvent
1378  event;
1379 
1380  XFontStruct
1381  *font_info;
1382 
1383  XGCValues
1384  context_values;
1385 
1386  XPixelInfo
1387  *icon_pixel,
1388  *pixel;
1389 
1390  XResourceInfo
1391  *icon_resources;
1392 
1393  XStandardColormap
1394  *icon_map,
1395  *map_info;
1396 
1397  XTextProperty
1398  window_name;
1399 
1400  XVisualInfo
1401  *icon_visual,
1402  *visual_info;
1403 
1404  XWindowChanges
1405  window_changes;
1406 
1407  XWindows
1408  *windows;
1409 
1410  XWMHints
1411  *manager_hints;
1412 
1413  assert(images != (Image *) NULL);
1414  assert(images->signature == MagickCoreSignature);
1415  if (images->debug != MagickFalse)
1416  (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",images->filename);
1418  windows=XSetWindows((XWindows *) ~0);
1419  if (windows != (XWindows *) NULL)
1420  {
1421  int
1422  status;
1423 
1424  if (*working_directory == '\0')
1425  (void) CopyMagickString(working_directory,".",MagickPathExtent);
1426  status=chdir(working_directory);
1427  if (status == -1)
1429  "UnableToOpenFile","%s",working_directory);
1430  warning_handler=resource_info->display_warnings ?
1431  SetErrorHandler(XWarning) : SetErrorHandler((ErrorHandler) NULL);
1432  warning_handler=resource_info->display_warnings ?
1434  }
1435  else
1436  {
1437  register Image
1438  *p;
1439 
1440  /*
1441  Initialize window structure.
1442  */
1443  for (p=images; p != (Image *) NULL; p=GetNextImageInList(p))
1444  {
1445  if (p->storage_class == DirectClass)
1446  {
1447  resource_info->colors=0;
1448  break;
1449  }
1450  if (p->colors > resource_info->colors)
1451  resource_info->colors=p->colors;
1452  }
1453  windows=XSetWindows(XInitializeWindows(display,resource_info));
1454  if (windows == (XWindows *) NULL)
1455  ThrowXWindowFatalException(XServerFatalError,"MemoryAllocationFailed",
1456  images->filename);
1457  /*
1458  Initialize window id's.
1459  */
1460  number_windows=0;
1461  magick_windows[number_windows++]=(&windows->icon);
1462  magick_windows[number_windows++]=(&windows->backdrop);
1463  magick_windows[number_windows++]=(&windows->image);
1464  magick_windows[number_windows++]=(&windows->info);
1465  magick_windows[number_windows++]=(&windows->command);
1466  magick_windows[number_windows++]=(&windows->widget);
1467  magick_windows[number_windows++]=(&windows->popup);
1468  for (i=0; i < (ssize_t) number_windows; i++)
1469  magick_windows[i]->id=(Window) NULL;
1470  }
1471  /*
1472  Initialize font info.
1473  */
1474  if (windows->font_info != (XFontStruct *) NULL)
1475  (void) XFreeFont(display,windows->font_info);
1476  windows->font_info=XBestFont(display,resource_info,MagickFalse);
1477  if (windows->font_info == (XFontStruct *) NULL)
1478  ThrowXWindowFatalException(XServerFatalError,"UnableToLoadFont",
1479  resource_info->font);
1480  /*
1481  Initialize Standard Colormap.
1482  */
1483  map_info=windows->map_info;
1484  icon_map=windows->icon_map;
1485  visual_info=windows->visual_info;
1486  icon_visual=windows->icon_visual;
1487  pixel=windows->pixel_info;
1488  icon_pixel=windows->icon_pixel;
1489  font_info=windows->font_info;
1490  icon_resources=windows->icon_resources;
1491  class_hints=windows->class_hints;
1492  manager_hints=windows->manager_hints;
1493  root_window=XRootWindow(display,visual_info->screen);
1494  coalesce_image=CoalesceImages(images,exception);
1495  if (coalesce_image == (Image *) NULL)
1496  ThrowXWindowFatalException(XServerFatalError,"MemoryAllocationFailed",
1497  images->filename);
1498  images=coalesce_image;
1499  if (resource_info->map_type == (char *) NULL)
1500  if ((visual_info->klass != TrueColor) &&
1501  (visual_info->klass != DirectColor))
1502  {
1503  Image
1504  *next;
1505 
1506  /*
1507  Determine if the sequence of images has the identical colormap.
1508  */
1509  for (next=images; next != (Image *) NULL; )
1510  {
1512  if ((next->storage_class == DirectClass) ||
1513  (next->colors != images->colors) ||
1514  (next->colors > (size_t) visual_info->colormap_size))
1515  break;
1516  for (i=0; i < (ssize_t) images->colors; i++)
1517  if (IsPixelInfoEquivalent(next->colormap+i,images->colormap+i) == MagickFalse)
1518  break;
1519  if (i < (ssize_t) images->colors)
1520  break;
1521  next=GetNextImageInList(next);
1522  }
1523  if (next != (Image *) NULL)
1524  (void) RemapImages(resource_info->quantize_info,images,
1525  (Image *) NULL,exception);
1526  }
1527  /*
1528  Sort images by increasing scene number.
1529  */
1530  number_scenes=GetImageListLength(images);
1531  image_list=ImageListToArray(images,exception);
1532  if (image_list == (Image **) NULL)
1533  ThrowXWindowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed",
1534  images->filename);
1535  for (scene=0; scene < (ssize_t) number_scenes; scene++)
1536  if (image_list[scene]->scene == 0)
1537  break;
1538  if (scene == (ssize_t) number_scenes)
1539  qsort((void *) image_list,number_scenes,sizeof(Image *),SceneCompare);
1540  /*
1541  Initialize Standard Colormap.
1542  */
1543  nexus=NewImageList();
1544  display_image=image_list[0];
1545  for (scene=0; scene < (ssize_t) number_scenes; scene++)
1546  {
1547  if ((resource_info->map_type != (char *) NULL) ||
1548  (visual_info->klass == TrueColor) ||
1549  (visual_info->klass == DirectColor))
1550  (void) SetImageType(image_list[scene],image_list[scene]->alpha_trait ==
1552  if ((display_image->columns < image_list[scene]->columns) &&
1553  (display_image->rows < image_list[scene]->rows))
1554  display_image=image_list[scene];
1555  }
1556  if (display_image->debug != MagickFalse)
1557  {
1559  "Image: %s[%.20g] %.20gx%.20g ",display_image->filename,(double)
1560  display_image->scene,(double) display_image->columns,(double)
1561  display_image->rows);
1562  if (display_image->colors != 0)
1563  (void) LogMagickEvent(X11Event,GetMagickModule(),"%.20gc ",(double)
1564  display_image->colors);
1565  (void) LogMagickEvent(X11Event,GetMagickModule(),"%s",
1566  display_image->magick);
1567  }
1568  XMakeStandardColormap(display,visual_info,resource_info,display_image,
1569  map_info,pixel,exception);
1570  /*
1571  Initialize graphic context.
1572  */
1573  windows->context.id=(Window) NULL;
1574  XGetWindowInfo(display,visual_info,map_info,pixel,font_info,
1575  resource_info,&windows->context);
1576  (void) CloneString(&class_hints->res_name,resource_info->client_name);
1577  (void) CloneString(&class_hints->res_class,resource_info->client_name);
1578  class_hints->res_class[0]=(char) toupper((int) class_hints->res_class[0]);
1579  manager_hints->flags=InputHint | StateHint;
1580  manager_hints->input=MagickFalse;
1581  manager_hints->initial_state=WithdrawnState;
1582  XMakeWindow(display,root_window,argv,argc,class_hints,manager_hints,
1583  &windows->context);
1584  if (display_image->debug != MagickFalse)
1586  "Window id: 0x%lx (context)",windows->context.id);
1587  context_values.background=pixel->background_color.pixel;
1588  context_values.font=font_info->fid;
1589  context_values.foreground=pixel->foreground_color.pixel;
1590  context_values.graphics_exposures=MagickFalse;
1591  context_mask=(MagickStatusType)
1592  (GCBackground | GCFont | GCForeground | GCGraphicsExposures);
1593  if (pixel->annotate_context != (GC) NULL)
1594  (void) XFreeGC(display,pixel->annotate_context);
1595  pixel->annotate_context=
1596  XCreateGC(display,windows->context.id,context_mask,&context_values);
1597  if (pixel->annotate_context == (GC) NULL)
1598  ThrowXWindowFatalException(XServerFatalError,"UnableToCreateGraphicContext",
1599  images->filename);
1600  context_values.background=pixel->depth_color.pixel;
1601  if (pixel->widget_context != (GC) NULL)
1602  (void) XFreeGC(display,pixel->widget_context);
1603  pixel->widget_context=
1604  XCreateGC(display,windows->context.id,context_mask,&context_values);
1605  if (pixel->widget_context == (GC) NULL)
1606  ThrowXWindowFatalException(XServerFatalError,"UnableToCreateGraphicContext",
1607  images->filename);
1608  context_values.background=pixel->foreground_color.pixel;
1609  context_values.foreground=pixel->background_color.pixel;
1610  context_values.plane_mask=
1611  context_values.background ^ context_values.foreground;
1612  if (pixel->highlight_context != (GC) NULL)
1613  (void) XFreeGC(display,pixel->highlight_context);
1614  pixel->highlight_context=XCreateGC(display,windows->context.id,
1615  (size_t) (context_mask | GCPlaneMask),&context_values);
1616  if (pixel->highlight_context == (GC) NULL)
1617  ThrowXWindowFatalException(XServerFatalError,"UnableToCreateGraphicContext",
1618  images->filename);
1619  (void) XDestroyWindow(display,windows->context.id);
1620  /*
1621  Initialize icon window.
1622  */
1623  XGetWindowInfo(display,icon_visual,icon_map,icon_pixel,(XFontStruct *) NULL,
1624  icon_resources,&windows->icon);
1625  windows->icon.geometry=resource_info->icon_geometry;
1626  XBestIconSize(display,&windows->icon,display_image);
1627  windows->icon.attributes.colormap=
1628  XDefaultColormap(display,icon_visual->screen);
1629  windows->icon.attributes.event_mask=ExposureMask | StructureNotifyMask;
1630  manager_hints->flags=InputHint | StateHint;
1631  manager_hints->input=MagickFalse;
1632  manager_hints->initial_state=IconicState;
1633  XMakeWindow(display,root_window,argv,argc,class_hints,manager_hints,
1634  &windows->icon);
1635  if (display_image->debug != MagickFalse)
1636  (void) LogMagickEvent(X11Event,GetMagickModule(),"Window id: 0x%lx (icon)",
1637  windows->icon.id);
1638  /*
1639  Initialize graphic context for icon window.
1640  */
1641  if (icon_pixel->annotate_context != (GC) NULL)
1642  (void) XFreeGC(display,icon_pixel->annotate_context);
1643  context_values.background=icon_pixel->background_color.pixel;
1644  context_values.foreground=icon_pixel->foreground_color.pixel;
1645  icon_pixel->annotate_context=XCreateGC(display,windows->icon.id,
1646  (size_t) (GCBackground | GCForeground),&context_values);
1647  if (icon_pixel->annotate_context == (GC) NULL)
1648  ThrowXWindowFatalException(XServerFatalError,"UnableToCreateGraphicContext",
1649  images->filename);
1650  windows->icon.annotate_context=icon_pixel->annotate_context;
1651  /*
1652  Initialize Image window.
1653  */
1654  XGetWindowInfo(display,visual_info,map_info,pixel,font_info,
1655  resource_info,&windows->image);
1656  windows->image.shape=MagickTrue; /* non-rectangular shape hint */
1657  if (resource_info->use_shared_memory == MagickFalse)
1658  windows->image.shared_memory=MagickFalse;
1659  if (resource_info->title != (char *) NULL)
1660  {
1661  char
1662  *title;
1663 
1664  title=InterpretImageProperties(resource_info->image_info,display_image,
1665  resource_info->title,exception);
1666  (void) CopyMagickString(windows->image.name,title,MagickPathExtent);
1667  (void) CopyMagickString(windows->image.icon_name,title,MagickPathExtent);
1668  title=DestroyString(title);
1669  }
1670  else
1671  {
1672  char
1673  filename[MagickPathExtent];
1674 
1675  /*
1676  Window name is the base of the filename.
1677  */
1678  GetPathComponent(display_image->magick_filename,TailPath,filename);
1679  (void) FormatLocaleString(windows->image.name,MagickPathExtent,
1680  "%s: %s[scene: %.20g frames: %.20g]",MagickPackageName,filename,(double)
1681  display_image->scene,(double) number_scenes);
1682  (void) CopyMagickString(windows->image.icon_name,filename,MagickPathExtent);
1683  }
1684  if (resource_info->immutable != MagickFalse)
1685  windows->image.immutable=MagickTrue;
1686  windows->image.shape=MagickTrue;
1687  windows->image.geometry=resource_info->image_geometry;
1688  (void) FormatLocaleString(geometry,MagickPathExtent,"%ux%u+0+0>!",
1689  XDisplayWidth(display,visual_info->screen),
1690  XDisplayHeight(display,visual_info->screen));
1691  geometry_info.width=display_image->columns;
1692  geometry_info.height=display_image->rows;
1693  geometry_info.x=0;
1694  geometry_info.y=0;
1695  (void) ParseMetaGeometry(geometry,&geometry_info.x,&geometry_info.y,
1696  &geometry_info.width,&geometry_info.height);
1697  windows->image.width=(unsigned int) geometry_info.width;
1698  windows->image.height=(unsigned int) geometry_info.height;
1699  windows->image.attributes.event_mask=ButtonMotionMask | ButtonPressMask |
1700  ButtonReleaseMask | EnterWindowMask | ExposureMask | KeyPressMask |
1701  KeyReleaseMask | LeaveWindowMask | OwnerGrabButtonMask |
1702  PropertyChangeMask | StructureNotifyMask | SubstructureNotifyMask;
1703  XGetWindowInfo(display,visual_info,map_info,pixel,font_info,
1704  resource_info,&windows->backdrop);
1705  if ((resource_info->backdrop) || (windows->backdrop.id != (Window) NULL))
1706  {
1707  /*
1708  Initialize backdrop window.
1709  */
1710  windows->backdrop.x=0;
1711  windows->backdrop.y=0;
1712  (void) CloneString(&windows->backdrop.name,"ImageMagick Backdrop");
1713  windows->backdrop.flags=(size_t) (USSize | USPosition);
1714  windows->backdrop.width=(unsigned int)
1715  XDisplayWidth(display,visual_info->screen);
1716  windows->backdrop.height=(unsigned int)
1717  XDisplayHeight(display,visual_info->screen);
1718  windows->backdrop.border_width=0;
1719  windows->backdrop.immutable=MagickTrue;
1720  windows->backdrop.attributes.do_not_propagate_mask=ButtonPressMask |
1721  ButtonReleaseMask;
1722  windows->backdrop.attributes.event_mask=ButtonPressMask | KeyPressMask |
1723  StructureNotifyMask;
1724  manager_hints->flags=IconWindowHint | InputHint | StateHint;
1725  manager_hints->icon_window=windows->icon.id;
1726  manager_hints->input=MagickTrue;
1727  manager_hints->initial_state=
1728  resource_info->iconic ? IconicState : NormalState;
1729  XMakeWindow(display,root_window,argv,argc,class_hints,manager_hints,
1730  &windows->backdrop);
1731  if (display_image->debug != MagickFalse)
1733  "Window id: 0x%lx (backdrop)",windows->backdrop.id);
1734  (void) XMapWindow(display,windows->backdrop.id);
1735  (void) XClearWindow(display,windows->backdrop.id);
1736  if (windows->image.id != (Window) NULL)
1737  {
1738  (void) XDestroyWindow(display,windows->image.id);
1739  windows->image.id=(Window) NULL;
1740  }
1741  /*
1742  Position image in the center the backdrop.
1743  */
1744  windows->image.flags|=USPosition;
1745  windows->image.x=(XDisplayWidth(display,visual_info->screen)/2)-
1746  (windows->image.width/2);
1747  windows->image.y=(XDisplayHeight(display,visual_info->screen)/2)-
1748  (windows->image.height/2);
1749  }
1750  manager_hints->flags=IconWindowHint | InputHint | StateHint;
1751  manager_hints->icon_window=windows->icon.id;
1752  manager_hints->input=MagickTrue;
1753  manager_hints->initial_state=
1754  resource_info->iconic ? IconicState : NormalState;
1755  if (windows->group_leader.id != (Window) NULL)
1756  {
1757  /*
1758  Follow the leader.
1759  */
1760  manager_hints->flags|=(MagickStatusType) WindowGroupHint;
1761  manager_hints->window_group=windows->group_leader.id;
1762  (void) XSelectInput(display,windows->group_leader.id,StructureNotifyMask);
1763  if (display_image->debug != MagickFalse)
1765  "Window id: 0x%lx (group leader)",windows->group_leader.id);
1766  }
1767  XMakeWindow(display,
1768  (Window) (resource_info->backdrop ? windows->backdrop.id : root_window),
1769  argv,argc,class_hints,manager_hints,&windows->image);
1770  (void) XChangeProperty(display,windows->image.id,windows->im_protocols,
1771  XA_STRING,8,PropModeReplace,(unsigned char *) NULL,0);
1772  if (windows->group_leader.id != (Window) NULL)
1773  (void) XSetTransientForHint(display,windows->image.id,
1774  windows->group_leader.id);
1775  if (display_image->debug != MagickFalse)
1776  (void) LogMagickEvent(X11Event,GetMagickModule(),"Window id: 0x%lx (image)",
1777  windows->image.id);
1778  /*
1779  Initialize Info widget.
1780  */
1781  XGetWindowInfo(display,visual_info,map_info,pixel,font_info,
1782  resource_info,&windows->info);
1783  (void) CloneString(&windows->info.name,"Info");
1784  (void) CloneString(&windows->info.icon_name,"Info");
1785  windows->info.border_width=1;
1786  windows->info.x=2;
1787  windows->info.y=2;
1788  windows->info.flags|=PPosition;
1789  windows->info.attributes.win_gravity=UnmapGravity;
1790  windows->info.attributes.event_mask=ButtonPressMask | ExposureMask |
1791  StructureNotifyMask;
1792  manager_hints->flags=InputHint | StateHint | WindowGroupHint;
1793  manager_hints->input=MagickFalse;
1794  manager_hints->initial_state=NormalState;
1795  manager_hints->window_group=windows->image.id;
1796  XMakeWindow(display,windows->image.id,argv,argc,class_hints,manager_hints,
1797  &windows->info);
1798  windows->info.highlight_stipple=XCreateBitmapFromData(display,
1799  windows->info.id,(char *) HighlightBitmap,HighlightWidth,HighlightHeight);
1800  windows->info.shadow_stipple=XCreateBitmapFromData(display,
1801  windows->info.id,(char *) ShadowBitmap,ShadowWidth,ShadowHeight);
1802  (void) XSetTransientForHint(display,windows->info.id,windows->image.id);
1803  if (windows->image.mapped)
1804  (void) XWithdrawWindow(display,windows->info.id,windows->info.screen);
1805  if (display_image->debug != MagickFalse)
1806  (void) LogMagickEvent(X11Event,GetMagickModule(),"Window id: 0x%lx (info)",
1807  windows->info.id);
1808  /*
1809  Initialize Command widget.
1810  */
1811  XGetWindowInfo(display,visual_info,map_info,pixel,font_info,
1812  resource_info,&windows->command);
1813  windows->command.data=MagickMenus;
1814  (void) XCommandWidget(display,windows,CommandMenu,(XEvent *) NULL);
1815  (void) FormatLocaleString(resource_name,MagickPathExtent,"%s.command",
1816  resource_info->client_name);
1817  windows->command.geometry=XGetResourceClass(resource_info->resource_database,
1818  resource_name,"geometry",(char *) NULL);
1819  (void) CloneString(&windows->command.name,MagickTitle);
1820  windows->command.border_width=0;
1821  windows->command.flags|=PPosition;
1822  windows->command.attributes.event_mask=ButtonMotionMask | ButtonPressMask |
1823  ButtonReleaseMask | EnterWindowMask | ExposureMask | LeaveWindowMask |
1824  OwnerGrabButtonMask | StructureNotifyMask;
1825  manager_hints->flags=InputHint | StateHint | WindowGroupHint;
1826  manager_hints->input=MagickTrue;
1827  manager_hints->initial_state=NormalState;
1828  manager_hints->window_group=windows->image.id;
1829  XMakeWindow(display,root_window,argv,argc,class_hints,manager_hints,
1830  &windows->command);
1831  windows->command.highlight_stipple=XCreateBitmapFromData(display,
1832  windows->command.id,(char *) HighlightBitmap,HighlightWidth,
1833  HighlightHeight);
1834  windows->command.shadow_stipple=XCreateBitmapFromData(display,
1835  windows->command.id,(char *) ShadowBitmap,ShadowWidth,ShadowHeight);
1836  (void) XSetTransientForHint(display,windows->command.id,windows->image.id);
1837  if (display_image->debug != MagickFalse)
1839  "Window id: 0x%lx (command)",windows->command.id);
1840  /*
1841  Initialize Widget window.
1842  */
1843  XGetWindowInfo(display,visual_info,map_info,pixel,font_info,
1844  resource_info,&windows->widget);
1845  (void) FormatLocaleString(resource_name,MagickPathExtent,"%s.widget",
1846  resource_info->client_name);
1847  windows->widget.geometry=XGetResourceClass(resource_info->resource_database,
1848  resource_name,"geometry",(char *) NULL);
1849  windows->widget.border_width=0;
1850  windows->widget.flags|=PPosition;
1851  windows->widget.attributes.event_mask=ButtonMotionMask | ButtonPressMask |
1852  ButtonReleaseMask | EnterWindowMask | ExposureMask | KeyPressMask |
1853  KeyReleaseMask | LeaveWindowMask | OwnerGrabButtonMask |
1854  StructureNotifyMask;
1855  manager_hints->flags=InputHint | StateHint | WindowGroupHint;
1856  manager_hints->input=MagickTrue;
1857  manager_hints->initial_state=NormalState;
1858  manager_hints->window_group=windows->image.id;
1859  XMakeWindow(display,root_window,argv,argc,class_hints,manager_hints,
1860  &windows->widget);
1861  windows->widget.highlight_stipple=XCreateBitmapFromData(display,
1862  windows->widget.id,(char *) HighlightBitmap,HighlightWidth,HighlightHeight);
1863  windows->widget.shadow_stipple=XCreateBitmapFromData(display,
1864  windows->widget.id,(char *) ShadowBitmap,ShadowWidth,ShadowHeight);
1865  (void) XSetTransientForHint(display,windows->widget.id,windows->image.id);
1866  if (display_image->debug != MagickFalse)
1868  "Window id: 0x%lx (widget)",windows->widget.id);
1869  /*
1870  Initialize popup window.
1871  */
1872  XGetWindowInfo(display,visual_info,map_info,pixel,font_info,
1873  resource_info,&windows->popup);
1874  windows->popup.border_width=0;
1875  windows->popup.flags|=PPosition;
1876  windows->popup.attributes.event_mask=ButtonMotionMask | ButtonPressMask |
1877  ButtonReleaseMask | EnterWindowMask | ExposureMask | KeyPressMask |
1878  KeyReleaseMask | LeaveWindowMask | StructureNotifyMask;
1879  manager_hints->flags=InputHint | StateHint | WindowGroupHint;
1880  manager_hints->input=MagickTrue;
1881  manager_hints->initial_state=NormalState;
1882  manager_hints->window_group=windows->image.id;
1883  XMakeWindow(display,root_window,argv,argc,class_hints,manager_hints,
1884  &windows->popup);
1885  windows->popup.highlight_stipple=XCreateBitmapFromData(display,
1886  windows->popup.id,(char *) HighlightBitmap,HighlightWidth,HighlightHeight);
1887  windows->popup.shadow_stipple=XCreateBitmapFromData(display,
1888  windows->popup.id,(char *) ShadowBitmap,ShadowWidth,ShadowHeight);
1889  (void) XSetTransientForHint(display,windows->popup.id,windows->image.id);
1890  if (display_image->debug != MagickFalse)
1892  "Window id: 0x%lx (pop up)",windows->popup.id);
1893  /*
1894  Set out progress and warning handlers.
1895  */
1896  if (warning_handler == (WarningHandler) NULL)
1897  {
1898  warning_handler=resource_info->display_warnings ?
1899  SetErrorHandler(XWarning) : SetErrorHandler((ErrorHandler) NULL);
1900  warning_handler=resource_info->display_warnings ?
1902  }
1903  /*
1904  Initialize X image structure.
1905  */
1906  windows->image.x=0;
1907  windows->image.y=0;
1908  /*
1909  Initialize image pixmaps structure.
1910  */
1911  window_changes.width=(int) windows->image.width;
1912  window_changes.height=(int) windows->image.height;
1913  (void) XReconfigureWMWindow(display,windows->image.id,windows->command.screen,
1914  (unsigned int) (CWWidth | CWHeight),&window_changes);
1915  windows->image.pixmaps=(Pixmap *) AcquireQuantumMemory(number_scenes,
1916  sizeof(*windows->image.pixmaps));
1917  windows->image.matte_pixmaps=(Pixmap *) AcquireQuantumMemory(number_scenes,
1918  sizeof(*windows->image.pixmaps));
1919  if ((windows->image.pixmaps == (Pixmap *) NULL) ||
1920  (windows->image.matte_pixmaps == (Pixmap *) NULL))
1921  ThrowXWindowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed",
1922  images->filename);
1923  if ((windows->image.mapped == MagickFalse) ||
1924  (windows->backdrop.id != (Window) NULL))
1925  (void) XMapWindow(display,windows->image.id);
1926  XSetCursorState(display,windows,MagickTrue);
1927  for (scene=0; scene < (ssize_t) number_scenes; scene++)
1928  {
1929  unsigned int
1930  columns,
1931  rows;
1932 
1933  /*
1934  Create X image.
1935  */
1936  windows->image.pixmap=(Pixmap) NULL;
1937  windows->image.matte_pixmap=(Pixmap) NULL;
1938  if ((resource_info->map_type != (char *) NULL) ||
1939  (visual_info->klass == TrueColor) ||
1940  (visual_info->klass == DirectColor))
1941  if (image_list[scene]->storage_class == PseudoClass)
1942  XGetPixelInfo(display,visual_info,map_info,resource_info,
1943  image_list[scene],windows->image.pixel_info);
1944  columns=(unsigned int) image_list[scene]->columns;
1945  rows=(unsigned int) image_list[scene]->rows;
1946  if ((image_list[scene]->columns != columns) ||
1947  (image_list[scene]->rows != rows))
1948  ThrowXWindowFatalException(XServerFatalError,"UnableToCreateXImage",
1949  image_list[scene]->filename);
1950  status=XMakeImage(display,resource_info,&windows->image,image_list[scene],
1951  columns,rows,exception);
1952  if (status == MagickFalse)
1953  ThrowXWindowFatalException(XServerFatalError,"UnableToCreateXImage",
1954  images->filename);
1955  if (image_list[scene]->debug != MagickFalse)
1956  {
1958  "Image: [%.20g] %s %.20gx%.20g ",(double) image_list[scene]->scene,
1959  image_list[scene]->filename,(double) columns,(double) rows);
1960  if (image_list[scene]->colors != 0)
1961  (void) LogMagickEvent(X11Event,GetMagickModule(),"%.20gc ",(double)
1962  image_list[scene]->colors);
1963  (void) LogMagickEvent(X11Event,GetMagickModule(),"%s",
1964  image_list[scene]->magick);
1965  }
1966  /*
1967  Window name is the base of the filename.
1968  */
1969  if (resource_info->title != (char *) NULL)
1970  {
1971  char
1972  *title;
1973 
1974  title=InterpretImageProperties(resource_info->image_info,
1975  image_list[scene],resource_info->title,exception);
1976  (void) CopyMagickString(windows->image.name,title,MagickPathExtent);
1977  title=DestroyString(title);
1978  }
1979  else
1980  {
1981  p=image_list[scene]->magick_filename+
1982  strlen(image_list[scene]->magick_filename)-1;
1983  while ((p > image_list[scene]->magick_filename) && (*(p-1) != '/'))
1984  p--;
1985  (void) FormatLocaleString(windows->image.name,MagickPathExtent,
1986  "%s: %s[%.20g of %.20g]",MagickPackageName,p,(double) scene+1,
1987  (double) number_scenes);
1988  }
1989  status=XStringListToTextProperty(&windows->image.name,1,&window_name);
1990  if (status != Success)
1991  {
1992  XSetWMName(display,windows->image.id,&window_name);
1993  (void) XFree((void *) window_name.value);
1994  }
1995  windows->image.pixmaps[scene]=windows->image.pixmap;
1996  windows->image.matte_pixmaps[scene]=windows->image.matte_pixmap;
1997  if (scene == 0)
1998  {
1999  event.xexpose.x=0;
2000  event.xexpose.y=0;
2001  event.xexpose.width=(int) image_list[scene]->columns;
2002  event.xexpose.height=(int) image_list[scene]->rows;
2003  XRefreshWindow(display,&windows->image,&event);
2004  (void) XSync(display,MagickFalse);
2005  }
2006  }
2007  XSetCursorState(display,windows,MagickFalse);
2008  if (windows->command.mapped)
2009  (void) XMapRaised(display,windows->command.id);
2010  /*
2011  Respond to events.
2012  */
2013  nexus=NewImageList();
2014  scene=0;
2015  first_scene=0;
2016  iterations=0;
2017  image=image_list[0];
2018  state=(MagickStatusType) (ForwardAnimationState | RepeatAnimationState);
2019  (void) XMagickCommand(display,resource_info,windows,PlayCommand,&images,
2020  &state,exception);
2021  do
2022  {
2023  if (XEventsQueued(display,QueuedAfterFlush) == 0)
2024  if ((state & PlayAnimationState) || (state & StepAnimationState))
2025  {
2027  pause;
2028 
2029  pause=MagickFalse;
2030  delay=1000*image->delay/MagickMax(image->ticks_per_second,1L);
2031  XDelay(display,resource_info->delay*(delay == 0 ? 10 : delay));
2032  if (state & ForwardAnimationState)
2033  {
2034  /*
2035  Forward animation: increment scene number.
2036  */
2037  if (scene < ((ssize_t) number_scenes-1))
2038  scene++;
2039  else
2040  {
2041  iterations++;
2042  if (iterations == (ssize_t) image_list[0]->iterations)
2043  {
2044  iterations=0;
2045  state|=ExitState;
2046  }
2047  if ((state & AutoReverseAnimationState) != 0)
2048  {
2049  state&=(~ForwardAnimationState);
2050  scene--;
2051  }
2052  else
2053  {
2054  if ((state & RepeatAnimationState) == 0)
2055  state&=(~PlayAnimationState);
2056  scene=first_scene;
2057  pause=MagickTrue;
2058  }
2059  }
2060  }
2061  else
2062  {
2063  /*
2064  Reverse animation: decrement scene number.
2065  */
2066  if (scene > first_scene)
2067  scene--;
2068  else
2069  {
2070  iterations++;
2071  if (iterations == (ssize_t) image_list[0]->iterations)
2072  {
2073  iterations=0;
2074  state&=(~RepeatAnimationState);
2075  }
2076  if (state & AutoReverseAnimationState)
2077  {
2078  state|=ForwardAnimationState;
2079  scene=first_scene;
2080  pause=MagickTrue;
2081  }
2082  else
2083  {
2084  if ((state & RepeatAnimationState) == MagickFalse)
2085  state&=(~PlayAnimationState);
2086  scene=(ssize_t) number_scenes-1;
2087  }
2088  }
2089  }
2090  scene=MagickMax(scene,0);
2091  image=image_list[scene];
2092  if ((image != (Image *) NULL) && (image->start_loop != 0))
2093  first_scene=scene;
2094  if ((state & StepAnimationState) ||
2095  (resource_info->title != (char *) NULL))
2096  {
2097  /*
2098  Update window title.
2099  */
2100  p=image_list[scene]->filename+
2101  strlen(image_list[scene]->filename)-1;
2102  while ((p > image_list[scene]->filename) && (*(p-1) != '/'))
2103  p--;
2104  (void) FormatLocaleString(windows->image.name,MagickPathExtent,
2105  "%s: %s[%.20g of %.20g]",MagickPackageName,p,(double)
2106  scene+1,(double) number_scenes);
2107  if (resource_info->title != (char *) NULL)
2108  {
2109  char
2110  *title;
2111 
2112  title=InterpretImageProperties(resource_info->image_info,
2113  image,resource_info->title,exception);
2114  (void) CopyMagickString(windows->image.name,title,
2116  title=DestroyString(title);
2117  }
2118  status=XStringListToTextProperty(&windows->image.name,1,
2119  &window_name);
2120  if (status != Success)
2121  {
2122  XSetWMName(display,windows->image.id,&window_name);
2123  (void) XFree((void *) window_name.value);
2124  }
2125  }
2126  /*
2127  Copy X pixmap to Image window.
2128  */
2129  XGetPixelInfo(display,visual_info,map_info,resource_info,
2130  image_list[scene],windows->image.pixel_info);
2131  windows->image.ximage->width=(int) image->columns;
2132  windows->image.ximage->height=(int) image->rows;
2133  windows->image.pixmap=windows->image.pixmaps[scene];
2134  windows->image.matte_pixmap=windows->image.matte_pixmaps[scene];
2135  event.xexpose.x=0;
2136  event.xexpose.y=0;
2137  event.xexpose.width=(int) image->columns;
2138  event.xexpose.height=(int) image->rows;
2139  if ((state & ExitState) == 0)
2140  {
2141  XRefreshWindow(display,&windows->image,&event);
2142  (void) XSync(display,MagickFalse);
2143  }
2144  state&=(~StepAnimationState);
2145  if (pause != MagickFalse)
2146  for (i=0; i < (ssize_t) resource_info->pause; i++)
2147  {
2148  int
2149  status;
2150 
2151  status=XCheckTypedWindowEvent(display,windows->image.id,KeyPress,
2152  &event);
2153  if (status != 0)
2154  {
2155  int
2156  length;
2157 
2158  length=XLookupString((XKeyEvent *) &event.xkey,command,(int)
2159  sizeof(command),&key_symbol,(XComposeStatus *) NULL);
2160  *(command+length)='\0';
2161  if ((key_symbol == XK_q) || (key_symbol == XK_Escape))
2162  {
2163  XClientMessage(display,windows->image.id,
2164  windows->im_protocols,windows->im_exit,CurrentTime);
2165  break;
2166  }
2167  }
2168  MagickDelay(1000);
2169  }
2170  continue;
2171  }
2172  /*
2173  Handle a window event.
2174  */
2175  timestamp=time((time_t *) NULL);
2176  (void) XNextEvent(display,&event);
2177  if (windows->image.stasis == MagickFalse)
2178  windows->image.stasis=(time((time_t *) NULL)-timestamp) > 0 ?
2180  if (event.xany.window == windows->command.id)
2181  {
2182  int
2183  id;
2184 
2185  /*
2186  Select a command from the Command widget.
2187  */
2188  id=XCommandWidget(display,windows,CommandMenu,&event);
2189  if (id < 0)
2190  continue;
2191  (void) CopyMagickString(command,CommandMenu[id],MagickPathExtent);
2192  command_type=CommandMenus[id];
2193  if (id < MagickMenus)
2194  {
2195  int
2196  entry;
2197 
2198  /*
2199  Select a command from a pop-up menu.
2200  */
2201  entry=XMenuWidget(display,windows,CommandMenu[id],Menus[id],
2202  command);
2203  if (entry < 0)
2204  continue;
2205  (void) CopyMagickString(command,Menus[id][entry],MagickPathExtent);
2206  command_type=Commands[id][entry];
2207  }
2208  if (command_type != NullCommand)
2209  nexus=XMagickCommand(display,resource_info,windows,
2210  command_type,&image,&state,exception);
2211  continue;
2212  }
2213  switch (event.type)
2214  {
2215  case ButtonPress:
2216  {
2217  if (display_image->debug != MagickFalse)
2219  "Button Press: 0x%lx %u +%d+%d",event.xbutton.window,
2220  event.xbutton.button,event.xbutton.x,event.xbutton.y);
2221  if ((event.xbutton.button == Button3) &&
2222  (event.xbutton.state & Mod1Mask))
2223  {
2224  /*
2225  Convert Alt-Button3 to Button2.
2226  */
2227  event.xbutton.button=Button2;
2228  event.xbutton.state&=(~Mod1Mask);
2229  }
2230  if (event.xbutton.window == windows->backdrop.id)
2231  {
2232  (void) XSetInputFocus(display,event.xbutton.window,RevertToParent,
2233  event.xbutton.time);
2234  break;
2235  }
2236  if (event.xbutton.window == windows->image.id)
2237  {
2238  if (resource_info->immutable != MagickFalse)
2239  {
2240  state|=ExitState;
2241  break;
2242  }
2243  /*
2244  Map/unmap Command widget.
2245  */
2246  if (windows->command.mapped)
2247  (void) XWithdrawWindow(display,windows->command.id,
2248  windows->command.screen);
2249  else
2250  {
2251  (void) XCommandWidget(display,windows,CommandMenu,
2252  (XEvent *) NULL);
2253  (void) XMapRaised(display,windows->command.id);
2254  }
2255  }
2256  break;
2257  }
2258  case ButtonRelease:
2259  {
2260  if (display_image->debug != MagickFalse)
2262  "Button Release: 0x%lx %u +%d+%d",event.xbutton.window,
2263  event.xbutton.button,event.xbutton.x,event.xbutton.y);
2264  break;
2265  }
2266  case ClientMessage:
2267  {
2268  if (display_image->debug != MagickFalse)
2270  "Client Message: 0x%lx 0x%lx %d 0x%lx",(unsigned long)
2271  event.xclient.window,(unsigned long) event.xclient.message_type,
2272  event.xclient.format,(unsigned long) event.xclient.data.l[0]);
2273  if (event.xclient.message_type == windows->im_protocols)
2274  {
2275  if (*event.xclient.data.l == (long) windows->im_update_colormap)
2276  {
2277  /*
2278  Update graphic context and window colormap.
2279  */
2280  for (i=0; i < (ssize_t) number_windows; i++)
2281  {
2282  if (magick_windows[i]->id == windows->icon.id)
2283  continue;
2284  context_values.background=pixel->background_color.pixel;
2285  context_values.foreground=pixel->foreground_color.pixel;
2286  (void) XChangeGC(display,magick_windows[i]->annotate_context,
2287  context_mask,&context_values);
2288  (void) XChangeGC(display,magick_windows[i]->widget_context,
2289  context_mask,&context_values);
2290  context_values.background=pixel->foreground_color.pixel;
2291  context_values.foreground=pixel->background_color.pixel;
2292  context_values.plane_mask=
2293  context_values.background ^ context_values.foreground;
2294  (void) XChangeGC(display,magick_windows[i]->highlight_context,
2295  (size_t) (context_mask | GCPlaneMask),
2296  &context_values);
2297  magick_windows[i]->attributes.background_pixel=
2298  pixel->background_color.pixel;
2299  magick_windows[i]->attributes.border_pixel=
2300  pixel->border_color.pixel;
2301  magick_windows[i]->attributes.colormap=map_info->colormap;
2302  (void) XChangeWindowAttributes(display,magick_windows[i]->id,
2303  (unsigned long) magick_windows[i]->mask,
2304  &magick_windows[i]->attributes);
2305  }
2306  if (windows->backdrop.id != (Window) NULL)
2307  (void) XInstallColormap(display,map_info->colormap);
2308  break;
2309  }
2310  if (*event.xclient.data.l == (long) windows->im_exit)
2311  {
2312  state|=ExitState;
2313  break;
2314  }
2315  break;
2316  }
2317  if (event.xclient.message_type == windows->dnd_protocols)
2318  {
2319  Atom
2320  selection,
2321  type;
2322 
2323  int
2324  format,
2325  status;
2326 
2327  unsigned char
2328  *data;
2329 
2330  unsigned long
2331  after,
2332  length;
2333 
2334  /*
2335  Display image named by the Drag-and-Drop selection.
2336  */
2337  if ((*event.xclient.data.l != 2) && (*event.xclient.data.l != 128))
2338  break;
2339  selection=XInternAtom(display,"DndSelection",MagickFalse);
2340  status=XGetWindowProperty(display,root_window,selection,0L,2047L,
2341  MagickFalse,(Atom) AnyPropertyType,&type,&format,&length,&after,
2342  &data);
2343  if ((status != Success) || (length == 0))
2344  break;
2345  if (*event.xclient.data.l == 2)
2346  {
2347  /*
2348  Offix DND.
2349  */
2350  (void) CopyMagickString(resource_info->image_info->filename,
2351  (char *) data,MagickPathExtent);
2352  }
2353  else
2354  {
2355  /*
2356  XDND.
2357  */
2358  if (LocaleNCompare((char *) data,"file:",5) != 0)
2359  {
2360  (void) XFree((void *) data);
2361  break;
2362  }
2363  (void) CopyMagickString(resource_info->image_info->filename,
2364  ((char *) data)+5,MagickPathExtent);
2365  }
2366  nexus=ReadImage(resource_info->image_info,exception);
2367  CatchException(exception);
2368  if (nexus != (Image *) NULL)
2369  state|=ExitState;
2370  (void) XFree((void *) data);
2371  break;
2372  }
2373  /*
2374  If client window delete message, exit.
2375  */
2376  if (event.xclient.message_type != windows->wm_protocols)
2377  break;
2378  if (*event.xclient.data.l == (long) windows->wm_take_focus)
2379  {
2380  (void) XSetInputFocus(display,event.xclient.window,RevertToParent,
2381  (Time) event.xclient.data.l[1]);
2382  break;
2383  }
2384  if (*event.xclient.data.l != (long) windows->wm_delete_window)
2385  break;
2386  (void) XWithdrawWindow(display,event.xclient.window,
2387  visual_info->screen);
2388  if (event.xclient.window == windows->image.id)
2389  {
2390  state|=ExitState;
2391  break;
2392  }
2393  break;
2394  }
2395  case ConfigureNotify:
2396  {
2397  if (display_image->debug != MagickFalse)
2399  "Configure Notify: 0x%lx %dx%d+%d+%d %d",event.xconfigure.window,
2400  event.xconfigure.width,event.xconfigure.height,event.xconfigure.x,
2401  event.xconfigure.y,event.xconfigure.send_event);
2402  if (event.xconfigure.window == windows->image.id)
2403  {
2404  if (event.xconfigure.send_event != 0)
2405  {
2406  XWindowChanges
2407  window_changes;
2408 
2409  /*
2410  Position the transient windows relative of the Image window.
2411  */
2412  if (windows->command.geometry == (char *) NULL)
2413  if (windows->command.mapped == MagickFalse)
2414  {
2415  windows->command.x=
2416  event.xconfigure.x-windows->command.width-25;
2417  windows->command.y=event.xconfigure.y;
2418  XConstrainWindowPosition(display,&windows->command);
2419  window_changes.x=windows->command.x;
2420  window_changes.y=windows->command.y;
2421  (void) XReconfigureWMWindow(display,windows->command.id,
2422  windows->command.screen,(unsigned int) (CWX | CWY),
2423  &window_changes);
2424  }
2425  if (windows->widget.geometry == (char *) NULL)
2426  if (windows->widget.mapped == MagickFalse)
2427  {
2428  windows->widget.x=
2429  event.xconfigure.x+event.xconfigure.width/10;
2430  windows->widget.y=
2431  event.xconfigure.y+event.xconfigure.height/10;
2432  XConstrainWindowPosition(display,&windows->widget);
2433  window_changes.x=windows->widget.x;
2434  window_changes.y=windows->widget.y;
2435  (void) XReconfigureWMWindow(display,windows->widget.id,
2436  windows->widget.screen,(unsigned int) (CWX | CWY),
2437  &window_changes);
2438  }
2439  }
2440  /*
2441  Image window has a new configuration.
2442  */
2443  windows->image.width=(unsigned int) event.xconfigure.width;
2444  windows->image.height=(unsigned int) event.xconfigure.height;
2445  break;
2446  }
2447  if (event.xconfigure.window == windows->icon.id)
2448  {
2449  /*
2450  Icon window has a new configuration.
2451  */
2452  windows->icon.width=(unsigned int) event.xconfigure.width;
2453  windows->icon.height=(unsigned int) event.xconfigure.height;
2454  break;
2455  }
2456  break;
2457  }
2458  case DestroyNotify:
2459  {
2460  /*
2461  Group leader has exited.
2462  */
2463  if (display_image->debug != MagickFalse)
2465  "Destroy Notify: 0x%lx",event.xdestroywindow.window);
2466  if (event.xdestroywindow.window == windows->group_leader.id)
2467  {
2468  state|=ExitState;
2469  break;
2470  }
2471  break;
2472  }
2473  case EnterNotify:
2474  {
2475  /*
2476  Selectively install colormap.
2477  */
2478  if (map_info->colormap != XDefaultColormap(display,visual_info->screen))
2479  if (event.xcrossing.mode != NotifyUngrab)
2480  XInstallColormap(display,map_info->colormap);
2481  break;
2482  }
2483  case Expose:
2484  {
2485  if (display_image->debug != MagickFalse)
2487  "Expose: 0x%lx %dx%d+%d+%d",event.xexpose.window,
2488  event.xexpose.width,event.xexpose.height,event.xexpose.x,
2489  event.xexpose.y);
2490  /*
2491  Repaint windows that are now exposed.
2492  */
2493  if (event.xexpose.window == windows->image.id)
2494  {
2495  windows->image.pixmap=windows->image.pixmaps[scene];
2496  windows->image.matte_pixmap=windows->image.matte_pixmaps[scene];
2497  XRefreshWindow(display,&windows->image,&event);
2498  break;
2499  }
2500  if (event.xexpose.window == windows->icon.id)
2501  if (event.xexpose.count == 0)
2502  {
2503  XRefreshWindow(display,&windows->icon,&event);
2504  break;
2505  }
2506  break;
2507  }
2508  case KeyPress:
2509  {
2510  static int
2511  length;
2512 
2513  /*
2514  Respond to a user key press.
2515  */
2516  length=XLookupString((XKeyEvent *) &event.xkey,command,(int)
2517  sizeof(command),&key_symbol,(XComposeStatus *) NULL);
2518  *(command+length)='\0';
2519  if (display_image->debug != MagickFalse)
2521  "Key press: 0x%lx (%c)",(unsigned long) key_symbol,*command);
2522  command_type=NullCommand;
2523  switch (key_symbol)
2524  {
2525  case XK_o:
2526  {
2527  if ((event.xkey.state & ControlMask) == MagickFalse)
2528  break;
2529  command_type=OpenCommand;
2530  break;
2531  }
2532  case XK_BackSpace:
2533  {
2534  command_type=StepBackwardCommand;
2535  break;
2536  }
2537  case XK_space:
2538  {
2539  command_type=StepForwardCommand;
2540  break;
2541  }
2542  case XK_less:
2543  {
2544  command_type=FasterCommand;
2545  break;
2546  }
2547  case XK_greater:
2548  {
2549  command_type=SlowerCommand;
2550  break;
2551  }
2552  case XK_F1:
2553  {
2554  command_type=HelpCommand;
2555  break;
2556  }
2557  case XK_Find:
2558  {
2559  command_type=BrowseDocumentationCommand;
2560  break;
2561  }
2562  case XK_question:
2563  {
2564  command_type=InfoCommand;
2565  break;
2566  }
2567  case XK_q:
2568  case XK_Escape:
2569  {
2570  command_type=QuitCommand;
2571  break;
2572  }
2573  default:
2574  break;
2575  }
2576  if (command_type != NullCommand)
2577  nexus=XMagickCommand(display,resource_info,windows,
2578  command_type,&image,&state,exception);
2579  break;
2580  }
2581  case KeyRelease:
2582  {
2583  /*
2584  Respond to a user key release.
2585  */
2586  (void) XLookupString((XKeyEvent *) &event.xkey,command,(int)
2587  sizeof(command),&key_symbol,(XComposeStatus *) NULL);
2588  if (display_image->debug != MagickFalse)
2590  "Key release: 0x%lx (%c)",(unsigned long) key_symbol,*command);
2591  break;
2592  }
2593  case LeaveNotify:
2594  {
2595  /*
2596  Selectively uninstall colormap.
2597  */
2598  if (map_info->colormap != XDefaultColormap(display,visual_info->screen))
2599  if (event.xcrossing.mode != NotifyUngrab)
2600  XUninstallColormap(display,map_info->colormap);
2601  break;
2602  }
2603  case MapNotify:
2604  {
2605  if (display_image->debug != MagickFalse)
2606  (void) LogMagickEvent(X11Event,GetMagickModule(),"Map Notify: 0x%lx",
2607  event.xmap.window);
2608  if (event.xmap.window == windows->backdrop.id)
2609  {
2610  (void) XSetInputFocus(display,event.xmap.window,RevertToParent,
2611  CurrentTime);
2612  windows->backdrop.mapped=MagickTrue;
2613  break;
2614  }
2615  if (event.xmap.window == windows->image.id)
2616  {
2617  if (windows->backdrop.id != (Window) NULL)
2618  (void) XInstallColormap(display,map_info->colormap);
2619  if (LocaleCompare(image_list[0]->magick,"LOGO") == 0)
2620  {
2621  if (LocaleCompare(display_image->filename,"LOGO") == 0)
2622  nexus=XMagickCommand(display,resource_info,windows,
2623  OpenCommand,&image,&state,exception);
2624  else
2625  state|=ExitState;
2626  }
2627  windows->image.mapped=MagickTrue;
2628  break;
2629  }
2630  if (event.xmap.window == windows->info.id)
2631  {
2632  windows->info.mapped=MagickTrue;
2633  break;
2634  }
2635  if (event.xmap.window == windows->icon.id)
2636  {
2637  /*
2638  Create an icon image.
2639  */
2640  XMakeStandardColormap(display,icon_visual,icon_resources,
2641  display_image,icon_map,icon_pixel,exception);
2642  (void) XMakeImage(display,icon_resources,&windows->icon,
2643  display_image,windows->icon.width,windows->icon.height,
2644  exception);
2645  (void) XSetWindowBackgroundPixmap(display,windows->icon.id,
2646  windows->icon.pixmap);
2647  (void) XClearWindow(display,windows->icon.id);
2648  (void) XWithdrawWindow(display,windows->info.id,
2649  windows->info.screen);
2650  windows->icon.mapped=MagickTrue;
2651  break;
2652  }
2653  if (event.xmap.window == windows->command.id)
2654  {
2655  windows->command.mapped=MagickTrue;
2656  break;
2657  }
2658  if (event.xmap.window == windows->popup.id)
2659  {
2660  windows->popup.mapped=MagickTrue;
2661  break;
2662  }
2663  if (event.xmap.window == windows->widget.id)
2664  {
2665  windows->widget.mapped=MagickTrue;
2666  break;
2667  }
2668  break;
2669  }
2670  case MappingNotify:
2671  {
2672  (void) XRefreshKeyboardMapping(&event.xmapping);
2673  break;
2674  }
2675  case NoExpose:
2676  break;
2677  case PropertyNotify:
2678  {
2679  Atom
2680  type;
2681 
2682  int
2683  format,
2684  status;
2685 
2686  unsigned char
2687  *data;
2688 
2689  unsigned long
2690  after,
2691  length;
2692 
2693  if (display_image->debug != MagickFalse)
2695  "Property Notify: 0x%lx 0x%lx %d",(unsigned long)
2696  event.xproperty.window,(unsigned long) event.xproperty.atom,
2697  event.xproperty.state);
2698  if (event.xproperty.atom != windows->im_remote_command)
2699  break;
2700  /*
2701  Display image named by the remote command protocol.
2702  */
2703  status=XGetWindowProperty(display,event.xproperty.window,
2704  event.xproperty.atom,0L,(long) MagickPathExtent,MagickFalse,(Atom)
2705  AnyPropertyType,&type,&format,&length,&after,&data);
2706  if ((status != Success) || (length == 0))
2707  break;
2708  (void) CopyMagickString(resource_info->image_info->filename,
2709  (char *) data,MagickPathExtent);
2710  nexus=ReadImage(resource_info->image_info,exception);
2711  CatchException(exception);
2712  if (nexus != (Image *) NULL)
2713  state|=ExitState;
2714  (void) XFree((void *) data);
2715  break;
2716  }
2717  case ReparentNotify:
2718  {
2719  if (display_image->debug != MagickFalse)
2721  "Reparent Notify: 0x%lx=>0x%lx",event.xreparent.parent,
2722  event.xreparent.window);
2723  break;
2724  }
2725  case UnmapNotify:
2726  {
2727  if (display_image->debug != MagickFalse)
2729  "Unmap Notify: 0x%lx",event.xunmap.window);
2730  if (event.xunmap.window == windows->backdrop.id)
2731  {
2732  windows->backdrop.mapped=MagickFalse;
2733  break;
2734  }
2735  if (event.xunmap.window == windows->image.id)
2736  {
2737  windows->image.mapped=MagickFalse;
2738  break;
2739  }
2740  if (event.xunmap.window == windows->info.id)
2741  {
2742  windows->info.mapped=MagickFalse;
2743  break;
2744  }
2745  if (event.xunmap.window == windows->icon.id)
2746  {
2747  if (map_info->colormap == icon_map->colormap)
2748  XConfigureImageColormap(display,resource_info,windows,
2749  display_image,exception);
2750  (void) XFreeStandardColormap(display,icon_visual,icon_map,
2751  icon_pixel);
2752  windows->icon.mapped=MagickFalse;
2753  break;
2754  }
2755  if (event.xunmap.window == windows->command.id)
2756  {
2757  windows->command.mapped=MagickFalse;
2758  break;
2759  }
2760  if (event.xunmap.window == windows->popup.id)
2761  {
2762  if (windows->backdrop.id != (Window) NULL)
2763  (void) XSetInputFocus(display,windows->image.id,RevertToParent,
2764  CurrentTime);
2765  windows->popup.mapped=MagickFalse;
2766  break;
2767  }
2768  if (event.xunmap.window == windows->widget.id)
2769  {
2770  if (windows->backdrop.id != (Window) NULL)
2771  (void) XSetInputFocus(display,windows->image.id,RevertToParent,
2772  CurrentTime);
2773  windows->widget.mapped=MagickFalse;
2774  break;
2775  }
2776  break;
2777  }
2778  default:
2779  {
2780  if (display_image->debug != MagickFalse)
2781  (void) LogMagickEvent(X11Event,GetMagickModule(),"Event type: %d",
2782  event.type);
2783  break;
2784  }
2785  }
2786  }
2787  while (!(state & ExitState));
2788  image_list=(Image **) RelinquishMagickMemory(image_list);
2789  images=DestroyImageList(images);
2790  if ((windows->visual_info->klass == GrayScale) ||
2791  (windows->visual_info->klass == PseudoColor) ||
2792  (windows->visual_info->klass == DirectColor))
2793  {
2794  /*
2795  Withdraw windows.
2796  */
2797  if (windows->info.mapped)
2798  (void) XWithdrawWindow(display,windows->info.id,windows->info.screen);
2799  if (windows->command.mapped)
2800  (void) XWithdrawWindow(display,windows->command.id,
2801  windows->command.screen);
2802  }
2803  if (resource_info->backdrop == MagickFalse)
2804  if (windows->backdrop.mapped)
2805  {
2806  (void) XWithdrawWindow(display,windows->backdrop.id,\
2807  windows->backdrop.screen);
2808  (void) XDestroyWindow(display,windows->backdrop.id);
2809  windows->backdrop.id=(Window) NULL;
2810  (void) XWithdrawWindow(display,windows->image.id,windows->image.screen);
2811  (void) XDestroyWindow(display,windows->image.id);
2812  windows->image.id=(Window) NULL;
2813  }
2814  XSetCursorState(display,windows,MagickTrue);
2815  XCheckRefreshWindows(display,windows);
2816  for (scene=1; scene < (ssize_t) number_scenes; scene++)
2817  {
2818  if (windows->image.pixmaps[scene] != (Pixmap) NULL)
2819  (void) XFreePixmap(display,windows->image.pixmaps[scene]);
2820  windows->image.pixmaps[scene]=(Pixmap) NULL;
2821  if (windows->image.matte_pixmaps[scene] != (Pixmap) NULL)
2822  (void) XFreePixmap(display,windows->image.matte_pixmaps[scene]);
2823  windows->image.matte_pixmaps[scene]=(Pixmap) NULL;
2824  }
2825  XSetCursorState(display,windows,MagickFalse);
2826  windows->image.pixmaps=(Pixmap *)
2827  RelinquishMagickMemory(windows->image.pixmaps);
2828  windows->image.matte_pixmaps=(Pixmap *)
2829  RelinquishMagickMemory(windows->image.matte_pixmaps);
2830  if (nexus == (Image *) NULL)
2831  {
2832  /*
2833  Free X resources.
2834  */
2835  if (windows->image.mapped != MagickFalse)
2836  (void) XWithdrawWindow(display,windows->image.id,windows->image.screen);
2837  XDelay(display,SuspendTime);
2838  (void) XFreeStandardColormap(display,icon_visual,icon_map,icon_pixel);
2839  if (resource_info->map_type == (char *) NULL)
2840  (void) XFreeStandardColormap(display,visual_info,map_info,pixel);
2841  DestroyXResources();
2842  }
2843  (void) XSync(display,MagickFalse);
2844  /*
2845  Restore our progress monitor and warning handlers.
2846  */
2849  /*
2850  Change to home directory.
2851  */
2852  directory=getcwd(working_directory,MagickPathExtent);
2853  (void) directory;
2854  if (*resource_info->home_directory == '\0')
2855  (void) CopyMagickString(resource_info->home_directory,".",MagickPathExtent);
2856  status=chdir(resource_info->home_directory);
2857  if (status == -1)
2859  "UnableToOpenFile","%s",resource_info->home_directory);
2860  return(nexus);
2861 }
2862 
2863 /*
2864 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2865 % %
2866 % %
2867 % %
2868 + X S a v e I m a g e %
2869 % %
2870 % %
2871 % %
2872 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2873 %
2874 % XSaveImage() saves an image to a file.
2875 %
2876 % The format of the XSaveImage method is:
2877 %
2878 % MagickBooleanType XSaveImage(Display *display,
2879 % XResourceInfo *resource_info,XWindows *windows,Image *image,
2880 % ExceptionInfo *exception)
2881 %
2882 % A description of each parameter follows:
2883 %
2884 % o status: Method XSaveImage return True if the image is
2885 % written. False is returned is there is a memory shortage or if the
2886 % image fails to write.
2887 %
2888 % o display: Specifies a connection to an X server; returned from
2889 % XOpenDisplay.
2890 %
2891 % o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
2892 %
2893 % o windows: Specifies a pointer to a XWindows structure.
2894 %
2895 % o image: the image.
2896 %
2897 */
2898 static MagickBooleanType XSaveImage(Display *display,
2899  XResourceInfo *resource_info,XWindows *windows,Image *image,
2900  ExceptionInfo *exception)
2901 {
2902  char
2903  filename[MagickPathExtent];
2904 
2905  ImageInfo
2906  *image_info;
2907 
2909  status;
2910 
2911  /*
2912  Request file name from user.
2913  */
2914  if (resource_info->write_filename != (char *) NULL)
2915  (void) CopyMagickString(filename,resource_info->write_filename,
2917  else
2918  {
2919  char
2920  path[MagickPathExtent];
2921 
2922  int
2923  status;
2924 
2925  GetPathComponent(image->filename,HeadPath,path);
2926  GetPathComponent(image->filename,TailPath,filename);
2927  if (*path == '\0')
2928  (void) CopyMagickString(path,".",MagickPathExtent);
2929  status=chdir(path);
2930  if (status == -1)
2932  "UnableToOpenFile","%s",path);
2933  }
2934  XFileBrowserWidget(display,windows,"Save",filename);
2935  if (*filename == '\0')
2936  return(MagickTrue);
2937  if (IsPathAccessible(filename) != MagickFalse)
2938  {
2939  int
2940  status;
2941 
2942  /*
2943  File exists-- seek user's permission before overwriting.
2944  */
2945  status=XConfirmWidget(display,windows,"Overwrite",filename);
2946  if (status == 0)
2947  return(MagickTrue);
2948  }
2949  image_info=CloneImageInfo(resource_info->image_info);
2950  (void) CopyMagickString(image_info->filename,filename,MagickPathExtent);
2951  (void) SetImageInfo(image_info,1,exception);
2952  if ((LocaleCompare(image_info->magick,"JPEG") == 0) ||
2953  (LocaleCompare(image_info->magick,"JPG") == 0))
2954  {
2955  char
2956  quality[MagickPathExtent];
2957 
2958  int
2959  status;
2960 
2961  /*
2962  Request JPEG quality from user.
2963  */
2964  (void) FormatLocaleString(quality,MagickPathExtent,"%.20g",(double)
2965  image_info->quality);
2966  status=XDialogWidget(display,windows,"Save","Enter JPEG quality:",
2967  quality);
2968  if (*quality == '\0')
2969  return(MagickTrue);
2970  image->quality=StringToUnsignedLong(quality);
2971  image_info->interlace=status != MagickFalse ? NoInterlace :
2973  }
2974  if ((LocaleCompare(image_info->magick,"EPS") == 0) ||
2975  (LocaleCompare(image_info->magick,"PDF") == 0) ||
2976  (LocaleCompare(image_info->magick,"PS") == 0) ||
2977  (LocaleCompare(image_info->magick,"PS2") == 0))
2978  {
2979  char
2980  geometry[MagickPathExtent];
2981 
2982  /*
2983  Request page geometry from user.
2984  */
2986  if (LocaleCompare(image_info->magick,"PDF") == 0)
2988  if (image_info->page != (char *) NULL)
2989  (void) CopyMagickString(geometry,image_info->page,MagickPathExtent);
2990  XListBrowserWidget(display,windows,&windows->widget,PageSizes,"Select",
2991  "Select page geometry:",geometry);
2992  if (*geometry != '\0')
2993  image_info->page=GetPageGeometry(geometry);
2994  }
2995  /*
2996  Write image.
2997  */
2998  image=GetFirstImageInList(image);
2999  status=WriteImages(image_info,image,filename,exception);
3000  if (status != MagickFalse)
3001  image->taint=MagickFalse;
3002  image_info=DestroyImageInfo(image_info);
3003  XSetCursorState(display,windows,MagickFalse);
3004  return(status != 0 ? MagickTrue : MagickFalse);
3005 }
3006 #else
3007 
3008 /*
3009 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3010 % %
3011 % %
3012 % %
3013 + A n i m a t e I m a g e s %
3014 % %
3015 % %
3016 % %
3017 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3018 %
3019 % AnimateImages() repeatedly displays an image sequence to any X window
3020 % screen. It returns a value other than 0 if successful. Check the
3021 % exception member of image to determine the reason for any failure.
3022 %
3023 % The format of the AnimateImages method is:
3024 %
3025 % MagickBooleanType AnimateImages(const ImageInfo *image_info,
3026 % Image *images)
3027 %
3028 % A description of each parameter follows:
3029 %
3030 % o image_info: the image info.
3031 %
3032 % o image: the image.
3033 %
3034 % o exception: return any errors or warnings in this structure.
3035 %
3036 */
3038  Image *image,ExceptionInfo *exception)
3039 {
3040  assert(image_info != (const ImageInfo *) NULL);
3041  assert(image_info->signature == MagickCoreSignature);
3042  (void) image_info;
3043  assert(image != (Image *) NULL);
3044  assert(image->signature == MagickCoreSignature);
3045  if (image->debug != MagickFalse)
3046  (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
3048  "DelegateLibrarySupportNotBuiltIn","'%s' (X11)",image->filename);
3049  return(MagickFalse);
3050 }
3051 #endif
size_t rows
Definition: image.h:172
MagickExport Image * CoalesceImages(const Image *image, ExceptionInfo *exception)
Definition: layer.c:229
size_t signature
Definition: image.h:488
static MagickBooleanType SetImageProgress(const Image *image, const char *tag, const MagickOffsetType offset, const MagickSizeType extent)
PixelInfo * colormap
Definition: image.h:179
char magick[MagickPathExtent]
Definition: image.h:480
size_t iterations
Definition: image.h:248
ssize_t ticks_per_second
Definition: image.h:245
#define XWMGeometry
Definition: vms.h:334
static unsigned long StringToUnsignedLong(const char *magick_restrict value)
#define XInternAtom
Definition: vms.h:189
Definition: log.h:56
MagickBooleanType taint
Definition: image.h:169
static ResourceInfo resource_info
Definition: resource.c:114
#define MagickPackageName
Definition: version.h:28
MagickExport WarningHandler SetWarningHandler(WarningHandler handler)
Definition: exception.c:880
#define XDisplayName
Definition: vms.h:106
#define XChangeWindowAttributes
Definition: vms.h:60
MagickExport MagickStatusType ParseMetaGeometry(const char *geometry, ssize_t *x, ssize_t *y, size_t *width, size_t *height)
Definition: geometry.c:1340
#define XCheckTypedWindowEvent
Definition: vms.h:63
MagickExport char * GetMagickHomeURL(void)
Definition: version.c:277
#define XPutImage
Definition: vms.h:228
#define XSetTransientForHint
Definition: vms.h:292
MagickExport const char LoadImageTag[]
Definition: image.c:116
MagickExport MagickBooleanType AnimateImages(const ImageInfo *image_info, Image *image, ExceptionInfo *exception)
Definition: animate.c:3037
MagickExport ssize_t FormatLocaleString(char *magick_restrict string, const size_t length, const char *magick_restrict format,...)
Definition: locale.c:504
size_t delay
Definition: image.h:240
char magick[MagickPathExtent]
Definition: image.h:319
MagickExport char * GetPageGeometry(const char *page_geometry)
Definition: geometry.c:361
#define XFreePixmap
Definition: vms.h:150
#define XVisualIDFromVisual
Definition: vms.h:333
InterlaceType interlace
Definition: image.h:401
ClassType storage_class
Definition: image.h:154
#define XDefaultScreen
Definition: vms.h:94
size_t width
Definition: geometry.h:130
Definition: log.h:52
static MagickBooleanType IsPixelInfoEquivalent(const PixelInfo *magick_restrict p, const PixelInfo *magick_restrict q)
Definition: image.h:151
#define XSync
Definition: vms.h:315
#define XCreatePixmap
Definition: vms.h:83
#define XAllocStandardColormap
Definition: vms.h:46
#define MagickCoreSignature
MagickExport MagickBooleanType SetImageType(Image *image, const ImageType type, ExceptionInfo *exception)
Definition: attribute.c:1201
MagickExport Image * GetFirstImageInList(const Image *images)
Definition: list.c:545
#define XDisplayHeight
Definition: vms.h:105
MagickExport MagickBooleanType RemapImages(const QuantizeInfo *quantize_info, Image *images, const Image *remap_image, ExceptionInfo *exception)
Definition: quantize.c:3205
#define XSetInputFocus
Definition: vms.h:278
MagickExport void GetPathComponent(const char *path, PathType type, char *component)
Definition: utility.c:1213
static WarningHandler warning_handler
Definition: exception.c:88
MagickBooleanType
Definition: magick-type.h:156
MagickExport Image * NewImageList(void)
Definition: list.c:922
size_t scene
Definition: image.h:240
unsigned int MagickStatusType
Definition: magick-type.h:119
MagickExport char * AcquireString(const char *source)
Definition: string.c:129
#define XReconfigureWMWindow
Definition: vms.h:240
MagickExport ErrorHandler SetErrorHandler(ErrorHandler handler)
Definition: exception.c:814
char * reason
Definition: exception.h:110
#define XFillRectangle
Definition: vms.h:132
#define XChangeProperty
Definition: vms.h:59
MagickExport void * AcquireQuantumMemory(const size_t count, const size_t quantum)
Definition: memory.c:533
char filename[MagickPathExtent]
Definition: image.h:480
MagickExport int LocaleNCompare(const char *p, const char *q, const size_t length)
Definition: locale.c:1540
#define XStringListToTextProperty
Definition: vms.h:311
#define XFree
Definition: vms.h:138
size_t MagickSizeType
Definition: magick-type.h:128
#define MagickPathExtent
MagickExport void MagickDelay(const MagickSizeType milliseconds)
Definition: utility.c:1705
PixelTrait alpha_trait
Definition: image.h:280
#define XSelectInput
Definition: vms.h:256
MagickExport Image * ReadImage(const ImageInfo *image_info, ExceptionInfo *exception)
Definition: constitute.c:358
MagickExport MagickBooleanType SetImageInfo(ImageInfo *image_info, const unsigned int frames, ExceptionInfo *exception)
Definition: image.c:2701
#define XClearWindow
Definition: vms.h:66
char magick_filename[MagickPathExtent]
Definition: image.h:319
MagickExport MagickBooleanType ThrowMagickException(ExceptionInfo *exception, const char *module, const char *function, const size_t line, const ExceptionType severity, const char *tag, const char *format,...)
Definition: exception.c:1064
MagickExport MagickBooleanType LogMagickEvent(const LogEventType type, const char *module, const char *function, const size_t line, const char *format,...)
Definition: log.c:1397
MagickExport MagickBooleanType IsPathAccessible(const char *path)
Definition: utility.c:1468
MagickExport const char * GetMagickVersion(size_t *version)
Definition: version.c:567
size_t signature
Definition: image.h:354
size_t columns
Definition: image.h:172
#define XCreateBitmapFromData
Definition: vms.h:76
ssize_t x
Definition: geometry.h:134
MagickExport const char * GetMagickCopyright(void)
Definition: version.c:75
size_t height
Definition: geometry.h:130
void(* WarningHandler)(const ExceptionType, const char *, const char *)
Definition: exception.h:133
#define XRootWindow
Definition: vms.h:249
MagickExport void CatchException(ExceptionInfo *exception)
Definition: exception.c:196
MagickExport size_t CopyMagickString(char *destination, const char *source, const size_t length)
Definition: string.c:755
MagickExport Image * DestroyImageList(Image *images)
Definition: list.c:446
MagickExport const char * GetClientName(void)
Definition: client.c:64
static int SceneCompare(const void *x, const void *y)
Definition: montage.c:291
#define MagickMax(x, y)
Definition: image-private.h:26
#define XGetWindowAttributes
Definition: vms.h:179
size_t quality
Definition: image.h:163
size_t colors
Definition: image.h:172
#define XAllocSizeHints
Definition: vms.h:45
#define XEventsQueued
Definition: vms.h:126
MagickExport int LocaleCompare(const char *p, const char *q)
Definition: locale.c:1440
char filename[MagickPathExtent]
Definition: image.h:319
#define GetMagickModule()
Definition: log.h:28
MagickExport MagickBooleanType ExpandFilenames(int *number_arguments, char ***arguments)
Definition: utility.c:735
size_t quality
Definition: image.h:410
#define XFreeFont
Definition: vms.h:144
#define XSetWindowBackgroundPixmap
Definition: vms.h:301
#define XDisplayWidth
Definition: vms.h:108
MagickExport Image ** ImageListToArray(const Image *images, ExceptionInfo *exception)
Definition: list.c:828
MagickExport char * InterpretImageProperties(ImageInfo *image_info, Image *image, const char *embed_text, ExceptionInfo *exception)
Definition: property.c:3372
MagickExport ImageInfo * DestroyImageInfo(ImageInfo *image_info)
Definition: image.c:1248
ssize_t start_loop
Definition: image.h:252
#define XGetWindowProperty
Definition: vms.h:180
#define XDefaultColormap
Definition: vms.h:89
char * server_name
Definition: image.h:413
#define XSetErrorHandler
Definition: vms.h:267
MagickExport Image * GetNextImageInList(const Image *images)
Definition: list.c:755
#define XMapWindow
Definition: vms.h:210
MagickExport char * DestroyString(char *string)
Definition: string.c:823
#define XUninstallColormap
Definition: vms.h:327
MagickExport void * AcquireMagickMemory(const size_t size)
Definition: memory.c:462
#define XCloseDisplay
Definition: vms.h:68
#define XWithdrawWindow
Definition: vms.h:339
MagickExport ImageInfo * CloneImageInfo(const ImageInfo *image_info)
Definition: image.c:937
MagickExport void AppendImageToList(Image **images, const Image *append)
Definition: list.c:77
#define XDestroyWindow
Definition: vms.h:102
#define XSetWMName
Definition: vms.h:296
#define XOpenDisplay
Definition: vms.h:218
MagickExport void * RelinquishMagickMemory(void *memory)
Definition: memory.c:1053
#define XFreeGC
Definition: vms.h:148
#define XChangeGC
Definition: vms.h:57
MagickExport char * CloneString(char **destination, const char *source)
Definition: string.c:286
MagickExport MagickBooleanType InvokeDelegate(ImageInfo *image_info, Image *image, const char *decode, const char *encode, ExceptionInfo *exception)
Definition: delegate.c:1623
#define XLookupString
Definition: vms.h:206
#define XInstallColormap
Definition: vms.h:188
#define MagickExport
ssize_t y
Definition: geometry.h:134
#define XMapRaised
Definition: vms.h:208
char * page
Definition: image.h:390
void(* ErrorHandler)(const ExceptionType, const char *, const char *)
Definition: exception.h:127
MagickExport size_t GetImageListLength(const Image *images)
Definition: list.c:680
#define XNextEvent
Definition: vms.h:215
#define XCreateGC
Definition: vms.h:80
char * description
Definition: exception.h:110
#define XRefreshKeyboardMapping
Definition: vms.h:242
MagickExport const char PSPageGeometry[]
Definition: image.c:120
MagickBooleanType debug
Definition: image.h:334
MagickExport MagickBooleanType WriteImages(const ImageInfo *image_info, Image *images, const char *filename, ExceptionInfo *exception)
Definition: constitute.c:1253
ExceptionType severity
Definition: exception.h:104