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