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