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