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