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