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