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