MagickCore  7.1.1-43
Convert, Edit, Or Compose Bitmap Images
xwindow.c
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"
49 #include "MagickCore/color-private.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"
56 #include "MagickCore/exception-private.h"
57 #include "MagickCore/geometry.h"
58 #include "MagickCore/identify.h"
59 #include "MagickCore/image.h"
60 #include "MagickCore/image-private.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"
66 #include "MagickCore/memory-private.h"
67 #include "MagickCore/monitor.h"
68 #include "MagickCore/nt-base-private.h"
69 #include "MagickCore/option.h"
70 #include "MagickCore/pixel-accessor.h"
71 #include "MagickCore/quantize.h"
72 #include "MagickCore/quantum.h"
73 #include "MagickCore/quantum-private.h"
74 #include "MagickCore/resource_.h"
75 #include "MagickCore/resize.h"
76 #include "MagickCore/statistic.h"
77 #include "MagickCore/string_.h"
78 #include "MagickCore/string-private.h"
79 #include "MagickCore/transform.h"
80 #include "MagickCore/transform-private.h"
81 #include "MagickCore/token.h"
82 #include "MagickCore/utility.h"
83 #include "MagickCore/utility-private.h"
84 #include "MagickCore/widget.h"
85 #include "MagickCore/widget-private.h"
86 #include "MagickCore/xwindow.h"
87 #include "MagickCore/xwindow-private.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((QuantumScale*(double) (color)),1.0* \
115  PerceptibleReciprocal((double) blue_gamma))*(double) 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((QuantumScale*(double) (color)),1.0* \
132  PerceptibleReciprocal((double) green_gamma))*(double) QuantumRange)))
133 #define XRedGamma(color) ClampToQuantum(red_gamma == 1.0 ? (double) \
134  (color) : ((pow((QuantumScale*(double) (color)),1.0* \
135  PerceptibleReciprocal((double) red_gamma))*(double) 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 declarations.
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 }
435 
436 /*
437 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
438 % %
439 % %
440 % %
441 % X A n n o t a t e I m a g e %
442 % %
443 % %
444 % %
445 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
446 %
447 % XAnnotateImage() annotates the image with text.
448 %
449 % The format of the XAnnotateImage method is:
450 %
451 % MagickBooleanType XAnnotateImage(Display *display,
452 % const XPixelInfo *pixel,XAnnotateInfo *annotate_info,Image *image,
453 % ExceptionInfo *exception)
454 %
455 % A description of each parameter follows:
456 %
457 % o display: Specifies a connection to an X server; returned from
458 % XOpenDisplay.
459 %
460 % o pixel: Specifies a pointer to a XPixelInfo structure.
461 %
462 % o annotate_info: Specifies a pointer to a XAnnotateInfo structure.
463 %
464 % o image: the image.
465 %
466 % o exception: return any errors or warnings in this structure.
467 %
468 */
469 MagickPrivate MagickBooleanType XAnnotateImage(Display *display,
470  const XPixelInfo *pixel,XAnnotateInfo *annotate_info,Image *image,
471  ExceptionInfo *exception)
472 {
473  CacheView
474  *annotate_view;
475 
476  GC
477  annotate_context;
478 
479  Image
480  *annotate_image;
481 
482  int
483  x,
484  y;
485 
486  PixelTrait
487  alpha_trait;
488 
489  Pixmap
490  annotate_pixmap;
491 
492  unsigned int
493  depth,
494  height,
495  width;
496 
497  Window
498  root_window;
499 
500  XGCValues
501  context_values;
502 
503  XImage
504  *annotate_ximage;
505 
506  /*
507  Initialize annotated image.
508  */
509  assert(display != (Display *) NULL);
510  assert(pixel != (XPixelInfo *) NULL);
511  assert(annotate_info != (XAnnotateInfo *) NULL);
512  assert(image != (Image *) NULL);
513  if (IsEventLogging() != MagickFalse)
514  (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
515  /*
516  Initialize annotated pixmap.
517  */
518  root_window=XRootWindow(display,XDefaultScreen(display));
519  depth=(unsigned int) XDefaultDepth(display,XDefaultScreen(display));
520  annotate_pixmap=XCreatePixmap(display,root_window,annotate_info->width,
521  annotate_info->height,depth);
522  if (annotate_pixmap == (Pixmap) NULL)
523  return(MagickFalse);
524  /*
525  Initialize graphics info.
526  */
527  context_values.background=0;
528  context_values.foreground=(size_t) (~0);
529  context_values.font=annotate_info->font_info->fid;
530  annotate_context=XCreateGC(display,root_window,(unsigned long)
531  (GCBackground | GCFont | GCForeground),&context_values);
532  if (annotate_context == (GC) NULL)
533  return(MagickFalse);
534  /*
535  Draw text to pixmap.
536  */
537  (void) XDrawImageString(display,annotate_pixmap,annotate_context,0,
538  (int) annotate_info->font_info->ascent,annotate_info->text,
539  (int) strlen(annotate_info->text));
540  (void) XFreeGC(display,annotate_context);
541  /*
542  Initialize annotated X image.
543  */
544  annotate_ximage=XGetImage(display,annotate_pixmap,0,0,annotate_info->width,
545  annotate_info->height,AllPlanes,ZPixmap);
546  if (annotate_ximage == (XImage *) NULL)
547  return(MagickFalse);
548  (void) XFreePixmap(display,annotate_pixmap);
549  /*
550  Initialize annotated image.
551  */
552  annotate_image=AcquireImage((ImageInfo *) NULL,exception);
553  if (annotate_image == (Image *) NULL)
554  return(MagickFalse);
555  annotate_image->columns=annotate_info->width;
556  annotate_image->rows=annotate_info->height;
557  /*
558  Transfer annotated X image to image.
559  */
560  width=(unsigned int) image->columns;
561  height=(unsigned int) image->rows;
562  x=0;
563  y=0;
564  (void) XParseGeometry(annotate_info->geometry,&x,&y,&width,&height);
565  (void) GetOneVirtualPixelInfo(image,UndefinedVirtualPixelMethod,(ssize_t) x,
566  (ssize_t) y,&annotate_image->background_color,exception);
567  if (annotate_info->stencil == ForegroundStencil)
568  annotate_image->alpha_trait=BlendPixelTrait;
569  annotate_view=AcquireAuthenticCacheView(annotate_image,exception);
570  for (y=0; y < (int) annotate_image->rows; y++)
571  {
572  int
573  x;
574 
575  Quantum
576  *magick_restrict q;
577 
578  q=GetCacheViewAuthenticPixels(annotate_view,0,(ssize_t) y,
579  annotate_image->columns,1,exception);
580  if (q == (Quantum *) NULL)
581  break;
582  for (x=0; x < (int) annotate_image->columns; x++)
583  {
584  SetPixelAlpha(annotate_image,OpaqueAlpha,q);
585  if (XGetPixel(annotate_ximage,x,y) == 0)
586  {
587  /*
588  Set this pixel to the background color.
589  */
590  SetPixelRed(annotate_image,ScaleShortToQuantum(
591  pixel->box_color.red),q);
592  SetPixelGreen(annotate_image,ScaleShortToQuantum(
593  pixel->box_color.green),q);
594  SetPixelBlue(annotate_image,ScaleShortToQuantum(
595  pixel->box_color.blue),q);
596  if ((annotate_info->stencil == ForegroundStencil) ||
597  (annotate_info->stencil == OpaqueStencil))
598  SetPixelAlpha(annotate_image,TransparentAlpha,q);
599  }
600  else
601  {
602  /*
603  Set this pixel to the pen color.
604  */
605  SetPixelRed(annotate_image,ScaleShortToQuantum(
606  pixel->pen_color.red),q);
607  SetPixelGreen(annotate_image,ScaleShortToQuantum(
608  pixel->pen_color.green),q);
609  SetPixelBlue(annotate_image,ScaleShortToQuantum(
610  pixel->pen_color.blue),q);
611  if (annotate_info->stencil == BackgroundStencil)
612  SetPixelAlpha(annotate_image,TransparentAlpha,q);
613  }
614  q+=(ptrdiff_t) GetPixelChannels(annotate_image);
615  }
616  if (SyncCacheViewAuthenticPixels(annotate_view,exception) == MagickFalse)
617  break;
618  }
619  annotate_view=DestroyCacheView(annotate_view);
620  XDestroyImage(annotate_ximage);
621  /*
622  Determine annotate geometry.
623  */
624  (void) XParseGeometry(annotate_info->geometry,&x,&y,&width,&height);
625  if ((width != (unsigned int) annotate_image->columns) ||
626  (height != (unsigned int) annotate_image->rows))
627  {
628  char
629  image_geometry[MagickPathExtent];
630 
631  /*
632  Scale image.
633  */
634  (void) FormatLocaleString(image_geometry,MagickPathExtent,"%ux%u",
635  width,height);
636  (void) TransformImage(&annotate_image,(char *) NULL,image_geometry,
637  exception);
638  }
639  if (annotate_info->degrees != 0.0)
640  {
641  Image
642  *rotate_image;
643 
644  int
645  rotations;
646 
647  double
648  normalized_degrees;
649 
650  /*
651  Rotate image.
652  */
653  rotate_image=RotateImage(annotate_image,annotate_info->degrees,exception);
654  if (rotate_image == (Image *) NULL)
655  return(MagickFalse);
656  annotate_image=DestroyImage(annotate_image);
657  annotate_image=rotate_image;
658  /*
659  Annotation is relative to the degree of rotation.
660  */
661  normalized_degrees=annotate_info->degrees;
662  while (normalized_degrees < -45.0)
663  normalized_degrees+=360.0;
664  for (rotations=0; normalized_degrees > 45.0; rotations++)
665  normalized_degrees-=90.0;
666  switch (rotations % 4)
667  {
668  default:
669  case 0:
670  break;
671  case 1:
672  {
673  /*
674  Rotate 90 degrees.
675  */
676  x-=(int) annotate_image->columns/2;
677  y+=(int) annotate_image->columns/2;
678  break;
679  }
680  case 2:
681  {
682  /*
683  Rotate 180 degrees.
684  */
685  x=x-(int) annotate_image->columns;
686  break;
687  }
688  case 3:
689  {
690  /*
691  Rotate 270 degrees.
692  */
693  x=x-(int) annotate_image->columns/2;
694  y=y-(int) (annotate_image->rows-(annotate_image->columns/2));
695  break;
696  }
697  }
698  }
699  /*
700  Composite text onto the image.
701  */
702  (void) XParseGeometry(annotate_info->geometry,&x,&y,&width,&height);
703  alpha_trait=image->alpha_trait;
704  (void) CompositeImage(image,annotate_image,
705  annotate_image->alpha_trait != UndefinedPixelTrait ? OverCompositeOp :
706  CopyCompositeOp,MagickTrue,(ssize_t) x,(ssize_t) y,exception);
707  image->alpha_trait=alpha_trait;
708  annotate_image=DestroyImage(annotate_image);
709  return(MagickTrue);
710 }
711 
712 /*
713 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
714 % %
715 % %
716 % %
717 % X B e s t F o n t %
718 % %
719 % %
720 % %
721 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
722 %
723 % XBestFont() returns the "best" font. "Best" is defined as a font specified
724 % in the X resource database or a font such that the text width displayed
725 % with the font does not exceed the specified maximum width.
726 %
727 % The format of the XBestFont method is:
728 %
729 % XFontStruct *XBestFont(Display *display,
730 % const XResourceInfo *resource_info,const MagickBooleanType text_font)
731 %
732 % A description of each parameter follows:
733 %
734 % o font: XBestFont returns a pointer to a XFontStruct structure.
735 %
736 % o display: Specifies a connection to an X server; returned from
737 % XOpenDisplay.
738 %
739 % o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
740 %
741 % o text_font: True is font should be mono-spaced (typewriter style).
742 %
743 */
744 
745 static char **FontToList(char *font)
746 {
747  char
748  **fontlist;
749 
750  char
751  *p,
752  *q;
753 
754  int
755  i;
756 
757  unsigned int
758  fonts;
759 
760  if (font == (char *) NULL)
761  return((char **) NULL);
762  /*
763  Convert string to an ASCII list.
764  */
765  fonts=1U;
766  for (p=font; *p != '\0'; p++)
767  if ((*p == ':') || (*p == ';') || (*p == ','))
768  fonts++;
769  fontlist=(char **) AcquireQuantumMemory((size_t) fonts+1UL,sizeof(*fontlist));
770  if (fontlist == (char **) NULL)
771  {
772  ThrowXWindowException(ResourceLimitError,"MemoryAllocationFailed",font);
773  return((char **) NULL);
774  }
775  p=font;
776  for (i=0; i < (int) fonts; i++)
777  {
778  for (q=p; *q != '\0'; q++)
779  if ((*q == ':') || (*q == ';') || (*q == ','))
780  break;
781  fontlist[i]=(char *) AcquireQuantumMemory((size_t) (q-p)+1UL,
782  sizeof(*fontlist[i]));
783  if (fontlist[i] == (char *) NULL)
784  {
785  ThrowXWindowException(ResourceLimitError,"MemoryAllocationFailed",font);
786  return((char **) NULL);
787  }
788  (void) CopyMagickString(fontlist[i],p,(size_t) (q-p+1));
789  p=q+1;
790  }
791  fontlist[i]=(char *) NULL;
792  return(fontlist);
793 }
794 
795 MagickPrivate XFontStruct *XBestFont(Display *display,
796  const XResourceInfo *resource_info,const MagickBooleanType text_font)
797 {
798  static const char
799  *Fonts[]=
800  {
801  "-*-helvetica-medium-r-normal--12-*-*-*-*-*-iso8859-1",
802  "-*-arial-medium-r-normal--12-*-*-*-*-*-iso8859-1",
803  "-*-helvetica-medium-r-normal--12-*-*-*-*-*-iso8859-15",
804  "-*-arial-medium-r-normal--12-*-*-*-*-*-iso8859-15",
805  "-*-helvetica-medium-r-normal--12-*-*-*-*-*-*-*",
806  "-*-arial-medium-r-normal--12-*-*-*-*-*-*-*",
807  "variable",
808  "fixed",
809  (char *) NULL
810  },
811  *TextFonts[]=
812  {
813  "-*-courier-medium-r-normal-*-12-*-*-*-*-*-iso8859-1",
814  "-*-courier-medium-r-normal-*-12-*-*-*-*-*-iso8859-15",
815  "-*-fixed-medium-r-normal-*-12-*-*-*-*-*-*-*",
816  "fixed",
817  (char *) NULL
818  };
819 
820  char
821  *font_name;
822 
823  const char
824  **p;
825 
826  XFontStruct
827  *font_info;
828 
829  font_info=(XFontStruct *) NULL;
830  font_name=resource_info->font;
831  if (text_font != MagickFalse)
832  font_name=resource_info->text_font;
833  if ((font_name != (char *) NULL) && (*font_name != '\0'))
834  {
835  char
836  **fontlist;
837 
838  int
839  i;
840 
841  /*
842  Load preferred font specified in the X resource database.
843  */
844  fontlist=FontToList(font_name);
845  if (fontlist != (char **) NULL)
846  {
847  for (i=0; fontlist[i] != (char *) NULL; i++)
848  {
849  if (font_info == (XFontStruct *) NULL)
850  font_info=XLoadQueryFont(display,fontlist[i]);
851  fontlist[i]=DestroyString(fontlist[i]);
852  }
853  fontlist=(char **) RelinquishMagickMemory(fontlist);
854  }
855  if (font_info == (XFontStruct *) NULL)
856  ThrowXWindowException(XServerError,"UnableToLoadFont",font_name);
857  }
858  /*
859  Load fonts from list of fonts until one is found.
860  */
861  p=Fonts;
862  if (text_font != MagickFalse)
863  p=TextFonts;
864  if (XDisplayHeight(display,XDefaultScreen(display)) >= 748)
865  p++;
866  while (*p != (char *) NULL)
867  {
868  if (font_info != (XFontStruct *) NULL)
869  break;
870  font_info=XLoadQueryFont(display,(char *) *p);
871  p++;
872  }
873  return(font_info);
874 }
875 
876 /*
877 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
878 % %
879 % %
880 % %
881 % X B e s t I c o n S i z e %
882 % %
883 % %
884 % %
885 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
886 %
887 % XBestIconSize() returns the "best" icon size. "Best" is defined as an icon
888 % size that maintains the aspect ratio of the image. If the window manager
889 % has preferred icon sizes, one of the preferred sizes is used.
890 %
891 % The format of the XBestIconSize method is:
892 %
893 % void XBestIconSize(Display *display,XWindowInfo *window,Image *image)
894 %
895 % A description of each parameter follows:
896 %
897 % o display: Specifies a connection to an X server; returned from
898 % XOpenDisplay.
899 %
900 % o image: the image.
901 %
902 */
903 MagickPrivate void XBestIconSize(Display *display,XWindowInfo *window,
904  Image *image)
905 {
906  int
907  i,
908  number_sizes;
909 
910  double
911  scale_factor;
912 
913  unsigned int
914  height,
915  icon_height,
916  icon_width,
917  width;
918 
919  Window
920  root_window;
921 
922  XIconSize
923  *icon_size,
924  *size_list;
925 
926  /*
927  Determine if the window manager has specified preferred icon sizes.
928  */
929  assert(display != (Display *) NULL);
930  assert(window != (XWindowInfo *) NULL);
931  assert(image != (Image *) NULL);
932  if (IsEventLogging() != MagickFalse)
933  (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
934  window->width=MaxIconSize;
935  window->height=MaxIconSize;
936  icon_size=(XIconSize *) NULL;
937  number_sizes=0;
938  root_window=XRootWindow(display,window->screen);
939  if (XGetIconSizes(display,root_window,&size_list,&number_sizes) != 0)
940  if ((number_sizes > 0) && (size_list != (XIconSize *) NULL))
941  icon_size=size_list;
942  if (icon_size == (XIconSize *) NULL)
943  {
944  /*
945  Window manager does not restrict icon size.
946  */
947  icon_size=XAllocIconSize();
948  if (icon_size == (XIconSize *) NULL)
949  {
950  ThrowXWindowException(ResourceLimitError,"MemoryAllocationFailed",
951  image->filename);
952  return;
953  }
954  icon_size->min_width=1;
955  icon_size->max_width=MaxIconSize;
956  icon_size->min_height=1;
957  icon_size->max_height=MaxIconSize;
958  icon_size->width_inc=1;
959  icon_size->height_inc=1;
960  }
961  /*
962  Determine aspect ratio of image.
963  */
964  width=(unsigned int) image->columns;
965  height=(unsigned int) image->rows;
966  i=0;
967  if (window->crop_geometry)
968  (void) XParseGeometry(window->crop_geometry,&i,&i,&width,&height);
969  /*
970  Look for an icon size that maintains the aspect ratio of image.
971  */
972  scale_factor=(double) icon_size->max_width/width;
973  if (scale_factor > ((double) icon_size->max_height/height))
974  scale_factor=(double) icon_size->max_height/height;
975  icon_width=(unsigned int) icon_size->min_width;
976  while ((int) icon_width < icon_size->max_width)
977  {
978  if (icon_width >= (unsigned int) (scale_factor*width+0.5))
979  break;
980  icon_width+=(unsigned int) icon_size->width_inc;
981  }
982  icon_height=(unsigned int) icon_size->min_height;
983  while ((int) icon_height < icon_size->max_height)
984  {
985  if (icon_height >= (unsigned int) (scale_factor*height+0.5))
986  break;
987  icon_height+=(unsigned int) icon_size->height_inc;
988  }
989  (void) XFree((void *) icon_size);
990  window->width=icon_width;
991  window->height=icon_height;
992 }
993 
994 /*
995 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
996 % %
997 % %
998 % %
999 % X B e s t P i x e l %
1000 % %
1001 % %
1002 % %
1003 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1004 %
1005 % XBestPixel() returns a pixel from an array of pixels that is closest to the
1006 % requested color. If the color array is NULL, the colors are obtained from
1007 % the X server.
1008 %
1009 % The format of the XBestPixel method is:
1010 %
1011 % void XBestPixel(Display *display,const Colormap colormap,XColor *colors,
1012 % unsigned int number_colors,XColor *color)
1013 %
1014 % A description of each parameter follows:
1015 %
1016 % o pixel: XBestPixel returns the pixel value closest to the requested
1017 % color.
1018 %
1019 % o display: Specifies a connection to an X server; returned from
1020 % XOpenDisplay.
1021 %
1022 % o colormap: Specifies the ID of the X server colormap.
1023 %
1024 % o colors: Specifies an array of XColor structures.
1025 %
1026 % o number_colors: Specifies the number of XColor structures in the
1027 % color definition array.
1028 %
1029 % o color: Specifies the desired RGB value to find in the colors array.
1030 %
1031 */
1032 MagickPrivate void XBestPixel(Display *display,const Colormap colormap,
1033  XColor *colors,unsigned int number_colors,XColor *color)
1034 {
1035  MagickBooleanType
1036  query_server;
1037 
1038  PixelInfo
1039  pixel;
1040 
1041  double
1042  min_distance;
1043 
1044  double
1045  distance;
1046 
1047  int
1048  i,
1049  j;
1050 
1051  Status
1052  status;
1053 
1054  /*
1055  Find closest representation for the requested RGB color.
1056  */
1057  assert(display != (Display *) NULL);
1058  assert(color != (XColor *) NULL);
1059  if (IsEventLogging() != MagickFalse)
1060  (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
1061  status=XAllocColor(display,colormap,color);
1062  if (status != False)
1063  return;
1064  query_server=colors == (XColor *) NULL ? MagickTrue : MagickFalse;
1065  if (query_server != MagickFalse)
1066  {
1067  /*
1068  Read X server colormap.
1069  */
1070  colors=(XColor *) AcquireQuantumMemory(number_colors,sizeof(*colors));
1071  if (colors == (XColor *) NULL)
1072  {
1073  ThrowXWindowException(ResourceLimitError,"MemoryAllocationFailed",
1074  "...");
1075  return;
1076  }
1077  for (i=0; i < (int) number_colors; i++)
1078  colors[i].pixel=(size_t) i;
1079  if (number_colors > 256)
1080  number_colors=256;
1081  (void) XQueryColors(display,colormap,colors,(int) number_colors);
1082  }
1083  min_distance=3.0*((double) QuantumRange+1.0)*((double)
1084  QuantumRange+1.0);
1085  j=0;
1086  for (i=0; i < (int) number_colors; i++)
1087  {
1088  pixel.red=colors[i].red-(double) color->red;
1089  distance=pixel.red*pixel.red;
1090  if (distance > min_distance)
1091  continue;
1092  pixel.green=colors[i].green-(double) color->green;
1093  distance+=pixel.green*pixel.green;
1094  if (distance > min_distance)
1095  continue;
1096  pixel.blue=colors[i].blue-(double) color->blue;
1097  distance+=pixel.blue*pixel.blue;
1098  if (distance > min_distance)
1099  continue;
1100  min_distance=distance;
1101  color->pixel=colors[i].pixel;
1102  j=i;
1103  }
1104  (void) XAllocColor(display,colormap,&colors[j]);
1105  if (query_server != MagickFalse)
1106  colors=(XColor *) RelinquishMagickMemory(colors);
1107 }
1108 
1109 /*
1110 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1111 % %
1112 % %
1113 % %
1114 % X B e s t V i s u a l I n f o %
1115 % %
1116 % %
1117 % %
1118 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1119 %
1120 % XBestVisualInfo() returns visual information for a visual that is the "best"
1121 % the server supports. "Best" is defined as:
1122 %
1123 % 1. Restrict the visual list to those supported by the default screen.
1124 %
1125 % 2. If a visual type is specified, restrict the visual list to those of
1126 % that type.
1127 %
1128 % 3. If a map type is specified, choose the visual that matches the id
1129 % specified by the Standard Colormap.
1130 %
1131 % 4 From the list of visuals, choose one that can display the most
1132 % simultaneous colors. If more than one visual can display the same
1133 % number of simultaneous colors, one is chosen based on a rank.
1134 %
1135 % The format of the XBestVisualInfo method is:
1136 %
1137 % XVisualInfo *XBestVisualInfo(Display *display,
1138 % XStandardColormap *map_info,XResourceInfo *resource_info)
1139 %
1140 % A description of each parameter follows:
1141 %
1142 % o visual_info: XBestVisualInfo returns a pointer to a X11 XVisualInfo
1143 % structure.
1144 %
1145 % o display: Specifies a connection to an X server; returned from
1146 % XOpenDisplay.
1147 %
1148 % o map_info: If map_type is specified, this structure is initialized
1149 % with info from the Standard Colormap.
1150 %
1151 % o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
1152 %
1153 */
1154 MagickPrivate XVisualInfo *XBestVisualInfo(Display *display,
1155  XStandardColormap *map_info,XResourceInfo *resource_info)
1156 {
1157 #define MaxStandardColormaps 7
1158 #define XVisualColormapSize(visual_info) MagickMin((unsigned int) (\
1159  (visual_info->klass == TrueColor) || (visual_info->klass == DirectColor) ? \
1160  visual_info->red_mask | visual_info->green_mask | visual_info->blue_mask : \
1161  (unsigned long) visual_info->colormap_size),1UL << visual_info->depth)
1162 
1163  char
1164  *map_type,
1165  *visual_type;
1166 
1167  int
1168  visual_mask;
1169 
1170  int
1171  i;
1172 
1173  size_t
1174  one;
1175 
1176  static int
1177  number_visuals;
1178 
1179  static XVisualInfo
1180  visual_template;
1181 
1182  XVisualInfo
1183  *visual_info,
1184  *visual_list;
1185 
1186  /*
1187  Restrict visual search by screen number.
1188  */
1189  assert(display != (Display *) NULL);
1190  assert(map_info != (XStandardColormap *) NULL);
1191  assert(resource_info != (XResourceInfo *) NULL);
1192  if (IsEventLogging() != MagickFalse)
1193  (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
1194  map_type=resource_info->map_type;
1195  visual_type=resource_info->visual_type;
1196  visual_mask=VisualScreenMask;
1197  visual_template.screen=XDefaultScreen(display);
1198  visual_template.depth=XDefaultDepth(display,XDefaultScreen(display));
1199  one=1;
1200  if ((resource_info->immutable != MagickFalse) && (resource_info->colors != 0))
1201  if (resource_info->colors <= (one << (size_t) visual_template.depth))
1202  visual_mask|=VisualDepthMask;
1203  if (visual_type != (char *) NULL)
1204  {
1205  /*
1206  Restrict visual search by class or visual id.
1207  */
1208  if (LocaleCompare("staticgray",visual_type) == 0)
1209  {
1210  visual_mask|=VisualClassMask;
1211  visual_template.klass=StaticGray;
1212  }
1213  else
1214  if (LocaleCompare("grayscale",visual_type) == 0)
1215  {
1216  visual_mask|=VisualClassMask;
1217  visual_template.klass=GrayScale;
1218  }
1219  else
1220  if (LocaleCompare("staticcolor",visual_type) == 0)
1221  {
1222  visual_mask|=VisualClassMask;
1223  visual_template.klass=StaticColor;
1224  }
1225  else
1226  if (LocaleCompare("pseudocolor",visual_type) == 0)
1227  {
1228  visual_mask|=VisualClassMask;
1229  visual_template.klass=PseudoColor;
1230  }
1231  else
1232  if (LocaleCompare("truecolor",visual_type) == 0)
1233  {
1234  visual_mask|=VisualClassMask;
1235  visual_template.klass=TrueColor;
1236  }
1237  else
1238  if (LocaleCompare("directcolor",visual_type) == 0)
1239  {
1240  visual_mask|=VisualClassMask;
1241  visual_template.klass=DirectColor;
1242  }
1243  else
1244  if (LocaleCompare("default",visual_type) == 0)
1245  {
1246  visual_mask|=VisualIDMask;
1247  visual_template.visualid=XVisualIDFromVisual(
1248  XDefaultVisual(display,XDefaultScreen(display)));
1249  }
1250  else
1251  if (isdigit((int) ((unsigned char) *visual_type)) != 0)
1252  {
1253  visual_mask|=VisualIDMask;
1254  visual_template.visualid=(size_t)
1255  strtol(visual_type,(char **) NULL,0);
1256  }
1257  else
1258  ThrowXWindowException(XServerError,
1259  "UnrecognizedVisualSpecifier",visual_type);
1260  }
1261  /*
1262  Get all visuals that meet our criteria so far.
1263  */
1264  number_visuals=0;
1265  visual_list=XGetVisualInfo(display,visual_mask,&visual_template,
1266  &number_visuals);
1267  visual_mask=VisualScreenMask | VisualIDMask;
1268  if ((number_visuals == 0) || (visual_list == (XVisualInfo *) NULL))
1269  {
1270  /*
1271  Failed to get visual; try using the default visual.
1272  */
1273  ThrowXWindowException(XServerWarning,"UnableToGetVisual",visual_type);
1274  visual_template.visualid=XVisualIDFromVisual(XDefaultVisual(display,
1275  XDefaultScreen(display)));
1276  visual_list=XGetVisualInfo(display,visual_mask,&visual_template,
1277  &number_visuals);
1278  if ((number_visuals == 0) || (visual_list == (XVisualInfo *) NULL))
1279  return((XVisualInfo *) NULL);
1280  ThrowXWindowException(XServerWarning,"UsingDefaultVisual",
1281  XVisualClassName(visual_list->klass));
1282  }
1283  resource_info->color_recovery=MagickFalse;
1284  if ((map_info != (XStandardColormap *) NULL) && (map_type != (char *) NULL))
1285  {
1286  Atom
1287  map_property;
1288 
1289  char
1290  map_name[MagickPathExtent];
1291 
1292  int
1293  j,
1294  number_maps;
1295 
1296  Status
1297  status;
1298 
1299  Window
1300  root_window;
1301 
1302  XStandardColormap
1303  *map_list;
1304 
1305  /*
1306  Choose a visual associated with a standard colormap.
1307  */
1308  root_window=XRootWindow(display,XDefaultScreen(display));
1309  status=False;
1310  number_maps=0;
1311  if (LocaleCompare(map_type,"list") != 0)
1312  {
1313  /*
1314  User specified Standard Colormap.
1315  */
1316  (void) FormatLocaleString((char *) map_name,MagickPathExtent,
1317  "RGB_%s_MAP",map_type);
1318  LocaleUpper(map_name);
1319  map_property=XInternAtom(display,(char *) map_name,MagickTrue);
1320  if (map_property != (Atom) NULL)
1321  status=XGetRGBColormaps(display,root_window,&map_list,&number_maps,
1322  map_property);
1323  }
1324  else
1325  {
1326  static const char
1327  *colormap[MaxStandardColormaps]=
1328  {
1329  "_HP_RGB_SMOOTH_MAP_LIST",
1330  "RGB_BEST_MAP",
1331  "RGB_DEFAULT_MAP",
1332  "RGB_GRAY_MAP",
1333  "RGB_RED_MAP",
1334  "RGB_GREEN_MAP",
1335  "RGB_BLUE_MAP",
1336  };
1337 
1338  /*
1339  Choose a standard colormap from a list.
1340  */
1341  for (i=0; i < MaxStandardColormaps; i++)
1342  {
1343  map_property=XInternAtom(display,(char *) colormap[i],MagickTrue);
1344  if (map_property == (Atom) NULL)
1345  continue;
1346  status=XGetRGBColormaps(display,root_window,&map_list,&number_maps,
1347  map_property);
1348  if (status != False)
1349  break;
1350  }
1351  resource_info->color_recovery=i == 0 ? MagickTrue : MagickFalse;
1352  }
1353  if (status == False)
1354  {
1355  ThrowXWindowException(XServerError,"UnableToGetStandardColormap",
1356  map_type);
1357  return((XVisualInfo *) NULL);
1358  }
1359  /*
1360  Search all Standard Colormaps and visuals for ids that match.
1361  */
1362  *map_info=map_list[0];
1363 #if !defined(PRE_R4_ICCCM)
1364  visual_template.visualid=XVisualIDFromVisual(visual_list[0].visual);
1365  for (i=0; i < number_maps; i++)
1366  for (j=0; j < number_visuals; j++)
1367  if (map_list[i].visualid ==
1368  XVisualIDFromVisual(visual_list[j].visual))
1369  {
1370  *map_info=map_list[i];
1371  visual_template.visualid=XVisualIDFromVisual(
1372  visual_list[j].visual);
1373  break;
1374  }
1375  if (map_info->visualid != visual_template.visualid)
1376  {
1377  ThrowXWindowException(XServerError,
1378  "UnableToMatchVisualToStandardColormap",map_type);
1379  return((XVisualInfo *) NULL);
1380  }
1381 #endif
1382  if (map_info->colormap == (Colormap) NULL)
1383  {
1384  ThrowXWindowException(XServerError,"StandardColormapIsNotInitialized",
1385  map_type);
1386  return((XVisualInfo *) NULL);
1387  }
1388  (void) XFree((void *) map_list);
1389  }
1390  else
1391  {
1392  static const unsigned int
1393  rank[]=
1394  {
1395  StaticGray,
1396  GrayScale,
1397  StaticColor,
1398  DirectColor,
1399  TrueColor,
1400  PseudoColor
1401  };
1402 
1403  XVisualInfo
1404  *p;
1405 
1406  /*
1407  Pick one visual that displays the most simultaneous colors.
1408  */
1409  visual_info=visual_list;
1410  p=visual_list;
1411  for (i=1; i < number_visuals; i++)
1412  {
1413  p++;
1414  if (XVisualColormapSize(p) > XVisualColormapSize(visual_info))
1415  visual_info=p;
1416  else
1417  if (XVisualColormapSize(p) == XVisualColormapSize(visual_info))
1418  if (rank[p->klass] > rank[visual_info->klass])
1419  visual_info=p;
1420  }
1421  visual_template.visualid=XVisualIDFromVisual(visual_info->visual);
1422  }
1423  (void) XFree((void *) visual_list);
1424  /*
1425  Retrieve only one visual by its screen & id number.
1426  */
1427  visual_info=XGetVisualInfo(display,visual_mask,&visual_template,
1428  &number_visuals);
1429  if ((number_visuals == 0) || (visual_info == (XVisualInfo *) NULL))
1430  return((XVisualInfo *) NULL);
1431  return(visual_info);
1432 }
1433 
1434 /*
1435 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1436 % %
1437 % %
1438 % %
1439 % X C h e c k D e f i n e C u r s o r %
1440 % %
1441 % %
1442 % %
1443 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1444 %
1445 % XCheckDefineCursor() prevents cursor changes on the root window.
1446 %
1447 % The format of the XXCheckDefineCursor method is:
1448 %
1449 % XCheckDefineCursor(display,window,cursor)
1450 %
1451 % A description of each parameter follows:
1452 %
1453 % o display: Specifies a connection to an X server; returned from
1454 % XOpenDisplay.
1455 %
1456 % o window: the window.
1457 %
1458 % o cursor: the cursor.
1459 %
1460 */
1461 MagickPrivate int XCheckDefineCursor(Display *display,Window window,
1462  Cursor cursor)
1463 {
1464  assert(display != (Display *) NULL);
1465  if (IsEventLogging() != MagickFalse)
1466  (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
1467  if (window == XRootWindow(display,XDefaultScreen(display)))
1468  return(0);
1469  return(XDefineCursor(display,window,cursor));
1470 }
1471 
1472 /*
1473 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1474 % %
1475 % %
1476 % %
1477 % X C h e c k R e f r e s h W i n d o w s %
1478 % %
1479 % %
1480 % %
1481 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1482 %
1483 % XCheckRefreshWindows() checks the X server for exposure events for a
1484 % particular window and updates the are associated with the exposure event.
1485 %
1486 % The format of the XCheckRefreshWindows method is:
1487 %
1488 % void XCheckRefreshWindows(Display *display,XWindows *windows)
1489 %
1490 % A description of each parameter follows:
1491 %
1492 % o display: Specifies a connection to an X server; returned from
1493 % XOpenDisplay.
1494 %
1495 % o windows: Specifies a pointer to a XWindows structure.
1496 %
1497 */
1498 MagickPrivate void XCheckRefreshWindows(Display *display,XWindows *windows)
1499 {
1500  Window
1501  id;
1502 
1503  XEvent
1504  event;
1505 
1506  assert(display != (Display *) NULL);
1507  assert(windows != (XWindows *) NULL);
1508  if (IsEventLogging() != MagickFalse)
1509  (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
1510  XDelay(display,SuspendTime);
1511  id=windows->command.id;
1512  while (XCheckTypedWindowEvent(display,id,Expose,&event) != MagickFalse)
1513  (void) XCommandWidget(display,windows,(char const **) NULL,&event);
1514  id=windows->image.id;
1515  while (XCheckTypedWindowEvent(display,id,Expose,&event) != MagickFalse)
1516  XRefreshWindow(display,&windows->image,&event);
1517  XDelay(display,SuspendTime << 1);
1518  id=windows->command.id;
1519  while (XCheckTypedWindowEvent(display,id,Expose,&event) != MagickFalse)
1520  (void) XCommandWidget(display,windows,(char const **) NULL,&event);
1521  id=windows->image.id;
1522  while (XCheckTypedWindowEvent(display,id,Expose,&event) != MagickFalse)
1523  XRefreshWindow(display,&windows->image,&event);
1524 }
1525 
1526 /*
1527 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1528 % %
1529 % %
1530 % %
1531 % X C l i e n t M e s s a g e %
1532 % %
1533 % %
1534 % %
1535 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1536 %
1537 % XClientMessage() sends a reason to a window with XSendEvent. The reason is
1538 % initialized with a particular protocol type and atom.
1539 %
1540 % The format of the XClientMessage function is:
1541 %
1542 % XClientMessage(display,window,protocol,reason,timestamp)
1543 %
1544 % A description of each parameter follows:
1545 %
1546 % o display: Specifies a pointer to the Display structure; returned from
1547 % XOpenDisplay.
1548 %
1549 % o window: Specifies a pointer to a Window structure.
1550 %
1551 % o protocol: Specifies an atom value.
1552 %
1553 % o reason: Specifies an atom value which is the reason to send.
1554 %
1555 % o timestamp: Specifies a value of type Time.
1556 %
1557 */
1558 MagickPrivate void XClientMessage(Display *display,const Window window,
1559  const Atom protocol,const Atom reason,const Time timestamp)
1560 {
1561  XClientMessageEvent
1562  client_event;
1563 
1564  assert(display != (Display *) NULL);
1565  (void) memset(&client_event,0,sizeof(client_event));
1566  client_event.type=ClientMessage;
1567  client_event.window=window;
1568  client_event.message_type=protocol;
1569  client_event.format=32;
1570  client_event.data.l[0]=(long) reason;
1571  client_event.data.l[1]=(long) timestamp;
1572  (void) XSendEvent(display,window,MagickFalse,NoEventMask,(XEvent *)
1573  &client_event);
1574 }
1575 
1576 /*
1577 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1578 % %
1579 % %
1580 % %
1581 + X C l i e n t W i n d o w %
1582 % %
1583 % %
1584 % %
1585 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1586 %
1587 % XClientWindow() finds a window, at or below the specified window, which has
1588 % a WM_STATE property. If such a window is found, it is returned, otherwise
1589 % the argument window is returned.
1590 %
1591 % The format of the XClientWindow function is:
1592 %
1593 % client_window=XClientWindow(display,target_window)
1594 %
1595 % A description of each parameter follows:
1596 %
1597 % o client_window: XClientWindow returns a window, at or below the specified
1598 % window, which has a WM_STATE property otherwise the argument
1599 % target_window is returned.
1600 %
1601 % o display: Specifies a pointer to the Display structure; returned from
1602 % XOpenDisplay.
1603 %
1604 % o target_window: Specifies the window to find a WM_STATE property.
1605 %
1606 */
1607 static Window XClientWindow(Display *display,Window target_window)
1608 {
1609  Atom
1610  state,
1611  type;
1612 
1613  int
1614  format;
1615 
1616  Status
1617  status;
1618 
1619  unsigned char
1620  *data;
1621 
1622  unsigned long
1623  after,
1624  number_items;
1625 
1626  Window
1627  client_window;
1628 
1629  assert(display != (Display *) NULL);
1630  if (IsEventLogging() != MagickFalse)
1631  (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
1632  state=XInternAtom(display,"WM_STATE",MagickTrue);
1633  if (state == (Atom) NULL)
1634  return(target_window);
1635  type=(Atom) NULL;
1636  status=XGetWindowProperty(display,target_window,state,0L,0L,MagickFalse,
1637  (Atom) AnyPropertyType,&type,&format,&number_items,&after,&data);
1638  if ((status == Success) && (type != (Atom) NULL))
1639  return(target_window);
1640  client_window=XWindowByProperty(display,target_window,state);
1641  if (client_window == (Window) NULL)
1642  return(target_window);
1643  return(client_window);
1644 }
1645 
1646 /*
1647 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1648 % %
1649 % %
1650 % %
1651 + X C o m p o n e n t T e r m i n u s %
1652 % %
1653 % %
1654 % %
1655 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1656 %
1657 % XComponentTerminus() destroys the module component.
1658 %
1659 % The format of the XComponentTerminus method is:
1660 %
1661 % XComponentTerminus(void)
1662 %
1663 */
1664 MagickPrivate void XComponentTerminus(void)
1665 {
1666  DestroyXResources();
1667 }
1668 
1669 /*
1670 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1671 % %
1672 % %
1673 % %
1674 % X C o n f i g u r e I m a g e C o l o r m a p %
1675 % %
1676 % %
1677 % %
1678 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1679 %
1680 % XConfigureImageColormap() creates a new X colormap.
1681 %
1682 % The format of the XConfigureImageColormap method is:
1683 %
1684 % void XConfigureImageColormap(Display *display,
1685 % XResourceInfo *resource_info,XWindows *windows,Image *image,
1686 % ExceptionInfo *exception)
1687 %
1688 % A description of each parameter follows:
1689 %
1690 % o display: Specifies a connection to an X server; returned from
1691 % XOpenDisplay.
1692 %
1693 % o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
1694 %
1695 % o windows: Specifies a pointer to a XWindows structure.
1696 %
1697 % o image: the image.
1698 %
1699 % o exception: return any errors or warnings in this structure.
1700 %
1701 */
1702 MagickPrivate void XConfigureImageColormap(Display *display,
1703  XResourceInfo *resource_info,XWindows *windows,Image *image,
1704  ExceptionInfo *exception)
1705 {
1706  Colormap
1707  colormap;
1708 
1709  /*
1710  Make standard colormap.
1711  */
1712  XSetCursorState(display,windows,MagickTrue);
1713  XCheckRefreshWindows(display,windows);
1714  XMakeStandardColormap(display,windows->visual_info,resource_info,image,
1715  windows->map_info,windows->pixel_info,exception);
1716  colormap=windows->map_info->colormap;
1717  (void) XSetWindowColormap(display,windows->image.id,colormap);
1718  (void) XSetWindowColormap(display,windows->command.id,colormap);
1719  (void) XSetWindowColormap(display,windows->widget.id,colormap);
1720  if (windows->magnify.mapped != MagickFalse)
1721  (void) XSetWindowColormap(display,windows->magnify.id,colormap);
1722  if (windows->pan.mapped != MagickFalse)
1723  (void) XSetWindowColormap(display,windows->pan.id,colormap);
1724  XSetCursorState(display,windows,MagickFalse);
1725  XClientMessage(display,windows->image.id,windows->im_protocols,
1726  windows->im_update_colormap,CurrentTime);
1727 }
1728 
1729 /*
1730 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1731 % %
1732 % %
1733 % %
1734 % X C o n s t r a i n W i n d o w P o s i t i o n %
1735 % %
1736 % %
1737 % %
1738 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1739 %
1740 % XConstrainWindowPosition() assures a window is positioned within the X
1741 % server boundaries.
1742 %
1743 % The format of the XConstrainWindowPosition method is:
1744 %
1745 % void XConstrainWindowPosition(Display *display,XWindowInfo *window_info)
1746 %
1747 % A description of each parameter follows:
1748 %
1749 % o display: Specifies a pointer to the Display structure; returned from
1750 % XOpenDisplay.
1751 %
1752 % o window_info: Specifies a pointer to a XWindowInfo structure.
1753 %
1754 */
1755 MagickPrivate void XConstrainWindowPosition(Display *display,
1756  XWindowInfo *window_info)
1757 {
1758  int
1759  limit;
1760 
1761  assert(display != (Display *) NULL);
1762  assert(window_info != (XWindowInfo *) NULL);
1763  if (IsEventLogging() != MagickFalse)
1764  (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
1765  limit=XDisplayWidth(display,window_info->screen)-(int) window_info->width;
1766  if (window_info->x < 0)
1767  window_info->x=0;
1768  else
1769  if (window_info->x > (int) limit)
1770  window_info->x=(int) limit;
1771  limit=XDisplayHeight(display,window_info->screen)-(int) window_info->height;
1772  if (window_info->y < 0)
1773  window_info->y=0;
1774  else
1775  if (window_info->y > limit)
1776  window_info->y=limit;
1777 }
1778 
1779 /*
1780 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1781 % %
1782 % %
1783 % %
1784 % X D e l a y %
1785 % %
1786 % %
1787 % %
1788 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1789 %
1790 % XDelay() suspends program execution for the number of milliseconds
1791 % specified.
1792 %
1793 % The format of the Delay method is:
1794 %
1795 % void XDelay(Display *display,const size_t milliseconds)
1796 %
1797 % A description of each parameter follows:
1798 %
1799 % o display: Specifies a pointer to the Display structure; returned from
1800 % XOpenDisplay.
1801 %
1802 % o milliseconds: Specifies the number of milliseconds to delay before
1803 % returning.
1804 %
1805 */
1806 MagickPrivate void XDelay(Display *display,const size_t milliseconds)
1807 {
1808  assert(display != (Display *) NULL);
1809  (void) XFlush(display);
1810  MagickDelay(milliseconds);
1811 }
1812 
1813 /*
1814 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1815 % %
1816 % %
1817 % %
1818 % X D e s t r o y R e s o u r c e I n f o %
1819 % %
1820 % %
1821 % %
1822 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1823 %
1824 % XDestroyResourceInfo() frees memory associated with the XResourceInfo
1825 % structure.
1826 %
1827 % The format of the XDestroyResourceInfo method is:
1828 %
1829 % void XDestroyResourceInfo(XResourceInfo *resource_info)
1830 %
1831 % A description of each parameter follows:
1832 %
1833 % o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
1834 %
1835 */
1836 MagickExport void XDestroyResourceInfo(XResourceInfo *resource_info)
1837 {
1838  if (resource_info->image_geometry != (char *) NULL)
1839  resource_info->image_geometry=(char *)
1840  RelinquishMagickMemory(resource_info->image_geometry);
1841  if (resource_info->quantize_info != (QuantizeInfo *) NULL)
1842  resource_info->quantize_info=DestroyQuantizeInfo(
1843  resource_info->quantize_info);
1844  if (resource_info->client_name != (char *) NULL)
1845  resource_info->client_name=(char *)
1846  RelinquishMagickMemory(resource_info->client_name);
1847  if (resource_info->name != (char *) NULL)
1848  resource_info->name=DestroyString(resource_info->name);
1849  (void) memset(resource_info,0,sizeof(*resource_info));
1850  (void) XSetWindows((XWindows *) NULL);
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+=(ssize_t) (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  char
2145  *q;
2146 
2147  const Quantum
2148  *p;
2149 
2150  int
2151  i,
2152  j,
2153  value,
2154  x,
2155  y;
2156 
2157  PixelInfo
2158  color;
2159 
2160  size_t
2161  pixel;
2162 
2163  unsigned char
2164  *blue_map[2][16],
2165  *green_map[2][16],
2166  *red_map[2][16];
2167 
2168  unsigned int
2169  scanline_pad;
2170 
2171  /*
2172  Allocate and initialize dither maps.
2173  */
2174  for (i=0; i < 2; i++)
2175  for (j=0; j < 16; j++)
2176  {
2177  red_map[i][j]=(unsigned char *) AcquireCriticalMemory(256UL*
2178  sizeof(*red_map));
2179  green_map[i][j]=(unsigned char *) AcquireCriticalMemory(256UL*
2180  sizeof(*green_map));
2181  blue_map[i][j]=(unsigned char *) AcquireCriticalMemory(256UL*
2182  sizeof(*blue_map));
2183  }
2184  /*
2185  Initialize dither tables.
2186  */
2187  for (i=0; i < 2; i++)
2188  for (j=0; j < 16; j++)
2189  for (x=0; x < 256; x++)
2190  {
2191  value=x-16;
2192  if (x < 48)
2193  value=x/2+8;
2194  value+=dither_red[i][j];
2195  red_map[i][j][x]=(unsigned char)
2196  ((value < 0) ? 0 : (value > 255) ? 255 : value);
2197  value=x-16;
2198  if (x < 48)
2199  value=x/2+8;
2200  value+=dither_green[i][j];
2201  green_map[i][j][x]=(unsigned char)
2202  ((value < 0) ? 0 : (value > 255) ? 255 : value);
2203  value=x-32;
2204  if (x < 112)
2205  value=x/2+24;
2206  value+=(int) (dither_blue[i][j] << 1);
2207  blue_map[i][j][x]=(unsigned char)
2208  ((value < 0) ? 0 : (value > 255) ? 255 : value);
2209  }
2210  /*
2211  Dither image.
2212  */
2213  scanline_pad=(unsigned int) (ximage->bytes_per_line-(int)
2214  ((ximage->width*ximage->bits_per_pixel) >> 3));
2215  i=0;
2216  j=0;
2217  q=ximage->data;
2218  image_view=AcquireVirtualCacheView(image,exception);
2219  for (y=0; y < (int) image->rows; y++)
2220  {
2221  p=GetCacheViewVirtualPixels(image_view,0,(ssize_t) y,image->columns,1,
2222  exception);
2223  if (p == (const Quantum *) NULL)
2224  break;
2225  for (x=0; x < (int) image->columns; x++)
2226  {
2227  color.red=(double) ClampToQuantum((double) (red_map[i][j][
2228  (int) ScaleQuantumToChar(GetPixelRed(image,p))] << 8));
2229  color.green=(double) ClampToQuantum((double) (green_map[i][j][
2230  (int) ScaleQuantumToChar(GetPixelGreen(image,p))] << 8));
2231  color.blue=(double) ClampToQuantum((double) (blue_map[i][j][
2232  (int) ScaleQuantumToChar(GetPixelBlue(image,p))] << 8));
2233  pixel=(size_t) (((size_t) color.red & 0xe0) |
2234  (((size_t) color.green & 0xe0) >> 3) |
2235  (((size_t) color.blue & 0xc0) >> 6));
2236  *q++=(char) pixel;
2237  p+=(ptrdiff_t) GetPixelChannels(image);
2238  j++;
2239  if (j == 16)
2240  j=0;
2241  }
2242  q+=(ptrdiff_t) scanline_pad;
2243  i++;
2244  if (i == 2)
2245  i=0;
2246  }
2247  image_view=DestroyCacheView(image_view);
2248  /*
2249  Free allocated memory.
2250  */
2251  for (i=0; i < 2; i++)
2252  for (j=0; j < 16; j++)
2253  {
2254  green_map[i][j]=(unsigned char *) RelinquishMagickMemory(green_map[i][j]);
2255  blue_map[i][j]=(unsigned char *) RelinquishMagickMemory(blue_map[i][j]);
2256  red_map[i][j]=(unsigned char *) RelinquishMagickMemory(red_map[i][j]);
2257  }
2258 }
2259 
2260 /*
2261 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2262 % %
2263 % %
2264 % %
2265 % X D r a w I m a g e %
2266 % %
2267 % %
2268 % %
2269 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2270 %
2271 % XDrawImage() draws a line on the image.
2272 %
2273 % The format of the XDrawImage method is:
2274 %
2275 % MagickBooleanType XDrawImage(Display *display,const XPixelInfo *pixel,
2276 % XDrawInfo *draw_info,Image *image,ExceptionInfo *exception)
2277 %
2278 % A description of each parameter follows:
2279 %
2280 % o display: Specifies a connection to an X server; returned from
2281 % XOpenDisplay.
2282 %
2283 % o pixel: Specifies a pointer to a XPixelInfo structure.
2284 %
2285 % o draw_info: Specifies a pointer to a XDrawInfo structure.
2286 %
2287 % o image: the image.
2288 %
2289 % o exception: return any errors or warnings in this structure.
2290 %
2291 */
2292 MagickPrivate MagickBooleanType XDrawImage(Display *display,
2293  const XPixelInfo *pixel,XDrawInfo *draw_info,Image *image,
2294  ExceptionInfo *exception)
2295 {
2296  CacheView
2297  *draw_view;
2298 
2299  GC
2300  draw_context;
2301 
2302  Image
2303  *draw_image;
2304 
2305  int
2306  x,
2307  y;
2308 
2309  PixelTrait
2310  alpha_trait;
2311 
2312  Pixmap
2313  draw_pixmap;
2314 
2315  unsigned int
2316  depth,
2317  height,
2318  width;
2319 
2320  Window
2321  root_window;
2322 
2323  XGCValues
2324  context_values;
2325 
2326  XImage
2327  *draw_ximage;
2328 
2329  /*
2330  Initialize drawd image.
2331  */
2332  assert(display != (Display *) NULL);
2333  assert(pixel != (XPixelInfo *) NULL);
2334  assert(draw_info != (XDrawInfo *) NULL);
2335  assert(image != (Image *) NULL);
2336  if (IsEventLogging() != MagickFalse)
2337  (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
2338  /*
2339  Initialize drawd pixmap.
2340  */
2341  root_window=XRootWindow(display,XDefaultScreen(display));
2342  depth=(unsigned int) XDefaultDepth(display,XDefaultScreen(display));
2343  draw_pixmap=XCreatePixmap(display,root_window,draw_info->width,
2344  draw_info->height,depth);
2345  if (draw_pixmap == (Pixmap) NULL)
2346  return(MagickFalse);
2347  /*
2348  Initialize graphics info.
2349  */
2350  context_values.background=(size_t) (~0);
2351  context_values.foreground=0;
2352  context_values.line_width=(int) draw_info->line_width;
2353  draw_context=XCreateGC(display,root_window,(size_t)
2354  (GCBackground | GCForeground | GCLineWidth),&context_values);
2355  if (draw_context == (GC) NULL)
2356  return(MagickFalse);
2357  /*
2358  Clear pixmap.
2359  */
2360  (void) XFillRectangle(display,draw_pixmap,draw_context,0,0,draw_info->width,
2361  draw_info->height);
2362  /*
2363  Draw line to pixmap.
2364  */
2365  (void) XSetBackground(display,draw_context,0);
2366  (void) XSetForeground(display,draw_context,(size_t) (~0));
2367  if (draw_info->stipple != (Pixmap) NULL)
2368  {
2369  (void) XSetFillStyle(display,draw_context,FillOpaqueStippled);
2370  (void) XSetStipple(display,draw_context,draw_info->stipple);
2371  }
2372  switch (draw_info->element)
2373  {
2374  case PointElement:
2375  default:
2376  {
2377  (void) XDrawLines(display,draw_pixmap,draw_context,
2378  draw_info->coordinate_info,(int) draw_info->number_coordinates,
2379  CoordModeOrigin);
2380  break;
2381  }
2382  case LineElement:
2383  {
2384  (void) XDrawLine(display,draw_pixmap,draw_context,draw_info->line_info.x1,
2385  draw_info->line_info.y1,draw_info->line_info.x2,
2386  draw_info->line_info.y2);
2387  break;
2388  }
2389  case RectangleElement:
2390  {
2391  (void) XDrawRectangle(display,draw_pixmap,draw_context,
2392  (int) draw_info->rectangle_info.x,(int) draw_info->rectangle_info.y,
2393  (unsigned int) draw_info->rectangle_info.width,
2394  (unsigned int) draw_info->rectangle_info.height);
2395  break;
2396  }
2397  case FillRectangleElement:
2398  {
2399  (void) XFillRectangle(display,draw_pixmap,draw_context,
2400  (int) draw_info->rectangle_info.x,(int) draw_info->rectangle_info.y,
2401  (unsigned int) draw_info->rectangle_info.width,
2402  (unsigned int) draw_info->rectangle_info.height);
2403  break;
2404  }
2405  case CircleElement:
2406  case EllipseElement:
2407  {
2408  (void) XDrawArc(display,draw_pixmap,draw_context,
2409  (int) draw_info->rectangle_info.x,(int) draw_info->rectangle_info.y,
2410  (unsigned int) draw_info->rectangle_info.width,
2411  (unsigned int) draw_info->rectangle_info.height,0,360*64);
2412  break;
2413  }
2414  case FillCircleElement:
2415  case FillEllipseElement:
2416  {
2417  (void) XFillArc(display,draw_pixmap,draw_context,
2418  (int) draw_info->rectangle_info.x,(int) draw_info->rectangle_info.y,
2419  (unsigned int) draw_info->rectangle_info.width,
2420  (unsigned int) draw_info->rectangle_info.height,0,360*64);
2421  break;
2422  }
2423  case PolygonElement:
2424  {
2425  XPoint
2426  *coordinate_info;
2427 
2428  coordinate_info=draw_info->coordinate_info;
2429  (void) XDrawLines(display,draw_pixmap,draw_context,coordinate_info,
2430  (int) draw_info->number_coordinates,CoordModeOrigin);
2431  (void) XDrawLine(display,draw_pixmap,draw_context,
2432  coordinate_info[draw_info->number_coordinates-1].x,
2433  coordinate_info[draw_info->number_coordinates-1].y,
2434  coordinate_info[0].x,coordinate_info[0].y);
2435  break;
2436  }
2437  case FillPolygonElement:
2438  {
2439  (void) XFillPolygon(display,draw_pixmap,draw_context,
2440  draw_info->coordinate_info,(int) draw_info->number_coordinates,Complex,
2441  CoordModeOrigin);
2442  break;
2443  }
2444  }
2445  (void) XFreeGC(display,draw_context);
2446  /*
2447  Initialize X image.
2448  */
2449  draw_ximage=XGetImage(display,draw_pixmap,0,0,draw_info->width,
2450  draw_info->height,AllPlanes,ZPixmap);
2451  if (draw_ximage == (XImage *) NULL)
2452  return(MagickFalse);
2453  (void) XFreePixmap(display,draw_pixmap);
2454  /*
2455  Initialize draw image.
2456  */
2457  draw_image=AcquireImage((ImageInfo *) NULL,exception);
2458  if (draw_image == (Image *) NULL)
2459  return(MagickFalse);
2460  draw_image->columns=draw_info->width;
2461  draw_image->rows=draw_info->height;
2462  /*
2463  Transfer drawn X image to image.
2464  */
2465  width=(unsigned int) image->columns;
2466  height=(unsigned int) image->rows;
2467  x=0;
2468  y=0;
2469  (void) XParseGeometry(draw_info->geometry,&x,&y,&width,&height);
2470  (void) GetOneVirtualPixelInfo(image,UndefinedVirtualPixelMethod,(ssize_t) x,
2471  (ssize_t) y,&draw_image->background_color,exception);
2472  if (SetImageStorageClass(draw_image,DirectClass,exception) == MagickFalse)
2473  return(MagickFalse);
2474  draw_image->alpha_trait=BlendPixelTrait;
2475  draw_view=AcquireAuthenticCacheView(draw_image,exception);
2476  for (y=0; y < (int) draw_image->rows; y++)
2477  {
2478  int
2479  x;
2480 
2481  Quantum
2482  *magick_restrict q;
2483 
2484  q=QueueCacheViewAuthenticPixels(draw_view,0,(ssize_t) y,draw_image->columns,
2485  1,exception);
2486  if (q == (Quantum *) NULL)
2487  break;
2488  for (x=0; x < (int) draw_image->columns; x++)
2489  {
2490  if (XGetPixel(draw_ximage,x,y) == 0)
2491  {
2492  /*
2493  Set this pixel to the background color.
2494  */
2495  SetPixelViaPixelInfo(draw_image,&draw_image->background_color,q);
2496  SetPixelAlpha(draw_image,(Quantum) (draw_info->stencil ==
2497  OpaqueStencil ? TransparentAlpha : OpaqueAlpha),q);
2498  }
2499  else
2500  {
2501  /*
2502  Set this pixel to the pen color.
2503  */
2504  SetPixelRed(draw_image,ScaleShortToQuantum(
2505  pixel->pen_color.red),q);
2506  SetPixelGreen(draw_image,ScaleShortToQuantum(
2507  pixel->pen_color.green),q);
2508  SetPixelBlue(draw_image,ScaleShortToQuantum(
2509  pixel->pen_color.blue),q);
2510  SetPixelAlpha(draw_image,(Quantum) (draw_info->stencil ==
2511  OpaqueStencil ? OpaqueAlpha : TransparentAlpha),q);
2512  }
2513  q+=(ptrdiff_t) GetPixelChannels(draw_image);
2514  }
2515  if (SyncCacheViewAuthenticPixels(draw_view,exception) == MagickFalse)
2516  break;
2517  }
2518  draw_view=DestroyCacheView(draw_view);
2519  XDestroyImage(draw_ximage);
2520  /*
2521  Determine draw geometry.
2522  */
2523  (void) XParseGeometry(draw_info->geometry,&x,&y,&width,&height);
2524  if ((width != (unsigned int) draw_image->columns) ||
2525  (height != (unsigned int) draw_image->rows))
2526  {
2527  char
2528  image_geometry[MagickPathExtent];
2529 
2530  /*
2531  Scale image.
2532  */
2533  (void) FormatLocaleString(image_geometry,MagickPathExtent,"%ux%u",
2534  width,height);
2535  (void) TransformImage(&draw_image,(char *) NULL,image_geometry,
2536  exception);
2537  }
2538  if (draw_info->degrees != 0.0)
2539  {
2540  Image
2541  *rotate_image;
2542 
2543  int
2544  rotations;
2545 
2546  double
2547  normalized_degrees;
2548 
2549  /*
2550  Rotate image.
2551  */
2552  rotate_image=RotateImage(draw_image,draw_info->degrees,exception);
2553  if (rotate_image == (Image *) NULL)
2554  return(MagickFalse);
2555  draw_image=DestroyImage(draw_image);
2556  draw_image=rotate_image;
2557  /*
2558  Annotation is relative to the degree of rotation.
2559  */
2560  normalized_degrees=draw_info->degrees;
2561  while (normalized_degrees < -45.0)
2562  normalized_degrees+=360.0;
2563  for (rotations=0; normalized_degrees > 45.0; rotations++)
2564  normalized_degrees-=90.0;
2565  switch (rotations % 4)
2566  {
2567  default:
2568  case 0:
2569  break;
2570  case 1:
2571  {
2572  /*
2573  Rotate 90 degrees.
2574  */
2575  x=x-(int) draw_image->columns/2;
2576  y=y+(int) draw_image->columns/2;
2577  break;
2578  }
2579  case 2:
2580  {
2581  /*
2582  Rotate 180 degrees.
2583  */
2584  x=x-(int) draw_image->columns;
2585  break;
2586  }
2587  case 3:
2588  {
2589  /*
2590  Rotate 270 degrees.
2591  */
2592  x=x-(int) draw_image->columns/2;
2593  y=y-(int) (draw_image->rows-(draw_image->columns/2));
2594  break;
2595  }
2596  }
2597  }
2598  /*
2599  Composite text onto the image.
2600  */
2601  draw_view=AcquireAuthenticCacheView(draw_image,exception);
2602  for (y=0; y < (int) draw_image->rows; y++)
2603  {
2604  int
2605  x;
2606 
2607  Quantum
2608  *magick_restrict q;
2609 
2610  q=GetCacheViewAuthenticPixels(draw_view,0,(ssize_t) y,draw_image->columns,1,
2611  exception);
2612  if (q == (Quantum *) NULL)
2613  break;
2614  for (x=0; x < (int) draw_image->columns; x++)
2615  {
2616  if (GetPixelAlpha(image,q) != TransparentAlpha)
2617  SetPixelAlpha(draw_image,OpaqueAlpha,q);
2618  q+=(ptrdiff_t) GetPixelChannels(draw_image);
2619  }
2620  if (SyncCacheViewAuthenticPixels(draw_view,exception) == MagickFalse)
2621  break;
2622  }
2623  draw_view=DestroyCacheView(draw_view);
2624  (void) XParseGeometry(draw_info->geometry,&x,&y,&width,&height);
2625  if (draw_info->stencil == TransparentStencil)
2626  (void) CompositeImage(image,draw_image,CopyAlphaCompositeOp,MagickTrue,
2627  (ssize_t) x,(ssize_t) y,exception);
2628  else
2629  {
2630  alpha_trait=image->alpha_trait;
2631  (void) CompositeImage(image,draw_image,OverCompositeOp,MagickTrue,
2632  (ssize_t) x,(ssize_t) y,exception);
2633  image->alpha_trait=alpha_trait;
2634  }
2635  draw_image=DestroyImage(draw_image);
2636  return(MagickTrue);
2637 }
2638 
2639 /*
2640 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2641 % %
2642 % %
2643 % %
2644 % X E r r o r %
2645 % %
2646 % %
2647 % %
2648 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2649 %
2650 % XError() ignores BadWindow errors for XQueryTree and XGetWindowAttributes,
2651 % and ignores BadDrawable errors for XGetGeometry, and ignores BadValue errors
2652 % for XQueryColor. It returns MagickFalse in those cases. Otherwise it
2653 % returns True.
2654 %
2655 % The format of the XError function is:
2656 %
2657 % int XError(display,error)
2658 %
2659 % A description of each parameter follows:
2660 %
2661 % o display: Specifies a pointer to the Display structure; returned from
2662 % XOpenDisplay.
2663 %
2664 % o error: Specifies the error event.
2665 %
2666 */
2667 
2668 #if defined(__cplusplus) || defined(c_plusplus)
2669 extern "C" {
2670 #endif
2671 
2672 MagickExport int XError(Display *display,XErrorEvent *error)
2673 {
2674  assert(display != (Display *) NULL);
2675  assert(error != (XErrorEvent *) NULL);
2676  if (IsEventLogging() != MagickFalse)
2677  (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
2678  xerror_alert=MagickTrue;
2679  switch (error->request_code)
2680  {
2681  case X_GetGeometry:
2682  {
2683  if ((int) error->error_code == BadDrawable)
2684  return(MagickFalse);
2685  break;
2686  }
2687  case X_GetWindowAttributes:
2688  case X_QueryTree:
2689  {
2690  if ((int) error->error_code == BadWindow)
2691  return(MagickFalse);
2692  break;
2693  }
2694  case X_QueryColors:
2695  {
2696  if ((int) error->error_code == BadValue)
2697  return(MagickFalse);
2698  break;
2699  }
2700  }
2701  return(MagickTrue);
2702 }
2703 
2704 #if defined(__cplusplus) || defined(c_plusplus)
2705 }
2706 #endif
2707 
2708 /*
2709 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2710 % %
2711 % %
2712 % %
2713 % X F r e e R e s o u r c e s %
2714 % %
2715 % %
2716 % %
2717 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2718 %
2719 % XFreeResources() frees X11 resources.
2720 %
2721 % The format of the XFreeResources method is:
2722 %
2723 % void XFreeResources(Display *display,XVisualInfo *visual_info,
2724 % XStandardColormap *map_info,XPixelInfo *pixel,XFontStruct *font_info,
2725 % XResourceInfo *resource_info,XWindowInfo *window_info)
2726 % resource_info,window_info)
2727 %
2728 % A description of each parameter follows:
2729 %
2730 % o display: Specifies a connection to an X server; returned from
2731 % XOpenDisplay.
2732 %
2733 % o visual_info: Specifies a pointer to a X11 XVisualInfo structure;
2734 % returned from XGetVisualInfo.
2735 %
2736 % o map_info: If map_type is specified, this structure is initialized
2737 % with info from the Standard Colormap.
2738 %
2739 % o pixel: Specifies a pointer to a XPixelInfo structure.
2740 %
2741 % o font_info: Specifies a pointer to a XFontStruct structure.
2742 %
2743 % o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
2744 %
2745 % o window_info: Specifies a pointer to a X11 XWindowInfo structure.
2746 %
2747 */
2748 MagickPrivate void XFreeResources(Display *display,XVisualInfo *visual_info,
2749  XStandardColormap *map_info,XPixelInfo *pixel,XFontStruct *font_info,
2750  XResourceInfo *resource_info,XWindowInfo *window_info)
2751 {
2752  assert(display != (Display *) NULL);
2753  assert(resource_info != (XResourceInfo *) NULL);
2754  if (IsEventLogging() != MagickFalse)
2755  (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
2756  if (window_info != (XWindowInfo *) NULL)
2757  {
2758  /*
2759  Free X image.
2760  */
2761  if (window_info->ximage != (XImage *) NULL)
2762  XDestroyImage(window_info->ximage);
2763  if (window_info->id != (Window) NULL)
2764  {
2765  /*
2766  Free destroy window and free cursors.
2767  */
2768  if (window_info->id != XRootWindow(display,visual_info->screen))
2769  (void) XDestroyWindow(display,window_info->id);
2770  if (window_info->annotate_context != (GC) NULL)
2771  (void) XFreeGC(display,window_info->annotate_context);
2772  if (window_info->highlight_context != (GC) NULL)
2773  (void) XFreeGC(display,window_info->highlight_context);
2774  if (window_info->widget_context != (GC) NULL)
2775  (void) XFreeGC(display,window_info->widget_context);
2776  if (window_info->cursor != (Cursor) NULL)
2777  (void) XFreeCursor(display,window_info->cursor);
2778  window_info->cursor=(Cursor) NULL;
2779  if (window_info->busy_cursor != (Cursor) NULL)
2780  (void) XFreeCursor(display,window_info->busy_cursor);
2781  window_info->busy_cursor=(Cursor) NULL;
2782  }
2783  }
2784  /*
2785  Free font.
2786  */
2787  if (font_info != (XFontStruct *) NULL)
2788  {
2789  (void) XFreeFont(display,font_info);
2790  font_info=(XFontStruct *) NULL;
2791  }
2792  if (map_info != (XStandardColormap *) NULL)
2793  {
2794  /*
2795  Free X Standard Colormap.
2796  */
2797  if (resource_info->map_type == (char *) NULL)
2798  (void) XFreeStandardColormap(display,visual_info,map_info,pixel);
2799  (void) XFree((void *) map_info);
2800  }
2801  /*
2802  Free X visual info.
2803  */
2804  if (visual_info != (XVisualInfo *) NULL)
2805  (void) XFree((void *) visual_info);
2806  if (resource_info->close_server != MagickFalse)
2807  (void) XCloseDisplay(display);
2808 }
2809 
2810 /*
2811 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2812 % %
2813 % %
2814 % %
2815 % X F r e e S t a n d a r d C o l o r m a p %
2816 % %
2817 % %
2818 % %
2819 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2820 %
2821 % XFreeStandardColormap() frees an X11 colormap.
2822 %
2823 % The format of the XFreeStandardColormap method is:
2824 %
2825 % void XFreeStandardColormap(Display *display,
2826 % const XVisualInfo *visual_info,XStandardColormap *map_info,
2827 % XPixelInfo *pixel)
2828 %
2829 % A description of each parameter follows:
2830 %
2831 % o display: Specifies a connection to an X server; returned from
2832 % XOpenDisplay.
2833 %
2834 % o visual_info: Specifies a pointer to a X11 XVisualInfo structure;
2835 % returned from XGetVisualInfo.
2836 %
2837 % o map_info: If map_type is specified, this structure is initialized
2838 % with info from the Standard Colormap.
2839 %
2840 % o pixel: Specifies a pointer to a XPixelInfo structure.
2841 %
2842 */
2843 MagickPrivate void XFreeStandardColormap(Display *display,
2844  const XVisualInfo *visual_info,XStandardColormap *map_info,XPixelInfo *pixel)
2845 {
2846  /*
2847  Free colormap.
2848  */
2849  assert(display != (Display *) NULL);
2850  assert(visual_info != (XVisualInfo *) NULL);
2851  assert(map_info != (XStandardColormap *) NULL);
2852  if (IsEventLogging() != MagickFalse)
2853  (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
2854  (void) XFlush(display);
2855  if (map_info->colormap != (Colormap) NULL)
2856  {
2857  if (map_info->colormap != XDefaultColormap(display,visual_info->screen))
2858  (void) XFreeColormap(display,map_info->colormap);
2859  else
2860  if (pixel != (XPixelInfo *) NULL)
2861  if ((visual_info->klass != TrueColor) &&
2862  (visual_info->klass != DirectColor))
2863  (void) XFreeColors(display,map_info->colormap,pixel->pixels,
2864  (int) pixel->colors,0);
2865  }
2866  map_info->colormap=(Colormap) NULL;
2867  if (pixel != (XPixelInfo *) NULL)
2868  {
2869  if (pixel->pixels != (unsigned long *) NULL)
2870  pixel->pixels=(unsigned long *) RelinquishMagickMemory(pixel->pixels);
2871  pixel->pixels=(unsigned long *) NULL;
2872  }
2873 }
2874 
2875 /*
2876 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2877 % %
2878 % %
2879 % %
2880 % X G e t A n n o t a t e I n f o %
2881 % %
2882 % %
2883 % %
2884 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2885 %
2886 % XGetAnnotateInfo() initializes the AnnotateInfo structure.
2887 %
2888 % The format of the XGetAnnotateInfo method is:
2889 %
2890 % void XGetAnnotateInfo(XAnnotateInfo *annotate_info)
2891 %
2892 % A description of each parameter follows:
2893 %
2894 % o annotate_info: Specifies a pointer to a XAnnotateInfo structure.
2895 %
2896 */
2897 MagickPrivate void XGetAnnotateInfo(XAnnotateInfo *annotate_info)
2898 {
2899  /*
2900  Initialize annotate structure.
2901  */
2902  assert(annotate_info != (XAnnotateInfo *) NULL);
2903  if (IsEventLogging() != MagickFalse)
2904  (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
2905  annotate_info->x=0;
2906  annotate_info->y=0;
2907  annotate_info->width=0;
2908  annotate_info->height=0;
2909  annotate_info->stencil=ForegroundStencil;
2910  annotate_info->degrees=0.0;
2911  annotate_info->font_info=(XFontStruct *) NULL;
2912  annotate_info->text=(char *) NULL;
2913  *annotate_info->geometry='\0';
2914  annotate_info->previous=(XAnnotateInfo *) NULL;
2915  annotate_info->next=(XAnnotateInfo *) NULL;
2916  (void) XSupportsLocale();
2917  (void) XSetLocaleModifiers("");
2918 }
2919 
2920 /*
2921 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2922 % %
2923 % %
2924 % %
2925 % X G e t M a p I n f o %
2926 % %
2927 % %
2928 % %
2929 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2930 %
2931 % XGetMapInfo() initializes the XStandardColormap structure.
2932 %
2933 % The format of the XStandardColormap method is:
2934 %
2935 % void XGetMapInfo(const XVisualInfo *visual_info,const Colormap colormap,
2936 % XStandardColormap *map_info)
2937 %
2938 % A description of each parameter follows:
2939 %
2940 % o colormap: Specifies the ID of the X server colormap.
2941 %
2942 % o visual_info: Specifies a pointer to a X11 XVisualInfo structure;
2943 % returned from XGetVisualInfo.
2944 %
2945 % o map_info: Specifies a pointer to a X11 XStandardColormap structure.
2946 %
2947 */
2948 MagickPrivate void XGetMapInfo(const XVisualInfo *visual_info,
2949  const Colormap colormap,XStandardColormap *map_info)
2950 {
2951  /*
2952  Initialize map info.
2953  */
2954  assert(visual_info != (XVisualInfo *) NULL);
2955  assert(map_info != (XStandardColormap *) NULL);
2956  if (IsEventLogging() != MagickFalse)
2957  (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
2958  map_info->colormap=colormap;
2959  map_info->red_max=visual_info->red_mask;
2960  map_info->red_mult=(size_t) (map_info->red_max != 0 ? 1 : 0);
2961  if (map_info->red_max != 0)
2962  while ((map_info->red_max & 0x01) == 0)
2963  {
2964  map_info->red_max>>=1;
2965  map_info->red_mult<<=1;
2966  }
2967  map_info->green_max=visual_info->green_mask;
2968  map_info->green_mult=(size_t) (map_info->green_max != 0 ? 1 : 0);
2969  if (map_info->green_max != 0)
2970  while ((map_info->green_max & 0x01) == 0)
2971  {
2972  map_info->green_max>>=1;
2973  map_info->green_mult<<=1;
2974  }
2975  map_info->blue_max=visual_info->blue_mask;
2976  map_info->blue_mult=(size_t) (map_info->blue_max != 0 ? 1 : 0);
2977  if (map_info->blue_max != 0)
2978  while ((map_info->blue_max & 0x01) == 0)
2979  {
2980  map_info->blue_max>>=1;
2981  map_info->blue_mult<<=1;
2982  }
2983  map_info->base_pixel=0;
2984 }
2985 
2986 /*
2987 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2988 % %
2989 % %
2990 % %
2991 % X G e t P i x e l I n f o %
2992 % %
2993 % %
2994 % %
2995 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2996 %
2997 % XGetPixelInfo() initializes the PixelInfo structure.
2998 %
2999 % The format of the XGetPixelInfo method is:
3000 %
3001 % void XGetPixelInfo(Display *display,const XVisualInfo *visual_info,
3002 % const XStandardColormap *map_info,const XResourceInfo *resource_info,
3003 % Image *image,XPixelInfo *pixel)
3004 % pixel)
3005 %
3006 % A description of each parameter follows:
3007 %
3008 % o display: Specifies a connection to an X server; returned from
3009 % XOpenDisplay.
3010 %
3011 % o visual_info: Specifies a pointer to a X11 XVisualInfo structure;
3012 % returned from XGetVisualInfo.
3013 %
3014 % o map_info: If map_type is specified, this structure is initialized
3015 % with info from the Standard Colormap.
3016 %
3017 % o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
3018 %
3019 % o image: the image.
3020 %
3021 % o pixel: Specifies a pointer to a XPixelInfo structure.
3022 %
3023 */
3024 MagickPrivate void XGetPixelInfo(Display *display,
3025  const XVisualInfo *visual_info,const XStandardColormap *map_info,
3026  const XResourceInfo *resource_info,Image *image,XPixelInfo *pixel)
3027 {
3028  static const char
3029  *PenColors[MaxNumberPens]=
3030  {
3031  "#000000000000", /* black */
3032  "#00000000ffff", /* blue */
3033  "#0000ffffffff", /* cyan */
3034  "#0000ffff0000", /* green */
3035  "#bdbdbdbdbdbd", /* gray */
3036  "#ffff00000000", /* red */
3037  "#ffff0000ffff", /* magenta */
3038  "#ffffffff0000", /* yellow */
3039  "#ffffffffffff", /* white */
3040  "#bdbdbdbdbdbd", /* gray */
3041  "#bdbdbdbdbdbd" /* gray */
3042  };
3043 
3044  Colormap
3045  colormap;
3046 
3047  ssize_t
3048  i;
3049 
3050  Status
3051  status;
3052 
3053  unsigned int
3054  packets;
3055 
3056  /*
3057  Initialize pixel info.
3058  */
3059  assert(display != (Display *) NULL);
3060  assert(visual_info != (XVisualInfo *) NULL);
3061  assert(map_info != (XStandardColormap *) NULL);
3062  assert(resource_info != (XResourceInfo *) NULL);
3063  assert(pixel != (XPixelInfo *) NULL);
3064  if (IsEventLogging() != MagickFalse)
3065  (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
3066  pixel->colors=0;
3067  if (image != (Image *) NULL)
3068  if (image->storage_class == PseudoClass)
3069  pixel->colors=(ssize_t) image->colors;
3070  packets=(unsigned int)
3071  MagickMax((int) pixel->colors,visual_info->colormap_size)+MaxNumberPens;
3072  if (pixel->pixels != (unsigned long *) NULL)
3073  pixel->pixels=(unsigned long *) RelinquishMagickMemory(pixel->pixels);
3074  pixel->pixels=(unsigned long *) AcquireQuantumMemory(packets,
3075  sizeof(*pixel->pixels));
3076  if (pixel->pixels == (unsigned long *) NULL)
3077  ThrowXWindowFatalException(ResourceLimitFatalError,"UnableToGetPixelInfo",
3078  image->filename);
3079  /*
3080  Set foreground color.
3081  */
3082  colormap=map_info->colormap;
3083  (void) XParseColor(display,colormap,(char *) ForegroundColor,
3084  &pixel->foreground_color);
3085  status=XParseColor(display,colormap,resource_info->foreground_color,
3086  &pixel->foreground_color);
3087  if (status == False)
3088  ThrowXWindowException(XServerError,"ColorIsNotKnownToServer",
3089  resource_info->foreground_color);
3090  pixel->foreground_color.pixel=
3091  XStandardPixel(map_info,&pixel->foreground_color);
3092  pixel->foreground_color.flags=(char) (DoRed | DoGreen | DoBlue);
3093  /*
3094  Set background color.
3095  */
3096  (void) XParseColor(display,colormap,"#d6d6d6d6d6d6",&pixel->background_color);
3097  status=XParseColor(display,colormap,resource_info->background_color,
3098  &pixel->background_color);
3099  if (status == False)
3100  ThrowXWindowException(XServerError,"ColorIsNotKnownToServer",
3101  resource_info->background_color);
3102  pixel->background_color.pixel=
3103  XStandardPixel(map_info,&pixel->background_color);
3104  pixel->background_color.flags=(char) (DoRed | DoGreen | DoBlue);
3105  /*
3106  Set border color.
3107  */
3108  (void) XParseColor(display,colormap,(char *) BorderColor,
3109  &pixel->border_color);
3110  status=XParseColor(display,colormap,resource_info->border_color,
3111  &pixel->border_color);
3112  if (status == False)
3113  ThrowXWindowException(XServerError,"ColorIsNotKnownToServer",
3114  resource_info->border_color);
3115  pixel->border_color.pixel=XStandardPixel(map_info,&pixel->border_color);
3116  pixel->border_color.flags=(char) (DoRed | DoGreen | DoBlue);
3117  /*
3118  Set matte color.
3119  */
3120  pixel->matte_color=pixel->background_color;
3121  if (resource_info->matte_color != (char *) NULL)
3122  {
3123  /*
3124  Matte color is specified as a X resource or command line argument.
3125  */
3126  status=XParseColor(display,colormap,resource_info->matte_color,
3127  &pixel->matte_color);
3128  if (status == False)
3129  ThrowXWindowException(XServerError,"ColorIsNotKnownToServer",
3130  resource_info->matte_color);
3131  pixel->matte_color.pixel=XStandardPixel(map_info,&pixel->matte_color);
3132  pixel->matte_color.flags=(char) (DoRed | DoGreen | DoBlue);
3133  }
3134  /*
3135  Set highlight color.
3136  */
3137  pixel->highlight_color.red=(unsigned short) (((double)
3138  pixel->matte_color.red*ScaleQuantumToShort(HighlightModulate))/65535L+
3139  (ScaleQuantumToShort((Quantum) (QuantumRange-HighlightModulate))));
3140  pixel->highlight_color.green=(unsigned short) (((double)
3141  pixel->matte_color.green*ScaleQuantumToShort(HighlightModulate))/65535L+
3142  (ScaleQuantumToShort((Quantum) (QuantumRange-HighlightModulate))));
3143  pixel->highlight_color.blue=(unsigned short) (((double)
3144  pixel->matte_color.blue*ScaleQuantumToShort(HighlightModulate))/65535L+
3145  (ScaleQuantumToShort((Quantum) (QuantumRange-HighlightModulate))));
3146  pixel->highlight_color.pixel=XStandardPixel(map_info,&pixel->highlight_color);
3147  pixel->highlight_color.flags=(char) (DoRed | DoGreen | DoBlue);
3148  /*
3149  Set shadow color.
3150  */
3151  pixel->shadow_color.red=(unsigned short) (((double)
3152  pixel->matte_color.red*ScaleQuantumToShort(ShadowModulate))/65535L);
3153  pixel->shadow_color.green=(unsigned short) (((double)
3154  pixel->matte_color.green*ScaleQuantumToShort(ShadowModulate))/65535L);
3155  pixel->shadow_color.blue=(unsigned short) (((double)
3156  pixel->matte_color.blue*ScaleQuantumToShort(ShadowModulate))/65535L);
3157  pixel->shadow_color.pixel=XStandardPixel(map_info,&pixel->shadow_color);
3158  pixel->shadow_color.flags=(char) (DoRed | DoGreen | DoBlue);
3159  /*
3160  Set depth color.
3161  */
3162  pixel->depth_color.red=(unsigned short) (((double)
3163  pixel->matte_color.red*ScaleQuantumToShort(DepthModulate))/65535L);
3164  pixel->depth_color.green=(unsigned short) (((double)
3165  pixel->matte_color.green*ScaleQuantumToShort(DepthModulate))/65535L);
3166  pixel->depth_color.blue=(unsigned short) (((double)
3167  pixel->matte_color.blue*ScaleQuantumToShort(DepthModulate))/65535L);
3168  pixel->depth_color.pixel=XStandardPixel(map_info,&pixel->depth_color);
3169  pixel->depth_color.flags=(char) (DoRed | DoGreen | DoBlue);
3170  /*
3171  Set trough color.
3172  */
3173  pixel->trough_color.red=(unsigned short) (((double)
3174  pixel->matte_color.red*ScaleQuantumToShort(TroughModulate))/65535L);
3175  pixel->trough_color.green=(unsigned short) (((double)
3176  pixel->matte_color.green*ScaleQuantumToShort(TroughModulate))/65535L);
3177  pixel->trough_color.blue=(unsigned short) (((double)
3178  pixel->matte_color.blue*ScaleQuantumToShort(TroughModulate))/65535L);
3179  pixel->trough_color.pixel=XStandardPixel(map_info,&pixel->trough_color);
3180  pixel->trough_color.flags=(char) (DoRed | DoGreen | DoBlue);
3181  /*
3182  Set pen color.
3183  */
3184  for (i=0; i < MaxNumberPens; i++)
3185  {
3186  (void) XParseColor(display,colormap,(char *) PenColors[i],
3187  &pixel->pen_colors[i]);
3188  status=XParseColor(display,colormap,resource_info->pen_colors[i],
3189  &pixel->pen_colors[i]);
3190  if (status == False)
3191  ThrowXWindowException(XServerError,"ColorIsNotKnownToServer",
3192  resource_info->pen_colors[i]);
3193  pixel->pen_colors[i].pixel=XStandardPixel(map_info,&pixel->pen_colors[i]);
3194  pixel->pen_colors[i].flags=(char) (DoRed | DoGreen | DoBlue);
3195  }
3196  pixel->box_color=pixel->background_color;
3197  pixel->pen_color=pixel->foreground_color;
3198  pixel->box_index=0;
3199  pixel->pen_index=1;
3200  if (image != (Image *) NULL)
3201  {
3202  if ((resource_info->gamma_correct != MagickFalse) &&
3203  (image->gamma != 0.0))
3204  {
3205  GeometryInfo
3206  geometry_info;
3207 
3208  MagickStatusType
3209  flags;
3210 
3211  /*
3212  Initialize map relative to display and image gamma.
3213  */
3214  flags=ParseGeometry(resource_info->display_gamma,&geometry_info);
3215  if ((flags & RhoValue) != 0)
3216  red_gamma=geometry_info.rho;
3217  green_gamma=red_gamma;
3218  if ((flags & SigmaValue) != 0)
3219  green_gamma=geometry_info.sigma;
3220  blue_gamma=red_gamma;
3221  if ((flags & XiValue) != 0)
3222  blue_gamma=geometry_info.xi;
3223  red_gamma*=image->gamma;
3224  green_gamma*=image->gamma;
3225  blue_gamma*=image->gamma;
3226  }
3227  if (image->storage_class == PseudoClass)
3228  {
3229  /*
3230  Initialize pixel array for images of type PseudoClass.
3231  */
3232  for (i=0; i < (ssize_t) image->colors; i++)
3233  pixel->pixels[i]=XGammaPacket(map_info,image->colormap+i);
3234  for (i=0; i < MaxNumberPens; i++)
3235  pixel->pixels[image->colors+(size_t) i]=pixel->pen_colors[i].pixel;
3236  pixel->colors+=MaxNumberPens;
3237  }
3238  }
3239 }
3240 
3241 /*
3242 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3243 % %
3244 % %
3245 % %
3246 % X G e t R e s o u r c e C l a s s %
3247 % %
3248 % %
3249 % %
3250 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3251 %
3252 % XGetResourceClass() queries the X server for the specified resource name or
3253 % class. If the resource name or class is not defined in the database, the
3254 % supplied default value is returned.
3255 %
3256 % The format of the XGetResourceClass method is:
3257 %
3258 % char *XGetResourceClass(XrmDatabase database,const char *client_name,
3259 % const char *keyword,char *resource_default)
3260 %
3261 % A description of each parameter follows:
3262 %
3263 % o database: Specifies a resource database; returned from
3264 % XrmGetStringDatabase.
3265 %
3266 % o client_name: Specifies the application name used to retrieve resource
3267 % info from the X server database.
3268 %
3269 % o keyword: Specifies the keyword of the value being retrieved.
3270 %
3271 % o resource_default: Specifies the default value to return if the query
3272 % fails to find the specified keyword/class.
3273 %
3274 */
3275 MagickExport char *XGetResourceClass(XrmDatabase database,
3276  const char *client_name,const char *keyword,char *resource_default)
3277 {
3278  char
3279  resource_class[MagickPathExtent],
3280  resource_name[MagickPathExtent];
3281 
3282  static char
3283  *resource_type;
3284 
3285  Status
3286  status;
3287 
3288  XrmValue
3289  resource_value;
3290 
3291  if (database == (XrmDatabase) NULL)
3292  return(resource_default);
3293  *resource_name='\0';
3294  *resource_class='\0';
3295  if (keyword != (char *) NULL)
3296  {
3297  int
3298  c,
3299  k;
3300 
3301  /*
3302  Initialize resource keyword and class.
3303  */
3304  (void) FormatLocaleString(resource_name,MagickPathExtent,"%s.%s",
3305  client_name,keyword);
3306  c=(int) (*client_name);
3307  if ((c >= XK_a) && (c <= XK_z))
3308  c-=(XK_a-XK_A);
3309  else
3310  if ((c >= XK_agrave) && (c <= XK_odiaeresis))
3311  c-=(XK_agrave-XK_Agrave);
3312  else
3313  if ((c >= XK_oslash) && (c <= XK_thorn))
3314  c-=(XK_oslash-XK_Ooblique);
3315  k=(int) (*keyword);
3316  if ((k >= XK_a) && (k <= XK_z))
3317  k-=(XK_a-XK_A);
3318  else
3319  if ((k >= XK_agrave) && (k <= XK_odiaeresis))
3320  k-=(XK_agrave-XK_Agrave);
3321  else
3322  if ((k >= XK_oslash) && (k <= XK_thorn))
3323  k-=(XK_oslash-XK_Ooblique);
3324  (void) FormatLocaleString(resource_class,MagickPathExtent,"%c%s.%c%s",c,
3325  client_name+1,k,keyword+1);
3326  }
3327  status=XrmGetResource(database,resource_name,resource_class,&resource_type,
3328  &resource_value);
3329  if (status == False)
3330  return(resource_default);
3331  return(resource_value.addr);
3332 }
3333 
3334 /*
3335 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3336 % %
3337 % %
3338 % %
3339 % X G e t R e s o u r c e D a t a b a s e %
3340 % %
3341 % %
3342 % %
3343 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3344 %
3345 % XGetResourceDatabase() creates a new resource database and initializes it.
3346 %
3347 % The format of the XGetResourceDatabase method is:
3348 %
3349 % XrmDatabase XGetResourceDatabase(Display *display,
3350 % const char *client_name)
3351 %
3352 % A description of each parameter follows:
3353 %
3354 % o database: XGetResourceDatabase() returns the database after it is
3355 % initialized.
3356 %
3357 % o display: Specifies a connection to an X server; returned from
3358 % XOpenDisplay.
3359 %
3360 % o client_name: Specifies the application name used to retrieve resource
3361 % info from the X server database.
3362 %
3363 */
3364 MagickExport XrmDatabase XGetResourceDatabase(Display *display,
3365  const char *client_name)
3366 {
3367  char
3368  filename[MagickPathExtent];
3369 
3370  int
3371  c;
3372 
3373  const char
3374  *p;
3375 
3376  XrmDatabase
3377  resource_database,
3378  server_database;
3379 
3380  if (display == (Display *) NULL)
3381  return((XrmDatabase) NULL);
3382  assert(client_name != (char *) NULL);
3383  /*
3384  Initialize resource database.
3385  */
3386  XrmInitialize();
3387  (void) XGetDefault(display,(char *) client_name,"dummy");
3388  resource_database=XrmGetDatabase(display);
3389  /*
3390  Combine application database.
3391  */
3392  p=client_name+(strlen(client_name)-1);
3393  while ((p > client_name) && (*p != '/'))
3394  p--;
3395  if (*p == '/')
3396  client_name=p+1;
3397  c=(int) (*client_name);
3398  if ((c >= XK_a) && (c <= XK_z))
3399  c-=(XK_a-XK_A);
3400  else
3401  if ((c >= XK_agrave) && (c <= XK_odiaeresis))
3402  c-=(XK_agrave-XK_Agrave);
3403  else
3404  if ((c >= XK_oslash) && (c <= XK_thorn))
3405  c-=(XK_oslash-XK_Ooblique);
3406 #if defined(X11_APPLICATION_PATH)
3407  (void) FormatLocaleString(filename,MagickPathExtent,"%s%c%s",
3408  X11_APPLICATION_PATH,c,client_name+1);
3409  (void) XrmCombineFileDatabase(filename,&resource_database,MagickFalse);
3410 #endif
3411  if (XResourceManagerString(display) != (char *) NULL)
3412  {
3413  /*
3414  Combine server database.
3415  */
3416  server_database=XrmGetStringDatabase(XResourceManagerString(display));
3417  XrmCombineDatabase(server_database,&resource_database,MagickFalse);
3418  }
3419  /*
3420  Merge user preferences database.
3421  */
3422 #if defined(X11_PREFERENCES_PATH)
3423  (void) FormatLocaleString(filename,MagickPathExtent,"%s%src",
3424  X11_PREFERENCES_PATH,client_name);
3425  ExpandFilename(filename);
3426  (void) XrmCombineFileDatabase(filename,&resource_database,MagickFalse);
3427 #endif
3428  return(resource_database);
3429 }
3430 
3431 /*
3432 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3433 % %
3434 % %
3435 % %
3436 % X G e t R e s o u r c e I n f o %
3437 % %
3438 % %
3439 % %
3440 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3441 %
3442 % XGetResourceInfo() initializes the ResourceInfo structure.
3443 %
3444 % The format of the XGetResourceInfo method is:
3445 %
3446 % void XGetResourceInfo(const ImageInfo *image_info,XrmDatabase database,
3447 % const char *client_name,XResourceInfo *resource_info)
3448 %
3449 % A description of each parameter follows:
3450 %
3451 % o image_info: the image info.
3452 %
3453 % o database: Specifies a resource database; returned from
3454 % XrmGetStringDatabase.
3455 %
3456 % o client_name: Specifies the application name used to retrieve
3457 % resource info from the X server database.
3458 %
3459 % o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
3460 %
3461 */
3462 MagickExport void XGetResourceInfo(const ImageInfo *image_info,
3463  XrmDatabase database,const char *client_name,XResourceInfo *resource_info)
3464 {
3465  char
3466  *directory,
3467  *resource_value;
3468 
3469  /*
3470  Initialize resource info fields.
3471  */
3472  assert(resource_info != (XResourceInfo *) NULL);
3473  if (IsEventLogging() != MagickFalse)
3474  (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
3475  (void) memset(resource_info,0,sizeof(*resource_info));
3476  resource_info->resource_database=database;
3477  resource_info->image_info=(ImageInfo *) image_info;
3478  (void) SetImageInfoProgressMonitor(resource_info->image_info,
3479  XMagickProgressMonitor,(void *) NULL);
3480  resource_info->quantize_info=CloneQuantizeInfo((QuantizeInfo *) NULL);
3481  resource_info->close_server=MagickTrue;
3482  resource_info->client_name=AcquireString(client_name);
3483  resource_value=XGetResourceClass(database,client_name,"backdrop",
3484  (char *) "False");
3485  resource_info->backdrop=IsStringTrue(resource_value);
3486  resource_info->background_color=XGetResourceInstance(database,client_name,
3487  "background",(char *) "#d6d6d6d6d6d6");
3488  resource_info->border_color=XGetResourceInstance(database,client_name,
3489  "borderColor",BorderColor);
3490  resource_value=XGetResourceClass(database,client_name,"borderWidth",
3491  (char *) "2");
3492  resource_info->border_width=(unsigned int) StringToUnsignedLong(
3493  resource_value);
3494  resource_value=XGetResourceClass(database,client_name,"colormap",
3495  (char *) "shared");
3496  resource_info->colormap=UndefinedColormap;
3497  if (LocaleCompare("private",resource_value) == 0)
3498  resource_info->colormap=PrivateColormap;
3499  if (LocaleCompare("shared",resource_value) == 0)
3500  resource_info->colormap=SharedColormap;
3501  if (resource_info->colormap == UndefinedColormap)
3502  ThrowXWindowException(OptionError,"UnrecognizedColormapType",
3503  resource_value);
3504  resource_value=XGetResourceClass(database,client_name,
3505  "colorRecovery",(char *) "False");
3506  resource_info->color_recovery=IsStringTrue(resource_value);
3507  resource_value=XGetResourceClass(database,client_name,"confirmExit",
3508  (char *) "False");
3509  resource_info->confirm_exit=IsStringTrue(resource_value);
3510  resource_value=XGetResourceClass(database,client_name,"confirmEdit",
3511  (char *) "False");
3512  resource_info->confirm_edit=IsStringTrue(resource_value);
3513  resource_value=XGetResourceClass(database,client_name,"delay",(char *) "1");
3514  resource_info->delay=(unsigned int) StringToUnsignedLong(resource_value);
3515  resource_info->display_gamma=XGetResourceClass(database,client_name,
3516  "displayGamma",(char *) "2.2");
3517  resource_value=XGetResourceClass(database,client_name,"displayWarnings",
3518  (char *) "True");
3519  resource_info->display_warnings=IsStringTrue(resource_value);
3520  resource_info->font=XGetResourceClass(database,client_name,"font",
3521  (char *) NULL);
3522  resource_info->font=XGetResourceClass(database,client_name,"fontList",
3523  resource_info->font);
3524  resource_info->font_name[0]=XGetResourceClass(database,client_name,"font1",
3525  (char *) "fixed");
3526  resource_info->font_name[1]=XGetResourceClass(database,client_name,"font2",
3527  (char *) "variable");
3528  resource_info->font_name[2]=XGetResourceClass(database,client_name,"font3",
3529  (char *) "5x8");
3530  resource_info->font_name[3]=XGetResourceClass(database,client_name,"font4",
3531  (char *) "6x10");
3532  resource_info->font_name[4]=XGetResourceClass(database,client_name,"font5",
3533  (char *) "7x13bold");
3534  resource_info->font_name[5]=XGetResourceClass(database,client_name,"font6",
3535  (char *) "8x13bold");
3536  resource_info->font_name[6]=XGetResourceClass(database,client_name,"font7",
3537  (char *) "9x15bold");
3538  resource_info->font_name[7]=XGetResourceClass(database,client_name,"font8",
3539  (char *) "10x20");
3540  resource_info->font_name[8]=XGetResourceClass(database,client_name,"font9",
3541  (char *) "12x24");
3542  resource_info->font_name[9]=XGetResourceClass(database,client_name,"font0",
3543  (char *) "fixed");
3544  resource_info->font_name[10]=XGetResourceClass(database,client_name,"font0",
3545  (char *) "fixed");
3546  resource_info->foreground_color=XGetResourceInstance(database,client_name,
3547  "foreground",ForegroundColor);
3548  resource_value=XGetResourceClass(database,client_name,"gammaCorrect",
3549  (char *) "False");
3550  resource_info->gamma_correct=IsStringTrue(resource_value);
3551  resource_info->image_geometry=ConstantString(XGetResourceClass(database,
3552  client_name,"geometry",(char *) NULL));
3553  resource_value=XGetResourceClass(database,client_name,"gravity",
3554  (char *) "Center");
3555  resource_info->gravity=(int) ParseCommandOption(MagickGravityOptions,
3556  MagickFalse,resource_value);
3557  directory=getcwd(resource_info->home_directory,MagickPathExtent);
3558  (void) directory;
3559  resource_info->icon_geometry=XGetResourceClass(database,client_name,
3560  "iconGeometry",(char *) NULL);
3561  resource_value=XGetResourceClass(database,client_name,"iconic",
3562  (char *) "False");
3563  resource_info->iconic=IsStringTrue(resource_value);
3564  resource_value=XGetResourceClass(database,client_name,"immutable",
3565  LocaleCompare(client_name,"PerlMagick") == 0 ? (char *) "True" :
3566  (char *) "False");
3567  resource_info->immutable=IsStringTrue(resource_value);
3568  resource_value=XGetResourceClass(database,client_name,"magnify",
3569  (char *) "3");
3570  resource_info->magnify=(unsigned int) StringToUnsignedLong(resource_value);
3571  resource_info->map_type=XGetResourceClass(database,client_name,"map",
3572  (char *) NULL);
3573  resource_info->matte_color=XGetResourceInstance(database,client_name,
3574  "mattecolor",(char *) NULL);
3575  resource_info->name=ConstantString(XGetResourceClass(database,client_name,
3576  "name",(char *) NULL));
3577  resource_info->pen_colors[0]=XGetResourceClass(database,client_name,"pen1",
3578  (char *) "black");
3579  resource_info->pen_colors[1]=XGetResourceClass(database,client_name,"pen2",
3580  (char *) "blue");
3581  resource_info->pen_colors[2]=XGetResourceClass(database,client_name,"pen3",
3582  (char *) "cyan");
3583  resource_info->pen_colors[3]=XGetResourceClass(database,client_name,"pen4",
3584  (char *) "green");
3585  resource_info->pen_colors[4]=XGetResourceClass(database,client_name,"pen5",
3586  (char *) "gray");
3587  resource_info->pen_colors[5]=XGetResourceClass(database,client_name,"pen6",
3588  (char *) "red");
3589  resource_info->pen_colors[6]=XGetResourceClass(database,client_name,"pen7",
3590  (char *) "magenta");
3591  resource_info->pen_colors[7]=XGetResourceClass(database,client_name,"pen8",
3592  (char *) "yellow");
3593  resource_info->pen_colors[8]=XGetResourceClass(database,client_name,"pen9",
3594  (char *) "white");
3595  resource_info->pen_colors[9]=XGetResourceClass(database,client_name,"pen0",
3596  (char *) "gray");
3597  resource_info->pen_colors[10]=XGetResourceClass(database,client_name,"pen0",
3598  (char *) "gray");
3599  resource_value=XGetResourceClass(database,client_name,"pause",(char *) "0");
3600  resource_info->pause=(unsigned int) StringToUnsignedLong(resource_value);
3601  resource_value=XGetResourceClass(database,client_name,"quantum",(char *) "1");
3602  resource_info->quantum=StringToLong(resource_value);
3603  resource_info->text_font=XGetResourceClass(database,client_name,(char *)
3604  "font",(char *) "fixed");
3605  resource_info->text_font=XGetResourceClass(database,client_name,
3606  "textFontList",resource_info->text_font);
3607  resource_info->title=XGetResourceClass(database,client_name,"title",
3608  (char *) NULL);
3609  resource_value=XGetResourceClass(database,client_name,"undoCache",
3610  (char *) "4096");
3611  resource_info->undo_cache=(unsigned int) StringToUnsignedLong(resource_value);
3612  resource_value=XGetResourceClass(database,client_name,"update",
3613  (char *) "False");
3614  resource_info->update=IsStringTrue(resource_value);
3615  resource_value=XGetResourceClass(database,client_name,"usePixmap",
3616  (char *) "True");
3617  resource_info->use_pixmap=IsStringTrue(resource_value);
3618  resource_value=XGetResourceClass(database,client_name,"sharedMemory",
3619  (char *) "True");
3620  resource_info->use_shared_memory=IsStringTrue(resource_value);
3621  resource_info->visual_type=XGetResourceClass(database,client_name,"visual",
3622  (char *) NULL);
3623  resource_info->window_group=XGetResourceClass(database,client_name,
3624  "windowGroup",(char *) NULL);
3625  resource_info->window_id=XGetResourceClass(database,client_name,"window",
3626  (char *) NULL);
3627  resource_info->write_filename=XGetResourceClass(database,client_name,
3628  "writeFilename",(char *) NULL);
3629  resource_info->debug=(GetLogEventMask() & X11Event) != 0 ? MagickTrue :
3630  MagickFalse;
3631 }
3632 
3633 /*
3634 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3635 % %
3636 % %
3637 % %
3638 % X G e t R e s o u r c e I n s t a n c e %
3639 % %
3640 % %
3641 % %
3642 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3643 %
3644 % XGetResourceInstance() queries the X server for the specified resource name.
3645 % If the resource name is not defined in the database, the supplied default
3646 % value is returned.
3647 %
3648 % The format of the XGetResourceInstance method is:
3649 %
3650 % char *XGetResourceInstance(XrmDatabase database,const char *client_name,
3651 % const char *keyword,const char *resource_default)
3652 %
3653 % A description of each parameter follows:
3654 %
3655 % o database: Specifies a resource database; returned from
3656 % XrmGetStringDatabase.
3657 %
3658 % o client_name: Specifies the application name used to retrieve
3659 % resource info from the X server database.
3660 %
3661 % o keyword: Specifies the keyword of the value being retrieved.
3662 %
3663 % o resource_default: Specifies the default value to return if the query
3664 % fails to find the specified keyword/class.
3665 %
3666 */
3667 MagickExport char *XGetResourceInstance(XrmDatabase database,
3668  const char *client_name,const char *keyword,const char *resource_default)
3669 {
3670  char
3671  *resource_type,
3672  resource_name[MagickPathExtent];
3673 
3674  Status
3675  status;
3676 
3677  XrmValue
3678  resource_value;
3679 
3680  if (database == (XrmDatabase) NULL)
3681  return((char *) resource_default);
3682  *resource_name='\0';
3683  if (keyword != (char *) NULL)
3684  (void) FormatLocaleString(resource_name,MagickPathExtent,"%s.%s",client_name,
3685  keyword);
3686  status=XrmGetResource(database,resource_name,"ImageMagick",&resource_type,
3687  &resource_value);
3688  if (status == False)
3689  return((char *) resource_default);
3690  return(resource_value.addr);
3691 }
3692 
3693 /*
3694 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3695 % %
3696 % %
3697 % %
3698 % X G e t S c r e e n D e n s i t y %
3699 % %
3700 % %
3701 % %
3702 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3703 %
3704 % XGetScreenDensity() returns the density of the X server screen in
3705 % dots-per-inch.
3706 %
3707 % The format of the XGetScreenDensity method is:
3708 %
3709 % char *XGetScreenDensity(Display *display)
3710 %
3711 % A description of each parameter follows:
3712 %
3713 % o density: XGetScreenDensity() returns the density of the X screen in
3714 % dots-per-inch.
3715 %
3716 % o display: Specifies a connection to an X server; returned from
3717 % XOpenDisplay.
3718 %
3719 */
3720 MagickExport char *XGetScreenDensity(Display *display)
3721 {
3722  char
3723  density[MagickPathExtent];
3724 
3725  double
3726  x_density,
3727  y_density;
3728 
3729  /*
3730  Set density as determined by screen size.
3731  */
3732  x_density=((((double) DisplayWidth(display,XDefaultScreen(display)))*25.4)/
3733  ((double) DisplayWidthMM(display,XDefaultScreen(display))));
3734  y_density=((((double) DisplayHeight(display,XDefaultScreen(display)))*25.4)/
3735  ((double) DisplayHeightMM(display,XDefaultScreen(display))));
3736  (void) FormatLocaleString(density,MagickPathExtent,"%gx%g",x_density,
3737  y_density);
3738  return(GetPageGeometry(density));
3739 }
3740 
3741 /*
3742 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3743 % %
3744 % %
3745 % %
3746 + X G e t S u b w i n d o w %
3747 % %
3748 % %
3749 % %
3750 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3751 %
3752 % XGetSubwindow() returns the subwindow of a window chosen the user with the
3753 % pointer and a button press.
3754 %
3755 % The format of the XGetSubwindow method is:
3756 %
3757 % Window XGetSubwindow(Display *display,Window window,int x,int y)
3758 %
3759 % A description of each parameter follows:
3760 %
3761 % o subwindow: XGetSubwindow() returns NULL if no subwindow is found
3762 % otherwise the subwindow is returned.
3763 %
3764 % o display: Specifies a connection to an X server; returned from
3765 % XOpenDisplay.
3766 %
3767 % o window: Specifies a pointer to a Window.
3768 %
3769 % o x: the x coordinate of the pointer relative to the origin of the
3770 % window.
3771 %
3772 % o y: the y coordinate of the pointer relative to the origin of the
3773 % window.
3774 %
3775 */
3776 static Window XGetSubwindow(Display *display,Window window,int x,int y)
3777 {
3778  int
3779  x_offset,
3780  y_offset;
3781 
3782  Status
3783  status;
3784 
3785  Window
3786  source_window,
3787  target_window;
3788 
3789  assert(display != (Display *) NULL);
3790  source_window=XRootWindow(display,XDefaultScreen(display));
3791  if (window == (Window) NULL)
3792  return(source_window);
3793  target_window=window;
3794  for ( ; ; )
3795  {
3796  status=XTranslateCoordinates(display,source_window,window,x,y,
3797  &x_offset,&y_offset,&target_window);
3798  if (status != True)
3799  break;
3800  if (target_window == (Window) NULL)
3801  break;
3802  source_window=window;
3803  window=target_window;
3804  x=x_offset;
3805  y=y_offset;
3806  }
3807  if (target_window == (Window) NULL)
3808  target_window=window;
3809  return(target_window);
3810 }
3811 
3812 /*
3813 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3814 % %
3815 % %
3816 % %
3817 % X G e t W i n d o w C o l o r %
3818 % %
3819 % %
3820 % %
3821 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3822 %
3823 % XGetWindowColor() returns the color of a pixel interactively chosen from the
3824 % X server.
3825 %
3826 % The format of the XGetWindowColor method is:
3827 %
3828 % MagickBooleanType XGetWindowColor(Display *display,XWindows *windows,
3829 % char *name,ExceptionInfo *exception)
3830 %
3831 % A description of each parameter follows:
3832 %
3833 % o display: Specifies a connection to an X server; returned from
3834 % XOpenDisplay.
3835 %
3836 % o windows: Specifies a pointer to a XWindows structure.
3837 %
3838 % o name: the name of the color if found in the X Color Database is
3839 % returned in this character string.
3840 %
3841 % o exception: return any errors or warnings in this structure.
3842 %
3843 */
3844 MagickPrivate MagickBooleanType XGetWindowColor(Display *display,
3845  XWindows *windows,char *name,ExceptionInfo *exception)
3846 {
3847  int
3848  x,
3849  y;
3850 
3851  PixelInfo
3852  pixel;
3853 
3855  crop_info;
3856 
3857  Status
3858  status;
3859 
3860  Window
3861  child,
3862  client_window,
3863  root_window,
3864  target_window;
3865 
3866  XColor
3867  color;
3868 
3869  XImage
3870  *ximage;
3871 
3872  XWindowAttributes
3873  window_attributes;
3874 
3875  /*
3876  Choose a pixel from the X server.
3877  */
3878  assert(display != (Display *) NULL);
3879  assert(name != (char *) NULL);
3880  if (IsEventLogging() != MagickFalse)
3881  (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",name);
3882  *name='\0';
3883  target_window=XSelectWindow(display,&crop_info);
3884  if (target_window == (Window) NULL)
3885  return(MagickFalse);
3886  root_window=XRootWindow(display,XDefaultScreen(display));
3887  client_window=target_window;
3888  if (target_window != root_window)
3889  {
3890  unsigned int
3891  d;
3892 
3893  /*
3894  Get client window.
3895  */
3896  status=XGetGeometry(display,target_window,&root_window,&x,&x,&d,&d,&d,&d);
3897  if (status != False)
3898  {
3899  client_window=XClientWindow(display,target_window);
3900  target_window=client_window;
3901  }
3902  }
3903  /*
3904  Verify window is viewable.
3905  */
3906  status=XGetWindowAttributes(display,target_window,&window_attributes);
3907  if ((status == False) || (window_attributes.map_state != IsViewable))
3908  return(MagickFalse);
3909  /*
3910  Get window X image.
3911  */
3912  (void) XTranslateCoordinates(display,root_window,target_window,
3913  (int) crop_info.x,(int) crop_info.y,&x,&y,&child);
3914  ximage=XGetImage(display,target_window,x,y,1,1,AllPlanes,ZPixmap);
3915  if (ximage == (XImage *) NULL)
3916  return(MagickFalse);
3917  color.pixel=XGetPixel(ximage,0,0);
3918  XDestroyImage(ximage);
3919  /*
3920  Match color against the color database.
3921  */
3922  (void) XQueryColor(display,window_attributes.colormap,&color);
3923  pixel.red=(double) ScaleShortToQuantum(color.red);
3924  pixel.green=(double) ScaleShortToQuantum(color.green);
3925  pixel.blue=(double) ScaleShortToQuantum(color.blue);
3926  pixel.alpha=(MagickRealType) OpaqueAlpha;
3927  (void) QueryColorname(windows->image.image,&pixel,X11Compliance,name,
3928  exception);
3929  return(MagickTrue);
3930 }
3931 
3932 /*
3933 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3934 % %
3935 % %
3936 % %
3937 + X G e t W i n d o w I m a g e %
3938 % %
3939 % %
3940 % %
3941 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3942 %
3943 % XGetWindowImage() reads an image from the target X window and returns it.
3944 % XGetWindowImage() optionally descends the window hierarchy and overlays the
3945 % target image with each child image in an optimized fashion. Any child
3946 % window that have the same visual, colormap, and are contained by its parent
3947 % are exempted.
3948 %
3949 % The format of the XGetWindowImage method is:
3950 %
3951 % Image *XGetWindowImage(Display *display,const Window window,
3952 % const unsigned int borders,const unsigned int level,
3953 % ExceptionInfo *exception)
3954 %
3955 % A description of each parameter follows:
3956 %
3957 % o display: Specifies a connection to an X server; returned from
3958 % XOpenDisplay.
3959 %
3960 % o window: Specifies the window to obtain the image from.
3961 %
3962 % o borders: Specifies whether borders pixels are to be saved with
3963 % the image.
3964 %
3965 % o level: Specifies an unsigned integer representing the level of
3966 % decent in the window hierarchy. This value must be zero or one on
3967 % the initial call to XGetWindowImage. A value of zero returns after
3968 % one call. A value of one causes the function to descend the window
3969 % hierarchy and overlay the target image with each subwindow image.
3970 %
3971 % o exception: return any errors or warnings in this structure.
3972 %
3973 */
3974 static Image *XGetWindowImage(Display *display,const Window window,
3975  const unsigned int borders,const unsigned int level,ExceptionInfo *exception)
3976 {
3977  typedef struct _ColormapInfo
3978  {
3979  Colormap
3980  colormap;
3981 
3982  XColor
3983  *colors;
3984 
3985  struct _ColormapInfo
3986  *next;
3987  } ColormapInfo;
3988 
3989  typedef struct _WindowInfo
3990  {
3991  Window
3992  window,
3993  parent;
3994 
3995  Visual
3996  *visual;
3997 
3998  Colormap
3999  colormap;
4000 
4001  XSegment
4002  bounds;
4003 
4005  crop_info;
4006  } WindowInfo;
4007 
4008  int
4009  display_height,
4010  display_width,
4011  id,
4012  x_offset,
4013  y_offset;
4014 
4015  Quantum
4016  index;
4017 
4019  crop_info;
4020 
4021  int
4022  i;
4023 
4024  static ColormapInfo
4025  *colormap_info = (ColormapInfo *) NULL;
4026 
4027  static int
4028  max_windows = 0,
4029  number_windows = 0;
4030 
4031  static WindowInfo
4032  *window_info;
4033 
4034  Status
4035  status;
4036 
4037  Window
4038  child,
4039  root_window;
4040 
4041  XWindowAttributes
4042  window_attributes;
4043 
4044  /*
4045  Verify window is viewable.
4046  */
4047  assert(display != (Display *) NULL);
4048  if (IsEventLogging() != MagickFalse)
4049  (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
4050  status=XGetWindowAttributes(display,window,&window_attributes);
4051  if ((status == False) || (window_attributes.map_state != IsViewable))
4052  return((Image *) NULL);
4053  /*
4054  Cropping rectangle is relative to root window.
4055  */
4056  root_window=XRootWindow(display,XDefaultScreen(display));
4057  (void) XTranslateCoordinates(display,window,root_window,0,0,&x_offset,
4058  &y_offset,&child);
4059  crop_info.x=(ssize_t) x_offset;
4060  crop_info.y=(ssize_t) y_offset;
4061  crop_info.width=(size_t) window_attributes.width;
4062  crop_info.height=(size_t) window_attributes.height;
4063  if (borders != MagickFalse)
4064  {
4065  /*
4066  Include border in image.
4067  */
4068  crop_info.x-=(ssize_t) window_attributes.border_width;
4069  crop_info.y-=(ssize_t) window_attributes.border_width;
4070  crop_info.width+=(size_t) (window_attributes.border_width << 1);
4071  crop_info.height+=(size_t) (window_attributes.border_width << 1);
4072  }
4073  /*
4074  Crop to root window.
4075  */
4076  if (crop_info.x < 0)
4077  {
4078  crop_info.width=(unsigned int) ((int) crop_info.width+crop_info.x);
4079  crop_info.x=0;
4080  }
4081  if (crop_info.y < 0)
4082  {
4083  crop_info.height=(unsigned int) ((int) crop_info.height+crop_info.y);
4084  crop_info.y=0;
4085  }
4086  display_width=XDisplayWidth(display,XDefaultScreen(display));
4087  if ((crop_info.x+(int) crop_info.width) > display_width)
4088  crop_info.width=(size_t) (display_width-crop_info.x);
4089  display_height=XDisplayHeight(display,XDefaultScreen(display));
4090  if ((crop_info.y+(int) crop_info.height) > display_height)
4091  crop_info.height=(size_t) (display_height-crop_info.y);
4092  /*
4093  Initialize window info attributes.
4094  */
4095  if (number_windows >= max_windows)
4096  {
4097  /*
4098  Allocate or resize window info buffer.
4099  */
4100  max_windows+=1024;
4101  if (window_info == (WindowInfo *) NULL)
4102  window_info=(WindowInfo *) AcquireQuantumMemory((size_t) max_windows,
4103  sizeof(*window_info));
4104  else
4105  window_info=(WindowInfo *) ResizeQuantumMemory(window_info,(size_t)
4106  max_windows,sizeof(*window_info));
4107  }
4108  if (window_info == (WindowInfo *) NULL)
4109  {
4110  ThrowXWindowException(ResourceLimitError,"MemoryAllocationFailed","...");
4111  return((Image *) NULL);
4112  }
4113  id=number_windows++;
4114  window_info[id].window=window;
4115  window_info[id].visual=window_attributes.visual;
4116  window_info[id].colormap=window_attributes.colormap;
4117  window_info[id].bounds.x1=(short) crop_info.x;
4118  window_info[id].bounds.y1=(short) crop_info.y;
4119  window_info[id].bounds.x2=(short) (crop_info.x+(int) crop_info.width-1);
4120  window_info[id].bounds.y2=(short) (crop_info.y+(int) crop_info.height-1);
4121  crop_info.x-=x_offset;
4122  crop_info.y-=y_offset;
4123  window_info[id].crop_info=crop_info;
4124  if (level != 0)
4125  {
4126  unsigned int
4127  number_children;
4128 
4129  Window
4130  *children;
4131 
4132  /*
4133  Descend the window hierarchy.
4134  */
4135  status=XQueryTree(display,window,&root_window,&window_info[id].parent,
4136  &children,&number_children);
4137  for (i=0; i < id; i++)
4138  if ((window_info[i].window == window_info[id].parent) &&
4139  (window_info[i].visual == window_info[id].visual) &&
4140  (window_info[i].colormap == window_info[id].colormap))
4141  {
4142  if ((window_info[id].bounds.x1 < window_info[i].bounds.x1) ||
4143  (window_info[id].bounds.x2 > window_info[i].bounds.x2) ||
4144  (window_info[id].bounds.y1 < window_info[i].bounds.y1) ||
4145  (window_info[id].bounds.y2 > window_info[i].bounds.y2))
4146  {
4147  /*
4148  Eliminate windows not circumscribed by their parent.
4149  */
4150  number_windows--;
4151  break;
4152  }
4153  }
4154  if ((status == True) && (number_children != 0))
4155  {
4156  for (i=0; i < (int) number_children; i++)
4157  (void) XGetWindowImage(display,children[i],MagickFalse,level+1,
4158  exception);
4159  (void) XFree((void *) children);
4160  }
4161  }
4162  if (level <= 1)
4163  {
4164  CacheView
4165  *composite_view;
4166 
4167  ColormapInfo
4168  *next;
4169 
4170  Image
4171  *composite_image,
4172  *image;
4173 
4174  int
4175  y;
4176 
4177  MagickBooleanType
4178  import;
4179 
4180  int
4181  j,
4182  x;
4183 
4184  Quantum
4185  *magick_restrict q;
4186 
4187  size_t
4188  pixel;
4189 
4190  unsigned int
4191  number_colors;
4192 
4193  XColor
4194  *colors;
4195 
4196  XImage
4197  *ximage;
4198 
4199  /*
4200  Get X image for each window in the list.
4201  */
4202  image=NewImageList();
4203  for (id=0; id < number_windows; id++)
4204  {
4205  /*
4206  Does target window intersect top level window?
4207  */
4208  import=((window_info[id].bounds.x2 >= window_info[0].bounds.x1) &&
4209  (window_info[id].bounds.x1 <= window_info[0].bounds.x2) &&
4210  (window_info[id].bounds.y2 >= window_info[0].bounds.y1) &&
4211  (window_info[id].bounds.y1 <= window_info[0].bounds.y2)) ?
4212  MagickTrue : MagickFalse;
4213  /*
4214  Is target window contained by another window with the same colormap?
4215  */
4216  for (j=0; j < id; j++)
4217  if ((window_info[id].visual == window_info[j].visual) &&
4218  (window_info[id].colormap == window_info[j].colormap))
4219  {
4220  if ((window_info[id].bounds.x1 >= window_info[j].bounds.x1) &&
4221  (window_info[id].bounds.x2 <= window_info[j].bounds.x2) &&
4222  (window_info[id].bounds.y1 >= window_info[j].bounds.y1) &&
4223  (window_info[id].bounds.y2 <= window_info[j].bounds.y2))
4224  import=MagickFalse;
4225  }
4226  if (import == MagickFalse)
4227  continue;
4228  /*
4229  Get X image.
4230  */
4231  ximage=XGetImage(display,window_info[id].window,(int)
4232  window_info[id].crop_info.x,(int) window_info[id].crop_info.y,
4233  (unsigned int) window_info[id].crop_info.width,(unsigned int)
4234  window_info[id].crop_info.height,AllPlanes,ZPixmap);
4235  if (ximage == (XImage *) NULL)
4236  continue;
4237  /*
4238  Initialize window colormap.
4239  */
4240  number_colors=0;
4241  colors=(XColor *) NULL;
4242  if (window_info[id].colormap != (Colormap) NULL)
4243  {
4244  ColormapInfo
4245  *p;
4246 
4247  /*
4248  Search colormap list for window colormap.
4249  */
4250  number_colors=(unsigned int) window_info[id].visual->map_entries;
4251  for (p=colormap_info; p != (ColormapInfo *) NULL; p=p->next)
4252  if (p->colormap == window_info[id].colormap)
4253  break;
4254  if (p == (ColormapInfo *) NULL)
4255  {
4256  /*
4257  Get the window colormap.
4258  */
4259  colors=(XColor *) AcquireQuantumMemory(number_colors,
4260  sizeof(*colors));
4261  if (colors == (XColor *) NULL)
4262  {
4263  XDestroyImage(ximage);
4264  return((Image *) NULL);
4265  }
4266  if ((window_info[id].visual->klass != DirectColor) &&
4267  (window_info[id].visual->klass != TrueColor))
4268  for (i=0; i < (int) number_colors; i++)
4269  {
4270  colors[i].pixel=(size_t) i;
4271  colors[i].pad='\0';
4272  }
4273  else
4274  {
4275  size_t
4276  blue,
4277  blue_bit,
4278  green,
4279  green_bit,
4280  red,
4281  red_bit;
4282 
4283  /*
4284  DirectColor or TrueColor visual.
4285  */
4286  red=0;
4287  green=0;
4288  blue=0;
4289  red_bit=window_info[id].visual->red_mask &
4290  (~(window_info[id].visual->red_mask)+1);
4291  green_bit=window_info[id].visual->green_mask &
4292  (~(window_info[id].visual->green_mask)+1);
4293  blue_bit=window_info[id].visual->blue_mask &
4294  (~(window_info[id].visual->blue_mask)+1);
4295  for (i=0; i < (int) number_colors; i++)
4296  {
4297  colors[i].pixel=(unsigned long) (red | green | blue);
4298  colors[i].pad='\0';
4299  red+=red_bit;
4300  if (red > window_info[id].visual->red_mask)
4301  red=0;
4302  green+=green_bit;
4303  if (green > window_info[id].visual->green_mask)
4304  green=0;
4305  blue+=blue_bit;
4306  if (blue > window_info[id].visual->blue_mask)
4307  blue=0;
4308  }
4309  }
4310  (void) XQueryColors(display,window_info[id].colormap,colors,
4311  (int) number_colors);
4312  /*
4313  Append colormap to colormap list.
4314  */
4315  p=(ColormapInfo *) AcquireMagickMemory(sizeof(*p));
4316  if (p == (ColormapInfo *) NULL)
4317  return((Image *) NULL);
4318  p->colormap=window_info[id].colormap;
4319  p->colors=colors;
4320  p->next=colormap_info;
4321  colormap_info=p;
4322  }
4323  colors=p->colors;
4324  }
4325  /*
4326  Allocate image structure.
4327  */
4328  composite_image=AcquireImage((ImageInfo *) NULL,exception);
4329  if (composite_image == (Image *) NULL)
4330  {
4331  XDestroyImage(ximage);
4332  return((Image *) NULL);
4333  }
4334  /*
4335  Convert X image to MIFF format.
4336  */
4337  if ((window_info[id].visual->klass != TrueColor) &&
4338  (window_info[id].visual->klass != DirectColor))
4339  composite_image->storage_class=PseudoClass;
4340  composite_image->columns=(size_t) ximage->width;
4341  composite_image->rows=(size_t) ximage->height;
4342  composite_view=AcquireAuthenticCacheView(composite_image,exception);
4343  switch (composite_image->storage_class)
4344  {
4345  case DirectClass:
4346  default:
4347  {
4348  size_t
4349  color,
4350  index;
4351 
4352  size_t
4353  blue_mask,
4354  blue_shift,
4355  green_mask,
4356  green_shift,
4357  red_mask,
4358  red_shift;
4359 
4360  /*
4361  Determine shift and mask for red, green, and blue.
4362  */
4363  red_mask=window_info[id].visual->red_mask;
4364  red_shift=0;
4365  while ((red_mask != 0) && ((red_mask & 0x01) == 0))
4366  {
4367  red_mask>>=1;
4368  red_shift++;
4369  }
4370  green_mask=window_info[id].visual->green_mask;
4371  green_shift=0;
4372  while ((green_mask != 0) && ((green_mask & 0x01) == 0))
4373  {
4374  green_mask>>=1;
4375  green_shift++;
4376  }
4377  blue_mask=window_info[id].visual->blue_mask;
4378  blue_shift=0;
4379  while ((blue_mask != 0) && ((blue_mask & 0x01) == 0))
4380  {
4381  blue_mask>>=1;
4382  blue_shift++;
4383  }
4384  /*
4385  Convert X image to DirectClass packets.
4386  */
4387  if ((number_colors != 0) &&
4388  (window_info[id].visual->klass == DirectColor))
4389  for (y=0; y < (int) composite_image->rows; y++)
4390  {
4391  q=QueueCacheViewAuthenticPixels(composite_view,0,(ssize_t) y,
4392  composite_image->columns,1,exception);
4393  if (q == (Quantum *) NULL)
4394  break;
4395  for (x=0; x < (int) composite_image->columns; x++)
4396  {
4397  pixel=XGetPixel(ximage,x,y);
4398  index=(pixel >> red_shift) & red_mask;
4399  SetPixelRed(composite_image,
4400  ScaleShortToQuantum(colors[index].red),q);
4401  index=(pixel >> green_shift) & green_mask;
4402  SetPixelGreen(composite_image,
4403  ScaleShortToQuantum(colors[index].green),q);
4404  index=(pixel >> blue_shift) & blue_mask;
4405  SetPixelBlue(composite_image,
4406  ScaleShortToQuantum(colors[index].blue),q);
4407  q+=(ptrdiff_t) GetPixelChannels(composite_image);
4408  }
4409  status=SyncCacheViewAuthenticPixels(composite_view,exception)
4410  == MagickFalse ? 0 : 1;
4411  if (status == MagickFalse)
4412  break;
4413  }
4414  else
4415  for (y=0; y < (int) composite_image->rows; y++)
4416  {
4417  q=QueueCacheViewAuthenticPixels(composite_view,0,(ssize_t) y,
4418  composite_image->columns,1,exception);
4419  if (q == (Quantum *) NULL)
4420  break;
4421  for (x=0; x < (int) composite_image->columns; x++)
4422  {
4423  pixel=XGetPixel(ximage,x,y);
4424  color=(pixel >> red_shift) & red_mask;
4425  if (red_mask != 0)
4426  color=(65535UL*color)/red_mask;
4427  SetPixelRed(composite_image,ScaleShortToQuantum(
4428  (unsigned short) color),q);
4429  color=(pixel >> green_shift) & green_mask;
4430  if (green_mask != 0)
4431  color=(65535UL*color)/green_mask;
4432  SetPixelGreen(composite_image,ScaleShortToQuantum(
4433  (unsigned short) color),q);
4434  color=(pixel >> blue_shift) & blue_mask;
4435  if (blue_mask != 0)
4436  color=(65535UL*color)/blue_mask;
4437  SetPixelBlue(composite_image,ScaleShortToQuantum(
4438  (unsigned short) color),q);
4439  q+=(ptrdiff_t) GetPixelChannels(composite_image);
4440  }
4441  status=SyncCacheViewAuthenticPixels(composite_view,exception)
4442  == MagickFalse ? 0 : 1;
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) == MagickFalse ? 0 : 1;
4455  if (status == MagickFalse)
4456  {
4457  XDestroyImage(ximage);
4458  composite_image=DestroyImage(composite_image);
4459  return((Image *) NULL);
4460  }
4461  if (colors == (XColor *) NULL)
4462  break;
4463  for (i=0; i < (int) composite_image->colors; i++)
4464  {
4465  composite_image->colormap[colors[i].pixel].red=(double)
4466  ScaleShortToQuantum(colors[i].red);
4467  composite_image->colormap[colors[i].pixel].green=(double)
4468  ScaleShortToQuantum(colors[i].green);
4469  composite_image->colormap[colors[i].pixel].blue=(double)
4470  ScaleShortToQuantum(colors[i].blue);
4471  }
4472  /*
4473  Convert X image to PseudoClass packets.
4474  */
4475  for (y=0; y < (int) composite_image->rows; y++)
4476  {
4477  q=QueueCacheViewAuthenticPixels(composite_view,0,(ssize_t) y,
4478  composite_image->columns,1,exception);
4479  if (q == (Quantum *) NULL)
4480  break;
4481  for (x=0; x < (int) composite_image->columns; x++)
4482  {
4483  index=(Quantum) XGetPixel(ximage,x,y);
4484  SetPixelIndex(composite_image,index,q);
4485  SetPixelViaPixelInfo(composite_image,
4486  composite_image->colormap+(ssize_t) index,q);
4487  q+=(ptrdiff_t) GetPixelChannels(composite_image);
4488  }
4489  status=SyncCacheViewAuthenticPixels(composite_view,exception)
4490  == MagickFalse ? 0 : 1;
4491  if (status == MagickFalse)
4492  break;
4493  }
4494  break;
4495  }
4496  }
4497  composite_view=DestroyCacheView(composite_view);
4498  XDestroyImage(ximage);
4499  if (image == (Image *) NULL)
4500  {
4501  image=composite_image;
4502  continue;
4503  }
4504  /*
4505  Composite any children in back-to-front order.
4506  */
4507  (void) XTranslateCoordinates(display,window_info[id].window,window,0,0,
4508  &x_offset,&y_offset,&child);
4509  x_offset-=(int) crop_info.x;
4510  if (x_offset < 0)
4511  x_offset=0;
4512  y_offset-=(int) crop_info.y;
4513  if (y_offset < 0)
4514  y_offset=0;
4515  (void) CompositeImage(image,composite_image,CopyCompositeOp,MagickTrue,
4516  (ssize_t) x_offset,(ssize_t) y_offset,exception);
4517  composite_image=DestroyImage(composite_image);
4518  }
4519  /*
4520  Relinquish resources.
4521  */
4522  while (colormap_info != (ColormapInfo *) NULL)
4523  {
4524  next=colormap_info->next;
4525  colormap_info->colors=(XColor *) RelinquishMagickMemory(
4526  colormap_info->colors);
4527  colormap_info=(ColormapInfo *) RelinquishMagickMemory(colormap_info);
4528  colormap_info=next;
4529  }
4530  /*
4531  Relinquish resources and restore initial state.
4532  */
4533  window_info=(WindowInfo *) RelinquishMagickMemory(window_info);
4534  max_windows=0;
4535  number_windows=0;
4536  colormap_info=(ColormapInfo *) NULL;
4537  return(image);
4538  }
4539  return((Image *) NULL);
4540 }
4541 
4542 /*
4543 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4544 % %
4545 % %
4546 % %
4547 % X G e t W i n d o w I n f o %
4548 % %
4549 % %
4550 % %
4551 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4552 %
4553 % XGetWindowInfo() initializes the XWindowInfo structure.
4554 %
4555 % The format of the XGetWindowInfo method is:
4556 %
4557 % void XGetWindowInfo(Display *display,XVisualInfo *visual_info,
4558 % XStandardColormap *map_info,XPixelInfo *pixel,XFontStruct *font_info,
4559 % XResourceInfo *resource_info,XWindowInfo *window)
4560 % resource_info,window)
4561 %
4562 % A description of each parameter follows:
4563 %
4564 % o display: Specifies a connection to an X server; returned from
4565 % XOpenDisplay.
4566 %
4567 % o visual_info: Specifies a pointer to a X11 XVisualInfo structure;
4568 % returned from XGetVisualInfo.
4569 %
4570 % o map_info: If map_type is specified, this structure is initialized
4571 % with info from the Standard Colormap.
4572 %
4573 % o pixel: Specifies a pointer to a XPixelInfo structure.
4574 %
4575 % o font_info: Specifies a pointer to a XFontStruct structure.
4576 %
4577 % o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
4578 %
4579 */
4580 MagickPrivate void XGetWindowInfo(Display *display,XVisualInfo *visual_info,
4581  XStandardColormap *map_info,XPixelInfo *pixel,XFontStruct *font_info,
4582  XResourceInfo *resource_info,XWindowInfo *window)
4583 {
4584  /*
4585  Initialize window info.
4586  */
4587  assert(display != (Display *) NULL);
4588  assert(visual_info != (XVisualInfo *) NULL);
4589  assert(map_info != (XStandardColormap *) NULL);
4590  assert(pixel != (XPixelInfo *) NULL);
4591  assert(resource_info != (XResourceInfo *) NULL);
4592  assert(window != (XWindowInfo *) NULL);
4593  if (IsEventLogging() != MagickFalse)
4594  (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
4595  if (window->id != (Window) NULL)
4596  {
4597  if (window->cursor != (Cursor) NULL)
4598  (void) XFreeCursor(display,window->cursor);
4599  if (window->busy_cursor != (Cursor) NULL)
4600  (void) XFreeCursor(display,window->busy_cursor);
4601  if (window->highlight_stipple != (Pixmap) NULL)
4602  (void) XFreePixmap(display,window->highlight_stipple);
4603  if (window->shadow_stipple != (Pixmap) NULL)
4604  (void) XFreePixmap(display,window->shadow_stipple);
4605  if (window->name == (char *) NULL)
4606  window->name=AcquireString("");
4607  if (window->icon_name == (char *) NULL)
4608  window->icon_name=AcquireString("");
4609  }
4610  else
4611  {
4612  /*
4613  Initialize these attributes just once.
4614  */
4615  window->id=(Window) NULL;
4616  if (window->name == (char *) NULL)
4617  window->name=AcquireString("");
4618  if (window->icon_name == (char *) NULL)
4619  window->icon_name=AcquireString("");
4620  window->x=XDisplayWidth(display,visual_info->screen) >> 1;
4621  window->y=XDisplayWidth(display,visual_info->screen) >> 1;
4622  window->ximage=(XImage *) NULL;
4623  window->matte_image=(XImage *) NULL;
4624  window->pixmap=(Pixmap) NULL;
4625  window->matte_pixmap=(Pixmap) NULL;
4626  window->mapped=MagickFalse;
4627  window->stasis=MagickFalse;
4628  window->shared_memory=MagickTrue;
4629  window->segment_info=(void *) NULL;
4630 #if defined(MAGICKCORE_HAVE_SHARED_MEMORY)
4631  {
4632  XShmSegmentInfo
4633  *segment_info;
4634 
4635  if (window->segment_info == (void *) NULL)
4636  window->segment_info=AcquireCriticalMemory(2*sizeof(*segment_info));
4637  segment_info=(XShmSegmentInfo *) window->segment_info;
4638  segment_info[0].shmid=(-1);
4639  segment_info[0].shmaddr=(char *) NULL;
4640  segment_info[1].shmid=(-1);
4641  segment_info[1].shmaddr=(char *) NULL;
4642  }
4643 #endif
4644  }
4645  /*
4646  Initialize these attributes every time function is called.
4647  */
4648  window->screen=visual_info->screen;
4649  window->root=XRootWindow(display,visual_info->screen);
4650  window->visual=visual_info->visual;
4651  window->storage_class=(unsigned int) visual_info->klass;
4652  window->depth=(unsigned int) visual_info->depth;
4653  window->visual_info=visual_info;
4654  window->map_info=map_info;
4655  window->pixel_info=pixel;
4656  window->font_info=font_info;
4657  window->cursor=XCreateFontCursor(display,XC_left_ptr);
4658  window->busy_cursor=XCreateFontCursor(display,XC_watch);
4659  window->geometry=(char *) NULL;
4660  window->icon_geometry=(char *) NULL;
4661  if (resource_info->icon_geometry != (char *) NULL)
4662  (void) CloneString(&window->icon_geometry,resource_info->icon_geometry);
4663  window->crop_geometry=(char *) NULL;
4664  window->flags=(size_t) PSize;
4665  window->width=1;
4666  window->height=1;
4667  window->min_width=1;
4668  window->min_height=1;
4669  window->width_inc=1;
4670  window->height_inc=1;
4671  window->border_width=resource_info->border_width;
4672  window->annotate_context=pixel->annotate_context;
4673  window->highlight_context=pixel->highlight_context;
4674  window->widget_context=pixel->widget_context;
4675  window->shadow_stipple=(Pixmap) NULL;
4676  window->highlight_stipple=(Pixmap) NULL;
4677  window->use_pixmap=MagickTrue;
4678  window->immutable=MagickFalse;
4679  window->shape=MagickFalse;
4680  window->data=0;
4681  window->mask=(int) (CWBackingStore | CWBackPixel | CWBackPixmap |
4682  CWBitGravity | CWBorderPixel | CWColormap | CWCursor | CWDontPropagate |
4683  CWEventMask | CWOverrideRedirect | CWSaveUnder | CWWinGravity);
4684  window->attributes.background_pixel=pixel->background_color.pixel;
4685  window->attributes.background_pixmap=(Pixmap) NULL;
4686  window->attributes.bit_gravity=ForgetGravity;
4687  window->attributes.backing_store=WhenMapped;
4688  window->attributes.save_under=MagickTrue;
4689  window->attributes.border_pixel=pixel->border_color.pixel;
4690  window->attributes.colormap=map_info->colormap;
4691  window->attributes.cursor=window->cursor;
4692  window->attributes.do_not_propagate_mask=NoEventMask;
4693  window->attributes.event_mask=NoEventMask;
4694  window->attributes.override_redirect=MagickFalse;
4695  window->attributes.win_gravity=NorthWestGravity;
4696  window->orphan=MagickFalse;
4697 }
4698 
4699 /*
4700 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4701 % %
4702 % %
4703 % %
4704 % X H i g h l i g h t E l l i p s e %
4705 % %
4706 % %
4707 % %
4708 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4709 %
4710 % XHighlightEllipse() puts a border on the X server around a region defined by
4711 % highlight_info.
4712 %
4713 % The format of the XHighlightEllipse method is:
4714 %
4715 % void XHighlightEllipse(Display *display,Window window,
4716 % GC annotate_context,const RectangleInfo *highlight_info)
4717 %
4718 % A description of each parameter follows:
4719 %
4720 % o display: Specifies a connection to an X server; returned from
4721 % XOpenDisplay.
4722 %
4723 % o window: Specifies a pointer to a Window structure.
4724 %
4725 % o annotate_context: Specifies a pointer to a GC structure.
4726 %
4727 % o highlight_info: Specifies a pointer to a RectangleInfo structure. It
4728 % contains the extents of any highlighting rectangle.
4729 %
4730 */
4731 MagickPrivate void XHighlightEllipse(Display *display,Window window,
4732  GC annotate_context,const RectangleInfo *highlight_info)
4733 {
4734  assert(display != (Display *) NULL);
4735  assert(window != (Window) NULL);
4736  assert(annotate_context != (GC) NULL);
4737  assert(highlight_info != (RectangleInfo *) NULL);
4738  if (IsEventLogging() != MagickFalse)
4739  (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
4740  if ((highlight_info->width < 4) || (highlight_info->height < 4))
4741  return;
4742  (void) XDrawArc(display,window,annotate_context,(int) highlight_info->x,
4743  (int) highlight_info->y,(unsigned int) highlight_info->width-1,
4744  (unsigned int) highlight_info->height-1,0,360*64);
4745  (void) XDrawArc(display,window,annotate_context,(int) highlight_info->x+1,
4746  (int) highlight_info->y+1,(unsigned int) highlight_info->width-3,
4747  (unsigned int) highlight_info->height-3,0,360*64);
4748 }
4749 
4750 /*
4751 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4752 % %
4753 % %
4754 % %
4755 % X H i g h l i g h t L i n e %
4756 % %
4757 % %
4758 % %
4759 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4760 %
4761 % XHighlightLine() puts a border on the X server around a region defined by
4762 % highlight_info.
4763 %
4764 % The format of the XHighlightLine method is:
4765 %
4766 % void XHighlightLine(Display *display,Window window,GC annotate_context,
4767 % const XSegment *highlight_info)
4768 %
4769 % A description of each parameter follows:
4770 %
4771 % o display: Specifies a connection to an X server; returned from
4772 % XOpenDisplay.
4773 %
4774 % o window: Specifies a pointer to a Window structure.
4775 %
4776 % o annotate_context: Specifies a pointer to a GC structure.
4777 %
4778 % o highlight_info: Specifies a pointer to a RectangleInfo structure. It
4779 % contains the extents of any highlighting rectangle.
4780 %
4781 */
4782 MagickPrivate void XHighlightLine(Display *display,Window window,
4783  GC annotate_context,const XSegment *highlight_info)
4784 {
4785  assert(display != (Display *) NULL);
4786  assert(window != (Window) NULL);
4787  assert(annotate_context != (GC) NULL);
4788  assert(highlight_info != (XSegment *) NULL);
4789  if (IsEventLogging() != MagickFalse)
4790  (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
4791  (void) XDrawLine(display,window,annotate_context,highlight_info->x1,
4792  highlight_info->y1,highlight_info->x2,highlight_info->y2);
4793 }
4794 
4795 /*
4796 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4797 % %
4798 % %
4799 % %
4800 % X H i g h l i g h t R e c t a n g l e %
4801 % %
4802 % %
4803 % %
4804 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4805 %
4806 % XHighlightRectangle() puts a border on the X server around a region defined
4807 % by highlight_info.
4808 %
4809 % The format of the XHighlightRectangle method is:
4810 %
4811 % void XHighlightRectangle(Display *display,Window window,
4812 % GC annotate_context,const RectangleInfo *highlight_info)
4813 %
4814 % A description of each parameter follows:
4815 %
4816 % o display: Specifies a connection to an X server; returned from
4817 % XOpenDisplay.
4818 %
4819 % o window: Specifies a pointer to a Window structure.
4820 %
4821 % o annotate_context: Specifies a pointer to a GC structure.
4822 %
4823 % o highlight_info: Specifies a pointer to a RectangleInfo structure. It
4824 % contains the extents of any highlighting rectangle.
4825 %
4826 */
4827 MagickPrivate void XHighlightRectangle(Display *display,Window window,
4828  GC annotate_context,const RectangleInfo *highlight_info)
4829 {
4830  assert(display != (Display *) NULL);
4831  assert(window != (Window) NULL);
4832  assert(annotate_context != (GC) NULL);
4833  assert(highlight_info != (RectangleInfo *) NULL);
4834  if (IsEventLogging() != MagickFalse)
4835  (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
4836  if ((highlight_info->width < 4) || (highlight_info->height < 4))
4837  return;
4838  (void) XDrawRectangle(display,window,annotate_context,(int) highlight_info->x,
4839  (int) highlight_info->y,(unsigned int) highlight_info->width-1,
4840  (unsigned int) highlight_info->height-1);
4841  (void) XDrawRectangle(display,window,annotate_context,(int) highlight_info->x+
4842  1,(int) highlight_info->y+1,(unsigned int) highlight_info->width-3,
4843  (unsigned int) highlight_info->height-3);
4844 }
4845 
4846 /*
4847 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4848 % %
4849 % %
4850 % %
4851 % X I m p o r t I m a g e %
4852 % %
4853 % %
4854 % %
4855 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4856 %
4857 % XImportImage() reads an image from an X window.
4858 %
4859 % The format of the XImportImage method is:
4860 %
4861 % Image *XImportImage(const ImageInfo *image_info,XImportInfo *ximage_info,
4862 % ExceptionInfo *exception)
4863 %
4864 % A description of each parameter follows:
4865 %
4866 % o image_info: the image info.
4867 %
4868 % o ximage_info: Specifies a pointer to an XImportInfo structure.
4869 %
4870 % o exception: return any errors or warnings in this structure.
4871 %
4872 */
4873 MagickExport Image *XImportImage(const ImageInfo *image_info,
4874  XImportInfo *ximage_info,ExceptionInfo *exception)
4875 {
4876  Colormap
4877  *colormaps;
4878 
4879  Display
4880  *display;
4881 
4882  Image
4883  *image;
4884 
4885  int
4886  number_colormaps,
4887  number_windows,
4888  x;
4889 
4891  crop_info;
4892 
4893  Status
4894  status;
4895 
4896  Window
4897  *children,
4898  client,
4899  prior_target,
4900  root,
4901  target;
4902 
4903  XTextProperty
4904  window_name;
4905 
4906  /*
4907  Open X server connection.
4908  */
4909  assert(image_info != (const ImageInfo *) NULL);
4910  assert(image_info->signature == MagickCoreSignature);
4911  assert(ximage_info != (XImportInfo *) NULL);
4912  if (IsEventLogging() != MagickFalse)
4913  (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
4914  image_info->filename);
4915  display=XOpenDisplay(image_info->server_name);
4916  if (display == (Display *) NULL)
4917  {
4918  ThrowXWindowException(XServerError,"UnableToOpenXServer",
4919  XDisplayName(image_info->server_name));
4920  return((Image *) NULL);
4921  }
4922  /*
4923  Set our forgiving exception handler.
4924  */
4925  (void) XSetErrorHandler(XError);
4926  /*
4927  Select target window.
4928  */
4929  crop_info.x=0;
4930  crop_info.y=0;
4931  crop_info.width=0;
4932  crop_info.height=0;
4933  root=XRootWindow(display,XDefaultScreen(display));
4934  target=(Window) NULL;
4935  if (*image_info->filename != '\0')
4936  {
4937  if (LocaleCompare(image_info->filename,"root") == 0)
4938  target=root;
4939  else
4940  {
4941  /*
4942  Select window by ID or name.
4943  */
4944  if (isdigit((int) ((unsigned char) *image_info->filename)) != 0)
4945  target=XWindowByID(display,root,(Window)
4946  strtol(image_info->filename,(char **) NULL,0));
4947  if (target == (Window) NULL)
4948  target=XWindowByName(display,root,image_info->filename);
4949  if (target == (Window) NULL)
4950  ThrowXWindowException(XServerError,"NoWindowWithSpecifiedIDExists",
4951  image_info->filename);
4952  }
4953  }
4954  /*
4955  If target window is not defined, interactively select one.
4956  */
4957  prior_target=target;
4958  if (target == (Window) NULL)
4959  target=XSelectWindow(display,&crop_info);
4960  if (target == (Window) NULL)
4961  ThrowXWindowException(XServerError,"UnableToReadXWindowImage",
4962  image_info->filename);
4963  client=target; /* obsolete */
4964  if (target != root)
4965  {
4966  unsigned int
4967  d;
4968 
4969  status=XGetGeometry(display,target,&root,&x,&x,&d,&d,&d,&d);
4970  if (status != False)
4971  {
4972  for ( ; ; )
4973  {
4974  Window
4975  parent;
4976 
4977  /*
4978  Find window manager frame.
4979  */
4980  status=XQueryTree(display,target,&root,&parent,&children,&d);
4981  if ((status != False) && (children != (Window *) NULL))
4982  (void) XFree((char *) children);
4983  if ((status == False) || (parent == (Window) NULL) ||
4984  (parent == root))
4985  break;
4986  target=parent;
4987  }
4988  /*
4989  Get client window.
4990  */
4991  client=XClientWindow(display,target);
4992  if (ximage_info->frame == MagickFalse)
4993  target=client;
4994  if ((ximage_info->frame == MagickFalse) &&
4995  (prior_target != MagickFalse))
4996  target=prior_target;
4997  }
4998  }
4999  if (ximage_info->screen != MagickFalse)
5000  {
5001  int
5002  y;
5003 
5004  Window
5005  child;
5006 
5007  XWindowAttributes
5008  window_attributes;
5009 
5010  /*
5011  Obtain window image directly from screen.
5012  */
5013  status=XGetWindowAttributes(display,target,&window_attributes);
5014  if (status == False)
5015  {
5016  ThrowXWindowException(XServerError,"UnableToReadXWindowAttributes",
5017  image_info->filename);
5018  (void) XCloseDisplay(display);
5019  return((Image *) NULL);
5020  }
5021  (void) XTranslateCoordinates(display,target,root,0,0,&x,&y,&child);
5022  crop_info.x=(ssize_t) x;
5023  crop_info.y=(ssize_t) y;
5024  crop_info.width=(size_t) window_attributes.width;
5025  crop_info.height=(size_t) window_attributes.height;
5026  if (ximage_info->borders != 0)
5027  {
5028  /*
5029  Include border in image.
5030  */
5031  crop_info.x-=window_attributes.border_width;
5032  crop_info.y-=window_attributes.border_width;
5033  crop_info.width+=(size_t) (window_attributes.border_width << 1);
5034  crop_info.height+=(size_t) (window_attributes.border_width << 1);
5035  }
5036  target=root;
5037  }
5038  /*
5039  If WM_COLORMAP_WINDOWS property is set or multiple colormaps, descend.
5040  */
5041  number_windows=0;
5042  status=XGetWMColormapWindows(display,target,&children,&number_windows);
5043  if ((status == True) && (number_windows > 0))
5044  {
5045  ximage_info->descend=MagickTrue;
5046  (void) XFree ((char *) children);
5047  }
5048  colormaps=XListInstalledColormaps(display,target,&number_colormaps);
5049  if (number_colormaps > 0)
5050  {
5051  if (number_colormaps > 1)
5052  ximage_info->descend=MagickTrue;
5053  (void) XFree((char *) colormaps);
5054  }
5055  /*
5056  Alert the user not to alter the screen.
5057  */
5058  if (ximage_info->silent == MagickFalse)
5059  (void) XBell(display,0);
5060  /*
5061  Get image by window id.
5062  */
5063  (void) XGrabServer(display);
5064  image=XGetWindowImage(display,target,ximage_info->borders,
5065  ximage_info->descend ? 1U : 0U,exception);
5066  (void) XUngrabServer(display);
5067  if (image != (Image *) NULL)
5068  {
5069  (void) CopyMagickString(image->filename,image_info->filename,
5070  MagickPathExtent);
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  (void) memset((void *) windows->pixel_info,0,sizeof(XPixelInfo));
5170  (void) memset((void *) windows->icon_pixel,0,sizeof(XPixelInfo));
5171  /*
5172  Initialize windows structure.
5173  */
5174  windows->display=display;
5175  windows->wm_protocols=XInternAtom(display,"WM_PROTOCOLS",MagickFalse);
5176  windows->wm_delete_window=XInternAtom(display,"WM_DELETE_WINDOW",MagickFalse);
5177  windows->wm_take_focus=XInternAtom(display,"WM_TAKE_FOCUS",MagickFalse);
5178  windows->im_protocols=XInternAtom(display,"IM_PROTOCOLS",MagickFalse);
5179  windows->im_remote_command=
5180  XInternAtom(display,"IM_REMOTE_COMMAND",MagickFalse);
5181  windows->im_update_widget=XInternAtom(display,"IM_UPDATE_WIDGET",MagickFalse);
5182  windows->im_update_colormap=
5183  XInternAtom(display,"IM_UPDATE_COLORMAP",MagickFalse);
5184  windows->im_former_image=XInternAtom(display,"IM_FORMER_IMAGE",MagickFalse);
5185  windows->im_next_image=XInternAtom(display,"IM_NEXT_IMAGE",MagickFalse);
5186  windows->im_retain_colors=XInternAtom(display,"IM_RETAIN_COLORS",MagickFalse);
5187  windows->im_exit=XInternAtom(display,"IM_EXIT",MagickFalse);
5188  windows->dnd_protocols=XInternAtom(display,"DndProtocol",MagickFalse);
5189 #if defined(MAGICKCORE_WINDOWS_SUPPORT)
5190  (void) XSynchronize(display,MagickFalse);
5191 #endif
5192  if ((GetLogEventMask() & X11Event) != 0)
5193  {
5194  (void) XSynchronize(display,MagickTrue);
5195  (void) LogMagickEvent(X11Event,GetMagickModule(),"Version: %s",
5196  GetMagickVersion((size_t *) NULL));
5197  (void) LogMagickEvent(X11Event,GetMagickModule(),"Protocols:");
5198  (void) LogMagickEvent(X11Event,GetMagickModule(),
5199  " Window Manager: 0x%lx",windows->wm_protocols);
5200  (void) LogMagickEvent(X11Event,GetMagickModule(),
5201  " delete window: 0x%lx",windows->wm_delete_window);
5202  (void) LogMagickEvent(X11Event,GetMagickModule()," take focus: 0x%lx",
5203  windows->wm_take_focus);
5204  (void) LogMagickEvent(X11Event,GetMagickModule()," ImageMagick: 0x%lx",
5205  windows->im_protocols);
5206  (void) LogMagickEvent(X11Event,GetMagickModule(),
5207  " remote command: 0x%lx",windows->im_remote_command);
5208  (void) LogMagickEvent(X11Event,GetMagickModule(),
5209  " update widget: 0x%lx",windows->im_update_widget);
5210  (void) LogMagickEvent(X11Event,GetMagickModule(),
5211  " update colormap: 0x%lx",windows->im_update_colormap);
5212  (void) LogMagickEvent(X11Event,GetMagickModule(),
5213  " former image: 0x%lx",windows->im_former_image);
5214  (void) LogMagickEvent(X11Event,GetMagickModule()," next image: 0x%lx",
5215  windows->im_next_image);
5216  (void) LogMagickEvent(X11Event,GetMagickModule(),
5217  " retain colors: 0x%lx",windows->im_retain_colors);
5218  (void) LogMagickEvent(X11Event,GetMagickModule()," exit: 0x%lx",
5219  windows->im_exit);
5220  (void) LogMagickEvent(X11Event,GetMagickModule()," Drag and Drop: 0x%lx",
5221  windows->dnd_protocols);
5222  }
5223  /*
5224  Allocate standard colormap.
5225  */
5226  windows->map_info=XAllocStandardColormap();
5227  windows->icon_map=XAllocStandardColormap();
5228  if ((windows->map_info == (XStandardColormap *) NULL) ||
5229  (windows->icon_map == (XStandardColormap *) NULL))
5230  ThrowXWindowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed",
5231  "...");
5232  windows->map_info->colormap=(Colormap) NULL;
5233  windows->icon_map->colormap=(Colormap) NULL;
5234  windows->pixel_info->pixels=(unsigned long *) NULL;
5235  windows->pixel_info->annotate_context=(GC) NULL;
5236  windows->pixel_info->highlight_context=(GC) NULL;
5237  windows->pixel_info->widget_context=(GC) NULL;
5238  windows->font_info=(XFontStruct *) NULL;
5239  windows->icon_pixel->annotate_context=(GC) NULL;
5240  windows->icon_pixel->pixels=(unsigned long *) NULL;
5241  /*
5242  Allocate visual.
5243  */
5244  *windows->icon_resources=(*resource_info);
5245  windows->icon_resources->visual_type=(char *) "default";
5246  windows->icon_resources->colormap=SharedColormap;
5247  windows->visual_info=
5248  XBestVisualInfo(display,windows->map_info,resource_info);
5249  windows->icon_visual=
5250  XBestVisualInfo(display,windows->icon_map,windows->icon_resources);
5251  if ((windows->visual_info == (XVisualInfo *) NULL) ||
5252  (windows->icon_visual == (XVisualInfo *) NULL))
5253  ThrowXWindowFatalException(XServerFatalError,"UnableToGetVisual",
5254  resource_info->visual_type);
5255  if ((GetLogEventMask() & X11Event) != 0)
5256  {
5257  (void) LogMagickEvent(X11Event,GetMagickModule(),"Visual:");
5258  (void) LogMagickEvent(X11Event,GetMagickModule()," visual id: 0x%lx",
5259  windows->visual_info->visualid);
5260  (void) LogMagickEvent(X11Event,GetMagickModule()," class: %s",
5261  XVisualClassName(windows->visual_info->klass));
5262  (void) LogMagickEvent(X11Event,GetMagickModule()," depth: %d planes",
5263  windows->visual_info->depth);
5264  (void) LogMagickEvent(X11Event,GetMagickModule(),
5265  " size of colormap: %d entries",windows->visual_info->colormap_size);
5266  (void) LogMagickEvent(X11Event,GetMagickModule(),
5267  " red, green, blue masks: 0x%lx 0x%lx 0x%lx",
5268  windows->visual_info->red_mask,windows->visual_info->green_mask,
5269  windows->visual_info->blue_mask);
5270  (void) LogMagickEvent(X11Event,GetMagickModule(),
5271  " significant bits in color: %d bits",
5272  windows->visual_info->bits_per_rgb);
5273  }
5274  /*
5275  Allocate class and manager hints.
5276  */
5277  windows->class_hints=XAllocClassHint();
5278  windows->manager_hints=XAllocWMHints();
5279  if ((windows->class_hints == (XClassHint *) NULL) ||
5280  (windows->manager_hints == (XWMHints *) NULL))
5281  ThrowXWindowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed",
5282  "...");
5283  /*
5284  Determine group leader if we have one.
5285  */
5286  root_window=XRootWindow(display,windows->visual_info->screen);
5287  windows->group_leader.id=(Window) NULL;
5288  if (resource_info->window_group != (char *) NULL)
5289  {
5290  if (isdigit((int) ((unsigned char) *resource_info->window_group)) != 0)
5291  windows->group_leader.id=XWindowByID(display,root_window,(Window)
5292  strtol((char *) resource_info->window_group,(char **) NULL,0));
5293  if (windows->group_leader.id == (Window) NULL)
5294  windows->group_leader.id=
5295  XWindowByName(display,root_window,resource_info->window_group);
5296  }
5297  return(windows);
5298 }
5299 
5300 /*
5301 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5302 % %
5303 % %
5304 % %
5305 % X M a k e C u r s o r %
5306 % %
5307 % %
5308 % %
5309 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5310 %
5311 % XMakeCursor() creates a crosshairs X11 cursor.
5312 %
5313 % The format of the XMakeCursor method is:
5314 %
5315 % Cursor XMakeCursor(Display *display,Window window,Colormap colormap,
5316 % char *background_color,char *foreground_color)
5317 %
5318 % A description of each parameter follows:
5319 %
5320 % o display: Specifies a connection to an X server; returned from
5321 % XOpenDisplay.
5322 %
5323 % o window: Specifies the ID of the window for which the cursor is
5324 % assigned.
5325 %
5326 % o colormap: Specifies the ID of the colormap from which the background
5327 % and foreground color will be retrieved.
5328 %
5329 % o background_color: Specifies the color to use for the cursor background.
5330 %
5331 % o foreground_color: Specifies the color to use for the cursor foreground.
5332 %
5333 */
5334 MagickPrivate Cursor XMakeCursor(Display *display,Window window,
5335  Colormap colormap,char *background_color,char *foreground_color)
5336 {
5337 #define scope_height 17
5338 #define scope_x_hot 8
5339 #define scope_y_hot 8
5340 #define scope_width 17
5341 
5342  static const unsigned char
5343  scope_bits[] =
5344  {
5345  0x80, 0x03, 0x00, 0x80, 0x02, 0x00, 0x80, 0x02, 0x00, 0x80, 0x02,
5346  0x00, 0x80, 0x02, 0x00, 0x80, 0x02, 0x00, 0x80, 0x02, 0x00, 0x7f,
5347  0xfc, 0x01, 0x01, 0x00, 0x01, 0x7f, 0xfc, 0x01, 0x80, 0x02, 0x00,
5348  0x80, 0x02, 0x00, 0x80, 0x02, 0x00, 0x80, 0x02, 0x00, 0x80, 0x02,
5349  0x00, 0x80, 0x02, 0x00, 0x80, 0x03, 0x00
5350  },
5351  scope_mask_bits[] =
5352  {
5353  0xc0, 0x07, 0x00, 0xc0, 0x07, 0x00, 0xc0, 0x06, 0x00, 0xc0, 0x06,
5354  0x00, 0xc0, 0x06, 0x00, 0xc0, 0x06, 0x00, 0xff, 0xfe, 0x01, 0x7f,
5355  0xfc, 0x01, 0x03, 0x80, 0x01, 0x7f, 0xfc, 0x01, 0xff, 0xfe, 0x01,
5356  0xc0, 0x06, 0x00, 0xc0, 0x06, 0x00, 0xc0, 0x06, 0x00, 0xc0, 0x06,
5357  0x00, 0xc0, 0x07, 0x00, 0xc0, 0x07, 0x00
5358  };
5359 
5360  Cursor
5361  cursor;
5362 
5363  Pixmap
5364  mask,
5365  source;
5366 
5367  XColor
5368  background,
5369  foreground;
5370 
5371  assert(display != (Display *) NULL);
5372  assert(window != (Window) NULL);
5373  assert(colormap != (Colormap) NULL);
5374  assert(background_color != (char *) NULL);
5375  assert(foreground_color != (char *) NULL);
5376  if (IsEventLogging() != MagickFalse)
5377  (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",background_color);
5378  source=XCreateBitmapFromData(display,window,(char *) scope_bits,scope_width,
5379  scope_height);
5380  mask=XCreateBitmapFromData(display,window,(char *) scope_mask_bits,
5381  scope_width,scope_height);
5382  if ((source == (Pixmap) NULL) || (mask == (Pixmap) NULL))
5383  {
5384  ThrowXWindowException(XServerError,"UnableToCreatePixmap","...");
5385  return((Cursor) NULL);
5386  }
5387  (void) XParseColor(display,colormap,background_color,&background);
5388  (void) XParseColor(display,colormap,foreground_color,&foreground);
5389  cursor=XCreatePixmapCursor(display,source,mask,&foreground,&background,
5390  scope_x_hot,scope_y_hot);
5391  (void) XFreePixmap(display,source);
5392  (void) XFreePixmap(display,mask);
5393  return(cursor);
5394 }
5395 
5396 /*
5397 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5398 % %
5399 % %
5400 % %
5401 % X M a k e I m a g e %
5402 % %
5403 % %
5404 % %
5405 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5406 %
5407 % XMakeImage() creates an X11 image. If the image size differs from the X11
5408 % image size, the image is first resized.
5409 %
5410 % The format of the XMakeImage method is:
5411 %
5412 % MagickBooleanType XMakeImage(Display *display,
5413 % const XResourceInfo *resource_info,XWindowInfo *window,Image *image,
5414 % unsigned int width,unsigned int height,ExceptionInfo *exception)
5415 %
5416 % A description of each parameter follows:
5417 %
5418 % o display: Specifies a connection to an X server; returned from
5419 % XOpenDisplay.
5420 %
5421 % o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
5422 %
5423 % o window: Specifies a pointer to a XWindowInfo structure.
5424 %
5425 % o image: the image.
5426 %
5427 % o width: Specifies the width in pixels of the rectangular area to
5428 % display.
5429 %
5430 % o height: Specifies the height in pixels of the rectangular area to
5431 % display.
5432 %
5433 % o exception: return any errors or warnings in this structure.
5434 %
5435 */
5436 MagickPrivate MagickBooleanType XMakeImage(Display *display,
5437  const XResourceInfo *resource_info,XWindowInfo *window,Image *image,
5438  unsigned int width,unsigned int height,ExceptionInfo *exception)
5439 {
5440 #define CheckOverflowException(length,width,height) \
5441  (((height) != 0) && ((length)/((size_t) height) != ((size_t) width)))
5442 
5443  int
5444  depth,
5445  format;
5446 
5447  XImage
5448  *matte_image,
5449  *ximage;
5450 
5451  assert(display != (Display *) NULL);
5452  assert(resource_info != (XResourceInfo *) NULL);
5453  assert(window != (XWindowInfo *) NULL);
5454  assert(width != 0);
5455  assert(height != 0);
5456  if (IsEventLogging() != MagickFalse)
5457  (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
5458  if ((window->width == 0) || (window->height == 0))
5459  return(MagickFalse);
5460  /*
5461  Apply user transforms to the image.
5462  */
5463  (void) XCheckDefineCursor(display,window->id,window->busy_cursor);
5464  (void) XFlush(display);
5465  depth=(int) window->depth;
5466  if (window->destroy)
5467  window->image=DestroyImage(window->image);
5468  window->image=image;
5469  window->destroy=MagickFalse;
5470  if (window->image != (Image *) NULL)
5471  {
5472  if (window->crop_geometry != (char *) NULL)
5473  {
5474  Image
5475  *crop_image;
5476 
5478  crop_info;
5479 
5480  /*
5481  Crop image.
5482  */
5483  window->image->page.x=0;
5484  window->image->page.y=0;
5485  (void) ParsePageGeometry(window->image,window->crop_geometry,
5486  &crop_info,exception);
5487  crop_image=CropImage(window->image,&crop_info,exception);
5488  if (crop_image != (Image *) NULL)
5489  {
5490  if (window->image != image)
5491  window->image=DestroyImage(window->image);
5492  window->image=crop_image;
5493  window->destroy=MagickTrue;
5494  }
5495  }
5496  if ((width != (unsigned int) window->image->columns) ||
5497  (height != (unsigned int) window->image->rows))
5498  {
5499  Image
5500  *resize_image;
5501 
5502  /*
5503  Resize image.
5504  */
5505  resize_image=NewImageList();
5506  if ((window->pixel_info->colors == 0) &&
5507  (window->image->rows > (unsigned long) XDisplayHeight(display,window->screen)) &&
5508  (window->image->columns > (unsigned long) XDisplayWidth(display,window->screen)))
5509  resize_image=ResizeImage(window->image,width,height,
5510  image->filter,exception);
5511  else
5512  {
5513  if (window->image->storage_class == PseudoClass)
5514  resize_image=SampleImage(window->image,width,height,
5515  exception);
5516  else
5517  resize_image=ThumbnailImage(window->image,width,height,
5518  exception);
5519  }
5520  if (resize_image != (Image *) NULL)
5521  {
5522  if (window->image != image)
5523  window->image=DestroyImage(window->image);
5524  window->image=resize_image;
5525  window->destroy=MagickTrue;
5526  }
5527  }
5528  width=(unsigned int) window->image->columns;
5529  assert((size_t) width == window->image->columns);
5530  height=(unsigned int) window->image->rows;
5531  assert((size_t) height == window->image->rows);
5532  }
5533  /*
5534  Create X image.
5535  */
5536  ximage=(XImage *) NULL;
5537  format=(depth == 1) ? XYBitmap : ZPixmap;
5538 #if defined(MAGICKCORE_HAVE_SHARED_MEMORY)
5539  if (window->shared_memory != MagickFalse)
5540  {
5541  size_t
5542  length;
5543 
5544  XShmSegmentInfo
5545  *segment_info;
5546 
5547  segment_info=(XShmSegmentInfo *) window->segment_info;
5548  segment_info[1].shmid=(-1);
5549  segment_info[1].shmaddr=(char *) NULL;
5550  ximage=XShmCreateImage(display,window->visual,(unsigned int) depth,format,
5551  (char *) NULL,&segment_info[1],width,height);
5552  length=0;
5553  if (ximage == (XImage *) NULL)
5554  window->shared_memory=MagickFalse;
5555  else
5556  {
5557  length=(size_t) (ximage->bytes_per_line*ximage->height);
5558  if (CheckOverflowException(length,ximage->bytes_per_line,ximage->height))
5559  window->shared_memory=MagickFalse;
5560  }
5561  if (window->shared_memory != MagickFalse)
5562  segment_info[1].shmid=shmget(IPC_PRIVATE,length,IPC_CREAT | 0777);
5563  if (window->shared_memory != MagickFalse)
5564  segment_info[1].shmaddr=(char *) shmat(segment_info[1].shmid,0,0);
5565  if (segment_info[1].shmid < 0)
5566  window->shared_memory=MagickFalse;
5567  if (window->shared_memory != MagickFalse)
5568  (void) shmctl(segment_info[1].shmid,IPC_RMID,0);
5569  else
5570  {
5571  if (ximage != (XImage *) NULL)
5572  XDestroyImage(ximage);
5573  ximage=(XImage *) NULL;
5574  if (segment_info[1].shmaddr)
5575  {
5576  (void) shmdt(segment_info[1].shmaddr);
5577  segment_info[1].shmaddr=(char *) NULL;
5578  }
5579  if (segment_info[1].shmid >= 0)
5580  {
5581  (void) shmctl(segment_info[1].shmid,IPC_RMID,0);
5582  segment_info[1].shmid=(-1);
5583  }
5584  }
5585  }
5586 #endif
5587  /*
5588  Allocate X image pixel data.
5589  */
5590 #if defined(MAGICKCORE_HAVE_SHARED_MEMORY)
5591  if (window->shared_memory)
5592  {
5593  Status
5594  status;
5595 
5596  XShmSegmentInfo
5597  *segment_info;
5598 
5599  (void) XSync(display,MagickFalse);
5600  xerror_alert=MagickFalse;
5601  segment_info=(XShmSegmentInfo *) window->segment_info;
5602  ximage->data=segment_info[1].shmaddr;
5603  segment_info[1].readOnly=MagickFalse;
5604  status=XShmAttach(display,&segment_info[1]);
5605  if (status != False)
5606  (void) XSync(display,MagickFalse);
5607  if ((status == False) || (xerror_alert != MagickFalse))
5608  {
5609  window->shared_memory=MagickFalse;
5610  if (status != False)
5611  XShmDetach(display,&segment_info[1]);
5612  ximage->data=NULL;
5613  XDestroyImage(ximage);
5614  ximage=(XImage *) NULL;
5615  if (segment_info[1].shmid >= 0)
5616  {
5617  if (segment_info[1].shmaddr != NULL)
5618  (void) shmdt(segment_info[1].shmaddr);
5619  (void) shmctl(segment_info[1].shmid,IPC_RMID,0);
5620  segment_info[1].shmid=(-1);
5621  segment_info[1].shmaddr=(char *) NULL;
5622  }
5623  }
5624  }
5625 #endif
5626  if (window->shared_memory == MagickFalse)
5627  ximage=XCreateImage(display,window->visual,(unsigned int) depth,format,0,
5628  (char *) NULL,width,height,XBitmapPad(display),0);
5629  if (ximage == (XImage *) NULL)
5630  {
5631  /*
5632  Unable to create X image.
5633  */
5634  (void) XCheckDefineCursor(display,window->id,window->cursor);
5635  return(MagickFalse);
5636  }
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);
5646  (void) LogMagickEvent(X11Event,GetMagickModule(),
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);
5655  (void) LogMagickEvent(X11Event,GetMagickModule(),
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 #if defined(MAGICKCORE_HAVE_SHARED_MEMORY)
5694  if (window->segment_info != (XShmSegmentInfo *) NULL)
5695  {
5696  XShmSegmentInfo
5697  *segment_info;
5698 
5699  segment_info=(XShmSegmentInfo *) window->segment_info;
5700  if (segment_info[0].shmid >= 0)
5701  {
5702  (void) XSync(display,MagickFalse);
5703  (void) XShmDetach(display,&segment_info[0]);
5704  (void) XSync(display,MagickFalse);
5705  if (segment_info[0].shmaddr != (char *) NULL)
5706  (void) shmdt(segment_info[0].shmaddr);
5707  (void) shmctl(segment_info[0].shmid,IPC_RMID,0);
5708  segment_info[0].shmid=(-1);
5709  segment_info[0].shmaddr=(char *) NULL;
5710  window->ximage->data=(char *) NULL;
5711  }
5712  }
5713 #endif
5714  if (window->ximage->data != (char *) NULL)
5715  free(window->ximage->data);
5716  window->ximage->data=(char *) NULL;
5717  XDestroyImage(window->ximage);
5718  window->ximage=(XImage *) NULL;
5719  }
5720 #if defined(MAGICKCORE_HAVE_SHARED_MEMORY)
5721  if (window->segment_info != (XShmSegmentInfo *) NULL)
5722  {
5723  XShmSegmentInfo
5724  *segment_info;
5725 
5726  segment_info=(XShmSegmentInfo *) window->segment_info;
5727  segment_info[0]=segment_info[1];
5728  }
5729 #endif
5730  window->ximage=ximage;
5731  matte_image=(XImage *) NULL;
5732  if ((window->shape != MagickFalse) && (window->image != (Image *) NULL))
5733  if ((window->image->alpha_trait != UndefinedPixelTrait) &&
5734  ((int) width <= XDisplayWidth(display,window->screen)) &&
5735  ((int) height <= XDisplayHeight(display,window->screen)))
5736  {
5737  /*
5738  Create matte image.
5739  */
5740  matte_image=XCreateImage(display,window->visual,1,XYBitmap,0,
5741  (char *) NULL,width,height,XBitmapPad(display),0);
5742  if ((GetLogEventMask() & X11Event) != 0)
5743  {
5744  (void) LogMagickEvent(X11Event,GetMagickModule(),"Matte Image:");
5745  (void) LogMagickEvent(X11Event,GetMagickModule(),
5746  " width, height: %dx%d",matte_image->width,matte_image->height);
5747  }
5748  if (matte_image != (XImage *) NULL)
5749  {
5750  /*
5751  Allocate matte image pixel data.
5752  */
5753  matte_image->data=(char *) malloc((size_t)
5754  (matte_image->bytes_per_line*matte_image->depth*
5755  matte_image->height));
5756  if (matte_image->data == (char *) NULL)
5757  {
5758  XDestroyImage(matte_image);
5759  matte_image=(XImage *) NULL;
5760  }
5761  }
5762  }
5763  if (window->matte_image != (XImage *) NULL)
5764  {
5765  /*
5766  Free matte image.
5767  */
5768  if (window->matte_image->data != (char *) NULL)
5769  free(window->matte_image->data);
5770  window->matte_image->data=(char *) NULL;
5771  XDestroyImage(window->matte_image);
5772  window->matte_image=(XImage *) NULL;
5773  }
5774  window->matte_image=matte_image;
5775  if (window->matte_pixmap != (Pixmap) NULL)
5776  {
5777  (void) XFreePixmap(display,window->matte_pixmap);
5778  window->matte_pixmap=(Pixmap) NULL;
5779 #if defined(MAGICKCORE_HAVE_SHAPE)
5780  if (window->shape != MagickFalse)
5781  XShapeCombineMask(display,window->id,ShapeBounding,0,0,None,ShapeSet);
5782 #endif
5783  }
5784  window->stasis=MagickFalse;
5785  /*
5786  Convert pixels to X image data.
5787  */
5788  if (window->image != (Image *) NULL)
5789  {
5790  if ((ximage->byte_order == LSBFirst) || ((ximage->format == XYBitmap) &&
5791  (ximage->bitmap_bit_order == LSBFirst)))
5792  XMakeImageLSBFirst(resource_info,window,window->image,ximage,
5793  matte_image,exception);
5794  else
5795  XMakeImageMSBFirst(resource_info,window,window->image,ximage,
5796  matte_image,exception);
5797  }
5798  if (window->matte_image != (XImage *) NULL)
5799  {
5800  /*
5801  Create matte pixmap.
5802  */
5803  window->matte_pixmap=XCreatePixmap(display,window->id,width,height,1);
5804  if (window->matte_pixmap != (Pixmap) NULL)
5805  {
5806  GC
5807  graphics_context;
5808 
5809  XGCValues
5810  context_values;
5811 
5812  /*
5813  Copy matte image to matte pixmap.
5814  */
5815  context_values.background=0;
5816  context_values.foreground=1;
5817  graphics_context=XCreateGC(display,window->matte_pixmap,
5818  (size_t) (GCBackground | GCForeground),&context_values);
5819  (void) XPutImage(display,window->matte_pixmap,graphics_context,
5820  window->matte_image,0,0,0,0,width,height);
5821  (void) XFreeGC(display,graphics_context);
5822 #if defined(MAGICKCORE_HAVE_SHAPE)
5823  if (window->shape != MagickFalse)
5824  XShapeCombineMask(display,window->id,ShapeBounding,0,0,
5825  window->matte_pixmap,ShapeSet);
5826 #endif
5827  }
5828  }
5829  (void) XMakePixmap(display,resource_info,window);
5830  /*
5831  Restore cursor.
5832  */
5833  (void) XCheckDefineCursor(display,window->id,window->cursor);
5834  return(MagickTrue);
5835 }
5836 
5837 /*
5838 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5839 % %
5840 % %
5841 % %
5842 + X M a k e I m a g e L S B F i r s t %
5843 % %
5844 % %
5845 % %
5846 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5847 %
5848 % XMakeImageLSBFirst() initializes the pixel data of an X11 Image. The X image
5849 % pixels are copied in least-significant bit and byte first order. The
5850 % server's scanline pad is respected. Rather than using one or two general
5851 % cases, many special cases are found here to help speed up the image
5852 % conversion.
5853 %
5854 % The format of the XMakeImageLSBFirst method is:
5855 %
5856 % void XMakeImageLSBFirst(Display *display,XWindows *windows,
5857 % ExceptionInfo *exception)
5858 %
5859 % A description of each parameter follows:
5860 %
5861 % o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
5862 %
5863 % o window: Specifies a pointer to a XWindowInfo structure.
5864 %
5865 % o image: the image.
5866 %
5867 % o ximage: Specifies a pointer to a XImage structure; returned from
5868 % XCreateImage.
5869 %
5870 % o matte_image: Specifies a pointer to a XImage structure; returned from
5871 % XCreateImage.
5872 %
5873 % o exception: return any errors or warnings in this structure.
5874 %
5875 */
5876 static void XMakeImageLSBFirst(const XResourceInfo *resource_info,
5877  const XWindowInfo *window,Image *image,XImage *ximage,XImage *matte_image,
5878  ExceptionInfo *exception)
5879 {
5880  CacheView
5881  *canvas_view;
5882 
5883  Image
5884  *canvas;
5885 
5886  int
5887  y;
5888 
5889  const Quantum
5890  *p;
5891 
5892  int
5893  x;
5894 
5895  unsigned char
5896  *q;
5897 
5898  unsigned char
5899  bit,
5900  byte;
5901 
5902  unsigned int
5903  scanline_pad;
5904 
5905  unsigned long
5906  pixel,
5907  *pixels;
5908 
5909  XStandardColormap
5910  *map_info;
5911 
5912  assert(resource_info != (XResourceInfo *) NULL);
5913  assert(window != (XWindowInfo *) NULL);
5914  assert(image != (Image *) NULL);
5915  if (IsEventLogging() != MagickFalse)
5916  (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
5917  canvas=image;
5918  if ((window->immutable == MagickFalse) &&
5919  (image->storage_class == DirectClass) &&
5920  (image->alpha_trait != UndefinedPixelTrait))
5921  {
5922  char
5923  size[MagickPathExtent];
5924 
5925  Image
5926  *pattern;
5927 
5928  ImageInfo
5929  *image_info;
5930 
5931  image_info=AcquireImageInfo();
5932  (void) CopyMagickString(image_info->filename,
5933  resource_info->image_info->texture != (char *) NULL ?
5934  resource_info->image_info->texture : "pattern:checkerboard",
5935  MagickPathExtent);
5936  (void) FormatLocaleString(size,MagickPathExtent,"%.20gx%.20g",(double)
5937  image->columns,(double) image->rows);
5938  image_info->size=ConstantString(size);
5939  pattern=ReadImage(image_info,exception);
5940  image_info=DestroyImageInfo(image_info);
5941  if (pattern != (Image *) NULL)
5942  {
5943  canvas=CloneImage(image,0,0,MagickTrue,exception);
5944  if (canvas == (Image *) NULL)
5945  return;
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])) < ((double) 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+=(ptrdiff_t) GetPixelChannels(canvas);
6004  }
6005  if (bit != 0)
6006  *q=byte >> (8-bit);
6007  q+=(ptrdiff_t) 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+=(ptrdiff_t) GetPixelChannels(canvas);
6061  }
6062  q+=(ptrdiff_t) 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+=(ptrdiff_t) GetPixelChannels(canvas);
6101  }
6102  q+=(ptrdiff_t) 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+=(ptrdiff_t) GetPixelChannels(canvas);
6129  }
6130  q+=(ptrdiff_t) 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+=(ptrdiff_t) GetPixelChannels(canvas);
6161  }
6162  q+=(ptrdiff_t) 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+=(ptrdiff_t) GetPixelChannels(canvas);
6218  }
6219  q+=(ptrdiff_t) 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+=(ptrdiff_t) GetPixelChannels(canvas);
6259  }
6260  q+=(ptrdiff_t) 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+=(ptrdiff_t) GetPixelChannels(canvas);
6287  }
6288  q+=(ptrdiff_t) 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+=(ptrdiff_t) 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+=(ptrdiff_t) 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+=(ptrdiff_t) 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+=(ptrdiff_t) 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+=(ptrdiff_t) GetPixelChannels(canvas);
6408  }
6409  q+=(ptrdiff_t) 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+=(ptrdiff_t) GetPixelChannels(canvas);
6444  }
6445  if (bit != 0)
6446  *q=byte >> (8-bit);
6447  q+=(ptrdiff_t) 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 
6516  unsigned char
6517  bit,
6518  byte;
6519 
6520  unsigned int
6521  scanline_pad;
6522 
6523  unsigned long
6524  pixel,
6525  *pixels;
6526 
6527  XStandardColormap
6528  *map_info;
6529 
6530  assert(resource_info != (XResourceInfo *) NULL);
6531  assert(window != (XWindowInfo *) NULL);
6532  assert(image != (Image *) NULL);
6533  if (IsEventLogging() != MagickFalse)
6534  (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
6535  canvas=image;
6536  if ((window->immutable != MagickFalse) &&
6537  (image->storage_class == DirectClass) &&
6538  (image->alpha_trait != UndefinedPixelTrait))
6539  {
6540  char
6541  size[MagickPathExtent];
6542 
6543  Image
6544  *pattern;
6545 
6546  ImageInfo
6547  *image_info;
6548 
6549  image_info=AcquireImageInfo();
6550  (void) CopyMagickString(image_info->filename,
6551  resource_info->image_info->texture != (char *) NULL ?
6552  resource_info->image_info->texture : "pattern:checkerboard",
6553  MagickPathExtent);
6554  (void) FormatLocaleString(size,MagickPathExtent,"%.20gx%.20g",(double)
6555  image->columns,(double) image->rows);
6556  image_info->size=ConstantString(size);
6557  pattern=ReadImage(image_info,exception);
6558  image_info=DestroyImageInfo(image_info);
6559  if (pattern != (Image *) NULL)
6560  {
6561  canvas=CloneImage(image,0,0,MagickTrue,exception);
6562  if (canvas == (Image *) NULL)
6563  return;
6564  (void) CompositeImage(canvas,pattern,DstOverCompositeOp,MagickFalse,
6565  0,0,exception);
6566  pattern=DestroyImage(pattern);
6567  }
6568  }
6569  scanline_pad=(unsigned int) (ximage->bytes_per_line-((ximage->width*
6570  ximage->bits_per_pixel) >> 3));
6571  map_info=window->map_info;
6572  pixels=window->pixel_info->pixels;
6573  q=(unsigned char *) ximage->data;
6574  x=0;
6575  canvas_view=AcquireVirtualCacheView(canvas,exception);
6576  if (ximage->format == XYBitmap)
6577  {
6578  unsigned short
6579  polarity;
6580 
6581  unsigned char
6582  background,
6583  foreground;
6584 
6585  /*
6586  Convert canvas to big-endian bitmap.
6587  */
6588  background=(unsigned char)
6589  (XPixelIntensity(&window->pixel_info->foreground_color) <
6590  XPixelIntensity(&window->pixel_info->background_color) ? 0x01 : 0x00);
6591  foreground=(unsigned char)
6592  (XPixelIntensity(&window->pixel_info->background_color) <
6593  XPixelIntensity(&window->pixel_info->foreground_color) ? 0x01 : 0x00);
6594  polarity=(unsigned short) ((GetPixelInfoIntensity(image,
6595  &canvas->colormap[0])) < ((double) QuantumRange/2.0) ? 1 : 0);
6596  if (canvas->colors == 2)
6597  polarity=GetPixelInfoIntensity(image,&canvas->colormap[0]) <
6598  GetPixelInfoIntensity(image,&canvas->colormap[1]);
6599  for (y=0; y < (int) canvas->rows; y++)
6600  {
6601  p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,canvas->columns,1,
6602  exception);
6603  if (p == (const Quantum *) NULL)
6604  break;
6605  bit=0;
6606  byte=0;
6607  for (x=(int) canvas->columns-1; x >= 0; x--)
6608  {
6609  byte<<=1;
6610  if (GetPixelIndex(canvas,p) == (Quantum) polarity)
6611  byte|=foreground;
6612  else
6613  byte|=background;
6614  bit++;
6615  if (bit == 8)
6616  {
6617  *q++=byte;
6618  bit=0;
6619  byte=0;
6620  }
6621  p+=(ptrdiff_t) GetPixelChannels(canvas);
6622  }
6623  if (bit != 0)
6624  *q=byte << (8-bit);
6625  q+=(ptrdiff_t) scanline_pad;
6626  }
6627  }
6628  else
6629  if (window->pixel_info->colors != 0)
6630  switch (ximage->bits_per_pixel)
6631  {
6632  case 2:
6633  {
6634  unsigned int
6635  nibble;
6636 
6637  /*
6638  Convert to 2 bit color-mapped X canvas.
6639  */
6640  for (y=0; y < (int) canvas->rows; y++)
6641  {
6642  p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
6643  canvas->columns,1,exception);
6644  if (p == (const Quantum *) NULL)
6645  break;
6646  nibble=0;
6647  for (x=0; x < (int) canvas->columns; x++)
6648  {
6649  pixel=pixels[(ssize_t)
6650  GetPixelIndex(canvas,p)] & 0xf;
6651  switch (nibble)
6652  {
6653  case 0:
6654  {
6655  *q=(unsigned char) (pixel << 6);
6656  nibble++;
6657  break;
6658  }
6659  case 1:
6660  {
6661  *q|=(unsigned char) (pixel << 4);
6662  nibble++;
6663  break;
6664  }
6665  case 2:
6666  {
6667  *q|=(unsigned char) (pixel << 2);
6668  nibble++;
6669  break;
6670  }
6671  case 3:
6672  {
6673  *q|=(unsigned char) pixel;
6674  q++;
6675  nibble=0;
6676  break;
6677  }
6678  }
6679  p+=(ptrdiff_t) GetPixelChannels(canvas);
6680  }
6681  q+=(ptrdiff_t) scanline_pad;
6682  }
6683  break;
6684  }
6685  case 4:
6686  {
6687  unsigned int
6688  nibble;
6689 
6690  /*
6691  Convert to 4 bit color-mapped X canvas.
6692  */
6693  for (y=0; y < (int) canvas->rows; y++)
6694  {
6695  p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
6696  canvas->columns,1,exception);
6697  if (p == (const Quantum *) NULL)
6698  break;
6699  nibble=0;
6700  for (x=0; x < (int) canvas->columns; x++)
6701  {
6702  pixel=pixels[(ssize_t)
6703  GetPixelIndex(canvas,p)] & 0xf;
6704  switch (nibble)
6705  {
6706  case 0:
6707  {
6708  *q=(unsigned char) (pixel << 4);
6709  nibble++;
6710  break;
6711  }
6712  case 1:
6713  {
6714  *q|=(unsigned char) pixel;
6715  q++;
6716  nibble=0;
6717  break;
6718  }
6719  }
6720  p+=(ptrdiff_t) GetPixelChannels(canvas);
6721  }
6722  q+=(ptrdiff_t) scanline_pad;
6723  }
6724  break;
6725  }
6726  case 6:
6727  case 8:
6728  {
6729  /*
6730  Convert to 8 bit color-mapped X canvas.
6731  */
6732  if ((resource_info->color_recovery != MagickFalse) &&
6733  (resource_info->quantize_info->dither_method != NoDitherMethod))
6734  {
6735  XDitherImage(canvas,ximage,exception);
6736  break;
6737  }
6738  for (y=0; y < (int) canvas->rows; y++)
6739  {
6740  p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
6741  canvas->columns,1,exception);
6742  if (p == (const Quantum *) NULL)
6743  break;
6744  for (x=0; x < (int) canvas->columns; x++)
6745  {
6746  pixel=pixels[(ssize_t) GetPixelIndex(canvas,p)];
6747  *q++=(unsigned char) pixel;
6748  p+=(ptrdiff_t) GetPixelChannels(canvas);
6749  }
6750  q+=(ptrdiff_t) scanline_pad;
6751  }
6752  break;
6753  }
6754  default:
6755  {
6756  int
6757  k;
6758 
6759  unsigned int
6760  bytes_per_pixel;
6761 
6762  unsigned char
6763  channel[sizeof(size_t)];
6764 
6765  /*
6766  Convert to 8 bit color-mapped X canvas.
6767  */
6768  bytes_per_pixel=(unsigned int) (ximage->bits_per_pixel >> 3);
6769  for (y=0; y < (int) canvas->rows; y++)
6770  {
6771  p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
6772  canvas->columns,1,exception);
6773  if (p == (const Quantum *) NULL)
6774  break;
6775  for (x=0; x < (int) canvas->columns; x++)
6776  {
6777  pixel=pixels[(ssize_t)
6778  GetPixelIndex(canvas,p)];
6779  for (k=(int) bytes_per_pixel-1; k >= 0; k--)
6780  {
6781  channel[k]=(unsigned char) pixel;
6782  pixel>>=8;
6783  }
6784  for (k=0; k < (int) bytes_per_pixel; k++)
6785  *q++=channel[k];
6786  p+=(ptrdiff_t) GetPixelChannels(canvas);
6787  }
6788  q+=(ptrdiff_t) scanline_pad;
6789  }
6790  break;
6791  }
6792  }
6793  else
6794  switch (ximage->bits_per_pixel)
6795  {
6796  case 2:
6797  {
6798  unsigned int
6799  nibble;
6800 
6801  /*
6802  Convert to 4 bit continuous-tone X canvas.
6803  */
6804  for (y=0; y < (int) canvas->rows; y++)
6805  {
6806  p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
6807  canvas->columns,1,exception);
6808  if (p == (const Quantum *) NULL)
6809  break;
6810  nibble=0;
6811  for (x=(int) canvas->columns-1; x >= 0; x--)
6812  {
6813  pixel=XGammaPixel(canvas,map_info,p);
6814  pixel&=0xf;
6815  switch (nibble)
6816  {
6817  case 0:
6818  {
6819  *q=(unsigned char) (pixel << 6);
6820  nibble++;
6821  break;
6822  }
6823  case 1:
6824  {
6825  *q|=(unsigned char) (pixel << 4);
6826  nibble++;
6827  break;
6828  }
6829  case 2:
6830  {
6831  *q|=(unsigned char) (pixel << 2);
6832  nibble++;
6833  break;
6834  }
6835  case 3:
6836  {
6837  *q|=(unsigned char) pixel;
6838  q++;
6839  nibble=0;
6840  break;
6841  }
6842  }
6843  p+=(ptrdiff_t) GetPixelChannels(canvas);
6844  }
6845  q+=(ptrdiff_t) scanline_pad;
6846  }
6847  break;
6848  }
6849  case 4:
6850  {
6851  unsigned int
6852  nibble;
6853 
6854  /*
6855  Convert to 4 bit continuous-tone X canvas.
6856  */
6857  for (y=0; y < (int) canvas->rows; y++)
6858  {
6859  p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
6860  canvas->columns,1,exception);
6861  if (p == (const Quantum *) NULL)
6862  break;
6863  nibble=0;
6864  for (x=(int) canvas->columns-1; x >= 0; x--)
6865  {
6866  pixel=XGammaPixel(canvas,map_info,p);
6867  pixel&=0xf;
6868  switch (nibble)
6869  {
6870  case 0:
6871  {
6872  *q=(unsigned char) (pixel << 4);
6873  nibble++;
6874  break;
6875  }
6876  case 1:
6877  {
6878  *q|=(unsigned char) pixel;
6879  q++;
6880  nibble=0;
6881  break;
6882  }
6883  }
6884  p+=(ptrdiff_t) GetPixelChannels(canvas);
6885  }
6886  q+=(ptrdiff_t) scanline_pad;
6887  }
6888  break;
6889  }
6890  case 6:
6891  case 8:
6892  {
6893  /*
6894  Convert to 8 bit continuous-tone X canvas.
6895  */
6896  if ((resource_info->color_recovery != MagickFalse) &&
6897  (resource_info->quantize_info->dither_method != NoDitherMethod))
6898  {
6899  XDitherImage(canvas,ximage,exception);
6900  break;
6901  }
6902  for (y=0; y < (int) canvas->rows; y++)
6903  {
6904  p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
6905  canvas->columns,1,exception);
6906  if (p == (const Quantum *) NULL)
6907  break;
6908  for (x=(int) canvas->columns-1; x >= 0; x--)
6909  {
6910  pixel=XGammaPixel(canvas,map_info,p);
6911  *q++=(unsigned char) pixel;
6912  p+=(ptrdiff_t) GetPixelChannels(canvas);
6913  }
6914  q+=(ptrdiff_t) scanline_pad;
6915  }
6916  break;
6917  }
6918  default:
6919  {
6920  if ((ximage->bits_per_pixel == 32) && (map_info->red_max == 255) &&
6921  (map_info->green_max == 255) && (map_info->blue_max == 255) &&
6922  (map_info->red_mult == 65536L) && (map_info->green_mult == 256) &&
6923  (map_info->blue_mult == 1))
6924  {
6925  /*
6926  Convert to 32 bit continuous-tone X canvas.
6927  */
6928  for (y=0; y < (int) canvas->rows; y++)
6929  {
6930  p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
6931  canvas->columns,1,exception);
6932  if (p == (const Quantum *) NULL)
6933  break;
6934  if ((red_gamma != 1.0) || (green_gamma != 1.0) ||
6935  (blue_gamma != 1.0))
6936  {
6937  /*
6938  Gamma correct canvas.
6939  */
6940  for (x=(int) canvas->columns-1; x >= 0; x--)
6941  {
6942  *q++=0;
6943  *q++=ScaleQuantumToChar(XRedGamma(
6944  GetPixelRed(canvas,p)));
6945  *q++=ScaleQuantumToChar(XGreenGamma(
6946  GetPixelGreen(canvas,p)));
6947  *q++=ScaleQuantumToChar(XBlueGamma(
6948  GetPixelBlue(canvas,p)));
6949  p+=(ptrdiff_t) GetPixelChannels(canvas);
6950  }
6951  continue;
6952  }
6953  for (x=(int) canvas->columns-1; x >= 0; x--)
6954  {
6955  *q++=0;
6956  *q++=ScaleQuantumToChar((Quantum) GetPixelRed(canvas,p));
6957  *q++=ScaleQuantumToChar((Quantum) GetPixelGreen(canvas,p));
6958  *q++=ScaleQuantumToChar((Quantum) GetPixelBlue(canvas,p));
6959  p+=(ptrdiff_t) GetPixelChannels(canvas);
6960  }
6961  }
6962  }
6963  else
6964  if ((ximage->bits_per_pixel == 32) && (map_info->red_max == 255) &&
6965  (map_info->green_max == 255) && (map_info->blue_max == 255) &&
6966  (map_info->red_mult == 1) && (map_info->green_mult == 256) &&
6967  (map_info->blue_mult == 65536L))
6968  {
6969  /*
6970  Convert to 32 bit continuous-tone X canvas.
6971  */
6972  for (y=0; y < (int) canvas->rows; y++)
6973  {
6974  p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
6975  canvas->columns,1,exception);
6976  if (p == (const Quantum *) NULL)
6977  break;
6978  if ((red_gamma != 1.0) || (green_gamma != 1.0) ||
6979  (blue_gamma != 1.0))
6980  {
6981  /*
6982  Gamma correct canvas.
6983  */
6984  for (x=(int) canvas->columns-1; x >= 0; x--)
6985  {
6986  *q++=0;
6987  *q++=ScaleQuantumToChar(XBlueGamma(
6988  GetPixelBlue(canvas,p)));
6989  *q++=ScaleQuantumToChar(XGreenGamma(
6990  GetPixelGreen(canvas,p)));
6991  *q++=ScaleQuantumToChar(XRedGamma(
6992  GetPixelRed(canvas,p)));
6993  p+=(ptrdiff_t) GetPixelChannels(canvas);
6994  }
6995  continue;
6996  }
6997  for (x=(int) canvas->columns-1; x >= 0; x--)
6998  {
6999  *q++=0;
7000  *q++=ScaleQuantumToChar((Quantum) GetPixelBlue(canvas,p));
7001  *q++=ScaleQuantumToChar((Quantum) GetPixelGreen(canvas,p));
7002  *q++=ScaleQuantumToChar((Quantum) GetPixelRed(canvas,p));
7003  p+=(ptrdiff_t) GetPixelChannels(canvas);
7004  }
7005  }
7006  }
7007  else
7008  {
7009  int
7010  k;
7011 
7012  unsigned int
7013  bytes_per_pixel;
7014 
7015  unsigned char
7016  channel[sizeof(size_t)];
7017 
7018  /*
7019  Convert to multi-byte continuous-tone X canvas.
7020  */
7021  bytes_per_pixel=(unsigned int) (ximage->bits_per_pixel >> 3);
7022  for (y=0; y < (int) canvas->rows; y++)
7023  {
7024  p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
7025  canvas->columns,1,exception);
7026  if (p == (const Quantum *) NULL)
7027  break;
7028  for (x=(int) canvas->columns-1; x >= 0; x--)
7029  {
7030  pixel=XGammaPixel(canvas,map_info,p);
7031  for (k=(int) bytes_per_pixel-1; k >= 0; k--)
7032  {
7033  channel[k]=(unsigned char) pixel;
7034  pixel>>=8;
7035  }
7036  for (k=0; k < (int) bytes_per_pixel; k++)
7037  *q++=channel[k];
7038  p+=(ptrdiff_t) GetPixelChannels(canvas);
7039  }
7040  q+=(ptrdiff_t) scanline_pad;
7041  }
7042  }
7043  break;
7044  }
7045  }
7046  if (matte_image != (XImage *) NULL)
7047  {
7048  /*
7049  Initialize matte canvas.
7050  */
7051  scanline_pad=(unsigned int) (matte_image->bytes_per_line-
7052  ((matte_image->width*matte_image->bits_per_pixel) >> 3));
7053  q=(unsigned char *) matte_image->data;
7054  for (y=0; y < (int) canvas->rows; y++)
7055  {
7056  p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,canvas->columns,1,
7057  exception);
7058  if (p == (const Quantum *) NULL)
7059  break;
7060  bit=0;
7061  byte=0;
7062  for (x=(int) canvas->columns-1; x >= 0; x--)
7063  {
7064  byte<<=1;
7065  if (GetPixelAlpha(canvas,p) > (QuantumRange/2))
7066  byte|=0x01;
7067  bit++;
7068  if (bit == 8)
7069  {
7070  *q++=byte;
7071  bit=0;
7072  byte=0;
7073  }
7074  p+=(ptrdiff_t) GetPixelChannels(canvas);
7075  }
7076  if (bit != 0)
7077  *q=byte << (8-bit);
7078  q+=(ptrdiff_t) scanline_pad;
7079  }
7080  }
7081  canvas_view=DestroyCacheView(canvas_view);
7082  if (canvas != image)
7083  canvas=DestroyImage(canvas);
7084 }
7085 
7086 /*
7087 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
7088 % %
7089 % %
7090 % %
7091 % X M a k e M a g n i f y I m a g e %
7092 % %
7093 % %
7094 % %
7095 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
7096 %
7097 % XMakeMagnifyImage() magnifies a region of an X image and displays it.
7098 %
7099 % The format of the XMakeMagnifyImage method is:
7100 %
7101 % void XMakeMagnifyImage(Display *display,XWindows *windows,
7102 % ExceptionInfo *exception)
7103 %
7104 % A description of each parameter follows:
7105 %
7106 % o display: Specifies a connection to an X server; returned from
7107 % XOpenDisplay.
7108 %
7109 % o windows: Specifies a pointer to a XWindows structure.
7110 %
7111 % o exception: return any errors or warnings in this structure.
7112 %
7113 */
7114 MagickPrivate void XMakeMagnifyImage(Display *display,XWindows *windows,
7115  ExceptionInfo *exception)
7116 {
7117  char
7118  tuple[MagickPathExtent];
7119 
7120  int
7121  y;
7122 
7123  PixelInfo
7124  pixel;
7125 
7126  int
7127  x;
7128 
7129  ssize_t
7130  i;
7131 
7132  unsigned char
7133  *p,
7134  *q;
7135 
7136  ssize_t
7137  n;
7138 
7139  static unsigned int
7140  previous_magnify = 0;
7141 
7142  static XWindowInfo
7143  magnify_window;
7144 
7145  unsigned int
7146  height,
7147  j,
7148  k,
7149  l,
7150  magnify,
7151  scanline_pad,
7152  width;
7153 
7154  XImage
7155  *ximage;
7156 
7157  /*
7158  Check boundary conditions.
7159  */
7160  assert(display != (Display *) NULL);
7161  assert(windows != (XWindows *) NULL);
7162  if (IsEventLogging() != MagickFalse)
7163  (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
7164  magnify=1;
7165  for (n=1; n < (ssize_t) windows->magnify.data; n++)
7166  magnify<<=1;
7167  while ((magnify*(unsigned int) windows->image.ximage->width) < windows->magnify.width)
7168  magnify<<=1;
7169  while ((magnify*(unsigned int) windows->image.ximage->height) < windows->magnify.height)
7170  magnify<<=1;
7171  while (magnify > windows->magnify.width)
7172  magnify>>=1;
7173  while (magnify > windows->magnify.height)
7174  magnify>>=1;
7175  if (magnify == 0)
7176  {
7177  magnify=1;
7178  if (previous_magnify != 0)
7179  magnify=previous_magnify;
7180  }
7181  if (magnify != previous_magnify)
7182  {
7183  Status
7184  status;
7185 
7186  XTextProperty
7187  window_name;
7188 
7189  /*
7190  New magnify factor: update magnify window name.
7191  */
7192  i=0;
7193  while ((1 << i) <= (int) magnify)
7194  i++;
7195  (void) FormatLocaleString(windows->magnify.name,MagickPathExtent,
7196  "Magnify %.20gX",(double) i);
7197  status=XStringListToTextProperty(&windows->magnify.name,1,&window_name);
7198  if (status != False)
7199  {
7200  XSetWMName(display,windows->magnify.id,&window_name);
7201  XSetWMIconName(display,windows->magnify.id,&window_name);
7202  (void) XFree((void *) window_name.value);
7203  }
7204  }
7205  previous_magnify=magnify;
7206  ximage=windows->image.ximage;
7207  width=(unsigned int) windows->magnify.ximage->width;
7208  height=(unsigned int) windows->magnify.ximage->height;
7209  if ((windows->magnify.x < 0) ||
7210  (windows->magnify.x >= windows->image.ximage->width))
7211  windows->magnify.x=windows->image.ximage->width >> 1;
7212  x=windows->magnify.x-(int) ((width/magnify) >> 1);
7213  if (x < 0)
7214  x=0;
7215  else
7216  if (x > (ximage->width-(int) (width/magnify)))
7217  x=ximage->width-(int) (width/magnify);
7218  if ((windows->magnify.y < 0) ||
7219  (windows->magnify.y >= windows->image.ximage->height))
7220  windows->magnify.y=windows->image.ximage->height >> 1;
7221  y=windows->magnify.y-(int) ((height/magnify) >> 1);
7222  if (y < 0)
7223  y=0;
7224  else
7225  if (y > (ximage->height-(int) (height/magnify)))
7226  y=ximage->height-(int) (height/magnify);
7227  q=(unsigned char *) windows->magnify.ximage->data;
7228  scanline_pad=(unsigned int) (windows->magnify.ximage->bytes_per_line-
7229  (((int) width*windows->magnify.ximage->bits_per_pixel) >> 3));
7230  if (ximage->bits_per_pixel < 8)
7231  {
7232  unsigned char
7233  background,
7234  byte,
7235  foreground,
7236  p_bit,
7237  q_bit;
7238 
7239  unsigned int
7240  plane;
7241 
7242  XPixelInfo
7243  *pixel_info;
7244 
7245  pixel_info=windows->magnify.pixel_info;
7246  switch (ximage->bitmap_bit_order)
7247  {
7248  case LSBFirst:
7249  {
7250  /*
7251  Magnify little-endian bitmap.
7252  */
7253  background=0x00;
7254  foreground=0x80;
7255  if (ximage->format == XYBitmap)
7256  {
7257  background=(unsigned char)
7258  (XPixelIntensity(&pixel_info->foreground_color) <
7259  XPixelIntensity(&pixel_info->background_color) ? 0x80 : 0x00);
7260  foreground=(unsigned char)
7261  (XPixelIntensity(&pixel_info->background_color) <
7262  XPixelIntensity(&pixel_info->foreground_color) ? 0x80 : 0x00);
7263  if (windows->magnify.depth > 1)
7264  Swap(background,foreground);
7265  }
7266  for (i=0; i < (ssize_t) height; i+=magnify)
7267  {
7268  /*
7269  Propagate pixel magnify rows.
7270  */
7271  for (j=0; j < magnify; j++)
7272  {
7273  p=(unsigned char *) ximage->data+y*ximage->bytes_per_line+
7274  ((x*ximage->bits_per_pixel) >> 3);
7275  p_bit=(unsigned char) (x*ximage->bits_per_pixel) & 0x07;
7276  q_bit=0;
7277  byte=0;
7278  for (k=0; k < width; k+=magnify)
7279  {
7280  /*
7281  Propagate pixel magnify columns.
7282  */
7283  for (l=0; l < magnify; l++)
7284  {
7285  /*
7286  Propagate each bit plane.
7287  */
7288  for (plane=0; (int) plane < ximage->bits_per_pixel; plane++)
7289  {
7290  byte>>=1;
7291  if (*p & (0x01 << (p_bit+plane)))
7292  byte|=foreground;
7293  else
7294  byte|=background;
7295  q_bit++;
7296  if (q_bit == 8)
7297  {
7298  *q++=byte;
7299  q_bit=0;
7300  byte=0;
7301  }
7302  }
7303  }
7304  p_bit+=ximage->bits_per_pixel;
7305  if (p_bit == 8)
7306  {
7307  p++;
7308  p_bit=0;
7309  }
7310  if (q_bit != 0)
7311  *q=byte >> (8-q_bit);
7312  q+=(ptrdiff_t) scanline_pad;
7313  }
7314  }
7315  y++;
7316  }
7317  break;
7318  }
7319  case MSBFirst:
7320  default:
7321  {
7322  /*
7323  Magnify big-endian bitmap.
7324  */
7325  background=0x00;
7326  foreground=0x01;
7327  if (ximage->format == XYBitmap)
7328  {
7329  background=(unsigned char)
7330  (XPixelIntensity(&pixel_info->foreground_color) <
7331  XPixelIntensity(&pixel_info->background_color) ? 0x01 : 0x00);
7332  foreground=(unsigned char)
7333  (XPixelIntensity(&pixel_info->background_color) <
7334  XPixelIntensity(&pixel_info->foreground_color) ? 0x01 : 0x00);
7335  if (windows->magnify.depth > 1)
7336  Swap(background,foreground);
7337  }
7338  for (i=0; i < (ssize_t) height; i+=magnify)
7339  {
7340  /*
7341  Propagate pixel magnify rows.
7342  */
7343  for (j=0; j < magnify; j++)
7344  {
7345  p=(unsigned char *) ximage->data+y*ximage->bytes_per_line+
7346  ((x*ximage->bits_per_pixel) >> 3);
7347  p_bit=(unsigned char) (x*ximage->bits_per_pixel) & 0x07;
7348  q_bit=0;
7349  byte=0;
7350  for (k=0; k < width; k+=magnify)
7351  {
7352  /*
7353  Propagate pixel magnify columns.
7354  */
7355  for (l=0; l < magnify; l++)
7356  {
7357  /*
7358  Propagate each bit plane.
7359  */
7360  for (plane=0; (int) plane < ximage->bits_per_pixel; plane++)
7361  {
7362  byte<<=1;
7363  if (*p & (0x80 >> (p_bit+plane)))
7364  byte|=foreground;
7365  else
7366  byte|=background;
7367  q_bit++;
7368  if (q_bit == 8)
7369  {
7370  *q++=byte;
7371  q_bit=0;
7372  byte=0;
7373  }
7374  }
7375  }
7376  p_bit+=ximage->bits_per_pixel;
7377  if (p_bit == 8)
7378  {
7379  p++;
7380  p_bit=0;
7381  }
7382  if (q_bit != 0)
7383  *q=byte << (8-q_bit);
7384  q+=(ptrdiff_t) scanline_pad;
7385  }
7386  }
7387  y++;
7388  }
7389  break;
7390  }
7391  }
7392  }
7393  else
7394  switch (ximage->bits_per_pixel)
7395  {
7396  case 6:
7397  case 8:
7398  {
7399  /*
7400  Magnify 8 bit X image.
7401  */
7402  for (i=0; i < (ssize_t) height; i+=magnify)
7403  {
7404  /*
7405  Propagate pixel magnify rows.
7406  */
7407  for (j=0; j < magnify; j++)
7408  {
7409  p=(unsigned char *) ximage->data+y*ximage->bytes_per_line+
7410  ((x*ximage->bits_per_pixel) >> 3);
7411  for (k=0; k < width; k+=magnify)
7412  {
7413  /*
7414  Propagate pixel magnify columns.
7415  */
7416  for (l=0; l < magnify; l++)
7417  *q++=(*p);
7418  p++;
7419  }
7420  q+=(ptrdiff_t) scanline_pad;
7421  }
7422  y++;
7423  }
7424  break;
7425  }
7426  default:
7427  {
7428  unsigned int
7429  bytes_per_pixel,
7430  m;
7431 
7432  /*
7433  Magnify multi-byte X image.
7434  */
7435  bytes_per_pixel=(unsigned int) ximage->bits_per_pixel >> 3;
7436  for (i=0; i < (ssize_t) height; i+=magnify)
7437  {
7438  /*
7439  Propagate pixel magnify rows.
7440  */
7441  for (j=0; j < magnify; j++)
7442  {
7443  p=(unsigned char *) ximage->data+y*ximage->bytes_per_line+
7444  ((x*ximage->bits_per_pixel) >> 3);
7445  for (k=0; k < width; k+=magnify)
7446  {
7447  /*
7448  Propagate pixel magnify columns.
7449  */
7450  for (l=0; l < magnify; l++)
7451  for (m=0; m < bytes_per_pixel; m++)
7452  *q++=(*(p+m));
7453  p+=(ptrdiff_t) bytes_per_pixel;
7454  }
7455  q+=(ptrdiff_t) scanline_pad;
7456  }
7457  y++;
7458  }
7459  break;
7460  }
7461  }
7462  /*
7463  Copy X image to magnify pixmap.
7464  */
7465  x=windows->magnify.x-(int) ((width/magnify) >> 1);
7466  if (x < 0)
7467  x=((int) (width >> 1)-windows->magnify.x*(int) magnify);
7468  else
7469  if (x > (ximage->width-(int) (width/magnify)))
7470  x=(int) ((ximage->width-windows->magnify.x)*(int) magnify-(int)
7471  (width >> 1));
7472  else
7473  x=0;
7474  y=windows->magnify.y-(int) ((height/magnify) >> 1);
7475  if (y < 0)
7476  y=((int) (height >> 1)-windows->magnify.y*(int) magnify);
7477  else
7478  if (y > (ximage->height-(int) (height/magnify)))
7479  y=(int) ((ximage->height-windows->magnify.y)*(int) magnify-(int)
7480  (height >> 1));
7481  else
7482  y=0;
7483  if ((x != 0) || (y != 0))
7484  (void) XFillRectangle(display,windows->magnify.pixmap,
7485  windows->magnify.annotate_context,0,0,width,height);
7486  (void) XPutImage(display,windows->magnify.pixmap,
7487  windows->magnify.annotate_context,windows->magnify.ximage,0,0,x,y,
7488  (unsigned int) ((int) width-x),(unsigned int) ((int) height-y));
7489  if ((magnify > 1) && ((magnify <= (width >> 1)) &&
7490  (magnify <= (height >> 1))))
7491  {
7493  highlight_info;
7494 
7495  /*
7496  Highlight center pixel.
7497  */
7498  highlight_info.x=(ssize_t) windows->magnify.width >> 1;
7499  highlight_info.y=(ssize_t) windows->magnify.height >> 1;
7500  highlight_info.width=magnify;
7501  highlight_info.height=magnify;
7502  (void) XDrawRectangle(display,windows->magnify.pixmap,
7503  windows->magnify.highlight_context,(int) highlight_info.x,
7504  (int) highlight_info.y,(unsigned int) highlight_info.width-1,
7505  (unsigned int) highlight_info.height-1);
7506  if (magnify > 2)
7507  (void) XDrawRectangle(display,windows->magnify.pixmap,
7508  windows->magnify.annotate_context,(int) highlight_info.x+1,
7509  (int) highlight_info.y+1,(unsigned int) highlight_info.width-3,
7510  (unsigned int) highlight_info.height-3);
7511  }
7512  /*
7513  Show center pixel color.
7514  */
7515  (void) GetOneVirtualPixelInfo(windows->image.image,TileVirtualPixelMethod,
7516  (ssize_t) windows->magnify.x,(ssize_t) windows->magnify.y,&pixel,exception);
7517  (void) FormatLocaleString(tuple,MagickPathExtent,"%d,%d: ",
7518  windows->magnify.x,windows->magnify.y);
7519  (void) ConcatenateMagickString(tuple,"(",MagickPathExtent);
7520  ConcatenateColorComponent(&pixel,RedPixelChannel,X11Compliance,tuple);
7521  (void) ConcatenateMagickString(tuple,",",MagickPathExtent);
7522  ConcatenateColorComponent(&pixel,GreenPixelChannel,X11Compliance,tuple);
7523  (void) ConcatenateMagickString(tuple,",",MagickPathExtent);
7524  ConcatenateColorComponent(&pixel,BluePixelChannel,X11Compliance,tuple);
7525  if (pixel.colorspace == CMYKColorspace)
7526  {
7527  (void) ConcatenateMagickString(tuple,",",MagickPathExtent);
7528  ConcatenateColorComponent(&pixel,BlackPixelChannel,X11Compliance,tuple);
7529  }
7530  if (pixel.alpha_trait != UndefinedPixelTrait)
7531  {
7532  (void) ConcatenateMagickString(tuple,",",MagickPathExtent);
7533  ConcatenateColorComponent(&pixel,AlphaPixelChannel,X11Compliance,tuple);
7534  }
7535  (void) ConcatenateMagickString(tuple,")",MagickPathExtent);
7536  height=(unsigned int) (windows->magnify.font_info->ascent+
7537  windows->magnify.font_info->descent);
7538  x=windows->magnify.font_info->max_bounds.width >> 1;
7539  y=windows->magnify.font_info->ascent+(int) (height >> 2);
7540  (void) XDrawImageString(display,windows->magnify.pixmap,
7541  windows->magnify.annotate_context,x,y,tuple,(int) strlen(tuple));
7542  GetColorTuple(&pixel,MagickTrue,tuple);
7543  y+=(int) height;
7544  (void) XDrawImageString(display,windows->magnify.pixmap,
7545  windows->magnify.annotate_context,x,y,tuple,(int) strlen(tuple));
7546  (void) QueryColorname(windows->image.image,&pixel,SVGCompliance,tuple,
7547  exception);
7548  y+=(int) height;
7549  (void) XDrawImageString(display,windows->magnify.pixmap,
7550  windows->magnify.annotate_context,x,y,tuple,(int) strlen(tuple));
7551  /*
7552  Refresh magnify window.
7553  */
7554  magnify_window=windows->magnify;
7555  magnify_window.x=0;
7556  magnify_window.y=0;
7557  XRefreshWindow(display,&magnify_window,(XEvent *) NULL);
7558 }
7559 
7560 /*
7561 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
7562 % %
7563 % %
7564 % %
7565 % X M a k e P i x m a p %
7566 % %
7567 % %
7568 % %
7569 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
7570 %
7571 % XMakePixmap() creates an X11 pixmap.
7572 %
7573 % The format of the XMakePixmap method is:
7574 %
7575 % void XMakeStandardColormap(Display *display,XVisualInfo *visual_info,
7576 % XResourceInfo *resource_info,Image *image,XStandardColormap *map_info,
7577 % XPixelInfo *pixel)
7578 %
7579 % A description of each parameter follows:
7580 %
7581 % o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
7582 %
7583 % o display: Specifies a connection to an X server; returned from
7584 % XOpenDisplay.
7585 %
7586 % o window: Specifies a pointer to a XWindowInfo structure.
7587 %
7588 */
7589 static MagickBooleanType XMakePixmap(Display *display,
7590  const XResourceInfo *resource_info,XWindowInfo *window)
7591 {
7592  unsigned int
7593  height,
7594  width;
7595 
7596  assert(display != (Display *) NULL);
7597  assert(resource_info != (XResourceInfo *) NULL);
7598  assert(window != (XWindowInfo *) NULL);
7599  if (IsEventLogging() != MagickFalse)
7600  (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
7601  if (window->pixmap != (Pixmap) NULL)
7602  {
7603  /*
7604  Destroy previous X pixmap.
7605  */
7606  (void) XFreePixmap(display,window->pixmap);
7607  window->pixmap=(Pixmap) NULL;
7608  }
7609  if (window->use_pixmap == MagickFalse)
7610  return(MagickFalse);
7611  if (window->ximage == (XImage *) NULL)
7612  return(MagickFalse);
7613  /*
7614  Display busy cursor.
7615  */
7616  (void) XCheckDefineCursor(display,window->id,window->busy_cursor);
7617  (void) XFlush(display);
7618  /*
7619  Create pixmap.
7620  */
7621  width=(unsigned int) window->ximage->width;
7622  height=(unsigned int) window->ximage->height;
7623  window->pixmap=XCreatePixmap(display,window->id,width,height,window->depth);
7624  if (window->pixmap == (Pixmap) NULL)
7625  {
7626  /*
7627  Unable to allocate pixmap.
7628  */
7629  (void) XCheckDefineCursor(display,window->id,window->cursor);
7630  return(MagickFalse);
7631  }
7632  /*
7633  Copy X image to pixmap.
7634  */
7635 #if defined(MAGICKCORE_HAVE_SHARED_MEMORY)
7636  if (window->shared_memory)
7637  (void) XShmPutImage(display,window->pixmap,window->annotate_context,
7638  window->ximage,0,0,0,0,width,height,MagickTrue);
7639 #endif
7640  if (window->shared_memory == MagickFalse)
7641  (void) XPutImage(display,window->pixmap,window->annotate_context,
7642  window->ximage,0,0,0,0,width,height);
7643  if ((GetLogEventMask() & X11Event) != 0)
7644  {
7645  (void) LogMagickEvent(X11Event,GetMagickModule(),"Pixmap:");
7646  (void) LogMagickEvent(X11Event,GetMagickModule()," width, height: %ux%u",
7647  width,height);
7648  }
7649  /*
7650  Restore cursor.
7651  */
7652  (void) XCheckDefineCursor(display,window->id,window->cursor);
7653  return(MagickTrue);
7654 }
7655 
7656 /*
7657 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
7658 % %
7659 % %
7660 % %
7661 % X M a k e S t a n d a r d C o l o r m a p %
7662 % %
7663 % %
7664 % %
7665 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
7666 %
7667 % XMakeStandardColormap() creates an X11 Standard Colormap.
7668 %
7669 % The format of the XMakeStandardColormap method is:
7670 %
7671 % void XMakeStandardColormap(Display *display,XVisualInfo *visual_info,
7672 % XResourceInfo *resource_info,Image *image,XStandardColormap *map_info,
7673 % XPixelInfo *pixel,ExceptionInfo *exception)
7674 %
7675 % A description of each parameter follows:
7676 %
7677 % o display: Specifies a connection to an X server; returned from
7678 % XOpenDisplay.
7679 %
7680 % o visual_info: Specifies a pointer to a X11 XVisualInfo structure;
7681 % returned from XGetVisualInfo.
7682 %
7683 % o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
7684 %
7685 % o image: the image.
7686 %
7687 % o map_info: If a Standard Colormap type is specified, this structure is
7688 % initialized with info from the Standard Colormap.
7689 %
7690 % o pixel: Specifies a pointer to a XPixelInfo structure.
7691 %
7692 % o exception: return any errors or warnings in this structure.
7693 %
7694 */
7695 
7696 #if defined(__cplusplus) || defined(c_plusplus)
7697 extern "C" {
7698 #endif
7699 
7700 static inline double DiversityPixelIntensity(
7701  const DiversityPacket *pixel)
7702 {
7703  double
7704  intensity;
7705 
7706  intensity=0.212656*(double) pixel->red+0.715158*(double) pixel->green+
7707  0.072186*(double) pixel->blue;
7708  return(intensity);
7709 }
7710 
7711 static int IntensityCompare(const void *x,const void *y)
7712 {
7713  DiversityPacket
7714  *color_1,
7715  *color_2;
7716 
7717  int
7718  diversity;
7719 
7720  color_1=(DiversityPacket *) x;
7721  color_2=(DiversityPacket *) y;
7722  diversity=(int) (DiversityPixelIntensity(color_2)-
7723  DiversityPixelIntensity(color_1));
7724  return(diversity);
7725 }
7726 
7727 static int PopularityCompare(const void *x,const void *y)
7728 {
7729  DiversityPacket
7730  *color_1,
7731  *color_2;
7732 
7733  color_1=(DiversityPacket *) x;
7734  color_2=(DiversityPacket *) y;
7735  return((int) color_2->count-(int) color_1->count);
7736 }
7737 
7738 #if defined(__cplusplus) || defined(c_plusplus)
7739 }
7740 #endif
7741 
7742 static inline Quantum ScaleXToQuantum(const size_t x,
7743  const size_t scale)
7744 {
7745  return((Quantum) (((double) QuantumRange*x)/scale+0.5));
7746 }
7747 
7748 MagickPrivate void XMakeStandardColormap(Display *display,
7749  XVisualInfo *visual_info,XResourceInfo *resource_info,Image *image,
7750  XStandardColormap *map_info,XPixelInfo *pixel,ExceptionInfo *exception)
7751 {
7752  Colormap
7753  colormap;
7754 
7755  ssize_t
7756  i;
7757 
7758  Status
7759  status;
7760 
7761  size_t
7762  number_colors,
7763  retain_colors;
7764 
7765  unsigned short
7766  gray_value;
7767 
7768  XColor
7769  color,
7770  *colors,
7771  *p;
7772 
7773  assert(display != (Display *) NULL);
7774  assert(visual_info != (XVisualInfo *) NULL);
7775  assert(map_info != (XStandardColormap *) NULL);
7776  assert(resource_info != (XResourceInfo *) NULL);
7777  assert(pixel != (XPixelInfo *) NULL);
7778  if (IsEventLogging() != MagickFalse)
7779  (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
7780  if (resource_info->map_type != (char *) NULL)
7781  {
7782  /*
7783  Standard Colormap is already defined (i.e. xstdcmap).
7784  */
7785  XGetPixelInfo(display,visual_info,map_info,resource_info,image,
7786  pixel);
7787  number_colors=(unsigned int) (map_info->base_pixel+
7788  (map_info->red_max+1)*(map_info->green_max+1)*(map_info->blue_max+1));
7789  if ((map_info->red_max*map_info->green_max*map_info->blue_max) != 0)
7790  if (((image->alpha_trait & BlendPixelTrait) == 0) &&
7791  (resource_info->color_recovery == MagickFalse) &&
7792  (resource_info->quantize_info->dither_method != NoDitherMethod) &&
7793  (number_colors < MaxColormapSize))
7794  {
7795  Image
7796  *affinity_image;
7797 
7798  Quantum
7799  *magick_restrict q;
7800 
7801  /*
7802  Improve image appearance with error diffusion.
7803  */
7804  affinity_image=AcquireImage((ImageInfo *) NULL,exception);
7805  if (affinity_image == (Image *) NULL)
7806  ThrowXWindowFatalException(ResourceLimitFatalError,
7807  "UnableToDitherImage",image->filename);
7808  affinity_image->columns=number_colors;
7809  affinity_image->rows=1;
7810  /*
7811  Initialize colormap image.
7812  */
7813  q=QueueAuthenticPixels(affinity_image,0,0,affinity_image->columns,
7814  1,exception);
7815  if (q != (Quantum *) NULL)
7816  {
7817  for (i=0; i < (ssize_t) number_colors; i++)
7818  {
7819  SetPixelRed(affinity_image,0,q);
7820  if (map_info->red_max != 0)
7821  SetPixelRed(affinity_image,ScaleXToQuantum((size_t)
7822  (i/(ssize_t) map_info->red_mult),map_info->red_max),q);
7823  SetPixelGreen(affinity_image,0,q);
7824  if (map_info->green_max != 0)
7825  SetPixelGreen(affinity_image,ScaleXToQuantum((size_t)
7826  ((i/(ssize_t) map_info->green_mult) % (ssize_t)
7827  (map_info->green_max+1)),map_info->green_max),q);
7828  SetPixelBlue(affinity_image,0,q);
7829  if (map_info->blue_max != 0)
7830  SetPixelBlue(affinity_image,ScaleXToQuantum((size_t)
7831  (i % (ssize_t) map_info->green_mult),map_info->blue_max),
7832  q);
7833  SetPixelAlpha(affinity_image,TransparentAlpha,q);
7834  q+=(ptrdiff_t) GetPixelChannels(affinity_image);
7835  }
7836  (void) SyncAuthenticPixels(affinity_image,exception);
7837  (void) RemapImage(resource_info->quantize_info,image,
7838  affinity_image,exception);
7839  }
7840  XGetPixelInfo(display,visual_info,map_info,resource_info,image,
7841  pixel);
7842  (void) SetImageStorageClass(image,DirectClass,exception);
7843  affinity_image=DestroyImage(affinity_image);
7844  }
7845  if ((GetLogEventMask() & X11Event) != 0)
7846  {
7847  (void) LogMagickEvent(X11Event,GetMagickModule(),
7848  "Standard Colormap:");
7849  (void) LogMagickEvent(X11Event,GetMagickModule(),
7850  " colormap id: 0x%lx",map_info->colormap);
7851  (void) LogMagickEvent(X11Event,GetMagickModule(),
7852  " red, green, blue max: %lu %lu %lu",map_info->red_max,
7853  map_info->green_max,map_info->blue_max);
7854  (void) LogMagickEvent(X11Event,GetMagickModule(),
7855  " red, green, blue mult: %lu %lu %lu",map_info->red_mult,
7856  map_info->green_mult,map_info->blue_mult);
7857  }
7858  return;
7859  }
7860  if ((visual_info->klass != DirectColor) &&
7861  (visual_info->klass != TrueColor))
7862  if ((image->storage_class == DirectClass) ||
7863  ((int) image->colors > visual_info->colormap_size))
7864  {
7865  QuantizeInfo
7866  quantize_info;
7867 
7868  /*
7869  Image has more colors than the visual supports.
7870  */
7871  quantize_info=(*resource_info->quantize_info);
7872  quantize_info.number_colors=(size_t) visual_info->colormap_size;
7873  (void) QuantizeImage(&quantize_info,image,exception);
7874  }
7875  /*
7876  Free previous and create new colormap.
7877  */
7878  (void) XFreeStandardColormap(display,visual_info,map_info,pixel);
7879  colormap=XDefaultColormap(display,visual_info->screen);
7880  if (visual_info->visual != XDefaultVisual(display,visual_info->screen))
7881  colormap=XCreateColormap(display,XRootWindow(display,visual_info->screen),
7882  visual_info->visual,visual_info->klass == DirectColor ?
7883  AllocAll : AllocNone);
7884  if (colormap == (Colormap) NULL)
7885  ThrowXWindowFatalException(ResourceLimitFatalError,"UnableToCreateColormap",
7886  image->filename);
7887  /*
7888  Initialize the map and pixel info structures.
7889  */
7890  XGetMapInfo(visual_info,colormap,map_info);
7891  XGetPixelInfo(display,visual_info,map_info,resource_info,image,pixel);
7892  /*
7893  Allocating colors in server colormap is based on visual class.
7894  */
7895  switch (visual_info->klass)
7896  {
7897  case StaticGray:
7898  case StaticColor:
7899  {
7900  /*
7901  Define Standard Colormap for StaticGray or StaticColor visual.
7902  */
7903  number_colors=image->colors;
7904  colors=(XColor *) AcquireQuantumMemory((size_t)
7905  visual_info->colormap_size,sizeof(*colors));
7906  if (colors == (XColor *) NULL)
7907  ThrowXWindowFatalException(ResourceLimitFatalError,
7908  "UnableToCreateColormap",image->filename);
7909  p=colors;
7910  color.flags=(char) (DoRed | DoGreen | DoBlue);
7911  for (i=0; i < (ssize_t) image->colors; i++)
7912  {
7913  color.red=ScaleQuantumToShort(XRedGamma(image->colormap[i].red));
7914  color.green=ScaleQuantumToShort(XGreenGamma(image->colormap[i].green));
7915  color.blue=ScaleQuantumToShort(XBlueGamma(image->colormap[i].blue));
7916  if (visual_info->klass != StaticColor)
7917  {
7918  gray_value=(unsigned short) XPixelIntensity(&color);
7919  color.red=gray_value;
7920  color.green=gray_value;
7921  color.blue=gray_value;
7922  }
7923  status=XAllocColor(display,colormap,&color);
7924  if (status == False)
7925  {
7926  colormap=XCopyColormapAndFree(display,colormap);
7927  (void) XAllocColor(display,colormap,&color);
7928  }
7929  pixel->pixels[i]=color.pixel;
7930  *p++=color;
7931  }
7932  break;
7933  }
7934  case GrayScale:
7935  case PseudoColor:
7936  {
7937  unsigned int
7938  colormap_type;
7939 
7940  /*
7941  Define Standard Colormap for GrayScale or PseudoColor visual.
7942  */
7943  number_colors=image->colors;
7944  colors=(XColor *) AcquireQuantumMemory((size_t)
7945  visual_info->colormap_size,sizeof(*colors));
7946  if (colors == (XColor *) NULL)
7947  ThrowXWindowFatalException(ResourceLimitFatalError,
7948  "UnableToCreateColormap",image->filename);
7949  /*
7950  Preallocate our GUI colors.
7951  */
7952  (void) XAllocColor(display,colormap,&pixel->foreground_color);
7953  (void) XAllocColor(display,colormap,&pixel->background_color);
7954  (void) XAllocColor(display,colormap,&pixel->border_color);
7955  (void) XAllocColor(display,colormap,&pixel->matte_color);
7956  (void) XAllocColor(display,colormap,&pixel->highlight_color);
7957  (void) XAllocColor(display,colormap,&pixel->shadow_color);
7958  (void) XAllocColor(display,colormap,&pixel->depth_color);
7959  (void) XAllocColor(display,colormap,&pixel->trough_color);
7960  for (i=0; i < MaxNumberPens; i++)
7961  (void) XAllocColor(display,colormap,&pixel->pen_colors[i]);
7962  /*
7963  Determine if image colors will "fit" into X server colormap.
7964  */
7965  colormap_type=resource_info->colormap;
7966  status=XAllocColorCells(display,colormap,MagickFalse,(unsigned long *)
7967  NULL,0,pixel->pixels,(unsigned int) image->colors);
7968  if (status != False)
7969  colormap_type=PrivateColormap;
7970  if (colormap_type == SharedColormap)
7971  {
7972  CacheView
7973  *image_view;
7974 
7975  DiversityPacket
7976  *diversity;
7977 
7978  int
7979  y;
7980 
7981  int
7982  x;
7983 
7984  unsigned short
7985  index;
7986 
7987  XColor
7988  *server_colors;
7989 
7990  /*
7991  Define Standard colormap for shared GrayScale or PseudoColor visual.
7992  */
7993  diversity=(DiversityPacket *) AcquireQuantumMemory(image->colors,
7994  sizeof(*diversity));
7995  if (diversity == (DiversityPacket *) NULL)
7996  ThrowXWindowFatalException(ResourceLimitFatalError,
7997  "UnableToCreateColormap",image->filename);
7998  for (i=0; i < (ssize_t) image->colors; i++)
7999  {
8000  diversity[i].red=ClampToQuantum(image->colormap[i].red);
8001  diversity[i].green=ClampToQuantum(image->colormap[i].green);
8002  diversity[i].blue=ClampToQuantum(image->colormap[i].blue);
8003  diversity[i].index=(unsigned short) i;
8004  diversity[i].count=0;
8005  }
8006  image_view=AcquireAuthenticCacheView(image,exception);
8007  for (y=0; y < (int) image->rows; y++)
8008  {
8009  int
8010  x;
8011 
8012  const Quantum
8013  *magick_restrict p;
8014 
8015  p=GetCacheViewAuthenticPixels(image_view,0,(ssize_t) y,
8016  image->columns,1,exception);
8017  if (p == (const Quantum *) NULL)
8018  break;
8019  for (x=(int) image->columns-1; x >= 0; x--)
8020  {
8021  diversity[(ssize_t) GetPixelIndex(image,p)].count++;
8022  p+=(ptrdiff_t) GetPixelChannels(image);
8023  }
8024  }
8025  image_view=DestroyCacheView(image_view);
8026  /*
8027  Sort colors by decreasing intensity.
8028  */
8029  qsort((void *) diversity,image->colors,sizeof(*diversity),
8030  IntensityCompare);
8031  for (i=0; i < (ssize_t) image->colors; )
8032  {
8033  diversity[i].count<<=4; /* increase this colors popularity */
8034  i+=MagickMax((int) (image->colors >> 4),2);
8035  }
8036  diversity[image->colors-1].count<<=4;
8037  qsort((void *) diversity,image->colors,sizeof(*diversity),
8038  PopularityCompare);
8039  /*
8040  Allocate colors.
8041  */
8042  p=colors;
8043  color.flags=(char) (DoRed | DoGreen | DoBlue);
8044  for (i=0; i < (ssize_t) image->colors; i++)
8045  {
8046  index=diversity[i].index;
8047  color.red=
8048  ScaleQuantumToShort(XRedGamma(image->colormap[index].red));
8049  color.green=
8050  ScaleQuantumToShort(XGreenGamma(image->colormap[index].green));
8051  color.blue=
8052  ScaleQuantumToShort(XBlueGamma(image->colormap[index].blue));
8053  if (visual_info->klass != PseudoColor)
8054  {
8055  gray_value=(unsigned short) XPixelIntensity(&color);
8056  color.red=gray_value;
8057  color.green=gray_value;
8058  color.blue=gray_value;
8059  }
8060  status=XAllocColor(display,colormap,&color);
8061  if (status == False)
8062  break;
8063  pixel->pixels[index]=color.pixel;
8064  *p++=color;
8065  }
8066  /*
8067  Read X server colormap.
8068  */
8069  server_colors=(XColor *) AcquireQuantumMemory((size_t)
8070  visual_info->colormap_size,sizeof(*server_colors));
8071  if (server_colors == (XColor *) NULL)
8072  ThrowXWindowFatalException(ResourceLimitFatalError,
8073  "UnableToCreateColormap",image->filename);
8074  for (x=visual_info->colormap_size-1; x >= 0; x--)
8075  server_colors[x].pixel=(size_t) x;
8076  (void) XQueryColors(display,colormap,server_colors,
8077  (int) MagickMin((unsigned int) visual_info->colormap_size,256));
8078  /*
8079  Select remaining colors from X server colormap.
8080  */
8081  for (; i < (ssize_t) image->colors; i++)
8082  {
8083  index=diversity[i].index;
8084  color.red=ScaleQuantumToShort(
8085  XRedGamma(image->colormap[index].red));
8086  color.green=ScaleQuantumToShort(
8087  XGreenGamma(image->colormap[index].green));
8088  color.blue=ScaleQuantumToShort(
8089  XBlueGamma(image->colormap[index].blue));
8090  if (visual_info->klass != PseudoColor)
8091  {
8092  gray_value=(unsigned short) XPixelIntensity(&color);
8093  color.red=gray_value;
8094  color.green=gray_value;
8095  color.blue=gray_value;
8096  }
8097  XBestPixel(display,colormap,server_colors,(unsigned int)
8098  visual_info->colormap_size,&color);
8099  pixel->pixels[index]=color.pixel;
8100  *p++=color;
8101  }
8102  if ((int) image->colors < visual_info->colormap_size)
8103  {
8104  /*
8105  Fill up colors array-- more choices for pen colors.
8106  */
8107  retain_colors=MagickMin((unsigned int)
8108  (visual_info->colormap_size-(int) image->colors),256);
8109  for (i=0; i < (ssize_t) retain_colors; i++)
8110  *p++=server_colors[i];
8111  number_colors+=retain_colors;
8112  }
8113  server_colors=(XColor *) RelinquishMagickMemory(server_colors);
8114  diversity=(DiversityPacket *) RelinquishMagickMemory(diversity);
8115  break;
8116  }
8117  /*
8118  Define Standard colormap for private GrayScale or PseudoColor visual.
8119  */
8120  if (status == False)
8121  {
8122  /*
8123  Not enough colormap entries in the colormap-- Create a new colormap.
8124  */
8125  colormap=XCreateColormap(display,
8126  XRootWindow(display,visual_info->screen),visual_info->visual,
8127  AllocNone);
8128  if (colormap == (Colormap) NULL)
8129  ThrowXWindowFatalException(ResourceLimitFatalError,
8130  "UnableToCreateColormap",image->filename);
8131  map_info->colormap=colormap;
8132  if ((int) image->colors < visual_info->colormap_size)
8133  {
8134  /*
8135  Retain colors from the default colormap to help lessens the
8136  effects of colormap flashing.
8137  */
8138  retain_colors=MagickMin((unsigned int)
8139  (visual_info->colormap_size-(int) image->colors),256);
8140  p=colors+image->colors;
8141  for (i=0; i < (ssize_t) retain_colors; i++)
8142  {
8143  p->pixel=(unsigned long) i;
8144  p++;
8145  }
8146  (void) XQueryColors(display,
8147  XDefaultColormap(display,visual_info->screen),
8148  colors+image->colors,(int) retain_colors);
8149  /*
8150  Transfer colors from default to private colormap.
8151  */
8152  (void) XAllocColorCells(display,colormap,MagickFalse,
8153  (unsigned long *) NULL,0,pixel->pixels,(unsigned int)
8154  retain_colors);
8155  p=colors+image->colors;
8156  for (i=0; i < (ssize_t) retain_colors; i++)
8157  {
8158  p->pixel=pixel->pixels[i];
8159  p++;
8160  }
8161  (void) XStoreColors(display,colormap,colors+image->colors,
8162  (int) retain_colors);
8163  number_colors+=retain_colors;
8164  }
8165  (void) XAllocColorCells(display,colormap,MagickFalse,
8166  (unsigned long *) NULL,0,pixel->pixels,(unsigned int)
8167  image->colors);
8168  }
8169  /*
8170  Store the image colormap.
8171  */
8172  p=colors;
8173  color.flags=(char) (DoRed | DoGreen | DoBlue);
8174  for (i=0; i < (ssize_t) image->colors; i++)
8175  {
8176  color.red=ScaleQuantumToShort(XRedGamma(image->colormap[i].red));
8177  color.green=ScaleQuantumToShort(XGreenGamma(image->colormap[i].green));
8178  color.blue=ScaleQuantumToShort(XBlueGamma(image->colormap[i].blue));
8179  if (visual_info->klass != PseudoColor)
8180  {
8181  gray_value=(unsigned short) XPixelIntensity(&color);
8182  color.red=gray_value;
8183  color.green=gray_value;
8184  color.blue=gray_value;
8185  }
8186  color.pixel=pixel->pixels[i];
8187  *p++=color;
8188  }
8189  (void) XStoreColors(display,colormap,colors,(int) image->colors);
8190  break;
8191  }
8192  case TrueColor:
8193  case DirectColor:
8194  default:
8195  {
8196  MagickBooleanType
8197  linear_colormap;
8198 
8199  /*
8200  Define Standard Colormap for TrueColor or DirectColor visual.
8201  */
8202  number_colors=(unsigned int) ((map_info->red_max*map_info->red_mult)+
8203  (map_info->green_max*map_info->green_mult)+
8204  (map_info->blue_max*map_info->blue_mult)+1);
8205  linear_colormap=(number_colors > 4096) ||
8206  (((int) (map_info->red_max+1) == visual_info->colormap_size) &&
8207  ((int) (map_info->green_max+1) == visual_info->colormap_size) &&
8208  ((int) (map_info->blue_max+1) == visual_info->colormap_size)) ?
8209  MagickTrue : MagickFalse;
8210  if (linear_colormap != MagickFalse)
8211  number_colors=(size_t) visual_info->colormap_size;
8212  /*
8213  Allocate color array.
8214  */
8215  colors=(XColor *) AcquireQuantumMemory(number_colors,sizeof(*colors));
8216  if (colors == (XColor *) NULL)
8217  ThrowXWindowFatalException(ResourceLimitFatalError,
8218  "UnableToCreateColormap",image->filename);
8219  /*
8220  Initialize linear color ramp.
8221  */
8222  p=colors;
8223  color.flags=(char) (DoRed | DoGreen | DoBlue);
8224  if (linear_colormap != MagickFalse)
8225  for (i=0; i < (ssize_t) number_colors; i++)
8226  {
8227  color.blue=(unsigned short) 0;
8228  if (map_info->blue_max != 0)
8229  color.blue=(unsigned short) (((65535L*(i % (ssize_t)
8230  map_info->green_mult))/(ssize_t) map_info->blue_max));
8231  color.green=color.blue;
8232  color.red=color.blue;
8233  color.pixel=XStandardPixel(map_info,&color);
8234  *p++=color;
8235  }
8236  else
8237  for (i=0; i < (ssize_t) number_colors; i++)
8238  {
8239  color.red=(unsigned short) 0;
8240  if (map_info->red_max != 0)
8241  color.red=(unsigned short) ((size_t) ((65535L*(i/(ssize_t)
8242  map_info->red_mult))/(ssize_t) map_info->red_max));
8243  color.green=(unsigned int) 0;
8244  if (map_info->green_max != 0)
8245  color.green=(unsigned short) ((size_t) ((65535L*((i/(ssize_t)
8246  map_info->green_mult) % (ssize_t) (map_info->green_max+1)))/
8247  (ssize_t) map_info->green_max));
8248  color.blue=(unsigned short) 0;
8249  if (map_info->blue_max != 0)
8250  color.blue=(unsigned short) ((size_t) ((65535L*(i % (ssize_t)
8251  map_info->green_mult))/(ssize_t) map_info->blue_max));
8252  color.pixel=XStandardPixel(map_info,&color);
8253  *p++=color;
8254  }
8255  if ((visual_info->klass == DirectColor) &&
8256  (colormap != XDefaultColormap(display,visual_info->screen)))
8257  (void) XStoreColors(display,colormap,colors,(int) number_colors);
8258  else
8259  for (i=0; i < (ssize_t) number_colors; i++)
8260  (void) XAllocColor(display,colormap,&colors[i]);
8261  break;
8262  }
8263  }
8264  if ((visual_info->klass != DirectColor) &&
8265  (visual_info->klass != TrueColor))
8266  {
8267  /*
8268  Set foreground, background, border, etc. pixels.
8269  */
8270  XBestPixel(display,colormap,colors,(unsigned int) number_colors,
8271  &pixel->foreground_color);
8272  XBestPixel(display,colormap,colors,(unsigned int) number_colors,
8273  &pixel->background_color);
8274  if (pixel->background_color.pixel == pixel->foreground_color.pixel)
8275  {
8276  /*
8277  Foreground and background colors must differ.
8278  */
8279  pixel->background_color.red=(~pixel->foreground_color.red);
8280  pixel->background_color.green=
8281  (~pixel->foreground_color.green);
8282  pixel->background_color.blue=
8283  (~pixel->foreground_color.blue);
8284  XBestPixel(display,colormap,colors,(unsigned int) number_colors,
8285  &pixel->background_color);
8286  }
8287  XBestPixel(display,colormap,colors,(unsigned int) number_colors,
8288  &pixel->border_color);
8289  XBestPixel(display,colormap,colors,(unsigned int) number_colors,
8290  &pixel->matte_color);
8291  XBestPixel(display,colormap,colors,(unsigned int) number_colors,
8292  &pixel->highlight_color);
8293  XBestPixel(display,colormap,colors,(unsigned int) number_colors,
8294  &pixel->shadow_color);
8295  XBestPixel(display,colormap,colors,(unsigned int) number_colors,
8296  &pixel->depth_color);
8297  XBestPixel(display,colormap,colors,(unsigned int) number_colors,
8298  &pixel->trough_color);
8299  for (i=0; i < MaxNumberPens; i++)
8300  {
8301  XBestPixel(display,colormap,colors,(unsigned int) number_colors,
8302  &pixel->pen_colors[i]);
8303  pixel->pixels[(ssize_t) image->colors+i]=pixel->pen_colors[i].pixel;
8304  }
8305  pixel->colors=(ssize_t) (image->colors+MaxNumberPens);
8306  }
8307  colors=(XColor *) RelinquishMagickMemory(colors);
8308  if ((GetLogEventMask() & X11Event) != 0)
8309  {
8310  (void) LogMagickEvent(X11Event,GetMagickModule(),"Standard Colormap:");
8311  (void) LogMagickEvent(X11Event,GetMagickModule()," colormap id: 0x%lx",
8312  map_info->colormap);
8313  (void) LogMagickEvent(X11Event,GetMagickModule(),
8314  " red, green, blue max: %lu %lu %lu",map_info->red_max,
8315  map_info->green_max,map_info->blue_max);
8316  (void) LogMagickEvent(X11Event,GetMagickModule(),
8317  " red, green, blue mult: %lu %lu %lu",map_info->red_mult,
8318  map_info->green_mult,map_info->blue_mult);
8319  }
8320 }
8321 
8322 /*
8323 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8324 % %
8325 % %
8326 % %
8327 % X M a k e W i n d o w %
8328 % %
8329 % %
8330 % %
8331 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8332 %
8333 % XMakeWindow() creates an X11 window.
8334 %
8335 % The format of the XMakeWindow method is:
8336 %
8337 % void XMakeWindow(Display *display,Window parent,char **argv,int argc,
8338 % XClassHint *class_hint,XWMHints *manager_hints,
8339 % XWindowInfo *window_info)
8340 %
8341 % A description of each parameter follows:
8342 %
8343 % o display: Specifies a connection to an X server; returned from
8344 % XOpenDisplay.
8345 %
8346 % o parent: Specifies the parent window_info.
8347 %
8348 % o argv: Specifies the application's argument list.
8349 %
8350 % o argc: Specifies the number of arguments.
8351 %
8352 % o class_hint: Specifies a pointer to a X11 XClassHint structure.
8353 %
8354 % o manager_hints: Specifies a pointer to a X11 XWMHints structure.
8355 %
8356 % o window_info: Specifies a pointer to a X11 XWindowInfo structure.
8357 %
8358 */
8359 MagickPrivate void XMakeWindow(Display *display,Window parent,char **argv,
8360  int argc,XClassHint *class_hint,XWMHints *manager_hints,
8361  XWindowInfo *window_info)
8362 {
8363 #define MinWindowSize 64
8364 
8365  Atom
8366  atom_list[2];
8367 
8368  int
8369  gravity;
8370 
8371  static XTextProperty
8372  icon_name,
8373  window_name;
8374 
8375  Status
8376  status;
8377 
8378  XSizeHints
8379  *size_hints;
8380 
8381  /*
8382  Set window info hints.
8383  */
8384  assert(display != (Display *) NULL);
8385  assert(window_info != (XWindowInfo *) NULL);
8386  if (IsEventLogging() != MagickFalse)
8387  (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
8388  size_hints=XAllocSizeHints();
8389  if (size_hints == (XSizeHints *) NULL)
8390  ThrowXWindowFatalException(XServerFatalError,"UnableToMakeXWindow",argv[0]);
8391  size_hints->flags=(int) window_info->flags;
8392  size_hints->x=window_info->x;
8393  size_hints->y=window_info->y;
8394  size_hints->width=(int) window_info->width;
8395  size_hints->height=(int) window_info->height;
8396  if (window_info->immutable != MagickFalse)
8397  {
8398  /*
8399  Window size cannot be changed.
8400  */
8401  size_hints->min_width=size_hints->width;
8402  size_hints->min_height=size_hints->height;
8403  size_hints->max_width=size_hints->width;
8404  size_hints->max_height=size_hints->height;
8405  size_hints->flags|=PMinSize;
8406  size_hints->flags|=PMaxSize;
8407  }
8408  else
8409  {
8410  /*
8411  Window size can be changed.
8412  */
8413  size_hints->min_width=(int) window_info->min_width;
8414  size_hints->min_height=(int) window_info->min_height;
8415  size_hints->flags|=PResizeInc;
8416  size_hints->width_inc=(int) window_info->width_inc;
8417  size_hints->height_inc=(int) window_info->height_inc;
8418 #if !defined(PRE_R4_ICCCM)
8419  size_hints->flags|=PBaseSize;
8420  size_hints->base_width=size_hints->width_inc;
8421  size_hints->base_height=size_hints->height_inc;
8422 #endif
8423  }
8424  gravity=NorthWestGravity;
8425  if (window_info->geometry != (char *) NULL)
8426  {
8427  char
8428  default_geometry[MagickPathExtent],
8429  geometry[MagickPathExtent];
8430 
8431  int
8432  flags;
8433 
8434  char
8435  *p;
8436 
8437  /*
8438  User specified geometry.
8439  */
8440  (void) FormatLocaleString(default_geometry,MagickPathExtent,"%dx%d",
8441  size_hints->width,size_hints->height);
8442  (void) CopyMagickString(geometry,window_info->geometry,MagickPathExtent);
8443  p=geometry;
8444  while (strlen(p) != 0)
8445  {
8446  if ((isspace((int) ((unsigned char) *p)) == 0) && (*p != '%'))
8447  p++;
8448  else
8449  (void) memmove(p,p+1,(size_t) (MagickPathExtent-(p-geometry)));
8450  }
8451  flags=XWMGeometry(display,window_info->screen,geometry,default_geometry,
8452  window_info->border_width,size_hints,&size_hints->x,&size_hints->y,
8453  &size_hints->width,&size_hints->height,&gravity);
8454  if ((flags & WidthValue) && (flags & HeightValue))
8455  size_hints->flags|=USSize;
8456  if ((flags & XValue) && (flags & YValue))
8457  {
8458  size_hints->flags|=USPosition;
8459  window_info->x=size_hints->x;
8460  window_info->y=size_hints->y;
8461  }
8462  }
8463 #if !defined(PRE_R4_ICCCM)
8464  size_hints->win_gravity=gravity;
8465  size_hints->flags|=PWinGravity;
8466 #endif
8467  if (window_info->id == (Window) NULL)
8468  window_info->id=XCreateWindow(display,parent,window_info->x,window_info->y,
8469  (unsigned int) size_hints->width,(unsigned int) size_hints->height,
8470  window_info->border_width,(int) window_info->depth,InputOutput,
8471  window_info->visual,(unsigned long) window_info->mask,
8472  &window_info->attributes);
8473  else
8474  {
8475  MagickStatusType
8476  mask;
8477 
8478  XEvent
8479  sans_event;
8480 
8481  XWindowChanges
8482  window_changes;
8483 
8484  /*
8485  Window already exists; change relevant attributes.
8486  */
8487  (void) XChangeWindowAttributes(display,window_info->id,(unsigned long)
8488  window_info->mask,&window_info->attributes);
8489  mask=ConfigureNotify;
8490  while (XCheckTypedWindowEvent(display,window_info->id,(int) mask,&sans_event)) ;
8491  window_changes.x=window_info->x;
8492  window_changes.y=window_info->y;
8493  window_changes.width=(int) window_info->width;
8494  window_changes.height=(int) window_info->height;
8495  mask=(MagickStatusType) (CWWidth | CWHeight);
8496  if (window_info->flags & USPosition)
8497  mask|=CWX | CWY;
8498  (void) XReconfigureWMWindow(display,window_info->id,window_info->screen,
8499  mask,&window_changes);
8500  }
8501  if (window_info->id == (Window) NULL)
8502  ThrowXWindowFatalException(XServerFatalError,"UnableToCreateWindow",
8503  window_info->name);
8504  status=XStringListToTextProperty(&window_info->name,1,&window_name);
8505  if (status == False)
8506  ThrowXWindowFatalException(XServerFatalError,"UnableToCreateTextProperty",
8507  window_info->name);
8508  status=XStringListToTextProperty(&window_info->icon_name,1,&icon_name);
8509  if (status == False)
8510  ThrowXWindowFatalException(XServerFatalError,"UnableToCreateTextProperty",
8511  window_info->icon_name);
8512  if (window_info->icon_geometry != (char *) NULL)
8513  {
8514  int
8515  flags,
8516  height,
8517  width;
8518 
8519  /*
8520  User specified icon geometry.
8521  */
8522  size_hints->flags|=USPosition;
8523  flags=XWMGeometry(display,window_info->screen,window_info->icon_geometry,
8524  (char *) NULL,0,size_hints,&manager_hints->icon_x,
8525  &manager_hints->icon_y,&width,&height,&gravity);
8526  if ((flags & XValue) && (flags & YValue))
8527  manager_hints->flags|=IconPositionHint;
8528  }
8529  XSetWMProperties(display,window_info->id,&window_name,&icon_name,argv,argc,
8530  size_hints,manager_hints,class_hint);
8531  if (window_name.value != (void *) NULL)
8532  {
8533  (void) XFree((void *) window_name.value);
8534  window_name.value=(unsigned char *) NULL;
8535  window_name.nitems=0;
8536  }
8537  if (icon_name.value != (void *) NULL)
8538  {
8539  (void) XFree((void *) icon_name.value);
8540  icon_name.value=(unsigned char *) NULL;
8541  icon_name.nitems=0;
8542  }
8543  atom_list[0]=XInternAtom(display,"WM_DELETE_WINDOW",MagickFalse);
8544  atom_list[1]=XInternAtom(display,"WM_TAKE_FOCUS",MagickFalse);
8545  (void) XSetWMProtocols(display,window_info->id,atom_list,2);
8546  (void) XFree((void *) size_hints);
8547  if (window_info->shape != MagickFalse)
8548  {
8549 #if defined(MAGICKCORE_HAVE_SHAPE)
8550  int
8551  error_base,
8552  event_base;
8553 
8554  /*
8555  Can we apply a non-rectangular shaping mask?
8556  */
8557  error_base=0;
8558  event_base=0;
8559  if (XShapeQueryExtension(display,&error_base,&event_base) == 0)
8560  window_info->shape=MagickFalse;
8561 #else
8562  window_info->shape=MagickFalse;
8563 #endif
8564  }
8565  window_info->shape=MagickFalse; /* Fedora 30 has a broken shape extension */
8566  if (window_info->shared_memory != MagickFalse)
8567  {
8568 #if defined(MAGICKCORE_HAVE_SHARED_MEMORY)
8569  /*
8570  Can we use shared memory with this window?
8571  */
8572  if (XShmQueryExtension(display) == 0)
8573  window_info->shared_memory=MagickFalse;
8574 #else
8575  window_info->shared_memory=MagickFalse;
8576 #endif
8577  }
8578  window_info->image=NewImageList();
8579  window_info->destroy=MagickFalse;
8580 }
8581 
8582 /*
8583 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8584 % %
8585 % %
8586 % %
8587 % X M a g i c k P r o g r e s s M o n i t o r %
8588 % %
8589 % %
8590 % %
8591 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8592 %
8593 % XMagickProgressMonitor() displays the progress a task is making in
8594 % completing a task.
8595 %
8596 % The format of the XMagickProgressMonitor method is:
8597 %
8598 % void XMagickProgressMonitor(const char *task,
8599 % const MagickOffsetType quantum,const MagickSizeType span,
8600 % void *client_data)
8601 %
8602 % A description of each parameter follows:
8603 %
8604 % o task: Identifies the task in progress.
8605 %
8606 % o quantum: Specifies the quantum position within the span which represents
8607 % how much progress has been made in completing a task.
8608 %
8609 % o span: Specifies the span relative to completing a task.
8610 %
8611 % o client_data: Pointer to any client data.
8612 %
8613 */
8614 
8615 static const char *GetLocaleMonitorMessage(const char *text)
8616 {
8617  char
8618  message[MagickPathExtent],
8619  tag[MagickPathExtent];
8620 
8621  const char
8622  *locale_message;
8623 
8624  char
8625  *p;
8626 
8627  (void) CopyMagickString(tag,text,MagickPathExtent);
8628  p=strrchr(tag,'/');
8629  if (p != (char *) NULL)
8630  *p='\0';
8631  (void) FormatLocaleString(message,MagickPathExtent,"Monitor/%s",tag);
8632  locale_message=GetLocaleMessage(message);
8633  if (locale_message == message)
8634  return(text);
8635  return(locale_message);
8636 }
8637 
8638 MagickPrivate MagickBooleanType XMagickProgressMonitor(const char *tag,
8639  const MagickOffsetType quantum,const MagickSizeType span,
8640  void *magick_unused(client_data))
8641 {
8642  XWindows
8643  *windows;
8644 
8645  windows=XSetWindows((XWindows *) ~0);
8646  if (windows == (XWindows *) NULL)
8647  return(MagickTrue);
8648  if (windows->info.mapped != MagickFalse)
8649  XProgressMonitorWidget(windows->display,windows,
8650  GetLocaleMonitorMessage(tag),quantum,span);
8651  return(MagickTrue);
8652 }
8653 
8654 /*
8655 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8656 % %
8657 % %
8658 % %
8659 % X Q u e r y C o l o r D a t a b a s e %
8660 % %
8661 % %
8662 % %
8663 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8664 %
8665 % XQueryColorCompliance() looks up a RGB values for a color given in the target
8666 % string.
8667 %
8668 % The format of the XQueryColorDatabase method is:
8669 %
8670 % MagickBooleanType XQueryColorCompliance(const char *target,XColor *color)
8671 %
8672 % A description of each parameter follows:
8673 %
8674 % o target: Specifies the color to lookup in the X color database.
8675 %
8676 % o color: A pointer to an PixelInfo structure. The RGB value of the target
8677 % color is returned as this value.
8678 %
8679 */
8680 MagickPrivate MagickBooleanType XQueryColorCompliance(const char *target,
8681  XColor *color)
8682 {
8683  Colormap
8684  colormap;
8685 
8686  static Display
8687  *display = (Display *) NULL;
8688 
8689  Status
8690  status;
8691 
8692  XColor
8693  xcolor;
8694 
8695  /*
8696  Initialize color return value.
8697  */
8698  assert(color != (XColor *) NULL);
8699  color->red=0;
8700  color->green=0;
8701  color->blue=0;
8702  color->flags=(char) (DoRed | DoGreen | DoBlue);
8703  if ((target == (char *) NULL) || (*target == '\0'))
8704  target="#ffffffffffff";
8705  /*
8706  Let the X server define the color for us.
8707  */
8708  if (display == (Display *) NULL)
8709  display=XOpenDisplay((char *) NULL);
8710  if (display == (Display *) NULL)
8711  {
8712  ThrowXWindowException(XServerError,"ColorIsNotKnownToServer",target);
8713  return(MagickFalse);
8714  }
8715  colormap=XDefaultColormap(display,XDefaultScreen(display));
8716  status=XParseColor(display,colormap,(char *) target,&xcolor);
8717  if (status == False)
8718  ThrowXWindowException(XServerError,"ColorIsNotKnownToServer",target)
8719  else
8720  {
8721  color->red=xcolor.red;
8722  color->green=xcolor.green;
8723  color->blue=xcolor.blue;
8724  color->flags=xcolor.flags;
8725  }
8726  return(status != False ? MagickTrue : MagickFalse);
8727 }
8728 
8729 /*
8730 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8731 % %
8732 % %
8733 % %
8734 % X Q u e r y P o s i t i o n %
8735 % %
8736 % %
8737 % %
8738 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8739 %
8740 % XQueryPosition() gets the pointer coordinates relative to a window.
8741 %
8742 % The format of the XQueryPosition method is:
8743 %
8744 % void XQueryPosition(Display *display,const Window window,int *x,int *y)
8745 %
8746 % A description of each parameter follows:
8747 %
8748 % o display: Specifies a connection to an X server; returned from
8749 % XOpenDisplay.
8750 %
8751 % o window: Specifies a pointer to a Window.
8752 %
8753 % o x: Return the x coordinate of the pointer relative to the origin of the
8754 % window.
8755 %
8756 % o y: Return the y coordinate of the pointer relative to the origin of the
8757 % window.
8758 %
8759 */
8760 MagickPrivate void XQueryPosition(Display *display,const Window window,int *x,
8761  int *y)
8762 {
8763  int
8764  x_root,
8765  y_root;
8766 
8767  unsigned int
8768  mask;
8769 
8770  Window
8771  root_window;
8772 
8773  assert(display != (Display *) NULL);
8774  assert(window != (Window) NULL);
8775  assert(x != (int *) NULL);
8776  assert(y != (int *) NULL);
8777  if (IsEventLogging() != MagickFalse)
8778  (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
8779  (void) XQueryPointer(display,window,&root_window,&root_window,&x_root,&y_root,
8780  x,y,&mask);
8781 }
8782 
8783 /*
8784 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8785 % %
8786 % %
8787 % %
8788 % X R e f r e s h W i n d o w %
8789 % %
8790 % %
8791 % %
8792 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8793 %
8794 % XRefreshWindow() refreshes an image in a X window.
8795 %
8796 % The format of the XRefreshWindow method is:
8797 %
8798 % void XRefreshWindow(Display *display,const XWindowInfo *window,
8799 % const XEvent *event)
8800 %
8801 % A description of each parameter follows:
8802 %
8803 % o display: Specifies a connection to an X server; returned from
8804 % XOpenDisplay.
8805 %
8806 % o window: Specifies a pointer to a XWindowInfo structure.
8807 %
8808 % o event: Specifies a pointer to a XEvent structure. If it is NULL,
8809 % the entire image is refreshed.
8810 %
8811 */
8812 MagickPrivate void XRefreshWindow(Display *display,const XWindowInfo *window,
8813  const XEvent *event)
8814 {
8815  int
8816  x,
8817  y;
8818 
8819  unsigned int
8820  height,
8821  width;
8822 
8823  assert(display != (Display *) NULL);
8824  assert(window != (XWindowInfo *) NULL);
8825  if (IsEventLogging() != MagickFalse)
8826  (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
8827  if (window->ximage == (XImage *) NULL)
8828  return;
8829  if (event != (XEvent *) NULL)
8830  {
8831  /*
8832  Determine geometry from expose event.
8833  */
8834  x=event->xexpose.x;
8835  y=event->xexpose.y;
8836  width=(unsigned int) event->xexpose.width;
8837  height=(unsigned int) event->xexpose.height;
8838  }
8839  else
8840  {
8841  XEvent
8842  sans_event;
8843 
8844  /*
8845  Refresh entire window; discard outstanding expose events.
8846  */
8847  x=0;
8848  y=0;
8849  width=window->width;
8850  height=window->height;
8851  while (XCheckTypedWindowEvent(display,window->id,Expose,&sans_event)) ;
8852  if (window->matte_pixmap != (Pixmap) NULL)
8853  {
8854 #if defined(MAGICKCORE_HAVE_SHAPE)
8855  if (window->shape != MagickFalse)
8856  XShapeCombineMask(display,window->id,ShapeBounding,0,0,
8857  window->matte_pixmap,ShapeSet);
8858 #endif
8859  }
8860  }
8861  /*
8862  Check boundary conditions.
8863  */
8864  if ((window->ximage->width-(x+window->x)) < (int) width)
8865  width=(unsigned int) (window->ximage->width-(x+window->x));
8866  if ((window->ximage->height-(y+window->y)) < (int) height)
8867  height=(unsigned int) (window->ximage->height-(y+window->y));
8868  /*
8869  Refresh image.
8870  */
8871  if (window->matte_pixmap != (Pixmap) NULL)
8872  (void) XSetClipMask(display,window->annotate_context,window->matte_pixmap);
8873  if (window->pixmap != (Pixmap) NULL)
8874  {
8875  if (window->depth > 1)
8876  (void) XCopyArea(display,window->pixmap,window->id,
8877  window->annotate_context,x+window->x,y+window->y,width,height,x,y);
8878  else
8879  (void) XCopyPlane(display,window->pixmap,window->id,
8880  window->highlight_context,x+window->x,y+window->y,width,height,x,y,
8881  1L);
8882  }
8883  else
8884  {
8885 #if defined(MAGICKCORE_HAVE_SHARED_MEMORY)
8886  if (window->shared_memory)
8887  (void) XShmPutImage(display,window->id,window->annotate_context,
8888  window->ximage,x+window->x,y+window->y,x,y,width,height,MagickTrue);
8889 #endif
8890  if (window->shared_memory == MagickFalse)
8891  (void) XPutImage(display,window->id,window->annotate_context,
8892  window->ximage,x+window->x,y+window->y,x,y,width,height);
8893  }
8894  if (window->matte_pixmap != (Pixmap) NULL)
8895  (void) XSetClipMask(display,window->annotate_context,None);
8896  (void) XFlush(display);
8897 }
8898 
8899 /*
8900 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8901 % %
8902 % %
8903 % %
8904 % X R e m o t e C o m m a n d %
8905 % %
8906 % %
8907 % %
8908 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8909 %
8910 % XRemoteCommand() forces a remote display(1) to display the specified
8911 % image filename.
8912 %
8913 % The format of the XRemoteCommand method is:
8914 %
8915 % MagickBooleanType XRemoteCommand(Display *display,const char *window,
8916 % const char *filename)
8917 %
8918 % A description of each parameter follows:
8919 %
8920 % o display: Specifies a connection to an X server; returned from
8921 % XOpenDisplay.
8922 %
8923 % o window: Specifies the name or id of an X window.
8924 %
8925 % o filename: the name of the image filename to display.
8926 %
8927 */
8928 MagickExport MagickBooleanType XRemoteCommand(Display *display,
8929  const char *window,const char *filename)
8930 {
8931  Atom
8932  remote_atom;
8933 
8934  Window
8935  remote_window,
8936  root_window;
8937 
8938  assert(filename != (char *) NULL);
8939  if (IsEventLogging() != MagickFalse)
8940  (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",filename);
8941  if (display == (Display *) NULL)
8942  display=XOpenDisplay((char *) NULL);
8943  if (display == (Display *) NULL)
8944  {
8945  ThrowXWindowException(XServerError,"UnableToOpenXServer",filename);
8946  return(MagickFalse);
8947  }
8948  remote_atom=XInternAtom(display,"IM_PROTOCOLS",MagickFalse);
8949  remote_window=(Window) NULL;
8950  root_window=XRootWindow(display,XDefaultScreen(display));
8951  if (window != (char *) NULL)
8952  {
8953  /*
8954  Search window hierarchy and identify any clients by name or ID.
8955  */
8956  if (isdigit((int) ((unsigned char) *window)) != 0)
8957  remote_window=XWindowByID(display,root_window,(Window)
8958  strtol((char *) window,(char **) NULL,0));
8959  if (remote_window == (Window) NULL)
8960  remote_window=XWindowByName(display,root_window,window);
8961  }
8962  if (remote_window == (Window) NULL)
8963  remote_window=XWindowByProperty(display,root_window,remote_atom);
8964  if (remote_window == (Window) NULL)
8965  {
8966  ThrowXWindowException(XServerError,"UnableToConnectToRemoteDisplay",
8967  filename);
8968  return(MagickFalse);
8969  }
8970  /*
8971  Send remote command.
8972  */
8973  remote_atom=XInternAtom(display,"IM_REMOTE_COMMAND",MagickFalse);
8974  (void) XChangeProperty(display,remote_window,remote_atom,XA_STRING,8,
8975  PropModeReplace,(unsigned char *) filename,(int) strlen(filename));
8976  (void) XSync(display,MagickFalse);
8977  return(MagickTrue);
8978 }
8979 
8980 /*
8981 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8982 % %
8983 % %
8984 % %
8985 % X R e n d e r I m a g e %
8986 % %
8987 % %
8988 % %
8989 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8990 %
8991 % XRenderImage() renders text on the image with an X11 font. It also returns
8992 % the bounding box of the text relative to the image.
8993 %
8994 % The format of the XRenderImage method is:
8995 %
8996 % MagickBooleanType XRenderImage(Image *image,DrawInfo *draw_info,
8997 % const PointInfo *offset,TypeMetric *metrics,ExceptionInfo *exception)
8998 %
8999 % A description of each parameter follows:
9000 %
9001 % o image: the image.
9002 %
9003 % o draw_info: the draw info.
9004 %
9005 % o offset: (x,y) location of text relative to image.
9006 %
9007 % o metrics: bounding box of text.
9008 %
9009 % o exception: return any errors or warnings in this structure.
9010 %
9011 */
9012 MagickPrivate MagickBooleanType XRenderImage(Image *image,
9013  const DrawInfo *draw_info,const PointInfo *offset,TypeMetric *metrics,
9014  ExceptionInfo *exception)
9015 {
9016  MagickBooleanType
9017  status;
9018 
9019  size_t
9020  height,
9021  width;
9022 
9023  static Display
9024  *display = (Display *) NULL;
9025 
9026  static DrawInfo
9027  cache_info;
9028 
9029  static XAnnotateInfo
9030  annotate_info;
9031 
9032  static XFontStruct
9033  *font_info;
9034 
9035  static XPixelInfo
9036  pixel;
9037 
9038  static XResourceInfo
9039  resource_info;
9040 
9041  static XrmDatabase
9042  resource_database;
9043 
9044  static XStandardColormap
9045  *map_info;
9046 
9047  static XVisualInfo
9048  *visual_info;
9049 
9050  if (display == (Display *) NULL)
9051  {
9052  const char
9053  *client_name;
9054 
9055  ImageInfo
9056  *image_info;
9057 
9058  /*
9059  Open X server connection.
9060  */
9061  display=XOpenDisplay(draw_info->server_name);
9062  if (display == (Display *) NULL)
9063  {
9064  ThrowXWindowException(XServerError,"UnableToOpenXServer",
9065  draw_info->server_name);
9066  return(MagickFalse);
9067  }
9068  /*
9069  Get user defaults from X resource database.
9070  */
9071  (void) XSetErrorHandler(XError);
9072  image_info=AcquireImageInfo();
9073  client_name=GetClientName();
9074  resource_database=XGetResourceDatabase(display,client_name);
9075  XGetResourceInfo(image_info,resource_database,client_name,&resource_info);
9076  resource_info.close_server=MagickFalse;
9077  resource_info.colormap=PrivateColormap;
9078  resource_info.font=AcquireString(draw_info->font);
9079  resource_info.background_color=AcquireString("#ffffffffffff");
9080  resource_info.foreground_color=AcquireString("#000000000000");
9081  map_info=XAllocStandardColormap();
9082  visual_info=(XVisualInfo *) NULL;
9083  font_info=(XFontStruct *) NULL;
9084  pixel.pixels=(unsigned long *) NULL;
9085  if (map_info == (XStandardColormap *) NULL)
9086  {
9087  ThrowXWindowException(ResourceLimitError,"MemoryAllocationFailed",
9088  image->filename);
9089  return(MagickFalse);
9090  }
9091  /*
9092  Initialize visual info.
9093  */
9094  visual_info=XBestVisualInfo(display,map_info,&resource_info);
9095  if (visual_info == (XVisualInfo *) NULL)
9096  {
9097  XFreeResources(display,visual_info,map_info,&pixel,font_info,
9098  &resource_info,(XWindowInfo *) NULL);
9099  ThrowXWindowException(XServerError,"UnableToGetVisual",
9100  image->filename);
9101  return(MagickFalse);
9102  }
9103  map_info->colormap=(Colormap) NULL;
9104  /*
9105  Initialize Standard Colormap info.
9106  */
9107  XGetMapInfo(visual_info,XDefaultColormap(display,visual_info->screen),
9108  map_info);
9109  XGetPixelInfo(display,visual_info,map_info,&resource_info,(Image *) NULL,
9110  &pixel);
9111  pixel.annotate_context=XDefaultGC(display,visual_info->screen);
9112  /*
9113  Initialize font info.
9114  */
9115  font_info=XBestFont(display,&resource_info,MagickFalse);
9116  if (font_info == (XFontStruct *) NULL)
9117  {
9118  XFreeResources(display,visual_info,map_info,&pixel,font_info,
9119  &resource_info,(XWindowInfo *) NULL);
9120  ThrowXWindowException(XServerError,"UnableToLoadFont",
9121  draw_info->font);
9122  return(MagickFalse);
9123  }
9124  cache_info=(*draw_info);
9125  }
9126  /*
9127  Initialize annotate info.
9128  */
9129  XGetAnnotateInfo(&annotate_info);
9130  annotate_info.stencil=ForegroundStencil;
9131  if (cache_info.font != draw_info->font)
9132  {
9133  /*
9134  Type name has changed.
9135  */
9136  (void) XFreeFont(display,font_info);
9137  (void) CloneString(&resource_info.font,draw_info->font);
9138  font_info=XBestFont(display,&resource_info,MagickFalse);
9139  if (font_info == (XFontStruct *) NULL)
9140  {
9141  ThrowXWindowException(XServerError,"UnableToLoadFont",
9142  draw_info->font);
9143  return(MagickFalse);
9144  }
9145  }
9146  if (draw_info->debug != MagickFalse)
9147  (void) LogMagickEvent(AnnotateEvent,GetMagickModule(),
9148  "Font %s; pointsize %g",draw_info->font != (char *) NULL ?
9149  draw_info->font : "none",draw_info->pointsize);
9150  cache_info=(*draw_info);
9151  annotate_info.font_info=font_info;
9152  annotate_info.text=(char *) draw_info->text;
9153  annotate_info.width=(unsigned int) XTextWidth(font_info,draw_info->text,(int)
9154  strlen(draw_info->text));
9155  annotate_info.height=(unsigned int) (font_info->ascent+font_info->descent);
9156  metrics->pixels_per_em.x=(double) font_info->max_bounds.width;
9157  metrics->pixels_per_em.y=(double) font_info->ascent+font_info->descent;
9158  metrics->ascent=(double) font_info->ascent+4;
9159  metrics->descent=(double) (-font_info->descent);
9160  metrics->width=annotate_info.width/ExpandAffine(&draw_info->affine);
9161  metrics->height=(double) font_info->ascent+font_info->descent;
9162  metrics->max_advance=(double) font_info->max_bounds.width;
9163  metrics->bounds.x1=0.0;
9164  metrics->bounds.y1=metrics->descent;
9165  metrics->bounds.x2=metrics->ascent+metrics->descent;
9166  metrics->bounds.y2=metrics->ascent+metrics->descent;
9167  metrics->underline_position=(-2.0);
9168  metrics->underline_thickness=1.0;
9169  if (draw_info->render == MagickFalse)
9170  return(MagickTrue);
9171  if (draw_info->fill.alpha == (double) TransparentAlpha)
9172  return(MagickTrue);
9173  /*
9174  Render fill color.
9175  */
9176  width=annotate_info.width;
9177  height=annotate_info.height;
9178  if ((fabs(draw_info->affine.rx) >= MagickEpsilon) ||
9179  (fabs(draw_info->affine.ry) >= MagickEpsilon))
9180  {
9181  if ((fabs(draw_info->affine.sx-draw_info->affine.sy) < MagickEpsilon) &&
9182  (fabs(draw_info->affine.rx+draw_info->affine.ry) < MagickEpsilon))
9183  annotate_info.degrees=(double) (180.0/MagickPI)*
9184  atan2(draw_info->affine.rx,draw_info->affine.sx);
9185  }
9186  (void) FormatLocaleString(annotate_info.geometry,MagickPathExtent,
9187  "%.20gx%.20g%+.20g%+.20g",(double) width,(double) height,
9188  ceil(offset->x-0.5),ceil(offset->y-metrics->ascent-metrics->descent+
9189  draw_info->interline_spacing-0.5));
9190  pixel.pen_color.red=ScaleQuantumToShort(
9191  ClampToQuantum(draw_info->fill.red));
9192  pixel.pen_color.green=ScaleQuantumToShort(
9193  ClampToQuantum(draw_info->fill.green));
9194  pixel.pen_color.blue=ScaleQuantumToShort(
9195  ClampToQuantum(draw_info->fill.blue));
9196  status=XAnnotateImage(display,&pixel,&annotate_info,image,exception);
9197  if (status == 0)
9198  {
9199  ThrowXWindowException(ResourceLimitError,"MemoryAllocationFailed",
9200  image->filename);
9201  return(MagickFalse);
9202  }
9203  return(MagickTrue);
9204 }
9205 
9206 /*
9207 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9208 % %
9209 % %
9210 % %
9211 % X R e t a i n W i n d o w C o l o r s %
9212 % %
9213 % %
9214 % %
9215 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9216 %
9217 % XRetainWindowColors() sets X11 color resources on a window. This preserves
9218 % the colors associated with an image displayed on the window.
9219 %
9220 % The format of the XRetainWindowColors method is:
9221 %
9222 % void XRetainWindowColors(Display *display,const Window window)
9223 %
9224 % A description of each parameter follows:
9225 %
9226 % o display: Specifies a connection to an X server; returned from
9227 % XOpenDisplay.
9228 %
9229 % o window: Specifies a pointer to a XWindowInfo structure.
9230 %
9231 */
9232 MagickExport void XRetainWindowColors(Display *display,const Window window)
9233 {
9234  Atom
9235  property;
9236 
9237  Pixmap
9238  pixmap;
9239 
9240  /*
9241  Put property on the window.
9242  */
9243  assert(display != (Display *) NULL);
9244  assert(window != (Window) NULL);
9245  if (IsEventLogging() != MagickFalse)
9246  (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
9247  property=XInternAtom(display,"_XSETROOT_ID",MagickFalse);
9248  if (property == (Atom) NULL)
9249  {
9250  ThrowXWindowException(XServerError,"UnableToCreateProperty",
9251  "_XSETROOT_ID");
9252  return;
9253  }
9254  pixmap=XCreatePixmap(display,window,1,1,1);
9255  if (pixmap == (Pixmap) NULL)
9256  {
9257  ThrowXWindowException(XServerError,"UnableToCreateBitmap","");
9258  return;
9259  }
9260  (void) XChangeProperty(display,window,property,XA_PIXMAP,32,PropModeReplace,
9261  (unsigned char *) &pixmap,1);
9262  (void) XSetCloseDownMode(display,RetainPermanent);
9263 }
9264 
9265 /*
9266 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9267 % %
9268 % %
9269 % %
9270 % X S e l e c t W i n d o w %
9271 % %
9272 % %
9273 % %
9274 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9275 %
9276 % XSelectWindow() allows a user to select a window using the mouse. If the
9277 % mouse moves, a cropping rectangle is drawn and the extents of the rectangle
9278 % is returned in the crop_info structure.
9279 %
9280 % The format of the XSelectWindow function is:
9281 %
9282 % target_window=XSelectWindow(display,crop_info)
9283 %
9284 % A description of each parameter follows:
9285 %
9286 % o window: XSelectWindow returns the window id.
9287 %
9288 % o display: Specifies a pointer to the Display structure; returned from
9289 % XOpenDisplay.
9290 %
9291 % o crop_info: Specifies a pointer to a RectangleInfo structure. It
9292 % contains the extents of any cropping rectangle.
9293 %
9294 */
9295 static Window XSelectWindow(Display *display,RectangleInfo *crop_info)
9296 {
9297 #define MinimumCropArea (unsigned int) 9
9298 
9299  Cursor
9300  target_cursor;
9301 
9302  GC
9303  annotate_context;
9304 
9305  int
9306  presses,
9307  x_offset,
9308  y_offset;
9309 
9310  Status
9311  status;
9312 
9313  Window
9314  root_window,
9315  target_window;
9316 
9317  XEvent
9318  event;
9319 
9320  XGCValues
9321  context_values;
9322 
9323  /*
9324  Initialize graphic context.
9325  */
9326  assert(display != (Display *) NULL);
9327  assert(crop_info != (RectangleInfo *) NULL);
9328  if (IsEventLogging() != MagickFalse)
9329  (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
9330  root_window=XRootWindow(display,XDefaultScreen(display));
9331  context_values.background=XBlackPixel(display,XDefaultScreen(display));
9332  context_values.foreground=XWhitePixel(display,XDefaultScreen(display));
9333  context_values.function=GXinvert;
9334  context_values.plane_mask=
9335  context_values.background ^ context_values.foreground;
9336  context_values.subwindow_mode=IncludeInferiors;
9337  annotate_context=XCreateGC(display,root_window,(size_t) (GCBackground |
9338  GCForeground | GCFunction | GCSubwindowMode),&context_values);
9339  if (annotate_context == (GC) NULL)
9340  return((Window) NULL);
9341  /*
9342  Grab the pointer using target cursor.
9343  */
9344  target_cursor=XMakeCursor(display,root_window,XDefaultColormap(display,
9345  XDefaultScreen(display)),(char * ) "white",(char * ) "black");
9346  status=XGrabPointer(display,root_window,MagickFalse,(unsigned int)
9347  (ButtonPressMask | ButtonReleaseMask | ButtonMotionMask),GrabModeSync,
9348  GrabModeAsync,root_window,target_cursor,CurrentTime);
9349  if (status != GrabSuccess)
9350  {
9351  ThrowXWindowException(XServerError,"UnableToGrabMouse","");
9352  return((Window) NULL);
9353  }
9354  /*
9355  Select a window.
9356  */
9357  crop_info->width=0;
9358  crop_info->height=0;
9359  presses=0;
9360  target_window=(Window) NULL;
9361  x_offset=0;
9362  y_offset=0;
9363  (void) XGrabServer(display);
9364  do
9365  {
9366  if ((crop_info->width*crop_info->height) >= MinimumCropArea)
9367  (void) XDrawRectangle(display,root_window,annotate_context,
9368  (int) crop_info->x,(int) crop_info->y,(unsigned int) crop_info->width-1,
9369  (unsigned int) crop_info->height-1);
9370  /*
9371  Allow another event.
9372  */
9373  (void) XAllowEvents(display,SyncPointer,CurrentTime);
9374  (void) XWindowEvent(display,root_window,ButtonPressMask |
9375  ButtonReleaseMask | ButtonMotionMask,&event);
9376  if ((crop_info->width*crop_info->height) >= MinimumCropArea)
9377  (void) XDrawRectangle(display,root_window,annotate_context,
9378  (int) crop_info->x,(int) crop_info->y,(unsigned int) crop_info->width-1,
9379  (unsigned int) crop_info->height-1);
9380  switch (event.type)
9381  {
9382  case ButtonPress:
9383  {
9384  target_window=XGetSubwindow(display,event.xbutton.subwindow,
9385  event.xbutton.x,event.xbutton.y);
9386  if (target_window == (Window) NULL)
9387  target_window=root_window;
9388  x_offset=event.xbutton.x_root;
9389  y_offset=event.xbutton.y_root;
9390  crop_info->x=(ssize_t) x_offset;
9391  crop_info->y=(ssize_t) y_offset;
9392  crop_info->width=0;
9393  crop_info->height=0;
9394  presses++;
9395  break;
9396  }
9397  case ButtonRelease:
9398  {
9399  presses--;
9400  break;
9401  }
9402  case MotionNotify:
9403  {
9404  /*
9405  Discard pending button motion events.
9406  */
9407  while (XCheckMaskEvent(display,ButtonMotionMask,&event)) ;
9408  crop_info->x=(ssize_t) event.xmotion.x;
9409  crop_info->y=(ssize_t) event.xmotion.y;
9410  /*
9411  Check boundary conditions.
9412  */
9413  if ((int) crop_info->x < x_offset)
9414  crop_info->width=(size_t) (x_offset-crop_info->x);
9415  else
9416  {
9417  crop_info->width=(size_t) (crop_info->x-x_offset);
9418  crop_info->x=(ssize_t) x_offset;
9419  }
9420  if ((int) crop_info->y < y_offset)
9421  crop_info->height=(size_t) (y_offset-crop_info->y);
9422  else
9423  {
9424  crop_info->height=(size_t) (crop_info->y-y_offset);
9425  crop_info->y=(ssize_t) y_offset;
9426  }
9427  }
9428  default:
9429  break;
9430  }
9431  } while ((target_window == (Window) NULL) || (presses > 0));
9432  (void) XUngrabServer(display);
9433  (void) XUngrabPointer(display,CurrentTime);
9434  (void) XFreeCursor(display,target_cursor);
9435  (void) XFreeGC(display,annotate_context);
9436  if ((crop_info->width*crop_info->height) < MinimumCropArea)
9437  {
9438  crop_info->width=0;
9439  crop_info->height=0;
9440  }
9441  if ((crop_info->width != 0) && (crop_info->height != 0))
9442  target_window=root_window;
9443  if (event.xbutton.button == Button3)
9444  target_window=(Window) NULL;
9445  return(target_window);
9446 }
9447 
9448 /*
9449 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9450 % %
9451 % %
9452 % %
9453 % X S e t C u r s o r S t a t e %
9454 % %
9455 % %
9456 % %
9457 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9458 %
9459 % XSetCursorState() sets the cursor state to busy, otherwise the cursor are
9460 % reset to their default.
9461 %
9462 % The format of the XXSetCursorState method is:
9463 %
9464 % XSetCursorState(display,windows,const MagickStatusType state)
9465 %
9466 % A description of each parameter follows:
9467 %
9468 % o display: Specifies a connection to an X server; returned from
9469 % XOpenDisplay.
9470 %
9471 % o windows: Specifies a pointer to a XWindows structure.
9472 %
9473 % o state: An unsigned integer greater than 0 sets the cursor state
9474 % to busy, otherwise the cursor are reset to their default.
9475 %
9476 */
9477 MagickPrivate void XSetCursorState(Display *display,XWindows *windows,
9478  const MagickStatusType state)
9479 {
9480  assert(display != (Display *) NULL);
9481  assert(windows != (XWindows *) NULL);
9482  if (IsEventLogging() != MagickFalse)
9483  (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
9484  if (state)
9485  {
9486  (void) XCheckDefineCursor(display,windows->image.id,
9487  windows->image.busy_cursor);
9488  (void) XCheckDefineCursor(display,windows->pan.id,
9489  windows->pan.busy_cursor);
9490  (void) XCheckDefineCursor(display,windows->magnify.id,
9491  windows->magnify.busy_cursor);
9492  (void) XCheckDefineCursor(display,windows->command.id,
9493  windows->command.busy_cursor);
9494  }
9495  else
9496  {
9497  (void) XCheckDefineCursor(display,windows->image.id,
9498  windows->image.cursor);
9499  (void) XCheckDefineCursor(display,windows->pan.id,windows->pan.cursor);
9500  (void) XCheckDefineCursor(display,windows->magnify.id,
9501  windows->magnify.cursor);
9502  (void) XCheckDefineCursor(display,windows->command.id,
9503  windows->command.cursor);
9504  (void) XCheckDefineCursor(display,windows->command.id,
9505  windows->widget.cursor);
9506  (void) XWithdrawWindow(display,windows->info.id,windows->info.screen);
9507  }
9508  windows->info.mapped=MagickFalse;
9509 }
9510 
9511 /*
9512 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9513 % %
9514 % %
9515 % %
9516 % X S e t W i n d o w s %
9517 % %
9518 % %
9519 % %
9520 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9521 %
9522 % XSetWindows() sets the X windows structure if the windows info is specified.
9523 % Otherwise the current windows structure is returned.
9524 %
9525 % The format of the XSetWindows method is:
9526 %
9527 % XWindows *XSetWindows(XWindows *windows_info)
9528 %
9529 % A description of each parameter follows:
9530 %
9531 % o windows_info: Initialize the Windows structure with this information.
9532 %
9533 */
9534 MagickPrivate XWindows *XSetWindows(XWindows *windows_info)
9535 {
9536  static XWindows
9537  *windows = (XWindows *) NULL;
9538 
9539  if (windows_info != (XWindows *) ~0)
9540  {
9541  windows=(XWindows *) RelinquishMagickMemory(windows);
9542  windows=windows_info;
9543  }
9544  return(windows);
9545 }
9546 /*
9547 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9548 % %
9549 % %
9550 % %
9551 % X U s e r P r e f e r e n c e s %
9552 % %
9553 % %
9554 % %
9555 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9556 %
9557 % XUserPreferences() saves the preferences in a configuration file in the
9558 % users' home directory.
9559 %
9560 % The format of the XUserPreferences method is:
9561 %
9562 % void XUserPreferences(XResourceInfo *resource_info)
9563 %
9564 % A description of each parameter follows:
9565 %
9566 % o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
9567 %
9568 */
9569 MagickPrivate void XUserPreferences(XResourceInfo *resource_info)
9570 {
9571 #if defined(X11_PREFERENCES_PATH)
9572  char
9573  cache[MagickPathExtent],
9574  filename[MagickPathExtent],
9575  specifier[MagickPathExtent];
9576 
9577  const char
9578  *client_name,
9579  *value;
9580 
9581  XrmDatabase
9582  preferences_database;
9583 
9584  /*
9585  Save user preferences to the client configuration file.
9586  */
9587  assert(resource_info != (XResourceInfo *) NULL);
9588  client_name=GetClientName();
9589  preferences_database=XrmGetStringDatabase("");
9590  (void) FormatLocaleString(specifier,MagickPathExtent,"%s.backdrop",client_name);
9591  value=resource_info->backdrop ? "True" : "False";
9592  XrmPutStringResource(&preferences_database,specifier,(char *) value);
9593  (void) FormatLocaleString(specifier,MagickPathExtent,"%s.colormap",client_name);
9594  value=resource_info->colormap == SharedColormap ? "Shared" : "Private";
9595  XrmPutStringResource(&preferences_database,specifier,(char *) value);
9596  (void) FormatLocaleString(specifier,MagickPathExtent,"%s.confirmExit",
9597  client_name);
9598  value=resource_info->confirm_exit ? "True" : "False";
9599  XrmPutStringResource(&preferences_database,specifier,(char *) value);
9600  (void) FormatLocaleString(specifier,MagickPathExtent,"%s.confirmEdit",
9601  client_name);
9602  value=resource_info->confirm_edit ? "True" : "False";
9603  XrmPutStringResource(&preferences_database,specifier,(char *) value);
9604  (void) FormatLocaleString(specifier,MagickPathExtent,"%s.displayWarnings",
9605  client_name);
9606  value=resource_info->display_warnings ? "True" : "False";
9607  XrmPutStringResource(&preferences_database,specifier,(char *) value);
9608  (void) FormatLocaleString(specifier,MagickPathExtent,"%s.dither",client_name);
9609  value=resource_info->quantize_info->dither_method != NoDitherMethod ?
9610  "True" : "False";
9611  XrmPutStringResource(&preferences_database,specifier,(char *) value);
9612  (void) FormatLocaleString(specifier,MagickPathExtent,"%s.gammaCorrect",
9613  client_name);
9614  value=resource_info->gamma_correct ? "True" : "False";
9615  XrmPutStringResource(&preferences_database,specifier,(char *) value);
9616  (void) FormatLocaleString(specifier,MagickPathExtent,"%s.undoCache",client_name);
9617  (void) FormatLocaleString(cache,MagickPathExtent,"%.20g",(double)
9618  resource_info->undo_cache);
9619  XrmPutStringResource(&preferences_database,specifier,cache);
9620  (void) FormatLocaleString(specifier,MagickPathExtent,"%s.usePixmap",client_name);
9621  value=resource_info->use_pixmap ? "True" : "False";
9622  XrmPutStringResource(&preferences_database,specifier,(char *) value);
9623  (void) FormatLocaleString(filename,MagickPathExtent,"%s%src",
9624  X11_PREFERENCES_PATH,client_name);
9625  ExpandFilename(filename);
9626  XrmPutFileDatabase(preferences_database,filename);
9627 #endif
9628 }
9629 
9630 /*
9631 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9632 % %
9633 % %
9634 % %
9635 % X V i s u a l C l a s s N a m e %
9636 % %
9637 % %
9638 % %
9639 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9640 %
9641 % XVisualClassName() returns the visual class name as a character string.
9642 %
9643 % The format of the XVisualClassName method is:
9644 %
9645 % char *XVisualClassName(const int visual_class)
9646 %
9647 % A description of each parameter follows:
9648 %
9649 % o visual_type: XVisualClassName returns the visual class as a character
9650 % string.
9651 %
9652 % o class: Specifies the visual class.
9653 %
9654 */
9655 static const char *XVisualClassName(const int visual_class)
9656 {
9657  switch (visual_class)
9658  {
9659  case StaticGray: return("StaticGray");
9660  case GrayScale: return("GrayScale");
9661  case StaticColor: return("StaticColor");
9662  case PseudoColor: return("PseudoColor");
9663  case TrueColor: return("TrueColor");
9664  case DirectColor: return("DirectColor");
9665  }
9666  return("unknown visual class");
9667 }
9668 
9669 /*
9670 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9671 % %
9672 % %
9673 % %
9674 % X W a r n i n g %
9675 % %
9676 % %
9677 % %
9678 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9679 %
9680 % XWarning() displays a warning reason in a Notice widget.
9681 %
9682 % The format of the XWarning method is:
9683 %
9684 % void XWarning(const unsigned int warning,const char *reason,
9685 % const char *description)
9686 %
9687 % A description of each parameter follows:
9688 %
9689 % o warning: Specifies the numeric warning category.
9690 %
9691 % o reason: Specifies the reason to display before terminating the
9692 % program.
9693 %
9694 % o description: Specifies any description to the reason.
9695 %
9696 */
9697 MagickPrivate void XWarning(const ExceptionType magick_unused(warning),
9698  const char *reason,const char *description)
9699 {
9700  char
9701  text[MagickPathExtent];
9702 
9703  XWindows
9704  *windows;
9705 
9706  if (reason == (char *) NULL)
9707  return;
9708  (void) CopyMagickString(text,reason,MagickPathExtent);
9709  (void) ConcatenateMagickString(text,":",MagickPathExtent);
9710  windows=XSetWindows((XWindows *) ~0);
9711  XNoticeWidget(windows->display,windows,text,(char *) description);
9712 }
9713 
9714 /*
9715 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9716 % %
9717 % %
9718 % %
9719 % X W i n d o w B y I D %
9720 % %
9721 % %
9722 % %
9723 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9724 %
9725 % XWindowByID() locates a child window with a given ID. If not window with
9726 % the given name is found, 0 is returned. Only the window specified and its
9727 % subwindows are searched.
9728 %
9729 % The format of the XWindowByID function is:
9730 %
9731 % child=XWindowByID(display,window,id)
9732 %
9733 % A description of each parameter follows:
9734 %
9735 % o child: XWindowByID returns the window with the specified
9736 % id. If no windows are found, XWindowByID returns 0.
9737 %
9738 % o display: Specifies a pointer to the Display structure; returned from
9739 % XOpenDisplay.
9740 %
9741 % o id: Specifies the id of the window to locate.
9742 %
9743 */
9744 MagickPrivate Window XWindowByID(Display *display,const Window root_window,
9745  const size_t id)
9746 {
9748  rectangle_info;
9749 
9750  int
9751  i;
9752 
9753  Status
9754  status;
9755 
9756  unsigned int
9757  number_children;
9758 
9759  Window
9760  child,
9761  *children,
9762  window;
9763 
9764  assert(display != (Display *) NULL);
9765  assert(root_window != (Window) NULL);
9766  if (IsEventLogging() != MagickFalse)
9767  (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
9768  if (id == 0)
9769  return(XSelectWindow(display,&rectangle_info));
9770  if (root_window == id)
9771  return(root_window);
9772  status=XQueryTree(display,root_window,&child,&child,&children,
9773  &number_children);
9774  if (status == False)
9775  return((Window) NULL);
9776  window=(Window) NULL;
9777  for (i=0; i < (int) number_children; i++)
9778  {
9779  /*
9780  Search each child and their children.
9781  */
9782  window=XWindowByID(display,children[i],id);
9783  if (window != (Window) NULL)
9784  break;
9785  }
9786  if (children != (Window *) NULL)
9787  (void) XFree((void *) children);
9788  return(window);
9789 }
9790 
9791 /*
9792 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9793 % %
9794 % %
9795 % %
9796 % X W i n d o w B y N a m e %
9797 % %
9798 % %
9799 % %
9800 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9801 %
9802 % XWindowByName() locates a window with a given name on a display. If no
9803 % window with the given name is found, 0 is returned. If more than one window
9804 % has the given name, the first one is returned. Only root and its children
9805 % are searched.
9806 %
9807 % The format of the XWindowByName function is:
9808 %
9809 % window=XWindowByName(display,root_window,name)
9810 %
9811 % A description of each parameter follows:
9812 %
9813 % o window: XWindowByName returns the window id.
9814 %
9815 % o display: Specifies a pointer to the Display structure; returned from
9816 % XOpenDisplay.
9817 %
9818 % o root_window: Specifies the id of the root window.
9819 %
9820 % o name: Specifies the name of the window to locate.
9821 %
9822 */
9823 MagickPrivate Window XWindowByName(Display *display,const Window root_window,
9824  const char *name)
9825 {
9826  int
9827  i;
9828 
9829  Status
9830  status;
9831 
9832  unsigned int
9833  number_children;
9834 
9835  Window
9836  *children,
9837  child,
9838  window;
9839 
9840  XTextProperty
9841  window_name;
9842 
9843  assert(display != (Display *) NULL);
9844  assert(root_window != (Window) NULL);
9845  assert(name != (char *) NULL);
9846  if (IsEventLogging() != MagickFalse)
9847  (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",name);
9848  if (XGetWMName(display,root_window,&window_name) != 0)
9849  if (LocaleCompare((char *) window_name.value,name) == 0)
9850  return(root_window);
9851  status=XQueryTree(display,root_window,&child,&child,&children,
9852  &number_children);
9853  if (status == False)
9854  return((Window) NULL);
9855  window=(Window) NULL;
9856  for (i=0; i < (int) number_children; i++)
9857  {
9858  /*
9859  Search each child and their children.
9860  */
9861  window=XWindowByName(display,children[i],name);
9862  if (window != (Window) NULL)
9863  break;
9864  }
9865  if (children != (Window *) NULL)
9866  (void) XFree((void *) children);
9867  return(window);
9868 }
9869 
9870 /*
9871 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9872 % %
9873 % %
9874 % %
9875 % X W i n d o w B y P r o p e r y %
9876 % %
9877 % %
9878 % %
9879 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9880 %
9881 % XWindowByProperty() locates a child window with a given property. If not
9882 % window with the given name is found, 0 is returned. If more than one window
9883 % has the given property, the first one is returned. Only the window
9884 % specified and its subwindows are searched.
9885 %
9886 % The format of the XWindowByProperty function is:
9887 %
9888 % child=XWindowByProperty(display,window,property)
9889 %
9890 % A description of each parameter follows:
9891 %
9892 % o child: XWindowByProperty returns the window id with the specified
9893 % property. If no windows are found, XWindowByProperty returns 0.
9894 %
9895 % o display: Specifies a pointer to the Display structure; returned from
9896 % XOpenDisplay.
9897 %
9898 % o property: Specifies the property of the window to locate.
9899 %
9900 */
9901 MagickPrivate Window XWindowByProperty(Display *display,const Window window,
9902  const Atom property)
9903 {
9904  Atom
9905  type;
9906 
9907  int
9908  format;
9909 
9910  Status
9911  status;
9912 
9913  unsigned char
9914  *data;
9915 
9916  unsigned int
9917  i,
9918  number_children;
9919 
9920  unsigned long
9921  after,
9922  number_items;
9923 
9924  Window
9925  child,
9926  *children,
9927  parent,
9928  root;
9929 
9930  assert(display != (Display *) NULL);
9931  assert(window != (Window) NULL);
9932  assert(property != (Atom) NULL);
9933  if (IsEventLogging() != MagickFalse)
9934  (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
9935  status=XQueryTree(display,window,&root,&parent,&children,&number_children);
9936  if (status == False)
9937  return((Window) NULL);
9938  type=(Atom) NULL;
9939  child=(Window) NULL;
9940  for (i=0; (i < number_children) && (child == (Window) NULL); i++)
9941  {
9942  status=XGetWindowProperty(display,children[i],property,0L,0L,MagickFalse,
9943  (Atom) AnyPropertyType,&type,&format,&number_items,&after,&data);
9944  if (data != NULL)
9945  (void) XFree((void *) data);
9946  if ((status == Success) && (type != (Atom) NULL))
9947  child=children[i];
9948  }
9949  for (i=0; (i < number_children) && (child == (Window) NULL); i++)
9950  child=XWindowByProperty(display,children[i],property);
9951  if (children != (Window *) NULL)
9952  (void) XFree((void *) children);
9953  return(child);
9954 }
9955 #else
9956 
9957 /*
9958 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9959 % %
9960 % %
9961 % %
9962 % X I m p o r t I m a g e %
9963 % %
9964 % %
9965 % %
9966 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9967 %
9968 % XImportImage() reads an image from an X window.
9969 %
9970 % The format of the XImportImage method is:
9971 %
9972 % Image *XImportImage(const ImageInfo *image_info,XImportInfo *ximage_info,
9973 % ExceptionInfo *exception)
9974 %
9975 % A description of each parameter follows:
9976 %
9977 % o image_info: the image info..
9978 %
9979 % o ximage_info: Specifies a pointer to an XImportInfo structure.
9980 %
9981 % o exception: return any errors or warnings in this structure.
9982 %
9983 */
9984 MagickExport Image *XImportImage(const ImageInfo *image_info,
9985  XImportInfo *ximage_info,ExceptionInfo *exception)
9986 {
9987  assert(image_info != (const ImageInfo *) NULL);
9988  assert(image_info->signature == MagickCoreSignature);
9989  assert(ximage_info != (XImportInfo *) NULL);
9990  assert(exception != (ExceptionInfo *) NULL);
9991  assert(exception->signature == MagickCoreSignature);
9992  if (IsEventLogging() != MagickFalse)
9993  (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
9994  image_info->filename);
9995  (void) ximage_info;
9996  (void) exception;
9997  return((Image *) NULL);
9998 }
9999 
10000 /*
10001 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
10002 % %
10003 % %
10004 % %
10005 % X R e n d e r X 1 1 %
10006 % %
10007 % %
10008 % %
10009 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
10010 %
10011 % XRenderImage() renders text on the image with an X11 font. It also returns
10012 % the bounding box of the text relative to the image.
10013 %
10014 % The format of the XRenderImage method is:
10015 %
10016 % MagickBooleanType XRenderImage(Image *image,DrawInfo *draw_info,
10017 % const PointInfo *offset,TypeMetric *metrics,ExceptionInfo *exception)
10018 %
10019 % A description of each parameter follows:
10020 %
10021 % o image: the image.
10022 %
10023 % o draw_info: the draw info.
10024 %
10025 % o offset: (x,y) location of text relative to image.
10026 %
10027 % o metrics: bounding box of text.
10028 %
10029 % o exception: return any errors or warnings in this structure.
10030 %
10031 */
10032 MagickPrivate MagickBooleanType XRenderImage(Image *image,
10033  const DrawInfo *draw_info,const PointInfo *offset,TypeMetric *metrics,
10034  ExceptionInfo *exception)
10035 {
10036  (void) draw_info;
10037  (void) offset;
10038  (void) metrics;
10039  (void) ThrowMagickException(exception,GetMagickModule(),
10040  MissingDelegateError,"DelegateLibrarySupportNotBuiltIn","'%s' (X11)",
10041  image->filename);
10042  return(MagickFalse);
10043 }
10044 #endif
10045 
10046 /*
10047 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
10048 % %
10049 % %
10050 % %
10051 + X C o m p o n e n t G e n e s i s %
10052 % %
10053 % %
10054 % %
10055 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
10056 %
10057 % XComponentGenesis() instantiates the X component.
10058 %
10059 % The format of the XComponentGenesis method is:
10060 %
10061 % MagickBooleanType XComponentGenesis(void)
10062 %
10063 */
10064 MagickPrivate MagickBooleanType XComponentGenesis(void)
10065 {
10066  return(MagickTrue);
10067 }
10068 
10069 /*
10070 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
10071 % %
10072 % %
10073 % %
10074 % X G e t I m p o r t I n f o %
10075 % %
10076 % %
10077 % %
10078 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
10079 %
10080 % XGetImportInfo() initializes the XImportInfo structure.
10081 %
10082 % The format of the XGetImportInfo method is:
10083 %
10084 % void XGetImportInfo(XImportInfo *ximage_info)
10085 %
10086 % A description of each parameter follows:
10087 %
10088 % o ximage_info: Specifies a pointer to an ImageInfo structure.
10089 %
10090 */
10091 MagickExport void XGetImportInfo(XImportInfo *ximage_info)
10092 {
10093  assert(ximage_info != (XImportInfo *) NULL);
10094  ximage_info->frame=MagickFalse;
10095  ximage_info->borders=MagickFalse;
10096  ximage_info->screen=MagickFalse;
10097  ximage_info->descend=MagickTrue;
10098  ximage_info->silent=MagickFalse;
10099 }
_XImportInfo
Definition: xwindow.h:25
_RectangleInfo
Definition: geometry.h:129
_GeometryInfo
Definition: geometry.h:105
_CacheView
Definition: cache-view.c:65
_Image
Definition: image.h:131
_PixelInfo
Definition: pixel.h:181
_QuantizeInfo
Definition: quantize.h:35
_ImageInfo
Definition: image.h:358
_TypeMetric
Definition: draw.h:380
_ExceptionInfo
Definition: exception.h:101
_PointInfo
Definition: geometry.h:122
_ColormapInfo
Definition: color.c:84
_DrawInfo
Definition: draw.h:209