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