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