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