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