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