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