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