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