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