MagickCore  6.9.12-92
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(((double) QuantumScale*(color)),1.0* \
110  PerceptibleReciprocal((double) blue_gamma))*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(((double) QuantumScale*(color)),1.0* \
120  PerceptibleReciprocal((double) green_gamma))*QuantumRange)))
121 #define XRedGamma(color) ClampToQuantum(red_gamma == 1.0 ? (double) \
122  (color) : ((pow(((double) QuantumScale*(color)),1.0* \
123  PerceptibleReciprocal((double) red_gamma))*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  (void) XSetWindows((XWindows *) NULL);
423 }
424 ␌
425 /*
426 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
427 % %
428 % %
429 % %
430 % X A n n o t a t e I m a g e %
431 % %
432 % %
433 % %
434 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
435 %
436 % XAnnotateImage() annotates the image with text.
437 %
438 % The format of the XAnnotateImage method is:
439 %
440 % MagickBooleanType XAnnotateImage(Display *display,
441 % const XPixelInfo *pixel,XAnnotateInfo *annotate_info,Image *image)
442 %
443 % A description of each parameter follows:
444 %
445 % o display: Specifies a connection to an X server; returned from
446 % XOpenDisplay.
447 %
448 % o pixel: Specifies a pointer to a XPixelInfo structure.
449 %
450 % o annotate_info: Specifies a pointer to a XAnnotateInfo structure.
451 %
452 % o image: the image.
453 %
454 */
455 MagickExport MagickBooleanType XAnnotateImage(Display *display,
456  const XPixelInfo *pixel,XAnnotateInfo *annotate_info,Image *image)
457 {
458  CacheView
459  *annotate_view;
460 
461  GC
462  annotate_context;
463 
465  *exception;
466 
467  Image
468  *annotate_image;
469 
470  int
471  x,
472  y;
473 
474  MagickBooleanType
475  matte;
476 
477  Pixmap
478  annotate_pixmap;
479 
480  unsigned int
481  depth,
482  height,
483  width;
484 
485  Window
486  root_window;
487 
488  XGCValues
489  context_values;
490 
491  XImage
492  *annotate_ximage;
493 
494  /*
495  Initialize annotated image.
496  */
497  assert(display != (Display *) NULL);
498  assert(pixel != (XPixelInfo *) NULL);
499  assert(annotate_info != (XAnnotateInfo *) NULL);
500  assert(image != (Image *) NULL);
501  if (IsEventLogging() != MagickFalse)
502  (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
503  /*
504  Initialize annotated pixmap.
505  */
506  root_window=XRootWindow(display,XDefaultScreen(display));
507  depth=(unsigned int) XDefaultDepth(display,XDefaultScreen(display));
508  annotate_pixmap=XCreatePixmap(display,root_window,annotate_info->width,
509  annotate_info->height,depth);
510  if (annotate_pixmap == (Pixmap) NULL)
511  return(MagickFalse);
512  /*
513  Initialize graphics info.
514  */
515  context_values.background=0;
516  context_values.foreground=(size_t) (~0);
517  context_values.font=annotate_info->font_info->fid;
518  annotate_context=XCreateGC(display,root_window,(unsigned long)
519  (GCBackground | GCFont | GCForeground),&context_values);
520  if (annotate_context == (GC) NULL)
521  return(MagickFalse);
522  /*
523  Draw text to pixmap.
524  */
525  (void) XDrawImageString(display,annotate_pixmap,annotate_context,0,
526  (int) annotate_info->font_info->ascent,annotate_info->text,
527  (int) strlen(annotate_info->text));
528  (void) XFreeGC(display,annotate_context);
529  /*
530  Initialize annotated X image.
531  */
532  annotate_ximage=XGetImage(display,annotate_pixmap,0,0,annotate_info->width,
533  annotate_info->height,AllPlanes,ZPixmap);
534  if (annotate_ximage == (XImage *) NULL)
535  return(MagickFalse);
536  (void) XFreePixmap(display,annotate_pixmap);
537  /*
538  Initialize annotated image.
539  */
540  annotate_image=AcquireImage((ImageInfo *) NULL);
541  if (annotate_image == (Image *) NULL)
542  return(MagickFalse);
543  annotate_image->columns=annotate_info->width;
544  annotate_image->rows=annotate_info->height;
545  /*
546  Transfer annotated X image to image.
547  */
548  width=(unsigned int) image->columns;
549  height=(unsigned int) image->rows;
550  x=0;
551  y=0;
552  (void) XParseGeometry(annotate_info->geometry,&x,&y,&width,&height);
553  (void) GetOneVirtualPixel(image,(ssize_t) x,(ssize_t) y,
554  &annotate_image->background_color,&image->exception);
555  if (annotate_info->stencil == ForegroundStencil)
556  annotate_image->matte=MagickTrue;
557  exception=(&image->exception);
558  annotate_view=AcquireAuthenticCacheView(annotate_image,exception);
559  for (y=0; y < (int) annotate_image->rows; y++)
560  {
561  int
562  x;
563 
565  *magick_restrict q;
566 
567  q=GetCacheViewAuthenticPixels(annotate_view,0,(ssize_t) y,
568  annotate_image->columns,1,exception);
569  if (q == (PixelPacket *) NULL)
570  break;
571  for (x=0; x < (int) annotate_image->columns; x++)
572  {
573  SetPixelOpacity(q,OpaqueOpacity);
574  if (XGetPixel(annotate_ximage,x,y) == 0)
575  {
576  /*
577  Set this pixel to the background color.
578  */
579  SetPixelRed(q,ScaleShortToQuantum(pixel->box_color.red));
580  SetPixelGreen(q,ScaleShortToQuantum(pixel->box_color.green));
581  SetPixelBlue(q,ScaleShortToQuantum(pixel->box_color.blue));
582  if ((annotate_info->stencil == ForegroundStencil) ||
583  (annotate_info->stencil == OpaqueStencil))
584  SetPixelOpacity(q,TransparentOpacity);
585  }
586  else
587  {
588  /*
589  Set this pixel to the pen color.
590  */
591  SetPixelRed(q,ScaleShortToQuantum(pixel->pen_color.red));
592  SetPixelGreen(q,ScaleShortToQuantum(pixel->pen_color.green));
593  SetPixelBlue(q,ScaleShortToQuantum(pixel->pen_color.blue));
594  if (annotate_info->stencil == BackgroundStencil)
595  SetPixelOpacity(q,TransparentOpacity);
596  }
597  q++;
598  }
599  if (SyncCacheViewAuthenticPixels(annotate_view,exception) == MagickFalse)
600  break;
601  }
602  annotate_view=DestroyCacheView(annotate_view);
603  XDestroyImage(annotate_ximage);
604  /*
605  Determine annotate geometry.
606  */
607  (void) XParseGeometry(annotate_info->geometry,&x,&y,&width,&height);
608  if ((width != (unsigned int) annotate_image->columns) ||
609  (height != (unsigned int) annotate_image->rows))
610  {
611  char
612  image_geometry[MaxTextExtent];
613 
614  /*
615  Scale image.
616  */
617  (void) FormatLocaleString(image_geometry,MaxTextExtent,"%ux%u",
618  width,height);
619  (void) TransformImage(&annotate_image,(char *) NULL,image_geometry);
620  }
621  if (annotate_info->degrees != 0.0)
622  {
623  Image
624  *rotate_image;
625 
626  int
627  rotations;
628 
629  MagickRealType
630  normalized_degrees;
631 
632  /*
633  Rotate image.
634  */
635  rotate_image=
636  RotateImage(annotate_image,annotate_info->degrees,&image->exception);
637  if (rotate_image == (Image *) NULL)
638  return(MagickFalse);
639  annotate_image=DestroyImage(annotate_image);
640  annotate_image=rotate_image;
641  /*
642  Annotation is relative to the degree of rotation.
643  */
644  normalized_degrees=annotate_info->degrees;
645  while (normalized_degrees < -45.0)
646  normalized_degrees+=360.0;
647  for (rotations=0; normalized_degrees > 45.0; rotations++)
648  normalized_degrees-=90.0;
649  switch (rotations % 4)
650  {
651  default:
652  case 0:
653  break;
654  case 1:
655  {
656  /*
657  Rotate 90 degrees.
658  */
659  x-=(int) annotate_image->columns/2;
660  y+=(int) annotate_image->columns/2;
661  break;
662  }
663  case 2:
664  {
665  /*
666  Rotate 180 degrees.
667  */
668  x=x-(int) annotate_image->columns;
669  break;
670  }
671  case 3:
672  {
673  /*
674  Rotate 270 degrees.
675  */
676  x=x-(int) annotate_image->columns/2;
677  y=y-(int) (annotate_image->rows-(annotate_image->columns/2));
678  break;
679  }
680  }
681  }
682  /*
683  Composite text onto the image.
684  */
685  (void) XParseGeometry(annotate_info->geometry,&x,&y,&width,&height);
686  matte=image->matte;
687  (void) CompositeImage(image,annotate_image->matte != MagickFalse ?
688  OverCompositeOp : CopyCompositeOp,annotate_image,(ssize_t) x,(ssize_t) y);
689  image->matte=matte;
690  annotate_image=DestroyImage(annotate_image);
691  return(MagickTrue);
692 }
693 ␌
694 /*
695 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
696 % %
697 % %
698 % %
699 % X B e s t F o n t %
700 % %
701 % %
702 % %
703 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
704 %
705 % XBestFont() returns the "best" font. "Best" is defined as a font specified
706 % in the X resource database or a font such that the text width displayed
707 % with the font does not exceed the specified maximum width.
708 %
709 % The format of the XBestFont method is:
710 %
711 % XFontStruct *XBestFont(Display *display,
712 % const XResourceInfo *resource_info,const MagickBooleanType text_font)
713 %
714 % A description of each parameter follows:
715 %
716 % o font: XBestFont returns a pointer to a XFontStruct structure.
717 %
718 % o display: Specifies a connection to an X server; returned from
719 % XOpenDisplay.
720 %
721 % o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
722 %
723 % o text_font: True is font should be mono-spaced (typewriter style).
724 %
725 */
726 
727 static char **FontToList(char *font)
728 {
729  char
730  **fontlist;
731 
732  char
733  *p,
734  *q;
735 
736  int
737  i;
738 
739  unsigned int
740  fonts;
741 
742  if (font == (char *) NULL)
743  return((char **) NULL);
744  /*
745  Convert string to an ASCII list.
746  */
747  fonts=1U;
748  for (p=font; *p != '\0'; p++)
749  if ((*p == ':') || (*p == ';') || (*p == ','))
750  fonts++;
751  fontlist=(char **) AcquireQuantumMemory((size_t) fonts+1UL,sizeof(*fontlist));
752  if (fontlist == (char **) NULL)
753  ThrowXWindowFatalException(ResourceLimitError,"MemoryAllocationFailed",
754  font);
755  p=font;
756  for (i=0; i < (int) fonts; i++)
757  {
758  for (q=p; *q != '\0'; q++)
759  if ((*q == ':') || (*q == ';') || (*q == ','))
760  break;
761  fontlist[i]=(char *) AcquireQuantumMemory((size_t) (q-p)+1UL,
762  sizeof(*fontlist[i]));
763  if (fontlist[i] == (char *) NULL)
764  ThrowXWindowFatalException(ResourceLimitError,"MemoryAllocationFailed",
765  font);
766  (void) CopyMagickString(fontlist[i],p,(size_t) (q-p+1));
767  p=q+1;
768  }
769  fontlist[i]=(char *) NULL;
770  return(fontlist);
771 }
772 
773 MagickExport XFontStruct *XBestFont(Display *display,
774  const XResourceInfo *resource_info,const MagickBooleanType text_font)
775 {
776  static const char
777  *Fonts[]=
778  {
779  "-*-helvetica-medium-r-normal--12-*-*-*-*-*-iso8859-1",
780  "-*-arial-medium-r-normal--12-*-*-*-*-*-iso8859-1",
781  "-*-helvetica-medium-r-normal--12-*-*-*-*-*-iso8859-15",
782  "-*-arial-medium-r-normal--12-*-*-*-*-*-iso8859-15",
783  "-*-helvetica-medium-r-normal--12-*-*-*-*-*-*-*",
784  "-*-arial-medium-r-normal--12-*-*-*-*-*-*-*",
785  "variable",
786  "fixed",
787  (char *) NULL
788  },
789  *TextFonts[]=
790  {
791  "-*-courier-medium-r-normal-*-12-*-*-*-*-*-iso8859-1",
792  "-*-courier-medium-r-normal-*-12-*-*-*-*-*-iso8859-15",
793  "-*-fixed-medium-r-normal-*-12-*-*-*-*-*-*-*",
794  "fixed",
795  (char *) NULL
796  };
797 
798  char
799  *font_name;
800 
801  const char
802  **p;
803 
804  XFontStruct
805  *font_info;
806 
807  font_info=(XFontStruct *) NULL;
808  font_name=resource_info->font;
809  if (text_font != MagickFalse)
810  font_name=resource_info->text_font;
811  if ((font_name != (char *) NULL) && (*font_name != '\0'))
812  {
813  char
814  **fontlist;
815 
816  int
817  i;
818 
819  /*
820  Load preferred font specified in the X resource database.
821  */
822  fontlist=FontToList(font_name);
823  if (fontlist != (char **) NULL)
824  {
825  for (i=0; fontlist[i] != (char *) NULL; i++)
826  {
827  if (font_info == (XFontStruct *) NULL)
828  font_info=XLoadQueryFont(display,fontlist[i]);
829  fontlist[i]=DestroyString(fontlist[i]);
830  }
831  fontlist=(char **) RelinquishMagickMemory(fontlist);
832  }
833  if (font_info == (XFontStruct *) NULL)
834  ThrowXWindowException(XServerError,"UnableToLoadFont",font_name);
835  }
836  /*
837  Load fonts from list of fonts until one is found.
838  */
839  p=Fonts;
840  if (text_font != MagickFalse)
841  p=TextFonts;
842  if (XDisplayHeight(display,XDefaultScreen(display)) >= 748)
843  p++;
844  while (*p != (char *) NULL)
845  {
846  if (font_info != (XFontStruct *) NULL)
847  break;
848  font_info=XLoadQueryFont(display,(char *) *p);
849  p++;
850  }
851  return(font_info);
852 }
853 ␌
854 /*
855 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
856 % %
857 % %
858 % %
859 % X B e s t I c o n S i z e %
860 % %
861 % %
862 % %
863 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
864 %
865 % XBestIconSize() returns the "best" icon size. "Best" is defined as an icon
866 % size that maintains the aspect ratio of the image. If the window manager
867 % has preferred icon sizes, one of the preferred sizes is used.
868 %
869 % The format of the XBestIconSize method is:
870 %
871 % void XBestIconSize(Display *display,XWindowInfo *window,Image *image)
872 %
873 % A description of each parameter follows:
874 %
875 % o display: Specifies a connection to an X server; returned from
876 % XOpenDisplay.
877 %
878 % o image: the image.
879 %
880 */
881 MagickExport void XBestIconSize(Display *display,XWindowInfo *window,
882  Image *image)
883 {
884  int
885  i,
886  number_sizes;
887 
888  MagickRealType
889  scale_factor;
890 
891  unsigned int
892  height,
893  icon_height,
894  icon_width,
895  width;
896 
897  Window
898  root_window;
899 
900  XIconSize
901  *icon_size,
902  *size_list;
903 
904  /*
905  Determine if the window manager has specified preferred icon sizes.
906  */
907  assert(display != (Display *) NULL);
908  assert(window != (XWindowInfo *) NULL);
909  assert(image != (Image *) NULL);
910  if (IsEventLogging() != MagickFalse)
911  (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
912  window->width=MaxIconSize;
913  window->height=MaxIconSize;
914  icon_size=(XIconSize *) NULL;
915  number_sizes=0;
916  root_window=XRootWindow(display,window->screen);
917  if (XGetIconSizes(display,root_window,&size_list,&number_sizes) != 0)
918  if ((number_sizes > 0) && (size_list != (XIconSize *) NULL))
919  icon_size=size_list;
920  if (icon_size == (XIconSize *) NULL)
921  {
922  /*
923  Window manager does not restrict icon size.
924  */
925  icon_size=XAllocIconSize();
926  if (icon_size == (XIconSize *) NULL)
927  ThrowXWindowFatalException(ResourceLimitError,
928  "MemoryAllocationFailed",image->filename);
929  icon_size->min_width=1;
930  icon_size->max_width=MaxIconSize;
931  icon_size->min_height=1;
932  icon_size->max_height=MaxIconSize;
933  icon_size->width_inc=1;
934  icon_size->height_inc=1;
935  }
936  /*
937  Determine aspect ratio of image.
938  */
939  width=(unsigned int) image->columns;
940  height=(unsigned int) image->rows;
941  i=0;
942  if (window->crop_geometry)
943  (void) XParseGeometry(window->crop_geometry,&i,&i,&width,&height);
944  /*
945  Look for an icon size that maintains the aspect ratio of image.
946  */
947  scale_factor=(MagickRealType) icon_size->max_width/width;
948  if (scale_factor > ((MagickRealType) icon_size->max_height/height))
949  scale_factor=(MagickRealType) icon_size->max_height/height;
950  icon_width=(unsigned int) icon_size->min_width;
951  while ((int) icon_width < icon_size->max_width)
952  {
953  if (icon_width >= (unsigned int) (scale_factor*width+0.5))
954  break;
955  icon_width+=icon_size->width_inc;
956  }
957  icon_height=(unsigned int) icon_size->min_height;
958  while ((int) icon_height < icon_size->max_height)
959  {
960  if (icon_height >= (unsigned int) (scale_factor*height+0.5))
961  break;
962  icon_height+=icon_size->height_inc;
963  }
964  (void) XFree((void *) icon_size);
965  window->width=icon_width;
966  window->height=icon_height;
967 }
968 ␌
969 /*
970 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
971 % %
972 % %
973 % %
974 % X B e s t P i x e l %
975 % %
976 % %
977 % %
978 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
979 %
980 % XBestPixel() returns a pixel from an array of pixels that is closest to the
981 % requested color. If the color array is NULL, the colors are obtained from
982 % the X server.
983 %
984 % The format of the XBestPixel method is:
985 %
986 % void XBestPixel(Display *display,const Colormap colormap,XColor *colors,
987 % unsigned int number_colors,XColor *color)
988 %
989 % A description of each parameter follows:
990 %
991 % o pixel: XBestPixel returns the pixel value closest to the requested
992 % color.
993 %
994 % o display: Specifies a connection to an X server; returned from
995 % XOpenDisplay.
996 %
997 % o colormap: Specifies the ID of the X server colormap.
998 %
999 % o colors: Specifies an array of XColor structures.
1000 %
1001 % o number_colors: Specifies the number of XColor structures in the
1002 % color definition array.
1003 %
1004 % o color: Specifies the desired RGB value to find in the colors array.
1005 %
1006 */
1007 MagickExport void XBestPixel(Display *display,const Colormap colormap,
1008  XColor *colors,unsigned int number_colors,XColor *color)
1009 {
1010  MagickBooleanType
1011  query_server;
1012 
1014  pixel;
1015 
1016  MagickRealType
1017  min_distance;
1018 
1019  MagickRealType
1020  distance;
1021 
1022  int
1023  i,
1024  j;
1025 
1026  Status
1027  status;
1028 
1029  /*
1030  Find closest representation for the requested RGB color.
1031  */
1032  assert(display != (Display *) NULL);
1033  assert(color != (XColor *) NULL);
1034  if (IsEventLogging() != MagickFalse)
1035  (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
1036  status=XAllocColor(display,colormap,color);
1037  if (status != False)
1038  return;
1039  query_server=colors == (XColor *) NULL ? MagickTrue : MagickFalse;
1040  if (query_server != MagickFalse)
1041  {
1042  /*
1043  Read X server colormap.
1044  */
1045  colors=(XColor *) AcquireQuantumMemory(number_colors,sizeof(*colors));
1046  if (colors == (XColor *) NULL)
1047  ThrowXWindowFatalException(ResourceLimitError,
1048  "MemoryAllocationFailed","...");
1049  for (i=0; i < (int) number_colors; i++)
1050  colors[i].pixel=(size_t) i;
1051  if (number_colors > 256)
1052  number_colors=256;
1053  (void) XQueryColors(display,colormap,colors,(int) number_colors);
1054  }
1055  min_distance=3.0*((MagickRealType) QuantumRange+1.0)*((MagickRealType)
1056  QuantumRange+1.0);
1057  j=0;
1058  for (i=0; i < (int) number_colors; i++)
1059  {
1060  pixel.red=colors[i].red-(MagickRealType) color->red;
1061  distance=pixel.red*pixel.red;
1062  if (distance > min_distance)
1063  continue;
1064  pixel.green=colors[i].green-(MagickRealType) color->green;
1065  distance+=pixel.green*pixel.green;
1066  if (distance > min_distance)
1067  continue;
1068  pixel.blue=colors[i].blue-(MagickRealType) color->blue;
1069  distance+=pixel.blue*pixel.blue;
1070  if (distance > min_distance)
1071  continue;
1072  min_distance=distance;
1073  color->pixel=colors[i].pixel;
1074  j=i;
1075  }
1076  (void) XAllocColor(display,colormap,&colors[j]);
1077  if (query_server != MagickFalse)
1078  colors=(XColor *) RelinquishMagickMemory(colors);
1079 }
1080 ␌
1081 /*
1082 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1083 % %
1084 % %
1085 % %
1086 % X B e s t V i s u a l I n f o %
1087 % %
1088 % %
1089 % %
1090 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1091 %
1092 % XBestVisualInfo() returns visual information for a visual that is the "best"
1093 % the server supports. "Best" is defined as:
1094 %
1095 % 1. Restrict the visual list to those supported by the default screen.
1096 %
1097 % 2. If a visual type is specified, restrict the visual list to those of
1098 % that type.
1099 %
1100 % 3. If a map type is specified, choose the visual that matches the id
1101 % specified by the Standard Colormap.
1102 %
1103 % 4 From the list of visuals, choose one that can display the most
1104 % simultaneous colors. If more than one visual can display the same
1105 % number of simultaneous colors, one is chosen based on a rank.
1106 %
1107 % The format of the XBestVisualInfo method is:
1108 %
1109 % XVisualInfo *XBestVisualInfo(Display *display,
1110 % XStandardColormap *map_info,XResourceInfo *resource_info)
1111 %
1112 % A description of each parameter follows:
1113 %
1114 % o visual_info: XBestVisualInfo returns a pointer to a X11 XVisualInfo
1115 % structure.
1116 %
1117 % o display: Specifies a connection to an X server; returned from
1118 % XOpenDisplay.
1119 %
1120 % o map_info: If map_type is specified, this structure is initialized
1121 % with info from the Standard Colormap.
1122 %
1123 % o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
1124 %
1125 */
1126 MagickExport XVisualInfo *XBestVisualInfo(Display *display,
1127  XStandardColormap *map_info,XResourceInfo *resource_info)
1128 {
1129 #define MaxStandardColormaps 7
1130 #define XVisualColormapSize(visual_info) MagickMin((unsigned int) (\
1131  (visual_info->klass == TrueColor) || (visual_info->klass == DirectColor) ? \
1132  visual_info->red_mask | visual_info->green_mask | visual_info->blue_mask : \
1133  (unsigned long) visual_info->colormap_size),1UL << visual_info->depth)
1134 
1135  char
1136  *map_type,
1137  *visual_type;
1138 
1139  int
1140  visual_mask;
1141 
1142  int
1143  i;
1144 
1145  size_t
1146  one;
1147 
1148  static int
1149  number_visuals;
1150 
1151  static XVisualInfo
1152  visual_template;
1153 
1154  XVisualInfo
1155  *visual_info,
1156  *visual_list;
1157 
1158  /*
1159  Restrict visual search by screen number.
1160  */
1161  assert(display != (Display *) NULL);
1162  assert(map_info != (XStandardColormap *) NULL);
1163  assert(resource_info != (XResourceInfo *) NULL);
1164  if (IsEventLogging() != MagickFalse)
1165  (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
1166  map_type=resource_info->map_type;
1167  visual_type=resource_info->visual_type;
1168  visual_mask=VisualScreenMask;
1169  visual_template.screen=XDefaultScreen(display);
1170  visual_template.depth=XDefaultDepth(display,XDefaultScreen(display));
1171  one=1;
1172  if ((resource_info->immutable != MagickFalse) && (resource_info->colors != 0))
1173  if (resource_info->colors <= (one << (size_t) visual_template.depth))
1174  visual_mask|=VisualDepthMask;
1175  if (visual_type != (char *) NULL)
1176  {
1177  /*
1178  Restrict visual search by class or visual id.
1179  */
1180  if (LocaleCompare("staticgray",visual_type) == 0)
1181  {
1182  visual_mask|=VisualClassMask;
1183  visual_template.klass=StaticGray;
1184  }
1185  else
1186  if (LocaleCompare("grayscale",visual_type) == 0)
1187  {
1188  visual_mask|=VisualClassMask;
1189  visual_template.klass=GrayScale;
1190  }
1191  else
1192  if (LocaleCompare("staticcolor",visual_type) == 0)
1193  {
1194  visual_mask|=VisualClassMask;
1195  visual_template.klass=StaticColor;
1196  }
1197  else
1198  if (LocaleCompare("pseudocolor",visual_type) == 0)
1199  {
1200  visual_mask|=VisualClassMask;
1201  visual_template.klass=PseudoColor;
1202  }
1203  else
1204  if (LocaleCompare("truecolor",visual_type) == 0)
1205  {
1206  visual_mask|=VisualClassMask;
1207  visual_template.klass=TrueColor;
1208  }
1209  else
1210  if (LocaleCompare("directcolor",visual_type) == 0)
1211  {
1212  visual_mask|=VisualClassMask;
1213  visual_template.klass=DirectColor;
1214  }
1215  else
1216  if (LocaleCompare("default",visual_type) == 0)
1217  {
1218  visual_mask|=VisualIDMask;
1219  visual_template.visualid=XVisualIDFromVisual(
1220  XDefaultVisual(display,XDefaultScreen(display)));
1221  }
1222  else
1223  if (isdigit((int) ((unsigned char) *visual_type)) != 0)
1224  {
1225  visual_mask|=VisualIDMask;
1226  visual_template.visualid=
1227  strtol(visual_type,(char **) NULL,0);
1228  }
1229  else
1230  ThrowXWindowException(XServerError,
1231  "UnrecognizedVisualSpecifier",visual_type);
1232  }
1233  /*
1234  Get all visuals that meet our criteria so far.
1235  */
1236  number_visuals=0;
1237  visual_list=XGetVisualInfo(display,visual_mask,&visual_template,
1238  &number_visuals);
1239  visual_mask=VisualScreenMask | VisualIDMask;
1240  if ((number_visuals == 0) || (visual_list == (XVisualInfo *) NULL))
1241  {
1242  /*
1243  Failed to get visual; try using the default visual.
1244  */
1245  ThrowXWindowException(XServerWarning,"UnableToGetVisual",visual_type);
1246  visual_template.visualid=XVisualIDFromVisual(XDefaultVisual(display,
1247  XDefaultScreen(display)));
1248  visual_list=XGetVisualInfo(display,visual_mask,&visual_template,
1249  &number_visuals);
1250  if ((number_visuals == 0) || (visual_list == (XVisualInfo *) NULL))
1251  return((XVisualInfo *) NULL);
1252  ThrowXWindowException(XServerWarning,"UsingDefaultVisual",
1253  XVisualClassName(visual_list->klass));
1254  }
1255  resource_info->color_recovery=MagickFalse;
1256  if ((map_info != (XStandardColormap *) NULL) && (map_type != (char *) NULL))
1257  {
1258  Atom
1259  map_property;
1260 
1261  char
1262  map_name[MaxTextExtent];
1263 
1264  int
1265  j,
1266  number_maps;
1267 
1268  Status
1269  status;
1270 
1271  Window
1272  root_window;
1273 
1274  XStandardColormap
1275  *map_list;
1276 
1277  /*
1278  Choose a visual associated with a standard colormap.
1279  */
1280  map_list=(XStandardColormap *) NULL;
1281  root_window=XRootWindow(display,XDefaultScreen(display));
1282  status=False;
1283  number_maps=0;
1284  if (LocaleCompare(map_type,"list") != 0)
1285  {
1286  /*
1287  User specified Standard Colormap.
1288  */
1289  (void) FormatLocaleString((char *) map_name,MaxTextExtent,
1290  "RGB_%s_MAP",map_type);
1291  LocaleUpper(map_name);
1292  map_property=XInternAtom(display,(char *) map_name,MagickTrue);
1293  if (map_property != (Atom) NULL)
1294  status=XGetRGBColormaps(display,root_window,&map_list,&number_maps,
1295  map_property);
1296  }
1297  else
1298  {
1299  static const char
1300  *colormap[MaxStandardColormaps]=
1301  {
1302  "_HP_RGB_SMOOTH_MAP_LIST",
1303  "RGB_BEST_MAP",
1304  "RGB_DEFAULT_MAP",
1305  "RGB_GRAY_MAP",
1306  "RGB_RED_MAP",
1307  "RGB_GREEN_MAP",
1308  "RGB_BLUE_MAP",
1309  };
1310 
1311  /*
1312  Choose a standard colormap from a list.
1313  */
1314  for (i=0; i < MaxStandardColormaps; i++)
1315  {
1316  map_property=XInternAtom(display,(char *) colormap[i],MagickTrue);
1317  if (map_property == (Atom) NULL)
1318  continue;
1319  status=XGetRGBColormaps(display,root_window,&map_list,&number_maps,
1320  map_property);
1321  if (status != False)
1322  break;
1323  }
1324  resource_info->color_recovery=i == 0 ? MagickTrue : MagickFalse;
1325  }
1326  if (status == False)
1327  ThrowXWindowFatalException(XServerError,"UnableToGetStandardColormap",
1328  map_type);
1329  /*
1330  Search all Standard Colormaps and visuals for ids that match.
1331  */
1332  *map_info=map_list[0];
1333 #if !defined(PRE_R4_ICCCM)
1334  visual_template.visualid=XVisualIDFromVisual(visual_list[0].visual);
1335  for (i=0; i < number_maps; i++)
1336  for (j=0; j < number_visuals; j++)
1337  if (map_list[i].visualid ==
1338  XVisualIDFromVisual(visual_list[j].visual))
1339  {
1340  *map_info=map_list[i];
1341  visual_template.visualid=XVisualIDFromVisual(
1342  visual_list[j].visual);
1343  break;
1344  }
1345  if (map_info->visualid != visual_template.visualid)
1346  ThrowXWindowFatalException(XServerError,
1347  "UnableToMatchVisualToStandardColormap",map_type);
1348 #endif
1349  if (map_info->colormap == (Colormap) NULL)
1350  ThrowXWindowFatalException(XServerError,
1351  "StandardColormapIsNotInitialized",map_type);
1352  (void) XFree((void *) map_list);
1353  }
1354  else
1355  {
1356  static const unsigned int
1357  rank[]=
1358  {
1359  StaticGray,
1360  GrayScale,
1361  StaticColor,
1362  DirectColor,
1363  TrueColor,
1364  PseudoColor
1365  };
1366 
1367  XVisualInfo
1368  *p;
1369 
1370  /*
1371  Pick one visual that displays the most simultaneous colors.
1372  */
1373  visual_info=visual_list;
1374  p=visual_list;
1375  for (i=1; i < number_visuals; i++)
1376  {
1377  p++;
1378  if (XVisualColormapSize(p) > XVisualColormapSize(visual_info))
1379  visual_info=p;
1380  else
1381  if (XVisualColormapSize(p) == XVisualColormapSize(visual_info))
1382  if (rank[p->klass] > rank[visual_info->klass])
1383  visual_info=p;
1384  }
1385  visual_template.visualid=XVisualIDFromVisual(visual_info->visual);
1386  }
1387  (void) XFree((void *) visual_list);
1388  /*
1389  Retrieve only one visual by its screen & id number.
1390  */
1391  visual_info=XGetVisualInfo(display,visual_mask,&visual_template,
1392  &number_visuals);
1393  if ((number_visuals == 0) || (visual_info == (XVisualInfo *) NULL))
1394  return((XVisualInfo *) NULL);
1395  return(visual_info);
1396 }
1397 ␌
1398 /*
1399 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1400 % %
1401 % %
1402 % %
1403 % X C h e c k D e f i n e C u r s o r %
1404 % %
1405 % %
1406 % %
1407 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1408 %
1409 % XCheckDefineCursor() prevents cursor changes on the root window.
1410 %
1411 % The format of the XXCheckDefineCursor method is:
1412 %
1413 % XCheckDefineCursor(display,window,cursor)
1414 %
1415 % A description of each parameter follows:
1416 %
1417 % o display: Specifies a connection to an X server; returned from
1418 % XOpenDisplay.
1419 %
1420 % o window: the window.
1421 %
1422 % o cursor: the cursor.
1423 %
1424 */
1425 MagickExport int XCheckDefineCursor(Display *display,Window window,
1426  Cursor cursor)
1427 {
1428  assert(display != (Display *) NULL);
1429  if (IsEventLogging() != MagickFalse)
1430  (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
1431  if (window == XRootWindow(display,XDefaultScreen(display)))
1432  return(0);
1433  return(XDefineCursor(display,window,cursor));
1434 }
1435 ␌
1436 /*
1437 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1438 % %
1439 % %
1440 % %
1441 % X C h e c k R e f r e s h W i n d o w s %
1442 % %
1443 % %
1444 % %
1445 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1446 %
1447 % XCheckRefreshWindows() checks the X server for exposure events for a
1448 % particular window and updates the are associated with the exposure event.
1449 %
1450 % The format of the XCheckRefreshWindows method is:
1451 %
1452 % void XCheckRefreshWindows(Display *display,XWindows *windows)
1453 %
1454 % A description of each parameter follows:
1455 %
1456 % o display: Specifies a connection to an X server; returned from
1457 % XOpenDisplay.
1458 %
1459 % o windows: Specifies a pointer to a XWindows structure.
1460 %
1461 */
1462 MagickExport void XCheckRefreshWindows(Display *display,XWindows *windows)
1463 {
1464  Window
1465  id;
1466 
1467  XEvent
1468  event;
1469 
1470  assert(display != (Display *) NULL);
1471  assert(windows != (XWindows *) NULL);
1472  if (IsEventLogging() != MagickFalse)
1473  (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
1474  XDelay(display,SuspendTime);
1475  id=windows->command.id;
1476  while (XCheckTypedWindowEvent(display,id,Expose,&event) != MagickFalse)
1477  (void) XCommandWidget(display,windows,(char const **) NULL,&event);
1478  id=windows->image.id;
1479  while (XCheckTypedWindowEvent(display,id,Expose,&event) != MagickFalse)
1480  XRefreshWindow(display,&windows->image,&event);
1481  XDelay(display,SuspendTime << 1);
1482  id=windows->command.id;
1483  while (XCheckTypedWindowEvent(display,id,Expose,&event) != MagickFalse)
1484  (void) XCommandWidget(display,windows,(char const **) NULL,&event);
1485  id=windows->image.id;
1486  while (XCheckTypedWindowEvent(display,id,Expose,&event) != MagickFalse)
1487  XRefreshWindow(display,&windows->image,&event);
1488 }
1489 ␌
1490 /*
1491 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1492 % %
1493 % %
1494 % %
1495 % X C l i e n t M e s s a g e %
1496 % %
1497 % %
1498 % %
1499 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1500 %
1501 % XClientMessage() sends a reason to a window with XSendEvent. The reason is
1502 % initialized with a particular protocol type and atom.
1503 %
1504 % The format of the XClientMessage function is:
1505 %
1506 % XClientMessage(display,window,protocol,reason,timestamp)
1507 %
1508 % A description of each parameter follows:
1509 %
1510 % o display: Specifies a pointer to the Display structure; returned from
1511 % XOpenDisplay.
1512 %
1513 % o window: Specifies a pointer to a Window structure.
1514 %
1515 % o protocol: Specifies an atom value.
1516 %
1517 % o reason: Specifies an atom value which is the reason to send.
1518 %
1519 % o timestamp: Specifies a value of type Time.
1520 %
1521 */
1522 MagickExport void XClientMessage(Display *display,const Window window,
1523  const Atom protocol,const Atom reason,const Time timestamp)
1524 {
1525  XClientMessageEvent
1526  client_event;
1527 
1528  assert(display != (Display *) NULL);
1529  (void) memset(&client_event,0,sizeof(client_event));
1530  client_event.type=ClientMessage;
1531  client_event.window=window;
1532  client_event.message_type=protocol;
1533  client_event.format=32;
1534  client_event.data.l[0]=(long) reason;
1535  client_event.data.l[1]=(long) timestamp;
1536  (void) XSendEvent(display,window,MagickFalse,NoEventMask,(XEvent *) &client_event);
1537 }
1538 ␌
1539 /*
1540 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1541 % %
1542 % %
1543 % %
1544 + X C l i e n t W i n d o w %
1545 % %
1546 % %
1547 % %
1548 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1549 %
1550 % XClientWindow() finds a window, at or below the specified window, which has
1551 % a WM_STATE property. If such a window is found, it is returned, otherwise
1552 % the argument window is returned.
1553 %
1554 % The format of the XClientWindow function is:
1555 %
1556 % client_window=XClientWindow(display,target_window)
1557 %
1558 % A description of each parameter follows:
1559 %
1560 % o client_window: XClientWindow returns a window, at or below the specified
1561 % window, which has a WM_STATE property otherwise the argument
1562 % target_window is returned.
1563 %
1564 % o display: Specifies a pointer to the Display structure; returned from
1565 % XOpenDisplay.
1566 %
1567 % o target_window: Specifies the window to find a WM_STATE property.
1568 %
1569 */
1570 static Window XClientWindow(Display *display,Window target_window)
1571 {
1572  Atom
1573  state,
1574  type;
1575 
1576  int
1577  format;
1578 
1579  Status
1580  status;
1581 
1582  unsigned char
1583  *data;
1584 
1585  unsigned long
1586  after,
1587  number_items;
1588 
1589  Window
1590  client_window;
1591 
1592  assert(display != (Display *) NULL);
1593  if (IsEventLogging() != MagickFalse)
1594  (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
1595  state=XInternAtom(display,"WM_STATE",MagickTrue);
1596  if (state == (Atom) NULL)
1597  return(target_window);
1598  type=(Atom) NULL;
1599  status=XGetWindowProperty(display,target_window,state,0L,0L,MagickFalse,
1600  (Atom) AnyPropertyType,&type,&format,&number_items,&after,&data);
1601  if ((status == Success) && (type != (Atom) NULL))
1602  return(target_window);
1603  client_window=XWindowByProperty(display,target_window,state);
1604  if (client_window == (Window) NULL)
1605  return(target_window);
1606  return(client_window);
1607 }
1608 ␌
1609 /*
1610 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1611 % %
1612 % %
1613 % %
1614 + X C o m p o n e n t T e r m i n u s %
1615 % %
1616 % %
1617 % %
1618 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1619 %
1620 % XComponentTerminus() destroys the module component.
1621 %
1622 % The format of the XComponentTerminus method is:
1623 %
1624 % XComponentTerminus(void)
1625 %
1626 */
1627 MagickExport void XComponentTerminus(void)
1628 {
1629  DestroyXResources();
1630 }
1631 ␌
1632 /*
1633 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1634 % %
1635 % %
1636 % %
1637 % X C o n f i g u r e I m a g e C o l o r m a p %
1638 % %
1639 % %
1640 % %
1641 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1642 %
1643 % XConfigureImageColormap() creates a new X colormap.
1644 %
1645 % The format of the XConfigureImageColormap method is:
1646 %
1647 % void XConfigureImageColormap(Display *display,
1648 % XResourceInfo *resource_info,XWindows *windows,Image *image)
1649 %
1650 % A description of each parameter follows:
1651 %
1652 % o display: Specifies a connection to an X server; returned from
1653 % XOpenDisplay.
1654 %
1655 % o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
1656 %
1657 % o windows: Specifies a pointer to a XWindows structure.
1658 %
1659 % o image: the image.
1660 %
1661 */
1662 MagickExport void XConfigureImageColormap(Display *display,
1663  XResourceInfo *resource_info,XWindows *windows,Image *image)
1664 {
1665  Colormap
1666  colormap;
1667 
1668  /*
1669  Make standard colormap.
1670  */
1671  XSetCursorState(display,windows,MagickTrue);
1672  XCheckRefreshWindows(display,windows);
1673  XMakeStandardColormap(display,windows->visual_info,resource_info,image,
1674  windows->map_info,windows->pixel_info);
1675  colormap=windows->map_info->colormap;
1676  (void) XSetWindowColormap(display,windows->image.id,colormap);
1677  (void) XSetWindowColormap(display,windows->command.id,colormap);
1678  (void) XSetWindowColormap(display,windows->widget.id,colormap);
1679  if (windows->magnify.mapped != MagickFalse)
1680  (void) XSetWindowColormap(display,windows->magnify.id,colormap);
1681  if (windows->pan.mapped != MagickFalse)
1682  (void) XSetWindowColormap(display,windows->pan.id,colormap);
1683  XSetCursorState(display,windows,MagickFalse);
1684  XClientMessage(display,windows->image.id,windows->im_protocols,
1685  windows->im_update_colormap,CurrentTime);
1686 }
1687 ␌
1688 /*
1689 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1690 % %
1691 % %
1692 % %
1693 % X C o n s t r a i n W i n d o w P o s i t i o n %
1694 % %
1695 % %
1696 % %
1697 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1698 %
1699 % XConstrainWindowPosition() assures a window is positioned within the X
1700 % server boundaries.
1701 %
1702 % The format of the XConstrainWindowPosition method is:
1703 %
1704 % void XConstrainWindowPosition(Display *display,XWindowInfo *window_info)
1705 %
1706 % A description of each parameter follows:
1707 %
1708 % o display: Specifies a pointer to the Display structure; returned from
1709 % XOpenDisplay.
1710 %
1711 % o window_info: Specifies a pointer to a XWindowInfo structure.
1712 %
1713 */
1714 MagickExport void XConstrainWindowPosition(Display *display,
1715  XWindowInfo *window_info)
1716 {
1717  int
1718  limit;
1719 
1720  assert(display != (Display *) NULL);
1721  assert(window_info != (XWindowInfo *) NULL);
1722  if (IsEventLogging() != MagickFalse)
1723  (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
1724  limit=XDisplayWidth(display,window_info->screen)-window_info->width;
1725  if (window_info->x < 0)
1726  window_info->x=0;
1727  else
1728  if (window_info->x > (int) limit)
1729  window_info->x=(int) limit;
1730  limit=XDisplayHeight(display,window_info->screen)-window_info->height;
1731  if (window_info->y < 0)
1732  window_info->y=0;
1733  else
1734  if (window_info->y > limit)
1735  window_info->y=limit;
1736 }
1737 ␌
1738 /*
1739 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1740 % %
1741 % %
1742 % %
1743 % X D e l a y %
1744 % %
1745 % %
1746 % %
1747 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1748 %
1749 % XDelay() suspends program execution for the number of milliseconds
1750 % specified.
1751 %
1752 % The format of the Delay method is:
1753 %
1754 % void XDelay(Display *display,const size_t milliseconds)
1755 %
1756 % A description of each parameter follows:
1757 %
1758 % o display: Specifies a pointer to the Display structure; returned from
1759 % XOpenDisplay.
1760 %
1761 % o milliseconds: Specifies the number of milliseconds to delay before
1762 % returning.
1763 %
1764 */
1765 MagickExport void XDelay(Display *display,const size_t milliseconds)
1766 {
1767  assert(display != (Display *) NULL);
1768  (void) XFlush(display);
1769  MagickDelay(milliseconds);
1770 }
1771 ␌
1772 /*
1773 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1774 % %
1775 % %
1776 % %
1777 % X D e s t r o y R e s o u r c e I n f o %
1778 % %
1779 % %
1780 % %
1781 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1782 %
1783 % XDestroyResourceInfo() frees memory associated with the XResourceInfo
1784 % structure.
1785 %
1786 % The format of the XDestroyResourceInfo method is:
1787 %
1788 % void XDestroyResourceInfo(XResourceInfo *resource_info)
1789 %
1790 % A description of each parameter follows:
1791 %
1792 % o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
1793 %
1794 */
1795 MagickExport void XDestroyResourceInfo(XResourceInfo *resource_info)
1796 {
1797  if (resource_info->image_geometry != (char *) NULL)
1798  resource_info->image_geometry=(char *)
1799  RelinquishMagickMemory(resource_info->image_geometry);
1800  if (resource_info->quantize_info != (QuantizeInfo *) NULL)
1801  resource_info->quantize_info=DestroyQuantizeInfo(
1802  resource_info->quantize_info);
1803  if (resource_info->client_name != (char *) NULL)
1804  resource_info->client_name=(char *)
1805  RelinquishMagickMemory(resource_info->client_name);
1806  if (resource_info->name != (char *) NULL)
1807  resource_info->name=DestroyString(resource_info->name);
1808  (void) memset(resource_info,0,sizeof(*resource_info));
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+=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 *) "256");
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  ThrowXWindowException(XServerError,"UnableToReadXWindowImage",
5005  image_info->filename)
5006  else
5007  {
5008  (void) CopyMagickString(image->filename,image_info->filename,
5009  MaxTextExtent);
5010  if ((crop_info.width != 0) && (crop_info.height != 0))
5011  {
5012  Image
5013  *crop_image;
5014 
5015  /*
5016  Crop image as defined by the cropping rectangle.
5017  */
5018  crop_image=CropImage(image,&crop_info,&image->exception);
5019  if (crop_image != (Image *) NULL)
5020  {
5021  image=DestroyImage(image);
5022  image=crop_image;
5023  }
5024  }
5025  status=XGetWMName(display,target,&window_name);
5026  if (status == True)
5027  {
5028  if (*image_info->filename == '\0')
5029  (void) CopyMagickString(image->filename,(char *) window_name.value,
5030  (size_t) window_name.nitems+1);
5031  (void) XFree((void *) window_name.value);
5032  }
5033  }
5034  if (ximage_info->silent == MagickFalse)
5035  {
5036  /*
5037  Alert the user we're done.
5038  */
5039  (void) XBell(display,0);
5040  (void) XBell(display,0);
5041  }
5042  (void) XCloseDisplay(display);
5043  return(image);
5044 }
5045 ␌
5046 /*
5047 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5048 % %
5049 % %
5050 % %
5051 % X I n i t i a l i z e W i n d o w s %
5052 % %
5053 % %
5054 % %
5055 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5056 %
5057 % XInitializeWindows() initializes the XWindows structure.
5058 %
5059 % The format of the XInitializeWindows method is:
5060 %
5061 % XWindows *XInitializeWindows(Display *display,
5062 % XResourceInfo *resource_info)
5063 %
5064 % A description of each parameter follows:
5065 %
5066 % o windows: XInitializeWindows returns a pointer to a XWindows structure.
5067 %
5068 % o display: Specifies a connection to an X server; returned from
5069 % XOpenDisplay.
5070 %
5071 % o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
5072 %
5073 */
5074 MagickExport XWindows *XInitializeWindows(Display *display,
5075  XResourceInfo *resource_info)
5076 {
5077  Window
5078  root_window;
5079 
5080  XWindows
5081  *windows;
5082 
5083  /*
5084  Allocate windows structure.
5085  */
5086  windows=(XWindows *) AcquireMagickMemory(sizeof(*windows));
5087  if (windows == (XWindows *) NULL)
5088  ThrowXWindowFatalException(XServerFatalError,"MemoryAllocationFailed",
5089  "...");
5090  (void) memset(windows,0,sizeof(*windows));
5091  windows->pixel_info=(XPixelInfo *) AcquireQuantumMemory(1,
5092  sizeof(*windows->pixel_info));
5093  windows->icon_pixel=(XPixelInfo *) AcquireQuantumMemory(1,
5094  sizeof(*windows->icon_pixel));
5095  windows->icon_resources=(XResourceInfo *) AcquireQuantumMemory(1,
5096  sizeof(*windows->icon_resources));
5097  if ((windows->pixel_info == (XPixelInfo *) NULL) ||
5098  (windows->icon_pixel == (XPixelInfo *) NULL) ||
5099  (windows->icon_resources == (XResourceInfo *) NULL))
5100  ThrowXWindowFatalException(XServerFatalError,"MemoryAllocationFailed",
5101  "...");
5102  (void) memset((void *) windows->pixel_info,0,sizeof(XPixelInfo));
5103  (void) memset((void *) windows->icon_pixel,0,sizeof(XPixelInfo));
5104  /*
5105  Initialize windows structure.
5106  */
5107  windows->display=display;
5108  windows->wm_protocols=XInternAtom(display,"WM_PROTOCOLS",MagickFalse);
5109  windows->wm_delete_window=XInternAtom(display,"WM_DELETE_WINDOW",MagickFalse);
5110  windows->wm_take_focus=XInternAtom(display,"WM_TAKE_FOCUS",MagickFalse);
5111  windows->im_protocols=XInternAtom(display,"IM_PROTOCOLS",MagickFalse);
5112  windows->im_remote_command=
5113  XInternAtom(display,"IM_REMOTE_COMMAND",MagickFalse);
5114  windows->im_update_widget=XInternAtom(display,"IM_UPDATE_WIDGET",MagickFalse);
5115  windows->im_update_colormap=
5116  XInternAtom(display,"IM_UPDATE_COLORMAP",MagickFalse);
5117  windows->im_former_image=XInternAtom(display,"IM_FORMER_IMAGE",MagickFalse);
5118  windows->im_next_image=XInternAtom(display,"IM_NEXT_IMAGE",MagickFalse);
5119  windows->im_retain_colors=XInternAtom(display,"IM_RETAIN_COLORS",MagickFalse);
5120  windows->im_exit=XInternAtom(display,"IM_EXIT",MagickFalse);
5121  windows->dnd_protocols=XInternAtom(display,"DndProtocol",MagickFalse);
5122 #if defined(MAGICKCORE_WINDOWS_SUPPORT)
5123  (void) XSynchronize(display,MagickFalse);
5124 #endif
5125  if ((GetLogEventMask() & X11Event) != 0)
5126  {
5127  (void) XSynchronize(display,MagickTrue);
5128  (void) LogMagickEvent(X11Event,GetMagickModule(),"Version: %s",
5129  GetMagickVersion((size_t *) NULL));
5130  (void) LogMagickEvent(X11Event,GetMagickModule(),"Protocols:");
5131  (void) LogMagickEvent(X11Event,GetMagickModule(),
5132  " Window Manager: 0x%lx",windows->wm_protocols);
5133  (void) LogMagickEvent(X11Event,GetMagickModule(),
5134  " delete window: 0x%lx",windows->wm_delete_window);
5135  (void) LogMagickEvent(X11Event,GetMagickModule()," take focus: 0x%lx",
5136  windows->wm_take_focus);
5137  (void) LogMagickEvent(X11Event,GetMagickModule()," ImageMagick: 0x%lx",
5138  windows->im_protocols);
5139  (void) LogMagickEvent(X11Event,GetMagickModule(),
5140  " remote command: 0x%lx",windows->im_remote_command);
5141  (void) LogMagickEvent(X11Event,GetMagickModule(),
5142  " update widget: 0x%lx",windows->im_update_widget);
5143  (void) LogMagickEvent(X11Event,GetMagickModule(),
5144  " update colormap: 0x%lx",windows->im_update_colormap);
5145  (void) LogMagickEvent(X11Event,GetMagickModule(),
5146  " former image: 0x%lx",windows->im_former_image);
5147  (void) LogMagickEvent(X11Event,GetMagickModule()," next image: 0x%lx",
5148  windows->im_next_image);
5149  (void) LogMagickEvent(X11Event,GetMagickModule(),
5150  " retain colors: 0x%lx",windows->im_retain_colors);
5151  (void) LogMagickEvent(X11Event,GetMagickModule()," exit: 0x%lx",
5152  windows->im_exit);
5153  (void) LogMagickEvent(X11Event,GetMagickModule()," Drag and Drop: 0x%lx",
5154  windows->dnd_protocols);
5155  }
5156  /*
5157  Allocate standard colormap.
5158  */
5159  windows->map_info=XAllocStandardColormap();
5160  windows->icon_map=XAllocStandardColormap();
5161  if ((windows->map_info == (XStandardColormap *) NULL) ||
5162  (windows->icon_map == (XStandardColormap *) NULL))
5163  ThrowXWindowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed",
5164  "...");
5165  windows->map_info->colormap=(Colormap) NULL;
5166  windows->icon_map->colormap=(Colormap) NULL;
5167  windows->pixel_info->pixels=(unsigned long *) NULL;
5168  windows->pixel_info->annotate_context=(GC) NULL;
5169  windows->pixel_info->highlight_context=(GC) NULL;
5170  windows->pixel_info->widget_context=(GC) NULL;
5171  windows->font_info=(XFontStruct *) NULL;
5172  windows->icon_pixel->annotate_context=(GC) NULL;
5173  windows->icon_pixel->pixels=(unsigned long *) NULL;
5174  /*
5175  Allocate visual.
5176  */
5177  *windows->icon_resources=(*resource_info);
5178  windows->icon_resources->visual_type=(char *) "default";
5179  windows->icon_resources->colormap=SharedColormap;
5180  windows->visual_info=
5181  XBestVisualInfo(display,windows->map_info,resource_info);
5182  windows->icon_visual=
5183  XBestVisualInfo(display,windows->icon_map,windows->icon_resources);
5184  if ((windows->visual_info == (XVisualInfo *) NULL) ||
5185  (windows->icon_visual == (XVisualInfo *) NULL))
5186  ThrowXWindowFatalException(XServerFatalError,"UnableToGetVisual",
5187  resource_info->visual_type);
5188  if ((GetLogEventMask() & X11Event) != 0)
5189  {
5190  (void) LogMagickEvent(X11Event,GetMagickModule(),"Visual:");
5191  (void) LogMagickEvent(X11Event,GetMagickModule()," visual id: 0x%lx",
5192  windows->visual_info->visualid);
5193  (void) LogMagickEvent(X11Event,GetMagickModule()," class: %s",
5194  XVisualClassName(windows->visual_info->klass));
5195  (void) LogMagickEvent(X11Event,GetMagickModule()," depth: %d planes",
5196  windows->visual_info->depth);
5197  (void) LogMagickEvent(X11Event,GetMagickModule(),
5198  " size of colormap: %d entries",windows->visual_info->colormap_size);
5199  (void) LogMagickEvent(X11Event,GetMagickModule(),
5200  " red, green, blue masks: 0x%lx 0x%lx 0x%lx",
5201  windows->visual_info->red_mask,windows->visual_info->green_mask,
5202  windows->visual_info->blue_mask);
5203  (void) LogMagickEvent(X11Event,GetMagickModule(),
5204  " significant bits in color: %d bits",
5205  windows->visual_info->bits_per_rgb);
5206  }
5207  /*
5208  Allocate class and manager hints.
5209  */
5210  windows->class_hints=XAllocClassHint();
5211  windows->manager_hints=XAllocWMHints();
5212  if ((windows->class_hints == (XClassHint *) NULL) ||
5213  (windows->manager_hints == (XWMHints *) NULL))
5214  ThrowXWindowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed",
5215  "...");
5216  /*
5217  Determine group leader if we have one.
5218  */
5219  root_window=XRootWindow(display,windows->visual_info->screen);
5220  windows->group_leader.id=(Window) NULL;
5221  if (resource_info->window_group != (char *) NULL)
5222  {
5223  if (isdigit((int) ((unsigned char) *resource_info->window_group)) != 0)
5224  windows->group_leader.id=XWindowByID(display,root_window,(Window)
5225  strtol((char *) resource_info->window_group,(char **) NULL,0));
5226  if (windows->group_leader.id == (Window) NULL)
5227  windows->group_leader.id=
5228  XWindowByName(display,root_window,resource_info->window_group);
5229  }
5230  return(windows);
5231 }
5232 ␌
5233 /*
5234 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5235 % %
5236 % %
5237 % %
5238 % X M a k e C u r s o r %
5239 % %
5240 % %
5241 % %
5242 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5243 %
5244 % XMakeCursor() creates a crosshairs X11 cursor.
5245 %
5246 % The format of the XMakeCursor method is:
5247 %
5248 % Cursor XMakeCursor(Display *display,Window window,Colormap colormap,
5249 % char *background_color,char *foreground_color)
5250 %
5251 % A description of each parameter follows:
5252 %
5253 % o display: Specifies a connection to an X server; returned from
5254 % XOpenDisplay.
5255 %
5256 % o window: Specifies the ID of the window for which the cursor is
5257 % assigned.
5258 %
5259 % o colormap: Specifies the ID of the colormap from which the background
5260 % and foreground color will be retrieved.
5261 %
5262 % o background_color: Specifies the color to use for the cursor background.
5263 %
5264 % o foreground_color: Specifies the color to use for the cursor foreground.
5265 %
5266 */
5267 MagickExport Cursor XMakeCursor(Display *display,Window window,
5268  Colormap colormap,char *background_color,char *foreground_color)
5269 {
5270 #define scope_height 17
5271 #define scope_x_hot 8
5272 #define scope_y_hot 8
5273 #define scope_width 17
5274 
5275  static const unsigned char
5276  scope_bits[] =
5277  {
5278  0x80, 0x03, 0x00, 0x80, 0x02, 0x00, 0x80, 0x02, 0x00, 0x80, 0x02,
5279  0x00, 0x80, 0x02, 0x00, 0x80, 0x02, 0x00, 0x80, 0x02, 0x00, 0x7f,
5280  0xfc, 0x01, 0x01, 0x00, 0x01, 0x7f, 0xfc, 0x01, 0x80, 0x02, 0x00,
5281  0x80, 0x02, 0x00, 0x80, 0x02, 0x00, 0x80, 0x02, 0x00, 0x80, 0x02,
5282  0x00, 0x80, 0x02, 0x00, 0x80, 0x03, 0x00
5283  },
5284  scope_mask_bits[] =
5285  {
5286  0xc0, 0x07, 0x00, 0xc0, 0x07, 0x00, 0xc0, 0x06, 0x00, 0xc0, 0x06,
5287  0x00, 0xc0, 0x06, 0x00, 0xc0, 0x06, 0x00, 0xff, 0xfe, 0x01, 0x7f,
5288  0xfc, 0x01, 0x03, 0x80, 0x01, 0x7f, 0xfc, 0x01, 0xff, 0xfe, 0x01,
5289  0xc0, 0x06, 0x00, 0xc0, 0x06, 0x00, 0xc0, 0x06, 0x00, 0xc0, 0x06,
5290  0x00, 0xc0, 0x07, 0x00, 0xc0, 0x07, 0x00
5291  };
5292 
5293  Cursor
5294  cursor;
5295 
5296  Pixmap
5297  mask,
5298  source;
5299 
5300  XColor
5301  background,
5302  foreground;
5303 
5304  assert(display != (Display *) NULL);
5305  assert(window != (Window) NULL);
5306  assert(colormap != (Colormap) NULL);
5307  assert(background_color != (char *) NULL);
5308  assert(foreground_color != (char *) NULL);
5309  if (IsEventLogging() != MagickFalse)
5310  (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",background_color);
5311  source=XCreateBitmapFromData(display,window,(char *) scope_bits,scope_width,
5312  scope_height);
5313  mask=XCreateBitmapFromData(display,window,(char *) scope_mask_bits,
5314  scope_width,scope_height);
5315  if ((source == (Pixmap) NULL) || (mask == (Pixmap) NULL))
5316  ThrowXWindowFatalException(XServerError,"UnableToCreatePixmap","...");
5317  (void) XParseColor(display,colormap,background_color,&background);
5318  (void) XParseColor(display,colormap,foreground_color,&foreground);
5319  cursor=XCreatePixmapCursor(display,source,mask,&foreground,&background,
5320  scope_x_hot,scope_y_hot);
5321  (void) XFreePixmap(display,source);
5322  (void) XFreePixmap(display,mask);
5323  return(cursor);
5324 }
5325 ␌
5326 /*
5327 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5328 % %
5329 % %
5330 % %
5331 % X M a k e I m a g e %
5332 % %
5333 % %
5334 % %
5335 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5336 %
5337 % XMakeImage() creates an X11 image. If the image size differs from the X11
5338 % image size, the image is first resized.
5339 %
5340 % The format of the XMakeImage method is:
5341 %
5342 % MagickBooleanType XMakeImage(Display *display,
5343 % const XResourceInfo *resource_info,XWindowInfo *window,Image *image,
5344 % unsigned int width,unsigned int height)
5345 %
5346 % A description of each parameter follows:
5347 %
5348 % o display: Specifies a connection to an X server; returned from
5349 % XOpenDisplay.
5350 %
5351 % o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
5352 %
5353 % o window: Specifies a pointer to a XWindowInfo structure.
5354 %
5355 % o image: the image.
5356 %
5357 % o width: Specifies the width in pixels of the rectangular area to
5358 % display.
5359 %
5360 % o height: Specifies the height in pixels of the rectangular area to
5361 % display.
5362 %
5363 */
5364 MagickExport MagickBooleanType XMakeImage(Display *display,
5365  const XResourceInfo *resource_info,XWindowInfo *window,Image *image,
5366  unsigned int width,unsigned int height)
5367 {
5368 #define CheckOverflowException(length,width,height) \
5369  (((height) != 0) && ((length)/((size_t) height) != ((size_t) width)))
5370 
5371  int
5372  depth,
5373  format;
5374 
5375  XImage
5376  *matte_image,
5377  *ximage;
5378 
5379  assert(display != (Display *) NULL);
5380  assert(resource_info != (XResourceInfo *) NULL);
5381  assert(window != (XWindowInfo *) NULL);
5382  assert(width != 0);
5383  assert(height != 0);
5384  if (IsEventLogging() != MagickFalse)
5385  (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
5386  if ((window->width == 0) || (window->height == 0))
5387  return(MagickFalse);
5388  /*
5389  Apply user transforms to the image.
5390  */
5391  (void) XCheckDefineCursor(display,window->id,window->busy_cursor);
5392  (void) XFlush(display);
5393  depth=(int) window->depth;
5394  if (window->destroy)
5395  window->image=DestroyImage(window->image);
5396  window->image=image;
5397  window->destroy=MagickFalse;
5398  if (window->image != (Image *) NULL)
5399  {
5400  if (window->crop_geometry != (char *) NULL)
5401  {
5402  Image
5403  *crop_image;
5404 
5406  crop_info;
5407 
5408  /*
5409  Crop image.
5410  */
5411  window->image->page.x=0;
5412  window->image->page.y=0;
5413  (void) ParsePageGeometry(window->image,window->crop_geometry,
5414  &crop_info,&image->exception);
5415  crop_image=CropImage(window->image,&crop_info,&image->exception);
5416  if (crop_image != (Image *) NULL)
5417  {
5418  if (window->image != image)
5419  window->image=DestroyImage(window->image);
5420  window->image=crop_image;
5421  window->destroy=MagickTrue;
5422  }
5423  }
5424  if ((width != (unsigned int) window->image->columns) ||
5425  (height != (unsigned int) window->image->rows))
5426  {
5427  Image
5428  *resize_image;
5429 
5430  /*
5431  Resize image.
5432  */
5433  resize_image=NewImageList();
5434  if ((window->pixel_info->colors == 0) &&
5435  (window->image->rows > (unsigned long) XDisplayHeight(display,window->screen)) &&
5436  (window->image->columns > (unsigned long) XDisplayWidth(display,window->screen)))
5437  resize_image=ResizeImage(window->image,width,height,
5438  image->filter,image->blur,&image->exception);
5439  else
5440  {
5441  if (window->image->storage_class == PseudoClass)
5442  resize_image=SampleImage(window->image,width,height,
5443  &image->exception);
5444  else
5445  resize_image=ThumbnailImage(window->image,width,height,
5446  &image->exception);
5447  }
5448  if (resize_image != (Image *) NULL)
5449  {
5450  if (window->image != image)
5451  window->image=DestroyImage(window->image);
5452  window->image=resize_image;
5453  window->destroy=MagickTrue;
5454  }
5455  }
5456  width=(unsigned int) window->image->columns;
5457  assert((size_t) width == window->image->columns);
5458  height=(unsigned int) window->image->rows;
5459  assert((size_t) height == window->image->rows);
5460  }
5461  /*
5462  Create X image.
5463  */
5464  ximage=(XImage *) NULL;
5465  format=(depth == 1) ? XYBitmap : ZPixmap;
5466 #if defined(MAGICKCORE_HAVE_SHARED_MEMORY)
5467  if (window->shared_memory != MagickFalse)
5468  {
5469  size_t
5470  length;
5471 
5472  XShmSegmentInfo
5473  *segment_info;
5474 
5475  segment_info=(XShmSegmentInfo *) window->segment_info;
5476  segment_info[1].shmid=(-1);
5477  segment_info[1].shmaddr=(char *) NULL;
5478  ximage=XShmCreateImage(display,window->visual,(unsigned int) depth,format,
5479  (char *) NULL,&segment_info[1],width,height);
5480  length=0;
5481  if (ximage == (XImage *) NULL)
5482  window->shared_memory=MagickFalse;
5483  else
5484  {
5485  length=(size_t) ximage->bytes_per_line*ximage->height;
5486  if (CheckOverflowException(length,ximage->bytes_per_line,ximage->height))
5487  window->shared_memory=MagickFalse;
5488  }
5489  if (window->shared_memory != MagickFalse)
5490  segment_info[1].shmid=shmget(IPC_PRIVATE,length,IPC_CREAT | 0777);
5491  if (window->shared_memory != MagickFalse)
5492  segment_info[1].shmaddr=(char *) shmat(segment_info[1].shmid,0,0);
5493  if (segment_info[1].shmid < 0)
5494  window->shared_memory=MagickFalse;
5495  if (window->shared_memory != MagickFalse)
5496  (void) shmctl(segment_info[1].shmid,IPC_RMID,0);
5497  else
5498  {
5499  if (ximage != (XImage *) NULL)
5500  XDestroyImage(ximage);
5501  ximage=(XImage *) NULL;
5502  if (segment_info[1].shmaddr)
5503  {
5504  (void) shmdt(segment_info[1].shmaddr);
5505  segment_info[1].shmaddr=(char *) NULL;
5506  }
5507  if (segment_info[1].shmid >= 0)
5508  {
5509  (void) shmctl(segment_info[1].shmid,IPC_RMID,0);
5510  segment_info[1].shmid=(-1);
5511  }
5512  }
5513  }
5514 #endif
5515  /*
5516  Allocate X image pixel data.
5517  */
5518 #if defined(MAGICKCORE_HAVE_SHARED_MEMORY)
5519  if (window->shared_memory)
5520  {
5521  Status
5522  status;
5523 
5524  XShmSegmentInfo
5525  *segment_info;
5526 
5527  (void) XSync(display,MagickFalse);
5528  xerror_alert=MagickFalse;
5529  segment_info=(XShmSegmentInfo *) window->segment_info;
5530  ximage->data=segment_info[1].shmaddr;
5531  segment_info[1].readOnly=MagickFalse;
5532  status=XShmAttach(display,&segment_info[1]);
5533  if (status != False)
5534  (void) XSync(display,MagickFalse);
5535  if ((status == False) || (xerror_alert != MagickFalse))
5536  {
5537  window->shared_memory=MagickFalse;
5538  if (status != False)
5539  XShmDetach(display,&segment_info[1]);
5540  ximage->data=NULL;
5541  XDestroyImage(ximage);
5542  ximage=(XImage *) NULL;
5543  if (segment_info[1].shmid >= 0)
5544  {
5545  if (segment_info[1].shmaddr != NULL)
5546  (void) shmdt(segment_info[1].shmaddr);
5547  (void) shmctl(segment_info[1].shmid,IPC_RMID,0);
5548  segment_info[1].shmid=(-1);
5549  segment_info[1].shmaddr=(char *) NULL;
5550  }
5551  }
5552  }
5553 #endif
5554  if (window->shared_memory == MagickFalse)
5555  ximage=XCreateImage(display,window->visual,(unsigned int) depth,format,0,
5556  (char *) NULL,width,height,XBitmapPad(display),0);
5557  if (ximage == (XImage *) NULL)
5558  {
5559  /*
5560  Unable to create X image.
5561  */
5562  (void) XCheckDefineCursor(display,window->id,window->cursor);
5563  return(MagickFalse);
5564  }
5565  if ((GetLogEventMask() & X11Event) != 0)
5566  {
5567  (void) LogMagickEvent(X11Event,GetMagickModule(),"XImage:");
5568  (void) LogMagickEvent(X11Event,GetMagickModule()," width, height: %dx%d",
5569  ximage->width,ximage->height);
5570  (void) LogMagickEvent(X11Event,GetMagickModule()," format: %d",
5571  ximage->format);
5572  (void) LogMagickEvent(X11Event,GetMagickModule()," byte order: %d",
5573  ximage->byte_order);
5574  (void) LogMagickEvent(X11Event,GetMagickModule(),
5575  " bitmap unit, bit order, pad: %d %d %d",ximage->bitmap_unit,
5576  ximage->bitmap_bit_order,ximage->bitmap_pad);
5577  (void) LogMagickEvent(X11Event,GetMagickModule()," depth: %d",
5578  ximage->depth);
5579  (void) LogMagickEvent(X11Event,GetMagickModule()," bytes per line: %d",
5580  ximage->bytes_per_line);
5581  (void) LogMagickEvent(X11Event,GetMagickModule()," bits per pixel: %d",
5582  ximage->bits_per_pixel);
5583  (void) LogMagickEvent(X11Event,GetMagickModule(),
5584  " red, green, blue masks: 0x%lx 0x%lx 0x%lx",ximage->red_mask,
5585  ximage->green_mask,ximage->blue_mask);
5586  }
5587  if (window->shared_memory == MagickFalse)
5588  {
5589  if (ximage->format == XYBitmap)
5590  {
5591  ximage->data=(char *) AcquireQuantumMemory((size_t)
5592  ximage->bytes_per_line,(size_t) ximage->depth*ximage->height);
5593  if (ximage->data != (char *) NULL)
5594  (void) memset(ximage->data,0,(size_t)
5595  ximage->bytes_per_line*ximage->depth*ximage->height);
5596  }
5597  else
5598  {
5599  ximage->data=(char *) AcquireQuantumMemory((size_t)
5600  ximage->bytes_per_line,(size_t) ximage->height);
5601  if (ximage->data != (char *) NULL)
5602  (void) memset(ximage->data,0,(size_t)
5603  ximage->bytes_per_line*ximage->height);
5604  }
5605  }
5606  if (ximage->data == (char *) NULL)
5607  {
5608  /*
5609  Unable to allocate pixel data.
5610  */
5611  XDestroyImage(ximage);
5612  ximage=(XImage *) NULL;
5613  (void) XCheckDefineCursor(display,window->id,window->cursor);
5614  return(MagickFalse);
5615  }
5616  if (window->ximage != (XImage *) NULL)
5617  {
5618  /*
5619  Destroy previous X image.
5620  */
5621 #if defined(MAGICKCORE_HAVE_SHARED_MEMORY)
5622  if (window->segment_info != (XShmSegmentInfo *) NULL)
5623  {
5624  XShmSegmentInfo
5625  *segment_info;
5626 
5627  segment_info=(XShmSegmentInfo *) window->segment_info;
5628  if (segment_info[0].shmid >= 0)
5629  {
5630  (void) XSync(display,MagickFalse);
5631  (void) XShmDetach(display,&segment_info[0]);
5632  (void) XSync(display,MagickFalse);
5633  if (segment_info[0].shmaddr != (char *) NULL)
5634  (void) shmdt(segment_info[0].shmaddr);
5635  (void) shmctl(segment_info[0].shmid,IPC_RMID,0);
5636  segment_info[0].shmid=(-1);
5637  segment_info[0].shmaddr=(char *) NULL;
5638  window->ximage->data=(char *) NULL;
5639  }
5640  }
5641 #endif
5642  if (window->ximage->data != (char *) NULL)
5643  free(window->ximage->data);
5644  window->ximage->data=(char *) NULL;
5645  XDestroyImage(window->ximage);
5646  window->ximage=(XImage *) NULL;
5647  }
5648 #if defined(MAGICKCORE_HAVE_SHARED_MEMORY)
5649  if (window->segment_info != (XShmSegmentInfo *) NULL)
5650  {
5651  XShmSegmentInfo
5652  *segment_info;
5653 
5654  segment_info=(XShmSegmentInfo *) window->segment_info;
5655  segment_info[0]=segment_info[1];
5656  }
5657 #endif
5658  window->ximage=ximage;
5659  matte_image=(XImage *) NULL;
5660  if ((window->shape != MagickFalse) && (window->image != (Image *) NULL))
5661  if ((window->image->matte != MagickFalse) &&
5662  ((int) width <= XDisplayWidth(display,window->screen)) &&
5663  ((int) height <= XDisplayHeight(display,window->screen)))
5664  {
5665  /*
5666  Create matte image.
5667  */
5668  matte_image=XCreateImage(display,window->visual,1,XYBitmap,0,
5669  (char *) NULL,width,height,XBitmapPad(display),0);
5670  if ((GetLogEventMask() & X11Event) != 0)
5671  {
5672  (void) LogMagickEvent(X11Event,GetMagickModule(),"Matte Image:");
5673  (void) LogMagickEvent(X11Event,GetMagickModule(),
5674  " width, height: %dx%d",matte_image->width,matte_image->height);
5675  }
5676  if (matte_image != (XImage *) NULL)
5677  {
5678  /*
5679  Allocate matte image pixel data.
5680  */
5681  matte_image->data=(char *) malloc((size_t)
5682  matte_image->bytes_per_line*matte_image->depth*
5683  matte_image->height);
5684  if (matte_image->data == (char *) NULL)
5685  {
5686  XDestroyImage(matte_image);
5687  matte_image=(XImage *) NULL;
5688  }
5689  }
5690  }
5691  if (window->matte_image != (XImage *) NULL)
5692  {
5693  /*
5694  Free matte image.
5695  */
5696  if (window->matte_image->data != (char *) NULL)
5697  free(window->matte_image->data);
5698  window->matte_image->data=(char *) NULL;
5699  XDestroyImage(window->matte_image);
5700  window->matte_image=(XImage *) NULL;
5701  }
5702  window->matte_image=matte_image;
5703  if (window->matte_pixmap != (Pixmap) NULL)
5704  {
5705  (void) XFreePixmap(display,window->matte_pixmap);
5706  window->matte_pixmap=(Pixmap) NULL;
5707 #if defined(MAGICKCORE_HAVE_SHAPE)
5708  if (window->shape != MagickFalse)
5709  XShapeCombineMask(display,window->id,ShapeBounding,0,0,None,ShapeSet);
5710 #endif
5711  }
5712  window->stasis=MagickFalse;
5713  /*
5714  Convert pixels to X image data.
5715  */
5716  if (window->image != (Image *) NULL)
5717  {
5718  if ((ximage->byte_order == LSBFirst) || ((ximage->format == XYBitmap) &&
5719  (ximage->bitmap_bit_order == LSBFirst)))
5720  XMakeImageLSBFirst(resource_info,window,window->image,ximage,
5721  matte_image);
5722  else
5723  XMakeImageMSBFirst(resource_info,window,window->image,ximage,
5724  matte_image);
5725  }
5726  if (window->matte_image != (XImage *) NULL)
5727  {
5728  /*
5729  Create matte pixmap.
5730  */
5731  window->matte_pixmap=XCreatePixmap(display,window->id,width,height,1);
5732  if (window->matte_pixmap != (Pixmap) NULL)
5733  {
5734  GC
5735  graphics_context;
5736 
5737  XGCValues
5738  context_values;
5739 
5740  /*
5741  Copy matte image to matte pixmap.
5742  */
5743  context_values.background=1;
5744  context_values.foreground=0;
5745  graphics_context=XCreateGC(display,window->matte_pixmap,
5746  (size_t) (GCBackground | GCForeground),&context_values);
5747  (void) XPutImage(display,window->matte_pixmap,graphics_context,
5748  window->matte_image,0,0,0,0,width,height);
5749  (void) XFreeGC(display,graphics_context);
5750 #if defined(MAGICKCORE_HAVE_SHAPE)
5751  if (window->shape != MagickFalse)
5752  XShapeCombineMask(display,window->id,ShapeBounding,0,0,
5753  window->matte_pixmap,ShapeSet);
5754 #endif
5755  }
5756  }
5757  (void) XMakePixmap(display,resource_info,window);
5758  /*
5759  Restore cursor.
5760  */
5761  (void) XCheckDefineCursor(display,window->id,window->cursor);
5762  return(MagickTrue);
5763 }
5764 ␌
5765 /*
5766 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5767 % %
5768 % %
5769 % %
5770 + X M a k e I m a g e L S B F i r s t %
5771 % %
5772 % %
5773 % %
5774 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5775 %
5776 % XMakeImageLSBFirst() initializes the pixel data of an X11 Image. The X image
5777 % pixels are copied in least-significant bit and byte first order. The
5778 % server's scanline pad is respected. Rather than using one or two general
5779 % cases, many special cases are found here to help speed up the image
5780 % conversion.
5781 %
5782 % The format of the XMakeImageLSBFirst method is:
5783 %
5784 % void XMakeImageLSBFirst(Display *display,XWindows *windows)
5785 %
5786 % A description of each parameter follows:
5787 %
5788 % o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
5789 %
5790 % o window: Specifies a pointer to a XWindowInfo structure.
5791 %
5792 % o image: the image.
5793 %
5794 % o ximage: Specifies a pointer to a XImage structure; returned from
5795 % XCreateImage.
5796 %
5797 % o matte_image: Specifies a pointer to a XImage structure; returned from
5798 % XCreateImage.
5799 %
5800 */
5801 static void XMakeImageLSBFirst(const XResourceInfo *resource_info,
5802  const XWindowInfo *window,Image *image,XImage *ximage,XImage *matte_image)
5803 {
5804  CacheView
5805  *canvas_view;
5806 
5807  Image
5808  *canvas;
5809 
5810  int
5811  y;
5812 
5813  const IndexPacket
5814  *indexes;
5815 
5816  const PixelPacket
5817  *p;
5818 
5819  int
5820  x;
5821 
5822  unsigned char
5823  *q;
5824 
5825  unsigned char
5826  bit,
5827  byte;
5828 
5829  unsigned int
5830  scanline_pad;
5831 
5832  unsigned long
5833  pixel,
5834  *pixels;
5835 
5836  XStandardColormap
5837  *map_info;
5838 
5839  assert(resource_info != (XResourceInfo *) NULL);
5840  assert(window != (XWindowInfo *) NULL);
5841  assert(image != (Image *) NULL);
5842  if (IsEventLogging() != MagickFalse)
5843  (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
5844  canvas=image;
5845  if ((window->immutable == MagickFalse) &&
5846  (image->storage_class == DirectClass) && (image->matte != MagickFalse))
5847  {
5848  char
5849  size[MaxTextExtent];
5850 
5851  Image
5852  *pattern;
5853 
5854  ImageInfo
5855  *image_info;
5856 
5857  image_info=AcquireImageInfo();
5858  (void) CopyMagickString(image_info->filename,
5859  resource_info->image_info->texture != (char *) NULL ?
5860  resource_info->image_info->texture : "pattern:checkerboard",
5861  MaxTextExtent);
5862  (void) FormatLocaleString(size,MaxTextExtent,"%.20gx%.20g",(double)
5863  image->columns,(double) image->rows);
5864  image_info->size=ConstantString(size);
5865  pattern=ReadImage(image_info,&image->exception);
5866  image_info=DestroyImageInfo(image_info);
5867  if (pattern != (Image *) NULL)
5868  {
5869  canvas=CloneImage(image,0,0,MagickTrue,&image->exception);
5870  if (canvas == (Image *) NULL)
5871  return;
5872  (void) CompositeImage(canvas,DstOverCompositeOp,pattern,0,0);
5873  pattern=DestroyImage(pattern);
5874  }
5875  }
5876  scanline_pad=(unsigned int) (ximage->bytes_per_line-((ximage->width*
5877  ximage->bits_per_pixel) >> 3));
5878  map_info=window->map_info;
5879  pixels=window->pixel_info->pixels;
5880  q=(unsigned char *) ximage->data;
5881  x=0;
5882  canvas_view=AcquireVirtualCacheView(canvas,&canvas->exception);
5883  if (ximage->format == XYBitmap)
5884  {
5885  unsigned short
5886  polarity;
5887 
5888  unsigned char
5889  background,
5890  foreground;
5891 
5892  /*
5893  Convert canvas to big-endian bitmap.
5894  */
5895  background=(unsigned char)
5896  (XPixelIntensity(&window->pixel_info->foreground_color) <
5897  XPixelIntensity(&window->pixel_info->background_color) ? 0x80 : 0x00);
5898  foreground=(unsigned char)
5899  (XPixelIntensity(&window->pixel_info->background_color) <
5900  XPixelIntensity(&window->pixel_info->foreground_color) ? 0x80 : 0x00);
5901  polarity=(unsigned short) ((GetPixelIntensity(image,
5902  &canvas->colormap[0])) < (QuantumRange/2.0) ? 1 : 0);
5903  if (canvas->colors == 2)
5904  polarity=GetPixelIntensity(canvas,&canvas->colormap[0]) <
5905  GetPixelIntensity(canvas,&canvas->colormap[1]);
5906  for (y=0; y < (int) canvas->rows; y++)
5907  {
5908  p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,canvas->columns,1,
5909  &canvas->exception);
5910  if (p == (const PixelPacket *) NULL)
5911  break;
5912  indexes=GetCacheViewVirtualIndexQueue(canvas_view);
5913  bit=0;
5914  byte=0;
5915  for (x=0; x < (int) canvas->columns; x++)
5916  {
5917  byte>>=1;
5918  if (GetPixelIndex(indexes+x) == (IndexPacket) polarity)
5919  byte|=foreground;
5920  else
5921  byte|=background;
5922  bit++;
5923  if (bit == 8)
5924  {
5925  *q++=byte;
5926  bit=0;
5927  byte=0;
5928  }
5929  }
5930  if (bit != 0)
5931  *q=byte >> (8-bit);
5932  q+=scanline_pad;
5933  }
5934  }
5935  else
5936  if (window->pixel_info->colors != 0)
5937  switch (ximage->bits_per_pixel)
5938  {
5939  case 2:
5940  {
5941  unsigned int
5942  nibble;
5943 
5944  /*
5945  Convert to 2 bit color-mapped X canvas.
5946  */
5947  for (y=0; y < (int) canvas->rows; y++)
5948  {
5949  p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
5950  canvas->columns,1,&canvas->exception);
5951  if (p == (const PixelPacket *) NULL)
5952  break;
5953  indexes=GetCacheViewVirtualIndexQueue(canvas_view);
5954  nibble=0;
5955  for (x=0; x < (int) canvas->columns; x++)
5956  {
5957  pixel=pixels[(ssize_t) GetPixelIndex(indexes+x)] & 0x0f;
5958  switch (nibble)
5959  {
5960  case 0:
5961  {
5962  *q=(unsigned char) pixel;
5963  nibble++;
5964  break;
5965  }
5966  case 1:
5967  {
5968  *q|=(unsigned char) (pixel << 2);
5969  nibble++;
5970  break;
5971  }
5972  case 2:
5973  {
5974  *q|=(unsigned char) (pixel << 4);
5975  nibble++;
5976  break;
5977  }
5978  case 3:
5979  {
5980  *q|=(unsigned char) (pixel << 6);
5981  q++;
5982  nibble=0;
5983  break;
5984  }
5985  }
5986  }
5987  q+=scanline_pad;
5988  }
5989  break;
5990  }
5991  case 4:
5992  {
5993  unsigned int
5994  nibble;
5995 
5996  /*
5997  Convert to 4 bit color-mapped X canvas.
5998  */
5999  for (y=0; y < (int) canvas->rows; y++)
6000  {
6001  p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
6002  canvas->columns,1,&canvas->exception);
6003  if (p == (const PixelPacket *) NULL)
6004  break;
6005  indexes=GetCacheViewVirtualIndexQueue(canvas_view);
6006  nibble=0;
6007  for (x=0; x < (int) canvas->columns; x++)
6008  {
6009  pixel=pixels[(ssize_t) GetPixelIndex(indexes+x)] & 0xf;
6010  switch (nibble)
6011  {
6012  case 0:
6013  {
6014  *q=(unsigned char) pixel;
6015  nibble++;
6016  break;
6017  }
6018  case 1:
6019  {
6020  *q|=(unsigned char) (pixel << 4);
6021  q++;
6022  nibble=0;
6023  break;
6024  }
6025  }
6026  }
6027  q+=scanline_pad;
6028  }
6029  break;
6030  }
6031  case 6:
6032  case 8:
6033  {
6034  /*
6035  Convert to 8 bit color-mapped X canvas.
6036  */
6037  if ((resource_info->color_recovery != MagickFalse) &&
6038  (resource_info->quantize_info->dither != MagickFalse))
6039  {
6040  XDitherImage(canvas,ximage);
6041  break;
6042  }
6043  for (y=0; y < (int) canvas->rows; y++)
6044  {
6045  p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
6046  canvas->columns,1,&canvas->exception);
6047  if (p == (const PixelPacket *) NULL)
6048  break;
6049  indexes=GetCacheViewVirtualIndexQueue(canvas_view);
6050  for (x=0; x < (int) canvas->columns; x++)
6051  {
6052  pixel=pixels[(ssize_t) GetPixelIndex(indexes+x)];
6053  *q++=(unsigned char) pixel;
6054  }
6055  q+=scanline_pad;
6056  }
6057  break;
6058  }
6059  default:
6060  {
6061  int
6062  k;
6063 
6064  unsigned int
6065  bytes_per_pixel;
6066 
6067  /*
6068  Convert to multi-byte color-mapped X canvas.
6069  */
6070  bytes_per_pixel=(unsigned int) (ximage->bits_per_pixel >> 3);
6071  for (y=0; y < (int) canvas->rows; y++)
6072  {
6073  p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
6074  canvas->columns,1,&canvas->exception);
6075  if (p == (const PixelPacket *) NULL)
6076  break;
6077  indexes=GetCacheViewVirtualIndexQueue(canvas_view);
6078  for (x=0; x < (int) canvas->columns; x++)
6079  {
6080  pixel=pixels[(ssize_t) GetPixelIndex(indexes+x)];
6081  for (k=0; k < (int) bytes_per_pixel; k++)
6082  {
6083  *q++=(unsigned char) (pixel & 0xff);
6084  pixel>>=8;
6085  }
6086  }
6087  q+=scanline_pad;
6088  }
6089  break;
6090  }
6091  }
6092  else
6093  switch (ximage->bits_per_pixel)
6094  {
6095  case 2:
6096  {
6097  unsigned int
6098  nibble;
6099 
6100  /*
6101  Convert to contiguous 2 bit continuous-tone X canvas.
6102  */
6103  for (y=0; y < (int) canvas->rows; y++)
6104  {
6105  nibble=0;
6106  p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
6107  canvas->columns,1,&canvas->exception);
6108  if (p == (const PixelPacket *) NULL)
6109  break;
6110  for (x=0; x < (int) canvas->columns; x++)
6111  {
6112  pixel=XGammaPixel(map_info,p);
6113  pixel&=0xf;
6114  switch (nibble)
6115  {
6116  case 0:
6117  {
6118  *q=(unsigned char) pixel;
6119  nibble++;
6120  break;
6121  }
6122  case 1:
6123  {
6124  *q|=(unsigned char) (pixel << 2);
6125  nibble++;
6126  break;
6127  }
6128  case 2:
6129  {
6130  *q|=(unsigned char) (pixel << 4);
6131  nibble++;
6132  break;
6133  }
6134  case 3:
6135  {
6136  *q|=(unsigned char) (pixel << 6);
6137  q++;
6138  nibble=0;
6139  break;
6140  }
6141  }
6142  p++;
6143  }
6144  q+=scanline_pad;
6145  }
6146  break;
6147  }
6148  case 4:
6149  {
6150  unsigned int
6151  nibble;
6152 
6153  /*
6154  Convert to contiguous 4 bit continuous-tone X canvas.
6155  */
6156  for (y=0; y < (int) canvas->rows; y++)
6157  {
6158  p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
6159  canvas->columns,1,&canvas->exception);
6160  if (p == (const PixelPacket *) NULL)
6161  break;
6162  nibble=0;
6163  for (x=0; x < (int) canvas->columns; x++)
6164  {
6165  pixel=XGammaPixel(map_info,p);
6166  pixel&=0xf;
6167  switch (nibble)
6168  {
6169  case 0:
6170  {
6171  *q=(unsigned char) pixel;
6172  nibble++;
6173  break;
6174  }
6175  case 1:
6176  {
6177  *q|=(unsigned char) (pixel << 4);
6178  q++;
6179  nibble=0;
6180  break;
6181  }
6182  }
6183  p++;
6184  }
6185  q+=scanline_pad;
6186  }
6187  break;
6188  }
6189  case 6:
6190  case 8:
6191  {
6192  /*
6193  Convert to contiguous 8 bit continuous-tone X canvas.
6194  */
6195  if ((resource_info->color_recovery != MagickFalse) &&
6196  (resource_info->quantize_info->dither != MagickFalse))
6197  {
6198  XDitherImage(canvas,ximage);
6199  break;
6200  }
6201  for (y=0; y < (int) canvas->rows; y++)
6202  {
6203  p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
6204  canvas->columns,1,&canvas->exception);
6205  if (p == (const PixelPacket *) NULL)
6206  break;
6207  for (x=0; x < (int) canvas->columns; x++)
6208  {
6209  pixel=XGammaPixel(map_info,p);
6210  *q++=(unsigned char) pixel;
6211  p++;
6212  }
6213  q+=scanline_pad;
6214  }
6215  break;
6216  }
6217  default:
6218  {
6219  if ((ximage->bits_per_pixel == 32) && (map_info->red_max == 255) &&
6220  (map_info->green_max == 255) && (map_info->blue_max == 255) &&
6221  (map_info->red_mult == 65536L) && (map_info->green_mult == 256) &&
6222  (map_info->blue_mult == 1))
6223  {
6224  /*
6225  Convert to 32 bit continuous-tone X canvas.
6226  */
6227  for (y=0; y < (int) canvas->rows; y++)
6228  {
6229  p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
6230  canvas->columns,1,&canvas->exception);
6231  if (p == (const PixelPacket *) NULL)
6232  break;
6233  if ((red_gamma != 1.0) || (green_gamma != 1.0) ||
6234  (blue_gamma != 1.0))
6235  {
6236  /*
6237  Gamma correct canvas.
6238  */
6239  for (x=(int) canvas->columns-1; x >= 0; x--)
6240  {
6241  *q++=ScaleQuantumToChar(XBlueGamma(GetPixelBlue(p)));
6242  *q++=ScaleQuantumToChar(XGreenGamma(GetPixelGreen(p)));
6243  *q++=ScaleQuantumToChar(XRedGamma(GetPixelRed(p)));
6244  *q++=0;
6245  p++;
6246  }
6247  continue;
6248  }
6249  for (x=(int) canvas->columns-1; x >= 0; x--)
6250  {
6251  *q++=ScaleQuantumToChar((Quantum) GetPixelBlue(p));
6252  *q++=ScaleQuantumToChar((Quantum) GetPixelGreen(p));
6253  *q++=ScaleQuantumToChar((Quantum) GetPixelRed(p));
6254  *q++=0;
6255  p++;
6256  }
6257  }
6258  }
6259  else
6260  if ((ximage->bits_per_pixel == 32) && (map_info->red_max == 255) &&
6261  (map_info->green_max == 255) && (map_info->blue_max == 255) &&
6262  (map_info->red_mult == 1) && (map_info->green_mult == 256) &&
6263  (map_info->blue_mult == 65536L))
6264  {
6265  /*
6266  Convert to 32 bit continuous-tone X canvas.
6267  */
6268  for (y=0; y < (int) canvas->rows; y++)
6269  {
6270  p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
6271  canvas->columns,1,&canvas->exception);
6272  if (p == (const PixelPacket *) NULL)
6273  break;
6274  if ((red_gamma != 1.0) || (green_gamma != 1.0) ||
6275  (blue_gamma != 1.0))
6276  {
6277  /*
6278  Gamma correct canvas.
6279  */
6280  for (x=(int) canvas->columns-1; x >= 0; x--)
6281  {
6282  *q++=ScaleQuantumToChar(XRedGamma(GetPixelRed(p)));
6283  *q++=ScaleQuantumToChar(XGreenGamma(GetPixelGreen(p)));
6284  *q++=ScaleQuantumToChar(XBlueGamma(GetPixelBlue(p)));
6285  *q++=0;
6286  p++;
6287  }
6288  continue;
6289  }
6290  for (x=(int) canvas->columns-1; x >= 0; x--)
6291  {
6292  *q++=ScaleQuantumToChar((Quantum) GetPixelRed(p));
6293  *q++=ScaleQuantumToChar((Quantum) GetPixelGreen(p));
6294  *q++=ScaleQuantumToChar((Quantum) GetPixelBlue(p));
6295  *q++=0;
6296  p++;
6297  }
6298  }
6299  }
6300  else
6301  {
6302  int
6303  k;
6304 
6305  unsigned int
6306  bytes_per_pixel;
6307 
6308  /*
6309  Convert to multi-byte continuous-tone X canvas.
6310  */
6311  bytes_per_pixel=(unsigned int) (ximage->bits_per_pixel >> 3);
6312  for (y=0; y < (int) canvas->rows; y++)
6313  {
6314  p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
6315  canvas->columns,1,&canvas->exception);
6316  if (p == (PixelPacket *) NULL)
6317  break;
6318  for (x=0; x < (int) canvas->columns; x++)
6319  {
6320  pixel=XGammaPixel(map_info,p);
6321  for (k=0; k < (int) bytes_per_pixel; k++)
6322  {
6323  *q++=(unsigned char) (pixel & 0xff);
6324  pixel>>=8;
6325  }
6326  p++;
6327  }
6328  q+=scanline_pad;
6329  }
6330  }
6331  break;
6332  }
6333  }
6334  if (matte_image != (XImage *) NULL)
6335  {
6336  /*
6337  Initialize matte canvas.
6338  */
6339  scanline_pad=(unsigned int) (matte_image->bytes_per_line-
6340  ((matte_image->width*matte_image->bits_per_pixel) >> 3));
6341  q=(unsigned char *) matte_image->data;
6342  for (y=0; y < (int) canvas->rows; y++)
6343  {
6344  p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,canvas->columns,1,
6345  &canvas->exception);
6346  if (p == (const PixelPacket *) NULL)
6347  break;
6348  bit=0;
6349  byte=0;
6350  for (x=(int) canvas->columns-1; x >= 0; x--)
6351  {
6352  byte>>=1;
6353  if (GetPixelOpacity(p) > (QuantumRange/2))
6354  byte|=0x80;
6355  bit++;
6356  if (bit == 8)
6357  {
6358  *q++=byte;
6359  bit=0;
6360  byte=0;
6361  }
6362  p++;
6363  }
6364  if (bit != 0)
6365  *q=byte >> (8-bit);
6366  q+=scanline_pad;
6367  }
6368  }
6369  canvas_view=DestroyCacheView(canvas_view);
6370  if (canvas != image)
6371  canvas=DestroyImage(canvas);
6372 }
6373 ␌
6374 /*
6375 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
6376 % %
6377 % %
6378 % %
6379 + X M a k e I m a g e M S B F i r s t %
6380 % %
6381 % %
6382 % %
6383 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
6384 %
6385 % XMakeImageMSBFirst() initializes the pixel data of an X11 Image. The X
6386 % image pixels are copied in most-significant bit and byte first order. The
6387 % server's scanline pad is also respected. Rather than using one or two
6388 % general cases, many special cases are found here to help speed up the image
6389 % conversion.
6390 %
6391 % The format of the XMakeImageMSBFirst method is:
6392 %
6393 % XMakeImageMSBFirst(resource_info,window,image,ximage,matte_image)
6394 %
6395 % A description of each parameter follows:
6396 %
6397 % o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
6398 %
6399 % o window: Specifies a pointer to a XWindowInfo structure.
6400 %
6401 % o image: the image.
6402 %
6403 % o ximage: Specifies a pointer to a XImage structure; returned from
6404 % XCreateImage.
6405 %
6406 % o matte_image: Specifies a pointer to a XImage structure; returned from
6407 % XCreateImage.
6408 %
6409 */
6410 static void XMakeImageMSBFirst(const XResourceInfo *resource_info,
6411  const XWindowInfo *window,Image *image,XImage *ximage,XImage *matte_image)
6412 {
6413  CacheView
6414  *canvas_view;
6415 
6416  Image
6417  *canvas;
6418 
6419  int
6420  y;
6421 
6422  int
6423  x;
6424 
6425  const IndexPacket
6426  *indexes;
6427 
6428  const PixelPacket
6429  *p;
6430 
6431  unsigned char
6432  *q;
6433 
6434  unsigned char
6435  bit,
6436  byte;
6437 
6438  unsigned int
6439  scanline_pad;
6440 
6441  unsigned long
6442  pixel,
6443  *pixels;
6444 
6445  XStandardColormap
6446  *map_info;
6447 
6448  assert(resource_info != (XResourceInfo *) NULL);
6449  assert(window != (XWindowInfo *) NULL);
6450  assert(image != (Image *) NULL);
6451  if (IsEventLogging() != MagickFalse)
6452  (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
6453  canvas=image;
6454  if ((window->immutable != MagickFalse) &&
6455  (image->storage_class == DirectClass) && (image->matte != MagickFalse))
6456  {
6457  char
6458  size[MaxTextExtent];
6459 
6460  Image
6461  *pattern;
6462 
6463  ImageInfo
6464  *image_info;
6465 
6466  image_info=AcquireImageInfo();
6467  (void) CopyMagickString(image_info->filename,
6468  resource_info->image_info->texture != (char *) NULL ?
6469  resource_info->image_info->texture : "pattern:checkerboard",
6470  MaxTextExtent);
6471  (void) FormatLocaleString(size,MaxTextExtent,"%.20gx%.20g",(double)
6472  image->columns,(double) image->rows);
6473  image_info->size=ConstantString(size);
6474  pattern=ReadImage(image_info,&image->exception);
6475  image_info=DestroyImageInfo(image_info);
6476  if (pattern != (Image *) NULL)
6477  {
6478  canvas=CloneImage(image,0,0,MagickTrue,&image->exception);
6479  if (canvas == (Image *) NULL)
6480  return;
6481  (void) CompositeImage(canvas,DstOverCompositeOp,pattern,0,0);
6482  pattern=DestroyImage(pattern);
6483  }
6484  }
6485  scanline_pad=(unsigned int) (ximage->bytes_per_line-
6486  ((ximage->width*ximage->bits_per_pixel) >> 3));
6487  map_info=window->map_info;
6488  pixels=window->pixel_info->pixels;
6489  q=(unsigned char *) ximage->data;
6490  x=0;
6491  canvas_view=AcquireVirtualCacheView(canvas,&canvas->exception);
6492  if (ximage->format == XYBitmap)
6493  {
6494  unsigned short
6495  polarity;
6496 
6497  unsigned char
6498  background,
6499  foreground;
6500 
6501  /*
6502  Convert canvas to big-endian bitmap.
6503  */
6504  background=(unsigned char)
6505  (XPixelIntensity(&window->pixel_info->foreground_color) <
6506  XPixelIntensity(&window->pixel_info->background_color) ? 0x01 : 0x00);
6507  foreground=(unsigned char)
6508  (XPixelIntensity(&window->pixel_info->background_color) <
6509  XPixelIntensity(&window->pixel_info->foreground_color) ? 0x01 : 0x00);
6510  polarity=(unsigned short) ((GetPixelIntensity(image,
6511  &canvas->colormap[0])) < (QuantumRange/2.0) ? 1 : 0);
6512  if (canvas->colors == 2)
6513  polarity=GetPixelIntensity(canvas,&canvas->colormap[0]) <
6514  GetPixelIntensity(canvas,&canvas->colormap[1]);
6515  for (y=0; y < (int) canvas->rows; y++)
6516  {
6517  p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,canvas->columns,1,
6518  &canvas->exception);
6519  if (p == (const PixelPacket *) NULL)
6520  break;
6521  indexes=GetCacheViewVirtualIndexQueue(canvas_view);
6522  bit=0;
6523  byte=0;
6524  for (x=(int) canvas->columns-1; x >= 0; x--)
6525  {
6526  byte<<=1;
6527  if (GetPixelIndex(indexes+x) == (IndexPacket) polarity)
6528  byte|=foreground;
6529  else
6530  byte|=background;
6531  bit++;
6532  if (bit == 8)
6533  {
6534  *q++=byte;
6535  bit=0;
6536  byte=0;
6537  }
6538  }
6539  if (bit != 0)
6540  *q=byte << (8-bit);
6541  q+=scanline_pad;
6542  }
6543  }
6544  else
6545  if (window->pixel_info->colors != 0)
6546  switch (ximage->bits_per_pixel)
6547  {
6548  case 2:
6549  {
6550  unsigned int
6551  nibble;
6552 
6553  /*
6554  Convert to 2 bit color-mapped X canvas.
6555  */
6556  for (y=0; y < (int) canvas->rows; y++)
6557  {
6558  p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
6559  canvas->columns,1,&canvas->exception);
6560  if (p == (const PixelPacket *) NULL)
6561  break;
6562  indexes=GetCacheViewVirtualIndexQueue(canvas_view);
6563  nibble=0;
6564  for (x=0; x < (int) canvas->columns; x++)
6565  {
6566  pixel=pixels[(ssize_t) GetPixelIndex(indexes+x)] & 0xf;
6567  switch (nibble)
6568  {
6569  case 0:
6570  {
6571  *q=(unsigned char) (pixel << 6);
6572  nibble++;
6573  break;
6574  }
6575  case 1:
6576  {
6577  *q|=(unsigned char) (pixel << 4);
6578  nibble++;
6579  break;
6580  }
6581  case 2:
6582  {
6583  *q|=(unsigned char) (pixel << 2);
6584  nibble++;
6585  break;
6586  }
6587  case 3:
6588  {
6589  *q|=(unsigned char) pixel;
6590  q++;
6591  nibble=0;
6592  break;
6593  }
6594  }
6595  }
6596  q+=scanline_pad;
6597  }
6598  break;
6599  }
6600  case 4:
6601  {
6602  unsigned int
6603  nibble;
6604 
6605  /*
6606  Convert to 4 bit color-mapped X canvas.
6607  */
6608  for (y=0; y < (int) canvas->rows; y++)
6609  {
6610  p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
6611  canvas->columns,1,&canvas->exception);
6612  if (p == (const PixelPacket *) NULL)
6613  break;
6614  indexes=GetCacheViewVirtualIndexQueue(canvas_view);
6615  nibble=0;
6616  for (x=0; x < (int) canvas->columns; x++)
6617  {
6618  pixel=pixels[(ssize_t) GetPixelIndex(indexes+x)] & 0xf;
6619  switch (nibble)
6620  {
6621  case 0:
6622  {
6623  *q=(unsigned char) (pixel << 4);
6624  nibble++;
6625  break;
6626  }
6627  case 1:
6628  {
6629  *q|=(unsigned char) pixel;
6630  q++;
6631  nibble=0;
6632  break;
6633  }
6634  }
6635  }
6636  q+=scanline_pad;
6637  }
6638  break;
6639  }
6640  case 6:
6641  case 8:
6642  {
6643  /*
6644  Convert to 8 bit color-mapped X canvas.
6645  */
6646  if (resource_info->color_recovery &&
6647  resource_info->quantize_info->dither)
6648  {
6649  XDitherImage(canvas,ximage);
6650  break;
6651  }
6652  for (y=0; y < (int) canvas->rows; y++)
6653  {
6654  p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
6655  canvas->columns,1,&canvas->exception);
6656  if (p == (const PixelPacket *) NULL)
6657  break;
6658  indexes=GetCacheViewVirtualIndexQueue(canvas_view);
6659  for (x=0; x < (int) canvas->columns; x++)
6660  {
6661  pixel=pixels[(ssize_t) GetPixelIndex(indexes+x)];
6662  *q++=(unsigned char) pixel;
6663  }
6664  q+=scanline_pad;
6665  }
6666  break;
6667  }
6668  default:
6669  {
6670  int
6671  k;
6672 
6673  unsigned int
6674  bytes_per_pixel;
6675 
6676  unsigned char
6677  channel[sizeof(size_t)];
6678 
6679  /*
6680  Convert to 8 bit color-mapped X canvas.
6681  */
6682  bytes_per_pixel=(unsigned int) (ximage->bits_per_pixel >> 3);
6683  for (y=0; y < (int) canvas->rows; y++)
6684  {
6685  p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
6686  canvas->columns,1,&canvas->exception);
6687  if (p == (const PixelPacket *) NULL)
6688  break;
6689  indexes=GetCacheViewVirtualIndexQueue(canvas_view);
6690  for (x=0; x < (int) canvas->columns; x++)
6691  {
6692  pixel=pixels[(ssize_t) GetPixelIndex(indexes+x)];
6693  for (k=(int) bytes_per_pixel-1; k >= 0; k--)
6694  {
6695  channel[k]=(unsigned char) pixel;
6696  pixel>>=8;
6697  }
6698  for (k=0; k < (int) bytes_per_pixel; k++)
6699  *q++=channel[k];
6700  }
6701  q+=scanline_pad;
6702  }
6703  break;
6704  }
6705  }
6706  else
6707  switch (ximage->bits_per_pixel)
6708  {
6709  case 2:
6710  {
6711  unsigned int
6712  nibble;
6713 
6714  /*
6715  Convert to 4 bit continuous-tone X canvas.
6716  */
6717  for (y=0; y < (int) canvas->rows; y++)
6718  {
6719  p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
6720  canvas->columns,1,&canvas->exception);
6721  if (p == (const PixelPacket *) NULL)
6722  break;
6723  nibble=0;
6724  for (x=(int) canvas->columns-1; x >= 0; x--)
6725  {
6726  pixel=XGammaPixel(map_info,p);
6727  pixel&=0xf;
6728  switch (nibble)
6729  {
6730  case 0:
6731  {
6732  *q=(unsigned char) (pixel << 6);
6733  nibble++;
6734  break;
6735  }
6736  case 1:
6737  {
6738  *q|=(unsigned char) (pixel << 4);
6739  nibble++;
6740  break;
6741  }
6742  case 2:
6743  {
6744  *q|=(unsigned char) (pixel << 2);
6745  nibble++;
6746  break;
6747  }
6748  case 3:
6749  {
6750  *q|=(unsigned char) pixel;
6751  q++;
6752  nibble=0;
6753  break;
6754  }
6755  }
6756  p++;
6757  }
6758  q+=scanline_pad;
6759  }
6760  break;
6761  }
6762  case 4:
6763  {
6764  unsigned int
6765  nibble;
6766 
6767  /*
6768  Convert to 4 bit continuous-tone X canvas.
6769  */
6770  for (y=0; y < (int) canvas->rows; y++)
6771  {
6772  p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
6773  canvas->columns,1,&canvas->exception);
6774  if (p == (const PixelPacket *) NULL)
6775  break;
6776  nibble=0;
6777  for (x=(int) canvas->columns-1; x >= 0; x--)
6778  {
6779  pixel=XGammaPixel(map_info,p);
6780  pixel&=0xf;
6781  switch (nibble)
6782  {
6783  case 0:
6784  {
6785  *q=(unsigned char) (pixel << 4);
6786  nibble++;
6787  break;
6788  }
6789  case 1:
6790  {
6791  *q|=(unsigned char) pixel;
6792  q++;
6793  nibble=0;
6794  break;
6795  }
6796  }
6797  p++;
6798  }
6799  q+=scanline_pad;
6800  }
6801  break;
6802  }
6803  case 6:
6804  case 8:
6805  {
6806  /*
6807  Convert to 8 bit continuous-tone X canvas.
6808  */
6809  if (resource_info->color_recovery &&
6810  resource_info->quantize_info->dither)
6811  {
6812  XDitherImage(canvas,ximage);
6813  break;
6814  }
6815  for (y=0; y < (int) canvas->rows; y++)
6816  {
6817  p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
6818  canvas->columns,1,&canvas->exception);
6819  if (p == (const PixelPacket *) NULL)
6820  break;
6821  for (x=(int) canvas->columns-1; x >= 0; x--)
6822  {
6823  pixel=XGammaPixel(map_info,p);
6824  *q++=(unsigned char) pixel;
6825  p++;
6826  }
6827  q+=scanline_pad;
6828  }
6829  break;
6830  }
6831  default:
6832  {
6833  if ((ximage->bits_per_pixel == 32) && (map_info->red_max == 255) &&
6834  (map_info->green_max == 255) && (map_info->blue_max == 255) &&
6835  (map_info->red_mult == 65536L) && (map_info->green_mult == 256) &&
6836  (map_info->blue_mult == 1))
6837  {
6838  /*
6839  Convert to 32 bit continuous-tone X canvas.
6840  */
6841  for (y=0; y < (int) canvas->rows; y++)
6842  {
6843  p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
6844  canvas->columns,1,&canvas->exception);
6845  if (p == (const PixelPacket *) NULL)
6846  break;
6847  if ((red_gamma != 1.0) || (green_gamma != 1.0) ||
6848  (blue_gamma != 1.0))
6849  {
6850  /*
6851  Gamma correct canvas.
6852  */
6853  for (x=(int) canvas->columns-1; x >= 0; x--)
6854  {
6855  *q++=0;
6856  *q++=ScaleQuantumToChar(XRedGamma(GetPixelRed(p)));
6857  *q++=ScaleQuantumToChar(XGreenGamma(GetPixelGreen(p)));
6858  *q++=ScaleQuantumToChar(XBlueGamma(GetPixelBlue(p)));
6859  p++;
6860  }
6861  continue;
6862  }
6863  for (x=(int) canvas->columns-1; x >= 0; x--)
6864  {
6865  *q++=0;
6866  *q++=ScaleQuantumToChar((Quantum) GetPixelRed(p));
6867  *q++=ScaleQuantumToChar((Quantum) GetPixelGreen(p));
6868  *q++=ScaleQuantumToChar((Quantum) GetPixelBlue(p));
6869  p++;
6870  }
6871  }
6872  }
6873  else
6874  if ((ximage->bits_per_pixel == 32) && (map_info->red_max == 255) &&
6875  (map_info->green_max == 255) && (map_info->blue_max == 255) &&
6876  (map_info->red_mult == 1) && (map_info->green_mult == 256) &&
6877  (map_info->blue_mult == 65536L))
6878  {
6879  /*
6880  Convert to 32 bit continuous-tone X canvas.
6881  */
6882  for (y=0; y < (int) canvas->rows; y++)
6883  {
6884  p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
6885  canvas->columns,1,&canvas->exception);
6886  if (p == (const PixelPacket *) NULL)
6887  break;
6888  if ((red_gamma != 1.0) || (green_gamma != 1.0) ||
6889  (blue_gamma != 1.0))
6890  {
6891  /*
6892  Gamma correct canvas.
6893  */
6894  for (x=(int) canvas->columns-1; x >= 0; x--)
6895  {
6896  *q++=0;
6897  *q++=ScaleQuantumToChar(XBlueGamma(GetPixelBlue(p)));
6898  *q++=ScaleQuantumToChar(XGreenGamma(GetPixelGreen(p)));
6899  *q++=ScaleQuantumToChar(XRedGamma(GetPixelRed(p)));
6900  p++;
6901  }
6902  continue;
6903  }
6904  for (x=(int) canvas->columns-1; x >= 0; x--)
6905  {
6906  *q++=0;
6907  *q++=ScaleQuantumToChar((Quantum) GetPixelBlue(p));
6908  *q++=ScaleQuantumToChar((Quantum) GetPixelGreen(p));
6909  *q++=ScaleQuantumToChar((Quantum) GetPixelRed(p));
6910  p++;
6911  }
6912  }
6913  }
6914  else
6915  {
6916  int
6917  k;
6918 
6919  unsigned int
6920  bytes_per_pixel;
6921 
6922  /*
6923  Convert to multi-byte continuous-tone X canvas.
6924  */
6925  bytes_per_pixel=(unsigned int) (ximage->bits_per_pixel >> 3);
6926  for (y=0; y < (int) canvas->rows; y++)
6927  {
6928  p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
6929  canvas->columns,1,&canvas->exception);
6930  if (p == (const PixelPacket *) NULL)
6931  break;
6932  for (x=(int) canvas->columns-1; x >= 0; x--)
6933  {
6934  pixel=XGammaPixel(map_info,p);
6935  for (k=(int) bytes_per_pixel-1; k >= 0; k--)
6936  {
6937  *q++=(unsigned char) (pixel & 0xff);
6938  pixel>>=8;
6939  }
6940  p++;
6941  }
6942  q+=scanline_pad;
6943  }
6944  }
6945  break;
6946  }
6947  }
6948  if (matte_image != (XImage *) NULL)
6949  {
6950  /*
6951  Initialize matte canvas.
6952  */
6953  scanline_pad=(unsigned int) (matte_image->bytes_per_line-
6954  ((matte_image->width*matte_image->bits_per_pixel) >> 3));
6955  q=(unsigned char *) matte_image->data;
6956  for (y=0; y < (int) canvas->rows; y++)
6957  {
6958  p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,canvas->columns,1,
6959  &canvas->exception);
6960  if (p == (const PixelPacket *) NULL)
6961  break;
6962  bit=0;
6963  byte=0;
6964  for (x=(int) canvas->columns-1; x >= 0; x--)
6965  {
6966  byte<<=1;
6967  if (GetPixelOpacity(p) > (QuantumRange/2))
6968  byte|=0x01;
6969  bit++;
6970  if (bit == 8)
6971  {
6972  *q++=byte;
6973  bit=0;
6974  byte=0;
6975  }
6976  p++;
6977  }
6978  if (bit != 0)
6979  *q=byte << (8-bit);
6980  q+=scanline_pad;
6981  }
6982  }
6983  canvas_view=DestroyCacheView(canvas_view);
6984  if (canvas != image)
6985  canvas=DestroyImage(canvas);
6986 }
6987 ␌
6988 /*
6989 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
6990 % %
6991 % %
6992 % %
6993 % X M a k e M a g n i f y I m a g e %
6994 % %
6995 % %
6996 % %
6997 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
6998 %
6999 % XMakeMagnifyImage() magnifies a region of an X image and displays it.
7000 %
7001 % The format of the XMakeMagnifyImage method is:
7002 %
7003 % void XMakeMagnifyImage(display,windows)
7004 %
7005 % A description of each parameter follows:
7006 %
7007 % o display: Specifies a connection to an X server; returned from
7008 % XOpenDisplay.
7009 %
7010 % o windows: Specifies a pointer to a XWindows structure.
7011 %
7012 */
7013 MagickExport void XMakeMagnifyImage(Display *display,XWindows *windows)
7014 {
7015  char
7016  tuple[MaxTextExtent];
7017 
7018  int
7019  y;
7020 
7022  pixel;
7023 
7024  int
7025  x;
7026 
7027  ssize_t
7028  i;
7029 
7030  unsigned char
7031  *p,
7032  *q;
7033 
7034  ssize_t
7035  n;
7036 
7037  static unsigned int
7038  previous_magnify = 0;
7039 
7040  static XWindowInfo
7041  magnify_window;
7042 
7043  unsigned int
7044  height,
7045  j,
7046  k,
7047  l,
7048  magnify,
7049  scanline_pad,
7050  width;
7051 
7052  XImage
7053  *ximage;
7054 
7055  /*
7056  Check boundary conditions.
7057  */
7058  assert(display != (Display *) NULL);
7059  assert(windows != (XWindows *) NULL);
7060  if (IsEventLogging() != MagickFalse)
7061  (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
7062  magnify=1;
7063  for (n=1; n < (ssize_t) windows->magnify.data; n++)
7064  magnify<<=1;
7065  while ((magnify*windows->image.ximage->width) < windows->magnify.width)
7066  magnify<<=1;
7067  while ((magnify*windows->image.ximage->height) < windows->magnify.height)
7068  magnify<<=1;
7069  while (magnify > windows->magnify.width)
7070  magnify>>=1;
7071  while (magnify > windows->magnify.height)
7072  magnify>>=1;
7073  if (magnify == 0)
7074  {
7075  magnify=1;
7076  if (previous_magnify != 0)
7077  magnify=previous_magnify;
7078  }
7079  if (magnify != previous_magnify)
7080  {
7081  Status
7082  status;
7083 
7084  XTextProperty
7085  window_name;
7086 
7087  /*
7088  New magnify factor: update magnify window name.
7089  */
7090  i=0;
7091  while ((1 << i) <= (int) magnify)
7092  i++;
7093  (void) FormatLocaleString(windows->magnify.name,MaxTextExtent,
7094  "Magnify %.20gX",(double) i);
7095  status=XStringListToTextProperty(&windows->magnify.name,1,&window_name);
7096  if (status != False)
7097  {
7098  XSetWMName(display,windows->magnify.id,&window_name);
7099  XSetWMIconName(display,windows->magnify.id,&window_name);
7100  (void) XFree((void *) window_name.value);
7101  }
7102  }
7103  previous_magnify=magnify;
7104  ximage=windows->image.ximage;
7105  width=(unsigned int) windows->magnify.ximage->width;
7106  height=(unsigned int) windows->magnify.ximage->height;
7107  if ((windows->magnify.x < 0) ||
7108  (windows->magnify.x >= windows->image.ximage->width))
7109  windows->magnify.x=windows->image.ximage->width >> 1;
7110  x=windows->magnify.x-((width/magnify) >> 1);
7111  if (x < 0)
7112  x=0;
7113  else
7114  if (x > (int) (ximage->width-(width/magnify)))
7115  x=ximage->width-width/magnify;
7116  if ((windows->magnify.y < 0) ||
7117  (windows->magnify.y >= windows->image.ximage->height))
7118  windows->magnify.y=windows->image.ximage->height >> 1;
7119  y=windows->magnify.y-((height/magnify) >> 1);
7120  if (y < 0)
7121  y=0;
7122  else
7123  if (y > (int) (ximage->height-(height/magnify)))
7124  y=ximage->height-height/magnify;
7125  q=(unsigned char *) windows->magnify.ximage->data;
7126  scanline_pad=(unsigned int) (windows->magnify.ximage->bytes_per_line-
7127  ((width*windows->magnify.ximage->bits_per_pixel) >> 3));
7128  if (ximage->bits_per_pixel < 8)
7129  {
7130  unsigned char
7131  background,
7132  byte,
7133  foreground,
7134  p_bit,
7135  q_bit;
7136 
7137  unsigned int
7138  plane;
7139 
7140  XPixelInfo
7141  *pixel_info;
7142 
7143  pixel_info=windows->magnify.pixel_info;
7144  switch (ximage->bitmap_bit_order)
7145  {
7146  case LSBFirst:
7147  {
7148  /*
7149  Magnify little-endian bitmap.
7150  */
7151  background=0x00;
7152  foreground=0x80;
7153  if (ximage->format == XYBitmap)
7154  {
7155  background=(unsigned char)
7156  (XPixelIntensity(&pixel_info->foreground_color) <
7157  XPixelIntensity(&pixel_info->background_color) ? 0x80 : 0x00);
7158  foreground=(unsigned char)
7159  (XPixelIntensity(&pixel_info->background_color) <
7160  XPixelIntensity(&pixel_info->foreground_color) ? 0x80 : 0x00);
7161  if (windows->magnify.depth > 1)
7162  Swap(background,foreground);
7163  }
7164  for (i=0; i < (ssize_t) height; i+=magnify)
7165  {
7166  /*
7167  Propogate pixel magnify rows.
7168  */
7169  for (j=0; j < magnify; j++)
7170  {
7171  p=(unsigned char *) ximage->data+y*ximage->bytes_per_line+
7172  ((x*ximage->bits_per_pixel) >> 3);
7173  p_bit=(unsigned char) (x*ximage->bits_per_pixel) & 0x07;
7174  q_bit=0;
7175  byte=0;
7176  for (k=0; k < width; k+=magnify)
7177  {
7178  /*
7179  Propogate pixel magnify columns.
7180  */
7181  for (l=0; l < magnify; l++)
7182  {
7183  /*
7184  Propogate each bit plane.
7185  */
7186  for (plane=0; (int) plane < ximage->bits_per_pixel; plane++)
7187  {
7188  byte>>=1;
7189  if (*p & (0x01 << (p_bit+plane)))
7190  byte|=foreground;
7191  else
7192  byte|=background;
7193  q_bit++;
7194  if (q_bit == 8)
7195  {
7196  *q++=byte;
7197  q_bit=0;
7198  byte=0;
7199  }
7200  }
7201  }
7202  p_bit+=ximage->bits_per_pixel;
7203  if (p_bit == 8)
7204  {
7205  p++;
7206  p_bit=0;
7207  }
7208  if (q_bit != 0)
7209  *q=byte >> (8-q_bit);
7210  q+=scanline_pad;
7211  }
7212  }
7213  y++;
7214  }
7215  break;
7216  }
7217  case MSBFirst:
7218  default:
7219  {
7220  /*
7221  Magnify big-endian bitmap.
7222  */
7223  background=0x00;
7224  foreground=0x01;
7225  if (ximage->format == XYBitmap)
7226  {
7227  background=(unsigned char)
7228  (XPixelIntensity(&pixel_info->foreground_color) <
7229  XPixelIntensity(&pixel_info->background_color) ? 0x01 : 0x00);
7230  foreground=(unsigned char)
7231  (XPixelIntensity(&pixel_info->background_color) <
7232  XPixelIntensity(&pixel_info->foreground_color) ? 0x01 : 0x00);
7233  if (windows->magnify.depth > 1)
7234  Swap(background,foreground);
7235  }
7236  for (i=0; i < (ssize_t) height; i+=magnify)
7237  {
7238  /*
7239  Propagate pixel magnify rows.
7240  */
7241  for (j=0; j < magnify; j++)
7242  {
7243  p=(unsigned char *) ximage->data+y*ximage->bytes_per_line+
7244  ((x*ximage->bits_per_pixel) >> 3);
7245  p_bit=(unsigned char) (x*ximage->bits_per_pixel) & 0x07;
7246  q_bit=0;
7247  byte=0;
7248  for (k=0; k < width; k+=magnify)
7249  {
7250  /*
7251  Propagate pixel magnify columns.
7252  */
7253  for (l=0; l < magnify; l++)
7254  {
7255  /*
7256  Propagate each bit plane.
7257  */
7258  for (plane=0; (int) plane < ximage->bits_per_pixel; plane++)
7259  {
7260  byte<<=1;
7261  if (*p & (0x80 >> (p_bit+plane)))
7262  byte|=foreground;
7263  else
7264  byte|=background;
7265  q_bit++;
7266  if (q_bit == 8)
7267  {
7268  *q++=byte;
7269  q_bit=0;
7270  byte=0;
7271  }
7272  }
7273  }
7274  p_bit+=ximage->bits_per_pixel;
7275  if (p_bit == 8)
7276  {
7277  p++;
7278  p_bit=0;
7279  }
7280  if (q_bit != 0)
7281  *q=byte << (8-q_bit);
7282  q+=scanline_pad;
7283  }
7284  }
7285  y++;
7286  }
7287  break;
7288  }
7289  }
7290  }
7291  else
7292  switch (ximage->bits_per_pixel)
7293  {
7294  case 6:
7295  case 8:
7296  {
7297  /*
7298  Magnify 8 bit X image.
7299  */
7300  for (i=0; i < (ssize_t) height; i+=magnify)
7301  {
7302  /*
7303  Propogate pixel magnify rows.
7304  */
7305  for (j=0; j < magnify; j++)
7306  {
7307  p=(unsigned char *) ximage->data+y*ximage->bytes_per_line+
7308  ((x*ximage->bits_per_pixel) >> 3);
7309  for (k=0; k < width; k+=magnify)
7310  {
7311  /*
7312  Propogate pixel magnify columns.
7313  */
7314  for (l=0; l < magnify; l++)
7315  *q++=(*p);
7316  p++;
7317  }
7318  q+=scanline_pad;
7319  }
7320  y++;
7321  }
7322  break;
7323  }
7324  default:
7325  {
7326  unsigned int
7327  bytes_per_pixel,
7328  m;
7329 
7330  /*
7331  Magnify multi-byte X image.
7332  */
7333  bytes_per_pixel=(unsigned int) ximage->bits_per_pixel >> 3;
7334  for (i=0; i < (ssize_t) height; i+=magnify)
7335  {
7336  /*
7337  Propagate pixel magnify rows.
7338  */
7339  for (j=0; j < magnify; j++)
7340  {
7341  p=(unsigned char *) ximage->data+y*ximage->bytes_per_line+
7342  ((x*ximage->bits_per_pixel) >> 3);
7343  for (k=0; k < width; k+=magnify)
7344  {
7345  /*
7346  Propagate pixel magnify columns.
7347  */
7348  for (l=0; l < magnify; l++)
7349  for (m=0; m < bytes_per_pixel; m++)
7350  *q++=(*(p+m));
7351  p+=bytes_per_pixel;
7352  }
7353  q+=scanline_pad;
7354  }
7355  y++;
7356  }
7357  break;
7358  }
7359  }
7360  /*
7361  Copy X image to magnify pixmap.
7362  */
7363  x=windows->magnify.x-((width/magnify) >> 1);
7364  if (x < 0)
7365  x=(int) ((width >> 1)-windows->magnify.x*magnify);
7366  else
7367  if (x > (int) (ximage->width-(width/magnify)))
7368  x=(int) ((ximage->width-windows->magnify.x)*magnify-(width >> 1));
7369  else
7370  x=0;
7371  y=windows->magnify.y-((height/magnify) >> 1);
7372  if (y < 0)
7373  y=(int) ((height >> 1)-windows->magnify.y*magnify);
7374  else
7375  if (y > (int) (ximage->height-(height/magnify)))
7376  y=(int) ((ximage->height-windows->magnify.y)*magnify-(height >> 1));
7377  else
7378  y=0;
7379  if ((x != 0) || (y != 0))
7380  (void) XFillRectangle(display,windows->magnify.pixmap,
7381  windows->magnify.annotate_context,0,0,width,height);
7382  (void) XPutImage(display,windows->magnify.pixmap,
7383  windows->magnify.annotate_context,windows->magnify.ximage,0,0,x,y,width-x,
7384  height-y);
7385  if ((magnify > 1) && ((magnify <= (width >> 1)) &&
7386  (magnify <= (height >> 1))))
7387  {
7389  highlight_info;
7390 
7391  /*
7392  Highlight center pixel.
7393  */
7394  highlight_info.x=(ssize_t) windows->magnify.width >> 1;
7395  highlight_info.y=(ssize_t) windows->magnify.height >> 1;
7396  highlight_info.width=magnify;
7397  highlight_info.height=magnify;
7398  (void) XDrawRectangle(display,windows->magnify.pixmap,
7399  windows->magnify.highlight_context,(int) highlight_info.x,
7400  (int) highlight_info.y,(unsigned int) highlight_info.width-1,
7401  (unsigned int) highlight_info.height-1);
7402  if (magnify > 2)
7403  (void) XDrawRectangle(display,windows->magnify.pixmap,
7404  windows->magnify.annotate_context,(int) highlight_info.x+1,
7405  (int) highlight_info.y+1,(unsigned int) highlight_info.width-3,
7406  (unsigned int) highlight_info.height-3);
7407  }
7408  /*
7409  Show center pixel color.
7410  */
7411  (void) GetOneVirtualMagickPixel(windows->image.image,(ssize_t)
7412  windows->magnify.x,(ssize_t) windows->magnify.y,&pixel,
7413  &windows->image.image->exception);
7414  (void) FormatLocaleString(tuple,MaxTextExtent,"%d,%d: ",
7415  windows->magnify.x,windows->magnify.y);
7416  (void) ConcatenateMagickString(tuple,"(",MaxTextExtent);
7417  ConcatenateColorComponent(&pixel,RedChannel,X11Compliance,tuple);
7418  (void) ConcatenateMagickString(tuple,",",MaxTextExtent);
7419  ConcatenateColorComponent(&pixel,GreenChannel,X11Compliance,tuple);
7420  (void) ConcatenateMagickString(tuple,",",MaxTextExtent);
7421  ConcatenateColorComponent(&pixel,BlueChannel,X11Compliance,tuple);
7422  if (pixel.colorspace == CMYKColorspace)
7423  {
7424  (void) ConcatenateMagickString(tuple,",",MaxTextExtent);
7425  ConcatenateColorComponent(&pixel,IndexChannel,X11Compliance,tuple);
7426  }
7427  if (pixel.matte != MagickFalse)
7428  {
7429  (void) ConcatenateMagickString(tuple,",",MaxTextExtent);
7430  ConcatenateColorComponent(&pixel,OpacityChannel,X11Compliance,tuple);
7431  }
7432  (void) ConcatenateMagickString(tuple,")",MaxTextExtent);
7433  height=(unsigned int) windows->magnify.font_info->ascent+
7434  windows->magnify.font_info->descent;
7435  x=windows->magnify.font_info->max_bounds.width >> 1;
7436  y=windows->magnify.font_info->ascent+(height >> 2);
7437  (void) XDrawImageString(display,windows->magnify.pixmap,
7438  windows->magnify.annotate_context,x,y,tuple,(int) strlen(tuple));
7439  GetColorTuple(&pixel,MagickTrue,tuple);
7440  y+=height;
7441  (void) XDrawImageString(display,windows->magnify.pixmap,
7442  windows->magnify.annotate_context,x,y,tuple,(int) strlen(tuple));
7443  (void) QueryMagickColorname(windows->image.image,&pixel,SVGCompliance,tuple,
7444  &windows->image.image->exception);
7445  y+=height;
7446  (void) XDrawImageString(display,windows->magnify.pixmap,
7447  windows->magnify.annotate_context,x,y,tuple,(int) strlen(tuple));
7448  /*
7449  Refresh magnify window.
7450  */
7451  magnify_window=windows->magnify;
7452  magnify_window.x=0;
7453  magnify_window.y=0;
7454  XRefreshWindow(display,&magnify_window,(XEvent *) NULL);
7455 }
7456 ␌
7457 /*
7458 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
7459 % %
7460 % %
7461 % %
7462 % X M a k e P i x m a p %
7463 % %
7464 % %
7465 % %
7466 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
7467 %
7468 % XMakePixmap() creates an X11 pixmap.
7469 %
7470 % The format of the XMakePixmap method is:
7471 %
7472 % void XMakeStandardColormap(Display *display,XVisualInfo *visual_info,
7473 % XResourceInfo *resource_info,Image *image,XStandardColormap *map_info,
7474 % XPixelInfo *pixel)
7475 %
7476 % A description of each parameter follows:
7477 %
7478 % o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
7479 %
7480 % o display: Specifies a connection to an X server; returned from
7481 % XOpenDisplay.
7482 %
7483 % o window: Specifies a pointer to a XWindowInfo structure.
7484 %
7485 */
7486 static MagickBooleanType XMakePixmap(Display *display,
7487  const XResourceInfo *resource_info,XWindowInfo *window)
7488 {
7489  unsigned int
7490  height,
7491  width;
7492 
7493  assert(display != (Display *) NULL);
7494  assert(resource_info != (XResourceInfo *) NULL);
7495  assert(window != (XWindowInfo *) NULL);
7496  if (IsEventLogging() != MagickFalse)
7497  (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
7498  (void) resource_info;
7499  if (window->pixmap != (Pixmap) NULL)
7500  {
7501  /*
7502  Destroy previous X pixmap.
7503  */
7504  (void) XFreePixmap(display,window->pixmap);
7505  window->pixmap=(Pixmap) NULL;
7506  }
7507  if (window->use_pixmap == MagickFalse)
7508  return(MagickFalse);
7509  if (window->ximage == (XImage *) NULL)
7510  return(MagickFalse);
7511  /*
7512  Display busy cursor.
7513  */
7514  (void) XCheckDefineCursor(display,window->id,window->busy_cursor);
7515  (void) XFlush(display);
7516  /*
7517  Create pixmap.
7518  */
7519  width=(unsigned int) window->ximage->width;
7520  height=(unsigned int) window->ximage->height;
7521  window->pixmap=XCreatePixmap(display,window->id,width,height,window->depth);
7522  if (window->pixmap == (Pixmap) NULL)
7523  {
7524  /*
7525  Unable to allocate pixmap.
7526  */
7527  (void) XCheckDefineCursor(display,window->id,window->cursor);
7528  return(MagickFalse);
7529  }
7530  /*
7531  Copy X image to pixmap.
7532  */
7533 #if defined(MAGICKCORE_HAVE_SHARED_MEMORY)
7534  if (window->shared_memory)
7535  (void) XShmPutImage(display,window->pixmap,window->annotate_context,
7536  window->ximage,0,0,0,0,width,height,MagickTrue);
7537 #endif
7538  if (window->shared_memory == MagickFalse)
7539  (void) XPutImage(display,window->pixmap,window->annotate_context,
7540  window->ximage,0,0,0,0,width,height);
7541  if ((GetLogEventMask() & X11Event) != 0)
7542  {
7543  (void) LogMagickEvent(X11Event,GetMagickModule(),"Pixmap:");
7544  (void) LogMagickEvent(X11Event,GetMagickModule()," width, height: %ux%u",
7545  width,height);
7546  }
7547  /*
7548  Restore cursor.
7549  */
7550  (void) XCheckDefineCursor(display,window->id,window->cursor);
7551  return(MagickTrue);
7552 }
7553 ␌
7554 /*
7555 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
7556 % %
7557 % %
7558 % %
7559 % X M a k e S t a n d a r d C o l o r m a p %
7560 % %
7561 % %
7562 % %
7563 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
7564 %
7565 % XMakeStandardColormap() creates an X11 Standard Colormap.
7566 %
7567 % The format of the XMakeStandardColormap method is:
7568 %
7569 % XMakeStandardColormap(display,visual_info,resource_info,image,
7570 % map_info,pixel)
7571 %
7572 % A description of each parameter follows:
7573 %
7574 % o display: Specifies a connection to an X server; returned from
7575 % XOpenDisplay.
7576 %
7577 % o visual_info: Specifies a pointer to a X11 XVisualInfo structure;
7578 % returned from XGetVisualInfo.
7579 %
7580 % o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
7581 %
7582 % o image: the image.
7583 %
7584 % o map_info: If a Standard Colormap type is specified, this structure is
7585 % initialized with info from the Standard Colormap.
7586 %
7587 % o pixel: Specifies a pointer to a XPixelInfo structure.
7588 %
7589 */
7590 
7591 #if defined(__cplusplus) || defined(c_plusplus)
7592 extern "C" {
7593 #endif
7594 
7595 static inline MagickRealType DiversityPixelIntensity(
7596  const DiversityPacket *pixel)
7597 {
7598  MagickRealType
7599  intensity;
7600 
7601  intensity=0.298839*pixel->red+0.586811*pixel->green+0.114350*pixel->blue;
7602  return(intensity);
7603 }
7604 
7605 static int IntensityCompare(const void *x,const void *y)
7606 {
7607  DiversityPacket
7608  *color_1,
7609  *color_2;
7610 
7611  int
7612  diversity;
7613 
7614  color_1=(DiversityPacket *) x;
7615  color_2=(DiversityPacket *) y;
7616  diversity=(int) (DiversityPixelIntensity(color_2)-
7617  DiversityPixelIntensity(color_1));
7618  return(diversity);
7619 }
7620 
7621 static int PopularityCompare(const void *x,const void *y)
7622 {
7623  DiversityPacket
7624  *color_1,
7625  *color_2;
7626 
7627  color_1=(DiversityPacket *) x;
7628  color_2=(DiversityPacket *) y;
7629  return((int) color_2->count-(int) color_1->count);
7630 }
7631 
7632 #if defined(__cplusplus) || defined(c_plusplus)
7633 }
7634 #endif
7635 
7636 static inline Quantum ScaleXToQuantum(const size_t x,
7637  const size_t scale)
7638 {
7639  return((Quantum) (((MagickRealType) QuantumRange*x)/scale+0.5));
7640 }
7641 
7642 MagickExport void XMakeStandardColormap(Display *display,
7643  XVisualInfo *visual_info,XResourceInfo *resource_info,Image *image,
7644  XStandardColormap *map_info,XPixelInfo *pixel)
7645 {
7646  Colormap
7647  colormap;
7648 
7650  *exception;
7651 
7652  IndexPacket
7653  *indexes;
7654 
7655  ssize_t
7656  i;
7657 
7658  Status
7659  status;
7660 
7661  size_t
7662  number_colors,
7663  retain_colors;
7664 
7665  unsigned short
7666  gray_value;
7667 
7668  XColor
7669  color,
7670  *colors,
7671  *p;
7672 
7673  assert(display != (Display *) NULL);
7674  assert(visual_info != (XVisualInfo *) NULL);
7675  assert(map_info != (XStandardColormap *) NULL);
7676  assert(resource_info != (XResourceInfo *) NULL);
7677  assert(pixel != (XPixelInfo *) NULL);
7678  if (IsEventLogging() != MagickFalse)
7679  (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
7680  exception=(&image->exception);
7681  if (resource_info->map_type != (char *) NULL)
7682  {
7683  /*
7684  Standard Colormap is already defined (i.e. xstdcmap).
7685  */
7686  XGetPixelPacket(display,visual_info,map_info,resource_info,image,
7687  pixel);
7688  number_colors=(unsigned int) (map_info->base_pixel+
7689  (map_info->red_max+1)*(map_info->green_max+1)*(map_info->blue_max+1));
7690  if ((map_info->red_max*map_info->green_max*map_info->blue_max) != 0)
7691  if ((image->matte == MagickFalse) &&
7692  (resource_info->color_recovery == MagickFalse) &&
7693  resource_info->quantize_info->dither &&
7694  (number_colors < MaxColormapSize))
7695  {
7696  Image
7697  *affinity_image;
7698 
7699  PixelPacket
7700  *magick_restrict q;
7701 
7702  /*
7703  Improve image appearance with error diffusion.
7704  */
7705  affinity_image=AcquireImage((ImageInfo *) NULL);
7706  if (affinity_image == (Image *) NULL)
7707  ThrowXWindowFatalException(ResourceLimitFatalError,
7708  "UnableToDitherImage",image->filename);
7709  affinity_image->columns=number_colors;
7710  affinity_image->rows=1;
7711  /*
7712  Initialize colormap image.
7713  */
7714  q=QueueAuthenticPixels(affinity_image,0,0,affinity_image->columns,
7715  1,exception);
7716  if (q != (PixelPacket *) NULL)
7717  {
7718  for (i=0; i < (ssize_t) number_colors; i++)
7719  {
7720  SetPixelRed(q,0);
7721  if (map_info->red_max != 0)
7722  SetPixelRed(q,ScaleXToQuantum((size_t) (i/
7723  map_info->red_mult),map_info->red_max));
7724  SetPixelGreen(q,0);
7725  if (map_info->green_max != 0)
7726  SetPixelGreen(q,ScaleXToQuantum((size_t) ((i/
7727  map_info->green_mult) % (map_info->green_max+1)),
7728  map_info->green_max));
7729  SetPixelBlue(q,0);
7730  if (map_info->blue_max != 0)
7731  SetPixelBlue(q,ScaleXToQuantum((size_t) (i %
7732  map_info->green_mult),map_info->blue_max));
7733  SetPixelOpacity(q,TransparentOpacity);
7734  q++;
7735  }
7736  (void) SyncAuthenticPixels(affinity_image,exception);
7737  (void) RemapImage(resource_info->quantize_info,image,
7738  affinity_image);
7739  }
7740  XGetPixelPacket(display,visual_info,map_info,resource_info,image,
7741  pixel);
7742  (void) SetImageStorageClass(image,DirectClass);
7743  affinity_image=DestroyImage(affinity_image);
7744  }
7745  if ((GetLogEventMask() & X11Event) != 0)
7746  {
7747  (void) LogMagickEvent(X11Event,GetMagickModule(),
7748  "Standard Colormap:");
7749  (void) LogMagickEvent(X11Event,GetMagickModule(),
7750  " colormap id: 0x%lx",map_info->colormap);
7751  (void) LogMagickEvent(X11Event,GetMagickModule(),
7752  " red, green, blue max: %lu %lu %lu",map_info->red_max,
7753  map_info->green_max,map_info->blue_max);
7754  (void) LogMagickEvent(X11Event,GetMagickModule(),
7755  " red, green, blue mult: %lu %lu %lu",map_info->red_mult,
7756  map_info->green_mult,map_info->blue_mult);
7757  }
7758  return;
7759  }
7760  if ((visual_info->klass != DirectColor) &&
7761  (visual_info->klass != TrueColor))
7762  if ((image->storage_class == DirectClass) ||
7763  ((int) image->colors > visual_info->colormap_size))
7764  {
7765  QuantizeInfo
7766  quantize_info;
7767 
7768  /*
7769  Image has more colors than the visual supports.
7770  */
7771  quantize_info=(*resource_info->quantize_info);
7772  quantize_info.number_colors=(size_t) visual_info->colormap_size;
7773  (void) QuantizeImage(&quantize_info,image);
7774  }
7775  /*
7776  Free previous and create new colormap.
7777  */
7778  (void) XFreeStandardColormap(display,visual_info,map_info,pixel);
7779  colormap=XDefaultColormap(display,visual_info->screen);
7780  if (visual_info->visual != XDefaultVisual(display,visual_info->screen))
7781  colormap=XCreateColormap(display,XRootWindow(display,visual_info->screen),
7782  visual_info->visual,visual_info->klass == DirectColor ?
7783  AllocAll : AllocNone);
7784  if (colormap == (Colormap) NULL)
7785  ThrowXWindowFatalException(ResourceLimitFatalError,"UnableToCreateColormap",
7786  image->filename);
7787  /*
7788  Initialize the map and pixel info structures.
7789  */
7790  XGetMapInfo(visual_info,colormap,map_info);
7791  XGetPixelPacket(display,visual_info,map_info,resource_info,image,pixel);
7792  /*
7793  Allocating colors in server colormap is based on visual class.
7794  */
7795  switch (visual_info->klass)
7796  {
7797  case StaticGray:
7798  case StaticColor:
7799  {
7800  /*
7801  Define Standard Colormap for StaticGray or StaticColor visual.
7802  */
7803  number_colors=image->colors;
7804  colors=(XColor *) AcquireQuantumMemory((size_t)
7805  visual_info->colormap_size,sizeof(*colors));
7806  if (colors == (XColor *) NULL)
7807  ThrowXWindowFatalException(ResourceLimitFatalError,
7808  "UnableToCreateColormap",image->filename);
7809  p=colors;
7810  color.flags=(char) (DoRed | DoGreen | DoBlue);
7811  for (i=0; i < (ssize_t) image->colors; i++)
7812  {
7813  color.red=ScaleQuantumToShort(XRedGamma(image->colormap[i].red));
7814  color.green=ScaleQuantumToShort(XGreenGamma(image->colormap[i].green));
7815  color.blue=ScaleQuantumToShort(XBlueGamma(image->colormap[i].blue));
7816  if (visual_info->klass != StaticColor)
7817  {
7818  gray_value=(unsigned short) XPixelIntensity(&color);
7819  color.red=gray_value;
7820  color.green=gray_value;
7821  color.blue=gray_value;
7822  }
7823  status=XAllocColor(display,colormap,&color);
7824  if (status == False)
7825  {
7826  colormap=XCopyColormapAndFree(display,colormap);
7827  (void) XAllocColor(display,colormap,&color);
7828  }
7829  pixel->pixels[i]=color.pixel;
7830  *p++=color;
7831  }
7832  break;
7833  }
7834  case GrayScale:
7835  case PseudoColor:
7836  {
7837  unsigned int
7838  colormap_type;
7839 
7840  /*
7841  Define Standard Colormap for GrayScale or PseudoColor visual.
7842  */
7843  number_colors=image->colors;
7844  colors=(XColor *) AcquireQuantumMemory((size_t)
7845  visual_info->colormap_size,sizeof(*colors));
7846  if (colors == (XColor *) NULL)
7847  ThrowXWindowFatalException(ResourceLimitFatalError,
7848  "UnableToCreateColormap",image->filename);
7849  /*
7850  Preallocate our GUI colors.
7851  */
7852  (void) XAllocColor(display,colormap,&pixel->foreground_color);
7853  (void) XAllocColor(display,colormap,&pixel->background_color);
7854  (void) XAllocColor(display,colormap,&pixel->border_color);
7855  (void) XAllocColor(display,colormap,&pixel->matte_color);
7856  (void) XAllocColor(display,colormap,&pixel->highlight_color);
7857  (void) XAllocColor(display,colormap,&pixel->shadow_color);
7858  (void) XAllocColor(display,colormap,&pixel->depth_color);
7859  (void) XAllocColor(display,colormap,&pixel->trough_color);
7860  for (i=0; i < MaxNumberPens; i++)
7861  (void) XAllocColor(display,colormap,&pixel->pen_colors[i]);
7862  /*
7863  Determine if image colors will "fit" into X server colormap.
7864  */
7865  colormap_type=resource_info->colormap;
7866  status=XAllocColorCells(display,colormap,MagickFalse,(unsigned long *)
7867  NULL,0,pixel->pixels,(unsigned int) image->colors);
7868  if (status != False)
7869  colormap_type=PrivateColormap;
7870  if (colormap_type == SharedColormap)
7871  {
7872  CacheView
7873  *image_view;
7874 
7875  DiversityPacket
7876  *diversity;
7877 
7878  int
7879  y;
7880 
7881  int
7882  x;
7883 
7884  unsigned short
7885  index;
7886 
7887  XColor
7888  *server_colors;
7889 
7890  /*
7891  Define Standard colormap for shared GrayScale or PseudoColor visual.
7892  */
7893  diversity=(DiversityPacket *) AcquireQuantumMemory(image->colors,
7894  sizeof(*diversity));
7895  if (diversity == (DiversityPacket *) NULL)
7896  ThrowXWindowFatalException(ResourceLimitFatalError,
7897  "UnableToCreateColormap",image->filename);
7898  for (i=0; i < (ssize_t) image->colors; i++)
7899  {
7900  diversity[i].red=image->colormap[i].red;
7901  diversity[i].green=image->colormap[i].green;
7902  diversity[i].blue=image->colormap[i].blue;
7903  diversity[i].index=(unsigned short) i;
7904  diversity[i].count=0;
7905  }
7906  image_view=AcquireAuthenticCacheView(image,exception);
7907  for (y=0; y < (int) image->rows; y++)
7908  {
7909  int
7910  x;
7911 
7912  const PixelPacket
7913  *magick_restrict p;
7914 
7915  p=GetCacheViewAuthenticPixels(image_view,0,(ssize_t) y,
7916  image->columns,1,exception);
7917  if (p == (const PixelPacket *) NULL)
7918  break;
7919  indexes=GetCacheViewAuthenticIndexQueue(image_view);
7920  for (x=(int) image->columns-1; x >= 0; x--)
7921  diversity[(ssize_t) GetPixelIndex(indexes+x)].count++;
7922  }
7923  image_view=DestroyCacheView(image_view);
7924  /*
7925  Sort colors by decreasing intensity.
7926  */
7927  qsort((void *) diversity,image->colors,sizeof(*diversity),
7928  IntensityCompare);
7929  for (i=0; i < (ssize_t) image->colors; )
7930  {
7931  diversity[i].count<<=4; /* increase this colors popularity */
7932  i+=MagickMax((int) (image->colors >> 4),2);
7933  }
7934  diversity[image->colors-1].count<<=4;
7935  qsort((void *) diversity,image->colors,sizeof(*diversity),
7936  PopularityCompare);
7937  /*
7938  Allocate colors.
7939  */
7940  p=colors;
7941  color.flags=(char) (DoRed | DoGreen | DoBlue);
7942  for (i=0; i < (ssize_t) image->colors; i++)
7943  {
7944  index=diversity[i].index;
7945  color.red=
7946  ScaleQuantumToShort(XRedGamma(image->colormap[index].red));
7947  color.green=
7948  ScaleQuantumToShort(XGreenGamma(image->colormap[index].green));
7949  color.blue=
7950  ScaleQuantumToShort(XBlueGamma(image->colormap[index].blue));
7951  if (visual_info->klass != PseudoColor)
7952  {
7953  gray_value=(unsigned short) XPixelIntensity(&color);
7954  color.red=gray_value;
7955  color.green=gray_value;
7956  color.blue=gray_value;
7957  }
7958  status=XAllocColor(display,colormap,&color);
7959  if (status == False)
7960  break;
7961  pixel->pixels[index]=color.pixel;
7962  *p++=color;
7963  }
7964  /*
7965  Read X server colormap.
7966  */
7967  server_colors=(XColor *) AcquireQuantumMemory((size_t)
7968  visual_info->colormap_size,sizeof(*server_colors));
7969  if (server_colors == (XColor *) NULL)
7970  ThrowXWindowFatalException(ResourceLimitFatalError,
7971  "UnableToCreateColormap",image->filename);
7972  for (x=visual_info->colormap_size-1; x >= 0; x--)
7973  server_colors[x].pixel=(size_t) x;
7974  (void) XQueryColors(display,colormap,server_colors,
7975  (int) MagickMin((unsigned int) visual_info->colormap_size,256));
7976  /*
7977  Select remaining colors from X server colormap.
7978  */
7979  for (; i < (ssize_t) image->colors; i++)
7980  {
7981  index=diversity[i].index;
7982  color.red=
7983  ScaleQuantumToShort(XRedGamma(image->colormap[index].red));
7984  color.green=
7985  ScaleQuantumToShort(XGreenGamma(image->colormap[index].green));
7986  color.blue=
7987  ScaleQuantumToShort(XBlueGamma(image->colormap[index].blue));
7988  if (visual_info->klass != PseudoColor)
7989  {
7990  gray_value=(unsigned short) XPixelIntensity(&color);
7991  color.red=gray_value;
7992  color.green=gray_value;
7993  color.blue=gray_value;
7994  }
7995  XBestPixel(display,colormap,server_colors,(unsigned int)
7996  visual_info->colormap_size,&color);
7997  pixel->pixels[index]=color.pixel;
7998  *p++=color;
7999  }
8000  if ((int) image->colors < visual_info->colormap_size)
8001  {
8002  /*
8003  Fill up colors array-- more choices for pen colors.
8004  */
8005  retain_colors=MagickMin((unsigned int)
8006  (visual_info->colormap_size-image->colors),256);
8007  for (i=0; i < (ssize_t) retain_colors; i++)
8008  *p++=server_colors[i];
8009  number_colors+=retain_colors;
8010  }
8011  server_colors=(XColor *) RelinquishMagickMemory(server_colors);
8012  diversity=(DiversityPacket *) RelinquishMagickMemory(diversity);
8013  break;
8014  }
8015  /*
8016  Define Standard colormap for private GrayScale or PseudoColor visual.
8017  */
8018  if (status == False)
8019  {
8020  /*
8021  Not enough colormap entries in the colormap-- Create a new colormap.
8022  */
8023  colormap=XCreateColormap(display,
8024  XRootWindow(display,visual_info->screen),visual_info->visual,
8025  AllocNone);
8026  if (colormap == (Colormap) NULL)
8027  ThrowXWindowFatalException(ResourceLimitFatalError,
8028  "UnableToCreateColormap",image->filename);
8029  map_info->colormap=colormap;
8030  if ((int) image->colors < visual_info->colormap_size)
8031  {
8032  /*
8033  Retain colors from the default colormap to help lessens the
8034  effects of colormap flashing.
8035  */
8036  retain_colors=MagickMin((unsigned int)
8037  (visual_info->colormap_size-image->colors),256);
8038  p=colors+image->colors;
8039  for (i=0; i < (ssize_t) retain_colors; i++)
8040  {
8041  p->pixel=(unsigned long) i;
8042  p++;
8043  }
8044  (void) XQueryColors(display,
8045  XDefaultColormap(display,visual_info->screen),
8046  colors+image->colors,(int) retain_colors);
8047  /*
8048  Transfer colors from default to private colormap.
8049  */
8050  (void) XAllocColorCells(display,colormap,MagickFalse,
8051  (unsigned long *) NULL,0,pixel->pixels,(unsigned int)
8052  retain_colors);
8053  p=colors+image->colors;
8054  for (i=0; i < (ssize_t) retain_colors; i++)
8055  {
8056  p->pixel=pixel->pixels[i];
8057  p++;
8058  }
8059  (void) XStoreColors(display,colormap,colors+image->colors,
8060  (int) retain_colors);
8061  number_colors+=retain_colors;
8062  }
8063  (void) XAllocColorCells(display,colormap,MagickFalse,
8064  (unsigned long *) NULL,0,pixel->pixels,(unsigned int)
8065  image->colors);
8066  }
8067  /*
8068  Store the image colormap.
8069  */
8070  p=colors;
8071  color.flags=(char) (DoRed | DoGreen | DoBlue);
8072  for (i=0; i < (ssize_t) image->colors; i++)
8073  {
8074  color.red=ScaleQuantumToShort(XRedGamma(image->colormap[i].red));
8075  color.green=ScaleQuantumToShort(XGreenGamma(image->colormap[i].green));
8076  color.blue=ScaleQuantumToShort(XBlueGamma(image->colormap[i].blue));
8077  if (visual_info->klass != PseudoColor)
8078  {
8079  gray_value=(unsigned short) XPixelIntensity(&color);
8080  color.red=gray_value;
8081  color.green=gray_value;
8082  color.blue=gray_value;
8083  }
8084  color.pixel=pixel->pixels[i];
8085  *p++=color;
8086  }
8087  (void) XStoreColors(display,colormap,colors,(int) image->colors);
8088  break;
8089  }
8090  case TrueColor:
8091  case DirectColor:
8092  default:
8093  {
8094  MagickBooleanType
8095  linear_colormap;
8096 
8097  /*
8098  Define Standard Colormap for TrueColor or DirectColor visual.
8099  */
8100  number_colors=(unsigned int) ((map_info->red_max*map_info->red_mult)+
8101  (map_info->green_max*map_info->green_mult)+
8102  (map_info->blue_max*map_info->blue_mult)+1);
8103  linear_colormap=(number_colors > 4096) ||
8104  (((int) (map_info->red_max+1) == visual_info->colormap_size) &&
8105  ((int) (map_info->green_max+1) == visual_info->colormap_size) &&
8106  ((int) (map_info->blue_max+1) == visual_info->colormap_size)) ?
8107  MagickTrue : MagickFalse;
8108  if (linear_colormap != MagickFalse)
8109  number_colors=(size_t) visual_info->colormap_size;
8110  /*
8111  Allocate color array.
8112  */
8113  colors=(XColor *) AcquireQuantumMemory(number_colors,sizeof(*colors));
8114  if (colors == (XColor *) NULL)
8115  ThrowXWindowFatalException(ResourceLimitFatalError,
8116  "UnableToCreateColormap",image->filename);
8117  /*
8118  Initialize linear color ramp.
8119  */
8120  p=colors;
8121  color.flags=(char) (DoRed | DoGreen | DoBlue);
8122  if (linear_colormap != MagickFalse)
8123  for (i=0; i < (ssize_t) number_colors; i++)
8124  {
8125  color.blue=(unsigned short) 0;
8126  if (map_info->blue_max != 0)
8127  color.blue=(unsigned short) ((size_t)
8128  ((65535L*(i % map_info->green_mult))/map_info->blue_max));
8129  color.green=color.blue;
8130  color.red=color.blue;
8131  color.pixel=XStandardPixel(map_info,&color);
8132  *p++=color;
8133  }
8134  else
8135  for (i=0; i < (ssize_t) number_colors; i++)
8136  {
8137  color.red=(unsigned short) 0;
8138  if (map_info->red_max != 0)
8139  color.red=(unsigned short) ((size_t)
8140  ((65535L*(i/map_info->red_mult))/map_info->red_max));
8141  color.green=(unsigned int) 0;
8142  if (map_info->green_max != 0)
8143  color.green=(unsigned short) ((size_t)
8144  ((65535L*((i/map_info->green_mult) % (map_info->green_max+1)))/
8145  map_info->green_max));
8146  color.blue=(unsigned short) 0;
8147  if (map_info->blue_max != 0)
8148  color.blue=(unsigned short) ((size_t)
8149  ((65535L*(i % map_info->green_mult))/map_info->blue_max));
8150  color.pixel=XStandardPixel(map_info,&color);
8151  *p++=color;
8152  }
8153  if ((visual_info->klass == DirectColor) &&
8154  (colormap != XDefaultColormap(display,visual_info->screen)))
8155  (void) XStoreColors(display,colormap,colors,(int) number_colors);
8156  else
8157  for (i=0; i < (ssize_t) number_colors; i++)
8158  (void) XAllocColor(display,colormap,&colors[i]);
8159  break;
8160  }
8161  }
8162  if ((visual_info->klass != DirectColor) &&
8163  (visual_info->klass != TrueColor))
8164  {
8165  /*
8166  Set foreground, background, border, etc. pixels.
8167  */
8168  XBestPixel(display,colormap,colors,(unsigned int) number_colors,
8169  &pixel->foreground_color);
8170  XBestPixel(display,colormap,colors,(unsigned int) number_colors,
8171  &pixel->background_color);
8172  if (pixel->background_color.pixel == pixel->foreground_color.pixel)
8173  {
8174  /*
8175  Foreground and background colors must differ.
8176  */
8177  pixel->background_color.red=(~pixel->foreground_color.red);
8178  pixel->background_color.green=
8179  (~pixel->foreground_color.green);
8180  pixel->background_color.blue=
8181  (~pixel->foreground_color.blue);
8182  XBestPixel(display,colormap,colors,(unsigned int) number_colors,
8183  &pixel->background_color);
8184  }
8185  XBestPixel(display,colormap,colors,(unsigned int) number_colors,
8186  &pixel->border_color);
8187  XBestPixel(display,colormap,colors,(unsigned int) number_colors,
8188  &pixel->matte_color);
8189  XBestPixel(display,colormap,colors,(unsigned int) number_colors,
8190  &pixel->highlight_color);
8191  XBestPixel(display,colormap,colors,(unsigned int) number_colors,
8192  &pixel->shadow_color);
8193  XBestPixel(display,colormap,colors,(unsigned int) number_colors,
8194  &pixel->depth_color);
8195  XBestPixel(display,colormap,colors,(unsigned int) number_colors,
8196  &pixel->trough_color);
8197  for (i=0; i < MaxNumberPens; i++)
8198  {
8199  XBestPixel(display,colormap,colors,(unsigned int) number_colors,
8200  &pixel->pen_colors[i]);
8201  pixel->pixels[image->colors+i]=pixel->pen_colors[i].pixel;
8202  }
8203  pixel->colors=(ssize_t) (image->colors+MaxNumberPens);
8204  }
8205  colors=(XColor *) RelinquishMagickMemory(colors);
8206  if ((GetLogEventMask() & X11Event) != 0)
8207  {
8208  (void) LogMagickEvent(X11Event,GetMagickModule(),"Standard Colormap:");
8209  (void) LogMagickEvent(X11Event,GetMagickModule()," colormap id: 0x%lx",
8210  map_info->colormap);
8211  (void) LogMagickEvent(X11Event,GetMagickModule(),
8212  " red, green, blue max: %lu %lu %lu",map_info->red_max,
8213  map_info->green_max,map_info->blue_max);
8214  (void) LogMagickEvent(X11Event,GetMagickModule(),
8215  " red, green, blue mult: %lu %lu %lu",map_info->red_mult,
8216  map_info->green_mult,map_info->blue_mult);
8217  }
8218 }
8219 ␌
8220 /*
8221 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8222 % %
8223 % %
8224 % %
8225 % X M a k e W i n d o w %
8226 % %
8227 % %
8228 % %
8229 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8230 %
8231 % XMakeWindow() creates an X11 window.
8232 %
8233 % The format of the XMakeWindow method is:
8234 %
8235 % void XMakeWindow(Display *display,Window parent,char **argv,int argc,
8236 % XClassHint *class_hint,XWMHints *manager_hints,
8237 % XWindowInfo *window_info)
8238 %
8239 % A description of each parameter follows:
8240 %
8241 % o display: Specifies a connection to an X server; returned from
8242 % XOpenDisplay.
8243 %
8244 % o parent: Specifies the parent window_info.
8245 %
8246 % o argv: Specifies the application's argument list.
8247 %
8248 % o argc: Specifies the number of arguments.
8249 %
8250 % o class_hint: Specifies a pointer to a X11 XClassHint structure.
8251 %
8252 % o manager_hints: Specifies a pointer to a X11 XWMHints structure.
8253 %
8254 % o window_info: Specifies a pointer to a X11 XWindowInfo structure.
8255 %
8256 */
8257 MagickExport void XMakeWindow(Display *display,Window parent,char **argv,
8258  int argc,XClassHint *class_hint,XWMHints *manager_hints,
8259  XWindowInfo *window_info)
8260 {
8261 #define MinWindowSize 64
8262 
8263  Atom
8264  atom_list[2];
8265 
8266  int
8267  gravity;
8268 
8269  static XTextProperty
8270  icon_name,
8271  window_name;
8272 
8273  Status
8274  status;
8275 
8276  XSizeHints
8277  *size_hints;
8278 
8279  /*
8280  Set window info hints.
8281  */
8282  assert(display != (Display *) NULL);
8283  assert(window_info != (XWindowInfo *) NULL);
8284  if (IsEventLogging() != MagickFalse)
8285  (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
8286  size_hints=XAllocSizeHints();
8287  if (size_hints == (XSizeHints *) NULL)
8288  ThrowXWindowFatalException(XServerFatalError,"UnableToMakeXWindow",argv[0]);
8289  size_hints->flags=(int) window_info->flags;
8290  size_hints->x=window_info->x;
8291  size_hints->y=window_info->y;
8292  size_hints->width=(int) window_info->width;
8293  size_hints->height=(int) window_info->height;
8294  if (window_info->immutable != MagickFalse)
8295  {
8296  /*
8297  Window size cannot be changed.
8298  */
8299  size_hints->min_width=size_hints->width;
8300  size_hints->min_height=size_hints->height;
8301  size_hints->max_width=size_hints->width;
8302  size_hints->max_height=size_hints->height;
8303  size_hints->flags|=PMinSize;
8304  size_hints->flags|=PMaxSize;
8305  }
8306  else
8307  {
8308  /*
8309  Window size can be changed.
8310  */
8311  size_hints->min_width=(int) window_info->min_width;
8312  size_hints->min_height=(int) window_info->min_height;
8313  size_hints->flags|=PResizeInc;
8314  size_hints->width_inc=(int) window_info->width_inc;
8315  size_hints->height_inc=(int) window_info->height_inc;
8316 #if !defined(PRE_R4_ICCCM)
8317  size_hints->flags|=PBaseSize;
8318  size_hints->base_width=size_hints->width_inc;
8319  size_hints->base_height=size_hints->height_inc;
8320 #endif
8321  }
8322  gravity=NorthWestGravity;
8323  if (window_info->geometry != (char *) NULL)
8324  {
8325  char
8326  default_geometry[MaxTextExtent],
8327  geometry[MaxTextExtent];
8328 
8329  int
8330  flags;
8331 
8332  char
8333  *p;
8334 
8335  /*
8336  User specified geometry.
8337  */
8338  (void) FormatLocaleString(default_geometry,MaxTextExtent,"%dx%d",
8339  size_hints->width,size_hints->height);
8340  (void) CopyMagickString(geometry,window_info->geometry,MaxTextExtent);
8341  p=geometry;
8342  while (strlen(p) != 0)
8343  {
8344  if ((isspace((int) ((unsigned char) *p)) == 0) && (*p != '%'))
8345  p++;
8346  else
8347  (void) memmove(p,p+1,MaxTextExtent-(p-geometry));
8348  }
8349  flags=XWMGeometry(display,window_info->screen,geometry,default_geometry,
8350  window_info->border_width,size_hints,&size_hints->x,&size_hints->y,
8351  &size_hints->width,&size_hints->height,&gravity);
8352  if ((flags & WidthValue) && (flags & HeightValue))
8353  size_hints->flags|=USSize;
8354  if ((flags & XValue) && (flags & YValue))
8355  {
8356  size_hints->flags|=USPosition;
8357  window_info->x=size_hints->x;
8358  window_info->y=size_hints->y;
8359  }
8360  }
8361 #if !defined(PRE_R4_ICCCM)
8362  size_hints->win_gravity=gravity;
8363  size_hints->flags|=PWinGravity;
8364 #endif
8365  if (window_info->id == (Window) NULL)
8366  window_info->id=XCreateWindow(display,parent,window_info->x,window_info->y,
8367  (unsigned int) size_hints->width,(unsigned int) size_hints->height,
8368  window_info->border_width,(int) window_info->depth,InputOutput,
8369  window_info->visual,(unsigned long) window_info->mask,
8370  &window_info->attributes);
8371  else
8372  {
8373  MagickStatusType
8374  mask;
8375 
8376  XEvent
8377  sans_event;
8378 
8379  XWindowChanges
8380  window_changes;
8381 
8382  /*
8383  Window already exists; change relevant attributes.
8384  */
8385  (void) XChangeWindowAttributes(display,window_info->id,(unsigned long)
8386  window_info->mask,&window_info->attributes);
8387  mask=ConfigureNotify;
8388  while (XCheckTypedWindowEvent(display,window_info->id,(int) mask,&sans_event)) ;
8389  window_changes.x=window_info->x;
8390  window_changes.y=window_info->y;
8391  window_changes.width=(int) window_info->width;
8392  window_changes.height=(int) window_info->height;
8393  mask=(MagickStatusType) (CWWidth | CWHeight);
8394  if (window_info->flags & USPosition)
8395  mask|=CWX | CWY;
8396  (void) XReconfigureWMWindow(display,window_info->id,window_info->screen,
8397  mask,&window_changes);
8398  }
8399  if (window_info->id == (Window) NULL)
8400  ThrowXWindowFatalException(XServerFatalError,"UnableToCreateWindow",
8401  window_info->name);
8402  status=XStringListToTextProperty(&window_info->name,1,&window_name);
8403  if (status == False)
8404  ThrowXWindowFatalException(XServerFatalError,"UnableToCreateTextProperty",
8405  window_info->name);
8406  status=XStringListToTextProperty(&window_info->icon_name,1,&icon_name);
8407  if (status == False)
8408  ThrowXWindowFatalException(XServerFatalError,"UnableToCreateTextProperty",
8409  window_info->icon_name);
8410  if (window_info->icon_geometry != (char *) NULL)
8411  {
8412  int
8413  flags,
8414  height,
8415  width;
8416 
8417  /*
8418  User specified icon geometry.
8419  */
8420  size_hints->flags|=USPosition;
8421  flags=XWMGeometry(display,window_info->screen,window_info->icon_geometry,
8422  (char *) NULL,0,size_hints,&manager_hints->icon_x,
8423  &manager_hints->icon_y,&width,&height,&gravity);
8424  if ((flags & XValue) && (flags & YValue))
8425  manager_hints->flags|=IconPositionHint;
8426  }
8427  XSetWMProperties(display,window_info->id,&window_name,&icon_name,argv,argc,
8428  size_hints,manager_hints,class_hint);
8429  if (window_name.value != (void *) NULL)
8430  {
8431  (void) XFree((void *) window_name.value);
8432  window_name.value=(unsigned char *) NULL;
8433  window_name.nitems=0;
8434  }
8435  if (icon_name.value != (void *) NULL)
8436  {
8437  (void) XFree((void *) icon_name.value);
8438  icon_name.value=(unsigned char *) NULL;
8439  icon_name.nitems=0;
8440  }
8441  atom_list[0]=XInternAtom(display,"WM_DELETE_WINDOW",MagickFalse);
8442  atom_list[1]=XInternAtom(display,"WM_TAKE_FOCUS",MagickFalse);
8443  (void) XSetWMProtocols(display,window_info->id,atom_list,2);
8444  (void) XFree((void *) size_hints);
8445  if (window_info->shape != MagickFalse)
8446  {
8447 #if defined(MAGICKCORE_HAVE_SHAPE)
8448  int
8449  error_base,
8450  event_base;
8451 
8452  /*
8453  Can we apply a non-rectangular shaping mask?
8454  */
8455  error_base=0;
8456  event_base=0;
8457  if (XShapeQueryExtension(display,&error_base,&event_base) == 0)
8458  window_info->shape=MagickFalse;
8459 #else
8460  window_info->shape=MagickFalse;
8461 #endif
8462  }
8463  window_info->shape=MagickFalse; /* Fedora 30 has a broken shape extension */
8464  if (window_info->shared_memory != MagickFalse)
8465  {
8466 #if defined(MAGICKCORE_HAVE_SHARED_MEMORY)
8467  /*
8468  Can we use shared memory with this window?
8469  */
8470  if (XShmQueryExtension(display) == 0)
8471  window_info->shared_memory=MagickFalse;
8472 #else
8473  window_info->shared_memory=MagickFalse;
8474 #endif
8475  }
8476  window_info->image=NewImageList();
8477  window_info->destroy=MagickFalse;
8478 }
8479 ␌
8480 /*
8481 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8482 % %
8483 % %
8484 % %
8485 % X M a g i c k P r o g r e s s M o n i t o r %
8486 % %
8487 % %
8488 % %
8489 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8490 %
8491 % XMagickProgressMonitor() displays the progress a task is making in
8492 % completing a task.
8493 %
8494 % The format of the XMagickProgressMonitor method is:
8495 %
8496 % void XMagickProgressMonitor(const char *task,
8497 % const MagickOffsetType quantum,const MagickSizeType span,
8498 % void *client_data)
8499 %
8500 % A description of each parameter follows:
8501 %
8502 % o task: Identifies the task in progress.
8503 %
8504 % o quantum: Specifies the quantum position within the span which represents
8505 % how much progress has been made in completing a task.
8506 %
8507 % o span: Specifies the span relative to completing a task.
8508 %
8509 % o client_data: Pointer to any client data.
8510 %
8511 */
8512 
8513 static const char *GetLocaleMonitorMessage(const char *text)
8514 {
8515  char
8516  message[MaxTextExtent],
8517  tag[MaxTextExtent];
8518 
8519  const char
8520  *locale_message;
8521 
8522  char
8523  *p;
8524 
8525  (void) CopyMagickString(tag,text,MaxTextExtent);
8526  p=strrchr(tag,'/');
8527  if (p != (char *) NULL)
8528  *p='\0';
8529  (void) FormatLocaleString(message,MaxTextExtent,"Monitor/%s",tag);
8530  locale_message=GetLocaleMessage(message);
8531  if (locale_message == message)
8532  return(text);
8533  return(locale_message);
8534 }
8535 
8536 MagickExport MagickBooleanType XMagickProgressMonitor(const char *tag,
8537  const MagickOffsetType quantum,const MagickSizeType span,
8538  void *magick_unused(client_data))
8539 {
8540  XWindows
8541  *windows;
8542 
8543  magick_unreferenced(client_data);
8544 
8545  windows=XSetWindows((XWindows *) ~0);
8546  if (windows == (XWindows *) NULL)
8547  return(MagickTrue);
8548  if (windows->info.mapped != MagickFalse)
8549  XProgressMonitorWidget(windows->display,windows,
8550  GetLocaleMonitorMessage(tag),quantum,span);
8551  return(MagickTrue);
8552 }
8553 ␌
8554 /*
8555 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8556 % %
8557 % %
8558 % %
8559 % X Q u e r y C o l o r D a t a b a s e %
8560 % %
8561 % %
8562 % %
8563 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8564 %
8565 % XQueryColorDatabase() looks up a RGB values for a color given in the target
8566 % string.
8567 %
8568 % The format of the XQueryColorDatabase method is:
8569 %
8570 % MagickBooleanType XQueryColorDatabase(const char *target,XColor *color)
8571 %
8572 % A description of each parameter follows:
8573 %
8574 % o target: Specifies the color to lookup in the X color database.
8575 %
8576 % o color: A pointer to an PixelPacket structure. The RGB value of the target
8577 % color is returned as this value.
8578 %
8579 */
8580 MagickExport MagickBooleanType XQueryColorDatabase(const char *target,
8581  XColor *color)
8582 {
8583  Colormap
8584  colormap;
8585 
8586  static Display
8587  *display = (Display *) NULL;
8588 
8589  Status
8590  status;
8591 
8592  XColor
8593  xcolor;
8594 
8595  /*
8596  Initialize color return value.
8597  */
8598  assert(color != (XColor *) NULL);
8599  color->red=0;
8600  color->green=0;
8601  color->blue=0;
8602  color->flags=(char) (DoRed | DoGreen | DoBlue);
8603  if ((target == (char *) NULL) || (*target == '\0'))
8604  target="#ffffffffffff";
8605  /*
8606  Let the X server define the color for us.
8607  */
8608  if (display == (Display *) NULL)
8609  display=XOpenDisplay((char *) NULL);
8610  if (display == (Display *) NULL)
8611  ThrowXWindowFatalException(XServerError,"ColorIsNotKnownToServer",target);
8612  colormap=XDefaultColormap(display,XDefaultScreen(display));
8613  status=XParseColor(display,colormap,(char *) target,&xcolor);
8614  if (status == False)
8615  ThrowXWindowException(XServerError,"ColorIsNotKnownToServer",target)
8616  else
8617  {
8618  color->red=xcolor.red;
8619  color->green=xcolor.green;
8620  color->blue=xcolor.blue;
8621  color->flags=xcolor.flags;
8622  }
8623  return(status != False ? MagickTrue : MagickFalse);
8624 }
8625 ␌
8626 /*
8627 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8628 % %
8629 % %
8630 % %
8631 % X Q u e r y P o s i t i o n %
8632 % %
8633 % %
8634 % %
8635 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8636 %
8637 % XQueryPosition() gets the pointer coordinates relative to a window.
8638 %
8639 % The format of the XQueryPosition method is:
8640 %
8641 % void XQueryPosition(Display *display,const Window window,int *x,int *y)
8642 %
8643 % A description of each parameter follows:
8644 %
8645 % o display: Specifies a connection to an X server; returned from
8646 % XOpenDisplay.
8647 %
8648 % o window: Specifies a pointer to a Window.
8649 %
8650 % o x: Return the x coordinate of the pointer relative to the origin of the
8651 % window.
8652 %
8653 % o y: Return the y coordinate of the pointer relative to the origin of the
8654 % window.
8655 %
8656 */
8657 MagickExport void XQueryPosition(Display *display,const Window window,int *x,int *y)
8658 {
8659  int
8660  x_root,
8661  y_root;
8662 
8663  unsigned int
8664  mask;
8665 
8666  Window
8667  root_window;
8668 
8669  assert(display != (Display *) NULL);
8670  assert(window != (Window) NULL);
8671  assert(x != (int *) NULL);
8672  assert(y != (int *) NULL);
8673  if (IsEventLogging() != MagickFalse)
8674  (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
8675  (void) XQueryPointer(display,window,&root_window,&root_window,&x_root,&y_root,
8676  x,y,&mask);
8677 }
8678 ␌
8679 /*
8680 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8681 % %
8682 % %
8683 % %
8684 % X R e f r e s h W i n d o w %
8685 % %
8686 % %
8687 % %
8688 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8689 %
8690 % XRefreshWindow() refreshes an image in a X window.
8691 %
8692 % The format of the XRefreshWindow method is:
8693 %
8694 % void XRefreshWindow(Display *display,const XWindowInfo *window,
8695 % const XEvent *event)
8696 %
8697 % A description of each parameter follows:
8698 %
8699 % o display: Specifies a connection to an X server; returned from
8700 % XOpenDisplay.
8701 %
8702 % o window: Specifies a pointer to a XWindowInfo structure.
8703 %
8704 % o event: Specifies a pointer to a XEvent structure. If it is NULL,
8705 % the entire image is refreshed.
8706 %
8707 */
8708 MagickExport void XRefreshWindow(Display *display,const XWindowInfo *window,
8709  const XEvent *event)
8710 {
8711  int
8712  x,
8713  y;
8714 
8715  unsigned int
8716  height,
8717  width;
8718 
8719  assert(display != (Display *) NULL);
8720  assert(window != (XWindowInfo *) NULL);
8721  if (IsEventLogging() != MagickFalse)
8722  (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
8723  if (window->ximage == (XImage *) NULL)
8724  return;
8725  if (event != (XEvent *) NULL)
8726  {
8727  /*
8728  Determine geometry from expose event.
8729  */
8730  x=event->xexpose.x;
8731  y=event->xexpose.y;
8732  width=(unsigned int) event->xexpose.width;
8733  height=(unsigned int) event->xexpose.height;
8734  }
8735  else
8736  {
8737  XEvent
8738  sans_event;
8739 
8740  /*
8741  Refresh entire window; discard outstanding expose events.
8742  */
8743  x=0;
8744  y=0;
8745  width=window->width;
8746  height=window->height;
8747  while (XCheckTypedWindowEvent(display,window->id,Expose,&sans_event)) ;
8748  if (window->matte_pixmap != (Pixmap) NULL)
8749  {
8750 #if defined(MAGICKCORE_HAVE_SHAPE)
8751  if (window->shape != MagickFalse)
8752  XShapeCombineMask(display,window->id,ShapeBounding,0,0,
8753  window->matte_pixmap,ShapeSet);
8754 #endif
8755  }
8756  }
8757  /*
8758  Check boundary conditions.
8759  */
8760  if ((window->ximage->width-(x+window->x)) < (int) width)
8761  width=(unsigned int) (window->ximage->width-(x+window->x));
8762  if ((window->ximage->height-(y+window->y)) < (int) height)
8763  height=(unsigned int) (window->ximage->height-(y+window->y));
8764  /*
8765  Refresh image.
8766  */
8767  if (window->matte_pixmap != (Pixmap) NULL)
8768  (void) XSetClipMask(display,window->annotate_context,window->matte_pixmap);
8769  if (window->pixmap != (Pixmap) NULL)
8770  {
8771  if (window->depth > 1)
8772  (void) XCopyArea(display,window->pixmap,window->id,
8773  window->annotate_context,x+window->x,y+window->y,width,height,x,y);
8774  else
8775  (void) XCopyPlane(display,window->pixmap,window->id,
8776  window->highlight_context,x+window->x,y+window->y,width,height,x,y,
8777  1L);
8778  }
8779  else
8780  {
8781 #if defined(MAGICKCORE_HAVE_SHARED_MEMORY)
8782  if (window->shared_memory)
8783  (void) XShmPutImage(display,window->id,window->annotate_context,
8784  window->ximage,x+window->x,y+window->y,x,y,width,height,MagickTrue);
8785 #endif
8786  if (window->shared_memory == MagickFalse)
8787  (void) XPutImage(display,window->id,window->annotate_context,
8788  window->ximage,x+window->x,y+window->y,x,y,width,height);
8789  }
8790  if (window->matte_pixmap != (Pixmap) NULL)
8791  (void) XSetClipMask(display,window->annotate_context,None);
8792  (void) XFlush(display);
8793 }
8794 ␌
8795 /*
8796 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8797 % %
8798 % %
8799 % %
8800 % X R e m o t e C o m m a n d %
8801 % %
8802 % %
8803 % %
8804 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8805 %
8806 % XRemoteCommand() forces a remote display(1) to display the specified
8807 % image filename.
8808 %
8809 % The format of the XRemoteCommand method is:
8810 %
8811 % MagickBooleanType XRemoteCommand(Display *display,const char *window,
8812 % const char *filename)
8813 %
8814 % A description of each parameter follows:
8815 %
8816 % o display: Specifies a connection to an X server; returned from
8817 % XOpenDisplay.
8818 %
8819 % o window: Specifies the name or id of an X window.
8820 %
8821 % o filename: the name of the image filename to display.
8822 %
8823 */
8824 MagickExport MagickBooleanType XRemoteCommand(Display *display,
8825  const char *window,const char *filename)
8826 {
8827  Atom
8828  remote_atom;
8829 
8830  Window
8831  remote_window,
8832  root_window;
8833 
8834  assert(filename != (char *) NULL);
8835  if (IsEventLogging() != MagickFalse)
8836  (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",filename);
8837  if (display == (Display *) NULL)
8838  display=XOpenDisplay((char *) NULL);
8839  if (display == (Display *) NULL)
8840  {
8841  ThrowXWindowException(XServerError,"UnableToOpenXServer",filename);
8842  return(MagickFalse);
8843  }
8844  remote_atom=XInternAtom(display,"IM_PROTOCOLS",MagickFalse);
8845  remote_window=(Window) NULL;
8846  root_window=XRootWindow(display,XDefaultScreen(display));
8847  if (window != (char *) NULL)
8848  {
8849  /*
8850  Search window hierarchy and identify any clients by name or ID.
8851  */
8852  if (isdigit((int) ((unsigned char) *window)) != 0)
8853  remote_window=XWindowByID(display,root_window,(Window)
8854  strtol((char *) window,(char **) NULL,0));
8855  if (remote_window == (Window) NULL)
8856  remote_window=XWindowByName(display,root_window,window);
8857  }
8858  if (remote_window == (Window) NULL)
8859  remote_window=XWindowByProperty(display,root_window,remote_atom);
8860  if (remote_window == (Window) NULL)
8861  {
8862  ThrowXWindowException(XServerError,"UnableToConnectToRemoteDisplay",
8863  filename);
8864  return(MagickFalse);
8865  }
8866  /*
8867  Send remote command.
8868  */
8869  remote_atom=XInternAtom(display,"IM_REMOTE_COMMAND",MagickFalse);
8870  (void) XChangeProperty(display,remote_window,remote_atom,XA_STRING,8,
8871  PropModeReplace,(unsigned char *) filename,(int) strlen(filename));
8872  (void) XSync(display,MagickFalse);
8873  return(MagickTrue);
8874 }
8875 ␌
8876 /*
8877 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8878 % %
8879 % %
8880 % %
8881 + X R e n d e r I m a g e %
8882 % %
8883 % %
8884 % %
8885 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8886 %
8887 % XRenderImage() renders text on the image with an X11 font. It also returns
8888 % the bounding box of the text relative to the image.
8889 %
8890 % The format of the XRenderImage method is:
8891 %
8892 % MagickBooleanType XRenderImage(Image *image,DrawInfo *draw_info,
8893 % const PointInfo *offset,TypeMetric *metrics)
8894 %
8895 % A description of each parameter follows:
8896 %
8897 % o image: the image.
8898 %
8899 % o draw_info: the draw info.
8900 %
8901 % o offset: (x,y) location of text relative to image.
8902 %
8903 % o metrics: bounding box of text.
8904 %
8905 */
8906 MagickPrivate MagickBooleanType XRenderImage(Image *image,
8907  const DrawInfo *draw_info,const PointInfo *offset,TypeMetric *metrics)
8908 {
8909  MagickBooleanType
8910  status;
8911 
8912  size_t
8913  height,
8914  width;
8915 
8916  static Display
8917  *display = (Display *) NULL;
8918 
8919  static DrawInfo
8920  cache_info;
8921 
8922  static XAnnotateInfo
8923  annotate_info;
8924 
8925  static XFontStruct
8926  *font_info;
8927 
8928  static XPixelInfo
8929  pixel;
8930 
8931  static XResourceInfo
8932  resource_info;
8933 
8934  static XrmDatabase
8935  resource_database;
8936 
8937  static XStandardColormap
8938  *map_info;
8939 
8940  static XVisualInfo
8941  *visual_info;
8942 
8943  if (display == (Display *) NULL)
8944  {
8945  const char
8946  *client_name;
8947 
8948  ImageInfo
8949  *image_info;
8950 
8951  /*
8952  Open X server connection.
8953  */
8954  display=XOpenDisplay(draw_info->server_name);
8955  if (display == (Display *) NULL)
8956  {
8957  ThrowXWindowException(XServerError,"UnableToOpenXServer",
8958  draw_info->server_name);
8959  return(MagickFalse);
8960  }
8961  /*
8962  Get user defaults from X resource database.
8963  */
8964  (void) XSetErrorHandler(XError);
8965  image_info=AcquireImageInfo();
8966  client_name=GetClientName();
8967  resource_database=XGetResourceDatabase(display,client_name);
8968  XGetResourceInfo(image_info,resource_database,client_name,&resource_info);
8969  resource_info.close_server=MagickFalse;
8970  resource_info.colormap=PrivateColormap;
8971  resource_info.font=AcquireString(draw_info->font);
8972  resource_info.background_color=AcquireString("#ffffffffffff");
8973  resource_info.foreground_color=AcquireString("#000000000000");
8974  map_info=XAllocStandardColormap();
8975  visual_info=(XVisualInfo *) NULL;
8976  font_info=(XFontStruct *) NULL;
8977  pixel.pixels=(unsigned long *) NULL;
8978  if (map_info == (XStandardColormap *) NULL)
8979  {
8980  ThrowXWindowException(ResourceLimitError,"MemoryAllocationFailed",
8981  image->filename);
8982  return(MagickFalse);
8983  }
8984  /*
8985  Initialize visual info.
8986  */
8987  visual_info=XBestVisualInfo(display,map_info,&resource_info);
8988  if (visual_info == (XVisualInfo *) NULL)
8989  {
8990  XFreeResources(display,visual_info,map_info,&pixel,font_info,
8991  &resource_info,(XWindowInfo *) NULL);
8992  ThrowXWindowException(XServerError,"UnableToGetVisual",
8993  image->filename);
8994  return(MagickFalse);
8995  }
8996  map_info->colormap=(Colormap) NULL;
8997  /*
8998  Initialize Standard Colormap info.
8999  */
9000  XGetMapInfo(visual_info,XDefaultColormap(display,visual_info->screen),
9001  map_info);
9002  XGetPixelPacket(display,visual_info,map_info,&resource_info,
9003  (Image *) NULL,&pixel);
9004  pixel.annotate_context=XDefaultGC(display,visual_info->screen);
9005  /*
9006  Initialize font info.
9007  */
9008  font_info=XBestFont(display,&resource_info,MagickFalse);
9009  if (font_info == (XFontStruct *) NULL)
9010  {
9011  XFreeResources(display,visual_info,map_info,&pixel,font_info,
9012  &resource_info,(XWindowInfo *) NULL);
9013  ThrowXWindowException(XServerError,"UnableToLoadFont",
9014  draw_info->font);
9015  return(MagickFalse);
9016  }
9017  cache_info=(*draw_info);
9018  }
9019  /*
9020  Initialize annotate info.
9021  */
9022  XGetAnnotateInfo(&annotate_info);
9023  annotate_info.stencil=ForegroundStencil;
9024  if (cache_info.font != draw_info->font)
9025  {
9026  /*
9027  Type name has changed.
9028  */
9029  (void) XFreeFont(display,font_info);
9030  (void) CloneString(&resource_info.font,draw_info->font);
9031  font_info=XBestFont(display,&resource_info,MagickFalse);
9032  if (font_info == (XFontStruct *) NULL)
9033  {
9034  ThrowXWindowException(XServerError,"UnableToLoadFont",
9035  draw_info->font);
9036  return(MagickFalse);
9037  }
9038  }
9039  if (draw_info->debug != MagickFalse)
9040  (void) LogMagickEvent(AnnotateEvent,GetMagickModule(),
9041  "Font %s; pointsize %g",draw_info->font != (char *) NULL ?
9042  draw_info->font : "none",draw_info->pointsize);
9043  cache_info=(*draw_info);
9044  annotate_info.font_info=font_info;
9045  annotate_info.text=(char *) draw_info->text;
9046  annotate_info.width=(unsigned int) XTextWidth(font_info,draw_info->text,(int)
9047  strlen(draw_info->text));
9048  annotate_info.height=(unsigned int) font_info->ascent+font_info->descent;
9049  metrics->pixels_per_em.x=(double) font_info->max_bounds.width;
9050  metrics->pixels_per_em.y=(double) font_info->ascent+font_info->descent;
9051  metrics->ascent=(double) font_info->ascent+4;
9052  metrics->descent=(double) (-font_info->descent);
9053  metrics->width=annotate_info.width/ExpandAffine(&draw_info->affine);
9054  metrics->height=font_info->ascent+font_info->descent;
9055  metrics->max_advance=(double) font_info->max_bounds.width;
9056  metrics->bounds.x1=0.0;
9057  metrics->bounds.y1=metrics->descent;
9058  metrics->bounds.x2=metrics->ascent+metrics->descent;
9059  metrics->bounds.y2=metrics->ascent+metrics->descent;
9060  metrics->underline_position=(-2.0);
9061  metrics->underline_thickness=1.0;
9062  if (draw_info->render == MagickFalse)
9063  return(MagickTrue);
9064  if (draw_info->fill.opacity == TransparentOpacity)
9065  return(MagickTrue);
9066  /*
9067  Render fill color.
9068  */
9069  width=annotate_info.width;
9070  height=annotate_info.height;
9071  if ((draw_info->affine.rx != 0.0) || (draw_info->affine.ry != 0.0))
9072  {
9073  if (((draw_info->affine.sx-draw_info->affine.sy) == 0.0) &&
9074  ((draw_info->affine.rx+draw_info->affine.ry) == 0.0))
9075  annotate_info.degrees=(180.0/MagickPI)*
9076  atan2(draw_info->affine.rx,draw_info->affine.sx);
9077  }
9078  (void) FormatLocaleString(annotate_info.geometry,MaxTextExtent,
9079  "%.20gx%.20g%+.20g%+.20g",(double) width,(double) height,
9080  ceil(offset->x-0.5),ceil(offset->y-metrics->ascent-metrics->descent+
9081  draw_info->interline_spacing-0.5));
9082  pixel.pen_color.red=ScaleQuantumToShort(draw_info->fill.red);
9083  pixel.pen_color.green=ScaleQuantumToShort(draw_info->fill.green);
9084  pixel.pen_color.blue=ScaleQuantumToShort(draw_info->fill.blue);
9085  status=XAnnotateImage(display,&pixel,&annotate_info,image);
9086  if (status == 0)
9087  {
9088  ThrowXWindowException(ResourceLimitError,"MemoryAllocationFailed",
9089  image->filename);
9090  return(MagickFalse);
9091  }
9092  return(MagickTrue);
9093 }
9094 ␌
9095 /*
9096 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9097 % %
9098 % %
9099 % %
9100 % X R e t a i n W i n d o w C o l o r s %
9101 % %
9102 % %
9103 % %
9104 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9105 %
9106 % XRetainWindowColors() sets X11 color resources on a window. This preserves
9107 % the colors associated with an image displayed on the window.
9108 %
9109 % The format of the XRetainWindowColors method is:
9110 %
9111 % void XRetainWindowColors(Display *display,const Window window)
9112 %
9113 % A description of each parameter follows:
9114 %
9115 % o display: Specifies a connection to an X server; returned from
9116 % XOpenDisplay.
9117 %
9118 % o window: Specifies a pointer to a XWindowInfo structure.
9119 %
9120 */
9121 MagickExport void XRetainWindowColors(Display *display,const Window window)
9122 {
9123  Atom
9124  property;
9125 
9126  Pixmap
9127  pixmap;
9128 
9129  /*
9130  Put property on the window.
9131  */
9132  assert(display != (Display *) NULL);
9133  assert(window != (Window) NULL);
9134  if (IsEventLogging() != MagickFalse)
9135  (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
9136  property=XInternAtom(display,"_XSETROOT_ID",MagickFalse);
9137  if (property == (Atom) NULL)
9138  ThrowXWindowFatalException(XServerError,"UnableToCreateProperty",
9139  "_XSETROOT_ID");
9140  pixmap=XCreatePixmap(display,window,1,1,1);
9141  if (pixmap == (Pixmap) NULL)
9142  ThrowXWindowFatalException(XServerError,"UnableToCreateBitmap","");
9143  (void) XChangeProperty(display,window,property,XA_PIXMAP,32,PropModeReplace,
9144  (unsigned char *) &pixmap,1);
9145  (void) XSetCloseDownMode(display,RetainPermanent);
9146 }
9147 ␌
9148 /*
9149 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9150 % %
9151 % %
9152 % %
9153 % X S e l e c t W i n d o w %
9154 % %
9155 % %
9156 % %
9157 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9158 %
9159 % XSelectWindow() allows a user to select a window using the mouse. If the
9160 % mouse moves, a cropping rectangle is drawn and the extents of the rectangle
9161 % is returned in the crop_info structure.
9162 %
9163 % The format of the XSelectWindow function is:
9164 %
9165 % target_window=XSelectWindow(display,crop_info)
9166 %
9167 % A description of each parameter follows:
9168 %
9169 % o window: XSelectWindow returns the window id.
9170 %
9171 % o display: Specifies a pointer to the Display structure; returned from
9172 % XOpenDisplay.
9173 %
9174 % o crop_info: Specifies a pointer to a RectangleInfo structure. It
9175 % contains the extents of any cropping rectangle.
9176 %
9177 */
9178 static Window XSelectWindow(Display *display,RectangleInfo *crop_info)
9179 {
9180 #define MinimumCropArea (unsigned int) 9
9181 
9182  Cursor
9183  target_cursor;
9184 
9185  GC
9186  annotate_context;
9187 
9188  int
9189  presses,
9190  x_offset,
9191  y_offset;
9192 
9193  Status
9194  status;
9195 
9196  Window
9197  root_window,
9198  target_window;
9199 
9200  XEvent
9201  event;
9202 
9203  XGCValues
9204  context_values;
9205 
9206  /*
9207  Initialize graphic context.
9208  */
9209  assert(display != (Display *) NULL);
9210  assert(crop_info != (RectangleInfo *) NULL);
9211  if (IsEventLogging() != MagickFalse)
9212  (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
9213  root_window=XRootWindow(display,XDefaultScreen(display));
9214  context_values.background=XBlackPixel(display,XDefaultScreen(display));
9215  context_values.foreground=XWhitePixel(display,XDefaultScreen(display));
9216  context_values.function=GXinvert;
9217  context_values.plane_mask=
9218  context_values.background ^ context_values.foreground;
9219  context_values.subwindow_mode=IncludeInferiors;
9220  annotate_context=XCreateGC(display,root_window,(size_t) (GCBackground |
9221  GCForeground | GCFunction | GCSubwindowMode),&context_values);
9222  if (annotate_context == (GC) NULL)
9223  return(MagickFalse);
9224  /*
9225  Grab the pointer using target cursor.
9226  */
9227  target_cursor=XMakeCursor(display,root_window,XDefaultColormap(display,
9228  XDefaultScreen(display)),(char * ) "white",(char * ) "black");
9229  status=XGrabPointer(display,root_window,MagickFalse,(unsigned int)
9230  (ButtonPressMask | ButtonReleaseMask | ButtonMotionMask),GrabModeSync,
9231  GrabModeAsync,root_window,target_cursor,CurrentTime);
9232  if (status != GrabSuccess)
9233  ThrowXWindowFatalException(XServerError,"UnableToGrabMouse","");
9234  /*
9235  Select a window.
9236  */
9237  crop_info->width=0;
9238  crop_info->height=0;
9239  presses=0;
9240  target_window=(Window) NULL;
9241  x_offset=0;
9242  y_offset=0;
9243  (void) XGrabServer(display);
9244  do
9245  {
9246  if ((crop_info->width*crop_info->height) >= MinimumCropArea)
9247  (void) XDrawRectangle(display,root_window,annotate_context,
9248  (int) crop_info->x,(int) crop_info->y,(unsigned int) crop_info->width-1,
9249  (unsigned int) crop_info->height-1);
9250  /*
9251  Allow another event.
9252  */
9253  (void) XAllowEvents(display,SyncPointer,CurrentTime);
9254  (void) XWindowEvent(display,root_window,ButtonPressMask |
9255  ButtonReleaseMask | ButtonMotionMask,&event);
9256  if ((crop_info->width*crop_info->height) >= MinimumCropArea)
9257  (void) XDrawRectangle(display,root_window,annotate_context,
9258  (int) crop_info->x,(int) crop_info->y,(unsigned int) crop_info->width-1,
9259  (unsigned int) crop_info->height-1);
9260  switch (event.type)
9261  {
9262  case ButtonPress:
9263  {
9264  target_window=XGetSubwindow(display,event.xbutton.subwindow,
9265  event.xbutton.x,event.xbutton.y);
9266  if (target_window == (Window) NULL)
9267  target_window=root_window;
9268  x_offset=event.xbutton.x_root;
9269  y_offset=event.xbutton.y_root;
9270  crop_info->x=(ssize_t) x_offset;
9271  crop_info->y=(ssize_t) y_offset;
9272  crop_info->width=0;
9273  crop_info->height=0;
9274  presses++;
9275  break;
9276  }
9277  case ButtonRelease:
9278  {
9279  presses--;
9280  break;
9281  }
9282  case MotionNotify:
9283  {
9284  /*
9285  Discard pending button motion events.
9286  */
9287  while (XCheckMaskEvent(display,ButtonMotionMask,&event)) ;
9288  crop_info->x=(ssize_t) event.xmotion.x;
9289  crop_info->y=(ssize_t) event.xmotion.y;
9290  /*
9291  Check boundary conditions.
9292  */
9293  if ((int) crop_info->x < x_offset)
9294  crop_info->width=(size_t) (x_offset-crop_info->x);
9295  else
9296  {
9297  crop_info->width=(size_t) (crop_info->x-x_offset);
9298  crop_info->x=(ssize_t) x_offset;
9299  }
9300  if ((int) crop_info->y < y_offset)
9301  crop_info->height=(size_t) (y_offset-crop_info->y);
9302  else
9303  {
9304  crop_info->height=(size_t) (crop_info->y-y_offset);
9305  crop_info->y=(ssize_t) y_offset;
9306  }
9307  }
9308  default:
9309  break;
9310  }
9311  } while ((target_window == (Window) NULL) || (presses > 0));
9312  (void) XUngrabServer(display);
9313  (void) XUngrabPointer(display,CurrentTime);
9314  (void) XFreeCursor(display,target_cursor);
9315  (void) XFreeGC(display,annotate_context);
9316  if ((crop_info->width*crop_info->height) < MinimumCropArea)
9317  {
9318  crop_info->width=0;
9319  crop_info->height=0;
9320  }
9321  if ((crop_info->width != 0) && (crop_info->height != 0))
9322  target_window=root_window;
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:153