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