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