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