blob: 47831ddaf9e5809fc27a829c76b2e5eec9f9d00d [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% %
cristy1454be72011-12-19 01:52:48 +000020% Copyright 1999-2012 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*/
cristy4c08aed2011-07-01 19:47:50 +000042#include "MagickCore/studio.h"
43#include "MagickCore/animate.h"
44#include "MagickCore/artifact.h"
45#include "MagickCore/blob.h"
46#include "MagickCore/cache.h"
47#include "MagickCore/client.h"
48#include "MagickCore/color.h"
49#include "MagickCore/color-private.h"
50#include "MagickCore/colormap.h"
51#include "MagickCore/composite.h"
cristy030436f2012-01-06 21:56:17 +000052#include "MagickCore/constitute.h"
cristy4c08aed2011-07-01 19:47:50 +000053#include "MagickCore/display.h"
cristyc53413d2011-11-17 13:04:26 +000054#include "MagickCore/distort.h"
cristy4c08aed2011-07-01 19:47:50 +000055#include "MagickCore/exception.h"
56#include "MagickCore/exception-private.h"
57#include "MagickCore/geometry.h"
58#include "MagickCore/identify.h"
59#include "MagickCore/image.h"
60#include "MagickCore/image-private.h"
61#include "MagickCore/list.h"
62#include "MagickCore/locale_.h"
63#include "MagickCore/log.h"
64#include "MagickCore/magick.h"
65#include "MagickCore/memory_.h"
66#include "MagickCore/monitor.h"
cristy2c5fc272012-02-22 01:27:46 +000067#include "MagickCore/nt-base-private.h"
cristy4c08aed2011-07-01 19:47:50 +000068#include "MagickCore/option.h"
69#include "MagickCore/pixel-accessor.h"
70#include "MagickCore/PreRvIcccm.h"
71#include "MagickCore/quantize.h"
72#include "MagickCore/quantum.h"
73#include "MagickCore/quantum-private.h"
74#include "MagickCore/resource_.h"
75#include "MagickCore/resize.h"
cristy4c08aed2011-07-01 19:47:50 +000076#include "MagickCore/statistic.h"
77#include "MagickCore/string_.h"
78#include "MagickCore/string-private.h"
79#include "MagickCore/transform.h"
80#include "MagickCore/utility.h"
cristyd1dd6e42011-09-04 01:46:08 +000081#include "MagickCore/utility-private.h"
cristy4c08aed2011-07-01 19:47:50 +000082#include "MagickCore/widget.h"
cristybcbda3f2011-09-03 13:01:22 +000083#include "MagickCore/widget-private.h"
cristy4c08aed2011-07-01 19:47:50 +000084#include "MagickCore/xwindow.h"
85#include "MagickCore/xwindow-private.h"
86#include "MagickCore/version.h"
cristy3ed852e2009-09-05 21:47:34 +000087#if defined(__BEOS__)
88#include <OS.h>
89#endif
90#if defined(MAGICKCORE_X11_DELEGATE)
91#include <X11/Xproto.h>
92#include <X11/Xlocale.h>
93#if defined(MAGICK_HAVE_POLL)
94# include <sys/poll.h>
95#endif
96#if defined(MAGICKCORE_HAVE_SHARED_MEMORY)
97#if defined(MAGICKCORE_HAVE_MACHINE_PARAM_H)
98# include <machine/param.h>
99#endif
100#include <sys/ipc.h>
101#include <sys/shm.h>
102#include <X11/extensions/XShm.h>
103#endif
104#if defined(MAGICKCORE_HAVE_SHAPE)
105#include <X11/extensions/shape.h>
106#endif
107
108/*
109 X defines.
110*/
cristyce70c172010-01-07 17:15:30 +0000111#define XBlueGamma(color) ClampToQuantum(blue_gamma == 1.0 ? (double) \
cristy3ed852e2009-09-05 21:47:34 +0000112 (color) : ((pow(((double) QuantumScale*(color)),1.0/(double) blue_gamma)* \
113 QuantumRange)))
cristy4c08aed2011-07-01 19:47:50 +0000114#define XGammaPacket(map,color) (size_t) (map->base_pixel+ \
cristy7e9f2332011-04-22 23:12:22 +0000115 ((ScaleQuantumToShort(XRedGamma((color)->red))*map->red_max/65535L)* \
116 map->red_mult)+ \
117 ((ScaleQuantumToShort(XGreenGamma((color)->green))*map->green_max/65535L)* \
118 map->green_mult)+ \
119 ((ScaleQuantumToShort(XBlueGamma((color)->blue))*map->blue_max/65535L)* \
120 map->blue_mult))
cristy4c08aed2011-07-01 19:47:50 +0000121#define XGammaPixel(image,map,color) (size_t) (map->base_pixel+ \
122 ((ScaleQuantumToShort(XRedGamma(GetPixelRed(image,color)))*map->red_max/65535L)* \
123 map->red_mult)+ \
124 ((ScaleQuantumToShort(XGreenGamma(GetPixelGreen(image,color)))*map->green_max/65535L)* \
125 map->green_mult)+ \
126 ((ScaleQuantumToShort(XBlueGamma(GetPixelBlue(image,color)))*map->blue_max/65535L)* \
127 map->blue_mult))
cristyce70c172010-01-07 17:15:30 +0000128#define XGreenGamma(color) ClampToQuantum(green_gamma == 1.0 ? (double) \
cristy3ed852e2009-09-05 21:47:34 +0000129 (color) : ((pow(((double) QuantumScale*(color)),1.0/(double) green_gamma)* \
130 QuantumRange)))
cristyce70c172010-01-07 17:15:30 +0000131#define XRedGamma(color) ClampToQuantum(red_gamma == 1.0 ? (double) \
cristy3ed852e2009-09-05 21:47:34 +0000132 (color) : ((pow(((double) QuantumScale*(color)),1.0/(double) red_gamma)* \
133 QuantumRange)))
cristybb503372010-05-27 20:51:26 +0000134#define XStandardPixel(map,color) (size_t) (map->base_pixel+ \
cristy7e9f2332011-04-22 23:12:22 +0000135 (((color)->red*map->red_max/65535L)*map->red_mult)+ \
136 (((color)->green*map->green_max/65535L)*map->green_mult)+ \
137 (((color)->blue*map->blue_max/65535L)*map->blue_mult))
cristy3ed852e2009-09-05 21:47:34 +0000138
139#define AccentuateModulate ScaleCharToQuantum(80)
140#define HighlightModulate ScaleCharToQuantum(125)
141#define ShadowModulate ScaleCharToQuantum(135)
142#define DepthModulate ScaleCharToQuantum(185)
143#define TroughModulate ScaleCharToQuantum(110)
144
145#define XLIB_ILLEGAL_ACCESS 1
146#undef ForgetGravity
147#undef NorthWestGravity
148#undef NorthGravity
149#undef NorthEastGravity
150#undef WestGravity
151#undef CenterGravity
152#undef EastGravity
153#undef SouthWestGravity
154#undef SouthGravity
155#undef SouthEastGravity
156#undef StaticGravity
157
158#undef index
159#if defined(hpux9)
160#define XFD_SET int
161#else
162#define XFD_SET fd_set
163#endif
164
165/*
166 Enumeration declarations.
167*/
168typedef enum
169{
170#undef DoRed
171 DoRed = 0x0001,
172#undef DoGreen
173 DoGreen = 0x0002,
174#undef DoBlue
175 DoBlue = 0x0004,
176 DoMatte = 0x0008
177} XColorFlags;
178
179/*
180 Typedef declarations.
181*/
182typedef struct _DiversityPacket
183{
184 Quantum
185 red,
186 green,
187 blue;
188
189 unsigned short
190 index;
191
cristybb503372010-05-27 20:51:26 +0000192 size_t
cristy3ed852e2009-09-05 21:47:34 +0000193 count;
194} DiversityPacket;
195
196/*
197 Constant declaractions.
198*/
199static MagickBooleanType
200 xerror_alert = MagickFalse;
201
202/*
203 Method prototypes.
204*/
205static const char
206 *XVisualClassName(const int);
207
208static MagickRealType
209 blue_gamma = 1.0,
210 green_gamma = 1.0,
211 red_gamma = 1.0;
212
213static MagickBooleanType
214 XMakePixmap(Display *,const XResourceInfo *,XWindowInfo *);
215
216static void
217 XMakeImageLSBFirst(const XResourceInfo *,const XWindowInfo *,Image *,
cristye941a752011-10-15 01:52:48 +0000218 XImage *,XImage *,ExceptionInfo *),
cristy3ed852e2009-09-05 21:47:34 +0000219 XMakeImageMSBFirst(const XResourceInfo *,const XWindowInfo *,Image *,
cristye941a752011-10-15 01:52:48 +0000220 XImage *,XImage *,ExceptionInfo *);
cristy3ed852e2009-09-05 21:47:34 +0000221
222static Window
223 XSelectWindow(Display *,RectangleInfo *);
224
225/*
226%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
227% %
228% %
229% %
230% D e s t r o y X R e s o u r c e s %
231% %
232% %
233% %
234%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
235%
236% DestroyXResources() destroys any X resources.
237%
238% The format of the DestroyXResources method is:
239%
240% void DestroyXResources()
241%
242% A description of each parameter follows:
243%
244*/
245MagickExport void DestroyXResources(void)
246{
247 register int
248 i;
249
250 unsigned int
251 number_windows;
252
253 XWindowInfo
254 *magick_windows[MaxXWindows];
255
256 XWindows
257 *windows;
258
259 DestroyXWidget();
260 windows=XSetWindows((XWindows *) ~0);
261 if ((windows == (XWindows *) NULL) || (windows->display == (Display *) NULL))
262 return;
263 number_windows=0;
264 magick_windows[number_windows++]=(&windows->context);
265 magick_windows[number_windows++]=(&windows->group_leader);
266 magick_windows[number_windows++]=(&windows->backdrop);
267 magick_windows[number_windows++]=(&windows->icon);
268 magick_windows[number_windows++]=(&windows->image);
269 magick_windows[number_windows++]=(&windows->info);
270 magick_windows[number_windows++]=(&windows->magnify);
271 magick_windows[number_windows++]=(&windows->pan);
272 magick_windows[number_windows++]=(&windows->command);
273 magick_windows[number_windows++]=(&windows->widget);
274 magick_windows[number_windows++]=(&windows->popup);
275 magick_windows[number_windows++]=(&windows->context);
276 for (i=0; i < (int) number_windows; i++)
277 {
278 if (magick_windows[i]->mapped != MagickFalse)
279 {
280 (void) XWithdrawWindow(windows->display,magick_windows[i]->id,
281 magick_windows[i]->screen);
282 magick_windows[i]->mapped=MagickFalse;
283 }
284 if (magick_windows[i]->name != (char *) NULL)
285 magick_windows[i]->name=(char *)
286 RelinquishMagickMemory(magick_windows[i]->name);
287 if (magick_windows[i]->icon_name != (char *) NULL)
288 magick_windows[i]->icon_name=(char *)
289 RelinquishMagickMemory(magick_windows[i]->icon_name);
290 if (magick_windows[i]->cursor != (Cursor) NULL)
291 {
292 (void) XFreeCursor(windows->display,magick_windows[i]->cursor);
293 magick_windows[i]->cursor=(Cursor) NULL;
294 }
295 if (magick_windows[i]->busy_cursor != (Cursor) NULL)
296 {
297 (void) XFreeCursor(windows->display,magick_windows[i]->busy_cursor);
298 magick_windows[i]->busy_cursor=(Cursor) NULL;
299 }
300 if (magick_windows[i]->highlight_stipple != (Pixmap) NULL)
301 {
302 (void) XFreePixmap(windows->display,
303 magick_windows[i]->highlight_stipple);
304 magick_windows[i]->highlight_stipple=(Pixmap) NULL;
305 }
306 if (magick_windows[i]->shadow_stipple != (Pixmap) NULL)
307 {
308 (void) XFreePixmap(windows->display,magick_windows[i]->shadow_stipple);
309 magick_windows[i]->shadow_stipple=(Pixmap) NULL;
310 }
311 if (magick_windows[i]->ximage != (XImage *) NULL)
312 {
313 XDestroyImage(magick_windows[i]->ximage);
314 magick_windows[i]->ximage=(XImage *) NULL;
315 }
316 if (magick_windows[i]->pixmap != (Pixmap) NULL)
317 {
318 (void) XFreePixmap(windows->display,magick_windows[i]->pixmap);
319 magick_windows[i]->pixmap=(Pixmap) NULL;
320 }
321 if (magick_windows[i]->id != (Window) NULL)
322 {
323 (void) XDestroyWindow(windows->display,magick_windows[i]->id);
324 magick_windows[i]->id=(Window) NULL;
325 }
326 if (magick_windows[i]->destroy != MagickFalse)
327 {
328 if (magick_windows[i]->image != (Image *) NULL)
329 {
330 magick_windows[i]->image=DestroyImage(magick_windows[i]->image);
331 magick_windows[i]->image=NewImageList();
332 }
333 if (magick_windows[i]->matte_pixmap != (Pixmap) NULL)
334 {
335 (void) XFreePixmap(windows->display,
336 magick_windows[i]->matte_pixmap);
337 magick_windows[i]->matte_pixmap=(Pixmap) NULL;
338 }
339 }
340 if (magick_windows[i]->segment_info != (void *) NULL)
341 {
342#if defined(MAGICKCORE_HAVE_SHARED_MEMORY)
343 XShmSegmentInfo
344 *segment_info;
345
346 segment_info=(XShmSegmentInfo *) magick_windows[i]->segment_info;
347 if (segment_info != (XShmSegmentInfo *) NULL)
348 if (segment_info[0].shmid >= 0)
349 {
350 if (segment_info[0].shmaddr != NULL)
351 (void) shmdt(segment_info[0].shmaddr);
352 (void) shmctl(segment_info[0].shmid,IPC_RMID,0);
353 segment_info[0].shmaddr=NULL;
354 segment_info[0].shmid=(-1);
355 }
356#endif
357 magick_windows[i]->segment_info=(void *)
358 RelinquishMagickMemory(magick_windows[i]->segment_info);
359 }
360 }
361 windows->icon_resources=(XResourceInfo *)
362 RelinquishMagickMemory(windows->icon_resources);
363 if (windows->icon_pixel != (XPixelInfo *) NULL)
364 {
cristyf2faecf2010-05-28 19:19:36 +0000365 if (windows->icon_pixel->pixels != (unsigned long *) NULL)
366 windows->icon_pixel->pixels=(unsigned long *)
cristy3ed852e2009-09-05 21:47:34 +0000367 RelinquishMagickMemory(windows->icon_pixel->pixels);
368 if (windows->icon_pixel->annotate_context != (GC) NULL)
369 XFreeGC(windows->display,windows->icon_pixel->annotate_context);
370 windows->icon_pixel=(XPixelInfo *)
371 RelinquishMagickMemory(windows->icon_pixel);
372 }
373 if (windows->pixel_info != (XPixelInfo *) NULL)
374 {
cristyf2faecf2010-05-28 19:19:36 +0000375 if (windows->pixel_info->pixels != (unsigned long *) NULL)
376 windows->pixel_info->pixels=(unsigned long *)
cristy3ed852e2009-09-05 21:47:34 +0000377 RelinquishMagickMemory(windows->pixel_info->pixels);
378 if (windows->pixel_info->annotate_context != (GC) NULL)
379 XFreeGC(windows->display,windows->pixel_info->annotate_context);
380 if (windows->pixel_info->widget_context != (GC) NULL)
381 XFreeGC(windows->display,windows->pixel_info->widget_context);
382 if (windows->pixel_info->highlight_context != (GC) NULL)
383 XFreeGC(windows->display,windows->pixel_info->highlight_context);
384 windows->pixel_info=(XPixelInfo *)
385 RelinquishMagickMemory(windows->pixel_info);
386 }
387 if (windows->font_info != (XFontStruct *) NULL)
388 {
389 XFreeFont(windows->display,windows->font_info);
390 windows->font_info=(XFontStruct *) NULL;
391 }
392 if (windows->class_hints != (XClassHint *) NULL)
393 {
cristyc9cc4a72011-09-18 02:12:41 +0000394 if (windows->class_hints->res_name != (char *) NULL)
395 windows->class_hints->res_name=DestroyString(
396 windows->class_hints->res_name);
397 if (windows->class_hints->res_class != (char *) NULL)
398 windows->class_hints->res_class=DestroyString(
399 windows->class_hints->res_class);
cristy3ed852e2009-09-05 21:47:34 +0000400 XFree(windows->class_hints);
401 windows->class_hints=(XClassHint *) NULL;
402 }
403 if (windows->manager_hints != (XWMHints *) NULL)
404 {
405 XFree(windows->manager_hints);
406 windows->manager_hints=(XWMHints *) NULL;
407 }
408 if (windows->map_info != (XStandardColormap *) NULL)
409 {
410 XFree(windows->map_info);
411 windows->map_info=(XStandardColormap *) NULL;
412 }
413 if (windows->icon_map != (XStandardColormap *) NULL)
414 {
415 XFree(windows->icon_map);
416 windows->icon_map=(XStandardColormap *) NULL;
417 }
418 if (windows->visual_info != (XVisualInfo *) NULL)
419 {
420 XFree(windows->visual_info);
421 windows->visual_info=(XVisualInfo *) NULL;
422 }
423 if (windows->icon_visual != (XVisualInfo *) NULL)
424 {
425 XFree(windows->icon_visual);
426 windows->icon_visual=(XVisualInfo *) NULL;
427 }
428 (void) XSetWindows((XWindows *) NULL);
429}
430
431/*
432%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
433% %
434% %
435% %
436% X A n n o t a t e I m a g e %
437% %
438% %
439% %
440%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
441%
442% XAnnotateImage() annotates the image with text.
443%
444% The format of the XAnnotateImage method is:
445%
446% MagickBooleanType XAnnotateImage(Display *display,
cristy7c3af952011-10-20 16:04:16 +0000447% const XPixelInfo *pixel,XAnnotateInfo *annotate_info,Image *image,
448% ExceptionInfo *exception)
cristy3ed852e2009-09-05 21:47:34 +0000449%
450% A description of each parameter follows:
451%
452% o display: Specifies a connection to an X server; returned from
453% XOpenDisplay.
454%
455% o pixel: Specifies a pointer to a XPixelInfo structure.
456%
457% o annotate_info: Specifies a pointer to a XAnnotateInfo structure.
458%
459% o image: the image.
460%
cristy7c3af952011-10-20 16:04:16 +0000461% o exception: return any errors or warnings in this structure.
462%
cristy3ed852e2009-09-05 21:47:34 +0000463*/
cristybcbda3f2011-09-03 13:01:22 +0000464MagickPrivate MagickBooleanType XAnnotateImage(Display *display,
cristy7c3af952011-10-20 16:04:16 +0000465 const XPixelInfo *pixel,XAnnotateInfo *annotate_info,Image *image,
466 ExceptionInfo *exception)
cristy3ed852e2009-09-05 21:47:34 +0000467{
cristyc57f6942010-11-12 01:47:39 +0000468 CacheView
469 *annotate_view;
470
cristy3ed852e2009-09-05 21:47:34 +0000471 GC
472 annotate_context;
473
cristy3ed852e2009-09-05 21:47:34 +0000474 Image
475 *annotate_image;
476
477 int
478 x,
479 y;
480
481 MagickBooleanType
482 matte;
483
484 Pixmap
485 annotate_pixmap;
486
487 unsigned int
488 depth,
489 height,
490 width;
491
492 Window
493 root_window;
494
495 XGCValues
496 context_values;
497
498 XImage
499 *annotate_ximage;
500
501 /*
502 Initialize annotated image.
503 */
504 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
505 assert(display != (Display *) NULL);
506 assert(pixel != (XPixelInfo *) NULL);
507 assert(annotate_info != (XAnnotateInfo *) NULL);
508 assert(image != (Image *) NULL);
509 /*
510 Initialize annotated pixmap.
511 */
512 root_window=XRootWindow(display,XDefaultScreen(display));
513 depth=(unsigned int) XDefaultDepth(display,XDefaultScreen(display));
514 annotate_pixmap=XCreatePixmap(display,root_window,annotate_info->width,
515 annotate_info->height,depth);
516 if (annotate_pixmap == (Pixmap) NULL)
517 return(MagickFalse);
518 /*
519 Initialize graphics info.
520 */
521 context_values.background=0;
cristybb503372010-05-27 20:51:26 +0000522 context_values.foreground=(size_t) (~0);
cristy3ed852e2009-09-05 21:47:34 +0000523 context_values.font=annotate_info->font_info->fid;
cristyc57f6942010-11-12 01:47:39 +0000524 annotate_context=XCreateGC(display,root_window,(unsigned long)
525 (GCBackground | GCFont | GCForeground),&context_values);
cristy3ed852e2009-09-05 21:47:34 +0000526 if (annotate_context == (GC) NULL)
527 return(MagickFalse);
528 /*
529 Draw text to pixmap.
530 */
531 (void) XDrawImageString(display,annotate_pixmap,annotate_context,0,
532 (int) annotate_info->font_info->ascent,annotate_info->text,
533 (int) strlen(annotate_info->text));
534 (void) XFreeGC(display,annotate_context);
535 /*
536 Initialize annotated X image.
537 */
538 annotate_ximage=XGetImage(display,annotate_pixmap,0,0,annotate_info->width,
539 annotate_info->height,AllPlanes,ZPixmap);
540 if (annotate_ximage == (XImage *) NULL)
541 return(MagickFalse);
542 (void) XFreePixmap(display,annotate_pixmap);
543 /*
544 Initialize annotated image.
545 */
cristy6710d842011-10-20 23:23:00 +0000546 annotate_image=AcquireImage((ImageInfo *) NULL,exception);
cristy3ed852e2009-09-05 21:47:34 +0000547 if (annotate_image == (Image *) NULL)
548 return(MagickFalse);
549 annotate_image->columns=annotate_info->width;
550 annotate_image->rows=annotate_info->height;
551 /*
552 Transfer annotated X image to image.
553 */
554 width=(unsigned int) image->columns;
555 height=(unsigned int) image->rows;
556 x=0;
557 y=0;
558 (void) XParseGeometry(annotate_info->geometry,&x,&y,&width,&height);
cristyf05d4942012-03-17 16:26:09 +0000559 (void) GetOneVirtualPixelInfo(image,UndefinedVirtualPixelMethod,(ssize_t) x,
560 (ssize_t) y,&annotate_image->background_color,exception);
cristy3ed852e2009-09-05 21:47:34 +0000561 if (annotate_info->stencil == ForegroundStencil)
562 annotate_image->matte=MagickTrue;
cristyc57f6942010-11-12 01:47:39 +0000563 annotate_view=AcquireCacheView(annotate_image);
cristy3ed852e2009-09-05 21:47:34 +0000564 for (y=0; y < (int) annotate_image->rows; y++)
565 {
cristyc57f6942010-11-12 01:47:39 +0000566 register int
cristy3ed852e2009-09-05 21:47:34 +0000567 x;
568
cristy4c08aed2011-07-01 19:47:50 +0000569 register Quantum
cristyc47d1f82009-11-26 01:44:43 +0000570 *restrict q;
cristy3ed852e2009-09-05 21:47:34 +0000571
cristyc57f6942010-11-12 01:47:39 +0000572 q=GetCacheViewAuthenticPixels(annotate_view,0,(ssize_t) y,
573 annotate_image->columns,1,exception);
cristyacd2ed22011-08-30 01:44:23 +0000574 if (q == (Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +0000575 break;
cristyc57f6942010-11-12 01:47:39 +0000576 for (x=0; x < (int) annotate_image->columns; x++)
cristy3ed852e2009-09-05 21:47:34 +0000577 {
cristy4c08aed2011-07-01 19:47:50 +0000578 SetPixelAlpha(annotate_image,OpaqueAlpha,q);
cristy3ed852e2009-09-05 21:47:34 +0000579 if (XGetPixel(annotate_ximage,x,y) == 0)
580 {
581 /*
582 Set this pixel to the background color.
583 */
cristy4c08aed2011-07-01 19:47:50 +0000584 SetPixelRed(annotate_image,ScaleShortToQuantum(
585 pixel->box_color.red),q);
586 SetPixelGreen(annotate_image,ScaleShortToQuantum(
587 pixel->box_color.green),q);
588 SetPixelBlue(annotate_image,ScaleShortToQuantum(
589 pixel->box_color.blue),q);
cristy3ed852e2009-09-05 21:47:34 +0000590 if ((annotate_info->stencil == ForegroundStencil) ||
591 (annotate_info->stencil == OpaqueStencil))
cristy4c08aed2011-07-01 19:47:50 +0000592 SetPixelAlpha(annotate_image,TransparentAlpha,q);
cristy3ed852e2009-09-05 21:47:34 +0000593 }
594 else
595 {
596 /*
597 Set this pixel to the pen color.
598 */
cristy4c08aed2011-07-01 19:47:50 +0000599 SetPixelRed(annotate_image,ScaleShortToQuantum(
600 pixel->pen_color.red),q);
601 SetPixelGreen(annotate_image,ScaleShortToQuantum(
602 pixel->pen_color.green),q);
603 SetPixelBlue(annotate_image,ScaleShortToQuantum(
604 pixel->pen_color.blue),q);
cristy3ed852e2009-09-05 21:47:34 +0000605 if (annotate_info->stencil == BackgroundStencil)
cristy4c08aed2011-07-01 19:47:50 +0000606 SetPixelAlpha(annotate_image,TransparentAlpha,q);
cristy3ed852e2009-09-05 21:47:34 +0000607 }
cristyed231572011-07-14 02:18:59 +0000608 q+=GetPixelChannels(annotate_image);
cristy3ed852e2009-09-05 21:47:34 +0000609 }
cristyc57f6942010-11-12 01:47:39 +0000610 if (SyncCacheViewAuthenticPixels(annotate_view,exception) == MagickFalse)
cristy3ed852e2009-09-05 21:47:34 +0000611 break;
612 }
cristyc57f6942010-11-12 01:47:39 +0000613 annotate_view=DestroyCacheView(annotate_view);
cristy3ed852e2009-09-05 21:47:34 +0000614 XDestroyImage(annotate_ximage);
615 /*
616 Determine annotate geometry.
617 */
618 (void) XParseGeometry(annotate_info->geometry,&x,&y,&width,&height);
619 if ((width != (unsigned int) annotate_image->columns) ||
620 (height != (unsigned int) annotate_image->rows))
621 {
622 char
623 image_geometry[MaxTextExtent];
624
625 /*
626 Scale image.
627 */
cristyb51dff52011-05-19 16:55:47 +0000628 (void) FormatLocaleString(image_geometry,MaxTextExtent,"%ux%u",
cristy3ed852e2009-09-05 21:47:34 +0000629 width,height);
cristye941a752011-10-15 01:52:48 +0000630 (void) TransformImage(&annotate_image,(char *) NULL,image_geometry,
631 exception);
cristy3ed852e2009-09-05 21:47:34 +0000632 }
633 if (annotate_info->degrees != 0.0)
634 {
635 Image
636 *rotate_image;
637
638 int
639 rotations;
640
641 MagickRealType
642 normalized_degrees;
643
644 /*
645 Rotate image.
646 */
cristy6710d842011-10-20 23:23:00 +0000647 rotate_image=RotateImage(annotate_image,annotate_info->degrees,exception);
cristy3ed852e2009-09-05 21:47:34 +0000648 if (rotate_image == (Image *) NULL)
649 return(MagickFalse);
650 annotate_image=DestroyImage(annotate_image);
651 annotate_image=rotate_image;
652 /*
653 Annotation is relative to the degree of rotation.
654 */
655 normalized_degrees=annotate_info->degrees;
656 while (normalized_degrees < -45.0)
657 normalized_degrees+=360.0;
658 for (rotations=0; normalized_degrees > 45.0; rotations++)
659 normalized_degrees-=90.0;
660 switch (rotations % 4)
661 {
662 default:
663 case 0:
664 break;
665 case 1:
666 {
667 /*
668 Rotate 90 degrees.
669 */
670 x-=(int) annotate_image->columns/2;
671 y+=(int) annotate_image->columns/2;
672 break;
673 }
674 case 2:
675 {
676 /*
677 Rotate 180 degrees.
678 */
679 x=x-(int) annotate_image->columns;
680 break;
681 }
682 case 3:
683 {
684 /*
685 Rotate 270 degrees.
686 */
687 x=x-(int) annotate_image->columns/2;
688 y=y-(int) (annotate_image->rows-(annotate_image->columns/2));
689 break;
690 }
691 }
692 }
693 /*
694 Composite text onto the image.
695 */
696 (void) XParseGeometry(annotate_info->geometry,&x,&y,&width,&height);
697 matte=image->matte;
698 (void) CompositeImage(image,annotate_image->matte != MagickFalse ?
cristye941a752011-10-15 01:52:48 +0000699 OverCompositeOp : CopyCompositeOp,annotate_image,(ssize_t) x,(ssize_t) y,
700 exception);
cristy3ed852e2009-09-05 21:47:34 +0000701 image->matte=matte;
702 annotate_image=DestroyImage(annotate_image);
703 return(MagickTrue);
704}
705
706/*
707%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
708% %
709% %
710% %
711% X B e s t F o n t %
712% %
713% %
714% %
715%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
716%
717% XBestFont() returns the "best" font. "Best" is defined as a font specified
718% in the X resource database or a font such that the text width displayed
719% with the font does not exceed the specified maximum width.
720%
721% The format of the XBestFont method is:
722%
723% XFontStruct *XBestFont(Display *display,
724% const XResourceInfo *resource_info,const MagickBooleanType text_font)
725%
726% A description of each parameter follows:
727%
728% o font: XBestFont returns a pointer to a XFontStruct structure.
729%
730% o display: Specifies a connection to an X server; returned from
731% XOpenDisplay.
732%
733% o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
734%
735% o text_font: True is font should be mono-spaced (typewriter style).
736%
cristy3ed852e2009-09-05 21:47:34 +0000737*/
738
739static char **FontToList(char *font)
740{
741 char
742 **fontlist;
743
744 register char
745 *p,
746 *q;
747
748 register int
749 i;
750
751 unsigned int
752 fonts;
753
754 if (font == (char *) NULL)
755 return((char **) NULL);
756 /*
757 Convert string to an ASCII list.
758 */
759 fonts=1U;
760 for (p=font; *p != '\0'; p++)
761 if ((*p == ':') || (*p == ';') || (*p == ','))
762 fonts++;
763 fontlist=(char **) AcquireQuantumMemory((size_t) fonts+1UL,sizeof(*fontlist));
764 if (fontlist == (char **) NULL)
765 {
766 ThrowXWindowFatalException(ResourceLimitError,"MemoryAllocationFailed",
767 font);
768 return((char **) NULL);
769 }
770 p=font;
771 for (i=0; i < (int) fonts; i++)
772 {
773 for (q=p; *q != '\0'; q++)
774 if ((*q == ':') || (*q == ';') || (*q == ','))
775 break;
776 fontlist[i]=(char *) AcquireQuantumMemory((size_t) (q-p)+1UL,
777 sizeof(*fontlist[i]));
778 if (fontlist[i] == (char *) NULL)
779 {
780 ThrowXWindowFatalException(ResourceLimitError,"MemoryAllocationFailed",
781 font);
782 return((char **) NULL);
783 }
784 (void) CopyMagickString(fontlist[i],p,(size_t) (q-p+1));
785 p=q+1;
786 }
787 fontlist[i]=(char *) NULL;
788 return(fontlist);
789}
790
cristybcbda3f2011-09-03 13:01:22 +0000791MagickPrivate XFontStruct *XBestFont(Display *display,
cristy3ed852e2009-09-05 21:47:34 +0000792 const XResourceInfo *resource_info,const MagickBooleanType text_font)
793{
794 static const char
795 *Fonts[]=
796 {
797 "-*-helvetica-medium-r-normal--12-*-*-*-*-*-iso8859-1",
798 "-*-arial-medium-r-normal--12-*-*-*-*-*-iso8859-1",
799 "-*-helvetica-medium-r-normal--12-*-*-*-*-*-iso8859-15",
800 "-*-arial-medium-r-normal--12-*-*-*-*-*-iso8859-15",
801 "-*-helvetica-medium-r-normal--12-*-*-*-*-*-*-*",
802 "-*-arial-medium-r-normal--12-*-*-*-*-*-*-*",
803 "variable",
804 "fixed",
805 (char *) NULL
806 },
807 *TextFonts[]=
808 {
809 "-*-courier-medium-r-normal-*-12-*-*-*-*-*-iso8859-1",
810 "-*-courier-medium-r-normal-*-12-*-*-*-*-*-iso8859-15",
811 "-*-fixed-medium-r-normal-*-12-*-*-*-*-*-*-*",
812 "fixed",
813 (char *) NULL
814 };
815
816 char
817 *font_name;
818
819 register const char
820 **p;
821
822 XFontStruct
823 *font_info;
824
825 font_info=(XFontStruct *) NULL;
826 font_name=resource_info->font;
827 if (text_font != MagickFalse)
828 font_name=resource_info->text_font;
829 if ((font_name != (char *) NULL) && (*font_name != '\0'))
830 {
831 char
832 **fontlist;
833
834 register int
835 i;
836
837 /*
838 Load preferred font specified in the X resource database.
839 */
840 fontlist=FontToList(font_name);
841 if (fontlist != (char **) NULL)
842 {
843 for (i=0; fontlist[i] != (char *) NULL; i++)
844 {
845 if (font_info == (XFontStruct *) NULL)
846 font_info=XLoadQueryFont(display,fontlist[i]);
847 fontlist[i]=DestroyString(fontlist[i]);
848 }
849 fontlist=(char **) RelinquishMagickMemory(fontlist);
850 }
851 if (font_info == (XFontStruct *) NULL)
852 ThrowXWindowFatalException(XServerError,"UnableToLoadFont",font_name);
853 }
854 /*
855 Load fonts from list of fonts until one is found.
856 */
857 p=Fonts;
858 if (text_font != MagickFalse)
859 p=TextFonts;
860 if (XDisplayHeight(display,XDefaultScreen(display)) >= 748)
861 p++;
862 while (*p != (char *) NULL)
863 {
864 if (font_info != (XFontStruct *) NULL)
865 break;
866 font_info=XLoadQueryFont(display,(char *) *p);
867 p++;
868 }
869 return(font_info);
870}
871
872/*
873%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
874% %
875% %
876% %
877% X B e s t I c o n S i z e %
878% %
879% %
880% %
881%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
882%
883% XBestIconSize() returns the "best" icon size. "Best" is defined as an icon
884% size that maintains the aspect ratio of the image. If the window manager
885% has preferred icon sizes, one of the preferred sizes is used.
886%
887% The format of the XBestIconSize method is:
888%
889% void XBestIconSize(Display *display,XWindowInfo *window,Image *image)
890%
891% A description of each parameter follows:
892%
893% o display: Specifies a connection to an X server; returned from
894% XOpenDisplay.
895%
896% o image: the image.
897%
898*/
cristybcbda3f2011-09-03 13:01:22 +0000899MagickPrivate void XBestIconSize(Display *display,XWindowInfo *window,
cristy3ed852e2009-09-05 21:47:34 +0000900 Image *image)
901{
902 int
903 i,
904 number_sizes;
905
906 MagickRealType
907 scale_factor;
908
909 unsigned int
910 height,
911 icon_height,
912 icon_width,
913 width;
914
915 Window
916 root_window;
917
918 XIconSize
919 *icon_size,
920 *size_list;
921
922 /*
923 Determine if the window manager has specified preferred icon sizes.
924 */
925 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
926 assert(display != (Display *) NULL);
927 assert(window != (XWindowInfo *) NULL);
928 assert(image != (Image *) NULL);
929 window->width=MaxIconSize;
930 window->height=MaxIconSize;
931 icon_size=(XIconSize *) NULL;
932 number_sizes=0;
933 root_window=XRootWindow(display,window->screen);
934 if (XGetIconSizes(display,root_window,&size_list,&number_sizes) != 0)
935 if ((number_sizes > 0) && (size_list != (XIconSize *) NULL))
936 icon_size=size_list;
937 if (icon_size == (XIconSize *) NULL)
938 {
939 /*
940 Window manager does not restrict icon size.
941 */
942 icon_size=XAllocIconSize();
943 if (icon_size == (XIconSize *) NULL)
944 {
945 ThrowXWindowFatalException(ResourceLimitError,
946 "MemoryAllocationFailed",image->filename);
947 return;
948 }
949 icon_size->min_width=1;
950 icon_size->max_width=MaxIconSize;
951 icon_size->min_height=1;
952 icon_size->max_height=MaxIconSize;
953 icon_size->width_inc=1;
954 icon_size->height_inc=1;
955 }
956 /*
957 Determine aspect ratio of image.
958 */
959 width=(unsigned int) image->columns;
960 height=(unsigned int) image->rows;
961 i=0;
962 if (window->crop_geometry)
963 (void) XParseGeometry(window->crop_geometry,&i,&i,&width,&height);
964 /*
965 Look for an icon size that maintains the aspect ratio of image.
966 */
967 scale_factor=(MagickRealType) icon_size->max_width/width;
968 if (scale_factor > ((MagickRealType) icon_size->max_height/height))
969 scale_factor=(MagickRealType) icon_size->max_height/height;
970 icon_width=(unsigned int) icon_size->min_width;
971 while ((int) icon_width < icon_size->max_width)
972 {
973 if (icon_width >= (unsigned int) (scale_factor*width+0.5))
974 break;
975 icon_width+=icon_size->width_inc;
976 }
977 icon_height=(unsigned int) icon_size->min_height;
978 while ((int) icon_height < icon_size->max_height)
979 {
980 if (icon_height >= (unsigned int) (scale_factor*height+0.5))
981 break;
982 icon_height+=icon_size->height_inc;
983 }
984 (void) XFree((void *) icon_size);
985 window->width=icon_width;
986 window->height=icon_height;
987}
988
989/*
990%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
991% %
992% %
993% %
994% X B e s t P i x e l %
995% %
996% %
997% %
998%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
999%
1000% XBestPixel() returns a pixel from an array of pixels that is closest to the
1001% requested color. If the color array is NULL, the colors are obtained from
1002% the X server.
1003%
1004% The format of the XBestPixel method is:
1005%
1006% void XBestPixel(Display *display,const Colormap colormap,XColor *colors,
1007% unsigned int number_colors,XColor *color)
1008%
1009% A description of each parameter follows:
1010%
1011% o pixel: XBestPixel returns the pixel value closest to the requested
1012% color.
1013%
1014% o display: Specifies a connection to an X server; returned from
1015% XOpenDisplay.
1016%
1017% o colormap: Specifies the ID of the X server colormap.
1018%
1019% o colors: Specifies an array of XColor structures.
1020%
1021% o number_colors: Specifies the number of XColor structures in the
1022% color definition array.
1023%
1024% o color: Specifies the desired RGB value to find in the colors array.
1025%
1026*/
cristybcbda3f2011-09-03 13:01:22 +00001027MagickPrivate void XBestPixel(Display *display,const Colormap colormap,
cristy3ed852e2009-09-05 21:47:34 +00001028 XColor *colors,unsigned int number_colors,XColor *color)
1029{
1030 MagickBooleanType
1031 query_server;
1032
cristy4c08aed2011-07-01 19:47:50 +00001033 PixelInfo
cristy3ed852e2009-09-05 21:47:34 +00001034 pixel;
1035
1036 MagickRealType
1037 min_distance;
1038
1039 register MagickRealType
1040 distance;
1041
1042 register int
1043 i,
1044 j;
1045
1046 Status
1047 status;
1048
1049 /*
1050 Find closest representation for the requested RGB color.
1051 */
1052 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
1053 assert(display != (Display *) NULL);
1054 assert(color != (XColor *) NULL);
1055 status=XAllocColor(display,colormap,color);
1056 if (status != False)
1057 return;
1058 query_server=colors == (XColor *) NULL ? MagickTrue : MagickFalse;
1059 if (query_server != MagickFalse)
1060 {
1061 /*
1062 Read X server colormap.
1063 */
1064 colors=(XColor *) AcquireQuantumMemory(number_colors,sizeof(*colors));
1065 if (colors == (XColor *) NULL)
1066 {
1067 ThrowXWindowFatalException(ResourceLimitError,
1068 "MemoryAllocationFailed","...");
1069 return;
1070 }
1071 for (i=0; i < (int) number_colors; i++)
cristybb503372010-05-27 20:51:26 +00001072 colors[i].pixel=(size_t) i;
cristy3ed852e2009-09-05 21:47:34 +00001073 if (number_colors > 256)
1074 number_colors=256;
1075 (void) XQueryColors(display,colormap,colors,(int) number_colors);
1076 }
1077 min_distance=3.0*((MagickRealType) QuantumRange+1.0)*((MagickRealType)
1078 QuantumRange+1.0);
1079 j=0;
1080 for (i=0; i < (int) number_colors; i++)
1081 {
1082 pixel.red=colors[i].red-(MagickRealType) color->red;
1083 distance=pixel.red*pixel.red;
1084 if (distance > min_distance)
1085 continue;
1086 pixel.green=colors[i].green-(MagickRealType) color->green;
1087 distance+=pixel.green*pixel.green;
1088 if (distance > min_distance)
1089 continue;
1090 pixel.blue=colors[i].blue-(MagickRealType) color->blue;
1091 distance+=pixel.blue*pixel.blue;
1092 if (distance > min_distance)
1093 continue;
1094 min_distance=distance;
1095 color->pixel=colors[i].pixel;
1096 j=i;
1097 }
1098 (void) XAllocColor(display,colormap,&colors[j]);
1099 if (query_server != MagickFalse)
1100 colors=(XColor *) RelinquishMagickMemory(colors);
1101}
1102
1103/*
1104%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1105% %
1106% %
1107% %
1108% X B e s t V i s u a l I n f o %
1109% %
1110% %
1111% %
1112%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1113%
1114% XBestVisualInfo() returns visual information for a visual that is the "best"
1115% the server supports. "Best" is defined as:
1116%
1117% 1. Restrict the visual list to those supported by the default screen.
1118%
1119% 2. If a visual type is specified, restrict the visual list to those of
1120% that type.
1121%
1122% 3. If a map type is specified, choose the visual that matches the id
1123% specified by the Standard Colormap.
1124%
1125% 4 From the list of visuals, choose one that can display the most
1126% simultaneous colors. If more than one visual can display the same
1127% number of simultaneous colors, one is chosen based on a rank.
1128%
1129% The format of the XBestVisualInfo method is:
1130%
1131% XVisualInfo *XBestVisualInfo(Display *display,
1132% XStandardColormap *map_info,XResourceInfo *resource_info)
1133%
1134% A description of each parameter follows:
1135%
1136% o visual_info: XBestVisualInfo returns a pointer to a X11 XVisualInfo
1137% structure.
1138%
1139% o display: Specifies a connection to an X server; returned from
1140% XOpenDisplay.
1141%
1142% o map_info: If map_type is specified, this structure is initialized
1143% with info from the Standard Colormap.
1144%
1145% o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
1146%
1147*/
1148
1149static inline int MagickMax(const int x,const int y)
1150{
1151 if (x > y)
1152 return(x);
1153 return(y);
1154}
1155
cristybb503372010-05-27 20:51:26 +00001156static inline size_t MagickMin(const unsigned int x,
cristy3ed852e2009-09-05 21:47:34 +00001157 const unsigned int y)
1158{
1159 if (x < y)
1160 return(x);
1161 return(y);
1162}
1163
cristybcbda3f2011-09-03 13:01:22 +00001164MagickPrivate XVisualInfo *XBestVisualInfo(Display *display,
cristy3ed852e2009-09-05 21:47:34 +00001165 XStandardColormap *map_info,XResourceInfo *resource_info)
1166{
1167#define MaxStandardColormaps 7
1168#define XVisualColormapSize(visual_info) MagickMin((unsigned int) (\
1169 (visual_info->klass == TrueColor) || (visual_info->klass == DirectColor) ? \
1170 visual_info->red_mask | visual_info->green_mask | visual_info->blue_mask : \
1171 (unsigned int) visual_info->colormap_size),1U << visual_info->depth)
1172
1173 char
1174 *map_type,
1175 *visual_type;
1176
cristyc57f6942010-11-12 01:47:39 +00001177 int
1178 visual_mask;
1179
cristy3ed852e2009-09-05 21:47:34 +00001180 register int
1181 i;
1182
cristy8891f9c2010-06-04 23:32:17 +00001183 size_t
1184 one;
1185
cristy3ed852e2009-09-05 21:47:34 +00001186 static int
1187 number_visuals;
1188
1189 static XVisualInfo
1190 visual_template;
1191
1192 XVisualInfo
1193 *visual_info,
1194 *visual_list;
1195
1196 /*
1197 Restrict visual search by screen number.
1198 */
1199 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
1200 assert(display != (Display *) NULL);
1201 assert(map_info != (XStandardColormap *) NULL);
1202 assert(resource_info != (XResourceInfo *) NULL);
1203 map_type=resource_info->map_type;
1204 visual_type=resource_info->visual_type;
1205 visual_mask=VisualScreenMask;
1206 visual_template.screen=XDefaultScreen(display);
1207 visual_template.depth=XDefaultDepth(display,XDefaultScreen(display));
cristy8891f9c2010-06-04 23:32:17 +00001208 one=1;
cristy3ed852e2009-09-05 21:47:34 +00001209 if ((resource_info->immutable != MagickFalse) && (resource_info->colors != 0))
cristy8891f9c2010-06-04 23:32:17 +00001210 if (resource_info->colors <= (one << (size_t) visual_template.depth))
cristy3ed852e2009-09-05 21:47:34 +00001211 visual_mask|=VisualDepthMask;
1212 if (visual_type != (char *) NULL)
1213 {
1214 /*
1215 Restrict visual search by class or visual id.
1216 */
1217 if (LocaleCompare("staticgray",visual_type) == 0)
1218 {
1219 visual_mask|=VisualClassMask;
1220 visual_template.klass=StaticGray;
1221 }
1222 else
1223 if (LocaleCompare("grayscale",visual_type) == 0)
1224 {
1225 visual_mask|=VisualClassMask;
1226 visual_template.klass=GrayScale;
1227 }
1228 else
1229 if (LocaleCompare("staticcolor",visual_type) == 0)
1230 {
1231 visual_mask|=VisualClassMask;
1232 visual_template.klass=StaticColor;
1233 }
1234 else
1235 if (LocaleCompare("pseudocolor",visual_type) == 0)
1236 {
1237 visual_mask|=VisualClassMask;
1238 visual_template.klass=PseudoColor;
1239 }
1240 else
1241 if (LocaleCompare("truecolor",visual_type) == 0)
1242 {
1243 visual_mask|=VisualClassMask;
1244 visual_template.klass=TrueColor;
1245 }
1246 else
1247 if (LocaleCompare("directcolor",visual_type) == 0)
1248 {
1249 visual_mask|=VisualClassMask;
1250 visual_template.klass=DirectColor;
1251 }
1252 else
1253 if (LocaleCompare("default",visual_type) == 0)
1254 {
1255 visual_mask|=VisualIDMask;
1256 visual_template.visualid=XVisualIDFromVisual(
1257 XDefaultVisual(display,XDefaultScreen(display)));
1258 }
1259 else
1260 if (isdigit((int) ((unsigned char) *visual_type)) != 0)
1261 {
1262 visual_mask|=VisualIDMask;
1263 visual_template.visualid=
1264 strtol(visual_type,(char **) NULL,0);
1265 }
1266 else
1267 ThrowXWindowFatalException(XServerError,
1268 "UnrecognizedVisualSpecifier",visual_type);
1269 }
1270 /*
1271 Get all visuals that meet our criteria so far.
1272 */
1273 number_visuals=0;
1274 visual_list=XGetVisualInfo(display,visual_mask,&visual_template,
1275 &number_visuals);
1276 visual_mask=VisualScreenMask | VisualIDMask;
1277 if ((number_visuals == 0) || (visual_list == (XVisualInfo *) NULL))
1278 {
1279 /*
1280 Failed to get visual; try using the default visual.
1281 */
1282 ThrowXWindowFatalException(XServerWarning,"UnableToGetVisual",
1283 visual_type);
1284 visual_template.visualid=XVisualIDFromVisual(XDefaultVisual(display,
1285 XDefaultScreen(display)));
1286 visual_list=XGetVisualInfo(display,visual_mask,&visual_template,
1287 &number_visuals);
1288 if ((number_visuals == 0) || (visual_list == (XVisualInfo *) NULL))
1289 return((XVisualInfo *) NULL);
1290 ThrowXWindowFatalException(XServerWarning,"UsingDefaultVisual",
1291 XVisualClassName(visual_list->klass));
1292 }
1293 resource_info->color_recovery=MagickFalse;
1294 if ((map_info != (XStandardColormap *) NULL) && (map_type != (char *) NULL))
1295 {
1296 Atom
1297 map_property;
1298
1299 char
1300 map_name[MaxTextExtent];
1301
1302 int
1303 j,
1304 number_maps;
1305
1306 Status
1307 status;
1308
1309 Window
1310 root_window;
1311
1312 XStandardColormap
1313 *map_list;
1314
1315 /*
1316 Choose a visual associated with a standard colormap.
1317 */
1318 root_window=XRootWindow(display,XDefaultScreen(display));
1319 status=False;
1320 if (LocaleCompare(map_type,"list") != 0)
1321 {
1322 /*
1323 User specified Standard Colormap.
1324 */
cristyb51dff52011-05-19 16:55:47 +00001325 (void) FormatLocaleString((char *) map_name,MaxTextExtent,
cristy3ed852e2009-09-05 21:47:34 +00001326 "RGB_%s_MAP",map_type);
1327 LocaleUpper(map_name);
1328 map_property=XInternAtom(display,(char *) map_name,MagickTrue);
1329 if (map_property != (Atom) NULL)
1330 status=XGetRGBColormaps(display,root_window,&map_list,&number_maps,
1331 map_property);
1332 }
1333 else
1334 {
1335 static const char
1336 *colormap[MaxStandardColormaps]=
1337 {
1338 "_HP_RGB_SMOOTH_MAP_LIST",
1339 "RGB_BEST_MAP",
1340 "RGB_DEFAULT_MAP",
1341 "RGB_GRAY_MAP",
1342 "RGB_RED_MAP",
1343 "RGB_GREEN_MAP",
1344 "RGB_BLUE_MAP",
1345 };
1346
1347 /*
1348 Choose a standard colormap from a list.
1349 */
1350 for (i=0; i < MaxStandardColormaps; i++)
1351 {
1352 map_property=XInternAtom(display,(char *) colormap[i],MagickTrue);
1353 if (map_property == (Atom) NULL)
1354 continue;
1355 status=XGetRGBColormaps(display,root_window,&map_list,&number_maps,
1356 map_property);
1357 if (status != False)
1358 break;
1359 }
1360 resource_info->color_recovery=i == 0 ? MagickTrue : MagickFalse;
1361 }
1362 if (status == False)
1363 {
1364 ThrowXWindowFatalException(XServerError,"UnableToGetStandardColormap",
1365 map_type);
1366 return((XVisualInfo *) NULL);
1367 }
1368 /*
1369 Search all Standard Colormaps and visuals for ids that match.
1370 */
1371 *map_info=map_list[0];
1372#if !defined(PRE_R4_ICCCM)
1373 visual_template.visualid=XVisualIDFromVisual(visual_list[0].visual);
1374 for (i=0; i < number_maps; i++)
1375 for (j=0; j < number_visuals; j++)
1376 if (map_list[i].visualid ==
1377 XVisualIDFromVisual(visual_list[j].visual))
1378 {
1379 *map_info=map_list[i];
1380 visual_template.visualid=XVisualIDFromVisual(
1381 visual_list[j].visual);
1382 break;
1383 }
1384 if (map_info->visualid != visual_template.visualid)
1385 {
1386 ThrowXWindowFatalException(XServerError,
1387 "UnableToMatchVisualToStandardColormap",map_type);
1388 return((XVisualInfo *) NULL);
1389 }
1390#endif
1391 if (map_info->colormap == (Colormap) NULL)
1392 {
1393 ThrowXWindowFatalException(XServerError,
1394 "StandardColormapIsNotInitialized",map_type);
1395 return((XVisualInfo *) NULL);
1396 }
1397 (void) XFree((void *) map_list);
1398 }
1399 else
1400 {
1401 static const unsigned int
1402 rank[]=
1403 {
1404 StaticGray,
1405 GrayScale,
1406 StaticColor,
1407 DirectColor,
1408 TrueColor,
1409 PseudoColor
1410 };
1411
1412 XVisualInfo
1413 *p;
1414
1415 /*
1416 Pick one visual that displays the most simultaneous colors.
1417 */
1418 visual_info=visual_list;
1419 p=visual_list;
1420 for (i=1; i < number_visuals; i++)
1421 {
1422 p++;
1423 if (XVisualColormapSize(p) > XVisualColormapSize(visual_info))
1424 visual_info=p;
1425 else
1426 if (XVisualColormapSize(p) == XVisualColormapSize(visual_info))
1427 if (rank[p->klass] > rank[visual_info->klass])
1428 visual_info=p;
1429 }
1430 visual_template.visualid=XVisualIDFromVisual(visual_info->visual);
1431 }
1432 (void) XFree((void *) visual_list);
1433 /*
1434 Retrieve only one visual by its screen & id number.
1435 */
1436 visual_info=XGetVisualInfo(display,visual_mask,&visual_template,
1437 &number_visuals);
1438 if ((number_visuals == 0) || (visual_info == (XVisualInfo *) NULL))
1439 return((XVisualInfo *) NULL);
1440 return(visual_info);
1441}
1442
1443/*
1444%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1445% %
1446% %
1447% %
1448% X C h e c k D e f i n e C u r s o r %
1449% %
1450% %
1451% %
1452%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1453%
1454% XCheckDefineCursor() prevents cursor changes on the root window.
1455%
1456% The format of the XXCheckDefineCursor method is:
1457%
1458% XCheckDefineCursor(display,window,cursor)
1459%
1460% A description of each parameter follows:
1461%
1462% o display: Specifies a connection to an X server; returned from
1463% XOpenDisplay.
1464%
1465% o window: the window.
1466%
1467% o cursor: the cursor.
1468%
1469*/
cristybcbda3f2011-09-03 13:01:22 +00001470MagickPrivate int XCheckDefineCursor(Display *display,Window window,
cristy3ed852e2009-09-05 21:47:34 +00001471 Cursor cursor)
1472{
1473 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
1474 assert(display != (Display *) NULL);
1475 if (window == XRootWindow(display,XDefaultScreen(display)))
1476 return(0);
1477 return(XDefineCursor(display,window,cursor));
1478}
1479
1480/*
1481%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1482% %
1483% %
1484% %
1485% X C h e c k R e f r e s h W i n d o w s %
1486% %
1487% %
1488% %
1489%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1490%
1491% XCheckRefreshWindows() checks the X server for exposure events for a
1492% particular window and updates the areassociated with the exposure event.
1493%
1494% The format of the XCheckRefreshWindows method is:
1495%
1496% void XCheckRefreshWindows(Display *display,XWindows *windows)
1497%
1498% A description of each parameter follows:
1499%
1500% o display: Specifies a connection to an X server; returned from
1501% XOpenDisplay.
1502%
1503% o windows: Specifies a pointer to a XWindows structure.
1504%
1505*/
cristybcbda3f2011-09-03 13:01:22 +00001506MagickPrivate void XCheckRefreshWindows(Display *display,XWindows *windows)
cristy3ed852e2009-09-05 21:47:34 +00001507{
1508 Window
1509 id;
1510
1511 XEvent
1512 event;
1513
1514 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
1515 assert(display != (Display *) NULL);
1516 assert(windows != (XWindows *) NULL);
1517 XDelay(display,SuspendTime);
1518 id=windows->command.id;
1519 while (XCheckTypedWindowEvent(display,id,Expose,&event) != MagickFalse)
1520 (void) XCommandWidget(display,windows,(char const **) NULL,&event);
1521 id=windows->image.id;
1522 while (XCheckTypedWindowEvent(display,id,Expose,&event) != MagickFalse)
1523 XRefreshWindow(display,&windows->image,&event);
1524 XDelay(display,SuspendTime << 1);
1525 id=windows->command.id;
1526 while (XCheckTypedWindowEvent(display,id,Expose,&event) != MagickFalse)
1527 (void) XCommandWidget(display,windows,(char const **) NULL,&event);
1528 id=windows->image.id;
1529 while (XCheckTypedWindowEvent(display,id,Expose,&event) != MagickFalse)
1530 XRefreshWindow(display,&windows->image,&event);
1531}
1532
1533/*
1534%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1535% %
1536% %
1537% %
1538% X C l i e n t M e s s a g e %
1539% %
1540% %
1541% %
1542%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1543%
1544% XClientMessage() sends a reason to a window with XSendEvent. The reason is
1545% initialized with a particular protocol type and atom.
1546%
1547% The format of the XClientMessage function is:
1548%
1549% XClientMessage(display,window,protocol,reason,timestamp)
1550%
1551% A description of each parameter follows:
1552%
1553% o display: Specifies a pointer to the Display structure; returned from
1554% XOpenDisplay.
1555%
1556% o window: Specifies a pointer to a Window structure.
1557%
1558% o protocol: Specifies an atom value.
1559%
1560% o reason: Specifies an atom value which is the reason to send.
1561%
1562% o timestamp: Specifies a value of type Time.
1563%
1564*/
cristybcbda3f2011-09-03 13:01:22 +00001565MagickPrivate void XClientMessage(Display *display,const Window window,
cristy3ed852e2009-09-05 21:47:34 +00001566 const Atom protocol,const Atom reason,const Time timestamp)
1567{
1568 XClientMessageEvent
1569 client_event;
1570
1571 assert(display != (Display *) NULL);
1572 client_event.type=ClientMessage;
1573 client_event.window=window;
1574 client_event.message_type=protocol;
1575 client_event.format=32;
cristyc57f6942010-11-12 01:47:39 +00001576 client_event.data.l[0]=(long) reason;
1577 client_event.data.l[1]=(long) timestamp;
cristy3ed852e2009-09-05 21:47:34 +00001578 (void) XSendEvent(display,window,MagickFalse,NoEventMask,(XEvent *) &client_event);
1579}
1580
1581/*
1582%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1583% %
1584% %
1585% %
1586+ X C l i e n t W i n d o w %
1587% %
1588% %
1589% %
1590%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1591%
1592% XClientWindow() finds a window, at or below the specified window, which has
1593% a WM_STATE property. If such a window is found, it is returned, otherwise
1594% the argument window is returned.
1595%
1596% The format of the XClientWindow function is:
1597%
1598% client_window=XClientWindow(display,target_window)
1599%
1600% A description of each parameter follows:
1601%
1602% o client_window: XClientWindow returns a window, at or below the specified
1603% window, which has a WM_STATE property otherwise the argument
1604% target_window is returned.
1605%
1606% o display: Specifies a pointer to the Display structure; returned from
1607% XOpenDisplay.
1608%
1609% o target_window: Specifies the window to find a WM_STATE property.
1610%
cristy3ed852e2009-09-05 21:47:34 +00001611*/
1612static Window XClientWindow(Display *display,Window target_window)
1613{
1614 Atom
1615 state,
1616 type;
1617
1618 int
1619 format;
1620
1621 Status
1622 status;
1623
1624 unsigned char
1625 *data;
1626
cristyf2faecf2010-05-28 19:19:36 +00001627 unsigned long
cristy3ed852e2009-09-05 21:47:34 +00001628 after,
1629 number_items;
1630
1631 Window
1632 client_window;
1633
1634 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
1635 assert(display != (Display *) NULL);
1636 state=XInternAtom(display,"WM_STATE",MagickTrue);
1637 if (state == (Atom) NULL)
1638 return(target_window);
1639 type=(Atom) NULL;
1640 status=XGetWindowProperty(display,target_window,state,0L,0L,MagickFalse,
1641 (Atom) AnyPropertyType,&type,&format,&number_items,&after,&data);
1642 if ((status == Success) && (type != (Atom) NULL))
1643 return(target_window);
1644 client_window=XWindowByProperty(display,target_window,state);
1645 if (client_window == (Window) NULL)
1646 return(target_window);
1647 return(client_window);
1648}
1649
1650/*
1651%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1652% %
1653% %
1654% %
cristyf34a1452009-10-24 22:29:27 +00001655+ X C o m p o n e n t T e r m i n u s %
1656% %
1657% %
1658% %
1659%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1660%
1661% XComponentTerminus() destroys the module component.
1662%
1663% The format of the XComponentTerminus method is:
1664%
1665% XComponentTerminus(void)
1666%
1667*/
cristy5ff4eaf2011-09-03 01:38:02 +00001668MagickPrivate void XComponentTerminus(void)
cristyf34a1452009-10-24 22:29:27 +00001669{
1670 DestroyXResources();
1671}
1672
1673/*
1674%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1675% %
1676% %
1677% %
cristy3ed852e2009-09-05 21:47:34 +00001678% X C o n f i g u r e I m a g e C o l o r m a p %
1679% %
1680% %
1681% %
1682%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1683%
1684% XConfigureImageColormap() creates a new X colormap.
1685%
1686% The format of the XConfigureImageColormap method is:
1687%
1688% void XConfigureImageColormap(Display *display,
cristy6710d842011-10-20 23:23:00 +00001689% XResourceInfo *resource_info,XWindows *windows,Image *image,
1690% ExceptionInfo *exception)
cristy3ed852e2009-09-05 21:47:34 +00001691%
1692% A description of each parameter follows:
1693%
1694% o display: Specifies a connection to an X server; returned from
1695% XOpenDisplay.
1696%
1697% o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
1698%
1699% o windows: Specifies a pointer to a XWindows structure.
1700%
1701% o image: the image.
1702%
cristy6710d842011-10-20 23:23:00 +00001703% o exception: return any errors or warnings in this structure.
1704%
cristy3ed852e2009-09-05 21:47:34 +00001705*/
cristybcbda3f2011-09-03 13:01:22 +00001706MagickPrivate void XConfigureImageColormap(Display *display,
cristy6710d842011-10-20 23:23:00 +00001707 XResourceInfo *resource_info,XWindows *windows,Image *image,
1708 ExceptionInfo *exception)
cristy3ed852e2009-09-05 21:47:34 +00001709{
1710 Colormap
1711 colormap;
1712
1713 /*
1714 Make standard colormap.
1715 */
1716 XSetCursorState(display,windows,MagickTrue);
1717 XCheckRefreshWindows(display,windows);
1718 XMakeStandardColormap(display,windows->visual_info,resource_info,image,
cristy6710d842011-10-20 23:23:00 +00001719 windows->map_info,windows->pixel_info,exception);
cristy3ed852e2009-09-05 21:47:34 +00001720 colormap=windows->map_info->colormap;
1721 (void) XSetWindowColormap(display,windows->image.id,colormap);
1722 (void) XSetWindowColormap(display,windows->command.id,colormap);
1723 (void) XSetWindowColormap(display,windows->widget.id,colormap);
1724 if (windows->magnify.mapped != MagickFalse)
1725 (void) XSetWindowColormap(display,windows->magnify.id,colormap);
1726 if (windows->pan.mapped != MagickFalse)
1727 (void) XSetWindowColormap(display,windows->pan.id,colormap);
1728 XSetCursorState(display,windows,MagickFalse);
1729 XClientMessage(display,windows->image.id,windows->im_protocols,
1730 windows->im_update_colormap,CurrentTime);
1731}
1732
1733/*
1734%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1735% %
1736% %
1737% %
1738% X C o n s t r a i n W i n d o w P o s i t i o n %
1739% %
1740% %
1741% %
1742%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1743%
1744% XConstrainWindowPosition() assures a window is positioned within the X
1745% server boundaries.
1746%
1747% The format of the XConstrainWindowPosition method is:
1748%
1749% void XConstrainWindowPosition(Display *display,XWindowInfo *window_info)
1750%
1751% A description of each parameter follows:
1752%
1753% o display: Specifies a pointer to the Display structure; returned from
1754% XOpenDisplay.
1755%
1756% o window_info: Specifies a pointer to a XWindowInfo structure.
1757%
1758*/
cristybcbda3f2011-09-03 13:01:22 +00001759MagickPrivate void XConstrainWindowPosition(Display *display,
cristy3ed852e2009-09-05 21:47:34 +00001760 XWindowInfo *window_info)
1761{
1762 int
1763 limit;
1764
1765 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
1766 assert(display != (Display *) NULL);
1767 assert(window_info != (XWindowInfo *) NULL);
1768 limit=XDisplayWidth(display,window_info->screen)-window_info->width;
1769 if (window_info->x < 0)
1770 window_info->x=0;
1771 else
1772 if (window_info->x > (int) limit)
1773 window_info->x=(int) limit;
1774 limit=XDisplayHeight(display,window_info->screen)-window_info->height;
1775 if (window_info->y < 0)
1776 window_info->y=0;
1777 else
1778 if (window_info->y > limit)
1779 window_info->y=limit;
1780}
1781
1782/*
1783%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1784% %
1785% %
1786% %
1787% X D e l a y %
1788% %
1789% %
1790% %
1791%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1792%
1793% XDelay() suspends program execution for the number of milliseconds
1794% specified.
1795%
1796% The format of the Delay method is:
1797%
cristybb503372010-05-27 20:51:26 +00001798% void XDelay(Display *display,const size_t milliseconds)
cristy3ed852e2009-09-05 21:47:34 +00001799%
1800% A description of each parameter follows:
1801%
1802% o display: Specifies a pointer to the Display structure; returned from
1803% XOpenDisplay.
1804%
1805% o milliseconds: Specifies the number of milliseconds to delay before
1806% returning.
1807%
1808*/
cristybcbda3f2011-09-03 13:01:22 +00001809MagickPrivate void XDelay(Display *display,const size_t milliseconds)
cristy3ed852e2009-09-05 21:47:34 +00001810{
1811 assert(display != (Display *) NULL);
1812 (void) XFlush(display);
cristya21afde2010-07-02 00:45:40 +00001813 MagickDelay(milliseconds);
cristy3ed852e2009-09-05 21:47:34 +00001814}
1815
1816/*
1817%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1818% %
1819% %
1820% %
1821% X D e s t r o y R e s o u r c e I n f o %
1822% %
1823% %
1824% %
1825%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1826%
1827% XDestroyResourceInfo() frees memory associated with the XResourceInfo
1828% structure.
1829%
1830% The format of the XDestroyResourceInfo method is:
1831%
1832% void XDestroyResourceInfo(XResourceInfo *resource_info)
1833%
1834% A description of each parameter follows:
1835%
1836% o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
1837%
1838*/
1839MagickExport void XDestroyResourceInfo(XResourceInfo *resource_info)
1840{
1841 if (resource_info->image_geometry != (char *) NULL)
1842 resource_info->image_geometry=(char *)
1843 RelinquishMagickMemory(resource_info->image_geometry);
1844 if (resource_info->quantize_info != (QuantizeInfo *) NULL)
1845 resource_info->quantize_info=DestroyQuantizeInfo(
1846 resource_info->quantize_info);
1847 if (resource_info->client_name != (char *) NULL)
1848 resource_info->client_name=(char *)
1849 RelinquishMagickMemory(resource_info->client_name);
1850 if (resource_info->name != (char *) NULL)
1851 resource_info->name=DestroyString(resource_info->name);
1852 (void) ResetMagickMemory(resource_info,0,sizeof(*resource_info));
1853}
1854
1855/*
1856%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1857% %
1858% %
1859% %
1860% X D e s t r o y W i n d o w C o l o r s %
1861% %
1862% %
1863% %
1864%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1865%
1866% XDestroyWindowColors() frees X11 color resources previously saved on a
1867% window by XRetainWindowColors or programs like xsetroot.
1868%
1869% The format of the XDestroyWindowColors method is:
1870%
1871% void XDestroyWindowColors(Display *display,Window window)
1872%
1873% A description of each parameter follows:
1874%
1875% o display: Specifies a connection to an X server; returned from
1876% XOpenDisplay.
1877%
1878% o window: Specifies a pointer to a Window structure.
1879%
1880*/
cristybcbda3f2011-09-03 13:01:22 +00001881MagickPrivate void XDestroyWindowColors(Display *display,Window window)
cristy3ed852e2009-09-05 21:47:34 +00001882{
1883 Atom
1884 property,
1885 type;
1886
1887 int
1888 format;
1889
1890 Status
1891 status;
1892
1893 unsigned char
1894 *data;
1895
cristyf2faecf2010-05-28 19:19:36 +00001896 unsigned long
cristy3ed852e2009-09-05 21:47:34 +00001897 after,
1898 length;
1899
1900 /*
1901 If there are previous resources on the root window, destroy them.
1902 */
1903 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
1904 assert(display != (Display *) NULL);
1905 property=XInternAtom(display,"_XSETROOT_ID",MagickFalse);
1906 if (property == (Atom) NULL)
1907 {
1908 ThrowXWindowFatalException(XServerError,"UnableToCreateProperty",
1909 "_XSETROOT_ID");
1910 return;
1911 }
1912 status=XGetWindowProperty(display,window,property,0L,1L,MagickTrue,
1913 (Atom) AnyPropertyType,&type,&format,&length,&after,&data);
1914 if (status != Success)
1915 return;
1916 if ((type == XA_PIXMAP) && (format == 32) && (length == 1) && (after == 0))
1917 {
1918 (void) XKillClient(display,(XID) (*((Pixmap *) data)));
1919 (void) XDeleteProperty(display,window,property);
1920 }
1921 if (type != None)
1922 (void) XFree((void *) data);
1923}
1924
1925/*
1926%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1927% %
1928% %
1929% %
1930% X D i s p l a y I m a g e I n f o %
1931% %
1932% %
1933% %
1934%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1935%
1936% XDisplayImageInfo() displays information about an X image.
1937%
1938% The format of the XDisplayImageInfo method is:
1939%
1940% void XDisplayImageInfo(Display *display,
1941% const XResourceInfo *resource_info,XWindows *windows,Image *undo_image,
cristy6710d842011-10-20 23:23:00 +00001942% Image *image,ExceptionInfo *exception)
cristy3ed852e2009-09-05 21:47:34 +00001943%
1944% A description of each parameter follows:
1945%
1946% o display: Specifies a connection to an X server; returned from
1947% XOpenDisplay.
1948%
1949% o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
1950%
1951% o windows: Specifies a pointer to a XWindows structure.
1952%
1953% o undo_image: the undo image.
1954%
1955% o image: the image.
1956%
cristy6710d842011-10-20 23:23:00 +00001957% o exception: return any errors or warnings in this structure.
1958%
cristy3ed852e2009-09-05 21:47:34 +00001959*/
cristybcbda3f2011-09-03 13:01:22 +00001960MagickPrivate void XDisplayImageInfo(Display *display,
cristy3ed852e2009-09-05 21:47:34 +00001961 const XResourceInfo *resource_info,XWindows *windows,Image *undo_image,
cristy6710d842011-10-20 23:23:00 +00001962 Image *image,ExceptionInfo *exception)
cristy3ed852e2009-09-05 21:47:34 +00001963{
1964 char
1965 filename[MaxTextExtent],
1966 *text,
1967 **textlist;
1968
1969 FILE
1970 *file;
1971
1972 int
1973 unique_file;
1974
cristybb503372010-05-27 20:51:26 +00001975 register ssize_t
cristy3ed852e2009-09-05 21:47:34 +00001976 i;
1977
cristybb503372010-05-27 20:51:26 +00001978 size_t
cristy3ed852e2009-09-05 21:47:34 +00001979 number_pixels;
1980
cristy9d314ff2011-03-09 01:30:28 +00001981 ssize_t
1982 bytes;
1983
1984 unsigned int
1985 levels;
1986
cristy3ed852e2009-09-05 21:47:34 +00001987 /*
1988 Write info about the X server to a file.
1989 */
1990 assert(display != (Display *) NULL);
1991 assert(resource_info != (XResourceInfo *) NULL);
1992 assert(windows != (XWindows *) NULL);
1993 assert(image != (Image *) NULL);
1994 if (image->debug)
1995 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
1996 file=(FILE *) NULL;
1997 unique_file=AcquireUniqueFileResource(filename);
1998 if (unique_file != -1)
1999 file=fdopen(unique_file,"w");
2000 if ((unique_file == -1) || (file == (FILE *) NULL))
2001 {
2002 XNoticeWidget(display,windows,"Unable to display image info",filename);
2003 return;
2004 }
2005 if (resource_info->gamma_correct != MagickFalse)
2006 if (resource_info->display_gamma != (char *) NULL)
cristyb51dff52011-05-19 16:55:47 +00002007 (void) FormatLocaleFile(file,"Display\n gamma: %s\n\n",
cristy3ed852e2009-09-05 21:47:34 +00002008 resource_info->display_gamma);
2009 /*
2010 Write info about the X image to a file.
2011 */
cristyb51dff52011-05-19 16:55:47 +00002012 (void) FormatLocaleFile(file,"X\n visual: %s\n",
cristy3ed852e2009-09-05 21:47:34 +00002013 XVisualClassName((int) windows->image.storage_class));
cristyb51dff52011-05-19 16:55:47 +00002014 (void) FormatLocaleFile(file," depth: %d\n",windows->image.ximage->depth);
cristy3ed852e2009-09-05 21:47:34 +00002015 if (windows->visual_info->colormap_size != 0)
cristyb51dff52011-05-19 16:55:47 +00002016 (void) FormatLocaleFile(file," colormap size: %d\n",
cristy3ed852e2009-09-05 21:47:34 +00002017 windows->visual_info->colormap_size);
2018 if (resource_info->colormap== SharedColormap)
cristyb51dff52011-05-19 16:55:47 +00002019 (void) FormatLocaleFile(file," colormap type: Shared\n");
cristy3ed852e2009-09-05 21:47:34 +00002020 else
cristyb51dff52011-05-19 16:55:47 +00002021 (void) FormatLocaleFile(file," colormap type: Private\n");
cristy1e604812011-05-19 18:07:50 +00002022 (void) FormatLocaleFile(file," geometry: %dx%d\n",
2023 windows->image.ximage->width,windows->image.ximage->height);
cristy3ed852e2009-09-05 21:47:34 +00002024 if (windows->image.crop_geometry != (char *) NULL)
cristy1e604812011-05-19 18:07:50 +00002025 (void) FormatLocaleFile(file," crop geometry: %s\n",
2026 windows->image.crop_geometry);
cristy3ed852e2009-09-05 21:47:34 +00002027 if (windows->image.pixmap == (Pixmap) NULL)
cristyb51dff52011-05-19 16:55:47 +00002028 (void) FormatLocaleFile(file," type: X Image\n");
cristy3ed852e2009-09-05 21:47:34 +00002029 else
cristyb51dff52011-05-19 16:55:47 +00002030 (void) FormatLocaleFile(file," type: Pixmap\n");
cristy3ed852e2009-09-05 21:47:34 +00002031 if (windows->image.shape != MagickFalse)
cristyb51dff52011-05-19 16:55:47 +00002032 (void) FormatLocaleFile(file," non-rectangular shape: True\n");
cristy3ed852e2009-09-05 21:47:34 +00002033 else
cristyb51dff52011-05-19 16:55:47 +00002034 (void) FormatLocaleFile(file," non-rectangular shape: False\n");
cristy3ed852e2009-09-05 21:47:34 +00002035 if (windows->image.shared_memory != MagickFalse)
cristyb51dff52011-05-19 16:55:47 +00002036 (void) FormatLocaleFile(file," shared memory: True\n");
cristy3ed852e2009-09-05 21:47:34 +00002037 else
cristyb51dff52011-05-19 16:55:47 +00002038 (void) FormatLocaleFile(file," shared memory: False\n");
2039 (void) FormatLocaleFile(file,"\n");
cristy3ed852e2009-09-05 21:47:34 +00002040 if (resource_info->font != (char *) NULL)
cristyb51dff52011-05-19 16:55:47 +00002041 (void) FormatLocaleFile(file,"Font: %s\n\n",resource_info->font);
cristy3ed852e2009-09-05 21:47:34 +00002042 if (resource_info->text_font != (char *) NULL)
cristyb51dff52011-05-19 16:55:47 +00002043 (void) FormatLocaleFile(file,"Text font: %s\n\n",resource_info->text_font);
cristy3ed852e2009-09-05 21:47:34 +00002044 /*
2045 Write info about the undo cache to a file.
2046 */
2047 bytes=0;
2048 for (levels=0; undo_image != (Image *) NULL; levels++)
2049 {
2050 number_pixels=undo_image->list->columns*undo_image->list->rows;
cristy101ab702011-10-13 13:06:32 +00002051 bytes+=number_pixels*sizeof(PixelInfo);
cristy3ed852e2009-09-05 21:47:34 +00002052 undo_image=GetPreviousImageInList(undo_image);
2053 }
cristyb51dff52011-05-19 16:55:47 +00002054 (void) FormatLocaleFile(file,"Undo Edit Cache\n levels: %u\n",levels);
cristy1e604812011-05-19 18:07:50 +00002055 (void) FormatLocaleFile(file," bytes: %.20gmb\n",(double)
2056 ((bytes+(1 << 19)) >> 20));
cristyb51dff52011-05-19 16:55:47 +00002057 (void) FormatLocaleFile(file," limit: %.20gmb\n\n",(double)
cristyf2faecf2010-05-28 19:19:36 +00002058 resource_info->undo_cache);
cristy3ed852e2009-09-05 21:47:34 +00002059 /*
2060 Write info about the image to a file.
2061 */
cristy6710d842011-10-20 23:23:00 +00002062 (void) IdentifyImage(image,file,MagickTrue,exception);
cristy3ed852e2009-09-05 21:47:34 +00002063 (void) fclose(file);
cristy6710d842011-10-20 23:23:00 +00002064 text=FileToString(filename,~0,exception);
cristy3ed852e2009-09-05 21:47:34 +00002065 (void) RelinquishUniqueFileResource(filename);
2066 if (text == (char *) NULL)
2067 {
2068 XNoticeWidget(display,windows,"MemoryAllocationFailed",
2069 "UnableToDisplayImageInfo");
2070 return;
2071 }
2072 textlist=StringToList(text);
2073 if (textlist != (char **) NULL)
2074 {
2075 char
2076 title[MaxTextExtent];
2077
2078 /*
2079 Display information about the image in the Text View widget.
2080 */
2081 (void) XWithdrawWindow(display,windows->info.id,windows->info.screen);
cristyb51dff52011-05-19 16:55:47 +00002082 (void) FormatLocaleString(title,MaxTextExtent,"Image Info: %s",
cristy3ed852e2009-09-05 21:47:34 +00002083 image->filename);
2084 XTextViewWidget(display,resource_info,windows,MagickTrue,title,
2085 (char const **) textlist);
2086 for (i=0; textlist[i] != (char *) NULL; i++)
2087 textlist[i]=DestroyString(textlist[i]);
2088 textlist=(char **) RelinquishMagickMemory(textlist);
2089 }
2090 text=DestroyString(text);
2091}
2092
2093/*
2094%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2095% %
2096% %
2097% %
2098+ X D i t h e r I m a g e %
2099% %
2100% %
2101% %
2102%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2103%
2104% XDitherImage() dithers the reference image as required by the HP Color
2105% Recovery algorithm. The color values are quantized to 3 bits of red and
2106% green, and 2 bits of blue (3/3/2) and can be used as indices into a 8-bit X
2107% standard colormap.
2108%
2109% The format of the XDitherImage method is:
2110%
cristy6710d842011-10-20 23:23:00 +00002111% void XDitherImage(Image *image,XImage *ximage,ExceptionInfo *exception)
cristy3ed852e2009-09-05 21:47:34 +00002112%
2113% A description of each parameter follows:
2114%
2115% o image: the image.
2116%
2117% o ximage: Specifies a pointer to a XImage structure; returned from
2118% XCreateImage.
2119%
cristy6710d842011-10-20 23:23:00 +00002120% o exception: return any errors or warnings in this structure.
2121%
cristy3ed852e2009-09-05 21:47:34 +00002122*/
cristy6710d842011-10-20 23:23:00 +00002123static void XDitherImage(Image *image,XImage *ximage,ExceptionInfo *exception)
cristy3ed852e2009-09-05 21:47:34 +00002124{
2125 static const short int
2126 dither_red[2][16]=
2127 {
2128 {-16, 4, -1, 11,-14, 6, -3, 9,-15, 5, -2, 10,-13, 7, -4, 8},
2129 { 15, -5, 0,-12, 13, -7, 2,-10, 14, -6, 1,-11, 12, -8, 3, -9}
2130 },
2131 dither_green[2][16]=
2132 {
2133 { 11,-15, 7, -3, 8,-14, 4, -2, 10,-16, 6, -4, 9,-13, 5, -1},
2134 {-12, 14, -8, 2, -9, 13, -5, 1,-11, 15, -7, 3,-10, 12, -6, 0}
2135 },
2136 dither_blue[2][16]=
2137 {
2138 { -3, 9,-13, 7, -1, 11,-15, 5, -4, 8,-14, 6, -2, 10,-16, 4},
2139 { 2,-10, 12, -8, 0,-12, 14, -6, 3, -9, 13, -7, 1,-11, 15, -5}
2140 };
2141
cristyc57f6942010-11-12 01:47:39 +00002142 CacheView
2143 *image_view;
cristy3ed852e2009-09-05 21:47:34 +00002144
2145 int
cristyc57f6942010-11-12 01:47:39 +00002146 value,
cristy3ed852e2009-09-05 21:47:34 +00002147 y;
2148
cristy101ab702011-10-13 13:06:32 +00002149 PixelInfo
cristyc57f6942010-11-12 01:47:39 +00002150 color;
cristy3ed852e2009-09-05 21:47:34 +00002151
2152 register char
2153 *q;
2154
cristy4c08aed2011-07-01 19:47:50 +00002155 register const Quantum
cristy3ed852e2009-09-05 21:47:34 +00002156 *p;
2157
2158 register int
2159 i,
2160 j,
2161 x;
2162
2163 unsigned int
2164 scanline_pad;
2165
cristybb503372010-05-27 20:51:26 +00002166 register size_t
cristy3ed852e2009-09-05 21:47:34 +00002167 pixel;
2168
2169 unsigned char
2170 *blue_map[2][16],
2171 *green_map[2][16],
2172 *red_map[2][16];
2173
2174 /*
2175 Allocate and initialize dither maps.
2176 */
2177 for (i=0; i < 2; i++)
2178 for (j=0; j < 16; j++)
2179 {
2180 red_map[i][j]=(unsigned char *) AcquireQuantumMemory(256UL,
2181 sizeof(*red_map));
2182 green_map[i][j]=(unsigned char *) AcquireQuantumMemory(256UL,
2183 sizeof(*green_map));
2184 blue_map[i][j]=(unsigned char *) AcquireQuantumMemory(256UL,
2185 sizeof(*blue_map));
2186 if ((red_map[i][j] == (unsigned char *) NULL) ||
2187 (green_map[i][j] == (unsigned char *) NULL) ||
2188 (blue_map[i][j] == (unsigned char *) NULL))
2189 {
2190 ThrowXWindowFatalException(ResourceLimitError,
2191 "MemoryAllocationFailed",image->filename);
2192 return;
2193 }
2194 }
2195 /*
2196 Initialize dither tables.
2197 */
2198 for (i=0; i < 2; i++)
2199 for (j=0; j < 16; j++)
2200 for (x=0; x < 256; x++)
2201 {
2202 value=x-16;
2203 if (x < 48)
2204 value=x/2+8;
2205 value+=dither_red[i][j];
2206 red_map[i][j][x]=(unsigned char)
2207 ((value < 0) ? 0 : (value > 255) ? 255 : value);
2208 value=x-16;
2209 if (x < 48)
2210 value=x/2+8;
2211 value+=dither_green[i][j];
2212 green_map[i][j][x]=(unsigned char)
2213 ((value < 0) ? 0 : (value > 255) ? 255 : value);
2214 value=x-32;
2215 if (x < 112)
2216 value=x/2+24;
cristybb503372010-05-27 20:51:26 +00002217 value+=((size_t) dither_blue[i][j] << 1);
cristy3ed852e2009-09-05 21:47:34 +00002218 blue_map[i][j][x]=(unsigned char)
2219 ((value < 0) ? 0 : (value > 255) ? 255 : value);
2220 }
2221 /*
2222 Dither image.
2223 */
2224 scanline_pad=(unsigned int) (ximage->bytes_per_line-
cristybb503372010-05-27 20:51:26 +00002225 ((size_t) (ximage->width*ximage->bits_per_pixel) >> 3));
cristy3ed852e2009-09-05 21:47:34 +00002226 i=0;
2227 j=0;
2228 q=ximage->data;
cristyc57f6942010-11-12 01:47:39 +00002229 image_view=AcquireCacheView(image);
cristy3ed852e2009-09-05 21:47:34 +00002230 for (y=0; y < (int) image->rows; y++)
2231 {
cristyc57f6942010-11-12 01:47:39 +00002232 p=GetCacheViewVirtualPixels(image_view,0,(ssize_t) y,image->columns,1,
cristy6710d842011-10-20 23:23:00 +00002233 exception);
cristy4c08aed2011-07-01 19:47:50 +00002234 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00002235 break;
2236 for (x=0; x < (int) image->columns; x++)
2237 {
cristye42f6582012-02-11 17:59:50 +00002238 color.red=(double) ClampToQuantum((MagickRealType) (red_map[i][j][
2239 (int) ScaleQuantumToChar(GetPixelRed(image,p))] << 8));
2240 color.green=(double) ClampToQuantum((MagickRealType) (green_map[i][j][
2241 (int) ScaleQuantumToChar(GetPixelGreen(image,p))] << 8));
2242 color.blue=(double) ClampToQuantum((MagickRealType) (blue_map[i][j][
2243 (int) ScaleQuantumToChar(GetPixelBlue(image,p))] << 8));
cristybb503372010-05-27 20:51:26 +00002244 pixel=(size_t) (((size_t) color.red & 0xe0) |
2245 (((size_t) color.green & 0xe0) >> 3) |
2246 (((size_t) color.blue & 0xc0) >> 6));
cristy3ed852e2009-09-05 21:47:34 +00002247 *q++=(char) pixel;
cristyed231572011-07-14 02:18:59 +00002248 p+=GetPixelChannels(image);
cristy3ed852e2009-09-05 21:47:34 +00002249 j++;
2250 if (j == 16)
2251 j=0;
2252 }
2253 q+=scanline_pad;
2254 i++;
2255 if (i == 2)
2256 i=0;
2257 }
cristyc57f6942010-11-12 01:47:39 +00002258 image_view=DestroyCacheView(image_view);
cristy3ed852e2009-09-05 21:47:34 +00002259 /*
2260 Free allocated memory.
2261 */
2262 for (i=0; i < 2; i++)
2263 for (j=0; j < 16; j++)
2264 {
2265 green_map[i][j]=(unsigned char *) RelinquishMagickMemory(green_map[i][j]);
2266 blue_map[i][j]=(unsigned char *) RelinquishMagickMemory(blue_map[i][j]);
2267 red_map[i][j]=(unsigned char *) RelinquishMagickMemory(red_map[i][j]);
2268 }
2269}
2270
2271/*
2272%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2273% %
2274% %
2275% %
2276% X D r a w I m a g e %
2277% %
2278% %
2279% %
2280%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2281%
2282% XDrawImage() draws a line on the image.
2283%
2284% The format of the XDrawImage method is:
2285%
cristy6710d842011-10-20 23:23:00 +00002286% MagickBooleanType XDrawImage(Display *display,const XPixelInfo *pixel,
2287% XDrawInfo *draw_info,Image *image,ExceptionInfo *exception)
cristy3ed852e2009-09-05 21:47:34 +00002288%
2289% A description of each parameter follows:
2290%
2291% o display: Specifies a connection to an X server; returned from
2292% XOpenDisplay.
2293%
2294% o pixel: Specifies a pointer to a XPixelInfo structure.
2295%
2296% o draw_info: Specifies a pointer to a XDrawInfo structure.
2297%
2298% o image: the image.
2299%
cristy6710d842011-10-20 23:23:00 +00002300% o exception: return any errors or warnings in this structure.
2301%
cristy3ed852e2009-09-05 21:47:34 +00002302*/
cristybcbda3f2011-09-03 13:01:22 +00002303MagickPrivate MagickBooleanType XDrawImage(Display *display,
cristy6710d842011-10-20 23:23:00 +00002304 const XPixelInfo *pixel,XDrawInfo *draw_info,Image *image,
2305 ExceptionInfo *exception)
cristy3ed852e2009-09-05 21:47:34 +00002306{
cristyc57f6942010-11-12 01:47:39 +00002307 CacheView
2308 *draw_view;
2309
cristy3ed852e2009-09-05 21:47:34 +00002310 GC
2311 draw_context;
2312
2313 Image
2314 *draw_image;
2315
2316 int
2317 x,
2318 y;
2319
2320 MagickBooleanType
2321 matte;
2322
2323 Pixmap
2324 draw_pixmap;
2325
2326 unsigned int
2327 depth,
2328 height,
2329 width;
2330
2331 Window
2332 root_window;
2333
2334 XGCValues
2335 context_values;
2336
2337 XImage
2338 *draw_ximage;
2339
2340 /*
2341 Initialize drawd image.
2342 */
2343 assert(display != (Display *) NULL);
2344 assert(pixel != (XPixelInfo *) NULL);
2345 assert(draw_info != (XDrawInfo *) NULL);
2346 assert(image != (Image *) NULL);
2347 if (image->debug != MagickFalse)
2348 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
2349 /*
2350 Initialize drawd pixmap.
2351 */
2352 root_window=XRootWindow(display,XDefaultScreen(display));
2353 depth=(unsigned int) XDefaultDepth(display,XDefaultScreen(display));
2354 draw_pixmap=XCreatePixmap(display,root_window,draw_info->width,
2355 draw_info->height,depth);
2356 if (draw_pixmap == (Pixmap) NULL)
2357 return(MagickFalse);
2358 /*
2359 Initialize graphics info.
2360 */
cristybb503372010-05-27 20:51:26 +00002361 context_values.background=(size_t) (~0);
cristy3ed852e2009-09-05 21:47:34 +00002362 context_values.foreground=0;
2363 context_values.line_width=(int) draw_info->line_width;
cristybb503372010-05-27 20:51:26 +00002364 draw_context=XCreateGC(display,root_window,(size_t)
cristy3ed852e2009-09-05 21:47:34 +00002365 (GCBackground | GCForeground | GCLineWidth),&context_values);
2366 if (draw_context == (GC) NULL)
2367 return(MagickFalse);
2368 /*
2369 Clear pixmap.
2370 */
2371 (void) XFillRectangle(display,draw_pixmap,draw_context,0,0,draw_info->width,
2372 draw_info->height);
2373 /*
2374 Draw line to pixmap.
2375 */
2376 (void) XSetBackground(display,draw_context,0);
cristybb503372010-05-27 20:51:26 +00002377 (void) XSetForeground(display,draw_context,(size_t) (~0));
cristydd05beb2010-11-21 21:23:39 +00002378 if (draw_info->stipple != (Pixmap) NULL)
2379 {
2380 (void) XSetFillStyle(display,draw_context,FillOpaqueStippled);
2381 (void) XSetStipple(display,draw_context,draw_info->stipple);
2382 }
cristy3ed852e2009-09-05 21:47:34 +00002383 switch (draw_info->element)
2384 {
2385 case PointElement:
2386 default:
2387 {
2388 (void) XDrawLines(display,draw_pixmap,draw_context,
2389 draw_info->coordinate_info,(int) draw_info->number_coordinates,
2390 CoordModeOrigin);
2391 break;
2392 }
2393 case LineElement:
2394 {
2395 (void) XDrawLine(display,draw_pixmap,draw_context,draw_info->line_info.x1,
2396 draw_info->line_info.y1,draw_info->line_info.x2,
2397 draw_info->line_info.y2);
2398 break;
2399 }
2400 case RectangleElement:
2401 {
2402 (void) XDrawRectangle(display,draw_pixmap,draw_context,
2403 (int) draw_info->rectangle_info.x,(int) draw_info->rectangle_info.y,
2404 (unsigned int) draw_info->rectangle_info.width,
2405 (unsigned int) draw_info->rectangle_info.height);
2406 break;
2407 }
2408 case FillRectangleElement:
2409 {
2410 (void) XFillRectangle(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);
2414 break;
2415 }
2416 case CircleElement:
2417 case EllipseElement:
2418 {
2419 (void) XDrawArc(display,draw_pixmap,draw_context,
2420 (int) draw_info->rectangle_info.x,(int) draw_info->rectangle_info.y,
2421 (unsigned int) draw_info->rectangle_info.width,
2422 (unsigned int) draw_info->rectangle_info.height,0,360*64);
2423 break;
2424 }
2425 case FillCircleElement:
2426 case FillEllipseElement:
2427 {
2428 (void) XFillArc(display,draw_pixmap,draw_context,
2429 (int) draw_info->rectangle_info.x,(int) draw_info->rectangle_info.y,
2430 (unsigned int) draw_info->rectangle_info.width,
2431 (unsigned int) draw_info->rectangle_info.height,0,360*64);
2432 break;
2433 }
2434 case PolygonElement:
2435 {
2436 XPoint
2437 *coordinate_info;
2438
2439 coordinate_info=draw_info->coordinate_info;
2440 (void) XDrawLines(display,draw_pixmap,draw_context,coordinate_info,
2441 (int) draw_info->number_coordinates,CoordModeOrigin);
2442 (void) XDrawLine(display,draw_pixmap,draw_context,
2443 coordinate_info[draw_info->number_coordinates-1].x,
2444 coordinate_info[draw_info->number_coordinates-1].y,
2445 coordinate_info[0].x,coordinate_info[0].y);
2446 break;
2447 }
2448 case FillPolygonElement:
2449 {
2450 (void) XFillPolygon(display,draw_pixmap,draw_context,
2451 draw_info->coordinate_info,(int) draw_info->number_coordinates,Complex,
2452 CoordModeOrigin);
2453 break;
2454 }
2455 }
2456 (void) XFreeGC(display,draw_context);
2457 /*
2458 Initialize X image.
2459 */
2460 draw_ximage=XGetImage(display,draw_pixmap,0,0,draw_info->width,
2461 draw_info->height,AllPlanes,ZPixmap);
2462 if (draw_ximage == (XImage *) NULL)
2463 return(MagickFalse);
2464 (void) XFreePixmap(display,draw_pixmap);
2465 /*
2466 Initialize draw image.
2467 */
cristy6710d842011-10-20 23:23:00 +00002468 draw_image=AcquireImage((ImageInfo *) NULL,exception);
cristy3ed852e2009-09-05 21:47:34 +00002469 if (draw_image == (Image *) NULL)
2470 return(MagickFalse);
2471 draw_image->columns=draw_info->width;
2472 draw_image->rows=draw_info->height;
2473 /*
2474 Transfer drawn X image to image.
2475 */
2476 width=(unsigned int) image->columns;
2477 height=(unsigned int) image->rows;
2478 x=0;
2479 y=0;
2480 (void) XParseGeometry(draw_info->geometry,&x,&y,&width,&height);
cristyf05d4942012-03-17 16:26:09 +00002481 (void) GetOneVirtualPixelInfo(image,UndefinedVirtualPixelMethod,(ssize_t) x,
2482 (ssize_t) y,&draw_image->background_color,exception);
cristy6710d842011-10-20 23:23:00 +00002483 if (SetImageStorageClass(draw_image,DirectClass,exception) == MagickFalse)
cristy3ed852e2009-09-05 21:47:34 +00002484 return(MagickFalse);
2485 draw_image->matte=MagickTrue;
cristyc57f6942010-11-12 01:47:39 +00002486 draw_view=AcquireCacheView(draw_image);
cristy3ed852e2009-09-05 21:47:34 +00002487 for (y=0; y < (int) draw_image->rows; y++)
2488 {
cristyc57f6942010-11-12 01:47:39 +00002489 register int
cristy3ed852e2009-09-05 21:47:34 +00002490 x;
2491
cristy4c08aed2011-07-01 19:47:50 +00002492 register Quantum
cristyc47d1f82009-11-26 01:44:43 +00002493 *restrict q;
cristy3ed852e2009-09-05 21:47:34 +00002494
cristyc57f6942010-11-12 01:47:39 +00002495 q=QueueCacheViewAuthenticPixels(draw_view,0,(ssize_t) y,draw_image->columns,
2496 1,exception);
cristyacd2ed22011-08-30 01:44:23 +00002497 if (q == (Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00002498 break;
cristyc57f6942010-11-12 01:47:39 +00002499 for (x=0; x < (int) draw_image->columns; x++)
cristy3ed852e2009-09-05 21:47:34 +00002500 {
2501 if (XGetPixel(draw_ximage,x,y) == 0)
2502 {
2503 /*
2504 Set this pixel to the background color.
2505 */
cristy803640d2011-11-17 02:11:32 +00002506 SetPixelInfoPixel(draw_image,&draw_image->background_color,q);
cristy76761582011-09-18 02:14:00 +00002507 SetPixelAlpha(draw_image,(Quantum) (draw_info->stencil ==
cristy4c08aed2011-07-01 19:47:50 +00002508 OpaqueStencil ? TransparentAlpha : OpaqueAlpha),q);
cristy3ed852e2009-09-05 21:47:34 +00002509 }
2510 else
2511 {
2512 /*
2513 Set this pixel to the pen color.
2514 */
cristy4c08aed2011-07-01 19:47:50 +00002515 SetPixelRed(draw_image,ScaleShortToQuantum(
2516 pixel->pen_color.red),q);
2517 SetPixelGreen(draw_image,ScaleShortToQuantum(
2518 pixel->pen_color.green),q);
2519 SetPixelBlue(draw_image,ScaleShortToQuantum(
2520 pixel->pen_color.blue),q);
2521 SetPixelAlpha(draw_image,(Quantum) (draw_info->stencil ==
2522 OpaqueStencil ? OpaqueAlpha : TransparentAlpha),q);
cristy3ed852e2009-09-05 21:47:34 +00002523 }
cristyed231572011-07-14 02:18:59 +00002524 q+=GetPixelChannels(draw_image);
cristy3ed852e2009-09-05 21:47:34 +00002525 }
cristyc57f6942010-11-12 01:47:39 +00002526 if (SyncCacheViewAuthenticPixels(draw_view,exception) == MagickFalse)
cristy3ed852e2009-09-05 21:47:34 +00002527 break;
2528 }
cristyc57f6942010-11-12 01:47:39 +00002529 draw_view=DestroyCacheView(draw_view);
cristy3ed852e2009-09-05 21:47:34 +00002530 XDestroyImage(draw_ximage);
2531 /*
2532 Determine draw geometry.
2533 */
2534 (void) XParseGeometry(draw_info->geometry,&x,&y,&width,&height);
2535 if ((width != (unsigned int) draw_image->columns) ||
2536 (height != (unsigned int) draw_image->rows))
2537 {
2538 char
2539 image_geometry[MaxTextExtent];
2540
2541 /*
2542 Scale image.
2543 */
cristyb51dff52011-05-19 16:55:47 +00002544 (void) FormatLocaleString(image_geometry,MaxTextExtent,"%ux%u",
cristy3ed852e2009-09-05 21:47:34 +00002545 width,height);
cristye941a752011-10-15 01:52:48 +00002546 (void) TransformImage(&draw_image,(char *) NULL,image_geometry,
2547 exception);
cristy3ed852e2009-09-05 21:47:34 +00002548 }
2549 if (draw_info->degrees != 0.0)
2550 {
2551 Image
2552 *rotate_image;
2553
2554 int
2555 rotations;
2556
2557 MagickRealType
2558 normalized_degrees;
2559
2560 /*
2561 Rotate image.
2562 */
cristy6710d842011-10-20 23:23:00 +00002563 rotate_image=RotateImage(draw_image,draw_info->degrees,exception);
cristy3ed852e2009-09-05 21:47:34 +00002564 if (rotate_image == (Image *) NULL)
2565 return(MagickFalse);
2566 draw_image=DestroyImage(draw_image);
2567 draw_image=rotate_image;
2568 /*
2569 Annotation is relative to the degree of rotation.
2570 */
2571 normalized_degrees=draw_info->degrees;
2572 while (normalized_degrees < -45.0)
2573 normalized_degrees+=360.0;
2574 for (rotations=0; normalized_degrees > 45.0; rotations++)
2575 normalized_degrees-=90.0;
2576 switch (rotations % 4)
2577 {
2578 default:
2579 case 0:
2580 break;
2581 case 1:
2582 {
2583 /*
2584 Rotate 90 degrees.
2585 */
2586 x=x-(int) draw_image->columns/2;
2587 y=y+(int) draw_image->columns/2;
2588 break;
2589 }
2590 case 2:
2591 {
2592 /*
2593 Rotate 180 degrees.
2594 */
2595 x=x-(int) draw_image->columns;
2596 break;
2597 }
2598 case 3:
2599 {
2600 /*
2601 Rotate 270 degrees.
2602 */
2603 x=x-(int) draw_image->columns/2;
2604 y=y-(int) (draw_image->rows-(draw_image->columns/2));
2605 break;
2606 }
2607 }
2608 }
2609 /*
2610 Composite text onto the image.
2611 */
cristyc57f6942010-11-12 01:47:39 +00002612 draw_view=AcquireCacheView(draw_image);
cristy3ed852e2009-09-05 21:47:34 +00002613 for (y=0; y < (int) draw_image->rows; y++)
2614 {
cristyc57f6942010-11-12 01:47:39 +00002615 register int
cristy3ed852e2009-09-05 21:47:34 +00002616 x;
2617
cristy4c08aed2011-07-01 19:47:50 +00002618 register Quantum
cristyc47d1f82009-11-26 01:44:43 +00002619 *restrict q;
cristy3ed852e2009-09-05 21:47:34 +00002620
cristyc57f6942010-11-12 01:47:39 +00002621 q=GetCacheViewAuthenticPixels(draw_view,0,(ssize_t) y,draw_image->columns,1,
2622 exception);
cristyacd2ed22011-08-30 01:44:23 +00002623 if (q == (Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00002624 break;
cristyc57f6942010-11-12 01:47:39 +00002625 for (x=0; x < (int) draw_image->columns; x++)
cristy3ed852e2009-09-05 21:47:34 +00002626 {
cristy4c08aed2011-07-01 19:47:50 +00002627 if (GetPixelAlpha(image,q) != TransparentAlpha)
2628 SetPixelAlpha(draw_image,OpaqueAlpha,q);
cristyed231572011-07-14 02:18:59 +00002629 q+=GetPixelChannels(draw_image);
cristy3ed852e2009-09-05 21:47:34 +00002630 }
cristyc57f6942010-11-12 01:47:39 +00002631 if (SyncCacheViewAuthenticPixels(draw_view,exception) == MagickFalse)
cristy3ed852e2009-09-05 21:47:34 +00002632 break;
2633 }
cristyc57f6942010-11-12 01:47:39 +00002634 draw_view=DestroyCacheView(draw_view);
cristy3ed852e2009-09-05 21:47:34 +00002635 (void) XParseGeometry(draw_info->geometry,&x,&y,&width,&height);
2636 if (draw_info->stencil == TransparentStencil)
cristye4a40472011-12-22 02:56:19 +00002637 (void) CompositeImage(image,CopyAlphaCompositeOp,draw_image,(ssize_t) x,
cristye941a752011-10-15 01:52:48 +00002638 (ssize_t) y,exception);
cristy3ed852e2009-09-05 21:47:34 +00002639 else
2640 {
2641 matte=image->matte;
cristyc57f6942010-11-12 01:47:39 +00002642 (void) CompositeImage(image,OverCompositeOp,draw_image,(ssize_t) x,
cristye941a752011-10-15 01:52:48 +00002643 (ssize_t) y,exception);
cristy3ed852e2009-09-05 21:47:34 +00002644 image->matte=matte;
2645 }
2646 draw_image=DestroyImage(draw_image);
2647 return(MagickTrue);
2648}
2649
2650/*
2651%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2652% %
2653% %
2654% %
2655% X E r r o r %
2656% %
2657% %
2658% %
2659%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2660%
2661% XError() ignores BadWindow errors for XQueryTree and XGetWindowAttributes,
2662% and ignores BadDrawable errors for XGetGeometry, and ignores BadValue errors
cristybcbda3f2011-09-03 13:01:22 +00002663% for XQueryColor. It returns MagickFalse in those cases. Otherwise it
2664% returns True.
cristy3ed852e2009-09-05 21:47:34 +00002665%
2666% The format of the XError function is:
2667%
cristybcbda3f2011-09-03 13:01:22 +00002668% int XError(display,error)
cristy3ed852e2009-09-05 21:47:34 +00002669%
2670% A description of each parameter follows:
2671%
2672% o display: Specifies a pointer to the Display structure; returned from
2673% XOpenDisplay.
2674%
2675% o error: Specifies the error event.
2676%
2677*/
2678
2679#if defined(__cplusplus) || defined(c_plusplus)
2680extern "C" {
2681#endif
2682
2683MagickExport int XError(Display *display,XErrorEvent *error)
2684{
2685 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
2686 assert(display != (Display *) NULL);
2687 assert(error != (XErrorEvent *) NULL);
2688 xerror_alert=MagickTrue;
2689 switch (error->request_code)
2690 {
2691 case X_GetGeometry:
2692 {
2693 if ((int) error->error_code == BadDrawable)
2694 return(MagickFalse);
2695 break;
2696 }
2697 case X_GetWindowAttributes:
2698 case X_QueryTree:
2699 {
2700 if ((int) error->error_code == BadWindow)
2701 return(MagickFalse);
2702 break;
2703 }
2704 case X_QueryColors:
2705 {
2706 if ((int) error->error_code == BadValue)
2707 return(MagickFalse);
2708 break;
2709 }
2710 }
2711 return(MagickTrue);
2712}
2713
2714#if defined(__cplusplus) || defined(c_plusplus)
2715}
2716#endif
2717
2718/*
2719%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2720% %
2721% %
2722% %
2723% X F r e e R e s o u r c e s %
2724% %
2725% %
2726% %
2727%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2728%
2729% XFreeResources() frees X11 resources.
2730%
2731% The format of the XFreeResources method is:
2732%
2733% void XFreeResources(Display *display,XVisualInfo *visual_info,
2734% XStandardColormap *map_info,XPixelInfo *pixel,XFontStruct *font_info,
2735% XResourceInfo *resource_info,XWindowInfo *window_info)
2736% resource_info,window_info)
2737%
2738% A description of each parameter follows:
2739%
2740% o display: Specifies a connection to an X server; returned from
2741% XOpenDisplay.
2742%
2743% o visual_info: Specifies a pointer to a X11 XVisualInfo structure;
2744% returned from XGetVisualInfo.
2745%
2746% o map_info: If map_type is specified, this structure is initialized
2747% with info from the Standard Colormap.
2748%
2749% o pixel: Specifies a pointer to a XPixelInfo structure.
2750%
2751% o font_info: Specifies a pointer to a XFontStruct structure.
2752%
2753% o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
2754%
2755% o window_info: Specifies a pointer to a X11 XWindowInfo structure.
2756%
2757*/
cristybcbda3f2011-09-03 13:01:22 +00002758MagickPrivate void XFreeResources(Display *display,XVisualInfo *visual_info,
cristy3ed852e2009-09-05 21:47:34 +00002759 XStandardColormap *map_info,XPixelInfo *pixel,XFontStruct *font_info,
2760 XResourceInfo *resource_info,XWindowInfo *window_info)
2761{
2762 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
2763 assert(display != (Display *) NULL);
2764 assert(resource_info != (XResourceInfo *) NULL);
2765 if (window_info != (XWindowInfo *) NULL)
2766 {
2767 /*
2768 Free X image.
2769 */
2770 if (window_info->ximage != (XImage *) NULL)
2771 XDestroyImage(window_info->ximage);
2772 if (window_info->id != (Window) NULL)
2773 {
2774 /*
2775 Free destroy window and free cursors.
2776 */
2777 if (window_info->id != XRootWindow(display,visual_info->screen))
2778 (void) XDestroyWindow(display,window_info->id);
2779 if (window_info->annotate_context != (GC) NULL)
2780 (void) XFreeGC(display,window_info->annotate_context);
2781 if (window_info->highlight_context != (GC) NULL)
2782 (void) XFreeGC(display,window_info->highlight_context);
2783 if (window_info->widget_context != (GC) NULL)
2784 (void) XFreeGC(display,window_info->widget_context);
2785 if (window_info->cursor != (Cursor) NULL)
2786 (void) XFreeCursor(display,window_info->cursor);
2787 window_info->cursor=(Cursor) NULL;
2788 if (window_info->busy_cursor != (Cursor) NULL)
2789 (void) XFreeCursor(display,window_info->busy_cursor);
2790 window_info->busy_cursor=(Cursor) NULL;
2791 }
2792 }
2793 /*
2794 Free font.
2795 */
2796 if (font_info != (XFontStruct *) NULL)
cristyaafc1922011-03-04 16:59:40 +00002797 {
2798 (void) XFreeFont(display,font_info);
2799 font_info=(XFontStruct *) NULL;
2800 }
cristy3ed852e2009-09-05 21:47:34 +00002801 if (map_info != (XStandardColormap *) NULL)
2802 {
2803 /*
2804 Free X Standard Colormap.
2805 */
2806 if (resource_info->map_type == (char *) NULL)
2807 (void) XFreeStandardColormap(display,visual_info,map_info,pixel);
2808 (void) XFree((void *) map_info);
2809 }
2810 /*
2811 Free X visual info.
2812 */
2813 if (visual_info != (XVisualInfo *) NULL)
2814 (void) XFree((void *) visual_info);
2815 if (resource_info->close_server != MagickFalse)
2816 (void) XCloseDisplay(display);
2817}
2818
2819/*
2820%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2821% %
2822% %
2823% %
2824% X F r e e S t a n d a r d C o l o r m a p %
2825% %
2826% %
2827% %
2828%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2829%
2830% XFreeStandardColormap() frees an X11 colormap.
2831%
2832% The format of the XFreeStandardColormap method is:
2833%
2834% void XFreeStandardColormap(Display *display,
2835% const XVisualInfo *visual_info,XStandardColormap *map_info,
2836% XPixelInfo *pixel)
2837%
2838% A description of each parameter follows:
2839%
2840% o display: Specifies a connection to an X server; returned from
2841% XOpenDisplay.
2842%
2843% o visual_info: Specifies a pointer to a X11 XVisualInfo structure;
2844% returned from XGetVisualInfo.
2845%
2846% o map_info: If map_type is specified, this structure is initialized
2847% with info from the Standard Colormap.
2848%
2849% o pixel: Specifies a pointer to a XPixelInfo structure.
2850%
2851*/
cristybcbda3f2011-09-03 13:01:22 +00002852MagickPrivate void XFreeStandardColormap(Display *display,
cristy3ed852e2009-09-05 21:47:34 +00002853 const XVisualInfo *visual_info,XStandardColormap *map_info,XPixelInfo *pixel)
2854{
2855 /*
2856 Free colormap.
2857 */
2858 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
2859 assert(display != (Display *) NULL);
2860 assert(visual_info != (XVisualInfo *) NULL);
2861 assert(map_info != (XStandardColormap *) NULL);
2862 (void) XFlush(display);
2863 if (map_info->colormap != (Colormap) NULL)
2864 {
2865 if (map_info->colormap != XDefaultColormap(display,visual_info->screen))
2866 (void) XFreeColormap(display,map_info->colormap);
2867 else
2868 if (pixel != (XPixelInfo *) NULL)
2869 if ((visual_info->klass != TrueColor) &&
2870 (visual_info->klass != DirectColor))
2871 (void) XFreeColors(display,map_info->colormap,pixel->pixels,
2872 (int) pixel->colors,0);
2873 }
2874 map_info->colormap=(Colormap) NULL;
2875 if (pixel != (XPixelInfo *) NULL)
2876 {
cristyf2faecf2010-05-28 19:19:36 +00002877 if (pixel->pixels != (unsigned long *) NULL)
2878 pixel->pixels=(unsigned long *) RelinquishMagickMemory(pixel->pixels);
2879 pixel->pixels=(unsigned long *) NULL;
cristy3ed852e2009-09-05 21:47:34 +00002880 }
2881}
2882
2883/*
2884%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2885% %
2886% %
2887% %
2888% X G e t A n n o t a t e I n f o %
2889% %
2890% %
2891% %
2892%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2893%
2894% XGetAnnotateInfo() initializes the AnnotateInfo structure.
2895%
2896% The format of the XGetAnnotateInfo method is:
2897%
2898% void XGetAnnotateInfo(XAnnotateInfo *annotate_info)
2899%
2900% A description of each parameter follows:
2901%
2902% o annotate_info: Specifies a pointer to a XAnnotateInfo structure.
2903%
2904*/
cristybcbda3f2011-09-03 13:01:22 +00002905MagickPrivate void XGetAnnotateInfo(XAnnotateInfo *annotate_info)
cristy3ed852e2009-09-05 21:47:34 +00002906{
2907 /*
2908 Initialize annotate structure.
2909 */
2910 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
2911 assert(annotate_info != (XAnnotateInfo *) NULL);
2912 annotate_info->x=0;
2913 annotate_info->y=0;
2914 annotate_info->width=0;
2915 annotate_info->height=0;
2916 annotate_info->stencil=ForegroundStencil;
2917 annotate_info->degrees=0.0;
2918 annotate_info->font_info=(XFontStruct *) NULL;
2919 annotate_info->text=(char *) NULL;
2920 *annotate_info->geometry='\0';
2921 annotate_info->previous=(XAnnotateInfo *) NULL;
2922 annotate_info->next=(XAnnotateInfo *) NULL;
2923 (void) XSupportsLocale();
2924 (void) XSetLocaleModifiers("");
2925}
2926
2927/*
2928%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2929% %
2930% %
2931% %
2932% X G e t M a p I n f o %
2933% %
2934% %
2935% %
2936%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2937%
2938% XGetMapInfo() initializes the XStandardColormap structure.
2939%
2940% The format of the XStandardColormap method is:
2941%
2942% void XGetMapInfo(const XVisualInfo *visual_info,const Colormap colormap,
2943% XStandardColormap *map_info)
2944%
2945% A description of each parameter follows:
2946%
2947% o colormap: Specifies the ID of the X server colormap.
2948%
2949% o visual_info: Specifies a pointer to a X11 XVisualInfo structure;
2950% returned from XGetVisualInfo.
2951%
2952% o map_info: Specifies a pointer to a X11 XStandardColormap structure.
2953%
2954*/
cristybcbda3f2011-09-03 13:01:22 +00002955MagickPrivate void XGetMapInfo(const XVisualInfo *visual_info,
cristy3ed852e2009-09-05 21:47:34 +00002956 const Colormap colormap,XStandardColormap *map_info)
2957{
2958 /*
2959 Initialize map info.
2960 */
2961 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
2962 assert(visual_info != (XVisualInfo *) NULL);
2963 assert(map_info != (XStandardColormap *) NULL);
2964 map_info->colormap=colormap;
2965 map_info->red_max=visual_info->red_mask;
cristybb503372010-05-27 20:51:26 +00002966 map_info->red_mult=(size_t) (map_info->red_max != 0 ? 1 : 0);
cristy3ed852e2009-09-05 21:47:34 +00002967 if (map_info->red_max != 0)
2968 while ((map_info->red_max & 0x01) == 0)
2969 {
2970 map_info->red_max>>=1;
2971 map_info->red_mult<<=1;
2972 }
2973 map_info->green_max=visual_info->green_mask;
cristybb503372010-05-27 20:51:26 +00002974 map_info->green_mult=(size_t) (map_info->green_max != 0 ? 1 : 0);
cristy3ed852e2009-09-05 21:47:34 +00002975 if (map_info->green_max != 0)
2976 while ((map_info->green_max & 0x01) == 0)
2977 {
2978 map_info->green_max>>=1;
2979 map_info->green_mult<<=1;
2980 }
2981 map_info->blue_max=visual_info->blue_mask;
cristybb503372010-05-27 20:51:26 +00002982 map_info->blue_mult=(size_t) (map_info->blue_max != 0 ? 1 : 0);
cristy3ed852e2009-09-05 21:47:34 +00002983 if (map_info->blue_max != 0)
2984 while ((map_info->blue_max & 0x01) == 0)
2985 {
2986 map_info->blue_max>>=1;
2987 map_info->blue_mult<<=1;
2988 }
2989 map_info->base_pixel=0;
2990}
2991
2992/*
2993%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2994% %
2995% %
2996% %
2997% X G e t P i x e l I n f o %
2998% %
2999% %
3000% %
3001%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3002%
cristy101ab702011-10-13 13:06:32 +00003003% XGetPixelInfo() initializes the PixelInfo structure.
cristy3ed852e2009-09-05 21:47:34 +00003004%
cristy4c08aed2011-07-01 19:47:50 +00003005% The format of the XGetPixelInfo method is:
cristy3ed852e2009-09-05 21:47:34 +00003006%
cristy4c08aed2011-07-01 19:47:50 +00003007% void XGetPixelInfo(Display *display,const XVisualInfo *visual_info,
cristy3ed852e2009-09-05 21:47:34 +00003008% const XStandardColormap *map_info,const XResourceInfo *resource_info,
3009% Image *image,XPixelInfo *pixel)
3010% pixel)
3011%
3012% A description of each parameter follows:
3013%
3014% o display: Specifies a connection to an X server; returned from
3015% XOpenDisplay.
3016%
3017% o visual_info: Specifies a pointer to a X11 XVisualInfo structure;
3018% returned from XGetVisualInfo.
3019%
3020% o map_info: If map_type is specified, this structure is initialized
3021% with info from the Standard Colormap.
3022%
3023% o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
3024%
3025% o image: the image.
3026%
3027% o pixel: Specifies a pointer to a XPixelInfo structure.
3028%
3029*/
cristybcbda3f2011-09-03 13:01:22 +00003030MagickPrivate void XGetPixelInfo(Display *display,
cristy3ed852e2009-09-05 21:47:34 +00003031 const XVisualInfo *visual_info,const XStandardColormap *map_info,
3032 const XResourceInfo *resource_info,Image *image,XPixelInfo *pixel)
3033{
3034 static const char
3035 *PenColors[MaxNumberPens]=
3036 {
3037 "#000000000000", /* black */
3038 "#00000000ffff", /* blue */
3039 "#0000ffffffff", /* cyan */
3040 "#0000ffff0000", /* green */
3041 "#bdbdbdbdbdbd", /* gray */
3042 "#ffff00000000", /* red */
3043 "#ffff0000ffff", /* magenta */
3044 "#ffffffff0000", /* yellow */
3045 "#ffffffffffff", /* white */
3046 "#bdbdbdbdbdbd", /* gray */
3047 "#bdbdbdbdbdbd" /* gray */
3048 };
3049
3050 Colormap
3051 colormap;
3052
cristybb503372010-05-27 20:51:26 +00003053 register ssize_t
cristy3ed852e2009-09-05 21:47:34 +00003054 i;
3055
3056 Status
3057 status;
3058
3059 unsigned int
3060 packets;
3061
3062 /*
3063 Initialize pixel info.
3064 */
3065 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
3066 assert(display != (Display *) NULL);
3067 assert(visual_info != (XVisualInfo *) NULL);
3068 assert(map_info != (XStandardColormap *) NULL);
3069 assert(resource_info != (XResourceInfo *) NULL);
3070 assert(pixel != (XPixelInfo *) NULL);
3071 pixel->colors=0;
3072 if (image != (Image *) NULL)
3073 if (image->storage_class == PseudoClass)
cristyc57f6942010-11-12 01:47:39 +00003074 pixel->colors=(ssize_t) image->colors;
cristy3ed852e2009-09-05 21:47:34 +00003075 packets=(unsigned int)
3076 MagickMax((int) pixel->colors,visual_info->colormap_size)+MaxNumberPens;
cristyf2faecf2010-05-28 19:19:36 +00003077 if (pixel->pixels != (unsigned long *) NULL)
3078 pixel->pixels=(unsigned long *) RelinquishMagickMemory(pixel->pixels);
3079 pixel->pixels=(unsigned long *) AcquireQuantumMemory(packets,
cristy3ed852e2009-09-05 21:47:34 +00003080 sizeof(pixel->pixels));
cristyf2faecf2010-05-28 19:19:36 +00003081 if (pixel->pixels == (unsigned long *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00003082 ThrowXWindowFatalException(ResourceLimitFatalError,"UnableToGetPixelInfo",
3083 image->filename);
3084 /*
3085 Set foreground color.
3086 */
3087 colormap=map_info->colormap;
3088 (void) XParseColor(display,colormap,(char *) ForegroundColor,
3089 &pixel->foreground_color);
3090 status=XParseColor(display,colormap,resource_info->foreground_color,
3091 &pixel->foreground_color);
3092 if (status == False)
3093 ThrowXWindowFatalException(XServerError,"ColorIsNotKnownToServer",
3094 resource_info->foreground_color);
3095 pixel->foreground_color.pixel=
3096 XStandardPixel(map_info,&pixel->foreground_color);
3097 pixel->foreground_color.flags=(char) (DoRed | DoGreen | DoBlue);
3098 /*
3099 Set background color.
3100 */
3101 (void) XParseColor(display,colormap,"#d6d6d6d6d6d6",&pixel->background_color);
3102 status=XParseColor(display,colormap,resource_info->background_color,
3103 &pixel->background_color);
3104 if (status == False)
3105 ThrowXWindowFatalException(XServerError,"ColorIsNotKnownToServer",
3106 resource_info->background_color);
3107 pixel->background_color.pixel=
3108 XStandardPixel(map_info,&pixel->background_color);
3109 pixel->background_color.flags=(char) (DoRed | DoGreen | DoBlue);
3110 /*
3111 Set border color.
3112 */
3113 (void) XParseColor(display,colormap,(char *) BorderColor,
3114 &pixel->border_color);
3115 status=XParseColor(display,colormap,resource_info->border_color,
3116 &pixel->border_color);
3117 if (status == False)
3118 ThrowXWindowFatalException(XServerError,"ColorIsNotKnownToServer",
3119 resource_info->border_color);
3120 pixel->border_color.pixel=XStandardPixel(map_info,&pixel->border_color);
3121 pixel->border_color.flags=(char) (DoRed | DoGreen | DoBlue);
3122 /*
3123 Set matte color.
3124 */
3125 pixel->matte_color=pixel->background_color;
3126 if (resource_info->matte_color != (char *) NULL)
3127 {
3128 /*
3129 Matte color is specified as a X resource or command line argument.
3130 */
3131 status=XParseColor(display,colormap,resource_info->matte_color,
3132 &pixel->matte_color);
3133 if (status == False)
3134 ThrowXWindowFatalException(XServerError,"ColorIsNotKnownToServer",
3135 resource_info->matte_color);
3136 pixel->matte_color.pixel=XStandardPixel(map_info,&pixel->matte_color);
3137 pixel->matte_color.flags=(char) (DoRed | DoGreen | DoBlue);
3138 }
3139 /*
3140 Set highlight color.
3141 */
3142 pixel->highlight_color.red=(unsigned short) ((
3143 pixel->matte_color.red*ScaleQuantumToShort(HighlightModulate))/65535L+
3144 (ScaleQuantumToShort((Quantum) (QuantumRange-HighlightModulate))));
3145 pixel->highlight_color.green=(unsigned short) ((
3146 pixel->matte_color.green*ScaleQuantumToShort(HighlightModulate))/65535L+
3147 (ScaleQuantumToShort((Quantum) (QuantumRange-HighlightModulate))));
3148 pixel->highlight_color.blue=(unsigned short) ((
3149 pixel->matte_color.blue*ScaleQuantumToShort(HighlightModulate))/65535L+
3150 (ScaleQuantumToShort((Quantum) (QuantumRange-HighlightModulate))));
3151 pixel->highlight_color.pixel=
3152 XStandardPixel(map_info,&pixel->highlight_color);
3153 pixel->highlight_color.flags=(char) (DoRed | DoGreen | DoBlue);
3154 /*
3155 Set shadow color.
3156 */
3157 pixel->shadow_color.red=(unsigned short) (((MagickRealType)
3158 pixel->matte_color.red*ScaleQuantumToShort(ShadowModulate))/65535L);
3159 pixel->shadow_color.green=(unsigned short) (((MagickRealType)
3160 pixel->matte_color.green*ScaleQuantumToShort(ShadowModulate))/65535L);
3161 pixel->shadow_color.blue=(unsigned short) (((MagickRealType)
3162 pixel->matte_color.blue*ScaleQuantumToShort(ShadowModulate))/65535L);
3163 pixel->shadow_color.pixel=XStandardPixel(map_info,&pixel->shadow_color);
3164 pixel->shadow_color.flags=(char) (DoRed | DoGreen | DoBlue);
3165 /*
3166 Set depth color.
3167 */
3168 pixel->depth_color.red=(unsigned short) (((MagickRealType)
3169 pixel->matte_color.red*ScaleQuantumToShort(DepthModulate))/65535L);
3170 pixel->depth_color.green=(unsigned short) (((MagickRealType)
3171 pixel->matte_color.green*ScaleQuantumToShort(DepthModulate))/65535L);
3172 pixel->depth_color.blue=(unsigned short) (((MagickRealType)
3173 pixel->matte_color.blue*ScaleQuantumToShort(DepthModulate))/65535L);
3174 pixel->depth_color.pixel=XStandardPixel(map_info,&pixel->depth_color);
3175 pixel->depth_color.flags=(char) (DoRed | DoGreen | DoBlue);
3176 /*
3177 Set trough color.
3178 */
3179 pixel->trough_color.red=(unsigned short) (((MagickRealType)
3180 pixel->matte_color.red*ScaleQuantumToShort(TroughModulate))/65535L);
3181 pixel->trough_color.green=(unsigned short) (((MagickRealType)
3182 pixel->matte_color.green*ScaleQuantumToShort(TroughModulate))/65535L);
3183 pixel->trough_color.blue=(unsigned short) (((MagickRealType)
3184 pixel->matte_color.blue*ScaleQuantumToShort(TroughModulate))/65535L);
3185 pixel->trough_color.pixel=XStandardPixel(map_info,&pixel->trough_color);
3186 pixel->trough_color.flags=(char) (DoRed | DoGreen | DoBlue);
3187 /*
3188 Set pen color.
3189 */
3190 for (i=0; i < MaxNumberPens; i++)
3191 {
3192 (void) XParseColor(display,colormap,(char *) PenColors[i],
3193 &pixel->pen_colors[i]);
3194 status=XParseColor(display,colormap,resource_info->pen_colors[i],
3195 &pixel->pen_colors[i]);
3196 if (status == False)
3197 ThrowXWindowFatalException(XServerError,"ColorIsNotKnownToServer",
3198 resource_info->pen_colors[i]);
3199 pixel->pen_colors[i].pixel=XStandardPixel(map_info,&pixel->pen_colors[i]);
3200 pixel->pen_colors[i].flags=(char) (DoRed | DoGreen | DoBlue);
3201 }
3202 pixel->box_color=pixel->background_color;
3203 pixel->pen_color=pixel->foreground_color;
3204 pixel->box_index=0;
3205 pixel->pen_index=1;
3206 if (image != (Image *) NULL)
3207 {
3208 if ((resource_info->gamma_correct != MagickFalse) &&
3209 (image->gamma != 0.0))
3210 {
3211 GeometryInfo
3212 geometry_info;
3213
3214 MagickStatusType
3215 flags;
3216
3217 /*
3218 Initialize map relative to display and image gamma.
3219 */
3220 flags=ParseGeometry(resource_info->display_gamma,&geometry_info);
3221 red_gamma=geometry_info.rho;
3222 green_gamma=geometry_info.sigma;
3223 if ((flags & SigmaValue) == 0)
3224 green_gamma=red_gamma;
3225 blue_gamma=geometry_info.xi;
3226 if ((flags & XiValue) == 0)
3227 blue_gamma=red_gamma;
3228 red_gamma*=image->gamma;
3229 green_gamma*=image->gamma;
3230 blue_gamma*=image->gamma;
3231 }
3232 if (image->storage_class == PseudoClass)
3233 {
3234 /*
3235 Initialize pixel array for images of type PseudoClass.
3236 */
cristybb503372010-05-27 20:51:26 +00003237 for (i=0; i < (ssize_t) image->colors; i++)
cristy4c08aed2011-07-01 19:47:50 +00003238 pixel->pixels[i]=XGammaPacket(map_info,image->colormap+i);
cristy3ed852e2009-09-05 21:47:34 +00003239 for (i=0; i < MaxNumberPens; i++)
3240 pixel->pixels[image->colors+i]=pixel->pen_colors[i].pixel;
3241 pixel->colors+=MaxNumberPens;
3242 }
3243 }
3244}
3245
3246/*
3247%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3248% %
3249% %
3250% %
3251% X G e t R e s o u r c e C l a s s %
3252% %
3253% %
3254% %
3255%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3256%
3257% XGetResourceClass() queries the X server for the specified resource name or
3258% class. If the resource name or class is not defined in the database, the
3259% supplied default value is returned.
3260%
3261% The format of the XGetResourceClass method is:
3262%
3263% char *XGetResourceClass(XrmDatabase database,const char *client_name,
3264% const char *keyword,char *resource_default)
3265%
3266% A description of each parameter follows:
3267%
3268% o database: Specifies a resource database; returned from
3269% XrmGetStringDatabase.
3270%
3271% o client_name: Specifies the application name used to retrieve resource
3272% info from the X server database.
3273%
3274% o keyword: Specifies the keyword of the value being retrieved.
3275%
3276% o resource_default: Specifies the default value to return if the query
3277% fails to find the specified keyword/class.
3278%
3279*/
3280MagickExport char *XGetResourceClass(XrmDatabase database,
3281 const char *client_name,const char *keyword,char *resource_default)
3282{
3283 char
3284 resource_class[MaxTextExtent],
3285 resource_name[MaxTextExtent];
3286
3287 static char
3288 *resource_type;
3289
3290 Status
3291 status;
3292
3293 XrmValue
3294 resource_value;
3295
3296 if (database == (XrmDatabase) NULL)
3297 return(resource_default);
3298 *resource_name='\0';
3299 *resource_class='\0';
3300 if (keyword != (char *) NULL)
3301 {
3302 int
3303 c,
3304 k;
3305
3306 /*
3307 Initialize resource keyword and class.
3308 */
cristyb51dff52011-05-19 16:55:47 +00003309 (void) FormatLocaleString(resource_name,MaxTextExtent,"%s.%s",
cristy3ed852e2009-09-05 21:47:34 +00003310 client_name,keyword);
3311 c=(int) (*client_name);
3312 if ((c >= XK_a) && (c <= XK_z))
3313 c-=(XK_a-XK_A);
3314 else
3315 if ((c >= XK_agrave) && (c <= XK_odiaeresis))
3316 c-=(XK_agrave-XK_Agrave);
3317 else
3318 if ((c >= XK_oslash) && (c <= XK_thorn))
3319 c-=(XK_oslash-XK_Ooblique);
3320 k=(int) (*keyword);
3321 if ((k >= XK_a) && (k <= XK_z))
3322 k-=(XK_a-XK_A);
3323 else
3324 if ((k >= XK_agrave) && (k <= XK_odiaeresis))
3325 k-=(XK_agrave-XK_Agrave);
3326 else
3327 if ((k >= XK_oslash) && (k <= XK_thorn))
3328 k-=(XK_oslash-XK_Ooblique);
cristyb51dff52011-05-19 16:55:47 +00003329 (void) FormatLocaleString(resource_class,MaxTextExtent,"%c%s.%c%s",c,
cristy3ed852e2009-09-05 21:47:34 +00003330 client_name+1,k,keyword+1);
3331 }
3332 status=XrmGetResource(database,resource_name,resource_class,&resource_type,
3333 &resource_value);
3334 if (status == False)
3335 return(resource_default);
3336 return(resource_value.addr);
3337}
3338
3339/*
3340%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3341% %
3342% %
3343% %
3344% X G e t R e s o u r c e D a t a b a s e %
3345% %
3346% %
3347% %
3348%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3349%
3350% XGetResourceDatabase() creates a new resource database and initializes it.
3351%
3352% The format of the XGetResourceDatabase method is:
3353%
3354% XrmDatabase XGetResourceDatabase(Display *display,
3355% const char *client_name)
3356%
3357% A description of each parameter follows:
3358%
3359% o database: XGetResourceDatabase() returns the database after it is
3360% initialized.
3361%
3362% o display: Specifies a connection to an X server; returned from
3363% XOpenDisplay.
3364%
3365% o client_name: Specifies the application name used to retrieve resource
3366% info from the X server database.
3367%
3368*/
3369MagickExport XrmDatabase XGetResourceDatabase(Display *display,
3370 const char *client_name)
3371{
3372 char
3373 filename[MaxTextExtent];
3374
3375 int
3376 c;
3377
3378 register const char
3379 *p;
3380
3381 XrmDatabase
3382 resource_database,
3383 server_database;
3384
3385 if (display == (Display *) NULL)
3386 return((XrmDatabase) NULL);
3387 assert(client_name != (char *) NULL);
3388 /*
3389 Initialize resource database.
3390 */
3391 XrmInitialize();
3392 (void) XGetDefault(display,(char *) client_name,"dummy");
3393 resource_database=XrmGetDatabase(display);
3394 /*
3395 Combine application database.
3396 */
3397 if (client_name != (char *) NULL)
3398 {
3399 /*
3400 Get basename of client.
3401 */
3402 p=client_name+(strlen(client_name)-1);
3403 while ((p > client_name) && (*p != '/'))
3404 p--;
3405 if (*p == '/')
3406 client_name=p+1;
3407 }
3408 c=(int) (*client_name);
3409 if ((c >= XK_a) && (c <= XK_z))
3410 c-=(XK_a-XK_A);
3411 else
3412 if ((c >= XK_agrave) && (c <= XK_odiaeresis))
3413 c-=(XK_agrave-XK_Agrave);
3414 else
3415 if ((c >= XK_oslash) && (c <= XK_thorn))
3416 c-=(XK_oslash-XK_Ooblique);
3417#if defined(X11_APPLICATION_PATH)
cristyb51dff52011-05-19 16:55:47 +00003418 (void) FormatLocaleString(filename,MaxTextExtent,"%s%c%s",
cristy3ed852e2009-09-05 21:47:34 +00003419 X11_APPLICATION_PATH,c,client_name+1);
3420 (void) XrmCombineFileDatabase(filename,&resource_database,MagickFalse);
3421#endif
3422 if (XResourceManagerString(display) != (char *) NULL)
3423 {
3424 /*
3425 Combine server database.
3426 */
3427 server_database=XrmGetStringDatabase(XResourceManagerString(display));
3428 XrmCombineDatabase(server_database,&resource_database,MagickFalse);
3429 }
3430 /*
3431 Merge user preferences database.
3432 */
3433#if defined(X11_PREFERENCES_PATH)
cristyb51dff52011-05-19 16:55:47 +00003434 (void) FormatLocaleString(filename,MaxTextExtent,"%s%src",
cristy3ed852e2009-09-05 21:47:34 +00003435 X11_PREFERENCES_PATH,client_name);
3436 ExpandFilename(filename);
3437 (void) XrmCombineFileDatabase(filename,&resource_database,MagickFalse);
3438#endif
3439 return(resource_database);
3440}
3441
3442/*
3443%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3444% %
3445% %
3446% %
3447% X G e t R e s o u r c e I n f o %
3448% %
3449% %
3450% %
3451%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3452%
3453% XGetResourceInfo(image_info,) initializes the ResourceInfo structure.
3454%
3455% The format of the XGetResourceInfo method is:
3456%
3457% void XGetResourceInfo(const ImageInfo *image_info,XrmDatabase database,
3458% const char *client_name,XResourceInfo *resource_info)
3459%
3460% A description of each parameter follows:
3461%
3462% o image_info: the image info.
3463%
3464% o database: Specifies a resource database; returned from
3465% XrmGetStringDatabase.
3466%
3467% o client_name: Specifies the application name used to retrieve
3468% resource info from the X server database.
3469%
3470% o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
3471%
3472*/
3473MagickExport void XGetResourceInfo(const ImageInfo *image_info,
3474 XrmDatabase database,const char *client_name,XResourceInfo *resource_info)
3475{
3476 char
cristy00976d82011-02-20 20:31:28 +00003477 *directory,
cristy3ed852e2009-09-05 21:47:34 +00003478 *resource_value;
3479
3480 /*
3481 Initialize resource info fields.
3482 */
3483 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
3484 assert(resource_info != (XResourceInfo *) NULL);
3485 (void) ResetMagickMemory(resource_info,0,sizeof(*resource_info));
3486 resource_info->resource_database=database;
3487 resource_info->image_info=(ImageInfo *) image_info;
3488 (void) SetImageInfoProgressMonitor(resource_info->image_info,
3489 XMagickProgressMonitor,(void *) NULL);
3490 resource_info->quantize_info=CloneQuantizeInfo((QuantizeInfo *) NULL);
3491 resource_info->close_server=MagickTrue;
3492 resource_info->client_name=AcquireString(client_name);
3493 resource_value=XGetResourceClass(database,client_name,"backdrop",
3494 (char *) "False");
3495 resource_info->backdrop=IsMagickTrue(resource_value);
3496 resource_info->background_color=XGetResourceInstance(database,client_name,
3497 "background",(char *) "#d6d6d6d6d6d6");
3498 resource_info->border_color=XGetResourceInstance(database,client_name,
3499 "borderColor",BorderColor);
3500 resource_value=XGetResourceClass(database,client_name,"borderWidth",
3501 (char *) "2");
cristy00976d82011-02-20 20:31:28 +00003502 resource_info->border_width=(unsigned int) StringToUnsignedLong(
3503 resource_value);
cristy3ed852e2009-09-05 21:47:34 +00003504 resource_value=XGetResourceClass(database,client_name,"colormap",
3505 (char *) "shared");
3506 resource_info->colormap=UndefinedColormap;
3507 if (LocaleCompare("private",resource_value) == 0)
3508 resource_info->colormap=PrivateColormap;
3509 if (LocaleCompare("shared",resource_value) == 0)
3510 resource_info->colormap=SharedColormap;
3511 if (resource_info->colormap == UndefinedColormap)
3512 ThrowXWindowFatalException(OptionError,"UnrecognizedColormapType",
3513 resource_value);
3514 resource_value=XGetResourceClass(database,client_name,
3515 "colorRecovery",(char *) "False");
3516 resource_info->color_recovery=IsMagickTrue(resource_value);
3517 resource_value=XGetResourceClass(database,client_name,"confirmExit",
3518 (char *) "False");
3519 resource_info->confirm_exit=IsMagickTrue(resource_value);
3520 resource_value=XGetResourceClass(database,client_name,"confirmEdit",
3521 (char *) "False");
3522 resource_info->confirm_edit=IsMagickTrue(resource_value);
cristyba0c3252010-06-27 13:31:44 +00003523 resource_value=XGetResourceClass(database,client_name,"delay",(char *) "1");
cristye27293e2009-12-18 02:53:20 +00003524 resource_info->delay=(unsigned int) StringToUnsignedLong(resource_value);
cristy3ed852e2009-09-05 21:47:34 +00003525 resource_info->display_gamma=XGetResourceClass(database,client_name,
3526 "displayGamma",(char *) "2.2");
3527 resource_value=XGetResourceClass(database,client_name,"displayWarnings",
3528 (char *) "True");
3529 resource_info->display_warnings=IsMagickTrue(resource_value);
3530 resource_info->font=XGetResourceClass(database,client_name,"font",
3531 (char *) NULL);
3532 resource_info->font=XGetResourceClass(database,client_name,"fontList",
3533 resource_info->font);
3534 resource_info->font_name[0]=XGetResourceClass(database,client_name,"font1",
3535 (char *) "fixed");
3536 resource_info->font_name[1]=XGetResourceClass(database,client_name,"font2",
3537 (char *) "variable");
3538 resource_info->font_name[2]=XGetResourceClass(database,client_name,"font3",
3539 (char *) "5x8");
3540 resource_info->font_name[3]=XGetResourceClass(database,client_name,"font4",
3541 (char *) "6x10");
3542 resource_info->font_name[4]=XGetResourceClass(database,client_name,"font5",
3543 (char *) "7x13bold");
3544 resource_info->font_name[5]=XGetResourceClass(database,client_name,"font6",
3545 (char *) "8x13bold");
3546 resource_info->font_name[6]=XGetResourceClass(database,client_name,"font7",
3547 (char *) "9x15bold");
3548 resource_info->font_name[7]=XGetResourceClass(database,client_name,"font8",
3549 (char *) "10x20");
3550 resource_info->font_name[8]=XGetResourceClass(database,client_name,"font9",
3551 (char *) "12x24");
3552 resource_info->font_name[9]=XGetResourceClass(database,client_name,"font0",
3553 (char *) "fixed");
3554 resource_info->font_name[10]=XGetResourceClass(database,client_name,"font0",
3555 (char *) "fixed");
3556 resource_info->foreground_color=XGetResourceInstance(database,client_name,
3557 "foreground",ForegroundColor);
3558 resource_value=XGetResourceClass(database,client_name,"gammaCorrect",
3559 (char *) "True");
3560 resource_info->gamma_correct=IsMagickTrue(resource_value);
3561 resource_info->image_geometry=ConstantString(XGetResourceClass(database,
3562 client_name,"geometry",(char *) NULL));
3563 resource_value=XGetResourceClass(database,client_name,"gravity",
3564 (char *) "Center");
cristy042ee782011-04-22 18:48:30 +00003565 resource_info->gravity=(GravityType) ParseCommandOption(MagickGravityOptions,
cristy3ed852e2009-09-05 21:47:34 +00003566 MagickFalse,resource_value);
cristy00976d82011-02-20 20:31:28 +00003567 directory=getcwd(resource_info->home_directory,MaxTextExtent);
3568 (void) directory;
cristy3ed852e2009-09-05 21:47:34 +00003569 resource_info->icon_geometry=XGetResourceClass(database,client_name,
3570 "iconGeometry",(char *) NULL);
3571 resource_value=XGetResourceClass(database,client_name,"iconic",
3572 (char *) "False");
3573 resource_info->iconic=IsMagickTrue(resource_value);
3574 resource_value=XGetResourceClass(database,client_name,"immutable",
3575 LocaleCompare(client_name,"PerlMagick") == 0 ? (char *) "True" :
3576 (char *) "False");
3577 resource_info->immutable=IsMagickTrue(resource_value);
3578 resource_value=XGetResourceClass(database,client_name,"magnify",
3579 (char *) "3");
cristye27293e2009-12-18 02:53:20 +00003580 resource_info->magnify=(unsigned int) StringToUnsignedLong(resource_value);
cristy3ed852e2009-09-05 21:47:34 +00003581 resource_info->map_type=XGetResourceClass(database,client_name,"map",
3582 (char *) NULL);
3583 resource_info->matte_color=XGetResourceInstance(database,client_name,
3584 "mattecolor",(char *) NULL);
3585 resource_info->name=ConstantString(XGetResourceClass(database,client_name,
3586 "name",(char *) NULL));
3587 resource_info->pen_colors[0]=XGetResourceClass(database,client_name,"pen1",
3588 (char *) "black");
3589 resource_info->pen_colors[1]=XGetResourceClass(database,client_name,"pen2",
3590 (char *) "blue");
3591 resource_info->pen_colors[2]=XGetResourceClass(database,client_name,"pen3",
3592 (char *) "cyan");
3593 resource_info->pen_colors[3]=XGetResourceClass(database,client_name,"pen4",
3594 (char *) "green");
3595 resource_info->pen_colors[4]=XGetResourceClass(database,client_name,"pen5",
3596 (char *) "gray");
3597 resource_info->pen_colors[5]=XGetResourceClass(database,client_name,"pen6",
3598 (char *) "red");
3599 resource_info->pen_colors[6]=XGetResourceClass(database,client_name,"pen7",
3600 (char *) "magenta");
3601 resource_info->pen_colors[7]=XGetResourceClass(database,client_name,"pen8",
3602 (char *) "yellow");
3603 resource_info->pen_colors[8]=XGetResourceClass(database,client_name,"pen9",
3604 (char *) "white");
3605 resource_info->pen_colors[9]=XGetResourceClass(database,client_name,"pen0",
3606 (char *) "gray");
3607 resource_info->pen_colors[10]=XGetResourceClass(database,client_name,"pen0",
3608 (char *) "gray");
3609 resource_value=XGetResourceClass(database,client_name,"pause",(char *) "0");
cristye27293e2009-12-18 02:53:20 +00003610 resource_info->pause=(unsigned int) StringToUnsignedLong(resource_value);
cristy3ed852e2009-09-05 21:47:34 +00003611 resource_value=XGetResourceClass(database,client_name,"quantum",(char *) "1");
cristyf2f27272009-12-17 14:48:46 +00003612 resource_info->quantum=StringToLong(resource_value);
cristy3ed852e2009-09-05 21:47:34 +00003613 resource_info->text_font=XGetResourceClass(database,client_name,(char *)
3614 "font",(char *) "fixed");
3615 resource_info->text_font=XGetResourceClass(database,client_name,
3616 "textFontList",resource_info->text_font);
3617 resource_info->title=XGetResourceClass(database,client_name,"title",
3618 (char *) NULL);
3619 resource_value=XGetResourceClass(database,client_name,"undoCache",
3620 (char *) "16");
cristye27293e2009-12-18 02:53:20 +00003621 resource_info->undo_cache=(unsigned int) StringToUnsignedLong(resource_value);
cristy3ed852e2009-09-05 21:47:34 +00003622 resource_value=XGetResourceClass(database,client_name,"update",
3623 (char *) "False");
3624 resource_info->update=IsMagickTrue(resource_value);
3625 resource_value=XGetResourceClass(database,client_name,"usePixmap",
3626 (char *) "True");
3627 resource_info->use_pixmap=IsMagickTrue(resource_value);
3628 resource_value=XGetResourceClass(database,client_name,"sharedMemory",
3629 (char *) "True");
3630 resource_info->use_shared_memory=IsMagickTrue(resource_value);
3631 resource_info->visual_type=XGetResourceClass(database,client_name,"visual",
3632 (char *) NULL);
3633 resource_info->window_group=XGetResourceClass(database,client_name,
3634 "windowGroup",(char *) NULL);
3635 resource_info->window_id=XGetResourceClass(database,client_name,"window",
3636 (char *) NULL);
3637 resource_info->write_filename=XGetResourceClass(database,client_name,
3638 "writeFilename",(char *) NULL);
3639}
3640
3641/*
3642%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3643% %
3644% %
3645% %
3646% X G e t R e s o u r c e I n s t a n c e %
3647% %
3648% %
3649% %
3650%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3651%
3652% XGetResourceInstance() queries the X server for the specified resource name.
3653% If the resource name is not defined in the database, the supplied default
3654% value is returned.
3655%
3656% The format of the XGetResourceInstance method is:
3657%
3658% char *XGetResourceInstance(XrmDatabase database,const char *client_name,
3659% const char *keyword,const char *resource_default)
3660%
3661% A description of each parameter follows:
3662%
3663% o database: Specifies a resource database; returned from
3664% XrmGetStringDatabase.
3665%
3666% o client_name: Specifies the application name used to retrieve
3667% resource info from the X server database.
3668%
3669% o keyword: Specifies the keyword of the value being retrieved.
3670%
3671% o resource_default: Specifies the default value to return if the query
3672% fails to find the specified keyword/class.
3673%
3674*/
3675MagickExport char *XGetResourceInstance(XrmDatabase database,
3676 const char *client_name,const char *keyword,const char *resource_default)
3677{
3678 char
3679 *resource_type,
3680 resource_name[MaxTextExtent];
3681
3682 Status
3683 status;
3684
3685 XrmValue
3686 resource_value;
3687
3688 if (database == (XrmDatabase) NULL)
3689 return((char *) resource_default);
3690 *resource_name='\0';
3691 if (keyword != (char *) NULL)
cristyb51dff52011-05-19 16:55:47 +00003692 (void) FormatLocaleString(resource_name,MaxTextExtent,"%s.%s",client_name,
cristy3ed852e2009-09-05 21:47:34 +00003693 keyword);
3694 status=XrmGetResource(database,resource_name,"ImageMagick",&resource_type,
3695 &resource_value);
3696 if (status == False)
3697 return((char *) resource_default);
3698 return(resource_value.addr);
3699}
3700
3701/*
3702%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3703% %
3704% %
3705% %
3706% X G e t S c r e e n D e n s i t y %
3707% %
3708% %
3709% %
3710%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3711%
3712% XGetScreenDensity() returns the density of the X server screen in
3713% dots-per-inch.
3714%
3715% The format of the XGetScreenDensity method is:
3716%
3717% char *XGetScreenDensity(Display *display)
3718%
3719% A description of each parameter follows:
3720%
3721% o density: XGetScreenDensity() returns the density of the X screen in
3722% dots-per-inch.
3723%
3724% o display: Specifies a connection to an X server; returned from
3725% XOpenDisplay.
3726%
3727*/
3728MagickExport char *XGetScreenDensity(Display *display)
3729{
3730 char
3731 density[MaxTextExtent];
3732
3733 double
3734 x_density,
3735 y_density;
3736
3737 /*
3738 Set density as determined by screen size.
3739 */
3740 x_density=((((double) DisplayWidth(display,XDefaultScreen(display)))*25.4)/
3741 ((double) DisplayWidthMM(display,XDefaultScreen(display))));
3742 y_density=((((double) DisplayHeight(display,XDefaultScreen(display)))*25.4)/
3743 ((double) DisplayHeightMM(display,XDefaultScreen(display))));
cristyb51dff52011-05-19 16:55:47 +00003744 (void) FormatLocaleString(density,MaxTextExtent,"%gx%g",x_density,
cristy8cd5b312010-01-07 01:10:24 +00003745 y_density);
cristy3ed852e2009-09-05 21:47:34 +00003746 return(GetPageGeometry(density));
3747}
3748
3749/*
3750%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3751% %
3752% %
3753% %
3754+ X G e t S u b w i n d o w %
3755% %
3756% %
3757% %
3758%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3759%
3760% XGetSubwindow() returns the subwindow of a window chosen the user with the
3761% pointer and a button press.
3762%
3763% The format of the XGetSubwindow method is:
3764%
3765% Window XGetSubwindow(Display *display,Window window,int x,int y)
3766%
3767% A description of each parameter follows:
3768%
3769% o subwindow: XGetSubwindow() returns NULL if no subwindow is found
3770% otherwise the subwindow is returned.
3771%
3772% o display: Specifies a connection to an X server; returned from
3773% XOpenDisplay.
3774%
3775% o window: Specifies a pointer to a Window.
3776%
3777% o x: the x coordinate of the pointer relative to the origin of the
3778% window.
3779%
3780% o y: the y coordinate of the pointer relative to the origin of the
3781% window.
3782%
cristy3ed852e2009-09-05 21:47:34 +00003783*/
3784static Window XGetSubwindow(Display *display,Window window,int x,int y)
3785{
3786 int
3787 x_offset,
3788 y_offset;
3789
3790 Status
3791 status;
3792
3793 Window
3794 source_window,
3795 target_window;
3796
3797 assert(display != (Display *) NULL);
3798 source_window=XRootWindow(display,XDefaultScreen(display));
3799 if (window == (Window) NULL)
3800 return(source_window);
3801 target_window=window;
3802 for ( ; ; )
3803 {
3804 status=XTranslateCoordinates(display,source_window,window,x,y,
3805 &x_offset,&y_offset,&target_window);
3806 if (status != True)
3807 break;
3808 if (target_window == (Window) NULL)
3809 break;
3810 source_window=window;
3811 window=target_window;
3812 x=x_offset;
3813 y=y_offset;
3814 }
3815 if (target_window == (Window) NULL)
3816 target_window=window;
3817 return(target_window);
3818}
3819
3820/*
3821%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3822% %
3823% %
3824% %
3825% X G e t W i n d o w C o l o r %
3826% %
3827% %
3828% %
3829%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3830%
3831% XGetWindowColor() returns the color of a pixel interactively chosen from the
3832% X server.
3833%
3834% The format of the XGetWindowColor method is:
3835%
3836% MagickBooleanType XGetWindowColor(Display *display,XWindows *windows,
cristy6710d842011-10-20 23:23:00 +00003837% char *name,ExceptionInfo *exception)
cristy3ed852e2009-09-05 21:47:34 +00003838%
3839% A description of each parameter follows:
3840%
3841% o display: Specifies a connection to an X server; returned from
3842% XOpenDisplay.
3843%
3844% o windows: Specifies a pointer to a XWindows structure.
3845%
3846% o name: the name of the color if found in the X Color Database is
3847% returned in this character string.
3848%
cristy6710d842011-10-20 23:23:00 +00003849% o exception: return any errors or warnings in this structure.
3850%
cristy3ed852e2009-09-05 21:47:34 +00003851*/
cristybcbda3f2011-09-03 13:01:22 +00003852MagickPrivate MagickBooleanType XGetWindowColor(Display *display,
cristy6710d842011-10-20 23:23:00 +00003853 XWindows *windows,char *name,ExceptionInfo *exception)
cristy3ed852e2009-09-05 21:47:34 +00003854{
3855 int
3856 x,
3857 y;
3858
cristy101ab702011-10-13 13:06:32 +00003859 PixelInfo
cristy3ed852e2009-09-05 21:47:34 +00003860 pixel;
3861
3862 RectangleInfo
3863 crop_info;
3864
3865 Status
3866 status;
3867
3868 Window
3869 child,
3870 client_window,
3871 root_window,
3872 target_window;
3873
3874 XColor
3875 color;
3876
3877 XImage
3878 *ximage;
3879
3880 XWindowAttributes
3881 window_attributes;
3882
3883 /*
3884 Choose a pixel from the X server.
3885 */
3886 assert(display != (Display *) NULL);
3887 assert(name != (char *) NULL);
3888 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",name);
3889 *name='\0';
3890 target_window=XSelectWindow(display,&crop_info);
3891 if (target_window == (Window) NULL)
3892 return(MagickFalse);
3893 root_window=XRootWindow(display,XDefaultScreen(display));
3894 client_window=target_window;
3895 if (target_window != root_window)
3896 {
3897 unsigned int
3898 d;
3899
3900 /*
3901 Get client window.
3902 */
3903 status=XGetGeometry(display,target_window,&root_window,&x,&x,&d,&d,&d,&d);
3904 if (status != False)
3905 {
3906 client_window=XClientWindow(display,target_window);
3907 target_window=client_window;
3908 }
3909 }
3910 /*
3911 Verify window is viewable.
3912 */
3913 status=XGetWindowAttributes(display,target_window,&window_attributes);
3914 if ((status == False) || (window_attributes.map_state != IsViewable))
3915 return(MagickFalse);
3916 /*
3917 Get window X image.
3918 */
3919 (void) XTranslateCoordinates(display,root_window,target_window,
3920 (int) crop_info.x,(int) crop_info.y,&x,&y,&child);
3921 ximage=XGetImage(display,target_window,x,y,1,1,AllPlanes,ZPixmap);
3922 if (ximage == (XImage *) NULL)
3923 return(MagickFalse);
3924 color.pixel=XGetPixel(ximage,0,0);
3925 XDestroyImage(ximage);
3926 /*
3927 Match color against the color database.
3928 */
3929 (void) XQueryColor(display,window_attributes.colormap,&color);
cristye42f6582012-02-11 17:59:50 +00003930 pixel.red=(double) ScaleShortToQuantum(color.red);
3931 pixel.green=(double) ScaleShortToQuantum(color.green);
3932 pixel.blue=(double) ScaleShortToQuantum(color.blue);
cristy4c08aed2011-07-01 19:47:50 +00003933 pixel.alpha=OpaqueAlpha;
cristy3ed852e2009-09-05 21:47:34 +00003934 (void) QueryColorname(windows->image.image,&pixel,X11Compliance,name,
cristy6710d842011-10-20 23:23:00 +00003935 exception);
cristy3ed852e2009-09-05 21:47:34 +00003936 return(MagickTrue);
3937}
3938
3939/*
3940%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3941% %
3942% %
3943% %
3944+ X G e t W i n d o w I m a g e %
3945% %
3946% %
3947% %
3948%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3949%
3950% XGetWindowImage() reads an image from the target X window and returns it.
3951% XGetWindowImage() optionally descends the window hierarchy and overlays the
3952% target image with each child image in an optimized fashion. Any child
3953% window that have the same visual, colormap, and are contained by its parent
3954% are exempted.
3955%
3956% The format of the XGetWindowImage method is:
3957%
3958% Image *XGetWindowImage(Display *display,const Window window,
cristy6710d842011-10-20 23:23:00 +00003959% const unsigned int borders,const unsigned int level,
3960% ExceptionInfo *exception)
cristy3ed852e2009-09-05 21:47:34 +00003961%
3962% A description of each parameter follows:
3963%
3964% o display: Specifies a connection to an X server; returned from
3965% XOpenDisplay.
3966%
3967% o window: Specifies the window to obtain the image from.
3968%
3969% o borders: Specifies whether borders pixels are to be saved with
3970% the image.
3971%
3972% o level: Specifies an unsigned integer representing the level of
3973% decent in the window hierarchy. This value must be zero or one on
3974% the initial call to XGetWindowImage. A value of zero returns after
3975% one call. A value of one causes the function to descend the window
3976% hierarchy and overlay the target image with each subwindow image.
3977%
cristy6710d842011-10-20 23:23:00 +00003978% o exception: return any errors or warnings in this structure.
3979%
cristy3ed852e2009-09-05 21:47:34 +00003980*/
3981static Image *XGetWindowImage(Display *display,const Window window,
cristy6710d842011-10-20 23:23:00 +00003982 const unsigned int borders,const unsigned int level,ExceptionInfo *exception)
cristy3ed852e2009-09-05 21:47:34 +00003983{
3984 typedef struct _ColormapInfo
3985 {
3986 Colormap
3987 colormap;
3988
3989 XColor
3990 *colors;
3991
3992 struct _ColormapInfo
3993 *next;
3994 } ColormapInfo;
3995
3996 typedef struct _WindowInfo
3997 {
3998 Window
3999 window,
4000 parent;
4001
4002 Visual
4003 *visual;
4004
4005 Colormap
4006 colormap;
4007
4008 XSegment
4009 bounds;
4010
4011 RectangleInfo
4012 crop_info;
4013 } WindowInfo;
4014
cristy3ed852e2009-09-05 21:47:34 +00004015 int
4016 display_height,
4017 display_width,
4018 id,
4019 x_offset,
4020 y_offset;
4021
cristy4c08aed2011-07-01 19:47:50 +00004022 Quantum
4023 index;
4024
cristy3ed852e2009-09-05 21:47:34 +00004025 RectangleInfo
4026 crop_info;
4027
cristy3ed852e2009-09-05 21:47:34 +00004028 register int
4029 i;
4030
4031 static ColormapInfo
4032 *colormap_info = (ColormapInfo *) NULL;
4033
4034 static int
4035 max_windows = 0,
4036 number_windows = 0;
4037
4038 static WindowInfo
4039 *window_info;
4040
4041 Status
4042 status;
4043
4044 Window
4045 child,
4046 root_window;
4047
4048 XWindowAttributes
4049 window_attributes;
4050
4051 /*
4052 Verify window is viewable.
4053 */
4054 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
4055 assert(display != (Display *) NULL);
4056 status=XGetWindowAttributes(display,window,&window_attributes);
4057 if ((status == False) || (window_attributes.map_state != IsViewable))
4058 return((Image *) NULL);
4059 /*
4060 Cropping rectangle is relative to root window.
4061 */
4062 root_window=XRootWindow(display,XDefaultScreen(display));
4063 (void) XTranslateCoordinates(display,window,root_window,0,0,&x_offset,
4064 &y_offset,&child);
cristybb503372010-05-27 20:51:26 +00004065 crop_info.x=(ssize_t) x_offset;
4066 crop_info.y=(ssize_t) y_offset;
4067 crop_info.width=(size_t) window_attributes.width;
4068 crop_info.height=(size_t) window_attributes.height;
cristy3ed852e2009-09-05 21:47:34 +00004069 if (borders != MagickFalse)
4070 {
4071 /*
4072 Include border in image.
4073 */
cristybb503372010-05-27 20:51:26 +00004074 crop_info.x-=(ssize_t) window_attributes.border_width;
4075 crop_info.y-=(ssize_t) window_attributes.border_width;
4076 crop_info.width+=(size_t) (window_attributes.border_width << 1);
4077 crop_info.height+=(size_t) (window_attributes.border_width << 1);
cristy3ed852e2009-09-05 21:47:34 +00004078 }
4079 /*
4080 Crop to root window.
4081 */
4082 if (crop_info.x < 0)
4083 {
4084 crop_info.width+=crop_info.x;
4085 crop_info.x=0;
4086 }
4087 if (crop_info.y < 0)
4088 {
4089 crop_info.height+=crop_info.y;
4090 crop_info.y=0;
4091 }
4092 display_width=XDisplayWidth(display,XDefaultScreen(display));
4093 if ((int) (crop_info.x+crop_info.width) > display_width)
cristybb503372010-05-27 20:51:26 +00004094 crop_info.width=(size_t) (display_width-crop_info.x);
cristy3ed852e2009-09-05 21:47:34 +00004095 display_height=XDisplayHeight(display,XDefaultScreen(display));
4096 if ((int) (crop_info.y+crop_info.height) > display_height)
cristybb503372010-05-27 20:51:26 +00004097 crop_info.height=(size_t) (display_height-crop_info.y);
cristy3ed852e2009-09-05 21:47:34 +00004098 /*
4099 Initialize window info attributes.
4100 */
4101 if (number_windows >= max_windows)
4102 {
4103 /*
4104 Allocate or resize window info buffer.
4105 */
4106 max_windows+=1024;
4107 if (window_info == (WindowInfo *) NULL)
4108 window_info=(WindowInfo *) AcquireQuantumMemory((size_t) max_windows,
4109 sizeof(*window_info));
4110 else
4111 window_info=(WindowInfo *) ResizeQuantumMemory(window_info,(size_t)
4112 max_windows,sizeof(*window_info));
4113 }
4114 if (window_info == (WindowInfo *) NULL)
4115 {
4116 ThrowXWindowFatalException(ResourceLimitError,
4117 "MemoryAllocationFailed","...");
4118 return((Image *) NULL);
4119 }
4120 id=number_windows++;
4121 window_info[id].window=window;
4122 window_info[id].visual=window_attributes.visual;
4123 window_info[id].colormap=window_attributes.colormap;
4124 window_info[id].bounds.x1=(short) crop_info.x;
4125 window_info[id].bounds.y1=(short) crop_info.y;
4126 window_info[id].bounds.x2=(short) (crop_info.x+(int) crop_info.width-1);
4127 window_info[id].bounds.y2=(short) (crop_info.y+(int) crop_info.height-1);
4128 crop_info.x-=x_offset;
4129 crop_info.y-=y_offset;
4130 window_info[id].crop_info=crop_info;
4131 if (level != 0)
4132 {
4133 unsigned int
4134 number_children;
4135
4136 Window
4137 *children;
4138
4139 /*
4140 Descend the window hierarchy.
4141 */
4142 status=XQueryTree(display,window,&root_window,&window_info[id].parent,
4143 &children,&number_children);
4144 for (i=0; i < id; i++)
4145 if ((window_info[i].window == window_info[id].parent) &&
4146 (window_info[i].visual == window_info[id].visual) &&
4147 (window_info[i].colormap == window_info[id].colormap))
4148 {
4149 if ((window_info[id].bounds.x1 <= window_info[i].bounds.x1) ||
4150 (window_info[id].bounds.x1 >= window_info[i].bounds.x2) ||
4151 (window_info[id].bounds.y1 <= window_info[i].bounds.y1) ||
4152 (window_info[id].bounds.y1 >= window_info[i].bounds.y2))
4153 {
4154 /*
4155 Eliminate windows not circumscribed by their parent.
4156 */
4157 number_windows--;
4158 break;
4159 }
4160 }
4161 if ((status == True) && (number_children != 0))
4162 {
4163 for (i=0; i < (int) number_children; i++)
cristy6710d842011-10-20 23:23:00 +00004164 (void) XGetWindowImage(display,children[i],MagickFalse,level+1,
4165 exception);
cristy3ed852e2009-09-05 21:47:34 +00004166 (void) XFree((void *) children);
4167 }
4168 }
4169 if (level <= 1)
4170 {
cristyc57f6942010-11-12 01:47:39 +00004171 CacheView
4172 *composite_view;
4173
cristy3ed852e2009-09-05 21:47:34 +00004174 ColormapInfo
4175 *next;
4176
cristy3ed852e2009-09-05 21:47:34 +00004177 Image
4178 *composite_image,
4179 *image;
4180
4181 int
4182 y;
4183
4184 MagickBooleanType
4185 import;
4186
4187 register int
4188 j,
4189 x;
4190
cristy4c08aed2011-07-01 19:47:50 +00004191 register Quantum
cristyc47d1f82009-11-26 01:44:43 +00004192 *restrict q;
cristy3ed852e2009-09-05 21:47:34 +00004193
cristybb503372010-05-27 20:51:26 +00004194 register size_t
cristy3ed852e2009-09-05 21:47:34 +00004195 pixel;
4196
4197 unsigned int
4198 number_colors;
4199
4200 XColor
4201 *colors;
4202
4203 XImage
4204 *ximage;
4205
4206 /*
4207 Get X image for each window in the list.
4208 */
4209 image=NewImageList();
4210 for (id=0; id < number_windows; id++)
4211 {
4212 /*
4213 Does target window intersect top level window?
4214 */
4215 import=
4216 ((window_info[id].bounds.x2 >= window_info[0].bounds.x1) &&
4217 (window_info[id].bounds.x1 <= window_info[0].bounds.x2) &&
4218 (window_info[id].bounds.y2 >= window_info[0].bounds.y1) &&
4219 (window_info[id].bounds.y1 <= window_info[0].bounds.y2)) ?
4220 MagickTrue : MagickFalse;
4221 /*
4222 Is target window contained by another window with the same colormap?
4223 */
4224 for (j=0; j < id; j++)
4225 if ((window_info[id].visual == window_info[j].visual) &&
4226 (window_info[id].colormap == window_info[j].colormap))
4227 {
4228 if ((window_info[id].bounds.x1 <= window_info[j].bounds.x1) ||
4229 (window_info[id].bounds.x1 >= window_info[j].bounds.x2) ||
4230 (window_info[id].bounds.y1 <= window_info[j].bounds.y1) ||
4231 (window_info[id].bounds.y1 >= window_info[j].bounds.y2))
4232 import=MagickFalse;
4233 }
4234 else
4235 if ((window_info[id].visual != window_info[j].visual) ||
4236 (window_info[id].colormap != window_info[j].colormap))
4237 {
4238 if ((window_info[id].bounds.x2 > window_info[j].bounds.x1) &&
4239 (window_info[id].bounds.x1 < window_info[j].bounds.x2) &&
4240 (window_info[id].bounds.y2 > window_info[j].bounds.y1) &&
4241 (window_info[id].bounds.y1 < window_info[j].bounds.y2))
4242 import=MagickTrue;
4243 }
4244 if (import == MagickFalse)
4245 continue;
4246 /*
4247 Get X image.
4248 */
4249 ximage=XGetImage(display,window_info[id].window,(int)
4250 window_info[id].crop_info.x,(int) window_info[id].crop_info.y,
4251 (unsigned int) window_info[id].crop_info.width,(unsigned int)
4252 window_info[id].crop_info.height,AllPlanes,ZPixmap);
4253 if (ximage == (XImage *) NULL)
4254 continue;
4255 /*
4256 Initialize window colormap.
4257 */
4258 number_colors=0;
4259 colors=(XColor *) NULL;
4260 if (window_info[id].colormap != (Colormap) NULL)
4261 {
4262 ColormapInfo
4263 *p;
4264
4265 /*
4266 Search colormap list for window colormap.
4267 */
4268 number_colors=(unsigned int) window_info[id].visual->map_entries;
4269 for (p=colormap_info; p != (ColormapInfo *) NULL; p=p->next)
4270 if (p->colormap == window_info[id].colormap)
4271 break;
4272 if (p == (ColormapInfo *) NULL)
4273 {
4274 /*
4275 Get the window colormap.
4276 */
4277 colors=(XColor *) AcquireQuantumMemory(number_colors,
4278 sizeof(*colors));
4279 if (colors == (XColor *) NULL)
4280 {
4281 XDestroyImage(ximage);
4282 return((Image *) NULL);
4283 }
4284 if ((window_info[id].visual->klass != DirectColor) &&
4285 (window_info[id].visual->klass != TrueColor))
4286 for (i=0; i < (int) number_colors; i++)
4287 {
cristybb503372010-05-27 20:51:26 +00004288 colors[i].pixel=(size_t) i;
cristy3ed852e2009-09-05 21:47:34 +00004289 colors[i].pad='\0';
4290 }
4291 else
4292 {
cristybb503372010-05-27 20:51:26 +00004293 size_t
cristy3ed852e2009-09-05 21:47:34 +00004294 blue,
4295 blue_bit,
4296 green,
4297 green_bit,
4298 red,
4299 red_bit;
4300
4301 /*
4302 DirectColor or TrueColor visual.
4303 */
4304 red=0;
4305 green=0;
4306 blue=0;
4307 red_bit=window_info[id].visual->red_mask &
4308 (~(window_info[id].visual->red_mask)+1);
4309 green_bit=window_info[id].visual->green_mask &
4310 (~(window_info[id].visual->green_mask)+1);
4311 blue_bit=window_info[id].visual->blue_mask &
4312 (~(window_info[id].visual->blue_mask)+1);
4313 for (i=0; i < (int) number_colors; i++)
4314 {
cristy8891f9c2010-06-04 23:32:17 +00004315 colors[i].pixel=(unsigned long) (red | green | blue);
cristy3ed852e2009-09-05 21:47:34 +00004316 colors[i].pad='\0';
4317 red+=red_bit;
4318 if (red > window_info[id].visual->red_mask)
4319 red=0;
4320 green+=green_bit;
4321 if (green > window_info[id].visual->green_mask)
4322 green=0;
4323 blue+=blue_bit;
4324 if (blue > window_info[id].visual->blue_mask)
4325 blue=0;
4326 }
4327 }
4328 (void) XQueryColors(display,window_info[id].colormap,colors,
4329 (int) number_colors);
4330 /*
4331 Append colormap to colormap list.
4332 */
cristy73bd4a52010-10-05 11:24:23 +00004333 p=(ColormapInfo *) AcquireMagickMemory(sizeof(*p));
cristy3ed852e2009-09-05 21:47:34 +00004334 if (p == (ColormapInfo *) NULL)
4335 return((Image *) NULL);
4336 p->colormap=window_info[id].colormap;
4337 p->colors=colors;
4338 p->next=colormap_info;
4339 colormap_info=p;
4340 }
4341 colors=p->colors;
4342 }
4343 /*
4344 Allocate image structure.
4345 */
cristy6710d842011-10-20 23:23:00 +00004346 composite_image=AcquireImage((ImageInfo *) NULL,exception);
cristy3ed852e2009-09-05 21:47:34 +00004347 if (composite_image == (Image *) NULL)
4348 {
4349 XDestroyImage(ximage);
4350 return((Image *) NULL);
4351 }
4352 /*
4353 Convert X image to MIFF format.
4354 */
4355 if ((window_info[id].visual->klass != TrueColor) &&
4356 (window_info[id].visual->klass != DirectColor))
4357 composite_image->storage_class=PseudoClass;
cristybb503372010-05-27 20:51:26 +00004358 composite_image->columns=(size_t) ximage->width;
4359 composite_image->rows=(size_t) ximage->height;
cristyc57f6942010-11-12 01:47:39 +00004360 composite_view=AcquireCacheView(composite_image);
cristy3ed852e2009-09-05 21:47:34 +00004361 switch (composite_image->storage_class)
4362 {
4363 case DirectClass:
4364 default:
4365 {
cristybb503372010-05-27 20:51:26 +00004366 register size_t
cristy3ed852e2009-09-05 21:47:34 +00004367 color,
4368 index;
4369
cristybb503372010-05-27 20:51:26 +00004370 size_t
cristy3ed852e2009-09-05 21:47:34 +00004371 blue_mask,
4372 blue_shift,
4373 green_mask,
4374 green_shift,
4375 red_mask,
4376 red_shift;
4377
4378 /*
4379 Determine shift and mask for red, green, and blue.
4380 */
4381 red_mask=window_info[id].visual->red_mask;
4382 red_shift=0;
4383 while ((red_mask != 0) && ((red_mask & 0x01) == 0))
4384 {
4385 red_mask>>=1;
4386 red_shift++;
4387 }
4388 green_mask=window_info[id].visual->green_mask;
4389 green_shift=0;
4390 while ((green_mask != 0) && ((green_mask & 0x01) == 0))
4391 {
4392 green_mask>>=1;
4393 green_shift++;
4394 }
4395 blue_mask=window_info[id].visual->blue_mask;
4396 blue_shift=0;
4397 while ((blue_mask != 0) && ((blue_mask & 0x01) == 0))
4398 {
4399 blue_mask>>=1;
4400 blue_shift++;
4401 }
4402 /*
4403 Convert X image to DirectClass packets.
4404 */
4405 if ((number_colors != 0) &&
4406 (window_info[id].visual->klass == DirectColor))
4407 for (y=0; y < (int) composite_image->rows; y++)
4408 {
cristyc57f6942010-11-12 01:47:39 +00004409 q=QueueCacheViewAuthenticPixels(composite_view,0,(ssize_t) y,
cristy3ed852e2009-09-05 21:47:34 +00004410 composite_image->columns,1,exception);
cristyacd2ed22011-08-30 01:44:23 +00004411 if (q == (Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00004412 break;
4413 for (x=0; x < (int) composite_image->columns; x++)
4414 {
4415 pixel=XGetPixel(ximage,x,y);
4416 index=(pixel >> red_shift) & red_mask;
cristy4c08aed2011-07-01 19:47:50 +00004417 SetPixelRed(composite_image,
4418 ScaleShortToQuantum(colors[index].red),q);
cristy3ed852e2009-09-05 21:47:34 +00004419 index=(pixel >> green_shift) & green_mask;
cristy4c08aed2011-07-01 19:47:50 +00004420 SetPixelGreen(composite_image,
4421 ScaleShortToQuantum(colors[index].green),q);
cristy3ed852e2009-09-05 21:47:34 +00004422 index=(pixel >> blue_shift) & blue_mask;
cristy4c08aed2011-07-01 19:47:50 +00004423 SetPixelBlue(composite_image,
4424 ScaleShortToQuantum(colors[index].blue),q);
cristyed231572011-07-14 02:18:59 +00004425 q+=GetPixelChannels(composite_image);
cristy3ed852e2009-09-05 21:47:34 +00004426 }
cristy0b1a7972011-10-22 22:17:02 +00004427 status=SyncCacheViewAuthenticPixels(composite_view,exception);
4428 if (status == MagickFalse)
cristy3ed852e2009-09-05 21:47:34 +00004429 break;
4430 }
4431 else
4432 for (y=0; y < (int) composite_image->rows; y++)
4433 {
cristyc57f6942010-11-12 01:47:39 +00004434 q=QueueCacheViewAuthenticPixels(composite_view,0,(ssize_t) y,
cristy3ed852e2009-09-05 21:47:34 +00004435 composite_image->columns,1,exception);
cristyacd2ed22011-08-30 01:44:23 +00004436 if (q == (Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00004437 break;
4438 for (x=0; x < (int) composite_image->columns; x++)
4439 {
4440 pixel=XGetPixel(ximage,x,y);
4441 color=(pixel >> red_shift) & red_mask;
4442 color=(65535UL*color)/red_mask;
cristy4c08aed2011-07-01 19:47:50 +00004443 SetPixelRed(composite_image,
4444 ScaleShortToQuantum((unsigned short) color),q);
cristy3ed852e2009-09-05 21:47:34 +00004445 color=(pixel >> green_shift) & green_mask;
4446 color=(65535UL*color)/green_mask;
cristy4c08aed2011-07-01 19:47:50 +00004447 SetPixelGreen(composite_image,
4448 ScaleShortToQuantum((unsigned short) color),q);
cristy3ed852e2009-09-05 21:47:34 +00004449 color=(pixel >> blue_shift) & blue_mask;
4450 color=(65535UL*color)/blue_mask;
cristy4c08aed2011-07-01 19:47:50 +00004451 SetPixelBlue(composite_image,
4452 ScaleShortToQuantum((unsigned short) color),q);
cristyed231572011-07-14 02:18:59 +00004453 q+=GetPixelChannels(composite_image);
cristy3ed852e2009-09-05 21:47:34 +00004454 }
cristy0b1a7972011-10-22 22:17:02 +00004455 status=SyncCacheViewAuthenticPixels(composite_view,exception);
4456 if (status == MagickFalse)
cristy3ed852e2009-09-05 21:47:34 +00004457 break;
4458 }
4459 break;
4460 }
4461 case PseudoClass:
4462 {
4463 /*
4464 Create colormap.
4465 */
cristy0b1a7972011-10-22 22:17:02 +00004466 status=AcquireImageColormap(composite_image,number_colors,
4467 exception);
4468 if (status == MagickFalse)
cristy3ed852e2009-09-05 21:47:34 +00004469 {
4470 XDestroyImage(ximage);
4471 composite_image=DestroyImage(composite_image);
4472 return((Image *) NULL);
4473 }
4474 for (i=0; i < (int) composite_image->colors; i++)
4475 {
cristye42f6582012-02-11 17:59:50 +00004476 composite_image->colormap[colors[i].pixel].red=(double)
cristy3ed852e2009-09-05 21:47:34 +00004477 ScaleShortToQuantum(colors[i].red);
cristye42f6582012-02-11 17:59:50 +00004478 composite_image->colormap[colors[i].pixel].green=(double)
cristy3ed852e2009-09-05 21:47:34 +00004479 ScaleShortToQuantum(colors[i].green);
cristye42f6582012-02-11 17:59:50 +00004480 composite_image->colormap[colors[i].pixel].blue=(double)
cristy3ed852e2009-09-05 21:47:34 +00004481 ScaleShortToQuantum(colors[i].blue);
4482 }
4483 /*
4484 Convert X image to PseudoClass packets.
4485 */
4486 for (y=0; y < (int) composite_image->rows; y++)
4487 {
cristyc57f6942010-11-12 01:47:39 +00004488 q=QueueCacheViewAuthenticPixels(composite_view,0,(ssize_t) y,
4489 composite_image->columns,1,exception);
cristyacd2ed22011-08-30 01:44:23 +00004490 if (q == (Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00004491 break;
cristy3ed852e2009-09-05 21:47:34 +00004492 for (x=0; x < (int) composite_image->columns; x++)
4493 {
cristy4c08aed2011-07-01 19:47:50 +00004494 index=(Quantum) XGetPixel(ximage,x,y);
4495 SetPixelIndex(composite_image,index,q);
cristy803640d2011-11-17 02:11:32 +00004496 SetPixelInfoPixel(composite_image,
cristy4c08aed2011-07-01 19:47:50 +00004497 composite_image->colormap+(ssize_t) index,q);
cristyed231572011-07-14 02:18:59 +00004498 q+=GetPixelChannels(composite_image);
cristy3ed852e2009-09-05 21:47:34 +00004499 }
cristy0b1a7972011-10-22 22:17:02 +00004500 status=SyncCacheViewAuthenticPixels(composite_view,exception);
4501 if (status == MagickFalse)
cristy3ed852e2009-09-05 21:47:34 +00004502 break;
4503 }
4504 break;
4505 }
4506 }
cristyc57f6942010-11-12 01:47:39 +00004507 composite_view=DestroyCacheView(composite_view);
cristy3ed852e2009-09-05 21:47:34 +00004508 XDestroyImage(ximage);
4509 if (image == (Image *) NULL)
4510 {
4511 image=composite_image;
4512 continue;
4513 }
4514 /*
4515 Composite any children in back-to-front order.
4516 */
4517 (void) XTranslateCoordinates(display,window_info[id].window,window,0,0,
4518 &x_offset,&y_offset,&child);
4519 x_offset-=(int) crop_info.x;
4520 if (x_offset < 0)
4521 x_offset=0;
4522 y_offset-=(int) crop_info.y;
4523 if (y_offset < 0)
4524 y_offset=0;
cristyc57f6942010-11-12 01:47:39 +00004525 (void) CompositeImage(image,CopyCompositeOp,composite_image,(ssize_t)
cristye941a752011-10-15 01:52:48 +00004526 x_offset,(ssize_t) y_offset,exception);
cristy5f257b22012-03-07 00:27:29 +00004527 composite_image=DestroyImage(composite_image);
cristy3ed852e2009-09-05 21:47:34 +00004528 }
4529 /*
4530 Relinquish resources.
4531 */
4532 while (colormap_info != (ColormapInfo *) NULL)
4533 {
4534 next=colormap_info->next;
cristye941a752011-10-15 01:52:48 +00004535 colormap_info->colors=(XColor *) RelinquishMagickMemory(
4536 colormap_info->colors);
cristy3ed852e2009-09-05 21:47:34 +00004537 colormap_info=(ColormapInfo *) RelinquishMagickMemory(colormap_info);
4538 colormap_info=next;
4539 }
4540 /*
4541 Relinquish resources and restore initial state.
4542 */
4543 window_info=(WindowInfo *) RelinquishMagickMemory(window_info);
4544 max_windows=0;
4545 number_windows=0;
4546 colormap_info=(ColormapInfo *) NULL;
4547 return(image);
4548 }
4549 return((Image *) NULL);
4550}
4551
4552/*
4553%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4554% %
4555% %
4556% %
4557% X G e t W i n d o w I n f o %
4558% %
4559% %
4560% %
4561%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4562%
4563% XGetWindowInfo() initializes the XWindowInfo structure.
4564%
4565% The format of the XGetWindowInfo method is:
4566%
4567% void XGetWindowInfo(Display *display,XVisualInfo *visual_info,
4568% XStandardColormap *map_info,XPixelInfo *pixel,XFontStruct *font_info,
4569% XResourceInfo *resource_info,XWindowInfo *window)
4570% resource_info,window)
4571%
4572% A description of each parameter follows:
4573%
4574% o display: Specifies a connection to an X server; returned from
4575% XOpenDisplay.
4576%
4577% o visual_info: Specifies a pointer to a X11 XVisualInfo structure;
4578% returned from XGetVisualInfo.
4579%
4580% o map_info: If map_type is specified, this structure is initialized
4581% with info from the Standard Colormap.
4582%
4583% o pixel: Specifies a pointer to a XPixelInfo structure.
4584%
4585% o font_info: Specifies a pointer to a XFontStruct structure.
4586%
4587% o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
4588%
4589*/
cristybcbda3f2011-09-03 13:01:22 +00004590MagickPrivate void XGetWindowInfo(Display *display,XVisualInfo *visual_info,
cristy3ed852e2009-09-05 21:47:34 +00004591 XStandardColormap *map_info,XPixelInfo *pixel,XFontStruct *font_info,
4592 XResourceInfo *resource_info,XWindowInfo *window)
4593{
4594 /*
4595 Initialize window info.
4596 */
4597 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
4598 assert(display != (Display *) NULL);
4599 assert(visual_info != (XVisualInfo *) NULL);
4600 assert(map_info != (XStandardColormap *) NULL);
4601 assert(pixel != (XPixelInfo *) NULL);
4602 assert(resource_info != (XResourceInfo *) NULL);
4603 assert(window != (XWindowInfo *) NULL);
4604 if (window->id != (Window) NULL)
4605 {
4606 if (window->cursor != (Cursor) NULL)
4607 (void) XFreeCursor(display,window->cursor);
4608 if (window->busy_cursor != (Cursor) NULL)
4609 (void) XFreeCursor(display,window->busy_cursor);
4610 if (window->highlight_stipple != (Pixmap) NULL)
4611 (void) XFreePixmap(display,window->highlight_stipple);
4612 if (window->shadow_stipple != (Pixmap) NULL)
4613 (void) XFreePixmap(display,window->shadow_stipple);
4614 if (window->name == (char *) NULL)
4615 window->name=AcquireString("");
4616 if (window->icon_name == (char *) NULL)
4617 window->icon_name=AcquireString("");
4618 }
4619 else
4620 {
4621 /*
4622 Initialize these attributes just once.
4623 */
4624 window->id=(Window) NULL;
4625 if (window->name == (char *) NULL)
4626 window->name=AcquireString("");
4627 if (window->icon_name == (char *) NULL)
4628 window->icon_name=AcquireString("");
4629 window->x=XDisplayWidth(display,visual_info->screen) >> 1;
4630 window->y=XDisplayWidth(display,visual_info->screen) >> 1;
4631 window->ximage=(XImage *) NULL;
4632 window->matte_image=(XImage *) NULL;
4633 window->pixmap=(Pixmap) NULL;
4634 window->matte_pixmap=(Pixmap) NULL;
4635 window->mapped=MagickFalse;
4636 window->stasis=MagickFalse;
4637 window->shared_memory=MagickTrue;
4638 window->segment_info=(void *) NULL;
4639#if defined(MAGICKCORE_HAVE_SHARED_MEMORY)
4640 {
4641 XShmSegmentInfo
4642 *segment_info;
4643
4644 if (window->segment_info == (void *) NULL)
4645 window->segment_info=AcquireQuantumMemory(2,sizeof(*segment_info));
4646 segment_info=(XShmSegmentInfo *) window->segment_info;
4647 segment_info[0].shmid=(-1);
4648 segment_info[0].shmaddr=(char *) NULL;
4649 segment_info[1].shmid=(-1);
4650 segment_info[1].shmaddr=(char *) NULL;
4651 }
4652#endif
4653 }
4654 /*
4655 Initialize these attributes every time function is called.
4656 */
4657 window->screen=visual_info->screen;
4658 window->root=XRootWindow(display,visual_info->screen);
4659 window->visual=visual_info->visual;
4660 window->storage_class=(unsigned int) visual_info->klass;
4661 window->depth=(unsigned int) visual_info->depth;
4662 window->visual_info=visual_info;
4663 window->map_info=map_info;
4664 window->pixel_info=pixel;
4665 window->font_info=font_info;
4666 window->cursor=XCreateFontCursor(display,XC_left_ptr);
4667 window->busy_cursor=XCreateFontCursor(display,XC_watch);
4668 window->geometry=(char *) NULL;
4669 window->icon_geometry=(char *) NULL;
4670 if (resource_info->icon_geometry != (char *) NULL)
4671 (void) CloneString(&window->icon_geometry,resource_info->icon_geometry);
4672 window->crop_geometry=(char *) NULL;
cristybb503372010-05-27 20:51:26 +00004673 window->flags=(size_t) PSize;
cristy3ed852e2009-09-05 21:47:34 +00004674 window->width=1;
4675 window->height=1;
4676 window->min_width=1;
4677 window->min_height=1;
4678 window->width_inc=1;
4679 window->height_inc=1;
4680 window->border_width=resource_info->border_width;
4681 window->annotate_context=pixel->annotate_context;
4682 window->highlight_context=pixel->highlight_context;
4683 window->widget_context=pixel->widget_context;
4684 window->shadow_stipple=(Pixmap) NULL;
4685 window->highlight_stipple=(Pixmap) NULL;
4686 window->use_pixmap=MagickTrue;
4687 window->immutable=MagickFalse;
4688 window->shape=MagickFalse;
4689 window->data=0;
cristyc57f6942010-11-12 01:47:39 +00004690 window->mask=(int) (CWBackingStore | CWBackPixel | CWBackPixmap |
cristy3ed852e2009-09-05 21:47:34 +00004691 CWBitGravity | CWBorderPixel | CWColormap | CWCursor | CWDontPropagate |
4692 CWEventMask | CWOverrideRedirect | CWSaveUnder | CWWinGravity);
4693 window->attributes.background_pixel=pixel->background_color.pixel;
4694 window->attributes.background_pixmap=(Pixmap) NULL;
4695 window->attributes.bit_gravity=ForgetGravity;
4696 window->attributes.backing_store=WhenMapped;
4697 window->attributes.save_under=MagickTrue;
4698 window->attributes.border_pixel=pixel->border_color.pixel;
4699 window->attributes.colormap=map_info->colormap;
4700 window->attributes.cursor=window->cursor;
4701 window->attributes.do_not_propagate_mask=NoEventMask;
4702 window->attributes.event_mask=NoEventMask;
4703 window->attributes.override_redirect=MagickFalse;
4704 window->attributes.win_gravity=NorthWestGravity;
4705 window->orphan=MagickFalse;
4706}
4707
4708/*
4709%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4710% %
4711% %
4712% %
4713% X H i g h l i g h t E l l i p s e %
4714% %
4715% %
4716% %
4717%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4718%
4719% XHighlightEllipse() puts a border on the X server around a region defined by
4720% highlight_info.
4721%
4722% The format of the XHighlightEllipse method is:
4723%
4724% void XHighlightEllipse(Display *display,Window window,
4725% GC annotate_context,const RectangleInfo *highlight_info)
4726%
4727% A description of each parameter follows:
4728%
4729% o display: Specifies a connection to an X server; returned from
4730% XOpenDisplay.
4731%
4732% o window: Specifies a pointer to a Window structure.
4733%
4734% o annotate_context: Specifies a pointer to a GC structure.
4735%
4736% o highlight_info: Specifies a pointer to a RectangleInfo structure. It
4737% contains the extents of any highlighting rectangle.
4738%
4739*/
cristybcbda3f2011-09-03 13:01:22 +00004740MagickPrivate void XHighlightEllipse(Display *display,Window window,
cristy3ed852e2009-09-05 21:47:34 +00004741 GC annotate_context,const RectangleInfo *highlight_info)
4742{
4743 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
4744 assert(display != (Display *) NULL);
4745 assert(window != (Window) NULL);
4746 assert(annotate_context != (GC) NULL);
4747 assert(highlight_info != (RectangleInfo *) NULL);
4748 if ((highlight_info->width < 4) || (highlight_info->height < 4))
4749 return;
4750 (void) XDrawArc(display,window,annotate_context,(int) highlight_info->x,
4751 (int) highlight_info->y,(unsigned int) highlight_info->width-1,
4752 (unsigned int) highlight_info->height-1,0,360*64);
4753 (void) XDrawArc(display,window,annotate_context,(int) highlight_info->x+1,
4754 (int) highlight_info->y+1,(unsigned int) highlight_info->width-3,
4755 (unsigned int) highlight_info->height-3,0,360*64);
4756}
4757
4758/*
4759%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4760% %
4761% %
4762% %
4763% X H i g h l i g h t L i n e %
4764% %
4765% %
4766% %
4767%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4768%
4769% XHighlightLine() puts a border on the X server around a region defined by
4770% highlight_info.
4771%
4772% The format of the XHighlightLine method is:
4773%
4774% void XHighlightLine(Display *display,Window window,GC annotate_context,
4775% const XSegment *highlight_info)
4776%
4777% A description of each parameter follows:
4778%
4779% o display: Specifies a connection to an X server; returned from
4780% XOpenDisplay.
4781%
4782% o window: Specifies a pointer to a Window structure.
4783%
4784% o annotate_context: Specifies a pointer to a GC structure.
4785%
4786% o highlight_info: Specifies a pointer to a RectangleInfo structure. It
4787% contains the extents of any highlighting rectangle.
4788%
4789*/
cristybcbda3f2011-09-03 13:01:22 +00004790MagickPrivate void XHighlightLine(Display *display,Window window,
cristy3ed852e2009-09-05 21:47:34 +00004791 GC annotate_context,const XSegment *highlight_info)
4792{
4793 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
4794 assert(display != (Display *) NULL);
4795 assert(window != (Window) NULL);
4796 assert(annotate_context != (GC) NULL);
4797 assert(highlight_info != (XSegment *) NULL);
4798 (void) XDrawLine(display,window,annotate_context,highlight_info->x1,
4799 highlight_info->y1,highlight_info->x2,highlight_info->y2);
4800}
4801
4802/*
4803%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4804% %
4805% %
4806% %
4807% X H i g h l i g h t R e c t a n g l e %
4808% %
4809% %
4810% %
4811%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4812%
4813% XHighlightRectangle() puts a border on the X server around a region defined
4814% by highlight_info.
4815%
4816% The format of the XHighlightRectangle method is:
4817%
4818% void XHighlightRectangle(Display *display,Window window,
4819% GC annotate_context,const RectangleInfo *highlight_info)
4820%
4821% A description of each parameter follows:
4822%
4823% o display: Specifies a connection to an X server; returned from
4824% XOpenDisplay.
4825%
4826% o window: Specifies a pointer to a Window structure.
4827%
4828% o annotate_context: Specifies a pointer to a GC structure.
4829%
4830% o highlight_info: Specifies a pointer to a RectangleInfo structure. It
4831% contains the extents of any highlighting rectangle.
4832%
4833*/
cristybcbda3f2011-09-03 13:01:22 +00004834MagickPrivate void XHighlightRectangle(Display *display,Window window,
cristy3ed852e2009-09-05 21:47:34 +00004835 GC annotate_context,const RectangleInfo *highlight_info)
4836{
4837 assert(display != (Display *) NULL);
4838 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
4839 assert(window != (Window) NULL);
4840 assert(annotate_context != (GC) NULL);
4841 assert(highlight_info != (RectangleInfo *) NULL);
4842 if ((highlight_info->width < 4) || (highlight_info->height < 4))
4843 return;
4844 (void) XDrawRectangle(display,window,annotate_context,(int) highlight_info->x,
4845 (int) highlight_info->y,(unsigned int) highlight_info->width-1,
4846 (unsigned int) highlight_info->height-1);
4847 (void) XDrawRectangle(display,window,annotate_context,(int) highlight_info->x+
4848 1,(int) highlight_info->y+1,(unsigned int) highlight_info->width-3,
4849 (unsigned int) highlight_info->height-3);
4850}
4851
4852/*
4853%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4854% %
4855% %
4856% %
4857% X I m p o r t I m a g e %
4858% %
4859% %
4860% %
4861%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4862%
4863% XImportImage() reads an image from an X window.
4864%
4865% The format of the XImportImage method is:
4866%
cristy6710d842011-10-20 23:23:00 +00004867% Image *XImportImage(const ImageInfo *image_info,XImportInfo *ximage_info,
4868% ExceptionInfo *exception)
cristy3ed852e2009-09-05 21:47:34 +00004869%
4870% A description of each parameter follows:
4871%
4872% o image_info: the image info.
4873%
4874% o ximage_info: Specifies a pointer to an XImportInfo structure.
4875%
cristy6710d842011-10-20 23:23:00 +00004876% o exception: return any errors or warnings in this structure.
4877%
cristy3ed852e2009-09-05 21:47:34 +00004878*/
4879MagickExport Image *XImportImage(const ImageInfo *image_info,
cristy6710d842011-10-20 23:23:00 +00004880 XImportInfo *ximage_info,ExceptionInfo *exception)
cristy3ed852e2009-09-05 21:47:34 +00004881{
4882 Colormap
4883 *colormaps;
4884
4885 Display
4886 *display;
4887
4888 Image
4889 *image;
4890
4891 int
4892 number_colormaps,
4893 number_windows,
4894 x;
4895
4896 RectangleInfo
4897 crop_info;
4898
4899 Status
4900 status;
4901
4902 Window
4903 *children,
4904 client,
4905 prior_target,
4906 root,
4907 target;
4908
4909 XTextProperty
4910 window_name;
4911
4912 /*
4913 Open X server connection.
4914 */
4915 assert(image_info != (const ImageInfo *) NULL);
4916 assert(image_info->signature == MagickSignature);
4917 if (image_info->debug != MagickFalse)
4918 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
4919 image_info->filename);
4920 assert(ximage_info != (XImportInfo *) NULL);
4921 display=XOpenDisplay(image_info->server_name);
4922 if (display == (Display *) NULL)
4923 {
4924 ThrowXWindowFatalException(XServerError,"UnableToOpenXServer",
4925 XDisplayName(image_info->server_name));
4926 return((Image *) NULL);
4927 }
4928 /*
4929 Set our forgiving exception handler.
4930 */
4931 (void) XSetErrorHandler(XError);
4932 /*
4933 Select target window.
4934 */
4935 crop_info.x=0;
4936 crop_info.y=0;
4937 crop_info.width=0;
4938 crop_info.height=0;
4939 root=XRootWindow(display,XDefaultScreen(display));
4940 target=(Window) NULL;
4941 if ((image_info->filename != (char *) NULL) &&
4942 (*image_info->filename != '\0'))
4943 {
4944 if (LocaleCompare(image_info->filename,"root") == 0)
4945 target=root;
4946 else
4947 {
4948 /*
4949 Select window by ID or name.
4950 */
4951 if (isdigit((unsigned char) *image_info->filename) != 0)
4952 target=XWindowByID(display,root,(Window)
4953 strtol(image_info->filename,(char **) NULL,0));
4954 if (target == (Window) NULL)
4955 target=XWindowByName(display,root,image_info->filename);
4956 if (target == (Window) NULL)
4957 ThrowXWindowFatalException(XServerError,
4958 "NoWindowWithSpecifiedIDExists",image_info->filename);
4959 }
4960 }
4961 /*
4962 If target window is not defined, interactively select one.
4963 */
4964 prior_target=target;
4965 if (target == (Window) NULL)
4966 target=XSelectWindow(display,&crop_info);
4967 if (target == (Window) NULL)
4968 ThrowXWindowFatalException(XServerError,"UnableToReadXWindowImage",
4969 image_info->filename);
4970 client=target; /* obsolete */
4971 if (target != root)
4972 {
4973 unsigned int
4974 d;
4975
4976 status=XGetGeometry(display,target,&root,&x,&x,&d,&d,&d,&d);
4977 if (status != False)
4978 {
4979 for ( ; ; )
4980 {
4981 Window
4982 parent;
4983
4984 /*
4985 Find window manager frame.
4986 */
4987 status=XQueryTree(display,target,&root,&parent,&children,&d);
4988 if ((status != False) && (children != (Window *) NULL))
4989 (void) XFree((char *) children);
4990 if ((status == False) || (parent == (Window) NULL) ||
4991 (parent == root))
4992 break;
4993 target=parent;
4994 }
4995 /*
4996 Get client window.
4997 */
4998 client=XClientWindow(display,target);
4999 if (ximage_info->frame == MagickFalse)
5000 target=client;
5001 if ((ximage_info->frame == MagickFalse) &&
5002 (prior_target != MagickFalse))
5003 target=prior_target;
cristy3ed852e2009-09-05 21:47:34 +00005004 }
5005 }
5006 if (ximage_info->screen)
5007 {
5008 int
5009 y;
5010
5011 Window
5012 child;
5013
5014 XWindowAttributes
5015 window_attributes;
5016
5017 /*
5018 Obtain window image directly from screen.
5019 */
5020 status=XGetWindowAttributes(display,target,&window_attributes);
5021 if (status == False)
5022 {
5023 ThrowXWindowFatalException(XServerError,
5024 "UnableToReadXWindowAttributes",image_info->filename);
5025 (void) XCloseDisplay(display);
5026 return((Image *) NULL);
5027 }
5028 (void) XTranslateCoordinates(display,target,root,0,0,&x,&y,&child);
cristyc57f6942010-11-12 01:47:39 +00005029 crop_info.x=(ssize_t) x;
5030 crop_info.y=(ssize_t) y;
cristybb503372010-05-27 20:51:26 +00005031 crop_info.width=(size_t) window_attributes.width;
5032 crop_info.height=(size_t) window_attributes.height;
cristy553743c2010-03-03 15:04:17 +00005033 if (ximage_info->borders != 0)
cristy3ed852e2009-09-05 21:47:34 +00005034 {
5035 /*
5036 Include border in image.
5037 */
5038 crop_info.x-=window_attributes.border_width;
5039 crop_info.y-=window_attributes.border_width;
5040 crop_info.width+=window_attributes.border_width << 1;
5041 crop_info.height+=window_attributes.border_width << 1;
5042 }
5043 target=root;
5044 }
5045 /*
5046 If WM_COLORMAP_WINDOWS property is set or multiple colormaps, descend.
5047 */
5048 number_windows=0;
5049 status=XGetWMColormapWindows(display,target,&children,&number_windows);
5050 if ((status == True) && (number_windows > 0))
5051 {
5052 ximage_info->descend=MagickTrue;
5053 (void) XFree ((char *) children);
5054 }
5055 colormaps=XListInstalledColormaps(display,target,&number_colormaps);
5056 if (number_colormaps > 0)
5057 {
5058 if (number_colormaps > 1)
5059 ximage_info->descend=MagickTrue;
5060 (void) XFree((char *) colormaps);
5061 }
5062 /*
5063 Alert the user not to alter the screen.
5064 */
5065 if (ximage_info->silent == MagickFalse)
5066 (void) XBell(display,0);
5067 /*
5068 Get image by window id.
5069 */
5070 (void) XGrabServer(display);
5071 image=XGetWindowImage(display,target,ximage_info->borders,
cristy6710d842011-10-20 23:23:00 +00005072 ximage_info->descend ? 1U : 0U,exception);
cristy3ed852e2009-09-05 21:47:34 +00005073 (void) XUngrabServer(display);
5074 if (image == (Image *) NULL)
5075 ThrowXWindowFatalException(XServerError,"UnableToReadXWindowImage",
5076 image_info->filename)
5077 else
5078 {
5079 (void) CopyMagickString(image->filename,image_info->filename,
5080 MaxTextExtent);
5081 if ((crop_info.width != 0) && (crop_info.height != 0))
5082 {
5083 Image
5084 *clone_image,
5085 *crop_image;
5086
5087 /*
5088 Crop image as defined by the cropping rectangle.
5089 */
cristy6710d842011-10-20 23:23:00 +00005090 clone_image=CloneImage(image,0,0,MagickTrue,exception);
cristy3ed852e2009-09-05 21:47:34 +00005091 if (clone_image != (Image *) NULL)
5092 {
cristy6710d842011-10-20 23:23:00 +00005093 crop_image=CropImage(clone_image,&crop_info,exception);
cristy3ed852e2009-09-05 21:47:34 +00005094 if (crop_image != (Image *) NULL)
5095 {
5096 image=DestroyImage(image);
5097 image=crop_image;
5098 }
5099 }
5100 }
5101 status=XGetWMName(display,target,&window_name);
5102 if (status == True)
5103 {
5104 if ((image_info->filename != (char *) NULL) &&
5105 (*image_info->filename == '\0'))
5106 (void) CopyMagickString(image->filename,(char *) window_name.value,
5107 (size_t) window_name.nitems+1);
5108 (void) XFree((void *) window_name.value);
5109 }
5110 }
5111 if (ximage_info->silent == MagickFalse)
5112 {
5113 /*
5114 Alert the user we're done.
5115 */
5116 (void) XBell(display,0);
5117 (void) XBell(display,0);
5118 }
5119 (void) XCloseDisplay(display);
5120 return(image);
5121}
5122
5123/*
5124%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5125% %
5126% %
5127% %
5128% X I n i t i a l i z e W i n d o w s %
5129% %
5130% %
5131% %
5132%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5133%
5134% XInitializeWindows() initializes the XWindows structure.
5135%
5136% The format of the XInitializeWindows method is:
5137%
5138% XWindows *XInitializeWindows(Display *display,
5139% XResourceInfo *resource_info)
5140%
5141% A description of each parameter follows:
5142%
5143% o windows: XInitializeWindows returns a pointer to a XWindows structure.
5144%
5145% o display: Specifies a connection to an X server; returned from
5146% XOpenDisplay.
5147%
5148% o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
5149%
5150*/
cristybcbda3f2011-09-03 13:01:22 +00005151MagickPrivate XWindows *XInitializeWindows(Display *display,
cristy3ed852e2009-09-05 21:47:34 +00005152 XResourceInfo *resource_info)
5153{
5154 Window
5155 root_window;
5156
5157 XWindows
5158 *windows;
5159
5160 /*
5161 Allocate windows structure.
5162 */
cristy73bd4a52010-10-05 11:24:23 +00005163 windows=(XWindows *) AcquireMagickMemory(sizeof(*windows));
cristy3ed852e2009-09-05 21:47:34 +00005164 if (windows == (XWindows *) NULL)
5165 {
5166 ThrowXWindowFatalException(XServerFatalError,"MemoryAllocationFailed",
5167 "...");
5168 return((XWindows *) NULL);
5169 }
5170 (void) ResetMagickMemory(windows,0,sizeof(*windows));
5171 windows->pixel_info=(XPixelInfo *) AcquireMagickMemory(
5172 sizeof(*windows->pixel_info));
5173 windows->icon_pixel=(XPixelInfo *) AcquireMagickMemory(
5174 sizeof(*windows->icon_pixel));
5175 windows->icon_resources=(XResourceInfo *) AcquireMagickMemory(
5176 sizeof(*windows->icon_resources));
5177 if ((windows->pixel_info == (XPixelInfo *) NULL) ||
5178 (windows->icon_pixel == (XPixelInfo *) NULL) ||
5179 (windows->icon_resources == (XResourceInfo *) NULL))
5180 {
5181 ThrowXWindowFatalException(XServerFatalError,"MemoryAllocationFailed",
5182 "...");
5183 return((XWindows *) NULL);
5184 }
5185 /*
5186 Initialize windows structure.
5187 */
5188 windows->display=display;
5189 windows->wm_protocols=XInternAtom(display,"WM_PROTOCOLS",MagickFalse);
5190 windows->wm_delete_window=XInternAtom(display,"WM_DELETE_WINDOW",MagickFalse);
5191 windows->wm_take_focus=XInternAtom(display,"WM_TAKE_FOCUS",MagickFalse);
5192 windows->im_protocols=XInternAtom(display,"IM_PROTOCOLS",MagickFalse);
5193 windows->im_remote_command=
5194 XInternAtom(display,"IM_REMOTE_COMMAND",MagickFalse);
5195 windows->im_update_widget=XInternAtom(display,"IM_UPDATE_WIDGET",MagickFalse);
5196 windows->im_update_colormap=
5197 XInternAtom(display,"IM_UPDATE_COLORMAP",MagickFalse);
5198 windows->im_former_image=XInternAtom(display,"IM_FORMER_IMAGE",MagickFalse);
5199 windows->im_next_image=XInternAtom(display,"IM_NEXT_IMAGE",MagickFalse);
5200 windows->im_retain_colors=XInternAtom(display,"IM_RETAIN_COLORS",MagickFalse);
5201 windows->im_exit=XInternAtom(display,"IM_EXIT",MagickFalse);
5202 windows->dnd_protocols=XInternAtom(display,"DndProtocol",MagickFalse);
cristy0157aea2010-04-24 21:12:18 +00005203#if defined(MAGICKCORE_WINDOWS_SUPPORT)
cristy3ed852e2009-09-05 21:47:34 +00005204 (void) XSynchronize(display,IsWindows95());
5205#endif
5206 if (IsEventLogging())
5207 {
5208 (void) XSynchronize(display,MagickTrue);
5209 (void) LogMagickEvent(X11Event,GetMagickModule(),"Version: %s",
cristybb503372010-05-27 20:51:26 +00005210 GetMagickVersion((size_t *) NULL));
cristy3ed852e2009-09-05 21:47:34 +00005211 (void) LogMagickEvent(X11Event,GetMagickModule(),"Protocols:");
5212 (void) LogMagickEvent(X11Event,GetMagickModule(),
5213 " Window Manager: 0x%lx",windows->wm_protocols);
5214 (void) LogMagickEvent(X11Event,GetMagickModule(),
5215 " delete window: 0x%lx",windows->wm_delete_window);
5216 (void) LogMagickEvent(X11Event,GetMagickModule()," take focus: 0x%lx",
5217 windows->wm_take_focus);
5218 (void) LogMagickEvent(X11Event,GetMagickModule()," ImageMagick: 0x%lx",
5219 windows->im_protocols);
5220 (void) LogMagickEvent(X11Event,GetMagickModule(),
5221 " remote command: 0x%lx",windows->im_remote_command);
5222 (void) LogMagickEvent(X11Event,GetMagickModule(),
5223 " update widget: 0x%lx",windows->im_update_widget);
5224 (void) LogMagickEvent(X11Event,GetMagickModule(),
5225 " update colormap: 0x%lx",windows->im_update_colormap);
5226 (void) LogMagickEvent(X11Event,GetMagickModule(),
5227 " former image: 0x%lx",windows->im_former_image);
5228 (void) LogMagickEvent(X11Event,GetMagickModule()," next image: 0x%lx",
5229 windows->im_next_image);
5230 (void) LogMagickEvent(X11Event,GetMagickModule(),
5231 " retain colors: 0x%lx",windows->im_retain_colors);
5232 (void) LogMagickEvent(X11Event,GetMagickModule()," exit: 0x%lx",
5233 windows->im_exit);
5234 (void) LogMagickEvent(X11Event,GetMagickModule()," Drag and Drop: 0x%lx",
5235 windows->dnd_protocols);
5236 }
5237 /*
5238 Allocate standard colormap.
5239 */
5240 windows->map_info=XAllocStandardColormap();
5241 windows->icon_map=XAllocStandardColormap();
5242 if ((windows->map_info == (XStandardColormap *) NULL) ||
5243 (windows->icon_map == (XStandardColormap *) NULL))
5244 ThrowXWindowFatalException(ResourceLimitFatalError,
5245 "MemoryAllocationFailed","...");
5246 windows->map_info->colormap=(Colormap) NULL;
5247 windows->icon_map->colormap=(Colormap) NULL;
cristyf2faecf2010-05-28 19:19:36 +00005248 windows->pixel_info->pixels=(unsigned long *) NULL;
cristy3ed852e2009-09-05 21:47:34 +00005249 windows->pixel_info->annotate_context=(GC) NULL;
5250 windows->pixel_info->highlight_context=(GC) NULL;
5251 windows->pixel_info->widget_context=(GC) NULL;
5252 windows->font_info=(XFontStruct *) NULL;
5253 windows->icon_pixel->annotate_context=(GC) NULL;
cristyf2faecf2010-05-28 19:19:36 +00005254 windows->icon_pixel->pixels=(unsigned long *) NULL;
cristy3ed852e2009-09-05 21:47:34 +00005255 /*
5256 Allocate visual.
5257 */
5258 *windows->icon_resources=(*resource_info);
5259 windows->icon_resources->visual_type=(char *) "default";
5260 windows->icon_resources->colormap=SharedColormap;
5261 windows->visual_info=
5262 XBestVisualInfo(display,windows->map_info,resource_info);
5263 windows->icon_visual=
5264 XBestVisualInfo(display,windows->icon_map,windows->icon_resources);
5265 if ((windows->visual_info == (XVisualInfo *) NULL) ||
5266 (windows->icon_visual == (XVisualInfo *) NULL))
5267 ThrowXWindowFatalException(XServerFatalError,"UnableToGetVisual",
5268 resource_info->visual_type);
5269 if (IsEventLogging())
5270 {
5271 (void) LogMagickEvent(X11Event,GetMagickModule(),"Visual:");
5272 (void) LogMagickEvent(X11Event,GetMagickModule()," visual id: 0x%lx",
5273 windows->visual_info->visualid);
5274 (void) LogMagickEvent(X11Event,GetMagickModule()," class: %s",
5275 XVisualClassName(windows->visual_info->klass));
5276 (void) LogMagickEvent(X11Event,GetMagickModule()," depth: %d planes",
5277 windows->visual_info->depth);
5278 (void) LogMagickEvent(X11Event,GetMagickModule(),
5279 " size of colormap: %d entries",windows->visual_info->colormap_size);
5280 (void) LogMagickEvent(X11Event,GetMagickModule(),
5281 " red, green, blue masks: 0x%lx 0x%lx 0x%lx",
5282 windows->visual_info->red_mask,windows->visual_info->green_mask,
5283 windows->visual_info->blue_mask);
5284 (void) LogMagickEvent(X11Event,GetMagickModule(),
5285 " significant bits in color: %d bits",
5286 windows->visual_info->bits_per_rgb);
5287 }
5288 /*
5289 Allocate class and manager hints.
5290 */
5291 windows->class_hints=XAllocClassHint();
5292 windows->manager_hints=XAllocWMHints();
5293 if ((windows->class_hints == (XClassHint *) NULL) ||
5294 (windows->manager_hints == (XWMHints *) NULL))
5295 ThrowXWindowFatalException(ResourceLimitFatalError,
5296 "MemoryAllocationFailed","...");
5297 /*
5298 Determine group leader if we have one.
5299 */
5300 root_window=XRootWindow(display,windows->visual_info->screen);
5301 windows->group_leader.id=(Window) NULL;
5302 if (resource_info->window_group != (char *) NULL)
5303 {
5304 if (isdigit((unsigned char) *resource_info->window_group) != 0)
5305 windows->group_leader.id=XWindowByID(display,root_window,(Window)
5306 strtol((char *) resource_info->window_group,(char **) NULL,0));
5307 if (windows->group_leader.id == (Window) NULL)
5308 windows->group_leader.id=
5309 XWindowByName(display,root_window,resource_info->window_group);
5310 }
5311 return(windows);
5312}
5313
5314/*
5315%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5316% %
5317% %
5318% %
5319% X M a k e C u r s o r %
5320% %
5321% %
5322% %
5323%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5324%
5325% XMakeCursor() creates a crosshairs X11 cursor.
5326%
5327% The format of the XMakeCursor method is:
5328%
5329% Cursor XMakeCursor(Display *display,Window window,Colormap colormap,
5330% char *background_color,char *foreground_color)
5331%
5332% A description of each parameter follows:
5333%
5334% o display: Specifies a connection to an X server; returned from
5335% XOpenDisplay.
5336%
5337% o window: Specifies the ID of the window for which the cursor is
5338% assigned.
5339%
5340% o colormap: Specifies the ID of the colormap from which the background
5341% and foreground color will be retrieved.
5342%
5343% o background_color: Specifies the color to use for the cursor background.
5344%
5345% o foreground_color: Specifies the color to use for the cursor foreground.
5346%
5347*/
cristybcbda3f2011-09-03 13:01:22 +00005348MagickPrivate Cursor XMakeCursor(Display *display,Window window,
cristy3ed852e2009-09-05 21:47:34 +00005349 Colormap colormap,char *background_color,char *foreground_color)
5350{
5351#define scope_height 17
5352#define scope_x_hot 8
5353#define scope_y_hot 8
5354#define scope_width 17
5355
5356 static const unsigned char
5357 scope_bits[] =
5358 {
5359 0x80, 0x03, 0x00, 0x80, 0x02, 0x00, 0x80, 0x02, 0x00, 0x80, 0x02,
5360 0x00, 0x80, 0x02, 0x00, 0x80, 0x02, 0x00, 0x80, 0x02, 0x00, 0x7f,
5361 0xfc, 0x01, 0x01, 0x00, 0x01, 0x7f, 0xfc, 0x01, 0x80, 0x02, 0x00,
5362 0x80, 0x02, 0x00, 0x80, 0x02, 0x00, 0x80, 0x02, 0x00, 0x80, 0x02,
5363 0x00, 0x80, 0x02, 0x00, 0x80, 0x03, 0x00
5364 },
5365 scope_mask_bits[] =
5366 {
5367 0xc0, 0x07, 0x00, 0xc0, 0x07, 0x00, 0xc0, 0x06, 0x00, 0xc0, 0x06,
5368 0x00, 0xc0, 0x06, 0x00, 0xc0, 0x06, 0x00, 0xff, 0xfe, 0x01, 0x7f,
5369 0xfc, 0x01, 0x03, 0x80, 0x01, 0x7f, 0xfc, 0x01, 0xff, 0xfe, 0x01,
5370 0xc0, 0x06, 0x00, 0xc0, 0x06, 0x00, 0xc0, 0x06, 0x00, 0xc0, 0x06,
5371 0x00, 0xc0, 0x07, 0x00, 0xc0, 0x07, 0x00
5372 };
5373
5374 Cursor
5375 cursor;
5376
5377 Pixmap
5378 mask,
5379 source;
5380
5381 XColor
5382 background,
5383 foreground;
5384
5385 assert(display != (Display *) NULL);
5386 assert(window != (Window) NULL);
5387 assert(colormap != (Colormap) NULL);
5388 assert(background_color != (char *) NULL);
5389 assert(foreground_color != (char *) NULL);
5390 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",background_color);
5391 source=XCreateBitmapFromData(display,window,(char *) scope_bits,scope_width,
5392 scope_height);
5393 mask=XCreateBitmapFromData(display,window,(char *) scope_mask_bits,
5394 scope_width,scope_height);
5395 if ((source == (Pixmap) NULL) || (mask == (Pixmap) NULL))
5396 {
5397 ThrowXWindowFatalException(XServerError,"UnableToCreatePixmap","...");
5398 return((Cursor) NULL);
5399 }
5400 (void) XParseColor(display,colormap,background_color,&background);
5401 (void) XParseColor(display,colormap,foreground_color,&foreground);
5402 cursor=XCreatePixmapCursor(display,source,mask,&foreground,&background,
5403 scope_x_hot,scope_y_hot);
5404 (void) XFreePixmap(display,source);
5405 (void) XFreePixmap(display,mask);
5406 return(cursor);
5407}
5408
5409/*
5410%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5411% %
5412% %
5413% %
5414% X M a k e I m a g e %
5415% %
5416% %
5417% %
5418%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5419%
5420% XMakeImage() creates an X11 image. If the image size differs from the X11
5421% image size, the image is first resized.
5422%
5423% The format of the XMakeImage method is:
5424%
5425% MagickBooleanType XMakeImage(Display *display,
5426% const XResourceInfo *resource_info,XWindowInfo *window,Image *image,
cristy051718b2011-08-28 22:49:25 +00005427% unsigned int width,unsigned int height,ExceptionInfo *exception)
cristy3ed852e2009-09-05 21:47:34 +00005428%
5429% A description of each parameter follows:
5430%
5431% o display: Specifies a connection to an X server; returned from
5432% XOpenDisplay.
5433%
5434% o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
5435%
5436% o window: Specifies a pointer to a XWindowInfo structure.
5437%
5438% o image: the image.
5439%
5440% o width: Specifies the width in pixels of the rectangular area to
5441% display.
5442%
5443% o height: Specifies the height in pixels of the rectangular area to
5444% display.
5445%
cristy051718b2011-08-28 22:49:25 +00005446% o exception: return any errors or warnings in this structure.
5447%
cristy3ed852e2009-09-05 21:47:34 +00005448*/
cristybcbda3f2011-09-03 13:01:22 +00005449MagickPrivate MagickBooleanType XMakeImage(Display *display,
cristy3ed852e2009-09-05 21:47:34 +00005450 const XResourceInfo *resource_info,XWindowInfo *window,Image *image,
cristy051718b2011-08-28 22:49:25 +00005451 unsigned int width,unsigned int height,ExceptionInfo *exception)
cristy3ed852e2009-09-05 21:47:34 +00005452{
5453#define CheckOverflowException(length,width,height) \
5454 (((height) != 0) && ((length)/((size_t) height) != ((size_t) width)))
5455
5456 int
5457 depth,
5458 format;
5459
5460 size_t
5461 length;
5462
5463 XImage
5464 *matte_image,
5465 *ximage;
5466
5467 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
5468 assert(display != (Display *) NULL);
5469 assert(resource_info != (XResourceInfo *) NULL);
5470 assert(window != (XWindowInfo *) NULL);
5471 assert(width != 0);
5472 assert(height != 0);
5473 if ((window->width == 0) || (window->height == 0))
5474 return(MagickFalse);
5475 /*
5476 Apply user transforms to the image.
5477 */
5478 (void) XCheckDefineCursor(display,window->id,window->busy_cursor);
5479 (void) XFlush(display);
5480 depth=(int) window->depth;
5481 if (window->destroy)
5482 window->image=DestroyImage(window->image);
5483 window->image=image;
5484 window->destroy=MagickFalse;
5485 if (window->image != (Image *) NULL)
5486 {
5487 if (window->crop_geometry != (char *) NULL)
5488 {
5489 Image
5490 *crop_image;
5491
5492 RectangleInfo
5493 crop_info;
5494
5495 /*
5496 Crop image.
5497 */
5498 window->image->page.x=0;
5499 window->image->page.y=0;
5500 (void) ParsePageGeometry(window->image,window->crop_geometry,
cristy6710d842011-10-20 23:23:00 +00005501 &crop_info,exception);
5502 crop_image=CropImage(window->image,&crop_info,exception);
cristy3ed852e2009-09-05 21:47:34 +00005503 if (crop_image != (Image *) NULL)
5504 {
5505 if (window->image != image)
5506 window->image=DestroyImage(window->image);
5507 window->image=crop_image;
5508 window->destroy=MagickTrue;
5509 }
5510 }
5511 if ((width != (unsigned int) window->image->columns) ||
5512 (height != (unsigned int) window->image->rows))
5513 {
5514 Image
5515 *resize_image;
5516
5517 /*
5518 Resize image.
5519 */
5520 resize_image=NewImageList();
5521 if (window->pixel_info->colors != 0)
cristy6710d842011-10-20 23:23:00 +00005522 resize_image=SampleImage(window->image,width,height,exception);
cristy3ed852e2009-09-05 21:47:34 +00005523 else
cristy6710d842011-10-20 23:23:00 +00005524 resize_image=ThumbnailImage(window->image,width,height,exception);
cristy3ed852e2009-09-05 21:47:34 +00005525 if (resize_image != (Image *) NULL)
5526 {
5527 if (window->image != image)
5528 window->image=DestroyImage(window->image);
5529 window->image=resize_image;
5530 window->destroy=MagickTrue;
5531 }
5532 }
5533 width=(unsigned int) window->image->columns;
cristybb503372010-05-27 20:51:26 +00005534 assert((size_t) width == window->image->columns);
cristy3ed852e2009-09-05 21:47:34 +00005535 height=(unsigned int) window->image->rows;
cristybb503372010-05-27 20:51:26 +00005536 assert((size_t) height == window->image->rows);
cristy3ed852e2009-09-05 21:47:34 +00005537 }
5538 /*
5539 Create X image.
5540 */
5541 ximage=(XImage *) NULL;
5542 format=(depth == 1) ? XYBitmap : ZPixmap;
5543#if defined(MAGICKCORE_HAVE_SHARED_MEMORY)
5544 if (window->shared_memory != MagickFalse)
5545 {
5546 XShmSegmentInfo
5547 *segment_info;
5548
5549 segment_info=(XShmSegmentInfo *) window->segment_info;
5550 segment_info[1].shmid=(-1);
5551 segment_info[1].shmaddr=(char *) NULL;
5552 ximage=XShmCreateImage(display,window->visual,(unsigned int) depth,format,
5553 (char *) NULL,&segment_info[1],width,height);
5554 if (ximage == (XImage *) NULL)
5555 window->shared_memory=MagickFalse;
5556 length=(size_t) ximage->bytes_per_line*ximage->height;
5557 if (CheckOverflowException(length,ximage->bytes_per_line,ximage->height))
5558 window->shared_memory=MagickFalse;
5559 if (window->shared_memory != MagickFalse)
5560 segment_info[1].shmid=shmget(IPC_PRIVATE,length,IPC_CREAT | 0777);
5561 if (window->shared_memory != MagickFalse)
5562 segment_info[1].shmaddr=(char *) shmat(segment_info[1].shmid,0,0);
5563 if (segment_info[1].shmid < 0)
5564 window->shared_memory=MagickFalse;
5565 if (window->shared_memory != MagickFalse)
5566 (void) shmctl(segment_info[1].shmid,IPC_RMID,0);
5567 else
5568 {
5569 if (ximage != (XImage *) NULL)
5570 XDestroyImage(ximage);
5571 ximage=(XImage *) NULL;
5572 if (segment_info[1].shmaddr)
5573 {
5574 (void) shmdt(segment_info[1].shmaddr);
5575 segment_info[1].shmaddr=(char *) NULL;
5576 }
5577 if (segment_info[1].shmid >= 0)
5578 {
5579 (void) shmctl(segment_info[1].shmid,IPC_RMID,0);
5580 segment_info[1].shmid=(-1);
5581 }
5582 }
5583 }
5584#endif
5585 /*
5586 Allocate X image pixel data.
5587 */
5588#if defined(MAGICKCORE_HAVE_SHARED_MEMORY)
5589 if (window->shared_memory)
5590 {
5591 Status
5592 status;
5593
5594 XShmSegmentInfo
5595 *segment_info;
5596
5597 (void) XSync(display,MagickFalse);
5598 xerror_alert=MagickFalse;
5599 segment_info=(XShmSegmentInfo *) window->segment_info;
5600 ximage->data=segment_info[1].shmaddr;
5601 segment_info[1].readOnly=MagickFalse;
5602 status=XShmAttach(display,&segment_info[1]);
5603 if (status != False)
5604 (void) XSync(display,MagickFalse);
5605 if ((status == False) || (xerror_alert != MagickFalse))
5606 {
5607 window->shared_memory=MagickFalse;
5608 if (status != False)
5609 XShmDetach(display,&segment_info[1]);
5610 if (ximage != (XImage *) NULL)
5611 {
5612 ximage->data=NULL;
5613 XDestroyImage(ximage);
5614 ximage=(XImage *) NULL;
5615 }
5616 if (segment_info[1].shmid >= 0)
5617 {
5618 if (segment_info[1].shmaddr != NULL)
5619 (void) shmdt(segment_info[1].shmaddr);
5620 (void) shmctl(segment_info[1].shmid,IPC_RMID,0);
5621 segment_info[1].shmid=(-1);
5622 segment_info[1].shmaddr=(char *) NULL;
5623 }
5624 }
5625 }
5626#endif
5627 if (window->shared_memory == MagickFalse)
5628 ximage=XCreateImage(display,window->visual,(unsigned int) depth,format,0,
5629 (char *) NULL,width,height,XBitmapPad(display),0);
5630 if (ximage == (XImage *) NULL)
5631 {
5632 /*
5633 Unable to create X image.
5634 */
5635 (void) XCheckDefineCursor(display,window->id,window->cursor);
5636 return(MagickFalse);
5637 }
5638 length=(size_t) ximage->bytes_per_line*ximage->height;
5639 if (IsEventLogging())
5640 {
5641 (void) LogMagickEvent(X11Event,GetMagickModule(),"XImage:");
5642 (void) LogMagickEvent(X11Event,GetMagickModule()," width, height: %dx%d",
5643 ximage->width,ximage->height);
5644 (void) LogMagickEvent(X11Event,GetMagickModule()," format: %d",
5645 ximage->format);
5646 (void) LogMagickEvent(X11Event,GetMagickModule()," byte order: %d",
5647 ximage->byte_order);
5648 (void) LogMagickEvent(X11Event,GetMagickModule(),
5649 " bitmap unit, bit order, pad: %d %d %d",ximage->bitmap_unit,
5650 ximage->bitmap_bit_order,ximage->bitmap_pad);
5651 (void) LogMagickEvent(X11Event,GetMagickModule()," depth: %d",
5652 ximage->depth);
5653 (void) LogMagickEvent(X11Event,GetMagickModule()," bytes per line: %d",
5654 ximage->bytes_per_line);
5655 (void) LogMagickEvent(X11Event,GetMagickModule()," bits per pixel: %d",
5656 ximage->bits_per_pixel);
5657 (void) LogMagickEvent(X11Event,GetMagickModule(),
5658 " red, green, blue masks: 0x%lx 0x%lx 0x%lx",ximage->red_mask,
5659 ximage->green_mask,ximage->blue_mask);
5660 }
5661 if (window->shared_memory == MagickFalse)
5662 {
5663 if (ximage->format != XYBitmap)
5664 ximage->data=(char *) AcquireQuantumMemory((size_t)
5665 ximage->bytes_per_line,(size_t) ximage->height);
5666 else
5667 ximage->data=(char *) AcquireQuantumMemory((size_t)
5668 ximage->bytes_per_line*ximage->depth,(size_t) ximage->height);
5669 }
5670 if (ximage->data == (char *) NULL)
5671 {
5672 /*
5673 Unable to allocate pixel data.
5674 */
5675 XDestroyImage(ximage);
5676 ximage=(XImage *) NULL;
5677 (void) XCheckDefineCursor(display,window->id,window->cursor);
5678 return(MagickFalse);
5679 }
5680 if (window->ximage != (XImage *) NULL)
5681 {
5682 /*
5683 Destroy previous X image.
5684 */
5685 length=(size_t) window->ximage->bytes_per_line*window->ximage->height;
5686#if defined(MAGICKCORE_HAVE_SHARED_MEMORY)
5687 if (window->segment_info != (XShmSegmentInfo *) NULL)
5688 {
5689 XShmSegmentInfo
5690 *segment_info;
5691
5692 segment_info=(XShmSegmentInfo *) window->segment_info;
5693 if (segment_info[0].shmid >= 0)
5694 {
5695 (void) XSync(display,MagickFalse);
5696 (void) XShmDetach(display,&segment_info[0]);
5697 (void) XSync(display,MagickFalse);
5698 if (segment_info[0].shmaddr != (char *) NULL)
5699 (void) shmdt(segment_info[0].shmaddr);
5700 (void) shmctl(segment_info[0].shmid,IPC_RMID,0);
5701 segment_info[0].shmid=(-1);
5702 segment_info[0].shmaddr=(char *) NULL;
5703 window->ximage->data=(char *) NULL;
5704 }
5705 }
5706#endif
5707 if (window->ximage->data != (char *) NULL)
5708 free(window->ximage->data);
5709 window->ximage->data=(char *) NULL;
5710 XDestroyImage(window->ximage);
5711 window->ximage=(XImage *) NULL;
5712 }
5713#if defined(MAGICKCORE_HAVE_SHARED_MEMORY)
5714 if (window->segment_info != (XShmSegmentInfo *) NULL)
5715 {
5716 XShmSegmentInfo
5717 *segment_info;
5718
5719 segment_info=(XShmSegmentInfo *) window->segment_info;
5720 segment_info[0]=segment_info[1];
5721 }
5722#endif
5723 window->ximage=ximage;
5724 matte_image=(XImage *) NULL;
5725 if ((window->shape != MagickFalse) && (window->image != (Image *) NULL))
5726 if ((window->image->matte != MagickFalse) &&
cristyc57f6942010-11-12 01:47:39 +00005727 ((int) width <= XDisplayWidth(display,window->screen)) &&
5728 ((int) height <= XDisplayHeight(display,window->screen)))
cristy3ed852e2009-09-05 21:47:34 +00005729 {
5730 /*
5731 Create matte image.
5732 */
5733 matte_image=XCreateImage(display,window->visual,1,XYBitmap,0,
5734 (char *) NULL,width,height,XBitmapPad(display),0);
5735 if (IsEventLogging())
5736 {
5737 (void) LogMagickEvent(X11Event,GetMagickModule(),"Matte Image:");
5738 (void) LogMagickEvent(X11Event,GetMagickModule(),
5739 " width, height: %dx%d",matte_image->width,matte_image->height);
5740 }
5741 if (matte_image != (XImage *) NULL)
5742 {
5743 /*
5744 Allocate matte image pixel data.
5745 */
5746 matte_image->data=(char *) AcquireQuantumMemory((size_t)
5747 matte_image->bytes_per_line*matte_image->depth,
5748 (size_t) matte_image->height);
5749 if (matte_image->data == (char *) NULL)
5750 {
5751 XDestroyImage(matte_image);
5752 matte_image=(XImage *) NULL;
5753 }
5754 }
5755 }
5756 if (window->matte_image != (XImage *) NULL)
5757 {
5758 /*
5759 Free matte image.
5760 */
5761 if (window->matte_image->data != (char *) NULL)
5762 free(window->matte_image->data);
5763 window->matte_image->data=(char *) NULL;
5764 XDestroyImage(window->matte_image);
5765 window->matte_image=(XImage *) NULL;
5766 }
5767 window->matte_image=matte_image;
5768 if (window->matte_pixmap != (Pixmap) NULL)
5769 {
5770 (void) XFreePixmap(display,window->matte_pixmap);
5771 window->matte_pixmap=(Pixmap) NULL;
5772#if defined(MAGICKCORE_HAVE_SHAPE)
5773 if (window->shape != MagickFalse)
5774 XShapeCombineMask(display,window->id,ShapeBounding,0,0,None,ShapeSet);
5775#endif
5776 }
5777 window->stasis=MagickFalse;
5778 /*
5779 Convert pixels to X image data.
5780 */
5781 if (window->image != (Image *) NULL)
5782 {
5783 if ((ximage->byte_order == LSBFirst) || ((ximage->format == XYBitmap) &&
5784 (ximage->bitmap_bit_order == LSBFirst)))
5785 XMakeImageLSBFirst(resource_info,window,window->image,ximage,
cristye941a752011-10-15 01:52:48 +00005786 matte_image,exception);
cristy3ed852e2009-09-05 21:47:34 +00005787 else
5788 XMakeImageMSBFirst(resource_info,window,window->image,ximage,
cristye941a752011-10-15 01:52:48 +00005789 matte_image,exception);
cristy3ed852e2009-09-05 21:47:34 +00005790 }
5791 if (window->matte_image != (XImage *) NULL)
5792 {
5793 /*
5794 Create matte pixmap.
5795 */
5796 window->matte_pixmap=XCreatePixmap(display,window->id,width,height,1);
5797 if (window->matte_pixmap != (Pixmap) NULL)
5798 {
5799 GC
5800 graphics_context;
5801
5802 XGCValues
5803 context_values;
5804
5805 /*
5806 Copy matte image to matte pixmap.
5807 */
cristy4c08aed2011-07-01 19:47:50 +00005808 context_values.background=0;
5809 context_values.foreground=1;
cristy3ed852e2009-09-05 21:47:34 +00005810 graphics_context=XCreateGC(display,window->matte_pixmap,
cristybb503372010-05-27 20:51:26 +00005811 (size_t) (GCBackground | GCForeground),&context_values);
cristy3ed852e2009-09-05 21:47:34 +00005812 (void) XPutImage(display,window->matte_pixmap,graphics_context,
5813 window->matte_image,0,0,0,0,width,height);
5814 (void) XFreeGC(display,graphics_context);
5815#if defined(MAGICKCORE_HAVE_SHAPE)
5816 if (window->shape != MagickFalse)
5817 XShapeCombineMask(display,window->id,ShapeBounding,0,0,
5818 window->matte_pixmap,ShapeSet);
5819#endif
5820 }
5821 }
5822 (void) XMakePixmap(display,resource_info,window);
5823 /*
5824 Restore cursor.
5825 */
5826 (void) XCheckDefineCursor(display,window->id,window->cursor);
5827 return(MagickTrue);
5828}
5829
5830/*
5831%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5832% %
5833% %
5834% %
5835+ X M a k e I m a g e L S B F i r s t %
5836% %
5837% %
5838% %
5839%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5840%
5841% XMakeImageLSBFirst() initializes the pixel data of an X11 Image. The X image
5842% pixels are copied in least-significant bit and byte first order. The
5843% server's scanline pad is respected. Rather than using one or two general
5844% cases, many special cases are found here to help speed up the image
5845% conversion.
5846%
5847% The format of the XMakeImageLSBFirst method is:
5848%
cristye941a752011-10-15 01:52:48 +00005849% void XMakeImageLSBFirst(Display *display,XWindows *windows,
5850% ExceptionInfo *exception)
cristy3ed852e2009-09-05 21:47:34 +00005851%
5852% A description of each parameter follows:
5853%
5854% o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
5855%
5856% o window: Specifies a pointer to a XWindowInfo structure.
5857%
5858% o image: the image.
5859%
5860% o ximage: Specifies a pointer to a XImage structure; returned from
5861% XCreateImage.
5862%
5863% o matte_image: Specifies a pointer to a XImage structure; returned from
5864% XCreateImage.
5865%
cristye941a752011-10-15 01:52:48 +00005866% o exception: return any errors or warnings in this structure.
5867%
cristy3ed852e2009-09-05 21:47:34 +00005868*/
5869static void XMakeImageLSBFirst(const XResourceInfo *resource_info,
cristye941a752011-10-15 01:52:48 +00005870 const XWindowInfo *window,Image *image,XImage *ximage,XImage *matte_image,
5871 ExceptionInfo *exception)
cristy3ed852e2009-09-05 21:47:34 +00005872{
cristyc57f6942010-11-12 01:47:39 +00005873 CacheView
5874 *canvas_view;
5875
cristy3ed852e2009-09-05 21:47:34 +00005876 Image
5877 *canvas;
5878
5879 int
5880 y;
5881
cristy4c08aed2011-07-01 19:47:50 +00005882 register const Quantum
cristy3ed852e2009-09-05 21:47:34 +00005883 *p;
5884
5885 register int
5886 x;
5887
5888 register unsigned char
5889 *q;
5890
5891 unsigned char
5892 bit,
5893 byte;
5894
5895 unsigned int
5896 scanline_pad;
5897
cristyf2faecf2010-05-28 19:19:36 +00005898 unsigned long
cristy3ed852e2009-09-05 21:47:34 +00005899 pixel,
5900 *pixels;
5901
5902 XStandardColormap
5903 *map_info;
5904
5905 assert(resource_info != (XResourceInfo *) NULL);
5906 assert(window != (XWindowInfo *) NULL);
5907 assert(image != (Image *) NULL);
5908 if (image->debug != MagickFalse)
5909 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
5910 canvas=image;
cristybab87c32010-02-09 20:54:22 +00005911 if ((window->immutable == MagickFalse) &&
cristy54666e82010-02-03 23:34:26 +00005912 (image->storage_class == DirectClass) && (image->matte != MagickFalse))
cristy3ed852e2009-09-05 21:47:34 +00005913 {
5914 char
5915 size[MaxTextExtent];
5916
5917 Image
5918 *pattern;
5919
5920 ImageInfo
5921 *image_info;
5922
5923 image_info=AcquireImageInfo();
5924 (void) CopyMagickString(image_info->filename,
5925 resource_info->image_info->texture != (char *) NULL ?
5926 resource_info->image_info->texture : "pattern:checkerboard",
5927 MaxTextExtent);
cristyb51dff52011-05-19 16:55:47 +00005928 (void) FormatLocaleString(size,MaxTextExtent,"%.20gx%.20g",(double)
cristye8c25f92010-06-03 00:53:06 +00005929 image->columns,(double) image->rows);
cristy3ed852e2009-09-05 21:47:34 +00005930 image_info->size=ConstantString(size);
cristy6710d842011-10-20 23:23:00 +00005931 pattern=ReadImage(image_info,exception);
cristy3ed852e2009-09-05 21:47:34 +00005932 image_info=DestroyImageInfo(image_info);
5933 if (pattern != (Image *) NULL)
5934 {
cristy6710d842011-10-20 23:23:00 +00005935 canvas=CloneImage(image,0,0,MagickTrue,exception);
cristy3ed852e2009-09-05 21:47:34 +00005936 if (canvas != (Image *) NULL)
cristye941a752011-10-15 01:52:48 +00005937 (void) CompositeImage(canvas,DstOverCompositeOp,pattern,0,0,
5938 exception);
cristy3ed852e2009-09-05 21:47:34 +00005939 pattern=DestroyImage(pattern);
5940 }
5941 }
5942 scanline_pad=(unsigned int) (ximage->bytes_per_line-((ximage->width*
5943 ximage->bits_per_pixel) >> 3));
5944 map_info=window->map_info;
5945 pixels=window->pixel_info->pixels;
5946 q=(unsigned char *) ximage->data;
5947 x=0;
cristyc57f6942010-11-12 01:47:39 +00005948 canvas_view=AcquireCacheView(canvas);
cristy3ed852e2009-09-05 21:47:34 +00005949 if (ximage->format == XYBitmap)
5950 {
5951 register unsigned short
5952 polarity;
5953
5954 unsigned char
5955 background,
5956 foreground;
5957
5958 /*
5959 Convert canvas to big-endian bitmap.
5960 */
5961 background=(unsigned char)
5962 (XPixelIntensity(&window->pixel_info->foreground_color) <
5963 XPixelIntensity(&window->pixel_info->background_color) ? 0x80 : 0x00);
5964 foreground=(unsigned char)
5965 (XPixelIntensity(&window->pixel_info->background_color) <
5966 XPixelIntensity(&window->pixel_info->foreground_color) ? 0x80 : 0x00);
cristy101ab702011-10-13 13:06:32 +00005967 polarity=(unsigned short) ((GetPixelInfoIntensity(
cristy3ed852e2009-09-05 21:47:34 +00005968 &canvas->colormap[0])) < ((Quantum) QuantumRange/2) ? 1 : 0);
5969 if (canvas->colors == 2)
cristy101ab702011-10-13 13:06:32 +00005970 polarity=GetPixelInfoIntensity(&canvas->colormap[0]) <
5971 GetPixelInfoIntensity(&canvas->colormap[1]);
cristy3ed852e2009-09-05 21:47:34 +00005972 for (y=0; y < (int) canvas->rows; y++)
5973 {
cristyc57f6942010-11-12 01:47:39 +00005974 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,canvas->columns,1,
cristy6710d842011-10-20 23:23:00 +00005975 exception);
cristy4c08aed2011-07-01 19:47:50 +00005976 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00005977 break;
cristy3ed852e2009-09-05 21:47:34 +00005978 bit=0;
5979 byte=0;
5980 for (x=0; x < (int) canvas->columns; x++)
5981 {
5982 byte>>=1;
cristy4c08aed2011-07-01 19:47:50 +00005983 if (GetPixelIndex(canvas,p) == (Quantum) polarity)
cristy3ed852e2009-09-05 21:47:34 +00005984 byte|=foreground;
5985 else
5986 byte|=background;
5987 bit++;
5988 if (bit == 8)
5989 {
5990 *q++=byte;
5991 bit=0;
5992 byte=0;
5993 }
cristyed231572011-07-14 02:18:59 +00005994 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00005995 }
5996 if (bit != 0)
5997 *q=byte >> (8-bit);
5998 q+=scanline_pad;
5999 }
6000 }
6001 else
6002 if (window->pixel_info->colors != 0)
6003 switch (ximage->bits_per_pixel)
6004 {
6005 case 2:
6006 {
6007 register unsigned int
6008 nibble;
6009
6010 /*
6011 Convert to 2 bit color-mapped X canvas.
6012 */
6013 for (y=0; y < (int) canvas->rows; y++)
6014 {
cristyc57f6942010-11-12 01:47:39 +00006015 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
cristy6710d842011-10-20 23:23:00 +00006016 canvas->columns,1,exception);
cristy4c08aed2011-07-01 19:47:50 +00006017 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00006018 break;
cristy3ed852e2009-09-05 21:47:34 +00006019 nibble=0;
6020 for (x=0; x < (int) canvas->columns; x++)
6021 {
cristy4c08aed2011-07-01 19:47:50 +00006022 pixel=pixels[(ssize_t) GetPixelIndex(canvas,p)] & 0x0f;
cristy3ed852e2009-09-05 21:47:34 +00006023 switch (nibble)
6024 {
6025 case 0:
6026 {
6027 *q=(unsigned char) pixel;
6028 nibble++;
6029 break;
6030 }
6031 case 1:
6032 {
6033 *q|=(unsigned char) (pixel << 2);
6034 nibble++;
6035 break;
6036 }
6037 case 2:
6038 {
6039 *q|=(unsigned char) (pixel << 4);
6040 nibble++;
6041 break;
6042 }
6043 case 3:
6044 {
6045 *q|=(unsigned char) (pixel << 6);
6046 q++;
6047 nibble=0;
6048 break;
6049 }
6050 }
cristyed231572011-07-14 02:18:59 +00006051 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00006052 }
6053 q+=scanline_pad;
6054 }
6055 break;
6056 }
6057 case 4:
6058 {
6059 register unsigned int
6060 nibble;
6061
6062 /*
6063 Convert to 4 bit color-mapped X canvas.
6064 */
6065 for (y=0; y < (int) canvas->rows; y++)
6066 {
cristyc57f6942010-11-12 01:47:39 +00006067 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
cristy6710d842011-10-20 23:23:00 +00006068 canvas->columns,1,exception);
cristy4c08aed2011-07-01 19:47:50 +00006069 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00006070 break;
cristy3ed852e2009-09-05 21:47:34 +00006071 nibble=0;
6072 for (x=0; x < (int) canvas->columns; x++)
6073 {
cristy4c08aed2011-07-01 19:47:50 +00006074 pixel=pixels[(ssize_t) GetPixelIndex(canvas,p)] & 0xf;
cristy3ed852e2009-09-05 21:47:34 +00006075 switch (nibble)
6076 {
6077 case 0:
6078 {
6079 *q=(unsigned char) pixel;
6080 nibble++;
6081 break;
6082 }
6083 case 1:
6084 {
6085 *q|=(unsigned char) (pixel << 4);
6086 q++;
6087 nibble=0;
6088 break;
6089 }
6090 }
cristyed231572011-07-14 02:18:59 +00006091 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00006092 }
6093 q+=scanline_pad;
6094 }
6095 break;
6096 }
6097 case 6:
6098 case 8:
6099 {
6100 /*
6101 Convert to 8 bit color-mapped X canvas.
6102 */
6103 if (resource_info->color_recovery &&
6104 resource_info->quantize_info->dither)
6105 {
cristy6710d842011-10-20 23:23:00 +00006106 XDitherImage(canvas,ximage,exception);
cristy3ed852e2009-09-05 21:47:34 +00006107 break;
6108 }
6109 for (y=0; y < (int) canvas->rows; y++)
6110 {
cristyc57f6942010-11-12 01:47:39 +00006111 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
cristy6710d842011-10-20 23:23:00 +00006112 canvas->columns,1,exception);
cristy4c08aed2011-07-01 19:47:50 +00006113 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00006114 break;
cristy3ed852e2009-09-05 21:47:34 +00006115 for (x=0; x < (int) canvas->columns; x++)
6116 {
cristy4c08aed2011-07-01 19:47:50 +00006117 pixel=pixels[(ssize_t) GetPixelIndex(canvas,p)];
cristy3ed852e2009-09-05 21:47:34 +00006118 *q++=(unsigned char) pixel;
cristyed231572011-07-14 02:18:59 +00006119 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00006120 }
6121 q+=scanline_pad;
6122 }
6123 break;
6124 }
6125 default:
6126 {
6127 register int
6128 k;
6129
6130 register unsigned int
6131 bytes_per_pixel;
6132
6133 unsigned char
cristybb503372010-05-27 20:51:26 +00006134 channel[sizeof(size_t)];
cristy3ed852e2009-09-05 21:47:34 +00006135
6136 /*
6137 Convert to multi-byte color-mapped X canvas.
6138 */
6139 bytes_per_pixel=(unsigned int) (ximage->bits_per_pixel >> 3);
6140 for (y=0; y < (int) canvas->rows; y++)
6141 {
cristyc57f6942010-11-12 01:47:39 +00006142 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
cristy6710d842011-10-20 23:23:00 +00006143 canvas->columns,1,exception);
cristy4c08aed2011-07-01 19:47:50 +00006144 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00006145 break;
cristy3ed852e2009-09-05 21:47:34 +00006146 for (x=0; x < (int) canvas->columns; x++)
6147 {
cristy4c08aed2011-07-01 19:47:50 +00006148 pixel=pixels[(ssize_t) GetPixelIndex(canvas,p)];
cristy3ed852e2009-09-05 21:47:34 +00006149 for (k=0; k < (int) bytes_per_pixel; k++)
6150 {
6151 channel[k]=(unsigned char) pixel;
6152 pixel>>=8;
6153 }
6154 for (k=0; k < (int) bytes_per_pixel; k++)
6155 *q++=channel[k];
cristyed231572011-07-14 02:18:59 +00006156 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00006157 }
6158 q+=scanline_pad;
6159 }
6160 break;
6161 }
6162 }
6163 else
6164 switch (ximage->bits_per_pixel)
6165 {
6166 case 2:
6167 {
6168 register unsigned int
6169 nibble;
6170
6171 /*
6172 Convert to contiguous 2 bit continuous-tone X canvas.
6173 */
6174 for (y=0; y < (int) canvas->rows; y++)
6175 {
6176 nibble=0;
cristyc57f6942010-11-12 01:47:39 +00006177 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
cristy6710d842011-10-20 23:23:00 +00006178 canvas->columns,1,exception);
cristy4c08aed2011-07-01 19:47:50 +00006179 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00006180 break;
6181 for (x=0; x < (int) canvas->columns; x++)
6182 {
cristy4c08aed2011-07-01 19:47:50 +00006183 pixel=XGammaPixel(canvas,map_info,p);
cristy3ed852e2009-09-05 21:47:34 +00006184 pixel&=0xf;
6185 switch (nibble)
6186 {
6187 case 0:
6188 {
6189 *q=(unsigned char) pixel;
6190 nibble++;
6191 break;
6192 }
6193 case 1:
6194 {
6195 *q|=(unsigned char) (pixel << 2);
6196 nibble++;
6197 break;
6198 }
6199 case 2:
6200 {
6201 *q|=(unsigned char) (pixel << 4);
6202 nibble++;
6203 break;
6204 }
6205 case 3:
6206 {
6207 *q|=(unsigned char) (pixel << 6);
6208 q++;
6209 nibble=0;
6210 break;
6211 }
6212 }
cristyed231572011-07-14 02:18:59 +00006213 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00006214 }
6215 q+=scanline_pad;
6216 }
6217 break;
6218 }
6219 case 4:
6220 {
6221 register unsigned int
6222 nibble;
6223
6224 /*
6225 Convert to contiguous 4 bit continuous-tone X canvas.
6226 */
6227 for (y=0; y < (int) canvas->rows; y++)
6228 {
cristyc57f6942010-11-12 01:47:39 +00006229 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
cristy6710d842011-10-20 23:23:00 +00006230 canvas->columns,1,exception);
cristy4c08aed2011-07-01 19:47:50 +00006231 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00006232 break;
6233 nibble=0;
6234 for (x=0; x < (int) canvas->columns; x++)
6235 {
cristy4c08aed2011-07-01 19:47:50 +00006236 pixel=XGammaPixel(canvas,map_info,p);
cristy3ed852e2009-09-05 21:47:34 +00006237 pixel&=0xf;
6238 switch (nibble)
6239 {
6240 case 0:
6241 {
6242 *q=(unsigned char) pixel;
6243 nibble++;
6244 break;
6245 }
6246 case 1:
6247 {
6248 *q|=(unsigned char) (pixel << 4);
6249 q++;
6250 nibble=0;
6251 break;
6252 }
6253 }
cristyed231572011-07-14 02:18:59 +00006254 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00006255 }
6256 q+=scanline_pad;
6257 }
6258 break;
6259 }
6260 case 6:
6261 case 8:
6262 {
6263 /*
6264 Convert to contiguous 8 bit continuous-tone X canvas.
6265 */
6266 if (resource_info->color_recovery &&
6267 resource_info->quantize_info->dither)
6268 {
cristy6710d842011-10-20 23:23:00 +00006269 XDitherImage(canvas,ximage,exception);
cristy3ed852e2009-09-05 21:47:34 +00006270 break;
6271 }
6272 for (y=0; y < (int) canvas->rows; y++)
6273 {
cristyc57f6942010-11-12 01:47:39 +00006274 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
cristy6710d842011-10-20 23:23:00 +00006275 canvas->columns,1,exception);
cristy4c08aed2011-07-01 19:47:50 +00006276 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00006277 break;
6278 for (x=0; x < (int) canvas->columns; x++)
6279 {
cristy4c08aed2011-07-01 19:47:50 +00006280 pixel=XGammaPixel(canvas,map_info,p);
cristy3ed852e2009-09-05 21:47:34 +00006281 *q++=(unsigned char) pixel;
cristyed231572011-07-14 02:18:59 +00006282 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00006283 }
6284 q+=scanline_pad;
6285 }
6286 break;
6287 }
6288 default:
6289 {
6290 if ((ximage->bits_per_pixel == 32) && (map_info->red_max == 255) &&
6291 (map_info->green_max == 255) && (map_info->blue_max == 255) &&
6292 (map_info->red_mult == 65536L) && (map_info->green_mult == 256) &&
6293 (map_info->blue_mult == 1))
6294 {
6295 /*
6296 Convert to 32 bit continuous-tone X canvas.
6297 */
6298 for (y=0; y < (int) canvas->rows; y++)
6299 {
cristyc57f6942010-11-12 01:47:39 +00006300 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
cristy6710d842011-10-20 23:23:00 +00006301 canvas->columns,1,exception);
cristy4c08aed2011-07-01 19:47:50 +00006302 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00006303 break;
6304 if ((red_gamma != 1.0) || (green_gamma != 1.0) ||
6305 (blue_gamma != 1.0))
6306 {
6307 /*
6308 Gamma correct canvas.
6309 */
6310 for (x=(int) canvas->columns-1; x >= 0; x--)
6311 {
cristyccf844f2010-02-03 23:28:16 +00006312 *q++=ScaleQuantumToChar(XBlueGamma(
cristy4c08aed2011-07-01 19:47:50 +00006313 GetPixelBlue(canvas,p)));
cristyccf844f2010-02-03 23:28:16 +00006314 *q++=ScaleQuantumToChar(XGreenGamma(
cristy4c08aed2011-07-01 19:47:50 +00006315 GetPixelGreen(canvas,p)));
cristyccf844f2010-02-03 23:28:16 +00006316 *q++=ScaleQuantumToChar(XRedGamma(
cristy4c08aed2011-07-01 19:47:50 +00006317 GetPixelRed(canvas,p)));
cristy3ed852e2009-09-05 21:47:34 +00006318 *q++=0;
cristyed231572011-07-14 02:18:59 +00006319 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00006320 }
6321 continue;
6322 }
6323 for (x=(int) canvas->columns-1; x >= 0; x--)
6324 {
cristy4c08aed2011-07-01 19:47:50 +00006325 *q++=ScaleQuantumToChar((Quantum)
6326 GetPixelBlue(canvas,p));
6327 *q++=ScaleQuantumToChar((Quantum)
6328 GetPixelGreen(canvas,p));
6329 *q++=ScaleQuantumToChar((Quantum)
6330 GetPixelRed(canvas,p));
cristy3ed852e2009-09-05 21:47:34 +00006331 *q++=0;
cristyed231572011-07-14 02:18:59 +00006332 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00006333 }
6334 }
6335 }
6336 else
6337 if ((ximage->bits_per_pixel == 32) && (map_info->red_max == 255) &&
6338 (map_info->green_max == 255) && (map_info->blue_max == 255) &&
6339 (map_info->red_mult == 1) && (map_info->green_mult == 256) &&
6340 (map_info->blue_mult == 65536L))
6341 {
6342 /*
6343 Convert to 32 bit continuous-tone X canvas.
6344 */
6345 for (y=0; y < (int) canvas->rows; y++)
6346 {
cristyc57f6942010-11-12 01:47:39 +00006347 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
cristy6710d842011-10-20 23:23:00 +00006348 canvas->columns,1,exception);
cristy4c08aed2011-07-01 19:47:50 +00006349 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00006350 break;
6351 if ((red_gamma != 1.0) || (green_gamma != 1.0) ||
6352 (blue_gamma != 1.0))
6353 {
6354 /*
6355 Gamma correct canvas.
6356 */
6357 for (x=(int) canvas->columns-1; x >= 0; x--)
6358 {
cristyccf844f2010-02-03 23:28:16 +00006359 *q++=ScaleQuantumToChar(XRedGamma(
cristy4c08aed2011-07-01 19:47:50 +00006360 GetPixelRed(canvas,p)));
cristyccf844f2010-02-03 23:28:16 +00006361 *q++=ScaleQuantumToChar(XGreenGamma(
cristy4c08aed2011-07-01 19:47:50 +00006362 GetPixelGreen(canvas,p)));
cristyccf844f2010-02-03 23:28:16 +00006363 *q++=ScaleQuantumToChar(XBlueGamma(
cristy4c08aed2011-07-01 19:47:50 +00006364 GetPixelBlue(canvas,p)));
cristy3ed852e2009-09-05 21:47:34 +00006365 *q++=0;
cristyed231572011-07-14 02:18:59 +00006366 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00006367 }
6368 continue;
6369 }
6370 for (x=(int) canvas->columns-1; x >= 0; x--)
6371 {
cristyccf844f2010-02-03 23:28:16 +00006372 *q++=ScaleQuantumToChar((Quantum)
cristy4c08aed2011-07-01 19:47:50 +00006373 GetPixelRed(canvas,p));
cristyccf844f2010-02-03 23:28:16 +00006374 *q++=ScaleQuantumToChar((Quantum)
cristy4c08aed2011-07-01 19:47:50 +00006375 GetPixelGreen(canvas,p));
cristyccf844f2010-02-03 23:28:16 +00006376 *q++=ScaleQuantumToChar((Quantum)
cristy4c08aed2011-07-01 19:47:50 +00006377 GetPixelBlue(canvas,p));
cristy3ed852e2009-09-05 21:47:34 +00006378 *q++=0;
cristyed231572011-07-14 02:18:59 +00006379 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00006380 }
6381 }
6382 }
6383 else
6384 {
6385 register int
6386 k;
6387
6388 register unsigned int
6389 bytes_per_pixel;
6390
6391 unsigned char
cristybb503372010-05-27 20:51:26 +00006392 channel[sizeof(size_t)];
cristy3ed852e2009-09-05 21:47:34 +00006393
6394 /*
6395 Convert to multi-byte continuous-tone X canvas.
6396 */
6397 bytes_per_pixel=(unsigned int) (ximage->bits_per_pixel >> 3);
6398 for (y=0; y < (int) canvas->rows; y++)
6399 {
cristyc57f6942010-11-12 01:47:39 +00006400 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
cristy6710d842011-10-20 23:23:00 +00006401 canvas->columns,1,exception);
cristy4c08aed2011-07-01 19:47:50 +00006402 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00006403 break;
cristyc57f6942010-11-12 01:47:39 +00006404 for (x=0; x < (int) canvas->columns; x++)
cristy3ed852e2009-09-05 21:47:34 +00006405 {
cristy4c08aed2011-07-01 19:47:50 +00006406 pixel=XGammaPixel(canvas,map_info,p);
cristy3ed852e2009-09-05 21:47:34 +00006407 for (k=0; k < (int) bytes_per_pixel; k++)
6408 {
6409 channel[k]=(unsigned char) pixel;
6410 pixel>>=8;
6411 }
6412 for (k=0; k < (int) bytes_per_pixel; k++)
6413 *q++=channel[k];
cristyed231572011-07-14 02:18:59 +00006414 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00006415 }
6416 q+=scanline_pad;
6417 }
6418 }
6419 break;
6420 }
6421 }
6422 if (matte_image != (XImage *) NULL)
6423 {
6424 /*
6425 Initialize matte canvas.
6426 */
6427 scanline_pad=(unsigned int) (matte_image->bytes_per_line-
6428 ((matte_image->width*matte_image->bits_per_pixel) >> 3));
6429 q=(unsigned char *) matte_image->data;
6430 for (y=0; y < (int) canvas->rows; y++)
6431 {
cristyc57f6942010-11-12 01:47:39 +00006432 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,canvas->columns,1,
cristy6710d842011-10-20 23:23:00 +00006433 exception);
cristy4c08aed2011-07-01 19:47:50 +00006434 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00006435 break;
6436 bit=0;
6437 byte=0;
6438 for (x=(int) canvas->columns-1; x >= 0; x--)
6439 {
6440 byte>>=1;
cristy4c08aed2011-07-01 19:47:50 +00006441 if (GetPixelAlpha(canvas,p) > (QuantumRange/2))
cristy3ed852e2009-09-05 21:47:34 +00006442 byte|=0x80;
6443 bit++;
6444 if (bit == 8)
6445 {
6446 *q++=byte;
6447 bit=0;
6448 byte=0;
6449 }
cristyed231572011-07-14 02:18:59 +00006450 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00006451 }
6452 if (bit != 0)
6453 *q=byte >> (8-bit);
6454 q+=scanline_pad;
6455 }
6456 }
cristyc57f6942010-11-12 01:47:39 +00006457 canvas_view=DestroyCacheView(canvas_view);
cristy3ed852e2009-09-05 21:47:34 +00006458 if (canvas != image)
6459 canvas=DestroyImage(canvas);
6460}
6461
6462/*
6463%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
6464% %
6465% %
6466% %
6467+ X M a k e I m a g e M S B F i r s t %
6468% %
6469% %
6470% %
6471%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
6472%
6473% XMakeImageMSBFirst() initializes the pixel data of an X11 Image. The X
6474% image pixels are copied in most-significant bit and byte first order. The
6475% server's scanline pad is also respected. Rather than using one or two
6476% general cases, many special cases are found here to help speed up the image
6477% conversion.
6478%
6479% The format of the XMakeImageMSBFirst method is:
6480%
cristye941a752011-10-15 01:52:48 +00006481% XMakeImageMSBFirst(resource_info,window,image,ximage,matte_image,
6482% ExceptionInfo *exception)
cristy3ed852e2009-09-05 21:47:34 +00006483%
6484% A description of each parameter follows:
6485%
6486% o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
6487%
6488% o window: Specifies a pointer to a XWindowInfo structure.
6489%
6490% o image: the image.
6491%
6492% o ximage: Specifies a pointer to a XImage structure; returned from
6493% XCreateImage.
6494%
6495% o matte_image: Specifies a pointer to a XImage structure; returned from
6496% XCreateImage.
6497%
cristye941a752011-10-15 01:52:48 +00006498% o exception: return any errors or warnings in this structure.
6499%
cristy3ed852e2009-09-05 21:47:34 +00006500*/
6501static void XMakeImageMSBFirst(const XResourceInfo *resource_info,
cristye941a752011-10-15 01:52:48 +00006502 const XWindowInfo *window,Image *image,XImage *ximage,XImage *matte_image,
6503 ExceptionInfo *exception)
cristy3ed852e2009-09-05 21:47:34 +00006504{
cristyc57f6942010-11-12 01:47:39 +00006505 CacheView
6506 *canvas_view;
6507
cristy3ed852e2009-09-05 21:47:34 +00006508 Image
6509 *canvas;
6510
6511 int
6512 y;
6513
6514 register int
6515 x;
6516
cristy4c08aed2011-07-01 19:47:50 +00006517 register const Quantum
cristy3ed852e2009-09-05 21:47:34 +00006518 *p;
6519
6520 register unsigned char
6521 *q;
6522
6523 unsigned char
6524 bit,
6525 byte;
6526
6527 unsigned int
6528 scanline_pad;
6529
cristyf2faecf2010-05-28 19:19:36 +00006530 unsigned long
cristy3ed852e2009-09-05 21:47:34 +00006531 pixel,
6532 *pixels;
6533
6534 XStandardColormap
6535 *map_info;
6536
6537 assert(resource_info != (XResourceInfo *) NULL);
6538 assert(window != (XWindowInfo *) NULL);
6539 assert(image != (Image *) NULL);
6540 if (image->debug != MagickFalse)
6541 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
6542 canvas=image;
cristy54666e82010-02-03 23:34:26 +00006543 if ((window->immutable != MagickFalse) &&
6544 (image->storage_class == DirectClass) && (image->matte != MagickFalse))
cristy3ed852e2009-09-05 21:47:34 +00006545 {
6546 char
6547 size[MaxTextExtent];
6548
6549 Image
6550 *pattern;
6551
6552 ImageInfo
6553 *image_info;
6554
6555 image_info=AcquireImageInfo();
6556 (void) CopyMagickString(image_info->filename,
6557 resource_info->image_info->texture != (char *) NULL ?
6558 resource_info->image_info->texture : "pattern:checkerboard",
6559 MaxTextExtent);
cristyb51dff52011-05-19 16:55:47 +00006560 (void) FormatLocaleString(size,MaxTextExtent,"%.20gx%.20g",(double)
cristye8c25f92010-06-03 00:53:06 +00006561 image->columns,(double) image->rows);
cristy3ed852e2009-09-05 21:47:34 +00006562 image_info->size=ConstantString(size);
cristy6710d842011-10-20 23:23:00 +00006563 pattern=ReadImage(image_info,exception);
cristy3ed852e2009-09-05 21:47:34 +00006564 image_info=DestroyImageInfo(image_info);
6565 if (pattern != (Image *) NULL)
6566 {
cristy6710d842011-10-20 23:23:00 +00006567 canvas=CloneImage(image,0,0,MagickTrue,exception);
cristy3ed852e2009-09-05 21:47:34 +00006568 if (canvas != (Image *) NULL)
cristye941a752011-10-15 01:52:48 +00006569 (void) CompositeImage(canvas,DstOverCompositeOp,pattern,0,0,
6570 exception);
cristy3ed852e2009-09-05 21:47:34 +00006571 pattern=DestroyImage(pattern);
6572 }
6573 }
cristy4c08aed2011-07-01 19:47:50 +00006574 scanline_pad=(unsigned int) (ximage->bytes_per_line-((ximage->width*
6575 ximage->bits_per_pixel) >> 3));
cristy3ed852e2009-09-05 21:47:34 +00006576 map_info=window->map_info;
6577 pixels=window->pixel_info->pixels;
6578 q=(unsigned char *) ximage->data;
6579 x=0;
cristyc57f6942010-11-12 01:47:39 +00006580 canvas_view=AcquireCacheView(canvas);
cristy3ed852e2009-09-05 21:47:34 +00006581 if (ximage->format == XYBitmap)
6582 {
6583 register unsigned short
6584 polarity;
6585
6586 unsigned char
6587 background,
6588 foreground;
6589
6590 /*
6591 Convert canvas to big-endian bitmap.
6592 */
6593 background=(unsigned char)
6594 (XPixelIntensity(&window->pixel_info->foreground_color) <
6595 XPixelIntensity(&window->pixel_info->background_color) ? 0x01 : 0x00);
6596 foreground=(unsigned char)
6597 (XPixelIntensity(&window->pixel_info->background_color) <
6598 XPixelIntensity(&window->pixel_info->foreground_color) ? 0x01 : 0x00);
cristy101ab702011-10-13 13:06:32 +00006599 polarity=(unsigned short) ((GetPixelInfoIntensity(
cristy3ed852e2009-09-05 21:47:34 +00006600 &canvas->colormap[0])) < ((Quantum) QuantumRange/2) ? 1 : 0);
6601 if (canvas->colors == 2)
cristy101ab702011-10-13 13:06:32 +00006602 polarity=GetPixelInfoIntensity(&canvas->colormap[0]) <
6603 GetPixelInfoIntensity(&canvas->colormap[1]);
cristy3ed852e2009-09-05 21:47:34 +00006604 for (y=0; y < (int) canvas->rows; y++)
6605 {
cristyc57f6942010-11-12 01:47:39 +00006606 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,canvas->columns,1,
cristy6710d842011-10-20 23:23:00 +00006607 exception);
cristy4c08aed2011-07-01 19:47:50 +00006608 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00006609 break;
cristy3ed852e2009-09-05 21:47:34 +00006610 bit=0;
6611 byte=0;
6612 for (x=(int) canvas->columns-1; x >= 0; x--)
6613 {
6614 byte<<=1;
cristy4c08aed2011-07-01 19:47:50 +00006615 if (GetPixelIndex(canvas,p) == (Quantum) polarity)
cristy3ed852e2009-09-05 21:47:34 +00006616 byte|=foreground;
6617 else
6618 byte|=background;
6619 bit++;
6620 if (bit == 8)
6621 {
6622 *q++=byte;
6623 bit=0;
6624 byte=0;
6625 }
cristyed231572011-07-14 02:18:59 +00006626 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00006627 }
6628 if (bit != 0)
6629 *q=byte << (8-bit);
6630 q+=scanline_pad;
6631 }
6632 }
6633 else
6634 if (window->pixel_info->colors != 0)
6635 switch (ximage->bits_per_pixel)
6636 {
6637 case 2:
6638 {
6639 register unsigned int
6640 nibble;
6641
6642 /*
6643 Convert to 2 bit color-mapped X canvas.
6644 */
6645 for (y=0; y < (int) canvas->rows; y++)
6646 {
cristyc57f6942010-11-12 01:47:39 +00006647 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
cristy6710d842011-10-20 23:23:00 +00006648 canvas->columns,1,exception);
cristy4c08aed2011-07-01 19:47:50 +00006649 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00006650 break;
cristy3ed852e2009-09-05 21:47:34 +00006651 nibble=0;
6652 for (x=0; x < (int) canvas->columns; x++)
6653 {
cristy4c08aed2011-07-01 19:47:50 +00006654 pixel=pixels[(ssize_t)
6655 GetPixelIndex(canvas,p)] & 0xf;
cristy3ed852e2009-09-05 21:47:34 +00006656 switch (nibble)
6657 {
6658 case 0:
6659 {
6660 *q=(unsigned char) (pixel << 6);
6661 nibble++;
6662 break;
6663 }
6664 case 1:
6665 {
6666 *q|=(unsigned char) (pixel << 4);
6667 nibble++;
6668 break;
6669 }
6670 case 2:
6671 {
6672 *q|=(unsigned char) (pixel << 2);
6673 nibble++;
6674 break;
6675 }
6676 case 3:
6677 {
6678 *q|=(unsigned char) pixel;
6679 q++;
6680 nibble=0;
6681 break;
6682 }
6683 }
cristyed231572011-07-14 02:18:59 +00006684 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00006685 }
6686 q+=scanline_pad;
6687 }
6688 break;
6689 }
6690 case 4:
6691 {
6692 register unsigned int
6693 nibble;
6694
6695 /*
6696 Convert to 4 bit color-mapped X canvas.
6697 */
6698 for (y=0; y < (int) canvas->rows; y++)
6699 {
cristyc57f6942010-11-12 01:47:39 +00006700 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
cristy6710d842011-10-20 23:23:00 +00006701 canvas->columns,1,exception);
cristy4c08aed2011-07-01 19:47:50 +00006702 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00006703 break;
cristy3ed852e2009-09-05 21:47:34 +00006704 nibble=0;
6705 for (x=0; x < (int) canvas->columns; x++)
6706 {
cristy4c08aed2011-07-01 19:47:50 +00006707 pixel=pixels[(ssize_t)
6708 GetPixelIndex(canvas,p)] & 0xf;
cristy3ed852e2009-09-05 21:47:34 +00006709 switch (nibble)
6710 {
6711 case 0:
6712 {
6713 *q=(unsigned char) (pixel << 4);
6714 nibble++;
6715 break;
6716 }
6717 case 1:
6718 {
6719 *q|=(unsigned char) pixel;
6720 q++;
6721 nibble=0;
6722 break;
6723 }
6724 }
cristyed231572011-07-14 02:18:59 +00006725 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00006726 }
6727 q+=scanline_pad;
6728 }
6729 break;
6730 }
6731 case 6:
6732 case 8:
6733 {
6734 /*
6735 Convert to 8 bit color-mapped X canvas.
6736 */
6737 if (resource_info->color_recovery &&
6738 resource_info->quantize_info->dither)
6739 {
cristy6710d842011-10-20 23:23:00 +00006740 XDitherImage(canvas,ximage,exception);
cristy3ed852e2009-09-05 21:47:34 +00006741 break;
6742 }
6743 for (y=0; y < (int) canvas->rows; y++)
6744 {
cristyc57f6942010-11-12 01:47:39 +00006745 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
cristy6710d842011-10-20 23:23:00 +00006746 canvas->columns,1,exception);
cristy4c08aed2011-07-01 19:47:50 +00006747 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00006748 break;
cristy3ed852e2009-09-05 21:47:34 +00006749 for (x=0; x < (int) canvas->columns; x++)
6750 {
cristy6710d842011-10-20 23:23:00 +00006751 pixel=pixels[(ssize_t) GetPixelIndex(canvas,p)];
cristy3ed852e2009-09-05 21:47:34 +00006752 *q++=(unsigned char) pixel;
cristyed231572011-07-14 02:18:59 +00006753 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00006754 }
6755 q+=scanline_pad;
6756 }
6757 break;
6758 }
6759 default:
6760 {
6761 register int
6762 k;
6763
6764 register unsigned int
6765 bytes_per_pixel;
6766
6767 unsigned char
cristybb503372010-05-27 20:51:26 +00006768 channel[sizeof(size_t)];
cristy3ed852e2009-09-05 21:47:34 +00006769
6770 /*
6771 Convert to 8 bit color-mapped X canvas.
6772 */
6773 bytes_per_pixel=(unsigned int) (ximage->bits_per_pixel >> 3);
6774 for (y=0; y < (int) canvas->rows; y++)
6775 {
cristyc57f6942010-11-12 01:47:39 +00006776 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
cristy6710d842011-10-20 23:23:00 +00006777 canvas->columns,1,exception);
cristy4c08aed2011-07-01 19:47:50 +00006778 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00006779 break;
cristy3ed852e2009-09-05 21:47:34 +00006780 for (x=0; x < (int) canvas->columns; x++)
6781 {
cristy4c08aed2011-07-01 19:47:50 +00006782 pixel=pixels[(ssize_t)
6783 GetPixelIndex(canvas,p)];
cristy3ed852e2009-09-05 21:47:34 +00006784 for (k=(int) bytes_per_pixel-1; k >= 0; k--)
6785 {
6786 channel[k]=(unsigned char) pixel;
6787 pixel>>=8;
6788 }
6789 for (k=0; k < (int) bytes_per_pixel; k++)
6790 *q++=channel[k];
cristyed231572011-07-14 02:18:59 +00006791 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00006792 }
6793 q+=scanline_pad;
6794 }
6795 break;
6796 }
6797 }
6798 else
6799 switch (ximage->bits_per_pixel)
6800 {
6801 case 2:
6802 {
6803 register unsigned int
6804 nibble;
6805
6806 /*
6807 Convert to 4 bit continuous-tone X canvas.
6808 */
6809 for (y=0; y < (int) canvas->rows; y++)
6810 {
cristyc57f6942010-11-12 01:47:39 +00006811 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
cristy6710d842011-10-20 23:23:00 +00006812 canvas->columns,1,exception);
cristy4c08aed2011-07-01 19:47:50 +00006813 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00006814 break;
6815 nibble=0;
6816 for (x=(int) canvas->columns-1; x >= 0; x--)
6817 {
cristy4c08aed2011-07-01 19:47:50 +00006818 pixel=XGammaPixel(canvas,map_info,p);
cristy3ed852e2009-09-05 21:47:34 +00006819 pixel&=0xf;
6820 switch (nibble)
6821 {
6822 case 0:
6823 {
6824 *q=(unsigned char) (pixel << 6);
6825 nibble++;
6826 break;
6827 }
6828 case 1:
6829 {
6830 *q|=(unsigned char) (pixel << 4);
6831 nibble++;
6832 break;
6833 }
6834 case 2:
6835 {
6836 *q|=(unsigned char) (pixel << 2);
6837 nibble++;
6838 break;
6839 }
6840 case 3:
6841 {
6842 *q|=(unsigned char) pixel;
6843 q++;
6844 nibble=0;
6845 break;
6846 }
6847 }
cristyed231572011-07-14 02:18:59 +00006848 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00006849 }
6850 q+=scanline_pad;
6851 }
6852 break;
6853 }
6854 case 4:
6855 {
6856 register unsigned int
6857 nibble;
6858
6859 /*
6860 Convert to 4 bit continuous-tone X canvas.
6861 */
6862 for (y=0; y < (int) canvas->rows; y++)
6863 {
cristyc57f6942010-11-12 01:47:39 +00006864 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
cristy6710d842011-10-20 23:23:00 +00006865 canvas->columns,1,exception);
cristy4c08aed2011-07-01 19:47:50 +00006866 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00006867 break;
6868 nibble=0;
6869 for (x=(int) canvas->columns-1; x >= 0; x--)
6870 {
cristy4c08aed2011-07-01 19:47:50 +00006871 pixel=XGammaPixel(canvas,map_info,p);
cristy3ed852e2009-09-05 21:47:34 +00006872 pixel&=0xf;
6873 switch (nibble)
6874 {
6875 case 0:
6876 {
6877 *q=(unsigned char) (pixel << 4);
6878 nibble++;
6879 break;
6880 }
6881 case 1:
6882 {
6883 *q|=(unsigned char) pixel;
6884 q++;
6885 nibble=0;
6886 break;
6887 }
6888 }
cristyed231572011-07-14 02:18:59 +00006889 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00006890 }
6891 q+=scanline_pad;
6892 }
6893 break;
6894 }
6895 case 6:
6896 case 8:
6897 {
6898 /*
6899 Convert to 8 bit continuous-tone X canvas.
6900 */
6901 if (resource_info->color_recovery &&
6902 resource_info->quantize_info->dither)
6903 {
cristy6710d842011-10-20 23:23:00 +00006904 XDitherImage(canvas,ximage,exception);
cristy3ed852e2009-09-05 21:47:34 +00006905 break;
6906 }
6907 for (y=0; y < (int) canvas->rows; y++)
6908 {
cristyc57f6942010-11-12 01:47:39 +00006909 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
cristy6710d842011-10-20 23:23:00 +00006910 canvas->columns,1,exception);
cristy4c08aed2011-07-01 19:47:50 +00006911 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00006912 break;
6913 for (x=(int) canvas->columns-1; x >= 0; x--)
6914 {
cristy4c08aed2011-07-01 19:47:50 +00006915 pixel=XGammaPixel(canvas,map_info,p);
cristy3ed852e2009-09-05 21:47:34 +00006916 *q++=(unsigned char) pixel;
cristyed231572011-07-14 02:18:59 +00006917 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00006918 }
6919 q+=scanline_pad;
6920 }
6921 break;
6922 }
6923 default:
6924 {
6925 if ((ximage->bits_per_pixel == 32) && (map_info->red_max == 255) &&
6926 (map_info->green_max == 255) && (map_info->blue_max == 255) &&
6927 (map_info->red_mult == 65536L) && (map_info->green_mult == 256) &&
6928 (map_info->blue_mult == 1))
6929 {
6930 /*
6931 Convert to 32 bit continuous-tone X canvas.
6932 */
6933 for (y=0; y < (int) canvas->rows; y++)
6934 {
cristyc57f6942010-11-12 01:47:39 +00006935 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
cristy6710d842011-10-20 23:23:00 +00006936 canvas->columns,1,exception);
cristy4c08aed2011-07-01 19:47:50 +00006937 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00006938 break;
6939 if ((red_gamma != 1.0) || (green_gamma != 1.0) ||
6940 (blue_gamma != 1.0))
6941 {
6942 /*
6943 Gamma correct canvas.
6944 */
6945 for (x=(int) canvas->columns-1; x >= 0; x--)
6946 {
6947 *q++=0;
cristyccf844f2010-02-03 23:28:16 +00006948 *q++=ScaleQuantumToChar(XRedGamma(
cristy4c08aed2011-07-01 19:47:50 +00006949 GetPixelRed(canvas,p)));
cristyccf844f2010-02-03 23:28:16 +00006950 *q++=ScaleQuantumToChar(XGreenGamma(
cristy4c08aed2011-07-01 19:47:50 +00006951 GetPixelGreen(canvas,p)));
cristyccf844f2010-02-03 23:28:16 +00006952 *q++=ScaleQuantumToChar(XBlueGamma(
cristy4c08aed2011-07-01 19:47:50 +00006953 GetPixelBlue(canvas,p)));
cristyed231572011-07-14 02:18:59 +00006954 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00006955 }
6956 continue;
6957 }
6958 for (x=(int) canvas->columns-1; x >= 0; x--)
6959 {
6960 *q++=0;
cristy4c08aed2011-07-01 19:47:50 +00006961 *q++=ScaleQuantumToChar((Quantum)
6962 GetPixelRed(canvas,p));
6963 *q++=ScaleQuantumToChar((Quantum)
6964 GetPixelGreen(canvas,p));
6965 *q++=ScaleQuantumToChar((Quantum)
6966 GetPixelBlue(canvas,p));
cristyed231572011-07-14 02:18:59 +00006967 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00006968 }
6969 }
6970 }
6971 else
6972 if ((ximage->bits_per_pixel == 32) && (map_info->red_max == 255) &&
6973 (map_info->green_max == 255) && (map_info->blue_max == 255) &&
6974 (map_info->red_mult == 1) && (map_info->green_mult == 256) &&
6975 (map_info->blue_mult == 65536L))
6976 {
6977 /*
6978 Convert to 32 bit continuous-tone X canvas.
6979 */
6980 for (y=0; y < (int) canvas->rows; y++)
6981 {
cristyc57f6942010-11-12 01:47:39 +00006982 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
cristy6710d842011-10-20 23:23:00 +00006983 canvas->columns,1,exception);
cristy4c08aed2011-07-01 19:47:50 +00006984 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00006985 break;
6986 if ((red_gamma != 1.0) || (green_gamma != 1.0) ||
6987 (blue_gamma != 1.0))
6988 {
6989 /*
6990 Gamma correct canvas.
6991 */
6992 for (x=(int) canvas->columns-1; x >= 0; x--)
6993 {
6994 *q++=0;
cristyccf844f2010-02-03 23:28:16 +00006995 *q++=ScaleQuantumToChar(XBlueGamma(
cristy4c08aed2011-07-01 19:47:50 +00006996 GetPixelBlue(canvas,p)));
cristyccf844f2010-02-03 23:28:16 +00006997 *q++=ScaleQuantumToChar(XGreenGamma(
cristy4c08aed2011-07-01 19:47:50 +00006998 GetPixelGreen(canvas,p)));
cristyccf844f2010-02-03 23:28:16 +00006999 *q++=ScaleQuantumToChar(XRedGamma(
cristy4c08aed2011-07-01 19:47:50 +00007000 GetPixelRed(canvas,p)));
cristyed231572011-07-14 02:18:59 +00007001 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00007002 }
7003 continue;
7004 }
7005 for (x=(int) canvas->columns-1; x >= 0; x--)
7006 {
7007 *q++=0;
cristyccf844f2010-02-03 23:28:16 +00007008 *q++=ScaleQuantumToChar((Quantum)
cristy4c08aed2011-07-01 19:47:50 +00007009 GetPixelBlue(canvas,p));
cristyccf844f2010-02-03 23:28:16 +00007010 *q++=ScaleQuantumToChar((Quantum)
cristy4c08aed2011-07-01 19:47:50 +00007011 GetPixelGreen(canvas,p));
cristyccf844f2010-02-03 23:28:16 +00007012 *q++=ScaleQuantumToChar((Quantum)
cristy4c08aed2011-07-01 19:47:50 +00007013 GetPixelRed(canvas,p));
cristyed231572011-07-14 02:18:59 +00007014 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00007015 }
7016 }
7017 }
7018 else
7019 {
7020 register int
7021 k;
7022
7023 register unsigned int
7024 bytes_per_pixel;
7025
7026 unsigned char
cristybb503372010-05-27 20:51:26 +00007027 channel[sizeof(size_t)];
cristy3ed852e2009-09-05 21:47:34 +00007028
7029 /*
7030 Convert to multi-byte continuous-tone X canvas.
7031 */
7032 bytes_per_pixel=(unsigned int) (ximage->bits_per_pixel >> 3);
7033 for (y=0; y < (int) canvas->rows; y++)
7034 {
cristyc57f6942010-11-12 01:47:39 +00007035 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
cristy6710d842011-10-20 23:23:00 +00007036 canvas->columns,1,exception);
cristy4c08aed2011-07-01 19:47:50 +00007037 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00007038 break;
7039 for (x=(int) canvas->columns-1; x >= 0; x--)
7040 {
cristy4c08aed2011-07-01 19:47:50 +00007041 pixel=XGammaPixel(canvas,map_info,p);
cristy3ed852e2009-09-05 21:47:34 +00007042 for (k=(int) bytes_per_pixel-1; k >= 0; k--)
7043 {
7044 channel[k]=(unsigned char) pixel;
7045 pixel>>=8;
7046 }
7047 for (k=0; k < (int) bytes_per_pixel; k++)
7048 *q++=channel[k];
cristyed231572011-07-14 02:18:59 +00007049 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00007050 }
7051 q+=scanline_pad;
7052 }
7053 }
7054 break;
7055 }
7056 }
7057 if (matte_image != (XImage *) NULL)
7058 {
7059 /*
7060 Initialize matte canvas.
7061 */
7062 scanline_pad=(unsigned int) (matte_image->bytes_per_line-
7063 ((matte_image->width*matte_image->bits_per_pixel) >> 3));
7064 q=(unsigned char *) matte_image->data;
7065 for (y=0; y < (int) canvas->rows; y++)
7066 {
cristyc57f6942010-11-12 01:47:39 +00007067 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,canvas->columns,1,
cristy6710d842011-10-20 23:23:00 +00007068 exception);
cristy4c08aed2011-07-01 19:47:50 +00007069 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00007070 break;
7071 bit=0;
7072 byte=0;
7073 for (x=(int) canvas->columns-1; x >= 0; x--)
7074 {
7075 byte<<=1;
cristy4c08aed2011-07-01 19:47:50 +00007076 if (GetPixelAlpha(canvas,p) > (QuantumRange/2))
cristy3ed852e2009-09-05 21:47:34 +00007077 byte|=0x01;
7078 bit++;
7079 if (bit == 8)
7080 {
7081 *q++=byte;
7082 bit=0;
7083 byte=0;
7084 }
cristyed231572011-07-14 02:18:59 +00007085 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00007086 }
7087 if (bit != 0)
7088 *q=byte << (8-bit);
7089 q+=scanline_pad;
7090 }
7091 }
cristyc57f6942010-11-12 01:47:39 +00007092 canvas_view=DestroyCacheView(canvas_view);
cristy3ed852e2009-09-05 21:47:34 +00007093 if (canvas != image)
7094 canvas=DestroyImage(canvas);
7095}
7096
7097/*
7098%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
7099% %
7100% %
7101% %
7102% X M a k e M a g n i f y I m a g e %
7103% %
7104% %
7105% %
7106%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
7107%
7108% XMakeMagnifyImage() magnifies a region of an X image and displays it.
7109%
7110% The format of the XMakeMagnifyImage method is:
7111%
cristy6710d842011-10-20 23:23:00 +00007112% void XMakeMagnifyImage(Display *display,XWindows *windows,
7113% ExceptionInfo *exception)
cristy3ed852e2009-09-05 21:47:34 +00007114%
7115% A description of each parameter follows:
7116%
7117% o display: Specifies a connection to an X server; returned from
7118% XOpenDisplay.
7119%
7120% o windows: Specifies a pointer to a XWindows structure.
7121%
cristy6710d842011-10-20 23:23:00 +00007122% o exception: return any errors or warnings in this structure.
7123%
cristy3ed852e2009-09-05 21:47:34 +00007124*/
cristy6710d842011-10-20 23:23:00 +00007125MagickPrivate void XMakeMagnifyImage(Display *display,XWindows *windows,
7126 ExceptionInfo *exception)
cristy3ed852e2009-09-05 21:47:34 +00007127{
7128 char
7129 tuple[MaxTextExtent];
7130
7131 int
7132 y;
7133
cristy4c08aed2011-07-01 19:47:50 +00007134 PixelInfo
cristy3ed852e2009-09-05 21:47:34 +00007135 pixel;
7136
7137 register int
7138 x;
7139
cristybb503372010-05-27 20:51:26 +00007140 register ssize_t
cristy3ed852e2009-09-05 21:47:34 +00007141 i;
7142
7143 register unsigned char
7144 *p,
7145 *q;
7146
cristy9d314ff2011-03-09 01:30:28 +00007147 ssize_t
7148 n;
7149
cristy3ed852e2009-09-05 21:47:34 +00007150 static unsigned int
7151 previous_magnify = 0;
7152
7153 static XWindowInfo
7154 magnify_window;
7155
7156 unsigned int
7157 height,
7158 j,
7159 k,
7160 l,
7161 magnify,
7162 scanline_pad,
7163 width;
7164
7165 XImage
7166 *ximage;
7167
7168 /*
7169 Check boundary conditions.
7170 */
7171 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
7172 assert(display != (Display *) NULL);
7173 assert(windows != (XWindows *) NULL);
7174 magnify=1;
cristybb503372010-05-27 20:51:26 +00007175 for (n=1; n < (ssize_t) windows->magnify.data; n++)
cristy3ed852e2009-09-05 21:47:34 +00007176 magnify<<=1;
7177 while ((magnify*windows->image.ximage->width) < windows->magnify.width)
7178 magnify<<=1;
7179 while ((magnify*windows->image.ximage->height) < windows->magnify.height)
7180 magnify<<=1;
7181 while (magnify > windows->magnify.width)
7182 magnify>>=1;
7183 while (magnify > windows->magnify.height)
7184 magnify>>=1;
7185 if (magnify != previous_magnify)
7186 {
7187 Status
7188 status;
7189
7190 XTextProperty
7191 window_name;
7192
7193 /*
7194 New magnify factor: update magnify window name.
7195 */
7196 i=0;
7197 while ((1 << i) <= (int) magnify)
7198 i++;
cristyb51dff52011-05-19 16:55:47 +00007199 (void) FormatLocaleString(windows->magnify.name,MaxTextExtent,
cristye8c25f92010-06-03 00:53:06 +00007200 "Magnify %.20gX",(double) i);
cristy3ed852e2009-09-05 21:47:34 +00007201 status=XStringListToTextProperty(&windows->magnify.name,1,&window_name);
7202 if (status != False)
7203 {
7204 XSetWMName(display,windows->magnify.id,&window_name);
7205 XSetWMIconName(display,windows->magnify.id,&window_name);
7206 (void) XFree((void *) window_name.value);
7207 }
7208 }
7209 previous_magnify=magnify;
7210 ximage=windows->image.ximage;
7211 width=(unsigned int) windows->magnify.ximage->width;
7212 height=(unsigned int) windows->magnify.ximage->height;
7213 if ((windows->magnify.x < 0) ||
7214 (windows->magnify.x >= windows->image.ximage->width))
7215 windows->magnify.x=windows->image.ximage->width >> 1;
7216 x=windows->magnify.x-((width/magnify) >> 1);
7217 if (x < 0)
7218 x=0;
7219 else
7220 if (x > (int) (ximage->width-(width/magnify)))
7221 x=ximage->width-width/magnify;
7222 if ((windows->magnify.y < 0) ||
7223 (windows->magnify.y >= windows->image.ximage->height))
7224 windows->magnify.y=windows->image.ximage->height >> 1;
7225 y=windows->magnify.y-((height/magnify) >> 1);
7226 if (y < 0)
7227 y=0;
7228 else
7229 if (y > (int) (ximage->height-(height/magnify)))
7230 y=ximage->height-height/magnify;
7231 q=(unsigned char *) windows->magnify.ximage->data;
7232 scanline_pad=(unsigned int) (windows->magnify.ximage->bytes_per_line-
7233 ((width*windows->magnify.ximage->bits_per_pixel) >> 3));
7234 if (ximage->bits_per_pixel < 8)
7235 {
7236 register unsigned char
7237 background,
7238 byte,
7239 foreground,
7240 p_bit,
7241 q_bit;
7242
7243 register unsigned int
7244 plane;
7245
7246 XPixelInfo
7247 *pixel_info;
7248
7249 pixel_info=windows->magnify.pixel_info;
7250 switch (ximage->bitmap_bit_order)
7251 {
7252 case LSBFirst:
7253 {
7254 /*
7255 Magnify little-endian bitmap.
7256 */
7257 background=0x00;
7258 foreground=0x80;
7259 if (ximage->format == XYBitmap)
7260 {
7261 background=(unsigned char)
7262 (XPixelIntensity(&pixel_info->foreground_color) <
7263 XPixelIntensity(&pixel_info->background_color) ? 0x80 : 0x00);
7264 foreground=(unsigned char)
7265 (XPixelIntensity(&pixel_info->background_color) <
7266 XPixelIntensity(&pixel_info->foreground_color) ? 0x80 : 0x00);
7267 if (windows->magnify.depth > 1)
7268 Swap(background,foreground);
7269 }
cristybb503372010-05-27 20:51:26 +00007270 for (i=0; i < (ssize_t) height; i+=magnify)
cristy3ed852e2009-09-05 21:47:34 +00007271 {
7272 /*
7273 Propogate pixel magnify rows.
7274 */
7275 for (j=0; j < magnify; j++)
7276 {
7277 p=(unsigned char *) ximage->data+y*ximage->bytes_per_line+
7278 ((x*ximage->bits_per_pixel) >> 3);
7279 p_bit=(unsigned char) (x*ximage->bits_per_pixel) & 0x07;
7280 q_bit=0;
7281 byte=0;
7282 for (k=0; k < width; k+=magnify)
7283 {
7284 /*
7285 Propogate pixel magnify columns.
7286 */
7287 for (l=0; l < magnify; l++)
7288 {
7289 /*
7290 Propogate each bit plane.
7291 */
7292 for (plane=0; (int) plane < ximage->bits_per_pixel; plane++)
7293 {
7294 byte>>=1;
7295 if (*p & (0x01 << (p_bit+plane)))
7296 byte|=foreground;
7297 else
7298 byte|=background;
7299 q_bit++;
7300 if (q_bit == 8)
7301 {
7302 *q++=byte;
7303 q_bit=0;
7304 byte=0;
7305 }
7306 }
7307 }
7308 p_bit+=ximage->bits_per_pixel;
7309 if (p_bit == 8)
7310 {
7311 p++;
7312 p_bit=0;
7313 }
7314 if (q_bit != 0)
7315 *q=byte >> (8-q_bit);
7316 q+=scanline_pad;
7317 }
7318 }
7319 y++;
7320 }
7321 break;
7322 }
7323 case MSBFirst:
7324 default:
7325 {
7326 /*
7327 Magnify big-endian bitmap.
7328 */
7329 background=0x00;
7330 foreground=0x01;
7331 if (ximage->format == XYBitmap)
7332 {
7333 background=(unsigned char)
7334 (XPixelIntensity(&pixel_info->foreground_color) <
7335 XPixelIntensity(&pixel_info->background_color) ? 0x01 : 0x00);
7336 foreground=(unsigned char)
7337 (XPixelIntensity(&pixel_info->background_color) <
7338 XPixelIntensity(&pixel_info->foreground_color) ? 0x01 : 0x00);
7339 if (windows->magnify.depth > 1)
7340 Swap(background,foreground);
7341 }
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 p_bit=(unsigned char) (x*ximage->bits_per_pixel) & 0x07;
7352 q_bit=0;
7353 byte=0;
7354 for (k=0; k < width; k+=magnify)
7355 {
7356 /*
7357 Propogate pixel magnify columns.
7358 */
7359 for (l=0; l < magnify; l++)
7360 {
7361 /*
7362 Propogate each bit plane.
7363 */
7364 for (plane=0; (int) plane < ximage->bits_per_pixel; plane++)
7365 {
7366 byte<<=1;
7367 if (*p & (0x80 >> (p_bit+plane)))
7368 byte|=foreground;
7369 else
7370 byte|=background;
7371 q_bit++;
7372 if (q_bit == 8)
7373 {
7374 *q++=byte;
7375 q_bit=0;
7376 byte=0;
7377 }
7378 }
7379 }
7380 p_bit+=ximage->bits_per_pixel;
7381 if (p_bit == 8)
7382 {
7383 p++;
7384 p_bit=0;
7385 }
7386 if (q_bit != 0)
7387 *q=byte << (8-q_bit);
7388 q+=scanline_pad;
7389 }
7390 }
7391 y++;
7392 }
7393 break;
7394 }
7395 }
7396 }
7397 else
7398 switch (ximage->bits_per_pixel)
7399 {
7400 case 6:
7401 case 8:
7402 {
7403 /*
7404 Magnify 8 bit X image.
7405 */
cristybb503372010-05-27 20:51:26 +00007406 for (i=0; i < (ssize_t) height; i+=magnify)
cristy3ed852e2009-09-05 21:47:34 +00007407 {
7408 /*
7409 Propogate pixel magnify rows.
7410 */
7411 for (j=0; j < magnify; j++)
7412 {
7413 p=(unsigned char *) ximage->data+y*ximage->bytes_per_line+
7414 ((x*ximage->bits_per_pixel) >> 3);
7415 for (k=0; k < width; k+=magnify)
7416 {
7417 /*
7418 Propogate pixel magnify columns.
7419 */
7420 for (l=0; l < magnify; l++)
7421 *q++=(*p);
7422 p++;
7423 }
7424 q+=scanline_pad;
7425 }
7426 y++;
7427 }
7428 break;
7429 }
7430 default:
7431 {
7432 register unsigned int
7433 bytes_per_pixel,
7434 m;
7435
7436 /*
7437 Magnify multi-byte X image.
7438 */
7439 bytes_per_pixel=(unsigned int) ximage->bits_per_pixel >> 3;
cristybb503372010-05-27 20:51:26 +00007440 for (i=0; i < (ssize_t) height; i+=magnify)
cristy3ed852e2009-09-05 21:47:34 +00007441 {
7442 /*
7443 Propogate pixel magnify rows.
7444 */
7445 for (j=0; j < magnify; j++)
7446 {
7447 p=(unsigned char *) ximage->data+y*ximage->bytes_per_line+
7448 ((x*ximage->bits_per_pixel) >> 3);
7449 for (k=0; k < width; k+=magnify)
7450 {
7451 /*
7452 Propogate pixel magnify columns.
7453 */
7454 for (l=0; l < magnify; l++)
7455 for (m=0; m < bytes_per_pixel; m++)
7456 *q++=(*(p+m));
7457 p+=bytes_per_pixel;
7458 }
7459 q+=scanline_pad;
7460 }
7461 y++;
7462 }
7463 break;
7464 }
7465 }
7466 /*
7467 Copy X image to magnify pixmap.
7468 */
7469 x=windows->magnify.x-((width/magnify) >> 1);
7470 if (x < 0)
7471 x=(int) ((width >> 1)-windows->magnify.x*magnify);
7472 else
7473 if (x > (int) (ximage->width-(width/magnify)))
7474 x=(int) ((ximage->width-windows->magnify.x)*magnify-(width >> 1));
7475 else
7476 x=0;
7477 y=windows->magnify.y-((height/magnify) >> 1);
7478 if (y < 0)
7479 y=(int) ((height >> 1)-windows->magnify.y*magnify);
7480 else
7481 if (y > (int) (ximage->height-(height/magnify)))
7482 y=(int) ((ximage->height-windows->magnify.y)*magnify-(height >> 1));
7483 else
7484 y=0;
7485 if ((x != 0) || (y != 0))
7486 (void) XFillRectangle(display,windows->magnify.pixmap,
7487 windows->magnify.annotate_context,0,0,width,height);
7488 (void) XPutImage(display,windows->magnify.pixmap,
7489 windows->magnify.annotate_context,windows->magnify.ximage,0,0,x,y,width-x,
7490 height-y);
7491 if ((magnify > 1) && ((magnify <= (width >> 1)) &&
7492 (magnify <= (height >> 1))))
7493 {
7494 RectangleInfo
7495 highlight_info;
7496
7497 /*
7498 Highlight center pixel.
7499 */
cristybb503372010-05-27 20:51:26 +00007500 highlight_info.x=(ssize_t) windows->magnify.width >> 1;
7501 highlight_info.y=(ssize_t) windows->magnify.height >> 1;
cristy3ed852e2009-09-05 21:47:34 +00007502 highlight_info.width=magnify;
7503 highlight_info.height=magnify;
7504 (void) XDrawRectangle(display,windows->magnify.pixmap,
7505 windows->magnify.highlight_context,(int) highlight_info.x,
7506 (int) highlight_info.y,(unsigned int) highlight_info.width-1,
7507 (unsigned int) highlight_info.height-1);
7508 if (magnify > 2)
7509 (void) XDrawRectangle(display,windows->magnify.pixmap,
7510 windows->magnify.annotate_context,(int) highlight_info.x+1,
7511 (int) highlight_info.y+1,(unsigned int) highlight_info.width-3,
7512 (unsigned int) highlight_info.height-3);
7513 }
7514 /*
7515 Show center pixel color.
7516 */
cristy3aa93752011-12-18 15:54:24 +00007517 (void) GetOneVirtualPixelInfo(windows->image.image,TileVirtualPixelMethod,
cristy52010022011-10-21 18:07:37 +00007518 (ssize_t) windows->magnify.x,(ssize_t) windows->magnify.y,&pixel,exception);
cristyb51dff52011-05-19 16:55:47 +00007519 (void) FormatLocaleString(tuple,MaxTextExtent,"%d,%d: ",
cristy3ed852e2009-09-05 21:47:34 +00007520 windows->magnify.x,windows->magnify.y);
7521 (void) ConcatenateMagickString(tuple,"(",MaxTextExtent);
cristyed231572011-07-14 02:18:59 +00007522 ConcatenateColorComponent(&pixel,RedPixelChannel,X11Compliance,tuple);
cristy3ed852e2009-09-05 21:47:34 +00007523 (void) ConcatenateMagickString(tuple,",",MaxTextExtent);
cristyed231572011-07-14 02:18:59 +00007524 ConcatenateColorComponent(&pixel,GreenPixelChannel,X11Compliance,tuple);
cristy3ed852e2009-09-05 21:47:34 +00007525 (void) ConcatenateMagickString(tuple,",",MaxTextExtent);
cristyed231572011-07-14 02:18:59 +00007526 ConcatenateColorComponent(&pixel,BluePixelChannel,X11Compliance,tuple);
cristy3ed852e2009-09-05 21:47:34 +00007527 if (pixel.colorspace == CMYKColorspace)
7528 {
7529 (void) ConcatenateMagickString(tuple,",",MaxTextExtent);
cristyed231572011-07-14 02:18:59 +00007530 ConcatenateColorComponent(&pixel,BlackPixelChannel,X11Compliance,tuple);
cristy3ed852e2009-09-05 21:47:34 +00007531 }
7532 if (pixel.matte != MagickFalse)
7533 {
7534 (void) ConcatenateMagickString(tuple,",",MaxTextExtent);
cristyed231572011-07-14 02:18:59 +00007535 ConcatenateColorComponent(&pixel,AlphaPixelChannel,X11Compliance,tuple);
cristy3ed852e2009-09-05 21:47:34 +00007536 }
7537 (void) ConcatenateMagickString(tuple,")",MaxTextExtent);
7538 height=(unsigned int) windows->magnify.font_info->ascent+
7539 windows->magnify.font_info->descent;
7540 x=windows->magnify.font_info->max_bounds.width >> 1;
7541 y=windows->magnify.font_info->ascent+(height >> 2);
7542 (void) XDrawImageString(display,windows->magnify.pixmap,
7543 windows->magnify.annotate_context,x,y,tuple,(int) strlen(tuple));
7544 GetColorTuple(&pixel,MagickTrue,tuple);
7545 y+=height;
7546 (void) XDrawImageString(display,windows->magnify.pixmap,
7547 windows->magnify.annotate_context,x,y,tuple,(int) strlen(tuple));
cristy269c9412011-10-13 23:41:15 +00007548 (void) QueryColorname(windows->image.image,&pixel,SVGCompliance,tuple,
cristy6710d842011-10-20 23:23:00 +00007549 exception);
cristy3ed852e2009-09-05 21:47:34 +00007550 y+=height;
7551 (void) XDrawImageString(display,windows->magnify.pixmap,
7552 windows->magnify.annotate_context,x,y,tuple,(int) strlen(tuple));
7553 /*
7554 Refresh magnify window.
7555 */
7556 magnify_window=windows->magnify;
7557 magnify_window.x=0;
7558 magnify_window.y=0;
7559 XRefreshWindow(display,&magnify_window,(XEvent *) NULL);
7560}
7561
7562/*
7563%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
7564% %
7565% %
7566% %
7567% X M a k e P i x m a p %
7568% %
7569% %
7570% %
7571%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
7572%
7573% XMakePixmap() creates an X11 pixmap.
7574%
7575% The format of the XMakePixmap method is:
7576%
7577% void XMakeStandardColormap(Display *display,XVisualInfo *visual_info,
7578% XResourceInfo *resource_info,Image *image,XStandardColormap *map_info,
7579% XPixelInfo *pixel)
7580%
7581% A description of each parameter follows:
7582%
7583% o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
7584%
7585% o display: Specifies a connection to an X server; returned from
7586% XOpenDisplay.
7587%
7588% o window: Specifies a pointer to a XWindowInfo structure.
7589%
cristy3ed852e2009-09-05 21:47:34 +00007590*/
7591static MagickBooleanType XMakePixmap(Display *display,
7592 const XResourceInfo *resource_info,XWindowInfo *window)
7593{
7594 unsigned int
7595 height,
7596 width;
7597
7598 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
7599 assert(display != (Display *) NULL);
7600 assert(resource_info != (XResourceInfo *) NULL);
7601 assert(window != (XWindowInfo *) NULL);
7602 if (window->pixmap != (Pixmap) NULL)
7603 {
7604 /*
7605 Destroy previous X pixmap.
7606 */
7607 (void) XFreePixmap(display,window->pixmap);
7608 window->pixmap=(Pixmap) NULL;
7609 }
7610 if (window->use_pixmap == MagickFalse)
7611 return(MagickFalse);
7612 if (window->ximage == (XImage *) NULL)
7613 return(MagickFalse);
7614 /*
7615 Display busy cursor.
7616 */
7617 (void) XCheckDefineCursor(display,window->id,window->busy_cursor);
7618 (void) XFlush(display);
7619 /*
7620 Create pixmap.
7621 */
7622 width=(unsigned int) window->ximage->width;
7623 height=(unsigned int) window->ximage->height;
7624 window->pixmap=XCreatePixmap(display,window->id,width,height,window->depth);
7625 if (window->pixmap == (Pixmap) NULL)
7626 {
7627 /*
7628 Unable to allocate pixmap.
7629 */
7630 (void) XCheckDefineCursor(display,window->id,window->cursor);
7631 return(MagickFalse);
7632 }
7633 /*
7634 Copy X image to pixmap.
7635 */
7636#if defined(MAGICKCORE_HAVE_SHARED_MEMORY)
7637 if (window->shared_memory)
7638 (void) XShmPutImage(display,window->pixmap,window->annotate_context,
7639 window->ximage,0,0,0,0,width,height,MagickTrue);
7640#endif
7641 if (window->shared_memory == MagickFalse)
7642 (void) XPutImage(display,window->pixmap,window->annotate_context,
7643 window->ximage,0,0,0,0,width,height);
7644 if (IsEventLogging())
7645 {
7646 (void) LogMagickEvent(X11Event,GetMagickModule(),"Pixmap:");
7647 (void) LogMagickEvent(X11Event,GetMagickModule()," width, height: %ux%u",
7648 width,height);
7649 }
7650 /*
7651 Restore cursor.
7652 */
7653 (void) XCheckDefineCursor(display,window->id,window->cursor);
7654 return(MagickTrue);
7655}
7656
7657/*
7658%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
7659% %
7660% %
7661% %
7662% X M a k e S t a n d a r d C o l o r m a p %
7663% %
7664% %
7665% %
7666%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
7667%
7668% XMakeStandardColormap() creates an X11 Standard Colormap.
7669%
7670% The format of the XMakeStandardColormap method is:
7671%
cristy6710d842011-10-20 23:23:00 +00007672% void XMakeStandardColormap(Display *display,XVisualInfo *visual_info,
7673% XResourceInfo *resource_info,Image *image,XStandardColormap *map_info,
7674% XPixelInfo *pixel,ExceptionInfo *exception)
cristy3ed852e2009-09-05 21:47:34 +00007675%
7676% A description of each parameter follows:
7677%
7678% o display: Specifies a connection to an X server; returned from
7679% XOpenDisplay.
7680%
7681% o visual_info: Specifies a pointer to a X11 XVisualInfo structure;
7682% returned from XGetVisualInfo.
7683%
7684% o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
7685%
7686% o image: the image.
7687%
7688% o map_info: If a Standard Colormap type is specified, this structure is
7689% initialized with info from the Standard Colormap.
7690%
7691% o pixel: Specifies a pointer to a XPixelInfo structure.
7692%
cristy6710d842011-10-20 23:23:00 +00007693% o exception: return any errors or warnings in this structure.
7694%
cristy3ed852e2009-09-05 21:47:34 +00007695*/
7696
7697#if defined(__cplusplus) || defined(c_plusplus)
7698extern "C" {
7699#endif
7700
7701static inline MagickRealType DiversityPixelIntensity(
7702 const DiversityPacket *pixel)
7703{
7704 MagickRealType
7705 intensity;
7706
7707 intensity=0.299*pixel->red+0.587*pixel->green+0.114*pixel->blue;
7708 return(intensity);
7709}
7710
7711static int IntensityCompare(const void *x,const void *y)
7712{
7713 DiversityPacket
7714 *color_1,
7715 *color_2;
7716
7717 int
7718 diversity;
7719
7720 color_1=(DiversityPacket *) x;
7721 color_2=(DiversityPacket *) y;
7722 diversity=(int) (DiversityPixelIntensity(color_2)-
7723 DiversityPixelIntensity(color_1));
7724 return(diversity);
7725}
7726
7727static int PopularityCompare(const void *x,const void *y)
7728{
7729 DiversityPacket
7730 *color_1,
7731 *color_2;
7732
7733 color_1=(DiversityPacket *) x;
7734 color_2=(DiversityPacket *) y;
7735 return((int) color_2->count-(int) color_1->count);
7736}
7737
7738#if defined(__cplusplus) || defined(c_plusplus)
7739}
7740#endif
7741
cristybb503372010-05-27 20:51:26 +00007742static inline Quantum ScaleXToQuantum(const size_t x,
7743 const size_t scale)
cristy3ed852e2009-09-05 21:47:34 +00007744{
7745 return((Quantum) (((MagickRealType) QuantumRange*x)/scale+0.5));
7746}
7747
cristybcbda3f2011-09-03 13:01:22 +00007748MagickPrivate void XMakeStandardColormap(Display *display,
cristy3ed852e2009-09-05 21:47:34 +00007749 XVisualInfo *visual_info,XResourceInfo *resource_info,Image *image,
cristy6710d842011-10-20 23:23:00 +00007750 XStandardColormap *map_info,XPixelInfo *pixel,ExceptionInfo *exception)
cristy3ed852e2009-09-05 21:47:34 +00007751{
7752 Colormap
7753 colormap;
7754
cristybb503372010-05-27 20:51:26 +00007755 register ssize_t
cristy3ed852e2009-09-05 21:47:34 +00007756 i;
7757
7758 Status
7759 status;
7760
cristybb503372010-05-27 20:51:26 +00007761 size_t
cristy3ed852e2009-09-05 21:47:34 +00007762 number_colors,
7763 retain_colors;
7764
7765 unsigned short
7766 gray_value;
7767
7768 XColor
7769 color,
7770 *colors,
7771 *p;
7772
7773 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
7774 assert(display != (Display *) NULL);
7775 assert(visual_info != (XVisualInfo *) NULL);
7776 assert(map_info != (XStandardColormap *) NULL);
7777 assert(resource_info != (XResourceInfo *) NULL);
7778 assert(pixel != (XPixelInfo *) NULL);
cristy3ed852e2009-09-05 21:47:34 +00007779 if (resource_info->map_type != (char *) NULL)
7780 {
7781 /*
7782 Standard Colormap is already defined (i.e. xstdcmap).
7783 */
cristy4c08aed2011-07-01 19:47:50 +00007784 XGetPixelInfo(display,visual_info,map_info,resource_info,image,
cristy3ed852e2009-09-05 21:47:34 +00007785 pixel);
7786 number_colors=(unsigned int) (map_info->base_pixel+
7787 (map_info->red_max+1)*(map_info->green_max+1)*(map_info->blue_max+1));
7788 if ((map_info->red_max*map_info->green_max*map_info->blue_max) != 0)
7789 if ((image->matte == MagickFalse) &&
7790 (resource_info->color_recovery == MagickFalse) &&
7791 resource_info->quantize_info->dither &&
7792 (number_colors < MaxColormapSize))
7793 {
7794 Image
7795 *affinity_image;
7796
cristy4c08aed2011-07-01 19:47:50 +00007797 register Quantum
cristyc47d1f82009-11-26 01:44:43 +00007798 *restrict q;
cristy3ed852e2009-09-05 21:47:34 +00007799
7800 /*
7801 Improve image appearance with error diffusion.
7802 */
cristy6710d842011-10-20 23:23:00 +00007803 affinity_image=AcquireImage((ImageInfo *) NULL,exception);
cristy3ed852e2009-09-05 21:47:34 +00007804 if (affinity_image == (Image *) NULL)
7805 ThrowXWindowFatalException(ResourceLimitFatalError,
7806 "UnableToDitherImage",image->filename);
7807 affinity_image->columns=number_colors;
7808 affinity_image->rows=1;
7809 /*
7810 Initialize colormap image.
7811 */
7812 q=QueueAuthenticPixels(affinity_image,0,0,affinity_image->columns,
7813 1,exception);
cristy4c08aed2011-07-01 19:47:50 +00007814 if (q != (Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00007815 {
cristybb503372010-05-27 20:51:26 +00007816 for (i=0; i < (ssize_t) number_colors; i++)
cristy3ed852e2009-09-05 21:47:34 +00007817 {
cristy4c08aed2011-07-01 19:47:50 +00007818 SetPixelRed(affinity_image,0,q);
cristy3ed852e2009-09-05 21:47:34 +00007819 if (map_info->red_max != 0)
cristy4c08aed2011-07-01 19:47:50 +00007820 SetPixelRed(affinity_image,
7821 ScaleXToQuantum((size_t) (i/map_info->red_mult),
7822 map_info->red_max),q);
7823 SetPixelGreen(affinity_image,0,q);
cristy3ed852e2009-09-05 21:47:34 +00007824 if (map_info->green_max != 0)
cristy4c08aed2011-07-01 19:47:50 +00007825 SetPixelGreen(affinity_image,
7826 ScaleXToQuantum((size_t) ((i/map_info->green_mult) %
7827 (map_info->green_max+1)),map_info->green_max),q);
7828 SetPixelBlue(affinity_image,0,q);
cristy3ed852e2009-09-05 21:47:34 +00007829 if (map_info->blue_max != 0)
cristy4c08aed2011-07-01 19:47:50 +00007830 SetPixelBlue(affinity_image,
7831 ScaleXToQuantum((size_t) (i % map_info->green_mult),
7832 map_info->blue_max),q);
7833 SetPixelAlpha(affinity_image,
7834 TransparentAlpha,q);
cristyed231572011-07-14 02:18:59 +00007835 q+=GetPixelChannels(affinity_image);
cristy3ed852e2009-09-05 21:47:34 +00007836 }
7837 (void) SyncAuthenticPixels(affinity_image,exception);
7838 (void) RemapImage(resource_info->quantize_info,image,
cristy018f07f2011-09-04 21:15:19 +00007839 affinity_image,exception);
cristy3ed852e2009-09-05 21:47:34 +00007840 }
cristy4c08aed2011-07-01 19:47:50 +00007841 XGetPixelInfo(display,visual_info,map_info,resource_info,image,
cristy3ed852e2009-09-05 21:47:34 +00007842 pixel);
cristy574cc262011-08-05 01:23:58 +00007843 (void) SetImageStorageClass(image,DirectClass,exception);
cristy3ed852e2009-09-05 21:47:34 +00007844 affinity_image=DestroyImage(affinity_image);
7845 }
7846 if (IsEventLogging())
7847 {
7848 (void) LogMagickEvent(X11Event,GetMagickModule(),
7849 "Standard Colormap:");
7850 (void) LogMagickEvent(X11Event,GetMagickModule(),
7851 " colormap id: 0x%lx",map_info->colormap);
7852 (void) LogMagickEvent(X11Event,GetMagickModule(),
7853 " red, green, blue max: %lu %lu %lu",map_info->red_max,
7854 map_info->green_max,map_info->blue_max);
7855 (void) LogMagickEvent(X11Event,GetMagickModule(),
7856 " red, green, blue mult: %lu %lu %lu",map_info->red_mult,
7857 map_info->green_mult,map_info->blue_mult);
7858 }
7859 return;
7860 }
7861 if ((visual_info->klass != DirectColor) &&
7862 (visual_info->klass != TrueColor))
7863 if ((image->storage_class == DirectClass) ||
7864 ((int) image->colors > visual_info->colormap_size))
7865 {
7866 QuantizeInfo
7867 quantize_info;
7868
7869 /*
7870 Image has more colors than the visual supports.
7871 */
7872 quantize_info=(*resource_info->quantize_info);
cristybb503372010-05-27 20:51:26 +00007873 quantize_info.number_colors=(size_t) visual_info->colormap_size;
cristy018f07f2011-09-04 21:15:19 +00007874 (void) QuantizeImage(&quantize_info,image,exception);
cristy3ed852e2009-09-05 21:47:34 +00007875 }
7876 /*
7877 Free previous and create new colormap.
7878 */
7879 (void) XFreeStandardColormap(display,visual_info,map_info,pixel);
7880 colormap=XDefaultColormap(display,visual_info->screen);
7881 if (visual_info->visual != XDefaultVisual(display,visual_info->screen))
7882 colormap=XCreateColormap(display,XRootWindow(display,visual_info->screen),
7883 visual_info->visual,visual_info->klass == DirectColor ?
7884 AllocAll : AllocNone);
7885 if (colormap == (Colormap) NULL)
7886 ThrowXWindowFatalException(ResourceLimitFatalError,"UnableToCreateColormap",
7887 image->filename);
7888 /*
7889 Initialize the map and pixel info structures.
7890 */
7891 XGetMapInfo(visual_info,colormap,map_info);
cristy4c08aed2011-07-01 19:47:50 +00007892 XGetPixelInfo(display,visual_info,map_info,resource_info,image,pixel);
cristy3ed852e2009-09-05 21:47:34 +00007893 /*
7894 Allocating colors in server colormap is based on visual class.
7895 */
7896 switch (visual_info->klass)
7897 {
7898 case StaticGray:
7899 case StaticColor:
7900 {
7901 /*
7902 Define Standard Colormap for StaticGray or StaticColor visual.
7903 */
7904 number_colors=image->colors;
7905 colors=(XColor *) AcquireQuantumMemory((size_t)
7906 visual_info->colormap_size,sizeof(*colors));
7907 if (colors == (XColor *) NULL)
7908 ThrowXWindowFatalException(ResourceLimitFatalError,
7909 "UnableToCreateColormap",image->filename);
7910 p=colors;
7911 color.flags=(char) (DoRed | DoGreen | DoBlue);
cristybb503372010-05-27 20:51:26 +00007912 for (i=0; i < (ssize_t) image->colors; i++)
cristy3ed852e2009-09-05 21:47:34 +00007913 {
7914 color.red=ScaleQuantumToShort(XRedGamma(image->colormap[i].red));
7915 color.green=ScaleQuantumToShort(XGreenGamma(image->colormap[i].green));
7916 color.blue=ScaleQuantumToShort(XBlueGamma(image->colormap[i].blue));
7917 if (visual_info->klass != StaticColor)
7918 {
7919 gray_value=(unsigned short) XPixelIntensity(&color);
7920 color.red=gray_value;
7921 color.green=gray_value;
7922 color.blue=gray_value;
7923 }
7924 status=XAllocColor(display,colormap,&color);
7925 if (status == False)
7926 {
7927 colormap=XCopyColormapAndFree(display,colormap);
7928 (void) XAllocColor(display,colormap,&color);
7929 }
7930 pixel->pixels[i]=color.pixel;
7931 *p++=color;
7932 }
7933 break;
7934 }
7935 case GrayScale:
7936 case PseudoColor:
7937 {
7938 unsigned int
7939 colormap_type;
7940
7941 /*
7942 Define Standard Colormap for GrayScale or PseudoColor visual.
7943 */
7944 number_colors=image->colors;
7945 colors=(XColor *) AcquireQuantumMemory((size_t)
7946 visual_info->colormap_size,sizeof(*colors));
7947 if (colors == (XColor *) NULL)
7948 ThrowXWindowFatalException(ResourceLimitFatalError,
7949 "UnableToCreateColormap",image->filename);
7950 /*
7951 Preallocate our GUI colors.
7952 */
7953 (void) XAllocColor(display,colormap,&pixel->foreground_color);
7954 (void) XAllocColor(display,colormap,&pixel->background_color);
7955 (void) XAllocColor(display,colormap,&pixel->border_color);
7956 (void) XAllocColor(display,colormap,&pixel->matte_color);
7957 (void) XAllocColor(display,colormap,&pixel->highlight_color);
7958 (void) XAllocColor(display,colormap,&pixel->shadow_color);
7959 (void) XAllocColor(display,colormap,&pixel->depth_color);
7960 (void) XAllocColor(display,colormap,&pixel->trough_color);
7961 for (i=0; i < MaxNumberPens; i++)
7962 (void) XAllocColor(display,colormap,&pixel->pen_colors[i]);
7963 /*
7964 Determine if image colors will "fit" into X server colormap.
7965 */
7966 colormap_type=resource_info->colormap;
cristyf2faecf2010-05-28 19:19:36 +00007967 status=XAllocColorCells(display,colormap,MagickFalse,(unsigned long *)
cristy3ed852e2009-09-05 21:47:34 +00007968 NULL,0,pixel->pixels,(unsigned int) image->colors);
7969 if (status != False)
7970 colormap_type=PrivateColormap;
7971 if (colormap_type == SharedColormap)
7972 {
cristyc57f6942010-11-12 01:47:39 +00007973 CacheView
7974 *image_view;
7975
cristy3ed852e2009-09-05 21:47:34 +00007976 DiversityPacket
7977 *diversity;
7978
7979 int
7980 y;
7981
7982 register int
7983 x;
7984
7985 unsigned short
7986 index;
7987
7988 XColor
7989 *server_colors;
7990
7991 /*
7992 Define Standard colormap for shared GrayScale or PseudoColor visual.
7993 */
7994 diversity=(DiversityPacket *) AcquireQuantumMemory(image->colors,
7995 sizeof(*diversity));
7996 if (diversity == (DiversityPacket *) NULL)
7997 ThrowXWindowFatalException(ResourceLimitFatalError,
7998 "UnableToCreateColormap",image->filename);
cristybb503372010-05-27 20:51:26 +00007999 for (i=0; i < (ssize_t) image->colors; i++)
cristy3ed852e2009-09-05 21:47:34 +00008000 {
cristye42f6582012-02-11 17:59:50 +00008001 diversity[i].red=ClampToQuantum(image->colormap[i].red);
8002 diversity[i].green=ClampToQuantum(image->colormap[i].green);
8003 diversity[i].blue=ClampToQuantum(image->colormap[i].blue);
cristy3ed852e2009-09-05 21:47:34 +00008004 diversity[i].index=(unsigned short) i;
8005 diversity[i].count=0;
8006 }
cristyc57f6942010-11-12 01:47:39 +00008007 image_view=AcquireCacheView(image);
cristy3ed852e2009-09-05 21:47:34 +00008008 for (y=0; y < (int) image->rows; y++)
8009 {
cristyc57f6942010-11-12 01:47:39 +00008010 register int
cristy3ed852e2009-09-05 21:47:34 +00008011 x;
8012
cristy4c08aed2011-07-01 19:47:50 +00008013 register const Quantum
cristyc57f6942010-11-12 01:47:39 +00008014 *restrict p;
cristy3ed852e2009-09-05 21:47:34 +00008015
cristyc57f6942010-11-12 01:47:39 +00008016 p=GetCacheViewAuthenticPixels(image_view,0,(ssize_t) y,
8017 image->columns,1,exception);
cristy4c08aed2011-07-01 19:47:50 +00008018 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00008019 break;
cristyc57f6942010-11-12 01:47:39 +00008020 for (x=(int) image->columns-1; x >= 0; x--)
cristy4c08aed2011-07-01 19:47:50 +00008021 {
8022 diversity[(ssize_t) GetPixelIndex(image,p)].count++;
cristyed231572011-07-14 02:18:59 +00008023 p+=GetPixelChannels(image);
cristy4c08aed2011-07-01 19:47:50 +00008024 }
cristy3ed852e2009-09-05 21:47:34 +00008025 }
cristyc57f6942010-11-12 01:47:39 +00008026 image_view=DestroyCacheView(image_view);
cristy3ed852e2009-09-05 21:47:34 +00008027 /*
8028 Sort colors by decreasing intensity.
8029 */
8030 qsort((void *) diversity,image->colors,sizeof(*diversity),
8031 IntensityCompare);
cristybb503372010-05-27 20:51:26 +00008032 for (i=0; i < (ssize_t) image->colors; )
cristy3ed852e2009-09-05 21:47:34 +00008033 {
8034 diversity[i].count<<=4; /* increase this colors popularity */
cristydfe2b662010-08-22 16:17:24 +00008035 i+=MagickMax((int) (image->colors >> 4),2);
cristy3ed852e2009-09-05 21:47:34 +00008036 }
8037 diversity[image->colors-1].count<<=4;
8038 qsort((void *) diversity,image->colors,sizeof(*diversity),
8039 PopularityCompare);
8040 /*
8041 Allocate colors.
8042 */
8043 p=colors;
8044 color.flags=(char) (DoRed | DoGreen | DoBlue);
cristybb503372010-05-27 20:51:26 +00008045 for (i=0; i < (ssize_t) image->colors; i++)
cristy3ed852e2009-09-05 21:47:34 +00008046 {
8047 index=diversity[i].index;
8048 color.red=
8049 ScaleQuantumToShort(XRedGamma(image->colormap[index].red));
8050 color.green=
8051 ScaleQuantumToShort(XGreenGamma(image->colormap[index].green));
8052 color.blue=
8053 ScaleQuantumToShort(XBlueGamma(image->colormap[index].blue));
8054 if (visual_info->klass != PseudoColor)
8055 {
8056 gray_value=(unsigned short) XPixelIntensity(&color);
8057 color.red=gray_value;
8058 color.green=gray_value;
8059 color.blue=gray_value;
8060 }
8061 status=XAllocColor(display,colormap,&color);
8062 if (status == False)
8063 break;
8064 pixel->pixels[index]=color.pixel;
8065 *p++=color;
8066 }
8067 /*
8068 Read X server colormap.
8069 */
8070 server_colors=(XColor *) AcquireQuantumMemory((size_t)
8071 visual_info->colormap_size,sizeof(*server_colors));
8072 if (server_colors == (XColor *) NULL)
8073 ThrowXWindowFatalException(ResourceLimitFatalError,
8074 "UnableToCreateColormap",image->filename);
8075 for (x=visual_info->colormap_size-1; x >= 0; x--)
cristybb503372010-05-27 20:51:26 +00008076 server_colors[x].pixel=(size_t) x;
cristy3ed852e2009-09-05 21:47:34 +00008077 (void) XQueryColors(display,colormap,server_colors,
8078 (int) MagickMin((unsigned int) visual_info->colormap_size,256));
8079 /*
8080 Select remaining colors from X server colormap.
8081 */
cristybb503372010-05-27 20:51:26 +00008082 for (; i < (ssize_t) image->colors; i++)
cristy3ed852e2009-09-05 21:47:34 +00008083 {
8084 index=diversity[i].index;
8085 color.red=
8086 ScaleQuantumToShort(XRedGamma(image->colormap[index].red));
8087 color.green=
8088 ScaleQuantumToShort(XGreenGamma(image->colormap[index].green));
8089 color.blue=
8090 ScaleQuantumToShort(XBlueGamma(image->colormap[index].blue));
8091 if (visual_info->klass != PseudoColor)
8092 {
8093 gray_value=(unsigned short) XPixelIntensity(&color);
8094 color.red=gray_value;
8095 color.green=gray_value;
8096 color.blue=gray_value;
8097 }
8098 XBestPixel(display,colormap,server_colors,(unsigned int)
8099 visual_info->colormap_size,&color);
8100 pixel->pixels[index]=color.pixel;
8101 *p++=color;
8102 }
8103 if ((int) image->colors < visual_info->colormap_size)
8104 {
8105 /*
8106 Fill up colors array-- more choices for pen colors.
8107 */
8108 retain_colors=MagickMin((unsigned int)
8109 (visual_info->colormap_size-image->colors),256);
cristybb503372010-05-27 20:51:26 +00008110 for (i=0; i < (ssize_t) retain_colors; i++)
cristy3ed852e2009-09-05 21:47:34 +00008111 *p++=server_colors[i];
8112 number_colors+=retain_colors;
8113 }
8114 server_colors=(XColor *) RelinquishMagickMemory(server_colors);
8115 diversity=(DiversityPacket *) RelinquishMagickMemory(diversity);
8116 break;
8117 }
8118 /*
8119 Define Standard colormap for private GrayScale or PseudoColor visual.
8120 */
8121 if (status == False)
8122 {
8123 /*
8124 Not enough colormap entries in the colormap-- Create a new colormap.
8125 */
8126 colormap=XCreateColormap(display,
8127 XRootWindow(display,visual_info->screen),visual_info->visual,
8128 AllocNone);
8129 if (colormap == (Colormap) NULL)
8130 ThrowXWindowFatalException(ResourceLimitFatalError,
8131 "UnableToCreateColormap",image->filename);
8132 map_info->colormap=colormap;
8133 if ((int) image->colors < visual_info->colormap_size)
8134 {
8135 /*
8136 Retain colors from the default colormap to help lessens the
8137 effects of colormap flashing.
8138 */
8139 retain_colors=MagickMin((unsigned int)
8140 (visual_info->colormap_size-image->colors),256);
8141 p=colors+image->colors;
cristybb503372010-05-27 20:51:26 +00008142 for (i=0; i < (ssize_t) retain_colors; i++)
cristy3ed852e2009-09-05 21:47:34 +00008143 {
cristyc57f6942010-11-12 01:47:39 +00008144 p->pixel=(unsigned long) i;
cristy3ed852e2009-09-05 21:47:34 +00008145 p++;
8146 }
8147 (void) XQueryColors(display,
8148 XDefaultColormap(display,visual_info->screen),
8149 colors+image->colors,(int) retain_colors);
8150 /*
8151 Transfer colors from default to private colormap.
8152 */
8153 (void) XAllocColorCells(display,colormap,MagickFalse,
cristyf2faecf2010-05-28 19:19:36 +00008154 (unsigned long *) NULL,0,pixel->pixels,(unsigned int)
cristy3ed852e2009-09-05 21:47:34 +00008155 retain_colors);
8156 p=colors+image->colors;
cristybb503372010-05-27 20:51:26 +00008157 for (i=0; i < (ssize_t) retain_colors; i++)
cristy3ed852e2009-09-05 21:47:34 +00008158 {
8159 p->pixel=pixel->pixels[i];
8160 p++;
8161 }
8162 (void) XStoreColors(display,colormap,colors+image->colors,
8163 (int) retain_colors);
8164 number_colors+=retain_colors;
8165 }
8166 (void) XAllocColorCells(display,colormap,MagickFalse,
cristyf2faecf2010-05-28 19:19:36 +00008167 (unsigned long *) NULL,0,pixel->pixels,(unsigned int)
cristy3ed852e2009-09-05 21:47:34 +00008168 image->colors);
8169 }
8170 /*
8171 Store the image colormap.
8172 */
8173 p=colors;
8174 color.flags=(char) (DoRed | DoGreen | DoBlue);
cristybb503372010-05-27 20:51:26 +00008175 for (i=0; i < (ssize_t) image->colors; i++)
cristy3ed852e2009-09-05 21:47:34 +00008176 {
8177 color.red=ScaleQuantumToShort(XRedGamma(image->colormap[i].red));
8178 color.green=ScaleQuantumToShort(XGreenGamma(image->colormap[i].green));
8179 color.blue=ScaleQuantumToShort(XBlueGamma(image->colormap[i].blue));
8180 if (visual_info->klass != PseudoColor)
8181 {
8182 gray_value=(unsigned short) XPixelIntensity(&color);
8183 color.red=gray_value;
8184 color.green=gray_value;
8185 color.blue=gray_value;
8186 }
8187 color.pixel=pixel->pixels[i];
8188 *p++=color;
8189 }
8190 (void) XStoreColors(display,colormap,colors,(int) image->colors);
8191 break;
8192 }
8193 case TrueColor:
8194 case DirectColor:
8195 default:
8196 {
8197 MagickBooleanType
8198 linear_colormap;
8199
8200 /*
8201 Define Standard Colormap for TrueColor or DirectColor visual.
8202 */
8203 number_colors=(unsigned int) ((map_info->red_max*map_info->red_mult)+
8204 (map_info->green_max*map_info->green_mult)+
8205 (map_info->blue_max*map_info->blue_mult)+1);
8206 linear_colormap=(number_colors > 4096) ||
8207 (((int) (map_info->red_max+1) == visual_info->colormap_size) &&
8208 ((int) (map_info->green_max+1) == visual_info->colormap_size) &&
8209 ((int) (map_info->blue_max+1) == visual_info->colormap_size)) ?
8210 MagickTrue : MagickFalse;
8211 if (linear_colormap != MagickFalse)
cristybb503372010-05-27 20:51:26 +00008212 number_colors=(size_t) visual_info->colormap_size;
cristy3ed852e2009-09-05 21:47:34 +00008213 /*
8214 Allocate color array.
8215 */
8216 colors=(XColor *) AcquireQuantumMemory(number_colors,sizeof(*colors));
8217 if (colors == (XColor *) NULL)
8218 ThrowXWindowFatalException(ResourceLimitFatalError,
8219 "UnableToCreateColormap",image->filename);
8220 /*
8221 Initialize linear color ramp.
8222 */
8223 p=colors;
8224 color.flags=(char) (DoRed | DoGreen | DoBlue);
8225 if (linear_colormap != MagickFalse)
cristybb503372010-05-27 20:51:26 +00008226 for (i=0; i < (ssize_t) number_colors; i++)
cristy3ed852e2009-09-05 21:47:34 +00008227 {
8228 color.blue=(unsigned short) 0;
8229 if (map_info->blue_max != 0)
cristybb503372010-05-27 20:51:26 +00008230 color.blue=(unsigned short) ((size_t)
cristy3ed852e2009-09-05 21:47:34 +00008231 ((65535L*(i % map_info->green_mult))/map_info->blue_max));
8232 color.green=color.blue;
8233 color.red=color.blue;
8234 color.pixel=XStandardPixel(map_info,&color);
8235 *p++=color;
8236 }
8237 else
cristybb503372010-05-27 20:51:26 +00008238 for (i=0; i < (ssize_t) number_colors; i++)
cristy3ed852e2009-09-05 21:47:34 +00008239 {
8240 color.red=(unsigned short) 0;
8241 if (map_info->red_max != 0)
cristybb503372010-05-27 20:51:26 +00008242 color.red=(unsigned short) ((size_t)
cristy3ed852e2009-09-05 21:47:34 +00008243 ((65535L*(i/map_info->red_mult))/map_info->red_max));
8244 color.green=(unsigned int) 0;
8245 if (map_info->green_max != 0)
cristybb503372010-05-27 20:51:26 +00008246 color.green=(unsigned short) ((size_t)
cristy3ed852e2009-09-05 21:47:34 +00008247 ((65535L*((i/map_info->green_mult) % (map_info->green_max+1)))/
8248 map_info->green_max));
8249 color.blue=(unsigned short) 0;
8250 if (map_info->blue_max != 0)
cristybb503372010-05-27 20:51:26 +00008251 color.blue=(unsigned short) ((size_t)
cristy3ed852e2009-09-05 21:47:34 +00008252 ((65535L*(i % map_info->green_mult))/map_info->blue_max));
8253 color.pixel=XStandardPixel(map_info,&color);
8254 *p++=color;
8255 }
8256 if ((visual_info->klass == DirectColor) &&
8257 (colormap != XDefaultColormap(display,visual_info->screen)))
8258 (void) XStoreColors(display,colormap,colors,(int) number_colors);
8259 else
cristybb503372010-05-27 20:51:26 +00008260 for (i=0; i < (ssize_t) number_colors; i++)
cristy3ed852e2009-09-05 21:47:34 +00008261 (void) XAllocColor(display,colormap,&colors[i]);
8262 break;
8263 }
8264 }
8265 if ((visual_info->klass != DirectColor) &&
8266 (visual_info->klass != TrueColor))
8267 {
8268 /*
8269 Set foreground, background, border, etc. pixels.
8270 */
8271 XBestPixel(display,colormap,colors,(unsigned int) number_colors,
8272 &pixel->foreground_color);
8273 XBestPixel(display,colormap,colors,(unsigned int) number_colors,
8274 &pixel->background_color);
8275 if (pixel->background_color.pixel == pixel->foreground_color.pixel)
8276 {
8277 /*
8278 Foreground and background colors must differ.
8279 */
8280 pixel->background_color.red=(~pixel->foreground_color.red);
8281 pixel->background_color.green=
8282 (~pixel->foreground_color.green);
8283 pixel->background_color.blue=
8284 (~pixel->foreground_color.blue);
8285 XBestPixel(display,colormap,colors,(unsigned int) number_colors,
8286 &pixel->background_color);
8287 }
8288 XBestPixel(display,colormap,colors,(unsigned int) number_colors,
8289 &pixel->border_color);
8290 XBestPixel(display,colormap,colors,(unsigned int) number_colors,
8291 &pixel->matte_color);
8292 XBestPixel(display,colormap,colors,(unsigned int) number_colors,
8293 &pixel->highlight_color);
8294 XBestPixel(display,colormap,colors,(unsigned int) number_colors,
8295 &pixel->shadow_color);
8296 XBestPixel(display,colormap,colors,(unsigned int) number_colors,
8297 &pixel->depth_color);
8298 XBestPixel(display,colormap,colors,(unsigned int) number_colors,
8299 &pixel->trough_color);
8300 for (i=0; i < MaxNumberPens; i++)
8301 {
8302 XBestPixel(display,colormap,colors,(unsigned int) number_colors,
8303 &pixel->pen_colors[i]);
8304 pixel->pixels[image->colors+i]=pixel->pen_colors[i].pixel;
8305 }
cristyc57f6942010-11-12 01:47:39 +00008306 pixel->colors=(ssize_t) (image->colors+MaxNumberPens);
cristy3ed852e2009-09-05 21:47:34 +00008307 }
8308 colors=(XColor *) RelinquishMagickMemory(colors);
8309 if (IsEventLogging())
8310 {
8311 (void) LogMagickEvent(X11Event,GetMagickModule(),"Standard Colormap:");
8312 (void) LogMagickEvent(X11Event,GetMagickModule()," colormap id: 0x%lx",
8313 map_info->colormap);
8314 (void) LogMagickEvent(X11Event,GetMagickModule(),
8315 " red, green, blue max: %lu %lu %lu",map_info->red_max,
8316 map_info->green_max,map_info->blue_max);
8317 (void) LogMagickEvent(X11Event,GetMagickModule(),
8318 " red, green, blue mult: %lu %lu %lu",map_info->red_mult,
8319 map_info->green_mult,map_info->blue_mult);
8320 }
8321}
8322
8323/*
8324%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8325% %
8326% %
8327% %
8328% X M a k e W i n d o w %
8329% %
8330% %
8331% %
8332%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8333%
8334% XMakeWindow() creates an X11 window.
8335%
8336% The format of the XMakeWindow method is:
8337%
8338% void XMakeWindow(Display *display,Window parent,char **argv,int argc,
8339% XClassHint *class_hint,XWMHints *manager_hints,
8340% XWindowInfo *window_info)
8341%
8342% A description of each parameter follows:
8343%
8344% o display: Specifies a connection to an X server; returned from
8345% XOpenDisplay.
8346%
8347% o parent: Specifies the parent window_info.
8348%
8349% o argv: Specifies the application's argument list.
8350%
8351% o argc: Specifies the number of arguments.
8352%
8353% o class_hint: Specifies a pointer to a X11 XClassHint structure.
8354%
8355% o manager_hints: Specifies a pointer to a X11 XWMHints structure.
8356%
8357% o window_info: Specifies a pointer to a X11 XWindowInfo structure.
8358%
8359*/
cristybcbda3f2011-09-03 13:01:22 +00008360MagickPrivate void XMakeWindow(Display *display,Window parent,char **argv,
cristy3ed852e2009-09-05 21:47:34 +00008361 int argc,XClassHint *class_hint,XWMHints *manager_hints,
8362 XWindowInfo *window_info)
8363{
8364#define MinWindowSize 64
8365
8366 Atom
8367 atom_list[2];
8368
8369 int
8370 gravity;
8371
8372 static XTextProperty
8373 icon_name,
8374 window_name;
8375
8376 Status
8377 status;
8378
8379 XSizeHints
8380 *size_hints;
8381
8382 /*
8383 Set window info hints.
8384 */
8385 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
8386 assert(display != (Display *) NULL);
8387 assert(window_info != (XWindowInfo *) NULL);
8388 size_hints=XAllocSizeHints();
8389 if (size_hints == (XSizeHints *) NULL)
8390 ThrowXWindowFatalException(XServerFatalError,"UnableToMakeXWindow",argv[0]);
cristydfe2b662010-08-22 16:17:24 +00008391 size_hints->flags=(int) window_info->flags;
cristy3ed852e2009-09-05 21:47:34 +00008392 size_hints->x=window_info->x;
8393 size_hints->y=window_info->y;
8394 size_hints->width=(int) window_info->width;
8395 size_hints->height=(int) window_info->height;
8396 if (window_info->immutable != MagickFalse)
8397 {
8398 /*
8399 Window size cannot be changed.
8400 */
8401 size_hints->min_width=size_hints->width;
8402 size_hints->min_height=size_hints->height;
8403 size_hints->max_width=size_hints->width;
8404 size_hints->max_height=size_hints->height;
8405 size_hints->flags|=PMinSize;
8406 size_hints->flags|=PMaxSize;
8407 }
8408 else
8409 {
8410 /*
8411 Window size can be changed.
8412 */
8413 size_hints->min_width=(int) window_info->min_width;
8414 size_hints->min_height=(int) window_info->min_height;
8415 size_hints->flags|=PResizeInc;
8416 size_hints->width_inc=(int) window_info->width_inc;
8417 size_hints->height_inc=(int) window_info->height_inc;
8418#if !defined(PRE_R4_ICCCM)
8419 size_hints->flags|=PBaseSize;
8420 size_hints->base_width=size_hints->width_inc;
8421 size_hints->base_height=size_hints->height_inc;
8422#endif
8423 }
8424 gravity=NorthWestGravity;
8425 if (window_info->geometry != (char *) NULL)
8426 {
8427 char
8428 default_geometry[MaxTextExtent],
8429 geometry[MaxTextExtent];
8430
8431 int
8432 flags;
8433
8434 register char
8435 *p;
8436
8437 /*
8438 User specified geometry.
8439 */
cristyb51dff52011-05-19 16:55:47 +00008440 (void) FormatLocaleString(default_geometry,MaxTextExtent,"%dx%d",
cristy3ed852e2009-09-05 21:47:34 +00008441 size_hints->width,size_hints->height);
8442 (void) CopyMagickString(geometry,window_info->geometry,MaxTextExtent);
8443 p=geometry;
8444 while (strlen(p) != 0)
8445 {
8446 if ((isspace((int) ((unsigned char) *p)) == 0) && (*p != '%'))
8447 p++;
8448 else
8449 (void) CopyMagickString(p,p+1,MaxTextExtent);
8450 }
8451 flags=XWMGeometry(display,window_info->screen,geometry,default_geometry,
8452 window_info->border_width,size_hints,&size_hints->x,&size_hints->y,
8453 &size_hints->width,&size_hints->height,&gravity);
8454 if ((flags & WidthValue) && (flags & HeightValue))
8455 size_hints->flags|=USSize;
8456 if ((flags & XValue) && (flags & YValue))
8457 {
8458 size_hints->flags|=USPosition;
8459 window_info->x=size_hints->x;
8460 window_info->y=size_hints->y;
8461 }
8462 }
8463#if !defined(PRE_R4_ICCCM)
8464 size_hints->win_gravity=gravity;
8465 size_hints->flags|=PWinGravity;
8466#endif
8467 if (window_info->id == (Window) NULL)
8468 window_info->id=XCreateWindow(display,parent,window_info->x,window_info->y,
8469 (unsigned int) size_hints->width,(unsigned int) size_hints->height,
8470 window_info->border_width,(int) window_info->depth,InputOutput,
cristyc57f6942010-11-12 01:47:39 +00008471 window_info->visual,(unsigned long) window_info->mask,
8472 &window_info->attributes);
cristy3ed852e2009-09-05 21:47:34 +00008473 else
8474 {
8475 MagickStatusType
8476 mask;
8477
8478 XEvent
8479 sans_event;
8480
8481 XWindowChanges
8482 window_changes;
8483
8484 /*
8485 Window already exists; change relevant attributes.
8486 */
cristyc57f6942010-11-12 01:47:39 +00008487 (void) XChangeWindowAttributes(display,window_info->id,(unsigned long)
8488 window_info->mask,&window_info->attributes);
cristy3ed852e2009-09-05 21:47:34 +00008489 mask=ConfigureNotify;
8490 while (XCheckTypedWindowEvent(display,window_info->id,(int) mask,&sans_event)) ;
8491 window_changes.x=window_info->x;
8492 window_changes.y=window_info->y;
8493 window_changes.width=(int) window_info->width;
8494 window_changes.height=(int) window_info->height;
8495 mask=(MagickStatusType) (CWWidth | CWHeight);
8496 if (window_info->flags & USPosition)
8497 mask|=CWX | CWY;
8498 (void) XReconfigureWMWindow(display,window_info->id,window_info->screen,
8499 mask,&window_changes);
8500 }
8501 if (window_info->id == (Window) NULL)
8502 ThrowXWindowFatalException(XServerFatalError,"UnableToCreateWindow",
8503 window_info->name);
8504 status=XStringListToTextProperty(&window_info->name,1,&window_name);
8505 if (status == False)
8506 ThrowXWindowFatalException(XServerFatalError,"UnableToCreateTextProperty",
8507 window_info->name);
8508 status=XStringListToTextProperty(&window_info->icon_name,1,&icon_name);
8509 if (status == False)
8510 ThrowXWindowFatalException(XServerFatalError,"UnableToCreateTextProperty",
8511 window_info->icon_name);
8512 if (window_info->icon_geometry != (char *) NULL)
8513 {
8514 int
8515 flags,
8516 height,
8517 width;
8518
8519 /*
8520 User specified icon geometry.
8521 */
8522 size_hints->flags|=USPosition;
8523 flags=XWMGeometry(display,window_info->screen,window_info->icon_geometry,
8524 (char *) NULL,0,size_hints,&manager_hints->icon_x,
8525 &manager_hints->icon_y,&width,&height,&gravity);
8526 if ((flags & XValue) && (flags & YValue))
8527 manager_hints->flags|=IconPositionHint;
8528 }
8529 XSetWMProperties(display,window_info->id,&window_name,&icon_name,argv,argc,
8530 size_hints,manager_hints,class_hint);
8531 if (window_name.value != (void *) NULL)
8532 {
8533 (void) XFree((void *) window_name.value);
8534 window_name.value=(unsigned char *) NULL;
8535 window_name.nitems=0;
8536 }
8537 if (icon_name.value != (void *) NULL)
8538 {
8539 (void) XFree((void *) icon_name.value);
8540 icon_name.value=(unsigned char *) NULL;
8541 icon_name.nitems=0;
8542 }
8543 atom_list[0]=XInternAtom(display,"WM_DELETE_WINDOW",MagickFalse);
8544 atom_list[1]=XInternAtom(display,"WM_TAKE_FOCUS",MagickFalse);
8545 (void) XSetWMProtocols(display,window_info->id,atom_list,2);
8546 (void) XFree((void *) size_hints);
8547 if (window_info->shape != MagickFalse)
8548 {
8549#if defined(MAGICKCORE_HAVE_SHAPE)
8550 int
8551 error_base,
8552 event_base;
8553
8554 /*
8555 Can we apply a non-rectangular shaping mask?
8556 */
8557 error_base=0;
8558 event_base=0;
8559 if (XShapeQueryExtension(display,&error_base,&event_base) == 0)
8560 window_info->shape=MagickFalse;
8561#else
8562 window_info->shape=MagickFalse;
8563#endif
8564 }
8565 if (window_info->shared_memory)
8566 {
8567#if defined(MAGICKCORE_HAVE_SHARED_MEMORY)
8568 /*
8569 Can we use shared memory with this window?
8570 */
8571 if (XShmQueryExtension(display) == 0)
8572 window_info->shared_memory=MagickFalse;
8573#else
8574 window_info->shared_memory=MagickFalse;
8575#endif
8576 }
8577 window_info->image=NewImageList();
8578 window_info->destroy=MagickFalse;
8579}
8580
8581/*
8582%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8583% %
8584% %
8585% %
8586% X M a g i c k P r o g r e s s M o n i t o r %
8587% %
8588% %
8589% %
8590%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8591%
8592% XMagickProgressMonitor() displays the progress a task is making in
8593% completing a task.
8594%
8595% The format of the XMagickProgressMonitor method is:
8596%
8597% void XMagickProgressMonitor(const char *task,
8598% const MagickOffsetType quantum,const MagickSizeType span,
8599% void *client_data)
8600%
8601% A description of each parameter follows:
8602%
8603% o task: Identifies the task in progress.
8604%
8605% o quantum: Specifies the quantum position within the span which represents
8606% how much progress has been made in completing a task.
8607%
8608% o span: Specifies the span relative to completing a task.
8609%
8610% o client_data: Pointer to any client data.
8611%
8612*/
8613
8614static const char *GetLocaleMonitorMessage(const char *text)
8615{
8616 char
8617 message[MaxTextExtent],
8618 tag[MaxTextExtent];
8619
8620 const char
8621 *locale_message;
8622
8623 register char
8624 *p;
8625
8626 (void) CopyMagickMemory(tag,text,MaxTextExtent);
8627 p=strrchr(tag,'/');
8628 if (p != (char *) NULL)
8629 *p='\0';
cristyb51dff52011-05-19 16:55:47 +00008630 (void) FormatLocaleString(message,MaxTextExtent,"Monitor/%s",tag);
cristy3ed852e2009-09-05 21:47:34 +00008631 locale_message=GetLocaleMessage(message);
8632 if (locale_message == message)
8633 return(text);
8634 return(locale_message);
8635}
8636
cristybcbda3f2011-09-03 13:01:22 +00008637MagickPrivate MagickBooleanType XMagickProgressMonitor(const char *tag,
cristy3ed852e2009-09-05 21:47:34 +00008638 const MagickOffsetType quantum,const MagickSizeType span,
8639 void *magick_unused(client_data))
8640{
8641 XWindows
8642 *windows;
8643
8644 windows=XSetWindows((XWindows *) ~0);
8645 if (windows == (XWindows *) NULL)
8646 return(MagickTrue);
8647 if (windows->info.mapped != MagickFalse)
8648 XProgressMonitorWidget(windows->display,windows,
8649 GetLocaleMonitorMessage(tag),quantum,span);
8650 return(MagickTrue);
8651}
8652
8653/*
8654%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8655% %
8656% %
8657% %
8658% X Q u e r y C o l o r D a t a b a s e %
8659% %
8660% %
8661% %
8662%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8663%
cristy9950d572011-10-01 18:22:35 +00008664% XQueryColorCompliance() looks up a RGB values for a color given in the target
cristy3ed852e2009-09-05 21:47:34 +00008665% string.
8666%
8667% The format of the XQueryColorDatabase method is:
8668%
cristy9950d572011-10-01 18:22:35 +00008669% MagickBooleanType XQueryColorCompliance(const char *target,XColor *color)
cristy3ed852e2009-09-05 21:47:34 +00008670%
8671% A description of each parameter follows:
8672%
8673% o target: Specifies the color to lookup in the X color database.
8674%
cristy101ab702011-10-13 13:06:32 +00008675% o color: A pointer to an PixelInfo structure. The RGB value of the target
cristy3ed852e2009-09-05 21:47:34 +00008676% color is returned as this value.
8677%
8678*/
cristy9950d572011-10-01 18:22:35 +00008679MagickPrivate MagickBooleanType XQueryColorCompliance(const char *target,
cristy3ed852e2009-09-05 21:47:34 +00008680 XColor *color)
8681{
8682 Colormap
8683 colormap;
8684
8685 static Display
8686 *display = (Display *) NULL;
8687
8688 Status
8689 status;
8690
8691 XColor
8692 xcolor;
8693
8694 /*
8695 Initialize color return value.
8696 */
8697 assert(color != (XColor *) NULL);
8698 color->red=0;
8699 color->green=0;
8700 color->blue=0;
8701 color->flags=(char) (DoRed | DoGreen | DoBlue);
8702 if ((target == (char *) NULL) || (*target == '\0'))
8703 target="#ffffffffffff";
8704 /*
8705 Let the X server define the color for us.
8706 */
8707 if (display == (Display *) NULL)
8708 display=XOpenDisplay((char *) NULL);
8709 if (display == (Display *) NULL)
8710 {
8711 ThrowXWindowFatalException(XServerError,"ColorIsNotKnownToServer",target);
8712 return(MagickFalse);
8713 }
8714 colormap=XDefaultColormap(display,XDefaultScreen(display));
8715 status=XParseColor(display,colormap,(char *) target,&xcolor);
8716 if (status == False)
8717 ThrowXWindowFatalException(XServerError,"ColorIsNotKnownToServer",target)
8718 else
8719 {
8720 color->red=xcolor.red;
8721 color->green=xcolor.green;
8722 color->blue=xcolor.blue;
8723 color->flags=xcolor.flags;
8724 }
8725 return(status != False ? MagickTrue : MagickFalse);
8726}
8727
8728/*
8729%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8730% %
8731% %
8732% %
8733% X Q u e r y P o s i t i o n %
8734% %
8735% %
8736% %
8737%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8738%
8739% XQueryPosition() gets the pointer coordinates relative to a window.
8740%
8741% The format of the XQueryPosition method is:
8742%
8743% void XQueryPosition(Display *display,const Window window,int *x,int *y)
8744%
8745% A description of each parameter follows:
8746%
8747% o display: Specifies a connection to an X server; returned from
8748% XOpenDisplay.
8749%
8750% o window: Specifies a pointer to a Window.
8751%
8752% o x: Return the x coordinate of the pointer relative to the origin of the
8753% window.
8754%
8755% o y: Return the y coordinate of the pointer relative to the origin of the
8756% window.
8757%
8758*/
cristybcbda3f2011-09-03 13:01:22 +00008759MagickPrivate void XQueryPosition(Display *display,const Window window,int *x,int *y)
cristy3ed852e2009-09-05 21:47:34 +00008760{
8761 int
8762 x_root,
8763 y_root;
8764
8765 unsigned int
8766 mask;
8767
8768 Window
8769 root_window;
8770
8771 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
8772 assert(display != (Display *) NULL);
8773 assert(window != (Window) NULL);
8774 assert(x != (int *) NULL);
8775 assert(y != (int *) NULL);
8776 (void) XQueryPointer(display,window,&root_window,&root_window,&x_root,&y_root,
8777 x,y,&mask);
8778}
8779
8780/*
8781%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8782% %
8783% %
8784% %
8785% X R e f r e s h W i n d o w %
8786% %
8787% %
8788% %
8789%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8790%
8791% XRefreshWindow() refreshes an image in a X window.
8792%
8793% The format of the XRefreshWindow method is:
8794%
8795% void XRefreshWindow(Display *display,const XWindowInfo *window,
8796% const XEvent *event)
8797%
8798% A description of each parameter follows:
8799%
8800% o display: Specifies a connection to an X server; returned from
8801% XOpenDisplay.
8802%
8803% o window: Specifies a pointer to a XWindowInfo structure.
8804%
8805% o event: Specifies a pointer to a XEvent structure. If it is NULL,
8806% the entire image is refreshed.
8807%
8808*/
cristybcbda3f2011-09-03 13:01:22 +00008809MagickPrivate void XRefreshWindow(Display *display,const XWindowInfo *window,
cristy3ed852e2009-09-05 21:47:34 +00008810 const XEvent *event)
8811{
8812 int
8813 x,
8814 y;
8815
8816 unsigned int
8817 height,
8818 width;
8819
8820 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
8821 assert(display != (Display *) NULL);
8822 assert(window != (XWindowInfo *) NULL);
8823 if (window->ximage == (XImage *) NULL)
8824 return;
8825 if (event != (XEvent *) NULL)
8826 {
8827 /*
8828 Determine geometry from expose event.
8829 */
8830 x=event->xexpose.x;
8831 y=event->xexpose.y;
8832 width=(unsigned int) event->xexpose.width;
8833 height=(unsigned int) event->xexpose.height;
8834 }
8835 else
8836 {
8837 XEvent
8838 sans_event;
8839
8840 /*
8841 Refresh entire window; discard outstanding expose events.
8842 */
8843 x=0;
8844 y=0;
8845 width=window->width;
8846 height=window->height;
8847 while (XCheckTypedWindowEvent(display,window->id,Expose,&sans_event)) ;
cristya0e5ad52010-02-10 02:05:12 +00008848 if (window->matte_pixmap != (Pixmap) NULL)
8849 {
8850#if defined(MAGICKCORE_HAVE_SHAPE)
8851 if (window->shape != MagickFalse)
8852 XShapeCombineMask(display,window->id,ShapeBounding,0,0,
8853 window->matte_pixmap,ShapeSet);
8854#endif
8855 }
cristy3ed852e2009-09-05 21:47:34 +00008856 }
8857 /*
8858 Check boundary conditions.
8859 */
8860 if ((window->ximage->width-(x+window->x)) < (int) width)
8861 width=(unsigned int) (window->ximage->width-(x+window->x));
8862 if ((window->ximage->height-(y+window->y)) < (int) height)
8863 height=(unsigned int) (window->ximage->height-(y+window->y));
8864 /*
8865 Refresh image.
8866 */
8867 if (window->matte_pixmap != (Pixmap) NULL)
cristya0e5ad52010-02-10 02:05:12 +00008868 (void) XSetClipMask(display,window->annotate_context,window->matte_pixmap);
cristy3ed852e2009-09-05 21:47:34 +00008869 if (window->pixmap != (Pixmap) NULL)
8870 {
8871 if (window->depth > 1)
8872 (void) XCopyArea(display,window->pixmap,window->id,
8873 window->annotate_context,x+window->x,y+window->y,width,height,x,y);
8874 else
8875 (void) XCopyPlane(display,window->pixmap,window->id,
8876 window->highlight_context,x+window->x,y+window->y,width,height,x,y,
8877 1L);
8878 }
8879 else
8880 {
8881#if defined(MAGICKCORE_HAVE_SHARED_MEMORY)
8882 if (window->shared_memory)
8883 (void) XShmPutImage(display,window->id,window->annotate_context,
8884 window->ximage,x+window->x,y+window->y,x,y,width,height,MagickTrue);
8885#endif
8886 if (window->shared_memory == MagickFalse)
8887 (void) XPutImage(display,window->id,window->annotate_context,
8888 window->ximage,x+window->x,y+window->y,x,y,width,height);
8889 }
8890 if (window->matte_pixmap != (Pixmap) NULL)
8891 (void) XSetClipMask(display,window->annotate_context,None);
8892 (void) XFlush(display);
8893}
8894
8895/*
8896%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8897% %
8898% %
8899% %
8900% X R e m o t e C o m m a n d %
8901% %
8902% %
8903% %
8904%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8905%
8906% XRemoteCommand() forces a remote display(1) to display the specified
8907% image filename.
8908%
8909% The format of the XRemoteCommand method is:
8910%
8911% MagickBooleanType XRemoteCommand(Display *display,const char *window,
8912% const char *filename)
8913%
8914% A description of each parameter follows:
8915%
8916% o display: Specifies a connection to an X server; returned from
8917% XOpenDisplay.
8918%
8919% o window: Specifies the name or id of an X window.
8920%
8921% o filename: the name of the image filename to display.
8922%
8923*/
8924MagickExport MagickBooleanType XRemoteCommand(Display *display,
8925 const char *window,const char *filename)
8926{
8927 Atom
8928 remote_atom;
8929
8930 Window
8931 remote_window,
8932 root_window;
8933
8934 assert(filename != (char *) NULL);
8935 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",filename);
8936 if (display == (Display *) NULL)
8937 display=XOpenDisplay((char *) NULL);
8938 if (display == (Display *) NULL)
8939 {
8940 ThrowXWindowException(XServerError,"UnableToOpenXServer",filename);
8941 return(MagickFalse);
8942 }
8943 remote_atom=XInternAtom(display,"IM_PROTOCOLS",MagickFalse);
8944 remote_window=(Window) NULL;
8945 root_window=XRootWindow(display,XDefaultScreen(display));
8946 if (window != (char *) NULL)
8947 {
8948 /*
8949 Search window hierarchy and identify any clients by name or ID.
8950 */
8951 if (isdigit((unsigned char) *window) != 0)
8952 remote_window=XWindowByID(display,root_window,(Window)
8953 strtol((char *) window,(char **) NULL,0));
8954 if (remote_window == (Window) NULL)
8955 remote_window=XWindowByName(display,root_window,window);
8956 }
8957 if (remote_window == (Window) NULL)
8958 remote_window=XWindowByProperty(display,root_window,remote_atom);
8959 if (remote_window == (Window) NULL)
8960 {
8961 ThrowXWindowException(XServerError,"UnableToConnectToRemoteDisplay",
8962 filename);
8963 return(MagickFalse);
8964 }
8965 /*
8966 Send remote command.
8967 */
8968 remote_atom=XInternAtom(display,"IM_REMOTE_COMMAND",MagickFalse);
8969 (void) XChangeProperty(display,remote_window,remote_atom,XA_STRING,8,
8970 PropModeReplace,(unsigned char *) filename,(int) strlen(filename));
8971 (void) XSync(display,MagickFalse);
8972 return(MagickTrue);
8973}
8974
8975/*
8976%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8977% %
8978% %
8979% %
8980% X R e t a i n W i n d o w C o l o r s %
8981% %
8982% %
8983% %
8984%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8985%
8986% XRetainWindowColors() sets X11 color resources on a window. This preserves
8987% the colors associated with an image displayed on the window.
8988%
8989% The format of the XRetainWindowColors method is:
8990%
8991% void XRetainWindowColors(Display *display,const Window window)
8992%
8993% A description of each parameter follows:
8994%
8995% o display: Specifies a connection to an X server; returned from
8996% XOpenDisplay.
8997%
8998% o window: Specifies a pointer to a XWindowInfo structure.
8999%
9000*/
9001MagickExport void XRetainWindowColors(Display *display,const Window window)
9002{
9003 Atom
9004 property;
9005
9006 Pixmap
9007 pixmap;
9008
9009 /*
9010 Put property on the window.
9011 */
9012 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
9013 assert(display != (Display *) NULL);
9014 assert(window != (Window) NULL);
9015 property=XInternAtom(display,"_XSETROOT_ID",MagickFalse);
9016 if (property == (Atom) NULL)
9017 {
9018 ThrowXWindowFatalException(XServerError,"UnableToCreateProperty",
9019 "_XSETROOT_ID");
9020 return;
9021 }
9022 pixmap=XCreatePixmap(display,window,1,1,1);
9023 if (pixmap == (Pixmap) NULL)
9024 {
9025 ThrowXWindowFatalException(XServerError,"UnableToCreateBitmap","");
9026 return;
9027 }
9028 (void) XChangeProperty(display,window,property,XA_PIXMAP,32,PropModeReplace,
9029 (unsigned char *) &pixmap,1);
9030 (void) XSetCloseDownMode(display,RetainPermanent);
9031}
9032
9033/*
9034%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9035% %
9036% %
9037% %
9038% X S e l e c t W i n d o w %
9039% %
9040% %
9041% %
9042%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9043%
9044% XSelectWindow() allows a user to select a window using the mouse. If the
9045% mouse moves, a cropping rectangle is drawn and the extents of the rectangle
9046% is returned in the crop_info structure.
9047%
9048% The format of the XSelectWindow function is:
9049%
9050% target_window=XSelectWindow(display,crop_info)
9051%
9052% A description of each parameter follows:
9053%
9054% o window: XSelectWindow returns the window id.
9055%
9056% o display: Specifies a pointer to the Display structure; returned from
9057% XOpenDisplay.
9058%
9059% o crop_info: Specifies a pointer to a RectangleInfo structure. It
9060% contains the extents of any cropping rectangle.
9061%
cristy3ed852e2009-09-05 21:47:34 +00009062*/
9063static Window XSelectWindow(Display *display,RectangleInfo *crop_info)
9064{
9065#define MinimumCropArea (unsigned int) 9
9066
9067 Cursor
9068 target_cursor;
9069
9070 GC
9071 annotate_context;
9072
9073 int
9074 presses,
9075 x_offset,
9076 y_offset;
9077
9078 Status
9079 status;
9080
9081 Window
9082 root_window,
9083 target_window;
9084
9085 XEvent
9086 event;
9087
9088 XGCValues
9089 context_values;
9090
9091 /*
9092 Initialize graphic context.
9093 */
9094 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
9095 assert(display != (Display *) NULL);
9096 assert(crop_info != (RectangleInfo *) NULL);
9097 root_window=XRootWindow(display,XDefaultScreen(display));
9098 context_values.background=XBlackPixel(display,XDefaultScreen(display));
9099 context_values.foreground=XWhitePixel(display,XDefaultScreen(display));
9100 context_values.function=GXinvert;
9101 context_values.plane_mask=
9102 context_values.background ^ context_values.foreground;
9103 context_values.subwindow_mode=IncludeInferiors;
cristybb503372010-05-27 20:51:26 +00009104 annotate_context=XCreateGC(display,root_window,(size_t) (GCBackground |
cristy3ed852e2009-09-05 21:47:34 +00009105 GCForeground | GCFunction | GCSubwindowMode),&context_values);
9106 if (annotate_context == (GC) NULL)
9107 return(MagickFalse);
9108 /*
9109 Grab the pointer using target cursor.
9110 */
9111 target_cursor=XMakeCursor(display,root_window,XDefaultColormap(display,
9112 XDefaultScreen(display)),(char * ) "white",(char * ) "black");
9113 status=XGrabPointer(display,root_window,MagickFalse,(unsigned int)
9114 (ButtonPressMask | ButtonReleaseMask | ButtonMotionMask),GrabModeSync,
9115 GrabModeAsync,root_window,target_cursor,CurrentTime);
9116 if (status != GrabSuccess)
9117 {
9118 ThrowXWindowFatalException(XServerError,"UnableToGrabMouse","");
9119 return((Window) NULL);
9120 }
9121 /*
9122 Select a window.
9123 */
9124 crop_info->width=0;
9125 crop_info->height=0;
9126 presses=0;
9127 target_window=(Window) NULL;
9128 x_offset=0;
9129 y_offset=0;
9130 do
9131 {
9132 if ((crop_info->width*crop_info->height) >= MinimumCropArea)
9133 (void) XDrawRectangle(display,root_window,annotate_context,
9134 (int) crop_info->x,(int) crop_info->y,(unsigned int) crop_info->width-1,
9135 (unsigned int) crop_info->height-1);
9136 /*
9137 Allow another event.
9138 */
9139 (void) XAllowEvents(display,SyncPointer,CurrentTime);
9140 (void) XWindowEvent(display,root_window,ButtonPressMask |
9141 ButtonReleaseMask | ButtonMotionMask,&event);
9142 if ((crop_info->width*crop_info->height) >= MinimumCropArea)
9143 (void) XDrawRectangle(display,root_window,annotate_context,
9144 (int) crop_info->x,(int) crop_info->y,(unsigned int) crop_info->width-1,
9145 (unsigned int) crop_info->height-1);
9146 switch (event.type)
9147 {
9148 case ButtonPress:
9149 {
9150 target_window=XGetSubwindow(display,event.xbutton.subwindow,
9151 event.xbutton.x,event.xbutton.y);
9152 if (target_window == (Window) NULL)
9153 target_window=root_window;
9154 x_offset=event.xbutton.x_root;
9155 y_offset=event.xbutton.y_root;
cristyecd0ab52010-05-30 14:59:20 +00009156 crop_info->x=(ssize_t) x_offset;
9157 crop_info->y=(ssize_t) y_offset;
cristy3ed852e2009-09-05 21:47:34 +00009158 crop_info->width=0;
9159 crop_info->height=0;
9160 presses++;
9161 break;
9162 }
9163 case ButtonRelease:
9164 {
9165 presses--;
9166 break;
9167 }
9168 case MotionNotify:
9169 {
9170 /*
9171 Discard pending button motion events.
9172 */
9173 while (XCheckMaskEvent(display,ButtonMotionMask,&event)) ;
cristyecd0ab52010-05-30 14:59:20 +00009174 crop_info->x=(ssize_t) event.xmotion.x;
9175 crop_info->y=(ssize_t) event.xmotion.y;
cristy3ed852e2009-09-05 21:47:34 +00009176 /*
9177 Check boundary conditions.
9178 */
9179 if ((int) crop_info->x < x_offset)
cristyecd0ab52010-05-30 14:59:20 +00009180 crop_info->width=(size_t) (x_offset-crop_info->x);
cristy3ed852e2009-09-05 21:47:34 +00009181 else
9182 {
cristyecd0ab52010-05-30 14:59:20 +00009183 crop_info->width=(size_t) (crop_info->x-x_offset);
9184 crop_info->x=(ssize_t) x_offset;
cristy3ed852e2009-09-05 21:47:34 +00009185 }
9186 if ((int) crop_info->y < y_offset)
cristyecd0ab52010-05-30 14:59:20 +00009187 crop_info->height=(size_t) (y_offset-crop_info->y);
cristy3ed852e2009-09-05 21:47:34 +00009188 else
9189 {
cristyecd0ab52010-05-30 14:59:20 +00009190 crop_info->height=(size_t) (crop_info->y-y_offset);
9191 crop_info->y=(ssize_t) y_offset;
cristy3ed852e2009-09-05 21:47:34 +00009192 }
9193 }
9194 default:
9195 break;
9196 }
9197 } while ((target_window == (Window) NULL) || (presses > 0));
9198 (void) XUngrabPointer(display,CurrentTime);
9199 (void) XFreeCursor(display,target_cursor);
9200 (void) XFreeGC(display,annotate_context);
9201 if ((crop_info->width*crop_info->height) < MinimumCropArea)
9202 {
9203 crop_info->width=0;
9204 crop_info->height=0;
9205 }
9206 if ((crop_info->width != 0) && (crop_info->height != 0))
9207 target_window=root_window;
9208 return(target_window);
9209}
9210
9211/*
9212%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9213% %
9214% %
9215% %
9216% X S e t C u r s o r S t a t e %
9217% %
9218% %
9219% %
9220%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9221%
9222% XSetCursorState() sets the cursor state to busy, otherwise the cursor are
9223% reset to their default.
9224%
9225% The format of the XXSetCursorState method is:
9226%
9227% XSetCursorState(display,windows,const MagickStatusType state)
9228%
9229% A description of each parameter follows:
9230%
9231% o display: Specifies a connection to an X server; returned from
9232% XOpenDisplay.
9233%
9234% o windows: Specifies a pointer to a XWindows structure.
9235%
9236% o state: An unsigned integer greater than 0 sets the cursor state
9237% to busy, otherwise the cursor are reset to their default.
9238%
9239*/
cristybcbda3f2011-09-03 13:01:22 +00009240MagickPrivate void XSetCursorState(Display *display,XWindows *windows,
cristy3ed852e2009-09-05 21:47:34 +00009241 const MagickStatusType state)
9242{
9243 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
9244 assert(display != (Display *) NULL);
9245 assert(windows != (XWindows *) NULL);
9246 if (state)
9247 {
9248 (void) XCheckDefineCursor(display,windows->image.id,
9249 windows->image.busy_cursor);
9250 (void) XCheckDefineCursor(display,windows->pan.id,
9251 windows->pan.busy_cursor);
9252 (void) XCheckDefineCursor(display,windows->magnify.id,
9253 windows->magnify.busy_cursor);
9254 (void) XCheckDefineCursor(display,windows->command.id,
9255 windows->command.busy_cursor);
9256 }
9257 else
9258 {
9259 (void) XCheckDefineCursor(display,windows->image.id,
9260 windows->image.cursor);
9261 (void) XCheckDefineCursor(display,windows->pan.id,windows->pan.cursor);
9262 (void) XCheckDefineCursor(display,windows->magnify.id,
9263 windows->magnify.cursor);
9264 (void) XCheckDefineCursor(display,windows->command.id,
9265 windows->command.cursor);
9266 (void) XCheckDefineCursor(display,windows->command.id,
9267 windows->widget.cursor);
9268 (void) XWithdrawWindow(display,windows->info.id,windows->info.screen);
9269 }
9270 windows->info.mapped=MagickFalse;
9271}
9272
9273/*
9274%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9275% %
9276% %
9277% %
9278% X S e t W i n d o w s %
9279% %
9280% %
9281% %
9282%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9283%
9284% XSetWindows() sets the X windows structure if the windows info is specified.
9285% Otherwise the current windows structure is returned.
9286%
9287% The format of the XSetWindows method is:
9288%
9289% XWindows *XSetWindows(XWindows *windows_info)
9290%
9291% A description of each parameter follows:
9292%
9293% o windows_info: Initialize the Windows structure with this information.
9294%
9295*/
cristybcbda3f2011-09-03 13:01:22 +00009296MagickPrivate XWindows *XSetWindows(XWindows *windows_info)
cristy3ed852e2009-09-05 21:47:34 +00009297{
9298 static XWindows
9299 *windows = (XWindows *) NULL;
9300
9301 if (windows_info != (XWindows *) ~0)
9302 {
9303 windows=(XWindows *) RelinquishMagickMemory(windows);
9304 windows=windows_info;
9305 }
9306 return(windows);
9307}
9308/*
9309%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9310% %
9311% %
9312% %
9313% X U s e r P r e f e r e n c e s %
9314% %
9315% %
9316% %
9317%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9318%
9319% XUserPreferences() saves the preferences in a configuration file in the
9320% users' home directory.
9321%
9322% The format of the XUserPreferences method is:
9323%
9324% void XUserPreferences(XResourceInfo *resource_info)
9325%
9326% A description of each parameter follows:
9327%
9328% o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
9329%
9330*/
cristybcbda3f2011-09-03 13:01:22 +00009331MagickPrivate void XUserPreferences(XResourceInfo *resource_info)
cristy3ed852e2009-09-05 21:47:34 +00009332{
9333#if defined(X11_PREFERENCES_PATH)
9334 char
9335 cache[MaxTextExtent],
9336 filename[MaxTextExtent],
9337 specifier[MaxTextExtent];
9338
9339 const char
cristy104cea82009-10-25 02:26:51 +00009340 *client_name,
cristy3ed852e2009-09-05 21:47:34 +00009341 *value;
9342
9343 XrmDatabase
9344 preferences_database;
9345
9346 /*
9347 Save user preferences to the client configuration file.
9348 */
9349 assert(resource_info != (XResourceInfo *) NULL);
cristy104cea82009-10-25 02:26:51 +00009350 client_name=GetClientName();
cristy3ed852e2009-09-05 21:47:34 +00009351 preferences_database=XrmGetStringDatabase("");
cristyb51dff52011-05-19 16:55:47 +00009352 (void) FormatLocaleString(specifier,MaxTextExtent,"%s.backdrop",client_name);
cristy3ed852e2009-09-05 21:47:34 +00009353 value=resource_info->backdrop ? "True" : "False";
9354 XrmPutStringResource(&preferences_database,specifier,(char *) value);
cristyb51dff52011-05-19 16:55:47 +00009355 (void) FormatLocaleString(specifier,MaxTextExtent,"%s.colormap",client_name);
cristy3ed852e2009-09-05 21:47:34 +00009356 value=resource_info->colormap == SharedColormap ? "Shared" : "Private";
9357 XrmPutStringResource(&preferences_database,specifier,(char *) value);
cristyb51dff52011-05-19 16:55:47 +00009358 (void) FormatLocaleString(specifier,MaxTextExtent,"%s.confirmExit",
cristy104cea82009-10-25 02:26:51 +00009359 client_name);
cristy3ed852e2009-09-05 21:47:34 +00009360 value=resource_info->confirm_exit ? "True" : "False";
9361 XrmPutStringResource(&preferences_database,specifier,(char *) value);
cristyb51dff52011-05-19 16:55:47 +00009362 (void) FormatLocaleString(specifier,MaxTextExtent,"%s.confirmEdit",
cristy104cea82009-10-25 02:26:51 +00009363 client_name);
cristy3ed852e2009-09-05 21:47:34 +00009364 value=resource_info->confirm_edit ? "True" : "False";
9365 XrmPutStringResource(&preferences_database,specifier,(char *) value);
cristyb51dff52011-05-19 16:55:47 +00009366 (void) FormatLocaleString(specifier,MaxTextExtent,"%s.displayWarnings",
cristy104cea82009-10-25 02:26:51 +00009367 client_name);
cristy3ed852e2009-09-05 21:47:34 +00009368 value=resource_info->display_warnings ? "True" : "False";
9369 XrmPutStringResource(&preferences_database,specifier,(char *) value);
cristyb51dff52011-05-19 16:55:47 +00009370 (void) FormatLocaleString(specifier,MaxTextExtent,"%s.dither",client_name);
cristy3ed852e2009-09-05 21:47:34 +00009371 value=resource_info->quantize_info->dither ? "True" : "False";
9372 XrmPutStringResource(&preferences_database,specifier,(char *) value);
cristyb51dff52011-05-19 16:55:47 +00009373 (void) FormatLocaleString(specifier,MaxTextExtent,"%s.gammaCorrect",
cristy104cea82009-10-25 02:26:51 +00009374 client_name);
cristy3ed852e2009-09-05 21:47:34 +00009375 value=resource_info->gamma_correct ? "True" : "False";
9376 XrmPutStringResource(&preferences_database,specifier,(char *) value);
cristyb51dff52011-05-19 16:55:47 +00009377 (void) FormatLocaleString(specifier,MaxTextExtent,"%s.undoCache",client_name);
9378 (void) FormatLocaleString(cache,MaxTextExtent,"%.20g",(double)
cristy3ed852e2009-09-05 21:47:34 +00009379 resource_info->undo_cache);
9380 XrmPutStringResource(&preferences_database,specifier,cache);
cristyb51dff52011-05-19 16:55:47 +00009381 (void) FormatLocaleString(specifier,MaxTextExtent,"%s.usePixmap",client_name);
cristy3ed852e2009-09-05 21:47:34 +00009382 value=resource_info->use_pixmap ? "True" : "False";
9383 XrmPutStringResource(&preferences_database,specifier,(char *) value);
cristyb51dff52011-05-19 16:55:47 +00009384 (void) FormatLocaleString(filename,MaxTextExtent,"%s%src",
cristy104cea82009-10-25 02:26:51 +00009385 X11_PREFERENCES_PATH,client_name);
cristy3ed852e2009-09-05 21:47:34 +00009386 ExpandFilename(filename);
9387 XrmPutFileDatabase(preferences_database,filename);
9388#endif
9389}
9390
9391/*
9392%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9393% %
9394% %
9395% %
9396% X V i s u a l C l a s s N a m e %
9397% %
9398% %
9399% %
9400%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9401%
9402% XVisualClassName() returns the visual class name as a character string.
9403%
9404% The format of the XVisualClassName method is:
9405%
9406% char *XVisualClassName(const int visual_class)
9407%
9408% A description of each parameter follows:
9409%
9410% o visual_type: XVisualClassName returns the visual class as a character
9411% string.
9412%
9413% o class: Specifies the visual class.
9414%
cristy3ed852e2009-09-05 21:47:34 +00009415*/
9416static const char *XVisualClassName(const int visual_class)
9417{
9418 switch (visual_class)
9419 {
9420 case StaticGray: return("StaticGray");
9421 case GrayScale: return("GrayScale");
9422 case StaticColor: return("StaticColor");
9423 case PseudoColor: return("PseudoColor");
9424 case TrueColor: return("TrueColor");
9425 case DirectColor: return("DirectColor");
9426 }
9427 return("unknown visual class");
9428}
9429
9430/*
9431%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9432% %
9433% %
9434% %
9435% X W a r n i n g %
9436% %
9437% %
9438% %
9439%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9440%
9441% XWarning() displays a warning reason in a Notice widget.
9442%
9443% The format of the XWarning method is:
9444%
9445% void XWarning(const unsigned int warning,const char *reason,
9446% const char *description)
9447%
9448% A description of each parameter follows:
9449%
9450% o warning: Specifies the numeric warning category.
9451%
9452% o reason: Specifies the reason to display before terminating the
9453% program.
9454%
9455% o description: Specifies any description to the reason.
9456%
9457*/
cristybcbda3f2011-09-03 13:01:22 +00009458MagickPrivate void XWarning(const ExceptionType magick_unused(warning),
cristy3ed852e2009-09-05 21:47:34 +00009459 const char *reason,const char *description)
9460{
9461 char
9462 text[MaxTextExtent];
9463
9464 XWindows
9465 *windows;
9466
9467 if (reason == (char *) NULL)
9468 return;
9469 (void) CopyMagickString(text,reason,MaxTextExtent);
9470 (void) ConcatenateMagickString(text,":",MaxTextExtent);
9471 windows=XSetWindows((XWindows *) ~0);
9472 XNoticeWidget(windows->display,windows,text,(char *) description);
9473}
9474
9475/*
9476%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9477% %
9478% %
9479% %
9480% X W i n d o w B y I D %
9481% %
9482% %
9483% %
9484%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9485%
9486% XWindowByID() locates a child window with a given ID. If not window with
9487% the given name is found, 0 is returned. Only the window specified and its
9488% subwindows are searched.
9489%
9490% The format of the XWindowByID function is:
9491%
9492% child=XWindowByID(display,window,id)
9493%
9494% A description of each parameter follows:
9495%
9496% o child: XWindowByID returns the window with the specified
9497% id. If no windows are found, XWindowByID returns 0.
9498%
9499% o display: Specifies a pointer to the Display structure; returned from
9500% XOpenDisplay.
9501%
9502% o id: Specifies the id of the window to locate.
9503%
9504*/
cristybcbda3f2011-09-03 13:01:22 +00009505MagickPrivate Window XWindowByID(Display *display,const Window root_window,
cristybb503372010-05-27 20:51:26 +00009506 const size_t id)
cristy3ed852e2009-09-05 21:47:34 +00009507{
9508 RectangleInfo
9509 rectangle_info;
9510
9511 register int
9512 i;
9513
9514 Status
9515 status;
9516
9517 unsigned int
9518 number_children;
9519
9520 Window
9521 child,
9522 *children,
9523 window;
9524
9525 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
9526 assert(display != (Display *) NULL);
9527 assert(root_window != (Window) NULL);
9528 if (id == 0)
9529 return(XSelectWindow(display,&rectangle_info));
9530 if (root_window == id)
cristydfe2b662010-08-22 16:17:24 +00009531 return(root_window);
cristy3ed852e2009-09-05 21:47:34 +00009532 status=XQueryTree(display,root_window,&child,&child,&children,
9533 &number_children);
9534 if (status == False)
9535 return((Window) NULL);
9536 window=(Window) NULL;
9537 for (i=0; i < (int) number_children; i++)
9538 {
9539 /*
9540 Search each child and their children.
9541 */
9542 window=XWindowByID(display,children[i],id);
9543 if (window != (Window) NULL)
9544 break;
9545 }
9546 if (children != (Window *) NULL)
9547 (void) XFree((void *) children);
9548 return(window);
9549}
9550
9551/*
9552%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9553% %
9554% %
9555% %
9556% X W i n d o w B y N a m e %
9557% %
9558% %
9559% %
9560%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9561%
9562% XWindowByName() locates a window with a given name on a display. If no
9563% window with the given name is found, 0 is returned. If more than one window
9564% has the given name, the first one is returned. Only root and its children
9565% are searched.
9566%
9567% The format of the XWindowByName function is:
9568%
9569% window=XWindowByName(display,root_window,name)
9570%
9571% A description of each parameter follows:
9572%
9573% o window: XWindowByName returns the window id.
9574%
9575% o display: Specifies a pointer to the Display structure; returned from
9576% XOpenDisplay.
9577%
9578% o root_window: Specifies the id of the root window.
9579%
9580% o name: Specifies the name of the window to locate.
9581%
9582*/
cristybcbda3f2011-09-03 13:01:22 +00009583MagickPrivate Window XWindowByName(Display *display,const Window root_window,
cristy3ed852e2009-09-05 21:47:34 +00009584 const char *name)
9585{
9586 register int
9587 i;
9588
9589 Status
9590 status;
9591
9592 unsigned int
9593 number_children;
9594
9595 Window
9596 *children,
9597 child,
9598 window;
9599
9600 XTextProperty
9601 window_name;
9602
9603 assert(display != (Display *) NULL);
9604 assert(root_window != (Window) NULL);
9605 assert(name != (char *) NULL);
9606 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",name);
9607 if (XGetWMName(display,root_window,&window_name) != 0)
9608 if (LocaleCompare((char *) window_name.value,name) == 0)
9609 return(root_window);
9610 status=XQueryTree(display,root_window,&child,&child,&children,
9611 &number_children);
9612 if (status == False)
9613 return((Window) NULL);
9614 window=(Window) NULL;
9615 for (i=0; i < (int) number_children; i++)
9616 {
9617 /*
9618 Search each child and their children.
9619 */
9620 window=XWindowByName(display,children[i],name);
9621 if (window != (Window) NULL)
9622 break;
9623 }
9624 if (children != (Window *) NULL)
9625 (void) XFree((void *) children);
9626 return(window);
9627}
9628
9629/*
9630%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9631% %
9632% %
9633% %
9634% X W i n d o w B y P r o p e r y %
9635% %
9636% %
9637% %
9638%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9639%
9640% XWindowByProperty() locates a child window with a given property. If not
9641% window with the given name is found, 0 is returned. If more than one window
9642% has the given property, the first one is returned. Only the window
9643% specified and its subwindows are searched.
9644%
9645% The format of the XWindowByProperty function is:
9646%
9647% child=XWindowByProperty(display,window,property)
9648%
9649% A description of each parameter follows:
9650%
9651% o child: XWindowByProperty returns the window id with the specified
9652% property. If no windows are found, XWindowByProperty returns 0.
9653%
9654% o display: Specifies a pointer to the Display structure; returned from
9655% XOpenDisplay.
9656%
9657% o property: Specifies the property of the window to locate.
9658%
9659*/
cristybcbda3f2011-09-03 13:01:22 +00009660MagickPrivate Window XWindowByProperty(Display *display,const Window window,
cristy3ed852e2009-09-05 21:47:34 +00009661 const Atom property)
9662{
9663 Atom
9664 type;
9665
9666 int
9667 format;
9668
9669 Status
9670 status;
9671
9672 unsigned char
9673 *data;
9674
9675 unsigned int
9676 i,
9677 number_children;
9678
cristyf2faecf2010-05-28 19:19:36 +00009679 unsigned long
cristy3ed852e2009-09-05 21:47:34 +00009680 after,
9681 number_items;
9682
9683 Window
9684 child,
9685 *children,
9686 parent,
9687 root;
9688
9689 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
9690 assert(display != (Display *) NULL);
9691 assert(window != (Window) NULL);
9692 assert(property != (Atom) NULL);
9693 status=XQueryTree(display,window,&root,&parent,&children,&number_children);
9694 if (status == False)
9695 return((Window) NULL);
9696 type=(Atom) NULL;
9697 child=(Window) NULL;
9698 for (i=0; (i < number_children) && (child == (Window) NULL); i++)
9699 {
9700 status=XGetWindowProperty(display,children[i],property,0L,0L,MagickFalse,
9701 (Atom) AnyPropertyType,&type,&format,&number_items,&after,&data);
9702 if (data != NULL)
9703 (void) XFree((void *) data);
9704 if ((status == Success) && (type != (Atom) NULL))
9705 child=children[i];
9706 }
9707 for (i=0; (i < number_children) && (child == (Window) NULL); i++)
9708 child=XWindowByProperty(display,children[i],property);
9709 if (children != (Window *) NULL)
9710 (void) XFree((void *) children);
9711 return(child);
9712}
9713#else
9714
9715/*
9716%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9717% %
9718% %
9719% %
9720% X I m p o r t I m a g e %
9721% %
9722% %
9723% %
9724%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9725%
9726% XImportImage() reads an image from an X window.
9727%
9728% The format of the XImportImage method is:
9729%
cristya0dc96a2011-12-19 23:58:54 +00009730% Image *XImportImage(const ImageInfo *image_info,XImportInfo *ximage_info,
9731% ExceptionInfo *exception)
cristy3ed852e2009-09-05 21:47:34 +00009732%
9733% A description of each parameter follows:
9734%
9735% o image_info: the image info..
9736%
9737% o ximage_info: Specifies a pointer to an XImportInfo structure.
9738%
cristya0dc96a2011-12-19 23:58:54 +00009739% o exception: return any errors or warnings in this structure.
9740%
cristy3ed852e2009-09-05 21:47:34 +00009741*/
cristybcbda3f2011-09-03 13:01:22 +00009742MagickPrivate Image *XImportImage(const ImageInfo *image_info,
cristya0dc96a2011-12-19 23:58:54 +00009743 XImportInfo *ximage_info,ExceptionInfo *exception)
cristy3ed852e2009-09-05 21:47:34 +00009744{
9745 assert(image_info != (const ImageInfo *) NULL);
9746 assert(image_info->signature == MagickSignature);
9747 if (image_info->debug != MagickFalse)
9748 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
9749 image_info->filename);
9750 assert(ximage_info != (XImportInfo *) NULL);
cristya0dc96a2011-12-19 23:58:54 +00009751 assert(exception != (ExceptionInfo *) NULL);
9752 assert(exception->signature == MagickSignature);
cristy3ed852e2009-09-05 21:47:34 +00009753 return((Image *) NULL);
9754}
9755#endif
9756
9757/*
9758%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9759% %
9760% %
9761% %
cristy576974e2009-10-25 20:45:31 +00009762+ X C o m p o n e n t G e n e s i s %
9763% %
9764% %
9765% %
9766%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9767%
9768% XComponentGenesis() instantiates the X component.
9769%
9770% The format of the XComponentGenesis method is:
9771%
9772% MagickBooleanType XComponentGenesis(void)
9773%
9774*/
cristy5ff4eaf2011-09-03 01:38:02 +00009775MagickPrivate MagickBooleanType XComponentGenesis(void)
cristy576974e2009-10-25 20:45:31 +00009776{
9777 return(MagickTrue);
9778}
9779
9780/*
9781%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9782% %
9783% %
9784% %
cristy3ed852e2009-09-05 21:47:34 +00009785% X G e t I m p o r t I n f o %
9786% %
9787% %
9788% %
9789%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9790%
9791% XGetImportInfo() initializes the XImportInfo structure.
9792%
9793% The format of the XGetImportInfo method is:
9794%
9795% void XGetImportInfo(XImportInfo *ximage_info)
9796%
9797% A description of each parameter follows:
9798%
9799% o ximage_info: Specifies a pointer to an ImageInfo structure.
9800%
9801*/
9802MagickExport void XGetImportInfo(XImportInfo *ximage_info)
9803{
9804 assert(ximage_info != (XImportInfo *) NULL);
9805 ximage_info->frame=MagickFalse;
9806 ximage_info->borders=MagickFalse;
9807 ximage_info->screen=MagickFalse;
9808 ximage_info->descend=MagickTrue;
9809 ximage_info->silent=MagickFalse;
9810}