]> 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 == 0)
7167     magnify=1;
7168   if (magnify != previous_magnify)
7169     {
7170       Status
7171         status;
7172
7173       XTextProperty
7174         window_name;
7175
7176       /*
7177         New magnify factor:  update magnify window name.
7178       */
7179       i=0;
7180       while ((1 << i) <= (int) magnify)
7181         i++;
7182       (void) FormatLocaleString(windows->magnify.name,MaxTextExtent,
7183         "Magnify %.20gX",(double) i);
7184       status=XStringListToTextProperty(&windows->magnify.name,1,&window_name);
7185       if (status != False)
7186         {
7187           XSetWMName(display,windows->magnify.id,&window_name);
7188           XSetWMIconName(display,windows->magnify.id,&window_name);
7189           (void) XFree((void *) window_name.value);
7190         }
7191     }
7192   previous_magnify=magnify;
7193   ximage=windows->image.ximage;
7194   width=(unsigned int) windows->magnify.ximage->width;
7195   height=(unsigned int) windows->magnify.ximage->height;
7196   if ((windows->magnify.x < 0) ||
7197       (windows->magnify.x >= windows->image.ximage->width))
7198     windows->magnify.x=windows->image.ximage->width >> 1;
7199   x=windows->magnify.x-((width/magnify) >> 1);
7200   if (x < 0)
7201     x=0;
7202   else
7203     if (x > (int) (ximage->width-(width/magnify)))
7204       x=ximage->width-width/magnify;
7205   if ((windows->magnify.y < 0) ||
7206       (windows->magnify.y >= windows->image.ximage->height))
7207     windows->magnify.y=windows->image.ximage->height >> 1;
7208   y=windows->magnify.y-((height/magnify) >> 1);
7209   if (y < 0)
7210     y=0;
7211   else
7212     if (y > (int) (ximage->height-(height/magnify)))
7213       y=ximage->height-height/magnify;
7214   q=(unsigned char *) windows->magnify.ximage->data;
7215   scanline_pad=(unsigned int) (windows->magnify.ximage->bytes_per_line-
7216     ((width*windows->magnify.ximage->bits_per_pixel) >> 3));
7217   if (ximage->bits_per_pixel < 8)
7218     {
7219       register unsigned char
7220         background,
7221         byte,
7222         foreground,
7223         p_bit,
7224         q_bit;
7225
7226       register unsigned int
7227         plane;
7228
7229       XPixelInfo
7230         *pixel_info;
7231
7232       pixel_info=windows->magnify.pixel_info;
7233       switch (ximage->bitmap_bit_order)
7234       {
7235         case LSBFirst:
7236         {
7237           /*
7238             Magnify little-endian bitmap.
7239           */
7240           background=0x00;
7241           foreground=0x80;
7242           if (ximage->format == XYBitmap)
7243             {
7244               background=(unsigned char)
7245                 (XPixelIntensity(&pixel_info->foreground_color) <
7246                  XPixelIntensity(&pixel_info->background_color) ?  0x80 : 0x00);
7247               foreground=(unsigned char)
7248                 (XPixelIntensity(&pixel_info->background_color) <
7249                  XPixelIntensity(&pixel_info->foreground_color) ?  0x80 : 0x00);
7250               if (windows->magnify.depth > 1)
7251                 Swap(background,foreground);
7252             }
7253           for (i=0; i < (ssize_t) height; i+=magnify)
7254           {
7255             /*
7256               Propogate pixel magnify rows.
7257             */
7258             for (j=0; j < magnify; j++)
7259             {
7260               p=(unsigned char *) ximage->data+y*ximage->bytes_per_line+
7261                 ((x*ximage->bits_per_pixel) >> 3);
7262               p_bit=(unsigned char) (x*ximage->bits_per_pixel) & 0x07;
7263               q_bit=0;
7264               byte=0;
7265               for (k=0; k < width; k+=magnify)
7266               {
7267                 /*
7268                   Propogate pixel magnify columns.
7269                 */
7270                 for (l=0; l < magnify; l++)
7271                 {
7272                   /*
7273                     Propogate each bit plane.
7274                   */
7275                   for (plane=0; (int) plane < ximage->bits_per_pixel; plane++)
7276                   {
7277                     byte>>=1;
7278                     if (*p & (0x01 << (p_bit+plane)))
7279                       byte|=foreground;
7280                     else
7281                       byte|=background;
7282                     q_bit++;
7283                     if (q_bit == 8)
7284                       {
7285                         *q++=byte;
7286                         q_bit=0;
7287                         byte=0;
7288                       }
7289                   }
7290                 }
7291                 p_bit+=ximage->bits_per_pixel;
7292                 if (p_bit == 8)
7293                   {
7294                     p++;
7295                     p_bit=0;
7296                   }
7297                 if (q_bit != 0)
7298                   *q=byte >> (8-q_bit);
7299                 q+=scanline_pad;
7300               }
7301             }
7302             y++;
7303           }
7304           break;
7305         }
7306         case MSBFirst:
7307         default:
7308         {
7309           /*
7310             Magnify big-endian bitmap.
7311           */
7312           background=0x00;
7313           foreground=0x01;
7314           if (ximage->format == XYBitmap)
7315             {
7316               background=(unsigned char)
7317                 (XPixelIntensity(&pixel_info->foreground_color) <
7318                  XPixelIntensity(&pixel_info->background_color) ?  0x01 : 0x00);
7319               foreground=(unsigned char)
7320                 (XPixelIntensity(&pixel_info->background_color) <
7321                  XPixelIntensity(&pixel_info->foreground_color) ?  0x01 : 0x00);
7322               if (windows->magnify.depth > 1)
7323                 Swap(background,foreground);
7324             }
7325           for (i=0; i < (ssize_t) height; i+=magnify)
7326           {
7327             /*
7328               Propogate pixel magnify rows.
7329             */
7330             for (j=0; j < magnify; j++)
7331             {
7332               p=(unsigned char *) ximage->data+y*ximage->bytes_per_line+
7333                 ((x*ximage->bits_per_pixel) >> 3);
7334               p_bit=(unsigned char) (x*ximage->bits_per_pixel) & 0x07;
7335               q_bit=0;
7336               byte=0;
7337               for (k=0; k < width; k+=magnify)
7338               {
7339                 /*
7340                   Propogate pixel magnify columns.
7341                 */
7342                 for (l=0; l < magnify; l++)
7343                 {
7344                   /*
7345                     Propogate each bit plane.
7346                   */
7347                   for (plane=0; (int) plane < ximage->bits_per_pixel; plane++)
7348                   {
7349                     byte<<=1;
7350                     if (*p & (0x80 >> (p_bit+plane)))
7351                       byte|=foreground;
7352                     else
7353                       byte|=background;
7354                     q_bit++;
7355                     if (q_bit == 8)
7356                       {
7357                         *q++=byte;
7358                         q_bit=0;
7359                         byte=0;
7360                       }
7361                   }
7362                 }
7363                 p_bit+=ximage->bits_per_pixel;
7364                 if (p_bit == 8)
7365                   {
7366                     p++;
7367                     p_bit=0;
7368                   }
7369                 if (q_bit != 0)
7370                   *q=byte << (8-q_bit);
7371                 q+=scanline_pad;
7372               }
7373             }
7374             y++;
7375           }
7376           break;
7377         }
7378       }
7379     }
7380   else
7381     switch (ximage->bits_per_pixel)
7382     {
7383       case 6:
7384       case 8:
7385       {
7386         /*
7387           Magnify 8 bit X image.
7388         */
7389         for (i=0; i < (ssize_t) height; i+=magnify)
7390         {
7391           /*
7392             Propogate pixel magnify rows.
7393           */
7394           for (j=0; j < magnify; j++)
7395           {
7396             p=(unsigned char *) ximage->data+y*ximage->bytes_per_line+
7397               ((x*ximage->bits_per_pixel) >> 3);
7398             for (k=0; k < width; k+=magnify)
7399             {
7400               /*
7401                 Propogate pixel magnify columns.
7402               */
7403               for (l=0; l < magnify; l++)
7404                 *q++=(*p);
7405               p++;
7406             }
7407             q+=scanline_pad;
7408           }
7409           y++;
7410         }
7411         break;
7412       }
7413       default:
7414       {
7415         register unsigned int
7416           bytes_per_pixel,
7417           m;
7418
7419         /*
7420           Magnify multi-byte X image.
7421         */
7422         bytes_per_pixel=(unsigned int) ximage->bits_per_pixel >> 3;
7423         for (i=0; i < (ssize_t) height; i+=magnify)
7424         {
7425           /*
7426             Propogate pixel magnify rows.
7427           */
7428           for (j=0; j < magnify; j++)
7429           {
7430             p=(unsigned char *) ximage->data+y*ximage->bytes_per_line+
7431               ((x*ximage->bits_per_pixel) >> 3);
7432             for (k=0; k < width; k+=magnify)
7433             {
7434               /*
7435                 Propogate pixel magnify columns.
7436               */
7437               for (l=0; l < magnify; l++)
7438                 for (m=0; m < bytes_per_pixel; m++)
7439                   *q++=(*(p+m));
7440               p+=bytes_per_pixel;
7441             }
7442             q+=scanline_pad;
7443           }
7444           y++;
7445         }
7446         break;
7447       }
7448     }
7449   /*
7450     Copy X image to magnify pixmap.
7451   */
7452   x=windows->magnify.x-((width/magnify) >> 1);
7453   if (x < 0)
7454     x=(int) ((width >> 1)-windows->magnify.x*magnify);
7455   else
7456     if (x > (int) (ximage->width-(width/magnify)))
7457       x=(int) ((ximage->width-windows->magnify.x)*magnify-(width >> 1));
7458     else
7459       x=0;
7460   y=windows->magnify.y-((height/magnify) >> 1);
7461   if (y < 0)
7462     y=(int) ((height >> 1)-windows->magnify.y*magnify);
7463   else
7464     if (y > (int) (ximage->height-(height/magnify)))
7465       y=(int) ((ximage->height-windows->magnify.y)*magnify-(height >> 1));
7466     else
7467       y=0;
7468   if ((x != 0) || (y != 0))
7469     (void) XFillRectangle(display,windows->magnify.pixmap,
7470       windows->magnify.annotate_context,0,0,width,height);
7471   (void) XPutImage(display,windows->magnify.pixmap,
7472     windows->magnify.annotate_context,windows->magnify.ximage,0,0,x,y,width-x,
7473     height-y);
7474   if ((magnify > 1) && ((magnify <= (width >> 1)) &&
7475       (magnify <= (height >> 1))))
7476     {
7477       RectangleInfo
7478         highlight_info;
7479
7480       /*
7481         Highlight center pixel.
7482       */
7483       highlight_info.x=(ssize_t) windows->magnify.width >> 1;
7484       highlight_info.y=(ssize_t) windows->magnify.height >> 1;
7485       highlight_info.width=magnify;
7486       highlight_info.height=magnify;
7487       (void) XDrawRectangle(display,windows->magnify.pixmap,
7488         windows->magnify.highlight_context,(int) highlight_info.x,
7489         (int) highlight_info.y,(unsigned int) highlight_info.width-1,
7490         (unsigned int) highlight_info.height-1);
7491       if (magnify > 2)
7492         (void) XDrawRectangle(display,windows->magnify.pixmap,
7493           windows->magnify.annotate_context,(int) highlight_info.x+1,
7494           (int) highlight_info.y+1,(unsigned int) highlight_info.width-3,
7495           (unsigned int) highlight_info.height-3);
7496     }
7497   /*
7498     Show center pixel color.
7499   */
7500   (void) GetOneVirtualPixelInfo(windows->image.image,TileVirtualPixelMethod,
7501     (ssize_t) windows->magnify.x,(ssize_t) windows->magnify.y,&pixel,exception);
7502   (void) FormatLocaleString(tuple,MaxTextExtent,"%d,%d: ",
7503     windows->magnify.x,windows->magnify.y);
7504   (void) ConcatenateMagickString(tuple,"(",MaxTextExtent);
7505   ConcatenateColorComponent(&pixel,RedPixelChannel,X11Compliance,tuple);
7506   (void) ConcatenateMagickString(tuple,",",MaxTextExtent);
7507   ConcatenateColorComponent(&pixel,GreenPixelChannel,X11Compliance,tuple);
7508   (void) ConcatenateMagickString(tuple,",",MaxTextExtent);
7509   ConcatenateColorComponent(&pixel,BluePixelChannel,X11Compliance,tuple);
7510   if (pixel.colorspace == CMYKColorspace)
7511     {
7512       (void) ConcatenateMagickString(tuple,",",MaxTextExtent);
7513       ConcatenateColorComponent(&pixel,BlackPixelChannel,X11Compliance,tuple);
7514     }
7515   if (pixel.alpha_trait == BlendPixelTrait)
7516     {
7517       (void) ConcatenateMagickString(tuple,",",MaxTextExtent);
7518       ConcatenateColorComponent(&pixel,AlphaPixelChannel,X11Compliance,tuple);
7519     }
7520   (void) ConcatenateMagickString(tuple,")",MaxTextExtent);
7521   height=(unsigned int) windows->magnify.font_info->ascent+
7522     windows->magnify.font_info->descent;
7523   x=windows->magnify.font_info->max_bounds.width >> 1;
7524   y=windows->magnify.font_info->ascent+(height >> 2);
7525   (void) XDrawImageString(display,windows->magnify.pixmap,
7526     windows->magnify.annotate_context,x,y,tuple,(int) strlen(tuple));
7527   GetColorTuple(&pixel,MagickTrue,tuple);
7528   y+=height;
7529   (void) XDrawImageString(display,windows->magnify.pixmap,
7530     windows->magnify.annotate_context,x,y,tuple,(int) strlen(tuple));
7531   (void) QueryColorname(windows->image.image,&pixel,SVGCompliance,tuple,
7532     exception);
7533   y+=height;
7534   (void) XDrawImageString(display,windows->magnify.pixmap,
7535     windows->magnify.annotate_context,x,y,tuple,(int) strlen(tuple));
7536   /*
7537     Refresh magnify window.
7538   */
7539   magnify_window=windows->magnify;
7540   magnify_window.x=0;
7541   magnify_window.y=0;
7542   XRefreshWindow(display,&magnify_window,(XEvent *) NULL);
7543 }
7544 \f
7545 /*
7546 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
7547 %                                                                             %
7548 %                                                                             %
7549 %                                                                             %
7550 %   X M a k e P i x m a p                                                     %
7551 %                                                                             %
7552 %                                                                             %
7553 %                                                                             %
7554 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
7555 %
7556 %  XMakePixmap() creates an X11 pixmap.
7557 %
7558 %  The format of the XMakePixmap method is:
7559 %
7560 %      void XMakeStandardColormap(Display *display,XVisualInfo *visual_info,
7561 %        XResourceInfo *resource_info,Image *image,XStandardColormap *map_info,
7562 %        XPixelInfo *pixel)
7563 %
7564 %  A description of each parameter follows:
7565 %
7566 %    o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
7567 %
7568 %    o display: Specifies a connection to an X server; returned from
7569 %      XOpenDisplay.
7570 %
7571 %    o window: Specifies a pointer to a XWindowInfo structure.
7572 %
7573 */
7574 static MagickBooleanType XMakePixmap(Display *display,
7575   const XResourceInfo *resource_info,XWindowInfo *window)
7576 {
7577   unsigned int
7578     height,
7579     width;
7580
7581   (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
7582   assert(display != (Display *) NULL);
7583   assert(resource_info != (XResourceInfo *) NULL);
7584   assert(window != (XWindowInfo  *) NULL);
7585   if (window->pixmap != (Pixmap) NULL)
7586     {
7587       /*
7588         Destroy previous X pixmap.
7589       */
7590       (void) XFreePixmap(display,window->pixmap);
7591       window->pixmap=(Pixmap) NULL;
7592     }
7593   if (window->use_pixmap == MagickFalse)
7594     return(MagickFalse);
7595   if (window->ximage == (XImage *) NULL)
7596     return(MagickFalse);
7597   /*
7598     Display busy cursor.
7599   */
7600   (void) XCheckDefineCursor(display,window->id,window->busy_cursor);
7601   (void) XFlush(display);
7602   /*
7603     Create pixmap.
7604   */
7605   width=(unsigned int) window->ximage->width;
7606   height=(unsigned int) window->ximage->height;
7607   window->pixmap=XCreatePixmap(display,window->id,width,height,window->depth);
7608   if (window->pixmap == (Pixmap) NULL)
7609     {
7610       /*
7611         Unable to allocate pixmap.
7612       */
7613       (void) XCheckDefineCursor(display,window->id,window->cursor);
7614       return(MagickFalse);
7615     }
7616   /*
7617     Copy X image to pixmap.
7618   */
7619 #if defined(MAGICKCORE_HAVE_SHARED_MEMORY)
7620   if (window->shared_memory)
7621     (void) XShmPutImage(display,window->pixmap,window->annotate_context,
7622       window->ximage,0,0,0,0,width,height,MagickTrue);
7623 #endif
7624   if (window->shared_memory == MagickFalse)
7625     (void) XPutImage(display,window->pixmap,window->annotate_context,
7626       window->ximage,0,0,0,0,width,height);
7627   if (IsEventLogging())
7628     {
7629       (void) LogMagickEvent(X11Event,GetMagickModule(),"Pixmap:");
7630       (void) LogMagickEvent(X11Event,GetMagickModule(),"  width, height: %ux%u",
7631         width,height);
7632     }
7633   /*
7634     Restore cursor.
7635   */
7636   (void) XCheckDefineCursor(display,window->id,window->cursor);
7637   return(MagickTrue);
7638 }
7639 \f
7640 /*
7641 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
7642 %                                                                             %
7643 %                                                                             %
7644 %                                                                             %
7645 %   X M a k e S t a n d a r d C o l o r m a p                                 %
7646 %                                                                             %
7647 %                                                                             %
7648 %                                                                             %
7649 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
7650 %
7651 %  XMakeStandardColormap() creates an X11 Standard Colormap.
7652 %
7653 %  The format of the XMakeStandardColormap method is:
7654 %
7655 %      void XMakeStandardColormap(Display *display,XVisualInfo *visual_info,
7656 %        XResourceInfo *resource_info,Image *image,XStandardColormap *map_info,
7657 %        XPixelInfo *pixel,ExceptionInfo *exception)
7658 %
7659 %  A description of each parameter follows:
7660 %
7661 %    o display: Specifies a connection to an X server; returned from
7662 %      XOpenDisplay.
7663 %
7664 %    o visual_info: Specifies a pointer to a X11 XVisualInfo structure;
7665 %      returned from XGetVisualInfo.
7666 %
7667 %    o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
7668 %
7669 %    o image: the image.
7670 %
7671 %    o map_info: If a Standard Colormap type is specified, this structure is
7672 %      initialized with info from the Standard Colormap.
7673 %
7674 %    o pixel: Specifies a pointer to a XPixelInfo structure.
7675 %
7676 %    o exception: return any errors or warnings in this structure.
7677 %
7678 */
7679
7680 #if defined(__cplusplus) || defined(c_plusplus)
7681 extern "C" {
7682 #endif
7683
7684 static inline double DiversityPixelIntensity(
7685   const DiversityPacket *pixel)
7686 {
7687   double
7688     intensity;
7689
7690   intensity=0.212656*pixel->red+0.715158*pixel->green+0.072186*pixel->blue;
7691   return(intensity);
7692 }
7693
7694 static int IntensityCompare(const void *x,const void *y)
7695 {
7696   DiversityPacket
7697     *color_1,
7698     *color_2;
7699
7700   int
7701     diversity;
7702
7703   color_1=(DiversityPacket *) x;
7704   color_2=(DiversityPacket *) y;
7705   diversity=(int) (DiversityPixelIntensity(color_2)-
7706     DiversityPixelIntensity(color_1));
7707   return(diversity);
7708 }
7709
7710 static int PopularityCompare(const void *x,const void *y)
7711 {
7712   DiversityPacket
7713     *color_1,
7714     *color_2;
7715
7716   color_1=(DiversityPacket *) x;
7717   color_2=(DiversityPacket *) y;
7718   return((int) color_2->count-(int) color_1->count);
7719 }
7720
7721 #if defined(__cplusplus) || defined(c_plusplus)
7722 }
7723 #endif
7724
7725 static inline Quantum ScaleXToQuantum(const size_t x,
7726   const size_t scale)
7727 {
7728   return((Quantum) (((double) QuantumRange*x)/scale+0.5));
7729 }
7730
7731 MagickPrivate void XMakeStandardColormap(Display *display,
7732   XVisualInfo *visual_info,XResourceInfo *resource_info,Image *image,
7733   XStandardColormap *map_info,XPixelInfo *pixel,ExceptionInfo *exception)
7734 {
7735   Colormap
7736     colormap;
7737
7738   register ssize_t
7739     i;
7740
7741   Status
7742     status;
7743
7744   size_t
7745     number_colors,
7746     retain_colors;
7747
7748   unsigned short
7749     gray_value;
7750
7751   XColor
7752     color,
7753     *colors,
7754     *p;
7755
7756   (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
7757   assert(display != (Display *) NULL);
7758   assert(visual_info != (XVisualInfo *) NULL);
7759   assert(map_info != (XStandardColormap *) NULL);
7760   assert(resource_info != (XResourceInfo *) NULL);
7761   assert(pixel != (XPixelInfo *) NULL);
7762   if (resource_info->map_type != (char *) NULL)
7763     {
7764       /*
7765         Standard Colormap is already defined (i.e. xstdcmap).
7766       */
7767       XGetPixelInfo(display,visual_info,map_info,resource_info,image,
7768         pixel);
7769       number_colors=(unsigned int) (map_info->base_pixel+
7770         (map_info->red_max+1)*(map_info->green_max+1)*(map_info->blue_max+1));
7771       if ((map_info->red_max*map_info->green_max*map_info->blue_max) != 0)
7772         if ((image->alpha_trait != BlendPixelTrait) &&
7773             (resource_info->color_recovery == MagickFalse) &&
7774             (resource_info->quantize_info->dither_method != NoDitherMethod) &&
7775             (number_colors < MaxColormapSize))
7776           {
7777             Image
7778               *affinity_image;
7779
7780             register Quantum
7781               *restrict q;
7782
7783             /*
7784               Improve image appearance with error diffusion.
7785             */
7786             affinity_image=AcquireImage((ImageInfo *) NULL,exception);
7787             if (affinity_image == (Image *) NULL)
7788               ThrowXWindowFatalException(ResourceLimitFatalError,
7789                 "UnableToDitherImage",image->filename);
7790             affinity_image->columns=number_colors;
7791             affinity_image->rows=1;
7792             /*
7793               Initialize colormap image.
7794             */
7795             q=QueueAuthenticPixels(affinity_image,0,0,affinity_image->columns,
7796               1,exception);
7797             if (q != (Quantum *) NULL)
7798               {
7799                 for (i=0; i < (ssize_t) number_colors; i++)
7800                 {
7801                   SetPixelRed(affinity_image,0,q);
7802                   if (map_info->red_max != 0)
7803                     SetPixelRed(affinity_image,ScaleXToQuantum((size_t)
7804                       (i/map_info->red_mult),map_info->red_max),q);
7805                   SetPixelGreen(affinity_image,0,q);
7806                   if (map_info->green_max != 0)
7807                     SetPixelGreen(affinity_image,ScaleXToQuantum((size_t)
7808                       ((i/map_info->green_mult) % (map_info->green_max+1)),
7809                       map_info->green_max),q);
7810                   SetPixelBlue(affinity_image,0,q);
7811                   if (map_info->blue_max != 0)
7812                     SetPixelBlue(affinity_image,ScaleXToQuantum((size_t)
7813                       (i % map_info->green_mult),map_info->blue_max),q);
7814                   SetPixelAlpha(affinity_image,
7815                     TransparentAlpha,q);
7816                   q+=GetPixelChannels(affinity_image);
7817                 }
7818                 (void) SyncAuthenticPixels(affinity_image,exception);
7819                 (void) RemapImage(resource_info->quantize_info,image,
7820                   affinity_image,exception);
7821               }
7822             XGetPixelInfo(display,visual_info,map_info,resource_info,image,
7823               pixel);
7824             (void) SetImageStorageClass(image,DirectClass,exception);
7825             affinity_image=DestroyImage(affinity_image);
7826           }
7827       if (IsEventLogging())
7828         {
7829           (void) LogMagickEvent(X11Event,GetMagickModule(),
7830             "Standard Colormap:");
7831           (void) LogMagickEvent(X11Event,GetMagickModule(),
7832             "  colormap id: 0x%lx",map_info->colormap);
7833           (void) LogMagickEvent(X11Event,GetMagickModule(),
7834             "  red, green, blue max: %lu %lu %lu",map_info->red_max,
7835             map_info->green_max,map_info->blue_max);
7836           (void) LogMagickEvent(X11Event,GetMagickModule(),
7837             "  red, green, blue mult: %lu %lu %lu",map_info->red_mult,
7838             map_info->green_mult,map_info->blue_mult);
7839         }
7840       return;
7841     }
7842   if ((visual_info->klass != DirectColor) &&
7843       (visual_info->klass != TrueColor))
7844     if ((image->storage_class == DirectClass) ||
7845         ((int) image->colors > visual_info->colormap_size))
7846       {
7847         QuantizeInfo
7848           quantize_info;
7849
7850         /*
7851           Image has more colors than the visual supports.
7852         */
7853         quantize_info=(*resource_info->quantize_info);
7854         quantize_info.number_colors=(size_t) visual_info->colormap_size;
7855         (void) QuantizeImage(&quantize_info,image,exception);
7856       }
7857   /*
7858     Free previous and create new colormap.
7859   */
7860   (void) XFreeStandardColormap(display,visual_info,map_info,pixel);
7861   colormap=XDefaultColormap(display,visual_info->screen);
7862   if (visual_info->visual != XDefaultVisual(display,visual_info->screen))
7863     colormap=XCreateColormap(display,XRootWindow(display,visual_info->screen),
7864       visual_info->visual,visual_info->klass == DirectColor ?
7865       AllocAll : AllocNone);
7866   if (colormap == (Colormap) NULL)
7867     ThrowXWindowFatalException(ResourceLimitFatalError,"UnableToCreateColormap",
7868       image->filename);
7869   /*
7870     Initialize the map and pixel info structures.
7871   */
7872   XGetMapInfo(visual_info,colormap,map_info);
7873   XGetPixelInfo(display,visual_info,map_info,resource_info,image,pixel);
7874   /*
7875     Allocating colors in server colormap is based on visual class.
7876   */
7877   switch (visual_info->klass)
7878   {
7879     case StaticGray:
7880     case StaticColor:
7881     {
7882       /*
7883         Define Standard Colormap for StaticGray or StaticColor visual.
7884       */
7885       number_colors=image->colors;
7886       colors=(XColor *) AcquireQuantumMemory((size_t)
7887         visual_info->colormap_size,sizeof(*colors));
7888       if (colors == (XColor *) NULL)
7889         ThrowXWindowFatalException(ResourceLimitFatalError,
7890           "UnableToCreateColormap",image->filename);
7891       p=colors;
7892       color.flags=(char) (DoRed | DoGreen | DoBlue);
7893       for (i=0; i < (ssize_t) image->colors; i++)
7894       {
7895         color.red=ScaleQuantumToShort(XRedGamma(image->colormap[i].red));
7896         color.green=ScaleQuantumToShort(XGreenGamma(image->colormap[i].green));
7897         color.blue=ScaleQuantumToShort(XBlueGamma(image->colormap[i].blue));
7898         if (visual_info->klass != StaticColor)
7899           {
7900             gray_value=(unsigned short) XPixelIntensity(&color);
7901             color.red=gray_value;
7902             color.green=gray_value;
7903             color.blue=gray_value;
7904           }
7905         status=XAllocColor(display,colormap,&color);
7906         if (status == False)
7907           {
7908             colormap=XCopyColormapAndFree(display,colormap);
7909             (void) XAllocColor(display,colormap,&color);
7910           }
7911         pixel->pixels[i]=color.pixel;
7912         *p++=color;
7913       }
7914       break;
7915     }
7916     case GrayScale:
7917     case PseudoColor:
7918     {
7919       unsigned int
7920         colormap_type;
7921
7922       /*
7923         Define Standard Colormap for GrayScale or PseudoColor visual.
7924       */
7925       number_colors=image->colors;
7926       colors=(XColor *) AcquireQuantumMemory((size_t)
7927         visual_info->colormap_size,sizeof(*colors));
7928       if (colors == (XColor *) NULL)
7929         ThrowXWindowFatalException(ResourceLimitFatalError,
7930           "UnableToCreateColormap",image->filename);
7931       /*
7932         Preallocate our GUI colors.
7933       */
7934       (void) XAllocColor(display,colormap,&pixel->foreground_color);
7935       (void) XAllocColor(display,colormap,&pixel->background_color);
7936       (void) XAllocColor(display,colormap,&pixel->border_color);
7937       (void) XAllocColor(display,colormap,&pixel->matte_color);
7938       (void) XAllocColor(display,colormap,&pixel->highlight_color);
7939       (void) XAllocColor(display,colormap,&pixel->shadow_color);
7940       (void) XAllocColor(display,colormap,&pixel->depth_color);
7941       (void) XAllocColor(display,colormap,&pixel->trough_color);
7942       for (i=0; i < MaxNumberPens; i++)
7943         (void) XAllocColor(display,colormap,&pixel->pen_colors[i]);
7944       /*
7945         Determine if image colors will "fit" into X server colormap.
7946       */
7947       colormap_type=resource_info->colormap;
7948       status=XAllocColorCells(display,colormap,MagickFalse,(unsigned long *)
7949         NULL,0,pixel->pixels,(unsigned int) image->colors);
7950       if (status != False)
7951         colormap_type=PrivateColormap;
7952       if (colormap_type == SharedColormap)
7953         {
7954           CacheView
7955             *image_view;
7956
7957           DiversityPacket
7958             *diversity;
7959
7960           int
7961             y;
7962
7963           register int
7964             x;
7965
7966           unsigned short
7967             index;
7968
7969           XColor
7970             *server_colors;
7971
7972           /*
7973             Define Standard colormap for shared GrayScale or PseudoColor visual.
7974           */
7975           diversity=(DiversityPacket *) AcquireQuantumMemory(image->colors,
7976             sizeof(*diversity));
7977           if (diversity == (DiversityPacket *) NULL)
7978             ThrowXWindowFatalException(ResourceLimitFatalError,
7979               "UnableToCreateColormap",image->filename);
7980           for (i=0; i < (ssize_t) image->colors; i++)
7981           {
7982             diversity[i].red=ClampToQuantum(image->colormap[i].red);
7983             diversity[i].green=ClampToQuantum(image->colormap[i].green);
7984             diversity[i].blue=ClampToQuantum(image->colormap[i].blue);
7985             diversity[i].index=(unsigned short) i;
7986             diversity[i].count=0;
7987           }
7988           image_view=AcquireAuthenticCacheView(image,exception);
7989           for (y=0; y < (int) image->rows; y++)
7990           {
7991             register int
7992               x;
7993
7994             register const Quantum
7995               *restrict p;
7996
7997             p=GetCacheViewAuthenticPixels(image_view,0,(ssize_t) y,
7998               image->columns,1,exception);
7999             if (p == (const Quantum *) NULL)
8000               break;
8001             for (x=(int) image->columns-1; x >= 0; x--)
8002             {
8003               diversity[(ssize_t) GetPixelIndex(image,p)].count++;
8004               p+=GetPixelChannels(image);
8005             }
8006           }
8007           image_view=DestroyCacheView(image_view);
8008           /*
8009             Sort colors by decreasing intensity.
8010           */
8011           qsort((void *) diversity,image->colors,sizeof(*diversity),
8012             IntensityCompare);
8013           for (i=0; i < (ssize_t) image->colors; )
8014           {
8015             diversity[i].count<<=4;  /* increase this colors popularity */
8016             i+=MagickMax((int) (image->colors >> 4),2);
8017           }
8018           diversity[image->colors-1].count<<=4;
8019           qsort((void *) diversity,image->colors,sizeof(*diversity),
8020             PopularityCompare);
8021           /*
8022             Allocate colors.
8023           */
8024           p=colors;
8025           color.flags=(char) (DoRed | DoGreen | DoBlue);
8026           for (i=0; i < (ssize_t) image->colors; i++)
8027           {
8028             index=diversity[i].index;
8029             color.red=
8030               ScaleQuantumToShort(XRedGamma(image->colormap[index].red));
8031             color.green=
8032               ScaleQuantumToShort(XGreenGamma(image->colormap[index].green));
8033             color.blue=
8034               ScaleQuantumToShort(XBlueGamma(image->colormap[index].blue));
8035             if (visual_info->klass != PseudoColor)
8036               {
8037                 gray_value=(unsigned short) XPixelIntensity(&color);
8038                 color.red=gray_value;
8039                 color.green=gray_value;
8040                 color.blue=gray_value;
8041               }
8042             status=XAllocColor(display,colormap,&color);
8043             if (status == False)
8044               break;
8045             pixel->pixels[index]=color.pixel;
8046             *p++=color;
8047           }
8048           /*
8049             Read X server colormap.
8050           */
8051           server_colors=(XColor *) AcquireQuantumMemory((size_t)
8052             visual_info->colormap_size,sizeof(*server_colors));
8053           if (server_colors == (XColor *) NULL)
8054             ThrowXWindowFatalException(ResourceLimitFatalError,
8055               "UnableToCreateColormap",image->filename);
8056           for (x=visual_info->colormap_size-1; x >= 0; x--)
8057             server_colors[x].pixel=(size_t) x;
8058           (void) XQueryColors(display,colormap,server_colors,
8059             (int) MagickMin((unsigned int) visual_info->colormap_size,256));
8060           /*
8061             Select remaining colors from X server colormap.
8062           */
8063           for (; i < (ssize_t) image->colors; i++)
8064           {
8065             index=diversity[i].index;
8066             color.red=ScaleQuantumToShort(
8067               XRedGamma(image->colormap[index].red));
8068             color.green=ScaleQuantumToShort(
8069               XGreenGamma(image->colormap[index].green));
8070             color.blue=ScaleQuantumToShort(
8071               XBlueGamma(image->colormap[index].blue));
8072             if (visual_info->klass != PseudoColor)
8073               {
8074                 gray_value=(unsigned short) XPixelIntensity(&color);
8075                 color.red=gray_value;
8076                 color.green=gray_value;
8077                 color.blue=gray_value;
8078               }
8079             XBestPixel(display,colormap,server_colors,(unsigned int)
8080               visual_info->colormap_size,&color);
8081             pixel->pixels[index]=color.pixel;
8082             *p++=color;
8083           }
8084           if ((int) image->colors < visual_info->colormap_size)
8085             {
8086               /*
8087                 Fill up colors array-- more choices for pen colors.
8088               */
8089               retain_colors=MagickMin((unsigned int)
8090                (visual_info->colormap_size-image->colors),256);
8091               for (i=0; i < (ssize_t) retain_colors; i++)
8092                 *p++=server_colors[i];
8093               number_colors+=retain_colors;
8094             }
8095           server_colors=(XColor *) RelinquishMagickMemory(server_colors);
8096           diversity=(DiversityPacket *) RelinquishMagickMemory(diversity);
8097           break;
8098         }
8099       /*
8100         Define Standard colormap for private GrayScale or PseudoColor visual.
8101       */
8102       if (status == False)
8103         {
8104           /*
8105             Not enough colormap entries in the colormap-- Create a new colormap.
8106           */
8107           colormap=XCreateColormap(display,
8108             XRootWindow(display,visual_info->screen),visual_info->visual,
8109             AllocNone);
8110           if (colormap == (Colormap) NULL)
8111             ThrowXWindowFatalException(ResourceLimitFatalError,
8112               "UnableToCreateColormap",image->filename);
8113           map_info->colormap=colormap;
8114           if ((int) image->colors < visual_info->colormap_size)
8115             {
8116               /*
8117                 Retain colors from the default colormap to help lessens the
8118                 effects of colormap flashing.
8119               */
8120               retain_colors=MagickMin((unsigned int)
8121                 (visual_info->colormap_size-image->colors),256);
8122               p=colors+image->colors;
8123               for (i=0; i < (ssize_t) retain_colors; i++)
8124               {
8125                 p->pixel=(unsigned long) i;
8126                 p++;
8127               }
8128               (void) XQueryColors(display,
8129                 XDefaultColormap(display,visual_info->screen),
8130                 colors+image->colors,(int) retain_colors);
8131               /*
8132                 Transfer colors from default to private colormap.
8133               */
8134               (void) XAllocColorCells(display,colormap,MagickFalse,
8135                 (unsigned long *) NULL,0,pixel->pixels,(unsigned int)
8136                 retain_colors);
8137               p=colors+image->colors;
8138               for (i=0; i < (ssize_t) retain_colors; i++)
8139               {
8140                 p->pixel=pixel->pixels[i];
8141                 p++;
8142               }
8143               (void) XStoreColors(display,colormap,colors+image->colors,
8144                 (int) retain_colors);
8145               number_colors+=retain_colors;
8146             }
8147           (void) XAllocColorCells(display,colormap,MagickFalse,
8148             (unsigned long *) NULL,0,pixel->pixels,(unsigned int)
8149             image->colors);
8150         }
8151       /*
8152         Store the image colormap.
8153       */
8154       p=colors;
8155       color.flags=(char) (DoRed | DoGreen | DoBlue);
8156       for (i=0; i < (ssize_t) image->colors; i++)
8157       {
8158         color.red=ScaleQuantumToShort(XRedGamma(image->colormap[i].red));
8159         color.green=ScaleQuantumToShort(XGreenGamma(image->colormap[i].green));
8160         color.blue=ScaleQuantumToShort(XBlueGamma(image->colormap[i].blue));
8161         if (visual_info->klass != PseudoColor)
8162           {
8163             gray_value=(unsigned short) XPixelIntensity(&color);
8164             color.red=gray_value;
8165             color.green=gray_value;
8166             color.blue=gray_value;
8167           }
8168         color.pixel=pixel->pixels[i];
8169         *p++=color;
8170       }
8171       (void) XStoreColors(display,colormap,colors,(int) image->colors);
8172       break;
8173     }
8174     case TrueColor:
8175     case DirectColor:
8176     default:
8177     {
8178       MagickBooleanType
8179         linear_colormap;
8180
8181       /*
8182         Define Standard Colormap for TrueColor or DirectColor visual.
8183       */
8184       number_colors=(unsigned int) ((map_info->red_max*map_info->red_mult)+
8185         (map_info->green_max*map_info->green_mult)+
8186         (map_info->blue_max*map_info->blue_mult)+1);
8187       linear_colormap=(number_colors > 4096) ||
8188         (((int) (map_info->red_max+1) == visual_info->colormap_size) &&
8189          ((int) (map_info->green_max+1) == visual_info->colormap_size) &&
8190          ((int) (map_info->blue_max+1) == visual_info->colormap_size)) ?
8191          MagickTrue : MagickFalse;
8192       if (linear_colormap != MagickFalse)
8193         number_colors=(size_t) visual_info->colormap_size;
8194       /*
8195         Allocate color array.
8196       */
8197       colors=(XColor *) AcquireQuantumMemory(number_colors,sizeof(*colors));
8198       if (colors == (XColor *) NULL)
8199         ThrowXWindowFatalException(ResourceLimitFatalError,
8200           "UnableToCreateColormap",image->filename);
8201       /*
8202         Initialize linear color ramp.
8203       */
8204       p=colors;
8205       color.flags=(char) (DoRed | DoGreen | DoBlue);
8206       if (linear_colormap != MagickFalse)
8207         for (i=0; i < (ssize_t) number_colors; i++)
8208         {
8209           color.blue=(unsigned short) 0;
8210           if (map_info->blue_max != 0)
8211             color.blue=(unsigned short) ((size_t)
8212               ((65535L*(i % map_info->green_mult))/map_info->blue_max));
8213           color.green=color.blue;
8214           color.red=color.blue;
8215           color.pixel=XStandardPixel(map_info,&color);
8216           *p++=color;
8217         }
8218       else
8219         for (i=0; i < (ssize_t) number_colors; i++)
8220         {
8221           color.red=(unsigned short) 0;
8222           if (map_info->red_max != 0)
8223             color.red=(unsigned short) ((size_t)
8224               ((65535L*(i/map_info->red_mult))/map_info->red_max));
8225           color.green=(unsigned int) 0;
8226           if (map_info->green_max != 0)
8227             color.green=(unsigned short) ((size_t)
8228               ((65535L*((i/map_info->green_mult) % (map_info->green_max+1)))/
8229                 map_info->green_max));
8230           color.blue=(unsigned short) 0;
8231           if (map_info->blue_max != 0)
8232             color.blue=(unsigned short) ((size_t)
8233               ((65535L*(i % map_info->green_mult))/map_info->blue_max));
8234           color.pixel=XStandardPixel(map_info,&color);
8235           *p++=color;
8236         }
8237       if ((visual_info->klass == DirectColor) &&
8238           (colormap != XDefaultColormap(display,visual_info->screen)))
8239         (void) XStoreColors(display,colormap,colors,(int) number_colors);
8240       else
8241         for (i=0; i < (ssize_t) number_colors; i++)
8242           (void) XAllocColor(display,colormap,&colors[i]);
8243       break;
8244     }
8245   }
8246   if ((visual_info->klass != DirectColor) &&
8247       (visual_info->klass != TrueColor))
8248     {
8249       /*
8250         Set foreground, background, border, etc. pixels.
8251       */
8252       XBestPixel(display,colormap,colors,(unsigned int) number_colors,
8253         &pixel->foreground_color);
8254       XBestPixel(display,colormap,colors,(unsigned int) number_colors,
8255         &pixel->background_color);
8256       if (pixel->background_color.pixel == pixel->foreground_color.pixel)
8257         {
8258           /*
8259             Foreground and background colors must differ.
8260           */
8261           pixel->background_color.red=(~pixel->foreground_color.red);
8262           pixel->background_color.green=
8263             (~pixel->foreground_color.green);
8264           pixel->background_color.blue=
8265             (~pixel->foreground_color.blue);
8266           XBestPixel(display,colormap,colors,(unsigned int) number_colors,
8267             &pixel->background_color);
8268         }
8269       XBestPixel(display,colormap,colors,(unsigned int) number_colors,
8270         &pixel->border_color);
8271       XBestPixel(display,colormap,colors,(unsigned int) number_colors,
8272         &pixel->matte_color);
8273       XBestPixel(display,colormap,colors,(unsigned int) number_colors,
8274         &pixel->highlight_color);
8275       XBestPixel(display,colormap,colors,(unsigned int) number_colors,
8276         &pixel->shadow_color);
8277       XBestPixel(display,colormap,colors,(unsigned int) number_colors,
8278         &pixel->depth_color);
8279       XBestPixel(display,colormap,colors,(unsigned int) number_colors,
8280         &pixel->trough_color);
8281       for (i=0; i < MaxNumberPens; i++)
8282       {
8283         XBestPixel(display,colormap,colors,(unsigned int) number_colors,
8284           &pixel->pen_colors[i]);
8285         pixel->pixels[image->colors+i]=pixel->pen_colors[i].pixel;
8286       }
8287       pixel->colors=(ssize_t) (image->colors+MaxNumberPens);
8288     }
8289   colors=(XColor *) RelinquishMagickMemory(colors);
8290   if (IsEventLogging())
8291     {
8292       (void) LogMagickEvent(X11Event,GetMagickModule(),"Standard Colormap:");
8293       (void) LogMagickEvent(X11Event,GetMagickModule(),"  colormap id: 0x%lx",
8294         map_info->colormap);
8295       (void) LogMagickEvent(X11Event,GetMagickModule(),
8296         "  red, green, blue max: %lu %lu %lu",map_info->red_max,
8297         map_info->green_max,map_info->blue_max);
8298       (void) LogMagickEvent(X11Event,GetMagickModule(),
8299         "  red, green, blue mult: %lu %lu %lu",map_info->red_mult,
8300         map_info->green_mult,map_info->blue_mult);
8301     }
8302 }
8303 \f
8304 /*
8305 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8306 %                                                                             %
8307 %                                                                             %
8308 %                                                                             %
8309 %   X M a k e W i n d o w                                                     %
8310 %                                                                             %
8311 %                                                                             %
8312 %                                                                             %
8313 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8314 %
8315 %  XMakeWindow() creates an X11 window.
8316 %
8317 %  The format of the XMakeWindow method is:
8318 %
8319 %      void XMakeWindow(Display *display,Window parent,char **argv,int argc,
8320 %        XClassHint *class_hint,XWMHints *manager_hints,
8321 %        XWindowInfo *window_info)
8322 %
8323 %  A description of each parameter follows:
8324 %
8325 %    o display: Specifies a connection to an X server; returned from
8326 %      XOpenDisplay.
8327 %
8328 %    o parent: Specifies the parent window_info.
8329 %
8330 %    o argv: Specifies the application's argument list.
8331 %
8332 %    o argc: Specifies the number of arguments.
8333 %
8334 %    o class_hint: Specifies a pointer to a X11 XClassHint structure.
8335 %
8336 %    o manager_hints: Specifies a pointer to a X11 XWMHints structure.
8337 %
8338 %    o window_info: Specifies a pointer to a X11 XWindowInfo structure.
8339 %
8340 */
8341 MagickPrivate void XMakeWindow(Display *display,Window parent,char **argv,
8342   int argc,XClassHint *class_hint,XWMHints *manager_hints,
8343   XWindowInfo *window_info)
8344 {
8345 #define MinWindowSize  64
8346
8347   Atom
8348     atom_list[2];
8349
8350   int
8351     gravity;
8352
8353   static XTextProperty
8354     icon_name,
8355     window_name;
8356
8357   Status
8358     status;
8359
8360   XSizeHints
8361     *size_hints;
8362
8363   /*
8364     Set window info hints.
8365   */
8366   (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
8367   assert(display != (Display *) NULL);
8368   assert(window_info != (XWindowInfo *) NULL);
8369   size_hints=XAllocSizeHints();
8370   if (size_hints == (XSizeHints *) NULL)
8371     ThrowXWindowFatalException(XServerFatalError,"UnableToMakeXWindow",argv[0]);
8372   size_hints->flags=(int) window_info->flags;
8373   size_hints->x=window_info->x;
8374   size_hints->y=window_info->y;
8375   size_hints->width=(int) window_info->width;
8376   size_hints->height=(int) window_info->height;
8377   if (window_info->immutable != MagickFalse)
8378     {
8379       /*
8380         Window size cannot be changed.
8381       */
8382       size_hints->min_width=size_hints->width;
8383       size_hints->min_height=size_hints->height;
8384       size_hints->max_width=size_hints->width;
8385       size_hints->max_height=size_hints->height;
8386       size_hints->flags|=PMinSize;
8387       size_hints->flags|=PMaxSize;
8388     }
8389   else
8390     {
8391       /*
8392         Window size can be changed.
8393       */
8394       size_hints->min_width=(int) window_info->min_width;
8395       size_hints->min_height=(int) window_info->min_height;
8396       size_hints->flags|=PResizeInc;
8397       size_hints->width_inc=(int) window_info->width_inc;
8398       size_hints->height_inc=(int) window_info->height_inc;
8399 #if !defined(PRE_R4_ICCCM)
8400       size_hints->flags|=PBaseSize;
8401       size_hints->base_width=size_hints->width_inc;
8402       size_hints->base_height=size_hints->height_inc;
8403 #endif
8404     }
8405   gravity=NorthWestGravity;
8406   if (window_info->geometry != (char *) NULL)
8407     {
8408       char
8409         default_geometry[MaxTextExtent],
8410         geometry[MaxTextExtent];
8411
8412       int
8413         flags;
8414
8415       register char
8416         *p;
8417
8418       /*
8419         User specified geometry.
8420       */
8421       (void) FormatLocaleString(default_geometry,MaxTextExtent,"%dx%d",
8422         size_hints->width,size_hints->height);
8423       (void) CopyMagickString(geometry,window_info->geometry,MaxTextExtent);
8424       p=geometry;
8425       while (strlen(p) != 0)
8426       {
8427         if ((isspace((int) ((unsigned char) *p)) == 0) && (*p != '%'))
8428           p++;
8429         else
8430           (void) CopyMagickString(p,p+1,MaxTextExtent);
8431       }
8432       flags=XWMGeometry(display,window_info->screen,geometry,default_geometry,
8433         window_info->border_width,size_hints,&size_hints->x,&size_hints->y,
8434         &size_hints->width,&size_hints->height,&gravity);
8435       if ((flags & WidthValue) && (flags & HeightValue))
8436         size_hints->flags|=USSize;
8437       if ((flags & XValue) && (flags & YValue))
8438         {
8439           size_hints->flags|=USPosition;
8440           window_info->x=size_hints->x;
8441           window_info->y=size_hints->y;
8442         }
8443     }
8444 #if !defined(PRE_R4_ICCCM)
8445   size_hints->win_gravity=gravity;
8446   size_hints->flags|=PWinGravity;
8447 #endif
8448   if (window_info->id == (Window) NULL)
8449     window_info->id=XCreateWindow(display,parent,window_info->x,window_info->y,
8450       (unsigned int) size_hints->width,(unsigned int) size_hints->height,
8451       window_info->border_width,(int) window_info->depth,InputOutput,
8452       window_info->visual,(unsigned long) window_info->mask,
8453       &window_info->attributes);
8454   else
8455     {
8456       MagickStatusType
8457         mask;
8458
8459       XEvent
8460         sans_event;
8461
8462       XWindowChanges
8463         window_changes;
8464
8465       /*
8466         Window already exists;  change relevant attributes.
8467       */
8468       (void) XChangeWindowAttributes(display,window_info->id,(unsigned long)
8469         window_info->mask,&window_info->attributes);
8470       mask=ConfigureNotify;
8471       while (XCheckTypedWindowEvent(display,window_info->id,(int) mask,&sans_event)) ;
8472       window_changes.x=window_info->x;
8473       window_changes.y=window_info->y;
8474       window_changes.width=(int) window_info->width;
8475       window_changes.height=(int) window_info->height;
8476       mask=(MagickStatusType) (CWWidth | CWHeight);
8477       if (window_info->flags & USPosition)
8478         mask|=CWX | CWY;
8479       (void) XReconfigureWMWindow(display,window_info->id,window_info->screen,
8480         mask,&window_changes);
8481     }
8482   if (window_info->id == (Window) NULL)
8483     ThrowXWindowFatalException(XServerFatalError,"UnableToCreateWindow",
8484       window_info->name);
8485   status=XStringListToTextProperty(&window_info->name,1,&window_name);
8486   if (status == False)
8487     ThrowXWindowFatalException(XServerFatalError,"UnableToCreateTextProperty",
8488       window_info->name);
8489   status=XStringListToTextProperty(&window_info->icon_name,1,&icon_name);
8490   if (status == False)
8491     ThrowXWindowFatalException(XServerFatalError,"UnableToCreateTextProperty",
8492       window_info->icon_name);
8493   if (window_info->icon_geometry != (char *) NULL)
8494     {
8495       int
8496         flags,
8497         height,
8498         width;
8499
8500       /*
8501         User specified icon geometry.
8502       */
8503       size_hints->flags|=USPosition;
8504       flags=XWMGeometry(display,window_info->screen,window_info->icon_geometry,
8505         (char *) NULL,0,size_hints,&manager_hints->icon_x,
8506         &manager_hints->icon_y,&width,&height,&gravity);
8507       if ((flags & XValue) && (flags & YValue))
8508         manager_hints->flags|=IconPositionHint;
8509     }
8510   XSetWMProperties(display,window_info->id,&window_name,&icon_name,argv,argc,
8511     size_hints,manager_hints,class_hint);
8512   if (window_name.value != (void *) NULL)
8513     {
8514       (void) XFree((void *) window_name.value);
8515       window_name.value=(unsigned char *) NULL;
8516       window_name.nitems=0;
8517     }
8518   if (icon_name.value != (void *) NULL)
8519     {
8520       (void) XFree((void *) icon_name.value);
8521       icon_name.value=(unsigned char *) NULL;
8522       icon_name.nitems=0;
8523     }
8524   atom_list[0]=XInternAtom(display,"WM_DELETE_WINDOW",MagickFalse);
8525   atom_list[1]=XInternAtom(display,"WM_TAKE_FOCUS",MagickFalse);
8526   (void) XSetWMProtocols(display,window_info->id,atom_list,2);
8527   (void) XFree((void *) size_hints);
8528   if (window_info->shape != MagickFalse)
8529     {
8530 #if defined(MAGICKCORE_HAVE_SHAPE)
8531       int
8532         error_base,
8533         event_base;
8534
8535       /*
8536         Can we apply a non-rectangular shaping mask?
8537       */
8538       error_base=0;
8539       event_base=0;
8540       if (XShapeQueryExtension(display,&error_base,&event_base) == 0)
8541         window_info->shape=MagickFalse;
8542 #else
8543       window_info->shape=MagickFalse;
8544 #endif
8545     }
8546   if (window_info->shared_memory)
8547     {
8548 #if defined(MAGICKCORE_HAVE_SHARED_MEMORY)
8549       /*
8550         Can we use shared memory with this window?
8551       */
8552       if (XShmQueryExtension(display) == 0)
8553         window_info->shared_memory=MagickFalse;
8554 #else
8555       window_info->shared_memory=MagickFalse;
8556 #endif
8557     }
8558   window_info->image=NewImageList();
8559   window_info->destroy=MagickFalse;
8560 }
8561 \f
8562 /*
8563 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8564 %                                                                             %
8565 %                                                                             %
8566 %                                                                             %
8567 %   X M a g i c k P r o g r e s s M o n i t o r                               %
8568 %                                                                             %
8569 %                                                                             %
8570 %                                                                             %
8571 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8572 %
8573 %  XMagickProgressMonitor() displays the progress a task is making in
8574 %  completing a task.
8575 %
8576 %  The format of the XMagickProgressMonitor method is:
8577 %
8578 %      void XMagickProgressMonitor(const char *task,
8579 %        const MagickOffsetType quantum,const MagickSizeType span,
8580 %        void *client_data)
8581 %
8582 %  A description of each parameter follows:
8583 %
8584 %    o task: Identifies the task in progress.
8585 %
8586 %    o quantum: Specifies the quantum position within the span which represents
8587 %      how much progress has been made in completing a task.
8588 %
8589 %    o span: Specifies the span relative to completing a task.
8590 %
8591 %    o client_data: Pointer to any client data.
8592 %
8593 */
8594
8595 static const char *GetLocaleMonitorMessage(const char *text)
8596 {
8597   char
8598     message[MaxTextExtent],
8599     tag[MaxTextExtent];
8600
8601   const char
8602     *locale_message;
8603
8604   register char
8605     *p;
8606
8607   (void) CopyMagickMemory(tag,text,MaxTextExtent);
8608   p=strrchr(tag,'/');
8609   if (p != (char *) NULL)
8610     *p='\0';
8611   (void) FormatLocaleString(message,MaxTextExtent,"Monitor/%s",tag);
8612   locale_message=GetLocaleMessage(message);
8613   if (locale_message == message)
8614     return(text);
8615   return(locale_message);
8616 }
8617
8618 MagickPrivate MagickBooleanType XMagickProgressMonitor(const char *tag,
8619   const MagickOffsetType quantum,const MagickSizeType span,
8620   void *magick_unused(client_data))
8621 {
8622   XWindows
8623     *windows;
8624
8625   windows=XSetWindows((XWindows *) ~0);
8626   if (windows == (XWindows *) NULL)
8627     return(MagickTrue);
8628   if (windows->info.mapped != MagickFalse)
8629     XProgressMonitorWidget(windows->display,windows,
8630       GetLocaleMonitorMessage(tag),quantum,span);
8631   return(MagickTrue);
8632 }
8633 \f
8634 /*
8635 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8636 %                                                                             %
8637 %                                                                             %
8638 %                                                                             %
8639 %   X Q u e r y C o l o r D a t a b a s e                                     %
8640 %                                                                             %
8641 %                                                                             %
8642 %                                                                             %
8643 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8644 %
8645 %  XQueryColorCompliance() looks up a RGB values for a color given in the target
8646 %  string.
8647 %
8648 %  The format of the XQueryColorDatabase method is:
8649 %
8650 %      MagickBooleanType XQueryColorCompliance(const char *target,XColor *color)
8651 %
8652 %  A description of each parameter follows:
8653 %
8654 %    o target: Specifies the color to lookup in the X color database.
8655 %
8656 %    o color: A pointer to an PixelInfo structure.  The RGB value of the target
8657 %      color is returned as this value.
8658 %
8659 */
8660 MagickPrivate MagickBooleanType XQueryColorCompliance(const char *target,
8661   XColor *color)
8662 {
8663   Colormap
8664     colormap;
8665
8666   static Display
8667     *display = (Display *) NULL;
8668
8669   Status
8670     status;
8671
8672   XColor
8673     xcolor;
8674
8675   /*
8676     Initialize color return value.
8677   */
8678   assert(color != (XColor *) NULL);
8679   color->red=0;
8680   color->green=0;
8681   color->blue=0;
8682   color->flags=(char) (DoRed | DoGreen | DoBlue);
8683   if ((target == (char *) NULL) || (*target == '\0'))
8684     target="#ffffffffffff";
8685   /*
8686     Let the X server define the color for us.
8687   */
8688   if (display == (Display *) NULL)
8689     display=XOpenDisplay((char *) NULL);
8690   if (display == (Display *) NULL)
8691     {
8692       ThrowXWindowException(XServerError,"ColorIsNotKnownToServer",target);
8693       return(MagickFalse);
8694     }
8695   colormap=XDefaultColormap(display,XDefaultScreen(display));
8696   status=XParseColor(display,colormap,(char *) target,&xcolor);
8697   if (status == False)
8698     ThrowXWindowException(XServerError,"ColorIsNotKnownToServer",target)
8699   else
8700     {
8701       color->red=xcolor.red;
8702       color->green=xcolor.green;
8703       color->blue=xcolor.blue;
8704       color->flags=xcolor.flags;
8705     }
8706   return(status != False ? MagickTrue : MagickFalse);
8707 }
8708 \f
8709 /*
8710 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8711 %                                                                             %
8712 %                                                                             %
8713 %                                                                             %
8714 %   X Q u e r y P o s i t i o n                                               %
8715 %                                                                             %
8716 %                                                                             %
8717 %                                                                             %
8718 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8719 %
8720 %  XQueryPosition() gets the pointer coordinates relative to a window.
8721 %
8722 %  The format of the XQueryPosition method is:
8723 %
8724 %      void XQueryPosition(Display *display,const Window window,int *x,int *y)
8725 %
8726 %  A description of each parameter follows:
8727 %
8728 %    o display: Specifies a connection to an X server;  returned from
8729 %      XOpenDisplay.
8730 %
8731 %    o window: Specifies a pointer to a Window.
8732 %
8733 %    o x: Return the x coordinate of the pointer relative to the origin of the
8734 %      window.
8735 %
8736 %    o y: Return the y coordinate of the pointer relative to the origin of the
8737 %      window.
8738 %
8739 */
8740 MagickPrivate void XQueryPosition(Display *display,const Window window,int *x,
8741   int *y)
8742 {
8743   int
8744     x_root,
8745     y_root;
8746
8747   unsigned int
8748     mask;
8749
8750   Window
8751     root_window;
8752
8753   (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
8754   assert(display != (Display *) NULL);
8755   assert(window != (Window) NULL);
8756   assert(x != (int *) NULL);
8757   assert(y != (int *) NULL);
8758   (void) XQueryPointer(display,window,&root_window,&root_window,&x_root,&y_root,
8759     x,y,&mask);
8760 }
8761 \f
8762 /*
8763 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8764 %                                                                             %
8765 %                                                                             %
8766 %                                                                             %
8767 %   X R e f r e s h W i n d o w                                               %
8768 %                                                                             %
8769 %                                                                             %
8770 %                                                                             %
8771 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8772 %
8773 %  XRefreshWindow() refreshes an image in a X window.
8774 %
8775 %  The format of the XRefreshWindow method is:
8776 %
8777 %      void XRefreshWindow(Display *display,const XWindowInfo *window,
8778 %        const XEvent *event)
8779 %
8780 %  A description of each parameter follows:
8781 %
8782 %    o display: Specifies a connection to an X server;  returned from
8783 %      XOpenDisplay.
8784 %
8785 %    o window: Specifies a pointer to a XWindowInfo structure.
8786 %
8787 %    o event: Specifies a pointer to a XEvent structure.  If it is NULL,
8788 %      the entire image is refreshed.
8789 %
8790 */
8791 MagickPrivate void XRefreshWindow(Display *display,const XWindowInfo *window,
8792   const XEvent *event)
8793 {
8794   int
8795     x,
8796     y;
8797
8798   unsigned int
8799     height,
8800     width;
8801
8802   (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
8803   assert(display != (Display *) NULL);
8804   assert(window != (XWindowInfo *) NULL);
8805   if (window->ximage == (XImage *) NULL)
8806     return;
8807   if (event != (XEvent *) NULL)
8808     {
8809       /*
8810         Determine geometry from expose event.
8811       */
8812       x=event->xexpose.x;
8813       y=event->xexpose.y;
8814       width=(unsigned int) event->xexpose.width;
8815       height=(unsigned int) event->xexpose.height;
8816     }
8817   else
8818     {
8819       XEvent
8820         sans_event;
8821
8822       /*
8823         Refresh entire window; discard outstanding expose events.
8824       */
8825       x=0;
8826       y=0;
8827       width=window->width;
8828       height=window->height;
8829       while (XCheckTypedWindowEvent(display,window->id,Expose,&sans_event)) ;
8830       if (window->matte_pixmap != (Pixmap) NULL)
8831         {
8832 #if defined(MAGICKCORE_HAVE_SHAPE)
8833           if (window->shape != MagickFalse)
8834             XShapeCombineMask(display,window->id,ShapeBounding,0,0,
8835               window->matte_pixmap,ShapeSet);
8836 #endif
8837         }
8838     }
8839   /*
8840     Check boundary conditions.
8841   */
8842   if ((window->ximage->width-(x+window->x)) < (int) width)
8843     width=(unsigned int) (window->ximage->width-(x+window->x));
8844   if ((window->ximage->height-(y+window->y)) < (int) height)
8845     height=(unsigned int) (window->ximage->height-(y+window->y));
8846   /*
8847     Refresh image.
8848   */
8849   if (window->matte_pixmap != (Pixmap) NULL)
8850     (void) XSetClipMask(display,window->annotate_context,window->matte_pixmap);
8851   if (window->pixmap != (Pixmap) NULL)
8852     {
8853       if (window->depth > 1)
8854         (void) XCopyArea(display,window->pixmap,window->id,
8855           window->annotate_context,x+window->x,y+window->y,width,height,x,y);
8856       else
8857         (void) XCopyPlane(display,window->pixmap,window->id,
8858           window->highlight_context,x+window->x,y+window->y,width,height,x,y,
8859           1L);
8860     }
8861   else
8862     {
8863 #if defined(MAGICKCORE_HAVE_SHARED_MEMORY)
8864       if (window->shared_memory)
8865         (void) XShmPutImage(display,window->id,window->annotate_context,
8866           window->ximage,x+window->x,y+window->y,x,y,width,height,MagickTrue);
8867 #endif
8868       if (window->shared_memory == MagickFalse)
8869         (void) XPutImage(display,window->id,window->annotate_context,
8870           window->ximage,x+window->x,y+window->y,x,y,width,height);
8871     }
8872   if (window->matte_pixmap != (Pixmap) NULL)
8873     (void) XSetClipMask(display,window->annotate_context,None);
8874   (void) XFlush(display);
8875 }
8876 \f
8877 /*
8878 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8879 %                                                                             %
8880 %                                                                             %
8881 %                                                                             %
8882 %   X R e m o t e C o m m a n d                                               %
8883 %                                                                             %
8884 %                                                                             %
8885 %                                                                             %
8886 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8887 %
8888 %  XRemoteCommand() forces a remote display(1) to display the specified
8889 %  image filename.
8890 %
8891 %  The format of the XRemoteCommand method is:
8892 %
8893 %      MagickBooleanType XRemoteCommand(Display *display,const char *window,
8894 %        const char *filename)
8895 %
8896 %  A description of each parameter follows:
8897 %
8898 %    o display: Specifies a connection to an X server; returned from
8899 %      XOpenDisplay.
8900 %
8901 %    o window: Specifies the name or id of an X window.
8902 %
8903 %    o filename: the name of the image filename to display.
8904 %
8905 */
8906 MagickExport MagickBooleanType XRemoteCommand(Display *display,
8907   const char *window,const char *filename)
8908 {
8909   Atom
8910     remote_atom;
8911
8912   Window
8913     remote_window,
8914     root_window;
8915
8916   assert(filename != (char *) NULL);
8917   (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",filename);
8918   if (display == (Display *) NULL)
8919     display=XOpenDisplay((char *) NULL);
8920   if (display == (Display *) NULL)
8921     {
8922       ThrowXWindowException(XServerError,"UnableToOpenXServer",filename);
8923       return(MagickFalse);
8924     }
8925   remote_atom=XInternAtom(display,"IM_PROTOCOLS",MagickFalse);
8926   remote_window=(Window) NULL;
8927   root_window=XRootWindow(display,XDefaultScreen(display));
8928   if (window != (char *) NULL)
8929     {
8930       /*
8931         Search window hierarchy and identify any clients by name or ID.
8932       */
8933       if (isdigit((int) ((unsigned char) *window)) != 0)
8934         remote_window=XWindowByID(display,root_window,(Window)
8935           strtol((char *) window,(char **) NULL,0));
8936       if (remote_window == (Window) NULL)
8937         remote_window=XWindowByName(display,root_window,window);
8938     }
8939   if (remote_window == (Window) NULL)
8940     remote_window=XWindowByProperty(display,root_window,remote_atom);
8941   if (remote_window == (Window) NULL)
8942     {
8943       ThrowXWindowException(XServerError,"UnableToConnectToRemoteDisplay",
8944         filename);
8945       return(MagickFalse);
8946     }
8947   /*
8948     Send remote command.
8949   */
8950   remote_atom=XInternAtom(display,"IM_REMOTE_COMMAND",MagickFalse);
8951   (void) XChangeProperty(display,remote_window,remote_atom,XA_STRING,8,
8952     PropModeReplace,(unsigned char *) filename,(int) strlen(filename));
8953   (void) XSync(display,MagickFalse);
8954   return(MagickTrue);
8955 }
8956 \f
8957 /*
8958 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8959 %                                                                             %
8960 %                                                                             %
8961 %                                                                             %
8962 %   X R e n d e r I m a g e                                                   %
8963 %                                                                             %
8964 %                                                                             %
8965 %                                                                             %
8966 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8967 %
8968 %  XRenderImage() renders text on the image with an X11 font.  It also returns
8969 %  the bounding box of the text relative to the image.
8970 %
8971 %  The format of the XRenderImage method is:
8972 %
8973 %      MagickBooleanType XRenderImage(Image *image,DrawInfo *draw_info,
8974 %        const PointInfo *offset,TypeMetric *metrics,ExceptionInfo *exception)
8975 %
8976 %  A description of each parameter follows:
8977 %
8978 %    o image: the image.
8979 %
8980 %    o draw_info: the draw info.
8981 %
8982 %    o offset: (x,y) location of text relative to image.
8983 %
8984 %    o metrics: bounding box of text.
8985 %
8986 %    o exception: return any errors or warnings in this structure.
8987 %
8988 */
8989 MagickPrivate MagickBooleanType XRenderImage(Image *image,
8990   const DrawInfo *draw_info,const PointInfo *offset,TypeMetric *metrics,
8991   ExceptionInfo *exception)
8992 {
8993   const char
8994     *client_name;
8995
8996   DrawInfo
8997     cache_info;
8998
8999   Display
9000     *display;
9001
9002   ImageInfo
9003     *image_info;
9004
9005   MagickBooleanType
9006     status;
9007
9008   size_t
9009     height,
9010     width;
9011
9012   XAnnotateInfo
9013     annotate_info;
9014
9015   XFontStruct
9016     *font_info;
9017
9018   XPixelInfo
9019     pixel;
9020
9021   XResourceInfo
9022     resource_info;
9023
9024   XrmDatabase
9025     resource_database;
9026
9027   XStandardColormap
9028     *map_info;
9029
9030   XVisualInfo
9031     *visual_info;
9032
9033   /*
9034     Open X server connection.
9035   */
9036   display=XOpenDisplay(draw_info->server_name);
9037   if (display == (Display *) NULL)
9038     {
9039       ThrowXWindowException(XServerError,"UnableToOpenXServer",
9040         draw_info->server_name);
9041       return(MagickFalse);
9042     }
9043   /*
9044     Get user defaults from X resource database.
9045   */
9046   (void) XSetErrorHandler(XError);
9047   image_info=AcquireImageInfo();
9048   client_name=GetClientName();
9049   resource_database=XGetResourceDatabase(display,client_name);
9050   XGetResourceInfo(image_info,resource_database,client_name,&resource_info);
9051   resource_info.close_server=MagickFalse;
9052   resource_info.colormap=PrivateColormap;
9053   resource_info.font=AcquireString(draw_info->font);
9054   resource_info.background_color=AcquireString("#ffffffffffff");
9055   resource_info.foreground_color=AcquireString("#000000000000");
9056   map_info=XAllocStandardColormap();
9057   visual_info=(XVisualInfo *) NULL;
9058   font_info=(XFontStruct *) NULL;
9059   pixel.pixels=(unsigned long *) NULL;
9060   if (map_info == (XStandardColormap *) NULL)
9061     {
9062       ThrowXWindowException(ResourceLimitError,"MemoryAllocationFailed",
9063         image->filename);
9064       return(MagickFalse);
9065     }
9066   /*
9067     Initialize visual info.
9068   */
9069   visual_info=XBestVisualInfo(display,map_info,&resource_info);
9070   if (visual_info == (XVisualInfo *) NULL)
9071     {
9072       XFreeResources(display,visual_info,map_info,&pixel,font_info,
9073         &resource_info,(XWindowInfo *) NULL);
9074       ThrowXWindowException(XServerError,"UnableToGetVisual",image->filename);
9075       return(MagickFalse);
9076     }
9077   map_info->colormap=(Colormap) NULL;
9078   /*
9079     Initialize Standard Colormap info.
9080   */
9081   XGetMapInfo(visual_info,XDefaultColormap(display,visual_info->screen),
9082     map_info);
9083   XGetPixelInfo(display,visual_info,map_info,&resource_info,(Image *) NULL,
9084     &pixel);
9085   pixel.annotate_context=XDefaultGC(display,visual_info->screen);
9086   /*
9087     Initialize font info.
9088   */
9089   font_info=XBestFont(display,&resource_info,MagickFalse);
9090   if (font_info == (XFontStruct *) NULL)
9091     {
9092       XFreeResources(display,visual_info,map_info,&pixel,font_info,
9093         &resource_info,(XWindowInfo *) NULL);
9094       ThrowXWindowException(XServerError,"UnableToLoadFont",draw_info->font);
9095       return(MagickFalse);
9096     }
9097   cache_info=(*draw_info);
9098   /*
9099     Initialize annotate info.
9100   */
9101   XGetAnnotateInfo(&annotate_info);
9102   annotate_info.stencil=ForegroundStencil;
9103   if (cache_info.font != draw_info->font)
9104     {
9105       /*
9106         Type name has changed.
9107       */
9108       (void) XFreeFont(display,font_info);
9109       (void) CloneString(&resource_info.font,draw_info->font);
9110       font_info=XBestFont(display,&resource_info,MagickFalse);
9111       if (font_info == (XFontStruct *) NULL)
9112         {
9113           ThrowXWindowException(XServerError,"UnableToLoadFont",
9114             draw_info->font);
9115           return(MagickFalse);
9116         }
9117     }
9118   if (image->debug != MagickFalse)
9119     (void) LogMagickEvent(AnnotateEvent,GetMagickModule(),
9120       "Font %s; pointsize %g",draw_info->font != (char *) NULL ?
9121       draw_info->font : "none",draw_info->pointsize);
9122   cache_info=(*draw_info);
9123   annotate_info.font_info=font_info;
9124   annotate_info.text=(char *) draw_info->text;
9125   annotate_info.width=(unsigned int) XTextWidth(font_info,draw_info->text,(int)
9126     strlen(draw_info->text));
9127   annotate_info.height=(unsigned int) font_info->ascent+font_info->descent;
9128   metrics->pixels_per_em.x=(double) font_info->max_bounds.width;
9129   metrics->pixels_per_em.y=(double) font_info->ascent+font_info->descent;
9130   metrics->ascent=(double) font_info->ascent+4;
9131   metrics->descent=(double) (-font_info->descent);
9132   metrics->width=annotate_info.width/ExpandAffine(&draw_info->affine);
9133   metrics->height=font_info->ascent+font_info->descent;
9134   metrics->max_advance=(double) font_info->max_bounds.width;
9135   metrics->bounds.x1=0.0;
9136   metrics->bounds.y1=metrics->descent;
9137   metrics->bounds.x2=metrics->ascent+metrics->descent;
9138   metrics->bounds.y2=metrics->ascent+metrics->descent;
9139   metrics->underline_position=(-2.0);
9140   metrics->underline_thickness=1.0;
9141   if (draw_info->render == MagickFalse)
9142     return(MagickTrue);
9143   if (draw_info->fill.alpha == TransparentAlpha)
9144     return(MagickTrue);
9145   /*
9146     Render fill color.
9147   */
9148   width=annotate_info.width;
9149   height=annotate_info.height;
9150   if ((fabs(draw_info->affine.rx) >= MagickEpsilon) ||
9151       (fabs(draw_info->affine.ry) >= MagickEpsilon))
9152     {
9153       if ((fabs(draw_info->affine.sx-draw_info->affine.sy) < MagickEpsilon) &&
9154           (fabs(draw_info->affine.rx+draw_info->affine.ry) < MagickEpsilon))
9155         annotate_info.degrees=(double) (180.0/MagickPI)*
9156           atan2(draw_info->affine.rx,draw_info->affine.sx);
9157     }
9158   (void) FormatLocaleString(annotate_info.geometry,MaxTextExtent,
9159     "%.20gx%.20g%+.20g%+.20g",(double) width,(double) height,
9160     ceil(offset->x-0.5),ceil(offset->y-metrics->ascent-metrics->descent+
9161     draw_info->interline_spacing-0.5));
9162   pixel.pen_color.red=ScaleQuantumToShort(draw_info->fill.red);
9163   pixel.pen_color.green=ScaleQuantumToShort(draw_info->fill.green);
9164   pixel.pen_color.blue=ScaleQuantumToShort(draw_info->fill.blue);
9165   status=XAnnotateImage(display,&pixel,&annotate_info,image,exception);
9166   if (status == 0)
9167     {
9168       ThrowXWindowException(ResourceLimitError,"MemoryAllocationFailed",
9169         image->filename);
9170       return(MagickFalse);
9171     }
9172   return(MagickTrue);
9173 }
9174 \f
9175 /*
9176 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9177 %                                                                             %
9178 %                                                                             %
9179 %                                                                             %
9180 %   X R e t a i n W i n d o w C o l o r s                                     %
9181 %                                                                             %
9182 %                                                                             %
9183 %                                                                             %
9184 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9185 %
9186 %  XRetainWindowColors() sets X11 color resources on a window.  This preserves
9187 %  the colors associated with an image displayed on the window.
9188 %
9189 %  The format of the XRetainWindowColors method is:
9190 %
9191 %      void XRetainWindowColors(Display *display,const Window window)
9192 %
9193 %  A description of each parameter follows:
9194 %
9195 %    o display: Specifies a connection to an X server; returned from
9196 %      XOpenDisplay.
9197 %
9198 %    o window: Specifies a pointer to a XWindowInfo structure.
9199 %
9200 */
9201 MagickExport void XRetainWindowColors(Display *display,const Window window)
9202 {
9203   Atom
9204     property;
9205
9206   Pixmap
9207     pixmap;
9208
9209   /*
9210     Put property on the window.
9211   */
9212   (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
9213   assert(display != (Display *) NULL);
9214   assert(window != (Window) NULL);
9215   property=XInternAtom(display,"_XSETROOT_ID",MagickFalse);
9216   if (property == (Atom) NULL)
9217     {
9218       ThrowXWindowException(XServerError,"UnableToCreateProperty",
9219         "_XSETROOT_ID");
9220       return;
9221     }
9222   pixmap=XCreatePixmap(display,window,1,1,1);
9223   if (pixmap == (Pixmap) NULL)
9224     {
9225       ThrowXWindowException(XServerError,"UnableToCreateBitmap","");
9226       return;
9227     }
9228   (void) XChangeProperty(display,window,property,XA_PIXMAP,32,PropModeReplace,
9229     (unsigned char *) &pixmap,1);
9230   (void) XSetCloseDownMode(display,RetainPermanent);
9231 }
9232 \f
9233 /*
9234 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9235 %                                                                             %
9236 %                                                                             %
9237 %                                                                             %
9238 %   X S e l e c t W i n d o w                                                 %
9239 %                                                                             %
9240 %                                                                             %
9241 %                                                                             %
9242 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9243 %
9244 %  XSelectWindow() allows a user to select a window using the mouse.  If the
9245 %  mouse moves, a cropping rectangle is drawn and the extents of the rectangle
9246 %  is returned in the crop_info structure.
9247 %
9248 %  The format of the XSelectWindow function is:
9249 %
9250 %      target_window=XSelectWindow(display,crop_info)
9251 %
9252 %  A description of each parameter follows:
9253 %
9254 %    o window: XSelectWindow returns the window id.
9255 %
9256 %    o display: Specifies a pointer to the Display structure;  returned from
9257 %      XOpenDisplay.
9258 %
9259 %    o crop_info: Specifies a pointer to a RectangleInfo structure.  It
9260 %      contains the extents of any cropping rectangle.
9261 %
9262 */
9263 static Window XSelectWindow(Display *display,RectangleInfo *crop_info)
9264 {
9265 #define MinimumCropArea  (unsigned int) 9
9266
9267   Cursor
9268     target_cursor;
9269
9270   GC
9271     annotate_context;
9272
9273   int
9274     presses,
9275     x_offset,
9276     y_offset;
9277
9278   Status
9279     status;
9280
9281   Window
9282     root_window,
9283     target_window;
9284
9285   XEvent
9286     event;
9287
9288   XGCValues
9289     context_values;
9290
9291   /*
9292     Initialize graphic context.
9293   */
9294   (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
9295   assert(display != (Display *) NULL);
9296   assert(crop_info != (RectangleInfo *) NULL);
9297   root_window=XRootWindow(display,XDefaultScreen(display));
9298   context_values.background=XBlackPixel(display,XDefaultScreen(display));
9299   context_values.foreground=XWhitePixel(display,XDefaultScreen(display));
9300   context_values.function=GXinvert;
9301   context_values.plane_mask=
9302     context_values.background ^ context_values.foreground;
9303   context_values.subwindow_mode=IncludeInferiors;
9304   annotate_context=XCreateGC(display,root_window,(size_t) (GCBackground |
9305     GCForeground | GCFunction | GCSubwindowMode),&context_values);
9306   if (annotate_context == (GC) NULL)
9307     return(MagickFalse);
9308   /*
9309     Grab the pointer using target cursor.
9310   */
9311   target_cursor=XMakeCursor(display,root_window,XDefaultColormap(display,
9312     XDefaultScreen(display)),(char * ) "white",(char * ) "black");
9313   status=XGrabPointer(display,root_window,MagickFalse,(unsigned int)
9314     (ButtonPressMask | ButtonReleaseMask | ButtonMotionMask),GrabModeSync,
9315     GrabModeAsync,root_window,target_cursor,CurrentTime);
9316   if (status != GrabSuccess)
9317     {
9318       ThrowXWindowException(XServerError,"UnableToGrabMouse","");
9319       return((Window) NULL);
9320     }
9321   /*
9322     Select a window.
9323   */
9324   crop_info->width=0;
9325   crop_info->height=0;
9326   presses=0;
9327   target_window=(Window) NULL;
9328   x_offset=0;
9329   y_offset=0;
9330   do
9331   {
9332     if ((crop_info->width*crop_info->height) >= MinimumCropArea)
9333       (void) XDrawRectangle(display,root_window,annotate_context,
9334         (int) crop_info->x,(int) crop_info->y,(unsigned int) crop_info->width-1,
9335         (unsigned int) crop_info->height-1);
9336     /*
9337       Allow another event.
9338     */
9339     (void) XAllowEvents(display,SyncPointer,CurrentTime);
9340     (void) XWindowEvent(display,root_window,ButtonPressMask |
9341       ButtonReleaseMask | ButtonMotionMask,&event);
9342     if ((crop_info->width*crop_info->height) >= MinimumCropArea)
9343       (void) XDrawRectangle(display,root_window,annotate_context,
9344         (int) crop_info->x,(int) crop_info->y,(unsigned int) crop_info->width-1,
9345         (unsigned int) crop_info->height-1);
9346     switch (event.type)
9347     {
9348       case ButtonPress:
9349       {
9350         target_window=XGetSubwindow(display,event.xbutton.subwindow,
9351           event.xbutton.x,event.xbutton.y);
9352         if (target_window == (Window) NULL)
9353           target_window=root_window;
9354         x_offset=event.xbutton.x_root;
9355         y_offset=event.xbutton.y_root;
9356         crop_info->x=(ssize_t) x_offset;
9357         crop_info->y=(ssize_t) y_offset;
9358         crop_info->width=0;
9359         crop_info->height=0;
9360         presses++;
9361         break;
9362       }
9363       case ButtonRelease:
9364       {
9365         presses--;
9366         break;
9367       }
9368       case MotionNotify:
9369       {
9370         /*
9371           Discard pending button motion events.
9372         */
9373         while (XCheckMaskEvent(display,ButtonMotionMask,&event)) ;
9374         crop_info->x=(ssize_t) event.xmotion.x;
9375         crop_info->y=(ssize_t) event.xmotion.y;
9376         /*
9377           Check boundary conditions.
9378         */
9379         if ((int) crop_info->x < x_offset)
9380           crop_info->width=(size_t) (x_offset-crop_info->x);
9381         else
9382           {
9383             crop_info->width=(size_t) (crop_info->x-x_offset);
9384             crop_info->x=(ssize_t) x_offset;
9385           }
9386         if ((int) crop_info->y < y_offset)
9387           crop_info->height=(size_t) (y_offset-crop_info->y);
9388         else
9389           {
9390             crop_info->height=(size_t) (crop_info->y-y_offset);
9391             crop_info->y=(ssize_t) y_offset;
9392           }
9393       }
9394       default:
9395         break;
9396     }
9397   } while ((target_window == (Window) NULL) || (presses > 0));
9398   (void) XUngrabPointer(display,CurrentTime);
9399   (void) XFreeCursor(display,target_cursor);
9400   (void) XFreeGC(display,annotate_context);
9401   if ((crop_info->width*crop_info->height) < MinimumCropArea)
9402     {
9403       crop_info->width=0;
9404       crop_info->height=0;
9405     }
9406   if ((crop_info->width != 0) && (crop_info->height != 0))
9407     target_window=root_window;
9408   return(target_window);
9409 }
9410 \f
9411 /*
9412 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9413 %                                                                             %
9414 %                                                                             %
9415 %                                                                             %
9416 %   X S e t C u r s o r S t a t e                                             %
9417 %                                                                             %
9418 %                                                                             %
9419 %                                                                             %
9420 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9421 %
9422 %  XSetCursorState() sets the cursor state to busy, otherwise the cursor are
9423 %  reset to their default.
9424 %
9425 %  The format of the XXSetCursorState method is:
9426 %
9427 %      XSetCursorState(display,windows,const MagickStatusType state)
9428 %
9429 %  A description of each parameter follows:
9430 %
9431 %    o display: Specifies a connection to an X server;  returned from
9432 %      XOpenDisplay.
9433 %
9434 %    o windows: Specifies a pointer to a XWindows structure.
9435 %
9436 %    o state: An unsigned integer greater than 0 sets the cursor state
9437 %      to busy, otherwise the cursor are reset to their default.
9438 %
9439 */
9440 MagickPrivate void XSetCursorState(Display *display,XWindows *windows,
9441   const MagickStatusType state)
9442 {
9443   (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
9444   assert(display != (Display *) NULL);
9445   assert(windows != (XWindows *) NULL);
9446   if (state)
9447     {
9448       (void) XCheckDefineCursor(display,windows->image.id,
9449         windows->image.busy_cursor);
9450       (void) XCheckDefineCursor(display,windows->pan.id,
9451         windows->pan.busy_cursor);
9452       (void) XCheckDefineCursor(display,windows->magnify.id,
9453         windows->magnify.busy_cursor);
9454       (void) XCheckDefineCursor(display,windows->command.id,
9455         windows->command.busy_cursor);
9456     }
9457   else
9458     {
9459       (void) XCheckDefineCursor(display,windows->image.id,
9460         windows->image.cursor);
9461       (void) XCheckDefineCursor(display,windows->pan.id,windows->pan.cursor);
9462       (void) XCheckDefineCursor(display,windows->magnify.id,
9463         windows->magnify.cursor);
9464       (void) XCheckDefineCursor(display,windows->command.id,
9465         windows->command.cursor);
9466       (void) XCheckDefineCursor(display,windows->command.id,
9467         windows->widget.cursor);
9468       (void) XWithdrawWindow(display,windows->info.id,windows->info.screen);
9469     }
9470   windows->info.mapped=MagickFalse;
9471 }
9472 \f
9473 /*
9474 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9475 %                                                                             %
9476 %                                                                             %
9477 %                                                                             %
9478 %   X S e t W i n d o w s                                                     %
9479 %                                                                             %
9480 %                                                                             %
9481 %                                                                             %
9482 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9483 %
9484 %  XSetWindows() sets the X windows structure if the windows info is specified.
9485 %  Otherwise the current windows structure is returned.
9486 %
9487 %  The format of the XSetWindows method is:
9488 %
9489 %      XWindows *XSetWindows(XWindows *windows_info)
9490 %
9491 %  A description of each parameter follows:
9492 %
9493 %    o windows_info: Initialize the Windows structure with this information.
9494 %
9495 */
9496 MagickPrivate XWindows *XSetWindows(XWindows *windows_info)
9497 {
9498   static XWindows
9499     *windows = (XWindows *) NULL;
9500
9501   if (windows_info != (XWindows *) ~0)
9502     {
9503       windows=(XWindows *) RelinquishMagickMemory(windows);
9504       windows=windows_info;
9505     }
9506   return(windows);
9507 }
9508 /*
9509 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9510 %                                                                             %
9511 %                                                                             %
9512 %                                                                             %
9513 %   X U s e r P r e f e r e n c e s                                           %
9514 %                                                                             %
9515 %                                                                             %
9516 %                                                                             %
9517 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9518 %
9519 %  XUserPreferences() saves the preferences in a configuration file in the
9520 %  users' home directory.
9521 %
9522 %  The format of the XUserPreferences method is:
9523 %
9524 %      void XUserPreferences(XResourceInfo *resource_info)
9525 %
9526 %  A description of each parameter follows:
9527 %
9528 %    o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
9529 %
9530 */
9531 MagickPrivate void XUserPreferences(XResourceInfo *resource_info)
9532 {
9533 #if defined(X11_PREFERENCES_PATH)
9534   char
9535     cache[MaxTextExtent],
9536     filename[MaxTextExtent],
9537     specifier[MaxTextExtent];
9538
9539   const char
9540     *client_name,
9541     *value;
9542
9543   XrmDatabase
9544     preferences_database;
9545
9546   /*
9547     Save user preferences to the client configuration file.
9548   */
9549   assert(resource_info != (XResourceInfo *) NULL);
9550   client_name=GetClientName();
9551   preferences_database=XrmGetStringDatabase("");
9552   (void) FormatLocaleString(specifier,MaxTextExtent,"%s.backdrop",client_name);
9553   value=resource_info->backdrop ? "True" : "False";
9554   XrmPutStringResource(&preferences_database,specifier,(char *) value);
9555   (void) FormatLocaleString(specifier,MaxTextExtent,"%s.colormap",client_name);
9556   value=resource_info->colormap == SharedColormap ? "Shared" : "Private";
9557   XrmPutStringResource(&preferences_database,specifier,(char *) value);
9558   (void) FormatLocaleString(specifier,MaxTextExtent,"%s.confirmExit",
9559     client_name);
9560   value=resource_info->confirm_exit ? "True" : "False";
9561   XrmPutStringResource(&preferences_database,specifier,(char *) value);
9562   (void) FormatLocaleString(specifier,MaxTextExtent,"%s.confirmEdit",
9563     client_name);
9564   value=resource_info->confirm_edit ? "True" : "False";
9565   XrmPutStringResource(&preferences_database,specifier,(char *) value);
9566   (void) FormatLocaleString(specifier,MaxTextExtent,"%s.displayWarnings",
9567     client_name);
9568   value=resource_info->display_warnings ? "True" : "False";
9569   XrmPutStringResource(&preferences_database,specifier,(char *) value);
9570   (void) FormatLocaleString(specifier,MaxTextExtent,"%s.dither",client_name);
9571   value=resource_info->quantize_info->dither_method != NoDitherMethod ?
9572     "True" : "False";
9573   XrmPutStringResource(&preferences_database,specifier,(char *) value);
9574   (void) FormatLocaleString(specifier,MaxTextExtent,"%s.gammaCorrect",
9575     client_name);
9576   value=resource_info->gamma_correct ? "True" : "False";
9577   XrmPutStringResource(&preferences_database,specifier,(char *) value);
9578   (void) FormatLocaleString(specifier,MaxTextExtent,"%s.undoCache",client_name);
9579   (void) FormatLocaleString(cache,MaxTextExtent,"%.20g",(double)
9580     resource_info->undo_cache);
9581   XrmPutStringResource(&preferences_database,specifier,cache);
9582   (void) FormatLocaleString(specifier,MaxTextExtent,"%s.usePixmap",client_name);
9583   value=resource_info->use_pixmap ? "True" : "False";
9584   XrmPutStringResource(&preferences_database,specifier,(char *) value);
9585   (void) FormatLocaleString(filename,MaxTextExtent,"%s%src",
9586     X11_PREFERENCES_PATH,client_name);
9587   ExpandFilename(filename);
9588   XrmPutFileDatabase(preferences_database,filename);
9589 #endif
9590 }
9591 \f
9592 /*
9593 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9594 %                                                                             %
9595 %                                                                             %
9596 %                                                                             %
9597 %   X V i s u a l C l a s s N a m e                                           %
9598 %                                                                             %
9599 %                                                                             %
9600 %                                                                             %
9601 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9602 %
9603 %  XVisualClassName() returns the visual class name as a character string.
9604 %
9605 %  The format of the XVisualClassName method is:
9606 %
9607 %      char *XVisualClassName(const int visual_class)
9608 %
9609 %  A description of each parameter follows:
9610 %
9611 %    o visual_type: XVisualClassName returns the visual class as a character
9612 %      string.
9613 %
9614 %    o class: Specifies the visual class.
9615 %
9616 */
9617 static const char *XVisualClassName(const int visual_class)
9618 {
9619   switch (visual_class)
9620   {
9621     case StaticGray: return("StaticGray");
9622     case GrayScale: return("GrayScale");
9623     case StaticColor: return("StaticColor");
9624     case PseudoColor: return("PseudoColor");
9625     case TrueColor: return("TrueColor");
9626     case DirectColor: return("DirectColor");
9627   }
9628   return("unknown visual class");
9629 }
9630 \f
9631 /*
9632 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9633 %                                                                             %
9634 %                                                                             %
9635 %                                                                             %
9636 %   X W a r n i n g                                                           %
9637 %                                                                             %
9638 %                                                                             %
9639 %                                                                             %
9640 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9641 %
9642 %  XWarning() displays a warning reason in a Notice widget.
9643 %
9644 %  The format of the XWarning method is:
9645 %
9646 %      void XWarning(const unsigned int warning,const char *reason,
9647 %        const char *description)
9648 %
9649 %  A description of each parameter follows:
9650 %
9651 %    o warning: Specifies the numeric warning category.
9652 %
9653 %    o reason: Specifies the reason to display before terminating the
9654 %      program.
9655 %
9656 %    o description: Specifies any description to the reason.
9657 %
9658 */
9659 MagickPrivate void XWarning(const ExceptionType magick_unused(warning),
9660   const char *reason,const char *description)
9661 {
9662   char
9663     text[MaxTextExtent];
9664
9665   XWindows
9666     *windows;
9667
9668   if (reason == (char *) NULL)
9669     return;
9670   (void) CopyMagickString(text,reason,MaxTextExtent);
9671   (void) ConcatenateMagickString(text,":",MaxTextExtent);
9672   windows=XSetWindows((XWindows *) ~0);
9673   XNoticeWidget(windows->display,windows,text,(char *) description);
9674 }
9675 \f
9676 /*
9677 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9678 %                                                                             %
9679 %                                                                             %
9680 %                                                                             %
9681 %   X W i n d o w B y I D                                                     %
9682 %                                                                             %
9683 %                                                                             %
9684 %                                                                             %
9685 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9686 %
9687 %  XWindowByID() locates a child window with a given ID.  If not window with
9688 %  the given name is found, 0 is returned.   Only the window specified and its
9689 %  subwindows are searched.
9690 %
9691 %  The format of the XWindowByID function is:
9692 %
9693 %      child=XWindowByID(display,window,id)
9694 %
9695 %  A description of each parameter follows:
9696 %
9697 %    o child: XWindowByID returns the window with the specified
9698 %      id.  If no windows are found, XWindowByID returns 0.
9699 %
9700 %    o display: Specifies a pointer to the Display structure;  returned from
9701 %      XOpenDisplay.
9702 %
9703 %    o id: Specifies the id of the window to locate.
9704 %
9705 */
9706 MagickPrivate Window XWindowByID(Display *display,const Window root_window,
9707   const size_t id)
9708 {
9709   RectangleInfo
9710     rectangle_info;
9711
9712   register int
9713     i;
9714
9715   Status
9716     status;
9717
9718   unsigned int
9719     number_children;
9720
9721   Window
9722     child,
9723     *children,
9724     window;
9725
9726   (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
9727   assert(display != (Display *) NULL);
9728   assert(root_window != (Window) NULL);
9729   if (id == 0)
9730     return(XSelectWindow(display,&rectangle_info));
9731   if (root_window == id)
9732     return(root_window);
9733   status=XQueryTree(display,root_window,&child,&child,&children,
9734     &number_children);
9735   if (status == False)
9736     return((Window) NULL);
9737   window=(Window) NULL;
9738   for (i=0; i < (int) number_children; i++)
9739   {
9740     /*
9741       Search each child and their children.
9742     */
9743     window=XWindowByID(display,children[i],id);
9744     if (window != (Window) NULL)
9745       break;
9746   }
9747   if (children != (Window *) NULL)
9748     (void) XFree((void *) children);
9749   return(window);
9750 }
9751 \f
9752 /*
9753 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9754 %                                                                             %
9755 %                                                                             %
9756 %                                                                             %
9757 %   X W i n d o w B y N a m e                                                 %
9758 %                                                                             %
9759 %                                                                             %
9760 %                                                                             %
9761 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9762 %
9763 %  XWindowByName() locates a window with a given name on a display.  If no
9764 %  window with the given name is found, 0 is returned. If more than one window
9765 %  has the given name, the first one is returned.  Only root and its children
9766 %  are searched.
9767 %
9768 %  The format of the XWindowByName function is:
9769 %
9770 %      window=XWindowByName(display,root_window,name)
9771 %
9772 %  A description of each parameter follows:
9773 %
9774 %    o window: XWindowByName returns the window id.
9775 %
9776 %    o display: Specifies a pointer to the Display structure;  returned from
9777 %      XOpenDisplay.
9778 %
9779 %    o root_window: Specifies the id of the root window.
9780 %
9781 %    o name: Specifies the name of the window to locate.
9782 %
9783 */
9784 MagickPrivate Window XWindowByName(Display *display,const Window root_window,
9785   const char *name)
9786 {
9787   register int
9788     i;
9789
9790   Status
9791     status;
9792
9793   unsigned int
9794     number_children;
9795
9796   Window
9797     *children,
9798     child,
9799     window;
9800
9801   XTextProperty
9802     window_name;
9803
9804   assert(display != (Display *) NULL);
9805   assert(root_window != (Window) NULL);
9806   assert(name != (char *) NULL);
9807   (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",name);
9808   if (XGetWMName(display,root_window,&window_name) != 0)
9809     if (LocaleCompare((char *) window_name.value,name) == 0)
9810       return(root_window);
9811   status=XQueryTree(display,root_window,&child,&child,&children,
9812     &number_children);
9813   if (status == False)
9814     return((Window) NULL);
9815   window=(Window) NULL;
9816   for (i=0; i < (int) number_children; i++)
9817   {
9818     /*
9819       Search each child and their children.
9820     */
9821     window=XWindowByName(display,children[i],name);
9822     if (window != (Window) NULL)
9823       break;
9824   }
9825   if (children != (Window *) NULL)
9826     (void) XFree((void *) children);
9827   return(window);
9828 }
9829 \f
9830 /*
9831 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9832 %                                                                             %
9833 %                                                                             %
9834 %                                                                             %
9835 %   X W i n d o w B y P r o p e r y                                           %
9836 %                                                                             %
9837 %                                                                             %
9838 %                                                                             %
9839 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9840 %
9841 %  XWindowByProperty() locates a child window with a given property. If not
9842 %  window with the given name is found, 0 is returned.  If more than one window
9843 %  has the given property, the first one is returned.  Only the window
9844 %  specified and its subwindows are searched.
9845 %
9846 %  The format of the XWindowByProperty function is:
9847 %
9848 %      child=XWindowByProperty(display,window,property)
9849 %
9850 %  A description of each parameter follows:
9851 %
9852 %    o child: XWindowByProperty returns the window id with the specified
9853 %      property.  If no windows are found, XWindowByProperty returns 0.
9854 %
9855 %    o display: Specifies a pointer to the Display structure;  returned from
9856 %      XOpenDisplay.
9857 %
9858 %    o property: Specifies the property of the window to locate.
9859 %
9860 */
9861 MagickPrivate Window XWindowByProperty(Display *display,const Window window,
9862   const Atom property)
9863 {
9864   Atom
9865     type;
9866
9867   int
9868     format;
9869
9870   Status
9871     status;
9872
9873   unsigned char
9874     *data;
9875
9876   unsigned int
9877     i,
9878     number_children;
9879
9880   unsigned long
9881     after,
9882     number_items;
9883
9884   Window
9885     child,
9886     *children,
9887     parent,
9888     root;
9889
9890   (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
9891   assert(display != (Display *) NULL);
9892   assert(window != (Window) NULL);
9893   assert(property != (Atom) NULL);
9894   status=XQueryTree(display,window,&root,&parent,&children,&number_children);
9895   if (status == False)
9896     return((Window) NULL);
9897   type=(Atom) NULL;
9898   child=(Window) NULL;
9899   for (i=0; (i < number_children) && (child == (Window) NULL); i++)
9900   {
9901     status=XGetWindowProperty(display,children[i],property,0L,0L,MagickFalse,
9902       (Atom) AnyPropertyType,&type,&format,&number_items,&after,&data);
9903     if (data != NULL)
9904       (void) XFree((void *) data);
9905     if ((status == Success) && (type != (Atom) NULL))
9906       child=children[i];
9907   }
9908   for (i=0; (i < number_children) && (child == (Window) NULL); i++)
9909     child=XWindowByProperty(display,children[i],property);
9910   if (children != (Window *) NULL)
9911     (void) XFree((void *) children);
9912   return(child);
9913 }
9914 #else
9915 \f
9916 /*
9917 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9918 %                                                                             %
9919 %                                                                             %
9920 %                                                                             %
9921 %   X I m p o r t I m a g e                                                   %
9922 %                                                                             %
9923 %                                                                             %
9924 %                                                                             %
9925 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9926 %
9927 %  XImportImage() reads an image from an X window.
9928 %
9929 %  The format of the XImportImage method is:
9930 %
9931 %      Image *XImportImage(const ImageInfo *image_info,XImportInfo *ximage_info,
9932 %        ExceptionInfo *exception)
9933 %
9934 %  A description of each parameter follows:
9935 %
9936 %    o image_info: the image info..
9937 %
9938 %    o ximage_info: Specifies a pointer to an XImportInfo structure.
9939 %
9940 %    o exception: return any errors or warnings in this structure.
9941 %
9942 */
9943 MagickExport Image *XImportImage(const ImageInfo *image_info,
9944   XImportInfo *ximage_info,ExceptionInfo *exception)
9945 {
9946   assert(image_info != (const ImageInfo *) NULL);
9947   assert(image_info->signature == MagickSignature);
9948   if (image_info->debug != MagickFalse)
9949     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
9950       image_info->filename);
9951   assert(ximage_info != (XImportInfo *) NULL);
9952   assert(exception != (ExceptionInfo *) NULL);
9953   assert(exception->signature == MagickSignature);
9954   return((Image *) NULL);
9955 }
9956 \f
9957 /*
9958 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9959 %                                                                             %
9960 %                                                                             %
9961 %                                                                             %
9962 %   X R e n d e r X 1 1                                                       %
9963 %                                                                             %
9964 %                                                                             %
9965 %                                                                             %
9966 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9967 %
9968 %  XRenderImage() renders text on the image with an X11 font.  It also returns
9969 %  the bounding box of the text relative to the image.
9970 %
9971 %  The format of the XRenderImage method is:
9972 %
9973 %      MagickBooleanType XRenderImage(Image *image,DrawInfo *draw_info,
9974 %        const PointInfo *offset,TypeMetric *metrics,ExceptionInfo *exception)
9975 %
9976 %  A description of each parameter follows:
9977 %
9978 %    o image: the image.
9979 %
9980 %    o draw_info: the draw info.
9981 %
9982 %    o offset: (x,y) location of text relative to image.
9983 %
9984 %    o metrics: bounding box of text.
9985 %
9986 %    o exception: return any errors or warnings in this structure.
9987 %
9988 */
9989 MagickPrivate MagickBooleanType XRenderImage(Image *image,
9990   const DrawInfo *draw_info,const PointInfo *offset,TypeMetric *metrics,
9991   ExceptionInfo *exception)
9992 {
9993   (void) draw_info;
9994   (void) offset;
9995   (void) metrics;
9996   (void) ThrowMagickException(exception,GetMagickModule(),
9997     MissingDelegateError,"DelegateLibrarySupportNotBuiltIn","'%s' (X11)",
9998     image->filename);
9999   return(MagickFalse);
10000 }
10001 #endif
10002 \f
10003 /*
10004 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
10005 %                                                                             %
10006 %                                                                             %
10007 %                                                                             %
10008 +   X C o m p o n e n t G e n e s i s                                         %
10009 %                                                                             %
10010 %                                                                             %
10011 %                                                                             %
10012 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
10013 %
10014 %  XComponentGenesis() instantiates the X component.
10015 %
10016 %  The format of the XComponentGenesis method is:
10017 %
10018 %      MagickBooleanType XComponentGenesis(void)
10019 %
10020 */
10021 MagickPrivate MagickBooleanType XComponentGenesis(void)
10022 {
10023   return(MagickTrue);
10024 }
10025 \f
10026 /*
10027 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
10028 %                                                                             %
10029 %                                                                             %
10030 %                                                                             %
10031 %   X G e t I m p o r t I n f o                                               %
10032 %                                                                             %
10033 %                                                                             %
10034 %                                                                             %
10035 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
10036 %
10037 %  XGetImportInfo() initializes the XImportInfo structure.
10038 %
10039 %  The format of the XGetImportInfo method is:
10040 %
10041 %      void XGetImportInfo(XImportInfo *ximage_info)
10042 %
10043 %  A description of each parameter follows:
10044 %
10045 %    o ximage_info: Specifies a pointer to an ImageInfo structure.
10046 %
10047 */
10048 MagickExport void XGetImportInfo(XImportInfo *ximage_info)
10049 {
10050   assert(ximage_info != (XImportInfo *) NULL);
10051   ximage_info->frame=MagickFalse;
10052   ximage_info->borders=MagickFalse;
10053   ximage_info->screen=MagickFalse;
10054   ximage_info->descend=MagickTrue;
10055   ximage_info->silent=MagickFalse;
10056 }