blob: 1997192c74ba2c2f32e8f4e7d0add05353615a66 [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;
cristy54666e82010-02-03 23:34:26 +00005849 if ((window->immutable != MagickFalse) &&
5850 (image->storage_class == DirectClass) && (image->matte != MagickFalse))
cristy3ed852e2009-09-05 21:47:34 +00005851 {
5852 char
5853 size[MaxTextExtent];
5854
5855 Image
5856 *pattern;
5857
5858 ImageInfo
5859 *image_info;
5860
5861 image_info=AcquireImageInfo();
5862 (void) CopyMagickString(image_info->filename,
5863 resource_info->image_info->texture != (char *) NULL ?
5864 resource_info->image_info->texture : "pattern:checkerboard",
5865 MaxTextExtent);
5866 (void) FormatMagickString(size,MaxTextExtent,"%lux%lu",image->columns,
5867 image->rows);
5868 image_info->size=ConstantString(size);
5869 pattern=ReadImage(image_info,&image->exception);
5870 image_info=DestroyImageInfo(image_info);
5871 if (pattern != (Image *) NULL)
5872 {
5873 canvas=CloneImage(image,0,0,MagickTrue,&image->exception);
5874 if (canvas != (Image *) NULL)
5875 (void) CompositeImage(canvas,DstOverCompositeOp,pattern,0,0);
5876 pattern=DestroyImage(pattern);
5877 }
5878 }
5879 scanline_pad=(unsigned int) (ximage->bytes_per_line-((ximage->width*
5880 ximage->bits_per_pixel) >> 3));
5881 map_info=window->map_info;
5882 pixels=window->pixel_info->pixels;
5883 q=(unsigned char *) ximage->data;
5884 x=0;
5885 if (ximage->format == XYBitmap)
5886 {
5887 register unsigned short
5888 polarity;
5889
5890 unsigned char
5891 background,
5892 foreground;
5893
5894 /*
5895 Convert canvas to big-endian bitmap.
5896 */
5897 background=(unsigned char)
5898 (XPixelIntensity(&window->pixel_info->foreground_color) <
5899 XPixelIntensity(&window->pixel_info->background_color) ? 0x80 : 0x00);
5900 foreground=(unsigned char)
5901 (XPixelIntensity(&window->pixel_info->background_color) <
5902 XPixelIntensity(&window->pixel_info->foreground_color) ? 0x80 : 0x00);
5903 polarity=(unsigned short) ((PixelIntensityToQuantum(
5904 &canvas->colormap[0])) < ((Quantum) QuantumRange/2) ? 1 : 0);
5905 if (canvas->colors == 2)
5906 polarity=PixelIntensity(&canvas->colormap[0]) <
5907 PixelIntensity(&canvas->colormap[1]);
5908 for (y=0; y < (int) canvas->rows; y++)
5909 {
5910 p=GetVirtualPixels(canvas,0,y,canvas->columns,1,&canvas->exception);
5911 if (p == (const PixelPacket *) NULL)
5912 break;
5913 indexes=GetVirtualIndexQueue(canvas);
5914 bit=0;
5915 byte=0;
5916 for (x=0; x < (int) canvas->columns; x++)
5917 {
5918 byte>>=1;
5919 if (indexes[x] == (IndexPacket) polarity)
5920 byte|=foreground;
5921 else
5922 byte|=background;
5923 bit++;
5924 if (bit == 8)
5925 {
5926 *q++=byte;
5927 bit=0;
5928 byte=0;
5929 }
5930 }
5931 if (bit != 0)
5932 *q=byte >> (8-bit);
5933 q+=scanline_pad;
5934 }
5935 }
5936 else
5937 if (window->pixel_info->colors != 0)
5938 switch (ximage->bits_per_pixel)
5939 {
5940 case 2:
5941 {
5942 register unsigned int
5943 nibble;
5944
5945 /*
5946 Convert to 2 bit color-mapped X canvas.
5947 */
5948 for (y=0; y < (int) canvas->rows; y++)
5949 {
5950 p=GetVirtualPixels(canvas,0,y,canvas->columns,1,&canvas->exception);
5951 if (p == (const PixelPacket *) NULL)
5952 break;
5953 indexes=GetVirtualIndexQueue(canvas);
5954 nibble=0;
5955 for (x=0; x < (int) canvas->columns; x++)
5956 {
5957 pixel=pixels[(long) indexes[x]] & 0x0f;
5958 switch (nibble)
5959 {
5960 case 0:
5961 {
5962 *q=(unsigned char) pixel;
5963 nibble++;
5964 break;
5965 }
5966 case 1:
5967 {
5968 *q|=(unsigned char) (pixel << 2);
5969 nibble++;
5970 break;
5971 }
5972 case 2:
5973 {
5974 *q|=(unsigned char) (pixel << 4);
5975 nibble++;
5976 break;
5977 }
5978 case 3:
5979 {
5980 *q|=(unsigned char) (pixel << 6);
5981 q++;
5982 nibble=0;
5983 break;
5984 }
5985 }
5986 }
5987 q+=scanline_pad;
5988 }
5989 break;
5990 }
5991 case 4:
5992 {
5993 register unsigned int
5994 nibble;
5995
5996 /*
5997 Convert to 4 bit color-mapped X canvas.
5998 */
5999 for (y=0; y < (int) canvas->rows; y++)
6000 {
6001 p=GetVirtualPixels(canvas,0,y,canvas->columns,1,&canvas->exception);
6002 if (p == (const PixelPacket *) NULL)
6003 break;
6004 indexes=GetVirtualIndexQueue(canvas);
6005 nibble=0;
6006 for (x=0; x < (int) canvas->columns; x++)
6007 {
6008 pixel=pixels[(long) indexes[x]] & 0xf;
6009 switch (nibble)
6010 {
6011 case 0:
6012 {
6013 *q=(unsigned char) pixel;
6014 nibble++;
6015 break;
6016 }
6017 case 1:
6018 {
6019 *q|=(unsigned char) (pixel << 4);
6020 q++;
6021 nibble=0;
6022 break;
6023 }
6024 }
6025 }
6026 q+=scanline_pad;
6027 }
6028 break;
6029 }
6030 case 6:
6031 case 8:
6032 {
6033 /*
6034 Convert to 8 bit color-mapped X canvas.
6035 */
6036 if (resource_info->color_recovery &&
6037 resource_info->quantize_info->dither)
6038 {
6039 XDitherImage(canvas,ximage);
6040 break;
6041 }
6042 for (y=0; y < (int) canvas->rows; y++)
6043 {
6044 p=GetVirtualPixels(canvas,0,y,canvas->columns,1,&canvas->exception);
6045 if (p == (const PixelPacket *) NULL)
6046 break;
6047 indexes=GetVirtualIndexQueue(canvas);
6048 for (x=0; x < (int) canvas->columns; x++)
6049 {
6050 pixel=pixels[(long) indexes[x]];
6051 *q++=(unsigned char) pixel;
6052 }
6053 q+=scanline_pad;
6054 }
6055 break;
6056 }
6057 default:
6058 {
6059 register int
6060 k;
6061
6062 register unsigned int
6063 bytes_per_pixel;
6064
6065 unsigned char
6066 channel[sizeof(unsigned long)];
6067
6068 /*
6069 Convert to multi-byte color-mapped X canvas.
6070 */
6071 bytes_per_pixel=(unsigned int) (ximage->bits_per_pixel >> 3);
6072 for (y=0; y < (int) canvas->rows; y++)
6073 {
6074 p=GetVirtualPixels(canvas,0,y,canvas->columns,1,&canvas->exception);
6075 if (p == (const PixelPacket *) NULL)
6076 break;
6077 indexes=GetVirtualIndexQueue(canvas);
6078 for (x=0; x < (int) canvas->columns; x++)
6079 {
6080 pixel=pixels[(long) indexes[x]];
6081 for (k=0; k < (int) bytes_per_pixel; k++)
6082 {
6083 channel[k]=(unsigned char) pixel;
6084 pixel>>=8;
6085 }
6086 for (k=0; k < (int) bytes_per_pixel; k++)
6087 *q++=channel[k];
6088 }
6089 q+=scanline_pad;
6090 }
6091 break;
6092 }
6093 }
6094 else
6095 switch (ximage->bits_per_pixel)
6096 {
6097 case 2:
6098 {
6099 register unsigned int
6100 nibble;
6101
6102 /*
6103 Convert to contiguous 2 bit continuous-tone X canvas.
6104 */
6105 for (y=0; y < (int) canvas->rows; y++)
6106 {
6107 nibble=0;
6108 p=GetVirtualPixels(canvas,0,y,canvas->columns,1,&canvas->exception);
6109 if (p == (const PixelPacket *) NULL)
6110 break;
6111 for (x=0; x < (int) canvas->columns; x++)
6112 {
6113 pixel=XGammaPixel(map_info,p);
6114 pixel&=0xf;
6115 switch (nibble)
6116 {
6117 case 0:
6118 {
6119 *q=(unsigned char) pixel;
6120 nibble++;
6121 break;
6122 }
6123 case 1:
6124 {
6125 *q|=(unsigned char) (pixel << 2);
6126 nibble++;
6127 break;
6128 }
6129 case 2:
6130 {
6131 *q|=(unsigned char) (pixel << 4);
6132 nibble++;
6133 break;
6134 }
6135 case 3:
6136 {
6137 *q|=(unsigned char) (pixel << 6);
6138 q++;
6139 nibble=0;
6140 break;
6141 }
6142 }
6143 p++;
6144 }
6145 q+=scanline_pad;
6146 }
6147 break;
6148 }
6149 case 4:
6150 {
6151 register unsigned int
6152 nibble;
6153
6154 /*
6155 Convert to contiguous 4 bit continuous-tone X canvas.
6156 */
6157 for (y=0; y < (int) canvas->rows; y++)
6158 {
6159 p=GetVirtualPixels(canvas,0,y,canvas->columns,1,&canvas->exception);
6160 if (p == (const PixelPacket *) NULL)
6161 break;
6162 nibble=0;
6163 for (x=0; x < (int) canvas->columns; x++)
6164 {
6165 pixel=XGammaPixel(map_info,p);
6166 pixel&=0xf;
6167 switch (nibble)
6168 {
6169 case 0:
6170 {
6171 *q=(unsigned char) pixel;
6172 nibble++;
6173 break;
6174 }
6175 case 1:
6176 {
6177 *q|=(unsigned char) (pixel << 4);
6178 q++;
6179 nibble=0;
6180 break;
6181 }
6182 }
6183 p++;
6184 }
6185 q+=scanline_pad;
6186 }
6187 break;
6188 }
6189 case 6:
6190 case 8:
6191 {
6192 /*
6193 Convert to contiguous 8 bit continuous-tone X canvas.
6194 */
6195 if (resource_info->color_recovery &&
6196 resource_info->quantize_info->dither)
6197 {
6198 XDitherImage(canvas,ximage);
6199 break;
6200 }
6201 for (y=0; y < (int) canvas->rows; y++)
6202 {
6203 p=GetVirtualPixels(canvas,0,y,canvas->columns,1,&canvas->exception);
6204 if (p == (const PixelPacket *) NULL)
6205 break;
6206 for (x=0; x < (int) canvas->columns; x++)
6207 {
6208 pixel=XGammaPixel(map_info,p);
6209 *q++=(unsigned char) pixel;
6210 p++;
6211 }
6212 q+=scanline_pad;
6213 }
6214 break;
6215 }
6216 default:
6217 {
6218 if ((ximage->bits_per_pixel == 32) && (map_info->red_max == 255) &&
6219 (map_info->green_max == 255) && (map_info->blue_max == 255) &&
6220 (map_info->red_mult == 65536L) && (map_info->green_mult == 256) &&
6221 (map_info->blue_mult == 1))
6222 {
6223 /*
6224 Convert to 32 bit continuous-tone X canvas.
6225 */
6226 for (y=0; y < (int) canvas->rows; y++)
6227 {
6228 p=GetVirtualPixels(canvas,0,y,canvas->columns,1,
6229 &canvas->exception);
6230 if (p == (const PixelPacket *) NULL)
6231 break;
6232 if ((red_gamma != 1.0) || (green_gamma != 1.0) ||
6233 (blue_gamma != 1.0))
6234 {
6235 /*
6236 Gamma correct canvas.
6237 */
6238 for (x=(int) canvas->columns-1; x >= 0; x--)
6239 {
cristyccf844f2010-02-03 23:28:16 +00006240 *q++=ScaleQuantumToChar(XBlueGamma(
6241 GetBluePixelComponent(p)));
6242 *q++=ScaleQuantumToChar(XGreenGamma(
6243 GetGreenPixelComponent(p)));
6244 *q++=ScaleQuantumToChar(XRedGamma(
6245 GetRedPixelComponent(p)));
cristy3ed852e2009-09-05 21:47:34 +00006246 *q++=0;
6247 p++;
6248 }
6249 continue;
6250 }
6251 for (x=(int) canvas->columns-1; x >= 0; x--)
6252 {
cristyce70c172010-01-07 17:15:30 +00006253 *q++=ScaleQuantumToChar((Quantum) GetBluePixelComponent(p));
6254 *q++=ScaleQuantumToChar((Quantum) GetGreenPixelComponent(p));
6255 *q++=ScaleQuantumToChar((Quantum) GetRedPixelComponent(p));
cristy3ed852e2009-09-05 21:47:34 +00006256 *q++=0;
6257 p++;
6258 }
6259 }
6260 }
6261 else
6262 if ((ximage->bits_per_pixel == 32) && (map_info->red_max == 255) &&
6263 (map_info->green_max == 255) && (map_info->blue_max == 255) &&
6264 (map_info->red_mult == 1) && (map_info->green_mult == 256) &&
6265 (map_info->blue_mult == 65536L))
6266 {
6267 /*
6268 Convert to 32 bit continuous-tone X canvas.
6269 */
6270 for (y=0; y < (int) canvas->rows; y++)
6271 {
6272 p=GetVirtualPixels(canvas,0,y,canvas->columns,1,
6273 &canvas->exception);
6274 if (p == (const PixelPacket *) NULL)
6275 break;
6276 if ((red_gamma != 1.0) || (green_gamma != 1.0) ||
6277 (blue_gamma != 1.0))
6278 {
6279 /*
6280 Gamma correct canvas.
6281 */
6282 for (x=(int) canvas->columns-1; x >= 0; x--)
6283 {
cristyccf844f2010-02-03 23:28:16 +00006284 *q++=ScaleQuantumToChar(XRedGamma(
6285 GetRedPixelComponent(p)));
6286 *q++=ScaleQuantumToChar(XGreenGamma(
6287 GetGreenPixelComponent(p)));
6288 *q++=ScaleQuantumToChar(XBlueGamma(
6289 GetBluePixelComponent(p)));
cristy3ed852e2009-09-05 21:47:34 +00006290 *q++=0;
6291 p++;
6292 }
6293 continue;
6294 }
6295 for (x=(int) canvas->columns-1; x >= 0; x--)
6296 {
cristyccf844f2010-02-03 23:28:16 +00006297 *q++=ScaleQuantumToChar((Quantum)
6298 GetRedPixelComponent(p));
6299 *q++=ScaleQuantumToChar((Quantum)
6300 GetGreenPixelComponent(p));
6301 *q++=ScaleQuantumToChar((Quantum)
6302 GetBluePixelComponent(p));
cristy3ed852e2009-09-05 21:47:34 +00006303 *q++=0;
6304 p++;
6305 }
6306 }
6307 }
6308 else
6309 {
6310 register int
6311 k;
6312
6313 register unsigned int
6314 bytes_per_pixel;
6315
6316 unsigned char
6317 channel[sizeof(unsigned long)];
6318
6319 /*
6320 Convert to multi-byte continuous-tone X canvas.
6321 */
6322 bytes_per_pixel=(unsigned int) (ximage->bits_per_pixel >> 3);
6323 for (y=0; y < (int) canvas->rows; y++)
6324 {
6325 p=GetVirtualPixels(canvas,0,y,canvas->columns,1,
6326 &canvas->exception);
6327 if (p == (PixelPacket *) NULL)
6328 break;
6329 for (x=0; x < (long) canvas->columns; x++)
6330 {
6331 pixel=XGammaPixel(map_info,p);
6332 for (k=0; k < (int) bytes_per_pixel; k++)
6333 {
6334 channel[k]=(unsigned char) pixel;
6335 pixel>>=8;
6336 }
6337 for (k=0; k < (int) bytes_per_pixel; k++)
6338 *q++=channel[k];
6339 p++;
6340 }
6341 q+=scanline_pad;
6342 }
6343 }
6344 break;
6345 }
6346 }
6347 if (matte_image != (XImage *) NULL)
6348 {
6349 /*
6350 Initialize matte canvas.
6351 */
6352 scanline_pad=(unsigned int) (matte_image->bytes_per_line-
6353 ((matte_image->width*matte_image->bits_per_pixel) >> 3));
6354 q=(unsigned char *) matte_image->data;
6355 for (y=0; y < (int) canvas->rows; y++)
6356 {
6357 p=GetVirtualPixels(canvas,0,y,canvas->columns,1,&canvas->exception);
6358 if (p == (const PixelPacket *) NULL)
6359 break;
6360 bit=0;
6361 byte=0;
6362 for (x=(int) canvas->columns-1; x >= 0; x--)
6363 {
6364 byte>>=1;
6365 if (p->opacity > (long) (QuantumRange/2))
6366 byte|=0x80;
6367 bit++;
6368 if (bit == 8)
6369 {
6370 *q++=byte;
6371 bit=0;
6372 byte=0;
6373 }
6374 p++;
6375 }
6376 if (bit != 0)
6377 *q=byte >> (8-bit);
6378 q+=scanline_pad;
6379 }
6380 }
6381 if (canvas != image)
6382 canvas=DestroyImage(canvas);
6383}
6384
6385/*
6386%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
6387% %
6388% %
6389% %
6390+ X M a k e I m a g e M S B F i r s t %
6391% %
6392% %
6393% %
6394%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
6395%
6396% XMakeImageMSBFirst() initializes the pixel data of an X11 Image. The X
6397% image pixels are copied in most-significant bit and byte first order. The
6398% server's scanline pad is also respected. Rather than using one or two
6399% general cases, many special cases are found here to help speed up the image
6400% conversion.
6401%
6402% The format of the XMakeImageMSBFirst method is:
6403%
6404% XMakeImageMSBFirst(resource_info,window,image,ximage,matte_image)
6405%
6406% A description of each parameter follows:
6407%
6408% o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
6409%
6410% o window: Specifies a pointer to a XWindowInfo structure.
6411%
6412% o image: the image.
6413%
6414% o ximage: Specifies a pointer to a XImage structure; returned from
6415% XCreateImage.
6416%
6417% o matte_image: Specifies a pointer to a XImage structure; returned from
6418% XCreateImage.
6419%
cristy3ed852e2009-09-05 21:47:34 +00006420*/
6421static void XMakeImageMSBFirst(const XResourceInfo *resource_info,
6422 const XWindowInfo *window,Image *image,XImage *ximage,XImage *matte_image)
6423{
6424 Image
6425 *canvas;
6426
6427 int
6428 y;
6429
6430 register int
6431 x;
6432
6433 register const IndexPacket
6434 *indexes;
6435
6436 register const PixelPacket
6437 *p;
6438
6439 register unsigned char
6440 *q;
6441
6442 unsigned char
6443 bit,
6444 byte;
6445
6446 unsigned int
6447 scanline_pad;
6448
6449 unsigned long
6450 pixel,
6451 *pixels;
6452
6453 XStandardColormap
6454 *map_info;
6455
6456 assert(resource_info != (XResourceInfo *) NULL);
6457 assert(window != (XWindowInfo *) NULL);
6458 assert(image != (Image *) NULL);
6459 if (image->debug != MagickFalse)
6460 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
6461 canvas=image;
cristy54666e82010-02-03 23:34:26 +00006462 if ((window->immutable != MagickFalse) &&
6463 (image->storage_class == DirectClass) && (image->matte != MagickFalse))
cristy3ed852e2009-09-05 21:47:34 +00006464 {
6465 char
6466 size[MaxTextExtent];
6467
6468 Image
6469 *pattern;
6470
6471 ImageInfo
6472 *image_info;
6473
6474 image_info=AcquireImageInfo();
6475 (void) CopyMagickString(image_info->filename,
6476 resource_info->image_info->texture != (char *) NULL ?
6477 resource_info->image_info->texture : "pattern:checkerboard",
6478 MaxTextExtent);
6479 (void) FormatMagickString(size,MaxTextExtent,"%lux%lu",image->columns,
6480 image->rows);
6481 image_info->size=ConstantString(size);
6482 pattern=ReadImage(image_info,&image->exception);
6483 image_info=DestroyImageInfo(image_info);
6484 if (pattern != (Image *) NULL)
6485 {
6486 canvas=CloneImage(image,0,0,MagickTrue,&image->exception);
6487 if (canvas != (Image *) NULL)
6488 (void) CompositeImage(canvas,DstOverCompositeOp,pattern,0,0);
6489 pattern=DestroyImage(pattern);
6490 }
6491 }
6492 scanline_pad=(unsigned int) (ximage->bytes_per_line-
6493 ((ximage->width*ximage->bits_per_pixel) >> 3));
6494 map_info=window->map_info;
6495 pixels=window->pixel_info->pixels;
6496 q=(unsigned char *) ximage->data;
6497 x=0;
6498 if (ximage->format == XYBitmap)
6499 {
6500 register unsigned short
6501 polarity;
6502
6503 unsigned char
6504 background,
6505 foreground;
6506
6507 /*
6508 Convert canvas to big-endian bitmap.
6509 */
6510 background=(unsigned char)
6511 (XPixelIntensity(&window->pixel_info->foreground_color) <
6512 XPixelIntensity(&window->pixel_info->background_color) ? 0x01 : 0x00);
6513 foreground=(unsigned char)
6514 (XPixelIntensity(&window->pixel_info->background_color) <
6515 XPixelIntensity(&window->pixel_info->foreground_color) ? 0x01 : 0x00);
6516 polarity=(unsigned short) ((PixelIntensityToQuantum(
6517 &canvas->colormap[0])) < ((Quantum) QuantumRange/2) ? 1 : 0);
6518 if (canvas->colors == 2)
6519 polarity=PixelIntensity(&canvas->colormap[0]) <
6520 PixelIntensity(&canvas->colormap[1]);
6521 for (y=0; y < (int) canvas->rows; y++)
6522 {
6523 p=GetVirtualPixels(canvas,0,y,canvas->columns,1,&canvas->exception);
6524 if (p == (const PixelPacket *) NULL)
6525 break;
6526 indexes=GetVirtualIndexQueue(canvas);
6527 bit=0;
6528 byte=0;
6529 for (x=(int) canvas->columns-1; x >= 0; x--)
6530 {
6531 byte<<=1;
6532 if (indexes[x] == (IndexPacket) polarity)
6533 byte|=foreground;
6534 else
6535 byte|=background;
6536 bit++;
6537 if (bit == 8)
6538 {
6539 *q++=byte;
6540 bit=0;
6541 byte=0;
6542 }
6543 }
6544 if (bit != 0)
6545 *q=byte << (8-bit);
6546 q+=scanline_pad;
6547 }
6548 }
6549 else
6550 if (window->pixel_info->colors != 0)
6551 switch (ximage->bits_per_pixel)
6552 {
6553 case 2:
6554 {
6555 register unsigned int
6556 nibble;
6557
6558 /*
6559 Convert to 2 bit color-mapped X canvas.
6560 */
6561 for (y=0; y < (int) canvas->rows; y++)
6562 {
6563 p=GetVirtualPixels(canvas,0,y,canvas->columns,1,&canvas->exception);
6564 if (p == (const PixelPacket *) NULL)
6565 break;
6566 indexes=GetVirtualIndexQueue(canvas);
6567 nibble=0;
6568 for (x=0; x < (int) canvas->columns; x++)
6569 {
6570 pixel=pixels[(long) indexes[x]] & 0xf;
6571 switch (nibble)
6572 {
6573 case 0:
6574 {
6575 *q=(unsigned char) (pixel << 6);
6576 nibble++;
6577 break;
6578 }
6579 case 1:
6580 {
6581 *q|=(unsigned char) (pixel << 4);
6582 nibble++;
6583 break;
6584 }
6585 case 2:
6586 {
6587 *q|=(unsigned char) (pixel << 2);
6588 nibble++;
6589 break;
6590 }
6591 case 3:
6592 {
6593 *q|=(unsigned char) pixel;
6594 q++;
6595 nibble=0;
6596 break;
6597 }
6598 }
6599 }
6600 q+=scanline_pad;
6601 }
6602 break;
6603 }
6604 case 4:
6605 {
6606 register unsigned int
6607 nibble;
6608
6609 /*
6610 Convert to 4 bit color-mapped X canvas.
6611 */
6612 for (y=0; y < (int) canvas->rows; y++)
6613 {
6614 p=GetVirtualPixels(canvas,0,y,canvas->columns,1,&canvas->exception);
6615 if (p == (const PixelPacket *) NULL)
6616 break;
6617 indexes=GetVirtualIndexQueue(canvas);
6618 nibble=0;
6619 for (x=0; x < (int) canvas->columns; x++)
6620 {
6621 pixel=pixels[(long) indexes[x]] & 0xf;
6622 switch (nibble)
6623 {
6624 case 0:
6625 {
6626 *q=(unsigned char) (pixel << 4);
6627 nibble++;
6628 break;
6629 }
6630 case 1:
6631 {
6632 *q|=(unsigned char) pixel;
6633 q++;
6634 nibble=0;
6635 break;
6636 }
6637 }
6638 }
6639 q+=scanline_pad;
6640 }
6641 break;
6642 }
6643 case 6:
6644 case 8:
6645 {
6646 /*
6647 Convert to 8 bit color-mapped X canvas.
6648 */
6649 if (resource_info->color_recovery &&
6650 resource_info->quantize_info->dither)
6651 {
6652 XDitherImage(canvas,ximage);
6653 break;
6654 }
6655 for (y=0; y < (int) canvas->rows; y++)
6656 {
6657 p=GetVirtualPixels(canvas,0,y,canvas->columns,1,&canvas->exception);
6658 if (p == (const PixelPacket *) NULL)
6659 break;
6660 indexes=GetVirtualIndexQueue(canvas);
6661 for (x=0; x < (int) canvas->columns; x++)
6662 {
6663 pixel=pixels[(long) indexes[x]];
6664 *q++=(unsigned char) pixel;
6665 }
6666 q+=scanline_pad;
6667 }
6668 break;
6669 }
6670 default:
6671 {
6672 register int
6673 k;
6674
6675 register unsigned int
6676 bytes_per_pixel;
6677
6678 unsigned char
6679 channel[sizeof(unsigned long)];
6680
6681 /*
6682 Convert to 8 bit color-mapped X canvas.
6683 */
6684 bytes_per_pixel=(unsigned int) (ximage->bits_per_pixel >> 3);
6685 for (y=0; y < (int) canvas->rows; y++)
6686 {
6687 p=GetVirtualPixels(canvas,0,y,canvas->columns,1,&canvas->exception);
6688 if (p == (const PixelPacket *) NULL)
6689 break;
6690 indexes=GetVirtualIndexQueue(canvas);
6691 for (x=0; x < (int) canvas->columns; x++)
6692 {
6693 pixel=pixels[(long) indexes[x]];
6694 for (k=(int) bytes_per_pixel-1; k >= 0; k--)
6695 {
6696 channel[k]=(unsigned char) pixel;
6697 pixel>>=8;
6698 }
6699 for (k=0; k < (int) bytes_per_pixel; k++)
6700 *q++=channel[k];
6701 }
6702 q+=scanline_pad;
6703 }
6704 break;
6705 }
6706 }
6707 else
6708 switch (ximage->bits_per_pixel)
6709 {
6710 case 2:
6711 {
6712 register unsigned int
6713 nibble;
6714
6715 /*
6716 Convert to 4 bit continuous-tone X canvas.
6717 */
6718 for (y=0; y < (int) canvas->rows; y++)
6719 {
6720 p=GetVirtualPixels(canvas,0,y,canvas->columns,1,&canvas->exception);
6721 if (p == (const PixelPacket *) NULL)
6722 break;
6723 nibble=0;
6724 for (x=(int) canvas->columns-1; x >= 0; x--)
6725 {
6726 pixel=XGammaPixel(map_info,p);
6727 pixel&=0xf;
6728 switch (nibble)
6729 {
6730 case 0:
6731 {
6732 *q=(unsigned char) (pixel << 6);
6733 nibble++;
6734 break;
6735 }
6736 case 1:
6737 {
6738 *q|=(unsigned char) (pixel << 4);
6739 nibble++;
6740 break;
6741 }
6742 case 2:
6743 {
6744 *q|=(unsigned char) (pixel << 2);
6745 nibble++;
6746 break;
6747 }
6748 case 3:
6749 {
6750 *q|=(unsigned char) pixel;
6751 q++;
6752 nibble=0;
6753 break;
6754 }
6755 }
6756 p++;
6757 }
6758 q+=scanline_pad;
6759 }
6760 break;
6761 }
6762 case 4:
6763 {
6764 register unsigned int
6765 nibble;
6766
6767 /*
6768 Convert to 4 bit continuous-tone X canvas.
6769 */
6770 for (y=0; y < (int) canvas->rows; y++)
6771 {
6772 p=GetVirtualPixels(canvas,0,y,canvas->columns,1,&canvas->exception);
6773 if (p == (const PixelPacket *) NULL)
6774 break;
6775 nibble=0;
6776 for (x=(int) canvas->columns-1; x >= 0; x--)
6777 {
6778 pixel=XGammaPixel(map_info,p);
6779 pixel&=0xf;
6780 switch (nibble)
6781 {
6782 case 0:
6783 {
6784 *q=(unsigned char) (pixel << 4);
6785 nibble++;
6786 break;
6787 }
6788 case 1:
6789 {
6790 *q|=(unsigned char) pixel;
6791 q++;
6792 nibble=0;
6793 break;
6794 }
6795 }
6796 p++;
6797 }
6798 q+=scanline_pad;
6799 }
6800 break;
6801 }
6802 case 6:
6803 case 8:
6804 {
6805 /*
6806 Convert to 8 bit continuous-tone X canvas.
6807 */
6808 if (resource_info->color_recovery &&
6809 resource_info->quantize_info->dither)
6810 {
6811 XDitherImage(canvas,ximage);
6812 break;
6813 }
6814 for (y=0; y < (int) canvas->rows; y++)
6815 {
6816 p=GetVirtualPixels(canvas,0,y,canvas->columns,1,&canvas->exception);
6817 if (p == (const PixelPacket *) NULL)
6818 break;
6819 for (x=(int) canvas->columns-1; x >= 0; x--)
6820 {
6821 pixel=XGammaPixel(map_info,p);
6822 *q++=(unsigned char) pixel;
6823 p++;
6824 }
6825 q+=scanline_pad;
6826 }
6827 break;
6828 }
6829 default:
6830 {
6831 if ((ximage->bits_per_pixel == 32) && (map_info->red_max == 255) &&
6832 (map_info->green_max == 255) && (map_info->blue_max == 255) &&
6833 (map_info->red_mult == 65536L) && (map_info->green_mult == 256) &&
6834 (map_info->blue_mult == 1))
6835 {
6836 /*
6837 Convert to 32 bit continuous-tone X canvas.
6838 */
6839 for (y=0; y < (int) canvas->rows; y++)
6840 {
6841 p=GetVirtualPixels(canvas,0,y,canvas->columns,1,
6842 &canvas->exception);
6843 if (p == (const PixelPacket *) NULL)
6844 break;
6845 if ((red_gamma != 1.0) || (green_gamma != 1.0) ||
6846 (blue_gamma != 1.0))
6847 {
6848 /*
6849 Gamma correct canvas.
6850 */
6851 for (x=(int) canvas->columns-1; x >= 0; x--)
6852 {
6853 *q++=0;
cristyccf844f2010-02-03 23:28:16 +00006854 *q++=ScaleQuantumToChar(XRedGamma(
6855 GetRedPixelComponent(p)));
6856 *q++=ScaleQuantumToChar(XGreenGamma(
6857 GetGreenPixelComponent(p)));
6858 *q++=ScaleQuantumToChar(XBlueGamma(
6859 GetBluePixelComponent(p)));
cristy3ed852e2009-09-05 21:47:34 +00006860 p++;
6861 }
6862 continue;
6863 }
6864 for (x=(int) canvas->columns-1; x >= 0; x--)
6865 {
6866 *q++=0;
cristyce70c172010-01-07 17:15:30 +00006867 *q++=ScaleQuantumToChar((Quantum) GetRedPixelComponent(p));
6868 *q++=ScaleQuantumToChar((Quantum) GetGreenPixelComponent(p));
6869 *q++=ScaleQuantumToChar((Quantum) GetBluePixelComponent(p));
cristy3ed852e2009-09-05 21:47:34 +00006870 p++;
6871 }
6872 }
6873 }
6874 else
6875 if ((ximage->bits_per_pixel == 32) && (map_info->red_max == 255) &&
6876 (map_info->green_max == 255) && (map_info->blue_max == 255) &&
6877 (map_info->red_mult == 1) && (map_info->green_mult == 256) &&
6878 (map_info->blue_mult == 65536L))
6879 {
6880 /*
6881 Convert to 32 bit continuous-tone X canvas.
6882 */
6883 for (y=0; y < (int) canvas->rows; y++)
6884 {
6885 p=GetVirtualPixels(canvas,0,y,canvas->columns,1,
6886 &canvas->exception);
6887 if (p == (const PixelPacket *) NULL)
6888 break;
6889 if ((red_gamma != 1.0) || (green_gamma != 1.0) ||
6890 (blue_gamma != 1.0))
6891 {
6892 /*
6893 Gamma correct canvas.
6894 */
6895 for (x=(int) canvas->columns-1; x >= 0; x--)
6896 {
6897 *q++=0;
cristyccf844f2010-02-03 23:28:16 +00006898 *q++=ScaleQuantumToChar(XBlueGamma(
6899 GetBluePixelComponent(p)));
6900 *q++=ScaleQuantumToChar(XGreenGamma(
6901 GetGreenPixelComponent(p)));
6902 *q++=ScaleQuantumToChar(XRedGamma(
6903 GetRedPixelComponent(p)));
cristy3ed852e2009-09-05 21:47:34 +00006904 p++;
6905 }
6906 continue;
6907 }
6908 for (x=(int) canvas->columns-1; x >= 0; x--)
6909 {
6910 *q++=0;
cristyccf844f2010-02-03 23:28:16 +00006911 *q++=ScaleQuantumToChar((Quantum)
6912 GetBluePixelComponent(p));
6913 *q++=ScaleQuantumToChar((Quantum)
6914 GetGreenPixelComponent(p));
6915 *q++=ScaleQuantumToChar((Quantum)
6916 GetRedPixelComponent(p));
cristy3ed852e2009-09-05 21:47:34 +00006917 p++;
6918 }
6919 }
6920 }
6921 else
6922 {
6923 register int
6924 k;
6925
6926 register unsigned int
6927 bytes_per_pixel;
6928
6929 unsigned char
6930 channel[sizeof(unsigned long)];
6931
6932 /*
6933 Convert to multi-byte continuous-tone X canvas.
6934 */
6935 bytes_per_pixel=(unsigned int) (ximage->bits_per_pixel >> 3);
6936 for (y=0; y < (int) canvas->rows; y++)
6937 {
6938 p=GetVirtualPixels(canvas,0,y,canvas->columns,1,
6939 &canvas->exception);
6940 if (p == (const PixelPacket *) NULL)
6941 break;
6942 for (x=(int) canvas->columns-1; x >= 0; x--)
6943 {
6944 pixel=XGammaPixel(map_info,p);
6945 for (k=(int) bytes_per_pixel-1; k >= 0; k--)
6946 {
6947 channel[k]=(unsigned char) pixel;
6948 pixel>>=8;
6949 }
6950 for (k=0; k < (int) bytes_per_pixel; k++)
6951 *q++=channel[k];
6952 p++;
6953 }
6954 q+=scanline_pad;
6955 }
6956 }
6957 break;
6958 }
6959 }
6960 if (matte_image != (XImage *) NULL)
6961 {
6962 /*
6963 Initialize matte canvas.
6964 */
6965 scanline_pad=(unsigned int) (matte_image->bytes_per_line-
6966 ((matte_image->width*matte_image->bits_per_pixel) >> 3));
6967 q=(unsigned char *) matte_image->data;
6968 for (y=0; y < (int) canvas->rows; y++)
6969 {
6970 p=GetVirtualPixels(canvas,0,y,canvas->columns,1,&canvas->exception);
6971 if (p == (const PixelPacket *) NULL)
6972 break;
6973 bit=0;
6974 byte=0;
6975 for (x=(int) canvas->columns-1; x >= 0; x--)
6976 {
6977 byte<<=1;
6978 if (p->opacity > (long) (QuantumRange/2))
6979 byte|=0x01;
6980 bit++;
6981 if (bit == 8)
6982 {
6983 *q++=byte;
6984 bit=0;
6985 byte=0;
6986 }
6987 p++;
6988 }
6989 if (bit != 0)
6990 *q=byte << (8-bit);
6991 q+=scanline_pad;
6992 }
6993 }
6994 if (canvas != image)
6995 canvas=DestroyImage(canvas);
6996}
6997
6998/*
6999%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
7000% %
7001% %
7002% %
7003% X M a k e M a g n i f y I m a g e %
7004% %
7005% %
7006% %
7007%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
7008%
7009% XMakeMagnifyImage() magnifies a region of an X image and displays it.
7010%
7011% The format of the XMakeMagnifyImage method is:
7012%
7013% void XMakeMagnifyImage(display,windows)
7014%
7015% A description of each parameter follows:
7016%
7017% o display: Specifies a connection to an X server; returned from
7018% XOpenDisplay.
7019%
7020% o windows: Specifies a pointer to a XWindows structure.
7021%
7022*/
7023MagickExport void XMakeMagnifyImage(Display *display,XWindows *windows)
7024{
7025 char
7026 tuple[MaxTextExtent];
7027
7028 int
7029 y;
7030
7031 long
7032 n;
7033
7034 MagickPixelPacket
7035 pixel;
7036
7037 register int
7038 x;
7039
7040 register long
7041 i;
7042
7043 register unsigned char
7044 *p,
7045 *q;
7046
7047 static unsigned int
7048 previous_magnify = 0;
7049
7050 static XWindowInfo
7051 magnify_window;
7052
7053 unsigned int
7054 height,
7055 j,
7056 k,
7057 l,
7058 magnify,
7059 scanline_pad,
7060 width;
7061
7062 XImage
7063 *ximage;
7064
7065 /*
7066 Check boundary conditions.
7067 */
7068 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
7069 assert(display != (Display *) NULL);
7070 assert(windows != (XWindows *) NULL);
7071 magnify=1;
7072 for (n=1; n < (long) windows->magnify.data; n++)
7073 magnify<<=1;
7074 while ((magnify*windows->image.ximage->width) < windows->magnify.width)
7075 magnify<<=1;
7076 while ((magnify*windows->image.ximage->height) < windows->magnify.height)
7077 magnify<<=1;
7078 while (magnify > windows->magnify.width)
7079 magnify>>=1;
7080 while (magnify > windows->magnify.height)
7081 magnify>>=1;
7082 if (magnify != previous_magnify)
7083 {
7084 Status
7085 status;
7086
7087 XTextProperty
7088 window_name;
7089
7090 /*
7091 New magnify factor: update magnify window name.
7092 */
7093 i=0;
7094 while ((1 << i) <= (int) magnify)
7095 i++;
7096 (void) FormatMagickString(windows->magnify.name,MaxTextExtent,
7097 "Magnify %luX",i);
7098 status=XStringListToTextProperty(&windows->magnify.name,1,&window_name);
7099 if (status != False)
7100 {
7101 XSetWMName(display,windows->magnify.id,&window_name);
7102 XSetWMIconName(display,windows->magnify.id,&window_name);
7103 (void) XFree((void *) window_name.value);
7104 }
7105 }
7106 previous_magnify=magnify;
7107 ximage=windows->image.ximage;
7108 width=(unsigned int) windows->magnify.ximage->width;
7109 height=(unsigned int) windows->magnify.ximage->height;
7110 if ((windows->magnify.x < 0) ||
7111 (windows->magnify.x >= windows->image.ximage->width))
7112 windows->magnify.x=windows->image.ximage->width >> 1;
7113 x=windows->magnify.x-((width/magnify) >> 1);
7114 if (x < 0)
7115 x=0;
7116 else
7117 if (x > (int) (ximage->width-(width/magnify)))
7118 x=ximage->width-width/magnify;
7119 if ((windows->magnify.y < 0) ||
7120 (windows->magnify.y >= windows->image.ximage->height))
7121 windows->magnify.y=windows->image.ximage->height >> 1;
7122 y=windows->magnify.y-((height/magnify) >> 1);
7123 if (y < 0)
7124 y=0;
7125 else
7126 if (y > (int) (ximage->height-(height/magnify)))
7127 y=ximage->height-height/magnify;
7128 q=(unsigned char *) windows->magnify.ximage->data;
7129 scanline_pad=(unsigned int) (windows->magnify.ximage->bytes_per_line-
7130 ((width*windows->magnify.ximage->bits_per_pixel) >> 3));
7131 if (ximage->bits_per_pixel < 8)
7132 {
7133 register unsigned char
7134 background,
7135 byte,
7136 foreground,
7137 p_bit,
7138 q_bit;
7139
7140 register unsigned int
7141 plane;
7142
7143 XPixelInfo
7144 *pixel_info;
7145
7146 pixel_info=windows->magnify.pixel_info;
7147 switch (ximage->bitmap_bit_order)
7148 {
7149 case LSBFirst:
7150 {
7151 /*
7152 Magnify little-endian bitmap.
7153 */
7154 background=0x00;
7155 foreground=0x80;
7156 if (ximage->format == XYBitmap)
7157 {
7158 background=(unsigned char)
7159 (XPixelIntensity(&pixel_info->foreground_color) <
7160 XPixelIntensity(&pixel_info->background_color) ? 0x80 : 0x00);
7161 foreground=(unsigned char)
7162 (XPixelIntensity(&pixel_info->background_color) <
7163 XPixelIntensity(&pixel_info->foreground_color) ? 0x80 : 0x00);
7164 if (windows->magnify.depth > 1)
7165 Swap(background,foreground);
7166 }
7167 for (i=0; i < (long) height; i+=magnify)
7168 {
7169 /*
7170 Propogate pixel magnify rows.
7171 */
7172 for (j=0; j < magnify; j++)
7173 {
7174 p=(unsigned char *) ximage->data+y*ximage->bytes_per_line+
7175 ((x*ximage->bits_per_pixel) >> 3);
7176 p_bit=(unsigned char) (x*ximage->bits_per_pixel) & 0x07;
7177 q_bit=0;
7178 byte=0;
7179 for (k=0; k < width; k+=magnify)
7180 {
7181 /*
7182 Propogate pixel magnify columns.
7183 */
7184 for (l=0; l < magnify; l++)
7185 {
7186 /*
7187 Propogate each bit plane.
7188 */
7189 for (plane=0; (int) plane < ximage->bits_per_pixel; plane++)
7190 {
7191 byte>>=1;
7192 if (*p & (0x01 << (p_bit+plane)))
7193 byte|=foreground;
7194 else
7195 byte|=background;
7196 q_bit++;
7197 if (q_bit == 8)
7198 {
7199 *q++=byte;
7200 q_bit=0;
7201 byte=0;
7202 }
7203 }
7204 }
7205 p_bit+=ximage->bits_per_pixel;
7206 if (p_bit == 8)
7207 {
7208 p++;
7209 p_bit=0;
7210 }
7211 if (q_bit != 0)
7212 *q=byte >> (8-q_bit);
7213 q+=scanline_pad;
7214 }
7215 }
7216 y++;
7217 }
7218 break;
7219 }
7220 case MSBFirst:
7221 default:
7222 {
7223 /*
7224 Magnify big-endian bitmap.
7225 */
7226 background=0x00;
7227 foreground=0x01;
7228 if (ximage->format == XYBitmap)
7229 {
7230 background=(unsigned char)
7231 (XPixelIntensity(&pixel_info->foreground_color) <
7232 XPixelIntensity(&pixel_info->background_color) ? 0x01 : 0x00);
7233 foreground=(unsigned char)
7234 (XPixelIntensity(&pixel_info->background_color) <
7235 XPixelIntensity(&pixel_info->foreground_color) ? 0x01 : 0x00);
7236 if (windows->magnify.depth > 1)
7237 Swap(background,foreground);
7238 }
7239 for (i=0; i < (long) height; i+=magnify)
7240 {
7241 /*
7242 Propogate pixel magnify rows.
7243 */
7244 for (j=0; j < magnify; j++)
7245 {
7246 p=(unsigned char *) ximage->data+y*ximage->bytes_per_line+
7247 ((x*ximage->bits_per_pixel) >> 3);
7248 p_bit=(unsigned char) (x*ximage->bits_per_pixel) & 0x07;
7249 q_bit=0;
7250 byte=0;
7251 for (k=0; k < width; k+=magnify)
7252 {
7253 /*
7254 Propogate pixel magnify columns.
7255 */
7256 for (l=0; l < magnify; l++)
7257 {
7258 /*
7259 Propogate each bit plane.
7260 */
7261 for (plane=0; (int) plane < ximage->bits_per_pixel; plane++)
7262 {
7263 byte<<=1;
7264 if (*p & (0x80 >> (p_bit+plane)))
7265 byte|=foreground;
7266 else
7267 byte|=background;
7268 q_bit++;
7269 if (q_bit == 8)
7270 {
7271 *q++=byte;
7272 q_bit=0;
7273 byte=0;
7274 }
7275 }
7276 }
7277 p_bit+=ximage->bits_per_pixel;
7278 if (p_bit == 8)
7279 {
7280 p++;
7281 p_bit=0;
7282 }
7283 if (q_bit != 0)
7284 *q=byte << (8-q_bit);
7285 q+=scanline_pad;
7286 }
7287 }
7288 y++;
7289 }
7290 break;
7291 }
7292 }
7293 }
7294 else
7295 switch (ximage->bits_per_pixel)
7296 {
7297 case 6:
7298 case 8:
7299 {
7300 /*
7301 Magnify 8 bit X image.
7302 */
7303 for (i=0; i < (long) height; i+=magnify)
7304 {
7305 /*
7306 Propogate pixel magnify rows.
7307 */
7308 for (j=0; j < magnify; j++)
7309 {
7310 p=(unsigned char *) ximage->data+y*ximage->bytes_per_line+
7311 ((x*ximage->bits_per_pixel) >> 3);
7312 for (k=0; k < width; k+=magnify)
7313 {
7314 /*
7315 Propogate pixel magnify columns.
7316 */
7317 for (l=0; l < magnify; l++)
7318 *q++=(*p);
7319 p++;
7320 }
7321 q+=scanline_pad;
7322 }
7323 y++;
7324 }
7325 break;
7326 }
7327 default:
7328 {
7329 register unsigned int
7330 bytes_per_pixel,
7331 m;
7332
7333 /*
7334 Magnify multi-byte X image.
7335 */
7336 bytes_per_pixel=(unsigned int) ximage->bits_per_pixel >> 3;
7337 for (i=0; i < (long) height; i+=magnify)
7338 {
7339 /*
7340 Propogate pixel magnify rows.
7341 */
7342 for (j=0; j < magnify; j++)
7343 {
7344 p=(unsigned char *) ximage->data+y*ximage->bytes_per_line+
7345 ((x*ximage->bits_per_pixel) >> 3);
7346 for (k=0; k < width; k+=magnify)
7347 {
7348 /*
7349 Propogate pixel magnify columns.
7350 */
7351 for (l=0; l < magnify; l++)
7352 for (m=0; m < bytes_per_pixel; m++)
7353 *q++=(*(p+m));
7354 p+=bytes_per_pixel;
7355 }
7356 q+=scanline_pad;
7357 }
7358 y++;
7359 }
7360 break;
7361 }
7362 }
7363 /*
7364 Copy X image to magnify pixmap.
7365 */
7366 x=windows->magnify.x-((width/magnify) >> 1);
7367 if (x < 0)
7368 x=(int) ((width >> 1)-windows->magnify.x*magnify);
7369 else
7370 if (x > (int) (ximage->width-(width/magnify)))
7371 x=(int) ((ximage->width-windows->magnify.x)*magnify-(width >> 1));
7372 else
7373 x=0;
7374 y=windows->magnify.y-((height/magnify) >> 1);
7375 if (y < 0)
7376 y=(int) ((height >> 1)-windows->magnify.y*magnify);
7377 else
7378 if (y > (int) (ximage->height-(height/magnify)))
7379 y=(int) ((ximage->height-windows->magnify.y)*magnify-(height >> 1));
7380 else
7381 y=0;
7382 if ((x != 0) || (y != 0))
7383 (void) XFillRectangle(display,windows->magnify.pixmap,
7384 windows->magnify.annotate_context,0,0,width,height);
7385 (void) XPutImage(display,windows->magnify.pixmap,
7386 windows->magnify.annotate_context,windows->magnify.ximage,0,0,x,y,width-x,
7387 height-y);
7388 if ((magnify > 1) && ((magnify <= (width >> 1)) &&
7389 (magnify <= (height >> 1))))
7390 {
7391 RectangleInfo
7392 highlight_info;
7393
7394 /*
7395 Highlight center pixel.
7396 */
7397 highlight_info.x=(long) windows->magnify.width >> 1;
7398 highlight_info.y=(long) windows->magnify.height >> 1;
7399 highlight_info.width=magnify;
7400 highlight_info.height=magnify;
7401 (void) XDrawRectangle(display,windows->magnify.pixmap,
7402 windows->magnify.highlight_context,(int) highlight_info.x,
7403 (int) highlight_info.y,(unsigned int) highlight_info.width-1,
7404 (unsigned int) highlight_info.height-1);
7405 if (magnify > 2)
7406 (void) XDrawRectangle(display,windows->magnify.pixmap,
7407 windows->magnify.annotate_context,(int) highlight_info.x+1,
7408 (int) highlight_info.y+1,(unsigned int) highlight_info.width-3,
7409 (unsigned int) highlight_info.height-3);
7410 }
7411 /*
7412 Show center pixel color.
7413 */
7414 (void) GetOneVirtualMagickPixel(windows->image.image,windows->magnify.x,
7415 windows->magnify.y,&pixel,&windows->image.image->exception);
7416 (void) FormatMagickString(tuple,MaxTextExtent,"%d,%d: ",
7417 windows->magnify.x,windows->magnify.y);
7418 (void) ConcatenateMagickString(tuple,"(",MaxTextExtent);
7419 ConcatenateColorComponent(&pixel,RedChannel,X11Compliance,tuple);
7420 (void) ConcatenateMagickString(tuple,",",MaxTextExtent);
7421 ConcatenateColorComponent(&pixel,GreenChannel,X11Compliance,tuple);
7422 (void) ConcatenateMagickString(tuple,",",MaxTextExtent);
7423 ConcatenateColorComponent(&pixel,BlueChannel,X11Compliance,tuple);
7424 if (pixel.colorspace == CMYKColorspace)
7425 {
7426 (void) ConcatenateMagickString(tuple,",",MaxTextExtent);
7427 ConcatenateColorComponent(&pixel,IndexChannel,X11Compliance,tuple);
7428 }
7429 if (pixel.matte != MagickFalse)
7430 {
7431 (void) ConcatenateMagickString(tuple,",",MaxTextExtent);
7432 ConcatenateColorComponent(&pixel,OpacityChannel,X11Compliance,tuple);
7433 }
7434 (void) ConcatenateMagickString(tuple,")",MaxTextExtent);
7435 height=(unsigned int) windows->magnify.font_info->ascent+
7436 windows->magnify.font_info->descent;
7437 x=windows->magnify.font_info->max_bounds.width >> 1;
7438 y=windows->magnify.font_info->ascent+(height >> 2);
7439 (void) XDrawImageString(display,windows->magnify.pixmap,
7440 windows->magnify.annotate_context,x,y,tuple,(int) strlen(tuple));
7441 GetColorTuple(&pixel,MagickTrue,tuple);
7442 y+=height;
7443 (void) XDrawImageString(display,windows->magnify.pixmap,
7444 windows->magnify.annotate_context,x,y,tuple,(int) strlen(tuple));
7445 (void) QueryMagickColorname(windows->image.image,&pixel,SVGCompliance,tuple,
7446 &windows->image.image->exception);
7447 y+=height;
7448 (void) XDrawImageString(display,windows->magnify.pixmap,
7449 windows->magnify.annotate_context,x,y,tuple,(int) strlen(tuple));
7450 /*
7451 Refresh magnify window.
7452 */
7453 magnify_window=windows->magnify;
7454 magnify_window.x=0;
7455 magnify_window.y=0;
7456 XRefreshWindow(display,&magnify_window,(XEvent *) NULL);
7457}
7458
7459/*
7460%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
7461% %
7462% %
7463% %
7464% X M a k e P i x m a p %
7465% %
7466% %
7467% %
7468%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
7469%
7470% XMakePixmap() creates an X11 pixmap.
7471%
7472% The format of the XMakePixmap method is:
7473%
7474% void XMakeStandardColormap(Display *display,XVisualInfo *visual_info,
7475% XResourceInfo *resource_info,Image *image,XStandardColormap *map_info,
7476% XPixelInfo *pixel)
7477%
7478% A description of each parameter follows:
7479%
7480% o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
7481%
7482% o display: Specifies a connection to an X server; returned from
7483% XOpenDisplay.
7484%
7485% o window: Specifies a pointer to a XWindowInfo structure.
7486%
cristy3ed852e2009-09-05 21:47:34 +00007487*/
7488static MagickBooleanType XMakePixmap(Display *display,
7489 const XResourceInfo *resource_info,XWindowInfo *window)
7490{
7491 unsigned int
7492 height,
7493 width;
7494
7495 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
7496 assert(display != (Display *) NULL);
7497 assert(resource_info != (XResourceInfo *) NULL);
7498 assert(window != (XWindowInfo *) NULL);
7499 if (window->pixmap != (Pixmap) NULL)
7500 {
7501 /*
7502 Destroy previous X pixmap.
7503 */
7504 (void) XFreePixmap(display,window->pixmap);
7505 window->pixmap=(Pixmap) NULL;
7506 }
7507 if (window->use_pixmap == MagickFalse)
7508 return(MagickFalse);
7509 if (window->ximage == (XImage *) NULL)
7510 return(MagickFalse);
7511 /*
7512 Display busy cursor.
7513 */
7514 (void) XCheckDefineCursor(display,window->id,window->busy_cursor);
7515 (void) XFlush(display);
7516 /*
7517 Create pixmap.
7518 */
7519 width=(unsigned int) window->ximage->width;
7520 height=(unsigned int) window->ximage->height;
7521 window->pixmap=XCreatePixmap(display,window->id,width,height,window->depth);
7522 if (window->pixmap == (Pixmap) NULL)
7523 {
7524 /*
7525 Unable to allocate pixmap.
7526 */
7527 (void) XCheckDefineCursor(display,window->id,window->cursor);
7528 return(MagickFalse);
7529 }
7530 /*
7531 Copy X image to pixmap.
7532 */
7533#if defined(MAGICKCORE_HAVE_SHARED_MEMORY)
7534 if (window->shared_memory)
7535 (void) XShmPutImage(display,window->pixmap,window->annotate_context,
7536 window->ximage,0,0,0,0,width,height,MagickTrue);
7537#endif
7538 if (window->shared_memory == MagickFalse)
7539 (void) XPutImage(display,window->pixmap,window->annotate_context,
7540 window->ximage,0,0,0,0,width,height);
7541 if (IsEventLogging())
7542 {
7543 (void) LogMagickEvent(X11Event,GetMagickModule(),"Pixmap:");
7544 (void) LogMagickEvent(X11Event,GetMagickModule()," width, height: %ux%u",
7545 width,height);
7546 }
7547 /*
7548 Restore cursor.
7549 */
7550 (void) XCheckDefineCursor(display,window->id,window->cursor);
7551 return(MagickTrue);
7552}
7553
7554/*
7555%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
7556% %
7557% %
7558% %
7559% X M a k e S t a n d a r d C o l o r m a p %
7560% %
7561% %
7562% %
7563%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
7564%
7565% XMakeStandardColormap() creates an X11 Standard Colormap.
7566%
7567% The format of the XMakeStandardColormap method is:
7568%
7569% XMakeStandardColormap(display,visual_info,resource_info,image,
7570% map_info,pixel)
7571%
7572% A description of each parameter follows:
7573%
7574% o display: Specifies a connection to an X server; returned from
7575% XOpenDisplay.
7576%
7577% o visual_info: Specifies a pointer to a X11 XVisualInfo structure;
7578% returned from XGetVisualInfo.
7579%
7580% o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
7581%
7582% o image: the image.
7583%
7584% o map_info: If a Standard Colormap type is specified, this structure is
7585% initialized with info from the Standard Colormap.
7586%
7587% o pixel: Specifies a pointer to a XPixelInfo structure.
7588%
cristy3ed852e2009-09-05 21:47:34 +00007589*/
7590
7591#if defined(__cplusplus) || defined(c_plusplus)
7592extern "C" {
7593#endif
7594
7595static inline MagickRealType DiversityPixelIntensity(
7596 const DiversityPacket *pixel)
7597{
7598 MagickRealType
7599 intensity;
7600
7601 intensity=0.299*pixel->red+0.587*pixel->green+0.114*pixel->blue;
7602 return(intensity);
7603}
7604
7605static int IntensityCompare(const void *x,const void *y)
7606{
7607 DiversityPacket
7608 *color_1,
7609 *color_2;
7610
7611 int
7612 diversity;
7613
7614 color_1=(DiversityPacket *) x;
7615 color_2=(DiversityPacket *) y;
7616 diversity=(int) (DiversityPixelIntensity(color_2)-
7617 DiversityPixelIntensity(color_1));
7618 return(diversity);
7619}
7620
7621static int PopularityCompare(const void *x,const void *y)
7622{
7623 DiversityPacket
7624 *color_1,
7625 *color_2;
7626
7627 color_1=(DiversityPacket *) x;
7628 color_2=(DiversityPacket *) y;
7629 return((int) color_2->count-(int) color_1->count);
7630}
7631
7632#if defined(__cplusplus) || defined(c_plusplus)
7633}
7634#endif
7635
7636static inline Quantum ScaleXToQuantum(const unsigned long x,
7637 const unsigned long scale)
7638{
7639 return((Quantum) (((MagickRealType) QuantumRange*x)/scale+0.5));
7640}
7641
7642MagickExport void XMakeStandardColormap(Display *display,
7643 XVisualInfo *visual_info,XResourceInfo *resource_info,Image *image,
7644 XStandardColormap *map_info,XPixelInfo *pixel)
7645{
7646 Colormap
7647 colormap;
7648
7649 ExceptionInfo
7650 *exception;
7651
7652 register IndexPacket
7653 *indexes;
7654
7655 register long
7656 i;
7657
7658 Status
7659 status;
7660
7661 unsigned long
7662 number_colors,
7663 retain_colors;
7664
7665 unsigned short
7666 gray_value;
7667
7668 XColor
7669 color,
7670 *colors,
7671 *p;
7672
7673 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
7674 assert(display != (Display *) NULL);
7675 assert(visual_info != (XVisualInfo *) NULL);
7676 assert(map_info != (XStandardColormap *) NULL);
7677 assert(resource_info != (XResourceInfo *) NULL);
7678 assert(pixel != (XPixelInfo *) NULL);
7679 exception=(&image->exception);
7680 if (resource_info->map_type != (char *) NULL)
7681 {
7682 /*
7683 Standard Colormap is already defined (i.e. xstdcmap).
7684 */
7685 XGetPixelPacket(display,visual_info,map_info,resource_info,image,
7686 pixel);
7687 number_colors=(unsigned int) (map_info->base_pixel+
7688 (map_info->red_max+1)*(map_info->green_max+1)*(map_info->blue_max+1));
7689 if ((map_info->red_max*map_info->green_max*map_info->blue_max) != 0)
7690 if ((image->matte == MagickFalse) &&
7691 (resource_info->color_recovery == MagickFalse) &&
7692 resource_info->quantize_info->dither &&
7693 (number_colors < MaxColormapSize))
7694 {
7695 Image
7696 *affinity_image;
7697
7698 register PixelPacket
cristyc47d1f82009-11-26 01:44:43 +00007699 *restrict q;
cristy3ed852e2009-09-05 21:47:34 +00007700
7701 /*
7702 Improve image appearance with error diffusion.
7703 */
7704 affinity_image=AcquireImage((ImageInfo *) NULL);
7705 if (affinity_image == (Image *) NULL)
7706 ThrowXWindowFatalException(ResourceLimitFatalError,
7707 "UnableToDitherImage",image->filename);
7708 affinity_image->columns=number_colors;
7709 affinity_image->rows=1;
7710 /*
7711 Initialize colormap image.
7712 */
7713 q=QueueAuthenticPixels(affinity_image,0,0,affinity_image->columns,
7714 1,exception);
7715 if (q != (PixelPacket *) NULL)
7716 {
7717 for (i=0; i < (long) number_colors; i++)
7718 {
7719 q->red=(Quantum) 0;
7720 if (map_info->red_max != 0)
7721 q->red=ScaleXToQuantum((unsigned long) (i/
7722 map_info->red_mult),map_info->red_max);
7723 q->green=(Quantum) 0;
7724 if (map_info->green_max != 0)
7725 q->green=ScaleXToQuantum((unsigned long) ((i/
7726 map_info->green_mult) % (map_info->green_max+1)),
7727 map_info->green_max);
7728 q->blue=(Quantum) 0;
7729 if (map_info->blue_max != 0)
7730 q->blue=ScaleXToQuantum((unsigned long) (i %
7731 map_info->green_mult),map_info->blue_max);
7732 q->opacity=(Quantum) TransparentOpacity;
7733 q++;
7734 }
7735 (void) SyncAuthenticPixels(affinity_image,exception);
7736 (void) RemapImage(resource_info->quantize_info,image,
7737 affinity_image);
7738 }
7739 XGetPixelPacket(display,visual_info,map_info,resource_info,image,
7740 pixel);
7741 (void) SetImageStorageClass(image,DirectClass);
7742 affinity_image=DestroyImage(affinity_image);
7743 }
7744 if (IsEventLogging())
7745 {
7746 (void) LogMagickEvent(X11Event,GetMagickModule(),
7747 "Standard Colormap:");
7748 (void) LogMagickEvent(X11Event,GetMagickModule(),
7749 " colormap id: 0x%lx",map_info->colormap);
7750 (void) LogMagickEvent(X11Event,GetMagickModule(),
7751 " red, green, blue max: %lu %lu %lu",map_info->red_max,
7752 map_info->green_max,map_info->blue_max);
7753 (void) LogMagickEvent(X11Event,GetMagickModule(),
7754 " red, green, blue mult: %lu %lu %lu",map_info->red_mult,
7755 map_info->green_mult,map_info->blue_mult);
7756 }
7757 return;
7758 }
7759 if ((visual_info->klass != DirectColor) &&
7760 (visual_info->klass != TrueColor))
7761 if ((image->storage_class == DirectClass) ||
7762 ((int) image->colors > visual_info->colormap_size))
7763 {
7764 QuantizeInfo
7765 quantize_info;
7766
7767 /*
7768 Image has more colors than the visual supports.
7769 */
7770 quantize_info=(*resource_info->quantize_info);
7771 quantize_info.number_colors=(unsigned long) visual_info->colormap_size;
7772 (void) QuantizeImage(&quantize_info,image);
7773 }
7774 /*
7775 Free previous and create new colormap.
7776 */
7777 (void) XFreeStandardColormap(display,visual_info,map_info,pixel);
7778 colormap=XDefaultColormap(display,visual_info->screen);
7779 if (visual_info->visual != XDefaultVisual(display,visual_info->screen))
7780 colormap=XCreateColormap(display,XRootWindow(display,visual_info->screen),
7781 visual_info->visual,visual_info->klass == DirectColor ?
7782 AllocAll : AllocNone);
7783 if (colormap == (Colormap) NULL)
7784 ThrowXWindowFatalException(ResourceLimitFatalError,"UnableToCreateColormap",
7785 image->filename);
7786 /*
7787 Initialize the map and pixel info structures.
7788 */
7789 XGetMapInfo(visual_info,colormap,map_info);
7790 XGetPixelPacket(display,visual_info,map_info,resource_info,image,pixel);
7791 /*
7792 Allocating colors in server colormap is based on visual class.
7793 */
7794 switch (visual_info->klass)
7795 {
7796 case StaticGray:
7797 case StaticColor:
7798 {
7799 /*
7800 Define Standard Colormap for StaticGray or StaticColor visual.
7801 */
7802 number_colors=image->colors;
7803 colors=(XColor *) AcquireQuantumMemory((size_t)
7804 visual_info->colormap_size,sizeof(*colors));
7805 if (colors == (XColor *) NULL)
7806 ThrowXWindowFatalException(ResourceLimitFatalError,
7807 "UnableToCreateColormap",image->filename);
7808 p=colors;
7809 color.flags=(char) (DoRed | DoGreen | DoBlue);
7810 for (i=0; i < (long) image->colors; i++)
7811 {
7812 color.red=ScaleQuantumToShort(XRedGamma(image->colormap[i].red));
7813 color.green=ScaleQuantumToShort(XGreenGamma(image->colormap[i].green));
7814 color.blue=ScaleQuantumToShort(XBlueGamma(image->colormap[i].blue));
7815 if (visual_info->klass != StaticColor)
7816 {
7817 gray_value=(unsigned short) XPixelIntensity(&color);
7818 color.red=gray_value;
7819 color.green=gray_value;
7820 color.blue=gray_value;
7821 }
7822 status=XAllocColor(display,colormap,&color);
7823 if (status == False)
7824 {
7825 colormap=XCopyColormapAndFree(display,colormap);
7826 (void) XAllocColor(display,colormap,&color);
7827 }
7828 pixel->pixels[i]=color.pixel;
7829 *p++=color;
7830 }
7831 break;
7832 }
7833 case GrayScale:
7834 case PseudoColor:
7835 {
7836 unsigned int
7837 colormap_type;
7838
7839 /*
7840 Define Standard Colormap for GrayScale or PseudoColor visual.
7841 */
7842 number_colors=image->colors;
7843 colors=(XColor *) AcquireQuantumMemory((size_t)
7844 visual_info->colormap_size,sizeof(*colors));
7845 if (colors == (XColor *) NULL)
7846 ThrowXWindowFatalException(ResourceLimitFatalError,
7847 "UnableToCreateColormap",image->filename);
7848 /*
7849 Preallocate our GUI colors.
7850 */
7851 (void) XAllocColor(display,colormap,&pixel->foreground_color);
7852 (void) XAllocColor(display,colormap,&pixel->background_color);
7853 (void) XAllocColor(display,colormap,&pixel->border_color);
7854 (void) XAllocColor(display,colormap,&pixel->matte_color);
7855 (void) XAllocColor(display,colormap,&pixel->highlight_color);
7856 (void) XAllocColor(display,colormap,&pixel->shadow_color);
7857 (void) XAllocColor(display,colormap,&pixel->depth_color);
7858 (void) XAllocColor(display,colormap,&pixel->trough_color);
7859 for (i=0; i < MaxNumberPens; i++)
7860 (void) XAllocColor(display,colormap,&pixel->pen_colors[i]);
7861 /*
7862 Determine if image colors will "fit" into X server colormap.
7863 */
7864 colormap_type=resource_info->colormap;
7865 status=XAllocColorCells(display,colormap,MagickFalse,(unsigned long *)
7866 NULL,0,pixel->pixels,(unsigned int) image->colors);
7867 if (status != False)
7868 colormap_type=PrivateColormap;
7869 if (colormap_type == SharedColormap)
7870 {
7871 DiversityPacket
7872 *diversity;
7873
7874 int
7875 y;
7876
7877 register int
7878 x;
7879
7880 unsigned short
7881 index;
7882
7883 XColor
7884 *server_colors;
7885
7886 /*
7887 Define Standard colormap for shared GrayScale or PseudoColor visual.
7888 */
7889 diversity=(DiversityPacket *) AcquireQuantumMemory(image->colors,
7890 sizeof(*diversity));
7891 if (diversity == (DiversityPacket *) NULL)
7892 ThrowXWindowFatalException(ResourceLimitFatalError,
7893 "UnableToCreateColormap",image->filename);
7894 for (i=0; i < (long) image->colors; i++)
7895 {
7896 diversity[i].red=image->colormap[i].red;
7897 diversity[i].green=image->colormap[i].green;
7898 diversity[i].blue=image->colormap[i].blue;
7899 diversity[i].index=(unsigned short) i;
7900 diversity[i].count=0;
7901 }
7902 for (y=0; y < (int) image->rows; y++)
7903 {
7904 register long
7905 x;
7906
7907 register PixelPacket
cristyc47d1f82009-11-26 01:44:43 +00007908 *restrict q;
cristy3ed852e2009-09-05 21:47:34 +00007909
7910 q=GetAuthenticPixels(image,0,y,image->columns,1,exception);
7911 if (q == (PixelPacket *) NULL)
7912 break;
7913 indexes=GetAuthenticIndexQueue(image);
7914 for (x=(long) image->columns-1; x >= 0; x--)
7915 diversity[(long) indexes[x]].count++;
7916 }
7917 /*
7918 Sort colors by decreasing intensity.
7919 */
7920 qsort((void *) diversity,image->colors,sizeof(*diversity),
7921 IntensityCompare);
7922 for (i=0; i < (long) image->colors; )
7923 {
7924 diversity[i].count<<=4; /* increase this colors popularity */
7925 i+=MagickMax((long) (image->colors >> 4),2);
7926 }
7927 diversity[image->colors-1].count<<=4;
7928 qsort((void *) diversity,image->colors,sizeof(*diversity),
7929 PopularityCompare);
7930 /*
7931 Allocate colors.
7932 */
7933 p=colors;
7934 color.flags=(char) (DoRed | DoGreen | DoBlue);
7935 for (i=0; i < (long) image->colors; i++)
7936 {
7937 index=diversity[i].index;
7938 color.red=
7939 ScaleQuantumToShort(XRedGamma(image->colormap[index].red));
7940 color.green=
7941 ScaleQuantumToShort(XGreenGamma(image->colormap[index].green));
7942 color.blue=
7943 ScaleQuantumToShort(XBlueGamma(image->colormap[index].blue));
7944 if (visual_info->klass != PseudoColor)
7945 {
7946 gray_value=(unsigned short) XPixelIntensity(&color);
7947 color.red=gray_value;
7948 color.green=gray_value;
7949 color.blue=gray_value;
7950 }
7951 status=XAllocColor(display,colormap,&color);
7952 if (status == False)
7953 break;
7954 pixel->pixels[index]=color.pixel;
7955 *p++=color;
7956 }
7957 /*
7958 Read X server colormap.
7959 */
7960 server_colors=(XColor *) AcquireQuantumMemory((size_t)
7961 visual_info->colormap_size,sizeof(*server_colors));
7962 if (server_colors == (XColor *) NULL)
7963 ThrowXWindowFatalException(ResourceLimitFatalError,
7964 "UnableToCreateColormap",image->filename);
7965 for (x=visual_info->colormap_size-1; x >= 0; x--)
7966 server_colors[x].pixel=(unsigned long) x;
7967 (void) XQueryColors(display,colormap,server_colors,
7968 (int) MagickMin((unsigned int) visual_info->colormap_size,256));
7969 /*
7970 Select remaining colors from X server colormap.
7971 */
7972 for (; i < (long) image->colors; i++)
7973 {
7974 index=diversity[i].index;
7975 color.red=
7976 ScaleQuantumToShort(XRedGamma(image->colormap[index].red));
7977 color.green=
7978 ScaleQuantumToShort(XGreenGamma(image->colormap[index].green));
7979 color.blue=
7980 ScaleQuantumToShort(XBlueGamma(image->colormap[index].blue));
7981 if (visual_info->klass != PseudoColor)
7982 {
7983 gray_value=(unsigned short) XPixelIntensity(&color);
7984 color.red=gray_value;
7985 color.green=gray_value;
7986 color.blue=gray_value;
7987 }
7988 XBestPixel(display,colormap,server_colors,(unsigned int)
7989 visual_info->colormap_size,&color);
7990 pixel->pixels[index]=color.pixel;
7991 *p++=color;
7992 }
7993 if ((int) image->colors < visual_info->colormap_size)
7994 {
7995 /*
7996 Fill up colors array-- more choices for pen colors.
7997 */
7998 retain_colors=MagickMin((unsigned int)
7999 (visual_info->colormap_size-image->colors),256);
8000 for (i=0; i < (long) retain_colors; i++)
8001 *p++=server_colors[i];
8002 number_colors+=retain_colors;
8003 }
8004 server_colors=(XColor *) RelinquishMagickMemory(server_colors);
8005 diversity=(DiversityPacket *) RelinquishMagickMemory(diversity);
8006 break;
8007 }
8008 /*
8009 Define Standard colormap for private GrayScale or PseudoColor visual.
8010 */
8011 if (status == False)
8012 {
8013 /*
8014 Not enough colormap entries in the colormap-- Create a new colormap.
8015 */
8016 colormap=XCreateColormap(display,
8017 XRootWindow(display,visual_info->screen),visual_info->visual,
8018 AllocNone);
8019 if (colormap == (Colormap) NULL)
8020 ThrowXWindowFatalException(ResourceLimitFatalError,
8021 "UnableToCreateColormap",image->filename);
8022 map_info->colormap=colormap;
8023 if ((int) image->colors < visual_info->colormap_size)
8024 {
8025 /*
8026 Retain colors from the default colormap to help lessens the
8027 effects of colormap flashing.
8028 */
8029 retain_colors=MagickMin((unsigned int)
8030 (visual_info->colormap_size-image->colors),256);
8031 p=colors+image->colors;
8032 for (i=0; i < (long) retain_colors; i++)
8033 {
8034 p->pixel=(unsigned long) i;
8035 p++;
8036 }
8037 (void) XQueryColors(display,
8038 XDefaultColormap(display,visual_info->screen),
8039 colors+image->colors,(int) retain_colors);
8040 /*
8041 Transfer colors from default to private colormap.
8042 */
8043 (void) XAllocColorCells(display,colormap,MagickFalse,
8044 (unsigned long *) NULL,0,pixel->pixels,(unsigned int)
8045 retain_colors);
8046 p=colors+image->colors;
8047 for (i=0; i < (long) retain_colors; i++)
8048 {
8049 p->pixel=pixel->pixels[i];
8050 p++;
8051 }
8052 (void) XStoreColors(display,colormap,colors+image->colors,
8053 (int) retain_colors);
8054 number_colors+=retain_colors;
8055 }
8056 (void) XAllocColorCells(display,colormap,MagickFalse,
8057 (unsigned long *) NULL,0,pixel->pixels,(unsigned int)
8058 image->colors);
8059 }
8060 /*
8061 Store the image colormap.
8062 */
8063 p=colors;
8064 color.flags=(char) (DoRed | DoGreen | DoBlue);
8065 for (i=0; i < (long) image->colors; i++)
8066 {
8067 color.red=ScaleQuantumToShort(XRedGamma(image->colormap[i].red));
8068 color.green=ScaleQuantumToShort(XGreenGamma(image->colormap[i].green));
8069 color.blue=ScaleQuantumToShort(XBlueGamma(image->colormap[i].blue));
8070 if (visual_info->klass != PseudoColor)
8071 {
8072 gray_value=(unsigned short) XPixelIntensity(&color);
8073 color.red=gray_value;
8074 color.green=gray_value;
8075 color.blue=gray_value;
8076 }
8077 color.pixel=pixel->pixels[i];
8078 *p++=color;
8079 }
8080 (void) XStoreColors(display,colormap,colors,(int) image->colors);
8081 break;
8082 }
8083 case TrueColor:
8084 case DirectColor:
8085 default:
8086 {
8087 MagickBooleanType
8088 linear_colormap;
8089
8090 /*
8091 Define Standard Colormap for TrueColor or DirectColor visual.
8092 */
8093 number_colors=(unsigned int) ((map_info->red_max*map_info->red_mult)+
8094 (map_info->green_max*map_info->green_mult)+
8095 (map_info->blue_max*map_info->blue_mult)+1);
8096 linear_colormap=(number_colors > 4096) ||
8097 (((int) (map_info->red_max+1) == visual_info->colormap_size) &&
8098 ((int) (map_info->green_max+1) == visual_info->colormap_size) &&
8099 ((int) (map_info->blue_max+1) == visual_info->colormap_size)) ?
8100 MagickTrue : MagickFalse;
8101 if (linear_colormap != MagickFalse)
8102 number_colors=(unsigned long) visual_info->colormap_size;
8103 /*
8104 Allocate color array.
8105 */
8106 colors=(XColor *) AcquireQuantumMemory(number_colors,sizeof(*colors));
8107 if (colors == (XColor *) NULL)
8108 ThrowXWindowFatalException(ResourceLimitFatalError,
8109 "UnableToCreateColormap",image->filename);
8110 /*
8111 Initialize linear color ramp.
8112 */
8113 p=colors;
8114 color.flags=(char) (DoRed | DoGreen | DoBlue);
8115 if (linear_colormap != MagickFalse)
8116 for (i=0; i < (long) number_colors; i++)
8117 {
8118 color.blue=(unsigned short) 0;
8119 if (map_info->blue_max != 0)
8120 color.blue=(unsigned short) ((unsigned long)
8121 ((65535L*(i % map_info->green_mult))/map_info->blue_max));
8122 color.green=color.blue;
8123 color.red=color.blue;
8124 color.pixel=XStandardPixel(map_info,&color);
8125 *p++=color;
8126 }
8127 else
8128 for (i=0; i < (long) number_colors; i++)
8129 {
8130 color.red=(unsigned short) 0;
8131 if (map_info->red_max != 0)
8132 color.red=(unsigned short) ((unsigned long)
8133 ((65535L*(i/map_info->red_mult))/map_info->red_max));
8134 color.green=(unsigned int) 0;
8135 if (map_info->green_max != 0)
8136 color.green=(unsigned short) ((unsigned long)
8137 ((65535L*((i/map_info->green_mult) % (map_info->green_max+1)))/
8138 map_info->green_max));
8139 color.blue=(unsigned short) 0;
8140 if (map_info->blue_max != 0)
8141 color.blue=(unsigned short) ((unsigned long)
8142 ((65535L*(i % map_info->green_mult))/map_info->blue_max));
8143 color.pixel=XStandardPixel(map_info,&color);
8144 *p++=color;
8145 }
8146 if ((visual_info->klass == DirectColor) &&
8147 (colormap != XDefaultColormap(display,visual_info->screen)))
8148 (void) XStoreColors(display,colormap,colors,(int) number_colors);
8149 else
8150 for (i=0; i < (long) number_colors; i++)
8151 (void) XAllocColor(display,colormap,&colors[i]);
8152 break;
8153 }
8154 }
8155 if ((visual_info->klass != DirectColor) &&
8156 (visual_info->klass != TrueColor))
8157 {
8158 /*
8159 Set foreground, background, border, etc. pixels.
8160 */
8161 XBestPixel(display,colormap,colors,(unsigned int) number_colors,
8162 &pixel->foreground_color);
8163 XBestPixel(display,colormap,colors,(unsigned int) number_colors,
8164 &pixel->background_color);
8165 if (pixel->background_color.pixel == pixel->foreground_color.pixel)
8166 {
8167 /*
8168 Foreground and background colors must differ.
8169 */
8170 pixel->background_color.red=(~pixel->foreground_color.red);
8171 pixel->background_color.green=
8172 (~pixel->foreground_color.green);
8173 pixel->background_color.blue=
8174 (~pixel->foreground_color.blue);
8175 XBestPixel(display,colormap,colors,(unsigned int) number_colors,
8176 &pixel->background_color);
8177 }
8178 XBestPixel(display,colormap,colors,(unsigned int) number_colors,
8179 &pixel->border_color);
8180 XBestPixel(display,colormap,colors,(unsigned int) number_colors,
8181 &pixel->matte_color);
8182 XBestPixel(display,colormap,colors,(unsigned int) number_colors,
8183 &pixel->highlight_color);
8184 XBestPixel(display,colormap,colors,(unsigned int) number_colors,
8185 &pixel->shadow_color);
8186 XBestPixel(display,colormap,colors,(unsigned int) number_colors,
8187 &pixel->depth_color);
8188 XBestPixel(display,colormap,colors,(unsigned int) number_colors,
8189 &pixel->trough_color);
8190 for (i=0; i < MaxNumberPens; i++)
8191 {
8192 XBestPixel(display,colormap,colors,(unsigned int) number_colors,
8193 &pixel->pen_colors[i]);
8194 pixel->pixels[image->colors+i]=pixel->pen_colors[i].pixel;
8195 }
8196 pixel->colors=image->colors+MaxNumberPens;
8197 }
8198 colors=(XColor *) RelinquishMagickMemory(colors);
8199 if (IsEventLogging())
8200 {
8201 (void) LogMagickEvent(X11Event,GetMagickModule(),"Standard Colormap:");
8202 (void) LogMagickEvent(X11Event,GetMagickModule()," colormap id: 0x%lx",
8203 map_info->colormap);
8204 (void) LogMagickEvent(X11Event,GetMagickModule(),
8205 " red, green, blue max: %lu %lu %lu",map_info->red_max,
8206 map_info->green_max,map_info->blue_max);
8207 (void) LogMagickEvent(X11Event,GetMagickModule(),
8208 " red, green, blue mult: %lu %lu %lu",map_info->red_mult,
8209 map_info->green_mult,map_info->blue_mult);
8210 }
8211}
8212
8213/*
8214%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8215% %
8216% %
8217% %
8218% X M a k e W i n d o w %
8219% %
8220% %
8221% %
8222%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8223%
8224% XMakeWindow() creates an X11 window.
8225%
8226% The format of the XMakeWindow method is:
8227%
8228% void XMakeWindow(Display *display,Window parent,char **argv,int argc,
8229% XClassHint *class_hint,XWMHints *manager_hints,
8230% XWindowInfo *window_info)
8231%
8232% A description of each parameter follows:
8233%
8234% o display: Specifies a connection to an X server; returned from
8235% XOpenDisplay.
8236%
8237% o parent: Specifies the parent window_info.
8238%
8239% o argv: Specifies the application's argument list.
8240%
8241% o argc: Specifies the number of arguments.
8242%
8243% o class_hint: Specifies a pointer to a X11 XClassHint structure.
8244%
8245% o manager_hints: Specifies a pointer to a X11 XWMHints structure.
8246%
8247% o window_info: Specifies a pointer to a X11 XWindowInfo structure.
8248%
8249*/
8250MagickExport void XMakeWindow(Display *display,Window parent,char **argv,
8251 int argc,XClassHint *class_hint,XWMHints *manager_hints,
8252 XWindowInfo *window_info)
8253{
8254#define MinWindowSize 64
8255
8256 Atom
8257 atom_list[2];
8258
8259 int
8260 gravity;
8261
8262 static XTextProperty
8263 icon_name,
8264 window_name;
8265
8266 Status
8267 status;
8268
8269 XSizeHints
8270 *size_hints;
8271
8272 /*
8273 Set window info hints.
8274 */
8275 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
8276 assert(display != (Display *) NULL);
8277 assert(window_info != (XWindowInfo *) NULL);
8278 size_hints=XAllocSizeHints();
8279 if (size_hints == (XSizeHints *) NULL)
8280 ThrowXWindowFatalException(XServerFatalError,"UnableToMakeXWindow",argv[0]);
8281 size_hints->flags=(long) window_info->flags;
8282 size_hints->x=window_info->x;
8283 size_hints->y=window_info->y;
8284 size_hints->width=(int) window_info->width;
8285 size_hints->height=(int) window_info->height;
8286 if (window_info->immutable != MagickFalse)
8287 {
8288 /*
8289 Window size cannot be changed.
8290 */
8291 size_hints->min_width=size_hints->width;
8292 size_hints->min_height=size_hints->height;
8293 size_hints->max_width=size_hints->width;
8294 size_hints->max_height=size_hints->height;
8295 size_hints->flags|=PMinSize;
8296 size_hints->flags|=PMaxSize;
8297 }
8298 else
8299 {
8300 /*
8301 Window size can be changed.
8302 */
8303 size_hints->min_width=(int) window_info->min_width;
8304 size_hints->min_height=(int) window_info->min_height;
8305 size_hints->flags|=PResizeInc;
8306 size_hints->width_inc=(int) window_info->width_inc;
8307 size_hints->height_inc=(int) window_info->height_inc;
8308#if !defined(PRE_R4_ICCCM)
8309 size_hints->flags|=PBaseSize;
8310 size_hints->base_width=size_hints->width_inc;
8311 size_hints->base_height=size_hints->height_inc;
8312#endif
8313 }
8314 gravity=NorthWestGravity;
8315 if (window_info->geometry != (char *) NULL)
8316 {
8317 char
8318 default_geometry[MaxTextExtent],
8319 geometry[MaxTextExtent];
8320
8321 int
8322 flags;
8323
8324 register char
8325 *p;
8326
8327 /*
8328 User specified geometry.
8329 */
8330 (void) FormatMagickString(default_geometry,MaxTextExtent,"%dx%d",
8331 size_hints->width,size_hints->height);
8332 (void) CopyMagickString(geometry,window_info->geometry,MaxTextExtent);
8333 p=geometry;
8334 while (strlen(p) != 0)
8335 {
8336 if ((isspace((int) ((unsigned char) *p)) == 0) && (*p != '%'))
8337 p++;
8338 else
8339 (void) CopyMagickString(p,p+1,MaxTextExtent);
8340 }
8341 flags=XWMGeometry(display,window_info->screen,geometry,default_geometry,
8342 window_info->border_width,size_hints,&size_hints->x,&size_hints->y,
8343 &size_hints->width,&size_hints->height,&gravity);
8344 if ((flags & WidthValue) && (flags & HeightValue))
8345 size_hints->flags|=USSize;
8346 if ((flags & XValue) && (flags & YValue))
8347 {
8348 size_hints->flags|=USPosition;
8349 window_info->x=size_hints->x;
8350 window_info->y=size_hints->y;
8351 }
8352 }
8353#if !defined(PRE_R4_ICCCM)
8354 size_hints->win_gravity=gravity;
8355 size_hints->flags|=PWinGravity;
8356#endif
8357 if (window_info->id == (Window) NULL)
8358 window_info->id=XCreateWindow(display,parent,window_info->x,window_info->y,
8359 (unsigned int) size_hints->width,(unsigned int) size_hints->height,
8360 window_info->border_width,(int) window_info->depth,InputOutput,
8361 window_info->visual,window_info->mask,&window_info->attributes);
8362 else
8363 {
8364 MagickStatusType
8365 mask;
8366
8367 XEvent
8368 sans_event;
8369
8370 XWindowChanges
8371 window_changes;
8372
8373 /*
8374 Window already exists; change relevant attributes.
8375 */
8376 (void) XChangeWindowAttributes(display,window_info->id,window_info->mask,
8377 &window_info->attributes);
8378 mask=ConfigureNotify;
8379 while (XCheckTypedWindowEvent(display,window_info->id,(int) mask,&sans_event)) ;
8380 window_changes.x=window_info->x;
8381 window_changes.y=window_info->y;
8382 window_changes.width=(int) window_info->width;
8383 window_changes.height=(int) window_info->height;
8384 mask=(MagickStatusType) (CWWidth | CWHeight);
8385 if (window_info->flags & USPosition)
8386 mask|=CWX | CWY;
8387 (void) XReconfigureWMWindow(display,window_info->id,window_info->screen,
8388 mask,&window_changes);
8389 }
8390 if (window_info->id == (Window) NULL)
8391 ThrowXWindowFatalException(XServerFatalError,"UnableToCreateWindow",
8392 window_info->name);
8393 status=XStringListToTextProperty(&window_info->name,1,&window_name);
8394 if (status == False)
8395 ThrowXWindowFatalException(XServerFatalError,"UnableToCreateTextProperty",
8396 window_info->name);
8397 status=XStringListToTextProperty(&window_info->icon_name,1,&icon_name);
8398 if (status == False)
8399 ThrowXWindowFatalException(XServerFatalError,"UnableToCreateTextProperty",
8400 window_info->icon_name);
8401 if (window_info->icon_geometry != (char *) NULL)
8402 {
8403 int
8404 flags,
8405 height,
8406 width;
8407
8408 /*
8409 User specified icon geometry.
8410 */
8411 size_hints->flags|=USPosition;
8412 flags=XWMGeometry(display,window_info->screen,window_info->icon_geometry,
8413 (char *) NULL,0,size_hints,&manager_hints->icon_x,
8414 &manager_hints->icon_y,&width,&height,&gravity);
8415 if ((flags & XValue) && (flags & YValue))
8416 manager_hints->flags|=IconPositionHint;
8417 }
8418 XSetWMProperties(display,window_info->id,&window_name,&icon_name,argv,argc,
8419 size_hints,manager_hints,class_hint);
8420 if (window_name.value != (void *) NULL)
8421 {
8422 (void) XFree((void *) window_name.value);
8423 window_name.value=(unsigned char *) NULL;
8424 window_name.nitems=0;
8425 }
8426 if (icon_name.value != (void *) NULL)
8427 {
8428 (void) XFree((void *) icon_name.value);
8429 icon_name.value=(unsigned char *) NULL;
8430 icon_name.nitems=0;
8431 }
8432 atom_list[0]=XInternAtom(display,"WM_DELETE_WINDOW",MagickFalse);
8433 atom_list[1]=XInternAtom(display,"WM_TAKE_FOCUS",MagickFalse);
8434 (void) XSetWMProtocols(display,window_info->id,atom_list,2);
8435 (void) XFree((void *) size_hints);
8436 if (window_info->shape != MagickFalse)
8437 {
8438#if defined(MAGICKCORE_HAVE_SHAPE)
8439 int
8440 error_base,
8441 event_base;
8442
8443 /*
8444 Can we apply a non-rectangular shaping mask?
8445 */
8446 error_base=0;
8447 event_base=0;
8448 if (XShapeQueryExtension(display,&error_base,&event_base) == 0)
8449 window_info->shape=MagickFalse;
8450#else
8451 window_info->shape=MagickFalse;
8452#endif
8453 }
8454 if (window_info->shared_memory)
8455 {
8456#if defined(MAGICKCORE_HAVE_SHARED_MEMORY)
8457 /*
8458 Can we use shared memory with this window?
8459 */
8460 if (XShmQueryExtension(display) == 0)
8461 window_info->shared_memory=MagickFalse;
8462#else
8463 window_info->shared_memory=MagickFalse;
8464#endif
8465 }
8466 window_info->image=NewImageList();
8467 window_info->destroy=MagickFalse;
8468}
8469
8470/*
8471%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8472% %
8473% %
8474% %
8475% X M a g i c k P r o g r e s s M o n i t o r %
8476% %
8477% %
8478% %
8479%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8480%
8481% XMagickProgressMonitor() displays the progress a task is making in
8482% completing a task.
8483%
8484% The format of the XMagickProgressMonitor method is:
8485%
8486% void XMagickProgressMonitor(const char *task,
8487% const MagickOffsetType quantum,const MagickSizeType span,
8488% void *client_data)
8489%
8490% A description of each parameter follows:
8491%
8492% o task: Identifies the task in progress.
8493%
8494% o quantum: Specifies the quantum position within the span which represents
8495% how much progress has been made in completing a task.
8496%
8497% o span: Specifies the span relative to completing a task.
8498%
8499% o client_data: Pointer to any client data.
8500%
8501*/
8502
8503static const char *GetLocaleMonitorMessage(const char *text)
8504{
8505 char
8506 message[MaxTextExtent],
8507 tag[MaxTextExtent];
8508
8509 const char
8510 *locale_message;
8511
8512 register char
8513 *p;
8514
8515 (void) CopyMagickMemory(tag,text,MaxTextExtent);
8516 p=strrchr(tag,'/');
8517 if (p != (char *) NULL)
8518 *p='\0';
8519 (void) FormatMagickString(message,MaxTextExtent,"Monitor/%s",tag);
8520 locale_message=GetLocaleMessage(message);
8521 if (locale_message == message)
8522 return(text);
8523 return(locale_message);
8524}
8525
8526MagickExport MagickBooleanType XMagickProgressMonitor(const char *tag,
8527 const MagickOffsetType quantum,const MagickSizeType span,
8528 void *magick_unused(client_data))
8529{
8530 XWindows
8531 *windows;
8532
8533 windows=XSetWindows((XWindows *) ~0);
8534 if (windows == (XWindows *) NULL)
8535 return(MagickTrue);
8536 if (windows->info.mapped != MagickFalse)
8537 XProgressMonitorWidget(windows->display,windows,
8538 GetLocaleMonitorMessage(tag),quantum,span);
8539 return(MagickTrue);
8540}
8541
8542/*
8543%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8544% %
8545% %
8546% %
8547% X Q u e r y C o l o r D a t a b a s e %
8548% %
8549% %
8550% %
8551%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8552%
8553% XQueryColorDatabase() looks up a RGB values for a color given in the target
8554% string.
8555%
8556% The format of the XQueryColorDatabase method is:
8557%
8558% MagickBooleanType XQueryColorDatabase(const char *target,XColor *color)
8559%
8560% A description of each parameter follows:
8561%
8562% o target: Specifies the color to lookup in the X color database.
8563%
8564% o color: A pointer to an PixelPacket structure. The RGB value of the target
8565% color is returned as this value.
8566%
8567*/
8568MagickExport MagickBooleanType XQueryColorDatabase(const char *target,
8569 XColor *color)
8570{
8571 Colormap
8572 colormap;
8573
8574 static Display
8575 *display = (Display *) NULL;
8576
8577 Status
8578 status;
8579
8580 XColor
8581 xcolor;
8582
8583 /*
8584 Initialize color return value.
8585 */
8586 assert(color != (XColor *) NULL);
8587 color->red=0;
8588 color->green=0;
8589 color->blue=0;
8590 color->flags=(char) (DoRed | DoGreen | DoBlue);
8591 if ((target == (char *) NULL) || (*target == '\0'))
8592 target="#ffffffffffff";
8593 /*
8594 Let the X server define the color for us.
8595 */
8596 if (display == (Display *) NULL)
8597 display=XOpenDisplay((char *) NULL);
8598 if (display == (Display *) NULL)
8599 {
8600 ThrowXWindowFatalException(XServerError,"ColorIsNotKnownToServer",target);
8601 return(MagickFalse);
8602 }
8603 colormap=XDefaultColormap(display,XDefaultScreen(display));
8604 status=XParseColor(display,colormap,(char *) target,&xcolor);
8605 if (status == False)
8606 ThrowXWindowFatalException(XServerError,"ColorIsNotKnownToServer",target)
8607 else
8608 {
8609 color->red=xcolor.red;
8610 color->green=xcolor.green;
8611 color->blue=xcolor.blue;
8612 color->flags=xcolor.flags;
8613 }
8614 return(status != False ? MagickTrue : MagickFalse);
8615}
8616
8617/*
8618%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8619% %
8620% %
8621% %
8622% X Q u e r y P o s i t i o n %
8623% %
8624% %
8625% %
8626%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8627%
8628% XQueryPosition() gets the pointer coordinates relative to a window.
8629%
8630% The format of the XQueryPosition method is:
8631%
8632% void XQueryPosition(Display *display,const Window window,int *x,int *y)
8633%
8634% A description of each parameter follows:
8635%
8636% o display: Specifies a connection to an X server; returned from
8637% XOpenDisplay.
8638%
8639% o window: Specifies a pointer to a Window.
8640%
8641% o x: Return the x coordinate of the pointer relative to the origin of the
8642% window.
8643%
8644% o y: Return the y coordinate of the pointer relative to the origin of the
8645% window.
8646%
8647*/
8648MagickExport void XQueryPosition(Display *display,const Window window,int *x,int *y)
8649{
8650 int
8651 x_root,
8652 y_root;
8653
8654 unsigned int
8655 mask;
8656
8657 Window
8658 root_window;
8659
8660 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
8661 assert(display != (Display *) NULL);
8662 assert(window != (Window) NULL);
8663 assert(x != (int *) NULL);
8664 assert(y != (int *) NULL);
8665 (void) XQueryPointer(display,window,&root_window,&root_window,&x_root,&y_root,
8666 x,y,&mask);
8667}
8668
8669/*
8670%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8671% %
8672% %
8673% %
8674% X R e f r e s h W i n d o w %
8675% %
8676% %
8677% %
8678%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8679%
8680% XRefreshWindow() refreshes an image in a X window.
8681%
8682% The format of the XRefreshWindow method is:
8683%
8684% void XRefreshWindow(Display *display,const XWindowInfo *window,
8685% const XEvent *event)
8686%
8687% A description of each parameter follows:
8688%
8689% o display: Specifies a connection to an X server; returned from
8690% XOpenDisplay.
8691%
8692% o window: Specifies a pointer to a XWindowInfo structure.
8693%
8694% o event: Specifies a pointer to a XEvent structure. If it is NULL,
8695% the entire image is refreshed.
8696%
8697*/
8698MagickExport void XRefreshWindow(Display *display,const XWindowInfo *window,
8699 const XEvent *event)
8700{
8701 int
8702 x,
8703 y;
8704
8705 unsigned int
8706 height,
8707 width;
8708
8709 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
8710 assert(display != (Display *) NULL);
8711 assert(window != (XWindowInfo *) NULL);
8712 if (window->ximage == (XImage *) NULL)
8713 return;
8714 if (event != (XEvent *) NULL)
8715 {
8716 /*
8717 Determine geometry from expose event.
8718 */
8719 x=event->xexpose.x;
8720 y=event->xexpose.y;
8721 width=(unsigned int) event->xexpose.width;
8722 height=(unsigned int) event->xexpose.height;
8723 }
8724 else
8725 {
8726 XEvent
8727 sans_event;
8728
8729 /*
8730 Refresh entire window; discard outstanding expose events.
8731 */
8732 x=0;
8733 y=0;
8734 width=window->width;
8735 height=window->height;
8736 while (XCheckTypedWindowEvent(display,window->id,Expose,&sans_event)) ;
8737 }
8738 /*
8739 Check boundary conditions.
8740 */
8741 if ((window->ximage->width-(x+window->x)) < (int) width)
8742 width=(unsigned int) (window->ximage->width-(x+window->x));
8743 if ((window->ximage->height-(y+window->y)) < (int) height)
8744 height=(unsigned int) (window->ximage->height-(y+window->y));
8745 /*
8746 Refresh image.
8747 */
8748 if (window->matte_pixmap != (Pixmap) NULL)
8749 {
8750#if defined(MAGICKCORE_HAVE_SHAPE)
8751 if (window->shape != MagickFalse)
8752 XShapeCombineMask(display,window->id,ShapeBounding,0,0,
8753 window->matte_pixmap,ShapeSet);
8754#endif
8755 (void) XSetClipMask(display,window->annotate_context,
8756 window->matte_pixmap);
8757 }
8758 if (window->pixmap != (Pixmap) NULL)
8759 {
8760 if (window->depth > 1)
8761 (void) XCopyArea(display,window->pixmap,window->id,
8762 window->annotate_context,x+window->x,y+window->y,width,height,x,y);
8763 else
8764 (void) XCopyPlane(display,window->pixmap,window->id,
8765 window->highlight_context,x+window->x,y+window->y,width,height,x,y,
8766 1L);
8767 }
8768 else
8769 {
8770#if defined(MAGICKCORE_HAVE_SHARED_MEMORY)
8771 if (window->shared_memory)
8772 (void) XShmPutImage(display,window->id,window->annotate_context,
8773 window->ximage,x+window->x,y+window->y,x,y,width,height,MagickTrue);
8774#endif
8775 if (window->shared_memory == MagickFalse)
8776 (void) XPutImage(display,window->id,window->annotate_context,
8777 window->ximage,x+window->x,y+window->y,x,y,width,height);
8778 }
8779 if (window->matte_pixmap != (Pixmap) NULL)
8780 (void) XSetClipMask(display,window->annotate_context,None);
8781 (void) XFlush(display);
8782}
8783
8784/*
8785%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8786% %
8787% %
8788% %
8789% X R e m o t e C o m m a n d %
8790% %
8791% %
8792% %
8793%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8794%
8795% XRemoteCommand() forces a remote display(1) to display the specified
8796% image filename.
8797%
8798% The format of the XRemoteCommand method is:
8799%
8800% MagickBooleanType XRemoteCommand(Display *display,const char *window,
8801% const char *filename)
8802%
8803% A description of each parameter follows:
8804%
8805% o display: Specifies a connection to an X server; returned from
8806% XOpenDisplay.
8807%
8808% o window: Specifies the name or id of an X window.
8809%
8810% o filename: the name of the image filename to display.
8811%
8812*/
8813MagickExport MagickBooleanType XRemoteCommand(Display *display,
8814 const char *window,const char *filename)
8815{
8816 Atom
8817 remote_atom;
8818
8819 Window
8820 remote_window,
8821 root_window;
8822
8823 assert(filename != (char *) NULL);
8824 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",filename);
8825 if (display == (Display *) NULL)
8826 display=XOpenDisplay((char *) NULL);
8827 if (display == (Display *) NULL)
8828 {
8829 ThrowXWindowException(XServerError,"UnableToOpenXServer",filename);
8830 return(MagickFalse);
8831 }
8832 remote_atom=XInternAtom(display,"IM_PROTOCOLS",MagickFalse);
8833 remote_window=(Window) NULL;
8834 root_window=XRootWindow(display,XDefaultScreen(display));
8835 if (window != (char *) NULL)
8836 {
8837 /*
8838 Search window hierarchy and identify any clients by name or ID.
8839 */
8840 if (isdigit((unsigned char) *window) != 0)
8841 remote_window=XWindowByID(display,root_window,(Window)
8842 strtol((char *) window,(char **) NULL,0));
8843 if (remote_window == (Window) NULL)
8844 remote_window=XWindowByName(display,root_window,window);
8845 }
8846 if (remote_window == (Window) NULL)
8847 remote_window=XWindowByProperty(display,root_window,remote_atom);
8848 if (remote_window == (Window) NULL)
8849 {
8850 ThrowXWindowException(XServerError,"UnableToConnectToRemoteDisplay",
8851 filename);
8852 return(MagickFalse);
8853 }
8854 /*
8855 Send remote command.
8856 */
8857 remote_atom=XInternAtom(display,"IM_REMOTE_COMMAND",MagickFalse);
8858 (void) XChangeProperty(display,remote_window,remote_atom,XA_STRING,8,
8859 PropModeReplace,(unsigned char *) filename,(int) strlen(filename));
8860 (void) XSync(display,MagickFalse);
8861 return(MagickTrue);
8862}
8863
8864/*
8865%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8866% %
8867% %
8868% %
8869% X R e t a i n W i n d o w C o l o r s %
8870% %
8871% %
8872% %
8873%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8874%
8875% XRetainWindowColors() sets X11 color resources on a window. This preserves
8876% the colors associated with an image displayed on the window.
8877%
8878% The format of the XRetainWindowColors method is:
8879%
8880% void XRetainWindowColors(Display *display,const Window window)
8881%
8882% A description of each parameter follows:
8883%
8884% o display: Specifies a connection to an X server; returned from
8885% XOpenDisplay.
8886%
8887% o window: Specifies a pointer to a XWindowInfo structure.
8888%
8889*/
8890MagickExport void XRetainWindowColors(Display *display,const Window window)
8891{
8892 Atom
8893 property;
8894
8895 Pixmap
8896 pixmap;
8897
8898 /*
8899 Put property on the window.
8900 */
8901 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
8902 assert(display != (Display *) NULL);
8903 assert(window != (Window) NULL);
8904 property=XInternAtom(display,"_XSETROOT_ID",MagickFalse);
8905 if (property == (Atom) NULL)
8906 {
8907 ThrowXWindowFatalException(XServerError,"UnableToCreateProperty",
8908 "_XSETROOT_ID");
8909 return;
8910 }
8911 pixmap=XCreatePixmap(display,window,1,1,1);
8912 if (pixmap == (Pixmap) NULL)
8913 {
8914 ThrowXWindowFatalException(XServerError,"UnableToCreateBitmap","");
8915 return;
8916 }
8917 (void) XChangeProperty(display,window,property,XA_PIXMAP,32,PropModeReplace,
8918 (unsigned char *) &pixmap,1);
8919 (void) XSetCloseDownMode(display,RetainPermanent);
8920}
8921
8922/*
8923%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8924% %
8925% %
8926% %
8927% X S e l e c t W i n d o w %
8928% %
8929% %
8930% %
8931%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8932%
8933% XSelectWindow() allows a user to select a window using the mouse. If the
8934% mouse moves, a cropping rectangle is drawn and the extents of the rectangle
8935% is returned in the crop_info structure.
8936%
8937% The format of the XSelectWindow function is:
8938%
8939% target_window=XSelectWindow(display,crop_info)
8940%
8941% A description of each parameter follows:
8942%
8943% o window: XSelectWindow returns the window id.
8944%
8945% o display: Specifies a pointer to the Display structure; returned from
8946% XOpenDisplay.
8947%
8948% o crop_info: Specifies a pointer to a RectangleInfo structure. It
8949% contains the extents of any cropping rectangle.
8950%
cristy3ed852e2009-09-05 21:47:34 +00008951*/
8952static Window XSelectWindow(Display *display,RectangleInfo *crop_info)
8953{
8954#define MinimumCropArea (unsigned int) 9
8955
8956 Cursor
8957 target_cursor;
8958
8959 GC
8960 annotate_context;
8961
8962 int
8963 presses,
8964 x_offset,
8965 y_offset;
8966
8967 Status
8968 status;
8969
8970 Window
8971 root_window,
8972 target_window;
8973
8974 XEvent
8975 event;
8976
8977 XGCValues
8978 context_values;
8979
8980 /*
8981 Initialize graphic context.
8982 */
8983 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
8984 assert(display != (Display *) NULL);
8985 assert(crop_info != (RectangleInfo *) NULL);
8986 root_window=XRootWindow(display,XDefaultScreen(display));
8987 context_values.background=XBlackPixel(display,XDefaultScreen(display));
8988 context_values.foreground=XWhitePixel(display,XDefaultScreen(display));
8989 context_values.function=GXinvert;
8990 context_values.plane_mask=
8991 context_values.background ^ context_values.foreground;
8992 context_values.subwindow_mode=IncludeInferiors;
8993 annotate_context=XCreateGC(display,root_window,(unsigned long) (GCBackground |
8994 GCForeground | GCFunction | GCSubwindowMode),&context_values);
8995 if (annotate_context == (GC) NULL)
8996 return(MagickFalse);
8997 /*
8998 Grab the pointer using target cursor.
8999 */
9000 target_cursor=XMakeCursor(display,root_window,XDefaultColormap(display,
9001 XDefaultScreen(display)),(char * ) "white",(char * ) "black");
9002 status=XGrabPointer(display,root_window,MagickFalse,(unsigned int)
9003 (ButtonPressMask | ButtonReleaseMask | ButtonMotionMask),GrabModeSync,
9004 GrabModeAsync,root_window,target_cursor,CurrentTime);
9005 if (status != GrabSuccess)
9006 {
9007 ThrowXWindowFatalException(XServerError,"UnableToGrabMouse","");
9008 return((Window) NULL);
9009 }
9010 /*
9011 Select a window.
9012 */
9013 crop_info->width=0;
9014 crop_info->height=0;
9015 presses=0;
9016 target_window=(Window) NULL;
9017 x_offset=0;
9018 y_offset=0;
9019 do
9020 {
9021 if ((crop_info->width*crop_info->height) >= MinimumCropArea)
9022 (void) XDrawRectangle(display,root_window,annotate_context,
9023 (int) crop_info->x,(int) crop_info->y,(unsigned int) crop_info->width-1,
9024 (unsigned int) crop_info->height-1);
9025 /*
9026 Allow another event.
9027 */
9028 (void) XAllowEvents(display,SyncPointer,CurrentTime);
9029 (void) XWindowEvent(display,root_window,ButtonPressMask |
9030 ButtonReleaseMask | ButtonMotionMask,&event);
9031 if ((crop_info->width*crop_info->height) >= MinimumCropArea)
9032 (void) XDrawRectangle(display,root_window,annotate_context,
9033 (int) crop_info->x,(int) crop_info->y,(unsigned int) crop_info->width-1,
9034 (unsigned int) crop_info->height-1);
9035 switch (event.type)
9036 {
9037 case ButtonPress:
9038 {
9039 target_window=XGetSubwindow(display,event.xbutton.subwindow,
9040 event.xbutton.x,event.xbutton.y);
9041 if (target_window == (Window) NULL)
9042 target_window=root_window;
9043 x_offset=event.xbutton.x_root;
9044 y_offset=event.xbutton.y_root;
9045 crop_info->x=x_offset;
9046 crop_info->y=y_offset;
9047 crop_info->width=0;
9048 crop_info->height=0;
9049 presses++;
9050 break;
9051 }
9052 case ButtonRelease:
9053 {
9054 presses--;
9055 break;
9056 }
9057 case MotionNotify:
9058 {
9059 /*
9060 Discard pending button motion events.
9061 */
9062 while (XCheckMaskEvent(display,ButtonMotionMask,&event)) ;
9063 crop_info->x=event.xmotion.x;
9064 crop_info->y=event.xmotion.y;
9065 /*
9066 Check boundary conditions.
9067 */
9068 if ((int) crop_info->x < x_offset)
9069 crop_info->width=(unsigned int) (x_offset-crop_info->x);
9070 else
9071 {
9072 crop_info->width=(unsigned int) (crop_info->x-x_offset);
9073 crop_info->x=x_offset;
9074 }
9075 if ((int) crop_info->y < y_offset)
9076 crop_info->height=(unsigned int) (y_offset-crop_info->y);
9077 else
9078 {
9079 crop_info->height=(unsigned int) (crop_info->y-y_offset);
9080 crop_info->y=y_offset;
9081 }
9082 }
9083 default:
9084 break;
9085 }
9086 } while ((target_window == (Window) NULL) || (presses > 0));
9087 (void) XUngrabPointer(display,CurrentTime);
9088 (void) XFreeCursor(display,target_cursor);
9089 (void) XFreeGC(display,annotate_context);
9090 if ((crop_info->width*crop_info->height) < MinimumCropArea)
9091 {
9092 crop_info->width=0;
9093 crop_info->height=0;
9094 }
9095 if ((crop_info->width != 0) && (crop_info->height != 0))
9096 target_window=root_window;
9097 return(target_window);
9098}
9099
9100/*
9101%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9102% %
9103% %
9104% %
9105% X S e t C u r s o r S t a t e %
9106% %
9107% %
9108% %
9109%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9110%
9111% XSetCursorState() sets the cursor state to busy, otherwise the cursor are
9112% reset to their default.
9113%
9114% The format of the XXSetCursorState method is:
9115%
9116% XSetCursorState(display,windows,const MagickStatusType state)
9117%
9118% A description of each parameter follows:
9119%
9120% o display: Specifies a connection to an X server; returned from
9121% XOpenDisplay.
9122%
9123% o windows: Specifies a pointer to a XWindows structure.
9124%
9125% o state: An unsigned integer greater than 0 sets the cursor state
9126% to busy, otherwise the cursor are reset to their default.
9127%
9128*/
9129MagickExport void XSetCursorState(Display *display,XWindows *windows,
9130 const MagickStatusType state)
9131{
9132 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
9133 assert(display != (Display *) NULL);
9134 assert(windows != (XWindows *) NULL);
9135 if (state)
9136 {
9137 (void) XCheckDefineCursor(display,windows->image.id,
9138 windows->image.busy_cursor);
9139 (void) XCheckDefineCursor(display,windows->pan.id,
9140 windows->pan.busy_cursor);
9141 (void) XCheckDefineCursor(display,windows->magnify.id,
9142 windows->magnify.busy_cursor);
9143 (void) XCheckDefineCursor(display,windows->command.id,
9144 windows->command.busy_cursor);
9145 }
9146 else
9147 {
9148 (void) XCheckDefineCursor(display,windows->image.id,
9149 windows->image.cursor);
9150 (void) XCheckDefineCursor(display,windows->pan.id,windows->pan.cursor);
9151 (void) XCheckDefineCursor(display,windows->magnify.id,
9152 windows->magnify.cursor);
9153 (void) XCheckDefineCursor(display,windows->command.id,
9154 windows->command.cursor);
9155 (void) XCheckDefineCursor(display,windows->command.id,
9156 windows->widget.cursor);
9157 (void) XWithdrawWindow(display,windows->info.id,windows->info.screen);
9158 }
9159 windows->info.mapped=MagickFalse;
9160}
9161
9162/*
9163%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9164% %
9165% %
9166% %
9167% X S e t W i n d o w s %
9168% %
9169% %
9170% %
9171%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9172%
9173% XSetWindows() sets the X windows structure if the windows info is specified.
9174% Otherwise the current windows structure is returned.
9175%
9176% The format of the XSetWindows method is:
9177%
9178% XWindows *XSetWindows(XWindows *windows_info)
9179%
9180% A description of each parameter follows:
9181%
9182% o windows_info: Initialize the Windows structure with this information.
9183%
9184*/
9185MagickExport XWindows *XSetWindows(XWindows *windows_info)
9186{
9187 static XWindows
9188 *windows = (XWindows *) NULL;
9189
9190 if (windows_info != (XWindows *) ~0)
9191 {
9192 windows=(XWindows *) RelinquishMagickMemory(windows);
9193 windows=windows_info;
9194 }
9195 return(windows);
9196}
9197/*
9198%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9199% %
9200% %
9201% %
9202% X U s e r P r e f e r e n c e s %
9203% %
9204% %
9205% %
9206%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9207%
9208% XUserPreferences() saves the preferences in a configuration file in the
9209% users' home directory.
9210%
9211% The format of the XUserPreferences method is:
9212%
9213% void XUserPreferences(XResourceInfo *resource_info)
9214%
9215% A description of each parameter follows:
9216%
9217% o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
9218%
9219*/
9220MagickExport void XUserPreferences(XResourceInfo *resource_info)
9221{
9222#if defined(X11_PREFERENCES_PATH)
9223 char
9224 cache[MaxTextExtent],
9225 filename[MaxTextExtent],
9226 specifier[MaxTextExtent];
9227
9228 const char
cristy104cea82009-10-25 02:26:51 +00009229 *client_name,
cristy3ed852e2009-09-05 21:47:34 +00009230 *value;
9231
9232 XrmDatabase
9233 preferences_database;
9234
9235 /*
9236 Save user preferences to the client configuration file.
9237 */
9238 assert(resource_info != (XResourceInfo *) NULL);
cristy104cea82009-10-25 02:26:51 +00009239 client_name=GetClientName();
cristy3ed852e2009-09-05 21:47:34 +00009240 preferences_database=XrmGetStringDatabase("");
cristy104cea82009-10-25 02:26:51 +00009241 (void) FormatMagickString(specifier,MaxTextExtent,"%s.backdrop",client_name);
cristy3ed852e2009-09-05 21:47:34 +00009242 value=resource_info->backdrop ? "True" : "False";
9243 XrmPutStringResource(&preferences_database,specifier,(char *) value);
cristy104cea82009-10-25 02:26:51 +00009244 (void) FormatMagickString(specifier,MaxTextExtent,"%s.colormap",client_name);
cristy3ed852e2009-09-05 21:47:34 +00009245 value=resource_info->colormap == SharedColormap ? "Shared" : "Private";
9246 XrmPutStringResource(&preferences_database,specifier,(char *) value);
9247 (void) FormatMagickString(specifier,MaxTextExtent,"%s.confirmExit",
cristy104cea82009-10-25 02:26:51 +00009248 client_name);
cristy3ed852e2009-09-05 21:47:34 +00009249 value=resource_info->confirm_exit ? "True" : "False";
9250 XrmPutStringResource(&preferences_database,specifier,(char *) value);
9251 (void) FormatMagickString(specifier,MaxTextExtent,"%s.confirmEdit",
cristy104cea82009-10-25 02:26:51 +00009252 client_name);
cristy3ed852e2009-09-05 21:47:34 +00009253 value=resource_info->confirm_edit ? "True" : "False";
9254 XrmPutStringResource(&preferences_database,specifier,(char *) value);
9255 (void) FormatMagickString(specifier,MaxTextExtent,"%s.displayWarnings",
cristy104cea82009-10-25 02:26:51 +00009256 client_name);
cristy3ed852e2009-09-05 21:47:34 +00009257 value=resource_info->display_warnings ? "True" : "False";
9258 XrmPutStringResource(&preferences_database,specifier,(char *) value);
cristy104cea82009-10-25 02:26:51 +00009259 (void) FormatMagickString(specifier,MaxTextExtent,"%s.dither",client_name);
cristy3ed852e2009-09-05 21:47:34 +00009260 value=resource_info->quantize_info->dither ? "True" : "False";
9261 XrmPutStringResource(&preferences_database,specifier,(char *) value);
9262 (void) FormatMagickString(specifier,MaxTextExtent,"%s.gammaCorrect",
cristy104cea82009-10-25 02:26:51 +00009263 client_name);
cristy3ed852e2009-09-05 21:47:34 +00009264 value=resource_info->gamma_correct ? "True" : "False";
9265 XrmPutStringResource(&preferences_database,specifier,(char *) value);
cristy104cea82009-10-25 02:26:51 +00009266 (void) FormatMagickString(specifier,MaxTextExtent,"%s.undoCache",client_name);
cristy3ed852e2009-09-05 21:47:34 +00009267 (void) FormatMagickString(cache,MaxTextExtent,"%lu",
9268 resource_info->undo_cache);
9269 XrmPutStringResource(&preferences_database,specifier,cache);
cristy104cea82009-10-25 02:26:51 +00009270 (void) FormatMagickString(specifier,MaxTextExtent,"%s.usePixmap",client_name);
cristy3ed852e2009-09-05 21:47:34 +00009271 value=resource_info->use_pixmap ? "True" : "False";
9272 XrmPutStringResource(&preferences_database,specifier,(char *) value);
9273 (void) FormatMagickString(filename,MaxTextExtent,"%s%src",
cristy104cea82009-10-25 02:26:51 +00009274 X11_PREFERENCES_PATH,client_name);
cristy3ed852e2009-09-05 21:47:34 +00009275 ExpandFilename(filename);
9276 XrmPutFileDatabase(preferences_database,filename);
9277#endif
9278}
9279
9280/*
9281%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9282% %
9283% %
9284% %
9285% X V i s u a l C l a s s N a m e %
9286% %
9287% %
9288% %
9289%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9290%
9291% XVisualClassName() returns the visual class name as a character string.
9292%
9293% The format of the XVisualClassName method is:
9294%
9295% char *XVisualClassName(const int visual_class)
9296%
9297% A description of each parameter follows:
9298%
9299% o visual_type: XVisualClassName returns the visual class as a character
9300% string.
9301%
9302% o class: Specifies the visual class.
9303%
cristy3ed852e2009-09-05 21:47:34 +00009304*/
9305static const char *XVisualClassName(const int visual_class)
9306{
9307 switch (visual_class)
9308 {
9309 case StaticGray: return("StaticGray");
9310 case GrayScale: return("GrayScale");
9311 case StaticColor: return("StaticColor");
9312 case PseudoColor: return("PseudoColor");
9313 case TrueColor: return("TrueColor");
9314 case DirectColor: return("DirectColor");
9315 }
9316 return("unknown visual class");
9317}
9318
9319/*
9320%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9321% %
9322% %
9323% %
9324% X W a r n i n g %
9325% %
9326% %
9327% %
9328%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9329%
9330% XWarning() displays a warning reason in a Notice widget.
9331%
9332% The format of the XWarning method is:
9333%
9334% void XWarning(const unsigned int warning,const char *reason,
9335% const char *description)
9336%
9337% A description of each parameter follows:
9338%
9339% o warning: Specifies the numeric warning category.
9340%
9341% o reason: Specifies the reason to display before terminating the
9342% program.
9343%
9344% o description: Specifies any description to the reason.
9345%
9346*/
9347MagickExport void XWarning(const ExceptionType magick_unused(warning),
9348 const char *reason,const char *description)
9349{
9350 char
9351 text[MaxTextExtent];
9352
9353 XWindows
9354 *windows;
9355
9356 if (reason == (char *) NULL)
9357 return;
9358 (void) CopyMagickString(text,reason,MaxTextExtent);
9359 (void) ConcatenateMagickString(text,":",MaxTextExtent);
9360 windows=XSetWindows((XWindows *) ~0);
9361 XNoticeWidget(windows->display,windows,text,(char *) description);
9362}
9363
9364/*
9365%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9366% %
9367% %
9368% %
9369% X W i n d o w B y I D %
9370% %
9371% %
9372% %
9373%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9374%
9375% XWindowByID() locates a child window with a given ID. If not window with
9376% the given name is found, 0 is returned. Only the window specified and its
9377% subwindows are searched.
9378%
9379% The format of the XWindowByID function is:
9380%
9381% child=XWindowByID(display,window,id)
9382%
9383% A description of each parameter follows:
9384%
9385% o child: XWindowByID returns the window with the specified
9386% id. If no windows are found, XWindowByID returns 0.
9387%
9388% o display: Specifies a pointer to the Display structure; returned from
9389% XOpenDisplay.
9390%
9391% o id: Specifies the id of the window to locate.
9392%
9393*/
9394MagickExport Window XWindowByID(Display *display,const Window root_window,
9395 const unsigned long id)
9396{
9397 RectangleInfo
9398 rectangle_info;
9399
9400 register int
9401 i;
9402
9403 Status
9404 status;
9405
9406 unsigned int
9407 number_children;
9408
9409 Window
9410 child,
9411 *children,
9412 window;
9413
9414 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
9415 assert(display != (Display *) NULL);
9416 assert(root_window != (Window) NULL);
9417 if (id == 0)
9418 return(XSelectWindow(display,&rectangle_info));
9419 if (root_window == id)
9420 return(id);
9421 status=XQueryTree(display,root_window,&child,&child,&children,
9422 &number_children);
9423 if (status == False)
9424 return((Window) NULL);
9425 window=(Window) NULL;
9426 for (i=0; i < (int) number_children; i++)
9427 {
9428 /*
9429 Search each child and their children.
9430 */
9431 window=XWindowByID(display,children[i],id);
9432 if (window != (Window) NULL)
9433 break;
9434 }
9435 if (children != (Window *) NULL)
9436 (void) XFree((void *) children);
9437 return(window);
9438}
9439
9440/*
9441%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9442% %
9443% %
9444% %
9445% X W i n d o w B y N a m e %
9446% %
9447% %
9448% %
9449%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9450%
9451% XWindowByName() locates a window with a given name on a display. If no
9452% window with the given name is found, 0 is returned. If more than one window
9453% has the given name, the first one is returned. Only root and its children
9454% are searched.
9455%
9456% The format of the XWindowByName function is:
9457%
9458% window=XWindowByName(display,root_window,name)
9459%
9460% A description of each parameter follows:
9461%
9462% o window: XWindowByName returns the window id.
9463%
9464% o display: Specifies a pointer to the Display structure; returned from
9465% XOpenDisplay.
9466%
9467% o root_window: Specifies the id of the root window.
9468%
9469% o name: Specifies the name of the window to locate.
9470%
9471*/
9472MagickExport Window XWindowByName(Display *display,const Window root_window,
9473 const char *name)
9474{
9475 register int
9476 i;
9477
9478 Status
9479 status;
9480
9481 unsigned int
9482 number_children;
9483
9484 Window
9485 *children,
9486 child,
9487 window;
9488
9489 XTextProperty
9490 window_name;
9491
9492 assert(display != (Display *) NULL);
9493 assert(root_window != (Window) NULL);
9494 assert(name != (char *) NULL);
9495 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",name);
9496 if (XGetWMName(display,root_window,&window_name) != 0)
9497 if (LocaleCompare((char *) window_name.value,name) == 0)
9498 return(root_window);
9499 status=XQueryTree(display,root_window,&child,&child,&children,
9500 &number_children);
9501 if (status == False)
9502 return((Window) NULL);
9503 window=(Window) NULL;
9504 for (i=0; i < (int) number_children; i++)
9505 {
9506 /*
9507 Search each child and their children.
9508 */
9509 window=XWindowByName(display,children[i],name);
9510 if (window != (Window) NULL)
9511 break;
9512 }
9513 if (children != (Window *) NULL)
9514 (void) XFree((void *) children);
9515 return(window);
9516}
9517
9518/*
9519%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9520% %
9521% %
9522% %
9523% X W i n d o w B y P r o p e r y %
9524% %
9525% %
9526% %
9527%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9528%
9529% XWindowByProperty() locates a child window with a given property. If not
9530% window with the given name is found, 0 is returned. If more than one window
9531% has the given property, the first one is returned. Only the window
9532% specified and its subwindows are searched.
9533%
9534% The format of the XWindowByProperty function is:
9535%
9536% child=XWindowByProperty(display,window,property)
9537%
9538% A description of each parameter follows:
9539%
9540% o child: XWindowByProperty returns the window id with the specified
9541% property. If no windows are found, XWindowByProperty returns 0.
9542%
9543% o display: Specifies a pointer to the Display structure; returned from
9544% XOpenDisplay.
9545%
9546% o property: Specifies the property of the window to locate.
9547%
9548*/
9549MagickExport Window XWindowByProperty(Display *display,const Window window,
9550 const Atom property)
9551{
9552 Atom
9553 type;
9554
9555 int
9556 format;
9557
9558 Status
9559 status;
9560
9561 unsigned char
9562 *data;
9563
9564 unsigned int
9565 i,
9566 number_children;
9567
9568 unsigned long
9569 after,
9570 number_items;
9571
9572 Window
9573 child,
9574 *children,
9575 parent,
9576 root;
9577
9578 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
9579 assert(display != (Display *) NULL);
9580 assert(window != (Window) NULL);
9581 assert(property != (Atom) NULL);
9582 status=XQueryTree(display,window,&root,&parent,&children,&number_children);
9583 if (status == False)
9584 return((Window) NULL);
9585 type=(Atom) NULL;
9586 child=(Window) NULL;
9587 for (i=0; (i < number_children) && (child == (Window) NULL); i++)
9588 {
9589 status=XGetWindowProperty(display,children[i],property,0L,0L,MagickFalse,
9590 (Atom) AnyPropertyType,&type,&format,&number_items,&after,&data);
9591 if (data != NULL)
9592 (void) XFree((void *) data);
9593 if ((status == Success) && (type != (Atom) NULL))
9594 child=children[i];
9595 }
9596 for (i=0; (i < number_children) && (child == (Window) NULL); i++)
9597 child=XWindowByProperty(display,children[i],property);
9598 if (children != (Window *) NULL)
9599 (void) XFree((void *) children);
9600 return(child);
9601}
9602#else
9603
9604/*
9605%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9606% %
9607% %
9608% %
9609% X I m p o r t I m a g e %
9610% %
9611% %
9612% %
9613%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9614%
9615% XImportImage() reads an image from an X window.
9616%
9617% The format of the XImportImage method is:
9618%
9619% Image *XImportImage(const ImageInfo *image_info,XImportInfo *ximage_info)
9620%
9621% A description of each parameter follows:
9622%
9623% o image_info: the image info..
9624%
9625% o ximage_info: Specifies a pointer to an XImportInfo structure.
9626%
9627*/
9628MagickExport Image *XImportImage(const ImageInfo *image_info,
9629 XImportInfo *ximage_info)
9630{
9631 assert(image_info != (const ImageInfo *) NULL);
9632 assert(image_info->signature == MagickSignature);
9633 if (image_info->debug != MagickFalse)
9634 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
9635 image_info->filename);
9636 assert(ximage_info != (XImportInfo *) NULL);
9637 return((Image *) NULL);
9638}
9639#endif
9640
9641/*
9642%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9643% %
9644% %
9645% %
cristy576974e2009-10-25 20:45:31 +00009646+ X C o m p o n e n t G e n e s i s %
9647% %
9648% %
9649% %
9650%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9651%
9652% XComponentGenesis() instantiates the X component.
9653%
9654% The format of the XComponentGenesis method is:
9655%
9656% MagickBooleanType XComponentGenesis(void)
9657%
9658*/
9659MagickExport MagickBooleanType XComponentGenesis(void)
9660{
9661 return(MagickTrue);
9662}
9663
9664/*
9665%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9666% %
9667% %
9668% %
cristy3ed852e2009-09-05 21:47:34 +00009669% X G e t I m p o r t I n f o %
9670% %
9671% %
9672% %
9673%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9674%
9675% XGetImportInfo() initializes the XImportInfo structure.
9676%
9677% The format of the XGetImportInfo method is:
9678%
9679% void XGetImportInfo(XImportInfo *ximage_info)
9680%
9681% A description of each parameter follows:
9682%
9683% o ximage_info: Specifies a pointer to an ImageInfo structure.
9684%
9685*/
9686MagickExport void XGetImportInfo(XImportInfo *ximage_info)
9687{
9688 assert(ximage_info != (XImportInfo *) NULL);
9689 ximage_info->frame=MagickFalse;
9690 ximage_info->borders=MagickFalse;
9691 ximage_info->screen=MagickFalse;
9692 ximage_info->descend=MagickTrue;
9693 ximage_info->silent=MagickFalse;
9694}