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