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