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