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