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