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