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