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