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