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