]> granicus.if.org Git - imagemagick/blob - magick/xwindow.c
minor note
[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   register ssize_t
1949     i;
1950
1951   size_t
1952     number_pixels;
1953
1954   ssize_t
1955     bytes;
1956
1957   unsigned int
1958     levels;
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     {
2763       (void) XFreeFont(display,font_info);
2764       font_info=(XFontStruct *) NULL;
2765     }
2766   if (map_info != (XStandardColormap *) NULL)
2767     {
2768       /*
2769         Free X Standard Colormap.
2770       */
2771       if (resource_info->map_type == (char *) NULL)
2772         (void) XFreeStandardColormap(display,visual_info,map_info,pixel);
2773       (void) XFree((void *) map_info);
2774     }
2775   /*
2776     Free X visual info.
2777   */
2778   if (visual_info != (XVisualInfo *) NULL)
2779     (void) XFree((void *) visual_info);
2780   if (resource_info->close_server != MagickFalse)
2781     (void) XCloseDisplay(display);
2782 }
2783 \f
2784 /*
2785 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2786 %                                                                             %
2787 %                                                                             %
2788 %                                                                             %
2789 %   X F r e e S t a n d a r d C o l o r m a p                                 %
2790 %                                                                             %
2791 %                                                                             %
2792 %                                                                             %
2793 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2794 %
2795 %  XFreeStandardColormap() frees an X11 colormap.
2796 %
2797 %  The format of the XFreeStandardColormap method is:
2798 %
2799 %      void XFreeStandardColormap(Display *display,
2800 %        const XVisualInfo *visual_info,XStandardColormap *map_info,
2801 %        XPixelInfo *pixel)
2802 %
2803 %  A description of each parameter follows:
2804 %
2805 %    o display: Specifies a connection to an X server; returned from
2806 %      XOpenDisplay.
2807 %
2808 %    o visual_info: Specifies a pointer to a X11 XVisualInfo structure;
2809 %      returned from XGetVisualInfo.
2810 %
2811 %    o map_info: If map_type is specified, this structure is initialized
2812 %      with info from the Standard Colormap.
2813 %
2814 %    o pixel: Specifies a pointer to a XPixelInfo structure.
2815 %
2816 */
2817 MagickExport void XFreeStandardColormap(Display *display,
2818   const XVisualInfo *visual_info,XStandardColormap *map_info,XPixelInfo *pixel)
2819 {
2820   /*
2821     Free colormap.
2822   */
2823   (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
2824   assert(display != (Display *) NULL);
2825   assert(visual_info != (XVisualInfo *) NULL);
2826   assert(map_info != (XStandardColormap *) NULL);
2827   (void) XFlush(display);
2828   if (map_info->colormap != (Colormap) NULL)
2829     {
2830       if (map_info->colormap != XDefaultColormap(display,visual_info->screen))
2831         (void) XFreeColormap(display,map_info->colormap);
2832       else
2833         if (pixel != (XPixelInfo *) NULL)
2834           if ((visual_info->klass != TrueColor) &&
2835               (visual_info->klass != DirectColor))
2836             (void) XFreeColors(display,map_info->colormap,pixel->pixels,
2837               (int) pixel->colors,0);
2838     }
2839   map_info->colormap=(Colormap) NULL;
2840   if (pixel != (XPixelInfo *) NULL)
2841     {
2842       if (pixel->pixels != (unsigned long *) NULL)
2843         pixel->pixels=(unsigned long *) RelinquishMagickMemory(pixel->pixels);
2844       pixel->pixels=(unsigned long *) NULL;
2845     }
2846 }
2847 \f
2848 /*
2849 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2850 %                                                                             %
2851 %                                                                             %
2852 %                                                                             %
2853 %   X G e t A n n o t a t e I n f o                                           %
2854 %                                                                             %
2855 %                                                                             %
2856 %                                                                             %
2857 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2858 %
2859 %  XGetAnnotateInfo() initializes the AnnotateInfo structure.
2860 %
2861 %  The format of the XGetAnnotateInfo method is:
2862 %
2863 %      void XGetAnnotateInfo(XAnnotateInfo *annotate_info)
2864 %
2865 %  A description of each parameter follows:
2866 %
2867 %    o annotate_info: Specifies a pointer to a XAnnotateInfo structure.
2868 %
2869 */
2870 MagickExport void XGetAnnotateInfo(XAnnotateInfo *annotate_info)
2871 {
2872   /*
2873     Initialize annotate structure.
2874   */
2875   (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
2876   assert(annotate_info != (XAnnotateInfo *) NULL);
2877   annotate_info->x=0;
2878   annotate_info->y=0;
2879   annotate_info->width=0;
2880   annotate_info->height=0;
2881   annotate_info->stencil=ForegroundStencil;
2882   annotate_info->degrees=0.0;
2883   annotate_info->font_info=(XFontStruct *) NULL;
2884   annotate_info->text=(char *) NULL;
2885   *annotate_info->geometry='\0';
2886   annotate_info->previous=(XAnnotateInfo *) NULL;
2887   annotate_info->next=(XAnnotateInfo *) NULL;
2888   (void) XSupportsLocale();
2889   (void) XSetLocaleModifiers("");
2890 }
2891 \f
2892 /*
2893 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2894 %                                                                             %
2895 %                                                                             %
2896 %                                                                             %
2897 %   X G e t M a p I n f o                                                     %
2898 %                                                                             %
2899 %                                                                             %
2900 %                                                                             %
2901 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2902 %
2903 %  XGetMapInfo() initializes the XStandardColormap structure.
2904 %
2905 %  The format of the XStandardColormap method is:
2906 %
2907 %      void XGetMapInfo(const XVisualInfo *visual_info,const Colormap colormap,
2908 %        XStandardColormap *map_info)
2909 %
2910 %  A description of each parameter follows:
2911 %
2912 %    o colormap: Specifies the ID of the X server colormap.
2913 %
2914 %    o visual_info: Specifies a pointer to a X11 XVisualInfo structure;
2915 %      returned from XGetVisualInfo.
2916 %
2917 %    o map_info: Specifies a pointer to a X11 XStandardColormap structure.
2918 %
2919 */
2920 MagickExport void XGetMapInfo(const XVisualInfo *visual_info,
2921   const Colormap colormap,XStandardColormap *map_info)
2922 {
2923   /*
2924     Initialize map info.
2925   */
2926   (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
2927   assert(visual_info != (XVisualInfo *) NULL);
2928   assert(map_info != (XStandardColormap *) NULL);
2929   map_info->colormap=colormap;
2930   map_info->red_max=visual_info->red_mask;
2931   map_info->red_mult=(size_t) (map_info->red_max != 0 ? 1 : 0);
2932   if (map_info->red_max != 0)
2933     while ((map_info->red_max & 0x01) == 0)
2934     {
2935       map_info->red_max>>=1;
2936       map_info->red_mult<<=1;
2937     }
2938   map_info->green_max=visual_info->green_mask;
2939   map_info->green_mult=(size_t) (map_info->green_max != 0 ? 1 : 0);
2940   if (map_info->green_max != 0)
2941     while ((map_info->green_max & 0x01) == 0)
2942     {
2943       map_info->green_max>>=1;
2944       map_info->green_mult<<=1;
2945     }
2946   map_info->blue_max=visual_info->blue_mask;
2947   map_info->blue_mult=(size_t) (map_info->blue_max != 0 ? 1 : 0);
2948   if (map_info->blue_max != 0)
2949     while ((map_info->blue_max & 0x01) == 0)
2950     {
2951       map_info->blue_max>>=1;
2952       map_info->blue_mult<<=1;
2953     }
2954   map_info->base_pixel=0;
2955 }
2956 \f
2957 /*
2958 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2959 %                                                                             %
2960 %                                                                             %
2961 %                                                                             %
2962 %   X G e t P i x e l I n f o                                                 %
2963 %                                                                             %
2964 %                                                                             %
2965 %                                                                             %
2966 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2967 %
2968 %  XGetPixelPacket() initializes the PixelPacket structure.
2969 %
2970 %  The format of the XGetPixelPacket method is:
2971 %
2972 %      void XGetPixelPacket(Display *display,const XVisualInfo *visual_info,
2973 %        const XStandardColormap *map_info,const XResourceInfo *resource_info,
2974 %        Image *image,XPixelInfo *pixel)
2975 %        pixel)
2976 %
2977 %  A description of each parameter follows:
2978 %
2979 %    o display: Specifies a connection to an X server; returned from
2980 %      XOpenDisplay.
2981 %
2982 %    o visual_info: Specifies a pointer to a X11 XVisualInfo structure;
2983 %      returned from XGetVisualInfo.
2984 %
2985 %    o map_info: If map_type is specified, this structure is initialized
2986 %      with info from the Standard Colormap.
2987 %
2988 %    o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
2989 %
2990 %    o image: the image.
2991 %
2992 %    o pixel: Specifies a pointer to a XPixelInfo structure.
2993 %
2994 */
2995 MagickExport void XGetPixelPacket(Display *display,
2996   const XVisualInfo *visual_info,const XStandardColormap *map_info,
2997   const XResourceInfo *resource_info,Image *image,XPixelInfo *pixel)
2998 {
2999   static const char
3000     *PenColors[MaxNumberPens]=
3001     {
3002       "#000000000000",  /* black */
3003       "#00000000ffff",  /* blue */
3004       "#0000ffffffff",  /* cyan */
3005       "#0000ffff0000",  /* green */
3006       "#bdbdbdbdbdbd",  /* gray */
3007       "#ffff00000000",  /* red */
3008       "#ffff0000ffff",  /* magenta */
3009       "#ffffffff0000",  /* yellow */
3010       "#ffffffffffff",  /* white */
3011       "#bdbdbdbdbdbd",  /* gray */
3012       "#bdbdbdbdbdbd"   /* gray */
3013     };
3014
3015   Colormap
3016     colormap;
3017
3018   register ssize_t
3019     i;
3020
3021   Status
3022     status;
3023
3024   unsigned int
3025     packets;
3026
3027   /*
3028     Initialize pixel info.
3029   */
3030   (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
3031   assert(display != (Display *) NULL);
3032   assert(visual_info != (XVisualInfo *) NULL);
3033   assert(map_info != (XStandardColormap *) NULL);
3034   assert(resource_info != (XResourceInfo *) NULL);
3035   assert(pixel != (XPixelInfo *) NULL);
3036   pixel->colors=0;
3037   if (image != (Image *) NULL)
3038     if (image->storage_class == PseudoClass)
3039       pixel->colors=(ssize_t) image->colors;
3040   packets=(unsigned int)
3041     MagickMax((int) pixel->colors,visual_info->colormap_size)+MaxNumberPens;
3042   if (pixel->pixels != (unsigned long *) NULL)
3043     pixel->pixels=(unsigned long *) RelinquishMagickMemory(pixel->pixels);
3044   pixel->pixels=(unsigned long *) AcquireQuantumMemory(packets,
3045     sizeof(pixel->pixels));
3046   if (pixel->pixels == (unsigned long *) NULL)
3047     ThrowXWindowFatalException(ResourceLimitFatalError,"UnableToGetPixelInfo",
3048       image->filename);
3049   /*
3050     Set foreground color.
3051   */
3052   colormap=map_info->colormap;
3053   (void) XParseColor(display,colormap,(char *) ForegroundColor,
3054     &pixel->foreground_color);
3055   status=XParseColor(display,colormap,resource_info->foreground_color,
3056     &pixel->foreground_color);
3057   if (status == False)
3058     ThrowXWindowFatalException(XServerError,"ColorIsNotKnownToServer",
3059       resource_info->foreground_color);
3060   pixel->foreground_color.pixel=
3061     XStandardPixel(map_info,&pixel->foreground_color);
3062   pixel->foreground_color.flags=(char) (DoRed | DoGreen | DoBlue);
3063   /*
3064     Set background color.
3065   */
3066   (void) XParseColor(display,colormap,"#d6d6d6d6d6d6",&pixel->background_color);
3067   status=XParseColor(display,colormap,resource_info->background_color,
3068     &pixel->background_color);
3069   if (status == False)
3070     ThrowXWindowFatalException(XServerError,"ColorIsNotKnownToServer",
3071       resource_info->background_color);
3072   pixel->background_color.pixel=
3073     XStandardPixel(map_info,&pixel->background_color);
3074   pixel->background_color.flags=(char) (DoRed | DoGreen | DoBlue);
3075   /*
3076     Set border color.
3077   */
3078   (void) XParseColor(display,colormap,(char *) BorderColor,
3079     &pixel->border_color);
3080   status=XParseColor(display,colormap,resource_info->border_color,
3081     &pixel->border_color);
3082   if (status == False)
3083     ThrowXWindowFatalException(XServerError,"ColorIsNotKnownToServer",
3084       resource_info->border_color);
3085   pixel->border_color.pixel=XStandardPixel(map_info,&pixel->border_color);
3086   pixel->border_color.flags=(char) (DoRed | DoGreen | DoBlue);
3087   /*
3088     Set matte color.
3089   */
3090   pixel->matte_color=pixel->background_color;
3091   if (resource_info->matte_color != (char *) NULL)
3092     {
3093       /*
3094         Matte color is specified as a X resource or command line argument.
3095       */
3096       status=XParseColor(display,colormap,resource_info->matte_color,
3097         &pixel->matte_color);
3098       if (status == False)
3099         ThrowXWindowFatalException(XServerError,"ColorIsNotKnownToServer",
3100           resource_info->matte_color);
3101       pixel->matte_color.pixel=XStandardPixel(map_info,&pixel->matte_color);
3102       pixel->matte_color.flags=(char) (DoRed | DoGreen | DoBlue);
3103     }
3104   /*
3105     Set highlight color.
3106   */
3107   pixel->highlight_color.red=(unsigned short) ((
3108     pixel->matte_color.red*ScaleQuantumToShort(HighlightModulate))/65535L+
3109     (ScaleQuantumToShort((Quantum) (QuantumRange-HighlightModulate))));
3110   pixel->highlight_color.green=(unsigned short) ((
3111     pixel->matte_color.green*ScaleQuantumToShort(HighlightModulate))/65535L+
3112     (ScaleQuantumToShort((Quantum) (QuantumRange-HighlightModulate))));
3113   pixel->highlight_color.blue=(unsigned short) ((
3114     pixel->matte_color.blue*ScaleQuantumToShort(HighlightModulate))/65535L+
3115     (ScaleQuantumToShort((Quantum) (QuantumRange-HighlightModulate))));
3116   pixel->highlight_color.pixel=
3117     XStandardPixel(map_info,&pixel->highlight_color);
3118   pixel->highlight_color.flags=(char) (DoRed | DoGreen | DoBlue);
3119   /*
3120     Set shadow color.
3121   */
3122   pixel->shadow_color.red=(unsigned short) (((MagickRealType)
3123     pixel->matte_color.red*ScaleQuantumToShort(ShadowModulate))/65535L);
3124   pixel->shadow_color.green=(unsigned short) (((MagickRealType)
3125     pixel->matte_color.green*ScaleQuantumToShort(ShadowModulate))/65535L);
3126   pixel->shadow_color.blue=(unsigned short) (((MagickRealType)
3127     pixel->matte_color.blue*ScaleQuantumToShort(ShadowModulate))/65535L);
3128   pixel->shadow_color.pixel=XStandardPixel(map_info,&pixel->shadow_color);
3129   pixel->shadow_color.flags=(char) (DoRed | DoGreen | DoBlue);
3130   /*
3131     Set depth color.
3132   */
3133   pixel->depth_color.red=(unsigned short) (((MagickRealType)
3134     pixel->matte_color.red*ScaleQuantumToShort(DepthModulate))/65535L);
3135   pixel->depth_color.green=(unsigned short) (((MagickRealType)
3136     pixel->matte_color.green*ScaleQuantumToShort(DepthModulate))/65535L);
3137   pixel->depth_color.blue=(unsigned short) (((MagickRealType)
3138     pixel->matte_color.blue*ScaleQuantumToShort(DepthModulate))/65535L);
3139   pixel->depth_color.pixel=XStandardPixel(map_info,&pixel->depth_color);
3140   pixel->depth_color.flags=(char) (DoRed | DoGreen | DoBlue);
3141   /*
3142     Set trough color.
3143   */
3144   pixel->trough_color.red=(unsigned short) (((MagickRealType)
3145     pixel->matte_color.red*ScaleQuantumToShort(TroughModulate))/65535L);
3146   pixel->trough_color.green=(unsigned short) (((MagickRealType)
3147     pixel->matte_color.green*ScaleQuantumToShort(TroughModulate))/65535L);
3148   pixel->trough_color.blue=(unsigned short) (((MagickRealType)
3149     pixel->matte_color.blue*ScaleQuantumToShort(TroughModulate))/65535L);
3150   pixel->trough_color.pixel=XStandardPixel(map_info,&pixel->trough_color);
3151   pixel->trough_color.flags=(char) (DoRed | DoGreen | DoBlue);
3152   /*
3153     Set pen color.
3154   */
3155   for (i=0; i < MaxNumberPens; i++)
3156   {
3157     (void) XParseColor(display,colormap,(char *) PenColors[i],
3158       &pixel->pen_colors[i]);
3159     status=XParseColor(display,colormap,resource_info->pen_colors[i],
3160       &pixel->pen_colors[i]);
3161     if (status == False)
3162       ThrowXWindowFatalException(XServerError,"ColorIsNotKnownToServer",
3163         resource_info->pen_colors[i]);
3164     pixel->pen_colors[i].pixel=XStandardPixel(map_info,&pixel->pen_colors[i]);
3165     pixel->pen_colors[i].flags=(char) (DoRed | DoGreen | DoBlue);
3166   }
3167   pixel->box_color=pixel->background_color;
3168   pixel->pen_color=pixel->foreground_color;
3169   pixel->box_index=0;
3170   pixel->pen_index=1;
3171   if (image != (Image *) NULL)
3172     {
3173       if ((resource_info->gamma_correct != MagickFalse) &&
3174           (image->gamma != 0.0))
3175         {
3176           GeometryInfo
3177             geometry_info;
3178
3179           MagickStatusType
3180             flags;
3181
3182           /*
3183             Initialize map relative to display and image gamma.
3184           */
3185           flags=ParseGeometry(resource_info->display_gamma,&geometry_info);
3186           red_gamma=geometry_info.rho;
3187           green_gamma=geometry_info.sigma;
3188           if ((flags & SigmaValue) == 0)
3189             green_gamma=red_gamma;
3190           blue_gamma=geometry_info.xi;
3191           if ((flags & XiValue) == 0)
3192             blue_gamma=red_gamma;
3193           red_gamma*=image->gamma;
3194           green_gamma*=image->gamma;
3195           blue_gamma*=image->gamma;
3196         }
3197       if (image->storage_class == PseudoClass)
3198         {
3199           /*
3200             Initialize pixel array for images of type PseudoClass.
3201           */
3202           for (i=0; i < (ssize_t) image->colors; i++)
3203             pixel->pixels[i]=
3204               XGammaPixel(map_info,image->colormap+i);
3205           for (i=0; i < MaxNumberPens; i++)
3206             pixel->pixels[image->colors+i]=pixel->pen_colors[i].pixel;
3207           pixel->colors+=MaxNumberPens;
3208         }
3209     }
3210 }
3211 \f
3212 /*
3213 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3214 %                                                                             %
3215 %                                                                             %
3216 %                                                                             %
3217 %   X G e t R e s o u r c e C l a s s                                         %
3218 %                                                                             %
3219 %                                                                             %
3220 %                                                                             %
3221 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3222 %
3223 %  XGetResourceClass() queries the X server for the specified resource name or
3224 %  class.  If the resource name or class is not defined in the database, the
3225 %  supplied default value is returned.
3226 %
3227 %  The format of the XGetResourceClass method is:
3228 %
3229 %      char *XGetResourceClass(XrmDatabase database,const char *client_name,
3230 %        const char *keyword,char *resource_default)
3231 %
3232 %  A description of each parameter follows:
3233 %
3234 %    o database: Specifies a resource database; returned from
3235 %      XrmGetStringDatabase.
3236 %
3237 %    o client_name:  Specifies the application name used to retrieve resource
3238 %      info from the X server database.
3239 %
3240 %    o keyword: Specifies the keyword of the value being retrieved.
3241 %
3242 %    o resource_default: Specifies the default value to return if the query
3243 %      fails to find the specified keyword/class.
3244 %
3245 */
3246 MagickExport char *XGetResourceClass(XrmDatabase database,
3247   const char *client_name,const char *keyword,char *resource_default)
3248 {
3249   char
3250     resource_class[MaxTextExtent],
3251     resource_name[MaxTextExtent];
3252
3253   static char
3254     *resource_type;
3255
3256   Status
3257     status;
3258
3259   XrmValue
3260     resource_value;
3261
3262   if (database == (XrmDatabase) NULL)
3263     return(resource_default);
3264   *resource_name='\0';
3265   *resource_class='\0';
3266   if (keyword != (char *) NULL)
3267     {
3268       int
3269         c,
3270         k;
3271
3272       /*
3273         Initialize resource keyword and class.
3274       */
3275       (void) FormatMagickString(resource_name,MaxTextExtent,"%s.%s",
3276         client_name,keyword);
3277       c=(int) (*client_name);
3278       if ((c >= XK_a) && (c <= XK_z))
3279         c-=(XK_a-XK_A);
3280       else
3281         if ((c >= XK_agrave) && (c <= XK_odiaeresis))
3282           c-=(XK_agrave-XK_Agrave);
3283         else
3284           if ((c >= XK_oslash) && (c <= XK_thorn))
3285             c-=(XK_oslash-XK_Ooblique);
3286       k=(int) (*keyword);
3287       if ((k >= XK_a) && (k <= XK_z))
3288         k-=(XK_a-XK_A);
3289       else
3290         if ((k >= XK_agrave) && (k <= XK_odiaeresis))
3291           k-=(XK_agrave-XK_Agrave);
3292         else
3293           if ((k >= XK_oslash) && (k <= XK_thorn))
3294             k-=(XK_oslash-XK_Ooblique);
3295       (void) FormatMagickString(resource_class,MaxTextExtent,"%c%s.%c%s",c,
3296         client_name+1,k,keyword+1);
3297     }
3298   status=XrmGetResource(database,resource_name,resource_class,&resource_type,
3299     &resource_value);
3300   if (status == False)
3301     return(resource_default);
3302   return(resource_value.addr);
3303 }
3304 \f
3305 /*
3306 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3307 %                                                                             %
3308 %                                                                             %
3309 %                                                                             %
3310 %   X G e t R e s o u r c e D a t a b a s e                                   %
3311 %                                                                             %
3312 %                                                                             %
3313 %                                                                             %
3314 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3315 %
3316 %  XGetResourceDatabase() creates a new resource database and initializes it.
3317 %
3318 %  The format of the XGetResourceDatabase method is:
3319 %
3320 %      XrmDatabase XGetResourceDatabase(Display *display,
3321 %        const char *client_name)
3322 %
3323 %  A description of each parameter follows:
3324 %
3325 %    o database: XGetResourceDatabase() returns the database after it is
3326 %      initialized.
3327 %
3328 %    o display: Specifies a connection to an X server;  returned from
3329 %      XOpenDisplay.
3330 %
3331 %    o client_name:  Specifies the application name used to retrieve resource
3332 %      info from the X server database.
3333 %
3334 */
3335 MagickExport XrmDatabase XGetResourceDatabase(Display *display,
3336   const char *client_name)
3337 {
3338   char
3339     filename[MaxTextExtent];
3340
3341   int
3342     c;
3343
3344   register const char
3345     *p;
3346
3347   XrmDatabase
3348     resource_database,
3349     server_database;
3350
3351   if (display == (Display *) NULL)
3352     return((XrmDatabase) NULL);
3353   assert(client_name != (char *) NULL);
3354   /*
3355     Initialize resource database.
3356   */
3357   XrmInitialize();
3358   (void) XGetDefault(display,(char *) client_name,"dummy");
3359   resource_database=XrmGetDatabase(display);
3360   /*
3361     Combine application database.
3362   */
3363   if (client_name != (char *) NULL)
3364     {
3365       /*
3366         Get basename of client.
3367       */
3368       p=client_name+(strlen(client_name)-1);
3369       while ((p > client_name) && (*p != '/'))
3370         p--;
3371       if (*p == '/')
3372         client_name=p+1;
3373     }
3374   c=(int) (*client_name);
3375   if ((c >= XK_a) && (c <= XK_z))
3376     c-=(XK_a-XK_A);
3377   else
3378     if ((c >= XK_agrave) && (c <= XK_odiaeresis))
3379       c-=(XK_agrave-XK_Agrave);
3380     else
3381       if ((c >= XK_oslash) && (c <= XK_thorn))
3382         c-=(XK_oslash-XK_Ooblique);
3383 #if defined(X11_APPLICATION_PATH)
3384   (void) FormatMagickString(filename,MaxTextExtent,"%s%c%s",
3385     X11_APPLICATION_PATH,c,client_name+1);
3386   (void) XrmCombineFileDatabase(filename,&resource_database,MagickFalse);
3387 #endif
3388   if (XResourceManagerString(display) != (char *) NULL)
3389     {
3390       /*
3391         Combine server database.
3392       */
3393       server_database=XrmGetStringDatabase(XResourceManagerString(display));
3394       XrmCombineDatabase(server_database,&resource_database,MagickFalse);
3395     }
3396   /*
3397     Merge user preferences database.
3398   */
3399 #if defined(X11_PREFERENCES_PATH)
3400   (void) FormatMagickString(filename,MaxTextExtent,"%s%src",
3401     X11_PREFERENCES_PATH,client_name);
3402   ExpandFilename(filename);
3403   (void) XrmCombineFileDatabase(filename,&resource_database,MagickFalse);
3404 #endif
3405   return(resource_database);
3406 }
3407 \f
3408 /*
3409 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3410 %                                                                             %
3411 %                                                                             %
3412 %                                                                             %
3413 %   X G e t R e s o u r c e I n f o                                           %
3414 %                                                                             %
3415 %                                                                             %
3416 %                                                                             %
3417 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3418 %
3419 %  XGetResourceInfo(image_info,) initializes the ResourceInfo structure.
3420 %
3421 %  The format of the XGetResourceInfo method is:
3422 %
3423 %      void XGetResourceInfo(const ImageInfo *image_info,XrmDatabase database,
3424 %        const char *client_name,XResourceInfo *resource_info)
3425 %
3426 %  A description of each parameter follows:
3427 %
3428 %    o image_info: the image info.
3429 %
3430 %    o database: Specifies a resource database; returned from
3431 %      XrmGetStringDatabase.
3432 %
3433 %    o client_name:  Specifies the application name used to retrieve
3434 %      resource info from the X server database.
3435 %
3436 %    o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
3437 %
3438 */
3439 MagickExport void XGetResourceInfo(const ImageInfo *image_info,
3440   XrmDatabase database,const char *client_name,XResourceInfo *resource_info)
3441 {
3442   char
3443     *directory,
3444     *resource_value;
3445
3446   /*
3447     Initialize resource info fields.
3448   */
3449   (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
3450   assert(resource_info != (XResourceInfo *) NULL);
3451   (void) ResetMagickMemory(resource_info,0,sizeof(*resource_info));
3452   resource_info->resource_database=database;
3453   resource_info->image_info=(ImageInfo *) image_info;
3454   (void) SetImageInfoProgressMonitor(resource_info->image_info,
3455     XMagickProgressMonitor,(void *) NULL);
3456   resource_info->quantize_info=CloneQuantizeInfo((QuantizeInfo *) NULL);
3457   resource_info->close_server=MagickTrue;
3458   resource_info->client_name=AcquireString(client_name);
3459   resource_value=XGetResourceClass(database,client_name,"backdrop",
3460     (char *) "False");
3461   resource_info->backdrop=IsMagickTrue(resource_value);
3462   resource_info->background_color=XGetResourceInstance(database,client_name,
3463     "background",(char *) "#d6d6d6d6d6d6");
3464   resource_info->border_color=XGetResourceInstance(database,client_name,
3465     "borderColor",BorderColor);
3466   resource_value=XGetResourceClass(database,client_name,"borderWidth",
3467     (char *) "2");
3468   resource_info->border_width=(unsigned int) StringToUnsignedLong(
3469     resource_value);
3470   resource_value=XGetResourceClass(database,client_name,"colormap",
3471     (char *) "shared");
3472   resource_info->colormap=UndefinedColormap;
3473   if (LocaleCompare("private",resource_value) == 0)
3474     resource_info->colormap=PrivateColormap;
3475   if (LocaleCompare("shared",resource_value) == 0)
3476     resource_info->colormap=SharedColormap;
3477   if (resource_info->colormap == UndefinedColormap)
3478     ThrowXWindowFatalException(OptionError,"UnrecognizedColormapType",
3479       resource_value);
3480   resource_value=XGetResourceClass(database,client_name,
3481     "colorRecovery",(char *) "False");
3482   resource_info->color_recovery=IsMagickTrue(resource_value);
3483   resource_value=XGetResourceClass(database,client_name,"confirmExit",
3484     (char *) "False");
3485   resource_info->confirm_exit=IsMagickTrue(resource_value);
3486   resource_value=XGetResourceClass(database,client_name,"confirmEdit",
3487     (char *) "False");
3488   resource_info->confirm_edit=IsMagickTrue(resource_value);
3489   resource_value=XGetResourceClass(database,client_name,"delay",(char *) "1");
3490   resource_info->delay=(unsigned int) StringToUnsignedLong(resource_value);
3491   resource_info->display_gamma=XGetResourceClass(database,client_name,
3492     "displayGamma",(char *) "2.2");
3493   resource_value=XGetResourceClass(database,client_name,"displayWarnings",
3494     (char *) "True");
3495   resource_info->display_warnings=IsMagickTrue(resource_value);
3496   resource_info->font=XGetResourceClass(database,client_name,"font",
3497     (char *) NULL);
3498   resource_info->font=XGetResourceClass(database,client_name,"fontList",
3499     resource_info->font);
3500   resource_info->font_name[0]=XGetResourceClass(database,client_name,"font1",
3501     (char *) "fixed");
3502   resource_info->font_name[1]=XGetResourceClass(database,client_name,"font2",
3503     (char *) "variable");
3504   resource_info->font_name[2]=XGetResourceClass(database,client_name,"font3",
3505     (char *) "5x8");
3506   resource_info->font_name[3]=XGetResourceClass(database,client_name,"font4",
3507     (char *) "6x10");
3508   resource_info->font_name[4]=XGetResourceClass(database,client_name,"font5",
3509     (char *) "7x13bold");
3510   resource_info->font_name[5]=XGetResourceClass(database,client_name,"font6",
3511     (char *) "8x13bold");
3512   resource_info->font_name[6]=XGetResourceClass(database,client_name,"font7",
3513     (char *) "9x15bold");
3514   resource_info->font_name[7]=XGetResourceClass(database,client_name,"font8",
3515     (char *) "10x20");
3516   resource_info->font_name[8]=XGetResourceClass(database,client_name,"font9",
3517     (char *) "12x24");
3518   resource_info->font_name[9]=XGetResourceClass(database,client_name,"font0",
3519     (char *) "fixed");
3520   resource_info->font_name[10]=XGetResourceClass(database,client_name,"font0",
3521     (char *) "fixed");
3522   resource_info->foreground_color=XGetResourceInstance(database,client_name,
3523     "foreground",ForegroundColor);
3524   resource_value=XGetResourceClass(database,client_name,"gammaCorrect",
3525     (char *) "True");
3526   resource_info->gamma_correct=IsMagickTrue(resource_value);
3527   resource_info->image_geometry=ConstantString(XGetResourceClass(database,
3528     client_name,"geometry",(char *) NULL));
3529   resource_value=XGetResourceClass(database,client_name,"gravity",
3530     (char *) "Center");
3531   resource_info->gravity=(GravityType) ParseMagickOption(MagickGravityOptions,
3532     MagickFalse,resource_value);
3533   directory=getcwd(resource_info->home_directory,MaxTextExtent);
3534   (void) directory;
3535   resource_info->icon_geometry=XGetResourceClass(database,client_name,
3536     "iconGeometry",(char *) NULL);
3537   resource_value=XGetResourceClass(database,client_name,"iconic",
3538     (char *) "False");
3539   resource_info->iconic=IsMagickTrue(resource_value);
3540   resource_value=XGetResourceClass(database,client_name,"immutable",
3541     LocaleCompare(client_name,"PerlMagick") == 0 ? (char *) "True" :
3542     (char *) "False");
3543   resource_info->immutable=IsMagickTrue(resource_value);
3544   resource_value=XGetResourceClass(database,client_name,"magnify",
3545     (char *) "3");
3546   resource_info->magnify=(unsigned int) StringToUnsignedLong(resource_value);
3547   resource_info->map_type=XGetResourceClass(database,client_name,"map",
3548     (char *) NULL);
3549   resource_info->matte_color=XGetResourceInstance(database,client_name,
3550     "mattecolor",(char *) NULL);
3551   resource_info->name=ConstantString(XGetResourceClass(database,client_name,
3552     "name",(char *) NULL));
3553   resource_info->pen_colors[0]=XGetResourceClass(database,client_name,"pen1",
3554     (char *) "black");
3555   resource_info->pen_colors[1]=XGetResourceClass(database,client_name,"pen2",
3556     (char *) "blue");
3557   resource_info->pen_colors[2]=XGetResourceClass(database,client_name,"pen3",
3558     (char *) "cyan");
3559   resource_info->pen_colors[3]=XGetResourceClass(database,client_name,"pen4",
3560     (char *) "green");
3561   resource_info->pen_colors[4]=XGetResourceClass(database,client_name,"pen5",
3562     (char *) "gray");
3563   resource_info->pen_colors[5]=XGetResourceClass(database,client_name,"pen6",
3564     (char *) "red");
3565   resource_info->pen_colors[6]=XGetResourceClass(database,client_name,"pen7",
3566     (char *) "magenta");
3567   resource_info->pen_colors[7]=XGetResourceClass(database,client_name,"pen8",
3568     (char *) "yellow");
3569   resource_info->pen_colors[8]=XGetResourceClass(database,client_name,"pen9",
3570     (char *) "white");
3571   resource_info->pen_colors[9]=XGetResourceClass(database,client_name,"pen0",
3572     (char *) "gray");
3573   resource_info->pen_colors[10]=XGetResourceClass(database,client_name,"pen0",
3574     (char *) "gray");
3575   resource_value=XGetResourceClass(database,client_name,"pause",(char *) "0");
3576   resource_info->pause=(unsigned int) StringToUnsignedLong(resource_value);
3577   resource_value=XGetResourceClass(database,client_name,"quantum",(char *) "1");
3578   resource_info->quantum=StringToLong(resource_value);
3579   resource_info->text_font=XGetResourceClass(database,client_name,(char *)
3580     "font",(char *) "fixed");
3581   resource_info->text_font=XGetResourceClass(database,client_name,
3582     "textFontList",resource_info->text_font);
3583   resource_info->title=XGetResourceClass(database,client_name,"title",
3584     (char *) NULL);
3585   resource_value=XGetResourceClass(database,client_name,"undoCache",
3586     (char *) "16");
3587   resource_info->undo_cache=(unsigned int) StringToUnsignedLong(resource_value);
3588   resource_value=XGetResourceClass(database,client_name,"update",
3589     (char *) "False");
3590   resource_info->update=IsMagickTrue(resource_value);
3591   resource_value=XGetResourceClass(database,client_name,"usePixmap",
3592     (char *) "True");
3593   resource_info->use_pixmap=IsMagickTrue(resource_value);
3594   resource_value=XGetResourceClass(database,client_name,"sharedMemory",
3595     (char *) "True");
3596   resource_info->use_shared_memory=IsMagickTrue(resource_value);
3597   resource_info->visual_type=XGetResourceClass(database,client_name,"visual",
3598     (char *) NULL);
3599   resource_info->window_group=XGetResourceClass(database,client_name,
3600     "windowGroup",(char *) NULL);
3601   resource_info->window_id=XGetResourceClass(database,client_name,"window",
3602     (char *) NULL);
3603   resource_info->write_filename=XGetResourceClass(database,client_name,
3604     "writeFilename",(char *) NULL);
3605 }
3606 \f
3607 /*
3608 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3609 %                                                                             %
3610 %                                                                             %
3611 %                                                                             %
3612 %   X G e t R e s o u r c e I n s t a n c e                                   %
3613 %                                                                             %
3614 %                                                                             %
3615 %                                                                             %
3616 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3617 %
3618 %  XGetResourceInstance() queries the X server for the specified resource name.
3619 %  If the resource name is not defined in the database, the supplied default
3620 %  value is returned.
3621 %
3622 %  The format of the XGetResourceInstance method is:
3623 %
3624 %      char *XGetResourceInstance(XrmDatabase database,const char *client_name,
3625 %        const char *keyword,const char *resource_default)
3626 %
3627 %  A description of each parameter follows:
3628 %
3629 %    o database: Specifies a resource database; returned from
3630 %      XrmGetStringDatabase.
3631 %
3632 %    o client_name:  Specifies the application name used to retrieve
3633 %      resource info from the X server database.
3634 %
3635 %    o keyword: Specifies the keyword of the value being retrieved.
3636 %
3637 %    o resource_default: Specifies the default value to return if the query
3638 %      fails to find the specified keyword/class.
3639 %
3640 */
3641 MagickExport char *XGetResourceInstance(XrmDatabase database,
3642   const char *client_name,const char *keyword,const char *resource_default)
3643 {
3644   char
3645     *resource_type,
3646     resource_name[MaxTextExtent];
3647
3648   Status
3649     status;
3650
3651   XrmValue
3652     resource_value;
3653
3654   if (database == (XrmDatabase) NULL)
3655     return((char *) resource_default);
3656   *resource_name='\0';
3657   if (keyword != (char *) NULL)
3658     (void) FormatMagickString(resource_name,MaxTextExtent,"%s.%s",client_name,
3659       keyword);
3660   status=XrmGetResource(database,resource_name,"ImageMagick",&resource_type,
3661     &resource_value);
3662   if (status == False)
3663     return((char *) resource_default);
3664   return(resource_value.addr);
3665 }
3666 \f
3667 /*
3668 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3669 %                                                                             %
3670 %                                                                             %
3671 %                                                                             %
3672 %   X G e t S c r e e n D e n s i t y                                         %
3673 %                                                                             %
3674 %                                                                             %
3675 %                                                                             %
3676 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3677 %
3678 %  XGetScreenDensity() returns the density of the X server screen in
3679 %  dots-per-inch.
3680 %
3681 %  The format of the XGetScreenDensity method is:
3682 %
3683 %      char *XGetScreenDensity(Display *display)
3684 %
3685 %  A description of each parameter follows:
3686 %
3687 %    o density: XGetScreenDensity() returns the density of the X screen in
3688 %      dots-per-inch.
3689 %
3690 %    o display: Specifies a connection to an X server;  returned from
3691 %      XOpenDisplay.
3692 %
3693 */
3694 MagickExport char *XGetScreenDensity(Display *display)
3695 {
3696   char
3697     density[MaxTextExtent];
3698
3699   double
3700     x_density,
3701     y_density;
3702
3703   /*
3704     Set density as determined by screen size.
3705   */
3706   x_density=((((double) DisplayWidth(display,XDefaultScreen(display)))*25.4)/
3707     ((double) DisplayWidthMM(display,XDefaultScreen(display))));
3708   y_density=((((double) DisplayHeight(display,XDefaultScreen(display)))*25.4)/
3709     ((double) DisplayHeightMM(display,XDefaultScreen(display))));
3710   (void) FormatMagickString(density,MaxTextExtent,"%gx%g",x_density,
3711     y_density);
3712   return(GetPageGeometry(density));
3713 }
3714 \f
3715 /*
3716 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3717 %                                                                             %
3718 %                                                                             %
3719 %                                                                             %
3720 +   X G e t S u b w i n d o w                                                 %
3721 %                                                                             %
3722 %                                                                             %
3723 %                                                                             %
3724 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3725 %
3726 %  XGetSubwindow() returns the subwindow of a window chosen the user with the
3727 %  pointer and a button press.
3728 %
3729 %  The format of the XGetSubwindow method is:
3730 %
3731 %      Window XGetSubwindow(Display *display,Window window,int x,int y)
3732 %
3733 %  A description of each parameter follows:
3734 %
3735 %    o subwindow: XGetSubwindow() returns NULL if no subwindow is found
3736 %      otherwise the subwindow is returned.
3737 %
3738 %    o display: Specifies a connection to an X server;  returned from
3739 %      XOpenDisplay.
3740 %
3741 %    o window: Specifies a pointer to a Window.
3742 %
3743 %    o x: the x coordinate of the pointer relative to the origin of the
3744 %      window.
3745 %
3746 %    o y: the y coordinate of the pointer relative to the origin of the
3747 %      window.
3748 %
3749 */
3750 static Window XGetSubwindow(Display *display,Window window,int x,int y)
3751 {
3752   int
3753     x_offset,
3754     y_offset;
3755
3756   Status
3757     status;
3758
3759   Window
3760     source_window,
3761     target_window;
3762
3763   assert(display != (Display *) NULL);
3764   source_window=XRootWindow(display,XDefaultScreen(display));
3765   if (window == (Window) NULL)
3766     return(source_window);
3767   target_window=window;
3768   for ( ; ; )
3769   {
3770     status=XTranslateCoordinates(display,source_window,window,x,y,
3771       &x_offset,&y_offset,&target_window);
3772     if (status != True)
3773       break;
3774     if (target_window == (Window) NULL)
3775       break;
3776     source_window=window;
3777     window=target_window;
3778     x=x_offset;
3779     y=y_offset;
3780   }
3781   if (target_window == (Window) NULL)
3782     target_window=window;
3783   return(target_window);
3784 }
3785 \f
3786 /*
3787 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3788 %                                                                             %
3789 %                                                                             %
3790 %                                                                             %
3791 %   X G e t W i n d o w C o l o r                                             %
3792 %                                                                             %
3793 %                                                                             %
3794 %                                                                             %
3795 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3796 %
3797 %  XGetWindowColor() returns the color of a pixel interactively chosen from the
3798 %  X server.
3799 %
3800 %  The format of the XGetWindowColor method is:
3801 %
3802 %      MagickBooleanType XGetWindowColor(Display *display,XWindows *windows,
3803 %        char *name)
3804 %
3805 %  A description of each parameter follows:
3806 %
3807 %    o display: Specifies a connection to an X server;  returned from
3808 %      XOpenDisplay.
3809 %
3810 %    o windows: Specifies a pointer to a XWindows structure.
3811 %
3812 %    o name: the name of the color if found in the X Color Database is
3813 %      returned in this character string.
3814 %
3815 */
3816 MagickExport MagickBooleanType XGetWindowColor(Display *display,
3817   XWindows *windows,char *name)
3818 {
3819   int
3820     x,
3821     y;
3822
3823   PixelPacket
3824     pixel;
3825
3826   RectangleInfo
3827     crop_info;
3828
3829   Status
3830     status;
3831
3832   Window
3833     child,
3834     client_window,
3835     root_window,
3836     target_window;
3837
3838   XColor
3839     color;
3840
3841   XImage
3842     *ximage;
3843
3844   XWindowAttributes
3845     window_attributes;
3846
3847   /*
3848     Choose a pixel from the X server.
3849   */
3850   assert(display != (Display *) NULL);
3851   assert(name != (char *) NULL);
3852   (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",name);
3853   *name='\0';
3854   target_window=XSelectWindow(display,&crop_info);
3855   if (target_window == (Window) NULL)
3856     return(MagickFalse);
3857   root_window=XRootWindow(display,XDefaultScreen(display));
3858   client_window=target_window;
3859   if (target_window != root_window)
3860     {
3861       unsigned int
3862         d;
3863
3864       /*
3865         Get client window.
3866       */
3867       status=XGetGeometry(display,target_window,&root_window,&x,&x,&d,&d,&d,&d);
3868       if (status != False)
3869         {
3870           client_window=XClientWindow(display,target_window);
3871           target_window=client_window;
3872         }
3873     }
3874   /*
3875     Verify window is viewable.
3876   */
3877   status=XGetWindowAttributes(display,target_window,&window_attributes);
3878   if ((status == False) || (window_attributes.map_state != IsViewable))
3879     return(MagickFalse);
3880   /*
3881     Get window X image.
3882   */
3883   (void) XTranslateCoordinates(display,root_window,target_window,
3884     (int) crop_info.x,(int) crop_info.y,&x,&y,&child);
3885   ximage=XGetImage(display,target_window,x,y,1,1,AllPlanes,ZPixmap);
3886   if (ximage == (XImage *) NULL)
3887     return(MagickFalse);
3888   color.pixel=XGetPixel(ximage,0,0);
3889   XDestroyImage(ximage);
3890   /*
3891     Match color against the color database.
3892   */
3893   (void) XQueryColor(display,window_attributes.colormap,&color);
3894   pixel.red=ScaleShortToQuantum(color.red);
3895   pixel.green=ScaleShortToQuantum(color.green);
3896   pixel.blue=ScaleShortToQuantum(color.blue);
3897   pixel.opacity=OpaqueOpacity;
3898   (void) QueryColorname(windows->image.image,&pixel,X11Compliance,name,
3899     &windows->image.image->exception);
3900   return(MagickTrue);
3901 }
3902 \f
3903 /*
3904 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3905 %                                                                             %
3906 %                                                                             %
3907 %                                                                             %
3908 +   X G e t W i n d o w I m a g e                                             %
3909 %                                                                             %
3910 %                                                                             %
3911 %                                                                             %
3912 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3913 %
3914 %  XGetWindowImage() reads an image from the target X window and returns it.
3915 %  XGetWindowImage() optionally descends the window hierarchy and overlays the
3916 %  target image with each child image in an optimized fashion.  Any child
3917 %  window that have the same visual, colormap, and are contained by its parent
3918 %  are exempted.
3919 %
3920 %  The format of the XGetWindowImage method is:
3921 %
3922 %      Image *XGetWindowImage(Display *display,const Window window,
3923 %        const unsigned int borders,const unsigned int level)
3924 %
3925 %  A description of each parameter follows:
3926 %
3927 %    o display: Specifies a connection to an X server;  returned from
3928 %      XOpenDisplay.
3929 %
3930 %    o window: Specifies the window to obtain the image from.
3931 %
3932 %    o borders: Specifies whether borders pixels are to be saved with
3933 %      the image.
3934 %
3935 %    o level: Specifies an unsigned integer representing the level of
3936 %      decent in the window hierarchy.  This value must be zero or one on
3937 %      the initial call to XGetWindowImage.  A value of zero returns after
3938 %      one call.  A value of one causes the function to descend the window
3939 %      hierarchy and overlay the target image with each subwindow image.
3940 %
3941 */
3942 static Image *XGetWindowImage(Display *display,const Window window,
3943   const unsigned int borders,const unsigned int level)
3944 {
3945   typedef struct _ColormapInfo
3946   {
3947     Colormap
3948       colormap;
3949
3950     XColor
3951       *colors;
3952
3953     struct _ColormapInfo
3954       *next;
3955   } ColormapInfo;
3956
3957   typedef struct _WindowInfo
3958   {
3959     Window
3960       window,
3961       parent;
3962
3963     Visual
3964       *visual;
3965
3966     Colormap
3967       colormap;
3968
3969     XSegment
3970       bounds;
3971
3972     RectangleInfo
3973       crop_info;
3974   } WindowInfo;
3975
3976   IndexPacket
3977     index;
3978
3979   int
3980     display_height,
3981     display_width,
3982     id,
3983     x_offset,
3984     y_offset;
3985
3986   RectangleInfo
3987     crop_info;
3988
3989   register IndexPacket
3990     *indexes;
3991
3992   register int
3993     i;
3994
3995   static ColormapInfo
3996     *colormap_info = (ColormapInfo *) NULL;
3997
3998   static int
3999     max_windows = 0,
4000     number_windows = 0;
4001
4002   static WindowInfo
4003     *window_info;
4004
4005   Status
4006     status;
4007
4008   Window
4009     child,
4010     root_window;
4011
4012   XWindowAttributes
4013     window_attributes;
4014
4015   /*
4016     Verify window is viewable.
4017   */
4018   (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
4019   assert(display != (Display *) NULL);
4020   status=XGetWindowAttributes(display,window,&window_attributes);
4021   if ((status == False) || (window_attributes.map_state != IsViewable))
4022     return((Image *) NULL);
4023   /*
4024     Cropping rectangle is relative to root window.
4025   */
4026   root_window=XRootWindow(display,XDefaultScreen(display));
4027   (void) XTranslateCoordinates(display,window,root_window,0,0,&x_offset,
4028     &y_offset,&child);
4029   crop_info.x=(ssize_t) x_offset;
4030   crop_info.y=(ssize_t) y_offset;
4031   crop_info.width=(size_t) window_attributes.width;
4032   crop_info.height=(size_t) window_attributes.height;
4033   if (borders != MagickFalse)
4034     {
4035       /*
4036         Include border in image.
4037       */
4038       crop_info.x-=(ssize_t) window_attributes.border_width;
4039       crop_info.y-=(ssize_t) window_attributes.border_width;
4040       crop_info.width+=(size_t) (window_attributes.border_width << 1);
4041       crop_info.height+=(size_t) (window_attributes.border_width << 1);
4042     }
4043   /*
4044     Crop to root window.
4045   */
4046   if (crop_info.x < 0)
4047     {
4048       crop_info.width+=crop_info.x;
4049       crop_info.x=0;
4050     }
4051   if (crop_info.y < 0)
4052     {
4053       crop_info.height+=crop_info.y;
4054       crop_info.y=0;
4055     }
4056   display_width=XDisplayWidth(display,XDefaultScreen(display));
4057   if ((int) (crop_info.x+crop_info.width) > display_width)
4058     crop_info.width=(size_t) (display_width-crop_info.x);
4059   display_height=XDisplayHeight(display,XDefaultScreen(display));
4060   if ((int) (crop_info.y+crop_info.height) > display_height)
4061     crop_info.height=(size_t) (display_height-crop_info.y);
4062   /*
4063     Initialize window info attributes.
4064   */
4065   if (number_windows >= max_windows)
4066     {
4067       /*
4068         Allocate or resize window info buffer.
4069       */
4070       max_windows+=1024;
4071       if (window_info == (WindowInfo *) NULL)
4072         window_info=(WindowInfo *) AcquireQuantumMemory((size_t) max_windows,
4073           sizeof(*window_info));
4074       else
4075         window_info=(WindowInfo *) ResizeQuantumMemory(window_info,(size_t)
4076           max_windows,sizeof(*window_info));
4077     }
4078   if (window_info == (WindowInfo *) NULL)
4079     {
4080       ThrowXWindowFatalException(ResourceLimitError,
4081         "MemoryAllocationFailed","...");
4082       return((Image *) NULL);
4083     }
4084   id=number_windows++;
4085   window_info[id].window=window;
4086   window_info[id].visual=window_attributes.visual;
4087   window_info[id].colormap=window_attributes.colormap;
4088   window_info[id].bounds.x1=(short) crop_info.x;
4089   window_info[id].bounds.y1=(short) crop_info.y;
4090   window_info[id].bounds.x2=(short) (crop_info.x+(int) crop_info.width-1);
4091   window_info[id].bounds.y2=(short) (crop_info.y+(int) crop_info.height-1);
4092   crop_info.x-=x_offset;
4093   crop_info.y-=y_offset;
4094   window_info[id].crop_info=crop_info;
4095   if (level != 0)
4096     {
4097       unsigned int
4098         number_children;
4099
4100       Window
4101         *children;
4102
4103       /*
4104         Descend the window hierarchy.
4105       */
4106       status=XQueryTree(display,window,&root_window,&window_info[id].parent,
4107         &children,&number_children);
4108       for (i=0; i < id; i++)
4109         if ((window_info[i].window == window_info[id].parent) &&
4110             (window_info[i].visual == window_info[id].visual) &&
4111             (window_info[i].colormap == window_info[id].colormap))
4112           {
4113             if ((window_info[id].bounds.x1 <= window_info[i].bounds.x1) ||
4114                 (window_info[id].bounds.x1 >= window_info[i].bounds.x2) ||
4115                 (window_info[id].bounds.y1 <= window_info[i].bounds.y1) ||
4116                 (window_info[id].bounds.y1 >= window_info[i].bounds.y2))
4117               {
4118                 /*
4119                   Eliminate windows not circumscribed by their parent.
4120                 */
4121                 number_windows--;
4122                 break;
4123               }
4124           }
4125       if ((status == True) && (number_children != 0))
4126         {
4127           for (i=0; i < (int) number_children; i++)
4128             (void) XGetWindowImage(display,children[i],MagickFalse,level+1);
4129           (void) XFree((void *) children);
4130         }
4131     }
4132   if (level <= 1)
4133     {
4134       CacheView
4135         *composite_view;
4136
4137       ColormapInfo
4138         *next;
4139
4140       ExceptionInfo
4141         *exception;
4142
4143       Image
4144         *composite_image,
4145         *image;
4146
4147       int
4148         y;
4149
4150       MagickBooleanType
4151         import;
4152
4153       register int
4154         j,
4155         x;
4156
4157       register PixelPacket
4158         *restrict q;
4159
4160       register size_t
4161         pixel;
4162
4163       unsigned int
4164         number_colors;
4165
4166       XColor
4167         *colors;
4168
4169       XImage
4170         *ximage;
4171
4172       /*
4173         Get X image for each window in the list.
4174       */
4175       image=NewImageList();
4176       for (id=0; id < number_windows; id++)
4177       {
4178         /*
4179           Does target window intersect top level window?
4180         */
4181         import=
4182           ((window_info[id].bounds.x2 >= window_info[0].bounds.x1) &&
4183            (window_info[id].bounds.x1 <= window_info[0].bounds.x2) &&
4184            (window_info[id].bounds.y2 >= window_info[0].bounds.y1) &&
4185            (window_info[id].bounds.y1 <= window_info[0].bounds.y2)) ?
4186           MagickTrue : MagickFalse;
4187         /*
4188           Is target window contained by another window with the same colormap?
4189         */
4190         for (j=0; j < id; j++)
4191           if ((window_info[id].visual == window_info[j].visual) &&
4192               (window_info[id].colormap == window_info[j].colormap))
4193             {
4194               if ((window_info[id].bounds.x1 <= window_info[j].bounds.x1) ||
4195                   (window_info[id].bounds.x1 >= window_info[j].bounds.x2) ||
4196                   (window_info[id].bounds.y1 <= window_info[j].bounds.y1) ||
4197                   (window_info[id].bounds.y1 >= window_info[j].bounds.y2))
4198                   import=MagickFalse;
4199             }
4200           else
4201             if ((window_info[id].visual != window_info[j].visual) ||
4202                 (window_info[id].colormap != window_info[j].colormap))
4203               {
4204                 if ((window_info[id].bounds.x2 > window_info[j].bounds.x1) &&
4205                     (window_info[id].bounds.x1 < window_info[j].bounds.x2) &&
4206                     (window_info[id].bounds.y2 > window_info[j].bounds.y1) &&
4207                     (window_info[id].bounds.y1 < window_info[j].bounds.y2))
4208                   import=MagickTrue;
4209               }
4210         if (import == MagickFalse)
4211           continue;
4212         /*
4213           Get X image.
4214         */
4215         ximage=XGetImage(display,window_info[id].window,(int)
4216           window_info[id].crop_info.x,(int) window_info[id].crop_info.y,
4217           (unsigned int) window_info[id].crop_info.width,(unsigned int)
4218           window_info[id].crop_info.height,AllPlanes,ZPixmap);
4219         if (ximage == (XImage *) NULL)
4220           continue;
4221         /*
4222           Initialize window colormap.
4223         */
4224         number_colors=0;
4225         colors=(XColor *) NULL;
4226         if (window_info[id].colormap != (Colormap) NULL)
4227           {
4228             ColormapInfo
4229               *p;
4230
4231             /*
4232               Search colormap list for window colormap.
4233             */
4234             number_colors=(unsigned int) window_info[id].visual->map_entries;
4235             for (p=colormap_info; p != (ColormapInfo *) NULL; p=p->next)
4236               if (p->colormap == window_info[id].colormap)
4237                 break;
4238             if (p == (ColormapInfo *) NULL)
4239               {
4240                 /*
4241                   Get the window colormap.
4242                 */
4243                 colors=(XColor *) AcquireQuantumMemory(number_colors,
4244                   sizeof(*colors));
4245                 if (colors == (XColor *) NULL)
4246                   {
4247                     XDestroyImage(ximage);
4248                     return((Image *) NULL);
4249                   }
4250                 if ((window_info[id].visual->klass != DirectColor) &&
4251                     (window_info[id].visual->klass != TrueColor))
4252                   for (i=0; i < (int) number_colors; i++)
4253                   {
4254                     colors[i].pixel=(size_t) i;
4255                     colors[i].pad='\0';
4256                   }
4257                 else
4258                   {
4259                     size_t
4260                       blue,
4261                       blue_bit,
4262                       green,
4263                       green_bit,
4264                       red,
4265                       red_bit;
4266
4267                     /*
4268                       DirectColor or TrueColor visual.
4269                     */
4270                     red=0;
4271                     green=0;
4272                     blue=0;
4273                     red_bit=window_info[id].visual->red_mask &
4274                       (~(window_info[id].visual->red_mask)+1);
4275                     green_bit=window_info[id].visual->green_mask &
4276                       (~(window_info[id].visual->green_mask)+1);
4277                     blue_bit=window_info[id].visual->blue_mask &
4278                       (~(window_info[id].visual->blue_mask)+1);
4279                     for (i=0; i < (int) number_colors; i++)
4280                     {
4281                       colors[i].pixel=(unsigned long) (red | green | blue);
4282                       colors[i].pad='\0';
4283                       red+=red_bit;
4284                       if (red > window_info[id].visual->red_mask)
4285                         red=0;
4286                       green+=green_bit;
4287                       if (green > window_info[id].visual->green_mask)
4288                         green=0;
4289                       blue+=blue_bit;
4290                       if (blue > window_info[id].visual->blue_mask)
4291                         blue=0;
4292                     }
4293                   }
4294                 (void) XQueryColors(display,window_info[id].colormap,colors,
4295                   (int) number_colors);
4296                 /*
4297                   Append colormap to colormap list.
4298                 */
4299                 p=(ColormapInfo *) AcquireMagickMemory(sizeof(*p));
4300                 if (p == (ColormapInfo *) NULL)
4301                   return((Image *) NULL);
4302                 p->colormap=window_info[id].colormap;
4303                 p->colors=colors;
4304                 p->next=colormap_info;
4305                 colormap_info=p;
4306               }
4307             colors=p->colors;
4308           }
4309         /*
4310           Allocate image structure.
4311         */
4312         composite_image=AcquireImage((ImageInfo *) NULL);
4313         if (composite_image == (Image *) NULL)
4314           {
4315             XDestroyImage(ximage);
4316             return((Image *) NULL);
4317           }
4318         /*
4319           Convert X image to MIFF format.
4320         */
4321         if ((window_info[id].visual->klass != TrueColor) &&
4322             (window_info[id].visual->klass != DirectColor))
4323           composite_image->storage_class=PseudoClass;
4324         composite_image->columns=(size_t) ximage->width;
4325         composite_image->rows=(size_t) ximage->height;
4326         exception=(&composite_image->exception);
4327         composite_view=AcquireCacheView(composite_image);
4328         switch (composite_image->storage_class)
4329         {
4330           case DirectClass:
4331           default:
4332           {
4333             register size_t
4334               color,
4335               index;
4336
4337             size_t
4338               blue_mask,
4339               blue_shift,
4340               green_mask,
4341               green_shift,
4342               red_mask,
4343               red_shift;
4344
4345             /*
4346               Determine shift and mask for red, green, and blue.
4347             */
4348             red_mask=window_info[id].visual->red_mask;
4349             red_shift=0;
4350             while ((red_mask != 0) && ((red_mask & 0x01) == 0))
4351             {
4352               red_mask>>=1;
4353               red_shift++;
4354             }
4355             green_mask=window_info[id].visual->green_mask;
4356             green_shift=0;
4357             while ((green_mask != 0) && ((green_mask & 0x01) == 0))
4358             {
4359               green_mask>>=1;
4360               green_shift++;
4361             }
4362             blue_mask=window_info[id].visual->blue_mask;
4363             blue_shift=0;
4364             while ((blue_mask != 0) && ((blue_mask & 0x01) == 0))
4365             {
4366               blue_mask>>=1;
4367               blue_shift++;
4368             }
4369             /*
4370               Convert X image to DirectClass packets.
4371             */
4372             if ((number_colors != 0) &&
4373                 (window_info[id].visual->klass == DirectColor))
4374               for (y=0; y < (int) composite_image->rows; y++)
4375               {
4376                 q=QueueCacheViewAuthenticPixels(composite_view,0,(ssize_t) y,
4377                   composite_image->columns,1,exception);
4378                 if (q == (PixelPacket *) NULL)
4379                   break;
4380                 for (x=0; x < (int) composite_image->columns; x++)
4381                 {
4382                   pixel=XGetPixel(ximage,x,y);
4383                   index=(pixel >> red_shift) & red_mask;
4384                   q->red=ScaleShortToQuantum(colors[index].red);
4385                   index=(pixel >> green_shift) & green_mask;
4386                   q->green=ScaleShortToQuantum(colors[index].green);
4387                   index=(pixel >> blue_shift) & blue_mask;
4388                   q->blue=ScaleShortToQuantum(colors[index].blue);
4389                   q++;
4390                 }
4391                 if (SyncCacheViewAuthenticPixels(composite_view,exception) == MagickFalse)
4392                   break;
4393               }
4394             else
4395               for (y=0; y < (int) composite_image->rows; y++)
4396               {
4397                 q=QueueCacheViewAuthenticPixels(composite_view,0,(ssize_t) y,
4398                   composite_image->columns,1,exception);
4399                 if (q == (PixelPacket *) NULL)
4400                   break;
4401                 for (x=0; x < (int) composite_image->columns; x++)
4402                 {
4403                   pixel=XGetPixel(ximage,x,y);
4404                   color=(pixel >> red_shift) & red_mask;
4405                   color=(65535UL*color)/red_mask;
4406                   q->red=ScaleShortToQuantum((unsigned short) color);
4407                   color=(pixel >> green_shift) & green_mask;
4408                   color=(65535UL*color)/green_mask;
4409                   q->green=ScaleShortToQuantum((unsigned short) color);
4410                   color=(pixel >> blue_shift) & blue_mask;
4411                   color=(65535UL*color)/blue_mask;
4412                   q->blue=ScaleShortToQuantum((unsigned short) color);
4413                   q++;
4414                 }
4415                 if (SyncCacheViewAuthenticPixels(composite_view,exception) == MagickFalse)
4416                   break;
4417               }
4418             break;
4419           }
4420           case PseudoClass:
4421           {
4422             /*
4423               Create colormap.
4424             */
4425             if (AcquireImageColormap(composite_image,number_colors) == MagickFalse)
4426               {
4427                 XDestroyImage(ximage);
4428                 composite_image=DestroyImage(composite_image);
4429                 return((Image *) NULL);
4430               }
4431             for (i=0; i < (int) composite_image->colors; i++)
4432             {
4433               composite_image->colormap[colors[i].pixel].red=
4434                 ScaleShortToQuantum(colors[i].red);
4435               composite_image->colormap[colors[i].pixel].green=
4436                 ScaleShortToQuantum(colors[i].green);
4437               composite_image->colormap[colors[i].pixel].blue=
4438                 ScaleShortToQuantum(colors[i].blue);
4439             }
4440             /*
4441               Convert X image to PseudoClass packets.
4442             */
4443             for (y=0; y < (int) composite_image->rows; y++)
4444             {
4445               q=QueueCacheViewAuthenticPixels(composite_view,0,(ssize_t) y,
4446                 composite_image->columns,1,exception);
4447               if (q == (PixelPacket *) NULL)
4448                 break;
4449               indexes=GetCacheViewAuthenticIndexQueue(composite_view);
4450               for (x=0; x < (int) composite_image->columns; x++)
4451               {
4452                 index=(IndexPacket) XGetPixel(ximage,x,y);
4453                 indexes[x]=index;
4454                 *q++=composite_image->colormap[(ssize_t) index];
4455               }
4456               if (SyncCacheViewAuthenticPixels(composite_view,exception) == MagickFalse)
4457                 break;
4458             }
4459             break;
4460           }
4461         }
4462         composite_view=DestroyCacheView(composite_view);
4463         XDestroyImage(ximage);
4464         if (image == (Image *) NULL)
4465           {
4466             image=composite_image;
4467             continue;
4468           }
4469         /*
4470           Composite any children in back-to-front order.
4471         */
4472         (void) XTranslateCoordinates(display,window_info[id].window,window,0,0,
4473           &x_offset,&y_offset,&child);
4474         x_offset-=(int) crop_info.x;
4475         if (x_offset < 0)
4476           x_offset=0;
4477         y_offset-=(int) crop_info.y;
4478         if (y_offset < 0)
4479           y_offset=0;
4480         (void) CompositeImage(image,CopyCompositeOp,composite_image,(ssize_t)
4481           x_offset,(ssize_t) y_offset);
4482       }
4483       /*
4484         Relinquish resources.
4485       */
4486       while (colormap_info != (ColormapInfo *) NULL)
4487       {
4488         next=colormap_info->next;
4489         colormap_info->colors=(XColor *)
4490           RelinquishMagickMemory(colormap_info->colors);
4491         colormap_info=(ColormapInfo *) RelinquishMagickMemory(colormap_info);
4492         colormap_info=next;
4493       }
4494       /*
4495         Relinquish resources and restore initial state.
4496       */
4497       window_info=(WindowInfo *) RelinquishMagickMemory(window_info);
4498       max_windows=0;
4499       number_windows=0;
4500       colormap_info=(ColormapInfo *) NULL;
4501       return(image);
4502     }
4503   return((Image *) NULL);
4504 }
4505 \f
4506 /*
4507 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4508 %                                                                             %
4509 %                                                                             %
4510 %                                                                             %
4511 %   X G e t W i n d o w I n f o                                               %
4512 %                                                                             %
4513 %                                                                             %
4514 %                                                                             %
4515 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4516 %
4517 %  XGetWindowInfo() initializes the XWindowInfo structure.
4518 %
4519 %  The format of the XGetWindowInfo method is:
4520 %
4521 %      void XGetWindowInfo(Display *display,XVisualInfo *visual_info,
4522 %        XStandardColormap *map_info,XPixelInfo *pixel,XFontStruct *font_info,
4523 %        XResourceInfo *resource_info,XWindowInfo *window)
4524 %        resource_info,window)
4525 %
4526 %  A description of each parameter follows:
4527 %
4528 %    o display: Specifies a connection to an X server; returned from
4529 %      XOpenDisplay.
4530 %
4531 %    o visual_info: Specifies a pointer to a X11 XVisualInfo structure;
4532 %      returned from XGetVisualInfo.
4533 %
4534 %    o map_info: If map_type is specified, this structure is initialized
4535 %      with info from the Standard Colormap.
4536 %
4537 %    o pixel: Specifies a pointer to a XPixelInfo structure.
4538 %
4539 %    o font_info: Specifies a pointer to a XFontStruct structure.
4540 %
4541 %    o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
4542 %
4543 */
4544 MagickExport void XGetWindowInfo(Display *display,XVisualInfo *visual_info,
4545   XStandardColormap *map_info,XPixelInfo *pixel,XFontStruct *font_info,
4546   XResourceInfo *resource_info,XWindowInfo *window)
4547 {
4548   /*
4549     Initialize window info.
4550   */
4551   (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
4552   assert(display != (Display *) NULL);
4553   assert(visual_info != (XVisualInfo *) NULL);
4554   assert(map_info != (XStandardColormap *) NULL);
4555   assert(pixel != (XPixelInfo *) NULL);
4556   assert(resource_info != (XResourceInfo *) NULL);
4557   assert(window != (XWindowInfo *) NULL);
4558   if (window->id != (Window) NULL)
4559     {
4560       if (window->cursor != (Cursor) NULL)
4561         (void) XFreeCursor(display,window->cursor);
4562       if (window->busy_cursor != (Cursor) NULL)
4563         (void) XFreeCursor(display,window->busy_cursor);
4564       if (window->highlight_stipple != (Pixmap) NULL)
4565         (void) XFreePixmap(display,window->highlight_stipple);
4566       if (window->shadow_stipple != (Pixmap) NULL)
4567         (void) XFreePixmap(display,window->shadow_stipple);
4568       if (window->name == (char *) NULL)
4569         window->name=AcquireString("");
4570       if (window->icon_name == (char *) NULL)
4571         window->icon_name=AcquireString("");
4572     }
4573   else
4574     {
4575       /*
4576         Initialize these attributes just once.
4577       */
4578       window->id=(Window) NULL;
4579       if (window->name == (char *) NULL)
4580         window->name=AcquireString("");
4581       if (window->icon_name == (char *) NULL)
4582         window->icon_name=AcquireString("");
4583       window->x=XDisplayWidth(display,visual_info->screen) >> 1;
4584       window->y=XDisplayWidth(display,visual_info->screen) >> 1;
4585       window->ximage=(XImage *) NULL;
4586       window->matte_image=(XImage *) NULL;
4587       window->pixmap=(Pixmap) NULL;
4588       window->matte_pixmap=(Pixmap) NULL;
4589       window->mapped=MagickFalse;
4590       window->stasis=MagickFalse;
4591       window->shared_memory=MagickTrue;
4592       window->segment_info=(void *) NULL;
4593 #if defined(MAGICKCORE_HAVE_SHARED_MEMORY)
4594       {
4595         XShmSegmentInfo
4596           *segment_info;
4597
4598         if (window->segment_info == (void *) NULL)
4599           window->segment_info=AcquireQuantumMemory(2,sizeof(*segment_info));
4600         segment_info=(XShmSegmentInfo *) window->segment_info;
4601         segment_info[0].shmid=(-1);
4602         segment_info[0].shmaddr=(char *) NULL;
4603         segment_info[1].shmid=(-1);
4604         segment_info[1].shmaddr=(char *) NULL;
4605       }
4606 #endif
4607     }
4608   /*
4609     Initialize these attributes every time function is called.
4610   */
4611   window->screen=visual_info->screen;
4612   window->root=XRootWindow(display,visual_info->screen);
4613   window->visual=visual_info->visual;
4614   window->storage_class=(unsigned int) visual_info->klass;
4615   window->depth=(unsigned int) visual_info->depth;
4616   window->visual_info=visual_info;
4617   window->map_info=map_info;
4618   window->pixel_info=pixel;
4619   window->font_info=font_info;
4620   window->cursor=XCreateFontCursor(display,XC_left_ptr);
4621   window->busy_cursor=XCreateFontCursor(display,XC_watch);
4622   window->geometry=(char *) NULL;
4623   window->icon_geometry=(char *) NULL;
4624   if (resource_info->icon_geometry != (char *) NULL)
4625     (void) CloneString(&window->icon_geometry,resource_info->icon_geometry);
4626   window->crop_geometry=(char *) NULL;
4627   window->flags=(size_t) PSize;
4628   window->width=1;
4629   window->height=1;
4630   window->min_width=1;
4631   window->min_height=1;
4632   window->width_inc=1;
4633   window->height_inc=1;
4634   window->border_width=resource_info->border_width;
4635   window->annotate_context=pixel->annotate_context;
4636   window->highlight_context=pixel->highlight_context;
4637   window->widget_context=pixel->widget_context;
4638   window->shadow_stipple=(Pixmap) NULL;
4639   window->highlight_stipple=(Pixmap) NULL;
4640   window->use_pixmap=MagickTrue;
4641   window->immutable=MagickFalse;
4642   window->shape=MagickFalse;
4643   window->data=0;
4644   window->mask=(int) (CWBackingStore | CWBackPixel | CWBackPixmap |
4645     CWBitGravity | CWBorderPixel | CWColormap | CWCursor | CWDontPropagate |
4646     CWEventMask | CWOverrideRedirect | CWSaveUnder | CWWinGravity);
4647   window->attributes.background_pixel=pixel->background_color.pixel;
4648   window->attributes.background_pixmap=(Pixmap) NULL;
4649   window->attributes.bit_gravity=ForgetGravity;
4650   window->attributes.backing_store=WhenMapped;
4651   window->attributes.save_under=MagickTrue;
4652   window->attributes.border_pixel=pixel->border_color.pixel;
4653   window->attributes.colormap=map_info->colormap;
4654   window->attributes.cursor=window->cursor;
4655   window->attributes.do_not_propagate_mask=NoEventMask;
4656   window->attributes.event_mask=NoEventMask;
4657   window->attributes.override_redirect=MagickFalse;
4658   window->attributes.win_gravity=NorthWestGravity;
4659   window->orphan=MagickFalse;
4660 }
4661 \f
4662 /*
4663 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4664 %                                                                             %
4665 %                                                                             %
4666 %                                                                             %
4667 %   X H i g h l i g h t E l l i p s e                                         %
4668 %                                                                             %
4669 %                                                                             %
4670 %                                                                             %
4671 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4672 %
4673 %  XHighlightEllipse() puts a border on the X server around a region defined by
4674 %  highlight_info.
4675 %
4676 %  The format of the XHighlightEllipse method is:
4677 %
4678 %      void XHighlightEllipse(Display *display,Window window,
4679 %        GC annotate_context,const RectangleInfo *highlight_info)
4680 %
4681 %  A description of each parameter follows:
4682 %
4683 %    o display: Specifies a connection to an X server; returned from
4684 %      XOpenDisplay.
4685 %
4686 %    o window: Specifies a pointer to a Window structure.
4687 %
4688 %    o annotate_context: Specifies a pointer to a GC structure.
4689 %
4690 %    o highlight_info: Specifies a pointer to a RectangleInfo structure.  It
4691 %      contains the extents of any highlighting rectangle.
4692 %
4693 */
4694 MagickExport void XHighlightEllipse(Display *display,Window window,
4695   GC annotate_context,const RectangleInfo *highlight_info)
4696 {
4697   (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
4698   assert(display != (Display *) NULL);
4699   assert(window != (Window) NULL);
4700   assert(annotate_context != (GC) NULL);
4701   assert(highlight_info != (RectangleInfo *) NULL);
4702   if ((highlight_info->width < 4) || (highlight_info->height < 4))
4703     return;
4704   (void) XDrawArc(display,window,annotate_context,(int) highlight_info->x,
4705     (int) highlight_info->y,(unsigned int) highlight_info->width-1,
4706     (unsigned int) highlight_info->height-1,0,360*64);
4707   (void) XDrawArc(display,window,annotate_context,(int) highlight_info->x+1,
4708     (int) highlight_info->y+1,(unsigned int) highlight_info->width-3,
4709     (unsigned int) highlight_info->height-3,0,360*64);
4710 }
4711 \f
4712 /*
4713 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4714 %                                                                             %
4715 %                                                                             %
4716 %                                                                             %
4717 %   X H i g h l i g h t L i n e                                               %
4718 %                                                                             %
4719 %                                                                             %
4720 %                                                                             %
4721 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4722 %
4723 %  XHighlightLine() puts a border on the X server around a region defined by
4724 %  highlight_info.
4725 %
4726 %  The format of the XHighlightLine method is:
4727 %
4728 %      void XHighlightLine(Display *display,Window window,GC annotate_context,
4729 %        const XSegment *highlight_info)
4730 %
4731 %  A description of each parameter follows:
4732 %
4733 %    o display: Specifies a connection to an X server; returned from
4734 %      XOpenDisplay.
4735 %
4736 %    o window: Specifies a pointer to a Window structure.
4737 %
4738 %    o annotate_context: Specifies a pointer to a GC structure.
4739 %
4740 %    o highlight_info: Specifies a pointer to a RectangleInfo structure.  It
4741 %      contains the extents of any highlighting rectangle.
4742 %
4743 */
4744 MagickExport void XHighlightLine(Display *display,Window window,
4745   GC annotate_context,const XSegment *highlight_info)
4746 {
4747   (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
4748   assert(display != (Display *) NULL);
4749   assert(window != (Window) NULL);
4750   assert(annotate_context != (GC) NULL);
4751   assert(highlight_info != (XSegment *) NULL);
4752   (void) XDrawLine(display,window,annotate_context,highlight_info->x1,
4753     highlight_info->y1,highlight_info->x2,highlight_info->y2);
4754 }
4755 \f
4756 /*
4757 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4758 %                                                                             %
4759 %                                                                             %
4760 %                                                                             %
4761 %   X H i g h l i g h t R e c t a n g l e                                     %
4762 %                                                                             %
4763 %                                                                             %
4764 %                                                                             %
4765 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4766 %
4767 %  XHighlightRectangle() puts a border on the X server around a region defined
4768 %  by highlight_info.
4769 %
4770 %  The format of the XHighlightRectangle method is:
4771 %
4772 %      void XHighlightRectangle(Display *display,Window window,
4773 %        GC annotate_context,const RectangleInfo *highlight_info)
4774 %
4775 %  A description of each parameter follows:
4776 %
4777 %    o display: Specifies a connection to an X server; returned from
4778 %      XOpenDisplay.
4779 %
4780 %    o window: Specifies a pointer to a Window structure.
4781 %
4782 %    o annotate_context: Specifies a pointer to a GC structure.
4783 %
4784 %    o highlight_info: Specifies a pointer to a RectangleInfo structure.  It
4785 %      contains the extents of any highlighting rectangle.
4786 %
4787 */
4788 MagickExport void XHighlightRectangle(Display *display,Window window,
4789   GC annotate_context,const RectangleInfo *highlight_info)
4790 {
4791   assert(display != (Display *) NULL);
4792   (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
4793   assert(window != (Window) NULL);
4794   assert(annotate_context != (GC) NULL);
4795   assert(highlight_info != (RectangleInfo *) NULL);
4796   if ((highlight_info->width < 4) || (highlight_info->height < 4))
4797     return;
4798   (void) XDrawRectangle(display,window,annotate_context,(int) highlight_info->x,
4799     (int) highlight_info->y,(unsigned int) highlight_info->width-1,
4800     (unsigned int) highlight_info->height-1);
4801   (void) XDrawRectangle(display,window,annotate_context,(int) highlight_info->x+
4802     1,(int) highlight_info->y+1,(unsigned int) highlight_info->width-3,
4803     (unsigned int) highlight_info->height-3);
4804 }
4805 \f
4806 /*
4807 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4808 %                                                                             %
4809 %                                                                             %
4810 %                                                                             %
4811 %   X I m p o r t I m a g e                                                   %
4812 %                                                                             %
4813 %                                                                             %
4814 %                                                                             %
4815 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4816 %
4817 %  XImportImage() reads an image from an X window.
4818 %
4819 %  The format of the XImportImage method is:
4820 %
4821 %      Image *XImportImage(const ImageInfo *image_info,XImportInfo *ximage_info)
4822 %
4823 %  A description of each parameter follows:
4824 %
4825 %    o image_info: the image info.
4826 %
4827 %    o ximage_info: Specifies a pointer to an XImportInfo structure.
4828 %
4829 */
4830 MagickExport Image *XImportImage(const ImageInfo *image_info,
4831   XImportInfo *ximage_info)
4832 {
4833   Colormap
4834     *colormaps;
4835
4836   Display
4837     *display;
4838
4839   Image
4840     *image;
4841
4842   int
4843     number_colormaps,
4844     number_windows,
4845     x;
4846
4847   RectangleInfo
4848     crop_info;
4849
4850   Status
4851     status;
4852
4853   Window
4854     *children,
4855     client,
4856     prior_target,
4857     root,
4858     target;
4859
4860   XTextProperty
4861     window_name;
4862
4863   /*
4864     Open X server connection.
4865   */
4866   assert(image_info != (const ImageInfo *) NULL);
4867   assert(image_info->signature == MagickSignature);
4868   if (image_info->debug != MagickFalse)
4869     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
4870       image_info->filename);
4871   assert(ximage_info != (XImportInfo *) NULL);
4872   display=XOpenDisplay(image_info->server_name);
4873   if (display == (Display *) NULL)
4874     {
4875       ThrowXWindowFatalException(XServerError,"UnableToOpenXServer",
4876         XDisplayName(image_info->server_name));
4877       return((Image *) NULL);
4878     }
4879   /*
4880     Set our forgiving exception handler.
4881   */
4882   (void) XSetErrorHandler(XError);
4883   /*
4884     Select target window.
4885   */
4886   crop_info.x=0;
4887   crop_info.y=0;
4888   crop_info.width=0;
4889   crop_info.height=0;
4890   root=XRootWindow(display,XDefaultScreen(display));
4891   target=(Window) NULL;
4892   if ((image_info->filename != (char *) NULL) &&
4893       (*image_info->filename != '\0'))
4894     {
4895       if (LocaleCompare(image_info->filename,"root") == 0)
4896         target=root;
4897       else
4898         {
4899           /*
4900             Select window by ID or name.
4901           */
4902           if (isdigit((unsigned char) *image_info->filename) != 0)
4903             target=XWindowByID(display,root,(Window)
4904               strtol(image_info->filename,(char **) NULL,0));
4905           if (target == (Window) NULL)
4906             target=XWindowByName(display,root,image_info->filename);
4907           if (target == (Window) NULL)
4908             ThrowXWindowFatalException(XServerError,
4909               "NoWindowWithSpecifiedIDExists",image_info->filename);
4910         }
4911     }
4912   /*
4913     If target window is not defined, interactively select one.
4914   */
4915   prior_target=target;
4916   if (target == (Window) NULL)
4917     target=XSelectWindow(display,&crop_info);
4918   if (target == (Window) NULL)
4919     ThrowXWindowFatalException(XServerError,"UnableToReadXWindowImage",
4920       image_info->filename);
4921   client=target;   /* obsolete */
4922   if (target != root)
4923     {
4924       unsigned int
4925         d;
4926
4927       status=XGetGeometry(display,target,&root,&x,&x,&d,&d,&d,&d);
4928       if (status != False)
4929         {
4930           for ( ; ; )
4931           {
4932             Window
4933               parent;
4934
4935             /*
4936               Find window manager frame.
4937             */
4938             status=XQueryTree(display,target,&root,&parent,&children,&d);
4939             if ((status != False) && (children != (Window *) NULL))
4940               (void) XFree((char *) children);
4941             if ((status == False) || (parent == (Window) NULL) ||
4942                 (parent == root))
4943               break;
4944             target=parent;
4945           }
4946           /*
4947             Get client window.
4948           */
4949           client=XClientWindow(display,target);
4950           if (ximage_info->frame == MagickFalse)
4951             target=client;
4952           if ((ximage_info->frame == MagickFalse) &&
4953               (prior_target != MagickFalse))
4954             target=prior_target;
4955           XDelay(display,SuspendTime << 4);
4956         }
4957     }
4958   if (ximage_info->screen)
4959     {
4960       int
4961         y;
4962
4963       Window
4964         child;
4965
4966       XWindowAttributes
4967         window_attributes;
4968
4969       /*
4970         Obtain window image directly from screen.
4971       */
4972       status=XGetWindowAttributes(display,target,&window_attributes);
4973       if (status == False)
4974         {
4975           ThrowXWindowFatalException(XServerError,
4976             "UnableToReadXWindowAttributes",image_info->filename);
4977           (void) XCloseDisplay(display);
4978           return((Image *) NULL);
4979         }
4980       (void) XTranslateCoordinates(display,target,root,0,0,&x,&y,&child);
4981       crop_info.x=(ssize_t) x;
4982       crop_info.y=(ssize_t) y;
4983       crop_info.width=(size_t) window_attributes.width;
4984       crop_info.height=(size_t) window_attributes.height;
4985       if (ximage_info->borders != 0)
4986         {
4987           /*
4988             Include border in image.
4989           */
4990           crop_info.x-=window_attributes.border_width;
4991           crop_info.y-=window_attributes.border_width;
4992           crop_info.width+=window_attributes.border_width << 1;
4993           crop_info.height+=window_attributes.border_width << 1;
4994         }
4995       target=root;
4996     }
4997   /*
4998     If WM_COLORMAP_WINDOWS property is set or multiple colormaps, descend.
4999   */
5000   number_windows=0;
5001   status=XGetWMColormapWindows(display,target,&children,&number_windows);
5002   if ((status == True) && (number_windows > 0))
5003     {
5004       ximage_info->descend=MagickTrue;
5005       (void) XFree ((char *) children);
5006     }
5007   colormaps=XListInstalledColormaps(display,target,&number_colormaps);
5008   if (number_colormaps > 0)
5009     {
5010       if (number_colormaps > 1)
5011         ximage_info->descend=MagickTrue;
5012       (void) XFree((char *) colormaps);
5013     }
5014   /*
5015     Alert the user not to alter the screen.
5016   */
5017   if (ximage_info->silent == MagickFalse)
5018     (void) XBell(display,0);
5019   /*
5020     Get image by window id.
5021   */
5022   (void) XGrabServer(display);
5023   image=XGetWindowImage(display,target,ximage_info->borders,
5024     ximage_info->descend ? 1U : 0U);
5025   (void) XUngrabServer(display);
5026   if (image == (Image *) NULL)
5027     ThrowXWindowFatalException(XServerError,"UnableToReadXWindowImage",
5028       image_info->filename)
5029   else
5030     {
5031       (void) CopyMagickString(image->filename,image_info->filename,
5032         MaxTextExtent);
5033       if ((crop_info.width != 0) && (crop_info.height != 0))
5034         {
5035           Image
5036             *clone_image,
5037             *crop_image;
5038
5039           /*
5040             Crop image as defined by the cropping rectangle.
5041           */
5042           clone_image=CloneImage(image,0,0,MagickTrue,&image->exception);
5043           if (clone_image != (Image *) NULL)
5044             {
5045               crop_image=CropImage(clone_image,&crop_info,&image->exception);
5046               if (crop_image != (Image *) NULL)
5047                 {
5048                   image=DestroyImage(image);
5049                   image=crop_image;
5050                 }
5051             }
5052         }
5053       status=XGetWMName(display,target,&window_name);
5054       if (status == True)
5055         {
5056           if ((image_info->filename != (char *) NULL) &&
5057               (*image_info->filename == '\0'))
5058             (void) CopyMagickString(image->filename,(char *) window_name.value,
5059               (size_t) window_name.nitems+1);
5060           (void) XFree((void *) window_name.value);
5061         }
5062     }
5063   if (ximage_info->silent == MagickFalse)
5064     {
5065       /*
5066         Alert the user we're done.
5067       */
5068       (void) XBell(display,0);
5069       (void) XBell(display,0);
5070     }
5071   (void) XCloseDisplay(display);
5072   return(image);
5073 }
5074 \f
5075 /*
5076 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5077 %                                                                             %
5078 %                                                                             %
5079 %                                                                             %
5080 %   X I n i t i a l i z e W i n d o w s                                       %
5081 %                                                                             %
5082 %                                                                             %
5083 %                                                                             %
5084 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5085 %
5086 %  XInitializeWindows() initializes the XWindows structure.
5087 %
5088 %  The format of the XInitializeWindows method is:
5089 %
5090 %      XWindows *XInitializeWindows(Display *display,
5091 %        XResourceInfo *resource_info)
5092 %
5093 %  A description of each parameter follows:
5094 %
5095 %    o windows: XInitializeWindows returns a pointer to a XWindows structure.
5096 %
5097 %    o display: Specifies a connection to an X server;  returned from
5098 %      XOpenDisplay.
5099 %
5100 %    o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
5101 %
5102 */
5103 MagickExport XWindows *XInitializeWindows(Display *display,
5104   XResourceInfo *resource_info)
5105 {
5106   Window
5107     root_window;
5108
5109   XWindows
5110     *windows;
5111
5112   /*
5113     Allocate windows structure.
5114   */
5115   windows=(XWindows *) AcquireMagickMemory(sizeof(*windows));
5116   if (windows == (XWindows *) NULL)
5117     {
5118       ThrowXWindowFatalException(XServerFatalError,"MemoryAllocationFailed",
5119         "...");
5120       return((XWindows *) NULL);
5121     }
5122   (void) ResetMagickMemory(windows,0,sizeof(*windows));
5123   windows->pixel_info=(XPixelInfo *) AcquireMagickMemory(
5124     sizeof(*windows->pixel_info));
5125   windows->icon_pixel=(XPixelInfo *) AcquireMagickMemory(
5126     sizeof(*windows->icon_pixel));
5127   windows->icon_resources=(XResourceInfo *) AcquireMagickMemory(
5128     sizeof(*windows->icon_resources));
5129   if ((windows->pixel_info == (XPixelInfo *) NULL) ||
5130       (windows->icon_pixel == (XPixelInfo *) NULL) ||
5131       (windows->icon_resources == (XResourceInfo *) NULL))
5132     {
5133       ThrowXWindowFatalException(XServerFatalError,"MemoryAllocationFailed",
5134         "...");
5135       return((XWindows *) NULL);
5136     }
5137   /*
5138     Initialize windows structure.
5139   */
5140   windows->display=display;
5141   windows->wm_protocols=XInternAtom(display,"WM_PROTOCOLS",MagickFalse);
5142   windows->wm_delete_window=XInternAtom(display,"WM_DELETE_WINDOW",MagickFalse);
5143   windows->wm_take_focus=XInternAtom(display,"WM_TAKE_FOCUS",MagickFalse);
5144   windows->im_protocols=XInternAtom(display,"IM_PROTOCOLS",MagickFalse);
5145   windows->im_remote_command=
5146     XInternAtom(display,"IM_REMOTE_COMMAND",MagickFalse);
5147   windows->im_update_widget=XInternAtom(display,"IM_UPDATE_WIDGET",MagickFalse);
5148   windows->im_update_colormap=
5149     XInternAtom(display,"IM_UPDATE_COLORMAP",MagickFalse);
5150   windows->im_former_image=XInternAtom(display,"IM_FORMER_IMAGE",MagickFalse);
5151   windows->im_next_image=XInternAtom(display,"IM_NEXT_IMAGE",MagickFalse);
5152   windows->im_retain_colors=XInternAtom(display,"IM_RETAIN_COLORS",MagickFalse);
5153   windows->im_exit=XInternAtom(display,"IM_EXIT",MagickFalse);
5154   windows->dnd_protocols=XInternAtom(display,"DndProtocol",MagickFalse);
5155 #if defined(MAGICKCORE_WINDOWS_SUPPORT)
5156   (void) XSynchronize(display,IsWindows95());
5157 #endif
5158   if (IsEventLogging())
5159     {
5160       (void) XSynchronize(display,MagickTrue);
5161       (void) LogMagickEvent(X11Event,GetMagickModule(),"Version: %s",
5162         GetMagickVersion((size_t *) NULL));
5163       (void) LogMagickEvent(X11Event,GetMagickModule(),"Protocols:");
5164       (void) LogMagickEvent(X11Event,GetMagickModule(),
5165         "  Window Manager: 0x%lx",windows->wm_protocols);
5166       (void) LogMagickEvent(X11Event,GetMagickModule(),
5167         "    delete window: 0x%lx",windows->wm_delete_window);
5168       (void) LogMagickEvent(X11Event,GetMagickModule(),"    take focus: 0x%lx",
5169         windows->wm_take_focus);
5170       (void) LogMagickEvent(X11Event,GetMagickModule(),"  ImageMagick: 0x%lx",
5171         windows->im_protocols);
5172       (void) LogMagickEvent(X11Event,GetMagickModule(),
5173         "    remote command: 0x%lx",windows->im_remote_command);
5174       (void) LogMagickEvent(X11Event,GetMagickModule(),
5175         "    update widget: 0x%lx",windows->im_update_widget);
5176       (void) LogMagickEvent(X11Event,GetMagickModule(),
5177         "    update colormap: 0x%lx",windows->im_update_colormap);
5178       (void) LogMagickEvent(X11Event,GetMagickModule(),
5179         "    former image: 0x%lx",windows->im_former_image);
5180       (void) LogMagickEvent(X11Event,GetMagickModule(),"    next image: 0x%lx",
5181         windows->im_next_image);
5182       (void) LogMagickEvent(X11Event,GetMagickModule(),
5183         "    retain colors: 0x%lx",windows->im_retain_colors);
5184       (void) LogMagickEvent(X11Event,GetMagickModule(),"    exit: 0x%lx",
5185         windows->im_exit);
5186       (void) LogMagickEvent(X11Event,GetMagickModule(),"  Drag and Drop: 0x%lx",
5187         windows->dnd_protocols);
5188     }
5189   /*
5190     Allocate standard colormap.
5191   */
5192   windows->map_info=XAllocStandardColormap();
5193   windows->icon_map=XAllocStandardColormap();
5194   if ((windows->map_info == (XStandardColormap *) NULL) ||
5195       (windows->icon_map == (XStandardColormap *) NULL))
5196     ThrowXWindowFatalException(ResourceLimitFatalError,
5197       "MemoryAllocationFailed","...");
5198   windows->map_info->colormap=(Colormap) NULL;
5199   windows->icon_map->colormap=(Colormap) NULL;
5200   windows->pixel_info->pixels=(unsigned long *) NULL;
5201   windows->pixel_info->annotate_context=(GC) NULL;
5202   windows->pixel_info->highlight_context=(GC) NULL;
5203   windows->pixel_info->widget_context=(GC) NULL;
5204   windows->font_info=(XFontStruct *) NULL;
5205   windows->icon_pixel->annotate_context=(GC) NULL;
5206   windows->icon_pixel->pixels=(unsigned long *) NULL;
5207   /*
5208     Allocate visual.
5209   */
5210   *windows->icon_resources=(*resource_info);
5211   windows->icon_resources->visual_type=(char *) "default";
5212   windows->icon_resources->colormap=SharedColormap;
5213   windows->visual_info=
5214     XBestVisualInfo(display,windows->map_info,resource_info);
5215   windows->icon_visual=
5216     XBestVisualInfo(display,windows->icon_map,windows->icon_resources);
5217   if ((windows->visual_info == (XVisualInfo *) NULL) ||
5218       (windows->icon_visual == (XVisualInfo *) NULL))
5219     ThrowXWindowFatalException(XServerFatalError,"UnableToGetVisual",
5220       resource_info->visual_type);
5221   if (IsEventLogging())
5222     {
5223       (void) LogMagickEvent(X11Event,GetMagickModule(),"Visual:");
5224       (void) LogMagickEvent(X11Event,GetMagickModule(),"  visual id: 0x%lx",
5225         windows->visual_info->visualid);
5226       (void) LogMagickEvent(X11Event,GetMagickModule(),"  class: %s",
5227         XVisualClassName(windows->visual_info->klass));
5228       (void) LogMagickEvent(X11Event,GetMagickModule(),"  depth: %d planes",
5229         windows->visual_info->depth);
5230       (void) LogMagickEvent(X11Event,GetMagickModule(),
5231         "  size of colormap: %d entries",windows->visual_info->colormap_size);
5232       (void) LogMagickEvent(X11Event,GetMagickModule(),
5233         "  red, green, blue masks: 0x%lx 0x%lx 0x%lx",
5234         windows->visual_info->red_mask,windows->visual_info->green_mask,
5235         windows->visual_info->blue_mask);
5236       (void) LogMagickEvent(X11Event,GetMagickModule(),
5237         "  significant bits in color: %d bits",
5238         windows->visual_info->bits_per_rgb);
5239     }
5240   /*
5241     Allocate class and manager hints.
5242   */
5243   windows->class_hints=XAllocClassHint();
5244   windows->manager_hints=XAllocWMHints();
5245   if ((windows->class_hints == (XClassHint *) NULL) ||
5246       (windows->manager_hints == (XWMHints *) NULL))
5247     ThrowXWindowFatalException(ResourceLimitFatalError,
5248       "MemoryAllocationFailed","...");
5249   /*
5250     Determine group leader if we have one.
5251   */
5252   root_window=XRootWindow(display,windows->visual_info->screen);
5253   windows->group_leader.id=(Window) NULL;
5254   if (resource_info->window_group != (char *) NULL)
5255     {
5256       if (isdigit((unsigned char) *resource_info->window_group) != 0)
5257         windows->group_leader.id=XWindowByID(display,root_window,(Window)
5258           strtol((char *) resource_info->window_group,(char **) NULL,0));
5259       if (windows->group_leader.id == (Window) NULL)
5260         windows->group_leader.id=
5261           XWindowByName(display,root_window,resource_info->window_group);
5262     }
5263   return(windows);
5264 }
5265 \f
5266 /*
5267 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5268 %                                                                             %
5269 %                                                                             %
5270 %                                                                             %
5271 %   X M a k e C u r s o r                                                     %
5272 %                                                                             %
5273 %                                                                             %
5274 %                                                                             %
5275 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5276 %
5277 %  XMakeCursor() creates a crosshairs X11 cursor.
5278 %
5279 %  The format of the XMakeCursor method is:
5280 %
5281 %      Cursor XMakeCursor(Display *display,Window window,Colormap colormap,
5282 %        char *background_color,char *foreground_color)
5283 %
5284 %  A description of each parameter follows:
5285 %
5286 %    o display: Specifies a connection to an X server;  returned from
5287 %      XOpenDisplay.
5288 %
5289 %    o window: Specifies the ID of the window for which the cursor is
5290 %      assigned.
5291 %
5292 %    o colormap: Specifies the ID of the colormap from which the background
5293 %      and foreground color will be retrieved.
5294 %
5295 %    o background_color: Specifies the color to use for the cursor background.
5296 %
5297 %    o foreground_color: Specifies the color to use for the cursor foreground.
5298 %
5299 */
5300 MagickExport Cursor XMakeCursor(Display *display,Window window,
5301   Colormap colormap,char *background_color,char *foreground_color)
5302 {
5303 #define scope_height 17
5304 #define scope_x_hot 8
5305 #define scope_y_hot 8
5306 #define scope_width 17
5307
5308   static const unsigned char
5309     scope_bits[] =
5310     {
5311       0x80, 0x03, 0x00, 0x80, 0x02, 0x00, 0x80, 0x02, 0x00, 0x80, 0x02,
5312       0x00, 0x80, 0x02, 0x00, 0x80, 0x02, 0x00, 0x80, 0x02, 0x00, 0x7f,
5313       0xfc, 0x01, 0x01, 0x00, 0x01, 0x7f, 0xfc, 0x01, 0x80, 0x02, 0x00,
5314       0x80, 0x02, 0x00, 0x80, 0x02, 0x00, 0x80, 0x02, 0x00, 0x80, 0x02,
5315       0x00, 0x80, 0x02, 0x00, 0x80, 0x03, 0x00
5316     },
5317     scope_mask_bits[] =
5318     {
5319       0xc0, 0x07, 0x00, 0xc0, 0x07, 0x00, 0xc0, 0x06, 0x00, 0xc0, 0x06,
5320       0x00, 0xc0, 0x06, 0x00, 0xc0, 0x06, 0x00, 0xff, 0xfe, 0x01, 0x7f,
5321       0xfc, 0x01, 0x03, 0x80, 0x01, 0x7f, 0xfc, 0x01, 0xff, 0xfe, 0x01,
5322       0xc0, 0x06, 0x00, 0xc0, 0x06, 0x00, 0xc0, 0x06, 0x00, 0xc0, 0x06,
5323       0x00, 0xc0, 0x07, 0x00, 0xc0, 0x07, 0x00
5324     };
5325
5326   Cursor
5327     cursor;
5328
5329   Pixmap
5330     mask,
5331     source;
5332
5333   XColor
5334     background,
5335     foreground;
5336
5337   assert(display != (Display *) NULL);
5338   assert(window != (Window) NULL);
5339   assert(colormap != (Colormap) NULL);
5340   assert(background_color != (char *) NULL);
5341   assert(foreground_color != (char *) NULL);
5342   (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",background_color);
5343   source=XCreateBitmapFromData(display,window,(char *) scope_bits,scope_width,
5344     scope_height);
5345   mask=XCreateBitmapFromData(display,window,(char *) scope_mask_bits,
5346     scope_width,scope_height);
5347   if ((source == (Pixmap) NULL) || (mask == (Pixmap) NULL))
5348     {
5349       ThrowXWindowFatalException(XServerError,"UnableToCreatePixmap","...");
5350       return((Cursor) NULL);
5351     }
5352   (void) XParseColor(display,colormap,background_color,&background);
5353   (void) XParseColor(display,colormap,foreground_color,&foreground);
5354   cursor=XCreatePixmapCursor(display,source,mask,&foreground,&background,
5355     scope_x_hot,scope_y_hot);
5356   (void) XFreePixmap(display,source);
5357   (void) XFreePixmap(display,mask);
5358   return(cursor);
5359 }
5360 \f
5361 /*
5362 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5363 %                                                                             %
5364 %                                                                             %
5365 %                                                                             %
5366 %   X M a k e I m a g e                                                       %
5367 %                                                                             %
5368 %                                                                             %
5369 %                                                                             %
5370 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5371 %
5372 %  XMakeImage() creates an X11 image.  If the image size differs from the X11
5373 %  image size, the image is first resized.
5374 %
5375 %  The format of the XMakeImage method is:
5376 %
5377 %      MagickBooleanType XMakeImage(Display *display,
5378 %        const XResourceInfo *resource_info,XWindowInfo *window,Image *image,
5379 %        unsigned int width,unsigned int height)
5380 %
5381 %  A description of each parameter follows:
5382 %
5383 %    o display: Specifies a connection to an X server; returned from
5384 %      XOpenDisplay.
5385 %
5386 %    o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
5387 %
5388 %    o window: Specifies a pointer to a XWindowInfo structure.
5389 %
5390 %    o image: the image.
5391 %
5392 %    o width: Specifies the width in pixels of the rectangular area to
5393 %      display.
5394 %
5395 %    o height: Specifies the height in pixels of the rectangular area to
5396 %      display.
5397 %
5398 */
5399 MagickExport MagickBooleanType XMakeImage(Display *display,
5400   const XResourceInfo *resource_info,XWindowInfo *window,Image *image,
5401   unsigned int width,unsigned int height)
5402 {
5403 #define CheckOverflowException(length,width,height) \
5404   (((height) != 0) && ((length)/((size_t) height) != ((size_t) width)))
5405
5406   int
5407     depth,
5408     format;
5409
5410   size_t
5411     length;
5412
5413   XImage
5414     *matte_image,
5415     *ximage;
5416
5417   (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
5418   assert(display != (Display *) NULL);
5419   assert(resource_info != (XResourceInfo *) NULL);
5420   assert(window != (XWindowInfo *) NULL);
5421   assert(width != 0);
5422   assert(height != 0);
5423   if ((window->width == 0) || (window->height == 0))
5424     return(MagickFalse);
5425   /*
5426     Apply user transforms to the image.
5427   */
5428   (void) XCheckDefineCursor(display,window->id,window->busy_cursor);
5429   (void) XFlush(display);
5430   depth=(int) window->depth;
5431   if (window->destroy)
5432     window->image=DestroyImage(window->image);
5433   window->image=image;
5434   window->destroy=MagickFalse;
5435   if (window->image != (Image *) NULL)
5436     {
5437       if (window->crop_geometry != (char *) NULL)
5438         {
5439           Image
5440             *crop_image;
5441
5442           RectangleInfo
5443             crop_info;
5444
5445           /*
5446             Crop image.
5447           */
5448           window->image->page.x=0;
5449           window->image->page.y=0;
5450           (void) ParsePageGeometry(window->image,window->crop_geometry,
5451             &crop_info,&image->exception);
5452           crop_image=CropImage(window->image,&crop_info,&image->exception);
5453           if (crop_image != (Image *) NULL)
5454             {
5455               if (window->image != image)
5456                 window->image=DestroyImage(window->image);
5457               window->image=crop_image;
5458               window->destroy=MagickTrue;
5459             }
5460         }
5461       if ((width != (unsigned int) window->image->columns) ||
5462           (height != (unsigned int) window->image->rows))
5463         {
5464           Image
5465             *resize_image;
5466
5467           /*
5468             Resize image.
5469           */
5470           resize_image=NewImageList();
5471           if (window->pixel_info->colors != 0)
5472             resize_image=SampleImage(window->image,width,height,
5473               &image->exception);
5474           else
5475             resize_image=ThumbnailImage(window->image,width,height,
5476               &image->exception);
5477           if (resize_image != (Image *) NULL)
5478             {
5479               if (window->image != image)
5480                 window->image=DestroyImage(window->image);
5481               window->image=resize_image;
5482               window->destroy=MagickTrue;
5483             }
5484         }
5485       width=(unsigned int) window->image->columns;
5486       assert((size_t) width == window->image->columns);
5487       height=(unsigned int) window->image->rows;
5488       assert((size_t) height == window->image->rows);
5489     }
5490   /*
5491     Create X image.
5492   */
5493   ximage=(XImage *) NULL;
5494   format=(depth == 1) ? XYBitmap : ZPixmap;
5495 #if defined(MAGICKCORE_HAVE_SHARED_MEMORY)
5496   if (window->shared_memory != MagickFalse)
5497     {
5498       XShmSegmentInfo
5499         *segment_info;
5500
5501       segment_info=(XShmSegmentInfo *) window->segment_info;
5502       segment_info[1].shmid=(-1);
5503       segment_info[1].shmaddr=(char *) NULL;
5504       ximage=XShmCreateImage(display,window->visual,(unsigned int) depth,format,
5505         (char *) NULL,&segment_info[1],width,height);
5506       if (ximage == (XImage *) NULL)
5507         window->shared_memory=MagickFalse;
5508       length=(size_t) ximage->bytes_per_line*ximage->height;
5509       if (CheckOverflowException(length,ximage->bytes_per_line,ximage->height))
5510         window->shared_memory=MagickFalse;
5511       if (window->shared_memory != MagickFalse)
5512         segment_info[1].shmid=shmget(IPC_PRIVATE,length,IPC_CREAT | 0777);
5513       if (window->shared_memory != MagickFalse)
5514         segment_info[1].shmaddr=(char *) shmat(segment_info[1].shmid,0,0);
5515       if (segment_info[1].shmid < 0)
5516         window->shared_memory=MagickFalse;
5517       if (window->shared_memory != MagickFalse)
5518         (void) shmctl(segment_info[1].shmid,IPC_RMID,0);
5519       else
5520         {
5521           if (ximage != (XImage *) NULL)
5522             XDestroyImage(ximage);
5523           ximage=(XImage *) NULL;
5524           if (segment_info[1].shmaddr)
5525             {
5526               (void) shmdt(segment_info[1].shmaddr);
5527               segment_info[1].shmaddr=(char *) NULL;
5528             }
5529           if (segment_info[1].shmid >= 0)
5530             {
5531               (void) shmctl(segment_info[1].shmid,IPC_RMID,0);
5532               segment_info[1].shmid=(-1);
5533             }
5534         }
5535     }
5536 #endif
5537   /*
5538     Allocate X image pixel data.
5539   */
5540 #if defined(MAGICKCORE_HAVE_SHARED_MEMORY)
5541   if (window->shared_memory)
5542     {
5543       Status
5544         status;
5545
5546       XShmSegmentInfo
5547         *segment_info;
5548
5549       (void) XSync(display,MagickFalse);
5550       xerror_alert=MagickFalse;
5551       segment_info=(XShmSegmentInfo *) window->segment_info;
5552       ximage->data=segment_info[1].shmaddr;
5553       segment_info[1].readOnly=MagickFalse;
5554       status=XShmAttach(display,&segment_info[1]);
5555       if (status != False)
5556         (void) XSync(display,MagickFalse);
5557       if ((status == False) || (xerror_alert != MagickFalse))
5558         {
5559           window->shared_memory=MagickFalse;
5560           if (status != False)
5561             XShmDetach(display,&segment_info[1]);
5562           if (ximage != (XImage *) NULL)
5563             {
5564               ximage->data=NULL;
5565               XDestroyImage(ximage);
5566               ximage=(XImage *) NULL;
5567             }
5568           if (segment_info[1].shmid >= 0)
5569             {
5570               if (segment_info[1].shmaddr != NULL)
5571                 (void) shmdt(segment_info[1].shmaddr);
5572               (void) shmctl(segment_info[1].shmid,IPC_RMID,0);
5573               segment_info[1].shmid=(-1);
5574               segment_info[1].shmaddr=(char *) NULL;
5575             }
5576         }
5577     }
5578 #endif
5579   if (window->shared_memory == MagickFalse)
5580     ximage=XCreateImage(display,window->visual,(unsigned int) depth,format,0,
5581       (char *) NULL,width,height,XBitmapPad(display),0);
5582   if (ximage == (XImage *) NULL)
5583     {
5584       /*
5585         Unable to create X image.
5586       */
5587       (void) XCheckDefineCursor(display,window->id,window->cursor);
5588       return(MagickFalse);
5589     }
5590   length=(size_t) ximage->bytes_per_line*ximage->height;
5591   if (IsEventLogging())
5592     {
5593       (void) LogMagickEvent(X11Event,GetMagickModule(),"XImage:");
5594       (void) LogMagickEvent(X11Event,GetMagickModule(),"  width, height: %dx%d",
5595         ximage->width,ximage->height);
5596       (void) LogMagickEvent(X11Event,GetMagickModule(),"  format: %d",
5597         ximage->format);
5598       (void) LogMagickEvent(X11Event,GetMagickModule(),"  byte order: %d",
5599         ximage->byte_order);
5600       (void) LogMagickEvent(X11Event,GetMagickModule(),
5601         "  bitmap unit, bit order, pad: %d %d %d",ximage->bitmap_unit,
5602         ximage->bitmap_bit_order,ximage->bitmap_pad);
5603       (void) LogMagickEvent(X11Event,GetMagickModule(),"  depth: %d",
5604         ximage->depth);
5605       (void) LogMagickEvent(X11Event,GetMagickModule(),"  bytes per line: %d",
5606         ximage->bytes_per_line);
5607       (void) LogMagickEvent(X11Event,GetMagickModule(),"  bits per pixel: %d",
5608         ximage->bits_per_pixel);
5609       (void) LogMagickEvent(X11Event,GetMagickModule(),
5610         "  red, green, blue masks: 0x%lx 0x%lx 0x%lx",ximage->red_mask,
5611         ximage->green_mask,ximage->blue_mask);
5612     }
5613   if (window->shared_memory == MagickFalse)
5614     {
5615       if (ximage->format != XYBitmap)
5616         ximage->data=(char *) AcquireQuantumMemory((size_t)
5617           ximage->bytes_per_line,(size_t) ximage->height);
5618       else
5619         ximage->data=(char *) AcquireQuantumMemory((size_t)
5620           ximage->bytes_per_line*ximage->depth,(size_t) ximage->height);
5621     }
5622   if (ximage->data == (char *) NULL)
5623     {
5624       /*
5625         Unable to allocate pixel data.
5626       */
5627       XDestroyImage(ximage);
5628       ximage=(XImage *) NULL;
5629       (void) XCheckDefineCursor(display,window->id,window->cursor);
5630       return(MagickFalse);
5631     }
5632   if (window->ximage != (XImage *) NULL)
5633     {
5634       /*
5635         Destroy previous X image.
5636       */
5637       length=(size_t) window->ximage->bytes_per_line*window->ximage->height;
5638 #if defined(MAGICKCORE_HAVE_SHARED_MEMORY)
5639       if (window->segment_info != (XShmSegmentInfo *) NULL)
5640         {
5641           XShmSegmentInfo
5642             *segment_info;
5643
5644           segment_info=(XShmSegmentInfo *) window->segment_info;
5645           if (segment_info[0].shmid >= 0)
5646             {
5647               (void) XSync(display,MagickFalse);
5648               (void) XShmDetach(display,&segment_info[0]);
5649               (void) XSync(display,MagickFalse);
5650               if (segment_info[0].shmaddr != (char *) NULL)
5651                 (void) shmdt(segment_info[0].shmaddr);
5652               (void) shmctl(segment_info[0].shmid,IPC_RMID,0);
5653               segment_info[0].shmid=(-1);
5654               segment_info[0].shmaddr=(char *) NULL;
5655               window->ximage->data=(char *) NULL;
5656           }
5657         }
5658 #endif
5659       if (window->ximage->data != (char *) NULL)
5660         free(window->ximage->data);
5661       window->ximage->data=(char *) NULL;
5662       XDestroyImage(window->ximage);
5663       window->ximage=(XImage *) NULL;
5664     }
5665 #if defined(MAGICKCORE_HAVE_SHARED_MEMORY)
5666   if (window->segment_info != (XShmSegmentInfo *) NULL)
5667     {
5668       XShmSegmentInfo
5669         *segment_info;
5670
5671       segment_info=(XShmSegmentInfo *) window->segment_info;
5672       segment_info[0]=segment_info[1];
5673     }
5674 #endif
5675   window->ximage=ximage;
5676   matte_image=(XImage *) NULL;
5677   if ((window->shape != MagickFalse) && (window->image != (Image *) NULL))
5678     if ((window->image->matte != MagickFalse) &&
5679         ((int) width <= XDisplayWidth(display,window->screen)) &&
5680         ((int) height <= XDisplayHeight(display,window->screen)))
5681       {
5682         /*
5683           Create matte image.
5684         */
5685         matte_image=XCreateImage(display,window->visual,1,XYBitmap,0,
5686           (char *) NULL,width,height,XBitmapPad(display),0);
5687         if (IsEventLogging())
5688           {
5689             (void) LogMagickEvent(X11Event,GetMagickModule(),"Matte Image:");
5690             (void) LogMagickEvent(X11Event,GetMagickModule(),
5691               "  width, height: %dx%d",matte_image->width,matte_image->height);
5692           }
5693         if (matte_image != (XImage *) NULL)
5694           {
5695             /*
5696               Allocate matte image pixel data.
5697             */
5698             matte_image->data=(char *) AcquireQuantumMemory((size_t)
5699               matte_image->bytes_per_line*matte_image->depth,
5700               (size_t) matte_image->height);
5701             if (matte_image->data == (char *) NULL)
5702               {
5703                 XDestroyImage(matte_image);
5704                 matte_image=(XImage *) NULL;
5705               }
5706           }
5707       }
5708   if (window->matte_image != (XImage *) NULL)
5709     {
5710       /*
5711         Free matte image.
5712       */
5713       if (window->matte_image->data != (char *) NULL)
5714         free(window->matte_image->data);
5715       window->matte_image->data=(char *) NULL;
5716       XDestroyImage(window->matte_image);
5717       window->matte_image=(XImage *) NULL;
5718     }
5719   window->matte_image=matte_image;
5720   if (window->matte_pixmap != (Pixmap) NULL)
5721     {
5722       (void) XFreePixmap(display,window->matte_pixmap);
5723       window->matte_pixmap=(Pixmap) NULL;
5724 #if defined(MAGICKCORE_HAVE_SHAPE)
5725       if (window->shape != MagickFalse)
5726         XShapeCombineMask(display,window->id,ShapeBounding,0,0,None,ShapeSet);
5727 #endif
5728     }
5729   window->stasis=MagickFalse;
5730   /*
5731     Convert pixels to X image data.
5732   */
5733   if (window->image != (Image *) NULL)
5734     {
5735       if ((ximage->byte_order == LSBFirst) || ((ximage->format == XYBitmap) &&
5736           (ximage->bitmap_bit_order == LSBFirst)))
5737         XMakeImageLSBFirst(resource_info,window,window->image,ximage,
5738           matte_image);
5739       else
5740         XMakeImageMSBFirst(resource_info,window,window->image,ximage,
5741           matte_image);
5742     }
5743   if (window->matte_image != (XImage *) NULL)
5744     {
5745       /*
5746         Create matte pixmap.
5747       */
5748       window->matte_pixmap=XCreatePixmap(display,window->id,width,height,1);
5749       if (window->matte_pixmap != (Pixmap) NULL)
5750         {
5751           GC
5752             graphics_context;
5753
5754           XGCValues
5755             context_values;
5756
5757           /*
5758             Copy matte image to matte pixmap.
5759           */
5760           context_values.background=1;
5761           context_values.foreground=0;
5762           graphics_context=XCreateGC(display,window->matte_pixmap,
5763             (size_t) (GCBackground | GCForeground),&context_values);
5764           (void) XPutImage(display,window->matte_pixmap,graphics_context,
5765             window->matte_image,0,0,0,0,width,height);
5766           (void) XFreeGC(display,graphics_context);
5767 #if defined(MAGICKCORE_HAVE_SHAPE)
5768           if (window->shape != MagickFalse)
5769             XShapeCombineMask(display,window->id,ShapeBounding,0,0,
5770               window->matte_pixmap,ShapeSet);
5771 #endif
5772         }
5773       }
5774   (void) XMakePixmap(display,resource_info,window);
5775   /*
5776     Restore cursor.
5777   */
5778   (void) XCheckDefineCursor(display,window->id,window->cursor);
5779   return(MagickTrue);
5780 }
5781 \f
5782 /*
5783 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5784 %                                                                             %
5785 %                                                                             %
5786 %                                                                             %
5787 +   X M a k e I m a g e L S B F i r s t                                       %
5788 %                                                                             %
5789 %                                                                             %
5790 %                                                                             %
5791 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5792 %
5793 %  XMakeImageLSBFirst() initializes the pixel data of an X11 Image. The X image
5794 %  pixels are copied in least-significant bit and byte first order.  The
5795 %  server's scanline pad is respected.  Rather than using one or two general
5796 %  cases, many special cases are found here to help speed up the image
5797 %  conversion.
5798 %
5799 %  The format of the XMakeImageLSBFirst method is:
5800 %
5801 %      void XMakeImageLSBFirst(Display *display,XWindows *windows)
5802 %
5803 %  A description of each parameter follows:
5804 %
5805 %    o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
5806 %
5807 %    o window: Specifies a pointer to a XWindowInfo structure.
5808 %
5809 %    o image: the image.
5810 %
5811 %    o ximage: Specifies a pointer to a XImage structure;  returned from
5812 %      XCreateImage.
5813 %
5814 %    o matte_image: Specifies a pointer to a XImage structure;  returned from
5815 %      XCreateImage.
5816 %
5817 */
5818 static void XMakeImageLSBFirst(const XResourceInfo *resource_info,
5819   const XWindowInfo *window,Image *image,XImage *ximage,XImage *matte_image)
5820 {
5821   CacheView
5822     *canvas_view;
5823
5824   Image
5825     *canvas;
5826
5827   int
5828     y;
5829
5830   register const IndexPacket
5831     *indexes;
5832
5833   register const PixelPacket
5834     *p;
5835
5836   register int
5837     x;
5838
5839   register unsigned char
5840     *q;
5841
5842   unsigned char
5843     bit,
5844     byte;
5845
5846   unsigned int
5847     scanline_pad;
5848
5849   unsigned long
5850     pixel,
5851     *pixels;
5852
5853   XStandardColormap
5854     *map_info;
5855
5856   assert(resource_info != (XResourceInfo *) NULL);
5857   assert(window != (XWindowInfo *) NULL);
5858   assert(image != (Image *) NULL);
5859   if (image->debug != MagickFalse)
5860     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
5861   canvas=image;
5862   if ((window->immutable == MagickFalse) &&
5863       (image->storage_class == DirectClass) && (image->matte != MagickFalse))
5864     {
5865       char
5866         size[MaxTextExtent];
5867
5868       Image
5869         *pattern;
5870
5871       ImageInfo
5872         *image_info;
5873
5874       image_info=AcquireImageInfo();
5875       (void) CopyMagickString(image_info->filename,
5876         resource_info->image_info->texture != (char *) NULL ?
5877         resource_info->image_info->texture : "pattern:checkerboard",
5878         MaxTextExtent);
5879       (void) FormatMagickString(size,MaxTextExtent,"%.20gx%.20g",(double)
5880         image->columns,(double) image->rows);
5881       image_info->size=ConstantString(size);
5882       pattern=ReadImage(image_info,&image->exception);
5883       image_info=DestroyImageInfo(image_info);
5884       if (pattern != (Image *) NULL)
5885         {
5886           canvas=CloneImage(image,0,0,MagickTrue,&image->exception);
5887           if (canvas != (Image *) NULL)
5888             (void) CompositeImage(canvas,DstOverCompositeOp,pattern,0,0);
5889           pattern=DestroyImage(pattern);
5890         }
5891     }
5892   scanline_pad=(unsigned int) (ximage->bytes_per_line-((ximage->width*
5893     ximage->bits_per_pixel) >> 3));
5894   map_info=window->map_info;
5895   pixels=window->pixel_info->pixels;
5896   q=(unsigned char *) ximage->data;
5897   x=0;
5898   canvas_view=AcquireCacheView(canvas);
5899   if (ximage->format == XYBitmap)
5900     {
5901       register unsigned short
5902         polarity;
5903
5904       unsigned char
5905         background,
5906         foreground;
5907
5908       /*
5909         Convert canvas to big-endian bitmap.
5910       */
5911       background=(unsigned char)
5912         (XPixelIntensity(&window->pixel_info->foreground_color) <
5913          XPixelIntensity(&window->pixel_info->background_color) ? 0x80 : 0x00);
5914       foreground=(unsigned char)
5915         (XPixelIntensity(&window->pixel_info->background_color) <
5916          XPixelIntensity(&window->pixel_info->foreground_color) ? 0x80 : 0x00);
5917       polarity=(unsigned short) ((PixelIntensityToQuantum(
5918         &canvas->colormap[0])) < ((Quantum) QuantumRange/2) ? 1 : 0);
5919       if (canvas->colors == 2)
5920         polarity=PixelIntensity(&canvas->colormap[0]) <
5921           PixelIntensity(&canvas->colormap[1]);
5922       for (y=0; y < (int) canvas->rows; y++)
5923       {
5924         p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,canvas->columns,1,
5925           &canvas->exception);
5926         if (p == (const PixelPacket *) NULL)
5927           break;
5928         indexes=GetCacheViewVirtualIndexQueue(canvas_view);
5929         bit=0;
5930         byte=0;
5931         for (x=0; x < (int) canvas->columns; x++)
5932         {
5933           byte>>=1;
5934           if (indexes[x] == (IndexPacket) polarity)
5935             byte|=foreground;
5936           else
5937             byte|=background;
5938           bit++;
5939           if (bit == 8)
5940             {
5941               *q++=byte;
5942               bit=0;
5943               byte=0;
5944             }
5945         }
5946         if (bit != 0)
5947           *q=byte >> (8-bit);
5948         q+=scanline_pad;
5949       }
5950     }
5951   else
5952     if (window->pixel_info->colors != 0)
5953       switch (ximage->bits_per_pixel)
5954       {
5955         case 2:
5956         {
5957           register unsigned int
5958             nibble;
5959
5960           /*
5961             Convert to 2 bit color-mapped X canvas.
5962           */
5963           for (y=0; y < (int) canvas->rows; y++)
5964           {
5965             p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
5966               canvas->columns,1,&canvas->exception);
5967             if (p == (const PixelPacket *) NULL)
5968               break;
5969             indexes=GetCacheViewVirtualIndexQueue(canvas_view);
5970             nibble=0;
5971             for (x=0; x < (int) canvas->columns; x++)
5972             {
5973               pixel=pixels[(ssize_t) indexes[x]] & 0x0f;
5974               switch (nibble)
5975               {
5976                 case 0:
5977                 {
5978                   *q=(unsigned char) pixel;
5979                   nibble++;
5980                   break;
5981                 }
5982                 case 1:
5983                 {
5984                   *q|=(unsigned char) (pixel << 2);
5985                   nibble++;
5986                   break;
5987                 }
5988                 case 2:
5989                 {
5990                   *q|=(unsigned char) (pixel << 4);
5991                   nibble++;
5992                   break;
5993                 }
5994                 case 3:
5995                 {
5996                   *q|=(unsigned char) (pixel << 6);
5997                   q++;
5998                   nibble=0;
5999                   break;
6000                 }
6001               }
6002             }
6003             q+=scanline_pad;
6004           }
6005           break;
6006         }
6007         case 4:
6008         {
6009           register unsigned int
6010             nibble;
6011
6012           /*
6013             Convert to 4 bit color-mapped X canvas.
6014           */
6015           for (y=0; y < (int) canvas->rows; y++)
6016           {
6017             p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
6018               canvas->columns,1,&canvas->exception);
6019             if (p == (const PixelPacket *) NULL)
6020               break;
6021             indexes=GetCacheViewVirtualIndexQueue(canvas_view);
6022             nibble=0;
6023             for (x=0; x < (int) canvas->columns; x++)
6024             {
6025               pixel=pixels[(ssize_t) indexes[x]] & 0xf;
6026               switch (nibble)
6027               {
6028                 case 0:
6029                 {
6030                   *q=(unsigned char) pixel;
6031                   nibble++;
6032                   break;
6033                 }
6034                 case 1:
6035                 {
6036                   *q|=(unsigned char) (pixel << 4);
6037                   q++;
6038                   nibble=0;
6039                   break;
6040                 }
6041               }
6042             }
6043             q+=scanline_pad;
6044           }
6045           break;
6046         }
6047         case 6:
6048         case 8:
6049         {
6050           /*
6051             Convert to 8 bit color-mapped X canvas.
6052           */
6053           if (resource_info->color_recovery &&
6054               resource_info->quantize_info->dither)
6055             {
6056               XDitherImage(canvas,ximage);
6057               break;
6058             }
6059           for (y=0; y < (int) canvas->rows; y++)
6060           {
6061             p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
6062               canvas->columns,1,&canvas->exception);
6063             if (p == (const PixelPacket *) NULL)
6064               break;
6065             indexes=GetCacheViewVirtualIndexQueue(canvas_view);
6066             for (x=0; x < (int) canvas->columns; x++)
6067             {
6068               pixel=pixels[(ssize_t) indexes[x]];
6069               *q++=(unsigned char) pixel;
6070             }
6071             q+=scanline_pad;
6072           }
6073           break;
6074         }
6075         default:
6076         {
6077           register int
6078             k;
6079
6080           register unsigned int
6081             bytes_per_pixel;
6082
6083           unsigned char
6084             channel[sizeof(size_t)];
6085
6086           /*
6087             Convert to multi-byte color-mapped X canvas.
6088           */
6089           bytes_per_pixel=(unsigned int) (ximage->bits_per_pixel >> 3);
6090           for (y=0; y < (int) canvas->rows; y++)
6091           {
6092             p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
6093               canvas->columns,1,&canvas->exception);
6094             if (p == (const PixelPacket *) NULL)
6095               break;
6096             indexes=GetCacheViewVirtualIndexQueue(canvas_view);
6097             for (x=0; x < (int) canvas->columns; x++)
6098             {
6099               pixel=pixels[(ssize_t) indexes[x]];
6100               for (k=0; k < (int) bytes_per_pixel; k++)
6101               {
6102                 channel[k]=(unsigned char) pixel;
6103                 pixel>>=8;
6104               }
6105               for (k=0; k < (int) bytes_per_pixel; k++)
6106                 *q++=channel[k];
6107             }
6108             q+=scanline_pad;
6109           }
6110           break;
6111         }
6112       }
6113     else
6114       switch (ximage->bits_per_pixel)
6115       {
6116         case 2:
6117         {
6118           register unsigned int
6119             nibble;
6120
6121           /*
6122             Convert to contiguous 2 bit continuous-tone X canvas.
6123           */
6124           for (y=0; y < (int) canvas->rows; y++)
6125           {
6126             nibble=0;
6127             p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
6128               canvas->columns,1,&canvas->exception);
6129             if (p == (const PixelPacket *) NULL)
6130               break;
6131             for (x=0; x < (int) canvas->columns; x++)
6132             {
6133               pixel=XGammaPixel(map_info,p);
6134               pixel&=0xf;
6135               switch (nibble)
6136               {
6137                 case 0:
6138                 {
6139                   *q=(unsigned char) pixel;
6140                   nibble++;
6141                   break;
6142                 }
6143                 case 1:
6144                 {
6145                   *q|=(unsigned char) (pixel << 2);
6146                   nibble++;
6147                   break;
6148                 }
6149                 case 2:
6150                 {
6151                   *q|=(unsigned char) (pixel << 4);
6152                   nibble++;
6153                   break;
6154                 }
6155                 case 3:
6156                 {
6157                   *q|=(unsigned char) (pixel << 6);
6158                   q++;
6159                   nibble=0;
6160                   break;
6161                 }
6162               }
6163               p++;
6164             }
6165             q+=scanline_pad;
6166           }
6167           break;
6168         }
6169         case 4:
6170         {
6171           register unsigned int
6172             nibble;
6173
6174           /*
6175             Convert to contiguous 4 bit continuous-tone X canvas.
6176           */
6177           for (y=0; y < (int) canvas->rows; y++)
6178           {
6179             p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
6180               canvas->columns,1,&canvas->exception);
6181             if (p == (const PixelPacket *) NULL)
6182               break;
6183             nibble=0;
6184             for (x=0; x < (int) canvas->columns; x++)
6185             {
6186               pixel=XGammaPixel(map_info,p);
6187               pixel&=0xf;
6188               switch (nibble)
6189               {
6190                 case 0:
6191                 {
6192                   *q=(unsigned char) pixel;
6193                   nibble++;
6194                   break;
6195                 }
6196                 case 1:
6197                 {
6198                   *q|=(unsigned char) (pixel << 4);
6199                   q++;
6200                   nibble=0;
6201                   break;
6202                 }
6203               }
6204               p++;
6205             }
6206             q+=scanline_pad;
6207           }
6208           break;
6209         }
6210         case 6:
6211         case 8:
6212         {
6213           /*
6214             Convert to contiguous 8 bit continuous-tone X canvas.
6215           */
6216           if (resource_info->color_recovery &&
6217               resource_info->quantize_info->dither)
6218             {
6219               XDitherImage(canvas,ximage);
6220               break;
6221             }
6222           for (y=0; y < (int) canvas->rows; y++)
6223           {
6224             p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
6225               canvas->columns,1,&canvas->exception);
6226             if (p == (const PixelPacket *) NULL)
6227               break;
6228             for (x=0; x < (int) canvas->columns; x++)
6229             {
6230               pixel=XGammaPixel(map_info,p);
6231               *q++=(unsigned char) pixel;
6232               p++;
6233             }
6234             q+=scanline_pad;
6235           }
6236           break;
6237         }
6238         default:
6239         {
6240           if ((ximage->bits_per_pixel == 32) && (map_info->red_max == 255) &&
6241               (map_info->green_max == 255) && (map_info->blue_max == 255) &&
6242               (map_info->red_mult == 65536L) && (map_info->green_mult == 256) &&
6243               (map_info->blue_mult == 1))
6244             {
6245               /*
6246                 Convert to 32 bit continuous-tone X canvas.
6247               */
6248               for (y=0; y < (int) canvas->rows; y++)
6249               {
6250                 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
6251                   canvas->columns,1,&canvas->exception);
6252                 if (p == (const PixelPacket *) NULL)
6253                   break;
6254                 if ((red_gamma != 1.0) || (green_gamma != 1.0) ||
6255                     (blue_gamma != 1.0))
6256                   {
6257                     /*
6258                       Gamma correct canvas.
6259                     */
6260                     for (x=(int) canvas->columns-1; x >= 0; x--)
6261                     {
6262                       *q++=ScaleQuantumToChar(XBlueGamma(
6263                         GetBluePixelComponent(p)));
6264                       *q++=ScaleQuantumToChar(XGreenGamma(
6265                         GetGreenPixelComponent(p)));
6266                       *q++=ScaleQuantumToChar(XRedGamma(
6267                         GetRedPixelComponent(p)));
6268                       *q++=0;
6269                       p++;
6270                     }
6271                     continue;
6272                   }
6273                 for (x=(int) canvas->columns-1; x >= 0; x--)
6274                 {
6275                   *q++=ScaleQuantumToChar((Quantum) GetBluePixelComponent(p));
6276                   *q++=ScaleQuantumToChar((Quantum) GetGreenPixelComponent(p));
6277                   *q++=ScaleQuantumToChar((Quantum) GetRedPixelComponent(p));
6278                   *q++=0;
6279                   p++;
6280                 }
6281               }
6282             }
6283           else
6284             if ((ximage->bits_per_pixel == 32) && (map_info->red_max == 255) &&
6285                 (map_info->green_max == 255) && (map_info->blue_max == 255) &&
6286                 (map_info->red_mult == 1) && (map_info->green_mult == 256) &&
6287                 (map_info->blue_mult == 65536L))
6288               {
6289                 /*
6290                   Convert to 32 bit continuous-tone X canvas.
6291                 */
6292                 for (y=0; y < (int) canvas->rows; y++)
6293                 {
6294                   p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
6295                     canvas->columns,1,&canvas->exception);
6296                   if (p == (const PixelPacket *) NULL)
6297                     break;
6298                   if ((red_gamma != 1.0) || (green_gamma != 1.0) ||
6299                       (blue_gamma != 1.0))
6300                     {
6301                       /*
6302                         Gamma correct canvas.
6303                       */
6304                       for (x=(int) canvas->columns-1; x >= 0; x--)
6305                       {
6306                         *q++=ScaleQuantumToChar(XRedGamma(
6307                           GetRedPixelComponent(p)));
6308                         *q++=ScaleQuantumToChar(XGreenGamma(
6309                           GetGreenPixelComponent(p)));
6310                         *q++=ScaleQuantumToChar(XBlueGamma(
6311                           GetBluePixelComponent(p)));
6312                         *q++=0;
6313                         p++;
6314                       }
6315                       continue;
6316                     }
6317                   for (x=(int) canvas->columns-1; x >= 0; x--)
6318                   {
6319                     *q++=ScaleQuantumToChar((Quantum)
6320                       GetRedPixelComponent(p));
6321                     *q++=ScaleQuantumToChar((Quantum)
6322                       GetGreenPixelComponent(p));
6323                     *q++=ScaleQuantumToChar((Quantum)
6324                       GetBluePixelComponent(p));
6325                     *q++=0;
6326                     p++;
6327                   }
6328                 }
6329               }
6330             else
6331               {
6332                 register int
6333                   k;
6334
6335                 register unsigned int
6336                   bytes_per_pixel;
6337
6338                 unsigned char
6339                   channel[sizeof(size_t)];
6340
6341                 /*
6342                   Convert to multi-byte continuous-tone X canvas.
6343                 */
6344                 bytes_per_pixel=(unsigned int) (ximage->bits_per_pixel >> 3);
6345                 for (y=0; y < (int) canvas->rows; y++)
6346                 {
6347                   p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
6348                     canvas->columns,1,&canvas->exception);
6349                   if (p == (PixelPacket *) NULL)
6350                     break;
6351                   for (x=0; x < (int) canvas->columns; x++)
6352                   {
6353                     pixel=XGammaPixel(map_info,p);
6354                     for (k=0; k < (int) bytes_per_pixel; k++)
6355                     {
6356                       channel[k]=(unsigned char) pixel;
6357                       pixel>>=8;
6358                     }
6359                     for (k=0; k < (int) bytes_per_pixel; k++)
6360                       *q++=channel[k];
6361                     p++;
6362                   }
6363                   q+=scanline_pad;
6364                 }
6365               }
6366           break;
6367         }
6368       }
6369   if (matte_image != (XImage *) NULL)
6370     {
6371       /*
6372         Initialize matte canvas.
6373       */
6374       scanline_pad=(unsigned int) (matte_image->bytes_per_line-
6375         ((matte_image->width*matte_image->bits_per_pixel) >> 3));
6376       q=(unsigned char *) matte_image->data;
6377       for (y=0; y < (int) canvas->rows; y++)
6378       {
6379         p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,canvas->columns,1,
6380           &canvas->exception);
6381         if (p == (const PixelPacket *) NULL)
6382           break;
6383         bit=0;
6384         byte=0;
6385         for (x=(int) canvas->columns-1; x >= 0; x--)
6386         {
6387           byte>>=1;
6388           if (p->opacity > (QuantumRange/2))
6389             byte|=0x80;
6390           bit++;
6391           if (bit == 8)
6392             {
6393               *q++=byte;
6394               bit=0;
6395               byte=0;
6396             }
6397           p++;
6398         }
6399         if (bit != 0)
6400           *q=byte >> (8-bit);
6401         q+=scanline_pad;
6402       }
6403     }
6404   canvas_view=DestroyCacheView(canvas_view);
6405   if (canvas != image)
6406     canvas=DestroyImage(canvas);
6407 }
6408 \f
6409 /*
6410 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
6411 %                                                                             %
6412 %                                                                             %
6413 %                                                                             %
6414 +   X M a k e I m a g e M S B F i r s t                                       %
6415 %                                                                             %
6416 %                                                                             %
6417 %                                                                             %
6418 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
6419 %
6420 %  XMakeImageMSBFirst() initializes the pixel data of an X11 Image.  The X
6421 %  image pixels are copied in most-significant bit and byte first order.  The
6422 %  server's scanline pad is also respected. Rather than using one or two
6423 %  general cases, many special cases are found here to help speed up the image
6424 %  conversion.
6425 %
6426 %  The format of the XMakeImageMSBFirst method is:
6427 %
6428 %      XMakeImageMSBFirst(resource_info,window,image,ximage,matte_image)
6429 %
6430 %  A description of each parameter follows:
6431 %
6432 %    o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
6433 %
6434 %    o window: Specifies a pointer to a XWindowInfo structure.
6435 %
6436 %    o image: the image.
6437 %
6438 %    o ximage: Specifies a pointer to a XImage structure;  returned from
6439 %      XCreateImage.
6440 %
6441 %    o matte_image: Specifies a pointer to a XImage structure;  returned from
6442 %      XCreateImage.
6443 %
6444 */
6445 static void XMakeImageMSBFirst(const XResourceInfo *resource_info,
6446   const XWindowInfo *window,Image *image,XImage *ximage,XImage *matte_image)
6447 {
6448   CacheView
6449     *canvas_view;
6450
6451   Image
6452     *canvas;
6453
6454   int
6455     y;
6456
6457   register int
6458     x;
6459
6460   register const IndexPacket
6461     *indexes;
6462
6463   register const PixelPacket
6464     *p;
6465
6466   register unsigned char
6467     *q;
6468
6469   unsigned char
6470     bit,
6471     byte;
6472
6473   unsigned int
6474     scanline_pad;
6475
6476   unsigned long
6477     pixel,
6478     *pixels;
6479
6480   XStandardColormap
6481     *map_info;
6482
6483   assert(resource_info != (XResourceInfo *) NULL);
6484   assert(window != (XWindowInfo *) NULL);
6485   assert(image != (Image *) NULL);
6486   if (image->debug != MagickFalse)
6487     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
6488   canvas=image;
6489   if ((window->immutable != MagickFalse) &&
6490       (image->storage_class == DirectClass) && (image->matte != MagickFalse))
6491     {
6492       char
6493         size[MaxTextExtent];
6494
6495       Image
6496         *pattern;
6497
6498       ImageInfo
6499         *image_info;
6500
6501       image_info=AcquireImageInfo();
6502       (void) CopyMagickString(image_info->filename,
6503         resource_info->image_info->texture != (char *) NULL ?
6504         resource_info->image_info->texture : "pattern:checkerboard",
6505         MaxTextExtent);
6506       (void) FormatMagickString(size,MaxTextExtent,"%.20gx%.20g",(double)
6507         image->columns,(double) image->rows);
6508       image_info->size=ConstantString(size);
6509       pattern=ReadImage(image_info,&image->exception);
6510       image_info=DestroyImageInfo(image_info);
6511       if (pattern != (Image *) NULL)
6512         {
6513           canvas=CloneImage(image,0,0,MagickTrue,&image->exception);
6514           if (canvas != (Image *) NULL)
6515             (void) CompositeImage(canvas,DstOverCompositeOp,pattern,0,0);
6516           pattern=DestroyImage(pattern);
6517         }
6518     }
6519   scanline_pad=(unsigned int) (ximage->bytes_per_line-
6520     ((ximage->width*ximage->bits_per_pixel) >> 3));
6521   map_info=window->map_info;
6522   pixels=window->pixel_info->pixels;
6523   q=(unsigned char *) ximage->data;
6524   x=0;
6525   canvas_view=AcquireCacheView(canvas);
6526   if (ximage->format == XYBitmap)
6527     {
6528       register unsigned short
6529         polarity;
6530
6531       unsigned char
6532         background,
6533         foreground;
6534
6535       /*
6536         Convert canvas to big-endian bitmap.
6537       */
6538       background=(unsigned char)
6539         (XPixelIntensity(&window->pixel_info->foreground_color) <
6540          XPixelIntensity(&window->pixel_info->background_color) ?  0x01 : 0x00);
6541       foreground=(unsigned char)
6542         (XPixelIntensity(&window->pixel_info->background_color) <
6543          XPixelIntensity(&window->pixel_info->foreground_color) ?  0x01 : 0x00);
6544       polarity=(unsigned short) ((PixelIntensityToQuantum(
6545         &canvas->colormap[0])) < ((Quantum) QuantumRange/2) ? 1 : 0);
6546       if (canvas->colors == 2)
6547         polarity=PixelIntensity(&canvas->colormap[0]) <
6548           PixelIntensity(&canvas->colormap[1]);
6549       for (y=0; y < (int) canvas->rows; y++)
6550       {
6551         p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,canvas->columns,1,
6552           &canvas->exception);
6553         if (p == (const PixelPacket *) NULL)
6554           break;
6555         indexes=GetCacheViewVirtualIndexQueue(canvas_view);
6556         bit=0;
6557         byte=0;
6558         for (x=(int) canvas->columns-1; x >= 0; x--)
6559         {
6560           byte<<=1;
6561           if (indexes[x] == (IndexPacket) polarity)
6562             byte|=foreground;
6563           else
6564             byte|=background;
6565           bit++;
6566           if (bit == 8)
6567             {
6568               *q++=byte;
6569               bit=0;
6570               byte=0;
6571             }
6572         }
6573         if (bit != 0)
6574           *q=byte << (8-bit);
6575         q+=scanline_pad;
6576       }
6577     }
6578   else
6579     if (window->pixel_info->colors != 0)
6580       switch (ximage->bits_per_pixel)
6581       {
6582         case 2:
6583         {
6584           register unsigned int
6585             nibble;
6586
6587           /*
6588             Convert to 2 bit color-mapped X canvas.
6589           */
6590           for (y=0; y < (int) canvas->rows; y++)
6591           {
6592             p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
6593               canvas->columns,1,&canvas->exception);
6594             if (p == (const PixelPacket *) NULL)
6595               break;
6596             indexes=GetCacheViewVirtualIndexQueue(canvas_view);
6597             nibble=0;
6598             for (x=0; x < (int) canvas->columns; x++)
6599             {
6600               pixel=pixels[(ssize_t) indexes[x]] & 0xf;
6601               switch (nibble)
6602               {
6603                 case 0:
6604                 {
6605                   *q=(unsigned char) (pixel << 6);
6606                   nibble++;
6607                   break;
6608                 }
6609                 case 1:
6610                 {
6611                   *q|=(unsigned char) (pixel << 4);
6612                   nibble++;
6613                   break;
6614                 }
6615                 case 2:
6616                 {
6617                   *q|=(unsigned char) (pixel << 2);
6618                   nibble++;
6619                   break;
6620                 }
6621                 case 3:
6622                 {
6623                   *q|=(unsigned char) pixel;
6624                   q++;
6625                   nibble=0;
6626                   break;
6627                 }
6628               }
6629             }
6630             q+=scanline_pad;
6631           }
6632           break;
6633         }
6634         case 4:
6635         {
6636           register unsigned int
6637             nibble;
6638
6639           /*
6640             Convert to 4 bit color-mapped X canvas.
6641           */
6642           for (y=0; y < (int) canvas->rows; y++)
6643           {
6644             p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
6645               canvas->columns,1,&canvas->exception);
6646             if (p == (const PixelPacket *) NULL)
6647               break;
6648             indexes=GetCacheViewVirtualIndexQueue(canvas_view);
6649             nibble=0;
6650             for (x=0; x < (int) canvas->columns; x++)
6651             {
6652               pixel=pixels[(ssize_t) indexes[x]] & 0xf;
6653               switch (nibble)
6654               {
6655                 case 0:
6656                 {
6657                   *q=(unsigned char) (pixel << 4);
6658                   nibble++;
6659                   break;
6660                 }
6661                 case 1:
6662                 {
6663                   *q|=(unsigned char) pixel;
6664                   q++;
6665                   nibble=0;
6666                   break;
6667                 }
6668               }
6669             }
6670             q+=scanline_pad;
6671           }
6672           break;
6673         }
6674         case 6:
6675         case 8:
6676         {
6677           /*
6678             Convert to 8 bit color-mapped X canvas.
6679           */
6680           if (resource_info->color_recovery &&
6681               resource_info->quantize_info->dither)
6682             {
6683               XDitherImage(canvas,ximage);
6684               break;
6685             }
6686           for (y=0; y < (int) canvas->rows; y++)
6687           {
6688             p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
6689               canvas->columns,1,&canvas->exception);
6690             if (p == (const PixelPacket *) NULL)
6691               break;
6692             indexes=GetCacheViewVirtualIndexQueue(canvas_view);
6693             for (x=0; x < (int) canvas->columns; x++)
6694             {
6695               pixel=pixels[(ssize_t) indexes[x]];
6696               *q++=(unsigned char) pixel;
6697             }
6698             q+=scanline_pad;
6699           }
6700           break;
6701         }
6702         default:
6703         {
6704           register int
6705             k;
6706
6707           register unsigned int
6708             bytes_per_pixel;
6709
6710           unsigned char
6711             channel[sizeof(size_t)];
6712
6713           /*
6714             Convert to 8 bit color-mapped X canvas.
6715           */
6716           bytes_per_pixel=(unsigned int) (ximage->bits_per_pixel >> 3);
6717           for (y=0; y < (int) canvas->rows; y++)
6718           {
6719             p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
6720               canvas->columns,1,&canvas->exception);
6721             if (p == (const PixelPacket *) NULL)
6722               break;
6723             indexes=GetCacheViewVirtualIndexQueue(canvas_view);
6724             for (x=0; x < (int) canvas->columns; x++)
6725             {
6726               pixel=pixels[(ssize_t) indexes[x]];
6727               for (k=(int) bytes_per_pixel-1; k >= 0; k--)
6728               {
6729                 channel[k]=(unsigned char) pixel;
6730                 pixel>>=8;
6731               }
6732               for (k=0; k < (int) bytes_per_pixel; k++)
6733                 *q++=channel[k];
6734             }
6735             q+=scanline_pad;
6736           }
6737           break;
6738         }
6739       }
6740     else
6741       switch (ximage->bits_per_pixel)
6742       {
6743         case 2:
6744         {
6745           register unsigned int
6746             nibble;
6747
6748           /*
6749             Convert to 4 bit continuous-tone X canvas.
6750           */
6751           for (y=0; y < (int) canvas->rows; y++)
6752           {
6753             p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
6754               canvas->columns,1,&canvas->exception);
6755             if (p == (const PixelPacket *) NULL)
6756               break;
6757             nibble=0;
6758             for (x=(int) canvas->columns-1; x >= 0; x--)
6759             {
6760               pixel=XGammaPixel(map_info,p);
6761               pixel&=0xf;
6762               switch (nibble)
6763               {
6764                 case 0:
6765                 {
6766                   *q=(unsigned char) (pixel << 6);
6767                   nibble++;
6768                   break;
6769                 }
6770                 case 1:
6771                 {
6772                   *q|=(unsigned char) (pixel << 4);
6773                   nibble++;
6774                   break;
6775                 }
6776                 case 2:
6777                 {
6778                   *q|=(unsigned char) (pixel << 2);
6779                   nibble++;
6780                   break;
6781                 }
6782                 case 3:
6783                 {
6784                   *q|=(unsigned char) pixel;
6785                   q++;
6786                   nibble=0;
6787                   break;
6788                 }
6789               }
6790               p++;
6791             }
6792             q+=scanline_pad;
6793           }
6794           break;
6795         }
6796         case 4:
6797         {
6798           register unsigned int
6799             nibble;
6800
6801           /*
6802             Convert to 4 bit continuous-tone X canvas.
6803           */
6804           for (y=0; y < (int) canvas->rows; y++)
6805           {
6806             p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
6807               canvas->columns,1,&canvas->exception);
6808             if (p == (const PixelPacket *) NULL)
6809               break;
6810             nibble=0;
6811             for (x=(int) canvas->columns-1; x >= 0; x--)
6812             {
6813               pixel=XGammaPixel(map_info,p);
6814               pixel&=0xf;
6815               switch (nibble)
6816               {
6817                 case 0:
6818                 {
6819                   *q=(unsigned char) (pixel << 4);
6820                   nibble++;
6821                   break;
6822                 }
6823                 case 1:
6824                 {
6825                   *q|=(unsigned char) pixel;
6826                   q++;
6827                   nibble=0;
6828                   break;
6829                 }
6830               }
6831               p++;
6832             }
6833             q+=scanline_pad;
6834           }
6835           break;
6836         }
6837         case 6:
6838         case 8:
6839         {
6840           /*
6841             Convert to 8 bit continuous-tone X canvas.
6842           */
6843           if (resource_info->color_recovery &&
6844               resource_info->quantize_info->dither)
6845             {
6846               XDitherImage(canvas,ximage);
6847               break;
6848             }
6849           for (y=0; y < (int) canvas->rows; y++)
6850           {
6851             p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
6852               canvas->columns,1,&canvas->exception);
6853             if (p == (const PixelPacket *) NULL)
6854               break;
6855             for (x=(int) canvas->columns-1; x >= 0; x--)
6856             {
6857               pixel=XGammaPixel(map_info,p);
6858               *q++=(unsigned char) pixel;
6859               p++;
6860             }
6861             q+=scanline_pad;
6862           }
6863           break;
6864         }
6865         default:
6866         {
6867           if ((ximage->bits_per_pixel == 32) && (map_info->red_max == 255) &&
6868               (map_info->green_max == 255) && (map_info->blue_max == 255) &&
6869               (map_info->red_mult == 65536L) && (map_info->green_mult == 256) &&
6870               (map_info->blue_mult == 1))
6871             {
6872               /*
6873                 Convert to 32 bit continuous-tone X canvas.
6874               */
6875               for (y=0; y < (int) canvas->rows; y++)
6876               {
6877                 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
6878                   canvas->columns,1,&canvas->exception);
6879                 if (p == (const PixelPacket *) NULL)
6880                   break;
6881                 if ((red_gamma != 1.0) || (green_gamma != 1.0) ||
6882                     (blue_gamma != 1.0))
6883                   {
6884                     /*
6885                       Gamma correct canvas.
6886                     */
6887                     for (x=(int) canvas->columns-1; x >= 0; x--)
6888                     {
6889                       *q++=0;
6890                       *q++=ScaleQuantumToChar(XRedGamma(
6891                         GetRedPixelComponent(p)));
6892                       *q++=ScaleQuantumToChar(XGreenGamma(
6893                         GetGreenPixelComponent(p)));
6894                       *q++=ScaleQuantumToChar(XBlueGamma(
6895                         GetBluePixelComponent(p)));
6896                       p++;
6897                     }
6898                     continue;
6899                   }
6900                 for (x=(int) canvas->columns-1; x >= 0; x--)
6901                 {
6902                   *q++=0;
6903                   *q++=ScaleQuantumToChar((Quantum) GetRedPixelComponent(p));
6904                   *q++=ScaleQuantumToChar((Quantum) GetGreenPixelComponent(p));
6905                   *q++=ScaleQuantumToChar((Quantum) GetBluePixelComponent(p));
6906                   p++;
6907                 }
6908               }
6909             }
6910           else
6911             if ((ximage->bits_per_pixel == 32) && (map_info->red_max == 255) &&
6912                 (map_info->green_max == 255) && (map_info->blue_max == 255) &&
6913                 (map_info->red_mult == 1) && (map_info->green_mult == 256) &&
6914                 (map_info->blue_mult == 65536L))
6915               {
6916                 /*
6917                   Convert to 32 bit continuous-tone X canvas.
6918                 */
6919                 for (y=0; y < (int) canvas->rows; y++)
6920                 {
6921                   p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
6922                     canvas->columns,1,&canvas->exception);
6923                   if (p == (const PixelPacket *) NULL)
6924                     break;
6925                   if ((red_gamma != 1.0) || (green_gamma != 1.0) ||
6926                       (blue_gamma != 1.0))
6927                     {
6928                       /*
6929                         Gamma correct canvas.
6930                       */
6931                       for (x=(int) canvas->columns-1; x >= 0; x--)
6932                       {
6933                         *q++=0;
6934                         *q++=ScaleQuantumToChar(XBlueGamma(
6935                           GetBluePixelComponent(p)));
6936                         *q++=ScaleQuantumToChar(XGreenGamma(
6937                           GetGreenPixelComponent(p)));
6938                         *q++=ScaleQuantumToChar(XRedGamma(
6939                           GetRedPixelComponent(p)));
6940                         p++;
6941                       }
6942                       continue;
6943                     }
6944                   for (x=(int) canvas->columns-1; x >= 0; x--)
6945                   {
6946                     *q++=0;
6947                     *q++=ScaleQuantumToChar((Quantum)
6948                       GetBluePixelComponent(p));
6949                     *q++=ScaleQuantumToChar((Quantum)
6950                       GetGreenPixelComponent(p));
6951                     *q++=ScaleQuantumToChar((Quantum)
6952                       GetRedPixelComponent(p));
6953                     p++;
6954                   }
6955                 }
6956               }
6957             else
6958               {
6959                 register int
6960                   k;
6961
6962                 register unsigned int
6963                   bytes_per_pixel;
6964
6965                 unsigned char
6966                   channel[sizeof(size_t)];
6967
6968                 /*
6969                   Convert to multi-byte continuous-tone X canvas.
6970                 */
6971                 bytes_per_pixel=(unsigned int) (ximage->bits_per_pixel >> 3);
6972                 for (y=0; y < (int) canvas->rows; y++)
6973                 {
6974                   p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
6975                     canvas->columns,1,&canvas->exception);
6976                   if (p == (const PixelPacket *) NULL)
6977                     break;
6978                   for (x=(int) canvas->columns-1; x >= 0; x--)
6979                   {
6980                     pixel=XGammaPixel(map_info,p);
6981                     for (k=(int) bytes_per_pixel-1; k >= 0; k--)
6982                     {
6983                       channel[k]=(unsigned char) pixel;
6984                       pixel>>=8;
6985                     }
6986                     for (k=0; k < (int) bytes_per_pixel; k++)
6987                       *q++=channel[k];
6988                     p++;
6989                   }
6990                   q+=scanline_pad;
6991                 }
6992               }
6993           break;
6994         }
6995       }
6996   if (matte_image != (XImage *) NULL)
6997     {
6998       /*
6999         Initialize matte canvas.
7000       */
7001       scanline_pad=(unsigned int) (matte_image->bytes_per_line-
7002         ((matte_image->width*matte_image->bits_per_pixel) >> 3));
7003       q=(unsigned char *) matte_image->data;
7004       for (y=0; y < (int) canvas->rows; y++)
7005       {
7006         p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,canvas->columns,1,
7007           &canvas->exception);
7008         if (p == (const PixelPacket *) NULL)
7009           break;
7010         bit=0;
7011         byte=0;
7012         for (x=(int) canvas->columns-1; x >= 0; x--)
7013         {
7014           byte<<=1;
7015           if (p->opacity > (QuantumRange/2))
7016             byte|=0x01;
7017           bit++;
7018           if (bit == 8)
7019             {
7020               *q++=byte;
7021               bit=0;
7022               byte=0;
7023             }
7024           p++;
7025         }
7026         if (bit != 0)
7027           *q=byte << (8-bit);
7028         q+=scanline_pad;
7029       }
7030     }
7031   canvas_view=DestroyCacheView(canvas_view);
7032   if (canvas != image)
7033     canvas=DestroyImage(canvas);
7034 }
7035 \f
7036 /*
7037 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
7038 %                                                                             %
7039 %                                                                             %
7040 %                                                                             %
7041 %   X M a k e M a g n i f y I m a g e                                         %
7042 %                                                                             %
7043 %                                                                             %
7044 %                                                                             %
7045 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
7046 %
7047 %  XMakeMagnifyImage() magnifies a region of an X image and displays it.
7048 %
7049 %  The format of the XMakeMagnifyImage method is:
7050 %
7051 %      void XMakeMagnifyImage(display,windows)
7052 %
7053 %  A description of each parameter follows:
7054 %
7055 %    o display: Specifies a connection to an X server;  returned from
7056 %      XOpenDisplay.
7057 %
7058 %    o windows: Specifies a pointer to a XWindows structure.
7059 %
7060 */
7061 MagickExport void XMakeMagnifyImage(Display *display,XWindows *windows)
7062 {
7063   char
7064     tuple[MaxTextExtent];
7065
7066   int
7067     y;
7068
7069   MagickPixelPacket
7070     pixel;
7071
7072   register int
7073     x;
7074
7075   register ssize_t
7076     i;
7077
7078   register unsigned char
7079     *p,
7080     *q;
7081
7082   ssize_t
7083     n;
7084
7085   static unsigned int
7086     previous_magnify = 0;
7087
7088   static XWindowInfo
7089     magnify_window;
7090
7091   unsigned int
7092     height,
7093     j,
7094     k,
7095     l,
7096     magnify,
7097     scanline_pad,
7098     width;
7099
7100   XImage
7101     *ximage;
7102
7103   /*
7104     Check boundary conditions.
7105   */
7106   (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
7107   assert(display != (Display *) NULL);
7108   assert(windows != (XWindows *) NULL);
7109   magnify=1;
7110   for (n=1; n < (ssize_t) windows->magnify.data; n++)
7111     magnify<<=1;
7112   while ((magnify*windows->image.ximage->width) < windows->magnify.width)
7113     magnify<<=1;
7114   while ((magnify*windows->image.ximage->height) < windows->magnify.height)
7115     magnify<<=1;
7116   while (magnify > windows->magnify.width)
7117     magnify>>=1;
7118   while (magnify > windows->magnify.height)
7119     magnify>>=1;
7120   if (magnify != previous_magnify)
7121     {
7122       Status
7123         status;
7124
7125       XTextProperty
7126         window_name;
7127
7128       /*
7129         New magnify factor:  update magnify window name.
7130       */
7131       i=0;
7132       while ((1 << i) <= (int) magnify)
7133         i++;
7134       (void) FormatMagickString(windows->magnify.name,MaxTextExtent,
7135         "Magnify %.20gX",(double) i);
7136       status=XStringListToTextProperty(&windows->magnify.name,1,&window_name);
7137       if (status != False)
7138         {
7139           XSetWMName(display,windows->magnify.id,&window_name);
7140           XSetWMIconName(display,windows->magnify.id,&window_name);
7141           (void) XFree((void *) window_name.value);
7142         }
7143     }
7144   previous_magnify=magnify;
7145   ximage=windows->image.ximage;
7146   width=(unsigned int) windows->magnify.ximage->width;
7147   height=(unsigned int) windows->magnify.ximage->height;
7148   if ((windows->magnify.x < 0) ||
7149       (windows->magnify.x >= windows->image.ximage->width))
7150     windows->magnify.x=windows->image.ximage->width >> 1;
7151   x=windows->magnify.x-((width/magnify) >> 1);
7152   if (x < 0)
7153     x=0;
7154   else
7155     if (x > (int) (ximage->width-(width/magnify)))
7156       x=ximage->width-width/magnify;
7157   if ((windows->magnify.y < 0) ||
7158       (windows->magnify.y >= windows->image.ximage->height))
7159     windows->magnify.y=windows->image.ximage->height >> 1;
7160   y=windows->magnify.y-((height/magnify) >> 1);
7161   if (y < 0)
7162     y=0;
7163   else
7164     if (y > (int) (ximage->height-(height/magnify)))
7165       y=ximage->height-height/magnify;
7166   q=(unsigned char *) windows->magnify.ximage->data;
7167   scanline_pad=(unsigned int) (windows->magnify.ximage->bytes_per_line-
7168     ((width*windows->magnify.ximage->bits_per_pixel) >> 3));
7169   if (ximage->bits_per_pixel < 8)
7170     {
7171       register unsigned char
7172         background,
7173         byte,
7174         foreground,
7175         p_bit,
7176         q_bit;
7177
7178       register unsigned int
7179         plane;
7180
7181       XPixelInfo
7182         *pixel_info;
7183
7184       pixel_info=windows->magnify.pixel_info;
7185       switch (ximage->bitmap_bit_order)
7186       {
7187         case LSBFirst:
7188         {
7189           /*
7190             Magnify little-endian bitmap.
7191           */
7192           background=0x00;
7193           foreground=0x80;
7194           if (ximage->format == XYBitmap)
7195             {
7196               background=(unsigned char)
7197                 (XPixelIntensity(&pixel_info->foreground_color) <
7198                  XPixelIntensity(&pixel_info->background_color) ?  0x80 : 0x00);
7199               foreground=(unsigned char)
7200                 (XPixelIntensity(&pixel_info->background_color) <
7201                  XPixelIntensity(&pixel_info->foreground_color) ?  0x80 : 0x00);
7202               if (windows->magnify.depth > 1)
7203                 Swap(background,foreground);
7204             }
7205           for (i=0; i < (ssize_t) height; i+=magnify)
7206           {
7207             /*
7208               Propogate pixel magnify rows.
7209             */
7210             for (j=0; j < magnify; j++)
7211             {
7212               p=(unsigned char *) ximage->data+y*ximage->bytes_per_line+
7213                 ((x*ximage->bits_per_pixel) >> 3);
7214               p_bit=(unsigned char) (x*ximage->bits_per_pixel) & 0x07;
7215               q_bit=0;
7216               byte=0;
7217               for (k=0; k < width; k+=magnify)
7218               {
7219                 /*
7220                   Propogate pixel magnify columns.
7221                 */
7222                 for (l=0; l < magnify; l++)
7223                 {
7224                   /*
7225                     Propogate each bit plane.
7226                   */
7227                   for (plane=0; (int) plane < ximage->bits_per_pixel; plane++)
7228                   {
7229                     byte>>=1;
7230                     if (*p & (0x01 << (p_bit+plane)))
7231                       byte|=foreground;
7232                     else
7233                       byte|=background;
7234                     q_bit++;
7235                     if (q_bit == 8)
7236                       {
7237                         *q++=byte;
7238                         q_bit=0;
7239                         byte=0;
7240                       }
7241                   }
7242                 }
7243                 p_bit+=ximage->bits_per_pixel;
7244                 if (p_bit == 8)
7245                   {
7246                     p++;
7247                     p_bit=0;
7248                   }
7249                 if (q_bit != 0)
7250                   *q=byte >> (8-q_bit);
7251                 q+=scanline_pad;
7252               }
7253             }
7254             y++;
7255           }
7256           break;
7257         }
7258         case MSBFirst:
7259         default:
7260         {
7261           /*
7262             Magnify big-endian bitmap.
7263           */
7264           background=0x00;
7265           foreground=0x01;
7266           if (ximage->format == XYBitmap)
7267             {
7268               background=(unsigned char)
7269                 (XPixelIntensity(&pixel_info->foreground_color) <
7270                  XPixelIntensity(&pixel_info->background_color) ?  0x01 : 0x00);
7271               foreground=(unsigned char)
7272                 (XPixelIntensity(&pixel_info->background_color) <
7273                  XPixelIntensity(&pixel_info->foreground_color) ?  0x01 : 0x00);
7274               if (windows->magnify.depth > 1)
7275                 Swap(background,foreground);
7276             }
7277           for (i=0; i < (ssize_t) height; i+=magnify)
7278           {
7279             /*
7280               Propogate pixel magnify rows.
7281             */
7282             for (j=0; j < magnify; j++)
7283             {
7284               p=(unsigned char *) ximage->data+y*ximage->bytes_per_line+
7285                 ((x*ximage->bits_per_pixel) >> 3);
7286               p_bit=(unsigned char) (x*ximage->bits_per_pixel) & 0x07;
7287               q_bit=0;
7288               byte=0;
7289               for (k=0; k < width; k+=magnify)
7290               {
7291                 /*
7292                   Propogate pixel magnify columns.
7293                 */
7294                 for (l=0; l < magnify; l++)
7295                 {
7296                   /*
7297                     Propogate each bit plane.
7298                   */
7299                   for (plane=0; (int) plane < ximage->bits_per_pixel; plane++)
7300                   {
7301                     byte<<=1;
7302                     if (*p & (0x80 >> (p_bit+plane)))
7303                       byte|=foreground;
7304                     else
7305                       byte|=background;
7306                     q_bit++;
7307                     if (q_bit == 8)
7308                       {
7309                         *q++=byte;
7310                         q_bit=0;
7311                         byte=0;
7312                       }
7313                   }
7314                 }
7315                 p_bit+=ximage->bits_per_pixel;
7316                 if (p_bit == 8)
7317                   {
7318                     p++;
7319                     p_bit=0;
7320                   }
7321                 if (q_bit != 0)
7322                   *q=byte << (8-q_bit);
7323                 q+=scanline_pad;
7324               }
7325             }
7326             y++;
7327           }
7328           break;
7329         }
7330       }
7331     }
7332   else
7333     switch (ximage->bits_per_pixel)
7334     {
7335       case 6:
7336       case 8:
7337       {
7338         /*
7339           Magnify 8 bit X image.
7340         */
7341         for (i=0; i < (ssize_t) height; i+=magnify)
7342         {
7343           /*
7344             Propogate pixel magnify rows.
7345           */
7346           for (j=0; j < magnify; j++)
7347           {
7348             p=(unsigned char *) ximage->data+y*ximage->bytes_per_line+
7349               ((x*ximage->bits_per_pixel) >> 3);
7350             for (k=0; k < width; k+=magnify)
7351             {
7352               /*
7353                 Propogate pixel magnify columns.
7354               */
7355               for (l=0; l < magnify; l++)
7356                 *q++=(*p);
7357               p++;
7358             }
7359             q+=scanline_pad;
7360           }
7361           y++;
7362         }
7363         break;
7364       }
7365       default:
7366       {
7367         register unsigned int
7368           bytes_per_pixel,
7369           m;
7370
7371         /*
7372           Magnify multi-byte X image.
7373         */
7374         bytes_per_pixel=(unsigned int) ximage->bits_per_pixel >> 3;
7375         for (i=0; i < (ssize_t) height; i+=magnify)
7376         {
7377           /*
7378             Propogate pixel magnify rows.
7379           */
7380           for (j=0; j < magnify; j++)
7381           {
7382             p=(unsigned char *) ximage->data+y*ximage->bytes_per_line+
7383               ((x*ximage->bits_per_pixel) >> 3);
7384             for (k=0; k < width; k+=magnify)
7385             {
7386               /*
7387                 Propogate pixel magnify columns.
7388               */
7389               for (l=0; l < magnify; l++)
7390                 for (m=0; m < bytes_per_pixel; m++)
7391                   *q++=(*(p+m));
7392               p+=bytes_per_pixel;
7393             }
7394             q+=scanline_pad;
7395           }
7396           y++;
7397         }
7398         break;
7399       }
7400     }
7401   /*
7402     Copy X image to magnify pixmap.
7403   */
7404   x=windows->magnify.x-((width/magnify) >> 1);
7405   if (x < 0)
7406     x=(int) ((width >> 1)-windows->magnify.x*magnify);
7407   else
7408     if (x > (int) (ximage->width-(width/magnify)))
7409       x=(int) ((ximage->width-windows->magnify.x)*magnify-(width >> 1));
7410     else
7411       x=0;
7412   y=windows->magnify.y-((height/magnify) >> 1);
7413   if (y < 0)
7414     y=(int) ((height >> 1)-windows->magnify.y*magnify);
7415   else
7416     if (y > (int) (ximage->height-(height/magnify)))
7417       y=(int) ((ximage->height-windows->magnify.y)*magnify-(height >> 1));
7418     else
7419       y=0;
7420   if ((x != 0) || (y != 0))
7421     (void) XFillRectangle(display,windows->magnify.pixmap,
7422       windows->magnify.annotate_context,0,0,width,height);
7423   (void) XPutImage(display,windows->magnify.pixmap,
7424     windows->magnify.annotate_context,windows->magnify.ximage,0,0,x,y,width-x,
7425     height-y);
7426   if ((magnify > 1) && ((magnify <= (width >> 1)) &&
7427       (magnify <= (height >> 1))))
7428     {
7429       RectangleInfo
7430         highlight_info;
7431
7432       /*
7433         Highlight center pixel.
7434       */
7435       highlight_info.x=(ssize_t) windows->magnify.width >> 1;
7436       highlight_info.y=(ssize_t) windows->magnify.height >> 1;
7437       highlight_info.width=magnify;
7438       highlight_info.height=magnify;
7439       (void) XDrawRectangle(display,windows->magnify.pixmap,
7440         windows->magnify.highlight_context,(int) highlight_info.x,
7441         (int) highlight_info.y,(unsigned int) highlight_info.width-1,
7442         (unsigned int) highlight_info.height-1);
7443       if (magnify > 2)
7444         (void) XDrawRectangle(display,windows->magnify.pixmap,
7445           windows->magnify.annotate_context,(int) highlight_info.x+1,
7446           (int) highlight_info.y+1,(unsigned int) highlight_info.width-3,
7447           (unsigned int) highlight_info.height-3);
7448     }
7449   /*
7450     Show center pixel color.
7451   */
7452   (void) GetOneVirtualMagickPixel(windows->image.image,(ssize_t)
7453     windows->magnify.x,(ssize_t) windows->magnify.y,&pixel,
7454     &windows->image.image->exception);
7455   (void) FormatMagickString(tuple,MaxTextExtent,"%d,%d: ",
7456     windows->magnify.x,windows->magnify.y);
7457   (void) ConcatenateMagickString(tuple,"(",MaxTextExtent);
7458   ConcatenateColorComponent(&pixel,RedChannel,X11Compliance,tuple);
7459   (void) ConcatenateMagickString(tuple,",",MaxTextExtent);
7460   ConcatenateColorComponent(&pixel,GreenChannel,X11Compliance,tuple);
7461   (void) ConcatenateMagickString(tuple,",",MaxTextExtent);
7462   ConcatenateColorComponent(&pixel,BlueChannel,X11Compliance,tuple);
7463   if (pixel.colorspace == CMYKColorspace)
7464     {
7465       (void) ConcatenateMagickString(tuple,",",MaxTextExtent);
7466       ConcatenateColorComponent(&pixel,IndexChannel,X11Compliance,tuple);
7467     }
7468   if (pixel.matte != MagickFalse)
7469     {
7470       (void) ConcatenateMagickString(tuple,",",MaxTextExtent);
7471       ConcatenateColorComponent(&pixel,OpacityChannel,X11Compliance,tuple);
7472     }
7473   (void) ConcatenateMagickString(tuple,")",MaxTextExtent);
7474   height=(unsigned int) windows->magnify.font_info->ascent+
7475     windows->magnify.font_info->descent;
7476   x=windows->magnify.font_info->max_bounds.width >> 1;
7477   y=windows->magnify.font_info->ascent+(height >> 2);
7478   (void) XDrawImageString(display,windows->magnify.pixmap,
7479     windows->magnify.annotate_context,x,y,tuple,(int) strlen(tuple));
7480   GetColorTuple(&pixel,MagickTrue,tuple);
7481   y+=height;
7482   (void) XDrawImageString(display,windows->magnify.pixmap,
7483     windows->magnify.annotate_context,x,y,tuple,(int) strlen(tuple));
7484   (void) QueryMagickColorname(windows->image.image,&pixel,SVGCompliance,tuple,
7485      &windows->image.image->exception);
7486   y+=height;
7487   (void) XDrawImageString(display,windows->magnify.pixmap,
7488     windows->magnify.annotate_context,x,y,tuple,(int) strlen(tuple));
7489   /*
7490     Refresh magnify window.
7491   */
7492   magnify_window=windows->magnify;
7493   magnify_window.x=0;
7494   magnify_window.y=0;
7495   XRefreshWindow(display,&magnify_window,(XEvent *) NULL);
7496 }
7497 \f
7498 /*
7499 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
7500 %                                                                             %
7501 %                                                                             %
7502 %                                                                             %
7503 %   X M a k e P i x m a p                                                     %
7504 %                                                                             %
7505 %                                                                             %
7506 %                                                                             %
7507 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
7508 %
7509 %  XMakePixmap() creates an X11 pixmap.
7510 %
7511 %  The format of the XMakePixmap method is:
7512 %
7513 %      void XMakeStandardColormap(Display *display,XVisualInfo *visual_info,
7514 %        XResourceInfo *resource_info,Image *image,XStandardColormap *map_info,
7515 %        XPixelInfo *pixel)
7516 %
7517 %  A description of each parameter follows:
7518 %
7519 %    o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
7520 %
7521 %    o display: Specifies a connection to an X server; returned from
7522 %      XOpenDisplay.
7523 %
7524 %    o window: Specifies a pointer to a XWindowInfo structure.
7525 %
7526 */
7527 static MagickBooleanType XMakePixmap(Display *display,
7528   const XResourceInfo *resource_info,XWindowInfo *window)
7529 {
7530   unsigned int
7531     height,
7532     width;
7533
7534   (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
7535   assert(display != (Display *) NULL);
7536   assert(resource_info != (XResourceInfo *) NULL);
7537   assert(window != (XWindowInfo  *) NULL);
7538   if (window->pixmap != (Pixmap) NULL)
7539     {
7540       /*
7541         Destroy previous X pixmap.
7542       */
7543       (void) XFreePixmap(display,window->pixmap);
7544       window->pixmap=(Pixmap) NULL;
7545     }
7546   if (window->use_pixmap == MagickFalse)
7547     return(MagickFalse);
7548   if (window->ximage == (XImage *) NULL)
7549     return(MagickFalse);
7550   /*
7551     Display busy cursor.
7552   */
7553   (void) XCheckDefineCursor(display,window->id,window->busy_cursor);
7554   (void) XFlush(display);
7555   /*
7556     Create pixmap.
7557   */
7558   width=(unsigned int) window->ximage->width;
7559   height=(unsigned int) window->ximage->height;
7560   window->pixmap=XCreatePixmap(display,window->id,width,height,window->depth);
7561   if (window->pixmap == (Pixmap) NULL)
7562     {
7563       /*
7564         Unable to allocate pixmap.
7565       */
7566       (void) XCheckDefineCursor(display,window->id,window->cursor);
7567       return(MagickFalse);
7568     }
7569   /*
7570     Copy X image to pixmap.
7571   */
7572 #if defined(MAGICKCORE_HAVE_SHARED_MEMORY)
7573   if (window->shared_memory)
7574     (void) XShmPutImage(display,window->pixmap,window->annotate_context,
7575       window->ximage,0,0,0,0,width,height,MagickTrue);
7576 #endif
7577   if (window->shared_memory == MagickFalse)
7578     (void) XPutImage(display,window->pixmap,window->annotate_context,
7579       window->ximage,0,0,0,0,width,height);
7580   if (IsEventLogging())
7581     {
7582       (void) LogMagickEvent(X11Event,GetMagickModule(),"Pixmap:");
7583       (void) LogMagickEvent(X11Event,GetMagickModule(),"  width, height: %ux%u",
7584         width,height);
7585     }
7586   /*
7587     Restore cursor.
7588   */
7589   (void) XCheckDefineCursor(display,window->id,window->cursor);
7590   return(MagickTrue);
7591 }
7592 \f
7593 /*
7594 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
7595 %                                                                             %
7596 %                                                                             %
7597 %                                                                             %
7598 %   X M a k e S t a n d a r d C o l o r m a p                                 %
7599 %                                                                             %
7600 %                                                                             %
7601 %                                                                             %
7602 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
7603 %
7604 %  XMakeStandardColormap() creates an X11 Standard Colormap.
7605 %
7606 %  The format of the XMakeStandardColormap method is:
7607 %
7608 %      XMakeStandardColormap(display,visual_info,resource_info,image,
7609 %        map_info,pixel)
7610 %
7611 %  A description of each parameter follows:
7612 %
7613 %    o display: Specifies a connection to an X server; returned from
7614 %      XOpenDisplay.
7615 %
7616 %    o visual_info: Specifies a pointer to a X11 XVisualInfo structure;
7617 %      returned from XGetVisualInfo.
7618 %
7619 %    o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
7620 %
7621 %    o image: the image.
7622 %
7623 %    o map_info: If a Standard Colormap type is specified, this structure is
7624 %      initialized with info from the Standard Colormap.
7625 %
7626 %    o pixel: Specifies a pointer to a XPixelInfo structure.
7627 %
7628 */
7629
7630 #if defined(__cplusplus) || defined(c_plusplus)
7631 extern "C" {
7632 #endif
7633
7634 static inline MagickRealType DiversityPixelIntensity(
7635   const DiversityPacket *pixel)
7636 {
7637   MagickRealType
7638     intensity;
7639
7640   intensity=0.299*pixel->red+0.587*pixel->green+0.114*pixel->blue;
7641   return(intensity);
7642 }
7643
7644 static int IntensityCompare(const void *x,const void *y)
7645 {
7646   DiversityPacket
7647     *color_1,
7648     *color_2;
7649
7650   int
7651     diversity;
7652
7653   color_1=(DiversityPacket *) x;
7654   color_2=(DiversityPacket *) y;
7655   diversity=(int) (DiversityPixelIntensity(color_2)-
7656     DiversityPixelIntensity(color_1));
7657   return(diversity);
7658 }
7659
7660 static int PopularityCompare(const void *x,const void *y)
7661 {
7662   DiversityPacket
7663     *color_1,
7664     *color_2;
7665
7666   color_1=(DiversityPacket *) x;
7667   color_2=(DiversityPacket *) y;
7668   return((int) color_2->count-(int) color_1->count);
7669 }
7670
7671 #if defined(__cplusplus) || defined(c_plusplus)
7672 }
7673 #endif
7674
7675 static inline Quantum ScaleXToQuantum(const size_t x,
7676   const size_t scale)
7677 {
7678   return((Quantum) (((MagickRealType) QuantumRange*x)/scale+0.5));
7679 }
7680
7681 MagickExport void XMakeStandardColormap(Display *display,
7682   XVisualInfo *visual_info,XResourceInfo *resource_info,Image *image,
7683   XStandardColormap *map_info,XPixelInfo *pixel)
7684 {
7685   Colormap
7686     colormap;
7687
7688   ExceptionInfo
7689     *exception;
7690
7691   register IndexPacket
7692     *indexes;
7693
7694   register ssize_t
7695     i;
7696
7697   Status
7698     status;
7699
7700   size_t
7701     number_colors,
7702     retain_colors;
7703
7704   unsigned short
7705     gray_value;
7706
7707   XColor
7708     color,
7709     *colors,
7710     *p;
7711
7712   (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
7713   assert(display != (Display *) NULL);
7714   assert(visual_info != (XVisualInfo *) NULL);
7715   assert(map_info != (XStandardColormap *) NULL);
7716   assert(resource_info != (XResourceInfo *) NULL);
7717   assert(pixel != (XPixelInfo *) NULL);
7718   exception=(&image->exception);
7719   if (resource_info->map_type != (char *) NULL)
7720     {
7721       /*
7722         Standard Colormap is already defined (i.e. xstdcmap).
7723       */
7724       XGetPixelPacket(display,visual_info,map_info,resource_info,image,
7725         pixel);
7726       number_colors=(unsigned int) (map_info->base_pixel+
7727         (map_info->red_max+1)*(map_info->green_max+1)*(map_info->blue_max+1));
7728       if ((map_info->red_max*map_info->green_max*map_info->blue_max) != 0)
7729         if ((image->matte == MagickFalse) &&
7730             (resource_info->color_recovery == MagickFalse) &&
7731             resource_info->quantize_info->dither &&
7732             (number_colors < MaxColormapSize))
7733           {
7734             Image
7735               *affinity_image;
7736
7737             register PixelPacket
7738               *restrict q;
7739
7740             /*
7741               Improve image appearance with error diffusion.
7742             */
7743             affinity_image=AcquireImage((ImageInfo *) NULL);
7744             if (affinity_image == (Image *) NULL)
7745               ThrowXWindowFatalException(ResourceLimitFatalError,
7746                 "UnableToDitherImage",image->filename);
7747             affinity_image->columns=number_colors;
7748             affinity_image->rows=1;
7749             /*
7750               Initialize colormap image.
7751             */
7752             q=QueueAuthenticPixels(affinity_image,0,0,affinity_image->columns,
7753               1,exception);
7754             if (q != (PixelPacket *) NULL)
7755               {
7756                 for (i=0; i < (ssize_t) number_colors; i++)
7757                 {
7758                   q->red=(Quantum) 0;
7759                   if (map_info->red_max != 0)
7760                     q->red=ScaleXToQuantum((size_t) (i/
7761                       map_info->red_mult),map_info->red_max);
7762                   q->green=(Quantum) 0;
7763                   if (map_info->green_max != 0)
7764                     q->green=ScaleXToQuantum((size_t) ((i/
7765                       map_info->green_mult) % (map_info->green_max+1)),
7766                       map_info->green_max);
7767                   q->blue=(Quantum) 0;
7768                   if (map_info->blue_max != 0)
7769                     q->blue=ScaleXToQuantum((size_t) (i %
7770                       map_info->green_mult),map_info->blue_max);
7771                   q->opacity=(Quantum) TransparentOpacity;
7772                   q++;
7773                 }
7774                 (void) SyncAuthenticPixels(affinity_image,exception);
7775                 (void) RemapImage(resource_info->quantize_info,image,
7776                   affinity_image);
7777               }
7778             XGetPixelPacket(display,visual_info,map_info,resource_info,image,
7779               pixel);
7780             (void) SetImageStorageClass(image,DirectClass);
7781             affinity_image=DestroyImage(affinity_image);
7782           }
7783       if (IsEventLogging())
7784         {
7785           (void) LogMagickEvent(X11Event,GetMagickModule(),
7786             "Standard Colormap:");
7787           (void) LogMagickEvent(X11Event,GetMagickModule(),
7788             "  colormap id: 0x%lx",map_info->colormap);
7789           (void) LogMagickEvent(X11Event,GetMagickModule(),
7790             "  red, green, blue max: %lu %lu %lu",map_info->red_max,
7791             map_info->green_max,map_info->blue_max);
7792           (void) LogMagickEvent(X11Event,GetMagickModule(),
7793             "  red, green, blue mult: %lu %lu %lu",map_info->red_mult,
7794             map_info->green_mult,map_info->blue_mult);
7795         }
7796       return;
7797     }
7798   if ((visual_info->klass != DirectColor) &&
7799       (visual_info->klass != TrueColor))
7800     if ((image->storage_class == DirectClass) ||
7801         ((int) image->colors > visual_info->colormap_size))
7802       {
7803         QuantizeInfo
7804           quantize_info;
7805
7806         /*
7807           Image has more colors than the visual supports.
7808         */
7809         quantize_info=(*resource_info->quantize_info);
7810         quantize_info.number_colors=(size_t) visual_info->colormap_size;
7811         (void) QuantizeImage(&quantize_info,image);
7812       }
7813   /*
7814     Free previous and create new colormap.
7815   */
7816   (void) XFreeStandardColormap(display,visual_info,map_info,pixel);
7817   colormap=XDefaultColormap(display,visual_info->screen);
7818   if (visual_info->visual != XDefaultVisual(display,visual_info->screen))
7819     colormap=XCreateColormap(display,XRootWindow(display,visual_info->screen),
7820       visual_info->visual,visual_info->klass == DirectColor ?
7821       AllocAll : AllocNone);
7822   if (colormap == (Colormap) NULL)
7823     ThrowXWindowFatalException(ResourceLimitFatalError,"UnableToCreateColormap",
7824       image->filename);
7825   /*
7826     Initialize the map and pixel info structures.
7827   */
7828   XGetMapInfo(visual_info,colormap,map_info);
7829   XGetPixelPacket(display,visual_info,map_info,resource_info,image,pixel);
7830   /*
7831     Allocating colors in server colormap is based on visual class.
7832   */
7833   switch (visual_info->klass)
7834   {
7835     case StaticGray:
7836     case StaticColor:
7837     {
7838       /*
7839         Define Standard Colormap for StaticGray or StaticColor visual.
7840       */
7841       number_colors=image->colors;
7842       colors=(XColor *) AcquireQuantumMemory((size_t)
7843         visual_info->colormap_size,sizeof(*colors));
7844       if (colors == (XColor *) NULL)
7845         ThrowXWindowFatalException(ResourceLimitFatalError,
7846           "UnableToCreateColormap",image->filename);
7847       p=colors;
7848       color.flags=(char) (DoRed | DoGreen | DoBlue);
7849       for (i=0; i < (ssize_t) image->colors; i++)
7850       {
7851         color.red=ScaleQuantumToShort(XRedGamma(image->colormap[i].red));
7852         color.green=ScaleQuantumToShort(XGreenGamma(image->colormap[i].green));
7853         color.blue=ScaleQuantumToShort(XBlueGamma(image->colormap[i].blue));
7854         if (visual_info->klass != StaticColor)
7855           {
7856             gray_value=(unsigned short) XPixelIntensity(&color);
7857             color.red=gray_value;
7858             color.green=gray_value;
7859             color.blue=gray_value;
7860           }
7861         status=XAllocColor(display,colormap,&color);
7862         if (status == False)
7863           {
7864             colormap=XCopyColormapAndFree(display,colormap);
7865             (void) XAllocColor(display,colormap,&color);
7866           }
7867         pixel->pixels[i]=color.pixel;
7868         *p++=color;
7869       }
7870       break;
7871     }
7872     case GrayScale:
7873     case PseudoColor:
7874     {
7875       unsigned int
7876         colormap_type;
7877
7878       /*
7879         Define Standard Colormap for GrayScale or PseudoColor visual.
7880       */
7881       number_colors=image->colors;
7882       colors=(XColor *) AcquireQuantumMemory((size_t)
7883         visual_info->colormap_size,sizeof(*colors));
7884       if (colors == (XColor *) NULL)
7885         ThrowXWindowFatalException(ResourceLimitFatalError,
7886           "UnableToCreateColormap",image->filename);
7887       /*
7888         Preallocate our GUI colors.
7889       */
7890       (void) XAllocColor(display,colormap,&pixel->foreground_color);
7891       (void) XAllocColor(display,colormap,&pixel->background_color);
7892       (void) XAllocColor(display,colormap,&pixel->border_color);
7893       (void) XAllocColor(display,colormap,&pixel->matte_color);
7894       (void) XAllocColor(display,colormap,&pixel->highlight_color);
7895       (void) XAllocColor(display,colormap,&pixel->shadow_color);
7896       (void) XAllocColor(display,colormap,&pixel->depth_color);
7897       (void) XAllocColor(display,colormap,&pixel->trough_color);
7898       for (i=0; i < MaxNumberPens; i++)
7899         (void) XAllocColor(display,colormap,&pixel->pen_colors[i]);
7900       /*
7901         Determine if image colors will "fit" into X server colormap.
7902       */
7903       colormap_type=resource_info->colormap;
7904       status=XAllocColorCells(display,colormap,MagickFalse,(unsigned long *)
7905         NULL,0,pixel->pixels,(unsigned int) image->colors);
7906       if (status != False)
7907         colormap_type=PrivateColormap;
7908       if (colormap_type == SharedColormap)
7909         {
7910           CacheView
7911             *image_view;
7912
7913           DiversityPacket
7914             *diversity;
7915
7916           int
7917             y;
7918
7919           register int
7920             x;
7921
7922           unsigned short
7923             index;
7924
7925           XColor
7926             *server_colors;
7927
7928           /*
7929             Define Standard colormap for shared GrayScale or PseudoColor visual.
7930           */
7931           diversity=(DiversityPacket *) AcquireQuantumMemory(image->colors,
7932             sizeof(*diversity));
7933           if (diversity == (DiversityPacket *) NULL)
7934             ThrowXWindowFatalException(ResourceLimitFatalError,
7935               "UnableToCreateColormap",image->filename);
7936           for (i=0; i < (ssize_t) image->colors; i++)
7937           {
7938             diversity[i].red=image->colormap[i].red;
7939             diversity[i].green=image->colormap[i].green;
7940             diversity[i].blue=image->colormap[i].blue;
7941             diversity[i].index=(unsigned short) i;
7942             diversity[i].count=0;
7943           }
7944           image_view=AcquireCacheView(image);
7945           for (y=0; y < (int) image->rows; y++)
7946           {
7947             register int
7948               x;
7949
7950             register const PixelPacket
7951               *restrict p;
7952
7953             p=GetCacheViewAuthenticPixels(image_view,0,(ssize_t) y,
7954               image->columns,1,exception);
7955             if (p == (const PixelPacket *) NULL)
7956               break;
7957             indexes=GetCacheViewAuthenticIndexQueue(image_view);
7958             for (x=(int) image->columns-1; x >= 0; x--)
7959               diversity[(ssize_t) indexes[x]].count++;
7960           }
7961           image_view=DestroyCacheView(image_view);
7962           /*
7963             Sort colors by decreasing intensity.
7964           */
7965           qsort((void *) diversity,image->colors,sizeof(*diversity),
7966             IntensityCompare);
7967           for (i=0; i < (ssize_t) image->colors; )
7968           {
7969             diversity[i].count<<=4;  /* increase this colors popularity */
7970             i+=MagickMax((int) (image->colors >> 4),2);
7971           }
7972           diversity[image->colors-1].count<<=4;
7973           qsort((void *) diversity,image->colors,sizeof(*diversity),
7974             PopularityCompare);
7975           /*
7976             Allocate colors.
7977           */
7978           p=colors;
7979           color.flags=(char) (DoRed | DoGreen | DoBlue);
7980           for (i=0; i < (ssize_t) image->colors; i++)
7981           {
7982             index=diversity[i].index;
7983             color.red=
7984               ScaleQuantumToShort(XRedGamma(image->colormap[index].red));
7985             color.green=
7986               ScaleQuantumToShort(XGreenGamma(image->colormap[index].green));
7987             color.blue=
7988               ScaleQuantumToShort(XBlueGamma(image->colormap[index].blue));
7989             if (visual_info->klass != PseudoColor)
7990               {
7991                 gray_value=(unsigned short) XPixelIntensity(&color);
7992                 color.red=gray_value;
7993                 color.green=gray_value;
7994                 color.blue=gray_value;
7995               }
7996             status=XAllocColor(display,colormap,&color);
7997             if (status == False)
7998               break;
7999             pixel->pixels[index]=color.pixel;
8000             *p++=color;
8001           }
8002           /*
8003             Read X server colormap.
8004           */
8005           server_colors=(XColor *) AcquireQuantumMemory((size_t)
8006             visual_info->colormap_size,sizeof(*server_colors));
8007           if (server_colors == (XColor *) NULL)
8008             ThrowXWindowFatalException(ResourceLimitFatalError,
8009               "UnableToCreateColormap",image->filename);
8010           for (x=visual_info->colormap_size-1; x >= 0; x--)
8011             server_colors[x].pixel=(size_t) x;
8012           (void) XQueryColors(display,colormap,server_colors,
8013             (int) MagickMin((unsigned int) visual_info->colormap_size,256));
8014           /*
8015             Select remaining colors from X server colormap.
8016           */
8017           for (; i < (ssize_t) image->colors; i++)
8018           {
8019             index=diversity[i].index;
8020             color.red=
8021               ScaleQuantumToShort(XRedGamma(image->colormap[index].red));
8022             color.green=
8023               ScaleQuantumToShort(XGreenGamma(image->colormap[index].green));
8024             color.blue=
8025               ScaleQuantumToShort(XBlueGamma(image->colormap[index].blue));
8026             if (visual_info->klass != PseudoColor)
8027               {
8028                 gray_value=(unsigned short) XPixelIntensity(&color);
8029                 color.red=gray_value;
8030                 color.green=gray_value;
8031                 color.blue=gray_value;
8032               }
8033             XBestPixel(display,colormap,server_colors,(unsigned int)
8034               visual_info->colormap_size,&color);
8035             pixel->pixels[index]=color.pixel;
8036             *p++=color;
8037           }
8038           if ((int) image->colors < visual_info->colormap_size)
8039             {
8040               /*
8041                 Fill up colors array-- more choices for pen colors.
8042               */
8043               retain_colors=MagickMin((unsigned int)
8044                (visual_info->colormap_size-image->colors),256);
8045               for (i=0; i < (ssize_t) retain_colors; i++)
8046                 *p++=server_colors[i];
8047               number_colors+=retain_colors;
8048             }
8049           server_colors=(XColor *) RelinquishMagickMemory(server_colors);
8050           diversity=(DiversityPacket *) RelinquishMagickMemory(diversity);
8051           break;
8052         }
8053       /*
8054         Define Standard colormap for private GrayScale or PseudoColor visual.
8055       */
8056       if (status == False)
8057         {
8058           /*
8059             Not enough colormap entries in the colormap-- Create a new colormap.
8060           */
8061           colormap=XCreateColormap(display,
8062             XRootWindow(display,visual_info->screen),visual_info->visual,
8063             AllocNone);
8064           if (colormap == (Colormap) NULL)
8065             ThrowXWindowFatalException(ResourceLimitFatalError,
8066               "UnableToCreateColormap",image->filename);
8067           map_info->colormap=colormap;
8068           if ((int) image->colors < visual_info->colormap_size)
8069             {
8070               /*
8071                 Retain colors from the default colormap to help lessens the
8072                 effects of colormap flashing.
8073               */
8074               retain_colors=MagickMin((unsigned int)
8075                 (visual_info->colormap_size-image->colors),256);
8076               p=colors+image->colors;
8077               for (i=0; i < (ssize_t) retain_colors; i++)
8078               {
8079                 p->pixel=(unsigned long) i;
8080                 p++;
8081               }
8082               (void) XQueryColors(display,
8083                 XDefaultColormap(display,visual_info->screen),
8084                 colors+image->colors,(int) retain_colors);
8085               /*
8086                 Transfer colors from default to private colormap.
8087               */
8088               (void) XAllocColorCells(display,colormap,MagickFalse,
8089                 (unsigned long *) NULL,0,pixel->pixels,(unsigned int)
8090                 retain_colors);
8091               p=colors+image->colors;
8092               for (i=0; i < (ssize_t) retain_colors; i++)
8093               {
8094                 p->pixel=pixel->pixels[i];
8095                 p++;
8096               }
8097               (void) XStoreColors(display,colormap,colors+image->colors,
8098                 (int) retain_colors);
8099               number_colors+=retain_colors;
8100             }
8101           (void) XAllocColorCells(display,colormap,MagickFalse,
8102             (unsigned long *) NULL,0,pixel->pixels,(unsigned int)
8103             image->colors);
8104         }
8105       /*
8106         Store the image colormap.
8107       */
8108       p=colors;
8109       color.flags=(char) (DoRed | DoGreen | DoBlue);
8110       for (i=0; i < (ssize_t) image->colors; i++)
8111       {
8112         color.red=ScaleQuantumToShort(XRedGamma(image->colormap[i].red));
8113         color.green=ScaleQuantumToShort(XGreenGamma(image->colormap[i].green));
8114         color.blue=ScaleQuantumToShort(XBlueGamma(image->colormap[i].blue));
8115         if (visual_info->klass != PseudoColor)
8116           {
8117             gray_value=(unsigned short) XPixelIntensity(&color);
8118             color.red=gray_value;
8119             color.green=gray_value;
8120             color.blue=gray_value;
8121           }
8122         color.pixel=pixel->pixels[i];
8123         *p++=color;
8124       }
8125       (void) XStoreColors(display,colormap,colors,(int) image->colors);
8126       break;
8127     }
8128     case TrueColor:
8129     case DirectColor:
8130     default:
8131     {
8132       MagickBooleanType
8133         linear_colormap;
8134
8135       /*
8136         Define Standard Colormap for TrueColor or DirectColor visual.
8137       */
8138       number_colors=(unsigned int) ((map_info->red_max*map_info->red_mult)+
8139         (map_info->green_max*map_info->green_mult)+
8140         (map_info->blue_max*map_info->blue_mult)+1);
8141       linear_colormap=(number_colors > 4096) ||
8142         (((int) (map_info->red_max+1) == visual_info->colormap_size) &&
8143          ((int) (map_info->green_max+1) == visual_info->colormap_size) &&
8144          ((int) (map_info->blue_max+1) == visual_info->colormap_size)) ?
8145          MagickTrue : MagickFalse;
8146       if (linear_colormap != MagickFalse)
8147         number_colors=(size_t) visual_info->colormap_size;
8148       /*
8149         Allocate color array.
8150       */
8151       colors=(XColor *) AcquireQuantumMemory(number_colors,sizeof(*colors));
8152       if (colors == (XColor *) NULL)
8153         ThrowXWindowFatalException(ResourceLimitFatalError,
8154           "UnableToCreateColormap",image->filename);
8155       /*
8156         Initialize linear color ramp.
8157       */
8158       p=colors;
8159       color.flags=(char) (DoRed | DoGreen | DoBlue);
8160       if (linear_colormap != MagickFalse)
8161         for (i=0; i < (ssize_t) number_colors; i++)
8162         {
8163           color.blue=(unsigned short) 0;
8164           if (map_info->blue_max != 0)
8165             color.blue=(unsigned short) ((size_t)
8166               ((65535L*(i % map_info->green_mult))/map_info->blue_max));
8167           color.green=color.blue;
8168           color.red=color.blue;
8169           color.pixel=XStandardPixel(map_info,&color);
8170           *p++=color;
8171         }
8172       else
8173         for (i=0; i < (ssize_t) number_colors; i++)
8174         {
8175           color.red=(unsigned short) 0;
8176           if (map_info->red_max != 0)
8177             color.red=(unsigned short) ((size_t)
8178               ((65535L*(i/map_info->red_mult))/map_info->red_max));
8179           color.green=(unsigned int) 0;
8180           if (map_info->green_max != 0)
8181             color.green=(unsigned short) ((size_t)
8182               ((65535L*((i/map_info->green_mult) % (map_info->green_max+1)))/
8183                 map_info->green_max));
8184           color.blue=(unsigned short) 0;
8185           if (map_info->blue_max != 0)
8186             color.blue=(unsigned short) ((size_t)
8187               ((65535L*(i % map_info->green_mult))/map_info->blue_max));
8188           color.pixel=XStandardPixel(map_info,&color);
8189           *p++=color;
8190         }
8191       if ((visual_info->klass == DirectColor) &&
8192           (colormap != XDefaultColormap(display,visual_info->screen)))
8193         (void) XStoreColors(display,colormap,colors,(int) number_colors);
8194       else
8195         for (i=0; i < (ssize_t) number_colors; i++)
8196           (void) XAllocColor(display,colormap,&colors[i]);
8197       break;
8198     }
8199   }
8200   if ((visual_info->klass != DirectColor) &&
8201       (visual_info->klass != TrueColor))
8202     {
8203       /*
8204         Set foreground, background, border, etc. pixels.
8205       */
8206       XBestPixel(display,colormap,colors,(unsigned int) number_colors,
8207         &pixel->foreground_color);
8208       XBestPixel(display,colormap,colors,(unsigned int) number_colors,
8209         &pixel->background_color);
8210       if (pixel->background_color.pixel == pixel->foreground_color.pixel)
8211         {
8212           /*
8213             Foreground and background colors must differ.
8214           */
8215           pixel->background_color.red=(~pixel->foreground_color.red);
8216           pixel->background_color.green=
8217             (~pixel->foreground_color.green);
8218           pixel->background_color.blue=
8219             (~pixel->foreground_color.blue);
8220           XBestPixel(display,colormap,colors,(unsigned int) number_colors,
8221             &pixel->background_color);
8222         }
8223       XBestPixel(display,colormap,colors,(unsigned int) number_colors,
8224         &pixel->border_color);
8225       XBestPixel(display,colormap,colors,(unsigned int) number_colors,
8226         &pixel->matte_color);
8227       XBestPixel(display,colormap,colors,(unsigned int) number_colors,
8228         &pixel->highlight_color);
8229       XBestPixel(display,colormap,colors,(unsigned int) number_colors,
8230         &pixel->shadow_color);
8231       XBestPixel(display,colormap,colors,(unsigned int) number_colors,
8232         &pixel->depth_color);
8233       XBestPixel(display,colormap,colors,(unsigned int) number_colors,
8234         &pixel->trough_color);
8235       for (i=0; i < MaxNumberPens; i++)
8236       {
8237         XBestPixel(display,colormap,colors,(unsigned int) number_colors,
8238           &pixel->pen_colors[i]);
8239         pixel->pixels[image->colors+i]=pixel->pen_colors[i].pixel;
8240       }
8241       pixel->colors=(ssize_t) (image->colors+MaxNumberPens);
8242     }
8243   colors=(XColor *) RelinquishMagickMemory(colors);
8244   if (IsEventLogging())
8245     {
8246       (void) LogMagickEvent(X11Event,GetMagickModule(),"Standard Colormap:");
8247       (void) LogMagickEvent(X11Event,GetMagickModule(),"  colormap id: 0x%lx",
8248         map_info->colormap);
8249       (void) LogMagickEvent(X11Event,GetMagickModule(),
8250         "  red, green, blue max: %lu %lu %lu",map_info->red_max,
8251         map_info->green_max,map_info->blue_max);
8252       (void) LogMagickEvent(X11Event,GetMagickModule(),
8253         "  red, green, blue mult: %lu %lu %lu",map_info->red_mult,
8254         map_info->green_mult,map_info->blue_mult);
8255     }
8256 }
8257 \f
8258 /*
8259 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8260 %                                                                             %
8261 %                                                                             %
8262 %                                                                             %
8263 %   X M a k e W i n d o w                                                     %
8264 %                                                                             %
8265 %                                                                             %
8266 %                                                                             %
8267 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8268 %
8269 %  XMakeWindow() creates an X11 window.
8270 %
8271 %  The format of the XMakeWindow method is:
8272 %
8273 %      void XMakeWindow(Display *display,Window parent,char **argv,int argc,
8274 %        XClassHint *class_hint,XWMHints *manager_hints,
8275 %        XWindowInfo *window_info)
8276 %
8277 %  A description of each parameter follows:
8278 %
8279 %    o display: Specifies a connection to an X server; returned from
8280 %      XOpenDisplay.
8281 %
8282 %    o parent: Specifies the parent window_info.
8283 %
8284 %    o argv: Specifies the application's argument list.
8285 %
8286 %    o argc: Specifies the number of arguments.
8287 %
8288 %    o class_hint: Specifies a pointer to a X11 XClassHint structure.
8289 %
8290 %    o manager_hints: Specifies a pointer to a X11 XWMHints structure.
8291 %
8292 %    o window_info: Specifies a pointer to a X11 XWindowInfo structure.
8293 %
8294 */
8295 MagickExport void XMakeWindow(Display *display,Window parent,char **argv,
8296   int argc,XClassHint *class_hint,XWMHints *manager_hints,
8297   XWindowInfo *window_info)
8298 {
8299 #define MinWindowSize  64
8300
8301   Atom
8302     atom_list[2];
8303
8304   int
8305     gravity;
8306
8307   static XTextProperty
8308     icon_name,
8309     window_name;
8310
8311   Status
8312     status;
8313
8314   XSizeHints
8315     *size_hints;
8316
8317   /*
8318     Set window info hints.
8319   */
8320   (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
8321   assert(display != (Display *) NULL);
8322   assert(window_info != (XWindowInfo *) NULL);
8323   size_hints=XAllocSizeHints();
8324   if (size_hints == (XSizeHints *) NULL)
8325     ThrowXWindowFatalException(XServerFatalError,"UnableToMakeXWindow",argv[0]);
8326   size_hints->flags=(int) window_info->flags;
8327   size_hints->x=window_info->x;
8328   size_hints->y=window_info->y;
8329   size_hints->width=(int) window_info->width;
8330   size_hints->height=(int) window_info->height;
8331   if (window_info->immutable != MagickFalse)
8332     {
8333       /*
8334         Window size cannot be changed.
8335       */
8336       size_hints->min_width=size_hints->width;
8337       size_hints->min_height=size_hints->height;
8338       size_hints->max_width=size_hints->width;
8339       size_hints->max_height=size_hints->height;
8340       size_hints->flags|=PMinSize;
8341       size_hints->flags|=PMaxSize;
8342     }
8343   else
8344     {
8345       /*
8346         Window size can be changed.
8347       */
8348       size_hints->min_width=(int) window_info->min_width;
8349       size_hints->min_height=(int) window_info->min_height;
8350       size_hints->flags|=PResizeInc;
8351       size_hints->width_inc=(int) window_info->width_inc;
8352       size_hints->height_inc=(int) window_info->height_inc;
8353 #if !defined(PRE_R4_ICCCM)
8354       size_hints->flags|=PBaseSize;
8355       size_hints->base_width=size_hints->width_inc;
8356       size_hints->base_height=size_hints->height_inc;
8357 #endif
8358     }
8359   gravity=NorthWestGravity;
8360   if (window_info->geometry != (char *) NULL)
8361     {
8362       char
8363         default_geometry[MaxTextExtent],
8364         geometry[MaxTextExtent];
8365
8366       int
8367         flags;
8368
8369       register char
8370         *p;
8371
8372       /*
8373         User specified geometry.
8374       */
8375       (void) FormatMagickString(default_geometry,MaxTextExtent,"%dx%d",
8376         size_hints->width,size_hints->height);
8377       (void) CopyMagickString(geometry,window_info->geometry,MaxTextExtent);
8378       p=geometry;
8379       while (strlen(p) != 0)
8380       {
8381         if ((isspace((int) ((unsigned char) *p)) == 0) && (*p != '%'))
8382           p++;
8383         else
8384           (void) CopyMagickString(p,p+1,MaxTextExtent);
8385       }
8386       flags=XWMGeometry(display,window_info->screen,geometry,default_geometry,
8387         window_info->border_width,size_hints,&size_hints->x,&size_hints->y,
8388         &size_hints->width,&size_hints->height,&gravity);
8389       if ((flags & WidthValue) && (flags & HeightValue))
8390         size_hints->flags|=USSize;
8391       if ((flags & XValue) && (flags & YValue))
8392         {
8393           size_hints->flags|=USPosition;
8394           window_info->x=size_hints->x;
8395           window_info->y=size_hints->y;
8396         }
8397     }
8398 #if !defined(PRE_R4_ICCCM)
8399   size_hints->win_gravity=gravity;
8400   size_hints->flags|=PWinGravity;
8401 #endif
8402   if (window_info->id == (Window) NULL)
8403     window_info->id=XCreateWindow(display,parent,window_info->x,window_info->y,
8404       (unsigned int) size_hints->width,(unsigned int) size_hints->height,
8405       window_info->border_width,(int) window_info->depth,InputOutput,
8406       window_info->visual,(unsigned long) window_info->mask,
8407       &window_info->attributes);
8408   else
8409     {
8410       MagickStatusType
8411         mask;
8412
8413       XEvent
8414         sans_event;
8415
8416       XWindowChanges
8417         window_changes;
8418
8419       /*
8420         Window already exists;  change relevant attributes.
8421       */
8422       (void) XChangeWindowAttributes(display,window_info->id,(unsigned long)
8423         window_info->mask,&window_info->attributes);
8424       mask=ConfigureNotify;
8425       while (XCheckTypedWindowEvent(display,window_info->id,(int) mask,&sans_event)) ;
8426       window_changes.x=window_info->x;
8427       window_changes.y=window_info->y;
8428       window_changes.width=(int) window_info->width;
8429       window_changes.height=(int) window_info->height;
8430       mask=(MagickStatusType) (CWWidth | CWHeight);
8431       if (window_info->flags & USPosition)
8432         mask|=CWX | CWY;
8433       (void) XReconfigureWMWindow(display,window_info->id,window_info->screen,
8434         mask,&window_changes);
8435     }
8436   if (window_info->id == (Window) NULL)
8437     ThrowXWindowFatalException(XServerFatalError,"UnableToCreateWindow",
8438       window_info->name);
8439   status=XStringListToTextProperty(&window_info->name,1,&window_name);
8440   if (status == False)
8441     ThrowXWindowFatalException(XServerFatalError,"UnableToCreateTextProperty",
8442       window_info->name);
8443   status=XStringListToTextProperty(&window_info->icon_name,1,&icon_name);
8444   if (status == False)
8445     ThrowXWindowFatalException(XServerFatalError,"UnableToCreateTextProperty",
8446       window_info->icon_name);
8447   if (window_info->icon_geometry != (char *) NULL)
8448     {
8449       int
8450         flags,
8451         height,
8452         width;
8453
8454       /*
8455         User specified icon geometry.
8456       */
8457       size_hints->flags|=USPosition;
8458       flags=XWMGeometry(display,window_info->screen,window_info->icon_geometry,
8459         (char *) NULL,0,size_hints,&manager_hints->icon_x,
8460         &manager_hints->icon_y,&width,&height,&gravity);
8461       if ((flags & XValue) && (flags & YValue))
8462         manager_hints->flags|=IconPositionHint;
8463     }
8464   XSetWMProperties(display,window_info->id,&window_name,&icon_name,argv,argc,
8465     size_hints,manager_hints,class_hint);
8466   if (window_name.value != (void *) NULL)
8467     {
8468       (void) XFree((void *) window_name.value);
8469       window_name.value=(unsigned char *) NULL;
8470       window_name.nitems=0;
8471     }
8472   if (icon_name.value != (void *) NULL)
8473     {
8474       (void) XFree((void *) icon_name.value);
8475       icon_name.value=(unsigned char *) NULL;
8476       icon_name.nitems=0;
8477     }
8478   atom_list[0]=XInternAtom(display,"WM_DELETE_WINDOW",MagickFalse);
8479   atom_list[1]=XInternAtom(display,"WM_TAKE_FOCUS",MagickFalse);
8480   (void) XSetWMProtocols(display,window_info->id,atom_list,2);
8481   (void) XFree((void *) size_hints);
8482   if (window_info->shape != MagickFalse)
8483     {
8484 #if defined(MAGICKCORE_HAVE_SHAPE)
8485       int
8486         error_base,
8487         event_base;
8488
8489       /*
8490         Can we apply a non-rectangular shaping mask?
8491       */
8492       error_base=0;
8493       event_base=0;
8494       if (XShapeQueryExtension(display,&error_base,&event_base) == 0)
8495         window_info->shape=MagickFalse;
8496 #else
8497       window_info->shape=MagickFalse;
8498 #endif
8499     }
8500   if (window_info->shared_memory)
8501     {
8502 #if defined(MAGICKCORE_HAVE_SHARED_MEMORY)
8503       /*
8504         Can we use shared memory with this window?
8505       */
8506       if (XShmQueryExtension(display) == 0)
8507         window_info->shared_memory=MagickFalse;
8508 #else
8509       window_info->shared_memory=MagickFalse;
8510 #endif
8511     }
8512   window_info->image=NewImageList();
8513   window_info->destroy=MagickFalse;
8514 }
8515 \f
8516 /*
8517 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8518 %                                                                             %
8519 %                                                                             %
8520 %                                                                             %
8521 %   X M a g i c k P r o g r e s s M o n i t o r                               %
8522 %                                                                             %
8523 %                                                                             %
8524 %                                                                             %
8525 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8526 %
8527 %  XMagickProgressMonitor() displays the progress a task is making in
8528 %  completing a task.
8529 %
8530 %  The format of the XMagickProgressMonitor method is:
8531 %
8532 %      void XMagickProgressMonitor(const char *task,
8533 %        const MagickOffsetType quantum,const MagickSizeType span,
8534 %        void *client_data)
8535 %
8536 %  A description of each parameter follows:
8537 %
8538 %    o task: Identifies the task in progress.
8539 %
8540 %    o quantum: Specifies the quantum position within the span which represents
8541 %      how much progress has been made in completing a task.
8542 %
8543 %    o span: Specifies the span relative to completing a task.
8544 %
8545 %    o client_data: Pointer to any client data.
8546 %
8547 */
8548
8549 static const char *GetLocaleMonitorMessage(const char *text)
8550 {
8551   char
8552     message[MaxTextExtent],
8553     tag[MaxTextExtent];
8554
8555   const char
8556     *locale_message;
8557
8558   register char
8559     *p;
8560
8561   (void) CopyMagickMemory(tag,text,MaxTextExtent);
8562   p=strrchr(tag,'/');
8563   if (p != (char *) NULL)
8564     *p='\0';
8565   (void) FormatMagickString(message,MaxTextExtent,"Monitor/%s",tag);
8566   locale_message=GetLocaleMessage(message);
8567   if (locale_message == message)
8568     return(text);
8569   return(locale_message);
8570 }
8571
8572 MagickExport MagickBooleanType XMagickProgressMonitor(const char *tag,
8573   const MagickOffsetType quantum,const MagickSizeType span,
8574   void *magick_unused(client_data))
8575 {
8576   XWindows
8577     *windows;
8578
8579   windows=XSetWindows((XWindows *) ~0);
8580   if (windows == (XWindows *) NULL)
8581     return(MagickTrue);
8582   if (windows->info.mapped != MagickFalse)
8583     XProgressMonitorWidget(windows->display,windows,
8584       GetLocaleMonitorMessage(tag),quantum,span);
8585   return(MagickTrue);
8586 }
8587 \f
8588 /*
8589 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8590 %                                                                             %
8591 %                                                                             %
8592 %                                                                             %
8593 %   X Q u e r y C o l o r D a t a b a s e                                     %
8594 %                                                                             %
8595 %                                                                             %
8596 %                                                                             %
8597 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8598 %
8599 %  XQueryColorDatabase() looks up a RGB values for a color given in the target
8600 %  string.
8601 %
8602 %  The format of the XQueryColorDatabase method is:
8603 %
8604 %      MagickBooleanType XQueryColorDatabase(const char *target,XColor *color)
8605 %
8606 %  A description of each parameter follows:
8607 %
8608 %    o target: Specifies the color to lookup in the X color database.
8609 %
8610 %    o color: A pointer to an PixelPacket structure.  The RGB value of the target
8611 %      color is returned as this value.
8612 %
8613 */
8614 MagickExport MagickBooleanType XQueryColorDatabase(const char *target,
8615   XColor *color)
8616 {
8617   Colormap
8618     colormap;
8619
8620   static Display
8621     *display = (Display *) NULL;
8622
8623   Status
8624     status;
8625
8626   XColor
8627     xcolor;
8628
8629   /*
8630     Initialize color return value.
8631   */
8632   assert(color != (XColor *) NULL);
8633   color->red=0;
8634   color->green=0;
8635   color->blue=0;
8636   color->flags=(char) (DoRed | DoGreen | DoBlue);
8637   if ((target == (char *) NULL) || (*target == '\0'))
8638     target="#ffffffffffff";
8639   /*
8640     Let the X server define the color for us.
8641   */
8642   if (display == (Display *) NULL)
8643     display=XOpenDisplay((char *) NULL);
8644   if (display == (Display *) NULL)
8645     {
8646       ThrowXWindowFatalException(XServerError,"ColorIsNotKnownToServer",target);
8647       return(MagickFalse);
8648     }
8649   colormap=XDefaultColormap(display,XDefaultScreen(display));
8650   status=XParseColor(display,colormap,(char *) target,&xcolor);
8651   if (status == False)
8652     ThrowXWindowFatalException(XServerError,"ColorIsNotKnownToServer",target)
8653   else
8654     {
8655       color->red=xcolor.red;
8656       color->green=xcolor.green;
8657       color->blue=xcolor.blue;
8658       color->flags=xcolor.flags;
8659     }
8660   return(status != False ? MagickTrue : MagickFalse);
8661 }
8662 \f
8663 /*
8664 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8665 %                                                                             %
8666 %                                                                             %
8667 %                                                                             %
8668 %   X Q u e r y P o s i t i o n                                               %
8669 %                                                                             %
8670 %                                                                             %
8671 %                                                                             %
8672 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8673 %
8674 %  XQueryPosition() gets the pointer coordinates relative to a window.
8675 %
8676 %  The format of the XQueryPosition method is:
8677 %
8678 %      void XQueryPosition(Display *display,const Window window,int *x,int *y)
8679 %
8680 %  A description of each parameter follows:
8681 %
8682 %    o display: Specifies a connection to an X server;  returned from
8683 %      XOpenDisplay.
8684 %
8685 %    o window: Specifies a pointer to a Window.
8686 %
8687 %    o x: Return the x coordinate of the pointer relative to the origin of the
8688 %      window.
8689 %
8690 %    o y: Return the y coordinate of the pointer relative to the origin of the
8691 %      window.
8692 %
8693 */
8694 MagickExport void XQueryPosition(Display *display,const Window window,int *x,int *y)
8695 {
8696   int
8697     x_root,
8698     y_root;
8699
8700   unsigned int
8701     mask;
8702
8703   Window
8704     root_window;
8705
8706   (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
8707   assert(display != (Display *) NULL);
8708   assert(window != (Window) NULL);
8709   assert(x != (int *) NULL);
8710   assert(y != (int *) NULL);
8711   (void) XQueryPointer(display,window,&root_window,&root_window,&x_root,&y_root,
8712     x,y,&mask);
8713 }
8714 \f
8715 /*
8716 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8717 %                                                                             %
8718 %                                                                             %
8719 %                                                                             %
8720 %   X R e f r e s h W i n d o w                                               %
8721 %                                                                             %
8722 %                                                                             %
8723 %                                                                             %
8724 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8725 %
8726 %  XRefreshWindow() refreshes an image in a X window.
8727 %
8728 %  The format of the XRefreshWindow method is:
8729 %
8730 %      void XRefreshWindow(Display *display,const XWindowInfo *window,
8731 %        const XEvent *event)
8732 %
8733 %  A description of each parameter follows:
8734 %
8735 %    o display: Specifies a connection to an X server;  returned from
8736 %      XOpenDisplay.
8737 %
8738 %    o window: Specifies a pointer to a XWindowInfo structure.
8739 %
8740 %    o event: Specifies a pointer to a XEvent structure.  If it is NULL,
8741 %      the entire image is refreshed.
8742 %
8743 */
8744 MagickExport void XRefreshWindow(Display *display,const XWindowInfo *window,
8745   const XEvent *event)
8746 {
8747   int
8748     x,
8749     y;
8750
8751   unsigned int
8752     height,
8753     width;
8754
8755   (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
8756   assert(display != (Display *) NULL);
8757   assert(window != (XWindowInfo *) NULL);
8758   if (window->ximage == (XImage *) NULL)
8759     return;
8760   if (event != (XEvent *) NULL)
8761     {
8762       /*
8763         Determine geometry from expose event.
8764       */
8765       x=event->xexpose.x;
8766       y=event->xexpose.y;
8767       width=(unsigned int) event->xexpose.width;
8768       height=(unsigned int) event->xexpose.height;
8769     }
8770   else
8771     {
8772       XEvent
8773         sans_event;
8774
8775       /*
8776         Refresh entire window; discard outstanding expose events.
8777       */
8778       x=0;
8779       y=0;
8780       width=window->width;
8781       height=window->height;
8782       while (XCheckTypedWindowEvent(display,window->id,Expose,&sans_event)) ;
8783       if (window->matte_pixmap != (Pixmap) NULL)
8784         {
8785 #if defined(MAGICKCORE_HAVE_SHAPE)
8786           if (window->shape != MagickFalse)
8787             XShapeCombineMask(display,window->id,ShapeBounding,0,0,
8788               window->matte_pixmap,ShapeSet);
8789 #endif
8790         }
8791     }
8792   /*
8793     Check boundary conditions.
8794   */
8795   if ((window->ximage->width-(x+window->x)) < (int) width)
8796     width=(unsigned int) (window->ximage->width-(x+window->x));
8797   if ((window->ximage->height-(y+window->y)) < (int) height)
8798     height=(unsigned int) (window->ximage->height-(y+window->y));
8799   /*
8800     Refresh image.
8801   */
8802   if (window->matte_pixmap != (Pixmap) NULL)
8803     (void) XSetClipMask(display,window->annotate_context,window->matte_pixmap);
8804   if (window->pixmap != (Pixmap) NULL)
8805     {
8806       if (window->depth > 1)
8807         (void) XCopyArea(display,window->pixmap,window->id,
8808           window->annotate_context,x+window->x,y+window->y,width,height,x,y);
8809       else
8810         (void) XCopyPlane(display,window->pixmap,window->id,
8811           window->highlight_context,x+window->x,y+window->y,width,height,x,y,
8812           1L);
8813     }
8814   else
8815     {
8816 #if defined(MAGICKCORE_HAVE_SHARED_MEMORY)
8817       if (window->shared_memory)
8818         (void) XShmPutImage(display,window->id,window->annotate_context,
8819           window->ximage,x+window->x,y+window->y,x,y,width,height,MagickTrue);
8820 #endif
8821       if (window->shared_memory == MagickFalse)
8822         (void) XPutImage(display,window->id,window->annotate_context,
8823           window->ximage,x+window->x,y+window->y,x,y,width,height);
8824     }
8825   if (window->matte_pixmap != (Pixmap) NULL)
8826     (void) XSetClipMask(display,window->annotate_context,None);
8827   (void) XFlush(display);
8828 }
8829 \f
8830 /*
8831 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8832 %                                                                             %
8833 %                                                                             %
8834 %                                                                             %
8835 %   X R e m o t e C o m m a n d                                               %
8836 %                                                                             %
8837 %                                                                             %
8838 %                                                                             %
8839 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8840 %
8841 %  XRemoteCommand() forces a remote display(1) to display the specified
8842 %  image filename.
8843 %
8844 %  The format of the XRemoteCommand method is:
8845 %
8846 %      MagickBooleanType XRemoteCommand(Display *display,const char *window,
8847 %        const char *filename)
8848 %
8849 %  A description of each parameter follows:
8850 %
8851 %    o display: Specifies a connection to an X server; returned from
8852 %      XOpenDisplay.
8853 %
8854 %    o window: Specifies the name or id of an X window.
8855 %
8856 %    o filename: the name of the image filename to display.
8857 %
8858 */
8859 MagickExport MagickBooleanType XRemoteCommand(Display *display,
8860   const char *window,const char *filename)
8861 {
8862   Atom
8863     remote_atom;
8864
8865   Window
8866     remote_window,
8867     root_window;
8868
8869   assert(filename != (char *) NULL);
8870   (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",filename);
8871   if (display == (Display *) NULL)
8872     display=XOpenDisplay((char *) NULL);
8873   if (display == (Display *) NULL)
8874     {
8875       ThrowXWindowException(XServerError,"UnableToOpenXServer",filename);
8876       return(MagickFalse);
8877     }
8878   remote_atom=XInternAtom(display,"IM_PROTOCOLS",MagickFalse);
8879   remote_window=(Window) NULL;
8880   root_window=XRootWindow(display,XDefaultScreen(display));
8881   if (window != (char *) NULL)
8882     {
8883       /*
8884         Search window hierarchy and identify any clients by name or ID.
8885       */
8886       if (isdigit((unsigned char) *window) != 0)
8887         remote_window=XWindowByID(display,root_window,(Window)
8888           strtol((char *) window,(char **) NULL,0));
8889       if (remote_window == (Window) NULL)
8890         remote_window=XWindowByName(display,root_window,window);
8891     }
8892   if (remote_window == (Window) NULL)
8893     remote_window=XWindowByProperty(display,root_window,remote_atom);
8894   if (remote_window == (Window) NULL)
8895     {
8896       ThrowXWindowException(XServerError,"UnableToConnectToRemoteDisplay",
8897         filename);
8898       return(MagickFalse);
8899     }
8900   /*
8901     Send remote command.
8902   */
8903   remote_atom=XInternAtom(display,"IM_REMOTE_COMMAND",MagickFalse);
8904   (void) XChangeProperty(display,remote_window,remote_atom,XA_STRING,8,
8905     PropModeReplace,(unsigned char *) filename,(int) strlen(filename));
8906   (void) XSync(display,MagickFalse);
8907   return(MagickTrue);
8908 }
8909 \f
8910 /*
8911 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8912 %                                                                             %
8913 %                                                                             %
8914 %                                                                             %
8915 %   X R e t a i n W i n d o w C o l o r s                                     %
8916 %                                                                             %
8917 %                                                                             %
8918 %                                                                             %
8919 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8920 %
8921 %  XRetainWindowColors() sets X11 color resources on a window.  This preserves
8922 %  the colors associated with an image displayed on the window.
8923 %
8924 %  The format of the XRetainWindowColors method is:
8925 %
8926 %      void XRetainWindowColors(Display *display,const Window window)
8927 %
8928 %  A description of each parameter follows:
8929 %
8930 %    o display: Specifies a connection to an X server; returned from
8931 %      XOpenDisplay.
8932 %
8933 %    o window: Specifies a pointer to a XWindowInfo structure.
8934 %
8935 */
8936 MagickExport void XRetainWindowColors(Display *display,const Window window)
8937 {
8938   Atom
8939     property;
8940
8941   Pixmap
8942     pixmap;
8943
8944   /*
8945     Put property on the window.
8946   */
8947   (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
8948   assert(display != (Display *) NULL);
8949   assert(window != (Window) NULL);
8950   property=XInternAtom(display,"_XSETROOT_ID",MagickFalse);
8951   if (property == (Atom) NULL)
8952     {
8953       ThrowXWindowFatalException(XServerError,"UnableToCreateProperty",
8954         "_XSETROOT_ID");
8955       return;
8956     }
8957   pixmap=XCreatePixmap(display,window,1,1,1);
8958   if (pixmap == (Pixmap) NULL)
8959     {
8960       ThrowXWindowFatalException(XServerError,"UnableToCreateBitmap","");
8961       return;
8962     }
8963   (void) XChangeProperty(display,window,property,XA_PIXMAP,32,PropModeReplace,
8964     (unsigned char *) &pixmap,1);
8965   (void) XSetCloseDownMode(display,RetainPermanent);
8966 }
8967 \f
8968 /*
8969 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8970 %                                                                             %
8971 %                                                                             %
8972 %                                                                             %
8973 %   X S e l e c t W i n d o w                                                 %
8974 %                                                                             %
8975 %                                                                             %
8976 %                                                                             %
8977 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8978 %
8979 %  XSelectWindow() allows a user to select a window using the mouse.  If the
8980 %  mouse moves, a cropping rectangle is drawn and the extents of the rectangle
8981 %  is returned in the crop_info structure.
8982 %
8983 %  The format of the XSelectWindow function is:
8984 %
8985 %      target_window=XSelectWindow(display,crop_info)
8986 %
8987 %  A description of each parameter follows:
8988 %
8989 %    o window: XSelectWindow returns the window id.
8990 %
8991 %    o display: Specifies a pointer to the Display structure;  returned from
8992 %      XOpenDisplay.
8993 %
8994 %    o crop_info: Specifies a pointer to a RectangleInfo structure.  It
8995 %      contains the extents of any cropping rectangle.
8996 %
8997 */
8998 static Window XSelectWindow(Display *display,RectangleInfo *crop_info)
8999 {
9000 #define MinimumCropArea  (unsigned int) 9
9001
9002   Cursor
9003     target_cursor;
9004
9005   GC
9006     annotate_context;
9007
9008   int
9009     presses,
9010     x_offset,
9011     y_offset;
9012
9013   Status
9014     status;
9015
9016   Window
9017     root_window,
9018     target_window;
9019
9020   XEvent
9021     event;
9022
9023   XGCValues
9024     context_values;
9025
9026   /*
9027     Initialize graphic context.
9028   */
9029   (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
9030   assert(display != (Display *) NULL);
9031   assert(crop_info != (RectangleInfo *) NULL);
9032   root_window=XRootWindow(display,XDefaultScreen(display));
9033   context_values.background=XBlackPixel(display,XDefaultScreen(display));
9034   context_values.foreground=XWhitePixel(display,XDefaultScreen(display));
9035   context_values.function=GXinvert;
9036   context_values.plane_mask=
9037     context_values.background ^ context_values.foreground;
9038   context_values.subwindow_mode=IncludeInferiors;
9039   annotate_context=XCreateGC(display,root_window,(size_t) (GCBackground |
9040     GCForeground | GCFunction | GCSubwindowMode),&context_values);
9041   if (annotate_context == (GC) NULL)
9042     return(MagickFalse);
9043   /*
9044     Grab the pointer using target cursor.
9045   */
9046   target_cursor=XMakeCursor(display,root_window,XDefaultColormap(display,
9047     XDefaultScreen(display)),(char * ) "white",(char * ) "black");
9048   status=XGrabPointer(display,root_window,MagickFalse,(unsigned int)
9049     (ButtonPressMask | ButtonReleaseMask | ButtonMotionMask),GrabModeSync,
9050     GrabModeAsync,root_window,target_cursor,CurrentTime);
9051   if (status != GrabSuccess)
9052     {
9053       ThrowXWindowFatalException(XServerError,"UnableToGrabMouse","");
9054       return((Window) NULL);
9055     }
9056   /*
9057     Select a window.
9058   */
9059   crop_info->width=0;
9060   crop_info->height=0;
9061   presses=0;
9062   target_window=(Window) NULL;
9063   x_offset=0;
9064   y_offset=0;
9065   do
9066   {
9067     if ((crop_info->width*crop_info->height) >= MinimumCropArea)
9068       (void) XDrawRectangle(display,root_window,annotate_context,
9069         (int) crop_info->x,(int) crop_info->y,(unsigned int) crop_info->width-1,
9070         (unsigned int) crop_info->height-1);
9071     /*
9072       Allow another event.
9073     */
9074     (void) XAllowEvents(display,SyncPointer,CurrentTime);
9075     (void) XWindowEvent(display,root_window,ButtonPressMask |
9076       ButtonReleaseMask | ButtonMotionMask,&event);
9077     if ((crop_info->width*crop_info->height) >= MinimumCropArea)
9078       (void) XDrawRectangle(display,root_window,annotate_context,
9079         (int) crop_info->x,(int) crop_info->y,(unsigned int) crop_info->width-1,
9080         (unsigned int) crop_info->height-1);
9081     switch (event.type)
9082     {
9083       case ButtonPress:
9084       {
9085         target_window=XGetSubwindow(display,event.xbutton.subwindow,
9086           event.xbutton.x,event.xbutton.y);
9087         if (target_window == (Window) NULL)
9088           target_window=root_window;
9089         x_offset=event.xbutton.x_root;
9090         y_offset=event.xbutton.y_root;
9091         crop_info->x=(ssize_t) x_offset;
9092         crop_info->y=(ssize_t) y_offset;
9093         crop_info->width=0;
9094         crop_info->height=0;
9095         presses++;
9096         break;
9097       }
9098       case ButtonRelease:
9099       {
9100         presses--;
9101         break;
9102       }
9103       case MotionNotify:
9104       {
9105         /*
9106           Discard pending button motion events.
9107         */
9108         while (XCheckMaskEvent(display,ButtonMotionMask,&event)) ;
9109         crop_info->x=(ssize_t) event.xmotion.x;
9110         crop_info->y=(ssize_t) event.xmotion.y;
9111         /*
9112           Check boundary conditions.
9113         */
9114         if ((int) crop_info->x < x_offset)
9115           crop_info->width=(size_t) (x_offset-crop_info->x);
9116         else
9117           {
9118             crop_info->width=(size_t) (crop_info->x-x_offset);
9119             crop_info->x=(ssize_t) x_offset;
9120           }
9121         if ((int) crop_info->y < y_offset)
9122           crop_info->height=(size_t) (y_offset-crop_info->y);
9123         else
9124           {
9125             crop_info->height=(size_t) (crop_info->y-y_offset);
9126             crop_info->y=(ssize_t) y_offset;
9127           }
9128       }
9129       default:
9130         break;
9131     }
9132   } while ((target_window == (Window) NULL) || (presses > 0));
9133   (void) XUngrabPointer(display,CurrentTime);
9134   (void) XFreeCursor(display,target_cursor);
9135   (void) XFreeGC(display,annotate_context);
9136   if ((crop_info->width*crop_info->height) < MinimumCropArea)
9137     {
9138       crop_info->width=0;
9139       crop_info->height=0;
9140     }
9141   if ((crop_info->width != 0) && (crop_info->height != 0))
9142     target_window=root_window;
9143   return(target_window);
9144 }
9145 \f
9146 /*
9147 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9148 %                                                                             %
9149 %                                                                             %
9150 %                                                                             %
9151 %   X S e t C u r s o r S t a t e                                             %
9152 %                                                                             %
9153 %                                                                             %
9154 %                                                                             %
9155 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9156 %
9157 %  XSetCursorState() sets the cursor state to busy, otherwise the cursor are
9158 %  reset to their default.
9159 %
9160 %  The format of the XXSetCursorState method is:
9161 %
9162 %      XSetCursorState(display,windows,const MagickStatusType state)
9163 %
9164 %  A description of each parameter follows:
9165 %
9166 %    o display: Specifies a connection to an X server;  returned from
9167 %      XOpenDisplay.
9168 %
9169 %    o windows: Specifies a pointer to a XWindows structure.
9170 %
9171 %    o state: An unsigned integer greater than 0 sets the cursor state
9172 %      to busy, otherwise the cursor are reset to their default.
9173 %
9174 */
9175 MagickExport void XSetCursorState(Display *display,XWindows *windows,
9176   const MagickStatusType state)
9177 {
9178   (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
9179   assert(display != (Display *) NULL);
9180   assert(windows != (XWindows *) NULL);
9181   if (state)
9182     {
9183       (void) XCheckDefineCursor(display,windows->image.id,
9184         windows->image.busy_cursor);
9185       (void) XCheckDefineCursor(display,windows->pan.id,
9186         windows->pan.busy_cursor);
9187       (void) XCheckDefineCursor(display,windows->magnify.id,
9188         windows->magnify.busy_cursor);
9189       (void) XCheckDefineCursor(display,windows->command.id,
9190         windows->command.busy_cursor);
9191     }
9192   else
9193     {
9194       (void) XCheckDefineCursor(display,windows->image.id,
9195         windows->image.cursor);
9196       (void) XCheckDefineCursor(display,windows->pan.id,windows->pan.cursor);
9197       (void) XCheckDefineCursor(display,windows->magnify.id,
9198         windows->magnify.cursor);
9199       (void) XCheckDefineCursor(display,windows->command.id,
9200         windows->command.cursor);
9201       (void) XCheckDefineCursor(display,windows->command.id,
9202         windows->widget.cursor);
9203       (void) XWithdrawWindow(display,windows->info.id,windows->info.screen);
9204     }
9205   windows->info.mapped=MagickFalse;
9206 }
9207 \f
9208 /*
9209 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9210 %                                                                             %
9211 %                                                                             %
9212 %                                                                             %
9213 %   X S e t W i n d o w s                                                     %
9214 %                                                                             %
9215 %                                                                             %
9216 %                                                                             %
9217 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9218 %
9219 %  XSetWindows() sets the X windows structure if the windows info is specified.
9220 %  Otherwise the current windows structure is returned.
9221 %
9222 %  The format of the XSetWindows method is:
9223 %
9224 %      XWindows *XSetWindows(XWindows *windows_info)
9225 %
9226 %  A description of each parameter follows:
9227 %
9228 %    o windows_info: Initialize the Windows structure with this information.
9229 %
9230 */
9231 MagickExport XWindows *XSetWindows(XWindows *windows_info)
9232 {
9233   static XWindows
9234     *windows = (XWindows *) NULL;
9235
9236   if (windows_info != (XWindows *) ~0)
9237     {
9238       windows=(XWindows *) RelinquishMagickMemory(windows);
9239       windows=windows_info;
9240     }
9241   return(windows);
9242 }
9243 /*
9244 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9245 %                                                                             %
9246 %                                                                             %
9247 %                                                                             %
9248 %   X U s e r P r e f e r e n c e s                                           %
9249 %                                                                             %
9250 %                                                                             %
9251 %                                                                             %
9252 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9253 %
9254 %  XUserPreferences() saves the preferences in a configuration file in the
9255 %  users' home directory.
9256 %
9257 %  The format of the XUserPreferences method is:
9258 %
9259 %      void XUserPreferences(XResourceInfo *resource_info)
9260 %
9261 %  A description of each parameter follows:
9262 %
9263 %    o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
9264 %
9265 */
9266 MagickExport void XUserPreferences(XResourceInfo *resource_info)
9267 {
9268 #if defined(X11_PREFERENCES_PATH)
9269   char
9270     cache[MaxTextExtent],
9271     filename[MaxTextExtent],
9272     specifier[MaxTextExtent];
9273
9274   const char
9275     *client_name,
9276     *value;
9277
9278   XrmDatabase
9279     preferences_database;
9280
9281   /*
9282     Save user preferences to the client configuration file.
9283   */
9284   assert(resource_info != (XResourceInfo *) NULL);
9285   client_name=GetClientName();
9286   preferences_database=XrmGetStringDatabase("");
9287   (void) FormatMagickString(specifier,MaxTextExtent,"%s.backdrop",client_name);
9288   value=resource_info->backdrop ? "True" : "False";
9289   XrmPutStringResource(&preferences_database,specifier,(char *) value);
9290   (void) FormatMagickString(specifier,MaxTextExtent,"%s.colormap",client_name);
9291   value=resource_info->colormap == SharedColormap ? "Shared" : "Private";
9292   XrmPutStringResource(&preferences_database,specifier,(char *) value);
9293   (void) FormatMagickString(specifier,MaxTextExtent,"%s.confirmExit",
9294     client_name);
9295   value=resource_info->confirm_exit ? "True" : "False";
9296   XrmPutStringResource(&preferences_database,specifier,(char *) value);
9297   (void) FormatMagickString(specifier,MaxTextExtent,"%s.confirmEdit",
9298     client_name);
9299   value=resource_info->confirm_edit ? "True" : "False";
9300   XrmPutStringResource(&preferences_database,specifier,(char *) value);
9301   (void) FormatMagickString(specifier,MaxTextExtent,"%s.displayWarnings",
9302     client_name);
9303   value=resource_info->display_warnings ? "True" : "False";
9304   XrmPutStringResource(&preferences_database,specifier,(char *) value);
9305   (void) FormatMagickString(specifier,MaxTextExtent,"%s.dither",client_name);
9306   value=resource_info->quantize_info->dither ? "True" : "False";
9307   XrmPutStringResource(&preferences_database,specifier,(char *) value);
9308   (void) FormatMagickString(specifier,MaxTextExtent,"%s.gammaCorrect",
9309     client_name);
9310   value=resource_info->gamma_correct ? "True" : "False";
9311   XrmPutStringResource(&preferences_database,specifier,(char *) value);
9312   (void) FormatMagickString(specifier,MaxTextExtent,"%s.undoCache",client_name);
9313   (void) FormatMagickString(cache,MaxTextExtent,"%.20g",(double)
9314     resource_info->undo_cache);
9315   XrmPutStringResource(&preferences_database,specifier,cache);
9316   (void) FormatMagickString(specifier,MaxTextExtent,"%s.usePixmap",client_name);
9317   value=resource_info->use_pixmap ? "True" : "False";
9318   XrmPutStringResource(&preferences_database,specifier,(char *) value);
9319   (void) FormatMagickString(filename,MaxTextExtent,"%s%src",
9320     X11_PREFERENCES_PATH,client_name);
9321   ExpandFilename(filename);
9322   XrmPutFileDatabase(preferences_database,filename);
9323 #endif
9324 }
9325 \f
9326 /*
9327 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9328 %                                                                             %
9329 %                                                                             %
9330 %                                                                             %
9331 %   X V i s u a l C l a s s N a m e                                           %
9332 %                                                                             %
9333 %                                                                             %
9334 %                                                                             %
9335 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9336 %
9337 %  XVisualClassName() returns the visual class name as a character string.
9338 %
9339 %  The format of the XVisualClassName method is:
9340 %
9341 %      char *XVisualClassName(const int visual_class)
9342 %
9343 %  A description of each parameter follows:
9344 %
9345 %    o visual_type: XVisualClassName returns the visual class as a character
9346 %      string.
9347 %
9348 %    o class: Specifies the visual class.
9349 %
9350 */
9351 static const char *XVisualClassName(const int visual_class)
9352 {
9353   switch (visual_class)
9354   {
9355     case StaticGray: return("StaticGray");
9356     case GrayScale: return("GrayScale");
9357     case StaticColor: return("StaticColor");
9358     case PseudoColor: return("PseudoColor");
9359     case TrueColor: return("TrueColor");
9360     case DirectColor: return("DirectColor");
9361   }
9362   return("unknown visual class");
9363 }
9364 \f
9365 /*
9366 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9367 %                                                                             %
9368 %                                                                             %
9369 %                                                                             %
9370 %   X W a r n i n g                                                           %
9371 %                                                                             %
9372 %                                                                             %
9373 %                                                                             %
9374 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9375 %
9376 %  XWarning() displays a warning reason in a Notice widget.
9377 %
9378 %  The format of the XWarning method is:
9379 %
9380 %      void XWarning(const unsigned int warning,const char *reason,
9381 %        const char *description)
9382 %
9383 %  A description of each parameter follows:
9384 %
9385 %    o warning: Specifies the numeric warning category.
9386 %
9387 %    o reason: Specifies the reason to display before terminating the
9388 %      program.
9389 %
9390 %    o description: Specifies any description to the reason.
9391 %
9392 */
9393 MagickExport void XWarning(const ExceptionType magick_unused(warning),
9394   const char *reason,const char *description)
9395 {
9396   char
9397     text[MaxTextExtent];
9398
9399   XWindows
9400     *windows;
9401
9402   if (reason == (char *) NULL)
9403     return;
9404   (void) CopyMagickString(text,reason,MaxTextExtent);
9405   (void) ConcatenateMagickString(text,":",MaxTextExtent);
9406   windows=XSetWindows((XWindows *) ~0);
9407   XNoticeWidget(windows->display,windows,text,(char *) description);
9408 }
9409 \f
9410 /*
9411 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9412 %                                                                             %
9413 %                                                                             %
9414 %                                                                             %
9415 %   X W i n d o w B y I D                                                     %
9416 %                                                                             %
9417 %                                                                             %
9418 %                                                                             %
9419 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9420 %
9421 %  XWindowByID() locates a child window with a given ID.  If not window with
9422 %  the given name is found, 0 is returned.   Only the window specified and its
9423 %  subwindows are searched.
9424 %
9425 %  The format of the XWindowByID function is:
9426 %
9427 %      child=XWindowByID(display,window,id)
9428 %
9429 %  A description of each parameter follows:
9430 %
9431 %    o child: XWindowByID returns the window with the specified
9432 %      id.  If no windows are found, XWindowByID returns 0.
9433 %
9434 %    o display: Specifies a pointer to the Display structure;  returned from
9435 %      XOpenDisplay.
9436 %
9437 %    o id: Specifies the id of the window to locate.
9438 %
9439 */
9440 MagickExport Window XWindowByID(Display *display,const Window root_window,
9441   const size_t id)
9442 {
9443   RectangleInfo
9444     rectangle_info;
9445
9446   register int
9447     i;
9448
9449   Status
9450     status;
9451
9452   unsigned int
9453     number_children;
9454
9455   Window
9456     child,
9457     *children,
9458     window;
9459
9460   (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
9461   assert(display != (Display *) NULL);
9462   assert(root_window != (Window) NULL);
9463   if (id == 0)
9464     return(XSelectWindow(display,&rectangle_info));
9465   if (root_window == id)
9466     return(root_window);
9467   status=XQueryTree(display,root_window,&child,&child,&children,
9468     &number_children);
9469   if (status == False)
9470     return((Window) NULL);
9471   window=(Window) NULL;
9472   for (i=0; i < (int) number_children; i++)
9473   {
9474     /*
9475       Search each child and their children.
9476     */
9477     window=XWindowByID(display,children[i],id);
9478     if (window != (Window) NULL)
9479       break;
9480   }
9481   if (children != (Window *) NULL)
9482     (void) XFree((void *) children);
9483   return(window);
9484 }
9485 \f
9486 /*
9487 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9488 %                                                                             %
9489 %                                                                             %
9490 %                                                                             %
9491 %   X W i n d o w B y N a m e                                                 %
9492 %                                                                             %
9493 %                                                                             %
9494 %                                                                             %
9495 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9496 %
9497 %  XWindowByName() locates a window with a given name on a display.  If no
9498 %  window with the given name is found, 0 is returned. If more than one window
9499 %  has the given name, the first one is returned.  Only root and its children
9500 %  are searched.
9501 %
9502 %  The format of the XWindowByName function is:
9503 %
9504 %      window=XWindowByName(display,root_window,name)
9505 %
9506 %  A description of each parameter follows:
9507 %
9508 %    o window: XWindowByName returns the window id.
9509 %
9510 %    o display: Specifies a pointer to the Display structure;  returned from
9511 %      XOpenDisplay.
9512 %
9513 %    o root_window: Specifies the id of the root window.
9514 %
9515 %    o name: Specifies the name of the window to locate.
9516 %
9517 */
9518 MagickExport Window XWindowByName(Display *display,const Window root_window,
9519   const char *name)
9520 {
9521   register int
9522     i;
9523
9524   Status
9525     status;
9526
9527   unsigned int
9528     number_children;
9529
9530   Window
9531     *children,
9532     child,
9533     window;
9534
9535   XTextProperty
9536     window_name;
9537
9538   assert(display != (Display *) NULL);
9539   assert(root_window != (Window) NULL);
9540   assert(name != (char *) NULL);
9541   (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",name);
9542   if (XGetWMName(display,root_window,&window_name) != 0)
9543     if (LocaleCompare((char *) window_name.value,name) == 0)
9544       return(root_window);
9545   status=XQueryTree(display,root_window,&child,&child,&children,
9546     &number_children);
9547   if (status == False)
9548     return((Window) NULL);
9549   window=(Window) NULL;
9550   for (i=0; i < (int) number_children; i++)
9551   {
9552     /*
9553       Search each child and their children.
9554     */
9555     window=XWindowByName(display,children[i],name);
9556     if (window != (Window) NULL)
9557       break;
9558   }
9559   if (children != (Window *) NULL)
9560     (void) XFree((void *) children);
9561   return(window);
9562 }
9563 \f
9564 /*
9565 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9566 %                                                                             %
9567 %                                                                             %
9568 %                                                                             %
9569 %   X W i n d o w B y P r o p e r y                                           %
9570 %                                                                             %
9571 %                                                                             %
9572 %                                                                             %
9573 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9574 %
9575 %  XWindowByProperty() locates a child window with a given property. If not
9576 %  window with the given name is found, 0 is returned.  If more than one window
9577 %  has the given property, the first one is returned.  Only the window
9578 %  specified and its subwindows are searched.
9579 %
9580 %  The format of the XWindowByProperty function is:
9581 %
9582 %      child=XWindowByProperty(display,window,property)
9583 %
9584 %  A description of each parameter follows:
9585 %
9586 %    o child: XWindowByProperty returns the window id with the specified
9587 %      property.  If no windows are found, XWindowByProperty returns 0.
9588 %
9589 %    o display: Specifies a pointer to the Display structure;  returned from
9590 %      XOpenDisplay.
9591 %
9592 %    o property: Specifies the property of the window to locate.
9593 %
9594 */
9595 MagickExport Window XWindowByProperty(Display *display,const Window window,
9596   const Atom property)
9597 {
9598   Atom
9599     type;
9600
9601   int
9602     format;
9603
9604   Status
9605     status;
9606
9607   unsigned char
9608     *data;
9609
9610   unsigned int
9611     i,
9612     number_children;
9613
9614   unsigned long
9615     after,
9616     number_items;
9617
9618   Window
9619     child,
9620     *children,
9621     parent,
9622     root;
9623
9624   (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
9625   assert(display != (Display *) NULL);
9626   assert(window != (Window) NULL);
9627   assert(property != (Atom) NULL);
9628   status=XQueryTree(display,window,&root,&parent,&children,&number_children);
9629   if (status == False)
9630     return((Window) NULL);
9631   type=(Atom) NULL;
9632   child=(Window) NULL;
9633   for (i=0; (i < number_children) && (child == (Window) NULL); i++)
9634   {
9635     status=XGetWindowProperty(display,children[i],property,0L,0L,MagickFalse,
9636       (Atom) AnyPropertyType,&type,&format,&number_items,&after,&data);
9637     if (data != NULL)
9638       (void) XFree((void *) data);
9639     if ((status == Success) && (type != (Atom) NULL))
9640       child=children[i];
9641   }
9642   for (i=0; (i < number_children) && (child == (Window) NULL); i++)
9643     child=XWindowByProperty(display,children[i],property);
9644   if (children != (Window *) NULL)
9645     (void) XFree((void *) children);
9646   return(child);
9647 }
9648 #else
9649 \f
9650 /*
9651 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9652 %                                                                             %
9653 %                                                                             %
9654 %                                                                             %
9655 %   X I m p o r t I m a g e                                                   %
9656 %                                                                             %
9657 %                                                                             %
9658 %                                                                             %
9659 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9660 %
9661 %  XImportImage() reads an image from an X window.
9662 %
9663 %  The format of the XImportImage method is:
9664 %
9665 %      Image *XImportImage(const ImageInfo *image_info,XImportInfo *ximage_info)
9666 %
9667 %  A description of each parameter follows:
9668 %
9669 %    o image_info: the image info..
9670 %
9671 %    o ximage_info: Specifies a pointer to an XImportInfo structure.
9672 %
9673 */
9674 MagickExport Image *XImportImage(const ImageInfo *image_info,
9675   XImportInfo *ximage_info)
9676 {
9677   assert(image_info != (const ImageInfo *) NULL);
9678   assert(image_info->signature == MagickSignature);
9679   if (image_info->debug != MagickFalse)
9680     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
9681       image_info->filename);
9682   assert(ximage_info != (XImportInfo *) NULL);
9683   return((Image *) NULL);
9684 }
9685 #endif
9686 \f
9687 /*
9688 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9689 %                                                                             %
9690 %                                                                             %
9691 %                                                                             %
9692 +   X C o m p o n e n t G e n e s i s                                         %
9693 %                                                                             %
9694 %                                                                             %
9695 %                                                                             %
9696 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9697 %
9698 %  XComponentGenesis() instantiates the X component.
9699 %
9700 %  The format of the XComponentGenesis method is:
9701 %
9702 %      MagickBooleanType XComponentGenesis(void)
9703 %
9704 */
9705 MagickExport MagickBooleanType XComponentGenesis(void)
9706 {
9707   return(MagickTrue);
9708 }
9709 \f
9710 /*
9711 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9712 %                                                                             %
9713 %                                                                             %
9714 %                                                                             %
9715 %   X G e t I m p o r t I n f o                                               %
9716 %                                                                             %
9717 %                                                                             %
9718 %                                                                             %
9719 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9720 %
9721 %  XGetImportInfo() initializes the XImportInfo structure.
9722 %
9723 %  The format of the XGetImportInfo method is:
9724 %
9725 %      void XGetImportInfo(XImportInfo *ximage_info)
9726 %
9727 %  A description of each parameter follows:
9728 %
9729 %    o ximage_info: Specifies a pointer to an ImageInfo structure.
9730 %
9731 */
9732 MagickExport void XGetImportInfo(XImportInfo *ximage_info)
9733 {
9734   assert(ximage_info != (XImportInfo *) NULL);
9735   ximage_info->frame=MagickFalse;
9736   ximage_info->borders=MagickFalse;
9737   ximage_info->screen=MagickFalse;
9738   ximage_info->descend=MagickTrue;
9739   ximage_info->silent=MagickFalse;
9740 }