MagickCore  7.1.0
xwindow.c
Go to the documentation of this file.
1 /*
2 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3 % %
4 % %
5 % %
6 % X X W W IIIII N N DDDD OOO W W %
7 % X X W W I NN N D D O O W W %
8 % X W W I N N N D D O O W W %
9 % X X W W W I N NN D D O O W W W %
10 % X X W W IIIII N N DDDD OOO W W %
11 % %
12 % %
13 % MagickCore X11 Utility Methods %
14 % %
15 % Software Design %
16 % Cristy %
17 % July 1992 %
18 % %
19 % %
20 % Copyright 1999-2021 ImageMagick Studio LLC, a non-profit organization %
21 % dedicated to making software imaging solutions freely available. %
22 % %
23 % You may not use this file except in compliance with the License. You may %
24 % obtain a copy of the License at %
25 % %
26 % https://imagemagick.org/script/license.php %
27 % %
28 % Unless required by applicable law or agreed to in writing, software %
29 % distributed under the License is distributed on an "AS IS" BASIS, %
30 % WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. %
31 % See the License for the specific language governing permissions and %
32 % limitations under the License. %
33 % %
34 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
35 %
36 %
37 */
38 
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"
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"
57 #include "MagickCore/geometry.h"
58 #include "MagickCore/identify.h"
59 #include "MagickCore/image.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"
67 #include "MagickCore/monitor.h"
69 #include "MagickCore/option.h"
71 #include "MagickCore/quantize.h"
72 #include "MagickCore/quantum.h"
74 #include "MagickCore/resource_.h"
75 #include "MagickCore/resize.h"
76 #include "MagickCore/statistic.h"
77 #include "MagickCore/string_.h"
79 #include "MagickCore/transform.h"
81 #include "MagickCore/token.h"
82 #include "MagickCore/utility.h"
84 #include "MagickCore/widget.h"
86 #include "MagickCore/xwindow.h"
88 #include "MagickCore/version.h"
89 #if defined(__BEOS__)
90 #include <OS.h>
91 #endif
92 #if defined(MAGICKCORE_X11_DELEGATE)
93 #include <X11/Xproto.h>
94 #include <X11/Xlocale.h>
95 #if defined(MAGICK_HAVE_POLL)
96 # include <sys/poll.h>
97 #endif
98 #if defined(MAGICKCORE_HAVE_SHARED_MEMORY)
99 #if defined(MAGICKCORE_HAVE_MACHINE_PARAM_H)
100 # include <machine/param.h>
101 #endif
102 #include <sys/ipc.h>
103 #include <sys/shm.h>
104 #include <X11/extensions/XShm.h>
105 #endif
106 #if defined(MAGICKCORE_HAVE_SHAPE)
107 #include <X11/extensions/shape.h>
108 #endif
109 
110 /*
111  X defines.
112 */
113 #define XBlueGamma(color) ClampToQuantum(blue_gamma == 1.0 ? (double) \
114  (color) : ((pow(((double) QuantumScale*(color)),1.0* \
115  PerceptibleReciprocal((double) blue_gamma))*QuantumRange)))
116 #define XGammaPacket(map,color) (size_t) (map->base_pixel+ \
117  ((ScaleQuantumToShort(XRedGamma((color)->red))*map->red_max/65535L)* \
118  map->red_mult)+ \
119  ((ScaleQuantumToShort(XGreenGamma((color)->green))*map->green_max/65535L)* \
120  map->green_mult)+ \
121  ((ScaleQuantumToShort(XBlueGamma((color)->blue))*map->blue_max/65535L)* \
122  map->blue_mult))
123 #define XGammaPixel(image,map,color) (size_t) (map->base_pixel+ \
124  ((ScaleQuantumToShort(XRedGamma(GetPixelRed(image,color)))*map->red_max/65535L)* \
125  map->red_mult)+ \
126  ((ScaleQuantumToShort(XGreenGamma(GetPixelGreen(image,color)))*map->green_max/65535L)* \
127  map->green_mult)+ \
128  ((ScaleQuantumToShort(XBlueGamma(GetPixelBlue(image,color)))*map->blue_max/65535L)* \
129  map->blue_mult))
130 #define XGreenGamma(color) ClampToQuantum(green_gamma == 1.0 ? (double) \
131  (color) : ((pow(((double) QuantumScale*(color)),1.0* \
132  PerceptibleReciprocal((double) green_gamma))*QuantumRange)))
133 #define XRedGamma(color) ClampToQuantum(red_gamma == 1.0 ? (double) \
134  (color) : ((pow(((double) QuantumScale*(color)),1.0* \
135  PerceptibleReciprocal((double) red_gamma))*QuantumRange)))
136 #define XStandardPixel(map,color) (size_t) (map->base_pixel+ \
137  (((color)->red*map->red_max/65535L)*map->red_mult)+ \
138  (((color)->green*map->green_max/65535L)*map->green_mult)+ \
139  (((color)->blue*map->blue_max/65535L)*map->blue_mult))
140 
141 #define AccentuateModulate ScaleCharToQuantum(80)
142 #define HighlightModulate ScaleCharToQuantum(125)
143 #define ShadowModulate ScaleCharToQuantum(135)
144 #define DepthModulate ScaleCharToQuantum(185)
145 #define TroughModulate ScaleCharToQuantum(110)
146 
147 #define XLIB_ILLEGAL_ACCESS 1
148 #undef ForgetGravity
149 #undef NorthWestGravity
150 #undef NorthGravity
151 #undef NorthEastGravity
152 #undef WestGravity
153 #undef CenterGravity
154 #undef EastGravity
155 #undef SouthWestGravity
156 #undef SouthGravity
157 #undef SouthEastGravity
158 #undef StaticGravity
159 
160 #undef index
161 #if defined(hpux9)
162 #define XFD_SET int
163 #else
164 #define XFD_SET fd_set
165 #endif
166 
167 /*
168  Enumeration declarations.
169 */
170 typedef enum
171 {
172 #undef DoRed
173  DoRed = 0x0001,
174 #undef DoGreen
175  DoGreen = 0x0002,
176 #undef DoBlue
177  DoBlue = 0x0004,
178  DoMatte = 0x0008
179 } XColorFlags;
180 
181 /*
182  Typedef declarations.
183 */
184 typedef struct _DiversityPacket
185 {
186  Quantum
187  red,
188  green,
189  blue;
190 
191  unsigned short
192  index;
193 
194  size_t
195  count;
196 } DiversityPacket;
197 
198 /*
199  Constant declaractions.
200 */
201 static MagickBooleanType
202  xerror_alert = MagickFalse;
203 
204 /*
205  Method prototypes.
206 */
207 static const char
208  *XVisualClassName(const int);
209 
210 static double
211  blue_gamma = 1.0,
212  green_gamma = 1.0,
213  red_gamma = 1.0;
214 
215 static MagickBooleanType
216  XMakePixmap(Display *,const XResourceInfo *,XWindowInfo *);
217 
218 static void
219  XMakeImageLSBFirst(const XResourceInfo *,const XWindowInfo *,Image *,
220  XImage *,XImage *,ExceptionInfo *),
221  XMakeImageMSBFirst(const XResourceInfo *,const XWindowInfo *,Image *,
222  XImage *,XImage *,ExceptionInfo *);
223 
224 static Window
225  XSelectWindow(Display *,RectangleInfo *);
226 
227 /*
228 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
229 % %
230 % %
231 % %
232 % D e s t r o y X R e s o u r c e s %
233 % %
234 % %
235 % %
236 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
237 %
238 % DestroyXResources() destroys any X resources.
239 %
240 % The format of the DestroyXResources method is:
241 %
242 % void DestroyXResources()
243 %
244 % A description of each parameter follows:
245 %
246 */
247 MagickExport void DestroyXResources(void)
248 {
249  int
250  i;
251 
252  unsigned int
253  number_windows;
254 
255  XWindowInfo
256  *magick_windows[MaxXWindows];
257 
258  XWindows
259  *windows;
260 
261  DestroyXWidget();
262  windows=XSetWindows((XWindows *) ~0);
263  if ((windows == (XWindows *) NULL) || (windows->display == (Display *) NULL))
264  return;
265  number_windows=0;
266  magick_windows[number_windows++]=(&windows->context);
267  magick_windows[number_windows++]=(&windows->group_leader);
268  magick_windows[number_windows++]=(&windows->backdrop);
269  magick_windows[number_windows++]=(&windows->icon);
270  magick_windows[number_windows++]=(&windows->image);
271  magick_windows[number_windows++]=(&windows->info);
272  magick_windows[number_windows++]=(&windows->magnify);
273  magick_windows[number_windows++]=(&windows->pan);
274  magick_windows[number_windows++]=(&windows->command);
275  magick_windows[number_windows++]=(&windows->widget);
276  magick_windows[number_windows++]=(&windows->popup);
277  for (i=0; i < (int) number_windows; i++)
278  {
279  if (magick_windows[i]->mapped != MagickFalse)
280  {
281  (void) XWithdrawWindow(windows->display,magick_windows[i]->id,
282  magick_windows[i]->screen);
283  magick_windows[i]->mapped=MagickFalse;
284  }
285  if (magick_windows[i]->name != (char *) NULL)
286  magick_windows[i]->name=(char *)
287  RelinquishMagickMemory(magick_windows[i]->name);
288  if (magick_windows[i]->icon_name != (char *) NULL)
289  magick_windows[i]->icon_name=(char *)
290  RelinquishMagickMemory(magick_windows[i]->icon_name);
291  if (magick_windows[i]->cursor != (Cursor) NULL)
292  {
293  (void) XFreeCursor(windows->display,magick_windows[i]->cursor);
294  magick_windows[i]->cursor=(Cursor) NULL;
295  }
296  if (magick_windows[i]->busy_cursor != (Cursor) NULL)
297  {
298  (void) XFreeCursor(windows->display,magick_windows[i]->busy_cursor);
299  magick_windows[i]->busy_cursor=(Cursor) NULL;
300  }
301  if (magick_windows[i]->highlight_stipple != (Pixmap) NULL)
302  {
303  (void) XFreePixmap(windows->display,
304  magick_windows[i]->highlight_stipple);
305  magick_windows[i]->highlight_stipple=(Pixmap) NULL;
306  }
307  if (magick_windows[i]->shadow_stipple != (Pixmap) NULL)
308  {
309  (void) XFreePixmap(windows->display,magick_windows[i]->shadow_stipple);
310  magick_windows[i]->shadow_stipple=(Pixmap) NULL;
311  }
312  if (magick_windows[i]->matte_image != (XImage *) NULL)
313  {
314  XDestroyImage(magick_windows[i]->matte_image);
315  magick_windows[i]->matte_image=(XImage *) NULL;
316  }
317  if (magick_windows[i]->ximage != (XImage *) NULL)
318  {
319  XDestroyImage(magick_windows[i]->ximage);
320  magick_windows[i]->ximage=(XImage *) NULL;
321  }
322  if (magick_windows[i]->pixmap != (Pixmap) NULL)
323  {
324  (void) XFreePixmap(windows->display,magick_windows[i]->pixmap);
325  magick_windows[i]->pixmap=(Pixmap) NULL;
326  }
327  if (magick_windows[i]->id != (Window) NULL)
328  {
329  (void) XDestroyWindow(windows->display,magick_windows[i]->id);
330  magick_windows[i]->id=(Window) NULL;
331  }
332  if (magick_windows[i]->destroy != MagickFalse)
333  {
334  if (magick_windows[i]->image != (Image *) NULL)
335  {
336  magick_windows[i]->image=DestroyImage(magick_windows[i]->image);
337  magick_windows[i]->image=NewImageList();
338  }
339  if (magick_windows[i]->matte_pixmap != (Pixmap) NULL)
340  {
341  (void) XFreePixmap(windows->display,
342  magick_windows[i]->matte_pixmap);
343  magick_windows[i]->matte_pixmap=(Pixmap) NULL;
344  }
345  }
346  if (magick_windows[i]->segment_info != (void *) NULL)
347  {
348 #if defined(MAGICKCORE_HAVE_SHARED_MEMORY)
349  XShmSegmentInfo
350  *segment_info;
351 
352  segment_info=(XShmSegmentInfo *) magick_windows[i]->segment_info;
353  if (segment_info != (XShmSegmentInfo *) NULL)
354  if (segment_info[0].shmid >= 0)
355  {
356  if (segment_info[0].shmaddr != NULL)
357  (void) shmdt(segment_info[0].shmaddr);
358  (void) shmctl(segment_info[0].shmid,IPC_RMID,0);
359  segment_info[0].shmaddr=NULL;
360  segment_info[0].shmid=(-1);
361  }
362 #endif
363  magick_windows[i]->segment_info=(void *)
364  RelinquishMagickMemory(magick_windows[i]->segment_info);
365  }
366  }
367  windows->icon_resources=(XResourceInfo *)
368  RelinquishMagickMemory(windows->icon_resources);
369  if (windows->icon_pixel != (XPixelInfo *) NULL)
370  {
371  if (windows->icon_pixel->pixels != (unsigned long *) NULL)
372  windows->icon_pixel->pixels=(unsigned long *)
373  RelinquishMagickMemory(windows->icon_pixel->pixels);
374  if (windows->icon_pixel->annotate_context != (GC) NULL)
375  XFreeGC(windows->display,windows->icon_pixel->annotate_context);
376  windows->icon_pixel=(XPixelInfo *)
377  RelinquishMagickMemory(windows->icon_pixel);
378  }
379  if (windows->pixel_info != (XPixelInfo *) NULL)
380  {
381  if (windows->pixel_info->pixels != (unsigned long *) NULL)
382  windows->pixel_info->pixels=(unsigned long *)
383  RelinquishMagickMemory(windows->pixel_info->pixels);
384  if (windows->pixel_info->annotate_context != (GC) NULL)
385  XFreeGC(windows->display,windows->pixel_info->annotate_context);
386  if (windows->pixel_info->widget_context != (GC) NULL)
387  XFreeGC(windows->display,windows->pixel_info->widget_context);
388  if (windows->pixel_info->highlight_context != (GC) NULL)
389  XFreeGC(windows->display,windows->pixel_info->highlight_context);
390  windows->pixel_info=(XPixelInfo *)
391  RelinquishMagickMemory(windows->pixel_info);
392  }
393  if (windows->font_info != (XFontStruct *) NULL)
394  {
395  XFreeFont(windows->display,windows->font_info);
396  windows->font_info=(XFontStruct *) NULL;
397  }
398  if (windows->class_hints != (XClassHint *) NULL)
399  {
400  if (windows->class_hints->res_name != (char *) NULL)
401  windows->class_hints->res_name=DestroyString(
402  windows->class_hints->res_name);
403  if (windows->class_hints->res_class != (char *) NULL)
404  windows->class_hints->res_class=DestroyString(
405  windows->class_hints->res_class);
406  XFree(windows->class_hints);
407  windows->class_hints=(XClassHint *) NULL;
408  }
409  if (windows->manager_hints != (XWMHints *) NULL)
410  {
411  XFree(windows->manager_hints);
412  windows->manager_hints=(XWMHints *) NULL;
413  }
414  if (windows->map_info != (XStandardColormap *) NULL)
415  {
416  XFree(windows->map_info);
417  windows->map_info=(XStandardColormap *) NULL;
418  }
419  if (windows->icon_map != (XStandardColormap *) NULL)
420  {
421  XFree(windows->icon_map);
422  windows->icon_map=(XStandardColormap *) NULL;
423  }
424  if (windows->visual_info != (XVisualInfo *) NULL)
425  {
426  XFree(windows->visual_info);
427  windows->visual_info=(XVisualInfo *) NULL;
428  }
429  if (windows->icon_visual != (XVisualInfo *) NULL)
430  {
431  XFree(windows->icon_visual);
432  windows->icon_visual=(XVisualInfo *) NULL;
433  }
434  (void) XSetWindows((XWindows *) NULL);
435 }
436 
437 /*
438 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
439 % %
440 % %
441 % %
442 % X A n n o t a t e I m a g e %
443 % %
444 % %
445 % %
446 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
447 %
448 % XAnnotateImage() annotates the image with text.
449 %
450 % The format of the XAnnotateImage method is:
451 %
452 % MagickBooleanType XAnnotateImage(Display *display,
453 % const XPixelInfo *pixel,XAnnotateInfo *annotate_info,Image *image,
454 % ExceptionInfo *exception)
455 %
456 % A description of each parameter follows:
457 %
458 % o display: Specifies a connection to an X server; returned from
459 % XOpenDisplay.
460 %
461 % o pixel: Specifies a pointer to a XPixelInfo structure.
462 %
463 % o annotate_info: Specifies a pointer to a XAnnotateInfo structure.
464 %
465 % o image: the image.
466 %
467 % o exception: return any errors or warnings in this structure.
468 %
469 */
470 MagickPrivate MagickBooleanType XAnnotateImage(Display *display,
471  const XPixelInfo *pixel,XAnnotateInfo *annotate_info,Image *image,
472  ExceptionInfo *exception)
473 {
474  CacheView
475  *annotate_view;
476 
477  GC
478  annotate_context;
479 
480  Image
481  *annotate_image;
482 
483  int
484  x,
485  y;
486 
487  PixelTrait
488  alpha_trait;
489 
490  Pixmap
491  annotate_pixmap;
492 
493  unsigned int
494  depth,
495  height,
496  width;
497 
498  Window
499  root_window;
500 
501  XGCValues
502  context_values;
503 
504  XImage
505  *annotate_ximage;
506 
507  /*
508  Initialize annotated image.
509  */
510  (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
511  assert(display != (Display *) NULL);
512  assert(pixel != (XPixelInfo *) NULL);
513  assert(annotate_info != (XAnnotateInfo *) NULL);
514  assert(image != (Image *) NULL);
515  /*
516  Initialize annotated pixmap.
517  */
518  root_window=XRootWindow(display,XDefaultScreen(display));
519  depth=(unsigned int) XDefaultDepth(display,XDefaultScreen(display));
520  annotate_pixmap=XCreatePixmap(display,root_window,annotate_info->width,
521  annotate_info->height,depth);
522  if (annotate_pixmap == (Pixmap) NULL)
523  return(MagickFalse);
524  /*
525  Initialize graphics info.
526  */
527  context_values.background=0;
528  context_values.foreground=(size_t) (~0);
529  context_values.font=annotate_info->font_info->fid;
530  annotate_context=XCreateGC(display,root_window,(unsigned long)
531  (GCBackground | GCFont | GCForeground),&context_values);
532  if (annotate_context == (GC) NULL)
533  return(MagickFalse);
534  /*
535  Draw text to pixmap.
536  */
537  (void) XDrawImageString(display,annotate_pixmap,annotate_context,0,
538  (int) annotate_info->font_info->ascent,annotate_info->text,
539  (int) strlen(annotate_info->text));
540  (void) XFreeGC(display,annotate_context);
541  /*
542  Initialize annotated X image.
543  */
544  annotate_ximage=XGetImage(display,annotate_pixmap,0,0,annotate_info->width,
545  annotate_info->height,AllPlanes,ZPixmap);
546  if (annotate_ximage == (XImage *) NULL)
547  return(MagickFalse);
548  (void) XFreePixmap(display,annotate_pixmap);
549  /*
550  Initialize annotated image.
551  */
552  annotate_image=AcquireImage((ImageInfo *) NULL,exception);
553  if (annotate_image == (Image *) NULL)
554  return(MagickFalse);
555  annotate_image->columns=annotate_info->width;
556  annotate_image->rows=annotate_info->height;
557  /*
558  Transfer annotated X image to image.
559  */
560  width=(unsigned int) image->columns;
561  height=(unsigned int) image->rows;
562  x=0;
563  y=0;
564  (void) XParseGeometry(annotate_info->geometry,&x,&y,&width,&height);
565  (void) GetOneVirtualPixelInfo(image,UndefinedVirtualPixelMethod,(ssize_t) x,
566  (ssize_t) y,&annotate_image->background_color,exception);
567  if (annotate_info->stencil == ForegroundStencil)
568  annotate_image->alpha_trait=BlendPixelTrait;
569  annotate_view=AcquireAuthenticCacheView(annotate_image,exception);
570  for (y=0; y < (int) annotate_image->rows; y++)
571  {
572  int
573  x;
574 
575  Quantum
576  *magick_restrict q;
577 
578  q=GetCacheViewAuthenticPixels(annotate_view,0,(ssize_t) y,
579  annotate_image->columns,1,exception);
580  if (q == (Quantum *) NULL)
581  break;
582  for (x=0; x < (int) annotate_image->columns; x++)
583  {
584  SetPixelAlpha(annotate_image,OpaqueAlpha,q);
585  if (XGetPixel(annotate_ximage,x,y) == 0)
586  {
587  /*
588  Set this pixel to the background color.
589  */
590  SetPixelRed(annotate_image,ScaleShortToQuantum(
591  pixel->box_color.red),q);
592  SetPixelGreen(annotate_image,ScaleShortToQuantum(
593  pixel->box_color.green),q);
594  SetPixelBlue(annotate_image,ScaleShortToQuantum(
595  pixel->box_color.blue),q);
596  if ((annotate_info->stencil == ForegroundStencil) ||
597  (annotate_info->stencil == OpaqueStencil))
598  SetPixelAlpha(annotate_image,TransparentAlpha,q);
599  }
600  else
601  {
602  /*
603  Set this pixel to the pen color.
604  */
605  SetPixelRed(annotate_image,ScaleShortToQuantum(
606  pixel->pen_color.red),q);
607  SetPixelGreen(annotate_image,ScaleShortToQuantum(
608  pixel->pen_color.green),q);
609  SetPixelBlue(annotate_image,ScaleShortToQuantum(
610  pixel->pen_color.blue),q);
611  if (annotate_info->stencil == BackgroundStencil)
612  SetPixelAlpha(annotate_image,TransparentAlpha,q);
613  }
614  q+=GetPixelChannels(annotate_image);
615  }
616  if (SyncCacheViewAuthenticPixels(annotate_view,exception) == MagickFalse)
617  break;
618  }
619  annotate_view=DestroyCacheView(annotate_view);
620  XDestroyImage(annotate_ximage);
621  /*
622  Determine annotate geometry.
623  */
624  (void) XParseGeometry(annotate_info->geometry,&x,&y,&width,&height);
625  if ((width != (unsigned int) annotate_image->columns) ||
626  (height != (unsigned int) annotate_image->rows))
627  {
628  char
629  image_geometry[MagickPathExtent];
630 
631  /*
632  Scale image.
633  */
634  (void) FormatLocaleString(image_geometry,MagickPathExtent,"%ux%u",
635  width,height);
636  (void) TransformImage(&annotate_image,(char *) NULL,image_geometry,
637  exception);
638  }
639  if (annotate_info->degrees != 0.0)
640  {
641  Image
642  *rotate_image;
643 
644  int
645  rotations;
646 
647  double
648  normalized_degrees;
649 
650  /*
651  Rotate image.
652  */
653  rotate_image=RotateImage(annotate_image,annotate_info->degrees,exception);
654  if (rotate_image == (Image *) NULL)
655  return(MagickFalse);
656  annotate_image=DestroyImage(annotate_image);
657  annotate_image=rotate_image;
658  /*
659  Annotation is relative to the degree of rotation.
660  */
661  normalized_degrees=annotate_info->degrees;
662  while (normalized_degrees < -45.0)
663  normalized_degrees+=360.0;
664  for (rotations=0; normalized_degrees > 45.0; rotations++)
665  normalized_degrees-=90.0;
666  switch (rotations % 4)
667  {
668  default:
669  case 0:
670  break;
671  case 1:
672  {
673  /*
674  Rotate 90 degrees.
675  */
676  x-=(int) annotate_image->columns/2;
677  y+=(int) annotate_image->columns/2;
678  break;
679  }
680  case 2:
681  {
682  /*
683  Rotate 180 degrees.
684  */
685  x=x-(int) annotate_image->columns;
686  break;
687  }
688  case 3:
689  {
690  /*
691  Rotate 270 degrees.
692  */
693  x=x-(int) annotate_image->columns/2;
694  y=y-(int) (annotate_image->rows-(annotate_image->columns/2));
695  break;
696  }
697  }
698  }
699  /*
700  Composite text onto the image.
701  */
702  (void) XParseGeometry(annotate_info->geometry,&x,&y,&width,&height);
703  alpha_trait=image->alpha_trait;
704  (void) CompositeImage(image,annotate_image,
705  annotate_image->alpha_trait != UndefinedPixelTrait ? OverCompositeOp :
706  CopyCompositeOp,MagickTrue,(ssize_t) x,(ssize_t) y,exception);
707  image->alpha_trait=alpha_trait;
708  annotate_image=DestroyImage(annotate_image);
709  return(MagickTrue);
710 }
711 
712 /*
713 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
714 % %
715 % %
716 % %
717 % X B e s t F o n t %
718 % %
719 % %
720 % %
721 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
722 %
723 % XBestFont() returns the "best" font. "Best" is defined as a font specified
724 % in the X resource database or a font such that the text width displayed
725 % with the font does not exceed the specified maximum width.
726 %
727 % The format of the XBestFont method is:
728 %
729 % XFontStruct *XBestFont(Display *display,
730 % const XResourceInfo *resource_info,const MagickBooleanType text_font)
731 %
732 % A description of each parameter follows:
733 %
734 % o font: XBestFont returns a pointer to a XFontStruct structure.
735 %
736 % o display: Specifies a connection to an X server; returned from
737 % XOpenDisplay.
738 %
739 % o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
740 %
741 % o text_font: True is font should be mono-spaced (typewriter style).
742 %
743 */
744 
745 static char **FontToList(char *font)
746 {
747  char
748  **fontlist;
749 
750  char
751  *p,
752  *q;
753 
754  int
755  i;
756 
757  unsigned int
758  fonts;
759 
760  if (font == (char *) NULL)
761  return((char **) NULL);
762  /*
763  Convert string to an ASCII list.
764  */
765  fonts=1U;
766  for (p=font; *p != '\0'; p++)
767  if ((*p == ':') || (*p == ';') || (*p == ','))
768  fonts++;
769  fontlist=(char **) AcquireQuantumMemory((size_t) fonts+1UL,sizeof(*fontlist));
770  if (fontlist == (char **) NULL)
771  {
772  ThrowXWindowException(ResourceLimitError,"MemoryAllocationFailed",font);
773  return((char **) NULL);
774  }
775  p=font;
776  for (i=0; i < (int) fonts; i++)
777  {
778  for (q=p; *q != '\0'; q++)
779  if ((*q == ':') || (*q == ';') || (*q == ','))
780  break;
781  fontlist[i]=(char *) AcquireQuantumMemory((size_t) (q-p)+1UL,
782  sizeof(*fontlist[i]));
783  if (fontlist[i] == (char *) NULL)
784  {
785  ThrowXWindowException(ResourceLimitError,"MemoryAllocationFailed",font);
786  return((char **) NULL);
787  }
788  (void) CopyMagickString(fontlist[i],p,(size_t) (q-p+1));
789  p=q+1;
790  }
791  fontlist[i]=(char *) NULL;
792  return(fontlist);
793 }
794 
795 MagickPrivate XFontStruct *XBestFont(Display *display,
796  const XResourceInfo *resource_info,const MagickBooleanType text_font)
797 {
798  static const char
799  *Fonts[]=
800  {
801  "-*-helvetica-medium-r-normal--12-*-*-*-*-*-iso8859-1",
802  "-*-arial-medium-r-normal--12-*-*-*-*-*-iso8859-1",
803  "-*-helvetica-medium-r-normal--12-*-*-*-*-*-iso8859-15",
804  "-*-arial-medium-r-normal--12-*-*-*-*-*-iso8859-15",
805  "-*-helvetica-medium-r-normal--12-*-*-*-*-*-*-*",
806  "-*-arial-medium-r-normal--12-*-*-*-*-*-*-*",
807  "variable",
808  "fixed",
809  (char *) NULL
810  },
811  *TextFonts[]=
812  {
813  "-*-courier-medium-r-normal-*-12-*-*-*-*-*-iso8859-1",
814  "-*-courier-medium-r-normal-*-12-*-*-*-*-*-iso8859-15",
815  "-*-fixed-medium-r-normal-*-12-*-*-*-*-*-*-*",
816  "fixed",
817  (char *) NULL
818  };
819 
820  char
821  *font_name;
822 
823  const char
824  **p;
825 
826  XFontStruct
827  *font_info;
828 
829  font_info=(XFontStruct *) NULL;
830  font_name=resource_info->font;
831  if (text_font != MagickFalse)
832  font_name=resource_info->text_font;
833  if ((font_name != (char *) NULL) && (*font_name != '\0'))
834  {
835  char
836  **fontlist;
837 
838  int
839  i;
840 
841  /*
842  Load preferred font specified in the X resource database.
843  */
844  fontlist=FontToList(font_name);
845  if (fontlist != (char **) NULL)
846  {
847  for (i=0; fontlist[i] != (char *) NULL; i++)
848  {
849  if (font_info == (XFontStruct *) NULL)
850  font_info=XLoadQueryFont(display,fontlist[i]);
851  fontlist[i]=DestroyString(fontlist[i]);
852  }
853  fontlist=(char **) RelinquishMagickMemory(fontlist);
854  }
855  if (font_info == (XFontStruct *) NULL)
856  ThrowXWindowException(XServerError,"UnableToLoadFont",font_name);
857  }
858  /*
859  Load fonts from list of fonts until one is found.
860  */
861  p=Fonts;
862  if (text_font != MagickFalse)
863  p=TextFonts;
864  if (XDisplayHeight(display,XDefaultScreen(display)) >= 748)
865  p++;
866  while (*p != (char *) NULL)
867  {
868  if (font_info != (XFontStruct *) NULL)
869  break;
870  font_info=XLoadQueryFont(display,(char *) *p);
871  p++;
872  }
873  return(font_info);
874 }
875 
876 /*
877 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
878 % %
879 % %
880 % %
881 % X B e s t I c o n S i z e %
882 % %
883 % %
884 % %
885 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
886 %
887 % XBestIconSize() returns the "best" icon size. "Best" is defined as an icon
888 % size that maintains the aspect ratio of the image. If the window manager
889 % has preferred icon sizes, one of the preferred sizes is used.
890 %
891 % The format of the XBestIconSize method is:
892 %
893 % void XBestIconSize(Display *display,XWindowInfo *window,Image *image)
894 %
895 % A description of each parameter follows:
896 %
897 % o display: Specifies a connection to an X server; returned from
898 % XOpenDisplay.
899 %
900 % o image: the image.
901 %
902 */
903 MagickPrivate void XBestIconSize(Display *display,XWindowInfo *window,
904  Image *image)
905 {
906  int
907  i,
908  number_sizes;
909 
910  double
911  scale_factor;
912 
913  unsigned int
914  height,
915  icon_height,
916  icon_width,
917  width;
918 
919  Window
920  root_window;
921 
922  XIconSize
923  *icon_size,
924  *size_list;
925 
926  /*
927  Determine if the window manager has specified preferred icon sizes.
928  */
929  (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
930  assert(display != (Display *) NULL);
931  assert(window != (XWindowInfo *) NULL);
932  assert(image != (Image *) NULL);
933  window->width=MaxIconSize;
934  window->height=MaxIconSize;
935  icon_size=(XIconSize *) NULL;
936  number_sizes=0;
937  root_window=XRootWindow(display,window->screen);
938  if (XGetIconSizes(display,root_window,&size_list,&number_sizes) != 0)
939  if ((number_sizes > 0) && (size_list != (XIconSize *) NULL))
940  icon_size=size_list;
941  if (icon_size == (XIconSize *) NULL)
942  {
943  /*
944  Window manager does not restrict icon size.
945  */
946  icon_size=XAllocIconSize();
947  if (icon_size == (XIconSize *) NULL)
948  {
949  ThrowXWindowException(ResourceLimitError,"MemoryAllocationFailed",
950  image->filename);
951  return;
952  }
953  icon_size->min_width=1;
954  icon_size->max_width=MaxIconSize;
955  icon_size->min_height=1;
956  icon_size->max_height=MaxIconSize;
957  icon_size->width_inc=1;
958  icon_size->height_inc=1;
959  }
960  /*
961  Determine aspect ratio of image.
962  */
963  width=(unsigned int) image->columns;
964  height=(unsigned int) image->rows;
965  i=0;
966  if (window->crop_geometry)
967  (void) XParseGeometry(window->crop_geometry,&i,&i,&width,&height);
968  /*
969  Look for an icon size that maintains the aspect ratio of image.
970  */
971  scale_factor=(double) icon_size->max_width/width;
972  if (scale_factor > ((double) icon_size->max_height/height))
973  scale_factor=(double) icon_size->max_height/height;
974  icon_width=(unsigned int) icon_size->min_width;
975  while ((int) icon_width < icon_size->max_width)
976  {
977  if (icon_width >= (unsigned int) (scale_factor*width+0.5))
978  break;
979  icon_width+=icon_size->width_inc;
980  }
981  icon_height=(unsigned int) icon_size->min_height;
982  while ((int) icon_height < icon_size->max_height)
983  {
984  if (icon_height >= (unsigned int) (scale_factor*height+0.5))
985  break;
986  icon_height+=icon_size->height_inc;
987  }
988  (void) XFree((void *) icon_size);
989  window->width=icon_width;
990  window->height=icon_height;
991 }
992 
993 /*
994 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
995 % %
996 % %
997 % %
998 % X B e s t P i x e l %
999 % %
1000 % %
1001 % %
1002 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1003 %
1004 % XBestPixel() returns a pixel from an array of pixels that is closest to the
1005 % requested color. If the color array is NULL, the colors are obtained from
1006 % the X server.
1007 %
1008 % The format of the XBestPixel method is:
1009 %
1010 % void XBestPixel(Display *display,const Colormap colormap,XColor *colors,
1011 % unsigned int number_colors,XColor *color)
1012 %
1013 % A description of each parameter follows:
1014 %
1015 % o pixel: XBestPixel returns the pixel value closest to the requested
1016 % color.
1017 %
1018 % o display: Specifies a connection to an X server; returned from
1019 % XOpenDisplay.
1020 %
1021 % o colormap: Specifies the ID of the X server colormap.
1022 %
1023 % o colors: Specifies an array of XColor structures.
1024 %
1025 % o number_colors: Specifies the number of XColor structures in the
1026 % color definition array.
1027 %
1028 % o color: Specifies the desired RGB value to find in the colors array.
1029 %
1030 */
1031 MagickPrivate void XBestPixel(Display *display,const Colormap colormap,
1032  XColor *colors,unsigned int number_colors,XColor *color)
1033 {
1035  query_server;
1036 
1037  PixelInfo
1038  pixel;
1039 
1040  double
1041  min_distance;
1042 
1043  double
1044  distance;
1045 
1046  int
1047  i,
1048  j;
1049 
1050  Status
1051  status;
1052 
1053  /*
1054  Find closest representation for the requested RGB color.
1055  */
1056  (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
1057  assert(display != (Display *) NULL);
1058  assert(color != (XColor *) NULL);
1059  status=XAllocColor(display,colormap,color);
1060  if (status != False)
1061  return;
1062  query_server=colors == (XColor *) NULL ? MagickTrue : MagickFalse;
1063  if (query_server != MagickFalse)
1064  {
1065  /*
1066  Read X server colormap.
1067  */
1068  colors=(XColor *) AcquireQuantumMemory(number_colors,sizeof(*colors));
1069  if (colors == (XColor *) NULL)
1070  {
1071  ThrowXWindowException(ResourceLimitError,"MemoryAllocationFailed",
1072  "...");
1073  return;
1074  }
1075  for (i=0; i < (int) number_colors; i++)
1076  colors[i].pixel=(size_t) i;
1077  if (number_colors > 256)
1078  number_colors=256;
1079  (void) XQueryColors(display,colormap,colors,(int) number_colors);
1080  }
1081  min_distance=3.0*((double) QuantumRange+1.0)*((double)
1082  QuantumRange+1.0);
1083  j=0;
1084  for (i=0; i < (int) number_colors; i++)
1085  {
1086  pixel.red=colors[i].red-(double) color->red;
1087  distance=pixel.red*pixel.red;
1088  if (distance > min_distance)
1089  continue;
1090  pixel.green=colors[i].green-(double) color->green;
1091  distance+=pixel.green*pixel.green;
1092  if (distance > min_distance)
1093  continue;
1094  pixel.blue=colors[i].blue-(double) color->blue;
1095  distance+=pixel.blue*pixel.blue;
1096  if (distance > min_distance)
1097  continue;
1098  min_distance=distance;
1099  color->pixel=colors[i].pixel;
1100  j=i;
1101  }
1102  (void) XAllocColor(display,colormap,&colors[j]);
1103  if (query_server != MagickFalse)
1104  colors=(XColor *) RelinquishMagickMemory(colors);
1105 }
1106 
1107 /*
1108 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1109 % %
1110 % %
1111 % %
1112 % X B e s t V i s u a l I n f o %
1113 % %
1114 % %
1115 % %
1116 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1117 %
1118 % XBestVisualInfo() returns visual information for a visual that is the "best"
1119 % the server supports. "Best" is defined as:
1120 %
1121 % 1. Restrict the visual list to those supported by the default screen.
1122 %
1123 % 2. If a visual type is specified, restrict the visual list to those of
1124 % that type.
1125 %
1126 % 3. If a map type is specified, choose the visual that matches the id
1127 % specified by the Standard Colormap.
1128 %
1129 % 4 From the list of visuals, choose one that can display the most
1130 % simultaneous colors. If more than one visual can display the same
1131 % number of simultaneous colors, one is chosen based on a rank.
1132 %
1133 % The format of the XBestVisualInfo method is:
1134 %
1135 % XVisualInfo *XBestVisualInfo(Display *display,
1136 % XStandardColormap *map_info,XResourceInfo *resource_info)
1137 %
1138 % A description of each parameter follows:
1139 %
1140 % o visual_info: XBestVisualInfo returns a pointer to a X11 XVisualInfo
1141 % structure.
1142 %
1143 % o display: Specifies a connection to an X server; returned from
1144 % XOpenDisplay.
1145 %
1146 % o map_info: If map_type is specified, this structure is initialized
1147 % with info from the Standard Colormap.
1148 %
1149 % o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
1150 %
1151 */
1152 MagickPrivate XVisualInfo *XBestVisualInfo(Display *display,
1153  XStandardColormap *map_info,XResourceInfo *resource_info)
1154 {
1155 #define MaxStandardColormaps 7
1156 #define XVisualColormapSize(visual_info) MagickMin((unsigned int) (\
1157  (visual_info->klass == TrueColor) || (visual_info->klass == DirectColor) ? \
1158  visual_info->red_mask | visual_info->green_mask | visual_info->blue_mask : \
1159  (unsigned long) visual_info->colormap_size),1UL << visual_info->depth)
1160 
1161  char
1162  *map_type,
1163  *visual_type;
1164 
1165  int
1166  visual_mask;
1167 
1168  int
1169  i;
1170 
1171  size_t
1172  one;
1173 
1174  static int
1175  number_visuals;
1176 
1177  static XVisualInfo
1178  visual_template;
1179 
1180  XVisualInfo
1181  *visual_info,
1182  *visual_list;
1183 
1184  /*
1185  Restrict visual search by screen number.
1186  */
1187  (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
1188  assert(display != (Display *) NULL);
1189  assert(map_info != (XStandardColormap *) NULL);
1190  assert(resource_info != (XResourceInfo *) NULL);
1191  map_type=resource_info->map_type;
1192  visual_type=resource_info->visual_type;
1193  visual_mask=VisualScreenMask;
1194  visual_template.screen=XDefaultScreen(display);
1195  visual_template.depth=XDefaultDepth(display,XDefaultScreen(display));
1196  one=1;
1197  if ((resource_info->immutable != MagickFalse) && (resource_info->colors != 0))
1198  if (resource_info->colors <= (one << (size_t) visual_template.depth))
1199  visual_mask|=VisualDepthMask;
1200  if (visual_type != (char *) NULL)
1201  {
1202  /*
1203  Restrict visual search by class or visual id.
1204  */
1205  if (LocaleCompare("staticgray",visual_type) == 0)
1206  {
1207  visual_mask|=VisualClassMask;
1208  visual_template.klass=StaticGray;
1209  }
1210  else
1211  if (LocaleCompare("grayscale",visual_type) == 0)
1212  {
1213  visual_mask|=VisualClassMask;
1214  visual_template.klass=GrayScale;
1215  }
1216  else
1217  if (LocaleCompare("staticcolor",visual_type) == 0)
1218  {
1219  visual_mask|=VisualClassMask;
1220  visual_template.klass=StaticColor;
1221  }
1222  else
1223  if (LocaleCompare("pseudocolor",visual_type) == 0)
1224  {
1225  visual_mask|=VisualClassMask;
1226  visual_template.klass=PseudoColor;
1227  }
1228  else
1229  if (LocaleCompare("truecolor",visual_type) == 0)
1230  {
1231  visual_mask|=VisualClassMask;
1232  visual_template.klass=TrueColor;
1233  }
1234  else
1235  if (LocaleCompare("directcolor",visual_type) == 0)
1236  {
1237  visual_mask|=VisualClassMask;
1238  visual_template.klass=DirectColor;
1239  }
1240  else
1241  if (LocaleCompare("default",visual_type) == 0)
1242  {
1243  visual_mask|=VisualIDMask;
1244  visual_template.visualid=XVisualIDFromVisual(
1245  XDefaultVisual(display,XDefaultScreen(display)));
1246  }
1247  else
1248  if (isdigit((int) ((unsigned char) *visual_type)) != 0)
1249  {
1250  visual_mask|=VisualIDMask;
1251  visual_template.visualid=
1252  strtol(visual_type,(char **) NULL,0);
1253  }
1254  else
1255  ThrowXWindowException(XServerError,
1256  "UnrecognizedVisualSpecifier",visual_type);
1257  }
1258  /*
1259  Get all visuals that meet our criteria so far.
1260  */
1261  number_visuals=0;
1262  visual_list=XGetVisualInfo(display,visual_mask,&visual_template,
1263  &number_visuals);
1264  visual_mask=VisualScreenMask | VisualIDMask;
1265  if ((number_visuals == 0) || (visual_list == (XVisualInfo *) NULL))
1266  {
1267  /*
1268  Failed to get visual; try using the default visual.
1269  */
1270  ThrowXWindowException(XServerWarning,"UnableToGetVisual",visual_type);
1271  visual_template.visualid=XVisualIDFromVisual(XDefaultVisual(display,
1272  XDefaultScreen(display)));
1273  visual_list=XGetVisualInfo(display,visual_mask,&visual_template,
1274  &number_visuals);
1275  if ((number_visuals == 0) || (visual_list == (XVisualInfo *) NULL))
1276  return((XVisualInfo *) NULL);
1277  ThrowXWindowException(XServerWarning,"UsingDefaultVisual",
1278  XVisualClassName(visual_list->klass));
1279  }
1280  resource_info->color_recovery=MagickFalse;
1281  if ((map_info != (XStandardColormap *) NULL) && (map_type != (char *) NULL))
1282  {
1283  Atom
1284  map_property;
1285 
1286  char
1287  map_name[MagickPathExtent];
1288 
1289  int
1290  j,
1291  number_maps;
1292 
1293  Status
1294  status;
1295 
1296  Window
1297  root_window;
1298 
1299  XStandardColormap
1300  *map_list;
1301 
1302  /*
1303  Choose a visual associated with a standard colormap.
1304  */
1305  root_window=XRootWindow(display,XDefaultScreen(display));
1306  status=False;
1307  number_maps=0;
1308  if (LocaleCompare(map_type,"list") != 0)
1309  {
1310  /*
1311  User specified Standard Colormap.
1312  */
1313  (void) FormatLocaleString((char *) map_name,MagickPathExtent,
1314  "RGB_%s_MAP",map_type);
1315  LocaleUpper(map_name);
1316  map_property=XInternAtom(display,(char *) map_name,MagickTrue);
1317  if (map_property != (Atom) NULL)
1318  status=XGetRGBColormaps(display,root_window,&map_list,&number_maps,
1319  map_property);
1320  }
1321  else
1322  {
1323  static const char
1324  *colormap[MaxStandardColormaps]=
1325  {
1326  "_HP_RGB_SMOOTH_MAP_LIST",
1327  "RGB_BEST_MAP",
1328  "RGB_DEFAULT_MAP",
1329  "RGB_GRAY_MAP",
1330  "RGB_RED_MAP",
1331  "RGB_GREEN_MAP",
1332  "RGB_BLUE_MAP",
1333  };
1334 
1335  /*
1336  Choose a standard colormap from a list.
1337  */
1338  for (i=0; i < MaxStandardColormaps; i++)
1339  {
1340  map_property=XInternAtom(display,(char *) colormap[i],MagickTrue);
1341  if (map_property == (Atom) NULL)
1342  continue;
1343  status=XGetRGBColormaps(display,root_window,&map_list,&number_maps,
1344  map_property);
1345  if (status != False)
1346  break;
1347  }
1348  resource_info->color_recovery=i == 0 ? MagickTrue : MagickFalse;
1349  }
1350  if (status == False)
1351  {
1352  ThrowXWindowException(XServerError,"UnableToGetStandardColormap",
1353  map_type);
1354  return((XVisualInfo *) NULL);
1355  }
1356  /*
1357  Search all Standard Colormaps and visuals for ids that match.
1358  */
1359  *map_info=map_list[0];
1360 #if !defined(PRE_R4_ICCCM)
1361  visual_template.visualid=XVisualIDFromVisual(visual_list[0].visual);
1362  for (i=0; i < number_maps; i++)
1363  for (j=0; j < number_visuals; j++)
1364  if (map_list[i].visualid ==
1365  XVisualIDFromVisual(visual_list[j].visual))
1366  {
1367  *map_info=map_list[i];
1368  visual_template.visualid=XVisualIDFromVisual(
1369  visual_list[j].visual);
1370  break;
1371  }
1372  if (map_info->visualid != visual_template.visualid)
1373  {
1374  ThrowXWindowException(XServerError,
1375  "UnableToMatchVisualToStandardColormap",map_type);
1376  return((XVisualInfo *) NULL);
1377  }
1378 #endif
1379  if (map_info->colormap == (Colormap) NULL)
1380  {
1381  ThrowXWindowException(XServerError,"StandardColormapIsNotInitialized",
1382  map_type);
1383  return((XVisualInfo *) NULL);
1384  }
1385  (void) XFree((void *) map_list);
1386  }
1387  else
1388  {
1389  static const unsigned int
1390  rank[]=
1391  {
1392  StaticGray,
1393  GrayScale,
1394  StaticColor,
1395  DirectColor,
1396  TrueColor,
1397  PseudoColor
1398  };
1399 
1400  XVisualInfo
1401  *p;
1402 
1403  /*
1404  Pick one visual that displays the most simultaneous colors.
1405  */
1406  visual_info=visual_list;
1407  p=visual_list;
1408  for (i=1; i < number_visuals; i++)
1409  {
1410  p++;
1411  if (XVisualColormapSize(p) > XVisualColormapSize(visual_info))
1412  visual_info=p;
1413  else
1414  if (XVisualColormapSize(p) == XVisualColormapSize(visual_info))
1415  if (rank[p->klass] > rank[visual_info->klass])
1416  visual_info=p;
1417  }
1418  visual_template.visualid=XVisualIDFromVisual(visual_info->visual);
1419  }
1420  (void) XFree((void *) visual_list);
1421  /*
1422  Retrieve only one visual by its screen & id number.
1423  */
1424  visual_info=XGetVisualInfo(display,visual_mask,&visual_template,
1425  &number_visuals);
1426  if ((number_visuals == 0) || (visual_info == (XVisualInfo *) NULL))
1427  return((XVisualInfo *) NULL);
1428  return(visual_info);
1429 }
1430 
1431 /*
1432 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1433 % %
1434 % %
1435 % %
1436 % X C h e c k D e f i n e C u r s o r %
1437 % %
1438 % %
1439 % %
1440 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1441 %
1442 % XCheckDefineCursor() prevents cursor changes on the root window.
1443 %
1444 % The format of the XXCheckDefineCursor method is:
1445 %
1446 % XCheckDefineCursor(display,window,cursor)
1447 %
1448 % A description of each parameter follows:
1449 %
1450 % o display: Specifies a connection to an X server; returned from
1451 % XOpenDisplay.
1452 %
1453 % o window: the window.
1454 %
1455 % o cursor: the cursor.
1456 %
1457 */
1458 MagickPrivate int XCheckDefineCursor(Display *display,Window window,
1459  Cursor cursor)
1460 {
1461  (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
1462  assert(display != (Display *) NULL);
1463  if (window == XRootWindow(display,XDefaultScreen(display)))
1464  return(0);
1465  return(XDefineCursor(display,window,cursor));
1466 }
1467 
1468 /*
1469 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1470 % %
1471 % %
1472 % %
1473 % X C h e c k R e f r e s h W i n d o w s %
1474 % %
1475 % %
1476 % %
1477 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1478 %
1479 % XCheckRefreshWindows() checks the X server for exposure events for a
1480 % particular window and updates the areassociated with the exposure event.
1481 %
1482 % The format of the XCheckRefreshWindows method is:
1483 %
1484 % void XCheckRefreshWindows(Display *display,XWindows *windows)
1485 %
1486 % A description of each parameter follows:
1487 %
1488 % o display: Specifies a connection to an X server; returned from
1489 % XOpenDisplay.
1490 %
1491 % o windows: Specifies a pointer to a XWindows structure.
1492 %
1493 */
1494 MagickPrivate void XCheckRefreshWindows(Display *display,XWindows *windows)
1495 {
1496  Window
1497  id;
1498 
1499  XEvent
1500  event;
1501 
1502  (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
1503  assert(display != (Display *) NULL);
1504  assert(windows != (XWindows *) NULL);
1505  XDelay(display,SuspendTime);
1506  id=windows->command.id;
1507  while (XCheckTypedWindowEvent(display,id,Expose,&event) != MagickFalse)
1508  (void) XCommandWidget(display,windows,(char const **) NULL,&event);
1509  id=windows->image.id;
1510  while (XCheckTypedWindowEvent(display,id,Expose,&event) != MagickFalse)
1511  XRefreshWindow(display,&windows->image,&event);
1512  XDelay(display,SuspendTime << 1);
1513  id=windows->command.id;
1514  while (XCheckTypedWindowEvent(display,id,Expose,&event) != MagickFalse)
1515  (void) XCommandWidget(display,windows,(char const **) NULL,&event);
1516  id=windows->image.id;
1517  while (XCheckTypedWindowEvent(display,id,Expose,&event) != MagickFalse)
1518  XRefreshWindow(display,&windows->image,&event);
1519 }
1520 
1521 /*
1522 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1523 % %
1524 % %
1525 % %
1526 % X C l i e n t M e s s a g e %
1527 % %
1528 % %
1529 % %
1530 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1531 %
1532 % XClientMessage() sends a reason to a window with XSendEvent. The reason is
1533 % initialized with a particular protocol type and atom.
1534 %
1535 % The format of the XClientMessage function is:
1536 %
1537 % XClientMessage(display,window,protocol,reason,timestamp)
1538 %
1539 % A description of each parameter follows:
1540 %
1541 % o display: Specifies a pointer to the Display structure; returned from
1542 % XOpenDisplay.
1543 %
1544 % o window: Specifies a pointer to a Window structure.
1545 %
1546 % o protocol: Specifies an atom value.
1547 %
1548 % o reason: Specifies an atom value which is the reason to send.
1549 %
1550 % o timestamp: Specifies a value of type Time.
1551 %
1552 */
1553 MagickPrivate void XClientMessage(Display *display,const Window window,
1554  const Atom protocol,const Atom reason,const Time timestamp)
1555 {
1556  XClientMessageEvent
1557  client_event;
1558 
1559  assert(display != (Display *) NULL);
1560  (void) memset(&client_event,0,sizeof(client_event));
1561  client_event.type=ClientMessage;
1562  client_event.window=window;
1563  client_event.message_type=protocol;
1564  client_event.format=32;
1565  client_event.data.l[0]=(long) reason;
1566  client_event.data.l[1]=(long) timestamp;
1567  (void) XSendEvent(display,window,MagickFalse,NoEventMask,(XEvent *)
1568  &client_event);
1569 }
1570 
1571 /*
1572 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1573 % %
1574 % %
1575 % %
1576 + X C l i e n t W i n d o w %
1577 % %
1578 % %
1579 % %
1580 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1581 %
1582 % XClientWindow() finds a window, at or below the specified window, which has
1583 % a WM_STATE property. If such a window is found, it is returned, otherwise
1584 % the argument window is returned.
1585 %
1586 % The format of the XClientWindow function is:
1587 %
1588 % client_window=XClientWindow(display,target_window)
1589 %
1590 % A description of each parameter follows:
1591 %
1592 % o client_window: XClientWindow returns a window, at or below the specified
1593 % window, which has a WM_STATE property otherwise the argument
1594 % target_window is returned.
1595 %
1596 % o display: Specifies a pointer to the Display structure; returned from
1597 % XOpenDisplay.
1598 %
1599 % o target_window: Specifies the window to find a WM_STATE property.
1600 %
1601 */
1602 static Window XClientWindow(Display *display,Window target_window)
1603 {
1604  Atom
1605  state,
1606  type;
1607 
1608  int
1609  format;
1610 
1611  Status
1612  status;
1613 
1614  unsigned char
1615  *data;
1616 
1617  unsigned long
1618  after,
1619  number_items;
1620 
1621  Window
1622  client_window;
1623 
1624  (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
1625  assert(display != (Display *) NULL);
1626  state=XInternAtom(display,"WM_STATE",MagickTrue);
1627  if (state == (Atom) NULL)
1628  return(target_window);
1629  type=(Atom) NULL;
1630  status=XGetWindowProperty(display,target_window,state,0L,0L,MagickFalse,
1631  (Atom) AnyPropertyType,&type,&format,&number_items,&after,&data);
1632  if ((status == Success) && (type != (Atom) NULL))
1633  return(target_window);
1634  client_window=XWindowByProperty(display,target_window,state);
1635  if (client_window == (Window) NULL)
1636  return(target_window);
1637  return(client_window);
1638 }
1639 
1640 /*
1641 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1642 % %
1643 % %
1644 % %
1645 + X C o m p o n e n t T e r m i n u s %
1646 % %
1647 % %
1648 % %
1649 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1650 %
1651 % XComponentTerminus() destroys the module component.
1652 %
1653 % The format of the XComponentTerminus method is:
1654 %
1655 % XComponentTerminus(void)
1656 %
1657 */
1658 MagickPrivate void XComponentTerminus(void)
1659 {
1660  DestroyXResources();
1661 }
1662 
1663 /*
1664 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1665 % %
1666 % %
1667 % %
1668 % X C o n f i g u r e I m a g e C o l o r m a p %
1669 % %
1670 % %
1671 % %
1672 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1673 %
1674 % XConfigureImageColormap() creates a new X colormap.
1675 %
1676 % The format of the XConfigureImageColormap method is:
1677 %
1678 % void XConfigureImageColormap(Display *display,
1679 % XResourceInfo *resource_info,XWindows *windows,Image *image,
1680 % ExceptionInfo *exception)
1681 %
1682 % A description of each parameter follows:
1683 %
1684 % o display: Specifies a connection to an X server; returned from
1685 % XOpenDisplay.
1686 %
1687 % o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
1688 %
1689 % o windows: Specifies a pointer to a XWindows structure.
1690 %
1691 % o image: the image.
1692 %
1693 % o exception: return any errors or warnings in this structure.
1694 %
1695 */
1696 MagickPrivate void XConfigureImageColormap(Display *display,
1697  XResourceInfo *resource_info,XWindows *windows,Image *image,
1698  ExceptionInfo *exception)
1699 {
1700  Colormap
1701  colormap;
1702 
1703  /*
1704  Make standard colormap.
1705  */
1706  XSetCursorState(display,windows,MagickTrue);
1707  XCheckRefreshWindows(display,windows);
1708  XMakeStandardColormap(display,windows->visual_info,resource_info,image,
1709  windows->map_info,windows->pixel_info,exception);
1710  colormap=windows->map_info->colormap;
1711  (void) XSetWindowColormap(display,windows->image.id,colormap);
1712  (void) XSetWindowColormap(display,windows->command.id,colormap);
1713  (void) XSetWindowColormap(display,windows->widget.id,colormap);
1714  if (windows->magnify.mapped != MagickFalse)
1715  (void) XSetWindowColormap(display,windows->magnify.id,colormap);
1716  if (windows->pan.mapped != MagickFalse)
1717  (void) XSetWindowColormap(display,windows->pan.id,colormap);
1718  XSetCursorState(display,windows,MagickFalse);
1719  XClientMessage(display,windows->image.id,windows->im_protocols,
1720  windows->im_update_colormap,CurrentTime);
1721 }
1722 
1723 /*
1724 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1725 % %
1726 % %
1727 % %
1728 % X C o n s t r a i n W i n d o w P o s i t i o n %
1729 % %
1730 % %
1731 % %
1732 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1733 %
1734 % XConstrainWindowPosition() assures a window is positioned within the X
1735 % server boundaries.
1736 %
1737 % The format of the XConstrainWindowPosition method is:
1738 %
1739 % void XConstrainWindowPosition(Display *display,XWindowInfo *window_info)
1740 %
1741 % A description of each parameter follows:
1742 %
1743 % o display: Specifies a pointer to the Display structure; returned from
1744 % XOpenDisplay.
1745 %
1746 % o window_info: Specifies a pointer to a XWindowInfo structure.
1747 %
1748 */
1749 MagickPrivate void XConstrainWindowPosition(Display *display,
1750  XWindowInfo *window_info)
1751 {
1752  int
1753  limit;
1754 
1755  (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
1756  assert(display != (Display *) NULL);
1757  assert(window_info != (XWindowInfo *) NULL);
1758  limit=XDisplayWidth(display,window_info->screen)-window_info->width;
1759  if (window_info->x < 0)
1760  window_info->x=0;
1761  else
1762  if (window_info->x > (int) limit)
1763  window_info->x=(int) limit;
1764  limit=XDisplayHeight(display,window_info->screen)-window_info->height;
1765  if (window_info->y < 0)
1766  window_info->y=0;
1767  else
1768  if (window_info->y > limit)
1769  window_info->y=limit;
1770 }
1771 
1772 /*
1773 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1774 % %
1775 % %
1776 % %
1777 % X D e l a y %
1778 % %
1779 % %
1780 % %
1781 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1782 %
1783 % XDelay() suspends program execution for the number of milliseconds
1784 % specified.
1785 %
1786 % The format of the Delay method is:
1787 %
1788 % void XDelay(Display *display,const size_t milliseconds)
1789 %
1790 % A description of each parameter follows:
1791 %
1792 % o display: Specifies a pointer to the Display structure; returned from
1793 % XOpenDisplay.
1794 %
1795 % o milliseconds: Specifies the number of milliseconds to delay before
1796 % returning.
1797 %
1798 */
1799 MagickPrivate void XDelay(Display *display,const size_t milliseconds)
1800 {
1801  assert(display != (Display *) NULL);
1802  (void) XFlush(display);
1803  MagickDelay(milliseconds);
1804 }
1805 
1806 /*
1807 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1808 % %
1809 % %
1810 % %
1811 % X D e s t r o y R e s o u r c e I n f o %
1812 % %
1813 % %
1814 % %
1815 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1816 %
1817 % XDestroyResourceInfo() frees memory associated with the XResourceInfo
1818 % structure.
1819 %
1820 % The format of the XDestroyResourceInfo method is:
1821 %
1822 % void XDestroyResourceInfo(XResourceInfo *resource_info)
1823 %
1824 % A description of each parameter follows:
1825 %
1826 % o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
1827 %
1828 */
1829 MagickExport void XDestroyResourceInfo(XResourceInfo *resource_info)
1830 {
1831  if (resource_info->image_geometry != (char *) NULL)
1832  resource_info->image_geometry=(char *)
1833  RelinquishMagickMemory(resource_info->image_geometry);
1834  if (resource_info->quantize_info != (QuantizeInfo *) NULL)
1835  resource_info->quantize_info=DestroyQuantizeInfo(
1836  resource_info->quantize_info);
1837  if (resource_info->client_name != (char *) NULL)
1838  resource_info->client_name=(char *)
1839  RelinquishMagickMemory(resource_info->client_name);
1840  if (resource_info->name != (char *) NULL)
1842  (void) memset(resource_info,0,sizeof(*resource_info));
1843 }
1844 
1845 /*
1846 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1847 % %
1848 % %
1849 % %
1850 % X D e s t r o y W i n d o w C o l o r s %
1851 % %
1852 % %
1853 % %
1854 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1855 %
1856 % XDestroyWindowColors() frees X11 color resources previously saved on a
1857 % window by XRetainWindowColors or programs like xsetroot.
1858 %
1859 % The format of the XDestroyWindowColors method is:
1860 %
1861 % void XDestroyWindowColors(Display *display,Window window)
1862 %
1863 % A description of each parameter follows:
1864 %
1865 % o display: Specifies a connection to an X server; returned from
1866 % XOpenDisplay.
1867 %
1868 % o window: Specifies a pointer to a Window structure.
1869 %
1870 */
1871 MagickPrivate void XDestroyWindowColors(Display *display,Window window)
1872 {
1873  Atom
1874  property,
1875  type;
1876 
1877  int
1878  format;
1879 
1880  Status
1881  status;
1882 
1883  unsigned char
1884  *data;
1885 
1886  unsigned long
1887  after,
1888  length;
1889 
1890  /*
1891  If there are previous resources on the root window, destroy them.
1892  */
1893  (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
1894  assert(display != (Display *) NULL);
1895  property=XInternAtom(display,"_XSETROOT_ID",MagickFalse);
1896  if (property == (Atom) NULL)
1897  {
1898  ThrowXWindowException(XServerError,"UnableToCreateProperty",
1899  "_XSETROOT_ID");
1900  return;
1901  }
1902  status=XGetWindowProperty(display,window,property,0L,1L,MagickTrue,
1903  (Atom) AnyPropertyType,&type,&format,&length,&after,&data);
1904  if (status != Success)
1905  return;
1906  if ((type == XA_PIXMAP) && (format == 32) && (length == 1) && (after == 0))
1907  {
1908  (void) XKillClient(display,(XID) (*((Pixmap *) data)));
1909  (void) XDeleteProperty(display,window,property);
1910  }
1911  if (type != None)
1912  (void) XFree((void *) data);
1913 }
1914 
1915 /*
1916 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1917 % %
1918 % %
1919 % %
1920 % X D i s p l a y I m a g e I n f o %
1921 % %
1922 % %
1923 % %
1924 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1925 %
1926 % XDisplayImageInfo() displays information about an X image.
1927 %
1928 % The format of the XDisplayImageInfo method is:
1929 %
1930 % void XDisplayImageInfo(Display *display,
1931 % const XResourceInfo *resource_info,XWindows *windows,Image *undo_image,
1932 % Image *image,ExceptionInfo *exception)
1933 %
1934 % A description of each parameter follows:
1935 %
1936 % o display: Specifies a connection to an X server; returned from
1937 % XOpenDisplay.
1938 %
1939 % o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
1940 %
1941 % o windows: Specifies a pointer to a XWindows structure.
1942 %
1943 % o undo_image: the undo image.
1944 %
1945 % o image: the image.
1946 %
1947 % o exception: return any errors or warnings in this structure.
1948 %
1949 */
1950 MagickPrivate void XDisplayImageInfo(Display *display,
1951  const XResourceInfo *resource_info,XWindows *windows,Image *undo_image,
1952  Image *image,ExceptionInfo *exception)
1953 {
1954  char
1955  filename[MagickPathExtent],
1956  *text,
1957  **textlist;
1958 
1959  FILE
1960  *file;
1961 
1962  int
1963  unique_file;
1964 
1965  ssize_t
1966  i;
1967 
1968  size_t
1969  number_pixels;
1970 
1971  ssize_t
1972  bytes;
1973 
1974  unsigned int
1975  levels;
1976 
1977  /*
1978  Write info about the X server to a file.
1979  */
1980  assert(display != (Display *) NULL);
1981  assert(resource_info != (XResourceInfo *) NULL);
1982  assert(windows != (XWindows *) NULL);
1983  assert(image != (Image *) NULL);
1984  if (image->debug)
1985  (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
1986  file=(FILE *) NULL;
1987  unique_file=AcquireUniqueFileResource(filename);
1988  if (unique_file != -1)
1989  file=fdopen(unique_file,"w");
1990  if ((unique_file == -1) || (file == (FILE *) NULL))
1991  {
1992  XNoticeWidget(display,windows,"Unable to display image info",filename);
1993  return;
1994  }
1995  if (resource_info->gamma_correct != MagickFalse)
1996  if (resource_info->display_gamma != (char *) NULL)
1997  (void) FormatLocaleFile(file,"Display\n gamma: %s\n\n",
1998  resource_info->display_gamma);
1999  /*
2000  Write info about the X image to a file.
2001  */
2002  (void) FormatLocaleFile(file,"X\n visual: %s\n",
2003  XVisualClassName((int) windows->image.storage_class));
2004  (void) FormatLocaleFile(file," depth: %d\n",windows->image.ximage->depth);
2005  if (windows->visual_info->colormap_size != 0)
2006  (void) FormatLocaleFile(file," colormap size: %d\n",
2007  windows->visual_info->colormap_size);
2008  if (resource_info->colormap== SharedColormap)
2009  (void) FormatLocaleFile(file," colormap type: Shared\n");
2010  else
2011  (void) FormatLocaleFile(file," colormap type: Private\n");
2012  (void) FormatLocaleFile(file," geometry: %dx%d\n",
2013  windows->image.ximage->width,windows->image.ximage->height);
2014  if (windows->image.crop_geometry != (char *) NULL)
2015  (void) FormatLocaleFile(file," crop geometry: %s\n",
2016  windows->image.crop_geometry);
2017  if (windows->image.pixmap == (Pixmap) NULL)
2018  (void) FormatLocaleFile(file," type: X Image\n");
2019  else
2020  (void) FormatLocaleFile(file," type: Pixmap\n");
2021  if (windows->image.shape != MagickFalse)
2022  (void) FormatLocaleFile(file," non-rectangular shape: True\n");
2023  else
2024  (void) FormatLocaleFile(file," non-rectangular shape: False\n");
2025  if (windows->image.shared_memory != MagickFalse)
2026  (void) FormatLocaleFile(file," shared memory: True\n");
2027  else
2028  (void) FormatLocaleFile(file," shared memory: False\n");
2029  (void) FormatLocaleFile(file,"\n");
2030  if (resource_info->font != (char *) NULL)
2031  (void) FormatLocaleFile(file,"Font: %s\n\n",resource_info->font);
2032  if (resource_info->text_font != (char *) NULL)
2033  (void) FormatLocaleFile(file,"Text font: %s\n\n",resource_info->text_font);
2034  /*
2035  Write info about the undo cache to a file.
2036  */
2037  bytes=0;
2038  for (levels=0; undo_image != (Image *) NULL; levels++)
2039  {
2040  number_pixels=undo_image->list->columns*undo_image->list->rows;
2041  bytes+=number_pixels*sizeof(PixelInfo);
2042  undo_image=GetPreviousImageInList(undo_image);
2043  }
2044  (void) FormatLocaleFile(file,"Undo Edit Cache\n levels: %u\n",levels);
2045  (void) FormatLocaleFile(file," bytes: %.20gmb\n",(double)
2046  ((bytes+(1 << 19)) >> 20));
2047  (void) FormatLocaleFile(file," limit: %.20gmb\n\n",(double)
2048  resource_info->undo_cache);
2049  /*
2050  Write info about the image to a file.
2051  */
2052  (void) IdentifyImage(image,file,MagickTrue,exception);
2053  (void) fclose(file);
2054  text=FileToString(filename,~0UL,exception);
2055  (void) RelinquishUniqueFileResource(filename);
2056  if (text == (char *) NULL)
2057  {
2058  XNoticeWidget(display,windows,"MemoryAllocationFailed",
2059  "UnableToDisplayImageInfo");
2060  return;
2061  }
2062  textlist=StringToList(text);
2063  if (textlist != (char **) NULL)
2064  {
2065  char
2066  title[MagickPathExtent];
2067 
2068  /*
2069  Display information about the image in the Text View widget.
2070  */
2071  (void) XWithdrawWindow(display,windows->info.id,windows->info.screen);
2072  (void) FormatLocaleString(title,MagickPathExtent,"Image Info: %s",
2073  image->filename);
2074  XTextViewWidget(display,resource_info,windows,MagickTrue,title,
2075  (char const **) textlist);
2076  for (i=0; textlist[i] != (char *) NULL; i++)
2077  textlist[i]=DestroyString(textlist[i]);
2078  textlist=(char **) RelinquishMagickMemory(textlist);
2079  }
2080  text=DestroyString(text);
2081 }
2082 
2083 /*
2084 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2085 % %
2086 % %
2087 % %
2088 + X D i t h e r I m a g e %
2089 % %
2090 % %
2091 % %
2092 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2093 %
2094 % XDitherImage() dithers the reference image as required by the HP Color
2095 % Recovery algorithm. The color values are quantized to 3 bits of red and
2096 % green, and 2 bits of blue (3/3/2) and can be used as indices into a 8-bit X
2097 % standard colormap.
2098 %
2099 % The format of the XDitherImage method is:
2100 %
2101 % void XDitherImage(Image *image,XImage *ximage,ExceptionInfo *exception)
2102 %
2103 % A description of each parameter follows:
2104 %
2105 % o image: the image.
2106 %
2107 % o ximage: Specifies a pointer to a XImage structure; returned from
2108 % XCreateImage.
2109 %
2110 % o exception: return any errors or warnings in this structure.
2111 %
2112 */
2113 static void XDitherImage(Image *image,XImage *ximage,ExceptionInfo *exception)
2114 {
2115  static const short int
2116  dither_red[2][16]=
2117  {
2118  {-16, 4, -1, 11,-14, 6, -3, 9,-15, 5, -2, 10,-13, 7, -4, 8},
2119  { 15, -5, 0,-12, 13, -7, 2,-10, 14, -6, 1,-11, 12, -8, 3, -9}
2120  },
2121  dither_green[2][16]=
2122  {
2123  { 11,-15, 7, -3, 8,-14, 4, -2, 10,-16, 6, -4, 9,-13, 5, -1},
2124  {-12, 14, -8, 2, -9, 13, -5, 1,-11, 15, -7, 3,-10, 12, -6, 0}
2125  },
2126  dither_blue[2][16]=
2127  {
2128  { -3, 9,-13, 7, -1, 11,-15, 5, -4, 8,-14, 6, -2, 10,-16, 4},
2129  { 2,-10, 12, -8, 0,-12, 14, -6, 3, -9, 13, -7, 1,-11, 15, -5}
2130  };
2131 
2132  CacheView
2133  *image_view;
2134 
2135  int
2136  value,
2137  y;
2138 
2139  PixelInfo
2140  color;
2141 
2142  char
2143  *q;
2144 
2145  const Quantum
2146  *p;
2147 
2148  int
2149  i,
2150  j,
2151  x;
2152 
2153  unsigned int
2154  scanline_pad;
2155 
2156  size_t
2157  pixel;
2158 
2159  unsigned char
2160  *blue_map[2][16],
2161  *green_map[2][16],
2162  *red_map[2][16];
2163 
2164  /*
2165  Allocate and initialize dither maps.
2166  */
2167  for (i=0; i < 2; i++)
2168  for (j=0; j < 16; j++)
2169  {
2170  red_map[i][j]=(unsigned char *) AcquireCriticalMemory(256UL*
2171  sizeof(*red_map));
2172  green_map[i][j]=(unsigned char *) AcquireCriticalMemory(256UL*
2173  sizeof(*green_map));
2174  blue_map[i][j]=(unsigned char *) AcquireCriticalMemory(256UL*
2175  sizeof(*blue_map));
2176  }
2177  /*
2178  Initialize dither tables.
2179  */
2180  for (i=0; i < 2; i++)
2181  for (j=0; j < 16; j++)
2182  for (x=0; x < 256; x++)
2183  {
2184  value=x-16;
2185  if (x < 48)
2186  value=x/2+8;
2187  value+=dither_red[i][j];
2188  red_map[i][j][x]=(unsigned char)
2189  ((value < 0) ? 0 : (value > 255) ? 255 : value);
2190  value=x-16;
2191  if (x < 48)
2192  value=x/2+8;
2193  value+=dither_green[i][j];
2194  green_map[i][j][x]=(unsigned char)
2195  ((value < 0) ? 0 : (value > 255) ? 255 : value);
2196  value=x-32;
2197  if (x < 112)
2198  value=x/2+24;
2199  value+=((size_t) dither_blue[i][j] << 1);
2200  blue_map[i][j][x]=(unsigned char)
2201  ((value < 0) ? 0 : (value > 255) ? 255 : value);
2202  }
2203  /*
2204  Dither image.
2205  */
2206  scanline_pad=(unsigned int) (ximage->bytes_per_line-
2207  ((size_t) (ximage->width*ximage->bits_per_pixel) >> 3));
2208  i=0;
2209  j=0;
2210  q=ximage->data;
2211  image_view=AcquireVirtualCacheView(image,exception);
2212  for (y=0; y < (int) image->rows; y++)
2213  {
2214  p=GetCacheViewVirtualPixels(image_view,0,(ssize_t) y,image->columns,1,
2215  exception);
2216  if (p == (const Quantum *) NULL)
2217  break;
2218  for (x=0; x < (int) image->columns; x++)
2219  {
2220  color.red=(double) ClampToQuantum((double) (red_map[i][j][
2221  (int) ScaleQuantumToChar(GetPixelRed(image,p))] << 8));
2222  color.green=(double) ClampToQuantum((double) (green_map[i][j][
2223  (int) ScaleQuantumToChar(GetPixelGreen(image,p))] << 8));
2224  color.blue=(double) ClampToQuantum((double) (blue_map[i][j][
2225  (int) ScaleQuantumToChar(GetPixelBlue(image,p))] << 8));
2226  pixel=(size_t) (((size_t) color.red & 0xe0) |
2227  (((size_t) color.green & 0xe0) >> 3) |
2228  (((size_t) color.blue & 0xc0) >> 6));
2229  *q++=(char) pixel;
2230  p+=GetPixelChannels(image);
2231  j++;
2232  if (j == 16)
2233  j=0;
2234  }
2235  q+=scanline_pad;
2236  i++;
2237  if (i == 2)
2238  i=0;
2239  }
2240  image_view=DestroyCacheView(image_view);
2241  /*
2242  Free allocated memory.
2243  */
2244  for (i=0; i < 2; i++)
2245  for (j=0; j < 16; j++)
2246  {
2247  green_map[i][j]=(unsigned char *) RelinquishMagickMemory(green_map[i][j]);
2248  blue_map[i][j]=(unsigned char *) RelinquishMagickMemory(blue_map[i][j]);
2249  red_map[i][j]=(unsigned char *) RelinquishMagickMemory(red_map[i][j]);
2250  }
2251 }
2252 
2253 /*
2254 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2255 % %
2256 % %
2257 % %
2258 % X D r a w I m a g e %
2259 % %
2260 % %
2261 % %
2262 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2263 %
2264 % XDrawImage() draws a line on the image.
2265 %
2266 % The format of the XDrawImage method is:
2267 %
2268 % MagickBooleanType XDrawImage(Display *display,const XPixelInfo *pixel,
2269 % XDrawInfo *draw_info,Image *image,ExceptionInfo *exception)
2270 %
2271 % A description of each parameter follows:
2272 %
2273 % o display: Specifies a connection to an X server; returned from
2274 % XOpenDisplay.
2275 %
2276 % o pixel: Specifies a pointer to a XPixelInfo structure.
2277 %
2278 % o draw_info: Specifies a pointer to a XDrawInfo structure.
2279 %
2280 % o image: the image.
2281 %
2282 % o exception: return any errors or warnings in this structure.
2283 %
2284 */
2285 MagickPrivate MagickBooleanType XDrawImage(Display *display,
2286  const XPixelInfo *pixel,XDrawInfo *draw_info,Image *image,
2287  ExceptionInfo *exception)
2288 {
2289  CacheView
2290  *draw_view;
2291 
2292  GC
2293  draw_context;
2294 
2295  Image
2296  *draw_image;
2297 
2298  int
2299  x,
2300  y;
2301 
2302  PixelTrait
2303  alpha_trait;
2304 
2305  Pixmap
2306  draw_pixmap;
2307 
2308  unsigned int
2309  depth,
2310  height,
2311  width;
2312 
2313  Window
2314  root_window;
2315 
2316  XGCValues
2317  context_values;
2318 
2319  XImage
2320  *draw_ximage;
2321 
2322  /*
2323  Initialize drawd image.
2324  */
2325  assert(display != (Display *) NULL);
2326  assert(pixel != (XPixelInfo *) NULL);
2327  assert(draw_info != (XDrawInfo *) NULL);
2328  assert(image != (Image *) NULL);
2329  if (image->debug != MagickFalse)
2330  (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
2331  /*
2332  Initialize drawd pixmap.
2333  */
2334  root_window=XRootWindow(display,XDefaultScreen(display));
2335  depth=(unsigned int) XDefaultDepth(display,XDefaultScreen(display));
2336  draw_pixmap=XCreatePixmap(display,root_window,draw_info->width,
2337  draw_info->height,depth);
2338  if (draw_pixmap == (Pixmap) NULL)
2339  return(MagickFalse);
2340  /*
2341  Initialize graphics info.
2342  */
2343  context_values.background=(size_t) (~0);
2344  context_values.foreground=0;
2345  context_values.line_width=(int) draw_info->line_width;
2346  draw_context=XCreateGC(display,root_window,(size_t)
2347  (GCBackground | GCForeground | GCLineWidth),&context_values);
2348  if (draw_context == (GC) NULL)
2349  return(MagickFalse);
2350  /*
2351  Clear pixmap.
2352  */
2353  (void) XFillRectangle(display,draw_pixmap,draw_context,0,0,draw_info->width,
2354  draw_info->height);
2355  /*
2356  Draw line to pixmap.
2357  */
2358  (void) XSetBackground(display,draw_context,0);
2359  (void) XSetForeground(display,draw_context,(size_t) (~0));
2360  if (draw_info->stipple != (Pixmap) NULL)
2361  {
2362  (void) XSetFillStyle(display,draw_context,FillOpaqueStippled);
2363  (void) XSetStipple(display,draw_context,draw_info->stipple);
2364  }
2365  switch (draw_info->element)
2366  {
2367  case PointElement:
2368  default:
2369  {
2370  (void) XDrawLines(display,draw_pixmap,draw_context,
2371  draw_info->coordinate_info,(int) draw_info->number_coordinates,
2372  CoordModeOrigin);
2373  break;
2374  }
2375  case LineElement:
2376  {
2377  (void) XDrawLine(display,draw_pixmap,draw_context,draw_info->line_info.x1,
2378  draw_info->line_info.y1,draw_info->line_info.x2,
2379  draw_info->line_info.y2);
2380  break;
2381  }
2382  case RectangleElement:
2383  {
2384  (void) XDrawRectangle(display,draw_pixmap,draw_context,
2385  (int) draw_info->rectangle_info.x,(int) draw_info->rectangle_info.y,
2386  (unsigned int) draw_info->rectangle_info.width,
2387  (unsigned int) draw_info->rectangle_info.height);
2388  break;
2389  }
2390  case FillRectangleElement:
2391  {
2392  (void) XFillRectangle(display,draw_pixmap,draw_context,
2393  (int) draw_info->rectangle_info.x,(int) draw_info->rectangle_info.y,
2394  (unsigned int) draw_info->rectangle_info.width,
2395  (unsigned int) draw_info->rectangle_info.height);
2396  break;
2397  }
2398  case CircleElement:
2399  case EllipseElement:
2400  {
2401  (void) XDrawArc(display,draw_pixmap,draw_context,
2402  (int) draw_info->rectangle_info.x,(int) draw_info->rectangle_info.y,
2403  (unsigned int) draw_info->rectangle_info.width,
2404  (unsigned int) draw_info->rectangle_info.height,0,360*64);
2405  break;
2406  }
2407  case FillCircleElement:
2408  case FillEllipseElement:
2409  {
2410  (void) XFillArc(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,0,360*64);
2414  break;
2415  }
2416  case PolygonElement:
2417  {
2418  XPoint
2419  *coordinate_info;
2420 
2421  coordinate_info=draw_info->coordinate_info;
2422  (void) XDrawLines(display,draw_pixmap,draw_context,coordinate_info,
2423  (int) draw_info->number_coordinates,CoordModeOrigin);
2424  (void) XDrawLine(display,draw_pixmap,draw_context,
2425  coordinate_info[draw_info->number_coordinates-1].x,
2426  coordinate_info[draw_info->number_coordinates-1].y,
2427  coordinate_info[0].x,coordinate_info[0].y);
2428  break;
2429  }
2430  case FillPolygonElement:
2431  {
2432  (void) XFillPolygon(display,draw_pixmap,draw_context,
2433  draw_info->coordinate_info,(int) draw_info->number_coordinates,Complex,
2434  CoordModeOrigin);
2435  break;
2436  }
2437  }
2438  (void) XFreeGC(display,draw_context);
2439  /*
2440  Initialize X image.
2441  */
2442  draw_ximage=XGetImage(display,draw_pixmap,0,0,draw_info->width,
2443  draw_info->height,AllPlanes,ZPixmap);
2444  if (draw_ximage == (XImage *) NULL)
2445  return(MagickFalse);
2446  (void) XFreePixmap(display,draw_pixmap);
2447  /*
2448  Initialize draw image.
2449  */
2450  draw_image=AcquireImage((ImageInfo *) NULL,exception);
2451  if (draw_image == (Image *) NULL)
2452  return(MagickFalse);
2453  draw_image->columns=draw_info->width;
2454  draw_image->rows=draw_info->height;
2455  /*
2456  Transfer drawn X image to image.
2457  */
2458  width=(unsigned int) image->columns;
2459  height=(unsigned int) image->rows;
2460  x=0;
2461  y=0;
2462  (void) XParseGeometry(draw_info->geometry,&x,&y,&width,&height);
2463  (void) GetOneVirtualPixelInfo(image,UndefinedVirtualPixelMethod,(ssize_t) x,
2464  (ssize_t) y,&draw_image->background_color,exception);
2465  if (SetImageStorageClass(draw_image,DirectClass,exception) == MagickFalse)
2466  return(MagickFalse);
2467  draw_image->alpha_trait=BlendPixelTrait;
2468  draw_view=AcquireAuthenticCacheView(draw_image,exception);
2469  for (y=0; y < (int) draw_image->rows; y++)
2470  {
2471  int
2472  x;
2473 
2474  Quantum
2475  *magick_restrict q;
2476 
2477  q=QueueCacheViewAuthenticPixels(draw_view,0,(ssize_t) y,draw_image->columns,
2478  1,exception);
2479  if (q == (Quantum *) NULL)
2480  break;
2481  for (x=0; x < (int) draw_image->columns; x++)
2482  {
2483  if (XGetPixel(draw_ximage,x,y) == 0)
2484  {
2485  /*
2486  Set this pixel to the background color.
2487  */
2488  SetPixelViaPixelInfo(draw_image,&draw_image->background_color,q);
2489  SetPixelAlpha(draw_image,(Quantum) (draw_info->stencil ==
2490  OpaqueStencil ? TransparentAlpha : OpaqueAlpha),q);
2491  }
2492  else
2493  {
2494  /*
2495  Set this pixel to the pen color.
2496  */
2497  SetPixelRed(draw_image,ScaleShortToQuantum(
2498  pixel->pen_color.red),q);
2499  SetPixelGreen(draw_image,ScaleShortToQuantum(
2500  pixel->pen_color.green),q);
2501  SetPixelBlue(draw_image,ScaleShortToQuantum(
2502  pixel->pen_color.blue),q);
2503  SetPixelAlpha(draw_image,(Quantum) (draw_info->stencil ==
2504  OpaqueStencil ? OpaqueAlpha : TransparentAlpha),q);
2505  }
2506  q+=GetPixelChannels(draw_image);
2507  }
2508  if (SyncCacheViewAuthenticPixels(draw_view,exception) == MagickFalse)
2509  break;
2510  }
2511  draw_view=DestroyCacheView(draw_view);
2512  XDestroyImage(draw_ximage);
2513  /*
2514  Determine draw geometry.
2515  */
2516  (void) XParseGeometry(draw_info->geometry,&x,&y,&width,&height);
2517  if ((width != (unsigned int) draw_image->columns) ||
2518  (height != (unsigned int) draw_image->rows))
2519  {
2520  char
2521  image_geometry[MagickPathExtent];
2522 
2523  /*
2524  Scale image.
2525  */
2526  (void) FormatLocaleString(image_geometry,MagickPathExtent,"%ux%u",
2527  width,height);
2528  (void) TransformImage(&draw_image,(char *) NULL,image_geometry,
2529  exception);
2530  }
2531  if (draw_info->degrees != 0.0)
2532  {
2533  Image
2534  *rotate_image;
2535 
2536  int
2537  rotations;
2538 
2539  double
2540  normalized_degrees;
2541 
2542  /*
2543  Rotate image.
2544  */
2545  rotate_image=RotateImage(draw_image,draw_info->degrees,exception);
2546  if (rotate_image == (Image *) NULL)
2547  return(MagickFalse);
2548  draw_image=DestroyImage(draw_image);
2549  draw_image=rotate_image;
2550  /*
2551  Annotation is relative to the degree of rotation.
2552  */
2553  normalized_degrees=draw_info->degrees;
2554  while (normalized_degrees < -45.0)
2555  normalized_degrees+=360.0;
2556  for (rotations=0; normalized_degrees > 45.0; rotations++)
2557  normalized_degrees-=90.0;
2558  switch (rotations % 4)
2559  {
2560  default:
2561  case 0:
2562  break;
2563  case 1:
2564  {
2565  /*
2566  Rotate 90 degrees.
2567  */
2568  x=x-(int) draw_image->columns/2;
2569  y=y+(int) draw_image->columns/2;
2570  break;
2571  }
2572  case 2:
2573  {
2574  /*
2575  Rotate 180 degrees.
2576  */
2577  x=x-(int) draw_image->columns;
2578  break;
2579  }
2580  case 3:
2581  {
2582  /*
2583  Rotate 270 degrees.
2584  */
2585  x=x-(int) draw_image->columns/2;
2586  y=y-(int) (draw_image->rows-(draw_image->columns/2));
2587  break;
2588  }
2589  }
2590  }
2591  /*
2592  Composite text onto the image.
2593  */
2594  draw_view=AcquireAuthenticCacheView(draw_image,exception);
2595  for (y=0; y < (int) draw_image->rows; y++)
2596  {
2597  int
2598  x;
2599 
2600  Quantum
2601  *magick_restrict q;
2602 
2603  q=GetCacheViewAuthenticPixels(draw_view,0,(ssize_t) y,draw_image->columns,1,
2604  exception);
2605  if (q == (Quantum *) NULL)
2606  break;
2607  for (x=0; x < (int) draw_image->columns; x++)
2608  {
2609  if (GetPixelAlpha(image,q) != TransparentAlpha)
2610  SetPixelAlpha(draw_image,OpaqueAlpha,q);
2611  q+=GetPixelChannels(draw_image);
2612  }
2613  if (SyncCacheViewAuthenticPixels(draw_view,exception) == MagickFalse)
2614  break;
2615  }
2616  draw_view=DestroyCacheView(draw_view);
2617  (void) XParseGeometry(draw_info->geometry,&x,&y,&width,&height);
2618  if (draw_info->stencil == TransparentStencil)
2619  (void) CompositeImage(image,draw_image,CopyAlphaCompositeOp,MagickTrue,
2620  (ssize_t) x,(ssize_t) y,exception);
2621  else
2622  {
2623  alpha_trait=image->alpha_trait;
2624  (void) CompositeImage(image,draw_image,OverCompositeOp,MagickTrue,
2625  (ssize_t) x,(ssize_t) y,exception);
2626  image->alpha_trait=alpha_trait;
2627  }
2628  draw_image=DestroyImage(draw_image);
2629  return(MagickTrue);
2630 }
2631 
2632 /*
2633 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2634 % %
2635 % %
2636 % %
2637 % X E r r o r %
2638 % %
2639 % %
2640 % %
2641 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2642 %
2643 % XError() ignores BadWindow errors for XQueryTree and XGetWindowAttributes,
2644 % and ignores BadDrawable errors for XGetGeometry, and ignores BadValue errors
2645 % for XQueryColor. It returns MagickFalse in those cases. Otherwise it
2646 % returns True.
2647 %
2648 % The format of the XError function is:
2649 %
2650 % int XError(display,error)
2651 %
2652 % A description of each parameter follows:
2653 %
2654 % o display: Specifies a pointer to the Display structure; returned from
2655 % XOpenDisplay.
2656 %
2657 % o error: Specifies the error event.
2658 %
2659 */
2660 
2661 #if defined(__cplusplus) || defined(c_plusplus)
2662 extern "C" {
2663 #endif
2664 
2665 MagickExport int XError(Display *display,XErrorEvent *error)
2666 {
2667  (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
2668  assert(display != (Display *) NULL);
2669  assert(error != (XErrorEvent *) NULL);
2670  xerror_alert=MagickTrue;
2671  switch (error->request_code)
2672  {
2673  case X_GetGeometry:
2674  {
2675  if ((int) error->error_code == BadDrawable)
2676  return(MagickFalse);
2677  break;
2678  }
2679  case X_GetWindowAttributes:
2680  case X_QueryTree:
2681  {
2682  if ((int) error->error_code == BadWindow)
2683  return(MagickFalse);
2684  break;
2685  }
2686  case X_QueryColors:
2687  {
2688  if ((int) error->error_code == BadValue)
2689  return(MagickFalse);
2690  break;
2691  }
2692  }
2693  return(MagickTrue);
2694 }
2695 
2696 #if defined(__cplusplus) || defined(c_plusplus)
2697 }
2698 #endif
2699 
2700 /*
2701 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2702 % %
2703 % %
2704 % %
2705 % X F r e e R e s o u r c e s %
2706 % %
2707 % %
2708 % %
2709 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2710 %
2711 % XFreeResources() frees X11 resources.
2712 %
2713 % The format of the XFreeResources method is:
2714 %
2715 % void XFreeResources(Display *display,XVisualInfo *visual_info,
2716 % XStandardColormap *map_info,XPixelInfo *pixel,XFontStruct *font_info,
2717 % XResourceInfo *resource_info,XWindowInfo *window_info)
2718 % resource_info,window_info)
2719 %
2720 % A description of each parameter follows:
2721 %
2722 % o display: Specifies a connection to an X server; returned from
2723 % XOpenDisplay.
2724 %
2725 % o visual_info: Specifies a pointer to a X11 XVisualInfo structure;
2726 % returned from XGetVisualInfo.
2727 %
2728 % o map_info: If map_type is specified, this structure is initialized
2729 % with info from the Standard Colormap.
2730 %
2731 % o pixel: Specifies a pointer to a XPixelInfo structure.
2732 %
2733 % o font_info: Specifies a pointer to a XFontStruct structure.
2734 %
2735 % o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
2736 %
2737 % o window_info: Specifies a pointer to a X11 XWindowInfo structure.
2738 %
2739 */
2740 MagickPrivate void XFreeResources(Display *display,XVisualInfo *visual_info,
2741  XStandardColormap *map_info,XPixelInfo *pixel,XFontStruct *font_info,
2742  XResourceInfo *resource_info,XWindowInfo *window_info)
2743 {
2744  (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
2745  assert(display != (Display *) NULL);
2746  assert(resource_info != (XResourceInfo *) NULL);
2747  if (window_info != (XWindowInfo *) NULL)
2748  {
2749  /*
2750  Free X image.
2751  */
2752  if (window_info->ximage != (XImage *) NULL)
2753  XDestroyImage(window_info->ximage);
2754  if (window_info->id != (Window) NULL)
2755  {
2756  /*
2757  Free destroy window and free cursors.
2758  */
2759  if (window_info->id != XRootWindow(display,visual_info->screen))
2760  (void) XDestroyWindow(display,window_info->id);
2761  if (window_info->annotate_context != (GC) NULL)
2762  (void) XFreeGC(display,window_info->annotate_context);
2763  if (window_info->highlight_context != (GC) NULL)
2764  (void) XFreeGC(display,window_info->highlight_context);
2765  if (window_info->widget_context != (GC) NULL)
2766  (void) XFreeGC(display,window_info->widget_context);
2767  if (window_info->cursor != (Cursor) NULL)
2768  (void) XFreeCursor(display,window_info->cursor);
2769  window_info->cursor=(Cursor) NULL;
2770  if (window_info->busy_cursor != (Cursor) NULL)
2771  (void) XFreeCursor(display,window_info->busy_cursor);
2772  window_info->busy_cursor=(Cursor) NULL;
2773  }
2774  }
2775  /*
2776  Free font.
2777  */
2778  if (font_info != (XFontStruct *) NULL)
2779  {
2780  (void) XFreeFont(display,font_info);
2781  font_info=(XFontStruct *) NULL;
2782  }
2783  if (map_info != (XStandardColormap *) NULL)
2784  {
2785  /*
2786  Free X Standard Colormap.
2787  */
2788  if (resource_info->map_type == (char *) NULL)
2789  (void) XFreeStandardColormap(display,visual_info,map_info,pixel);
2790  (void) XFree((void *) map_info);
2791  }
2792  /*
2793  Free X visual info.
2794  */
2795  if (visual_info != (XVisualInfo *) NULL)
2796  (void) XFree((void *) visual_info);
2797  if (resource_info->close_server != MagickFalse)
2798  (void) XCloseDisplay(display);
2799 }
2800 
2801 /*
2802 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2803 % %
2804 % %
2805 % %
2806 % X F r e e S t a n d a r d C o l o r m a p %
2807 % %
2808 % %
2809 % %
2810 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2811 %
2812 % XFreeStandardColormap() frees an X11 colormap.
2813 %
2814 % The format of the XFreeStandardColormap method is:
2815 %
2816 % void XFreeStandardColormap(Display *display,
2817 % const XVisualInfo *visual_info,XStandardColormap *map_info,
2818 % XPixelInfo *pixel)
2819 %
2820 % A description of each parameter follows:
2821 %
2822 % o display: Specifies a connection to an X server; returned from
2823 % XOpenDisplay.
2824 %
2825 % o visual_info: Specifies a pointer to a X11 XVisualInfo structure;
2826 % returned from XGetVisualInfo.
2827 %
2828 % o map_info: If map_type is specified, this structure is initialized
2829 % with info from the Standard Colormap.
2830 %
2831 % o pixel: Specifies a pointer to a XPixelInfo structure.
2832 %
2833 */
2834 MagickPrivate void XFreeStandardColormap(Display *display,
2835  const XVisualInfo *visual_info,XStandardColormap *map_info,XPixelInfo *pixel)
2836 {
2837  /*
2838  Free colormap.
2839  */
2840  (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
2841  assert(display != (Display *) NULL);
2842  assert(visual_info != (XVisualInfo *) NULL);
2843  assert(map_info != (XStandardColormap *) NULL);
2844  (void) XFlush(display);
2845  if (map_info->colormap != (Colormap) NULL)
2846  {
2847  if (map_info->colormap != XDefaultColormap(display,visual_info->screen))
2848  (void) XFreeColormap(display,map_info->colormap);
2849  else
2850  if (pixel != (XPixelInfo *) NULL)
2851  if ((visual_info->klass != TrueColor) &&
2852  (visual_info->klass != DirectColor))
2853  (void) XFreeColors(display,map_info->colormap,pixel->pixels,
2854  (int) pixel->colors,0);
2855  }
2856  map_info->colormap=(Colormap) NULL;
2857  if (pixel != (XPixelInfo *) NULL)
2858  {
2859  if (pixel->pixels != (unsigned long *) NULL)
2860  pixel->pixels=(unsigned long *) RelinquishMagickMemory(pixel->pixels);
2861  pixel->pixels=(unsigned long *) NULL;
2862  }
2863 }
2864 
2865 /*
2866 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2867 % %
2868 % %
2869 % %
2870 % X G e t A n n o t a t e I n f o %
2871 % %
2872 % %
2873 % %
2874 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2875 %
2876 % XGetAnnotateInfo() initializes the AnnotateInfo structure.
2877 %
2878 % The format of the XGetAnnotateInfo method is:
2879 %
2880 % void XGetAnnotateInfo(XAnnotateInfo *annotate_info)
2881 %
2882 % A description of each parameter follows:
2883 %
2884 % o annotate_info: Specifies a pointer to a XAnnotateInfo structure.
2885 %
2886 */
2887 MagickPrivate void XGetAnnotateInfo(XAnnotateInfo *annotate_info)
2888 {
2889  /*
2890  Initialize annotate structure.
2891  */
2892  (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
2893  assert(annotate_info != (XAnnotateInfo *) NULL);
2894  annotate_info->x=0;
2895  annotate_info->y=0;
2896  annotate_info->width=0;
2897  annotate_info->height=0;
2898  annotate_info->stencil=ForegroundStencil;
2899  annotate_info->degrees=0.0;
2900  annotate_info->font_info=(XFontStruct *) NULL;
2901  annotate_info->text=(char *) NULL;
2902  *annotate_info->geometry='\0';
2903  annotate_info->previous=(XAnnotateInfo *) NULL;
2904  annotate_info->next=(XAnnotateInfo *) NULL;
2905  (void) XSupportsLocale();
2906  (void) XSetLocaleModifiers("");
2907 }
2908 
2909 /*
2910 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2911 % %
2912 % %
2913 % %
2914 % X G e t M a p I n f o %
2915 % %
2916 % %
2917 % %
2918 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2919 %
2920 % XGetMapInfo() initializes the XStandardColormap structure.
2921 %
2922 % The format of the XStandardColormap method is:
2923 %
2924 % void XGetMapInfo(const XVisualInfo *visual_info,const Colormap colormap,
2925 % XStandardColormap *map_info)
2926 %
2927 % A description of each parameter follows:
2928 %
2929 % o colormap: Specifies the ID of the X server colormap.
2930 %
2931 % o visual_info: Specifies a pointer to a X11 XVisualInfo structure;
2932 % returned from XGetVisualInfo.
2933 %
2934 % o map_info: Specifies a pointer to a X11 XStandardColormap structure.
2935 %
2936 */
2937 MagickPrivate void XGetMapInfo(const XVisualInfo *visual_info,
2938  const Colormap colormap,XStandardColormap *map_info)
2939 {
2940  /*
2941  Initialize map info.
2942  */
2943  (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
2944  assert(visual_info != (XVisualInfo *) NULL);
2945  assert(map_info != (XStandardColormap *) NULL);
2946  map_info->colormap=colormap;
2947  map_info->red_max=visual_info->red_mask;
2948  map_info->red_mult=(size_t) (map_info->red_max != 0 ? 1 : 0);
2949  if (map_info->red_max != 0)
2950  while ((map_info->red_max & 0x01) == 0)
2951  {
2952  map_info->red_max>>=1;
2953  map_info->red_mult<<=1;
2954  }
2955  map_info->green_max=visual_info->green_mask;
2956  map_info->green_mult=(size_t) (map_info->green_max != 0 ? 1 : 0);
2957  if (map_info->green_max != 0)
2958  while ((map_info->green_max & 0x01) == 0)
2959  {
2960  map_info->green_max>>=1;
2961  map_info->green_mult<<=1;
2962  }
2963  map_info->blue_max=visual_info->blue_mask;
2964  map_info->blue_mult=(size_t) (map_info->blue_max != 0 ? 1 : 0);
2965  if (map_info->blue_max != 0)
2966  while ((map_info->blue_max & 0x01) == 0)
2967  {
2968  map_info->blue_max>>=1;
2969  map_info->blue_mult<<=1;
2970  }
2971  map_info->base_pixel=0;
2972 }
2973 
2974 /*
2975 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2976 % %
2977 % %
2978 % %
2979 % X G e t P i x e l I n f o %
2980 % %
2981 % %
2982 % %
2983 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2984 %
2985 % XGetPixelInfo() initializes the PixelInfo structure.
2986 %
2987 % The format of the XGetPixelInfo method is:
2988 %
2989 % void XGetPixelInfo(Display *display,const XVisualInfo *visual_info,
2990 % const XStandardColormap *map_info,const XResourceInfo *resource_info,
2991 % Image *image,XPixelInfo *pixel)
2992 % pixel)
2993 %
2994 % A description of each parameter follows:
2995 %
2996 % o display: Specifies a connection to an X server; returned from
2997 % XOpenDisplay.
2998 %
2999 % o visual_info: Specifies a pointer to a X11 XVisualInfo structure;
3000 % returned from XGetVisualInfo.
3001 %
3002 % o map_info: If map_type is specified, this structure is initialized
3003 % with info from the Standard Colormap.
3004 %
3005 % o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
3006 %
3007 % o image: the image.
3008 %
3009 % o pixel: Specifies a pointer to a XPixelInfo structure.
3010 %
3011 */
3012 MagickPrivate void XGetPixelInfo(Display *display,
3013  const XVisualInfo *visual_info,const XStandardColormap *map_info,
3014  const XResourceInfo *resource_info,Image *image,XPixelInfo *pixel)
3015 {
3016  static const char
3017  *PenColors[MaxNumberPens]=
3018  {
3019  "#000000000000", /* black */
3020  "#00000000ffff", /* blue */
3021  "#0000ffffffff", /* cyan */
3022  "#0000ffff0000", /* green */
3023  "#bdbdbdbdbdbd", /* gray */
3024  "#ffff00000000", /* red */
3025  "#ffff0000ffff", /* magenta */
3026  "#ffffffff0000", /* yellow */
3027  "#ffffffffffff", /* white */
3028  "#bdbdbdbdbdbd", /* gray */
3029  "#bdbdbdbdbdbd" /* gray */
3030  };
3031 
3032  Colormap
3033  colormap;
3034 
3035  ssize_t
3036  i;
3037 
3038  Status
3039  status;
3040 
3041  unsigned int
3042  packets;
3043 
3044  /*
3045  Initialize pixel info.
3046  */
3047  (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
3048  assert(display != (Display *) NULL);
3049  assert(visual_info != (XVisualInfo *) NULL);
3050  assert(map_info != (XStandardColormap *) NULL);
3051  assert(resource_info != (XResourceInfo *) NULL);
3052  assert(pixel != (XPixelInfo *) NULL);
3053  pixel->colors=0;
3054  if (image != (Image *) NULL)
3055  if (image->storage_class == PseudoClass)
3056  pixel->colors=(ssize_t) image->colors;
3057  packets=(unsigned int)
3058  MagickMax((int) pixel->colors,visual_info->colormap_size)+MaxNumberPens;
3059  if (pixel->pixels != (unsigned long *) NULL)
3060  pixel->pixels=(unsigned long *) RelinquishMagickMemory(pixel->pixels);
3061  pixel->pixels=(unsigned long *) AcquireQuantumMemory(packets,
3062  sizeof(*pixel->pixels));
3063  if (pixel->pixels == (unsigned long *) NULL)
3064  ThrowXWindowFatalException(ResourceLimitFatalError,"UnableToGetPixelInfo",
3065  image->filename);
3066  /*
3067  Set foreground color.
3068  */
3069  colormap=map_info->colormap;
3070  (void) XParseColor(display,colormap,(char *) ForegroundColor,
3071  &pixel->foreground_color);
3072  status=XParseColor(display,colormap,resource_info->foreground_color,
3073  &pixel->foreground_color);
3074  if (status == False)
3075  ThrowXWindowException(XServerError,"ColorIsNotKnownToServer",
3076  resource_info->foreground_color);
3077  pixel->foreground_color.pixel=
3078  XStandardPixel(map_info,&pixel->foreground_color);
3079  pixel->foreground_color.flags=(char) (DoRed | DoGreen | DoBlue);
3080  /*
3081  Set background color.
3082  */
3083  (void) XParseColor(display,colormap,"#d6d6d6d6d6d6",&pixel->background_color);
3084  status=XParseColor(display,colormap,resource_info->background_color,
3085  &pixel->background_color);
3086  if (status == False)
3087  ThrowXWindowException(XServerError,"ColorIsNotKnownToServer",
3088  resource_info->background_color);
3089  pixel->background_color.pixel=
3090  XStandardPixel(map_info,&pixel->background_color);
3091  pixel->background_color.flags=(char) (DoRed | DoGreen | DoBlue);
3092  /*
3093  Set border color.
3094  */
3095  (void) XParseColor(display,colormap,(char *) BorderColor,
3096  &pixel->border_color);
3097  status=XParseColor(display,colormap,resource_info->border_color,
3098  &pixel->border_color);
3099  if (status == False)
3100  ThrowXWindowException(XServerError,"ColorIsNotKnownToServer",
3101  resource_info->border_color);
3102  pixel->border_color.pixel=XStandardPixel(map_info,&pixel->border_color);
3103  pixel->border_color.flags=(char) (DoRed | DoGreen | DoBlue);
3104  /*
3105  Set matte color.
3106  */
3107  pixel->matte_color=pixel->background_color;
3108  if (resource_info->matte_color != (char *) NULL)
3109  {
3110  /*
3111  Matte color is specified as a X resource or command line argument.
3112  */
3113  status=XParseColor(display,colormap,resource_info->matte_color,
3114  &pixel->matte_color);
3115  if (status == False)
3116  ThrowXWindowException(XServerError,"ColorIsNotKnownToServer",
3117  resource_info->matte_color);
3118  pixel->matte_color.pixel=XStandardPixel(map_info,&pixel->matte_color);
3119  pixel->matte_color.flags=(char) (DoRed | DoGreen | DoBlue);
3120  }
3121  /*
3122  Set highlight color.
3123  */
3124  pixel->highlight_color.red=(unsigned short) (((double)
3125  pixel->matte_color.red*ScaleQuantumToShort(HighlightModulate))/65535L+
3126  (ScaleQuantumToShort((Quantum) (QuantumRange-HighlightModulate))));
3127  pixel->highlight_color.green=(unsigned short) (((double)
3128  pixel->matte_color.green*ScaleQuantumToShort(HighlightModulate))/65535L+
3129  (ScaleQuantumToShort((Quantum) (QuantumRange-HighlightModulate))));
3130  pixel->highlight_color.blue=(unsigned short) (((double)
3131  pixel->matte_color.blue*ScaleQuantumToShort(HighlightModulate))/65535L+
3132  (ScaleQuantumToShort((Quantum) (QuantumRange-HighlightModulate))));
3133  pixel->highlight_color.pixel=XStandardPixel(map_info,&pixel->highlight_color);
3134  pixel->highlight_color.flags=(char) (DoRed | DoGreen | DoBlue);
3135  /*
3136  Set shadow color.
3137  */
3138  pixel->shadow_color.red=(unsigned short) (((double)
3139  pixel->matte_color.red*ScaleQuantumToShort(ShadowModulate))/65535L);
3140  pixel->shadow_color.green=(unsigned short) (((double)
3141  pixel->matte_color.green*ScaleQuantumToShort(ShadowModulate))/65535L);
3142  pixel->shadow_color.blue=(unsigned short) (((double)
3143  pixel->matte_color.blue*ScaleQuantumToShort(ShadowModulate))/65535L);
3144  pixel->shadow_color.pixel=XStandardPixel(map_info,&pixel->shadow_color);
3145  pixel->shadow_color.flags=(char) (DoRed | DoGreen | DoBlue);
3146  /*
3147  Set depth color.
3148  */
3149  pixel->depth_color.red=(unsigned short) (((double)
3150  pixel->matte_color.red*ScaleQuantumToShort(DepthModulate))/65535L);
3151  pixel->depth_color.green=(unsigned short) (((double)
3152  pixel->matte_color.green*ScaleQuantumToShort(DepthModulate))/65535L);
3153  pixel->depth_color.blue=(unsigned short) (((double)
3154  pixel->matte_color.blue*ScaleQuantumToShort(DepthModulate))/65535L);
3155  pixel->depth_color.pixel=XStandardPixel(map_info,&pixel->depth_color);
3156  pixel->depth_color.flags=(char) (DoRed | DoGreen | DoBlue);
3157  /*
3158  Set trough color.
3159  */
3160  pixel->trough_color.red=(unsigned short) (((double)
3161  pixel->matte_color.red*ScaleQuantumToShort(TroughModulate))/65535L);
3162  pixel->trough_color.green=(unsigned short) (((double)
3163  pixel->matte_color.green*ScaleQuantumToShort(TroughModulate))/65535L);
3164  pixel->trough_color.blue=(unsigned short) (((double)
3165  pixel->matte_color.blue*ScaleQuantumToShort(TroughModulate))/65535L);
3166  pixel->trough_color.pixel=XStandardPixel(map_info,&pixel->trough_color);
3167  pixel->trough_color.flags=(char) (DoRed | DoGreen | DoBlue);
3168  /*
3169  Set pen color.
3170  */
3171  for (i=0; i < MaxNumberPens; i++)
3172  {
3173  (void) XParseColor(display,colormap,(char *) PenColors[i],
3174  &pixel->pen_colors[i]);
3175  status=XParseColor(display,colormap,resource_info->pen_colors[i],
3176  &pixel->pen_colors[i]);
3177  if (status == False)
3178  ThrowXWindowException(XServerError,"ColorIsNotKnownToServer",
3179  resource_info->pen_colors[i]);
3180  pixel->pen_colors[i].pixel=XStandardPixel(map_info,&pixel->pen_colors[i]);
3181  pixel->pen_colors[i].flags=(char) (DoRed | DoGreen | DoBlue);
3182  }
3183  pixel->box_color=pixel->background_color;
3184  pixel->pen_color=pixel->foreground_color;
3185  pixel->box_index=0;
3186  pixel->pen_index=1;
3187  if (image != (Image *) NULL)
3188  {
3189  if ((resource_info->gamma_correct != MagickFalse) &&
3190  (image->gamma != 0.0))
3191  {
3192  GeometryInfo
3193  geometry_info;
3194 
3196  flags;
3197 
3198  /*
3199  Initialize map relative to display and image gamma.
3200  */
3201  flags=ParseGeometry(resource_info->display_gamma,&geometry_info);
3202  if ((flags & RhoValue) != 0)
3203  red_gamma=geometry_info.rho;
3204  green_gamma=red_gamma;
3205  if ((flags & SigmaValue) != 0)
3206  green_gamma=geometry_info.sigma;
3207  blue_gamma=red_gamma;
3208  if ((flags & XiValue) != 0)
3209  blue_gamma=geometry_info.xi;
3210  red_gamma*=image->gamma;
3211  green_gamma*=image->gamma;
3212  blue_gamma*=image->gamma;
3213  }
3214  if (image->storage_class == PseudoClass)
3215  {
3216  /*
3217  Initialize pixel array for images of type PseudoClass.
3218  */
3219  for (i=0; i < (ssize_t) image->colors; i++)
3220  pixel->pixels[i]=XGammaPacket(map_info,image->colormap+i);
3221  for (i=0; i < MaxNumberPens; i++)
3222  pixel->pixels[image->colors+i]=pixel->pen_colors[i].pixel;
3223  pixel->colors+=MaxNumberPens;
3224  }
3225  }
3226 }
3227 
3228 /*
3229 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3230 % %
3231 % %
3232 % %
3233 % X G e t R e s o u r c e C l a s s %
3234 % %
3235 % %
3236 % %
3237 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3238 %
3239 % XGetResourceClass() queries the X server for the specified resource name or
3240 % class. If the resource name or class is not defined in the database, the
3241 % supplied default value is returned.
3242 %
3243 % The format of the XGetResourceClass method is:
3244 %
3245 % char *XGetResourceClass(XrmDatabase database,const char *client_name,
3246 % const char *keyword,char *resource_default)
3247 %
3248 % A description of each parameter follows:
3249 %
3250 % o database: Specifies a resource database; returned from
3251 % XrmGetStringDatabase.
3252 %
3253 % o client_name: Specifies the application name used to retrieve resource
3254 % info from the X server database.
3255 %
3256 % o keyword: Specifies the keyword of the value being retrieved.
3257 %
3258 % o resource_default: Specifies the default value to return if the query
3259 % fails to find the specified keyword/class.
3260 %
3261 */
3262 MagickExport char *XGetResourceClass(XrmDatabase database,
3263  const char *client_name,const char *keyword,char *resource_default)
3264 {
3265  char
3266  resource_class[MagickPathExtent],
3267  resource_name[MagickPathExtent];
3268 
3269  static char
3270  *resource_type;
3271 
3272  Status
3273  status;
3274 
3275  XrmValue
3276  resource_value;
3277 
3278  if (database == (XrmDatabase) NULL)
3279  return(resource_default);
3280  *resource_name='\0';
3281  *resource_class='\0';
3282  if (keyword != (char *) NULL)
3283  {
3284  int
3285  c,
3286  k;
3287 
3288  /*
3289  Initialize resource keyword and class.
3290  */
3291  (void) FormatLocaleString(resource_name,MagickPathExtent,"%s.%s",
3292  client_name,keyword);
3293  c=(int) (*client_name);
3294  if ((c >= XK_a) && (c <= XK_z))
3295  c-=(XK_a-XK_A);
3296  else
3297  if ((c >= XK_agrave) && (c <= XK_odiaeresis))
3298  c-=(XK_agrave-XK_Agrave);
3299  else
3300  if ((c >= XK_oslash) && (c <= XK_thorn))
3301  c-=(XK_oslash-XK_Ooblique);
3302  k=(int) (*keyword);
3303  if ((k >= XK_a) && (k <= XK_z))
3304  k-=(XK_a-XK_A);
3305  else
3306  if ((k >= XK_agrave) && (k <= XK_odiaeresis))
3307  k-=(XK_agrave-XK_Agrave);
3308  else
3309  if ((k >= XK_oslash) && (k <= XK_thorn))
3310  k-=(XK_oslash-XK_Ooblique);
3311  (void) FormatLocaleString(resource_class,MagickPathExtent,"%c%s.%c%s",c,
3312  client_name+1,k,keyword+1);
3313  }
3314  status=XrmGetResource(database,resource_name,resource_class,&resource_type,
3315  &resource_value);
3316  if (status == False)
3317  return(resource_default);
3318  return(resource_value.addr);
3319 }
3320 
3321 /*
3322 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3323 % %
3324 % %
3325 % %
3326 % X G e t R e s o u r c e D a t a b a s e %
3327 % %
3328 % %
3329 % %
3330 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3331 %
3332 % XGetResourceDatabase() creates a new resource database and initializes it.
3333 %
3334 % The format of the XGetResourceDatabase method is:
3335 %
3336 % XrmDatabase XGetResourceDatabase(Display *display,
3337 % const char *client_name)
3338 %
3339 % A description of each parameter follows:
3340 %
3341 % o database: XGetResourceDatabase() returns the database after it is
3342 % initialized.
3343 %
3344 % o display: Specifies a connection to an X server; returned from
3345 % XOpenDisplay.
3346 %
3347 % o client_name: Specifies the application name used to retrieve resource
3348 % info from the X server database.
3349 %
3350 */
3351 MagickExport XrmDatabase XGetResourceDatabase(Display *display,
3352  const char *client_name)
3353 {
3354  char
3355  filename[MagickPathExtent];
3356 
3357  int
3358  c;
3359 
3360  const char
3361  *p;
3362 
3363  XrmDatabase
3364  resource_database,
3365  server_database;
3366 
3367  if (display == (Display *) NULL)
3368  return((XrmDatabase) NULL);
3369  assert(client_name != (char *) NULL);
3370  /*
3371  Initialize resource database.
3372  */
3373  XrmInitialize();
3374  (void) XGetDefault(display,(char *) client_name,"dummy");
3375  resource_database=XrmGetDatabase(display);
3376  /*
3377  Combine application database.
3378  */
3379  p=client_name+(strlen(client_name)-1);
3380  while ((p > client_name) && (*p != '/'))
3381  p--;
3382  if (*p == '/')
3383  client_name=p+1;
3384  c=(int) (*client_name);
3385  if ((c >= XK_a) && (c <= XK_z))
3386  c-=(XK_a-XK_A);
3387  else
3388  if ((c >= XK_agrave) && (c <= XK_odiaeresis))
3389  c-=(XK_agrave-XK_Agrave);
3390  else
3391  if ((c >= XK_oslash) && (c <= XK_thorn))
3392  c-=(XK_oslash-XK_Ooblique);
3393 #if defined(X11_APPLICATION_PATH)
3394  (void) FormatLocaleString(filename,MagickPathExtent,"%s%c%s",
3395  X11_APPLICATION_PATH,c,client_name+1);
3396  (void) XrmCombineFileDatabase(filename,&resource_database,MagickFalse);
3397 #endif
3398  if (XResourceManagerString(display) != (char *) NULL)
3399  {
3400  /*
3401  Combine server database.
3402  */
3403  server_database=XrmGetStringDatabase(XResourceManagerString(display));
3404  XrmCombineDatabase(server_database,&resource_database,MagickFalse);
3405  }
3406  /*
3407  Merge user preferences database.
3408  */
3409 #if defined(X11_PREFERENCES_PATH)
3410  (void) FormatLocaleString(filename,MagickPathExtent,"%s%src",
3411  X11_PREFERENCES_PATH,client_name);
3412  ExpandFilename(filename);
3413  (void) XrmCombineFileDatabase(filename,&resource_database,MagickFalse);
3414 #endif
3415  return(resource_database);
3416 }
3417 
3418 /*
3419 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3420 % %
3421 % %
3422 % %
3423 % X G e t R e s o u r c e I n f o %
3424 % %
3425 % %
3426 % %
3427 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3428 %
3429 % XGetResourceInfo(image_info,) initializes the ResourceInfo structure.
3430 %
3431 % The format of the XGetResourceInfo method is:
3432 %
3433 % void XGetResourceInfo(const ImageInfo *image_info,XrmDatabase database,
3434 % const char *client_name,XResourceInfo *resource_info)
3435 %
3436 % A description of each parameter follows:
3437 %
3438 % o image_info: the image info.
3439 %
3440 % o database: Specifies a resource database; returned from
3441 % XrmGetStringDatabase.
3442 %
3443 % o client_name: Specifies the application name used to retrieve
3444 % resource info from the X server database.
3445 %
3446 % o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
3447 %
3448 */
3449 MagickExport void XGetResourceInfo(const ImageInfo *image_info,
3450  XrmDatabase database,const char *client_name,XResourceInfo *resource_info)
3451 {
3452  char
3453  *directory,
3454  *resource_value;
3455 
3456  /*
3457  Initialize resource info fields.
3458  */
3459  (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
3460  assert(resource_info != (XResourceInfo *) NULL);
3461  (void) memset(resource_info,0,sizeof(*resource_info));
3462  resource_info->resource_database=database;
3463  resource_info->image_info=(ImageInfo *) image_info;
3464  (void) SetImageInfoProgressMonitor(resource_info->image_info,
3465  XMagickProgressMonitor,(void *) NULL);
3466  resource_info->quantize_info=CloneQuantizeInfo((QuantizeInfo *) NULL);
3467  resource_info->close_server=MagickTrue;
3468  resource_info->client_name=AcquireString(client_name);
3469  resource_value=XGetResourceClass(database,client_name,"backdrop",
3470  (char *) "False");
3471  resource_info->backdrop=IsStringTrue(resource_value);
3472  resource_info->background_color=XGetResourceInstance(database,client_name,
3473  "background",(char *) "#d6d6d6d6d6d6");
3474  resource_info->border_color=XGetResourceInstance(database,client_name,
3475  "borderColor",BorderColor);
3476  resource_value=XGetResourceClass(database,client_name,"borderWidth",
3477  (char *) "2");
3478  resource_info->border_width=(unsigned int) StringToUnsignedLong(
3479  resource_value);
3480  resource_value=XGetResourceClass(database,client_name,"colormap",
3481  (char *) "shared");
3482  resource_info->colormap=UndefinedColormap;
3483  if (LocaleCompare("private",resource_value) == 0)
3484  resource_info->colormap=PrivateColormap;
3485  if (LocaleCompare("shared",resource_value) == 0)
3486  resource_info->colormap=SharedColormap;
3487  if (resource_info->colormap == UndefinedColormap)
3488  ThrowXWindowException(OptionError,"UnrecognizedColormapType",
3489  resource_value);
3490  resource_value=XGetResourceClass(database,client_name,
3491  "colorRecovery",(char *) "False");
3492  resource_info->color_recovery=IsStringTrue(resource_value);
3493  resource_value=XGetResourceClass(database,client_name,"confirmExit",
3494  (char *) "False");
3495  resource_info->confirm_exit=IsStringTrue(resource_value);
3496  resource_value=XGetResourceClass(database,client_name,"confirmEdit",
3497  (char *) "False");
3498  resource_info->confirm_edit=IsStringTrue(resource_value);
3499  resource_value=XGetResourceClass(database,client_name,"delay",(char *) "1");
3500  resource_info->delay=(unsigned int) StringToUnsignedLong(resource_value);
3501  resource_info->display_gamma=XGetResourceClass(database,client_name,
3502  "displayGamma",(char *) "2.2");
3503  resource_value=XGetResourceClass(database,client_name,"displayWarnings",
3504  (char *) "True");
3505  resource_info->display_warnings=IsStringTrue(resource_value);
3506  resource_info->font=XGetResourceClass(database,client_name,"font",
3507  (char *) NULL);
3508  resource_info->font=XGetResourceClass(database,client_name,"fontList",
3509  resource_info->font);
3510  resource_info->font_name[0]=XGetResourceClass(database,client_name,"font1",
3511  (char *) "fixed");
3512  resource_info->font_name[1]=XGetResourceClass(database,client_name,"font2",
3513  (char *) "variable");
3514  resource_info->font_name[2]=XGetResourceClass(database,client_name,"font3",
3515  (char *) "5x8");
3516  resource_info->font_name[3]=XGetResourceClass(database,client_name,"font4",
3517  (char *) "6x10");
3518  resource_info->font_name[4]=XGetResourceClass(database,client_name,"font5",
3519  (char *) "7x13bold");
3520  resource_info->font_name[5]=XGetResourceClass(database,client_name,"font6",
3521  (char *) "8x13bold");
3522  resource_info->font_name[6]=XGetResourceClass(database,client_name,"font7",
3523  (char *) "9x15bold");
3524  resource_info->font_name[7]=XGetResourceClass(database,client_name,"font8",
3525  (char *) "10x20");
3526  resource_info->font_name[8]=XGetResourceClass(database,client_name,"font9",
3527  (char *) "12x24");
3528  resource_info->font_name[9]=XGetResourceClass(database,client_name,"font0",
3529  (char *) "fixed");
3530  resource_info->font_name[10]=XGetResourceClass(database,client_name,"font0",
3531  (char *) "fixed");
3532  resource_info->foreground_color=XGetResourceInstance(database,client_name,
3533  "foreground",ForegroundColor);
3534  resource_value=XGetResourceClass(database,client_name,"gammaCorrect",
3535  (char *) "False");
3536  resource_info->gamma_correct=IsStringTrue(resource_value);
3537  resource_info->image_geometry=ConstantString(XGetResourceClass(database,
3538  client_name,"geometry",(char *) NULL));
3539  resource_value=XGetResourceClass(database,client_name,"gravity",
3540  (char *) "Center");
3542  MagickFalse,resource_value);
3543  directory=getcwd(resource_info->home_directory,MagickPathExtent);
3544  (void) directory;
3545  resource_info->icon_geometry=XGetResourceClass(database,client_name,
3546  "iconGeometry",(char *) NULL);
3547  resource_value=XGetResourceClass(database,client_name,"iconic",
3548  (char *) "False");
3549  resource_info->iconic=IsStringTrue(resource_value);
3550  resource_value=XGetResourceClass(database,client_name,"immutable",
3551  LocaleCompare(client_name,"PerlMagick") == 0 ? (char *) "True" :
3552  (char *) "False");
3553  resource_info->immutable=IsStringTrue(resource_value);
3554  resource_value=XGetResourceClass(database,client_name,"magnify",
3555  (char *) "3");
3556  resource_info->magnify=(unsigned int) StringToUnsignedLong(resource_value);
3557  resource_info->map_type=XGetResourceClass(database,client_name,"map",
3558  (char *) NULL);
3559  resource_info->matte_color=XGetResourceInstance(database,client_name,
3560  "mattecolor",(char *) NULL);
3561  resource_info->name=ConstantString(XGetResourceClass(database,client_name,
3562  "name",(char *) NULL));
3563  resource_info->pen_colors[0]=XGetResourceClass(database,client_name,"pen1",
3564  (char *) "black");
3565  resource_info->pen_colors[1]=XGetResourceClass(database,client_name,"pen2",
3566  (char *) "blue");
3567  resource_info->pen_colors[2]=XGetResourceClass(database,client_name,"pen3",
3568  (char *) "cyan");
3569  resource_info->pen_colors[3]=XGetResourceClass(database,client_name,"pen4",
3570  (char *) "green");
3571  resource_info->pen_colors[4]=XGetResourceClass(database,client_name,"pen5",
3572  (char *) "gray");
3573  resource_info->pen_colors[5]=XGetResourceClass(database,client_name,"pen6",
3574  (char *) "red");
3575  resource_info->pen_colors[6]=XGetResourceClass(database,client_name,"pen7",
3576  (char *) "magenta");
3577  resource_info->pen_colors[7]=XGetResourceClass(database,client_name,"pen8",
3578  (char *) "yellow");
3579  resource_info->pen_colors[8]=XGetResourceClass(database,client_name,"pen9",
3580  (char *) "white");
3581  resource_info->pen_colors[9]=XGetResourceClass(database,client_name,"pen0",
3582  (char *) "gray");
3583  resource_info->pen_colors[10]=XGetResourceClass(database,client_name,"pen0",
3584  (char *) "gray");
3585  resource_value=XGetResourceClass(database,client_name,"pause",(char *) "0");
3586  resource_info->pause=(unsigned int) StringToUnsignedLong(resource_value);
3587  resource_value=XGetResourceClass(database,client_name,"quantum",(char *) "1");
3588  resource_info->quantum=StringToLong(resource_value);
3589  resource_info->text_font=XGetResourceClass(database,client_name,(char *)
3590  "font",(char *) "fixed");
3591  resource_info->text_font=XGetResourceClass(database,client_name,
3592  "textFontList",resource_info->text_font);
3593  resource_info->title=XGetResourceClass(database,client_name,"title",
3594  (char *) NULL);
3595  resource_value=XGetResourceClass(database,client_name,"undoCache",
3596  (char *) "256");
3597  resource_info->undo_cache=(unsigned int) StringToUnsignedLong(resource_value);
3598  resource_value=XGetResourceClass(database,client_name,"update",
3599  (char *) "False");
3600  resource_info->update=IsStringTrue(resource_value);
3601  resource_value=XGetResourceClass(database,client_name,"usePixmap",
3602  (char *) "True");
3603  resource_info->use_pixmap=IsStringTrue(resource_value);
3604  resource_value=XGetResourceClass(database,client_name,"sharedMemory",
3605  (char *) "True");
3606  resource_info->use_shared_memory=IsStringTrue(resource_value);
3607  resource_info->visual_type=XGetResourceClass(database,client_name,"visual",
3608  (char *) NULL);
3609  resource_info->window_group=XGetResourceClass(database,client_name,
3610  "windowGroup",(char *) NULL);
3611  resource_info->window_id=XGetResourceClass(database,client_name,"window",
3612  (char *) NULL);
3613  resource_info->write_filename=XGetResourceClass(database,client_name,
3614  "writeFilename",(char *) NULL);
3615 }
3616 
3617 /*
3618 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3619 % %
3620 % %
3621 % %
3622 % X G e t R e s o u r c e I n s t a n c e %
3623 % %
3624 % %
3625 % %
3626 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3627 %
3628 % XGetResourceInstance() queries the X server for the specified resource name.
3629 % If the resource name is not defined in the database, the supplied default
3630 % value is returned.
3631 %
3632 % The format of the XGetResourceInstance method is:
3633 %
3634 % char *XGetResourceInstance(XrmDatabase database,const char *client_name,
3635 % const char *keyword,const char *resource_default)
3636 %
3637 % A description of each parameter follows:
3638 %
3639 % o database: Specifies a resource database; returned from
3640 % XrmGetStringDatabase.
3641 %
3642 % o client_name: Specifies the application name used to retrieve
3643 % resource info from the X server database.
3644 %
3645 % o keyword: Specifies the keyword of the value being retrieved.
3646 %
3647 % o resource_default: Specifies the default value to return if the query
3648 % fails to find the specified keyword/class.
3649 %
3650 */
3651 MagickExport char *XGetResourceInstance(XrmDatabase database,
3652  const char *client_name,const char *keyword,const char *resource_default)
3653 {
3654  char
3655  *resource_type,
3656  resource_name[MagickPathExtent];
3657 
3658  Status
3659  status;
3660 
3661  XrmValue
3662  resource_value;
3663 
3664  if (database == (XrmDatabase) NULL)
3665  return((char *) resource_default);
3666  *resource_name='\0';
3667  if (keyword != (char *) NULL)
3668  (void) FormatLocaleString(resource_name,MagickPathExtent,"%s.%s",client_name,
3669  keyword);
3670  status=XrmGetResource(database,resource_name,"ImageMagick",&resource_type,
3671  &resource_value);
3672  if (status == False)
3673  return((char *) resource_default);
3674  return(resource_value.addr);
3675 }
3676 
3677 /*
3678 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3679 % %
3680 % %
3681 % %
3682 % X G e t S c r e e n D e n s i t y %
3683 % %
3684 % %
3685 % %
3686 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3687 %
3688 % XGetScreenDensity() returns the density of the X server screen in
3689 % dots-per-inch.
3690 %
3691 % The format of the XGetScreenDensity method is:
3692 %
3693 % char *XGetScreenDensity(Display *display)
3694 %
3695 % A description of each parameter follows:
3696 %
3697 % o density: XGetScreenDensity() returns the density of the X screen in
3698 % dots-per-inch.
3699 %
3700 % o display: Specifies a connection to an X server; returned from
3701 % XOpenDisplay.
3702 %
3703 */
3704 MagickExport char *XGetScreenDensity(Display *display)
3705 {
3706  char
3707  density[MagickPathExtent];
3708 
3709  double
3710  x_density,
3711  y_density;
3712 
3713  /*
3714  Set density as determined by screen size.
3715  */
3716  x_density=((((double) DisplayWidth(display,XDefaultScreen(display)))*25.4)/
3717  ((double) DisplayWidthMM(display,XDefaultScreen(display))));
3718  y_density=((((double) DisplayHeight(display,XDefaultScreen(display)))*25.4)/
3719  ((double) DisplayHeightMM(display,XDefaultScreen(display))));
3720  (void) FormatLocaleString(density,MagickPathExtent,"%gx%g",x_density,
3721  y_density);
3722  return(GetPageGeometry(density));
3723 }
3724 
3725 /*
3726 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3727 % %
3728 % %
3729 % %
3730 + X G e t S u b w i n d o w %
3731 % %
3732 % %
3733 % %
3734 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3735 %
3736 % XGetSubwindow() returns the subwindow of a window chosen the user with the
3737 % pointer and a button press.
3738 %
3739 % The format of the XGetSubwindow method is:
3740 %
3741 % Window XGetSubwindow(Display *display,Window window,int x,int y)
3742 %
3743 % A description of each parameter follows:
3744 %
3745 % o subwindow: XGetSubwindow() returns NULL if no subwindow is found
3746 % otherwise the subwindow is returned.
3747 %
3748 % o display: Specifies a connection to an X server; returned from
3749 % XOpenDisplay.
3750 %
3751 % o window: Specifies a pointer to a Window.
3752 %
3753 % o x: the x coordinate of the pointer relative to the origin of the
3754 % window.
3755 %
3756 % o y: the y coordinate of the pointer relative to the origin of the
3757 % window.
3758 %
3759 */
3760 static Window XGetSubwindow(Display *display,Window window,int x,int y)
3761 {
3762  int
3763  x_offset,
3764  y_offset;
3765 
3766  Status
3767  status;
3768 
3769  Window
3770  source_window,
3771  target_window;
3772 
3773  assert(display != (Display *) NULL);
3774  source_window=XRootWindow(display,XDefaultScreen(display));
3775  if (window == (Window) NULL)
3776  return(source_window);
3777  target_window=window;
3778  for ( ; ; )
3779  {
3780  status=XTranslateCoordinates(display,source_window,window,x,y,
3781  &x_offset,&y_offset,&target_window);
3782  if (status != True)
3783  break;
3784  if (target_window == (Window) NULL)
3785  break;
3786  source_window=window;
3787  window=target_window;
3788  x=x_offset;
3789  y=y_offset;
3790  }
3791  if (target_window == (Window) NULL)
3792  target_window=window;
3793  return(target_window);
3794 }
3795 
3796 /*
3797 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3798 % %
3799 % %
3800 % %
3801 % X G e t W i n d o w C o l o r %
3802 % %
3803 % %
3804 % %
3805 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3806 %
3807 % XGetWindowColor() returns the color of a pixel interactively chosen from the
3808 % X server.
3809 %
3810 % The format of the XGetWindowColor method is:
3811 %
3812 % MagickBooleanType XGetWindowColor(Display *display,XWindows *windows,
3813 % char *name,ExceptionInfo *exception)
3814 %
3815 % A description of each parameter follows:
3816 %
3817 % o display: Specifies a connection to an X server; returned from
3818 % XOpenDisplay.
3819 %
3820 % o windows: Specifies a pointer to a XWindows structure.
3821 %
3822 % o name: the name of the color if found in the X Color Database is
3823 % returned in this character string.
3824 %
3825 % o exception: return any errors or warnings in this structure.
3826 %
3827 */
3828 MagickPrivate MagickBooleanType XGetWindowColor(Display *display,
3829  XWindows *windows,char *name,ExceptionInfo *exception)
3830 {
3831  int
3832  x,
3833  y;
3834 
3835  PixelInfo
3836  pixel;
3837 
3839  crop_info;
3840 
3841  Status
3842  status;
3843 
3844  Window
3845  child,
3846  client_window,
3847  root_window,
3848  target_window;
3849 
3850  XColor
3851  color;
3852 
3853  XImage
3854  *ximage;
3855 
3856  XWindowAttributes
3857  window_attributes;
3858 
3859  /*
3860  Choose a pixel from the X server.
3861  */
3862  assert(display != (Display *) NULL);
3863  assert(name != (char *) NULL);
3864  (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",name);
3865  *name='\0';
3866  target_window=XSelectWindow(display,&crop_info);
3867  if (target_window == (Window) NULL)
3868  return(MagickFalse);
3869  root_window=XRootWindow(display,XDefaultScreen(display));
3870  client_window=target_window;
3871  if (target_window != root_window)
3872  {
3873  unsigned int
3874  d;
3875 
3876  /*
3877  Get client window.
3878  */
3879  status=XGetGeometry(display,target_window,&root_window,&x,&x,&d,&d,&d,&d);
3880  if (status != False)
3881  {
3882  client_window=XClientWindow(display,target_window);
3883  target_window=client_window;
3884  }
3885  }
3886  /*
3887  Verify window is viewable.
3888  */
3889  status=XGetWindowAttributes(display,target_window,&window_attributes);
3890  if ((status == False) || (window_attributes.map_state != IsViewable))
3891  return(MagickFalse);
3892  /*
3893  Get window X image.
3894  */
3895  (void) XTranslateCoordinates(display,root_window,target_window,
3896  (int) crop_info.x,(int) crop_info.y,&x,&y,&child);
3897  ximage=XGetImage(display,target_window,x,y,1,1,AllPlanes,ZPixmap);
3898  if (ximage == (XImage *) NULL)
3899  return(MagickFalse);
3900  color.pixel=XGetPixel(ximage,0,0);
3901  XDestroyImage(ximage);
3902  /*
3903  Match color against the color database.
3904  */
3905  (void) XQueryColor(display,window_attributes.colormap,&color);
3906  pixel.red=(double) ScaleShortToQuantum(color.red);
3907  pixel.green=(double) ScaleShortToQuantum(color.green);
3908  pixel.blue=(double) ScaleShortToQuantum(color.blue);
3910  (void) QueryColorname(windows->image.image,&pixel,X11Compliance,name,
3911  exception);
3912  return(MagickTrue);
3913 }
3914 
3915 /*
3916 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3917 % %
3918 % %
3919 % %
3920 + X G e t W i n d o w I m a g e %
3921 % %
3922 % %
3923 % %
3924 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3925 %
3926 % XGetWindowImage() reads an image from the target X window and returns it.
3927 % XGetWindowImage() optionally descends the window hierarchy and overlays the
3928 % target image with each child image in an optimized fashion. Any child
3929 % window that have the same visual, colormap, and are contained by its parent
3930 % are exempted.
3931 %
3932 % The format of the XGetWindowImage method is:
3933 %
3934 % Image *XGetWindowImage(Display *display,const Window window,
3935 % const unsigned int borders,const unsigned int level,
3936 % ExceptionInfo *exception)
3937 %
3938 % A description of each parameter follows:
3939 %
3940 % o display: Specifies a connection to an X server; returned from
3941 % XOpenDisplay.
3942 %
3943 % o window: Specifies the window to obtain the image from.
3944 %
3945 % o borders: Specifies whether borders pixels are to be saved with
3946 % the image.
3947 %
3948 % o level: Specifies an unsigned integer representing the level of
3949 % decent in the window hierarchy. This value must be zero or one on
3950 % the initial call to XGetWindowImage. A value of zero returns after
3951 % one call. A value of one causes the function to descend the window
3952 % hierarchy and overlay the target image with each subwindow image.
3953 %
3954 % o exception: return any errors or warnings in this structure.
3955 %
3956 */
3957 static Image *XGetWindowImage(Display *display,const Window window,
3958  const unsigned int borders,const unsigned int level,ExceptionInfo *exception)
3959 {
3960  typedef struct _ColormapInfo
3961  {
3962  Colormap
3963  colormap;
3964 
3965  XColor
3966  *colors;
3967 
3968  struct _ColormapInfo
3969  *next;
3970  } ColormapInfo;
3971 
3972  typedef struct _WindowInfo
3973  {
3974  Window
3975  window,
3976  parent;
3977 
3978  Visual
3979  *visual;
3980 
3981  Colormap
3982  colormap;
3983 
3984  XSegment
3985  bounds;
3986 
3988  crop_info;
3989  } WindowInfo;
3990 
3991  int
3992  display_height,
3993  display_width,
3994  id,
3995  x_offset,
3996  y_offset;
3997 
3998  Quantum
3999  index;
4000 
4002  crop_info;
4003 
4004  int
4005  i;
4006 
4007  static ColormapInfo
4008  *colormap_info = (ColormapInfo *) NULL;
4009 
4010  static int
4011  max_windows = 0,
4012  number_windows = 0;
4013 
4014  static WindowInfo
4015  *window_info;
4016 
4017  Status
4018  status;
4019 
4020  Window
4021  child,
4022  root_window;
4023 
4024  XWindowAttributes
4025  window_attributes;
4026 
4027  /*
4028  Verify window is viewable.
4029  */
4030  (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
4031  assert(display != (Display *) NULL);
4032  status=XGetWindowAttributes(display,window,&window_attributes);
4033  if ((status == False) || (window_attributes.map_state != IsViewable))
4034  return((Image *) NULL);
4035  /*
4036  Cropping rectangle is relative to root window.
4037  */
4038  root_window=XRootWindow(display,XDefaultScreen(display));
4039  (void) XTranslateCoordinates(display,window,root_window,0,0,&x_offset,
4040  &y_offset,&child);
4041  crop_info.x=(ssize_t) x_offset;
4042  crop_info.y=(ssize_t) y_offset;
4043  crop_info.width=(size_t) window_attributes.width;
4044  crop_info.height=(size_t) window_attributes.height;
4045  if (borders != MagickFalse)
4046  {
4047  /*
4048  Include border in image.
4049  */
4050  crop_info.x-=(ssize_t) window_attributes.border_width;
4051  crop_info.y-=(ssize_t) window_attributes.border_width;
4052  crop_info.width+=(size_t) (window_attributes.border_width << 1);
4053  crop_info.height+=(size_t) (window_attributes.border_width << 1);
4054  }
4055  /*
4056  Crop to root window.
4057  */
4058  if (crop_info.x < 0)
4059  {
4060  crop_info.width+=crop_info.x;
4061  crop_info.x=0;
4062  }
4063  if (crop_info.y < 0)
4064  {
4065  crop_info.height+=crop_info.y;
4066  crop_info.y=0;
4067  }
4068  display_width=XDisplayWidth(display,XDefaultScreen(display));
4069  if ((int) (crop_info.x+crop_info.width) > display_width)
4070  crop_info.width=(size_t) (display_width-crop_info.x);
4071  display_height=XDisplayHeight(display,XDefaultScreen(display));
4072  if ((int) (crop_info.y+crop_info.height) > display_height)
4073  crop_info.height=(size_t) (display_height-crop_info.y);
4074  /*
4075  Initialize window info attributes.
4076  */
4077  if (number_windows >= max_windows)
4078  {
4079  /*
4080  Allocate or resize window info buffer.
4081  */
4082  max_windows+=1024;
4083  if (window_info == (WindowInfo *) NULL)
4084  window_info=(WindowInfo *) AcquireQuantumMemory((size_t) max_windows,
4085  sizeof(*window_info));
4086  else
4087  window_info=(WindowInfo *) ResizeQuantumMemory(window_info,(size_t)
4088  max_windows,sizeof(*window_info));
4089  }
4090  if (window_info == (WindowInfo *) NULL)
4091  {
4092  ThrowXWindowException(ResourceLimitError,"MemoryAllocationFailed","...");
4093  return((Image *) NULL);
4094  }
4095  id=number_windows++;
4096  window_info[id].window=window;
4097  window_info[id].visual=window_attributes.visual;
4098  window_info[id].colormap=window_attributes.colormap;
4099  window_info[id].bounds.x1=(short) crop_info.x;
4100  window_info[id].bounds.y1=(short) crop_info.y;
4101  window_info[id].bounds.x2=(short) (crop_info.x+(int) crop_info.width-1);
4102  window_info[id].bounds.y2=(short) (crop_info.y+(int) crop_info.height-1);
4103  crop_info.x-=x_offset;
4104  crop_info.y-=y_offset;
4105  window_info[id].crop_info=crop_info;
4106  if (level != 0)
4107  {
4108  unsigned int
4109  number_children;
4110 
4111  Window
4112  *children;
4113 
4114  /*
4115  Descend the window hierarchy.
4116  */
4117  status=XQueryTree(display,window,&root_window,&window_info[id].parent,
4118  &children,&number_children);
4119  for (i=0; i < id; i++)
4120  if ((window_info[i].window == window_info[id].parent) &&
4121  (window_info[i].visual == window_info[id].visual) &&
4122  (window_info[i].colormap == window_info[id].colormap))
4123  {
4124  if ((window_info[id].bounds.x1 < window_info[i].bounds.x1) ||
4125  (window_info[id].bounds.x2 > window_info[i].bounds.x2) ||
4126  (window_info[id].bounds.y1 < window_info[i].bounds.y1) ||
4127  (window_info[id].bounds.y2 > window_info[i].bounds.y2))
4128  {
4129  /*
4130  Eliminate windows not circumscribed by their parent.
4131  */
4132  number_windows--;
4133  break;
4134  }
4135  }
4136  if ((status == True) && (number_children != 0))
4137  {
4138  for (i=0; i < (int) number_children; i++)
4139  (void) XGetWindowImage(display,children[i],MagickFalse,level+1,
4140  exception);
4141  (void) XFree((void *) children);
4142  }
4143  }
4144  if (level <= 1)
4145  {
4146  CacheView
4147  *composite_view;
4148 
4149  ColormapInfo
4150  *next;
4151 
4152  Image
4153  *composite_image,
4154  *image;
4155 
4156  int
4157  y;
4158 
4160  import;
4161 
4162  int
4163  j,
4164  x;
4165 
4166  Quantum
4167  *magick_restrict q;
4168 
4169  size_t
4170  pixel;
4171 
4172  unsigned int
4173  number_colors;
4174 
4175  XColor
4176  *colors;
4177 
4178  XImage
4179  *ximage;
4180 
4181  /*
4182  Get X image for each window in the list.
4183  */
4184  image=NewImageList();
4185  for (id=0; id < number_windows; id++)
4186  {
4187  /*
4188  Does target window intersect top level window?
4189  */
4190  import=((window_info[id].bounds.x2 >= window_info[0].bounds.x1) &&
4191  (window_info[id].bounds.x1 <= window_info[0].bounds.x2) &&
4192  (window_info[id].bounds.y2 >= window_info[0].bounds.y1) &&
4193  (window_info[id].bounds.y1 <= window_info[0].bounds.y2)) ?
4195  /*
4196  Is target window contained by another window with the same colormap?
4197  */
4198  for (j=0; j < id; j++)
4199  if ((window_info[id].visual == window_info[j].visual) &&
4200  (window_info[id].colormap == window_info[j].colormap))
4201  {
4202  if ((window_info[id].bounds.x1 >= window_info[j].bounds.x1) &&
4203  (window_info[id].bounds.x2 <= window_info[j].bounds.x2) &&
4204  (window_info[id].bounds.y1 >= window_info[j].bounds.y1) &&
4205  (window_info[id].bounds.y2 <= window_info[j].bounds.y2))
4206  import=MagickFalse;
4207  }
4208  if (import == MagickFalse)
4209  continue;
4210  /*
4211  Get X image.
4212  */
4213  ximage=XGetImage(display,window_info[id].window,(int)
4214  window_info[id].crop_info.x,(int) window_info[id].crop_info.y,
4215  (unsigned int) window_info[id].crop_info.width,(unsigned int)
4216  window_info[id].crop_info.height,AllPlanes,ZPixmap);
4217  if (ximage == (XImage *) NULL)
4218  continue;
4219  /*
4220  Initialize window colormap.
4221  */
4222  number_colors=0;
4223  colors=(XColor *) NULL;
4224  if (window_info[id].colormap != (Colormap) NULL)
4225  {
4226  ColormapInfo
4227  *p;
4228 
4229  /*
4230  Search colormap list for window colormap.
4231  */
4232  number_colors=(unsigned int) window_info[id].visual->map_entries;
4233  for (p=colormap_info; p != (ColormapInfo *) NULL; p=p->next)
4234  if (p->colormap == window_info[id].colormap)
4235  break;
4236  if (p == (ColormapInfo *) NULL)
4237  {
4238  /*
4239  Get the window colormap.
4240  */
4241  colors=(XColor *) AcquireQuantumMemory(number_colors,
4242  sizeof(*colors));
4243  if (colors == (XColor *) NULL)
4244  {
4245  XDestroyImage(ximage);
4246  return((Image *) NULL);
4247  }
4248  if ((window_info[id].visual->klass != DirectColor) &&
4249  (window_info[id].visual->klass != TrueColor))
4250  for (i=0; i < (int) number_colors; i++)
4251  {
4252  colors[i].pixel=(size_t) i;
4253  colors[i].pad='\0';
4254  }
4255  else
4256  {
4257  size_t
4258  blue,
4259  blue_bit,
4260  green,
4261  green_bit,
4262  red,
4263  red_bit;
4264 
4265  /*
4266  DirectColor or TrueColor visual.
4267  */
4268  red=0;
4269  green=0;
4270  blue=0;
4271  red_bit=window_info[id].visual->red_mask &
4272  (~(window_info[id].visual->red_mask)+1);
4273  green_bit=window_info[id].visual->green_mask &
4274  (~(window_info[id].visual->green_mask)+1);
4275  blue_bit=window_info[id].visual->blue_mask &
4276  (~(window_info[id].visual->blue_mask)+1);
4277  for (i=0; i < (int) number_colors; i++)
4278  {
4279  colors[i].pixel=(unsigned long) (red | green | blue);
4280  colors[i].pad='\0';
4281  red+=red_bit;
4282  if (red > window_info[id].visual->red_mask)
4283  red=0;
4284  green+=green_bit;
4285  if (green > window_info[id].visual->green_mask)
4286  green=0;
4287  blue+=blue_bit;
4288  if (blue > window_info[id].visual->blue_mask)
4289  blue=0;
4290  }
4291  }
4292  (void) XQueryColors(display,window_info[id].colormap,colors,
4293  (int) number_colors);
4294  /*
4295  Append colormap to colormap list.
4296  */
4297  p=(ColormapInfo *) AcquireMagickMemory(sizeof(*p));
4298  if (p == (ColormapInfo *) NULL)
4299  return((Image *) NULL);
4300  p->colormap=window_info[id].colormap;
4301  p->colors=colors;
4302  p->next=colormap_info;
4303  colormap_info=p;
4304  }
4305  colors=p->colors;
4306  }
4307  /*
4308  Allocate image structure.
4309  */
4310  composite_image=AcquireImage((ImageInfo *) NULL,exception);
4311  if (composite_image == (Image *) NULL)
4312  {
4313  XDestroyImage(ximage);
4314  return((Image *) NULL);
4315  }
4316  /*
4317  Convert X image to MIFF format.
4318  */
4319  if ((window_info[id].visual->klass != TrueColor) &&
4320  (window_info[id].visual->klass != DirectColor))
4321  composite_image->storage_class=PseudoClass;
4322  composite_image->columns=(size_t) ximage->width;
4323  composite_image->rows=(size_t) ximage->height;
4324  composite_view=AcquireAuthenticCacheView(composite_image,exception);
4325  switch (composite_image->storage_class)
4326  {
4327  case DirectClass:
4328  default:
4329  {
4330  size_t
4331  color,
4332  index;
4333 
4334  size_t
4335  blue_mask,
4336  blue_shift,
4337  green_mask,
4338  green_shift,
4339  red_mask,
4340  red_shift;
4341 
4342  /*
4343  Determine shift and mask for red, green, and blue.
4344  */
4345  red_mask=window_info[id].visual->red_mask;
4346  red_shift=0;
4347  while ((red_mask != 0) && ((red_mask & 0x01) == 0))
4348  {
4349  red_mask>>=1;
4350  red_shift++;
4351  }
4352  green_mask=window_info[id].visual->green_mask;
4353  green_shift=0;
4354  while ((green_mask != 0) && ((green_mask & 0x01) == 0))
4355  {
4356  green_mask>>=1;
4357  green_shift++;
4358  }
4359  blue_mask=window_info[id].visual->blue_mask;
4360  blue_shift=0;
4361  while ((blue_mask != 0) && ((blue_mask & 0x01) == 0))
4362  {
4363  blue_mask>>=1;
4364  blue_shift++;
4365  }
4366  /*
4367  Convert X image to DirectClass packets.
4368  */
4369  if ((number_colors != 0) &&
4370  (window_info[id].visual->klass == DirectColor))
4371  for (y=0; y < (int) composite_image->rows; y++)
4372  {
4373  q=QueueCacheViewAuthenticPixels(composite_view,0,(ssize_t) y,
4374  composite_image->columns,1,exception);
4375  if (q == (Quantum *) NULL)
4376  break;
4377  for (x=0; x < (int) composite_image->columns; x++)
4378  {
4379  pixel=XGetPixel(ximage,x,y);
4380  index=(pixel >> red_shift) & red_mask;
4381  SetPixelRed(composite_image,
4382  ScaleShortToQuantum(colors[index].red),q);
4383  index=(pixel >> green_shift) & green_mask;
4384  SetPixelGreen(composite_image,
4385  ScaleShortToQuantum(colors[index].green),q);
4386  index=(pixel >> blue_shift) & blue_mask;
4387  SetPixelBlue(composite_image,
4388  ScaleShortToQuantum(colors[index].blue),q);
4389  q+=GetPixelChannels(composite_image);
4390  }
4391  status=SyncCacheViewAuthenticPixels(composite_view,exception);
4392  if (status == MagickFalse)
4393  break;
4394  }
4395  else
4396  for (y=0; y < (int) composite_image->rows; y++)
4397  {
4398  q=QueueCacheViewAuthenticPixels(composite_view,0,(ssize_t) y,
4399  composite_image->columns,1,exception);
4400  if (q == (Quantum *) NULL)
4401  break;
4402  for (x=0; x < (int) composite_image->columns; x++)
4403  {
4404  pixel=XGetPixel(ximage,x,y);
4405  color=(pixel >> red_shift) & red_mask;
4406  if (red_mask != 0)
4407  color=(65535UL*color)/red_mask;
4408  SetPixelRed(composite_image,ScaleShortToQuantum(
4409  (unsigned short) color),q);
4410  color=(pixel >> green_shift) & green_mask;
4411  if (green_mask != 0)
4412  color=(65535UL*color)/green_mask;
4413  SetPixelGreen(composite_image,ScaleShortToQuantum(
4414  (unsigned short) color),q);
4415  color=(pixel >> blue_shift) & blue_mask;
4416  if (blue_mask != 0)
4417  color=(65535UL*color)/blue_mask;
4418  SetPixelBlue(composite_image,ScaleShortToQuantum(
4419  (unsigned short) color),q);
4420  q+=GetPixelChannels(composite_image);
4421  }
4422  status=SyncCacheViewAuthenticPixels(composite_view,exception);
4423  if (status == MagickFalse)
4424  break;
4425  }
4426  break;
4427  }
4428  case PseudoClass:
4429  {
4430  /*
4431  Create colormap.
4432  */
4433  status=AcquireImageColormap(composite_image,number_colors,
4434  exception);
4435  if (status == MagickFalse)
4436  {
4437  XDestroyImage(ximage);
4438  composite_image=DestroyImage(composite_image);
4439  return((Image *) NULL);
4440  }
4441  for (i=0; i < (int) composite_image->colors; i++)
4442  {
4443  composite_image->colormap[colors[i].pixel].red=(double)
4444  ScaleShortToQuantum(colors[i].red);
4445  composite_image->colormap[colors[i].pixel].green=(double)
4446  ScaleShortToQuantum(colors[i].green);
4447  composite_image->colormap[colors[i].pixel].blue=(double)
4448  ScaleShortToQuantum(colors[i].blue);
4449  }
4450  /*
4451  Convert X image to PseudoClass packets.
4452  */
4453  for (y=0; y < (int) composite_image->rows; y++)
4454  {
4455  q=QueueCacheViewAuthenticPixels(composite_view,0,(ssize_t) y,
4456  composite_image->columns,1,exception);
4457  if (q == (Quantum *) NULL)
4458  break;
4459  for (x=0; x < (int) composite_image->columns; x++)
4460  {
4461  index=(Quantum) XGetPixel(ximage,x,y);
4462  SetPixelIndex(composite_image,index,q);
4463  SetPixelViaPixelInfo(composite_image,
4464  composite_image->colormap+(ssize_t) index,q);
4465  q+=GetPixelChannels(composite_image);
4466  }
4467  status=SyncCacheViewAuthenticPixels(composite_view,exception);
4468  if (status == MagickFalse)
4469  break;
4470  }
4471  break;
4472  }
4473  }
4474  composite_view=DestroyCacheView(composite_view);
4475  XDestroyImage(ximage);
4476  if (image == (Image *) NULL)
4477  {
4478  image=composite_image;
4479  continue;
4480  }
4481  /*
4482  Composite any children in back-to-front order.
4483  */
4484  (void) XTranslateCoordinates(display,window_info[id].window,window,0,0,
4485  &x_offset,&y_offset,&child);
4486  x_offset-=(int) crop_info.x;
4487  if (x_offset < 0)
4488  x_offset=0;
4489  y_offset-=(int) crop_info.y;
4490  if (y_offset < 0)
4491  y_offset=0;
4492  (void) CompositeImage(image,composite_image,CopyCompositeOp,MagickTrue,
4493  (ssize_t) x_offset,(ssize_t) y_offset,exception);
4494  composite_image=DestroyImage(composite_image);
4495  }
4496  /*
4497  Relinquish resources.
4498  */
4499  while (colormap_info != (ColormapInfo *) NULL)
4500  {
4501  next=colormap_info->next;
4502  colormap_info->colors=(XColor *) RelinquishMagickMemory(
4503  colormap_info->colors);
4504  colormap_info=(ColormapInfo *) RelinquishMagickMemory(colormap_info);
4505  colormap_info=next;
4506  }
4507  /*
4508  Relinquish resources and restore initial state.
4509  */
4510  window_info=(WindowInfo *) RelinquishMagickMemory(window_info);
4511  max_windows=0;
4512  number_windows=0;
4513  colormap_info=(ColormapInfo *) NULL;
4514  return(image);
4515  }
4516  return((Image *) NULL);
4517 }
4518 
4519 /*
4520 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4521 % %
4522 % %
4523 % %
4524 % X G e t W i n d o w I n f o %
4525 % %
4526 % %
4527 % %
4528 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4529 %
4530 % XGetWindowInfo() initializes the XWindowInfo structure.
4531 %
4532 % The format of the XGetWindowInfo method is:
4533 %
4534 % void XGetWindowInfo(Display *display,XVisualInfo *visual_info,
4535 % XStandardColormap *map_info,XPixelInfo *pixel,XFontStruct *font_info,
4536 % XResourceInfo *resource_info,XWindowInfo *window)
4537 % resource_info,window)
4538 %
4539 % A description of each parameter follows:
4540 %
4541 % o display: Specifies a connection to an X server; returned from
4542 % XOpenDisplay.
4543 %
4544 % o visual_info: Specifies a pointer to a X11 XVisualInfo structure;
4545 % returned from XGetVisualInfo.
4546 %
4547 % o map_info: If map_type is specified, this structure is initialized
4548 % with info from the Standard Colormap.
4549 %
4550 % o pixel: Specifies a pointer to a XPixelInfo structure.
4551 %
4552 % o font_info: Specifies a pointer to a XFontStruct structure.
4553 %
4554 % o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
4555 %
4556 */
4557 MagickPrivate void XGetWindowInfo(Display *display,XVisualInfo *visual_info,
4558  XStandardColormap *map_info,XPixelInfo *pixel,XFontStruct *font_info,
4559  XResourceInfo *resource_info,XWindowInfo *window)
4560 {
4561  /*
4562  Initialize window info.
4563  */
4564  (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
4565  assert(display != (Display *) NULL);
4566  assert(visual_info != (XVisualInfo *) NULL);
4567  assert(map_info != (XStandardColormap *) NULL);
4568  assert(pixel != (XPixelInfo *) NULL);
4569  assert(resource_info != (XResourceInfo *) NULL);
4570  assert(window != (XWindowInfo *) NULL);
4571  if (window->id != (Window) NULL)
4572  {
4573  if (window->cursor != (Cursor) NULL)
4574  (void) XFreeCursor(display,window->cursor);
4575  if (window->busy_cursor != (Cursor) NULL)
4576  (void) XFreeCursor(display,window->busy_cursor);
4577  if (window->highlight_stipple != (Pixmap) NULL)
4578  (void) XFreePixmap(display,window->highlight_stipple);
4579  if (window->shadow_stipple != (Pixmap) NULL)
4580  (void) XFreePixmap(display,window->shadow_stipple);
4581  if (window->name == (char *) NULL)
4582  window->name=AcquireString("");
4583  if (window->icon_name == (char *) NULL)
4584  window->icon_name=AcquireString("");
4585  }
4586  else
4587  {
4588  /*
4589  Initialize these attributes just once.
4590  */
4591  window->id=(Window) NULL;
4592  if (window->name == (char *) NULL)
4593  window->name=AcquireString("");
4594  if (window->icon_name == (char *) NULL)
4595  window->icon_name=AcquireString("");
4596  window->x=XDisplayWidth(display,visual_info->screen) >> 1;
4597  window->y=XDisplayWidth(display,visual_info->screen) >> 1;
4598  window->ximage=(XImage *) NULL;
4599  window->matte_image=(XImage *) NULL;
4600  window->pixmap=(Pixmap) NULL;
4601  window->matte_pixmap=(Pixmap) NULL;
4602  window->mapped=MagickFalse;
4603  window->stasis=MagickFalse;
4604  window->shared_memory=MagickTrue;
4605  window->segment_info=(void *) NULL;
4606 #if defined(MAGICKCORE_HAVE_SHARED_MEMORY)
4607  {
4608  XShmSegmentInfo
4609  *segment_info;
4610 
4611  if (window->segment_info == (void *) NULL)
4612  window->segment_info=AcquireCriticalMemory(2*sizeof(*segment_info));
4613  segment_info=(XShmSegmentInfo *) window->segment_info;
4614  segment_info[0].shmid=(-1);
4615  segment_info[0].shmaddr=(char *) NULL;
4616  segment_info[1].shmid=(-1);
4617  segment_info[1].shmaddr=(char *) NULL;
4618  }
4619 #endif
4620  }
4621  /*
4622  Initialize these attributes every time function is called.
4623  */
4624  window->screen=visual_info->screen;
4625  window->root=XRootWindow(display,visual_info->screen);
4626  window->visual=visual_info->visual;
4627  window->storage_class=(unsigned int) visual_info->klass;
4628  window->depth=(unsigned int) visual_info->depth;
4629  window->visual_info=visual_info;
4630  window->map_info=map_info;
4631  window->pixel_info=pixel;
4632  window->font_info=font_info;
4633  window->cursor=XCreateFontCursor(display,XC_left_ptr);
4634  window->busy_cursor=XCreateFontCursor(display,XC_watch);
4635  window->geometry=(char *) NULL;
4636  window->icon_geometry=(char *) NULL;
4637  if (resource_info->icon_geometry != (char *) NULL)
4638  (void) CloneString(&window->icon_geometry,resource_info->icon_geometry);
4639  window->crop_geometry=(char *) NULL;
4640  window->flags=(size_t) PSize;
4641  window->width=1;
4642  window->height=1;
4643  window->min_width=1;
4644  window->min_height=1;
4645  window->width_inc=1;
4646  window->height_inc=1;
4647  window->border_width=resource_info->border_width;
4648  window->annotate_context=pixel->annotate_context;
4649  window->highlight_context=pixel->highlight_context;
4650  window->widget_context=pixel->widget_context;
4651  window->shadow_stipple=(Pixmap) NULL;
4652  window->highlight_stipple=(Pixmap) NULL;
4653  window->use_pixmap=MagickTrue;
4654  window->immutable=MagickFalse;
4655  window->shape=MagickFalse;
4656  window->data=0;
4657  window->mask=(int) (CWBackingStore | CWBackPixel | CWBackPixmap |
4658  CWBitGravity | CWBorderPixel | CWColormap | CWCursor | CWDontPropagate |
4659  CWEventMask | CWOverrideRedirect | CWSaveUnder | CWWinGravity);
4660  window->attributes.background_pixel=pixel->background_color.pixel;
4661  window->attributes.background_pixmap=(Pixmap) NULL;
4662  window->attributes.bit_gravity=ForgetGravity;
4663  window->attributes.backing_store=WhenMapped;
4664  window->attributes.save_under=MagickTrue;
4665  window->attributes.border_pixel=pixel->border_color.pixel;
4666  window->attributes.colormap=map_info->colormap;
4667  window->attributes.cursor=window->cursor;
4668  window->attributes.do_not_propagate_mask=NoEventMask;
4669  window->attributes.event_mask=NoEventMask;
4670  window->attributes.override_redirect=MagickFalse;
4671  window->attributes.win_gravity=NorthWestGravity;
4672  window->orphan=MagickFalse;
4673 }
4674 
4675 /*
4676 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4677 % %
4678 % %
4679 % %
4680 % X H i g h l i g h t E l l i p s e %
4681 % %
4682 % %
4683 % %
4684 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4685 %
4686 % XHighlightEllipse() puts a border on the X server around a region defined by
4687 % highlight_info.
4688 %
4689 % The format of the XHighlightEllipse method is:
4690 %
4691 % void XHighlightEllipse(Display *display,Window window,
4692 % GC annotate_context,const RectangleInfo *highlight_info)
4693 %
4694 % A description of each parameter follows:
4695 %
4696 % o display: Specifies a connection to an X server; returned from
4697 % XOpenDisplay.
4698 %
4699 % o window: Specifies a pointer to a Window structure.
4700 %
4701 % o annotate_context: Specifies a pointer to a GC structure.
4702 %
4703 % o highlight_info: Specifies a pointer to a RectangleInfo structure. It
4704 % contains the extents of any highlighting rectangle.
4705 %
4706 */
4707 MagickPrivate void XHighlightEllipse(Display *display,Window window,
4708  GC annotate_context,const RectangleInfo *highlight_info)
4709 {
4710  (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
4711  assert(display != (Display *) NULL);
4712  assert(window != (Window) NULL);
4713  assert(annotate_context != (GC) NULL);
4714  assert(highlight_info != (RectangleInfo *) NULL);
4715  if ((highlight_info->width < 4) || (highlight_info->height < 4))
4716  return;
4717  (void) XDrawArc(display,window,annotate_context,(int) highlight_info->x,
4718  (int) highlight_info->y,(unsigned int) highlight_info->width-1,
4719  (unsigned int) highlight_info->height-1,0,360*64);
4720  (void) XDrawArc(display,window,annotate_context,(int) highlight_info->x+1,
4721  (int) highlight_info->y+1,(unsigned int) highlight_info->width-3,
4722  (unsigned int) highlight_info->height-3,0,360*64);
4723 }
4724 
4725 /*
4726 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4727 % %
4728 % %
4729 % %
4730 % X H i g h l i g h t L i n e %
4731 % %
4732 % %
4733 % %
4734 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4735 %
4736 % XHighlightLine() puts a border on the X server around a region defined by
4737 % highlight_info.
4738 %
4739 % The format of the XHighlightLine method is:
4740 %
4741 % void XHighlightLine(Display *display,Window window,GC annotate_context,
4742 % const XSegment *highlight_info)
4743 %
4744 % A description of each parameter follows:
4745 %
4746 % o display: Specifies a connection to an X server; returned from
4747 % XOpenDisplay.
4748 %
4749 % o window: Specifies a pointer to a Window structure.
4750 %
4751 % o annotate_context: Specifies a pointer to a GC structure.
4752 %
4753 % o highlight_info: Specifies a pointer to a RectangleInfo structure. It
4754 % contains the extents of any highlighting rectangle.
4755 %
4756 */
4757 MagickPrivate void XHighlightLine(Display *display,Window window,
4758  GC annotate_context,const XSegment *highlight_info)
4759 {
4760  (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
4761  assert(display != (Display *) NULL);
4762  assert(window != (Window) NULL);
4763  assert(annotate_context != (GC) NULL);
4764  assert(highlight_info != (XSegment *) NULL);
4765  (void) XDrawLine(display,window,annotate_context,highlight_info->x1,
4766  highlight_info->y1,highlight_info->x2,highlight_info->y2);
4767 }
4768 
4769 /*
4770 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4771 % %
4772 % %
4773 % %
4774 % X H i g h l i g h t R e c t a n g l e %
4775 % %
4776 % %
4777 % %
4778 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4779 %
4780 % XHighlightRectangle() puts a border on the X server around a region defined
4781 % by highlight_info.
4782 %
4783 % The format of the XHighlightRectangle method is:
4784 %
4785 % void XHighlightRectangle(Display *display,Window window,
4786 % GC annotate_context,const RectangleInfo *highlight_info)
4787 %
4788 % A description of each parameter follows:
4789 %
4790 % o display: Specifies a connection to an X server; returned from
4791 % XOpenDisplay.
4792 %
4793 % o window: Specifies a pointer to a Window structure.
4794 %
4795 % o annotate_context: Specifies a pointer to a GC structure.
4796 %
4797 % o highlight_info: Specifies a pointer to a RectangleInfo structure. It
4798 % contains the extents of any highlighting rectangle.
4799 %
4800 */
4801 MagickPrivate void XHighlightRectangle(Display *display,Window window,
4802  GC annotate_context,const RectangleInfo *highlight_info)
4803 {
4804  assert(display != (Display *) NULL);
4805  (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
4806  assert(window != (Window) NULL);
4807  assert(annotate_context != (GC) NULL);
4808  assert(highlight_info != (RectangleInfo *) NULL);
4809  if ((highlight_info->width < 4) || (highlight_info->height < 4))
4810  return;
4811  (void) XDrawRectangle(display,window,annotate_context,(int) highlight_info->x,
4812  (int) highlight_info->y,(unsigned int) highlight_info->width-1,
4813  (unsigned int) highlight_info->height-1);
4814  (void) XDrawRectangle(display,window,annotate_context,(int) highlight_info->x+
4815  1,(int) highlight_info->y+1,(unsigned int) highlight_info->width-3,
4816  (unsigned int) highlight_info->height-3);
4817 }
4818 
4819 /*
4820 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4821 % %
4822 % %
4823 % %
4824 % X I m p o r t I m a g e %
4825 % %
4826 % %
4827 % %
4828 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4829 %
4830 % XImportImage() reads an image from an X window.
4831 %
4832 % The format of the XImportImage method is:
4833 %
4834 % Image *XImportImage(const ImageInfo *image_info,XImportInfo *ximage_info,
4835 % ExceptionInfo *exception)
4836 %
4837 % A description of each parameter follows:
4838 %
4839 % o image_info: the image info.
4840 %
4841 % o ximage_info: Specifies a pointer to an XImportInfo structure.
4842 %
4843 % o exception: return any errors or warnings in this structure.
4844 %
4845 */
4846 MagickExport Image *XImportImage(const ImageInfo *image_info,
4847  XImportInfo *ximage_info,ExceptionInfo *exception)
4848 {
4849  Colormap
4850  *colormaps;
4851 
4852  Display
4853  *display;
4854 
4855  Image
4856  *image;
4857 
4858  int
4859  number_colormaps,
4860  number_windows,
4861  x;
4862 
4864  crop_info;
4865 
4866  Status
4867  status;
4868 
4869  Window
4870  *children,
4871  client,
4872  prior_target,
4873  root,
4874  target;
4875 
4876  XTextProperty
4877  window_name;
4878 
4879  /*
4880  Open X server connection.
4881  */
4882  assert(image_info != (const ImageInfo *) NULL);
4883  assert(image_info->signature == MagickCoreSignature);
4884  if (image_info->debug != MagickFalse)
4886  image_info->filename);
4887  assert(ximage_info != (XImportInfo *) NULL);
4888  display=XOpenDisplay(image_info->server_name);
4889  if (display == (Display *) NULL)
4890  {
4891  ThrowXWindowException(XServerError,"UnableToOpenXServer",
4892  XDisplayName(image_info->server_name));
4893  return((Image *) NULL);
4894  }
4895  /*
4896  Set our forgiving exception handler.
4897  */
4898  (void) XSetErrorHandler(XError);
4899  /*
4900  Select target window.
4901  */
4902  crop_info.x=0;
4903  crop_info.y=0;
4904  crop_info.width=0;
4905  crop_info.height=0;
4906  root=XRootWindow(display,XDefaultScreen(display));
4907  target=(Window) NULL;
4908  if (*image_info->filename != '\0')
4909  {
4910  if (LocaleCompare(image_info->filename,"root") == 0)
4911  target=root;
4912  else
4913  {
4914  /*
4915  Select window by ID or name.
4916  */
4917  if (isdigit((int) ((unsigned char) *image_info->filename)) != 0)
4918  target=XWindowByID(display,root,(Window)
4919  strtol(image_info->filename,(char **) NULL,0));
4920  if (target == (Window) NULL)
4921  target=XWindowByName(display,root,image_info->filename);
4922  if (target == (Window) NULL)
4923  ThrowXWindowException(XServerError,"NoWindowWithSpecifiedIDExists",
4924  image_info->filename);
4925  }
4926  }
4927  /*
4928  If target window is not defined, interactively select one.
4929  */
4930  prior_target=target;
4931  if (target == (Window) NULL)
4932  target=XSelectWindow(display,&crop_info);
4933  if (target == (Window) NULL)
4934  ThrowXWindowException(XServerError,"UnableToReadXWindowImage",
4935  image_info->filename);
4936  client=target; /* obsolete */
4937  if (target != root)
4938  {
4939  unsigned int
4940  d;
4941 
4942  status=XGetGeometry(display,target,&root,&x,&x,&d,&d,&d,&d);
4943  if (status != False)
4944  {
4945  for ( ; ; )
4946  {
4947  Window
4948  parent;
4949 
4950  /*
4951  Find window manager frame.
4952  */
4953  status=XQueryTree(display,target,&root,&parent,&children,&d);
4954  if ((status != False) && (children != (Window *) NULL))
4955  (void) XFree((char *) children);
4956  if ((status == False) || (parent == (Window) NULL) ||
4957  (parent == root))
4958  break;
4959  target=parent;
4960  }
4961  /*
4962  Get client window.
4963  */
4964  client=XClientWindow(display,target);
4965  if (ximage_info->frame == MagickFalse)
4966  target=client;
4967  if ((ximage_info->frame == MagickFalse) &&
4968  (prior_target != MagickFalse))
4969  target=prior_target;
4970  }
4971  }
4972  if (ximage_info->screen != MagickFalse)
4973  {
4974  int
4975  y;
4976 
4977  Window
4978  child;
4979 
4980  XWindowAttributes
4981  window_attributes;
4982 
4983  /*
4984  Obtain window image directly from screen.
4985  */
4986  status=XGetWindowAttributes(display,target,&window_attributes);
4987  if (status == False)
4988  {
4989  ThrowXWindowException(XServerError,"UnableToReadXWindowAttributes",
4990  image_info->filename);
4991  (void) XCloseDisplay(display);
4992  return((Image *) NULL);
4993  }
4994  (void) XTranslateCoordinates(display,target,root,0,0,&x,&y,&child);
4995  crop_info.x=(ssize_t) x;
4996  crop_info.y=(ssize_t) y;
4997  crop_info.width=(size_t) window_attributes.width;
4998  crop_info.height=(size_t) window_attributes.height;
4999  if (ximage_info->borders != 0)
5000  {
5001  /*
5002  Include border in image.
5003  */
5004  crop_info.x-=window_attributes.border_width;
5005  crop_info.y-=window_attributes.border_width;
5006  crop_info.width+=window_attributes.border_width << 1;
5007  crop_info.height+=window_attributes.border_width << 1;
5008  }
5009  target=root;
5010  }
5011  /*
5012  If WM_COLORMAP_WINDOWS property is set or multiple colormaps, descend.
5013  */
5014  number_windows=0;
5015  status=XGetWMColormapWindows(display,target,&children,&number_windows);
5016  if ((status == True) && (number_windows > 0))
5017  {
5018  ximage_info->descend=MagickTrue;
5019  (void) XFree ((char *) children);
5020  }
5021  colormaps=XListInstalledColormaps(display,target,&number_colormaps);
5022  if (number_colormaps > 0)
5023  {
5024  if (number_colormaps > 1)
5025  ximage_info->descend=MagickTrue;
5026  (void) XFree((char *) colormaps);
5027  }
5028  /*
5029  Alert the user not to alter the screen.
5030  */
5031  if (ximage_info->silent == MagickFalse)
5032  (void) XBell(display,0);
5033  /*
5034  Get image by window id.
5035  */
5036  (void) XGrabServer(display);
5037  image=XGetWindowImage(display,target,ximage_info->borders,
5038  ximage_info->descend ? 1U : 0U,exception);
5039  (void) XUngrabServer(display);
5040  if (image == (Image *) NULL)
5041  ThrowXWindowException(XServerError,"UnableToReadXWindowImage",
5042  image_info->filename)
5043  else
5044  {
5045  (void) CopyMagickString(image->filename,image_info->filename,
5047  if ((crop_info.width != 0) && (crop_info.height != 0))
5048  {
5049  Image
5050  *crop_image;
5051 
5052  /*
5053  Crop image as defined by the cropping rectangle.
5054  */
5055  crop_image=CropImage(image,&crop_info,exception);
5056  if (crop_image != (Image *) NULL)
5057  {
5058  image=DestroyImage(image);
5059  image=crop_image;
5060  }
5061  }
5062  status=XGetWMName(display,target,&window_name);
5063  if (status == True)
5064  {
5065  if (*image_info->filename == '\0')
5066  (void) CopyMagickString(image->filename,(char *) window_name.value,
5067  (size_t) window_name.nitems+1);
5068  (void) XFree((void *) window_name.value);
5069  }
5070  }
5071  if (ximage_info->silent == MagickFalse)
5072  {
5073  /*
5074  Alert the user we're done.
5075  */
5076  (void) XBell(display,0);
5077  (void) XBell(display,0);
5078  }
5079  (void) XCloseDisplay(display);
5080  return(image);
5081 }
5082 
5083 /*
5084 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5085 % %
5086 % %
5087 % %
5088 % X I n i t i a l i z e W i n d o w s %
5089 % %
5090 % %
5091 % %
5092 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5093 %
5094 % XInitializeWindows() initializes the XWindows structure.
5095 %
5096 % The format of the XInitializeWindows method is:
5097 %
5098 % XWindows *XInitializeWindows(Display *display,
5099 % XResourceInfo *resource_info)
5100 %
5101 % A description of each parameter follows:
5102 %
5103 % o windows: XInitializeWindows returns a pointer to a XWindows structure.
5104 %
5105 % o display: Specifies a connection to an X server; returned from
5106 % XOpenDisplay.
5107 %
5108 % o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
5109 %
5110 */
5111 MagickPrivate XWindows *XInitializeWindows(Display *display,
5112  XResourceInfo *resource_info)
5113 {
5114  Window
5115  root_window;
5116 
5117  XWindows
5118  *windows;
5119 
5120  /*
5121  Allocate windows structure.
5122  */
5123  windows=(XWindows *) AcquireMagickMemory(sizeof(*windows));
5124  if (windows == (XWindows *) NULL)
5125  {
5126  ThrowXWindowFatalException(XServerFatalError,"MemoryAllocationFailed",
5127  "...");
5128  return((XWindows *) NULL);
5129  }
5130  (void) memset(windows,0,sizeof(*windows));
5131  windows->pixel_info=(XPixelInfo *) AcquireQuantumMemory(1,
5132  sizeof(*windows->pixel_info));
5133  windows->icon_pixel=(XPixelInfo *) AcquireQuantumMemory(1,
5134  sizeof(*windows->icon_pixel));
5135  windows->icon_resources=(XResourceInfo *) AcquireQuantumMemory(1,
5136  sizeof(*windows->icon_resources));
5137  if ((windows->pixel_info == (XPixelInfo *) NULL) ||
5138  (windows->icon_pixel == (XPixelInfo *) NULL) ||
5139  (windows->icon_resources == (XResourceInfo *) NULL))
5140  {
5141  ThrowXWindowFatalException(XServerFatalError,"MemoryAllocationFailed",
5142  "...");
5143  return((XWindows *) NULL);
5144  }
5145  /*
5146  Initialize windows structure.
5147  */
5148  windows->display=display;
5149  windows->wm_protocols=XInternAtom(display,"WM_PROTOCOLS",MagickFalse);
5150  windows->wm_delete_window=XInternAtom(display,"WM_DELETE_WINDOW",MagickFalse);
5151  windows->wm_take_focus=XInternAtom(display,"WM_TAKE_FOCUS",MagickFalse);
5152  windows->im_protocols=XInternAtom(display,"IM_PROTOCOLS",MagickFalse);
5153  windows->im_remote_command=
5154  XInternAtom(display,"IM_REMOTE_COMMAND",MagickFalse);
5155  windows->im_update_widget=XInternAtom(display,"IM_UPDATE_WIDGET",MagickFalse);
5156  windows->im_update_colormap=
5157  XInternAtom(display,"IM_UPDATE_COLORMAP",MagickFalse);
5158  windows->im_former_image=XInternAtom(display,"IM_FORMER_IMAGE",MagickFalse);
5159  windows->im_next_image=XInternAtom(display,"IM_NEXT_IMAGE",MagickFalse);
5160  windows->im_retain_colors=XInternAtom(display,"IM_RETAIN_COLORS",MagickFalse);
5161  windows->im_exit=XInternAtom(display,"IM_EXIT",MagickFalse);
5162  windows->dnd_protocols=XInternAtom(display,"DndProtocol",MagickFalse);
5163 #if defined(MAGICKCORE_WINDOWS_SUPPORT)
5164  (void) XSynchronize(display,MagickFalse);
5165 #endif
5166  if (IsEventLogging())
5167  {
5168  (void) XSynchronize(display,MagickTrue);
5169  (void) LogMagickEvent(X11Event,GetMagickModule(),"Version: %s",
5170  GetMagickVersion((size_t *) NULL));
5171  (void) LogMagickEvent(X11Event,GetMagickModule(),"Protocols:");
5173  " Window Manager: 0x%lx",windows->wm_protocols);
5175  " delete window: 0x%lx",windows->wm_delete_window);
5176  (void) LogMagickEvent(X11Event,GetMagickModule()," take focus: 0x%lx",
5177  windows->wm_take_focus);
5178  (void) LogMagickEvent(X11Event,GetMagickModule()," ImageMagick: 0x%lx",
5179  windows->im_protocols);
5181  " remote command: 0x%lx",windows->im_remote_command);
5183  " update widget: 0x%lx",windows->im_update_widget);
5185  " update colormap: 0x%lx",windows->im_update_colormap);
5187  " former image: 0x%lx",windows->im_former_image);
5188  (void) LogMagickEvent(X11Event,GetMagickModule()," next image: 0x%lx",
5189  windows->im_next_image);
5191  " retain colors: 0x%lx",windows->im_retain_colors);
5192  (void) LogMagickEvent(X11Event,GetMagickModule()," exit: 0x%lx",
5193  windows->im_exit);
5194  (void) LogMagickEvent(X11Event,GetMagickModule()," Drag and Drop: 0x%lx",
5195  windows->dnd_protocols);
5196  }
5197  /*
5198  Allocate standard colormap.
5199  */
5200  windows->map_info=XAllocStandardColormap();
5201  windows->icon_map=XAllocStandardColormap();
5202  if ((windows->map_info == (XStandardColormap *) NULL) ||
5203  (windows->icon_map == (XStandardColormap *) NULL))
5204  ThrowXWindowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed",
5205  "...");
5206  windows->map_info->colormap=(Colormap) NULL;
5207  windows->icon_map->colormap=(Colormap) NULL;
5208  windows->pixel_info->pixels=(unsigned long *) NULL;
5209  windows->pixel_info->annotate_context=(GC) NULL;
5210  windows->pixel_info->highlight_context=(GC) NULL;
5211  windows->pixel_info->widget_context=(GC) NULL;
5212  windows->font_info=(XFontStruct *) NULL;
5213  windows->icon_pixel->annotate_context=(GC) NULL;
5214  windows->icon_pixel->pixels=(unsigned long *) NULL;
5215  /*
5216  Allocate visual.
5217  */
5218  *windows->icon_resources=(*resource_info);
5219  windows->icon_resources->visual_type=(char *) "default";
5220  windows->icon_resources->colormap=SharedColormap;
5221  windows->visual_info=
5222  XBestVisualInfo(display,windows->map_info,resource_info);
5223  windows->icon_visual=
5224  XBestVisualInfo(display,windows->icon_map,windows->icon_resources);
5225  if ((windows->visual_info == (XVisualInfo *) NULL) ||
5226  (windows->icon_visual == (XVisualInfo *) NULL))
5227  ThrowXWindowFatalException(XServerFatalError,"UnableToGetVisual",
5228  resource_info->visual_type);
5229  if (IsEventLogging())
5230  {
5231  (void) LogMagickEvent(X11Event,GetMagickModule(),"Visual:");
5232  (void) LogMagickEvent(X11Event,GetMagickModule()," visual id: 0x%lx",
5233  windows->visual_info->visualid);
5234  (void) LogMagickEvent(X11Event,GetMagickModule()," class: %s",
5235  XVisualClassName(windows->visual_info->klass));
5236  (void) LogMagickEvent(X11Event,GetMagickModule()," depth: %d planes",
5237  windows->visual_info->depth);
5239  " size of colormap: %d entries",windows->visual_info->colormap_size);
5241  " red, green, blue masks: 0x%lx 0x%lx 0x%lx",
5242  windows->visual_info->red_mask,windows->visual_info->green_mask,
5243  windows->visual_info->blue_mask);
5245  " significant bits in color: %d bits",
5246  windows->visual_info->bits_per_rgb);
5247  }
5248  /*
5249  Allocate class and manager hints.
5250  */
5251  windows->class_hints=XAllocClassHint();
5252  windows->manager_hints=XAllocWMHints();
5253  if ((windows->class_hints == (XClassHint *) NULL) ||
5254  (windows->manager_hints == (XWMHints *) NULL))
5255  ThrowXWindowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed",
5256  "...");
5257  /*
5258  Determine group leader if we have one.
5259  */
5260  root_window=XRootWindow(display,windows->visual_info->screen);
5261  windows->group_leader.id=(Window) NULL;
5262  if (resource_info->window_group != (char *) NULL)
5263  {
5264  if (isdigit((int) ((unsigned char) *resource_info->window_group)) != 0)
5265  windows->group_leader.id=XWindowByID(display,root_window,(Window)
5266  strtol((char *) resource_info->window_group,(char **) NULL,0));
5267  if (windows->group_leader.id == (Window) NULL)
5268  windows->group_leader.id=
5269  XWindowByName(display,root_window,resource_info->window_group);
5270  }
5271  return(windows);
5272 }
5273 
5274 /*
5275 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5276 % %
5277 % %
5278 % %
5279 % X M a k e C u r s o r %
5280 % %
5281 % %
5282 % %
5283 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5284 %
5285 % XMakeCursor() creates a crosshairs X11 cursor.
5286 %
5287 % The format of the XMakeCursor method is:
5288 %
5289 % Cursor XMakeCursor(Display *display,Window window,Colormap colormap,
5290 % char *background_color,char *foreground_color)
5291 %
5292 % A description of each parameter follows:
5293 %
5294 % o display: Specifies a connection to an X server; returned from
5295 % XOpenDisplay.
5296 %
5297 % o window: Specifies the ID of the window for which the cursor is
5298 % assigned.
5299 %
5300 % o colormap: Specifies the ID of the colormap from which the background
5301 % and foreground color will be retrieved.
5302 %
5303 % o background_color: Specifies the color to use for the cursor background.
5304 %
5305 % o foreground_color: Specifies the color to use for the cursor foreground.
5306 %
5307 */
5308 MagickPrivate Cursor XMakeCursor(Display *display,Window window,
5309  Colormap colormap,char *background_color,char *foreground_color)
5310 {
5311 #define scope_height 17
5312 #define scope_x_hot 8
5313 #define scope_y_hot 8
5314 #define scope_width 17
5315 
5316  static const unsigned char
5317  scope_bits[] =
5318  {
5319  0x80, 0x03, 0x00, 0x80, 0x02, 0x00, 0x80, 0x02, 0x00, 0x80, 0x02,
5320  0x00, 0x80, 0x02, 0x00, 0x80, 0x02, 0x00, 0x80, 0x02, 0x00, 0x7f,
5321  0xfc, 0x01, 0x01, 0x00, 0x01, 0x7f, 0xfc, 0x01, 0x80, 0x02, 0x00,
5322  0x80, 0x02, 0x00, 0x80, 0x02, 0x00, 0x80, 0x02, 0x00, 0x80, 0x02,
5323  0x00, 0x80, 0x02, 0x00, 0x80, 0x03, 0x00
5324  },
5325  scope_mask_bits[] =
5326  {
5327  0xc0, 0x07, 0x00, 0xc0, 0x07, 0x00, 0xc0, 0x06, 0x00, 0xc0, 0x06,
5328  0x00, 0xc0, 0x06, 0x00, 0xc0, 0x06, 0x00, 0xff, 0xfe, 0x01, 0x7f,
5329  0xfc, 0x01, 0x03, 0x80, 0x01, 0x7f, 0xfc, 0x01, 0xff, 0xfe, 0x01,
5330  0xc0, 0x06, 0x00, 0xc0, 0x06, 0x00, 0xc0, 0x06, 0x00, 0xc0, 0x06,
5331  0x00, 0xc0, 0x07, 0x00, 0xc0, 0x07, 0x00
5332  };
5333 
5334  Cursor
5335  cursor;
5336 
5337  Pixmap
5338  mask,
5339  source;
5340 
5341  XColor
5342  background,
5343  foreground;
5344 
5345  assert(display != (Display *) NULL);
5346  assert(window != (Window) NULL);
5347  assert(colormap != (Colormap) NULL);
5348  assert(background_color != (char *) NULL);
5349  assert(foreground_color != (char *) NULL);
5350  (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",background_color);
5351  source=XCreateBitmapFromData(display,window,(char *) scope_bits,scope_width,
5352  scope_height);
5353  mask=XCreateBitmapFromData(display,window,(char *) scope_mask_bits,
5354  scope_width,scope_height);
5355  if ((source == (Pixmap) NULL) || (mask == (Pixmap) NULL))
5356  {
5357  ThrowXWindowException(XServerError,"UnableToCreatePixmap","...");
5358  return((Cursor) NULL);
5359  }
5360  (void) XParseColor(display,colormap,background_color,&background);
5361  (void) XParseColor(display,colormap,foreground_color,&foreground);
5362  cursor=XCreatePixmapCursor(display,source,mask,&foreground,&background,
5363  scope_x_hot,scope_y_hot);
5364  (void) XFreePixmap(display,source);
5365  (void) XFreePixmap(display,mask);
5366  return(cursor);
5367 }
5368 
5369 /*
5370 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5371 % %
5372 % %
5373 % %
5374 % X M a k e I m a g e %
5375 % %
5376 % %
5377 % %
5378 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5379 %
5380 % XMakeImage() creates an X11 image. If the image size differs from the X11
5381 % image size, the image is first resized.
5382 %
5383 % The format of the XMakeImage method is:
5384 %
5385 % MagickBooleanType XMakeImage(Display *display,
5386 % const XResourceInfo *resource_info,XWindowInfo *window,Image *image,
5387 % unsigned int width,unsigned int height,ExceptionInfo *exception)
5388 %
5389 % A description of each parameter follows:
5390 %
5391 % o display: Specifies a connection to an X server; returned from
5392 % XOpenDisplay.
5393 %
5394 % o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
5395 %
5396 % o window: Specifies a pointer to a XWindowInfo structure.
5397 %
5398 % o image: the image.
5399 %
5400 % o width: Specifies the width in pixels of the rectangular area to
5401 % display.
5402 %
5403 % o height: Specifies the height in pixels of the rectangular area to
5404 % display.
5405 %
5406 % o exception: return any errors or warnings in this structure.
5407 %
5408 */
5409 MagickPrivate MagickBooleanType XMakeImage(Display *display,
5410  const XResourceInfo *resource_info,XWindowInfo *window,Image *image,
5411  unsigned int width,unsigned int height,ExceptionInfo *exception)
5412 {
5413 #define CheckOverflowException(length,width,height) \
5414  (((height) != 0) && ((length)/((size_t) height) != ((size_t) width)))
5415 
5416  int
5417  depth,
5418  format;
5419 
5420  size_t
5421  length;
5422 
5423  XImage
5424  *matte_image,
5425  *ximage;
5426 
5427  (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
5428  assert(display != (Display *) NULL);
5429  assert(resource_info != (XResourceInfo *) NULL);
5430  assert(window != (XWindowInfo *) NULL);
5431  assert(width != 0);
5432  assert(height != 0);
5433  if ((window->width == 0) || (window->height == 0))
5434  return(MagickFalse);
5435  /*
5436  Apply user transforms to the image.
5437  */
5438  (void) XCheckDefineCursor(display,window->id,window->busy_cursor);
5439  (void) XFlush(display);
5440  depth=(int) window->depth;
5441  if (window->destroy)
5442  window->image=DestroyImage(window->image);
5443  window->image=image;
5444  window->destroy=MagickFalse;
5445  if (window->image != (Image *) NULL)
5446  {
5447  if (window->crop_geometry != (char *) NULL)
5448  {
5449  Image
5450  *crop_image;
5451 
5453  crop_info;
5454 
5455  /*
5456  Crop image.
5457  */
5458  window->image->page.x=0;
5459  window->image->page.y=0;
5460  (void) ParsePageGeometry(window->image,window->crop_geometry,
5461  &crop_info,exception);
5462  crop_image=CropImage(window->image,&crop_info,exception);
5463  if (crop_image != (Image *) NULL)
5464  {
5465  if (window->image != image)
5466  window->image=DestroyImage(window->image);
5467  window->image=crop_image;
5468  window->destroy=MagickTrue;
5469  }
5470  }
5471  if ((width != (unsigned int) window->image->columns) ||
5472  (height != (unsigned int) window->image->rows))
5473  {
5474  Image
5475  *resize_image;
5476 
5477  /*
5478  Resize image.
5479  */
5480  resize_image=NewImageList();
5481  if ((window->pixel_info->colors == 0) &&
5482  (window->image->rows > (unsigned long) XDisplayHeight(display,window->screen)) &&
5483  (window->image->columns > (unsigned long) XDisplayWidth(display,window->screen)))
5484  resize_image=ResizeImage(window->image,width,height,
5485  image->filter,exception);
5486  else
5487  {
5488  if (window->image->storage_class == PseudoClass)
5489  resize_image=SampleImage(window->image,width,height,
5490  exception);
5491  else
5492  resize_image=ThumbnailImage(window->image,width,height,
5493  exception);
5494  }
5495  if (resize_image != (Image *) NULL)
5496  {
5497  if (window->image != image)
5498  window->image=DestroyImage(window->image);
5499  window->image=resize_image;
5500  window->destroy=MagickTrue;
5501  }
5502  }
5503  width=(unsigned int) window->image->columns;
5504  assert((size_t) width == window->image->columns);
5505  height=(unsigned int) window->image->rows;
5506  assert((size_t) height == window->image->rows);
5507  }
5508  /*
5509  Create X image.
5510  */
5511  ximage=(XImage *) NULL;
5512  format=(depth == 1) ? XYBitmap : ZPixmap;
5513 #if defined(MAGICKCORE_HAVE_SHARED_MEMORY)
5514  if (window->shared_memory != MagickFalse)
5515  {
5516  XShmSegmentInfo
5517  *segment_info;
5518 
5519  segment_info=(XShmSegmentInfo *) window->segment_info;
5520  segment_info[1].shmid=(-1);
5521  segment_info[1].shmaddr=(char *) NULL;
5522  ximage=XShmCreateImage(display,window->visual,(unsigned int) depth,format,
5523  (char *) NULL,&segment_info[1],width,height);
5524  length=0;
5525  if (ximage == (XImage *) NULL)
5526  window->shared_memory=MagickFalse;
5527  else
5528  {
5529  length=(size_t) ximage->bytes_per_line*ximage->height;
5530  if (CheckOverflowException(length,ximage->bytes_per_line,ximage->height))
5531  window->shared_memory=MagickFalse;
5532  }
5533  if (window->shared_memory != MagickFalse)
5534  segment_info[1].shmid=shmget(IPC_PRIVATE,length,IPC_CREAT | 0777);
5535  if (window->shared_memory != MagickFalse)
5536  segment_info[1].shmaddr=(char *) shmat(segment_info[1].shmid,0,0);
5537  if (segment_info[1].shmid < 0)
5538  window->shared_memory=MagickFalse;
5539  if (window->shared_memory != MagickFalse)
5540  (void) shmctl(segment_info[1].shmid,IPC_RMID,0);
5541  else
5542  {
5543  if (ximage != (XImage *) NULL)
5544  XDestroyImage(ximage);
5545  ximage=(XImage *) NULL;
5546  if (segment_info[1].shmaddr)
5547  {
5548  (void) shmdt(segment_info[1].shmaddr);
5549  segment_info[1].shmaddr=(char *) NULL;
5550  }
5551  if (segment_info[1].shmid >= 0)
5552  {
5553  (void) shmctl(segment_info[1].shmid,IPC_RMID,0);
5554  segment_info[1].shmid=(-1);
5555  }
5556  }
5557  }
5558 #endif
5559  /*
5560  Allocate X image pixel data.
5561  */
5562 #if defined(MAGICKCORE_HAVE_SHARED_MEMORY)
5563  if (window->shared_memory)
5564  {
5565  Status
5566  status;
5567 
5568  XShmSegmentInfo
5569  *segment_info;
5570 
5571  (void) XSync(display,MagickFalse);
5572  xerror_alert=MagickFalse;
5573  segment_info=(XShmSegmentInfo *) window->segment_info;
5574  ximage->data=segment_info[1].shmaddr;
5575  segment_info[1].readOnly=MagickFalse;
5576  status=XShmAttach(display,&segment_info[1]);
5577  if (status != False)
5578  (void) XSync(display,MagickFalse);
5579  if ((status == False) || (xerror_alert != MagickFalse))
5580  {
5581  window->shared_memory=MagickFalse;
5582  if (status != False)
5583  XShmDetach(display,&segment_info[1]);
5584  ximage->data=NULL;
5585  XDestroyImage(ximage);
5586  ximage=(XImage *) NULL;
5587  if (segment_info[1].shmid >= 0)
5588  {
5589  if (segment_info[1].shmaddr != NULL)
5590  (void) shmdt(segment_info[1].shmaddr);
5591  (void) shmctl(segment_info[1].shmid,IPC_RMID,0);
5592  segment_info[1].shmid=(-1);
5593  segment_info[1].shmaddr=(char *) NULL;
5594  }
5595  }
5596  }
5597 #endif
5598  if (window->shared_memory == MagickFalse)
5599  ximage=XCreateImage(display,window->visual,(unsigned int) depth,format,0,
5600  (char *) NULL,width,height,XBitmapPad(display),0);
5601  if (ximage == (XImage *) NULL)
5602  {
5603  /*
5604  Unable to create X image.
5605  */
5606  (void) XCheckDefineCursor(display,window->id,window->cursor);
5607  return(MagickFalse);
5608  }
5609  length=(size_t) ximage->bytes_per_line*ximage->height;
5610  if (IsEventLogging())
5611  {
5612  (void) LogMagickEvent(X11Event,GetMagickModule(),"XImage:");
5613  (void) LogMagickEvent(X11Event,GetMagickModule()," width, height: %dx%d",
5614  ximage->width,ximage->height);
5615  (void) LogMagickEvent(X11Event,GetMagickModule()," format: %d",
5616  ximage->format);
5617  (void) LogMagickEvent(X11Event,GetMagickModule()," byte order: %d",
5618  ximage->byte_order);
5620  " bitmap unit, bit order, pad: %d %d %d",ximage->bitmap_unit,
5621  ximage->bitmap_bit_order,ximage->bitmap_pad);
5622  (void) LogMagickEvent(X11Event,GetMagickModule()," depth: %d",
5623  ximage->depth);
5624  (void) LogMagickEvent(X11Event,GetMagickModule()," bytes per line: %d",
5625  ximage->bytes_per_line);
5626  (void) LogMagickEvent(X11Event,GetMagickModule()," bits per pixel: %d",
5627  ximage->bits_per_pixel);
5629  " red, green, blue masks: 0x%lx 0x%lx 0x%lx",ximage->red_mask,
5630  ximage->green_mask,ximage->blue_mask);
5631  }
5632  if (window->shared_memory == MagickFalse)
5633  {
5634  if (ximage->format == XYBitmap)
5635  {
5636  ximage->data=(char *) AcquireQuantumMemory((size_t)
5637  ximage->bytes_per_line,(size_t) ximage->depth*ximage->height);
5638  if (ximage->data != (char *) NULL)
5639  (void) memset(ximage->data,0,(size_t)
5640  ximage->bytes_per_line*ximage->depth*ximage->height);
5641  }
5642  else
5643  {
5644  ximage->data=(char *) AcquireQuantumMemory((size_t)
5645  ximage->bytes_per_line,(size_t) ximage->height);
5646  if (ximage->data != (char *) NULL)
5647  (void) memset(ximage->data,0,(size_t)
5648  ximage->bytes_per_line*ximage->height);
5649  }
5650  }
5651  if (ximage->data == (char *) NULL)
5652  {
5653  /*
5654  Unable to allocate pixel data.
5655  */
5656  XDestroyImage(ximage);
5657  ximage=(XImage *) NULL;
5658  (void) XCheckDefineCursor(display,window->id,window->cursor);
5659  return(MagickFalse);
5660  }
5661  if (window->ximage != (XImage *) NULL)
5662  {
5663  /*
5664  Destroy previous X image.
5665  */
5666  length=(size_t) window->ximage->bytes_per_line*window->ximage->height;
5667 #if defined(MAGICKCORE_HAVE_SHARED_MEMORY)
5668  if (window->segment_info != (XShmSegmentInfo *) NULL)
5669  {
5670  XShmSegmentInfo
5671  *segment_info;
5672 
5673  segment_info=(XShmSegmentInfo *) window->segment_info;
5674  if (segment_info[0].shmid >= 0)
5675  {
5676  (void) XSync(display,MagickFalse);
5677  (void) XShmDetach(display,&segment_info[0]);
5678  (void) XSync(display,MagickFalse);
5679  if (segment_info[0].shmaddr != (char *) NULL)
5680  (void) shmdt(segment_info[0].shmaddr);
5681  (void) shmctl(segment_info[0].shmid,IPC_RMID,0);
5682  segment_info[0].shmid=(-1);
5683  segment_info[0].shmaddr=(char *) NULL;
5684  window->ximage->data=(char *) NULL;
5685  }
5686  }
5687 #endif
5688  if (window->ximage->data != (char *) NULL)
5689  free(window->ximage->data);
5690  window->ximage->data=(char *) NULL;
5691  XDestroyImage(window->ximage);
5692  window->ximage=(XImage *) NULL;
5693  }
5694 #if defined(MAGICKCORE_HAVE_SHARED_MEMORY)
5695  if (window->segment_info != (XShmSegmentInfo *) NULL)
5696  {
5697  XShmSegmentInfo
5698  *segment_info;
5699 
5700  segment_info=(XShmSegmentInfo *) window->segment_info;
5701  segment_info[0]=segment_info[1];
5702  }
5703 #endif
5704  window->ximage=ximage;
5705  matte_image=(XImage *) NULL;
5706  if ((window->shape != MagickFalse) && (window->image != (Image *) NULL))
5707  if ((window->image->alpha_trait != UndefinedPixelTrait) &&
5708  ((int) width <= XDisplayWidth(display,window->screen)) &&
5709  ((int) height <= XDisplayHeight(display,window->screen)))
5710  {
5711  /*
5712  Create matte image.
5713  */
5714  matte_image=XCreateImage(display,window->visual,1,XYBitmap,0,
5715  (char *) NULL,width,height,XBitmapPad(display),0);
5716  if (IsEventLogging())
5717  {
5718  (void) LogMagickEvent(X11Event,GetMagickModule(),"Matte Image:");
5720  " width, height: %dx%d",matte_image->width,matte_image->height);
5721  }
5722  if (matte_image != (XImage *) NULL)
5723  {
5724  /*
5725  Allocate matte image pixel data.
5726  */
5727  matte_image->data=(char *) malloc((size_t)
5728  matte_image->bytes_per_line*matte_image->depth*
5729  matte_image->height);
5730  if (matte_image->data == (char *) NULL)
5731  {
5732  XDestroyImage(matte_image);
5733  matte_image=(XImage *) NULL;
5734  }
5735  }
5736  }
5737  if (window->matte_image != (XImage *) NULL)
5738  {
5739  /*
5740  Free matte image.
5741  */
5742  if (window->matte_image->data != (char *) NULL)
5743  free(window->matte_image->data);
5744  window->matte_image->data=(char *) NULL;
5745  XDestroyImage(window->matte_image);
5746  window->matte_image=(XImage *) NULL;
5747  }
5748  window->matte_image=matte_image;
5749  if (window->matte_pixmap != (Pixmap) NULL)
5750  {
5751  (void) XFreePixmap(display,window->matte_pixmap);
5752  window->matte_pixmap=(Pixmap) NULL;
5753 #if defined(MAGICKCORE_HAVE_SHAPE)
5754  if (window->shape != MagickFalse)
5755  XShapeCombineMask(display,window->id,ShapeBounding,0,0,None,ShapeSet);
5756 #endif
5757  }
5758  window->stasis=MagickFalse;
5759  /*
5760  Convert pixels to X image data.
5761  */
5762  if (window->image != (Image *) NULL)
5763  {
5764  if ((ximage->byte_order == LSBFirst) || ((ximage->format == XYBitmap) &&
5765  (ximage->bitmap_bit_order == LSBFirst)))
5766  XMakeImageLSBFirst(resource_info,window,window->image,ximage,
5767  matte_image,exception);
5768  else
5769  XMakeImageMSBFirst(resource_info,window,window->image,ximage,
5770  matte_image,exception);
5771  }
5772  if (window->matte_image != (XImage *) NULL)
5773  {
5774  /*
5775  Create matte pixmap.
5776  */
5777  window->matte_pixmap=XCreatePixmap(display,window->id,width,height,1);
5778  if (window->matte_pixmap != (Pixmap) NULL)
5779  {
5780  GC
5781  graphics_context;
5782 
5783  XGCValues
5784  context_values;
5785 
5786  /*
5787  Copy matte image to matte pixmap.
5788  */
5789  context_values.background=0;
5790  context_values.foreground=1;
5791  graphics_context=XCreateGC(display,window->matte_pixmap,
5792  (size_t) (GCBackground | GCForeground),&context_values);
5793  (void) XPutImage(display,window->matte_pixmap,graphics_context,
5794  window->matte_image,0,0,0,0,width,height);
5795  (void) XFreeGC(display,graphics_context);
5796 #if defined(MAGICKCORE_HAVE_SHAPE)
5797  if (window->shape != MagickFalse)
5798  XShapeCombineMask(display,window->id,ShapeBounding,0,0,
5799  window->matte_pixmap,ShapeSet);
5800 #endif
5801  }
5802  }
5803  (void) XMakePixmap(display,resource_info,window);
5804  /*
5805  Restore cursor.
5806  */
5807  (void) XCheckDefineCursor(display,window->id,window->cursor);
5808  return(MagickTrue);
5809 }
5810 
5811 /*
5812 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5813 % %
5814 % %
5815 % %
5816 + X M a k e I m a g e L S B F i r s t %
5817 % %
5818 % %
5819 % %
5820 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5821 %
5822 % XMakeImageLSBFirst() initializes the pixel data of an X11 Image. The X image
5823 % pixels are copied in least-significant bit and byte first order. The
5824 % server's scanline pad is respected. Rather than using one or two general
5825 % cases, many special cases are found here to help speed up the image
5826 % conversion.
5827 %
5828 % The format of the XMakeImageLSBFirst method is:
5829 %
5830 % void XMakeImageLSBFirst(Display *display,XWindows *windows,
5831 % ExceptionInfo *exception)
5832 %
5833 % A description of each parameter follows:
5834 %
5835 % o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
5836 %
5837 % o window: Specifies a pointer to a XWindowInfo structure.
5838 %
5839 % o image: the image.
5840 %
5841 % o ximage: Specifies a pointer to a XImage structure; returned from
5842 % XCreateImage.
5843 %
5844 % o matte_image: Specifies a pointer to a XImage structure; returned from
5845 % XCreateImage.
5846 %
5847 % o exception: return any errors or warnings in this structure.
5848 %
5849 */
5850 static void XMakeImageLSBFirst(const XResourceInfo *resource_info,
5851  const XWindowInfo *window,Image *image,XImage *ximage,XImage *matte_image,
5852  ExceptionInfo *exception)
5853 {
5854  CacheView
5855  *canvas_view;
5856 
5857  Image
5858  *canvas;
5859 
5860  int
5861  y;
5862 
5863  const Quantum
5864  *p;
5865 
5866  int
5867  x;
5868 
5869  unsigned char
5870  *q;
5871 
5872  unsigned char
5873  bit,
5874  byte;
5875 
5876  unsigned int
5877  scanline_pad;
5878 
5879  unsigned long
5880  pixel,
5881  *pixels;
5882 
5883  XStandardColormap
5884  *map_info;
5885 
5886  assert(resource_info != (XResourceInfo *) NULL);
5887  assert(window != (XWindowInfo *) NULL);
5888  assert(image != (Image *) NULL);
5889  if (image->debug != MagickFalse)
5890  (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
5891  canvas=image;
5892  if ((window->immutable == MagickFalse) &&
5893  (image->storage_class == DirectClass) &&
5894  (image->alpha_trait != UndefinedPixelTrait))
5895  {
5896  char
5897  size[MagickPathExtent];
5898 
5899  Image
5900  *pattern;
5901 
5902  ImageInfo
5903  *image_info;
5904 
5905  image_info=AcquireImageInfo();
5906  (void) CopyMagickString(image_info->filename,
5907  resource_info->image_info->texture != (char *) NULL ?
5908  resource_info->image_info->texture : "pattern:checkerboard",
5910  (void) FormatLocaleString(size,MagickPathExtent,"%.20gx%.20g",(double)
5911  image->columns,(double) image->rows);
5912  image_info->size=ConstantString(size);
5913  pattern=ReadImage(image_info,exception);
5914  image_info=DestroyImageInfo(image_info);
5915  if (pattern != (Image *) NULL)
5916  {
5917  canvas=CloneImage(image,0,0,MagickTrue,exception);
5918  if (canvas != (Image *) NULL)
5919  (void) CompositeImage(canvas,pattern,DstOverCompositeOp,MagickTrue,
5920  0,0,exception);
5921  pattern=DestroyImage(pattern);
5922  }
5923  }
5924  scanline_pad=(unsigned int) (ximage->bytes_per_line-((ximage->width*
5925  ximage->bits_per_pixel) >> 3));
5926  map_info=window->map_info;
5927  pixels=window->pixel_info->pixels;
5928  q=(unsigned char *) ximage->data;
5929  x=0;
5930  canvas_view=AcquireVirtualCacheView(canvas,exception);
5931  if (ximage->format == XYBitmap)
5932  {
5933  unsigned short
5934  polarity;
5935 
5936  unsigned char
5937  background,
5938  foreground;
5939 
5940  /*
5941  Convert canvas to big-endian bitmap.
5942  */
5943  background=(unsigned char)
5944  (XPixelIntensity(&window->pixel_info->foreground_color) <
5945  XPixelIntensity(&window->pixel_info->background_color) ? 0x80 : 0x00);
5946  foreground=(unsigned char)
5947  (XPixelIntensity(&window->pixel_info->background_color) <
5948  XPixelIntensity(&window->pixel_info->foreground_color) ? 0x80 : 0x00);
5949  polarity=(unsigned short) ((GetPixelInfoIntensity(image,
5950  &canvas->colormap[0])) < (QuantumRange/2.0) ? 1 : 0);
5951  if (canvas->colors == 2)
5952  polarity=GetPixelInfoIntensity(image,&canvas->colormap[0]) <
5953  GetPixelInfoIntensity(image,&canvas->colormap[1]);
5954  for (y=0; y < (int) canvas->rows; y++)
5955  {
5956  p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,canvas->columns,1,
5957  exception);
5958  if (p == (const Quantum *) NULL)
5959  break;
5960  bit=0;
5961  byte=0;
5962  for (x=0; x < (int) canvas->columns; x++)
5963  {
5964  byte>>=1;
5965  if (GetPixelIndex(canvas,p) == (Quantum) polarity)
5966  byte|=foreground;
5967  else
5968  byte|=background;
5969  bit++;
5970  if (bit == 8)
5971  {
5972  *q++=byte;
5973  bit=0;
5974  byte=0;
5975  }
5976  p+=GetPixelChannels(canvas);
5977  }
5978  if (bit != 0)
5979  *q=byte >> (8-bit);
5980  q+=scanline_pad;
5981  }
5982  }
5983  else
5984  if (window->pixel_info->colors != 0)
5985  switch (ximage->bits_per_pixel)
5986  {
5987  case 2:
5988  {
5989  unsigned int
5990  nibble;
5991 
5992  /*
5993  Convert to 2 bit color-mapped X canvas.
5994  */
5995  for (y=0; y < (int) canvas->rows; y++)
5996  {
5997  p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
5998  canvas->columns,1,exception);
5999  if (p == (const Quantum *) NULL)
6000  break;
6001  nibble=0;
6002  for (x=0; x < (int) canvas->columns; x++)
6003  {
6004  pixel=pixels[(ssize_t) GetPixelIndex(canvas,p)] & 0x0f;
6005  switch (nibble)
6006  {
6007  case 0:
6008  {
6009  *q=(unsigned char) pixel;
6010  nibble++;
6011  break;
6012  }
6013  case 1:
6014  {
6015  *q|=(unsigned char) (pixel << 2);
6016  nibble++;
6017  break;
6018  }
6019  case 2:
6020  {
6021  *q|=(unsigned char) (pixel << 4);
6022  nibble++;
6023  break;
6024  }
6025  case 3:
6026  {
6027  *q|=(unsigned char) (pixel << 6);
6028  q++;
6029  nibble=0;
6030  break;
6031  }
6032  }
6033  p+=GetPixelChannels(canvas);
6034  }
6035  q+=scanline_pad;
6036  }
6037  break;
6038  }
6039  case 4:
6040  {
6041  unsigned int
6042  nibble;
6043 
6044  /*
6045  Convert to 4 bit color-mapped X canvas.
6046  */
6047  for (y=0; y < (int) canvas->rows; y++)
6048  {
6049  p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
6050  canvas->columns,1,exception);
6051  if (p == (const Quantum *) NULL)
6052  break;
6053  nibble=0;
6054  for (x=0; x < (int) canvas->columns; x++)
6055  {
6056  pixel=pixels[(ssize_t) GetPixelIndex(canvas,p)] & 0xf;
6057  switch (nibble)
6058  {
6059  case 0:
6060  {
6061  *q=(unsigned char) pixel;
6062  nibble++;
6063  break;
6064  }
6065  case 1:
6066  {
6067  *q|=(unsigned char) (pixel << 4);
6068  q++;
6069  nibble=0;
6070  break;
6071  }
6072  }
6073  p+=GetPixelChannels(canvas);
6074  }
6075  q+=scanline_pad;
6076  }
6077  break;
6078  }
6079  case 6:
6080  case 8:
6081  {
6082  /*
6083  Convert to 8 bit color-mapped X canvas.
6084  */
6085  if (resource_info->color_recovery &&
6086  resource_info->quantize_info->dither_method != NoDitherMethod)
6087  {
6088  XDitherImage(canvas,ximage,exception);
6089  break;
6090  }
6091  for (y=0; y < (int) canvas->rows; y++)
6092  {
6093  p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
6094  canvas->columns,1,exception);
6095  if (p == (const Quantum *) NULL)
6096  break;
6097  for (x=0; x < (int) canvas->columns; x++)
6098  {
6099  pixel=pixels[(ssize_t) GetPixelIndex(canvas,p)];
6100  *q++=(unsigned char) pixel;
6101  p+=GetPixelChannels(canvas);
6102  }
6103  q+=scanline_pad;
6104  }
6105  break;
6106  }
6107  default:
6108  {
6109  int
6110  k;
6111 
6112  unsigned int
6113  bytes_per_pixel;
6114 
6115  /*
6116  Convert to multi-byte color-mapped X canvas.
6117  */
6118  bytes_per_pixel=(unsigned int) (ximage->bits_per_pixel >> 3);
6119  for (y=0; y < (int) canvas->rows; y++)
6120  {
6121  p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
6122  canvas->columns,1,exception);
6123  if (p == (const Quantum *) NULL)
6124  break;
6125  for (x=0; x < (int) canvas->columns; x++)
6126  {
6127  pixel=pixels[(ssize_t) GetPixelIndex(canvas,p)];
6128  for (k=0; k < (int) bytes_per_pixel; k++)
6129  {
6130  *q++=(unsigned char) (pixel & 0xff);
6131  pixel>>=8;
6132  }
6133  p+=GetPixelChannels(canvas);
6134  }
6135  q+=scanline_pad;
6136  }
6137  break;
6138  }
6139  }
6140  else
6141  switch (ximage->bits_per_pixel)
6142  {
6143  case 2:
6144  {
6145  unsigned int
6146  nibble;
6147 
6148  /*
6149  Convert to contiguous 2 bit continuous-tone X canvas.
6150  */
6151  for (y=0; y < (int) canvas->rows; y++)
6152  {
6153  nibble=0;
6154  p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
6155  canvas->columns,1,exception);
6156  if (p == (const Quantum *) NULL)
6157  break;
6158  for (x=0; x < (int) canvas->columns; x++)
6159  {
6160  pixel=XGammaPixel(canvas,map_info,p);
6161  pixel&=0xf;
6162  switch (nibble)
6163  {
6164  case 0:
6165  {
6166  *q=(unsigned char) pixel;
6167  nibble++;
6168  break;
6169  }
6170  case 1:
6171  {
6172  *q|=(unsigned char) (pixel << 2);
6173  nibble++;
6174  break;
6175  }
6176  case 2:
6177  {
6178  *q|=(unsigned char) (pixel << 4);
6179  nibble++;
6180  break;
6181  }
6182  case 3:
6183  {
6184  *q|=(unsigned char) (pixel << 6);
6185  q++;
6186  nibble=0;
6187  break;
6188  }
6189  }
6190  p+=GetPixelChannels(canvas);
6191  }
6192  q+=scanline_pad;
6193  }
6194  break;
6195  }
6196  case 4:
6197  {
6198  unsigned int
6199  nibble;
6200 
6201  /*
6202  Convert to contiguous 4 bit continuous-tone X canvas.
6203  */
6204  for (y=0; y < (int) canvas->rows; y++)
6205  {
6206  p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
6207  canvas->columns,1,exception);
6208  if (p == (const Quantum *) NULL)
6209  break;
6210  nibble=0;
6211  for (x=0; x < (int) canvas->columns; x++)
6212  {
6213  pixel=XGammaPixel(canvas,map_info,p);
6214  pixel&=0xf;
6215  switch (nibble)
6216  {
6217  case 0:
6218  {
6219  *q=(unsigned char) pixel;
6220  nibble++;
6221  break;
6222  }
6223  case 1:
6224  {
6225  *q|=(unsigned char) (pixel << 4);
6226  q++;
6227  nibble=0;
6228  break;
6229  }
6230  }
6231  p+=GetPixelChannels(canvas);
6232  }
6233  q+=scanline_pad;
6234  }
6235  break;
6236  }
6237  case 6:
6238  case 8:
6239  {
6240  /*
6241  Convert to contiguous 8 bit continuous-tone X canvas.
6242  */
6243  if (resource_info->color_recovery &&
6244  resource_info->quantize_info->dither_method != NoDitherMethod)
6245  {
6246  XDitherImage(canvas,ximage,exception);
6247  break;
6248  }
6249  for (y=0; y < (int) canvas->rows; y++)
6250  {
6251  p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
6252  canvas->columns,1,exception);
6253  if (p == (const Quantum *) NULL)
6254  break;
6255  for (x=0; x < (int) canvas->columns; x++)
6256  {
6257  pixel=XGammaPixel(canvas,map_info,p);
6258  *q++=(unsigned char) pixel;
6259  p+=GetPixelChannels(canvas);
6260  }
6261  q+=scanline_pad;
6262  }
6263  break;
6264  }
6265  default:
6266  {
6267  if ((ximage->bits_per_pixel == 32) && (map_info->red_max == 255) &&
6268  (map_info->green_max == 255) && (map_info->blue_max == 255) &&
6269  (map_info->red_mult == 65536L) && (map_info->green_mult == 256) &&
6270  (map_info->blue_mult == 1))
6271  {
6272  /*
6273  Convert to 32 bit continuous-tone X canvas.
6274  */
6275  for (y=0; y < (int) canvas->rows; y++)
6276  {
6277  p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
6278  canvas->columns,1,exception);
6279  if (p == (const Quantum *) NULL)
6280  break;
6281  if ((red_gamma != 1.0) || (green_gamma != 1.0) ||
6282  (blue_gamma != 1.0))
6283  {
6284  /*
6285  Gamma correct canvas.
6286  */
6287  for (x=(int) canvas->columns-1; x >= 0; x--)
6288  {
6289  *q++=ScaleQuantumToChar(XBlueGamma(
6290  GetPixelBlue(canvas,p)));
6291  *q++=ScaleQuantumToChar(XGreenGamma(
6292  GetPixelGreen(canvas,p)));
6293  *q++=ScaleQuantumToChar(XRedGamma(
6294  GetPixelRed(canvas,p)));
6295  *q++=0;
6296  p+=GetPixelChannels(canvas);
6297  }
6298  continue;
6299  }
6300  for (x=(int) canvas->columns-1; x >= 0; x--)
6301  {
6302  *q++=ScaleQuantumToChar((Quantum) GetPixelBlue(canvas,p));
6303  *q++=ScaleQuantumToChar((Quantum) GetPixelGreen(canvas,p));
6304  *q++=ScaleQuantumToChar((Quantum) GetPixelRed(canvas,p));
6305  *q++=0;
6306  p+=GetPixelChannels(canvas);
6307  }
6308  }
6309  }
6310  else
6311  if ((ximage->bits_per_pixel == 32) && (map_info->red_max == 255) &&
6312  (map_info->green_max == 255) && (map_info->blue_max == 255) &&
6313  (map_info->red_mult == 1) && (map_info->green_mult == 256) &&
6314  (map_info->blue_mult == 65536L))
6315  {
6316  /*
6317  Convert to 32 bit continuous-tone X canvas.
6318  */
6319  for (y=0; y < (int) canvas->rows; y++)
6320  {
6321  p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
6322  canvas->columns,1,exception);
6323  if (p == (const Quantum *) NULL)
6324  break;
6325  if ((red_gamma != 1.0) || (green_gamma != 1.0) ||
6326  (blue_gamma != 1.0))
6327  {
6328  /*
6329  Gamma correct canvas.
6330  */
6331  for (x=(int) canvas->columns-1; x >= 0; x--)
6332  {
6333  *q++=ScaleQuantumToChar(XRedGamma(
6334  GetPixelRed(canvas,p)));
6335  *q++=ScaleQuantumToChar(XGreenGamma(
6336  GetPixelGreen(canvas,p)));
6337  *q++=ScaleQuantumToChar(XBlueGamma(
6338  GetPixelBlue(canvas,p)));
6339  *q++=0;
6340  p+=GetPixelChannels(canvas);
6341  }
6342  continue;
6343  }
6344  for (x=(int) canvas->columns-1; x >= 0; x--)
6345  {
6346  *q++=ScaleQuantumToChar((Quantum) GetPixelRed(canvas,p));
6347  *q++=ScaleQuantumToChar((Quantum) GetPixelGreen(canvas,p));
6348  *q++=ScaleQuantumToChar((Quantum) GetPixelBlue(canvas,p));
6349  *q++=0;
6350  p+=GetPixelChannels(canvas);
6351  }
6352  }
6353  }
6354  else
6355  {
6356  int
6357  k;
6358 
6359  unsigned int
6360  bytes_per_pixel;
6361 
6362  /*
6363  Convert to multi-byte continuous-tone X canvas.
6364  */
6365  bytes_per_pixel=(unsigned int) (ximage->bits_per_pixel >> 3);
6366  for (y=0; y < (int) canvas->rows; y++)
6367  {
6368  p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
6369  canvas->columns,1,exception);
6370  if (p == (const Quantum *) NULL)
6371  break;
6372  for (x=0; x < (int) canvas->columns; x++)
6373  {
6374  pixel=XGammaPixel(canvas,map_info,p);
6375  for (k=0; k < (int) bytes_per_pixel; k++)
6376  {
6377  *q++=(unsigned char) (pixel & 0xff);
6378  pixel>>=8;
6379  }
6380  p+=GetPixelChannels(canvas);
6381  }
6382  q+=scanline_pad;
6383  }
6384  }
6385  break;
6386  }
6387  }
6388  if (matte_image != (XImage *) NULL)
6389  {
6390  /*
6391  Initialize matte canvas.
6392  */
6393  scanline_pad=(unsigned int) (matte_image->bytes_per_line-
6394  ((matte_image->width*matte_image->bits_per_pixel) >> 3));
6395  q=(unsigned char *) matte_image->data;
6396  for (y=0; y < (int) canvas->rows; y++)
6397  {
6398  p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,canvas->columns,1,
6399  exception);
6400  if (p == (const Quantum *) NULL)
6401  break;
6402  bit=0;
6403  byte=0;
6404  for (x=(int) canvas->columns-1; x >= 0; x--)
6405  {
6406  byte>>=1;
6407  if (GetPixelAlpha(canvas,p) > (QuantumRange/2))
6408  byte|=0x80;
6409  bit++;
6410  if (bit == 8)
6411  {
6412  *q++=byte;
6413  bit=0;
6414  byte=0;
6415  }
6416  p+=GetPixelChannels(canvas);
6417  }
6418  if (bit != 0)
6419  *q=byte >> (8-bit);
6420  q+=scanline_pad;
6421  }
6422  }
6423  canvas_view=DestroyCacheView(canvas_view);
6424  if (canvas != image)
6425  canvas=DestroyImage(canvas);
6426 }
6427 
6428 /*
6429 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
6430 % %
6431 % %
6432 % %
6433 + X M a k e I m a g e M S B F i r s t %
6434 % %
6435 % %
6436 % %
6437 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
6438 %
6439 % XMakeImageMSBFirst() initializes the pixel data of an X11 Image. The X
6440 % image pixels are copied in most-significant bit and byte first order. The
6441 % server's scanline pad is also respected. Rather than using one or two
6442 % general cases, many special cases are found here to help speed up the image
6443 % conversion.
6444 %
6445 % The format of the XMakeImageMSBFirst method is:
6446 %
6447 % XMakeImageMSBFirst(resource_info,window,image,ximage,matte_image,
6448 % ExceptionInfo *exception)
6449 %
6450 % A description of each parameter follows:
6451 %
6452 % o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
6453 %
6454 % o window: Specifies a pointer to a XWindowInfo structure.
6455 %
6456 % o image: the image.
6457 %
6458 % o ximage: Specifies a pointer to a XImage structure; returned from
6459 % XCreateImage.
6460 %
6461 % o matte_image: Specifies a pointer to a XImage structure; returned from
6462 % XCreateImage.
6463 %
6464 % o exception: return any errors or warnings in this structure.
6465 %
6466 */
6467 static void XMakeImageMSBFirst(const XResourceInfo *resource_info,
6468  const XWindowInfo *window,Image *image,XImage *ximage,XImage *matte_image,
6469  ExceptionInfo *exception)
6470 {
6471  CacheView
6472  *canvas_view;
6473 
6474  Image
6475  *canvas;
6476 
6477  int
6478  y;
6479 
6480  int
6481  x;
6482 
6483  const Quantum
6484  *p;
6485 
6486  unsigned char
6487  *q;
6488 
6489  unsigned char
6490  bit,
6491  byte;
6492 
6493  unsigned int
6494  scanline_pad;
6495 
6496  unsigned long
6497  pixel,
6498  *pixels;
6499 
6500  XStandardColormap
6501  *map_info;
6502 
6503  assert(resource_info != (XResourceInfo *) NULL);
6504  assert(window != (XWindowInfo *) NULL);
6505  assert(image != (Image *) NULL);
6506  if (image->debug != MagickFalse)
6507  (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
6508  canvas=image;
6509  if ((window->immutable != MagickFalse) &&
6510  (image->storage_class == DirectClass) &&
6511  (image->alpha_trait != UndefinedPixelTrait))
6512  {
6513  char
6514  size[MagickPathExtent];
6515 
6516  Image
6517  *pattern;
6518 
6519  ImageInfo
6520  *image_info;
6521 
6522  image_info=AcquireImageInfo();
6523  (void) CopyMagickString(image_info->filename,
6524  resource_info->image_info->texture != (char *) NULL ?
6525  resource_info->image_info->texture : "pattern:checkerboard",
6527  (void) FormatLocaleString(size,MagickPathExtent,"%.20gx%.20g",(double)
6528  image->columns,(double) image->rows);
6529  image_info->size=ConstantString(size);
6530  pattern=ReadImage(image_info,exception);
6531  image_info=DestroyImageInfo(image_info);
6532  if (pattern != (Image *) NULL)
6533  {
6534  canvas=CloneImage(image,0,0,MagickTrue,exception);
6535  if (canvas != (Image *) NULL)
6536  (void) CompositeImage(canvas,pattern,DstOverCompositeOp,MagickFalse,
6537  0,0,exception);
6538  pattern=DestroyImage(pattern);
6539  }
6540  }
6541  scanline_pad=(unsigned int) (ximage->bytes_per_line-((ximage->width*
6542  ximage->