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