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