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