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