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