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