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