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