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  (void) memset(&client_event,0,sizeof(client_event));
1556  client_event.type=ClientMessage;
1557  client_event.window=window;
1558  client_event.message_type=protocol;
1559  client_event.format=32;
1560  client_event.data.l[0]=(long) reason;
1561  client_event.data.l[1]=(long) timestamp;
1562  (void) XSendEvent(display,window,MagickFalse,NoEventMask,(XEvent *)
1563  &client_event);
1564 }
1565 
1566 /*
1567 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1568 % %
1569 % %
1570 % %
1571 + X C l i e n t W i n d o w %
1572 % %
1573 % %
1574 % %
1575 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1576 %
1577 % XClientWindow() finds a window, at or below the specified window, which has
1578 % a WM_STATE property. If such a window is found, it is returned, otherwise
1579 % the argument window is returned.
1580 %
1581 % The format of the XClientWindow function is:
1582 %
1583 % client_window=XClientWindow(display,target_window)
1584 %
1585 % A description of each parameter follows:
1586 %
1587 % o client_window: XClientWindow returns a window, at or below the specified
1588 % window, which has a WM_STATE property otherwise the argument
1589 % target_window is returned.
1590 %
1591 % o display: Specifies a pointer to the Display structure; returned from
1592 % XOpenDisplay.
1593 %
1594 % o target_window: Specifies the window to find a WM_STATE property.
1595 %
1596 */
1597 static Window XClientWindow(Display *display,Window target_window)
1598 {
1599  Atom
1600  state,
1601  type;
1602 
1603  int
1604  format;
1605 
1606  Status
1607  status;
1608 
1609  unsigned char
1610  *data;
1611 
1612  unsigned long
1613  after,
1614  number_items;
1615 
1616  Window
1617  client_window;
1618 
1619  (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
1620  assert(display != (Display *) NULL);
1621  state=XInternAtom(display,"WM_STATE",MagickTrue);
1622  if (state == (Atom) NULL)
1623  return(target_window);
1624  type=(Atom) NULL;
1625  status=XGetWindowProperty(display,target_window,state,0L,0L,MagickFalse,
1626  (Atom) AnyPropertyType,&type,&format,&number_items,&after,&data);
1627  if ((status == Success) && (type != (Atom) NULL))
1628  return(target_window);
1629  client_window=XWindowByProperty(display,target_window,state);
1630  if (client_window == (Window) NULL)
1631  return(target_window);
1632  return(client_window);
1633 }
1634 
1635 /*
1636 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1637 % %
1638 % %
1639 % %
1640 + X C o m p o n e n t T e r m i n u s %
1641 % %
1642 % %
1643 % %
1644 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1645 %
1646 % XComponentTerminus() destroys the module component.
1647 %
1648 % The format of the XComponentTerminus method is:
1649 %
1650 % XComponentTerminus(void)
1651 %
1652 */
1653 MagickPrivate void XComponentTerminus(void)
1654 {
1655  DestroyXResources();
1656 }
1657 
1658 /*
1659 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1660 % %
1661 % %
1662 % %
1663 % X C o n f i g u r e I m a g e C o l o r m a p %
1664 % %
1665 % %
1666 % %
1667 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1668 %
1669 % XConfigureImageColormap() creates a new X colormap.
1670 %
1671 % The format of the XConfigureImageColormap method is:
1672 %
1673 % void XConfigureImageColormap(Display *display,
1674 % XResourceInfo *resource_info,XWindows *windows,Image *image,
1675 % ExceptionInfo *exception)
1676 %
1677 % A description of each parameter follows:
1678 %
1679 % o display: Specifies a connection to an X server; returned from
1680 % XOpenDisplay.
1681 %
1682 % o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
1683 %
1684 % o windows: Specifies a pointer to a XWindows structure.
1685 %
1686 % o image: the image.
1687 %
1688 % o exception: return any errors or warnings in this structure.
1689 %
1690 */
1691 MagickPrivate void XConfigureImageColormap(Display *display,
1692  XResourceInfo *resource_info,XWindows *windows,Image *image,
1693  ExceptionInfo *exception)
1694 {
1695  Colormap
1696  colormap;
1697 
1698  /*
1699  Make standard colormap.
1700  */
1701  XSetCursorState(display,windows,MagickTrue);
1702  XCheckRefreshWindows(display,windows);
1703  XMakeStandardColormap(display,windows->visual_info,resource_info,image,
1704  windows->map_info,windows->pixel_info,exception);
1705  colormap=windows->map_info->colormap;
1706  (void) XSetWindowColormap(display,windows->image.id,colormap);
1707  (void) XSetWindowColormap(display,windows->command.id,colormap);
1708  (void) XSetWindowColormap(display,windows->widget.id,colormap);
1709  if (windows->magnify.mapped != MagickFalse)
1710  (void) XSetWindowColormap(display,windows->magnify.id,colormap);
1711  if (windows->pan.mapped != MagickFalse)
1712  (void) XSetWindowColormap(display,windows->pan.id,colormap);
1713  XSetCursorState(display,windows,MagickFalse);
1714  XClientMessage(display,windows->image.id,windows->im_protocols,
1715  windows->im_update_colormap,CurrentTime);
1716 }
1717 
1718 /*
1719 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1720 % %
1721 % %
1722 % %
1723 % X C o n s t r a i n W i n d o w P o s i t i o n %
1724 % %
1725 % %
1726 % %
1727 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1728 %
1729 % XConstrainWindowPosition() assures a window is positioned within the X
1730 % server boundaries.
1731 %
1732 % The format of the XConstrainWindowPosition method is:
1733 %
1734 % void XConstrainWindowPosition(Display *display,XWindowInfo *window_info)
1735 %
1736 % A description of each parameter follows:
1737 %
1738 % o display: Specifies a pointer to the Display structure; returned from
1739 % XOpenDisplay.
1740 %
1741 % o window_info: Specifies a pointer to a XWindowInfo structure.
1742 %
1743 */
1744 MagickPrivate void XConstrainWindowPosition(Display *display,
1745  XWindowInfo *window_info)
1746 {
1747  int
1748  limit;
1749 
1750  (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
1751  assert(display != (Display *) NULL);
1752  assert(window_info != (XWindowInfo *) NULL);
1753  limit=XDisplayWidth(display,window_info->screen)-window_info->width;
1754  if (window_info->x < 0)
1755  window_info->x=0;
1756  else
1757  if (window_info->x > (int) limit)
1758  window_info->x=(int) limit;
1759  limit=XDisplayHeight(display,window_info->screen)-window_info->height;
1760  if (window_info->y < 0)
1761  window_info->y=0;
1762  else
1763  if (window_info->y > limit)
1764  window_info->y=limit;
1765 }
1766 
1767 /*
1768 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1769 % %
1770 % %
1771 % %
1772 % X D e l a y %
1773 % %
1774 % %
1775 % %
1776 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1777 %
1778 % XDelay() suspends program execution for the number of milliseconds
1779 % specified.
1780 %
1781 % The format of the Delay method is:
1782 %
1783 % void XDelay(Display *display,const size_t milliseconds)
1784 %
1785 % A description of each parameter follows:
1786 %
1787 % o display: Specifies a pointer to the Display structure; returned from
1788 % XOpenDisplay.
1789 %
1790 % o milliseconds: Specifies the number of milliseconds to delay before
1791 % returning.
1792 %
1793 */
1794 MagickPrivate void XDelay(Display *display,const size_t milliseconds)
1795 {
1796  assert(display != (Display *) NULL);
1797  (void) XFlush(display);
1798  MagickDelay(milliseconds);
1799 }
1800 
1801 /*
1802 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1803 % %
1804 % %
1805 % %
1806 % X D e s t r o y R e s o u r c e I n f o %
1807 % %
1808 % %
1809 % %
1810 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1811 %
1812 % XDestroyResourceInfo() frees memory associated with the XResourceInfo
1813 % structure.
1814 %
1815 % The format of the XDestroyResourceInfo method is:
1816 %
1817 % void XDestroyResourceInfo(XResourceInfo *resource_info)
1818 %
1819 % A description of each parameter follows:
1820 %
1821 % o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
1822 %
1823 */
1824 MagickExport void XDestroyResourceInfo(XResourceInfo *resource_info)
1825 {
1826  if (resource_info->image_geometry != (char *) NULL)
1827  resource_info->image_geometry=(char *)
1828  RelinquishMagickMemory(resource_info->image_geometry);
1829  if (resource_info->quantize_info != (QuantizeInfo *) NULL)
1830  resource_info->quantize_info=DestroyQuantizeInfo(
1831  resource_info->quantize_info);
1832  if (resource_info->client_name != (char *) NULL)
1833  resource_info->client_name=(char *)
1834  RelinquishMagickMemory(resource_info->client_name);
1835  if (resource_info->name != (char *) NULL)
1836  resource_info->name=DestroyString(resource_info->name);
1837  (void) memset(resource_info,0,sizeof(*resource_info));
1838 }
1839 
1840 /*
1841 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1842 % %
1843 % %
1844 % %
1845 % X D e s t r o y W i n d o w C o l o r s %
1846 % %
1847 % %
1848 % %
1849 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1850 %
1851 % XDestroyWindowColors() frees X11 color resources previously saved on a
1852 % window by XRetainWindowColors or programs like xsetroot.
1853 %
1854 % The format of the XDestroyWindowColors method is:
1855 %
1856 % void XDestroyWindowColors(Display *display,Window window)
1857 %
1858 % A description of each parameter follows:
1859 %
1860 % o display: Specifies a connection to an X server; returned from
1861 % XOpenDisplay.
1862 %
1863 % o window: Specifies a pointer to a Window structure.
1864 %
1865 */
1866 MagickPrivate void XDestroyWindowColors(Display *display,Window window)
1867 {
1868  Atom
1869  property,
1870  type;
1871 
1872  int
1873  format;
1874 
1875  Status
1876  status;
1877 
1878  unsigned char
1879  *data;
1880 
1881  unsigned long
1882  after,
1883  length;
1884 
1885  /*
1886  If there are previous resources on the root window, destroy them.
1887  */
1888  (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
1889  assert(display != (Display *) NULL);
1890  property=XInternAtom(display,"_XSETROOT_ID",MagickFalse);
1891  if (property == (Atom) NULL)
1892  {
1893  ThrowXWindowException(XServerError,"UnableToCreateProperty",
1894  "_XSETROOT_ID");
1895  return;
1896  }
1897  status=XGetWindowProperty(display,window,property,0L,1L,MagickTrue,
1898  (Atom) AnyPropertyType,&type,&format,&length,&after,&data);
1899  if (status != Success)
1900  return;
1901  if ((type == XA_PIXMAP) && (format == 32) && (length == 1) && (after == 0))
1902  {
1903  (void) XKillClient(display,(XID) (*((Pixmap *) data)));
1904  (void) XDeleteProperty(display,window,property);
1905  }
1906  if (type != None)
1907  (void) XFree((void *) data);
1908 }
1909 
1910 /*
1911 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1912 % %
1913 % %
1914 % %
1915 % X D i s p l a y I m a g e I n f o %
1916 % %
1917 % %
1918 % %
1919 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1920 %
1921 % XDisplayImageInfo() displays information about an X image.
1922 %
1923 % The format of the XDisplayImageInfo method is:
1924 %
1925 % void XDisplayImageInfo(Display *display,
1926 % const XResourceInfo *resource_info,XWindows *windows,Image *undo_image,
1927 % Image *image,ExceptionInfo *exception)
1928 %
1929 % A description of each parameter follows:
1930 %
1931 % o display: Specifies a connection to an X server; returned from
1932 % XOpenDisplay.
1933 %
1934 % o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
1935 %
1936 % o windows: Specifies a pointer to a XWindows structure.
1937 %
1938 % o undo_image: the undo image.
1939 %
1940 % o image: the image.
1941 %
1942 % o exception: return any errors or warnings in this structure.
1943 %
1944 */
1945 MagickPrivate void XDisplayImageInfo(Display *display,
1946  const XResourceInfo *resource_info,XWindows *windows,Image *undo_image,
1947  Image *image,ExceptionInfo *exception)
1948 {
1949  char
1950  filename[MagickPathExtent],
1951  *text,
1952  **textlist;
1953 
1954  FILE
1955  *file;
1956 
1957  int
1958  unique_file;
1959 
1960  register ssize_t
1961  i;
1962 
1963  size_t
1964  number_pixels;
1965 
1966  ssize_t
1967  bytes;
1968 
1969  unsigned int
1970  levels;
1971 
1972  /*
1973  Write info about the X server to a file.
1974  */
1975  assert(display != (Display *) NULL);
1976  assert(resource_info != (XResourceInfo *) NULL);
1977  assert(windows != (XWindows *) NULL);
1978  assert(image != (Image *) NULL);
1979  if (image->debug)
1980  (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
1981  file=(FILE *) NULL;
1982  unique_file=AcquireUniqueFileResource(filename);
1983  if (unique_file != -1)
1984  file=fdopen(unique_file,"w");
1985  if ((unique_file == -1) || (file == (FILE *) NULL))
1986  {
1987  XNoticeWidget(display,windows,"Unable to display image info",filename);
1988  return;
1989  }
1990  if (resource_info->gamma_correct != MagickFalse)
1991  if (resource_info->display_gamma != (char *) NULL)
1992  (void) FormatLocaleFile(file,"Display\n gamma: %s\n\n",
1993  resource_info->display_gamma);
1994  /*
1995  Write info about the X image to a file.
1996  */
1997  (void) FormatLocaleFile(file,"X\n visual: %s\n",
1998  XVisualClassName((int) windows->image.storage_class));
1999  (void) FormatLocaleFile(file," depth: %d\n",windows->image.ximage->depth);
2000  if (windows->visual_info->colormap_size != 0)
2001  (void) FormatLocaleFile(file," colormap size: %d\n",
2002  windows->visual_info->colormap_size);
2003  if (resource_info->colormap== SharedColormap)
2004  (void) FormatLocaleFile(file," colormap type: Shared\n");
2005  else
2006  (void) FormatLocaleFile(file," colormap type: Private\n");
2007  (void) FormatLocaleFile(file," geometry: %dx%d\n",
2008  windows->image.ximage->width,windows->image.ximage->height);
2009  if (windows->image.crop_geometry != (char *) NULL)
2010  (void) FormatLocaleFile(file," crop geometry: %s\n",
2011  windows->image.crop_geometry);
2012  if (windows->image.pixmap == (Pixmap) NULL)
2013  (void) FormatLocaleFile(file," type: X Image\n");
2014  else
2015  (void) FormatLocaleFile(file," type: Pixmap\n");
2016  if (windows->image.shape != MagickFalse)
2017  (void) FormatLocaleFile(file," non-rectangular shape: True\n");
2018  else
2019  (void) FormatLocaleFile(file," non-rectangular shape: False\n");
2020  if (windows->image.shared_memory != MagickFalse)
2021  (void) FormatLocaleFile(file," shared memory: True\n");
2022  else
2023  (void) FormatLocaleFile(file," shared memory: False\n");
2024  (void) FormatLocaleFile(file,"\n");
2025  if (resource_info->font != (char *) NULL)
2026  (void) FormatLocaleFile(file,"Font: %s\n\n",resource_info->font);
2027  if (resource_info->text_font != (char *) NULL)
2028  (void) FormatLocaleFile(file,"Text font: %s\n\n",resource_info->text_font);
2029  /*
2030  Write info about the undo cache to a file.
2031  */
2032  bytes=0;
2033  for (levels=0; undo_image != (Image *) NULL; levels++)
2034  {
2035  number_pixels=undo_image->list->columns*undo_image->list->rows;
2036  bytes+=number_pixels*sizeof(PixelInfo);
2037  undo_image=GetPreviousImageInList(undo_image);
2038  }
2039  (void) FormatLocaleFile(file,"Undo Edit Cache\n levels: %u\n",levels);
2040  (void) FormatLocaleFile(file," bytes: %.20gmb\n",(double)
2041  ((bytes+(1 << 19)) >> 20));
2042  (void) FormatLocaleFile(file," limit: %.20gmb\n\n",(double)
2043  resource_info->undo_cache);
2044  /*
2045  Write info about the image to a file.
2046  */
2047  (void) IdentifyImage(image,file,MagickTrue,exception);
2048  (void) fclose(file);
2049  text=FileToString(filename,~0UL,exception);
2050  (void) RelinquishUniqueFileResource(filename);
2051  if (text == (char *) NULL)
2052  {
2053  XNoticeWidget(display,windows,"MemoryAllocationFailed",
2054  "UnableToDisplayImageInfo");
2055  return;
2056  }
2057  textlist=StringToList(text);
2058  if (textlist != (char **) NULL)
2059  {
2060  char
2061  title[MagickPathExtent];
2062 
2063  /*
2064  Display information about the image in the Text View widget.
2065  */
2066  (void) XWithdrawWindow(display,windows->info.id,windows->info.screen);
2067  (void) FormatLocaleString(title,MagickPathExtent,"Image Info: %s",
2068  image->filename);
2069  XTextViewWidget(display,resource_info,windows,MagickTrue,title,
2070  (char const **) textlist);
2071  for (i=0; textlist[i] != (char *) NULL; i++)
2072  textlist[i]=DestroyString(textlist[i]);
2073  textlist=(char **) RelinquishMagickMemory(textlist);
2074  }
2075  text=DestroyString(text);
2076 }
2077 
2078 /*
2079 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2080 % %
2081 % %
2082 % %
2083 + X D i t h e r I m a g e %
2084 % %
2085 % %
2086 % %
2087 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2088 %
2089 % XDitherImage() dithers the reference image as required by the HP Color
2090 % Recovery algorithm. The color values are quantized to 3 bits of red and
2091 % green, and 2 bits of blue (3/3/2) and can be used as indices into a 8-bit X
2092 % standard colormap.
2093 %
2094 % The format of the XDitherImage method is:
2095 %
2096 % void XDitherImage(Image *image,XImage *ximage,ExceptionInfo *exception)
2097 %
2098 % A description of each parameter follows:
2099 %
2100 % o image: the image.
2101 %
2102 % o ximage: Specifies a pointer to a XImage structure; returned from
2103 % XCreateImage.
2104 %
2105 % o exception: return any errors or warnings in this structure.
2106 %
2107 */
2108 static void XDitherImage(Image *image,XImage *ximage,ExceptionInfo *exception)
2109 {
2110  static const short int
2111  dither_red[2][16]=
2112  {
2113  {-16, 4, -1, 11,-14, 6, -3, 9,-15, 5, -2, 10,-13, 7, -4, 8},
2114  { 15, -5, 0,-12, 13, -7, 2,-10, 14, -6, 1,-11, 12, -8, 3, -9}
2115  },
2116  dither_green[2][16]=
2117  {
2118  { 11,-15, 7, -3, 8,-14, 4, -2, 10,-16, 6, -4, 9,-13, 5, -1},
2119  {-12, 14, -8, 2, -9, 13, -5, 1,-11, 15, -7, 3,-10, 12, -6, 0}
2120  },
2121  dither_blue[2][16]=
2122  {
2123  { -3, 9,-13, 7, -1, 11,-15, 5, -4, 8,-14, 6, -2, 10,-16, 4},
2124  { 2,-10, 12, -8, 0,-12, 14, -6, 3, -9, 13, -7, 1,-11, 15, -5}
2125  };
2126 
2127  CacheView
2128  *image_view;
2129 
2130  int
2131  value,
2132  y;
2133 
2134  PixelInfo
2135  color;
2136 
2137  register char
2138  *q;
2139 
2140  register const Quantum
2141  *p;
2142 
2143  register int
2144  i,
2145  j,
2146  x;
2147 
2148  unsigned int
2149  scanline_pad;
2150 
2151  register size_t
2152  pixel;
2153 
2154  unsigned char
2155  *blue_map[2][16],
2156  *green_map[2][16],
2157  *red_map[2][16];
2158 
2159  /*
2160  Allocate and initialize dither maps.
2161  */
2162  for (i=0; i < 2; i++)
2163  for (j=0; j < 16; j++)
2164  {
2165  red_map[i][j]=(unsigned char *) AcquireCriticalMemory(256UL*
2166  sizeof(*red_map));
2167  green_map[i][j]=(unsigned char *) AcquireCriticalMemory(256UL*
2168  sizeof(*green_map));
2169  blue_map[i][j]=(unsigned char *) AcquireCriticalMemory(256UL*
2170  sizeof(*blue_map));
2171  }
2172  /*
2173  Initialize dither tables.
2174  */
2175  for (i=0; i < 2; i++)
2176  for (j=0; j < 16; j++)
2177  for (x=0; x < 256; x++)
2178  {
2179  value=x-16;
2180  if (x < 48)
2181  value=x/2+8;
2182  value+=dither_red[i][j];
2183  red_map[i][j][x]=(unsigned char)
2184  ((value < 0) ? 0 : (value > 255) ? 255 : value);
2185  value=x-16;
2186  if (x < 48)
2187  value=x/2+8;
2188  value+=dither_green[i][j];
2189  green_map[i][j][x]=(unsigned char)
2190  ((value < 0) ? 0 : (value > 255) ? 255 : value);
2191  value=x-32;
2192  if (x < 112)
2193  value=x/2+24;
2194  value+=((size_t) dither_blue[i][j] << 1);
2195  blue_map[i][j][x]=(unsigned char)
2196  ((value < 0) ? 0 : (value > 255) ? 255 : value);
2197  }
2198  /*
2199  Dither image.
2200  */
2201  scanline_pad=(unsigned int) (ximage->bytes_per_line-
2202  ((size_t) (ximage->width*ximage->bits_per_pixel) >> 3));
2203  i=0;
2204  j=0;
2205  q=ximage->data;
2206  image_view=AcquireVirtualCacheView(image,exception);
2207  for (y=0; y < (int) image->rows; y++)
2208  {
2209  p=GetCacheViewVirtualPixels(image_view,0,(ssize_t) y,image->columns,1,
2210  exception);
2211  if (p == (const Quantum *) NULL)
2212  break;
2213  for (x=0; x < (int) image->columns; x++)
2214  {
2215  color.red=(double) ClampToQuantum((double) (red_map[i][j][
2216  (int) ScaleQuantumToChar(GetPixelRed(image,p))] << 8));
2217  color.green=(double) ClampToQuantum((double) (green_map[i][j][
2218  (int) ScaleQuantumToChar(GetPixelGreen(image,p))] << 8));
2219  color.blue=(double) ClampToQuantum((double) (blue_map[i][j][
2220  (int) ScaleQuantumToChar(GetPixelBlue(image,p))] << 8));
2221  pixel=(size_t) (((size_t) color.red & 0xe0) |
2222  (((size_t) color.green & 0xe0) >> 3) |
2223  (((size_t) color.blue & 0xc0) >> 6));
2224  *q++=(char) pixel;
2225  p+=GetPixelChannels(image);
2226  j++;
2227  if (j == 16)
2228  j=0;
2229  }
2230  q+=scanline_pad;
2231  i++;
2232  if (i == 2)
2233  i=0;
2234  }
2235  image_view=DestroyCacheView(image_view);
2236  /*
2237  Free allocated memory.
2238  */
2239  for (i=0; i < 2; i++)
2240  for (j=0; j < 16; j++)
2241  {
2242  green_map[i][j]=(unsigned char *) RelinquishMagickMemory(green_map[i][j]);
2243  blue_map[i][j]=(unsigned char *) RelinquishMagickMemory(blue_map[i][j]);
2244  red_map[i][j]=(unsigned char *) RelinquishMagickMemory(red_map[i][j]);
2245  }
2246 }
2247 
2248 /*
2249 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2250 % %
2251 % %
2252 % %
2253 % X D r a w I m a g e %
2254 % %
2255 % %
2256 % %
2257 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2258 %
2259 % XDrawImage() draws a line on the image.
2260 %
2261 % The format of the XDrawImage method is:
2262 %
2263 % MagickBooleanType XDrawImage(Display *display,const XPixelInfo *pixel,
2264 % XDrawInfo *draw_info,Image *image,ExceptionInfo *exception)
2265 %
2266 % A description of each parameter follows:
2267 %
2268 % o display: Specifies a connection to an X server; returned from
2269 % XOpenDisplay.
2270 %
2271 % o pixel: Specifies a pointer to a XPixelInfo structure.
2272 %
2273 % o draw_info: Specifies a pointer to a XDrawInfo structure.
2274 %
2275 % o image: the image.
2276 %
2277 % o exception: return any errors or warnings in this structure.
2278 %
2279 */
2280 MagickPrivate MagickBooleanType XDrawImage(Display *display,
2281  const XPixelInfo *pixel,XDrawInfo *draw_info,Image *image,
2282  ExceptionInfo *exception)
2283 {
2284  CacheView
2285  *draw_view;
2286 
2287  GC
2288  draw_context;
2289 
2290  Image
2291  *draw_image;
2292 
2293  int
2294  x,
2295  y;
2296 
2297  PixelTrait
2298  alpha_trait;
2299 
2300  Pixmap
2301  draw_pixmap;
2302 
2303  unsigned int
2304  depth,
2305  height,
2306  width;
2307 
2308  Window
2309  root_window;
2310 
2311  XGCValues
2312  context_values;
2313 
2314  XImage
2315  *draw_ximage;
2316 
2317  /*
2318  Initialize drawd image.
2319  */
2320  assert(display != (Display *) NULL);
2321  assert(pixel != (XPixelInfo *) NULL);
2322  assert(draw_info != (XDrawInfo *) NULL);
2323  assert(image != (Image *) NULL);
2324  if (image->debug != MagickFalse)
2325  (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
2326  /*
2327  Initialize drawd pixmap.
2328  */
2329  root_window=XRootWindow(display,XDefaultScreen(display));
2330  depth=(unsigned int) XDefaultDepth(display,XDefaultScreen(display));
2331  draw_pixmap=XCreatePixmap(display,root_window,draw_info->width,
2332  draw_info->height,depth);
2333  if (draw_pixmap == (Pixmap) NULL)
2334  return(MagickFalse);
2335  /*
2336  Initialize graphics info.
2337  */
2338  context_values.background=(size_t) (~0);
2339  context_values.foreground=0;
2340  context_values.line_width=(int) draw_info->line_width;
2341  draw_context=XCreateGC(display,root_window,(size_t)
2342  (GCBackground | GCForeground | GCLineWidth),&context_values);
2343  if (draw_context == (GC) NULL)
2344  return(MagickFalse);
2345  /*
2346  Clear pixmap.
2347  */
2348  (void) XFillRectangle(display,draw_pixmap,draw_context,0,0,draw_info->width,
2349  draw_info->height);
2350  /*
2351  Draw line to pixmap.
2352  */
2353  (void) XSetBackground(display,draw_context,0);
2354  (void) XSetForeground(display,draw_context,(size_t) (~0));
2355  if (draw_info->stipple != (Pixmap) NULL)
2356  {
2357  (void) XSetFillStyle(display,draw_context,FillOpaqueStippled);
2358  (void) XSetStipple(display,draw_context,draw_info->stipple);
2359  }
2360  switch (draw_info->element)
2361  {
2362  case PointElement:
2363  default:
2364  {
2365  (void) XDrawLines(display,draw_pixmap,draw_context,
2366  draw_info->coordinate_info,(int) draw_info->number_coordinates,
2367  CoordModeOrigin);
2368  break;
2369  }
2370  case LineElement:
2371  {
2372  (void) XDrawLine(display,draw_pixmap,draw_context,draw_info->line_info.x1,
2373  draw_info->line_info.y1,draw_info->line_info.x2,
2374  draw_info->line_info.y2);
2375  break;
2376  }
2377  case RectangleElement:
2378  {
2379  (void) XDrawRectangle(display,draw_pixmap,draw_context,
2380  (int) draw_info->rectangle_info.x,(int) draw_info->rectangle_info.y,
2381  (unsigned int) draw_info->rectangle_info.width,
2382  (unsigned int) draw_info->rectangle_info.height);
2383  break;
2384  }
2385  case FillRectangleElement:
2386  {
2387  (void) XFillRectangle(display,draw_pixmap,draw_context,
2388  (int) draw_info->rectangle_info.x,(int) draw_info->rectangle_info.y,
2389  (unsigned int) draw_info->rectangle_info.width,
2390  (unsigned int) draw_info->rectangle_info.height);
2391  break;
2392  }
2393  case CircleElement:
2394  case EllipseElement:
2395  {
2396  (void) XDrawArc(display,draw_pixmap,draw_context,
2397  (int) draw_info->rectangle_info.x,(int) draw_info->rectangle_info.y,
2398  (unsigned int) draw_info->rectangle_info.width,
2399  (unsigned int) draw_info->rectangle_info.height,0,360*64);
2400  break;
2401  }
2402  case FillCircleElement:
2403  case FillEllipseElement:
2404  {
2405  (void) XFillArc(display,draw_pixmap,draw_context,
2406  (int) draw_info->rectangle_info.x,(int) draw_info->rectangle_info.y,
2407  (unsigned int) draw_info->rectangle_info.width,
2408  (unsigned int) draw_info->rectangle_info.height,0,360*64);
2409  break;
2410  }
2411  case PolygonElement:
2412  {
2413  XPoint
2414  *coordinate_info;
2415 
2416  coordinate_info=draw_info->coordinate_info;
2417  (void) XDrawLines(display,draw_pixmap,draw_context,coordinate_info,
2418  (int) draw_info->number_coordinates,CoordModeOrigin);
2419  (void) XDrawLine(display,draw_pixmap,draw_context,
2420  coordinate_info[draw_info->number_coordinates-1].x,
2421  coordinate_info[draw_info->number_coordinates-1].y,
2422  coordinate_info[0].x,coordinate_info[0].y);
2423  break;
2424  }
2425  case FillPolygonElement:
2426  {
2427  (void) XFillPolygon(display,draw_pixmap,draw_context,
2428  draw_info->coordinate_info,(int) draw_info->number_coordinates,Complex,
2429  CoordModeOrigin);
2430  break;
2431  }
2432  }
2433  (void) XFreeGC(display,draw_context);
2434  /*
2435  Initialize X image.
2436  */
2437  draw_ximage=XGetImage(display,draw_pixmap,0,0,draw_info->width,
2438  draw_info->height,AllPlanes,ZPixmap);
2439  if (draw_ximage == (XImage *) NULL)
2440  return(MagickFalse);
2441  (void) XFreePixmap(display,draw_pixmap);
2442  /*
2443  Initialize draw image.
2444  */
2445  draw_image=AcquireImage((ImageInfo *) NULL,exception);
2446  if (draw_image == (Image *) NULL)
2447  return(MagickFalse);
2448  draw_image->columns=draw_info->width;
2449  draw_image->rows=draw_info->height;
2450  /*
2451  Transfer drawn X image to image.
2452  */
2453  width=(unsigned int) image->columns;
2454  height=(unsigned int) image->rows;
2455  x=0;
2456  y=0;
2457  (void) XParseGeometry(draw_info->geometry,&x,&y,&width,&height);
2458  (void) GetOneVirtualPixelInfo(image,UndefinedVirtualPixelMethod,(ssize_t) x,
2459  (ssize_t) y,&draw_image->background_color,exception);
2460  if (SetImageStorageClass(draw_image,DirectClass,exception) == MagickFalse)
2461  return(MagickFalse);
2462  draw_image->alpha_trait=BlendPixelTrait;
2463  draw_view=AcquireAuthenticCacheView(draw_image,exception);
2464  for (y=0; y < (int) draw_image->rows; y++)
2465  {
2466  register int
2467  x;
2468 
2469  register Quantum
2470  *magick_restrict q;
2471 
2472  q=QueueCacheViewAuthenticPixels(draw_view,0,(ssize_t) y,draw_image->columns,
2473  1,exception);
2474  if (q == (Quantum *) NULL)
2475  break;
2476  for (x=0; x < (int) draw_image->columns; x++)
2477  {
2478  if (XGetPixel(draw_ximage,x,y) == 0)
2479  {
2480  /*
2481  Set this pixel to the background color.
2482  */
2483  SetPixelViaPixelInfo(draw_image,&draw_image->background_color,q);
2484  SetPixelAlpha(draw_image,(Quantum) (draw_info->stencil ==
2485  OpaqueStencil ? TransparentAlpha : OpaqueAlpha),q);
2486  }
2487  else
2488  {
2489  /*
2490  Set this pixel to the pen color.
2491  */
2492  SetPixelRed(draw_image,ScaleShortToQuantum(
2493  pixel->pen_color.red),q);
2494  SetPixelGreen(draw_image,ScaleShortToQuantum(
2495  pixel->pen_color.green),q);
2496  SetPixelBlue(draw_image,ScaleShortToQuantum(
2497  pixel->pen_color.blue),q);
2498  SetPixelAlpha(draw_image,(Quantum) (draw_info->stencil ==
2499  OpaqueStencil ? OpaqueAlpha : TransparentAlpha),q);
2500  }
2501  q+=GetPixelChannels(draw_image);
2502  }
2503  if (SyncCacheViewAuthenticPixels(draw_view,exception) == MagickFalse)
2504  break;
2505  }
2506  draw_view=DestroyCacheView(draw_view);
2507  XDestroyImage(draw_ximage);
2508  /*
2509  Determine draw geometry.
2510  */
2511  (void) XParseGeometry(draw_info->geometry,&x,&y,&width,&height);
2512  if ((width != (unsigned int) draw_image->columns) ||
2513  (height != (unsigned int) draw_image->rows))
2514  {
2515  char
2516  image_geometry[MagickPathExtent];
2517 
2518  /*
2519  Scale image.
2520  */
2521  (void) FormatLocaleString(image_geometry,MagickPathExtent,"%ux%u",
2522  width,height);
2523  (void) TransformImage(&draw_image,(char *) NULL,image_geometry,
2524  exception);
2525  }
2526  if (draw_info->degrees != 0.0)
2527  {
2528  Image
2529  *rotate_image;
2530 
2531  int
2532  rotations;
2533 
2534  double
2535  normalized_degrees;
2536 
2537  /*
2538  Rotate image.
2539  */
2540  rotate_image=RotateImage(draw_image,draw_info->degrees,exception);
2541  if (rotate_image == (Image *) NULL)
2542  return(MagickFalse);
2543  draw_image=DestroyImage(draw_image);
2544  draw_image=rotate_image;
2545  /*
2546  Annotation is relative to the degree of rotation.
2547  */
2548  normalized_degrees=draw_info->degrees;
2549  while (normalized_degrees < -45.0)
2550  normalized_degrees+=360.0;
2551  for (rotations=0; normalized_degrees > 45.0; rotations++)
2552  normalized_degrees-=90.0;
2553  switch (rotations % 4)
2554  {
2555  default:
2556  case 0:
2557  break;
2558  case 1:
2559  {
2560  /*
2561  Rotate 90 degrees.
2562  */
2563  x=x-(int) draw_image->columns/2;
2564  y=y+(int) draw_image->columns/2;
2565  break;
2566  }
2567  case 2:
2568  {
2569  /*
2570  Rotate 180 degrees.
2571  */
2572  x=x-(int) draw_image->columns;
2573  break;
2574  }
2575  case 3:
2576  {
2577  /*
2578  Rotate 270 degrees.
2579  */
2580  x=x-(int) draw_image->columns/2;
2581  y=y-(int) (draw_image->rows-(draw_image->columns/2));
2582  break;
2583  }
2584  }
2585  }
2586  /*
2587  Composite text onto the image.
2588  */
2589  draw_view=AcquireAuthenticCacheView(draw_image,exception);
2590  for (y=0; y < (int) draw_image->rows; y++)
2591  {
2592  register int
2593  x;
2594 
2595  register Quantum
2596  *magick_restrict q;
2597 
2598  q=GetCacheViewAuthenticPixels(draw_view,0,(ssize_t) y,draw_image->columns,1,
2599  exception);
2600  if (q == (Quantum *) NULL)
2601  break;
2602  for (x=0; x < (int) draw_image->columns; x++)
2603  {
2604  if (GetPixelAlpha(image,q) != TransparentAlpha)
2605  SetPixelAlpha(draw_image,OpaqueAlpha,q);
2606  q+=GetPixelChannels(draw_image);
2607  }
2608  if (SyncCacheViewAuthenticPixels(draw_view,exception) == MagickFalse)
2609  break;
2610  }
2611  draw_view=DestroyCacheView(draw_view);
2612  (void) XParseGeometry(draw_info->geometry,&x,&y,&width,&height);
2613  if (draw_info->stencil == TransparentStencil)
2614  (void) CompositeImage(image,draw_image,CopyAlphaCompositeOp,MagickTrue,
2615  (ssize_t) x,(ssize_t) y,exception);
2616  else
2617  {
2618  alpha_trait=image->alpha_trait;
2619  (void) CompositeImage(image,draw_image,OverCompositeOp,MagickTrue,
2620  (ssize_t) x,(ssize_t) y,exception);
2621  image->alpha_trait=alpha_trait;
2622  }
2623  draw_image=DestroyImage(draw_image);
2624  return(MagickTrue);
2625 }
2626 
2627 /*
2628 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2629 % %
2630 % %
2631 % %
2632 % X E r r o r %
2633 % %
2634 % %
2635 % %
2636 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2637 %
2638 % XError() ignores BadWindow errors for XQueryTree and XGetWindowAttributes,
2639 % and ignores BadDrawable errors for XGetGeometry, and ignores BadValue errors
2640 % for XQueryColor. It returns MagickFalse in those cases. Otherwise it
2641 % returns True.
2642 %
2643 % The format of the XError function is:
2644 %
2645 % int XError(display,error)
2646 %
2647 % A description of each parameter follows:
2648 %
2649 % o display: Specifies a pointer to the Display structure; returned from
2650 % XOpenDisplay.
2651 %
2652 % o error: Specifies the error event.
2653 %
2654 */
2655 
2656 #if defined(__cplusplus) || defined(c_plusplus)
2657 extern "C" {
2658 #endif
2659 
2660 MagickExport int XError(Display *display,XErrorEvent *error)
2661 {
2662  (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
2663  assert(display != (Display *) NULL);
2664  assert(error != (XErrorEvent *) NULL);
2665  xerror_alert=MagickTrue;
2666  switch (error->request_code)
2667  {
2668  case X_GetGeometry:
2669  {
2670  if ((int) error->error_code == BadDrawable)
2671  return(MagickFalse);
2672  break;
2673  }
2674  case X_GetWindowAttributes:
2675  case X_QueryTree:
2676  {
2677  if ((int) error->error_code == BadWindow)
2678  return(MagickFalse);
2679  break;
2680  }
2681  case X_QueryColors:
2682  {
2683  if ((int) error->error_code == BadValue)
2684  return(MagickFalse);
2685  break;
2686  }
2687  }
2688  return(MagickTrue);
2689 }
2690 
2691 #if defined(__cplusplus) || defined(c_plusplus)
2692 }
2693 #endif
2694 
2695 /*
2696 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2697 % %
2698 % %
2699 % %
2700 % X F r e e R e s o u r c e s %
2701 % %
2702 % %
2703 % %
2704 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2705 %
2706 % XFreeResources() frees X11 resources.
2707 %
2708 % The format of the XFreeResources method is:
2709 %
2710 % void XFreeResources(Display *display,XVisualInfo *visual_info,
2711 % XStandardColormap *map_info,XPixelInfo *pixel,XFontStruct *font_info,
2712 % XResourceInfo *resource_info,XWindowInfo *window_info)
2713 % resource_info,window_info)
2714 %
2715 % A description of each parameter follows:
2716 %
2717 % o display: Specifies a connection to an X server; returned from
2718 % XOpenDisplay.
2719 %
2720 % o visual_info: Specifies a pointer to a X11 XVisualInfo structure;
2721 % returned from XGetVisualInfo.
2722 %
2723 % o map_info: If map_type is specified, this structure is initialized
2724 % with info from the Standard Colormap.
2725 %
2726 % o pixel: Specifies a pointer to a XPixelInfo structure.
2727 %
2728 % o font_info: Specifies a pointer to a XFontStruct structure.
2729 %
2730 % o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
2731 %
2732 % o window_info: Specifies a pointer to a X11 XWindowInfo structure.
2733 %
2734 */
2735 MagickPrivate void XFreeResources(Display *display,XVisualInfo *visual_info,
2736  XStandardColormap *map_info,XPixelInfo *pixel,XFontStruct *font_info,
2737  XResourceInfo *resource_info,XWindowInfo *window_info)
2738 {
2739  (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
2740  assert(display != (Display *) NULL);
2741  assert(resource_info != (XResourceInfo *) NULL);
2742  if (window_info != (XWindowInfo *) NULL)
2743  {
2744  /*
2745  Free X image.
2746  */
2747  if (window_info->ximage != (XImage *) NULL)
2748  XDestroyImage(window_info->ximage);
2749  if (window_info->id != (Window) NULL)
2750  {
2751  /*
2752  Free destroy window and free cursors.
2753  */
2754  if (window_info->id != XRootWindow(display,visual_info->screen))
2755  (void) XDestroyWindow(display,window_info->id);
2756  if (window_info->annotate_context != (GC) NULL)
2757  (void) XFreeGC(display,window_info->annotate_context);
2758  if (window_info->highlight_context != (GC) NULL)
2759  (void) XFreeGC(display,window_info->highlight_context);
2760  if (window_info->widget_context != (GC) NULL)
2761  (void) XFreeGC(display,window_info->widget_context);
2762  if (window_info->cursor != (Cursor) NULL)
2763  (void) XFreeCursor(display,window_info->cursor);
2764  window_info->cursor=(Cursor) NULL;
2765  if (window_info->busy_cursor != (Cursor) NULL)
2766  (void) XFreeCursor(display,window_info->busy_cursor);
2767  window_info->busy_cursor=(Cursor) NULL;
2768  }
2769  }
2770  /*
2771  Free font.
2772  */
2773  if (font_info != (XFontStruct *) NULL)
2774  {
2775  (void) XFreeFont(display,font_info);
2776  font_info=(XFontStruct *) NULL;
2777  }
2778  if (map_info != (XStandardColormap *) NULL)
2779  {
2780  /*
2781  Free X Standard Colormap.
2782  */
2783  if (resource_info->map_type == (char *) NULL)
2784  (void) XFreeStandardColormap(display,visual_info,map_info,pixel);
2785  (void) XFree((void *) map_info);
2786  }
2787  /*
2788  Free X visual info.
2789  */
2790  if (visual_info != (XVisualInfo *) NULL)
2791  (void) XFree((void *) visual_info);
2792  if (resource_info->close_server != MagickFalse)
2793  (void) XCloseDisplay(display);
2794 }
2795 
2796 /*
2797 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2798 % %
2799 % %
2800 % %
2801 % X F r e e S t a n d a r d C o l o r m a p %
2802 % %
2803 % %
2804 % %
2805 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2806 %
2807 % XFreeStandardColormap() frees an X11 colormap.
2808 %
2809 % The format of the XFreeStandardColormap method is:
2810 %
2811 % void XFreeStandardColormap(Display *display,
2812 % const XVisualInfo *visual_info,XStandardColormap *map_info,
2813 % XPixelInfo *pixel)
2814 %
2815 % A description of each parameter follows:
2816 %
2817 % o display: Specifies a connection to an X server; returned from
2818 % XOpenDisplay.
2819 %
2820 % o visual_info: Specifies a pointer to a X11 XVisualInfo structure;
2821 % returned from XGetVisualInfo.
2822 %
2823 % o map_info: If map_type is specified, this structure is initialized
2824 % with info from the Standard Colormap.
2825 %
2826 % o pixel: Specifies a pointer to a XPixelInfo structure.
2827 %
2828 */
2829 MagickPrivate void XFreeStandardColormap(Display *display,
2830  const XVisualInfo *visual_info,XStandardColormap *map_info,XPixelInfo *pixel)
2831 {
2832  /*
2833  Free colormap.
2834  */
2835  (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
2836  assert(display != (Display *) NULL);
2837  assert(visual_info != (XVisualInfo *) NULL);
2838  assert(map_info != (XStandardColormap *) NULL);
2839  (void) XFlush(display);
2840  if (map_info->colormap != (Colormap) NULL)
2841  {
2842  if (map_info->colormap != XDefaultColormap(display,visual_info->screen))
2843  (void) XFreeColormap(display,map_info->colormap);
2844  else
2845  if (pixel != (XPixelInfo *) NULL)
2846  if ((visual_info->klass != TrueColor) &&
2847  (visual_info->klass != DirectColor))
2848  (void) XFreeColors(display,map_info->colormap,pixel->pixels,
2849  (int) pixel->colors,0);
2850  }
2851  map_info->colormap=(Colormap) NULL;
2852  if (pixel != (XPixelInfo *) NULL)
2853  {
2854  if (pixel->pixels != (unsigned long *) NULL)
2855  pixel->pixels=(unsigned long *) RelinquishMagickMemory(pixel->pixels);
2856  pixel->pixels=(unsigned long *) NULL;
2857  }
2858 }
2859 
2860 /*
2861 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2862 % %
2863 % %
2864 % %
2865 % X G e t A n n o t a t e I n f o %
2866 % %
2867 % %
2868 % %
2869 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2870 %
2871 % XGetAnnotateInfo() initializes the AnnotateInfo structure.
2872 %
2873 % The format of the XGetAnnotateInfo method is:
2874 %
2875 % void XGetAnnotateInfo(XAnnotateInfo *annotate_info)
2876 %
2877 % A description of each parameter follows:
2878 %
2879 % o annotate_info: Specifies a pointer to a XAnnotateInfo structure.
2880 %
2881 */
2882 MagickPrivate void XGetAnnotateInfo(XAnnotateInfo *annotate_info)
2883 {
2884  /*
2885  Initialize annotate structure.
2886  */
2887  (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
2888  assert(annotate_info != (XAnnotateInfo *) NULL);
2889  annotate_info->x=0;
2890  annotate_info->y=0;
2891  annotate_info->width=0;
2892  annotate_info->height=0;
2893  annotate_info->stencil=ForegroundStencil;
2894  annotate_info->degrees=0.0;
2895  annotate_info->font_info=(XFontStruct *) NULL;
2896  annotate_info->text=(char *) NULL;
2897  *annotate_info->geometry='\0';
2898  annotate_info->previous=(XAnnotateInfo *) NULL;
2899  annotate_info->next=(XAnnotateInfo *) NULL;
2900  (void) XSupportsLocale();
2901  (void) XSetLocaleModifiers("");
2902 }
2903 
2904 /*
2905 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2906 % %
2907 % %
2908 % %
2909 % X G e t M a p I n f o %
2910 % %
2911 % %
2912 % %
2913 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2914 %
2915 % XGetMapInfo() initializes the XStandardColormap structure.
2916 %
2917 % The format of the XStandardColormap method is:
2918 %
2919 % void XGetMapInfo(const XVisualInfo *visual_info,const Colormap colormap,
2920 % XStandardColormap *map_info)
2921 %
2922 % A description of each parameter follows:
2923 %
2924 % o colormap: Specifies the ID of the X server colormap.
2925 %
2926 % o visual_info: Specifies a pointer to a X11 XVisualInfo structure;
2927 % returned from XGetVisualInfo.
2928 %
2929 % o map_info: Specifies a pointer to a X11 XStandardColormap structure.
2930 %
2931 */
2932 MagickPrivate void XGetMapInfo(const XVisualInfo *visual_info,
2933  const Colormap colormap,XStandardColormap *map_info)
2934 {
2935  /*
2936  Initialize map info.
2937  */
2938  (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
2939  assert(visual_info != (XVisualInfo *) NULL);
2940  assert(map_info != (XStandardColormap *) NULL);
2941  map_info->colormap=colormap;
2942  map_info->red_max=visual_info->red_mask;
2943  map_info->red_mult=(size_t) (map_info->red_max != 0 ? 1 : 0);
2944  if (map_info->red_max != 0)
2945  while ((map_info->red_max & 0x01) == 0)
2946  {
2947  map_info->red_max>>=1;
2948  map_info->red_mult<<=1;
2949  }
2950  map_info->green_max=visual_info->green_mask;
2951  map_info->green_mult=(size_t) (map_info->green_max != 0 ? 1 : 0);
2952  if (map_info->green_max != 0)
2953  while ((map_info->green_max & 0x01) == 0)
2954  {
2955  map_info->green_max>>=1;
2956  map_info->green_mult<<=1;
2957  }
2958  map_info->blue_max=visual_info->blue_mask;
2959  map_info->blue_mult=(size_t) (map_info->blue_max != 0 ? 1 : 0);
2960  if (map_info->blue_max != 0)
2961  while ((map_info->blue_max & 0x01) == 0)
2962  {
2963  map_info->blue_max>>=1;
2964  map_info->blue_mult<<=1;
2965  }
2966  map_info->base_pixel=0;
2967 }
2968 
2969 /*
2970 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2971 % %
2972 % %
2973 % %
2974 % X G e t P i x e l I n f o %
2975 % %
2976 % %
2977 % %
2978 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2979 %
2980 % XGetPixelInfo() initializes the PixelInfo structure.
2981 %
2982 % The format of the XGetPixelInfo method is:
2983 %
2984 % void XGetPixelInfo(Display *display,const XVisualInfo *visual_info,
2985 % const XStandardColormap *map_info,const XResourceInfo *resource_info,
2986 % Image *image,XPixelInfo *pixel)
2987 % pixel)
2988 %
2989 % A description of each parameter follows:
2990 %
2991 % o display: Specifies a connection to an X server; returned from
2992 % XOpenDisplay.
2993 %
2994 % o visual_info: Specifies a pointer to a X11 XVisualInfo structure;
2995 % returned from XGetVisualInfo.
2996 %
2997 % o map_info: If map_type is specified, this structure is initialized
2998 % with info from the Standard Colormap.
2999 %
3000 % o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
3001 %
3002 % o image: the image.
3003 %
3004 % o pixel: Specifies a pointer to a XPixelInfo structure.
3005 %
3006 */
3007 MagickPrivate void XGetPixelInfo(Display *display,
3008  const XVisualInfo *visual_info,const XStandardColormap *map_info,
3009  const XResourceInfo *resource_info,Image *image,XPixelInfo *pixel)
3010 {
3011  static const char
3012  *PenColors[MaxNumberPens]=
3013  {
3014  "#000000000000", /* black */
3015  "#00000000ffff", /* blue */
3016  "#0000ffffffff", /* cyan */
3017  "#0000ffff0000", /* green */
3018  "#bdbdbdbdbdbd", /* gray */
3019  "#ffff00000000", /* red */
3020  "#ffff0000ffff", /* magenta */
3021  "#ffffffff0000", /* yellow */
3022  "#ffffffffffff", /* white */
3023  "#bdbdbdbdbdbd", /* gray */
3024  "#bdbdbdbdbdbd" /* gray */
3025  };
3026 
3027  Colormap
3028  colormap;
3029 
3030  extern const char
3031  BorderColor[],
3032  ForegroundColor[];
3033 
3034  register ssize_t
3035  i;
3036 
3037  Status
3038  status;
3039 
3040  unsigned int
3041  packets;
3042 
3043  /*
3044  Initialize pixel info.
3045  */
3046  (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
3047  assert(display != (Display *) NULL);
3048  assert(visual_info != (XVisualInfo *) NULL);
3049  assert(map_info != (XStandardColormap *) NULL);
3050  assert(resource_info != (XResourceInfo *) NULL);
3051  assert(pixel != (XPixelInfo *) NULL);
3052  pixel->colors=0;
3053  if (image != (Image *) NULL)
3054  if (image->storage_class == PseudoClass)
3055  pixel->colors=(ssize_t) image->colors;
3056  packets=(unsigned int)
3057  MagickMax((int) pixel->colors,visual_info->colormap_size)+MaxNumberPens;
3058  if (pixel->pixels != (unsigned long *) NULL)
3059  pixel->pixels=(unsigned long *) RelinquishMagickMemory(pixel->pixels);
3060  pixel->pixels=(unsigned long *) AcquireQuantumMemory(packets,
3061  sizeof(*pixel->pixels));
3062  if (pixel->pixels == (unsigned long *) NULL)
3063  ThrowXWindowFatalException(ResourceLimitFatalError,"UnableToGetPixelInfo",
3064  image->filename);
3065  /*
3066  Set foreground color.
3067  */
3068  colormap=map_info->colormap;
3069  (void) XParseColor(display,colormap,(char *) ForegroundColor,
3070  &pixel->foreground_color);
3071  status=XParseColor(display,colormap,resource_info->foreground_color,
3072  &pixel->foreground_color);
3073  if (status == False)
3074  ThrowXWindowException(XServerError,"ColorIsNotKnownToServer",
3075  resource_info->foreground_color);
3076  pixel->foreground_color.pixel=
3077  XStandardPixel(map_info,&pixel->foreground_color);
3078  pixel->foreground_color.flags=(char) (DoRed | DoGreen | DoBlue);
3079  /*
3080  Set background color.
3081  */
3082  (void) XParseColor(display,colormap,"#d6d6d6d6d6d6",&pixel->background_color);
3083  status=XParseColor(display,colormap,resource_info->background_color,
3084  &pixel->background_color);
3085  if (status == False)
3086  ThrowXWindowException(XServerError,"ColorIsNotKnownToServer",
3087  resource_info->background_color);
3088  pixel->background_color.pixel=
3089  XStandardPixel(map_info,&pixel->background_color);
3090  pixel->background_color.flags=(char) (DoRed | DoGreen | DoBlue);
3091  /*
3092  Set border color.
3093  */
3094  (void) XParseColor(display,colormap,(char *) BorderColor,
3095  &pixel->border_color);
3096  status=XParseColor(display,colormap,resource_info->border_color,
3097  &pixel->border_color);
3098  if (status == False)
3099  ThrowXWindowException(XServerError,"ColorIsNotKnownToServer",
3100  resource_info->border_color);
3101  pixel->border_color.pixel=XStandardPixel(map_info,&pixel->border_color);
3102  pixel->border_color.flags=(char) (DoRed | DoGreen | DoBlue);
3103  /*
3104  Set matte color.
3105  */
3106  pixel->matte_color=pixel->background_color;
3107  if (resource_info->matte_color != (char *) NULL)
3108  {
3109  /*
3110  Matte color is specified as a X resource or command line argument.
3111  */
3112  status=XParseColor(display,colormap,resource_info->matte_color,
3113  &pixel->matte_color);
3114  if (status == False)
3115  ThrowXWindowException(XServerError,"ColorIsNotKnownToServer",
3116  resource_info->matte_color);
3117  pixel->matte_color.pixel=XStandardPixel(map_info,&pixel->matte_color);
3118  pixel->matte_color.flags=(char) (DoRed | DoGreen | DoBlue);
3119  }
3120  /*
3121  Set highlight color.
3122  */
3123  pixel->highlight_color.red=(unsigned short) (((double)
3124  pixel->matte_color.red*ScaleQuantumToShort(HighlightModulate))/65535L+
3125  (ScaleQuantumToShort((Quantum) (QuantumRange-HighlightModulate))));
3126  pixel->highlight_color.green=(unsigned short) (((double)
3127  pixel->matte_color.green*ScaleQuantumToShort(HighlightModulate))/65535L+
3128  (ScaleQuantumToShort((Quantum) (QuantumRange-HighlightModulate))));
3129  pixel->highlight_color.blue=(unsigned short) (((double)
3130  pixel->matte_color.blue*ScaleQuantumToShort(HighlightModulate))/65535L+
3131  (ScaleQuantumToShort((Quantum) (QuantumRange-HighlightModulate))));
3132  pixel->highlight_color.pixel=XStandardPixel(map_info,&pixel->highlight_color);
3133  pixel->highlight_color.flags=(char) (DoRed | DoGreen | DoBlue);
3134  /*
3135  Set shadow color.
3136  */
3137  pixel->shadow_color.red=(unsigned short) (((double)
3138  pixel->matte_color.red*ScaleQuantumToShort(ShadowModulate))/65535L);
3139  pixel->shadow_color.green=(unsigned short) (((double)
3140  pixel->matte_color.green*ScaleQuantumToShort(ShadowModulate))/65535L);
3141  pixel->shadow_color.blue=(unsigned short) (((double)
3142  pixel->matte_color.blue*ScaleQuantumToShort(ShadowModulate))/65535L);
3143  pixel->shadow_color.pixel=XStandardPixel(map_info,&pixel->shadow_color);
3144  pixel->shadow_color.flags=(char) (DoRed | DoGreen | DoBlue);
3145  /*
3146  Set depth color.
3147  */
3148  pixel->depth_color.red=(unsigned short) (((double)
3149  pixel->matte_color.red*ScaleQuantumToShort(DepthModulate))/65535L);
3150  pixel->depth_color.green=(unsigned short) (((double)
3151  pixel->matte_color.green*ScaleQuantumToShort(DepthModulate))/65535L);
3152  pixel->depth_color.blue=(unsigned short) (((double)
3153  pixel->matte_color.blue*ScaleQuantumToShort(DepthModulate))/65535L);
3154  pixel->depth_color.pixel=XStandardPixel(map_info,&pixel->depth_color);
3155  pixel->depth_color.flags=(char) (DoRed | DoGreen | DoBlue);
3156  /*
3157  Set trough color.
3158  */
3159  pixel->trough_color.red=(unsigned short) (((double)
3160  pixel->matte_color.red*ScaleQuantumToShort(TroughModulate))/65535L);
3161  pixel->trough_color.green=(unsigned short) (((double)
3162  pixel->matte_color.green*ScaleQuantumToShort(TroughModulate))/65535L);
3163  pixel->trough_color.blue=(unsigned short) (((double)
3164  pixel->matte_color.blue*ScaleQuantumToShort(TroughModulate))/65535L);
3165  pixel->trough_color.pixel=XStandardPixel(map_info,&pixel->trough_color);
3166  pixel->trough_color.flags=(char) (DoRed | DoGreen | DoBlue);
3167  /*
3168  Set pen color.
3169  */
3170  for (i=0; i < MaxNumberPens; i++)
3171  {
3172  (void) XParseColor(display,colormap,(char *) PenColors[i],
3173  &pixel->pen_colors[i]);
3174  status=XParseColor(display,colormap,resource_info->pen_colors[i],
3175  &pixel->pen_colors[i]);
3176  if (status == False)
3177  ThrowXWindowException(XServerError,"ColorIsNotKnownToServer",
3178  resource_info->pen_colors[i]);
3179  pixel->pen_colors[i].pixel=XStandardPixel(map_info,&pixel->pen_colors[i]);
3180  pixel->pen_colors[i].flags=(char) (DoRed | DoGreen | DoBlue);
3181  }
3182  pixel->box_color=pixel->background_color;
3183  pixel->pen_color=pixel->foreground_color;
3184  pixel->box_index=0;
3185  pixel->pen_index=1;
3186  if (image != (Image *) NULL)
3187  {
3188  if ((resource_info->gamma_correct != MagickFalse) &&
3189  (image->gamma != 0.0))
3190  {
3191  GeometryInfo
3192  geometry_info;
3193 
3195  flags;
3196 
3197  /*
3198  Initialize map relative to display and image gamma.
3199  */
3200  flags=ParseGeometry(resource_info->display_gamma,&geometry_info);
3201  red_gamma=geometry_info.rho;
3202  green_gamma=geometry_info.sigma;
3203  if ((flags & SigmaValue) == 0)
3204  green_gamma=red_gamma;
3205  blue_gamma=geometry_info.xi;
3206  if ((flags & XiValue) == 0)
3207  blue_gamma=red_gamma;
3208  red_gamma*=image->gamma;
3209  green_gamma*=image->gamma;
3210  blue_gamma*=image->gamma;
3211  }
3212  if (image->storage_class == PseudoClass)
3213  {
3214  /*
3215  Initialize pixel array for images of type PseudoClass.
3216  */
3217  for (i=0; i < (ssize_t) image->colors; i++)
3218  pixel->pixels[i]=XGammaPacket(map_info,image->colormap+i);
3219  for (i=0; i < MaxNumberPens; i++)
3220  pixel->pixels[image->colors+i]=pixel->pen_colors[i].pixel;
3221  pixel->colors+=MaxNumberPens;
3222  }
3223  }
3224 }
3225 
3226 /*
3227 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3228 % %
3229 % %
3230 % %
3231 % X G e t R e s o u r c e C l a s s %
3232 % %
3233 % %
3234 % %
3235 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3236 %
3237 % XGetResourceClass() queries the X server for the specified resource name or
3238 % class. If the resource name or class is not defined in the database, the
3239 % supplied default value is returned.
3240 %
3241 % The format of the XGetResourceClass method is:
3242 %
3243 % char *XGetResourceClass(XrmDatabase database,const char *client_name,
3244 % const char *keyword,char *resource_default)
3245 %
3246 % A description of each parameter follows:
3247 %
3248 % o database: Specifies a resource database; returned from
3249 % XrmGetStringDatabase.
3250 %
3251 % o client_name: Specifies the application name used to retrieve resource
3252 % info from the X server database.
3253 %
3254 % o keyword: Specifies the keyword of the value being retrieved.
3255 %
3256 % o resource_default: Specifies the default value to return if the query
3257 % fails to find the specified keyword/class.
3258 %
3259 */
3260 MagickExport char *XGetResourceClass(XrmDatabase database,
3261  const char *client_name,const char *keyword,char *resource_default)
3262 {
3263  char
3264  resource_class[MagickPathExtent],
3265  resource_name[MagickPathExtent];
3266 
3267  static char
3268  *resource_type;
3269 
3270  Status
3271  status;
3272 
3273  XrmValue
3274  resource_value;
3275 
3276  if (database == (XrmDatabase) NULL)
3277  return(resource_default);
3278  *resource_name='\0';
3279  *resource_class='\0';
3280  if (keyword != (char *) NULL)
3281  {
3282  int
3283  c,
3284  k;
3285 
3286  /*
3287  Initialize resource keyword and class.
3288  */
3289  (void) FormatLocaleString(resource_name,MagickPathExtent,"%s.%s",
3290  client_name,keyword);
3291  c=(int) (*client_name);
3292  if ((c >= XK_a) && (c <= XK_z))
3293  c-=(XK_a-XK_A);
3294  else
3295  if ((c >= XK_agrave) && (c <= XK_odiaeresis))
3296  c-=(XK_agrave-XK_Agrave);
3297  else
3298  if ((c >= XK_oslash) && (c <= XK_thorn))
3299  c-=(XK_oslash-XK_Ooblique);
3300  k=(int) (*keyword);
3301  if ((k >= XK_a) && (k <= XK_z))
3302  k-=(XK_a-XK_A);
3303  else
3304  if ((k >= XK_agrave) && (k <= XK_odiaeresis))
3305  k-=(XK_agrave-XK_Agrave);
3306  else
3307  if ((k >= XK_oslash) && (k <= XK_thorn))
3308  k-=(XK_oslash-XK_Ooblique);
3309  (void) FormatLocaleString(resource_class,MagickPathExtent,"%c%s.%c%s",c,
3310  client_name+1,k,keyword+1);
3311  }
3312  status=XrmGetResource(database,resource_name,resource_class,&resource_type,
3313  &resource_value);
3314  if (status == False)
3315  return(resource_default);
3316  return(resource_value.addr);
3317 }
3318 
3319 /*
3320 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3321 % %
3322 % %
3323 % %
3324 % X G e t R e s o u r c e D a t a b a s e %
3325 % %
3326 % %
3327 % %
3328 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3329 %
3330 % XGetResourceDatabase() creates a new resource database and initializes it.
3331 %
3332 % The format of the XGetResourceDatabase method is:
3333 %
3334 % XrmDatabase XGetResourceDatabase(Display *display,
3335 % const char *client_name)
3336 %
3337 % A description of each parameter follows:
3338 %
3339 % o database: XGetResourceDatabase() returns the database after it is
3340 % initialized.
3341 %
3342 % o display: Specifies a connection to an X server; returned from
3343 % XOpenDisplay.
3344 %
3345 % o client_name: Specifies the application name used to retrieve resource
3346 % info from the X server database.
3347 %
3348 */
3349 MagickExport XrmDatabase XGetResourceDatabase(Display *display,
3350  const char *client_name)
3351 {
3352  char
3353  filename[MagickPathExtent];
3354 
3355  int
3356  c;
3357 
3358  register const char
3359  *p;
3360 
3361  XrmDatabase
3362  resource_database,
3363  server_database;
3364 
3365  if (display == (Display *) NULL)
3366  return((XrmDatabase) NULL);
3367  assert(client_name != (char *) NULL);
3368  /*
3369  Initialize resource database.
3370  */
3371  XrmInitialize();
3372  (void) XGetDefault(display,(char *) client_name,"dummy");
3373  resource_database=XrmGetDatabase(display);
3374  /*
3375  Combine application database.
3376  */
3377  if (client_name != (char *) NULL)
3378  {
3379  /*
3380  Get basename of client.
3381  */
3382  p=client_name+(strlen(client_name)-1);
3383  while ((p > client_name) && (*p != '/'))
3384  p--;
3385  if (*p == '/')
3386  client_name=p+1;
3387  }
3388  c=(int) (*client_name);
3389  if ((c >= XK_a) && (c <= XK_z))
3390  c-=(XK_a-XK_A);
3391  else
3392  if ((c >= XK_agrave) && (c <= XK_odiaeresis))
3393  c-=(XK_agrave-XK_Agrave);
3394  else
3395  if ((c >= XK_oslash) && (c <= XK_thorn))
3396  c-=(XK_oslash-XK_Ooblique);
3397 #if defined(X11_APPLICATION_PATH)
3398  (void) FormatLocaleString(filename,MagickPathExtent,"%s%c%s",
3399  X11_APPLICATION_PATH,c,client_name+1);
3400  (void) XrmCombineFileDatabase(filename,&resource_database,MagickFalse);
3401 #endif
3402  if (XResourceManagerString(display) != (char *) NULL)
3403  {
3404  /*
3405  Combine server database.
3406  */
3407  server_database=XrmGetStringDatabase(XResourceManagerString(display));
3408  XrmCombineDatabase(server_database,&resource_database,MagickFalse);
3409  }
3410  /*
3411  Merge user preferences database.
3412  */
3413 #if defined(X11_PREFERENCES_PATH)
3414  (void) FormatLocaleString(filename,MagickPathExtent,"%s%src",
3415  X11_PREFERENCES_PATH,client_name);
3416  ExpandFilename(filename);
3417  (void) XrmCombineFileDatabase(filename,&resource_database,MagickFalse);
3418 #endif
3419  return(resource_database);
3420 }
3421 
3422 /*
3423 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3424 % %
3425 % %
3426 % %
3427 % X G e t R e s o u r c e I n f o %
3428 % %
3429 % %
3430 % %
3431 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3432 %
3433 % XGetResourceInfo(image_info,) initializes the ResourceInfo structure.
3434 %
3435 % The format of the XGetResourceInfo method is:
3436 %
3437 % void XGetResourceInfo(const ImageInfo *image_info,XrmDatabase database,
3438 % const char *client_name,XResourceInfo *resource_info)
3439 %
3440 % A description of each parameter follows:
3441 %
3442 % o image_info: the image info.
3443 %
3444 % o database: Specifies a resource database; returned from
3445 % XrmGetStringDatabase.
3446 %
3447 % o client_name: Specifies the application name used to retrieve
3448 % resource info from the X server database.
3449 %
3450 % o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
3451 %
3452 */
3453 MagickExport void XGetResourceInfo(const ImageInfo *image_info,
3454  XrmDatabase database,const char *client_name,XResourceInfo *resource_info)
3455 {
3456  char
3457  *directory,
3458  *resource_value;
3459 
3460  extern const char
3461  BorderColor[],
3462  ForegroundColor[];
3463 
3464  /*
3465  Initialize resource info fields.
3466  */
3467  (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
3468  assert(resource_info != (XResourceInfo *) NULL);
3469  (void) memset(resource_info,0,sizeof(*resource_info));
3470  resource_info->resource_database=database;
3471  resource_info->image_info=(ImageInfo *) image_info;
3472  (void) SetImageInfoProgressMonitor(resource_info->image_info,
3473  XMagickProgressMonitor,(void *) NULL);
3474  resource_info->quantize_info=CloneQuantizeInfo((QuantizeInfo *) NULL);
3475  resource_info->close_server=MagickTrue;
3476  resource_info->client_name=AcquireString(client_name);
3477  resource_value=XGetResourceClass(database,client_name,"backdrop",
3478  (char *) "False");
3479  resource_info->backdrop=IsStringTrue(resource_value);
3480  resource_info->background_color=XGetResourceInstance(database,client_name,
3481  "background",(char *) "#d6d6d6d6d6d6");
3482  resource_info->border_color=XGetResourceInstance(database,client_name,
3483  "borderColor",BorderColor);
3484  resource_value=XGetResourceClass(database,client_name,"borderWidth",
3485  (char *) "2");
3486  resource_info->border_width=(unsigned int) StringToUnsignedLong(
3487  resource_value);
3488  resource_value=XGetResourceClass(database,client_name,"colormap",
3489  (char *) "shared");
3490  resource_info->colormap=UndefinedColormap;
3491  if (LocaleCompare("private",resource_value) == 0)
3492  resource_info->colormap=PrivateColormap;
3493  if (LocaleCompare("shared",resource_value) == 0)
3494  resource_info->colormap=SharedColormap;
3495  if (resource_info->colormap == UndefinedColormap)
3496  ThrowXWindowException(OptionError,"UnrecognizedColormapType",
3497  resource_value);
3498  resource_value=XGetResourceClass(database,client_name,
3499  "colorRecovery",(char *) "False");
3500  resource_info->color_recovery=IsStringTrue(resource_value);
3501  resource_value=XGetResourceClass(database,client_name,"confirmExit",
3502  (char *) "False");
3503  resource_info->confirm_exit=IsStringTrue(resource_value);
3504  resource_value=XGetResourceClass(database,client_name,"confirmEdit",
3505  (char *) "False");
3506  resource_info->confirm_edit=IsStringTrue(resource_value);
3507  resource_value=XGetResourceClass(database,client_name,"delay",(char *) "1");
3508  resource_info->delay=(unsigned int) StringToUnsignedLong(resource_value);
3509  resource_info->display_gamma=XGetResourceClass(database,client_name,
3510  "displayGamma",(char *) "2.2");
3511  resource_value=XGetResourceClass(database,client_name,"displayWarnings",
3512  (char *) "True");
3513  resource_info->display_warnings=IsStringTrue(resource_value);
3514  resource_info->font=XGetResourceClass(database,client_name,"font",
3515  (char *) NULL);
3516  resource_info->font=XGetResourceClass(database,client_name,"fontList",
3517  resource_info->font);
3518  resource_info->font_name[0]=XGetResourceClass(database,client_name,"font1",
3519  (char *) "fixed");
3520  resource_info->font_name[1]=XGetResourceClass(database,client_name,"font2",
3521  (char *) "variable");
3522  resource_info->font_name[2]=XGetResourceClass(database,client_name,"font3",
3523  (char *) "5x8");
3524  resource_info->font_name[3]=XGetResourceClass(database,client_name,"font4",
3525  (char *) "6x10");
3526  resource_info->font_name[4]=XGetResourceClass(database,client_name,"font5",
3527  (char *) "7x13bold");
3528  resource_info->font_name[5]=XGetResourceClass(database,client_name,"font6",
3529  (char *) "8x13bold");
3530  resource_info->font_name[6]=XGetResourceClass(database,client_name,"font7",
3531  (char *) "9x15bold");
3532  resource_info->font_name[7]=XGetResourceClass(database,client_name,"font8",
3533  (char *) "10x20");
3534  resource_info->font_name[8]=XGetResourceClass(database,client_name,"font9",
3535  (char *) "12x24");
3536  resource_info->font_name[9]=XGetResourceClass(database,client_name,"font0",
3537  (char *) "fixed");
3538  resource_info->font_name[10]=XGetResourceClass(database,client_name,"font0",
3539  (char *) "fixed");
3540  resource_info->foreground_color=XGetResourceInstance(database,client_name,
3541  "foreground",ForegroundColor);
3542  resource_value=XGetResourceClass(database,client_name,"gammaCorrect",
3543  (char *) "False");
3544  resource_info->gamma_correct=IsStringTrue(resource_value);
3545  resource_info->image_geometry=ConstantString(XGetResourceClass(database,
3546  client_name,"geometry",(char *) NULL));
3547  resource_value=XGetResourceClass(database,client_name,"gravity",
3548  (char *) "Center");
3549  resource_info->gravity=(GravityType) ParseCommandOption(MagickGravityOptions,
3550  MagickFalse,resource_value);
3551  directory=getcwd(resource_info->home_directory,MagickPathExtent);
3552  (void) directory;
3553  resource_info->icon_geometry=XGetResourceClass(database,client_name,
3554  "iconGeometry",(char *) NULL);
3555  resource_value=XGetResourceClass(database,client_name,"iconic",
3556  (char *) "False");
3557  resource_info->iconic=IsStringTrue(resource_value);
3558  resource_value=XGetResourceClass(database,client_name,"immutable",
3559  LocaleCompare(client_name,"PerlMagick") == 0 ? (char *) "True" :
3560  (char *) "False");
3561  resource_info->immutable=IsStringTrue(resource_value);
3562  resource_value=XGetResourceClass(database,client_name,"magnify",
3563  (char *) "3");
3564  resource_info->magnify=(unsigned int) StringToUnsignedLong(resource_value);
3565  resource_info->map_type=XGetResourceClass(database,client_name,"map",
3566  (char *) NULL);
3567  resource_info->matte_color=XGetResourceInstance(database,client_name,
3568  "mattecolor",(char *) NULL);
3569  resource_info->name=ConstantString(XGetResourceClass(database,client_name,
3570  "name",(char *) NULL));
3571  resource_info->pen_colors[0]=XGetResourceClass(database,client_name,"pen1",
3572  (char *) "black");
3573  resource_info->pen_colors[1]=XGetResourceClass(database,client_name,"pen2",
3574  (char *) "blue");
3575  resource_info->pen_colors[2]=XGetResourceClass(database,client_name,"pen3",
3576  (char *) "cyan");
3577  resource_info->pen_colors[3]=XGetResourceClass(database,client_name,"pen4",
3578  (char *) "green");
3579  resource_info->pen_colors[4]=XGetResourceClass(database,client_name,"pen5",
3580  (char *) "gray");
3581  resource_info->pen_colors[5]=XGetResourceClass(database,client_name,"pen6",
3582  (char *) "red");
3583  resource_info->pen_colors[6]=XGetResourceClass(database,client_name,"pen7",
3584  (char *) "magenta");
3585  resource_info->pen_colors[7]=XGetResourceClass(database,client_name,"pen8",
3586  (char *) "yellow");
3587  resource_info->pen_colors[8]=XGetResourceClass(database,client_name,"pen9",
3588  (char *) "white");
3589  resource_info->pen_colors[9]=XGetResourceClass(database,client_name,"pen0",
3590  (char *) "gray");
3591  resource_info->pen_colors[10]=XGetResourceClass(database,client_name,"pen0",
3592  (char *) "gray");
3593  resource_value=XGetResourceClass(database,client_name,"pause",(char *) "0");
3594  resource_info->pause=(unsigned int) StringToUnsignedLong(resource_value);
3595  resource_value=XGetResourceClass(database,client_name,"quantum",(char *) "1");
3596  resource_info->quantum=StringToLong(resource_value);
3597  resource_info->text_font=XGetResourceClass(database,client_name,(char *)
3598  "font",(char *) "fixed");
3599  resource_info->text_font=XGetResourceClass(database,client_name,
3600  "textFontList",resource_info->text_font);
3601  resource_info->title=XGetResourceClass(database,client_name,"title",
3602  (char *) NULL);
3603  resource_value=XGetResourceClass(database,client_name,"undoCache",
3604  (char *) "256");
3605  resource_info->undo_cache=(unsigned int) StringToUnsignedLong(resource_value);
3606  resource_value=XGetResourceClass(database,client_name,"update",
3607  (char *) "False");
3608  resource_info->update=IsStringTrue(resource_value);
3609  resource_value=XGetResourceClass(database,client_name,"usePixmap",
3610  (char *) "True");
3611  resource_info->use_pixmap=IsStringTrue(resource_value);
3612  resource_value=XGetResourceClass(database,client_name,"sharedMemory",
3613  (char *) "True");
3614  resource_info->use_shared_memory=IsStringTrue(resource_value);
3615  resource_info->visual_type=XGetResourceClass(database,client_name,"visual",
3616  (char *) NULL);
3617  resource_info->window_group=XGetResourceClass(database,client_name,
3618  "windowGroup",(char *) NULL);
3619  resource_info->window_id=XGetResourceClass(database,client_name,"window",
3620  (char *) NULL);
3621  resource_info->write_filename=XGetResourceClass(database,client_name,
3622  "writeFilename",(char *) NULL);
3623 }
3624 
3625 /*
3626 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3627 % %
3628 % %
3629 % %
3630 % X G e t R e s o u r c e I n s t a n c e %
3631 % %
3632 % %
3633 % %
3634 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3635 %
3636 % XGetResourceInstance() queries the X server for the specified resource name.
3637 % If the resource name is not defined in the database, the supplied default
3638 % value is returned.
3639 %
3640 % The format of the XGetResourceInstance method is:
3641 %
3642 % char *XGetResourceInstance(XrmDatabase database,const char *client_name,
3643 % const char *keyword,const char *resource_default)
3644 %
3645 % A description of each parameter follows:
3646 %
3647 % o database: Specifies a resource database; returned from
3648 % XrmGetStringDatabase.
3649 %
3650 % o client_name: Specifies the application name used to retrieve
3651 % resource info from the X server database.
3652 %
3653 % o keyword: Specifies the keyword of the value being retrieved.
3654 %
3655 % o resource_default: Specifies the default value to return if the query
3656 % fails to find the specified keyword/class.
3657 %
3658 */
3659 MagickExport char *XGetResourceInstance(XrmDatabase database,
3660  const char *client_name,const char *keyword,const char *resource_default)
3661 {
3662  char
3663  *resource_type,
3664  resource_name[MagickPathExtent];
3665 
3666  Status
3667  status;
3668 
3669  XrmValue
3670  resource_value;
3671 
3672  if (database == (XrmDatabase) NULL)
3673  return((char *) resource_default);
3674  *resource_name='\0';
3675  if (keyword != (char *) NULL)
3676  (void) FormatLocaleString(resource_name,MagickPathExtent,"%s.%s",client_name,
3677  keyword);
3678  status=XrmGetResource(database,resource_name,"ImageMagick",&resource_type,
3679  &resource_value);
3680  if (status == False)
3681  return((char *) resource_default);
3682  return(resource_value.addr);
3683 }
3684 
3685 /*
3686 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3687 % %
3688 % %
3689 % %
3690 % X G e t S c r e e n D e n s i t y %
3691 % %
3692 % %
3693 % %
3694 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3695 %
3696 % XGetScreenDensity() returns the density of the X server screen in
3697 % dots-per-inch.
3698 %
3699 % The format of the XGetScreenDensity method is:
3700 %
3701 % char *XGetScreenDensity(Display *display)
3702 %
3703 % A description of each parameter follows:
3704 %
3705 % o density: XGetScreenDensity() returns the density of the X screen in
3706 % dots-per-inch.
3707 %
3708 % o display: Specifies a connection to an X server; returned from
3709 % XOpenDisplay.
3710 %
3711 */
3712 MagickExport char *XGetScreenDensity(Display *display)
3713 {
3714  char
3715  density[MagickPathExtent];
3716 
3717  double
3718  x_density,
3719  y_density;
3720 
3721  /*
3722  Set density as determined by screen size.
3723  */
3724  x_density=((((double) DisplayWidth(display,XDefaultScreen(display)))*25.4)/
3725  ((double) DisplayWidthMM(display,XDefaultScreen(display))));
3726  y_density=((((double) DisplayHeight(display,XDefaultScreen(display)))*25.4)/
3727  ((double) DisplayHeightMM(display,XDefaultScreen(display))));
3728  (void) FormatLocaleString(density,MagickPathExtent,"%gx%g",x_density,
3729  y_density);
3730  return(GetPageGeometry(density));
3731 }
3732 
3733 /*
3734 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3735 % %
3736 % %
3737 % %
3738 + X G e t S u b w i n d o w %
3739 % %
3740 % %
3741 % %
3742 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3743 %
3744 % XGetSubwindow() returns the subwindow of a window chosen the user with the
3745 % pointer and a button press.
3746 %
3747 % The format of the XGetSubwindow method is:
3748 %
3749 % Window XGetSubwindow(Display *display,Window window,int x,int y)
3750 %
3751 % A description of each parameter follows:
3752 %
3753 % o subwindow: XGetSubwindow() returns NULL if no subwindow is found
3754 % otherwise the subwindow is returned.
3755 %
3756 % o display: Specifies a connection to an X server; returned from
3757 % XOpenDisplay.
3758 %
3759 % o window: Specifies a pointer to a Window.
3760 %
3761 % o x: the x coordinate of the pointer relative to the origin of the
3762 % window.
3763 %
3764 % o y: the y coordinate of the pointer relative to the origin of the
3765 % window.
3766 %
3767 */
3768 static Window XGetSubwindow(Display *display,Window window,int x,int y)
3769 {
3770  int
3771  x_offset,
3772  y_offset;
3773 
3774  Status
3775  status;
3776 
3777  Window
3778  source_window,
3779  target_window;
3780 
3781  assert(display != (Display *) NULL);
3782  source_window=XRootWindow(display,XDefaultScreen(display));
3783  if (window == (Window) NULL)
3784  return(source_window);
3785  target_window=window;
3786  for ( ; ; )
3787  {
3788  status=XTranslateCoordinates(display,source_window,window,x,y,
3789  &x_offset,&y_offset,&target_window);
3790  if (status != True)
3791  break;
3792  if (target_window == (Window) NULL)
3793  break;
3794  source_window=window;
3795  window=target_window;
3796  x=x_offset;
3797  y=y_offset;
3798  }
3799  if (target_window == (Window) NULL)
3800  target_window=window;
3801  return(target_window);
3802 }
3803 
3804 /*
3805 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3806 % %
3807 % %
3808 % %
3809 % X G e t W i n d o w C o l o r %
3810 % %
3811 % %
3812 % %
3813 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3814 %
3815 % XGetWindowColor() returns the color of a pixel interactively chosen from the
3816 % X server.
3817 %
3818 % The format of the XGetWindowColor method is:
3819 %
3820 % MagickBooleanType XGetWindowColor(Display *display,XWindows *windows,
3821 % char *name,ExceptionInfo *exception)
3822 %
3823 % A description of each parameter follows:
3824 %
3825 % o display: Specifies a connection to an X server; returned from
3826 % XOpenDisplay.
3827 %
3828 % o windows: Specifies a pointer to a XWindows structure.
3829 %
3830 % o name: the name of the color if found in the X Color Database is
3831 % returned in this character string.
3832 %
3833 % o exception: return any errors or warnings in this structure.
3834 %
3835 */
3836 MagickPrivate MagickBooleanType XGetWindowColor(Display *display,
3837  XWindows *windows,char *name,ExceptionInfo *exception)
3838 {
3839  int
3840  x,
3841  y;
3842 
3843  PixelInfo
3844  pixel;
3845 
3847  crop_info;
3848 
3849  Status
3850  status;
3851 
3852  Window
3853  child,
3854  client_window,
3855  root_window,
3856  target_window;
3857 
3858  XColor
3859  color;
3860 
3861  XImage
3862  *ximage;
3863 
3864  XWindowAttributes
3865  window_attributes;
3866 
3867  /*
3868  Choose a pixel from the X server.
3869  */
3870  assert(display != (Display *) NULL);
3871  assert(name != (char *) NULL);
3872  (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",name);
3873  *name='\0';
3874  target_window=XSelectWindow(display,&crop_info);
3875  if (target_window == (Window) NULL)
3876  return(MagickFalse);
3877  root_window=XRootWindow(display,XDefaultScreen(display));
3878  client_window=target_window;
3879  if (target_window != root_window)
3880  {
3881  unsigned int
3882  d;
3883 
3884  /*
3885  Get client window.
3886  */
3887  status=XGetGeometry(display,target_window,&root_window,&x,&x,&d,&d,&d,&d);
3888  if (status != False)
3889  {
3890  client_window=XClientWindow(display,target_window);
3891  target_window=client_window;
3892  }
3893  }
3894  /*
3895  Verify window is viewable.
3896  */
3897  status=XGetWindowAttributes(display,target_window,&window_attributes);
3898  if ((status == False) || (window_attributes.map_state != IsViewable))
3899  return(MagickFalse);
3900  /*
3901  Get window X image.
3902  */
3903  (void) XTranslateCoordinates(display,root_window,target_window,
3904  (int) crop_info.x,(int) crop_info.y,&x,&y,&child);
3905  ximage=XGetImage(display,target_window,x,y,1,1,AllPlanes,ZPixmap);
3906  if (ximage == (XImage *) NULL)
3907  return(MagickFalse);
3908  color.pixel=XGetPixel(ximage,0,0);
3909  XDestroyImage(ximage);
3910  /*
3911  Match color against the color database.
3912  */
3913  (void) XQueryColor(display,window_attributes.colormap,&color);
3914  pixel.red=(double) ScaleShortToQuantum(color.red);
3915  pixel.green=(double) ScaleShortToQuantum(color.green);
3916  pixel.blue=(double) ScaleShortToQuantum(color.blue);
3918  (void) QueryColorname(windows->image.image,&pixel,X11Compliance,name,
3919  exception);
3920  return(MagickTrue);
3921 }
3922 
3923 /*
3924 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3925 % %
3926 % %
3927 % %
3928 + X G e t W i n d o w I m a g e %
3929 % %
3930 % %
3931 % %
3932 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3933 %
3934 % XGetWindowImage() reads an image from the target X window and returns it.
3935 % XGetWindowImage() optionally descends the window hierarchy and overlays the
3936 % target image with each child image in an optimized fashion. Any child
3937 % window that have the same visual, colormap, and are contained by its parent
3938 % are exempted.
3939 %
3940 % The format of the XGetWindowImage method is:
3941 %
3942 % Image *XGetWindowImage(Display *display,const Window window,
3943 % const unsigned int borders,const unsigned int level,
3944 % ExceptionInfo *exception)
3945 %
3946 % A description of each parameter follows:
3947 %
3948 % o display: Specifies a connection to an X server; returned from
3949 % XOpenDisplay.
3950 %
3951 % o window: Specifies the window to obtain the image from.
3952 %
3953 % o borders: Specifies whether borders pixels are to be saved with
3954 % the image.
3955 %
3956 % o level: Specifies an unsigned integer representing the level of
3957 % decent in the window hierarchy. This value must be zero or one on
3958 % the initial call to XGetWindowImage. A value of zero returns after
3959 % one call. A value of one causes the function to descend the window
3960 % hierarchy and overlay the target image with each subwindow image.
3961 %
3962 % o exception: return any errors or warnings in this structure.
3963 %
3964 */
3965 static Image *XGetWindowImage(Display *display,const Window window,
3966  const unsigned int borders,const unsigned int level,ExceptionInfo *exception)
3967 {
3968  typedef struct _ColormapInfo
3969  {
3970  Colormap
3971  colormap;
3972 
3973  XColor
3974  *colors;
3975 
3976  struct _ColormapInfo
3977  *next;
3978  } ColormapInfo;
3979 
3980  typedef struct _WindowInfo
3981  {
3982  Window
3983  window,
3984  parent;
3985 
3986  Visual
3987  *visual;
3988 
3989  Colormap
3990  colormap;
3991 
3992  XSegment
3993  bounds;
3994 
3996  crop_info;
3997  } WindowInfo;
3998 
3999  int
4000  display_height,
4001  display_width,
4002  id,
4003  x_offset,
4004  y_offset;
4005 
4006  Quantum
4007  index;
4008 
4010  crop_info;
4011 
4012  register int
4013  i;
4014 
4015  static ColormapInfo
4016  *colormap_info = (ColormapInfo *) NULL;
4017 
4018  static int
4019  max_windows = 0,
4020  number_windows = 0;
4021 
4022  static WindowInfo
4023  *window_info;
4024 
4025  Status
4026  status;
4027 
4028  Window
4029  child,
4030  root_window;
4031 
4032  XWindowAttributes
4033  window_attributes;
4034 
4035  /*
4036  Verify window is viewable.
4037  */
4038  (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
4039  assert(display != (Display *) NULL);
4040  status=XGetWindowAttributes(display,window,&window_attributes);
4041  if ((status == False) || (window_attributes.map_state != IsViewable))
4042  return((Image *) NULL);
4043  /*
4044  Cropping rectangle is relative to root window.
4045  */
4046  root_window=XRootWindow(display,XDefaultScreen(display));
4047  (void) XTranslateCoordinates(display,window,root_window,0,0,&x_offset,
4048  &y_offset,&child);
4049  crop_info.x=(ssize_t) x_offset;
4050  crop_info.y=(ssize_t) y_offset;
4051  crop_info.width=(size_t) window_attributes.width;
4052  crop_info.height=(size_t) window_attributes.height;
4053  if (borders != MagickFalse)
4054  {
4055  /*
4056  Include border in image.
4057  */
4058  crop_info.x-=(ssize_t) window_attributes.border_width;
4059  crop_info.y-=(ssize_t) window_attributes.border_width;
4060  crop_info.width+=(size_t) (window_attributes.border_width << 1);
4061  crop_info.height+=(size_t) (window_attributes.border_width << 1);
4062  }
4063  /*
4064  Crop to root window.
4065  */
4066  if (crop_info.x < 0)
4067  {
4068  crop_info.width+=crop_info.x;
4069  crop_info.x=0;
4070  }
4071  if (crop_info.y < 0)
4072  {
4073  crop_info.height+=crop_info.y;
4074  crop_info.y=0;
4075  }
4076  display_width=XDisplayWidth(display,XDefaultScreen(display));
4077  if ((int) (crop_info.x+crop_info.width) > display_width)
4078  crop_info.width=(size_t) (display_width-crop_info.x);
4079  display_height=XDisplayHeight(display,XDefaultScreen(display));
4080  if ((int) (crop_info.y+crop_info.height) > display_height)
4081  crop_info.height=(size_t) (display_height-crop_info.y);
4082  /*
4083  Initialize window info attributes.
4084  */
4085  if (number_windows >= max_windows)
4086  {
4087  /*
4088  Allocate or resize window info buffer.
4089  */
4090  max_windows+=1024;
4091  if (window_info == (WindowInfo *) NULL)
4092  window_info=(WindowInfo *) AcquireQuantumMemory((size_t) max_windows,
4093  sizeof(*window_info));
4094  else
4095  window_info=(WindowInfo *) ResizeQuantumMemory(window_info,(size_t)
4096  max_windows,sizeof(*window_info));
4097  }
4098  if (window_info == (WindowInfo *) NULL)
4099  {
4100  ThrowXWindowException(ResourceLimitError,"MemoryAllocationFailed","...");
4101  return((Image *) NULL);
4102  }
4103  id=number_windows++;
4104  window_info[id].window=window;
4105  window_info[id].visual=window_attributes.visual;
4106  window_info[id].colormap=window_attributes.colormap;
4107  window_info[id].bounds.x1=(short) crop_info.x;
4108  window_info[id].bounds.y1=(short) crop_info.y;
4109  window_info[id].bounds.x2=(short) (crop_info.x+(int) crop_info.width-1);
4110  window_info[id].bounds.y2=(short) (crop_info.y+(int) crop_info.height-1);
4111  crop_info.x-=x_offset;
4112  crop_info.y-=y_offset;
4113  window_info[id].crop_info=crop_info;
4114  if (level != 0)
4115  {
4116  unsigned int
4117  number_children;
4118 
4119  Window
4120  *children;
4121 
4122  /*
4123  Descend the window hierarchy.
4124  */
4125  status=XQueryTree(display,window,&root_window,&window_info[id].parent,
4126  &children,&number_children);
4127  for (i=0; i < id; i++)
4128  if ((window_info[i].window == window_info[id].parent) &&
4129  (window_info[i].visual == window_info[id].visual) &&
4130  (window_info[i].colormap == window_info[id].colormap))
4131  {
4132  if ((window_info[id].bounds.x1 < window_info[i].bounds.x1) ||
4133  (window_info[id].bounds.x2 > window_info[i].bounds.x2) ||
4134  (window_info[id].bounds.y1 < window_info[i].bounds.y1) ||
4135  (window_info[id].bounds.y2 > window_info[i].bounds.y2))
4136  {
4137  /*
4138  Eliminate windows not circumscribed by their parent.
4139  */
4140  number_windows--;
4141  break;
4142  }
4143  }
4144  if ((status == True) && (number_children != 0))
4145  {
4146  for (i=0; i < (int) number_children; i++)
4147  (void) XGetWindowImage(display,children[i],MagickFalse,level+1,
4148  exception);
4149  (void) XFree((void *) children);
4150  }
4151  }
4152  if (level <= 1)
4153  {
4154  CacheView
4155  *composite_view;
4156 
4157  ColormapInfo
4158  *next;
4159 
4160  Image
4161  *composite_image,
4162  *image;
4163 
4164  int
4165  y;
4166 
4168  import;
4169 
4170  register int
4171  j,
4172  x;
4173 
4174  register Quantum
4175  *magick_restrict q;
4176 
4177  register size_t
4178  pixel;
4179 
4180  unsigned int
4181  number_colors;
4182 
4183  XColor
4184  *colors;
4185 
4186  XImage
4187  *ximage;
4188 
4189  /*
4190  Get X image for each window in the list.
4191  */
4192  image=NewImageList();
4193  for (id=0; id < number_windows; id++)
4194  {
4195  /*
4196  Does target window intersect top level window?
4197  */
4198  import=((window_info[id].bounds.x2 >= window_info[0].bounds.x1) &&
4199  (window_info[id].bounds.x1 <= window_info[0].bounds.x2) &&
4200  (window_info[id].bounds.y2 >= window_info[0].bounds.y1) &&
4201  (window_info[id].bounds.y1 <= window_info[0].bounds.y2)) ?
4203  /*
4204  Is target window contained by another window with the same colormap?
4205  */
4206  for (j=0; j < id; j++)
4207  if ((window_info[id].visual == window_info[j].visual) &&
4208  (window_info[id].colormap == window_info[j].colormap))
4209  {
4210  if ((window_info[id].bounds.x1 >= window_info[j].bounds.x1) &&
4211  (window_info[id].bounds.x2 <= window_info[j].bounds.x2) &&
4212  (window_info[id].bounds.y1 >= window_info[j].bounds.y1) &&
4213  (window_info[id].bounds.y2 <= window_info[j].bounds.y2))
4214  import=MagickFalse;
4215  }
4216  if (import == MagickFalse)
4217  continue;
4218  /*
4219  Get X image.
4220  */
4221  ximage=XGetImage(display,window_info[id].window,(int)
4222  window_info[id].crop_info.x,(int) window_info[id].crop_info.y,
4223  (unsigned int) window_info[id].crop_info.width,(unsigned int)
4224  window_info[id].crop_info.height,AllPlanes,ZPixmap);
4225  if (ximage == (XImage *) NULL)
4226  continue;
4227  /*
4228  Initialize window colormap.
4229  */
4230  number_colors=0;
4231  colors=(XColor *) NULL;
4232  if (window_info[id].colormap != (Colormap) NULL)
4233  {
4234  ColormapInfo
4235  *p;
4236 
4237  /*
4238  Search colormap list for window colormap.
4239  */
4240  number_colors=(unsigned int) window_info[id].visual->map_entries;
4241  for (p=colormap_info; p != (ColormapInfo *) NULL; p=p->next)
4242  if (p->colormap == window_info[id].colormap)
4243  break;
4244  if (p == (ColormapInfo *) NULL)
4245  {
4246  /*
4247  Get the window colormap.
4248  */
4249  colors=(XColor *) AcquireQuantumMemory(number_colors,
4250  sizeof(*colors));
4251  if (colors == (XColor *) NULL)
4252  {
4253  XDestroyImage(ximage);
4254  return((Image *) NULL);
4255  }
4256  if ((window_info[id].visual->klass != DirectColor) &&
4257  (window_info[id].visual->klass != TrueColor))
4258  for (i=0; i < (int) number_colors; i++)
4259  {
4260  colors[i].pixel=(size_t) i;
4261  colors[i].pad='\0';
4262  }
4263  else
4264  {
4265  size_t
4266  blue,
4267  blue_bit,
4268  green,
4269  green_bit,
4270  red,
4271  red_bit;
4272 
4273  /*
4274  DirectColor or TrueColor visual.
4275  */
4276  red=0;
4277  green=0;
4278  blue=0;
4279  red_bit=window_info[id].visual->red_mask &
4280  (~(window_info[id].visual->red_mask)+1);
4281  green_bit=window_info[id].visual->green_mask &
4282  (~(window_info[id].visual->green_mask)+1);
4283  blue_bit=window_info[id].visual->blue_mask &
4284  (~(window_info[id].visual->blue_mask)+1);
4285  for (i=0; i < (int) number_colors; i++)
4286  {
4287  colors[i].pixel=(unsigned long) (red | green | blue);
4288  colors[i].pad='\0';
4289  red+=red_bit;
4290  if (red > window_info[id].visual->red_mask)
4291  red=0;
4292  green+=green_bit;
4293  if (green > window_info[id].visual->green_mask)
4294  green=0;
4295  blue+=blue_bit;
4296  if (blue > window_info[id].visual->blue_mask)
4297  blue=0;
4298  }
4299  }
4300  (void) XQueryColors(display,window_info[id].colormap,colors,
4301  (int) number_colors);
4302  /*
4303  Append colormap to colormap list.
4304  */
4305  p=(ColormapInfo *) AcquireMagickMemory(sizeof(*p));
4306  if (p == (ColormapInfo *) NULL)
4307  return((Image *) NULL);
4308  p->colormap=window_info[id].colormap;
4309  p->colors=colors;
4310  p->next=colormap_info;
4311  colormap_info=p;
4312  }
4313  colors=p->colors;
4314  }
4315  /*
4316  Allocate image structure.
4317  */
4318  composite_image=AcquireImage((ImageInfo *) NULL,exception);
4319  if (composite_image == (Image *) NULL)
4320  {
4321  XDestroyImage(ximage);
4322  return((Image *) NULL);
4323  }
4324  /*
4325  Convert X image to MIFF format.
4326  */
4327  if ((window_info[id].visual->klass != TrueColor) &&
4328  (window_info[id].visual->klass != DirectColor))
4329  composite_image->storage_class=PseudoClass;
4330  composite_image->columns=(size_t) ximage->width;
4331  composite_image->rows=(size_t) ximage->height;
4332  composite_view=AcquireAuthenticCacheView(composite_image,exception);
4333  switch (composite_image->storage_class)
4334  {
4335  case DirectClass:
4336  default:
4337  {
4338  register size_t
4339  color,
4340  index;
4341 
4342  size_t
4343  blue_mask,
4344  blue_shift,
4345  green_mask,
4346  green_shift,
4347  red_mask,
4348  red_shift;
4349 
4350  /*
4351  Determine shift and mask for red, green, and blue.
4352  */
4353  red_mask=window_info[id].visual->red_mask;
4354  red_shift=0;
4355  while ((red_mask != 0) && ((red_mask & 0x01) == 0))
4356  {
4357  red_mask>>=1;
4358  red_shift++;
4359  }
4360  green_mask=window_info[id].visual->green_mask;
4361  green_shift=0;
4362  while ((green_mask != 0) && ((green_mask & 0x01) == 0))
4363  {
4364  green_mask>>=1;
4365  green_shift++;
4366  }
4367  blue_mask=window_info[id].visual->blue_mask;
4368  blue_shift=0;
4369  while ((blue_mask != 0) && ((blue_mask & 0x01) == 0))
4370  {
4371  blue_mask>>=1;
4372  blue_shift++;
4373  }
4374  /*
4375  Convert X image to DirectClass packets.
4376  */
4377  if ((number_colors != 0) &&
4378  (window_info[id].visual->klass == DirectColor))
4379  for (y=0; y < (int) composite_image->rows; y++)
4380  {
4381  q=QueueCacheViewAuthenticPixels(composite_view,0,(ssize_t) y,
4382  composite_image->columns,1,exception);
4383  if (q == (Quantum *) NULL)
4384  break;
4385  for (x=0; x < (int) composite_image->columns; x++)
4386  {
4387  pixel=XGetPixel(ximage,x,y);
4388  index=(pixel >> red_shift) & red_mask;
4389  SetPixelRed(composite_image,
4390  ScaleShortToQuantum(colors[index].red),q);
4391  index=(pixel >> green_shift) & green_mask;
4392  SetPixelGreen(composite_image,
4393  ScaleShortToQuantum(colors[index].green),q);
4394  index=(pixel >> blue_shift) & blue_mask;
4395  SetPixelBlue(composite_image,
4396  ScaleShortToQuantum(colors[index].blue),q);
4397  q+=GetPixelChannels(composite_image);
4398  }
4399  status=SyncCacheViewAuthenticPixels(composite_view,exception);
4400  if (status == MagickFalse)
4401  break;
4402  }
4403  else
4404  for (y=0; y < (int) composite_image->rows; y++)
4405  {
4406  q=QueueCacheViewAuthenticPixels(composite_view,0,(ssize_t) y,
4407  composite_image->columns,1,exception);
4408  if (q == (Quantum *) NULL)
4409  break;
4410  for (x=0; x < (int) composite_image->columns; x++)
4411  {
4412  pixel=XGetPixel(ximage,x,y);
4413  color=(pixel >> red_shift) & red_mask;
4414  if (red_mask != 0)
4415  color=(65535UL*color)/red_mask;
4416  SetPixelRed(composite_image,ScaleShortToQuantum(
4417  (unsigned short) color),q);
4418  color=(pixel >> green_shift) & green_mask;
4419  if (green_mask != 0)
4420  color=(65535UL*color)/green_mask;
4421  SetPixelGreen(composite_image,ScaleShortToQuantum(
4422  (unsigned short) color),q);
4423  color=(pixel >> blue_shift) & blue_mask;
4424  if (blue_mask != 0)
4425  color=(65535UL*color)/blue_mask;
4426  SetPixelBlue(composite_image,ScaleShortToQuantum(
4427  (unsigned short) color),q);
4428  q+=GetPixelChannels(composite_image);
4429  }
4430  status=SyncCacheViewAuthenticPixels(composite_view,exception);
4431  if (status == MagickFalse)
4432  break;
4433  }
4434  break;
4435  }
4436  case PseudoClass:
4437  {
4438  /*
4439  Create colormap.
4440  */
4441  status=AcquireImageColormap(composite_image,number_colors,
4442  exception);
4443  if (status == MagickFalse)
4444  {
4445  XDestroyImage(ximage);
4446  composite_image=DestroyImage(composite_image);
4447  return((Image *) NULL);
4448  }
4449  for (i=0; i < (int) composite_image->colors; i++)
4450  {
4451  composite_image->colormap[colors[i].pixel].red=(double)
4452  ScaleShortToQuantum(colors[i].red);
4453  composite_image->colormap[colors[i].pixel].green=(double)
4454  ScaleShortToQuantum(colors[i].green);
4455  composite_image->colormap[colors[i].pixel].blue=(double)
4456  ScaleShortToQuantum(colors[i].blue);
4457  }
4458  /*
4459  Convert X image to PseudoClass packets.
4460  */
4461  for (y=0; y < (int) composite_image->rows; y++)
4462  {
4463  q=QueueCacheViewAuthenticPixels(composite_view,0,(ssize_t) y,
4464  composite_image->columns,1,exception);
4465  if (q == (Quantum *) NULL)
4466  break;
4467  for (x=0; x < (int) composite_image->columns; x++)
4468  {
4469  index=(Quantum) XGetPixel(ximage,x,y);
4470  SetPixelIndex(composite_image,index,q);
4471  SetPixelViaPixelInfo(composite_image,
4472  composite_image->colormap+(ssize_t) index,q);
4473  q+=GetPixelChannels(composite_image);
4474  }
4475  status=SyncCacheViewAuthenticPixels(composite_view,exception);
4476  if (status == MagickFalse)
4477  break;
4478  }
4479  break;
4480  }
4481  }
4482  composite_view=DestroyCacheView(composite_view);
4483  XDestroyImage(ximage);
4484  if (image == (Image *) NULL)
4485  {
4486  image=composite_image;
4487  continue;
4488  }
4489  /*
4490  Composite any children in back-to-front order.
4491  */
4492  (void) XTranslateCoordinates(display,window_info[id].window,window,0,0,
4493  &x_offset,&y_offset,&child);
4494  x_offset-=(int) crop_info.x;
4495  if (x_offset < 0)
4496  x_offset=0;
4497  y_offset-=(int) crop_info.y;
4498  if (y_offset < 0)
4499  y_offset=0;
4500  (void) CompositeImage(image,composite_image,CopyCompositeOp,MagickTrue,
4501  (ssize_t) x_offset,(ssize_t) y_offset,exception);
4502  composite_image=DestroyImage(composite_image);
4503  }
4504  /*
4505  Relinquish resources.
4506  */
4507  while (colormap_info != (ColormapInfo *) NULL)
4508  {
4509  next=colormap_info->next;
4510  colormap_info->colors=(XColor *) RelinquishMagickMemory(
4511  colormap_info->colors);
4512  colormap_info=(ColormapInfo *) RelinquishMagickMemory(colormap_info);
4513  colormap_info=next;
4514  }
4515  /*
4516  Relinquish resources and restore initial state.
4517  */
4518  window_info=(WindowInfo *) RelinquishMagickMemory(window_info);
4519  max_windows=0;
4520  number_windows=0;
4521  colormap_info=(ColormapInfo *) NULL;
4522  return(image);
4523  }
4524  return((Image *) NULL);
4525 }
4526 
4527 /*
4528 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4529 % %
4530 % %
4531 % %
4532 % X G e t W i n d o w I n f o %
4533 % %
4534 % %
4535 % %
4536 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4537 %
4538 % XGetWindowInfo() initializes the XWindowInfo structure.
4539 %
4540 % The format of the XGetWindowInfo method is:
4541 %
4542 % void XGetWindowInfo(Display *display,XVisualInfo *visual_info,
4543 % XStandardColormap *map_info,XPixelInfo *pixel,XFontStruct *font_info,
4544 % XResourceInfo *resource_info,XWindowInfo *window)
4545 % resource_info,window)
4546 %
4547 % A description of each parameter follows:
4548 %
4549 % o display: Specifies a connection to an X server; returned from
4550 % XOpenDisplay.
4551 %
4552 % o visual_info: Specifies a pointer to a X11 XVisualInfo structure;
4553 % returned from XGetVisualInfo.
4554 %
4555 % o map_info: If map_type is specified, this structure is initialized
4556 % with info from the Standard Colormap.
4557 %
4558 % o pixel: Specifies a pointer to a XPixelInfo structure.
4559 %
4560 % o font_info: Specifies a pointer to a XFontStruct structure.
4561 %
4562 % o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
4563 %
4564 */
4565 MagickPrivate void XGetWindowInfo(Display *display,XVisualInfo *visual_info,
4566  XStandardColormap *map_info,XPixelInfo *pixel,XFontStruct *font_info,
4567  XResourceInfo *resource_info,XWindowInfo *window)
4568 {
4569  /*
4570  Initialize window info.
4571  */
4572  (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
4573  assert(display != (Display *) NULL);
4574  assert(visual_info != (XVisualInfo *) NULL);
4575  assert(map_info != (XStandardColormap *) NULL);
4576  assert(pixel != (XPixelInfo *) NULL);
4577  assert(resource_info != (XResourceInfo *) NULL);
4578  assert(window != (XWindowInfo *) NULL);
4579  if (window->id != (Window) NULL)
4580  {
4581  if (window->cursor != (Cursor) NULL)
4582  (void) XFreeCursor(display,window->cursor);
4583  if (window->busy_cursor != (Cursor) NULL)
4584  (void) XFreeCursor(display,window->busy_cursor);
4585  if (window->highlight_stipple != (Pixmap) NULL)
4586  (void) XFreePixmap(display,window->highlight_stipple);
4587  if (window->shadow_stipple != (Pixmap) NULL)
4588  (void) XFreePixmap(display,window->shadow_stipple);
4589  if (window->name == (char *) NULL)
4590  window->name=AcquireString("");
4591  if (window->icon_name == (char *) NULL)
4592  window->icon_name=AcquireString("");
4593  }
4594  else
4595  {
4596  /*
4597  Initialize these attributes just once.
4598  */
4599  window->id=(Window) NULL;
4600  if (window->name == (char *) NULL)
4601  window->name=AcquireString("");
4602  if (window->icon_name == (char *) NULL)
4603  window->icon_name=AcquireString("");
4604  window->x=XDisplayWidth(display,visual_info->screen) >> 1;
4605  window->y=XDisplayWidth(display,visual_info->screen) >> 1;
4606  window->ximage=(XImage *) NULL;
4607  window->matte_image=(XImage *) NULL;
4608  window->pixmap=(Pixmap) NULL;
4609  window->matte_pixmap=(Pixmap) NULL;
4610  window->mapped=MagickFalse;
4611  window->stasis=MagickFalse;
4612  window->shared_memory=MagickTrue;
4613  window->segment_info=(void *) NULL;
4614 #if defined(MAGICKCORE_HAVE_SHARED_MEMORY)
4615  {
4616  XShmSegmentInfo
4617  *segment_info;
4618 
4619  if (window->segment_info == (void *) NULL)
4620  window->segment_info=AcquireCriticalMemory(2*sizeof(*segment_info));
4621  segment_info=(XShmSegmentInfo *) window->segment_info;
4622  segment_info[0].shmid=(-1);
4623  segment_info[0].shmaddr=(char *) NULL;
4624  segment_info[1].shmid=(-1);
4625  segment_info[1].shmaddr=(char *) NULL;
4626  }
4627 #endif
4628  }
4629  /*
4630  Initialize these attributes every time function is called.
4631  */
4632  window->screen=visual_info->screen;
4633  window->root=XRootWindow(display,visual_info->screen);
4634  window->visual=visual_info->visual;
4635  window->storage_class=(unsigned int) visual_info->klass;
4636  window->depth=(unsigned int) visual_info->depth;
4637  window->visual_info=visual_info;
4638  window->map_info=map_info;
4639  window->pixel_info=pixel;
4640  window->font_info=font_info;
4641  window->cursor=XCreateFontCursor(display,XC_left_ptr);
4642  window->busy_cursor=XCreateFontCursor(display,XC_watch);
4643  window->geometry=(char *) NULL;
4644  window->icon_geometry=(char *) NULL;
4645  if (resource_info->icon_geometry != (char *) NULL)
4646  (void) CloneString(&window->icon_geometry,resource_info->icon_geometry);
4647  window->crop_geometry=(char *) NULL;
4648  window->flags=(size_t) PSize;
4649  window->width=1;
4650  window->height=1;
4651  window->min_width=1;
4652  window->min_height=1;
4653  window->width_inc=1;
4654  window->height_inc=1;
4655  window->border_width=resource_info->border_width;
4656  window->annotate_context=pixel->annotate_context;
4657  window->highlight_context=pixel->highlight_context;
4658  window->widget_context=pixel->widget_context;
4659  window->shadow_stipple=(Pixmap) NULL;
4660  window->highlight_stipple=(Pixmap) NULL;
4661  window->use_pixmap=MagickTrue;
4662  window->immutable=MagickFalse;
4663  window->shape=MagickFalse;
4664  window->data=0;
4665  window->mask=(int) (CWBackingStore | CWBackPixel | CWBackPixmap |
4666  CWBitGravity | CWBorderPixel | CWColormap | CWCursor | CWDontPropagate |
4667  CWEventMask | CWOverrideRedirect | CWSaveUnder | CWWinGravity);
4668  window->attributes.background_pixel=pixel->background_color.pixel;
4669  window->attributes.background_pixmap=(Pixmap) NULL;
4670  window->attributes.bit_gravity=ForgetGravity;
4671  window->attributes.backing_store=WhenMapped;
4672  window->attributes.save_under=MagickTrue;
4673  window->attributes.border_pixel=pixel->border_color.pixel;
4674  window->attributes.colormap=map_info->colormap;
4675  window->attributes.cursor=window->cursor;
4676  window->attributes.do_not_propagate_mask=NoEventMask;
4677  window->attributes.event_mask=NoEventMask;
4678  window->attributes.override_redirect=MagickFalse;
4679  window->attributes.win_gravity=NorthWestGravity;
4680  window->orphan=MagickFalse;
4681 }
4682 
4683 /*
4684 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4685 % %
4686 % %
4687 % %
4688 % X H i g h l i g h t E l l i p s e %
4689 % %
4690 % %
4691 % %
4692 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4693 %
4694 % XHighlightEllipse() puts a border on the X server around a region defined by
4695 % highlight_info.
4696 %
4697 % The format of the XHighlightEllipse method is:
4698 %
4699 % void XHighlightEllipse(Display *display,Window window,
4700 % GC annotate_context,const RectangleInfo *highlight_info)
4701 %
4702 % A description of each parameter follows:
4703 %
4704 % o display: Specifies a connection to an X server; returned from
4705 % XOpenDisplay.
4706 %
4707 % o window: Specifies a pointer to a Window structure.
4708 %
4709 % o annotate_context: Specifies a pointer to a GC structure.
4710 %
4711 % o highlight_info: Specifies a pointer to a RectangleInfo structure. It
4712 % contains the extents of any highlighting rectangle.
4713 %
4714 */
4715 MagickPrivate void XHighlightEllipse(Display *display,Window window,
4716  GC annotate_context,const RectangleInfo *highlight_info)
4717 {
4718  (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
4719  assert(display != (Display *) NULL);
4720  assert(window != (Window) NULL);
4721  assert(annotate_context != (GC) NULL);
4722  assert(highlight_info != (RectangleInfo *) NULL);
4723  if ((highlight_info->width < 4) || (highlight_info->height < 4))
4724  return;
4725  (void) XDrawArc(display,window,annotate_context,(int) highlight_info->x,
4726  (int) highlight_info->y,(unsigned int) highlight_info->width-1,
4727  (unsigned int) highlight_info->height-1,0,360*64);
4728  (void) XDrawArc(display,window,annotate_context,(int) highlight_info->x+1,
4729  (int) highlight_info->y+1,(unsigned int) highlight_info->width-3,
4730  (unsigned int) highlight_info->height-3,0,360*64);
4731 }
4732 
4733 /*
4734 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4735 % %
4736 % %
4737 % %
4738 % X H i g h l i g h t L i n e %
4739 % %
4740 % %
4741 % %
4742 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4743 %
4744 % XHighlightLine() puts a border on the X server around a region defined by
4745 % highlight_info.
4746 %
4747 % The format of the XHighlightLine method is:
4748 %
4749 % void XHighlightLine(Display *display,Window window,GC annotate_context,
4750 % const XSegment *highlight_info)
4751 %
4752 % A description of each parameter follows:
4753 %
4754 % o display: Specifies a connection to an X server; returned from
4755 % XOpenDisplay.
4756 %
4757 % o window: Specifies a pointer to a Window structure.
4758 %
4759 % o annotate_context: Specifies a pointer to a GC structure.
4760 %
4761 % o highlight_info: Specifies a pointer to a RectangleInfo structure. It
4762 % contains the extents of any highlighting rectangle.
4763 %
4764 */
4765 MagickPrivate void XHighlightLine(Display *display,Window window,
4766  GC annotate_context,const XSegment *highlight_info)
4767 {
4768  (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
4769  assert(display != (Display *) NULL);
4770  assert(window != (Window) NULL);
4771  assert(annotate_context != (GC) NULL);
4772  assert(highlight_info != (XSegment *) NULL);
4773  (void) XDrawLine(display,window,annotate_context,highlight_info->x1,
4774  highlight_info->y1,highlight_info->x2,highlight_info->y2);
4775 }
4776 
4777 /*
4778 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4779 % %
4780 % %
4781 % %
4782 % X H i g h l i g h t R e c t a n g l e %
4783 % %
4784 % %
4785 % %
4786 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4787 %
4788 % XHighlightRectangle() puts a border on the X server around a region defined
4789 % by highlight_info.
4790 %
4791 % The format of the XHighlightRectangle method is:
4792 %
4793 % void XHighlightRectangle(Display *display,Window window,
4794 % GC annotate_context,const RectangleInfo *highlight_info)
4795 %
4796 % A description of each parameter follows:
4797 %
4798 % o display: Specifies a connection to an X server; returned from
4799 % XOpenDisplay.
4800 %
4801 % o window: Specifies a pointer to a Window structure.
4802 %
4803 % o annotate_context: Specifies a pointer to a GC structure.
4804 %
4805 % o highlight_info: Specifies a pointer to a RectangleInfo structure. It
4806 % contains the extents of any highlighting rectangle.
4807 %
4808 */
4809 MagickPrivate void XHighlightRectangle(Display *display,Window window,
4810  GC annotate_context,const RectangleInfo *highlight_info)
4811 {
4812  assert(display != (Display *) NULL);
4813  (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
4814  assert(window != (Window) NULL);
4815  assert(annotate_context != (GC) NULL);
4816  assert(highlight_info != (RectangleInfo *) NULL);
4817  if ((highlight_info->width < 4) || (highlight_info->height < 4))
4818  return;
4819  (void) XDrawRectangle(display,window,annotate_context,(int) highlight_info->x,
4820  (int) highlight_info->y,(unsigned int) highlight_info->width-1,
4821  (unsigned int) highlight_info->height-1);
4822  (void) XDrawRectangle(display,window,annotate_context,(int) highlight_info->x+
4823  1,(int) highlight_info->y+1,(unsigned int) highlight_info->width-3,
4824  (unsigned int) highlight_info->height-3);
4825 }
4826 
4827 /*
4828 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4829 % %
4830 % %
4831 % %
4832 % X I m p o r t I m a g e %
4833 % %
4834 % %
4835 % %
4836 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4837 %
4838 % XImportImage() reads an image from an X window.
4839 %
4840 % The format of the XImportImage method is:
4841 %
4842 % Image *XImportImage(const ImageInfo *image_info,XImportInfo *ximage_info,
4843 % ExceptionInfo *exception)
4844 %
4845 % A description of each parameter follows:
4846 %
4847 % o image_info: the image info.
4848 %
4849 % o ximage_info: Specifies a pointer to an XImportInfo structure.
4850 %
4851 % o exception: return any errors or warnings in this structure.
4852 %
4853 */
4854 MagickExport Image *XImportImage(const ImageInfo *image_info,
4855  XImportInfo *ximage_info,ExceptionInfo *exception)
4856 {
4857  Colormap
4858  *colormaps;
4859 
4860  Display
4861  *display;
4862 
4863  Image
4864  *image;
4865 
4866  int
4867  number_colormaps,
4868  number_windows,
4869  x;
4870 
4872  crop_info;
4873 
4874  Status
4875  status;
4876 
4877  Window
4878  *children,
4879  client,
4880  prior_target,
4881  root,
4882  target;
4883 
4884  XTextProperty
4885  window_name;
4886 
4887  /*
4888  Open X server connection.
4889  */
4890  assert(image_info != (const ImageInfo *) NULL);
4891  assert(image_info->signature == MagickCoreSignature);
4892  if (image_info->debug != MagickFalse)
4894  image_info->filename);
4895  assert(ximage_info != (XImportInfo *) NULL);
4896  display=XOpenDisplay(image_info->server_name);
4897  if (display == (Display *) NULL)
4898  {
4899  ThrowXWindowException(XServerError,"UnableToOpenXServer",
4900  XDisplayName(image_info->server_name));
4901  return((Image *) NULL);
4902  }
4903  /*
4904  Set our forgiving exception handler.
4905  */
4906  (void) XSetErrorHandler(XError);
4907  /*
4908  Select target window.
4909  */
4910  crop_info.x=0;
4911  crop_info.y=0;
4912  crop_info.width=0;
4913  crop_info.height=0;
4914  root=XRootWindow(display,XDefaultScreen(display));
4915  target=(Window) NULL;
4916  if (*image_info->filename != '\0')
4917  {
4918  if (LocaleCompare(image_info->filename,"root") == 0)
4919  target=root;
4920  else
4921  {
4922  /*
4923  Select window by ID or name.
4924  */
4925  if (isdigit((int) ((unsigned char) *image_info->filename)) != 0)
4926  target=XWindowByID(display,root,(Window)
4927  strtol(image_info->filename,(char **) NULL,0));
4928  if (target == (Window) NULL)
4929  target=XWindowByName(display,root,image_info->filename);
4930  if (target == (Window) NULL)
4931  ThrowXWindowException(XServerError,"NoWindowWithSpecifiedIDExists",
4932  image_info->filename);
4933  }
4934  }
4935  /*
4936  If target window is not defined, interactively select one.
4937  */
4938  prior_target=target;
4939  if (target == (Window) NULL)
4940  target=XSelectWindow(display,&crop_info);
4941  if (target == (Window) NULL)
4942  ThrowXWindowException(XServerError,"UnableToReadXWindowImage",
4943  image_info->filename);
4944  client=target; /* obsolete */
4945  if (target != root)
4946  {
4947  unsigned int
4948  d;
4949 
4950  status=XGetGeometry(display,target,&root,&x,&x,&d,&d,&d,&d);
4951  if (status != False)
4952  {
4953  for ( ; ; )
4954  {
4955  Window
4956  parent;
4957 
4958  /*
4959  Find window manager frame.
4960  */
4961  status=XQueryTree(display,target,&root,&parent,&children,&d);
4962  if ((status != False) && (children != (Window *) NULL))
4963  (void) XFree((char *) children);
4964  if ((status == False) || (parent == (Window) NULL) ||
4965  (parent == root))
4966  break;
4967  target=parent;
4968  }
4969  /*
4970  Get client window.
4971  */
4972  client=XClientWindow(display,target);
4973  if (ximage_info->frame == MagickFalse)
4974  target=client;
4975  if ((ximage_info->frame == MagickFalse) &&
4976  (prior_target != MagickFalse))
4977  target=prior_target;
4978  }
4979  }
4980  if (ximage_info->screen)
4981  {
4982  int
4983  y;
4984 
4985  Window
4986  child;
4987 
4988  XWindowAttributes
4989  window_attributes;
4990 
4991  /*
4992  Obtain window image directly from screen.
4993  */
4994  status=XGetWindowAttributes(display,target,&window_attributes);
4995  if (status == False)
4996  {
4997  ThrowXWindowException(XServerError,"UnableToReadXWindowAttributes",
4998  image_info->filename);
4999  (void) XCloseDisplay(display);
5000  return((Image *) NULL);
5001  }
5002  (void) XTranslateCoordinates(display,target,root,0,0,&x,&y,&child);
5003  crop_info.x=(ssize_t) x;
5004  crop_info.y=(ssize_t) y;
5005  crop_info.width=(size_t) window_attributes.width;
5006  crop_info.height=(size_t) window_attributes.height;
5007  if (ximage_info->borders != 0)
5008  {
5009  /*
5010  Include border in image.
5011  */
5012  crop_info.x-=window_attributes.border_width;
5013  crop_info.y-=window_attributes.border_width;
5014  crop_info.width+=window_attributes.border_width << 1;
5015  crop_info.height+=window_attributes.border_width << 1;
5016  }
5017  target=root;
5018  }
5019  /*
5020  If WM_COLORMAP_WINDOWS property is set or multiple colormaps, descend.
5021  */
5022  number_windows=0;
5023  status=XGetWMColormapWindows(display,target,&children,&number_windows);
5024  if ((status == True) && (number_windows > 0))
5025  {
5026  ximage_info->descend=MagickTrue;
5027  (void) XFree ((char *) children);
5028  }
5029  colormaps=XListInstalledColormaps(display,target,&number_colormaps);
5030  if (number_colormaps > 0)
5031  {
5032  if (number_colormaps > 1)
5033  ximage_info->descend=MagickTrue;
5034  (void) XFree((char *) colormaps);
5035  }
5036  /*
5037  Alert the user not to alter the screen.
5038  */
5039  if (ximage_info->silent == MagickFalse)
5040  (void) XBell(display,0);
5041  /*
5042  Get image by window id.
5043  */
5044  (void) XGrabServer(display);
5045  image=XGetWindowImage(display,target,ximage_info->borders,
5046  ximage_info->descend ? 1U : 0U,exception);
5047  (void) XUngrabServer(display);
5048  if (image == (Image *) NULL)
5049  ThrowXWindowException(XServerError,"UnableToReadXWindowImage",
5050  image_info->filename)
5051  else
5052  {
5053  (void) CopyMagickString(image->filename,image_info->filename,
5054  MagickPathExtent);
5055  if ((crop_info.width != 0) && (crop_info.height != 0))
5056  {
5057  Image
5058  *clone_image,
5059  *crop_image;
5060 
5061  /*
5062  Crop image as defined by the cropping rectangle.
5063  */
5064  clone_image=CloneImage(image,0,0,MagickTrue,exception);
5065  if (clone_image != (Image *) NULL)
5066  {
5067  crop_image=CropImage(clone_image,&crop_info,exception);
5068  if (crop_image != (Image *) NULL)
5069  {
5070  image=DestroyImage(image);
5071  image=crop_image;
5072  }
5073  }
5074  }
5075  status=XGetWMName(display,target,&window_name);
5076  if (status == True)
5077  {
5078  if (*image_info->filename == '\0')
5079  (void) CopyMagickString(image->filename,(char *) window_name.value,
5080  (size_t) window_name.nitems+1);
5081  (void) XFree((void *) window_name.value);
5082  }
5083  }
5084  if (ximage_info->silent == MagickFalse)
5085  {
5086  /*
5087  Alert the user we're done.
5088  */
5089  (void) XBell(display,0);
5090  (void) XBell(display,0);
5091  }
5092  (void) XCloseDisplay(display);
5093  return(image);
5094 }
5095 
5096 /*
5097 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5098 % %
5099 % %
5100 % %
5101 % X I n i t i a l i z e W i n d o w s %
5102 % %
5103 % %
5104 % %
5105 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5106 %
5107 % XInitializeWindows() initializes the XWindows structure.
5108 %
5109 % The format of the XInitializeWindows method is:
5110 %
5111 % XWindows *XInitializeWindows(Display *display,
5112 % XResourceInfo *resource_info)
5113 %
5114 % A description of each parameter follows:
5115 %
5116 % o windows: XInitializeWindows returns a pointer to a XWindows structure.
5117 %
5118 % o display: Specifies a connection to an X server; returned from
5119 % XOpenDisplay.
5120 %
5121 % o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
5122 %
5123 */
5124 MagickPrivate XWindows *XInitializeWindows(Display *display,
5125  XResourceInfo *resource_info)
5126 {
5127  Window
5128  root_window;
5129 
5130  XWindows
5131  *windows;
5132 
5133  /*
5134  Allocate windows structure.
5135  */
5136  windows=(XWindows *) AcquireMagickMemory(sizeof(*windows));
5137  if (windows == (XWindows *) NULL)
5138  {
5139  ThrowXWindowFatalException(XServerFatalError,"MemoryAllocationFailed",
5140  "...");
5141  return((XWindows *) NULL);
5142  }
5143  (void) memset(windows,0,sizeof(*windows));
5144  windows->pixel_info=(XPixelInfo *) AcquireMagickMemory(
5145  sizeof(*windows->pixel_info));
5146  windows->icon_pixel=(XPixelInfo *) AcquireMagickMemory(
5147  sizeof(*windows->icon_pixel));
5148  windows->icon_resources=(XResourceInfo *) AcquireMagickMemory(
5149  sizeof(*windows->icon_resources));
5150  if ((windows->pixel_info == (XPixelInfo *) NULL) ||
5151  (windows->icon_pixel == (XPixelInfo *) NULL) ||
5152  (windows->icon_resources == (XResourceInfo *) NULL))
5153  {
5154  ThrowXWindowFatalException(XServerFatalError,"MemoryAllocationFailed",
5155  "...");
5156  return((XWindows *) NULL);
5157  }
5158  /*
5159  Initialize windows structure.
5160  */
5161  windows->display=display;
5162  windows->wm_protocols=XInternAtom(display,"WM_PROTOCOLS",MagickFalse);
5163  windows->wm_delete_window=XInternAtom(display,"WM_DELETE_WINDOW",MagickFalse);
5164  windows->wm_take_focus=XInternAtom(display,"WM_TAKE_FOCUS",MagickFalse);
5165  windows->im_protocols=XInternAtom(display,"IM_PROTOCOLS",MagickFalse);
5166  windows->im_remote_command=
5167  XInternAtom(display,"IM_REMOTE_COMMAND",MagickFalse);
5168  windows->im_update_widget=XInternAtom(display,"IM_UPDATE_WIDGET",MagickFalse);
5169  windows->im_update_colormap=
5170  XInternAtom(display,"IM_UPDATE_COLORMAP",MagickFalse);
5171  windows->im_former_image=XInternAtom(display,"IM_FORMER_IMAGE",MagickFalse);
5172  windows->im_next_image=XInternAtom(display,"IM_NEXT_IMAGE",MagickFalse);
5173  windows->im_retain_colors=XInternAtom(display,"IM_RETAIN_COLORS",MagickFalse);
5174  windows->im_exit=XInternAtom(display,"IM_EXIT",MagickFalse);
5175  windows->dnd_protocols=XInternAtom(display,"DndProtocol",MagickFalse);
5176 #if defined(MAGICKCORE_WINDOWS_SUPPORT)
5177  (void) XSynchronize(display,IsWindows95());
5178 #endif
5179  if (IsEventLogging())
5180  {
5181  (void) XSynchronize(display,MagickTrue);
5182  (void) LogMagickEvent(X11Event,GetMagickModule(),"Version: %s",
5183  GetMagickVersion((size_t *) NULL));
5184  (void) LogMagickEvent(X11Event,GetMagickModule(),"Protocols:");
5186  " Window Manager: 0x%lx",windows->wm_protocols);
5188  " delete window: 0x%lx",windows->wm_delete_window);
5189  (void) LogMagickEvent(X11Event,GetMagickModule()," take focus: 0x%lx",
5190  windows->wm_take_focus);
5191  (void) LogMagickEvent(X11Event,GetMagickModule()," ImageMagick: 0x%lx",
5192  windows->im_protocols);
5194  " remote command: 0x%lx",windows->im_remote_command);
5196  " update widget: 0x%lx",windows->im_update_widget);
5198  " update colormap: 0x%lx",windows->im_update_colormap);
5200  " former image: 0x%lx",windows->im_former_image);
5201  (void) LogMagickEvent(X11Event,GetMagickModule()," next image: 0x%lx",
5202  windows->im_next_image);
5204  " retain colors: 0x%lx",windows->im_retain_colors);
5205  (void) LogMagickEvent(X11Event,GetMagickModule()," exit: 0x%lx",
5206  windows->im_exit);
5207  (void) LogMagickEvent(X11Event,GetMagickModule()," Drag and Drop: 0x%lx",
5208  windows->dnd_protocols);
5209  }
5210  /*
5211  Allocate standard colormap.
5212  */
5213  windows->map_info=XAllocStandardColormap();
5214  windows->icon_map=XAllocStandardColormap();
5215  if ((windows->map_info == (XStandardColormap *) NULL) ||
5216  (windows->icon_map == (XStandardColormap *) NULL))
5217  ThrowXWindowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed",
5218  "...");
5219  windows->map_info->colormap=(Colormap) NULL;
5220  windows->icon_map->colormap=(Colormap) NULL;
5221  windows->pixel_info->pixels=(unsigned long *) NULL;
5222  windows->pixel_info->annotate_context=(GC) NULL;
5223  windows->pixel_info->highlight_context=(GC) NULL;
5224  windows->pixel_info->widget_context=(GC) NULL;
5225  windows->font_info=(XFontStruct *) NULL;
5226  windows->icon_pixel->annotate_context=(GC) NULL;
5227  windows->icon_pixel->pixels=(unsigned long *) NULL;
5228  /*
5229  Allocate visual.
5230  */
5231  *windows->icon_resources=(*resource_info);
5232  windows->icon_resources->visual_type=(char *) "default";
5233  windows->icon_resources->colormap=SharedColormap;
5234  windows->visual_info=
5235  XBestVisualInfo(display,windows->map_info,resource_info);
5236  windows->icon_visual=
5237  XBestVisualInfo(display,windows->icon_map,windows->icon_resources);
5238  if ((windows->visual_info == (XVisualInfo *) NULL) ||
5239  (windows->icon_visual == (XVisualInfo *) NULL))
5240  ThrowXWindowFatalException(XServerFatalError,"UnableToGetVisual",
5241  resource_info->visual_type);
5242  if (IsEventLogging())
5243  {
5244  (void) LogMagickEvent(X11Event,GetMagickModule(),"Visual:");
5245  (void) LogMagickEvent(X11Event,GetMagickModule()," visual id: 0x%lx",
5246  windows->visual_info->visualid);
5247  (void) LogMagickEvent(X11Event,GetMagickModule()," class: %s",
5248  XVisualClassName(windows->visual_info->klass));
5249  (void) LogMagickEvent(X11Event,GetMagickModule()," depth: %d planes",
5250  windows->visual_info->depth);
5252  " size of colormap: %d entries",windows->visual_info->colormap_size);
5254  " red, green, blue masks: 0x%lx 0x%lx 0x%lx",
5255  windows->visual_info->red_mask,windows->visual_info->green_mask,
5256  windows->visual_info->blue_mask);
5258  " significant bits in color: %d bits",
5259  windows->visual_info->bits_per_rgb);
5260  }
5261  /*
5262  Allocate class and manager hints.
5263  */
5264  windows->class_hints=XAllocClassHint();
5265  windows->manager_hints=XAllocWMHints();
5266  if ((windows->class_hints == (XClassHint *) NULL) ||
5267  (windows->manager_hints == (XWMHints *) NULL))
5268  ThrowXWindowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed",
5269  "...");
5270  /*
5271  Determine group leader if we have one.
5272  */
5273  root_window=XRootWindow(display,windows->visual_info->screen);
5274  windows->group_leader.id=(Window) NULL;
5275  if (resource_info->window_group != (char *) NULL)
5276  {
5277  if (isdigit((int) ((unsigned char) *resource_info->window_group)) != 0)
5278  windows->group_leader.id=XWindowByID(display,root_window,(Window)
5279  strtol((char *) resource_info->window_group,(char **) NULL,0));
5280  if (windows->group_leader.id == (Window) NULL)
5281  windows->group_leader.id=
5282  XWindowByName(display,root_window,resource_info->window_group);
5283  }
5284  return(windows);
5285 }
5286 
5287 /*
5288 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5289 % %
5290 % %
5291 % %
5292 % X M a k e C u r s o r %
5293 % %
5294 % %
5295 % %
5296 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5297 %
5298 % XMakeCursor() creates a crosshairs X11 cursor.
5299 %
5300 % The format of the XMakeCursor method is:
5301 %
5302 % Cursor XMakeCursor(Display *display,Window window,Colormap colormap,
5303 % char *background_color,char *foreground_color)
5304 %
5305 % A description of each parameter follows:
5306 %
5307 % o display: Specifies a connection to an X server; returned from
5308 % XOpenDisplay.
5309 %
5310 % o window: Specifies the ID of the window for which the cursor is
5311 % assigned.
5312 %
5313 % o colormap: Specifies the ID of the colormap from which the background
5314 % and foreground color will be retrieved.
5315 %
5316 % o background_color: Specifies the color to use for the cursor background.
5317 %
5318 % o foreground_color: Specifies the color to use for the cursor foreground.
5319 %
5320 */
5321 MagickPrivate Cursor XMakeCursor(Display *display,Window window,
5322  Colormap colormap,char *background_color,char *foreground_color)
5323 {
5324 #define scope_height 17
5325 #define scope_x_hot 8
5326 #define scope_y_hot 8
5327 #define scope_width 17
5328 
5329  static const unsigned char
5330  scope_bits[] =
5331  {
5332  0x80, 0x03, 0x00, 0x80, 0x02, 0x00, 0x80, 0x02, 0x00, 0x80, 0x02,
5333  0x00, 0x80, 0x02, 0x00, 0x80, 0x02, 0x00, 0x80, 0x02, 0x00, 0x7f,
5334  0xfc, 0x01, 0x01, 0x00, 0x01, 0x7f, 0xfc, 0x01, 0x80, 0x02, 0x00,
5335  0x80, 0x02, 0x00, 0x80, 0x02, 0x00, 0x80, 0x02, 0x00, 0x80, 0x02,
5336  0x00, 0x80, 0x02, 0x00, 0x80, 0x03, 0x00
5337  },
5338  scope_mask_bits[] =
5339  {
5340  0xc0, 0x07, 0x00, 0xc0, 0x07, 0x00, 0xc0, 0x06, 0x00, 0xc0, 0x06,
5341  0x00, 0xc0, 0x06, 0x00, 0xc0, 0x06, 0x00, 0xff, 0xfe, 0x01, 0x7f,
5342  0xfc, 0x01, 0x03, 0x80, 0x01, 0x7f, 0xfc, 0x01, 0xff, 0xfe, 0x01,
5343  0xc0, 0x06, 0x00, 0xc0, 0x06, 0x00, 0xc0, 0x06, 0x00, 0xc0, 0x06,
5344  0x00, 0xc0, 0x07, 0x00, 0xc0, 0x07, 0x00
5345  };
5346 
5347  Cursor
5348  cursor;
5349 
5350  Pixmap
5351  mask,
5352  source;
5353 
5354  XColor
5355  background,
5356  foreground;
5357 
5358  assert(display != (Display *) NULL);
5359  assert(window != (Window) NULL);
5360  assert(colormap != (Colormap) NULL);
5361  assert(background_color != (char *) NULL);
5362  assert(foreground_color != (char *) NULL);
5363  (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",background_color);
5364  source=XCreateBitmapFromData(display,window,(char *) scope_bits,scope_width,
5365  scope_height);
5366  mask=XCreateBitmapFromData(display,window,(char *) scope_mask_bits,
5367  scope_width,scope_height);
5368  if ((source == (Pixmap) NULL) || (mask == (Pixmap) NULL))
5369  {
5370  ThrowXWindowException(XServerError,"UnableToCreatePixmap","...");
5371  return((Cursor) NULL);
5372  }
5373  (void) XParseColor(display,colormap,background_color,&background);
5374  (void) XParseColor(display,colormap,foreground_color,&foreground);
5375  cursor=XCreatePixmapCursor(display,source,mask,&foreground,&background,
5376  scope_x_hot,scope_y_hot);
5377  (void) XFreePixmap(display,source);
5378  (void) XFreePixmap(display,mask);
5379  return(cursor);
5380 }
5381 
5382 /*
5383 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5384 % %
5385 % %
5386 % %
5387 % X M a k e I m a g e %
5388 % %
5389 % %
5390 % %
5391 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5392 %
5393 % XMakeImage() creates an X11 image. If the image size differs from the X11
5394 % image size, the image is first resized.
5395 %
5396 % The format of the XMakeImage method is:
5397 %
5398 % MagickBooleanType XMakeImage(Display *display,
5399 % const XResourceInfo *resource_info,XWindowInfo *window,Image *image,
5400 % unsigned int width,unsigned int height,ExceptionInfo *exception)
5401 %
5402 % A description of each parameter follows:
5403 %
5404 % o display: Specifies a connection to an X server; returned from
5405 % XOpenDisplay.
5406 %
5407 % o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
5408 %
5409 % o window: Specifies a pointer to a XWindowInfo structure.
5410 %
5411 % o image: the image.
5412 %
5413 % o width: Specifies the width in pixels of the rectangular area to
5414 % display.
5415 %
5416 % o height: Specifies the height in pixels of the rectangular area to
5417 % display.
5418 %
5419 % o exception: return any errors or warnings in this structure.
5420 %
5421 */
5422 MagickPrivate MagickBooleanType XMakeImage(Display *display,
5423  const XResourceInfo *resource_info,XWindowInfo *window,Image *image,
5424  unsigned int width,unsigned int height,ExceptionInfo *exception)
5425 {
5426 #define CheckOverflowException(length,width,height) \
5427  (((height) != 0) && ((length)/((size_t) height) != ((size_t) width)))
5428 
5429  int
5430  depth,
5431  format;
5432 
5433  size_t
5434  length;
5435 
5436  XImage
5437  *matte_image,
5438  *ximage;
5439 
5440  (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
5441  assert(display != (Display *) NULL);
5442  assert(resource_info != (XResourceInfo *) NULL);
5443  assert(window != (XWindowInfo *) NULL);
5444  assert(width != 0);
5445  assert(height != 0);
5446  if ((window->width == 0) || (window->height == 0))
5447  return(MagickFalse);
5448  /*
5449  Apply user transforms to the image.
5450  */
5451  (void) XCheckDefineCursor(display,window->id,window->busy_cursor);
5452  (void) XFlush(display);
5453  depth=(int) window->depth;
5454  if (window->destroy)
5455  window->image=DestroyImage(window->image);
5456  window->image=image;
5457  window->destroy=MagickFalse;
5458  if (window->image != (Image *) NULL)
5459  {
5460  if (window->crop_geometry != (char *) NULL)
5461  {
5462  Image
5463  *crop_image;
5464 
5466  crop_info;
5467 
5468  /*
5469  Crop image.
5470  */
5471  window->image->page.x=0;
5472  window->image->page.y=0;
5473  (void) ParsePageGeometry(window->image,window->crop_geometry,
5474  &crop_info,exception);
5475  crop_image=CropImage(window->image,&crop_info,exception);
5476  if (crop_image != (Image *) NULL)
5477  {
5478  if (window->image != image)
5479  window->image=DestroyImage(window->image);
5480  window->image=crop_image;
5481  window->destroy=MagickTrue;
5482  }
5483  }
5484  if ((width != (unsigned int) window->image->columns) ||
5485  (height != (unsigned int) window->image->rows))
5486  {
5487  Image
5488  *resize_image;
5489 
5490  /*
5491  Resize image.
5492  */
5493  resize_image=NewImageList();
5494  if ((window->pixel_info->colors == 0) &&
5495  (window->image->rows > (unsigned long) XDisplayHeight(display,window->screen)) &&
5496  (window->image->columns > (unsigned long) XDisplayWidth(display,window->screen)))
5497  resize_image=ResizeImage(window->image,width,height,
5498  image->filter,exception);
5499  else
5500  {
5501  if (window->image->storage_class == PseudoClass)
5502  resize_image=SampleImage(window->image,width,height,
5503  exception);
5504  else
5505  resize_image=ThumbnailImage(window->image,width,height,
5506  exception);
5507  }
5508  if (resize_image != (Image *) NULL)
5509  {
5510  if (window->image != image)
5511  window->image=DestroyImage(window->image);
5512  window->image=resize_image;
5513  window->destroy=MagickTrue;
5514  }
5515  }
5516  width=(unsigned int) window->image->columns;
5517  assert((size_t) width == window->image->columns);
5518  height=(unsigned int) window->image->rows;
5519  assert((size_t) height == window->image->rows);
5520  }
5521  /*
5522  Create X image.
5523  */
5524  ximage=(XImage *) NULL;
5525  format=(depth == 1) ? XYBitmap : ZPixmap;
5526 #if defined(MAGICKCORE_HAVE_SHARED_MEMORY)
5527  if (window->shared_memory != MagickFalse)
5528  {
5529  XShmSegmentInfo
5530  *segment_info;
5531 
5532  segment_info=(XShmSegmentInfo *) window->segment_info;
5533  segment_info[1].shmid=(-1);
5534  segment_info[1].shmaddr=(char *) NULL;
5535  ximage=XShmCreateImage(display,window->visual,(unsigned int) depth,format,
5536  (char *) NULL,&segment_info[1],width,height);
5537  if (ximage == (XImage *) NULL)
5538  window->shared_memory=MagickFalse;
5539  else
5540  {
5541  length=(size_t) ximage->bytes_per_line*ximage->height;
5542  if (CheckOverflowException(length,ximage->bytes_per_line,ximage->height))
5543  window->shared_memory=MagickFalse;
5544  }
5545  if (window->shared_memory != MagickFalse)
5546  segment_info[1].shmid=shmget(IPC_PRIVATE,length,IPC_CREAT | 0777);
5547  if (window->shared_memory != MagickFalse)
5548  segment_info[1].shmaddr=(char *) shmat(segment_info[1].shmid,0,0);
5549  if (segment_info[1].shmid < 0)
5550  window->shared_memory=MagickFalse;
5551  if (window->shared_memory != MagickFalse)
5552  (void) shmctl(segment_info[1].shmid,IPC_RMID,0);
5553  else
5554  {
5555  if (ximage != (XImage *) NULL)
5556  XDestroyImage(ximage);
5557  ximage=(XImage *) NULL;
5558  if (segment_info[1].shmaddr)
5559  {
5560  (void) shmdt(segment_info[1].shmaddr);
5561  segment_info[1].shmaddr=(char *) NULL;
5562  }
5563  if (segment_info[1].shmid >= 0)
5564  {
5565  (void) shmctl(segment_info[1].shmid,IPC_RMID,0);
5566  segment_info[1].shmid=(-1);
5567  }
5568  }
5569  }
5570 #endif
5571  /*
5572  Allocate X image pixel data.
5573  */
5574 #if defined(MAGICKCORE_HAVE_SHARED_MEMORY)
5575  if (window->shared_memory)
5576  {
5577  Status
5578  status;
5579 
5580  XShmSegmentInfo
5581  *segment_info;
5582 
5583  (void) XSync(display,MagickFalse);
5584  xerror_alert=MagickFalse;
5585  segment_info=(XShmSegmentInfo *) window->segment_info;
5586  ximage->data=segment_info[1].shmaddr;
5587  segment_info[1].readOnly=MagickFalse;
5588  status=XShmAttach(display,&segment_info[1]);
5589  if (status != False)
5590  (void) XSync(display,MagickFalse);
5591  if ((status == False) || (xerror_alert != MagickFalse))
5592  {
5593  window->shared_memory=MagickFalse;
5594  if (status != False)
5595  XShmDetach(display,&segment_info[1]);
5596  ximage->data=NULL;
5597  XDestroyImage(ximage);
5598  ximage=(XImage *) NULL;
5599  if (segment_info[1].shmid >= 0)
5600  {
5601  if (segment_info[1].shmaddr != NULL)
5602  (void) shmdt(segment_info[1].shmaddr);
5603  (void) shmctl(segment_info[1].shmid,IPC_RMID,0);
5604  segment_info[1].shmid=(-1);
5605  segment_info[1].shmaddr=(char *) NULL;
5606  }
5607  }
5608  }
5609 #endif
5610  if (window->shared_memory == MagickFalse)
5611  ximage=XCreateImage(display,window->visual,(unsigned int) depth,format,0,
5612  (char *) NULL,width,height,XBitmapPad(display),0);
5613  if (ximage == (XImage *) NULL)
5614  {
5615  /*
5616  Unable to create X image.
5617  */
5618  (void) XCheckDefineCursor(display,window->id,window->cursor);
5619  return(MagickFalse);
5620  }
5621  length=(size_t) ximage->bytes_per_line*ximage->height;
5622  if (IsEventLogging())
5623  {
5624  (void) LogMagickEvent(X11Event,GetMagickModule(),"XImage:");
5625  (void) LogMagickEvent(X11Event,GetMagickModule()," width, height: %dx%d",
5626  ximage->width,ximage->height);
5627  (void) LogMagickEvent(X11Event,GetMagickModule()," format: %d",
5628  ximage->format);
5629  (void) LogMagickEvent(X11Event,GetMagickModule()," byte order: %d",
5630  ximage->byte_order);
5632  " bitmap unit, bit order, pad: %d %d %d",ximage->bitmap_unit,
5633  ximage->bitmap_bit_order,ximage->bitmap_pad);
5634  (void) LogMagickEvent(X11Event,GetMagickModule()," depth: %d",
5635  ximage->depth);
5636  (void) LogMagickEvent(X11Event,GetMagickModule()," bytes per line: %d",
5637  ximage->bytes_per_line);
5638  (void) LogMagickEvent(X11Event,GetMagickModule()," bits per pixel: %d",
5639  ximage->bits_per_pixel);
5641  " red, green, blue masks: 0x%lx 0x%lx 0x%lx",ximage->red_mask,
5642  ximage->green_mask,ximage->blue_mask);
5643  }
5644  if (window->shared_memory == MagickFalse)
5645  {
5646  if (ximage->format == XYBitmap)
5647  {
5648  ximage->data=(char *) AcquireQuantumMemory((size_t)
5649  ximage->bytes_per_line,(size_t) ximage->depth*ximage->height);
5650  if (ximage->data != (char *) NULL)
5651  (void) memset(ximage->data,0,(size_t)
5652  ximage->bytes_per_line*ximage->depth*ximage->height);
5653  }
5654  else
5655  {
5656  ximage->data=(char *) AcquireQuantumMemory((size_t)
5657  ximage->bytes_per_line,(size_t) ximage->height);
5658  if (ximage->data != (char *) NULL)
5659  (void) memset(ximage->data,0,(size_t)
5660  ximage->bytes_per_line*ximage->height);
5661  }
5662  }
5663  if (ximage->data == (char *) NULL)
5664  {
5665  /*
5666  Unable to allocate pixel data.
5667  */
5668  XDestroyImage(ximage);
5669  ximage=(XImage *) NULL;
5670  (void) XCheckDefineCursor(display,window->id,window->cursor);
5671  return(MagickFalse);
5672  }
5673  if (window->ximage != (XImage *) NULL)
5674  {
5675  /*
5676  Destroy previous X image.
5677  */
5678  length=(size_t) window->ximage->bytes_per_line*window->ximage->height;
5679 #if defined(MAGICKCORE_HAVE_SHARED_MEMORY)
5680  if (window->segment_info != (XShmSegmentInfo *) NULL)
5681  {
5682  XShmSegmentInfo
5683  *segment_info;
5684 
5685  segment_info=(XShmSegmentInfo *) window->segment_info;
5686  if (segment_info[0].shmid >= 0)
5687  {
5688  (void) XSync(display,MagickFalse);
5689  (void) XShmDetach(display,&segment_info[0]);
5690  (void) XSync(display,MagickFalse);
5691  if (segment_info[0].shmaddr != (char *) NULL)
5692  (void) shmdt(segment_info[0].shmaddr);
5693  (void) shmctl(segment_info[0].shmid,IPC_RMID,0);
5694  segment_info[0].shmid=(-1);
5695  segment_info[0].shmaddr=(char *) NULL;
5696  window->ximage->data=(char *) NULL;
5697  }
5698  }
5699 #endif
5700  if (window->ximage->data != (char *) NULL)
5701  free(window->ximage->data);
5702  window->ximage->data=(char *) NULL;
5703  XDestroyImage(window->ximage);
5704  window->ximage=(XImage *) NULL;
5705  }
5706 #if defined(MAGICKCORE_HAVE_SHARED_MEMORY)
5707  if (window->segment_info != (XShmSegmentInfo *) NULL)
5708  {
5709  XShmSegmentInfo
5710  *segment_info;
5711 
5712  segment_info=(XShmSegmentInfo *) window->segment_info;
5713  segment_info[0]=segment_info[1];
5714  }
5715 #endif
5716  window->ximage=ximage;
5717  matte_image=(XImage *) NULL;
5718  if ((window->shape != MagickFalse) && (window->image != (Image *) NULL))
5719  if ((window->image->alpha_trait != UndefinedPixelTrait) &&
5720  ((int) width <= XDisplayWidth(display,window->screen)) &&
5721  ((int) height <= XDisplayHeight(display,window->screen)))
5722  {
5723  /*
5724  Create matte image.
5725  */
5726  matte_image=XCreateImage(display,window->visual,1,XYBitmap,0,
5727  (char *) NULL,width,height,XBitmapPad(display),0);
5728  if (IsEventLogging())
5729  {
5730  (void) LogMagickEvent(X11Event,GetMagickModule(),"Matte Image:");
5732  " width, height: %dx%d",matte_image->width,matte_image->height);
5733  }
5734  if (matte_image != (XImage *) NULL)
5735  {
5736  /*
5737  Allocate matte image pixel data.
5738  */
5739  matte_image->data=(char *) malloc((size_t)
5740  matte_image->bytes_per_line*matte_image->depth*
5741  matte_image->height);
5742  if (matte_image->data == (char *) NULL)
5743  {
5744  XDestroyImage(matte_image);
5745  matte_image=(XImage *) NULL;
5746  }
5747  }
5748  }
5749  if (window->matte_image != (XImage *) NULL)
5750  {
5751  /*
5752  Free matte image.
5753  */
5754  if (window->matte_image->data != (char *) NULL)
5755  free(window->matte_image->data);
5756  window->matte_image->data=(char *) NULL;
5757  XDestroyImage(window->matte_image);
5758  window->matte_image=(XImage *) NULL;
5759  }
5760  window->matte_image=matte_image;
5761  if (window->matte_pixmap != (Pixmap) NULL)
5762  {
5763  (void) XFreePixmap(display,window->matte_pixmap);
5764  window->matte_pixmap=(Pixmap) NULL;
5765 #if defined(MAGICKCORE_HAVE_SHAPE)
5766  if (window->shape != MagickFalse)
5767  XShapeCombineMask(display,window->id,ShapeBounding,0,0,None,ShapeSet);
5768 #endif
5769  }
5770  window->stasis=MagickFalse;
5771  /*
5772  Convert pixels to X image data.
5773  */
5774  if (window->image != (Image *) NULL)
5775  {
5776  if ((ximage->byte_order == LSBFirst) || ((ximage->format == XYBitmap) &&
5777  (ximage->bitmap_bit_order == LSBFirst)))
5778  XMakeImageLSBFirst(resource_info,window,window->image,ximage,
5779  matte_image,exception);
5780  else
5781  XMakeImageMSBFirst(resource_info,window,window->image,ximage,
5782  matte_image,exception);
5783  }
5784  if (window->matte_image != (XImage *) NULL)
5785  {
5786  /*
5787  Create matte pixmap.
5788  */
5789  window->matte_pixmap=XCreatePixmap(display,window->id,width,height,1);
5790  if (window->matte_pixmap != (Pixmap) NULL)
5791  {
5792  GC
5793  graphics_context;
5794 
5795  XGCValues
5796  context_values;
5797 
5798  /*
5799  Copy matte image to matte pixmap.
5800  */
5801  context_values.background=0;
5802  context_values.foreground=1;
5803  graphics_context=XCreateGC(display,window->matte_pixmap,
5804  (size_t) (GCBackground | GCForeground),&context_values);
5805  (void) XPutImage(display,window->matte_pixmap,graphics_context,
5806  window->matte_image,0,0,0,0,width,height);
5807  (void) XFreeGC(display,graphics_context);
5808 #if defined(MAGICKCORE_HAVE_SHAPE)
5809  if (window->shape != MagickFalse)
5810  XShapeCombineMask(display,window->id,ShapeBounding,0,0,
5811  window->matte_pixmap,ShapeSet);
5812 #endif
5813  }
5814  }
5815  (void) XMakePixmap(display,resource_info,window);
5816  /*
5817  Restore cursor.
5818  */
5819  (void) XCheckDefineCursor(display,window->id,window->cursor);
5820  return(MagickTrue);
5821 }
5822 
5823 /*
5824 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5825 % %
5826 % %
5827 % %
5828 + X M a k e I m a g e L S B F i r s t %
5829 % %
5830 % %
5831 % %
5832 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5833 %
5834 % XMakeImageLSBFirst() initializes the pixel data of an X11 Image. The X image
5835 % pixels are copied in least-significant bit and byte first order. The
5836 % server's scanline pad is respected. Rather than using one or two general
5837 % cases, many special cases are found here to help speed up the image
5838 % conversion.
5839 %
5840 % The format of the XMakeImageLSBFirst method is:
5841 %
5842 % void XMakeImageLSBFirst(Display *display,XWindows *windows,
5843 % ExceptionInfo *exception)
5844 %
5845 % A description of each parameter follows:
5846 %
5847 % o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
5848 %
5849 % o window: Specifies a pointer to a XWindowInfo structure.
5850 %
5851 % o image: the image.
5852 %
5853 % o ximage: Specifies a pointer to a XImage structure; returned from
5854 % XCreateImage.
5855 %
5856 % o matte_image: Specifies a pointer to a XImage structure; returned from
5857 % XCreateImage.
5858 %
5859 % o exception: return any errors or warnings in this structure.
5860 %
5861 */
5862 static void XMakeImageLSBFirst(const XResourceInfo *resource_info,
5863  const XWindowInfo *window,Image *image,XImage *ximage,XImage *matte_image,
5864  ExceptionInfo *exception)
5865 {
5866  CacheView
5867  *canvas_view;
5868 
5869  Image
5870  *canvas;
5871 
5872  int
5873  y;
5874 
5875  register const Quantum
5876  *p;
5877 
5878  register int
5879  x;
5880 
5881  register unsigned char
5882  *q;
5883 
5884  unsigned char
5885  bit,
5886  byte;
5887 
5888  unsigned int
5889  scanline_pad;
5890 
5891  unsigned long
5892  pixel,
5893  *pixels;
5894 
5895  XStandardColormap
5896  *map_info;
5897 
5898  assert(resource_info != (XResourceInfo *) NULL);
5899  assert(window != (XWindowInfo *) NULL);
5900  assert(image != (Image *) NULL);
5901  if (image->debug != MagickFalse)
5902  (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
5903  canvas=image;
5904  if ((window->immutable == MagickFalse) &&
5905  (image->storage_class == DirectClass) && (image->alpha_trait != UndefinedPixelTrait))
5906  {
5907  char
5908  size[MagickPathExtent];
5909 
5910  Image
5911  *pattern;
5912 
5913  ImageInfo
5914  *image_info;
5915 
5916  image_info=AcquireImageInfo();
5917  (void) CopyMagickString(image_info->filename,
5918  resource_info->image_info->texture != (char *) NULL ?
5919  resource_info->image_info->texture : "pattern:checkerboard",
5921  (void) FormatLocaleString(size,MagickPathExtent,"%.20gx%.20g",(double)
5922  image->columns,(double) image->rows);
5923  image_info->size=ConstantString(size);
5924  pattern=ReadImage(image_info,exception);
5925  image_info=DestroyImageInfo(image_info);
5926  if (pattern != (Image *) NULL)
5927  {
5928  canvas=CloneImage(image,0,0,MagickTrue,exception);
5929  if (canvas != (Image *) NULL)
5930  (void) CompositeImage(canvas,pattern,DstOverCompositeOp,MagickTrue,
5931  0,0,exception);
5932  pattern=DestroyImage(pattern);
5933  }
5934  }
5935  scanline_pad=(unsigned int) (ximage->bytes_per_line-((ximage->width*
5936  ximage->bits_per_pixel) >> 3));
5937  map_info=window->map_info;
5938  pixels=window->pixel_info->pixels;
5939  q=(unsigned char *) ximage->data;
5940  x=0;
5941  canvas_view=AcquireVirtualCacheView(canvas,exception);
5942  if (ximage->format == XYBitmap)
5943  {
5944  register unsigned short
5945  polarity;
5946 
5947  unsigned char
5948  background,
5949  foreground;
5950 
5951  /*
5952  Convert canvas to big-endian bitmap.
5953  */
5954  background=(unsigned char)
5955  (XPixelIntensity(&window->pixel_info->foreground_color) <
5956  XPixelIntensity(&window->pixel_info->background_color) ? 0x80 : 0x00);
5957  foreground=(unsigned char)
5958  (XPixelIntensity(&window->pixel_info->background_color) <
5959  XPixelIntensity(&window->pixel_info->foreground_color) ? 0x80 : 0x00);
5960  polarity=(unsigned short) ((GetPixelInfoIntensity(image,
5961  &canvas->colormap[0])) < (QuantumRange/2.0) ? 1 : 0);
5962  if (canvas->colors == 2)
5963  polarity=GetPixelInfoIntensity(image,&canvas->colormap[0]) <
5964  GetPixelInfoIntensity(image,&canvas->colormap[1]);
5965  for (y=0; y < (int) canvas->rows; y++)
5966  {
5967  p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,canvas->columns,1,
5968  exception);
5969  if (p == (const Quantum *) NULL)
5970  break;
5971  bit=0;
5972  byte=0;
5973  for (x=0; x < (int) canvas->columns; x++)
5974  {
5975  byte>>=1;
5976  if (GetPixelIndex(canvas,p) == (Quantum) polarity)
5977  byte|=foreground;
5978  else
5979  byte|=background;
5980  bit++;
5981  if (bit == 8)
5982  {
5983  *q++=byte;
5984  bit=0;
5985  byte=0;
5986  }
5987  p+=GetPixelChannels(canvas);
5988  }
5989  if (bit != 0)
5990  *q=byte >> (8-bit);
5991  q+=scanline_pad;
5992  }
5993  }
5994  else
5995  if (window->pixel_info->colors != 0)
5996  switch (ximage->bits_per_pixel)
5997  {
5998  case 2:
5999  {
6000  register unsigned int
6001  nibble;
6002 
6003  /*
6004  Convert to 2 bit color-mapped X canvas.
6005  */
6006  for (y=0; y < (int) canvas->rows; y++)
6007  {
6008  p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
6009  canvas->columns,1,exception);
6010  if (p == (const Quantum *) NULL)
6011  break;
6012  nibble=0;
6013  for (x=0; x < (int) canvas->columns; x++)
6014  {
6015  pixel=pixels[(ssize_t) GetPixelIndex(canvas,p)] & 0x0f;
6016  switch (nibble)
6017  {
6018  case 0:
6019  {
6020  *q=(unsigned char) pixel;
6021  nibble++;
6022  break;
6023  }
6024  case 1:
6025  {
6026  *q|=(unsigned char) (pixel << 2);
6027  nibble++;
6028  break;
6029  }
6030  case 2:
6031  {
6032  *q|=(unsigned char) (pixel << 4);
6033  nibble++;
6034  break;
6035  }
6036  case 3:
6037  {
6038  *q|=(unsigned char) (pixel << 6);
6039  q++;
6040  nibble=0;
6041  break;
6042  }
6043  }
6044  p+=GetPixelChannels(canvas);
6045  }
6046  q+=scanline_pad;
6047  }
6048  break;
6049  }
6050  case 4:
6051  {
6052  register unsigned int
6053  nibble;
6054 
6055  /*
6056  Convert to 4 bit color-mapped X canvas.
6057  */
6058  for (y=0; y < (int) canvas->rows; y++)
6059  {
6060  p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
6061  canvas->columns,1,exception);
6062  if (p == (const Quantum *) NULL)
6063  break;
6064  nibble=0;
6065  for (x=0; x < (int) canvas->columns; x++)
6066  {
6067  pixel=pixels[(ssize_t) GetPixelIndex(canvas,p)] & 0xf;
6068  switch (nibble)
6069  {
6070  case 0:
6071  {
6072  *q=(unsigned char) pixel;
6073  nibble++;
6074  break;
6075  }
6076  case 1:
6077  {
6078  *q|=(unsigned char) (pixel << 4);
6079  q++;
6080  nibble=0;
6081  break;
6082  }
6083  }
6084  p+=GetPixelChannels(canvas);
6085  }
6086  q+=scanline_pad;
6087  }
6088  break;
6089  }
6090  case 6:
6091  case 8:
6092  {
6093  /*
6094  Convert to 8 bit color-mapped X canvas.
6095  */
6096  if (resource_info->color_recovery &&
6097  resource_info->quantize_info->dither_method != NoDitherMethod)
6098  {
6099  XDitherImage(canvas,ximage,exception);
6100  break;
6101  }
6102  for (y=0; y < (int) canvas->rows; y++)
6103  {
6104  p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
6105  canvas->columns,1,exception);
6106  if (p == (const Quantum *) NULL)
6107  break;
6108  for (x=0; x < (int) canvas->columns; x++)
6109  {
6110  pixel=pixels[(ssize_t) GetPixelIndex(canvas,p)];
6111  *q++=(unsigned char) pixel;
6112  p+=GetPixelChannels(canvas);
6113  }
6114  q+=scanline_pad;
6115  }
6116  break;
6117  }
6118  default:
6119  {
6120  register int
6121  k;
6122 
6123  register unsigned int
6124  bytes_per_pixel;
6125 
6126  /*
6127  Convert to multi-byte color-mapped X canvas.
6128  */
6129  bytes_per_pixel=(unsigned int) (ximage->bits_per_pixel >> 3);
6130  for (y=0; y < (int) canvas->rows; y++)
6131  {
6132  p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
6133  canvas->columns,1,exception);
6134  if (p == (const Quantum *) NULL)
6135  break;
6136  for (x=0; x < (int) canvas->columns; x++)
6137  {
6138  pixel=pixels[(ssize_t) GetPixelIndex(canvas,p)];
6139  for (k=0; k < (int) bytes_per_pixel; k++)
6140  {
6141  *q++=(unsigned char) (pixel & 0xff);
6142  pixel>>=8;
6143  }
6144  p+=GetPixelChannels(canvas);
6145  }
6146  q+=scanline_pad;
6147  }
6148  break;
6149  }
6150  }
6151  else
6152  switch (ximage->bits_per_pixel)
6153  {
6154  case 2:
6155  {
6156  register unsigned int
6157  nibble;
6158 
6159  /*
6160  Convert to contiguous 2 bit continuous-tone X canvas.
6161  */
6162  for (y=0; y < (int) canvas->rows; y++)
6163  {
6164  nibble=0;
6165  p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
6166  canvas->columns,1,exception);
6167  if (p == (const Quantum *) NULL)
6168  break;
6169  for (x=0; x < (int) canvas->columns; x++)
6170  {
6171  pixel=XGammaPixel(canvas,map_info,p);
6172  pixel&=0xf;
6173  switch (nibble)
6174  {
6175  case 0:
6176  {
6177  *q=(unsigned char) pixel;
6178  nibble++;
6179  break;
6180  }
6181  case 1:
6182  {
6183  *q|=(unsigned char) (pixel << 2);
6184  nibble++;
6185  break;
6186  }
6187  case 2:
6188  {
6189  *q|=(unsigned char) (pixel << 4);
6190  nibble++;
6191  break;
6192  }
6193  case 3:
6194  {
6195  *q|=(unsigned char) (pixel << 6);
6196  q++;
6197  nibble=0;
6198  break;
6199  }
6200  }
6201  p+=GetPixelChannels(canvas);
6202  }
6203  q+=scanline_pad;
6204  }
6205  break;
6206  }
6207  case 4:
6208  {
6209  register unsigned int
6210  nibble;
6211 
6212  /*
6213  Convert to contiguous 4 bit continuous-tone X canvas.
6214  */
6215  for (y=0; y < (int) canvas->rows; y++)
6216  {
6217  p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
6218  canvas->columns,1,exception);
6219  if (p == (const Quantum *) NULL)
6220  break;
6221  nibble=0;
6222  for (x=0; x < (int) canvas->columns; x++)
6223  {
6224  pixel=XGammaPixel(canvas,map_info,p);
6225  pixel&=0xf;
6226  switch (nibble)
6227  {
6228  case 0:
6229  {
6230  *q=(unsigned char) pixel;
6231  nibble++;
6232  break;
6233  }
6234  case 1:
6235  {
6236  *q|=(unsigned char) (pixel << 4);
6237  q++;
6238  nibble=0;
6239  break;
6240  }
6241  }
6242  p+=GetPixelChannels(canvas);
6243  }
6244  q+=scanline_pad;
6245  }
6246  break;
6247  }
6248  case 6:
6249  case 8:
6250  {
6251  /*
6252  Convert to contiguous 8 bit continuous-tone X canvas.
6253  */
6254  if (resource_info->color_recovery &&
6255  resource_info->quantize_info->dither_method != NoDitherMethod)
6256  {
6257  XDitherImage(canvas,ximage,exception);
6258  break;
6259  }
6260  for (y=0; y < (int) canvas->rows; y++)
6261  {
6262  p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
6263  canvas->columns,1,exception);
6264  if (p == (const Quantum *) NULL)
6265  break;
6266  for (x=0; x < (int) canvas->columns; x++)
6267  {
6268  pixel=XGammaPixel(canvas,map_info,p);
6269  *q++=(unsigned char) pixel;
6270  p+=GetPixelChannels(canvas);
6271  }
6272  q+=scanline_pad;
6273  }
6274  break;
6275  }
6276  default:
6277  {
6278  if ((ximage->bits_per_pixel == 32) && (map_info->red_max == 255) &&
6279  (map_info->green_max == 255) && (map_info->blue_max == 255) &&
6280  (map_info->red_mult == 65536L) && (map_info->green_mult == 256) &&
6281  (map_info->blue_mult == 1))
6282  {
6283  /*
6284  Convert to 32 bit continuous-tone X canvas.
6285  */
6286  for (y=0; y < (int) canvas->rows; y++)
6287  {
6288  p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
6289  canvas->columns,1,exception);
6290  if (p == (const Quantum *) NULL)
6291  break;
6292  if ((red_gamma != 1.0) || (green_gamma != 1.0) ||
6293  (blue_gamma != 1.0))
6294  {
6295  /*
6296  Gamma correct canvas.
6297  */
6298  for (x=(int) canvas->columns-1; x >= 0; x--)
6299  {
6300  *q++=ScaleQuantumToChar(XBlueGamma(
6301  GetPixelBlue(canvas,p)));
6302  *q++=ScaleQuantumToChar(XGreenGamma(
6303  GetPixelGreen(canvas,p)));
6304  *q++=ScaleQuantumToChar(XRedGamma(
6305  GetPixelRed(canvas,p)));
6306  *q++=0;
6307  p+=GetPixelChannels(canvas);
6308  }
6309  continue;
6310  }
6311  for (x=(int) canvas->columns-1; x >= 0; x--)
6312  {
6313  *q++=ScaleQuantumToChar((Quantum) GetPixelBlue(canvas,p));
6314  *q++=ScaleQuantumToChar((Quantum) GetPixelGreen(canvas,p));
6315  *q++=ScaleQuantumToChar((Quantum) GetPixelRed(canvas,p));
6316  *q++=0;
6317  p+=GetPixelChannels(canvas);
6318  }
6319  }
6320  }
6321  else
6322  if ((ximage->bits_per_pixel == 32) && (map_info->red_max == 255) &&
6323  (map_info->green_max == 255) && (map_info->blue_max == 255) &&
6324  (map_info->red_mult == 1) && (map_info->green_mult == 256) &&
6325  (map_info->blue_mult == 65536L))
6326  {
6327  /*
6328  Convert to 32 bit continuous-tone X canvas.
6329  */
6330  for (y=0; y < (int) canvas->rows; y++)
6331  {
6332  p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
6333  canvas->columns,1,exception);
6334  if (p == (const Quantum *) NULL)
6335  break;
6336  if ((red_gamma != 1.0) || (green_gamma != 1.0) ||
6337  (blue_gamma != 1.0))
6338  {
6339  /*
6340  Gamma correct canvas.
6341  */
6342  for (x=(int) canvas->columns-1; x >= 0; x--)
6343  {
6344  *q++=ScaleQuantumToChar(XRedGamma(
6345  GetPixelRed(canvas,p)));
6346  *q++=ScaleQuantumToChar(XGreenGamma(
6347  GetPixelGreen(canvas,p)));
6348  *q++=ScaleQuantumToChar(XBlueGamma(
6349  GetPixelBlue(canvas,p)));
6350  *q++=0;
6351  p+=GetPixelChannels(canvas);
6352  }
6353  continue;
6354  }
6355  for (x=(int) canvas->columns-1; x >= 0; x--)
6356  {
6357  *q++=ScaleQuantumToChar((Quantum) GetPixelRed(canvas,p));
6358  *q++=ScaleQuantumToChar((Quantum) GetPixelGreen(canvas,p));
6359  *q++=ScaleQuantumToChar((Quantum) GetPixelBlue(canvas,p));
6360  *q++=0;
6361  p+=GetPixelChannels(canvas);
6362  }
6363  }
6364  }
6365  else
6366  {
6367  register int
6368  k;
6369 
6370  register unsigned int
6371  bytes_per_pixel;
6372 
6373  /*
6374  Convert to multi-byte continuous-tone X canvas.
6375  */
6376  bytes_per_pixel=(unsigned int) (ximage->bits_per_pixel >> 3);
6377  for (y=0; y < (int) canvas->rows; y++)
6378  {
6379  p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
6380  canvas->columns,1,exception);
6381  if (p == (const Quantum *) NULL)
6382  break;
6383  for (x=0; x < (int) canvas->columns; x++)
6384  {
6385  pixel=XGammaPixel(canvas,map_info,p);
6386  for (k=0; k < (int) bytes_per_pixel; k++)
6387  {
6388  *q++=(unsigned char) (pixel & 0xff);
6389  pixel>>=8;
6390  }
6391  p+=GetPixelChannels(canvas);
6392  }
6393  q+=scanline_pad;
6394  }
6395  }
6396  break;
6397  }
6398  }
6399  if (matte_image != (XImage *) NULL)
6400  {
6401  /*
6402  Initialize matte canvas.
6403  */
6404  scanline_pad=(unsigned int) (matte_image->bytes_per_line-
6405  ((matte_image->width*matte_image->bits_per_pixel) >> 3));
6406  q=(unsigned char *) matte_image->data;
6407  for (y=0; y < (int) canvas->rows; y++)
6408  {
6409  p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,canvas->columns,1,
6410  exception);
6411  if (p == (const Quantum *) NULL)
6412  break;
6413  bit=0;
6414  byte=0;
6415  for (x=(int) canvas->columns-1; x >= 0; x--)
6416  {
6417  byte>>=1;
6418  if (GetPixelAlpha(canvas,p) > (QuantumRange/2))
6419  byte|=0x80;
6420  bit++;
6421  if (bit == 8)
6422  {
6423  *q++=byte;
6424  bit=0;
6425  byte=0;
6426  }
6427  p+=GetPixelChannels(canvas);
6428  }
6429  if (bit != 0)
6430  *q=byte >> (8-bit);
6431  q+=scanline_pad;
6432  }
6433  }
6434  canvas_view=DestroyCacheView(canvas_view);
6435  if (canvas != image)
6436  canvas=DestroyImage(canvas);
6437 }
6438 
6439 /*
6440 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
6441 % %
6442 % %
6443 % %
6444 + X M a k e I m a g e M S B F i r s t %
6445 % %
6446 % %
6447 % %
6448 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
6449 %
6450 % XMakeImageMSBFirst() initializes the pixel data of an X11 Image. The X
6451 % image pixels are copied in most-significant bit and byte first order. The
6452 % server's scanline pad is also respected. Rather than using one or two
6453 % general cases, many special cases are found here to help speed up the image
6454 % conversion.
6455 %
6456 % The format of the XMakeImageMSBFirst method is:
6457 %
6458 % XMakeImageMSBFirst(resource_info,window,image,ximage,matte_image,
6459 % ExceptionInfo *exception)
6460 %
6461 % A description of each parameter follows:
6462 %
6463 % o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
6464 %
6465 % o window: Specifies a pointer to a XWindowInfo structure.
6466 %
6467 % o image: the image.
6468 %
6469 % o ximage: Specifies a pointer to a XImage structure; returned from
6470 % XCreateImage.
6471 %
6472 % o matte_image: Specifies a pointer to a XImage structure; returned from
6473 % XCreateImage.
6474 %
6475 % o exception: return any errors or warnings in this structure.
6476 %
6477 */
6478 static void XMakeImageMSBFirst(const XResourceInfo *resource_info,
6479  const XWindowInfo *window,Image *image,XImage *ximage,XImage *matte_image,
6480  ExceptionInfo *exception)
6481 {
6482  CacheView
6483  *canvas_view;
6484 
6485  Image
6486  *canvas;
6487 
6488  int
6489  y;
6490 
6491  register int
6492  x;
6493 
6494  register const Quantum
6495  *p;
6496 
6497  register unsigned char
6498  *q;
6499 
6500  unsigned char
6501  bit,
6502  byte;
6503 
6504  unsigned int
6505  scanline_pad;
6506 
6507  unsigned long
6508  pixel,
6509  *pixels;
6510 
6511  XStandardColormap
6512  *map_info;
6513 
6514  assert(resource_info != (XResourceInfo *) NULL);
6515  assert(window != (XWindowInfo *) NULL);
6516  assert(image != (Image *) NULL);
6517  if (image->debug != MagickFalse)
6518  (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
6519  canvas=image;
6520  if ((window->immutable != MagickFalse) &&
6521  (image->storage_class == DirectClass) &&
6522  (image->alpha_trait != UndefinedPixelTrait))
6523  {
6524  char
6525  size[MagickPathExtent];
6526 
6527  Image
6528  *pattern;
6529 
6530  ImageInfo
6531  *image_info;
6532 
6533  image_info=AcquireImageInfo();
6534  (void) CopyMagickString(image_info->filename,
6535  resource_info->image_info->texture != (char *) NULL ?
6536  resource_info->image_info->texture : "pattern:checkerboard",
6538  (void) FormatLocaleString(size,MagickPathExtent,"%.20gx%.20g",(double)
6539  image->columns,(double) image->rows);
6540  image_info->size=ConstantString(size);
6541  pattern=ReadImage(image_info,exception);
6542  image_info=DestroyImageInfo(image_info);
6543  if (pattern != (Image *) NULL)
6544  {
6545  canvas=CloneImage(image,0,0,MagickTrue,exception);
6546  if (canvas != (Image *) NULL)
6547  (void) CompositeImage(canvas,pattern,DstOverCompositeOp,MagickFalse,
6548  0,0,exception);
6549  pattern=DestroyImage(pattern);
6550  }
6551  }
6552  scanline_pad=(unsigned int) (ximage->bytes_per_line-((ximage->width*
6553  ximage->bits_per_pixel) >> 3));
6554  map_info=window->map_info;
6555  pixels=window->pixel_info->pixels;
6556  q=(unsigned char *) ximage->data;
6557  x=0;
6558  canvas_view=AcquireVirtualCacheView(canvas,exception);
6559  if (ximage->format == XYBitmap)
6560  {
6561  register unsigned short
6562  polarity;
6563 
6564  unsigned char
6565  background,
6566  foreground;
6567 
6568  /*
6569  Convert canvas to big-endian bitmap.
6570  */
6571  background=(unsigned char)
6572  (XPixelIntensity(&window->pixel_info->foreground_color) <
6573  XPixelIntensity(&window->pixel_info->background_color) ? 0x01 : 0x00);
6574  foreground=(unsigned char)
6575  (XPixelIntensity(&window->pixel_info->background_color) <
6576  XPixelIntensity(&window->pixel_info->foreground_color) ? 0x01 : 0x00);
6577  polarity=(unsigned short) ((GetPixelInfoIntensity(image,
6578  &canvas->colormap[0])) < (QuantumRange/2.0) ? 1 : 0);
6579  if (canvas->colors == 2)
6580  polarity=GetPixelInfoIntensity(image,&canvas->colormap[0]) <
6581  GetPixelInfoIntensity(image,&canvas->colormap[1]);
6582  for (y=0; y < (int) canvas->rows; y++)
6583  {
6584  p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,canvas->columns,1,
6585  exception);
6586  if (p == (const Quantum *) NULL)
6587  break;
6588  bit=0;
6589  byte=0;
6590  for (x=(int) canvas->columns-1; x >= 0; x--)
6591  {
6592  byte<<=1;
6593  if (GetPixelIndex(canvas,p) == (Quantum) polarity)
6594  byte|=foreground;
6595  else
6596  byte|=background;
6597  bit++;
6598  if (bit == 8)
6599  {
6600  *q++=byte;
6601  bit=0;
6602  byte=0;
6603  }
6604  p+=GetPixelChannels(canvas);
6605  }
6606  if (bit != 0)
6607  *q=byte << (8-bit);
6608  q+=scanline_pad;
6609  }
6610  }
6611  else
6612  if (window->pixel_info->colors != 0)
6613  switch (ximage->bits_per_pixel)
6614  {
6615  case 2:
6616  {
6617  register unsigned int
6618  nibble;
6619 
6620  /*
6621  Convert to 2 bit color-mapped X canvas.
6622  */
6623  for (y=0; y < (int) canvas->rows; y++)
6624  {
6625  p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
6626  canvas->columns,1,exception);
6627  if (p == (const Quantum *) NULL)
6628  break;
6629  nibble=0;
6630  for (x=0; x < (int) canvas->columns; x++)
6631  {
6632  pixel=pixels[(ssize_t)
6633  GetPixelIndex(canvas,p)] & 0xf;
6634  switch (nibble)
6635  {
6636  case 0:
6637  {
6638  *q=(unsigned char) (pixel << 6);