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