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