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