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