MagickCore  7.0.10
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-2020 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  register ssize_t
3036  i;
3037 
3038  Status
3039  status;
3040 
3041  unsigned int
3042  packets;
3043 
3044  /*
3045  Initialize pixel info.
3046  */
3047  (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
3048  assert(display != (Display *) NULL);
3049  assert(visual_info != (XVisualInfo *) NULL);
3050  assert(map_info != (XStandardColormap *) NULL);
3051  assert(resource_info != (XResourceInfo *) NULL);
3052  assert(pixel != (XPixelInfo *) NULL);
3053  pixel->colors=0;
3054  if (image != (Image *) NULL)
3055  if (image->storage_class == PseudoClass)
3056  pixel->colors=(ssize_t) image->colors;
3057  packets=(unsigned int)
3058  MagickMax((int) pixel->colors,visual_info->colormap_size)+MaxNumberPens;
3059  if (pixel->pixels != (unsigned long *) NULL)
3060  pixel->pixels=(unsigned long *) RelinquishMagickMemory(pixel->pixels);
3061  pixel->pixels=(unsigned long *) AcquireQuantumMemory(packets,
3062  sizeof(*pixel->pixels));
3063  if (pixel->pixels == (unsigned long *) NULL)
3064  ThrowXWindowFatalException(ResourceLimitFatalError,"UnableToGetPixelInfo",
3065  image->filename);
3066  /*
3067  Set foreground color.
3068  */
3069  colormap=map_info->colormap;
3070  (void) XParseColor(display,colormap,(char *) ForegroundColor,
3071  &pixel->foreground_color);
3072  status=XParseColor(display,colormap,resource_info->foreground_color,
3073  &pixel->foreground_color);
3074  if (status == False)
3075  ThrowXWindowException(XServerError,"ColorIsNotKnownToServer",
3076  resource_info->foreground_color);
3077  pixel->foreground_color.pixel=
3078  XStandardPixel(map_info,&pixel->foreground_color);
3079  pixel->foreground_color.flags=(char) (DoRed | DoGreen | DoBlue);
3080  /*
3081  Set background color.
3082  */
3083  (void) XParseColor(display,colormap,"#d6d6d6d6d6d6",&pixel->background_color);
3084  status=XParseColor(display,colormap,resource_info->background_color,
3085  &pixel->background_color);
3086  if (status == False)
3087  ThrowXWindowException(XServerError,"ColorIsNotKnownToServer",
3088  resource_info->background_color);
3089  pixel->background_color.pixel=
3090  XStandardPixel(map_info,&pixel->background_color);
3091  pixel->background_color.flags=(char) (DoRed | DoGreen | DoBlue);
3092  /*
3093  Set border color.
3094  */
3095  (void) XParseColor(display,colormap,(char *) BorderColor,
3096  &pixel->border_color);
3097  status=XParseColor(display,colormap,resource_info->border_color,
3098  &pixel->border_color);
3099  if (status == False)
3100  ThrowXWindowException(XServerError,"ColorIsNotKnownToServer",
3101  resource_info->border_color);
3102  pixel->border_color.pixel=XStandardPixel(map_info,&pixel->border_color);
3103  pixel->border_color.flags=(char) (DoRed | DoGreen | DoBlue);
3104  /*
3105  Set matte color.
3106  */
3107  pixel->matte_color=pixel->background_color;
3108  if (resource_info->matte_color != (char *) NULL)
3109  {
3110  /*
3111  Matte color is specified as a X resource or command line argument.
3112  */
3113  status=XParseColor(display,colormap,resource_info->matte_color,
3114  &pixel->matte_color);
3115  if (status == False)
3116  ThrowXWindowException(XServerError,"ColorIsNotKnownToServer",
3117  resource_info->matte_color);
3118  pixel->matte_color.pixel=XStandardPixel(map_info,&pixel->matte_color);
3119  pixel->matte_color.flags=(char) (DoRed | DoGreen | DoBlue);
3120  }
3121  /*
3122  Set highlight color.
3123  */
3124  pixel->highlight_color.red=(unsigned short) (((double)
3125  pixel->matte_color.red*ScaleQuantumToShort(HighlightModulate))/65535L+
3126  (ScaleQuantumToShort((Quantum) (QuantumRange-HighlightModulate))));
3127  pixel->highlight_color.green=(unsigned short) (((double)
3128  pixel->matte_color.green*ScaleQuantumToShort(HighlightModulate))/65535L+
3129  (ScaleQuantumToShort((Quantum) (QuantumRange-HighlightModulate))));
3130  pixel->highlight_color.blue=(unsigned short) (((double)
3131  pixel->matte_color.blue*ScaleQuantumToShort(HighlightModulate))/65535L+
3132  (ScaleQuantumToShort((Quantum) (QuantumRange-HighlightModulate))));
3133  pixel->highlight_color.pixel=XStandardPixel(map_info,&pixel->highlight_color);
3134  pixel->highlight_color.flags=(char) (DoRed | DoGreen | DoBlue);
3135  /*
3136  Set shadow color.
3137  */
3138  pixel->shadow_color.red=(unsigned short) (((double)
3139  pixel->matte_color.red*ScaleQuantumToShort(ShadowModulate))/65535L);
3140  pixel->shadow_color.green=(unsigned short) (((double)
3141  pixel->matte_color.green*ScaleQuantumToShort(ShadowModulate))/65535L);
3142  pixel->shadow_color.blue=(unsigned short) (((double)
3143  pixel->matte_color.blue*ScaleQuantumToShort(ShadowModulate))/65535L);
3144  pixel->shadow_color.pixel=XStandardPixel(map_info,&pixel->shadow_color);
3145  pixel->shadow_color.flags=(char) (DoRed | DoGreen | DoBlue);
3146  /*
3147  Set depth color.
3148  */
3149  pixel->depth_color.red=(unsigned short) (((double)
3150  pixel->matte_color.red*ScaleQuantumToShort(DepthModulate))/65535L);
3151  pixel->depth_color.green=(unsigned short) (((double)
3152  pixel->matte_color.green*ScaleQuantumToShort(DepthModulate))/65535L);
3153  pixel->depth_color.blue=(unsigned short) (((double)
3154  pixel->matte_color.blue*ScaleQuantumToShort(DepthModulate))/65535L);
3155  pixel->depth_color.pixel=XStandardPixel(map_info,&pixel->depth_color);
3156  pixel->depth_color.flags=(char) (DoRed | DoGreen | DoBlue);
3157  /*
3158  Set trough color.
3159  */
3160  pixel->trough_color.red=(unsigned short) (((double)
3161  pixel->matte_color.red*ScaleQuantumToShort(TroughModulate))/65535L);
3162  pixel->trough_color.green=(unsigned short) (((double)
3163  pixel->matte_color.green*ScaleQuantumToShort(TroughModulate))/65535L);
3164  pixel->trough_color.blue=(unsigned short) (((double)
3165  pixel->matte_color.blue*ScaleQuantumToShort(TroughModulate))/65535L);
3166  pixel->trough_color.pixel=XStandardPixel(map_info,&pixel->trough_color);
3167  pixel->trough_color.flags=(char) (DoRed | DoGreen | DoBlue);
3168  /*
3169  Set pen color.
3170  */
3171  for (i=0; i < MaxNumberPens; i++)
3172  {
3173  (void) XParseColor(display,colormap,(char *) PenColors[i],
3174  &pixel->pen_colors[i]);
3175  status=XParseColor(display,colormap,resource_info->pen_colors[i],
3176  &pixel->pen_colors[i]);
3177  if (status == False)
3178  ThrowXWindowException(XServerError,"ColorIsNotKnownToServer",
3179  resource_info->pen_colors[i]);
3180  pixel->pen_colors[i].pixel=XStandardPixel(map_info,&pixel->pen_colors[i]);
3181  pixel->pen_colors[i].flags=(char) (DoRed | DoGreen | DoBlue);
3182  }
3183  pixel->box_color=pixel->background_color;
3184  pixel->pen_color=pixel->foreground_color;
3185  pixel->box_index=0;
3186  pixel->pen_index=1;
3187  if (image != (Image *) NULL)
3188  {
3189  if ((resource_info->gamma_correct != MagickFalse) &&
3190  (image->gamma != 0.0))
3191  {
3192  GeometryInfo
3193  geometry_info;
3194 
3196  flags;
3197 
3198  /*
3199  Initialize map relative to display and image gamma.
3200  */
3201  flags=ParseGeometry(resource_info->display_gamma,&geometry_info);
3202  red_gamma=geometry_info.rho;
3203  green_gamma=geometry_info.sigma;
3204  if ((flags & SigmaValue) == 0)
3205  green_gamma=red_gamma;
3206  blue_gamma=geometry_info.xi;
3207  if ((flags & XiValue) == 0)
3208  blue_gamma=red_gamma;
3209  red_gamma*=image->gamma;
3210  green_gamma*=image->gamma;
3211  blue_gamma*=image->gamma;
3212  }
3213  if (image->storage_class == PseudoClass)
3214  {
3215  /*
3216  Initialize pixel array for images of type PseudoClass.
3217  */
3218  for (i=0; i < (ssize_t) image->colors; i++)
3219  pixel->pixels[i]=XGammaPacket(map_info,image->colormap+i);
3220  for (i=0; i < MaxNumberPens; i++)
3221  pixel->pixels[image->colors+i]=pixel->pen_colors[i].pixel;
3222  pixel->colors+=MaxNumberPens;
3223  }
3224  }
3225 }
3226 
3227 /*
3228 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3229 % %
3230 % %
3231 % %
3232 % X G e t R e s o u r c e C l a s s %
3233 % %
3234 % %
3235 % %
3236 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3237 %
3238 % XGetResourceClass() queries the X server for the specified resource name or
3239 % class. If the resource name or class is not defined in the database, the
3240 % supplied default value is returned.
3241 %
3242 % The format of the XGetResourceClass method is:
3243 %
3244 % char *XGetResourceClass(XrmDatabase database,const char *client_name,
3245 % const char *keyword,char *resource_default)
3246 %
3247 % A description of each parameter follows:
3248 %
3249 % o database: Specifies a resource database; returned from
3250 % XrmGetStringDatabase.
3251 %
3252 % o client_name: Specifies the application name used to retrieve resource
3253 % info from the X server database.
3254 %
3255 % o keyword: Specifies the keyword of the value being retrieved.
3256 %
3257 % o resource_default: Specifies the default value to return if the query
3258 % fails to find the specified keyword/class.
3259 %
3260 */
3261 MagickExport char *XGetResourceClass(XrmDatabase database,
3262  const char *client_name,const char *keyword,char *resource_default)
3263 {
3264  char
3265  resource_class[MagickPathExtent],
3266  resource_name[MagickPathExtent];
3267 
3268  static char
3269  *resource_type;
3270 
3271  Status
3272  status;
3273 
3274  XrmValue
3275  resource_value;
3276 
3277  if (database == (XrmDatabase) NULL)
3278  return(resource_default);
3279  *resource_name='\0';
3280  *resource_class='\0';
3281  if (keyword != (char *) NULL)
3282  {
3283  int
3284  c,
3285  k;
3286 
3287  /*
3288  Initialize resource keyword and class.
3289  */
3290  (void) FormatLocaleString(resource_name,MagickPathExtent,"%s.%s",
3291  client_name,keyword);
3292  c=(int) (*client_name);
3293  if ((c >= XK_a) && (c <= XK_z))
3294  c-=(XK_a-XK_A);
3295  else
3296  if ((c >= XK_agrave) && (c <= XK_odiaeresis))
3297  c-=(XK_agrave-XK_Agrave);
3298  else
3299  if ((c >= XK_oslash) && (c <= XK_thorn))
3300  c-=(XK_oslash-XK_Ooblique);
3301  k=(int) (*keyword);
3302  if ((k >= XK_a) && (k <= XK_z))
3303  k-=(XK_a-XK_A);
3304  else
3305  if ((k >= XK_agrave) && (k <= XK_odiaeresis))
3306  k-=(XK_agrave-XK_Agrave);
3307  else
3308  if ((k >= XK_oslash) && (k <= XK_thorn))
3309  k-=(XK_oslash-XK_Ooblique);
3310  (void) FormatLocaleString(resource_class,MagickPathExtent,"%c%s.%c%s",c,
3311  client_name+1,k,keyword+1);
3312  }
3313  status=XrmGetResource(database,resource_name,resource_class,&resource_type,
3314  &resource_value);
3315  if (status == False)
3316  return(resource_default);
3317  return(resource_value.addr);
3318 }
3319 
3320 /*
3321 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3322 % %
3323 % %
3324 % %
3325 % X G e t R e s o u r c e D a t a b a s e %
3326 % %
3327 % %
3328 % %
3329 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3330 %
3331 % XGetResourceDatabase() creates a new resource database and initializes it.
3332 %
3333 % The format of the XGetResourceDatabase method is:
3334 %
3335 % XrmDatabase XGetResourceDatabase(Display *display,
3336 % const char *client_name)
3337 %
3338 % A description of each parameter follows:
3339 %
3340 % o database: XGetResourceDatabase() returns the database after it is
3341 % initialized.
3342 %
3343 % o display: Specifies a connection to an X server; returned from
3344 % XOpenDisplay.
3345 %
3346 % o client_name: Specifies the application name used to retrieve resource
3347 % info from the X server database.
3348 %
3349 */
3350 MagickExport XrmDatabase XGetResourceDatabase(Display *display,
3351  const char *client_name)
3352 {
3353  char
3354  filename[MagickPathExtent];
3355 
3356  int
3357  c;
3358 
3359  register const char
3360  *p;
3361 
3362  XrmDatabase
3363  resource_database,
3364  server_database;
3365 
3366  if (display == (Display *) NULL)
3367  return((XrmDatabase) NULL);
3368  assert(client_name != (char *) NULL);
3369  /*
3370  Initialize resource database.
3371  */
3372  XrmInitialize();
3373  (void) XGetDefault(display,(char *) client_name,"dummy");
3374  resource_database=XrmGetDatabase(display);
3375  /*
3376  Combine application database.
3377  */
3378  p=client_name+(strlen(client_name)-1);
3379  while ((p > client_name) && (*p != '/'))
3380  p--;
3381  if (*p == '/')
3382  client_name=p+1;
3383  c=(int) (*client_name);
3384  if ((c >= XK_a) && (c <= XK_z))
3385  c-=(XK_a-XK_A);
3386  else
3387  if ((c >= XK_agrave) && (c <= XK_odiaeresis))
3388  c-=(XK_agrave-XK_Agrave);
3389  else
3390  if ((c >= XK_oslash) && (c <= XK_thorn))
3391  c-=(XK_oslash-XK_Ooblique);
3392 #if defined(X11_APPLICATION_PATH)
3393  (void) FormatLocaleString(filename,MagickPathExtent,"%s%c%s",
3394  X11_APPLICATION_PATH,c,client_name+1);
3395  (void) XrmCombineFileDatabase(filename,&resource_database,MagickFalse);
3396 #endif
3397  if (XResourceManagerString(display) != (char *) NULL)
3398  {
3399  /*
3400  Combine server database.
3401  */
3402  server_database=XrmGetStringDatabase(XResourceManagerString(display));
3403  XrmCombineDatabase(server_database,&resource_database,MagickFalse);
3404  }
3405  /*
3406  Merge user preferences database.
3407  */
3408 #if defined(X11_PREFERENCES_PATH)
3409  (void) FormatLocaleString(filename,MagickPathExtent,"%s%src",
3410  X11_PREFERENCES_PATH,client_name);
3411  ExpandFilename(filename);
3412  (void) XrmCombineFileDatabase(filename,&resource_database,MagickFalse);
3413 #endif
3414  return(resource_database);
3415 }
3416 
3417 /*
3418 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3419 % %
3420 % %
3421 % %
3422 % X G e t R e s o u r c e I n f o %
3423 % %
3424 % %
3425 % %
3426 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3427 %
3428 % XGetResourceInfo(image_info,) initializes the ResourceInfo structure.
3429 %
3430 % The format of the XGetResourceInfo method is:
3431 %
3432 % void XGetResourceInfo(const ImageInfo *image_info,XrmDatabase database,
3433 % const char *client_name,XResourceInfo *resource_info)
3434 %
3435 % A description of each parameter follows:
3436 %
3437 % o image_info: the image info.
3438 %
3439 % o database: Specifies a resource database; returned from
3440 % XrmGetStringDatabase.
3441 %
3442 % o client_name: Specifies the application name used to retrieve
3443 % resource info from the X server database.
3444 %
3445 % o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
3446 %
3447 */
3448 MagickExport void XGetResourceInfo(const ImageInfo *image_info,
3449  XrmDatabase database,const char *client_name,XResourceInfo *resource_info)
3450 {
3451  char
3452  *directory,
3453  *resource_value;
3454 
3455  /*
3456  Initialize resource info fields.
3457  */
3458  (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
3459  assert(resource_info != (XResourceInfo *) NULL);
3460  (void) memset(resource_info,0,sizeof(*resource_info));
3461  resource_info->resource_database=database;
3462  resource_info->image_info=(ImageInfo *) image_info;
3463  (void) SetImageInfoProgressMonitor(resource_info->image_info,
3464  XMagickProgressMonitor,(void *) NULL);
3465  resource_info->quantize_info=CloneQuantizeInfo((QuantizeInfo *) NULL);
3466  resource_info->close_server=MagickTrue;
3467  resource_info->client_name=AcquireString(client_name);
3468  resource_value=XGetResourceClass(database,client_name,"backdrop",
3469  (char *) "False");
3470  resource_info->backdrop=IsStringTrue(resource_value);
3471  resource_info->background_color=XGetResourceInstance(database,client_name,
3472  "background",(char *) "#d6d6d6d6d6d6");
3473  resource_info->border_color=XGetResourceInstance(database,client_name,
3474  "borderColor",BorderColor);
3475  resource_value=XGetResourceClass(database,client_name,"borderWidth",
3476  (char *) "2");
3477  resource_info->border_width=(unsigned int) StringToUnsignedLong(
3478  resource_value);
3479  resource_value=XGetResourceClass(database,client_name,"colormap",
3480  (char *) "shared");
3481  resource_info->colormap=UndefinedColormap;
3482  if (LocaleCompare("private",resource_value) == 0)
3483  resource_info->colormap=PrivateColormap;
3484  if (LocaleCompare("shared",resource_value) == 0)
3485  resource_info->colormap=SharedColormap;
3486  if (resource_info->colormap == UndefinedColormap)
3487  ThrowXWindowException(OptionError,"UnrecognizedColormapType",
3488  resource_value);
3489  resource_value=XGetResourceClass(database,client_name,
3490  "colorRecovery",(char *) "False");
3491  resource_info->color_recovery=IsStringTrue(resource_value);
3492  resource_value=XGetResourceClass(database,client_name,"confirmExit",
3493  (char *) "False");
3494  resource_info->confirm_exit=IsStringTrue(resource_value);
3495  resource_value=XGetResourceClass(database,client_name,"confirmEdit",
3496  (char *) "False");
3497  resource_info->confirm_edit=IsStringTrue(resource_value);
3498  resource_value=XGetResourceClass(database,client_name,"delay",(char *) "1");
3499  resource_info->delay=(unsigned int) StringToUnsignedLong(resource_value);
3500  resource_info->display_gamma=XGetResourceClass(database,client_name,
3501  "displayGamma",(char *) "2.2");
3502  resource_value=XGetResourceClass(database,client_name,"displayWarnings",
3503  (char *) "True");
3504  resource_info->display_warnings=IsStringTrue(resource_value);
3505  resource_info->font=XGetResourceClass(database,client_name,"font",
3506  (char *) NULL);
3507  resource_info->font=XGetResourceClass(database,client_name,"fontList",
3508  resource_info->font);
3509  resource_info->font_name[0]=XGetResourceClass(database,client_name,"font1",
3510  (char *) "fixed");
3511  resource_info->font_name[1]=XGetResourceClass(database,client_name,"font2",
3512  (char *) "variable");
3513  resource_info->font_name[2]=XGetResourceClass(database,client_name,"font3",
3514  (char *) "5x8");
3515  resource_info->font_name[3]=XGetResourceClass(database,client_name,"font4",
3516  (char *) "6x10");
3517  resource_info->font_name[4]=XGetResourceClass(database,client_name,"font5",
3518  (char *) "7x13bold");
3519  resource_info->font_name[5]=XGetResourceClass(database,client_name,"font6",
3520  (char *) "8x13bold");
3521  resource_info->font_name[6]=XGetResourceClass(database,client_name,"font7",
3522  (char *) "9x15bold");
3523  resource_info->font_name[7]=XGetResourceClass(database,client_name,"font8",
3524  (char *) "10x20");
3525  resource_info->font_name[8]=XGetResourceClass(database,client_name,"font9",
3526  (char *) "12x24");
3527  resource_info->font_name[9]=XGetResourceClass(database,client_name,"font0",
3528  (char *) "fixed");
3529  resource_info->font_name[10]=XGetResourceClass(database,client_name,"font0",
3530  (char *) "fixed");
3531  resource_info->foreground_color=XGetResourceInstance(database,client_name,
3532  "foreground",ForegroundColor);
3533  resource_value=XGetResourceClass(database,client_name,"gammaCorrect",
3534  (char *) "False");
3535  resource_info->gamma_correct=IsStringTrue(resource_value);
3536  resource_info->image_geometry=ConstantString(XGetResourceClass(database,
3537  client_name,"geometry",(char *) NULL));
3538  resource_value=XGetResourceClass(database,client_name,"gravity",
3539  (char *) "Center");
3540  resource_info->gravity=(GravityType) ParseCommandOption(MagickGravityOptions,
3541  MagickFalse,resource_value);
3542  directory=getcwd(resource_info->home_directory,MagickPathExtent);
3543  (void) directory;
3544  resource_info->icon_geometry=XGetResourceClass(database,client_name,
3545  "iconGeometry",(char *) NULL);
3546  resource_value=XGetResourceClass(database,client_name,"iconic",
3547  (char *) "False");
3548  resource_info->iconic=IsStringTrue(resource_value);
3549  resource_value=XGetResourceClass(database,client_name,"immutable",
3550  LocaleCompare(client_name,"PerlMagick") == 0 ? (char *) "True" :
3551  (char *) "False");
3552  resource_info->immutable=IsStringTrue(resource_value);
3553  resource_value=XGetResourceClass(database,client_name,"magnify",
3554  (char *) "3");
3555  resource_info->magnify=(unsigned int) StringToUnsignedLong(resource_value);
3556  resource_info->map_type=XGetResourceClass(database,client_name,"map",
3557  (char *) NULL);
3558  resource_info->matte_color=XGetResourceInstance(database,client_name,
3559  "mattecolor",(char *) NULL);
3560  resource_info->name=ConstantString(XGetResourceClass(database,client_name,
3561  "name",(char *) NULL));
3562  resource_info->pen_colors[0]=XGetResourceClass(database,client_name,"pen1",
3563  (char *) "black");
3564  resource_info->pen_colors[1]=XGetResourceClass(database,client_name,"pen2",
3565  (char *) "blue");
3566  resource_info->pen_colors[2]=XGetResourceClass(database,client_name,"pen3",
3567  (char *) "cyan");
3568  resource_info->pen_colors[3]=XGetResourceClass(database,client_name,"pen4",
3569  (char *) "green");
3570  resource_info->pen_colors[4]=XGetResourceClass(database,client_name,"pen5",
3571  (char *) "gray");
3572  resource_info->pen_colors[5]=XGetResourceClass(database,client_name,"pen6",
3573  (char *) "red");
3574  resource_info->pen_colors[6]=XGetResourceClass(database,client_name,"pen7",
3575  (char *) "magenta");
3576  resource_info->pen_colors[7]=XGetResourceClass(database,client_name,"pen8",
3577  (char *) "yellow");
3578  resource_info->pen_colors[8]=XGetResourceClass(database,client_name,"pen9",
3579  (char *) "white");
3580  resource_info->pen_colors[9]=XGetResourceClass(database,client_name,"pen0",
3581  (char *) "gray");
3582  resource_info->pen_colors[10]=XGetResourceClass(database,client_name,"pen0",
3583  (char *) "gray");
3584  resource_value=XGetResourceClass(database,client_name,"pause",(char *) "0");
3585  resource_info->pause=(unsigned int) StringToUnsignedLong(resource_value);
3586  resource_value=XGetResourceClass(database,client_name,"quantum",(char *) "1");
3587  resource_info->quantum=StringToLong(resource_value);
3588  resource_info->text_font=XGetResourceClass(database,client_name,(char *)
3589  "font",(char *) "fixed");
3590  resource_info->text_font=XGetResourceClass(database,client_name,
3591  "textFontList",resource_info->text_font);
3592  resource_info->title=XGetResourceClass(database,client_name,"title",
3593  (char *) NULL);
3594  resource_value=XGetResourceClass(database,client_name,"undoCache",
3595  (char *) "256");
3596  resource_info->undo_cache=(unsigned int) StringToUnsignedLong(resource_value);
3597  resource_value=XGetResourceClass(database,client_name,"update",
3598  (char *) "False");
3599  resource_info->update=IsStringTrue(resource_value);
3600  resource_value=XGetResourceClass(database,client_name,"usePixmap",
3601  (char *) "True");
3602  resource_info->use_pixmap=IsStringTrue(resource_value);
3603  resource_value=XGetResourceClass(database,client_name,"sharedMemory",
3604  (char *) "True");
3605  resource_info->use_shared_memory=IsStringTrue(resource_value);
3606  resource_info->visual_type=XGetResourceClass(database,client_name,"visual",
3607  (char *) NULL);
3608  resource_info->window_group=XGetResourceClass(database,client_name,
3609  "windowGroup",(char *) NULL);
3610  resource_info->window_id=XGetResourceClass(database,client_name,"window",
3611  (char *) NULL);
3612  resource_info->write_filename=XGetResourceClass(database,client_name,
3613  "writeFilename",(char *) NULL);
3614 }
3615 
3616 /*
3617 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3618 % %
3619 % %
3620 % %
3621 % X G e t R e s o u r c e I n s t a n c e %
3622 % %
3623 % %
3624 % %
3625 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3626 %
3627 % XGetResourceInstance() queries the X server for the specified resource name.
3628 % If the resource name is not defined in the database, the supplied default
3629 % value is returned.
3630 %
3631 % The format of the XGetResourceInstance method is:
3632 %
3633 % char *XGetResourceInstance(XrmDatabase database,const char *client_name,
3634 % const char *keyword,const char *resource_default)
3635 %
3636 % A description of each parameter follows:
3637 %
3638 % o database: Specifies a resource database; returned from
3639 % XrmGetStringDatabase.
3640 %
3641 % o client_name: Specifies the application name used to retrieve
3642 % resource info from the X server database.
3643 %
3644 % o keyword: Specifies the keyword of the value being retrieved.
3645 %
3646 % o resource_default: Specifies the default value to return if the query
3647 % fails to find the specified keyword/class.
3648 %
3649 */
3650 MagickExport char *XGetResourceInstance(XrmDatabase database,
3651  const char *client_name,const char *keyword,const char *resource_default)
3652 {
3653  char
3654  *resource_type,
3655  resource_name[MagickPathExtent];
3656 
3657  Status
3658  status;
3659 
3660  XrmValue
3661  resource_value;
3662 
3663  if (database == (XrmDatabase) NULL)
3664  return((char *) resource_default);
3665  *resource_name='\0';
3666  if (keyword != (char *) NULL)
3667  (void) FormatLocaleString(resource_name,MagickPathExtent,"%s.%s",client_name,
3668  keyword);
3669  status=XrmGetResource(database,resource_name,"ImageMagick",&resource_type,
3670  &resource_value);
3671  if (status == False)
3672  return((char *) resource_default);
3673  return(resource_value.addr);
3674 }
3675 
3676 /*
3677 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3678 % %
3679 % %
3680 % %
3681 % X G e t S c r e e n D e n s i t y %
3682 % %
3683 % %
3684 % %
3685 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3686 %
3687 % XGetScreenDensity() returns the density of the X server screen in
3688 % dots-per-inch.
3689 %
3690 % The format of the XGetScreenDensity method is:
3691 %
3692 % char *XGetScreenDensity(Display *display)
3693 %
3694 % A description of each parameter follows:
3695 %
3696 % o density: XGetScreenDensity() returns the density of the X screen in
3697 % dots-per-inch.
3698 %
3699 % o display: Specifies a connection to an X server; returned from
3700 % XOpenDisplay.
3701 %
3702 */
3703 MagickExport char *XGetScreenDensity(Display *display)
3704 {
3705  char
3706  density[MagickPathExtent];
3707 
3708  double
3709  x_density,
3710  y_density;
3711 
3712  /*
3713  Set density as determined by screen size.
3714  */
3715  x_density=((((double) DisplayWidth(display,XDefaultScreen(display)))*25.4)/
3716  ((double) DisplayWidthMM(display,XDefaultScreen(display))));
3717  y_density=((((double) DisplayHeight(display,XDefaultScreen(display)))*25.4)/
3718  ((double) DisplayHeightMM(display,XDefaultScreen(display))));
3719  (void) FormatLocaleString(density,MagickPathExtent,"%gx%g",x_density,
3720  y_density);
3721  return(GetPageGeometry(density));
3722 }
3723 
3724 /*
3725 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3726 % %
3727 % %
3728 % %
3729 + X G e t S u b w i n d o w %
3730 % %
3731 % %
3732 % %
3733 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3734 %
3735 % XGetSubwindow() returns the subwindow of a window chosen the user with the
3736 % pointer and a button press.
3737 %
3738 % The format of the XGetSubwindow method is:
3739 %
3740 % Window XGetSubwindow(Display *display,Window window,int x,int y)
3741 %
3742 % A description of each parameter follows:
3743 %
3744 % o subwindow: XGetSubwindow() returns NULL if no subwindow is found
3745 % otherwise the subwindow is returned.
3746 %
3747 % o display: Specifies a connection to an X server; returned from
3748 % XOpenDisplay.
3749 %
3750 % o window: Specifies a pointer to a Window.
3751 %
3752 % o x: the x coordinate of the pointer relative to the origin of the
3753 % window.
3754 %
3755 % o y: the y coordinate of the pointer relative to the origin of the
3756 % window.
3757 %
3758 */
3759 static Window XGetSubwindow(Display *display,Window window,int x,int y)
3760 {
3761  int
3762  x_offset,
3763  y_offset;
3764 
3765  Status
3766  status;
3767 
3768  Window
3769  source_window,
3770  target_window;
3771 
3772  assert(display != (Display *) NULL);
3773  source_window=XRootWindow(display,XDefaultScreen(display));
3774  if (window == (Window) NULL)
3775  return(source_window);
3776  target_window=window;
3777  for ( ; ; )
3778  {
3779  status=XTranslateCoordinates(display,source_window,window,x,y,
3780  &x_offset,&y_offset,&target_window);
3781  if (status != True)
3782  break;
3783  if (target_window == (Window) NULL)
3784  break;
3785  source_window=window;
3786  window=target_window;
3787  x=x_offset;
3788  y=y_offset;
3789  }
3790  if (target_window == (Window) NULL)
3791  target_window=window;
3792  return(target_window);
3793 }
3794 
3795 /*
3796 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3797 % %
3798 % %
3799 % %
3800 % X G e t W i n d o w C o l o r %
3801 % %
3802 % %
3803 % %
3804 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3805 %
3806 % XGetWindowColor() returns the color of a pixel interactively chosen from the
3807 % X server.
3808 %
3809 % The format of the XGetWindowColor method is:
3810 %
3811 % MagickBooleanType XGetWindowColor(Display *display,XWindows *windows,
3812 % char *name,ExceptionInfo *exception)
3813 %
3814 % A description of each parameter follows:
3815 %
3816 % o display: Specifies a connection to an X server; returned from
3817 % XOpenDisplay.
3818 %
3819 % o windows: Specifies a pointer to a XWindows structure.
3820 %
3821 % o name: the name of the color if found in the X Color Database is
3822 % returned in this character string.
3823 %
3824 % o exception: return any errors or warnings in this structure.
3825 %
3826 */
3827 MagickPrivate MagickBooleanType XGetWindowColor(Display *display,
3828  XWindows *windows,char *name,ExceptionInfo *exception)
3829 {
3830  int
3831  x,
3832  y;
3833 
3834  PixelInfo
3835  pixel;
3836 
3838  crop_info;
3839 
3840  Status
3841  status;
3842 
3843  Window
3844  child,
3845  client_window,
3846  root_window,
3847  target_window;
3848 
3849  XColor
3850  color;
3851 
3852  XImage
3853  *ximage;
3854 
3855  XWindowAttributes
3856  window_attributes;
3857 
3858  /*
3859  Choose a pixel from the X server.
3860  */
3861  assert(display != (Display *) NULL);
3862  assert(name != (char *) NULL);
3863  (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",name);
3864  *name='\0';
3865  target_window=XSelectWindow(display,&crop_info);
3866  if (target_window == (Window) NULL)
3867  return(MagickFalse);
3868  root_window=XRootWindow(display,XDefaultScreen(display));
3869  client_window=target_window;
3870  if (target_window != root_window)
3871  {
3872  unsigned int
3873  d;
3874 
3875  /*
3876  Get client window.
3877  */
3878  status=XGetGeometry(display,target_window,&root_window,&x,&x,&d,&d,&d,&d);
3879  if (status != False)
3880  {
3881  client_window=XClientWindow(display,target_window);
3882  target_window=client_window;
3883  }
3884  }
3885  /*
3886  Verify window is viewable.
3887  */
3888  status=XGetWindowAttributes(display,target_window,&window_attributes);
3889  if ((status == False) || (window_attributes.map_state != IsViewable))
3890  return(MagickFalse);
3891  /*
3892  Get window X image.
3893  */
3894  (void) XTranslateCoordinates(display,root_window,target_window,
3895  (int) crop_info.x,(int) crop_info.y,&x,&y,&child);
3896  ximage=XGetImage(display,target_window,x,y,1,1,AllPlanes,ZPixmap);
3897  if (ximage == (XImage *) NULL)
3898  return(MagickFalse);
3899  color.pixel=XGetPixel(ximage,0,0);
3900  XDestroyImage(ximage);
3901  /*
3902  Match color against the color database.
3903  */
3904  (void) XQueryColor(display,window_attributes.colormap,&color);
3905  pixel.red=(double) ScaleShortToQuantum(color.red);
3906  pixel.green=(double) ScaleShortToQuantum(color.green);
3907  pixel.blue=(double) ScaleShortToQuantum(color.blue);
3909  (void) QueryColorname(windows->image.image,&pixel,X11Compliance,name,
3910  exception);
3911  return(MagickTrue);
3912 }
3913 
3914 /*
3915 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3916 % %
3917 % %
3918 % %
3919 + X G e t W i n d o w I m a g e %
3920 % %
3921 % %
3922 % %
3923 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3924 %
3925 % XGetWindowImage() reads an image from the target X window and returns it.
3926 % XGetWindowImage() optionally descends the window hierarchy and overlays the
3927 % target image with each child image in an optimized fashion. Any child
3928 % window that have the same visual, colormap, and are contained by its parent
3929 % are exempted.
3930 %
3931 % The format of the XGetWindowImage method is:
3932 %
3933 % Image *XGetWindowImage(Display *display,const Window window,
3934 % const unsigned int borders,const unsigned int level,
3935 % ExceptionInfo *exception)
3936 %
3937 % A description of each parameter follows:
3938 %
3939 % o display: Specifies a connection to an X server; returned from
3940 % XOpenDisplay.
3941 %
3942 % o window: Specifies the window to obtain the image from.
3943 %
3944 % o borders: Specifies whether borders pixels are to be saved with
3945 % the image.
3946 %
3947 % o level: Specifies an unsigned integer representing the level of
3948 % decent in the window hierarchy. This value must be zero or one on
3949 % the initial call to XGetWindowImage. A value of zero returns after
3950 % one call. A value of one causes the function to descend the window
3951 % hierarchy and overlay the target image with each subwindow image.
3952 %
3953 % o exception: return any errors or warnings in this structure.
3954 %
3955 */
3956 static Image *XGetWindowImage(Display *display,const Window window,
3957  const unsigned int borders,const unsigned int level,ExceptionInfo *exception)
3958 {
3959  typedef struct _ColormapInfo
3960  {
3961  Colormap
3962  colormap;
3963 
3964  XColor
3965  *colors;
3966 
3967  struct _ColormapInfo
3968  *next;
3969  } ColormapInfo;
3970 
3971  typedef struct _WindowInfo
3972  {
3973  Window
3974  window,
3975  parent;
3976 
3977  Visual
3978  *visual;
3979 
3980  Colormap
3981  colormap;
3982 
3983  XSegment
3984  bounds;
3985 
3987  crop_info;
3988  } WindowInfo;
3989 
3990  int
3991  display_height,
3992  display_width,
3993  id,
3994  x_offset,
3995  y_offset;
3996 
3997  Quantum
3998  index;
3999 
4001  crop_info;
4002 
4003  register int
4004  i;
4005 
4006  static ColormapInfo
4007  *colormap_info = (ColormapInfo *) NULL;
4008 
4009  static int
4010  max_windows = 0,
4011  number_windows = 0;
4012 
4013  static WindowInfo
4014  *window_info;
4015 
4016  Status
4017  status;
4018 
4019  Window
4020  child,
4021  root_window;
4022 
4023  XWindowAttributes
4024  window_attributes;
4025 
4026  /*
4027  Verify window is viewable.
4028  */
4029  (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
4030  assert(display != (Display *) NULL);
4031  status=XGetWindowAttributes(display,window,&window_attributes);
4032  if ((status == False) || (window_attributes.map_state != IsViewable))
4033  return((Image *) NULL);
4034  /*
4035  Cropping rectangle is relative to root window.
4036  */
4037  root_window=XRootWindow(display,XDefaultScreen(display));
4038  (void) XTranslateCoordinates(display,window,root_window,0,0,&x_offset,
4039  &y_offset,&child);
4040  crop_info.x=(ssize_t) x_offset;
4041  crop_info.y=(ssize_t) y_offset;
4042  crop_info.width=(size_t) window_attributes.width;
4043  crop_info.height=(size_t) window_attributes.height;
4044  if (borders != MagickFalse)
4045  {
4046  /*
4047  Include border in image.
4048  */
4049  crop_info.x-=(ssize_t) window_attributes.border_width;
4050  crop_info.y-=(ssize_t) window_attributes.border_width;
4051  crop_info.width+=(size_t) (window_attributes.border_width << 1);
4052  crop_info.height+=(size_t) (window_attributes.border_width << 1);
4053  }
4054  /*
4055  Crop to root window.
4056  */
4057  if (crop_info.x < 0)
4058  {
4059  crop_info.width+=crop_info.x;
4060  crop_info.x=0;
4061  }
4062  if (crop_info.y < 0)
4063  {
4064  crop_info.height+=crop_info.y;
4065  crop_info.y=0;
4066  }
4067  display_width=XDisplayWidth(display,XDefaultScreen(display));
4068  if ((int) (crop_info.x+crop_info.width) > display_width)
4069  crop_info.width=(size_t) (display_width-crop_info.x);
4070  display_height=XDisplayHeight(display,XDefaultScreen(display));
4071  if ((int) (crop_info.y+crop_info.height) > display_height)
4072  crop_info.height=(size_t) (display_height-crop_info.y);
4073  /*
4074  Initialize window info attributes.
4075  */
4076  if (number_windows >= max_windows)
4077  {
4078  /*
4079  Allocate or resize window info buffer.
4080  */
4081  max_windows+=1024;
4082  if (window_info == (WindowInfo *) NULL)
4083  window_info=(WindowInfo *) AcquireQuantumMemory((size_t) max_windows,
4084  sizeof(*window_info));
4085  else
4086  window_info=(WindowInfo *) ResizeQuantumMemory(window_info,(size_t)
4087  max_windows,sizeof(*window_info));
4088  }
4089  if (window_info == (WindowInfo *) NULL)
4090  {
4091  ThrowXWindowException(ResourceLimitError,"MemoryAllocationFailed","...");
4092  return((Image *) NULL);
4093  }
4094  id=number_windows++;
4095  window_info[id].window=window;
4096  window_info[id].visual=window_attributes.visual;
4097  window_info[id].colormap=window_attributes.colormap;
4098  window_info[id].bounds.x1=(short) crop_info.x;
4099  window_info[id].bounds.y1=(short) crop_info.y;
4100  window_info[id].bounds.x2=(short) (crop_info.x+(int) crop_info.width-1);
4101  window_info[id].bounds.y2=(short) (crop_info.y+(int) crop_info.height-1);
4102  crop_info.x-=x_offset;
4103  crop_info.y-=y_offset;
4104  window_info[id].crop_info=crop_info;
4105  if (level != 0)
4106  {
4107  unsigned int
4108  number_children;
4109 
4110  Window
4111  *children;
4112 
4113  /*
4114  Descend the window hierarchy.
4115  */
4116  status=XQueryTree(display,window,&root_window,&window_info[id].parent,
4117  &children,&number_children);
4118  for (i=0; i < id; i++)
4119  if ((window_info[i].window == window_info[id].parent) &&
4120  (window_info[i].visual == window_info[id].visual) &&
4121  (window_info[i].colormap == window_info[id].colormap))
4122  {
4123  if ((window_info[id].bounds.x1 < window_info[i].bounds.x1) ||
4124  (window_info[id].bounds.x2 > window_info[i].bounds.x2) ||
4125  (window_info[id].bounds.y1 < window_info[i].bounds.y1) ||
4126  (window_info[id].bounds.y2 > window_info[i].bounds.y2))
4127  {
4128  /*
4129  Eliminate windows not circumscribed by their parent.
4130  */
4131  number_windows--;
4132  break;
4133  }
4134  }
4135  if ((status == True) && (number_children != 0))
4136  {
4137  for (i=0; i < (int) number_children; i++)
4138  (void) XGetWindowImage(display,children[i],MagickFalse,level+1,
4139  exception);
4140  (void) XFree((void *) children);
4141  }
4142  }
4143  if (level <= 1)
4144  {
4145  CacheView
4146  *composite_view;
4147 
4148  ColormapInfo
4149  *next;
4150 
4151  Image
4152  *composite_image,
4153  *image;
4154 
4155  int
4156  y;
4157 
4159  import;
4160 
4161  register int
4162  j,
4163  x;
4164 
4165  register Quantum
4166  *magick_restrict q;
4167 
4168  register size_t
4169  pixel;
4170 
4171  unsigned int
4172  number_colors;
4173 
4174  XColor
4175  *colors;
4176 
4177  XImage
4178  *ximage;
4179 
4180  /*
4181  Get X image for each window in the list.
4182  */
4183  image=NewImageList();
4184  for (id=0; id < number_windows; id++)
4185  {
4186  /*
4187  Does target window intersect top level window?
4188  */
4189  import=((window_info[id].bounds.x2 >= window_info[0].bounds.x1) &&
4190  (window_info[id].bounds.x1 <= window_info[0].bounds.x2) &&
4191  (window_info[id].bounds.y2 >= window_info[0].bounds.y1) &&
4192  (window_info[id].bounds.y1 <= window_info[0].bounds.y2)) ?
4194  /*
4195  Is target window contained by another window with the same colormap?
4196  */
4197  for (j=0; j < id; j++)
4198  if ((window_info[id].visual == window_info[j].visual) &&
4199  (window_info[id].colormap == window_info[j].colormap))
4200  {
4201  if ((window_info[id].bounds.x1 >= window_info[j].bounds.x1) &&
4202  (window_info[id].bounds.x2 <= window_info[j].bounds.x2) &&
4203  (window_info[id].bounds.y1 >= window_info[j].bounds.y1) &&
4204  (window_info[id].bounds.y2 <= window_info[j].bounds.y2))
4205  import=MagickFalse;
4206  }
4207  if (import == MagickFalse)
4208  continue;
4209  /*
4210  Get X image.
4211  */
4212  ximage=XGetImage(display,window_info[id].window,(int)
4213  window_info[id].crop_info.x,(int) window_info[id].crop_info.y,
4214  (unsigned int) window_info[id].crop_info.width,(unsigned int)
4215  window_info[id].crop_info.height,AllPlanes,ZPixmap);
4216  if (ximage == (XImage *) NULL)
4217  continue;
4218  /*
4219  Initialize window colormap.
4220  */
4221  number_colors=0;
4222  colors=(XColor *) NULL;
4223  if (window_info[id].colormap != (Colormap) NULL)
4224  {
4225  ColormapInfo
4226  *p;
4227 
4228  /*
4229  Search colormap list for window colormap.
4230  */
4231  number_colors=(unsigned int) window_info[id].visual->map_entries;
4232  for (p=colormap_info; p != (ColormapInfo *) NULL; p=p->next)
4233  if (p->colormap == window_info[id].colormap)
4234  break;
4235  if (p == (ColormapInfo *) NULL)
4236  {
4237  /*
4238  Get the window colormap.
4239  */
4240  colors=(XColor *) AcquireQuantumMemory(number_colors,
4241  sizeof(*colors));
4242  if (colors == (XColor *) NULL)
4243  {
4244  XDestroyImage(ximage);
4245  return((Image *) NULL);
4246  }
4247  if ((window_info[id].visual->klass != DirectColor) &&
4248  (window_info[id].visual->klass != TrueColor))
4249  for (i=0; i < (int) number_colors; i++)
4250  {
4251  colors[i].pixel=(size_t) i;
4252  colors[i].pad='\0';
4253  }
4254  else
4255  {
4256  size_t
4257  blue,
4258  blue_bit,
4259  green,
4260  green_bit,
4261  red,
4262  red_bit;
4263 
4264  /*
4265  DirectColor or TrueColor visual.
4266  */
4267  red=0;
4268  green=0;
4269  blue=0;
4270  red_bit=window_info[id].visual->red_mask &
4271  (~(window_info[id].visual->red_mask)+1);
4272  green_bit=window_info[id].visual->green_mask &
4273  (~(window_info[id].visual->green_mask)+1);
4274  blue_bit=window_info[id].visual->blue_mask &
4275  (~(window_info[id].visual->blue_mask)+1);
4276  for (i=0; i < (int) number_colors; i++)
4277  {
4278  colors[i].pixel=(unsigned long) (red | green | blue);
4279  colors[i].pad='\0';
4280  red+=red_bit;
4281  if (red > window_info[id].visual->red_mask)
4282  red=0;
4283  green+=green_bit;
4284  if (green > window_info[id].visual->green_mask)
4285  green=0;
4286  blue+=blue_bit;
4287  if (blue > window_info[id].visual->blue_mask)
4288  blue=0;
4289  }
4290  }
4291  (void) XQueryColors(display,window_info[id].colormap,colors,
4292  (int) number_colors);
4293  /*
4294  Append colormap to colormap list.
4295  */
4296  p=(ColormapInfo *) AcquireMagickMemory(sizeof(*p));
4297  if (p == (ColormapInfo *) NULL)
4298  return((Image *) NULL);
4299  p->colormap=window_info[id].colormap;
4300  p->colors=colors;
4301  p->next=colormap_info;
4302  colormap_info=p;
4303  }
4304  colors=p->colors;
4305  }
4306  /*
4307  Allocate image structure.
4308  */
4309  composite_image=AcquireImage((ImageInfo *) NULL,exception);
4310  if (composite_image == (Image *) NULL)
4311  {
4312  XDestroyImage(ximage);
4313  return((Image *) NULL);
4314  }
4315  /*
4316  Convert X image to MIFF format.
4317  */
4318  if ((window_info[id].visual->klass != TrueColor) &&
4319  (window_info[id].visual->klass != DirectColor))
4320  composite_image->storage_class=PseudoClass;
4321  composite_image->columns=(size_t) ximage->width;
4322  composite_image->rows=(size_t) ximage->height;
4323  composite_view=AcquireAuthenticCacheView(composite_image,exception);
4324  switch (composite_image->storage_class)
4325  {
4326  case DirectClass:
4327  default:
4328  {
4329  register size_t
4330  color,
4331  index;
4332 
4333  size_t
4334  blue_mask,
4335  blue_shift,
4336  green_mask,
4337  green_shift,
4338  red_mask,
4339  red_shift;
4340 
4341  /*
4342  Determine shift and mask for red, green, and blue.
4343  */
4344  red_mask=window_info[id].visual->red_mask;
4345  red_shift=0;
4346  while ((red_mask != 0) && ((red_mask & 0x01) == 0))
4347  {
4348  red_mask>>=1;
4349  red_shift++;
4350  }
4351  green_mask=window_info[id].visual->green_mask;
4352  green_shift=0;
4353  while ((green_mask != 0) && ((green_mask & 0x01) == 0))
4354  {
4355  green_mask>>=1;
4356  green_shift++;
4357  }
4358  blue_mask=window_info[id].visual->blue_mask;
4359  blue_shift=0;
4360  while ((blue_mask != 0) && ((blue_mask & 0x01) == 0))
4361  {
4362  blue_mask>>=1;
4363  blue_shift++;
4364  }
4365  /*
4366  Convert X image to DirectClass packets.
4367  */
4368  if ((number_colors != 0) &&
4369  (window_info[id].visual->klass == DirectColor))
4370  for (y=0; y < (int) composite_image->rows; y++)
4371  {
4372  q=QueueCacheViewAuthenticPixels(composite_view,0,(ssize_t) y,
4373  composite_image->columns,1,exception);
4374  if (q == (Quantum *) NULL)
4375  break;
4376  for (x=0; x < (int) composite_image->columns; x++)
4377  {
4378  pixel=XGetPixel(ximage,x,y);
4379  index=(pixel >> red_shift) & red_mask;
4380  SetPixelRed(composite_image,
4381  ScaleShortToQuantum(colors[index].red),q);
4382  index=(pixel >> green_shift) & green_mask;
4383  SetPixelGreen(composite_image,
4384  ScaleShortToQuantum(colors[index].green),q);
4385  index=(pixel >> blue_shift) & blue_mask;
4386  SetPixelBlue(composite_image,
4387  ScaleShortToQuantum(colors[index].blue),q);
4388  q+=GetPixelChannels(composite_image);
4389  }
4390  status=SyncCacheViewAuthenticPixels(composite_view,exception);
4391  if (status == MagickFalse)
4392  break;
4393  }
4394  else
4395  for (y=0; y < (int) composite_image->rows; y++)
4396  {
4397  q=QueueCacheViewAuthenticPixels(composite_view,0,(ssize_t) y,
4398  composite_image->columns,1,exception);
4399  if (q == (Quantum *) NULL)
4400  break;
4401  for (x=0; x < (int) composite_image->columns; x++)
4402  {
4403  pixel=XGetPixel(ximage,x,y);
4404  color=(pixel >> red_shift) & red_mask;
4405  if (red_mask != 0)
4406  color=(65535UL*color)/red_mask;
4407  SetPixelRed(composite_image,ScaleShortToQuantum(
4408  (unsigned short) color),q);
4409  color=(pixel >> green_shift) & green_mask;
4410  if (green_mask != 0)
4411  color=(65535UL*color)/green_mask;
4412  SetPixelGreen(composite_image,ScaleShortToQuantum(
4413  (unsigned short) color),q);
4414  color=(pixel >> blue_shift) & blue_mask;
4415  if (blue_mask != 0)
4416  color=(65535UL*color)/blue_mask;
4417  SetPixelBlue(composite_image,ScaleShortToQuantum(
4418  (unsigned short) color),q);
4419  q+=GetPixelChannels(composite_image);
4420  }
4421  status=SyncCacheViewAuthenticPixels(composite_view,exception);
4422  if (status == MagickFalse)
4423  break;
4424  }
4425  break;
4426  }
4427  case PseudoClass:
4428  {
4429  /*
4430  Create colormap.
4431  */
4432  status=AcquireImageColormap(composite_image,number_colors,
4433  exception);
4434  if (status == MagickFalse)
4435  {
4436  XDestroyImage(ximage);
4437  composite_image=DestroyImage(composite_image);
4438  return((Image *) NULL);
4439  }
4440  for (i=0; i < (int) composite_image->colors; i++)
4441  {
4442  composite_image->colormap[colors[i].pixel].red=(double)
4443  ScaleShortToQuantum(colors[i].red);
4444  composite_image->colormap[colors[i].pixel].green=(double)
4445  ScaleShortToQuantum(colors[i].green);
4446  composite_image->colormap[colors[i].pixel].blue=(double)
4447  ScaleShortToQuantum(colors[i].blue);
4448  }
4449  /*
4450  Convert X image to PseudoClass packets.
4451  */
4452  for (y=0; y < (int) composite_image->rows; y++)
4453  {
4454  q=QueueCacheViewAuthenticPixels(composite_view,0,(ssize_t) y,
4455  composite_image->columns,1,exception);
4456  if (q == (Quantum *) NULL)
4457  break;
4458  for (x=0; x < (int) composite_image->columns; x++)
4459  {
4460  index=(Quantum) XGetPixel(ximage,x,y);
4461  SetPixelIndex(composite_image,index,q);
4462  SetPixelViaPixelInfo(composite_image,
4463  composite_image->colormap+(ssize_t) index,q);
4464  q+=GetPixelChannels(composite_image);
4465  }
4466  status=SyncCacheViewAuthenticPixels(composite_view,exception);
4467  if (status == MagickFalse)
4468  break;
4469  }
4470  break;
4471  }
4472  }
4473  composite_view=DestroyCacheView(composite_view);
4474  XDestroyImage(ximage);
4475  if (image == (Image *) NULL)
4476  {
4477  image=composite_image;
4478  continue;
4479  }
4480  /*
4481  Composite any children in back-to-front order.
4482  */
4483  (void) XTranslateCoordinates(display,window_info[id].window,window,0,0,
4484  &x_offset,&y_offset,&child);
4485  x_offset-=(int) crop_info.x;
4486  if (x_offset < 0)
4487  x_offset=0;
4488  y_offset-=(int) crop_info.y;
4489  if (y_offset < 0)
4490  y_offset=0;
4491  (void) CompositeImage(image,composite_image,CopyCompositeOp,MagickTrue,
4492  (ssize_t) x_offset,(ssize_t) y_offset,exception);
4493  composite_image=DestroyImage(composite_image);
4494  }
4495  /*
4496  Relinquish resources.
4497  */
4498  while (colormap_info != (ColormapInfo *) NULL)
4499  {
4500  next=colormap_info->next;
4501  colormap_info->colors=(XColor *) RelinquishMagickMemory(
4502  colormap_info->colors);
4503  colormap_info=(ColormapInfo *) RelinquishMagickMemory(colormap_info);
4504  colormap_info=next;
4505  }
4506  /*
4507  Relinquish resources and restore initial state.
4508  */
4509  window_info=(WindowInfo *) RelinquishMagickMemory(window_info);
4510  max_windows=0;
4511  number_windows=0;
4512  colormap_info=(ColormapInfo *) NULL;
4513  return(image);
4514  }
4515  return((Image *) NULL);
4516 }
4517 
4518 /*
4519 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4520 % %
4521 % %
4522 % %
4523 % X G e t W i n d o w I n f o %
4524 % %
4525 % %
4526 % %
4527 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4528 %
4529 % XGetWindowInfo() initializes the XWindowInfo structure.
4530 %
4531 % The format of the XGetWindowInfo method is:
4532 %
4533 % void XGetWindowInfo(Display *display,XVisualInfo *visual_info,
4534 % XStandardColormap *map_info,XPixelInfo *pixel,XFontStruct *font_info,
4535 % XResourceInfo *resource_info,XWindowInfo *window)
4536 % resource_info,window)
4537 %
4538 % A description of each parameter follows:
4539 %
4540 % o display: Specifies a connection to an X server; returned from
4541 % XOpenDisplay.
4542 %
4543 % o visual_info: Specifies a pointer to a X11 XVisualInfo structure;
4544 % returned from XGetVisualInfo.
4545 %
4546 % o map_info: If map_type is specified, this structure is initialized
4547 % with info from the Standard Colormap.
4548 %
4549 % o pixel: Specifies a pointer to a XPixelInfo structure.
4550 %
4551 % o font_info: Specifies a pointer to a XFontStruct structure.
4552 %
4553 % o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
4554 %
4555 */
4556 MagickPrivate void XGetWindowInfo(Display *display,XVisualInfo *visual_info,
4557  XStandardColormap *map_info,XPixelInfo *pixel,XFontStruct *font_info,
4558  XResourceInfo *resource_info,XWindowInfo *window)
4559 {
4560  /*
4561  Initialize window info.
4562  */
4563  (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
4564  assert(display != (Display *) NULL);
4565  assert(visual_info != (XVisualInfo *) NULL);
4566  assert(map_info != (XStandardColormap *) NULL);
4567  assert(pixel != (XPixelInfo *) NULL);
4568  assert(resource_info != (XResourceInfo *) NULL);
4569  assert(window != (XWindowInfo *) NULL);
4570  if (window->id != (Window) NULL)
4571  {
4572  if (window->cursor != (Cursor) NULL)
4573  (void) XFreeCursor(display,window->cursor);
4574  if (window->busy_cursor != (Cursor) NULL)
4575  (void) XFreeCursor(display,window->busy_cursor);
4576  if (window->highlight_stipple != (Pixmap) NULL)
4577  (void) XFreePixmap(display,window->highlight_stipple);
4578  if (window->shadow_stipple != (Pixmap) NULL)
4579  (void) XFreePixmap(display,window->shadow_stipple);
4580  if (window->name == (char *) NULL)
4581  window->name=AcquireString("");
4582  if (window->icon_name == (char *) NULL)
4583  window->icon_name=AcquireString("");
4584  }
4585  else
4586  {
4587  /*
4588  Initialize these attributes just once.
4589  */
4590  window->id=(Window) NULL;
4591  if (window->name == (char *) NULL)
4592  window->name=AcquireString("");
4593  if (window->icon_name == (char *) NULL)
4594  window->icon_name=AcquireString("");
4595  window->x=XDisplayWidth(display,visual_info->screen) >> 1;
4596  window->y=XDisplayWidth(display,visual_info->screen) >> 1;
4597  window->ximage=(XImage *) NULL;
4598  window->matte_image=(XImage *) NULL;
4599  window->pixmap=(Pixmap) NULL;
4600  window->matte_pixmap=(Pixmap) NULL;
4601  window->mapped=MagickFalse;
4602  window->stasis=MagickFalse;
4603  window->shared_memory=MagickTrue;
4604  window->segment_info=(void *) NULL;
4605 #if defined(MAGICKCORE_HAVE_SHARED_MEMORY)
4606  {
4607  XShmSegmentInfo
4608  *segment_info;
4609 
4610  if (window->segment_info == (void *) NULL)
4611  window->segment_info=AcquireCriticalMemory(2*sizeof(*segment_info));
4612  segment_info=(XShmSegmentInfo *) window->segment_info;
4613  segment_info[0].shmid=(-1);
4614  segment_info[0].shmaddr=(char *) NULL;
4615  segment_info[1].shmid=(-1);
4616  segment_info[1].shmaddr=(char *) NULL;
4617  }
4618 #endif
4619  }
4620  /*
4621  Initialize these attributes every time function is called.
4622  */
4623  window->screen=visual_info->screen;
4624  window->root=XRootWindow(display,visual_info->screen);
4625  window->visual=visual_info->visual;
4626  window->storage_class=(unsigned int) visual_info->klass;
4627  window->depth=(unsigned int) visual_info->depth;
4628  window->visual_info=visual_info;
4629  window->map_info=map_info;
4630  window->pixel_info=pixel;
4631  window->font_info=font_info;
4632  window->cursor=XCreateFontCursor(display,XC_left_ptr);
4633  window->busy_cursor=XCreateFontCursor(display,XC_watch);
4634  window->geometry=(char *) NULL;
4635  window->icon_geometry=(char *) NULL;
4636  if (resource_info->icon_geometry != (char *) NULL)
4637  (void) CloneString(&window->icon_geometry,resource_info->icon_geometry);
4638  window->crop_geometry=(char *) NULL;
4639  window->flags=(size_t) PSize;
4640  window->width=1;
4641  window->height=1;
4642  window->min_width=1;
4643  window->min_height=1;
4644  window->width_inc=1;
4645  window->height_inc=1;
4646  window->border_width=resource_info->border_width;
4647  window->annotate_context=pixel->annotate_context;
4648  window->highlight_context=pixel->highlight_context;
4649  window->widget_context=pixel->widget_context;
4650  window->shadow_stipple=(Pixmap) NULL;
4651  window->highlight_stipple=(Pixmap) NULL;
4652  window->use_pixmap=MagickTrue;
4653  window->immutable=MagickFalse;
4654  window->shape=MagickFalse;
4655  window->data=0;
4656  window->mask=(int) (CWBackingStore | CWBackPixel | CWBackPixmap |
4657  CWBitGravity | CWBorderPixel | CWColormap | CWCursor | CWDontPropagate |
4658  CWEventMask | CWOverrideRedirect | CWSaveUnder | CWWinGravity);
4659  window->attributes.background_pixel=pixel->background_color.pixel;
4660  window->attributes.background_pixmap=(Pixmap) NULL;
4661  window->attributes.bit_gravity=ForgetGravity;
4662  window->attributes.backing_store=WhenMapped;
4663  window->attributes.save_under=MagickTrue;
4664  window->attributes.border_pixel=pixel->border_color.pixel;
4665  window->attributes.colormap=map_info->colormap;
4666  window->attributes.cursor=window->cursor;
4667  window->attributes.do_not_propagate_mask=NoEventMask;
4668  window->attributes.event_mask=NoEventMask;
4669  window->attributes.override_redirect=MagickFalse;
4670  window->attributes.win_gravity=NorthWestGravity;
4671  window->orphan=MagickFalse;
4672 }
4673 
4674 /*
4675 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4676 % %
4677 % %
4678 % %
4679 % X H i g h l i g h t E l l i p s e %
4680 % %
4681 % %
4682 % %
4683 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4684 %
4685 % XHighlightEllipse() puts a border on the X server around a region defined by
4686 % highlight_info.
4687 %
4688 % The format of the XHighlightEllipse method is:
4689 %
4690 % void XHighlightEllipse(Display *display,Window window,
4691 % GC annotate_context,const RectangleInfo *highlight_info)
4692 %
4693 % A description of each parameter follows:
4694 %
4695 % o display: Specifies a connection to an X server; returned from
4696 % XOpenDisplay.
4697 %
4698 % o window: Specifies a pointer to a Window structure.
4699 %
4700 % o annotate_context: Specifies a pointer to a GC structure.
4701 %
4702 % o highlight_info: Specifies a pointer to a RectangleInfo structure. It
4703 % contains the extents of any highlighting rectangle.
4704 %
4705 */
4706 MagickPrivate void XHighlightEllipse(Display *display,Window window,
4707  GC annotate_context,const RectangleInfo *highlight_info)
4708 {
4709  (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
4710  assert(display != (Display *) NULL);
4711  assert(window != (Window) NULL);
4712  assert(annotate_context != (GC) NULL);
4713  assert(highlight_info != (RectangleInfo *) NULL);
4714  if ((highlight_info->width < 4) || (highlight_info->height < 4))
4715  return;
4716  (void) XDrawArc(display,window,annotate_context,(int) highlight_info->x,
4717  (int) highlight_info->y,(unsigned int) highlight_info->width-1,
4718  (unsigned int) highlight_info->height-1,0,360*64);
4719  (void) XDrawArc(display,window,annotate_context,(int) highlight_info->x+1,
4720  (int) highlight_info->y+1,(unsigned int) highlight_info->width-3,
4721  (unsigned int) highlight_info->height-3,0,360*64);
4722 }
4723 
4724 /*
4725 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4726 % %
4727 % %
4728 % %
4729 % X H i g h l i g h t L i n e %
4730 % %
4731 % %
4732 % %
4733 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4734 %
4735 % XHighlightLine() puts a border on the X server around a region defined by
4736 % highlight_info.
4737 %
4738 % The format of the XHighlightLine method is:
4739 %
4740 % void XHighlightLine(Display *display,Window window,GC annotate_context,
4741 % const XSegment *highlight_info)
4742 %
4743 % A description of each parameter follows:
4744 %
4745 % o display: Specifies a connection to an X server; returned from
4746 % XOpenDisplay.
4747 %
4748 % o window: Specifies a pointer to a Window structure.
4749 %
4750 % o annotate_context: Specifies a pointer to a GC structure.
4751 %
4752 % o highlight_info: Specifies a pointer to a RectangleInfo structure. It
4753 % contains the extents of any highlighting rectangle.
4754 %
4755 */
4756 MagickPrivate void XHighlightLine(Display *display,Window window,
4757  GC annotate_context,const XSegment *highlight_info)
4758 {
4759  (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
4760  assert(display != (Display *) NULL);
4761  assert(window != (Window) NULL);
4762  assert(annotate_context != (GC) NULL);
4763  assert(highlight_info != (XSegment *) NULL);
4764  (void) XDrawLine(display,window,annotate_context,highlight_info->x1,
4765  highlight_info->y1,highlight_info->x2,highlight_info->y2);
4766 }
4767 
4768 /*
4769 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4770 % %
4771 % %
4772 % %
4773 % X H i g h l i g h t R e c t a n g l e %
4774 % %
4775 % %
4776 % %
4777 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4778 %
4779 % XHighlightRectangle() puts a border on the X server around a region defined
4780 % by highlight_info.
4781 %
4782 % The format of the XHighlightRectangle method is:
4783 %
4784 % void XHighlightRectangle(Display *display,Window window,
4785 % GC annotate_context,const RectangleInfo *highlight_info)
4786 %
4787 % A description of each parameter follows:
4788 %
4789 % o display: Specifies a connection to an X server; returned from
4790 % XOpenDisplay.
4791 %
4792 % o window: Specifies a pointer to a Window structure.
4793 %
4794 % o annotate_context: Specifies a pointer to a GC structure.
4795 %
4796 % o highlight_info: Specifies a pointer to a RectangleInfo structure. It
4797 % contains the extents of any highlighting rectangle.
4798 %
4799 */
4800 MagickPrivate void XHighlightRectangle(Display *display,Window window,
4801  GC annotate_context,const RectangleInfo *highlight_info)
4802 {
4803  assert(display != (Display *) NULL);
4804  (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
4805  assert(window != (Window) NULL);
4806  assert(annotate_context != (GC) NULL);
4807  assert(highlight_info != (RectangleInfo *) NULL);
4808  if ((highlight_info->width < 4) || (highlight_info->height < 4))
4809  return;
4810  (void) XDrawRectangle(display,window,annotate_context,(int) highlight_info->x,
4811  (int) highlight_info->y,(unsigned int) highlight_info->width-1,
4812  (unsigned int) highlight_info->height-1);
4813  (void) XDrawRectangle(display,window,annotate_context,(int) highlight_info->x+
4814  1,(int) highlight_info->y+1,(unsigned int) highlight_info->width-3,
4815  (unsigned int) highlight_info->height-3);
4816 }
4817 
4818 /*
4819 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4820 % %
4821 % %
4822 % %
4823 % X I m p o r t I m a g e %
4824 % %
4825 % %
4826 % %
4827 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4828 %
4829 % XImportImage() reads an image from an X window.
4830 %
4831 % The format of the XImportImage method is:
4832 %
4833 % Image *XImportImage(const ImageInfo *image_info,XImportInfo *ximage_info,
4834 % ExceptionInfo *exception)
4835 %
4836 % A description of each parameter follows:
4837 %
4838 % o image_info: the image info.
4839 %
4840 % o ximage_info: Specifies a pointer to an XImportInfo structure.
4841 %
4842 % o exception: return any errors or warnings in this structure.
4843 %
4844 */
4845 MagickExport Image *XImportImage(const ImageInfo *image_info,
4846  XImportInfo *ximage_info,ExceptionInfo *exception)
4847 {
4848  Colormap
4849  *colormaps;
4850 
4851  Display
4852  *display;
4853 
4854  Image
4855  *image;
4856 
4857  int
4858  number_colormaps,
4859  number_windows,
4860  x;
4861 
4863  crop_info;
4864 
4865  Status
4866  status;
4867 
4868  Window
4869  *children,
4870  client,
4871  prior_target,
4872  root,
4873  target;
4874 
4875  XTextProperty
4876  window_name;
4877 
4878  /*
4879  Open X server connection.
4880  */
4881  assert(image_info != (const ImageInfo *) NULL);
4882  assert(image_info->signature == MagickCoreSignature);
4883  if (image_info->debug != MagickFalse)
4885  image_info->filename);
4886  assert(ximage_info != (XImportInfo *) NULL);
4887  display=XOpenDisplay(image_info->server_name);
4888  if (display == (Display *) NULL)
4889  {
4890  ThrowXWindowException(XServerError,"UnableToOpenXServer",
4891  XDisplayName(image_info->server_name));
4892  return((Image *) NULL);
4893  }
4894  /*
4895  Set our forgiving exception handler.
4896  */
4897  (void) XSetErrorHandler(XError);
4898  /*
4899  Select target window.
4900  */
4901  crop_info.x=0;
4902  crop_info.y=0;
4903  crop_info.width=0;
4904  crop_info.height=0;
4905  root=XRootWindow(display,XDefaultScreen(display));
4906  target=(Window) NULL;
4907  if (*image_info->filename != '\0')
4908  {
4909  if (LocaleCompare(image_info->filename,"root") == 0)
4910  target=root;
4911  else
4912  {
4913  /*
4914  Select window by ID or name.
4915  */
4916  if (isdigit((int) ((unsigned char) *image_info->filename)) != 0)
4917  target=XWindowByID(display,root,(Window)
4918  strtol(image_info->filename,(char **) NULL,0));
4919  if (target == (Window) NULL)
4920  target=XWindowByName(display,root,image_info->filename);
4921  if (target == (Window) NULL)
4922  ThrowXWindowException(XServerError,"NoWindowWithSpecifiedIDExists",
4923  image_info->filename);
4924  }
4925  }
4926  /*
4927  If target window is not defined, interactively select one.
4928  */
4929  prior_target=target;
4930  if (target == (Window) NULL)
4931  target=XSelectWindow(display,&crop_info);
4932  if (target == (Window) NULL)
4933  ThrowXWindowException(XServerError,"UnableToReadXWindowImage",
4934  image_info->filename);
4935  client=target; /* obsolete */
4936  if (target != root)
4937  {
4938  unsigned int
4939  d;
4940 
4941  status=XGetGeometry(display,target,&root,&x,&x,&d,&d,&d,&d);
4942  if (status != False)
4943  {
4944  for ( ; ; )
4945  {
4946  Window
4947  parent;
4948 
4949  /*
4950  Find window manager frame.
4951  */
4952  status=XQueryTree(display,target,&root,&parent,&children,&d);
4953  if ((status != False) && (children != (Window *) NULL))
4954  (void) XFree((char *) children);
4955  if ((status == False) || (parent == (Window) NULL) ||
4956  (parent == root))
4957  break;
4958  target=parent;
4959  }
4960  /*
4961  Get client window.
4962  */
4963  client=XClientWindow(display,target);
4964  if (ximage_info->frame == MagickFalse)
4965  target=client;
4966  if ((ximage_info->frame == MagickFalse) &&
4967  (prior_target != MagickFalse))
4968  target=prior_target;
4969  }
4970  }
4971  if (ximage_info->screen)
4972  {
4973  int
4974  y;
4975 
4976  Window
4977  child;
4978 
4979  XWindowAttributes
4980  window_attributes;
4981 
4982  /*
4983  Obtain window image directly from screen.
4984  */
4985  status=XGetWindowAttributes(display,target,&window_attributes);
4986  if (status == False)
4987  {
4988  ThrowXWindowException(XServerError,"UnableToReadXWindowAttributes",
4989  image_info->filename);
4990  (void) XCloseDisplay(display);
4991  return((Image *) NULL);
4992  }
4993  (void) XTranslateCoordinates(display,target,root,0,0,&x,&y,&child);
4994  crop_info.x=(ssize_t) x;
4995  crop_info.y=(ssize_t) y;
4996  crop_info.width=(size_t) window_attributes.width;
4997  crop_info.height=(size_t) window_attributes.height;
4998  if (ximage_info->borders != 0)
4999  {
5000  /*
5001  Include border in image.
5002  */
5003  crop_info.x-=window_attributes.border_width;
5004  crop_info.y-=window_attributes.border_width;
5005  crop_info.width+=window_attributes.border_width << 1;
5006  crop_info.height+=window_attributes.border_width << 1;
5007  }
5008  target=root;
5009  }
5010  /*
5011  If WM_COLORMAP_WINDOWS property is set or multiple colormaps, descend.
5012  */
5013  number_windows=0;
5014  status=XGetWMColormapWindows(display,target,&children,&number_windows);
5015  if ((status == True) && (number_windows > 0))
5016  {
5017  ximage_info->descend=MagickTrue;
5018  (void) XFree ((char *) children);
5019  }
5020  colormaps=XListInstalledColormaps(display,target,&number_colormaps);
5021  if (number_colormaps > 0)
5022  {
5023  if (number_colormaps > 1)
5024  ximage_info->descend=MagickTrue;
5025  (void) XFree((char *) colormaps);
5026  }
5027  /*
5028  Alert the user not to alter the screen.
5029  */
5030  if (ximage_info->silent == MagickFalse)
5031  (void) XBell(display,0);
5032  /*
5033  Get image by window id.
5034  */
5035  (void) XGrabServer(display);
5036  image=XGetWindowImage(display,target,ximage_info->borders,
5037  ximage_info->descend ? 1U : 0U,exception);
5038  (void) XUngrabServer(display);
5039  if (image == (Image *) NULL)
5040  ThrowXWindowException(XServerError,"UnableToReadXWindowImage",
5041  image_info->filename)
5042  else
5043  {
5044  (void) CopyMagickString(image->filename,image_info->filename,
5045  MagickPathExtent);
5046  if ((crop_info.width != 0) && (crop_info.height != 0))
5047  {
5048  Image
5049  *crop_image;
5050 
5051  /*
5052  Crop image as defined by the cropping rectangle.
5053  */
5054  crop_image=CropImage(image,&crop_info,exception);
5055  if (crop_image != (Image *) NULL)
5056  {
5057  image=DestroyImage(image);
5058  image=crop_image;
5059  }
5060  }
5061  status=XGetWMName(display,target,&window_name);
5062  if (status == True)
5063  {
5064  if (*image_info->filename == '\0')
5065  (void) CopyMagickString(image->filename,(char *) window_name.value,
5066  (size_t) window_name.nitems+1);
5067  (void) XFree((void *) window_name.value);
5068  }
5069  }
5070  if (ximage_info->silent == MagickFalse)
5071  {
5072  /*
5073  Alert the user we're done.
5074  */
5075  (void) XBell(display,0);
5076  (void) XBell(display,0);
5077  }
5078  (void) XCloseDisplay(display);
5079  return(image);
5080 }
5081 
5082 /*
5083 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5084 % %
5085 % %
5086 % %
5087 % X I n i t i a l i z e W i n d o w s %
5088 % %
5089 % %
5090 % %
5091 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5092 %
5093 % XInitializeWindows() initializes the XWindows structure.
5094 %
5095 % The format of the XInitializeWindows method is:
5096 %
5097 % XWindows *XInitializeWindows(Display *display,
5098 % XResourceInfo *resource_info)
5099 %
5100 % A description of each parameter follows:
5101 %
5102 % o windows: XInitializeWindows returns a pointer to a XWindows structure.
5103 %
5104 % o display: Specifies a connection to an X server; returned from
5105 % XOpenDisplay.
5106 %
5107 % o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
5108 %
5109 */
5110 MagickPrivate XWindows *XInitializeWindows(Display *display,
5111  XResourceInfo *resource_info)
5112 {
5113  Window
5114  root_window;
5115 
5116  XWindows
5117  *windows;
5118 
5119  /*
5120  Allocate windows structure.
5121  */
5122  windows=(XWindows *) AcquireMagickMemory(sizeof(*windows));
5123  if (windows == (XWindows *) NULL)
5124  {
5125  ThrowXWindowFatalException(XServerFatalError,"MemoryAllocationFailed",
5126  "...");
5127  return((XWindows *) NULL);
5128  }
5129  (void) memset(windows,0,sizeof(*windows));
5130  windows->pixel_info=(XPixelInfo *) AcquireMagickMemory(
5131  sizeof(*windows->pixel_info));
5132  windows->icon_pixel=(XPixelInfo *) AcquireMagickMemory(
5133  sizeof(*windows->icon_pixel));
5134  windows->icon_resources=(XResourceInfo *) AcquireMagickMemory(
5135  sizeof(*windows->icon_resources));
5136  if ((windows->pixel_info == (XPixelInfo *) NULL) ||
5137  (windows->icon_pixel == (XPixelInfo *) NULL) ||
5138  (windows->icon_resources == (XResourceInfo *) NULL))
5139  {
5140  ThrowXWindowFatalException(XServerFatalError,"MemoryAllocationFailed",
5141  "...");
5142  return((XWindows *) NULL);
5143  }
5144  /*
5145  Initialize windows structure.
5146  */
5147  windows->display=display;
5148  windows->wm_protocols=XInternAtom(display,"WM_PROTOCOLS",MagickFalse);
5149  windows->wm_delete_window=XInternAtom(display,"WM_DELETE_WINDOW",MagickFalse);
5150  windows->wm_take_focus=XInternAtom(display,"WM_TAKE_FOCUS",MagickFalse);
5151  windows->im_protocols=XInternAtom(display,"IM_PROTOCOLS",MagickFalse);
5152  windows->im_remote_command=
5153  XInternAtom(display,"IM_REMOTE_COMMAND",MagickFalse);
5154  windows->im_update_widget=XInternAtom(display,"IM_UPDATE_WIDGET",MagickFalse);
5155  windows->im_update_colormap=
5156  XInternAtom(display,"IM_UPDATE_COLORMAP",MagickFalse);
5157  windows->im_former_image=XInternAtom(display,"IM_FORMER_IMAGE",MagickFalse);
5158  windows->im_next_image=XInternAtom(display,"IM_NEXT_IMAGE",MagickFalse);
5159  windows->im_retain_colors=XInternAtom(display,"IM_RETAIN_COLORS",MagickFalse);
5160  windows->im_exit=XInternAtom(display,"IM_EXIT",MagickFalse);
5161  windows->dnd_protocols=XInternAtom(display,"DndProtocol",MagickFalse);
5162 #if defined(MAGICKCORE_WINDOWS_SUPPORT)
5163  (void) XSynchronize(display,IsWindows95());
5164 #endif
5165  if (IsEventLogging())
5166  {
5167  (void) XSynchronize(display,MagickTrue);
5168  (void) LogMagickEvent(X11Event,GetMagickModule(),"Version: %s",
5169  GetMagickVersion((size_t *) NULL));
5170  (void) LogMagickEvent(X11Event,GetMagickModule(),"Protocols:");
5172  " Window Manager: 0x%lx",windows->wm_protocols);
5174  " delete window: 0x%lx",windows->wm_delete_window);
5175  (void) LogMagickEvent(X11Event,GetMagickModule()," take focus: 0x%lx",
5176  windows->wm_take_focus);
5177  (void) LogMagickEvent(X11Event,GetMagickModule()," ImageMagick: 0x%lx",
5178  windows->im_protocols);
5180  " remote command: 0x%lx",windows->im_remote_command);
5182  " update widget: 0x%lx",windows->im_update_widget);
5184  " update colormap: 0x%lx",windows->im_update_colormap);
5186  " former image: 0x%lx",windows->im_former_image);
5187  (void) LogMagickEvent(X11Event,GetMagickModule()," next image: 0x%lx",
5188  windows->im_next_image);
5190  " retain colors: 0x%lx",windows->im_retain_colors);
5191  (void) LogMagickEvent(X11Event,GetMagickModule()," exit: 0x%lx",
5192  windows->im_exit);
5193  (void) LogMagickEvent(X11Event,GetMagickModule()," Drag and Drop: 0x%lx",
5194  windows->dnd_protocols);
5195  }
5196  /*
5197  Allocate standard colormap.
5198  */
5199  windows->map_info=XAllocStandardColormap();
5200  windows->icon_map=XAllocStandardColormap();
5201  if ((windows->map_info == (XStandardColormap *) NULL) ||
5202  (windows->icon_map == (XStandardColormap *) NULL))
5203  ThrowXWindowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed",
5204  "...");
5205  windows->map_info->colormap=(Colormap) NULL;
5206  windows->icon_map->colormap=(Colormap) NULL;
5207  windows->pixel_info->pixels=(unsigned long *) NULL;
5208  windows->pixel_info->annotate_context=(GC) NULL;
5209  windows->pixel_info->highlight_context=(GC) NULL;
5210  windows->pixel_info->widget_context=(GC) NULL;
5211  windows->font_info=(XFontStruct *) NULL;
5212  windows->icon_pixel->annotate_context=(GC) NULL;
5213  windows->icon_pixel->pixels=(unsigned long *) NULL;
5214  /*
5215  Allocate visual.
5216  */
5217  *windows->icon_resources=(*resource_info);
5218  windows->icon_resources->visual_type=(char *) "default";
5219  windows->icon_resources->colormap=SharedColormap;
5220  windows->visual_info=
5221  XBestVisualInfo(display,windows->map_info,resource_info);
5222  windows->icon_visual=
5223  XBestVisualInfo(display,windows->icon_map,windows->icon_resources);
5224  if ((windows->visual_info == (XVisualInfo *) NULL) ||
5225  (windows->icon_visual == (XVisualInfo *) NULL))
5226  ThrowXWindowFatalException(XServerFatalError,"UnableToGetVisual",
5227  resource_info->visual_type);
5228  if (IsEventLogging())
5229  {
5230  (void) LogMagickEvent(X11Event,GetMagickModule(),"Visual:");
5231  (void) LogMagickEvent(X11Event,GetMagickModule()," visual id: 0x%lx",
5232  windows->visual_info->visualid);
5233  (void) LogMagickEvent(X11Event,GetMagickModule()," class: %s",
5234  XVisualClassName(windows->visual_info->klass));
5235  (void) LogMagickEvent(X11Event,GetMagickModule()," depth: %d planes",
5236  windows->visual_info->depth);
5238  " size of colormap: %d entries",windows->visual_info->colormap_size);
5240  " red, green, blue masks: 0x%lx 0x%lx 0x%lx",
5241  windows->visual_info->red_mask,windows->visual_info->green_mask,
5242  windows->visual_info->blue_mask);
5244  " significant bits in color: %d bits",
5245  windows->visual_info->bits_per_rgb);
5246  }
5247  /*
5248  Allocate class and manager hints.
5249  */
5250  windows->class_hints=XAllocClassHint();
5251  windows->manager_hints=XAllocWMHints();
5252  if ((windows->class_hints == (XClassHint *) NULL) ||
5253  (windows->manager_hints == (XWMHints *) NULL))
5254  ThrowXWindowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed",
5255  "...");
5256  /*
5257  Determine group leader if we have one.
5258  */
5259  root_window=XRootWindow(display,windows->visual_info->screen);
5260  windows->group_leader.id=(Window) NULL;
5261  if (resource_info->window_group != (char *) NULL)
5262  {
5263  if (isdigit((int) ((unsigned char) *resource_info->window_group)) != 0)
5264  windows->group_leader.id=XWindowByID(display,root_window,(Window)
5265  strtol((char *) resource_info->window_group,(char **) NULL,0));
5266  if (windows->group_leader.id == (Window) NULL)
5267  windows->group_leader.id=
5268  XWindowByName(display,root_window,resource_info->window_group);
5269  }
5270  return(windows);
5271 }
5272 
5273 /*
5274 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5275 % %
5276 % %
5277 % %
5278 % X M a k e C u r s o r %
5279 % %
5280 % %
5281 % %
5282 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5283 %
5284 % XMakeCursor() creates a crosshairs X11 cursor.
5285 %
5286 % The format of the XMakeCursor method is:
5287 %
5288 % Cursor XMakeCursor(Display *display,Window window,Colormap colormap,
5289 % char *background_color,char *foreground_color)
5290 %
5291 % A description of each parameter follows:
5292 %
5293 % o display: Specifies a connection to an X server; returned from
5294 % XOpenDisplay.
5295 %
5296 % o window: Specifies the ID of the window for which the cursor is
5297 % assigned.
5298 %
5299 % o colormap: Specifies the ID of the colormap from which the background
5300 % and foreground color will be retrieved.
5301 %
5302 % o background_color: Specifies the color to use for the cursor background.
5303 %
5304 % o foreground_color: Specifies the color to use for the cursor foreground.
5305 %
5306 */
5307 MagickPrivate Cursor XMakeCursor(Display *display,Window window,
5308  Colormap colormap,char *background_color,char *foreground_color)
5309 {
5310 #define scope_height 17
5311 #define scope_x_hot 8
5312 #define scope_y_hot 8
5313 #define scope_width 17
5314 
5315  static const unsigned char
5316  scope_bits[] =
5317  {
5318  0x80, 0x03, 0x00, 0x80, 0x02, 0x00, 0x80, 0x02, 0x00, 0x80, 0x02,
5319  0x00, 0x80, 0x02, 0x00, 0x80, 0x02, 0x00, 0x80, 0x02, 0x00, 0x7f,
5320  0xfc, 0x01, 0x01, 0x00, 0x01, 0x7f, 0xfc, 0x01, 0x80, 0x02, 0x00,
5321  0x80, 0x02, 0x00, 0x80, 0x02, 0x00, 0x80, 0x02, 0x00, 0x80, 0x02,
5322  0x00, 0x80, 0x02, 0x00, 0x80, 0x03, 0x00
5323  },
5324  scope_mask_bits[] =
5325  {
5326  0xc0, 0x07, 0x00, 0xc0, 0x07, 0x00, 0xc0, 0x06, 0x00, 0xc0, 0x06,
5327  0x00, 0xc0, 0x06, 0x00, 0xc0, 0x06, 0x00, 0xff, 0xfe, 0x01, 0x7f,
5328  0xfc, 0x01, 0x03, 0x80, 0x01, 0x7f, 0xfc, 0x01, 0xff, 0xfe, 0x01,
5329  0xc0, 0x06, 0x00, 0xc0, 0x06, 0x00, 0xc0, 0x06, 0x00, 0xc0, 0x06,
5330  0x00, 0xc0, 0x07, 0x00, 0xc0, 0x07, 0x00
5331  };
5332 
5333  Cursor
5334  cursor;
5335 
5336  Pixmap
5337  mask,
5338  source;
5339 
5340  XColor
5341  background,
5342  foreground;
5343 
5344  assert(display != (Display *) NULL);
5345  assert(window != (Window) NULL);
5346  assert(colormap != (Colormap) NULL);
5347  assert(background_color != (char *) NULL);
5348  assert(foreground_color != (char *) NULL);
5349  (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",background_color);
5350  source=XCreateBitmapFromData(display,window,(char *) scope_bits,scope_width,
5351  scope_height);
5352  mask=XCreateBitmapFromData(display,window,(char *) scope_mask_bits,
5353  scope_width,scope_height);
5354  if ((source == (Pixmap) NULL) || (mask == (Pixmap) NULL))
5355  {
5356  ThrowXWindowException(XServerError,"UnableToCreatePixmap","...");
5357  return((Cursor) NULL);
5358  }
5359  (void) XParseColor(display,colormap,background_color,&background);
5360  (void) XParseColor(display,colormap,foreground_color,&foreground);
5361  cursor=XCreatePixmapCursor(display,source,mask,&foreground,&background,
5362  scope_x_hot,scope_y_hot);
5363  (void) XFreePixmap(display,source);
5364  (void) XFreePixmap(display,mask);
5365  return(cursor);
5366 }
5367 
5368 /*
5369 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5370 % %
5371 % %
5372 % %
5373 % X M a k e I m a g e %
5374 % %
5375 % %
5376 % %
5377 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5378 %
5379 % XMakeImage() creates an X11 image. If the image size differs from the X11
5380 % image size, the image is first resized.
5381 %
5382 % The format of the XMakeImage method is:
5383 %
5384 % MagickBooleanType XMakeImage(Display *display,
5385 % const XResourceInfo *resource_info,XWindowInfo *window,Image *image,
5386 % unsigned int width,unsigned int height,ExceptionInfo *exception)
5387 %
5388 % A description of each parameter follows:
5389 %
5390 % o display: Specifies a connection to an X server; returned from
5391 % XOpenDisplay.
5392 %
5393 % o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
5394 %
5395 % o window: Specifies a pointer to a XWindowInfo structure.
5396 %
5397 % o image: the image.
5398 %
5399 % o width: Specifies the width in pixels of the rectangular area to
5400 % display.
5401 %
5402 % o height: Specifies the height in pixels of the rectangular area to
5403 % display.
5404 %
5405 % o exception: return any errors or warnings in this structure.
5406 %
5407 */
5408 MagickPrivate MagickBooleanType XMakeImage(Display *display,
5409  const XResourceInfo *resource_info,XWindowInfo *window,Image *image,
5410  unsigned int width,unsigned int height,ExceptionInfo *exception)
5411 {
5412 #define CheckOverflowException(length,width,height) \
5413  (((height) != 0) && ((length)/((size_t) height) != ((size_t) width)))
5414 
5415  int
5416  depth,
5417  format;
5418 
5419  size_t
5420  length;
5421 
5422  XImage
5423  *matte_image,
5424  *ximage;
5425 
5426  (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
5427  assert(display != (Display *) NULL);
5428  assert(resource_info != (XResourceInfo *) NULL);
5429  assert(window != (XWindowInfo *) NULL);
5430  assert(width != 0);
5431  assert(height != 0);
5432  if ((window->width == 0) || (window->height == 0))
5433  return(MagickFalse);
5434  /*
5435  Apply user transforms to the image.
5436  */
5437  (void) XCheckDefineCursor(display,window->id,window->busy_cursor);
5438  (void) XFlush(display);
5439  depth=(int) window->depth;
5440  if (window->destroy)
5441  window->image=DestroyImage(window->image);
5442  window->image=image;
5443  window->destroy=MagickFalse;
5444  if (window->image != (Image *) NULL)
5445  {
5446  if (window->crop_geometry != (char *) NULL)
5447  {
5448  Image
5449  *crop_image;
5450 
5452  crop_info;
5453 
5454  /*
5455  Crop image.
5456  */
5457  window->image->page.x=0;
5458  window->image->page.y=0;
5459  (void) ParsePageGeometry(window->image,window->crop_geometry,
5460  &crop_info,exception);
5461  crop_image=CropImage(window->image,&crop_info,exception);
5462  if (crop_image != (Image *) NULL)
5463  {
5464  if (window->image != image)
5465  window->image=DestroyImage(window->image);
5466  window->image=crop_image;
5467  window->destroy=MagickTrue;
5468  }
5469  }
5470  if ((width != (unsigned int) window->image->columns) ||
5471  (height != (unsigned int) window->image->rows))
5472  {
5473  Image
5474  *resize_image;
5475 
5476  /*
5477  Resize image.
5478  */
5479  resize_image=NewImageList();
5480  if ((window->pixel_info->colors == 0) &&
5481  (window->image->rows > (unsigned long) XDisplayHeight(display,window->screen)) &&
5482  (window->image->columns > (unsigned long) XDisplayWidth(display,window->screen)))
5483  resize_image=ResizeImage(window->image,width,height,
5484  image->filter,exception);
5485  else
5486  {
5487  if (window->image->storage_class == PseudoClass)
5488  resize_image=SampleImage(window->image,width,height,
5489  exception);
5490  else
5491  resize_image=ThumbnailImage(window->image,width,height,
5492  exception);
5493  }
5494  if (resize_image != (Image *) NULL)
5495  {
5496  if (window->image != image)
5497  window->image=DestroyImage(window->image);
5498  window->image=resize_image;
5499  window->destroy=MagickTrue;
5500  }
5501  }
5502  width=(unsigned int) window->image->columns;
5503  assert((size_t) width == window->image->columns);
5504  height=(unsigned int) window->image->rows;
5505  assert((size_t) height == window->image->rows);
5506  }
5507  /*
5508  Create X image.
5509  */
5510  ximage=(XImage *) NULL;
5511  format=(depth == 1) ? XYBitmap : ZPixmap;
5512 #if defined(MAGICKCORE_HAVE_SHARED_MEMORY)
5513  if (window->shared_memory != MagickFalse)
5514  {
5515  XShmSegmentInfo
5516  *segment_info;
5517 
5518  segment_info=(XShmSegmentInfo *) window->segment_info;
5519  segment_info[1].shmid=(-1);
5520  segment_info[1].shmaddr=(char *) NULL;
5521  ximage=XShmCreateImage(display,window->visual,(unsigned int) depth,format,
5522  (char *) NULL,&segment_info[1],width,height);
5523  length=0;
5524  if (ximage == (XImage *) NULL)
5525  window->shared_memory=MagickFalse;
5526  else
5527  {
5528  length=(size_t) ximage->bytes_per_line*ximage->height;
5529  if (CheckOverflowException(length,ximage->bytes_per_line,ximage->height))
5530  window->shared_memory=MagickFalse;
5531  }
5532  if (window->shared_memory != MagickFalse)
5533  segment_info[1].shmid=shmget(IPC_PRIVATE,length,IPC_CREAT | 0777);
5534  if (window->shared_memory != MagickFalse)
5535  segment_info[1].shmaddr=(char *) shmat(segment_info[1].shmid,0,0);
5536  if (segment_info[1].shmid < 0)
5537  window->shared_memory=MagickFalse;
5538  if (window->shared_memory != MagickFalse)
5539  (void) shmctl(segment_info[1].shmid,IPC_RMID,0);
5540  else
5541  {
5542  if (ximage != (XImage *) NULL)
5543  XDestroyImage(ximage);
5544  ximage=(XImage *) NULL;
5545  if (segment_info[1].shmaddr)
5546  {
5547  (void) shmdt(segment_info[1].shmaddr);
5548  segment_info[1].shmaddr=(char *) NULL;
5549  }
5550  if (segment_info[1].shmid >= 0)
5551  {
5552  (void) shmctl(segment_info[1].shmid,IPC_RMID,0);
5553  segment_info[1].shmid=(-1);
5554  }
5555  }
5556  }
5557 #endif
5558  /*
5559  Allocate X image pixel data.
5560  */
5561 #if defined(MAGICKCORE_HAVE_SHARED_MEMORY)
5562  if (window->shared_memory)
5563  {
5564  Status
5565  status;
5566 
5567  XShmSegmentInfo
5568  *segment_info;
5569 
5570  (void) XSync(display,MagickFalse);
5571  xerror_alert=MagickFalse;
5572  segment_info=(XShmSegmentInfo *) window->segment_info;
5573  ximage->data=segment_info[1].shmaddr;
5574  segment_info[1].readOnly=MagickFalse;
5575  status=XShmAttach(display,&segment_info[1]);
5576  if (status != False)
5577  (void) XSync(display,MagickFalse);
5578  if ((status == False) || (xerror_alert != MagickFalse))
5579  {
5580  window->shared_memory=MagickFalse;
5581  if (status != False)
5582  XShmDetach(display,&segment_info[1]);
5583  ximage->data=NULL;
5584  XDestroyImage(ximage);
5585  ximage=(XImage *) NULL;
5586  if (segment_info[1].shmid >= 0)
5587  {
5588  if (segment_info[1].shmaddr != NULL)
5589  (void) shmdt(segment_info[1].shmaddr);
5590  (void) shmctl(segment_info[1].shmid,IPC_RMID,0);
5591  segment_info[1].shmid=(-1);
5592  segment_info[1].shmaddr=(char *) NULL;
5593  }
5594  }
5595  }
5596 #endif
5597  if (window->shared_memory == MagickFalse)
5598  ximage=XCreateImage(display,window->visual,(unsigned int) depth,format,0,
5599  (char *) NULL,width,height,XBitmapPad(display),0);
5600  if (ximage == (XImage *) NULL)
5601  {
5602  /*
5603  Unable to create X image.
5604  */
5605  (void) XCheckDefineCursor(display,window->id,window->cursor);
5606  return(MagickFalse);
5607  }
5608  length=(size_t) ximage->bytes_per_line*ximage->height;
5609  if (IsEventLogging())
5610  {
5611  (void) LogMagickEvent(X11Event,GetMagickModule(),"XImage:");
5612  (void) LogMagickEvent(X11Event,GetMagickModule()," width, height: %dx%d",
5613  ximage->width,ximage->height);
5614  (void) LogMagickEvent(X11Event,GetMagickModule()," format: %d",
5615  ximage->format);
5616  (void) LogMagickEvent(X11Event,GetMagickModule()," byte order: %d",
5617  ximage->byte_order);
5619  " bitmap unit, bit order, pad: %d %d %d",ximage->bitmap_unit,
5620  ximage->bitmap_bit_order,ximage->bitmap_pad);
5621  (void) LogMagickEvent(X11Event,GetMagickModule()," depth: %d",
5622  ximage->depth);
5623  (void) LogMagickEvent(X11Event,GetMagickModule()," bytes per line: %d",
5624  ximage->bytes_per_line);
5625  (void) LogMagickEvent(X11Event,GetMagickModule()," bits per pixel: %d",
5626  ximage->bits_per_pixel);
5628  " red, green, blue masks: 0x%lx 0x%lx 0x%lx",ximage->red_mask,
5629  ximage->green_mask,ximage->blue_mask);
5630  }
5631  if (window->shared_memory == MagickFalse)
5632  {
5633  if (ximage->format == XYBitmap)
5634  {
5635  ximage->data=(char *) AcquireQuantumMemory((size_t)
5636  ximage->bytes_per_line,(size_t) ximage->depth*ximage->height);
5637  if (ximage->data != (char *) NULL)
5638  (void) memset(ximage->data,0,(size_t)
5639  ximage->bytes_per_line*ximage->depth*ximage->height);
5640  }
5641  else
5642  {
5643  ximage->data=(char *) AcquireQuantumMemory((size_t)
5644  ximage->bytes_per_line,(size_t) ximage->height);
5645  if (ximage->data != (char *) NULL)
5646  (void) memset(ximage->data,0,(size_t)
5647  ximage->bytes_per_line*ximage->height);
5648  }
5649  }
5650  if (ximage->data == (char *) NULL)
5651  {
5652  /*
5653  Unable to allocate pixel data.
5654  */
5655  XDestroyImage(ximage);
5656  ximage=(XImage *) NULL;
5657  (void) XCheckDefineCursor(display,window->id,window->cursor);
5658  return(MagickFalse);
5659  }
5660  if (window->ximage != (XImage *) NULL)
5661  {
5662  /*
5663  Destroy previous X image.
5664  */
5665  length=(size_t) window->ximage->bytes_per_line*window->ximage->height;
5666 #if defined(MAGICKCORE_HAVE_SHARED_MEMORY)
5667  if (window->segment_info != (XShmSegmentInfo *) NULL)
5668  {
5669  XShmSegmentInfo
5670  *segment_info;
5671 
5672  segment_info=(XShmSegmentInfo *) window->segment_info;
5673  if (segment_info[0].shmid >= 0)
5674  {
5675  (void) XSync(display,MagickFalse);
5676  (void) XShmDetach(display,&segment_info[0]);
5677  (void) XSync(display,MagickFalse);
5678  if (segment_info[0].shmaddr != (char *) NULL)
5679  (void) shmdt(segment_info[0].shmaddr);
5680  (void) shmctl(segment_info[0].shmid,IPC_RMID,0);
5681  segment_info[0].shmid=(-1);
5682  segment_info[0].shmaddr=(char *) NULL;
5683  window->ximage->data=(char *) NULL;
5684  }
5685  }
5686 #endif
5687  if (window->ximage->data != (char *) NULL)
5688  free(window->ximage->data);
5689  window->ximage->data=(char *) NULL;
5690  XDestroyImage(window->ximage);
5691  window->ximage=(XImage *) NULL;
5692  }
5693 #if defined(MAGICKCORE_HAVE_SHARED_MEMORY)
5694  if (window->segment_info != (XShmSegmentInfo *) NULL)
5695  {
5696  XShmSegmentInfo
5697  *segment_info;
5698 
5699  segment_info=(XShmSegmentInfo *) window->segment_info;
5700  segment_info[0]=segment_info[1];
5701  }
5702 #endif
5703  window->ximage=ximage;
5704  matte_image=(XImage *) NULL;
5705  if ((window->shape != MagickFalse) && (window->image != (Image *) NULL))
5706  if ((window->image->alpha_trait != UndefinedPixelTrait) &&
5707  ((int) width <= XDisplayWidth(display,window->screen)) &&
5708  ((int) height <= XDisplayHeight(display,window->screen)))
5709  {
5710  /*
5711  Create matte image.
5712  */
5713  matte_image=XCreateImage(display,window->visual,1,XYBitmap,0,
5714  (char *) NULL,width,height,XBitmapPad(display),0);
5715  if (IsEventLogging())
5716  {
5717  (void) LogMagickEvent(X11Event,GetMagickModule(),"Matte Image:");
5719  " width, height: %dx%d",matte_image->width,matte_image->height);
5720  }
5721  if (matte_image != (XImage *) NULL)
5722  {
5723  /*
5724  Allocate matte image pixel data.
5725  */
5726  matte_image->data=(char *) malloc((size_t)
5727  matte_image->bytes_per_line*matte_image->depth*
5728  matte_image->height);
5729  if (matte_image->data == (char *) NULL)
5730  {
5731  XDestroyImage(matte_image);
5732  matte_image=(XImage *) NULL;
5733  }
5734  }
5735  }
5736  if (window->matte_image != (XImage *) NULL)
5737  {
5738  /*
5739  Free matte image.
5740  */
5741  if (window->matte_image->data != (char *) NULL)
5742  free(window->matte_image->data);
5743  window->matte_image->data=(char *) NULL;
5744  XDestroyImage(window->matte_image);
5745  window->matte_image=(XImage *) NULL;
5746  }
5747  window->matte_image=matte_image;
5748  if (window->matte_pixmap != (Pixmap) NULL)
5749  {
5750  (void) XFreePixmap(display,window->matte_pixmap);
5751  window->matte_pixmap=(Pixmap) NULL;
5752 #if defined(MAGICKCORE_HAVE_SHAPE)
5753  if (window->shape != MagickFalse)
5754  XShapeCombineMask(display,window->id,ShapeBounding,0,0,None,ShapeSet);
5755 #endif
5756  }
5757  window->stasis=MagickFalse;
5758  /*
5759  Convert pixels to X image data.
5760  */
5761  if (window->image != (Image *) NULL)
5762  {
5763  if ((ximage->byte_order == LSBFirst) || ((ximage->format == XYBitmap) &&
5764  (ximage->bitmap_bit_order == LSBFirst)))
5765  XMakeImageLSBFirst(resource_info,window,window->image,ximage,
5766  matte_image,exception);
5767  else
5768  XMakeImageMSBFirst(resource_info,window,window->image,ximage,
5769  matte_image,exception);
5770  }
5771  if (window->matte_image != (XImage *) NULL)
5772  {
5773  /*
5774  Create matte pixmap.
5775  */
5776  window->matte_pixmap=XCreatePixmap(display,window->id,width,height,1);
5777  if (window->matte_pixmap != (Pixmap) NULL)
5778  {
5779  GC
5780  graphics_context;
5781 
5782  XGCValues
5783  context_values;
5784 
5785  /*
5786  Copy matte image to matte pixmap.
5787  */
5788  context_values.background=0;
5789  context_values.foreground=1;
5790  graphics_context=XCreateGC(display,window->matte_pixmap,
5791  (size_t) (GCBackground | GCForeground),&context_values);
5792  (void) XPutImage(display,window->matte_pixmap,graphics_context,
5793  window->matte_image,0,0,0,0,width,height);
5794  (void) XFreeGC(display,graphics_context);
5795 #if defined(MAGICKCORE_HAVE_SHAPE)
5796  if (window->shape != MagickFalse)
5797  XShapeCombineMask(display,window->id,ShapeBounding,0,0,
5798  window->matte_pixmap,ShapeSet);
5799 #endif
5800  }
5801  }
5802  (void) XMakePixmap(display,resource_info,window);
5803  /*
5804  Restore cursor.
5805  */
5806  (void) XCheckDefineCursor(display,window->id,window->cursor);
5807  return(MagickTrue);
5808 }
5809 
5810 /*
5811 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5812 % %
5813 % %
5814 % %
5815 + X M a k e I m a g e L S B F i r s t %
5816 % %
5817 % %
5818 % %
5819 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5820 %
5821 % XMakeImageLSBFirst() initializes the pixel data of an X11 Image. The X image
5822 % pixels are copied in least-significant bit and byte first order. The
5823 % server's scanline pad is respected. Rather than using one or two general
5824 % cases, many special cases are found here to help speed up the image
5825 % conversion.
5826 %
5827 % The format of the XMakeImageLSBFirst method is:
5828 %
5829 % void XMakeImageLSBFirst(Display *display,XWindows *windows,
5830 % ExceptionInfo *exception)
5831 %
5832 % A description of each parameter follows:
5833 %
5834 % o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
5835 %
5836 % o window: Specifies a pointer to a XWindowInfo structure.
5837 %
5838 % o image: the image.
5839 %
5840 % o ximage: Specifies a pointer to a XImage structure; returned from
5841 % XCreateImage.
5842 %
5843 % o matte_image: Specifies a pointer to a XImage structure; returned from
5844 % XCreateImage.
5845 %
5846 % o exception: return any errors or warnings in this structure.
5847 %
5848 */
5849 static void XMakeImageLSBFirst(const XResourceInfo *resource_info,
5850  const XWindowInfo *window,Image *image,XImage *ximage,XImage *matte_image,
5851  ExceptionInfo *exception)
5852 {
5853  CacheView
5854  *canvas_view;
5855 
5856  Image
5857  *canvas;
5858 
5859  int
5860  y;
5861 
5862  register const Quantum
5863  *p;
5864 
5865  register int
5866  x;
5867 
5868  register unsigned char
5869  *q;
5870 
5871  unsigned char
5872  bit,
5873  byte;
5874 
5875  unsigned int
5876  scanline_pad;
5877 
5878  unsigned long
5879  pixel,
5880  *pixels;
5881 
5882  XStandardColormap
5883  *map_info;
5884 
5885  assert(resource_info != (XResourceInfo *) NULL);
5886  assert(window != (XWindowInfo *) NULL);
5887  assert(image != (Image *) NULL);
5888  if (image->debug != MagickFalse)
5889  (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
5890  canvas=image;
5891  if ((window->immutable == MagickFalse) &&
5892  (image->storage_class == DirectClass) &&
5893  (image->alpha_trait != UndefinedPixelTrait))
5894  {
5895  char
5896  size[MagickPathExtent];
5897 
5898  Image
5899  *pattern;
5900 
5901  ImageInfo
5902  *image_info;
5903 
5904  image_info=AcquireImageInfo();
5905  (void) CopyMagickString(image_info->filename,
5906  resource_info->image_info->texture != (char *) NULL ?
5907  resource_info->image_info->texture : "pattern:checkerboard",
5909  (void) FormatLocaleString(size,MagickPathExtent,"%.20gx%.20g",(double)
5910  image->columns,(double) image->rows);
5911  image_info->size=ConstantString(size);
5912  pattern=ReadImage(image_info,exception);
5913  image_info=DestroyImageInfo(image_info);
5914  if (pattern != (Image *) NULL)
5915  {
5916  canvas=CloneImage(image,0,0,MagickTrue,exception);
5917  if (canvas != (Image *) NULL)
5918  (void) CompositeImage(canvas,pattern,DstOverCompositeOp,MagickTrue,
5919  0,0,exception);
5920  pattern=DestroyImage(pattern);
5921  }
5922  }
5923  scanline_pad=(unsigned int) (ximage->bytes_per_line-((ximage->width*
5924  ximage->bits_per_pixel) >> 3));
5925  map_info=window->map_info;
5926  pixels=window->pixel_info->pixels;
5927  q=(unsigned char *) ximage->data;
5928  x=0;
5929  canvas_view=AcquireVirtualCacheView(canvas,exception);
5930  if (ximage->format == XYBitmap)
5931  {
5932  register unsigned short
5933  polarity;
5934 
5935  unsigned char
5936  background,
5937  foreground;
5938 
5939  /*
5940  Convert canvas to big-endian bitmap.
5941  */
5942  background=(unsigned char)
5943  (XPixelIntensity(&window->pixel_info->foreground_color) <
5944  XPixelIntensity(&window->pixel_info->background_color) ? 0x80 : 0x00);
5945  foreground=(unsigned char)
5946  (XPixelIntensity(&window->pixel_info->background_color) <
5947  XPixelIntensity(&window->pixel_info->foreground_color) ? 0x80 : 0x00);
5948  polarity=(unsigned short) ((GetPixelInfoIntensity(image,
5949  &canvas->colormap[0])) < (QuantumRange/2.0) ? 1 : 0);
5950  if (canvas->colors == 2)
5951  polarity=GetPixelInfoIntensity(image,&canvas->colormap[0]) <
5952  GetPixelInfoIntensity(image,&canvas->colormap[1]);
5953  for (y=0; y < (int) canvas->rows; y++)
5954  {
5955  p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,canvas->columns,1,
5956  exception);
5957  if (p == (const Quantum *) NULL)
5958  break;
5959  bit=0;
5960  byte=0;
5961  for (x=0; x < (int) canvas->columns; x++)
5962  {
5963  byte>>=1;
5964  if (GetPixelIndex(canvas,p) == (Quantum) polarity)
5965  byte|=foreground;
5966  else
5967  byte|=background;
5968  bit++;
5969  if (bit == 8)
5970  {
5971  *q++=byte;
5972  bit=0;
5973  byte=0;
5974  }
5975  p+=GetPixelChannels(canvas);
5976  }
5977  if (bit != 0)
5978  *q=byte >> (8-bit);
5979  q+=scanline_pad;
5980  }
5981  }
5982  else
5983  if (window->pixel_info->colors != 0)
5984  switch (ximage->bits_per_pixel)
5985  {
5986  case 2:
5987  {
5988  register unsigned int
5989  nibble;
5990 
5991  /*
5992  Convert to 2 bit color-mapped X canvas.
5993  */
5994  for (y=0; y < (int) canvas->rows; y++)
5995  {
5996  p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
5997  canvas->columns,1,exception);
5998  if (p == (const Quantum *) NULL)
5999  break;
6000  nibble=0;
6001  for (x=0; x < (int) canvas->columns; x++)
6002  {
6003  pixel=pixels[(ssize_t) GetPixelIndex(canvas,p)] & 0x0f;
6004  switch (nibble)
6005  {
6006  case 0:
6007  {
6008  *q=(unsigned char) pixel;
6009  nibble++;
6010  break;
6011  }
6012  case 1:
6013  {
6014  *q|=(unsigned char) (pixel << 2);
6015  nibble++;
6016  break;
6017  }
6018  case 2:
6019  {
6020  *q|=(unsigned char) (pixel << 4);
6021  nibble++;
6022  break;
6023  }
6024  case 3:
6025  {
6026  *q|=(unsigned char) (pixel << 6);
6027  q++;
6028  nibble=0;
6029  break;
6030  }
6031  }
6032  p+=GetPixelChannels(canvas);
6033  }
6034  q+=scanline_pad;
6035  }
6036  break;
6037  }
6038  case 4:
6039  {
6040  register unsigned int
6041  nibble;
6042 
6043  /*
6044  Convert to 4 bit color-mapped X canvas.
6045  */
6046  for (y=0; y < (int) canvas->rows; y++)
6047  {
6048  p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
6049  canvas->columns,1,exception);
6050  if (p == (const Quantum *) NULL)
6051  break;
6052  nibble=0;
6053  for (x=0; x < (int) canvas->columns; x++)
6054  {
6055  pixel=pixels[(ssize_t) GetPixelIndex(canvas,p)] & 0xf;
6056  switch (nibble)
6057  {
6058  case 0:
6059  {
6060  *q=(unsigned char) pixel;
6061  nibble++;
6062  break;
6063  }
6064  case 1:
6065  {
6066  *q|=(unsigned char) (pixel << 4);
6067  q++;
6068  nibble=0;
6069  break;
6070  }
6071  }
6072  p+=GetPixelChannels(canvas);
6073  }
6074  q+=scanline_pad;
6075  }
6076  break;
6077  }
6078  case 6:
6079  case 8:
6080  {
6081  /*
6082  Convert to 8 bit color-mapped X canvas.
6083  */
6084  if (resource_info->color_recovery &&
6085  resource_info->quantize_info->dither_method != NoDitherMethod)
6086  {
6087  XDitherImage(canvas,ximage,exception);
6088  break;
6089  }
6090  for (y=0; y < (int) canvas->rows; y++)
6091  {
6092  p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
6093  canvas->columns,1,exception);
6094  if (p == (const Quantum *) NULL)
6095  break;
6096  for (x=0; x < (int) canvas->columns; x++)
6097  {
6098  pixel=pixels[(ssize_t) GetPixelIndex(canvas,p)];
6099  *q++=(unsigned char) pixel;
6100  p+=GetPixelChannels(canvas);
6101  }
6102  q+=scanline_pad;
6103  }
6104  break;
6105  }
6106  default:
6107  {
6108  register int
6109  k;
6110 
6111  register unsigned int
6112  bytes_per_pixel;
6113 
6114  /*
6115  Convert to multi-byte color-mapped X canvas.
6116  */
6117  bytes_per_pixel=(unsigned int) (ximage->bits_per_pixel >> 3);
6118  for (y=0; y < (int) canvas->rows; y++)
6119  {
6120  p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
6121  canvas->columns,1,exception);
6122  if (p == (const Quantum *) NULL)
6123  break;
6124  for (x=0; x < (int) canvas->columns; x++)
6125  {
6126  pixel=pixels[(ssize_t) GetPixelIndex(canvas,p)];
6127  for (k=0; k < (int) bytes_per_pixel; k++)
6128  {
6129  *q++=(unsigned char) (pixel & 0xff);
6130  pixel>>=8;
6131  }
6132  p+=GetPixelChannels(canvas);
6133  }
6134  q+=scanline_pad;
6135  }
6136  break;
6137  }
6138  }
6139  else
6140  switch (ximage->bits_per_pixel)
6141  {
6142  case 2:
6143  {
6144  register unsigned int
6145  nibble;
6146 
6147  /*
6148  Convert to contiguous 2 bit continuous-tone X canvas.
6149  */
6150  for (y=0; y < (int) canvas->rows; y++)
6151  {
6152  nibble=0;
6153  p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
6154  canvas->columns,1,exception);
6155  if (p == (const Quantum *) NULL)
6156  break;
6157  for (x=0; x < (int) canvas->columns; x++)
6158  {
6159  pixel=XGammaPixel(canvas,map_info,p);
6160  pixel&=0xf;
6161  switch (nibble)
6162  {
6163  case 0:
6164  {
6165  *q=(unsigned char) pixel;
6166  nibble++;
6167  break;
6168  }
6169  case 1:
6170  {
6171  *q|=(unsigned char) (pixel << 2);
6172  nibble++;
6173  break;
6174  }
6175  case 2:
6176  {
6177  *q|=(unsigned char) (pixel << 4);
6178  nibble++;
6179  break;
6180  }
6181  case 3:
6182  {
6183  *q|=(unsigned char) (pixel << 6);
6184  q++;
6185  nibble=0;
6186  break;
6187  }
6188  }
6189  p+=GetPixelChannels(canvas);
6190  }
6191  q+=scanline_pad;
6192  }
6193  break;
6194  }
6195  case 4:
6196  {
6197  register unsigned int
6198  nibble;
6199 
6200  /*
6201  Convert to contiguous 4 bit continuous-tone X canvas.
6202  */
6203  for (y=0; y < (int) canvas->rows; y++)
6204  {
6205  p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
6206  canvas->columns,1,exception);
6207  if (p == (const Quantum *) NULL)
6208  break;
6209  nibble=0;
6210  for (x=0; x < (int) canvas->columns; x++)
6211  {
6212  pixel=XGammaPixel(canvas,map_info,p);
6213  pixel&=0xf;
6214  switch (nibble)
6215  {
6216  case 0:
6217  {
6218  *q=(unsigned char) pixel;
6219  nibble++;
6220  break;
6221  }
6222  case 1:
6223  {
6224  *q|=(unsigned char) (pixel << 4);
6225  q++;
6226  nibble=0;
6227  break;
6228  }
6229  }
6230  p+=GetPixelChannels(canvas);
6231  }
6232  q+=scanline_pad;
6233  }
6234  break;
6235  }
6236  case 6:
6237  case 8:
6238  {
6239  /*
6240  Convert to contiguous 8 bit continuous-tone X canvas.
6241  */
6242  if (resource_info->color_recovery &&
6243  resource_info->quantize_info->dither_method != NoDitherMethod)
6244  {
6245  XDitherImage(canvas,ximage,exception);
6246  break;
6247  }
6248  for (y=0; y < (int) canvas->rows; y++)
6249  {
6250  p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
6251  canvas->columns,1,exception);
6252  if (p == (const Quantum *) NULL)
6253  break;
6254  for (x=0; x < (int) canvas->columns; x++)
6255  {
6256  pixel=XGammaPixel(canvas,map_info,p);
6257  *q++=(unsigned char) pixel;
6258  p+=GetPixelChannels(canvas);
6259  }
6260  q+=scanline_pad;
6261  }
6262  break;
6263  }
6264  default:
6265  {
6266  if ((ximage->bits_per_pixel == 32) && (map_info->red_max == 255) &&
6267  (map_info->green_max == 255) && (map_info->blue_max == 255) &&
6268  (map_info->red_mult == 65536L) && (map_info->green_mult == 256) &&
6269  (map_info->blue_mult == 1))
6270  {
6271  /*
6272  Convert to 32 bit continuous-tone X canvas.
6273  */
6274  for (y=0; y < (int) canvas->rows; y++)
6275  {
6276  p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
6277  canvas->columns,1,exception);
6278  if (p == (const Quantum *) NULL)
6279  break;
6280  if ((red_gamma != 1.0) || (green_gamma != 1.0) ||
6281  (blue_gamma != 1.0))
6282  {
6283  /*
6284  Gamma correct canvas.
6285  */
6286  for (x=(int) canvas->columns-1; x >= 0; x--)
6287  {
6288  *q++=ScaleQuantumToChar(XBlueGamma(
6289  GetPixelBlue(canvas,p)));
6290  *q++=ScaleQuantumToChar(XGreenGamma(
6291  GetPixelGreen(canvas,p)));
6292  *q++=ScaleQuantumToChar(XRedGamma(
6293  GetPixelRed(canvas,p)));
6294  *q++=0;
6295  p+=GetPixelChannels(canvas);
6296  }
6297  continue;
6298  }
6299  for (x=(int) canvas->columns-1; x >= 0; x--)
6300  {
6301  *q++=ScaleQuantumToChar((Quantum) GetPixelBlue(canvas,p));
6302  *q++=ScaleQuantumToChar((Quantum) GetPixelGreen(canvas,p));
6303  *q++=ScaleQuantumToChar((Quantum) GetPixelRed(canvas,p));
6304  *q++=0;
6305  p+=GetPixelChannels(canvas);
6306  }
6307  }
6308  }
6309  else
6310  if ((ximage->bits_per_pixel == 32) && (map_info->red_max == 255) &&
6311  (map_info->green_max == 255) && (map_info->blue_max == 255) &&
6312  (map_info->red_mult == 1) && (map_info->green_mult == 256) &&
6313  (map_info->blue_mult == 65536L))
6314  {
6315  /*
6316  Convert to 32 bit continuous-tone X canvas.
6317  */
6318  for (y=0; y < (int) canvas->rows; y++)
6319  {
6320  p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
6321  canvas->columns,1,exception);
6322  if (p == (const Quantum *) NULL)
6323  break;
6324  if ((red_gamma != 1.0) || (green_gamma != 1.0) ||
6325  (blue_gamma != 1.0))
6326  {
6327  /*
6328  Gamma correct canvas.
6329  */
6330  for (x=(int) canvas->columns-1; x >= 0; x--)
6331  {
6332  *q++=ScaleQuantumToChar(XRedGamma(
6333  GetPixelRed(canvas,p)));
6334  *q++=ScaleQuantumToChar(XGreenGamma(
6335  GetPixelGreen(canvas,p)));
6336  *q++=ScaleQuantumToChar(XBlueGamma(
6337  GetPixelBlue(canvas,p)));
6338  *q++=0;
6339  p+=GetPixelChannels(canvas);
6340  }
6341  continue;
6342  }
6343  for (x=(int) canvas->columns-1; x >= 0; x--)
6344  {
6345  *q++=ScaleQuantumToChar((Quantum) GetPixelRed(canvas,p));
6346  *q++=ScaleQuantumToChar((Quantum) GetPixelGreen(canvas,p));
6347  *q++=ScaleQuantumToChar((Quantum) GetPixelBlue(canvas,p));
6348  *q++=0;
6349  p+=GetPixelChannels(canvas);
6350  }
6351  }
6352  }
6353  else
6354  {
6355  register int
6356  k;
6357 
6358  register unsigned int
6359  bytes_per_pixel;
6360 
6361  /*
6362  Convert to multi-byte continuous-tone X canvas.
6363  */
6364  bytes_per_pixel=(unsigned int) (ximage->bits_per_pixel >> 3);
6365  for (y=0; y < (int) canvas->rows; y++)
6366  {
6367  p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
6368  canvas->columns,1,exception);
6369  if (p == (const Quantum *) NULL)
6370  break;
6371  for (x=0; x < (int) canvas->columns; x++)
6372  {
6373  pixel=XGammaPixel(canvas,map_info,p);
6374  for (k=0; k < (int) bytes_per_pixel; k++)
6375  {
6376  *q++=(unsigned char) (pixel & 0xff);
6377  pixel>>=8;
6378  }
6379  p+=GetPixelChannels(canvas);
6380  }
6381  q+=scanline_pad;
6382  }
6383  }
6384  break;
6385  }
6386  }
6387  if (matte_image != (XImage *) NULL)
6388  {
6389  /*
6390  Initialize matte canvas.
6391  */
6392  scanline_pad=(unsigned int) (matte_image->bytes_per_line-
6393  ((matte_image->width*matte_image->bits_per_pixel) >> 3));
6394  q=(unsigned char *) matte_image->data;
6395  for (y=0; y < (int) canvas->rows; y++)
6396  {
6397  p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,canvas->columns,1,
6398  exception);
6399  if (p == (const Quantum *) NULL)
6400  break;
6401  bit=0;
6402  byte=0;
6403  for (x=(int) canvas->columns-1; x >= 0; x--)
6404  {
6405  byte>>=1;
6406  if (GetPixelAlpha(canvas,p) > (QuantumRange/2))
6407  byte|=0x80;
6408  bit++;
6409  if (bit == 8)
6410  {
6411  *q++=byte;
6412  bit=0;
6413  byte=0;
6414  }
6415  p+=GetPixelChannels(canvas);
6416  }
6417  if (bit != 0)
6418  *q=byte >> (8-bit);
6419  q+=scanline_pad;
6420  }
6421  }
6422  canvas_view=DestroyCacheView(canvas_view);
6423  if (canvas != image)
6424  canvas=DestroyImage(canvas);
6425 }
6426 
6427 /*
6428 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
6429 % %
6430 % %
6431 % %
6432 + X M a k e I m a g e M S B F i r s t %
6433 % %
6434 % %
6435 % %
6436 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
6437 %
6438 % XMakeImageMSBFirst() initializes the pixel data of an X11 Image. The X
6439 % image pixels are copied in most-significant bit and byte first order. The
6440 % server's scanline pad is also respected. Rather than using one or two
6441 % general cases, many special cases are found here to help speed up the image
6442 % conversion.
6443 %
6444 % The format of the XMakeImageMSBFirst method is:
6445 %
6446 % XMakeImageMSBFirst(resource_info,window,image,ximage,matte_image,
6447 % ExceptionInfo *exception)
6448 %
6449 % A description of each parameter follows:
6450 %
6451 % o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
6452 %
6453 % o window: Specifies a pointer to a XWindowInfo structure.
6454 %
6455 % o image: the image.
6456 %
6457 % o ximage: Specifies a pointer to a XImage structure; returned from
6458 % XCreateImage.
6459 %
6460 % o matte_image: Specifies a pointer to a XImage structure; returned from
6461 % XCreateImage.
6462 %
6463 % o exception: return any errors or warnings in this structure.
6464 %
6465 */
6466 static void XMakeImageMSBFirst(const XResourceInfo *resource_info,
6467  const XWindowInfo *window,Image *image,XImage *ximage,XImage *matte_image,
6468  ExceptionInfo *exception)
6469 {
6470  CacheView
6471  *canvas_view;
6472 
6473  Image
6474  *canvas;
6475 
6476  int
6477  y;
6478 
6479  register int
6480  x;
6481 
6482  register const Quantum
6483  *p;
6484 
6485  register unsigned char
6486  *q;
6487 
6488  unsigned char
6489  bit,
6490  byte;
6491 
6492  unsigned int
6493  scanline_pad;
6494 
6495  unsigned long
6496  pixel,
6497  *pixels;
6498 
6499  XStandardColormap
6500  *map_info;
6501 
6502  assert(resource_info != (XResourceInfo *) NULL);
6503  assert(window != (XWindowInfo *) NULL);
6504  assert(image != (Image *) NULL);
6505  if (image->debug != MagickFalse)
6506  (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
6507  canvas=image;
6508  if ((window->immutable != MagickFalse) &&
6509  (image->storage_class == DirectClass) &&
6510  (image->alpha_trait != UndefinedPixelTrait))
6511  {
6512  char
6513  size[MagickPathExtent];
6514 
6515  Image
6516  *pattern;
6517 
6518  ImageInfo
6519  *image_info;
6520 
6521  image_info=AcquireImageInfo();
6522  (void) CopyMagickString(image_info->filename,
6523  resource_info->image_info->texture != (char *) NULL ?
6524  resource_info->image_info->texture : "pattern:checkerboard",
6526  (void) FormatLocaleString(size,MagickPathExtent,"%.20gx%.20g",(double)
6527  image->columns,(double) image->rows);
6528  image_info->size=ConstantString(size);
6529  pattern=ReadImage(image_info,exception);
6530  image_info=DestroyImageInfo(image_info);
6531  if (pattern != (Image *) NULL)
6532  {
6533  canvas=CloneImage(image,0,0,MagickTrue,exception);
6534  if (canvas != (Image *) NULL)
6535  (void) CompositeImage(canvas,pattern,DstOverCompositeOp,MagickFalse,
6536  0,0,exception);
6537  pattern=DestroyImage(pattern);
6538  }
6539  }
6540  scanline_pad=(unsigned int) (ximage->bytes_per_line-((ximage->width*
6541  ximage->bits_per_pixel) >> 3));
6542  map_info=window->map_info;
6543  pixels=window->pixel_info->pixels;
6544  q=(unsigned char *) ximage->data;
6545  x=0;
6546  canvas_view=AcquireVirtualCacheView(canvas,exception);
6547  if (ximage->format == XYBitmap)
6548  {
6549  register unsigned short
6550  polarity;
6551 
6552  unsigned char
6553  background,
6554  foreground;
6555 
6556  /*
6557  Convert canvas to big-endian bitmap.
6558  */
6559  background=(unsigned char)
6560  (XPixelIntensity(&window->pixel_info->foreground_color) <
6561  XPixelIntensity(&window->pixel_info->background_color) ? 0x01 : 0x00);
6562  foreground=(unsigned char)
6563  (XPixelIntensity(&window->pixel_info->background_color) <
6564  XPixelIntensity(&window->pixel_info->foreground_color) ? 0x01 : 0x00);
6565  polarity=(unsigned short) ((GetPixelInfoIntensity(image,
6566  &canvas->colormap[0])) < (QuantumRange/2.0) ? 1 : 0);
6567  if (canvas->colors == 2)