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