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