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