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