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