]> granicus.if.org Git - imagemagick/blob - magick/xwindow.c
(no commit message)
[imagemagick] / magick / xwindow.c
1 /*
2 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3 %                                                                             %
4 %                                                                             %
5 %                                                                             %
6 %              X   X  W   W  IIIII  N   N  DDDD    OOO   W   W                %
7 %               X X   W   W    I    NN  N  D   D  O   O  W   W                %
8 %                X    W   W    I    N N N  D   D  O   O  W   W                %
9 %               X X   W W W    I    N  NN  D   D  O   O  W W W                %
10 %              X   X   W W   IIIII  N   N  DDDD    OOO    W W                 %
11 %                                                                             %
12 %                                                                             %
13 %                       MagickCore X11 Utility Methods                        %
14 %                                                                             %
15 %                               Software Design                               %
16 %                                 John Cristy                                 %
17 %                                  July 1992                                  %
18 %                                                                             %
19 %                                                                             %
20 %  Copyright 1999-2010 ImageMagick Studio LLC, a non-profit organization      %
21 %  dedicated to making software imaging solutions freely available.           %
22 %                                                                             %
23 %  You may not use this file except in compliance with the License.  You may  %
24 %  obtain a copy of the License at                                            %
25 %                                                                             %
26 %    http://www.imagemagick.org/script/license.php                            %
27 %                                                                             %
28 %  Unless required by applicable law or agreed to in writing, software        %
29 %  distributed under the License is distributed on an "AS IS" BASIS,          %
30 %  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.   %
31 %  See the License for the specific language governing permissions and        %
32 %  limitations under the License.                                             %
33 %                                                                             %
34 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
35 %
36 %
37 */
38 \f
39 /*
40   Include declarations.
41 */
42 #include "magick/studio.h"
43 #include "magick/animate.h"
44 #include "magick/artifact.h"
45 #include "magick/blob.h"
46 #include "magick/cache.h"
47 #include "magick/client.h"
48 #include "magick/color.h"
49 #include "magick/color-private.h"
50 #include "magick/composite.h"
51 #include "magick/display.h"
52 #include "magick/exception.h"
53 #include "magick/exception-private.h"
54 #include "magick/geometry.h"
55 #include "magick/identify.h"
56 #include "magick/image.h"
57 #include "magick/image-private.h"
58 #include "magick/list.h"
59 #include "magick/locale_.h"
60 #include "magick/log.h"
61 #include "magick/magick.h"
62 #include "magick/memory_.h"
63 #include "magick/monitor.h"
64 #include "magick/option.h"
65 #include "magick/PreRvIcccm.h"
66 #include "magick/quantize.h"
67 #include "magick/quantum.h"
68 #include "magick/quantum-private.h"
69 #include "magick/resource_.h"
70 #include "magick/resize.h"
71 #include "magick/shear.h"
72 #include "magick/statistic.h"
73 #include "magick/string_.h"
74 #include "magick/string-private.h"
75 #include "magick/transform.h"
76 #include "magick/utility.h"
77 #include "magick/widget.h"
78 #include "magick/xwindow.h"
79 #include "magick/xwindow-private.h"
80 #include "magick/version.h"
81 #if defined(__BEOS__)
82 #include <OS.h>
83 #endif
84 #if defined(MAGICKCORE_X11_DELEGATE)
85 #include <X11/Xproto.h>
86 #include <X11/Xlocale.h>
87 #if defined(MAGICK_HAVE_POLL)
88 # include <sys/poll.h>
89 #endif
90 #if defined(MAGICKCORE_HAVE_SHARED_MEMORY)
91 #if defined(MAGICKCORE_HAVE_MACHINE_PARAM_H)
92 # include <machine/param.h>
93 #endif
94 #include <sys/ipc.h>
95 #include <sys/shm.h>
96 #include <X11/extensions/XShm.h>
97 #endif
98 #if defined(MAGICKCORE_HAVE_SHAPE)
99 #include <X11/extensions/shape.h>
100 #endif
101 \f
102 /*
103   X defines.
104 */
105 #define XBlueGamma(color) RoundToQuantum(blue_gamma == 1.0 ? (double) \
106   (color) : ((pow(((double) QuantumScale*(color)),1.0/(double) blue_gamma)* \
107   QuantumRange)))
108 #define XGammaPixel(map,color)  (unsigned long) (map->base_pixel+ \
109   ((ScaleQuantumToShort(XRedGamma((color)->red))*map->red_max/65535L)* \
110     map->red_mult)+ \
111   ((ScaleQuantumToShort(XGreenGamma((color)->green))*map->green_max/65535L)* \
112     map->green_mult)+ \
113   ((ScaleQuantumToShort(XBlueGamma((color)->blue))*map->blue_max/65535L)* \
114     map->blue_mult))
115 #define XGreenGamma(color) RoundToQuantum(green_gamma == 1.0 ? (double) \
116   (color) : ((pow(((double) QuantumScale*(color)),1.0/(double) green_gamma)* \
117   QuantumRange)))
118 #define XRedGamma(color) RoundToQuantum(red_gamma == 1.0 ? (double) \
119   (color) : ((pow(((double) QuantumScale*(color)),1.0/(double) red_gamma)* \
120   QuantumRange)))
121 #define XStandardPixel(map,color)  (unsigned long) (map->base_pixel+ \
122   (((color)->red*map->red_max/65535L)*map->red_mult)+ \
123   (((color)->green*map->green_max/65535L)*map->green_mult)+ \
124   (((color)->blue*map->blue_max/65535L)*map->blue_mult))
125
126 #define AccentuateModulate  ScaleCharToQuantum(80)
127 #define HighlightModulate  ScaleCharToQuantum(125)
128 #define ShadowModulate  ScaleCharToQuantum(135)
129 #define DepthModulate  ScaleCharToQuantum(185)
130 #define TroughModulate  ScaleCharToQuantum(110)
131
132 #define XLIB_ILLEGAL_ACCESS  1
133 #undef ForgetGravity
134 #undef NorthWestGravity
135 #undef NorthGravity
136 #undef NorthEastGravity
137 #undef WestGravity
138 #undef CenterGravity
139 #undef EastGravity
140 #undef SouthWestGravity
141 #undef SouthGravity
142 #undef SouthEastGravity
143 #undef StaticGravity
144
145 #undef index
146 #if defined(hpux9)
147 #define XFD_SET  int
148 #else
149 #define XFD_SET  fd_set
150 #endif
151
152 /*
153   Enumeration declarations.
154 */
155 typedef enum
156 {
157 #undef DoRed
158   DoRed = 0x0001,
159 #undef DoGreen
160   DoGreen = 0x0002,
161 #undef DoBlue
162   DoBlue = 0x0004,
163   DoMatte = 0x0008
164 } XColorFlags;
165
166 /*
167   Typedef declarations.
168 */
169 typedef struct _DiversityPacket
170 {
171   Quantum
172     red,
173     green,
174     blue;
175
176   unsigned short
177     index;
178
179   unsigned long
180     count;
181 } DiversityPacket;
182 \f
183 /*
184   Constant declaractions.
185 */
186 static MagickBooleanType
187   xerror_alert = MagickFalse;
188 \f
189 /*
190   Method prototypes.
191 */
192 static const char
193   *XVisualClassName(const int);
194
195 static MagickRealType
196   blue_gamma = 1.0,
197   green_gamma = 1.0,
198   red_gamma = 1.0;
199
200 static MagickBooleanType
201   XMakePixmap(Display *,const XResourceInfo *,XWindowInfo *);
202
203 static void
204   XMakeImageLSBFirst(const XResourceInfo *,const XWindowInfo *,Image *,
205     XImage *,XImage *),
206   XMakeImageMSBFirst(const XResourceInfo *,const XWindowInfo *,Image *,
207     XImage *,XImage *);
208
209 static Window
210   XSelectWindow(Display *,RectangleInfo *);
211 \f
212 /*
213 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
214 %                                                                             %
215 %                                                                             %
216 %                                                                             %
217 %   D e s t r o y X R e s o u r c e s                                         %
218 %                                                                             %
219 %                                                                             %
220 %                                                                             %
221 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
222 %
223 %  DestroyXResources() destroys any X resources.
224 %
225 %  The format of the DestroyXResources method is:
226 %
227 %      void DestroyXResources()
228 %
229 %  A description of each parameter follows:
230 %
231 */
232 MagickExport void DestroyXResources(void)
233 {
234   register int
235     i;
236
237   unsigned int
238     number_windows;
239
240   XWindowInfo
241     *magick_windows[MaxXWindows];
242
243   XWindows
244     *windows;
245
246   DestroyXWidget();
247   windows=XSetWindows((XWindows *) ~0);
248   if ((windows == (XWindows *) NULL) || (windows->display == (Display *) NULL))
249     return;
250   number_windows=0;
251   magick_windows[number_windows++]=(&windows->context);
252   magick_windows[number_windows++]=(&windows->group_leader);
253   magick_windows[number_windows++]=(&windows->backdrop);
254   magick_windows[number_windows++]=(&windows->icon);
255   magick_windows[number_windows++]=(&windows->image);
256   magick_windows[number_windows++]=(&windows->info);
257   magick_windows[number_windows++]=(&windows->magnify);
258   magick_windows[number_windows++]=(&windows->pan);
259   magick_windows[number_windows++]=(&windows->command);
260   magick_windows[number_windows++]=(&windows->widget);
261   magick_windows[number_windows++]=(&windows->popup);
262   magick_windows[number_windows++]=(&windows->context);
263   for (i=0; i < (int) number_windows; i++)
264   {
265     if (magick_windows[i]->mapped != MagickFalse)
266       {
267         (void) XWithdrawWindow(windows->display,magick_windows[i]->id,
268           magick_windows[i]->screen);
269         magick_windows[i]->mapped=MagickFalse;
270       }
271     if (magick_windows[i]->name != (char *) NULL)
272       magick_windows[i]->name=(char *)
273         RelinquishMagickMemory(magick_windows[i]->name);
274     if (magick_windows[i]->icon_name != (char *) NULL)
275       magick_windows[i]->icon_name=(char *)
276         RelinquishMagickMemory(magick_windows[i]->icon_name);
277     if (magick_windows[i]->cursor != (Cursor) NULL)
278       {
279         (void) XFreeCursor(windows->display,magick_windows[i]->cursor);
280         magick_windows[i]->cursor=(Cursor) NULL;
281       }
282     if (magick_windows[i]->busy_cursor != (Cursor) NULL)
283       {
284         (void) XFreeCursor(windows->display,magick_windows[i]->busy_cursor);
285         magick_windows[i]->busy_cursor=(Cursor) NULL;
286       }
287     if (magick_windows[i]->highlight_stipple != (Pixmap) NULL)
288       {
289         (void) XFreePixmap(windows->display,
290           magick_windows[i]->highlight_stipple);
291         magick_windows[i]->highlight_stipple=(Pixmap) NULL;
292       }
293     if (magick_windows[i]->shadow_stipple != (Pixmap) NULL)
294       {
295         (void) XFreePixmap(windows->display,magick_windows[i]->shadow_stipple);
296         magick_windows[i]->shadow_stipple=(Pixmap) NULL;
297       }
298     if (magick_windows[i]->ximage != (XImage *) NULL)
299       {
300         XDestroyImage(magick_windows[i]->ximage);
301         magick_windows[i]->ximage=(XImage *) NULL;
302       }
303     if (magick_windows[i]->pixmap != (Pixmap) NULL)
304       {
305         (void) XFreePixmap(windows->display,magick_windows[i]->pixmap);
306         magick_windows[i]->pixmap=(Pixmap) NULL;
307       }
308     if (magick_windows[i]->id != (Window) NULL)
309       {
310         (void) XDestroyWindow(windows->display,magick_windows[i]->id);
311         magick_windows[i]->id=(Window) NULL;
312       }
313     if (magick_windows[i]->destroy != MagickFalse)
314       {
315         if (magick_windows[i]->image != (Image *) NULL)
316           {
317             magick_windows[i]->image=DestroyImage(magick_windows[i]->image);
318             magick_windows[i]->image=NewImageList();
319           }
320         if (magick_windows[i]->matte_pixmap != (Pixmap) NULL)
321           {
322             (void) XFreePixmap(windows->display,
323               magick_windows[i]->matte_pixmap);
324             magick_windows[i]->matte_pixmap=(Pixmap) NULL;
325           }
326       }
327     if (magick_windows[i]->segment_info != (void *) NULL)
328       {
329 #if defined(MAGICKCORE_HAVE_SHARED_MEMORY)
330         XShmSegmentInfo
331           *segment_info;
332
333         segment_info=(XShmSegmentInfo *) magick_windows[i]->segment_info;
334         if (segment_info != (XShmSegmentInfo *) NULL)
335           if (segment_info[0].shmid >= 0)
336             {
337               if (segment_info[0].shmaddr != NULL)
338                 (void) shmdt(segment_info[0].shmaddr);
339               (void) shmctl(segment_info[0].shmid,IPC_RMID,0);
340               segment_info[0].shmaddr=NULL;
341               segment_info[0].shmid=(-1);
342             }
343 #endif
344         magick_windows[i]->segment_info=(void *)
345           RelinquishMagickMemory(magick_windows[i]->segment_info);
346       }
347   }
348   windows->icon_resources=(XResourceInfo *)
349     RelinquishMagickMemory(windows->icon_resources);
350   if (windows->icon_pixel != (XPixelInfo *) NULL)
351     {
352       if (windows->icon_pixel->pixels != (unsigned long *) NULL)
353         windows->icon_pixel->pixels=(unsigned long *)
354           RelinquishMagickMemory(windows->icon_pixel->pixels);
355       if (windows->icon_pixel->annotate_context != (GC) NULL)
356         XFreeGC(windows->display,windows->icon_pixel->annotate_context);
357       windows->icon_pixel=(XPixelInfo *)
358         RelinquishMagickMemory(windows->icon_pixel);
359     }
360   if (windows->pixel_info != (XPixelInfo *) NULL)
361     {
362       if (windows->pixel_info->pixels != (unsigned long *) NULL)
363         windows->pixel_info->pixels=(unsigned long *)
364           RelinquishMagickMemory(windows->pixel_info->pixels);
365       if (windows->pixel_info->annotate_context != (GC) NULL)
366         XFreeGC(windows->display,windows->pixel_info->annotate_context);
367       if (windows->pixel_info->widget_context != (GC) NULL)
368         XFreeGC(windows->display,windows->pixel_info->widget_context);
369       if (windows->pixel_info->highlight_context != (GC) NULL)
370         XFreeGC(windows->display,windows->pixel_info->highlight_context);
371       windows->pixel_info=(XPixelInfo *)
372         RelinquishMagickMemory(windows->pixel_info);
373     }
374   if (windows->font_info != (XFontStruct *) NULL)
375     {
376       XFreeFont(windows->display,windows->font_info);
377       windows->font_info=(XFontStruct *) NULL;
378     }
379   if (windows->class_hints != (XClassHint *) NULL)
380     {
381       if (windows->class_hints->res_name != (char *) NULL)
382         XFree(windows->class_hints->res_name);
383       if (windows->class_hints->res_class != (char *) NULL)
384         XFree(windows->class_hints->res_class);
385       XFree(windows->class_hints);
386       windows->class_hints=(XClassHint *) NULL;
387     }
388   if (windows->manager_hints != (XWMHints *) NULL)
389     {
390       XFree(windows->manager_hints);
391       windows->manager_hints=(XWMHints *) NULL;
392     }
393   if (windows->map_info != (XStandardColormap *) NULL)
394     {
395       XFree(windows->map_info);
396       windows->map_info=(XStandardColormap *) NULL;
397     }
398   if (windows->icon_map != (XStandardColormap *) NULL)
399     {
400       XFree(windows->icon_map);
401       windows->icon_map=(XStandardColormap *) NULL;
402     }
403   if (windows->visual_info != (XVisualInfo *) NULL)
404     {
405       XFree(windows->visual_info);
406       windows->visual_info=(XVisualInfo *) NULL;
407     }
408   if (windows->icon_visual != (XVisualInfo *) NULL)
409     {
410       XFree(windows->icon_visual);
411       windows->icon_visual=(XVisualInfo *) NULL;
412     }
413   (void) XSetWindows((XWindows *) NULL);
414 }
415 \f
416 /*
417 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
418 %                                                                             %
419 %                                                                             %
420 %                                                                             %
421 %   X A n n o t a t e I m a g e                                               %
422 %                                                                             %
423 %                                                                             %
424 %                                                                             %
425 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
426 %
427 %  XAnnotateImage() annotates the image with text.
428 %
429 %  The format of the XAnnotateImage method is:
430 %
431 %      MagickBooleanType XAnnotateImage(Display *display,
432 %        const XPixelInfo *pixel,XAnnotateInfo *annotate_info,Image *image)
433 %
434 %  A description of each parameter follows:
435 %
436 %    o display: Specifies a connection to an X server;  returned from
437 %      XOpenDisplay.
438 %
439 %    o pixel: Specifies a pointer to a XPixelInfo structure.
440 %
441 %    o annotate_info: Specifies a pointer to a XAnnotateInfo structure.
442 %
443 %    o image: the image.
444 %
445 */
446 MagickExport MagickBooleanType XAnnotateImage(Display *display,
447   const XPixelInfo *pixel,XAnnotateInfo *annotate_info,Image *image)
448 {
449   GC
450     annotate_context;
451
452   ExceptionInfo
453     *exception;
454
455   Image
456     *annotate_image;
457
458   int
459     x,
460     y;
461
462   MagickBooleanType
463     matte;
464
465   Pixmap
466     annotate_pixmap;
467
468   unsigned int
469     depth,
470     height,
471     width;
472
473   Window
474     root_window;
475
476   XGCValues
477     context_values;
478
479   XImage
480     *annotate_ximage;
481
482   /*
483     Initialize annotated image.
484   */
485   (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
486   assert(display != (Display *) NULL);
487   assert(pixel != (XPixelInfo *) NULL);
488   assert(annotate_info != (XAnnotateInfo *) NULL);
489   assert(image != (Image *) NULL);
490   /*
491     Initialize annotated pixmap.
492   */
493   root_window=XRootWindow(display,XDefaultScreen(display));
494   depth=(unsigned int) XDefaultDepth(display,XDefaultScreen(display));
495   annotate_pixmap=XCreatePixmap(display,root_window,annotate_info->width,
496     annotate_info->height,depth);
497   if (annotate_pixmap == (Pixmap) NULL)
498     return(MagickFalse);
499   /*
500     Initialize graphics info.
501   */
502   context_values.background=0;
503   context_values.foreground=(unsigned long) (~0);
504   context_values.font=annotate_info->font_info->fid;
505   annotate_context=XCreateGC(display,root_window,(unsigned long)
506     GCBackground | GCFont | GCForeground,&context_values);
507   if (annotate_context == (GC) NULL)
508     return(MagickFalse);
509   /*
510     Draw text to pixmap.
511   */
512   (void) XDrawImageString(display,annotate_pixmap,annotate_context,0,
513     (int) annotate_info->font_info->ascent,annotate_info->text,
514     (int) strlen(annotate_info->text));
515   (void) XFreeGC(display,annotate_context);
516   /*
517     Initialize annotated X image.
518   */
519   annotate_ximage=XGetImage(display,annotate_pixmap,0,0,annotate_info->width,
520     annotate_info->height,AllPlanes,ZPixmap);
521   if (annotate_ximage == (XImage *) NULL)
522     return(MagickFalse);
523   (void) XFreePixmap(display,annotate_pixmap);
524   /*
525     Initialize annotated image.
526   */
527   annotate_image=AcquireImage((ImageInfo *) NULL);
528   if (annotate_image == (Image *) NULL)
529     return(MagickFalse);
530   annotate_image->columns=annotate_info->width;
531   annotate_image->rows=annotate_info->height;
532   /*
533     Transfer annotated X image to image.
534   */
535   width=(unsigned int) image->columns;
536   height=(unsigned int) image->rows;
537   x=0;
538   y=0;
539   (void) XParseGeometry(annotate_info->geometry,&x,&y,&width,&height);
540   (void) GetOneVirtualPixel(image,x,y,&annotate_image->background_color,
541     &image->exception);
542   if (annotate_info->stencil == ForegroundStencil)
543     annotate_image->matte=MagickTrue;
544   exception=(&image->exception);
545   for (y=0; y < (int) annotate_image->rows; y++)
546   {
547     register long
548       x;
549
550     register PixelPacket
551       *restrict q;
552
553     q=GetAuthenticPixels(annotate_image,0,y,annotate_image->columns,1,
554       exception);
555     if (q == (PixelPacket *) NULL)
556       break;
557     for (x=0; x < (long) annotate_image->columns; x++)
558     {
559       q->opacity=OpaqueOpacity;
560       if (XGetPixel(annotate_ximage,x,y) == 0)
561         {
562           /*
563             Set this pixel to the background color.
564           */
565           q->red=ScaleShortToQuantum(pixel->box_color.red);
566           q->green=ScaleShortToQuantum(pixel->box_color.green);
567           q->blue=ScaleShortToQuantum(pixel->box_color.blue);
568           if ((annotate_info->stencil == ForegroundStencil) ||
569               (annotate_info->stencil == OpaqueStencil))
570             q->opacity=(Quantum) TransparentOpacity;
571         }
572       else
573         {
574           /*
575             Set this pixel to the pen color.
576           */
577           q->red=ScaleShortToQuantum(pixel->pen_color.red);
578           q->green=ScaleShortToQuantum(pixel->pen_color.green);
579           q->blue=ScaleShortToQuantum(pixel->pen_color.blue);
580           if (annotate_info->stencil == BackgroundStencil)
581             q->opacity=(Quantum) TransparentOpacity;
582         }
583       q++;
584     }
585     if (SyncAuthenticPixels(annotate_image,exception) == MagickFalse)
586       break;
587   }
588   XDestroyImage(annotate_ximage);
589   /*
590     Determine annotate geometry.
591   */
592   (void) XParseGeometry(annotate_info->geometry,&x,&y,&width,&height);
593   if ((width != (unsigned int) annotate_image->columns) ||
594       (height != (unsigned int) annotate_image->rows))
595     {
596       char
597         image_geometry[MaxTextExtent];
598
599       /*
600         Scale image.
601       */
602       (void) FormatMagickString(image_geometry,MaxTextExtent,"%ux%u",
603         width,height);
604       (void) TransformImage(&annotate_image,(char *) NULL,image_geometry);
605     }
606   if (annotate_info->degrees != 0.0)
607     {
608       Image
609         *rotate_image;
610
611       int
612         rotations;
613
614       MagickRealType
615         normalized_degrees;
616
617       /*
618         Rotate image.
619       */
620       rotate_image=
621         RotateImage(annotate_image,annotate_info->degrees,&image->exception);
622       if (rotate_image == (Image *) NULL)
623         return(MagickFalse);
624       annotate_image=DestroyImage(annotate_image);
625       annotate_image=rotate_image;
626       /*
627         Annotation is relative to the degree of rotation.
628       */
629       normalized_degrees=annotate_info->degrees;
630       while (normalized_degrees < -45.0)
631         normalized_degrees+=360.0;
632       for (rotations=0; normalized_degrees > 45.0; rotations++)
633         normalized_degrees-=90.0;
634       switch (rotations % 4)
635       {
636         default:
637         case 0:
638           break;
639         case 1:
640         {
641           /*
642             Rotate 90 degrees.
643           */
644           x-=(int) annotate_image->columns/2;
645           y+=(int) annotate_image->columns/2;
646           break;
647         }
648         case 2:
649         {
650           /*
651             Rotate 180 degrees.
652           */
653           x=x-(int) annotate_image->columns;
654           break;
655         }
656         case 3:
657         {
658           /*
659             Rotate 270 degrees.
660           */
661           x=x-(int) annotate_image->columns/2;
662           y=y-(int) (annotate_image->rows-(annotate_image->columns/2));
663           break;
664         }
665       }
666     }
667   /*
668     Composite text onto the image.
669   */
670   (void) XParseGeometry(annotate_info->geometry,&x,&y,&width,&height);
671   matte=image->matte;
672   (void) CompositeImage(image,annotate_image->matte != MagickFalse ?
673     OverCompositeOp : CopyCompositeOp,annotate_image,x,y);
674   image->matte=matte;
675   annotate_image=DestroyImage(annotate_image);
676   return(MagickTrue);
677 }
678 \f
679 /*
680 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
681 %                                                                             %
682 %                                                                             %
683 %                                                                             %
684 %   X B e s t F o n t                                                         %
685 %                                                                             %
686 %                                                                             %
687 %                                                                             %
688 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
689 %
690 %  XBestFont() returns the "best" font.  "Best" is defined as a font specified
691 %  in the X resource database or a font such that the text width displayed
692 %  with the font does not exceed the specified maximum width.
693 %
694 %  The format of the XBestFont method is:
695 %
696 %      XFontStruct *XBestFont(Display *display,
697 %        const XResourceInfo *resource_info,const MagickBooleanType text_font)
698 %
699 %  A description of each parameter follows:
700 %
701 %    o font: XBestFont returns a pointer to a XFontStruct structure.
702 %
703 %    o display: Specifies a connection to an X server;  returned from
704 %      XOpenDisplay.
705 %
706 %    o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
707 %
708 %    o text_font:  True is font should be mono-spaced (typewriter style).
709 %
710 %
711 */
712
713 static char **FontToList(char *font)
714 {
715   char
716     **fontlist;
717
718   register char
719     *p,
720     *q;
721
722   register int
723     i;
724
725   unsigned int
726     fonts;
727
728   if (font == (char *) NULL)
729     return((char **) NULL);
730   /*
731     Convert string to an ASCII list.
732   */
733   fonts=1U;
734   for (p=font; *p != '\0'; p++)
735     if ((*p == ':') || (*p == ';') || (*p == ','))
736       fonts++;
737   fontlist=(char **) AcquireQuantumMemory((size_t) fonts+1UL,sizeof(*fontlist));
738   if (fontlist == (char **) NULL)
739     {
740       ThrowXWindowFatalException(ResourceLimitError,"MemoryAllocationFailed",
741         font);
742       return((char **) NULL);
743     }
744   p=font;
745   for (i=0; i < (int) fonts; i++)
746   {
747     for (q=p; *q != '\0'; q++)
748       if ((*q == ':') || (*q == ';') || (*q == ','))
749         break;
750     fontlist[i]=(char *) AcquireQuantumMemory((size_t) (q-p)+1UL,
751       sizeof(*fontlist[i]));
752     if (fontlist[i] == (char *) NULL)
753       {
754         ThrowXWindowFatalException(ResourceLimitError,"MemoryAllocationFailed",
755           font);
756         return((char **) NULL);
757       }
758     (void) CopyMagickString(fontlist[i],p,(size_t) (q-p+1));
759     p=q+1;
760   }
761   fontlist[i]=(char *) NULL;
762   return(fontlist);
763 }
764
765 MagickExport XFontStruct *XBestFont(Display *display,
766   const XResourceInfo *resource_info,const MagickBooleanType text_font)
767 {
768   static const char
769     *Fonts[]=
770     {
771       "-*-helvetica-medium-r-normal--12-*-*-*-*-*-iso8859-1",
772       "-*-arial-medium-r-normal--12-*-*-*-*-*-iso8859-1",
773       "-*-helvetica-medium-r-normal--12-*-*-*-*-*-iso8859-15",
774       "-*-arial-medium-r-normal--12-*-*-*-*-*-iso8859-15",
775       "-*-helvetica-medium-r-normal--12-*-*-*-*-*-*-*",
776       "-*-arial-medium-r-normal--12-*-*-*-*-*-*-*",
777       "variable",
778       "fixed",
779       (char *) NULL
780     },
781     *TextFonts[]=
782     {
783       "-*-courier-medium-r-normal-*-12-*-*-*-*-*-iso8859-1",
784       "-*-courier-medium-r-normal-*-12-*-*-*-*-*-iso8859-15",
785       "-*-fixed-medium-r-normal-*-12-*-*-*-*-*-*-*",
786       "fixed",
787       (char *) NULL
788     };
789
790   char
791     *font_name;
792
793   register const char
794     **p;
795
796   XFontStruct
797     *font_info;
798
799   font_info=(XFontStruct *) NULL;
800   font_name=resource_info->font;
801   if (text_font != MagickFalse)
802     font_name=resource_info->text_font;
803   if ((font_name != (char *) NULL) && (*font_name != '\0'))
804     {
805       char
806         **fontlist;
807
808       register int
809         i;
810
811       /*
812         Load preferred font specified in the X resource database.
813       */
814       fontlist=FontToList(font_name);
815       if (fontlist != (char **) NULL)
816         {
817           for (i=0; fontlist[i] != (char *) NULL; i++)
818           {
819             if (font_info == (XFontStruct *) NULL)
820               font_info=XLoadQueryFont(display,fontlist[i]);
821             fontlist[i]=DestroyString(fontlist[i]);
822           }
823           fontlist=(char **) RelinquishMagickMemory(fontlist);
824         }
825       if (font_info == (XFontStruct *) NULL)
826         ThrowXWindowFatalException(XServerError,"UnableToLoadFont",font_name);
827     }
828   /*
829     Load fonts from list of fonts until one is found.
830   */
831   p=Fonts;
832   if (text_font != MagickFalse)
833     p=TextFonts;
834   if (XDisplayHeight(display,XDefaultScreen(display)) >= 748)
835     p++;
836   while (*p != (char *) NULL)
837   {
838     if (font_info != (XFontStruct *) NULL)
839       break;
840     font_info=XLoadQueryFont(display,(char *) *p);
841     p++;
842   }
843   return(font_info);
844 }
845 \f
846 /*
847 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
848 %                                                                             %
849 %                                                                             %
850 %                                                                             %
851 %   X B e s t I c o n S i z e                                                 %
852 %                                                                             %
853 %                                                                             %
854 %                                                                             %
855 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
856 %
857 %  XBestIconSize() returns the "best" icon size.  "Best" is defined as an icon
858 %  size that maintains the aspect ratio of the image.  If the window manager
859 %  has preferred icon sizes, one of the preferred sizes is used.
860 %
861 %  The format of the XBestIconSize method is:
862 %
863 %      void XBestIconSize(Display *display,XWindowInfo *window,Image *image)
864 %
865 %  A description of each parameter follows:
866 %
867 %    o display: Specifies a connection to an X server;  returned from
868 %      XOpenDisplay.
869 %
870 %    o image: the image.
871 %
872 */
873 MagickExport void XBestIconSize(Display *display,XWindowInfo *window,
874   Image *image)
875 {
876   int
877     i,
878     number_sizes;
879
880   MagickRealType
881     scale_factor;
882
883   unsigned int
884     height,
885     icon_height,
886     icon_width,
887     width;
888
889   Window
890     root_window;
891
892   XIconSize
893     *icon_size,
894     *size_list;
895
896   /*
897     Determine if the window manager has specified preferred icon sizes.
898   */
899   (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
900   assert(display != (Display *) NULL);
901   assert(window != (XWindowInfo *) NULL);
902   assert(image != (Image *) NULL);
903   window->width=MaxIconSize;
904   window->height=MaxIconSize;
905   icon_size=(XIconSize *) NULL;
906   number_sizes=0;
907   root_window=XRootWindow(display,window->screen);
908   if (XGetIconSizes(display,root_window,&size_list,&number_sizes) != 0)
909     if ((number_sizes > 0) && (size_list != (XIconSize *) NULL))
910       icon_size=size_list;
911   if (icon_size == (XIconSize *) NULL)
912     {
913       /*
914         Window manager does not restrict icon size.
915       */
916       icon_size=XAllocIconSize();
917       if (icon_size == (XIconSize *) NULL)
918         {
919           ThrowXWindowFatalException(ResourceLimitError,
920             "MemoryAllocationFailed",image->filename);
921           return;
922         }
923       icon_size->min_width=1;
924       icon_size->max_width=MaxIconSize;
925       icon_size->min_height=1;
926       icon_size->max_height=MaxIconSize;
927       icon_size->width_inc=1;
928       icon_size->height_inc=1;
929     }
930   /*
931     Determine aspect ratio of image.
932   */
933   width=(unsigned int) image->columns;
934   height=(unsigned int) image->rows;
935   i=0;
936   if (window->crop_geometry)
937     (void) XParseGeometry(window->crop_geometry,&i,&i,&width,&height);
938   /*
939     Look for an icon size that maintains the aspect ratio of image.
940   */
941   scale_factor=(MagickRealType) icon_size->max_width/width;
942   if (scale_factor > ((MagickRealType) icon_size->max_height/height))
943     scale_factor=(MagickRealType) icon_size->max_height/height;
944   icon_width=(unsigned int) icon_size->min_width;
945   while ((int) icon_width < icon_size->max_width)
946   {
947     if (icon_width >= (unsigned int) (scale_factor*width+0.5))
948       break;
949     icon_width+=icon_size->width_inc;
950   }
951   icon_height=(unsigned int) icon_size->min_height;
952   while ((int) icon_height < icon_size->max_height)
953   {
954     if (icon_height >= (unsigned int) (scale_factor*height+0.5))
955       break;
956     icon_height+=icon_size->height_inc;
957   }
958   (void) XFree((void *) icon_size);
959   window->width=icon_width;
960   window->height=icon_height;
961 }
962 \f
963 /*
964 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
965 %                                                                             %
966 %                                                                             %
967 %                                                                             %
968 %   X B e s t P i x e l                                                       %
969 %                                                                             %
970 %                                                                             %
971 %                                                                             %
972 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
973 %
974 %  XBestPixel() returns a pixel from an array of pixels that is closest to the
975 %  requested color.  If the color array is NULL, the colors are obtained from
976 %  the X server.
977 %
978 %  The format of the XBestPixel method is:
979 %
980 %      void XBestPixel(Display *display,const Colormap colormap,XColor *colors,
981 %        unsigned int number_colors,XColor *color)
982 %
983 %  A description of each parameter follows:
984 %
985 %    o pixel: XBestPixel returns the pixel value closest to the requested
986 %      color.
987 %
988 %    o display: Specifies a connection to an X server;  returned from
989 %      XOpenDisplay.
990 %
991 %    o colormap: Specifies the ID of the X server colormap.
992 %
993 %    o colors: Specifies an array of XColor structures.
994 %
995 %    o number_colors: Specifies the number of XColor structures in the
996 %      color definition array.
997 %
998 %    o color: Specifies the desired RGB value to find in the colors array.
999 %
1000 */
1001 MagickExport void XBestPixel(Display *display,const Colormap colormap,
1002   XColor *colors,unsigned int number_colors,XColor *color)
1003 {
1004   MagickBooleanType
1005     query_server;
1006
1007   MagickPixelPacket
1008     pixel;
1009
1010   MagickRealType
1011     min_distance;
1012
1013   register MagickRealType
1014     distance;
1015
1016   register int
1017     i,
1018     j;
1019
1020   Status
1021     status;
1022
1023   /*
1024     Find closest representation for the requested RGB color.
1025   */
1026   (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
1027   assert(display != (Display *) NULL);
1028   assert(color != (XColor *) NULL);
1029   status=XAllocColor(display,colormap,color);
1030   if (status != False)
1031     return;
1032   query_server=colors == (XColor *) NULL ? MagickTrue : MagickFalse;
1033   if (query_server != MagickFalse)
1034     {
1035       /*
1036         Read X server colormap.
1037       */
1038       colors=(XColor *) AcquireQuantumMemory(number_colors,sizeof(*colors));
1039       if (colors == (XColor *) NULL)
1040         {
1041           ThrowXWindowFatalException(ResourceLimitError,
1042             "MemoryAllocationFailed","...");
1043           return;
1044         }
1045       for (i=0; i < (int) number_colors; i++)
1046         colors[i].pixel=(unsigned long) i;
1047       if (number_colors > 256)
1048         number_colors=256;
1049       (void) XQueryColors(display,colormap,colors,(int) number_colors);
1050     }
1051   min_distance=3.0*((MagickRealType) QuantumRange+1.0)*((MagickRealType)
1052     QuantumRange+1.0);
1053   j=0;
1054   for (i=0; i < (int) number_colors; i++)
1055   {
1056     pixel.red=colors[i].red-(MagickRealType) color->red;
1057     distance=pixel.red*pixel.red;
1058     if (distance > min_distance)
1059       continue;
1060     pixel.green=colors[i].green-(MagickRealType) color->green;
1061     distance+=pixel.green*pixel.green;
1062     if (distance > min_distance)
1063       continue;
1064     pixel.blue=colors[i].blue-(MagickRealType) color->blue;
1065     distance+=pixel.blue*pixel.blue;
1066     if (distance > min_distance)
1067       continue;
1068     min_distance=distance;
1069     color->pixel=colors[i].pixel;
1070     j=i;
1071   }
1072   (void) XAllocColor(display,colormap,&colors[j]);
1073   if (query_server != MagickFalse)
1074     colors=(XColor *) RelinquishMagickMemory(colors);
1075 }
1076 \f
1077 /*
1078 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1079 %                                                                             %
1080 %                                                                             %
1081 %                                                                             %
1082 %   X B e s t V i s u a l I n f o                                             %
1083 %                                                                             %
1084 %                                                                             %
1085 %                                                                             %
1086 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1087 %
1088 %  XBestVisualInfo() returns visual information for a visual that is the "best"
1089 %  the server supports.  "Best" is defined as:
1090 %
1091 %    1. Restrict the visual list to those supported by the default screen.
1092 %
1093 %    2. If a visual type is specified, restrict the visual list to those of
1094 %       that type.
1095 %
1096 %    3. If a map type is specified, choose the visual that matches the id
1097 %       specified by the Standard Colormap.
1098 %
1099 %    4  From the list of visuals, choose one that can display the most
1100 %       simultaneous colors.  If more than one visual can display the same
1101 %       number of simultaneous colors, one is chosen based on a rank.
1102 %
1103 %  The format of the XBestVisualInfo method is:
1104 %
1105 %      XVisualInfo *XBestVisualInfo(Display *display,
1106 %        XStandardColormap *map_info,XResourceInfo *resource_info)
1107 %
1108 %  A description of each parameter follows:
1109 %
1110 %    o visual_info: XBestVisualInfo returns a pointer to a X11 XVisualInfo
1111 %      structure.
1112 %
1113 %    o display: Specifies a connection to an X server;  returned from
1114 %      XOpenDisplay.
1115 %
1116 %    o map_info: If map_type is specified, this structure is initialized
1117 %      with info from the Standard Colormap.
1118 %
1119 %    o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
1120 %
1121 */
1122
1123 static inline int MagickMax(const int x,const int y)
1124 {
1125   if (x > y)
1126     return(x);
1127   return(y);
1128 }
1129
1130 static inline unsigned long MagickMin(const unsigned int x,
1131   const unsigned int y)
1132 {
1133   if (x < y)
1134     return(x);
1135   return(y);
1136 }
1137
1138 MagickExport XVisualInfo *XBestVisualInfo(Display *display,
1139   XStandardColormap *map_info,XResourceInfo *resource_info)
1140 {
1141 #define MaxStandardColormaps  7
1142 #define XVisualColormapSize(visual_info) MagickMin((unsigned int) (\
1143   (visual_info->klass == TrueColor) || (visual_info->klass == DirectColor) ? \
1144    visual_info->red_mask | visual_info->green_mask | visual_info->blue_mask : \
1145    (unsigned int) visual_info->colormap_size),1U << visual_info->depth)
1146
1147   char
1148     *map_type,
1149     *visual_type;
1150
1151   long
1152     visual_mask;
1153
1154   register int
1155     i;
1156
1157   static int
1158     number_visuals;
1159
1160   static XVisualInfo
1161     visual_template;
1162
1163   XVisualInfo
1164     *visual_info,
1165     *visual_list;
1166
1167   /*
1168     Restrict visual search by screen number.
1169   */
1170   (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
1171   assert(display != (Display *) NULL);
1172   assert(map_info != (XStandardColormap *) NULL);
1173   assert(resource_info != (XResourceInfo *) NULL);
1174   map_type=resource_info->map_type;
1175   visual_type=resource_info->visual_type;
1176   visual_mask=VisualScreenMask;
1177   visual_template.screen=XDefaultScreen(display);
1178   visual_template.depth=XDefaultDepth(display,XDefaultScreen(display));
1179   if ((resource_info->immutable != MagickFalse) && (resource_info->colors != 0))
1180     if (resource_info->colors <= (1UL << (unsigned long) visual_template.depth))
1181       visual_mask|=VisualDepthMask;
1182   if (visual_type != (char *) NULL)
1183     {
1184       /*
1185         Restrict visual search by class or visual id.
1186       */
1187       if (LocaleCompare("staticgray",visual_type) == 0)
1188         {
1189           visual_mask|=VisualClassMask;
1190           visual_template.klass=StaticGray;
1191         }
1192       else
1193         if (LocaleCompare("grayscale",visual_type) == 0)
1194           {
1195             visual_mask|=VisualClassMask;
1196             visual_template.klass=GrayScale;
1197           }
1198         else
1199           if (LocaleCompare("staticcolor",visual_type) == 0)
1200             {
1201               visual_mask|=VisualClassMask;
1202               visual_template.klass=StaticColor;
1203             }
1204           else
1205             if (LocaleCompare("pseudocolor",visual_type) == 0)
1206               {
1207                 visual_mask|=VisualClassMask;
1208                 visual_template.klass=PseudoColor;
1209               }
1210             else
1211               if (LocaleCompare("truecolor",visual_type) == 0)
1212                 {
1213                   visual_mask|=VisualClassMask;
1214                   visual_template.klass=TrueColor;
1215                 }
1216               else
1217                 if (LocaleCompare("directcolor",visual_type) == 0)
1218                   {
1219                     visual_mask|=VisualClassMask;
1220                     visual_template.klass=DirectColor;
1221                   }
1222                 else
1223                   if (LocaleCompare("default",visual_type) == 0)
1224                     {
1225                       visual_mask|=VisualIDMask;
1226                       visual_template.visualid=XVisualIDFromVisual(
1227                         XDefaultVisual(display,XDefaultScreen(display)));
1228                     }
1229                   else
1230                     if (isdigit((int) ((unsigned char) *visual_type)) != 0)
1231                       {
1232                         visual_mask|=VisualIDMask;
1233                         visual_template.visualid=
1234                           strtol(visual_type,(char **) NULL,0);
1235                       }
1236                     else
1237                       ThrowXWindowFatalException(XServerError,
1238                         "UnrecognizedVisualSpecifier",visual_type);
1239     }
1240   /*
1241     Get all visuals that meet our criteria so far.
1242   */
1243   number_visuals=0;
1244   visual_list=XGetVisualInfo(display,visual_mask,&visual_template,
1245     &number_visuals);
1246   visual_mask=VisualScreenMask | VisualIDMask;
1247   if ((number_visuals == 0) || (visual_list == (XVisualInfo *) NULL))
1248     {
1249       /*
1250         Failed to get visual;  try using the default visual.
1251       */
1252       ThrowXWindowFatalException(XServerWarning,"UnableToGetVisual",
1253         visual_type);
1254       visual_template.visualid=XVisualIDFromVisual(XDefaultVisual(display,
1255         XDefaultScreen(display)));
1256       visual_list=XGetVisualInfo(display,visual_mask,&visual_template,
1257         &number_visuals);
1258       if ((number_visuals == 0) || (visual_list == (XVisualInfo *) NULL))
1259         return((XVisualInfo *) NULL);
1260       ThrowXWindowFatalException(XServerWarning,"UsingDefaultVisual",
1261         XVisualClassName(visual_list->klass));
1262     }
1263   resource_info->color_recovery=MagickFalse;
1264   if ((map_info != (XStandardColormap *) NULL) && (map_type != (char *) NULL))
1265     {
1266       Atom
1267         map_property;
1268
1269       char
1270         map_name[MaxTextExtent];
1271
1272       int
1273         j,
1274         number_maps;
1275
1276       Status
1277         status;
1278
1279       Window
1280         root_window;
1281
1282       XStandardColormap
1283         *map_list;
1284
1285       /*
1286         Choose a visual associated with a standard colormap.
1287       */
1288       root_window=XRootWindow(display,XDefaultScreen(display));
1289       status=False;
1290       if (LocaleCompare(map_type,"list") != 0)
1291         {
1292           /*
1293             User specified Standard Colormap.
1294           */
1295           (void) FormatMagickString((char *) map_name,MaxTextExtent,
1296             "RGB_%s_MAP",map_type);
1297           LocaleUpper(map_name);
1298           map_property=XInternAtom(display,(char *) map_name,MagickTrue);
1299           if (map_property != (Atom) NULL)
1300             status=XGetRGBColormaps(display,root_window,&map_list,&number_maps,
1301               map_property);
1302         }
1303       else
1304         {
1305           static const char
1306             *colormap[MaxStandardColormaps]=
1307             {
1308               "_HP_RGB_SMOOTH_MAP_LIST",
1309               "RGB_BEST_MAP",
1310               "RGB_DEFAULT_MAP",
1311               "RGB_GRAY_MAP",
1312               "RGB_RED_MAP",
1313               "RGB_GREEN_MAP",
1314               "RGB_BLUE_MAP",
1315             };
1316
1317           /*
1318             Choose a standard colormap from a list.
1319           */
1320           for (i=0; i < MaxStandardColormaps; i++)
1321           {
1322             map_property=XInternAtom(display,(char *) colormap[i],MagickTrue);
1323             if (map_property == (Atom) NULL)
1324               continue;
1325             status=XGetRGBColormaps(display,root_window,&map_list,&number_maps,
1326               map_property);
1327             if (status != False)
1328               break;
1329           }
1330           resource_info->color_recovery=i == 0 ? MagickTrue : MagickFalse;
1331         }
1332       if (status == False)
1333         {
1334           ThrowXWindowFatalException(XServerError,"UnableToGetStandardColormap",
1335             map_type);
1336           return((XVisualInfo *) NULL);
1337         }
1338       /*
1339         Search all Standard Colormaps and visuals for ids that match.
1340       */
1341       *map_info=map_list[0];
1342 #if !defined(PRE_R4_ICCCM)
1343       visual_template.visualid=XVisualIDFromVisual(visual_list[0].visual);
1344       for (i=0; i < number_maps; i++)
1345         for (j=0; j < number_visuals; j++)
1346           if (map_list[i].visualid ==
1347               XVisualIDFromVisual(visual_list[j].visual))
1348             {
1349               *map_info=map_list[i];
1350               visual_template.visualid=XVisualIDFromVisual(
1351                 visual_list[j].visual);
1352               break;
1353             }
1354       if (map_info->visualid != visual_template.visualid)
1355         {
1356           ThrowXWindowFatalException(XServerError,
1357             "UnableToMatchVisualToStandardColormap",map_type);
1358           return((XVisualInfo *) NULL);
1359         }
1360 #endif
1361       if (map_info->colormap == (Colormap) NULL)
1362         {
1363           ThrowXWindowFatalException(XServerError,
1364             "StandardColormapIsNotInitialized",map_type);
1365           return((XVisualInfo *) NULL);
1366         }
1367       (void) XFree((void *) map_list);
1368     }
1369   else
1370     {
1371       static const unsigned int
1372         rank[]=
1373           {
1374             StaticGray,
1375             GrayScale,
1376             StaticColor,
1377             DirectColor,
1378             TrueColor,
1379             PseudoColor
1380           };
1381
1382       XVisualInfo
1383         *p;
1384
1385       /*
1386         Pick one visual that displays the most simultaneous colors.
1387       */
1388       visual_info=visual_list;
1389       p=visual_list;
1390       for (i=1; i < number_visuals; i++)
1391       {
1392         p++;
1393         if (XVisualColormapSize(p) > XVisualColormapSize(visual_info))
1394           visual_info=p;
1395         else
1396           if (XVisualColormapSize(p) == XVisualColormapSize(visual_info))
1397             if (rank[p->klass] > rank[visual_info->klass])
1398               visual_info=p;
1399       }
1400       visual_template.visualid=XVisualIDFromVisual(visual_info->visual);
1401     }
1402   (void) XFree((void *) visual_list);
1403   /*
1404     Retrieve only one visual by its screen & id number.
1405   */
1406   visual_info=XGetVisualInfo(display,visual_mask,&visual_template,
1407     &number_visuals);
1408   if ((number_visuals == 0) || (visual_info == (XVisualInfo *) NULL))
1409     return((XVisualInfo *) NULL);
1410   return(visual_info);
1411 }
1412 \f
1413 /*
1414 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1415 %                                                                             %
1416 %                                                                             %
1417 %                                                                             %
1418 %   X C h e c k D e f i n e C u r s o r                                       %
1419 %                                                                             %
1420 %                                                                             %
1421 %                                                                             %
1422 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1423 %
1424 %  XCheckDefineCursor() prevents cursor changes on the root window.
1425 %
1426 %  The format of the XXCheckDefineCursor method is:
1427 %
1428 %      XCheckDefineCursor(display,window,cursor)
1429 %
1430 %  A description of each parameter follows:
1431 %
1432 %    o display: Specifies a connection to an X server;  returned from
1433 %      XOpenDisplay.
1434 %
1435 %    o window: the window.
1436 %
1437 %    o cursor: the cursor.
1438 %
1439 */
1440 MagickExport int XCheckDefineCursor(Display *display,Window window,
1441   Cursor cursor)
1442 {
1443   (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
1444   assert(display != (Display *) NULL);
1445   if (window == XRootWindow(display,XDefaultScreen(display)))
1446     return(0);
1447   return(XDefineCursor(display,window,cursor));
1448 }
1449 \f
1450 /*
1451 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1452 %                                                                             %
1453 %                                                                             %
1454 %                                                                             %
1455 %   X C h e c k R e f r e s h W i n d o w s                                   %
1456 %                                                                             %
1457 %                                                                             %
1458 %                                                                             %
1459 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1460 %
1461 %  XCheckRefreshWindows() checks the X server for exposure events for a
1462 %  particular window and updates the areassociated with the exposure event.
1463 %
1464 %  The format of the XCheckRefreshWindows method is:
1465 %
1466 %      void XCheckRefreshWindows(Display *display,XWindows *windows)
1467 %
1468 %  A description of each parameter follows:
1469 %
1470 %    o display: Specifies a connection to an X server;  returned from
1471 %      XOpenDisplay.
1472 %
1473 %    o windows: Specifies a pointer to a XWindows structure.
1474 %
1475 */
1476 MagickExport void XCheckRefreshWindows(Display *display,XWindows *windows)
1477 {
1478   Window
1479     id;
1480
1481   XEvent
1482     event;
1483
1484   (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
1485   assert(display != (Display *) NULL);
1486   assert(windows != (XWindows *) NULL);
1487   XDelay(display,SuspendTime);
1488   id=windows->command.id;
1489   while (XCheckTypedWindowEvent(display,id,Expose,&event) != MagickFalse)
1490     (void) XCommandWidget(display,windows,(char const **) NULL,&event);
1491   id=windows->image.id;
1492   while (XCheckTypedWindowEvent(display,id,Expose,&event) != MagickFalse)
1493     XRefreshWindow(display,&windows->image,&event);
1494   XDelay(display,SuspendTime << 1);
1495   id=windows->command.id;
1496   while (XCheckTypedWindowEvent(display,id,Expose,&event) != MagickFalse)
1497     (void) XCommandWidget(display,windows,(char const **) NULL,&event);
1498   id=windows->image.id;
1499   while (XCheckTypedWindowEvent(display,id,Expose,&event) != MagickFalse)
1500     XRefreshWindow(display,&windows->image,&event);
1501 }
1502 \f
1503 /*
1504 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1505 %                                                                             %
1506 %                                                                             %
1507 %                                                                             %
1508 %   X C l i e n t M e s s a g e                                               %
1509 %                                                                             %
1510 %                                                                             %
1511 %                                                                             %
1512 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1513 %
1514 %  XClientMessage() sends a reason to a window with XSendEvent.  The reason is
1515 %  initialized with a particular protocol type and atom.
1516 %
1517 %  The format of the XClientMessage function is:
1518 %
1519 %      XClientMessage(display,window,protocol,reason,timestamp)
1520 %
1521 %  A description of each parameter follows:
1522 %
1523 %    o display: Specifies a pointer to the Display structure;  returned from
1524 %      XOpenDisplay.
1525 %
1526 %    o window: Specifies a pointer to a Window structure.
1527 %
1528 %    o protocol: Specifies an atom value.
1529 %
1530 %    o reason: Specifies an atom value which is the reason to send.
1531 %
1532 %    o timestamp: Specifies a value of type Time.
1533 %
1534 */
1535 MagickExport void XClientMessage(Display *display,const Window window,
1536   const Atom protocol,const Atom reason,const Time timestamp)
1537 {
1538   XClientMessageEvent
1539     client_event;
1540
1541   assert(display != (Display *) NULL);
1542   client_event.type=ClientMessage;
1543   client_event.window=window;
1544   client_event.message_type=protocol;
1545   client_event.format=32;
1546   client_event.data.l[0]=(long) reason;
1547   client_event.data.l[1]=(long) timestamp;
1548   (void) XSendEvent(display,window,MagickFalse,NoEventMask,(XEvent *) &client_event);
1549 }
1550 \f
1551 /*
1552 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1553 %                                                                             %
1554 %                                                                             %
1555 %                                                                             %
1556 +   X C l i e n t W i n d o w                                                 %
1557 %                                                                             %
1558 %                                                                             %
1559 %                                                                             %
1560 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1561 %
1562 %  XClientWindow() finds a window, at or below the specified window, which has
1563 %  a WM_STATE property.  If such a window is found, it is returned, otherwise
1564 %  the argument window is returned.
1565 %
1566 %  The format of the XClientWindow function is:
1567 %
1568 %      client_window=XClientWindow(display,target_window)
1569 %
1570 %  A description of each parameter follows:
1571 %
1572 %    o client_window: XClientWindow returns a window, at or below the specified
1573 %      window, which has a WM_STATE property otherwise the argument
1574 %      target_window is returned.
1575 %
1576 %    o display: Specifies a pointer to the Display structure;  returned from
1577 %      XOpenDisplay.
1578 %
1579 %    o target_window: Specifies the window to find a WM_STATE property.
1580 %
1581 */
1582 static Window XClientWindow(Display *display,Window target_window)
1583 {
1584   Atom
1585     state,
1586     type;
1587
1588   int
1589     format;
1590
1591   Status
1592     status;
1593
1594   unsigned char
1595     *data;
1596
1597   unsigned long
1598     after,
1599     number_items;
1600
1601   Window
1602     client_window;
1603
1604   (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
1605   assert(display != (Display *) NULL);
1606   state=XInternAtom(display,"WM_STATE",MagickTrue);
1607   if (state == (Atom) NULL)
1608     return(target_window);
1609   type=(Atom) NULL;
1610   status=XGetWindowProperty(display,target_window,state,0L,0L,MagickFalse,
1611     (Atom) AnyPropertyType,&type,&format,&number_items,&after,&data);
1612   if ((status == Success) && (type != (Atom) NULL))
1613     return(target_window);
1614   client_window=XWindowByProperty(display,target_window,state);
1615   if (client_window == (Window) NULL)
1616     return(target_window);
1617   return(client_window);
1618 }
1619 \f
1620 /*
1621 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1622 %                                                                             %
1623 %                                                                             %
1624 %                                                                             %
1625 +   X C o m p o n e n t T e r m i n u s                                       %
1626 %                                                                             %
1627 %                                                                             %
1628 %                                                                             %
1629 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1630 %
1631 %  XComponentTerminus() destroys the module component.
1632 %
1633 %  The format of the XComponentTerminus method is:
1634 %
1635 %      XComponentTerminus(void)
1636 %
1637 */
1638 MagickExport void XComponentTerminus(void)
1639 {
1640   DestroyXResources();
1641 }
1642 \f
1643 /*
1644 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1645 %                                                                             %
1646 %                                                                             %
1647 %                                                                             %
1648 %   X C o n f i g u r e I m a g e C o l o r m a p                             %
1649 %                                                                             %
1650 %                                                                             %
1651 %                                                                             %
1652 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1653 %
1654 %  XConfigureImageColormap() creates a new X colormap.
1655 %
1656 %  The format of the XConfigureImageColormap method is:
1657 %
1658 %      void XConfigureImageColormap(Display *display,
1659 %        XResourceInfo *resource_info,XWindows *windows,Image *image)
1660 %
1661 %  A description of each parameter follows:
1662 %
1663 %    o display: Specifies a connection to an X server; returned from
1664 %      XOpenDisplay.
1665 %
1666 %    o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
1667 %
1668 %    o windows: Specifies a pointer to a XWindows structure.
1669 %
1670 %    o image: the image.
1671 %
1672 */
1673 MagickExport void XConfigureImageColormap(Display *display,
1674   XResourceInfo *resource_info,XWindows *windows,Image *image)
1675 {
1676   Colormap
1677     colormap;
1678
1679   /*
1680     Make standard colormap.
1681   */
1682   XSetCursorState(display,windows,MagickTrue);
1683   XCheckRefreshWindows(display,windows);
1684   XMakeStandardColormap(display,windows->visual_info,resource_info,image,
1685     windows->map_info,windows->pixel_info);
1686   colormap=windows->map_info->colormap;
1687   (void) XSetWindowColormap(display,windows->image.id,colormap);
1688   (void) XSetWindowColormap(display,windows->command.id,colormap);
1689   (void) XSetWindowColormap(display,windows->widget.id,colormap);
1690   if (windows->magnify.mapped != MagickFalse)
1691     (void) XSetWindowColormap(display,windows->magnify.id,colormap);
1692   if (windows->pan.mapped != MagickFalse)
1693     (void) XSetWindowColormap(display,windows->pan.id,colormap);
1694   XSetCursorState(display,windows,MagickFalse);
1695   XClientMessage(display,windows->image.id,windows->im_protocols,
1696     windows->im_update_colormap,CurrentTime);
1697 }
1698 \f
1699 /*
1700 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1701 %                                                                             %
1702 %                                                                             %
1703 %                                                                             %
1704 %   X C o n s t r a i n W i n d o w P o s i t i o n                           %
1705 %                                                                             %
1706 %                                                                             %
1707 %                                                                             %
1708 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1709 %
1710 %  XConstrainWindowPosition() assures a window is positioned within the X
1711 %  server boundaries.
1712 %
1713 %  The format of the XConstrainWindowPosition method is:
1714 %
1715 %      void XConstrainWindowPosition(Display *display,XWindowInfo *window_info)
1716 %
1717 %  A description of each parameter follows:
1718 %
1719 %    o display: Specifies a pointer to the Display structure;  returned from
1720 %      XOpenDisplay.
1721 %
1722 %    o window_info: Specifies a pointer to a XWindowInfo structure.
1723 %
1724 */
1725 MagickExport void XConstrainWindowPosition(Display *display,
1726   XWindowInfo *window_info)
1727 {
1728   int
1729     limit;
1730
1731   (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
1732   assert(display != (Display *) NULL);
1733   assert(window_info != (XWindowInfo *) NULL);
1734   limit=XDisplayWidth(display,window_info->screen)-window_info->width;
1735   if (window_info->x < 0)
1736     window_info->x=0;
1737   else
1738     if (window_info->x > (int) limit)
1739       window_info->x=(int) limit;
1740   limit=XDisplayHeight(display,window_info->screen)-window_info->height;
1741   if (window_info->y < 0)
1742     window_info->y=0;
1743   else
1744     if (window_info->y > limit)
1745       window_info->y=limit;
1746 }
1747 \f
1748 /*
1749 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1750 %                                                                             %
1751 %                                                                             %
1752 %                                                                             %
1753 %   X D e l a y                                                               %
1754 %                                                                             %
1755 %                                                                             %
1756 %                                                                             %
1757 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1758 %
1759 %  XDelay() suspends program execution for the number of milliseconds
1760 %  specified.
1761 %
1762 %  The format of the Delay method is:
1763 %
1764 %      void XDelay(Display *display,const unsigned long milliseconds)
1765 %
1766 %  A description of each parameter follows:
1767 %
1768 %    o display: Specifies a pointer to the Display structure;  returned from
1769 %      XOpenDisplay.
1770 %
1771 %    o milliseconds: Specifies the number of milliseconds to delay before
1772 %      returning.
1773 %
1774 */
1775 MagickExport void XDelay(Display *display,const unsigned long milliseconds)
1776 {
1777   assert(display != (Display *) NULL);
1778   (void) XFlush(display);
1779   if (milliseconds == 0)
1780     return;
1781 #if defined(__WINDOWS__)
1782   Sleep(milliseconds);
1783 #elif defined(vms)
1784   {
1785     float
1786       timer;
1787
1788     timer=milliseconds/1000.0;
1789     lib$wait(&timer);
1790   }
1791 #elif defined(MAGICKCORE_HAVE_USLEEP)
1792   usleep(1000*milliseconds);
1793 #elif defined(MAGICKCORE_HAVE_SELECT)
1794   {
1795     struct timeval
1796       timer;
1797
1798     timer.tv_sec=(long) milliseconds/1000;
1799     timer.tv_usec=(long) (milliseconds % 1000)*1000;
1800     (void) select(0,(XFD_SET *) NULL,(XFD_SET *) NULL,(XFD_SET *) NULL,&timer);
1801   }
1802 #elif defined(MAGICKCORE_HAVE_POLL)
1803   (void) poll((struct pollfd *) NULL,0,(int) milliseconds);
1804 #elif defined(__BEOS__)
1805   snooze(1000*milliseconds);
1806 #else
1807 # error "Time delay method not defined."
1808 #endif
1809 }
1810 \f
1811 /*
1812 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1813 %                                                                             %
1814 %                                                                             %
1815 %                                                                             %
1816 %   X D e s t r o y R e s o u r c e I n f o                                   %
1817 %                                                                             %
1818 %                                                                             %
1819 %                                                                             %
1820 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1821 %
1822 %  XDestroyResourceInfo() frees memory associated with the XResourceInfo
1823 %  structure.
1824 %
1825 %  The format of the XDestroyResourceInfo method is:
1826 %
1827 %      void XDestroyResourceInfo(XResourceInfo *resource_info)
1828 %
1829 %  A description of each parameter follows:
1830 %
1831 %    o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
1832 %
1833 */
1834 MagickExport void XDestroyResourceInfo(XResourceInfo *resource_info)
1835 {
1836   if (resource_info->image_geometry != (char *) NULL)
1837     resource_info->image_geometry=(char *)
1838       RelinquishMagickMemory(resource_info->image_geometry);
1839   if (resource_info->quantize_info != (QuantizeInfo *) NULL)
1840     resource_info->quantize_info=DestroyQuantizeInfo(
1841       resource_info->quantize_info);
1842   if (resource_info->client_name != (char *) NULL)
1843     resource_info->client_name=(char *)
1844       RelinquishMagickMemory(resource_info->client_name);
1845   if (resource_info->name != (char *) NULL)
1846     resource_info->name=DestroyString(resource_info->name);
1847   (void) ResetMagickMemory(resource_info,0,sizeof(*resource_info));
1848 }
1849 \f
1850 /*
1851 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1852 %                                                                             %
1853 %                                                                             %
1854 %                                                                             %
1855 %   X D e s t r o y W i n d o w C o l o r s                                   %
1856 %                                                                             %
1857 %                                                                             %
1858 %                                                                             %
1859 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1860 %
1861 %  XDestroyWindowColors() frees X11 color resources previously saved on a
1862 %  window by XRetainWindowColors or programs like xsetroot.
1863 %
1864 %  The format of the XDestroyWindowColors method is:
1865 %
1866 %      void XDestroyWindowColors(Display *display,Window window)
1867 %
1868 %  A description of each parameter follows:
1869 %
1870 %    o display: Specifies a connection to an X server; returned from
1871 %      XOpenDisplay.
1872 %
1873 %    o window: Specifies a pointer to a Window structure.
1874 %
1875 */
1876 MagickExport void XDestroyWindowColors(Display *display,Window window)
1877 {
1878   Atom
1879     property,
1880     type;
1881
1882   int
1883     format;
1884
1885   Status
1886     status;
1887
1888   unsigned char
1889     *data;
1890
1891   unsigned long
1892     after,
1893     length;
1894
1895   /*
1896     If there are previous resources on the root window, destroy them.
1897   */
1898   (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
1899   assert(display != (Display *) NULL);
1900   property=XInternAtom(display,"_XSETROOT_ID",MagickFalse);
1901   if (property == (Atom) NULL)
1902     {
1903       ThrowXWindowFatalException(XServerError,"UnableToCreateProperty",
1904         "_XSETROOT_ID");
1905       return;
1906     }
1907   status=XGetWindowProperty(display,window,property,0L,1L,MagickTrue,
1908     (Atom) AnyPropertyType,&type,&format,&length,&after,&data);
1909   if (status != Success)
1910     return;
1911   if ((type == XA_PIXMAP) && (format == 32) && (length == 1) && (after == 0))
1912     {
1913       (void) XKillClient(display,(XID) (*((Pixmap *) data)));
1914       (void) XDeleteProperty(display,window,property);
1915     }
1916   if (type != None)
1917     (void) XFree((void *) data);
1918 }
1919 \f
1920 /*
1921 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1922 %                                                                             %
1923 %                                                                             %
1924 %                                                                             %
1925 %   X D i s p l a y I m a g e I n f o                                         %
1926 %                                                                             %
1927 %                                                                             %
1928 %                                                                             %
1929 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1930 %
1931 %  XDisplayImageInfo() displays information about an X image.
1932 %
1933 %  The format of the XDisplayImageInfo method is:
1934 %
1935 %      void XDisplayImageInfo(Display *display,
1936 %        const XResourceInfo *resource_info,XWindows *windows,Image *undo_image,
1937 %        Image *image)
1938 %
1939 %  A description of each parameter follows:
1940 %
1941 %    o display: Specifies a connection to an X server;  returned from
1942 %      XOpenDisplay.
1943 %
1944 %    o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
1945 %
1946 %    o windows: Specifies a pointer to a XWindows structure.
1947 %
1948 %    o undo_image: the undo image.
1949 %
1950 %    o image: the image.
1951 %
1952 */
1953 MagickExport void XDisplayImageInfo(Display *display,
1954   const XResourceInfo *resource_info,XWindows *windows,Image *undo_image,
1955   Image *image)
1956 {
1957   char
1958     filename[MaxTextExtent],
1959     *text,
1960     **textlist;
1961
1962   FILE
1963     *file;
1964
1965   int
1966     unique_file;
1967
1968   long
1969     bytes;
1970
1971   register long
1972     i;
1973
1974   unsigned int
1975     levels;
1976
1977   unsigned long
1978     number_pixels;
1979
1980   /*
1981     Write info about the X server to a file.
1982   */
1983   assert(display != (Display *) NULL);
1984   assert(resource_info != (XResourceInfo *) NULL);
1985   assert(windows != (XWindows *) NULL);
1986   assert(image != (Image *) NULL);
1987   if (image->debug)
1988     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
1989   file=(FILE *) NULL;
1990   unique_file=AcquireUniqueFileResource(filename);
1991   if (unique_file != -1)
1992     file=fdopen(unique_file,"w");
1993   if ((unique_file == -1) || (file == (FILE *) NULL))
1994     {
1995       XNoticeWidget(display,windows,"Unable to display image info",filename);
1996       return;
1997     }
1998   if (resource_info->gamma_correct != MagickFalse)
1999     if (resource_info->display_gamma != (char *) NULL)
2000       (void) fprintf(file,"Display\n  gamma: %s\n\n",
2001         resource_info->display_gamma);
2002   /*
2003     Write info about the X image to a file.
2004   */
2005   (void) fprintf(file,"X\n  visual: %s\n",
2006     XVisualClassName((int) windows->image.storage_class));
2007   (void) fprintf(file,"  depth: %d\n",windows->image.ximage->depth);
2008   if (windows->visual_info->colormap_size != 0)
2009     (void) fprintf(file,"  colormap size: %d\n",
2010       windows->visual_info->colormap_size);
2011   if (resource_info->colormap== SharedColormap)
2012     (void) fprintf(file,"  colormap type: Shared\n");
2013   else
2014     (void) fprintf(file,"  colormap type: Private\n");
2015   (void) fprintf(file,"  geometry: %dx%d\n",windows->image.ximage->width,
2016     windows->image.ximage->height);
2017   if (windows->image.crop_geometry != (char *) NULL)
2018     (void) fprintf(file,"  crop geometry: %s\n",windows->image.crop_geometry);
2019   if (windows->image.pixmap == (Pixmap) NULL)
2020     (void) fprintf(file,"  type: X Image\n");
2021   else
2022     (void) fprintf(file,"  type: Pixmap\n");
2023   if (windows->image.shape != MagickFalse)
2024     (void) fprintf(file,"  non-rectangular shape: True\n");
2025   else
2026     (void) fprintf(file,"  non-rectangular shape: False\n");
2027   if (windows->image.shared_memory != MagickFalse)
2028     (void) fprintf(file,"  shared memory: True\n");
2029   else
2030     (void) fprintf(file,"  shared memory: False\n");
2031   (void) fprintf(file,"\n");
2032   if (resource_info->font != (char *) NULL)
2033     (void) fprintf(file,"Font: %s\n\n",resource_info->font);
2034   if (resource_info->text_font != (char *) NULL)
2035     (void) fprintf(file,"Text font: %s\n\n",resource_info->text_font);
2036   /*
2037     Write info about the undo cache to a file.
2038   */
2039   bytes=0;
2040   for (levels=0; undo_image != (Image *) NULL; levels++)
2041   {
2042     number_pixels=undo_image->list->columns*undo_image->list->rows;
2043     bytes+=number_pixels*sizeof(PixelPacket);
2044     undo_image=GetPreviousImageInList(undo_image);
2045   }
2046   (void) fprintf(file,"Undo Edit Cache\n  levels: %u\n",levels);
2047   (void) fprintf(file,"  bytes: %lumb\n",(unsigned long)
2048     (bytes+(1 << 19)) >> 20);
2049   (void) fprintf(file,"  limit: %lumb\n\n",resource_info->undo_cache);
2050   /*
2051     Write info about the image to a file.
2052   */
2053   (void) IdentifyImage(image,file,MagickTrue);
2054   (void) fclose(file);
2055   text=FileToString(filename,~0,&image->exception);
2056   (void) RelinquishUniqueFileResource(filename);
2057   if (text == (char *) NULL)
2058     {
2059       XNoticeWidget(display,windows,"MemoryAllocationFailed",
2060         "UnableToDisplayImageInfo");
2061       return;
2062     }
2063   textlist=StringToList(text);
2064   if (textlist != (char **) NULL)
2065     {
2066       char
2067         title[MaxTextExtent];
2068
2069       /*
2070         Display information about the image in the Text View widget.
2071       */
2072       (void) XWithdrawWindow(display,windows->info.id,windows->info.screen);
2073       (void) FormatMagickString(title,MaxTextExtent,"Image Info: %s",
2074         image->filename);
2075       XTextViewWidget(display,resource_info,windows,MagickTrue,title,
2076         (char const **) textlist);
2077       for (i=0; textlist[i] != (char *) NULL; i++)
2078         textlist[i]=DestroyString(textlist[i]);
2079       textlist=(char **) RelinquishMagickMemory(textlist);
2080     }
2081   text=DestroyString(text);
2082 }
2083 \f
2084 /*
2085 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2086 %                                                                             %
2087 %                                                                             %
2088 %                                                                             %
2089 +     X D i t h e r I m a g e                                                 %
2090 %                                                                             %
2091 %                                                                             %
2092 %                                                                             %
2093 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2094 %
2095 %  XDitherImage() dithers the reference image as required by the HP Color
2096 %  Recovery algorithm.  The color values are quantized to 3 bits of red and
2097 %  green, and 2 bits of blue (3/3/2) and can be used as indices into a 8-bit X
2098 %  standard colormap.
2099 %
2100 %  The format of the XDitherImage method is:
2101 %
2102 %      void XDitherImage(Image *image,XImage *ximage)
2103 %
2104 %  A description of each parameter follows:
2105 %
2106 %    o image: the image.
2107 %
2108 %    o ximage: Specifies a pointer to a XImage structure;  returned from
2109 %      XCreateImage.
2110 %
2111 %
2112 */
2113 static void XDitherImage(Image *image,XImage *ximage)
2114 {
2115   static const short int
2116     dither_red[2][16]=
2117     {
2118       {-16,  4, -1, 11,-14,  6, -3,  9,-15,  5, -2, 10,-13,  7, -4,  8},
2119       { 15, -5,  0,-12, 13, -7,  2,-10, 14, -6,  1,-11, 12, -8,  3, -9}
2120     },
2121     dither_green[2][16]=
2122     {
2123       { 11,-15,  7, -3,  8,-14,  4, -2, 10,-16,  6, -4,  9,-13,  5, -1},
2124       {-12, 14, -8,  2, -9, 13, -5,  1,-11, 15, -7,  3,-10, 12, -6,  0}
2125     },
2126     dither_blue[2][16]=
2127     {
2128       { -3,  9,-13,  7, -1, 11,-15,  5, -4,  8,-14,  6, -2, 10,-16,  4},
2129       {  2,-10, 12, -8,  0,-12, 14, -6,  3, -9, 13, -7,  1,-11, 15, -5}
2130     };
2131
2132   PixelPacket
2133     color;
2134
2135   int
2136     y;
2137
2138   long
2139     value;
2140
2141   register char
2142     *q;
2143
2144   register const PixelPacket
2145     *p;
2146
2147   register int
2148     i,
2149     j,
2150     x;
2151
2152   unsigned int
2153     scanline_pad;
2154
2155   register unsigned long
2156     pixel;
2157
2158   unsigned char
2159     *blue_map[2][16],
2160     *green_map[2][16],
2161     *red_map[2][16];
2162
2163   /*
2164     Allocate and initialize dither maps.
2165   */
2166   for (i=0; i < 2; i++)
2167     for (j=0; j < 16; j++)
2168     {
2169       red_map[i][j]=(unsigned char *) AcquireQuantumMemory(256UL,
2170         sizeof(*red_map));
2171       green_map[i][j]=(unsigned char *) AcquireQuantumMemory(256UL,
2172         sizeof(*green_map));
2173       blue_map[i][j]=(unsigned char *) AcquireQuantumMemory(256UL,
2174         sizeof(*blue_map));
2175       if ((red_map[i][j] == (unsigned char *) NULL) ||
2176           (green_map[i][j] == (unsigned char *) NULL) ||
2177           (blue_map[i][j] == (unsigned char *) NULL))
2178         {
2179           ThrowXWindowFatalException(ResourceLimitError,
2180             "MemoryAllocationFailed",image->filename);
2181           return;
2182         }
2183     }
2184   /*
2185     Initialize dither tables.
2186   */
2187   for (i=0; i < 2; i++)
2188     for (j=0; j < 16; j++)
2189       for (x=0; x < 256; x++)
2190       {
2191         value=x-16;
2192         if (x < 48)
2193           value=x/2+8;
2194         value+=dither_red[i][j];
2195         red_map[i][j][x]=(unsigned char)
2196           ((value < 0) ? 0 : (value > 255) ? 255 : value);
2197         value=x-16;
2198         if (x < 48)
2199           value=x/2+8;
2200         value+=dither_green[i][j];
2201         green_map[i][j][x]=(unsigned char)
2202           ((value < 0) ? 0 : (value > 255) ? 255 : value);
2203         value=x-32;
2204         if (x < 112)
2205           value=x/2+24;
2206         value+=((unsigned long) dither_blue[i][j] << 1);
2207         blue_map[i][j][x]=(unsigned char)
2208           ((value < 0) ? 0 : (value > 255) ? 255 : value);
2209       }
2210   /*
2211     Dither image.
2212   */
2213   scanline_pad=(unsigned int) (ximage->bytes_per_line-
2214     ((unsigned long) (ximage->width*ximage->bits_per_pixel) >> 3));
2215   i=0;
2216   j=0;
2217   q=ximage->data;
2218   for (y=0; y < (int) image->rows; y++)
2219   {
2220     p=GetVirtualPixels(image,0,y,image->columns,1,&image->exception);
2221     if (p == (const PixelPacket *) NULL)
2222       break;
2223     for (x=0; x < (int) image->columns; x++)
2224     {
2225       color.red=RoundToQuantum((MagickRealType) (red_map[i][j][(int)
2226         ScaleQuantumToChar(p->red)] << 8));
2227       color.green=RoundToQuantum((MagickRealType) (green_map[i][j][(int)
2228         ScaleQuantumToChar(p->green)] << 8));
2229       color.blue=RoundToQuantum((MagickRealType) (blue_map[i][j][(int)
2230         ScaleQuantumToChar(p->blue)] << 8));
2231       pixel=(unsigned long) (((unsigned long) color.red & 0xe0) |
2232         (((unsigned long) color.green & 0xe0) >> 3) |
2233         (((unsigned long) color.blue & 0xc0) >> 6));
2234       *q++=(char) pixel;
2235       p++;
2236       j++;
2237       if (j == 16)
2238         j=0;
2239     }
2240     q+=scanline_pad;
2241     i++;
2242     if (i == 2)
2243       i=0;
2244   }
2245   /*
2246     Free allocated memory.
2247   */
2248   for (i=0; i < 2; i++)
2249     for (j=0; j < 16; j++)
2250     {
2251       green_map[i][j]=(unsigned char *) RelinquishMagickMemory(green_map[i][j]);
2252       blue_map[i][j]=(unsigned char *) RelinquishMagickMemory(blue_map[i][j]);
2253       red_map[i][j]=(unsigned char *) RelinquishMagickMemory(red_map[i][j]);
2254     }
2255 }
2256 \f
2257 /*
2258 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2259 %                                                                             %
2260 %                                                                             %
2261 %                                                                             %
2262 %   X D r a w I m a g e                                                       %
2263 %                                                                             %
2264 %                                                                             %
2265 %                                                                             %
2266 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2267 %
2268 %  XDrawImage() draws a line on the image.
2269 %
2270 %  The format of the XDrawImage method is:
2271 %
2272 %    MagickBooleanType XDrawImage(display,pixel,draw_info,image)
2273 %
2274 %  A description of each parameter follows:
2275 %
2276 %    o display: Specifies a connection to an X server;  returned from
2277 %      XOpenDisplay.
2278 %
2279 %    o pixel: Specifies a pointer to a XPixelInfo structure.
2280 %
2281 %    o draw_info: Specifies a pointer to a XDrawInfo structure.
2282 %
2283 %    o image: the image.
2284 %
2285 */
2286 MagickExport MagickBooleanType XDrawImage(Display *display,
2287   const XPixelInfo *pixel,XDrawInfo *draw_info,Image *image)
2288 {
2289   ExceptionInfo
2290     *exception;
2291
2292   GC
2293     draw_context;
2294
2295   Image
2296     *draw_image;
2297
2298   int
2299     x,
2300     y;
2301
2302   MagickBooleanType
2303     matte;
2304
2305   Pixmap
2306     draw_pixmap;
2307
2308   unsigned int
2309     depth,
2310     height,
2311     width;
2312
2313   Window
2314     root_window;
2315
2316   XGCValues
2317     context_values;
2318
2319   XImage
2320     *draw_ximage;
2321
2322   /*
2323     Initialize drawd image.
2324   */
2325   assert(display != (Display *) NULL);
2326   assert(pixel != (XPixelInfo *) NULL);
2327   assert(draw_info != (XDrawInfo *) NULL);
2328   assert(image != (Image *) NULL);
2329   if (image->debug != MagickFalse)
2330     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
2331   /*
2332     Initialize drawd pixmap.
2333   */
2334   root_window=XRootWindow(display,XDefaultScreen(display));
2335   depth=(unsigned int) XDefaultDepth(display,XDefaultScreen(display));
2336   draw_pixmap=XCreatePixmap(display,root_window,draw_info->width,
2337     draw_info->height,depth);
2338   if (draw_pixmap == (Pixmap) NULL)
2339     return(MagickFalse);
2340   /*
2341     Initialize graphics info.
2342   */
2343   context_values.background=(unsigned long) (~0);
2344   context_values.foreground=0;
2345   context_values.line_width=(int) draw_info->line_width;
2346   draw_context=XCreateGC(display,root_window,(unsigned long)
2347     (GCBackground | GCForeground | GCLineWidth),&context_values);
2348   if (draw_context == (GC) NULL)
2349     return(MagickFalse);
2350   /*
2351     Clear pixmap.
2352   */
2353   (void) XFillRectangle(display,draw_pixmap,draw_context,0,0,draw_info->width,
2354     draw_info->height);
2355   /*
2356     Draw line to pixmap.
2357   */
2358   (void) XSetBackground(display,draw_context,0);
2359   (void) XSetForeground(display,draw_context,(unsigned long) (~0));
2360   (void) XSetFillStyle(display,draw_context,FillOpaqueStippled);
2361   (void) XSetStipple(display,draw_context,draw_info->stipple);
2362   switch (draw_info->element)
2363   {
2364     case PointElement:
2365     default:
2366     {
2367       (void) XDrawLines(display,draw_pixmap,draw_context,
2368         draw_info->coordinate_info,(int) draw_info->number_coordinates,
2369         CoordModeOrigin);
2370       break;
2371     }
2372     case LineElement:
2373     {
2374       (void) XDrawLine(display,draw_pixmap,draw_context,draw_info->line_info.x1,
2375         draw_info->line_info.y1,draw_info->line_info.x2,
2376         draw_info->line_info.y2);
2377       break;
2378     }
2379     case RectangleElement:
2380     {
2381       (void) XDrawRectangle(display,draw_pixmap,draw_context,
2382         (int) draw_info->rectangle_info.x,(int) draw_info->rectangle_info.y,
2383         (unsigned int) draw_info->rectangle_info.width,
2384         (unsigned int) draw_info->rectangle_info.height);
2385       break;
2386     }
2387     case FillRectangleElement:
2388     {
2389       (void) XFillRectangle(display,draw_pixmap,draw_context,
2390         (int) draw_info->rectangle_info.x,(int) draw_info->rectangle_info.y,
2391         (unsigned int) draw_info->rectangle_info.width,
2392         (unsigned int) draw_info->rectangle_info.height);
2393       break;
2394     }
2395     case CircleElement:
2396     case EllipseElement:
2397     {
2398       (void) XDrawArc(display,draw_pixmap,draw_context,
2399         (int) draw_info->rectangle_info.x,(int) draw_info->rectangle_info.y,
2400         (unsigned int) draw_info->rectangle_info.width,
2401         (unsigned int) draw_info->rectangle_info.height,0,360*64);
2402       break;
2403     }
2404     case FillCircleElement:
2405     case FillEllipseElement:
2406     {
2407       (void) XFillArc(display,draw_pixmap,draw_context,
2408         (int) draw_info->rectangle_info.x,(int) draw_info->rectangle_info.y,
2409         (unsigned int) draw_info->rectangle_info.width,
2410         (unsigned int) draw_info->rectangle_info.height,0,360*64);
2411       break;
2412     }
2413     case PolygonElement:
2414     {
2415       XPoint
2416         *coordinate_info;
2417
2418       coordinate_info=draw_info->coordinate_info;
2419       (void) XDrawLines(display,draw_pixmap,draw_context,coordinate_info,
2420         (int) draw_info->number_coordinates,CoordModeOrigin);
2421       (void) XDrawLine(display,draw_pixmap,draw_context,
2422         coordinate_info[draw_info->number_coordinates-1].x,
2423         coordinate_info[draw_info->number_coordinates-1].y,
2424         coordinate_info[0].x,coordinate_info[0].y);
2425       break;
2426     }
2427     case FillPolygonElement:
2428     {
2429       (void) XFillPolygon(display,draw_pixmap,draw_context,
2430         draw_info->coordinate_info,(int) draw_info->number_coordinates,Complex,
2431         CoordModeOrigin);
2432       break;
2433     }
2434   }
2435   (void) XFreeGC(display,draw_context);
2436   /*
2437     Initialize X image.
2438   */
2439   draw_ximage=XGetImage(display,draw_pixmap,0,0,draw_info->width,
2440     draw_info->height,AllPlanes,ZPixmap);
2441   if (draw_ximage == (XImage *) NULL)
2442     return(MagickFalse);
2443   (void) XFreePixmap(display,draw_pixmap);
2444   /*
2445     Initialize draw image.
2446   */
2447   draw_image=AcquireImage((ImageInfo *) NULL);
2448   if (draw_image == (Image *) NULL)
2449     return(MagickFalse);
2450   draw_image->columns=draw_info->width;
2451   draw_image->rows=draw_info->height;
2452   /*
2453     Transfer drawn X image to image.
2454   */
2455   width=(unsigned int) image->columns;
2456   height=(unsigned int) image->rows;
2457   x=0;
2458   y=0;
2459   (void) XParseGeometry(draw_info->geometry,&x,&y,&width,&height);
2460   (void) GetOneVirtualPixel(image,x,y,&draw_image->background_color,
2461     &image->exception);
2462   if (SetImageStorageClass(draw_image,DirectClass) == MagickFalse)
2463     return(MagickFalse);
2464   draw_image->matte=MagickTrue;
2465   exception=(&image->exception);
2466   for (y=0; y < (int) draw_image->rows; y++)
2467   {
2468     register long
2469       x;
2470
2471     register PixelPacket
2472       *restrict q;
2473
2474     q=QueueAuthenticPixels(draw_image,0,y,draw_image->columns,1,exception);
2475     if (q == (PixelPacket *) NULL)
2476       break;
2477     for (x=0; x < (long) draw_image->columns; x++)
2478     {
2479       if (XGetPixel(draw_ximage,x,y) == 0)
2480         {
2481           /*
2482             Set this pixel to the background color.
2483           */
2484           *q=draw_image->background_color;
2485           q->opacity=(Quantum) (draw_info->stencil == OpaqueStencil ?
2486             TransparentOpacity : OpaqueOpacity);
2487         }
2488       else
2489         {
2490           /*
2491             Set this pixel to the pen color.
2492           */
2493           q->red=ScaleShortToQuantum(pixel->pen_color.red);
2494           q->green=ScaleShortToQuantum(pixel->pen_color.green);
2495           q->blue=ScaleShortToQuantum(pixel->pen_color.blue);
2496           q->opacity=(Quantum) (draw_info->stencil == OpaqueStencil ?
2497             OpaqueOpacity : TransparentOpacity);
2498         }
2499       q++;
2500     }
2501     if (SyncAuthenticPixels(draw_image,exception) == MagickFalse)
2502       break;
2503   }
2504   XDestroyImage(draw_ximage);
2505   /*
2506     Determine draw geometry.
2507   */
2508   (void) XParseGeometry(draw_info->geometry,&x,&y,&width,&height);
2509   if ((width != (unsigned int) draw_image->columns) ||
2510       (height != (unsigned int) draw_image->rows))
2511     {
2512       char
2513         image_geometry[MaxTextExtent];
2514
2515       /*
2516         Scale image.
2517       */
2518       (void) FormatMagickString(image_geometry,MaxTextExtent,"%ux%u",
2519         width,height);
2520       (void) TransformImage(&draw_image,(char *) NULL,image_geometry);
2521     }
2522   if (draw_info->degrees != 0.0)
2523     {
2524       Image
2525         *rotate_image;
2526
2527       int
2528         rotations;
2529
2530       MagickRealType
2531         normalized_degrees;
2532
2533       /*
2534         Rotate image.
2535       */
2536       rotate_image=RotateImage(draw_image,draw_info->degrees,&image->exception);
2537       if (rotate_image == (Image *) NULL)
2538         return(MagickFalse);
2539       draw_image=DestroyImage(draw_image);
2540       draw_image=rotate_image;
2541       /*
2542         Annotation is relative to the degree of rotation.
2543       */
2544       normalized_degrees=draw_info->degrees;
2545       while (normalized_degrees < -45.0)
2546         normalized_degrees+=360.0;
2547       for (rotations=0; normalized_degrees > 45.0; rotations++)
2548         normalized_degrees-=90.0;
2549       switch (rotations % 4)
2550       {
2551         default:
2552         case 0:
2553           break;
2554         case 1:
2555         {
2556           /*
2557             Rotate 90 degrees.
2558           */
2559           x=x-(int) draw_image->columns/2;
2560           y=y+(int) draw_image->columns/2;
2561           break;
2562         }
2563         case 2:
2564         {
2565           /*
2566             Rotate 180 degrees.
2567           */
2568           x=x-(int) draw_image->columns;
2569           break;
2570         }
2571         case 3:
2572         {
2573           /*
2574             Rotate 270 degrees.
2575           */
2576           x=x-(int) draw_image->columns/2;
2577           y=y-(int) (draw_image->rows-(draw_image->columns/2));
2578           break;
2579         }
2580       }
2581     }
2582   /*
2583     Composite text onto the image.
2584   */
2585   for (y=0; y < (int) draw_image->rows; y++)
2586   {
2587     register long
2588       x;
2589
2590     register PixelPacket
2591       *restrict q;
2592
2593     q=GetAuthenticPixels(draw_image,0,y,draw_image->columns,1,exception);
2594     if (q == (PixelPacket *) NULL)
2595       break;
2596     for (x=0; x < (long) draw_image->columns; x++)
2597     {
2598       if (q->opacity != (Quantum) TransparentOpacity)
2599         q->opacity=OpaqueOpacity;
2600       q++;
2601     }
2602     if (SyncAuthenticPixels(draw_image,exception) == MagickFalse)
2603       break;
2604   }
2605   (void) XParseGeometry(draw_info->geometry,&x,&y,&width,&height);
2606   if (draw_info->stencil == TransparentStencil)
2607     (void) CompositeImage(image,CopyOpacityCompositeOp,draw_image,x,y);
2608   else
2609     {
2610       matte=image->matte;
2611       (void) CompositeImage(image,OverCompositeOp,draw_image,x,y);
2612       image->matte=matte;
2613     }
2614   draw_image=DestroyImage(draw_image);
2615   return(MagickTrue);
2616 }
2617 \f
2618 /*
2619 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2620 %                                                                             %
2621 %                                                                             %
2622 %                                                                             %
2623 %   X E r r o r                                                               %
2624 %                                                                             %
2625 %                                                                             %
2626 %                                                                             %
2627 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2628 %
2629 %  XError() ignores BadWindow errors for XQueryTree and XGetWindowAttributes,
2630 %  and ignores BadDrawable errors for XGetGeometry, and ignores BadValue errors
2631 %  for XQueryColor.  It returns MagickFalse in those cases.  Otherwise it returns
2632 %  True.
2633 %
2634 %  The format of the XError function is:
2635 %
2636 %      XError(display,error)
2637 %
2638 %  A description of each parameter follows:
2639 %
2640 %    o display: Specifies a pointer to the Display structure;  returned from
2641 %      XOpenDisplay.
2642 %
2643 %    o error: Specifies the error event.
2644 %
2645 */
2646
2647 #if defined(__cplusplus) || defined(c_plusplus)
2648 extern "C" {
2649 #endif
2650
2651 MagickExport int XError(Display *display,XErrorEvent *error)
2652 {
2653   (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
2654   assert(display != (Display *) NULL);
2655   assert(error != (XErrorEvent *) NULL);
2656   xerror_alert=MagickTrue;
2657   switch (error->request_code)
2658   {
2659     case X_GetGeometry:
2660     {
2661       if ((int) error->error_code == BadDrawable)
2662         return(MagickFalse);
2663       break;
2664     }
2665     case X_GetWindowAttributes:
2666     case X_QueryTree:
2667     {
2668       if ((int) error->error_code == BadWindow)
2669         return(MagickFalse);
2670       break;
2671     }
2672     case X_QueryColors:
2673     {
2674       if ((int) error->error_code == BadValue)
2675         return(MagickFalse);
2676       break;
2677     }
2678   }
2679   return(MagickTrue);
2680 }
2681
2682 #if defined(__cplusplus) || defined(c_plusplus)
2683 }
2684 #endif
2685 \f
2686 /*
2687 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2688 %                                                                             %
2689 %                                                                             %
2690 %                                                                             %
2691 %   X F r e e R e s o u r c e s                                               %
2692 %                                                                             %
2693 %                                                                             %
2694 %                                                                             %
2695 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2696 %
2697 %  XFreeResources() frees X11 resources.
2698 %
2699 %  The format of the XFreeResources method is:
2700 %
2701 %      void XFreeResources(Display *display,XVisualInfo *visual_info,
2702 %        XStandardColormap *map_info,XPixelInfo *pixel,XFontStruct *font_info,
2703 %        XResourceInfo *resource_info,XWindowInfo *window_info)
2704 %        resource_info,window_info)
2705 %
2706 %  A description of each parameter follows:
2707 %
2708 %    o display: Specifies a connection to an X server; returned from
2709 %      XOpenDisplay.
2710 %
2711 %    o visual_info: Specifies a pointer to a X11 XVisualInfo structure;
2712 %      returned from XGetVisualInfo.
2713 %
2714 %    o map_info: If map_type is specified, this structure is initialized
2715 %      with info from the Standard Colormap.
2716 %
2717 %    o pixel: Specifies a pointer to a XPixelInfo structure.
2718 %
2719 %    o font_info: Specifies a pointer to a XFontStruct structure.
2720 %
2721 %    o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
2722 %
2723 %    o window_info: Specifies a pointer to a X11 XWindowInfo structure.
2724 %
2725 */
2726 MagickExport void XFreeResources(Display *display,XVisualInfo *visual_info,
2727   XStandardColormap *map_info,XPixelInfo *pixel,XFontStruct *font_info,
2728   XResourceInfo *resource_info,XWindowInfo *window_info)
2729 {
2730   (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
2731   assert(display != (Display *) NULL);
2732   assert(resource_info != (XResourceInfo *) NULL);
2733   if (window_info != (XWindowInfo *) NULL)
2734     {
2735       /*
2736         Free X image.
2737       */
2738       if (window_info->ximage != (XImage *) NULL)
2739         XDestroyImage(window_info->ximage);
2740       if (window_info->id != (Window) NULL)
2741         {
2742           /*
2743             Free destroy window and free cursors.
2744           */
2745           if (window_info->id != XRootWindow(display,visual_info->screen))
2746             (void) XDestroyWindow(display,window_info->id);
2747           if (window_info->annotate_context != (GC) NULL)
2748             (void) XFreeGC(display,window_info->annotate_context);
2749           if (window_info->highlight_context != (GC) NULL)
2750             (void) XFreeGC(display,window_info->highlight_context);
2751           if (window_info->widget_context != (GC) NULL)
2752             (void) XFreeGC(display,window_info->widget_context);
2753           if (window_info->cursor != (Cursor) NULL)
2754             (void) XFreeCursor(display,window_info->cursor);
2755           window_info->cursor=(Cursor) NULL;
2756           if (window_info->busy_cursor != (Cursor) NULL)
2757             (void) XFreeCursor(display,window_info->busy_cursor);
2758           window_info->busy_cursor=(Cursor) NULL;
2759         }
2760     }
2761   /*
2762     Free font.
2763   */
2764   if (font_info != (XFontStruct *) NULL)
2765     (void) XFreeFont(display,font_info);
2766   if (map_info != (XStandardColormap *) NULL)
2767     {
2768       /*
2769         Free X Standard Colormap.
2770       */
2771       if (resource_info->map_type == (char *) NULL)
2772         (void) XFreeStandardColormap(display,visual_info,map_info,pixel);
2773       (void) XFree((void *) map_info);
2774     }
2775   /*
2776     Free X visual info.
2777   */
2778   if (visual_info != (XVisualInfo *) NULL)
2779     (void) XFree((void *) visual_info);
2780   if (resource_info->close_server != MagickFalse)
2781     (void) XCloseDisplay(display);
2782 }
2783 \f
2784 /*
2785 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2786 %                                                                             %
2787 %                                                                             %
2788 %                                                                             %
2789 %   X F r e e S t a n d a r d C o l o r m a p                                 %
2790 %                                                                             %
2791 %                                                                             %
2792 %                                                                             %
2793 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2794 %
2795 %  XFreeStandardColormap() frees an X11 colormap.
2796 %
2797 %  The format of the XFreeStandardColormap method is:
2798 %
2799 %      void XFreeStandardColormap(Display *display,
2800 %        const XVisualInfo *visual_info,XStandardColormap *map_info,
2801 %        XPixelInfo *pixel)
2802 %
2803 %  A description of each parameter follows:
2804 %
2805 %    o display: Specifies a connection to an X server; returned from
2806 %      XOpenDisplay.
2807 %
2808 %    o visual_info: Specifies a pointer to a X11 XVisualInfo structure;
2809 %      returned from XGetVisualInfo.
2810 %
2811 %    o map_info: If map_type is specified, this structure is initialized
2812 %      with info from the Standard Colormap.
2813 %
2814 %    o pixel: Specifies a pointer to a XPixelInfo structure.
2815 %
2816 */
2817 MagickExport void XFreeStandardColormap(Display *display,
2818   const XVisualInfo *visual_info,XStandardColormap *map_info,XPixelInfo *pixel)
2819 {
2820   /*
2821     Free colormap.
2822   */
2823   (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
2824   assert(display != (Display *) NULL);
2825   assert(visual_info != (XVisualInfo *) NULL);
2826   assert(map_info != (XStandardColormap *) NULL);
2827   (void) XFlush(display);
2828   if (map_info->colormap != (Colormap) NULL)
2829     {
2830       if (map_info->colormap != XDefaultColormap(display,visual_info->screen))
2831         (void) XFreeColormap(display,map_info->colormap);
2832       else
2833         if (pixel != (XPixelInfo *) NULL)
2834           if ((visual_info->klass != TrueColor) &&
2835               (visual_info->klass != DirectColor))
2836             (void) XFreeColors(display,map_info->colormap,pixel->pixels,
2837               (int) pixel->colors,0);
2838     }
2839   map_info->colormap=(Colormap) NULL;
2840   if (pixel != (XPixelInfo *) NULL)
2841     {
2842       if (pixel->pixels != (unsigned long *) NULL)
2843         pixel->pixels=(unsigned long *) RelinquishMagickMemory(pixel->pixels);
2844       pixel->pixels=(unsigned long *) NULL;
2845     }
2846 }
2847 \f
2848 /*
2849 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2850 %                                                                             %
2851 %                                                                             %
2852 %                                                                             %
2853 %   X G e t A n n o t a t e I n f o                                           %
2854 %                                                                             %
2855 %                                                                             %
2856 %                                                                             %
2857 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2858 %
2859 %  XGetAnnotateInfo() initializes the AnnotateInfo structure.
2860 %
2861 %  The format of the XGetAnnotateInfo method is:
2862 %
2863 %      void XGetAnnotateInfo(XAnnotateInfo *annotate_info)
2864 %
2865 %  A description of each parameter follows:
2866 %
2867 %    o annotate_info: Specifies a pointer to a XAnnotateInfo structure.
2868 %
2869 */
2870 MagickExport void XGetAnnotateInfo(XAnnotateInfo *annotate_info)
2871 {
2872   /*
2873     Initialize annotate structure.
2874   */
2875   (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
2876   assert(annotate_info != (XAnnotateInfo *) NULL);
2877   annotate_info->x=0;
2878   annotate_info->y=0;
2879   annotate_info->width=0;
2880   annotate_info->height=0;
2881   annotate_info->stencil=ForegroundStencil;
2882   annotate_info->degrees=0.0;
2883   annotate_info->font_info=(XFontStruct *) NULL;
2884   annotate_info->text=(char *) NULL;
2885   *annotate_info->geometry='\0';
2886   annotate_info->previous=(XAnnotateInfo *) NULL;
2887   annotate_info->next=(XAnnotateInfo *) NULL;
2888   (void) XSupportsLocale();
2889   (void) XSetLocaleModifiers("");
2890 }
2891 \f
2892 /*
2893 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2894 %                                                                             %
2895 %                                                                             %
2896 %                                                                             %
2897 %   X G e t M a p I n f o                                                     %
2898 %                                                                             %
2899 %                                                                             %
2900 %                                                                             %
2901 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2902 %
2903 %  XGetMapInfo() initializes the XStandardColormap structure.
2904 %
2905 %  The format of the XStandardColormap method is:
2906 %
2907 %      void XGetMapInfo(const XVisualInfo *visual_info,const Colormap colormap,
2908 %        XStandardColormap *map_info)
2909 %
2910 %  A description of each parameter follows:
2911 %
2912 %    o colormap: Specifies the ID of the X server colormap.
2913 %
2914 %    o visual_info: Specifies a pointer to a X11 XVisualInfo structure;
2915 %      returned from XGetVisualInfo.
2916 %
2917 %    o map_info: Specifies a pointer to a X11 XStandardColormap structure.
2918 %
2919 */
2920 MagickExport void XGetMapInfo(const XVisualInfo *visual_info,
2921   const Colormap colormap,XStandardColormap *map_info)
2922 {
2923   /*
2924     Initialize map info.
2925   */
2926   (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
2927   assert(visual_info != (XVisualInfo *) NULL);
2928   assert(map_info != (XStandardColormap *) NULL);
2929   map_info->colormap=colormap;
2930   map_info->red_max=visual_info->red_mask;
2931   map_info->red_mult=(unsigned long) (map_info->red_max != 0 ? 1 : 0);
2932   if (map_info->red_max != 0)
2933     while ((map_info->red_max & 0x01) == 0)
2934     {
2935       map_info->red_max>>=1;
2936       map_info->red_mult<<=1;
2937     }
2938   map_info->green_max=visual_info->green_mask;
2939   map_info->green_mult=(unsigned long) (map_info->green_max != 0 ? 1 : 0);
2940   if (map_info->green_max != 0)
2941     while ((map_info->green_max & 0x01) == 0)
2942     {
2943       map_info->green_max>>=1;
2944       map_info->green_mult<<=1;
2945     }
2946   map_info->blue_max=visual_info->blue_mask;
2947   map_info->blue_mult=(unsigned long) (map_info->blue_max != 0 ? 1 : 0);
2948   if (map_info->blue_max != 0)
2949     while ((map_info->blue_max & 0x01) == 0)
2950     {
2951       map_info->blue_max>>=1;
2952       map_info->blue_mult<<=1;
2953     }
2954   map_info->base_pixel=0;
2955 }
2956 \f
2957 /*
2958 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2959 %                                                                             %
2960 %                                                                             %
2961 %                                                                             %
2962 %   X G e t P i x e l I n f o                                                 %
2963 %                                                                             %
2964 %                                                                             %
2965 %                                                                             %
2966 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2967 %
2968 %  XGetPixelPacket() initializes the PixelPacket structure.
2969 %
2970 %  The format of the XGetPixelPacket method is:
2971 %
2972 %      void XGetPixelPacket(Display *display,const XVisualInfo *visual_info,
2973 %        const XStandardColormap *map_info,const XResourceInfo *resource_info,
2974 %        Image *image,XPixelInfo *pixel)
2975 %        pixel)
2976 %
2977 %  A description of each parameter follows:
2978 %
2979 %    o display: Specifies a connection to an X server; returned from
2980 %      XOpenDisplay.
2981 %
2982 %    o visual_info: Specifies a pointer to a X11 XVisualInfo structure;
2983 %      returned from XGetVisualInfo.
2984 %
2985 %    o map_info: If map_type is specified, this structure is initialized
2986 %      with info from the Standard Colormap.
2987 %
2988 %    o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
2989 %
2990 %    o image: the image.
2991 %
2992 %    o pixel: Specifies a pointer to a XPixelInfo structure.
2993 %
2994 */
2995 MagickExport void XGetPixelPacket(Display *display,
2996   const XVisualInfo *visual_info,const XStandardColormap *map_info,
2997   const XResourceInfo *resource_info,Image *image,XPixelInfo *pixel)
2998 {
2999   static const char
3000     *PenColors[MaxNumberPens]=
3001     {
3002       "#000000000000",  /* black */
3003       "#00000000ffff",  /* blue */
3004       "#0000ffffffff",  /* cyan */
3005       "#0000ffff0000",  /* green */
3006       "#bdbdbdbdbdbd",  /* gray */
3007       "#ffff00000000",  /* red */
3008       "#ffff0000ffff",  /* magenta */
3009       "#ffffffff0000",  /* yellow */
3010       "#ffffffffffff",  /* white */
3011       "#bdbdbdbdbdbd",  /* gray */
3012       "#bdbdbdbdbdbd"   /* gray */
3013     };
3014
3015   Colormap
3016     colormap;
3017
3018   register long
3019     i;
3020
3021   Status
3022     status;
3023
3024   unsigned int
3025     packets;
3026
3027   /*
3028     Initialize pixel info.
3029   */
3030   (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
3031   assert(display != (Display *) NULL);
3032   assert(visual_info != (XVisualInfo *) NULL);
3033   assert(map_info != (XStandardColormap *) NULL);
3034   assert(resource_info != (XResourceInfo *) NULL);
3035   assert(pixel != (XPixelInfo *) NULL);
3036   pixel->colors=0;
3037   if (image != (Image *) NULL)
3038     if (image->storage_class == PseudoClass)
3039       pixel->colors=image->colors;
3040   packets=(unsigned int)
3041     MagickMax((int) pixel->colors,visual_info->colormap_size)+MaxNumberPens;
3042   if (pixel->pixels != (unsigned long *) NULL)
3043     pixel->pixels=(unsigned long *) RelinquishMagickMemory(pixel->pixels);
3044   pixel->pixels=(unsigned long *) AcquireQuantumMemory(packets,
3045     sizeof(pixel->pixels));
3046   if (pixel->pixels == (unsigned long *) NULL)
3047     ThrowXWindowFatalException(ResourceLimitFatalError,"UnableToGetPixelInfo",
3048       image->filename);
3049   /*
3050     Set foreground color.
3051   */
3052   colormap=map_info->colormap;
3053   (void) XParseColor(display,colormap,(char *) ForegroundColor,
3054     &pixel->foreground_color);
3055   status=XParseColor(display,colormap,resource_info->foreground_color,
3056     &pixel->foreground_color);
3057   if (status == False)
3058     ThrowXWindowFatalException(XServerError,"ColorIsNotKnownToServer",
3059       resource_info->foreground_color);
3060   pixel->foreground_color.pixel=
3061     XStandardPixel(map_info,&pixel->foreground_color);
3062   pixel->foreground_color.flags=(char) (DoRed | DoGreen | DoBlue);
3063   /*
3064     Set background color.
3065   */
3066   (void) XParseColor(display,colormap,"#d6d6d6d6d6d6",&pixel->background_color);
3067   status=XParseColor(display,colormap,resource_info->background_color,
3068     &pixel->background_color);
3069   if (status == False)
3070     ThrowXWindowFatalException(XServerError,"ColorIsNotKnownToServer",
3071       resource_info->background_color);
3072   pixel->background_color.pixel=
3073     XStandardPixel(map_info,&pixel->background_color);
3074   pixel->background_color.flags=(char) (DoRed | DoGreen | DoBlue);
3075   /*
3076     Set border color.
3077   */
3078   (void) XParseColor(display,colormap,(char *) BorderColor,
3079     &pixel->border_color);
3080   status=XParseColor(display,colormap,resource_info->border_color,
3081     &pixel->border_color);
3082   if (status == False)
3083     ThrowXWindowFatalException(XServerError,"ColorIsNotKnownToServer",
3084       resource_info->border_color);
3085   pixel->border_color.pixel=XStandardPixel(map_info,&pixel->border_color);
3086   pixel->border_color.flags=(char) (DoRed | DoGreen | DoBlue);
3087   /*
3088     Set matte color.
3089   */
3090   pixel->matte_color=pixel->background_color;
3091   if (resource_info->matte_color != (char *) NULL)
3092     {
3093       /*
3094         Matte color is specified as a X resource or command line argument.
3095       */
3096       status=XParseColor(display,colormap,resource_info->matte_color,
3097         &pixel->matte_color);
3098       if (status == False)
3099         ThrowXWindowFatalException(XServerError,"ColorIsNotKnownToServer",
3100           resource_info->matte_color);
3101       pixel->matte_color.pixel=XStandardPixel(map_info,&pixel->matte_color);
3102       pixel->matte_color.flags=(char) (DoRed | DoGreen | DoBlue);
3103     }
3104   /*
3105     Set highlight color.
3106   */
3107   pixel->highlight_color.red=(unsigned short) ((
3108     pixel->matte_color.red*ScaleQuantumToShort(HighlightModulate))/65535L+
3109     (ScaleQuantumToShort((Quantum) (QuantumRange-HighlightModulate))));
3110   pixel->highlight_color.green=(unsigned short) ((
3111     pixel->matte_color.green*ScaleQuantumToShort(HighlightModulate))/65535L+
3112     (ScaleQuantumToShort((Quantum) (QuantumRange-HighlightModulate))));
3113   pixel->highlight_color.blue=(unsigned short) ((
3114     pixel->matte_color.blue*ScaleQuantumToShort(HighlightModulate))/65535L+
3115     (ScaleQuantumToShort((Quantum) (QuantumRange-HighlightModulate))));
3116   pixel->highlight_color.pixel=
3117     XStandardPixel(map_info,&pixel->highlight_color);
3118   pixel->highlight_color.flags=(char) (DoRed | DoGreen | DoBlue);
3119   /*
3120     Set shadow color.
3121   */
3122   pixel->shadow_color.red=(unsigned short) (((MagickRealType)
3123     pixel->matte_color.red*ScaleQuantumToShort(ShadowModulate))/65535L);
3124   pixel->shadow_color.green=(unsigned short) (((MagickRealType)
3125     pixel->matte_color.green*ScaleQuantumToShort(ShadowModulate))/65535L);
3126   pixel->shadow_color.blue=(unsigned short) (((MagickRealType)
3127     pixel->matte_color.blue*ScaleQuantumToShort(ShadowModulate))/65535L);
3128   pixel->shadow_color.pixel=XStandardPixel(map_info,&pixel->shadow_color);
3129   pixel->shadow_color.flags=(char) (DoRed | DoGreen | DoBlue);
3130   /*
3131     Set depth color.
3132   */
3133   pixel->depth_color.red=(unsigned short) (((MagickRealType)
3134     pixel->matte_color.red*ScaleQuantumToShort(DepthModulate))/65535L);
3135   pixel->depth_color.green=(unsigned short) (((MagickRealType)
3136     pixel->matte_color.green*ScaleQuantumToShort(DepthModulate))/65535L);
3137   pixel->depth_color.blue=(unsigned short) (((MagickRealType)
3138     pixel->matte_color.blue*ScaleQuantumToShort(DepthModulate))/65535L);
3139   pixel->depth_color.pixel=XStandardPixel(map_info,&pixel->depth_color);
3140   pixel->depth_color.flags=(char) (DoRed | DoGreen | DoBlue);
3141   /*
3142     Set trough color.
3143   */
3144   pixel->trough_color.red=(unsigned short) (((MagickRealType)
3145     pixel->matte_color.red*ScaleQuantumToShort(TroughModulate))/65535L);
3146   pixel->trough_color.green=(unsigned short) (((MagickRealType)
3147     pixel->matte_color.green*ScaleQuantumToShort(TroughModulate))/65535L);
3148   pixel->trough_color.blue=(unsigned short) (((MagickRealType)
3149     pixel->matte_color.blue*ScaleQuantumToShort(TroughModulate))/65535L);
3150   pixel->trough_color.pixel=XStandardPixel(map_info,&pixel->trough_color);
3151   pixel->trough_color.flags=(char) (DoRed | DoGreen | DoBlue);
3152   /*
3153     Set pen color.
3154   */
3155   for (i=0; i < MaxNumberPens; i++)
3156   {
3157     (void) XParseColor(display,colormap,(char *) PenColors[i],
3158       &pixel->pen_colors[i]);
3159     status=XParseColor(display,colormap,resource_info->pen_colors[i],
3160       &pixel->pen_colors[i]);
3161     if (status == False)
3162       ThrowXWindowFatalException(XServerError,"ColorIsNotKnownToServer",
3163         resource_info->pen_colors[i]);
3164     pixel->pen_colors[i].pixel=XStandardPixel(map_info,&pixel->pen_colors[i]);
3165     pixel->pen_colors[i].flags=(char) (DoRed | DoGreen | DoBlue);
3166   }
3167   pixel->box_color=pixel->background_color;
3168   pixel->pen_color=pixel->foreground_color;
3169   pixel->box_index=0;
3170   pixel->pen_index=1;
3171   if (image != (Image *) NULL)
3172     {
3173       if ((resource_info->gamma_correct != MagickFalse) &&
3174           (image->gamma != 0.0))
3175         {
3176           GeometryInfo
3177             geometry_info;
3178
3179           MagickStatusType
3180             flags;
3181
3182           /*
3183             Initialize map relative to display and image gamma.
3184           */
3185           flags=ParseGeometry(resource_info->display_gamma,&geometry_info);
3186           red_gamma=geometry_info.rho;
3187           green_gamma=geometry_info.sigma;
3188           if ((flags & SigmaValue) == 0)
3189             green_gamma=red_gamma;
3190           blue_gamma=geometry_info.xi;
3191           if ((flags & XiValue) == 0)
3192             blue_gamma=red_gamma;
3193           red_gamma*=image->gamma;
3194           green_gamma*=image->gamma;
3195           blue_gamma*=image->gamma;
3196         }
3197       if (image->storage_class == PseudoClass)
3198         {
3199           /*
3200             Initialize pixel array for images of type PseudoClass.
3201           */
3202           for (i=0; i < (long) image->colors; i++)
3203             pixel->pixels[i]=
3204               XGammaPixel(map_info,image->colormap+i);
3205           for (i=0; i < MaxNumberPens; i++)
3206             pixel->pixels[image->colors+i]=pixel->pen_colors[i].pixel;
3207           pixel->colors+=MaxNumberPens;
3208         }
3209     }
3210 }
3211 \f
3212 /*
3213 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3214 %                                                                             %
3215 %                                                                             %
3216 %                                                                             %
3217 %   X G e t R e s o u r c e C l a s s                                         %
3218 %                                                                             %
3219 %                                                                             %
3220 %                                                                             %
3221 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3222 %
3223 %  XGetResourceClass() queries the X server for the specified resource name or
3224 %  class.  If the resource name or class is not defined in the database, the
3225 %  supplied default value is returned.
3226 %
3227 %  The format of the XGetResourceClass method is:
3228 %
3229 %      char *XGetResourceClass(XrmDatabase database,const char *client_name,
3230 %        const char *keyword,char *resource_default)
3231 %
3232 %  A description of each parameter follows:
3233 %
3234 %    o database: Specifies a resource database; returned from
3235 %      XrmGetStringDatabase.
3236 %
3237 %    o client_name:  Specifies the application name used to retrieve resource
3238 %      info from the X server database.
3239 %
3240 %    o keyword: Specifies the keyword of the value being retrieved.
3241 %
3242 %    o resource_default: Specifies the default value to return if the query
3243 %      fails to find the specified keyword/class.
3244 %
3245 */
3246 MagickExport char *XGetResourceClass(XrmDatabase database,
3247   const char *client_name,const char *keyword,char *resource_default)
3248 {
3249   char
3250     resource_class[MaxTextExtent],
3251     resource_name[MaxTextExtent];
3252
3253   static char
3254     *resource_type;
3255
3256   Status
3257     status;
3258
3259   XrmValue
3260     resource_value;
3261
3262   if (database == (XrmDatabase) NULL)
3263     return(resource_default);
3264   *resource_name='\0';
3265   *resource_class='\0';
3266   if (keyword != (char *) NULL)
3267     {
3268       int
3269         c,
3270         k;
3271
3272       /*
3273         Initialize resource keyword and class.
3274       */
3275       (void) FormatMagickString(resource_name,MaxTextExtent,"%s.%s",
3276         client_name,keyword);
3277       c=(int) (*client_name);
3278       if ((c >= XK_a) && (c <= XK_z))
3279         c-=(XK_a-XK_A);
3280       else
3281         if ((c >= XK_agrave) && (c <= XK_odiaeresis))
3282           c-=(XK_agrave-XK_Agrave);
3283         else
3284           if ((c >= XK_oslash) && (c <= XK_thorn))
3285             c-=(XK_oslash-XK_Ooblique);
3286       k=(int) (*keyword);
3287       if ((k >= XK_a) && (k <= XK_z))
3288         k-=(XK_a-XK_A);
3289       else
3290         if ((k >= XK_agrave) && (k <= XK_odiaeresis))
3291           k-=(XK_agrave-XK_Agrave);
3292         else
3293           if ((k >= XK_oslash) && (k <= XK_thorn))
3294             k-=(XK_oslash-XK_Ooblique);
3295       (void) FormatMagickString(resource_class,MaxTextExtent,"%c%s.%c%s",c,
3296         client_name+1,k,keyword+1);
3297     }
3298   status=XrmGetResource(database,resource_name,resource_class,&resource_type,
3299     &resource_value);
3300   if (status == False)
3301     return(resource_default);
3302   return(resource_value.addr);
3303 }
3304 \f
3305 /*
3306 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3307 %                                                                             %
3308 %                                                                             %
3309 %                                                                             %
3310 %   X G e t R e s o u r c e D a t a b a s e                                   %
3311 %                                                                             %
3312 %                                                                             %
3313 %                                                                             %
3314 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3315 %
3316 %  XGetResourceDatabase() creates a new resource database and initializes it.
3317 %
3318 %  The format of the XGetResourceDatabase method is:
3319 %
3320 %      XrmDatabase XGetResourceDatabase(Display *display,
3321 %        const char *client_name)
3322 %
3323 %  A description of each parameter follows:
3324 %
3325 %    o database: XGetResourceDatabase() returns the database after it is
3326 %      initialized.
3327 %
3328 %    o display: Specifies a connection to an X server;  returned from
3329 %      XOpenDisplay.
3330 %
3331 %    o client_name:  Specifies the application name used to retrieve resource
3332 %      info from the X server database.
3333 %
3334 */
3335 MagickExport XrmDatabase XGetResourceDatabase(Display *display,
3336   const char *client_name)
3337 {
3338   char
3339     filename[MaxTextExtent];
3340
3341   int
3342     c;
3343
3344   register const char
3345     *p;
3346
3347   XrmDatabase
3348     resource_database,
3349     server_database;
3350
3351   if (display == (Display *) NULL)
3352     return((XrmDatabase) NULL);
3353   assert(client_name != (char *) NULL);
3354   /*
3355     Initialize resource database.
3356   */
3357   XrmInitialize();
3358   (void) XGetDefault(display,(char *) client_name,"dummy");
3359   resource_database=XrmGetDatabase(display);
3360   /*
3361     Combine application database.
3362   */
3363   if (client_name != (char *) NULL)
3364     {
3365       /*
3366         Get basename of client.
3367       */
3368       p=client_name+(strlen(client_name)-1);
3369       while ((p > client_name) && (*p != '/'))
3370         p--;
3371       if (*p == '/')
3372         client_name=p+1;
3373     }
3374   c=(int) (*client_name);
3375   if ((c >= XK_a) && (c <= XK_z))
3376     c-=(XK_a-XK_A);
3377   else
3378     if ((c >= XK_agrave) && (c <= XK_odiaeresis))
3379       c-=(XK_agrave-XK_Agrave);
3380     else
3381       if ((c >= XK_oslash) && (c <= XK_thorn))
3382         c-=(XK_oslash-XK_Ooblique);
3383 #if defined(X11_APPLICATION_PATH)
3384   (void) FormatMagickString(filename,MaxTextExtent,"%s%c%s",
3385     X11_APPLICATION_PATH,c,client_name+1);
3386   (void) XrmCombineFileDatabase(filename,&resource_database,MagickFalse);
3387 #endif
3388   if (XResourceManagerString(display) != (char *) NULL)
3389     {
3390       /*
3391         Combine server database.
3392       */
3393       server_database=XrmGetStringDatabase(XResourceManagerString(display));
3394       XrmCombineDatabase(server_database,&resource_database,MagickFalse);
3395     }
3396   /*
3397     Merge user preferences database.
3398   */
3399 #if defined(X11_PREFERENCES_PATH)
3400   (void) FormatMagickString(filename,MaxTextExtent,"%s%src",
3401     X11_PREFERENCES_PATH,client_name);
3402   ExpandFilename(filename);
3403   (void) XrmCombineFileDatabase(filename,&resource_database,MagickFalse);
3404 #endif
3405   return(resource_database);
3406 }
3407 \f
3408 /*
3409 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3410 %                                                                             %
3411 %                                                                             %
3412 %                                                                             %
3413 %   X G e t R e s o u r c e I n f o                                           %
3414 %                                                                             %
3415 %                                                                             %
3416 %                                                                             %
3417 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3418 %
3419 %  XGetResourceInfo(image_info,) initializes the ResourceInfo structure.
3420 %
3421 %  The format of the XGetResourceInfo method is:
3422 %
3423 %      void XGetResourceInfo(const ImageInfo *image_info,XrmDatabase database,
3424 %        const char *client_name,XResourceInfo *resource_info)
3425 %
3426 %  A description of each parameter follows:
3427 %
3428 %    o image_info: the image info.
3429 %
3430 %    o database: Specifies a resource database; returned from
3431 %      XrmGetStringDatabase.
3432 %
3433 %    o client_name:  Specifies the application name used to retrieve
3434 %      resource info from the X server database.
3435 %
3436 %    o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
3437 %
3438 */
3439 MagickExport void XGetResourceInfo(const ImageInfo *image_info,
3440   XrmDatabase database,const char *client_name,XResourceInfo *resource_info)
3441 {
3442   char
3443     *cwd,
3444     *resource_value;
3445
3446   /*
3447     Initialize resource info fields.
3448   */
3449   (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
3450   assert(resource_info != (XResourceInfo *) NULL);
3451   (void) ResetMagickMemory(resource_info,0,sizeof(*resource_info));
3452   resource_info->resource_database=database;
3453   resource_info->image_info=(ImageInfo *) image_info;
3454   (void) SetImageInfoProgressMonitor(resource_info->image_info,
3455     XMagickProgressMonitor,(void *) NULL);
3456   resource_info->quantize_info=CloneQuantizeInfo((QuantizeInfo *) NULL);
3457   resource_info->close_server=MagickTrue;
3458   resource_info->client_name=AcquireString(client_name);
3459   resource_value=XGetResourceClass(database,client_name,"backdrop",
3460     (char *) "False");
3461   resource_info->backdrop=IsMagickTrue(resource_value);
3462   resource_info->background_color=XGetResourceInstance(database,client_name,
3463     "background",(char *) "#d6d6d6d6d6d6");
3464   resource_info->border_color=XGetResourceInstance(database,client_name,
3465     "borderColor",BorderColor);
3466   resource_value=XGetResourceClass(database,client_name,"borderWidth",
3467     (char *) "2");
3468   resource_info->border_width=(unsigned int) StringToLong(resource_value);
3469   resource_value=XGetResourceClass(database,client_name,"colormap",
3470     (char *) "shared");
3471   resource_info->colormap=UndefinedColormap;
3472   if (LocaleCompare("private",resource_value) == 0)
3473     resource_info->colormap=PrivateColormap;
3474   if (LocaleCompare("shared",resource_value) == 0)
3475     resource_info->colormap=SharedColormap;
3476   if (resource_info->colormap == UndefinedColormap)
3477     ThrowXWindowFatalException(OptionError,"UnrecognizedColormapType",
3478       resource_value);
3479   resource_value=XGetResourceClass(database,client_name,
3480     "colorRecovery",(char *) "False");
3481   resource_info->color_recovery=IsMagickTrue(resource_value);
3482   resource_value=XGetResourceClass(database,client_name,"confirmExit",
3483     (char *) "False");
3484   resource_info->confirm_exit=IsMagickTrue(resource_value);
3485   resource_value=XGetResourceClass(database,client_name,"confirmEdit",
3486     (char *) "False");
3487   resource_info->confirm_edit=IsMagickTrue(resource_value);
3488   resource_value=XGetResourceClass(database,client_name,"delay",(char *) "1");
3489   resource_info->delay=(unsigned int) StringToLong(resource_value);
3490   resource_info->display_gamma=XGetResourceClass(database,client_name,
3491     "displayGamma",(char *) "2.2");
3492   resource_value=XGetResourceClass(database,client_name,"displayWarnings",
3493     (char *) "True");
3494   resource_info->display_warnings=IsMagickTrue(resource_value);
3495   resource_info->font=XGetResourceClass(database,client_name,"font",
3496     (char *) NULL);
3497   resource_info->font=XGetResourceClass(database,client_name,"fontList",
3498     resource_info->font);
3499   resource_info->font_name[0]=XGetResourceClass(database,client_name,"font1",
3500     (char *) "fixed");
3501   resource_info->font_name[1]=XGetResourceClass(database,client_name,"font2",
3502     (char *) "variable");
3503   resource_info->font_name[2]=XGetResourceClass(database,client_name,"font3",
3504     (char *) "5x8");
3505   resource_info->font_name[3]=XGetResourceClass(database,client_name,"font4",
3506     (char *) "6x10");
3507   resource_info->font_name[4]=XGetResourceClass(database,client_name,"font5",
3508     (char *) "7x13bold");
3509   resource_info->font_name[5]=XGetResourceClass(database,client_name,"font6",
3510     (char *) "8x13bold");
3511   resource_info->font_name[6]=XGetResourceClass(database,client_name,"font7",
3512     (char *) "9x15bold");
3513   resource_info->font_name[7]=XGetResourceClass(database,client_name,"font8",
3514     (char *) "10x20");
3515   resource_info->font_name[8]=XGetResourceClass(database,client_name,"font9",
3516     (char *) "12x24");
3517   resource_info->font_name[9]=XGetResourceClass(database,client_name,"font0",
3518     (char *) "fixed");
3519   resource_info->font_name[10]=XGetResourceClass(database,client_name,"font0",
3520     (char *) "fixed");
3521   resource_info->foreground_color=XGetResourceInstance(database,client_name,
3522     "foreground",ForegroundColor);
3523   resource_value=XGetResourceClass(database,client_name,"gammaCorrect",
3524     (char *) "True");
3525   resource_info->gamma_correct=IsMagickTrue(resource_value);
3526   resource_info->image_geometry=ConstantString(XGetResourceClass(database,
3527     client_name,"geometry",(char *) NULL));
3528   resource_value=XGetResourceClass(database,client_name,"gravity",
3529     (char *) "Center");
3530   resource_info->gravity=(GravityType) ParseMagickOption(MagickGravityOptions,
3531     MagickFalse,resource_value);
3532   cwd=getcwd(resource_info->home_directory,MaxTextExtent);
3533   resource_info->icon_geometry=XGetResourceClass(database,client_name,
3534     "iconGeometry",(char *) NULL);
3535   resource_value=XGetResourceClass(database,client_name,"iconic",
3536     (char *) "False");
3537   resource_info->iconic=IsMagickTrue(resource_value);
3538   resource_value=XGetResourceClass(database,client_name,"immutable",
3539     LocaleCompare(client_name,"PerlMagick") == 0 ? (char *) "True" :
3540     (char *) "False");
3541   resource_info->immutable=IsMagickTrue(resource_value);
3542   resource_value=XGetResourceClass(database,client_name,"magnify",
3543     (char *) "3");
3544   resource_info->magnify=(unsigned int) StringToLong(resource_value);
3545   resource_info->map_type=XGetResourceClass(database,client_name,"map",
3546     (char *) NULL);
3547   resource_info->matte_color=XGetResourceInstance(database,client_name,
3548     "mattecolor",(char *) NULL);
3549   resource_info->name=ConstantString(XGetResourceClass(database,client_name,
3550     "name",(char *) NULL));
3551   resource_info->pen_colors[0]=XGetResourceClass(database,client_name,"pen1",
3552     (char *) "black");
3553   resource_info->pen_colors[1]=XGetResourceClass(database,client_name,"pen2",
3554     (char *) "blue");
3555   resource_info->pen_colors[2]=XGetResourceClass(database,client_name,"pen3",
3556     (char *) "cyan");
3557   resource_info->pen_colors[3]=XGetResourceClass(database,client_name,"pen4",
3558     (char *) "green");
3559   resource_info->pen_colors[4]=XGetResourceClass(database,client_name,"pen5",
3560     (char *) "gray");
3561   resource_info->pen_colors[5]=XGetResourceClass(database,client_name,"pen6",
3562     (char *) "red");
3563   resource_info->pen_colors[6]=XGetResourceClass(database,client_name,"pen7",
3564     (char *) "magenta");
3565   resource_info->pen_colors[7]=XGetResourceClass(database,client_name,"pen8",
3566     (char *) "yellow");
3567   resource_info->pen_colors[8]=XGetResourceClass(database,client_name,"pen9",
3568     (char *) "white");
3569   resource_info->pen_colors[9]=XGetResourceClass(database,client_name,"pen0",
3570     (char *) "gray");
3571   resource_info->pen_colors[10]=XGetResourceClass(database,client_name,"pen0",
3572     (char *) "gray");
3573   resource_value=XGetResourceClass(database,client_name,"pause",(char *) "0");
3574   resource_info->pause=(unsigned int) StringToLong(resource_value);
3575   resource_value=XGetResourceClass(database,client_name,"quantum",(char *) "1");
3576   resource_info->quantum=StringToLong(resource_value);
3577   resource_info->text_font=XGetResourceClass(database,client_name,(char *)
3578     "font",(char *) "fixed");
3579   resource_info->text_font=XGetResourceClass(database,client_name,
3580     "textFontList",resource_info->text_font);
3581   resource_info->title=XGetResourceClass(database,client_name,"title",
3582     (char *) NULL);
3583   resource_value=XGetResourceClass(database,client_name,"undoCache",
3584     (char *) "16");
3585   resource_info->undo_cache=(unsigned int) StringToLong(resource_value);
3586   resource_value=XGetResourceClass(database,client_name,"update",
3587     (char *) "False");
3588   resource_info->update=IsMagickTrue(resource_value);
3589   resource_value=XGetResourceClass(database,client_name,"usePixmap",
3590     (char *) "True");
3591   resource_info->use_pixmap=IsMagickTrue(resource_value);
3592   resource_value=XGetResourceClass(database,client_name,"sharedMemory",
3593     (char *) "True");
3594   resource_info->use_shared_memory=IsMagickTrue(resource_value);
3595   resource_info->visual_type=XGetResourceClass(database,client_name,"visual",
3596     (char *) NULL);
3597   resource_info->window_group=XGetResourceClass(database,client_name,
3598     "windowGroup",(char *) NULL);
3599   resource_info->window_id=XGetResourceClass(database,client_name,"window",
3600     (char *) NULL);
3601   resource_info->write_filename=XGetResourceClass(database,client_name,
3602     "writeFilename",(char *) NULL);
3603 }
3604 \f
3605 /*
3606 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3607 %                                                                             %
3608 %                                                                             %
3609 %                                                                             %
3610 %   X G e t R e s o u r c e I n s t a n c e                                   %
3611 %                                                                             %
3612 %                                                                             %
3613 %                                                                             %
3614 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3615 %
3616 %  XGetResourceInstance() queries the X server for the specified resource name.
3617 %  If the resource name is not defined in the database, the supplied default
3618 %  value is returned.
3619 %
3620 %  The format of the XGetResourceInstance method is:
3621 %
3622 %      char *XGetResourceInstance(XrmDatabase database,const char *client_name,
3623 %        const char *keyword,const char *resource_default)
3624 %
3625 %  A description of each parameter follows:
3626 %
3627 %    o database: Specifies a resource database; returned from
3628 %      XrmGetStringDatabase.
3629 %
3630 %    o client_name:  Specifies the application name used to retrieve
3631 %      resource info from the X server database.
3632 %
3633 %    o keyword: Specifies the keyword of the value being retrieved.
3634 %
3635 %    o resource_default: Specifies the default value to return if the query
3636 %      fails to find the specified keyword/class.
3637 %
3638 */
3639 MagickExport char *XGetResourceInstance(XrmDatabase database,
3640   const char *client_name,const char *keyword,const char *resource_default)
3641 {
3642   char
3643     *resource_type,
3644     resource_name[MaxTextExtent];
3645
3646   Status
3647     status;
3648
3649   XrmValue
3650     resource_value;
3651
3652   if (database == (XrmDatabase) NULL)
3653     return((char *) resource_default);
3654   *resource_name='\0';
3655   if (keyword != (char *) NULL)
3656     (void) FormatMagickString(resource_name,MaxTextExtent,"%s.%s",client_name,
3657       keyword);
3658   status=XrmGetResource(database,resource_name,"ImageMagick",&resource_type,
3659     &resource_value);
3660   if (status == False)
3661     return((char *) resource_default);
3662   return(resource_value.addr);
3663 }
3664 \f
3665 /*
3666 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3667 %                                                                             %
3668 %                                                                             %
3669 %                                                                             %
3670 %   X G e t S c r e e n D e n s i t y                                         %
3671 %                                                                             %
3672 %                                                                             %
3673 %                                                                             %
3674 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3675 %
3676 %  XGetScreenDensity() returns the density of the X server screen in
3677 %  dots-per-inch.
3678 %
3679 %  The format of the XGetScreenDensity method is:
3680 %
3681 %      char *XGetScreenDensity(Display *display)
3682 %
3683 %  A description of each parameter follows:
3684 %
3685 %    o density: XGetScreenDensity() returns the density of the X screen in
3686 %      dots-per-inch.
3687 %
3688 %    o display: Specifies a connection to an X server;  returned from
3689 %      XOpenDisplay.
3690 %
3691 */
3692 MagickExport char *XGetScreenDensity(Display *display)
3693 {
3694   char
3695     density[MaxTextExtent];
3696
3697   double
3698     x_density,
3699     y_density;
3700
3701   /*
3702     Set density as determined by screen size.
3703   */
3704   x_density=((((double) DisplayWidth(display,XDefaultScreen(display)))*25.4)/
3705     ((double) DisplayWidthMM(display,XDefaultScreen(display))));
3706   y_density=((((double) DisplayHeight(display,XDefaultScreen(display)))*25.4)/
3707     ((double) DisplayHeightMM(display,XDefaultScreen(display))));
3708   (void) FormatMagickString(density,MaxTextExtent,"%gx%g",x_density,y_density);
3709   return(GetPageGeometry(density));
3710 }
3711 \f
3712 /*
3713 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3714 %                                                                             %
3715 %                                                                             %
3716 %                                                                             %
3717 +   X G e t S u b w i n d o w                                                 %
3718 %                                                                             %
3719 %                                                                             %
3720 %                                                                             %
3721 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3722 %
3723 %  XGetSubwindow() returns the subwindow of a window chosen the user with the
3724 %  pointer and a button press.
3725 %
3726 %  The format of the XGetSubwindow method is:
3727 %
3728 %      Window XGetSubwindow(Display *display,Window window,int x,int y)
3729 %
3730 %  A description of each parameter follows:
3731 %
3732 %    o subwindow: XGetSubwindow() returns NULL if no subwindow is found
3733 %      otherwise the subwindow is returned.
3734 %
3735 %    o display: Specifies a connection to an X server;  returned from
3736 %      XOpenDisplay.
3737 %
3738 %    o window: Specifies a pointer to a Window.
3739 %
3740 %    o x: the x coordinate of the pointer relative to the origin of the
3741 %      window.
3742 %
3743 %    o y: the y coordinate of the pointer relative to the origin of the
3744 %      window.
3745 %
3746 %
3747 */
3748 static Window XGetSubwindow(Display *display,Window window,int x,int y)
3749 {
3750   int
3751     x_offset,
3752     y_offset;
3753
3754   Status
3755     status;
3756
3757   Window
3758     source_window,
3759     target_window;
3760
3761   assert(display != (Display *) NULL);
3762   source_window=XRootWindow(display,XDefaultScreen(display));
3763   if (window == (Window) NULL)
3764     return(source_window);
3765   target_window=window;
3766   for ( ; ; )
3767   {
3768     status=XTranslateCoordinates(display,source_window,window,x,y,
3769       &x_offset,&y_offset,&target_window);
3770     if (status != True)
3771       break;
3772     if (target_window == (Window) NULL)
3773       break;
3774     source_window=window;
3775     window=target_window;
3776     x=x_offset;
3777     y=y_offset;
3778   }
3779   if (target_window == (Window) NULL)
3780     target_window=window;
3781   return(target_window);
3782 }
3783 \f
3784 /*
3785 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3786 %                                                                             %
3787 %                                                                             %
3788 %                                                                             %
3789 %   X G e t W i n d o w C o l o r                                             %
3790 %                                                                             %
3791 %                                                                             %
3792 %                                                                             %
3793 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3794 %
3795 %  XGetWindowColor() returns the color of a pixel interactively chosen from the
3796 %  X server.
3797 %
3798 %  The format of the XGetWindowColor method is:
3799 %
3800 %      MagickBooleanType XGetWindowColor(Display *display,XWindows *windows,
3801 %        char *name)
3802 %
3803 %  A description of each parameter follows:
3804 %
3805 %    o display: Specifies a connection to an X server;  returned from
3806 %      XOpenDisplay.
3807 %
3808 %    o windows: Specifies a pointer to a XWindows structure.
3809 %
3810 %    o name: the name of the color if found in the X Color Database is
3811 %      returned in this character string.
3812 %
3813 */
3814 MagickExport MagickBooleanType XGetWindowColor(Display *display,
3815   XWindows *windows,char *name)
3816 {
3817   int
3818     x,
3819     y;
3820
3821   PixelPacket
3822     pixel;
3823
3824   RectangleInfo
3825     crop_info;
3826
3827   Status
3828     status;
3829
3830   Window
3831     child,
3832     client_window,
3833     root_window,
3834     target_window;
3835
3836   XColor
3837     color;
3838
3839   XImage
3840     *ximage;
3841
3842   XWindowAttributes
3843     window_attributes;
3844
3845   /*
3846     Choose a pixel from the X server.
3847   */
3848   assert(display != (Display *) NULL);
3849   assert(name != (char *) NULL);
3850   (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",name);
3851   *name='\0';
3852   target_window=XSelectWindow(display,&crop_info);
3853   if (target_window == (Window) NULL)
3854     return(MagickFalse);
3855   root_window=XRootWindow(display,XDefaultScreen(display));
3856   client_window=target_window;
3857   if (target_window != root_window)
3858     {
3859       unsigned int
3860         d;
3861
3862       /*
3863         Get client window.
3864       */
3865       status=XGetGeometry(display,target_window,&root_window,&x,&x,&d,&d,&d,&d);
3866       if (status != False)
3867         {
3868           client_window=XClientWindow(display,target_window);
3869           target_window=client_window;
3870         }
3871     }
3872   /*
3873     Verify window is viewable.
3874   */
3875   status=XGetWindowAttributes(display,target_window,&window_attributes);
3876   if ((status == False) || (window_attributes.map_state != IsViewable))
3877     return(MagickFalse);
3878   /*
3879     Get window X image.
3880   */
3881   (void) XTranslateCoordinates(display,root_window,target_window,
3882     (int) crop_info.x,(int) crop_info.y,&x,&y,&child);
3883   ximage=XGetImage(display,target_window,x,y,1,1,AllPlanes,ZPixmap);
3884   if (ximage == (XImage *) NULL)
3885     return(MagickFalse);
3886   color.pixel=XGetPixel(ximage,0,0);
3887   XDestroyImage(ximage);
3888   /*
3889     Match color against the color database.
3890   */
3891   (void) XQueryColor(display,window_attributes.colormap,&color);
3892   pixel.red=ScaleShortToQuantum(color.red);
3893   pixel.green=ScaleShortToQuantum(color.green);
3894   pixel.blue=ScaleShortToQuantum(color.blue);
3895   pixel.opacity=OpaqueOpacity;
3896   (void) QueryColorname(windows->image.image,&pixel,X11Compliance,name,
3897     &windows->image.image->exception);
3898   return(MagickTrue);
3899 }
3900 \f
3901 /*
3902 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3903 %                                                                             %
3904 %                                                                             %
3905 %                                                                             %
3906 +   X G e t W i n d o w I m a g e                                             %
3907 %                                                                             %
3908 %                                                                             %
3909 %                                                                             %
3910 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3911 %
3912 %  XGetWindowImage() reads an image from the target X window and returns it.
3913 %  XGetWindowImage() optionally descends the window hierarchy and overlays the
3914 %  target image with each child image in an optimized fashion.  Any child
3915 %  window that have the same visual, colormap, and are contained by its parent
3916 %  are exempted.
3917 %
3918 %  The format of the XGetWindowImage method is:
3919 %
3920 %      Image *XGetWindowImage(Display *display,const Window window,
3921 %        const unsigned int borders,const unsigned int level)
3922 %
3923 %  A description of each parameter follows:
3924 %
3925 %    o display: Specifies a connection to an X server;  returned from
3926 %      XOpenDisplay.
3927 %
3928 %    o window: Specifies the window to obtain the image from.
3929 %
3930 %    o borders: Specifies whether borders pixels are to be saved with
3931 %      the image.
3932 %
3933 %    o level: Specifies an unsigned integer representing the level of
3934 %      decent in the window hierarchy.  This value must be zero or one on
3935 %      the initial call to XGetWindowImage.  A value of zero returns after
3936 %      one call.  A value of one causes the function to descend the window
3937 %      hierarchy and overlay the target image with each subwindow image.
3938 %
3939 %
3940 */
3941 static Image *XGetWindowImage(Display *display,const Window window,
3942   const unsigned int borders,const unsigned int level)
3943 {
3944   typedef struct _ColormapInfo
3945   {
3946     Colormap
3947       colormap;
3948
3949     XColor
3950       *colors;
3951
3952     struct _ColormapInfo
3953       *next;
3954   } ColormapInfo;
3955
3956   typedef struct _WindowInfo
3957   {
3958     Window
3959       window,
3960       parent;
3961
3962     Visual
3963       *visual;
3964
3965     Colormap
3966       colormap;
3967
3968     XSegment
3969       bounds;
3970
3971     RectangleInfo
3972       crop_info;
3973   } WindowInfo;
3974
3975   IndexPacket
3976     index;
3977
3978   int
3979     display_height,
3980     display_width,
3981     id,
3982     x_offset,
3983     y_offset;
3984
3985   RectangleInfo
3986     crop_info;
3987
3988   register IndexPacket
3989     *indexes;
3990
3991   register int
3992     i;
3993
3994   static ColormapInfo
3995     *colormap_info = (ColormapInfo *) NULL;
3996
3997   static int
3998     max_windows = 0,
3999     number_windows = 0;
4000
4001   static WindowInfo
4002     *window_info;
4003
4004   Status
4005     status;
4006
4007   Window
4008     child,
4009     root_window;
4010
4011   XWindowAttributes
4012     window_attributes;
4013
4014   /*
4015     Verify window is viewable.
4016   */
4017   (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
4018   assert(display != (Display *) NULL);
4019   status=XGetWindowAttributes(display,window,&window_attributes);
4020   if ((status == False) || (window_attributes.map_state != IsViewable))
4021     return((Image *) NULL);
4022   /*
4023     Cropping rectangle is relative to root window.
4024   */
4025   root_window=XRootWindow(display,XDefaultScreen(display));
4026   (void) XTranslateCoordinates(display,window,root_window,0,0,&x_offset,
4027     &y_offset,&child);
4028   crop_info.x=(long) x_offset;
4029   crop_info.y=(long) y_offset;
4030   crop_info.width=(unsigned long) window_attributes.width;
4031   crop_info.height=(unsigned long) window_attributes.height;
4032   if (borders != MagickFalse)
4033     {
4034       /*
4035         Include border in image.
4036       */
4037       crop_info.x-=(long) window_attributes.border_width;
4038       crop_info.y-=(long) window_attributes.border_width;
4039       crop_info.width+=(unsigned long) (window_attributes.border_width << 1);
4040       crop_info.height+=(unsigned long) (window_attributes.border_width << 1);
4041     }
4042   /*
4043     Crop to root window.
4044   */
4045   if (crop_info.x < 0)
4046     {
4047       crop_info.width+=crop_info.x;
4048       crop_info.x=0;
4049     }
4050   if (crop_info.y < 0)
4051     {
4052       crop_info.height+=crop_info.y;
4053       crop_info.y=0;
4054     }
4055   display_width=XDisplayWidth(display,XDefaultScreen(display));
4056   if ((int) (crop_info.x+crop_info.width) > display_width)
4057     crop_info.width=(unsigned long) (display_width-crop_info.x);
4058   display_height=XDisplayHeight(display,XDefaultScreen(display));
4059   if ((int) (crop_info.y+crop_info.height) > display_height)
4060     crop_info.height=(unsigned long) (display_height-crop_info.y);
4061   /*
4062     Initialize window info attributes.
4063   */
4064   if (number_windows >= max_windows)
4065     {
4066       /*
4067         Allocate or resize window info buffer.
4068       */
4069       max_windows+=1024;
4070       if (window_info == (WindowInfo *) NULL)
4071         window_info=(WindowInfo *) AcquireQuantumMemory((size_t) max_windows,
4072           sizeof(*window_info));
4073       else
4074         window_info=(WindowInfo *) ResizeQuantumMemory(window_info,(size_t)
4075           max_windows,sizeof(*window_info));
4076     }
4077   if (window_info == (WindowInfo *) NULL)
4078     {
4079       ThrowXWindowFatalException(ResourceLimitError,
4080         "MemoryAllocationFailed","...");
4081       return((Image *) NULL);
4082     }
4083   id=number_windows++;
4084   window_info[id].window=window;
4085   window_info[id].visual=window_attributes.visual;
4086   window_info[id].colormap=window_attributes.colormap;
4087   window_info[id].bounds.x1=(short) crop_info.x;
4088   window_info[id].bounds.y1=(short) crop_info.y;
4089   window_info[id].bounds.x2=(short) (crop_info.x+(int) crop_info.width-1);
4090   window_info[id].bounds.y2=(short) (crop_info.y+(int) crop_info.height-1);
4091   crop_info.x-=x_offset;
4092   crop_info.y-=y_offset;
4093   window_info[id].crop_info=crop_info;
4094   if (level != 0)
4095     {
4096       unsigned int
4097         number_children;
4098
4099       Window
4100         *children;
4101
4102       /*
4103         Descend the window hierarchy.
4104       */
4105       status=XQueryTree(display,window,&root_window,&window_info[id].parent,
4106         &children,&number_children);
4107       for (i=0; i < id; i++)
4108         if ((window_info[i].window == window_info[id].parent) &&
4109             (window_info[i].visual == window_info[id].visual) &&
4110             (window_info[i].colormap == window_info[id].colormap))
4111           {
4112             if ((window_info[id].bounds.x1 <= window_info[i].bounds.x1) ||
4113                 (window_info[id].bounds.x1 >= window_info[i].bounds.x2) ||
4114                 (window_info[id].bounds.y1 <= window_info[i].bounds.y1) ||
4115                 (window_info[id].bounds.y1 >= window_info[i].bounds.y2))
4116               {
4117                 /*
4118                   Eliminate windows not circumscribed by their parent.
4119                 */
4120                 number_windows--;
4121                 break;
4122               }
4123           }
4124       if ((status == True) && (number_children != 0))
4125         {
4126           for (i=0; i < (int) number_children; i++)
4127             (void) XGetWindowImage(display,children[i],MagickFalse,level+1);
4128           (void) XFree((void *) children);
4129         }
4130     }
4131   if (level <= 1)
4132     {
4133       ColormapInfo
4134         *next;
4135
4136       ExceptionInfo
4137         *exception;
4138
4139       Image
4140         *composite_image,
4141         *image;
4142
4143       int
4144         y;
4145
4146       MagickBooleanType
4147         import;
4148
4149       register int
4150         j,
4151         x;
4152
4153       register PixelPacket
4154         *restrict q;
4155
4156       register unsigned long
4157         pixel;
4158
4159       unsigned int
4160         number_colors;
4161
4162       XColor
4163         *colors;
4164
4165       XImage
4166         *ximage;
4167
4168       /*
4169         Get X image for each window in the list.
4170       */
4171       image=NewImageList();
4172       for (id=0; id < number_windows; id++)
4173       {
4174         /*
4175           Does target window intersect top level window?
4176         */
4177         import=
4178           ((window_info[id].bounds.x2 >= window_info[0].bounds.x1) &&
4179            (window_info[id].bounds.x1 <= window_info[0].bounds.x2) &&
4180            (window_info[id].bounds.y2 >= window_info[0].bounds.y1) &&
4181            (window_info[id].bounds.y1 <= window_info[0].bounds.y2)) ?
4182           MagickTrue : MagickFalse;
4183         /*
4184           Is target window contained by another window with the same colormap?
4185         */
4186         for (j=0; j < id; j++)
4187           if ((window_info[id].visual == window_info[j].visual) &&
4188               (window_info[id].colormap == window_info[j].colormap))
4189             {
4190               if ((window_info[id].bounds.x1 <= window_info[j].bounds.x1) ||
4191                   (window_info[id].bounds.x1 >= window_info[j].bounds.x2) ||
4192                   (window_info[id].bounds.y1 <= window_info[j].bounds.y1) ||
4193                   (window_info[id].bounds.y1 >= window_info[j].bounds.y2))
4194                   import=MagickFalse;
4195             }
4196           else
4197             if ((window_info[id].visual != window_info[j].visual) ||
4198                 (window_info[id].colormap != window_info[j].colormap))
4199               {
4200                 if ((window_info[id].bounds.x2 > window_info[j].bounds.x1) &&
4201                     (window_info[id].bounds.x1 < window_info[j].bounds.x2) &&
4202                     (window_info[id].bounds.y2 > window_info[j].bounds.y1) &&
4203                     (window_info[id].bounds.y1 < window_info[j].bounds.y2))
4204                   import=MagickTrue;
4205               }
4206         if (import == MagickFalse)
4207           continue;
4208         /*
4209           Get X image.
4210         */
4211         ximage=XGetImage(display,window_info[id].window,(int)
4212           window_info[id].crop_info.x,(int) window_info[id].crop_info.y,
4213           (unsigned int) window_info[id].crop_info.width,(unsigned int)
4214           window_info[id].crop_info.height,AllPlanes,ZPixmap);
4215         if (ximage == (XImage *) NULL)
4216           continue;
4217         /*
4218           Initialize window colormap.
4219         */
4220         number_colors=0;
4221         colors=(XColor *) NULL;
4222         if (window_info[id].colormap != (Colormap) NULL)
4223           {
4224             ColormapInfo
4225               *p;
4226
4227             /*
4228               Search colormap list for window colormap.
4229             */
4230             number_colors=(unsigned int) window_info[id].visual->map_entries;
4231             for (p=colormap_info; p != (ColormapInfo *) NULL; p=p->next)
4232               if (p->colormap == window_info[id].colormap)
4233                 break;
4234             if (p == (ColormapInfo *) NULL)
4235               {
4236                 /*
4237                   Get the window colormap.
4238                 */
4239                 colors=(XColor *) AcquireQuantumMemory(number_colors,
4240                   sizeof(*colors));
4241                 if (colors == (XColor *) NULL)
4242                   {
4243                     XDestroyImage(ximage);
4244                     return((Image *) NULL);
4245                   }
4246                 if ((window_info[id].visual->klass != DirectColor) &&
4247                     (window_info[id].visual->klass != TrueColor))
4248                   for (i=0; i < (int) number_colors; i++)
4249                   {
4250                     colors[i].pixel=(unsigned long) i;
4251                     colors[i].pad='\0';
4252                   }
4253                 else
4254                   {
4255                     unsigned long
4256                       blue,
4257                       blue_bit,
4258                       green,
4259                       green_bit,
4260                       red,
4261                       red_bit;
4262
4263                     /*
4264                       DirectColor or TrueColor visual.
4265                     */
4266                     red=0;
4267                     green=0;
4268                     blue=0;
4269                     red_bit=window_info[id].visual->red_mask &
4270                       (~(window_info[id].visual->red_mask)+1);
4271                     green_bit=window_info[id].visual->green_mask &
4272                       (~(window_info[id].visual->green_mask)+1);
4273                     blue_bit=window_info[id].visual->blue_mask &
4274                       (~(window_info[id].visual->blue_mask)+1);
4275                     for (i=0; i < (int) number_colors; i++)
4276                     {
4277                       colors[i].pixel=red | green | blue;
4278                       colors[i].pad='\0';
4279                       red+=red_bit;
4280                       if (red > window_info[id].visual->red_mask)
4281                         red=0;
4282                       green+=green_bit;
4283                       if (green > window_info[id].visual->green_mask)
4284                         green=0;
4285                       blue+=blue_bit;
4286                       if (blue > window_info[id].visual->blue_mask)
4287                         blue=0;
4288                     }
4289                   }
4290                 (void) XQueryColors(display,window_info[id].colormap,colors,
4291                   (int) number_colors);
4292                 /*
4293                   Append colormap to colormap list.
4294                 */
4295                 p=(ColormapInfo *) AcquireAlignedMemory(1,sizeof(*p));
4296                 if (p == (ColormapInfo *) NULL)
4297                   return((Image *) NULL);
4298                 p->colormap=window_info[id].colormap;
4299                 p->colors=colors;
4300                 p->next=colormap_info;
4301                 colormap_info=p;
4302               }
4303             colors=p->colors;
4304           }
4305         /*
4306           Allocate image structure.
4307         */
4308         composite_image=AcquireImage((ImageInfo *) NULL);
4309         if (composite_image == (Image *) NULL)
4310           {
4311             XDestroyImage(ximage);
4312             return((Image *) NULL);
4313           }
4314         /*
4315           Convert X image to MIFF format.
4316         */
4317         if ((window_info[id].visual->klass != TrueColor) &&
4318             (window_info[id].visual->klass != DirectColor))
4319           composite_image->storage_class=PseudoClass;
4320         composite_image->columns=(unsigned long) ximage->width;
4321         composite_image->rows=(unsigned long) ximage->height;
4322         exception=(&composite_image->exception);
4323         switch (composite_image->storage_class)
4324         {
4325           case DirectClass:
4326           default:
4327           {
4328             register unsigned long
4329               color,
4330               index;
4331
4332             unsigned long
4333               blue_mask,
4334               blue_shift,
4335               green_mask,
4336               green_shift,
4337               red_mask,
4338               red_shift;
4339
4340             /*
4341               Determine shift and mask for red, green, and blue.
4342             */
4343             red_mask=window_info[id].visual->red_mask;
4344             red_shift=0;
4345             while ((red_mask != 0) && ((red_mask & 0x01) == 0))
4346             {
4347               red_mask>>=1;
4348               red_shift++;
4349             }
4350             green_mask=window_info[id].visual->green_mask;
4351             green_shift=0;
4352             while ((green_mask != 0) && ((green_mask & 0x01) == 0))
4353             {
4354               green_mask>>=1;
4355               green_shift++;
4356             }
4357             blue_mask=window_info[id].visual->blue_mask;
4358             blue_shift=0;
4359             while ((blue_mask != 0) && ((blue_mask & 0x01) == 0))
4360             {
4361               blue_mask>>=1;
4362               blue_shift++;
4363             }
4364             /*
4365               Convert X image to DirectClass packets.
4366             */
4367             if ((number_colors != 0) &&
4368                 (window_info[id].visual->klass == DirectColor))
4369               for (y=0; y < (int) composite_image->rows; y++)
4370               {
4371                 q=QueueAuthenticPixels(composite_image,0,y,
4372                   composite_image->columns,1,exception);
4373                 if (q == (PixelPacket *) NULL)
4374                   break;
4375                 for (x=0; x < (int) composite_image->columns; x++)
4376                 {
4377                   pixel=XGetPixel(ximage,x,y);
4378                   index=(pixel >> red_shift) & red_mask;
4379                   q->red=ScaleShortToQuantum(colors[index].red);
4380                   index=(pixel >> green_shift) & green_mask;
4381                   q->green=ScaleShortToQuantum(colors[index].green);
4382                   index=(pixel >> blue_shift) & blue_mask;
4383                   q->blue=ScaleShortToQuantum(colors[index].blue);
4384                   q++;
4385                 }
4386                 if (SyncAuthenticPixels(composite_image,exception) == MagickFalse)
4387                   break;
4388               }
4389             else
4390               for (y=0; y < (int) composite_image->rows; y++)
4391               {
4392                 q=QueueAuthenticPixels(composite_image,0,y,
4393                   composite_image->columns,1,exception);
4394                 if (q == (PixelPacket *) NULL)
4395                   break;
4396                 for (x=0; x < (int) composite_image->columns; x++)
4397                 {
4398                   pixel=XGetPixel(ximage,x,y);
4399                   color=(pixel >> red_shift) & red_mask;
4400                   color=(65535UL*color)/red_mask;
4401                   q->red=ScaleShortToQuantum((unsigned short) color);
4402                   color=(pixel >> green_shift) & green_mask;
4403                   color=(65535UL*color)/green_mask;
4404                   q->green=ScaleShortToQuantum((unsigned short) color);
4405                   color=(pixel >> blue_shift) & blue_mask;
4406                   color=(65535UL*color)/blue_mask;
4407                   q->blue=ScaleShortToQuantum((unsigned short) color);
4408                   q++;
4409                 }
4410                 if (SyncAuthenticPixels(composite_image,exception) == MagickFalse)
4411                   break;
4412               }
4413             break;
4414           }
4415           case PseudoClass:
4416           {
4417             /*
4418               Create colormap.
4419             */
4420             if (AcquireImageColormap(composite_image,number_colors) == MagickFalse)
4421               {
4422                 XDestroyImage(ximage);
4423                 composite_image=DestroyImage(composite_image);
4424                 return((Image *) NULL);
4425               }
4426             for (i=0; i < (int) composite_image->colors; i++)
4427             {
4428               composite_image->colormap[colors[i].pixel].red=
4429                 ScaleShortToQuantum(colors[i].red);
4430               composite_image->colormap[colors[i].pixel].green=
4431                 ScaleShortToQuantum(colors[i].green);
4432               composite_image->colormap[colors[i].pixel].blue=
4433                 ScaleShortToQuantum(colors[i].blue);
4434             }
4435             /*
4436               Convert X image to PseudoClass packets.
4437             */
4438             for (y=0; y < (int) composite_image->rows; y++)
4439             {
4440               q=QueueAuthenticPixels(composite_image,0,y,composite_image->columns,1,exception);
4441               if (q == (PixelPacket *) NULL)
4442                 break;
4443               indexes=GetAuthenticIndexQueue(composite_image);
4444               for (x=0; x < (int) composite_image->columns; x++)
4445               {
4446                 index=(IndexPacket) XGetPixel(ximage,x,y);
4447                 indexes[x]=index;
4448                 *q++=composite_image->colormap[(long) index];
4449               }
4450               if (SyncAuthenticPixels(composite_image,exception) == MagickFalse)
4451                 break;
4452             }
4453             break;
4454           }
4455         }
4456         XDestroyImage(ximage);
4457         if (image == (Image *) NULL)
4458           {
4459             image=composite_image;
4460             continue;
4461           }
4462         /*
4463           Composite any children in back-to-front order.
4464         */
4465         (void) XTranslateCoordinates(display,window_info[id].window,window,0,0,
4466           &x_offset,&y_offset,&child);
4467         x_offset-=(int) crop_info.x;
4468         if (x_offset < 0)
4469           x_offset=0;
4470         y_offset-=(int) crop_info.y;
4471         if (y_offset < 0)
4472           y_offset=0;
4473         (void) CompositeImage(image,CopyCompositeOp,composite_image,x_offset,
4474           y_offset);
4475       }
4476       /*
4477         Relinquish resources.
4478       */
4479       while (colormap_info != (ColormapInfo *) NULL)
4480       {
4481         next=colormap_info->next;
4482         colormap_info->colors=(XColor *)
4483           RelinquishMagickMemory(colormap_info->colors);
4484         colormap_info=(ColormapInfo *) RelinquishMagickMemory(colormap_info);
4485         colormap_info=next;
4486       }
4487       /*
4488         Relinquish resources and restore initial state.
4489       */
4490       window_info=(WindowInfo *) RelinquishMagickMemory(window_info);
4491       max_windows=0;
4492       number_windows=0;
4493       colormap_info=(ColormapInfo *) NULL;
4494       return(image);
4495     }
4496   return((Image *) NULL);
4497 }
4498 \f
4499 /*
4500 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4501 %                                                                             %
4502 %                                                                             %
4503 %                                                                             %
4504 %   X G e t W i n d o w I n f o                                               %
4505 %                                                                             %
4506 %                                                                             %
4507 %                                                                             %
4508 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4509 %
4510 %  XGetWindowInfo() initializes the XWindowInfo structure.
4511 %
4512 %  The format of the XGetWindowInfo method is:
4513 %
4514 %      void XGetWindowInfo(Display *display,XVisualInfo *visual_info,
4515 %        XStandardColormap *map_info,XPixelInfo *pixel,XFontStruct *font_info,
4516 %        XResourceInfo *resource_info,XWindowInfo *window)
4517 %        resource_info,window)
4518 %
4519 %  A description of each parameter follows:
4520 %
4521 %    o display: Specifies a connection to an X server; returned from
4522 %      XOpenDisplay.
4523 %
4524 %    o visual_info: Specifies a pointer to a X11 XVisualInfo structure;
4525 %      returned from XGetVisualInfo.
4526 %
4527 %    o map_info: If map_type is specified, this structure is initialized
4528 %      with info from the Standard Colormap.
4529 %
4530 %    o pixel: Specifies a pointer to a XPixelInfo structure.
4531 %
4532 %    o font_info: Specifies a pointer to a XFontStruct structure.
4533 %
4534 %    o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
4535 %
4536 */
4537 MagickExport void XGetWindowInfo(Display *display,XVisualInfo *visual_info,
4538   XStandardColormap *map_info,XPixelInfo *pixel,XFontStruct *font_info,
4539   XResourceInfo *resource_info,XWindowInfo *window)
4540 {
4541   /*
4542     Initialize window info.
4543   */
4544   (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
4545   assert(display != (Display *) NULL);
4546   assert(visual_info != (XVisualInfo *) NULL);
4547   assert(map_info != (XStandardColormap *) NULL);
4548   assert(pixel != (XPixelInfo *) NULL);
4549   assert(resource_info != (XResourceInfo *) NULL);
4550   assert(window != (XWindowInfo *) NULL);
4551   if (window->id != (Window) NULL)
4552     {
4553       if (window->cursor != (Cursor) NULL)
4554         (void) XFreeCursor(display,window->cursor);
4555       if (window->busy_cursor != (Cursor) NULL)
4556         (void) XFreeCursor(display,window->busy_cursor);
4557       if (window->highlight_stipple != (Pixmap) NULL)
4558         (void) XFreePixmap(display,window->highlight_stipple);
4559       if (window->shadow_stipple != (Pixmap) NULL)
4560         (void) XFreePixmap(display,window->shadow_stipple);
4561       if (window->name == (char *) NULL)
4562         window->name=AcquireString("");
4563       if (window->icon_name == (char *) NULL)
4564         window->icon_name=AcquireString("");
4565     }
4566   else
4567     {
4568       /*
4569         Initialize these attributes just once.
4570       */
4571       window->id=(Window) NULL;
4572       if (window->name == (char *) NULL)
4573         window->name=AcquireString("");
4574       if (window->icon_name == (char *) NULL)
4575         window->icon_name=AcquireString("");
4576       window->x=XDisplayWidth(display,visual_info->screen) >> 1;
4577       window->y=XDisplayWidth(display,visual_info->screen) >> 1;
4578       window->ximage=(XImage *) NULL;
4579       window->matte_image=(XImage *) NULL;
4580       window->pixmap=(Pixmap) NULL;
4581       window->matte_pixmap=(Pixmap) NULL;
4582       window->mapped=MagickFalse;
4583       window->stasis=MagickFalse;
4584       window->shared_memory=MagickTrue;
4585       window->segment_info=(void *) NULL;
4586 #if defined(MAGICKCORE_HAVE_SHARED_MEMORY)
4587       {
4588         XShmSegmentInfo
4589           *segment_info;
4590
4591         if (window->segment_info == (void *) NULL)
4592           window->segment_info=AcquireQuantumMemory(2,sizeof(*segment_info));
4593         segment_info=(XShmSegmentInfo *) window->segment_info;
4594         segment_info[0].shmid=(-1);
4595         segment_info[0].shmaddr=(char *) NULL;
4596         segment_info[1].shmid=(-1);
4597         segment_info[1].shmaddr=(char *) NULL;
4598       }
4599 #endif
4600     }
4601   /*
4602     Initialize these attributes every time function is called.
4603   */
4604   window->screen=visual_info->screen;
4605   window->root=XRootWindow(display,visual_info->screen);
4606   window->visual=visual_info->visual;
4607   window->storage_class=(unsigned int) visual_info->klass;
4608   window->depth=(unsigned int) visual_info->depth;
4609   window->visual_info=visual_info;
4610   window->map_info=map_info;
4611   window->pixel_info=pixel;
4612   window->font_info=font_info;
4613   window->cursor=XCreateFontCursor(display,XC_left_ptr);
4614   window->busy_cursor=XCreateFontCursor(display,XC_watch);
4615   window->geometry=(char *) NULL;
4616   window->icon_geometry=(char *) NULL;
4617   if (resource_info->icon_geometry != (char *) NULL)
4618     (void) CloneString(&window->icon_geometry,resource_info->icon_geometry);
4619   window->crop_geometry=(char *) NULL;
4620   window->flags=(unsigned long) PSize;
4621   window->width=1;
4622   window->height=1;
4623   window->min_width=1;
4624   window->min_height=1;
4625   window->width_inc=1;
4626   window->height_inc=1;
4627   window->border_width=resource_info->border_width;
4628   window->annotate_context=pixel->annotate_context;
4629   window->highlight_context=pixel->highlight_context;
4630   window->widget_context=pixel->widget_context;
4631   window->shadow_stipple=(Pixmap) NULL;
4632   window->highlight_stipple=(Pixmap) NULL;
4633   window->use_pixmap=MagickTrue;
4634   window->immutable=MagickFalse;
4635   window->shape=MagickFalse;
4636   window->data=0;
4637   window->mask=(unsigned long) (CWBackingStore | CWBackPixel | CWBackPixmap |
4638     CWBitGravity | CWBorderPixel | CWColormap | CWCursor | CWDontPropagate |
4639     CWEventMask | CWOverrideRedirect | CWSaveUnder | CWWinGravity);
4640   window->attributes.background_pixel=pixel->background_color.pixel;
4641   window->attributes.background_pixmap=(Pixmap) NULL;
4642   window->attributes.bit_gravity=ForgetGravity;
4643   window->attributes.backing_store=WhenMapped;
4644   window->attributes.save_under=MagickTrue;
4645   window->attributes.border_pixel=pixel->border_color.pixel;
4646   window->attributes.colormap=map_info->colormap;
4647   window->attributes.cursor=window->cursor;
4648   window->attributes.do_not_propagate_mask=NoEventMask;
4649   window->attributes.event_mask=NoEventMask;
4650   window->attributes.override_redirect=MagickFalse;
4651   window->attributes.win_gravity=NorthWestGravity;
4652   window->orphan=MagickFalse;
4653 }
4654 \f
4655 /*
4656 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4657 %                                                                             %
4658 %                                                                             %
4659 %                                                                             %
4660 %   X H i g h l i g h t E l l i p s e                                         %
4661 %                                                                             %
4662 %                                                                             %
4663 %                                                                             %
4664 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4665 %
4666 %  XHighlightEllipse() puts a border on the X server around a region defined by
4667 %  highlight_info.
4668 %
4669 %  The format of the XHighlightEllipse method is:
4670 %
4671 %      void XHighlightEllipse(Display *display,Window window,
4672 %        GC annotate_context,const RectangleInfo *highlight_info)
4673 %
4674 %  A description of each parameter follows:
4675 %
4676 %    o display: Specifies a connection to an X server; returned from
4677 %      XOpenDisplay.
4678 %
4679 %    o window: Specifies a pointer to a Window structure.
4680 %
4681 %    o annotate_context: Specifies a pointer to a GC structure.
4682 %
4683 %    o highlight_info: Specifies a pointer to a RectangleInfo structure.  It
4684 %      contains the extents of any highlighting rectangle.
4685 %
4686 */
4687 MagickExport void XHighlightEllipse(Display *display,Window window,
4688   GC annotate_context,const RectangleInfo *highlight_info)
4689 {
4690   (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
4691   assert(display != (Display *) NULL);
4692   assert(window != (Window) NULL);
4693   assert(annotate_context != (GC) NULL);
4694   assert(highlight_info != (RectangleInfo *) NULL);
4695   if ((highlight_info->width < 4) || (highlight_info->height < 4))
4696     return;
4697   (void) XDrawArc(display,window,annotate_context,(int) highlight_info->x,
4698     (int) highlight_info->y,(unsigned int) highlight_info->width-1,
4699     (unsigned int) highlight_info->height-1,0,360*64);
4700   (void) XDrawArc(display,window,annotate_context,(int) highlight_info->x+1,
4701     (int) highlight_info->y+1,(unsigned int) highlight_info->width-3,
4702     (unsigned int) highlight_info->height-3,0,360*64);
4703 }
4704 \f
4705 /*
4706 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4707 %                                                                             %
4708 %                                                                             %
4709 %                                                                             %
4710 %   X H i g h l i g h t L i n e                                               %
4711 %                                                                             %
4712 %                                                                             %
4713 %                                                                             %
4714 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4715 %
4716 %  XHighlightLine() puts a border on the X server around a region defined by
4717 %  highlight_info.
4718 %
4719 %  The format of the XHighlightLine method is:
4720 %
4721 %      void XHighlightLine(Display *display,Window window,GC annotate_context,
4722 %        const XSegment *highlight_info)
4723 %
4724 %  A description of each parameter follows:
4725 %
4726 %    o display: Specifies a connection to an X server; returned from
4727 %      XOpenDisplay.
4728 %
4729 %    o window: Specifies a pointer to a Window structure.
4730 %
4731 %    o annotate_context: Specifies a pointer to a GC structure.
4732 %
4733 %    o highlight_info: Specifies a pointer to a RectangleInfo structure.  It
4734 %      contains the extents of any highlighting rectangle.
4735 %
4736 */
4737 MagickExport void XHighlightLine(Display *display,Window window,
4738   GC annotate_context,const XSegment *highlight_info)
4739 {
4740   (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
4741   assert(display != (Display *) NULL);
4742   assert(window != (Window) NULL);
4743   assert(annotate_context != (GC) NULL);
4744   assert(highlight_info != (XSegment *) NULL);
4745   (void) XDrawLine(display,window,annotate_context,highlight_info->x1,
4746     highlight_info->y1,highlight_info->x2,highlight_info->y2);
4747 }
4748 \f
4749 /*
4750 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4751 %                                                                             %
4752 %                                                                             %
4753 %                                                                             %
4754 %   X H i g h l i g h t R e c t a n g l e                                     %
4755 %                                                                             %
4756 %                                                                             %
4757 %                                                                             %
4758 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4759 %
4760 %  XHighlightRectangle() puts a border on the X server around a region defined
4761 %  by highlight_info.
4762 %
4763 %  The format of the XHighlightRectangle method is:
4764 %
4765 %      void XHighlightRectangle(Display *display,Window window,
4766 %        GC annotate_context,const RectangleInfo *highlight_info)
4767 %
4768 %  A description of each parameter follows:
4769 %
4770 %    o display: Specifies a connection to an X server; returned from
4771 %      XOpenDisplay.
4772 %
4773 %    o window: Specifies a pointer to a Window structure.
4774 %
4775 %    o annotate_context: Specifies a pointer to a GC structure.
4776 %
4777 %    o highlight_info: Specifies a pointer to a RectangleInfo structure.  It
4778 %      contains the extents of any highlighting rectangle.
4779 %
4780 */
4781 MagickExport void XHighlightRectangle(Display *display,Window window,
4782   GC annotate_context,const RectangleInfo *highlight_info)
4783 {
4784   assert(display != (Display *) NULL);
4785   (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
4786   assert(window != (Window) NULL);
4787   assert(annotate_context != (GC) NULL);
4788   assert(highlight_info != (RectangleInfo *) NULL);
4789   if ((highlight_info->width < 4) || (highlight_info->height < 4))
4790     return;
4791   (void) XDrawRectangle(display,window,annotate_context,(int) highlight_info->x,
4792     (int) highlight_info->y,(unsigned int) highlight_info->width-1,
4793     (unsigned int) highlight_info->height-1);
4794   (void) XDrawRectangle(display,window,annotate_context,(int) highlight_info->x+
4795     1,(int) highlight_info->y+1,(unsigned int) highlight_info->width-3,
4796     (unsigned int) highlight_info->height-3);
4797 }
4798 \f
4799 /*
4800 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4801 %                                                                             %
4802 %                                                                             %
4803 %                                                                             %
4804 %   X I m p o r t I m a g e                                                   %
4805 %                                                                             %
4806 %                                                                             %
4807 %                                                                             %
4808 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4809 %
4810 %  XImportImage() reads an image from an X window.
4811 %
4812 %  The format of the XImportImage method is:
4813 %
4814 %      Image *XImportImage(const ImageInfo *image_info,XImportInfo *ximage_info)
4815 %
4816 %  A description of each parameter follows:
4817 %
4818 %    o image_info: the image info.
4819 %
4820 %    o ximage_info: Specifies a pointer to an XImportInfo structure.
4821 %
4822 */
4823 MagickExport Image *XImportImage(const ImageInfo *image_info,
4824   XImportInfo *ximage_info)
4825 {
4826   Colormap
4827     *colormaps;
4828
4829   Display
4830     *display;
4831
4832   Image
4833     *image;
4834
4835   int
4836     number_colormaps,
4837     number_windows,
4838     x;
4839
4840   RectangleInfo
4841     crop_info;
4842
4843   Status
4844     status;
4845
4846   Window
4847     *children,
4848     client,
4849     prior_target,
4850     root,
4851     target;
4852
4853   XTextProperty
4854     window_name;
4855
4856   /*
4857     Open X server connection.
4858   */
4859   assert(image_info != (const ImageInfo *) NULL);
4860   assert(image_info->signature == MagickSignature);
4861   if (image_info->debug != MagickFalse)
4862     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
4863       image_info->filename);
4864   assert(ximage_info != (XImportInfo *) NULL);
4865   display=XOpenDisplay(image_info->server_name);
4866   if (display == (Display *) NULL)
4867     {
4868       ThrowXWindowFatalException(XServerError,"UnableToOpenXServer",
4869         XDisplayName(image_info->server_name));
4870       return((Image *) NULL);
4871     }
4872   /*
4873     Set our forgiving exception handler.
4874   */
4875   (void) XSetErrorHandler(XError);
4876   /*
4877     Select target window.
4878   */
4879   crop_info.x=0;
4880   crop_info.y=0;
4881   crop_info.width=0;
4882   crop_info.height=0;
4883   root=XRootWindow(display,XDefaultScreen(display));
4884   target=(Window) NULL;
4885   if ((image_info->filename != (char *) NULL) &&
4886       (*image_info->filename != '\0'))
4887     {
4888       if (LocaleCompare(image_info->filename,"root") == 0)
4889         target=root;
4890       else
4891         {
4892           /*
4893             Select window by ID or name.
4894           */
4895           if (isdigit((unsigned char) *image_info->filename) != 0)
4896             target=XWindowByID(display,root,(Window)
4897               strtol(image_info->filename,(char **) NULL,0));
4898           if (target == (Window) NULL)
4899             target=XWindowByName(display,root,image_info->filename);
4900           if (target == (Window) NULL)
4901             ThrowXWindowFatalException(XServerError,
4902               "NoWindowWithSpecifiedIDExists",image_info->filename);
4903         }
4904     }
4905   /*
4906     If target window is not defined, interactively select one.
4907   */
4908   prior_target=target;
4909   if (target == (Window) NULL)
4910     target=XSelectWindow(display,&crop_info);
4911   if (target == (Window) NULL)
4912     ThrowXWindowFatalException(XServerError,"UnableToReadXWindowImage",
4913       image_info->filename);
4914   client=target;   /* obsolete */
4915   if (target != root)
4916     {
4917       unsigned int
4918         d;
4919
4920       status=XGetGeometry(display,target,&root,&x,&x,&d,&d,&d,&d);
4921       if (status != False)
4922         {
4923           for ( ; ; )
4924           {
4925             Window
4926               parent;
4927
4928             /*
4929               Find window manager frame.
4930             */
4931             status=XQueryTree(display,target,&root,&parent,&children,&d);
4932             if ((status != False) && (children != (Window *) NULL))
4933               (void) XFree((char *) children);
4934             if ((status == False) || (parent == (Window) NULL) ||
4935                 (parent == root))
4936               break;
4937             target=parent;
4938           }
4939           /*
4940             Get client window.
4941           */
4942           client=XClientWindow(display,target);
4943           if (ximage_info->frame == MagickFalse)
4944             target=client;
4945           if ((ximage_info->frame == MagickFalse) &&
4946               (prior_target != MagickFalse))
4947             target=prior_target;
4948           XDelay(display,SuspendTime << 4);
4949         }
4950     }
4951   if (ximage_info->screen)
4952     {
4953       int
4954         y;
4955
4956       Window
4957         child;
4958
4959       XWindowAttributes
4960         window_attributes;
4961
4962       /*
4963         Obtain window image directly from screen.
4964       */
4965       status=XGetWindowAttributes(display,target,&window_attributes);
4966       if (status == False)
4967         {
4968           ThrowXWindowFatalException(XServerError,
4969             "UnableToReadXWindowAttributes",image_info->filename);
4970           (void) XCloseDisplay(display);
4971           return((Image *) NULL);
4972         }
4973       (void) XTranslateCoordinates(display,target,root,0,0,&x,&y,&child);
4974       crop_info.x=x;
4975       crop_info.y=y;
4976       crop_info.width=(unsigned long) window_attributes.width;
4977       crop_info.height=(unsigned long) window_attributes.height;
4978       if (ximage_info->borders)
4979         {
4980           /*
4981             Include border in image.
4982           */
4983           crop_info.x-=window_attributes.border_width;
4984           crop_info.y-=window_attributes.border_width;
4985           crop_info.width+=window_attributes.border_width << 1;
4986           crop_info.height+=window_attributes.border_width << 1;
4987         }
4988       target=root;
4989     }
4990   /*
4991     If WM_COLORMAP_WINDOWS property is set or multiple colormaps, descend.
4992   */
4993   number_windows=0;
4994   status=XGetWMColormapWindows(display,target,&children,&number_windows);
4995   if ((status == True) && (number_windows > 0))
4996     {
4997       ximage_info->descend=MagickTrue;
4998       (void) XFree ((char *) children);
4999     }
5000   colormaps=XListInstalledColormaps(display,target,&number_colormaps);
5001   if (number_colormaps > 0)
5002     {
5003       if (number_colormaps > 1)
5004         ximage_info->descend=MagickTrue;
5005       (void) XFree((char *) colormaps);
5006     }
5007   /*
5008     Alert the user not to alter the screen.
5009   */
5010   if (ximage_info->silent == MagickFalse)
5011     (void) XBell(display,0);
5012   /*
5013     Get image by window id.
5014   */
5015   (void) XGrabServer(display);
5016   image=XGetWindowImage(display,target,ximage_info->borders,
5017     ximage_info->descend ? 1U : 0U);
5018   (void) XUngrabServer(display);
5019   if (image == (Image *) NULL)
5020     ThrowXWindowFatalException(XServerError,"UnableToReadXWindowImage",
5021       image_info->filename)
5022   else
5023     {
5024       (void) CopyMagickString(image->filename,image_info->filename,
5025         MaxTextExtent);
5026       if ((crop_info.width != 0) && (crop_info.height != 0))
5027         {
5028           Image
5029             *clone_image,
5030             *crop_image;
5031
5032           /*
5033             Crop image as defined by the cropping rectangle.
5034           */
5035           clone_image=CloneImage(image,0,0,MagickTrue,&image->exception);
5036           if (clone_image != (Image *) NULL)
5037             {
5038               crop_image=CropImage(clone_image,&crop_info,&image->exception);
5039               if (crop_image != (Image *) NULL)
5040                 {
5041                   image=DestroyImage(image);
5042                   image=crop_image;
5043                 }
5044             }
5045         }
5046       status=XGetWMName(display,target,&window_name);
5047       if (status == True)
5048         {
5049           if ((image_info->filename != (char *) NULL) &&
5050               (*image_info->filename == '\0'))
5051             (void) CopyMagickString(image->filename,(char *) window_name.value,
5052               (size_t) window_name.nitems+1);
5053           (void) XFree((void *) window_name.value);
5054         }
5055     }
5056   if (ximage_info->silent == MagickFalse)
5057     {
5058       /*
5059         Alert the user we're done.
5060       */
5061       (void) XBell(display,0);
5062       (void) XBell(display,0);
5063     }
5064   (void) XCloseDisplay(display);
5065   return(image);
5066 }
5067 \f
5068 /*
5069 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5070 %                                                                             %
5071 %                                                                             %
5072 %                                                                             %
5073 %   X I n i t i a l i z e W i n d o w s                                       %
5074 %                                                                             %
5075 %                                                                             %
5076 %                                                                             %
5077 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5078 %
5079 %  XInitializeWindows() initializes the XWindows structure.
5080 %
5081 %  The format of the XInitializeWindows method is:
5082 %
5083 %      XWindows *XInitializeWindows(Display *display,
5084 %        XResourceInfo *resource_info)
5085 %
5086 %  A description of each parameter follows:
5087 %
5088 %    o windows: XInitializeWindows returns a pointer to a XWindows structure.
5089 %
5090 %    o display: Specifies a connection to an X server;  returned from
5091 %      XOpenDisplay.
5092 %
5093 %    o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
5094 %
5095 */
5096 MagickExport XWindows *XInitializeWindows(Display *display,
5097   XResourceInfo *resource_info)
5098 {
5099   Window
5100     root_window;
5101
5102   XWindows
5103     *windows;
5104
5105   /*
5106     Allocate windows structure.
5107   */
5108   windows=(XWindows *) AcquireAlignedMemory(1,sizeof(*windows));
5109   if (windows == (XWindows *) NULL)
5110     {
5111       ThrowXWindowFatalException(XServerFatalError,"MemoryAllocationFailed",
5112         "...");
5113       return((XWindows *) NULL);
5114     }
5115   (void) ResetMagickMemory(windows,0,sizeof(*windows));
5116   windows->pixel_info=(XPixelInfo *) AcquireMagickMemory(
5117     sizeof(*windows->pixel_info));
5118   windows->icon_pixel=(XPixelInfo *) AcquireMagickMemory(
5119     sizeof(*windows->icon_pixel));
5120   windows->icon_resources=(XResourceInfo *) AcquireMagickMemory(
5121     sizeof(*windows->icon_resources));
5122   if ((windows->pixel_info == (XPixelInfo *) NULL) ||
5123       (windows->icon_pixel == (XPixelInfo *) NULL) ||
5124       (windows->icon_resources == (XResourceInfo *) NULL))
5125     {
5126       ThrowXWindowFatalException(XServerFatalError,"MemoryAllocationFailed",
5127         "...");
5128       return((XWindows *) NULL);
5129     }
5130   /*
5131     Initialize windows structure.
5132   */
5133   windows->display=display;
5134   windows->wm_protocols=XInternAtom(display,"WM_PROTOCOLS",MagickFalse);
5135   windows->wm_delete_window=XInternAtom(display,"WM_DELETE_WINDOW",MagickFalse);
5136   windows->wm_take_focus=XInternAtom(display,"WM_TAKE_FOCUS",MagickFalse);
5137   windows->im_protocols=XInternAtom(display,"IM_PROTOCOLS",MagickFalse);
5138   windows->im_remote_command=
5139     XInternAtom(display,"IM_REMOTE_COMMAND",MagickFalse);
5140   windows->im_update_widget=XInternAtom(display,"IM_UPDATE_WIDGET",MagickFalse);
5141   windows->im_update_colormap=
5142     XInternAtom(display,"IM_UPDATE_COLORMAP",MagickFalse);
5143   windows->im_former_image=XInternAtom(display,"IM_FORMER_IMAGE",MagickFalse);
5144   windows->im_next_image=XInternAtom(display,"IM_NEXT_IMAGE",MagickFalse);
5145   windows->im_retain_colors=XInternAtom(display,"IM_RETAIN_COLORS",MagickFalse);
5146   windows->im_exit=XInternAtom(display,"IM_EXIT",MagickFalse);
5147   windows->dnd_protocols=XInternAtom(display,"DndProtocol",MagickFalse);
5148 #if defined(__WINDOWS__)
5149   (void) XSynchronize(display,IsWindows95());
5150 #endif
5151   if (IsEventLogging())
5152     {
5153       (void) XSynchronize(display,MagickTrue);
5154       (void) LogMagickEvent(X11Event,GetMagickModule(),"Version: %s",
5155         GetMagickVersion((unsigned long *) NULL));
5156       (void) LogMagickEvent(X11Event,GetMagickModule(),"Protocols:");
5157       (void) LogMagickEvent(X11Event,GetMagickModule(),
5158         "  Window Manager: 0x%lx",windows->wm_protocols);
5159       (void) LogMagickEvent(X11Event,GetMagickModule(),
5160         "    delete window: 0x%lx",windows->wm_delete_window);
5161       (void) LogMagickEvent(X11Event,GetMagickModule(),"    take focus: 0x%lx",
5162         windows->wm_take_focus);
5163       (void) LogMagickEvent(X11Event,GetMagickModule(),"  ImageMagick: 0x%lx",
5164         windows->im_protocols);
5165       (void) LogMagickEvent(X11Event,GetMagickModule(),
5166         "    remote command: 0x%lx",windows->im_remote_command);
5167       (void) LogMagickEvent(X11Event,GetMagickModule(),
5168         "    update widget: 0x%lx",windows->im_update_widget);
5169       (void) LogMagickEvent(X11Event,GetMagickModule(),
5170         "    update colormap: 0x%lx",windows->im_update_colormap);
5171       (void) LogMagickEvent(X11Event,GetMagickModule(),
5172         "    former image: 0x%lx",windows->im_former_image);
5173       (void) LogMagickEvent(X11Event,GetMagickModule(),"    next image: 0x%lx",
5174         windows->im_next_image);
5175       (void) LogMagickEvent(X11Event,GetMagickModule(),
5176         "    retain colors: 0x%lx",windows->im_retain_colors);
5177       (void) LogMagickEvent(X11Event,GetMagickModule(),"    exit: 0x%lx",
5178         windows->im_exit);
5179       (void) LogMagickEvent(X11Event,GetMagickModule(),"  Drag and Drop: 0x%lx",
5180         windows->dnd_protocols);
5181     }
5182   /*
5183     Allocate standard colormap.
5184   */
5185   windows->map_info=XAllocStandardColormap();
5186   windows->icon_map=XAllocStandardColormap();
5187   if ((windows->map_info == (XStandardColormap *) NULL) ||
5188       (windows->icon_map == (XStandardColormap *) NULL))
5189     ThrowXWindowFatalException(ResourceLimitFatalError,
5190       "MemoryAllocationFailed","...");
5191   windows->map_info->colormap=(Colormap) NULL;
5192   windows->icon_map->colormap=(Colormap) NULL;
5193   windows->pixel_info->pixels=(unsigned long *) NULL;
5194   windows->pixel_info->annotate_context=(GC) NULL;
5195   windows->pixel_info->highlight_context=(GC) NULL;
5196   windows->pixel_info->widget_context=(GC) NULL;
5197   windows->font_info=(XFontStruct *) NULL;
5198   windows->icon_pixel->annotate_context=(GC) NULL;
5199   windows->icon_pixel->pixels=(unsigned long *) NULL;
5200   /*
5201     Allocate visual.
5202   */
5203   *windows->icon_resources=(*resource_info);
5204   windows->icon_resources->visual_type=(char *) "default";
5205   windows->icon_resources->colormap=SharedColormap;
5206   windows->visual_info=
5207     XBestVisualInfo(display,windows->map_info,resource_info);
5208   windows->icon_visual=
5209     XBestVisualInfo(display,windows->icon_map,windows->icon_resources);
5210   if ((windows->visual_info == (XVisualInfo *) NULL) ||
5211       (windows->icon_visual == (XVisualInfo *) NULL))
5212     ThrowXWindowFatalException(XServerFatalError,"UnableToGetVisual",
5213       resource_info->visual_type);
5214   if (IsEventLogging())
5215     {
5216       (void) LogMagickEvent(X11Event,GetMagickModule(),"Visual:");
5217       (void) LogMagickEvent(X11Event,GetMagickModule(),"  visual id: 0x%lx",
5218         windows->visual_info->visualid);
5219       (void) LogMagickEvent(X11Event,GetMagickModule(),"  class: %s",
5220         XVisualClassName(windows->visual_info->klass));
5221       (void) LogMagickEvent(X11Event,GetMagickModule(),"  depth: %d planes",
5222         windows->visual_info->depth);
5223       (void) LogMagickEvent(X11Event,GetMagickModule(),
5224         "  size of colormap: %d entries",windows->visual_info->colormap_size);
5225       (void) LogMagickEvent(X11Event,GetMagickModule(),
5226         "  red, green, blue masks: 0x%lx 0x%lx 0x%lx",
5227         windows->visual_info->red_mask,windows->visual_info->green_mask,
5228         windows->visual_info->blue_mask);
5229       (void) LogMagickEvent(X11Event,GetMagickModule(),
5230         "  significant bits in color: %d bits",
5231         windows->visual_info->bits_per_rgb);
5232     }
5233   /*
5234     Allocate class and manager hints.
5235   */
5236   windows->class_hints=XAllocClassHint();
5237   windows->manager_hints=XAllocWMHints();
5238   if ((windows->class_hints == (XClassHint *) NULL) ||
5239       (windows->manager_hints == (XWMHints *) NULL))
5240     ThrowXWindowFatalException(ResourceLimitFatalError,
5241       "MemoryAllocationFailed","...");
5242   /*
5243     Determine group leader if we have one.
5244   */
5245   root_window=XRootWindow(display,windows->visual_info->screen);
5246   windows->group_leader.id=(Window) NULL;
5247   if (resource_info->window_group != (char *) NULL)
5248     {
5249       if (isdigit((unsigned char) *resource_info->window_group) != 0)
5250         windows->group_leader.id=XWindowByID(display,root_window,(Window)
5251           strtol((char *) resource_info->window_group,(char **) NULL,0));
5252       if (windows->group_leader.id == (Window) NULL)
5253         windows->group_leader.id=
5254           XWindowByName(display,root_window,resource_info->window_group);
5255     }
5256   return(windows);
5257 }
5258 \f
5259 /*
5260 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5261 %                                                                             %
5262 %                                                                             %
5263 %                                                                             %
5264 %   X M a k e C u r s o r                                                     %
5265 %                                                                             %
5266 %                                                                             %
5267 %                                                                             %
5268 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5269 %
5270 %  XMakeCursor() creates a crosshairs X11 cursor.
5271 %
5272 %  The format of the XMakeCursor method is:
5273 %
5274 %      Cursor XMakeCursor(Display *display,Window window,Colormap colormap,
5275 %        char *background_color,char *foreground_color)
5276 %
5277 %  A description of each parameter follows:
5278 %
5279 %    o display: Specifies a connection to an X server;  returned from
5280 %      XOpenDisplay.
5281 %
5282 %    o window: Specifies the ID of the window for which the cursor is
5283 %      assigned.
5284 %
5285 %    o colormap: Specifies the ID of the colormap from which the background
5286 %      and foreground color will be retrieved.
5287 %
5288 %    o background_color: Specifies the color to use for the cursor background.
5289 %
5290 %    o foreground_color: Specifies the color to use for the cursor foreground.
5291 %
5292 */
5293 MagickExport Cursor XMakeCursor(Display *display,Window window,
5294   Colormap colormap,char *background_color,char *foreground_color)
5295 {
5296 #define scope_height 17
5297 #define scope_x_hot 8
5298 #define scope_y_hot 8
5299 #define scope_width 17
5300
5301   static const unsigned char
5302     scope_bits[] =
5303     {
5304       0x80, 0x03, 0x00, 0x80, 0x02, 0x00, 0x80, 0x02, 0x00, 0x80, 0x02,
5305       0x00, 0x80, 0x02, 0x00, 0x80, 0x02, 0x00, 0x80, 0x02, 0x00, 0x7f,
5306       0xfc, 0x01, 0x01, 0x00, 0x01, 0x7f, 0xfc, 0x01, 0x80, 0x02, 0x00,
5307       0x80, 0x02, 0x00, 0x80, 0x02, 0x00, 0x80, 0x02, 0x00, 0x80, 0x02,
5308       0x00, 0x80, 0x02, 0x00, 0x80, 0x03, 0x00
5309     },
5310     scope_mask_bits[] =
5311     {
5312       0xc0, 0x07, 0x00, 0xc0, 0x07, 0x00, 0xc0, 0x06, 0x00, 0xc0, 0x06,
5313       0x00, 0xc0, 0x06, 0x00, 0xc0, 0x06, 0x00, 0xff, 0xfe, 0x01, 0x7f,
5314       0xfc, 0x01, 0x03, 0x80, 0x01, 0x7f, 0xfc, 0x01, 0xff, 0xfe, 0x01,
5315       0xc0, 0x06, 0x00, 0xc0, 0x06, 0x00, 0xc0, 0x06, 0x00, 0xc0, 0x06,
5316       0x00, 0xc0, 0x07, 0x00, 0xc0, 0x07, 0x00
5317     };
5318
5319   Cursor
5320     cursor;
5321
5322   Pixmap
5323     mask,
5324     source;
5325
5326   XColor
5327     background,
5328     foreground;
5329
5330   assert(display != (Display *) NULL);
5331   assert(window != (Window) NULL);
5332   assert(colormap != (Colormap) NULL);
5333   assert(background_color != (char *) NULL);
5334   assert(foreground_color != (char *) NULL);
5335   (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",background_color);
5336   source=XCreateBitmapFromData(display,window,(char *) scope_bits,scope_width,
5337     scope_height);
5338   mask=XCreateBitmapFromData(display,window,(char *) scope_mask_bits,
5339     scope_width,scope_height);
5340   if ((source == (Pixmap) NULL) || (mask == (Pixmap) NULL))
5341     {
5342       ThrowXWindowFatalException(XServerError,"UnableToCreatePixmap","...");
5343       return((Cursor) NULL);
5344     }
5345   (void) XParseColor(display,colormap,background_color,&background);
5346   (void) XParseColor(display,colormap,foreground_color,&foreground);
5347   cursor=XCreatePixmapCursor(display,source,mask,&foreground,&background,
5348     scope_x_hot,scope_y_hot);
5349   (void) XFreePixmap(display,source);
5350   (void) XFreePixmap(display,mask);
5351   return(cursor);
5352 }
5353 \f
5354 /*
5355 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5356 %                                                                             %
5357 %                                                                             %
5358 %                                                                             %
5359 %   X M a k e I m a g e                                                       %
5360 %                                                                             %
5361 %                                                                             %
5362 %                                                                             %
5363 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5364 %
5365 %  XMakeImage() creates an X11 image.  If the image size differs from the X11
5366 %  image size, the image is first resized.
5367 %
5368 %  The format of the XMakeImage method is:
5369 %
5370 %      MagickBooleanType XMakeImage(Display *display,
5371 %        const XResourceInfo *resource_info,XWindowInfo *window,Image *image,
5372 %        unsigned int width,unsigned int height)
5373 %
5374 %  A description of each parameter follows:
5375 %
5376 %    o display: Specifies a connection to an X server; returned from
5377 %      XOpenDisplay.
5378 %
5379 %    o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
5380 %
5381 %    o window: Specifies a pointer to a XWindowInfo structure.
5382 %
5383 %    o image: the image.
5384 %
5385 %    o width: Specifies the width in pixels of the rectangular area to
5386 %      display.
5387 %
5388 %    o height: Specifies the height in pixels of the rectangular area to
5389 %      display.
5390 %
5391 */
5392 MagickExport MagickBooleanType XMakeImage(Display *display,
5393   const XResourceInfo *resource_info,XWindowInfo *window,Image *image,
5394   unsigned int width,unsigned int height)
5395 {
5396 #define CheckOverflowException(length,width,height) \
5397   (((height) != 0) && ((length)/((size_t) height) != ((size_t) width)))
5398
5399   int
5400     depth,
5401     format;
5402
5403   size_t
5404     length;
5405
5406   XImage
5407     *matte_image,
5408     *ximage;
5409
5410   (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
5411   assert(display != (Display *) NULL);
5412   assert(resource_info != (XResourceInfo *) NULL);
5413   assert(window != (XWindowInfo *) NULL);
5414   assert(width != 0);
5415   assert(height != 0);
5416   if ((window->width == 0) || (window->height == 0))
5417     return(MagickFalse);
5418   /*
5419     Apply user transforms to the image.
5420   */
5421   (void) XCheckDefineCursor(display,window->id,window->busy_cursor);
5422   (void) XFlush(display);
5423   depth=(int) window->depth;
5424   if (window->destroy)
5425     window->image=DestroyImage(window->image);
5426   window->image=image;
5427   window->destroy=MagickFalse;
5428   if (window->image != (Image *) NULL)
5429     {
5430       if (window->crop_geometry != (char *) NULL)
5431         {
5432           Image
5433             *crop_image;
5434
5435           RectangleInfo
5436             crop_info;
5437
5438           /*
5439             Crop image.
5440           */
5441           window->image->page.x=0;
5442           window->image->page.y=0;
5443           (void) ParsePageGeometry(window->image,window->crop_geometry,
5444             &crop_info,&image->exception);
5445           crop_image=CropImage(window->image,&crop_info,&image->exception);
5446           if (crop_image != (Image *) NULL)
5447             {
5448               if (window->image != image)
5449                 window->image=DestroyImage(window->image);
5450               window->image=crop_image;
5451               window->destroy=MagickTrue;
5452             }
5453         }
5454       if ((width != (unsigned int) window->image->columns) ||
5455           (height != (unsigned int) window->image->rows))
5456         {
5457           Image
5458             *resize_image;
5459
5460           /*
5461             Resize image.
5462           */
5463           resize_image=NewImageList();
5464           if (window->pixel_info->colors != 0)
5465             resize_image=SampleImage(window->image,width,height,
5466               &image->exception);
5467           else
5468             resize_image=ThumbnailImage(window->image,width,height,
5469               &image->exception);
5470           if (resize_image != (Image *) NULL)
5471             {
5472               if (window->image != image)
5473                 window->image=DestroyImage(window->image);
5474               window->image=resize_image;
5475               window->destroy=MagickTrue;
5476             }
5477         }
5478       width=(unsigned int) window->image->columns;
5479       assert((unsigned long) width == window->image->columns);
5480       height=(unsigned int) window->image->rows;
5481       assert((unsigned long) height == window->image->rows);
5482     }
5483   /*
5484     Create X image.
5485   */
5486   ximage=(XImage *) NULL;
5487   format=(depth == 1) ? XYBitmap : ZPixmap;
5488 #if defined(MAGICKCORE_HAVE_SHARED_MEMORY)
5489   if (window->shared_memory != MagickFalse)
5490     {
5491       XShmSegmentInfo
5492         *segment_info;
5493
5494       segment_info=(XShmSegmentInfo *) window->segment_info;
5495       segment_info[1].shmid=(-1);
5496       segment_info[1].shmaddr=(char *) NULL;
5497       ximage=XShmCreateImage(display,window->visual,(unsigned int) depth,format,
5498         (char *) NULL,&segment_info[1],width,height);
5499       if (ximage == (XImage *) NULL)
5500         window->shared_memory=MagickFalse;
5501       length=(size_t) ximage->bytes_per_line*ximage->height;
5502       if (CheckOverflowException(length,ximage->bytes_per_line,ximage->height))
5503         window->shared_memory=MagickFalse;
5504       if (window->shared_memory != MagickFalse)
5505         segment_info[1].shmid=shmget(IPC_PRIVATE,length,IPC_CREAT | 0777);
5506       if (window->shared_memory != MagickFalse)
5507         segment_info[1].shmaddr=(char *) shmat(segment_info[1].shmid,0,0);
5508       if (segment_info[1].shmid < 0)
5509         window->shared_memory=MagickFalse;
5510       if (window->shared_memory != MagickFalse)
5511         (void) shmctl(segment_info[1].shmid,IPC_RMID,0);
5512       else
5513         {
5514           if (ximage != (XImage *) NULL)
5515             XDestroyImage(ximage);
5516           ximage=(XImage *) NULL;
5517           if (segment_info[1].shmaddr)
5518             {
5519               (void) shmdt(segment_info[1].shmaddr);
5520               segment_info[1].shmaddr=(char *) NULL;
5521             }
5522           if (segment_info[1].shmid >= 0)
5523             {
5524               (void) shmctl(segment_info[1].shmid,IPC_RMID,0);
5525               segment_info[1].shmid=(-1);
5526             }
5527         }
5528     }
5529 #endif
5530   /*
5531     Allocate X image pixel data.
5532   */
5533 #if defined(MAGICKCORE_HAVE_SHARED_MEMORY)
5534   if (window->shared_memory)
5535     {
5536       Status
5537         status;
5538
5539       XShmSegmentInfo
5540         *segment_info;
5541
5542       (void) XSync(display,MagickFalse);
5543       xerror_alert=MagickFalse;
5544       segment_info=(XShmSegmentInfo *) window->segment_info;
5545       ximage->data=segment_info[1].shmaddr;
5546       segment_info[1].readOnly=MagickFalse;
5547       status=XShmAttach(display,&segment_info[1]);
5548       if (status != False)
5549         (void) XSync(display,MagickFalse);
5550       if ((status == False) || (xerror_alert != MagickFalse))
5551         {
5552           window->shared_memory=MagickFalse;
5553           if (status != False)
5554             XShmDetach(display,&segment_info[1]);
5555           if (ximage != (XImage *) NULL)
5556             {
5557               ximage->data=NULL;
5558               XDestroyImage(ximage);
5559               ximage=(XImage *) NULL;
5560             }
5561           if (segment_info[1].shmid >= 0)
5562             {
5563               if (segment_info[1].shmaddr != NULL)
5564                 (void) shmdt(segment_info[1].shmaddr);
5565               (void) shmctl(segment_info[1].shmid,IPC_RMID,0);
5566               segment_info[1].shmid=(-1);
5567               segment_info[1].shmaddr=(char *) NULL;
5568             }
5569         }
5570     }
5571 #endif
5572   if (window->shared_memory == MagickFalse)
5573     ximage=XCreateImage(display,window->visual,(unsigned int) depth,format,0,
5574       (char *) NULL,width,height,XBitmapPad(display),0);
5575   if (ximage == (XImage *) NULL)
5576     {
5577       /*
5578         Unable to create X image.
5579       */
5580       (void) XCheckDefineCursor(display,window->id,window->cursor);
5581       return(MagickFalse);
5582     }
5583   length=(size_t) ximage->bytes_per_line*ximage->height;
5584   if (IsEventLogging())
5585     {
5586       (void) LogMagickEvent(X11Event,GetMagickModule(),"XImage:");
5587       (void) LogMagickEvent(X11Event,GetMagickModule(),"  width, height: %dx%d",
5588         ximage->width,ximage->height);
5589       (void) LogMagickEvent(X11Event,GetMagickModule(),"  format: %d",
5590         ximage->format);
5591       (void) LogMagickEvent(X11Event,GetMagickModule(),"  byte order: %d",
5592         ximage->byte_order);
5593       (void) LogMagickEvent(X11Event,GetMagickModule(),
5594         "  bitmap unit, bit order, pad: %d %d %d",ximage->bitmap_unit,
5595         ximage->bitmap_bit_order,ximage->bitmap_pad);
5596       (void) LogMagickEvent(X11Event,GetMagickModule(),"  depth: %d",
5597         ximage->depth);
5598       (void) LogMagickEvent(X11Event,GetMagickModule(),"  bytes per line: %d",
5599         ximage->bytes_per_line);
5600       (void) LogMagickEvent(X11Event,GetMagickModule(),"  bits per pixel: %d",
5601         ximage->bits_per_pixel);
5602       (void) LogMagickEvent(X11Event,GetMagickModule(),
5603         "  red, green, blue masks: 0x%lx 0x%lx 0x%lx",ximage->red_mask,
5604         ximage->green_mask,ximage->blue_mask);
5605     }
5606   if (window->shared_memory == MagickFalse)
5607     {
5608       if (ximage->format != XYBitmap)
5609         ximage->data=(char *) AcquireQuantumMemory((size_t)
5610           ximage->bytes_per_line,(size_t) ximage->height);
5611       else
5612         ximage->data=(char *) AcquireQuantumMemory((size_t)
5613           ximage->bytes_per_line*ximage->depth,(size_t) ximage->height);
5614     }
5615   if (ximage->data == (char *) NULL)
5616     {
5617       /*
5618         Unable to allocate pixel data.
5619       */
5620       XDestroyImage(ximage);
5621       ximage=(XImage *) NULL;
5622       (void) XCheckDefineCursor(display,window->id,window->cursor);
5623       return(MagickFalse);
5624     }
5625   if (window->ximage != (XImage *) NULL)
5626     {
5627       /*
5628         Destroy previous X image.
5629       */
5630       length=(size_t) window->ximage->bytes_per_line*window->ximage->height;
5631 #if defined(MAGICKCORE_HAVE_SHARED_MEMORY)
5632       if (window->segment_info != (XShmSegmentInfo *) NULL)
5633         {
5634           XShmSegmentInfo
5635             *segment_info;
5636
5637           segment_info=(XShmSegmentInfo *) window->segment_info;
5638           if (segment_info[0].shmid >= 0)
5639             {
5640               (void) XSync(display,MagickFalse);
5641               (void) XShmDetach(display,&segment_info[0]);
5642               (void) XSync(display,MagickFalse);
5643               if (segment_info[0].shmaddr != (char *) NULL)
5644                 (void) shmdt(segment_info[0].shmaddr);
5645               (void) shmctl(segment_info[0].shmid,IPC_RMID,0);
5646               segment_info[0].shmid=(-1);
5647               segment_info[0].shmaddr=(char *) NULL;
5648               window->ximage->data=(char *) NULL;
5649           }
5650         }
5651 #endif
5652       if (window->ximage->data != (char *) NULL)
5653         free(window->ximage->data);
5654       window->ximage->data=(char *) NULL;
5655       XDestroyImage(window->ximage);
5656       window->ximage=(XImage *) NULL;
5657     }
5658 #if defined(MAGICKCORE_HAVE_SHARED_MEMORY)
5659   if (window->segment_info != (XShmSegmentInfo *) NULL)
5660     {
5661       XShmSegmentInfo
5662         *segment_info;
5663
5664       segment_info=(XShmSegmentInfo *) window->segment_info;
5665       segment_info[0]=segment_info[1];
5666     }
5667 #endif
5668   window->ximage=ximage;
5669   matte_image=(XImage *) NULL;
5670   if ((window->shape != MagickFalse) && (window->image != (Image *) NULL))
5671     if ((window->image->matte != MagickFalse) &&
5672         ((long) width <= XDisplayWidth(display,window->screen)) &&
5673         ((long) height <= XDisplayHeight(display,window->screen)))
5674       {
5675         /*
5676           Create matte image.
5677         */
5678         matte_image=XCreateImage(display,window->visual,1,XYBitmap,0,
5679           (char *) NULL,width,height,XBitmapPad(display),0);
5680         if (IsEventLogging())
5681           {
5682             (void) LogMagickEvent(X11Event,GetMagickModule(),"Matte Image:");
5683             (void) LogMagickEvent(X11Event,GetMagickModule(),
5684               "  width, height: %dx%d",matte_image->width,matte_image->height);
5685           }
5686         if (matte_image != (XImage *) NULL)
5687           {
5688             /*
5689               Allocate matte image pixel data.
5690             */
5691             matte_image->data=(char *) AcquireQuantumMemory((size_t)
5692               matte_image->bytes_per_line*matte_image->depth,
5693               (size_t) matte_image->height);
5694             if (matte_image->data == (char *) NULL)
5695               {
5696                 XDestroyImage(matte_image);
5697                 matte_image=(XImage *) NULL;
5698               }
5699           }
5700       }
5701   if (window->matte_image != (XImage *) NULL)
5702     {
5703       /*
5704         Free matte image.
5705       */
5706       if (window->matte_image->data != (char *) NULL)
5707         free(window->matte_image->data);
5708       window->matte_image->data=(char *) NULL;
5709       XDestroyImage(window->matte_image);
5710       window->matte_image=(XImage *) NULL;
5711     }
5712   window->matte_image=matte_image;
5713   if (window->matte_pixmap != (Pixmap) NULL)
5714     {
5715       (void) XFreePixmap(display,window->matte_pixmap);
5716       window->matte_pixmap=(Pixmap) NULL;
5717 #if defined(MAGICKCORE_HAVE_SHAPE)
5718       if (window->shape != MagickFalse)
5719         XShapeCombineMask(display,window->id,ShapeBounding,0,0,None,ShapeSet);
5720 #endif
5721     }
5722   window->stasis=MagickFalse;
5723   /*
5724     Convert pixels to X image data.
5725   */
5726   if (window->image != (Image *) NULL)
5727     {
5728       if ((ximage->byte_order == LSBFirst) || ((ximage->format == XYBitmap) &&
5729           (ximage->bitmap_bit_order == LSBFirst)))
5730         XMakeImageLSBFirst(resource_info,window,window->image,ximage,
5731           matte_image);
5732       else
5733         XMakeImageMSBFirst(resource_info,window,window->image,ximage,
5734           matte_image);
5735     }
5736   if (window->matte_image != (XImage *) NULL)
5737     {
5738       /*
5739         Create matte pixmap.
5740       */
5741       window->matte_pixmap=XCreatePixmap(display,window->id,width,height,1);
5742       if (window->matte_pixmap != (Pixmap) NULL)
5743         {
5744           GC
5745             graphics_context;
5746
5747           XGCValues
5748             context_values;
5749
5750           /*
5751             Copy matte image to matte pixmap.
5752           */
5753           context_values.background=1;
5754           context_values.foreground=0;
5755           graphics_context=XCreateGC(display,window->matte_pixmap,
5756             (unsigned long) (GCBackground | GCForeground),&context_values);
5757           (void) XPutImage(display,window->matte_pixmap,graphics_context,
5758             window->matte_image,0,0,0,0,width,height);
5759           (void) XFreeGC(display,graphics_context);
5760 #if defined(MAGICKCORE_HAVE_SHAPE)
5761           if (window->shape != MagickFalse)
5762             XShapeCombineMask(display,window->id,ShapeBounding,0,0,
5763               window->matte_pixmap,ShapeSet);
5764 #endif
5765         }
5766       }
5767   (void) XMakePixmap(display,resource_info,window);
5768   /*
5769     Restore cursor.
5770   */
5771   (void) XCheckDefineCursor(display,window->id,window->cursor);
5772   return(MagickTrue);
5773 }
5774 \f
5775 /*
5776 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5777 %                                                                             %
5778 %                                                                             %
5779 %                                                                             %
5780 +   X M a k e I m a g e L S B F i r s t                                       %
5781 %                                                                             %
5782 %                                                                             %
5783 %                                                                             %
5784 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5785 %
5786 %  XMakeImageLSBFirst() initializes the pixel data of an X11 Image. The X image
5787 %  pixels are copied in least-significant bit and byte first order.  The
5788 %  server's scanline pad is respected.  Rather than using one or two general
5789 %  cases, many special cases are found here to help speed up the image
5790 %  conversion.
5791 %
5792 %  The format of the XMakeImageLSBFirst method is:
5793 %
5794 %      void XMakeImageLSBFirst(Display *display,XWindows *windows)
5795 %
5796 %  A description of each parameter follows:
5797 %
5798 %    o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
5799 %
5800 %    o window: Specifies a pointer to a XWindowInfo structure.
5801 %
5802 %    o image: the image.
5803 %
5804 %    o ximage: Specifies a pointer to a XImage structure;  returned from
5805 %      XCreateImage.
5806 %
5807 %    o matte_image: Specifies a pointer to a XImage structure;  returned from
5808 %      XCreateImage.
5809 %
5810 */
5811 static void XMakeImageLSBFirst(const XResourceInfo *resource_info,
5812   const XWindowInfo *window,Image *image,XImage *ximage,XImage *matte_image)
5813 {
5814   Image
5815     *canvas;
5816
5817   int
5818     y;
5819
5820   register const IndexPacket
5821     *indexes;
5822
5823   register const PixelPacket
5824     *p;
5825
5826   register int
5827     x;
5828
5829   register unsigned char
5830     *q;
5831
5832   unsigned char
5833     bit,
5834     byte;
5835
5836   unsigned int
5837     scanline_pad;
5838
5839   unsigned long
5840     pixel,
5841     *pixels;
5842
5843   XStandardColormap
5844     *map_info;
5845
5846   assert(resource_info != (XResourceInfo *) NULL);
5847   assert(window != (XWindowInfo *) NULL);
5848   assert(image != (Image *) NULL);
5849   if (image->debug != MagickFalse)
5850     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
5851   canvas=image;
5852   if ((image->storage_class == DirectClass) && (image->matte != MagickFalse))
5853     {
5854       char
5855         size[MaxTextExtent];
5856
5857       Image
5858         *pattern;
5859
5860       ImageInfo
5861         *image_info;
5862
5863       image_info=AcquireImageInfo();
5864       (void) CopyMagickString(image_info->filename,
5865         resource_info->image_info->texture != (char *) NULL ?
5866         resource_info->image_info->texture : "pattern:checkerboard",
5867         MaxTextExtent);
5868       (void) FormatMagickString(size,MaxTextExtent,"%lux%lu",image->columns,
5869         image->rows);
5870       image_info->size=ConstantString(size);
5871       pattern=ReadImage(image_info,&image->exception);
5872       image_info=DestroyImageInfo(image_info);
5873       if (pattern != (Image *) NULL)
5874         {
5875           canvas=CloneImage(image,0,0,MagickTrue,&image->exception);
5876           if (canvas != (Image *) NULL)
5877             (void) CompositeImage(canvas,DstOverCompositeOp,pattern,0,0);
5878           pattern=DestroyImage(pattern);
5879         }
5880     }
5881   scanline_pad=(unsigned int) (ximage->bytes_per_line-((ximage->width*
5882     ximage->bits_per_pixel) >> 3));
5883   map_info=window->map_info;
5884   pixels=window->pixel_info->pixels;
5885   q=(unsigned char *) ximage->data;
5886   x=0;
5887   if (ximage->format == XYBitmap)
5888     {
5889       register unsigned short
5890         polarity;
5891
5892       unsigned char
5893         background,
5894         foreground;
5895
5896       /*
5897         Convert canvas to big-endian bitmap.
5898       */
5899       background=(unsigned char)
5900         (XPixelIntensity(&window->pixel_info->foreground_color) <
5901          XPixelIntensity(&window->pixel_info->background_color) ? 0x80 : 0x00);
5902       foreground=(unsigned char)
5903         (XPixelIntensity(&window->pixel_info->background_color) <
5904          XPixelIntensity(&window->pixel_info->foreground_color) ? 0x80 : 0x00);
5905       polarity=(unsigned short) ((PixelIntensityToQuantum(
5906         &canvas->colormap[0])) < ((Quantum) QuantumRange/2) ? 1 : 0);
5907       if (canvas->colors == 2)
5908         polarity=PixelIntensity(&canvas->colormap[0]) <
5909           PixelIntensity(&canvas->colormap[1]);
5910       for (y=0; y < (int) canvas->rows; y++)
5911       {
5912         p=GetVirtualPixels(canvas,0,y,canvas->columns,1,&canvas->exception);
5913         if (p == (const PixelPacket *) NULL)
5914           break;
5915         indexes=GetVirtualIndexQueue(canvas);
5916         bit=0;
5917         byte=0;
5918         for (x=0; x < (int) canvas->columns; x++)
5919         {
5920           byte>>=1;
5921           if (indexes[x] == (IndexPacket) polarity)
5922             byte|=foreground;
5923           else
5924             byte|=background;
5925           bit++;
5926           if (bit == 8)
5927             {
5928               *q++=byte;
5929               bit=0;
5930               byte=0;
5931             }
5932         }
5933         if (bit != 0)
5934           *q=byte >> (8-bit);
5935         q+=scanline_pad;
5936       }
5937     }
5938   else
5939     if (window->pixel_info->colors != 0)
5940       switch (ximage->bits_per_pixel)
5941       {
5942         case 2:
5943         {
5944           register unsigned int
5945             nibble;
5946
5947           /*
5948             Convert to 2 bit color-mapped X canvas.
5949           */
5950           for (y=0; y < (int) canvas->rows; y++)
5951           {
5952             p=GetVirtualPixels(canvas,0,y,canvas->columns,1,&canvas->exception);
5953             if (p == (const PixelPacket *) NULL)
5954               break;
5955             indexes=GetVirtualIndexQueue(canvas);
5956             nibble=0;
5957             for (x=0; x < (int) canvas->columns; x++)
5958             {
5959               pixel=pixels[(long) indexes[x]] & 0x0f;
5960               switch (nibble)
5961               {
5962                 case 0:
5963                 {
5964                   *q=(unsigned char) pixel;
5965                   nibble++;
5966                   break;
5967                 }
5968                 case 1:
5969                 {
5970                   *q|=(unsigned char) (pixel << 2);
5971                   nibble++;
5972                   break;
5973                 }
5974                 case 2:
5975                 {
5976                   *q|=(unsigned char) (pixel << 4);
5977                   nibble++;
5978                   break;
5979                 }
5980                 case 3:
5981                 {
5982                   *q|=(unsigned char) (pixel << 6);
5983                   q++;
5984                   nibble=0;
5985                   break;
5986                 }
5987               }
5988             }
5989             q+=scanline_pad;
5990           }
5991           break;
5992         }
5993         case 4:
5994         {
5995           register unsigned int
5996             nibble;
5997
5998           /*
5999             Convert to 4 bit color-mapped X canvas.
6000           */
6001           for (y=0; y < (int) canvas->rows; y++)
6002           {
6003             p=GetVirtualPixels(canvas,0,y,canvas->columns,1,&canvas->exception);
6004             if (p == (const PixelPacket *) NULL)
6005               break;
6006             indexes=GetVirtualIndexQueue(canvas);
6007             nibble=0;
6008             for (x=0; x < (int) canvas->columns; x++)
6009             {
6010               pixel=pixels[(long) indexes[x]] & 0xf;
6011               switch (nibble)
6012               {
6013                 case 0:
6014                 {
6015                   *q=(unsigned char) pixel;
6016                   nibble++;
6017                   break;
6018                 }
6019                 case 1:
6020                 {
6021                   *q|=(unsigned char) (pixel << 4);
6022                   q++;
6023                   nibble=0;
6024                   break;
6025                 }
6026               }
6027             }
6028             q+=scanline_pad;
6029           }
6030           break;
6031         }
6032         case 6:
6033         case 8:
6034         {
6035           /*
6036             Convert to 8 bit color-mapped X canvas.
6037           */
6038           if (resource_info->color_recovery &&
6039               resource_info->quantize_info->dither)
6040             {
6041               XDitherImage(canvas,ximage);
6042               break;
6043             }
6044           for (y=0; y < (int) canvas->rows; y++)
6045           {
6046             p=GetVirtualPixels(canvas,0,y,canvas->columns,1,&canvas->exception);
6047             if (p == (const PixelPacket *) NULL)
6048               break;
6049             indexes=GetVirtualIndexQueue(canvas);
6050             for (x=0; x < (int) canvas->columns; x++)
6051             {
6052               pixel=pixels[(long) indexes[x]];
6053               *q++=(unsigned char) pixel;
6054             }
6055             q+=scanline_pad;
6056           }
6057           break;
6058         }
6059         default:
6060         {
6061           register int
6062             k;
6063
6064           register unsigned int
6065             bytes_per_pixel;
6066
6067           unsigned char
6068             channel[sizeof(unsigned long)];
6069
6070           /*
6071             Convert to multi-byte color-mapped X canvas.
6072           */
6073           bytes_per_pixel=(unsigned int) (ximage->bits_per_pixel >> 3);
6074           for (y=0; y < (int) canvas->rows; y++)
6075           {
6076             p=GetVirtualPixels(canvas,0,y,canvas->columns,1,&canvas->exception);
6077             if (p == (const PixelPacket *) NULL)
6078               break;
6079             indexes=GetVirtualIndexQueue(canvas);
6080             for (x=0; x < (int) canvas->columns; x++)
6081             {
6082               pixel=pixels[(long) indexes[x]];
6083               for (k=0; k < (int) bytes_per_pixel; k++)
6084               {
6085                 channel[k]=(unsigned char) pixel;
6086                 pixel>>=8;
6087               }
6088               for (k=0; k < (int) bytes_per_pixel; k++)
6089                 *q++=channel[k];
6090             }
6091             q+=scanline_pad;
6092           }
6093           break;
6094         }
6095       }
6096     else
6097       switch (ximage->bits_per_pixel)
6098       {
6099         case 2:
6100         {
6101           register unsigned int
6102             nibble;
6103
6104           /*
6105             Convert to contiguous 2 bit continuous-tone X canvas.
6106           */
6107           for (y=0; y < (int) canvas->rows; y++)
6108           {
6109             nibble=0;
6110             p=GetVirtualPixels(canvas,0,y,canvas->columns,1,&canvas->exception);
6111             if (p == (const PixelPacket *) NULL)
6112               break;
6113             for (x=0; x < (int) canvas->columns; x++)
6114             {
6115               pixel=XGammaPixel(map_info,p);
6116               pixel&=0xf;
6117               switch (nibble)
6118               {
6119                 case 0:
6120                 {
6121                   *q=(unsigned char) pixel;
6122                   nibble++;
6123                   break;
6124                 }
6125                 case 1:
6126                 {
6127                   *q|=(unsigned char) (pixel << 2);
6128                   nibble++;
6129                   break;
6130                 }
6131                 case 2:
6132                 {
6133                   *q|=(unsigned char) (pixel << 4);
6134                   nibble++;
6135                   break;
6136                 }
6137                 case 3:
6138                 {
6139                   *q|=(unsigned char) (pixel << 6);
6140                   q++;
6141                   nibble=0;
6142                   break;
6143                 }
6144               }
6145               p++;
6146             }
6147             q+=scanline_pad;
6148           }
6149           break;
6150         }
6151         case 4:
6152         {
6153           register unsigned int
6154             nibble;
6155
6156           /*
6157             Convert to contiguous 4 bit continuous-tone X canvas.
6158           */
6159           for (y=0; y < (int) canvas->rows; y++)
6160           {
6161             p=GetVirtualPixels(canvas,0,y,canvas->columns,1,&canvas->exception);
6162             if (p == (const PixelPacket *) NULL)
6163               break;
6164             nibble=0;
6165             for (x=0; x < (int) canvas->columns; x++)
6166             {
6167               pixel=XGammaPixel(map_info,p);
6168               pixel&=0xf;
6169               switch (nibble)
6170               {
6171                 case 0:
6172                 {
6173                   *q=(unsigned char) pixel;
6174                   nibble++;
6175                   break;
6176                 }
6177                 case 1:
6178                 {
6179                   *q|=(unsigned char) (pixel << 4);
6180                   q++;
6181                   nibble=0;
6182                   break;
6183                 }
6184               }
6185               p++;
6186             }
6187             q+=scanline_pad;
6188           }
6189           break;
6190         }
6191         case 6:
6192         case 8:
6193         {
6194           /*
6195             Convert to contiguous 8 bit continuous-tone X canvas.
6196           */
6197           if (resource_info->color_recovery &&
6198               resource_info->quantize_info->dither)
6199             {
6200               XDitherImage(canvas,ximage);
6201               break;
6202             }
6203           for (y=0; y < (int) canvas->rows; y++)
6204           {
6205             p=GetVirtualPixels(canvas,0,y,canvas->columns,1,&canvas->exception);
6206             if (p == (const PixelPacket *) NULL)
6207               break;
6208             for (x=0; x < (int) canvas->columns; x++)
6209             {
6210               pixel=XGammaPixel(map_info,p);
6211               *q++=(unsigned char) pixel;
6212               p++;
6213             }
6214             q+=scanline_pad;
6215           }
6216           break;
6217         }
6218         default:
6219         {
6220           if ((ximage->bits_per_pixel == 32) && (map_info->red_max == 255) &&
6221               (map_info->green_max == 255) && (map_info->blue_max == 255) &&
6222               (map_info->red_mult == 65536L) && (map_info->green_mult == 256) &&
6223               (map_info->blue_mult == 1))
6224             {
6225               /*
6226                 Convert to 32 bit continuous-tone X canvas.
6227               */
6228               for (y=0; y < (int) canvas->rows; y++)
6229               {
6230                 p=GetVirtualPixels(canvas,0,y,canvas->columns,1,
6231                   &canvas->exception);
6232                 if (p == (const PixelPacket *) NULL)
6233                   break;
6234                 if ((red_gamma != 1.0) || (green_gamma != 1.0) ||
6235                     (blue_gamma != 1.0))
6236                   {
6237                     /*
6238                       Gamma correct canvas.
6239                     */
6240                     for (x=(int) canvas->columns-1; x >= 0; x--)
6241                     {
6242                       *q++=ScaleQuantumToChar(XBlueGamma(p->blue));
6243                       *q++=ScaleQuantumToChar(XGreenGamma(p->green));
6244                       *q++=ScaleQuantumToChar(XRedGamma(p->red));
6245                       *q++=0;
6246                       p++;
6247                     }
6248                     continue;
6249                   }
6250                 for (x=(int) canvas->columns-1; x >= 0; x--)
6251                 {
6252                   *q++=ScaleQuantumToChar((Quantum) p->blue);
6253                   *q++=ScaleQuantumToChar((Quantum) p->green);
6254                   *q++=ScaleQuantumToChar((Quantum) p->red);
6255                   *q++=0;
6256                   p++;
6257                 }
6258               }
6259             }
6260           else
6261             if ((ximage->bits_per_pixel == 32) && (map_info->red_max == 255) &&
6262                 (map_info->green_max == 255) && (map_info->blue_max == 255) &&
6263                 (map_info->red_mult == 1) && (map_info->green_mult == 256) &&
6264                 (map_info->blue_mult == 65536L))
6265               {
6266                 /*
6267                   Convert to 32 bit continuous-tone X canvas.
6268                 */
6269                 for (y=0; y < (int) canvas->rows; y++)
6270                 {
6271                   p=GetVirtualPixels(canvas,0,y,canvas->columns,1,
6272                     &canvas->exception);
6273                   if (p == (const PixelPacket *) NULL)
6274                     break;
6275                   if ((red_gamma != 1.0) || (green_gamma != 1.0) ||
6276                       (blue_gamma != 1.0))
6277                     {
6278                       /*
6279                         Gamma correct canvas.
6280                       */
6281                       for (x=(int) canvas->columns-1; x >= 0; x--)
6282                       {
6283                         *q++=ScaleQuantumToChar(XRedGamma(p->red));
6284                         *q++=ScaleQuantumToChar(XGreenGamma(p->green));
6285                         *q++=ScaleQuantumToChar(XBlueGamma(p->blue));
6286                         *q++=0;
6287                         p++;
6288                       }
6289                       continue;
6290                     }
6291                   for (x=(int) canvas->columns-1; x >= 0; x--)
6292                   {
6293                     *q++=ScaleQuantumToChar((Quantum) p->red);
6294                     *q++=ScaleQuantumToChar((Quantum) p->green);
6295                     *q++=ScaleQuantumToChar((Quantum) p->blue);
6296                     *q++=0;
6297                     p++;
6298                   }
6299                 }
6300               }
6301             else
6302               {
6303                 register int
6304                   k;
6305
6306                 register unsigned int
6307                   bytes_per_pixel;
6308
6309                 unsigned char
6310                   channel[sizeof(unsigned long)];
6311
6312                 /*
6313                   Convert to multi-byte continuous-tone X canvas.
6314                 */
6315                 bytes_per_pixel=(unsigned int) (ximage->bits_per_pixel >> 3);
6316                 for (y=0; y < (int) canvas->rows; y++)
6317                 {
6318                   p=GetVirtualPixels(canvas,0,y,canvas->columns,1,
6319                     &canvas->exception);
6320                   if (p == (PixelPacket *) NULL)
6321                     break;
6322                   for (x=0; x < (long) canvas->columns; x++)
6323                   {
6324                     pixel=XGammaPixel(map_info,p);
6325                     for (k=0; k < (int) bytes_per_pixel; k++)
6326                     {
6327                       channel[k]=(unsigned char) pixel;
6328                       pixel>>=8;
6329                     }
6330                     for (k=0; k < (int) bytes_per_pixel; k++)
6331                       *q++=channel[k];
6332                     p++;
6333                   }
6334                   q+=scanline_pad;
6335                 }
6336               }
6337           break;
6338         }
6339       }
6340   if (matte_image != (XImage *) NULL)
6341     {
6342       /*
6343         Initialize matte canvas.
6344       */
6345       scanline_pad=(unsigned int) (matte_image->bytes_per_line-
6346         ((matte_image->width*matte_image->bits_per_pixel) >> 3));
6347       q=(unsigned char *) matte_image->data;
6348       for (y=0; y < (int) canvas->rows; y++)
6349       {
6350         p=GetVirtualPixels(canvas,0,y,canvas->columns,1,&canvas->exception);
6351         if (p == (const PixelPacket *) NULL)
6352           break;
6353         bit=0;
6354         byte=0;
6355         for (x=(int) canvas->columns-1; x >= 0; x--)
6356         {
6357           byte>>=1;
6358           if (p->opacity > (long) (QuantumRange/2))
6359             byte|=0x80;
6360           bit++;
6361           if (bit == 8)
6362             {
6363               *q++=byte;
6364               bit=0;
6365               byte=0;
6366             }
6367           p++;
6368         }
6369         if (bit != 0)
6370           *q=byte >> (8-bit);
6371         q+=scanline_pad;
6372       }
6373     }
6374   if (canvas != image)
6375     canvas=DestroyImage(canvas);
6376 }
6377 \f
6378 /*
6379 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
6380 %                                                                             %
6381 %                                                                             %
6382 %                                                                             %
6383 +   X M a k e I m a g e M S B F i r s t                                       %
6384 %                                                                             %
6385 %                                                                             %
6386 %                                                                             %
6387 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
6388 %
6389 %  XMakeImageMSBFirst() initializes the pixel data of an X11 Image.  The X
6390 %  image pixels are copied in most-significant bit and byte first order.  The
6391 %  server's scanline pad is also respected. Rather than using one or two
6392 %  general cases, many special cases are found here to help speed up the image
6393 %  conversion.
6394 %
6395 %  The format of the XMakeImageMSBFirst method is:
6396 %
6397 %      XMakeImageMSBFirst(resource_info,window,image,ximage,matte_image)
6398 %
6399 %  A description of each parameter follows:
6400 %
6401 %    o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
6402 %
6403 %    o window: Specifies a pointer to a XWindowInfo structure.
6404 %
6405 %    o image: the image.
6406 %
6407 %    o ximage: Specifies a pointer to a XImage structure;  returned from
6408 %      XCreateImage.
6409 %
6410 %    o matte_image: Specifies a pointer to a XImage structure;  returned from
6411 %      XCreateImage.
6412 %
6413 %
6414 */
6415 static void XMakeImageMSBFirst(const XResourceInfo *resource_info,
6416   const XWindowInfo *window,Image *image,XImage *ximage,XImage *matte_image)
6417 {
6418   Image
6419     *canvas;
6420
6421   int
6422     y;
6423
6424   register int
6425     x;
6426
6427   register const IndexPacket
6428     *indexes;
6429
6430   register const PixelPacket
6431     *p;
6432
6433   register unsigned char
6434     *q;
6435
6436   unsigned char
6437     bit,
6438     byte;
6439
6440   unsigned int
6441     scanline_pad;
6442
6443   unsigned long
6444     pixel,
6445     *pixels;
6446
6447   XStandardColormap
6448     *map_info;
6449
6450   assert(resource_info != (XResourceInfo *) NULL);
6451   assert(window != (XWindowInfo *) NULL);
6452   assert(image != (Image *) NULL);
6453   if (image->debug != MagickFalse)
6454     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
6455   canvas=image;
6456   if ((image->storage_class == DirectClass) && (image->matte != MagickFalse))
6457     {
6458       char
6459         size[MaxTextExtent];
6460
6461       Image
6462         *pattern;
6463
6464       ImageInfo
6465         *image_info;
6466
6467       image_info=AcquireImageInfo();
6468       (void) CopyMagickString(image_info->filename,
6469         resource_info->image_info->texture != (char *) NULL ?
6470         resource_info->image_info->texture : "pattern:checkerboard",
6471         MaxTextExtent);
6472       (void) FormatMagickString(size,MaxTextExtent,"%lux%lu",image->columns,
6473         image->rows);
6474       image_info->size=ConstantString(size);
6475       pattern=ReadImage(image_info,&image->exception);
6476       image_info=DestroyImageInfo(image_info);
6477       if (pattern != (Image *) NULL)
6478         {
6479           canvas=CloneImage(image,0,0,MagickTrue,&image->exception);
6480           if (canvas != (Image *) NULL)
6481             (void) CompositeImage(canvas,DstOverCompositeOp,pattern,0,0);
6482           pattern=DestroyImage(pattern);
6483         }
6484     }
6485   scanline_pad=(unsigned int) (ximage->bytes_per_line-
6486     ((ximage->width*ximage->bits_per_pixel) >> 3));
6487   map_info=window->map_info;
6488   pixels=window->pixel_info->pixels;
6489   q=(unsigned char *) ximage->data;
6490   x=0;
6491   if (ximage->format == XYBitmap)
6492     {
6493       register unsigned short
6494         polarity;
6495
6496       unsigned char
6497         background,
6498         foreground;
6499
6500       /*
6501         Convert canvas to big-endian bitmap.
6502       */
6503       background=(unsigned char)
6504         (XPixelIntensity(&window->pixel_info->foreground_color) <
6505          XPixelIntensity(&window->pixel_info->background_color) ?  0x01 : 0x00);
6506       foreground=(unsigned char)
6507         (XPixelIntensity(&window->pixel_info->background_color) <
6508          XPixelIntensity(&window->pixel_info->foreground_color) ?  0x01 : 0x00);
6509       polarity=(unsigned short) ((PixelIntensityToQuantum(
6510         &canvas->colormap[0])) < ((Quantum) QuantumRange/2) ? 1 : 0);
6511       if (canvas->colors == 2)
6512         polarity=PixelIntensity(&canvas->colormap[0]) <
6513           PixelIntensity(&canvas->colormap[1]);
6514       for (y=0; y < (int) canvas->rows; y++)
6515       {
6516         p=GetVirtualPixels(canvas,0,y,canvas->columns,1,&canvas->exception);
6517         if (p == (const PixelPacket *) NULL)
6518           break;
6519         indexes=GetVirtualIndexQueue(canvas);
6520         bit=0;
6521         byte=0;
6522         for (x=(int) canvas->columns-1; x >= 0; x--)
6523         {
6524           byte<<=1;
6525           if (indexes[x] == (IndexPacket) polarity)
6526             byte|=foreground;
6527           else
6528             byte|=background;
6529           bit++;
6530           if (bit == 8)
6531             {
6532               *q++=byte;
6533               bit=0;
6534               byte=0;
6535             }
6536         }
6537         if (bit != 0)
6538           *q=byte << (8-bit);
6539         q+=scanline_pad;
6540       }
6541     }
6542   else
6543     if (window->pixel_info->colors != 0)
6544       switch (ximage->bits_per_pixel)
6545       {
6546         case 2:
6547         {
6548           register unsigned int
6549             nibble;
6550
6551           /*
6552             Convert to 2 bit color-mapped X canvas.
6553           */
6554           for (y=0; y < (int) canvas->rows; y++)
6555           {
6556             p=GetVirtualPixels(canvas,0,y,canvas->columns,1,&canvas->exception);
6557             if (p == (const PixelPacket *) NULL)
6558               break;
6559             indexes=GetVirtualIndexQueue(canvas);
6560             nibble=0;
6561             for (x=0; x < (int) canvas->columns; x++)
6562             {
6563               pixel=pixels[(long) indexes[x]] & 0xf;
6564               switch (nibble)
6565               {
6566                 case 0:
6567                 {
6568                   *q=(unsigned char) (pixel << 6);
6569                   nibble++;
6570                   break;
6571                 }
6572                 case 1:
6573                 {
6574                   *q|=(unsigned char) (pixel << 4);
6575                   nibble++;
6576                   break;
6577                 }
6578                 case 2:
6579                 {
6580                   *q|=(unsigned char) (pixel << 2);
6581                   nibble++;
6582                   break;
6583                 }
6584                 case 3:
6585                 {
6586                   *q|=(unsigned char) pixel;
6587                   q++;
6588                   nibble=0;
6589                   break;
6590                 }
6591               }
6592             }
6593             q+=scanline_pad;
6594           }
6595           break;
6596         }
6597         case 4:
6598         {
6599           register unsigned int
6600             nibble;
6601
6602           /*
6603             Convert to 4 bit color-mapped X canvas.
6604           */
6605           for (y=0; y < (int) canvas->rows; y++)
6606           {
6607             p=GetVirtualPixels(canvas,0,y,canvas->columns,1,&canvas->exception);
6608             if (p == (const PixelPacket *) NULL)
6609               break;
6610             indexes=GetVirtualIndexQueue(canvas);
6611             nibble=0;
6612             for (x=0; x < (int) canvas->columns; x++)
6613             {
6614               pixel=pixels[(long) indexes[x]] & 0xf;
6615               switch (nibble)
6616               {
6617                 case 0:
6618                 {
6619                   *q=(unsigned char) (pixel << 4);
6620                   nibble++;
6621                   break;
6622                 }
6623                 case 1:
6624                 {
6625                   *q|=(unsigned char) pixel;
6626                   q++;
6627                   nibble=0;
6628                   break;
6629                 }
6630               }
6631             }
6632             q+=scanline_pad;
6633           }
6634           break;
6635         }
6636         case 6:
6637         case 8:
6638         {
6639           /*
6640             Convert to 8 bit color-mapped X canvas.
6641           */
6642           if (resource_info->color_recovery &&
6643               resource_info->quantize_info->dither)
6644             {
6645               XDitherImage(canvas,ximage);
6646               break;
6647             }
6648           for (y=0; y < (int) canvas->rows; y++)
6649           {
6650             p=GetVirtualPixels(canvas,0,y,canvas->columns,1,&canvas->exception);
6651             if (p == (const PixelPacket *) NULL)
6652               break;
6653             indexes=GetVirtualIndexQueue(canvas);
6654             for (x=0; x < (int) canvas->columns; x++)
6655             {
6656               pixel=pixels[(long) indexes[x]];
6657               *q++=(unsigned char) pixel;
6658             }
6659             q+=scanline_pad;
6660           }
6661           break;
6662         }
6663         default:
6664         {
6665           register int
6666             k;
6667
6668           register unsigned int
6669             bytes_per_pixel;
6670
6671           unsigned char
6672             channel[sizeof(unsigned long)];
6673
6674           /*
6675             Convert to 8 bit color-mapped X canvas.
6676           */
6677           bytes_per_pixel=(unsigned int) (ximage->bits_per_pixel >> 3);
6678           for (y=0; y < (int) canvas->rows; y++)
6679           {
6680             p=GetVirtualPixels(canvas,0,y,canvas->columns,1,&canvas->exception);
6681             if (p == (const PixelPacket *) NULL)
6682               break;
6683             indexes=GetVirtualIndexQueue(canvas);
6684             for (x=0; x < (int) canvas->columns; x++)
6685             {
6686               pixel=pixels[(long) indexes[x]];
6687               for (k=(int) bytes_per_pixel-1; k >= 0; k--)
6688               {
6689                 channel[k]=(unsigned char) pixel;
6690                 pixel>>=8;
6691               }
6692               for (k=0; k < (int) bytes_per_pixel; k++)
6693                 *q++=channel[k];
6694             }
6695             q+=scanline_pad;
6696           }
6697           break;
6698         }
6699       }
6700     else
6701       switch (ximage->bits_per_pixel)
6702       {
6703         case 2:
6704         {
6705           register unsigned int
6706             nibble;
6707
6708           /*
6709             Convert to 4 bit continuous-tone X canvas.
6710           */
6711           for (y=0; y < (int) canvas->rows; y++)
6712           {
6713             p=GetVirtualPixels(canvas,0,y,canvas->columns,1,&canvas->exception);
6714             if (p == (const PixelPacket *) NULL)
6715               break;
6716             nibble=0;
6717             for (x=(int) canvas->columns-1; x >= 0; x--)
6718             {
6719               pixel=XGammaPixel(map_info,p);
6720               pixel&=0xf;
6721               switch (nibble)
6722               {
6723                 case 0:
6724                 {
6725                   *q=(unsigned char) (pixel << 6);
6726                   nibble++;
6727                   break;
6728                 }
6729                 case 1:
6730                 {
6731                   *q|=(unsigned char) (pixel << 4);
6732                   nibble++;
6733                   break;
6734                 }
6735                 case 2:
6736                 {
6737                   *q|=(unsigned char) (pixel << 2);
6738                   nibble++;
6739                   break;
6740                 }
6741                 case 3:
6742                 {
6743                   *q|=(unsigned char) pixel;
6744                   q++;
6745                   nibble=0;
6746                   break;
6747                 }
6748               }
6749               p++;
6750             }
6751             q+=scanline_pad;
6752           }
6753           break;
6754         }
6755         case 4:
6756         {
6757           register unsigned int
6758             nibble;
6759
6760           /*
6761             Convert to 4 bit continuous-tone X canvas.
6762           */
6763           for (y=0; y < (int) canvas->rows; y++)
6764           {
6765             p=GetVirtualPixels(canvas,0,y,canvas->columns,1,&canvas->exception);
6766             if (p == (const PixelPacket *) NULL)
6767               break;
6768             nibble=0;
6769             for (x=(int) canvas->columns-1; x >= 0; x--)
6770             {
6771               pixel=XGammaPixel(map_info,p);
6772               pixel&=0xf;
6773               switch (nibble)
6774               {
6775                 case 0:
6776                 {
6777                   *q=(unsigned char) (pixel << 4);
6778                   nibble++;
6779                   break;
6780                 }
6781                 case 1:
6782                 {
6783                   *q|=(unsigned char) pixel;
6784                   q++;
6785                   nibble=0;
6786                   break;
6787                 }
6788               }
6789               p++;
6790             }
6791             q+=scanline_pad;
6792           }
6793           break;
6794         }
6795         case 6:
6796         case 8:
6797         {
6798           /*
6799             Convert to 8 bit continuous-tone X canvas.
6800           */
6801           if (resource_info->color_recovery &&
6802               resource_info->quantize_info->dither)
6803             {
6804               XDitherImage(canvas,ximage);
6805               break;
6806             }
6807           for (y=0; y < (int) canvas->rows; y++)
6808           {
6809             p=GetVirtualPixels(canvas,0,y,canvas->columns,1,&canvas->exception);
6810             if (p == (const PixelPacket *) NULL)
6811               break;
6812             for (x=(int) canvas->columns-1; x >= 0; x--)
6813             {
6814               pixel=XGammaPixel(map_info,p);
6815               *q++=(unsigned char) pixel;
6816               p++;
6817             }
6818             q+=scanline_pad;
6819           }
6820           break;
6821         }
6822         default:
6823         {
6824           if ((ximage->bits_per_pixel == 32) && (map_info->red_max == 255) &&
6825               (map_info->green_max == 255) && (map_info->blue_max == 255) &&
6826               (map_info->red_mult == 65536L) && (map_info->green_mult == 256) &&
6827               (map_info->blue_mult == 1))
6828             {
6829               /*
6830                 Convert to 32 bit continuous-tone X canvas.
6831               */
6832               for (y=0; y < (int) canvas->rows; y++)
6833               {
6834                 p=GetVirtualPixels(canvas,0,y,canvas->columns,1,
6835                   &canvas->exception);
6836                 if (p == (const PixelPacket *) NULL)
6837                   break;
6838                 if ((red_gamma != 1.0) || (green_gamma != 1.0) ||
6839                     (blue_gamma != 1.0))
6840                   {
6841                     /*
6842                       Gamma correct canvas.
6843                     */
6844                     for (x=(int) canvas->columns-1; x >= 0; x--)
6845                     {
6846                       *q++=0;
6847                       *q++=ScaleQuantumToChar(XRedGamma(p->red));
6848                       *q++=ScaleQuantumToChar(XGreenGamma(p->green));
6849                       *q++=ScaleQuantumToChar(XBlueGamma(p->blue));
6850                       p++;
6851                     }
6852                     continue;
6853                   }
6854                 for (x=(int) canvas->columns-1; x >= 0; x--)
6855                 {
6856                   *q++=0;
6857                   *q++=ScaleQuantumToChar((Quantum) p->red);
6858                   *q++=ScaleQuantumToChar((Quantum) p->green);
6859                   *q++=ScaleQuantumToChar((Quantum) p->blue);
6860                   p++;
6861                 }
6862               }
6863             }
6864           else
6865             if ((ximage->bits_per_pixel == 32) && (map_info->red_max == 255) &&
6866                 (map_info->green_max == 255) && (map_info->blue_max == 255) &&
6867                 (map_info->red_mult == 1) && (map_info->green_mult == 256) &&
6868                 (map_info->blue_mult == 65536L))
6869               {
6870                 /*
6871                   Convert to 32 bit continuous-tone X canvas.
6872                 */
6873                 for (y=0; y < (int) canvas->rows; y++)
6874                 {
6875                   p=GetVirtualPixels(canvas,0,y,canvas->columns,1,
6876                     &canvas->exception);
6877                   if (p == (const PixelPacket *) NULL)
6878                     break;
6879                   if ((red_gamma != 1.0) || (green_gamma != 1.0) ||
6880                       (blue_gamma != 1.0))
6881                     {
6882                       /*
6883                         Gamma correct canvas.
6884                       */
6885                       for (x=(int) canvas->columns-1; x >= 0; x--)
6886                       {
6887                         *q++=0;
6888                         *q++=ScaleQuantumToChar(XBlueGamma(p->blue));
6889                         *q++=ScaleQuantumToChar(XGreenGamma(p->green));
6890                         *q++=ScaleQuantumToChar(XRedGamma(p->red));
6891                         p++;
6892                       }
6893                       continue;
6894                     }
6895                   for (x=(int) canvas->columns-1; x >= 0; x--)
6896                   {
6897                     *q++=0;
6898                     *q++=ScaleQuantumToChar((Quantum) p->blue);
6899                     *q++=ScaleQuantumToChar((Quantum) p->green);
6900                     *q++=ScaleQuantumToChar((Quantum) p->red);
6901                     p++;
6902                   }
6903                 }
6904               }
6905             else
6906               {
6907                 register int
6908                   k;
6909
6910                 register unsigned int
6911                   bytes_per_pixel;
6912
6913                 unsigned char
6914                   channel[sizeof(unsigned long)];
6915
6916                 /*
6917                   Convert to multi-byte continuous-tone X canvas.
6918                 */
6919                 bytes_per_pixel=(unsigned int) (ximage->bits_per_pixel >> 3);
6920                 for (y=0; y < (int) canvas->rows; y++)
6921                 {
6922                   p=GetVirtualPixels(canvas,0,y,canvas->columns,1,
6923                     &canvas->exception);
6924                   if (p == (const PixelPacket *) NULL)
6925                     break;
6926                   for (x=(int) canvas->columns-1; x >= 0; x--)
6927                   {
6928                     pixel=XGammaPixel(map_info,p);
6929                     for (k=(int) bytes_per_pixel-1; k >= 0; k--)
6930                     {
6931                       channel[k]=(unsigned char) pixel;
6932                       pixel>>=8;
6933                     }
6934                     for (k=0; k < (int) bytes_per_pixel; k++)
6935                       *q++=channel[k];
6936                     p++;
6937                   }
6938                   q+=scanline_pad;
6939                 }
6940               }
6941           break;
6942         }
6943       }
6944   if (matte_image != (XImage *) NULL)
6945     {
6946       /*
6947         Initialize matte canvas.
6948       */
6949       scanline_pad=(unsigned int) (matte_image->bytes_per_line-
6950         ((matte_image->width*matte_image->bits_per_pixel) >> 3));
6951       q=(unsigned char *) matte_image->data;
6952       for (y=0; y < (int) canvas->rows; y++)
6953       {
6954         p=GetVirtualPixels(canvas,0,y,canvas->columns,1,&canvas->exception);
6955         if (p == (const PixelPacket *) NULL)
6956           break;
6957         bit=0;
6958         byte=0;
6959         for (x=(int) canvas->columns-1; x >= 0; x--)
6960         {
6961           byte<<=1;
6962           if (p->opacity > (long) (QuantumRange/2))
6963             byte|=0x01;
6964           bit++;
6965           if (bit == 8)
6966             {
6967               *q++=byte;
6968               bit=0;
6969               byte=0;
6970             }
6971           p++;
6972         }
6973         if (bit != 0)
6974           *q=byte << (8-bit);
6975         q+=scanline_pad;
6976       }
6977     }
6978   if (canvas != image)
6979     canvas=DestroyImage(canvas);
6980 }
6981 \f
6982 /*
6983 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
6984 %                                                                             %
6985 %                                                                             %
6986 %                                                                             %
6987 %   X M a k e M a g n i f y I m a g e                                         %
6988 %                                                                             %
6989 %                                                                             %
6990 %                                                                             %
6991 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
6992 %
6993 %  XMakeMagnifyImage() magnifies a region of an X image and displays it.
6994 %
6995 %  The format of the XMakeMagnifyImage method is:
6996 %
6997 %      void XMakeMagnifyImage(display,windows)
6998 %
6999 %  A description of each parameter follows:
7000 %
7001 %    o display: Specifies a connection to an X server;  returned from
7002 %      XOpenDisplay.
7003 %
7004 %    o windows: Specifies a pointer to a XWindows structure.
7005 %
7006 */
7007 MagickExport void XMakeMagnifyImage(Display *display,XWindows *windows)
7008 {
7009   char
7010     tuple[MaxTextExtent];
7011
7012   int
7013     y;
7014
7015   long
7016     n;
7017
7018   MagickPixelPacket
7019     pixel;
7020
7021   register int
7022     x;
7023
7024   register long
7025     i;
7026
7027   register unsigned char
7028     *p,
7029     *q;
7030
7031   static unsigned int
7032     previous_magnify = 0;
7033
7034   static XWindowInfo
7035     magnify_window;
7036
7037   unsigned int
7038     height,
7039     j,
7040     k,
7041     l,
7042     magnify,
7043     scanline_pad,
7044     width;
7045
7046   XImage
7047     *ximage;
7048
7049   /*
7050     Check boundary conditions.
7051   */
7052   (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
7053   assert(display != (Display *) NULL);
7054   assert(windows != (XWindows *) NULL);
7055   magnify=1;
7056   for (n=1; n < (long) windows->magnify.data; n++)
7057     magnify<<=1;
7058   while ((magnify*windows->image.ximage->width) < windows->magnify.width)
7059     magnify<<=1;
7060   while ((magnify*windows->image.ximage->height) < windows->magnify.height)
7061     magnify<<=1;
7062   while (magnify > windows->magnify.width)
7063     magnify>>=1;
7064   while (magnify > windows->magnify.height)
7065     magnify>>=1;
7066   if (magnify != previous_magnify)
7067     {
7068       Status
7069         status;
7070
7071       XTextProperty
7072         window_name;
7073
7074       /*
7075         New magnify factor:  update magnify window name.
7076       */
7077       i=0;
7078       while ((1 << i) <= (int) magnify)
7079         i++;
7080       (void) FormatMagickString(windows->magnify.name,MaxTextExtent,
7081         "Magnify %luX",i);
7082       status=XStringListToTextProperty(&windows->magnify.name,1,&window_name);
7083       if (status != False)
7084         {
7085           XSetWMName(display,windows->magnify.id,&window_name);
7086           XSetWMIconName(display,windows->magnify.id,&window_name);
7087           (void) XFree((void *) window_name.value);
7088         }
7089     }
7090   previous_magnify=magnify;
7091   ximage=windows->image.ximage;
7092   width=(unsigned int) windows->magnify.ximage->width;
7093   height=(unsigned int) windows->magnify.ximage->height;
7094   if ((windows->magnify.x < 0) ||
7095       (windows->magnify.x >= windows->image.ximage->width))
7096     windows->magnify.x=windows->image.ximage->width >> 1;
7097   x=windows->magnify.x-((width/magnify) >> 1);
7098   if (x < 0)
7099     x=0;
7100   else
7101     if (x > (int) (ximage->width-(width/magnify)))
7102       x=ximage->width-width/magnify;
7103   if ((windows->magnify.y < 0) ||
7104       (windows->magnify.y >= windows->image.ximage->height))
7105     windows->magnify.y=windows->image.ximage->height >> 1;
7106   y=windows->magnify.y-((height/magnify) >> 1);
7107   if (y < 0)
7108     y=0;
7109   else
7110     if (y > (int) (ximage->height-(height/magnify)))
7111       y=ximage->height-height/magnify;
7112   q=(unsigned char *) windows->magnify.ximage->data;
7113   scanline_pad=(unsigned int) (windows->magnify.ximage->bytes_per_line-
7114     ((width*windows->magnify.ximage->bits_per_pixel) >> 3));
7115   if (ximage->bits_per_pixel < 8)
7116     {
7117       register unsigned char
7118         background,
7119         byte,
7120         foreground,
7121         p_bit,
7122         q_bit;
7123
7124       register unsigned int
7125         plane;
7126
7127       XPixelInfo
7128         *pixel_info;
7129
7130       pixel_info=windows->magnify.pixel_info;
7131       switch (ximage->bitmap_bit_order)
7132       {
7133         case LSBFirst:
7134         {
7135           /*
7136             Magnify little-endian bitmap.
7137           */
7138           background=0x00;
7139           foreground=0x80;
7140           if (ximage->format == XYBitmap)
7141             {
7142               background=(unsigned char)
7143                 (XPixelIntensity(&pixel_info->foreground_color) <
7144                  XPixelIntensity(&pixel_info->background_color) ?  0x80 : 0x00);
7145               foreground=(unsigned char)
7146                 (XPixelIntensity(&pixel_info->background_color) <
7147                  XPixelIntensity(&pixel_info->foreground_color) ?  0x80 : 0x00);
7148               if (windows->magnify.depth > 1)
7149                 Swap(background,foreground);
7150             }
7151           for (i=0; i < (long) height; i+=magnify)
7152           {
7153             /*
7154               Propogate pixel magnify rows.
7155             */
7156             for (j=0; j < magnify; j++)
7157             {
7158               p=(unsigned char *) ximage->data+y*ximage->bytes_per_line+
7159                 ((x*ximage->bits_per_pixel) >> 3);
7160               p_bit=(unsigned char) (x*ximage->bits_per_pixel) & 0x07;
7161               q_bit=0;
7162               byte=0;
7163               for (k=0; k < width; k+=magnify)
7164               {
7165                 /*
7166                   Propogate pixel magnify columns.
7167                 */
7168                 for (l=0; l < magnify; l++)
7169                 {
7170                   /*
7171                     Propogate each bit plane.
7172                   */
7173                   for (plane=0; (int) plane < ximage->bits_per_pixel; plane++)
7174                   {
7175                     byte>>=1;
7176                     if (*p & (0x01 << (p_bit+plane)))
7177                       byte|=foreground;
7178                     else
7179                       byte|=background;
7180                     q_bit++;
7181                     if (q_bit == 8)
7182                       {
7183                         *q++=byte;
7184                         q_bit=0;
7185                         byte=0;
7186                       }
7187                   }
7188                 }
7189                 p_bit+=ximage->bits_per_pixel;
7190                 if (p_bit == 8)
7191                   {
7192                     p++;
7193                     p_bit=0;
7194                   }
7195                 if (q_bit != 0)
7196                   *q=byte >> (8-q_bit);
7197                 q+=scanline_pad;
7198               }
7199             }
7200             y++;
7201           }
7202           break;
7203         }
7204         case MSBFirst:
7205         default:
7206         {
7207           /*
7208             Magnify big-endian bitmap.
7209           */
7210           background=0x00;
7211           foreground=0x01;
7212           if (ximage->format == XYBitmap)
7213             {
7214               background=(unsigned char)
7215                 (XPixelIntensity(&pixel_info->foreground_color) <
7216                  XPixelIntensity(&pixel_info->background_color) ?  0x01 : 0x00);
7217               foreground=(unsigned char)
7218                 (XPixelIntensity(&pixel_info->background_color) <
7219                  XPixelIntensity(&pixel_info->foreground_color) ?  0x01 : 0x00);
7220               if (windows->magnify.depth > 1)
7221                 Swap(background,foreground);
7222             }
7223           for (i=0; i < (long) height; i+=magnify)
7224           {
7225             /*
7226               Propogate pixel magnify rows.
7227             */
7228             for (j=0; j < magnify; j++)
7229             {
7230               p=(unsigned char *) ximage->data+y*ximage->bytes_per_line+
7231                 ((x*ximage->bits_per_pixel) >> 3);
7232               p_bit=(unsigned char) (x*ximage->bits_per_pixel) & 0x07;
7233               q_bit=0;
7234               byte=0;
7235               for (k=0; k < width; k+=magnify)
7236               {
7237                 /*
7238                   Propogate pixel magnify columns.
7239                 */
7240                 for (l=0; l < magnify; l++)
7241                 {
7242                   /*
7243                     Propogate each bit plane.
7244                   */
7245                   for (plane=0; (int) plane < ximage->bits_per_pixel; plane++)
7246                   {
7247                     byte<<=1;
7248                     if (*p & (0x80 >> (p_bit+plane)))
7249                       byte|=foreground;
7250                     else
7251                       byte|=background;
7252                     q_bit++;
7253                     if (q_bit == 8)
7254                       {
7255                         *q++=byte;
7256                         q_bit=0;
7257                         byte=0;
7258                       }
7259                   }
7260                 }
7261                 p_bit+=ximage->bits_per_pixel;
7262                 if (p_bit == 8)
7263                   {
7264                     p++;
7265                     p_bit=0;
7266                   }
7267                 if (q_bit != 0)
7268                   *q=byte << (8-q_bit);
7269                 q+=scanline_pad;
7270               }
7271             }
7272             y++;
7273           }
7274           break;
7275         }
7276       }
7277     }
7278   else
7279     switch (ximage->bits_per_pixel)
7280     {
7281       case 6:
7282       case 8:
7283       {
7284         /*
7285           Magnify 8 bit X image.
7286         */
7287         for (i=0; i < (long) height; i+=magnify)
7288         {
7289           /*
7290             Propogate pixel magnify rows.
7291           */
7292           for (j=0; j < magnify; j++)
7293           {
7294             p=(unsigned char *) ximage->data+y*ximage->bytes_per_line+
7295               ((x*ximage->bits_per_pixel) >> 3);
7296             for (k=0; k < width; k+=magnify)
7297             {
7298               /*
7299                 Propogate pixel magnify columns.
7300               */
7301               for (l=0; l < magnify; l++)
7302                 *q++=(*p);
7303               p++;
7304             }
7305             q+=scanline_pad;
7306           }
7307           y++;
7308         }
7309         break;
7310       }
7311       default:
7312       {
7313         register unsigned int
7314           bytes_per_pixel,
7315           m;
7316
7317         /*
7318           Magnify multi-byte X image.
7319         */
7320         bytes_per_pixel=(unsigned int) ximage->bits_per_pixel >> 3;
7321         for (i=0; i < (long) height; i+=magnify)
7322         {
7323           /*
7324             Propogate pixel magnify rows.
7325           */
7326           for (j=0; j < magnify; j++)
7327           {
7328             p=(unsigned char *) ximage->data+y*ximage->bytes_per_line+
7329               ((x*ximage->bits_per_pixel) >> 3);
7330             for (k=0; k < width; k+=magnify)
7331             {
7332               /*
7333                 Propogate pixel magnify columns.
7334               */
7335               for (l=0; l < magnify; l++)
7336                 for (m=0; m < bytes_per_pixel; m++)
7337                   *q++=(*(p+m));
7338               p+=bytes_per_pixel;
7339             }
7340             q+=scanline_pad;
7341           }
7342           y++;
7343         }
7344         break;
7345       }
7346     }
7347   /*
7348     Copy X image to magnify pixmap.
7349   */
7350   x=windows->magnify.x-((width/magnify) >> 1);
7351   if (x < 0)
7352     x=(int) ((width >> 1)-windows->magnify.x*magnify);
7353   else
7354     if (x > (int) (ximage->width-(width/magnify)))
7355       x=(int) ((ximage->width-windows->magnify.x)*magnify-(width >> 1));
7356     else
7357       x=0;
7358   y=windows->magnify.y-((height/magnify) >> 1);
7359   if (y < 0)
7360     y=(int) ((height >> 1)-windows->magnify.y*magnify);
7361   else
7362     if (y > (int) (ximage->height-(height/magnify)))
7363       y=(int) ((ximage->height-windows->magnify.y)*magnify-(height >> 1));
7364     else
7365       y=0;
7366   if ((x != 0) || (y != 0))
7367     (void) XFillRectangle(display,windows->magnify.pixmap,
7368       windows->magnify.annotate_context,0,0,width,height);
7369   (void) XPutImage(display,windows->magnify.pixmap,
7370     windows->magnify.annotate_context,windows->magnify.ximage,0,0,x,y,width-x,
7371     height-y);
7372   if ((magnify > 1) && ((magnify <= (width >> 1)) &&
7373       (magnify <= (height >> 1))))
7374     {
7375       RectangleInfo
7376         highlight_info;
7377
7378       /*
7379         Highlight center pixel.
7380       */
7381       highlight_info.x=(long) windows->magnify.width >> 1;
7382       highlight_info.y=(long) windows->magnify.height >> 1;
7383       highlight_info.width=magnify;
7384       highlight_info.height=magnify;
7385       (void) XDrawRectangle(display,windows->magnify.pixmap,
7386         windows->magnify.highlight_context,(int) highlight_info.x,
7387         (int) highlight_info.y,(unsigned int) highlight_info.width-1,
7388         (unsigned int) highlight_info.height-1);
7389       if (magnify > 2)
7390         (void) XDrawRectangle(display,windows->magnify.pixmap,
7391           windows->magnify.annotate_context,(int) highlight_info.x+1,
7392           (int) highlight_info.y+1,(unsigned int) highlight_info.width-3,
7393           (unsigned int) highlight_info.height-3);
7394     }
7395   /*
7396     Show center pixel color.
7397   */
7398   (void) GetOneVirtualMagickPixel(windows->image.image,windows->magnify.x,
7399     windows->magnify.y,&pixel,&windows->image.image->exception);
7400   (void) FormatMagickString(tuple,MaxTextExtent,"%d,%d: ",
7401     windows->magnify.x,windows->magnify.y);
7402   (void) ConcatenateMagickString(tuple,"(",MaxTextExtent);
7403   ConcatenateColorComponent(&pixel,RedChannel,X11Compliance,tuple);
7404   (void) ConcatenateMagickString(tuple,",",MaxTextExtent);
7405   ConcatenateColorComponent(&pixel,GreenChannel,X11Compliance,tuple);
7406   (void) ConcatenateMagickString(tuple,",",MaxTextExtent);
7407   ConcatenateColorComponent(&pixel,BlueChannel,X11Compliance,tuple);
7408   if (pixel.colorspace == CMYKColorspace)
7409     {
7410       (void) ConcatenateMagickString(tuple,",",MaxTextExtent);
7411       ConcatenateColorComponent(&pixel,IndexChannel,X11Compliance,tuple);
7412     }
7413   if (pixel.matte != MagickFalse)
7414     {
7415       (void) ConcatenateMagickString(tuple,",",MaxTextExtent);
7416       ConcatenateColorComponent(&pixel,OpacityChannel,X11Compliance,tuple);
7417     }
7418   (void) ConcatenateMagickString(tuple,")",MaxTextExtent);
7419   height=(unsigned int) windows->magnify.font_info->ascent+
7420     windows->magnify.font_info->descent;
7421   x=windows->magnify.font_info->max_bounds.width >> 1;
7422   y=windows->magnify.font_info->ascent+(height >> 2);
7423   (void) XDrawImageString(display,windows->magnify.pixmap,
7424     windows->magnify.annotate_context,x,y,tuple,(int) strlen(tuple));
7425   GetColorTuple(&pixel,MagickTrue,tuple);
7426   y+=height;
7427   (void) XDrawImageString(display,windows->magnify.pixmap,
7428     windows->magnify.annotate_context,x,y,tuple,(int) strlen(tuple));
7429   (void) QueryMagickColorname(windows->image.image,&pixel,SVGCompliance,tuple,
7430      &windows->image.image->exception);
7431   y+=height;
7432   (void) XDrawImageString(display,windows->magnify.pixmap,
7433     windows->magnify.annotate_context,x,y,tuple,(int) strlen(tuple));
7434   /*
7435     Refresh magnify window.
7436   */
7437   magnify_window=windows->magnify;
7438   magnify_window.x=0;
7439   magnify_window.y=0;
7440   XRefreshWindow(display,&magnify_window,(XEvent *) NULL);
7441 }
7442 \f
7443 /*
7444 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
7445 %                                                                             %
7446 %                                                                             %
7447 %                                                                             %
7448 %   X M a k e P i x m a p                                                     %
7449 %                                                                             %
7450 %                                                                             %
7451 %                                                                             %
7452 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
7453 %
7454 %  XMakePixmap() creates an X11 pixmap.
7455 %
7456 %  The format of the XMakePixmap method is:
7457 %
7458 %      void XMakeStandardColormap(Display *display,XVisualInfo *visual_info,
7459 %        XResourceInfo *resource_info,Image *image,XStandardColormap *map_info,
7460 %        XPixelInfo *pixel)
7461 %
7462 %  A description of each parameter follows:
7463 %
7464 %    o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
7465 %
7466 %    o display: Specifies a connection to an X server; returned from
7467 %      XOpenDisplay.
7468 %
7469 %    o window: Specifies a pointer to a XWindowInfo structure.
7470 %
7471 %
7472 */
7473 static MagickBooleanType XMakePixmap(Display *display,
7474   const XResourceInfo *resource_info,XWindowInfo *window)
7475 {
7476   unsigned int
7477     height,
7478     width;
7479
7480   (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
7481   assert(display != (Display *) NULL);
7482   assert(resource_info != (XResourceInfo *) NULL);
7483   assert(window != (XWindowInfo  *) NULL);
7484   if (window->pixmap != (Pixmap) NULL)
7485     {
7486       /*
7487         Destroy previous X pixmap.
7488       */
7489       (void) XFreePixmap(display,window->pixmap);
7490       window->pixmap=(Pixmap) NULL;
7491     }
7492   if (window->use_pixmap == MagickFalse)
7493     return(MagickFalse);
7494   if (window->ximage == (XImage *) NULL)
7495     return(MagickFalse);
7496   /*
7497     Display busy cursor.
7498   */
7499   (void) XCheckDefineCursor(display,window->id,window->busy_cursor);
7500   (void) XFlush(display);
7501   /*
7502     Create pixmap.
7503   */
7504   width=(unsigned int) window->ximage->width;
7505   height=(unsigned int) window->ximage->height;
7506   window->pixmap=XCreatePixmap(display,window->id,width,height,window->depth);
7507   if (window->pixmap == (Pixmap) NULL)
7508     {
7509       /*
7510         Unable to allocate pixmap.
7511       */
7512       (void) XCheckDefineCursor(display,window->id,window->cursor);
7513       return(MagickFalse);
7514     }
7515   /*
7516     Copy X image to pixmap.
7517   */
7518 #if defined(MAGICKCORE_HAVE_SHARED_MEMORY)
7519   if (window->shared_memory)
7520     (void) XShmPutImage(display,window->pixmap,window->annotate_context,
7521       window->ximage,0,0,0,0,width,height,MagickTrue);
7522 #endif
7523   if (window->shared_memory == MagickFalse)
7524     (void) XPutImage(display,window->pixmap,window->annotate_context,
7525       window->ximage,0,0,0,0,width,height);
7526   if (IsEventLogging())
7527     {
7528       (void) LogMagickEvent(X11Event,GetMagickModule(),"Pixmap:");
7529       (void) LogMagickEvent(X11Event,GetMagickModule(),"  width, height: %ux%u",
7530         width,height);
7531     }
7532   /*
7533     Restore cursor.
7534   */
7535   (void) XCheckDefineCursor(display,window->id,window->cursor);
7536   return(MagickTrue);
7537 }
7538 \f
7539 /*
7540 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
7541 %                                                                             %
7542 %                                                                             %
7543 %                                                                             %
7544 %   X M a k e S t a n d a r d C o l o r m a p                                 %
7545 %                                                                             %
7546 %                                                                             %
7547 %                                                                             %
7548 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
7549 %
7550 %  XMakeStandardColormap() creates an X11 Standard Colormap.
7551 %
7552 %  The format of the XMakeStandardColormap method is:
7553 %
7554 %      XMakeStandardColormap(display,visual_info,resource_info,image,
7555 %        map_info,pixel)
7556 %
7557 %  A description of each parameter follows:
7558 %
7559 %    o display: Specifies a connection to an X server; returned from
7560 %      XOpenDisplay.
7561 %
7562 %    o visual_info: Specifies a pointer to a X11 XVisualInfo structure;
7563 %      returned from XGetVisualInfo.
7564 %
7565 %    o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
7566 %
7567 %    o image: the image.
7568 %
7569 %    o map_info: If a Standard Colormap type is specified, this structure is
7570 %      initialized with info from the Standard Colormap.
7571 %
7572 %    o pixel: Specifies a pointer to a XPixelInfo structure.
7573 %
7574 %
7575 */
7576
7577 #if defined(__cplusplus) || defined(c_plusplus)
7578 extern "C" {
7579 #endif
7580
7581 static inline MagickRealType DiversityPixelIntensity(
7582   const DiversityPacket *pixel)
7583 {
7584   MagickRealType
7585     intensity;
7586
7587   intensity=0.299*pixel->red+0.587*pixel->green+0.114*pixel->blue;
7588   return(intensity);
7589 }
7590
7591 static int IntensityCompare(const void *x,const void *y)
7592 {
7593   DiversityPacket
7594     *color_1,
7595     *color_2;
7596
7597   int
7598     diversity;
7599
7600   color_1=(DiversityPacket *) x;
7601   color_2=(DiversityPacket *) y;
7602   diversity=(int) (DiversityPixelIntensity(color_2)-
7603     DiversityPixelIntensity(color_1));
7604   return(diversity);
7605 }
7606
7607 static int PopularityCompare(const void *x,const void *y)
7608 {
7609   DiversityPacket
7610     *color_1,
7611     *color_2;
7612
7613   color_1=(DiversityPacket *) x;
7614   color_2=(DiversityPacket *) y;
7615   return((int) color_2->count-(int) color_1->count);
7616 }
7617
7618 #if defined(__cplusplus) || defined(c_plusplus)
7619 }
7620 #endif
7621
7622 static inline Quantum ScaleXToQuantum(const unsigned long x,
7623   const unsigned long scale)
7624 {
7625   return((Quantum) (((MagickRealType) QuantumRange*x)/scale+0.5));
7626 }
7627
7628 MagickExport void XMakeStandardColormap(Display *display,
7629   XVisualInfo *visual_info,XResourceInfo *resource_info,Image *image,
7630   XStandardColormap *map_info,XPixelInfo *pixel)
7631 {
7632   Colormap
7633     colormap;
7634
7635   ExceptionInfo
7636     *exception;
7637
7638   register IndexPacket
7639     *indexes;
7640
7641   register long
7642     i;
7643
7644   Status
7645     status;
7646
7647   unsigned long
7648     number_colors,
7649     retain_colors;
7650
7651   unsigned short
7652     gray_value;
7653
7654   XColor
7655     color,
7656     *colors,
7657     *p;
7658
7659   (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
7660   assert(display != (Display *) NULL);
7661   assert(visual_info != (XVisualInfo *) NULL);
7662   assert(map_info != (XStandardColormap *) NULL);
7663   assert(resource_info != (XResourceInfo *) NULL);
7664   assert(pixel != (XPixelInfo *) NULL);
7665   exception=(&image->exception);
7666   if (resource_info->map_type != (char *) NULL)
7667     {
7668       /*
7669         Standard Colormap is already defined (i.e. xstdcmap).
7670       */
7671       XGetPixelPacket(display,visual_info,map_info,resource_info,image,
7672         pixel);
7673       number_colors=(unsigned int) (map_info->base_pixel+
7674         (map_info->red_max+1)*(map_info->green_max+1)*(map_info->blue_max+1));
7675       if ((map_info->red_max*map_info->green_max*map_info->blue_max) != 0)
7676         if ((image->matte == MagickFalse) &&
7677             (resource_info->color_recovery == MagickFalse) &&
7678             resource_info->quantize_info->dither &&
7679             (number_colors < MaxColormapSize))
7680           {
7681             Image
7682               *affinity_image;
7683
7684             register PixelPacket
7685               *restrict q;
7686
7687             /*
7688               Improve image appearance with error diffusion.
7689             */
7690             affinity_image=AcquireImage((ImageInfo *) NULL);
7691             if (affinity_image == (Image *) NULL)
7692               ThrowXWindowFatalException(ResourceLimitFatalError,
7693                 "UnableToDitherImage",image->filename);
7694             affinity_image->columns=number_colors;
7695             affinity_image->rows=1;
7696             /*
7697               Initialize colormap image.
7698             */
7699             q=QueueAuthenticPixels(affinity_image,0,0,affinity_image->columns,
7700               1,exception);
7701             if (q != (PixelPacket *) NULL)
7702               {
7703                 for (i=0; i < (long) number_colors; i++)
7704                 {
7705                   q->red=(Quantum) 0;
7706                   if (map_info->red_max != 0)
7707                     q->red=ScaleXToQuantum((unsigned long) (i/
7708                       map_info->red_mult),map_info->red_max);
7709                   q->green=(Quantum) 0;
7710                   if (map_info->green_max != 0)
7711                     q->green=ScaleXToQuantum((unsigned long) ((i/
7712                       map_info->green_mult) % (map_info->green_max+1)),
7713                       map_info->green_max);
7714                   q->blue=(Quantum) 0;
7715                   if (map_info->blue_max != 0)
7716                     q->blue=ScaleXToQuantum((unsigned long) (i %
7717                       map_info->green_mult),map_info->blue_max);
7718                   q->opacity=(Quantum) TransparentOpacity;
7719                   q++;
7720                 }
7721                 (void) SyncAuthenticPixels(affinity_image,exception);
7722                 (void) RemapImage(resource_info->quantize_info,image,
7723                   affinity_image);
7724               }
7725             XGetPixelPacket(display,visual_info,map_info,resource_info,image,
7726               pixel);
7727             (void) SetImageStorageClass(image,DirectClass);
7728             affinity_image=DestroyImage(affinity_image);
7729           }
7730       if (IsEventLogging())
7731         {
7732           (void) LogMagickEvent(X11Event,GetMagickModule(),
7733             "Standard Colormap:");
7734           (void) LogMagickEvent(X11Event,GetMagickModule(),
7735             "  colormap id: 0x%lx",map_info->colormap);
7736           (void) LogMagickEvent(X11Event,GetMagickModule(),
7737             "  red, green, blue max: %lu %lu %lu",map_info->red_max,
7738             map_info->green_max,map_info->blue_max);
7739           (void) LogMagickEvent(X11Event,GetMagickModule(),
7740             "  red, green, blue mult: %lu %lu %lu",map_info->red_mult,
7741             map_info->green_mult,map_info->blue_mult);
7742         }
7743       return;
7744     }
7745   if ((visual_info->klass != DirectColor) &&
7746       (visual_info->klass != TrueColor))
7747     if ((image->storage_class == DirectClass) ||
7748         ((int) image->colors > visual_info->colormap_size))
7749       {
7750         QuantizeInfo
7751           quantize_info;
7752
7753         /*
7754           Image has more colors than the visual supports.
7755         */
7756         quantize_info=(*resource_info->quantize_info);
7757         quantize_info.number_colors=(unsigned long) visual_info->colormap_size;
7758         (void) QuantizeImage(&quantize_info,image);
7759       }
7760   /*
7761     Free previous and create new colormap.
7762   */
7763   (void) XFreeStandardColormap(display,visual_info,map_info,pixel);
7764   colormap=XDefaultColormap(display,visual_info->screen);
7765   if (visual_info->visual != XDefaultVisual(display,visual_info->screen))
7766     colormap=XCreateColormap(display,XRootWindow(display,visual_info->screen),
7767       visual_info->visual,visual_info->klass == DirectColor ?
7768       AllocAll : AllocNone);
7769   if (colormap == (Colormap) NULL)
7770     ThrowXWindowFatalException(ResourceLimitFatalError,"UnableToCreateColormap",
7771       image->filename);
7772   /*
7773     Initialize the map and pixel info structures.
7774   */
7775   XGetMapInfo(visual_info,colormap,map_info);
7776   XGetPixelPacket(display,visual_info,map_info,resource_info,image,pixel);
7777   /*
7778     Allocating colors in server colormap is based on visual class.
7779   */
7780   switch (visual_info->klass)
7781   {
7782     case StaticGray:
7783     case StaticColor:
7784     {
7785       /*
7786         Define Standard Colormap for StaticGray or StaticColor visual.
7787       */
7788       number_colors=image->colors;
7789       colors=(XColor *) AcquireQuantumMemory((size_t)
7790         visual_info->colormap_size,sizeof(*colors));
7791       if (colors == (XColor *) NULL)
7792         ThrowXWindowFatalException(ResourceLimitFatalError,
7793           "UnableToCreateColormap",image->filename);
7794       p=colors;
7795       color.flags=(char) (DoRed | DoGreen | DoBlue);
7796       for (i=0; i < (long) image->colors; i++)
7797       {
7798         color.red=ScaleQuantumToShort(XRedGamma(image->colormap[i].red));
7799         color.green=ScaleQuantumToShort(XGreenGamma(image->colormap[i].green));
7800         color.blue=ScaleQuantumToShort(XBlueGamma(image->colormap[i].blue));
7801         if (visual_info->klass != StaticColor)
7802           {
7803             gray_value=(unsigned short) XPixelIntensity(&color);
7804             color.red=gray_value;
7805             color.green=gray_value;
7806             color.blue=gray_value;
7807           }
7808         status=XAllocColor(display,colormap,&color);
7809         if (status == False)
7810           {
7811             colormap=XCopyColormapAndFree(display,colormap);
7812             (void) XAllocColor(display,colormap,&color);
7813           }
7814         pixel->pixels[i]=color.pixel;
7815         *p++=color;
7816       }
7817       break;
7818     }
7819     case GrayScale:
7820     case PseudoColor:
7821     {
7822       unsigned int
7823         colormap_type;
7824
7825       /*
7826         Define Standard Colormap for GrayScale or PseudoColor visual.
7827       */
7828       number_colors=image->colors;
7829       colors=(XColor *) AcquireQuantumMemory((size_t)
7830         visual_info->colormap_size,sizeof(*colors));
7831       if (colors == (XColor *) NULL)
7832         ThrowXWindowFatalException(ResourceLimitFatalError,
7833           "UnableToCreateColormap",image->filename);
7834       /*
7835         Preallocate our GUI colors.
7836       */
7837       (void) XAllocColor(display,colormap,&pixel->foreground_color);
7838       (void) XAllocColor(display,colormap,&pixel->background_color);
7839       (void) XAllocColor(display,colormap,&pixel->border_color);
7840       (void) XAllocColor(display,colormap,&pixel->matte_color);
7841       (void) XAllocColor(display,colormap,&pixel->highlight_color);
7842       (void) XAllocColor(display,colormap,&pixel->shadow_color);
7843       (void) XAllocColor(display,colormap,&pixel->depth_color);
7844       (void) XAllocColor(display,colormap,&pixel->trough_color);
7845       for (i=0; i < MaxNumberPens; i++)
7846         (void) XAllocColor(display,colormap,&pixel->pen_colors[i]);
7847       /*
7848         Determine if image colors will "fit" into X server colormap.
7849       */
7850       colormap_type=resource_info->colormap;
7851       status=XAllocColorCells(display,colormap,MagickFalse,(unsigned long *)
7852         NULL,0,pixel->pixels,(unsigned int) image->colors);
7853       if (status != False)
7854         colormap_type=PrivateColormap;
7855       if (colormap_type == SharedColormap)
7856         {
7857           DiversityPacket
7858             *diversity;
7859
7860           int
7861             y;
7862
7863           register int
7864             x;
7865
7866           unsigned short
7867             index;
7868
7869           XColor
7870             *server_colors;
7871
7872           /*
7873             Define Standard colormap for shared GrayScale or PseudoColor visual.
7874           */
7875           diversity=(DiversityPacket *) AcquireQuantumMemory(image->colors,
7876             sizeof(*diversity));
7877           if (diversity == (DiversityPacket *) NULL)
7878             ThrowXWindowFatalException(ResourceLimitFatalError,
7879               "UnableToCreateColormap",image->filename);
7880           for (i=0; i < (long) image->colors; i++)
7881           {
7882             diversity[i].red=image->colormap[i].red;
7883             diversity[i].green=image->colormap[i].green;
7884             diversity[i].blue=image->colormap[i].blue;
7885             diversity[i].index=(unsigned short) i;
7886             diversity[i].count=0;
7887           }
7888           for (y=0; y < (int) image->rows; y++)
7889           {
7890             register long
7891               x;
7892
7893             register PixelPacket
7894               *restrict q;
7895
7896             q=GetAuthenticPixels(image,0,y,image->columns,1,exception);
7897             if (q == (PixelPacket *) NULL)
7898               break;
7899             indexes=GetAuthenticIndexQueue(image);
7900             for (x=(long) image->columns-1; x >= 0; x--)
7901               diversity[(long) indexes[x]].count++;
7902           }
7903           /*
7904             Sort colors by decreasing intensity.
7905           */
7906           qsort((void *) diversity,image->colors,sizeof(*diversity),
7907             IntensityCompare);
7908           for (i=0; i < (long) image->colors; )
7909           {
7910             diversity[i].count<<=4;  /* increase this colors popularity */
7911             i+=MagickMax((long) (image->colors >> 4),2);
7912           }
7913           diversity[image->colors-1].count<<=4;
7914           qsort((void *) diversity,image->colors,sizeof(*diversity),
7915             PopularityCompare);
7916           /*
7917             Allocate colors.
7918           */
7919           p=colors;
7920           color.flags=(char) (DoRed | DoGreen | DoBlue);
7921           for (i=0; i < (long) image->colors; i++)
7922           {
7923             index=diversity[i].index;
7924             color.red=
7925               ScaleQuantumToShort(XRedGamma(image->colormap[index].red));
7926             color.green=
7927               ScaleQuantumToShort(XGreenGamma(image->colormap[index].green));
7928             color.blue=
7929               ScaleQuantumToShort(XBlueGamma(image->colormap[index].blue));
7930             if (visual_info->klass != PseudoColor)
7931               {
7932                 gray_value=(unsigned short) XPixelIntensity(&color);
7933                 color.red=gray_value;
7934                 color.green=gray_value;
7935                 color.blue=gray_value;
7936               }
7937             status=XAllocColor(display,colormap,&color);
7938             if (status == False)
7939               break;
7940             pixel->pixels[index]=color.pixel;
7941             *p++=color;
7942           }
7943           /*
7944             Read X server colormap.
7945           */
7946           server_colors=(XColor *) AcquireQuantumMemory((size_t)
7947             visual_info->colormap_size,sizeof(*server_colors));
7948           if (server_colors == (XColor *) NULL)
7949             ThrowXWindowFatalException(ResourceLimitFatalError,
7950               "UnableToCreateColormap",image->filename);
7951           for (x=visual_info->colormap_size-1; x >= 0; x--)
7952             server_colors[x].pixel=(unsigned long) x;
7953           (void) XQueryColors(display,colormap,server_colors,
7954             (int) MagickMin((unsigned int) visual_info->colormap_size,256));
7955           /*
7956             Select remaining colors from X server colormap.
7957           */
7958           for (; i < (long) image->colors; i++)
7959           {
7960             index=diversity[i].index;
7961             color.red=
7962               ScaleQuantumToShort(XRedGamma(image->colormap[index].red));
7963             color.green=
7964               ScaleQuantumToShort(XGreenGamma(image->colormap[index].green));
7965             color.blue=
7966               ScaleQuantumToShort(XBlueGamma(image->colormap[index].blue));
7967             if (visual_info->klass != PseudoColor)
7968               {
7969                 gray_value=(unsigned short) XPixelIntensity(&color);
7970                 color.red=gray_value;
7971                 color.green=gray_value;
7972                 color.blue=gray_value;
7973               }
7974             XBestPixel(display,colormap,server_colors,(unsigned int)
7975               visual_info->colormap_size,&color);
7976             pixel->pixels[index]=color.pixel;
7977             *p++=color;
7978           }
7979           if ((int) image->colors < visual_info->colormap_size)
7980             {
7981               /*
7982                 Fill up colors array-- more choices for pen colors.
7983               */
7984               retain_colors=MagickMin((unsigned int)
7985                (visual_info->colormap_size-image->colors),256);
7986               for (i=0; i < (long) retain_colors; i++)
7987                 *p++=server_colors[i];
7988               number_colors+=retain_colors;
7989             }
7990           server_colors=(XColor *) RelinquishMagickMemory(server_colors);
7991           diversity=(DiversityPacket *) RelinquishMagickMemory(diversity);
7992           break;
7993         }
7994       /*
7995         Define Standard colormap for private GrayScale or PseudoColor visual.
7996       */
7997       if (status == False)
7998         {
7999           /*
8000             Not enough colormap entries in the colormap-- Create a new colormap.
8001           */
8002           colormap=XCreateColormap(display,
8003             XRootWindow(display,visual_info->screen),visual_info->visual,
8004             AllocNone);
8005           if (colormap == (Colormap) NULL)
8006             ThrowXWindowFatalException(ResourceLimitFatalError,
8007               "UnableToCreateColormap",image->filename);
8008           map_info->colormap=colormap;
8009           if ((int) image->colors < visual_info->colormap_size)
8010             {
8011               /*
8012                 Retain colors from the default colormap to help lessens the
8013                 effects of colormap flashing.
8014               */
8015               retain_colors=MagickMin((unsigned int)
8016                 (visual_info->colormap_size-image->colors),256);
8017               p=colors+image->colors;
8018               for (i=0; i < (long) retain_colors; i++)
8019               {
8020                 p->pixel=(unsigned long) i;
8021                 p++;
8022               }
8023               (void) XQueryColors(display,
8024                 XDefaultColormap(display,visual_info->screen),
8025                 colors+image->colors,(int) retain_colors);
8026               /*
8027                 Transfer colors from default to private colormap.
8028               */
8029               (void) XAllocColorCells(display,colormap,MagickFalse,
8030                 (unsigned long *) NULL,0,pixel->pixels,(unsigned int)
8031                 retain_colors);
8032               p=colors+image->colors;
8033               for (i=0; i < (long) retain_colors; i++)
8034               {
8035                 p->pixel=pixel->pixels[i];
8036                 p++;
8037               }
8038               (void) XStoreColors(display,colormap,colors+image->colors,
8039                 (int) retain_colors);
8040               number_colors+=retain_colors;
8041             }
8042           (void) XAllocColorCells(display,colormap,MagickFalse,
8043             (unsigned long *) NULL,0,pixel->pixels,(unsigned int)
8044             image->colors);
8045         }
8046       /*
8047         Store the image colormap.
8048       */
8049       p=colors;
8050       color.flags=(char) (DoRed | DoGreen | DoBlue);
8051       for (i=0; i < (long) image->colors; i++)
8052       {
8053         color.red=ScaleQuantumToShort(XRedGamma(image->colormap[i].red));
8054         color.green=ScaleQuantumToShort(XGreenGamma(image->colormap[i].green));
8055         color.blue=ScaleQuantumToShort(XBlueGamma(image->colormap[i].blue));
8056         if (visual_info->klass != PseudoColor)
8057           {
8058             gray_value=(unsigned short) XPixelIntensity(&color);
8059             color.red=gray_value;
8060             color.green=gray_value;
8061             color.blue=gray_value;
8062           }
8063         color.pixel=pixel->pixels[i];
8064         *p++=color;
8065       }
8066       (void) XStoreColors(display,colormap,colors,(int) image->colors);
8067       break;
8068     }
8069     case TrueColor:
8070     case DirectColor:
8071     default:
8072     {
8073       MagickBooleanType
8074         linear_colormap;
8075
8076       /*
8077         Define Standard Colormap for TrueColor or DirectColor visual.
8078       */
8079       number_colors=(unsigned int) ((map_info->red_max*map_info->red_mult)+
8080         (map_info->green_max*map_info->green_mult)+
8081         (map_info->blue_max*map_info->blue_mult)+1);
8082       linear_colormap=(number_colors > 4096) ||
8083         (((int) (map_info->red_max+1) == visual_info->colormap_size) &&
8084          ((int) (map_info->green_max+1) == visual_info->colormap_size) &&
8085          ((int) (map_info->blue_max+1) == visual_info->colormap_size)) ?
8086          MagickTrue : MagickFalse;
8087       if (linear_colormap != MagickFalse)
8088         number_colors=(unsigned long) visual_info->colormap_size;
8089       /*
8090         Allocate color array.
8091       */
8092       colors=(XColor *) AcquireQuantumMemory(number_colors,sizeof(*colors));
8093       if (colors == (XColor *) NULL)
8094         ThrowXWindowFatalException(ResourceLimitFatalError,
8095           "UnableToCreateColormap",image->filename);
8096       /*
8097         Initialize linear color ramp.
8098       */
8099       p=colors;
8100       color.flags=(char) (DoRed | DoGreen | DoBlue);
8101       if (linear_colormap != MagickFalse)
8102         for (i=0; i < (long) number_colors; i++)
8103         {
8104           color.blue=(unsigned short) 0;
8105           if (map_info->blue_max != 0)
8106             color.blue=(unsigned short) ((unsigned long)
8107               ((65535L*(i % map_info->green_mult))/map_info->blue_max));
8108           color.green=color.blue;
8109           color.red=color.blue;
8110           color.pixel=XStandardPixel(map_info,&color);
8111           *p++=color;
8112         }
8113       else
8114         for (i=0; i < (long) number_colors; i++)
8115         {
8116           color.red=(unsigned short) 0;
8117           if (map_info->red_max != 0)
8118             color.red=(unsigned short) ((unsigned long)
8119               ((65535L*(i/map_info->red_mult))/map_info->red_max));
8120           color.green=(unsigned int) 0;
8121           if (map_info->green_max != 0)
8122             color.green=(unsigned short) ((unsigned long)
8123               ((65535L*((i/map_info->green_mult) % (map_info->green_max+1)))/
8124                 map_info->green_max));
8125           color.blue=(unsigned short) 0;
8126           if (map_info->blue_max != 0)
8127             color.blue=(unsigned short) ((unsigned long)
8128               ((65535L*(i % map_info->green_mult))/map_info->blue_max));
8129           color.pixel=XStandardPixel(map_info,&color);
8130           *p++=color;
8131         }
8132       if ((visual_info->klass == DirectColor) &&
8133           (colormap != XDefaultColormap(display,visual_info->screen)))
8134         (void) XStoreColors(display,colormap,colors,(int) number_colors);
8135       else
8136         for (i=0; i < (long) number_colors; i++)
8137           (void) XAllocColor(display,colormap,&colors[i]);
8138       break;
8139     }
8140   }
8141   if ((visual_info->klass != DirectColor) &&
8142       (visual_info->klass != TrueColor))
8143     {
8144       /*
8145         Set foreground, background, border, etc. pixels.
8146       */
8147       XBestPixel(display,colormap,colors,(unsigned int) number_colors,
8148         &pixel->foreground_color);
8149       XBestPixel(display,colormap,colors,(unsigned int) number_colors,
8150         &pixel->background_color);
8151       if (pixel->background_color.pixel == pixel->foreground_color.pixel)
8152         {
8153           /*
8154             Foreground and background colors must differ.
8155           */
8156           pixel->background_color.red=(~pixel->foreground_color.red);
8157           pixel->background_color.green=
8158             (~pixel->foreground_color.green);
8159           pixel->background_color.blue=
8160             (~pixel->foreground_color.blue);
8161           XBestPixel(display,colormap,colors,(unsigned int) number_colors,
8162             &pixel->background_color);
8163         }
8164       XBestPixel(display,colormap,colors,(unsigned int) number_colors,
8165         &pixel->border_color);
8166       XBestPixel(display,colormap,colors,(unsigned int) number_colors,
8167         &pixel->matte_color);
8168       XBestPixel(display,colormap,colors,(unsigned int) number_colors,
8169         &pixel->highlight_color);
8170       XBestPixel(display,colormap,colors,(unsigned int) number_colors,
8171         &pixel->shadow_color);
8172       XBestPixel(display,colormap,colors,(unsigned int) number_colors,
8173         &pixel->depth_color);
8174       XBestPixel(display,colormap,colors,(unsigned int) number_colors,
8175         &pixel->trough_color);
8176       for (i=0; i < MaxNumberPens; i++)
8177       {
8178         XBestPixel(display,colormap,colors,(unsigned int) number_colors,
8179           &pixel->pen_colors[i]);
8180         pixel->pixels[image->colors+i]=pixel->pen_colors[i].pixel;
8181       }
8182       pixel->colors=image->colors+MaxNumberPens;
8183     }
8184   colors=(XColor *) RelinquishMagickMemory(colors);
8185   if (IsEventLogging())
8186     {
8187       (void) LogMagickEvent(X11Event,GetMagickModule(),"Standard Colormap:");
8188       (void) LogMagickEvent(X11Event,GetMagickModule(),"  colormap id: 0x%lx",
8189         map_info->colormap);
8190       (void) LogMagickEvent(X11Event,GetMagickModule(),
8191         "  red, green, blue max: %lu %lu %lu",map_info->red_max,
8192         map_info->green_max,map_info->blue_max);
8193       (void) LogMagickEvent(X11Event,GetMagickModule(),
8194         "  red, green, blue mult: %lu %lu %lu",map_info->red_mult,
8195         map_info->green_mult,map_info->blue_mult);
8196     }
8197 }
8198 \f
8199 /*
8200 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8201 %                                                                             %
8202 %                                                                             %
8203 %                                                                             %
8204 %   X M a k e W i n d o w                                                     %
8205 %                                                                             %
8206 %                                                                             %
8207 %                                                                             %
8208 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8209 %
8210 %  XMakeWindow() creates an X11 window.
8211 %
8212 %  The format of the XMakeWindow method is:
8213 %
8214 %      void XMakeWindow(Display *display,Window parent,char **argv,int argc,
8215 %        XClassHint *class_hint,XWMHints *manager_hints,
8216 %        XWindowInfo *window_info)
8217 %
8218 %  A description of each parameter follows:
8219 %
8220 %    o display: Specifies a connection to an X server; returned from
8221 %      XOpenDisplay.
8222 %
8223 %    o parent: Specifies the parent window_info.
8224 %
8225 %    o argv: Specifies the application's argument list.
8226 %
8227 %    o argc: Specifies the number of arguments.
8228 %
8229 %    o class_hint: Specifies a pointer to a X11 XClassHint structure.
8230 %
8231 %    o manager_hints: Specifies a pointer to a X11 XWMHints structure.
8232 %
8233 %    o window_info: Specifies a pointer to a X11 XWindowInfo structure.
8234 %
8235 */
8236 MagickExport void XMakeWindow(Display *display,Window parent,char **argv,
8237   int argc,XClassHint *class_hint,XWMHints *manager_hints,
8238   XWindowInfo *window_info)
8239 {
8240 #define MinWindowSize  64
8241
8242   Atom
8243     atom_list[2];
8244
8245   int
8246     gravity;
8247
8248   static XTextProperty
8249     icon_name,
8250     window_name;
8251
8252   Status
8253     status;
8254
8255   XSizeHints
8256     *size_hints;
8257
8258   /*
8259     Set window info hints.
8260   */
8261   (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
8262   assert(display != (Display *) NULL);
8263   assert(window_info != (XWindowInfo *) NULL);
8264   size_hints=XAllocSizeHints();
8265   if (size_hints == (XSizeHints *) NULL)
8266     ThrowXWindowFatalException(XServerFatalError,"UnableToMakeXWindow",argv[0]);
8267   size_hints->flags=(long) window_info->flags;
8268   size_hints->x=window_info->x;
8269   size_hints->y=window_info->y;
8270   size_hints->width=(int) window_info->width;
8271   size_hints->height=(int) window_info->height;
8272   if (window_info->immutable != MagickFalse)
8273     {
8274       /*
8275         Window size cannot be changed.
8276       */
8277       size_hints->min_width=size_hints->width;
8278       size_hints->min_height=size_hints->height;
8279       size_hints->max_width=size_hints->width;
8280       size_hints->max_height=size_hints->height;
8281       size_hints->flags|=PMinSize;
8282       size_hints->flags|=PMaxSize;
8283     }
8284   else
8285     {
8286       /*
8287         Window size can be changed.
8288       */
8289       size_hints->min_width=(int) window_info->min_width;
8290       size_hints->min_height=(int) window_info->min_height;
8291       size_hints->flags|=PResizeInc;
8292       size_hints->width_inc=(int) window_info->width_inc;
8293       size_hints->height_inc=(int) window_info->height_inc;
8294 #if !defined(PRE_R4_ICCCM)
8295       size_hints->flags|=PBaseSize;
8296       size_hints->base_width=size_hints->width_inc;
8297       size_hints->base_height=size_hints->height_inc;
8298 #endif
8299     }
8300   gravity=NorthWestGravity;
8301   if (window_info->geometry != (char *) NULL)
8302     {
8303       char
8304         default_geometry[MaxTextExtent],
8305         geometry[MaxTextExtent];
8306
8307       int
8308         flags;
8309
8310       register char
8311         *p;
8312
8313       /*
8314         User specified geometry.
8315       */
8316       (void) FormatMagickString(default_geometry,MaxTextExtent,"%dx%d",
8317         size_hints->width,size_hints->height);
8318       (void) CopyMagickString(geometry,window_info->geometry,MaxTextExtent);
8319       p=geometry;
8320       while (strlen(p) != 0)
8321       {
8322         if ((isspace((int) ((unsigned char) *p)) == 0) && (*p != '%'))
8323           p++;
8324         else
8325           (void) CopyMagickString(p,p+1,MaxTextExtent);
8326       }
8327       flags=XWMGeometry(display,window_info->screen,geometry,default_geometry,
8328         window_info->border_width,size_hints,&size_hints->x,&size_hints->y,
8329         &size_hints->width,&size_hints->height,&gravity);
8330       if ((flags & WidthValue) && (flags & HeightValue))
8331         size_hints->flags|=USSize;
8332       if ((flags & XValue) && (flags & YValue))
8333         {
8334           size_hints->flags|=USPosition;
8335           window_info->x=size_hints->x;
8336           window_info->y=size_hints->y;
8337         }
8338     }
8339 #if !defined(PRE_R4_ICCCM)
8340   size_hints->win_gravity=gravity;
8341   size_hints->flags|=PWinGravity;
8342 #endif
8343   if (window_info->id == (Window) NULL)
8344     window_info->id=XCreateWindow(display,parent,window_info->x,window_info->y,
8345       (unsigned int) size_hints->width,(unsigned int) size_hints->height,
8346       window_info->border_width,(int) window_info->depth,InputOutput,
8347       window_info->visual,window_info->mask,&window_info->attributes);
8348   else
8349     {
8350       MagickStatusType
8351         mask;
8352
8353       XEvent
8354         sans_event;
8355
8356       XWindowChanges
8357         window_changes;
8358
8359       /*
8360         Window already exists;  change relevant attributes.
8361       */
8362       (void) XChangeWindowAttributes(display,window_info->id,window_info->mask,
8363         &window_info->attributes);
8364       mask=ConfigureNotify;
8365       while (XCheckTypedWindowEvent(display,window_info->id,(int) mask,&sans_event)) ;
8366       window_changes.x=window_info->x;
8367       window_changes.y=window_info->y;
8368       window_changes.width=(int) window_info->width;
8369       window_changes.height=(int) window_info->height;
8370       mask=(MagickStatusType) (CWWidth | CWHeight);
8371       if (window_info->flags & USPosition)
8372         mask|=CWX | CWY;
8373       (void) XReconfigureWMWindow(display,window_info->id,window_info->screen,
8374         mask,&window_changes);
8375     }
8376   if (window_info->id == (Window) NULL)
8377     ThrowXWindowFatalException(XServerFatalError,"UnableToCreateWindow",
8378       window_info->name);
8379   status=XStringListToTextProperty(&window_info->name,1,&window_name);
8380   if (status == False)
8381     ThrowXWindowFatalException(XServerFatalError,"UnableToCreateTextProperty",
8382       window_info->name);
8383   status=XStringListToTextProperty(&window_info->icon_name,1,&icon_name);
8384   if (status == False)
8385     ThrowXWindowFatalException(XServerFatalError,"UnableToCreateTextProperty",
8386       window_info->icon_name);
8387   if (window_info->icon_geometry != (char *) NULL)
8388     {
8389       int
8390         flags,
8391         height,
8392         width;
8393
8394       /*
8395         User specified icon geometry.
8396       */
8397       size_hints->flags|=USPosition;
8398       flags=XWMGeometry(display,window_info->screen,window_info->icon_geometry,
8399         (char *) NULL,0,size_hints,&manager_hints->icon_x,
8400         &manager_hints->icon_y,&width,&height,&gravity);
8401       if ((flags & XValue) && (flags & YValue))
8402         manager_hints->flags|=IconPositionHint;
8403     }
8404   XSetWMProperties(display,window_info->id,&window_name,&icon_name,argv,argc,
8405     size_hints,manager_hints,class_hint);
8406   if (window_name.value != (void *) NULL)
8407     {
8408       (void) XFree((void *) window_name.value);
8409       window_name.value=(unsigned char *) NULL;
8410       window_name.nitems=0;
8411     }
8412   if (icon_name.value != (void *) NULL)
8413     {
8414       (void) XFree((void *) icon_name.value);
8415       icon_name.value=(unsigned char *) NULL;
8416       icon_name.nitems=0;
8417     }
8418   atom_list[0]=XInternAtom(display,"WM_DELETE_WINDOW",MagickFalse);
8419   atom_list[1]=XInternAtom(display,"WM_TAKE_FOCUS",MagickFalse);
8420   (void) XSetWMProtocols(display,window_info->id,atom_list,2);
8421   (void) XFree((void *) size_hints);
8422   if (window_info->shape != MagickFalse)
8423     {
8424 #if defined(MAGICKCORE_HAVE_SHAPE)
8425       int
8426         error_base,
8427         event_base;
8428
8429       /*
8430         Can we apply a non-rectangular shaping mask?
8431       */
8432       error_base=0;
8433       event_base=0;
8434       if (XShapeQueryExtension(display,&error_base,&event_base) == 0)
8435         window_info->shape=MagickFalse;
8436 #else
8437       window_info->shape=MagickFalse;
8438 #endif
8439     }
8440   if (window_info->shared_memory)
8441     {
8442 #if defined(MAGICKCORE_HAVE_SHARED_MEMORY)
8443       /*
8444         Can we use shared memory with this window?
8445       */
8446       if (XShmQueryExtension(display) == 0)
8447         window_info->shared_memory=MagickFalse;
8448 #else
8449       window_info->shared_memory=MagickFalse;
8450 #endif
8451     }
8452   window_info->image=NewImageList();
8453   window_info->destroy=MagickFalse;
8454 }
8455 \f
8456 /*
8457 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8458 %                                                                             %
8459 %                                                                             %
8460 %                                                                             %
8461 %   X M a g i c k P r o g r e s s M o n i t o r                               %
8462 %                                                                             %
8463 %                                                                             %
8464 %                                                                             %
8465 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8466 %
8467 %  XMagickProgressMonitor() displays the progress a task is making in
8468 %  completing a task.
8469 %
8470 %  The format of the XMagickProgressMonitor method is:
8471 %
8472 %      void XMagickProgressMonitor(const char *task,
8473 %        const MagickOffsetType quantum,const MagickSizeType span,
8474 %        void *client_data)
8475 %
8476 %  A description of each parameter follows:
8477 %
8478 %    o task: Identifies the task in progress.
8479 %
8480 %    o quantum: Specifies the quantum position within the span which represents
8481 %      how much progress has been made in completing a task.
8482 %
8483 %    o span: Specifies the span relative to completing a task.
8484 %
8485 %    o client_data: Pointer to any client data.
8486 %
8487 */
8488
8489 static const char *GetLocaleMonitorMessage(const char *text)
8490 {
8491   char
8492     message[MaxTextExtent],
8493     tag[MaxTextExtent];
8494
8495   const char
8496     *locale_message;
8497
8498   register char
8499     *p;
8500
8501   (void) CopyMagickMemory(tag,text,MaxTextExtent);
8502   p=strrchr(tag,'/');
8503   if (p != (char *) NULL)
8504     *p='\0';
8505   (void) FormatMagickString(message,MaxTextExtent,"Monitor/%s",tag);
8506   locale_message=GetLocaleMessage(message);
8507   if (locale_message == message)
8508     return(text);
8509   return(locale_message);
8510 }
8511
8512 MagickExport MagickBooleanType XMagickProgressMonitor(const char *tag,
8513   const MagickOffsetType quantum,const MagickSizeType span,
8514   void *magick_unused(client_data))
8515 {
8516   XWindows
8517     *windows;
8518
8519   windows=XSetWindows((XWindows *) ~0);
8520   if (windows == (XWindows *) NULL)
8521     return(MagickTrue);
8522   if (windows->info.mapped != MagickFalse)
8523     XProgressMonitorWidget(windows->display,windows,
8524       GetLocaleMonitorMessage(tag),quantum,span);
8525   return(MagickTrue);
8526 }
8527 \f
8528 /*
8529 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8530 %                                                                             %
8531 %                                                                             %
8532 %                                                                             %
8533 %   X Q u e r y C o l o r D a t a b a s e                                     %
8534 %                                                                             %
8535 %                                                                             %
8536 %                                                                             %
8537 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8538 %
8539 %  XQueryColorDatabase() looks up a RGB values for a color given in the target
8540 %  string.
8541 %
8542 %  The format of the XQueryColorDatabase method is:
8543 %
8544 %      MagickBooleanType XQueryColorDatabase(const char *target,XColor *color)
8545 %
8546 %  A description of each parameter follows:
8547 %
8548 %    o target: Specifies the color to lookup in the X color database.
8549 %
8550 %    o color: A pointer to an PixelPacket structure.  The RGB value of the target
8551 %      color is returned as this value.
8552 %
8553 */
8554 MagickExport MagickBooleanType XQueryColorDatabase(const char *target,
8555   XColor *color)
8556 {
8557   Colormap
8558     colormap;
8559
8560   static Display
8561     *display = (Display *) NULL;
8562
8563   Status
8564     status;
8565
8566   XColor
8567     xcolor;
8568
8569   /*
8570     Initialize color return value.
8571   */
8572   assert(color != (XColor *) NULL);
8573   color->red=0;
8574   color->green=0;
8575   color->blue=0;
8576   color->flags=(char) (DoRed | DoGreen | DoBlue);
8577   if ((target == (char *) NULL) || (*target == '\0'))
8578     target="#ffffffffffff";
8579   /*
8580     Let the X server define the color for us.
8581   */
8582   if (display == (Display *) NULL)
8583     display=XOpenDisplay((char *) NULL);
8584   if (display == (Display *) NULL)
8585     {
8586       ThrowXWindowFatalException(XServerError,"ColorIsNotKnownToServer",target);
8587       return(MagickFalse);
8588     }
8589   colormap=XDefaultColormap(display,XDefaultScreen(display));
8590   status=XParseColor(display,colormap,(char *) target,&xcolor);
8591   if (status == False)
8592     ThrowXWindowFatalException(XServerError,"ColorIsNotKnownToServer",target)
8593   else
8594     {
8595       color->red=xcolor.red;
8596       color->green=xcolor.green;
8597       color->blue=xcolor.blue;
8598       color->flags=xcolor.flags;
8599     }
8600   return(status != False ? MagickTrue : MagickFalse);
8601 }
8602 \f
8603 /*
8604 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8605 %                                                                             %
8606 %                                                                             %
8607 %                                                                             %
8608 %   X Q u e r y P o s i t i o n                                               %
8609 %                                                                             %
8610 %                                                                             %
8611 %                                                                             %
8612 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8613 %
8614 %  XQueryPosition() gets the pointer coordinates relative to a window.
8615 %
8616 %  The format of the XQueryPosition method is:
8617 %
8618 %      void XQueryPosition(Display *display,const Window window,int *x,int *y)
8619 %
8620 %  A description of each parameter follows:
8621 %
8622 %    o display: Specifies a connection to an X server;  returned from
8623 %      XOpenDisplay.
8624 %
8625 %    o window: Specifies a pointer to a Window.
8626 %
8627 %    o x: Return the x coordinate of the pointer relative to the origin of the
8628 %      window.
8629 %
8630 %    o y: Return the y coordinate of the pointer relative to the origin of the
8631 %      window.
8632 %
8633 */
8634 MagickExport void XQueryPosition(Display *display,const Window window,int *x,int *y)
8635 {
8636   int
8637     x_root,
8638     y_root;
8639
8640   unsigned int
8641     mask;
8642
8643   Window
8644     root_window;
8645
8646   (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
8647   assert(display != (Display *) NULL);
8648   assert(window != (Window) NULL);
8649   assert(x != (int *) NULL);
8650   assert(y != (int *) NULL);
8651   (void) XQueryPointer(display,window,&root_window,&root_window,&x_root,&y_root,
8652     x,y,&mask);
8653 }
8654 \f
8655 /*
8656 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8657 %                                                                             %
8658 %                                                                             %
8659 %                                                                             %
8660 %   X R e f r e s h W i n d o w                                               %
8661 %                                                                             %
8662 %                                                                             %
8663 %                                                                             %
8664 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8665 %
8666 %  XRefreshWindow() refreshes an image in a X window.
8667 %
8668 %  The format of the XRefreshWindow method is:
8669 %
8670 %      void XRefreshWindow(Display *display,const XWindowInfo *window,
8671 %        const XEvent *event)
8672 %
8673 %  A description of each parameter follows:
8674 %
8675 %    o display: Specifies a connection to an X server;  returned from
8676 %      XOpenDisplay.
8677 %
8678 %    o window: Specifies a pointer to a XWindowInfo structure.
8679 %
8680 %    o event: Specifies a pointer to a XEvent structure.  If it is NULL,
8681 %      the entire image is refreshed.
8682 %
8683 */
8684 MagickExport void XRefreshWindow(Display *display,const XWindowInfo *window,
8685   const XEvent *event)
8686 {
8687   int
8688     x,
8689     y;
8690
8691   unsigned int
8692     height,
8693     width;
8694
8695   (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
8696   assert(display != (Display *) NULL);
8697   assert(window != (XWindowInfo *) NULL);
8698   if (window->ximage == (XImage *) NULL)
8699     return;
8700   if (event != (XEvent *) NULL)
8701     {
8702       /*
8703         Determine geometry from expose event.
8704       */
8705       x=event->xexpose.x;
8706       y=event->xexpose.y;
8707       width=(unsigned int) event->xexpose.width;
8708       height=(unsigned int) event->xexpose.height;
8709     }
8710   else
8711     {
8712       XEvent
8713         sans_event;
8714
8715       /*
8716         Refresh entire window; discard outstanding expose events.
8717       */
8718       x=0;
8719       y=0;
8720       width=window->width;
8721       height=window->height;
8722       while (XCheckTypedWindowEvent(display,window->id,Expose,&sans_event)) ;
8723     }
8724   /*
8725     Check boundary conditions.
8726   */
8727   if ((window->ximage->width-(x+window->x)) < (int) width)
8728     width=(unsigned int) (window->ximage->width-(x+window->x));
8729   if ((window->ximage->height-(y+window->y)) < (int) height)
8730     height=(unsigned int) (window->ximage->height-(y+window->y));
8731   /*
8732     Refresh image.
8733   */
8734   if (window->matte_pixmap != (Pixmap) NULL)
8735     {
8736 #if defined(MAGICKCORE_HAVE_SHAPE)
8737       if (window->shape != MagickFalse)
8738         XShapeCombineMask(display,window->id,ShapeBounding,0,0,
8739           window->matte_pixmap,ShapeSet);
8740 #endif
8741       (void) XSetClipMask(display,window->annotate_context,
8742         window->matte_pixmap);
8743     }
8744   if (window->pixmap != (Pixmap) NULL)
8745     {
8746       if (window->depth > 1)
8747         (void) XCopyArea(display,window->pixmap,window->id,
8748           window->annotate_context,x+window->x,y+window->y,width,height,x,y);
8749       else
8750         (void) XCopyPlane(display,window->pixmap,window->id,
8751           window->highlight_context,x+window->x,y+window->y,width,height,x,y,
8752           1L);
8753     }
8754   else
8755     {
8756 #if defined(MAGICKCORE_HAVE_SHARED_MEMORY)
8757       if (window->shared_memory)
8758         (void) XShmPutImage(display,window->id,window->annotate_context,
8759           window->ximage,x+window->x,y+window->y,x,y,width,height,MagickTrue);
8760 #endif
8761       if (window->shared_memory == MagickFalse)
8762         (void) XPutImage(display,window->id,window->annotate_context,
8763           window->ximage,x+window->x,y+window->y,x,y,width,height);
8764     }
8765   if (window->matte_pixmap != (Pixmap) NULL)
8766     (void) XSetClipMask(display,window->annotate_context,None);
8767   (void) XFlush(display);
8768 }
8769 \f
8770 /*
8771 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8772 %                                                                             %
8773 %                                                                             %
8774 %                                                                             %
8775 %   X R e m o t e C o m m a n d                                               %
8776 %                                                                             %
8777 %                                                                             %
8778 %                                                                             %
8779 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8780 %
8781 %  XRemoteCommand() forces a remote display(1) to display the specified
8782 %  image filename.
8783 %
8784 %  The format of the XRemoteCommand method is:
8785 %
8786 %      MagickBooleanType XRemoteCommand(Display *display,const char *window,
8787 %        const char *filename)
8788 %
8789 %  A description of each parameter follows:
8790 %
8791 %    o display: Specifies a connection to an X server; returned from
8792 %      XOpenDisplay.
8793 %
8794 %    o window: Specifies the name or id of an X window.
8795 %
8796 %    o filename: the name of the image filename to display.
8797 %
8798 */
8799 MagickExport MagickBooleanType XRemoteCommand(Display *display,
8800   const char *window,const char *filename)
8801 {
8802   Atom
8803     remote_atom;
8804
8805   Window
8806     remote_window,
8807     root_window;
8808
8809   assert(filename != (char *) NULL);
8810   (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",filename);
8811   if (display == (Display *) NULL)
8812     display=XOpenDisplay((char *) NULL);
8813   if (display == (Display *) NULL)
8814     {
8815       ThrowXWindowException(XServerError,"UnableToOpenXServer",filename);
8816       return(MagickFalse);
8817     }
8818   remote_atom=XInternAtom(display,"IM_PROTOCOLS",MagickFalse);
8819   remote_window=(Window) NULL;
8820   root_window=XRootWindow(display,XDefaultScreen(display));
8821   if (window != (char *) NULL)
8822     {
8823       /*
8824         Search window hierarchy and identify any clients by name or ID.
8825       */
8826       if (isdigit((unsigned char) *window) != 0)
8827         remote_window=XWindowByID(display,root_window,(Window)
8828           strtol((char *) window,(char **) NULL,0));
8829       if (remote_window == (Window) NULL)
8830         remote_window=XWindowByName(display,root_window,window);
8831     }
8832   if (remote_window == (Window) NULL)
8833     remote_window=XWindowByProperty(display,root_window,remote_atom);
8834   if (remote_window == (Window) NULL)
8835     {
8836       ThrowXWindowException(XServerError,"UnableToConnectToRemoteDisplay",
8837         filename);
8838       return(MagickFalse);
8839     }
8840   /*
8841     Send remote command.
8842   */
8843   remote_atom=XInternAtom(display,"IM_REMOTE_COMMAND",MagickFalse);
8844   (void) XChangeProperty(display,remote_window,remote_atom,XA_STRING,8,
8845     PropModeReplace,(unsigned char *) filename,(int) strlen(filename));
8846   (void) XSync(display,MagickFalse);
8847   return(MagickTrue);
8848 }
8849 \f
8850 /*
8851 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8852 %                                                                             %
8853 %                                                                             %
8854 %                                                                             %
8855 %   X R e t a i n W i n d o w C o l o r s                                     %
8856 %                                                                             %
8857 %                                                                             %
8858 %                                                                             %
8859 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8860 %
8861 %  XRetainWindowColors() sets X11 color resources on a window.  This preserves
8862 %  the colors associated with an image displayed on the window.
8863 %
8864 %  The format of the XRetainWindowColors method is:
8865 %
8866 %      void XRetainWindowColors(Display *display,const Window window)
8867 %
8868 %  A description of each parameter follows:
8869 %
8870 %    o display: Specifies a connection to an X server; returned from
8871 %      XOpenDisplay.
8872 %
8873 %    o window: Specifies a pointer to a XWindowInfo structure.
8874 %
8875 */
8876 MagickExport void XRetainWindowColors(Display *display,const Window window)
8877 {
8878   Atom
8879     property;
8880
8881   Pixmap
8882     pixmap;
8883
8884   /*
8885     Put property on the window.
8886   */
8887   (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
8888   assert(display != (Display *) NULL);
8889   assert(window != (Window) NULL);
8890   property=XInternAtom(display,"_XSETROOT_ID",MagickFalse);
8891   if (property == (Atom) NULL)
8892     {
8893       ThrowXWindowFatalException(XServerError,"UnableToCreateProperty",
8894         "_XSETROOT_ID");
8895       return;
8896     }
8897   pixmap=XCreatePixmap(display,window,1,1,1);
8898   if (pixmap == (Pixmap) NULL)
8899     {
8900       ThrowXWindowFatalException(XServerError,"UnableToCreateBitmap","");
8901       return;
8902     }
8903   (void) XChangeProperty(display,window,property,XA_PIXMAP,32,PropModeReplace,
8904     (unsigned char *) &pixmap,1);
8905   (void) XSetCloseDownMode(display,RetainPermanent);
8906 }
8907 \f
8908 /*
8909 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8910 %                                                                             %
8911 %                                                                             %
8912 %                                                                             %
8913 %   X S e l e c t W i n d o w                                                 %
8914 %                                                                             %
8915 %                                                                             %
8916 %                                                                             %
8917 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8918 %
8919 %  XSelectWindow() allows a user to select a window using the mouse.  If the
8920 %  mouse moves, a cropping rectangle is drawn and the extents of the rectangle
8921 %  is returned in the crop_info structure.
8922 %
8923 %  The format of the XSelectWindow function is:
8924 %
8925 %      target_window=XSelectWindow(display,crop_info)
8926 %
8927 %  A description of each parameter follows:
8928 %
8929 %    o window: XSelectWindow returns the window id.
8930 %
8931 %    o display: Specifies a pointer to the Display structure;  returned from
8932 %      XOpenDisplay.
8933 %
8934 %    o crop_info: Specifies a pointer to a RectangleInfo structure.  It
8935 %      contains the extents of any cropping rectangle.
8936 %
8937 %
8938 */
8939 static Window XSelectWindow(Display *display,RectangleInfo *crop_info)
8940 {
8941 #define MinimumCropArea  (unsigned int) 9
8942
8943   Cursor
8944     target_cursor;
8945
8946   GC
8947     annotate_context;
8948
8949   int
8950     presses,
8951     x_offset,
8952     y_offset;
8953
8954   Status
8955     status;
8956
8957   Window
8958     root_window,
8959     target_window;
8960
8961   XEvent
8962     event;
8963
8964   XGCValues
8965     context_values;
8966
8967   /*
8968     Initialize graphic context.
8969   */
8970   (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
8971   assert(display != (Display *) NULL);
8972   assert(crop_info != (RectangleInfo *) NULL);
8973   root_window=XRootWindow(display,XDefaultScreen(display));
8974   context_values.background=XBlackPixel(display,XDefaultScreen(display));
8975   context_values.foreground=XWhitePixel(display,XDefaultScreen(display));
8976   context_values.function=GXinvert;
8977   context_values.plane_mask=
8978     context_values.background ^ context_values.foreground;
8979   context_values.subwindow_mode=IncludeInferiors;
8980   annotate_context=XCreateGC(display,root_window,(unsigned long) (GCBackground |
8981     GCForeground | GCFunction | GCSubwindowMode),&context_values);
8982   if (annotate_context == (GC) NULL)
8983     return(MagickFalse);
8984   /*
8985     Grab the pointer using target cursor.
8986   */
8987   target_cursor=XMakeCursor(display,root_window,XDefaultColormap(display,
8988     XDefaultScreen(display)),(char * ) "white",(char * ) "black");
8989   status=XGrabPointer(display,root_window,MagickFalse,(unsigned int)
8990     (ButtonPressMask | ButtonReleaseMask | ButtonMotionMask),GrabModeSync,
8991     GrabModeAsync,root_window,target_cursor,CurrentTime);
8992   if (status != GrabSuccess)
8993     {
8994       ThrowXWindowFatalException(XServerError,"UnableToGrabMouse","");
8995       return((Window) NULL);
8996     }
8997   /*
8998     Select a window.
8999   */
9000   crop_info->width=0;
9001   crop_info->height=0;
9002   presses=0;
9003   target_window=(Window) NULL;
9004   x_offset=0;
9005   y_offset=0;
9006   do
9007   {
9008     if ((crop_info->width*crop_info->height) >= MinimumCropArea)
9009       (void) XDrawRectangle(display,root_window,annotate_context,
9010         (int) crop_info->x,(int) crop_info->y,(unsigned int) crop_info->width-1,
9011         (unsigned int) crop_info->height-1);
9012     /*
9013       Allow another event.
9014     */
9015     (void) XAllowEvents(display,SyncPointer,CurrentTime);
9016     (void) XWindowEvent(display,root_window,ButtonPressMask |
9017       ButtonReleaseMask | ButtonMotionMask,&event);
9018     if ((crop_info->width*crop_info->height) >= MinimumCropArea)
9019       (void) XDrawRectangle(display,root_window,annotate_context,
9020         (int) crop_info->x,(int) crop_info->y,(unsigned int) crop_info->width-1,
9021         (unsigned int) crop_info->height-1);
9022     switch (event.type)
9023     {
9024       case ButtonPress:
9025       {
9026         target_window=XGetSubwindow(display,event.xbutton.subwindow,
9027           event.xbutton.x,event.xbutton.y);
9028         if (target_window == (Window) NULL)
9029           target_window=root_window;
9030         x_offset=event.xbutton.x_root;
9031         y_offset=event.xbutton.y_root;
9032         crop_info->x=x_offset;
9033         crop_info->y=y_offset;
9034         crop_info->width=0;
9035         crop_info->height=0;
9036         presses++;
9037         break;
9038       }
9039       case ButtonRelease:
9040       {
9041         presses--;
9042         break;
9043       }
9044       case MotionNotify:
9045       {
9046         /*
9047           Discard pending button motion events.
9048         */
9049         while (XCheckMaskEvent(display,ButtonMotionMask,&event)) ;
9050         crop_info->x=event.xmotion.x;
9051         crop_info->y=event.xmotion.y;
9052         /*
9053           Check boundary conditions.
9054         */
9055         if ((int) crop_info->x < x_offset)
9056           crop_info->width=(unsigned int) (x_offset-crop_info->x);
9057         else
9058           {
9059             crop_info->width=(unsigned int) (crop_info->x-x_offset);
9060             crop_info->x=x_offset;
9061           }
9062         if ((int) crop_info->y < y_offset)
9063           crop_info->height=(unsigned int) (y_offset-crop_info->y);
9064         else
9065           {
9066             crop_info->height=(unsigned int) (crop_info->y-y_offset);
9067             crop_info->y=y_offset;
9068           }
9069       }
9070       default:
9071         break;
9072     }
9073   } while ((target_window == (Window) NULL) || (presses > 0));
9074   (void) XUngrabPointer(display,CurrentTime);
9075   (void) XFreeCursor(display,target_cursor);
9076   (void) XFreeGC(display,annotate_context);
9077   if ((crop_info->width*crop_info->height) < MinimumCropArea)
9078     {
9079       crop_info->width=0;
9080       crop_info->height=0;
9081     }
9082   if ((crop_info->width != 0) && (crop_info->height != 0))
9083     target_window=root_window;
9084   return(target_window);
9085 }
9086 \f
9087 /*
9088 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9089 %                                                                             %
9090 %                                                                             %
9091 %                                                                             %
9092 %   X S e t C u r s o r S t a t e                                             %
9093 %                                                                             %
9094 %                                                                             %
9095 %                                                                             %
9096 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9097 %
9098 %  XSetCursorState() sets the cursor state to busy, otherwise the cursor are
9099 %  reset to their default.
9100 %
9101 %  The format of the XXSetCursorState method is:
9102 %
9103 %      XSetCursorState(display,windows,const MagickStatusType state)
9104 %
9105 %  A description of each parameter follows:
9106 %
9107 %    o display: Specifies a connection to an X server;  returned from
9108 %      XOpenDisplay.
9109 %
9110 %    o windows: Specifies a pointer to a XWindows structure.
9111 %
9112 %    o state: An unsigned integer greater than 0 sets the cursor state
9113 %      to busy, otherwise the cursor are reset to their default.
9114 %
9115 */
9116 MagickExport void XSetCursorState(Display *display,XWindows *windows,
9117   const MagickStatusType state)
9118 {
9119   (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
9120   assert(display != (Display *) NULL);
9121   assert(windows != (XWindows *) NULL);
9122   if (state)
9123     {
9124       (void) XCheckDefineCursor(display,windows->image.id,
9125         windows->image.busy_cursor);
9126       (void) XCheckDefineCursor(display,windows->pan.id,
9127         windows->pan.busy_cursor);
9128       (void) XCheckDefineCursor(display,windows->magnify.id,
9129         windows->magnify.busy_cursor);
9130       (void) XCheckDefineCursor(display,windows->command.id,
9131         windows->command.busy_cursor);
9132     }
9133   else
9134     {
9135       (void) XCheckDefineCursor(display,windows->image.id,
9136         windows->image.cursor);
9137       (void) XCheckDefineCursor(display,windows->pan.id,windows->pan.cursor);
9138       (void) XCheckDefineCursor(display,windows->magnify.id,
9139         windows->magnify.cursor);
9140       (void) XCheckDefineCursor(display,windows->command.id,
9141         windows->command.cursor);
9142       (void) XCheckDefineCursor(display,windows->command.id,
9143         windows->widget.cursor);
9144       (void) XWithdrawWindow(display,windows->info.id,windows->info.screen);
9145     }
9146   windows->info.mapped=MagickFalse;
9147 }
9148 \f
9149 /*
9150 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9151 %                                                                             %
9152 %                                                                             %
9153 %                                                                             %
9154 %   X S e t W i n d o w s                                                     %
9155 %                                                                             %
9156 %                                                                             %
9157 %                                                                             %
9158 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9159 %
9160 %  XSetWindows() sets the X windows structure if the windows info is specified.
9161 %  Otherwise the current windows structure is returned.
9162 %
9163 %  The format of the XSetWindows method is:
9164 %
9165 %      XWindows *XSetWindows(XWindows *windows_info)
9166 %
9167 %  A description of each parameter follows:
9168 %
9169 %    o windows_info: Initialize the Windows structure with this information.
9170 %
9171 */
9172 MagickExport XWindows *XSetWindows(XWindows *windows_info)
9173 {
9174   static XWindows
9175     *windows = (XWindows *) NULL;
9176
9177   if (windows_info != (XWindows *) ~0)
9178     {
9179       windows=(XWindows *) RelinquishMagickMemory(windows);
9180       windows=windows_info;
9181     }
9182   return(windows);
9183 }
9184 /*
9185 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9186 %                                                                             %
9187 %                                                                             %
9188 %                                                                             %
9189 %   X U s e r P r e f e r e n c e s                                           %
9190 %                                                                             %
9191 %                                                                             %
9192 %                                                                             %
9193 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9194 %
9195 %  XUserPreferences() saves the preferences in a configuration file in the
9196 %  users' home directory.
9197 %
9198 %  The format of the XUserPreferences method is:
9199 %
9200 %      void XUserPreferences(XResourceInfo *resource_info)
9201 %
9202 %  A description of each parameter follows:
9203 %
9204 %    o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
9205 %
9206 */
9207 MagickExport void XUserPreferences(XResourceInfo *resource_info)
9208 {
9209 #if defined(X11_PREFERENCES_PATH)
9210   char
9211     cache[MaxTextExtent],
9212     filename[MaxTextExtent],
9213     specifier[MaxTextExtent];
9214
9215   const char
9216     *client_name,
9217     *value;
9218
9219   XrmDatabase
9220     preferences_database;
9221
9222   /*
9223     Save user preferences to the client configuration file.
9224   */
9225   assert(resource_info != (XResourceInfo *) NULL);
9226   client_name=GetClientName();
9227   preferences_database=XrmGetStringDatabase("");
9228   (void) FormatMagickString(specifier,MaxTextExtent,"%s.backdrop",client_name);
9229   value=resource_info->backdrop ? "True" : "False";
9230   XrmPutStringResource(&preferences_database,specifier,(char *) value);
9231   (void) FormatMagickString(specifier,MaxTextExtent,"%s.colormap",client_name);
9232   value=resource_info->colormap == SharedColormap ? "Shared" : "Private";
9233   XrmPutStringResource(&preferences_database,specifier,(char *) value);
9234   (void) FormatMagickString(specifier,MaxTextExtent,"%s.confirmExit",
9235     client_name);
9236   value=resource_info->confirm_exit ? "True" : "False";
9237   XrmPutStringResource(&preferences_database,specifier,(char *) value);
9238   (void) FormatMagickString(specifier,MaxTextExtent,"%s.confirmEdit",
9239     client_name);
9240   value=resource_info->confirm_edit ? "True" : "False";
9241   XrmPutStringResource(&preferences_database,specifier,(char *) value);
9242   (void) FormatMagickString(specifier,MaxTextExtent,"%s.displayWarnings",
9243     client_name);
9244   value=resource_info->display_warnings ? "True" : "False";
9245   XrmPutStringResource(&preferences_database,specifier,(char *) value);
9246   (void) FormatMagickString(specifier,MaxTextExtent,"%s.dither",client_name);
9247   value=resource_info->quantize_info->dither ? "True" : "False";
9248   XrmPutStringResource(&preferences_database,specifier,(char *) value);
9249   (void) FormatMagickString(specifier,MaxTextExtent,"%s.gammaCorrect",
9250     client_name);
9251   value=resource_info->gamma_correct ? "True" : "False";
9252   XrmPutStringResource(&preferences_database,specifier,(char *) value);
9253   (void) FormatMagickString(specifier,MaxTextExtent,"%s.undoCache",client_name);
9254   (void) FormatMagickString(cache,MaxTextExtent,"%lu",
9255     resource_info->undo_cache);
9256   XrmPutStringResource(&preferences_database,specifier,cache);
9257   (void) FormatMagickString(specifier,MaxTextExtent,"%s.usePixmap",client_name);
9258   value=resource_info->use_pixmap ? "True" : "False";
9259   XrmPutStringResource(&preferences_database,specifier,(char *) value);
9260   (void) FormatMagickString(filename,MaxTextExtent,"%s%src",
9261     X11_PREFERENCES_PATH,client_name);
9262   ExpandFilename(filename);
9263   XrmPutFileDatabase(preferences_database,filename);
9264 #endif
9265 }
9266 \f
9267 /*
9268 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9269 %                                                                             %
9270 %                                                                             %
9271 %                                                                             %
9272 %   X V i s u a l C l a s s N a m e                                           %
9273 %                                                                             %
9274 %                                                                             %
9275 %                                                                             %
9276 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9277 %
9278 %  XVisualClassName() returns the visual class name as a character string.
9279 %
9280 %  The format of the XVisualClassName method is:
9281 %
9282 %      char *XVisualClassName(const int visual_class)
9283 %
9284 %  A description of each parameter follows:
9285 %
9286 %    o visual_type: XVisualClassName returns the visual class as a character
9287 %      string.
9288 %
9289 %    o class: Specifies the visual class.
9290 %
9291 %
9292 */
9293 static const char *XVisualClassName(const int visual_class)
9294 {
9295   switch (visual_class)
9296   {
9297     case StaticGray: return("StaticGray");
9298     case GrayScale: return("GrayScale");
9299     case StaticColor: return("StaticColor");
9300     case PseudoColor: return("PseudoColor");
9301     case TrueColor: return("TrueColor");
9302     case DirectColor: return("DirectColor");
9303   }
9304   return("unknown visual class");
9305 }
9306 \f
9307 /*
9308 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9309 %                                                                             %
9310 %                                                                             %
9311 %                                                                             %
9312 %   X W a r n i n g                                                           %
9313 %                                                                             %
9314 %                                                                             %
9315 %                                                                             %
9316 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9317 %
9318 %  XWarning() displays a warning reason in a Notice widget.
9319 %
9320 %  The format of the XWarning method is:
9321 %
9322 %      void XWarning(const unsigned int warning,const char *reason,
9323 %        const char *description)
9324 %
9325 %  A description of each parameter follows:
9326 %
9327 %    o warning: Specifies the numeric warning category.
9328 %
9329 %    o reason: Specifies the reason to display before terminating the
9330 %      program.
9331 %
9332 %    o description: Specifies any description to the reason.
9333 %
9334 */
9335 MagickExport void XWarning(const ExceptionType magick_unused(warning),
9336   const char *reason,const char *description)
9337 {
9338   char
9339     text[MaxTextExtent];
9340
9341   XWindows
9342     *windows;
9343
9344   if (reason == (char *) NULL)
9345     return;
9346   (void) CopyMagickString(text,reason,MaxTextExtent);
9347   (void) ConcatenateMagickString(text,":",MaxTextExtent);
9348   windows=XSetWindows((XWindows *) ~0);
9349   XNoticeWidget(windows->display,windows,text,(char *) description);
9350 }
9351 \f
9352 /*
9353 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9354 %                                                                             %
9355 %                                                                             %
9356 %                                                                             %
9357 %   X W i n d o w B y I D                                                     %
9358 %                                                                             %
9359 %                                                                             %
9360 %                                                                             %
9361 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9362 %
9363 %  XWindowByID() locates a child window with a given ID.  If not window with
9364 %  the given name is found, 0 is returned.   Only the window specified and its
9365 %  subwindows are searched.
9366 %
9367 %  The format of the XWindowByID function is:
9368 %
9369 %      child=XWindowByID(display,window,id)
9370 %
9371 %  A description of each parameter follows:
9372 %
9373 %    o child: XWindowByID returns the window with the specified
9374 %      id.  If no windows are found, XWindowByID returns 0.
9375 %
9376 %    o display: Specifies a pointer to the Display structure;  returned from
9377 %      XOpenDisplay.
9378 %
9379 %    o id: Specifies the id of the window to locate.
9380 %
9381 */
9382 MagickExport Window XWindowByID(Display *display,const Window root_window,
9383   const unsigned long id)
9384 {
9385   RectangleInfo
9386     rectangle_info;
9387
9388   register int
9389     i;
9390
9391   Status
9392     status;
9393
9394   unsigned int
9395     number_children;
9396
9397   Window
9398     child,
9399     *children,
9400     window;
9401
9402   (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
9403   assert(display != (Display *) NULL);
9404   assert(root_window != (Window) NULL);
9405   if (id == 0)
9406     return(XSelectWindow(display,&rectangle_info));
9407   if (root_window == id)
9408     return(id);
9409   status=XQueryTree(display,root_window,&child,&child,&children,
9410     &number_children);
9411   if (status == False)
9412     return((Window) NULL);
9413   window=(Window) NULL;
9414   for (i=0; i < (int) number_children; i++)
9415   {
9416     /*
9417       Search each child and their children.
9418     */
9419     window=XWindowByID(display,children[i],id);
9420     if (window != (Window) NULL)
9421       break;
9422   }
9423   if (children != (Window *) NULL)
9424     (void) XFree((void *) children);
9425   return(window);
9426 }
9427 \f
9428 /*
9429 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9430 %                                                                             %
9431 %                                                                             %
9432 %                                                                             %
9433 %   X W i n d o w B y N a m e                                                 %
9434 %                                                                             %
9435 %                                                                             %
9436 %                                                                             %
9437 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9438 %
9439 %  XWindowByName() locates a window with a given name on a display.  If no
9440 %  window with the given name is found, 0 is returned. If more than one window
9441 %  has the given name, the first one is returned.  Only root and its children
9442 %  are searched.
9443 %
9444 %  The format of the XWindowByName function is:
9445 %
9446 %      window=XWindowByName(display,root_window,name)
9447 %
9448 %  A description of each parameter follows:
9449 %
9450 %    o window: XWindowByName returns the window id.
9451 %
9452 %    o display: Specifies a pointer to the Display structure;  returned from
9453 %      XOpenDisplay.
9454 %
9455 %    o root_window: Specifies the id of the root window.
9456 %
9457 %    o name: Specifies the name of the window to locate.
9458 %
9459 */
9460 MagickExport Window XWindowByName(Display *display,const Window root_window,
9461   const char *name)
9462 {
9463   register int
9464     i;
9465
9466   Status
9467     status;
9468
9469   unsigned int
9470     number_children;
9471
9472   Window
9473     *children,
9474     child,
9475     window;
9476
9477   XTextProperty
9478     window_name;
9479
9480   assert(display != (Display *) NULL);
9481   assert(root_window != (Window) NULL);
9482   assert(name != (char *) NULL);
9483   (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",name);
9484   if (XGetWMName(display,root_window,&window_name) != 0)
9485     if (LocaleCompare((char *) window_name.value,name) == 0)
9486       return(root_window);
9487   status=XQueryTree(display,root_window,&child,&child,&children,
9488     &number_children);
9489   if (status == False)
9490     return((Window) NULL);
9491   window=(Window) NULL;
9492   for (i=0; i < (int) number_children; i++)
9493   {
9494     /*
9495       Search each child and their children.
9496     */
9497     window=XWindowByName(display,children[i],name);
9498     if (window != (Window) NULL)
9499       break;
9500   }
9501   if (children != (Window *) NULL)
9502     (void) XFree((void *) children);
9503   return(window);
9504 }
9505 \f
9506 /*
9507 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9508 %                                                                             %
9509 %                                                                             %
9510 %                                                                             %
9511 %   X W i n d o w B y P r o p e r y                                           %
9512 %                                                                             %
9513 %                                                                             %
9514 %                                                                             %
9515 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9516 %
9517 %  XWindowByProperty() locates a child window with a given property. If not
9518 %  window with the given name is found, 0 is returned.  If more than one window
9519 %  has the given property, the first one is returned.  Only the window
9520 %  specified and its subwindows are searched.
9521 %
9522 %  The format of the XWindowByProperty function is:
9523 %
9524 %      child=XWindowByProperty(display,window,property)
9525 %
9526 %  A description of each parameter follows:
9527 %
9528 %    o child: XWindowByProperty returns the window id with the specified
9529 %      property.  If no windows are found, XWindowByProperty returns 0.
9530 %
9531 %    o display: Specifies a pointer to the Display structure;  returned from
9532 %      XOpenDisplay.
9533 %
9534 %    o property: Specifies the property of the window to locate.
9535 %
9536 */
9537 MagickExport Window XWindowByProperty(Display *display,const Window window,
9538   const Atom property)
9539 {
9540   Atom
9541     type;
9542
9543   int
9544     format;
9545
9546   Status
9547     status;
9548
9549   unsigned char
9550     *data;
9551
9552   unsigned int
9553     i,
9554     number_children;
9555
9556   unsigned long
9557     after,
9558     number_items;
9559
9560   Window
9561     child,
9562     *children,
9563     parent,
9564     root;
9565
9566   (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
9567   assert(display != (Display *) NULL);
9568   assert(window != (Window) NULL);
9569   assert(property != (Atom) NULL);
9570   status=XQueryTree(display,window,&root,&parent,&children,&number_children);
9571   if (status == False)
9572     return((Window) NULL);
9573   type=(Atom) NULL;
9574   child=(Window) NULL;
9575   for (i=0; (i < number_children) && (child == (Window) NULL); i++)
9576   {
9577     status=XGetWindowProperty(display,children[i],property,0L,0L,MagickFalse,
9578       (Atom) AnyPropertyType,&type,&format,&number_items,&after,&data);
9579     if (data != NULL)
9580       (void) XFree((void *) data);
9581     if ((status == Success) && (type != (Atom) NULL))
9582       child=children[i];
9583   }
9584   for (i=0; (i < number_children) && (child == (Window) NULL); i++)
9585     child=XWindowByProperty(display,children[i],property);
9586   if (children != (Window *) NULL)
9587     (void) XFree((void *) children);
9588   return(child);
9589 }
9590 #else
9591 \f
9592 /*
9593 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9594 %                                                                             %
9595 %                                                                             %
9596 %                                                                             %
9597 %   X I m p o r t I m a g e                                                   %
9598 %                                                                             %
9599 %                                                                             %
9600 %                                                                             %
9601 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9602 %
9603 %  XImportImage() reads an image from an X window.
9604 %
9605 %  The format of the XImportImage method is:
9606 %
9607 %      Image *XImportImage(const ImageInfo *image_info,XImportInfo *ximage_info)
9608 %
9609 %  A description of each parameter follows:
9610 %
9611 %    o image_info: the image info..
9612 %
9613 %    o ximage_info: Specifies a pointer to an XImportInfo structure.
9614 %
9615 */
9616 MagickExport Image *XImportImage(const ImageInfo *image_info,
9617   XImportInfo *ximage_info)
9618 {
9619   assert(image_info != (const ImageInfo *) NULL);
9620   assert(image_info->signature == MagickSignature);
9621   if (image_info->debug != MagickFalse)
9622     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
9623       image_info->filename);
9624   assert(ximage_info != (XImportInfo *) NULL);
9625   return((Image *) NULL);
9626 }
9627 #endif
9628 \f
9629 /*
9630 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9631 %                                                                             %
9632 %                                                                             %
9633 %                                                                             %
9634 +   X C o m p o n e n t G e n e s i s                                         %
9635 %                                                                             %
9636 %                                                                             %
9637 %                                                                             %
9638 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9639 %
9640 %  XComponentGenesis() instantiates the X component.
9641 %
9642 %  The format of the XComponentGenesis method is:
9643 %
9644 %      MagickBooleanType XComponentGenesis(void)
9645 %
9646 */
9647 MagickExport MagickBooleanType XComponentGenesis(void)
9648 {
9649   return(MagickTrue);
9650 }
9651 \f
9652 /*
9653 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9654 %                                                                             %
9655 %                                                                             %
9656 %                                                                             %
9657 %   X G e t I m p o r t I n f o                                               %
9658 %                                                                             %
9659 %                                                                             %
9660 %                                                                             %
9661 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9662 %
9663 %  XGetImportInfo() initializes the XImportInfo structure.
9664 %
9665 %  The format of the XGetImportInfo method is:
9666 %
9667 %      void XGetImportInfo(XImportInfo *ximage_info)
9668 %
9669 %  A description of each parameter follows:
9670 %
9671 %    o ximage_info: Specifies a pointer to an ImageInfo structure.
9672 %
9673 */
9674 MagickExport void XGetImportInfo(XImportInfo *ximage_info)
9675 {
9676   assert(ximage_info != (XImportInfo *) NULL);
9677   ximage_info->frame=MagickFalse;
9678   ximage_info->borders=MagickFalse;
9679   ximage_info->screen=MagickFalse;
9680   ximage_info->descend=MagickTrue;
9681   ximage_info->silent=MagickFalse;
9682 }