blob: 8973c08bbb40fd6b3e52b5be1fb475799a468b8a [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"
cristy0740a982011-10-13 15:01:01 +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
cristy2ed42f62011-10-02 19:49:57 +0000487 Quantum
cristy5f95f4f2011-10-23 01:01:01 +0000488 virtual_pixel[CompositePixelChannel];
cristy2ed42f62011-10-02 19:49:57 +0000489
cristy3ed852e2009-09-05 21:47:34 +0000490 unsigned int
491 depth,
492 height,
493 width;
494
495 Window
496 root_window;
497
498 XGCValues
499 context_values;
500
501 XImage
502 *annotate_ximage;
503
504 /*
505 Initialize annotated image.
506 */
507 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
508 assert(display != (Display *) NULL);
509 assert(pixel != (XPixelInfo *) NULL);
510 assert(annotate_info != (XAnnotateInfo *) NULL);
511 assert(image != (Image *) NULL);
512 /*
513 Initialize annotated pixmap.
514 */
515 root_window=XRootWindow(display,XDefaultScreen(display));
516 depth=(unsigned int) XDefaultDepth(display,XDefaultScreen(display));
517 annotate_pixmap=XCreatePixmap(display,root_window,annotate_info->width,
518 annotate_info->height,depth);
519 if (annotate_pixmap == (Pixmap) NULL)
520 return(MagickFalse);
521 /*
522 Initialize graphics info.
523 */
524 context_values.background=0;
cristybb503372010-05-27 20:51:26 +0000525 context_values.foreground=(size_t) (~0);
cristy3ed852e2009-09-05 21:47:34 +0000526 context_values.font=annotate_info->font_info->fid;
cristyc57f6942010-11-12 01:47:39 +0000527 annotate_context=XCreateGC(display,root_window,(unsigned long)
528 (GCBackground | GCFont | GCForeground),&context_values);
cristy3ed852e2009-09-05 21:47:34 +0000529 if (annotate_context == (GC) NULL)
530 return(MagickFalse);
531 /*
532 Draw text to pixmap.
533 */
534 (void) XDrawImageString(display,annotate_pixmap,annotate_context,0,
535 (int) annotate_info->font_info->ascent,annotate_info->text,
536 (int) strlen(annotate_info->text));
537 (void) XFreeGC(display,annotate_context);
538 /*
539 Initialize annotated X image.
540 */
541 annotate_ximage=XGetImage(display,annotate_pixmap,0,0,annotate_info->width,
542 annotate_info->height,AllPlanes,ZPixmap);
543 if (annotate_ximage == (XImage *) NULL)
544 return(MagickFalse);
545 (void) XFreePixmap(display,annotate_pixmap);
546 /*
547 Initialize annotated image.
548 */
cristy6710d842011-10-20 23:23:00 +0000549 annotate_image=AcquireImage((ImageInfo *) NULL,exception);
cristy3ed852e2009-09-05 21:47:34 +0000550 if (annotate_image == (Image *) NULL)
551 return(MagickFalse);
552 annotate_image->columns=annotate_info->width;
553 annotate_image->rows=annotate_info->height;
554 /*
555 Transfer annotated X image to image.
556 */
557 width=(unsigned int) image->columns;
558 height=(unsigned int) image->rows;
559 x=0;
560 y=0;
561 (void) XParseGeometry(annotate_info->geometry,&x,&y,&width,&height);
cristy2ed42f62011-10-02 19:49:57 +0000562 (void) GetOneVirtualPixel(image,(ssize_t) x,(ssize_t) y,virtual_pixel,
cristy6710d842011-10-20 23:23:00 +0000563 exception);
cristy2ed42f62011-10-02 19:49:57 +0000564 annotate_image->background_color.red=virtual_pixel[RedPixelChannel];
565 annotate_image->background_color.green=virtual_pixel[GreenPixelChannel];
566 annotate_image->background_color.blue=virtual_pixel[BluePixelChannel];
567 annotate_image->background_color.alpha=virtual_pixel[AlphaPixelChannel];
cristy3ed852e2009-09-05 21:47:34 +0000568 if (annotate_info->stencil == ForegroundStencil)
569 annotate_image->matte=MagickTrue;
cristyc57f6942010-11-12 01:47:39 +0000570 annotate_view=AcquireCacheView(annotate_image);
cristy3ed852e2009-09-05 21:47:34 +0000571 for (y=0; y < (int) annotate_image->rows; y++)
572 {
cristyc57f6942010-11-12 01:47:39 +0000573 register int
cristy3ed852e2009-09-05 21:47:34 +0000574 x;
575
cristy4c08aed2011-07-01 19:47:50 +0000576 register Quantum
cristyc47d1f82009-11-26 01:44:43 +0000577 *restrict q;
cristy3ed852e2009-09-05 21:47:34 +0000578
cristyc57f6942010-11-12 01:47:39 +0000579 q=GetCacheViewAuthenticPixels(annotate_view,0,(ssize_t) y,
580 annotate_image->columns,1,exception);
cristyacd2ed22011-08-30 01:44:23 +0000581 if (q == (Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +0000582 break;
cristyc57f6942010-11-12 01:47:39 +0000583 for (x=0; x < (int) annotate_image->columns; x++)
cristy3ed852e2009-09-05 21:47:34 +0000584 {
cristy4c08aed2011-07-01 19:47:50 +0000585 SetPixelAlpha(annotate_image,OpaqueAlpha,q);
cristy3ed852e2009-09-05 21:47:34 +0000586 if (XGetPixel(annotate_ximage,x,y) == 0)
587 {
588 /*
589 Set this pixel to the background color.
590 */
cristy4c08aed2011-07-01 19:47:50 +0000591 SetPixelRed(annotate_image,ScaleShortToQuantum(
592 pixel->box_color.red),q);
593 SetPixelGreen(annotate_image,ScaleShortToQuantum(
594 pixel->box_color.green),q);
595 SetPixelBlue(annotate_image,ScaleShortToQuantum(
596 pixel->box_color.blue),q);
cristy3ed852e2009-09-05 21:47:34 +0000597 if ((annotate_info->stencil == ForegroundStencil) ||
598 (annotate_info->stencil == OpaqueStencil))
cristy4c08aed2011-07-01 19:47:50 +0000599 SetPixelAlpha(annotate_image,TransparentAlpha,q);
cristy3ed852e2009-09-05 21:47:34 +0000600 }
601 else
602 {
603 /*
604 Set this pixel to the pen color.
605 */
cristy4c08aed2011-07-01 19:47:50 +0000606 SetPixelRed(annotate_image,ScaleShortToQuantum(
607 pixel->pen_color.red),q);
608 SetPixelGreen(annotate_image,ScaleShortToQuantum(
609 pixel->pen_color.green),q);
610 SetPixelBlue(annotate_image,ScaleShortToQuantum(
611 pixel->pen_color.blue),q);
cristy3ed852e2009-09-05 21:47:34 +0000612 if (annotate_info->stencil == BackgroundStencil)
cristy4c08aed2011-07-01 19:47:50 +0000613 SetPixelAlpha(annotate_image,TransparentAlpha,q);
cristy3ed852e2009-09-05 21:47:34 +0000614 }
cristyed231572011-07-14 02:18:59 +0000615 q+=GetPixelChannels(annotate_image);
cristy3ed852e2009-09-05 21:47:34 +0000616 }
cristyc57f6942010-11-12 01:47:39 +0000617 if (SyncCacheViewAuthenticPixels(annotate_view,exception) == MagickFalse)
cristy3ed852e2009-09-05 21:47:34 +0000618 break;
619 }
cristyc57f6942010-11-12 01:47:39 +0000620 annotate_view=DestroyCacheView(annotate_view);
cristy3ed852e2009-09-05 21:47:34 +0000621 XDestroyImage(annotate_ximage);
622 /*
623 Determine annotate geometry.
624 */
625 (void) XParseGeometry(annotate_info->geometry,&x,&y,&width,&height);
626 if ((width != (unsigned int) annotate_image->columns) ||
627 (height != (unsigned int) annotate_image->rows))
628 {
629 char
630 image_geometry[MaxTextExtent];
631
632 /*
633 Scale image.
634 */
cristyb51dff52011-05-19 16:55:47 +0000635 (void) FormatLocaleString(image_geometry,MaxTextExtent,"%ux%u",
cristy3ed852e2009-09-05 21:47:34 +0000636 width,height);
cristye941a752011-10-15 01:52:48 +0000637 (void) TransformImage(&annotate_image,(char *) NULL,image_geometry,
638 exception);
cristy3ed852e2009-09-05 21:47:34 +0000639 }
640 if (annotate_info->degrees != 0.0)
641 {
642 Image
643 *rotate_image;
644
645 int
646 rotations;
647
648 MagickRealType
649 normalized_degrees;
650
651 /*
652 Rotate image.
653 */
cristy6710d842011-10-20 23:23:00 +0000654 rotate_image=RotateImage(annotate_image,annotate_info->degrees,exception);
cristy3ed852e2009-09-05 21:47:34 +0000655 if (rotate_image == (Image *) NULL)
656 return(MagickFalse);
657 annotate_image=DestroyImage(annotate_image);
658 annotate_image=rotate_image;
659 /*
660 Annotation is relative to the degree of rotation.
661 */
662 normalized_degrees=annotate_info->degrees;
663 while (normalized_degrees < -45.0)
664 normalized_degrees+=360.0;
665 for (rotations=0; normalized_degrees > 45.0; rotations++)
666 normalized_degrees-=90.0;
667 switch (rotations % 4)
668 {
669 default:
670 case 0:
671 break;
672 case 1:
673 {
674 /*
675 Rotate 90 degrees.
676 */
677 x-=(int) annotate_image->columns/2;
678 y+=(int) annotate_image->columns/2;
679 break;
680 }
681 case 2:
682 {
683 /*
684 Rotate 180 degrees.
685 */
686 x=x-(int) annotate_image->columns;
687 break;
688 }
689 case 3:
690 {
691 /*
692 Rotate 270 degrees.
693 */
694 x=x-(int) annotate_image->columns/2;
695 y=y-(int) (annotate_image->rows-(annotate_image->columns/2));
696 break;
697 }
698 }
699 }
700 /*
701 Composite text onto the image.
702 */
703 (void) XParseGeometry(annotate_info->geometry,&x,&y,&width,&height);
704 matte=image->matte;
705 (void) CompositeImage(image,annotate_image->matte != MagickFalse ?
cristye941a752011-10-15 01:52:48 +0000706 OverCompositeOp : CopyCompositeOp,annotate_image,(ssize_t) x,(ssize_t) y,
707 exception);
cristy3ed852e2009-09-05 21:47:34 +0000708 image->matte=matte;
709 annotate_image=DestroyImage(annotate_image);
710 return(MagickTrue);
711}
712
713/*
714%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
715% %
716% %
717% %
718% X B e s t F o n t %
719% %
720% %
721% %
722%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
723%
724% XBestFont() returns the "best" font. "Best" is defined as a font specified
725% in the X resource database or a font such that the text width displayed
726% with the font does not exceed the specified maximum width.
727%
728% The format of the XBestFont method is:
729%
730% XFontStruct *XBestFont(Display *display,
731% const XResourceInfo *resource_info,const MagickBooleanType text_font)
732%
733% A description of each parameter follows:
734%
735% o font: XBestFont returns a pointer to a XFontStruct structure.
736%
737% o display: Specifies a connection to an X server; returned from
738% XOpenDisplay.
739%
740% o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
741%
742% o text_font: True is font should be mono-spaced (typewriter style).
743%
cristy3ed852e2009-09-05 21:47:34 +0000744*/
745
746static char **FontToList(char *font)
747{
748 char
749 **fontlist;
750
751 register char
752 *p,
753 *q;
754
755 register int
756 i;
757
758 unsigned int
759 fonts;
760
761 if (font == (char *) NULL)
762 return((char **) NULL);
763 /*
764 Convert string to an ASCII list.
765 */
766 fonts=1U;
767 for (p=font; *p != '\0'; p++)
768 if ((*p == ':') || (*p == ';') || (*p == ','))
769 fonts++;
770 fontlist=(char **) AcquireQuantumMemory((size_t) fonts+1UL,sizeof(*fontlist));
771 if (fontlist == (char **) NULL)
772 {
773 ThrowXWindowFatalException(ResourceLimitError,"MemoryAllocationFailed",
774 font);
775 return((char **) NULL);
776 }
777 p=font;
778 for (i=0; i < (int) fonts; i++)
779 {
780 for (q=p; *q != '\0'; q++)
781 if ((*q == ':') || (*q == ';') || (*q == ','))
782 break;
783 fontlist[i]=(char *) AcquireQuantumMemory((size_t) (q-p)+1UL,
784 sizeof(*fontlist[i]));
785 if (fontlist[i] == (char *) NULL)
786 {
787 ThrowXWindowFatalException(ResourceLimitError,"MemoryAllocationFailed",
788 font);
789 return((char **) NULL);
790 }
791 (void) CopyMagickString(fontlist[i],p,(size_t) (q-p+1));
792 p=q+1;
793 }
794 fontlist[i]=(char *) NULL;
795 return(fontlist);
796}
797
cristybcbda3f2011-09-03 13:01:22 +0000798MagickPrivate XFontStruct *XBestFont(Display *display,
cristy3ed852e2009-09-05 21:47:34 +0000799 const XResourceInfo *resource_info,const MagickBooleanType text_font)
800{
801 static const char
802 *Fonts[]=
803 {
804 "-*-helvetica-medium-r-normal--12-*-*-*-*-*-iso8859-1",
805 "-*-arial-medium-r-normal--12-*-*-*-*-*-iso8859-1",
806 "-*-helvetica-medium-r-normal--12-*-*-*-*-*-iso8859-15",
807 "-*-arial-medium-r-normal--12-*-*-*-*-*-iso8859-15",
808 "-*-helvetica-medium-r-normal--12-*-*-*-*-*-*-*",
809 "-*-arial-medium-r-normal--12-*-*-*-*-*-*-*",
810 "variable",
811 "fixed",
812 (char *) NULL
813 },
814 *TextFonts[]=
815 {
816 "-*-courier-medium-r-normal-*-12-*-*-*-*-*-iso8859-1",
817 "-*-courier-medium-r-normal-*-12-*-*-*-*-*-iso8859-15",
818 "-*-fixed-medium-r-normal-*-12-*-*-*-*-*-*-*",
819 "fixed",
820 (char *) NULL
821 };
822
823 char
824 *font_name;
825
826 register const char
827 **p;
828
829 XFontStruct
830 *font_info;
831
832 font_info=(XFontStruct *) NULL;
833 font_name=resource_info->font;
834 if (text_font != MagickFalse)
835 font_name=resource_info->text_font;
836 if ((font_name != (char *) NULL) && (*font_name != '\0'))
837 {
838 char
839 **fontlist;
840
841 register int
842 i;
843
844 /*
845 Load preferred font specified in the X resource database.
846 */
847 fontlist=FontToList(font_name);
848 if (fontlist != (char **) NULL)
849 {
850 for (i=0; fontlist[i] != (char *) NULL; i++)
851 {
852 if (font_info == (XFontStruct *) NULL)
853 font_info=XLoadQueryFont(display,fontlist[i]);
854 fontlist[i]=DestroyString(fontlist[i]);
855 }
856 fontlist=(char **) RelinquishMagickMemory(fontlist);
857 }
858 if (font_info == (XFontStruct *) NULL)
859 ThrowXWindowFatalException(XServerError,"UnableToLoadFont",font_name);
860 }
861 /*
862 Load fonts from list of fonts until one is found.
863 */
864 p=Fonts;
865 if (text_font != MagickFalse)
866 p=TextFonts;
867 if (XDisplayHeight(display,XDefaultScreen(display)) >= 748)
868 p++;
869 while (*p != (char *) NULL)
870 {
871 if (font_info != (XFontStruct *) NULL)
872 break;
873 font_info=XLoadQueryFont(display,(char *) *p);
874 p++;
875 }
876 return(font_info);
877}
878
879/*
880%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
881% %
882% %
883% %
884% X B e s t I c o n S i z e %
885% %
886% %
887% %
888%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
889%
890% XBestIconSize() returns the "best" icon size. "Best" is defined as an icon
891% size that maintains the aspect ratio of the image. If the window manager
892% has preferred icon sizes, one of the preferred sizes is used.
893%
894% The format of the XBestIconSize method is:
895%
896% void XBestIconSize(Display *display,XWindowInfo *window,Image *image)
897%
898% A description of each parameter follows:
899%
900% o display: Specifies a connection to an X server; returned from
901% XOpenDisplay.
902%
903% o image: the image.
904%
905*/
cristybcbda3f2011-09-03 13:01:22 +0000906MagickPrivate void XBestIconSize(Display *display,XWindowInfo *window,
cristy3ed852e2009-09-05 21:47:34 +0000907 Image *image)
908{
909 int
910 i,
911 number_sizes;
912
913 MagickRealType
914 scale_factor;
915
916 unsigned int
917 height,
918 icon_height,
919 icon_width,
920 width;
921
922 Window
923 root_window;
924
925 XIconSize
926 *icon_size,
927 *size_list;
928
929 /*
930 Determine if the window manager has specified preferred icon sizes.
931 */
932 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
933 assert(display != (Display *) NULL);
934 assert(window != (XWindowInfo *) NULL);
935 assert(image != (Image *) NULL);
936 window->width=MaxIconSize;
937 window->height=MaxIconSize;
938 icon_size=(XIconSize *) NULL;
939 number_sizes=0;
940 root_window=XRootWindow(display,window->screen);
941 if (XGetIconSizes(display,root_window,&size_list,&number_sizes) != 0)
942 if ((number_sizes > 0) && (size_list != (XIconSize *) NULL))
943 icon_size=size_list;
944 if (icon_size == (XIconSize *) NULL)
945 {
946 /*
947 Window manager does not restrict icon size.
948 */
949 icon_size=XAllocIconSize();
950 if (icon_size == (XIconSize *) NULL)
951 {
952 ThrowXWindowFatalException(ResourceLimitError,
953 "MemoryAllocationFailed",image->filename);
954 return;
955 }
956 icon_size->min_width=1;
957 icon_size->max_width=MaxIconSize;
958 icon_size->min_height=1;
959 icon_size->max_height=MaxIconSize;
960 icon_size->width_inc=1;
961 icon_size->height_inc=1;
962 }
963 /*
964 Determine aspect ratio of image.
965 */
966 width=(unsigned int) image->columns;
967 height=(unsigned int) image->rows;
968 i=0;
969 if (window->crop_geometry)
970 (void) XParseGeometry(window->crop_geometry,&i,&i,&width,&height);
971 /*
972 Look for an icon size that maintains the aspect ratio of image.
973 */
974 scale_factor=(MagickRealType) icon_size->max_width/width;
975 if (scale_factor > ((MagickRealType) icon_size->max_height/height))
976 scale_factor=(MagickRealType) icon_size->max_height/height;
977 icon_width=(unsigned int) icon_size->min_width;
978 while ((int) icon_width < icon_size->max_width)
979 {
980 if (icon_width >= (unsigned int) (scale_factor*width+0.5))
981 break;
982 icon_width+=icon_size->width_inc;
983 }
984 icon_height=(unsigned int) icon_size->min_height;
985 while ((int) icon_height < icon_size->max_height)
986 {
987 if (icon_height >= (unsigned int) (scale_factor*height+0.5))
988 break;
989 icon_height+=icon_size->height_inc;
990 }
991 (void) XFree((void *) icon_size);
992 window->width=icon_width;
993 window->height=icon_height;
994}
995
996/*
997%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
998% %
999% %
1000% %
1001% X B e s t P i x e l %
1002% %
1003% %
1004% %
1005%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1006%
1007% XBestPixel() returns a pixel from an array of pixels that is closest to the
1008% requested color. If the color array is NULL, the colors are obtained from
1009% the X server.
1010%
1011% The format of the XBestPixel method is:
1012%
1013% void XBestPixel(Display *display,const Colormap colormap,XColor *colors,
1014% unsigned int number_colors,XColor *color)
1015%
1016% A description of each parameter follows:
1017%
1018% o pixel: XBestPixel returns the pixel value closest to the requested
1019% color.
1020%
1021% o display: Specifies a connection to an X server; returned from
1022% XOpenDisplay.
1023%
1024% o colormap: Specifies the ID of the X server colormap.
1025%
1026% o colors: Specifies an array of XColor structures.
1027%
1028% o number_colors: Specifies the number of XColor structures in the
1029% color definition array.
1030%
1031% o color: Specifies the desired RGB value to find in the colors array.
1032%
1033*/
cristybcbda3f2011-09-03 13:01:22 +00001034MagickPrivate void XBestPixel(Display *display,const Colormap colormap,
cristy3ed852e2009-09-05 21:47:34 +00001035 XColor *colors,unsigned int number_colors,XColor *color)
1036{
1037 MagickBooleanType
1038 query_server;
1039
cristy4c08aed2011-07-01 19:47:50 +00001040 PixelInfo
cristy3ed852e2009-09-05 21:47:34 +00001041 pixel;
1042
1043 MagickRealType
1044 min_distance;
1045
1046 register MagickRealType
1047 distance;
1048
1049 register int
1050 i,
1051 j;
1052
1053 Status
1054 status;
1055
1056 /*
1057 Find closest representation for the requested RGB color.
1058 */
1059 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
1060 assert(display != (Display *) NULL);
1061 assert(color != (XColor *) NULL);
1062 status=XAllocColor(display,colormap,color);
1063 if (status != False)
1064 return;
1065 query_server=colors == (XColor *) NULL ? MagickTrue : MagickFalse;
1066 if (query_server != MagickFalse)
1067 {
1068 /*
1069 Read X server colormap.
1070 */
1071 colors=(XColor *) AcquireQuantumMemory(number_colors,sizeof(*colors));
1072 if (colors == (XColor *) NULL)
1073 {
1074 ThrowXWindowFatalException(ResourceLimitError,
1075 "MemoryAllocationFailed","...");
1076 return;
1077 }
1078 for (i=0; i < (int) number_colors; i++)
cristybb503372010-05-27 20:51:26 +00001079 colors[i].pixel=(size_t) i;
cristy3ed852e2009-09-05 21:47:34 +00001080 if (number_colors > 256)
1081 number_colors=256;
1082 (void) XQueryColors(display,colormap,colors,(int) number_colors);
1083 }
1084 min_distance=3.0*((MagickRealType) QuantumRange+1.0)*((MagickRealType)
1085 QuantumRange+1.0);
1086 j=0;
1087 for (i=0; i < (int) number_colors; i++)
1088 {
1089 pixel.red=colors[i].red-(MagickRealType) color->red;
1090 distance=pixel.red*pixel.red;
1091 if (distance > min_distance)
1092 continue;
1093 pixel.green=colors[i].green-(MagickRealType) color->green;
1094 distance+=pixel.green*pixel.green;
1095 if (distance > min_distance)
1096 continue;
1097 pixel.blue=colors[i].blue-(MagickRealType) color->blue;
1098 distance+=pixel.blue*pixel.blue;
1099 if (distance > min_distance)
1100 continue;
1101 min_distance=distance;
1102 color->pixel=colors[i].pixel;
1103 j=i;
1104 }
1105 (void) XAllocColor(display,colormap,&colors[j]);
1106 if (query_server != MagickFalse)
1107 colors=(XColor *) RelinquishMagickMemory(colors);
1108}
1109
1110/*
1111%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1112% %
1113% %
1114% %
1115% X B e s t V i s u a l I n f o %
1116% %
1117% %
1118% %
1119%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1120%
1121% XBestVisualInfo() returns visual information for a visual that is the "best"
1122% the server supports. "Best" is defined as:
1123%
1124% 1. Restrict the visual list to those supported by the default screen.
1125%
1126% 2. If a visual type is specified, restrict the visual list to those of
1127% that type.
1128%
1129% 3. If a map type is specified, choose the visual that matches the id
1130% specified by the Standard Colormap.
1131%
1132% 4 From the list of visuals, choose one that can display the most
1133% simultaneous colors. If more than one visual can display the same
1134% number of simultaneous colors, one is chosen based on a rank.
1135%
1136% The format of the XBestVisualInfo method is:
1137%
1138% XVisualInfo *XBestVisualInfo(Display *display,
1139% XStandardColormap *map_info,XResourceInfo *resource_info)
1140%
1141% A description of each parameter follows:
1142%
1143% o visual_info: XBestVisualInfo returns a pointer to a X11 XVisualInfo
1144% structure.
1145%
1146% o display: Specifies a connection to an X server; returned from
1147% XOpenDisplay.
1148%
1149% o map_info: If map_type is specified, this structure is initialized
1150% with info from the Standard Colormap.
1151%
1152% o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
1153%
1154*/
1155
1156static inline int MagickMax(const int x,const int y)
1157{
1158 if (x > y)
1159 return(x);
1160 return(y);
1161}
1162
cristybb503372010-05-27 20:51:26 +00001163static inline size_t MagickMin(const unsigned int x,
cristy3ed852e2009-09-05 21:47:34 +00001164 const unsigned int y)
1165{
1166 if (x < y)
1167 return(x);
1168 return(y);
1169}
1170
cristybcbda3f2011-09-03 13:01:22 +00001171MagickPrivate XVisualInfo *XBestVisualInfo(Display *display,
cristy3ed852e2009-09-05 21:47:34 +00001172 XStandardColormap *map_info,XResourceInfo *resource_info)
1173{
1174#define MaxStandardColormaps 7
1175#define XVisualColormapSize(visual_info) MagickMin((unsigned int) (\
1176 (visual_info->klass == TrueColor) || (visual_info->klass == DirectColor) ? \
1177 visual_info->red_mask | visual_info->green_mask | visual_info->blue_mask : \
1178 (unsigned int) visual_info->colormap_size),1U << visual_info->depth)
1179
1180 char
1181 *map_type,
1182 *visual_type;
1183
cristyc57f6942010-11-12 01:47:39 +00001184 int
1185 visual_mask;
1186
cristy3ed852e2009-09-05 21:47:34 +00001187 register int
1188 i;
1189
cristy8891f9c2010-06-04 23:32:17 +00001190 size_t
1191 one;
1192
cristy3ed852e2009-09-05 21:47:34 +00001193 static int
1194 number_visuals;
1195
1196 static XVisualInfo
1197 visual_template;
1198
1199 XVisualInfo
1200 *visual_info,
1201 *visual_list;
1202
1203 /*
1204 Restrict visual search by screen number.
1205 */
1206 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
1207 assert(display != (Display *) NULL);
1208 assert(map_info != (XStandardColormap *) NULL);
1209 assert(resource_info != (XResourceInfo *) NULL);
1210 map_type=resource_info->map_type;
1211 visual_type=resource_info->visual_type;
1212 visual_mask=VisualScreenMask;
1213 visual_template.screen=XDefaultScreen(display);
1214 visual_template.depth=XDefaultDepth(display,XDefaultScreen(display));
cristy8891f9c2010-06-04 23:32:17 +00001215 one=1;
cristy3ed852e2009-09-05 21:47:34 +00001216 if ((resource_info->immutable != MagickFalse) && (resource_info->colors != 0))
cristy8891f9c2010-06-04 23:32:17 +00001217 if (resource_info->colors <= (one << (size_t) visual_template.depth))
cristy3ed852e2009-09-05 21:47:34 +00001218 visual_mask|=VisualDepthMask;
1219 if (visual_type != (char *) NULL)
1220 {
1221 /*
1222 Restrict visual search by class or visual id.
1223 */
1224 if (LocaleCompare("staticgray",visual_type) == 0)
1225 {
1226 visual_mask|=VisualClassMask;
1227 visual_template.klass=StaticGray;
1228 }
1229 else
1230 if (LocaleCompare("grayscale",visual_type) == 0)
1231 {
1232 visual_mask|=VisualClassMask;
1233 visual_template.klass=GrayScale;
1234 }
1235 else
1236 if (LocaleCompare("staticcolor",visual_type) == 0)
1237 {
1238 visual_mask|=VisualClassMask;
1239 visual_template.klass=StaticColor;
1240 }
1241 else
1242 if (LocaleCompare("pseudocolor",visual_type) == 0)
1243 {
1244 visual_mask|=VisualClassMask;
1245 visual_template.klass=PseudoColor;
1246 }
1247 else
1248 if (LocaleCompare("truecolor",visual_type) == 0)
1249 {
1250 visual_mask|=VisualClassMask;
1251 visual_template.klass=TrueColor;
1252 }
1253 else
1254 if (LocaleCompare("directcolor",visual_type) == 0)
1255 {
1256 visual_mask|=VisualClassMask;
1257 visual_template.klass=DirectColor;
1258 }
1259 else
1260 if (LocaleCompare("default",visual_type) == 0)
1261 {
1262 visual_mask|=VisualIDMask;
1263 visual_template.visualid=XVisualIDFromVisual(
1264 XDefaultVisual(display,XDefaultScreen(display)));
1265 }
1266 else
1267 if (isdigit((int) ((unsigned char) *visual_type)) != 0)
1268 {
1269 visual_mask|=VisualIDMask;
1270 visual_template.visualid=
1271 strtol(visual_type,(char **) NULL,0);
1272 }
1273 else
1274 ThrowXWindowFatalException(XServerError,
1275 "UnrecognizedVisualSpecifier",visual_type);
1276 }
1277 /*
1278 Get all visuals that meet our criteria so far.
1279 */
1280 number_visuals=0;
1281 visual_list=XGetVisualInfo(display,visual_mask,&visual_template,
1282 &number_visuals);
1283 visual_mask=VisualScreenMask | VisualIDMask;
1284 if ((number_visuals == 0) || (visual_list == (XVisualInfo *) NULL))
1285 {
1286 /*
1287 Failed to get visual; try using the default visual.
1288 */
1289 ThrowXWindowFatalException(XServerWarning,"UnableToGetVisual",
1290 visual_type);
1291 visual_template.visualid=XVisualIDFromVisual(XDefaultVisual(display,
1292 XDefaultScreen(display)));
1293 visual_list=XGetVisualInfo(display,visual_mask,&visual_template,
1294 &number_visuals);
1295 if ((number_visuals == 0) || (visual_list == (XVisualInfo *) NULL))
1296 return((XVisualInfo *) NULL);
1297 ThrowXWindowFatalException(XServerWarning,"UsingDefaultVisual",
1298 XVisualClassName(visual_list->klass));
1299 }
1300 resource_info->color_recovery=MagickFalse;
1301 if ((map_info != (XStandardColormap *) NULL) && (map_type != (char *) NULL))
1302 {
1303 Atom
1304 map_property;
1305
1306 char
1307 map_name[MaxTextExtent];
1308
1309 int
1310 j,
1311 number_maps;
1312
1313 Status
1314 status;
1315
1316 Window
1317 root_window;
1318
1319 XStandardColormap
1320 *map_list;
1321
1322 /*
1323 Choose a visual associated with a standard colormap.
1324 */
1325 root_window=XRootWindow(display,XDefaultScreen(display));
1326 status=False;
1327 if (LocaleCompare(map_type,"list") != 0)
1328 {
1329 /*
1330 User specified Standard Colormap.
1331 */
cristyb51dff52011-05-19 16:55:47 +00001332 (void) FormatLocaleString((char *) map_name,MaxTextExtent,
cristy3ed852e2009-09-05 21:47:34 +00001333 "RGB_%s_MAP",map_type);
1334 LocaleUpper(map_name);
1335 map_property=XInternAtom(display,(char *) map_name,MagickTrue);
1336 if (map_property != (Atom) NULL)
1337 status=XGetRGBColormaps(display,root_window,&map_list,&number_maps,
1338 map_property);
1339 }
1340 else
1341 {
1342 static const char
1343 *colormap[MaxStandardColormaps]=
1344 {
1345 "_HP_RGB_SMOOTH_MAP_LIST",
1346 "RGB_BEST_MAP",
1347 "RGB_DEFAULT_MAP",
1348 "RGB_GRAY_MAP",
1349 "RGB_RED_MAP",
1350 "RGB_GREEN_MAP",
1351 "RGB_BLUE_MAP",
1352 };
1353
1354 /*
1355 Choose a standard colormap from a list.
1356 */
1357 for (i=0; i < MaxStandardColormaps; i++)
1358 {
1359 map_property=XInternAtom(display,(char *) colormap[i],MagickTrue);
1360 if (map_property == (Atom) NULL)
1361 continue;
1362 status=XGetRGBColormaps(display,root_window,&map_list,&number_maps,
1363 map_property);
1364 if (status != False)
1365 break;
1366 }
1367 resource_info->color_recovery=i == 0 ? MagickTrue : MagickFalse;
1368 }
1369 if (status == False)
1370 {
1371 ThrowXWindowFatalException(XServerError,"UnableToGetStandardColormap",
1372 map_type);
1373 return((XVisualInfo *) NULL);
1374 }
1375 /*
1376 Search all Standard Colormaps and visuals for ids that match.
1377 */
1378 *map_info=map_list[0];
1379#if !defined(PRE_R4_ICCCM)
1380 visual_template.visualid=XVisualIDFromVisual(visual_list[0].visual);
1381 for (i=0; i < number_maps; i++)
1382 for (j=0; j < number_visuals; j++)
1383 if (map_list[i].visualid ==
1384 XVisualIDFromVisual(visual_list[j].visual))
1385 {
1386 *map_info=map_list[i];
1387 visual_template.visualid=XVisualIDFromVisual(
1388 visual_list[j].visual);
1389 break;
1390 }
1391 if (map_info->visualid != visual_template.visualid)
1392 {
1393 ThrowXWindowFatalException(XServerError,
1394 "UnableToMatchVisualToStandardColormap",map_type);
1395 return((XVisualInfo *) NULL);
1396 }
1397#endif
1398 if (map_info->colormap == (Colormap) NULL)
1399 {
1400 ThrowXWindowFatalException(XServerError,
1401 "StandardColormapIsNotInitialized",map_type);
1402 return((XVisualInfo *) NULL);
1403 }
1404 (void) XFree((void *) map_list);
1405 }
1406 else
1407 {
1408 static const unsigned int
1409 rank[]=
1410 {
1411 StaticGray,
1412 GrayScale,
1413 StaticColor,
1414 DirectColor,
1415 TrueColor,
1416 PseudoColor
1417 };
1418
1419 XVisualInfo
1420 *p;
1421
1422 /*
1423 Pick one visual that displays the most simultaneous colors.
1424 */
1425 visual_info=visual_list;
1426 p=visual_list;
1427 for (i=1; i < number_visuals; i++)
1428 {
1429 p++;
1430 if (XVisualColormapSize(p) > XVisualColormapSize(visual_info))
1431 visual_info=p;
1432 else
1433 if (XVisualColormapSize(p) == XVisualColormapSize(visual_info))
1434 if (rank[p->klass] > rank[visual_info->klass])
1435 visual_info=p;
1436 }
1437 visual_template.visualid=XVisualIDFromVisual(visual_info->visual);
1438 }
1439 (void) XFree((void *) visual_list);
1440 /*
1441 Retrieve only one visual by its screen & id number.
1442 */
1443 visual_info=XGetVisualInfo(display,visual_mask,&visual_template,
1444 &number_visuals);
1445 if ((number_visuals == 0) || (visual_info == (XVisualInfo *) NULL))
1446 return((XVisualInfo *) NULL);
1447 return(visual_info);
1448}
1449
1450/*
1451%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1452% %
1453% %
1454% %
1455% X C h e c k D e f i n e C u r s o r %
1456% %
1457% %
1458% %
1459%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1460%
1461% XCheckDefineCursor() prevents cursor changes on the root window.
1462%
1463% The format of the XXCheckDefineCursor method is:
1464%
1465% XCheckDefineCursor(display,window,cursor)
1466%
1467% A description of each parameter follows:
1468%
1469% o display: Specifies a connection to an X server; returned from
1470% XOpenDisplay.
1471%
1472% o window: the window.
1473%
1474% o cursor: the cursor.
1475%
1476*/
cristybcbda3f2011-09-03 13:01:22 +00001477MagickPrivate int XCheckDefineCursor(Display *display,Window window,
cristy3ed852e2009-09-05 21:47:34 +00001478 Cursor cursor)
1479{
1480 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
1481 assert(display != (Display *) NULL);
1482 if (window == XRootWindow(display,XDefaultScreen(display)))
1483 return(0);
1484 return(XDefineCursor(display,window,cursor));
1485}
1486
1487/*
1488%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1489% %
1490% %
1491% %
1492% X C h e c k R e f r e s h W i n d o w s %
1493% %
1494% %
1495% %
1496%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1497%
1498% XCheckRefreshWindows() checks the X server for exposure events for a
1499% particular window and updates the areassociated with the exposure event.
1500%
1501% The format of the XCheckRefreshWindows method is:
1502%
1503% void XCheckRefreshWindows(Display *display,XWindows *windows)
1504%
1505% A description of each parameter follows:
1506%
1507% o display: Specifies a connection to an X server; returned from
1508% XOpenDisplay.
1509%
1510% o windows: Specifies a pointer to a XWindows structure.
1511%
1512*/
cristybcbda3f2011-09-03 13:01:22 +00001513MagickPrivate void XCheckRefreshWindows(Display *display,XWindows *windows)
cristy3ed852e2009-09-05 21:47:34 +00001514{
1515 Window
1516 id;
1517
1518 XEvent
1519 event;
1520
1521 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
1522 assert(display != (Display *) NULL);
1523 assert(windows != (XWindows *) NULL);
1524 XDelay(display,SuspendTime);
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 XDelay(display,SuspendTime << 1);
1532 id=windows->command.id;
1533 while (XCheckTypedWindowEvent(display,id,Expose,&event) != MagickFalse)
1534 (void) XCommandWidget(display,windows,(char const **) NULL,&event);
1535 id=windows->image.id;
1536 while (XCheckTypedWindowEvent(display,id,Expose,&event) != MagickFalse)
1537 XRefreshWindow(display,&windows->image,&event);
1538}
1539
1540/*
1541%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1542% %
1543% %
1544% %
1545% X C l i e n t M e s s a g e %
1546% %
1547% %
1548% %
1549%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1550%
1551% XClientMessage() sends a reason to a window with XSendEvent. The reason is
1552% initialized with a particular protocol type and atom.
1553%
1554% The format of the XClientMessage function is:
1555%
1556% XClientMessage(display,window,protocol,reason,timestamp)
1557%
1558% A description of each parameter follows:
1559%
1560% o display: Specifies a pointer to the Display structure; returned from
1561% XOpenDisplay.
1562%
1563% o window: Specifies a pointer to a Window structure.
1564%
1565% o protocol: Specifies an atom value.
1566%
1567% o reason: Specifies an atom value which is the reason to send.
1568%
1569% o timestamp: Specifies a value of type Time.
1570%
1571*/
cristybcbda3f2011-09-03 13:01:22 +00001572MagickPrivate void XClientMessage(Display *display,const Window window,
cristy3ed852e2009-09-05 21:47:34 +00001573 const Atom protocol,const Atom reason,const Time timestamp)
1574{
1575 XClientMessageEvent
1576 client_event;
1577
1578 assert(display != (Display *) NULL);
1579 client_event.type=ClientMessage;
1580 client_event.window=window;
1581 client_event.message_type=protocol;
1582 client_event.format=32;
cristyc57f6942010-11-12 01:47:39 +00001583 client_event.data.l[0]=(long) reason;
1584 client_event.data.l[1]=(long) timestamp;
cristy3ed852e2009-09-05 21:47:34 +00001585 (void) XSendEvent(display,window,MagickFalse,NoEventMask,(XEvent *) &client_event);
1586}
1587
1588/*
1589%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1590% %
1591% %
1592% %
1593+ X C l i e n t W i n d o w %
1594% %
1595% %
1596% %
1597%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1598%
1599% XClientWindow() finds a window, at or below the specified window, which has
1600% a WM_STATE property. If such a window is found, it is returned, otherwise
1601% the argument window is returned.
1602%
1603% The format of the XClientWindow function is:
1604%
1605% client_window=XClientWindow(display,target_window)
1606%
1607% A description of each parameter follows:
1608%
1609% o client_window: XClientWindow returns a window, at or below the specified
1610% window, which has a WM_STATE property otherwise the argument
1611% target_window is returned.
1612%
1613% o display: Specifies a pointer to the Display structure; returned from
1614% XOpenDisplay.
1615%
1616% o target_window: Specifies the window to find a WM_STATE property.
1617%
cristy3ed852e2009-09-05 21:47:34 +00001618*/
1619static Window XClientWindow(Display *display,Window target_window)
1620{
1621 Atom
1622 state,
1623 type;
1624
1625 int
1626 format;
1627
1628 Status
1629 status;
1630
1631 unsigned char
1632 *data;
1633
cristyf2faecf2010-05-28 19:19:36 +00001634 unsigned long
cristy3ed852e2009-09-05 21:47:34 +00001635 after,
1636 number_items;
1637
1638 Window
1639 client_window;
1640
1641 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
1642 assert(display != (Display *) NULL);
1643 state=XInternAtom(display,"WM_STATE",MagickTrue);
1644 if (state == (Atom) NULL)
1645 return(target_window);
1646 type=(Atom) NULL;
1647 status=XGetWindowProperty(display,target_window,state,0L,0L,MagickFalse,
1648 (Atom) AnyPropertyType,&type,&format,&number_items,&after,&data);
1649 if ((status == Success) && (type != (Atom) NULL))
1650 return(target_window);
1651 client_window=XWindowByProperty(display,target_window,state);
1652 if (client_window == (Window) NULL)
1653 return(target_window);
1654 return(client_window);
1655}
1656
1657/*
1658%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1659% %
1660% %
1661% %
cristyf34a1452009-10-24 22:29:27 +00001662+ X C o m p o n e n t T e r m i n u s %
1663% %
1664% %
1665% %
1666%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1667%
1668% XComponentTerminus() destroys the module component.
1669%
1670% The format of the XComponentTerminus method is:
1671%
1672% XComponentTerminus(void)
1673%
1674*/
cristy5ff4eaf2011-09-03 01:38:02 +00001675MagickPrivate void XComponentTerminus(void)
cristyf34a1452009-10-24 22:29:27 +00001676{
1677 DestroyXResources();
1678}
1679
1680/*
1681%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1682% %
1683% %
1684% %
cristy3ed852e2009-09-05 21:47:34 +00001685% X C o n f i g u r e I m a g e C o l o r m a p %
1686% %
1687% %
1688% %
1689%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1690%
1691% XConfigureImageColormap() creates a new X colormap.
1692%
1693% The format of the XConfigureImageColormap method is:
1694%
1695% void XConfigureImageColormap(Display *display,
cristy6710d842011-10-20 23:23:00 +00001696% XResourceInfo *resource_info,XWindows *windows,Image *image,
1697% ExceptionInfo *exception)
cristy3ed852e2009-09-05 21:47:34 +00001698%
1699% A description of each parameter follows:
1700%
1701% o display: Specifies a connection to an X server; returned from
1702% XOpenDisplay.
1703%
1704% o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
1705%
1706% o windows: Specifies a pointer to a XWindows structure.
1707%
1708% o image: the image.
1709%
cristy6710d842011-10-20 23:23:00 +00001710% o exception: return any errors or warnings in this structure.
1711%
cristy3ed852e2009-09-05 21:47:34 +00001712*/
cristybcbda3f2011-09-03 13:01:22 +00001713MagickPrivate void XConfigureImageColormap(Display *display,
cristy6710d842011-10-20 23:23:00 +00001714 XResourceInfo *resource_info,XWindows *windows,Image *image,
1715 ExceptionInfo *exception)
cristy3ed852e2009-09-05 21:47:34 +00001716{
1717 Colormap
1718 colormap;
1719
1720 /*
1721 Make standard colormap.
1722 */
1723 XSetCursorState(display,windows,MagickTrue);
1724 XCheckRefreshWindows(display,windows);
1725 XMakeStandardColormap(display,windows->visual_info,resource_info,image,
cristy6710d842011-10-20 23:23:00 +00001726 windows->map_info,windows->pixel_info,exception);
cristy3ed852e2009-09-05 21:47:34 +00001727 colormap=windows->map_info->colormap;
1728 (void) XSetWindowColormap(display,windows->image.id,colormap);
1729 (void) XSetWindowColormap(display,windows->command.id,colormap);
1730 (void) XSetWindowColormap(display,windows->widget.id,colormap);
1731 if (windows->magnify.mapped != MagickFalse)
1732 (void) XSetWindowColormap(display,windows->magnify.id,colormap);
1733 if (windows->pan.mapped != MagickFalse)
1734 (void) XSetWindowColormap(display,windows->pan.id,colormap);
1735 XSetCursorState(display,windows,MagickFalse);
1736 XClientMessage(display,windows->image.id,windows->im_protocols,
1737 windows->im_update_colormap,CurrentTime);
1738}
1739
1740/*
1741%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1742% %
1743% %
1744% %
1745% X C o n s t r a i n W i n d o w P o s i t i o n %
1746% %
1747% %
1748% %
1749%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1750%
1751% XConstrainWindowPosition() assures a window is positioned within the X
1752% server boundaries.
1753%
1754% The format of the XConstrainWindowPosition method is:
1755%
1756% void XConstrainWindowPosition(Display *display,XWindowInfo *window_info)
1757%
1758% A description of each parameter follows:
1759%
1760% o display: Specifies a pointer to the Display structure; returned from
1761% XOpenDisplay.
1762%
1763% o window_info: Specifies a pointer to a XWindowInfo structure.
1764%
1765*/
cristybcbda3f2011-09-03 13:01:22 +00001766MagickPrivate void XConstrainWindowPosition(Display *display,
cristy3ed852e2009-09-05 21:47:34 +00001767 XWindowInfo *window_info)
1768{
1769 int
1770 limit;
1771
1772 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
1773 assert(display != (Display *) NULL);
1774 assert(window_info != (XWindowInfo *) NULL);
1775 limit=XDisplayWidth(display,window_info->screen)-window_info->width;
1776 if (window_info->x < 0)
1777 window_info->x=0;
1778 else
1779 if (window_info->x > (int) limit)
1780 window_info->x=(int) limit;
1781 limit=XDisplayHeight(display,window_info->screen)-window_info->height;
1782 if (window_info->y < 0)
1783 window_info->y=0;
1784 else
1785 if (window_info->y > limit)
1786 window_info->y=limit;
1787}
1788
1789/*
1790%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1791% %
1792% %
1793% %
1794% X D e l a y %
1795% %
1796% %
1797% %
1798%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1799%
1800% XDelay() suspends program execution for the number of milliseconds
1801% specified.
1802%
1803% The format of the Delay method is:
1804%
cristybb503372010-05-27 20:51:26 +00001805% void XDelay(Display *display,const size_t milliseconds)
cristy3ed852e2009-09-05 21:47:34 +00001806%
1807% A description of each parameter follows:
1808%
1809% o display: Specifies a pointer to the Display structure; returned from
1810% XOpenDisplay.
1811%
1812% o milliseconds: Specifies the number of milliseconds to delay before
1813% returning.
1814%
1815*/
cristybcbda3f2011-09-03 13:01:22 +00001816MagickPrivate void XDelay(Display *display,const size_t milliseconds)
cristy3ed852e2009-09-05 21:47:34 +00001817{
1818 assert(display != (Display *) NULL);
1819 (void) XFlush(display);
cristya21afde2010-07-02 00:45:40 +00001820 MagickDelay(milliseconds);
cristy3ed852e2009-09-05 21:47:34 +00001821}
1822
1823/*
1824%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1825% %
1826% %
1827% %
1828% X D e s t r o y R e s o u r c e I n f o %
1829% %
1830% %
1831% %
1832%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1833%
1834% XDestroyResourceInfo() frees memory associated with the XResourceInfo
1835% structure.
1836%
1837% The format of the XDestroyResourceInfo method is:
1838%
1839% void XDestroyResourceInfo(XResourceInfo *resource_info)
1840%
1841% A description of each parameter follows:
1842%
1843% o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
1844%
1845*/
1846MagickExport void XDestroyResourceInfo(XResourceInfo *resource_info)
1847{
1848 if (resource_info->image_geometry != (char *) NULL)
1849 resource_info->image_geometry=(char *)
1850 RelinquishMagickMemory(resource_info->image_geometry);
1851 if (resource_info->quantize_info != (QuantizeInfo *) NULL)
1852 resource_info->quantize_info=DestroyQuantizeInfo(
1853 resource_info->quantize_info);
1854 if (resource_info->client_name != (char *) NULL)
1855 resource_info->client_name=(char *)
1856 RelinquishMagickMemory(resource_info->client_name);
1857 if (resource_info->name != (char *) NULL)
1858 resource_info->name=DestroyString(resource_info->name);
1859 (void) ResetMagickMemory(resource_info,0,sizeof(*resource_info));
1860}
1861
1862/*
1863%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1864% %
1865% %
1866% %
1867% X D e s t r o y W i n d o w C o l o r s %
1868% %
1869% %
1870% %
1871%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1872%
1873% XDestroyWindowColors() frees X11 color resources previously saved on a
1874% window by XRetainWindowColors or programs like xsetroot.
1875%
1876% The format of the XDestroyWindowColors method is:
1877%
1878% void XDestroyWindowColors(Display *display,Window window)
1879%
1880% A description of each parameter follows:
1881%
1882% o display: Specifies a connection to an X server; returned from
1883% XOpenDisplay.
1884%
1885% o window: Specifies a pointer to a Window structure.
1886%
1887*/
cristybcbda3f2011-09-03 13:01:22 +00001888MagickPrivate void XDestroyWindowColors(Display *display,Window window)
cristy3ed852e2009-09-05 21:47:34 +00001889{
1890 Atom
1891 property,
1892 type;
1893
1894 int
1895 format;
1896
1897 Status
1898 status;
1899
1900 unsigned char
1901 *data;
1902
cristyf2faecf2010-05-28 19:19:36 +00001903 unsigned long
cristy3ed852e2009-09-05 21:47:34 +00001904 after,
1905 length;
1906
1907 /*
1908 If there are previous resources on the root window, destroy them.
1909 */
1910 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
1911 assert(display != (Display *) NULL);
1912 property=XInternAtom(display,"_XSETROOT_ID",MagickFalse);
1913 if (property == (Atom) NULL)
1914 {
1915 ThrowXWindowFatalException(XServerError,"UnableToCreateProperty",
1916 "_XSETROOT_ID");
1917 return;
1918 }
1919 status=XGetWindowProperty(display,window,property,0L,1L,MagickTrue,
1920 (Atom) AnyPropertyType,&type,&format,&length,&after,&data);
1921 if (status != Success)
1922 return;
1923 if ((type == XA_PIXMAP) && (format == 32) && (length == 1) && (after == 0))
1924 {
1925 (void) XKillClient(display,(XID) (*((Pixmap *) data)));
1926 (void) XDeleteProperty(display,window,property);
1927 }
1928 if (type != None)
1929 (void) XFree((void *) data);
1930}
1931
1932/*
1933%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1934% %
1935% %
1936% %
1937% X D i s p l a y I m a g e I n f o %
1938% %
1939% %
1940% %
1941%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1942%
1943% XDisplayImageInfo() displays information about an X image.
1944%
1945% The format of the XDisplayImageInfo method is:
1946%
1947% void XDisplayImageInfo(Display *display,
1948% const XResourceInfo *resource_info,XWindows *windows,Image *undo_image,
cristy6710d842011-10-20 23:23:00 +00001949% Image *image,ExceptionInfo *exception)
cristy3ed852e2009-09-05 21:47:34 +00001950%
1951% A description of each parameter follows:
1952%
1953% o display: Specifies a connection to an X server; returned from
1954% XOpenDisplay.
1955%
1956% o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
1957%
1958% o windows: Specifies a pointer to a XWindows structure.
1959%
1960% o undo_image: the undo image.
1961%
1962% o image: the image.
1963%
cristy6710d842011-10-20 23:23:00 +00001964% o exception: return any errors or warnings in this structure.
1965%
cristy3ed852e2009-09-05 21:47:34 +00001966*/
cristybcbda3f2011-09-03 13:01:22 +00001967MagickPrivate void XDisplayImageInfo(Display *display,
cristy3ed852e2009-09-05 21:47:34 +00001968 const XResourceInfo *resource_info,XWindows *windows,Image *undo_image,
cristy6710d842011-10-20 23:23:00 +00001969 Image *image,ExceptionInfo *exception)
cristy3ed852e2009-09-05 21:47:34 +00001970{
1971 char
1972 filename[MaxTextExtent],
1973 *text,
1974 **textlist;
1975
1976 FILE
1977 *file;
1978
1979 int
1980 unique_file;
1981
cristybb503372010-05-27 20:51:26 +00001982 register ssize_t
cristy3ed852e2009-09-05 21:47:34 +00001983 i;
1984
cristybb503372010-05-27 20:51:26 +00001985 size_t
cristy3ed852e2009-09-05 21:47:34 +00001986 number_pixels;
1987
cristy9d314ff2011-03-09 01:30:28 +00001988 ssize_t
1989 bytes;
1990
1991 unsigned int
1992 levels;
1993
cristy3ed852e2009-09-05 21:47:34 +00001994 /*
1995 Write info about the X server to a file.
1996 */
1997 assert(display != (Display *) NULL);
1998 assert(resource_info != (XResourceInfo *) NULL);
1999 assert(windows != (XWindows *) NULL);
2000 assert(image != (Image *) NULL);
2001 if (image->debug)
2002 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
2003 file=(FILE *) NULL;
2004 unique_file=AcquireUniqueFileResource(filename);
2005 if (unique_file != -1)
2006 file=fdopen(unique_file,"w");
2007 if ((unique_file == -1) || (file == (FILE *) NULL))
2008 {
2009 XNoticeWidget(display,windows,"Unable to display image info",filename);
2010 return;
2011 }
2012 if (resource_info->gamma_correct != MagickFalse)
2013 if (resource_info->display_gamma != (char *) NULL)
cristyb51dff52011-05-19 16:55:47 +00002014 (void) FormatLocaleFile(file,"Display\n gamma: %s\n\n",
cristy3ed852e2009-09-05 21:47:34 +00002015 resource_info->display_gamma);
2016 /*
2017 Write info about the X image to a file.
2018 */
cristyb51dff52011-05-19 16:55:47 +00002019 (void) FormatLocaleFile(file,"X\n visual: %s\n",
cristy3ed852e2009-09-05 21:47:34 +00002020 XVisualClassName((int) windows->image.storage_class));
cristyb51dff52011-05-19 16:55:47 +00002021 (void) FormatLocaleFile(file," depth: %d\n",windows->image.ximage->depth);
cristy3ed852e2009-09-05 21:47:34 +00002022 if (windows->visual_info->colormap_size != 0)
cristyb51dff52011-05-19 16:55:47 +00002023 (void) FormatLocaleFile(file," colormap size: %d\n",
cristy3ed852e2009-09-05 21:47:34 +00002024 windows->visual_info->colormap_size);
2025 if (resource_info->colormap== SharedColormap)
cristyb51dff52011-05-19 16:55:47 +00002026 (void) FormatLocaleFile(file," colormap type: Shared\n");
cristy3ed852e2009-09-05 21:47:34 +00002027 else
cristyb51dff52011-05-19 16:55:47 +00002028 (void) FormatLocaleFile(file," colormap type: Private\n");
cristy1e604812011-05-19 18:07:50 +00002029 (void) FormatLocaleFile(file," geometry: %dx%d\n",
2030 windows->image.ximage->width,windows->image.ximage->height);
cristy3ed852e2009-09-05 21:47:34 +00002031 if (windows->image.crop_geometry != (char *) NULL)
cristy1e604812011-05-19 18:07:50 +00002032 (void) FormatLocaleFile(file," crop geometry: %s\n",
2033 windows->image.crop_geometry);
cristy3ed852e2009-09-05 21:47:34 +00002034 if (windows->image.pixmap == (Pixmap) NULL)
cristyb51dff52011-05-19 16:55:47 +00002035 (void) FormatLocaleFile(file," type: X Image\n");
cristy3ed852e2009-09-05 21:47:34 +00002036 else
cristyb51dff52011-05-19 16:55:47 +00002037 (void) FormatLocaleFile(file," type: Pixmap\n");
cristy3ed852e2009-09-05 21:47:34 +00002038 if (windows->image.shape != MagickFalse)
cristyb51dff52011-05-19 16:55:47 +00002039 (void) FormatLocaleFile(file," non-rectangular shape: True\n");
cristy3ed852e2009-09-05 21:47:34 +00002040 else
cristyb51dff52011-05-19 16:55:47 +00002041 (void) FormatLocaleFile(file," non-rectangular shape: False\n");
cristy3ed852e2009-09-05 21:47:34 +00002042 if (windows->image.shared_memory != MagickFalse)
cristyb51dff52011-05-19 16:55:47 +00002043 (void) FormatLocaleFile(file," shared memory: True\n");
cristy3ed852e2009-09-05 21:47:34 +00002044 else
cristyb51dff52011-05-19 16:55:47 +00002045 (void) FormatLocaleFile(file," shared memory: False\n");
2046 (void) FormatLocaleFile(file,"\n");
cristy3ed852e2009-09-05 21:47:34 +00002047 if (resource_info->font != (char *) NULL)
cristyb51dff52011-05-19 16:55:47 +00002048 (void) FormatLocaleFile(file,"Font: %s\n\n",resource_info->font);
cristy3ed852e2009-09-05 21:47:34 +00002049 if (resource_info->text_font != (char *) NULL)
cristyb51dff52011-05-19 16:55:47 +00002050 (void) FormatLocaleFile(file,"Text font: %s\n\n",resource_info->text_font);
cristy3ed852e2009-09-05 21:47:34 +00002051 /*
2052 Write info about the undo cache to a file.
2053 */
2054 bytes=0;
2055 for (levels=0; undo_image != (Image *) NULL; levels++)
2056 {
2057 number_pixels=undo_image->list->columns*undo_image->list->rows;
cristy101ab702011-10-13 13:06:32 +00002058 bytes+=number_pixels*sizeof(PixelInfo);
cristy3ed852e2009-09-05 21:47:34 +00002059 undo_image=GetPreviousImageInList(undo_image);
2060 }
cristyb51dff52011-05-19 16:55:47 +00002061 (void) FormatLocaleFile(file,"Undo Edit Cache\n levels: %u\n",levels);
cristy1e604812011-05-19 18:07:50 +00002062 (void) FormatLocaleFile(file," bytes: %.20gmb\n",(double)
2063 ((bytes+(1 << 19)) >> 20));
cristyb51dff52011-05-19 16:55:47 +00002064 (void) FormatLocaleFile(file," limit: %.20gmb\n\n",(double)
cristyf2faecf2010-05-28 19:19:36 +00002065 resource_info->undo_cache);
cristy3ed852e2009-09-05 21:47:34 +00002066 /*
2067 Write info about the image to a file.
2068 */
cristy6710d842011-10-20 23:23:00 +00002069 (void) IdentifyImage(image,file,MagickTrue,exception);
cristy3ed852e2009-09-05 21:47:34 +00002070 (void) fclose(file);
cristy6710d842011-10-20 23:23:00 +00002071 text=FileToString(filename,~0,exception);
cristy3ed852e2009-09-05 21:47:34 +00002072 (void) RelinquishUniqueFileResource(filename);
2073 if (text == (char *) NULL)
2074 {
2075 XNoticeWidget(display,windows,"MemoryAllocationFailed",
2076 "UnableToDisplayImageInfo");
2077 return;
2078 }
2079 textlist=StringToList(text);
2080 if (textlist != (char **) NULL)
2081 {
2082 char
2083 title[MaxTextExtent];
2084
2085 /*
2086 Display information about the image in the Text View widget.
2087 */
2088 (void) XWithdrawWindow(display,windows->info.id,windows->info.screen);
cristyb51dff52011-05-19 16:55:47 +00002089 (void) FormatLocaleString(title,MaxTextExtent,"Image Info: %s",
cristy3ed852e2009-09-05 21:47:34 +00002090 image->filename);
2091 XTextViewWidget(display,resource_info,windows,MagickTrue,title,
2092 (char const **) textlist);
2093 for (i=0; textlist[i] != (char *) NULL; i++)
2094 textlist[i]=DestroyString(textlist[i]);
2095 textlist=(char **) RelinquishMagickMemory(textlist);
2096 }
2097 text=DestroyString(text);
2098}
2099
2100/*
2101%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2102% %
2103% %
2104% %
2105+ X D i t h e r I m a g e %
2106% %
2107% %
2108% %
2109%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2110%
2111% XDitherImage() dithers the reference image as required by the HP Color
2112% Recovery algorithm. The color values are quantized to 3 bits of red and
2113% green, and 2 bits of blue (3/3/2) and can be used as indices into a 8-bit X
2114% standard colormap.
2115%
2116% The format of the XDitherImage method is:
2117%
cristy6710d842011-10-20 23:23:00 +00002118% void XDitherImage(Image *image,XImage *ximage,ExceptionInfo *exception)
cristy3ed852e2009-09-05 21:47:34 +00002119%
2120% A description of each parameter follows:
2121%
2122% o image: the image.
2123%
2124% o ximage: Specifies a pointer to a XImage structure; returned from
2125% XCreateImage.
2126%
cristy6710d842011-10-20 23:23:00 +00002127% o exception: return any errors or warnings in this structure.
2128%
cristy3ed852e2009-09-05 21:47:34 +00002129*/
cristy6710d842011-10-20 23:23:00 +00002130static void XDitherImage(Image *image,XImage *ximage,ExceptionInfo *exception)
cristy3ed852e2009-09-05 21:47:34 +00002131{
2132 static const short int
2133 dither_red[2][16]=
2134 {
2135 {-16, 4, -1, 11,-14, 6, -3, 9,-15, 5, -2, 10,-13, 7, -4, 8},
2136 { 15, -5, 0,-12, 13, -7, 2,-10, 14, -6, 1,-11, 12, -8, 3, -9}
2137 },
2138 dither_green[2][16]=
2139 {
2140 { 11,-15, 7, -3, 8,-14, 4, -2, 10,-16, 6, -4, 9,-13, 5, -1},
2141 {-12, 14, -8, 2, -9, 13, -5, 1,-11, 15, -7, 3,-10, 12, -6, 0}
2142 },
2143 dither_blue[2][16]=
2144 {
2145 { -3, 9,-13, 7, -1, 11,-15, 5, -4, 8,-14, 6, -2, 10,-16, 4},
2146 { 2,-10, 12, -8, 0,-12, 14, -6, 3, -9, 13, -7, 1,-11, 15, -5}
2147 };
2148
cristyc57f6942010-11-12 01:47:39 +00002149 CacheView
2150 *image_view;
cristy3ed852e2009-09-05 21:47:34 +00002151
2152 int
cristyc57f6942010-11-12 01:47:39 +00002153 value,
cristy3ed852e2009-09-05 21:47:34 +00002154 y;
2155
cristy101ab702011-10-13 13:06:32 +00002156 PixelInfo
cristyc57f6942010-11-12 01:47:39 +00002157 color;
cristy3ed852e2009-09-05 21:47:34 +00002158
2159 register char
2160 *q;
2161
cristy4c08aed2011-07-01 19:47:50 +00002162 register const Quantum
cristy3ed852e2009-09-05 21:47:34 +00002163 *p;
2164
2165 register int
2166 i,
2167 j,
2168 x;
2169
2170 unsigned int
2171 scanline_pad;
2172
cristybb503372010-05-27 20:51:26 +00002173 register size_t
cristy3ed852e2009-09-05 21:47:34 +00002174 pixel;
2175
2176 unsigned char
2177 *blue_map[2][16],
2178 *green_map[2][16],
2179 *red_map[2][16];
2180
2181 /*
2182 Allocate and initialize dither maps.
2183 */
2184 for (i=0; i < 2; i++)
2185 for (j=0; j < 16; j++)
2186 {
2187 red_map[i][j]=(unsigned char *) AcquireQuantumMemory(256UL,
2188 sizeof(*red_map));
2189 green_map[i][j]=(unsigned char *) AcquireQuantumMemory(256UL,
2190 sizeof(*green_map));
2191 blue_map[i][j]=(unsigned char *) AcquireQuantumMemory(256UL,
2192 sizeof(*blue_map));
2193 if ((red_map[i][j] == (unsigned char *) NULL) ||
2194 (green_map[i][j] == (unsigned char *) NULL) ||
2195 (blue_map[i][j] == (unsigned char *) NULL))
2196 {
2197 ThrowXWindowFatalException(ResourceLimitError,
2198 "MemoryAllocationFailed",image->filename);
2199 return;
2200 }
2201 }
2202 /*
2203 Initialize dither tables.
2204 */
2205 for (i=0; i < 2; i++)
2206 for (j=0; j < 16; j++)
2207 for (x=0; x < 256; x++)
2208 {
2209 value=x-16;
2210 if (x < 48)
2211 value=x/2+8;
2212 value+=dither_red[i][j];
2213 red_map[i][j][x]=(unsigned char)
2214 ((value < 0) ? 0 : (value > 255) ? 255 : value);
2215 value=x-16;
2216 if (x < 48)
2217 value=x/2+8;
2218 value+=dither_green[i][j];
2219 green_map[i][j][x]=(unsigned char)
2220 ((value < 0) ? 0 : (value > 255) ? 255 : value);
2221 value=x-32;
2222 if (x < 112)
2223 value=x/2+24;
cristybb503372010-05-27 20:51:26 +00002224 value+=((size_t) dither_blue[i][j] << 1);
cristy3ed852e2009-09-05 21:47:34 +00002225 blue_map[i][j][x]=(unsigned char)
2226 ((value < 0) ? 0 : (value > 255) ? 255 : value);
2227 }
2228 /*
2229 Dither image.
2230 */
2231 scanline_pad=(unsigned int) (ximage->bytes_per_line-
cristybb503372010-05-27 20:51:26 +00002232 ((size_t) (ximage->width*ximage->bits_per_pixel) >> 3));
cristy3ed852e2009-09-05 21:47:34 +00002233 i=0;
2234 j=0;
2235 q=ximage->data;
cristyc57f6942010-11-12 01:47:39 +00002236 image_view=AcquireCacheView(image);
cristy3ed852e2009-09-05 21:47:34 +00002237 for (y=0; y < (int) image->rows; y++)
2238 {
cristyc57f6942010-11-12 01:47:39 +00002239 p=GetCacheViewVirtualPixels(image_view,0,(ssize_t) y,image->columns,1,
cristy6710d842011-10-20 23:23:00 +00002240 exception);
cristy4c08aed2011-07-01 19:47:50 +00002241 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00002242 break;
2243 for (x=0; x < (int) image->columns; x++)
2244 {
cristyce70c172010-01-07 17:15:30 +00002245 color.red=ClampToQuantum((MagickRealType) (red_map[i][j][(int)
cristy4c08aed2011-07-01 19:47:50 +00002246 ScaleQuantumToChar(GetPixelRed(image,p))] << 8));
cristyce70c172010-01-07 17:15:30 +00002247 color.green=ClampToQuantum((MagickRealType) (green_map[i][j][(int)
cristy4c08aed2011-07-01 19:47:50 +00002248 ScaleQuantumToChar(GetPixelGreen(image,p))] << 8));
cristyce70c172010-01-07 17:15:30 +00002249 color.blue=ClampToQuantum((MagickRealType) (blue_map[i][j][(int)
cristy4c08aed2011-07-01 19:47:50 +00002250 ScaleQuantumToChar(GetPixelBlue(image,p))] << 8));
cristybb503372010-05-27 20:51:26 +00002251 pixel=(size_t) (((size_t) color.red & 0xe0) |
2252 (((size_t) color.green & 0xe0) >> 3) |
2253 (((size_t) color.blue & 0xc0) >> 6));
cristy3ed852e2009-09-05 21:47:34 +00002254 *q++=(char) pixel;
cristyed231572011-07-14 02:18:59 +00002255 p+=GetPixelChannels(image);
cristy3ed852e2009-09-05 21:47:34 +00002256 j++;
2257 if (j == 16)
2258 j=0;
2259 }
2260 q+=scanline_pad;
2261 i++;
2262 if (i == 2)
2263 i=0;
2264 }
cristyc57f6942010-11-12 01:47:39 +00002265 image_view=DestroyCacheView(image_view);
cristy3ed852e2009-09-05 21:47:34 +00002266 /*
2267 Free allocated memory.
2268 */
2269 for (i=0; i < 2; i++)
2270 for (j=0; j < 16; j++)
2271 {
2272 green_map[i][j]=(unsigned char *) RelinquishMagickMemory(green_map[i][j]);
2273 blue_map[i][j]=(unsigned char *) RelinquishMagickMemory(blue_map[i][j]);
2274 red_map[i][j]=(unsigned char *) RelinquishMagickMemory(red_map[i][j]);
2275 }
2276}
2277
2278/*
2279%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2280% %
2281% %
2282% %
2283% X D r a w I m a g e %
2284% %
2285% %
2286% %
2287%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2288%
2289% XDrawImage() draws a line on the image.
2290%
2291% The format of the XDrawImage method is:
2292%
cristy6710d842011-10-20 23:23:00 +00002293% MagickBooleanType XDrawImage(Display *display,const XPixelInfo *pixel,
2294% XDrawInfo *draw_info,Image *image,ExceptionInfo *exception)
cristy3ed852e2009-09-05 21:47:34 +00002295%
2296% A description of each parameter follows:
2297%
2298% o display: Specifies a connection to an X server; returned from
2299% XOpenDisplay.
2300%
2301% o pixel: Specifies a pointer to a XPixelInfo structure.
2302%
2303% o draw_info: Specifies a pointer to a XDrawInfo structure.
2304%
2305% o image: the image.
2306%
cristy6710d842011-10-20 23:23:00 +00002307% o exception: return any errors or warnings in this structure.
2308%
cristy3ed852e2009-09-05 21:47:34 +00002309*/
cristybcbda3f2011-09-03 13:01:22 +00002310MagickPrivate MagickBooleanType XDrawImage(Display *display,
cristy6710d842011-10-20 23:23:00 +00002311 const XPixelInfo *pixel,XDrawInfo *draw_info,Image *image,
2312 ExceptionInfo *exception)
cristy3ed852e2009-09-05 21:47:34 +00002313{
cristyc57f6942010-11-12 01:47:39 +00002314 CacheView
2315 *draw_view;
2316
cristy3ed852e2009-09-05 21:47:34 +00002317 GC
2318 draw_context;
2319
2320 Image
2321 *draw_image;
2322
2323 int
2324 x,
2325 y;
2326
2327 MagickBooleanType
2328 matte;
2329
cristy2ed42f62011-10-02 19:49:57 +00002330 Quantum
cristy5f95f4f2011-10-23 01:01:01 +00002331 virtual_pixel[CompositePixelChannel];
cristy2ed42f62011-10-02 19:49:57 +00002332
cristy3ed852e2009-09-05 21:47:34 +00002333 Pixmap
2334 draw_pixmap;
2335
2336 unsigned int
2337 depth,
2338 height,
2339 width;
2340
2341 Window
2342 root_window;
2343
2344 XGCValues
2345 context_values;
2346
2347 XImage
2348 *draw_ximage;
2349
2350 /*
2351 Initialize drawd image.
2352 */
2353 assert(display != (Display *) NULL);
2354 assert(pixel != (XPixelInfo *) NULL);
2355 assert(draw_info != (XDrawInfo *) NULL);
2356 assert(image != (Image *) NULL);
2357 if (image->debug != MagickFalse)
2358 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
2359 /*
2360 Initialize drawd pixmap.
2361 */
2362 root_window=XRootWindow(display,XDefaultScreen(display));
2363 depth=(unsigned int) XDefaultDepth(display,XDefaultScreen(display));
2364 draw_pixmap=XCreatePixmap(display,root_window,draw_info->width,
2365 draw_info->height,depth);
2366 if (draw_pixmap == (Pixmap) NULL)
2367 return(MagickFalse);
2368 /*
2369 Initialize graphics info.
2370 */
cristybb503372010-05-27 20:51:26 +00002371 context_values.background=(size_t) (~0);
cristy3ed852e2009-09-05 21:47:34 +00002372 context_values.foreground=0;
2373 context_values.line_width=(int) draw_info->line_width;
cristybb503372010-05-27 20:51:26 +00002374 draw_context=XCreateGC(display,root_window,(size_t)
cristy3ed852e2009-09-05 21:47:34 +00002375 (GCBackground | GCForeground | GCLineWidth),&context_values);
2376 if (draw_context == (GC) NULL)
2377 return(MagickFalse);
2378 /*
2379 Clear pixmap.
2380 */
2381 (void) XFillRectangle(display,draw_pixmap,draw_context,0,0,draw_info->width,
2382 draw_info->height);
2383 /*
2384 Draw line to pixmap.
2385 */
2386 (void) XSetBackground(display,draw_context,0);
cristybb503372010-05-27 20:51:26 +00002387 (void) XSetForeground(display,draw_context,(size_t) (~0));
cristydd05beb2010-11-21 21:23:39 +00002388 if (draw_info->stipple != (Pixmap) NULL)
2389 {
2390 (void) XSetFillStyle(display,draw_context,FillOpaqueStippled);
2391 (void) XSetStipple(display,draw_context,draw_info->stipple);
2392 }
cristy3ed852e2009-09-05 21:47:34 +00002393 switch (draw_info->element)
2394 {
2395 case PointElement:
2396 default:
2397 {
2398 (void) XDrawLines(display,draw_pixmap,draw_context,
2399 draw_info->coordinate_info,(int) draw_info->number_coordinates,
2400 CoordModeOrigin);
2401 break;
2402 }
2403 case LineElement:
2404 {
2405 (void) XDrawLine(display,draw_pixmap,draw_context,draw_info->line_info.x1,
2406 draw_info->line_info.y1,draw_info->line_info.x2,
2407 draw_info->line_info.y2);
2408 break;
2409 }
2410 case RectangleElement:
2411 {
2412 (void) XDrawRectangle(display,draw_pixmap,draw_context,
2413 (int) draw_info->rectangle_info.x,(int) draw_info->rectangle_info.y,
2414 (unsigned int) draw_info->rectangle_info.width,
2415 (unsigned int) draw_info->rectangle_info.height);
2416 break;
2417 }
2418 case FillRectangleElement:
2419 {
2420 (void) XFillRectangle(display,draw_pixmap,draw_context,
2421 (int) draw_info->rectangle_info.x,(int) draw_info->rectangle_info.y,
2422 (unsigned int) draw_info->rectangle_info.width,
2423 (unsigned int) draw_info->rectangle_info.height);
2424 break;
2425 }
2426 case CircleElement:
2427 case EllipseElement:
2428 {
2429 (void) XDrawArc(display,draw_pixmap,draw_context,
2430 (int) draw_info->rectangle_info.x,(int) draw_info->rectangle_info.y,
2431 (unsigned int) draw_info->rectangle_info.width,
2432 (unsigned int) draw_info->rectangle_info.height,0,360*64);
2433 break;
2434 }
2435 case FillCircleElement:
2436 case FillEllipseElement:
2437 {
2438 (void) XFillArc(display,draw_pixmap,draw_context,
2439 (int) draw_info->rectangle_info.x,(int) draw_info->rectangle_info.y,
2440 (unsigned int) draw_info->rectangle_info.width,
2441 (unsigned int) draw_info->rectangle_info.height,0,360*64);
2442 break;
2443 }
2444 case PolygonElement:
2445 {
2446 XPoint
2447 *coordinate_info;
2448
2449 coordinate_info=draw_info->coordinate_info;
2450 (void) XDrawLines(display,draw_pixmap,draw_context,coordinate_info,
2451 (int) draw_info->number_coordinates,CoordModeOrigin);
2452 (void) XDrawLine(display,draw_pixmap,draw_context,
2453 coordinate_info[draw_info->number_coordinates-1].x,
2454 coordinate_info[draw_info->number_coordinates-1].y,
2455 coordinate_info[0].x,coordinate_info[0].y);
2456 break;
2457 }
2458 case FillPolygonElement:
2459 {
2460 (void) XFillPolygon(display,draw_pixmap,draw_context,
2461 draw_info->coordinate_info,(int) draw_info->number_coordinates,Complex,
2462 CoordModeOrigin);
2463 break;
2464 }
2465 }
2466 (void) XFreeGC(display,draw_context);
2467 /*
2468 Initialize X image.
2469 */
2470 draw_ximage=XGetImage(display,draw_pixmap,0,0,draw_info->width,
2471 draw_info->height,AllPlanes,ZPixmap);
2472 if (draw_ximage == (XImage *) NULL)
2473 return(MagickFalse);
2474 (void) XFreePixmap(display,draw_pixmap);
2475 /*
2476 Initialize draw image.
2477 */
cristy6710d842011-10-20 23:23:00 +00002478 draw_image=AcquireImage((ImageInfo *) NULL,exception);
cristy3ed852e2009-09-05 21:47:34 +00002479 if (draw_image == (Image *) NULL)
2480 return(MagickFalse);
2481 draw_image->columns=draw_info->width;
2482 draw_image->rows=draw_info->height;
2483 /*
2484 Transfer drawn X image to image.
2485 */
2486 width=(unsigned int) image->columns;
2487 height=(unsigned int) image->rows;
2488 x=0;
2489 y=0;
2490 (void) XParseGeometry(draw_info->geometry,&x,&y,&width,&height);
cristy2ed42f62011-10-02 19:49:57 +00002491 (void) GetOneVirtualPixel(image,(ssize_t) x,(ssize_t) y,virtual_pixel,
cristy6710d842011-10-20 23:23:00 +00002492 exception);
cristy2ed42f62011-10-02 19:49:57 +00002493 draw_image->background_color.red=virtual_pixel[RedPixelChannel];
2494 draw_image->background_color.green=virtual_pixel[GreenPixelChannel];
2495 draw_image->background_color.blue=virtual_pixel[BluePixelChannel];
2496 draw_image->background_color.alpha=virtual_pixel[AlphaPixelChannel];
cristy6710d842011-10-20 23:23:00 +00002497 if (SetImageStorageClass(draw_image,DirectClass,exception) == MagickFalse)
cristy3ed852e2009-09-05 21:47:34 +00002498 return(MagickFalse);
2499 draw_image->matte=MagickTrue;
cristyc57f6942010-11-12 01:47:39 +00002500 draw_view=AcquireCacheView(draw_image);
cristy3ed852e2009-09-05 21:47:34 +00002501 for (y=0; y < (int) draw_image->rows; y++)
2502 {
cristyc57f6942010-11-12 01:47:39 +00002503 register int
cristy3ed852e2009-09-05 21:47:34 +00002504 x;
2505
cristy4c08aed2011-07-01 19:47:50 +00002506 register Quantum
cristyc47d1f82009-11-26 01:44:43 +00002507 *restrict q;
cristy3ed852e2009-09-05 21:47:34 +00002508
cristyc57f6942010-11-12 01:47:39 +00002509 q=QueueCacheViewAuthenticPixels(draw_view,0,(ssize_t) y,draw_image->columns,
2510 1,exception);
cristyacd2ed22011-08-30 01:44:23 +00002511 if (q == (Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00002512 break;
cristyc57f6942010-11-12 01:47:39 +00002513 for (x=0; x < (int) draw_image->columns; x++)
cristy3ed852e2009-09-05 21:47:34 +00002514 {
2515 if (XGetPixel(draw_ximage,x,y) == 0)
2516 {
2517 /*
2518 Set this pixel to the background color.
2519 */
cristy803640d2011-11-17 02:11:32 +00002520 SetPixelInfoPixel(draw_image,&draw_image->background_color,q);
cristy76761582011-09-18 02:14:00 +00002521 SetPixelAlpha(draw_image,(Quantum) (draw_info->stencil ==
cristy4c08aed2011-07-01 19:47:50 +00002522 OpaqueStencil ? TransparentAlpha : OpaqueAlpha),q);
cristy3ed852e2009-09-05 21:47:34 +00002523 }
2524 else
2525 {
2526 /*
2527 Set this pixel to the pen color.
2528 */
cristy4c08aed2011-07-01 19:47:50 +00002529 SetPixelRed(draw_image,ScaleShortToQuantum(
2530 pixel->pen_color.red),q);
2531 SetPixelGreen(draw_image,ScaleShortToQuantum(
2532 pixel->pen_color.green),q);
2533 SetPixelBlue(draw_image,ScaleShortToQuantum(
2534 pixel->pen_color.blue),q);
2535 SetPixelAlpha(draw_image,(Quantum) (draw_info->stencil ==
2536 OpaqueStencil ? OpaqueAlpha : TransparentAlpha),q);
cristy3ed852e2009-09-05 21:47:34 +00002537 }
cristyed231572011-07-14 02:18:59 +00002538 q+=GetPixelChannels(draw_image);
cristy3ed852e2009-09-05 21:47:34 +00002539 }
cristyc57f6942010-11-12 01:47:39 +00002540 if (SyncCacheViewAuthenticPixels(draw_view,exception) == MagickFalse)
cristy3ed852e2009-09-05 21:47:34 +00002541 break;
2542 }
cristyc57f6942010-11-12 01:47:39 +00002543 draw_view=DestroyCacheView(draw_view);
cristy3ed852e2009-09-05 21:47:34 +00002544 XDestroyImage(draw_ximage);
2545 /*
2546 Determine draw geometry.
2547 */
2548 (void) XParseGeometry(draw_info->geometry,&x,&y,&width,&height);
2549 if ((width != (unsigned int) draw_image->columns) ||
2550 (height != (unsigned int) draw_image->rows))
2551 {
2552 char
2553 image_geometry[MaxTextExtent];
2554
2555 /*
2556 Scale image.
2557 */
cristyb51dff52011-05-19 16:55:47 +00002558 (void) FormatLocaleString(image_geometry,MaxTextExtent,"%ux%u",
cristy3ed852e2009-09-05 21:47:34 +00002559 width,height);
cristye941a752011-10-15 01:52:48 +00002560 (void) TransformImage(&draw_image,(char *) NULL,image_geometry,
2561 exception);
cristy3ed852e2009-09-05 21:47:34 +00002562 }
2563 if (draw_info->degrees != 0.0)
2564 {
2565 Image
2566 *rotate_image;
2567
2568 int
2569 rotations;
2570
2571 MagickRealType
2572 normalized_degrees;
2573
2574 /*
2575 Rotate image.
2576 */
cristy6710d842011-10-20 23:23:00 +00002577 rotate_image=RotateImage(draw_image,draw_info->degrees,exception);
cristy3ed852e2009-09-05 21:47:34 +00002578 if (rotate_image == (Image *) NULL)
2579 return(MagickFalse);
2580 draw_image=DestroyImage(draw_image);
2581 draw_image=rotate_image;
2582 /*
2583 Annotation is relative to the degree of rotation.
2584 */
2585 normalized_degrees=draw_info->degrees;
2586 while (normalized_degrees < -45.0)
2587 normalized_degrees+=360.0;
2588 for (rotations=0; normalized_degrees > 45.0; rotations++)
2589 normalized_degrees-=90.0;
2590 switch (rotations % 4)
2591 {
2592 default:
2593 case 0:
2594 break;
2595 case 1:
2596 {
2597 /*
2598 Rotate 90 degrees.
2599 */
2600 x=x-(int) draw_image->columns/2;
2601 y=y+(int) draw_image->columns/2;
2602 break;
2603 }
2604 case 2:
2605 {
2606 /*
2607 Rotate 180 degrees.
2608 */
2609 x=x-(int) draw_image->columns;
2610 break;
2611 }
2612 case 3:
2613 {
2614 /*
2615 Rotate 270 degrees.
2616 */
2617 x=x-(int) draw_image->columns/2;
2618 y=y-(int) (draw_image->rows-(draw_image->columns/2));
2619 break;
2620 }
2621 }
2622 }
2623 /*
2624 Composite text onto the image.
2625 */
cristyc57f6942010-11-12 01:47:39 +00002626 draw_view=AcquireCacheView(draw_image);
cristy3ed852e2009-09-05 21:47:34 +00002627 for (y=0; y < (int) draw_image->rows; y++)
2628 {
cristyc57f6942010-11-12 01:47:39 +00002629 register int
cristy3ed852e2009-09-05 21:47:34 +00002630 x;
2631
cristy4c08aed2011-07-01 19:47:50 +00002632 register Quantum
cristyc47d1f82009-11-26 01:44:43 +00002633 *restrict q;
cristy3ed852e2009-09-05 21:47:34 +00002634
cristyc57f6942010-11-12 01:47:39 +00002635 q=GetCacheViewAuthenticPixels(draw_view,0,(ssize_t) y,draw_image->columns,1,
2636 exception);
cristyacd2ed22011-08-30 01:44:23 +00002637 if (q == (Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00002638 break;
cristyc57f6942010-11-12 01:47:39 +00002639 for (x=0; x < (int) draw_image->columns; x++)
cristy3ed852e2009-09-05 21:47:34 +00002640 {
cristy4c08aed2011-07-01 19:47:50 +00002641 if (GetPixelAlpha(image,q) != TransparentAlpha)
2642 SetPixelAlpha(draw_image,OpaqueAlpha,q);
cristyed231572011-07-14 02:18:59 +00002643 q+=GetPixelChannels(draw_image);
cristy3ed852e2009-09-05 21:47:34 +00002644 }
cristyc57f6942010-11-12 01:47:39 +00002645 if (SyncCacheViewAuthenticPixels(draw_view,exception) == MagickFalse)
cristy3ed852e2009-09-05 21:47:34 +00002646 break;
2647 }
cristyc57f6942010-11-12 01:47:39 +00002648 draw_view=DestroyCacheView(draw_view);
cristy3ed852e2009-09-05 21:47:34 +00002649 (void) XParseGeometry(draw_info->geometry,&x,&y,&width,&height);
2650 if (draw_info->stencil == TransparentStencil)
cristye4a40472011-12-22 02:56:19 +00002651 (void) CompositeImage(image,CopyAlphaCompositeOp,draw_image,(ssize_t) x,
cristye941a752011-10-15 01:52:48 +00002652 (ssize_t) y,exception);
cristy3ed852e2009-09-05 21:47:34 +00002653 else
2654 {
2655 matte=image->matte;
cristyc57f6942010-11-12 01:47:39 +00002656 (void) CompositeImage(image,OverCompositeOp,draw_image,(ssize_t) x,
cristye941a752011-10-15 01:52:48 +00002657 (ssize_t) y,exception);
cristy3ed852e2009-09-05 21:47:34 +00002658 image->matte=matte;
2659 }
2660 draw_image=DestroyImage(draw_image);
2661 return(MagickTrue);
2662}
2663
2664/*
2665%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2666% %
2667% %
2668% %
2669% X E r r o r %
2670% %
2671% %
2672% %
2673%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2674%
2675% XError() ignores BadWindow errors for XQueryTree and XGetWindowAttributes,
2676% and ignores BadDrawable errors for XGetGeometry, and ignores BadValue errors
cristybcbda3f2011-09-03 13:01:22 +00002677% for XQueryColor. It returns MagickFalse in those cases. Otherwise it
2678% returns True.
cristy3ed852e2009-09-05 21:47:34 +00002679%
2680% The format of the XError function is:
2681%
cristybcbda3f2011-09-03 13:01:22 +00002682% int XError(display,error)
cristy3ed852e2009-09-05 21:47:34 +00002683%
2684% A description of each parameter follows:
2685%
2686% o display: Specifies a pointer to the Display structure; returned from
2687% XOpenDisplay.
2688%
2689% o error: Specifies the error event.
2690%
2691*/
2692
2693#if defined(__cplusplus) || defined(c_plusplus)
2694extern "C" {
2695#endif
2696
2697MagickExport int XError(Display *display,XErrorEvent *error)
2698{
2699 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
2700 assert(display != (Display *) NULL);
2701 assert(error != (XErrorEvent *) NULL);
2702 xerror_alert=MagickTrue;
2703 switch (error->request_code)
2704 {
2705 case X_GetGeometry:
2706 {
2707 if ((int) error->error_code == BadDrawable)
2708 return(MagickFalse);
2709 break;
2710 }
2711 case X_GetWindowAttributes:
2712 case X_QueryTree:
2713 {
2714 if ((int) error->error_code == BadWindow)
2715 return(MagickFalse);
2716 break;
2717 }
2718 case X_QueryColors:
2719 {
2720 if ((int) error->error_code == BadValue)
2721 return(MagickFalse);
2722 break;
2723 }
2724 }
2725 return(MagickTrue);
2726}
2727
2728#if defined(__cplusplus) || defined(c_plusplus)
2729}
2730#endif
2731
2732/*
2733%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2734% %
2735% %
2736% %
2737% X F r e e R e s o u r c e s %
2738% %
2739% %
2740% %
2741%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2742%
2743% XFreeResources() frees X11 resources.
2744%
2745% The format of the XFreeResources method is:
2746%
2747% void XFreeResources(Display *display,XVisualInfo *visual_info,
2748% XStandardColormap *map_info,XPixelInfo *pixel,XFontStruct *font_info,
2749% XResourceInfo *resource_info,XWindowInfo *window_info)
2750% resource_info,window_info)
2751%
2752% A description of each parameter follows:
2753%
2754% o display: Specifies a connection to an X server; returned from
2755% XOpenDisplay.
2756%
2757% o visual_info: Specifies a pointer to a X11 XVisualInfo structure;
2758% returned from XGetVisualInfo.
2759%
2760% o map_info: If map_type is specified, this structure is initialized
2761% with info from the Standard Colormap.
2762%
2763% o pixel: Specifies a pointer to a XPixelInfo structure.
2764%
2765% o font_info: Specifies a pointer to a XFontStruct structure.
2766%
2767% o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
2768%
2769% o window_info: Specifies a pointer to a X11 XWindowInfo structure.
2770%
2771*/
cristybcbda3f2011-09-03 13:01:22 +00002772MagickPrivate void XFreeResources(Display *display,XVisualInfo *visual_info,
cristy3ed852e2009-09-05 21:47:34 +00002773 XStandardColormap *map_info,XPixelInfo *pixel,XFontStruct *font_info,
2774 XResourceInfo *resource_info,XWindowInfo *window_info)
2775{
2776 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
2777 assert(display != (Display *) NULL);
2778 assert(resource_info != (XResourceInfo *) NULL);
2779 if (window_info != (XWindowInfo *) NULL)
2780 {
2781 /*
2782 Free X image.
2783 */
2784 if (window_info->ximage != (XImage *) NULL)
2785 XDestroyImage(window_info->ximage);
2786 if (window_info->id != (Window) NULL)
2787 {
2788 /*
2789 Free destroy window and free cursors.
2790 */
2791 if (window_info->id != XRootWindow(display,visual_info->screen))
2792 (void) XDestroyWindow(display,window_info->id);
2793 if (window_info->annotate_context != (GC) NULL)
2794 (void) XFreeGC(display,window_info->annotate_context);
2795 if (window_info->highlight_context != (GC) NULL)
2796 (void) XFreeGC(display,window_info->highlight_context);
2797 if (window_info->widget_context != (GC) NULL)
2798 (void) XFreeGC(display,window_info->widget_context);
2799 if (window_info->cursor != (Cursor) NULL)
2800 (void) XFreeCursor(display,window_info->cursor);
2801 window_info->cursor=(Cursor) NULL;
2802 if (window_info->busy_cursor != (Cursor) NULL)
2803 (void) XFreeCursor(display,window_info->busy_cursor);
2804 window_info->busy_cursor=(Cursor) NULL;
2805 }
2806 }
2807 /*
2808 Free font.
2809 */
2810 if (font_info != (XFontStruct *) NULL)
cristyaafc1922011-03-04 16:59:40 +00002811 {
2812 (void) XFreeFont(display,font_info);
2813 font_info=(XFontStruct *) NULL;
2814 }
cristy3ed852e2009-09-05 21:47:34 +00002815 if (map_info != (XStandardColormap *) NULL)
2816 {
2817 /*
2818 Free X Standard Colormap.
2819 */
2820 if (resource_info->map_type == (char *) NULL)
2821 (void) XFreeStandardColormap(display,visual_info,map_info,pixel);
2822 (void) XFree((void *) map_info);
2823 }
2824 /*
2825 Free X visual info.
2826 */
2827 if (visual_info != (XVisualInfo *) NULL)
2828 (void) XFree((void *) visual_info);
2829 if (resource_info->close_server != MagickFalse)
2830 (void) XCloseDisplay(display);
2831}
2832
2833/*
2834%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2835% %
2836% %
2837% %
2838% X F r e e S t a n d a r d C o l o r m a p %
2839% %
2840% %
2841% %
2842%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2843%
2844% XFreeStandardColormap() frees an X11 colormap.
2845%
2846% The format of the XFreeStandardColormap method is:
2847%
2848% void XFreeStandardColormap(Display *display,
2849% const XVisualInfo *visual_info,XStandardColormap *map_info,
2850% XPixelInfo *pixel)
2851%
2852% A description of each parameter follows:
2853%
2854% o display: Specifies a connection to an X server; returned from
2855% XOpenDisplay.
2856%
2857% o visual_info: Specifies a pointer to a X11 XVisualInfo structure;
2858% returned from XGetVisualInfo.
2859%
2860% o map_info: If map_type is specified, this structure is initialized
2861% with info from the Standard Colormap.
2862%
2863% o pixel: Specifies a pointer to a XPixelInfo structure.
2864%
2865*/
cristybcbda3f2011-09-03 13:01:22 +00002866MagickPrivate void XFreeStandardColormap(Display *display,
cristy3ed852e2009-09-05 21:47:34 +00002867 const XVisualInfo *visual_info,XStandardColormap *map_info,XPixelInfo *pixel)
2868{
2869 /*
2870 Free colormap.
2871 */
2872 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
2873 assert(display != (Display *) NULL);
2874 assert(visual_info != (XVisualInfo *) NULL);
2875 assert(map_info != (XStandardColormap *) NULL);
2876 (void) XFlush(display);
2877 if (map_info->colormap != (Colormap) NULL)
2878 {
2879 if (map_info->colormap != XDefaultColormap(display,visual_info->screen))
2880 (void) XFreeColormap(display,map_info->colormap);
2881 else
2882 if (pixel != (XPixelInfo *) NULL)
2883 if ((visual_info->klass != TrueColor) &&
2884 (visual_info->klass != DirectColor))
2885 (void) XFreeColors(display,map_info->colormap,pixel->pixels,
2886 (int) pixel->colors,0);
2887 }
2888 map_info->colormap=(Colormap) NULL;
2889 if (pixel != (XPixelInfo *) NULL)
2890 {
cristyf2faecf2010-05-28 19:19:36 +00002891 if (pixel->pixels != (unsigned long *) NULL)
2892 pixel->pixels=(unsigned long *) RelinquishMagickMemory(pixel->pixels);
2893 pixel->pixels=(unsigned long *) NULL;
cristy3ed852e2009-09-05 21:47:34 +00002894 }
2895}
2896
2897/*
2898%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2899% %
2900% %
2901% %
2902% X G e t A n n o t a t e I n f o %
2903% %
2904% %
2905% %
2906%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2907%
2908% XGetAnnotateInfo() initializes the AnnotateInfo structure.
2909%
2910% The format of the XGetAnnotateInfo method is:
2911%
2912% void XGetAnnotateInfo(XAnnotateInfo *annotate_info)
2913%
2914% A description of each parameter follows:
2915%
2916% o annotate_info: Specifies a pointer to a XAnnotateInfo structure.
2917%
2918*/
cristybcbda3f2011-09-03 13:01:22 +00002919MagickPrivate void XGetAnnotateInfo(XAnnotateInfo *annotate_info)
cristy3ed852e2009-09-05 21:47:34 +00002920{
2921 /*
2922 Initialize annotate structure.
2923 */
2924 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
2925 assert(annotate_info != (XAnnotateInfo *) NULL);
2926 annotate_info->x=0;
2927 annotate_info->y=0;
2928 annotate_info->width=0;
2929 annotate_info->height=0;
2930 annotate_info->stencil=ForegroundStencil;
2931 annotate_info->degrees=0.0;
2932 annotate_info->font_info=(XFontStruct *) NULL;
2933 annotate_info->text=(char *) NULL;
2934 *annotate_info->geometry='\0';
2935 annotate_info->previous=(XAnnotateInfo *) NULL;
2936 annotate_info->next=(XAnnotateInfo *) NULL;
2937 (void) XSupportsLocale();
2938 (void) XSetLocaleModifiers("");
2939}
2940
2941/*
2942%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2943% %
2944% %
2945% %
2946% X G e t M a p I n f o %
2947% %
2948% %
2949% %
2950%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2951%
2952% XGetMapInfo() initializes the XStandardColormap structure.
2953%
2954% The format of the XStandardColormap method is:
2955%
2956% void XGetMapInfo(const XVisualInfo *visual_info,const Colormap colormap,
2957% XStandardColormap *map_info)
2958%
2959% A description of each parameter follows:
2960%
2961% o colormap: Specifies the ID of the X server colormap.
2962%
2963% o visual_info: Specifies a pointer to a X11 XVisualInfo structure;
2964% returned from XGetVisualInfo.
2965%
2966% o map_info: Specifies a pointer to a X11 XStandardColormap structure.
2967%
2968*/
cristybcbda3f2011-09-03 13:01:22 +00002969MagickPrivate void XGetMapInfo(const XVisualInfo *visual_info,
cristy3ed852e2009-09-05 21:47:34 +00002970 const Colormap colormap,XStandardColormap *map_info)
2971{
2972 /*
2973 Initialize map info.
2974 */
2975 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
2976 assert(visual_info != (XVisualInfo *) NULL);
2977 assert(map_info != (XStandardColormap *) NULL);
2978 map_info->colormap=colormap;
2979 map_info->red_max=visual_info->red_mask;
cristybb503372010-05-27 20:51:26 +00002980 map_info->red_mult=(size_t) (map_info->red_max != 0 ? 1 : 0);
cristy3ed852e2009-09-05 21:47:34 +00002981 if (map_info->red_max != 0)
2982 while ((map_info->red_max & 0x01) == 0)
2983 {
2984 map_info->red_max>>=1;
2985 map_info->red_mult<<=1;
2986 }
2987 map_info->green_max=visual_info->green_mask;
cristybb503372010-05-27 20:51:26 +00002988 map_info->green_mult=(size_t) (map_info->green_max != 0 ? 1 : 0);
cristy3ed852e2009-09-05 21:47:34 +00002989 if (map_info->green_max != 0)
2990 while ((map_info->green_max & 0x01) == 0)
2991 {
2992 map_info->green_max>>=1;
2993 map_info->green_mult<<=1;
2994 }
2995 map_info->blue_max=visual_info->blue_mask;
cristybb503372010-05-27 20:51:26 +00002996 map_info->blue_mult=(size_t) (map_info->blue_max != 0 ? 1 : 0);
cristy3ed852e2009-09-05 21:47:34 +00002997 if (map_info->blue_max != 0)
2998 while ((map_info->blue_max & 0x01) == 0)
2999 {
3000 map_info->blue_max>>=1;
3001 map_info->blue_mult<<=1;
3002 }
3003 map_info->base_pixel=0;
3004}
3005
3006/*
3007%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3008% %
3009% %
3010% %
3011% X G e t P i x e l I n f o %
3012% %
3013% %
3014% %
3015%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3016%
cristy101ab702011-10-13 13:06:32 +00003017% XGetPixelInfo() initializes the PixelInfo structure.
cristy3ed852e2009-09-05 21:47:34 +00003018%
cristy4c08aed2011-07-01 19:47:50 +00003019% The format of the XGetPixelInfo method is:
cristy3ed852e2009-09-05 21:47:34 +00003020%
cristy4c08aed2011-07-01 19:47:50 +00003021% void XGetPixelInfo(Display *display,const XVisualInfo *visual_info,
cristy3ed852e2009-09-05 21:47:34 +00003022% const XStandardColormap *map_info,const XResourceInfo *resource_info,
3023% Image *image,XPixelInfo *pixel)
3024% pixel)
3025%
3026% A description of each parameter follows:
3027%
3028% o display: Specifies a connection to an X server; returned from
3029% XOpenDisplay.
3030%
3031% o visual_info: Specifies a pointer to a X11 XVisualInfo structure;
3032% returned from XGetVisualInfo.
3033%
3034% o map_info: If map_type is specified, this structure is initialized
3035% with info from the Standard Colormap.
3036%
3037% o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
3038%
3039% o image: the image.
3040%
3041% o pixel: Specifies a pointer to a XPixelInfo structure.
3042%
3043*/
cristybcbda3f2011-09-03 13:01:22 +00003044MagickPrivate void XGetPixelInfo(Display *display,
cristy3ed852e2009-09-05 21:47:34 +00003045 const XVisualInfo *visual_info,const XStandardColormap *map_info,
3046 const XResourceInfo *resource_info,Image *image,XPixelInfo *pixel)
3047{
3048 static const char
3049 *PenColors[MaxNumberPens]=
3050 {
3051 "#000000000000", /* black */
3052 "#00000000ffff", /* blue */
3053 "#0000ffffffff", /* cyan */
3054 "#0000ffff0000", /* green */
3055 "#bdbdbdbdbdbd", /* gray */
3056 "#ffff00000000", /* red */
3057 "#ffff0000ffff", /* magenta */
3058 "#ffffffff0000", /* yellow */
3059 "#ffffffffffff", /* white */
3060 "#bdbdbdbdbdbd", /* gray */
3061 "#bdbdbdbdbdbd" /* gray */
3062 };
3063
3064 Colormap
3065 colormap;
3066
cristybb503372010-05-27 20:51:26 +00003067 register ssize_t
cristy3ed852e2009-09-05 21:47:34 +00003068 i;
3069
3070 Status
3071 status;
3072
3073 unsigned int
3074 packets;
3075
3076 /*
3077 Initialize pixel info.
3078 */
3079 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
3080 assert(display != (Display *) NULL);
3081 assert(visual_info != (XVisualInfo *) NULL);
3082 assert(map_info != (XStandardColormap *) NULL);
3083 assert(resource_info != (XResourceInfo *) NULL);
3084 assert(pixel != (XPixelInfo *) NULL);
3085 pixel->colors=0;
3086 if (image != (Image *) NULL)
3087 if (image->storage_class == PseudoClass)
cristyc57f6942010-11-12 01:47:39 +00003088 pixel->colors=(ssize_t) image->colors;
cristy3ed852e2009-09-05 21:47:34 +00003089 packets=(unsigned int)
3090 MagickMax((int) pixel->colors,visual_info->colormap_size)+MaxNumberPens;
cristyf2faecf2010-05-28 19:19:36 +00003091 if (pixel->pixels != (unsigned long *) NULL)
3092 pixel->pixels=(unsigned long *) RelinquishMagickMemory(pixel->pixels);
3093 pixel->pixels=(unsigned long *) AcquireQuantumMemory(packets,
cristy3ed852e2009-09-05 21:47:34 +00003094 sizeof(pixel->pixels));
cristyf2faecf2010-05-28 19:19:36 +00003095 if (pixel->pixels == (unsigned long *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00003096 ThrowXWindowFatalException(ResourceLimitFatalError,"UnableToGetPixelInfo",
3097 image->filename);
3098 /*
3099 Set foreground color.
3100 */
3101 colormap=map_info->colormap;
3102 (void) XParseColor(display,colormap,(char *) ForegroundColor,
3103 &pixel->foreground_color);
3104 status=XParseColor(display,colormap,resource_info->foreground_color,
3105 &pixel->foreground_color);
3106 if (status == False)
3107 ThrowXWindowFatalException(XServerError,"ColorIsNotKnownToServer",
3108 resource_info->foreground_color);
3109 pixel->foreground_color.pixel=
3110 XStandardPixel(map_info,&pixel->foreground_color);
3111 pixel->foreground_color.flags=(char) (DoRed | DoGreen | DoBlue);
3112 /*
3113 Set background color.
3114 */
3115 (void) XParseColor(display,colormap,"#d6d6d6d6d6d6",&pixel->background_color);
3116 status=XParseColor(display,colormap,resource_info->background_color,
3117 &pixel->background_color);
3118 if (status == False)
3119 ThrowXWindowFatalException(XServerError,"ColorIsNotKnownToServer",
3120 resource_info->background_color);
3121 pixel->background_color.pixel=
3122 XStandardPixel(map_info,&pixel->background_color);
3123 pixel->background_color.flags=(char) (DoRed | DoGreen | DoBlue);
3124 /*
3125 Set border color.
3126 */
3127 (void) XParseColor(display,colormap,(char *) BorderColor,
3128 &pixel->border_color);
3129 status=XParseColor(display,colormap,resource_info->border_color,
3130 &pixel->border_color);
3131 if (status == False)
3132 ThrowXWindowFatalException(XServerError,"ColorIsNotKnownToServer",
3133 resource_info->border_color);
3134 pixel->border_color.pixel=XStandardPixel(map_info,&pixel->border_color);
3135 pixel->border_color.flags=(char) (DoRed | DoGreen | DoBlue);
3136 /*
3137 Set matte color.
3138 */
3139 pixel->matte_color=pixel->background_color;
3140 if (resource_info->matte_color != (char *) NULL)
3141 {
3142 /*
3143 Matte color is specified as a X resource or command line argument.
3144 */
3145 status=XParseColor(display,colormap,resource_info->matte_color,
3146 &pixel->matte_color);
3147 if (status == False)
3148 ThrowXWindowFatalException(XServerError,"ColorIsNotKnownToServer",
3149 resource_info->matte_color);
3150 pixel->matte_color.pixel=XStandardPixel(map_info,&pixel->matte_color);
3151 pixel->matte_color.flags=(char) (DoRed | DoGreen | DoBlue);
3152 }
3153 /*
3154 Set highlight color.
3155 */
3156 pixel->highlight_color.red=(unsigned short) ((
3157 pixel->matte_color.red*ScaleQuantumToShort(HighlightModulate))/65535L+
3158 (ScaleQuantumToShort((Quantum) (QuantumRange-HighlightModulate))));
3159 pixel->highlight_color.green=(unsigned short) ((
3160 pixel->matte_color.green*ScaleQuantumToShort(HighlightModulate))/65535L+
3161 (ScaleQuantumToShort((Quantum) (QuantumRange-HighlightModulate))));
3162 pixel->highlight_color.blue=(unsigned short) ((
3163 pixel->matte_color.blue*ScaleQuantumToShort(HighlightModulate))/65535L+
3164 (ScaleQuantumToShort((Quantum) (QuantumRange-HighlightModulate))));
3165 pixel->highlight_color.pixel=
3166 XStandardPixel(map_info,&pixel->highlight_color);
3167 pixel->highlight_color.flags=(char) (DoRed | DoGreen | DoBlue);
3168 /*
3169 Set shadow color.
3170 */
3171 pixel->shadow_color.red=(unsigned short) (((MagickRealType)
3172 pixel->matte_color.red*ScaleQuantumToShort(ShadowModulate))/65535L);
3173 pixel->shadow_color.green=(unsigned short) (((MagickRealType)
3174 pixel->matte_color.green*ScaleQuantumToShort(ShadowModulate))/65535L);
3175 pixel->shadow_color.blue=(unsigned short) (((MagickRealType)
3176 pixel->matte_color.blue*ScaleQuantumToShort(ShadowModulate))/65535L);
3177 pixel->shadow_color.pixel=XStandardPixel(map_info,&pixel->shadow_color);
3178 pixel->shadow_color.flags=(char) (DoRed | DoGreen | DoBlue);
3179 /*
3180 Set depth color.
3181 */
3182 pixel->depth_color.red=(unsigned short) (((MagickRealType)
3183 pixel->matte_color.red*ScaleQuantumToShort(DepthModulate))/65535L);
3184 pixel->depth_color.green=(unsigned short) (((MagickRealType)
3185 pixel->matte_color.green*ScaleQuantumToShort(DepthModulate))/65535L);
3186 pixel->depth_color.blue=(unsigned short) (((MagickRealType)
3187 pixel->matte_color.blue*ScaleQuantumToShort(DepthModulate))/65535L);
3188 pixel->depth_color.pixel=XStandardPixel(map_info,&pixel->depth_color);
3189 pixel->depth_color.flags=(char) (DoRed | DoGreen | DoBlue);
3190 /*
3191 Set trough color.
3192 */
3193 pixel->trough_color.red=(unsigned short) (((MagickRealType)
3194 pixel->matte_color.red*ScaleQuantumToShort(TroughModulate))/65535L);
3195 pixel->trough_color.green=(unsigned short) (((MagickRealType)
3196 pixel->matte_color.green*ScaleQuantumToShort(TroughModulate))/65535L);
3197 pixel->trough_color.blue=(unsigned short) (((MagickRealType)
3198 pixel->matte_color.blue*ScaleQuantumToShort(TroughModulate))/65535L);
3199 pixel->trough_color.pixel=XStandardPixel(map_info,&pixel->trough_color);
3200 pixel->trough_color.flags=(char) (DoRed | DoGreen | DoBlue);
3201 /*
3202 Set pen color.
3203 */
3204 for (i=0; i < MaxNumberPens; i++)
3205 {
3206 (void) XParseColor(display,colormap,(char *) PenColors[i],
3207 &pixel->pen_colors[i]);
3208 status=XParseColor(display,colormap,resource_info->pen_colors[i],
3209 &pixel->pen_colors[i]);
3210 if (status == False)
3211 ThrowXWindowFatalException(XServerError,"ColorIsNotKnownToServer",
3212 resource_info->pen_colors[i]);
3213 pixel->pen_colors[i].pixel=XStandardPixel(map_info,&pixel->pen_colors[i]);
3214 pixel->pen_colors[i].flags=(char) (DoRed | DoGreen | DoBlue);
3215 }
3216 pixel->box_color=pixel->background_color;
3217 pixel->pen_color=pixel->foreground_color;
3218 pixel->box_index=0;
3219 pixel->pen_index=1;
3220 if (image != (Image *) NULL)
3221 {
3222 if ((resource_info->gamma_correct != MagickFalse) &&
3223 (image->gamma != 0.0))
3224 {
3225 GeometryInfo
3226 geometry_info;
3227
3228 MagickStatusType
3229 flags;
3230
3231 /*
3232 Initialize map relative to display and image gamma.
3233 */
3234 flags=ParseGeometry(resource_info->display_gamma,&geometry_info);
3235 red_gamma=geometry_info.rho;
3236 green_gamma=geometry_info.sigma;
3237 if ((flags & SigmaValue) == 0)
3238 green_gamma=red_gamma;
3239 blue_gamma=geometry_info.xi;
3240 if ((flags & XiValue) == 0)
3241 blue_gamma=red_gamma;
3242 red_gamma*=image->gamma;
3243 green_gamma*=image->gamma;
3244 blue_gamma*=image->gamma;
3245 }
3246 if (image->storage_class == PseudoClass)
3247 {
3248 /*
3249 Initialize pixel array for images of type PseudoClass.
3250 */
cristybb503372010-05-27 20:51:26 +00003251 for (i=0; i < (ssize_t) image->colors; i++)
cristy4c08aed2011-07-01 19:47:50 +00003252 pixel->pixels[i]=XGammaPacket(map_info,image->colormap+i);
cristy3ed852e2009-09-05 21:47:34 +00003253 for (i=0; i < MaxNumberPens; i++)
3254 pixel->pixels[image->colors+i]=pixel->pen_colors[i].pixel;
3255 pixel->colors+=MaxNumberPens;
3256 }
3257 }
3258}
3259
3260/*
3261%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3262% %
3263% %
3264% %
3265% X G e t R e s o u r c e C l a s s %
3266% %
3267% %
3268% %
3269%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3270%
3271% XGetResourceClass() queries the X server for the specified resource name or
3272% class. If the resource name or class is not defined in the database, the
3273% supplied default value is returned.
3274%
3275% The format of the XGetResourceClass method is:
3276%
3277% char *XGetResourceClass(XrmDatabase database,const char *client_name,
3278% const char *keyword,char *resource_default)
3279%
3280% A description of each parameter follows:
3281%
3282% o database: Specifies a resource database; returned from
3283% XrmGetStringDatabase.
3284%
3285% o client_name: Specifies the application name used to retrieve resource
3286% info from the X server database.
3287%
3288% o keyword: Specifies the keyword of the value being retrieved.
3289%
3290% o resource_default: Specifies the default value to return if the query
3291% fails to find the specified keyword/class.
3292%
3293*/
3294MagickExport char *XGetResourceClass(XrmDatabase database,
3295 const char *client_name,const char *keyword,char *resource_default)
3296{
3297 char
3298 resource_class[MaxTextExtent],
3299 resource_name[MaxTextExtent];
3300
3301 static char
3302 *resource_type;
3303
3304 Status
3305 status;
3306
3307 XrmValue
3308 resource_value;
3309
3310 if (database == (XrmDatabase) NULL)
3311 return(resource_default);
3312 *resource_name='\0';
3313 *resource_class='\0';
3314 if (keyword != (char *) NULL)
3315 {
3316 int
3317 c,
3318 k;
3319
3320 /*
3321 Initialize resource keyword and class.
3322 */
cristyb51dff52011-05-19 16:55:47 +00003323 (void) FormatLocaleString(resource_name,MaxTextExtent,"%s.%s",
cristy3ed852e2009-09-05 21:47:34 +00003324 client_name,keyword);
3325 c=(int) (*client_name);
3326 if ((c >= XK_a) && (c <= XK_z))
3327 c-=(XK_a-XK_A);
3328 else
3329 if ((c >= XK_agrave) && (c <= XK_odiaeresis))
3330 c-=(XK_agrave-XK_Agrave);
3331 else
3332 if ((c >= XK_oslash) && (c <= XK_thorn))
3333 c-=(XK_oslash-XK_Ooblique);
3334 k=(int) (*keyword);
3335 if ((k >= XK_a) && (k <= XK_z))
3336 k-=(XK_a-XK_A);
3337 else
3338 if ((k >= XK_agrave) && (k <= XK_odiaeresis))
3339 k-=(XK_agrave-XK_Agrave);
3340 else
3341 if ((k >= XK_oslash) && (k <= XK_thorn))
3342 k-=(XK_oslash-XK_Ooblique);
cristyb51dff52011-05-19 16:55:47 +00003343 (void) FormatLocaleString(resource_class,MaxTextExtent,"%c%s.%c%s",c,
cristy3ed852e2009-09-05 21:47:34 +00003344 client_name+1,k,keyword+1);
3345 }
3346 status=XrmGetResource(database,resource_name,resource_class,&resource_type,
3347 &resource_value);
3348 if (status == False)
3349 return(resource_default);
3350 return(resource_value.addr);
3351}
3352
3353/*
3354%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3355% %
3356% %
3357% %
3358% X G e t R e s o u r c e D a t a b a s e %
3359% %
3360% %
3361% %
3362%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3363%
3364% XGetResourceDatabase() creates a new resource database and initializes it.
3365%
3366% The format of the XGetResourceDatabase method is:
3367%
3368% XrmDatabase XGetResourceDatabase(Display *display,
3369% const char *client_name)
3370%
3371% A description of each parameter follows:
3372%
3373% o database: XGetResourceDatabase() returns the database after it is
3374% initialized.
3375%
3376% o display: Specifies a connection to an X server; returned from
3377% XOpenDisplay.
3378%
3379% o client_name: Specifies the application name used to retrieve resource
3380% info from the X server database.
3381%
3382*/
3383MagickExport XrmDatabase XGetResourceDatabase(Display *display,
3384 const char *client_name)
3385{
3386 char
3387 filename[MaxTextExtent];
3388
3389 int
3390 c;
3391
3392 register const char
3393 *p;
3394
3395 XrmDatabase
3396 resource_database,
3397 server_database;
3398
3399 if (display == (Display *) NULL)
3400 return((XrmDatabase) NULL);
3401 assert(client_name != (char *) NULL);
3402 /*
3403 Initialize resource database.
3404 */
3405 XrmInitialize();
3406 (void) XGetDefault(display,(char *) client_name,"dummy");
3407 resource_database=XrmGetDatabase(display);
3408 /*
3409 Combine application database.
3410 */
3411 if (client_name != (char *) NULL)
3412 {
3413 /*
3414 Get basename of client.
3415 */
3416 p=client_name+(strlen(client_name)-1);
3417 while ((p > client_name) && (*p != '/'))
3418 p--;
3419 if (*p == '/')
3420 client_name=p+1;
3421 }
3422 c=(int) (*client_name);
3423 if ((c >= XK_a) && (c <= XK_z))
3424 c-=(XK_a-XK_A);
3425 else
3426 if ((c >= XK_agrave) && (c <= XK_odiaeresis))
3427 c-=(XK_agrave-XK_Agrave);
3428 else
3429 if ((c >= XK_oslash) && (c <= XK_thorn))
3430 c-=(XK_oslash-XK_Ooblique);
3431#if defined(X11_APPLICATION_PATH)
cristyb51dff52011-05-19 16:55:47 +00003432 (void) FormatLocaleString(filename,MaxTextExtent,"%s%c%s",
cristy3ed852e2009-09-05 21:47:34 +00003433 X11_APPLICATION_PATH,c,client_name+1);
3434 (void) XrmCombineFileDatabase(filename,&resource_database,MagickFalse);
3435#endif
3436 if (XResourceManagerString(display) != (char *) NULL)
3437 {
3438 /*
3439 Combine server database.
3440 */
3441 server_database=XrmGetStringDatabase(XResourceManagerString(display));
3442 XrmCombineDatabase(server_database,&resource_database,MagickFalse);
3443 }
3444 /*
3445 Merge user preferences database.
3446 */
3447#if defined(X11_PREFERENCES_PATH)
cristyb51dff52011-05-19 16:55:47 +00003448 (void) FormatLocaleString(filename,MaxTextExtent,"%s%src",
cristy3ed852e2009-09-05 21:47:34 +00003449 X11_PREFERENCES_PATH,client_name);
3450 ExpandFilename(filename);
3451 (void) XrmCombineFileDatabase(filename,&resource_database,MagickFalse);
3452#endif
3453 return(resource_database);
3454}
3455
3456/*
3457%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3458% %
3459% %
3460% %
3461% X G e t R e s o u r c e I n f o %
3462% %
3463% %
3464% %
3465%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3466%
3467% XGetResourceInfo(image_info,) initializes the ResourceInfo structure.
3468%
3469% The format of the XGetResourceInfo method is:
3470%
3471% void XGetResourceInfo(const ImageInfo *image_info,XrmDatabase database,
3472% const char *client_name,XResourceInfo *resource_info)
3473%
3474% A description of each parameter follows:
3475%
3476% o image_info: the image info.
3477%
3478% o database: Specifies a resource database; returned from
3479% XrmGetStringDatabase.
3480%
3481% o client_name: Specifies the application name used to retrieve
3482% resource info from the X server database.
3483%
3484% o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
3485%
3486*/
3487MagickExport void XGetResourceInfo(const ImageInfo *image_info,
3488 XrmDatabase database,const char *client_name,XResourceInfo *resource_info)
3489{
3490 char
cristy00976d82011-02-20 20:31:28 +00003491 *directory,
cristy3ed852e2009-09-05 21:47:34 +00003492 *resource_value;
3493
3494 /*
3495 Initialize resource info fields.
3496 */
3497 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
3498 assert(resource_info != (XResourceInfo *) NULL);
3499 (void) ResetMagickMemory(resource_info,0,sizeof(*resource_info));
3500 resource_info->resource_database=database;
3501 resource_info->image_info=(ImageInfo *) image_info;
3502 (void) SetImageInfoProgressMonitor(resource_info->image_info,
3503 XMagickProgressMonitor,(void *) NULL);
3504 resource_info->quantize_info=CloneQuantizeInfo((QuantizeInfo *) NULL);
3505 resource_info->close_server=MagickTrue;
3506 resource_info->client_name=AcquireString(client_name);
3507 resource_value=XGetResourceClass(database,client_name,"backdrop",
3508 (char *) "False");
3509 resource_info->backdrop=IsMagickTrue(resource_value);
3510 resource_info->background_color=XGetResourceInstance(database,client_name,
3511 "background",(char *) "#d6d6d6d6d6d6");
3512 resource_info->border_color=XGetResourceInstance(database,client_name,
3513 "borderColor",BorderColor);
3514 resource_value=XGetResourceClass(database,client_name,"borderWidth",
3515 (char *) "2");
cristy00976d82011-02-20 20:31:28 +00003516 resource_info->border_width=(unsigned int) StringToUnsignedLong(
3517 resource_value);
cristy3ed852e2009-09-05 21:47:34 +00003518 resource_value=XGetResourceClass(database,client_name,"colormap",
3519 (char *) "shared");
3520 resource_info->colormap=UndefinedColormap;
3521 if (LocaleCompare("private",resource_value) == 0)
3522 resource_info->colormap=PrivateColormap;
3523 if (LocaleCompare("shared",resource_value) == 0)
3524 resource_info->colormap=SharedColormap;
3525 if (resource_info->colormap == UndefinedColormap)
3526 ThrowXWindowFatalException(OptionError,"UnrecognizedColormapType",
3527 resource_value);
3528 resource_value=XGetResourceClass(database,client_name,
3529 "colorRecovery",(char *) "False");
3530 resource_info->color_recovery=IsMagickTrue(resource_value);
3531 resource_value=XGetResourceClass(database,client_name,"confirmExit",
3532 (char *) "False");
3533 resource_info->confirm_exit=IsMagickTrue(resource_value);
3534 resource_value=XGetResourceClass(database,client_name,"confirmEdit",
3535 (char *) "False");
3536 resource_info->confirm_edit=IsMagickTrue(resource_value);
cristyba0c3252010-06-27 13:31:44 +00003537 resource_value=XGetResourceClass(database,client_name,"delay",(char *) "1");
cristye27293e2009-12-18 02:53:20 +00003538 resource_info->delay=(unsigned int) StringToUnsignedLong(resource_value);
cristy3ed852e2009-09-05 21:47:34 +00003539 resource_info->display_gamma=XGetResourceClass(database,client_name,
3540 "displayGamma",(char *) "2.2");
3541 resource_value=XGetResourceClass(database,client_name,"displayWarnings",
3542 (char *) "True");
3543 resource_info->display_warnings=IsMagickTrue(resource_value);
3544 resource_info->font=XGetResourceClass(database,client_name,"font",
3545 (char *) NULL);
3546 resource_info->font=XGetResourceClass(database,client_name,"fontList",
3547 resource_info->font);
3548 resource_info->font_name[0]=XGetResourceClass(database,client_name,"font1",
3549 (char *) "fixed");
3550 resource_info->font_name[1]=XGetResourceClass(database,client_name,"font2",
3551 (char *) "variable");
3552 resource_info->font_name[2]=XGetResourceClass(database,client_name,"font3",
3553 (char *) "5x8");
3554 resource_info->font_name[3]=XGetResourceClass(database,client_name,"font4",
3555 (char *) "6x10");
3556 resource_info->font_name[4]=XGetResourceClass(database,client_name,"font5",
3557 (char *) "7x13bold");
3558 resource_info->font_name[5]=XGetResourceClass(database,client_name,"font6",
3559 (char *) "8x13bold");
3560 resource_info->font_name[6]=XGetResourceClass(database,client_name,"font7",
3561 (char *) "9x15bold");
3562 resource_info->font_name[7]=XGetResourceClass(database,client_name,"font8",
3563 (char *) "10x20");
3564 resource_info->font_name[8]=XGetResourceClass(database,client_name,"font9",
3565 (char *) "12x24");
3566 resource_info->font_name[9]=XGetResourceClass(database,client_name,"font0",
3567 (char *) "fixed");
3568 resource_info->font_name[10]=XGetResourceClass(database,client_name,"font0",
3569 (char *) "fixed");
3570 resource_info->foreground_color=XGetResourceInstance(database,client_name,
3571 "foreground",ForegroundColor);
3572 resource_value=XGetResourceClass(database,client_name,"gammaCorrect",
3573 (char *) "True");
3574 resource_info->gamma_correct=IsMagickTrue(resource_value);
3575 resource_info->image_geometry=ConstantString(XGetResourceClass(database,
3576 client_name,"geometry",(char *) NULL));
3577 resource_value=XGetResourceClass(database,client_name,"gravity",
3578 (char *) "Center");
cristy042ee782011-04-22 18:48:30 +00003579 resource_info->gravity=(GravityType) ParseCommandOption(MagickGravityOptions,
cristy3ed852e2009-09-05 21:47:34 +00003580 MagickFalse,resource_value);
cristy00976d82011-02-20 20:31:28 +00003581 directory=getcwd(resource_info->home_directory,MaxTextExtent);
3582 (void) directory;
cristy3ed852e2009-09-05 21:47:34 +00003583 resource_info->icon_geometry=XGetResourceClass(database,client_name,
3584 "iconGeometry",(char *) NULL);
3585 resource_value=XGetResourceClass(database,client_name,"iconic",
3586 (char *) "False");
3587 resource_info->iconic=IsMagickTrue(resource_value);
3588 resource_value=XGetResourceClass(database,client_name,"immutable",
3589 LocaleCompare(client_name,"PerlMagick") == 0 ? (char *) "True" :
3590 (char *) "False");
3591 resource_info->immutable=IsMagickTrue(resource_value);
3592 resource_value=XGetResourceClass(database,client_name,"magnify",
3593 (char *) "3");
cristye27293e2009-12-18 02:53:20 +00003594 resource_info->magnify=(unsigned int) StringToUnsignedLong(resource_value);
cristy3ed852e2009-09-05 21:47:34 +00003595 resource_info->map_type=XGetResourceClass(database,client_name,"map",
3596 (char *) NULL);
3597 resource_info->matte_color=XGetResourceInstance(database,client_name,
3598 "mattecolor",(char *) NULL);
3599 resource_info->name=ConstantString(XGetResourceClass(database,client_name,
3600 "name",(char *) NULL));
3601 resource_info->pen_colors[0]=XGetResourceClass(database,client_name,"pen1",
3602 (char *) "black");
3603 resource_info->pen_colors[1]=XGetResourceClass(database,client_name,"pen2",
3604 (char *) "blue");
3605 resource_info->pen_colors[2]=XGetResourceClass(database,client_name,"pen3",
3606 (char *) "cyan");
3607 resource_info->pen_colors[3]=XGetResourceClass(database,client_name,"pen4",
3608 (char *) "green");
3609 resource_info->pen_colors[4]=XGetResourceClass(database,client_name,"pen5",
3610 (char *) "gray");
3611 resource_info->pen_colors[5]=XGetResourceClass(database,client_name,"pen6",
3612 (char *) "red");
3613 resource_info->pen_colors[6]=XGetResourceClass(database,client_name,"pen7",
3614 (char *) "magenta");
3615 resource_info->pen_colors[7]=XGetResourceClass(database,client_name,"pen8",
3616 (char *) "yellow");
3617 resource_info->pen_colors[8]=XGetResourceClass(database,client_name,"pen9",
3618 (char *) "white");
3619 resource_info->pen_colors[9]=XGetResourceClass(database,client_name,"pen0",
3620 (char *) "gray");
3621 resource_info->pen_colors[10]=XGetResourceClass(database,client_name,"pen0",
3622 (char *) "gray");
3623 resource_value=XGetResourceClass(database,client_name,"pause",(char *) "0");
cristye27293e2009-12-18 02:53:20 +00003624 resource_info->pause=(unsigned int) StringToUnsignedLong(resource_value);
cristy3ed852e2009-09-05 21:47:34 +00003625 resource_value=XGetResourceClass(database,client_name,"quantum",(char *) "1");
cristyf2f27272009-12-17 14:48:46 +00003626 resource_info->quantum=StringToLong(resource_value);
cristy3ed852e2009-09-05 21:47:34 +00003627 resource_info->text_font=XGetResourceClass(database,client_name,(char *)
3628 "font",(char *) "fixed");
3629 resource_info->text_font=XGetResourceClass(database,client_name,
3630 "textFontList",resource_info->text_font);
3631 resource_info->title=XGetResourceClass(database,client_name,"title",
3632 (char *) NULL);
3633 resource_value=XGetResourceClass(database,client_name,"undoCache",
3634 (char *) "16");
cristye27293e2009-12-18 02:53:20 +00003635 resource_info->undo_cache=(unsigned int) StringToUnsignedLong(resource_value);
cristy3ed852e2009-09-05 21:47:34 +00003636 resource_value=XGetResourceClass(database,client_name,"update",
3637 (char *) "False");
3638 resource_info->update=IsMagickTrue(resource_value);
3639 resource_value=XGetResourceClass(database,client_name,"usePixmap",
3640 (char *) "True");
3641 resource_info->use_pixmap=IsMagickTrue(resource_value);
3642 resource_value=XGetResourceClass(database,client_name,"sharedMemory",
3643 (char *) "True");
3644 resource_info->use_shared_memory=IsMagickTrue(resource_value);
3645 resource_info->visual_type=XGetResourceClass(database,client_name,"visual",
3646 (char *) NULL);
3647 resource_info->window_group=XGetResourceClass(database,client_name,
3648 "windowGroup",(char *) NULL);
3649 resource_info->window_id=XGetResourceClass(database,client_name,"window",
3650 (char *) NULL);
3651 resource_info->write_filename=XGetResourceClass(database,client_name,
3652 "writeFilename",(char *) NULL);
3653}
3654
3655/*
3656%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3657% %
3658% %
3659% %
3660% X G e t R e s o u r c e I n s t a n c e %
3661% %
3662% %
3663% %
3664%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3665%
3666% XGetResourceInstance() queries the X server for the specified resource name.
3667% If the resource name is not defined in the database, the supplied default
3668% value is returned.
3669%
3670% The format of the XGetResourceInstance method is:
3671%
3672% char *XGetResourceInstance(XrmDatabase database,const char *client_name,
3673% const char *keyword,const char *resource_default)
3674%
3675% A description of each parameter follows:
3676%
3677% o database: Specifies a resource database; returned from
3678% XrmGetStringDatabase.
3679%
3680% o client_name: Specifies the application name used to retrieve
3681% resource info from the X server database.
3682%
3683% o keyword: Specifies the keyword of the value being retrieved.
3684%
3685% o resource_default: Specifies the default value to return if the query
3686% fails to find the specified keyword/class.
3687%
3688*/
3689MagickExport char *XGetResourceInstance(XrmDatabase database,
3690 const char *client_name,const char *keyword,const char *resource_default)
3691{
3692 char
3693 *resource_type,
3694 resource_name[MaxTextExtent];
3695
3696 Status
3697 status;
3698
3699 XrmValue
3700 resource_value;
3701
3702 if (database == (XrmDatabase) NULL)
3703 return((char *) resource_default);
3704 *resource_name='\0';
3705 if (keyword != (char *) NULL)
cristyb51dff52011-05-19 16:55:47 +00003706 (void) FormatLocaleString(resource_name,MaxTextExtent,"%s.%s",client_name,
cristy3ed852e2009-09-05 21:47:34 +00003707 keyword);
3708 status=XrmGetResource(database,resource_name,"ImageMagick",&resource_type,
3709 &resource_value);
3710 if (status == False)
3711 return((char *) resource_default);
3712 return(resource_value.addr);
3713}
3714
3715/*
3716%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3717% %
3718% %
3719% %
3720% X G e t S c r e e n D e n s i t y %
3721% %
3722% %
3723% %
3724%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3725%
3726% XGetScreenDensity() returns the density of the X server screen in
3727% dots-per-inch.
3728%
3729% The format of the XGetScreenDensity method is:
3730%
3731% char *XGetScreenDensity(Display *display)
3732%
3733% A description of each parameter follows:
3734%
3735% o density: XGetScreenDensity() returns the density of the X screen in
3736% dots-per-inch.
3737%
3738% o display: Specifies a connection to an X server; returned from
3739% XOpenDisplay.
3740%
3741*/
3742MagickExport char *XGetScreenDensity(Display *display)
3743{
3744 char
3745 density[MaxTextExtent];
3746
3747 double
3748 x_density,
3749 y_density;
3750
3751 /*
3752 Set density as determined by screen size.
3753 */
3754 x_density=((((double) DisplayWidth(display,XDefaultScreen(display)))*25.4)/
3755 ((double) DisplayWidthMM(display,XDefaultScreen(display))));
3756 y_density=((((double) DisplayHeight(display,XDefaultScreen(display)))*25.4)/
3757 ((double) DisplayHeightMM(display,XDefaultScreen(display))));
cristyb51dff52011-05-19 16:55:47 +00003758 (void) FormatLocaleString(density,MaxTextExtent,"%gx%g",x_density,
cristy8cd5b312010-01-07 01:10:24 +00003759 y_density);
cristy3ed852e2009-09-05 21:47:34 +00003760 return(GetPageGeometry(density));
3761}
3762
3763/*
3764%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3765% %
3766% %
3767% %
3768+ X G e t S u b w i n d o w %
3769% %
3770% %
3771% %
3772%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3773%
3774% XGetSubwindow() returns the subwindow of a window chosen the user with the
3775% pointer and a button press.
3776%
3777% The format of the XGetSubwindow method is:
3778%
3779% Window XGetSubwindow(Display *display,Window window,int x,int y)
3780%
3781% A description of each parameter follows:
3782%
3783% o subwindow: XGetSubwindow() returns NULL if no subwindow is found
3784% otherwise the subwindow is returned.
3785%
3786% o display: Specifies a connection to an X server; returned from
3787% XOpenDisplay.
3788%
3789% o window: Specifies a pointer to a Window.
3790%
3791% o x: the x coordinate of the pointer relative to the origin of the
3792% window.
3793%
3794% o y: the y coordinate of the pointer relative to the origin of the
3795% window.
3796%
cristy3ed852e2009-09-05 21:47:34 +00003797*/
3798static Window XGetSubwindow(Display *display,Window window,int x,int y)
3799{
3800 int
3801 x_offset,
3802 y_offset;
3803
3804 Status
3805 status;
3806
3807 Window
3808 source_window,
3809 target_window;
3810
3811 assert(display != (Display *) NULL);
3812 source_window=XRootWindow(display,XDefaultScreen(display));
3813 if (window == (Window) NULL)
3814 return(source_window);
3815 target_window=window;
3816 for ( ; ; )
3817 {
3818 status=XTranslateCoordinates(display,source_window,window,x,y,
3819 &x_offset,&y_offset,&target_window);
3820 if (status != True)
3821 break;
3822 if (target_window == (Window) NULL)
3823 break;
3824 source_window=window;
3825 window=target_window;
3826 x=x_offset;
3827 y=y_offset;
3828 }
3829 if (target_window == (Window) NULL)
3830 target_window=window;
3831 return(target_window);
3832}
3833
3834/*
3835%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3836% %
3837% %
3838% %
3839% X G e t W i n d o w C o l o r %
3840% %
3841% %
3842% %
3843%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3844%
3845% XGetWindowColor() returns the color of a pixel interactively chosen from the
3846% X server.
3847%
3848% The format of the XGetWindowColor method is:
3849%
3850% MagickBooleanType XGetWindowColor(Display *display,XWindows *windows,
cristy6710d842011-10-20 23:23:00 +00003851% char *name,ExceptionInfo *exception)
cristy3ed852e2009-09-05 21:47:34 +00003852%
3853% A description of each parameter follows:
3854%
3855% o display: Specifies a connection to an X server; returned from
3856% XOpenDisplay.
3857%
3858% o windows: Specifies a pointer to a XWindows structure.
3859%
3860% o name: the name of the color if found in the X Color Database is
3861% returned in this character string.
3862%
cristy6710d842011-10-20 23:23:00 +00003863% o exception: return any errors or warnings in this structure.
3864%
cristy3ed852e2009-09-05 21:47:34 +00003865*/
cristybcbda3f2011-09-03 13:01:22 +00003866MagickPrivate MagickBooleanType XGetWindowColor(Display *display,
cristy6710d842011-10-20 23:23:00 +00003867 XWindows *windows,char *name,ExceptionInfo *exception)
cristy3ed852e2009-09-05 21:47:34 +00003868{
3869 int
3870 x,
3871 y;
3872
cristy101ab702011-10-13 13:06:32 +00003873 PixelInfo
cristy3ed852e2009-09-05 21:47:34 +00003874 pixel;
3875
3876 RectangleInfo
3877 crop_info;
3878
3879 Status
3880 status;
3881
3882 Window
3883 child,
3884 client_window,
3885 root_window,
3886 target_window;
3887
3888 XColor
3889 color;
3890
3891 XImage
3892 *ximage;
3893
3894 XWindowAttributes
3895 window_attributes;
3896
3897 /*
3898 Choose a pixel from the X server.
3899 */
3900 assert(display != (Display *) NULL);
3901 assert(name != (char *) NULL);
3902 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",name);
3903 *name='\0';
3904 target_window=XSelectWindow(display,&crop_info);
3905 if (target_window == (Window) NULL)
3906 return(MagickFalse);
3907 root_window=XRootWindow(display,XDefaultScreen(display));
3908 client_window=target_window;
3909 if (target_window != root_window)
3910 {
3911 unsigned int
3912 d;
3913
3914 /*
3915 Get client window.
3916 */
3917 status=XGetGeometry(display,target_window,&root_window,&x,&x,&d,&d,&d,&d);
3918 if (status != False)
3919 {
3920 client_window=XClientWindow(display,target_window);
3921 target_window=client_window;
3922 }
3923 }
3924 /*
3925 Verify window is viewable.
3926 */
3927 status=XGetWindowAttributes(display,target_window,&window_attributes);
3928 if ((status == False) || (window_attributes.map_state != IsViewable))
3929 return(MagickFalse);
3930 /*
3931 Get window X image.
3932 */
3933 (void) XTranslateCoordinates(display,root_window,target_window,
3934 (int) crop_info.x,(int) crop_info.y,&x,&y,&child);
3935 ximage=XGetImage(display,target_window,x,y,1,1,AllPlanes,ZPixmap);
3936 if (ximage == (XImage *) NULL)
3937 return(MagickFalse);
3938 color.pixel=XGetPixel(ximage,0,0);
3939 XDestroyImage(ximage);
3940 /*
3941 Match color against the color database.
3942 */
3943 (void) XQueryColor(display,window_attributes.colormap,&color);
3944 pixel.red=ScaleShortToQuantum(color.red);
3945 pixel.green=ScaleShortToQuantum(color.green);
3946 pixel.blue=ScaleShortToQuantum(color.blue);
cristy4c08aed2011-07-01 19:47:50 +00003947 pixel.alpha=OpaqueAlpha;
cristy3ed852e2009-09-05 21:47:34 +00003948 (void) QueryColorname(windows->image.image,&pixel,X11Compliance,name,
cristy6710d842011-10-20 23:23:00 +00003949 exception);
cristy3ed852e2009-09-05 21:47:34 +00003950 return(MagickTrue);
3951}
3952
3953/*
3954%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3955% %
3956% %
3957% %
3958+ X G e t W i n d o w I m a g e %
3959% %
3960% %
3961% %
3962%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3963%
3964% XGetWindowImage() reads an image from the target X window and returns it.
3965% XGetWindowImage() optionally descends the window hierarchy and overlays the
3966% target image with each child image in an optimized fashion. Any child
3967% window that have the same visual, colormap, and are contained by its parent
3968% are exempted.
3969%
3970% The format of the XGetWindowImage method is:
3971%
3972% Image *XGetWindowImage(Display *display,const Window window,
cristy6710d842011-10-20 23:23:00 +00003973% const unsigned int borders,const unsigned int level,
3974% ExceptionInfo *exception)
cristy3ed852e2009-09-05 21:47:34 +00003975%
3976% A description of each parameter follows:
3977%
3978% o display: Specifies a connection to an X server; returned from
3979% XOpenDisplay.
3980%
3981% o window: Specifies the window to obtain the image from.
3982%
3983% o borders: Specifies whether borders pixels are to be saved with
3984% the image.
3985%
3986% o level: Specifies an unsigned integer representing the level of
3987% decent in the window hierarchy. This value must be zero or one on
3988% the initial call to XGetWindowImage. A value of zero returns after
3989% one call. A value of one causes the function to descend the window
3990% hierarchy and overlay the target image with each subwindow image.
3991%
cristy6710d842011-10-20 23:23:00 +00003992% o exception: return any errors or warnings in this structure.
3993%
cristy3ed852e2009-09-05 21:47:34 +00003994*/
3995static Image *XGetWindowImage(Display *display,const Window window,
cristy6710d842011-10-20 23:23:00 +00003996 const unsigned int borders,const unsigned int level,ExceptionInfo *exception)
cristy3ed852e2009-09-05 21:47:34 +00003997{
3998 typedef struct _ColormapInfo
3999 {
4000 Colormap
4001 colormap;
4002
4003 XColor
4004 *colors;
4005
4006 struct _ColormapInfo
4007 *next;
4008 } ColormapInfo;
4009
4010 typedef struct _WindowInfo
4011 {
4012 Window
4013 window,
4014 parent;
4015
4016 Visual
4017 *visual;
4018
4019 Colormap
4020 colormap;
4021
4022 XSegment
4023 bounds;
4024
4025 RectangleInfo
4026 crop_info;
4027 } WindowInfo;
4028
cristy3ed852e2009-09-05 21:47:34 +00004029 int
4030 display_height,
4031 display_width,
4032 id,
4033 x_offset,
4034 y_offset;
4035
cristy4c08aed2011-07-01 19:47:50 +00004036 Quantum
4037 index;
4038
cristy3ed852e2009-09-05 21:47:34 +00004039 RectangleInfo
4040 crop_info;
4041
cristy3ed852e2009-09-05 21:47:34 +00004042 register int
4043 i;
4044
4045 static ColormapInfo
4046 *colormap_info = (ColormapInfo *) NULL;
4047
4048 static int
4049 max_windows = 0,
4050 number_windows = 0;
4051
4052 static WindowInfo
4053 *window_info;
4054
4055 Status
4056 status;
4057
4058 Window
4059 child,
4060 root_window;
4061
4062 XWindowAttributes
4063 window_attributes;
4064
4065 /*
4066 Verify window is viewable.
4067 */
4068 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
4069 assert(display != (Display *) NULL);
4070 status=XGetWindowAttributes(display,window,&window_attributes);
4071 if ((status == False) || (window_attributes.map_state != IsViewable))
4072 return((Image *) NULL);
4073 /*
4074 Cropping rectangle is relative to root window.
4075 */
4076 root_window=XRootWindow(display,XDefaultScreen(display));
4077 (void) XTranslateCoordinates(display,window,root_window,0,0,&x_offset,
4078 &y_offset,&child);
cristybb503372010-05-27 20:51:26 +00004079 crop_info.x=(ssize_t) x_offset;
4080 crop_info.y=(ssize_t) y_offset;
4081 crop_info.width=(size_t) window_attributes.width;
4082 crop_info.height=(size_t) window_attributes.height;
cristy3ed852e2009-09-05 21:47:34 +00004083 if (borders != MagickFalse)
4084 {
4085 /*
4086 Include border in image.
4087 */
cristybb503372010-05-27 20:51:26 +00004088 crop_info.x-=(ssize_t) window_attributes.border_width;
4089 crop_info.y-=(ssize_t) window_attributes.border_width;
4090 crop_info.width+=(size_t) (window_attributes.border_width << 1);
4091 crop_info.height+=(size_t) (window_attributes.border_width << 1);
cristy3ed852e2009-09-05 21:47:34 +00004092 }
4093 /*
4094 Crop to root window.
4095 */
4096 if (crop_info.x < 0)
4097 {
4098 crop_info.width+=crop_info.x;
4099 crop_info.x=0;
4100 }
4101 if (crop_info.y < 0)
4102 {
4103 crop_info.height+=crop_info.y;
4104 crop_info.y=0;
4105 }
4106 display_width=XDisplayWidth(display,XDefaultScreen(display));
4107 if ((int) (crop_info.x+crop_info.width) > display_width)
cristybb503372010-05-27 20:51:26 +00004108 crop_info.width=(size_t) (display_width-crop_info.x);
cristy3ed852e2009-09-05 21:47:34 +00004109 display_height=XDisplayHeight(display,XDefaultScreen(display));
4110 if ((int) (crop_info.y+crop_info.height) > display_height)
cristybb503372010-05-27 20:51:26 +00004111 crop_info.height=(size_t) (display_height-crop_info.y);
cristy3ed852e2009-09-05 21:47:34 +00004112 /*
4113 Initialize window info attributes.
4114 */
4115 if (number_windows >= max_windows)
4116 {
4117 /*
4118 Allocate or resize window info buffer.
4119 */
4120 max_windows+=1024;
4121 if (window_info == (WindowInfo *) NULL)
4122 window_info=(WindowInfo *) AcquireQuantumMemory((size_t) max_windows,
4123 sizeof(*window_info));
4124 else
4125 window_info=(WindowInfo *) ResizeQuantumMemory(window_info,(size_t)
4126 max_windows,sizeof(*window_info));
4127 }
4128 if (window_info == (WindowInfo *) NULL)
4129 {
4130 ThrowXWindowFatalException(ResourceLimitError,
4131 "MemoryAllocationFailed","...");
4132 return((Image *) NULL);
4133 }
4134 id=number_windows++;
4135 window_info[id].window=window;
4136 window_info[id].visual=window_attributes.visual;
4137 window_info[id].colormap=window_attributes.colormap;
4138 window_info[id].bounds.x1=(short) crop_info.x;
4139 window_info[id].bounds.y1=(short) crop_info.y;
4140 window_info[id].bounds.x2=(short) (crop_info.x+(int) crop_info.width-1);
4141 window_info[id].bounds.y2=(short) (crop_info.y+(int) crop_info.height-1);
4142 crop_info.x-=x_offset;
4143 crop_info.y-=y_offset;
4144 window_info[id].crop_info=crop_info;
4145 if (level != 0)
4146 {
4147 unsigned int
4148 number_children;
4149
4150 Window
4151 *children;
4152
4153 /*
4154 Descend the window hierarchy.
4155 */
4156 status=XQueryTree(display,window,&root_window,&window_info[id].parent,
4157 &children,&number_children);
4158 for (i=0; i < id; i++)
4159 if ((window_info[i].window == window_info[id].parent) &&
4160 (window_info[i].visual == window_info[id].visual) &&
4161 (window_info[i].colormap == window_info[id].colormap))
4162 {
4163 if ((window_info[id].bounds.x1 <= window_info[i].bounds.x1) ||
4164 (window_info[id].bounds.x1 >= window_info[i].bounds.x2) ||
4165 (window_info[id].bounds.y1 <= window_info[i].bounds.y1) ||
4166 (window_info[id].bounds.y1 >= window_info[i].bounds.y2))
4167 {
4168 /*
4169 Eliminate windows not circumscribed by their parent.
4170 */
4171 number_windows--;
4172 break;
4173 }
4174 }
4175 if ((status == True) && (number_children != 0))
4176 {
4177 for (i=0; i < (int) number_children; i++)
cristy6710d842011-10-20 23:23:00 +00004178 (void) XGetWindowImage(display,children[i],MagickFalse,level+1,
4179 exception);
cristy3ed852e2009-09-05 21:47:34 +00004180 (void) XFree((void *) children);
4181 }
4182 }
4183 if (level <= 1)
4184 {
cristyc57f6942010-11-12 01:47:39 +00004185 CacheView
4186 *composite_view;
4187
cristy3ed852e2009-09-05 21:47:34 +00004188 ColormapInfo
4189 *next;
4190
cristy3ed852e2009-09-05 21:47:34 +00004191 Image
4192 *composite_image,
4193 *image;
4194
4195 int
4196 y;
4197
4198 MagickBooleanType
4199 import;
4200
4201 register int
4202 j,
4203 x;
4204
cristy4c08aed2011-07-01 19:47:50 +00004205 register Quantum
cristyc47d1f82009-11-26 01:44:43 +00004206 *restrict q;
cristy3ed852e2009-09-05 21:47:34 +00004207
cristybb503372010-05-27 20:51:26 +00004208 register size_t
cristy3ed852e2009-09-05 21:47:34 +00004209 pixel;
4210
4211 unsigned int
4212 number_colors;
4213
4214 XColor
4215 *colors;
4216
4217 XImage
4218 *ximage;
4219
4220 /*
4221 Get X image for each window in the list.
4222 */
4223 image=NewImageList();
4224 for (id=0; id < number_windows; id++)
4225 {
4226 /*
4227 Does target window intersect top level window?
4228 */
4229 import=
4230 ((window_info[id].bounds.x2 >= window_info[0].bounds.x1) &&
4231 (window_info[id].bounds.x1 <= window_info[0].bounds.x2) &&
4232 (window_info[id].bounds.y2 >= window_info[0].bounds.y1) &&
4233 (window_info[id].bounds.y1 <= window_info[0].bounds.y2)) ?
4234 MagickTrue : MagickFalse;
4235 /*
4236 Is target window contained by another window with the same colormap?
4237 */
4238 for (j=0; j < id; j++)
4239 if ((window_info[id].visual == window_info[j].visual) &&
4240 (window_info[id].colormap == window_info[j].colormap))
4241 {
4242 if ((window_info[id].bounds.x1 <= window_info[j].bounds.x1) ||
4243 (window_info[id].bounds.x1 >= window_info[j].bounds.x2) ||
4244 (window_info[id].bounds.y1 <= window_info[j].bounds.y1) ||
4245 (window_info[id].bounds.y1 >= window_info[j].bounds.y2))
4246 import=MagickFalse;
4247 }
4248 else
4249 if ((window_info[id].visual != window_info[j].visual) ||
4250 (window_info[id].colormap != window_info[j].colormap))
4251 {
4252 if ((window_info[id].bounds.x2 > window_info[j].bounds.x1) &&
4253 (window_info[id].bounds.x1 < window_info[j].bounds.x2) &&
4254 (window_info[id].bounds.y2 > window_info[j].bounds.y1) &&
4255 (window_info[id].bounds.y1 < window_info[j].bounds.y2))
4256 import=MagickTrue;
4257 }
4258 if (import == MagickFalse)
4259 continue;
4260 /*
4261 Get X image.
4262 */
4263 ximage=XGetImage(display,window_info[id].window,(int)
4264 window_info[id].crop_info.x,(int) window_info[id].crop_info.y,
4265 (unsigned int) window_info[id].crop_info.width,(unsigned int)
4266 window_info[id].crop_info.height,AllPlanes,ZPixmap);
4267 if (ximage == (XImage *) NULL)
4268 continue;
4269 /*
4270 Initialize window colormap.
4271 */
4272 number_colors=0;
4273 colors=(XColor *) NULL;
4274 if (window_info[id].colormap != (Colormap) NULL)
4275 {
4276 ColormapInfo
4277 *p;
4278
4279 /*
4280 Search colormap list for window colormap.
4281 */
4282 number_colors=(unsigned int) window_info[id].visual->map_entries;
4283 for (p=colormap_info; p != (ColormapInfo *) NULL; p=p->next)
4284 if (p->colormap == window_info[id].colormap)
4285 break;
4286 if (p == (ColormapInfo *) NULL)
4287 {
4288 /*
4289 Get the window colormap.
4290 */
4291 colors=(XColor *) AcquireQuantumMemory(number_colors,
4292 sizeof(*colors));
4293 if (colors == (XColor *) NULL)
4294 {
4295 XDestroyImage(ximage);
4296 return((Image *) NULL);
4297 }
4298 if ((window_info[id].visual->klass != DirectColor) &&
4299 (window_info[id].visual->klass != TrueColor))
4300 for (i=0; i < (int) number_colors; i++)
4301 {
cristybb503372010-05-27 20:51:26 +00004302 colors[i].pixel=(size_t) i;
cristy3ed852e2009-09-05 21:47:34 +00004303 colors[i].pad='\0';
4304 }
4305 else
4306 {
cristybb503372010-05-27 20:51:26 +00004307 size_t
cristy3ed852e2009-09-05 21:47:34 +00004308 blue,
4309 blue_bit,
4310 green,
4311 green_bit,
4312 red,
4313 red_bit;
4314
4315 /*
4316 DirectColor or TrueColor visual.
4317 */
4318 red=0;
4319 green=0;
4320 blue=0;
4321 red_bit=window_info[id].visual->red_mask &
4322 (~(window_info[id].visual->red_mask)+1);
4323 green_bit=window_info[id].visual->green_mask &
4324 (~(window_info[id].visual->green_mask)+1);
4325 blue_bit=window_info[id].visual->blue_mask &
4326 (~(window_info[id].visual->blue_mask)+1);
4327 for (i=0; i < (int) number_colors; i++)
4328 {
cristy8891f9c2010-06-04 23:32:17 +00004329 colors[i].pixel=(unsigned long) (red | green | blue);
cristy3ed852e2009-09-05 21:47:34 +00004330 colors[i].pad='\0';
4331 red+=red_bit;
4332 if (red > window_info[id].visual->red_mask)
4333 red=0;
4334 green+=green_bit;
4335 if (green > window_info[id].visual->green_mask)
4336 green=0;
4337 blue+=blue_bit;
4338 if (blue > window_info[id].visual->blue_mask)
4339 blue=0;
4340 }
4341 }
4342 (void) XQueryColors(display,window_info[id].colormap,colors,
4343 (int) number_colors);
4344 /*
4345 Append colormap to colormap list.
4346 */
cristy73bd4a52010-10-05 11:24:23 +00004347 p=(ColormapInfo *) AcquireMagickMemory(sizeof(*p));
cristy3ed852e2009-09-05 21:47:34 +00004348 if (p == (ColormapInfo *) NULL)
4349 return((Image *) NULL);
4350 p->colormap=window_info[id].colormap;
4351 p->colors=colors;
4352 p->next=colormap_info;
4353 colormap_info=p;
4354 }
4355 colors=p->colors;
4356 }
4357 /*
4358 Allocate image structure.
4359 */
cristy6710d842011-10-20 23:23:00 +00004360 composite_image=AcquireImage((ImageInfo *) NULL,exception);
cristy3ed852e2009-09-05 21:47:34 +00004361 if (composite_image == (Image *) NULL)
4362 {
4363 XDestroyImage(ximage);
4364 return((Image *) NULL);
4365 }
4366 /*
4367 Convert X image to MIFF format.
4368 */
4369 if ((window_info[id].visual->klass != TrueColor) &&
4370 (window_info[id].visual->klass != DirectColor))
4371 composite_image->storage_class=PseudoClass;
cristybb503372010-05-27 20:51:26 +00004372 composite_image->columns=(size_t) ximage->width;
4373 composite_image->rows=(size_t) ximage->height;
cristyc57f6942010-11-12 01:47:39 +00004374 composite_view=AcquireCacheView(composite_image);
cristy3ed852e2009-09-05 21:47:34 +00004375 switch (composite_image->storage_class)
4376 {
4377 case DirectClass:
4378 default:
4379 {
cristybb503372010-05-27 20:51:26 +00004380 register size_t
cristy3ed852e2009-09-05 21:47:34 +00004381 color,
4382 index;
4383
cristybb503372010-05-27 20:51:26 +00004384 size_t
cristy3ed852e2009-09-05 21:47:34 +00004385 blue_mask,
4386 blue_shift,
4387 green_mask,
4388 green_shift,
4389 red_mask,
4390 red_shift;
4391
4392 /*
4393 Determine shift and mask for red, green, and blue.
4394 */
4395 red_mask=window_info[id].visual->red_mask;
4396 red_shift=0;
4397 while ((red_mask != 0) && ((red_mask & 0x01) == 0))
4398 {
4399 red_mask>>=1;
4400 red_shift++;
4401 }
4402 green_mask=window_info[id].visual->green_mask;
4403 green_shift=0;
4404 while ((green_mask != 0) && ((green_mask & 0x01) == 0))
4405 {
4406 green_mask>>=1;
4407 green_shift++;
4408 }
4409 blue_mask=window_info[id].visual->blue_mask;
4410 blue_shift=0;
4411 while ((blue_mask != 0) && ((blue_mask & 0x01) == 0))
4412 {
4413 blue_mask>>=1;
4414 blue_shift++;
4415 }
4416 /*
4417 Convert X image to DirectClass packets.
4418 */
4419 if ((number_colors != 0) &&
4420 (window_info[id].visual->klass == DirectColor))
4421 for (y=0; y < (int) composite_image->rows; y++)
4422 {
cristyc57f6942010-11-12 01:47:39 +00004423 q=QueueCacheViewAuthenticPixels(composite_view,0,(ssize_t) y,
cristy3ed852e2009-09-05 21:47:34 +00004424 composite_image->columns,1,exception);
cristyacd2ed22011-08-30 01:44:23 +00004425 if (q == (Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00004426 break;
4427 for (x=0; x < (int) composite_image->columns; x++)
4428 {
4429 pixel=XGetPixel(ximage,x,y);
4430 index=(pixel >> red_shift) & red_mask;
cristy4c08aed2011-07-01 19:47:50 +00004431 SetPixelRed(composite_image,
4432 ScaleShortToQuantum(colors[index].red),q);
cristy3ed852e2009-09-05 21:47:34 +00004433 index=(pixel >> green_shift) & green_mask;
cristy4c08aed2011-07-01 19:47:50 +00004434 SetPixelGreen(composite_image,
4435 ScaleShortToQuantum(colors[index].green),q);
cristy3ed852e2009-09-05 21:47:34 +00004436 index=(pixel >> blue_shift) & blue_mask;
cristy4c08aed2011-07-01 19:47:50 +00004437 SetPixelBlue(composite_image,
4438 ScaleShortToQuantum(colors[index].blue),q);
cristyed231572011-07-14 02:18:59 +00004439 q+=GetPixelChannels(composite_image);
cristy3ed852e2009-09-05 21:47:34 +00004440 }
cristy0b1a7972011-10-22 22:17:02 +00004441 status=SyncCacheViewAuthenticPixels(composite_view,exception);
4442 if (status == MagickFalse)
cristy3ed852e2009-09-05 21:47:34 +00004443 break;
4444 }
4445 else
4446 for (y=0; y < (int) composite_image->rows; y++)
4447 {
cristyc57f6942010-11-12 01:47:39 +00004448 q=QueueCacheViewAuthenticPixels(composite_view,0,(ssize_t) y,
cristy3ed852e2009-09-05 21:47:34 +00004449 composite_image->columns,1,exception);
cristyacd2ed22011-08-30 01:44:23 +00004450 if (q == (Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00004451 break;
4452 for (x=0; x < (int) composite_image->columns; x++)
4453 {
4454 pixel=XGetPixel(ximage,x,y);
4455 color=(pixel >> red_shift) & red_mask;
4456 color=(65535UL*color)/red_mask;
cristy4c08aed2011-07-01 19:47:50 +00004457 SetPixelRed(composite_image,
4458 ScaleShortToQuantum((unsigned short) color),q);
cristy3ed852e2009-09-05 21:47:34 +00004459 color=(pixel >> green_shift) & green_mask;
4460 color=(65535UL*color)/green_mask;
cristy4c08aed2011-07-01 19:47:50 +00004461 SetPixelGreen(composite_image,
4462 ScaleShortToQuantum((unsigned short) color),q);
cristy3ed852e2009-09-05 21:47:34 +00004463 color=(pixel >> blue_shift) & blue_mask;
4464 color=(65535UL*color)/blue_mask;
cristy4c08aed2011-07-01 19:47:50 +00004465 SetPixelBlue(composite_image,
4466 ScaleShortToQuantum((unsigned short) color),q);
cristyed231572011-07-14 02:18:59 +00004467 q+=GetPixelChannels(composite_image);
cristy3ed852e2009-09-05 21:47:34 +00004468 }
cristy0b1a7972011-10-22 22:17:02 +00004469 status=SyncCacheViewAuthenticPixels(composite_view,exception);
4470 if (status == MagickFalse)
cristy3ed852e2009-09-05 21:47:34 +00004471 break;
4472 }
4473 break;
4474 }
4475 case PseudoClass:
4476 {
4477 /*
4478 Create colormap.
4479 */
cristy0b1a7972011-10-22 22:17:02 +00004480 status=AcquireImageColormap(composite_image,number_colors,
4481 exception);
4482 if (status == MagickFalse)
cristy3ed852e2009-09-05 21:47:34 +00004483 {
4484 XDestroyImage(ximage);
4485 composite_image=DestroyImage(composite_image);
4486 return((Image *) NULL);
4487 }
4488 for (i=0; i < (int) composite_image->colors; i++)
4489 {
4490 composite_image->colormap[colors[i].pixel].red=
4491 ScaleShortToQuantum(colors[i].red);
4492 composite_image->colormap[colors[i].pixel].green=
4493 ScaleShortToQuantum(colors[i].green);
4494 composite_image->colormap[colors[i].pixel].blue=
4495 ScaleShortToQuantum(colors[i].blue);
4496 }
4497 /*
4498 Convert X image to PseudoClass packets.
4499 */
4500 for (y=0; y < (int) composite_image->rows; y++)
4501 {
cristyc57f6942010-11-12 01:47:39 +00004502 q=QueueCacheViewAuthenticPixels(composite_view,0,(ssize_t) y,
4503 composite_image->columns,1,exception);
cristyacd2ed22011-08-30 01:44:23 +00004504 if (q == (Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00004505 break;
cristy3ed852e2009-09-05 21:47:34 +00004506 for (x=0; x < (int) composite_image->columns; x++)
4507 {
cristy4c08aed2011-07-01 19:47:50 +00004508 index=(Quantum) XGetPixel(ximage,x,y);
4509 SetPixelIndex(composite_image,index,q);
cristy803640d2011-11-17 02:11:32 +00004510 SetPixelInfoPixel(composite_image,
cristy4c08aed2011-07-01 19:47:50 +00004511 composite_image->colormap+(ssize_t) index,q);
cristyed231572011-07-14 02:18:59 +00004512 q+=GetPixelChannels(composite_image);
cristy3ed852e2009-09-05 21:47:34 +00004513 }
cristy0b1a7972011-10-22 22:17:02 +00004514 status=SyncCacheViewAuthenticPixels(composite_view,exception);
4515 if (status == MagickFalse)
cristy3ed852e2009-09-05 21:47:34 +00004516 break;
4517 }
4518 break;
4519 }
4520 }
cristyc57f6942010-11-12 01:47:39 +00004521 composite_view=DestroyCacheView(composite_view);
cristy3ed852e2009-09-05 21:47:34 +00004522 XDestroyImage(ximage);
4523 if (image == (Image *) NULL)
4524 {
4525 image=composite_image;
4526 continue;
4527 }
4528 /*
4529 Composite any children in back-to-front order.
4530 */
4531 (void) XTranslateCoordinates(display,window_info[id].window,window,0,0,
4532 &x_offset,&y_offset,&child);
4533 x_offset-=(int) crop_info.x;
4534 if (x_offset < 0)
4535 x_offset=0;
4536 y_offset-=(int) crop_info.y;
4537 if (y_offset < 0)
4538 y_offset=0;
cristyc57f6942010-11-12 01:47:39 +00004539 (void) CompositeImage(image,CopyCompositeOp,composite_image,(ssize_t)
cristye941a752011-10-15 01:52:48 +00004540 x_offset,(ssize_t) y_offset,exception);
cristy3ed852e2009-09-05 21:47:34 +00004541 }
4542 /*
4543 Relinquish resources.
4544 */
4545 while (colormap_info != (ColormapInfo *) NULL)
4546 {
4547 next=colormap_info->next;
cristye941a752011-10-15 01:52:48 +00004548 colormap_info->colors=(XColor *) RelinquishMagickMemory(
4549 colormap_info->colors);
cristy3ed852e2009-09-05 21:47:34 +00004550 colormap_info=(ColormapInfo *) RelinquishMagickMemory(colormap_info);
4551 colormap_info=next;
4552 }
4553 /*
4554 Relinquish resources and restore initial state.
4555 */
4556 window_info=(WindowInfo *) RelinquishMagickMemory(window_info);
4557 max_windows=0;
4558 number_windows=0;
4559 colormap_info=(ColormapInfo *) NULL;
4560 return(image);
4561 }
4562 return((Image *) NULL);
4563}
4564
4565/*
4566%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4567% %
4568% %
4569% %
4570% X G e t W i n d o w I n f o %
4571% %
4572% %
4573% %
4574%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4575%
4576% XGetWindowInfo() initializes the XWindowInfo structure.
4577%
4578% The format of the XGetWindowInfo method is:
4579%
4580% void XGetWindowInfo(Display *display,XVisualInfo *visual_info,
4581% XStandardColormap *map_info,XPixelInfo *pixel,XFontStruct *font_info,
4582% XResourceInfo *resource_info,XWindowInfo *window)
4583% resource_info,window)
4584%
4585% A description of each parameter follows:
4586%
4587% o display: Specifies a connection to an X server; returned from
4588% XOpenDisplay.
4589%
4590% o visual_info: Specifies a pointer to a X11 XVisualInfo structure;
4591% returned from XGetVisualInfo.
4592%
4593% o map_info: If map_type is specified, this structure is initialized
4594% with info from the Standard Colormap.
4595%
4596% o pixel: Specifies a pointer to a XPixelInfo structure.
4597%
4598% o font_info: Specifies a pointer to a XFontStruct structure.
4599%
4600% o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
4601%
4602*/
cristybcbda3f2011-09-03 13:01:22 +00004603MagickPrivate void XGetWindowInfo(Display *display,XVisualInfo *visual_info,
cristy3ed852e2009-09-05 21:47:34 +00004604 XStandardColormap *map_info,XPixelInfo *pixel,XFontStruct *font_info,
4605 XResourceInfo *resource_info,XWindowInfo *window)
4606{
4607 /*
4608 Initialize window info.
4609 */
4610 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
4611 assert(display != (Display *) NULL);
4612 assert(visual_info != (XVisualInfo *) NULL);
4613 assert(map_info != (XStandardColormap *) NULL);
4614 assert(pixel != (XPixelInfo *) NULL);
4615 assert(resource_info != (XResourceInfo *) NULL);
4616 assert(window != (XWindowInfo *) NULL);
4617 if (window->id != (Window) NULL)
4618 {
4619 if (window->cursor != (Cursor) NULL)
4620 (void) XFreeCursor(display,window->cursor);
4621 if (window->busy_cursor != (Cursor) NULL)
4622 (void) XFreeCursor(display,window->busy_cursor);
4623 if (window->highlight_stipple != (Pixmap) NULL)
4624 (void) XFreePixmap(display,window->highlight_stipple);
4625 if (window->shadow_stipple != (Pixmap) NULL)
4626 (void) XFreePixmap(display,window->shadow_stipple);
4627 if (window->name == (char *) NULL)
4628 window->name=AcquireString("");
4629 if (window->icon_name == (char *) NULL)
4630 window->icon_name=AcquireString("");
4631 }
4632 else
4633 {
4634 /*
4635 Initialize these attributes just once.
4636 */
4637 window->id=(Window) NULL;
4638 if (window->name == (char *) NULL)
4639 window->name=AcquireString("");
4640 if (window->icon_name == (char *) NULL)
4641 window->icon_name=AcquireString("");
4642 window->x=XDisplayWidth(display,visual_info->screen) >> 1;
4643 window->y=XDisplayWidth(display,visual_info->screen) >> 1;
4644 window->ximage=(XImage *) NULL;
4645 window->matte_image=(XImage *) NULL;
4646 window->pixmap=(Pixmap) NULL;
4647 window->matte_pixmap=(Pixmap) NULL;
4648 window->mapped=MagickFalse;
4649 window->stasis=MagickFalse;
4650 window->shared_memory=MagickTrue;
4651 window->segment_info=(void *) NULL;
4652#if defined(MAGICKCORE_HAVE_SHARED_MEMORY)
4653 {
4654 XShmSegmentInfo
4655 *segment_info;
4656
4657 if (window->segment_info == (void *) NULL)
4658 window->segment_info=AcquireQuantumMemory(2,sizeof(*segment_info));
4659 segment_info=(XShmSegmentInfo *) window->segment_info;
4660 segment_info[0].shmid=(-1);
4661 segment_info[0].shmaddr=(char *) NULL;
4662 segment_info[1].shmid=(-1);
4663 segment_info[1].shmaddr=(char *) NULL;
4664 }
4665#endif
4666 }
4667 /*
4668 Initialize these attributes every time function is called.
4669 */
4670 window->screen=visual_info->screen;
4671 window->root=XRootWindow(display,visual_info->screen);
4672 window->visual=visual_info->visual;
4673 window->storage_class=(unsigned int) visual_info->klass;
4674 window->depth=(unsigned int) visual_info->depth;
4675 window->visual_info=visual_info;
4676 window->map_info=map_info;
4677 window->pixel_info=pixel;
4678 window->font_info=font_info;
4679 window->cursor=XCreateFontCursor(display,XC_left_ptr);
4680 window->busy_cursor=XCreateFontCursor(display,XC_watch);
4681 window->geometry=(char *) NULL;
4682 window->icon_geometry=(char *) NULL;
4683 if (resource_info->icon_geometry != (char *) NULL)
4684 (void) CloneString(&window->icon_geometry,resource_info->icon_geometry);
4685 window->crop_geometry=(char *) NULL;
cristybb503372010-05-27 20:51:26 +00004686 window->flags=(size_t) PSize;
cristy3ed852e2009-09-05 21:47:34 +00004687 window->width=1;
4688 window->height=1;
4689 window->min_width=1;
4690 window->min_height=1;
4691 window->width_inc=1;
4692 window->height_inc=1;
4693 window->border_width=resource_info->border_width;
4694 window->annotate_context=pixel->annotate_context;
4695 window->highlight_context=pixel->highlight_context;
4696 window->widget_context=pixel->widget_context;
4697 window->shadow_stipple=(Pixmap) NULL;
4698 window->highlight_stipple=(Pixmap) NULL;
4699 window->use_pixmap=MagickTrue;
4700 window->immutable=MagickFalse;
4701 window->shape=MagickFalse;
4702 window->data=0;
cristyc57f6942010-11-12 01:47:39 +00004703 window->mask=(int) (CWBackingStore | CWBackPixel | CWBackPixmap |
cristy3ed852e2009-09-05 21:47:34 +00004704 CWBitGravity | CWBorderPixel | CWColormap | CWCursor | CWDontPropagate |
4705 CWEventMask | CWOverrideRedirect | CWSaveUnder | CWWinGravity);
4706 window->attributes.background_pixel=pixel->background_color.pixel;
4707 window->attributes.background_pixmap=(Pixmap) NULL;
4708 window->attributes.bit_gravity=ForgetGravity;
4709 window->attributes.backing_store=WhenMapped;
4710 window->attributes.save_under=MagickTrue;
4711 window->attributes.border_pixel=pixel->border_color.pixel;
4712 window->attributes.colormap=map_info->colormap;
4713 window->attributes.cursor=window->cursor;
4714 window->attributes.do_not_propagate_mask=NoEventMask;
4715 window->attributes.event_mask=NoEventMask;
4716 window->attributes.override_redirect=MagickFalse;
4717 window->attributes.win_gravity=NorthWestGravity;
4718 window->orphan=MagickFalse;
4719}
4720
4721/*
4722%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4723% %
4724% %
4725% %
4726% X H i g h l i g h t E l l i p s e %
4727% %
4728% %
4729% %
4730%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4731%
4732% XHighlightEllipse() puts a border on the X server around a region defined by
4733% highlight_info.
4734%
4735% The format of the XHighlightEllipse method is:
4736%
4737% void XHighlightEllipse(Display *display,Window window,
4738% GC annotate_context,const RectangleInfo *highlight_info)
4739%
4740% A description of each parameter follows:
4741%
4742% o display: Specifies a connection to an X server; returned from
4743% XOpenDisplay.
4744%
4745% o window: Specifies a pointer to a Window structure.
4746%
4747% o annotate_context: Specifies a pointer to a GC structure.
4748%
4749% o highlight_info: Specifies a pointer to a RectangleInfo structure. It
4750% contains the extents of any highlighting rectangle.
4751%
4752*/
cristybcbda3f2011-09-03 13:01:22 +00004753MagickPrivate void XHighlightEllipse(Display *display,Window window,
cristy3ed852e2009-09-05 21:47:34 +00004754 GC annotate_context,const RectangleInfo *highlight_info)
4755{
4756 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
4757 assert(display != (Display *) NULL);
4758 assert(window != (Window) NULL);
4759 assert(annotate_context != (GC) NULL);
4760 assert(highlight_info != (RectangleInfo *) NULL);
4761 if ((highlight_info->width < 4) || (highlight_info->height < 4))
4762 return;
4763 (void) XDrawArc(display,window,annotate_context,(int) highlight_info->x,
4764 (int) highlight_info->y,(unsigned int) highlight_info->width-1,
4765 (unsigned int) highlight_info->height-1,0,360*64);
4766 (void) XDrawArc(display,window,annotate_context,(int) highlight_info->x+1,
4767 (int) highlight_info->y+1,(unsigned int) highlight_info->width-3,
4768 (unsigned int) highlight_info->height-3,0,360*64);
4769}
4770
4771/*
4772%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4773% %
4774% %
4775% %
4776% X H i g h l i g h t L i n e %
4777% %
4778% %
4779% %
4780%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4781%
4782% XHighlightLine() puts a border on the X server around a region defined by
4783% highlight_info.
4784%
4785% The format of the XHighlightLine method is:
4786%
4787% void XHighlightLine(Display *display,Window window,GC annotate_context,
4788% const XSegment *highlight_info)
4789%
4790% A description of each parameter follows:
4791%
4792% o display: Specifies a connection to an X server; returned from
4793% XOpenDisplay.
4794%
4795% o window: Specifies a pointer to a Window structure.
4796%
4797% o annotate_context: Specifies a pointer to a GC structure.
4798%
4799% o highlight_info: Specifies a pointer to a RectangleInfo structure. It
4800% contains the extents of any highlighting rectangle.
4801%
4802*/
cristybcbda3f2011-09-03 13:01:22 +00004803MagickPrivate void XHighlightLine(Display *display,Window window,
cristy3ed852e2009-09-05 21:47:34 +00004804 GC annotate_context,const XSegment *highlight_info)
4805{
4806 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
4807 assert(display != (Display *) NULL);
4808 assert(window != (Window) NULL);
4809 assert(annotate_context != (GC) NULL);
4810 assert(highlight_info != (XSegment *) NULL);
4811 (void) XDrawLine(display,window,annotate_context,highlight_info->x1,
4812 highlight_info->y1,highlight_info->x2,highlight_info->y2);
4813}
4814
4815/*
4816%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4817% %
4818% %
4819% %
4820% X H i g h l i g h t R e c t a n g l e %
4821% %
4822% %
4823% %
4824%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4825%
4826% XHighlightRectangle() puts a border on the X server around a region defined
4827% by highlight_info.
4828%
4829% The format of the XHighlightRectangle method is:
4830%
4831% void XHighlightRectangle(Display *display,Window window,
4832% GC annotate_context,const RectangleInfo *highlight_info)
4833%
4834% A description of each parameter follows:
4835%
4836% o display: Specifies a connection to an X server; returned from
4837% XOpenDisplay.
4838%
4839% o window: Specifies a pointer to a Window structure.
4840%
4841% o annotate_context: Specifies a pointer to a GC structure.
4842%
4843% o highlight_info: Specifies a pointer to a RectangleInfo structure. It
4844% contains the extents of any highlighting rectangle.
4845%
4846*/
cristybcbda3f2011-09-03 13:01:22 +00004847MagickPrivate void XHighlightRectangle(Display *display,Window window,
cristy3ed852e2009-09-05 21:47:34 +00004848 GC annotate_context,const RectangleInfo *highlight_info)
4849{
4850 assert(display != (Display *) NULL);
4851 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
4852 assert(window != (Window) NULL);
4853 assert(annotate_context != (GC) NULL);
4854 assert(highlight_info != (RectangleInfo *) NULL);
4855 if ((highlight_info->width < 4) || (highlight_info->height < 4))
4856 return;
4857 (void) XDrawRectangle(display,window,annotate_context,(int) highlight_info->x,
4858 (int) highlight_info->y,(unsigned int) highlight_info->width-1,
4859 (unsigned int) highlight_info->height-1);
4860 (void) XDrawRectangle(display,window,annotate_context,(int) highlight_info->x+
4861 1,(int) highlight_info->y+1,(unsigned int) highlight_info->width-3,
4862 (unsigned int) highlight_info->height-3);
4863}
4864
4865/*
4866%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4867% %
4868% %
4869% %
4870% X I m p o r t I m a g e %
4871% %
4872% %
4873% %
4874%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4875%
4876% XImportImage() reads an image from an X window.
4877%
4878% The format of the XImportImage method is:
4879%
cristy6710d842011-10-20 23:23:00 +00004880% Image *XImportImage(const ImageInfo *image_info,XImportInfo *ximage_info,
4881% ExceptionInfo *exception)
cristy3ed852e2009-09-05 21:47:34 +00004882%
4883% A description of each parameter follows:
4884%
4885% o image_info: the image info.
4886%
4887% o ximage_info: Specifies a pointer to an XImportInfo structure.
4888%
cristy6710d842011-10-20 23:23:00 +00004889% o exception: return any errors or warnings in this structure.
4890%
cristy3ed852e2009-09-05 21:47:34 +00004891*/
4892MagickExport Image *XImportImage(const ImageInfo *image_info,
cristy6710d842011-10-20 23:23:00 +00004893 XImportInfo *ximage_info,ExceptionInfo *exception)
cristy3ed852e2009-09-05 21:47:34 +00004894{
4895 Colormap
4896 *colormaps;
4897
4898 Display
4899 *display;
4900
4901 Image
4902 *image;
4903
4904 int
4905 number_colormaps,
4906 number_windows,
4907 x;
4908
4909 RectangleInfo
4910 crop_info;
4911
4912 Status
4913 status;
4914
4915 Window
4916 *children,
4917 client,
4918 prior_target,
4919 root,
4920 target;
4921
4922 XTextProperty
4923 window_name;
4924
4925 /*
4926 Open X server connection.
4927 */
4928 assert(image_info != (const ImageInfo *) NULL);
4929 assert(image_info->signature == MagickSignature);
4930 if (image_info->debug != MagickFalse)
4931 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
4932 image_info->filename);
4933 assert(ximage_info != (XImportInfo *) NULL);
4934 display=XOpenDisplay(image_info->server_name);
4935 if (display == (Display *) NULL)
4936 {
4937 ThrowXWindowFatalException(XServerError,"UnableToOpenXServer",
4938 XDisplayName(image_info->server_name));
4939 return((Image *) NULL);
4940 }
4941 /*
4942 Set our forgiving exception handler.
4943 */
4944 (void) XSetErrorHandler(XError);
4945 /*
4946 Select target window.
4947 */
4948 crop_info.x=0;
4949 crop_info.y=0;
4950 crop_info.width=0;
4951 crop_info.height=0;
4952 root=XRootWindow(display,XDefaultScreen(display));
4953 target=(Window) NULL;
4954 if ((image_info->filename != (char *) NULL) &&
4955 (*image_info->filename != '\0'))
4956 {
4957 if (LocaleCompare(image_info->filename,"root") == 0)
4958 target=root;
4959 else
4960 {
4961 /*
4962 Select window by ID or name.
4963 */
4964 if (isdigit((unsigned char) *image_info->filename) != 0)
4965 target=XWindowByID(display,root,(Window)
4966 strtol(image_info->filename,(char **) NULL,0));
4967 if (target == (Window) NULL)
4968 target=XWindowByName(display,root,image_info->filename);
4969 if (target == (Window) NULL)
4970 ThrowXWindowFatalException(XServerError,
4971 "NoWindowWithSpecifiedIDExists",image_info->filename);
4972 }
4973 }
4974 /*
4975 If target window is not defined, interactively select one.
4976 */
4977 prior_target=target;
4978 if (target == (Window) NULL)
4979 target=XSelectWindow(display,&crop_info);
4980 if (target == (Window) NULL)
4981 ThrowXWindowFatalException(XServerError,"UnableToReadXWindowImage",
4982 image_info->filename);
4983 client=target; /* obsolete */
4984 if (target != root)
4985 {
4986 unsigned int
4987 d;
4988
4989 status=XGetGeometry(display,target,&root,&x,&x,&d,&d,&d,&d);
4990 if (status != False)
4991 {
4992 for ( ; ; )
4993 {
4994 Window
4995 parent;
4996
4997 /*
4998 Find window manager frame.
4999 */
5000 status=XQueryTree(display,target,&root,&parent,&children,&d);
5001 if ((status != False) && (children != (Window *) NULL))
5002 (void) XFree((char *) children);
5003 if ((status == False) || (parent == (Window) NULL) ||
5004 (parent == root))
5005 break;
5006 target=parent;
5007 }
5008 /*
5009 Get client window.
5010 */
5011 client=XClientWindow(display,target);
5012 if (ximage_info->frame == MagickFalse)
5013 target=client;
5014 if ((ximage_info->frame == MagickFalse) &&
5015 (prior_target != MagickFalse))
5016 target=prior_target;
5017 XDelay(display,SuspendTime << 4);
5018 }
5019 }
5020 if (ximage_info->screen)
5021 {
5022 int
5023 y;
5024
5025 Window
5026 child;
5027
5028 XWindowAttributes
5029 window_attributes;
5030
5031 /*
5032 Obtain window image directly from screen.
5033 */
5034 status=XGetWindowAttributes(display,target,&window_attributes);
5035 if (status == False)
5036 {
5037 ThrowXWindowFatalException(XServerError,
5038 "UnableToReadXWindowAttributes",image_info->filename);
5039 (void) XCloseDisplay(display);
5040 return((Image *) NULL);
5041 }
5042 (void) XTranslateCoordinates(display,target,root,0,0,&x,&y,&child);
cristyc57f6942010-11-12 01:47:39 +00005043 crop_info.x=(ssize_t) x;
5044 crop_info.y=(ssize_t) y;
cristybb503372010-05-27 20:51:26 +00005045 crop_info.width=(size_t) window_attributes.width;
5046 crop_info.height=(size_t) window_attributes.height;
cristy553743c2010-03-03 15:04:17 +00005047 if (ximage_info->borders != 0)
cristy3ed852e2009-09-05 21:47:34 +00005048 {
5049 /*
5050 Include border in image.
5051 */
5052 crop_info.x-=window_attributes.border_width;
5053 crop_info.y-=window_attributes.border_width;
5054 crop_info.width+=window_attributes.border_width << 1;
5055 crop_info.height+=window_attributes.border_width << 1;
5056 }
5057 target=root;
5058 }
5059 /*
5060 If WM_COLORMAP_WINDOWS property is set or multiple colormaps, descend.
5061 */
5062 number_windows=0;
5063 status=XGetWMColormapWindows(display,target,&children,&number_windows);
5064 if ((status == True) && (number_windows > 0))
5065 {
5066 ximage_info->descend=MagickTrue;
5067 (void) XFree ((char *) children);
5068 }
5069 colormaps=XListInstalledColormaps(display,target,&number_colormaps);
5070 if (number_colormaps > 0)
5071 {
5072 if (number_colormaps > 1)
5073 ximage_info->descend=MagickTrue;
5074 (void) XFree((char *) colormaps);
5075 }
5076 /*
5077 Alert the user not to alter the screen.
5078 */
5079 if (ximage_info->silent == MagickFalse)
5080 (void) XBell(display,0);
5081 /*
5082 Get image by window id.
5083 */
5084 (void) XGrabServer(display);
5085 image=XGetWindowImage(display,target,ximage_info->borders,
cristy6710d842011-10-20 23:23:00 +00005086 ximage_info->descend ? 1U : 0U,exception);
cristy3ed852e2009-09-05 21:47:34 +00005087 (void) XUngrabServer(display);
5088 if (image == (Image *) NULL)
5089 ThrowXWindowFatalException(XServerError,"UnableToReadXWindowImage",
5090 image_info->filename)
5091 else
5092 {
5093 (void) CopyMagickString(image->filename,image_info->filename,
5094 MaxTextExtent);
5095 if ((crop_info.width != 0) && (crop_info.height != 0))
5096 {
5097 Image
5098 *clone_image,
5099 *crop_image;
5100
5101 /*
5102 Crop image as defined by the cropping rectangle.
5103 */
cristy6710d842011-10-20 23:23:00 +00005104 clone_image=CloneImage(image,0,0,MagickTrue,exception);
cristy3ed852e2009-09-05 21:47:34 +00005105 if (clone_image != (Image *) NULL)
5106 {
cristy6710d842011-10-20 23:23:00 +00005107 crop_image=CropImage(clone_image,&crop_info,exception);
cristy3ed852e2009-09-05 21:47:34 +00005108 if (crop_image != (Image *) NULL)
5109 {
5110 image=DestroyImage(image);
5111 image=crop_image;
5112 }
5113 }
5114 }
5115 status=XGetWMName(display,target,&window_name);
5116 if (status == True)
5117 {
5118 if ((image_info->filename != (char *) NULL) &&
5119 (*image_info->filename == '\0'))
5120 (void) CopyMagickString(image->filename,(char *) window_name.value,
5121 (size_t) window_name.nitems+1);
5122 (void) XFree((void *) window_name.value);
5123 }
5124 }
5125 if (ximage_info->silent == MagickFalse)
5126 {
5127 /*
5128 Alert the user we're done.
5129 */
5130 (void) XBell(display,0);
5131 (void) XBell(display,0);
5132 }
5133 (void) XCloseDisplay(display);
5134 return(image);
5135}
5136
5137/*
5138%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5139% %
5140% %
5141% %
5142% X I n i t i a l i z e W i n d o w s %
5143% %
5144% %
5145% %
5146%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5147%
5148% XInitializeWindows() initializes the XWindows structure.
5149%
5150% The format of the XInitializeWindows method is:
5151%
5152% XWindows *XInitializeWindows(Display *display,
5153% XResourceInfo *resource_info)
5154%
5155% A description of each parameter follows:
5156%
5157% o windows: XInitializeWindows returns a pointer to a XWindows structure.
5158%
5159% o display: Specifies a connection to an X server; returned from
5160% XOpenDisplay.
5161%
5162% o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
5163%
5164*/
cristybcbda3f2011-09-03 13:01:22 +00005165MagickPrivate XWindows *XInitializeWindows(Display *display,
cristy3ed852e2009-09-05 21:47:34 +00005166 XResourceInfo *resource_info)
5167{
5168 Window
5169 root_window;
5170
5171 XWindows
5172 *windows;
5173
5174 /*
5175 Allocate windows structure.
5176 */
cristy73bd4a52010-10-05 11:24:23 +00005177 windows=(XWindows *) AcquireMagickMemory(sizeof(*windows));
cristy3ed852e2009-09-05 21:47:34 +00005178 if (windows == (XWindows *) NULL)
5179 {
5180 ThrowXWindowFatalException(XServerFatalError,"MemoryAllocationFailed",
5181 "...");
5182 return((XWindows *) NULL);
5183 }
5184 (void) ResetMagickMemory(windows,0,sizeof(*windows));
5185 windows->pixel_info=(XPixelInfo *) AcquireMagickMemory(
5186 sizeof(*windows->pixel_info));
5187 windows->icon_pixel=(XPixelInfo *) AcquireMagickMemory(
5188 sizeof(*windows->icon_pixel));
5189 windows->icon_resources=(XResourceInfo *) AcquireMagickMemory(
5190 sizeof(*windows->icon_resources));
5191 if ((windows->pixel_info == (XPixelInfo *) NULL) ||
5192 (windows->icon_pixel == (XPixelInfo *) NULL) ||
5193 (windows->icon_resources == (XResourceInfo *) NULL))
5194 {
5195 ThrowXWindowFatalException(XServerFatalError,"MemoryAllocationFailed",
5196 "...");
5197 return((XWindows *) NULL);
5198 }
5199 /*
5200 Initialize windows structure.
5201 */
5202 windows->display=display;
5203 windows->wm_protocols=XInternAtom(display,"WM_PROTOCOLS",MagickFalse);
5204 windows->wm_delete_window=XInternAtom(display,"WM_DELETE_WINDOW",MagickFalse);
5205 windows->wm_take_focus=XInternAtom(display,"WM_TAKE_FOCUS",MagickFalse);
5206 windows->im_protocols=XInternAtom(display,"IM_PROTOCOLS",MagickFalse);
5207 windows->im_remote_command=
5208 XInternAtom(display,"IM_REMOTE_COMMAND",MagickFalse);
5209 windows->im_update_widget=XInternAtom(display,"IM_UPDATE_WIDGET",MagickFalse);
5210 windows->im_update_colormap=
5211 XInternAtom(display,"IM_UPDATE_COLORMAP",MagickFalse);
5212 windows->im_former_image=XInternAtom(display,"IM_FORMER_IMAGE",MagickFalse);
5213 windows->im_next_image=XInternAtom(display,"IM_NEXT_IMAGE",MagickFalse);
5214 windows->im_retain_colors=XInternAtom(display,"IM_RETAIN_COLORS",MagickFalse);
5215 windows->im_exit=XInternAtom(display,"IM_EXIT",MagickFalse);
5216 windows->dnd_protocols=XInternAtom(display,"DndProtocol",MagickFalse);
cristy0157aea2010-04-24 21:12:18 +00005217#if defined(MAGICKCORE_WINDOWS_SUPPORT)
cristy3ed852e2009-09-05 21:47:34 +00005218 (void) XSynchronize(display,IsWindows95());
5219#endif
5220 if (IsEventLogging())
5221 {
5222 (void) XSynchronize(display,MagickTrue);
5223 (void) LogMagickEvent(X11Event,GetMagickModule(),"Version: %s",
cristybb503372010-05-27 20:51:26 +00005224 GetMagickVersion((size_t *) NULL));
cristy3ed852e2009-09-05 21:47:34 +00005225 (void) LogMagickEvent(X11Event,GetMagickModule(),"Protocols:");
5226 (void) LogMagickEvent(X11Event,GetMagickModule(),
5227 " Window Manager: 0x%lx",windows->wm_protocols);
5228 (void) LogMagickEvent(X11Event,GetMagickModule(),
5229 " delete window: 0x%lx",windows->wm_delete_window);
5230 (void) LogMagickEvent(X11Event,GetMagickModule()," take focus: 0x%lx",
5231 windows->wm_take_focus);
5232 (void) LogMagickEvent(X11Event,GetMagickModule()," ImageMagick: 0x%lx",
5233 windows->im_protocols);
5234 (void) LogMagickEvent(X11Event,GetMagickModule(),
5235 " remote command: 0x%lx",windows->im_remote_command);
5236 (void) LogMagickEvent(X11Event,GetMagickModule(),
5237 " update widget: 0x%lx",windows->im_update_widget);
5238 (void) LogMagickEvent(X11Event,GetMagickModule(),
5239 " update colormap: 0x%lx",windows->im_update_colormap);
5240 (void) LogMagickEvent(X11Event,GetMagickModule(),
5241 " former image: 0x%lx",windows->im_former_image);
5242 (void) LogMagickEvent(X11Event,GetMagickModule()," next image: 0x%lx",
5243 windows->im_next_image);
5244 (void) LogMagickEvent(X11Event,GetMagickModule(),
5245 " retain colors: 0x%lx",windows->im_retain_colors);
5246 (void) LogMagickEvent(X11Event,GetMagickModule()," exit: 0x%lx",
5247 windows->im_exit);
5248 (void) LogMagickEvent(X11Event,GetMagickModule()," Drag and Drop: 0x%lx",
5249 windows->dnd_protocols);
5250 }
5251 /*
5252 Allocate standard colormap.
5253 */
5254 windows->map_info=XAllocStandardColormap();
5255 windows->icon_map=XAllocStandardColormap();
5256 if ((windows->map_info == (XStandardColormap *) NULL) ||
5257 (windows->icon_map == (XStandardColormap *) NULL))
5258 ThrowXWindowFatalException(ResourceLimitFatalError,
5259 "MemoryAllocationFailed","...");
5260 windows->map_info->colormap=(Colormap) NULL;
5261 windows->icon_map->colormap=(Colormap) NULL;
cristyf2faecf2010-05-28 19:19:36 +00005262 windows->pixel_info->pixels=(unsigned long *) NULL;
cristy3ed852e2009-09-05 21:47:34 +00005263 windows->pixel_info->annotate_context=(GC) NULL;
5264 windows->pixel_info->highlight_context=(GC) NULL;
5265 windows->pixel_info->widget_context=(GC) NULL;
5266 windows->font_info=(XFontStruct *) NULL;
5267 windows->icon_pixel->annotate_context=(GC) NULL;
cristyf2faecf2010-05-28 19:19:36 +00005268 windows->icon_pixel->pixels=(unsigned long *) NULL;
cristy3ed852e2009-09-05 21:47:34 +00005269 /*
5270 Allocate visual.
5271 */
5272 *windows->icon_resources=(*resource_info);
5273 windows->icon_resources->visual_type=(char *) "default";
5274 windows->icon_resources->colormap=SharedColormap;
5275 windows->visual_info=
5276 XBestVisualInfo(display,windows->map_info,resource_info);
5277 windows->icon_visual=
5278 XBestVisualInfo(display,windows->icon_map,windows->icon_resources);
5279 if ((windows->visual_info == (XVisualInfo *) NULL) ||
5280 (windows->icon_visual == (XVisualInfo *) NULL))
5281 ThrowXWindowFatalException(XServerFatalError,"UnableToGetVisual",
5282 resource_info->visual_type);
5283 if (IsEventLogging())
5284 {
5285 (void) LogMagickEvent(X11Event,GetMagickModule(),"Visual:");
5286 (void) LogMagickEvent(X11Event,GetMagickModule()," visual id: 0x%lx",
5287 windows->visual_info->visualid);
5288 (void) LogMagickEvent(X11Event,GetMagickModule()," class: %s",
5289 XVisualClassName(windows->visual_info->klass));
5290 (void) LogMagickEvent(X11Event,GetMagickModule()," depth: %d planes",
5291 windows->visual_info->depth);
5292 (void) LogMagickEvent(X11Event,GetMagickModule(),
5293 " size of colormap: %d entries",windows->visual_info->colormap_size);
5294 (void) LogMagickEvent(X11Event,GetMagickModule(),
5295 " red, green, blue masks: 0x%lx 0x%lx 0x%lx",
5296 windows->visual_info->red_mask,windows->visual_info->green_mask,
5297 windows->visual_info->blue_mask);
5298 (void) LogMagickEvent(X11Event,GetMagickModule(),
5299 " significant bits in color: %d bits",
5300 windows->visual_info->bits_per_rgb);
5301 }
5302 /*
5303 Allocate class and manager hints.
5304 */
5305 windows->class_hints=XAllocClassHint();
5306 windows->manager_hints=XAllocWMHints();
5307 if ((windows->class_hints == (XClassHint *) NULL) ||
5308 (windows->manager_hints == (XWMHints *) NULL))
5309 ThrowXWindowFatalException(ResourceLimitFatalError,
5310 "MemoryAllocationFailed","...");
5311 /*
5312 Determine group leader if we have one.
5313 */
5314 root_window=XRootWindow(display,windows->visual_info->screen);
5315 windows->group_leader.id=(Window) NULL;
5316 if (resource_info->window_group != (char *) NULL)
5317 {
5318 if (isdigit((unsigned char) *resource_info->window_group) != 0)
5319 windows->group_leader.id=XWindowByID(display,root_window,(Window)
5320 strtol((char *) resource_info->window_group,(char **) NULL,0));
5321 if (windows->group_leader.id == (Window) NULL)
5322 windows->group_leader.id=
5323 XWindowByName(display,root_window,resource_info->window_group);
5324 }
5325 return(windows);
5326}
5327
5328/*
5329%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5330% %
5331% %
5332% %
5333% X M a k e C u r s o r %
5334% %
5335% %
5336% %
5337%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5338%
5339% XMakeCursor() creates a crosshairs X11 cursor.
5340%
5341% The format of the XMakeCursor method is:
5342%
5343% Cursor XMakeCursor(Display *display,Window window,Colormap colormap,
5344% char *background_color,char *foreground_color)
5345%
5346% A description of each parameter follows:
5347%
5348% o display: Specifies a connection to an X server; returned from
5349% XOpenDisplay.
5350%
5351% o window: Specifies the ID of the window for which the cursor is
5352% assigned.
5353%
5354% o colormap: Specifies the ID of the colormap from which the background
5355% and foreground color will be retrieved.
5356%
5357% o background_color: Specifies the color to use for the cursor background.
5358%
5359% o foreground_color: Specifies the color to use for the cursor foreground.
5360%
5361*/
cristybcbda3f2011-09-03 13:01:22 +00005362MagickPrivate Cursor XMakeCursor(Display *display,Window window,
cristy3ed852e2009-09-05 21:47:34 +00005363 Colormap colormap,char *background_color,char *foreground_color)
5364{
5365#define scope_height 17
5366#define scope_x_hot 8
5367#define scope_y_hot 8
5368#define scope_width 17
5369
5370 static const unsigned char
5371 scope_bits[] =
5372 {
5373 0x80, 0x03, 0x00, 0x80, 0x02, 0x00, 0x80, 0x02, 0x00, 0x80, 0x02,
5374 0x00, 0x80, 0x02, 0x00, 0x80, 0x02, 0x00, 0x80, 0x02, 0x00, 0x7f,
5375 0xfc, 0x01, 0x01, 0x00, 0x01, 0x7f, 0xfc, 0x01, 0x80, 0x02, 0x00,
5376 0x80, 0x02, 0x00, 0x80, 0x02, 0x00, 0x80, 0x02, 0x00, 0x80, 0x02,
5377 0x00, 0x80, 0x02, 0x00, 0x80, 0x03, 0x00
5378 },
5379 scope_mask_bits[] =
5380 {
5381 0xc0, 0x07, 0x00, 0xc0, 0x07, 0x00, 0xc0, 0x06, 0x00, 0xc0, 0x06,
5382 0x00, 0xc0, 0x06, 0x00, 0xc0, 0x06, 0x00, 0xff, 0xfe, 0x01, 0x7f,
5383 0xfc, 0x01, 0x03, 0x80, 0x01, 0x7f, 0xfc, 0x01, 0xff, 0xfe, 0x01,
5384 0xc0, 0x06, 0x00, 0xc0, 0x06, 0x00, 0xc0, 0x06, 0x00, 0xc0, 0x06,
5385 0x00, 0xc0, 0x07, 0x00, 0xc0, 0x07, 0x00
5386 };
5387
5388 Cursor
5389 cursor;
5390
5391 Pixmap
5392 mask,
5393 source;
5394
5395 XColor
5396 background,
5397 foreground;
5398
5399 assert(display != (Display *) NULL);
5400 assert(window != (Window) NULL);
5401 assert(colormap != (Colormap) NULL);
5402 assert(background_color != (char *) NULL);
5403 assert(foreground_color != (char *) NULL);
5404 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",background_color);
5405 source=XCreateBitmapFromData(display,window,(char *) scope_bits,scope_width,
5406 scope_height);
5407 mask=XCreateBitmapFromData(display,window,(char *) scope_mask_bits,
5408 scope_width,scope_height);
5409 if ((source == (Pixmap) NULL) || (mask == (Pixmap) NULL))
5410 {
5411 ThrowXWindowFatalException(XServerError,"UnableToCreatePixmap","...");
5412 return((Cursor) NULL);
5413 }
5414 (void) XParseColor(display,colormap,background_color,&background);
5415 (void) XParseColor(display,colormap,foreground_color,&foreground);
5416 cursor=XCreatePixmapCursor(display,source,mask,&foreground,&background,
5417 scope_x_hot,scope_y_hot);
5418 (void) XFreePixmap(display,source);
5419 (void) XFreePixmap(display,mask);
5420 return(cursor);
5421}
5422
5423/*
5424%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5425% %
5426% %
5427% %
5428% X M a k e I m a g e %
5429% %
5430% %
5431% %
5432%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5433%
5434% XMakeImage() creates an X11 image. If the image size differs from the X11
5435% image size, the image is first resized.
5436%
5437% The format of the XMakeImage method is:
5438%
5439% MagickBooleanType XMakeImage(Display *display,
5440% const XResourceInfo *resource_info,XWindowInfo *window,Image *image,
cristy051718b2011-08-28 22:49:25 +00005441% unsigned int width,unsigned int height,ExceptionInfo *exception)
cristy3ed852e2009-09-05 21:47:34 +00005442%
5443% A description of each parameter follows:
5444%
5445% o display: Specifies a connection to an X server; returned from
5446% XOpenDisplay.
5447%
5448% o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
5449%
5450% o window: Specifies a pointer to a XWindowInfo structure.
5451%
5452% o image: the image.
5453%
5454% o width: Specifies the width in pixels of the rectangular area to
5455% display.
5456%
5457% o height: Specifies the height in pixels of the rectangular area to
5458% display.
5459%
cristy051718b2011-08-28 22:49:25 +00005460% o exception: return any errors or warnings in this structure.
5461%
cristy3ed852e2009-09-05 21:47:34 +00005462*/
cristybcbda3f2011-09-03 13:01:22 +00005463MagickPrivate MagickBooleanType XMakeImage(Display *display,
cristy3ed852e2009-09-05 21:47:34 +00005464 const XResourceInfo *resource_info,XWindowInfo *window,Image *image,
cristy051718b2011-08-28 22:49:25 +00005465 unsigned int width,unsigned int height,ExceptionInfo *exception)
cristy3ed852e2009-09-05 21:47:34 +00005466{
5467#define CheckOverflowException(length,width,height) \
5468 (((height) != 0) && ((length)/((size_t) height) != ((size_t) width)))
5469
5470 int
5471 depth,
5472 format;
5473
5474 size_t
5475 length;
5476
5477 XImage
5478 *matte_image,
5479 *ximage;
5480
5481 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
5482 assert(display != (Display *) NULL);
5483 assert(resource_info != (XResourceInfo *) NULL);
5484 assert(window != (XWindowInfo *) NULL);
5485 assert(width != 0);
5486 assert(height != 0);
5487 if ((window->width == 0) || (window->height == 0))
5488 return(MagickFalse);
5489 /*
5490 Apply user transforms to the image.
5491 */
5492 (void) XCheckDefineCursor(display,window->id,window->busy_cursor);
5493 (void) XFlush(display);
5494 depth=(int) window->depth;
5495 if (window->destroy)
5496 window->image=DestroyImage(window->image);
5497 window->image=image;
5498 window->destroy=MagickFalse;
5499 if (window->image != (Image *) NULL)
5500 {
5501 if (window->crop_geometry != (char *) NULL)
5502 {
5503 Image
5504 *crop_image;
5505
5506 RectangleInfo
5507 crop_info;
5508
5509 /*
5510 Crop image.
5511 */
5512 window->image->page.x=0;
5513 window->image->page.y=0;
5514 (void) ParsePageGeometry(window->image,window->crop_geometry,
cristy6710d842011-10-20 23:23:00 +00005515 &crop_info,exception);
5516 crop_image=CropImage(window->image,&crop_info,exception);
cristy3ed852e2009-09-05 21:47:34 +00005517 if (crop_image != (Image *) NULL)
5518 {
5519 if (window->image != image)
5520 window->image=DestroyImage(window->image);
5521 window->image=crop_image;
5522 window->destroy=MagickTrue;
5523 }
5524 }
5525 if ((width != (unsigned int) window->image->columns) ||
5526 (height != (unsigned int) window->image->rows))
5527 {
5528 Image
5529 *resize_image;
5530
5531 /*
5532 Resize image.
5533 */
5534 resize_image=NewImageList();
5535 if (window->pixel_info->colors != 0)
cristy6710d842011-10-20 23:23:00 +00005536 resize_image=SampleImage(window->image,width,height,exception);
cristy3ed852e2009-09-05 21:47:34 +00005537 else
cristy6710d842011-10-20 23:23:00 +00005538 resize_image=ThumbnailImage(window->image,width,height,exception);
cristy3ed852e2009-09-05 21:47:34 +00005539 if (resize_image != (Image *) NULL)
5540 {
5541 if (window->image != image)
5542 window->image=DestroyImage(window->image);
5543 window->image=resize_image;
5544 window->destroy=MagickTrue;
5545 }
5546 }
5547 width=(unsigned int) window->image->columns;
cristybb503372010-05-27 20:51:26 +00005548 assert((size_t) width == window->image->columns);
cristy3ed852e2009-09-05 21:47:34 +00005549 height=(unsigned int) window->image->rows;
cristybb503372010-05-27 20:51:26 +00005550 assert((size_t) height == window->image->rows);
cristy3ed852e2009-09-05 21:47:34 +00005551 }
5552 /*
5553 Create X image.
5554 */
5555 ximage=(XImage *) NULL;
5556 format=(depth == 1) ? XYBitmap : ZPixmap;
5557#if defined(MAGICKCORE_HAVE_SHARED_MEMORY)
5558 if (window->shared_memory != MagickFalse)
5559 {
5560 XShmSegmentInfo
5561 *segment_info;
5562
5563 segment_info=(XShmSegmentInfo *) window->segment_info;
5564 segment_info[1].shmid=(-1);
5565 segment_info[1].shmaddr=(char *) NULL;
5566 ximage=XShmCreateImage(display,window->visual,(unsigned int) depth,format,
5567 (char *) NULL,&segment_info[1],width,height);
5568 if (ximage == (XImage *) NULL)
5569 window->shared_memory=MagickFalse;
5570 length=(size_t) ximage->bytes_per_line*ximage->height;
5571 if (CheckOverflowException(length,ximage->bytes_per_line,ximage->height))
5572 window->shared_memory=MagickFalse;
5573 if (window->shared_memory != MagickFalse)
5574 segment_info[1].shmid=shmget(IPC_PRIVATE,length,IPC_CREAT | 0777);
5575 if (window->shared_memory != MagickFalse)
5576 segment_info[1].shmaddr=(char *) shmat(segment_info[1].shmid,0,0);
5577 if (segment_info[1].shmid < 0)
5578 window->shared_memory=MagickFalse;
5579 if (window->shared_memory != MagickFalse)
5580 (void) shmctl(segment_info[1].shmid,IPC_RMID,0);
5581 else
5582 {
5583 if (ximage != (XImage *) NULL)
5584 XDestroyImage(ximage);
5585 ximage=(XImage *) NULL;
5586 if (segment_info[1].shmaddr)
5587 {
5588 (void) shmdt(segment_info[1].shmaddr);
5589 segment_info[1].shmaddr=(char *) NULL;
5590 }
5591 if (segment_info[1].shmid >= 0)
5592 {
5593 (void) shmctl(segment_info[1].shmid,IPC_RMID,0);
5594 segment_info[1].shmid=(-1);
5595 }
5596 }
5597 }
5598#endif
5599 /*
5600 Allocate X image pixel data.
5601 */
5602#if defined(MAGICKCORE_HAVE_SHARED_MEMORY)
5603 if (window->shared_memory)
5604 {
5605 Status
5606 status;
5607
5608 XShmSegmentInfo
5609 *segment_info;
5610
5611 (void) XSync(display,MagickFalse);
5612 xerror_alert=MagickFalse;
5613 segment_info=(XShmSegmentInfo *) window->segment_info;
5614 ximage->data=segment_info[1].shmaddr;
5615 segment_info[1].readOnly=MagickFalse;
5616 status=XShmAttach(display,&segment_info[1]);
5617 if (status != False)
5618 (void) XSync(display,MagickFalse);
5619 if ((status == False) || (xerror_alert != MagickFalse))
5620 {
5621 window->shared_memory=MagickFalse;
5622 if (status != False)
5623 XShmDetach(display,&segment_info[1]);
5624 if (ximage != (XImage *) NULL)
5625 {
5626 ximage->data=NULL;
5627 XDestroyImage(ximage);
5628 ximage=(XImage *) NULL;
5629 }
5630 if (segment_info[1].shmid >= 0)
5631 {
5632 if (segment_info[1].shmaddr != NULL)
5633 (void) shmdt(segment_info[1].shmaddr);
5634 (void) shmctl(segment_info[1].shmid,IPC_RMID,0);
5635 segment_info[1].shmid=(-1);
5636 segment_info[1].shmaddr=(char *) NULL;
5637 }
5638 }
5639 }
5640#endif
5641 if (window->shared_memory == MagickFalse)
5642 ximage=XCreateImage(display,window->visual,(unsigned int) depth,format,0,
5643 (char *) NULL,width,height,XBitmapPad(display),0);
5644 if (ximage == (XImage *) NULL)
5645 {
5646 /*
5647 Unable to create X image.
5648 */
5649 (void) XCheckDefineCursor(display,window->id,window->cursor);
5650 return(MagickFalse);
5651 }
5652 length=(size_t) ximage->bytes_per_line*ximage->height;
5653 if (IsEventLogging())
5654 {
5655 (void) LogMagickEvent(X11Event,GetMagickModule(),"XImage:");
5656 (void) LogMagickEvent(X11Event,GetMagickModule()," width, height: %dx%d",
5657 ximage->width,ximage->height);
5658 (void) LogMagickEvent(X11Event,GetMagickModule()," format: %d",
5659 ximage->format);
5660 (void) LogMagickEvent(X11Event,GetMagickModule()," byte order: %d",
5661 ximage->byte_order);
5662 (void) LogMagickEvent(X11Event,GetMagickModule(),
5663 " bitmap unit, bit order, pad: %d %d %d",ximage->bitmap_unit,
5664 ximage->bitmap_bit_order,ximage->bitmap_pad);
5665 (void) LogMagickEvent(X11Event,GetMagickModule()," depth: %d",
5666 ximage->depth);
5667 (void) LogMagickEvent(X11Event,GetMagickModule()," bytes per line: %d",
5668 ximage->bytes_per_line);
5669 (void) LogMagickEvent(X11Event,GetMagickModule()," bits per pixel: %d",
5670 ximage->bits_per_pixel);
5671 (void) LogMagickEvent(X11Event,GetMagickModule(),
5672 " red, green, blue masks: 0x%lx 0x%lx 0x%lx",ximage->red_mask,
5673 ximage->green_mask,ximage->blue_mask);
5674 }
5675 if (window->shared_memory == MagickFalse)
5676 {
5677 if (ximage->format != XYBitmap)
5678 ximage->data=(char *) AcquireQuantumMemory((size_t)
5679 ximage->bytes_per_line,(size_t) ximage->height);
5680 else
5681 ximage->data=(char *) AcquireQuantumMemory((size_t)
5682 ximage->bytes_per_line*ximage->depth,(size_t) ximage->height);
5683 }
5684 if (ximage->data == (char *) NULL)
5685 {
5686 /*
5687 Unable to allocate pixel data.
5688 */
5689 XDestroyImage(ximage);
5690 ximage=(XImage *) NULL;
5691 (void) XCheckDefineCursor(display,window->id,window->cursor);
5692 return(MagickFalse);
5693 }
5694 if (window->ximage != (XImage *) NULL)
5695 {
5696 /*
5697 Destroy previous X image.
5698 */
5699 length=(size_t) window->ximage->bytes_per_line*window->ximage->height;
5700#if defined(MAGICKCORE_HAVE_SHARED_MEMORY)
5701 if (window->segment_info != (XShmSegmentInfo *) NULL)
5702 {
5703 XShmSegmentInfo
5704 *segment_info;
5705
5706 segment_info=(XShmSegmentInfo *) window->segment_info;
5707 if (segment_info[0].shmid >= 0)
5708 {
5709 (void) XSync(display,MagickFalse);
5710 (void) XShmDetach(display,&segment_info[0]);
5711 (void) XSync(display,MagickFalse);
5712 if (segment_info[0].shmaddr != (char *) NULL)
5713 (void) shmdt(segment_info[0].shmaddr);
5714 (void) shmctl(segment_info[0].shmid,IPC_RMID,0);
5715 segment_info[0].shmid=(-1);
5716 segment_info[0].shmaddr=(char *) NULL;
5717 window->ximage->data=(char *) NULL;
5718 }
5719 }
5720#endif
5721 if (window->ximage->data != (char *) NULL)
5722 free(window->ximage->data);
5723 window->ximage->data=(char *) NULL;
5724 XDestroyImage(window->ximage);
5725 window->ximage=(XImage *) NULL;
5726 }
5727#if defined(MAGICKCORE_HAVE_SHARED_MEMORY)
5728 if (window->segment_info != (XShmSegmentInfo *) NULL)
5729 {
5730 XShmSegmentInfo
5731 *segment_info;
5732
5733 segment_info=(XShmSegmentInfo *) window->segment_info;
5734 segment_info[0]=segment_info[1];
5735 }
5736#endif
5737 window->ximage=ximage;
5738 matte_image=(XImage *) NULL;
5739 if ((window->shape != MagickFalse) && (window->image != (Image *) NULL))
5740 if ((window->image->matte != MagickFalse) &&
cristyc57f6942010-11-12 01:47:39 +00005741 ((int) width <= XDisplayWidth(display,window->screen)) &&
5742 ((int) height <= XDisplayHeight(display,window->screen)))
cristy3ed852e2009-09-05 21:47:34 +00005743 {
5744 /*
5745 Create matte image.
5746 */
5747 matte_image=XCreateImage(display,window->visual,1,XYBitmap,0,
5748 (char *) NULL,width,height,XBitmapPad(display),0);
5749 if (IsEventLogging())
5750 {
5751 (void) LogMagickEvent(X11Event,GetMagickModule(),"Matte Image:");
5752 (void) LogMagickEvent(X11Event,GetMagickModule(),
5753 " width, height: %dx%d",matte_image->width,matte_image->height);
5754 }
5755 if (matte_image != (XImage *) NULL)
5756 {
5757 /*
5758 Allocate matte image pixel data.
5759 */
5760 matte_image->data=(char *) AcquireQuantumMemory((size_t)
5761 matte_image->bytes_per_line*matte_image->depth,
5762 (size_t) matte_image->height);
5763 if (matte_image->data == (char *) NULL)
5764 {
5765 XDestroyImage(matte_image);
5766 matte_image=(XImage *) NULL;
5767 }
5768 }
5769 }
5770 if (window->matte_image != (XImage *) NULL)
5771 {
5772 /*
5773 Free matte image.
5774 */
5775 if (window->matte_image->data != (char *) NULL)
5776 free(window->matte_image->data);
5777 window->matte_image->data=(char *) NULL;
5778 XDestroyImage(window->matte_image);
5779 window->matte_image=(XImage *) NULL;
5780 }
5781 window->matte_image=matte_image;
5782 if (window->matte_pixmap != (Pixmap) NULL)
5783 {
5784 (void) XFreePixmap(display,window->matte_pixmap);
5785 window->matte_pixmap=(Pixmap) NULL;
5786#if defined(MAGICKCORE_HAVE_SHAPE)
5787 if (window->shape != MagickFalse)
5788 XShapeCombineMask(display,window->id,ShapeBounding,0,0,None,ShapeSet);
5789#endif
5790 }
5791 window->stasis=MagickFalse;
5792 /*
5793 Convert pixels to X image data.
5794 */
5795 if (window->image != (Image *) NULL)
5796 {
5797 if ((ximage->byte_order == LSBFirst) || ((ximage->format == XYBitmap) &&
5798 (ximage->bitmap_bit_order == LSBFirst)))
5799 XMakeImageLSBFirst(resource_info,window,window->image,ximage,
cristye941a752011-10-15 01:52:48 +00005800 matte_image,exception);
cristy3ed852e2009-09-05 21:47:34 +00005801 else
5802 XMakeImageMSBFirst(resource_info,window,window->image,ximage,
cristye941a752011-10-15 01:52:48 +00005803 matte_image,exception);
cristy3ed852e2009-09-05 21:47:34 +00005804 }
5805 if (window->matte_image != (XImage *) NULL)
5806 {
5807 /*
5808 Create matte pixmap.
5809 */
5810 window->matte_pixmap=XCreatePixmap(display,window->id,width,height,1);
5811 if (window->matte_pixmap != (Pixmap) NULL)
5812 {
5813 GC
5814 graphics_context;
5815
5816 XGCValues
5817 context_values;
5818
5819 /*
5820 Copy matte image to matte pixmap.
5821 */
cristy4c08aed2011-07-01 19:47:50 +00005822 context_values.background=0;
5823 context_values.foreground=1;
cristy3ed852e2009-09-05 21:47:34 +00005824 graphics_context=XCreateGC(display,window->matte_pixmap,
cristybb503372010-05-27 20:51:26 +00005825 (size_t) (GCBackground | GCForeground),&context_values);
cristy3ed852e2009-09-05 21:47:34 +00005826 (void) XPutImage(display,window->matte_pixmap,graphics_context,
5827 window->matte_image,0,0,0,0,width,height);
5828 (void) XFreeGC(display,graphics_context);
5829#if defined(MAGICKCORE_HAVE_SHAPE)
5830 if (window->shape != MagickFalse)
5831 XShapeCombineMask(display,window->id,ShapeBounding,0,0,
5832 window->matte_pixmap,ShapeSet);
5833#endif
5834 }
5835 }
5836 (void) XMakePixmap(display,resource_info,window);
5837 /*
5838 Restore cursor.
5839 */
5840 (void) XCheckDefineCursor(display,window->id,window->cursor);
5841 return(MagickTrue);
5842}
5843
5844/*
5845%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5846% %
5847% %
5848% %
5849+ X M a k e I m a g e L S B F i r s t %
5850% %
5851% %
5852% %
5853%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5854%
5855% XMakeImageLSBFirst() initializes the pixel data of an X11 Image. The X image
5856% pixels are copied in least-significant bit and byte first order. The
5857% server's scanline pad is respected. Rather than using one or two general
5858% cases, many special cases are found here to help speed up the image
5859% conversion.
5860%
5861% The format of the XMakeImageLSBFirst method is:
5862%
cristye941a752011-10-15 01:52:48 +00005863% void XMakeImageLSBFirst(Display *display,XWindows *windows,
5864% ExceptionInfo *exception)
cristy3ed852e2009-09-05 21:47:34 +00005865%
5866% A description of each parameter follows:
5867%
5868% o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
5869%
5870% o window: Specifies a pointer to a XWindowInfo structure.
5871%
5872% o image: the image.
5873%
5874% o ximage: Specifies a pointer to a XImage structure; returned from
5875% XCreateImage.
5876%
5877% o matte_image: Specifies a pointer to a XImage structure; returned from
5878% XCreateImage.
5879%
cristye941a752011-10-15 01:52:48 +00005880% o exception: return any errors or warnings in this structure.
5881%
cristy3ed852e2009-09-05 21:47:34 +00005882*/
5883static void XMakeImageLSBFirst(const XResourceInfo *resource_info,
cristye941a752011-10-15 01:52:48 +00005884 const XWindowInfo *window,Image *image,XImage *ximage,XImage *matte_image,
5885 ExceptionInfo *exception)
cristy3ed852e2009-09-05 21:47:34 +00005886{
cristyc57f6942010-11-12 01:47:39 +00005887 CacheView
5888 *canvas_view;
5889
cristy3ed852e2009-09-05 21:47:34 +00005890 Image
5891 *canvas;
5892
5893 int
5894 y;
5895
cristy4c08aed2011-07-01 19:47:50 +00005896 register const Quantum
cristy3ed852e2009-09-05 21:47:34 +00005897 *p;
5898
5899 register int
5900 x;
5901
5902 register unsigned char
5903 *q;
5904
5905 unsigned char
5906 bit,
5907 byte;
5908
5909 unsigned int
5910 scanline_pad;
5911
cristyf2faecf2010-05-28 19:19:36 +00005912 unsigned long
cristy3ed852e2009-09-05 21:47:34 +00005913 pixel,
5914 *pixels;
5915
5916 XStandardColormap
5917 *map_info;
5918
5919 assert(resource_info != (XResourceInfo *) NULL);
5920 assert(window != (XWindowInfo *) NULL);
5921 assert(image != (Image *) NULL);
5922 if (image->debug != MagickFalse)
5923 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
5924 canvas=image;
cristybab87c32010-02-09 20:54:22 +00005925 if ((window->immutable == MagickFalse) &&
cristy54666e82010-02-03 23:34:26 +00005926 (image->storage_class == DirectClass) && (image->matte != MagickFalse))
cristy3ed852e2009-09-05 21:47:34 +00005927 {
5928 char
5929 size[MaxTextExtent];
5930
5931 Image
5932 *pattern;
5933
5934 ImageInfo
5935 *image_info;
5936
5937 image_info=AcquireImageInfo();
5938 (void) CopyMagickString(image_info->filename,
5939 resource_info->image_info->texture != (char *) NULL ?
5940 resource_info->image_info->texture : "pattern:checkerboard",
5941 MaxTextExtent);
cristyb51dff52011-05-19 16:55:47 +00005942 (void) FormatLocaleString(size,MaxTextExtent,"%.20gx%.20g",(double)
cristye8c25f92010-06-03 00:53:06 +00005943 image->columns,(double) image->rows);
cristy3ed852e2009-09-05 21:47:34 +00005944 image_info->size=ConstantString(size);
cristy6710d842011-10-20 23:23:00 +00005945 pattern=ReadImage(image_info,exception);
cristy3ed852e2009-09-05 21:47:34 +00005946 image_info=DestroyImageInfo(image_info);
5947 if (pattern != (Image *) NULL)
5948 {
cristy6710d842011-10-20 23:23:00 +00005949 canvas=CloneImage(image,0,0,MagickTrue,exception);
cristy3ed852e2009-09-05 21:47:34 +00005950 if (canvas != (Image *) NULL)
cristye941a752011-10-15 01:52:48 +00005951 (void) CompositeImage(canvas,DstOverCompositeOp,pattern,0,0,
5952 exception);
cristy3ed852e2009-09-05 21:47:34 +00005953 pattern=DestroyImage(pattern);
5954 }
5955 }
5956 scanline_pad=(unsigned int) (ximage->bytes_per_line-((ximage->width*
5957 ximage->bits_per_pixel) >> 3));
5958 map_info=window->map_info;
5959 pixels=window->pixel_info->pixels;
5960 q=(unsigned char *) ximage->data;
5961 x=0;
cristyc57f6942010-11-12 01:47:39 +00005962 canvas_view=AcquireCacheView(canvas);
cristy3ed852e2009-09-05 21:47:34 +00005963 if (ximage->format == XYBitmap)
5964 {
5965 register unsigned short
5966 polarity;
5967
5968 unsigned char
5969 background,
5970 foreground;
5971
5972 /*
5973 Convert canvas to big-endian bitmap.
5974 */
5975 background=(unsigned char)
5976 (XPixelIntensity(&window->pixel_info->foreground_color) <
5977 XPixelIntensity(&window->pixel_info->background_color) ? 0x80 : 0x00);
5978 foreground=(unsigned char)
5979 (XPixelIntensity(&window->pixel_info->background_color) <
5980 XPixelIntensity(&window->pixel_info->foreground_color) ? 0x80 : 0x00);
cristy101ab702011-10-13 13:06:32 +00005981 polarity=(unsigned short) ((GetPixelInfoIntensity(
cristy3ed852e2009-09-05 21:47:34 +00005982 &canvas->colormap[0])) < ((Quantum) QuantumRange/2) ? 1 : 0);
5983 if (canvas->colors == 2)
cristy101ab702011-10-13 13:06:32 +00005984 polarity=GetPixelInfoIntensity(&canvas->colormap[0]) <
5985 GetPixelInfoIntensity(&canvas->colormap[1]);
cristy3ed852e2009-09-05 21:47:34 +00005986 for (y=0; y < (int) canvas->rows; y++)
5987 {
cristyc57f6942010-11-12 01:47:39 +00005988 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,canvas->columns,1,
cristy6710d842011-10-20 23:23:00 +00005989 exception);
cristy4c08aed2011-07-01 19:47:50 +00005990 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00005991 break;
cristy3ed852e2009-09-05 21:47:34 +00005992 bit=0;
5993 byte=0;
5994 for (x=0; x < (int) canvas->columns; x++)
5995 {
5996 byte>>=1;
cristy4c08aed2011-07-01 19:47:50 +00005997 if (GetPixelIndex(canvas,p) == (Quantum) polarity)
cristy3ed852e2009-09-05 21:47:34 +00005998 byte|=foreground;
5999 else
6000 byte|=background;
6001 bit++;
6002 if (bit == 8)
6003 {
6004 *q++=byte;
6005 bit=0;
6006 byte=0;
6007 }
cristyed231572011-07-14 02:18:59 +00006008 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00006009 }
6010 if (bit != 0)
6011 *q=byte >> (8-bit);
6012 q+=scanline_pad;
6013 }
6014 }
6015 else
6016 if (window->pixel_info->colors != 0)
6017 switch (ximage->bits_per_pixel)
6018 {
6019 case 2:
6020 {
6021 register unsigned int
6022 nibble;
6023
6024 /*
6025 Convert to 2 bit color-mapped X canvas.
6026 */
6027 for (y=0; y < (int) canvas->rows; y++)
6028 {
cristyc57f6942010-11-12 01:47:39 +00006029 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
cristy6710d842011-10-20 23:23:00 +00006030 canvas->columns,1,exception);
cristy4c08aed2011-07-01 19:47:50 +00006031 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00006032 break;
cristy3ed852e2009-09-05 21:47:34 +00006033 nibble=0;
6034 for (x=0; x < (int) canvas->columns; x++)
6035 {
cristy4c08aed2011-07-01 19:47:50 +00006036 pixel=pixels[(ssize_t) GetPixelIndex(canvas,p)] & 0x0f;
cristy3ed852e2009-09-05 21:47:34 +00006037 switch (nibble)
6038 {
6039 case 0:
6040 {
6041 *q=(unsigned char) pixel;
6042 nibble++;
6043 break;
6044 }
6045 case 1:
6046 {
6047 *q|=(unsigned char) (pixel << 2);
6048 nibble++;
6049 break;
6050 }
6051 case 2:
6052 {
6053 *q|=(unsigned char) (pixel << 4);
6054 nibble++;
6055 break;
6056 }
6057 case 3:
6058 {
6059 *q|=(unsigned char) (pixel << 6);
6060 q++;
6061 nibble=0;
6062 break;
6063 }
6064 }
cristyed231572011-07-14 02:18:59 +00006065 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00006066 }
6067 q+=scanline_pad;
6068 }
6069 break;
6070 }
6071 case 4:
6072 {
6073 register unsigned int
6074 nibble;
6075
6076 /*
6077 Convert to 4 bit color-mapped X canvas.
6078 */
6079 for (y=0; y < (int) canvas->rows; y++)
6080 {
cristyc57f6942010-11-12 01:47:39 +00006081 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
cristy6710d842011-10-20 23:23:00 +00006082 canvas->columns,1,exception);
cristy4c08aed2011-07-01 19:47:50 +00006083 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00006084 break;
cristy3ed852e2009-09-05 21:47:34 +00006085 nibble=0;
6086 for (x=0; x < (int) canvas->columns; x++)
6087 {
cristy4c08aed2011-07-01 19:47:50 +00006088 pixel=pixels[(ssize_t) GetPixelIndex(canvas,p)] & 0xf;
cristy3ed852e2009-09-05 21:47:34 +00006089 switch (nibble)
6090 {
6091 case 0:
6092 {
6093 *q=(unsigned char) pixel;
6094 nibble++;
6095 break;
6096 }
6097 case 1:
6098 {
6099 *q|=(unsigned char) (pixel << 4);
6100 q++;
6101 nibble=0;
6102 break;
6103 }
6104 }
cristyed231572011-07-14 02:18:59 +00006105 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00006106 }
6107 q+=scanline_pad;
6108 }
6109 break;
6110 }
6111 case 6:
6112 case 8:
6113 {
6114 /*
6115 Convert to 8 bit color-mapped X canvas.
6116 */
6117 if (resource_info->color_recovery &&
6118 resource_info->quantize_info->dither)
6119 {
cristy6710d842011-10-20 23:23:00 +00006120 XDitherImage(canvas,ximage,exception);
cristy3ed852e2009-09-05 21:47:34 +00006121 break;
6122 }
6123 for (y=0; y < (int) canvas->rows; y++)
6124 {
cristyc57f6942010-11-12 01:47:39 +00006125 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
cristy6710d842011-10-20 23:23:00 +00006126 canvas->columns,1,exception);
cristy4c08aed2011-07-01 19:47:50 +00006127 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00006128 break;
cristy3ed852e2009-09-05 21:47:34 +00006129 for (x=0; x < (int) canvas->columns; x++)
6130 {
cristy4c08aed2011-07-01 19:47:50 +00006131 pixel=pixels[(ssize_t) GetPixelIndex(canvas,p)];
cristy3ed852e2009-09-05 21:47:34 +00006132 *q++=(unsigned char) pixel;
cristyed231572011-07-14 02:18:59 +00006133 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00006134 }
6135 q+=scanline_pad;
6136 }
6137 break;
6138 }
6139 default:
6140 {
6141 register int
6142 k;
6143
6144 register unsigned int
6145 bytes_per_pixel;
6146
6147 unsigned char
cristybb503372010-05-27 20:51:26 +00006148 channel[sizeof(size_t)];
cristy3ed852e2009-09-05 21:47:34 +00006149
6150 /*
6151 Convert to multi-byte color-mapped X canvas.
6152 */
6153 bytes_per_pixel=(unsigned int) (ximage->bits_per_pixel >> 3);
6154 for (y=0; y < (int) canvas->rows; y++)
6155 {
cristyc57f6942010-11-12 01:47:39 +00006156 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
cristy6710d842011-10-20 23:23:00 +00006157 canvas->columns,1,exception);
cristy4c08aed2011-07-01 19:47:50 +00006158 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00006159 break;
cristy3ed852e2009-09-05 21:47:34 +00006160 for (x=0; x < (int) canvas->columns; x++)
6161 {
cristy4c08aed2011-07-01 19:47:50 +00006162 pixel=pixels[(ssize_t) GetPixelIndex(canvas,p)];
cristy3ed852e2009-09-05 21:47:34 +00006163 for (k=0; k < (int) bytes_per_pixel; k++)
6164 {
6165 channel[k]=(unsigned char) pixel;
6166 pixel>>=8;
6167 }
6168 for (k=0; k < (int) bytes_per_pixel; k++)
6169 *q++=channel[k];
cristyed231572011-07-14 02:18:59 +00006170 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00006171 }
6172 q+=scanline_pad;
6173 }
6174 break;
6175 }
6176 }
6177 else
6178 switch (ximage->bits_per_pixel)
6179 {
6180 case 2:
6181 {
6182 register unsigned int
6183 nibble;
6184
6185 /*
6186 Convert to contiguous 2 bit continuous-tone X canvas.
6187 */
6188 for (y=0; y < (int) canvas->rows; y++)
6189 {
6190 nibble=0;
cristyc57f6942010-11-12 01:47:39 +00006191 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
cristy6710d842011-10-20 23:23:00 +00006192 canvas->columns,1,exception);
cristy4c08aed2011-07-01 19:47:50 +00006193 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00006194 break;
6195 for (x=0; x < (int) canvas->columns; x++)
6196 {
cristy4c08aed2011-07-01 19:47:50 +00006197 pixel=XGammaPixel(canvas,map_info,p);
cristy3ed852e2009-09-05 21:47:34 +00006198 pixel&=0xf;
6199 switch (nibble)
6200 {
6201 case 0:
6202 {
6203 *q=(unsigned char) pixel;
6204 nibble++;
6205 break;
6206 }
6207 case 1:
6208 {
6209 *q|=(unsigned char) (pixel << 2);
6210 nibble++;
6211 break;
6212 }
6213 case 2:
6214 {
6215 *q|=(unsigned char) (pixel << 4);
6216 nibble++;
6217 break;
6218 }
6219 case 3:
6220 {
6221 *q|=(unsigned char) (pixel << 6);
6222 q++;
6223 nibble=0;
6224 break;
6225 }
6226 }
cristyed231572011-07-14 02:18:59 +00006227 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00006228 }
6229 q+=scanline_pad;
6230 }
6231 break;
6232 }
6233 case 4:
6234 {
6235 register unsigned int
6236 nibble;
6237
6238 /*
6239 Convert to contiguous 4 bit continuous-tone X canvas.
6240 */
6241 for (y=0; y < (int) canvas->rows; y++)
6242 {
cristyc57f6942010-11-12 01:47:39 +00006243 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
cristy6710d842011-10-20 23:23:00 +00006244 canvas->columns,1,exception);
cristy4c08aed2011-07-01 19:47:50 +00006245 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00006246 break;
6247 nibble=0;
6248 for (x=0; x < (int) canvas->columns; x++)
6249 {
cristy4c08aed2011-07-01 19:47:50 +00006250 pixel=XGammaPixel(canvas,map_info,p);
cristy3ed852e2009-09-05 21:47:34 +00006251 pixel&=0xf;
6252 switch (nibble)
6253 {
6254 case 0:
6255 {
6256 *q=(unsigned char) pixel;
6257 nibble++;
6258 break;
6259 }
6260 case 1:
6261 {
6262 *q|=(unsigned char) (pixel << 4);
6263 q++;
6264 nibble=0;
6265 break;
6266 }
6267 }
cristyed231572011-07-14 02:18:59 +00006268 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00006269 }
6270 q+=scanline_pad;
6271 }
6272 break;
6273 }
6274 case 6:
6275 case 8:
6276 {
6277 /*
6278 Convert to contiguous 8 bit continuous-tone X canvas.
6279 */
6280 if (resource_info->color_recovery &&
6281 resource_info->quantize_info->dither)
6282 {
cristy6710d842011-10-20 23:23:00 +00006283 XDitherImage(canvas,ximage,exception);
cristy3ed852e2009-09-05 21:47:34 +00006284 break;
6285 }
6286 for (y=0; y < (int) canvas->rows; y++)
6287 {
cristyc57f6942010-11-12 01:47:39 +00006288 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
cristy6710d842011-10-20 23:23:00 +00006289 canvas->columns,1,exception);
cristy4c08aed2011-07-01 19:47:50 +00006290 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00006291 break;
6292 for (x=0; x < (int) canvas->columns; x++)
6293 {
cristy4c08aed2011-07-01 19:47:50 +00006294 pixel=XGammaPixel(canvas,map_info,p);
cristy3ed852e2009-09-05 21:47:34 +00006295 *q++=(unsigned char) pixel;
cristyed231572011-07-14 02:18:59 +00006296 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00006297 }
6298 q+=scanline_pad;
6299 }
6300 break;
6301 }
6302 default:
6303 {
6304 if ((ximage->bits_per_pixel == 32) && (map_info->red_max == 255) &&
6305 (map_info->green_max == 255) && (map_info->blue_max == 255) &&
6306 (map_info->red_mult == 65536L) && (map_info->green_mult == 256) &&
6307 (map_info->blue_mult == 1))
6308 {
6309 /*
6310 Convert to 32 bit continuous-tone X canvas.
6311 */
6312 for (y=0; y < (int) canvas->rows; y++)
6313 {
cristyc57f6942010-11-12 01:47:39 +00006314 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
cristy6710d842011-10-20 23:23:00 +00006315 canvas->columns,1,exception);
cristy4c08aed2011-07-01 19:47:50 +00006316 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00006317 break;
6318 if ((red_gamma != 1.0) || (green_gamma != 1.0) ||
6319 (blue_gamma != 1.0))
6320 {
6321 /*
6322 Gamma correct canvas.
6323 */
6324 for (x=(int) canvas->columns-1; x >= 0; x--)
6325 {
cristyccf844f2010-02-03 23:28:16 +00006326 *q++=ScaleQuantumToChar(XBlueGamma(
cristy4c08aed2011-07-01 19:47:50 +00006327 GetPixelBlue(canvas,p)));
cristyccf844f2010-02-03 23:28:16 +00006328 *q++=ScaleQuantumToChar(XGreenGamma(
cristy4c08aed2011-07-01 19:47:50 +00006329 GetPixelGreen(canvas,p)));
cristyccf844f2010-02-03 23:28:16 +00006330 *q++=ScaleQuantumToChar(XRedGamma(
cristy4c08aed2011-07-01 19:47:50 +00006331 GetPixelRed(canvas,p)));
cristy3ed852e2009-09-05 21:47:34 +00006332 *q++=0;
cristyed231572011-07-14 02:18:59 +00006333 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00006334 }
6335 continue;
6336 }
6337 for (x=(int) canvas->columns-1; x >= 0; x--)
6338 {
cristy4c08aed2011-07-01 19:47:50 +00006339 *q++=ScaleQuantumToChar((Quantum)
6340 GetPixelBlue(canvas,p));
6341 *q++=ScaleQuantumToChar((Quantum)
6342 GetPixelGreen(canvas,p));
6343 *q++=ScaleQuantumToChar((Quantum)
6344 GetPixelRed(canvas,p));
cristy3ed852e2009-09-05 21:47:34 +00006345 *q++=0;
cristyed231572011-07-14 02:18:59 +00006346 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00006347 }
6348 }
6349 }
6350 else
6351 if ((ximage->bits_per_pixel == 32) && (map_info->red_max == 255) &&
6352 (map_info->green_max == 255) && (map_info->blue_max == 255) &&
6353 (map_info->red_mult == 1) && (map_info->green_mult == 256) &&
6354 (map_info->blue_mult == 65536L))
6355 {
6356 /*
6357 Convert to 32 bit continuous-tone X canvas.
6358 */
6359 for (y=0; y < (int) canvas->rows; y++)
6360 {
cristyc57f6942010-11-12 01:47:39 +00006361 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
cristy6710d842011-10-20 23:23:00 +00006362 canvas->columns,1,exception);
cristy4c08aed2011-07-01 19:47:50 +00006363 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00006364 break;
6365 if ((red_gamma != 1.0) || (green_gamma != 1.0) ||
6366 (blue_gamma != 1.0))
6367 {
6368 /*
6369 Gamma correct canvas.
6370 */
6371 for (x=(int) canvas->columns-1; x >= 0; x--)
6372 {
cristyccf844f2010-02-03 23:28:16 +00006373 *q++=ScaleQuantumToChar(XRedGamma(
cristy4c08aed2011-07-01 19:47:50 +00006374 GetPixelRed(canvas,p)));
cristyccf844f2010-02-03 23:28:16 +00006375 *q++=ScaleQuantumToChar(XGreenGamma(
cristy4c08aed2011-07-01 19:47:50 +00006376 GetPixelGreen(canvas,p)));
cristyccf844f2010-02-03 23:28:16 +00006377 *q++=ScaleQuantumToChar(XBlueGamma(
cristy4c08aed2011-07-01 19:47:50 +00006378 GetPixelBlue(canvas,p)));
cristy3ed852e2009-09-05 21:47:34 +00006379 *q++=0;
cristyed231572011-07-14 02:18:59 +00006380 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00006381 }
6382 continue;
6383 }
6384 for (x=(int) canvas->columns-1; x >= 0; x--)
6385 {
cristyccf844f2010-02-03 23:28:16 +00006386 *q++=ScaleQuantumToChar((Quantum)
cristy4c08aed2011-07-01 19:47:50 +00006387 GetPixelRed(canvas,p));
cristyccf844f2010-02-03 23:28:16 +00006388 *q++=ScaleQuantumToChar((Quantum)
cristy4c08aed2011-07-01 19:47:50 +00006389 GetPixelGreen(canvas,p));
cristyccf844f2010-02-03 23:28:16 +00006390 *q++=ScaleQuantumToChar((Quantum)
cristy4c08aed2011-07-01 19:47:50 +00006391 GetPixelBlue(canvas,p));
cristy3ed852e2009-09-05 21:47:34 +00006392 *q++=0;
cristyed231572011-07-14 02:18:59 +00006393 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00006394 }
6395 }
6396 }
6397 else
6398 {
6399 register int
6400 k;
6401
6402 register unsigned int
6403 bytes_per_pixel;
6404
6405 unsigned char
cristybb503372010-05-27 20:51:26 +00006406 channel[sizeof(size_t)];
cristy3ed852e2009-09-05 21:47:34 +00006407
6408 /*
6409 Convert to multi-byte continuous-tone X canvas.
6410 */
6411 bytes_per_pixel=(unsigned int) (ximage->bits_per_pixel >> 3);
6412 for (y=0; y < (int) canvas->rows; y++)
6413 {
cristyc57f6942010-11-12 01:47:39 +00006414 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
cristy6710d842011-10-20 23:23:00 +00006415 canvas->columns,1,exception);
cristy4c08aed2011-07-01 19:47:50 +00006416 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00006417 break;
cristyc57f6942010-11-12 01:47:39 +00006418 for (x=0; x < (int) canvas->columns; x++)
cristy3ed852e2009-09-05 21:47:34 +00006419 {
cristy4c08aed2011-07-01 19:47:50 +00006420 pixel=XGammaPixel(canvas,map_info,p);
cristy3ed852e2009-09-05 21:47:34 +00006421 for (k=0; k < (int) bytes_per_pixel; k++)
6422 {
6423 channel[k]=(unsigned char) pixel;
6424 pixel>>=8;
6425 }
6426 for (k=0; k < (int) bytes_per_pixel; k++)
6427 *q++=channel[k];
cristyed231572011-07-14 02:18:59 +00006428 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00006429 }
6430 q+=scanline_pad;
6431 }
6432 }
6433 break;
6434 }
6435 }
6436 if (matte_image != (XImage *) NULL)
6437 {
6438 /*
6439 Initialize matte canvas.
6440 */
6441 scanline_pad=(unsigned int) (matte_image->bytes_per_line-
6442 ((matte_image->width*matte_image->bits_per_pixel) >> 3));
6443 q=(unsigned char *) matte_image->data;
6444 for (y=0; y < (int) canvas->rows; y++)
6445 {
cristyc57f6942010-11-12 01:47:39 +00006446 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,canvas->columns,1,
cristy6710d842011-10-20 23:23:00 +00006447 exception);
cristy4c08aed2011-07-01 19:47:50 +00006448 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00006449 break;
6450 bit=0;
6451 byte=0;
6452 for (x=(int) canvas->columns-1; x >= 0; x--)
6453 {
6454 byte>>=1;
cristy4c08aed2011-07-01 19:47:50 +00006455 if (GetPixelAlpha(canvas,p) > (QuantumRange/2))
cristy3ed852e2009-09-05 21:47:34 +00006456 byte|=0x80;
6457 bit++;
6458 if (bit == 8)
6459 {
6460 *q++=byte;
6461 bit=0;
6462 byte=0;
6463 }
cristyed231572011-07-14 02:18:59 +00006464 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00006465 }
6466 if (bit != 0)
6467 *q=byte >> (8-bit);
6468 q+=scanline_pad;
6469 }
6470 }
cristyc57f6942010-11-12 01:47:39 +00006471 canvas_view=DestroyCacheView(canvas_view);
cristy3ed852e2009-09-05 21:47:34 +00006472 if (canvas != image)
6473 canvas=DestroyImage(canvas);
6474}
6475
6476/*
6477%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
6478% %
6479% %
6480% %
6481+ X M a k e I m a g e M S B F i r s t %
6482% %
6483% %
6484% %
6485%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
6486%
6487% XMakeImageMSBFirst() initializes the pixel data of an X11 Image. The X
6488% image pixels are copied in most-significant bit and byte first order. The
6489% server's scanline pad is also respected. Rather than using one or two
6490% general cases, many special cases are found here to help speed up the image
6491% conversion.
6492%
6493% The format of the XMakeImageMSBFirst method is:
6494%
cristye941a752011-10-15 01:52:48 +00006495% XMakeImageMSBFirst(resource_info,window,image,ximage,matte_image,
6496% ExceptionInfo *exception)
cristy3ed852e2009-09-05 21:47:34 +00006497%
6498% A description of each parameter follows:
6499%
6500% o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
6501%
6502% o window: Specifies a pointer to a XWindowInfo structure.
6503%
6504% o image: the image.
6505%
6506% o ximage: Specifies a pointer to a XImage structure; returned from
6507% XCreateImage.
6508%
6509% o matte_image: Specifies a pointer to a XImage structure; returned from
6510% XCreateImage.
6511%
cristye941a752011-10-15 01:52:48 +00006512% o exception: return any errors or warnings in this structure.
6513%
cristy3ed852e2009-09-05 21:47:34 +00006514*/
6515static void XMakeImageMSBFirst(const XResourceInfo *resource_info,
cristye941a752011-10-15 01:52:48 +00006516 const XWindowInfo *window,Image *image,XImage *ximage,XImage *matte_image,
6517 ExceptionInfo *exception)
cristy3ed852e2009-09-05 21:47:34 +00006518{
cristyc57f6942010-11-12 01:47:39 +00006519 CacheView
6520 *canvas_view;
6521
cristy3ed852e2009-09-05 21:47:34 +00006522 Image
6523 *canvas;
6524
6525 int
6526 y;
6527
6528 register int
6529 x;
6530
cristy4c08aed2011-07-01 19:47:50 +00006531 register const Quantum
cristy3ed852e2009-09-05 21:47:34 +00006532 *p;
6533
6534 register unsigned char
6535 *q;
6536
6537 unsigned char
6538 bit,
6539 byte;
6540
6541 unsigned int
6542 scanline_pad;
6543
cristyf2faecf2010-05-28 19:19:36 +00006544 unsigned long
cristy3ed852e2009-09-05 21:47:34 +00006545 pixel,
6546 *pixels;
6547
6548 XStandardColormap
6549 *map_info;
6550
6551 assert(resource_info != (XResourceInfo *) NULL);
6552 assert(window != (XWindowInfo *) NULL);
6553 assert(image != (Image *) NULL);
6554 if (image->debug != MagickFalse)
6555 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
6556 canvas=image;
cristy54666e82010-02-03 23:34:26 +00006557 if ((window->immutable != MagickFalse) &&
6558 (image->storage_class == DirectClass) && (image->matte != MagickFalse))
cristy3ed852e2009-09-05 21:47:34 +00006559 {
6560 char
6561 size[MaxTextExtent];
6562
6563 Image
6564 *pattern;
6565
6566 ImageInfo
6567 *image_info;
6568
6569 image_info=AcquireImageInfo();
6570 (void) CopyMagickString(image_info->filename,
6571 resource_info->image_info->texture != (char *) NULL ?
6572 resource_info->image_info->texture : "pattern:checkerboard",
6573 MaxTextExtent);
cristyb51dff52011-05-19 16:55:47 +00006574 (void) FormatLocaleString(size,MaxTextExtent,"%.20gx%.20g",(double)
cristye8c25f92010-06-03 00:53:06 +00006575 image->columns,(double) image->rows);
cristy3ed852e2009-09-05 21:47:34 +00006576 image_info->size=ConstantString(size);
cristy6710d842011-10-20 23:23:00 +00006577 pattern=ReadImage(image_info,exception);
cristy3ed852e2009-09-05 21:47:34 +00006578 image_info=DestroyImageInfo(image_info);
6579 if (pattern != (Image *) NULL)
6580 {
cristy6710d842011-10-20 23:23:00 +00006581 canvas=CloneImage(image,0,0,MagickTrue,exception);
cristy3ed852e2009-09-05 21:47:34 +00006582 if (canvas != (Image *) NULL)
cristye941a752011-10-15 01:52:48 +00006583 (void) CompositeImage(canvas,DstOverCompositeOp,pattern,0,0,
6584 exception);
cristy3ed852e2009-09-05 21:47:34 +00006585 pattern=DestroyImage(pattern);
6586 }
6587 }
cristy4c08aed2011-07-01 19:47:50 +00006588 scanline_pad=(unsigned int) (ximage->bytes_per_line-((ximage->width*
6589 ximage->bits_per_pixel) >> 3));
cristy3ed852e2009-09-05 21:47:34 +00006590 map_info=window->map_info;
6591 pixels=window->pixel_info->pixels;
6592 q=(unsigned char *) ximage->data;
6593 x=0;
cristyc57f6942010-11-12 01:47:39 +00006594 canvas_view=AcquireCacheView(canvas);
cristy3ed852e2009-09-05 21:47:34 +00006595 if (ximage->format == XYBitmap)
6596 {
6597 register unsigned short
6598 polarity;
6599
6600 unsigned char
6601 background,
6602 foreground;
6603
6604 /*
6605 Convert canvas to big-endian bitmap.
6606 */
6607 background=(unsigned char)
6608 (XPixelIntensity(&window->pixel_info->foreground_color) <
6609 XPixelIntensity(&window->pixel_info->background_color) ? 0x01 : 0x00);
6610 foreground=(unsigned char)
6611 (XPixelIntensity(&window->pixel_info->background_color) <
6612 XPixelIntensity(&window->pixel_info->foreground_color) ? 0x01 : 0x00);
cristy101ab702011-10-13 13:06:32 +00006613 polarity=(unsigned short) ((GetPixelInfoIntensity(
cristy3ed852e2009-09-05 21:47:34 +00006614 &canvas->colormap[0])) < ((Quantum) QuantumRange/2) ? 1 : 0);
6615 if (canvas->colors == 2)
cristy101ab702011-10-13 13:06:32 +00006616 polarity=GetPixelInfoIntensity(&canvas->colormap[0]) <
6617 GetPixelInfoIntensity(&canvas->colormap[1]);
cristy3ed852e2009-09-05 21:47:34 +00006618 for (y=0; y < (int) canvas->rows; y++)
6619 {
cristyc57f6942010-11-12 01:47:39 +00006620 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,canvas->columns,1,
cristy6710d842011-10-20 23:23:00 +00006621 exception);
cristy4c08aed2011-07-01 19:47:50 +00006622 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00006623 break;
cristy3ed852e2009-09-05 21:47:34 +00006624 bit=0;
6625 byte=0;
6626 for (x=(int) canvas->columns-1; x >= 0; x--)
6627 {
6628 byte<<=1;
cristy4c08aed2011-07-01 19:47:50 +00006629 if (GetPixelIndex(canvas,p) == (Quantum) polarity)
cristy3ed852e2009-09-05 21:47:34 +00006630 byte|=foreground;
6631 else
6632 byte|=background;
6633 bit++;
6634 if (bit == 8)
6635 {
6636 *q++=byte;
6637 bit=0;
6638 byte=0;
6639 }
cristyed231572011-07-14 02:18:59 +00006640 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00006641 }
6642 if (bit != 0)
6643 *q=byte << (8-bit);
6644 q+=scanline_pad;
6645 }
6646 }
6647 else
6648 if (window->pixel_info->colors != 0)
6649 switch (ximage->bits_per_pixel)
6650 {
6651 case 2:
6652 {
6653 register unsigned int
6654 nibble;
6655
6656 /*
6657 Convert to 2 bit color-mapped X canvas.
6658 */
6659 for (y=0; y < (int) canvas->rows; y++)
6660 {
cristyc57f6942010-11-12 01:47:39 +00006661 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
cristy6710d842011-10-20 23:23:00 +00006662 canvas->columns,1,exception);
cristy4c08aed2011-07-01 19:47:50 +00006663 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00006664 break;
cristy3ed852e2009-09-05 21:47:34 +00006665 nibble=0;
6666 for (x=0; x < (int) canvas->columns; x++)
6667 {
cristy4c08aed2011-07-01 19:47:50 +00006668 pixel=pixels[(ssize_t)
6669 GetPixelIndex(canvas,p)] & 0xf;
cristy3ed852e2009-09-05 21:47:34 +00006670 switch (nibble)
6671 {
6672 case 0:
6673 {
6674 *q=(unsigned char) (pixel << 6);
6675 nibble++;
6676 break;
6677 }
6678 case 1:
6679 {
6680 *q|=(unsigned char) (pixel << 4);
6681 nibble++;
6682 break;
6683 }
6684 case 2:
6685 {
6686 *q|=(unsigned char) (pixel << 2);
6687 nibble++;
6688 break;
6689 }
6690 case 3:
6691 {
6692 *q|=(unsigned char) pixel;
6693 q++;
6694 nibble=0;
6695 break;
6696 }
6697 }
cristyed231572011-07-14 02:18:59 +00006698 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00006699 }
6700 q+=scanline_pad;
6701 }
6702 break;
6703 }
6704 case 4:
6705 {
6706 register unsigned int
6707 nibble;
6708
6709 /*
6710 Convert to 4 bit color-mapped X canvas.
6711 */
6712 for (y=0; y < (int) canvas->rows; y++)
6713 {
cristyc57f6942010-11-12 01:47:39 +00006714 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
cristy6710d842011-10-20 23:23:00 +00006715 canvas->columns,1,exception);
cristy4c08aed2011-07-01 19:47:50 +00006716 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00006717 break;
cristy3ed852e2009-09-05 21:47:34 +00006718 nibble=0;
6719 for (x=0; x < (int) canvas->columns; x++)
6720 {
cristy4c08aed2011-07-01 19:47:50 +00006721 pixel=pixels[(ssize_t)
6722 GetPixelIndex(canvas,p)] & 0xf;
cristy3ed852e2009-09-05 21:47:34 +00006723 switch (nibble)
6724 {
6725 case 0:
6726 {
6727 *q=(unsigned char) (pixel << 4);
6728 nibble++;
6729 break;
6730 }
6731 case 1:
6732 {
6733 *q|=(unsigned char) pixel;
6734 q++;
6735 nibble=0;
6736 break;
6737 }
6738 }
cristyed231572011-07-14 02:18:59 +00006739 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00006740 }
6741 q+=scanline_pad;
6742 }
6743 break;
6744 }
6745 case 6:
6746 case 8:
6747 {
6748 /*
6749 Convert to 8 bit color-mapped X canvas.
6750 */
6751 if (resource_info->color_recovery &&
6752 resource_info->quantize_info->dither)
6753 {
cristy6710d842011-10-20 23:23:00 +00006754 XDitherImage(canvas,ximage,exception);
cristy3ed852e2009-09-05 21:47:34 +00006755 break;
6756 }
6757 for (y=0; y < (int) canvas->rows; y++)
6758 {
cristyc57f6942010-11-12 01:47:39 +00006759 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
cristy6710d842011-10-20 23:23:00 +00006760 canvas->columns,1,exception);
cristy4c08aed2011-07-01 19:47:50 +00006761 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00006762 break;
cristy3ed852e2009-09-05 21:47:34 +00006763 for (x=0; x < (int) canvas->columns; x++)
6764 {
cristy6710d842011-10-20 23:23:00 +00006765 pixel=pixels[(ssize_t) GetPixelIndex(canvas,p)];
cristy3ed852e2009-09-05 21:47:34 +00006766 *q++=(unsigned char) pixel;
cristyed231572011-07-14 02:18:59 +00006767 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00006768 }
6769 q+=scanline_pad;
6770 }
6771 break;
6772 }
6773 default:
6774 {
6775 register int
6776 k;
6777
6778 register unsigned int
6779 bytes_per_pixel;
6780
6781 unsigned char
cristybb503372010-05-27 20:51:26 +00006782 channel[sizeof(size_t)];
cristy3ed852e2009-09-05 21:47:34 +00006783
6784 /*
6785 Convert to 8 bit color-mapped X canvas.
6786 */
6787 bytes_per_pixel=(unsigned int) (ximage->bits_per_pixel >> 3);
6788 for (y=0; y < (int) canvas->rows; y++)
6789 {
cristyc57f6942010-11-12 01:47:39 +00006790 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
cristy6710d842011-10-20 23:23:00 +00006791 canvas->columns,1,exception);
cristy4c08aed2011-07-01 19:47:50 +00006792 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00006793 break;
cristy3ed852e2009-09-05 21:47:34 +00006794 for (x=0; x < (int) canvas->columns; x++)
6795 {
cristy4c08aed2011-07-01 19:47:50 +00006796 pixel=pixels[(ssize_t)
6797 GetPixelIndex(canvas,p)];
cristy3ed852e2009-09-05 21:47:34 +00006798 for (k=(int) bytes_per_pixel-1; k >= 0; k--)
6799 {
6800 channel[k]=(unsigned char) pixel;
6801 pixel>>=8;
6802 }
6803 for (k=0; k < (int) bytes_per_pixel; k++)
6804 *q++=channel[k];
cristyed231572011-07-14 02:18:59 +00006805 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00006806 }
6807 q+=scanline_pad;
6808 }
6809 break;
6810 }
6811 }
6812 else
6813 switch (ximage->bits_per_pixel)
6814 {
6815 case 2:
6816 {
6817 register unsigned int
6818 nibble;
6819
6820 /*
6821 Convert to 4 bit continuous-tone X canvas.
6822 */
6823 for (y=0; y < (int) canvas->rows; y++)
6824 {
cristyc57f6942010-11-12 01:47:39 +00006825 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
cristy6710d842011-10-20 23:23:00 +00006826 canvas->columns,1,exception);
cristy4c08aed2011-07-01 19:47:50 +00006827 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00006828 break;
6829 nibble=0;
6830 for (x=(int) canvas->columns-1; x >= 0; x--)
6831 {
cristy4c08aed2011-07-01 19:47:50 +00006832 pixel=XGammaPixel(canvas,map_info,p);
cristy3ed852e2009-09-05 21:47:34 +00006833 pixel&=0xf;
6834 switch (nibble)
6835 {
6836 case 0:
6837 {
6838 *q=(unsigned char) (pixel << 6);
6839 nibble++;
6840 break;
6841 }
6842 case 1:
6843 {
6844 *q|=(unsigned char) (pixel << 4);
6845 nibble++;
6846 break;
6847 }
6848 case 2:
6849 {
6850 *q|=(unsigned char) (pixel << 2);
6851 nibble++;
6852 break;
6853 }
6854 case 3:
6855 {
6856 *q|=(unsigned char) pixel;
6857 q++;
6858 nibble=0;
6859 break;
6860 }
6861 }
cristyed231572011-07-14 02:18:59 +00006862 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00006863 }
6864 q+=scanline_pad;
6865 }
6866 break;
6867 }
6868 case 4:
6869 {
6870 register unsigned int
6871 nibble;
6872
6873 /*
6874 Convert to 4 bit continuous-tone X canvas.
6875 */
6876 for (y=0; y < (int) canvas->rows; y++)
6877 {
cristyc57f6942010-11-12 01:47:39 +00006878 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
cristy6710d842011-10-20 23:23:00 +00006879 canvas->columns,1,exception);
cristy4c08aed2011-07-01 19:47:50 +00006880 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00006881 break;
6882 nibble=0;
6883 for (x=(int) canvas->columns-1; x >= 0; x--)
6884 {
cristy4c08aed2011-07-01 19:47:50 +00006885 pixel=XGammaPixel(canvas,map_info,p);
cristy3ed852e2009-09-05 21:47:34 +00006886 pixel&=0xf;
6887 switch (nibble)
6888 {
6889 case 0:
6890 {
6891 *q=(unsigned char) (pixel << 4);
6892 nibble++;
6893 break;
6894 }
6895 case 1:
6896 {
6897 *q|=(unsigned char) pixel;
6898 q++;
6899 nibble=0;
6900 break;
6901 }
6902 }
cristyed231572011-07-14 02:18:59 +00006903 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00006904 }
6905 q+=scanline_pad;
6906 }
6907 break;
6908 }
6909 case 6:
6910 case 8:
6911 {
6912 /*
6913 Convert to 8 bit continuous-tone X canvas.
6914 */
6915 if (resource_info->color_recovery &&
6916 resource_info->quantize_info->dither)
6917 {
cristy6710d842011-10-20 23:23:00 +00006918 XDitherImage(canvas,ximage,exception);
cristy3ed852e2009-09-05 21:47:34 +00006919 break;
6920 }
6921 for (y=0; y < (int) canvas->rows; y++)
6922 {
cristyc57f6942010-11-12 01:47:39 +00006923 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
cristy6710d842011-10-20 23:23:00 +00006924 canvas->columns,1,exception);
cristy4c08aed2011-07-01 19:47:50 +00006925 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00006926 break;
6927 for (x=(int) canvas->columns-1; x >= 0; x--)
6928 {
cristy4c08aed2011-07-01 19:47:50 +00006929 pixel=XGammaPixel(canvas,map_info,p);
cristy3ed852e2009-09-05 21:47:34 +00006930 *q++=(unsigned char) pixel;
cristyed231572011-07-14 02:18:59 +00006931 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00006932 }
6933 q+=scanline_pad;
6934 }
6935 break;
6936 }
6937 default:
6938 {
6939 if ((ximage->bits_per_pixel == 32) && (map_info->red_max == 255) &&
6940 (map_info->green_max == 255) && (map_info->blue_max == 255) &&
6941 (map_info->red_mult == 65536L) && (map_info->green_mult == 256) &&
6942 (map_info->blue_mult == 1))
6943 {
6944 /*
6945 Convert to 32 bit continuous-tone X canvas.
6946 */
6947 for (y=0; y < (int) canvas->rows; y++)
6948 {
cristyc57f6942010-11-12 01:47:39 +00006949 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
cristy6710d842011-10-20 23:23:00 +00006950 canvas->columns,1,exception);
cristy4c08aed2011-07-01 19:47:50 +00006951 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00006952 break;
6953 if ((red_gamma != 1.0) || (green_gamma != 1.0) ||
6954 (blue_gamma != 1.0))
6955 {
6956 /*
6957 Gamma correct canvas.
6958 */
6959 for (x=(int) canvas->columns-1; x >= 0; x--)
6960 {
6961 *q++=0;
cristyccf844f2010-02-03 23:28:16 +00006962 *q++=ScaleQuantumToChar(XRedGamma(
cristy4c08aed2011-07-01 19:47:50 +00006963 GetPixelRed(canvas,p)));
cristyccf844f2010-02-03 23:28:16 +00006964 *q++=ScaleQuantumToChar(XGreenGamma(
cristy4c08aed2011-07-01 19:47:50 +00006965 GetPixelGreen(canvas,p)));
cristyccf844f2010-02-03 23:28:16 +00006966 *q++=ScaleQuantumToChar(XBlueGamma(
cristy4c08aed2011-07-01 19:47:50 +00006967 GetPixelBlue(canvas,p)));
cristyed231572011-07-14 02:18:59 +00006968 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00006969 }
6970 continue;
6971 }
6972 for (x=(int) canvas->columns-1; x >= 0; x--)
6973 {
6974 *q++=0;
cristy4c08aed2011-07-01 19:47:50 +00006975 *q++=ScaleQuantumToChar((Quantum)
6976 GetPixelRed(canvas,p));
6977 *q++=ScaleQuantumToChar((Quantum)
6978 GetPixelGreen(canvas,p));
6979 *q++=ScaleQuantumToChar((Quantum)
6980 GetPixelBlue(canvas,p));
cristyed231572011-07-14 02:18:59 +00006981 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00006982 }
6983 }
6984 }
6985 else
6986 if ((ximage->bits_per_pixel == 32) && (map_info->red_max == 255) &&
6987 (map_info->green_max == 255) && (map_info->blue_max == 255) &&
6988 (map_info->red_mult == 1) && (map_info->green_mult == 256) &&
6989 (map_info->blue_mult == 65536L))
6990 {
6991 /*
6992 Convert to 32 bit continuous-tone X canvas.
6993 */
6994 for (y=0; y < (int) canvas->rows; y++)
6995 {
cristyc57f6942010-11-12 01:47:39 +00006996 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
cristy6710d842011-10-20 23:23:00 +00006997 canvas->columns,1,exception);
cristy4c08aed2011-07-01 19:47:50 +00006998 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00006999 break;
7000 if ((red_gamma != 1.0) || (green_gamma != 1.0) ||
7001 (blue_gamma != 1.0))
7002 {
7003 /*
7004 Gamma correct canvas.
7005 */
7006 for (x=(int) canvas->columns-1; x >= 0; x--)
7007 {
7008 *q++=0;
cristyccf844f2010-02-03 23:28:16 +00007009 *q++=ScaleQuantumToChar(XBlueGamma(
cristy4c08aed2011-07-01 19:47:50 +00007010 GetPixelBlue(canvas,p)));
cristyccf844f2010-02-03 23:28:16 +00007011 *q++=ScaleQuantumToChar(XGreenGamma(
cristy4c08aed2011-07-01 19:47:50 +00007012 GetPixelGreen(canvas,p)));
cristyccf844f2010-02-03 23:28:16 +00007013 *q++=ScaleQuantumToChar(XRedGamma(
cristy4c08aed2011-07-01 19:47:50 +00007014 GetPixelRed(canvas,p)));
cristyed231572011-07-14 02:18:59 +00007015 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00007016 }
7017 continue;
7018 }
7019 for (x=(int) canvas->columns-1; x >= 0; x--)
7020 {
7021 *q++=0;
cristyccf844f2010-02-03 23:28:16 +00007022 *q++=ScaleQuantumToChar((Quantum)
cristy4c08aed2011-07-01 19:47:50 +00007023 GetPixelBlue(canvas,p));
cristyccf844f2010-02-03 23:28:16 +00007024 *q++=ScaleQuantumToChar((Quantum)
cristy4c08aed2011-07-01 19:47:50 +00007025 GetPixelGreen(canvas,p));
cristyccf844f2010-02-03 23:28:16 +00007026 *q++=ScaleQuantumToChar((Quantum)
cristy4c08aed2011-07-01 19:47:50 +00007027 GetPixelRed(canvas,p));
cristyed231572011-07-14 02:18:59 +00007028 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00007029 }
7030 }
7031 }
7032 else
7033 {
7034 register int
7035 k;
7036
7037 register unsigned int
7038 bytes_per_pixel;
7039
7040 unsigned char
cristybb503372010-05-27 20:51:26 +00007041 channel[sizeof(size_t)];
cristy3ed852e2009-09-05 21:47:34 +00007042
7043 /*
7044 Convert to multi-byte continuous-tone X canvas.
7045 */
7046 bytes_per_pixel=(unsigned int) (ximage->bits_per_pixel >> 3);
7047 for (y=0; y < (int) canvas->rows; y++)
7048 {
cristyc57f6942010-11-12 01:47:39 +00007049 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
cristy6710d842011-10-20 23:23:00 +00007050 canvas->columns,1,exception);
cristy4c08aed2011-07-01 19:47:50 +00007051 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00007052 break;
7053 for (x=(int) canvas->columns-1; x >= 0; x--)
7054 {
cristy4c08aed2011-07-01 19:47:50 +00007055 pixel=XGammaPixel(canvas,map_info,p);
cristy3ed852e2009-09-05 21:47:34 +00007056 for (k=(int) bytes_per_pixel-1; k >= 0; k--)
7057 {
7058 channel[k]=(unsigned char) pixel;
7059 pixel>>=8;
7060 }
7061 for (k=0; k < (int) bytes_per_pixel; k++)
7062 *q++=channel[k];
cristyed231572011-07-14 02:18:59 +00007063 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00007064 }
7065 q+=scanline_pad;
7066 }
7067 }
7068 break;
7069 }
7070 }
7071 if (matte_image != (XImage *) NULL)
7072 {
7073 /*
7074 Initialize matte canvas.
7075 */
7076 scanline_pad=(unsigned int) (matte_image->bytes_per_line-
7077 ((matte_image->width*matte_image->bits_per_pixel) >> 3));
7078 q=(unsigned char *) matte_image->data;
7079 for (y=0; y < (int) canvas->rows; y++)
7080 {
cristyc57f6942010-11-12 01:47:39 +00007081 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,canvas->columns,1,
cristy6710d842011-10-20 23:23:00 +00007082 exception);
cristy4c08aed2011-07-01 19:47:50 +00007083 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00007084 break;
7085 bit=0;
7086 byte=0;
7087 for (x=(int) canvas->columns-1; x >= 0; x--)
7088 {
7089 byte<<=1;
cristy4c08aed2011-07-01 19:47:50 +00007090 if (GetPixelAlpha(canvas,p) > (QuantumRange/2))
cristy3ed852e2009-09-05 21:47:34 +00007091 byte|=0x01;
7092 bit++;
7093 if (bit == 8)
7094 {
7095 *q++=byte;
7096 bit=0;
7097 byte=0;
7098 }
cristyed231572011-07-14 02:18:59 +00007099 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00007100 }
7101 if (bit != 0)
7102 *q=byte << (8-bit);
7103 q+=scanline_pad;
7104 }
7105 }
cristyc57f6942010-11-12 01:47:39 +00007106 canvas_view=DestroyCacheView(canvas_view);
cristy3ed852e2009-09-05 21:47:34 +00007107 if (canvas != image)
7108 canvas=DestroyImage(canvas);
7109}
7110
7111/*
7112%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
7113% %
7114% %
7115% %
7116% X M a k e M a g n i f y I m a g e %
7117% %
7118% %
7119% %
7120%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
7121%
7122% XMakeMagnifyImage() magnifies a region of an X image and displays it.
7123%
7124% The format of the XMakeMagnifyImage method is:
7125%
cristy6710d842011-10-20 23:23:00 +00007126% void XMakeMagnifyImage(Display *display,XWindows *windows,
7127% ExceptionInfo *exception)
cristy3ed852e2009-09-05 21:47:34 +00007128%
7129% A description of each parameter follows:
7130%
7131% o display: Specifies a connection to an X server; returned from
7132% XOpenDisplay.
7133%
7134% o windows: Specifies a pointer to a XWindows structure.
7135%
cristy6710d842011-10-20 23:23:00 +00007136% o exception: return any errors or warnings in this structure.
7137%
cristy3ed852e2009-09-05 21:47:34 +00007138*/
cristy6710d842011-10-20 23:23:00 +00007139MagickPrivate void XMakeMagnifyImage(Display *display,XWindows *windows,
7140 ExceptionInfo *exception)
cristy3ed852e2009-09-05 21:47:34 +00007141{
7142 char
7143 tuple[MaxTextExtent];
7144
7145 int
7146 y;
7147
cristy4c08aed2011-07-01 19:47:50 +00007148 PixelInfo
cristy3ed852e2009-09-05 21:47:34 +00007149 pixel;
7150
7151 register int
7152 x;
7153
cristybb503372010-05-27 20:51:26 +00007154 register ssize_t
cristy3ed852e2009-09-05 21:47:34 +00007155 i;
7156
7157 register unsigned char
7158 *p,
7159 *q;
7160
cristy9d314ff2011-03-09 01:30:28 +00007161 ssize_t
7162 n;
7163
cristy3ed852e2009-09-05 21:47:34 +00007164 static unsigned int
7165 previous_magnify = 0;
7166
7167 static XWindowInfo
7168 magnify_window;
7169
7170 unsigned int
7171 height,
7172 j,
7173 k,
7174 l,
7175 magnify,
7176 scanline_pad,
7177 width;
7178
7179 XImage
7180 *ximage;
7181
7182 /*
7183 Check boundary conditions.
7184 */
7185 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
7186 assert(display != (Display *) NULL);
7187 assert(windows != (XWindows *) NULL);
7188 magnify=1;
cristybb503372010-05-27 20:51:26 +00007189 for (n=1; n < (ssize_t) windows->magnify.data; n++)
cristy3ed852e2009-09-05 21:47:34 +00007190 magnify<<=1;
7191 while ((magnify*windows->image.ximage->width) < windows->magnify.width)
7192 magnify<<=1;
7193 while ((magnify*windows->image.ximage->height) < windows->magnify.height)
7194 magnify<<=1;
7195 while (magnify > windows->magnify.width)
7196 magnify>>=1;
7197 while (magnify > windows->magnify.height)
7198 magnify>>=1;
7199 if (magnify != previous_magnify)
7200 {
7201 Status
7202 status;
7203
7204 XTextProperty
7205 window_name;
7206
7207 /*
7208 New magnify factor: update magnify window name.
7209 */
7210 i=0;
7211 while ((1 << i) <= (int) magnify)
7212 i++;
cristyb51dff52011-05-19 16:55:47 +00007213 (void) FormatLocaleString(windows->magnify.name,MaxTextExtent,
cristye8c25f92010-06-03 00:53:06 +00007214 "Magnify %.20gX",(double) i);
cristy3ed852e2009-09-05 21:47:34 +00007215 status=XStringListToTextProperty(&windows->magnify.name,1,&window_name);
7216 if (status != False)
7217 {
7218 XSetWMName(display,windows->magnify.id,&window_name);
7219 XSetWMIconName(display,windows->magnify.id,&window_name);
7220 (void) XFree((void *) window_name.value);
7221 }
7222 }
7223 previous_magnify=magnify;
7224 ximage=windows->image.ximage;
7225 width=(unsigned int) windows->magnify.ximage->width;
7226 height=(unsigned int) windows->magnify.ximage->height;
7227 if ((windows->magnify.x < 0) ||
7228 (windows->magnify.x >= windows->image.ximage->width))
7229 windows->magnify.x=windows->image.ximage->width >> 1;
7230 x=windows->magnify.x-((width/magnify) >> 1);
7231 if (x < 0)
7232 x=0;
7233 else
7234 if (x > (int) (ximage->width-(width/magnify)))
7235 x=ximage->width-width/magnify;
7236 if ((windows->magnify.y < 0) ||
7237 (windows->magnify.y >= windows->image.ximage->height))
7238 windows->magnify.y=windows->image.ximage->height >> 1;
7239 y=windows->magnify.y-((height/magnify) >> 1);
7240 if (y < 0)
7241 y=0;
7242 else
7243 if (y > (int) (ximage->height-(height/magnify)))
7244 y=ximage->height-height/magnify;
7245 q=(unsigned char *) windows->magnify.ximage->data;
7246 scanline_pad=(unsigned int) (windows->magnify.ximage->bytes_per_line-
7247 ((width*windows->magnify.ximage->bits_per_pixel) >> 3));
7248 if (ximage->bits_per_pixel < 8)
7249 {
7250 register unsigned char
7251 background,
7252 byte,
7253 foreground,
7254 p_bit,
7255 q_bit;
7256
7257 register unsigned int
7258 plane;
7259
7260 XPixelInfo
7261 *pixel_info;
7262
7263 pixel_info=windows->magnify.pixel_info;
7264 switch (ximage->bitmap_bit_order)
7265 {
7266 case LSBFirst:
7267 {
7268 /*
7269 Magnify little-endian bitmap.
7270 */
7271 background=0x00;
7272 foreground=0x80;
7273 if (ximage->format == XYBitmap)
7274 {
7275 background=(unsigned char)
7276 (XPixelIntensity(&pixel_info->foreground_color) <
7277 XPixelIntensity(&pixel_info->background_color) ? 0x80 : 0x00);
7278 foreground=(unsigned char)
7279 (XPixelIntensity(&pixel_info->background_color) <
7280 XPixelIntensity(&pixel_info->foreground_color) ? 0x80 : 0x00);
7281 if (windows->magnify.depth > 1)
7282 Swap(background,foreground);
7283 }
cristybb503372010-05-27 20:51:26 +00007284 for (i=0; i < (ssize_t) height; i+=magnify)
cristy3ed852e2009-09-05 21:47:34 +00007285 {
7286 /*
7287 Propogate pixel magnify rows.
7288 */
7289 for (j=0; j < magnify; j++)
7290 {
7291 p=(unsigned char *) ximage->data+y*ximage->bytes_per_line+
7292 ((x*ximage->bits_per_pixel) >> 3);
7293 p_bit=(unsigned char) (x*ximage->bits_per_pixel) & 0x07;
7294 q_bit=0;
7295 byte=0;
7296 for (k=0; k < width; k+=magnify)
7297 {
7298 /*
7299 Propogate pixel magnify columns.
7300 */
7301 for (l=0; l < magnify; l++)
7302 {
7303 /*
7304 Propogate each bit plane.
7305 */
7306 for (plane=0; (int) plane < ximage->bits_per_pixel; plane++)
7307 {
7308 byte>>=1;
7309 if (*p & (0x01 << (p_bit+plane)))
7310 byte|=foreground;
7311 else
7312 byte|=background;
7313 q_bit++;
7314 if (q_bit == 8)
7315 {
7316 *q++=byte;
7317 q_bit=0;
7318 byte=0;
7319 }
7320 }
7321 }
7322 p_bit+=ximage->bits_per_pixel;
7323 if (p_bit == 8)
7324 {
7325 p++;
7326 p_bit=0;
7327 }
7328 if (q_bit != 0)
7329 *q=byte >> (8-q_bit);
7330 q+=scanline_pad;
7331 }
7332 }
7333 y++;
7334 }
7335 break;
7336 }
7337 case MSBFirst:
7338 default:
7339 {
7340 /*
7341 Magnify big-endian bitmap.
7342 */
7343 background=0x00;
7344 foreground=0x01;
7345 if (ximage->format == XYBitmap)
7346 {
7347 background=(unsigned char)
7348 (XPixelIntensity(&pixel_info->foreground_color) <
7349 XPixelIntensity(&pixel_info->background_color) ? 0x01 : 0x00);
7350 foreground=(unsigned char)
7351 (XPixelIntensity(&pixel_info->background_color) <
7352 XPixelIntensity(&pixel_info->foreground_color) ? 0x01 : 0x00);
7353 if (windows->magnify.depth > 1)
7354 Swap(background,foreground);
7355 }
cristybb503372010-05-27 20:51:26 +00007356 for (i=0; i < (ssize_t) height; i+=magnify)
cristy3ed852e2009-09-05 21:47:34 +00007357 {
7358 /*
7359 Propogate pixel magnify rows.
7360 */
7361 for (j=0; j < magnify; j++)
7362 {
7363 p=(unsigned char *) ximage->data+y*ximage->bytes_per_line+
7364 ((x*ximage->bits_per_pixel) >> 3);
7365 p_bit=(unsigned char) (x*ximage->bits_per_pixel) & 0x07;
7366 q_bit=0;
7367 byte=0;
7368 for (k=0; k < width; k+=magnify)
7369 {
7370 /*
7371 Propogate pixel magnify columns.
7372 */
7373 for (l=0; l < magnify; l++)
7374 {
7375 /*
7376 Propogate each bit plane.
7377 */
7378 for (plane=0; (int) plane < ximage->bits_per_pixel; plane++)
7379 {
7380 byte<<=1;
7381 if (*p & (0x80 >> (p_bit+plane)))
7382 byte|=foreground;
7383 else
7384 byte|=background;
7385 q_bit++;
7386 if (q_bit == 8)
7387 {
7388 *q++=byte;
7389 q_bit=0;
7390 byte=0;
7391 }
7392 }
7393 }
7394 p_bit+=ximage->bits_per_pixel;
7395 if (p_bit == 8)
7396 {
7397 p++;
7398 p_bit=0;
7399 }
7400 if (q_bit != 0)
7401 *q=byte << (8-q_bit);
7402 q+=scanline_pad;
7403 }
7404 }
7405 y++;
7406 }
7407 break;
7408 }
7409 }
7410 }
7411 else
7412 switch (ximage->bits_per_pixel)
7413 {
7414 case 6:
7415 case 8:
7416 {
7417 /*
7418 Magnify 8 bit X image.
7419 */
cristybb503372010-05-27 20:51:26 +00007420 for (i=0; i < (ssize_t) height; i+=magnify)
cristy3ed852e2009-09-05 21:47:34 +00007421 {
7422 /*
7423 Propogate pixel magnify rows.
7424 */
7425 for (j=0; j < magnify; j++)
7426 {
7427 p=(unsigned char *) ximage->data+y*ximage->bytes_per_line+
7428 ((x*ximage->bits_per_pixel) >> 3);
7429 for (k=0; k < width; k+=magnify)
7430 {
7431 /*
7432 Propogate pixel magnify columns.
7433 */
7434 for (l=0; l < magnify; l++)
7435 *q++=(*p);
7436 p++;
7437 }
7438 q+=scanline_pad;
7439 }
7440 y++;
7441 }
7442 break;
7443 }
7444 default:
7445 {
7446 register unsigned int
7447 bytes_per_pixel,
7448 m;
7449
7450 /*
7451 Magnify multi-byte X image.
7452 */
7453 bytes_per_pixel=(unsigned int) ximage->bits_per_pixel >> 3;
cristybb503372010-05-27 20:51:26 +00007454 for (i=0; i < (ssize_t) height; i+=magnify)
cristy3ed852e2009-09-05 21:47:34 +00007455 {
7456 /*
7457 Propogate pixel magnify rows.
7458 */
7459 for (j=0; j < magnify; j++)
7460 {
7461 p=(unsigned char *) ximage->data+y*ximage->bytes_per_line+
7462 ((x*ximage->bits_per_pixel) >> 3);
7463 for (k=0; k < width; k+=magnify)
7464 {
7465 /*
7466 Propogate pixel magnify columns.
7467 */
7468 for (l=0; l < magnify; l++)
7469 for (m=0; m < bytes_per_pixel; m++)
7470 *q++=(*(p+m));
7471 p+=bytes_per_pixel;
7472 }
7473 q+=scanline_pad;
7474 }
7475 y++;
7476 }
7477 break;
7478 }
7479 }
7480 /*
7481 Copy X image to magnify pixmap.
7482 */
7483 x=windows->magnify.x-((width/magnify) >> 1);
7484 if (x < 0)
7485 x=(int) ((width >> 1)-windows->magnify.x*magnify);
7486 else
7487 if (x > (int) (ximage->width-(width/magnify)))
7488 x=(int) ((ximage->width-windows->magnify.x)*magnify-(width >> 1));
7489 else
7490 x=0;
7491 y=windows->magnify.y-((height/magnify) >> 1);
7492 if (y < 0)
7493 y=(int) ((height >> 1)-windows->magnify.y*magnify);
7494 else
7495 if (y > (int) (ximage->height-(height/magnify)))
7496 y=(int) ((ximage->height-windows->magnify.y)*magnify-(height >> 1));
7497 else
7498 y=0;
7499 if ((x != 0) || (y != 0))
7500 (void) XFillRectangle(display,windows->magnify.pixmap,
7501 windows->magnify.annotate_context,0,0,width,height);
7502 (void) XPutImage(display,windows->magnify.pixmap,
7503 windows->magnify.annotate_context,windows->magnify.ximage,0,0,x,y,width-x,
7504 height-y);
7505 if ((magnify > 1) && ((magnify <= (width >> 1)) &&
7506 (magnify <= (height >> 1))))
7507 {
7508 RectangleInfo
7509 highlight_info;
7510
7511 /*
7512 Highlight center pixel.
7513 */
cristybb503372010-05-27 20:51:26 +00007514 highlight_info.x=(ssize_t) windows->magnify.width >> 1;
7515 highlight_info.y=(ssize_t) windows->magnify.height >> 1;
cristy3ed852e2009-09-05 21:47:34 +00007516 highlight_info.width=magnify;
7517 highlight_info.height=magnify;
7518 (void) XDrawRectangle(display,windows->magnify.pixmap,
7519 windows->magnify.highlight_context,(int) highlight_info.x,
7520 (int) highlight_info.y,(unsigned int) highlight_info.width-1,
7521 (unsigned int) highlight_info.height-1);
7522 if (magnify > 2)
7523 (void) XDrawRectangle(display,windows->magnify.pixmap,
7524 windows->magnify.annotate_context,(int) highlight_info.x+1,
7525 (int) highlight_info.y+1,(unsigned int) highlight_info.width-3,
7526 (unsigned int) highlight_info.height-3);
7527 }
7528 /*
7529 Show center pixel color.
7530 */
cristy3aa93752011-12-18 15:54:24 +00007531 (void) GetOneVirtualPixelInfo(windows->image.image,TileVirtualPixelMethod,
cristy52010022011-10-21 18:07:37 +00007532 (ssize_t) windows->magnify.x,(ssize_t) windows->magnify.y,&pixel,exception);
cristyb51dff52011-05-19 16:55:47 +00007533 (void) FormatLocaleString(tuple,MaxTextExtent,"%d,%d: ",
cristy3ed852e2009-09-05 21:47:34 +00007534 windows->magnify.x,windows->magnify.y);
7535 (void) ConcatenateMagickString(tuple,"(",MaxTextExtent);
cristyed231572011-07-14 02:18:59 +00007536 ConcatenateColorComponent(&pixel,RedPixelChannel,X11Compliance,tuple);
cristy3ed852e2009-09-05 21:47:34 +00007537 (void) ConcatenateMagickString(tuple,",",MaxTextExtent);
cristyed231572011-07-14 02:18:59 +00007538 ConcatenateColorComponent(&pixel,GreenPixelChannel,X11Compliance,tuple);
cristy3ed852e2009-09-05 21:47:34 +00007539 (void) ConcatenateMagickString(tuple,",",MaxTextExtent);
cristyed231572011-07-14 02:18:59 +00007540 ConcatenateColorComponent(&pixel,BluePixelChannel,X11Compliance,tuple);
cristy3ed852e2009-09-05 21:47:34 +00007541 if (pixel.colorspace == CMYKColorspace)
7542 {
7543 (void) ConcatenateMagickString(tuple,",",MaxTextExtent);
cristyed231572011-07-14 02:18:59 +00007544 ConcatenateColorComponent(&pixel,BlackPixelChannel,X11Compliance,tuple);
cristy3ed852e2009-09-05 21:47:34 +00007545 }
7546 if (pixel.matte != MagickFalse)
7547 {
7548 (void) ConcatenateMagickString(tuple,",",MaxTextExtent);
cristyed231572011-07-14 02:18:59 +00007549 ConcatenateColorComponent(&pixel,AlphaPixelChannel,X11Compliance,tuple);
cristy3ed852e2009-09-05 21:47:34 +00007550 }
7551 (void) ConcatenateMagickString(tuple,")",MaxTextExtent);
7552 height=(unsigned int) windows->magnify.font_info->ascent+
7553 windows->magnify.font_info->descent;
7554 x=windows->magnify.font_info->max_bounds.width >> 1;
7555 y=windows->magnify.font_info->ascent+(height >> 2);
7556 (void) XDrawImageString(display,windows->magnify.pixmap,
7557 windows->magnify.annotate_context,x,y,tuple,(int) strlen(tuple));
7558 GetColorTuple(&pixel,MagickTrue,tuple);
7559 y+=height;
7560 (void) XDrawImageString(display,windows->magnify.pixmap,
7561 windows->magnify.annotate_context,x,y,tuple,(int) strlen(tuple));
cristy269c9412011-10-13 23:41:15 +00007562 (void) QueryColorname(windows->image.image,&pixel,SVGCompliance,tuple,
cristy6710d842011-10-20 23:23:00 +00007563 exception);
cristy3ed852e2009-09-05 21:47:34 +00007564 y+=height;
7565 (void) XDrawImageString(display,windows->magnify.pixmap,
7566 windows->magnify.annotate_context,x,y,tuple,(int) strlen(tuple));
7567 /*
7568 Refresh magnify window.
7569 */
7570 magnify_window=windows->magnify;
7571 magnify_window.x=0;
7572 magnify_window.y=0;
7573 XRefreshWindow(display,&magnify_window,(XEvent *) NULL);
7574}
7575
7576/*
7577%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
7578% %
7579% %
7580% %
7581% X M a k e P i x m a p %
7582% %
7583% %
7584% %
7585%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
7586%
7587% XMakePixmap() creates an X11 pixmap.
7588%
7589% The format of the XMakePixmap method is:
7590%
7591% void XMakeStandardColormap(Display *display,XVisualInfo *visual_info,
7592% XResourceInfo *resource_info,Image *image,XStandardColormap *map_info,
7593% XPixelInfo *pixel)
7594%
7595% A description of each parameter follows:
7596%
7597% o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
7598%
7599% o display: Specifies a connection to an X server; returned from
7600% XOpenDisplay.
7601%
7602% o window: Specifies a pointer to a XWindowInfo structure.
7603%
cristy3ed852e2009-09-05 21:47:34 +00007604*/
7605static MagickBooleanType XMakePixmap(Display *display,
7606 const XResourceInfo *resource_info,XWindowInfo *window)
7607{
7608 unsigned int
7609 height,
7610 width;
7611
7612 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
7613 assert(display != (Display *) NULL);
7614 assert(resource_info != (XResourceInfo *) NULL);
7615 assert(window != (XWindowInfo *) NULL);
7616 if (window->pixmap != (Pixmap) NULL)
7617 {
7618 /*
7619 Destroy previous X pixmap.
7620 */
7621 (void) XFreePixmap(display,window->pixmap);
7622 window->pixmap=(Pixmap) NULL;
7623 }
7624 if (window->use_pixmap == MagickFalse)
7625 return(MagickFalse);
7626 if (window->ximage == (XImage *) NULL)
7627 return(MagickFalse);
7628 /*
7629 Display busy cursor.
7630 */
7631 (void) XCheckDefineCursor(display,window->id,window->busy_cursor);
7632 (void) XFlush(display);
7633 /*
7634 Create pixmap.
7635 */
7636 width=(unsigned int) window->ximage->width;
7637 height=(unsigned int) window->ximage->height;
7638 window->pixmap=XCreatePixmap(display,window->id,width,height,window->depth);
7639 if (window->pixmap == (Pixmap) NULL)
7640 {
7641 /*
7642 Unable to allocate pixmap.
7643 */
7644 (void) XCheckDefineCursor(display,window->id,window->cursor);
7645 return(MagickFalse);
7646 }
7647 /*
7648 Copy X image to pixmap.
7649 */
7650#if defined(MAGICKCORE_HAVE_SHARED_MEMORY)
7651 if (window->shared_memory)
7652 (void) XShmPutImage(display,window->pixmap,window->annotate_context,
7653 window->ximage,0,0,0,0,width,height,MagickTrue);
7654#endif
7655 if (window->shared_memory == MagickFalse)
7656 (void) XPutImage(display,window->pixmap,window->annotate_context,
7657 window->ximage,0,0,0,0,width,height);
7658 if (IsEventLogging())
7659 {
7660 (void) LogMagickEvent(X11Event,GetMagickModule(),"Pixmap:");
7661 (void) LogMagickEvent(X11Event,GetMagickModule()," width, height: %ux%u",
7662 width,height);
7663 }
7664 /*
7665 Restore cursor.
7666 */
7667 (void) XCheckDefineCursor(display,window->id,window->cursor);
7668 return(MagickTrue);
7669}
7670
7671/*
7672%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
7673% %
7674% %
7675% %
7676% X M a k e S t a n d a r d C o l o r m a p %
7677% %
7678% %
7679% %
7680%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
7681%
7682% XMakeStandardColormap() creates an X11 Standard Colormap.
7683%
7684% The format of the XMakeStandardColormap method is:
7685%
cristy6710d842011-10-20 23:23:00 +00007686% void XMakeStandardColormap(Display *display,XVisualInfo *visual_info,
7687% XResourceInfo *resource_info,Image *image,XStandardColormap *map_info,
7688% XPixelInfo *pixel,ExceptionInfo *exception)
cristy3ed852e2009-09-05 21:47:34 +00007689%
7690% A description of each parameter follows:
7691%
7692% o display: Specifies a connection to an X server; returned from
7693% XOpenDisplay.
7694%
7695% o visual_info: Specifies a pointer to a X11 XVisualInfo structure;
7696% returned from XGetVisualInfo.
7697%
7698% o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
7699%
7700% o image: the image.
7701%
7702% o map_info: If a Standard Colormap type is specified, this structure is
7703% initialized with info from the Standard Colormap.
7704%
7705% o pixel: Specifies a pointer to a XPixelInfo structure.
7706%
cristy6710d842011-10-20 23:23:00 +00007707% o exception: return any errors or warnings in this structure.
7708%
cristy3ed852e2009-09-05 21:47:34 +00007709*/
7710
7711#if defined(__cplusplus) || defined(c_plusplus)
7712extern "C" {
7713#endif
7714
7715static inline MagickRealType DiversityPixelIntensity(
7716 const DiversityPacket *pixel)
7717{
7718 MagickRealType
7719 intensity;
7720
7721 intensity=0.299*pixel->red+0.587*pixel->green+0.114*pixel->blue;
7722 return(intensity);
7723}
7724
7725static int IntensityCompare(const void *x,const void *y)
7726{
7727 DiversityPacket
7728 *color_1,
7729 *color_2;
7730
7731 int
7732 diversity;
7733
7734 color_1=(DiversityPacket *) x;
7735 color_2=(DiversityPacket *) y;
7736 diversity=(int) (DiversityPixelIntensity(color_2)-
7737 DiversityPixelIntensity(color_1));
7738 return(diversity);
7739}
7740
7741static int PopularityCompare(const void *x,const void *y)
7742{
7743 DiversityPacket
7744 *color_1,
7745 *color_2;
7746
7747 color_1=(DiversityPacket *) x;
7748 color_2=(DiversityPacket *) y;
7749 return((int) color_2->count-(int) color_1->count);
7750}
7751
7752#if defined(__cplusplus) || defined(c_plusplus)
7753}
7754#endif
7755
cristybb503372010-05-27 20:51:26 +00007756static inline Quantum ScaleXToQuantum(const size_t x,
7757 const size_t scale)
cristy3ed852e2009-09-05 21:47:34 +00007758{
7759 return((Quantum) (((MagickRealType) QuantumRange*x)/scale+0.5));
7760}
7761
cristybcbda3f2011-09-03 13:01:22 +00007762MagickPrivate void XMakeStandardColormap(Display *display,
cristy3ed852e2009-09-05 21:47:34 +00007763 XVisualInfo *visual_info,XResourceInfo *resource_info,Image *image,
cristy6710d842011-10-20 23:23:00 +00007764 XStandardColormap *map_info,XPixelInfo *pixel,ExceptionInfo *exception)
cristy3ed852e2009-09-05 21:47:34 +00007765{
7766 Colormap
7767 colormap;
7768
cristybb503372010-05-27 20:51:26 +00007769 register ssize_t
cristy3ed852e2009-09-05 21:47:34 +00007770 i;
7771
7772 Status
7773 status;
7774
cristybb503372010-05-27 20:51:26 +00007775 size_t
cristy3ed852e2009-09-05 21:47:34 +00007776 number_colors,
7777 retain_colors;
7778
7779 unsigned short
7780 gray_value;
7781
7782 XColor
7783 color,
7784 *colors,
7785 *p;
7786
7787 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
7788 assert(display != (Display *) NULL);
7789 assert(visual_info != (XVisualInfo *) NULL);
7790 assert(map_info != (XStandardColormap *) NULL);
7791 assert(resource_info != (XResourceInfo *) NULL);
7792 assert(pixel != (XPixelInfo *) NULL);
cristy3ed852e2009-09-05 21:47:34 +00007793 if (resource_info->map_type != (char *) NULL)
7794 {
7795 /*
7796 Standard Colormap is already defined (i.e. xstdcmap).
7797 */
cristy4c08aed2011-07-01 19:47:50 +00007798 XGetPixelInfo(display,visual_info,map_info,resource_info,image,
cristy3ed852e2009-09-05 21:47:34 +00007799 pixel);
7800 number_colors=(unsigned int) (map_info->base_pixel+
7801 (map_info->red_max+1)*(map_info->green_max+1)*(map_info->blue_max+1));
7802 if ((map_info->red_max*map_info->green_max*map_info->blue_max) != 0)
7803 if ((image->matte == MagickFalse) &&
7804 (resource_info->color_recovery == MagickFalse) &&
7805 resource_info->quantize_info->dither &&
7806 (number_colors < MaxColormapSize))
7807 {
7808 Image
7809 *affinity_image;
7810
cristy4c08aed2011-07-01 19:47:50 +00007811 register Quantum
cristyc47d1f82009-11-26 01:44:43 +00007812 *restrict q;
cristy3ed852e2009-09-05 21:47:34 +00007813
7814 /*
7815 Improve image appearance with error diffusion.
7816 */
cristy6710d842011-10-20 23:23:00 +00007817 affinity_image=AcquireImage((ImageInfo *) NULL,exception);
cristy3ed852e2009-09-05 21:47:34 +00007818 if (affinity_image == (Image *) NULL)
7819 ThrowXWindowFatalException(ResourceLimitFatalError,
7820 "UnableToDitherImage",image->filename);
7821 affinity_image->columns=number_colors;
7822 affinity_image->rows=1;
7823 /*
7824 Initialize colormap image.
7825 */
7826 q=QueueAuthenticPixels(affinity_image,0,0,affinity_image->columns,
7827 1,exception);
cristy4c08aed2011-07-01 19:47:50 +00007828 if (q != (Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00007829 {
cristybb503372010-05-27 20:51:26 +00007830 for (i=0; i < (ssize_t) number_colors; i++)
cristy3ed852e2009-09-05 21:47:34 +00007831 {
cristy4c08aed2011-07-01 19:47:50 +00007832 SetPixelRed(affinity_image,0,q);
cristy3ed852e2009-09-05 21:47:34 +00007833 if (map_info->red_max != 0)
cristy4c08aed2011-07-01 19:47:50 +00007834 SetPixelRed(affinity_image,
7835 ScaleXToQuantum((size_t) (i/map_info->red_mult),
7836 map_info->red_max),q);
7837 SetPixelGreen(affinity_image,0,q);
cristy3ed852e2009-09-05 21:47:34 +00007838 if (map_info->green_max != 0)
cristy4c08aed2011-07-01 19:47:50 +00007839 SetPixelGreen(affinity_image,
7840 ScaleXToQuantum((size_t) ((i/map_info->green_mult) %
7841 (map_info->green_max+1)),map_info->green_max),q);
7842 SetPixelBlue(affinity_image,0,q);
cristy3ed852e2009-09-05 21:47:34 +00007843 if (map_info->blue_max != 0)
cristy4c08aed2011-07-01 19:47:50 +00007844 SetPixelBlue(affinity_image,
7845 ScaleXToQuantum((size_t) (i % map_info->green_mult),
7846 map_info->blue_max),q);
7847 SetPixelAlpha(affinity_image,
7848 TransparentAlpha,q);
cristyed231572011-07-14 02:18:59 +00007849 q+=GetPixelChannels(affinity_image);
cristy3ed852e2009-09-05 21:47:34 +00007850 }
7851 (void) SyncAuthenticPixels(affinity_image,exception);
7852 (void) RemapImage(resource_info->quantize_info,image,
cristy018f07f2011-09-04 21:15:19 +00007853 affinity_image,exception);
cristy3ed852e2009-09-05 21:47:34 +00007854 }
cristy4c08aed2011-07-01 19:47:50 +00007855 XGetPixelInfo(display,visual_info,map_info,resource_info,image,
cristy3ed852e2009-09-05 21:47:34 +00007856 pixel);
cristy574cc262011-08-05 01:23:58 +00007857 (void) SetImageStorageClass(image,DirectClass,exception);
cristy3ed852e2009-09-05 21:47:34 +00007858 affinity_image=DestroyImage(affinity_image);
7859 }
7860 if (IsEventLogging())
7861 {
7862 (void) LogMagickEvent(X11Event,GetMagickModule(),
7863 "Standard Colormap:");
7864 (void) LogMagickEvent(X11Event,GetMagickModule(),
7865 " colormap id: 0x%lx",map_info->colormap);
7866 (void) LogMagickEvent(X11Event,GetMagickModule(),
7867 " red, green, blue max: %lu %lu %lu",map_info->red_max,
7868 map_info->green_max,map_info->blue_max);
7869 (void) LogMagickEvent(X11Event,GetMagickModule(),
7870 " red, green, blue mult: %lu %lu %lu",map_info->red_mult,
7871 map_info->green_mult,map_info->blue_mult);
7872 }
7873 return;
7874 }
7875 if ((visual_info->klass != DirectColor) &&
7876 (visual_info->klass != TrueColor))
7877 if ((image->storage_class == DirectClass) ||
7878 ((int) image->colors > visual_info->colormap_size))
7879 {
7880 QuantizeInfo
7881 quantize_info;
7882
7883 /*
7884 Image has more colors than the visual supports.
7885 */
7886 quantize_info=(*resource_info->quantize_info);
cristybb503372010-05-27 20:51:26 +00007887 quantize_info.number_colors=(size_t) visual_info->colormap_size;
cristy018f07f2011-09-04 21:15:19 +00007888 (void) QuantizeImage(&quantize_info,image,exception);
cristy3ed852e2009-09-05 21:47:34 +00007889 }
7890 /*
7891 Free previous and create new colormap.
7892 */
7893 (void) XFreeStandardColormap(display,visual_info,map_info,pixel);
7894 colormap=XDefaultColormap(display,visual_info->screen);
7895 if (visual_info->visual != XDefaultVisual(display,visual_info->screen))
7896 colormap=XCreateColormap(display,XRootWindow(display,visual_info->screen),
7897 visual_info->visual,visual_info->klass == DirectColor ?
7898 AllocAll : AllocNone);
7899 if (colormap == (Colormap) NULL)
7900 ThrowXWindowFatalException(ResourceLimitFatalError,"UnableToCreateColormap",
7901 image->filename);
7902 /*
7903 Initialize the map and pixel info structures.
7904 */
7905 XGetMapInfo(visual_info,colormap,map_info);
cristy4c08aed2011-07-01 19:47:50 +00007906 XGetPixelInfo(display,visual_info,map_info,resource_info,image,pixel);
cristy3ed852e2009-09-05 21:47:34 +00007907 /*
7908 Allocating colors in server colormap is based on visual class.
7909 */
7910 switch (visual_info->klass)
7911 {
7912 case StaticGray:
7913 case StaticColor:
7914 {
7915 /*
7916 Define Standard Colormap for StaticGray or StaticColor visual.
7917 */
7918 number_colors=image->colors;
7919 colors=(XColor *) AcquireQuantumMemory((size_t)
7920 visual_info->colormap_size,sizeof(*colors));
7921 if (colors == (XColor *) NULL)
7922 ThrowXWindowFatalException(ResourceLimitFatalError,
7923 "UnableToCreateColormap",image->filename);
7924 p=colors;
7925 color.flags=(char) (DoRed | DoGreen | DoBlue);
cristybb503372010-05-27 20:51:26 +00007926 for (i=0; i < (ssize_t) image->colors; i++)
cristy3ed852e2009-09-05 21:47:34 +00007927 {
7928 color.red=ScaleQuantumToShort(XRedGamma(image->colormap[i].red));
7929 color.green=ScaleQuantumToShort(XGreenGamma(image->colormap[i].green));
7930 color.blue=ScaleQuantumToShort(XBlueGamma(image->colormap[i].blue));
7931 if (visual_info->klass != StaticColor)
7932 {
7933 gray_value=(unsigned short) XPixelIntensity(&color);
7934 color.red=gray_value;
7935 color.green=gray_value;
7936 color.blue=gray_value;
7937 }
7938 status=XAllocColor(display,colormap,&color);
7939 if (status == False)
7940 {
7941 colormap=XCopyColormapAndFree(display,colormap);
7942 (void) XAllocColor(display,colormap,&color);
7943 }
7944 pixel->pixels[i]=color.pixel;
7945 *p++=color;
7946 }
7947 break;
7948 }
7949 case GrayScale:
7950 case PseudoColor:
7951 {
7952 unsigned int
7953 colormap_type;
7954
7955 /*
7956 Define Standard Colormap for GrayScale or PseudoColor visual.
7957 */
7958 number_colors=image->colors;
7959 colors=(XColor *) AcquireQuantumMemory((size_t)
7960 visual_info->colormap_size,sizeof(*colors));
7961 if (colors == (XColor *) NULL)
7962 ThrowXWindowFatalException(ResourceLimitFatalError,
7963 "UnableToCreateColormap",image->filename);
7964 /*
7965 Preallocate our GUI colors.
7966 */
7967 (void) XAllocColor(display,colormap,&pixel->foreground_color);
7968 (void) XAllocColor(display,colormap,&pixel->background_color);
7969 (void) XAllocColor(display,colormap,&pixel->border_color);
7970 (void) XAllocColor(display,colormap,&pixel->matte_color);
7971 (void) XAllocColor(display,colormap,&pixel->highlight_color);
7972 (void) XAllocColor(display,colormap,&pixel->shadow_color);
7973 (void) XAllocColor(display,colormap,&pixel->depth_color);
7974 (void) XAllocColor(display,colormap,&pixel->trough_color);
7975 for (i=0; i < MaxNumberPens; i++)
7976 (void) XAllocColor(display,colormap,&pixel->pen_colors[i]);
7977 /*
7978 Determine if image colors will "fit" into X server colormap.
7979 */
7980 colormap_type=resource_info->colormap;
cristyf2faecf2010-05-28 19:19:36 +00007981 status=XAllocColorCells(display,colormap,MagickFalse,(unsigned long *)
cristy3ed852e2009-09-05 21:47:34 +00007982 NULL,0,pixel->pixels,(unsigned int) image->colors);
7983 if (status != False)
7984 colormap_type=PrivateColormap;
7985 if (colormap_type == SharedColormap)
7986 {
cristyc57f6942010-11-12 01:47:39 +00007987 CacheView
7988 *image_view;
7989
cristy3ed852e2009-09-05 21:47:34 +00007990 DiversityPacket
7991 *diversity;
7992
7993 int
7994 y;
7995
7996 register int
7997 x;
7998
7999 unsigned short
8000 index;
8001
8002 XColor
8003 *server_colors;
8004
8005 /*
8006 Define Standard colormap for shared GrayScale or PseudoColor visual.
8007 */
8008 diversity=(DiversityPacket *) AcquireQuantumMemory(image->colors,
8009 sizeof(*diversity));
8010 if (diversity == (DiversityPacket *) NULL)
8011 ThrowXWindowFatalException(ResourceLimitFatalError,
8012 "UnableToCreateColormap",image->filename);
cristybb503372010-05-27 20:51:26 +00008013 for (i=0; i < (ssize_t) image->colors; i++)
cristy3ed852e2009-09-05 21:47:34 +00008014 {
8015 diversity[i].red=image->colormap[i].red;
8016 diversity[i].green=image->colormap[i].green;
8017 diversity[i].blue=image->colormap[i].blue;
8018 diversity[i].index=(unsigned short) i;
8019 diversity[i].count=0;
8020 }
cristyc57f6942010-11-12 01:47:39 +00008021 image_view=AcquireCacheView(image);
cristy3ed852e2009-09-05 21:47:34 +00008022 for (y=0; y < (int) image->rows; y++)
8023 {
cristyc57f6942010-11-12 01:47:39 +00008024 register int
cristy3ed852e2009-09-05 21:47:34 +00008025 x;
8026
cristy4c08aed2011-07-01 19:47:50 +00008027 register const Quantum
cristyc57f6942010-11-12 01:47:39 +00008028 *restrict p;
cristy3ed852e2009-09-05 21:47:34 +00008029
cristyc57f6942010-11-12 01:47:39 +00008030 p=GetCacheViewAuthenticPixels(image_view,0,(ssize_t) y,
8031 image->columns,1,exception);
cristy4c08aed2011-07-01 19:47:50 +00008032 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00008033 break;
cristyc57f6942010-11-12 01:47:39 +00008034 for (x=(int) image->columns-1; x >= 0; x--)
cristy4c08aed2011-07-01 19:47:50 +00008035 {
8036 diversity[(ssize_t) GetPixelIndex(image,p)].count++;
cristyed231572011-07-14 02:18:59 +00008037 p+=GetPixelChannels(image);
cristy4c08aed2011-07-01 19:47:50 +00008038 }
cristy3ed852e2009-09-05 21:47:34 +00008039 }
cristyc57f6942010-11-12 01:47:39 +00008040 image_view=DestroyCacheView(image_view);
cristy3ed852e2009-09-05 21:47:34 +00008041 /*
8042 Sort colors by decreasing intensity.
8043 */
8044 qsort((void *) diversity,image->colors,sizeof(*diversity),
8045 IntensityCompare);
cristybb503372010-05-27 20:51:26 +00008046 for (i=0; i < (ssize_t) image->colors; )
cristy3ed852e2009-09-05 21:47:34 +00008047 {
8048 diversity[i].count<<=4; /* increase this colors popularity */
cristydfe2b662010-08-22 16:17:24 +00008049 i+=MagickMax((int) (image->colors >> 4),2);
cristy3ed852e2009-09-05 21:47:34 +00008050 }
8051 diversity[image->colors-1].count<<=4;
8052 qsort((void *) diversity,image->colors,sizeof(*diversity),
8053 PopularityCompare);
8054 /*
8055 Allocate colors.
8056 */
8057 p=colors;
8058 color.flags=(char) (DoRed | DoGreen | DoBlue);
cristybb503372010-05-27 20:51:26 +00008059 for (i=0; i < (ssize_t) image->colors; i++)
cristy3ed852e2009-09-05 21:47:34 +00008060 {
8061 index=diversity[i].index;
8062 color.red=
8063 ScaleQuantumToShort(XRedGamma(image->colormap[index].red));
8064 color.green=
8065 ScaleQuantumToShort(XGreenGamma(image->colormap[index].green));
8066 color.blue=
8067 ScaleQuantumToShort(XBlueGamma(image->colormap[index].blue));
8068 if (visual_info->klass != PseudoColor)
8069 {
8070 gray_value=(unsigned short) XPixelIntensity(&color);
8071 color.red=gray_value;
8072 color.green=gray_value;
8073 color.blue=gray_value;
8074 }
8075 status=XAllocColor(display,colormap,&color);
8076 if (status == False)
8077 break;
8078 pixel->pixels[index]=color.pixel;
8079 *p++=color;
8080 }
8081 /*
8082 Read X server colormap.
8083 */
8084 server_colors=(XColor *) AcquireQuantumMemory((size_t)
8085 visual_info->colormap_size,sizeof(*server_colors));
8086 if (server_colors == (XColor *) NULL)
8087 ThrowXWindowFatalException(ResourceLimitFatalError,
8088 "UnableToCreateColormap",image->filename);
8089 for (x=visual_info->colormap_size-1; x >= 0; x--)
cristybb503372010-05-27 20:51:26 +00008090 server_colors[x].pixel=(size_t) x;
cristy3ed852e2009-09-05 21:47:34 +00008091 (void) XQueryColors(display,colormap,server_colors,
8092 (int) MagickMin((unsigned int) visual_info->colormap_size,256));
8093 /*
8094 Select remaining colors from X server colormap.
8095 */
cristybb503372010-05-27 20:51:26 +00008096 for (; i < (ssize_t) image->colors; i++)
cristy3ed852e2009-09-05 21:47:34 +00008097 {
8098 index=diversity[i].index;
8099 color.red=
8100 ScaleQuantumToShort(XRedGamma(image->colormap[index].red));
8101 color.green=
8102 ScaleQuantumToShort(XGreenGamma(image->colormap[index].green));
8103 color.blue=
8104 ScaleQuantumToShort(XBlueGamma(image->colormap[index].blue));
8105 if (visual_info->klass != PseudoColor)
8106 {
8107 gray_value=(unsigned short) XPixelIntensity(&color);
8108 color.red=gray_value;
8109 color.green=gray_value;
8110 color.blue=gray_value;
8111 }
8112 XBestPixel(display,colormap,server_colors,(unsigned int)
8113 visual_info->colormap_size,&color);
8114 pixel->pixels[index]=color.pixel;
8115 *p++=color;
8116 }
8117 if ((int) image->colors < visual_info->colormap_size)
8118 {
8119 /*
8120 Fill up colors array-- more choices for pen colors.
8121 */
8122 retain_colors=MagickMin((unsigned int)
8123 (visual_info->colormap_size-image->colors),256);
cristybb503372010-05-27 20:51:26 +00008124 for (i=0; i < (ssize_t) retain_colors; i++)
cristy3ed852e2009-09-05 21:47:34 +00008125 *p++=server_colors[i];
8126 number_colors+=retain_colors;
8127 }
8128 server_colors=(XColor *) RelinquishMagickMemory(server_colors);
8129 diversity=(DiversityPacket *) RelinquishMagickMemory(diversity);
8130 break;
8131 }
8132 /*
8133 Define Standard colormap for private GrayScale or PseudoColor visual.
8134 */
8135 if (status == False)
8136 {
8137 /*
8138 Not enough colormap entries in the colormap-- Create a new colormap.
8139 */
8140 colormap=XCreateColormap(display,
8141 XRootWindow(display,visual_info->screen),visual_info->visual,
8142 AllocNone);
8143 if (colormap == (Colormap) NULL)
8144 ThrowXWindowFatalException(ResourceLimitFatalError,
8145 "UnableToCreateColormap",image->filename);
8146 map_info->colormap=colormap;
8147 if ((int) image->colors < visual_info->colormap_size)
8148 {
8149 /*
8150 Retain colors from the default colormap to help lessens the
8151 effects of colormap flashing.
8152 */
8153 retain_colors=MagickMin((unsigned int)
8154 (visual_info->colormap_size-image->colors),256);
8155 p=colors+image->colors;
cristybb503372010-05-27 20:51:26 +00008156 for (i=0; i < (ssize_t) retain_colors; i++)
cristy3ed852e2009-09-05 21:47:34 +00008157 {
cristyc57f6942010-11-12 01:47:39 +00008158 p->pixel=(unsigned long) i;
cristy3ed852e2009-09-05 21:47:34 +00008159 p++;
8160 }
8161 (void) XQueryColors(display,
8162 XDefaultColormap(display,visual_info->screen),
8163 colors+image->colors,(int) retain_colors);
8164 /*
8165 Transfer colors from default to private colormap.
8166 */
8167 (void) XAllocColorCells(display,colormap,MagickFalse,
cristyf2faecf2010-05-28 19:19:36 +00008168 (unsigned long *) NULL,0,pixel->pixels,(unsigned int)
cristy3ed852e2009-09-05 21:47:34 +00008169 retain_colors);
8170 p=colors+image->colors;
cristybb503372010-05-27 20:51:26 +00008171 for (i=0; i < (ssize_t) retain_colors; i++)
cristy3ed852e2009-09-05 21:47:34 +00008172 {
8173 p->pixel=pixel->pixels[i];
8174 p++;
8175 }
8176 (void) XStoreColors(display,colormap,colors+image->colors,
8177 (int) retain_colors);
8178 number_colors+=retain_colors;
8179 }
8180 (void) XAllocColorCells(display,colormap,MagickFalse,
cristyf2faecf2010-05-28 19:19:36 +00008181 (unsigned long *) NULL,0,pixel->pixels,(unsigned int)
cristy3ed852e2009-09-05 21:47:34 +00008182 image->colors);
8183 }
8184 /*
8185 Store the image colormap.
8186 */
8187 p=colors;
8188 color.flags=(char) (DoRed | DoGreen | DoBlue);
cristybb503372010-05-27 20:51:26 +00008189 for (i=0; i < (ssize_t) image->colors; i++)
cristy3ed852e2009-09-05 21:47:34 +00008190 {
8191 color.red=ScaleQuantumToShort(XRedGamma(image->colormap[i].red));
8192 color.green=ScaleQuantumToShort(XGreenGamma(image->colormap[i].green));
8193 color.blue=ScaleQuantumToShort(XBlueGamma(image->colormap[i].blue));
8194 if (visual_info->klass != PseudoColor)
8195 {
8196 gray_value=(unsigned short) XPixelIntensity(&color);
8197 color.red=gray_value;
8198 color.green=gray_value;
8199 color.blue=gray_value;
8200 }
8201 color.pixel=pixel->pixels[i];
8202 *p++=color;
8203 }
8204 (void) XStoreColors(display,colormap,colors,(int) image->colors);
8205 break;
8206 }
8207 case TrueColor:
8208 case DirectColor:
8209 default:
8210 {
8211 MagickBooleanType
8212 linear_colormap;
8213
8214 /*
8215 Define Standard Colormap for TrueColor or DirectColor visual.
8216 */
8217 number_colors=(unsigned int) ((map_info->red_max*map_info->red_mult)+
8218 (map_info->green_max*map_info->green_mult)+
8219 (map_info->blue_max*map_info->blue_mult)+1);
8220 linear_colormap=(number_colors > 4096) ||
8221 (((int) (map_info->red_max+1) == visual_info->colormap_size) &&
8222 ((int) (map_info->green_max+1) == visual_info->colormap_size) &&
8223 ((int) (map_info->blue_max+1) == visual_info->colormap_size)) ?
8224 MagickTrue : MagickFalse;
8225 if (linear_colormap != MagickFalse)
cristybb503372010-05-27 20:51:26 +00008226 number_colors=(size_t) visual_info->colormap_size;
cristy3ed852e2009-09-05 21:47:34 +00008227 /*
8228 Allocate color array.
8229 */
8230 colors=(XColor *) AcquireQuantumMemory(number_colors,sizeof(*colors));
8231 if (colors == (XColor *) NULL)
8232 ThrowXWindowFatalException(ResourceLimitFatalError,
8233 "UnableToCreateColormap",image->filename);
8234 /*
8235 Initialize linear color ramp.
8236 */
8237 p=colors;
8238 color.flags=(char) (DoRed | DoGreen | DoBlue);
8239 if (linear_colormap != MagickFalse)
cristybb503372010-05-27 20:51:26 +00008240 for (i=0; i < (ssize_t) number_colors; i++)
cristy3ed852e2009-09-05 21:47:34 +00008241 {
8242 color.blue=(unsigned short) 0;
8243 if (map_info->blue_max != 0)
cristybb503372010-05-27 20:51:26 +00008244 color.blue=(unsigned short) ((size_t)
cristy3ed852e2009-09-05 21:47:34 +00008245 ((65535L*(i % map_info->green_mult))/map_info->blue_max));
8246 color.green=color.blue;
8247 color.red=color.blue;
8248 color.pixel=XStandardPixel(map_info,&color);
8249 *p++=color;
8250 }
8251 else
cristybb503372010-05-27 20:51:26 +00008252 for (i=0; i < (ssize_t) number_colors; i++)
cristy3ed852e2009-09-05 21:47:34 +00008253 {
8254 color.red=(unsigned short) 0;
8255 if (map_info->red_max != 0)
cristybb503372010-05-27 20:51:26 +00008256 color.red=(unsigned short) ((size_t)
cristy3ed852e2009-09-05 21:47:34 +00008257 ((65535L*(i/map_info->red_mult))/map_info->red_max));
8258 color.green=(unsigned int) 0;
8259 if (map_info->green_max != 0)
cristybb503372010-05-27 20:51:26 +00008260 color.green=(unsigned short) ((size_t)
cristy3ed852e2009-09-05 21:47:34 +00008261 ((65535L*((i/map_info->green_mult) % (map_info->green_max+1)))/
8262 map_info->green_max));
8263 color.blue=(unsigned short) 0;
8264 if (map_info->blue_max != 0)
cristybb503372010-05-27 20:51:26 +00008265 color.blue=(unsigned short) ((size_t)
cristy3ed852e2009-09-05 21:47:34 +00008266 ((65535L*(i % map_info->green_mult))/map_info->blue_max));
8267 color.pixel=XStandardPixel(map_info,&color);
8268 *p++=color;
8269 }
8270 if ((visual_info->klass == DirectColor) &&
8271 (colormap != XDefaultColormap(display,visual_info->screen)))
8272 (void) XStoreColors(display,colormap,colors,(int) number_colors);
8273 else
cristybb503372010-05-27 20:51:26 +00008274 for (i=0; i < (ssize_t) number_colors; i++)
cristy3ed852e2009-09-05 21:47:34 +00008275 (void) XAllocColor(display,colormap,&colors[i]);
8276 break;
8277 }
8278 }
8279 if ((visual_info->klass != DirectColor) &&
8280 (visual_info->klass != TrueColor))
8281 {
8282 /*
8283 Set foreground, background, border, etc. pixels.
8284 */
8285 XBestPixel(display,colormap,colors,(unsigned int) number_colors,
8286 &pixel->foreground_color);
8287 XBestPixel(display,colormap,colors,(unsigned int) number_colors,
8288 &pixel->background_color);
8289 if (pixel->background_color.pixel == pixel->foreground_color.pixel)
8290 {
8291 /*
8292 Foreground and background colors must differ.
8293 */
8294 pixel->background_color.red=(~pixel->foreground_color.red);
8295 pixel->background_color.green=
8296 (~pixel->foreground_color.green);
8297 pixel->background_color.blue=
8298 (~pixel->foreground_color.blue);
8299 XBestPixel(display,colormap,colors,(unsigned int) number_colors,
8300 &pixel->background_color);
8301 }
8302 XBestPixel(display,colormap,colors,(unsigned int) number_colors,
8303 &pixel->border_color);
8304 XBestPixel(display,colormap,colors,(unsigned int) number_colors,
8305 &pixel->matte_color);
8306 XBestPixel(display,colormap,colors,(unsigned int) number_colors,
8307 &pixel->highlight_color);
8308 XBestPixel(display,colormap,colors,(unsigned int) number_colors,
8309 &pixel->shadow_color);
8310 XBestPixel(display,colormap,colors,(unsigned int) number_colors,
8311 &pixel->depth_color);
8312 XBestPixel(display,colormap,colors,(unsigned int) number_colors,
8313 &pixel->trough_color);
8314 for (i=0; i < MaxNumberPens; i++)
8315 {
8316 XBestPixel(display,colormap,colors,(unsigned int) number_colors,
8317 &pixel->pen_colors[i]);
8318 pixel->pixels[image->colors+i]=pixel->pen_colors[i].pixel;
8319 }
cristyc57f6942010-11-12 01:47:39 +00008320 pixel->colors=(ssize_t) (image->colors+MaxNumberPens);
cristy3ed852e2009-09-05 21:47:34 +00008321 }
8322 colors=(XColor *) RelinquishMagickMemory(colors);
8323 if (IsEventLogging())
8324 {
8325 (void) LogMagickEvent(X11Event,GetMagickModule(),"Standard Colormap:");
8326 (void) LogMagickEvent(X11Event,GetMagickModule()," colormap id: 0x%lx",
8327 map_info->colormap);
8328 (void) LogMagickEvent(X11Event,GetMagickModule(),
8329 " red, green, blue max: %lu %lu %lu",map_info->red_max,
8330 map_info->green_max,map_info->blue_max);
8331 (void) LogMagickEvent(X11Event,GetMagickModule(),
8332 " red, green, blue mult: %lu %lu %lu",map_info->red_mult,
8333 map_info->green_mult,map_info->blue_mult);
8334 }
8335}
8336
8337/*
8338%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8339% %
8340% %
8341% %
8342% X M a k e W i n d o w %
8343% %
8344% %
8345% %
8346%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8347%
8348% XMakeWindow() creates an X11 window.
8349%
8350% The format of the XMakeWindow method is:
8351%
8352% void XMakeWindow(Display *display,Window parent,char **argv,int argc,
8353% XClassHint *class_hint,XWMHints *manager_hints,
8354% XWindowInfo *window_info)
8355%
8356% A description of each parameter follows:
8357%
8358% o display: Specifies a connection to an X server; returned from
8359% XOpenDisplay.
8360%
8361% o parent: Specifies the parent window_info.
8362%
8363% o argv: Specifies the application's argument list.
8364%
8365% o argc: Specifies the number of arguments.
8366%
8367% o class_hint: Specifies a pointer to a X11 XClassHint structure.
8368%
8369% o manager_hints: Specifies a pointer to a X11 XWMHints structure.
8370%
8371% o window_info: Specifies a pointer to a X11 XWindowInfo structure.
8372%
8373*/
cristybcbda3f2011-09-03 13:01:22 +00008374MagickPrivate void XMakeWindow(Display *display,Window parent,char **argv,
cristy3ed852e2009-09-05 21:47:34 +00008375 int argc,XClassHint *class_hint,XWMHints *manager_hints,
8376 XWindowInfo *window_info)
8377{
8378#define MinWindowSize 64
8379
8380 Atom
8381 atom_list[2];
8382
8383 int
8384 gravity;
8385
8386 static XTextProperty
8387 icon_name,
8388 window_name;
8389
8390 Status
8391 status;
8392
8393 XSizeHints
8394 *size_hints;
8395
8396 /*
8397 Set window info hints.
8398 */
8399 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
8400 assert(display != (Display *) NULL);
8401 assert(window_info != (XWindowInfo *) NULL);
8402 size_hints=XAllocSizeHints();
8403 if (size_hints == (XSizeHints *) NULL)
8404 ThrowXWindowFatalException(XServerFatalError,"UnableToMakeXWindow",argv[0]);
cristydfe2b662010-08-22 16:17:24 +00008405 size_hints->flags=(int) window_info->flags;
cristy3ed852e2009-09-05 21:47:34 +00008406 size_hints->x=window_info->x;
8407 size_hints->y=window_info->y;
8408 size_hints->width=(int) window_info->width;
8409 size_hints->height=(int) window_info->height;
8410 if (window_info->immutable != MagickFalse)
8411 {
8412 /*
8413 Window size cannot be changed.
8414 */
8415 size_hints->min_width=size_hints->width;
8416 size_hints->min_height=size_hints->height;
8417 size_hints->max_width=size_hints->width;
8418 size_hints->max_height=size_hints->height;
8419 size_hints->flags|=PMinSize;
8420 size_hints->flags|=PMaxSize;
8421 }
8422 else
8423 {
8424 /*
8425 Window size can be changed.
8426 */
8427 size_hints->min_width=(int) window_info->min_width;
8428 size_hints->min_height=(int) window_info->min_height;
8429 size_hints->flags|=PResizeInc;
8430 size_hints->width_inc=(int) window_info->width_inc;
8431 size_hints->height_inc=(int) window_info->height_inc;
8432#if !defined(PRE_R4_ICCCM)
8433 size_hints->flags|=PBaseSize;
8434 size_hints->base_width=size_hints->width_inc;
8435 size_hints->base_height=size_hints->height_inc;
8436#endif
8437 }
8438 gravity=NorthWestGravity;
8439 if (window_info->geometry != (char *) NULL)
8440 {
8441 char
8442 default_geometry[MaxTextExtent],
8443 geometry[MaxTextExtent];
8444
8445 int
8446 flags;
8447
8448 register char
8449 *p;
8450
8451 /*
8452 User specified geometry.
8453 */
cristyb51dff52011-05-19 16:55:47 +00008454 (void) FormatLocaleString(default_geometry,MaxTextExtent,"%dx%d",
cristy3ed852e2009-09-05 21:47:34 +00008455 size_hints->width,size_hints->height);
8456 (void) CopyMagickString(geometry,window_info->geometry,MaxTextExtent);
8457 p=geometry;
8458 while (strlen(p) != 0)
8459 {
8460 if ((isspace((int) ((unsigned char) *p)) == 0) && (*p != '%'))
8461 p++;
8462 else
8463 (void) CopyMagickString(p,p+1,MaxTextExtent);
8464 }
8465 flags=XWMGeometry(display,window_info->screen,geometry,default_geometry,
8466 window_info->border_width,size_hints,&size_hints->x,&size_hints->y,
8467 &size_hints->width,&size_hints->height,&gravity);
8468 if ((flags & WidthValue) && (flags & HeightValue))
8469 size_hints->flags|=USSize;
8470 if ((flags & XValue) && (flags & YValue))
8471 {
8472 size_hints->flags|=USPosition;
8473 window_info->x=size_hints->x;
8474 window_info->y=size_hints->y;
8475 }
8476 }
8477#if !defined(PRE_R4_ICCCM)
8478 size_hints->win_gravity=gravity;
8479 size_hints->flags|=PWinGravity;
8480#endif
8481 if (window_info->id == (Window) NULL)
8482 window_info->id=XCreateWindow(display,parent,window_info->x,window_info->y,
8483 (unsigned int) size_hints->width,(unsigned int) size_hints->height,
8484 window_info->border_width,(int) window_info->depth,InputOutput,
cristyc57f6942010-11-12 01:47:39 +00008485 window_info->visual,(unsigned long) window_info->mask,
8486 &window_info->attributes);
cristy3ed852e2009-09-05 21:47:34 +00008487 else
8488 {
8489 MagickStatusType
8490 mask;
8491
8492 XEvent
8493 sans_event;
8494
8495 XWindowChanges
8496 window_changes;
8497
8498 /*
8499 Window already exists; change relevant attributes.
8500 */
cristyc57f6942010-11-12 01:47:39 +00008501 (void) XChangeWindowAttributes(display,window_info->id,(unsigned long)
8502 window_info->mask,&window_info->attributes);
cristy3ed852e2009-09-05 21:47:34 +00008503 mask=ConfigureNotify;
8504 while (XCheckTypedWindowEvent(display,window_info->id,(int) mask,&sans_event)) ;
8505 window_changes.x=window_info->x;
8506 window_changes.y=window_info->y;
8507 window_changes.width=(int) window_info->width;
8508 window_changes.height=(int) window_info->height;
8509 mask=(MagickStatusType) (CWWidth | CWHeight);
8510 if (window_info->flags & USPosition)
8511 mask|=CWX | CWY;
8512 (void) XReconfigureWMWindow(display,window_info->id,window_info->screen,
8513 mask,&window_changes);
8514 }
8515 if (window_info->id == (Window) NULL)
8516 ThrowXWindowFatalException(XServerFatalError,"UnableToCreateWindow",
8517 window_info->name);
8518 status=XStringListToTextProperty(&window_info->name,1,&window_name);
8519 if (status == False)
8520 ThrowXWindowFatalException(XServerFatalError,"UnableToCreateTextProperty",
8521 window_info->name);
8522 status=XStringListToTextProperty(&window_info->icon_name,1,&icon_name);
8523 if (status == False)
8524 ThrowXWindowFatalException(XServerFatalError,"UnableToCreateTextProperty",
8525 window_info->icon_name);
8526 if (window_info->icon_geometry != (char *) NULL)
8527 {
8528 int
8529 flags,
8530 height,
8531 width;
8532
8533 /*
8534 User specified icon geometry.
8535 */
8536 size_hints->flags|=USPosition;
8537 flags=XWMGeometry(display,window_info->screen,window_info->icon_geometry,
8538 (char *) NULL,0,size_hints,&manager_hints->icon_x,
8539 &manager_hints->icon_y,&width,&height,&gravity);
8540 if ((flags & XValue) && (flags & YValue))
8541 manager_hints->flags|=IconPositionHint;
8542 }
8543 XSetWMProperties(display,window_info->id,&window_name,&icon_name,argv,argc,
8544 size_hints,manager_hints,class_hint);
8545 if (window_name.value != (void *) NULL)
8546 {
8547 (void) XFree((void *) window_name.value);
8548 window_name.value=(unsigned char *) NULL;
8549 window_name.nitems=0;
8550 }
8551 if (icon_name.value != (void *) NULL)
8552 {
8553 (void) XFree((void *) icon_name.value);
8554 icon_name.value=(unsigned char *) NULL;
8555 icon_name.nitems=0;
8556 }
8557 atom_list[0]=XInternAtom(display,"WM_DELETE_WINDOW",MagickFalse);
8558 atom_list[1]=XInternAtom(display,"WM_TAKE_FOCUS",MagickFalse);
8559 (void) XSetWMProtocols(display,window_info->id,atom_list,2);
8560 (void) XFree((void *) size_hints);
8561 if (window_info->shape != MagickFalse)
8562 {
8563#if defined(MAGICKCORE_HAVE_SHAPE)
8564 int
8565 error_base,
8566 event_base;
8567
8568 /*
8569 Can we apply a non-rectangular shaping mask?
8570 */
8571 error_base=0;
8572 event_base=0;
8573 if (XShapeQueryExtension(display,&error_base,&event_base) == 0)
8574 window_info->shape=MagickFalse;
8575#else
8576 window_info->shape=MagickFalse;
8577#endif
8578 }
8579 if (window_info->shared_memory)
8580 {
8581#if defined(MAGICKCORE_HAVE_SHARED_MEMORY)
8582 /*
8583 Can we use shared memory with this window?
8584 */
8585 if (XShmQueryExtension(display) == 0)
8586 window_info->shared_memory=MagickFalse;
8587#else
8588 window_info->shared_memory=MagickFalse;
8589#endif
8590 }
8591 window_info->image=NewImageList();
8592 window_info->destroy=MagickFalse;
8593}
8594
8595/*
8596%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8597% %
8598% %
8599% %
8600% X M a g i c k P r o g r e s s M o n i t o r %
8601% %
8602% %
8603% %
8604%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8605%
8606% XMagickProgressMonitor() displays the progress a task is making in
8607% completing a task.
8608%
8609% The format of the XMagickProgressMonitor method is:
8610%
8611% void XMagickProgressMonitor(const char *task,
8612% const MagickOffsetType quantum,const MagickSizeType span,
8613% void *client_data)
8614%
8615% A description of each parameter follows:
8616%
8617% o task: Identifies the task in progress.
8618%
8619% o quantum: Specifies the quantum position within the span which represents
8620% how much progress has been made in completing a task.
8621%
8622% o span: Specifies the span relative to completing a task.
8623%
8624% o client_data: Pointer to any client data.
8625%
8626*/
8627
8628static const char *GetLocaleMonitorMessage(const char *text)
8629{
8630 char
8631 message[MaxTextExtent],
8632 tag[MaxTextExtent];
8633
8634 const char
8635 *locale_message;
8636
8637 register char
8638 *p;
8639
8640 (void) CopyMagickMemory(tag,text,MaxTextExtent);
8641 p=strrchr(tag,'/');
8642 if (p != (char *) NULL)
8643 *p='\0';
cristyb51dff52011-05-19 16:55:47 +00008644 (void) FormatLocaleString(message,MaxTextExtent,"Monitor/%s",tag);
cristy3ed852e2009-09-05 21:47:34 +00008645 locale_message=GetLocaleMessage(message);
8646 if (locale_message == message)
8647 return(text);
8648 return(locale_message);
8649}
8650
cristybcbda3f2011-09-03 13:01:22 +00008651MagickPrivate MagickBooleanType XMagickProgressMonitor(const char *tag,
cristy3ed852e2009-09-05 21:47:34 +00008652 const MagickOffsetType quantum,const MagickSizeType span,
8653 void *magick_unused(client_data))
8654{
8655 XWindows
8656 *windows;
8657
8658 windows=XSetWindows((XWindows *) ~0);
8659 if (windows == (XWindows *) NULL)
8660 return(MagickTrue);
8661 if (windows->info.mapped != MagickFalse)
8662 XProgressMonitorWidget(windows->display,windows,
8663 GetLocaleMonitorMessage(tag),quantum,span);
8664 return(MagickTrue);
8665}
8666
8667/*
8668%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8669% %
8670% %
8671% %
8672% X Q u e r y C o l o r D a t a b a s e %
8673% %
8674% %
8675% %
8676%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8677%
cristy9950d572011-10-01 18:22:35 +00008678% XQueryColorCompliance() looks up a RGB values for a color given in the target
cristy3ed852e2009-09-05 21:47:34 +00008679% string.
8680%
8681% The format of the XQueryColorDatabase method is:
8682%
cristy9950d572011-10-01 18:22:35 +00008683% MagickBooleanType XQueryColorCompliance(const char *target,XColor *color)
cristy3ed852e2009-09-05 21:47:34 +00008684%
8685% A description of each parameter follows:
8686%
8687% o target: Specifies the color to lookup in the X color database.
8688%
cristy101ab702011-10-13 13:06:32 +00008689% o color: A pointer to an PixelInfo structure. The RGB value of the target
cristy3ed852e2009-09-05 21:47:34 +00008690% color is returned as this value.
8691%
8692*/
cristy9950d572011-10-01 18:22:35 +00008693MagickPrivate MagickBooleanType XQueryColorCompliance(const char *target,
cristy3ed852e2009-09-05 21:47:34 +00008694 XColor *color)
8695{
8696 Colormap
8697 colormap;
8698
8699 static Display
8700 *display = (Display *) NULL;
8701
8702 Status
8703 status;
8704
8705 XColor
8706 xcolor;
8707
8708 /*
8709 Initialize color return value.
8710 */
8711 assert(color != (XColor *) NULL);
8712 color->red=0;
8713 color->green=0;
8714 color->blue=0;
8715 color->flags=(char) (DoRed | DoGreen | DoBlue);
8716 if ((target == (char *) NULL) || (*target == '\0'))
8717 target="#ffffffffffff";
8718 /*
8719 Let the X server define the color for us.
8720 */
8721 if (display == (Display *) NULL)
8722 display=XOpenDisplay((char *) NULL);
8723 if (display == (Display *) NULL)
8724 {
8725 ThrowXWindowFatalException(XServerError,"ColorIsNotKnownToServer",target);
8726 return(MagickFalse);
8727 }
8728 colormap=XDefaultColormap(display,XDefaultScreen(display));
8729 status=XParseColor(display,colormap,(char *) target,&xcolor);
8730 if (status == False)
8731 ThrowXWindowFatalException(XServerError,"ColorIsNotKnownToServer",target)
8732 else
8733 {
8734 color->red=xcolor.red;
8735 color->green=xcolor.green;
8736 color->blue=xcolor.blue;
8737 color->flags=xcolor.flags;
8738 }
8739 return(status != False ? MagickTrue : MagickFalse);
8740}
8741
8742/*
8743%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8744% %
8745% %
8746% %
8747% X Q u e r y P o s i t i o n %
8748% %
8749% %
8750% %
8751%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8752%
8753% XQueryPosition() gets the pointer coordinates relative to a window.
8754%
8755% The format of the XQueryPosition method is:
8756%
8757% void XQueryPosition(Display *display,const Window window,int *x,int *y)
8758%
8759% A description of each parameter follows:
8760%
8761% o display: Specifies a connection to an X server; returned from
8762% XOpenDisplay.
8763%
8764% o window: Specifies a pointer to a Window.
8765%
8766% o x: Return the x coordinate of the pointer relative to the origin of the
8767% window.
8768%
8769% o y: Return the y coordinate of the pointer relative to the origin of the
8770% window.
8771%
8772*/
cristybcbda3f2011-09-03 13:01:22 +00008773MagickPrivate void XQueryPosition(Display *display,const Window window,int *x,int *y)
cristy3ed852e2009-09-05 21:47:34 +00008774{
8775 int
8776 x_root,
8777 y_root;
8778
8779 unsigned int
8780 mask;
8781
8782 Window
8783 root_window;
8784
8785 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
8786 assert(display != (Display *) NULL);
8787 assert(window != (Window) NULL);
8788 assert(x != (int *) NULL);
8789 assert(y != (int *) NULL);
8790 (void) XQueryPointer(display,window,&root_window,&root_window,&x_root,&y_root,
8791 x,y,&mask);
8792}
8793
8794/*
8795%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8796% %
8797% %
8798% %
8799% X R e f r e s h W i n d o w %
8800% %
8801% %
8802% %
8803%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8804%
8805% XRefreshWindow() refreshes an image in a X window.
8806%
8807% The format of the XRefreshWindow method is:
8808%
8809% void XRefreshWindow(Display *display,const XWindowInfo *window,
8810% const XEvent *event)
8811%
8812% A description of each parameter follows:
8813%
8814% o display: Specifies a connection to an X server; returned from
8815% XOpenDisplay.
8816%
8817% o window: Specifies a pointer to a XWindowInfo structure.
8818%
8819% o event: Specifies a pointer to a XEvent structure. If it is NULL,
8820% the entire image is refreshed.
8821%
8822*/
cristybcbda3f2011-09-03 13:01:22 +00008823MagickPrivate void XRefreshWindow(Display *display,const XWindowInfo *window,
cristy3ed852e2009-09-05 21:47:34 +00008824 const XEvent *event)
8825{
8826 int
8827 x,
8828 y;
8829
8830 unsigned int
8831 height,
8832 width;
8833
8834 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
8835 assert(display != (Display *) NULL);
8836 assert(window != (XWindowInfo *) NULL);
8837 if (window->ximage == (XImage *) NULL)
8838 return;
8839 if (event != (XEvent *) NULL)
8840 {
8841 /*
8842 Determine geometry from expose event.
8843 */
8844 x=event->xexpose.x;
8845 y=event->xexpose.y;
8846 width=(unsigned int) event->xexpose.width;
8847 height=(unsigned int) event->xexpose.height;
8848 }
8849 else
8850 {
8851 XEvent
8852 sans_event;
8853
8854 /*
8855 Refresh entire window; discard outstanding expose events.
8856 */
8857 x=0;
8858 y=0;
8859 width=window->width;
8860 height=window->height;
8861 while (XCheckTypedWindowEvent(display,window->id,Expose,&sans_event)) ;
cristya0e5ad52010-02-10 02:05:12 +00008862 if (window->matte_pixmap != (Pixmap) NULL)
8863 {
8864#if defined(MAGICKCORE_HAVE_SHAPE)
8865 if (window->shape != MagickFalse)
8866 XShapeCombineMask(display,window->id,ShapeBounding,0,0,
8867 window->matte_pixmap,ShapeSet);
8868#endif
8869 }
cristy3ed852e2009-09-05 21:47:34 +00008870 }
8871 /*
8872 Check boundary conditions.
8873 */
8874 if ((window->ximage->width-(x+window->x)) < (int) width)
8875 width=(unsigned int) (window->ximage->width-(x+window->x));
8876 if ((window->ximage->height-(y+window->y)) < (int) height)
8877 height=(unsigned int) (window->ximage->height-(y+window->y));
8878 /*
8879 Refresh image.
8880 */
8881 if (window->matte_pixmap != (Pixmap) NULL)
cristya0e5ad52010-02-10 02:05:12 +00008882 (void) XSetClipMask(display,window->annotate_context,window->matte_pixmap);
cristy3ed852e2009-09-05 21:47:34 +00008883 if (window->pixmap != (Pixmap) NULL)
8884 {
8885 if (window->depth > 1)
8886 (void) XCopyArea(display,window->pixmap,window->id,
8887 window->annotate_context,x+window->x,y+window->y,width,height,x,y);
8888 else
8889 (void) XCopyPlane(display,window->pixmap,window->id,
8890 window->highlight_context,x+window->x,y+window->y,width,height,x,y,
8891 1L);
8892 }
8893 else
8894 {
8895#if defined(MAGICKCORE_HAVE_SHARED_MEMORY)
8896 if (window->shared_memory)
8897 (void) XShmPutImage(display,window->id,window->annotate_context,
8898 window->ximage,x+window->x,y+window->y,x,y,width,height,MagickTrue);
8899#endif
8900 if (window->shared_memory == MagickFalse)
8901 (void) XPutImage(display,window->id,window->annotate_context,
8902 window->ximage,x+window->x,y+window->y,x,y,width,height);
8903 }
8904 if (window->matte_pixmap != (Pixmap) NULL)
8905 (void) XSetClipMask(display,window->annotate_context,None);
8906 (void) XFlush(display);
8907}
8908
8909/*
8910%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8911% %
8912% %
8913% %
8914% X R e m o t e C o m m a n d %
8915% %
8916% %
8917% %
8918%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8919%
8920% XRemoteCommand() forces a remote display(1) to display the specified
8921% image filename.
8922%
8923% The format of the XRemoteCommand method is:
8924%
8925% MagickBooleanType XRemoteCommand(Display *display,const char *window,
8926% const char *filename)
8927%
8928% A description of each parameter follows:
8929%
8930% o display: Specifies a connection to an X server; returned from
8931% XOpenDisplay.
8932%
8933% o window: Specifies the name or id of an X window.
8934%
8935% o filename: the name of the image filename to display.
8936%
8937*/
8938MagickExport MagickBooleanType XRemoteCommand(Display *display,
8939 const char *window,const char *filename)
8940{
8941 Atom
8942 remote_atom;
8943
8944 Window
8945 remote_window,
8946 root_window;
8947
8948 assert(filename != (char *) NULL);
8949 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",filename);
8950 if (display == (Display *) NULL)
8951 display=XOpenDisplay((char *) NULL);
8952 if (display == (Display *) NULL)
8953 {
8954 ThrowXWindowException(XServerError,"UnableToOpenXServer",filename);
8955 return(MagickFalse);
8956 }
8957 remote_atom=XInternAtom(display,"IM_PROTOCOLS",MagickFalse);
8958 remote_window=(Window) NULL;
8959 root_window=XRootWindow(display,XDefaultScreen(display));
8960 if (window != (char *) NULL)
8961 {
8962 /*
8963 Search window hierarchy and identify any clients by name or ID.
8964 */
8965 if (isdigit((unsigned char) *window) != 0)
8966 remote_window=XWindowByID(display,root_window,(Window)
8967 strtol((char *) window,(char **) NULL,0));
8968 if (remote_window == (Window) NULL)
8969 remote_window=XWindowByName(display,root_window,window);
8970 }
8971 if (remote_window == (Window) NULL)
8972 remote_window=XWindowByProperty(display,root_window,remote_atom);
8973 if (remote_window == (Window) NULL)
8974 {
8975 ThrowXWindowException(XServerError,"UnableToConnectToRemoteDisplay",
8976 filename);
8977 return(MagickFalse);
8978 }
8979 /*
8980 Send remote command.
8981 */
8982 remote_atom=XInternAtom(display,"IM_REMOTE_COMMAND",MagickFalse);
8983 (void) XChangeProperty(display,remote_window,remote_atom,XA_STRING,8,
8984 PropModeReplace,(unsigned char *) filename,(int) strlen(filename));
8985 (void) XSync(display,MagickFalse);
8986 return(MagickTrue);
8987}
8988
8989/*
8990%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8991% %
8992% %
8993% %
8994% X R e t a i n W i n d o w C o l o r s %
8995% %
8996% %
8997% %
8998%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8999%
9000% XRetainWindowColors() sets X11 color resources on a window. This preserves
9001% the colors associated with an image displayed on the window.
9002%
9003% The format of the XRetainWindowColors method is:
9004%
9005% void XRetainWindowColors(Display *display,const Window window)
9006%
9007% A description of each parameter follows:
9008%
9009% o display: Specifies a connection to an X server; returned from
9010% XOpenDisplay.
9011%
9012% o window: Specifies a pointer to a XWindowInfo structure.
9013%
9014*/
9015MagickExport void XRetainWindowColors(Display *display,const Window window)
9016{
9017 Atom
9018 property;
9019
9020 Pixmap
9021 pixmap;
9022
9023 /*
9024 Put property on the window.
9025 */
9026 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
9027 assert(display != (Display *) NULL);
9028 assert(window != (Window) NULL);
9029 property=XInternAtom(display,"_XSETROOT_ID",MagickFalse);
9030 if (property == (Atom) NULL)
9031 {
9032 ThrowXWindowFatalException(XServerError,"UnableToCreateProperty",
9033 "_XSETROOT_ID");
9034 return;
9035 }
9036 pixmap=XCreatePixmap(display,window,1,1,1);
9037 if (pixmap == (Pixmap) NULL)
9038 {
9039 ThrowXWindowFatalException(XServerError,"UnableToCreateBitmap","");
9040 return;
9041 }
9042 (void) XChangeProperty(display,window,property,XA_PIXMAP,32,PropModeReplace,
9043 (unsigned char *) &pixmap,1);
9044 (void) XSetCloseDownMode(display,RetainPermanent);
9045}
9046
9047/*
9048%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9049% %
9050% %
9051% %
9052% X S e l e c t W i n d o w %
9053% %
9054% %
9055% %
9056%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9057%
9058% XSelectWindow() allows a user to select a window using the mouse. If the
9059% mouse moves, a cropping rectangle is drawn and the extents of the rectangle
9060% is returned in the crop_info structure.
9061%
9062% The format of the XSelectWindow function is:
9063%
9064% target_window=XSelectWindow(display,crop_info)
9065%
9066% A description of each parameter follows:
9067%
9068% o window: XSelectWindow returns the window id.
9069%
9070% o display: Specifies a pointer to the Display structure; returned from
9071% XOpenDisplay.
9072%
9073% o crop_info: Specifies a pointer to a RectangleInfo structure. It
9074% contains the extents of any cropping rectangle.
9075%
cristy3ed852e2009-09-05 21:47:34 +00009076*/
9077static Window XSelectWindow(Display *display,RectangleInfo *crop_info)
9078{
9079#define MinimumCropArea (unsigned int) 9
9080
9081 Cursor
9082 target_cursor;
9083
9084 GC
9085 annotate_context;
9086
9087 int
9088 presses,
9089 x_offset,
9090 y_offset;
9091
9092 Status
9093 status;
9094
9095 Window
9096 root_window,
9097 target_window;
9098
9099 XEvent
9100 event;
9101
9102 XGCValues
9103 context_values;
9104
9105 /*
9106 Initialize graphic context.
9107 */
9108 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
9109 assert(display != (Display *) NULL);
9110 assert(crop_info != (RectangleInfo *) NULL);
9111 root_window=XRootWindow(display,XDefaultScreen(display));
9112 context_values.background=XBlackPixel(display,XDefaultScreen(display));
9113 context_values.foreground=XWhitePixel(display,XDefaultScreen(display));
9114 context_values.function=GXinvert;
9115 context_values.plane_mask=
9116 context_values.background ^ context_values.foreground;
9117 context_values.subwindow_mode=IncludeInferiors;
cristybb503372010-05-27 20:51:26 +00009118 annotate_context=XCreateGC(display,root_window,(size_t) (GCBackground |
cristy3ed852e2009-09-05 21:47:34 +00009119 GCForeground | GCFunction | GCSubwindowMode),&context_values);
9120 if (annotate_context == (GC) NULL)
9121 return(MagickFalse);
9122 /*
9123 Grab the pointer using target cursor.
9124 */
9125 target_cursor=XMakeCursor(display,root_window,XDefaultColormap(display,
9126 XDefaultScreen(display)),(char * ) "white",(char * ) "black");
9127 status=XGrabPointer(display,root_window,MagickFalse,(unsigned int)
9128 (ButtonPressMask | ButtonReleaseMask | ButtonMotionMask),GrabModeSync,
9129 GrabModeAsync,root_window,target_cursor,CurrentTime);
9130 if (status != GrabSuccess)
9131 {
9132 ThrowXWindowFatalException(XServerError,"UnableToGrabMouse","");
9133 return((Window) NULL);
9134 }
9135 /*
9136 Select a window.
9137 */
9138 crop_info->width=0;
9139 crop_info->height=0;
9140 presses=0;
9141 target_window=(Window) NULL;
9142 x_offset=0;
9143 y_offset=0;
9144 do
9145 {
9146 if ((crop_info->width*crop_info->height) >= MinimumCropArea)
9147 (void) XDrawRectangle(display,root_window,annotate_context,
9148 (int) crop_info->x,(int) crop_info->y,(unsigned int) crop_info->width-1,
9149 (unsigned int) crop_info->height-1);
9150 /*
9151 Allow another event.
9152 */
9153 (void) XAllowEvents(display,SyncPointer,CurrentTime);
9154 (void) XWindowEvent(display,root_window,ButtonPressMask |
9155 ButtonReleaseMask | ButtonMotionMask,&event);
9156 if ((crop_info->width*crop_info->height) >= MinimumCropArea)
9157 (void) XDrawRectangle(display,root_window,annotate_context,
9158 (int) crop_info->x,(int) crop_info->y,(unsigned int) crop_info->width-1,
9159 (unsigned int) crop_info->height-1);
9160 switch (event.type)
9161 {
9162 case ButtonPress:
9163 {
9164 target_window=XGetSubwindow(display,event.xbutton.subwindow,
9165 event.xbutton.x,event.xbutton.y);
9166 if (target_window == (Window) NULL)
9167 target_window=root_window;
9168 x_offset=event.xbutton.x_root;
9169 y_offset=event.xbutton.y_root;
cristyecd0ab52010-05-30 14:59:20 +00009170 crop_info->x=(ssize_t) x_offset;
9171 crop_info->y=(ssize_t) y_offset;
cristy3ed852e2009-09-05 21:47:34 +00009172 crop_info->width=0;
9173 crop_info->height=0;
9174 presses++;
9175 break;
9176 }
9177 case ButtonRelease:
9178 {
9179 presses--;
9180 break;
9181 }
9182 case MotionNotify:
9183 {
9184 /*
9185 Discard pending button motion events.
9186 */
9187 while (XCheckMaskEvent(display,ButtonMotionMask,&event)) ;
cristyecd0ab52010-05-30 14:59:20 +00009188 crop_info->x=(ssize_t) event.xmotion.x;
9189 crop_info->y=(ssize_t) event.xmotion.y;
cristy3ed852e2009-09-05 21:47:34 +00009190 /*
9191 Check boundary conditions.
9192 */
9193 if ((int) crop_info->x < x_offset)
cristyecd0ab52010-05-30 14:59:20 +00009194 crop_info->width=(size_t) (x_offset-crop_info->x);
cristy3ed852e2009-09-05 21:47:34 +00009195 else
9196 {
cristyecd0ab52010-05-30 14:59:20 +00009197 crop_info->width=(size_t) (crop_info->x-x_offset);
9198 crop_info->x=(ssize_t) x_offset;
cristy3ed852e2009-09-05 21:47:34 +00009199 }
9200 if ((int) crop_info->y < y_offset)
cristyecd0ab52010-05-30 14:59:20 +00009201 crop_info->height=(size_t) (y_offset-crop_info->y);
cristy3ed852e2009-09-05 21:47:34 +00009202 else
9203 {
cristyecd0ab52010-05-30 14:59:20 +00009204 crop_info->height=(size_t) (crop_info->y-y_offset);
9205 crop_info->y=(ssize_t) y_offset;
cristy3ed852e2009-09-05 21:47:34 +00009206 }
9207 }
9208 default:
9209 break;
9210 }
9211 } while ((target_window == (Window) NULL) || (presses > 0));
9212 (void) XUngrabPointer(display,CurrentTime);
9213 (void) XFreeCursor(display,target_cursor);
9214 (void) XFreeGC(display,annotate_context);
9215 if ((crop_info->width*crop_info->height) < MinimumCropArea)
9216 {
9217 crop_info->width=0;
9218 crop_info->height=0;
9219 }
9220 if ((crop_info->width != 0) && (crop_info->height != 0))
9221 target_window=root_window;
9222 return(target_window);
9223}
9224
9225/*
9226%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9227% %
9228% %
9229% %
9230% X S e t C u r s o r S t a t e %
9231% %
9232% %
9233% %
9234%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9235%
9236% XSetCursorState() sets the cursor state to busy, otherwise the cursor are
9237% reset to their default.
9238%
9239% The format of the XXSetCursorState method is:
9240%
9241% XSetCursorState(display,windows,const MagickStatusType state)
9242%
9243% A description of each parameter follows:
9244%
9245% o display: Specifies a connection to an X server; returned from
9246% XOpenDisplay.
9247%
9248% o windows: Specifies a pointer to a XWindows structure.
9249%
9250% o state: An unsigned integer greater than 0 sets the cursor state
9251% to busy, otherwise the cursor are reset to their default.
9252%
9253*/
cristybcbda3f2011-09-03 13:01:22 +00009254MagickPrivate void XSetCursorState(Display *display,XWindows *windows,
cristy3ed852e2009-09-05 21:47:34 +00009255 const MagickStatusType state)
9256{
9257 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
9258 assert(display != (Display *) NULL);
9259 assert(windows != (XWindows *) NULL);
9260 if (state)
9261 {
9262 (void) XCheckDefineCursor(display,windows->image.id,
9263 windows->image.busy_cursor);
9264 (void) XCheckDefineCursor(display,windows->pan.id,
9265 windows->pan.busy_cursor);
9266 (void) XCheckDefineCursor(display,windows->magnify.id,
9267 windows->magnify.busy_cursor);
9268 (void) XCheckDefineCursor(display,windows->command.id,
9269 windows->command.busy_cursor);
9270 }
9271 else
9272 {
9273 (void) XCheckDefineCursor(display,windows->image.id,
9274 windows->image.cursor);
9275 (void) XCheckDefineCursor(display,windows->pan.id,windows->pan.cursor);
9276 (void) XCheckDefineCursor(display,windows->magnify.id,
9277 windows->magnify.cursor);
9278 (void) XCheckDefineCursor(display,windows->command.id,
9279 windows->command.cursor);
9280 (void) XCheckDefineCursor(display,windows->command.id,
9281 windows->widget.cursor);
9282 (void) XWithdrawWindow(display,windows->info.id,windows->info.screen);
9283 }
9284 windows->info.mapped=MagickFalse;
9285}
9286
9287/*
9288%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9289% %
9290% %
9291% %
9292% X S e t W i n d o w s %
9293% %
9294% %
9295% %
9296%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9297%
9298% XSetWindows() sets the X windows structure if the windows info is specified.
9299% Otherwise the current windows structure is returned.
9300%
9301% The format of the XSetWindows method is:
9302%
9303% XWindows *XSetWindows(XWindows *windows_info)
9304%
9305% A description of each parameter follows:
9306%
9307% o windows_info: Initialize the Windows structure with this information.
9308%
9309*/
cristybcbda3f2011-09-03 13:01:22 +00009310MagickPrivate XWindows *XSetWindows(XWindows *windows_info)
cristy3ed852e2009-09-05 21:47:34 +00009311{
9312 static XWindows
9313 *windows = (XWindows *) NULL;
9314
9315 if (windows_info != (XWindows *) ~0)
9316 {
9317 windows=(XWindows *) RelinquishMagickMemory(windows);
9318 windows=windows_info;
9319 }
9320 return(windows);
9321}
9322/*
9323%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9324% %
9325% %
9326% %
9327% X U s e r P r e f e r e n c e s %
9328% %
9329% %
9330% %
9331%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9332%
9333% XUserPreferences() saves the preferences in a configuration file in the
9334% users' home directory.
9335%
9336% The format of the XUserPreferences method is:
9337%
9338% void XUserPreferences(XResourceInfo *resource_info)
9339%
9340% A description of each parameter follows:
9341%
9342% o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
9343%
9344*/
cristybcbda3f2011-09-03 13:01:22 +00009345MagickPrivate void XUserPreferences(XResourceInfo *resource_info)
cristy3ed852e2009-09-05 21:47:34 +00009346{
9347#if defined(X11_PREFERENCES_PATH)
9348 char
9349 cache[MaxTextExtent],
9350 filename[MaxTextExtent],
9351 specifier[MaxTextExtent];
9352
9353 const char
cristy104cea82009-10-25 02:26:51 +00009354 *client_name,
cristy3ed852e2009-09-05 21:47:34 +00009355 *value;
9356
9357 XrmDatabase
9358 preferences_database;
9359
9360 /*
9361 Save user preferences to the client configuration file.
9362 */
9363 assert(resource_info != (XResourceInfo *) NULL);
cristy104cea82009-10-25 02:26:51 +00009364 client_name=GetClientName();
cristy3ed852e2009-09-05 21:47:34 +00009365 preferences_database=XrmGetStringDatabase("");
cristyb51dff52011-05-19 16:55:47 +00009366 (void) FormatLocaleString(specifier,MaxTextExtent,"%s.backdrop",client_name);
cristy3ed852e2009-09-05 21:47:34 +00009367 value=resource_info->backdrop ? "True" : "False";
9368 XrmPutStringResource(&preferences_database,specifier,(char *) value);
cristyb51dff52011-05-19 16:55:47 +00009369 (void) FormatLocaleString(specifier,MaxTextExtent,"%s.colormap",client_name);
cristy3ed852e2009-09-05 21:47:34 +00009370 value=resource_info->colormap == SharedColormap ? "Shared" : "Private";
9371 XrmPutStringResource(&preferences_database,specifier,(char *) value);
cristyb51dff52011-05-19 16:55:47 +00009372 (void) FormatLocaleString(specifier,MaxTextExtent,"%s.confirmExit",
cristy104cea82009-10-25 02:26:51 +00009373 client_name);
cristy3ed852e2009-09-05 21:47:34 +00009374 value=resource_info->confirm_exit ? "True" : "False";
9375 XrmPutStringResource(&preferences_database,specifier,(char *) value);
cristyb51dff52011-05-19 16:55:47 +00009376 (void) FormatLocaleString(specifier,MaxTextExtent,"%s.confirmEdit",
cristy104cea82009-10-25 02:26:51 +00009377 client_name);
cristy3ed852e2009-09-05 21:47:34 +00009378 value=resource_info->confirm_edit ? "True" : "False";
9379 XrmPutStringResource(&preferences_database,specifier,(char *) value);
cristyb51dff52011-05-19 16:55:47 +00009380 (void) FormatLocaleString(specifier,MaxTextExtent,"%s.displayWarnings",
cristy104cea82009-10-25 02:26:51 +00009381 client_name);
cristy3ed852e2009-09-05 21:47:34 +00009382 value=resource_info->display_warnings ? "True" : "False";
9383 XrmPutStringResource(&preferences_database,specifier,(char *) value);
cristyb51dff52011-05-19 16:55:47 +00009384 (void) FormatLocaleString(specifier,MaxTextExtent,"%s.dither",client_name);
cristy3ed852e2009-09-05 21:47:34 +00009385 value=resource_info->quantize_info->dither ? "True" : "False";
9386 XrmPutStringResource(&preferences_database,specifier,(char *) value);
cristyb51dff52011-05-19 16:55:47 +00009387 (void) FormatLocaleString(specifier,MaxTextExtent,"%s.gammaCorrect",
cristy104cea82009-10-25 02:26:51 +00009388 client_name);
cristy3ed852e2009-09-05 21:47:34 +00009389 value=resource_info->gamma_correct ? "True" : "False";
9390 XrmPutStringResource(&preferences_database,specifier,(char *) value);
cristyb51dff52011-05-19 16:55:47 +00009391 (void) FormatLocaleString(specifier,MaxTextExtent,"%s.undoCache",client_name);
9392 (void) FormatLocaleString(cache,MaxTextExtent,"%.20g",(double)
cristy3ed852e2009-09-05 21:47:34 +00009393 resource_info->undo_cache);
9394 XrmPutStringResource(&preferences_database,specifier,cache);
cristyb51dff52011-05-19 16:55:47 +00009395 (void) FormatLocaleString(specifier,MaxTextExtent,"%s.usePixmap",client_name);
cristy3ed852e2009-09-05 21:47:34 +00009396 value=resource_info->use_pixmap ? "True" : "False";
9397 XrmPutStringResource(&preferences_database,specifier,(char *) value);
cristyb51dff52011-05-19 16:55:47 +00009398 (void) FormatLocaleString(filename,MaxTextExtent,"%s%src",
cristy104cea82009-10-25 02:26:51 +00009399 X11_PREFERENCES_PATH,client_name);
cristy3ed852e2009-09-05 21:47:34 +00009400 ExpandFilename(filename);
9401 XrmPutFileDatabase(preferences_database,filename);
9402#endif
9403}
9404
9405/*
9406%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9407% %
9408% %
9409% %
9410% X V i s u a l C l a s s N a m e %
9411% %
9412% %
9413% %
9414%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9415%
9416% XVisualClassName() returns the visual class name as a character string.
9417%
9418% The format of the XVisualClassName method is:
9419%
9420% char *XVisualClassName(const int visual_class)
9421%
9422% A description of each parameter follows:
9423%
9424% o visual_type: XVisualClassName returns the visual class as a character
9425% string.
9426%
9427% o class: Specifies the visual class.
9428%
cristy3ed852e2009-09-05 21:47:34 +00009429*/
9430static const char *XVisualClassName(const int visual_class)
9431{
9432 switch (visual_class)
9433 {
9434 case StaticGray: return("StaticGray");
9435 case GrayScale: return("GrayScale");
9436 case StaticColor: return("StaticColor");
9437 case PseudoColor: return("PseudoColor");
9438 case TrueColor: return("TrueColor");
9439 case DirectColor: return("DirectColor");
9440 }
9441 return("unknown visual class");
9442}
9443
9444/*
9445%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9446% %
9447% %
9448% %
9449% X W a r n i n g %
9450% %
9451% %
9452% %
9453%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9454%
9455% XWarning() displays a warning reason in a Notice widget.
9456%
9457% The format of the XWarning method is:
9458%
9459% void XWarning(const unsigned int warning,const char *reason,
9460% const char *description)
9461%
9462% A description of each parameter follows:
9463%
9464% o warning: Specifies the numeric warning category.
9465%
9466% o reason: Specifies the reason to display before terminating the
9467% program.
9468%
9469% o description: Specifies any description to the reason.
9470%
9471*/
cristybcbda3f2011-09-03 13:01:22 +00009472MagickPrivate void XWarning(const ExceptionType magick_unused(warning),
cristy3ed852e2009-09-05 21:47:34 +00009473 const char *reason,const char *description)
9474{
9475 char
9476 text[MaxTextExtent];
9477
9478 XWindows
9479 *windows;
9480
9481 if (reason == (char *) NULL)
9482 return;
9483 (void) CopyMagickString(text,reason,MaxTextExtent);
9484 (void) ConcatenateMagickString(text,":",MaxTextExtent);
9485 windows=XSetWindows((XWindows *) ~0);
9486 XNoticeWidget(windows->display,windows,text,(char *) description);
9487}
9488
9489/*
9490%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9491% %
9492% %
9493% %
9494% X W i n d o w B y I D %
9495% %
9496% %
9497% %
9498%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9499%
9500% XWindowByID() locates a child window with a given ID. If not window with
9501% the given name is found, 0 is returned. Only the window specified and its
9502% subwindows are searched.
9503%
9504% The format of the XWindowByID function is:
9505%
9506% child=XWindowByID(display,window,id)
9507%
9508% A description of each parameter follows:
9509%
9510% o child: XWindowByID returns the window with the specified
9511% id. If no windows are found, XWindowByID returns 0.
9512%
9513% o display: Specifies a pointer to the Display structure; returned from
9514% XOpenDisplay.
9515%
9516% o id: Specifies the id of the window to locate.
9517%
9518*/
cristybcbda3f2011-09-03 13:01:22 +00009519MagickPrivate Window XWindowByID(Display *display,const Window root_window,
cristybb503372010-05-27 20:51:26 +00009520 const size_t id)
cristy3ed852e2009-09-05 21:47:34 +00009521{
9522 RectangleInfo
9523 rectangle_info;
9524
9525 register int
9526 i;
9527
9528 Status
9529 status;
9530
9531 unsigned int
9532 number_children;
9533
9534 Window
9535 child,
9536 *children,
9537 window;
9538
9539 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
9540 assert(display != (Display *) NULL);
9541 assert(root_window != (Window) NULL);
9542 if (id == 0)
9543 return(XSelectWindow(display,&rectangle_info));
9544 if (root_window == id)
cristydfe2b662010-08-22 16:17:24 +00009545 return(root_window);
cristy3ed852e2009-09-05 21:47:34 +00009546 status=XQueryTree(display,root_window,&child,&child,&children,
9547 &number_children);
9548 if (status == False)
9549 return((Window) NULL);
9550 window=(Window) NULL;
9551 for (i=0; i < (int) number_children; i++)
9552 {
9553 /*
9554 Search each child and their children.
9555 */
9556 window=XWindowByID(display,children[i],id);
9557 if (window != (Window) NULL)
9558 break;
9559 }
9560 if (children != (Window *) NULL)
9561 (void) XFree((void *) children);
9562 return(window);
9563}
9564
9565/*
9566%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9567% %
9568% %
9569% %
9570% X W i n d o w B y N a m e %
9571% %
9572% %
9573% %
9574%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9575%
9576% XWindowByName() locates a window with a given name on a display. If no
9577% window with the given name is found, 0 is returned. If more than one window
9578% has the given name, the first one is returned. Only root and its children
9579% are searched.
9580%
9581% The format of the XWindowByName function is:
9582%
9583% window=XWindowByName(display,root_window,name)
9584%
9585% A description of each parameter follows:
9586%
9587% o window: XWindowByName returns the window id.
9588%
9589% o display: Specifies a pointer to the Display structure; returned from
9590% XOpenDisplay.
9591%
9592% o root_window: Specifies the id of the root window.
9593%
9594% o name: Specifies the name of the window to locate.
9595%
9596*/
cristybcbda3f2011-09-03 13:01:22 +00009597MagickPrivate Window XWindowByName(Display *display,const Window root_window,
cristy3ed852e2009-09-05 21:47:34 +00009598 const char *name)
9599{
9600 register int
9601 i;
9602
9603 Status
9604 status;
9605
9606 unsigned int
9607 number_children;
9608
9609 Window
9610 *children,
9611 child,
9612 window;
9613
9614 XTextProperty
9615 window_name;
9616
9617 assert(display != (Display *) NULL);
9618 assert(root_window != (Window) NULL);
9619 assert(name != (char *) NULL);
9620 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",name);
9621 if (XGetWMName(display,root_window,&window_name) != 0)
9622 if (LocaleCompare((char *) window_name.value,name) == 0)
9623 return(root_window);
9624 status=XQueryTree(display,root_window,&child,&child,&children,
9625 &number_children);
9626 if (status == False)
9627 return((Window) NULL);
9628 window=(Window) NULL;
9629 for (i=0; i < (int) number_children; i++)
9630 {
9631 /*
9632 Search each child and their children.
9633 */
9634 window=XWindowByName(display,children[i],name);
9635 if (window != (Window) NULL)
9636 break;
9637 }
9638 if (children != (Window *) NULL)
9639 (void) XFree((void *) children);
9640 return(window);
9641}
9642
9643/*
9644%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9645% %
9646% %
9647% %
9648% X W i n d o w B y P r o p e r y %
9649% %
9650% %
9651% %
9652%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9653%
9654% XWindowByProperty() locates a child window with a given property. If not
9655% window with the given name is found, 0 is returned. If more than one window
9656% has the given property, the first one is returned. Only the window
9657% specified and its subwindows are searched.
9658%
9659% The format of the XWindowByProperty function is:
9660%
9661% child=XWindowByProperty(display,window,property)
9662%
9663% A description of each parameter follows:
9664%
9665% o child: XWindowByProperty returns the window id with the specified
9666% property. If no windows are found, XWindowByProperty returns 0.
9667%
9668% o display: Specifies a pointer to the Display structure; returned from
9669% XOpenDisplay.
9670%
9671% o property: Specifies the property of the window to locate.
9672%
9673*/
cristybcbda3f2011-09-03 13:01:22 +00009674MagickPrivate Window XWindowByProperty(Display *display,const Window window,
cristy3ed852e2009-09-05 21:47:34 +00009675 const Atom property)
9676{
9677 Atom
9678 type;
9679
9680 int
9681 format;
9682
9683 Status
9684 status;
9685
9686 unsigned char
9687 *data;
9688
9689 unsigned int
9690 i,
9691 number_children;
9692
cristyf2faecf2010-05-28 19:19:36 +00009693 unsigned long
cristy3ed852e2009-09-05 21:47:34 +00009694 after,
9695 number_items;
9696
9697 Window
9698 child,
9699 *children,
9700 parent,
9701 root;
9702
9703 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
9704 assert(display != (Display *) NULL);
9705 assert(window != (Window) NULL);
9706 assert(property != (Atom) NULL);
9707 status=XQueryTree(display,window,&root,&parent,&children,&number_children);
9708 if (status == False)
9709 return((Window) NULL);
9710 type=(Atom) NULL;
9711 child=(Window) NULL;
9712 for (i=0; (i < number_children) && (child == (Window) NULL); i++)
9713 {
9714 status=XGetWindowProperty(display,children[i],property,0L,0L,MagickFalse,
9715 (Atom) AnyPropertyType,&type,&format,&number_items,&after,&data);
9716 if (data != NULL)
9717 (void) XFree((void *) data);
9718 if ((status == Success) && (type != (Atom) NULL))
9719 child=children[i];
9720 }
9721 for (i=0; (i < number_children) && (child == (Window) NULL); i++)
9722 child=XWindowByProperty(display,children[i],property);
9723 if (children != (Window *) NULL)
9724 (void) XFree((void *) children);
9725 return(child);
9726}
9727#else
9728
9729/*
9730%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9731% %
9732% %
9733% %
9734% X I m p o r t I m a g e %
9735% %
9736% %
9737% %
9738%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9739%
9740% XImportImage() reads an image from an X window.
9741%
9742% The format of the XImportImage method is:
9743%
cristya0dc96a2011-12-19 23:58:54 +00009744% Image *XImportImage(const ImageInfo *image_info,XImportInfo *ximage_info,
9745% ExceptionInfo *exception)
cristy3ed852e2009-09-05 21:47:34 +00009746%
9747% A description of each parameter follows:
9748%
9749% o image_info: the image info..
9750%
9751% o ximage_info: Specifies a pointer to an XImportInfo structure.
9752%
cristya0dc96a2011-12-19 23:58:54 +00009753% o exception: return any errors or warnings in this structure.
9754%
cristy3ed852e2009-09-05 21:47:34 +00009755*/
cristybcbda3f2011-09-03 13:01:22 +00009756MagickPrivate Image *XImportImage(const ImageInfo *image_info,
cristya0dc96a2011-12-19 23:58:54 +00009757 XImportInfo *ximage_info,ExceptionInfo *exception)
cristy3ed852e2009-09-05 21:47:34 +00009758{
9759 assert(image_info != (const ImageInfo *) NULL);
9760 assert(image_info->signature == MagickSignature);
9761 if (image_info->debug != MagickFalse)
9762 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
9763 image_info->filename);
9764 assert(ximage_info != (XImportInfo *) NULL);
cristya0dc96a2011-12-19 23:58:54 +00009765 assert(exception != (ExceptionInfo *) NULL);
9766 assert(exception->signature == MagickSignature);
cristy3ed852e2009-09-05 21:47:34 +00009767 return((Image *) NULL);
9768}
9769#endif
9770
9771/*
9772%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9773% %
9774% %
9775% %
cristy576974e2009-10-25 20:45:31 +00009776+ X C o m p o n e n t G e n e s i s %
9777% %
9778% %
9779% %
9780%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9781%
9782% XComponentGenesis() instantiates the X component.
9783%
9784% The format of the XComponentGenesis method is:
9785%
9786% MagickBooleanType XComponentGenesis(void)
9787%
9788*/
cristy5ff4eaf2011-09-03 01:38:02 +00009789MagickPrivate MagickBooleanType XComponentGenesis(void)
cristy576974e2009-10-25 20:45:31 +00009790{
9791 return(MagickTrue);
9792}
9793
9794/*
9795%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9796% %
9797% %
9798% %
cristy3ed852e2009-09-05 21:47:34 +00009799% X G e t I m p o r t I n f o %
9800% %
9801% %
9802% %
9803%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9804%
9805% XGetImportInfo() initializes the XImportInfo structure.
9806%
9807% The format of the XGetImportInfo method is:
9808%
9809% void XGetImportInfo(XImportInfo *ximage_info)
9810%
9811% A description of each parameter follows:
9812%
9813% o ximage_info: Specifies a pointer to an ImageInfo structure.
9814%
9815*/
9816MagickExport void XGetImportInfo(XImportInfo *ximage_info)
9817{
9818 assert(ximage_info != (XImportInfo *) NULL);
9819 ximage_info->frame=MagickFalse;
9820 ximage_info->borders=MagickFalse;
9821 ximage_info->screen=MagickFalse;
9822 ximage_info->descend=MagickTrue;
9823 ximage_info->silent=MagickFalse;
9824}