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