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