]> granicus.if.org Git - imagemagick/blob - MagickCore/xwindow.c
7584f3a3fee11600fb533dd0c266b9e74648089f
[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 double
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   PixelTrait
483     alpha_trait;
484
485   Pixmap
486     annotate_pixmap;
487
488   unsigned int
489     depth,
490     height,
491     width;
492
493   Window
494     root_window;
495
496   XGCValues
497     context_values;
498
499   XImage
500     *annotate_ximage;
501
502   /*
503     Initialize annotated image.
504   */
505   (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
506   assert(display != (Display *) NULL);
507   assert(pixel != (XPixelInfo *) NULL);
508   assert(annotate_info != (XAnnotateInfo *) NULL);
509   assert(image != (Image *) NULL);
510   /*
511     Initialize annotated pixmap.
512   */
513   root_window=XRootWindow(display,XDefaultScreen(display));
514   depth=(unsigned int) XDefaultDepth(display,XDefaultScreen(display));
515   annotate_pixmap=XCreatePixmap(display,root_window,annotate_info->width,
516     annotate_info->height,depth);
517   if (annotate_pixmap == (Pixmap) NULL)
518     return(MagickFalse);
519   /*
520     Initialize graphics info.
521   */
522   context_values.background=0;
523   context_values.foreground=(size_t) (~0);
524   context_values.font=annotate_info->font_info->fid;
525   annotate_context=XCreateGC(display,root_window,(unsigned long)
526     (GCBackground | GCFont | GCForeground),&context_values);
527   if (annotate_context == (GC) NULL)
528     return(MagickFalse);
529   /*
530     Draw text to pixmap.
531   */
532   (void) XDrawImageString(display,annotate_pixmap,annotate_context,0,
533     (int) annotate_info->font_info->ascent,annotate_info->text,
534     (int) strlen(annotate_info->text));
535   (void) XFreeGC(display,annotate_context);
536   /*
537     Initialize annotated X image.
538   */
539   annotate_ximage=XGetImage(display,annotate_pixmap,0,0,annotate_info->width,
540     annotate_info->height,AllPlanes,ZPixmap);
541   if (annotate_ximage == (XImage *) NULL)
542     return(MagickFalse);
543   (void) XFreePixmap(display,annotate_pixmap);
544   /*
545     Initialize annotated image.
546   */
547   annotate_image=AcquireImage((ImageInfo *) NULL,exception);
548   if (annotate_image == (Image *) NULL)
549     return(MagickFalse);
550   annotate_image->columns=annotate_info->width;
551   annotate_image->rows=annotate_info->height;
552   /*
553     Transfer annotated X image to image.
554   */
555   width=(unsigned int) image->columns;
556   height=(unsigned int) image->rows;
557   x=0;
558   y=0;
559   (void) XParseGeometry(annotate_info->geometry,&x,&y,&width,&height);
560   (void) GetOneVirtualPixelInfo(image,UndefinedVirtualPixelMethod,(ssize_t) x,
561     (ssize_t) y,&annotate_image->background_color,exception);
562   if (annotate_info->stencil == ForegroundStencil)
563     annotate_image->alpha_trait=BlendPixelTrait;
564   annotate_view=AcquireAuthenticCacheView(annotate_image,exception);
565   for (y=0; y < (int) annotate_image->rows; y++)
566   {
567     register int
568       x;
569
570     register Quantum
571       *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       double
643         normalized_degrees;
644
645       /*
646         Rotate image.
647       */
648       rotate_image=RotateImage(annotate_image,annotate_info->degrees,exception);
649       if (rotate_image == (Image *) NULL)
650         return(MagickFalse);
651       annotate_image=DestroyImage(annotate_image);
652       annotate_image=rotate_image;
653       /*
654         Annotation is relative to the degree of rotation.
655       */
656       normalized_degrees=annotate_info->degrees;
657       while (normalized_degrees < -45.0)
658         normalized_degrees+=360.0;
659       for (rotations=0; normalized_degrees > 45.0; rotations++)
660         normalized_degrees-=90.0;
661       switch (rotations % 4)
662       {
663         default:
664         case 0:
665           break;
666         case 1:
667         {
668           /*
669             Rotate 90 degrees.
670           */
671           x-=(int) annotate_image->columns/2;
672           y+=(int) annotate_image->columns/2;
673           break;
674         }
675         case 2:
676         {
677           /*
678             Rotate 180 degrees.
679           */
680           x=x-(int) annotate_image->columns;
681           break;
682         }
683         case 3:
684         {
685           /*
686             Rotate 270 degrees.
687           */
688           x=x-(int) annotate_image->columns/2;
689           y=y-(int) (annotate_image->rows-(annotate_image->columns/2));
690           break;
691         }
692       }
693     }
694   /*
695     Composite text onto the image.
696   */
697   (void) XParseGeometry(annotate_info->geometry,&x,&y,&width,&height);
698   alpha_trait=image->alpha_trait;
699   (void) CompositeImage(image,annotate_image,
700     annotate_image->alpha_trait == BlendPixelTrait ? OverCompositeOp :
701     CopyCompositeOp,MagickTrue,(ssize_t) x,(ssize_t) y,exception);
702   image->alpha_trait=alpha_trait;
703   annotate_image=DestroyImage(annotate_image);
704   return(MagickTrue);
705 }
706 \f
707 /*
708 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
709 %                                                                             %
710 %                                                                             %
711 %                                                                             %
712 %   X B e s t F o n t                                                         %
713 %                                                                             %
714 %                                                                             %
715 %                                                                             %
716 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
717 %
718 %  XBestFont() returns the "best" font.  "Best" is defined as a font specified
719 %  in the X resource database or a font such that the text width displayed
720 %  with the font does not exceed the specified maximum width.
721 %
722 %  The format of the XBestFont method is:
723 %
724 %      XFontStruct *XBestFont(Display *display,
725 %        const XResourceInfo *resource_info,const MagickBooleanType text_font)
726 %
727 %  A description of each parameter follows:
728 %
729 %    o font: XBestFont returns a pointer to a XFontStruct structure.
730 %
731 %    o display: Specifies a connection to an X server;  returned from
732 %      XOpenDisplay.
733 %
734 %    o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
735 %
736 %    o text_font:  True is font should be mono-spaced (typewriter style).
737 %
738 */
739
740 static char **FontToList(char *font)
741 {
742   char
743     **fontlist;
744
745   register char
746     *p,
747     *q;
748
749   register int
750     i;
751
752   unsigned int
753     fonts;
754
755   if (font == (char *) NULL)
756     return((char **) NULL);
757   /*
758     Convert string to an ASCII list.
759   */
760   fonts=1U;
761   for (p=font; *p != '\0'; p++)
762     if ((*p == ':') || (*p == ';') || (*p == ','))
763       fonts++;
764   fontlist=(char **) AcquireQuantumMemory((size_t) fonts+1UL,sizeof(*fontlist));
765   if (fontlist == (char **) NULL)
766     {
767       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   double
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=(double) icon_size->max_width/width;
969   if (scale_factor > ((double) icon_size->max_height/height))
970     scale_factor=(double) 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   double
1038     min_distance;
1039
1040   register double
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*((double) QuantumRange+1.0)*((double)
1079     QuantumRange+1.0);
1080   j=0;
1081   for (i=0; i < (int) number_colors; i++)
1082   {
1083     pixel.red=colors[i].red-(double) color->red;
1084     distance=pixel.red*pixel.red;
1085     if (distance > min_distance)
1086       continue;
1087     pixel.green=colors[i].green-(double) color->green;
1088     distance+=pixel.green*pixel.green;
1089     if (distance > min_distance)
1090       continue;
1091     pixel.blue=colors[i].blue-(double) 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((double) (red_map[i][j][
2240         (int) ScaleQuantumToChar(GetPixelRed(image,p))] << 8));
2241       color.green=(double) ClampToQuantum((double) (green_map[i][j][
2242         (int) ScaleQuantumToChar(GetPixelGreen(image,p))] << 8));
2243       color.blue=(double) ClampToQuantum((double) (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   PixelTrait
2322     alpha_trait;
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->alpha_trait=BlendPixelTrait;
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       double
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       alpha_trait=image->alpha_trait;
2643       (void) CompositeImage(image,draw_image,OverCompositeOp,MagickTrue,
2644         (ssize_t) x,(ssize_t) y,exception);
2645       image->alpha_trait=alpha_trait;
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) (((double)
3163     pixel->matte_color.red*ScaleQuantumToShort(ShadowModulate))/65535L);
3164   pixel->shadow_color.green=(unsigned short) (((double)
3165     pixel->matte_color.green*ScaleQuantumToShort(ShadowModulate))/65535L);
3166   pixel->shadow_color.blue=(unsigned short) (((double)
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) (((double)
3174     pixel->matte_color.red*ScaleQuantumToShort(DepthModulate))/65535L);
3175   pixel->depth_color.green=(unsigned short) (((double)
3176     pixel->matte_color.green*ScaleQuantumToShort(DepthModulate))/65535L);
3177   pixel->depth_color.blue=(unsigned short) (((double)
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) (((double)
3185     pixel->matte_color.red*ScaleQuantumToShort(TroughModulate))/65535L);
3186   pixel->trough_color.green=(unsigned short) (((double)
3187     pixel->matte_color.green*ScaleQuantumToShort(TroughModulate))/65535L);
3188   pixel->trough_color.blue=(unsigned short) (((double)
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 *) "False");
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 *) "256");
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->alpha_trait == BlendPixelTrait) &&
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->alpha_trait == BlendPixelTrait))
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])) < (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) GetPixelBlue(canvas,p));
6335                   *q++=ScaleQuantumToChar((Quantum) GetPixelGreen(canvas,p));
6336                   *q++=ScaleQuantumToChar((Quantum) GetPixelRed(canvas,p));
6337                   *q++=0;
6338                   p+=GetPixelChannels(canvas);
6339                 }
6340               }
6341             }
6342           else
6343             if ((ximage->bits_per_pixel == 32) && (map_info->red_max == 255) &&
6344                 (map_info->green_max == 255) && (map_info->blue_max == 255) &&
6345                 (map_info->red_mult == 1) && (map_info->green_mult == 256) &&
6346                 (map_info->blue_mult == 65536L))
6347               {
6348                 /*
6349                   Convert to 32 bit continuous-tone X canvas.
6350                 */
6351                 for (y=0; y < (int) canvas->rows; y++)
6352                 {
6353                   p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
6354                     canvas->columns,1,exception);
6355                   if (p == (const Quantum *) NULL)
6356                     break;
6357                   if ((red_gamma != 1.0) || (green_gamma != 1.0) ||
6358                       (blue_gamma != 1.0))
6359                     {
6360                       /*
6361                         Gamma correct canvas.
6362                       */
6363                       for (x=(int) canvas->columns-1; x >= 0; x--)
6364                       {
6365                         *q++=ScaleQuantumToChar(XRedGamma(
6366                           GetPixelRed(canvas,p)));
6367                         *q++=ScaleQuantumToChar(XGreenGamma(
6368                           GetPixelGreen(canvas,p)));
6369                         *q++=ScaleQuantumToChar(XBlueGamma(
6370                           GetPixelBlue(canvas,p)));
6371                         *q++=0;
6372                         p+=GetPixelChannels(canvas);
6373                       }
6374                       continue;
6375                     }
6376                   for (x=(int) canvas->columns-1; x >= 0; x--)
6377                   {
6378                     *q++=ScaleQuantumToChar((Quantum) GetPixelRed(canvas,p));
6379                     *q++=ScaleQuantumToChar((Quantum) GetPixelGreen(canvas,p));
6380                     *q++=ScaleQuantumToChar((Quantum) GetPixelBlue(canvas,p));
6381                     *q++=0;
6382                     p+=GetPixelChannels(canvas);
6383                   }
6384                 }
6385               }
6386             else
6387               {
6388                 register int
6389                   k;
6390
6391                 register unsigned int
6392                   bytes_per_pixel;
6393
6394                 unsigned char
6395                   channel[sizeof(size_t)];
6396
6397                 /*
6398                   Convert to multi-byte continuous-tone X canvas.
6399                 */
6400                 bytes_per_pixel=(unsigned int) (ximage->bits_per_pixel >> 3);
6401                 for (y=0; y < (int) canvas->rows; y++)
6402                 {
6403                   p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
6404                     canvas->columns,1,exception);
6405                   if (p == (const Quantum *) NULL)
6406                     break;
6407                   for (x=0; x < (int) canvas->columns; x++)
6408                   {
6409                     pixel=XGammaPixel(canvas,map_info,p);
6410                     for (k=0; k < (int) bytes_per_pixel; k++)
6411                     {
6412                       channel[k]=(unsigned char) pixel;
6413                       pixel>>=8;
6414                     }
6415                     for (k=0; k < (int) bytes_per_pixel; k++)
6416                       *q++=channel[k];
6417                     p+=GetPixelChannels(canvas);
6418                   }
6419                   q+=scanline_pad;
6420                 }
6421               }
6422           break;
6423         }
6424       }
6425   if (matte_image != (XImage *) NULL)
6426     {
6427       /*
6428         Initialize matte canvas.
6429       */
6430       scanline_pad=(unsigned int) (matte_image->bytes_per_line-
6431         ((matte_image->width*matte_image->bits_per_pixel) >> 3));
6432       q=(unsigned char *) matte_image->data;
6433       for (y=0; y < (int) canvas->rows; y++)
6434       {
6435         p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,canvas->columns,1,
6436           exception);
6437         if (p == (const Quantum *) NULL)
6438           break;
6439         bit=0;
6440         byte=0;
6441         for (x=(int) canvas->columns-1; x >= 0; x--)
6442         {
6443           byte>>=1;
6444           if (GetPixelAlpha(canvas,p) > (QuantumRange/2))
6445             byte|=0x80;
6446           bit++;
6447           if (bit == 8)
6448             {
6449               *q++=byte;
6450               bit=0;
6451               byte=0;
6452             }
6453           p+=GetPixelChannels(canvas);
6454         }
6455         if (bit != 0)
6456           *q=byte >> (8-bit);
6457         q+=scanline_pad;
6458       }
6459     }
6460   canvas_view=DestroyCacheView(canvas_view);
6461   if (canvas != image)
6462     canvas=DestroyImage(canvas);
6463 }
6464 \f
6465 /*
6466 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
6467 %                                                                             %
6468 %                                                                             %
6469 %                                                                             %
6470 +   X M a k e I m a g e M S B F i r s t                                       %
6471 %                                                                             %
6472 %                                                                             %
6473 %                                                                             %
6474 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
6475 %
6476 %  XMakeImageMSBFirst() initializes the pixel data of an X11 Image.  The X
6477 %  image pixels are copied in most-significant bit and byte first order.  The
6478 %  server's scanline pad is also respected. Rather than using one or two
6479 %  general cases, many special cases are found here to help speed up the image
6480 %  conversion.
6481 %
6482 %  The format of the XMakeImageMSBFirst method is:
6483 %
6484 %      XMakeImageMSBFirst(resource_info,window,image,ximage,matte_image,
6485 %        ExceptionInfo *exception)
6486 %
6487 %  A description of each parameter follows:
6488 %
6489 %    o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
6490 %
6491 %    o window: Specifies a pointer to a XWindowInfo structure.
6492 %
6493 %    o image: the image.
6494 %
6495 %    o ximage: Specifies a pointer to a XImage structure;  returned from
6496 %      XCreateImage.
6497 %
6498 %    o matte_image: Specifies a pointer to a XImage structure;  returned from
6499 %      XCreateImage.
6500 %
6501 %    o exception: return any errors or warnings in this structure.
6502 %
6503 */
6504 static void XMakeImageMSBFirst(const XResourceInfo *resource_info,
6505   const XWindowInfo *window,Image *image,XImage *ximage,XImage *matte_image,
6506   ExceptionInfo *exception)
6507 {
6508   CacheView
6509     *canvas_view;
6510
6511   Image
6512     *canvas;
6513
6514   int
6515     y;
6516
6517   register int
6518     x;
6519
6520   register const Quantum
6521     *p;
6522
6523   register unsigned char
6524     *q;
6525
6526   unsigned char
6527     bit,
6528     byte;
6529
6530   unsigned int
6531     scanline_pad;
6532
6533   unsigned long
6534     pixel,
6535     *pixels;
6536
6537   XStandardColormap
6538     *map_info;
6539
6540   assert(resource_info != (XResourceInfo *) NULL);
6541   assert(window != (XWindowInfo *) NULL);
6542   assert(image != (Image *) NULL);
6543   if (image->debug != MagickFalse)
6544     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
6545   canvas=image;
6546   if ((window->immutable != MagickFalse) &&
6547       (image->storage_class == DirectClass) && (image->alpha_trait == BlendPixelTrait))
6548     {
6549       char
6550         size[MaxTextExtent];
6551
6552       Image
6553         *pattern;
6554
6555       ImageInfo
6556         *image_info;
6557
6558       image_info=AcquireImageInfo();
6559       (void) CopyMagickString(image_info->filename,
6560         resource_info->image_info->texture != (char *) NULL ?
6561         resource_info->image_info->texture : "pattern:checkerboard",
6562         MaxTextExtent);
6563       (void) FormatLocaleString(size,MaxTextExtent,"%.20gx%.20g",(double)
6564         image->columns,(double) image->rows);
6565       image_info->size=ConstantString(size);
6566       pattern=ReadImage(image_info,exception);
6567       image_info=DestroyImageInfo(image_info);
6568       if (pattern != (Image *) NULL)
6569         {
6570           canvas=CloneImage(image,0,0,MagickTrue,exception);
6571           if (canvas != (Image *) NULL)
6572             (void) CompositeImage(canvas,pattern,DstOverCompositeOp,MagickFalse,
6573               0,0,exception);
6574           pattern=DestroyImage(pattern);
6575         }
6576     }
6577   scanline_pad=(unsigned int) (ximage->bytes_per_line-((ximage->width*
6578     ximage->bits_per_pixel) >> 3));
6579   map_info=window->map_info;
6580   pixels=window->pixel_info->pixels;
6581   q=(unsigned char *) ximage->data;
6582   x=0;
6583   canvas_view=AcquireVirtualCacheView(canvas,exception);
6584   if (ximage->format == XYBitmap)
6585     {
6586       register unsigned short
6587         polarity;
6588
6589       unsigned char
6590         background,
6591         foreground;
6592
6593       /*
6594         Convert canvas to big-endian bitmap.
6595       */
6596       background=(unsigned char)
6597         (XPixelIntensity(&window->pixel_info->foreground_color) <
6598          XPixelIntensity(&window->pixel_info->background_color) ?  0x01 : 0x00);
6599       foreground=(unsigned char)
6600         (XPixelIntensity(&window->pixel_info->background_color) <
6601          XPixelIntensity(&window->pixel_info->foreground_color) ?  0x01 : 0x00);
6602       polarity=(unsigned short) ((GetPixelInfoIntensity(
6603         &canvas->colormap[0])) < (QuantumRange/2) ? 1 : 0);
6604       if (canvas->colors == 2)
6605         polarity=GetPixelInfoIntensity(&canvas->colormap[0]) <
6606           GetPixelInfoIntensity(&canvas->colormap[1]);
6607       for (y=0; y < (int) canvas->rows; y++)
6608       {
6609         p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,canvas->columns,1,
6610           exception);
6611         if (p == (const Quantum *) NULL)
6612           break;
6613         bit=0;
6614         byte=0;
6615         for (x=(int) canvas->columns-1; x >= 0; x--)
6616         {
6617           byte<<=1;
6618           if (GetPixelIndex(canvas,p) == (Quantum) polarity)
6619             byte|=foreground;
6620           else
6621             byte|=background;
6622           bit++;
6623           if (bit == 8)
6624             {
6625               *q++=byte;
6626               bit=0;
6627               byte=0;
6628             }
6629           p+=GetPixelChannels(canvas);
6630         }
6631         if (bit != 0)
6632           *q=byte << (8-bit);
6633         q+=scanline_pad;
6634       }
6635     }
6636   else
6637     if (window->pixel_info->colors != 0)
6638       switch (ximage->bits_per_pixel)
6639       {
6640         case 2:
6641         {
6642           register unsigned int
6643             nibble;
6644
6645           /*
6646             Convert to 2 bit color-mapped X canvas.
6647           */
6648           for (y=0; y < (int) canvas->rows; y++)
6649           {
6650             p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
6651               canvas->columns,1,exception);
6652             if (p == (const Quantum *) NULL)
6653               break;
6654             nibble=0;
6655             for (x=0; x < (int) canvas->columns; x++)
6656             {
6657               pixel=pixels[(ssize_t)
6658                 GetPixelIndex(canvas,p)] & 0xf;
6659               switch (nibble)
6660               {
6661                 case 0:
6662                 {
6663                   *q=(unsigned char) (pixel << 6);
6664                   nibble++;
6665                   break;
6666                 }
6667                 case 1:
6668                 {
6669                   *q|=(unsigned char) (pixel << 4);
6670                   nibble++;
6671                   break;
6672                 }
6673                 case 2:
6674                 {
6675                   *q|=(unsigned char) (pixel << 2);
6676                   nibble++;
6677                   break;
6678                 }
6679                 case 3:
6680                 {
6681                   *q|=(unsigned char) pixel;
6682                   q++;
6683                   nibble=0;
6684                   break;
6685                 }
6686               }
6687               p+=GetPixelChannels(canvas);
6688             }
6689             q+=scanline_pad;
6690           }
6691           break;
6692         }
6693         case 4:
6694         {
6695           register unsigned int
6696             nibble;
6697
6698           /*
6699             Convert to 4 bit color-mapped X canvas.
6700           */
6701           for (y=0; y < (int) canvas->rows; y++)
6702           {
6703             p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
6704               canvas->columns,1,exception);
6705             if (p == (const Quantum *) NULL)
6706               break;
6707             nibble=0;
6708             for (x=0; x < (int) canvas->columns; x++)
6709             {
6710               pixel=pixels[(ssize_t)
6711                 GetPixelIndex(canvas,p)] & 0xf;
6712               switch (nibble)
6713               {
6714                 case 0:
6715                 {
6716                   *q=(unsigned char) (pixel << 4);
6717                   nibble++;
6718                   break;
6719                 }
6720                 case 1:
6721                 {
6722                   *q|=(unsigned char) pixel;
6723                   q++;
6724                   nibble=0;
6725                   break;
6726                 }
6727               }
6728               p+=GetPixelChannels(canvas);
6729             }
6730             q+=scanline_pad;
6731           }
6732           break;
6733         }
6734         case 6:
6735         case 8:
6736         {
6737           /*
6738             Convert to 8 bit color-mapped X canvas.
6739           */
6740           if (resource_info->color_recovery &&
6741               resource_info->quantize_info->dither_method != NoDitherMethod)
6742             {
6743               XDitherImage(canvas,ximage,exception);
6744               break;
6745             }
6746           for (y=0; y < (int) canvas->rows; y++)
6747           {
6748             p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
6749               canvas->columns,1,exception);
6750             if (p == (const Quantum *) NULL)
6751               break;
6752             for (x=0; x < (int) canvas->columns; x++)
6753             {
6754               pixel=pixels[(ssize_t) GetPixelIndex(canvas,p)];
6755               *q++=(unsigned char) pixel;
6756               p+=GetPixelChannels(canvas);
6757             }
6758             q+=scanline_pad;
6759           }
6760           break;
6761         }
6762         default:
6763         {
6764           register int
6765             k;
6766
6767           register unsigned int
6768             bytes_per_pixel;
6769
6770           unsigned char
6771             channel[sizeof(size_t)];
6772
6773           /*
6774             Convert to 8 bit color-mapped X canvas.
6775           */
6776           bytes_per_pixel=(unsigned int) (ximage->bits_per_pixel >> 3);
6777           for (y=0; y < (int) canvas->rows; y++)
6778           {
6779             p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
6780               canvas->columns,1,exception);
6781             if (p == (const Quantum *) NULL)
6782               break;
6783             for (x=0; x < (int) canvas->columns; x++)
6784             {
6785               pixel=pixels[(ssize_t)
6786                 GetPixelIndex(canvas,p)];
6787               for (k=(int) bytes_per_pixel-1; k >= 0; k--)
6788               {
6789                 channel[k]=(unsigned char) pixel;
6790                 pixel>>=8;
6791               }
6792               for (k=0; k < (int) bytes_per_pixel; k++)
6793                 *q++=channel[k];
6794               p+=GetPixelChannels(canvas);
6795             }
6796             q+=scanline_pad;
6797           }
6798           break;
6799         }
6800       }
6801     else
6802       switch (ximage->bits_per_pixel)
6803       {
6804         case 2:
6805         {
6806           register unsigned int
6807             nibble;
6808
6809           /*
6810             Convert to 4 bit continuous-tone X canvas.
6811           */
6812           for (y=0; y < (int) canvas->rows; y++)
6813           {
6814             p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
6815               canvas->columns,1,exception);
6816             if (p == (const Quantum *) NULL)
6817               break;
6818             nibble=0;
6819             for (x=(int) canvas->columns-1; x >= 0; x--)
6820             {
6821               pixel=XGammaPixel(canvas,map_info,p);
6822               pixel&=0xf;
6823               switch (nibble)
6824               {
6825                 case 0:
6826                 {
6827                   *q=(unsigned char) (pixel << 6);
6828                   nibble++;
6829                   break;
6830                 }
6831                 case 1:
6832                 {
6833                   *q|=(unsigned char) (pixel << 4);
6834                   nibble++;
6835                   break;
6836                 }
6837                 case 2:
6838                 {
6839                   *q|=(unsigned char) (pixel << 2);
6840                   nibble++;
6841                   break;
6842                 }
6843                 case 3:
6844                 {
6845                   *q|=(unsigned char) pixel;
6846                   q++;
6847                   nibble=0;
6848                   break;
6849                 }
6850               }
6851               p+=GetPixelChannels(canvas);
6852             }
6853             q+=scanline_pad;
6854           }
6855           break;
6856         }
6857         case 4:
6858         {
6859           register unsigned int
6860             nibble;
6861
6862           /*
6863             Convert to 4 bit continuous-tone X canvas.
6864           */
6865           for (y=0; y < (int) canvas->rows; y++)
6866           {
6867             p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
6868               canvas->columns,1,exception);
6869             if (p == (const Quantum *) NULL)
6870               break;
6871             nibble=0;
6872             for (x=(int) canvas->columns-1; x >= 0; x--)
6873             {
6874               pixel=XGammaPixel(canvas,map_info,p);
6875               pixel&=0xf;
6876               switch (nibble)
6877               {
6878                 case 0:
6879                 {
6880                   *q=(unsigned char) (pixel << 4);
6881                   nibble++;
6882                   break;
6883                 }
6884                 case 1:
6885                 {
6886                   *q|=(unsigned char) pixel;
6887                   q++;
6888                   nibble=0;
6889                   break;
6890                 }
6891               }
6892               p+=GetPixelChannels(canvas);
6893             }
6894             q+=scanline_pad;
6895           }
6896           break;
6897         }
6898         case 6:
6899         case 8:
6900         {
6901           /*
6902             Convert to 8 bit continuous-tone X canvas.
6903           */
6904           if (resource_info->color_recovery &&
6905               resource_info->quantize_info->dither_method != NoDitherMethod)
6906             {
6907               XDitherImage(canvas,ximage,exception);
6908               break;
6909             }
6910           for (y=0; y < (int) canvas->rows; y++)
6911           {
6912             p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
6913               canvas->columns,1,exception);
6914             if (p == (const Quantum *) NULL)
6915               break;
6916             for (x=(int) canvas->columns-1; x >= 0; x--)
6917             {
6918               pixel=XGammaPixel(canvas,map_info,p);
6919               *q++=(unsigned char) pixel;
6920               p+=GetPixelChannels(canvas);
6921             }
6922             q+=scanline_pad;
6923           }
6924           break;
6925         }
6926         default:
6927         {
6928           if ((ximage->bits_per_pixel == 32) && (map_info->red_max == 255) &&
6929               (map_info->green_max == 255) && (map_info->blue_max == 255) &&
6930               (map_info->red_mult == 65536L) && (map_info->green_mult == 256) &&
6931               (map_info->blue_mult == 1))
6932             {
6933               /*
6934                 Convert to 32 bit continuous-tone X canvas.
6935               */
6936               for (y=0; y < (int) canvas->rows; y++)
6937               {
6938                 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
6939                   canvas->columns,1,exception);
6940                 if (p == (const Quantum *) NULL)
6941                   break;
6942                 if ((red_gamma != 1.0) || (green_gamma != 1.0) ||
6943                     (blue_gamma != 1.0))
6944                   {
6945                     /*
6946                       Gamma correct canvas.
6947                     */
6948                     for (x=(int) canvas->columns-1; x >= 0; x--)
6949                     {
6950                       *q++=0;
6951                       *q++=ScaleQuantumToChar(XRedGamma(
6952                         GetPixelRed(canvas,p)));
6953                       *q++=ScaleQuantumToChar(XGreenGamma(
6954                         GetPixelGreen(canvas,p)));
6955                       *q++=ScaleQuantumToChar(XBlueGamma(
6956                         GetPixelBlue(canvas,p)));
6957                       p+=GetPixelChannels(canvas);
6958                     }
6959                     continue;
6960                   }
6961                 for (x=(int) canvas->columns-1; x >= 0; x--)
6962                 {
6963                   *q++=0;
6964                   *q++=ScaleQuantumToChar((Quantum) GetPixelRed(canvas,p));
6965                   *q++=ScaleQuantumToChar((Quantum) GetPixelGreen(canvas,p));
6966                   *q++=ScaleQuantumToChar((Quantum) GetPixelBlue(canvas,p));
6967                   p+=GetPixelChannels(canvas);
6968                 }
6969               }
6970             }
6971           else
6972             if ((ximage->bits_per_pixel == 32) && (map_info->red_max == 255) &&
6973                 (map_info->green_max == 255) && (map_info->blue_max == 255) &&
6974                 (map_info->red_mult == 1) && (map_info->green_mult == 256) &&
6975                 (map_info->blue_mult == 65536L))
6976               {
6977                 /*
6978                   Convert to 32 bit continuous-tone X canvas.
6979                 */
6980                 for (y=0; y < (int) canvas->rows; y++)
6981                 {
6982                   p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
6983                     canvas->columns,1,exception);
6984                   if (p == (const Quantum *) NULL)
6985                     break;
6986                   if ((red_gamma != 1.0) || (green_gamma != 1.0) ||
6987                       (blue_gamma != 1.0))
6988                     {
6989                       /*
6990                         Gamma correct canvas.
6991                       */
6992                       for (x=(int) canvas->columns-1; x >= 0; x--)
6993                       {
6994                         *q++=0;
6995                         *q++=ScaleQuantumToChar(XBlueGamma(
6996                           GetPixelBlue(canvas,p)));
6997                         *q++=ScaleQuantumToChar(XGreenGamma(
6998                           GetPixelGreen(canvas,p)));
6999                         *q++=ScaleQuantumToChar(XRedGamma(
7000                           GetPixelRed(canvas,p)));
7001                         p+=GetPixelChannels(canvas);
7002                       }
7003                       continue;
7004                     }
7005                   for (x=(int) canvas->columns-1; x >= 0; x--)
7006                   {
7007                     *q++=0;
7008                     *q++=ScaleQuantumToChar((Quantum) GetPixelBlue(canvas,p));
7009                     *q++=ScaleQuantumToChar((Quantum) GetPixelGreen(canvas,p));
7010                     *q++=ScaleQuantumToChar((Quantum) GetPixelRed(canvas,p));
7011                     p+=GetPixelChannels(canvas);
7012                   }
7013                 }
7014               }
7015             else
7016               {
7017                 register int
7018                   k;
7019
7020                 register unsigned int
7021                   bytes_per_pixel;
7022
7023                 unsigned char
7024                   channel[sizeof(size_t)];
7025
7026                 /*
7027                   Convert to multi-byte continuous-tone X canvas.
7028                 */
7029                 bytes_per_pixel=(unsigned int) (ximage->bits_per_pixel >> 3);
7030                 for (y=0; y < (int) canvas->rows; y++)
7031                 {
7032                   p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
7033                     canvas->columns,1,exception);
7034                   if (p == (const Quantum *) NULL)
7035                     break;
7036                   for (x=(int) canvas->columns-1; x >= 0; x--)
7037                   {
7038                     pixel=XGammaPixel(canvas,map_info,p);
7039                     for (k=(int) bytes_per_pixel-1; k >= 0; k--)
7040                     {
7041                       channel[k]=(unsigned char) pixel;
7042                       pixel>>=8;
7043                     }
7044                     for (k=0; k < (int) bytes_per_pixel; k++)
7045                       *q++=channel[k];
7046                     p+=GetPixelChannels(canvas);
7047                   }
7048                   q+=scanline_pad;
7049                 }
7050               }
7051           break;
7052         }
7053       }
7054   if (matte_image != (XImage *) NULL)
7055     {
7056       /*
7057         Initialize matte canvas.
7058       */
7059       scanline_pad=(unsigned int) (matte_image->bytes_per_line-
7060         ((matte_image->width*matte_image->bits_per_pixel) >> 3));
7061       q=(unsigned char *) matte_image->data;
7062       for (y=0; y < (int) canvas->rows; y++)
7063       {
7064         p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,canvas->columns,1,
7065           exception);
7066         if (p == (const Quantum *) NULL)
7067           break;
7068         bit=0;
7069         byte=0;
7070         for (x=(int) canvas->columns-1; x >= 0; x--)
7071         {
7072           byte<<=1;
7073           if (GetPixelAlpha(canvas,p) > (QuantumRange/2))
7074             byte|=0x01;
7075           bit++;
7076           if (bit == 8)
7077             {
7078               *q++=byte;
7079               bit=0;
7080               byte=0;
7081             }
7082           p+=GetPixelChannels(canvas);
7083         }
7084         if (bit != 0)
7085           *q=byte << (8-bit);
7086         q+=scanline_pad;
7087       }
7088     }
7089   canvas_view=DestroyCacheView(canvas_view);
7090   if (canvas != image)
7091     canvas=DestroyImage(canvas);
7092 }
7093 \f
7094 /*
7095 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
7096 %                                                                             %
7097 %                                                                             %
7098 %                                                                             %
7099 %   X M a k e M a g n i f y I m a g e                                         %
7100 %                                                                             %
7101 %                                                                             %
7102 %                                                                             %
7103 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
7104 %
7105 %  XMakeMagnifyImage() magnifies a region of an X image and displays it.
7106 %
7107 %  The format of the XMakeMagnifyImage method is:
7108 %
7109 %      void XMakeMagnifyImage(Display *display,XWindows *windows,
7110 %        ExceptionInfo *exception)
7111 %
7112 %  A description of each parameter follows:
7113 %
7114 %    o display: Specifies a connection to an X server;  returned from
7115 %      XOpenDisplay.
7116 %
7117 %    o windows: Specifies a pointer to a XWindows structure.
7118 %
7119 %    o exception: return any errors or warnings in this structure.
7120 %
7121 */
7122 MagickPrivate void XMakeMagnifyImage(Display *display,XWindows *windows,
7123   ExceptionInfo *exception)
7124 {
7125   char
7126     tuple[MaxTextExtent];
7127
7128   int
7129     y;
7130
7131   PixelInfo
7132     pixel;
7133
7134   register int
7135     x;
7136
7137   register ssize_t
7138     i;
7139
7140   register unsigned char
7141     *p,
7142     *q;
7143
7144   ssize_t
7145     n;
7146
7147   static unsigned int
7148     previous_magnify = 0;
7149
7150   static XWindowInfo
7151     magnify_window;
7152
7153   unsigned int
7154     height,
7155     j,
7156     k,
7157     l,
7158     magnify,
7159     scanline_pad,
7160     width;
7161
7162   XImage
7163     *ximage;
7164
7165   /*
7166     Check boundary conditions.
7167   */
7168   (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
7169   assert(display != (Display *) NULL);
7170   assert(windows != (XWindows *) NULL);
7171   magnify=1;
7172   for (n=1; n < (ssize_t) windows->magnify.data; n++)
7173     magnify<<=1;
7174   while ((magnify*windows->image.ximage->width) < windows->magnify.width)
7175     magnify<<=1;
7176   while ((magnify*windows->image.ximage->height) < windows->magnify.height)
7177     magnify<<=1;
7178   while (magnify > windows->magnify.width)
7179     magnify>>=1;
7180   while (magnify > windows->magnify.height)
7181     magnify>>=1;
7182   if (magnify != previous_magnify)
7183     {
7184       Status
7185         status;
7186
7187       XTextProperty
7188         window_name;
7189
7190       /*
7191         New magnify factor:  update magnify window name.
7192       */
7193       i=0;
7194       while ((1 << i) <= (int) magnify)
7195         i++;
7196       (void) FormatLocaleString(windows->magnify.name,MaxTextExtent,
7197         "Magnify %.20gX",(double) i);
7198       status=XStringListToTextProperty(&windows->magnify.name,1,&window_name);
7199       if (status != False)
7200         {
7201           XSetWMName(display,windows->magnify.id,&window_name);
7202           XSetWMIconName(display,windows->magnify.id,&window_name);
7203           (void) XFree((void *) window_name.value);
7204         }
7205     }
7206   previous_magnify=magnify;
7207   ximage=windows->image.ximage;
7208   width=(unsigned int) windows->magnify.ximage->width;
7209   height=(unsigned int) windows->magnify.ximage->height;
7210   if ((windows->magnify.x < 0) ||
7211       (windows->magnify.x >= windows->image.ximage->width))
7212     windows->magnify.x=windows->image.ximage->width >> 1;
7213   x=windows->magnify.x-((width/magnify) >> 1);
7214   if (x < 0)
7215     x=0;
7216   else
7217     if (x > (int) (ximage->width-(width/magnify)))
7218       x=ximage->width-width/magnify;
7219   if ((windows->magnify.y < 0) ||
7220       (windows->magnify.y >= windows->image.ximage->height))
7221     windows->magnify.y=windows->image.ximage->height >> 1;
7222   y=windows->magnify.y-((height/magnify) >> 1);
7223   if (y < 0)
7224     y=0;
7225   else
7226     if (y > (int) (ximage->height-(height/magnify)))
7227       y=ximage->height-height/magnify;
7228   q=(unsigned char *) windows->magnify.ximage->data;
7229   scanline_pad=(unsigned int) (windows->magnify.ximage->bytes_per_line-
7230     ((width*windows->magnify.ximage->bits_per_pixel) >> 3));
7231   if (ximage->bits_per_pixel < 8)
7232     {
7233       register unsigned char
7234         background,
7235         byte,
7236         foreground,
7237         p_bit,
7238         q_bit;
7239
7240       register unsigned int
7241         plane;
7242
7243       XPixelInfo
7244         *pixel_info;
7245
7246       pixel_info=windows->magnify.pixel_info;
7247       switch (ximage->bitmap_bit_order)
7248       {
7249         case LSBFirst:
7250         {
7251           /*
7252             Magnify little-endian bitmap.
7253           */
7254           background=0x00;
7255           foreground=0x80;
7256           if (ximage->format == XYBitmap)
7257             {
7258               background=(unsigned char)
7259                 (XPixelIntensity(&pixel_info->foreground_color) <
7260                  XPixelIntensity(&pixel_info->background_color) ?  0x80 : 0x00);
7261               foreground=(unsigned char)
7262                 (XPixelIntensity(&pixel_info->background_color) <
7263                  XPixelIntensity(&pixel_info->foreground_color) ?  0x80 : 0x00);
7264               if (windows->magnify.depth > 1)
7265                 Swap(background,foreground);
7266             }
7267           for (i=0; i < (ssize_t) height; i+=magnify)
7268           {
7269             /*
7270               Propogate pixel magnify rows.
7271             */
7272             for (j=0; j < magnify; j++)
7273             {
7274               p=(unsigned char *) ximage->data+y*ximage->bytes_per_line+
7275                 ((x*ximage->bits_per_pixel) >> 3);
7276               p_bit=(unsigned char) (x*ximage->bits_per_pixel) & 0x07;
7277               q_bit=0;
7278               byte=0;
7279               for (k=0; k < width; k+=magnify)
7280               {
7281                 /*
7282                   Propogate pixel magnify columns.
7283                 */
7284                 for (l=0; l < magnify; l++)
7285                 {
7286                   /*
7287                     Propogate each bit plane.
7288                   */
7289                   for (plane=0; (int) plane < ximage->bits_per_pixel; plane++)
7290                   {
7291                     byte>>=1;
7292                     if (*p & (0x01 << (p_bit+plane)))
7293                       byte|=foreground;
7294                     else
7295                       byte|=background;
7296                     q_bit++;
7297                     if (q_bit == 8)
7298                       {
7299                         *q++=byte;
7300                         q_bit=0;
7301                         byte=0;
7302                       }
7303                   }
7304                 }
7305                 p_bit+=ximage->bits_per_pixel;
7306                 if (p_bit == 8)
7307                   {
7308                     p++;
7309                     p_bit=0;
7310                   }
7311                 if (q_bit != 0)
7312                   *q=byte >> (8-q_bit);
7313                 q+=scanline_pad;
7314               }
7315             }
7316             y++;
7317           }
7318           break;
7319         }
7320         case MSBFirst:
7321         default:
7322         {
7323           /*
7324             Magnify big-endian bitmap.
7325           */
7326           background=0x00;
7327           foreground=0x01;
7328           if (ximage->format == XYBitmap)
7329             {
7330               background=(unsigned char)
7331                 (XPixelIntensity(&pixel_info->foreground_color) <
7332                  XPixelIntensity(&pixel_info->background_color) ?  0x01 : 0x00);
7333               foreground=(unsigned char)
7334                 (XPixelIntensity(&pixel_info->background_color) <
7335                  XPixelIntensity(&pixel_info->foreground_color) ?  0x01 : 0x00);
7336               if (windows->magnify.depth > 1)
7337                 Swap(background,foreground);
7338             }
7339           for (i=0; i < (ssize_t) height; i+=magnify)
7340           {
7341             /*
7342               Propogate pixel magnify rows.
7343             */
7344             for (j=0; j < magnify; j++)
7345             {
7346               p=(unsigned char *) ximage->data+y*ximage->bytes_per_line+
7347                 ((x*ximage->bits_per_pixel) >> 3);
7348               p_bit=(unsigned char) (x*ximage->bits_per_pixel) & 0x07;
7349               q_bit=0;
7350               byte=0;
7351               for (k=0; k < width; k+=magnify)
7352               {
7353                 /*
7354                   Propogate pixel magnify columns.
7355                 */
7356                 for (l=0; l < magnify; l++)
7357                 {
7358                   /*
7359                     Propogate each bit plane.
7360                   */
7361                   for (plane=0; (int) plane < ximage->bits_per_pixel; plane++)
7362                   {
7363                     byte<<=1;
7364                     if (*p & (0x80 >> (p_bit+plane)))
7365                       byte|=foreground;
7366                     else
7367                       byte|=background;
7368                     q_bit++;
7369                     if (q_bit == 8)
7370                       {
7371                         *q++=byte;
7372                         q_bit=0;
7373                         byte=0;
7374                       }
7375                   }
7376                 }
7377                 p_bit+=ximage->bits_per_pixel;
7378                 if (p_bit == 8)
7379                   {
7380                     p++;
7381                     p_bit=0;
7382                   }
7383                 if (q_bit != 0)
7384                   *q=byte << (8-q_bit);
7385                 q+=scanline_pad;
7386               }
7387             }
7388             y++;
7389           }
7390           break;
7391         }
7392       }
7393     }
7394   else
7395     switch (ximage->bits_per_pixel)
7396     {
7397       case 6:
7398       case 8:
7399       {
7400         /*
7401           Magnify 8 bit X image.
7402         */
7403         for (i=0; i < (ssize_t) height; i+=magnify)
7404         {
7405           /*
7406             Propogate pixel magnify rows.
7407           */
7408           for (j=0; j < magnify; j++)
7409           {
7410             p=(unsigned char *) ximage->data+y*ximage->bytes_per_line+
7411               ((x*ximage->bits_per_pixel) >> 3);
7412             for (k=0; k < width; k+=magnify)
7413             {
7414               /*
7415                 Propogate pixel magnify columns.
7416               */
7417               for (l=0; l < magnify; l++)
7418                 *q++=(*p);
7419               p++;
7420             }
7421             q+=scanline_pad;
7422           }
7423           y++;
7424         }
7425         break;
7426       }
7427       default:
7428       {
7429         register unsigned int
7430           bytes_per_pixel,
7431           m;
7432
7433         /*
7434           Magnify multi-byte X image.
7435         */
7436         bytes_per_pixel=(unsigned int) ximage->bits_per_pixel >> 3;
7437         for (i=0; i < (ssize_t) height; i+=magnify)
7438         {
7439           /*
7440             Propogate pixel magnify rows.
7441           */
7442           for (j=0; j < magnify; j++)
7443           {
7444             p=(unsigned char *) ximage->data+y*ximage->bytes_per_line+
7445               ((x*ximage->bits_per_pixel) >> 3);
7446             for (k=0; k < width; k+=magnify)
7447             {
7448               /*
7449                 Propogate pixel magnify columns.
7450               */
7451               for (l=0; l < magnify; l++)
7452                 for (m=0; m < bytes_per_pixel; m++)
7453                   *q++=(*(p+m));
7454               p+=bytes_per_pixel;
7455             }
7456             q+=scanline_pad;
7457           }
7458           y++;
7459         }
7460         break;
7461       }
7462     }
7463   /*
7464     Copy X image to magnify pixmap.
7465   */
7466   x=windows->magnify.x-((width/magnify) >> 1);
7467   if (x < 0)
7468     x=(int) ((width >> 1)-windows->magnify.x*magnify);
7469   else
7470     if (x > (int) (ximage->width-(width/magnify)))
7471       x=(int) ((ximage->width-windows->magnify.x)*magnify-(width >> 1));
7472     else
7473       x=0;
7474   y=windows->magnify.y-((height/magnify) >> 1);
7475   if (y < 0)
7476     y=(int) ((height >> 1)-windows->magnify.y*magnify);
7477   else
7478     if (y > (int) (ximage->height-(height/magnify)))
7479       y=(int) ((ximage->height-windows->magnify.y)*magnify-(height >> 1));
7480     else
7481       y=0;
7482   if ((x != 0) || (y != 0))
7483     (void) XFillRectangle(display,windows->magnify.pixmap,
7484       windows->magnify.annotate_context,0,0,width,height);
7485   (void) XPutImage(display,windows->magnify.pixmap,
7486     windows->magnify.annotate_context,windows->magnify.ximage,0,0,x,y,width-x,
7487     height-y);
7488   if ((magnify > 1) && ((magnify <= (width >> 1)) &&
7489       (magnify <= (height >> 1))))
7490     {
7491       RectangleInfo
7492         highlight_info;
7493
7494       /*
7495         Highlight center pixel.
7496       */
7497       highlight_info.x=(ssize_t) windows->magnify.width >> 1;
7498       highlight_info.y=(ssize_t) windows->magnify.height >> 1;
7499       highlight_info.width=magnify;
7500       highlight_info.height=magnify;
7501       (void) XDrawRectangle(display,windows->magnify.pixmap,
7502         windows->magnify.highlight_context,(int) highlight_info.x,
7503         (int) highlight_info.y,(unsigned int) highlight_info.width-1,
7504         (unsigned int) highlight_info.height-1);
7505       if (magnify > 2)
7506         (void) XDrawRectangle(display,windows->magnify.pixmap,
7507           windows->magnify.annotate_context,(int) highlight_info.x+1,
7508           (int) highlight_info.y+1,(unsigned int) highlight_info.width-3,
7509           (unsigned int) highlight_info.height-3);
7510     }
7511   /*
7512     Show center pixel color.
7513   */
7514   (void) GetOneVirtualPixelInfo(windows->image.image,TileVirtualPixelMethod,
7515     (ssize_t) windows->magnify.x,(ssize_t) windows->magnify.y,&pixel,exception);
7516   (void) FormatLocaleString(tuple,MaxTextExtent,"%d,%d: ",
7517     windows->magnify.x,windows->magnify.y);
7518   (void) ConcatenateMagickString(tuple,"(",MaxTextExtent);
7519   ConcatenateColorComponent(&pixel,RedPixelChannel,X11Compliance,tuple);
7520   (void) ConcatenateMagickString(tuple,",",MaxTextExtent);
7521   ConcatenateColorComponent(&pixel,GreenPixelChannel,X11Compliance,tuple);
7522   (void) ConcatenateMagickString(tuple,",",MaxTextExtent);
7523   ConcatenateColorComponent(&pixel,BluePixelChannel,X11Compliance,tuple);
7524   if (pixel.colorspace == CMYKColorspace)
7525     {
7526       (void) ConcatenateMagickString(tuple,",",MaxTextExtent);
7527       ConcatenateColorComponent(&pixel,BlackPixelChannel,X11Compliance,tuple);
7528     }
7529   if (pixel.alpha_trait == BlendPixelTrait)
7530     {
7531       (void) ConcatenateMagickString(tuple,",",MaxTextExtent);
7532       ConcatenateColorComponent(&pixel,AlphaPixelChannel,X11Compliance,tuple);
7533     }
7534   (void) ConcatenateMagickString(tuple,")",MaxTextExtent);
7535   height=(unsigned int) windows->magnify.font_info->ascent+
7536     windows->magnify.font_info->descent;
7537   x=windows->magnify.font_info->max_bounds.width >> 1;
7538   y=windows->magnify.font_info->ascent+(height >> 2);
7539   (void) XDrawImageString(display,windows->magnify.pixmap,
7540     windows->magnify.annotate_context,x,y,tuple,(int) strlen(tuple));
7541   GetColorTuple(&pixel,MagickTrue,tuple);
7542   y+=height;
7543   (void) XDrawImageString(display,windows->magnify.pixmap,
7544     windows->magnify.annotate_context,x,y,tuple,(int) strlen(tuple));
7545   (void) QueryColorname(windows->image.image,&pixel,SVGCompliance,tuple,
7546     exception);
7547   y+=height;
7548   (void) XDrawImageString(display,windows->magnify.pixmap,
7549     windows->magnify.annotate_context,x,y,tuple,(int) strlen(tuple));
7550   /*
7551     Refresh magnify window.
7552   */
7553   magnify_window=windows->magnify;
7554   magnify_window.x=0;
7555   magnify_window.y=0;
7556   XRefreshWindow(display,&magnify_window,(XEvent *) NULL);
7557 }
7558 \f
7559 /*
7560 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
7561 %                                                                             %
7562 %                                                                             %
7563 %                                                                             %
7564 %   X M a k e P i x m a p                                                     %
7565 %                                                                             %
7566 %                                                                             %
7567 %                                                                             %
7568 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
7569 %
7570 %  XMakePixmap() creates an X11 pixmap.
7571 %
7572 %  The format of the XMakePixmap method is:
7573 %
7574 %      void XMakeStandardColormap(Display *display,XVisualInfo *visual_info,
7575 %        XResourceInfo *resource_info,Image *image,XStandardColormap *map_info,
7576 %        XPixelInfo *pixel)
7577 %
7578 %  A description of each parameter follows:
7579 %
7580 %    o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
7581 %
7582 %    o display: Specifies a connection to an X server; returned from
7583 %      XOpenDisplay.
7584 %
7585 %    o window: Specifies a pointer to a XWindowInfo structure.
7586 %
7587 */
7588 static MagickBooleanType XMakePixmap(Display *display,
7589   const XResourceInfo *resource_info,XWindowInfo *window)
7590 {
7591   unsigned int
7592     height,
7593     width;
7594
7595   (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
7596   assert(display != (Display *) NULL);
7597   assert(resource_info != (XResourceInfo *) NULL);
7598   assert(window != (XWindowInfo  *) NULL);
7599   if (window->pixmap != (Pixmap) NULL)
7600     {
7601       /*
7602         Destroy previous X pixmap.
7603       */
7604       (void) XFreePixmap(display,window->pixmap);
7605       window->pixmap=(Pixmap) NULL;
7606     }
7607   if (window->use_pixmap == MagickFalse)
7608     return(MagickFalse);
7609   if (window->ximage == (XImage *) NULL)
7610     return(MagickFalse);
7611   /*
7612     Display busy cursor.
7613   */
7614   (void) XCheckDefineCursor(display,window->id,window->busy_cursor);
7615   (void) XFlush(display);
7616   /*
7617     Create pixmap.
7618   */
7619   width=(unsigned int) window->ximage->width;
7620   height=(unsigned int) window->ximage->height;
7621   window->pixmap=XCreatePixmap(display,window->id,width,height,window->depth);
7622   if (window->pixmap == (Pixmap) NULL)
7623     {
7624       /*
7625         Unable to allocate pixmap.
7626       */
7627       (void) XCheckDefineCursor(display,window->id,window->cursor);
7628       return(MagickFalse);
7629     }
7630   /*
7631     Copy X image to pixmap.
7632   */
7633 #if defined(MAGICKCORE_HAVE_SHARED_MEMORY)
7634   if (window->shared_memory)
7635     (void) XShmPutImage(display,window->pixmap,window->annotate_context,
7636       window->ximage,0,0,0,0,width,height,MagickTrue);
7637 #endif
7638   if (window->shared_memory == MagickFalse)
7639     (void) XPutImage(display,window->pixmap,window->annotate_context,
7640       window->ximage,0,0,0,0,width,height);
7641   if (IsEventLogging())
7642     {
7643       (void) LogMagickEvent(X11Event,GetMagickModule(),"Pixmap:");
7644       (void) LogMagickEvent(X11Event,GetMagickModule(),"  width, height: %ux%u",
7645         width,height);
7646     }
7647   /*
7648     Restore cursor.
7649   */
7650   (void) XCheckDefineCursor(display,window->id,window->cursor);
7651   return(MagickTrue);
7652 }
7653 \f
7654 /*
7655 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
7656 %                                                                             %
7657 %                                                                             %
7658 %                                                                             %
7659 %   X M a k e S t a n d a r d C o l o r m a p                                 %
7660 %                                                                             %
7661 %                                                                             %
7662 %                                                                             %
7663 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
7664 %
7665 %  XMakeStandardColormap() creates an X11 Standard Colormap.
7666 %
7667 %  The format of the XMakeStandardColormap method is:
7668 %
7669 %      void XMakeStandardColormap(Display *display,XVisualInfo *visual_info,
7670 %        XResourceInfo *resource_info,Image *image,XStandardColormap *map_info,
7671 %        XPixelInfo *pixel,ExceptionInfo *exception)
7672 %
7673 %  A description of each parameter follows:
7674 %
7675 %    o display: Specifies a connection to an X server; returned from
7676 %      XOpenDisplay.
7677 %
7678 %    o visual_info: Specifies a pointer to a X11 XVisualInfo structure;
7679 %      returned from XGetVisualInfo.
7680 %
7681 %    o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
7682 %
7683 %    o image: the image.
7684 %
7685 %    o map_info: If a Standard Colormap type is specified, this structure is
7686 %      initialized with info from the Standard Colormap.
7687 %
7688 %    o pixel: Specifies a pointer to a XPixelInfo structure.
7689 %
7690 %    o exception: return any errors or warnings in this structure.
7691 %
7692 */
7693
7694 #if defined(__cplusplus) || defined(c_plusplus)
7695 extern "C" {
7696 #endif
7697
7698 static inline double DiversityPixelIntensity(
7699   const DiversityPacket *pixel)
7700 {
7701   double
7702     intensity;
7703
7704   intensity=0.298839f*pixel->red+0.586811f*pixel->green+0.114350f*pixel->blue;
7705   return(intensity);
7706 }
7707
7708 static int IntensityCompare(const void *x,const void *y)
7709 {
7710   DiversityPacket
7711     *color_1,
7712     *color_2;
7713
7714   int
7715     diversity;
7716
7717   color_1=(DiversityPacket *) x;
7718   color_2=(DiversityPacket *) y;
7719   diversity=(int) (DiversityPixelIntensity(color_2)-
7720     DiversityPixelIntensity(color_1));
7721   return(diversity);
7722 }
7723
7724 static int PopularityCompare(const void *x,const void *y)
7725 {
7726   DiversityPacket
7727     *color_1,
7728     *color_2;
7729
7730   color_1=(DiversityPacket *) x;
7731   color_2=(DiversityPacket *) y;
7732   return((int) color_2->count-(int) color_1->count);
7733 }
7734
7735 #if defined(__cplusplus) || defined(c_plusplus)
7736 }
7737 #endif
7738
7739 static inline Quantum ScaleXToQuantum(const size_t x,
7740   const size_t scale)
7741 {
7742   return((Quantum) (((double) QuantumRange*x)/scale+0.5));
7743 }
7744
7745 MagickPrivate void XMakeStandardColormap(Display *display,
7746   XVisualInfo *visual_info,XResourceInfo *resource_info,Image *image,
7747   XStandardColormap *map_info,XPixelInfo *pixel,ExceptionInfo *exception)
7748 {
7749   Colormap
7750     colormap;
7751
7752   register ssize_t
7753     i;
7754
7755   Status
7756     status;
7757
7758   size_t
7759     number_colors,
7760     retain_colors;
7761
7762   unsigned short
7763     gray_value;
7764
7765   XColor
7766     color,
7767     *colors,
7768     *p;
7769
7770   (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
7771   assert(display != (Display *) NULL);
7772   assert(visual_info != (XVisualInfo *) NULL);
7773   assert(map_info != (XStandardColormap *) NULL);
7774   assert(resource_info != (XResourceInfo *) NULL);
7775   assert(pixel != (XPixelInfo *) NULL);
7776   if (resource_info->map_type != (char *) NULL)
7777     {
7778       /*
7779         Standard Colormap is already defined (i.e. xstdcmap).
7780       */
7781       XGetPixelInfo(display,visual_info,map_info,resource_info,image,
7782         pixel);
7783       number_colors=(unsigned int) (map_info->base_pixel+
7784         (map_info->red_max+1)*(map_info->green_max+1)*(map_info->blue_max+1));
7785       if ((map_info->red_max*map_info->green_max*map_info->blue_max) != 0)
7786         if ((image->alpha_trait != BlendPixelTrait) &&
7787             (resource_info->color_recovery == MagickFalse) &&
7788             (resource_info->quantize_info->dither_method != NoDitherMethod) &&
7789             (number_colors < MaxColormapSize))
7790           {
7791             Image
7792               *affinity_image;
7793
7794             register Quantum
7795               *restrict q;
7796
7797             /*
7798               Improve image appearance with error diffusion.
7799             */
7800             affinity_image=AcquireImage((ImageInfo *) NULL,exception);
7801             if (affinity_image == (Image *) NULL)
7802               ThrowXWindowFatalException(ResourceLimitFatalError,
7803                 "UnableToDitherImage",image->filename);
7804             affinity_image->columns=number_colors;
7805             affinity_image->rows=1;
7806             /*
7807               Initialize colormap image.
7808             */
7809             q=QueueAuthenticPixels(affinity_image,0,0,affinity_image->columns,
7810               1,exception);
7811             if (q != (Quantum *) NULL)
7812               {
7813                 for (i=0; i < (ssize_t) number_colors; i++)
7814                 {
7815                   SetPixelRed(affinity_image,0,q);
7816                   if (map_info->red_max != 0)
7817                     SetPixelRed(affinity_image,
7818                       ScaleXToQuantum((size_t) (i/map_info->red_mult),
7819                       map_info->red_max),q);
7820                   SetPixelGreen(affinity_image,0,q);
7821                   if (map_info->green_max != 0)
7822                     SetPixelGreen(affinity_image,
7823                       ScaleXToQuantum((size_t) ((i/map_info->green_mult) %
7824                       (map_info->green_max+1)),map_info->green_max),q);
7825                   SetPixelBlue(affinity_image,0,q);
7826                   if (map_info->blue_max != 0)
7827                     SetPixelBlue(affinity_image,
7828                       ScaleXToQuantum((size_t) (i % map_info->green_mult),
7829                       map_info->blue_max),q);
7830                   SetPixelAlpha(affinity_image,
7831                     TransparentAlpha,q);
7832                   q+=GetPixelChannels(affinity_image);
7833                 }
7834                 (void) SyncAuthenticPixels(affinity_image,exception);
7835                 (void) RemapImage(resource_info->quantize_info,image,
7836                   affinity_image,exception);
7837               }
7838             XGetPixelInfo(display,visual_info,map_info,resource_info,image,
7839               pixel);
7840             (void) SetImageStorageClass(image,DirectClass,exception);
7841             affinity_image=DestroyImage(affinity_image);
7842           }
7843       if (IsEventLogging())
7844         {
7845           (void) LogMagickEvent(X11Event,GetMagickModule(),
7846             "Standard Colormap:");
7847           (void) LogMagickEvent(X11Event,GetMagickModule(),
7848             "  colormap id: 0x%lx",map_info->colormap);
7849           (void) LogMagickEvent(X11Event,GetMagickModule(),
7850             "  red, green, blue max: %lu %lu %lu",map_info->red_max,
7851             map_info->green_max,map_info->blue_max);
7852           (void) LogMagickEvent(X11Event,GetMagickModule(),
7853             "  red, green, blue mult: %lu %lu %lu",map_info->red_mult,
7854             map_info->green_mult,map_info->blue_mult);
7855         }
7856       return;
7857     }
7858   if ((visual_info->klass != DirectColor) &&
7859       (visual_info->klass != TrueColor))
7860     if ((image->storage_class == DirectClass) ||
7861         ((int) image->colors > visual_info->colormap_size))
7862       {
7863         QuantizeInfo
7864           quantize_info;
7865
7866         /*
7867           Image has more colors than the visual supports.
7868         */
7869         quantize_info=(*resource_info->quantize_info);
7870         quantize_info.number_colors=(size_t) visual_info->colormap_size;
7871         (void) QuantizeImage(&quantize_info,image,exception);
7872       }
7873   /*
7874     Free previous and create new colormap.
7875   */
7876   (void) XFreeStandardColormap(display,visual_info,map_info,pixel);
7877   colormap=XDefaultColormap(display,visual_info->screen);
7878   if (visual_info->visual != XDefaultVisual(display,visual_info->screen))
7879     colormap=XCreateColormap(display,XRootWindow(display,visual_info->screen),
7880       visual_info->visual,visual_info->klass == DirectColor ?
7881       AllocAll : AllocNone);
7882   if (colormap == (Colormap) NULL)
7883     ThrowXWindowFatalException(ResourceLimitFatalError,"UnableToCreateColormap",
7884       image->filename);
7885   /*
7886     Initialize the map and pixel info structures.
7887   */
7888   XGetMapInfo(visual_info,colormap,map_info);
7889   XGetPixelInfo(display,visual_info,map_info,resource_info,image,pixel);
7890   /*
7891     Allocating colors in server colormap is based on visual class.
7892   */
7893   switch (visual_info->klass)
7894   {
7895     case StaticGray:
7896     case StaticColor:
7897     {
7898       /*
7899         Define Standard Colormap for StaticGray or StaticColor visual.
7900       */
7901       number_colors=image->colors;
7902       colors=(XColor *) AcquireQuantumMemory((size_t)
7903         visual_info->colormap_size,sizeof(*colors));
7904       if (colors == (XColor *) NULL)
7905         ThrowXWindowFatalException(ResourceLimitFatalError,
7906           "UnableToCreateColormap",image->filename);
7907       p=colors;
7908       color.flags=(char) (DoRed | DoGreen | DoBlue);
7909       for (i=0; i < (ssize_t) image->colors; i++)
7910       {
7911         color.red=ScaleQuantumToShort(XRedGamma(image->colormap[i].red));
7912         color.green=ScaleQuantumToShort(XGreenGamma(image->colormap[i].green));
7913         color.blue=ScaleQuantumToShort(XBlueGamma(image->colormap[i].blue));
7914         if (visual_info->klass != StaticColor)
7915           {
7916             gray_value=(unsigned short) XPixelIntensity(&color);
7917             color.red=gray_value;
7918             color.green=gray_value;
7919             color.blue=gray_value;
7920           }
7921         status=XAllocColor(display,colormap,&color);
7922         if (status == False)
7923           {
7924             colormap=XCopyColormapAndFree(display,colormap);
7925             (void) XAllocColor(display,colormap,&color);
7926           }
7927         pixel->pixels[i]=color.pixel;
7928         *p++=color;
7929       }
7930       break;
7931     }
7932     case GrayScale:
7933     case PseudoColor:
7934     {
7935       unsigned int
7936         colormap_type;
7937
7938       /*
7939         Define Standard Colormap for GrayScale or PseudoColor visual.
7940       */
7941       number_colors=image->colors;
7942       colors=(XColor *) AcquireQuantumMemory((size_t)
7943         visual_info->colormap_size,sizeof(*colors));
7944       if (colors == (XColor *) NULL)
7945         ThrowXWindowFatalException(ResourceLimitFatalError,
7946           "UnableToCreateColormap",image->filename);
7947       /*
7948         Preallocate our GUI colors.
7949       */
7950       (void) XAllocColor(display,colormap,&pixel->foreground_color);
7951       (void) XAllocColor(display,colormap,&pixel->background_color);
7952       (void) XAllocColor(display,colormap,&pixel->border_color);
7953       (void) XAllocColor(display,colormap,&pixel->matte_color);
7954       (void) XAllocColor(display,colormap,&pixel->highlight_color);
7955       (void) XAllocColor(display,colormap,&pixel->shadow_color);
7956       (void) XAllocColor(display,colormap,&pixel->depth_color);
7957       (void) XAllocColor(display,colormap,&pixel->trough_color);
7958       for (i=0; i < MaxNumberPens; i++)
7959         (void) XAllocColor(display,colormap,&pixel->pen_colors[i]);
7960       /*
7961         Determine if image colors will "fit" into X server colormap.
7962       */
7963       colormap_type=resource_info->colormap;
7964       status=XAllocColorCells(display,colormap,MagickFalse,(unsigned long *)
7965         NULL,0,pixel->pixels,(unsigned int) image->colors);
7966       if (status != False)
7967         colormap_type=PrivateColormap;
7968       if (colormap_type == SharedColormap)
7969         {
7970           CacheView
7971             *image_view;
7972
7973           DiversityPacket
7974             *diversity;
7975
7976           int
7977             y;
7978
7979           register int
7980             x;
7981
7982           unsigned short
7983             index;
7984
7985           XColor
7986             *server_colors;
7987
7988           /*
7989             Define Standard colormap for shared GrayScale or PseudoColor visual.
7990           */
7991           diversity=(DiversityPacket *) AcquireQuantumMemory(image->colors,
7992             sizeof(*diversity));
7993           if (diversity == (DiversityPacket *) NULL)
7994             ThrowXWindowFatalException(ResourceLimitFatalError,
7995               "UnableToCreateColormap",image->filename);
7996           for (i=0; i < (ssize_t) image->colors; i++)
7997           {
7998             diversity[i].red=ClampToQuantum(image->colormap[i].red);
7999             diversity[i].green=ClampToQuantum(image->colormap[i].green);
8000             diversity[i].blue=ClampToQuantum(image->colormap[i].blue);
8001             diversity[i].index=(unsigned short) i;
8002             diversity[i].count=0;
8003           }
8004           image_view=AcquireAuthenticCacheView(image,exception);
8005           for (y=0; y < (int) image->rows; y++)
8006           {
8007             register int
8008               x;
8009
8010             register const Quantum
8011               *restrict p;
8012
8013             p=GetCacheViewAuthenticPixels(image_view,0,(ssize_t) y,
8014               image->columns,1,exception);
8015             if (p == (const Quantum *) NULL)
8016               break;
8017             for (x=(int) image->columns-1; x >= 0; x--)
8018             {
8019               diversity[(ssize_t) GetPixelIndex(image,p)].count++;
8020               p+=GetPixelChannels(image);
8021             }
8022           }
8023           image_view=DestroyCacheView(image_view);
8024           /*
8025             Sort colors by decreasing intensity.
8026           */
8027           qsort((void *) diversity,image->colors,sizeof(*diversity),
8028             IntensityCompare);
8029           for (i=0; i < (ssize_t) image->colors; )
8030           {
8031             diversity[i].count<<=4;  /* increase this colors popularity */
8032             i+=MagickMax((int) (image->colors >> 4),2);
8033           }
8034           diversity[image->colors-1].count<<=4;
8035           qsort((void *) diversity,image->colors,sizeof(*diversity),
8036             PopularityCompare);
8037           /*
8038             Allocate colors.
8039           */
8040           p=colors;
8041           color.flags=(char) (DoRed | DoGreen | DoBlue);
8042           for (i=0; i < (ssize_t) image->colors; i++)
8043           {
8044             index=diversity[i].index;
8045             color.red=
8046               ScaleQuantumToShort(XRedGamma(image->colormap[index].red));
8047             color.green=
8048               ScaleQuantumToShort(XGreenGamma(image->colormap[index].green));
8049             color.blue=
8050               ScaleQuantumToShort(XBlueGamma(image->colormap[index].blue));
8051             if (visual_info->klass != PseudoColor)
8052               {
8053                 gray_value=(unsigned short) XPixelIntensity(&color);
8054                 color.red=gray_value;
8055                 color.green=gray_value;
8056                 color.blue=gray_value;
8057               }
8058             status=XAllocColor(display,colormap,&color);
8059             if (status == False)
8060               break;
8061             pixel->pixels[index]=color.pixel;
8062             *p++=color;
8063           }
8064           /*
8065             Read X server colormap.
8066           */
8067           server_colors=(XColor *) AcquireQuantumMemory((size_t)
8068             visual_info->colormap_size,sizeof(*server_colors));
8069           if (server_colors == (XColor *) NULL)
8070             ThrowXWindowFatalException(ResourceLimitFatalError,
8071               "UnableToCreateColormap",image->filename);
8072           for (x=visual_info->colormap_size-1; x >= 0; x--)
8073             server_colors[x].pixel=(size_t) x;
8074           (void) XQueryColors(display,colormap,server_colors,
8075             (int) MagickMin((unsigned int) visual_info->colormap_size,256));
8076           /*
8077             Select remaining colors from X server colormap.
8078           */
8079           for (; i < (ssize_t) image->colors; i++)
8080           {
8081             index=diversity[i].index;
8082             color.red=
8083               ScaleQuantumToShort(XRedGamma(image->colormap[index].red));
8084             color.green=
8085               ScaleQuantumToShort(XGreenGamma(image->colormap[index].green));
8086             color.blue=
8087               ScaleQuantumToShort(XBlueGamma(image->colormap[index].blue));
8088             if (visual_info->klass != PseudoColor)
8089               {
8090                 gray_value=(unsigned short) XPixelIntensity(&color);
8091                 color.red=gray_value;
8092                 color.green=gray_value;
8093                 color.blue=gray_value;
8094               }
8095             XBestPixel(display,colormap,server_colors,(unsigned int)
8096               visual_info->colormap_size,&color);
8097             pixel->pixels[index]=color.pixel;
8098             *p++=color;
8099           }
8100           if ((int) image->colors < visual_info->colormap_size)
8101             {
8102               /*
8103                 Fill up colors array-- more choices for pen colors.
8104               */
8105               retain_colors=MagickMin((unsigned int)
8106                (visual_info->colormap_size-image->colors),256);
8107               for (i=0; i < (ssize_t) retain_colors; i++)
8108                 *p++=server_colors[i];
8109               number_colors+=retain_colors;
8110             }
8111           server_colors=(XColor *) RelinquishMagickMemory(server_colors);
8112           diversity=(DiversityPacket *) RelinquishMagickMemory(diversity);
8113           break;
8114         }
8115       /*
8116         Define Standard colormap for private GrayScale or PseudoColor visual.
8117       */
8118       if (status == False)
8119         {
8120           /*
8121             Not enough colormap entries in the colormap-- Create a new colormap.
8122           */
8123           colormap=XCreateColormap(display,
8124             XRootWindow(display,visual_info->screen),visual_info->visual,
8125             AllocNone);
8126           if (colormap == (Colormap) NULL)
8127             ThrowXWindowFatalException(ResourceLimitFatalError,
8128               "UnableToCreateColormap",image->filename);
8129           map_info->colormap=colormap;
8130           if ((int) image->colors < visual_info->colormap_size)
8131             {
8132               /*
8133                 Retain colors from the default colormap to help lessens the
8134                 effects of colormap flashing.
8135               */
8136               retain_colors=MagickMin((unsigned int)
8137                 (visual_info->colormap_size-image->colors),256);
8138               p=colors+image->colors;
8139               for (i=0; i < (ssize_t) retain_colors; i++)
8140               {
8141                 p->pixel=(unsigned long) i;
8142                 p++;
8143               }
8144               (void) XQueryColors(display,
8145                 XDefaultColormap(display,visual_info->screen),
8146                 colors+image->colors,(int) retain_colors);
8147               /*
8148                 Transfer colors from default to private colormap.
8149               */
8150               (void) XAllocColorCells(display,colormap,MagickFalse,
8151                 (unsigned long *) NULL,0,pixel->pixels,(unsigned int)
8152                 retain_colors);
8153               p=colors+image->colors;
8154               for (i=0; i < (ssize_t) retain_colors; i++)
8155               {
8156                 p->pixel=pixel->pixels[i];
8157                 p++;
8158               }
8159               (void) XStoreColors(display,colormap,colors+image->colors,
8160                 (int) retain_colors);
8161               number_colors+=retain_colors;
8162             }
8163           (void) XAllocColorCells(display,colormap,MagickFalse,
8164             (unsigned long *) NULL,0,pixel->pixels,(unsigned int)
8165             image->colors);
8166         }
8167       /*
8168         Store the image colormap.
8169       */
8170       p=colors;
8171       color.flags=(char) (DoRed | DoGreen | DoBlue);
8172       for (i=0; i < (ssize_t) image->colors; i++)
8173       {
8174         color.red=ScaleQuantumToShort(XRedGamma(image->colormap[i].red));
8175         color.green=ScaleQuantumToShort(XGreenGamma(image->colormap[i].green));
8176         color.blue=ScaleQuantumToShort(XBlueGamma(image->colormap[i].blue));
8177         if (visual_info->klass != PseudoColor)
8178           {
8179             gray_value=(unsigned short) XPixelIntensity(&color);
8180             color.red=gray_value;
8181             color.green=gray_value;
8182             color.blue=gray_value;
8183           }
8184         color.pixel=pixel->pixels[i];
8185         *p++=color;
8186       }
8187       (void) XStoreColors(display,colormap,colors,(int) image->colors);
8188       break;
8189     }
8190     case TrueColor:
8191     case DirectColor:
8192     default:
8193     {
8194       MagickBooleanType
8195         linear_colormap;
8196
8197       /*
8198         Define Standard Colormap for TrueColor or DirectColor visual.
8199       */
8200       number_colors=(unsigned int) ((map_info->red_max*map_info->red_mult)+
8201         (map_info->green_max*map_info->green_mult)+
8202         (map_info->blue_max*map_info->blue_mult)+1);
8203       linear_colormap=(number_colors > 4096) ||
8204         (((int) (map_info->red_max+1) == visual_info->colormap_size) &&
8205          ((int) (map_info->green_max+1) == visual_info->colormap_size) &&
8206          ((int) (map_info->blue_max+1) == visual_info->colormap_size)) ?
8207          MagickTrue : MagickFalse;
8208       if (linear_colormap != MagickFalse)
8209         number_colors=(size_t) visual_info->colormap_size;
8210       /*
8211         Allocate color array.
8212       */
8213       colors=(XColor *) AcquireQuantumMemory(number_colors,sizeof(*colors));
8214       if (colors == (XColor *) NULL)
8215         ThrowXWindowFatalException(ResourceLimitFatalError,
8216           "UnableToCreateColormap",image->filename);
8217       /*
8218         Initialize linear color ramp.
8219       */
8220       p=colors;
8221       color.flags=(char) (DoRed | DoGreen | DoBlue);
8222       if (linear_colormap != MagickFalse)
8223         for (i=0; i < (ssize_t) number_colors; i++)
8224         {
8225           color.blue=(unsigned short) 0;
8226           if (map_info->blue_max != 0)
8227             color.blue=(unsigned short) ((size_t)
8228               ((65535L*(i % map_info->green_mult))/map_info->blue_max));
8229           color.green=color.blue;
8230           color.red=color.blue;
8231           color.pixel=XStandardPixel(map_info,&color);
8232           *p++=color;
8233         }
8234       else
8235         for (i=0; i < (ssize_t) number_colors; i++)
8236         {
8237           color.red=(unsigned short) 0;
8238           if (map_info->red_max != 0)
8239             color.red=(unsigned short) ((size_t)
8240               ((65535L*(i/map_info->red_mult))/map_info->red_max));
8241           color.green=(unsigned int) 0;
8242           if (map_info->green_max != 0)
8243             color.green=(unsigned short) ((size_t)
8244               ((65535L*((i/map_info->green_mult) % (map_info->green_max+1)))/
8245                 map_info->green_max));
8246           color.blue=(unsigned short) 0;
8247           if (map_info->blue_max != 0)
8248             color.blue=(unsigned short) ((size_t)
8249               ((65535L*(i % map_info->green_mult))/map_info->blue_max));
8250           color.pixel=XStandardPixel(map_info,&color);
8251           *p++=color;
8252         }
8253       if ((visual_info->klass == DirectColor) &&
8254           (colormap != XDefaultColormap(display,visual_info->screen)))
8255         (void) XStoreColors(display,colormap,colors,(int) number_colors);
8256       else
8257         for (i=0; i < (ssize_t) number_colors; i++)
8258           (void) XAllocColor(display,colormap,&colors[i]);
8259       break;
8260     }
8261   }
8262   if ((visual_info->klass != DirectColor) &&
8263       (visual_info->klass != TrueColor))
8264     {
8265       /*
8266         Set foreground, background, border, etc. pixels.
8267       */
8268       XBestPixel(display,colormap,colors,(unsigned int) number_colors,
8269         &pixel->foreground_color);
8270       XBestPixel(display,colormap,colors,(unsigned int) number_colors,
8271         &pixel->background_color);
8272       if (pixel->background_color.pixel == pixel->foreground_color.pixel)
8273         {
8274           /*
8275             Foreground and background colors must differ.
8276           */
8277           pixel->background_color.red=(~pixel->foreground_color.red);
8278           pixel->background_color.green=
8279             (~pixel->foreground_color.green);
8280           pixel->background_color.blue=
8281             (~pixel->foreground_color.blue);
8282           XBestPixel(display,colormap,colors,(unsigned int) number_colors,
8283             &pixel->background_color);
8284         }
8285       XBestPixel(display,colormap,colors,(unsigned int) number_colors,
8286         &pixel->border_color);
8287       XBestPixel(display,colormap,colors,(unsigned int) number_colors,
8288         &pixel->matte_color);
8289       XBestPixel(display,colormap,colors,(unsigned int) number_colors,
8290         &pixel->highlight_color);
8291       XBestPixel(display,colormap,colors,(unsigned int) number_colors,
8292         &pixel->shadow_color);
8293       XBestPixel(display,colormap,colors,(unsigned int) number_colors,
8294         &pixel->depth_color);
8295       XBestPixel(display,colormap,colors,(unsigned int) number_colors,
8296         &pixel->trough_color);
8297       for (i=0; i < MaxNumberPens; i++)
8298       {
8299         XBestPixel(display,colormap,colors,(unsigned int) number_colors,
8300           &pixel->pen_colors[i]);
8301         pixel->pixels[image->colors+i]=pixel->pen_colors[i].pixel;
8302       }
8303       pixel->colors=(ssize_t) (image->colors+MaxNumberPens);
8304     }
8305   colors=(XColor *) RelinquishMagickMemory(colors);
8306   if (IsEventLogging())
8307     {
8308       (void) LogMagickEvent(X11Event,GetMagickModule(),"Standard Colormap:");
8309       (void) LogMagickEvent(X11Event,GetMagickModule(),"  colormap id: 0x%lx",
8310         map_info->colormap);
8311       (void) LogMagickEvent(X11Event,GetMagickModule(),
8312         "  red, green, blue max: %lu %lu %lu",map_info->red_max,
8313         map_info->green_max,map_info->blue_max);
8314       (void) LogMagickEvent(X11Event,GetMagickModule(),
8315         "  red, green, blue mult: %lu %lu %lu",map_info->red_mult,
8316         map_info->green_mult,map_info->blue_mult);
8317     }
8318 }
8319 \f
8320 /*
8321 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8322 %                                                                             %
8323 %                                                                             %
8324 %                                                                             %
8325 %   X M a k e W i n d o w                                                     %
8326 %                                                                             %
8327 %                                                                             %
8328 %                                                                             %
8329 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8330 %
8331 %  XMakeWindow() creates an X11 window.
8332 %
8333 %  The format of the XMakeWindow method is:
8334 %
8335 %      void XMakeWindow(Display *display,Window parent,char **argv,int argc,
8336 %        XClassHint *class_hint,XWMHints *manager_hints,
8337 %        XWindowInfo *window_info)
8338 %
8339 %  A description of each parameter follows:
8340 %
8341 %    o display: Specifies a connection to an X server; returned from
8342 %      XOpenDisplay.
8343 %
8344 %    o parent: Specifies the parent window_info.
8345 %
8346 %    o argv: Specifies the application's argument list.
8347 %
8348 %    o argc: Specifies the number of arguments.
8349 %
8350 %    o class_hint: Specifies a pointer to a X11 XClassHint structure.
8351 %
8352 %    o manager_hints: Specifies a pointer to a X11 XWMHints structure.
8353 %
8354 %    o window_info: Specifies a pointer to a X11 XWindowInfo structure.
8355 %
8356 */
8357 MagickPrivate void XMakeWindow(Display *display,Window parent,char **argv,
8358   int argc,XClassHint *class_hint,XWMHints *manager_hints,
8359   XWindowInfo *window_info)
8360 {
8361 #define MinWindowSize  64
8362
8363   Atom
8364     atom_list[2];
8365
8366   int
8367     gravity;
8368
8369   static XTextProperty
8370     icon_name,
8371     window_name;
8372
8373   Status
8374     status;
8375
8376   XSizeHints
8377     *size_hints;
8378
8379   /*
8380     Set window info hints.
8381   */
8382   (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
8383   assert(display != (Display *) NULL);
8384   assert(window_info != (XWindowInfo *) NULL);
8385   size_hints=XAllocSizeHints();
8386   if (size_hints == (XSizeHints *) NULL)
8387     ThrowXWindowFatalException(XServerFatalError,"UnableToMakeXWindow",argv[0]);
8388   size_hints->flags=(int) window_info->flags;
8389   size_hints->x=window_info->x;
8390   size_hints->y=window_info->y;
8391   size_hints->width=(int) window_info->width;
8392   size_hints->height=(int) window_info->height;
8393   if (window_info->immutable != MagickFalse)
8394     {
8395       /*
8396         Window size cannot be changed.
8397       */
8398       size_hints->min_width=size_hints->width;
8399       size_hints->min_height=size_hints->height;
8400       size_hints->max_width=size_hints->width;
8401       size_hints->max_height=size_hints->height;
8402       size_hints->flags|=PMinSize;
8403       size_hints->flags|=PMaxSize;
8404     }
8405   else
8406     {
8407       /*
8408         Window size can be changed.
8409       */
8410       size_hints->min_width=(int) window_info->min_width;
8411       size_hints->min_height=(int) window_info->min_height;
8412       size_hints->flags|=PResizeInc;
8413       size_hints->width_inc=(int) window_info->width_inc;
8414       size_hints->height_inc=(int) window_info->height_inc;
8415 #if !defined(PRE_R4_ICCCM)
8416       size_hints->flags|=PBaseSize;
8417       size_hints->base_width=size_hints->width_inc;
8418       size_hints->base_height=size_hints->height_inc;
8419 #endif
8420     }
8421   gravity=NorthWestGravity;
8422   if (window_info->geometry != (char *) NULL)
8423     {
8424       char
8425         default_geometry[MaxTextExtent],
8426         geometry[MaxTextExtent];
8427
8428       int
8429         flags;
8430
8431       register char
8432         *p;
8433
8434       /*
8435         User specified geometry.
8436       */
8437       (void) FormatLocaleString(default_geometry,MaxTextExtent,"%dx%d",
8438         size_hints->width,size_hints->height);
8439       (void) CopyMagickString(geometry,window_info->geometry,MaxTextExtent);
8440       p=geometry;
8441       while (strlen(p) != 0)
8442       {
8443         if ((isspace((int) ((unsigned char) *p)) == 0) && (*p != '%'))
8444           p++;
8445         else
8446           (void) CopyMagickString(p,p+1,MaxTextExtent);
8447       }
8448       flags=XWMGeometry(display,window_info->screen,geometry,default_geometry,
8449         window_info->border_width,size_hints,&size_hints->x,&size_hints->y,
8450         &size_hints->width,&size_hints->height,&gravity);
8451       if ((flags & WidthValue) && (flags & HeightValue))
8452         size_hints->flags|=USSize;
8453       if ((flags & XValue) && (flags & YValue))
8454         {
8455           size_hints->flags|=USPosition;
8456           window_info->x=size_hints->x;
8457           window_info->y=size_hints->y;
8458         }
8459     }
8460 #if !defined(PRE_R4_ICCCM)
8461   size_hints->win_gravity=gravity;
8462   size_hints->flags|=PWinGravity;
8463 #endif
8464   if (window_info->id == (Window) NULL)
8465     window_info->id=XCreateWindow(display,parent,window_info->x,window_info->y,
8466       (unsigned int) size_hints->width,(unsigned int) size_hints->height,
8467       window_info->border_width,(int) window_info->depth,InputOutput,
8468       window_info->visual,(unsigned long) window_info->mask,
8469       &window_info->attributes);
8470   else
8471     {
8472       MagickStatusType
8473         mask;
8474
8475       XEvent
8476         sans_event;
8477
8478       XWindowChanges
8479         window_changes;
8480
8481       /*
8482         Window already exists;  change relevant attributes.
8483       */
8484       (void) XChangeWindowAttributes(display,window_info->id,(unsigned long)
8485         window_info->mask,&window_info->attributes);
8486       mask=ConfigureNotify;
8487       while (XCheckTypedWindowEvent(display,window_info->id,(int) mask,&sans_event)) ;
8488       window_changes.x=window_info->x;
8489       window_changes.y=window_info->y;
8490       window_changes.width=(int) window_info->width;
8491       window_changes.height=(int) window_info->height;
8492       mask=(MagickStatusType) (CWWidth | CWHeight);
8493       if (window_info->flags & USPosition)
8494         mask|=CWX | CWY;
8495       (void) XReconfigureWMWindow(display,window_info->id,window_info->screen,
8496         mask,&window_changes);
8497     }
8498   if (window_info->id == (Window) NULL)
8499     ThrowXWindowFatalException(XServerFatalError,"UnableToCreateWindow",
8500       window_info->name);
8501   status=XStringListToTextProperty(&window_info->name,1,&window_name);
8502   if (status == False)
8503     ThrowXWindowFatalException(XServerFatalError,"UnableToCreateTextProperty",
8504       window_info->name);
8505   status=XStringListToTextProperty(&window_info->icon_name,1,&icon_name);
8506   if (status == False)
8507     ThrowXWindowFatalException(XServerFatalError,"UnableToCreateTextProperty",
8508       window_info->icon_name);
8509   if (window_info->icon_geometry != (char *) NULL)
8510     {
8511       int
8512         flags,
8513         height,
8514         width;
8515
8516       /*
8517         User specified icon geometry.
8518       */
8519       size_hints->flags|=USPosition;
8520       flags=XWMGeometry(display,window_info->screen,window_info->icon_geometry,
8521         (char *) NULL,0,size_hints,&manager_hints->icon_x,
8522         &manager_hints->icon_y,&width,&height,&gravity);
8523       if ((flags & XValue) && (flags & YValue))
8524         manager_hints->flags|=IconPositionHint;
8525     }
8526   XSetWMProperties(display,window_info->id,&window_name,&icon_name,argv,argc,
8527     size_hints,manager_hints,class_hint);
8528   if (window_name.value != (void *) NULL)
8529     {
8530       (void) XFree((void *) window_name.value);
8531       window_name.value=(unsigned char *) NULL;
8532       window_name.nitems=0;
8533     }
8534   if (icon_name.value != (void *) NULL)
8535     {
8536       (void) XFree((void *) icon_name.value);
8537       icon_name.value=(unsigned char *) NULL;
8538       icon_name.nitems=0;
8539     }
8540   atom_list[0]=XInternAtom(display,"WM_DELETE_WINDOW",MagickFalse);
8541   atom_list[1]=XInternAtom(display,"WM_TAKE_FOCUS",MagickFalse);
8542   (void) XSetWMProtocols(display,window_info->id,atom_list,2);
8543   (void) XFree((void *) size_hints);
8544   if (window_info->shape != MagickFalse)
8545     {
8546 #if defined(MAGICKCORE_HAVE_SHAPE)
8547       int
8548         error_base,
8549         event_base;
8550
8551       /*
8552         Can we apply a non-rectangular shaping mask?
8553       */
8554       error_base=0;
8555       event_base=0;
8556       if (XShapeQueryExtension(display,&error_base,&event_base) == 0)
8557         window_info->shape=MagickFalse;
8558 #else
8559       window_info->shape=MagickFalse;
8560 #endif
8561     }
8562   if (window_info->shared_memory)
8563     {
8564 #if defined(MAGICKCORE_HAVE_SHARED_MEMORY)
8565       /*
8566         Can we use shared memory with this window?
8567       */
8568       if (XShmQueryExtension(display) == 0)
8569         window_info->shared_memory=MagickFalse;
8570 #else
8571       window_info->shared_memory=MagickFalse;
8572 #endif
8573     }
8574   window_info->image=NewImageList();
8575   window_info->destroy=MagickFalse;
8576 }
8577 \f
8578 /*
8579 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8580 %                                                                             %
8581 %                                                                             %
8582 %                                                                             %
8583 %   X M a g i c k P r o g r e s s M o n i t o r                               %
8584 %                                                                             %
8585 %                                                                             %
8586 %                                                                             %
8587 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8588 %
8589 %  XMagickProgressMonitor() displays the progress a task is making in
8590 %  completing a task.
8591 %
8592 %  The format of the XMagickProgressMonitor method is:
8593 %
8594 %      void XMagickProgressMonitor(const char *task,
8595 %        const MagickOffsetType quantum,const MagickSizeType span,
8596 %        void *client_data)
8597 %
8598 %  A description of each parameter follows:
8599 %
8600 %    o task: Identifies the task in progress.
8601 %
8602 %    o quantum: Specifies the quantum position within the span which represents
8603 %      how much progress has been made in completing a task.
8604 %
8605 %    o span: Specifies the span relative to completing a task.
8606 %
8607 %    o client_data: Pointer to any client data.
8608 %
8609 */
8610
8611 static const char *GetLocaleMonitorMessage(const char *text)
8612 {
8613   char
8614     message[MaxTextExtent],
8615     tag[MaxTextExtent];
8616
8617   const char
8618     *locale_message;
8619
8620   register char
8621     *p;
8622
8623   (void) CopyMagickMemory(tag,text,MaxTextExtent);
8624   p=strrchr(tag,'/');
8625   if (p != (char *) NULL)
8626     *p='\0';
8627   (void) FormatLocaleString(message,MaxTextExtent,"Monitor/%s",tag);
8628   locale_message=GetLocaleMessage(message);
8629   if (locale_message == message)
8630     return(text);
8631   return(locale_message);
8632 }
8633
8634 MagickPrivate MagickBooleanType XMagickProgressMonitor(const char *tag,
8635   const MagickOffsetType quantum,const MagickSizeType span,
8636   void *magick_unused(client_data))
8637 {
8638   XWindows
8639     *windows;
8640
8641   windows=XSetWindows((XWindows *) ~0);
8642   if (windows == (XWindows *) NULL)
8643     return(MagickTrue);
8644   if (windows->info.mapped != MagickFalse)
8645     XProgressMonitorWidget(windows->display,windows,
8646       GetLocaleMonitorMessage(tag),quantum,span);
8647   return(MagickTrue);
8648 }
8649 \f
8650 /*
8651 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8652 %                                                                             %
8653 %                                                                             %
8654 %                                                                             %
8655 %   X Q u e r y C o l o r D a t a b a s e                                     %
8656 %                                                                             %
8657 %                                                                             %
8658 %                                                                             %
8659 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8660 %
8661 %  XQueryColorCompliance() looks up a RGB values for a color given in the target
8662 %  string.
8663 %
8664 %  The format of the XQueryColorDatabase method is:
8665 %
8666 %      MagickBooleanType XQueryColorCompliance(const char *target,XColor *color)
8667 %
8668 %  A description of each parameter follows:
8669 %
8670 %    o target: Specifies the color to lookup in the X color database.
8671 %
8672 %    o color: A pointer to an PixelInfo structure.  The RGB value of the target
8673 %      color is returned as this value.
8674 %
8675 */
8676 MagickPrivate MagickBooleanType XQueryColorCompliance(const char *target,
8677   XColor *color)
8678 {
8679   Colormap
8680     colormap;
8681
8682   static Display
8683     *display = (Display *) NULL;
8684
8685   Status
8686     status;
8687
8688   XColor
8689     xcolor;
8690
8691   /*
8692     Initialize color return value.
8693   */
8694   assert(color != (XColor *) NULL);
8695   color->red=0;
8696   color->green=0;
8697   color->blue=0;
8698   color->flags=(char) (DoRed | DoGreen | DoBlue);
8699   if ((target == (char *) NULL) || (*target == '\0'))
8700     target="#ffffffffffff";
8701   /*
8702     Let the X server define the color for us.
8703   */
8704   if (display == (Display *) NULL)
8705     display=XOpenDisplay((char *) NULL);
8706   if (display == (Display *) NULL)
8707     {
8708       ThrowXWindowFatalException(XServerError,"ColorIsNotKnownToServer",target);
8709       return(MagickFalse);
8710     }
8711   colormap=XDefaultColormap(display,XDefaultScreen(display));
8712   status=XParseColor(display,colormap,(char *) target,&xcolor);
8713   if (status == False)
8714     ThrowXWindowFatalException(XServerError,"ColorIsNotKnownToServer",target)
8715   else
8716     {
8717       color->red=xcolor.red;
8718       color->green=xcolor.green;
8719       color->blue=xcolor.blue;
8720       color->flags=xcolor.flags;
8721     }
8722   return(status != False ? MagickTrue : MagickFalse);
8723 }
8724 \f
8725 /*
8726 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8727 %                                                                             %
8728 %                                                                             %
8729 %                                                                             %
8730 %   X Q u e r y P o s i t i o n                                               %
8731 %                                                                             %
8732 %                                                                             %
8733 %                                                                             %
8734 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8735 %
8736 %  XQueryPosition() gets the pointer coordinates relative to a window.
8737 %
8738 %  The format of the XQueryPosition method is:
8739 %
8740 %      void XQueryPosition(Display *display,const Window window,int *x,int *y)
8741 %
8742 %  A description of each parameter follows:
8743 %
8744 %    o display: Specifies a connection to an X server;  returned from
8745 %      XOpenDisplay.
8746 %
8747 %    o window: Specifies a pointer to a Window.
8748 %
8749 %    o x: Return the x coordinate of the pointer relative to the origin of the
8750 %      window.
8751 %
8752 %    o y: Return the y coordinate of the pointer relative to the origin of the
8753 %      window.
8754 %
8755 */
8756 MagickPrivate void XQueryPosition(Display *display,const Window window,int *x,int *y)
8757 {
8758   int
8759     x_root,
8760     y_root;
8761
8762   unsigned int
8763     mask;
8764
8765   Window
8766     root_window;
8767
8768   (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
8769   assert(display != (Display *) NULL);
8770   assert(window != (Window) NULL);
8771   assert(x != (int *) NULL);
8772   assert(y != (int *) NULL);
8773   (void) XQueryPointer(display,window,&root_window,&root_window,&x_root,&y_root,
8774     x,y,&mask);
8775 }
8776 \f
8777 /*
8778 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8779 %                                                                             %
8780 %                                                                             %
8781 %                                                                             %
8782 %   X R e f r e s h W i n d o w                                               %
8783 %                                                                             %
8784 %                                                                             %
8785 %                                                                             %
8786 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8787 %
8788 %  XRefreshWindow() refreshes an image in a X window.
8789 %
8790 %  The format of the XRefreshWindow method is:
8791 %
8792 %      void XRefreshWindow(Display *display,const XWindowInfo *window,
8793 %        const XEvent *event)
8794 %
8795 %  A description of each parameter follows:
8796 %
8797 %    o display: Specifies a connection to an X server;  returned from
8798 %      XOpenDisplay.
8799 %
8800 %    o window: Specifies a pointer to a XWindowInfo structure.
8801 %
8802 %    o event: Specifies a pointer to a XEvent structure.  If it is NULL,
8803 %      the entire image is refreshed.
8804 %
8805 */
8806 MagickPrivate void XRefreshWindow(Display *display,const XWindowInfo *window,
8807   const XEvent *event)
8808 {
8809   int
8810     x,
8811     y;
8812
8813   unsigned int
8814     height,
8815     width;
8816
8817   (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
8818   assert(display != (Display *) NULL);
8819   assert(window != (XWindowInfo *) NULL);
8820   if (window->ximage == (XImage *) NULL)
8821     return;
8822   if (event != (XEvent *) NULL)
8823     {
8824       /*
8825         Determine geometry from expose event.
8826       */
8827       x=event->xexpose.x;
8828       y=event->xexpose.y;
8829       width=(unsigned int) event->xexpose.width;
8830       height=(unsigned int) event->xexpose.height;
8831     }
8832   else
8833     {
8834       XEvent
8835         sans_event;
8836
8837       /*
8838         Refresh entire window; discard outstanding expose events.
8839       */
8840       x=0;
8841       y=0;
8842       width=window->width;
8843       height=window->height;
8844       while (XCheckTypedWindowEvent(display,window->id,Expose,&sans_event)) ;
8845       if (window->matte_pixmap != (Pixmap) NULL)
8846         {
8847 #if defined(MAGICKCORE_HAVE_SHAPE)
8848           if (window->shape != MagickFalse)
8849             XShapeCombineMask(display,window->id,ShapeBounding,0,0,
8850               window->matte_pixmap,ShapeSet);
8851 #endif
8852         }
8853     }
8854   /*
8855     Check boundary conditions.
8856   */
8857   if ((window->ximage->width-(x+window->x)) < (int) width)
8858     width=(unsigned int) (window->ximage->width-(x+window->x));
8859   if ((window->ximage->height-(y+window->y)) < (int) height)
8860     height=(unsigned int) (window->ximage->height-(y+window->y));
8861   /*
8862     Refresh image.
8863   */
8864   if (window->matte_pixmap != (Pixmap) NULL)
8865     (void) XSetClipMask(display,window->annotate_context,window->matte_pixmap);
8866   if (window->pixmap != (Pixmap) NULL)
8867     {
8868       if (window->depth > 1)
8869         (void) XCopyArea(display,window->pixmap,window->id,
8870           window->annotate_context,x+window->x,y+window->y,width,height,x,y);
8871       else
8872         (void) XCopyPlane(display,window->pixmap,window->id,
8873           window->highlight_context,x+window->x,y+window->y,width,height,x,y,
8874           1L);
8875     }
8876   else
8877     {
8878 #if defined(MAGICKCORE_HAVE_SHARED_MEMORY)
8879       if (window->shared_memory)
8880         (void) XShmPutImage(display,window->id,window->annotate_context,
8881           window->ximage,x+window->x,y+window->y,x,y,width,height,MagickTrue);
8882 #endif
8883       if (window->shared_memory == MagickFalse)
8884         (void) XPutImage(display,window->id,window->annotate_context,
8885           window->ximage,x+window->x,y+window->y,x,y,width,height);
8886     }
8887   if (window->matte_pixmap != (Pixmap) NULL)
8888     (void) XSetClipMask(display,window->annotate_context,None);
8889   (void) XFlush(display);
8890 }
8891 \f
8892 /*
8893 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8894 %                                                                             %
8895 %                                                                             %
8896 %                                                                             %
8897 %   X R e m o t e C o m m a n d                                               %
8898 %                                                                             %
8899 %                                                                             %
8900 %                                                                             %
8901 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8902 %
8903 %  XRemoteCommand() forces a remote display(1) to display the specified
8904 %  image filename.
8905 %
8906 %  The format of the XRemoteCommand method is:
8907 %
8908 %      MagickBooleanType XRemoteCommand(Display *display,const char *window,
8909 %        const char *filename)
8910 %
8911 %  A description of each parameter follows:
8912 %
8913 %    o display: Specifies a connection to an X server; returned from
8914 %      XOpenDisplay.
8915 %
8916 %    o window: Specifies the name or id of an X window.
8917 %
8918 %    o filename: the name of the image filename to display.
8919 %
8920 */
8921 MagickExport MagickBooleanType XRemoteCommand(Display *display,
8922   const char *window,const char *filename)
8923 {
8924   Atom
8925     remote_atom;
8926
8927   Window
8928     remote_window,
8929     root_window;
8930
8931   assert(filename != (char *) NULL);
8932   (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",filename);
8933   if (display == (Display *) NULL)
8934     display=XOpenDisplay((char *) NULL);
8935   if (display == (Display *) NULL)
8936     {
8937       ThrowXWindowException(XServerError,"UnableToOpenXServer",filename);
8938       return(MagickFalse);
8939     }
8940   remote_atom=XInternAtom(display,"IM_PROTOCOLS",MagickFalse);
8941   remote_window=(Window) NULL;
8942   root_window=XRootWindow(display,XDefaultScreen(display));
8943   if (window != (char *) NULL)
8944     {
8945       /*
8946         Search window hierarchy and identify any clients by name or ID.
8947       */
8948       if (isdigit((unsigned char) *window) != 0)
8949         remote_window=XWindowByID(display,root_window,(Window)
8950           strtol((char *) window,(char **) NULL,0));
8951       if (remote_window == (Window) NULL)
8952         remote_window=XWindowByName(display,root_window,window);
8953     }
8954   if (remote_window == (Window) NULL)
8955     remote_window=XWindowByProperty(display,root_window,remote_atom);
8956   if (remote_window == (Window) NULL)
8957     {
8958       ThrowXWindowException(XServerError,"UnableToConnectToRemoteDisplay",
8959         filename);
8960       return(MagickFalse);
8961     }
8962   /*
8963     Send remote command.
8964   */
8965   remote_atom=XInternAtom(display,"IM_REMOTE_COMMAND",MagickFalse);
8966   (void) XChangeProperty(display,remote_window,remote_atom,XA_STRING,8,
8967     PropModeReplace,(unsigned char *) filename,(int) strlen(filename));
8968   (void) XSync(display,MagickFalse);
8969   return(MagickTrue);
8970 }
8971 \f
8972 /*
8973 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8974 %                                                                             %
8975 %                                                                             %
8976 %                                                                             %
8977 %   X R e t a i n W i n d o w C o l o r s                                     %
8978 %                                                                             %
8979 %                                                                             %
8980 %                                                                             %
8981 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8982 %
8983 %  XRetainWindowColors() sets X11 color resources on a window.  This preserves
8984 %  the colors associated with an image displayed on the window.
8985 %
8986 %  The format of the XRetainWindowColors method is:
8987 %
8988 %      void XRetainWindowColors(Display *display,const Window window)
8989 %
8990 %  A description of each parameter follows:
8991 %
8992 %    o display: Specifies a connection to an X server; returned from
8993 %      XOpenDisplay.
8994 %
8995 %    o window: Specifies a pointer to a XWindowInfo structure.
8996 %
8997 */
8998 MagickExport void XRetainWindowColors(Display *display,const Window window)
8999 {
9000   Atom
9001     property;
9002
9003   Pixmap
9004     pixmap;
9005
9006   /*
9007     Put property on the window.
9008   */
9009   (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
9010   assert(display != (Display *) NULL);
9011   assert(window != (Window) NULL);
9012   property=XInternAtom(display,"_XSETROOT_ID",MagickFalse);
9013   if (property == (Atom) NULL)
9014     {
9015       ThrowXWindowFatalException(XServerError,"UnableToCreateProperty",
9016         "_XSETROOT_ID");
9017       return;
9018     }
9019   pixmap=XCreatePixmap(display,window,1,1,1);
9020   if (pixmap == (Pixmap) NULL)
9021     {
9022       ThrowXWindowFatalException(XServerError,"UnableToCreateBitmap","");
9023       return;
9024     }
9025   (void) XChangeProperty(display,window,property,XA_PIXMAP,32,PropModeReplace,
9026     (unsigned char *) &pixmap,1);
9027   (void) XSetCloseDownMode(display,RetainPermanent);
9028 }
9029 \f
9030 /*
9031 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9032 %                                                                             %
9033 %                                                                             %
9034 %                                                                             %
9035 %   X S e l e c t W i n d o w                                                 %
9036 %                                                                             %
9037 %                                                                             %
9038 %                                                                             %
9039 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9040 %
9041 %  XSelectWindow() allows a user to select a window using the mouse.  If the
9042 %  mouse moves, a cropping rectangle is drawn and the extents of the rectangle
9043 %  is returned in the crop_info structure.
9044 %
9045 %  The format of the XSelectWindow function is:
9046 %
9047 %      target_window=XSelectWindow(display,crop_info)
9048 %
9049 %  A description of each parameter follows:
9050 %
9051 %    o window: XSelectWindow returns the window id.
9052 %
9053 %    o display: Specifies a pointer to the Display structure;  returned from
9054 %      XOpenDisplay.
9055 %
9056 %    o crop_info: Specifies a pointer to a RectangleInfo structure.  It
9057 %      contains the extents of any cropping rectangle.
9058 %
9059 */
9060 static Window XSelectWindow(Display *display,RectangleInfo *crop_info)
9061 {
9062 #define MinimumCropArea  (unsigned int) 9
9063
9064   Cursor
9065     target_cursor;
9066
9067   GC
9068     annotate_context;
9069
9070   int
9071     presses,
9072     x_offset,
9073     y_offset;
9074
9075   Status
9076     status;
9077
9078   Window
9079     root_window,
9080     target_window;
9081
9082   XEvent
9083     event;
9084
9085   XGCValues
9086     context_values;
9087
9088   /*
9089     Initialize graphic context.
9090   */
9091   (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
9092   assert(display != (Display *) NULL);
9093   assert(crop_info != (RectangleInfo *) NULL);
9094   root_window=XRootWindow(display,XDefaultScreen(display));
9095   context_values.background=XBlackPixel(display,XDefaultScreen(display));
9096   context_values.foreground=XWhitePixel(display,XDefaultScreen(display));
9097   context_values.function=GXinvert;
9098   context_values.plane_mask=
9099     context_values.background ^ context_values.foreground;
9100   context_values.subwindow_mode=IncludeInferiors;
9101   annotate_context=XCreateGC(display,root_window,(size_t) (GCBackground |
9102     GCForeground | GCFunction | GCSubwindowMode),&context_values);
9103   if (annotate_context == (GC) NULL)
9104     return(MagickFalse);
9105   /*
9106     Grab the pointer using target cursor.
9107   */
9108   target_cursor=XMakeCursor(display,root_window,XDefaultColormap(display,
9109     XDefaultScreen(display)),(char * ) "white",(char * ) "black");
9110   status=XGrabPointer(display,root_window,MagickFalse,(unsigned int)
9111     (ButtonPressMask | ButtonReleaseMask | ButtonMotionMask),GrabModeSync,
9112     GrabModeAsync,root_window,target_cursor,CurrentTime);
9113   if (status != GrabSuccess)
9114     {
9115       ThrowXWindowFatalException(XServerError,"UnableToGrabMouse","");
9116       return((Window) NULL);
9117     }
9118   /*
9119     Select a window.
9120   */
9121   crop_info->width=0;
9122   crop_info->height=0;
9123   presses=0;
9124   target_window=(Window) NULL;
9125   x_offset=0;
9126   y_offset=0;
9127   do
9128   {
9129     if ((crop_info->width*crop_info->height) >= MinimumCropArea)
9130       (void) XDrawRectangle(display,root_window,annotate_context,
9131         (int) crop_info->x,(int) crop_info->y,(unsigned int) crop_info->width-1,
9132         (unsigned int) crop_info->height-1);
9133     /*
9134       Allow another event.
9135     */
9136     (void) XAllowEvents(display,SyncPointer,CurrentTime);
9137     (void) XWindowEvent(display,root_window,ButtonPressMask |
9138       ButtonReleaseMask | ButtonMotionMask,&event);
9139     if ((crop_info->width*crop_info->height) >= MinimumCropArea)
9140       (void) XDrawRectangle(display,root_window,annotate_context,
9141         (int) crop_info->x,(int) crop_info->y,(unsigned int) crop_info->width-1,
9142         (unsigned int) crop_info->height-1);
9143     switch (event.type)
9144     {
9145       case ButtonPress:
9146       {
9147         target_window=XGetSubwindow(display,event.xbutton.subwindow,
9148           event.xbutton.x,event.xbutton.y);
9149         if (target_window == (Window) NULL)
9150           target_window=root_window;
9151         x_offset=event.xbutton.x_root;
9152         y_offset=event.xbutton.y_root;
9153         crop_info->x=(ssize_t) x_offset;
9154         crop_info->y=(ssize_t) y_offset;
9155         crop_info->width=0;
9156         crop_info->height=0;
9157         presses++;
9158         break;
9159       }
9160       case ButtonRelease:
9161       {
9162         presses--;
9163         break;
9164       }
9165       case MotionNotify:
9166       {
9167         /*
9168           Discard pending button motion events.
9169         */
9170         while (XCheckMaskEvent(display,ButtonMotionMask,&event)) ;
9171         crop_info->x=(ssize_t) event.xmotion.x;
9172         crop_info->y=(ssize_t) event.xmotion.y;
9173         /*
9174           Check boundary conditions.
9175         */
9176         if ((int) crop_info->x < x_offset)
9177           crop_info->width=(size_t) (x_offset-crop_info->x);
9178         else
9179           {
9180             crop_info->width=(size_t) (crop_info->x-x_offset);
9181             crop_info->x=(ssize_t) x_offset;
9182           }
9183         if ((int) crop_info->y < y_offset)
9184           crop_info->height=(size_t) (y_offset-crop_info->y);
9185         else
9186           {
9187             crop_info->height=(size_t) (crop_info->y-y_offset);
9188             crop_info->y=(ssize_t) y_offset;
9189           }
9190       }
9191       default:
9192         break;
9193     }
9194   } while ((target_window == (Window) NULL) || (presses > 0));
9195   (void) XUngrabPointer(display,CurrentTime);
9196   (void) XFreeCursor(display,target_cursor);
9197   (void) XFreeGC(display,annotate_context);
9198   if ((crop_info->width*crop_info->height) < MinimumCropArea)
9199     {
9200       crop_info->width=0;
9201       crop_info->height=0;
9202     }
9203   if ((crop_info->width != 0) && (crop_info->height != 0))
9204     target_window=root_window;
9205   return(target_window);
9206 }
9207 \f
9208 /*
9209 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9210 %                                                                             %
9211 %                                                                             %
9212 %                                                                             %
9213 %   X S e t C u r s o r S t a t e                                             %
9214 %                                                                             %
9215 %                                                                             %
9216 %                                                                             %
9217 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9218 %
9219 %  XSetCursorState() sets the cursor state to busy, otherwise the cursor are
9220 %  reset to their default.
9221 %
9222 %  The format of the XXSetCursorState method is:
9223 %
9224 %      XSetCursorState(display,windows,const MagickStatusType state)
9225 %
9226 %  A description of each parameter follows:
9227 %
9228 %    o display: Specifies a connection to an X server;  returned from
9229 %      XOpenDisplay.
9230 %
9231 %    o windows: Specifies a pointer to a XWindows structure.
9232 %
9233 %    o state: An unsigned integer greater than 0 sets the cursor state
9234 %      to busy, otherwise the cursor are reset to their default.
9235 %
9236 */
9237 MagickPrivate void XSetCursorState(Display *display,XWindows *windows,
9238   const MagickStatusType state)
9239 {
9240   (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
9241   assert(display != (Display *) NULL);
9242   assert(windows != (XWindows *) NULL);
9243   if (state)
9244     {
9245       (void) XCheckDefineCursor(display,windows->image.id,
9246         windows->image.busy_cursor);
9247       (void) XCheckDefineCursor(display,windows->pan.id,
9248         windows->pan.busy_cursor);
9249       (void) XCheckDefineCursor(display,windows->magnify.id,
9250         windows->magnify.busy_cursor);
9251       (void) XCheckDefineCursor(display,windows->command.id,
9252         windows->command.busy_cursor);
9253     }
9254   else
9255     {
9256       (void) XCheckDefineCursor(display,windows->image.id,
9257         windows->image.cursor);
9258       (void) XCheckDefineCursor(display,windows->pan.id,windows->pan.cursor);
9259       (void) XCheckDefineCursor(display,windows->magnify.id,
9260         windows->magnify.cursor);
9261       (void) XCheckDefineCursor(display,windows->command.id,
9262         windows->command.cursor);
9263       (void) XCheckDefineCursor(display,windows->command.id,
9264         windows->widget.cursor);
9265       (void) XWithdrawWindow(display,windows->info.id,windows->info.screen);
9266     }
9267   windows->info.mapped=MagickFalse;
9268 }
9269 \f
9270 /*
9271 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9272 %                                                                             %
9273 %                                                                             %
9274 %                                                                             %
9275 %   X S e t W i n d o w s                                                     %
9276 %                                                                             %
9277 %                                                                             %
9278 %                                                                             %
9279 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9280 %
9281 %  XSetWindows() sets the X windows structure if the windows info is specified.
9282 %  Otherwise the current windows structure is returned.
9283 %
9284 %  The format of the XSetWindows method is:
9285 %
9286 %      XWindows *XSetWindows(XWindows *windows_info)
9287 %
9288 %  A description of each parameter follows:
9289 %
9290 %    o windows_info: Initialize the Windows structure with this information.
9291 %
9292 */
9293 MagickPrivate XWindows *XSetWindows(XWindows *windows_info)
9294 {
9295   static XWindows
9296     *windows = (XWindows *) NULL;
9297
9298   if (windows_info != (XWindows *) ~0)
9299     {
9300       windows=(XWindows *) RelinquishMagickMemory(windows);
9301       windows=windows_info;
9302     }
9303   return(windows);
9304 }
9305 /*
9306 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9307 %                                                                             %
9308 %                                                                             %
9309 %                                                                             %
9310 %   X U s e r P r e f e r e n c e s                                           %
9311 %                                                                             %
9312 %                                                                             %
9313 %                                                                             %
9314 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9315 %
9316 %  XUserPreferences() saves the preferences in a configuration file in the
9317 %  users' home directory.
9318 %
9319 %  The format of the XUserPreferences method is:
9320 %
9321 %      void XUserPreferences(XResourceInfo *resource_info)
9322 %
9323 %  A description of each parameter follows:
9324 %
9325 %    o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
9326 %
9327 */
9328 MagickPrivate void XUserPreferences(XResourceInfo *resource_info)
9329 {
9330 #if defined(X11_PREFERENCES_PATH)
9331   char
9332     cache[MaxTextExtent],
9333     filename[MaxTextExtent],
9334     specifier[MaxTextExtent];
9335
9336   const char
9337     *client_name,
9338     *value;
9339
9340   XrmDatabase
9341     preferences_database;
9342
9343   /*
9344     Save user preferences to the client configuration file.
9345   */
9346   assert(resource_info != (XResourceInfo *) NULL);
9347   client_name=GetClientName();
9348   preferences_database=XrmGetStringDatabase("");
9349   (void) FormatLocaleString(specifier,MaxTextExtent,"%s.backdrop",client_name);
9350   value=resource_info->backdrop ? "True" : "False";
9351   XrmPutStringResource(&preferences_database,specifier,(char *) value);
9352   (void) FormatLocaleString(specifier,MaxTextExtent,"%s.colormap",client_name);
9353   value=resource_info->colormap == SharedColormap ? "Shared" : "Private";
9354   XrmPutStringResource(&preferences_database,specifier,(char *) value);
9355   (void) FormatLocaleString(specifier,MaxTextExtent,"%s.confirmExit",
9356     client_name);
9357   value=resource_info->confirm_exit ? "True" : "False";
9358   XrmPutStringResource(&preferences_database,specifier,(char *) value);
9359   (void) FormatLocaleString(specifier,MaxTextExtent,"%s.confirmEdit",
9360     client_name);
9361   value=resource_info->confirm_edit ? "True" : "False";
9362   XrmPutStringResource(&preferences_database,specifier,(char *) value);
9363   (void) FormatLocaleString(specifier,MaxTextExtent,"%s.displayWarnings",
9364     client_name);
9365   value=resource_info->display_warnings ? "True" : "False";
9366   XrmPutStringResource(&preferences_database,specifier,(char *) value);
9367   (void) FormatLocaleString(specifier,MaxTextExtent,"%s.dither",client_name);
9368   value=resource_info->quantize_info->dither_method != NoDitherMethod ?
9369     "True" : "False";
9370   XrmPutStringResource(&preferences_database,specifier,(char *) value);
9371   (void) FormatLocaleString(specifier,MaxTextExtent,"%s.gammaCorrect",
9372     client_name);
9373   value=resource_info->gamma_correct ? "True" : "False";
9374   XrmPutStringResource(&preferences_database,specifier,(char *) value);
9375   (void) FormatLocaleString(specifier,MaxTextExtent,"%s.undoCache",client_name);
9376   (void) FormatLocaleString(cache,MaxTextExtent,"%.20g",(double)
9377     resource_info->undo_cache);
9378   XrmPutStringResource(&preferences_database,specifier,cache);
9379   (void) FormatLocaleString(specifier,MaxTextExtent,"%s.usePixmap",client_name);
9380   value=resource_info->use_pixmap ? "True" : "False";
9381   XrmPutStringResource(&preferences_database,specifier,(char *) value);
9382   (void) FormatLocaleString(filename,MaxTextExtent,"%s%src",
9383     X11_PREFERENCES_PATH,client_name);
9384   ExpandFilename(filename);
9385   XrmPutFileDatabase(preferences_database,filename);
9386 #endif
9387 }
9388 \f
9389 /*
9390 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9391 %                                                                             %
9392 %                                                                             %
9393 %                                                                             %
9394 %   X V i s u a l C l a s s N a m e                                           %
9395 %                                                                             %
9396 %                                                                             %
9397 %                                                                             %
9398 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9399 %
9400 %  XVisualClassName() returns the visual class name as a character string.
9401 %
9402 %  The format of the XVisualClassName method is:
9403 %
9404 %      char *XVisualClassName(const int visual_class)
9405 %
9406 %  A description of each parameter follows:
9407 %
9408 %    o visual_type: XVisualClassName returns the visual class as a character
9409 %      string.
9410 %
9411 %    o class: Specifies the visual class.
9412 %
9413 */
9414 static const char *XVisualClassName(const int visual_class)
9415 {
9416   switch (visual_class)
9417   {
9418     case StaticGray: return("StaticGray");
9419     case GrayScale: return("GrayScale");
9420     case StaticColor: return("StaticColor");
9421     case PseudoColor: return("PseudoColor");
9422     case TrueColor: return("TrueColor");
9423     case DirectColor: return("DirectColor");
9424   }
9425   return("unknown visual class");
9426 }
9427 \f
9428 /*
9429 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9430 %                                                                             %
9431 %                                                                             %
9432 %                                                                             %
9433 %   X W a r n i n g                                                           %
9434 %                                                                             %
9435 %                                                                             %
9436 %                                                                             %
9437 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9438 %
9439 %  XWarning() displays a warning reason in a Notice widget.
9440 %
9441 %  The format of the XWarning method is:
9442 %
9443 %      void XWarning(const unsigned int warning,const char *reason,
9444 %        const char *description)
9445 %
9446 %  A description of each parameter follows:
9447 %
9448 %    o warning: Specifies the numeric warning category.
9449 %
9450 %    o reason: Specifies the reason to display before terminating the
9451 %      program.
9452 %
9453 %    o description: Specifies any description to the reason.
9454 %
9455 */
9456 MagickPrivate void XWarning(const ExceptionType magick_unused(warning),
9457   const char *reason,const char *description)
9458 {
9459   char
9460     text[MaxTextExtent];
9461
9462   XWindows
9463     *windows;
9464
9465   if (reason == (char *) NULL)
9466     return;
9467   (void) CopyMagickString(text,reason,MaxTextExtent);
9468   (void) ConcatenateMagickString(text,":",MaxTextExtent);
9469   windows=XSetWindows((XWindows *) ~0);
9470   XNoticeWidget(windows->display,windows,text,(char *) description);
9471 }
9472 \f
9473 /*
9474 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9475 %                                                                             %
9476 %                                                                             %
9477 %                                                                             %
9478 %   X W i n d o w B y I D                                                     %
9479 %                                                                             %
9480 %                                                                             %
9481 %                                                                             %
9482 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9483 %
9484 %  XWindowByID() locates a child window with a given ID.  If not window with
9485 %  the given name is found, 0 is returned.   Only the window specified and its
9486 %  subwindows are searched.
9487 %
9488 %  The format of the XWindowByID function is:
9489 %
9490 %      child=XWindowByID(display,window,id)
9491 %
9492 %  A description of each parameter follows:
9493 %
9494 %    o child: XWindowByID returns the window with the specified
9495 %      id.  If no windows are found, XWindowByID returns 0.
9496 %
9497 %    o display: Specifies a pointer to the Display structure;  returned from
9498 %      XOpenDisplay.
9499 %
9500 %    o id: Specifies the id of the window to locate.
9501 %
9502 */
9503 MagickPrivate Window XWindowByID(Display *display,const Window root_window,
9504   const size_t id)
9505 {
9506   RectangleInfo
9507     rectangle_info;
9508
9509   register int
9510     i;
9511
9512   Status
9513     status;
9514
9515   unsigned int
9516     number_children;
9517
9518   Window
9519     child,
9520     *children,
9521     window;
9522
9523   (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
9524   assert(display != (Display *) NULL);
9525   assert(root_window != (Window) NULL);
9526   if (id == 0)
9527     return(XSelectWindow(display,&rectangle_info));
9528   if (root_window == id)
9529     return(root_window);
9530   status=XQueryTree(display,root_window,&child,&child,&children,
9531     &number_children);
9532   if (status == False)
9533     return((Window) NULL);
9534   window=(Window) NULL;
9535   for (i=0; i < (int) number_children; i++)
9536   {
9537     /*
9538       Search each child and their children.
9539     */
9540     window=XWindowByID(display,children[i],id);
9541     if (window != (Window) NULL)
9542       break;
9543   }
9544   if (children != (Window *) NULL)
9545     (void) XFree((void *) children);
9546   return(window);
9547 }
9548 \f
9549 /*
9550 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9551 %                                                                             %
9552 %                                                                             %
9553 %                                                                             %
9554 %   X W i n d o w B y N a m e                                                 %
9555 %                                                                             %
9556 %                                                                             %
9557 %                                                                             %
9558 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9559 %
9560 %  XWindowByName() locates a window with a given name on a display.  If no
9561 %  window with the given name is found, 0 is returned. If more than one window
9562 %  has the given name, the first one is returned.  Only root and its children
9563 %  are searched.
9564 %
9565 %  The format of the XWindowByName function is:
9566 %
9567 %      window=XWindowByName(display,root_window,name)
9568 %
9569 %  A description of each parameter follows:
9570 %
9571 %    o window: XWindowByName returns the window id.
9572 %
9573 %    o display: Specifies a pointer to the Display structure;  returned from
9574 %      XOpenDisplay.
9575 %
9576 %    o root_window: Specifies the id of the root window.
9577 %
9578 %    o name: Specifies the name of the window to locate.
9579 %
9580 */
9581 MagickPrivate Window XWindowByName(Display *display,const Window root_window,
9582   const char *name)
9583 {
9584   register int
9585     i;
9586
9587   Status
9588     status;
9589
9590   unsigned int
9591     number_children;
9592
9593   Window
9594     *children,
9595     child,
9596     window;
9597
9598   XTextProperty
9599     window_name;
9600
9601   assert(display != (Display *) NULL);
9602   assert(root_window != (Window) NULL);
9603   assert(name != (char *) NULL);
9604   (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",name);
9605   if (XGetWMName(display,root_window,&window_name) != 0)
9606     if (LocaleCompare((char *) window_name.value,name) == 0)
9607       return(root_window);
9608   status=XQueryTree(display,root_window,&child,&child,&children,
9609     &number_children);
9610   if (status == False)
9611     return((Window) NULL);
9612   window=(Window) NULL;
9613   for (i=0; i < (int) number_children; i++)
9614   {
9615     /*
9616       Search each child and their children.
9617     */
9618     window=XWindowByName(display,children[i],name);
9619     if (window != (Window) NULL)
9620       break;
9621   }
9622   if (children != (Window *) NULL)
9623     (void) XFree((void *) children);
9624   return(window);
9625 }
9626 \f
9627 /*
9628 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9629 %                                                                             %
9630 %                                                                             %
9631 %                                                                             %
9632 %   X W i n d o w B y P r o p e r y                                           %
9633 %                                                                             %
9634 %                                                                             %
9635 %                                                                             %
9636 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9637 %
9638 %  XWindowByProperty() locates a child window with a given property. If not
9639 %  window with the given name is found, 0 is returned.  If more than one window
9640 %  has the given property, the first one is returned.  Only the window
9641 %  specified and its subwindows are searched.
9642 %
9643 %  The format of the XWindowByProperty function is:
9644 %
9645 %      child=XWindowByProperty(display,window,property)
9646 %
9647 %  A description of each parameter follows:
9648 %
9649 %    o child: XWindowByProperty returns the window id with the specified
9650 %      property.  If no windows are found, XWindowByProperty returns 0.
9651 %
9652 %    o display: Specifies a pointer to the Display structure;  returned from
9653 %      XOpenDisplay.
9654 %
9655 %    o property: Specifies the property of the window to locate.
9656 %
9657 */
9658 MagickPrivate Window XWindowByProperty(Display *display,const Window window,
9659   const Atom property)
9660 {
9661   Atom
9662     type;
9663
9664   int
9665     format;
9666
9667   Status
9668     status;
9669
9670   unsigned char
9671     *data;
9672
9673   unsigned int
9674     i,
9675     number_children;
9676
9677   unsigned long
9678     after,
9679     number_items;
9680
9681   Window
9682     child,
9683     *children,
9684     parent,
9685     root;
9686
9687   (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
9688   assert(display != (Display *) NULL);
9689   assert(window != (Window) NULL);
9690   assert(property != (Atom) NULL);
9691   status=XQueryTree(display,window,&root,&parent,&children,&number_children);
9692   if (status == False)
9693     return((Window) NULL);
9694   type=(Atom) NULL;
9695   child=(Window) NULL;
9696   for (i=0; (i < number_children) && (child == (Window) NULL); i++)
9697   {
9698     status=XGetWindowProperty(display,children[i],property,0L,0L,MagickFalse,
9699       (Atom) AnyPropertyType,&type,&format,&number_items,&after,&data);
9700     if (data != NULL)
9701       (void) XFree((void *) data);
9702     if ((status == Success) && (type != (Atom) NULL))
9703       child=children[i];
9704   }
9705   for (i=0; (i < number_children) && (child == (Window) NULL); i++)
9706     child=XWindowByProperty(display,children[i],property);
9707   if (children != (Window *) NULL)
9708     (void) XFree((void *) children);
9709   return(child);
9710 }
9711 #else
9712 \f
9713 /*
9714 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9715 %                                                                             %
9716 %                                                                             %
9717 %                                                                             %
9718 %   X I m p o r t I m a g e                                                   %
9719 %                                                                             %
9720 %                                                                             %
9721 %                                                                             %
9722 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9723 %
9724 %  XImportImage() reads an image from an X window.
9725 %
9726 %  The format of the XImportImage method is:
9727 %
9728 %      Image *XImportImage(const ImageInfo *image_info,XImportInfo *ximage_info,
9729 %        ExceptionInfo *exception)
9730 %
9731 %  A description of each parameter follows:
9732 %
9733 %    o image_info: the image info..
9734 %
9735 %    o ximage_info: Specifies a pointer to an XImportInfo structure.
9736 %
9737 %    o exception: return any errors or warnings in this structure.
9738 %
9739 */
9740 MagickPrivate Image *XImportImage(const ImageInfo *image_info,
9741   XImportInfo *ximage_info,ExceptionInfo *exception)
9742 {
9743   assert(image_info != (const ImageInfo *) NULL);
9744   assert(image_info->signature == MagickSignature);
9745   if (image_info->debug != MagickFalse)
9746     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
9747       image_info->filename);
9748   assert(ximage_info != (XImportInfo *) NULL);
9749   assert(exception != (ExceptionInfo *) NULL);
9750   assert(exception->signature == MagickSignature);
9751   return((Image *) NULL);
9752 }
9753 #endif
9754 \f
9755 /*
9756 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9757 %                                                                             %
9758 %                                                                             %
9759 %                                                                             %
9760 +   X C o m p o n e n t G e n e s i s                                         %
9761 %                                                                             %
9762 %                                                                             %
9763 %                                                                             %
9764 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9765 %
9766 %  XComponentGenesis() instantiates the X component.
9767 %
9768 %  The format of the XComponentGenesis method is:
9769 %
9770 %      MagickBooleanType XComponentGenesis(void)
9771 %
9772 */
9773 MagickPrivate MagickBooleanType XComponentGenesis(void)
9774 {
9775   return(MagickTrue);
9776 }
9777 \f
9778 /*
9779 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9780 %                                                                             %
9781 %                                                                             %
9782 %                                                                             %
9783 %   X G e t I m p o r t I n f o                                               %
9784 %                                                                             %
9785 %                                                                             %
9786 %                                                                             %
9787 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9788 %
9789 %  XGetImportInfo() initializes the XImportInfo structure.
9790 %
9791 %  The format of the XGetImportInfo method is:
9792 %
9793 %      void XGetImportInfo(XImportInfo *ximage_info)
9794 %
9795 %  A description of each parameter follows:
9796 %
9797 %    o ximage_info: Specifies a pointer to an ImageInfo structure.
9798 %
9799 */
9800 MagickExport void XGetImportInfo(XImportInfo *ximage_info)
9801 {
9802   assert(ximage_info != (XImportInfo *) NULL);
9803   ximage_info->frame=MagickFalse;
9804   ximage_info->borders=MagickFalse;
9805   ximage_info->screen=MagickFalse;
9806   ximage_info->descend=MagickTrue;
9807   ximage_info->silent=MagickFalse;
9808 }