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