MagickCore  6.9.12-56
Convert, Edit, Or Compose Bitmap Images
 All Data Structures
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-2021 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 declaractions.
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 areassociated 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(image_info,) 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  /*
5103  Initialize windows structure.
5104  */
5105  windows->display=display;
5106  windows->wm_protocols=XInternAtom(display,"WM_PROTOCOLS",MagickFalse);
5107  windows->wm_delete_window=XInternAtom(display,"WM_DELETE_WINDOW",MagickFalse);
5108  windows->wm_take_focus=XInternAtom(display,"WM_TAKE_FOCUS",MagickFalse);
5109  windows->im_protocols=XInternAtom(display,"IM_PROTOCOLS",MagickFalse);
5110  windows->im_remote_command=
5111  XInternAtom(display,"IM_REMOTE_COMMAND",MagickFalse);
5112  windows->im_update_widget=XInternAtom(display,"IM_UPDATE_WIDGET",MagickFalse);
5113  windows->im_update_colormap=
5114  XInternAtom(display,"IM_UPDATE_COLORMAP",MagickFalse);
5115  windows->im_former_image=XInternAtom(display,"IM_FORMER_IMAGE",MagickFalse);
5116  windows->im_next_image=XInternAtom(display,"IM_NEXT_IMAGE",MagickFalse);
5117  windows->im_retain_colors=XInternAtom(display,"IM_RETAIN_COLORS",MagickFalse);
5118  windows->im_exit=XInternAtom(display,"IM_EXIT",MagickFalse);
5119  windows->dnd_protocols=XInternAtom(display,"DndProtocol",MagickFalse);
5120 #if defined(MAGICKCORE_WINDOWS_SUPPORT)
5121  (void) XSynchronize(display,MagickFalse);
5122 #endif
5123  if ((GetLogEventMask() & X11Event) != 0)
5124  {
5125  (void) XSynchronize(display,MagickTrue);
5126  (void) LogMagickEvent(X11Event,GetMagickModule(),"Version: %s",
5127  GetMagickVersion((size_t *) NULL));
5128  (void) LogMagickEvent(X11Event,GetMagickModule(),"Protocols:");
5129  (void) LogMagickEvent(X11Event,GetMagickModule(),
5130  " Window Manager: 0x%lx",windows->wm_protocols);
5131  (void) LogMagickEvent(X11Event,GetMagickModule(),
5132  " delete window: 0x%lx",windows->wm_delete_window);
5133  (void) LogMagickEvent(X11Event,GetMagickModule()," take focus: 0x%lx",
5134  windows->wm_take_focus);
5135  (void) LogMagickEvent(X11Event,GetMagickModule()," ImageMagick: 0x%lx",
5136  windows->im_protocols);
5137  (void) LogMagickEvent(X11Event,GetMagickModule(),
5138  " remote command: 0x%lx",windows->im_remote_command);
5139  (void) LogMagickEvent(X11Event,GetMagickModule(),
5140  " update widget: 0x%lx",windows->im_update_widget);
5141  (void) LogMagickEvent(X11Event,GetMagickModule(),
5142  " update colormap: 0x%lx",windows->im_update_colormap);
5143  (void) LogMagickEvent(X11Event,GetMagickModule(),
5144  " former image: 0x%lx",windows->im_former_image);
5145  (void) LogMagickEvent(X11Event,GetMagickModule()," next image: 0x%lx",
5146  windows->im_next_image);
5147  (void) LogMagickEvent(X11Event,GetMagickModule(),
5148  " retain colors: 0x%lx",windows->im_retain_colors);
5149  (void) LogMagickEvent(X11Event,GetMagickModule()," exit: 0x%lx",
5150  windows->im_exit);
5151  (void) LogMagickEvent(X11Event,GetMagickModule()," Drag and Drop: 0x%lx",
5152  windows->dnd_protocols);
5153  }
5154  /*
5155  Allocate standard colormap.
5156  */
5157  windows->map_info=XAllocStandardColormap();
5158  windows->icon_map=XAllocStandardColormap();
5159  if ((windows->map_info == (XStandardColormap *) NULL) ||
5160  (windows->icon_map == (XStandardColormap *) NULL))
5161  ThrowXWindowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed",
5162  "...");
5163  windows->map_info->colormap=(Colormap) NULL;
5164  windows->icon_map->colormap=(Colormap) NULL;
5165  windows->pixel_info->pixels=(unsigned long *) NULL;
5166  windows->pixel_info->annotate_context=(GC) NULL;
5167  windows->pixel_info->highlight_context=(GC) NULL;
5168  windows->pixel_info->widget_context=(GC) NULL;
5169  windows->font_info=(XFontStruct *) NULL;
5170  windows->icon_pixel->annotate_context=(GC) NULL;
5171  windows->icon_pixel->pixels=(unsigned long *) NULL;
5172  /*
5173  Allocate visual.
5174  */
5175  *windows->icon_resources=(*resource_info);
5176  windows->icon_resources->visual_type=(char *) "default";
5177  windows->icon_resources->colormap=SharedColormap;
5178  windows->visual_info=
5179  XBestVisualInfo(display,windows->map_info,resource_info);
5180  windows->icon_visual=
5181  XBestVisualInfo(display,windows->icon_map,windows->icon_resources);
5182  if ((windows->visual_info == (XVisualInfo *) NULL) ||
5183  (windows->icon_visual == (XVisualInfo *) NULL))
5184  ThrowXWindowFatalException(XServerFatalError,"UnableToGetVisual",
5185  resource_info->visual_type);
5186  if ((GetLogEventMask() & X11Event) != 0)
5187  {
5188  (void) LogMagickEvent(X11Event,GetMagickModule(),"Visual:");
5189  (void) LogMagickEvent(X11Event,GetMagickModule()," visual id: 0x%lx",
5190  windows->visual_info->visualid);
5191  (void) LogMagickEvent(X11Event,GetMagickModule()," class: %s",
5192  XVisualClassName(windows->visual_info->klass));
5193  (void) LogMagickEvent(X11Event,GetMagickModule()," depth: %d planes",
5194  windows->visual_info->depth);
5195  (void) LogMagickEvent(X11Event,GetMagickModule(),
5196  " size of colormap: %d entries",windows->visual_info->colormap_size);
5197  (void) LogMagickEvent(X11Event,GetMagickModule(),
5198  " red, green, blue masks: 0x%lx 0x%lx 0x%lx",
5199  windows->visual_info->red_mask,windows->visual_info->green_mask,
5200  windows->visual_info->blue_mask);
5201  (void) LogMagickEvent(X11Event,GetMagickModule(),
5202  " significant bits in color: %d bits",
5203  windows->visual_info->bits_per_rgb);
5204  }
5205  /*
5206  Allocate class and manager hints.
5207  */
5208  windows->class_hints=XAllocClassHint();
5209  windows->manager_hints=XAllocWMHints();
5210  if ((windows->class_hints == (XClassHint *) NULL) ||
5211  (windows->manager_hints == (XWMHints *) NULL))
5212  ThrowXWindowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed",
5213  "...");
5214  /*
5215  Determine group leader if we have one.
5216  */
5217  root_window=XRootWindow(display,windows->visual_info->screen);
5218  windows->group_leader.id=(Window) NULL;
5219  if (resource_info->window_group != (char *) NULL)
5220  {
5221  if (isdigit((int) ((unsigned char) *resource_info->window_group)) != 0)
5222  windows->group_leader.id=XWindowByID(display,root_window,(Window)
5223  strtol((char *) resource_info->window_group,(char **) NULL,0));
5224  if (windows->group_leader.id == (Window) NULL)
5225  windows->group_leader.id=
5226  XWindowByName(display,root_window,resource_info->window_group);
5227  }
5228  return(windows);
5229 }
5230 
5231 /*
5232 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5233 % %
5234 % %
5235 % %
5236 % X M a k e C u r s o r %
5237 % %
5238 % %
5239 % %
5240 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5241 %
5242 % XMakeCursor() creates a crosshairs X11 cursor.
5243 %
5244 % The format of the XMakeCursor method is:
5245 %
5246 % Cursor XMakeCursor(Display *display,Window window,Colormap colormap,
5247 % char *background_color,char *foreground_color)
5248 %
5249 % A description of each parameter follows:
5250 %
5251 % o display: Specifies a connection to an X server; returned from
5252 % XOpenDisplay.
5253 %
5254 % o window: Specifies the ID of the window for which the cursor is
5255 % assigned.
5256 %
5257 % o colormap: Specifies the ID of the colormap from which the background
5258 % and foreground color will be retrieved.
5259 %
5260 % o background_color: Specifies the color to use for the cursor background.
5261 %
5262 % o foreground_color: Specifies the color to use for the cursor foreground.
5263 %
5264 */
5265 MagickExport Cursor XMakeCursor(Display *display,Window window,
5266  Colormap colormap,char *background_color,char *foreground_color)
5267 {
5268 #define scope_height 17
5269 #define scope_x_hot 8
5270 #define scope_y_hot 8
5271 #define scope_width 17
5272 
5273  static const unsigned char
5274  scope_bits[] =
5275  {
5276  0x80, 0x03, 0x00, 0x80, 0x02, 0x00, 0x80, 0x02, 0x00, 0x80, 0x02,
5277  0x00, 0x80, 0x02, 0x00, 0x80, 0x02, 0x00, 0x80, 0x02, 0x00, 0x7f,
5278  0xfc, 0x01, 0x01, 0x00, 0x01, 0x7f, 0xfc, 0x01, 0x80, 0x02, 0x00,
5279  0x80, 0x02, 0x00, 0x80, 0x02, 0x00, 0x80, 0x02, 0x00, 0x80, 0x02,
5280  0x00, 0x80, 0x02, 0x00, 0x80, 0x03, 0x00
5281  },
5282  scope_mask_bits[] =
5283  {
5284  0xc0, 0x07, 0x00, 0xc0, 0x07, 0x00, 0xc0, 0x06, 0x00, 0xc0, 0x06,
5285  0x00, 0xc0, 0x06, 0x00, 0xc0, 0x06, 0x00, 0xff, 0xfe, 0x01, 0x7f,
5286  0xfc, 0x01, 0x03, 0x80, 0x01, 0x7f, 0xfc, 0x01, 0xff, 0xfe, 0x01,
5287  0xc0, 0x06, 0x00, 0xc0, 0x06, 0x00, 0xc0, 0x06, 0x00, 0xc0, 0x06,
5288  0x00, 0xc0, 0x07, 0x00, 0xc0, 0x07, 0x00
5289  };
5290 
5291  Cursor
5292  cursor;
5293 
5294  Pixmap
5295  mask,
5296  source;
5297 
5298  XColor
5299  background,
5300  foreground;
5301 
5302  assert(display != (Display *) NULL);
5303  assert(window != (Window) NULL);
5304  assert(colormap != (Colormap) NULL);
5305  assert(background_color != (char *) NULL);
5306  assert(foreground_color != (char *) NULL);
5307  if (IsEventLogging() != MagickFalse)
5308  (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",background_color);
5309  source=XCreateBitmapFromData(display,window,(char *) scope_bits,scope_width,
5310  scope_height);
5311  mask=XCreateBitmapFromData(display,window,(char *) scope_mask_bits,
5312  scope_width,scope_height);
5313  if ((source == (Pixmap) NULL) || (mask == (Pixmap) NULL))
5314  ThrowXWindowFatalException(XServerError,"UnableToCreatePixmap","...");
5315  (void) XParseColor(display,colormap,background_color,&background);
5316  (void) XParseColor(display,colormap,foreground_color,&foreground);
5317  cursor=XCreatePixmapCursor(display,source,mask,&foreground,&background,
5318  scope_x_hot,scope_y_hot);
5319  (void) XFreePixmap(display,source);
5320  (void) XFreePixmap(display,mask);
5321  return(cursor);
5322 }
5323 
5324 /*
5325 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5326 % %
5327 % %
5328 % %
5329 % X M a k e I m a g e %
5330 % %
5331 % %
5332 % %
5333 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5334 %
5335 % XMakeImage() creates an X11 image. If the image size differs from the X11
5336 % image size, the image is first resized.
5337 %
5338 % The format of the XMakeImage method is:
5339 %
5340 % MagickBooleanType XMakeImage(Display *display,
5341 % const XResourceInfo *resource_info,XWindowInfo *window,Image *image,
5342 % unsigned int width,unsigned int height)
5343 %
5344 % A description of each parameter follows:
5345 %
5346 % o display: Specifies a connection to an X server; returned from
5347 % XOpenDisplay.
5348 %
5349 % o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
5350 %
5351 % o window: Specifies a pointer to a XWindowInfo structure.
5352 %
5353 % o image: the image.
5354 %
5355 % o width: Specifies the width in pixels of the rectangular area to
5356 % display.
5357 %
5358 % o height: Specifies the height in pixels of the rectangular area to
5359 % display.
5360 %
5361 */
5362 MagickExport MagickBooleanType XMakeImage(Display *display,
5363  const XResourceInfo *resource_info,XWindowInfo *window,Image *image,
5364  unsigned int width,unsigned int height)
5365 {
5366 #define CheckOverflowException(length,width,height) \
5367  (((height) != 0) && ((length)/((size_t) height) != ((size_t) width)))
5368 
5369  int
5370  depth,
5371  format;
5372 
5373  size_t
5374  length;
5375 
5376  XImage
5377  *matte_image,
5378  *ximage;
5379 
5380  assert(display != (Display *) NULL);
5381  assert(resource_info != (XResourceInfo *) NULL);
5382  assert(window != (XWindowInfo *) NULL);
5383  assert(width != 0);
5384  assert(height != 0);
5385  magick_unreferenced(length);
5386  if (IsEventLogging() != MagickFalse)
5387  (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
5388  if ((window->width == 0) || (window->height == 0))
5389  return(MagickFalse);
5390  /*
5391  Apply user transforms to the image.
5392  */
5393  (void) XCheckDefineCursor(display,window->id,window->busy_cursor);
5394  (void) XFlush(display);
5395  depth=(int) window->depth;
5396  if (window->destroy)
5397  window->image=DestroyImage(window->image);
5398  window->image=image;
5399  window->destroy=MagickFalse;
5400  if (window->image != (Image *) NULL)
5401  {
5402  if (window->crop_geometry != (char *) NULL)
5403  {
5404  Image
5405  *crop_image;
5406 
5408  crop_info;
5409 
5410  /*
5411  Crop image.
5412  */
5413  window->image->page.x=0;
5414  window->image->page.y=0;
5415  (void) ParsePageGeometry(window->image,window->crop_geometry,
5416  &crop_info,&image->exception);
5417  crop_image=CropImage(window->image,&crop_info,&image->exception);
5418  if (crop_image != (Image *) NULL)
5419  {
5420  if (window->image != image)
5421  window->image=DestroyImage(window->image);
5422  window->image=crop_image;
5423  window->destroy=MagickTrue;
5424  }
5425  }
5426  if ((width != (unsigned int) window->image->columns) ||
5427  (height != (unsigned int) window->image->rows))
5428  {
5429  Image
5430  *resize_image;
5431 
5432  /*
5433  Resize image.
5434  */
5435  resize_image=NewImageList();
5436  if ((window->pixel_info->colors == 0) &&
5437  (window->image->rows > (unsigned long) XDisplayHeight(display,window->screen)) &&
5438  (window->image->columns > (unsigned long) XDisplayWidth(display,window->screen)))
5439  resize_image=ResizeImage(window->image,width,height,
5440  image->filter,image->blur,&image->exception);
5441  else
5442  {
5443  if (window->image->storage_class == PseudoClass)
5444  resize_image=SampleImage(window->image,width,height,
5445  &image->exception);
5446  else
5447  resize_image=ThumbnailImage(window->image,width,height,
5448  &image->exception);
5449  }
5450  if (resize_image != (Image *) NULL)
5451  {
5452  if (window->image != image)
5453  window->image=DestroyImage(window->image);
5454  window->image=resize_image;
5455  window->destroy=MagickTrue;
5456  }
5457  }
5458  width=(unsigned int) window->image->columns;
5459  assert((size_t) width == window->image->columns);
5460  height=(unsigned int) window->image->rows;
5461  assert((size_t) height == window->image->rows);
5462  }
5463  /*
5464  Create X image.
5465  */
5466  ximage=(XImage *) NULL;
5467  format=(depth == 1) ? XYBitmap : ZPixmap;
5468 #if defined(MAGICKCORE_HAVE_SHARED_MEMORY)
5469  if (window->shared_memory != MagickFalse)
5470  {
5471  XShmSegmentInfo
5472  *segment_info;
5473 
5474  segment_info=(XShmSegmentInfo *) window->segment_info;
5475  segment_info[1].shmid=(-1);
5476  segment_info[1].shmaddr=(char *) NULL;
5477  ximage=XShmCreateImage(display,window->visual,(unsigned int) depth,format,
5478  (char *) NULL,&segment_info[1],width,height);
5479  length=0;
5480  if (ximage == (XImage *) NULL)
5481  window->shared_memory=MagickFalse;
5482  else
5483  {
5484  length=(size_t) ximage->bytes_per_line*ximage->height;
5485  if (CheckOverflowException(length,ximage->bytes_per_line,ximage->height))
5486  window->shared_memory=MagickFalse;
5487  }
5488  if (window->shared_memory != MagickFalse)
5489  segment_info[1].shmid=shmget(IPC_PRIVATE,length,IPC_CREAT | 0777);
5490  if (window->shared_memory != MagickFalse)
5491  segment_info[1].shmaddr=(char *) shmat(segment_info[1].shmid,0,0);
5492  if (segment_info[1].shmid < 0)
5493  window->shared_memory=MagickFalse;
5494  if (window->shared_memory != MagickFalse)
5495  (void) shmctl(segment_info[1].shmid,IPC_RMID,0);
5496  else
5497  {
5498  if (ximage != (XImage *) NULL)
5499  XDestroyImage(ximage);
5500  ximage=(XImage *) NULL;
5501  if (segment_info[1].shmaddr)
5502  {
5503  (void) shmdt(segment_info[1].shmaddr);
5504  segment_info[1].shmaddr=(char *) NULL;
5505  }
5506  if (segment_info[1].shmid >= 0)
5507  {
5508  (void) shmctl(segment_info[1].shmid,IPC_RMID,0);
5509  segment_info[1].shmid=(-1);
5510  }
5511  }
5512  }
5513 #endif
5514  /*
5515  Allocate X image pixel data.
5516  */
5517 #if defined(MAGICKCORE_HAVE_SHARED_MEMORY)
5518  if (window->shared_memory)
5519  {
5520  Status
5521  status;
5522 
5523  XShmSegmentInfo
5524  *segment_info;
5525 
5526  (void) XSync(display,MagickFalse);
5527  xerror_alert=MagickFalse;
5528  segment_info=(XShmSegmentInfo *) window->segment_info;
5529  ximage->data=segment_info[1].shmaddr;
5530  segment_info[1].readOnly=MagickFalse;
5531  status=XShmAttach(display,&segment_info[1]);
5532  if (status != False)
5533  (void) XSync(display,MagickFalse);
5534  if ((status == False) || (xerror_alert != MagickFalse))
5535  {
5536  window->shared_memory=MagickFalse;
5537  if (status != False)
5538  XShmDetach(display,&segment_info[1]);
5539  ximage->data=NULL;
5540  XDestroyImage(ximage);
5541  ximage=(XImage *) NULL;
5542  if (segment_info[1].shmid >= 0)
5543  {
5544  if (segment_info[1].shmaddr != NULL)
5545  (void) shmdt(segment_info[1].shmaddr);
5546  (void) shmctl(segment_info[1].shmid,IPC_RMID,0);
5547  segment_info[1].shmid=(-1);
5548  segment_info[1].shmaddr=(char *) NULL;
5549  }
5550  }
5551  }
5552 #endif
5553  if (window->shared_memory == MagickFalse)
5554  ximage=XCreateImage(display,window->visual,(unsigned int) depth,format,0,
5555  (char *) NULL,width,height,XBitmapPad(display),0);
5556  if (ximage == (XImage *) NULL)
5557  {
5558  /*
5559  Unable to create X image.
5560  */
5561  (void) XCheckDefineCursor(display,window->id,window->cursor);
5562  return(MagickFalse);
5563  }
5564  length=(size_t) ximage->bytes_per_line*ximage->height;
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  length=(size_t) window->ximage->bytes_per_line*window->ximage->height;
5622 #if defined(MAGICKCORE_HAVE_SHARED_MEMORY)
5623  if (window->segment_info != (XShmSegmentInfo *) NULL)
5624  {
5625  XShmSegmentInfo
5626  *segment_info;
5627 
5628  segment_info=(XShmSegmentInfo *) window->segment_info;
5629  if (segment_info[0].shmid >= 0)
5630  {
5631  (void) XSync(display,MagickFalse);
5632  (void) XShmDetach(display,&segment_info[0]);
5633  (void) XSync(display,MagickFalse);
5634  if (segment_info[0].shmaddr != (char *) NULL)
5635  (void) shmdt(segment_info[0].shmaddr);
5636  (void) shmctl(segment_info[0].shmid,IPC_RMID,0);
5637  segment_info[0].shmid=(-1);
5638  segment_info[0].shmaddr=(char *) NULL;
5639  window->ximage->data=(char *) NULL;
5640  }
5641  }
5642 #endif
5643  if (window->ximage->data != (char *) NULL)
5644  free(window->ximage->data);
5645  window->ximage->data=(char *) NULL;
5646  XDestroyImage(window->ximage);
5647  window->ximage=(XImage *) NULL;
5648  }
5649 #if defined(MAGICKCORE_HAVE_SHARED_MEMORY)
5650  if (window->segment_info != (XShmSegmentInfo *) NULL)
5651  {
5652  XShmSegmentInfo
5653  *segment_info;
5654 
5655  segment_info=(XShmSegmentInfo *) window->segment_info;
5656  segment_info[0]=segment_info[1];
5657  }
5658 #endif
5659  window->ximage=ximage;
5660  matte_image=(XImage *) NULL;
5661  if ((window->shape != MagickFalse) && (window->image != (Image *) NULL))
5662  if ((window->image->matte != MagickFalse) &&
5663  ((int) width <= XDisplayWidth(display,window->screen)) &&
5664  ((int) height <= XDisplayHeight(display,window->screen)))
5665  {
5666  /*
5667  Create matte image.
5668  */
5669  matte_image=XCreateImage(display,window->visual,1,XYBitmap,0,
5670  (char *) NULL,width,height,XBitmapPad(display),0);
5671  if ((GetLogEventMask() & X11Event) != 0)
5672  {
5673  (void) LogMagickEvent(X11Event,GetMagickModule(),"Matte Image:");
5674  (void) LogMagickEvent(X11Event,GetMagickModule(),
5675  " width, height: %dx%d",matte_image->width,matte_image->height);
5676  }
5677  if (matte_image != (XImage *) NULL)
5678  {
5679  /*
5680  Allocate matte image pixel data.
5681  */
5682  matte_image->data=(char *) malloc((size_t)
5683  matte_image->bytes_per_line*matte_image->depth*
5684  matte_image->height);
5685  if (matte_image->data == (char *) NULL)
5686  {
5687  XDestroyImage(matte_image);
5688  matte_image=(XImage *) NULL;
5689  }
5690  }
5691  }
5692  if (window->matte_image != (XImage *) NULL)
5693  {
5694  /*
5695  Free matte image.
5696  */
5697  if (window->matte_image->data != (char *) NULL)
5698  free(window->matte_image->data);
5699  window->matte_image->data=(char *) NULL;
5700  XDestroyImage(window->matte_image);
5701  window->matte_image=(XImage *) NULL;
5702  }
5703  window->matte_image=matte_image;
5704  if (window->matte_pixmap != (Pixmap) NULL)
5705  {
5706  (void) XFreePixmap(display,window->matte_pixmap);
5707  window->matte_pixmap=(Pixmap) NULL;
5708 #if defined(MAGICKCORE_HAVE_SHAPE)
5709  if (window->shape != MagickFalse)
5710  XShapeCombineMask(display,window->id,ShapeBounding,0,0,None,ShapeSet);
5711 #endif
5712  }
5713  window->stasis=MagickFalse;
5714  /*
5715  Convert pixels to X image data.
5716  */
5717  if (window->image != (Image *) NULL)
5718  {
5719  if ((ximage->byte_order == LSBFirst) || ((ximage->format == XYBitmap) &&
5720  (ximage->bitmap_bit_order == LSBFirst)))
5721  XMakeImageLSBFirst(resource_info,window,window->image,ximage,
5722  matte_image);
5723  else
5724  XMakeImageMSBFirst(resource_info,window,window->image,ximage,
5725  matte_image);
5726  }
5727  if (window->matte_image != (XImage *) NULL)
5728  {
5729  /*
5730  Create matte pixmap.
5731  */
5732  window->matte_pixmap=XCreatePixmap(display,window->id,width,height,1);
5733  if (window->matte_pixmap != (Pixmap) NULL)
5734  {
5735  GC
5736  graphics_context;
5737 
5738  XGCValues
5739  context_values;
5740 
5741  /*
5742  Copy matte image to matte pixmap.
5743  */
5744  context_values.background=1;
5745  context_values.foreground=0;
5746  graphics_context=XCreateGC(display,window->matte_pixmap,
5747  (size_t) (GCBackground | GCForeground),&context_values);
5748  (void) XPutImage(display,window->matte_pixmap,graphics_context,
5749  window->matte_image,0,0,0,0,width,height);
5750  (void) XFreeGC(display,graphics_context);
5751 #if defined(MAGICKCORE_HAVE_SHAPE)
5752  if (window->shape != MagickFalse)
5753  XShapeCombineMask(display,window->id,ShapeBounding,0,0,
5754  window->matte_pixmap,ShapeSet);
5755 #endif
5756  }
5757  }
5758  (void) XMakePixmap(display,resource_info,window);
5759  /*
5760  Restore cursor.
5761  */
5762  (void) XCheckDefineCursor(display,window->id,window->cursor);
5763  return(MagickTrue);
5764 }
5765 
5766 /*
5767 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5768 % %
5769 % %
5770 % %
5771 + X M a k e I m a g e L S B F i r s t %
5772 % %
5773 % %
5774 % %
5775 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5776 %
5777 % XMakeImageLSBFirst() initializes the pixel data of an X11 Image. The X image
5778 % pixels are copied in least-significant bit and byte first order. The
5779 % server's scanline pad is respected. Rather than using one or two general
5780 % cases, many special cases are found here to help speed up the image
5781 % conversion.
5782 %
5783 % The format of the XMakeImageLSBFirst method is:
5784 %
5785 % void XMakeImageLSBFirst(Display *display,XWindows *windows)
5786 %
5787 % A description of each parameter follows:
5788 %
5789 % o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
5790 %
5791 % o window: Specifies a pointer to a XWindowInfo structure.
5792 %
5793 % o image: the image.
5794 %
5795 % o ximage: Specifies a pointer to a XImage structure; returned from
5796 % XCreateImage.
5797 %
5798 % o matte_image: Specifies a pointer to a XImage structure; returned from
5799 % XCreateImage.
5800 %
5801 */
5802 static void XMakeImageLSBFirst(const XResourceInfo *resource_info,
5803  const XWindowInfo *window,Image *image,XImage *ximage,XImage *matte_image)
5804 {
5805  CacheView
5806  *canvas_view;
5807 
5808  Image
5809  *canvas;
5810 
5811  int
5812  y;
5813 
5814  const IndexPacket
5815  *indexes;
5816 
5817  const PixelPacket
5818  *p;
5819 
5820  int
5821  x;
5822 
5823  unsigned char
5824  *q;
5825 
5826  unsigned char
5827  bit,
5828  byte;
5829 
5830  unsigned int
5831  scanline_pad;
5832 
5833  unsigned long
5834  pixel,
5835  *pixels;
5836 
5837  XStandardColormap
5838  *map_info;
5839 
5840  assert(resource_info != (XResourceInfo *) NULL);
5841  assert(window != (XWindowInfo *) NULL);
5842  assert(image != (Image *) NULL);
5843  if (IsEventLogging() != MagickFalse)
5844  (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
5845  canvas=image;
5846  if ((window->immutable == MagickFalse) &&
5847  (image->storage_class == DirectClass) && (image->matte != MagickFalse))
5848  {
5849  char
5850  size[MaxTextExtent];
5851 
5852  Image
5853  *pattern;
5854 
5855  ImageInfo
5856  *image_info;
5857 
5858  image_info=AcquireImageInfo();
5859  (void) CopyMagickString(image_info->filename,
5860  resource_info->image_info->texture != (char *) NULL ?
5861  resource_info->image_info->texture : "pattern:checkerboard",
5862  MaxTextExtent);
5863  (void) FormatLocaleString(size,MaxTextExtent,"%.20gx%.20g",(double)
5864  image->columns,(double) image->rows);
5865  image_info->size=ConstantString(size);
5866  pattern=ReadImage(image_info,&image->exception);
5867  image_info=DestroyImageInfo(image_info);
5868  if (pattern != (Image *) NULL)
5869  {
5870  canvas=CloneImage(image,0,0,MagickTrue,&image->exception);
5871  if (canvas == (Image *) NULL)
5872  return;
5873  (void) CompositeImage(canvas,DstOverCompositeOp,pattern,0,0);
5874  pattern=DestroyImage(pattern);
5875  }
5876  }
5877  scanline_pad=(unsigned int) (ximage->bytes_per_line-((ximage->width*
5878  ximage->bits_per_pixel) >> 3));
5879  map_info=window->map_info;
5880  pixels=window->pixel_info->pixels;
5881  q=(unsigned char *) ximage->data;
5882  x=0;
5883  canvas_view=AcquireVirtualCacheView(canvas,&canvas->exception);
5884  if (ximage->format == XYBitmap)
5885  {
5886  unsigned short
5887  polarity;
5888 
5889  unsigned char
5890  background,
5891  foreground;
5892 
5893  /*
5894  Convert canvas to big-endian bitmap.
5895  */
5896  background=(unsigned char)
5897  (XPixelIntensity(&window->pixel_info->foreground_color) <
5898  XPixelIntensity(&window->pixel_info->background_color) ? 0x80 : 0x00);
5899  foreground=(unsigned char)
5900  (XPixelIntensity(&window->pixel_info->background_color) <
5901  XPixelIntensity(&window->pixel_info->foreground_color) ? 0x80 : 0x00);
5902  polarity=(unsigned short) ((GetPixelIntensity(image,
5903  &canvas->colormap[0])) < (QuantumRange/2.0) ? 1 : 0);
5904  if (canvas->colors == 2)
5905  polarity=GetPixelIntensity(canvas,&canvas->colormap[0]) <
5906  GetPixelIntensity(canvas,&canvas->colormap[1]);
5907  for (y=0; y < (int) canvas->rows; y++)
5908  {
5909  p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,canvas->columns,1,
5910  &canvas->exception);
5911  if (p == (const PixelPacket *) NULL)
5912  break;
5913  indexes=GetCacheViewVirtualIndexQueue(canvas_view);
5914  bit=0;
5915  byte=0;
5916  for (x=0; x < (int) canvas->columns; x++)
5917  {
5918  byte>>=1;
5919  if (GetPixelIndex(indexes+x) == (IndexPacket) polarity)
5920  byte|=foreground;
5921  else
5922  byte|=background;
5923  bit++;
5924  if (bit == 8)
5925  {
5926  *q++=byte;
5927  bit=0;
5928  byte=0;
5929  }
5930  }
5931  if (bit != 0)
5932  *q=byte >> (8-bit);
5933  q+=scanline_pad;
5934  }
5935  }
5936  else
5937  if (window->pixel_info->colors != 0)
5938  switch (ximage->bits_per_pixel)
5939  {
5940  case 2:
5941  {
5942  unsigned int
5943  nibble;
5944 
5945  /*
5946  Convert to 2 bit color-mapped X canvas.
5947  */
5948  for (y=0; y < (int) canvas->rows; y++)
5949  {
5950  p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
5951  canvas->columns,1,&canvas->exception);
5952  if (p == (const PixelPacket *) NULL)
5953  break;
5954  indexes=GetCacheViewVirtualIndexQueue(canvas_view);
5955  nibble=0;
5956  for (x=0; x < (int) canvas->columns; x++)
5957  {
5958  pixel=pixels[(ssize_t) GetPixelIndex(indexes+x)] & 0x0f;
5959  switch (nibble)
5960  {
5961  case 0:
5962  {
5963  *q=(unsigned char) pixel;
5964  nibble++;
5965  break;
5966  }
5967  case 1:
5968  {
5969  *q|=(unsigned char) (pixel << 2);
5970  nibble++;
5971  break;
5972  }
5973  case 2:
5974  {
5975  *q|=(unsigned char) (pixel << 4);
5976  nibble++;
5977  break;
5978  }
5979  case 3:
5980  {
5981  *q|=(unsigned char) (pixel << 6);
5982  q++;
5983  nibble=0;
5984  break;
5985  }
5986  }
5987  }
5988  q+=scanline_pad;
5989  }
5990  break;
5991  }
5992  case 4:
5993  {
5994  unsigned int
5995  nibble;
5996 
5997  /*
5998  Convert to 4 bit color-mapped X canvas.
5999  */
6000  for (y=0; y < (int) canvas->rows; y++)
6001  {
6002  p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
6003  canvas->columns,1,&canvas->exception);
6004  if (p == (const PixelPacket *) NULL)
6005  break;
6006  indexes=GetCacheViewVirtualIndexQueue(canvas_view);
6007  nibble=0;
6008  for (x=0; x < (int) canvas->columns; x++)
6009  {
6010  pixel=pixels[(ssize_t) GetPixelIndex(indexes+x)] & 0xf;
6011  switch (nibble)
6012  {
6013  case 0:
6014  {
6015  *q=(unsigned char) pixel;
6016  nibble++;
6017  break;
6018  }
6019  case 1:
6020  {
6021  *q|=(unsigned char) (pixel << 4);
6022  q++;
6023  nibble=0;
6024  break;
6025  }
6026  }
6027  }
6028  q+=scanline_pad;
6029  }
6030  break;
6031  }
6032  case 6:
6033  case 8:
6034  {
6035  /*
6036  Convert to 8 bit color-mapped X canvas.
6037  */
6038  if ((resource_info->color_recovery != MagickFalse) &&
6039  (resource_info->quantize_info->dither != MagickFalse))
6040  {
6041  XDitherImage(canvas,ximage);
6042  break;
6043  }
6044  for (y=0; y < (int) canvas->rows; y++)
6045  {
6046  p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
6047  canvas->columns,1,&canvas->exception);
6048  if (p == (const PixelPacket *) NULL)
6049  break;
6050  indexes=GetCacheViewVirtualIndexQueue(canvas_view);
6051  for (x=0; x < (int) canvas->columns; x++)
6052  {
6053  pixel=pixels[(ssize_t) GetPixelIndex(indexes+x)];
6054  *q++=(unsigned char) pixel;
6055  }
6056  q+=scanline_pad;
6057  }
6058  break;
6059  }
6060  default:
6061  {
6062  int
6063  k;
6064 
6065  unsigned int
6066  bytes_per_pixel;
6067 
6068  /*
6069  Convert to multi-byte color-mapped X canvas.
6070  */
6071  bytes_per_pixel=(unsigned int) (ximage->bits_per_pixel >> 3);
6072  for (y=0; y < (int) canvas->rows; y++)
6073  {
6074  p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
6075  canvas->columns,1,&canvas->exception);
6076  if (p == (const PixelPacket *) NULL)
6077  break;
6078  indexes=GetCacheViewVirtualIndexQueue(canvas_view);
6079  for (x=0; x < (int) canvas->columns; x++)
6080  {
6081  pixel=pixels[(ssize_t) GetPixelIndex(indexes+x)];
6082  for (k=0; k < (int) bytes_per_pixel; k++)
6083  {
6084  *q++=(unsigned char) (pixel & 0xff);
6085  pixel>>=8;
6086  }
6087  }
6088  q+=scanline_pad;
6089  }
6090  break;
6091  }
6092  }
6093  else
6094  switch (ximage->bits_per_pixel)
6095  {
6096  case 2:
6097  {
6098  unsigned int
6099  nibble;
6100 
6101  /*
6102  Convert to contiguous 2 bit continuous-tone X canvas.
6103  */
6104  for (y=0; y < (int) canvas->rows; y++)
6105  {
6106  nibble=0;
6107  p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
6108  canvas->columns,1,&canvas->exception);
6109  if (p == (const PixelPacket *) NULL)
6110  break;
6111  for (x=0; x < (int) canvas->columns; x++)
6112  {
6113  pixel=XGammaPixel(map_info,p);
6114  pixel&=0xf;
6115  switch (nibble)
6116  {
6117  case 0:
6118  {
6119  *q=(unsigned char) pixel;
6120  nibble++;
6121  break;
6122  }
6123  case 1:
6124  {
6125  *q|=(unsigned char) (pixel << 2);
6126  nibble++;
6127  break;
6128  }
6129  case 2:
6130  {
6131  *q|=(unsigned char) (pixel << 4);
6132  nibble++;
6133  break;
6134  }
6135  case 3:
6136  {
6137  *q|=(unsigned char) (pixel << 6);
6138  q++;
6139  nibble=0;
6140  break;
6141  }
6142  }
6143  p++;
6144  }
6145  q+=scanline_pad;
6146  }
6147  break;
6148  }
6149  case 4:
6150  {
6151  unsigned int
6152  nibble;
6153 
6154  /*
6155  Convert to contiguous 4 bit continuous-tone X canvas.
6156  */
6157  for (y=0; y < (int) canvas->rows; y++)
6158  {
6159  p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
6160  canvas->columns,1,&canvas->exception);
6161  if (p == (const PixelPacket *) NULL)
6162  break;
6163  nibble=0;
6164  for (x=0; x < (int) canvas->columns; x++)
6165  {
6166  pixel=XGammaPixel(map_info,p);
6167  pixel&=0xf;
6168  switch (nibble)
6169  {
6170  case 0:
6171  {
6172  *q=(unsigned char) pixel;
6173  nibble++;
6174  break;
6175  }
6176  case 1:
6177  {
6178  *q|=(unsigned char) (pixel << 4);
6179  q++;
6180  nibble=0;
6181  break;
6182  }
6183  }
6184  p++;
6185  }
6186  q+=scanline_pad;
6187  }
6188  break;
6189  }
6190  case 6:
6191  case 8:
6192  {
6193  /*
6194  Convert to contiguous 8 bit continuous-tone X canvas.
6195  */
6196  if ((resource_info->color_recovery != MagickFalse) &&
6197  (resource_info->quantize_info->dither != MagickFalse))
6198  {
6199  XDitherImage(canvas,ximage);
6200  break;
6201  }
6202  for (y=0; y < (int) canvas->rows; y++)
6203  {
6204  p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
6205  canvas->columns,1,&canvas->exception);
6206  if (p == (const PixelPacket *) NULL)
6207  break;
6208  for (x=0; x < (int) canvas->columns; x++)
6209  {
6210  pixel=XGammaPixel(map_info,p);
6211  *q++=(unsigned char) pixel;
6212  p++;
6213  }
6214  q+=scanline_pad;
6215  }
6216  break;
6217  }
6218  default:
6219  {
6220  if ((ximage->bits_per_pixel == 32) && (map_info->red_max == 255) &&
6221  (map_info->green_max == 255) && (map_info->blue_max == 255) &&
6222  (map_info->red_mult == 65536L) && (map_info->green_mult == 256) &&
6223  (map_info->blue_mult == 1))
6224  {
6225  /*
6226  Convert to 32 bit continuous-tone X canvas.
6227  */
6228  for (y=0; y < (int) canvas->rows; y++)
6229  {
6230  p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
6231  canvas->columns,1,&canvas->exception);
6232  if (p == (const PixelPacket *) NULL)
6233  break;
6234  if ((red_gamma != 1.0) || (green_gamma != 1.0) ||
6235  (blue_gamma != 1.0))
6236  {
6237  /*
6238  Gamma correct canvas.
6239  */
6240  for (x=(int) canvas->columns-1; x >= 0; x--)
6241  {
6242  *q++=ScaleQuantumToChar(XBlueGamma(GetPixelBlue(p)));
6243  *q++=ScaleQuantumToChar(XGreenGamma(GetPixelGreen(p)));
6244  *q++=ScaleQuantumToChar(XRedGamma(GetPixelRed(p)));
6245  *q++=0;
6246  p++;
6247  }
6248  continue;
6249  }
6250  for (x=(int) canvas->columns-1; x >= 0; x--)
6251  {
6252  *q++=ScaleQuantumToChar((Quantum) GetPixelBlue(p));
6253  *q++=ScaleQuantumToChar((Quantum) GetPixelGreen(p));
6254  *q++=ScaleQuantumToChar((Quantum) GetPixelRed(p));
6255  *q++=0;
6256  p++;
6257  }
6258  }
6259  }
6260  else
6261  if ((ximage->bits_per_pixel == 32) && (map_info->red_max == 255) &&
6262  (map_info->green_max == 255) && (map_info->blue_max == 255) &&
6263  (map_info->red_mult == 1) && (map_info->green_mult == 256) &&
6264  (map_info->blue_mult == 65536L))
6265  {
6266  /*
6267  Convert to 32 bit continuous-tone X canvas.
6268  */
6269  for (y=0; y < (int) canvas->rows; y++)
6270  {
6271  p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
6272  canvas->columns,1,&canvas->exception);
6273  if (p == (const PixelPacket *) NULL)
6274  break;
6275  if ((red_gamma != 1.0) || (green_gamma != 1.0) ||
6276  (blue_gamma != 1.0))
6277  {
6278  /*
6279  Gamma correct canvas.
6280  */
6281  for (x=(int) canvas->columns-1; x >= 0; x--)
6282  {
6283  *q++=ScaleQuantumToChar(XRedGamma(GetPixelRed(p)));
6284  *q++=ScaleQuantumToChar(XGreenGamma(GetPixelGreen(p)));
6285  *q++=ScaleQuantumToChar(XBlueGamma(GetPixelBlue(p)));
6286  *q++=0;
6287  p++;
6288  }
6289  continue;
6290  }
6291  for (x=(int) canvas->columns-1; x >= 0; x--)
6292  {
6293  *q++=ScaleQuantumToChar((Quantum) GetPixelRed(p));
6294  *q++=ScaleQuantumToChar((Quantum) GetPixelGreen(p));
6295  *q++=ScaleQuantumToChar((Quantum) GetPixelBlue(p));
6296  *q++=0;
6297  p++;
6298  }
6299  }
6300  }
6301  else
6302  {
6303  int
6304  k;
6305 
6306  unsigned int
6307  bytes_per_pixel;
6308 
6309  /*
6310  Convert to multi-byte continuous-tone X canvas.
6311  */
6312  bytes_per_pixel=(unsigned int) (ximage->bits_per_pixel >> 3);
6313  for (y=0; y < (int) canvas->rows; y++)
6314  {
6315  p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
6316  canvas->columns,1,&canvas->exception);
6317  if (p == (PixelPacket *) NULL)
6318  break;
6319  for (x=0; x < (int) canvas->columns; x++)
6320  {
6321  pixel=XGammaPixel(map_info,p);
6322  for (k=0; k < (int) bytes_per_pixel; k++)
6323  {
6324  *q++=(unsigned char) (pixel & 0xff);
6325  pixel>>=8;
6326  }
6327  p++;
6328  }
6329  q+=scanline_pad;
6330  }
6331  }
6332  break;
6333  }
6334  }
6335  if (matte_image != (XImage *) NULL)
6336  {
6337  /*
6338  Initialize matte canvas.
6339  */
6340  scanline_pad=(unsigned int) (matte_image->bytes_per_line-
6341  ((matte_image->width*matte_image->bits_per_pixel) >> 3));
6342  q=(unsigned char *) matte_image->data;
6343  for (y=0; y < (int) canvas->rows; y++)
6344  {
6345  p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,canvas->columns,1,
6346  &canvas->exception);
6347  if (p == (const PixelPacket *) NULL)
6348  break;
6349  bit=0;
6350  byte=0;
6351  for (x=(int) canvas->columns-1; x >= 0; x--)
6352  {
6353  byte>>=1;
6354  if (GetPixelOpacity(p) > (QuantumRange/2))
6355  byte|=0x80;
6356  bit++;
6357  if (bit == 8)
6358  {
6359  *q++=byte;
6360  bit=0;
6361  byte=0;
6362  }
6363  p++;
6364  }
6365  if (bit != 0)
6366  *q=byte >> (8-bit);
6367  q+=scanline_pad;
6368  }
6369  }
6370  canvas_view=DestroyCacheView(canvas_view);
6371  if (canvas != image)
6372  canvas=DestroyImage(canvas);
6373 }
6374 
6375 /*
6376 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
6377 % %
6378 % %
6379 % %
6380 + X M a k e I m a g e M S B F i r s t %
6381 % %
6382 % %
6383 % %
6384 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
6385 %
6386 % XMakeImageMSBFirst() initializes the pixel data of an X11 Image. The X
6387 % image pixels are copied in most-significant bit and byte first order. The
6388 % server's scanline pad is also respected. Rather than using one or two
6389 % general cases, many special cases are found here to help speed up the image
6390 % conversion.
6391 %
6392 % The format of the XMakeImageMSBFirst method is:
6393 %
6394 % XMakeImageMSBFirst(resource_info,window,image,ximage,matte_image)
6395 %
6396 % A description of each parameter follows:
6397 %
6398 % o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
6399 %
6400 % o window: Specifies a pointer to a XWindowInfo structure.
6401 %
6402 % o image: the image.
6403 %
6404 % o ximage: Specifies a pointer to a XImage structure; returned from
6405 % XCreateImage.
6406 %
6407 % o matte_image: Specifies a pointer to a XImage structure; returned from
6408 % XCreateImage.
6409 %
6410 */
6411 static void XMakeImageMSBFirst(const XResourceInfo *resource_info,
6412  const XWindowInfo *window,Image *image,XImage *ximage,XImage *matte_image)
6413 {
6414  CacheView
6415  *canvas_view;
6416 
6417  Image
6418  *canvas;
6419 
6420  int
6421  y;
6422 
6423  int
6424  x;
6425 
6426  const IndexPacket
6427  *indexes;
6428 
6429  const PixelPacket
6430  *p;
6431 
6432  unsigned char
6433  *q;
6434 
6435  unsigned char
6436  bit,
6437  byte;
6438 
6439  unsigned int
6440  scanline_pad;
6441 
6442  unsigned long
6443  pixel,
6444  *pixels;
6445 
6446  XStandardColormap
6447  *map_info;
6448 
6449  assert(resource_info != (XResourceInfo *) NULL);
6450  assert(window != (XWindowInfo *) NULL);
6451  assert(image != (Image *) NULL);
6452  if (IsEventLogging() != MagickFalse)
6453  (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
6454  canvas=image;
6455  if ((window->immutable != MagickFalse) &&
6456  (image->storage_class == DirectClass) && (image->matte != MagickFalse))
6457  {
6458  char
6459  size[MaxTextExtent];
6460 
6461  Image
6462  *pattern;
6463 
6464  ImageInfo
6465  *image_info;
6466 
6467  image_info=AcquireImageInfo();
6468  (void) CopyMagickString(image_info->filename,
6469  resource_info->image_info->texture != (char *) NULL ?
6470  resource_info->image_info->texture : "pattern:checkerboard",
6471  MaxTextExtent);
6472  (void) FormatLocaleString(size,MaxTextExtent,"%.20gx%.20g",(double)
6473  image->columns,(double) image->rows);
6474  image_info->size=ConstantString(size);
6475  pattern=ReadImage(image_info,&image->exception);
6476  image_info=DestroyImageInfo(image_info);
6477  if (pattern != (Image *) NULL)
6478  {
6479  canvas=CloneImage(image,0,0,MagickTrue,&image->exception);
6480  if (canvas == (Image *) NULL)
6481  return;
6482  (void) CompositeImage(canvas,DstOverCompositeOp,pattern,0,0);
6483  pattern=DestroyImage(pattern);
6484  }
6485  }
6486  scanline_pad=(unsigned int) (ximage->bytes_per_line-
6487  ((ximage->width*ximage->bits_per_pixel) >> 3));
6488  map_info=window->map_info;
6489  pixels=window->pixel_info->pixels;
6490  q=(unsigned char *) ximage->data;
6491  x=0;
6492  canvas_view=AcquireVirtualCacheView(canvas,&canvas->exception);
6493  if (ximage->format == XYBitmap)
6494  {
6495  unsigned short
6496  polarity;
6497 
6498  unsigned char
6499  background,
6500  foreground;
6501 
6502  /*
6503  Convert canvas to big-endian bitmap.
6504  */
6505  background=(unsigned char)
6506  (XPixelIntensity(&window->pixel_info->foreground_color) <
6507  XPixelIntensity(&window->pixel_info->background_color) ? 0x01 : 0x00);
6508  foreground=(unsigned char)
6509  (XPixelIntensity(&window->pixel_info->background_color) <
6510  XPixelIntensity(&window->pixel_info->foreground_color) ? 0x01 : 0x00);
6511  polarity=(unsigned short) ((GetPixelIntensity(image,
6512  &canvas->colormap[0])) < (QuantumRange/2.0) ? 1 : 0);
6513  if (canvas->colors == 2)
6514  polarity=GetPixelIntensity(canvas,&canvas->colormap[0]) <
6515  GetPixelIntensity(canvas,&canvas->colormap[1]);
6516  for (y=0; y < (int) canvas->rows; y++)
6517  {
6518  p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,canvas->columns,1,
6519  &canvas->exception);
6520  if (p == (const PixelPacket *) NULL)
6521  break;
6522  indexes=GetCacheViewVirtualIndexQueue(canvas_view);
6523  bit=0;
6524  byte=0;
6525  for (x=(int) canvas->columns-1; x >= 0; x--)
6526  {
6527  byte<<=1;
6528  if (GetPixelIndex(indexes+x) == (IndexPacket) polarity)
6529  byte|=foreground;
6530  else
6531  byte|=background;
6532  bit++;
6533  if (bit == 8)
6534  {
6535  *q++=byte;
6536  bit=0;
6537  byte=0;
6538  }
6539  }
6540  if (bit != 0)
6541  *q=byte << (8-bit);
6542  q+=scanline_pad;
6543  }
6544  }
6545  else
6546  if (window->pixel_info->colors != 0)
6547  switch (ximage->bits_per_pixel)
6548  {
6549  case 2:
6550  {
6551  unsigned int
6552  nibble;
6553 
6554  /*
6555  Convert to 2 bit color-mapped X canvas.
6556  */
6557  for (y=0; y < (int) canvas->rows; y++)
6558  {
6559  p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
6560  canvas->columns,1,&canvas->exception);
6561  if (p == (const PixelPacket *) NULL)
6562  break;
6563  indexes=GetCacheViewVirtualIndexQueue(canvas_view);
6564  nibble=0;
6565  for (x=0; x < (int) canvas->columns; x++)
6566  {
6567  pixel=pixels[(ssize_t) GetPixelIndex(indexes+x)] & 0xf;
6568  switch (nibble)
6569  {
6570  case 0:
6571  {
6572  *q=(unsigned char) (pixel << 6);
6573  nibble++;
6574  break;
6575  }
6576  case 1:
6577  {
6578  *q|=(unsigned char) (pixel << 4);
6579  nibble++;
6580  break;
6581  }
6582  case 2:
6583  {
6584  *q|=(unsigned char) (pixel << 2);
6585  nibble++;
6586  break;
6587  }
6588  case 3:
6589  {
6590  *q|=(unsigned char) pixel;
6591  q++;
6592  nibble=0;
6593  break;
6594  }
6595  }
6596  }
6597  q+=scanline_pad;
6598  }
6599  break;
6600  }
6601  case 4:
6602  {
6603  unsigned int
6604  nibble;
6605 
6606  /*
6607  Convert to 4 bit color-mapped X canvas.
6608  */
6609  for (y=0; y < (int) canvas->rows; y++)
6610  {
6611  p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
6612  canvas->columns,1,&canvas->exception);
6613  if (p == (const PixelPacket *) NULL)
6614  break;
6615  indexes=GetCacheViewVirtualIndexQueue(canvas_view);
6616  nibble=0;
6617  for (x=0; x < (int) canvas->columns; x++)
6618  {
6619  pixel=pixels[(ssize_t) GetPixelIndex(indexes+x)] & 0xf;
6620  switch (nibble)
6621  {
6622  case 0:
6623  {
6624  *q=(unsigned char) (pixel << 4);
6625  nibble++;
6626  break;
6627  }
6628  case 1:
6629  {
6630  *q|=(unsigned char) pixel;
6631  q++;
6632  nibble=0;
6633  break;
6634  }
6635  }
6636  }
6637  q+=scanline_pad;
6638  }
6639  break;
6640  }
6641  case 6:
6642  case 8:
6643  {
6644  /*
6645  Convert to 8 bit color-mapped X canvas.
6646  */
6647  if (resource_info->color_recovery &&
6648  resource_info->quantize_info->dither)
6649  {
6650  XDitherImage(canvas,ximage);
6651  break;
6652  }
6653  for (y=0; y < (int) canvas->rows; y++)
6654  {
6655  p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
6656  canvas->columns,1,&canvas->exception);
6657  if (p == (const PixelPacket *) NULL)
6658  break;
6659  indexes=GetCacheViewVirtualIndexQueue(canvas_view);
6660  for (x=0; x < (int) canvas->columns; x++)
6661  {
6662  pixel=pixels[(ssize_t) GetPixelIndex(indexes+x)];
6663  *q++=(unsigned char) pixel;
6664  }
6665  q+=scanline_pad;
6666  }
6667  break;
6668  }
6669  default:
6670  {
6671  int
6672  k;
6673 
6674  unsigned int
6675  bytes_per_pixel;
6676 
6677  unsigned char
6678  channel[sizeof(size_t)];
6679 
6680  /*
6681  Convert to 8 bit color-mapped X canvas.
6682  */
6683  bytes_per_pixel=(unsigned int) (ximage->bits_per_pixel >> 3);
6684  for (y=0; y < (int) canvas->rows; y++)
6685  {
6686  p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
6687  canvas->columns,1,&canvas->exception);
6688  if (p == (const PixelPacket *) NULL)
6689  break;
6690  indexes=GetCacheViewVirtualIndexQueue(canvas_view);
6691  for (x=0; x < (int) canvas->columns; x++)
6692  {
6693  pixel=pixels[(ssize_t) GetPixelIndex(indexes+x)];
6694  for (k=(int) bytes_per_pixel-1; k >= 0; k--)
6695  {
6696  channel[k]=(unsigned char) pixel;
6697  pixel>>=8;
6698  }
6699  for (k=0; k < (int) bytes_per_pixel; k++)
6700  *q++=channel[k];
6701  }
6702  q+=scanline_pad;
6703  }
6704  break;
6705  }
6706  }
6707  else
6708  switch (ximage->bits_per_pixel)
6709  {
6710  case 2:
6711  {
6712  unsigned int
6713  nibble;
6714 
6715  /*
6716  Convert to 4 bit continuous-tone X canvas.
6717  */
6718  for (y=0; y < (int) canvas->rows; y++)
6719  {
6720  p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
6721  canvas->columns,1,&canvas->exception);
6722  if (p == (const PixelPacket *) NULL)
6723  break;
6724  nibble=0;
6725  for (x=(int) canvas->columns-1; x >= 0; x--)
6726  {
6727  pixel=XGammaPixel(map_info,p);
6728  pixel&=0xf;
6729  switch (nibble)
6730  {
6731  case 0:
6732  {
6733  *q=(unsigned char) (pixel << 6);
6734  nibble++;
6735  break;
6736  }
6737  case 1:
6738  {
6739  *q|=(unsigned char) (pixel << 4);
6740  nibble++;
6741  break;
6742  }
6743  case 2:
6744  {
6745  *q|=(unsigned char) (pixel << 2);
6746  nibble++;
6747  break;
6748  }
6749  case 3:
6750  {
6751  *q|=(unsigned char) pixel;
6752  q++;
6753  nibble=0;
6754  break;
6755  }
6756  }
6757  p++;
6758  }
6759  q+=scanline_pad;
6760  }
6761  break;
6762  }
6763  case 4:
6764  {
6765  unsigned int
6766  nibble;
6767 
6768  /*
6769  Convert to 4 bit continuous-tone X canvas.
6770  */
6771  for (y=0; y < (int) canvas->rows; y++)
6772  {
6773  p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
6774  canvas->columns,1,&canvas->exception);
6775  if (p == (const PixelPacket *) NULL)
6776  break;
6777  nibble=0;
6778  for (x=(int) canvas->columns-1; x >= 0; x--)
6779  {
6780  pixel=XGammaPixel(map_info,p);
6781  pixel&=0xf;
6782  switch (nibble)
6783  {
6784  case 0:
6785  {
6786  *q=(unsigned char) (pixel << 4);
6787  nibble++;
6788  break;
6789  }
6790  case 1:
6791  {
6792  *q|=(unsigned char) pixel;
6793  q++;
6794  nibble=0;
6795  break;
6796  }
6797  }
6798  p++;
6799  }
6800  q+=scanline_pad;
6801  }
6802  break;
6803  }
6804  case 6:
6805  case 8:
6806  {
6807  /*
6808  Convert to 8 bit continuous-tone X canvas.
6809  */
6810  if (resource_info->color_recovery &&
6811  resource_info->quantize_info->dither)
6812  {
6813  XDitherImage(canvas,ximage);
6814  break;
6815  }
6816  for (y=0; y < (int) canvas->rows; y++)
6817  {
6818  p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
6819  canvas->columns,1,&canvas->exception);
6820  if (p == (const PixelPacket *) NULL)
6821  break;
6822  for (x=(int) canvas->columns-1; x >= 0; x--)
6823  {
6824  pixel=XGammaPixel(map_info,p);
6825  *q++=(unsigned char) pixel;
6826  p++;
6827  }
6828  q+=scanline_pad;
6829  }
6830  break;
6831  }
6832  default:
6833  {
6834  if ((ximage->bits_per_pixel == 32) && (map_info->red_max == 255) &&
6835  (map_info->green_max == 255) && (map_info->blue_max == 255) &&
6836  (map_info->red_mult == 65536L) && (map_info->green_mult == 256) &&
6837  (map_info->blue_mult == 1))
6838  {
6839  /*
6840  Convert to 32 bit continuous-tone X canvas.
6841  */
6842  for (y=0; y < (int) canvas->rows; y++)
6843  {
6844  p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
6845  canvas->columns,1,&canvas->exception);
6846  if (p == (const PixelPacket *) NULL)
6847  break;
6848  if ((red_gamma != 1.0) || (green_gamma != 1.0) ||
6849  (blue_gamma != 1.0))
6850  {
6851  /*
6852  Gamma correct canvas.
6853  */
6854  for (x=(int) canvas->columns-1; x >= 0; x--)
6855  {
6856  *q++=0;
6857  *q++=ScaleQuantumToChar(XRedGamma(GetPixelRed(p)));
6858  *q++=ScaleQuantumToChar(XGreenGamma(GetPixelGreen(p)));
6859  *q++=ScaleQuantumToChar(XBlueGamma(GetPixelBlue(p)));
6860  p++;
6861  }
6862  continue;
6863  }
6864  for (x=(int) canvas->columns-1; x >= 0; x--)
6865  {
6866  *q++=0;
6867  *q++=ScaleQuantumToChar((Quantum) GetPixelRed(p));
6868  *q++=ScaleQuantumToChar((Quantum) GetPixelGreen(p));
6869  *q++=ScaleQuantumToChar((Quantum) GetPixelBlue(p));
6870  p++;
6871  }
6872  }
6873  }
6874  else
6875  if ((ximage->bits_per_pixel == 32) && (map_info->red_max == 255) &&
6876  (map_info->green_max == 255) && (map_info->blue_max == 255) &&
6877  (map_info->red_mult == 1) && (map_info->green_mult == 256) &&
6878  (map_info->blue_mult == 65536L))
6879  {
6880  /*
6881  Convert to 32 bit continuous-tone X canvas.
6882  */
6883  for (y=0; y < (int) canvas->rows; y++)
6884  {
6885  p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
6886  canvas->columns,1,&canvas->exception);
6887  if (p == (const PixelPacket *) NULL)
6888  break;
6889  if ((red_gamma != 1.0) || (green_gamma != 1.0) ||
6890  (blue_gamma != 1.0))
6891  {
6892  /*
6893  Gamma correct canvas.
6894  */
6895  for (x=(int) canvas->columns-1; x >= 0; x--)
6896  {
6897  *q++=0;
6898  *q++=ScaleQuantumToChar(XBlueGamma(GetPixelBlue(p)));
6899  *q++=ScaleQuantumToChar(XGreenGamma(GetPixelGreen(p)));
6900  *q++=ScaleQuantumToChar(XRedGamma(GetPixelRed(p)));
6901  p++;
6902  }
6903  continue;
6904  }
6905  for (x=(int) canvas->columns-1; x >= 0; x--)
6906  {
6907  *q++=0;
6908  *q++=ScaleQuantumToChar((Quantum) GetPixelBlue(p));
6909  *q++=ScaleQuantumToChar((Quantum) GetPixelGreen(p));
6910  *q++=ScaleQuantumToChar((Quantum) GetPixelRed(p));
6911  p++;
6912  }
6913  }
6914  }
6915  else
6916  {
6917  int
6918  k;
6919 
6920  unsigned int
6921  bytes_per_pixel;
6922 
6923  /*
6924  Convert to multi-byte continuous-tone X canvas.
6925  */
6926  bytes_per_pixel=(unsigned int) (ximage->bits_per_pixel >> 3);
6927  for (y=0; y < (int) canvas->rows; y++)
6928  {
6929  p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
6930  canvas->columns,1,&canvas->exception);
6931  if (p == (const PixelPacket *) NULL)
6932  break;
6933  for (x=(int) canvas->columns-1; x >= 0; x--)
6934  {
6935  pixel=XGammaPixel(map_info,p);
6936  for (k=(int) bytes_per_pixel-1; k >= 0; k--)
6937  {
6938  *q++=(unsigned char) (pixel & 0xff);
6939  pixel>>=8;
6940  }
6941  p++;
6942  }
6943  q+=scanline_pad;
6944  }
6945  }
6946  break;
6947  }
6948  }
6949  if (matte_image != (XImage *) NULL)
6950  {
6951  /*
6952  Initialize matte canvas.
6953  */
6954  scanline_pad=(unsigned int) (matte_image->bytes_per_line-
6955  ((matte_image->width*matte_image->bits_per_pixel) >> 3));
6956  q=(unsigned char *) matte_image->data;
6957  for (y=0; y < (int) canvas->rows; y++)
6958  {
6959  p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,canvas->columns,1,
6960  &canvas->exception);
6961  if (p == (const PixelPacket *) NULL)
6962  break;
6963  bit=0;
6964  byte=0;
6965  for (x=(int) canvas->columns-1; x >= 0; x--)
6966  {
6967  byte<<=1;
6968  if (GetPixelOpacity(p) > (QuantumRange/2))
6969  byte|=0x01;
6970  bit++;
6971  if (bit == 8)
6972  {
6973  *q++=byte;
6974  bit=0;
6975  byte=0;
6976  }
6977  p++;
6978  }
6979  if (bit != 0)
6980  *q=byte << (8-bit);
6981  q+=scanline_pad;
6982  }
6983  }
6984  canvas_view=DestroyCacheView(canvas_view);
6985  if (canvas != image)
6986  canvas=DestroyImage(canvas);
6987 }
6988 
6989 /*
6990 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
6991 % %
6992 % %
6993 % %
6994 % X M a k e M a g n i f y I m a g e %
6995 % %
6996 % %
6997 % %
6998 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
6999 %
7000 % XMakeMagnifyImage() magnifies a region of an X image and displays it.
7001 %
7002 % The format of the XMakeMagnifyImage method is:
7003 %
7004 % void XMakeMagnifyImage(display,windows)
7005 %
7006 % A description of each parameter follows:
7007 %
7008 % o display: Specifies a connection to an X server; returned from
7009 % XOpenDisplay.
7010 %
7011 % o windows: Specifies a pointer to a XWindows structure.
7012 %
7013 */
7014 MagickExport void XMakeMagnifyImage(Display *display,XWindows *windows)
7015 {
7016  char
7017  tuple[MaxTextExtent];
7018 
7019  int
7020  y;
7021 
7023  pixel;
7024 
7025  int
7026  x;
7027 
7028  ssize_t
7029  i;
7030 
7031  unsigned char
7032  *p,
7033  *q;
7034 
7035  ssize_t
7036  n;
7037 
7038  static unsigned int
7039  previous_magnify = 0;
7040 
7041  static XWindowInfo
7042  magnify_window;
7043 
7044  unsigned int
7045  height,
7046  j,
7047  k,
7048  l,
7049  magnify,
7050  scanline_pad,
7051  width;
7052 
7053  XImage
7054  *ximage;
7055 
7056  /*
7057  Check boundary conditions.
7058  */
7059  assert(display != (Display *) NULL);
7060  assert(windows != (XWindows *) NULL);
7061  if (IsEventLogging() != MagickFalse)
7062  (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
7063  magnify=1;
7064  for (n=1; n < (ssize_t) windows->magnify.data; n++)
7065  magnify<<=1;
7066  while ((magnify*windows->image.ximage->width) < windows->magnify.width)
7067  magnify<<=1;
7068  while ((magnify*windows->image.ximage->height) < windows->magnify.height)
7069  magnify<<=1;
7070  while (magnify > windows->magnify.width)
7071  magnify>>=1;
7072  while (magnify > windows->magnify.height)
7073  magnify>>=1;
7074  if (magnify == 0)
7075  {
7076  magnify=1;
7077  if (previous_magnify != 0)
7078  magnify=previous_magnify;
7079  }
7080  if (magnify != previous_magnify)
7081  {
7082  Status
7083  status;
7084 
7085  XTextProperty
7086  window_name;
7087 
7088  /*
7089  New magnify factor: update magnify window name.
7090  */
7091  i=0;
7092  while ((1 << i) <= (int) magnify)
7093  i++;
7094  (void) FormatLocaleString(windows->magnify.name,MaxTextExtent,
7095  "Magnify %.20gX",(double) i);
7096  status=XStringListToTextProperty(&windows->magnify.name,1,&window_name);
7097  if (status != False)
7098  {
7099  XSetWMName(display,windows->magnify.id,&window_name);
7100  XSetWMIconName(display,windows->magnify.id,&window_name);
7101  (void) XFree((void *) window_name.value);
7102  }
7103  }
7104  previous_magnify=magnify;
7105  ximage=windows->image.ximage;
7106  width=(unsigned int) windows->magnify.ximage->width;
7107  height=(unsigned int) windows->magnify.ximage->height;
7108  if ((windows->magnify.x < 0) ||
7109  (windows->magnify.x >= windows->image.ximage->width))
7110  windows->magnify.x=windows->image.ximage->width >> 1;
7111  x=windows->magnify.x-((width/magnify) >> 1);
7112  if (x < 0)
7113  x=0;
7114  else
7115  if (x > (int) (ximage->width-(width/magnify)))
7116  x=ximage->width-width/magnify;
7117  if ((windows->magnify.y < 0) ||
7118  (windows->magnify.y >= windows->image.ximage->height))
7119  windows->magnify.y=windows->image.ximage->height >> 1;
7120  y=windows->magnify.y-((height/magnify) >> 1);
7121  if (y < 0)
7122  y=0;
7123  else
7124  if (y > (int) (ximage->height-(height/magnify)))
7125  y=ximage->height-height/magnify;
7126  q=(unsigned char *) windows->magnify.ximage->data;
7127  scanline_pad=(unsigned int) (windows->magnify.ximage->bytes_per_line-
7128  ((width*windows->magnify.ximage->bits_per_pixel) >> 3));
7129  if (ximage->bits_per_pixel < 8)
7130  {
7131  unsigned char
7132  background,
7133  byte,
7134  foreground,
7135  p_bit,
7136  q_bit;
7137 
7138  unsigned int
7139  plane;
7140 
7141  XPixelInfo
7142  *pixel_info;
7143 
7144  pixel_info=windows->magnify.pixel_info;
7145  switch (ximage->bitmap_bit_order)
7146  {
7147  case LSBFirst:
7148  {
7149  /*
7150  Magnify little-endian bitmap.
7151  */
7152  background=0x00;
7153  foreground=0x80;
7154  if (ximage->format == XYBitmap)
7155  {
7156  background=(unsigned char)
7157  (XPixelIntensity(&pixel_info->foreground_color) <
7158  XPixelIntensity(&pixel_info->background_color) ? 0x80 : 0x00);
7159  foreground=(unsigned char)
7160  (XPixelIntensity(&pixel_info->background_color) <
7161  XPixelIntensity(&pixel_info->foreground_color) ? 0x80 : 0x00);
7162  if (windows->magnify.depth > 1)
7163  Swap(background,foreground);
7164  }
7165  for (i=0; i < (ssize_t) height; i+=magnify)
7166  {
7167  /*
7168  Propogate pixel magnify rows.
7169  */
7170  for (j=0; j < magnify; j++)
7171  {
7172  p=(unsigned char *) ximage->data+y*ximage->bytes_per_line+
7173  ((x*ximage->bits_per_pixel) >> 3);
7174  p_bit=(unsigned char) (x*ximage->bits_per_pixel) & 0x07;
7175  q_bit=0;
7176  byte=0;
7177  for (k=0; k < width; k+=magnify)
7178  {
7179  /*
7180  Propogate pixel magnify columns.
7181  */
7182  for (l=0; l < magnify; l++)
7183  {
7184  /*
7185  Propogate each bit plane.
7186  */
7187  for (plane=0; (int) plane < ximage->bits_per_pixel; plane++)
7188  {
7189  byte>>=1;
7190  if (*p & (0x01 << (p_bit+plane)))
7191  byte|=foreground;
7192  else
7193  byte|=background;
7194  q_bit++;
7195  if (q_bit == 8)
7196  {
7197  *q++=byte;
7198  q_bit=0;
7199  byte=0;
7200  }
7201  }
7202  }
7203  p_bit+=ximage->bits_per_pixel;
7204  if (p_bit == 8)
7205  {
7206  p++;
7207  p_bit=0;
7208  }
7209  if (q_bit != 0)
7210  *q=byte >> (8-q_bit);
7211  q+=scanline_pad;
7212  }
7213  }
7214  y++;
7215  }
7216  break;
7217  }
7218  case MSBFirst:
7219  default:
7220  {
7221  /*
7222  Magnify big-endian bitmap.
7223  */
7224  background=0x00;
7225  foreground=0x01;
7226  if (ximage->format == XYBitmap)
7227  {
7228  background=(unsigned char)
7229  (XPixelIntensity(&pixel_info->foreground_color) <
7230  XPixelIntensity(&pixel_info->background_color) ? 0x01 : 0x00);
7231  foreground=(unsigned char)
7232  (XPixelIntensity(&pixel_info->background_color) <
7233  XPixelIntensity(&pixel_info->foreground_color) ? 0x01 : 0x00);
7234  if (windows->magnify.depth > 1)
7235  Swap(background,foreground);
7236  }
7237  for (i=0; i < (ssize_t) height; i+=magnify)
7238  {
7239  /*
7240  Propogate pixel magnify rows.
7241  */
7242  for (j=0; j < magnify; j++)
7243  {
7244  p=(unsigned char *) ximage->data+y*ximage->bytes_per_line+
7245  ((x*ximage->bits_per_pixel) >> 3);
7246  p_bit=(unsigned char) (x*ximage->bits_per_pixel) & 0x07;
7247  q_bit=0;
7248  byte=0;
7249  for (k=0; k < width; k+=magnify)
7250  {
7251  /*
7252  Propogate pixel magnify columns.
7253  */
7254  for (l=0; l < magnify; l++)
7255  {
7256  /*
7257  Propogate each bit plane.
7258  */
7259  for (plane=0; (int) plane < ximage->bits_per_pixel; plane++)
7260  {
7261  byte<<=1;
7262  if (*p & (0x80 >> (p_bit+plane)))
7263  byte|=foreground;
7264  else
7265  byte|=background;
7266  q_bit++;
7267  if (q_bit == 8)
7268  {
7269  *q++=byte;
7270  q_bit=0;
7271  byte=0;
7272  }
7273  }
7274  }
7275  p_bit+=ximage->bits_per_pixel;
7276  if (p_bit == 8)
7277  {
7278  p++;
7279  p_bit=0;
7280  }
7281  if (q_bit != 0)
7282  *q=byte << (8-q_bit);
7283  q+=scanline_pad;
7284  }
7285  }
7286  y++;
7287  }
7288  break;
7289  }
7290  }
7291  }
7292  else
7293  switch (ximage->bits_per_pixel)
7294  {
7295  case 6:
7296  case 8:
7297  {
7298  /*
7299  Magnify 8 bit X image.
7300  */
7301  for (i=0; i < (ssize_t) height; i+=magnify)
7302  {
7303  /*
7304  Propogate pixel magnify rows.
7305  */
7306  for (j=0; j < magnify; j++)
7307  {
7308  p=(unsigned char *) ximage->data+y*ximage->bytes_per_line+
7309  ((x*ximage->bits_per_pixel) >> 3);
7310  for (k=0; k < width; k+=magnify)
7311  {
7312  /*
7313  Propogate pixel magnify columns.
7314  */
7315  for (l=0; l < magnify; l++)
7316  *q++=(*p);
7317  p++;
7318  }
7319  q+=scanline_pad;
7320  }
7321  y++;
7322  }
7323  break;
7324  }
7325  default:
7326  {
7327  unsigned int
7328  bytes_per_pixel,
7329  m;
7330 
7331  /*
7332  Magnify multi-byte X image.
7333  */
7334  bytes_per_pixel=(unsigned int) ximage->bits_per_pixel >> 3;
7335  for (i=0; i < (ssize_t) height; i+=magnify)
7336  {
7337  /*
7338  Propogate pixel magnify rows.
7339  */
7340  for (j=0; j < magnify; j++)
7341  {
7342  p=(unsigned char *) ximage->data+y*ximage->bytes_per_line+
7343  ((x*ximage->bits_per_pixel) >> 3);
7344  for (k=0; k < width; k+=magnify)
7345  {
7346  /*
7347  Propogate pixel magnify columns.
7348  */
7349  for (l=0; l < magnify; l++)
7350  for (m=0; m < bytes_per_pixel; m++)
7351  *q++=(*(p+m));
7352  p+=bytes_per_pixel;
7353  }
7354  q+=scanline_pad;
7355  }
7356  y++;
7357  }
7358  break;
7359  }
7360  }
7361  /*
7362  Copy X image to magnify pixmap.
7363  */
7364  x=windows->magnify.x-((width/magnify) >> 1);
7365  if (x < 0)
7366  x=(int) ((width >> 1)-windows->magnify.x*magnify);
7367  else
7368  if (x > (int) (ximage->width-(width/magnify)))
7369  x=(int) ((ximage->width-windows->magnify.x)*magnify-(width >> 1));
7370  else
7371  x=0;
7372  y=windows->magnify.y-((height/magnify) >> 1);
7373  if (y < 0)
7374  y=(int) ((height >> 1)-windows->magnify.y*magnify);
7375  else
7376  if (y > (int) (ximage->height-(height/magnify)))
7377  y=(int) ((ximage->height-windows->magnify.y)*magnify-(height >> 1));
7378  else
7379  y=0;
7380  if ((x != 0) || (y != 0))
7381  (void) XFillRectangle(display,windows->magnify.pixmap,
7382  windows->magnify.annotate_context,0,0,width,height);
7383  (void) XPutImage(display,windows->magnify.pixmap,
7384  windows->magnify.annotate_context,windows->magnify.ximage,0,0,x,y,width-x,
7385  height-y);
7386  if ((magnify > 1) && ((magnify <= (width >> 1)) &&
7387  (magnify <= (height >> 1))))
7388  {
7390  highlight_info;
7391 
7392  /*
7393  Highlight center pixel.
7394  */
7395  highlight_info.x=(ssize_t) windows->magnify.width >> 1;
7396  highlight_info.y=(ssize_t) windows->magnify.height >> 1;
7397  highlight_info.width=magnify;
7398  highlight_info.height=magnify;
7399  (void) XDrawRectangle(display,windows->magnify.pixmap,
7400  windows->magnify.highlight_context,(int) highlight_info.x,
7401  (int) highlight_info.y,(unsigned int) highlight_info.width-1,
7402  (unsigned int) highlight_info.height-1);
7403  if (magnify > 2)
7404  (void) XDrawRectangle(display,windows->magnify.pixmap,
7405  windows->magnify.annotate_context,(int) highlight_info.x+1,
7406  (int) highlight_info.y+1,(unsigned int) highlight_info.width-3,
7407  (unsigned int) highlight_info.height-3);
7408  }
7409  /*
7410  Show center pixel color.
7411  */
7412  (void) GetOneVirtualMagickPixel(windows->image.image,(ssize_t)
7413  windows->magnify.x,(ssize_t) windows->magnify.y,&pixel,
7414  &windows->image.image->exception);
7415  (void) FormatLocaleString(tuple,MaxTextExtent,"%d,%d: ",
7416  windows->magnify.x,windows->magnify.y);
7417  (void) ConcatenateMagickString(tuple,"(",MaxTextExtent);
7418  ConcatenateColorComponent(&pixel,RedChannel,X11Compliance,tuple);
7419  (void) ConcatenateMagickString(tuple,",",MaxTextExtent);
7420  ConcatenateColorComponent(&pixel,GreenChannel,X11Compliance,tuple);
7421  (void) ConcatenateMagickString(tuple,",",MaxTextExtent);
7422  ConcatenateColorComponent(&pixel,BlueChannel,X11Compliance,tuple);
7423  if (pixel.colorspace == CMYKColorspace)
7424  {
7425  (void) ConcatenateMagickString(tuple,",",MaxTextExtent);
7426  ConcatenateColorComponent(&pixel,IndexChannel,X11Compliance,tuple);
7427  }
7428  if (pixel.matte != MagickFalse)
7429  {
7430  (void) ConcatenateMagickString(tuple,",",MaxTextExtent);
7431  ConcatenateColorComponent(&pixel,OpacityChannel,X11Compliance,tuple);
7432  }
7433  (void) ConcatenateMagickString(tuple,")",MaxTextExtent);
7434  height=(unsigned int) windows->magnify.font_info->ascent+
7435  windows->magnify.font_info->descent;
7436  x=windows->magnify.font_info->max_bounds.width >> 1;
7437  y=windows->magnify.font_info->ascent+(height >> 2);
7438  (void) XDrawImageString(display,windows->magnify.pixmap,
7439  windows->magnify.annotate_context,x,y,tuple,(int) strlen(tuple));
7440  GetColorTuple(&pixel,MagickTrue,tuple);
7441  y+=height;
7442  (void) XDrawImageString(display,windows->magnify.pixmap,
7443  windows->magnify.annotate_context,x,y,tuple,(int) strlen(tuple));
7444  (void) QueryMagickColorname(windows->image.image,&pixel,SVGCompliance,tuple,
7445  &windows->image.image->exception);
7446  y+=height;
7447  (void) XDrawImageString(display,windows->magnify.pixmap,
7448  windows->magnify.annotate_context,x,y,tuple,(int) strlen(tuple));
7449  /*
7450  Refresh magnify window.
7451  */
7452  magnify_window=windows->magnify;
7453  magnify_window.x=0;
7454  magnify_window.y=0;
7455  XRefreshWindow(display,&magnify_window,(XEvent *) NULL);
7456 }
7457 
7458 /*
7459 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
7460 % %
7461 % %
7462 % %
7463 % X M a k e P i x m a p %
7464 % %
7465 % %
7466 % %
7467 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
7468 %
7469 % XMakePixmap() creates an X11 pixmap.
7470 %
7471 % The format of the XMakePixmap method is:
7472 %
7473 % void XMakeStandardColormap(Display *display,XVisualInfo *visual_info,
7474 % XResourceInfo *resource_info,Image *image,XStandardColormap *map_info,
7475 % XPixelInfo *pixel)
7476 %
7477 % A description of each parameter follows:
7478 %
7479 % o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
7480 %
7481 % o display: Specifies a connection to an X server; returned from
7482 % XOpenDisplay.
7483 %
7484 % o window: Specifies a pointer to a XWindowInfo structure.
7485 %
7486 */
7487 static MagickBooleanType XMakePixmap(Display *display,
7488  const XResourceInfo *resource_info,XWindowInfo *window)
7489 {
7490  unsigned int
7491  height,
7492  width;
7493 
7494  assert(display != (Display *) NULL);
7495  assert(resource_info != (XResourceInfo *) NULL);
7496  assert(window != (XWindowInfo *) NULL);
7497  if (IsEventLogging() != MagickFalse)
7498  (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
7499  (void) resource_info;
7500  if (window->pixmap != (Pixmap) NULL)
7501  {
7502  /*
7503  Destroy previous X pixmap.
7504  */
7505  (void) XFreePixmap(display,window->pixmap);
7506  window->pixmap=(Pixmap) NULL;
7507  }
7508  if (window->use_pixmap == MagickFalse)
7509  return(MagickFalse);
7510  if (window->ximage == (XImage *) NULL)
7511  return(MagickFalse);
7512  /*
7513  Display busy cursor.
7514  */
7515  (void) XCheckDefineCursor(display,window->id,window->busy_cursor);
7516  (void) XFlush(display);
7517  /*
7518  Create pixmap.
7519  */
7520  width=(unsigned int) window->ximage->width;
7521  height=(unsigned int) window->ximage->height;
7522  window->pixmap=XCreatePixmap(display,window->id,width,height,window->depth);
7523  if (window->pixmap == (Pixmap) NULL)
7524  {
7525  /*
7526  Unable to allocate pixmap.
7527  */
7528  (void) XCheckDefineCursor(display,window->id,window->cursor);
7529  return(MagickFalse);
7530  }
7531  /*
7532  Copy X image to pixmap.
7533  */
7534 #if defined(MAGICKCORE_HAVE_SHARED_MEMORY)
7535  if (window->shared_memory)
7536  (void) XShmPutImage(display,window->pixmap,window->annotate_context,
7537  window->ximage,0,0,0,0,width,height,MagickTrue);
7538 #endif
7539  if (window->shared_memory == MagickFalse)
7540  (void) XPutImage(display,window->pixmap,window->annotate_context,
7541  window->ximage,0,0,0,0,width,height);
7542  if ((GetLogEventMask() & X11Event) != 0)
7543  {
7544  (void) LogMagickEvent(X11Event,GetMagickModule(),"Pixmap:");
7545  (void) LogMagickEvent(X11Event,GetMagickModule()," width, height: %ux%u",
7546  width,height);
7547  }
7548  /*
7549  Restore cursor.
7550  */
7551  (void) XCheckDefineCursor(display,window->id,window->cursor);
7552  return(MagickTrue);
7553 }
7554 
7555 /*
7556 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
7557 % %
7558 % %
7559 % %
7560 % X M a k e S t a n d a r d C o l o r m a p %
7561 % %
7562 % %
7563 % %
7564 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
7565 %
7566 % XMakeStandardColormap() creates an X11 Standard Colormap.
7567 %
7568 % The format of the XMakeStandardColormap method is:
7569 %
7570 % XMakeStandardColormap(display,visual_info,resource_info,image,
7571 % map_info,pixel)
7572 %
7573 % A description of each parameter follows:
7574 %
7575 % o display: Specifies a connection to an X server; returned from
7576 % XOpenDisplay.
7577 %
7578 % o visual_info: Specifies a pointer to a X11 XVisualInfo structure;
7579 % returned from XGetVisualInfo.
7580 %
7581 % o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
7582 %
7583 % o image: the image.
7584 %
7585 % o map_info: If a Standard Colormap type is specified, this structure is
7586 % initialized with info from the Standard Colormap.
7587 %
7588 % o pixel: Specifies a pointer to a XPixelInfo structure.
7589 %
7590 */
7591 
7592 #if defined(__cplusplus) || defined(c_plusplus)
7593 extern "C" {
7594 #endif
7595 
7596 static inline MagickRealType DiversityPixelIntensity(
7597  const DiversityPacket *pixel)
7598 {
7599  MagickRealType
7600  intensity;
7601 
7602  intensity=0.298839*pixel->red+0.586811*pixel->green+0.114350*pixel->blue;
7603  return(intensity);
7604 }
7605 
7606 static int IntensityCompare(const void *x,const void *y)
7607 {
7608  DiversityPacket
7609  *color_1,
7610  *color_2;
7611 
7612  int
7613  diversity;
7614 
7615  color_1=(DiversityPacket *) x;
7616  color_2=(DiversityPacket *) y;
7617  diversity=(int) (DiversityPixelIntensity(color_2)-
7618  DiversityPixelIntensity(color_1));
7619  return(diversity);
7620 }
7621 
7622 static int PopularityCompare(const void *x,const void *y)
7623 {
7624  DiversityPacket
7625  *color_1,
7626  *color_2;
7627 
7628  color_1=(DiversityPacket *) x;
7629  color_2=(DiversityPacket *) y;
7630  return((int) color_2->count-(int) color_1->count);
7631 }
7632 
7633 #if defined(__cplusplus) || defined(c_plusplus)
7634 }
7635 #endif
7636 
7637 static inline Quantum ScaleXToQuantum(const size_t x,
7638  const size_t scale)
7639 {
7640  return((Quantum) (((MagickRealType) QuantumRange*x)/scale+0.5));
7641 }
7642 
7643 MagickExport void XMakeStandardColormap(Display *display,
7644  XVisualInfo *visual_info,XResourceInfo *resource_info,Image *image,
7645  XStandardColormap *map_info,XPixelInfo *pixel)
7646 {
7647  Colormap
7648  colormap;
7649 
7651  *exception;
7652 
7653  IndexPacket
7654  *indexes;
7655 
7656  ssize_t
7657  i;
7658 
7659  Status
7660  status;
7661 
7662  size_t
7663  number_colors,
7664  retain_colors;
7665 
7666  unsigned short
7667  gray_value;
7668 
7669  XColor
7670  color,
7671  *colors,
7672  *p;
7673 
7674  assert(display != (Display *) NULL);
7675  assert(visual_info != (XVisualInfo *) NULL);
7676  assert(map_info != (XStandardColormap *) NULL);
7677  assert(resource_info != (XResourceInfo *) NULL);
7678  assert(pixel != (XPixelInfo *) NULL);
7679  if (IsEventLogging() != MagickFalse)
7680  (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
7681  exception=(&image->exception);
7682  if (resource_info->map_type != (char *) NULL)
7683  {
7684  /*
7685  Standard Colormap is already defined (i.e. xstdcmap).
7686  */
7687  XGetPixelPacket(display,visual_info,map_info,resource_info,image,
7688  pixel);
7689  number_colors=(unsigned int) (map_info->base_pixel+
7690  (map_info->red_max+1)*(map_info->green_max+1)*(map_info->blue_max+1));
7691  if ((map_info->red_max*map_info->green_max*map_info->blue_max) != 0)
7692  if ((image->matte == MagickFalse) &&
7693  (resource_info->color_recovery == MagickFalse) &&
7694  resource_info->quantize_info->dither &&
7695  (number_colors < MaxColormapSize))
7696  {
7697  Image
7698  *affinity_image;
7699 
7700  PixelPacket
7701  *magick_restrict q;
7702 
7703  /*
7704  Improve image appearance with error diffusion.
7705  */
7706  affinity_image=AcquireImage((ImageInfo *) NULL);
7707  if (affinity_image == (Image *) NULL)
7708  ThrowXWindowFatalException(ResourceLimitFatalError,
7709  "UnableToDitherImage",image->filename);
7710  affinity_image->columns=number_colors;
7711  affinity_image->rows=1;
7712  /*
7713  Initialize colormap image.
7714  */
7715  q=QueueAuthenticPixels(affinity_image,0,0,affinity_image->columns,
7716  1,exception);
7717  if (q != (PixelPacket *) NULL)
7718  {
7719  for (i=0; i < (ssize_t) number_colors; i++)
7720  {
7721  SetPixelRed(q,0);
7722  if (map_info->red_max != 0)
7723  SetPixelRed(q,ScaleXToQuantum((size_t) (i/
7724  map_info->red_mult),map_info->red_max));
7725  SetPixelGreen(q,0);
7726  if (map_info->green_max != 0)
7727  SetPixelGreen(q,ScaleXToQuantum((size_t) ((i/
7728  map_info->green_mult) % (map_info->green_max+1)),
7729  map_info->green_max));
7730  SetPixelBlue(q,0);
7731  if (map_info->blue_max != 0)
7732  SetPixelBlue(q,ScaleXToQuantum((size_t) (i %
7733  map_info->green_mult),map_info->blue_max));
7734  SetPixelOpacity(q,TransparentOpacity);
7735  q++;
7736  }
7737  (void) SyncAuthenticPixels(affinity_image,exception);
7738  (void) RemapImage(resource_info->quantize_info,image,
7739  affinity_image);
7740  }
7741  XGetPixelPacket(display,visual_info,map_info,resource_info,image,
7742  pixel);
7743  (void) SetImageStorageClass(image,DirectClass);
7744  affinity_image=DestroyImage(affinity_image);
7745  }
7746  if ((GetLogEventMask() & X11Event) != 0)
7747  {
7748  (void) LogMagickEvent(X11Event,GetMagickModule(),
7749  "Standard Colormap:");
7750  (void) LogMagickEvent(X11Event,GetMagickModule(),
7751  " colormap id: 0x%lx",map_info->colormap);
7752  (void) LogMagickEvent(X11Event,GetMagickModule(),
7753  " red, green, blue max: %lu %lu %lu",map_info->red_max,
7754  map_info->green_max,map_info->blue_max);
7755  (void) LogMagickEvent(X11Event,GetMagickModule(),
7756  " red, green, blue mult: %lu %lu %lu",map_info->red_mult,
7757  map_info->green_mult,map_info->blue_mult);
7758  }
7759  return;
7760  }
7761  if ((visual_info->klass != DirectColor) &&
7762  (visual_info->klass != TrueColor))
7763  if ((image->storage_class == DirectClass) ||
7764  ((int) image->colors > visual_info->colormap_size))
7765  {
7766  QuantizeInfo
7767  quantize_info;
7768 
7769  /*
7770  Image has more colors than the visual supports.
7771  */
7772  quantize_info=(*resource_info->quantize_info);
7773  quantize_info.number_colors=(size_t) visual_info->colormap_size;
7774  (void) QuantizeImage(&quantize_info,image);
7775  }
7776  /*
7777  Free previous and create new colormap.
7778  */
7779  (void) XFreeStandardColormap(display,visual_info,map_info,pixel);
7780  colormap=XDefaultColormap(display,visual_info->screen);
7781  if (visual_info->visual != XDefaultVisual(display,visual_info->screen))
7782  colormap=XCreateColormap(display,XRootWindow(display,visual_info->screen),
7783  visual_info->visual,visual_info->klass == DirectColor ?
7784  AllocAll : AllocNone);
7785  if (colormap == (Colormap) NULL)
7786  ThrowXWindowFatalException(ResourceLimitFatalError,"UnableToCreateColormap",
7787  image->filename);
7788  /*
7789  Initialize the map and pixel info structures.
7790  */
7791  XGetMapInfo(visual_info,colormap,map_info);
7792  XGetPixelPacket(display,visual_info,map_info,resource_info,image,pixel);
7793  /*
7794  Allocating colors in server colormap is based on visual class.
7795  */
7796  switch (visual_info->klass)
7797  {
7798  case StaticGray:
7799  case StaticColor:
7800  {
7801  /*
7802  Define Standard Colormap for StaticGray or StaticColor visual.
7803  */
7804  number_colors=image->colors;
7805  colors=(XColor *) AcquireQuantumMemory((size_t)
7806  visual_info->colormap_size,sizeof(*colors));
7807  if (colors == (XColor *) NULL)
7808  ThrowXWindowFatalException(ResourceLimitFatalError,
7809  "UnableToCreateColormap",image->filename);
7810  p=colors;
7811  color.flags=(char) (DoRed | DoGreen | DoBlue);
7812  for (i=0; i < (ssize_t) image->colors; i++)
7813  {
7814  color.red=ScaleQuantumToShort(XRedGamma(image->colormap[i].red));
7815  color.green=ScaleQuantumToShort(XGreenGamma(image->colormap[i].green));
7816  color.blue=ScaleQuantumToShort(XBlueGamma(image->colormap[i].blue));
7817  if (visual_info->klass != StaticColor)
7818  {
7819  gray_value=(unsigned short) XPixelIntensity(&color);
7820  color.red=gray_value;
7821  color.green=gray_value;
7822  color.blue=gray_value;
7823  }
7824  status=XAllocColor(display,colormap,&color);
7825  if (status == False)
7826  {
7827  colormap=XCopyColormapAndFree(display,colormap);
7828  (void) XAllocColor(display,colormap,&color);
7829  }
7830  pixel->pixels[i]=color.pixel;
7831  *p++=color;
7832  }
7833  break;
7834  }
7835  case GrayScale:
7836  case PseudoColor:
7837  {
7838  unsigned int
7839  colormap_type;
7840 
7841  /*
7842  Define Standard Colormap for GrayScale or PseudoColor visual.
7843  */
7844  number_colors=image->colors;
7845  colors=(XColor *) AcquireQuantumMemory((size_t)
7846  visual_info->colormap_size,sizeof(*colors));
7847  if (colors == (XColor *) NULL)
7848  ThrowXWindowFatalException(ResourceLimitFatalError,
7849  "UnableToCreateColormap",image->filename);
7850  /*
7851  Preallocate our GUI colors.
7852  */
7853  (void) XAllocColor(display,colormap,&pixel->foreground_color);
7854  (void) XAllocColor(display,colormap,&pixel->background_color);
7855  (void) XAllocColor(display,colormap,&pixel->border_color);
7856  (void) XAllocColor(display,colormap,&pixel->matte_color);
7857  (void) XAllocColor(display,colormap,&pixel->highlight_color);
7858  (void) XAllocColor(display,colormap,&pixel->shadow_color);
7859  (void) XAllocColor(display,colormap,&pixel->depth_color);
7860  (void) XAllocColor(display,colormap,&pixel->trough_color);
7861  for (i=0; i < MaxNumberPens; i++)
7862  (void) XAllocColor(display,colormap,&pixel->pen_colors[i]);
7863  /*
7864  Determine if image colors will "fit" into X server colormap.
7865  */
7866  colormap_type=resource_info->colormap;
7867  status=XAllocColorCells(display,colormap,MagickFalse,(unsigned long *)
7868  NULL,0,pixel->pixels,(unsigned int) image->colors);
7869  if (status != False)
7870  colormap_type=PrivateColormap;
7871  if (colormap_type == SharedColormap)
7872  {
7873  CacheView
7874  *image_view;
7875 
7876  DiversityPacket
7877  *diversity;
7878 
7879  int
7880  y;
7881 
7882  int
7883  x;
7884 
7885  unsigned short
7886  index;
7887 
7888  XColor
7889  *server_colors;
7890 
7891  /*
7892  Define Standard colormap for shared GrayScale or PseudoColor visual.
7893  */
7894  diversity=(DiversityPacket *) AcquireQuantumMemory(image->colors,
7895  sizeof(*diversity));
7896  if (diversity == (DiversityPacket *) NULL)
7897  ThrowXWindowFatalException(ResourceLimitFatalError,
7898  "UnableToCreateColormap",image->filename);
7899  for (i=0; i < (ssize_t) image->colors; i++)
7900  {
7901  diversity[i].red=image->colormap[i].red;
7902  diversity[i].green=image->colormap[i].green;
7903  diversity[i].blue=image->colormap[i].blue;
7904  diversity[i].index=(unsigned short) i;
7905  diversity[i].count=0;
7906  }
7907  image_view=AcquireAuthenticCacheView(image,exception);
7908  for (y=0; y < (int) image->rows; y++)
7909  {
7910  int
7911  x;
7912 
7913  const PixelPacket
7914  *magick_restrict p;
7915 
7916  p=GetCacheViewAuthenticPixels(image_view,0,(ssize_t) y,
7917  image->columns,1,exception);
7918  if (p == (const PixelPacket *) NULL)
7919  break;
7920  indexes=GetCacheViewAuthenticIndexQueue(image_view);
7921  for (x=(int) image->columns-1; x >= 0; x--)
7922  diversity[(ssize_t) GetPixelIndex(indexes+x)].count++;
7923  }
7924  image_view=DestroyCacheView(image_view);
7925  /*
7926  Sort colors by decreasing intensity.
7927  */
7928  qsort((void *) diversity,image->colors,sizeof(*diversity),
7929  IntensityCompare);
7930  for (i=0; i < (ssize_t) image->colors; )
7931  {
7932  diversity[i].count<<=4; /* increase this colors popularity */
7933  i+=MagickMax((int) (image->colors >> 4),2);
7934  }
7935  diversity[image->colors-1].count<<=4;
7936  qsort((void *) diversity,image->colors,sizeof(*diversity),
7937  PopularityCompare);
7938  /*
7939  Allocate colors.
7940  */
7941  p=colors;
7942  color.flags=(char) (DoRed | DoGreen | DoBlue);
7943  for (i=0; i < (ssize_t) image->colors; i++)
7944  {
7945  index=diversity[i].index;
7946  color.red=
7947  ScaleQuantumToShort(XRedGamma(image->colormap[index].red));
7948  color.green=
7949  ScaleQuantumToShort(XGreenGamma(image->colormap[index].green));
7950  color.blue=
7951  ScaleQuantumToShort(XBlueGamma(image->colormap[index].blue));
7952  if (visual_info->klass != PseudoColor)
7953  {
7954  gray_value=(unsigned short) XPixelIntensity(&color);
7955  color.red=gray_value;
7956  color.green=gray_value;
7957  color.blue=gray_value;
7958  }
7959  status=XAllocColor(display,colormap,&color);
7960  if (status == False)
7961  break;
7962  pixel->pixels[index]=color.pixel;
7963  *p++=color;
7964  }
7965  /*
7966  Read X server colormap.
7967  */
7968  server_colors=(XColor *) AcquireQuantumMemory((size_t)
7969  visual_info->colormap_size,sizeof(*server_colors));
7970  if (server_colors == (XColor *) NULL)
7971  ThrowXWindowFatalException(ResourceLimitFatalError,
7972  "UnableToCreateColormap",image->filename);
7973  for (x=visual_info->colormap_size-1; x >= 0; x--)
7974  server_colors[x].pixel=(size_t) x;
7975  (void) XQueryColors(display,colormap,server_colors,
7976  (int) MagickMin((unsigned int) visual_info->colormap_size,256));
7977  /*
7978  Select remaining colors from X server colormap.
7979  */
7980  for (; i < (ssize_t) image->colors; i++)
7981  {
7982  index=diversity[i].index;
7983  color.red=
7984  ScaleQuantumToShort(XRedGamma(image->colormap[index].red));
7985  color.green=
7986  ScaleQuantumToShort(XGreenGamma(image->colormap[index].green));
7987  color.blue=
7988  ScaleQuantumToShort(XBlueGamma(image->colormap[index].blue));
7989  if (visual_info->klass != PseudoColor)
7990  {
7991  gray_value=(unsigned short) XPixelIntensity(&color);
7992  color.red=gray_value;
7993  color.green=gray_value;
7994  color.blue=gray_value;
7995  }
7996  XBestPixel(display,colormap,server_colors,(unsigned int)
7997  visual_info->colormap_size,&color);
7998  pixel->pixels[index]=color.pixel;
7999  *p++=color;
8000  }
8001  if ((int) image->colors < visual_info->colormap_size)
8002  {
8003  /*
8004  Fill up colors array-- more choices for pen colors.
8005  */
8006  retain_colors=MagickMin((unsigned int)
8007  (visual_info->colormap_size-image->colors),256);
8008  for (i=0; i < (ssize_t) retain_colors; i++)
8009  *p++=server_colors[i];
8010  number_colors+=retain_colors;
8011  }
8012  server_colors=(XColor *) RelinquishMagickMemory(server_colors);
8013  diversity=(DiversityPacket *) RelinquishMagickMemory(diversity);
8014  break;
8015  }
8016  /*
8017  Define Standard colormap for private GrayScale or PseudoColor visual.
8018  */
8019  if (status == False)
8020  {
8021  /*
8022  Not enough colormap entries in the colormap-- Create a new colormap.
8023  */
8024  colormap=XCreateColormap(display,
8025  XRootWindow(display,visual_info->screen),visual_info->visual,
8026  AllocNone);
8027  if (colormap == (Colormap) NULL)
8028  ThrowXWindowFatalException(ResourceLimitFatalError,
8029  "UnableToCreateColormap",image->filename);
8030  map_info->colormap=colormap;
8031  if ((int) image->colors < visual_info->colormap_size)
8032  {
8033  /*
8034  Retain colors from the default colormap to help lessens the
8035  effects of colormap flashing.
8036  */
8037  retain_colors=MagickMin((unsigned int)
8038  (visual_info->colormap_size-image->colors),256);
8039  p=colors+image->colors;
8040  for (i=0; i < (ssize_t) retain_colors; i++)
8041  {
8042  p->pixel=(unsigned long) i;
8043  p++;
8044  }
8045  (void) XQueryColors(display,
8046  XDefaultColormap(display,visual_info->screen),
8047  colors+image->colors,(int) retain_colors);
8048  /*
8049  Transfer colors from default to private colormap.
8050  */
8051  (void) XAllocColorCells(display,colormap,MagickFalse,
8052  (unsigned long *) NULL,0,pixel->pixels,(unsigned int)
8053  retain_colors);
8054  p=colors+image->colors;
8055  for (i=0; i < (ssize_t) retain_colors; i++)
8056  {
8057  p->pixel=pixel->pixels[i];
8058  p++;
8059  }
8060  (void) XStoreColors(display,colormap,colors+image->colors,
8061  (int) retain_colors);
8062  number_colors+=retain_colors;
8063  }
8064  (void) XAllocColorCells(display,colormap,MagickFalse,
8065  (unsigned long *) NULL,0,pixel->pixels,(unsigned int)
8066  image->colors);
8067  }
8068  /*
8069  Store the image colormap.
8070  */
8071  p=colors;
8072  color.flags=(char) (DoRed | DoGreen | DoBlue);
8073  for (i=0; i < (ssize_t) image->colors; i++)
8074  {
8075  color.red=ScaleQuantumToShort(XRedGamma(image->colormap[i].red));
8076  color.green=ScaleQuantumToShort(XGreenGamma(image->colormap[i].green));
8077  color.blue=ScaleQuantumToShort(XBlueGamma(image->colormap[i].blue));
8078  if (visual_info->klass != PseudoColor)
8079  {
8080  gray_value=(unsigned short) XPixelIntensity(&color);
8081  color.red=gray_value;
8082  color.green=gray_value;
8083  color.blue=gray_value;
8084  }
8085  color.pixel=pixel->pixels[i];
8086  *p++=color;
8087  }
8088  (void) XStoreColors(display,colormap,colors,(int) image->colors);
8089  break;
8090  }
8091  case TrueColor:
8092  case DirectColor:
8093  default:
8094  {
8095  MagickBooleanType
8096  linear_colormap;
8097 
8098  /*
8099  Define Standard Colormap for TrueColor or DirectColor visual.
8100  */
8101  number_colors=(unsigned int) ((map_info->red_max*map_info->red_mult)+
8102  (map_info->green_max*map_info->green_mult)+
8103  (map_info->blue_max*map_info->blue_mult)+1);
8104  linear_colormap=(number_colors > 4096) ||
8105  (((int) (map_info->red_max+1) == visual_info->colormap_size) &&
8106  ((int) (map_info->green_max+1) == visual_info->colormap_size) &&
8107  ((int) (map_info->blue_max+1) == visual_info->colormap_size)) ?
8108  MagickTrue : MagickFalse;
8109  if (linear_colormap != MagickFalse)
8110  number_colors=(size_t) visual_info->colormap_size;
8111  /*
8112  Allocate color array.
8113  */
8114  colors=(XColor *) AcquireQuantumMemory(number_colors,sizeof(*colors));
8115  if (colors == (XColor *) NULL)
8116  ThrowXWindowFatalException(ResourceLimitFatalError,
8117  "UnableToCreateColormap",image->filename);
8118  /*
8119  Initialize linear color ramp.
8120  */
8121  p=colors;
8122  color.flags=(char) (DoRed | DoGreen | DoBlue);
8123  if (linear_colormap != MagickFalse)
8124  for (i=0; i < (ssize_t) number_colors; i++)
8125  {
8126  color.blue=(unsigned short) 0;
8127  if (map_info->blue_max != 0)
8128  color.blue=(unsigned short) ((size_t)
8129  ((65535L*(i % map_info->green_mult))/map_info->blue_max));
8130  color.green=color.blue;
8131  color.red=color.blue;
8132  color.pixel=XStandardPixel(map_info,&color);
8133  *p++=color;
8134  }
8135  else
8136  for (i=0; i < (ssize_t) number_colors; i++)
8137  {
8138  color.red=(unsigned short) 0;
8139  if (map_info->red_max != 0)
8140  color.red=(unsigned short) ((size_t)
8141  ((65535L*(i/map_info->red_mult))/map_info->red_max));
8142  color.green=(unsigned int) 0;
8143  if (map_info->green_max != 0)
8144  color.green=(unsigned short) ((size_t)
8145  ((65535L*((i/map_info->green_mult) % (map_info->green_max+1)))/
8146  map_info->green_max));
8147  color.blue=(unsigned short) 0;
8148  if (map_info->blue_max != 0)
8149  color.blue=(unsigned short) ((size_t)
8150  ((65535L*(i % map_info->green_mult))/map_info->blue_max));
8151  color.pixel=XStandardPixel(map_info,&color);
8152  *p++=color;
8153  }
8154  if ((visual_info->klass == DirectColor) &&
8155  (colormap != XDefaultColormap(display,visual_info->screen)))
8156  (void) XStoreColors(display,colormap,colors,(int) number_colors);
8157  else
8158  for (i=0; i < (ssize_t) number_colors; i++)
8159  (void) XAllocColor(display,colormap,&colors[i]);
8160  break;
8161  }
8162  }
8163  if ((visual_info->klass != DirectColor) &&
8164  (visual_info->klass != TrueColor))
8165  {
8166  /*
8167  Set foreground, background, border, etc. pixels.
8168  */
8169  XBestPixel(display,colormap,colors,(unsigned int) number_colors,
8170  &pixel->foreground_color);
8171  XBestPixel(display,colormap,colors,(unsigned int) number_colors,
8172  &pixel->background_color);
8173  if (pixel->background_color.pixel == pixel->foreground_color.pixel)
8174  {
8175  /*
8176  Foreground and background colors must differ.
8177  */
8178  pixel->background_color.red=(~pixel->foreground_color.red);
8179  pixel->background_color.green=
8180  (~pixel->foreground_color.green);
8181  pixel->background_color.blue=
8182  (~pixel->foreground_color.blue);
8183  XBestPixel(display,colormap,colors,(unsigned int) number_colors,
8184  &pixel->background_color);
8185  }
8186  XBestPixel(display,colormap,colors,(unsigned int) number_colors,
8187  &pixel->border_color);
8188  XBestPixel(display,colormap,colors,(unsigned int) number_colors,
8189  &pixel->matte_color);
8190  XBestPixel(display,colormap,colors,(unsigned int) number_colors,
8191  &pixel->highlight_color);
8192  XBestPixel(display,colormap,colors,(unsigned int) number_colors,
8193  &pixel->shadow_color);
8194  XBestPixel(display,colormap,colors,(unsigned int) number_colors,
8195  &pixel->depth_color);
8196  XBestPixel(display,colormap,colors,(unsigned int) number_colors,
8197  &pixel->trough_color);
8198  for (i=0; i < MaxNumberPens; i++)
8199  {
8200  XBestPixel(display,colormap,colors,(unsigned int) number_colors,
8201  &pixel->pen_colors[i]);
8202  pixel->pixels[image->colors+i]=pixel->pen_colors[i].pixel;
8203  }
8204  pixel->colors=(ssize_t) (image->colors+MaxNumberPens);
8205  }
8206  colors=(XColor *) RelinquishMagickMemory(colors);
8207  if ((GetLogEventMask() & X11Event) != 0)
8208  {
8209  (void) LogMagickEvent(X11Event,GetMagickModule(),"Standard Colormap:");
8210  (void) LogMagickEvent(X11Event,GetMagickModule()," colormap id: 0x%lx",
8211  map_info->colormap);
8212  (void) LogMagickEvent(X11Event,GetMagickModule(),
8213  " red, green, blue max: %lu %lu %lu",map_info->red_max,
8214  map_info->green_max,map_info->blue_max);
8215  (void) LogMagickEvent(X11Event,GetMagickModule(),
8216  " red, green, blue mult: %lu %lu %lu",map_info->red_mult,
8217  map_info->green_mult,map_info->blue_mult);
8218  }
8219 }
8220 
8221 /*
8222 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8223 % %
8224 % %
8225 % %
8226 % X M a k e W i n d o w %
8227 % %
8228 % %
8229 % %
8230 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8231 %
8232 % XMakeWindow() creates an X11 window.
8233 %
8234 % The format of the XMakeWindow method is:
8235 %
8236 % void XMakeWindow(Display *display,Window parent,char **argv,int argc,
8237 % XClassHint *class_hint,XWMHints *manager_hints,
8238 % XWindowInfo *window_info)
8239 %
8240 % A description of each parameter follows:
8241 %
8242 % o display: Specifies a connection to an X server; returned from
8243 % XOpenDisplay.
8244 %
8245 % o parent: Specifies the parent window_info.
8246 %
8247 % o argv: Specifies the application's argument list.
8248 %
8249 % o argc: Specifies the number of arguments.
8250 %
8251 % o class_hint: Specifies a pointer to a X11 XClassHint structure.
8252 %
8253 % o manager_hints: Specifies a pointer to a X11 XWMHints structure.
8254 %
8255 % o window_info: Specifies a pointer to a X11 XWindowInfo structure.
8256 %
8257 */
8258 MagickExport void XMakeWindow(Display *display,Window parent,char **argv,
8259  int argc,XClassHint *class_hint,XWMHints *manager_hints,
8260  XWindowInfo *window_info)
8261 {
8262 #define MinWindowSize 64
8263 
8264  Atom
8265  atom_list[2];
8266 
8267  int
8268  gravity;
8269 
8270  static XTextProperty
8271  icon_name,
8272  window_name;
8273 
8274  Status
8275  status;
8276 
8277  XSizeHints
8278  *size_hints;
8279 
8280  /*
8281  Set window info hints.
8282  */
8283  assert(display != (Display *) NULL);
8284  assert(window_info != (XWindowInfo *) NULL);
8285  if (IsEventLogging() != MagickFalse)
8286  (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
8287  size_hints=XAllocSizeHints();
8288  if (size_hints == (XSizeHints *) NULL)
8289  ThrowXWindowFatalException(XServerFatalError,"UnableToMakeXWindow",argv[0]);
8290  size_hints->flags=(int) window_info->flags;
8291  size_hints->x=window_info->x;
8292  size_hints->y=window_info->y;
8293  size_hints->width=(int) window_info->width;
8294  size_hints->height=(int) window_info->height;
8295  if (window_info->immutable != MagickFalse)
8296  {
8297  /*
8298  Window size cannot be changed.
8299  */
8300  size_hints->min_width=size_hints->width;
8301  size_hints->min_height=size_hints->height;
8302  size_hints->max_width=size_hints->width;
8303  size_hints->max_height=size_hints->height;
8304  size_hints->flags|=PMinSize;
8305  size_hints->flags|=PMaxSize;
8306  }
8307  else
8308  {
8309  /*
8310  Window size can be changed.
8311  */
8312  size_hints->min_width=(int) window_info->min_width;
8313  size_hints->min_height=(int) window_info->min_height;
8314  size_hints->flags|=PResizeInc;
8315  size_hints->width_inc=(int) window_info->width_inc;
8316  size_hints->height_inc=(int) window_info->height_inc;
8317 #if !defined(PRE_R4_ICCCM)
8318  size_hints->flags|=PBaseSize;
8319  size_hints->base_width=size_hints->width_inc;
8320  size_hints->base_height=size_hints->height_inc;
8321 #endif
8322  }
8323  gravity=NorthWestGravity;
8324  if (window_info->geometry != (char *) NULL)
8325  {
8326  char
8327  default_geometry[MaxTextExtent],
8328  geometry[MaxTextExtent];
8329 
8330  int
8331  flags;
8332 
8333  char
8334  *p;
8335 
8336  /*
8337  User specified geometry.
8338  */
8339  (void) FormatLocaleString(default_geometry,MaxTextExtent,"%dx%d",
8340  size_hints->width,size_hints->height);
8341  (void) CopyMagickString(geometry,window_info->geometry,MaxTextExtent);
8342  p=geometry;
8343  while (strlen(p) != 0)
8344  {
8345  if ((isspace((int) ((unsigned char) *p)) == 0) && (*p != '%'))
8346  p++;
8347  else
8348  (void) memmove(p,p+1,MaxTextExtent-(p-geometry));
8349  }
8350  flags=XWMGeometry(display,window_info->screen,geometry,default_geometry,
8351  window_info->border_width,size_hints,&size_hints->x,&size_hints->y,
8352  &size_hints->width,&size_hints->height,&gravity);
8353  if ((flags & WidthValue) && (flags & HeightValue))
8354  size_hints->flags|=USSize;
8355  if ((flags & XValue) && (flags & YValue))
8356  {
8357  size_hints->flags|=USPosition;
8358  window_info->x=size_hints->x;
8359  window_info->y=size_hints->y;
8360  }
8361  }
8362 #if !defined(PRE_R4_ICCCM)
8363  size_hints->win_gravity=gravity;
8364  size_hints->flags|=PWinGravity;
8365 #endif
8366  if (window_info->id == (Window) NULL)
8367  window_info->id=XCreateWindow(display,parent,window_info->x,window_info->y,
8368  (unsigned int) size_hints->width,(unsigned int) size_hints->height,
8369  window_info->border_width,(int) window_info->depth,InputOutput,
8370  window_info->visual,(unsigned long) window_info->mask,
8371  &window_info->attributes);
8372  else
8373  {
8374  MagickStatusType
8375  mask;
8376 
8377  XEvent
8378  sans_event;
8379 
8380  XWindowChanges
8381  window_changes;
8382 
8383  /*
8384  Window already exists; change relevant attributes.
8385  */
8386  (void) XChangeWindowAttributes(display,window_info->id,(unsigned long)
8387  window_info->mask,&window_info->attributes);
8388  mask=ConfigureNotify;
8389  while (XCheckTypedWindowEvent(display,window_info->id,(int) mask,&sans_event)) ;
8390  window_changes.x=window_info->x;
8391  window_changes.y=window_info->y;
8392  window_changes.width=(int) window_info->width;
8393  window_changes.height=(int) window_info->height;
8394  mask=(MagickStatusType) (CWWidth | CWHeight);
8395  if (window_info->flags & USPosition)
8396  mask|=CWX | CWY;
8397  (void) XReconfigureWMWindow(display,window_info->id,window_info->screen,
8398  mask,&window_changes);
8399  }
8400  if (window_info->id == (Window) NULL)
8401  ThrowXWindowFatalException(XServerFatalError,"UnableToCreateWindow",
8402  window_info->name);
8403  status=XStringListToTextProperty(&window_info->name,1,&window_name);
8404  if (status == False)
8405  ThrowXWindowFatalException(XServerFatalError,"UnableToCreateTextProperty",
8406  window_info->name);
8407  status=XStringListToTextProperty(&window_info->icon_name,1,&icon_name);
8408  if (status == False)
8409  ThrowXWindowFatalException(XServerFatalError,"UnableToCreateTextProperty",
8410  window_info->icon_name);
8411  if (window_info->icon_geometry != (char *) NULL)
8412  {
8413  int
8414  flags,
8415  height,
8416  width;
8417 
8418  /*
8419  User specified icon geometry.
8420  */
8421  size_hints->flags|=USPosition;
8422  flags=XWMGeometry(display,window_info->screen,window_info->icon_geometry,
8423  (char *) NULL,0,size_hints,&manager_hints->icon_x,
8424  &manager_hints->icon_y,&width,&height,&gravity);
8425  if ((flags & XValue) && (flags & YValue))
8426  manager_hints->flags|=IconPositionHint;
8427  }
8428  XSetWMProperties(display,window_info->id,&window_name,&icon_name,argv,argc,
8429  size_hints,manager_hints,class_hint);
8430  if (window_name.value != (void *) NULL)
8431  {
8432  (void) XFree((void *) window_name.value);
8433  window_name.value=(unsigned char *) NULL;
8434  window_name.nitems=0;
8435  }
8436  if (icon_name.value != (void *) NULL)
8437  {
8438  (void) XFree((void *) icon_name.value);
8439  icon_name.value=(unsigned char *) NULL;
8440  icon_name.nitems=0;
8441  }
8442  atom_list[0]=XInternAtom(display,"WM_DELETE_WINDOW",MagickFalse);
8443  atom_list[1]=XInternAtom(display,"WM_TAKE_FOCUS",MagickFalse);
8444  (void) XSetWMProtocols(display,window_info->id,atom_list,2);
8445  (void) XFree((void *) size_hints);
8446  if (window_info->shape != MagickFalse)
8447  {
8448 #if defined(MAGICKCORE_HAVE_SHAPE)
8449  int
8450  error_base,
8451  event_base;
8452 
8453  /*
8454  Can we apply a non-rectangular shaping mask?
8455  */
8456  error_base=0;
8457  event_base=0;
8458  if (XShapeQueryExtension(display,&error_base,&event_base) == 0)
8459  window_info->shape=MagickFalse;
8460 #else
8461  window_info->shape=MagickFalse;
8462 #endif
8463  }
8464  window_info->shape=MagickFalse; /* Fedora 30 has a broken shape extention */
8465  if (window_info->shared_memory != MagickFalse)
8466  {
8467 #if defined(MAGICKCORE_HAVE_SHARED_MEMORY)
8468  /*
8469  Can we use shared memory with this window?
8470  */
8471  if (XShmQueryExtension(display) == 0)
8472  window_info->shared_memory=MagickFalse;
8473 #else
8474  window_info->shared_memory=MagickFalse;
8475 #endif
8476  }
8477  window_info->image=NewImageList();
8478  window_info->destroy=MagickFalse;
8479 }
8480 
8481 /*
8482 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8483 % %
8484 % %
8485 % %
8486 % X M a g i c k P r o g r e s s M o n i t o r %
8487 % %
8488 % %
8489 % %
8490 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8491 %
8492 % XMagickProgressMonitor() displays the progress a task is making in
8493 % completing a task.
8494 %
8495 % The format of the XMagickProgressMonitor method is:
8496 %
8497 % void XMagickProgressMonitor(const char *task,
8498 % const MagickOffsetType quantum,const MagickSizeType span,
8499 % void *client_data)
8500 %
8501 % A description of each parameter follows:
8502 %
8503 % o task: Identifies the task in progress.
8504 %
8505 % o quantum: Specifies the quantum position within the span which represents
8506 % how much progress has been made in completing a task.
8507 %
8508 % o span: Specifies the span relative to completing a task.
8509 %
8510 % o client_data: Pointer to any client data.
8511 %
8512 */
8513 
8514 static const char *GetLocaleMonitorMessage(const char *text)
8515 {
8516  char
8517  message[MaxTextExtent],
8518  tag[MaxTextExtent];
8519 
8520  const char
8521  *locale_message;
8522 
8523  char
8524  *p;
8525 
8526  (void) CopyMagickString(tag,text,MaxTextExtent);
8527  p=strrchr(tag,'/');
8528  if (p != (char *) NULL)
8529  *p='\0';
8530  (void) FormatLocaleString(message,MaxTextExtent,"Monitor/%s",tag);
8531  locale_message=GetLocaleMessage(message);
8532  if (locale_message == message)
8533  return(text);
8534  return(locale_message);
8535 }
8536 
8537 MagickExport MagickBooleanType XMagickProgressMonitor(const char *tag,
8538  const MagickOffsetType quantum,const MagickSizeType span,
8539  void *magick_unused(client_data))
8540 {
8541  XWindows
8542  *windows;
8543 
8544  magick_unreferenced(client_data);
8545 
8546  windows=XSetWindows((XWindows *) ~0);
8547  if (windows == (XWindows *) NULL)
8548  return(MagickTrue);
8549  if (windows->info.mapped != MagickFalse)
8550  XProgressMonitorWidget(windows->display,windows,
8551  GetLocaleMonitorMessage(tag),quantum,span);
8552  return(MagickTrue);
8553 }
8554 
8555 /*
8556 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8557 % %
8558 % %
8559 % %
8560 % X Q u e r y C o l o r D a t a b a s e %
8561 % %
8562 % %
8563 % %
8564 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8565 %
8566 % XQueryColorDatabase() looks up a RGB values for a color given in the target
8567 % string.
8568 %
8569 % The format of the XQueryColorDatabase method is:
8570 %
8571 % MagickBooleanType XQueryColorDatabase(const char *target,XColor *color)
8572 %
8573 % A description of each parameter follows:
8574 %
8575 % o target: Specifies the color to lookup in the X color database.
8576 %
8577 % o color: A pointer to an PixelPacket structure. The RGB value of the target
8578 % color is returned as this value.
8579 %
8580 */
8581 MagickExport MagickBooleanType XQueryColorDatabase(const char *target,
8582  XColor *color)
8583 {
8584  Colormap
8585  colormap;
8586 
8587  static Display
8588  *display = (Display *) NULL;
8589 
8590  Status
8591  status;
8592 
8593  XColor
8594  xcolor;
8595 
8596  /*
8597  Initialize color return value.
8598  */
8599  assert(color != (XColor *) NULL);
8600  color->red=0;
8601  color->green=0;
8602  color->blue=0;
8603  color->flags=(char) (DoRed | DoGreen | DoBlue);
8604  if ((target == (char *) NULL) || (*target == '\0'))
8605  target="#ffffffffffff";
8606  /*
8607  Let the X server define the color for us.
8608  */
8609  if (display == (Display *) NULL)
8610  display=XOpenDisplay((char *) NULL);
8611  if (display == (Display *) NULL)
8612  ThrowXWindowFatalException(XServerError,"ColorIsNotKnownToServer",target);
8613  colormap=XDefaultColormap(display,XDefaultScreen(display));
8614  status=XParseColor(display,colormap,(char *) target,&xcolor);
8615  if (status == False)
8616  ThrowXWindowException(XServerError,"ColorIsNotKnownToServer",target)
8617  else
8618  {
8619  color->red=xcolor.red;
8620  color->green=xcolor.green;
8621  color->blue=xcolor.blue;
8622  color->flags=xcolor.flags;
8623  }
8624  return(status != False ? MagickTrue : MagickFalse);
8625 }
8626 
8627 /*
8628 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8629 % %
8630 % %
8631 % %
8632 % X Q u e r y P o s i t i o n %
8633 % %
8634 % %
8635 % %
8636 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8637 %
8638 % XQueryPosition() gets the pointer coordinates relative to a window.
8639 %
8640 % The format of the XQueryPosition method is:
8641 %
8642 % void XQueryPosition(Display *display,const Window window,int *x,int *y)
8643 %
8644 % A description of each parameter follows:
8645 %
8646 % o display: Specifies a connection to an X server; returned from
8647 % XOpenDisplay.
8648 %
8649 % o window: Specifies a pointer to a Window.
8650 %
8651 % o x: Return the x coordinate of the pointer relative to the origin of the
8652 % window.
8653 %
8654 % o y: Return the y coordinate of the pointer relative to the origin of the
8655 % window.
8656 %
8657 */
8658 MagickExport void XQueryPosition(Display *display,const Window window,int *x,int *y)
8659 {
8660  int
8661  x_root,
8662  y_root;
8663 
8664  unsigned int
8665  mask;
8666 
8667  Window
8668  root_window;
8669 
8670  assert(display != (Display *) NULL);
8671  assert(window != (Window) NULL);
8672  assert(x != (int *) NULL);
8673  assert(y != (int *) NULL);
8674  if (IsEventLogging() != MagickFalse)
8675  (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
8676  (void) XQueryPointer(display,window,&root_window,&root_window,&x_root,&y_root,
8677  x,y,&mask);
8678 }
8679 
8680 /*
8681 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8682 % %
8683 % %
8684 % %
8685 % X R e f r e s h W i n d o w %
8686 % %
8687 % %
8688 % %
8689 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8690 %
8691 % XRefreshWindow() refreshes an image in a X window.
8692 %
8693 % The format of the XRefreshWindow method is:
8694 %
8695 % void XRefreshWindow(Display *display,const XWindowInfo *window,
8696 % const XEvent *event)
8697 %
8698 % A description of each parameter follows:
8699 %
8700 % o display: Specifies a connection to an X server; returned from
8701 % XOpenDisplay.
8702 %
8703 % o window: Specifies a pointer to a XWindowInfo structure.
8704 %
8705 % o event: Specifies a pointer to a XEvent structure. If it is NULL,
8706 % the entire image is refreshed.
8707 %
8708 */
8709 MagickExport void XRefreshWindow(Display *display,const XWindowInfo *window,
8710  const XEvent *event)
8711 {
8712  int
8713  x,
8714  y;
8715 
8716  unsigned int
8717  height,
8718  width;
8719 
8720  assert(display != (Display *) NULL);
8721  assert(window != (XWindowInfo *) NULL);
8722  if (IsEventLogging() != MagickFalse)
8723  (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
8724  if (window->ximage == (XImage *) NULL)
8725  return;
8726  if (event != (XEvent *) NULL)
8727  {
8728  /*
8729  Determine geometry from expose event.
8730  */
8731  x=event->xexpose.x;
8732  y=event->xexpose.y;
8733  width=(unsigned int) event->xexpose.width;
8734  height=(unsigned int) event->xexpose.height;
8735  }
8736  else
8737  {
8738  XEvent
8739  sans_event;
8740 
8741  /*
8742  Refresh entire window; discard outstanding expose events.
8743  */
8744  x=0;
8745  y=0;
8746  width=window->width;
8747  height=window->height;
8748  while (XCheckTypedWindowEvent(display,window->id,Expose,&sans_event)) ;
8749  if (window->matte_pixmap != (Pixmap) NULL)
8750  {
8751 #if defined(MAGICKCORE_HAVE_SHAPE)
8752  if (window->shape != MagickFalse)
8753  XShapeCombineMask(display,window->id,ShapeBounding,0,0,
8754  window->matte_pixmap,ShapeSet);
8755 #endif
8756  }
8757  }
8758  /*
8759  Check boundary conditions.
8760  */
8761  if ((window->ximage->width-(x+window->x)) < (int) width)
8762  width=(unsigned int) (window->ximage->width-(x+window->x));
8763  if ((window->ximage->height-(y+window->y)) < (int) height)
8764  height=(unsigned int) (window->ximage->height-(y+window->y));
8765  /*
8766  Refresh image.
8767  */
8768  if (window->matte_pixmap != (Pixmap) NULL)
8769  (void) XSetClipMask(display,window->annotate_context,window->matte_pixmap);
8770  if (window->pixmap != (Pixmap) NULL)
8771  {
8772  if (window->depth > 1)
8773  (void) XCopyArea(display,window->pixmap,window->id,
8774  window->annotate_context,x+window->x,y+window->y,width,height,x,y);
8775  else
8776  (void) XCopyPlane(display,window->pixmap,window->id,
8777  window->highlight_context,x+window->x,y+window->y,width,height,x,y,
8778  1L);
8779  }
8780  else
8781  {
8782 #if defined(MAGICKCORE_HAVE_SHARED_MEMORY)
8783  if (window->shared_memory)
8784  (void) XShmPutImage(display,window->id,window->annotate_context,
8785  window->ximage,x+window->x,y+window->y,x,y,width,height,MagickTrue);
8786 #endif
8787  if (window->shared_memory == MagickFalse)
8788  (void) XPutImage(display,window->id,window->annotate_context,
8789  window->ximage,x+window->x,y+window->y,x,y,width,height);
8790  }
8791  if (window->matte_pixmap != (Pixmap) NULL)
8792  (void) XSetClipMask(display,window->annotate_context,None);
8793  (void) XFlush(display);
8794 }
8795 
8796 /*
8797 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8798 % %
8799 % %
8800 % %
8801 % X R e m o t e C o m m a n d %
8802 % %
8803 % %
8804 % %
8805 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8806 %
8807 % XRemoteCommand() forces a remote display(1) to display the specified
8808 % image filename.
8809 %
8810 % The format of the XRemoteCommand method is:
8811 %
8812 % MagickBooleanType XRemoteCommand(Display *display,const char *window,
8813 % const char *filename)
8814 %
8815 % A description of each parameter follows:
8816 %
8817 % o display: Specifies a connection to an X server; returned from
8818 % XOpenDisplay.
8819 %
8820 % o window: Specifies the name or id of an X window.
8821 %
8822 % o filename: the name of the image filename to display.
8823 %
8824 */
8825 MagickExport MagickBooleanType XRemoteCommand(Display *display,
8826  const char *window,const char *filename)
8827 {
8828  Atom
8829  remote_atom;
8830 
8831  Window
8832  remote_window,
8833  root_window;
8834 
8835  assert(filename != (char *) NULL);
8836  if (IsEventLogging() != MagickFalse)
8837  (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",filename);
8838  if (display == (Display *) NULL)
8839  display=XOpenDisplay((char *) NULL);
8840  if (display == (Display *) NULL)
8841  {
8842  ThrowXWindowException(XServerError,"UnableToOpenXServer",filename);
8843  return(MagickFalse);
8844  }
8845  remote_atom=XInternAtom(display,"IM_PROTOCOLS",MagickFalse);
8846  remote_window=(Window) NULL;
8847  root_window=XRootWindow(display,XDefaultScreen(display));
8848  if (window != (char *) NULL)
8849  {
8850  /*
8851  Search window hierarchy and identify any clients by name or ID.
8852  */
8853  if (isdigit((int) ((unsigned char) *window)) != 0)
8854  remote_window=XWindowByID(display,root_window,(Window)
8855  strtol((char *) window,(char **) NULL,0));
8856  if (remote_window == (Window) NULL)
8857  remote_window=XWindowByName(display,root_window,window);
8858  }
8859  if (remote_window == (Window) NULL)
8860  remote_window=XWindowByProperty(display,root_window,remote_atom);
8861  if (remote_window == (Window) NULL)
8862  {
8863  ThrowXWindowException(XServerError,"UnableToConnectToRemoteDisplay",
8864  filename);
8865  return(MagickFalse);
8866  }
8867  /*
8868  Send remote command.
8869  */
8870  remote_atom=XInternAtom(display,"IM_REMOTE_COMMAND",MagickFalse);
8871  (void) XChangeProperty(display,remote_window,remote_atom,XA_STRING,8,
8872  PropModeReplace,(unsigned char *) filename,(int) strlen(filename));
8873  (void) XSync(display,MagickFalse);
8874  return(MagickTrue);
8875 }
8876 
8877 /*
8878 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8879 % %
8880 % %
8881 % %
8882 + X R e n d e r I m a g e %
8883 % %
8884 % %
8885 % %
8886 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8887 %
8888 % XRenderImage() renders text on the image with an X11 font. It also returns
8889 % the bounding box of the text relative to the image.
8890 %
8891 % The format of the XRenderImage method is:
8892 %
8893 % MagickBooleanType XRenderImage(Image *image,DrawInfo *draw_info,
8894 % const PointInfo *offset,TypeMetric *metrics)
8895 %
8896 % A description of each parameter follows:
8897 %
8898 % o image: the image.
8899 %
8900 % o draw_info: the draw info.
8901 %
8902 % o offset: (x,y) location of text relative to image.
8903 %
8904 % o metrics: bounding box of text.
8905 %
8906 */
8907 MagickPrivate MagickBooleanType XRenderImage(Image *image,
8908  const DrawInfo *draw_info,const PointInfo *offset,TypeMetric *metrics)
8909 {
8910  const char
8911  *client_name;
8912 
8913  DrawInfo
8914  cache_info;
8915 
8916  Display
8917  *display = (Display *) NULL;
8918 
8919  ImageInfo
8920  *image_info;
8921 
8922  MagickBooleanType
8923  status;
8924 
8925  size_t
8926  height,
8927  width;
8928 
8929  XAnnotateInfo
8930  annotate_info;
8931 
8932  XFontStruct
8933  *font_info;
8934 
8935  XPixelInfo
8936  pixel;
8937 
8938  XResourceInfo
8939  resource_info;
8940 
8941  XrmDatabase
8942  resource_database;
8943 
8944  XStandardColormap
8945  *map_info;
8946 
8947  XVisualInfo
8948  *visual_info;
8949 
8950  /*
8951  Open X server connection.
8952  */
8953  display=XOpenDisplay(draw_info->server_name);
8954  if (display == (Display *) NULL)
8955  {
8956  ThrowXWindowException(XServerError,"UnableToOpenXServer",
8957  draw_info->server_name);
8958  return(MagickFalse);
8959  }
8960  /*
8961  Get user defaults from X resource database.
8962  */
8963  (void) XSetErrorHandler(XError);
8964  image_info=AcquireImageInfo();
8965  client_name=GetClientName();
8966  resource_database=XGetResourceDatabase(display,client_name);
8967  XGetResourceInfo(image_info,resource_database,client_name,&resource_info);
8968  resource_info.close_server=MagickFalse;
8969  resource_info.colormap=PrivateColormap;
8970  resource_info.font=AcquireString(draw_info->font);
8971  resource_info.background_color=AcquireString("#ffffffffffff");
8972  resource_info.foreground_color=AcquireString("#000000000000");
8973  map_info=XAllocStandardColormap();
8974  visual_info=(XVisualInfo *) NULL;
8975  font_info=(XFontStruct *) NULL;
8976  pixel.pixels=(unsigned long *) NULL;
8977  if (map_info == (XStandardColormap *) NULL)
8978  {
8979  ThrowXWindowException(ResourceLimitError,"MemoryAllocationFailed",
8980  image->filename);
8981  return(MagickFalse);
8982  }
8983  /*
8984  Initialize visual info.
8985  */
8986  visual_info=XBestVisualInfo(display,map_info,&resource_info);
8987  if (visual_info == (XVisualInfo *) NULL)
8988  {
8989  XFreeResources(display,visual_info,map_info,&pixel,font_info,
8990  &resource_info,(XWindowInfo *) NULL);
8991  ThrowXWindowException(XServerError,"UnableToGetVisual",image->filename);
8992  return(MagickFalse);
8993  }
8994  map_info->colormap=(Colormap) NULL;
8995  /*
8996  Initialize Standard Colormap info.
8997  */
8998  XGetMapInfo(visual_info,XDefaultColormap(display,visual_info->screen),
8999  map_info);
9000  XGetPixelPacket(display,visual_info,map_info,&resource_info,(Image *) NULL,
9001  &pixel);
9002  pixel.annotate_context=XDefaultGC(display,visual_info->screen);
9003  /*
9004  Initialize font info.
9005  */
9006  font_info=XBestFont(display,&resource_info,MagickFalse);
9007  if (font_info == (XFontStruct *) NULL)
9008  {
9009  XFreeResources(display,visual_info,map_info,&pixel,font_info,
9010  &resource_info,(XWindowInfo *) NULL);
9011  ThrowXWindowException(XServerError,"UnableToLoadFont",draw_info->font);
9012  return(MagickFalse);
9013  }
9014  cache_info=(*draw_info);
9015  /*
9016  Initialize annotate info.
9017  */
9018  XGetAnnotateInfo(&annotate_info);
9019  annotate_info.stencil=ForegroundStencil;
9020  if (cache_info.font != draw_info->font)
9021  {
9022  /*
9023  Type name has changed.
9024  */
9025  (void) XFreeFont(display,font_info);
9026  (void) CloneString(&resource_info.font,draw_info->font);
9027  font_info=XBestFont(display,&resource_info,MagickFalse);
9028  if (font_info == (XFontStruct *) NULL)
9029  {
9030  ThrowXWindowException(XServerError,"UnableToLoadFont",
9031  draw_info->font);
9032  return(MagickFalse);
9033  }
9034  }
9035  if (draw_info->debug != MagickFalse)
9036  (void) LogMagickEvent(AnnotateEvent,GetMagickModule(),
9037  "Font %s; pointsize %g",draw_info->font != (char *) NULL ?
9038  draw_info->font : "none",draw_info->pointsize);
9039  cache_info=(*draw_info);
9040  annotate_info.font_info=font_info;
9041  annotate_info.text=(char *) draw_info->text;
9042  annotate_info.width=(unsigned int) XTextWidth(font_info,draw_info->text,(int)
9043  strlen(draw_info->text));
9044  annotate_info.height=(unsigned int) font_info->ascent+font_info->descent;
9045  metrics->pixels_per_em.x=(double) font_info->max_bounds.width;
9046  metrics->pixels_per_em.y=(double) font_info->ascent+font_info->descent;
9047  metrics->ascent=(double) font_info->ascent+4;
9048  metrics->descent=(double) (-font_info->descent);
9049  metrics->width=annotate_info.width/ExpandAffine(&draw_info->affine);
9050  metrics->height=font_info->ascent+font_info->descent;
9051  metrics->max_advance=(double) font_info->max_bounds.width;
9052  metrics->bounds.x1=0.0;
9053  metrics->bounds.y1=metrics->descent;
9054  metrics->bounds.x2=metrics->ascent+metrics->descent;
9055  metrics->bounds.y2=metrics->ascent+metrics->descent;
9056  metrics->underline_position=(-2.0);
9057  metrics->underline_thickness=1.0;
9058  if (draw_info->render == MagickFalse)
9059  return(MagickTrue);
9060  if (draw_info->fill.opacity == TransparentOpacity)
9061  return(MagickTrue);
9062  /*
9063  Render fill color.
9064  */
9065  width=annotate_info.width;
9066  height=annotate_info.height;
9067  if ((draw_info->affine.rx != 0.0) || (draw_info->affine.ry != 0.0))
9068  {
9069  if (((draw_info->affine.sx-draw_info->affine.sy) == 0.0) &&
9070  ((draw_info->affine.rx+draw_info->affine.ry) == 0.0))
9071  annotate_info.degrees=(180.0/MagickPI)*
9072  atan2(draw_info->affine.rx,draw_info->affine.sx);
9073  }
9074  (void) FormatLocaleString(annotate_info.geometry,MaxTextExtent,
9075  "%.20gx%.20g%+.20g%+.20g",(double) width,(double) height,
9076  ceil(offset->x-0.5),ceil(offset->y-metrics->ascent-metrics->descent+
9077  draw_info->interline_spacing-0.5));
9078  pixel.pen_color.red=ScaleQuantumToShort(draw_info->fill.red);
9079  pixel.pen_color.green=ScaleQuantumToShort(draw_info->fill.green);
9080  pixel.pen_color.blue=ScaleQuantumToShort(draw_info->fill.blue);
9081  status=XAnnotateImage(display,&pixel,&annotate_info,image);
9082  if (status == 0)
9083  {
9084  ThrowXWindowException(ResourceLimitError,"MemoryAllocationFailed",
9085  image->filename);
9086  return(MagickFalse);
9087  }
9088  return(MagickTrue);
9089 }
9090 
9091 /*
9092 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9093 % %
9094 % %
9095 % %
9096 % X R e t a i n W i n d o w C o l o r s %
9097 % %
9098 % %
9099 % %
9100 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9101 %
9102 % XRetainWindowColors() sets X11 color resources on a window. This preserves
9103 % the colors associated with an image displayed on the window.
9104 %
9105 % The format of the XRetainWindowColors method is:
9106 %
9107 % void XRetainWindowColors(Display *display,const Window window)
9108 %
9109 % A description of each parameter follows:
9110 %
9111 % o display: Specifies a connection to an X server; returned from
9112 % XOpenDisplay.
9113 %
9114 % o window: Specifies a pointer to a XWindowInfo structure.
9115 %
9116 */
9117 MagickExport void XRetainWindowColors(Display *display,const Window window)
9118 {
9119  Atom
9120  property;
9121 
9122  Pixmap
9123  pixmap;
9124 
9125  /*
9126  Put property on the window.
9127  */
9128  assert(display != (Display *) NULL);
9129  assert(window != (Window) NULL);
9130  if (IsEventLogging() != MagickFalse)
9131  (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
9132  property=XInternAtom(display,"_XSETROOT_ID",MagickFalse);
9133  if (property == (Atom) NULL)
9134  ThrowXWindowFatalException(XServerError,"UnableToCreateProperty",
9135  "_XSETROOT_ID");
9136  pixmap=XCreatePixmap(display,window,1,1,1);
9137  if (pixmap == (Pixmap) NULL)
9138  ThrowXWindowFatalException(XServerError,"UnableToCreateBitmap","");
9139  (void) XChangeProperty(display,window,property,XA_PIXMAP,32,PropModeReplace,
9140  (unsigned char *) &pixmap,1);
9141  (void) XSetCloseDownMode(display,RetainPermanent);
9142 }
9143 
9144 /*
9145 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9146 % %
9147 % %
9148 % %
9149 % X S e l e c t W i n d o w %
9150 % %
9151 % %
9152 % %
9153 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9154 %
9155 % XSelectWindow() allows a user to select a window using the mouse. If the
9156 % mouse moves, a cropping rectangle is drawn and the extents of the rectangle
9157 % is returned in the crop_info structure.
9158 %
9159 % The format of the XSelectWindow function is:
9160 %
9161 % target_window=XSelectWindow(display,crop_info)
9162 %
9163 % A description of each parameter follows:
9164 %
9165 % o window: XSelectWindow returns the window id.
9166 %
9167 % o display: Specifies a pointer to the Display structure; returned from
9168 % XOpenDisplay.
9169 %
9170 % o crop_info: Specifies a pointer to a RectangleInfo structure. It
9171 % contains the extents of any cropping rectangle.
9172 %
9173 */
9174 static Window XSelectWindow(Display *display,RectangleInfo *crop_info)
9175 {
9176 #define MinimumCropArea (unsigned int) 9
9177 
9178  Cursor
9179  target_cursor;
9180 
9181  GC
9182  annotate_context;
9183 
9184  int
9185  presses,
9186  x_offset,
9187  y_offset;
9188 
9189  Status
9190  status;
9191 
9192  Window
9193  root_window,
9194  target_window;
9195 
9196  XEvent
9197  event;
9198 
9199  XGCValues
9200  context_values;
9201 
9202  /*
9203  Initialize graphic context.
9204  */
9205  assert(display != (Display *) NULL);
9206  assert(crop_info != (RectangleInfo *) NULL);
9207  if (IsEventLogging() != MagickFalse)
9208  (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
9209  root_window=XRootWindow(display,XDefaultScreen(display));
9210  context_values.background=XBlackPixel(display,XDefaultScreen(display));
9211  context_values.foreground=XWhitePixel(display,XDefaultScreen(display));
9212  context_values.function=GXinvert;
9213  context_values.plane_mask=
9214  context_values.background ^ context_values.foreground;
9215  context_values.subwindow_mode=IncludeInferiors;
9216  annotate_context=XCreateGC(display,root_window,(size_t) (GCBackground |
9217  GCForeground | GCFunction | GCSubwindowMode),&context_values);
9218  if (annotate_context == (GC) NULL)
9219  return(MagickFalse);
9220  /*
9221  Grab the pointer using target cursor.
9222  */
9223  target_cursor=XMakeCursor(display,root_window,XDefaultColormap(display,
9224  XDefaultScreen(display)),(char * ) "white",(char * ) "black");
9225  status=XGrabPointer(display,root_window,MagickFalse,(unsigned int)
9226  (ButtonPressMask | ButtonReleaseMask | ButtonMotionMask),GrabModeSync,
9227  GrabModeAsync,root_window,target_cursor,CurrentTime);
9228  if (status != GrabSuccess)
9229  ThrowXWindowFatalException(XServerError,"UnableToGrabMouse","");
9230  /*
9231  Select a window.
9232  */
9233  crop_info->width=0;
9234  crop_info->height=0;
9235  presses=0;
9236  target_window=(Window) NULL;
9237  x_offset=0;
9238  y_offset=0;
9239  (void) XGrabServer(display);
9240  do
9241  {
9242  if ((crop_info->width*crop_info->height) >= MinimumCropArea)
9243  (void) XDrawRectangle(display,root_window,annotate_context,
9244  (int) crop_info->x,(int) crop_info->y,(unsigned int) crop_info->width-1,
9245  (unsigned int) crop_info->height-1);
9246  /*
9247  Allow another event.
9248  */
9249  (void) XAllowEvents(display,SyncPointer,CurrentTime);
9250  (void) XWindowEvent(display,root_window,ButtonPressMask |
9251  ButtonReleaseMask | ButtonMotionMask,&event);
9252  if ((crop_info->width*crop_info->height) >= MinimumCropArea)
9253  (void) XDrawRectangle(display,root_window,annotate_context,
9254  (int) crop_info->x,(int) crop_info->y,(unsigned int) crop_info->width-1,
9255  (unsigned int) crop_info->height-1);
9256  switch (event.type)
9257  {
9258  case ButtonPress:
9259  {
9260  target_window=XGetSubwindow(display,event.xbutton.subwindow,
9261  event.xbutton.x,event.xbutton.y);
9262  if (target_window == (Window) NULL)
9263  target_window=root_window;
9264  x_offset=event.xbutton.x_root;
9265  y_offset=event.xbutton.y_root;
9266  crop_info->x=(ssize_t) x_offset;
9267  crop_info->y=(ssize_t) y_offset;
9268  crop_info->width=0;
9269  crop_info->height=0;
9270  presses++;
9271  break;
9272  }
9273  case ButtonRelease:
9274  {
9275  presses--;
9276  break;
9277  }
9278  case MotionNotify:
9279  {
9280  /*
9281  Discard pending button motion events.
9282  */
9283  while (XCheckMaskEvent(display,ButtonMotionMask,&event)) ;
9284  crop_info->x=(ssize_t) event.xmotion.x;
9285  crop_info->y=(ssize_t) event.xmotion.y;
9286  /*
9287  Check boundary conditions.
9288  */
9289  if ((int) crop_info->x < x_offset)
9290  crop_info->width=(size_t) (x_offset-crop_info->x);
9291  else
9292  {
9293  crop_info->width=(size_t) (crop_info->x-x_offset);
9294  crop_info->x=(ssize_t) x_offset;
9295  }
9296  if ((int) crop_info->y < y_offset)
9297  crop_info->height=(size_t) (y_offset-crop_info->y);
9298  else
9299  {
9300  crop_info->height=(size_t) (crop_info->y-y_offset);
9301  crop_info->y=(ssize_t) y_offset;
9302  }
9303  }
9304  default:
9305  break;
9306  }
9307  } while ((target_window == (Window) NULL) || (presses > 0));
9308  (void) XUngrabServer(display);
9309  (void) XUngrabPointer(display,CurrentTime);
9310  (void) XFreeCursor(display,target_cursor);
9311  (void) XFreeGC(display,annotate_context);
9312  if ((crop_info->width*crop_info->height) < MinimumCropArea)
9313  {
9314  crop_info->width=0;
9315  crop_info->height=0;
9316  }
9317  if ((crop_info->width != 0) && (crop_info->height != 0))
9318  target_window=root_window;
9319  return(target_window);
9320 }
9321 
9322 /*
9323 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9324 % %
9325 % %
9326 % %
9327 % X S e t C u r s o r S t a t e %
9328 % %
9329 % %
9330 % %
9331 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9332 %
9333 % XSetCursorState() sets the cursor state to busy, otherwise the cursor are
9334 % reset to their default.
9335 %
9336 % The format of the XXSetCursorState method is:
9337 %
9338 % XSetCursorState(display,windows,const MagickStatusType state)
9339 %
9340 % A description of each parameter follows:
9341 %
9342 % o display: Specifies a connection to an X server; returned from
9343 % XOpenDisplay.
9344 %
9345 % o windows: Specifies a pointer to a XWindows structure.
9346 %
9347 % o state: An unsigned integer greater than 0 sets the cursor state
9348 % to busy, otherwise the cursor are reset to their default.
9349 %
9350 */
9351 MagickExport void XSetCursorState(Display *display,XWindows *windows,
9352  const MagickStatusType state)
9353 {
9354  assert(display != (Display *) NULL);
9355  assert(windows != (XWindows *) NULL);
9356  if (IsEventLogging() != MagickFalse)
9357  (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
9358  if (state)
9359  {
9360  (void) XCheckDefineCursor(display,windows->image.id,
9361  windows->image.busy_cursor);
9362  (void) XCheckDefineCursor(display,windows->pan.id,
9363  windows->pan.busy_cursor);
9364  (void) XCheckDefineCursor(display,windows->magnify.id,
9365  windows->magnify.busy_cursor);
9366  (void) XCheckDefineCursor(display,windows->command.id,
9367  windows->command.busy_cursor);
9368  }
9369  else
9370  {
9371  (void) XCheckDefineCursor(display,windows->image.id,
9372  windows->image.cursor);
9373  (void) XCheckDefineCursor(display,windows->pan.id,windows->pan.cursor);
9374  (void) XCheckDefineCursor(display,windows->magnify.id,
9375  windows->magnify.cursor);
9376  (void) XCheckDefineCursor(display,windows->command.id,
9377  windows->command.cursor);
9378  (void) XCheckDefineCursor(display,windows->command.id,
9379  windows->widget.cursor);
9380  (void) XWithdrawWindow(display,windows->info.id,windows->info.screen);
9381  }
9382  windows->info.mapped=MagickFalse;
9383 }
9384 
9385 /*
9386 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9387 % %
9388 % %
9389 % %
9390 % X S e t W i n d o w s %
9391 % %
9392 % %
9393 % %
9394 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9395 %
9396 % XSetWindows() sets the X windows structure if the windows info is specified.
9397 % Otherwise the current windows structure is returned.
9398 %
9399 % The format of the XSetWindows method is:
9400 %
9401 % XWindows *XSetWindows(XWindows *windows_info)
9402 %
9403 % A description of each parameter follows:
9404 %
9405 % o windows_info: Initialize the Windows structure with this information.
9406 %
9407 */
9408 MagickExport XWindows *XSetWindows(XWindows *windows_info)
9409 {
9410  static XWindows
9411  *windows = (XWindows *) NULL;
9412 
9413  if (windows_info != (XWindows *) ~0)
9414  {
9415  windows=(XWindows *) RelinquishMagickMemory(windows);
9416  windows=windows_info;
9417  }
9418  return(windows);
9419 }
9420 /*
9421 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9422 % %
9423 % %
9424 % %
9425 % X U s e r P r e f e r e n c e s %
9426 % %
9427 % %
9428 % %
9429 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9430 %
9431 % XUserPreferences() saves the preferences in a configuration file in the
9432 % users' home directory.
9433 %
9434 % The format of the XUserPreferences method is:
9435 %
9436 % void XUserPreferences(XResourceInfo *resource_info)
9437 %
9438 % A description of each parameter follows:
9439 %
9440 % o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
9441 %
9442 */
9443 MagickExport void XUserPreferences(XResourceInfo *resource_info)
9444 {
9445 #if defined(X11_PREFERENCES_PATH)
9446  char
9447  cache[MaxTextExtent],
9448  filename[MaxTextExtent],
9449  specifier[MaxTextExtent];
9450 
9451  const char
9452  *client_name,
9453  *value;
9454 
9455  XrmDatabase
9456  preferences_database;
9457 
9458  /*
9459  Save user preferences to the client configuration file.
9460  */
9461  assert(resource_info != (XResourceInfo *) NULL);
9462  client_name=GetClientName();
9463  preferences_database=XrmGetStringDatabase("");
9464  (void) FormatLocaleString(specifier,MaxTextExtent,"%s.backdrop",client_name);
9465  value=resource_info->backdrop ? "True" : "False";
9466  XrmPutStringResource(&preferences_database,specifier,(char *) value);
9467  (void) FormatLocaleString(specifier,MaxTextExtent,"%s.colormap",client_name);
9468  value=resource_info->colormap == SharedColormap ? "Shared" : "Private";
9469  XrmPutStringResource(&preferences_database,specifier,(char *) value);
9470  (void) FormatLocaleString(specifier,MaxTextExtent,"%s.confirmExit",
9471  client_name);
9472  value=resource_info->confirm_exit ? "True" : "False";
9473  XrmPutStringResource(&preferences_database,specifier,(char *) value);
9474  (void) FormatLocaleString(specifier,MaxTextExtent,"%s.confirmEdit",
9475  client_name);
9476  value=resource_info->confirm_edit ? "True" : "False";
9477  XrmPutStringResource(&preferences_database,specifier,(char *) value);
9478  (void) FormatLocaleString(specifier,MaxTextExtent,"%s.displayWarnings",
9479  client_name);
9480  value=resource_info->display_warnings ? "True" : "False";
9481  XrmPutStringResource(&preferences_database,specifier,(char *) value);
9482  (void) FormatLocaleString(specifier,MaxTextExtent,"%s.dither",client_name);
9483  value=resource_info->quantize_info->dither ? "True" : "False";
9484  XrmPutStringResource(&preferences_database,specifier,(char *) value);
9485  (void) FormatLocaleString(specifier,MaxTextExtent,"%s.gammaCorrect",
9486  client_name);
9487  value=resource_info->gamma_correct ? "True" : "False";
9488  XrmPutStringResource(&preferences_database,specifier,(char *) value);
9489  (void) FormatLocaleString(specifier,MaxTextExtent,"%s.undoCache",client_name);
9490  (void) FormatLocaleString(cache,MaxTextExtent,"%.20g",(double)
9491  resource_info->undo_cache);
9492  XrmPutStringResource(&preferences_database,specifier,cache);
9493  (void) FormatLocaleString(specifier,MaxTextExtent,"%s.usePixmap",client_name);
9494  value=resource_info->use_pixmap ? "True" : "False";
9495  XrmPutStringResource(&preferences_database,specifier,(char *) value);
9496  (void) FormatLocaleString(filename,MaxTextExtent,"%s%src",
9497  X11_PREFERENCES_PATH,client_name);
9498  ExpandFilename(filename);
9499  XrmPutFileDatabase(preferences_database,filename);
9500 #endif
9501 }
9502 
9503 /*
9504 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9505 % %
9506 % %
9507 % %
9508 % X V i s u a l C l a s s N a m e %
9509 % %
9510 % %
9511 % %
9512 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9513 %
9514 % XVisualClassName() returns the visual class name as a character string.
9515 %
9516 % The format of the XVisualClassName method is:
9517 %
9518 % char *XVisualClassName(const int visual_class)
9519 %
9520 % A description of each parameter follows:
9521 %
9522 % o visual_type: XVisualClassName returns the visual class as a character
9523 % string.
9524 %
9525 % o class: Specifies the visual class.
9526 %
9527 */
9528 static const char *XVisualClassName(const int visual_class)
9529 {
9530  switch (visual_class)
9531  {
9532  case StaticGray: return("StaticGray");
9533  case GrayScale: return("GrayScale");
9534  case StaticColor: return("StaticColor");
9535  case PseudoColor: return("PseudoColor");
9536  case TrueColor: return("TrueColor");
9537  case DirectColor: return("DirectColor");
9538  }
9539  return("unknown visual class");
9540 }
9541 
9542 /*
9543 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9544 % %
9545 % %
9546 % %
9547 % X W a r n i n g %
9548 % %
9549 % %
9550 % %
9551 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9552 %
9553 % XWarning() displays a warning reason in a Notice widget.
9554 %
9555 % The format of the XWarning method is:
9556 %
9557 % void XWarning(const unsigned int warning,const char *reason,
9558 % const char *description)
9559 %
9560 % A description of each parameter follows:
9561 %
9562 % o warning: Specifies the numeric warning category.
9563 %
9564 % o reason: Specifies the reason to display before terminating the
9565 % program.
9566 %
9567 % o description: Specifies any description to the reason.
9568 %
9569 */
9570 MagickExport void XWarning(const ExceptionType magick_unused(warning),
9571  const char *reason,const char *description)
9572 {
9573  char
9574  text[MaxTextExtent];
9575 
9576  XWindows
9577  *windows;
9578 
9579  magick_unreferenced(warning);
9580 
9581  if (reason == (char *) NULL)
9582  return;
9583  (void) CopyMagickString(text,reason,MaxTextExtent);
9584  (void) ConcatenateMagickString(text,":",MaxTextExtent);
9585  windows=XSetWindows((XWindows *) ~0);
9586  XNoticeWidget(windows->display,windows,text,(char *) description);
9587 }
9588 
9589 /*
9590 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9591 % %
9592 % %
9593 % %
9594 % X W i n d o w B y I D %
9595 % %
9596 % %
9597 % %
9598 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9599 %
9600 % XWindowByID() locates a child window with a given ID. If not window with
9601 % the given name is found, 0 is returned. Only the window specified and its
9602 % subwindows are searched.
9603 %
9604 % The format of the XWindowByID function is:
9605 %
9606 % child=XWindowByID(display,window,id)
9607 %
9608 % A description of each parameter follows:
9609 %
9610 % o child: XWindowByID returns the window with the specified
9611 % id. If no windows are found, XWindowByID returns 0.
9612 %
9613 % o display: Specifies a pointer to the Display structure; returned from
9614 % XOpenDisplay.
9615 %
9616 % o id: Specifies the id of the window to locate.
9617 %
9618 */
9619 MagickExport Window XWindowByID(Display *display,const Window root_window,
9620  const size_t id)
9621 {
9623  rectangle_info;
9624 
9625  int
9626  i;
9627 
9628  Status
9629  status;
9630 
9631  unsigned int
9632  number_children;
9633 
9634  Window
9635  child,
9636  *children,
9637  window;
9638 
9639  assert(display != (Display *) NULL);
9640  assert(root_window != (Window) NULL);
9641  if (IsEventLogging() != MagickFalse)
9642  (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
9643  if (id == 0)
9644  return(XSelectWindow(display,&rectangle_info));
9645  if (root_window == id)
9646  return(root_window);
9647  status=XQueryTree(display,root_window,&child,&child,&children,
9648  &number_children);
9649  if (status == False)
9650  return((Window) NULL);
9651  window=(Window) NULL;
9652  for (i=0; i < (int) number_children; i++)
9653  {
9654  /*
9655  Search each child and their children.
9656  */
9657  window=XWindowByID(display,children[i],id);
9658  if (window != (Window) NULL)
9659  break;
9660  }
9661  if (children != (Window *) NULL)
9662  (void) XFree((void *) children);
9663  return(window);
9664 }
9665 
9666 /*
9667 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9668 % %
9669 % %
9670 % %
9671 % X W i n d o w B y N a m e %
9672 % %
9673 % %
9674 % %
9675 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9676 %
9677 % XWindowByName() locates a window with a given name on a display. If no
9678 % window with the given name is found, 0 is returned. If more than one window
9679 % has the given name, the first one is returned. Only root and its children
9680 % are searched.
9681 %
9682 % The format of the XWindowByName function is:
9683 %
9684 % window=XWindowByName(display,root_window,name)
9685 %
9686 % A description of each parameter follows:
9687 %
9688 % o window: XWindowByName returns the window id.
9689 %
9690 % o display: Specifies a pointer to the Display structure; returned from
9691 % XOpenDisplay.
9692 %
9693 % o root_window: Specifies the id of the root window.
9694 %
9695 % o name: Specifies the name of the window to locate.
9696 %
9697 */
9698 MagickExport Window XWindowByName(Display *display,const Window root_window,
9699  const char *name)
9700 {
9701  int
9702  i;
9703 
9704  Status
9705  status;
9706 
9707  unsigned int
9708  number_children;
9709 
9710  Window
9711  *children,
9712  child,
9713  window;
9714 
9715  XTextProperty
9716  window_name;
9717 
9718  assert(display != (Display *) NULL);
9719  assert(root_window != (Window) NULL);
9720  assert(name != (char *) NULL);
9721  if (IsEventLogging() != MagickFalse)
9722  (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",name);
9723  if (XGetWMName(display,root_window,&window_name) != 0)
9724  if (LocaleCompare((char *) window_name.value,name) == 0)
9725  return(root_window);
9726  status=XQueryTree(display,root_window,&child,&child,&children,
9727  &number_children);
9728  if (status == False)
9729  return((Window) NULL);
9730  window=(Window) NULL;
9731  for (i=0; i < (int) number_children; i++)
9732  {
9733  /*
9734  Search each child and their children.
9735  */
9736  window=XWindowByName(display,children[i],name);
9737  if (window != (Window) NULL)
9738  break;
9739  }
9740  if (children != (Window *) NULL)
9741  (void) XFree((void *) children);
9742  return(window);
9743 }
9744 
9745 /*
9746 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9747 % %
9748 % %
9749 % %
9750 % X W i n d o w B y P r o p e r y %
9751 % %
9752 % %
9753 % %
9754 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9755 %
9756 % XWindowByProperty() locates a child window with a given property. If not
9757 % window with the given name is found, 0 is returned. If more than one window
9758 % has the given property, the first one is returned. Only the window
9759 % specified and its subwindows are searched.
9760 %
9761 % The format of the XWindowByProperty function is:
9762 %
9763 % child=XWindowByProperty(display,window,property)
9764 %
9765 % A description of each parameter follows:
9766 %
9767 % o child: XWindowByProperty returns the window id with the specified
9768 % property. If no windows are found, XWindowByProperty returns 0.
9769 %
9770 % o display: Specifies a pointer to the Display structure; returned from
9771 % XOpenDisplay.
9772 %
9773 % o property: Specifies the property of the window to locate.
9774 %
9775 */
9776 MagickExport Window XWindowByProperty(Display *display,const Window window,
9777  const Atom property)
9778 {
9779  Atom
9780  type;
9781 
9782  int
9783  format;
9784 
9785  Status
9786  status;
9787 
9788  unsigned char
9789  *data;
9790 
9791  unsigned int
9792  i,
9793  number_children;
9794 
9795  unsigned long
9796  after,
9797  number_items;
9798 
9799  Window
9800  child,
9801  *children,
9802  parent,
9803  root;
9804 
9805  assert(display != (Display *) NULL);
9806  assert(window != (Window) NULL);
9807  assert(property != (Atom) NULL);
9808  if (IsEventLogging() != MagickFalse)
9809  (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
9810  status=XQueryTree(display,window,&root,&parent,&children,&number_children);
9811  if (status == False)
9812  return((Window) NULL);
9813  type=(Atom) NULL;
9814  child=(Window) NULL;
9815  for (i=0; (i < number_children) && (child == (Window) NULL); i++)
9816  {
9817  status=XGetWindowProperty(display,children[i],property,0L,0L,MagickFalse,
9818  (Atom) AnyPropertyType,&type,&format,&number_items,&after,&data);
9819  if (data != NULL)
9820  (void) XFree((void *) data);
9821  if ((status == Success) && (type != (Atom) NULL))
9822  child=children[i];
9823  }
9824  for (i=0; (i < number_children) && (child == (Window) NULL); i++)
9825  child=XWindowByProperty(display,children[i],property);
9826  if (children != (Window *) NULL)
9827  (void) XFree((void *) children);
9828  return(child);
9829 }
9830 #else
9831 
9832 /*
9833 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9834 % %
9835 % %
9836 % %
9837 % X I m p o r t I m a g e %
9838 % %
9839 % %
9840 % %
9841 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9842 %
9843 % XImportImage() reads an image from an X window.
9844 %
9845 % The format of the XImportImage method is:
9846 %
9847 % Image *XImportImage(const ImageInfo *image_info,XImportInfo *ximage_info)
9848 %
9849 % A description of each parameter follows:
9850 %
9851 % o image_info: the image info..
9852 %
9853 % o ximage_info: Specifies a pointer to an XImportInfo structure.
9854 %
9855 */
9856 MagickExport Image *XImportImage(const ImageInfo *image_info,
9857  XImportInfo *ximage_info)
9858 {
9859  assert(image_info != (const ImageInfo *) NULL);
9860  assert(image_info->signature == MagickCoreSignature);
9861  assert(ximage_info != (XImportInfo *) NULL);
9862  if (IsEventLogging() != MagickFalse)
9863  (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
9864  image_info->filename);
9865  (void) ximage_info;
9866  return((Image *) NULL);
9867 }
9868 
9869 /*
9870 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9871 % %
9872 % %
9873 % %
9874 + X R e n d e r I m a g e %
9875 % %
9876 % %
9877 % %
9878 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9879 %
9880 % XRenderImage() renders text on the image with an X11 font. It also returns
9881 % the bounding box of the text relative to the image.
9882 %
9883 % The format of the XRenderImage method is:
9884 %
9885 % MagickBooleanType XRenderImage(Image *image,DrawInfo *draw_info,
9886 % const PointInfo *offset,TypeMetric *metrics)
9887 %
9888 % A description of each parameter follows:
9889 %
9890 % o image: the image.
9891 %
9892 % o draw_info: the draw info.
9893 %
9894 % o offset: (x,y) location of text relative to image.
9895 %
9896 % o metrics: bounding box of text.
9897 %
9898 */
9899 MagickPrivate MagickBooleanType XRenderImage(Image *image,
9900  const DrawInfo *draw_info,const PointInfo *offset,TypeMetric *metrics)
9901 {
9902  (void) draw_info;
9903  (void) offset;
9904  (void) metrics;
9905  (void) ThrowMagickException(&image->exception,GetMagickModule(),
9906  MissingDelegateError,"DelegateLibrarySupportNotBuiltIn","`%s' (X11)",
9907  image->filename);
9908  return(MagickFalse);
9909 }
9910 #endif
9911 
9912 /*
9913 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9914 % %
9915 % %
9916 % %
9917 + X C o m p o n e n t G e n e s i s %
9918 % %
9919 % %
9920 % %
9921 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9922 %
9923 % XComponentGenesis() instantiates the X component.
9924 %
9925 % The format of the XComponentGenesis method is:
9926 %
9927 % MagickBooleanType XComponentGenesis(void)
9928 %
9929 */
9930 MagickExport MagickBooleanType XComponentGenesis(void)
9931 {
9932  return(MagickTrue);
9933 }
9934 
9935 /*
9936 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9937 % %
9938 % %
9939 % %
9940 % X G e t I m p o r t I n f o %
9941 % %
9942 % %
9943 % %
9944 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9945 %
9946 % XGetImportInfo() initializes the XImportInfo structure.
9947 %
9948 % The format of the XGetImportInfo method is:
9949 %
9950 % void XGetImportInfo(XImportInfo *ximage_info)
9951 %
9952 % A description of each parameter follows:
9953 %
9954 % o ximage_info: Specifies a pointer to an ImageInfo structure.
9955 %
9956 */
9957 MagickExport void XGetImportInfo(XImportInfo *ximage_info)
9958 {
9959  assert(ximage_info != (XImportInfo *) NULL);
9960  ximage_info->frame=MagickFalse;
9961  ximage_info->borders=MagickFalse;
9962  ximage_info->screen=MagickFalse;
9963  ximage_info->descend=MagickTrue;
9964  ximage_info->silent=MagickFalse;
9965 }
Definition: image.h:152