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