|
MagickCore
6.7.5
|
00001 /* 00002 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 00003 % % 00004 % % 00005 % % 00006 % AAA N N IIIII M M AAA TTTTT EEEEE % 00007 % A A NN N I MM MM A A T E % 00008 % AAAAA N N N I M M M AAAAA T EEE % 00009 % A A N NN I M M A A T E % 00010 % A A N N IIIII M M A A T EEEEE % 00011 % % 00012 % % 00013 % Methods to Interactively Animate an Image Sequence % 00014 % % 00015 % Software Design % 00016 % John Cristy % 00017 % July 1992 % 00018 % % 00019 % % 00020 % Copyright 1999-2012 ImageMagick Studio LLC, a non-profit organization % 00021 % dedicated to making software imaging solutions freely available. % 00022 % % 00023 % You may not use this file except in compliance with the License. You may % 00024 % obtain a copy of the License at % 00025 % % 00026 % http://www.imagemagick.org/script/license.php % 00027 % % 00028 % Unless required by applicable law or agreed to in writing, software % 00029 % distributed under the License is distributed on an "AS IS" BASIS, % 00030 % WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. % 00031 % See the License for the specific language governing permissions and % 00032 % limitations under the License. % 00033 % % 00034 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 00035 % 00036 % 00037 */ 00038 00039 /* 00040 Include declarations. 00041 */ 00042 #include "MagickCore/studio.h" 00043 #include "MagickCore/animate.h" 00044 #include "MagickCore/animate-private.h" 00045 #include "MagickCore/client.h" 00046 #include "MagickCore/color.h" 00047 #include "MagickCore/color-private.h" 00048 #include "MagickCore/colorspace.h" 00049 #include "MagickCore/constitute.h" 00050 #include "MagickCore/delegate.h" 00051 #include "MagickCore/exception.h" 00052 #include "MagickCore/exception-private.h" 00053 #include "MagickCore/geometry.h" 00054 #include "MagickCore/image-private.h" 00055 #include "MagickCore/layer.h" 00056 #include "MagickCore/list.h" 00057 #include "MagickCore/log.h" 00058 #include "MagickCore/image.h" 00059 #include "MagickCore/memory_.h" 00060 #include "MagickCore/monitor.h" 00061 #include "MagickCore/monitor-private.h" 00062 #include "MagickCore/option.h" 00063 #include "MagickCore/pixel-accessor.h" 00064 #include "MagickCore/property.h" 00065 #include "MagickCore/resource_.h" 00066 #include "MagickCore/string_.h" 00067 #include "MagickCore/string-private.h" 00068 #include "MagickCore/transform.h" 00069 #include "MagickCore/utility.h" 00070 #include "MagickCore/utility-private.h" 00071 #include "MagickCore/version.h" 00072 #include "MagickCore/widget.h" 00073 #include "MagickCore/widget-private.h" 00074 #include "MagickCore/xwindow.h" 00075 #include "MagickCore/xwindow-private.h" 00076 00077 #if defined(MAGICKCORE_X11_DELEGATE) 00078 /* 00079 Animate state declarations. 00080 */ 00081 #define AutoReverseAnimationState 0x0004 00082 #define ForwardAnimationState 0x0008 00083 #define HighlightState 0x0010 00084 #define PlayAnimationState 0x0020 00085 #define RepeatAnimationState 0x0040 00086 #define StepAnimationState 0x0080 00087 00088 /* 00089 Static declarations. 00090 */ 00091 static const char 00092 *AnimateHelp[]= 00093 { 00094 "BUTTONS", 00095 "", 00096 " Press any button to map or unmap the Command widget.", 00097 "", 00098 "COMMAND WIDGET", 00099 " The Command widget lists a number of sub-menus and commands.", 00100 " They are", 00101 "", 00102 " Animate", 00103 " Open...", 00104 " Save...", 00105 " Play", 00106 " Step", 00107 " Repeat", 00108 " Auto Reverse", 00109 " Speed", 00110 " Slower", 00111 " Faster", 00112 " Direction", 00113 " Forward", 00114 " Reverse", 00115 " Help", 00116 " Overview", 00117 " Browse Documentation", 00118 " About Animate", 00119 " Image Info", 00120 " Quit", 00121 "", 00122 " Menu items with a indented triangle have a sub-menu. They", 00123 " are represented above as the indented items. To access a", 00124 " sub-menu item, move the pointer to the appropriate menu and", 00125 " press a button and drag. When you find the desired sub-menu", 00126 " item, release the button and the command is executed. Move", 00127 " the pointer away from the sub-menu if you decide not to", 00128 " execute a particular command.", 00129 "", 00130 "KEYBOARD ACCELERATORS", 00131 " Accelerators are one or two key presses that effect a", 00132 " particular command. The keyboard accelerators that", 00133 " animate(1) understands is:", 00134 "", 00135 " Ctl+O Press to open an image from a file.", 00136 "", 00137 " space Press to display the next image in the sequence.", 00138 "", 00139 " < Press to speed-up the display of the images. Refer to", 00140 " -delay for more information.", 00141 "", 00142 " > Press to slow the display of the images. Refer to", 00143 " -delay for more information.", 00144 "", 00145 " F1 Press to display helpful information about animate(1).", 00146 "", 00147 " Find Press to browse documentation about ImageMagick.", 00148 "", 00149 " ? Press to display information about the image. Press", 00150 " any key or button to erase the information.", 00151 "", 00152 " This information is printed: image name; image size;", 00153 " and the total number of unique colors in the image.", 00154 "", 00155 " Ctl-q Press to discard all images and exit program.", 00156 (char *) NULL 00157 }; 00158 00159 /* 00160 Constant declarations. 00161 */ 00162 static const char 00163 *PageSizes[]= 00164 { 00165 "Letter", 00166 "Tabloid", 00167 "Ledger", 00168 "Legal", 00169 "Statement", 00170 "Executive", 00171 "A3", 00172 "A4", 00173 "A5", 00174 "B4", 00175 "B5", 00176 "Folio", 00177 "Quarto", 00178 "10x14", 00179 (char *) NULL 00180 }; 00181 00182 static const unsigned char 00183 HighlightBitmap[8] = 00184 { 00185 (unsigned char) 0xaa, 00186 (unsigned char) 0x55, 00187 (unsigned char) 0xaa, 00188 (unsigned char) 0x55, 00189 (unsigned char) 0xaa, 00190 (unsigned char) 0x55, 00191 (unsigned char) 0xaa, 00192 (unsigned char) 0x55 00193 }, 00194 ShadowBitmap[8] = 00195 { 00196 (unsigned char) 0x00, 00197 (unsigned char) 0x00, 00198 (unsigned char) 0x00, 00199 (unsigned char) 0x00, 00200 (unsigned char) 0x00, 00201 (unsigned char) 0x00, 00202 (unsigned char) 0x00, 00203 (unsigned char) 0x00 00204 }; 00205 00206 /* 00207 Enumeration declarations. 00208 */ 00209 typedef enum 00210 { 00211 OpenCommand, 00212 SaveCommand, 00213 PlayCommand, 00214 StepCommand, 00215 RepeatCommand, 00216 AutoReverseCommand, 00217 SlowerCommand, 00218 FasterCommand, 00219 ForwardCommand, 00220 ReverseCommand, 00221 HelpCommand, 00222 BrowseDocumentationCommand, 00223 VersionCommand, 00224 InfoCommand, 00225 QuitCommand, 00226 StepBackwardCommand, 00227 StepForwardCommand, 00228 NullCommand 00229 } CommandType; 00230 00231 /* 00232 Stipples. 00233 */ 00234 #define HighlightWidth 8 00235 #define HighlightHeight 8 00236 #define ShadowWidth 8 00237 #define ShadowHeight 8 00238 00239 /* 00240 Forward declarations. 00241 */ 00242 static Image 00243 *XMagickCommand(Display *,XResourceInfo *,XWindows *,const CommandType, 00244 Image **,MagickStatusType *,ExceptionInfo *); 00245 00246 static MagickBooleanType 00247 XSaveImage(Display *,XResourceInfo *,XWindows *,Image *,ExceptionInfo *); 00248 00249 /* 00250 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 00251 % % 00252 % % 00253 % % 00254 % A n i m a t e I m a g e s % 00255 % % 00256 % % 00257 % % 00258 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 00259 % 00260 % AnimateImages() repeatedly displays an image sequence to any X window 00261 % screen. It returns a value other than 0 if successful. Check the 00262 % exception member of image to determine the reason for any failure. 00263 % 00264 % The format of the AnimateImages method is: 00265 % 00266 % MagickBooleanType AnimateImages(const ImageInfo *image_info, 00267 % Image *images,ExceptionInfo *exception) 00268 % 00269 % A description of each parameter follows: 00270 % 00271 % o image_info: the image info. 00272 % 00273 % o image: the image. 00274 % 00275 % o exception: return any errors or warnings in this structure. 00276 % 00277 */ 00278 MagickExport MagickBooleanType AnimateImages(const ImageInfo *image_info, 00279 Image *images,ExceptionInfo *exception) 00280 { 00281 char 00282 *argv[1]; 00283 00284 Display 00285 *display; 00286 00287 MagickStatusType 00288 status; 00289 00290 XrmDatabase 00291 resource_database; 00292 00293 XResourceInfo 00294 resource_info; 00295 00296 assert(image_info != (const ImageInfo *) NULL); 00297 assert(image_info->signature == MagickSignature); 00298 assert(images != (Image *) NULL); 00299 assert(images->signature == MagickSignature); 00300 if (images->debug != MagickFalse) 00301 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",images->filename); 00302 display=XOpenDisplay(image_info->server_name); 00303 if (display == (Display *) NULL) 00304 { 00305 (void) ThrowMagickException(exception,GetMagickModule(),XServerError, 00306 "UnableToOpenXServer","`%s'",XDisplayName(image_info->server_name)); 00307 return(MagickFalse); 00308 } 00309 if (exception->severity != UndefinedException) 00310 CatchException(exception); 00311 (void) XSetErrorHandler(XError); 00312 resource_database=XGetResourceDatabase(display,GetClientName()); 00313 (void) ResetMagickMemory(&resource_info,0,sizeof(XResourceInfo)); 00314 XGetResourceInfo(image_info,resource_database,GetClientName(),&resource_info); 00315 if (image_info->page != (char *) NULL) 00316 resource_info.image_geometry=AcquireString(image_info->page); 00317 resource_info.immutable=MagickTrue; 00318 argv[0]=AcquireString(GetClientName()); 00319 (void) XAnimateImages(display,&resource_info,argv,1,images,exception); 00320 (void) SetErrorHandler((ErrorHandler) NULL); 00321 (void) SetWarningHandler((WarningHandler) NULL); 00322 argv[0]=DestroyString(argv[0]); 00323 (void) XCloseDisplay(display); 00324 XDestroyResourceInfo(&resource_info); 00325 status=exception->severity == UndefinedException ? MagickTrue : MagickFalse; 00326 return(status != 0 ? MagickTrue : MagickFalse); 00327 } 00328 00329 /* 00330 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 00331 % % 00332 % % 00333 % % 00334 + X M a g i c k C o m m a n d % 00335 % % 00336 % % 00337 % % 00338 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 00339 % 00340 % XMagickCommand() makes a transform to the image or Image window as specified 00341 % by a user menu button or keyboard command. 00342 % 00343 % The format of the XMagickCommand method is: 00344 % 00345 % Image *XMagickCommand(Display *display,XResourceInfo *resource_info, 00346 % XWindows *windows,const CommandType command_type,Image **image, 00347 % MagickStatusType *state,ExceptionInfo *exception) 00348 % 00349 % A description of each parameter follows: 00350 % 00351 % o display: Specifies a connection to an X server; returned from 00352 % XOpenDisplay. 00353 % 00354 % o resource_info: Specifies a pointer to a X11 XResourceInfo structure. 00355 % 00356 % o windows: Specifies a pointer to a XWindows structure. 00357 % 00358 % o image: the image; XMagickCommand 00359 % may transform the image and return a new image pointer. 00360 % 00361 % o state: Specifies a MagickStatusType; XMagickCommand may return a 00362 % modified state. 00363 % 00364 % o exception: return any errors or warnings in this structure. 00365 % 00366 % 00367 */ 00368 static Image *XMagickCommand(Display *display,XResourceInfo *resource_info, 00369 XWindows *windows,const CommandType command_type,Image **image, 00370 MagickStatusType *state,ExceptionInfo *exception) 00371 { 00372 Image 00373 *nexus; 00374 00375 MagickBooleanType 00376 proceed; 00377 00378 MagickStatusType 00379 status; 00380 00381 XTextProperty 00382 window_name; 00383 00384 /* 00385 Process user command. 00386 */ 00387 nexus=NewImageList(); 00388 switch (command_type) 00389 { 00390 case OpenCommand: 00391 { 00392 char 00393 **filelist; 00394 00395 Image 00396 *images, 00397 *next; 00398 00399 ImageInfo 00400 *read_info; 00401 00402 int 00403 number_files; 00404 00405 register int 00406 i; 00407 00408 static char 00409 filenames[MaxTextExtent] = "*"; 00410 00411 if (resource_info->immutable != MagickFalse) 00412 break; 00413 /* 00414 Request file name from user. 00415 */ 00416 XFileBrowserWidget(display,windows,"Animate",filenames); 00417 if (*filenames == '\0') 00418 return((Image *) NULL); 00419 /* 00420 Expand the filenames. 00421 */ 00422 filelist=(char **) AcquireMagickMemory(sizeof(char *)); 00423 if (filelist == (char **) NULL) 00424 { 00425 ThrowXWindowException(ResourceLimitError,"MemoryAllocationFailed", 00426 filenames); 00427 return((Image *) NULL); 00428 } 00429 number_files=1; 00430 filelist[0]=filenames; 00431 status=ExpandFilenames(&number_files,&filelist); 00432 if ((status == MagickFalse) || (number_files == 0)) 00433 { 00434 if (number_files == 0) 00435 { 00436 ThrowXWindowException(ImageError,"NoImagesWereLoaded",filenames); 00437 return((Image *) NULL); 00438 } 00439 ThrowXWindowException(ResourceLimitError,"MemoryAllocationFailed", 00440 filenames); 00441 return((Image *) NULL); 00442 } 00443 read_info=CloneImageInfo(resource_info->image_info); 00444 images=NewImageList(); 00445 XSetCursorState(display,windows,MagickTrue); 00446 XCheckRefreshWindows(display,windows); 00447 for (i=0; i < number_files; i++) 00448 { 00449 (void) CopyMagickString(read_info->filename,filelist[i],MaxTextExtent); 00450 filelist[i]=DestroyString(filelist[i]); 00451 *read_info->magick='\0'; 00452 next=ReadImage(read_info,exception); 00453 CatchException(exception); 00454 if (next != (Image *) NULL) 00455 AppendImageToList(&images,next); 00456 if (number_files <= 5) 00457 continue; 00458 proceed=SetImageProgress(images,LoadImageTag,i,(MagickSizeType) 00459 number_files); 00460 if (proceed == MagickFalse) 00461 break; 00462 } 00463 filelist=(char **) RelinquishMagickMemory(filelist); 00464 read_info=DestroyImageInfo(read_info); 00465 if (images == (Image *) NULL) 00466 { 00467 XSetCursorState(display,windows,MagickFalse); 00468 ThrowXWindowException(ImageError,"NoImagesWereLoaded",filenames); 00469 return((Image *) NULL); 00470 } 00471 nexus=GetFirstImageInList(images); 00472 *state|=ExitState; 00473 break; 00474 } 00475 case PlayCommand: 00476 { 00477 char 00478 basename[MaxTextExtent]; 00479 00480 int 00481 status; 00482 00483 /* 00484 Window name is the base of the filename. 00485 */ 00486 *state|=PlayAnimationState; 00487 *state&=(~AutoReverseAnimationState); 00488 GetPathComponent((*image)->magick_filename,BasePath,basename); 00489 (void) FormatLocaleString(windows->image.name,MaxTextExtent, 00490 "%s: %s",MagickPackageName,basename); 00491 if (resource_info->title != (char *) NULL) 00492 { 00493 char 00494 *title; 00495 00496 title=InterpretImageProperties(resource_info->image_info,*image, 00497 resource_info->title,exception); 00498 (void) CopyMagickString(windows->image.name,title,MaxTextExtent); 00499 title=DestroyString(title); 00500 } 00501 status=XStringListToTextProperty(&windows->image.name,1,&window_name); 00502 if (status == 0) 00503 break; 00504 XSetWMName(display,windows->image.id,&window_name); 00505 (void) XFree((void *) window_name.value); 00506 break; 00507 } 00508 case StepCommand: 00509 case StepBackwardCommand: 00510 case StepForwardCommand: 00511 { 00512 *state|=StepAnimationState; 00513 *state&=(~PlayAnimationState); 00514 if (command_type == StepBackwardCommand) 00515 *state&=(~ForwardAnimationState); 00516 if (command_type == StepForwardCommand) 00517 *state|=ForwardAnimationState; 00518 if (resource_info->title != (char *) NULL) 00519 break; 00520 break; 00521 } 00522 case RepeatCommand: 00523 { 00524 *state|=RepeatAnimationState; 00525 *state&=(~AutoReverseAnimationState); 00526 *state|=PlayAnimationState; 00527 break; 00528 } 00529 case AutoReverseCommand: 00530 { 00531 *state|=AutoReverseAnimationState; 00532 *state&=(~RepeatAnimationState); 00533 *state|=PlayAnimationState; 00534 break; 00535 } 00536 case SaveCommand: 00537 { 00538 /* 00539 Save image. 00540 */ 00541 status=XSaveImage(display,resource_info,windows,*image,exception); 00542 if (status == MagickFalse) 00543 { 00544 char 00545 message[MaxTextExtent]; 00546 00547 (void) FormatLocaleString(message,MaxTextExtent,"%s:%s", 00548 exception->reason != (char *) NULL ? exception->reason : "", 00549 exception->description != (char *) NULL ? exception->description : 00550 ""); 00551 XNoticeWidget(display,windows,"Unable to save file:",message); 00552 break; 00553 } 00554 break; 00555 } 00556 case SlowerCommand: 00557 { 00558 resource_info->delay++; 00559 break; 00560 } 00561 case FasterCommand: 00562 { 00563 if (resource_info->delay == 0) 00564 break; 00565 resource_info->delay--; 00566 break; 00567 } 00568 case ForwardCommand: 00569 { 00570 *state=ForwardAnimationState; 00571 *state&=(~AutoReverseAnimationState); 00572 break; 00573 } 00574 case ReverseCommand: 00575 { 00576 *state&=(~ForwardAnimationState); 00577 *state&=(~AutoReverseAnimationState); 00578 break; 00579 } 00580 case InfoCommand: 00581 { 00582 XDisplayImageInfo(display,resource_info,windows,(Image *) NULL,*image, 00583 exception); 00584 break; 00585 } 00586 case HelpCommand: 00587 { 00588 /* 00589 User requested help. 00590 */ 00591 XTextViewWidget(display,resource_info,windows,MagickFalse, 00592 "Help Viewer - Animate",AnimateHelp); 00593 break; 00594 } 00595 case BrowseDocumentationCommand: 00596 { 00597 Atom 00598 mozilla_atom; 00599 00600 Window 00601 mozilla_window, 00602 root_window; 00603 00604 /* 00605 Browse the ImageMagick documentation. 00606 */ 00607 root_window=XRootWindow(display,XDefaultScreen(display)); 00608 mozilla_atom=XInternAtom(display,"_MOZILLA_VERSION",MagickFalse); 00609 mozilla_window=XWindowByProperty(display,root_window,mozilla_atom); 00610 if (mozilla_window != (Window) NULL) 00611 { 00612 char 00613 command[MaxTextExtent], 00614 *url; 00615 00616 /* 00617 Display documentation using Netscape remote control. 00618 */ 00619 url=GetMagickHomeURL(); 00620 (void) FormatLocaleString(command,MaxTextExtent, 00621 "openurl(%s,new-tab)",url); 00622 url=DestroyString(url); 00623 mozilla_atom=XInternAtom(display,"_MOZILLA_COMMAND",MagickFalse); 00624 (void) XChangeProperty(display,mozilla_window,mozilla_atom, 00625 XA_STRING,8,PropModeReplace,(unsigned char *) command, 00626 (int) strlen(command)); 00627 XSetCursorState(display,windows,MagickFalse); 00628 break; 00629 } 00630 XSetCursorState(display,windows,MagickTrue); 00631 XCheckRefreshWindows(display,windows); 00632 status=InvokeDelegate(resource_info->image_info,*image,"browse", 00633 (char *) NULL,exception); 00634 if (status == MagickFalse) 00635 XNoticeWidget(display,windows,"Unable to browse documentation", 00636 (char *) NULL); 00637 XDelay(display,1500); 00638 XSetCursorState(display,windows,MagickFalse); 00639 break; 00640 } 00641 case VersionCommand: 00642 { 00643 XNoticeWidget(display,windows,GetMagickVersion((size_t *) NULL), 00644 GetMagickCopyright()); 00645 break; 00646 } 00647 case QuitCommand: 00648 { 00649 /* 00650 exit program 00651 */ 00652 if (resource_info->confirm_exit == MagickFalse) 00653 XClientMessage(display,windows->image.id,windows->im_protocols, 00654 windows->im_exit,CurrentTime); 00655 else 00656 { 00657 int 00658 status; 00659 00660 /* 00661 Confirm program exit. 00662 */ 00663 status=XConfirmWidget(display,windows,"Do you really want to exit", 00664 resource_info->client_name); 00665 if (status != 0) 00666 XClientMessage(display,windows->image.id,windows->im_protocols, 00667 windows->im_exit,CurrentTime); 00668 } 00669 break; 00670 } 00671 default: 00672 break; 00673 } 00674 return(nexus); 00675 } 00676 00677 /* 00678 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 00679 % % 00680 % % 00681 % % 00682 + X A n i m a t e B a c k g r o u n d I m a g e % 00683 % % 00684 % % 00685 % % 00686 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 00687 % 00688 % XAnimateBackgroundImage() animates an image sequence in the background of 00689 % a window. 00690 % 00691 % The format of the XAnimateBackgroundImage method is: 00692 % 00693 % void XAnimateBackgroundImage(Display *display, 00694 % XResourceInfo *resource_info,Image *images,ExceptionInfo *exception) 00695 % 00696 % A description of each parameter follows: 00697 % 00698 % o display: Specifies a connection to an X server; returned from 00699 % XOpenDisplay. 00700 % 00701 % o resource_info: Specifies a pointer to a X11 XResourceInfo structure. 00702 % 00703 % o images: the image list. 00704 % 00705 % o exception: return any errors or warnings in this structure. 00706 % 00707 */ 00708 00709 static inline ssize_t MagickMax(const ssize_t x,const ssize_t y) 00710 { 00711 if (x > y) 00712 return(x); 00713 return(y); 00714 } 00715 00716 #if defined(__cplusplus) || defined(c_plusplus) 00717 extern "C" { 00718 #endif 00719 00720 static int SceneCompare(const void *x,const void *y) 00721 { 00722 const Image 00723 **image_1, 00724 **image_2; 00725 00726 image_1=(const Image **) x; 00727 image_2=(const Image **) y; 00728 return((int) ((*image_1)->scene-(*image_2)->scene)); 00729 } 00730 00731 #if defined(__cplusplus) || defined(c_plusplus) 00732 } 00733 #endif 00734 00735 MagickExport void XAnimateBackgroundImage(Display *display, 00736 XResourceInfo *resource_info,Image *images,ExceptionInfo *exception) 00737 { 00738 char 00739 geometry[MaxTextExtent], 00740 visual_type[MaxTextExtent]; 00741 00742 Image 00743 *coalesce_image, 00744 *display_image, 00745 **image_list; 00746 00747 int 00748 scene; 00749 00750 MagickStatusType 00751 status; 00752 00753 RectangleInfo 00754 geometry_info; 00755 00756 register ssize_t 00757 i; 00758 00759 size_t 00760 number_scenes; 00761 00762 static XPixelInfo 00763 pixel; 00764 00765 static XStandardColormap 00766 *map_info; 00767 00768 static XVisualInfo 00769 *visual_info = (XVisualInfo *) NULL; 00770 00771 static XWindowInfo 00772 window_info; 00773 00774 unsigned int 00775 height, 00776 width; 00777 00778 size_t 00779 delay; 00780 00781 Window 00782 root_window; 00783 00784 XEvent 00785 event; 00786 00787 XGCValues 00788 context_values; 00789 00790 XResourceInfo 00791 resources; 00792 00793 XWindowAttributes 00794 window_attributes; 00795 00796 /* 00797 Determine target window. 00798 */ 00799 assert(images != (Image *) NULL); 00800 assert(images->signature == MagickSignature); 00801 if (images->debug != MagickFalse) 00802 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",images->filename); 00803 resources=(*resource_info); 00804 window_info.id=(Window) NULL; 00805 root_window=XRootWindow(display,XDefaultScreen(display)); 00806 if (LocaleCompare(resources.window_id,"root") == 0) 00807 window_info.id=root_window; 00808 else 00809 { 00810 if (isdigit((int) ((unsigned char) *resources.window_id)) != 0) 00811 window_info.id=XWindowByID(display,root_window, 00812 (Window) strtol((char *) resources.window_id,(char **) NULL,0)); 00813 if (window_info.id == (Window) NULL) 00814 window_info.id= 00815 XWindowByName(display,root_window,resources.window_id); 00816 } 00817 if (window_info.id == (Window) NULL) 00818 { 00819 ThrowXWindowException(XServerError,"NoWindowWithSpecifiedIDExists", 00820 resources.window_id); 00821 return; 00822 } 00823 /* 00824 Determine window visual id. 00825 */ 00826 window_attributes.width=XDisplayWidth(display,XDefaultScreen(display)); 00827 window_attributes.height=XDisplayHeight(display,XDefaultScreen(display)); 00828 (void) CopyMagickString(visual_type,"default",MaxTextExtent); 00829 status=XGetWindowAttributes(display,window_info.id,&window_attributes) != 0 ? 00830 MagickTrue : MagickFalse; 00831 if (status != MagickFalse) 00832 (void) FormatLocaleString(visual_type,MaxTextExtent,"0x%lx", 00833 XVisualIDFromVisual(window_attributes.visual)); 00834 if (visual_info == (XVisualInfo *) NULL) 00835 { 00836 /* 00837 Allocate standard colormap. 00838 */ 00839 map_info=XAllocStandardColormap(); 00840 if (map_info == (XStandardColormap *) NULL) 00841 ThrowXWindowFatalException(ResourceLimitError,"MemoryAllocationFailed", 00842 images->filename); 00843 map_info->colormap=(Colormap) NULL; 00844 pixel.pixels=(unsigned long *) NULL; 00845 /* 00846 Initialize visual info. 00847 */ 00848 resources.map_type=(char *) NULL; 00849 resources.visual_type=visual_type; 00850 visual_info=XBestVisualInfo(display,map_info,&resources); 00851 if (visual_info == (XVisualInfo *) NULL) 00852 ThrowXWindowFatalException(XServerFatalError,"UnableToGetVisual", 00853 images->filename); 00854 /* 00855 Initialize window info. 00856 */ 00857 window_info.ximage=(XImage *) NULL; 00858 window_info.matte_image=(XImage *) NULL; 00859 window_info.pixmap=(Pixmap) NULL; 00860 window_info.matte_pixmap=(Pixmap) NULL; 00861 } 00862 /* 00863 Free previous root colors. 00864 */ 00865 if (window_info.id == root_window) 00866 XDestroyWindowColors(display,root_window); 00867 coalesce_image=CoalesceImages(images,exception); 00868 if (coalesce_image == (Image *) NULL) 00869 ThrowXWindowFatalException(ResourceLimitError,"MemoryAllocationFailed", 00870 images->filename); 00871 images=coalesce_image; 00872 if (resources.map_type == (char *) NULL) 00873 if ((visual_info->klass != TrueColor) && 00874 (visual_info->klass != DirectColor)) 00875 { 00876 Image 00877 *next; 00878 00879 /* 00880 Determine if the sequence of images has the identical colormap. 00881 */ 00882 for (next=images; next != (Image *) NULL; ) 00883 { 00884 next->matte=MagickFalse; 00885 if ((next->storage_class == DirectClass) || 00886 (next->colors != images->colors) || 00887 (next->colors > (size_t) visual_info->colormap_size)) 00888 break; 00889 for (i=0; i < (ssize_t) images->colors; i++) 00890 if (IsPixelInfoEquivalent(next->colormap+i,images->colormap+i) == MagickFalse) 00891 break; 00892 if (i < (ssize_t) images->colors) 00893 break; 00894 next=GetNextImageInList(next); 00895 } 00896 if (next != (Image *) NULL) 00897 (void) RemapImages(resources.quantize_info,images,(Image *) NULL, 00898 exception); 00899 } 00900 /* 00901 Sort images by increasing scene number. 00902 */ 00903 number_scenes=GetImageListLength(images); 00904 image_list=ImageListToArray(images,exception); 00905 if (image_list == (Image **) NULL) 00906 ThrowXWindowFatalException(ResourceLimitFatalError, 00907 "MemoryAllocationFailed",images->filename); 00908 for (i=0; i < (ssize_t) number_scenes; i++) 00909 if (image_list[i]->scene == 0) 00910 break; 00911 if (i == (ssize_t) number_scenes) 00912 qsort((void *) image_list,number_scenes,sizeof(Image *),SceneCompare); 00913 /* 00914 Initialize Standard Colormap. 00915 */ 00916 resources.colormap=SharedColormap; 00917 display_image=image_list[0]; 00918 for (scene=0; scene < (int) number_scenes; scene++) 00919 { 00920 if ((resource_info->map_type != (char *) NULL) || 00921 (visual_info->klass == TrueColor) || 00922 (visual_info->klass == DirectColor)) 00923 (void) SetImageType(image_list[scene],image_list[scene]->matte == 00924 MagickFalse ? TrueColorType : TrueColorMatteType,exception); 00925 if ((display_image->columns < image_list[scene]->columns) && 00926 (display_image->rows < image_list[scene]->rows)) 00927 display_image=image_list[scene]; 00928 } 00929 if ((resource_info->map_type != (char *) NULL) || 00930 (visual_info->klass == TrueColor) || (visual_info->klass == DirectColor)) 00931 (void) SetImageType(display_image,display_image->matte == MagickFalse ? 00932 TrueColorType : TrueColorMatteType,exception); 00933 XMakeStandardColormap(display,visual_info,&resources,display_image,map_info, 00934 &pixel,exception); 00935 /* 00936 Graphic context superclass. 00937 */ 00938 context_values.background=pixel.background_color.pixel; 00939 context_values.foreground=pixel.foreground_color.pixel; 00940 pixel.annotate_context=XCreateGC(display,window_info.id,(unsigned long) 00941 (GCBackground | GCForeground),&context_values); 00942 if (pixel.annotate_context == (GC) NULL) 00943 ThrowXWindowFatalException(XServerFatalError,"UnableToCreateGraphicContext", 00944 images->filename); 00945 /* 00946 Initialize Image window attributes. 00947 */ 00948 XGetWindowInfo(display,visual_info,map_info,&pixel,(XFontStruct *) NULL, 00949 &resources,&window_info); 00950 /* 00951 Create the X image. 00952 */ 00953 window_info.width=(unsigned int) image_list[0]->columns; 00954 window_info.height=(unsigned int) image_list[0]->rows; 00955 if ((image_list[0]->columns != window_info.width) || 00956 (image_list[0]->rows != window_info.height)) 00957 ThrowXWindowFatalException(XServerFatalError,"UnableToCreateXImage", 00958 image_list[0]->filename); 00959 (void) FormatLocaleString(geometry,MaxTextExtent,"%ux%u+0+0>", 00960 window_attributes.width,window_attributes.height); 00961 geometry_info.width=window_info.width; 00962 geometry_info.height=window_info.height; 00963 geometry_info.x=(ssize_t) window_info.x; 00964 geometry_info.y=(ssize_t) window_info.y; 00965 (void) ParseMetaGeometry(geometry,&geometry_info.x,&geometry_info.y, 00966 &geometry_info.width,&geometry_info.height); 00967 window_info.width=(unsigned int) geometry_info.width; 00968 window_info.height=(unsigned int) geometry_info.height; 00969 window_info.x=(int) geometry_info.x; 00970 window_info.y=(int) geometry_info.y; 00971 status=XMakeImage(display,&resources,&window_info,image_list[0], 00972 window_info.width,window_info.height,exception); 00973 if (status == MagickFalse) 00974 ThrowXWindowFatalException(XServerFatalError,"UnableToCreateXImage", 00975 images->filename); 00976 window_info.x=0; 00977 window_info.y=0; 00978 if (display_image->debug != MagickFalse) 00979 { 00980 (void) LogMagickEvent(X11Event,GetMagickModule(), 00981 "Image: %s[%.20g] %.20gx%.20g ",image_list[0]->filename,(double) 00982 image_list[0]->scene,(double) image_list[0]->columns,(double) 00983 image_list[0]->rows); 00984 if (image_list[0]->colors != 0) 00985 (void) LogMagickEvent(X11Event,GetMagickModule(),"%.20gc ",(double) 00986 image_list[0]->colors); 00987 (void) LogMagickEvent(X11Event,GetMagickModule(),"%s", 00988 image_list[0]->magick); 00989 } 00990 /* 00991 Adjust image dimensions as specified by backdrop or geometry options. 00992 */ 00993 width=window_info.width; 00994 height=window_info.height; 00995 if (resources.backdrop != MagickFalse) 00996 { 00997 /* 00998 Center image on window. 00999 */ 01000 window_info.x=(int) (window_attributes.width/2)- 01001 (window_info.ximage->width/2); 01002 window_info.y=(int) (window_attributes.height/2)- 01003 (window_info.ximage->height/2); 01004 width=(unsigned int) window_attributes.width; 01005 height=(unsigned int) window_attributes.height; 01006 } 01007 if (resources.image_geometry != (char *) NULL) 01008 { 01009 char 01010 default_geometry[MaxTextExtent]; 01011 01012 int 01013 flags, 01014 gravity; 01015 01016 XSizeHints 01017 *size_hints; 01018 01019 /* 01020 User specified geometry. 01021 */ 01022 size_hints=XAllocSizeHints(); 01023 if (size_hints == (XSizeHints *) NULL) 01024 ThrowXWindowFatalException(ResourceLimitFatalError, 01025 "MemoryAllocationFailed",images->filename); 01026 size_hints->flags=0L; 01027 (void) FormatLocaleString(default_geometry,MaxTextExtent,"%ux%u",width, 01028 height); 01029 flags=XWMGeometry(display,visual_info->screen,resources.image_geometry, 01030 default_geometry,window_info.border_width,size_hints,&window_info.x, 01031 &window_info.y,(int *) &width,(int *) &height,&gravity); 01032 if (((flags & (XValue | YValue))) != 0) 01033 { 01034 width=(unsigned int) window_attributes.width; 01035 height=(unsigned int) window_attributes.height; 01036 } 01037 (void) XFree((void *) size_hints); 01038 } 01039 /* 01040 Create the X pixmap. 01041 */ 01042 window_info.pixmap=XCreatePixmap(display,window_info.id,(unsigned int) width, 01043 (unsigned int) height,window_info.depth); 01044 if (window_info.pixmap == (Pixmap) NULL) 01045 ThrowXWindowFatalException(XServerFatalError,"UnableToCreateXPixmap", 01046 images->filename); 01047 /* 01048 Display pixmap on the window. 01049 */ 01050 if (((unsigned int) width > window_info.width) || 01051 ((unsigned int) height > window_info.height)) 01052 (void) XFillRectangle(display,window_info.pixmap, 01053 window_info.annotate_context,0,0,(unsigned int) width, 01054 (unsigned int) height); 01055 (void) XPutImage(display,window_info.pixmap,window_info.annotate_context, 01056 window_info.ximage,0,0,window_info.x,window_info.y,window_info.width, 01057 window_info.height); 01058 (void) XSetWindowBackgroundPixmap(display,window_info.id,window_info.pixmap); 01059 (void) XClearWindow(display,window_info.id); 01060 /* 01061 Initialize image pixmaps structure. 01062 */ 01063 window_info.pixmaps=(Pixmap *) AcquireQuantumMemory(number_scenes, 01064 sizeof(*window_info.pixmaps)); 01065 window_info.matte_pixmaps=(Pixmap *) AcquireQuantumMemory(number_scenes, 01066 sizeof(*window_info.matte_pixmaps)); 01067 if ((window_info.pixmaps == (Pixmap *) NULL) || 01068 (window_info.matte_pixmaps == (Pixmap *) NULL)) 01069 ThrowXWindowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed", 01070 images->filename); 01071 window_info.pixmaps[0]=window_info.pixmap; 01072 window_info.matte_pixmaps[0]=window_info.pixmap; 01073 for (scene=1; scene < (int) number_scenes; scene++) 01074 { 01075 unsigned int 01076 columns, 01077 rows; 01078 01079 /* 01080 Create X image. 01081 */ 01082 window_info.pixmap=(Pixmap) NULL; 01083 window_info.matte_pixmap=(Pixmap) NULL; 01084 if ((resources.map_type != (char *) NULL) || 01085 (visual_info->klass == TrueColor) || 01086 (visual_info->klass == DirectColor)) 01087 if (image_list[scene]->storage_class == PseudoClass) 01088 XGetPixelInfo(display,visual_info,map_info,&resources, 01089 image_list[scene],window_info.pixel_info); 01090 columns=(unsigned int) image_list[scene]->columns; 01091 rows=(unsigned int) image_list[scene]->rows; 01092 if ((image_list[scene]->columns != columns) || 01093 (image_list[scene]->rows != rows)) 01094 ThrowXWindowFatalException(XServerFatalError,"UnableToCreateXImage", 01095 image_list[scene]->filename); 01096 status=XMakeImage(display,&resources,&window_info,image_list[scene], 01097 columns,rows,exception); 01098 if (status == MagickFalse) 01099 ThrowXWindowFatalException(XServerFatalError,"UnableToCreateXImage", 01100 images->filename); 01101 if (display_image->debug != MagickFalse) 01102 { 01103 (void) LogMagickEvent(X11Event,GetMagickModule(), 01104 "Image: [%.20g] %s %.20gx%.20g ",(double) image_list[scene]->scene, 01105 image_list[scene]->filename,(double) columns,(double) rows); 01106 if (image_list[scene]->colors != 0) 01107 (void) LogMagickEvent(X11Event,GetMagickModule(),"%.20gc ",(double) 01108 image_list[scene]->colors); 01109 (void) LogMagickEvent(X11Event,GetMagickModule(),"%s", 01110 image_list[scene]->magick); 01111 } 01112 /* 01113 Create the X pixmap. 01114 */ 01115 window_info.pixmap=XCreatePixmap(display,window_info.id,width,height, 01116 window_info.depth); 01117 if (window_info.pixmap == (Pixmap) NULL) 01118 ThrowXWindowFatalException(XServerFatalError,"UnableToCreateXPixmap", 01119 images->filename); 01120 /* 01121 Display pixmap on the window. 01122 */ 01123 if ((width > window_info.width) || (height > window_info.height)) 01124 (void) XFillRectangle(display,window_info.pixmap, 01125 window_info.annotate_context,0,0,width,height); 01126 (void) XPutImage(display,window_info.pixmap,window_info.annotate_context, 01127 window_info.ximage,0,0,window_info.x,window_info.y,window_info.width, 01128 window_info.height); 01129 (void) XSetWindowBackgroundPixmap(display,window_info.id, 01130 window_info.pixmap); 01131 (void) XClearWindow(display,window_info.id); 01132 window_info.pixmaps[scene]=window_info.pixmap; 01133 window_info.matte_pixmaps[scene]=window_info.matte_pixmap; 01134 if (image_list[scene]->matte) 01135 (void) XClearWindow(display,window_info.id); 01136 delay=1000*image_list[scene]->delay/MagickMax( 01137 image_list[scene]->ticks_per_second,1L); 01138 XDelay(display,resources.delay*(delay == 0 ? 10 : delay)); 01139 } 01140 window_info.pixel_info=(&pixel); 01141 /* 01142 Display pixmap on the window. 01143 */ 01144 (void) XSelectInput(display,window_info.id,SubstructureNotifyMask); 01145 event.type=Expose; 01146 do 01147 { 01148 for (scene=0; scene < (int) number_scenes; scene++) 01149 { 01150 if (XEventsQueued(display,QueuedAfterFlush) > 0) 01151 { 01152 (void) XNextEvent(display,&event); 01153 if (event.type == DestroyNotify) 01154 break; 01155 } 01156 window_info.pixmap=window_info.pixmaps[scene]; 01157 window_info.matte_pixmap=window_info.matte_pixmaps[scene]; 01158 (void) XSetWindowBackgroundPixmap(display,window_info.id, 01159 window_info.pixmap); 01160 (void) XClearWindow(display,window_info.id); 01161 (void) XSync(display,MagickFalse); 01162 delay=1000*image_list[scene]->delay/MagickMax( 01163 image_list[scene]->ticks_per_second,1L); 01164 XDelay(display,resources.delay*(delay == 0 ? 10 : delay)); 01165 } 01166 } while (event.type != DestroyNotify); 01167 (void) XSync(display,MagickFalse); 01168 image_list=(Image **) RelinquishMagickMemory(image_list); 01169 images=DestroyImageList(images); 01170 } 01171 01172 /* 01173 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 01174 % % 01175 % % 01176 % % 01177 + X A n i m a t e I m a g e s % 01178 % % 01179 % % 01180 % % 01181 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 01182 % 01183 % XAnimateImages() displays an image via X11. 01184 % 01185 % The format of the XAnimateImages method is: 01186 % 01187 % Image *XAnimateImages(Display *display,XResourceInfo *resource_info, 01188 % char **argv,const int argc,Image *images,ExceptionInfo *exception) 01189 % 01190 % A description of each parameter follows: 01191 % 01192 % o display: Specifies a connection to an X server; returned from 01193 % XOpenDisplay. 01194 % 01195 % o resource_info: Specifies a pointer to a X11 XResourceInfo structure. 01196 % 01197 % o argv: Specifies the application's argument list. 01198 % 01199 % o argc: Specifies the number of arguments. 01200 % 01201 % o images: the image list. 01202 % 01203 % o exception: return any errors or warnings in this structure. 01204 % 01205 */ 01206 MagickExport Image *XAnimateImages(Display *display, 01207 XResourceInfo *resource_info,char **argv,const int argc,Image *images, 01208 ExceptionInfo *exception) 01209 { 01210 #define MagickMenus 4 01211 #define MaXWindows 8 01212 #define MagickTitle "Commands" 01213 01214 static const char 01215 *CommandMenu[]= 01216 { 01217 "Animate", 01218 "Speed", 01219 "Direction", 01220 "Help", 01221 "Image Info", 01222 "Quit", 01223 (char *) NULL 01224 }, 01225 *AnimateMenu[]= 01226 { 01227 "Open...", 01228 "Play", 01229 "Step", 01230 "Repeat", 01231 "Auto Reverse", 01232 "Save...", 01233 (char *) NULL 01234 }, 01235 *SpeedMenu[]= 01236 { 01237 "Faster", 01238 "Slower", 01239 (char *) NULL 01240 }, 01241 *DirectionMenu[]= 01242 { 01243 "Forward", 01244 "Reverse", 01245 (char *) NULL 01246 }, 01247 *HelpMenu[]= 01248 { 01249 "Overview", 01250 "Browse Documentation", 01251 "About Animate", 01252 (char *) NULL 01253 }; 01254 01255 static const char 01256 **Menus[MagickMenus]= 01257 { 01258 AnimateMenu, 01259 SpeedMenu, 01260 DirectionMenu, 01261 HelpMenu 01262 }; 01263 01264 static const CommandType 01265 CommandMenus[]= 01266 { 01267 NullCommand, 01268 NullCommand, 01269 NullCommand, 01270 NullCommand, 01271 InfoCommand, 01272 QuitCommand 01273 }, 01274 CommandTypes[]= 01275 { 01276 OpenCommand, 01277 PlayCommand, 01278 StepCommand, 01279 RepeatCommand, 01280 AutoReverseCommand, 01281 SaveCommand 01282 }, 01283 SpeedCommands[]= 01284 { 01285 FasterCommand, 01286 SlowerCommand 01287 }, 01288 DirectionCommands[]= 01289 { 01290 ForwardCommand, 01291 ReverseCommand 01292 }, 01293 HelpCommands[]= 01294 { 01295 HelpCommand, 01296 BrowseDocumentationCommand, 01297 VersionCommand 01298 }; 01299 01300 static const CommandType 01301 *Commands[MagickMenus]= 01302 { 01303 CommandTypes, 01304 SpeedCommands, 01305 DirectionCommands, 01306 HelpCommands 01307 }; 01308 01309 char 01310 command[MaxTextExtent], 01311 *directory, 01312 geometry[MaxTextExtent], 01313 resource_name[MaxTextExtent]; 01314 01315 CommandType 01316 command_type; 01317 01318 Image 01319 *coalesce_image, 01320 *display_image, 01321 *image, 01322 **image_list, 01323 *nexus; 01324 01325 int 01326 status; 01327 01328 KeySym 01329 key_symbol; 01330 01331 MagickStatusType 01332 context_mask, 01333 state; 01334 01335 RectangleInfo 01336 geometry_info; 01337 01338 register char 01339 *p; 01340 01341 register ssize_t 01342 i; 01343 01344 ssize_t 01345 first_scene, 01346 iterations, 01347 scene; 01348 01349 static char 01350 working_directory[MaxTextExtent]; 01351 01352 static size_t 01353 number_windows; 01354 01355 static XWindowInfo 01356 *magick_windows[MaXWindows]; 01357 01358 time_t 01359 timestamp; 01360 01361 size_t 01362 delay, 01363 number_scenes; 01364 01365 WarningHandler 01366 warning_handler; 01367 01368 Window 01369 root_window; 01370 01371 XClassHint 01372 *class_hints; 01373 01374 XEvent 01375 event; 01376 01377 XFontStruct 01378 *font_info; 01379 01380 XGCValues 01381 context_values; 01382 01383 XPixelInfo 01384 *icon_pixel, 01385 *pixel; 01386 01387 XResourceInfo 01388 *icon_resources; 01389 01390 XStandardColormap 01391 *icon_map, 01392 *map_info; 01393 01394 XTextProperty 01395 window_name; 01396 01397 XVisualInfo 01398 *icon_visual, 01399 *visual_info; 01400 01401 XWindowChanges 01402 window_changes; 01403 01404 XWindows 01405 *windows; 01406 01407 XWMHints 01408 *manager_hints; 01409 01410 assert(images != (Image *) NULL); 01411 assert(images->signature == MagickSignature); 01412 if (images->debug != MagickFalse) 01413 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",images->filename); 01414 warning_handler=(WarningHandler) NULL; 01415 windows=XSetWindows((XWindows *) ~0); 01416 if (windows != (XWindows *) NULL) 01417 { 01418 int 01419 status; 01420 01421 status=chdir(working_directory); 01422 if (status == -1) 01423 (void) ThrowMagickException(exception,GetMagickModule(),FileOpenError, 01424 "UnableToOpenFile","%s",working_directory); 01425 warning_handler=resource_info->display_warnings ? 01426 SetErrorHandler(XWarning) : SetErrorHandler((ErrorHandler) NULL); 01427 warning_handler=resource_info->display_warnings ? 01428 SetWarningHandler(XWarning) : SetWarningHandler((WarningHandler) NULL); 01429 } 01430 else 01431 { 01432 register Image 01433 *p; 01434 01435 /* 01436 Initialize window structure. 01437 */ 01438 for (p=images; p != (Image *) NULL; p=GetNextImageInList(p)) 01439 { 01440 if (p->storage_class == DirectClass) 01441 { 01442 resource_info->colors=0; 01443 break; 01444 } 01445 if (p->colors > resource_info->colors) 01446 resource_info->colors=p->colors; 01447 } 01448 windows=XSetWindows(XInitializeWindows(display,resource_info)); 01449 if (windows == (XWindows *) NULL) 01450 ThrowXWindowFatalException(XServerFatalError,"MemoryAllocationFailed", 01451 images->filename); 01452 /* 01453 Initialize window id's. 01454 */ 01455 number_windows=0; 01456 magick_windows[number_windows++]=(&windows->icon); 01457 magick_windows[number_windows++]=(&windows->backdrop); 01458 magick_windows[number_windows++]=(&windows->image); 01459 magick_windows[number_windows++]=(&windows->info); 01460 magick_windows[number_windows++]=(&windows->command); 01461 magick_windows[number_windows++]=(&windows->widget); 01462 magick_windows[number_windows++]=(&windows->popup); 01463 for (i=0; i < (ssize_t) number_windows; i++) 01464 magick_windows[i]->id=(Window) NULL; 01465 } 01466 /* 01467 Initialize font info. 01468 */ 01469 if (windows->font_info != (XFontStruct *) NULL) 01470 (void) XFreeFont(display,windows->font_info); 01471 windows->font_info=XBestFont(display,resource_info,MagickFalse); 01472 if (windows->font_info == (XFontStruct *) NULL) 01473 ThrowXWindowFatalException(XServerFatalError,"UnableToLoadFont", 01474 resource_info->font); 01475 /* 01476 Initialize Standard Colormap. 01477 */ 01478 map_info=windows->map_info; 01479 icon_map=windows->icon_map; 01480 visual_info=windows->visual_info; 01481 icon_visual=windows->icon_visual; 01482 pixel=windows->pixel_info; 01483 icon_pixel=windows->icon_pixel; 01484 font_info=windows->font_info; 01485 icon_resources=windows->icon_resources; 01486 class_hints=windows->class_hints; 01487 manager_hints=windows->manager_hints; 01488 root_window=XRootWindow(display,visual_info->screen); 01489 coalesce_image=CoalesceImages(images,exception); 01490 if (coalesce_image == (Image *) NULL) 01491 ThrowXWindowFatalException(XServerFatalError,"MemoryAllocationFailed", 01492 images->filename); 01493 images=coalesce_image; 01494 if (resource_info->map_type == (char *) NULL) 01495 if ((visual_info->klass != TrueColor) && 01496 (visual_info->klass != DirectColor)) 01497 { 01498 Image 01499 *next; 01500 01501 /* 01502 Determine if the sequence of images has the identical colormap. 01503 */ 01504 for (next=images; next != (Image *) NULL; ) 01505 { 01506 next->matte=MagickFalse; 01507 if ((next->storage_class == DirectClass) || 01508 (next->colors != images->colors) || 01509 (next->colors > (size_t) visual_info->colormap_size)) 01510 break; 01511 for (i=0; i < (ssize_t) images->colors; i++) 01512 if (IsPixelInfoEquivalent(next->colormap+i,images->colormap+i) == MagickFalse) 01513 break; 01514 if (i < (ssize_t) images->colors) 01515 break; 01516 next=GetNextImageInList(next); 01517 } 01518 if (next != (Image *) NULL) 01519 (void) RemapImages(resource_info->quantize_info,images, 01520 (Image *) NULL,exception); 01521 } 01522 /* 01523 Sort images by increasing scene number. 01524 */ 01525 number_scenes=GetImageListLength(images); 01526 image_list=ImageListToArray(images,exception); 01527 if (image_list == (Image **) NULL) 01528 ThrowXWindowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed", 01529 images->filename); 01530 for (scene=0; scene < (ssize_t) number_scenes; scene++) 01531 if (image_list[scene]->scene == 0) 01532 break; 01533 if (scene == (ssize_t) number_scenes) 01534 qsort((void *) image_list,number_scenes,sizeof(Image *),SceneCompare); 01535 /* 01536 Initialize Standard Colormap. 01537 */ 01538 nexus=NewImageList(); 01539 display_image=image_list[0]; 01540 for (scene=0; scene < (ssize_t) number_scenes; scene++) 01541 { 01542 if ((resource_info->map_type != (char *) NULL) || 01543 (visual_info->klass == TrueColor) || 01544 (visual_info->klass == DirectColor)) 01545 (void) SetImageType(image_list[scene],image_list[scene]->matte == 01546 MagickFalse ? TrueColorType : TrueColorMatteType,exception); 01547 if ((display_image->columns < image_list[scene]->columns) && 01548 (display_image->rows < image_list[scene]->rows)) 01549 display_image=image_list[scene]; 01550 } 01551 if (display_image->debug != MagickFalse) 01552 { 01553 (void) LogMagickEvent(X11Event,GetMagickModule(), 01554 "Image: %s[%.20g] %.20gx%.20g ",display_image->filename,(double) 01555 display_image->scene,(double) display_image->columns,(double) 01556 display_image->rows); 01557 if (display_image->colors != 0) 01558 (void) LogMagickEvent(X11Event,GetMagickModule(),"%.20gc ",(double) 01559 display_image->colors); 01560 (void) LogMagickEvent(X11Event,GetMagickModule(),"%s", 01561 display_image->magick); 01562 } 01563 XMakeStandardColormap(display,visual_info,resource_info,display_image, 01564 map_info,pixel,exception); 01565 /* 01566 Initialize graphic context. 01567 */ 01568 windows->context.id=(Window) NULL; 01569 XGetWindowInfo(display,visual_info,map_info,pixel,font_info, 01570 resource_info,&windows->context); 01571 (void) CloneString(&class_hints->res_name,resource_info->client_name); 01572 (void) CloneString(&class_hints->res_class,resource_info->client_name); 01573 class_hints->res_class[0]=(char) toupper((int) class_hints->res_class[0]); 01574 manager_hints->flags=InputHint | StateHint; 01575 manager_hints->input=MagickFalse; 01576 manager_hints->initial_state=WithdrawnState; 01577 XMakeWindow(display,root_window,argv,argc,class_hints,manager_hints, 01578 &windows->context); 01579 if (display_image->debug != MagickFalse) 01580 (void) LogMagickEvent(X11Event,GetMagickModule(), 01581 "Window id: 0x%lx (context)",windows->context.id); 01582 context_values.background=pixel->background_color.pixel; 01583 context_values.font=font_info->fid; 01584 context_values.foreground=pixel->foreground_color.pixel; 01585 context_values.graphics_exposures=MagickFalse; 01586 context_mask=(MagickStatusType) 01587 (GCBackground | GCFont | GCForeground | GCGraphicsExposures); 01588 if (pixel->annotate_context != (GC) NULL) 01589 (void) XFreeGC(display,pixel->annotate_context); 01590 pixel->annotate_context= 01591 XCreateGC(display,windows->context.id,context_mask,&context_values); 01592 if (pixel->annotate_context == (GC) NULL) 01593 ThrowXWindowFatalException(XServerFatalError,"UnableToCreateGraphicContext", 01594 images->filename); 01595 context_values.background=pixel->depth_color.pixel; 01596 if (pixel->widget_context != (GC) NULL) 01597 (void) XFreeGC(display,pixel->widget_context); 01598 pixel->widget_context= 01599 XCreateGC(display,windows->context.id,context_mask,&context_values); 01600 if (pixel->widget_context == (GC) NULL) 01601 ThrowXWindowFatalException(XServerFatalError,"UnableToCreateGraphicContext", 01602 images->filename); 01603 context_values.background=pixel->foreground_color.pixel; 01604 context_values.foreground=pixel->background_color.pixel; 01605 context_values.plane_mask= 01606 context_values.background ^ context_values.foreground; 01607 if (pixel->highlight_context != (GC) NULL) 01608 (void) XFreeGC(display,pixel->highlight_context); 01609 pixel->highlight_context=XCreateGC(display,windows->context.id, 01610 (size_t) (context_mask | GCPlaneMask),&context_values); 01611 if (pixel->highlight_context == (GC) NULL) 01612 ThrowXWindowFatalException(XServerFatalError,"UnableToCreateGraphicContext", 01613 images->filename); 01614 (void) XDestroyWindow(display,windows->context.id); 01615 /* 01616 Initialize icon window. 01617 */ 01618 XGetWindowInfo(display,icon_visual,icon_map,icon_pixel,(XFontStruct *) NULL, 01619 icon_resources,&windows->icon); 01620 windows->icon.geometry=resource_info->icon_geometry; 01621 XBestIconSize(display,&windows->icon,display_image); 01622 windows->icon.attributes.colormap= 01623 XDefaultColormap(display,icon_visual->screen); 01624 windows->icon.attributes.event_mask=ExposureMask | StructureNotifyMask; 01625 manager_hints->flags=InputHint | StateHint; 01626 manager_hints->input=MagickFalse; 01627 manager_hints->initial_state=IconicState; 01628 XMakeWindow(display,root_window,argv,argc,class_hints,manager_hints, 01629 &windows->icon); 01630 if (display_image->debug != MagickFalse) 01631 (void) LogMagickEvent(X11Event,GetMagickModule(),"Window id: 0x%lx (icon)", 01632 windows->icon.id); 01633 /* 01634 Initialize graphic context for icon window. 01635 */ 01636 if (icon_pixel->annotate_context != (GC) NULL) 01637 (void) XFreeGC(display,icon_pixel->annotate_context); 01638 context_values.background=icon_pixel->background_color.pixel; 01639 context_values.foreground=icon_pixel->foreground_color.pixel; 01640 icon_pixel->annotate_context=XCreateGC(display,windows->icon.id, 01641 (size_t) (GCBackground | GCForeground),&context_values); 01642 if (icon_pixel->annotate_context == (GC) NULL) 01643 ThrowXWindowFatalException(XServerFatalError,"UnableToCreateGraphicContext", 01644 images->filename); 01645 windows->icon.annotate_context=icon_pixel->annotate_context; 01646 /* 01647 Initialize Image window. 01648 */ 01649 XGetWindowInfo(display,visual_info,map_info,pixel,font_info, 01650 resource_info,&windows->image); 01651 windows->image.shape=MagickTrue; /* non-rectangular shape hint */ 01652 if (resource_info->use_shared_memory == MagickFalse) 01653 windows->image.shared_memory=MagickFalse; 01654 if (resource_info->title != (char *) NULL) 01655 { 01656 char 01657 *title; 01658 01659 title=InterpretImageProperties(resource_info->image_info,display_image, 01660 resource_info->title,exception); 01661 (void) CopyMagickString(windows->image.name,title,MaxTextExtent); 01662 (void) CopyMagickString(windows->image.icon_name,title,MaxTextExtent); 01663 title=DestroyString(title); 01664 } 01665 else 01666 { 01667 char 01668 filename[MaxTextExtent]; 01669 01670 /* 01671 Window name is the base of the filename. 01672 */ 01673 GetPathComponent(display_image->magick_filename,TailPath,filename); 01674 (void) FormatLocaleString(windows->image.name,MaxTextExtent, 01675 "%s: %s[scene: %.20g frames: %.20g]",MagickPackageName,filename,(double) 01676 display_image->scene,(double) number_scenes); 01677 (void) CopyMagickString(windows->image.icon_name,filename,MaxTextExtent); 01678 } 01679 if (resource_info->immutable != MagickFalse) 01680 windows->image.immutable=MagickTrue; 01681 windows->image.shape=MagickTrue; 01682 windows->image.geometry=resource_info->image_geometry; 01683 (void) FormatLocaleString(geometry,MaxTextExtent,"%ux%u+0+0>!", 01684 XDisplayWidth(display,visual_info->screen), 01685 XDisplayHeight(display,visual_info->screen)); 01686 geometry_info.width=display_image->columns; 01687 geometry_info.height=display_image->rows; 01688 geometry_info.x=0; 01689 geometry_info.y=0; 01690 (void) ParseMetaGeometry(geometry,&geometry_info.x,&geometry_info.y, 01691 &geometry_info.width,&geometry_info.height); 01692 windows->image.width=(unsigned int) geometry_info.width; 01693 windows->image.height=(unsigned int) geometry_info.height; 01694 windows->image.attributes.event_mask=ButtonMotionMask | ButtonPressMask | 01695 ButtonReleaseMask | EnterWindowMask | ExposureMask | KeyPressMask | 01696 KeyReleaseMask | LeaveWindowMask | OwnerGrabButtonMask | 01697 PropertyChangeMask | StructureNotifyMask | SubstructureNotifyMask; 01698 XGetWindowInfo(display,visual_info,map_info,pixel,font_info, 01699 resource_info,&windows->backdrop); 01700 if ((resource_info->backdrop) || (windows->backdrop.id != (Window) NULL)) 01701 { 01702 /* 01703 Initialize backdrop window. 01704 */ 01705 windows->backdrop.x=0; 01706 windows->backdrop.y=0; 01707 (void) CloneString(&windows->backdrop.name,"ImageMagick Backdrop"); 01708 windows->backdrop.flags=(size_t) (USSize | USPosition); 01709 windows->backdrop.width=(unsigned int) 01710 XDisplayWidth(display,visual_info->screen); 01711 windows->backdrop.height=(unsigned int) 01712 XDisplayHeight(display,visual_info->screen); 01713 windows->backdrop.border_width=0; 01714 windows->backdrop.immutable=MagickTrue; 01715 windows->backdrop.attributes.do_not_propagate_mask=ButtonPressMask | 01716 ButtonReleaseMask; 01717 windows->backdrop.attributes.event_mask=ButtonPressMask | KeyPressMask | 01718 StructureNotifyMask; 01719 manager_hints->flags=IconWindowHint | InputHint | StateHint; 01720 manager_hints->icon_window=windows->icon.id; 01721 manager_hints->input=MagickTrue; 01722 manager_hints->initial_state= 01723 resource_info->iconic ? IconicState : NormalState; 01724 XMakeWindow(display,root_window,argv,argc,class_hints,manager_hints, 01725 &windows->backdrop); 01726 if (display_image->debug != MagickFalse) 01727 (void) LogMagickEvent(X11Event,GetMagickModule(), 01728 "Window id: 0x%lx (backdrop)",windows->backdrop.id); 01729 (void) XMapWindow(display,windows->backdrop.id); 01730 (void) XClearWindow(display,windows->backdrop.id); 01731 if (windows->image.id != (Window) NULL) 01732 { 01733 (void) XDestroyWindow(display,windows->image.id); 01734 windows->image.id=(Window) NULL; 01735 } 01736 /* 01737 Position image in the center the backdrop. 01738 */ 01739 windows->image.flags|=USPosition; 01740 windows->image.x=(XDisplayWidth(display,visual_info->screen)/2)- 01741 (windows->image.width/2); 01742 windows->image.y=(XDisplayHeight(display,visual_info->screen)/2)- 01743 (windows->image.height/2); 01744 } 01745 manager_hints->flags=IconWindowHint | InputHint | StateHint; 01746 manager_hints->icon_window=windows->icon.id; 01747 manager_hints->input=MagickTrue; 01748 manager_hints->initial_state= 01749 resource_info->iconic ? IconicState : NormalState; 01750 if (windows->group_leader.id != (Window) NULL) 01751 { 01752 /* 01753 Follow the leader. 01754 */ 01755 manager_hints->flags|=(MagickStatusType) WindowGroupHint; 01756 manager_hints->window_group=windows->group_leader.id; 01757 (void) XSelectInput(display,windows->group_leader.id,StructureNotifyMask); 01758 if (display_image->debug != MagickFalse) 01759 (void) LogMagickEvent(X11Event,GetMagickModule(), 01760 "Window id: 0x%lx (group leader)",windows->group_leader.id); 01761 } 01762 XMakeWindow(display, 01763 (Window) (resource_info->backdrop ? windows->backdrop.id : root_window), 01764 argv,argc,class_hints,manager_hints,&windows->image); 01765 (void) XChangeProperty(display,windows->image.id,windows->im_protocols, 01766 XA_STRING,8,PropModeReplace,(unsigned char *) NULL,0); 01767 if (windows->group_leader.id != (Window) NULL) 01768 (void) XSetTransientForHint(display,windows->image.id, 01769 windows->group_leader.id); 01770 if (display_image->debug != MagickFalse) 01771 (void) LogMagickEvent(X11Event,GetMagickModule(),"Window id: 0x%lx (image)", 01772 windows->image.id); 01773 /* 01774 Initialize Info widget. 01775 */ 01776 XGetWindowInfo(display,visual_info,map_info,pixel,font_info, 01777 resource_info,&windows->info); 01778 (void) CloneString(&windows->info.name,"Info"); 01779 (void) CloneString(&windows->info.icon_name,"Info"); 01780 windows->info.border_width=1; 01781 windows->info.x=2; 01782 windows->info.y=2; 01783 windows->info.flags|=PPosition; 01784 windows->info.attributes.win_gravity=UnmapGravity; 01785 windows->info.attributes.event_mask=ButtonPressMask | ExposureMask | 01786 StructureNotifyMask; 01787 manager_hints->flags=InputHint | StateHint | WindowGroupHint; 01788 manager_hints->input=MagickFalse; 01789 manager_hints->initial_state=NormalState; 01790 manager_hints->window_group=windows->image.id; 01791 XMakeWindow(display,windows->image.id,argv,argc,class_hints,manager_hints, 01792 &windows->info); 01793 windows->info.highlight_stipple=XCreateBitmapFromData(display, 01794 windows->info.id,(char *) HighlightBitmap,HighlightWidth,HighlightHeight); 01795 windows->info.shadow_stipple=XCreateBitmapFromData(display, 01796 windows->info.id,(char *) ShadowBitmap,ShadowWidth,ShadowHeight); 01797 (void) XSetTransientForHint(display,windows->info.id,windows->image.id); 01798 if (windows->image.mapped) 01799 (void) XWithdrawWindow(display,windows->info.id,windows->info.screen); 01800 if (display_image->debug != MagickFalse) 01801 (void) LogMagickEvent(X11Event,GetMagickModule(),"Window id: 0x%lx (info)", 01802 windows->info.id); 01803 /* 01804 Initialize Command widget. 01805 */ 01806 XGetWindowInfo(display,visual_info,map_info,pixel,font_info, 01807 resource_info,&windows->command); 01808 windows->command.data=MagickMenus; 01809 (void) XCommandWidget(display,windows,CommandMenu,(XEvent *) NULL); 01810 (void) FormatLocaleString(resource_name,MaxTextExtent,"%s.command", 01811 resource_info->client_name); 01812 windows->command.geometry=XGetResourceClass(resource_info->resource_database, 01813 resource_name,"geometry",(char *) NULL); 01814 (void) CloneString(&windows->command.name,MagickTitle); 01815 windows->command.border_width=0; 01816 windows->command.flags|=PPosition; 01817 windows->command.attributes.event_mask=ButtonMotionMask | ButtonPressMask | 01818 ButtonReleaseMask | EnterWindowMask | ExposureMask | LeaveWindowMask | 01819 OwnerGrabButtonMask | StructureNotifyMask; 01820 manager_hints->flags=InputHint | StateHint | WindowGroupHint; 01821 manager_hints->input=MagickTrue; 01822 manager_hints->initial_state=NormalState; 01823 manager_hints->window_group=windows->image.id; 01824 XMakeWindow(display,root_window,argv,argc,class_hints,manager_hints, 01825 &windows->command); 01826 windows->command.highlight_stipple=XCreateBitmapFromData(display, 01827 windows->command.id,(char *) HighlightBitmap,HighlightWidth, 01828 HighlightHeight); 01829 windows->command.shadow_stipple=XCreateBitmapFromData(display, 01830 windows->command.id,(char *) ShadowBitmap,ShadowWidth,ShadowHeight); 01831 (void) XSetTransientForHint(display,windows->command.id,windows->image.id); 01832 if (display_image->debug != MagickFalse) 01833 (void) LogMagickEvent(X11Event,GetMagickModule(), 01834 "Window id: 0x%lx (command)",windows->command.id); 01835 /* 01836 Initialize Widget window. 01837 */ 01838 XGetWindowInfo(display,visual_info,map_info,pixel,font_info, 01839 resource_info,&windows->widget); 01840 (void) FormatLocaleString(resource_name,MaxTextExtent,"%s.widget", 01841 resource_info->client_name); 01842 windows->widget.geometry=XGetResourceClass(resource_info->resource_database, 01843 resource_name,"geometry",(char *) NULL); 01844 windows->widget.border_width=0; 01845 windows->widget.flags|=PPosition; 01846 windows->widget.attributes.event_mask=ButtonMotionMask | ButtonPressMask | 01847 ButtonReleaseMask | EnterWindowMask | ExposureMask | KeyPressMask | 01848 KeyReleaseMask | LeaveWindowMask | OwnerGrabButtonMask | 01849 StructureNotifyMask; 01850 manager_hints->flags=InputHint | StateHint | WindowGroupHint; 01851 manager_hints->input=MagickTrue; 01852 manager_hints->initial_state=NormalState; 01853 manager_hints->window_group=windows->image.id; 01854 XMakeWindow(display,root_window,argv,argc,class_hints,manager_hints, 01855 &windows->widget); 01856 windows->widget.highlight_stipple=XCreateBitmapFromData(display, 01857 windows->widget.id,(char *) HighlightBitmap,HighlightWidth,HighlightHeight); 01858 windows->widget.shadow_stipple=XCreateBitmapFromData(display, 01859 windows->widget.id,(char *) ShadowBitmap,ShadowWidth,ShadowHeight); 01860 (void) XSetTransientForHint(display,windows->widget.id,windows->image.id); 01861 if (display_image->debug != MagickFalse) 01862 (void) LogMagickEvent(X11Event,GetMagickModule(), 01863 "Window id: 0x%lx (widget)",windows->widget.id); 01864 /* 01865 Initialize popup window. 01866 */ 01867 XGetWindowInfo(display,visual_info,map_info,pixel,font_info, 01868 resource_info,&windows->popup); 01869 windows->popup.border_width=0; 01870 windows->popup.flags|=PPosition; 01871 windows->popup.attributes.event_mask=ButtonMotionMask | ButtonPressMask | 01872 ButtonReleaseMask | EnterWindowMask | ExposureMask | KeyPressMask | 01873 KeyReleaseMask | LeaveWindowMask | StructureNotifyMask; 01874 manager_hints->flags=InputHint | StateHint | WindowGroupHint; 01875 manager_hints->input=MagickTrue; 01876 manager_hints->initial_state=NormalState; 01877 manager_hints->window_group=windows->image.id; 01878 XMakeWindow(display,root_window,argv,argc,class_hints,manager_hints, 01879 &windows->popup); 01880 windows->popup.highlight_stipple=XCreateBitmapFromData(display, 01881 windows->popup.id,(char *) HighlightBitmap,HighlightWidth,HighlightHeight); 01882 windows->popup.shadow_stipple=XCreateBitmapFromData(display, 01883 windows->popup.id,(char *) ShadowBitmap,ShadowWidth,ShadowHeight); 01884 (void) XSetTransientForHint(display,windows->popup.id,windows->image.id); 01885 if (display_image->debug != MagickFalse) 01886 (void) LogMagickEvent(X11Event,GetMagickModule(), 01887 "Window id: 0x%lx (pop up)",windows->popup.id); 01888 /* 01889 Set out progress and warning handlers. 01890 */ 01891 if (warning_handler == (WarningHandler) NULL) 01892 { 01893 warning_handler=resource_info->display_warnings ? 01894 SetErrorHandler(XWarning) : SetErrorHandler((ErrorHandler) NULL); 01895 warning_handler=resource_info->display_warnings ? 01896 SetWarningHandler(XWarning) : SetWarningHandler((WarningHandler) NULL); 01897 } 01898 /* 01899 Initialize X image structure. 01900 */ 01901 windows->image.x=0; 01902 windows->image.y=0; 01903 /* 01904 Initialize image pixmaps structure. 01905 */ 01906 window_changes.width=(int) windows->image.width; 01907 window_changes.height=(int) windows->image.height; 01908 (void) XReconfigureWMWindow(display,windows->image.id,windows->command.screen, 01909 (unsigned int) (CWWidth | CWHeight),&window_changes); 01910 windows->image.pixmaps=(Pixmap *) AcquireQuantumMemory(number_scenes, 01911 sizeof(*windows->image.pixmaps)); 01912 windows->image.matte_pixmaps=(Pixmap *) AcquireQuantumMemory(number_scenes, 01913 sizeof(*windows->image.pixmaps)); 01914 if ((windows->image.pixmaps == (Pixmap *) NULL) || 01915 (windows->image.matte_pixmaps == (Pixmap *) NULL)) 01916 ThrowXWindowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed", 01917 images->filename); 01918 if ((windows->image.mapped == MagickFalse) || 01919 (windows->backdrop.id != (Window) NULL)) 01920 (void) XMapWindow(display,windows->image.id); 01921 XSetCursorState(display,windows,MagickTrue); 01922 for (scene=0; scene < (ssize_t) number_scenes; scene++) 01923 { 01924 unsigned int 01925 columns, 01926 rows; 01927 01928 /* 01929 Create X image. 01930 */ 01931 (void) TransformImageColorspace(image_list[scene],RGBColorspace,exception); 01932 windows->image.pixmap=(Pixmap) NULL; 01933 windows->image.matte_pixmap=(Pixmap) NULL; 01934 if ((resource_info->map_type != (char *) NULL) || 01935 (visual_info->klass == TrueColor) || 01936 (visual_info->klass == DirectColor)) 01937 if (image_list[scene]->storage_class == PseudoClass) 01938 XGetPixelInfo(display,visual_info,map_info,resource_info, 01939 image_list[scene],windows->image.pixel_info); 01940 columns=(unsigned int) image_list[scene]->columns; 01941 rows=(unsigned int) image_list[scene]->rows; 01942 if ((image_list[scene]->columns != columns) || 01943 (image_list[scene]->rows != rows)) 01944 ThrowXWindowFatalException(XServerFatalError,"UnableToCreateXImage", 01945 image_list[scene]->filename); 01946 status=XMakeImage(display,resource_info,&windows->image,image_list[scene], 01947 columns,rows,exception); 01948 if (status == MagickFalse) 01949 ThrowXWindowFatalException(XServerFatalError,"UnableToCreateXImage", 01950 images->filename); 01951 if (image_list[scene]->debug != MagickFalse) 01952 { 01953 (void) LogMagickEvent(X11Event,GetMagickModule(), 01954 "Image: [%.20g] %s %.20gx%.20g ",(double) image_list[scene]->scene, 01955 image_list[scene]->filename,(double) columns,(double) rows); 01956 if (image_list[scene]->colors != 0) 01957 (void) LogMagickEvent(X11Event,GetMagickModule(),"%.20gc ",(double) 01958 image_list[scene]->colors); 01959 (void) LogMagickEvent(X11Event,GetMagickModule(),"%s", 01960 image_list[scene]->magick); 01961 } 01962 /* 01963 Window name is the base of the filename. 01964 */ 01965 if (resource_info->title != (char *) NULL) 01966 { 01967 char 01968 *title; 01969 01970 title=InterpretImageProperties(resource_info->image_info, 01971 image_list[scene],resource_info->title,exception); 01972 (void) CopyMagickString(windows->image.name,title,MaxTextExtent); 01973 title=DestroyString(title); 01974 } 01975 else 01976 { 01977 p=image_list[scene]->magick_filename+ 01978 strlen(image_list[scene]->magick_filename)-1; 01979 while ((p > image_list[scene]->magick_filename) && (*(p-1) != '/')) 01980 p--; 01981 (void) FormatLocaleString(windows->image.name,MaxTextExtent, 01982 "%s: %s[%.20g of %.20g]",MagickPackageName,p,(double) scene+1, 01983 (double) number_scenes); 01984 } 01985 status=XStringListToTextProperty(&windows->image.name,1,&window_name); 01986 if (status != Success) 01987 { 01988 XSetWMName(display,windows->image.id,&window_name); 01989 (void) XFree((void *) window_name.value); 01990 } 01991 windows->image.pixmaps[scene]=windows->image.pixmap; 01992 windows->image.matte_pixmaps[scene]=windows->image.matte_pixmap; 01993 if (scene == 0) 01994 { 01995 event.xexpose.x=0; 01996 event.xexpose.y=0; 01997 event.xexpose.width=(int) image_list[scene]->columns; 01998 event.xexpose.height=(int) image_list[scene]->rows; 01999 XRefreshWindow(display,&windows->image,&event); 02000 (void) XSync(display,MagickFalse); 02001 } 02002 } 02003 XSetCursorState(display,windows,MagickFalse); 02004 if (windows->command.mapped) 02005 (void) XMapRaised(display,windows->command.id); 02006 /* 02007 Respond to events. 02008 */ 02009 nexus=NewImageList(); 02010 scene=0; 02011 first_scene=0; 02012 iterations=0; 02013 image=image_list[0]; 02014 state=(MagickStatusType) (ForwardAnimationState | RepeatAnimationState); 02015 (void) XMagickCommand(display,resource_info,windows,PlayCommand,&images, 02016 &state,exception); 02017 do 02018 { 02019 if (XEventsQueued(display,QueuedAfterFlush) == 0) 02020 if ((state & PlayAnimationState) || (state & StepAnimationState)) 02021 { 02022 MagickBooleanType 02023 pause; 02024 02025 pause=MagickFalse; 02026 delay=1000*image->delay/MagickMax(image->ticks_per_second,1L); 02027 XDelay(display,resource_info->delay*(delay == 0 ? 10 : delay)); 02028 if (state & ForwardAnimationState) 02029 { 02030 /* 02031 Forward animation: increment scene number. 02032 */ 02033 if (scene < ((ssize_t) number_scenes-1)) 02034 scene++; 02035 else 02036 { 02037 iterations++; 02038 if (iterations == (ssize_t) image_list[0]->iterations) 02039 { 02040 iterations=0; 02041 state|=ExitState; 02042 } 02043 if ((state & AutoReverseAnimationState) != 0) 02044 { 02045 state&=(~ForwardAnimationState); 02046 scene--; 02047 } 02048 else 02049 { 02050 if ((state & RepeatAnimationState) == 0) 02051 state&=(~PlayAnimationState); 02052 scene=first_scene; 02053 pause=MagickTrue; 02054 } 02055 } 02056 } 02057 else 02058 { 02059 /* 02060 Reverse animation: decrement scene number. 02061 */ 02062 if (scene > first_scene) 02063 scene--; 02064 else 02065 { 02066 iterations++; 02067 if (iterations == (ssize_t) image_list[0]->iterations) 02068 { 02069 iterations=0; 02070 state&=(~RepeatAnimationState); 02071 } 02072 if (state & AutoReverseAnimationState) 02073 { 02074 state|=ForwardAnimationState; 02075 scene=first_scene; 02076 pause=MagickTrue; 02077 } 02078 else 02079 { 02080 if ((state & RepeatAnimationState) == MagickFalse) 02081 state&=(~PlayAnimationState); 02082 scene=(ssize_t) number_scenes-1; 02083 } 02084 } 02085 } 02086 scene=MagickMax(scene,0); 02087 image=image_list[scene]; 02088 if ((image != (Image *) NULL) && (image->start_loop != 0)) 02089 first_scene=scene; 02090 if ((state & StepAnimationState) || 02091 (resource_info->title != (char *) NULL)) 02092 { 02093 /* 02094 Update window title. 02095 */ 02096 p=image_list[scene]->filename+ 02097 strlen(image_list[scene]->filename)-1; 02098 while ((p > image_list[scene]->filename) && (*(p-1) != '/')) 02099 p--; 02100 (void) FormatLocaleString(windows->image.name,MaxTextExtent, 02101 "%s: %s[%.20g of %.20g]",MagickPackageName,p,(double) 02102 scene+1,(double) number_scenes); 02103 if (resource_info->title != (char *) NULL) 02104 { 02105 char 02106 *title; 02107 02108 title=InterpretImageProperties(resource_info->image_info, 02109 image,resource_info->title,exception); 02110 (void) CopyMagickString(windows->image.name,title, 02111 MaxTextExtent); 02112 title=DestroyString(title); 02113 } 02114 status=XStringListToTextProperty(&windows->image.name,1, 02115 &window_name); 02116 if (status != Success) 02117 { 02118 XSetWMName(display,windows->image.id,&window_name); 02119 (void) XFree((void *) window_name.value); 02120 } 02121 } 02122 /* 02123 Copy X pixmap to Image window. 02124 */ 02125 XGetPixelInfo(display,visual_info,map_info,resource_info, 02126 image_list[scene],windows->image.pixel_info); 02127 windows->image.ximage->width=(int) image->columns; 02128 windows->image.ximage->height=(int) image->rows; 02129 windows->image.pixmap=windows->image.pixmaps[scene]; 02130 windows->image.matte_pixmap=windows->image.matte_pixmaps[scene]; 02131 event.xexpose.x=0; 02132 event.xexpose.y=0; 02133 event.xexpose.width=(int) image->columns; 02134 event.xexpose.height=(int) image->rows; 02135 if ((state & ExitState) == 0) 02136 { 02137 XRefreshWindow(display,&windows->image,&event); 02138 (void) XSync(display,MagickFalse); 02139 } 02140 state&=(~StepAnimationState); 02141 if (pause != MagickFalse) 02142 for (i=0; i < (ssize_t) resource_info->pause; i++) 02143 { 02144 int 02145 status; 02146 02147 status=XCheckTypedWindowEvent(display,windows->image.id,KeyPress, 02148 &event); 02149 if (status != 0) 02150 { 02151 int 02152 length; 02153 02154 length=XLookupString((XKeyEvent *) &event.xkey,command,(int) 02155 sizeof(command),&key_symbol,(XComposeStatus *) NULL); 02156 *(command+length)='\0'; 02157 if ((key_symbol == XK_q) || (key_symbol == XK_Escape)) 02158 { 02159 XClientMessage(display,windows->image.id, 02160 windows->im_protocols,windows->im_exit,CurrentTime); 02161 break; 02162 } 02163 } 02164 (void) sleep(1); 02165 } 02166 continue; 02167 } 02168 /* 02169 Handle a window event. 02170 */ 02171 timestamp=time((time_t *) NULL); 02172 (void) XNextEvent(display,&event); 02173 if (windows->image.stasis == MagickFalse) 02174 windows->image.stasis=(time((time_t *) NULL)-timestamp) > 0 ? 02175 MagickTrue : MagickFalse; 02176 if (event.xany.window == windows->command.id) 02177 { 02178 int 02179 id; 02180 02181 /* 02182 Select a command from the Command widget. 02183 */ 02184 id=XCommandWidget(display,windows,CommandMenu,&event); 02185 if (id < 0) 02186 continue; 02187 (void) CopyMagickString(command,CommandMenu[id],MaxTextExtent); 02188 command_type=CommandMenus[id]; 02189 if (id < MagickMenus) 02190 { 02191 int 02192 entry; 02193 02194 /* 02195 Select a command from a pop-up menu. 02196 */ 02197 entry=XMenuWidget(display,windows,CommandMenu[id],Menus[id], 02198 command); 02199 if (entry < 0) 02200 continue; 02201 (void) CopyMagickString(command,Menus[id][entry],MaxTextExtent); 02202 command_type=Commands[id][entry]; 02203 } 02204 if (command_type != NullCommand) 02205 nexus=XMagickCommand(display,resource_info,windows, 02206 command_type,&image,&state,exception); 02207 continue; 02208 } 02209 switch (event.type) 02210 { 02211 case ButtonPress: 02212 { 02213 if (display_image->debug != MagickFalse) 02214 (void) LogMagickEvent(X11Event,GetMagickModule(), 02215 "Button Press: 0x%lx %u +%d+%d",event.xbutton.window, 02216 event.xbutton.button,event.xbutton.x,event.xbutton.y); 02217 if ((event.xbutton.button == Button3) && 02218 (event.xbutton.state & Mod1Mask)) 02219 { 02220 /* 02221 Convert Alt-Button3 to Button2. 02222 */ 02223 event.xbutton.button=Button2; 02224 event.xbutton.state&=(~Mod1Mask); 02225 } 02226 if (event.xbutton.window == windows->backdrop.id) 02227 { 02228 (void) XSetInputFocus(display,event.xbutton.window,RevertToParent, 02229 event.xbutton.time); 02230 break; 02231 } 02232 if (event.xbutton.window == windows->image.id) 02233 { 02234 if (resource_info->immutable != MagickFalse) 02235 { 02236 state|=ExitState; 02237 break; 02238 } 02239 /* 02240 Map/unmap Command widget. 02241 */ 02242 if (windows->command.mapped) 02243 (void) XWithdrawWindow(display,windows->command.id, 02244 windows->command.screen); 02245 else 02246 { 02247 (void) XCommandWidget(display,windows,CommandMenu, 02248 (XEvent *) NULL); 02249 (void) XMapRaised(display,windows->command.id); 02250 } 02251 } 02252 break; 02253 } 02254 case ButtonRelease: 02255 { 02256 if (display_image->debug != MagickFalse) 02257 (void) LogMagickEvent(X11Event,GetMagickModule(), 02258 "Button Release: 0x%lx %u +%d+%d",event.xbutton.window, 02259 event.xbutton.button,event.xbutton.x,event.xbutton.y); 02260 break; 02261 } 02262 case ClientMessage: 02263 { 02264 if (display_image->debug != MagickFalse) 02265 (void) LogMagickEvent(X11Event,GetMagickModule(), 02266 "Client Message: 0x%lx 0x%lx %d 0x%lx",(unsigned long) 02267 event.xclient.window,(unsigned long) event.xclient.message_type, 02268 event.xclient.format,(unsigned long) event.xclient.data.l[0]); 02269 if (event.xclient.message_type == windows->im_protocols) 02270 { 02271 if (*event.xclient.data.l == (long) windows->im_update_colormap) 02272 { 02273 /* 02274 Update graphic context and window colormap. 02275 */ 02276 for (i=0; i < (ssize_t) number_windows; i++) 02277 { 02278 if (magick_windows[i]->id == windows->icon.id) 02279 continue; 02280 context_values.background=pixel->background_color.pixel; 02281 context_values.foreground=pixel->foreground_color.pixel; 02282 (void) XChangeGC(display,magick_windows[i]->annotate_context, 02283 context_mask,&context_values); 02284 (void) XChangeGC(display,magick_windows[i]->widget_context, 02285 context_mask,&context_values); 02286 context_values.background=pixel->foreground_color.pixel; 02287 context_values.foreground=pixel->background_color.pixel; 02288 context_values.plane_mask= 02289 context_values.background ^ context_values.foreground; 02290 (void) XChangeGC(display,magick_windows[i]->highlight_context, 02291 (size_t) (context_mask | GCPlaneMask), 02292 &context_values); 02293 magick_windows[i]->attributes.background_pixel= 02294 pixel->background_color.pixel; 02295 magick_windows[i]->attributes.border_pixel= 02296 pixel->border_color.pixel; 02297 magick_windows[i]->attributes.colormap=map_info->colormap; 02298 (void) XChangeWindowAttributes(display,magick_windows[i]->id, 02299 (unsigned long) magick_windows[i]->mask, 02300 &magick_windows[i]->attributes); 02301 } 02302 if (windows->backdrop.id != (Window) NULL) 02303 (void) XInstallColormap(display,map_info->colormap); 02304 break; 02305 } 02306 if (*event.xclient.data.l == (long) windows->im_exit) 02307 { 02308 state|=ExitState; 02309 break; 02310 } 02311 break; 02312 } 02313 if (event.xclient.message_type == windows->dnd_protocols) 02314 { 02315 Atom 02316 selection, 02317 type; 02318 02319 int 02320 format, 02321 status; 02322 02323 unsigned char 02324 *data; 02325 02326 unsigned long 02327 after, 02328 length; 02329 02330 /* 02331 Display image named by the Drag-and-Drop selection. 02332 */ 02333 if ((*event.xclient.data.l != 2) && (*event.xclient.data.l != 128)) 02334 break; 02335 selection=XInternAtom(display,"DndSelection",MagickFalse); 02336 status=XGetWindowProperty(display,root_window,selection,0L,2047L, 02337 MagickFalse,(Atom) AnyPropertyType,&type,&format,&length,&after, 02338 &data); 02339 if ((status != Success) || (length == 0)) 02340 break; 02341 if (*event.xclient.data.l == 2) 02342 { 02343 /* 02344 Offix DND. 02345 */ 02346 (void) CopyMagickString(resource_info->image_info->filename, 02347 (char *) data,MaxTextExtent); 02348 } 02349 else 02350 { 02351 /* 02352 XDND. 02353 */ 02354 if (LocaleNCompare((char *) data,"file:",5) != 0) 02355 { 02356 (void) XFree((void *) data); 02357 break; 02358 } 02359 (void) CopyMagickString(resource_info->image_info->filename, 02360 ((char *) data)+5,MaxTextExtent); 02361 } 02362 nexus=ReadImage(resource_info->image_info,exception); 02363 CatchException(exception); 02364 if (nexus != (Image *) NULL) 02365 state|=ExitState; 02366 (void) XFree((void *) data); 02367 break; 02368 } 02369 /* 02370 If client window delete message, exit. 02371 */ 02372 if (event.xclient.message_type != windows->wm_protocols) 02373 break; 02374 if (*event.xclient.data.l == (long) windows->wm_take_focus) 02375 { 02376 (void) XSetInputFocus(display,event.xclient.window,RevertToParent, 02377 (Time) event.xclient.data.l[1]); 02378 break; 02379 } 02380 if (*event.xclient.data.l != (long) windows->wm_delete_window) 02381 break; 02382 (void) XWithdrawWindow(display,event.xclient.window, 02383 visual_info->screen); 02384 if (event.xclient.window == windows->image.id) 02385 { 02386 state|=ExitState; 02387 break; 02388 } 02389 break; 02390 } 02391 case ConfigureNotify: 02392 { 02393 if (display_image->debug != MagickFalse) 02394 (void) LogMagickEvent(X11Event,GetMagickModule(), 02395 "Configure Notify: 0x%lx %dx%d+%d+%d %d",event.xconfigure.window, 02396 event.xconfigure.width,event.xconfigure.height,event.xconfigure.x, 02397 event.xconfigure.y,event.xconfigure.send_event); 02398 if (event.xconfigure.window == windows->image.id) 02399 { 02400 if (event.xconfigure.send_event != 0) 02401 { 02402 XWindowChanges 02403 window_changes; 02404 02405 /* 02406 Position the transient windows relative of the Image window. 02407 */ 02408 if (windows->command.geometry == (char *) NULL) 02409 if (windows->command.mapped == MagickFalse) 02410 { 02411 windows->command.x= 02412 event.xconfigure.x-windows->command.width-25; 02413 windows->command.y=event.xconfigure.y; 02414 XConstrainWindowPosition(display,&windows->command); 02415 window_changes.x=windows->command.x; 02416 window_changes.y=windows->command.y; 02417 (void) XReconfigureWMWindow(display,windows->command.id, 02418 windows->command.screen,(unsigned int) (CWX | CWY), 02419 &window_changes); 02420 } 02421 if (windows->widget.geometry == (char *) NULL) 02422 if (windows->widget.mapped == MagickFalse) 02423 { 02424 windows->widget.x= 02425 event.xconfigure.x+event.xconfigure.width/10; 02426 windows->widget.y= 02427 event.xconfigure.y+event.xconfigure.height/10; 02428 XConstrainWindowPosition(display,&windows->widget); 02429 window_changes.x=windows->widget.x; 02430 window_changes.y=windows->widget.y; 02431 (void) XReconfigureWMWindow(display,windows->widget.id, 02432 windows->widget.screen,(unsigned int) (CWX | CWY), 02433 &window_changes); 02434 } 02435 } 02436 /* 02437 Image window has a new configuration. 02438 */ 02439 windows->image.width=(unsigned int) event.xconfigure.width; 02440 windows->image.height=(unsigned int) event.xconfigure.height; 02441 break; 02442 } 02443 if (event.xconfigure.window == windows->icon.id) 02444 { 02445 /* 02446 Icon window has a new configuration. 02447 */ 02448 windows->icon.width=(unsigned int) event.xconfigure.width; 02449 windows->icon.height=(unsigned int) event.xconfigure.height; 02450 break; 02451 } 02452 break; 02453 } 02454 case DestroyNotify: 02455 { 02456 /* 02457 Group leader has exited. 02458 */ 02459 if (display_image->debug != MagickFalse) 02460 (void) LogMagickEvent(X11Event,GetMagickModule(), 02461 "Destroy Notify: 0x%lx",event.xdestroywindow.window); 02462 if (event.xdestroywindow.window == windows->group_leader.id) 02463 { 02464 state|=ExitState; 02465 break; 02466 } 02467 break; 02468 } 02469 case EnterNotify: 02470 { 02471 /* 02472 Selectively install colormap. 02473 */ 02474 if (map_info->colormap != XDefaultColormap(display,visual_info->screen)) 02475 if (event.xcrossing.mode != NotifyUngrab) 02476 XInstallColormap(display,map_info->colormap); 02477 break; 02478 } 02479 case Expose: 02480 { 02481 if (display_image->debug != MagickFalse) 02482 (void) LogMagickEvent(X11Event,GetMagickModule(), 02483 "Expose: 0x%lx %dx%d+%d+%d",event.xexpose.window, 02484 event.xexpose.width,event.xexpose.height,event.xexpose.x, 02485 event.xexpose.y); 02486 /* 02487 Repaint windows that are now exposed. 02488 */ 02489 if (event.xexpose.window == windows->image.id) 02490 { 02491 windows->image.pixmap=windows->image.pixmaps[scene]; 02492 windows->image.matte_pixmap=windows->image.matte_pixmaps[scene]; 02493 XRefreshWindow(display,&windows->image,&event); 02494 break; 02495 } 02496 if (event.xexpose.window == windows->icon.id) 02497 if (event.xexpose.count == 0) 02498 { 02499 XRefreshWindow(display,&windows->icon,&event); 02500 break; 02501 } 02502 break; 02503 } 02504 case KeyPress: 02505 { 02506 static int 02507 length; 02508 02509 /* 02510 Respond to a user key press. 02511 */ 02512 length=XLookupString((XKeyEvent *) &event.xkey,command,(int) 02513 sizeof(command),&key_symbol,(XComposeStatus *) NULL); 02514 *(command+length)='\0'; 02515 if (display_image->debug != MagickFalse) 02516 (void) LogMagickEvent(X11Event,GetMagickModule(), 02517 "Key press: 0x%lx (%c)",(unsigned long) key_symbol,*command); 02518 command_type=NullCommand; 02519 switch (key_symbol) 02520 { 02521 case XK_o: 02522 { 02523 if ((event.xkey.state & ControlMask) == MagickFalse) 02524 break; 02525 command_type=OpenCommand; 02526 break; 02527 } 02528 case XK_BackSpace: 02529 { 02530 command_type=StepBackwardCommand; 02531 break; 02532 } 02533 case XK_space: 02534 { 02535 command_type=StepForwardCommand; 02536 break; 02537 } 02538 case XK_less: 02539 { 02540 command_type=FasterCommand; 02541 break; 02542 } 02543 case XK_greater: 02544 { 02545 command_type=SlowerCommand; 02546 break; 02547 } 02548 case XK_F1: 02549 { 02550 command_type=HelpCommand; 02551 break; 02552 } 02553 case XK_Find: 02554 { 02555 command_type=BrowseDocumentationCommand; 02556 break; 02557 } 02558 case XK_question: 02559 { 02560 command_type=InfoCommand; 02561 break; 02562 } 02563 case XK_q: 02564 case XK_Escape: 02565 { 02566 command_type=QuitCommand; 02567 break; 02568 } 02569 default: 02570 break; 02571 } 02572 if (command_type != NullCommand) 02573 nexus=XMagickCommand(display,resource_info,windows, 02574 command_type,&image,&state,exception); 02575 break; 02576 } 02577 case KeyRelease: 02578 { 02579 /* 02580 Respond to a user key release. 02581 */ 02582 (void) XLookupString((XKeyEvent *) &event.xkey,command,(int) 02583 sizeof(command),&key_symbol,(XComposeStatus *) NULL); 02584 if (display_image->debug != MagickFalse) 02585 (void) LogMagickEvent(X11Event,GetMagickModule(), 02586 "Key release: 0x%lx (%c)",(unsigned long) key_symbol,*command); 02587 break; 02588 } 02589 case LeaveNotify: 02590 { 02591 /* 02592 Selectively uninstall colormap. 02593 */ 02594 if (map_info->colormap != XDefaultColormap(display,visual_info->screen)) 02595 if (event.xcrossing.mode != NotifyUngrab) 02596 XUninstallColormap(display,map_info->colormap); 02597 break; 02598 } 02599 case MapNotify: 02600 { 02601 if (display_image->debug != MagickFalse) 02602 (void) LogMagickEvent(X11Event,GetMagickModule(),"Map Notify: 0x%lx", 02603 event.xmap.window); 02604 if (event.xmap.window == windows->backdrop.id) 02605 { 02606 (void) XSetInputFocus(display,event.xmap.window,RevertToParent, 02607 CurrentTime); 02608 windows->backdrop.mapped=MagickTrue; 02609 break; 02610 } 02611 if (event.xmap.window == windows->image.id) 02612 { 02613 if (windows->backdrop.id != (Window) NULL) 02614 (void) XInstallColormap(display,map_info->colormap); 02615 if (LocaleCompare(image_list[0]->magick,"LOGO") == 0) 02616 { 02617 if (LocaleCompare(display_image->filename,"LOGO") == 0) 02618 nexus=XMagickCommand(display,resource_info,windows, 02619 OpenCommand,&image,&state,exception); 02620 else 02621 state|=ExitState; 02622 } 02623 windows->image.mapped=MagickTrue; 02624 break; 02625 } 02626 if (event.xmap.window == windows->info.id) 02627 { 02628 windows->info.mapped=MagickTrue; 02629 break; 02630 } 02631 if (event.xmap.window == windows->icon.id) 02632 { 02633 /* 02634 Create an icon image. 02635 */ 02636 XMakeStandardColormap(display,icon_visual,icon_resources, 02637 display_image,icon_map,icon_pixel,exception); 02638 (void) XMakeImage(display,icon_resources,&windows->icon, 02639 display_image,windows->icon.width,windows->icon.height, 02640 exception); 02641 (void) XSetWindowBackgroundPixmap(display,windows->icon.id, 02642 windows->icon.pixmap); 02643 (void) XClearWindow(display,windows->icon.id); 02644 (void) XWithdrawWindow(display,windows->info.id, 02645 windows->info.screen); 02646 windows->icon.mapped=MagickTrue; 02647 break; 02648 } 02649 if (event.xmap.window == windows->command.id) 02650 { 02651 windows->command.mapped=MagickTrue; 02652 break; 02653 } 02654 if (event.xmap.window == windows->popup.id) 02655 { 02656 windows->popup.mapped=MagickTrue; 02657 break; 02658 } 02659 if (event.xmap.window == windows->widget.id) 02660 { 02661 windows->widget.mapped=MagickTrue; 02662 break; 02663 } 02664 break; 02665 } 02666 case MappingNotify: 02667 { 02668 (void) XRefreshKeyboardMapping(&event.xmapping); 02669 break; 02670 } 02671 case NoExpose: 02672 break; 02673 case PropertyNotify: 02674 { 02675 Atom 02676 type; 02677 02678 int 02679 format, 02680 status; 02681 02682 unsigned char 02683 *data; 02684 02685 unsigned long 02686 after, 02687 length; 02688 02689 if (display_image->debug != MagickFalse) 02690 (void) LogMagickEvent(X11Event,GetMagickModule(), 02691 "Property Notify: 0x%lx 0x%lx %d",(unsigned long) 02692 event.xproperty.window,(unsigned long) event.xproperty.atom, 02693 event.xproperty.state); 02694 if (event.xproperty.atom != windows->im_remote_command) 02695 break; 02696 /* 02697 Display image named by the remote command protocol. 02698 */ 02699 status=XGetWindowProperty(display,event.xproperty.window, 02700 event.xproperty.atom,0L,(long) MaxTextExtent,MagickFalse,(Atom) 02701 AnyPropertyType,&type,&format,&length,&after,&data); 02702 if ((status != Success) || (length == 0)) 02703 break; 02704 (void) CopyMagickString(resource_info->image_info->filename, 02705 (char *) data,MaxTextExtent); 02706 nexus=ReadImage(resource_info->image_info,exception); 02707 CatchException(exception); 02708 if (nexus != (Image *) NULL) 02709 state|=ExitState; 02710 (void) XFree((void *) data); 02711 break; 02712 } 02713 case ReparentNotify: 02714 { 02715 if (display_image->debug != MagickFalse) 02716 (void) LogMagickEvent(X11Event,GetMagickModule(), 02717 "Reparent Notify: 0x%lx=>0x%lx",event.xreparent.parent, 02718 event.xreparent.window); 02719 break; 02720 } 02721 case UnmapNotify: 02722 { 02723 if (display_image->debug != MagickFalse) 02724 (void) LogMagickEvent(X11Event,GetMagickModule(), 02725 "Unmap Notify: 0x%lx",event.xunmap.window); 02726 if (event.xunmap.window == windows->backdrop.id) 02727 { 02728 windows->backdrop.mapped=MagickFalse; 02729 break; 02730 } 02731 if (event.xunmap.window == windows->image.id) 02732 { 02733 windows->image.mapped=MagickFalse; 02734 break; 02735 } 02736 if (event.xunmap.window == windows->info.id) 02737 { 02738 windows->info.mapped=MagickFalse; 02739 break; 02740 } 02741 if (event.xunmap.window == windows->icon.id) 02742 { 02743 if (map_info->colormap == icon_map->colormap) 02744 XConfigureImageColormap(display,resource_info,windows, 02745 display_image,exception); 02746 (void) XFreeStandardColormap(display,icon_visual,icon_map, 02747 icon_pixel); 02748 windows->icon.mapped=MagickFalse; 02749 break; 02750 } 02751 if (event.xunmap.window == windows->command.id) 02752 { 02753 windows->command.mapped=MagickFalse; 02754 break; 02755 } 02756 if (event.xunmap.window == windows->popup.id) 02757 { 02758 if (windows->backdrop.id != (Window) NULL) 02759 (void) XSetInputFocus(display,windows->image.id,RevertToParent, 02760 CurrentTime); 02761 windows->popup.mapped=MagickFalse; 02762 break; 02763 } 02764 if (event.xunmap.window == windows->widget.id) 02765 { 02766 if (windows->backdrop.id != (Window) NULL) 02767 (void) XSetInputFocus(display,windows->image.id,RevertToParent, 02768 CurrentTime); 02769 windows->widget.mapped=MagickFalse; 02770 break; 02771 } 02772 break; 02773 } 02774 default: 02775 { 02776 if (display_image->debug != MagickFalse) 02777 (void) LogMagickEvent(X11Event,GetMagickModule(),"Event type: %d", 02778 event.type); 02779 break; 02780 } 02781 } 02782 } 02783 while (!(state & ExitState)); 02784 image_list=(Image **) RelinquishMagickMemory(image_list); 02785 images=DestroyImageList(images); 02786 if ((windows->visual_info->klass == GrayScale) || 02787 (windows->visual_info->klass == PseudoColor) || 02788 (windows->visual_info->klass == DirectColor)) 02789 { 02790 /* 02791 Withdraw windows. 02792 */ 02793 if (windows->info.mapped) 02794 (void) XWithdrawWindow(display,windows->info.id,windows->info.screen); 02795 if (windows->command.mapped) 02796 (void) XWithdrawWindow(display,windows->command.id, 02797 windows->command.screen); 02798 } 02799 if (resource_info->backdrop == MagickFalse) 02800 if (windows->backdrop.mapped) 02801 { 02802 (void) XWithdrawWindow(display,windows->backdrop.id,\ 02803 windows->backdrop.screen); 02804 (void) XDestroyWindow(display,windows->backdrop.id); 02805 windows->backdrop.id=(Window) NULL; 02806 (void) XWithdrawWindow(display,windows->image.id,windows->image.screen); 02807 (void) XDestroyWindow(display,windows->image.id); 02808 windows->image.id=(Window) NULL; 02809 } 02810 XSetCursorState(display,windows,MagickTrue); 02811 XCheckRefreshWindows(display,windows); 02812 for (scene=1; scene < (ssize_t) number_scenes; scene++) 02813 { 02814 if (windows->image.pixmaps[scene] != (Pixmap) NULL) 02815 (void) XFreePixmap(display,windows->image.pixmaps[scene]); 02816 windows->image.pixmaps[scene]=(Pixmap) NULL; 02817 if (windows->image.matte_pixmaps[scene] != (Pixmap) NULL) 02818 (void) XFreePixmap(display,windows->image.matte_pixmaps[scene]); 02819 windows->image.matte_pixmaps[scene]=(Pixmap) NULL; 02820 } 02821 XSetCursorState(display,windows,MagickFalse); 02822 windows->image.pixmaps=(Pixmap *) 02823 RelinquishMagickMemory(windows->image.pixmaps); 02824 windows->image.matte_pixmaps=(Pixmap *) 02825 RelinquishMagickMemory(windows->image.matte_pixmaps); 02826 if (nexus == (Image *) NULL) 02827 { 02828 /* 02829 Free X resources. 02830 */ 02831 if (windows->image.mapped != MagickFalse) 02832 (void) XWithdrawWindow(display,windows->image.id,windows->image.screen); XDelay(display,SuspendTime); 02833 (void) XFreeStandardColormap(display,icon_visual,icon_map,icon_pixel); 02834 if (resource_info->map_type == (char *) NULL) 02835 (void) XFreeStandardColormap(display,visual_info,map_info,pixel); 02836 DestroyXResources(); 02837 } 02838 (void) XSync(display,MagickFalse); 02839 /* 02840 Restore our progress monitor and warning handlers. 02841 */ 02842 (void) SetErrorHandler(warning_handler); 02843 (void) SetWarningHandler(warning_handler); 02844 /* 02845 Change to home directory. 02846 */ 02847 directory=getcwd(working_directory,MaxTextExtent); 02848 (void) directory; 02849 status=chdir(resource_info->home_directory); 02850 if (status == -1) 02851 (void) ThrowMagickException(exception,GetMagickModule(),FileOpenError, 02852 "UnableToOpenFile","%s",resource_info->home_directory); 02853 return(nexus); 02854 } 02855 02856 /* 02857 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 02858 % % 02859 % % 02860 % % 02861 + X S a v e I m a g e % 02862 % % 02863 % % 02864 % % 02865 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 02866 % 02867 % XSaveImage() saves an image to a file. 02868 % 02869 % The format of the XSaveImage method is: 02870 % 02871 % MagickBooleanType XSaveImage(Display *display, 02872 % XResourceInfo *resource_info,XWindows *windows,Image *image, 02873 % ExceptionInfo *exception) 02874 % 02875 % A description of each parameter follows: 02876 % 02877 % o status: Method XSaveImage return True if the image is 02878 % written. False is returned is there is a memory shortage or if the 02879 % image fails to write. 02880 % 02881 % o display: Specifies a connection to an X server; returned from 02882 % XOpenDisplay. 02883 % 02884 % o resource_info: Specifies a pointer to a X11 XResourceInfo structure. 02885 % 02886 % o windows: Specifies a pointer to a XWindows structure. 02887 % 02888 % o image: the image. 02889 % 02890 */ 02891 static MagickBooleanType XSaveImage(Display *display, 02892 XResourceInfo *resource_info,XWindows *windows,Image *image, 02893 ExceptionInfo *exception) 02894 { 02895 char 02896 filename[MaxTextExtent]; 02897 02898 ImageInfo 02899 *image_info; 02900 02901 MagickStatusType 02902 status; 02903 02904 /* 02905 Request file name from user. 02906 */ 02907 if (resource_info->write_filename != (char *) NULL) 02908 (void) CopyMagickString(filename,resource_info->write_filename, 02909 MaxTextExtent); 02910 else 02911 { 02912 char 02913 path[MaxTextExtent]; 02914 02915 int 02916 status; 02917 02918 GetPathComponent(image->filename,HeadPath,path); 02919 GetPathComponent(image->filename,TailPath,filename); 02920 status=chdir(path); 02921 if (status == -1) 02922 (void) ThrowMagickException(exception,GetMagickModule(),FileOpenError, 02923 "UnableToOpenFile","%s",path); 02924 } 02925 XFileBrowserWidget(display,windows,"Save",filename); 02926 if (*filename == '\0') 02927 return(MagickTrue); 02928 if (IsPathAccessible(filename) != MagickFalse) 02929 { 02930 int 02931 status; 02932 02933 /* 02934 File exists-- seek user's permission before overwriting. 02935 */ 02936 status=XConfirmWidget(display,windows,"Overwrite",filename); 02937 if (status == 0) 02938 return(MagickTrue); 02939 } 02940 image_info=CloneImageInfo(resource_info->image_info); 02941 (void) CopyMagickString(image_info->filename,filename,MaxTextExtent); 02942 (void) SetImageInfo(image_info,1,exception); 02943 if ((LocaleCompare(image_info->magick,"JPEG") == 0) || 02944 (LocaleCompare(image_info->magick,"JPG") == 0)) 02945 { 02946 char 02947 quality[MaxTextExtent]; 02948 02949 int 02950 status; 02951 02952 /* 02953 Request JPEG quality from user. 02954 */ 02955 (void) FormatLocaleString(quality,MaxTextExtent,"%.20g",(double) 02956 image_info->quality); 02957 status=XDialogWidget(display,windows,"Save","Enter JPEG quality:", 02958 quality); 02959 if (*quality == '\0') 02960 return(MagickTrue); 02961 image->quality=StringToUnsignedLong(quality); 02962 image_info->interlace=status != MagickFalse ? NoInterlace : 02963 PlaneInterlace; 02964 } 02965 if ((LocaleCompare(image_info->magick,"EPS") == 0) || 02966 (LocaleCompare(image_info->magick,"PDF") == 0) || 02967 (LocaleCompare(image_info->magick,"PS") == 0) || 02968 (LocaleCompare(image_info->magick,"PS2") == 0)) 02969 { 02970 char 02971 geometry[MaxTextExtent]; 02972 02973 /* 02974 Request page geometry from user. 02975 */ 02976 (void) CopyMagickString(geometry,PSPageGeometry,MaxTextExtent); 02977 if (LocaleCompare(image_info->magick,"PDF") == 0) 02978 (void) CopyMagickString(geometry,PSPageGeometry,MaxTextExtent); 02979 if (image_info->page != (char *) NULL) 02980 (void) CopyMagickString(geometry,image_info->page,MaxTextExtent); 02981 XListBrowserWidget(display,windows,&windows->widget,PageSizes,"Select", 02982 "Select page geometry:",geometry); 02983 if (*geometry != '\0') 02984 image_info->page=GetPageGeometry(geometry); 02985 } 02986 /* 02987 Write image. 02988 */ 02989 image=GetFirstImageInList(image); 02990 status=WriteImages(image_info,image,filename,exception); 02991 if (status != MagickFalse) 02992 image->taint=MagickFalse; 02993 image_info=DestroyImageInfo(image_info); 02994 XSetCursorState(display,windows,MagickFalse); 02995 return(status != 0 ? MagickTrue : MagickFalse); 02996 } 02997 #else 02998 02999 /* 03000 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 03001 % % 03002 % % 03003 % % 03004 + A n i m a t e I m a g e s % 03005 % % 03006 % % 03007 % % 03008 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 03009 % 03010 % AnimateImages() repeatedly displays an image sequence to any X window 03011 % screen. It returns a value other than 0 if successful. Check the 03012 % exception member of image to determine the reason for any failure. 03013 % 03014 % The format of the AnimateImages method is: 03015 % 03016 % MagickBooleanType AnimateImages(const ImageInfo *image_info, 03017 % Image *images) 03018 % 03019 % A description of each parameter follows: 03020 % 03021 % o image_info: the image info. 03022 % 03023 % o image: the image. 03024 % 03025 % o exception: return any errors or warnings in this structure. 03026 % 03027 */ 03028 MagickExport MagickBooleanType AnimateImages(const ImageInfo *image_info, 03029 Image *image,ExceptionInfo *exception) 03030 { 03031 assert(image_info != (const ImageInfo *) NULL); 03032 assert(image_info->signature == MagickSignature); 03033 assert(image != (Image *) NULL); 03034 assert(image->signature == MagickSignature); 03035 if (image->debug != MagickFalse) 03036 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename); 03037 (void) ThrowMagickException(exception,GetMagickModule(),MissingDelegateError, 03038 "DelegateLibrarySupportNotBuiltIn","`%s' (X11)",image->filename); 03039 return(MagickFalse); 03040 } 03041 #endif