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