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