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