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