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