blob: 99bad6718778e5754f0012b11d6c2e210e009f49 [file] [log] [blame]
cristy3ed852e2009-09-05 21:47:34 +00001/*
2%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3% %
4% %
5% %
6% X X W W IIIII N N DDDD OOO W W %
7% X X W W I NN N D D O O W W %
8% X W W I N N N D D O O W W %
9% X X W W W I N NN D D O O W W W %
10% X X W W IIIII N N DDDD OOO W W %
11% %
12% %
13% MagickCore X11 Utility Methods %
14% %
15% Software Design %
16% John Cristy %
17% July 1992 %
18% %
19% %
cristy1454be72011-12-19 01:52:48 +000020% Copyright 1999-2012 ImageMagick Studio LLC, a non-profit organization %
cristy3ed852e2009-09-05 21:47:34 +000021% dedicated to making software imaging solutions freely available. %
22% %
23% You may not use this file except in compliance with the License. You may %
24% obtain a copy of the License at %
25% %
26% http://www.imagemagick.org/script/license.php %
27% %
28% Unless required by applicable law or agreed to in writing, software %
29% distributed under the License is distributed on an "AS IS" BASIS, %
30% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. %
31% See the License for the specific language governing permissions and %
32% limitations under the License. %
33% %
34%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
35%
36%
37*/
38
39/*
40 Include declarations.
41*/
cristy4c08aed2011-07-01 19:47:50 +000042#include "MagickCore/studio.h"
43#include "MagickCore/animate.h"
44#include "MagickCore/artifact.h"
45#include "MagickCore/blob.h"
46#include "MagickCore/cache.h"
47#include "MagickCore/client.h"
48#include "MagickCore/color.h"
49#include "MagickCore/color-private.h"
50#include "MagickCore/colormap.h"
51#include "MagickCore/composite.h"
cristy030436f2012-01-06 21:56:17 +000052#include "MagickCore/constitute.h"
cristy4c08aed2011-07-01 19:47:50 +000053#include "MagickCore/display.h"
cristyc53413d2011-11-17 13:04:26 +000054#include "MagickCore/distort.h"
cristy4c08aed2011-07-01 19:47:50 +000055#include "MagickCore/exception.h"
56#include "MagickCore/exception-private.h"
57#include "MagickCore/geometry.h"
58#include "MagickCore/identify.h"
59#include "MagickCore/image.h"
60#include "MagickCore/image-private.h"
61#include "MagickCore/list.h"
62#include "MagickCore/locale_.h"
63#include "MagickCore/log.h"
64#include "MagickCore/magick.h"
65#include "MagickCore/memory_.h"
66#include "MagickCore/monitor.h"
cristy2c5fc272012-02-22 01:27:46 +000067#include "MagickCore/nt-base-private.h"
cristy4c08aed2011-07-01 19:47:50 +000068#include "MagickCore/option.h"
69#include "MagickCore/pixel-accessor.h"
70#include "MagickCore/PreRvIcccm.h"
71#include "MagickCore/quantize.h"
72#include "MagickCore/quantum.h"
73#include "MagickCore/quantum-private.h"
74#include "MagickCore/resource_.h"
75#include "MagickCore/resize.h"
cristy4c08aed2011-07-01 19:47:50 +000076#include "MagickCore/statistic.h"
77#include "MagickCore/string_.h"
78#include "MagickCore/string-private.h"
79#include "MagickCore/transform.h"
80#include "MagickCore/utility.h"
cristyd1dd6e42011-09-04 01:46:08 +000081#include "MagickCore/utility-private.h"
cristy4c08aed2011-07-01 19:47:50 +000082#include "MagickCore/widget.h"
cristybcbda3f2011-09-03 13:01:22 +000083#include "MagickCore/widget-private.h"
cristy4c08aed2011-07-01 19:47:50 +000084#include "MagickCore/xwindow.h"
85#include "MagickCore/xwindow-private.h"
86#include "MagickCore/version.h"
cristy3ed852e2009-09-05 21:47:34 +000087#if defined(__BEOS__)
88#include <OS.h>
89#endif
90#if defined(MAGICKCORE_X11_DELEGATE)
91#include <X11/Xproto.h>
92#include <X11/Xlocale.h>
93#if defined(MAGICK_HAVE_POLL)
94# include <sys/poll.h>
95#endif
96#if defined(MAGICKCORE_HAVE_SHARED_MEMORY)
97#if defined(MAGICKCORE_HAVE_MACHINE_PARAM_H)
98# include <machine/param.h>
99#endif
100#include <sys/ipc.h>
101#include <sys/shm.h>
102#include <X11/extensions/XShm.h>
103#endif
104#if defined(MAGICKCORE_HAVE_SHAPE)
105#include <X11/extensions/shape.h>
106#endif
107
108/*
109 X defines.
110*/
cristyce70c172010-01-07 17:15:30 +0000111#define XBlueGamma(color) ClampToQuantum(blue_gamma == 1.0 ? (double) \
cristy3ed852e2009-09-05 21:47:34 +0000112 (color) : ((pow(((double) QuantumScale*(color)),1.0/(double) blue_gamma)* \
113 QuantumRange)))
cristy4c08aed2011-07-01 19:47:50 +0000114#define XGammaPacket(map,color) (size_t) (map->base_pixel+ \
cristy7e9f2332011-04-22 23:12:22 +0000115 ((ScaleQuantumToShort(XRedGamma((color)->red))*map->red_max/65535L)* \
116 map->red_mult)+ \
117 ((ScaleQuantumToShort(XGreenGamma((color)->green))*map->green_max/65535L)* \
118 map->green_mult)+ \
119 ((ScaleQuantumToShort(XBlueGamma((color)->blue))*map->blue_max/65535L)* \
120 map->blue_mult))
cristy4c08aed2011-07-01 19:47:50 +0000121#define XGammaPixel(image,map,color) (size_t) (map->base_pixel+ \
122 ((ScaleQuantumToShort(XRedGamma(GetPixelRed(image,color)))*map->red_max/65535L)* \
123 map->red_mult)+ \
124 ((ScaleQuantumToShort(XGreenGamma(GetPixelGreen(image,color)))*map->green_max/65535L)* \
125 map->green_mult)+ \
126 ((ScaleQuantumToShort(XBlueGamma(GetPixelBlue(image,color)))*map->blue_max/65535L)* \
127 map->blue_mult))
cristyce70c172010-01-07 17:15:30 +0000128#define XGreenGamma(color) ClampToQuantum(green_gamma == 1.0 ? (double) \
cristy3ed852e2009-09-05 21:47:34 +0000129 (color) : ((pow(((double) QuantumScale*(color)),1.0/(double) green_gamma)* \
130 QuantumRange)))
cristyce70c172010-01-07 17:15:30 +0000131#define XRedGamma(color) ClampToQuantum(red_gamma == 1.0 ? (double) \
cristy3ed852e2009-09-05 21:47:34 +0000132 (color) : ((pow(((double) QuantumScale*(color)),1.0/(double) red_gamma)* \
133 QuantumRange)))
cristybb503372010-05-27 20:51:26 +0000134#define XStandardPixel(map,color) (size_t) (map->base_pixel+ \
cristy7e9f2332011-04-22 23:12:22 +0000135 (((color)->red*map->red_max/65535L)*map->red_mult)+ \
136 (((color)->green*map->green_max/65535L)*map->green_mult)+ \
137 (((color)->blue*map->blue_max/65535L)*map->blue_mult))
cristy3ed852e2009-09-05 21:47:34 +0000138
139#define AccentuateModulate ScaleCharToQuantum(80)
140#define HighlightModulate ScaleCharToQuantum(125)
141#define ShadowModulate ScaleCharToQuantum(135)
142#define DepthModulate ScaleCharToQuantum(185)
143#define TroughModulate ScaleCharToQuantum(110)
144
145#define XLIB_ILLEGAL_ACCESS 1
146#undef ForgetGravity
147#undef NorthWestGravity
148#undef NorthGravity
149#undef NorthEastGravity
150#undef WestGravity
151#undef CenterGravity
152#undef EastGravity
153#undef SouthWestGravity
154#undef SouthGravity
155#undef SouthEastGravity
156#undef StaticGravity
157
158#undef index
159#if defined(hpux9)
160#define XFD_SET int
161#else
162#define XFD_SET fd_set
163#endif
164
165/*
166 Enumeration declarations.
167*/
168typedef enum
169{
170#undef DoRed
171 DoRed = 0x0001,
172#undef DoGreen
173 DoGreen = 0x0002,
174#undef DoBlue
175 DoBlue = 0x0004,
176 DoMatte = 0x0008
177} XColorFlags;
178
179/*
180 Typedef declarations.
181*/
182typedef struct _DiversityPacket
183{
184 Quantum
185 red,
186 green,
187 blue;
188
189 unsigned short
190 index;
191
cristybb503372010-05-27 20:51:26 +0000192 size_t
cristy3ed852e2009-09-05 21:47:34 +0000193 count;
194} DiversityPacket;
195
196/*
197 Constant declaractions.
198*/
199static MagickBooleanType
200 xerror_alert = MagickFalse;
201
202/*
203 Method prototypes.
204*/
205static const char
206 *XVisualClassName(const int);
207
208static MagickRealType
209 blue_gamma = 1.0,
210 green_gamma = 1.0,
211 red_gamma = 1.0;
212
213static MagickBooleanType
214 XMakePixmap(Display *,const XResourceInfo *,XWindowInfo *);
215
216static void
217 XMakeImageLSBFirst(const XResourceInfo *,const XWindowInfo *,Image *,
cristye941a752011-10-15 01:52:48 +0000218 XImage *,XImage *,ExceptionInfo *),
cristy3ed852e2009-09-05 21:47:34 +0000219 XMakeImageMSBFirst(const XResourceInfo *,const XWindowInfo *,Image *,
cristye941a752011-10-15 01:52:48 +0000220 XImage *,XImage *,ExceptionInfo *);
cristy3ed852e2009-09-05 21:47:34 +0000221
222static Window
223 XSelectWindow(Display *,RectangleInfo *);
224
225/*
226%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
227% %
228% %
229% %
230% D e s t r o y X R e s o u r c e s %
231% %
232% %
233% %
234%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
235%
236% DestroyXResources() destroys any X resources.
237%
238% The format of the DestroyXResources method is:
239%
240% void DestroyXResources()
241%
242% A description of each parameter follows:
243%
244*/
245MagickExport void DestroyXResources(void)
246{
247 register int
248 i;
249
250 unsigned int
251 number_windows;
252
253 XWindowInfo
254 *magick_windows[MaxXWindows];
255
256 XWindows
257 *windows;
258
259 DestroyXWidget();
260 windows=XSetWindows((XWindows *) ~0);
261 if ((windows == (XWindows *) NULL) || (windows->display == (Display *) NULL))
262 return;
263 number_windows=0;
264 magick_windows[number_windows++]=(&windows->context);
265 magick_windows[number_windows++]=(&windows->group_leader);
266 magick_windows[number_windows++]=(&windows->backdrop);
267 magick_windows[number_windows++]=(&windows->icon);
268 magick_windows[number_windows++]=(&windows->image);
269 magick_windows[number_windows++]=(&windows->info);
270 magick_windows[number_windows++]=(&windows->magnify);
271 magick_windows[number_windows++]=(&windows->pan);
272 magick_windows[number_windows++]=(&windows->command);
273 magick_windows[number_windows++]=(&windows->widget);
274 magick_windows[number_windows++]=(&windows->popup);
275 magick_windows[number_windows++]=(&windows->context);
276 for (i=0; i < (int) number_windows; i++)
277 {
278 if (magick_windows[i]->mapped != MagickFalse)
279 {
280 (void) XWithdrawWindow(windows->display,magick_windows[i]->id,
281 magick_windows[i]->screen);
282 magick_windows[i]->mapped=MagickFalse;
283 }
284 if (magick_windows[i]->name != (char *) NULL)
285 magick_windows[i]->name=(char *)
286 RelinquishMagickMemory(magick_windows[i]->name);
287 if (magick_windows[i]->icon_name != (char *) NULL)
288 magick_windows[i]->icon_name=(char *)
289 RelinquishMagickMemory(magick_windows[i]->icon_name);
290 if (magick_windows[i]->cursor != (Cursor) NULL)
291 {
292 (void) XFreeCursor(windows->display,magick_windows[i]->cursor);
293 magick_windows[i]->cursor=(Cursor) NULL;
294 }
295 if (magick_windows[i]->busy_cursor != (Cursor) NULL)
296 {
297 (void) XFreeCursor(windows->display,magick_windows[i]->busy_cursor);
298 magick_windows[i]->busy_cursor=(Cursor) NULL;
299 }
300 if (magick_windows[i]->highlight_stipple != (Pixmap) NULL)
301 {
302 (void) XFreePixmap(windows->display,
303 magick_windows[i]->highlight_stipple);
304 magick_windows[i]->highlight_stipple=(Pixmap) NULL;
305 }
306 if (magick_windows[i]->shadow_stipple != (Pixmap) NULL)
307 {
308 (void) XFreePixmap(windows->display,magick_windows[i]->shadow_stipple);
309 magick_windows[i]->shadow_stipple=(Pixmap) NULL;
310 }
311 if (magick_windows[i]->ximage != (XImage *) NULL)
312 {
313 XDestroyImage(magick_windows[i]->ximage);
314 magick_windows[i]->ximage=(XImage *) NULL;
315 }
316 if (magick_windows[i]->pixmap != (Pixmap) NULL)
317 {
318 (void) XFreePixmap(windows->display,magick_windows[i]->pixmap);
319 magick_windows[i]->pixmap=(Pixmap) NULL;
320 }
321 if (magick_windows[i]->id != (Window) NULL)
322 {
323 (void) XDestroyWindow(windows->display,magick_windows[i]->id);
324 magick_windows[i]->id=(Window) NULL;
325 }
326 if (magick_windows[i]->destroy != MagickFalse)
327 {
328 if (magick_windows[i]->image != (Image *) NULL)
329 {
330 magick_windows[i]->image=DestroyImage(magick_windows[i]->image);
331 magick_windows[i]->image=NewImageList();
332 }
333 if (magick_windows[i]->matte_pixmap != (Pixmap) NULL)
334 {
335 (void) XFreePixmap(windows->display,
336 magick_windows[i]->matte_pixmap);
337 magick_windows[i]->matte_pixmap=(Pixmap) NULL;
338 }
339 }
340 if (magick_windows[i]->segment_info != (void *) NULL)
341 {
342#if defined(MAGICKCORE_HAVE_SHARED_MEMORY)
343 XShmSegmentInfo
344 *segment_info;
345
346 segment_info=(XShmSegmentInfo *) magick_windows[i]->segment_info;
347 if (segment_info != (XShmSegmentInfo *) NULL)
348 if (segment_info[0].shmid >= 0)
349 {
350 if (segment_info[0].shmaddr != NULL)
351 (void) shmdt(segment_info[0].shmaddr);
352 (void) shmctl(segment_info[0].shmid,IPC_RMID,0);
353 segment_info[0].shmaddr=NULL;
354 segment_info[0].shmid=(-1);
355 }
356#endif
357 magick_windows[i]->segment_info=(void *)
358 RelinquishMagickMemory(magick_windows[i]->segment_info);
359 }
360 }
361 windows->icon_resources=(XResourceInfo *)
362 RelinquishMagickMemory(windows->icon_resources);
363 if (windows->icon_pixel != (XPixelInfo *) NULL)
364 {
cristyf2faecf2010-05-28 19:19:36 +0000365 if (windows->icon_pixel->pixels != (unsigned long *) NULL)
366 windows->icon_pixel->pixels=(unsigned long *)
cristy3ed852e2009-09-05 21:47:34 +0000367 RelinquishMagickMemory(windows->icon_pixel->pixels);
368 if (windows->icon_pixel->annotate_context != (GC) NULL)
369 XFreeGC(windows->display,windows->icon_pixel->annotate_context);
370 windows->icon_pixel=(XPixelInfo *)
371 RelinquishMagickMemory(windows->icon_pixel);
372 }
373 if (windows->pixel_info != (XPixelInfo *) NULL)
374 {
cristyf2faecf2010-05-28 19:19:36 +0000375 if (windows->pixel_info->pixels != (unsigned long *) NULL)
376 windows->pixel_info->pixels=(unsigned long *)
cristy3ed852e2009-09-05 21:47:34 +0000377 RelinquishMagickMemory(windows->pixel_info->pixels);
378 if (windows->pixel_info->annotate_context != (GC) NULL)
379 XFreeGC(windows->display,windows->pixel_info->annotate_context);
380 if (windows->pixel_info->widget_context != (GC) NULL)
381 XFreeGC(windows->display,windows->pixel_info->widget_context);
382 if (windows->pixel_info->highlight_context != (GC) NULL)
383 XFreeGC(windows->display,windows->pixel_info->highlight_context);
384 windows->pixel_info=(XPixelInfo *)
385 RelinquishMagickMemory(windows->pixel_info);
386 }
387 if (windows->font_info != (XFontStruct *) NULL)
388 {
389 XFreeFont(windows->display,windows->font_info);
390 windows->font_info=(XFontStruct *) NULL;
391 }
392 if (windows->class_hints != (XClassHint *) NULL)
393 {
cristyc9cc4a72011-09-18 02:12:41 +0000394 if (windows->class_hints->res_name != (char *) NULL)
395 windows->class_hints->res_name=DestroyString(
396 windows->class_hints->res_name);
397 if (windows->class_hints->res_class != (char *) NULL)
398 windows->class_hints->res_class=DestroyString(
399 windows->class_hints->res_class);
cristy3ed852e2009-09-05 21:47:34 +0000400 XFree(windows->class_hints);
401 windows->class_hints=(XClassHint *) NULL;
402 }
403 if (windows->manager_hints != (XWMHints *) NULL)
404 {
405 XFree(windows->manager_hints);
406 windows->manager_hints=(XWMHints *) NULL;
407 }
408 if (windows->map_info != (XStandardColormap *) NULL)
409 {
410 XFree(windows->map_info);
411 windows->map_info=(XStandardColormap *) NULL;
412 }
413 if (windows->icon_map != (XStandardColormap *) NULL)
414 {
415 XFree(windows->icon_map);
416 windows->icon_map=(XStandardColormap *) NULL;
417 }
418 if (windows->visual_info != (XVisualInfo *) NULL)
419 {
420 XFree(windows->visual_info);
421 windows->visual_info=(XVisualInfo *) NULL;
422 }
423 if (windows->icon_visual != (XVisualInfo *) NULL)
424 {
425 XFree(windows->icon_visual);
426 windows->icon_visual=(XVisualInfo *) NULL;
427 }
428 (void) XSetWindows((XWindows *) NULL);
429}
430
431/*
432%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
433% %
434% %
435% %
436% X A n n o t a t e I m a g e %
437% %
438% %
439% %
440%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
441%
442% XAnnotateImage() annotates the image with text.
443%
444% The format of the XAnnotateImage method is:
445%
446% MagickBooleanType XAnnotateImage(Display *display,
cristy7c3af952011-10-20 16:04:16 +0000447% const XPixelInfo *pixel,XAnnotateInfo *annotate_info,Image *image,
448% ExceptionInfo *exception)
cristy3ed852e2009-09-05 21:47:34 +0000449%
450% A description of each parameter follows:
451%
452% o display: Specifies a connection to an X server; returned from
453% XOpenDisplay.
454%
455% o pixel: Specifies a pointer to a XPixelInfo structure.
456%
457% o annotate_info: Specifies a pointer to a XAnnotateInfo structure.
458%
459% o image: the image.
460%
cristy7c3af952011-10-20 16:04:16 +0000461% o exception: return any errors or warnings in this structure.
462%
cristy3ed852e2009-09-05 21:47:34 +0000463*/
cristybcbda3f2011-09-03 13:01:22 +0000464MagickPrivate MagickBooleanType XAnnotateImage(Display *display,
cristy7c3af952011-10-20 16:04:16 +0000465 const XPixelInfo *pixel,XAnnotateInfo *annotate_info,Image *image,
466 ExceptionInfo *exception)
cristy3ed852e2009-09-05 21:47:34 +0000467{
cristyc57f6942010-11-12 01:47:39 +0000468 CacheView
469 *annotate_view;
470
cristy3ed852e2009-09-05 21:47:34 +0000471 GC
472 annotate_context;
473
cristy3ed852e2009-09-05 21:47:34 +0000474 Image
475 *annotate_image;
476
477 int
478 x,
479 y;
480
481 MagickBooleanType
482 matte;
483
484 Pixmap
485 annotate_pixmap;
486
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);
cristye42f6582012-02-11 17:59:50 +0000564 annotate_image->background_color.red=(double)
565 virtual_pixel[RedPixelChannel];
566 annotate_image->background_color.green=(double)
567 virtual_pixel[GreenPixelChannel];
568 annotate_image->background_color.blue=(double)
569 virtual_pixel[BluePixelChannel];
570 annotate_image->background_color.alpha=(double)
571 virtual_pixel[AlphaPixelChannel];
cristy3ed852e2009-09-05 21:47:34 +0000572 if (annotate_info->stencil == ForegroundStencil)
573 annotate_image->matte=MagickTrue;
cristyc57f6942010-11-12 01:47:39 +0000574 annotate_view=AcquireCacheView(annotate_image);
cristy3ed852e2009-09-05 21:47:34 +0000575 for (y=0; y < (int) annotate_image->rows; y++)
576 {
cristyc57f6942010-11-12 01:47:39 +0000577 register int
cristy3ed852e2009-09-05 21:47:34 +0000578 x;
579
cristy4c08aed2011-07-01 19:47:50 +0000580 register Quantum
cristyc47d1f82009-11-26 01:44:43 +0000581 *restrict q;
cristy3ed852e2009-09-05 21:47:34 +0000582
cristyc57f6942010-11-12 01:47:39 +0000583 q=GetCacheViewAuthenticPixels(annotate_view,0,(ssize_t) y,
584 annotate_image->columns,1,exception);
cristyacd2ed22011-08-30 01:44:23 +0000585 if (q == (Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +0000586 break;
cristyc57f6942010-11-12 01:47:39 +0000587 for (x=0; x < (int) annotate_image->columns; x++)
cristy3ed852e2009-09-05 21:47:34 +0000588 {
cristy4c08aed2011-07-01 19:47:50 +0000589 SetPixelAlpha(annotate_image,OpaqueAlpha,q);
cristy3ed852e2009-09-05 21:47:34 +0000590 if (XGetPixel(annotate_ximage,x,y) == 0)
591 {
592 /*
593 Set this pixel to the background color.
594 */
cristy4c08aed2011-07-01 19:47:50 +0000595 SetPixelRed(annotate_image,ScaleShortToQuantum(
596 pixel->box_color.red),q);
597 SetPixelGreen(annotate_image,ScaleShortToQuantum(
598 pixel->box_color.green),q);
599 SetPixelBlue(annotate_image,ScaleShortToQuantum(
600 pixel->box_color.blue),q);
cristy3ed852e2009-09-05 21:47:34 +0000601 if ((annotate_info->stencil == ForegroundStencil) ||
602 (annotate_info->stencil == OpaqueStencil))
cristy4c08aed2011-07-01 19:47:50 +0000603 SetPixelAlpha(annotate_image,TransparentAlpha,q);
cristy3ed852e2009-09-05 21:47:34 +0000604 }
605 else
606 {
607 /*
608 Set this pixel to the pen color.
609 */
cristy4c08aed2011-07-01 19:47:50 +0000610 SetPixelRed(annotate_image,ScaleShortToQuantum(
611 pixel->pen_color.red),q);
612 SetPixelGreen(annotate_image,ScaleShortToQuantum(
613 pixel->pen_color.green),q);
614 SetPixelBlue(annotate_image,ScaleShortToQuantum(
615 pixel->pen_color.blue),q);
cristy3ed852e2009-09-05 21:47:34 +0000616 if (annotate_info->stencil == BackgroundStencil)
cristy4c08aed2011-07-01 19:47:50 +0000617 SetPixelAlpha(annotate_image,TransparentAlpha,q);
cristy3ed852e2009-09-05 21:47:34 +0000618 }
cristyed231572011-07-14 02:18:59 +0000619 q+=GetPixelChannels(annotate_image);
cristy3ed852e2009-09-05 21:47:34 +0000620 }
cristyc57f6942010-11-12 01:47:39 +0000621 if (SyncCacheViewAuthenticPixels(annotate_view,exception) == MagickFalse)
cristy3ed852e2009-09-05 21:47:34 +0000622 break;
623 }
cristyc57f6942010-11-12 01:47:39 +0000624 annotate_view=DestroyCacheView(annotate_view);
cristy3ed852e2009-09-05 21:47:34 +0000625 XDestroyImage(annotate_ximage);
626 /*
627 Determine annotate geometry.
628 */
629 (void) XParseGeometry(annotate_info->geometry,&x,&y,&width,&height);
630 if ((width != (unsigned int) annotate_image->columns) ||
631 (height != (unsigned int) annotate_image->rows))
632 {
633 char
634 image_geometry[MaxTextExtent];
635
636 /*
637 Scale image.
638 */
cristyb51dff52011-05-19 16:55:47 +0000639 (void) FormatLocaleString(image_geometry,MaxTextExtent,"%ux%u",
cristy3ed852e2009-09-05 21:47:34 +0000640 width,height);
cristye941a752011-10-15 01:52:48 +0000641 (void) TransformImage(&annotate_image,(char *) NULL,image_geometry,
642 exception);
cristy3ed852e2009-09-05 21:47:34 +0000643 }
644 if (annotate_info->degrees != 0.0)
645 {
646 Image
647 *rotate_image;
648
649 int
650 rotations;
651
652 MagickRealType
653 normalized_degrees;
654
655 /*
656 Rotate image.
657 */
cristy6710d842011-10-20 23:23:00 +0000658 rotate_image=RotateImage(annotate_image,annotate_info->degrees,exception);
cristy3ed852e2009-09-05 21:47:34 +0000659 if (rotate_image == (Image *) NULL)
660 return(MagickFalse);
661 annotate_image=DestroyImage(annotate_image);
662 annotate_image=rotate_image;
663 /*
664 Annotation is relative to the degree of rotation.
665 */
666 normalized_degrees=annotate_info->degrees;
667 while (normalized_degrees < -45.0)
668 normalized_degrees+=360.0;
669 for (rotations=0; normalized_degrees > 45.0; rotations++)
670 normalized_degrees-=90.0;
671 switch (rotations % 4)
672 {
673 default:
674 case 0:
675 break;
676 case 1:
677 {
678 /*
679 Rotate 90 degrees.
680 */
681 x-=(int) annotate_image->columns/2;
682 y+=(int) annotate_image->columns/2;
683 break;
684 }
685 case 2:
686 {
687 /*
688 Rotate 180 degrees.
689 */
690 x=x-(int) annotate_image->columns;
691 break;
692 }
693 case 3:
694 {
695 /*
696 Rotate 270 degrees.
697 */
698 x=x-(int) annotate_image->columns/2;
699 y=y-(int) (annotate_image->rows-(annotate_image->columns/2));
700 break;
701 }
702 }
703 }
704 /*
705 Composite text onto the image.
706 */
707 (void) XParseGeometry(annotate_info->geometry,&x,&y,&width,&height);
708 matte=image->matte;
709 (void) CompositeImage(image,annotate_image->matte != MagickFalse ?
cristye941a752011-10-15 01:52:48 +0000710 OverCompositeOp : CopyCompositeOp,annotate_image,(ssize_t) x,(ssize_t) y,
711 exception);
cristy3ed852e2009-09-05 21:47:34 +0000712 image->matte=matte;
713 annotate_image=DestroyImage(annotate_image);
714 return(MagickTrue);
715}
716
717/*
718%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
719% %
720% %
721% %
722% X B e s t F o n t %
723% %
724% %
725% %
726%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
727%
728% XBestFont() returns the "best" font. "Best" is defined as a font specified
729% in the X resource database or a font such that the text width displayed
730% with the font does not exceed the specified maximum width.
731%
732% The format of the XBestFont method is:
733%
734% XFontStruct *XBestFont(Display *display,
735% const XResourceInfo *resource_info,const MagickBooleanType text_font)
736%
737% A description of each parameter follows:
738%
739% o font: XBestFont returns a pointer to a XFontStruct structure.
740%
741% o display: Specifies a connection to an X server; returned from
742% XOpenDisplay.
743%
744% o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
745%
746% o text_font: True is font should be mono-spaced (typewriter style).
747%
cristy3ed852e2009-09-05 21:47:34 +0000748*/
749
750static char **FontToList(char *font)
751{
752 char
753 **fontlist;
754
755 register char
756 *p,
757 *q;
758
759 register int
760 i;
761
762 unsigned int
763 fonts;
764
765 if (font == (char *) NULL)
766 return((char **) NULL);
767 /*
768 Convert string to an ASCII list.
769 */
770 fonts=1U;
771 for (p=font; *p != '\0'; p++)
772 if ((*p == ':') || (*p == ';') || (*p == ','))
773 fonts++;
774 fontlist=(char **) AcquireQuantumMemory((size_t) fonts+1UL,sizeof(*fontlist));
775 if (fontlist == (char **) NULL)
776 {
777 ThrowXWindowFatalException(ResourceLimitError,"MemoryAllocationFailed",
778 font);
779 return((char **) NULL);
780 }
781 p=font;
782 for (i=0; i < (int) fonts; i++)
783 {
784 for (q=p; *q != '\0'; q++)
785 if ((*q == ':') || (*q == ';') || (*q == ','))
786 break;
787 fontlist[i]=(char *) AcquireQuantumMemory((size_t) (q-p)+1UL,
788 sizeof(*fontlist[i]));
789 if (fontlist[i] == (char *) NULL)
790 {
791 ThrowXWindowFatalException(ResourceLimitError,"MemoryAllocationFailed",
792 font);
793 return((char **) NULL);
794 }
795 (void) CopyMagickString(fontlist[i],p,(size_t) (q-p+1));
796 p=q+1;
797 }
798 fontlist[i]=(char *) NULL;
799 return(fontlist);
800}
801
cristybcbda3f2011-09-03 13:01:22 +0000802MagickPrivate XFontStruct *XBestFont(Display *display,
cristy3ed852e2009-09-05 21:47:34 +0000803 const XResourceInfo *resource_info,const MagickBooleanType text_font)
804{
805 static const char
806 *Fonts[]=
807 {
808 "-*-helvetica-medium-r-normal--12-*-*-*-*-*-iso8859-1",
809 "-*-arial-medium-r-normal--12-*-*-*-*-*-iso8859-1",
810 "-*-helvetica-medium-r-normal--12-*-*-*-*-*-iso8859-15",
811 "-*-arial-medium-r-normal--12-*-*-*-*-*-iso8859-15",
812 "-*-helvetica-medium-r-normal--12-*-*-*-*-*-*-*",
813 "-*-arial-medium-r-normal--12-*-*-*-*-*-*-*",
814 "variable",
815 "fixed",
816 (char *) NULL
817 },
818 *TextFonts[]=
819 {
820 "-*-courier-medium-r-normal-*-12-*-*-*-*-*-iso8859-1",
821 "-*-courier-medium-r-normal-*-12-*-*-*-*-*-iso8859-15",
822 "-*-fixed-medium-r-normal-*-12-*-*-*-*-*-*-*",
823 "fixed",
824 (char *) NULL
825 };
826
827 char
828 *font_name;
829
830 register const char
831 **p;
832
833 XFontStruct
834 *font_info;
835
836 font_info=(XFontStruct *) NULL;
837 font_name=resource_info->font;
838 if (text_font != MagickFalse)
839 font_name=resource_info->text_font;
840 if ((font_name != (char *) NULL) && (*font_name != '\0'))
841 {
842 char
843 **fontlist;
844
845 register int
846 i;
847
848 /*
849 Load preferred font specified in the X resource database.
850 */
851 fontlist=FontToList(font_name);
852 if (fontlist != (char **) NULL)
853 {
854 for (i=0; fontlist[i] != (char *) NULL; i++)
855 {
856 if (font_info == (XFontStruct *) NULL)
857 font_info=XLoadQueryFont(display,fontlist[i]);
858 fontlist[i]=DestroyString(fontlist[i]);
859 }
860 fontlist=(char **) RelinquishMagickMemory(fontlist);
861 }
862 if (font_info == (XFontStruct *) NULL)
863 ThrowXWindowFatalException(XServerError,"UnableToLoadFont",font_name);
864 }
865 /*
866 Load fonts from list of fonts until one is found.
867 */
868 p=Fonts;
869 if (text_font != MagickFalse)
870 p=TextFonts;
871 if (XDisplayHeight(display,XDefaultScreen(display)) >= 748)
872 p++;
873 while (*p != (char *) NULL)
874 {
875 if (font_info != (XFontStruct *) NULL)
876 break;
877 font_info=XLoadQueryFont(display,(char *) *p);
878 p++;
879 }
880 return(font_info);
881}
882
883/*
884%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
885% %
886% %
887% %
888% X B e s t I c o n S i z e %
889% %
890% %
891% %
892%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
893%
894% XBestIconSize() returns the "best" icon size. "Best" is defined as an icon
895% size that maintains the aspect ratio of the image. If the window manager
896% has preferred icon sizes, one of the preferred sizes is used.
897%
898% The format of the XBestIconSize method is:
899%
900% void XBestIconSize(Display *display,XWindowInfo *window,Image *image)
901%
902% A description of each parameter follows:
903%
904% o display: Specifies a connection to an X server; returned from
905% XOpenDisplay.
906%
907% o image: the image.
908%
909*/
cristybcbda3f2011-09-03 13:01:22 +0000910MagickPrivate void XBestIconSize(Display *display,XWindowInfo *window,
cristy3ed852e2009-09-05 21:47:34 +0000911 Image *image)
912{
913 int
914 i,
915 number_sizes;
916
917 MagickRealType
918 scale_factor;
919
920 unsigned int
921 height,
922 icon_height,
923 icon_width,
924 width;
925
926 Window
927 root_window;
928
929 XIconSize
930 *icon_size,
931 *size_list;
932
933 /*
934 Determine if the window manager has specified preferred icon sizes.
935 */
936 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
937 assert(display != (Display *) NULL);
938 assert(window != (XWindowInfo *) NULL);
939 assert(image != (Image *) NULL);
940 window->width=MaxIconSize;
941 window->height=MaxIconSize;
942 icon_size=(XIconSize *) NULL;
943 number_sizes=0;
944 root_window=XRootWindow(display,window->screen);
945 if (XGetIconSizes(display,root_window,&size_list,&number_sizes) != 0)
946 if ((number_sizes > 0) && (size_list != (XIconSize *) NULL))
947 icon_size=size_list;
948 if (icon_size == (XIconSize *) NULL)
949 {
950 /*
951 Window manager does not restrict icon size.
952 */
953 icon_size=XAllocIconSize();
954 if (icon_size == (XIconSize *) NULL)
955 {
956 ThrowXWindowFatalException(ResourceLimitError,
957 "MemoryAllocationFailed",image->filename);
958 return;
959 }
960 icon_size->min_width=1;
961 icon_size->max_width=MaxIconSize;
962 icon_size->min_height=1;
963 icon_size->max_height=MaxIconSize;
964 icon_size->width_inc=1;
965 icon_size->height_inc=1;
966 }
967 /*
968 Determine aspect ratio of image.
969 */
970 width=(unsigned int) image->columns;
971 height=(unsigned int) image->rows;
972 i=0;
973 if (window->crop_geometry)
974 (void) XParseGeometry(window->crop_geometry,&i,&i,&width,&height);
975 /*
976 Look for an icon size that maintains the aspect ratio of image.
977 */
978 scale_factor=(MagickRealType) icon_size->max_width/width;
979 if (scale_factor > ((MagickRealType) icon_size->max_height/height))
980 scale_factor=(MagickRealType) icon_size->max_height/height;
981 icon_width=(unsigned int) icon_size->min_width;
982 while ((int) icon_width < icon_size->max_width)
983 {
984 if (icon_width >= (unsigned int) (scale_factor*width+0.5))
985 break;
986 icon_width+=icon_size->width_inc;
987 }
988 icon_height=(unsigned int) icon_size->min_height;
989 while ((int) icon_height < icon_size->max_height)
990 {
991 if (icon_height >= (unsigned int) (scale_factor*height+0.5))
992 break;
993 icon_height+=icon_size->height_inc;
994 }
995 (void) XFree((void *) icon_size);
996 window->width=icon_width;
997 window->height=icon_height;
998}
999
1000/*
1001%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1002% %
1003% %
1004% %
1005% X B e s t P i x e l %
1006% %
1007% %
1008% %
1009%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1010%
1011% XBestPixel() returns a pixel from an array of pixels that is closest to the
1012% requested color. If the color array is NULL, the colors are obtained from
1013% the X server.
1014%
1015% The format of the XBestPixel method is:
1016%
1017% void XBestPixel(Display *display,const Colormap colormap,XColor *colors,
1018% unsigned int number_colors,XColor *color)
1019%
1020% A description of each parameter follows:
1021%
1022% o pixel: XBestPixel returns the pixel value closest to the requested
1023% color.
1024%
1025% o display: Specifies a connection to an X server; returned from
1026% XOpenDisplay.
1027%
1028% o colormap: Specifies the ID of the X server colormap.
1029%
1030% o colors: Specifies an array of XColor structures.
1031%
1032% o number_colors: Specifies the number of XColor structures in the
1033% color definition array.
1034%
1035% o color: Specifies the desired RGB value to find in the colors array.
1036%
1037*/
cristybcbda3f2011-09-03 13:01:22 +00001038MagickPrivate void XBestPixel(Display *display,const Colormap colormap,
cristy3ed852e2009-09-05 21:47:34 +00001039 XColor *colors,unsigned int number_colors,XColor *color)
1040{
1041 MagickBooleanType
1042 query_server;
1043
cristy4c08aed2011-07-01 19:47:50 +00001044 PixelInfo
cristy3ed852e2009-09-05 21:47:34 +00001045 pixel;
1046
1047 MagickRealType
1048 min_distance;
1049
1050 register MagickRealType
1051 distance;
1052
1053 register int
1054 i,
1055 j;
1056
1057 Status
1058 status;
1059
1060 /*
1061 Find closest representation for the requested RGB color.
1062 */
1063 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
1064 assert(display != (Display *) NULL);
1065 assert(color != (XColor *) NULL);
1066 status=XAllocColor(display,colormap,color);
1067 if (status != False)
1068 return;
1069 query_server=colors == (XColor *) NULL ? MagickTrue : MagickFalse;
1070 if (query_server != MagickFalse)
1071 {
1072 /*
1073 Read X server colormap.
1074 */
1075 colors=(XColor *) AcquireQuantumMemory(number_colors,sizeof(*colors));
1076 if (colors == (XColor *) NULL)
1077 {
1078 ThrowXWindowFatalException(ResourceLimitError,
1079 "MemoryAllocationFailed","...");
1080 return;
1081 }
1082 for (i=0; i < (int) number_colors; i++)
cristybb503372010-05-27 20:51:26 +00001083 colors[i].pixel=(size_t) i;
cristy3ed852e2009-09-05 21:47:34 +00001084 if (number_colors > 256)
1085 number_colors=256;
1086 (void) XQueryColors(display,colormap,colors,(int) number_colors);
1087 }
1088 min_distance=3.0*((MagickRealType) QuantumRange+1.0)*((MagickRealType)
1089 QuantumRange+1.0);
1090 j=0;
1091 for (i=0; i < (int) number_colors; i++)
1092 {
1093 pixel.red=colors[i].red-(MagickRealType) color->red;
1094 distance=pixel.red*pixel.red;
1095 if (distance > min_distance)
1096 continue;
1097 pixel.green=colors[i].green-(MagickRealType) color->green;
1098 distance+=pixel.green*pixel.green;
1099 if (distance > min_distance)
1100 continue;
1101 pixel.blue=colors[i].blue-(MagickRealType) color->blue;
1102 distance+=pixel.blue*pixel.blue;
1103 if (distance > min_distance)
1104 continue;
1105 min_distance=distance;
1106 color->pixel=colors[i].pixel;
1107 j=i;
1108 }
1109 (void) XAllocColor(display,colormap,&colors[j]);
1110 if (query_server != MagickFalse)
1111 colors=(XColor *) RelinquishMagickMemory(colors);
1112}
1113
1114/*
1115%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1116% %
1117% %
1118% %
1119% X B e s t V i s u a l I n f o %
1120% %
1121% %
1122% %
1123%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1124%
1125% XBestVisualInfo() returns visual information for a visual that is the "best"
1126% the server supports. "Best" is defined as:
1127%
1128% 1. Restrict the visual list to those supported by the default screen.
1129%
1130% 2. If a visual type is specified, restrict the visual list to those of
1131% that type.
1132%
1133% 3. If a map type is specified, choose the visual that matches the id
1134% specified by the Standard Colormap.
1135%
1136% 4 From the list of visuals, choose one that can display the most
1137% simultaneous colors. If more than one visual can display the same
1138% number of simultaneous colors, one is chosen based on a rank.
1139%
1140% The format of the XBestVisualInfo method is:
1141%
1142% XVisualInfo *XBestVisualInfo(Display *display,
1143% XStandardColormap *map_info,XResourceInfo *resource_info)
1144%
1145% A description of each parameter follows:
1146%
1147% o visual_info: XBestVisualInfo returns a pointer to a X11 XVisualInfo
1148% structure.
1149%
1150% o display: Specifies a connection to an X server; returned from
1151% XOpenDisplay.
1152%
1153% o map_info: If map_type is specified, this structure is initialized
1154% with info from the Standard Colormap.
1155%
1156% o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
1157%
1158*/
1159
1160static inline int MagickMax(const int x,const int y)
1161{
1162 if (x > y)
1163 return(x);
1164 return(y);
1165}
1166
cristybb503372010-05-27 20:51:26 +00001167static inline size_t MagickMin(const unsigned int x,
cristy3ed852e2009-09-05 21:47:34 +00001168 const unsigned int y)
1169{
1170 if (x < y)
1171 return(x);
1172 return(y);
1173}
1174
cristybcbda3f2011-09-03 13:01:22 +00001175MagickPrivate XVisualInfo *XBestVisualInfo(Display *display,
cristy3ed852e2009-09-05 21:47:34 +00001176 XStandardColormap *map_info,XResourceInfo *resource_info)
1177{
1178#define MaxStandardColormaps 7
1179#define XVisualColormapSize(visual_info) MagickMin((unsigned int) (\
1180 (visual_info->klass == TrueColor) || (visual_info->klass == DirectColor) ? \
1181 visual_info->red_mask | visual_info->green_mask | visual_info->blue_mask : \
1182 (unsigned int) visual_info->colormap_size),1U << visual_info->depth)
1183
1184 char
1185 *map_type,
1186 *visual_type;
1187
cristyc57f6942010-11-12 01:47:39 +00001188 int
1189 visual_mask;
1190
cristy3ed852e2009-09-05 21:47:34 +00001191 register int
1192 i;
1193
cristy8891f9c2010-06-04 23:32:17 +00001194 size_t
1195 one;
1196
cristy3ed852e2009-09-05 21:47:34 +00001197 static int
1198 number_visuals;
1199
1200 static XVisualInfo
1201 visual_template;
1202
1203 XVisualInfo
1204 *visual_info,
1205 *visual_list;
1206
1207 /*
1208 Restrict visual search by screen number.
1209 */
1210 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
1211 assert(display != (Display *) NULL);
1212 assert(map_info != (XStandardColormap *) NULL);
1213 assert(resource_info != (XResourceInfo *) NULL);
1214 map_type=resource_info->map_type;
1215 visual_type=resource_info->visual_type;
1216 visual_mask=VisualScreenMask;
1217 visual_template.screen=XDefaultScreen(display);
1218 visual_template.depth=XDefaultDepth(display,XDefaultScreen(display));
cristy8891f9c2010-06-04 23:32:17 +00001219 one=1;
cristy3ed852e2009-09-05 21:47:34 +00001220 if ((resource_info->immutable != MagickFalse) && (resource_info->colors != 0))
cristy8891f9c2010-06-04 23:32:17 +00001221 if (resource_info->colors <= (one << (size_t) visual_template.depth))
cristy3ed852e2009-09-05 21:47:34 +00001222 visual_mask|=VisualDepthMask;
1223 if (visual_type != (char *) NULL)
1224 {
1225 /*
1226 Restrict visual search by class or visual id.
1227 */
1228 if (LocaleCompare("staticgray",visual_type) == 0)
1229 {
1230 visual_mask|=VisualClassMask;
1231 visual_template.klass=StaticGray;
1232 }
1233 else
1234 if (LocaleCompare("grayscale",visual_type) == 0)
1235 {
1236 visual_mask|=VisualClassMask;
1237 visual_template.klass=GrayScale;
1238 }
1239 else
1240 if (LocaleCompare("staticcolor",visual_type) == 0)
1241 {
1242 visual_mask|=VisualClassMask;
1243 visual_template.klass=StaticColor;
1244 }
1245 else
1246 if (LocaleCompare("pseudocolor",visual_type) == 0)
1247 {
1248 visual_mask|=VisualClassMask;
1249 visual_template.klass=PseudoColor;
1250 }
1251 else
1252 if (LocaleCompare("truecolor",visual_type) == 0)
1253 {
1254 visual_mask|=VisualClassMask;
1255 visual_template.klass=TrueColor;
1256 }
1257 else
1258 if (LocaleCompare("directcolor",visual_type) == 0)
1259 {
1260 visual_mask|=VisualClassMask;
1261 visual_template.klass=DirectColor;
1262 }
1263 else
1264 if (LocaleCompare("default",visual_type) == 0)
1265 {
1266 visual_mask|=VisualIDMask;
1267 visual_template.visualid=XVisualIDFromVisual(
1268 XDefaultVisual(display,XDefaultScreen(display)));
1269 }
1270 else
1271 if (isdigit((int) ((unsigned char) *visual_type)) != 0)
1272 {
1273 visual_mask|=VisualIDMask;
1274 visual_template.visualid=
1275 strtol(visual_type,(char **) NULL,0);
1276 }
1277 else
1278 ThrowXWindowFatalException(XServerError,
1279 "UnrecognizedVisualSpecifier",visual_type);
1280 }
1281 /*
1282 Get all visuals that meet our criteria so far.
1283 */
1284 number_visuals=0;
1285 visual_list=XGetVisualInfo(display,visual_mask,&visual_template,
1286 &number_visuals);
1287 visual_mask=VisualScreenMask | VisualIDMask;
1288 if ((number_visuals == 0) || (visual_list == (XVisualInfo *) NULL))
1289 {
1290 /*
1291 Failed to get visual; try using the default visual.
1292 */
1293 ThrowXWindowFatalException(XServerWarning,"UnableToGetVisual",
1294 visual_type);
1295 visual_template.visualid=XVisualIDFromVisual(XDefaultVisual(display,
1296 XDefaultScreen(display)));
1297 visual_list=XGetVisualInfo(display,visual_mask,&visual_template,
1298 &number_visuals);
1299 if ((number_visuals == 0) || (visual_list == (XVisualInfo *) NULL))
1300 return((XVisualInfo *) NULL);
1301 ThrowXWindowFatalException(XServerWarning,"UsingDefaultVisual",
1302 XVisualClassName(visual_list->klass));
1303 }
1304 resource_info->color_recovery=MagickFalse;
1305 if ((map_info != (XStandardColormap *) NULL) && (map_type != (char *) NULL))
1306 {
1307 Atom
1308 map_property;
1309
1310 char
1311 map_name[MaxTextExtent];
1312
1313 int
1314 j,
1315 number_maps;
1316
1317 Status
1318 status;
1319
1320 Window
1321 root_window;
1322
1323 XStandardColormap
1324 *map_list;
1325
1326 /*
1327 Choose a visual associated with a standard colormap.
1328 */
1329 root_window=XRootWindow(display,XDefaultScreen(display));
1330 status=False;
1331 if (LocaleCompare(map_type,"list") != 0)
1332 {
1333 /*
1334 User specified Standard Colormap.
1335 */
cristyb51dff52011-05-19 16:55:47 +00001336 (void) FormatLocaleString((char *) map_name,MaxTextExtent,
cristy3ed852e2009-09-05 21:47:34 +00001337 "RGB_%s_MAP",map_type);
1338 LocaleUpper(map_name);
1339 map_property=XInternAtom(display,(char *) map_name,MagickTrue);
1340 if (map_property != (Atom) NULL)
1341 status=XGetRGBColormaps(display,root_window,&map_list,&number_maps,
1342 map_property);
1343 }
1344 else
1345 {
1346 static const char
1347 *colormap[MaxStandardColormaps]=
1348 {
1349 "_HP_RGB_SMOOTH_MAP_LIST",
1350 "RGB_BEST_MAP",
1351 "RGB_DEFAULT_MAP",
1352 "RGB_GRAY_MAP",
1353 "RGB_RED_MAP",
1354 "RGB_GREEN_MAP",
1355 "RGB_BLUE_MAP",
1356 };
1357
1358 /*
1359 Choose a standard colormap from a list.
1360 */
1361 for (i=0; i < MaxStandardColormaps; i++)
1362 {
1363 map_property=XInternAtom(display,(char *) colormap[i],MagickTrue);
1364 if (map_property == (Atom) NULL)
1365 continue;
1366 status=XGetRGBColormaps(display,root_window,&map_list,&number_maps,
1367 map_property);
1368 if (status != False)
1369 break;
1370 }
1371 resource_info->color_recovery=i == 0 ? MagickTrue : MagickFalse;
1372 }
1373 if (status == False)
1374 {
1375 ThrowXWindowFatalException(XServerError,"UnableToGetStandardColormap",
1376 map_type);
1377 return((XVisualInfo *) NULL);
1378 }
1379 /*
1380 Search all Standard Colormaps and visuals for ids that match.
1381 */
1382 *map_info=map_list[0];
1383#if !defined(PRE_R4_ICCCM)
1384 visual_template.visualid=XVisualIDFromVisual(visual_list[0].visual);
1385 for (i=0; i < number_maps; i++)
1386 for (j=0; j < number_visuals; j++)
1387 if (map_list[i].visualid ==
1388 XVisualIDFromVisual(visual_list[j].visual))
1389 {
1390 *map_info=map_list[i];
1391 visual_template.visualid=XVisualIDFromVisual(
1392 visual_list[j].visual);
1393 break;
1394 }
1395 if (map_info->visualid != visual_template.visualid)
1396 {
1397 ThrowXWindowFatalException(XServerError,
1398 "UnableToMatchVisualToStandardColormap",map_type);
1399 return((XVisualInfo *) NULL);
1400 }
1401#endif
1402 if (map_info->colormap == (Colormap) NULL)
1403 {
1404 ThrowXWindowFatalException(XServerError,
1405 "StandardColormapIsNotInitialized",map_type);
1406 return((XVisualInfo *) NULL);
1407 }
1408 (void) XFree((void *) map_list);
1409 }
1410 else
1411 {
1412 static const unsigned int
1413 rank[]=
1414 {
1415 StaticGray,
1416 GrayScale,
1417 StaticColor,
1418 DirectColor,
1419 TrueColor,
1420 PseudoColor
1421 };
1422
1423 XVisualInfo
1424 *p;
1425
1426 /*
1427 Pick one visual that displays the most simultaneous colors.
1428 */
1429 visual_info=visual_list;
1430 p=visual_list;
1431 for (i=1; i < number_visuals; i++)
1432 {
1433 p++;
1434 if (XVisualColormapSize(p) > XVisualColormapSize(visual_info))
1435 visual_info=p;
1436 else
1437 if (XVisualColormapSize(p) == XVisualColormapSize(visual_info))
1438 if (rank[p->klass] > rank[visual_info->klass])
1439 visual_info=p;
1440 }
1441 visual_template.visualid=XVisualIDFromVisual(visual_info->visual);
1442 }
1443 (void) XFree((void *) visual_list);
1444 /*
1445 Retrieve only one visual by its screen & id number.
1446 */
1447 visual_info=XGetVisualInfo(display,visual_mask,&visual_template,
1448 &number_visuals);
1449 if ((number_visuals == 0) || (visual_info == (XVisualInfo *) NULL))
1450 return((XVisualInfo *) NULL);
1451 return(visual_info);
1452}
1453
1454/*
1455%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1456% %
1457% %
1458% %
1459% X C h e c k D e f i n e C u r s o r %
1460% %
1461% %
1462% %
1463%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1464%
1465% XCheckDefineCursor() prevents cursor changes on the root window.
1466%
1467% The format of the XXCheckDefineCursor method is:
1468%
1469% XCheckDefineCursor(display,window,cursor)
1470%
1471% A description of each parameter follows:
1472%
1473% o display: Specifies a connection to an X server; returned from
1474% XOpenDisplay.
1475%
1476% o window: the window.
1477%
1478% o cursor: the cursor.
1479%
1480*/
cristybcbda3f2011-09-03 13:01:22 +00001481MagickPrivate int XCheckDefineCursor(Display *display,Window window,
cristy3ed852e2009-09-05 21:47:34 +00001482 Cursor cursor)
1483{
1484 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
1485 assert(display != (Display *) NULL);
1486 if (window == XRootWindow(display,XDefaultScreen(display)))
1487 return(0);
1488 return(XDefineCursor(display,window,cursor));
1489}
1490
1491/*
1492%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1493% %
1494% %
1495% %
1496% X C h e c k R e f r e s h W i n d o w s %
1497% %
1498% %
1499% %
1500%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1501%
1502% XCheckRefreshWindows() checks the X server for exposure events for a
1503% particular window and updates the areassociated with the exposure event.
1504%
1505% The format of the XCheckRefreshWindows method is:
1506%
1507% void XCheckRefreshWindows(Display *display,XWindows *windows)
1508%
1509% A description of each parameter follows:
1510%
1511% o display: Specifies a connection to an X server; returned from
1512% XOpenDisplay.
1513%
1514% o windows: Specifies a pointer to a XWindows structure.
1515%
1516*/
cristybcbda3f2011-09-03 13:01:22 +00001517MagickPrivate void XCheckRefreshWindows(Display *display,XWindows *windows)
cristy3ed852e2009-09-05 21:47:34 +00001518{
1519 Window
1520 id;
1521
1522 XEvent
1523 event;
1524
1525 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
1526 assert(display != (Display *) NULL);
1527 assert(windows != (XWindows *) NULL);
1528 XDelay(display,SuspendTime);
1529 id=windows->command.id;
1530 while (XCheckTypedWindowEvent(display,id,Expose,&event) != MagickFalse)
1531 (void) XCommandWidget(display,windows,(char const **) NULL,&event);
1532 id=windows->image.id;
1533 while (XCheckTypedWindowEvent(display,id,Expose,&event) != MagickFalse)
1534 XRefreshWindow(display,&windows->image,&event);
1535 XDelay(display,SuspendTime << 1);
1536 id=windows->command.id;
1537 while (XCheckTypedWindowEvent(display,id,Expose,&event) != MagickFalse)
1538 (void) XCommandWidget(display,windows,(char const **) NULL,&event);
1539 id=windows->image.id;
1540 while (XCheckTypedWindowEvent(display,id,Expose,&event) != MagickFalse)
1541 XRefreshWindow(display,&windows->image,&event);
1542}
1543
1544/*
1545%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1546% %
1547% %
1548% %
1549% X C l i e n t M e s s a g e %
1550% %
1551% %
1552% %
1553%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1554%
1555% XClientMessage() sends a reason to a window with XSendEvent. The reason is
1556% initialized with a particular protocol type and atom.
1557%
1558% The format of the XClientMessage function is:
1559%
1560% XClientMessage(display,window,protocol,reason,timestamp)
1561%
1562% A description of each parameter follows:
1563%
1564% o display: Specifies a pointer to the Display structure; returned from
1565% XOpenDisplay.
1566%
1567% o window: Specifies a pointer to a Window structure.
1568%
1569% o protocol: Specifies an atom value.
1570%
1571% o reason: Specifies an atom value which is the reason to send.
1572%
1573% o timestamp: Specifies a value of type Time.
1574%
1575*/
cristybcbda3f2011-09-03 13:01:22 +00001576MagickPrivate void XClientMessage(Display *display,const Window window,
cristy3ed852e2009-09-05 21:47:34 +00001577 const Atom protocol,const Atom reason,const Time timestamp)
1578{
1579 XClientMessageEvent
1580 client_event;
1581
1582 assert(display != (Display *) NULL);
1583 client_event.type=ClientMessage;
1584 client_event.window=window;
1585 client_event.message_type=protocol;
1586 client_event.format=32;
cristyc57f6942010-11-12 01:47:39 +00001587 client_event.data.l[0]=(long) reason;
1588 client_event.data.l[1]=(long) timestamp;
cristy3ed852e2009-09-05 21:47:34 +00001589 (void) XSendEvent(display,window,MagickFalse,NoEventMask,(XEvent *) &client_event);
1590}
1591
1592/*
1593%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1594% %
1595% %
1596% %
1597+ X C l i e n t W i n d o w %
1598% %
1599% %
1600% %
1601%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1602%
1603% XClientWindow() finds a window, at or below the specified window, which has
1604% a WM_STATE property. If such a window is found, it is returned, otherwise
1605% the argument window is returned.
1606%
1607% The format of the XClientWindow function is:
1608%
1609% client_window=XClientWindow(display,target_window)
1610%
1611% A description of each parameter follows:
1612%
1613% o client_window: XClientWindow returns a window, at or below the specified
1614% window, which has a WM_STATE property otherwise the argument
1615% target_window is returned.
1616%
1617% o display: Specifies a pointer to the Display structure; returned from
1618% XOpenDisplay.
1619%
1620% o target_window: Specifies the window to find a WM_STATE property.
1621%
cristy3ed852e2009-09-05 21:47:34 +00001622*/
1623static Window XClientWindow(Display *display,Window target_window)
1624{
1625 Atom
1626 state,
1627 type;
1628
1629 int
1630 format;
1631
1632 Status
1633 status;
1634
1635 unsigned char
1636 *data;
1637
cristyf2faecf2010-05-28 19:19:36 +00001638 unsigned long
cristy3ed852e2009-09-05 21:47:34 +00001639 after,
1640 number_items;
1641
1642 Window
1643 client_window;
1644
1645 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
1646 assert(display != (Display *) NULL);
1647 state=XInternAtom(display,"WM_STATE",MagickTrue);
1648 if (state == (Atom) NULL)
1649 return(target_window);
1650 type=(Atom) NULL;
1651 status=XGetWindowProperty(display,target_window,state,0L,0L,MagickFalse,
1652 (Atom) AnyPropertyType,&type,&format,&number_items,&after,&data);
1653 if ((status == Success) && (type != (Atom) NULL))
1654 return(target_window);
1655 client_window=XWindowByProperty(display,target_window,state);
1656 if (client_window == (Window) NULL)
1657 return(target_window);
1658 return(client_window);
1659}
1660
1661/*
1662%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1663% %
1664% %
1665% %
cristyf34a1452009-10-24 22:29:27 +00001666+ X C o m p o n e n t T e r m i n u s %
1667% %
1668% %
1669% %
1670%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1671%
1672% XComponentTerminus() destroys the module component.
1673%
1674% The format of the XComponentTerminus method is:
1675%
1676% XComponentTerminus(void)
1677%
1678*/
cristy5ff4eaf2011-09-03 01:38:02 +00001679MagickPrivate void XComponentTerminus(void)
cristyf34a1452009-10-24 22:29:27 +00001680{
1681 DestroyXResources();
1682}
1683
1684/*
1685%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1686% %
1687% %
1688% %
cristy3ed852e2009-09-05 21:47:34 +00001689% X C o n f i g u r e I m a g e C o l o r m a p %
1690% %
1691% %
1692% %
1693%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1694%
1695% XConfigureImageColormap() creates a new X colormap.
1696%
1697% The format of the XConfigureImageColormap method is:
1698%
1699% void XConfigureImageColormap(Display *display,
cristy6710d842011-10-20 23:23:00 +00001700% XResourceInfo *resource_info,XWindows *windows,Image *image,
1701% ExceptionInfo *exception)
cristy3ed852e2009-09-05 21:47:34 +00001702%
1703% A description of each parameter follows:
1704%
1705% o display: Specifies a connection to an X server; returned from
1706% XOpenDisplay.
1707%
1708% o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
1709%
1710% o windows: Specifies a pointer to a XWindows structure.
1711%
1712% o image: the image.
1713%
cristy6710d842011-10-20 23:23:00 +00001714% o exception: return any errors or warnings in this structure.
1715%
cristy3ed852e2009-09-05 21:47:34 +00001716*/
cristybcbda3f2011-09-03 13:01:22 +00001717MagickPrivate void XConfigureImageColormap(Display *display,
cristy6710d842011-10-20 23:23:00 +00001718 XResourceInfo *resource_info,XWindows *windows,Image *image,
1719 ExceptionInfo *exception)
cristy3ed852e2009-09-05 21:47:34 +00001720{
1721 Colormap
1722 colormap;
1723
1724 /*
1725 Make standard colormap.
1726 */
1727 XSetCursorState(display,windows,MagickTrue);
1728 XCheckRefreshWindows(display,windows);
1729 XMakeStandardColormap(display,windows->visual_info,resource_info,image,
cristy6710d842011-10-20 23:23:00 +00001730 windows->map_info,windows->pixel_info,exception);
cristy3ed852e2009-09-05 21:47:34 +00001731 colormap=windows->map_info->colormap;
1732 (void) XSetWindowColormap(display,windows->image.id,colormap);
1733 (void) XSetWindowColormap(display,windows->command.id,colormap);
1734 (void) XSetWindowColormap(display,windows->widget.id,colormap);
1735 if (windows->magnify.mapped != MagickFalse)
1736 (void) XSetWindowColormap(display,windows->magnify.id,colormap);
1737 if (windows->pan.mapped != MagickFalse)
1738 (void) XSetWindowColormap(display,windows->pan.id,colormap);
1739 XSetCursorState(display,windows,MagickFalse);
1740 XClientMessage(display,windows->image.id,windows->im_protocols,
1741 windows->im_update_colormap,CurrentTime);
1742}
1743
1744/*
1745%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1746% %
1747% %
1748% %
1749% X C o n s t r a i n W i n d o w P o s i t i o n %
1750% %
1751% %
1752% %
1753%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1754%
1755% XConstrainWindowPosition() assures a window is positioned within the X
1756% server boundaries.
1757%
1758% The format of the XConstrainWindowPosition method is:
1759%
1760% void XConstrainWindowPosition(Display *display,XWindowInfo *window_info)
1761%
1762% A description of each parameter follows:
1763%
1764% o display: Specifies a pointer to the Display structure; returned from
1765% XOpenDisplay.
1766%
1767% o window_info: Specifies a pointer to a XWindowInfo structure.
1768%
1769*/
cristybcbda3f2011-09-03 13:01:22 +00001770MagickPrivate void XConstrainWindowPosition(Display *display,
cristy3ed852e2009-09-05 21:47:34 +00001771 XWindowInfo *window_info)
1772{
1773 int
1774 limit;
1775
1776 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
1777 assert(display != (Display *) NULL);
1778 assert(window_info != (XWindowInfo *) NULL);
1779 limit=XDisplayWidth(display,window_info->screen)-window_info->width;
1780 if (window_info->x < 0)
1781 window_info->x=0;
1782 else
1783 if (window_info->x > (int) limit)
1784 window_info->x=(int) limit;
1785 limit=XDisplayHeight(display,window_info->screen)-window_info->height;
1786 if (window_info->y < 0)
1787 window_info->y=0;
1788 else
1789 if (window_info->y > limit)
1790 window_info->y=limit;
1791}
1792
1793/*
1794%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1795% %
1796% %
1797% %
1798% X D e l a y %
1799% %
1800% %
1801% %
1802%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1803%
1804% XDelay() suspends program execution for the number of milliseconds
1805% specified.
1806%
1807% The format of the Delay method is:
1808%
cristybb503372010-05-27 20:51:26 +00001809% void XDelay(Display *display,const size_t milliseconds)
cristy3ed852e2009-09-05 21:47:34 +00001810%
1811% A description of each parameter follows:
1812%
1813% o display: Specifies a pointer to the Display structure; returned from
1814% XOpenDisplay.
1815%
1816% o milliseconds: Specifies the number of milliseconds to delay before
1817% returning.
1818%
1819*/
cristybcbda3f2011-09-03 13:01:22 +00001820MagickPrivate void XDelay(Display *display,const size_t milliseconds)
cristy3ed852e2009-09-05 21:47:34 +00001821{
1822 assert(display != (Display *) NULL);
1823 (void) XFlush(display);
cristya21afde2010-07-02 00:45:40 +00001824 MagickDelay(milliseconds);
cristy3ed852e2009-09-05 21:47:34 +00001825}
1826
1827/*
1828%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1829% %
1830% %
1831% %
1832% X D e s t r o y R e s o u r c e I n f o %
1833% %
1834% %
1835% %
1836%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1837%
1838% XDestroyResourceInfo() frees memory associated with the XResourceInfo
1839% structure.
1840%
1841% The format of the XDestroyResourceInfo method is:
1842%
1843% void XDestroyResourceInfo(XResourceInfo *resource_info)
1844%
1845% A description of each parameter follows:
1846%
1847% o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
1848%
1849*/
1850MagickExport void XDestroyResourceInfo(XResourceInfo *resource_info)
1851{
1852 if (resource_info->image_geometry != (char *) NULL)
1853 resource_info->image_geometry=(char *)
1854 RelinquishMagickMemory(resource_info->image_geometry);
1855 if (resource_info->quantize_info != (QuantizeInfo *) NULL)
1856 resource_info->quantize_info=DestroyQuantizeInfo(
1857 resource_info->quantize_info);
1858 if (resource_info->client_name != (char *) NULL)
1859 resource_info->client_name=(char *)
1860 RelinquishMagickMemory(resource_info->client_name);
1861 if (resource_info->name != (char *) NULL)
1862 resource_info->name=DestroyString(resource_info->name);
1863 (void) ResetMagickMemory(resource_info,0,sizeof(*resource_info));
1864}
1865
1866/*
1867%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1868% %
1869% %
1870% %
1871% X D e s t r o y W i n d o w C o l o r s %
1872% %
1873% %
1874% %
1875%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1876%
1877% XDestroyWindowColors() frees X11 color resources previously saved on a
1878% window by XRetainWindowColors or programs like xsetroot.
1879%
1880% The format of the XDestroyWindowColors method is:
1881%
1882% void XDestroyWindowColors(Display *display,Window window)
1883%
1884% A description of each parameter follows:
1885%
1886% o display: Specifies a connection to an X server; returned from
1887% XOpenDisplay.
1888%
1889% o window: Specifies a pointer to a Window structure.
1890%
1891*/
cristybcbda3f2011-09-03 13:01:22 +00001892MagickPrivate void XDestroyWindowColors(Display *display,Window window)
cristy3ed852e2009-09-05 21:47:34 +00001893{
1894 Atom
1895 property,
1896 type;
1897
1898 int
1899 format;
1900
1901 Status
1902 status;
1903
1904 unsigned char
1905 *data;
1906
cristyf2faecf2010-05-28 19:19:36 +00001907 unsigned long
cristy3ed852e2009-09-05 21:47:34 +00001908 after,
1909 length;
1910
1911 /*
1912 If there are previous resources on the root window, destroy them.
1913 */
1914 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
1915 assert(display != (Display *) NULL);
1916 property=XInternAtom(display,"_XSETROOT_ID",MagickFalse);
1917 if (property == (Atom) NULL)
1918 {
1919 ThrowXWindowFatalException(XServerError,"UnableToCreateProperty",
1920 "_XSETROOT_ID");
1921 return;
1922 }
1923 status=XGetWindowProperty(display,window,property,0L,1L,MagickTrue,
1924 (Atom) AnyPropertyType,&type,&format,&length,&after,&data);
1925 if (status != Success)
1926 return;
1927 if ((type == XA_PIXMAP) && (format == 32) && (length == 1) && (after == 0))
1928 {
1929 (void) XKillClient(display,(XID) (*((Pixmap *) data)));
1930 (void) XDeleteProperty(display,window,property);
1931 }
1932 if (type != None)
1933 (void) XFree((void *) data);
1934}
1935
1936/*
1937%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1938% %
1939% %
1940% %
1941% X D i s p l a y I m a g e I n f o %
1942% %
1943% %
1944% %
1945%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1946%
1947% XDisplayImageInfo() displays information about an X image.
1948%
1949% The format of the XDisplayImageInfo method is:
1950%
1951% void XDisplayImageInfo(Display *display,
1952% const XResourceInfo *resource_info,XWindows *windows,Image *undo_image,
cristy6710d842011-10-20 23:23:00 +00001953% Image *image,ExceptionInfo *exception)
cristy3ed852e2009-09-05 21:47:34 +00001954%
1955% A description of each parameter follows:
1956%
1957% o display: Specifies a connection to an X server; returned from
1958% XOpenDisplay.
1959%
1960% o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
1961%
1962% o windows: Specifies a pointer to a XWindows structure.
1963%
1964% o undo_image: the undo image.
1965%
1966% o image: the image.
1967%
cristy6710d842011-10-20 23:23:00 +00001968% o exception: return any errors or warnings in this structure.
1969%
cristy3ed852e2009-09-05 21:47:34 +00001970*/
cristybcbda3f2011-09-03 13:01:22 +00001971MagickPrivate void XDisplayImageInfo(Display *display,
cristy3ed852e2009-09-05 21:47:34 +00001972 const XResourceInfo *resource_info,XWindows *windows,Image *undo_image,
cristy6710d842011-10-20 23:23:00 +00001973 Image *image,ExceptionInfo *exception)
cristy3ed852e2009-09-05 21:47:34 +00001974{
1975 char
1976 filename[MaxTextExtent],
1977 *text,
1978 **textlist;
1979
1980 FILE
1981 *file;
1982
1983 int
1984 unique_file;
1985
cristybb503372010-05-27 20:51:26 +00001986 register ssize_t
cristy3ed852e2009-09-05 21:47:34 +00001987 i;
1988
cristybb503372010-05-27 20:51:26 +00001989 size_t
cristy3ed852e2009-09-05 21:47:34 +00001990 number_pixels;
1991
cristy9d314ff2011-03-09 01:30:28 +00001992 ssize_t
1993 bytes;
1994
1995 unsigned int
1996 levels;
1997
cristy3ed852e2009-09-05 21:47:34 +00001998 /*
1999 Write info about the X server to a file.
2000 */
2001 assert(display != (Display *) NULL);
2002 assert(resource_info != (XResourceInfo *) NULL);
2003 assert(windows != (XWindows *) NULL);
2004 assert(image != (Image *) NULL);
2005 if (image->debug)
2006 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
2007 file=(FILE *) NULL;
2008 unique_file=AcquireUniqueFileResource(filename);
2009 if (unique_file != -1)
2010 file=fdopen(unique_file,"w");
2011 if ((unique_file == -1) || (file == (FILE *) NULL))
2012 {
2013 XNoticeWidget(display,windows,"Unable to display image info",filename);
2014 return;
2015 }
2016 if (resource_info->gamma_correct != MagickFalse)
2017 if (resource_info->display_gamma != (char *) NULL)
cristyb51dff52011-05-19 16:55:47 +00002018 (void) FormatLocaleFile(file,"Display\n gamma: %s\n\n",
cristy3ed852e2009-09-05 21:47:34 +00002019 resource_info->display_gamma);
2020 /*
2021 Write info about the X image to a file.
2022 */
cristyb51dff52011-05-19 16:55:47 +00002023 (void) FormatLocaleFile(file,"X\n visual: %s\n",
cristy3ed852e2009-09-05 21:47:34 +00002024 XVisualClassName((int) windows->image.storage_class));
cristyb51dff52011-05-19 16:55:47 +00002025 (void) FormatLocaleFile(file," depth: %d\n",windows->image.ximage->depth);
cristy3ed852e2009-09-05 21:47:34 +00002026 if (windows->visual_info->colormap_size != 0)
cristyb51dff52011-05-19 16:55:47 +00002027 (void) FormatLocaleFile(file," colormap size: %d\n",
cristy3ed852e2009-09-05 21:47:34 +00002028 windows->visual_info->colormap_size);
2029 if (resource_info->colormap== SharedColormap)
cristyb51dff52011-05-19 16:55:47 +00002030 (void) FormatLocaleFile(file," colormap type: Shared\n");
cristy3ed852e2009-09-05 21:47:34 +00002031 else
cristyb51dff52011-05-19 16:55:47 +00002032 (void) FormatLocaleFile(file," colormap type: Private\n");
cristy1e604812011-05-19 18:07:50 +00002033 (void) FormatLocaleFile(file," geometry: %dx%d\n",
2034 windows->image.ximage->width,windows->image.ximage->height);
cristy3ed852e2009-09-05 21:47:34 +00002035 if (windows->image.crop_geometry != (char *) NULL)
cristy1e604812011-05-19 18:07:50 +00002036 (void) FormatLocaleFile(file," crop geometry: %s\n",
2037 windows->image.crop_geometry);
cristy3ed852e2009-09-05 21:47:34 +00002038 if (windows->image.pixmap == (Pixmap) NULL)
cristyb51dff52011-05-19 16:55:47 +00002039 (void) FormatLocaleFile(file," type: X Image\n");
cristy3ed852e2009-09-05 21:47:34 +00002040 else
cristyb51dff52011-05-19 16:55:47 +00002041 (void) FormatLocaleFile(file," type: Pixmap\n");
cristy3ed852e2009-09-05 21:47:34 +00002042 if (windows->image.shape != MagickFalse)
cristyb51dff52011-05-19 16:55:47 +00002043 (void) FormatLocaleFile(file," non-rectangular shape: True\n");
cristy3ed852e2009-09-05 21:47:34 +00002044 else
cristyb51dff52011-05-19 16:55:47 +00002045 (void) FormatLocaleFile(file," non-rectangular shape: False\n");
cristy3ed852e2009-09-05 21:47:34 +00002046 if (windows->image.shared_memory != MagickFalse)
cristyb51dff52011-05-19 16:55:47 +00002047 (void) FormatLocaleFile(file," shared memory: True\n");
cristy3ed852e2009-09-05 21:47:34 +00002048 else
cristyb51dff52011-05-19 16:55:47 +00002049 (void) FormatLocaleFile(file," shared memory: False\n");
2050 (void) FormatLocaleFile(file,"\n");
cristy3ed852e2009-09-05 21:47:34 +00002051 if (resource_info->font != (char *) NULL)
cristyb51dff52011-05-19 16:55:47 +00002052 (void) FormatLocaleFile(file,"Font: %s\n\n",resource_info->font);
cristy3ed852e2009-09-05 21:47:34 +00002053 if (resource_info->text_font != (char *) NULL)
cristyb51dff52011-05-19 16:55:47 +00002054 (void) FormatLocaleFile(file,"Text font: %s\n\n",resource_info->text_font);
cristy3ed852e2009-09-05 21:47:34 +00002055 /*
2056 Write info about the undo cache to a file.
2057 */
2058 bytes=0;
2059 for (levels=0; undo_image != (Image *) NULL; levels++)
2060 {
2061 number_pixels=undo_image->list->columns*undo_image->list->rows;
cristy101ab702011-10-13 13:06:32 +00002062 bytes+=number_pixels*sizeof(PixelInfo);
cristy3ed852e2009-09-05 21:47:34 +00002063 undo_image=GetPreviousImageInList(undo_image);
2064 }
cristyb51dff52011-05-19 16:55:47 +00002065 (void) FormatLocaleFile(file,"Undo Edit Cache\n levels: %u\n",levels);
cristy1e604812011-05-19 18:07:50 +00002066 (void) FormatLocaleFile(file," bytes: %.20gmb\n",(double)
2067 ((bytes+(1 << 19)) >> 20));
cristyb51dff52011-05-19 16:55:47 +00002068 (void) FormatLocaleFile(file," limit: %.20gmb\n\n",(double)
cristyf2faecf2010-05-28 19:19:36 +00002069 resource_info->undo_cache);
cristy3ed852e2009-09-05 21:47:34 +00002070 /*
2071 Write info about the image to a file.
2072 */
cristy6710d842011-10-20 23:23:00 +00002073 (void) IdentifyImage(image,file,MagickTrue,exception);
cristy3ed852e2009-09-05 21:47:34 +00002074 (void) fclose(file);
cristy6710d842011-10-20 23:23:00 +00002075 text=FileToString(filename,~0,exception);
cristy3ed852e2009-09-05 21:47:34 +00002076 (void) RelinquishUniqueFileResource(filename);
2077 if (text == (char *) NULL)
2078 {
2079 XNoticeWidget(display,windows,"MemoryAllocationFailed",
2080 "UnableToDisplayImageInfo");
2081 return;
2082 }
2083 textlist=StringToList(text);
2084 if (textlist != (char **) NULL)
2085 {
2086 char
2087 title[MaxTextExtent];
2088
2089 /*
2090 Display information about the image in the Text View widget.
2091 */
2092 (void) XWithdrawWindow(display,windows->info.id,windows->info.screen);
cristyb51dff52011-05-19 16:55:47 +00002093 (void) FormatLocaleString(title,MaxTextExtent,"Image Info: %s",
cristy3ed852e2009-09-05 21:47:34 +00002094 image->filename);
2095 XTextViewWidget(display,resource_info,windows,MagickTrue,title,
2096 (char const **) textlist);
2097 for (i=0; textlist[i] != (char *) NULL; i++)
2098 textlist[i]=DestroyString(textlist[i]);
2099 textlist=(char **) RelinquishMagickMemory(textlist);
2100 }
2101 text=DestroyString(text);
2102}
2103
2104/*
2105%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2106% %
2107% %
2108% %
2109+ X D i t h e r I m a g e %
2110% %
2111% %
2112% %
2113%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2114%
2115% XDitherImage() dithers the reference image as required by the HP Color
2116% Recovery algorithm. The color values are quantized to 3 bits of red and
2117% green, and 2 bits of blue (3/3/2) and can be used as indices into a 8-bit X
2118% standard colormap.
2119%
2120% The format of the XDitherImage method is:
2121%
cristy6710d842011-10-20 23:23:00 +00002122% void XDitherImage(Image *image,XImage *ximage,ExceptionInfo *exception)
cristy3ed852e2009-09-05 21:47:34 +00002123%
2124% A description of each parameter follows:
2125%
2126% o image: the image.
2127%
2128% o ximage: Specifies a pointer to a XImage structure; returned from
2129% XCreateImage.
2130%
cristy6710d842011-10-20 23:23:00 +00002131% o exception: return any errors or warnings in this structure.
2132%
cristy3ed852e2009-09-05 21:47:34 +00002133*/
cristy6710d842011-10-20 23:23:00 +00002134static void XDitherImage(Image *image,XImage *ximage,ExceptionInfo *exception)
cristy3ed852e2009-09-05 21:47:34 +00002135{
2136 static const short int
2137 dither_red[2][16]=
2138 {
2139 {-16, 4, -1, 11,-14, 6, -3, 9,-15, 5, -2, 10,-13, 7, -4, 8},
2140 { 15, -5, 0,-12, 13, -7, 2,-10, 14, -6, 1,-11, 12, -8, 3, -9}
2141 },
2142 dither_green[2][16]=
2143 {
2144 { 11,-15, 7, -3, 8,-14, 4, -2, 10,-16, 6, -4, 9,-13, 5, -1},
2145 {-12, 14, -8, 2, -9, 13, -5, 1,-11, 15, -7, 3,-10, 12, -6, 0}
2146 },
2147 dither_blue[2][16]=
2148 {
2149 { -3, 9,-13, 7, -1, 11,-15, 5, -4, 8,-14, 6, -2, 10,-16, 4},
2150 { 2,-10, 12, -8, 0,-12, 14, -6, 3, -9, 13, -7, 1,-11, 15, -5}
2151 };
2152
cristyc57f6942010-11-12 01:47:39 +00002153 CacheView
2154 *image_view;
cristy3ed852e2009-09-05 21:47:34 +00002155
2156 int
cristyc57f6942010-11-12 01:47:39 +00002157 value,
cristy3ed852e2009-09-05 21:47:34 +00002158 y;
2159
cristy101ab702011-10-13 13:06:32 +00002160 PixelInfo
cristyc57f6942010-11-12 01:47:39 +00002161 color;
cristy3ed852e2009-09-05 21:47:34 +00002162
2163 register char
2164 *q;
2165
cristy4c08aed2011-07-01 19:47:50 +00002166 register const Quantum
cristy3ed852e2009-09-05 21:47:34 +00002167 *p;
2168
2169 register int
2170 i,
2171 j,
2172 x;
2173
2174 unsigned int
2175 scanline_pad;
2176
cristybb503372010-05-27 20:51:26 +00002177 register size_t
cristy3ed852e2009-09-05 21:47:34 +00002178 pixel;
2179
2180 unsigned char
2181 *blue_map[2][16],
2182 *green_map[2][16],
2183 *red_map[2][16];
2184
2185 /*
2186 Allocate and initialize dither maps.
2187 */
2188 for (i=0; i < 2; i++)
2189 for (j=0; j < 16; j++)
2190 {
2191 red_map[i][j]=(unsigned char *) AcquireQuantumMemory(256UL,
2192 sizeof(*red_map));
2193 green_map[i][j]=(unsigned char *) AcquireQuantumMemory(256UL,
2194 sizeof(*green_map));
2195 blue_map[i][j]=(unsigned char *) AcquireQuantumMemory(256UL,
2196 sizeof(*blue_map));
2197 if ((red_map[i][j] == (unsigned char *) NULL) ||
2198 (green_map[i][j] == (unsigned char *) NULL) ||
2199 (blue_map[i][j] == (unsigned char *) NULL))
2200 {
2201 ThrowXWindowFatalException(ResourceLimitError,
2202 "MemoryAllocationFailed",image->filename);
2203 return;
2204 }
2205 }
2206 /*
2207 Initialize dither tables.
2208 */
2209 for (i=0; i < 2; i++)
2210 for (j=0; j < 16; j++)
2211 for (x=0; x < 256; x++)
2212 {
2213 value=x-16;
2214 if (x < 48)
2215 value=x/2+8;
2216 value+=dither_red[i][j];
2217 red_map[i][j][x]=(unsigned char)
2218 ((value < 0) ? 0 : (value > 255) ? 255 : value);
2219 value=x-16;
2220 if (x < 48)
2221 value=x/2+8;
2222 value+=dither_green[i][j];
2223 green_map[i][j][x]=(unsigned char)
2224 ((value < 0) ? 0 : (value > 255) ? 255 : value);
2225 value=x-32;
2226 if (x < 112)
2227 value=x/2+24;
cristybb503372010-05-27 20:51:26 +00002228 value+=((size_t) dither_blue[i][j] << 1);
cristy3ed852e2009-09-05 21:47:34 +00002229 blue_map[i][j][x]=(unsigned char)
2230 ((value < 0) ? 0 : (value > 255) ? 255 : value);
2231 }
2232 /*
2233 Dither image.
2234 */
2235 scanline_pad=(unsigned int) (ximage->bytes_per_line-
cristybb503372010-05-27 20:51:26 +00002236 ((size_t) (ximage->width*ximage->bits_per_pixel) >> 3));
cristy3ed852e2009-09-05 21:47:34 +00002237 i=0;
2238 j=0;
2239 q=ximage->data;
cristyc57f6942010-11-12 01:47:39 +00002240 image_view=AcquireCacheView(image);
cristy3ed852e2009-09-05 21:47:34 +00002241 for (y=0; y < (int) image->rows; y++)
2242 {
cristyc57f6942010-11-12 01:47:39 +00002243 p=GetCacheViewVirtualPixels(image_view,0,(ssize_t) y,image->columns,1,
cristy6710d842011-10-20 23:23:00 +00002244 exception);
cristy4c08aed2011-07-01 19:47:50 +00002245 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00002246 break;
2247 for (x=0; x < (int) image->columns; x++)
2248 {
cristye42f6582012-02-11 17:59:50 +00002249 color.red=(double) ClampToQuantum((MagickRealType) (red_map[i][j][
2250 (int) ScaleQuantumToChar(GetPixelRed(image,p))] << 8));
2251 color.green=(double) ClampToQuantum((MagickRealType) (green_map[i][j][
2252 (int) ScaleQuantumToChar(GetPixelGreen(image,p))] << 8));
2253 color.blue=(double) ClampToQuantum((MagickRealType) (blue_map[i][j][
2254 (int) ScaleQuantumToChar(GetPixelBlue(image,p))] << 8));
cristybb503372010-05-27 20:51:26 +00002255 pixel=(size_t) (((size_t) color.red & 0xe0) |
2256 (((size_t) color.green & 0xe0) >> 3) |
2257 (((size_t) color.blue & 0xc0) >> 6));
cristy3ed852e2009-09-05 21:47:34 +00002258 *q++=(char) pixel;
cristyed231572011-07-14 02:18:59 +00002259 p+=GetPixelChannels(image);
cristy3ed852e2009-09-05 21:47:34 +00002260 j++;
2261 if (j == 16)
2262 j=0;
2263 }
2264 q+=scanline_pad;
2265 i++;
2266 if (i == 2)
2267 i=0;
2268 }
cristyc57f6942010-11-12 01:47:39 +00002269 image_view=DestroyCacheView(image_view);
cristy3ed852e2009-09-05 21:47:34 +00002270 /*
2271 Free allocated memory.
2272 */
2273 for (i=0; i < 2; i++)
2274 for (j=0; j < 16; j++)
2275 {
2276 green_map[i][j]=(unsigned char *) RelinquishMagickMemory(green_map[i][j]);
2277 blue_map[i][j]=(unsigned char *) RelinquishMagickMemory(blue_map[i][j]);
2278 red_map[i][j]=(unsigned char *) RelinquishMagickMemory(red_map[i][j]);
2279 }
2280}
2281
2282/*
2283%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2284% %
2285% %
2286% %
2287% X D r a w I m a g e %
2288% %
2289% %
2290% %
2291%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2292%
2293% XDrawImage() draws a line on the image.
2294%
2295% The format of the XDrawImage method is:
2296%
cristy6710d842011-10-20 23:23:00 +00002297% MagickBooleanType XDrawImage(Display *display,const XPixelInfo *pixel,
2298% XDrawInfo *draw_info,Image *image,ExceptionInfo *exception)
cristy3ed852e2009-09-05 21:47:34 +00002299%
2300% A description of each parameter follows:
2301%
2302% o display: Specifies a connection to an X server; returned from
2303% XOpenDisplay.
2304%
2305% o pixel: Specifies a pointer to a XPixelInfo structure.
2306%
2307% o draw_info: Specifies a pointer to a XDrawInfo structure.
2308%
2309% o image: the image.
2310%
cristy6710d842011-10-20 23:23:00 +00002311% o exception: return any errors or warnings in this structure.
2312%
cristy3ed852e2009-09-05 21:47:34 +00002313*/
cristybcbda3f2011-09-03 13:01:22 +00002314MagickPrivate MagickBooleanType XDrawImage(Display *display,
cristy6710d842011-10-20 23:23:00 +00002315 const XPixelInfo *pixel,XDrawInfo *draw_info,Image *image,
2316 ExceptionInfo *exception)
cristy3ed852e2009-09-05 21:47:34 +00002317{
cristyc57f6942010-11-12 01:47:39 +00002318 CacheView
2319 *draw_view;
2320
cristy3ed852e2009-09-05 21:47:34 +00002321 GC
2322 draw_context;
2323
2324 Image
2325 *draw_image;
2326
2327 int
2328 x,
2329 y;
2330
2331 MagickBooleanType
2332 matte;
2333
cristy2ed42f62011-10-02 19:49:57 +00002334 Quantum
cristy5f95f4f2011-10-23 01:01:01 +00002335 virtual_pixel[CompositePixelChannel];
cristy2ed42f62011-10-02 19:49:57 +00002336
cristy3ed852e2009-09-05 21:47:34 +00002337 Pixmap
2338 draw_pixmap;
2339
2340 unsigned int
2341 depth,
2342 height,
2343 width;
2344
2345 Window
2346 root_window;
2347
2348 XGCValues
2349 context_values;
2350
2351 XImage
2352 *draw_ximage;
2353
2354 /*
2355 Initialize drawd image.
2356 */
2357 assert(display != (Display *) NULL);
2358 assert(pixel != (XPixelInfo *) NULL);
2359 assert(draw_info != (XDrawInfo *) NULL);
2360 assert(image != (Image *) NULL);
2361 if (image->debug != MagickFalse)
2362 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
2363 /*
2364 Initialize drawd pixmap.
2365 */
2366 root_window=XRootWindow(display,XDefaultScreen(display));
2367 depth=(unsigned int) XDefaultDepth(display,XDefaultScreen(display));
2368 draw_pixmap=XCreatePixmap(display,root_window,draw_info->width,
2369 draw_info->height,depth);
2370 if (draw_pixmap == (Pixmap) NULL)
2371 return(MagickFalse);
2372 /*
2373 Initialize graphics info.
2374 */
cristybb503372010-05-27 20:51:26 +00002375 context_values.background=(size_t) (~0);
cristy3ed852e2009-09-05 21:47:34 +00002376 context_values.foreground=0;
2377 context_values.line_width=(int) draw_info->line_width;
cristybb503372010-05-27 20:51:26 +00002378 draw_context=XCreateGC(display,root_window,(size_t)
cristy3ed852e2009-09-05 21:47:34 +00002379 (GCBackground | GCForeground | GCLineWidth),&context_values);
2380 if (draw_context == (GC) NULL)
2381 return(MagickFalse);
2382 /*
2383 Clear pixmap.
2384 */
2385 (void) XFillRectangle(display,draw_pixmap,draw_context,0,0,draw_info->width,
2386 draw_info->height);
2387 /*
2388 Draw line to pixmap.
2389 */
2390 (void) XSetBackground(display,draw_context,0);
cristybb503372010-05-27 20:51:26 +00002391 (void) XSetForeground(display,draw_context,(size_t) (~0));
cristydd05beb2010-11-21 21:23:39 +00002392 if (draw_info->stipple != (Pixmap) NULL)
2393 {
2394 (void) XSetFillStyle(display,draw_context,FillOpaqueStippled);
2395 (void) XSetStipple(display,draw_context,draw_info->stipple);
2396 }
cristy3ed852e2009-09-05 21:47:34 +00002397 switch (draw_info->element)
2398 {
2399 case PointElement:
2400 default:
2401 {
2402 (void) XDrawLines(display,draw_pixmap,draw_context,
2403 draw_info->coordinate_info,(int) draw_info->number_coordinates,
2404 CoordModeOrigin);
2405 break;
2406 }
2407 case LineElement:
2408 {
2409 (void) XDrawLine(display,draw_pixmap,draw_context,draw_info->line_info.x1,
2410 draw_info->line_info.y1,draw_info->line_info.x2,
2411 draw_info->line_info.y2);
2412 break;
2413 }
2414 case RectangleElement:
2415 {
2416 (void) XDrawRectangle(display,draw_pixmap,draw_context,
2417 (int) draw_info->rectangle_info.x,(int) draw_info->rectangle_info.y,
2418 (unsigned int) draw_info->rectangle_info.width,
2419 (unsigned int) draw_info->rectangle_info.height);
2420 break;
2421 }
2422 case FillRectangleElement:
2423 {
2424 (void) XFillRectangle(display,draw_pixmap,draw_context,
2425 (int) draw_info->rectangle_info.x,(int) draw_info->rectangle_info.y,
2426 (unsigned int) draw_info->rectangle_info.width,
2427 (unsigned int) draw_info->rectangle_info.height);
2428 break;
2429 }
2430 case CircleElement:
2431 case EllipseElement:
2432 {
2433 (void) XDrawArc(display,draw_pixmap,draw_context,
2434 (int) draw_info->rectangle_info.x,(int) draw_info->rectangle_info.y,
2435 (unsigned int) draw_info->rectangle_info.width,
2436 (unsigned int) draw_info->rectangle_info.height,0,360*64);
2437 break;
2438 }
2439 case FillCircleElement:
2440 case FillEllipseElement:
2441 {
2442 (void) XFillArc(display,draw_pixmap,draw_context,
2443 (int) draw_info->rectangle_info.x,(int) draw_info->rectangle_info.y,
2444 (unsigned int) draw_info->rectangle_info.width,
2445 (unsigned int) draw_info->rectangle_info.height,0,360*64);
2446 break;
2447 }
2448 case PolygonElement:
2449 {
2450 XPoint
2451 *coordinate_info;
2452
2453 coordinate_info=draw_info->coordinate_info;
2454 (void) XDrawLines(display,draw_pixmap,draw_context,coordinate_info,
2455 (int) draw_info->number_coordinates,CoordModeOrigin);
2456 (void) XDrawLine(display,draw_pixmap,draw_context,
2457 coordinate_info[draw_info->number_coordinates-1].x,
2458 coordinate_info[draw_info->number_coordinates-1].y,
2459 coordinate_info[0].x,coordinate_info[0].y);
2460 break;
2461 }
2462 case FillPolygonElement:
2463 {
2464 (void) XFillPolygon(display,draw_pixmap,draw_context,
2465 draw_info->coordinate_info,(int) draw_info->number_coordinates,Complex,
2466 CoordModeOrigin);
2467 break;
2468 }
2469 }
2470 (void) XFreeGC(display,draw_context);
2471 /*
2472 Initialize X image.
2473 */
2474 draw_ximage=XGetImage(display,draw_pixmap,0,0,draw_info->width,
2475 draw_info->height,AllPlanes,ZPixmap);
2476 if (draw_ximage == (XImage *) NULL)
2477 return(MagickFalse);
2478 (void) XFreePixmap(display,draw_pixmap);
2479 /*
2480 Initialize draw image.
2481 */
cristy6710d842011-10-20 23:23:00 +00002482 draw_image=AcquireImage((ImageInfo *) NULL,exception);
cristy3ed852e2009-09-05 21:47:34 +00002483 if (draw_image == (Image *) NULL)
2484 return(MagickFalse);
2485 draw_image->columns=draw_info->width;
2486 draw_image->rows=draw_info->height;
2487 /*
2488 Transfer drawn X image to image.
2489 */
2490 width=(unsigned int) image->columns;
2491 height=(unsigned int) image->rows;
2492 x=0;
2493 y=0;
2494 (void) XParseGeometry(draw_info->geometry,&x,&y,&width,&height);
cristy2ed42f62011-10-02 19:49:57 +00002495 (void) GetOneVirtualPixel(image,(ssize_t) x,(ssize_t) y,virtual_pixel,
cristy6710d842011-10-20 23:23:00 +00002496 exception);
cristye42f6582012-02-11 17:59:50 +00002497 draw_image->background_color.red=(double) virtual_pixel[RedPixelChannel];
2498 draw_image->background_color.green=(double) virtual_pixel[GreenPixelChannel];
2499 draw_image->background_color.blue=(double) virtual_pixel[BluePixelChannel];
2500 draw_image->background_color.alpha=(double) virtual_pixel[AlphaPixelChannel];
cristy6710d842011-10-20 23:23:00 +00002501 if (SetImageStorageClass(draw_image,DirectClass,exception) == MagickFalse)
cristy3ed852e2009-09-05 21:47:34 +00002502 return(MagickFalse);
2503 draw_image->matte=MagickTrue;
cristyc57f6942010-11-12 01:47:39 +00002504 draw_view=AcquireCacheView(draw_image);
cristy3ed852e2009-09-05 21:47:34 +00002505 for (y=0; y < (int) draw_image->rows; y++)
2506 {
cristyc57f6942010-11-12 01:47:39 +00002507 register int
cristy3ed852e2009-09-05 21:47:34 +00002508 x;
2509
cristy4c08aed2011-07-01 19:47:50 +00002510 register Quantum
cristyc47d1f82009-11-26 01:44:43 +00002511 *restrict q;
cristy3ed852e2009-09-05 21:47:34 +00002512
cristyc57f6942010-11-12 01:47:39 +00002513 q=QueueCacheViewAuthenticPixels(draw_view,0,(ssize_t) y,draw_image->columns,
2514 1,exception);
cristyacd2ed22011-08-30 01:44:23 +00002515 if (q == (Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00002516 break;
cristyc57f6942010-11-12 01:47:39 +00002517 for (x=0; x < (int) draw_image->columns; x++)
cristy3ed852e2009-09-05 21:47:34 +00002518 {
2519 if (XGetPixel(draw_ximage,x,y) == 0)
2520 {
2521 /*
2522 Set this pixel to the background color.
2523 */
cristy803640d2011-11-17 02:11:32 +00002524 SetPixelInfoPixel(draw_image,&draw_image->background_color,q);
cristy76761582011-09-18 02:14:00 +00002525 SetPixelAlpha(draw_image,(Quantum) (draw_info->stencil ==
cristy4c08aed2011-07-01 19:47:50 +00002526 OpaqueStencil ? TransparentAlpha : OpaqueAlpha),q);
cristy3ed852e2009-09-05 21:47:34 +00002527 }
2528 else
2529 {
2530 /*
2531 Set this pixel to the pen color.
2532 */
cristy4c08aed2011-07-01 19:47:50 +00002533 SetPixelRed(draw_image,ScaleShortToQuantum(
2534 pixel->pen_color.red),q);
2535 SetPixelGreen(draw_image,ScaleShortToQuantum(
2536 pixel->pen_color.green),q);
2537 SetPixelBlue(draw_image,ScaleShortToQuantum(
2538 pixel->pen_color.blue),q);
2539 SetPixelAlpha(draw_image,(Quantum) (draw_info->stencil ==
2540 OpaqueStencil ? OpaqueAlpha : TransparentAlpha),q);
cristy3ed852e2009-09-05 21:47:34 +00002541 }
cristyed231572011-07-14 02:18:59 +00002542 q+=GetPixelChannels(draw_image);
cristy3ed852e2009-09-05 21:47:34 +00002543 }
cristyc57f6942010-11-12 01:47:39 +00002544 if (SyncCacheViewAuthenticPixels(draw_view,exception) == MagickFalse)
cristy3ed852e2009-09-05 21:47:34 +00002545 break;
2546 }
cristyc57f6942010-11-12 01:47:39 +00002547 draw_view=DestroyCacheView(draw_view);
cristy3ed852e2009-09-05 21:47:34 +00002548 XDestroyImage(draw_ximage);
2549 /*
2550 Determine draw geometry.
2551 */
2552 (void) XParseGeometry(draw_info->geometry,&x,&y,&width,&height);
2553 if ((width != (unsigned int) draw_image->columns) ||
2554 (height != (unsigned int) draw_image->rows))
2555 {
2556 char
2557 image_geometry[MaxTextExtent];
2558
2559 /*
2560 Scale image.
2561 */
cristyb51dff52011-05-19 16:55:47 +00002562 (void) FormatLocaleString(image_geometry,MaxTextExtent,"%ux%u",
cristy3ed852e2009-09-05 21:47:34 +00002563 width,height);
cristye941a752011-10-15 01:52:48 +00002564 (void) TransformImage(&draw_image,(char *) NULL,image_geometry,
2565 exception);
cristy3ed852e2009-09-05 21:47:34 +00002566 }
2567 if (draw_info->degrees != 0.0)
2568 {
2569 Image
2570 *rotate_image;
2571
2572 int
2573 rotations;
2574
2575 MagickRealType
2576 normalized_degrees;
2577
2578 /*
2579 Rotate image.
2580 */
cristy6710d842011-10-20 23:23:00 +00002581 rotate_image=RotateImage(draw_image,draw_info->degrees,exception);
cristy3ed852e2009-09-05 21:47:34 +00002582 if (rotate_image == (Image *) NULL)
2583 return(MagickFalse);
2584 draw_image=DestroyImage(draw_image);
2585 draw_image=rotate_image;
2586 /*
2587 Annotation is relative to the degree of rotation.
2588 */
2589 normalized_degrees=draw_info->degrees;
2590 while (normalized_degrees < -45.0)
2591 normalized_degrees+=360.0;
2592 for (rotations=0; normalized_degrees > 45.0; rotations++)
2593 normalized_degrees-=90.0;
2594 switch (rotations % 4)
2595 {
2596 default:
2597 case 0:
2598 break;
2599 case 1:
2600 {
2601 /*
2602 Rotate 90 degrees.
2603 */
2604 x=x-(int) draw_image->columns/2;
2605 y=y+(int) draw_image->columns/2;
2606 break;
2607 }
2608 case 2:
2609 {
2610 /*
2611 Rotate 180 degrees.
2612 */
2613 x=x-(int) draw_image->columns;
2614 break;
2615 }
2616 case 3:
2617 {
2618 /*
2619 Rotate 270 degrees.
2620 */
2621 x=x-(int) draw_image->columns/2;
2622 y=y-(int) (draw_image->rows-(draw_image->columns/2));
2623 break;
2624 }
2625 }
2626 }
2627 /*
2628 Composite text onto the image.
2629 */
cristyc57f6942010-11-12 01:47:39 +00002630 draw_view=AcquireCacheView(draw_image);
cristy3ed852e2009-09-05 21:47:34 +00002631 for (y=0; y < (int) draw_image->rows; y++)
2632 {
cristyc57f6942010-11-12 01:47:39 +00002633 register int
cristy3ed852e2009-09-05 21:47:34 +00002634 x;
2635
cristy4c08aed2011-07-01 19:47:50 +00002636 register Quantum
cristyc47d1f82009-11-26 01:44:43 +00002637 *restrict q;
cristy3ed852e2009-09-05 21:47:34 +00002638
cristyc57f6942010-11-12 01:47:39 +00002639 q=GetCacheViewAuthenticPixels(draw_view,0,(ssize_t) y,draw_image->columns,1,
2640 exception);
cristyacd2ed22011-08-30 01:44:23 +00002641 if (q == (Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00002642 break;
cristyc57f6942010-11-12 01:47:39 +00002643 for (x=0; x < (int) draw_image->columns; x++)
cristy3ed852e2009-09-05 21:47:34 +00002644 {
cristy4c08aed2011-07-01 19:47:50 +00002645 if (GetPixelAlpha(image,q) != TransparentAlpha)
2646 SetPixelAlpha(draw_image,OpaqueAlpha,q);
cristyed231572011-07-14 02:18:59 +00002647 q+=GetPixelChannels(draw_image);
cristy3ed852e2009-09-05 21:47:34 +00002648 }
cristyc57f6942010-11-12 01:47:39 +00002649 if (SyncCacheViewAuthenticPixels(draw_view,exception) == MagickFalse)
cristy3ed852e2009-09-05 21:47:34 +00002650 break;
2651 }
cristyc57f6942010-11-12 01:47:39 +00002652 draw_view=DestroyCacheView(draw_view);
cristy3ed852e2009-09-05 21:47:34 +00002653 (void) XParseGeometry(draw_info->geometry,&x,&y,&width,&height);
2654 if (draw_info->stencil == TransparentStencil)
cristye4a40472011-12-22 02:56:19 +00002655 (void) CompositeImage(image,CopyAlphaCompositeOp,draw_image,(ssize_t) x,
cristye941a752011-10-15 01:52:48 +00002656 (ssize_t) y,exception);
cristy3ed852e2009-09-05 21:47:34 +00002657 else
2658 {
2659 matte=image->matte;
cristyc57f6942010-11-12 01:47:39 +00002660 (void) CompositeImage(image,OverCompositeOp,draw_image,(ssize_t) x,
cristye941a752011-10-15 01:52:48 +00002661 (ssize_t) y,exception);
cristy3ed852e2009-09-05 21:47:34 +00002662 image->matte=matte;
2663 }
2664 draw_image=DestroyImage(draw_image);
2665 return(MagickTrue);
2666}
2667
2668/*
2669%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2670% %
2671% %
2672% %
2673% X E r r o r %
2674% %
2675% %
2676% %
2677%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2678%
2679% XError() ignores BadWindow errors for XQueryTree and XGetWindowAttributes,
2680% and ignores BadDrawable errors for XGetGeometry, and ignores BadValue errors
cristybcbda3f2011-09-03 13:01:22 +00002681% for XQueryColor. It returns MagickFalse in those cases. Otherwise it
2682% returns True.
cristy3ed852e2009-09-05 21:47:34 +00002683%
2684% The format of the XError function is:
2685%
cristybcbda3f2011-09-03 13:01:22 +00002686% int XError(display,error)
cristy3ed852e2009-09-05 21:47:34 +00002687%
2688% A description of each parameter follows:
2689%
2690% o display: Specifies a pointer to the Display structure; returned from
2691% XOpenDisplay.
2692%
2693% o error: Specifies the error event.
2694%
2695*/
2696
2697#if defined(__cplusplus) || defined(c_plusplus)
2698extern "C" {
2699#endif
2700
2701MagickExport int XError(Display *display,XErrorEvent *error)
2702{
2703 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
2704 assert(display != (Display *) NULL);
2705 assert(error != (XErrorEvent *) NULL);
2706 xerror_alert=MagickTrue;
2707 switch (error->request_code)
2708 {
2709 case X_GetGeometry:
2710 {
2711 if ((int) error->error_code == BadDrawable)
2712 return(MagickFalse);
2713 break;
2714 }
2715 case X_GetWindowAttributes:
2716 case X_QueryTree:
2717 {
2718 if ((int) error->error_code == BadWindow)
2719 return(MagickFalse);
2720 break;
2721 }
2722 case X_QueryColors:
2723 {
2724 if ((int) error->error_code == BadValue)
2725 return(MagickFalse);
2726 break;
2727 }
2728 }
2729 return(MagickTrue);
2730}
2731
2732#if defined(__cplusplus) || defined(c_plusplus)
2733}
2734#endif
2735
2736/*
2737%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2738% %
2739% %
2740% %
2741% X F r e e R e s o u r c e s %
2742% %
2743% %
2744% %
2745%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2746%
2747% XFreeResources() frees X11 resources.
2748%
2749% The format of the XFreeResources method is:
2750%
2751% void XFreeResources(Display *display,XVisualInfo *visual_info,
2752% XStandardColormap *map_info,XPixelInfo *pixel,XFontStruct *font_info,
2753% XResourceInfo *resource_info,XWindowInfo *window_info)
2754% resource_info,window_info)
2755%
2756% A description of each parameter follows:
2757%
2758% o display: Specifies a connection to an X server; returned from
2759% XOpenDisplay.
2760%
2761% o visual_info: Specifies a pointer to a X11 XVisualInfo structure;
2762% returned from XGetVisualInfo.
2763%
2764% o map_info: If map_type is specified, this structure is initialized
2765% with info from the Standard Colormap.
2766%
2767% o pixel: Specifies a pointer to a XPixelInfo structure.
2768%
2769% o font_info: Specifies a pointer to a XFontStruct structure.
2770%
2771% o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
2772%
2773% o window_info: Specifies a pointer to a X11 XWindowInfo structure.
2774%
2775*/
cristybcbda3f2011-09-03 13:01:22 +00002776MagickPrivate void XFreeResources(Display *display,XVisualInfo *visual_info,
cristy3ed852e2009-09-05 21:47:34 +00002777 XStandardColormap *map_info,XPixelInfo *pixel,XFontStruct *font_info,
2778 XResourceInfo *resource_info,XWindowInfo *window_info)
2779{
2780 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
2781 assert(display != (Display *) NULL);
2782 assert(resource_info != (XResourceInfo *) NULL);
2783 if (window_info != (XWindowInfo *) NULL)
2784 {
2785 /*
2786 Free X image.
2787 */
2788 if (window_info->ximage != (XImage *) NULL)
2789 XDestroyImage(window_info->ximage);
2790 if (window_info->id != (Window) NULL)
2791 {
2792 /*
2793 Free destroy window and free cursors.
2794 */
2795 if (window_info->id != XRootWindow(display,visual_info->screen))
2796 (void) XDestroyWindow(display,window_info->id);
2797 if (window_info->annotate_context != (GC) NULL)
2798 (void) XFreeGC(display,window_info->annotate_context);
2799 if (window_info->highlight_context != (GC) NULL)
2800 (void) XFreeGC(display,window_info->highlight_context);
2801 if (window_info->widget_context != (GC) NULL)
2802 (void) XFreeGC(display,window_info->widget_context);
2803 if (window_info->cursor != (Cursor) NULL)
2804 (void) XFreeCursor(display,window_info->cursor);
2805 window_info->cursor=(Cursor) NULL;
2806 if (window_info->busy_cursor != (Cursor) NULL)
2807 (void) XFreeCursor(display,window_info->busy_cursor);
2808 window_info->busy_cursor=(Cursor) NULL;
2809 }
2810 }
2811 /*
2812 Free font.
2813 */
2814 if (font_info != (XFontStruct *) NULL)
cristyaafc1922011-03-04 16:59:40 +00002815 {
2816 (void) XFreeFont(display,font_info);
2817 font_info=(XFontStruct *) NULL;
2818 }
cristy3ed852e2009-09-05 21:47:34 +00002819 if (map_info != (XStandardColormap *) NULL)
2820 {
2821 /*
2822 Free X Standard Colormap.
2823 */
2824 if (resource_info->map_type == (char *) NULL)
2825 (void) XFreeStandardColormap(display,visual_info,map_info,pixel);
2826 (void) XFree((void *) map_info);
2827 }
2828 /*
2829 Free X visual info.
2830 */
2831 if (visual_info != (XVisualInfo *) NULL)
2832 (void) XFree((void *) visual_info);
2833 if (resource_info->close_server != MagickFalse)
2834 (void) XCloseDisplay(display);
2835}
2836
2837/*
2838%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2839% %
2840% %
2841% %
2842% X F r e e S t a n d a r d C o l o r m a p %
2843% %
2844% %
2845% %
2846%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2847%
2848% XFreeStandardColormap() frees an X11 colormap.
2849%
2850% The format of the XFreeStandardColormap method is:
2851%
2852% void XFreeStandardColormap(Display *display,
2853% const XVisualInfo *visual_info,XStandardColormap *map_info,
2854% XPixelInfo *pixel)
2855%
2856% A description of each parameter follows:
2857%
2858% o display: Specifies a connection to an X server; returned from
2859% XOpenDisplay.
2860%
2861% o visual_info: Specifies a pointer to a X11 XVisualInfo structure;
2862% returned from XGetVisualInfo.
2863%
2864% o map_info: If map_type is specified, this structure is initialized
2865% with info from the Standard Colormap.
2866%
2867% o pixel: Specifies a pointer to a XPixelInfo structure.
2868%
2869*/
cristybcbda3f2011-09-03 13:01:22 +00002870MagickPrivate void XFreeStandardColormap(Display *display,
cristy3ed852e2009-09-05 21:47:34 +00002871 const XVisualInfo *visual_info,XStandardColormap *map_info,XPixelInfo *pixel)
2872{
2873 /*
2874 Free colormap.
2875 */
2876 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
2877 assert(display != (Display *) NULL);
2878 assert(visual_info != (XVisualInfo *) NULL);
2879 assert(map_info != (XStandardColormap *) NULL);
2880 (void) XFlush(display);
2881 if (map_info->colormap != (Colormap) NULL)
2882 {
2883 if (map_info->colormap != XDefaultColormap(display,visual_info->screen))
2884 (void) XFreeColormap(display,map_info->colormap);
2885 else
2886 if (pixel != (XPixelInfo *) NULL)
2887 if ((visual_info->klass != TrueColor) &&
2888 (visual_info->klass != DirectColor))
2889 (void) XFreeColors(display,map_info->colormap,pixel->pixels,
2890 (int) pixel->colors,0);
2891 }
2892 map_info->colormap=(Colormap) NULL;
2893 if (pixel != (XPixelInfo *) NULL)
2894 {
cristyf2faecf2010-05-28 19:19:36 +00002895 if (pixel->pixels != (unsigned long *) NULL)
2896 pixel->pixels=(unsigned long *) RelinquishMagickMemory(pixel->pixels);
2897 pixel->pixels=(unsigned long *) NULL;
cristy3ed852e2009-09-05 21:47:34 +00002898 }
2899}
2900
2901/*
2902%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2903% %
2904% %
2905% %
2906% X G e t A n n o t a t e I n f o %
2907% %
2908% %
2909% %
2910%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2911%
2912% XGetAnnotateInfo() initializes the AnnotateInfo structure.
2913%
2914% The format of the XGetAnnotateInfo method is:
2915%
2916% void XGetAnnotateInfo(XAnnotateInfo *annotate_info)
2917%
2918% A description of each parameter follows:
2919%
2920% o annotate_info: Specifies a pointer to a XAnnotateInfo structure.
2921%
2922*/
cristybcbda3f2011-09-03 13:01:22 +00002923MagickPrivate void XGetAnnotateInfo(XAnnotateInfo *annotate_info)
cristy3ed852e2009-09-05 21:47:34 +00002924{
2925 /*
2926 Initialize annotate structure.
2927 */
2928 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
2929 assert(annotate_info != (XAnnotateInfo *) NULL);
2930 annotate_info->x=0;
2931 annotate_info->y=0;
2932 annotate_info->width=0;
2933 annotate_info->height=0;
2934 annotate_info->stencil=ForegroundStencil;
2935 annotate_info->degrees=0.0;
2936 annotate_info->font_info=(XFontStruct *) NULL;
2937 annotate_info->text=(char *) NULL;
2938 *annotate_info->geometry='\0';
2939 annotate_info->previous=(XAnnotateInfo *) NULL;
2940 annotate_info->next=(XAnnotateInfo *) NULL;
2941 (void) XSupportsLocale();
2942 (void) XSetLocaleModifiers("");
2943}
2944
2945/*
2946%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2947% %
2948% %
2949% %
2950% X G e t M a p I n f o %
2951% %
2952% %
2953% %
2954%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2955%
2956% XGetMapInfo() initializes the XStandardColormap structure.
2957%
2958% The format of the XStandardColormap method is:
2959%
2960% void XGetMapInfo(const XVisualInfo *visual_info,const Colormap colormap,
2961% XStandardColormap *map_info)
2962%
2963% A description of each parameter follows:
2964%
2965% o colormap: Specifies the ID of the X server colormap.
2966%
2967% o visual_info: Specifies a pointer to a X11 XVisualInfo structure;
2968% returned from XGetVisualInfo.
2969%
2970% o map_info: Specifies a pointer to a X11 XStandardColormap structure.
2971%
2972*/
cristybcbda3f2011-09-03 13:01:22 +00002973MagickPrivate void XGetMapInfo(const XVisualInfo *visual_info,
cristy3ed852e2009-09-05 21:47:34 +00002974 const Colormap colormap,XStandardColormap *map_info)
2975{
2976 /*
2977 Initialize map info.
2978 */
2979 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
2980 assert(visual_info != (XVisualInfo *) NULL);
2981 assert(map_info != (XStandardColormap *) NULL);
2982 map_info->colormap=colormap;
2983 map_info->red_max=visual_info->red_mask;
cristybb503372010-05-27 20:51:26 +00002984 map_info->red_mult=(size_t) (map_info->red_max != 0 ? 1 : 0);
cristy3ed852e2009-09-05 21:47:34 +00002985 if (map_info->red_max != 0)
2986 while ((map_info->red_max & 0x01) == 0)
2987 {
2988 map_info->red_max>>=1;
2989 map_info->red_mult<<=1;
2990 }
2991 map_info->green_max=visual_info->green_mask;
cristybb503372010-05-27 20:51:26 +00002992 map_info->green_mult=(size_t) (map_info->green_max != 0 ? 1 : 0);
cristy3ed852e2009-09-05 21:47:34 +00002993 if (map_info->green_max != 0)
2994 while ((map_info->green_max & 0x01) == 0)
2995 {
2996 map_info->green_max>>=1;
2997 map_info->green_mult<<=1;
2998 }
2999 map_info->blue_max=visual_info->blue_mask;
cristybb503372010-05-27 20:51:26 +00003000 map_info->blue_mult=(size_t) (map_info->blue_max != 0 ? 1 : 0);
cristy3ed852e2009-09-05 21:47:34 +00003001 if (map_info->blue_max != 0)
3002 while ((map_info->blue_max & 0x01) == 0)
3003 {
3004 map_info->blue_max>>=1;
3005 map_info->blue_mult<<=1;
3006 }
3007 map_info->base_pixel=0;
3008}
3009
3010/*
3011%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3012% %
3013% %
3014% %
3015% X G e t P i x e l I n f o %
3016% %
3017% %
3018% %
3019%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3020%
cristy101ab702011-10-13 13:06:32 +00003021% XGetPixelInfo() initializes the PixelInfo structure.
cristy3ed852e2009-09-05 21:47:34 +00003022%
cristy4c08aed2011-07-01 19:47:50 +00003023% The format of the XGetPixelInfo method is:
cristy3ed852e2009-09-05 21:47:34 +00003024%
cristy4c08aed2011-07-01 19:47:50 +00003025% void XGetPixelInfo(Display *display,const XVisualInfo *visual_info,
cristy3ed852e2009-09-05 21:47:34 +00003026% const XStandardColormap *map_info,const XResourceInfo *resource_info,
3027% Image *image,XPixelInfo *pixel)
3028% pixel)
3029%
3030% A description of each parameter follows:
3031%
3032% o display: Specifies a connection to an X server; returned from
3033% XOpenDisplay.
3034%
3035% o visual_info: Specifies a pointer to a X11 XVisualInfo structure;
3036% returned from XGetVisualInfo.
3037%
3038% o map_info: If map_type is specified, this structure is initialized
3039% with info from the Standard Colormap.
3040%
3041% o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
3042%
3043% o image: the image.
3044%
3045% o pixel: Specifies a pointer to a XPixelInfo structure.
3046%
3047*/
cristybcbda3f2011-09-03 13:01:22 +00003048MagickPrivate void XGetPixelInfo(Display *display,
cristy3ed852e2009-09-05 21:47:34 +00003049 const XVisualInfo *visual_info,const XStandardColormap *map_info,
3050 const XResourceInfo *resource_info,Image *image,XPixelInfo *pixel)
3051{
3052 static const char
3053 *PenColors[MaxNumberPens]=
3054 {
3055 "#000000000000", /* black */
3056 "#00000000ffff", /* blue */
3057 "#0000ffffffff", /* cyan */
3058 "#0000ffff0000", /* green */
3059 "#bdbdbdbdbdbd", /* gray */
3060 "#ffff00000000", /* red */
3061 "#ffff0000ffff", /* magenta */
3062 "#ffffffff0000", /* yellow */
3063 "#ffffffffffff", /* white */
3064 "#bdbdbdbdbdbd", /* gray */
3065 "#bdbdbdbdbdbd" /* gray */
3066 };
3067
3068 Colormap
3069 colormap;
3070
cristybb503372010-05-27 20:51:26 +00003071 register ssize_t
cristy3ed852e2009-09-05 21:47:34 +00003072 i;
3073
3074 Status
3075 status;
3076
3077 unsigned int
3078 packets;
3079
3080 /*
3081 Initialize pixel info.
3082 */
3083 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
3084 assert(display != (Display *) NULL);
3085 assert(visual_info != (XVisualInfo *) NULL);
3086 assert(map_info != (XStandardColormap *) NULL);
3087 assert(resource_info != (XResourceInfo *) NULL);
3088 assert(pixel != (XPixelInfo *) NULL);
3089 pixel->colors=0;
3090 if (image != (Image *) NULL)
3091 if (image->storage_class == PseudoClass)
cristyc57f6942010-11-12 01:47:39 +00003092 pixel->colors=(ssize_t) image->colors;
cristy3ed852e2009-09-05 21:47:34 +00003093 packets=(unsigned int)
3094 MagickMax((int) pixel->colors,visual_info->colormap_size)+MaxNumberPens;
cristyf2faecf2010-05-28 19:19:36 +00003095 if (pixel->pixels != (unsigned long *) NULL)
3096 pixel->pixels=(unsigned long *) RelinquishMagickMemory(pixel->pixels);
3097 pixel->pixels=(unsigned long *) AcquireQuantumMemory(packets,
cristy3ed852e2009-09-05 21:47:34 +00003098 sizeof(pixel->pixels));
cristyf2faecf2010-05-28 19:19:36 +00003099 if (pixel->pixels == (unsigned long *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00003100 ThrowXWindowFatalException(ResourceLimitFatalError,"UnableToGetPixelInfo",
3101 image->filename);
3102 /*
3103 Set foreground color.
3104 */
3105 colormap=map_info->colormap;
3106 (void) XParseColor(display,colormap,(char *) ForegroundColor,
3107 &pixel->foreground_color);
3108 status=XParseColor(display,colormap,resource_info->foreground_color,
3109 &pixel->foreground_color);
3110 if (status == False)
3111 ThrowXWindowFatalException(XServerError,"ColorIsNotKnownToServer",
3112 resource_info->foreground_color);
3113 pixel->foreground_color.pixel=
3114 XStandardPixel(map_info,&pixel->foreground_color);
3115 pixel->foreground_color.flags=(char) (DoRed | DoGreen | DoBlue);
3116 /*
3117 Set background color.
3118 */
3119 (void) XParseColor(display,colormap,"#d6d6d6d6d6d6",&pixel->background_color);
3120 status=XParseColor(display,colormap,resource_info->background_color,
3121 &pixel->background_color);
3122 if (status == False)
3123 ThrowXWindowFatalException(XServerError,"ColorIsNotKnownToServer",
3124 resource_info->background_color);
3125 pixel->background_color.pixel=
3126 XStandardPixel(map_info,&pixel->background_color);
3127 pixel->background_color.flags=(char) (DoRed | DoGreen | DoBlue);
3128 /*
3129 Set border color.
3130 */
3131 (void) XParseColor(display,colormap,(char *) BorderColor,
3132 &pixel->border_color);
3133 status=XParseColor(display,colormap,resource_info->border_color,
3134 &pixel->border_color);
3135 if (status == False)
3136 ThrowXWindowFatalException(XServerError,"ColorIsNotKnownToServer",
3137 resource_info->border_color);
3138 pixel->border_color.pixel=XStandardPixel(map_info,&pixel->border_color);
3139 pixel->border_color.flags=(char) (DoRed | DoGreen | DoBlue);
3140 /*
3141 Set matte color.
3142 */
3143 pixel->matte_color=pixel->background_color;
3144 if (resource_info->matte_color != (char *) NULL)
3145 {
3146 /*
3147 Matte color is specified as a X resource or command line argument.
3148 */
3149 status=XParseColor(display,colormap,resource_info->matte_color,
3150 &pixel->matte_color);
3151 if (status == False)
3152 ThrowXWindowFatalException(XServerError,"ColorIsNotKnownToServer",
3153 resource_info->matte_color);
3154 pixel->matte_color.pixel=XStandardPixel(map_info,&pixel->matte_color);
3155 pixel->matte_color.flags=(char) (DoRed | DoGreen | DoBlue);
3156 }
3157 /*
3158 Set highlight color.
3159 */
3160 pixel->highlight_color.red=(unsigned short) ((
3161 pixel->matte_color.red*ScaleQuantumToShort(HighlightModulate))/65535L+
3162 (ScaleQuantumToShort((Quantum) (QuantumRange-HighlightModulate))));
3163 pixel->highlight_color.green=(unsigned short) ((
3164 pixel->matte_color.green*ScaleQuantumToShort(HighlightModulate))/65535L+
3165 (ScaleQuantumToShort((Quantum) (QuantumRange-HighlightModulate))));
3166 pixel->highlight_color.blue=(unsigned short) ((
3167 pixel->matte_color.blue*ScaleQuantumToShort(HighlightModulate))/65535L+
3168 (ScaleQuantumToShort((Quantum) (QuantumRange-HighlightModulate))));
3169 pixel->highlight_color.pixel=
3170 XStandardPixel(map_info,&pixel->highlight_color);
3171 pixel->highlight_color.flags=(char) (DoRed | DoGreen | DoBlue);
3172 /*
3173 Set shadow color.
3174 */
3175 pixel->shadow_color.red=(unsigned short) (((MagickRealType)
3176 pixel->matte_color.red*ScaleQuantumToShort(ShadowModulate))/65535L);
3177 pixel->shadow_color.green=(unsigned short) (((MagickRealType)
3178 pixel->matte_color.green*ScaleQuantumToShort(ShadowModulate))/65535L);
3179 pixel->shadow_color.blue=(unsigned short) (((MagickRealType)
3180 pixel->matte_color.blue*ScaleQuantumToShort(ShadowModulate))/65535L);
3181 pixel->shadow_color.pixel=XStandardPixel(map_info,&pixel->shadow_color);
3182 pixel->shadow_color.flags=(char) (DoRed | DoGreen | DoBlue);
3183 /*
3184 Set depth color.
3185 */
3186 pixel->depth_color.red=(unsigned short) (((MagickRealType)
3187 pixel->matte_color.red*ScaleQuantumToShort(DepthModulate))/65535L);
3188 pixel->depth_color.green=(unsigned short) (((MagickRealType)
3189 pixel->matte_color.green*ScaleQuantumToShort(DepthModulate))/65535L);
3190 pixel->depth_color.blue=(unsigned short) (((MagickRealType)
3191 pixel->matte_color.blue*ScaleQuantumToShort(DepthModulate))/65535L);
3192 pixel->depth_color.pixel=XStandardPixel(map_info,&pixel->depth_color);
3193 pixel->depth_color.flags=(char) (DoRed | DoGreen | DoBlue);
3194 /*
3195 Set trough color.
3196 */
3197 pixel->trough_color.red=(unsigned short) (((MagickRealType)
3198 pixel->matte_color.red*ScaleQuantumToShort(TroughModulate))/65535L);
3199 pixel->trough_color.green=(unsigned short) (((MagickRealType)
3200 pixel->matte_color.green*ScaleQuantumToShort(TroughModulate))/65535L);
3201 pixel->trough_color.blue=(unsigned short) (((MagickRealType)
3202 pixel->matte_color.blue*ScaleQuantumToShort(TroughModulate))/65535L);
3203 pixel->trough_color.pixel=XStandardPixel(map_info,&pixel->trough_color);
3204 pixel->trough_color.flags=(char) (DoRed | DoGreen | DoBlue);
3205 /*
3206 Set pen color.
3207 */
3208 for (i=0; i < MaxNumberPens; i++)
3209 {
3210 (void) XParseColor(display,colormap,(char *) PenColors[i],
3211 &pixel->pen_colors[i]);
3212 status=XParseColor(display,colormap,resource_info->pen_colors[i],
3213 &pixel->pen_colors[i]);
3214 if (status == False)
3215 ThrowXWindowFatalException(XServerError,"ColorIsNotKnownToServer",
3216 resource_info->pen_colors[i]);
3217 pixel->pen_colors[i].pixel=XStandardPixel(map_info,&pixel->pen_colors[i]);
3218 pixel->pen_colors[i].flags=(char) (DoRed | DoGreen | DoBlue);
3219 }
3220 pixel->box_color=pixel->background_color;
3221 pixel->pen_color=pixel->foreground_color;
3222 pixel->box_index=0;
3223 pixel->pen_index=1;
3224 if (image != (Image *) NULL)
3225 {
3226 if ((resource_info->gamma_correct != MagickFalse) &&
3227 (image->gamma != 0.0))
3228 {
3229 GeometryInfo
3230 geometry_info;
3231
3232 MagickStatusType
3233 flags;
3234
3235 /*
3236 Initialize map relative to display and image gamma.
3237 */
3238 flags=ParseGeometry(resource_info->display_gamma,&geometry_info);
3239 red_gamma=geometry_info.rho;
3240 green_gamma=geometry_info.sigma;
3241 if ((flags & SigmaValue) == 0)
3242 green_gamma=red_gamma;
3243 blue_gamma=geometry_info.xi;
3244 if ((flags & XiValue) == 0)
3245 blue_gamma=red_gamma;
3246 red_gamma*=image->gamma;
3247 green_gamma*=image->gamma;
3248 blue_gamma*=image->gamma;
3249 }
3250 if (image->storage_class == PseudoClass)
3251 {
3252 /*
3253 Initialize pixel array for images of type PseudoClass.
3254 */
cristybb503372010-05-27 20:51:26 +00003255 for (i=0; i < (ssize_t) image->colors; i++)
cristy4c08aed2011-07-01 19:47:50 +00003256 pixel->pixels[i]=XGammaPacket(map_info,image->colormap+i);
cristy3ed852e2009-09-05 21:47:34 +00003257 for (i=0; i < MaxNumberPens; i++)
3258 pixel->pixels[image->colors+i]=pixel->pen_colors[i].pixel;
3259 pixel->colors+=MaxNumberPens;
3260 }
3261 }
3262}
3263
3264/*
3265%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3266% %
3267% %
3268% %
3269% X G e t R e s o u r c e C l a s s %
3270% %
3271% %
3272% %
3273%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3274%
3275% XGetResourceClass() queries the X server for the specified resource name or
3276% class. If the resource name or class is not defined in the database, the
3277% supplied default value is returned.
3278%
3279% The format of the XGetResourceClass method is:
3280%
3281% char *XGetResourceClass(XrmDatabase database,const char *client_name,
3282% const char *keyword,char *resource_default)
3283%
3284% A description of each parameter follows:
3285%
3286% o database: Specifies a resource database; returned from
3287% XrmGetStringDatabase.
3288%
3289% o client_name: Specifies the application name used to retrieve resource
3290% info from the X server database.
3291%
3292% o keyword: Specifies the keyword of the value being retrieved.
3293%
3294% o resource_default: Specifies the default value to return if the query
3295% fails to find the specified keyword/class.
3296%
3297*/
3298MagickExport char *XGetResourceClass(XrmDatabase database,
3299 const char *client_name,const char *keyword,char *resource_default)
3300{
3301 char
3302 resource_class[MaxTextExtent],
3303 resource_name[MaxTextExtent];
3304
3305 static char
3306 *resource_type;
3307
3308 Status
3309 status;
3310
3311 XrmValue
3312 resource_value;
3313
3314 if (database == (XrmDatabase) NULL)
3315 return(resource_default);
3316 *resource_name='\0';
3317 *resource_class='\0';
3318 if (keyword != (char *) NULL)
3319 {
3320 int
3321 c,
3322 k;
3323
3324 /*
3325 Initialize resource keyword and class.
3326 */
cristyb51dff52011-05-19 16:55:47 +00003327 (void) FormatLocaleString(resource_name,MaxTextExtent,"%s.%s",
cristy3ed852e2009-09-05 21:47:34 +00003328 client_name,keyword);
3329 c=(int) (*client_name);
3330 if ((c >= XK_a) && (c <= XK_z))
3331 c-=(XK_a-XK_A);
3332 else
3333 if ((c >= XK_agrave) && (c <= XK_odiaeresis))
3334 c-=(XK_agrave-XK_Agrave);
3335 else
3336 if ((c >= XK_oslash) && (c <= XK_thorn))
3337 c-=(XK_oslash-XK_Ooblique);
3338 k=(int) (*keyword);
3339 if ((k >= XK_a) && (k <= XK_z))
3340 k-=(XK_a-XK_A);
3341 else
3342 if ((k >= XK_agrave) && (k <= XK_odiaeresis))
3343 k-=(XK_agrave-XK_Agrave);
3344 else
3345 if ((k >= XK_oslash) && (k <= XK_thorn))
3346 k-=(XK_oslash-XK_Ooblique);
cristyb51dff52011-05-19 16:55:47 +00003347 (void) FormatLocaleString(resource_class,MaxTextExtent,"%c%s.%c%s",c,
cristy3ed852e2009-09-05 21:47:34 +00003348 client_name+1,k,keyword+1);
3349 }
3350 status=XrmGetResource(database,resource_name,resource_class,&resource_type,
3351 &resource_value);
3352 if (status == False)
3353 return(resource_default);
3354 return(resource_value.addr);
3355}
3356
3357/*
3358%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3359% %
3360% %
3361% %
3362% X G e t R e s o u r c e D a t a b a s e %
3363% %
3364% %
3365% %
3366%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3367%
3368% XGetResourceDatabase() creates a new resource database and initializes it.
3369%
3370% The format of the XGetResourceDatabase method is:
3371%
3372% XrmDatabase XGetResourceDatabase(Display *display,
3373% const char *client_name)
3374%
3375% A description of each parameter follows:
3376%
3377% o database: XGetResourceDatabase() returns the database after it is
3378% initialized.
3379%
3380% o display: Specifies a connection to an X server; returned from
3381% XOpenDisplay.
3382%
3383% o client_name: Specifies the application name used to retrieve resource
3384% info from the X server database.
3385%
3386*/
3387MagickExport XrmDatabase XGetResourceDatabase(Display *display,
3388 const char *client_name)
3389{
3390 char
3391 filename[MaxTextExtent];
3392
3393 int
3394 c;
3395
3396 register const char
3397 *p;
3398
3399 XrmDatabase
3400 resource_database,
3401 server_database;
3402
3403 if (display == (Display *) NULL)
3404 return((XrmDatabase) NULL);
3405 assert(client_name != (char *) NULL);
3406 /*
3407 Initialize resource database.
3408 */
3409 XrmInitialize();
3410 (void) XGetDefault(display,(char *) client_name,"dummy");
3411 resource_database=XrmGetDatabase(display);
3412 /*
3413 Combine application database.
3414 */
3415 if (client_name != (char *) NULL)
3416 {
3417 /*
3418 Get basename of client.
3419 */
3420 p=client_name+(strlen(client_name)-1);
3421 while ((p > client_name) && (*p != '/'))
3422 p--;
3423 if (*p == '/')
3424 client_name=p+1;
3425 }
3426 c=(int) (*client_name);
3427 if ((c >= XK_a) && (c <= XK_z))
3428 c-=(XK_a-XK_A);
3429 else
3430 if ((c >= XK_agrave) && (c <= XK_odiaeresis))
3431 c-=(XK_agrave-XK_Agrave);
3432 else
3433 if ((c >= XK_oslash) && (c <= XK_thorn))
3434 c-=(XK_oslash-XK_Ooblique);
3435#if defined(X11_APPLICATION_PATH)
cristyb51dff52011-05-19 16:55:47 +00003436 (void) FormatLocaleString(filename,MaxTextExtent,"%s%c%s",
cristy3ed852e2009-09-05 21:47:34 +00003437 X11_APPLICATION_PATH,c,client_name+1);
3438 (void) XrmCombineFileDatabase(filename,&resource_database,MagickFalse);
3439#endif
3440 if (XResourceManagerString(display) != (char *) NULL)
3441 {
3442 /*
3443 Combine server database.
3444 */
3445 server_database=XrmGetStringDatabase(XResourceManagerString(display));
3446 XrmCombineDatabase(server_database,&resource_database,MagickFalse);
3447 }
3448 /*
3449 Merge user preferences database.
3450 */
3451#if defined(X11_PREFERENCES_PATH)
cristyb51dff52011-05-19 16:55:47 +00003452 (void) FormatLocaleString(filename,MaxTextExtent,"%s%src",
cristy3ed852e2009-09-05 21:47:34 +00003453 X11_PREFERENCES_PATH,client_name);
3454 ExpandFilename(filename);
3455 (void) XrmCombineFileDatabase(filename,&resource_database,MagickFalse);
3456#endif
3457 return(resource_database);
3458}
3459
3460/*
3461%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3462% %
3463% %
3464% %
3465% X G e t R e s o u r c e I n f o %
3466% %
3467% %
3468% %
3469%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3470%
3471% XGetResourceInfo(image_info,) initializes the ResourceInfo structure.
3472%
3473% The format of the XGetResourceInfo method is:
3474%
3475% void XGetResourceInfo(const ImageInfo *image_info,XrmDatabase database,
3476% const char *client_name,XResourceInfo *resource_info)
3477%
3478% A description of each parameter follows:
3479%
3480% o image_info: the image info.
3481%
3482% o database: Specifies a resource database; returned from
3483% XrmGetStringDatabase.
3484%
3485% o client_name: Specifies the application name used to retrieve
3486% resource info from the X server database.
3487%
3488% o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
3489%
3490*/
3491MagickExport void XGetResourceInfo(const ImageInfo *image_info,
3492 XrmDatabase database,const char *client_name,XResourceInfo *resource_info)
3493{
3494 char
cristy00976d82011-02-20 20:31:28 +00003495 *directory,
cristy3ed852e2009-09-05 21:47:34 +00003496 *resource_value;
3497
3498 /*
3499 Initialize resource info fields.
3500 */
3501 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
3502 assert(resource_info != (XResourceInfo *) NULL);
3503 (void) ResetMagickMemory(resource_info,0,sizeof(*resource_info));
3504 resource_info->resource_database=database;
3505 resource_info->image_info=(ImageInfo *) image_info;
3506 (void) SetImageInfoProgressMonitor(resource_info->image_info,
3507 XMagickProgressMonitor,(void *) NULL);
3508 resource_info->quantize_info=CloneQuantizeInfo((QuantizeInfo *) NULL);
3509 resource_info->close_server=MagickTrue;
3510 resource_info->client_name=AcquireString(client_name);
3511 resource_value=XGetResourceClass(database,client_name,"backdrop",
3512 (char *) "False");
3513 resource_info->backdrop=IsMagickTrue(resource_value);
3514 resource_info->background_color=XGetResourceInstance(database,client_name,
3515 "background",(char *) "#d6d6d6d6d6d6");
3516 resource_info->border_color=XGetResourceInstance(database,client_name,
3517 "borderColor",BorderColor);
3518 resource_value=XGetResourceClass(database,client_name,"borderWidth",
3519 (char *) "2");
cristy00976d82011-02-20 20:31:28 +00003520 resource_info->border_width=(unsigned int) StringToUnsignedLong(
3521 resource_value);
cristy3ed852e2009-09-05 21:47:34 +00003522 resource_value=XGetResourceClass(database,client_name,"colormap",
3523 (char *) "shared");
3524 resource_info->colormap=UndefinedColormap;
3525 if (LocaleCompare("private",resource_value) == 0)
3526 resource_info->colormap=PrivateColormap;
3527 if (LocaleCompare("shared",resource_value) == 0)
3528 resource_info->colormap=SharedColormap;
3529 if (resource_info->colormap == UndefinedColormap)
3530 ThrowXWindowFatalException(OptionError,"UnrecognizedColormapType",
3531 resource_value);
3532 resource_value=XGetResourceClass(database,client_name,
3533 "colorRecovery",(char *) "False");
3534 resource_info->color_recovery=IsMagickTrue(resource_value);
3535 resource_value=XGetResourceClass(database,client_name,"confirmExit",
3536 (char *) "False");
3537 resource_info->confirm_exit=IsMagickTrue(resource_value);
3538 resource_value=XGetResourceClass(database,client_name,"confirmEdit",
3539 (char *) "False");
3540 resource_info->confirm_edit=IsMagickTrue(resource_value);
cristyba0c3252010-06-27 13:31:44 +00003541 resource_value=XGetResourceClass(database,client_name,"delay",(char *) "1");
cristye27293e2009-12-18 02:53:20 +00003542 resource_info->delay=(unsigned int) StringToUnsignedLong(resource_value);
cristy3ed852e2009-09-05 21:47:34 +00003543 resource_info->display_gamma=XGetResourceClass(database,client_name,
3544 "displayGamma",(char *) "2.2");
3545 resource_value=XGetResourceClass(database,client_name,"displayWarnings",
3546 (char *) "True");
3547 resource_info->display_warnings=IsMagickTrue(resource_value);
3548 resource_info->font=XGetResourceClass(database,client_name,"font",
3549 (char *) NULL);
3550 resource_info->font=XGetResourceClass(database,client_name,"fontList",
3551 resource_info->font);
3552 resource_info->font_name[0]=XGetResourceClass(database,client_name,"font1",
3553 (char *) "fixed");
3554 resource_info->font_name[1]=XGetResourceClass(database,client_name,"font2",
3555 (char *) "variable");
3556 resource_info->font_name[2]=XGetResourceClass(database,client_name,"font3",
3557 (char *) "5x8");
3558 resource_info->font_name[3]=XGetResourceClass(database,client_name,"font4",
3559 (char *) "6x10");
3560 resource_info->font_name[4]=XGetResourceClass(database,client_name,"font5",
3561 (char *) "7x13bold");
3562 resource_info->font_name[5]=XGetResourceClass(database,client_name,"font6",
3563 (char *) "8x13bold");
3564 resource_info->font_name[6]=XGetResourceClass(database,client_name,"font7",
3565 (char *) "9x15bold");
3566 resource_info->font_name[7]=XGetResourceClass(database,client_name,"font8",
3567 (char *) "10x20");
3568 resource_info->font_name[8]=XGetResourceClass(database,client_name,"font9",
3569 (char *) "12x24");
3570 resource_info->font_name[9]=XGetResourceClass(database,client_name,"font0",
3571 (char *) "fixed");
3572 resource_info->font_name[10]=XGetResourceClass(database,client_name,"font0",
3573 (char *) "fixed");
3574 resource_info->foreground_color=XGetResourceInstance(database,client_name,
3575 "foreground",ForegroundColor);
3576 resource_value=XGetResourceClass(database,client_name,"gammaCorrect",
3577 (char *) "True");
3578 resource_info->gamma_correct=IsMagickTrue(resource_value);
3579 resource_info->image_geometry=ConstantString(XGetResourceClass(database,
3580 client_name,"geometry",(char *) NULL));
3581 resource_value=XGetResourceClass(database,client_name,"gravity",
3582 (char *) "Center");
cristy042ee782011-04-22 18:48:30 +00003583 resource_info->gravity=(GravityType) ParseCommandOption(MagickGravityOptions,
cristy3ed852e2009-09-05 21:47:34 +00003584 MagickFalse,resource_value);
cristy00976d82011-02-20 20:31:28 +00003585 directory=getcwd(resource_info->home_directory,MaxTextExtent);
3586 (void) directory;
cristy3ed852e2009-09-05 21:47:34 +00003587 resource_info->icon_geometry=XGetResourceClass(database,client_name,
3588 "iconGeometry",(char *) NULL);
3589 resource_value=XGetResourceClass(database,client_name,"iconic",
3590 (char *) "False");
3591 resource_info->iconic=IsMagickTrue(resource_value);
3592 resource_value=XGetResourceClass(database,client_name,"immutable",
3593 LocaleCompare(client_name,"PerlMagick") == 0 ? (char *) "True" :
3594 (char *) "False");
3595 resource_info->immutable=IsMagickTrue(resource_value);
3596 resource_value=XGetResourceClass(database,client_name,"magnify",
3597 (char *) "3");
cristye27293e2009-12-18 02:53:20 +00003598 resource_info->magnify=(unsigned int) StringToUnsignedLong(resource_value);
cristy3ed852e2009-09-05 21:47:34 +00003599 resource_info->map_type=XGetResourceClass(database,client_name,"map",
3600 (char *) NULL);
3601 resource_info->matte_color=XGetResourceInstance(database,client_name,
3602 "mattecolor",(char *) NULL);
3603 resource_info->name=ConstantString(XGetResourceClass(database,client_name,
3604 "name",(char *) NULL));
3605 resource_info->pen_colors[0]=XGetResourceClass(database,client_name,"pen1",
3606 (char *) "black");
3607 resource_info->pen_colors[1]=XGetResourceClass(database,client_name,"pen2",
3608 (char *) "blue");
3609 resource_info->pen_colors[2]=XGetResourceClass(database,client_name,"pen3",
3610 (char *) "cyan");
3611 resource_info->pen_colors[3]=XGetResourceClass(database,client_name,"pen4",
3612 (char *) "green");
3613 resource_info->pen_colors[4]=XGetResourceClass(database,client_name,"pen5",
3614 (char *) "gray");
3615 resource_info->pen_colors[5]=XGetResourceClass(database,client_name,"pen6",
3616 (char *) "red");
3617 resource_info->pen_colors[6]=XGetResourceClass(database,client_name,"pen7",
3618 (char *) "magenta");
3619 resource_info->pen_colors[7]=XGetResourceClass(database,client_name,"pen8",
3620 (char *) "yellow");
3621 resource_info->pen_colors[8]=XGetResourceClass(database,client_name,"pen9",
3622 (char *) "white");
3623 resource_info->pen_colors[9]=XGetResourceClass(database,client_name,"pen0",
3624 (char *) "gray");
3625 resource_info->pen_colors[10]=XGetResourceClass(database,client_name,"pen0",
3626 (char *) "gray");
3627 resource_value=XGetResourceClass(database,client_name,"pause",(char *) "0");
cristye27293e2009-12-18 02:53:20 +00003628 resource_info->pause=(unsigned int) StringToUnsignedLong(resource_value);
cristy3ed852e2009-09-05 21:47:34 +00003629 resource_value=XGetResourceClass(database,client_name,"quantum",(char *) "1");
cristyf2f27272009-12-17 14:48:46 +00003630 resource_info->quantum=StringToLong(resource_value);
cristy3ed852e2009-09-05 21:47:34 +00003631 resource_info->text_font=XGetResourceClass(database,client_name,(char *)
3632 "font",(char *) "fixed");
3633 resource_info->text_font=XGetResourceClass(database,client_name,
3634 "textFontList",resource_info->text_font);
3635 resource_info->title=XGetResourceClass(database,client_name,"title",
3636 (char *) NULL);
3637 resource_value=XGetResourceClass(database,client_name,"undoCache",
3638 (char *) "16");
cristye27293e2009-12-18 02:53:20 +00003639 resource_info->undo_cache=(unsigned int) StringToUnsignedLong(resource_value);
cristy3ed852e2009-09-05 21:47:34 +00003640 resource_value=XGetResourceClass(database,client_name,"update",
3641 (char *) "False");
3642 resource_info->update=IsMagickTrue(resource_value);
3643 resource_value=XGetResourceClass(database,client_name,"usePixmap",
3644 (char *) "True");
3645 resource_info->use_pixmap=IsMagickTrue(resource_value);
3646 resource_value=XGetResourceClass(database,client_name,"sharedMemory",
3647 (char *) "True");
3648 resource_info->use_shared_memory=IsMagickTrue(resource_value);
3649 resource_info->visual_type=XGetResourceClass(database,client_name,"visual",
3650 (char *) NULL);
3651 resource_info->window_group=XGetResourceClass(database,client_name,
3652 "windowGroup",(char *) NULL);
3653 resource_info->window_id=XGetResourceClass(database,client_name,"window",
3654 (char *) NULL);
3655 resource_info->write_filename=XGetResourceClass(database,client_name,
3656 "writeFilename",(char *) NULL);
3657}
3658
3659/*
3660%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3661% %
3662% %
3663% %
3664% X G e t R e s o u r c e I n s t a n c e %
3665% %
3666% %
3667% %
3668%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3669%
3670% XGetResourceInstance() queries the X server for the specified resource name.
3671% If the resource name is not defined in the database, the supplied default
3672% value is returned.
3673%
3674% The format of the XGetResourceInstance method is:
3675%
3676% char *XGetResourceInstance(XrmDatabase database,const char *client_name,
3677% const char *keyword,const char *resource_default)
3678%
3679% A description of each parameter follows:
3680%
3681% o database: Specifies a resource database; returned from
3682% XrmGetStringDatabase.
3683%
3684% o client_name: Specifies the application name used to retrieve
3685% resource info from the X server database.
3686%
3687% o keyword: Specifies the keyword of the value being retrieved.
3688%
3689% o resource_default: Specifies the default value to return if the query
3690% fails to find the specified keyword/class.
3691%
3692*/
3693MagickExport char *XGetResourceInstance(XrmDatabase database,
3694 const char *client_name,const char *keyword,const char *resource_default)
3695{
3696 char
3697 *resource_type,
3698 resource_name[MaxTextExtent];
3699
3700 Status
3701 status;
3702
3703 XrmValue
3704 resource_value;
3705
3706 if (database == (XrmDatabase) NULL)
3707 return((char *) resource_default);
3708 *resource_name='\0';
3709 if (keyword != (char *) NULL)
cristyb51dff52011-05-19 16:55:47 +00003710 (void) FormatLocaleString(resource_name,MaxTextExtent,"%s.%s",client_name,
cristy3ed852e2009-09-05 21:47:34 +00003711 keyword);
3712 status=XrmGetResource(database,resource_name,"ImageMagick",&resource_type,
3713 &resource_value);
3714 if (status == False)
3715 return((char *) resource_default);
3716 return(resource_value.addr);
3717}
3718
3719/*
3720%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3721% %
3722% %
3723% %
3724% X G e t S c r e e n D e n s i t y %
3725% %
3726% %
3727% %
3728%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3729%
3730% XGetScreenDensity() returns the density of the X server screen in
3731% dots-per-inch.
3732%
3733% The format of the XGetScreenDensity method is:
3734%
3735% char *XGetScreenDensity(Display *display)
3736%
3737% A description of each parameter follows:
3738%
3739% o density: XGetScreenDensity() returns the density of the X screen in
3740% dots-per-inch.
3741%
3742% o display: Specifies a connection to an X server; returned from
3743% XOpenDisplay.
3744%
3745*/
3746MagickExport char *XGetScreenDensity(Display *display)
3747{
3748 char
3749 density[MaxTextExtent];
3750
3751 double
3752 x_density,
3753 y_density;
3754
3755 /*
3756 Set density as determined by screen size.
3757 */
3758 x_density=((((double) DisplayWidth(display,XDefaultScreen(display)))*25.4)/
3759 ((double) DisplayWidthMM(display,XDefaultScreen(display))));
3760 y_density=((((double) DisplayHeight(display,XDefaultScreen(display)))*25.4)/
3761 ((double) DisplayHeightMM(display,XDefaultScreen(display))));
cristyb51dff52011-05-19 16:55:47 +00003762 (void) FormatLocaleString(density,MaxTextExtent,"%gx%g",x_density,
cristy8cd5b312010-01-07 01:10:24 +00003763 y_density);
cristy3ed852e2009-09-05 21:47:34 +00003764 return(GetPageGeometry(density));
3765}
3766
3767/*
3768%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3769% %
3770% %
3771% %
3772+ X G e t S u b w i n d o w %
3773% %
3774% %
3775% %
3776%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3777%
3778% XGetSubwindow() returns the subwindow of a window chosen the user with the
3779% pointer and a button press.
3780%
3781% The format of the XGetSubwindow method is:
3782%
3783% Window XGetSubwindow(Display *display,Window window,int x,int y)
3784%
3785% A description of each parameter follows:
3786%
3787% o subwindow: XGetSubwindow() returns NULL if no subwindow is found
3788% otherwise the subwindow is returned.
3789%
3790% o display: Specifies a connection to an X server; returned from
3791% XOpenDisplay.
3792%
3793% o window: Specifies a pointer to a Window.
3794%
3795% o x: the x coordinate of the pointer relative to the origin of the
3796% window.
3797%
3798% o y: the y coordinate of the pointer relative to the origin of the
3799% window.
3800%
cristy3ed852e2009-09-05 21:47:34 +00003801*/
3802static Window XGetSubwindow(Display *display,Window window,int x,int y)
3803{
3804 int
3805 x_offset,
3806 y_offset;
3807
3808 Status
3809 status;
3810
3811 Window
3812 source_window,
3813 target_window;
3814
3815 assert(display != (Display *) NULL);
3816 source_window=XRootWindow(display,XDefaultScreen(display));
3817 if (window == (Window) NULL)
3818 return(source_window);
3819 target_window=window;
3820 for ( ; ; )
3821 {
3822 status=XTranslateCoordinates(display,source_window,window,x,y,
3823 &x_offset,&y_offset,&target_window);
3824 if (status != True)
3825 break;
3826 if (target_window == (Window) NULL)
3827 break;
3828 source_window=window;
3829 window=target_window;
3830 x=x_offset;
3831 y=y_offset;
3832 }
3833 if (target_window == (Window) NULL)
3834 target_window=window;
3835 return(target_window);
3836}
3837
3838/*
3839%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3840% %
3841% %
3842% %
3843% X G e t W i n d o w C o l o r %
3844% %
3845% %
3846% %
3847%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3848%
3849% XGetWindowColor() returns the color of a pixel interactively chosen from the
3850% X server.
3851%
3852% The format of the XGetWindowColor method is:
3853%
3854% MagickBooleanType XGetWindowColor(Display *display,XWindows *windows,
cristy6710d842011-10-20 23:23:00 +00003855% char *name,ExceptionInfo *exception)
cristy3ed852e2009-09-05 21:47:34 +00003856%
3857% A description of each parameter follows:
3858%
3859% o display: Specifies a connection to an X server; returned from
3860% XOpenDisplay.
3861%
3862% o windows: Specifies a pointer to a XWindows structure.
3863%
3864% o name: the name of the color if found in the X Color Database is
3865% returned in this character string.
3866%
cristy6710d842011-10-20 23:23:00 +00003867% o exception: return any errors or warnings in this structure.
3868%
cristy3ed852e2009-09-05 21:47:34 +00003869*/
cristybcbda3f2011-09-03 13:01:22 +00003870MagickPrivate MagickBooleanType XGetWindowColor(Display *display,
cristy6710d842011-10-20 23:23:00 +00003871 XWindows *windows,char *name,ExceptionInfo *exception)
cristy3ed852e2009-09-05 21:47:34 +00003872{
3873 int
3874 x,
3875 y;
3876
cristy101ab702011-10-13 13:06:32 +00003877 PixelInfo
cristy3ed852e2009-09-05 21:47:34 +00003878 pixel;
3879
3880 RectangleInfo
3881 crop_info;
3882
3883 Status
3884 status;
3885
3886 Window
3887 child,
3888 client_window,
3889 root_window,
3890 target_window;
3891
3892 XColor
3893 color;
3894
3895 XImage
3896 *ximage;
3897
3898 XWindowAttributes
3899 window_attributes;
3900
3901 /*
3902 Choose a pixel from the X server.
3903 */
3904 assert(display != (Display *) NULL);
3905 assert(name != (char *) NULL);
3906 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",name);
3907 *name='\0';
3908 target_window=XSelectWindow(display,&crop_info);
3909 if (target_window == (Window) NULL)
3910 return(MagickFalse);
3911 root_window=XRootWindow(display,XDefaultScreen(display));
3912 client_window=target_window;
3913 if (target_window != root_window)
3914 {
3915 unsigned int
3916 d;
3917
3918 /*
3919 Get client window.
3920 */
3921 status=XGetGeometry(display,target_window,&root_window,&x,&x,&d,&d,&d,&d);
3922 if (status != False)
3923 {
3924 client_window=XClientWindow(display,target_window);
3925 target_window=client_window;
3926 }
3927 }
3928 /*
3929 Verify window is viewable.
3930 */
3931 status=XGetWindowAttributes(display,target_window,&window_attributes);
3932 if ((status == False) || (window_attributes.map_state != IsViewable))
3933 return(MagickFalse);
3934 /*
3935 Get window X image.
3936 */
3937 (void) XTranslateCoordinates(display,root_window,target_window,
3938 (int) crop_info.x,(int) crop_info.y,&x,&y,&child);
3939 ximage=XGetImage(display,target_window,x,y,1,1,AllPlanes,ZPixmap);
3940 if (ximage == (XImage *) NULL)
3941 return(MagickFalse);
3942 color.pixel=XGetPixel(ximage,0,0);
3943 XDestroyImage(ximage);
3944 /*
3945 Match color against the color database.
3946 */
3947 (void) XQueryColor(display,window_attributes.colormap,&color);
cristye42f6582012-02-11 17:59:50 +00003948 pixel.red=(double) ScaleShortToQuantum(color.red);
3949 pixel.green=(double) ScaleShortToQuantum(color.green);
3950 pixel.blue=(double) ScaleShortToQuantum(color.blue);
cristy4c08aed2011-07-01 19:47:50 +00003951 pixel.alpha=OpaqueAlpha;
cristy3ed852e2009-09-05 21:47:34 +00003952 (void) QueryColorname(windows->image.image,&pixel,X11Compliance,name,
cristy6710d842011-10-20 23:23:00 +00003953 exception);
cristy3ed852e2009-09-05 21:47:34 +00003954 return(MagickTrue);
3955}
3956
3957/*
3958%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3959% %
3960% %
3961% %
3962+ X G e t W i n d o w I m a g e %
3963% %
3964% %
3965% %
3966%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3967%
3968% XGetWindowImage() reads an image from the target X window and returns it.
3969% XGetWindowImage() optionally descends the window hierarchy and overlays the
3970% target image with each child image in an optimized fashion. Any child
3971% window that have the same visual, colormap, and are contained by its parent
3972% are exempted.
3973%
3974% The format of the XGetWindowImage method is:
3975%
3976% Image *XGetWindowImage(Display *display,const Window window,
cristy6710d842011-10-20 23:23:00 +00003977% const unsigned int borders,const unsigned int level,
3978% ExceptionInfo *exception)
cristy3ed852e2009-09-05 21:47:34 +00003979%
3980% A description of each parameter follows:
3981%
3982% o display: Specifies a connection to an X server; returned from
3983% XOpenDisplay.
3984%
3985% o window: Specifies the window to obtain the image from.
3986%
3987% o borders: Specifies whether borders pixels are to be saved with
3988% the image.
3989%
3990% o level: Specifies an unsigned integer representing the level of
3991% decent in the window hierarchy. This value must be zero or one on
3992% the initial call to XGetWindowImage. A value of zero returns after
3993% one call. A value of one causes the function to descend the window
3994% hierarchy and overlay the target image with each subwindow image.
3995%
cristy6710d842011-10-20 23:23:00 +00003996% o exception: return any errors or warnings in this structure.
3997%
cristy3ed852e2009-09-05 21:47:34 +00003998*/
3999static Image *XGetWindowImage(Display *display,const Window window,
cristy6710d842011-10-20 23:23:00 +00004000 const unsigned int borders,const unsigned int level,ExceptionInfo *exception)
cristy3ed852e2009-09-05 21:47:34 +00004001{
4002 typedef struct _ColormapInfo
4003 {
4004 Colormap
4005 colormap;
4006
4007 XColor
4008 *colors;
4009
4010 struct _ColormapInfo
4011 *next;
4012 } ColormapInfo;
4013
4014 typedef struct _WindowInfo
4015 {
4016 Window
4017 window,
4018 parent;
4019
4020 Visual
4021 *visual;
4022
4023 Colormap
4024 colormap;
4025
4026 XSegment
4027 bounds;
4028
4029 RectangleInfo
4030 crop_info;
4031 } WindowInfo;
4032
cristy3ed852e2009-09-05 21:47:34 +00004033 int
4034 display_height,
4035 display_width,
4036 id,
4037 x_offset,
4038 y_offset;
4039
cristy4c08aed2011-07-01 19:47:50 +00004040 Quantum
4041 index;
4042
cristy3ed852e2009-09-05 21:47:34 +00004043 RectangleInfo
4044 crop_info;
4045
cristy3ed852e2009-09-05 21:47:34 +00004046 register int
4047 i;
4048
4049 static ColormapInfo
4050 *colormap_info = (ColormapInfo *) NULL;
4051
4052 static int
4053 max_windows = 0,
4054 number_windows = 0;
4055
4056 static WindowInfo
4057 *window_info;
4058
4059 Status
4060 status;
4061
4062 Window
4063 child,
4064 root_window;
4065
4066 XWindowAttributes
4067 window_attributes;
4068
4069 /*
4070 Verify window is viewable.
4071 */
4072 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
4073 assert(display != (Display *) NULL);
4074 status=XGetWindowAttributes(display,window,&window_attributes);
4075 if ((status == False) || (window_attributes.map_state != IsViewable))
4076 return((Image *) NULL);
4077 /*
4078 Cropping rectangle is relative to root window.
4079 */
4080 root_window=XRootWindow(display,XDefaultScreen(display));
4081 (void) XTranslateCoordinates(display,window,root_window,0,0,&x_offset,
4082 &y_offset,&child);
cristybb503372010-05-27 20:51:26 +00004083 crop_info.x=(ssize_t) x_offset;
4084 crop_info.y=(ssize_t) y_offset;
4085 crop_info.width=(size_t) window_attributes.width;
4086 crop_info.height=(size_t) window_attributes.height;
cristy3ed852e2009-09-05 21:47:34 +00004087 if (borders != MagickFalse)
4088 {
4089 /*
4090 Include border in image.
4091 */
cristybb503372010-05-27 20:51:26 +00004092 crop_info.x-=(ssize_t) window_attributes.border_width;
4093 crop_info.y-=(ssize_t) window_attributes.border_width;
4094 crop_info.width+=(size_t) (window_attributes.border_width << 1);
4095 crop_info.height+=(size_t) (window_attributes.border_width << 1);
cristy3ed852e2009-09-05 21:47:34 +00004096 }
4097 /*
4098 Crop to root window.
4099 */
4100 if (crop_info.x < 0)
4101 {
4102 crop_info.width+=crop_info.x;
4103 crop_info.x=0;
4104 }
4105 if (crop_info.y < 0)
4106 {
4107 crop_info.height+=crop_info.y;
4108 crop_info.y=0;
4109 }
4110 display_width=XDisplayWidth(display,XDefaultScreen(display));
4111 if ((int) (crop_info.x+crop_info.width) > display_width)
cristybb503372010-05-27 20:51:26 +00004112 crop_info.width=(size_t) (display_width-crop_info.x);
cristy3ed852e2009-09-05 21:47:34 +00004113 display_height=XDisplayHeight(display,XDefaultScreen(display));
4114 if ((int) (crop_info.y+crop_info.height) > display_height)
cristybb503372010-05-27 20:51:26 +00004115 crop_info.height=(size_t) (display_height-crop_info.y);
cristy3ed852e2009-09-05 21:47:34 +00004116 /*
4117 Initialize window info attributes.
4118 */
4119 if (number_windows >= max_windows)
4120 {
4121 /*
4122 Allocate or resize window info buffer.
4123 */
4124 max_windows+=1024;
4125 if (window_info == (WindowInfo *) NULL)
4126 window_info=(WindowInfo *) AcquireQuantumMemory((size_t) max_windows,
4127 sizeof(*window_info));
4128 else
4129 window_info=(WindowInfo *) ResizeQuantumMemory(window_info,(size_t)
4130 max_windows,sizeof(*window_info));
4131 }
4132 if (window_info == (WindowInfo *) NULL)
4133 {
4134 ThrowXWindowFatalException(ResourceLimitError,
4135 "MemoryAllocationFailed","...");
4136 return((Image *) NULL);
4137 }
4138 id=number_windows++;
4139 window_info[id].window=window;
4140 window_info[id].visual=window_attributes.visual;
4141 window_info[id].colormap=window_attributes.colormap;
4142 window_info[id].bounds.x1=(short) crop_info.x;
4143 window_info[id].bounds.y1=(short) crop_info.y;
4144 window_info[id].bounds.x2=(short) (crop_info.x+(int) crop_info.width-1);
4145 window_info[id].bounds.y2=(short) (crop_info.y+(int) crop_info.height-1);
4146 crop_info.x-=x_offset;
4147 crop_info.y-=y_offset;
4148 window_info[id].crop_info=crop_info;
4149 if (level != 0)
4150 {
4151 unsigned int
4152 number_children;
4153
4154 Window
4155 *children;
4156
4157 /*
4158 Descend the window hierarchy.
4159 */
4160 status=XQueryTree(display,window,&root_window,&window_info[id].parent,
4161 &children,&number_children);
4162 for (i=0; i < id; i++)
4163 if ((window_info[i].window == window_info[id].parent) &&
4164 (window_info[i].visual == window_info[id].visual) &&
4165 (window_info[i].colormap == window_info[id].colormap))
4166 {
4167 if ((window_info[id].bounds.x1 <= window_info[i].bounds.x1) ||
4168 (window_info[id].bounds.x1 >= window_info[i].bounds.x2) ||
4169 (window_info[id].bounds.y1 <= window_info[i].bounds.y1) ||
4170 (window_info[id].bounds.y1 >= window_info[i].bounds.y2))
4171 {
4172 /*
4173 Eliminate windows not circumscribed by their parent.
4174 */
4175 number_windows--;
4176 break;
4177 }
4178 }
4179 if ((status == True) && (number_children != 0))
4180 {
4181 for (i=0; i < (int) number_children; i++)
cristy6710d842011-10-20 23:23:00 +00004182 (void) XGetWindowImage(display,children[i],MagickFalse,level+1,
4183 exception);
cristy3ed852e2009-09-05 21:47:34 +00004184 (void) XFree((void *) children);
4185 }
4186 }
4187 if (level <= 1)
4188 {
cristyc57f6942010-11-12 01:47:39 +00004189 CacheView
4190 *composite_view;
4191
cristy3ed852e2009-09-05 21:47:34 +00004192 ColormapInfo
4193 *next;
4194
cristy3ed852e2009-09-05 21:47:34 +00004195 Image
4196 *composite_image,
4197 *image;
4198
4199 int
4200 y;
4201
4202 MagickBooleanType
4203 import;
4204
4205 register int
4206 j,
4207 x;
4208
cristy4c08aed2011-07-01 19:47:50 +00004209 register Quantum
cristyc47d1f82009-11-26 01:44:43 +00004210 *restrict q;
cristy3ed852e2009-09-05 21:47:34 +00004211
cristybb503372010-05-27 20:51:26 +00004212 register size_t
cristy3ed852e2009-09-05 21:47:34 +00004213 pixel;
4214
4215 unsigned int
4216 number_colors;
4217
4218 XColor
4219 *colors;
4220
4221 XImage
4222 *ximage;
4223
4224 /*
4225 Get X image for each window in the list.
4226 */
4227 image=NewImageList();
4228 for (id=0; id < number_windows; id++)
4229 {
4230 /*
4231 Does target window intersect top level window?
4232 */
4233 import=
4234 ((window_info[id].bounds.x2 >= window_info[0].bounds.x1) &&
4235 (window_info[id].bounds.x1 <= window_info[0].bounds.x2) &&
4236 (window_info[id].bounds.y2 >= window_info[0].bounds.y1) &&
4237 (window_info[id].bounds.y1 <= window_info[0].bounds.y2)) ?
4238 MagickTrue : MagickFalse;
4239 /*
4240 Is target window contained by another window with the same colormap?
4241 */
4242 for (j=0; j < id; j++)
4243 if ((window_info[id].visual == window_info[j].visual) &&
4244 (window_info[id].colormap == window_info[j].colormap))
4245 {
4246 if ((window_info[id].bounds.x1 <= window_info[j].bounds.x1) ||
4247 (window_info[id].bounds.x1 >= window_info[j].bounds.x2) ||
4248 (window_info[id].bounds.y1 <= window_info[j].bounds.y1) ||
4249 (window_info[id].bounds.y1 >= window_info[j].bounds.y2))
4250 import=MagickFalse;
4251 }
4252 else
4253 if ((window_info[id].visual != window_info[j].visual) ||
4254 (window_info[id].colormap != window_info[j].colormap))
4255 {
4256 if ((window_info[id].bounds.x2 > window_info[j].bounds.x1) &&
4257 (window_info[id].bounds.x1 < window_info[j].bounds.x2) &&
4258 (window_info[id].bounds.y2 > window_info[j].bounds.y1) &&
4259 (window_info[id].bounds.y1 < window_info[j].bounds.y2))
4260 import=MagickTrue;
4261 }
4262 if (import == MagickFalse)
4263 continue;
4264 /*
4265 Get X image.
4266 */
4267 ximage=XGetImage(display,window_info[id].window,(int)
4268 window_info[id].crop_info.x,(int) window_info[id].crop_info.y,
4269 (unsigned int) window_info[id].crop_info.width,(unsigned int)
4270 window_info[id].crop_info.height,AllPlanes,ZPixmap);
4271 if (ximage == (XImage *) NULL)
4272 continue;
4273 /*
4274 Initialize window colormap.
4275 */
4276 number_colors=0;
4277 colors=(XColor *) NULL;
4278 if (window_info[id].colormap != (Colormap) NULL)
4279 {
4280 ColormapInfo
4281 *p;
4282
4283 /*
4284 Search colormap list for window colormap.
4285 */
4286 number_colors=(unsigned int) window_info[id].visual->map_entries;
4287 for (p=colormap_info; p != (ColormapInfo *) NULL; p=p->next)
4288 if (p->colormap == window_info[id].colormap)
4289 break;
4290 if (p == (ColormapInfo *) NULL)
4291 {
4292 /*
4293 Get the window colormap.
4294 */
4295 colors=(XColor *) AcquireQuantumMemory(number_colors,
4296 sizeof(*colors));
4297 if (colors == (XColor *) NULL)
4298 {
4299 XDestroyImage(ximage);
4300 return((Image *) NULL);
4301 }
4302 if ((window_info[id].visual->klass != DirectColor) &&
4303 (window_info[id].visual->klass != TrueColor))
4304 for (i=0; i < (int) number_colors; i++)
4305 {
cristybb503372010-05-27 20:51:26 +00004306 colors[i].pixel=(size_t) i;
cristy3ed852e2009-09-05 21:47:34 +00004307 colors[i].pad='\0';
4308 }
4309 else
4310 {
cristybb503372010-05-27 20:51:26 +00004311 size_t
cristy3ed852e2009-09-05 21:47:34 +00004312 blue,
4313 blue_bit,
4314 green,
4315 green_bit,
4316 red,
4317 red_bit;
4318
4319 /*
4320 DirectColor or TrueColor visual.
4321 */
4322 red=0;
4323 green=0;
4324 blue=0;
4325 red_bit=window_info[id].visual->red_mask &
4326 (~(window_info[id].visual->red_mask)+1);
4327 green_bit=window_info[id].visual->green_mask &
4328 (~(window_info[id].visual->green_mask)+1);
4329 blue_bit=window_info[id].visual->blue_mask &
4330 (~(window_info[id].visual->blue_mask)+1);
4331 for (i=0; i < (int) number_colors; i++)
4332 {
cristy8891f9c2010-06-04 23:32:17 +00004333 colors[i].pixel=(unsigned long) (red | green | blue);
cristy3ed852e2009-09-05 21:47:34 +00004334 colors[i].pad='\0';
4335 red+=red_bit;
4336 if (red > window_info[id].visual->red_mask)
4337 red=0;
4338 green+=green_bit;
4339 if (green > window_info[id].visual->green_mask)
4340 green=0;
4341 blue+=blue_bit;
4342 if (blue > window_info[id].visual->blue_mask)
4343 blue=0;
4344 }
4345 }
4346 (void) XQueryColors(display,window_info[id].colormap,colors,
4347 (int) number_colors);
4348 /*
4349 Append colormap to colormap list.
4350 */
cristy73bd4a52010-10-05 11:24:23 +00004351 p=(ColormapInfo *) AcquireMagickMemory(sizeof(*p));
cristy3ed852e2009-09-05 21:47:34 +00004352 if (p == (ColormapInfo *) NULL)
4353 return((Image *) NULL);
4354 p->colormap=window_info[id].colormap;
4355 p->colors=colors;
4356 p->next=colormap_info;
4357 colormap_info=p;
4358 }
4359 colors=p->colors;
4360 }
4361 /*
4362 Allocate image structure.
4363 */
cristy6710d842011-10-20 23:23:00 +00004364 composite_image=AcquireImage((ImageInfo *) NULL,exception);
cristy3ed852e2009-09-05 21:47:34 +00004365 if (composite_image == (Image *) NULL)
4366 {
4367 XDestroyImage(ximage);
4368 return((Image *) NULL);
4369 }
4370 /*
4371 Convert X image to MIFF format.
4372 */
4373 if ((window_info[id].visual->klass != TrueColor) &&
4374 (window_info[id].visual->klass != DirectColor))
4375 composite_image->storage_class=PseudoClass;
cristybb503372010-05-27 20:51:26 +00004376 composite_image->columns=(size_t) ximage->width;
4377 composite_image->rows=(size_t) ximage->height;
cristyc57f6942010-11-12 01:47:39 +00004378 composite_view=AcquireCacheView(composite_image);
cristy3ed852e2009-09-05 21:47:34 +00004379 switch (composite_image->storage_class)
4380 {
4381 case DirectClass:
4382 default:
4383 {
cristybb503372010-05-27 20:51:26 +00004384 register size_t
cristy3ed852e2009-09-05 21:47:34 +00004385 color,
4386 index;
4387
cristybb503372010-05-27 20:51:26 +00004388 size_t
cristy3ed852e2009-09-05 21:47:34 +00004389 blue_mask,
4390 blue_shift,
4391 green_mask,
4392 green_shift,
4393 red_mask,
4394 red_shift;
4395
4396 /*
4397 Determine shift and mask for red, green, and blue.
4398 */
4399 red_mask=window_info[id].visual->red_mask;
4400 red_shift=0;
4401 while ((red_mask != 0) && ((red_mask & 0x01) == 0))
4402 {
4403 red_mask>>=1;
4404 red_shift++;
4405 }
4406 green_mask=window_info[id].visual->green_mask;
4407 green_shift=0;
4408 while ((green_mask != 0) && ((green_mask & 0x01) == 0))
4409 {
4410 green_mask>>=1;
4411 green_shift++;
4412 }
4413 blue_mask=window_info[id].visual->blue_mask;
4414 blue_shift=0;
4415 while ((blue_mask != 0) && ((blue_mask & 0x01) == 0))
4416 {
4417 blue_mask>>=1;
4418 blue_shift++;
4419 }
4420 /*
4421 Convert X image to DirectClass packets.
4422 */
4423 if ((number_colors != 0) &&
4424 (window_info[id].visual->klass == DirectColor))
4425 for (y=0; y < (int) composite_image->rows; y++)
4426 {
cristyc57f6942010-11-12 01:47:39 +00004427 q=QueueCacheViewAuthenticPixels(composite_view,0,(ssize_t) y,
cristy3ed852e2009-09-05 21:47:34 +00004428 composite_image->columns,1,exception);
cristyacd2ed22011-08-30 01:44:23 +00004429 if (q == (Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00004430 break;
4431 for (x=0; x < (int) composite_image->columns; x++)
4432 {
4433 pixel=XGetPixel(ximage,x,y);
4434 index=(pixel >> red_shift) & red_mask;
cristy4c08aed2011-07-01 19:47:50 +00004435 SetPixelRed(composite_image,
4436 ScaleShortToQuantum(colors[index].red),q);
cristy3ed852e2009-09-05 21:47:34 +00004437 index=(pixel >> green_shift) & green_mask;
cristy4c08aed2011-07-01 19:47:50 +00004438 SetPixelGreen(composite_image,
4439 ScaleShortToQuantum(colors[index].green),q);
cristy3ed852e2009-09-05 21:47:34 +00004440 index=(pixel >> blue_shift) & blue_mask;
cristy4c08aed2011-07-01 19:47:50 +00004441 SetPixelBlue(composite_image,
4442 ScaleShortToQuantum(colors[index].blue),q);
cristyed231572011-07-14 02:18:59 +00004443 q+=GetPixelChannels(composite_image);
cristy3ed852e2009-09-05 21:47:34 +00004444 }
cristy0b1a7972011-10-22 22:17:02 +00004445 status=SyncCacheViewAuthenticPixels(composite_view,exception);
4446 if (status == MagickFalse)
cristy3ed852e2009-09-05 21:47:34 +00004447 break;
4448 }
4449 else
4450 for (y=0; y < (int) composite_image->rows; y++)
4451 {
cristyc57f6942010-11-12 01:47:39 +00004452 q=QueueCacheViewAuthenticPixels(composite_view,0,(ssize_t) y,
cristy3ed852e2009-09-05 21:47:34 +00004453 composite_image->columns,1,exception);
cristyacd2ed22011-08-30 01:44:23 +00004454 if (q == (Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00004455 break;
4456 for (x=0; x < (int) composite_image->columns; x++)
4457 {
4458 pixel=XGetPixel(ximage,x,y);
4459 color=(pixel >> red_shift) & red_mask;
4460 color=(65535UL*color)/red_mask;
cristy4c08aed2011-07-01 19:47:50 +00004461 SetPixelRed(composite_image,
4462 ScaleShortToQuantum((unsigned short) color),q);
cristy3ed852e2009-09-05 21:47:34 +00004463 color=(pixel >> green_shift) & green_mask;
4464 color=(65535UL*color)/green_mask;
cristy4c08aed2011-07-01 19:47:50 +00004465 SetPixelGreen(composite_image,
4466 ScaleShortToQuantum((unsigned short) color),q);
cristy3ed852e2009-09-05 21:47:34 +00004467 color=(pixel >> blue_shift) & blue_mask;
4468 color=(65535UL*color)/blue_mask;
cristy4c08aed2011-07-01 19:47:50 +00004469 SetPixelBlue(composite_image,
4470 ScaleShortToQuantum((unsigned short) color),q);
cristyed231572011-07-14 02:18:59 +00004471 q+=GetPixelChannels(composite_image);
cristy3ed852e2009-09-05 21:47:34 +00004472 }
cristy0b1a7972011-10-22 22:17:02 +00004473 status=SyncCacheViewAuthenticPixels(composite_view,exception);
4474 if (status == MagickFalse)
cristy3ed852e2009-09-05 21:47:34 +00004475 break;
4476 }
4477 break;
4478 }
4479 case PseudoClass:
4480 {
4481 /*
4482 Create colormap.
4483 */
cristy0b1a7972011-10-22 22:17:02 +00004484 status=AcquireImageColormap(composite_image,number_colors,
4485 exception);
4486 if (status == MagickFalse)
cristy3ed852e2009-09-05 21:47:34 +00004487 {
4488 XDestroyImage(ximage);
4489 composite_image=DestroyImage(composite_image);
4490 return((Image *) NULL);
4491 }
4492 for (i=0; i < (int) composite_image->colors; i++)
4493 {
cristye42f6582012-02-11 17:59:50 +00004494 composite_image->colormap[colors[i].pixel].red=(double)
cristy3ed852e2009-09-05 21:47:34 +00004495 ScaleShortToQuantum(colors[i].red);
cristye42f6582012-02-11 17:59:50 +00004496 composite_image->colormap[colors[i].pixel].green=(double)
cristy3ed852e2009-09-05 21:47:34 +00004497 ScaleShortToQuantum(colors[i].green);
cristye42f6582012-02-11 17:59:50 +00004498 composite_image->colormap[colors[i].pixel].blue=(double)
cristy3ed852e2009-09-05 21:47:34 +00004499 ScaleShortToQuantum(colors[i].blue);
4500 }
4501 /*
4502 Convert X image to PseudoClass packets.
4503 */
4504 for (y=0; y < (int) composite_image->rows; y++)
4505 {
cristyc57f6942010-11-12 01:47:39 +00004506 q=QueueCacheViewAuthenticPixels(composite_view,0,(ssize_t) y,
4507 composite_image->columns,1,exception);
cristyacd2ed22011-08-30 01:44:23 +00004508 if (q == (Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00004509 break;
cristy3ed852e2009-09-05 21:47:34 +00004510 for (x=0; x < (int) composite_image->columns; x++)
4511 {
cristy4c08aed2011-07-01 19:47:50 +00004512 index=(Quantum) XGetPixel(ximage,x,y);
4513 SetPixelIndex(composite_image,index,q);
cristy803640d2011-11-17 02:11:32 +00004514 SetPixelInfoPixel(composite_image,
cristy4c08aed2011-07-01 19:47:50 +00004515 composite_image->colormap+(ssize_t) index,q);
cristyed231572011-07-14 02:18:59 +00004516 q+=GetPixelChannels(composite_image);
cristy3ed852e2009-09-05 21:47:34 +00004517 }
cristy0b1a7972011-10-22 22:17:02 +00004518 status=SyncCacheViewAuthenticPixels(composite_view,exception);
4519 if (status == MagickFalse)
cristy3ed852e2009-09-05 21:47:34 +00004520 break;
4521 }
4522 break;
4523 }
4524 }
cristyc57f6942010-11-12 01:47:39 +00004525 composite_view=DestroyCacheView(composite_view);
cristy3ed852e2009-09-05 21:47:34 +00004526 XDestroyImage(ximage);
4527 if (image == (Image *) NULL)
4528 {
4529 image=composite_image;
4530 continue;
4531 }
4532 /*
4533 Composite any children in back-to-front order.
4534 */
4535 (void) XTranslateCoordinates(display,window_info[id].window,window,0,0,
4536 &x_offset,&y_offset,&child);
4537 x_offset-=(int) crop_info.x;
4538 if (x_offset < 0)
4539 x_offset=0;
4540 y_offset-=(int) crop_info.y;
4541 if (y_offset < 0)
4542 y_offset=0;
cristyc57f6942010-11-12 01:47:39 +00004543 (void) CompositeImage(image,CopyCompositeOp,composite_image,(ssize_t)
cristye941a752011-10-15 01:52:48 +00004544 x_offset,(ssize_t) y_offset,exception);
cristy3ed852e2009-09-05 21:47:34 +00004545 }
4546 /*
4547 Relinquish resources.
4548 */
4549 while (colormap_info != (ColormapInfo *) NULL)
4550 {
4551 next=colormap_info->next;
cristye941a752011-10-15 01:52:48 +00004552 colormap_info->colors=(XColor *) RelinquishMagickMemory(
4553 colormap_info->colors);
cristy3ed852e2009-09-05 21:47:34 +00004554 colormap_info=(ColormapInfo *) RelinquishMagickMemory(colormap_info);
4555 colormap_info=next;
4556 }
4557 /*
4558 Relinquish resources and restore initial state.
4559 */
4560 window_info=(WindowInfo *) RelinquishMagickMemory(window_info);
4561 max_windows=0;
4562 number_windows=0;
4563 colormap_info=(ColormapInfo *) NULL;
4564 return(image);
4565 }
4566 return((Image *) NULL);
4567}
4568
4569/*
4570%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4571% %
4572% %
4573% %
4574% X G e t W i n d o w I n f o %
4575% %
4576% %
4577% %
4578%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4579%
4580% XGetWindowInfo() initializes the XWindowInfo structure.
4581%
4582% The format of the XGetWindowInfo method is:
4583%
4584% void XGetWindowInfo(Display *display,XVisualInfo *visual_info,
4585% XStandardColormap *map_info,XPixelInfo *pixel,XFontStruct *font_info,
4586% XResourceInfo *resource_info,XWindowInfo *window)
4587% resource_info,window)
4588%
4589% A description of each parameter follows:
4590%
4591% o display: Specifies a connection to an X server; returned from
4592% XOpenDisplay.
4593%
4594% o visual_info: Specifies a pointer to a X11 XVisualInfo structure;
4595% returned from XGetVisualInfo.
4596%
4597% o map_info: If map_type is specified, this structure is initialized
4598% with info from the Standard Colormap.
4599%
4600% o pixel: Specifies a pointer to a XPixelInfo structure.
4601%
4602% o font_info: Specifies a pointer to a XFontStruct structure.
4603%
4604% o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
4605%
4606*/
cristybcbda3f2011-09-03 13:01:22 +00004607MagickPrivate void XGetWindowInfo(Display *display,XVisualInfo *visual_info,
cristy3ed852e2009-09-05 21:47:34 +00004608 XStandardColormap *map_info,XPixelInfo *pixel,XFontStruct *font_info,
4609 XResourceInfo *resource_info,XWindowInfo *window)
4610{
4611 /*
4612 Initialize window info.
4613 */
4614 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
4615 assert(display != (Display *) NULL);
4616 assert(visual_info != (XVisualInfo *) NULL);
4617 assert(map_info != (XStandardColormap *) NULL);
4618 assert(pixel != (XPixelInfo *) NULL);
4619 assert(resource_info != (XResourceInfo *) NULL);
4620 assert(window != (XWindowInfo *) NULL);
4621 if (window->id != (Window) NULL)
4622 {
4623 if (window->cursor != (Cursor) NULL)
4624 (void) XFreeCursor(display,window->cursor);
4625 if (window->busy_cursor != (Cursor) NULL)
4626 (void) XFreeCursor(display,window->busy_cursor);
4627 if (window->highlight_stipple != (Pixmap) NULL)
4628 (void) XFreePixmap(display,window->highlight_stipple);
4629 if (window->shadow_stipple != (Pixmap) NULL)
4630 (void) XFreePixmap(display,window->shadow_stipple);
4631 if (window->name == (char *) NULL)
4632 window->name=AcquireString("");
4633 if (window->icon_name == (char *) NULL)
4634 window->icon_name=AcquireString("");
4635 }
4636 else
4637 {
4638 /*
4639 Initialize these attributes just once.
4640 */
4641 window->id=(Window) NULL;
4642 if (window->name == (char *) NULL)
4643 window->name=AcquireString("");
4644 if (window->icon_name == (char *) NULL)
4645 window->icon_name=AcquireString("");
4646 window->x=XDisplayWidth(display,visual_info->screen) >> 1;
4647 window->y=XDisplayWidth(display,visual_info->screen) >> 1;
4648 window->ximage=(XImage *) NULL;
4649 window->matte_image=(XImage *) NULL;
4650 window->pixmap=(Pixmap) NULL;
4651 window->matte_pixmap=(Pixmap) NULL;
4652 window->mapped=MagickFalse;
4653 window->stasis=MagickFalse;
4654 window->shared_memory=MagickTrue;
4655 window->segment_info=(void *) NULL;
4656#if defined(MAGICKCORE_HAVE_SHARED_MEMORY)
4657 {
4658 XShmSegmentInfo
4659 *segment_info;
4660
4661 if (window->segment_info == (void *) NULL)
4662 window->segment_info=AcquireQuantumMemory(2,sizeof(*segment_info));
4663 segment_info=(XShmSegmentInfo *) window->segment_info;
4664 segment_info[0].shmid=(-1);
4665 segment_info[0].shmaddr=(char *) NULL;
4666 segment_info[1].shmid=(-1);
4667 segment_info[1].shmaddr=(char *) NULL;
4668 }
4669#endif
4670 }
4671 /*
4672 Initialize these attributes every time function is called.
4673 */
4674 window->screen=visual_info->screen;
4675 window->root=XRootWindow(display,visual_info->screen);
4676 window->visual=visual_info->visual;
4677 window->storage_class=(unsigned int) visual_info->klass;
4678 window->depth=(unsigned int) visual_info->depth;
4679 window->visual_info=visual_info;
4680 window->map_info=map_info;
4681 window->pixel_info=pixel;
4682 window->font_info=font_info;
4683 window->cursor=XCreateFontCursor(display,XC_left_ptr);
4684 window->busy_cursor=XCreateFontCursor(display,XC_watch);
4685 window->geometry=(char *) NULL;
4686 window->icon_geometry=(char *) NULL;
4687 if (resource_info->icon_geometry != (char *) NULL)
4688 (void) CloneString(&window->icon_geometry,resource_info->icon_geometry);
4689 window->crop_geometry=(char *) NULL;
cristybb503372010-05-27 20:51:26 +00004690 window->flags=(size_t) PSize;
cristy3ed852e2009-09-05 21:47:34 +00004691 window->width=1;
4692 window->height=1;
4693 window->min_width=1;
4694 window->min_height=1;
4695 window->width_inc=1;
4696 window->height_inc=1;
4697 window->border_width=resource_info->border_width;
4698 window->annotate_context=pixel->annotate_context;
4699 window->highlight_context=pixel->highlight_context;
4700 window->widget_context=pixel->widget_context;
4701 window->shadow_stipple=(Pixmap) NULL;
4702 window->highlight_stipple=(Pixmap) NULL;
4703 window->use_pixmap=MagickTrue;
4704 window->immutable=MagickFalse;
4705 window->shape=MagickFalse;
4706 window->data=0;
cristyc57f6942010-11-12 01:47:39 +00004707 window->mask=(int) (CWBackingStore | CWBackPixel | CWBackPixmap |
cristy3ed852e2009-09-05 21:47:34 +00004708 CWBitGravity | CWBorderPixel | CWColormap | CWCursor | CWDontPropagate |
4709 CWEventMask | CWOverrideRedirect | CWSaveUnder | CWWinGravity);
4710 window->attributes.background_pixel=pixel->background_color.pixel;
4711 window->attributes.background_pixmap=(Pixmap) NULL;
4712 window->attributes.bit_gravity=ForgetGravity;
4713 window->attributes.backing_store=WhenMapped;
4714 window->attributes.save_under=MagickTrue;
4715 window->attributes.border_pixel=pixel->border_color.pixel;
4716 window->attributes.colormap=map_info->colormap;
4717 window->attributes.cursor=window->cursor;
4718 window->attributes.do_not_propagate_mask=NoEventMask;
4719 window->attributes.event_mask=NoEventMask;
4720 window->attributes.override_redirect=MagickFalse;
4721 window->attributes.win_gravity=NorthWestGravity;
4722 window->orphan=MagickFalse;
4723}
4724
4725/*
4726%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4727% %
4728% %
4729% %
4730% X H i g h l i g h t E l l i p s e %
4731% %
4732% %
4733% %
4734%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4735%
4736% XHighlightEllipse() puts a border on the X server around a region defined by
4737% highlight_info.
4738%
4739% The format of the XHighlightEllipse method is:
4740%
4741% void XHighlightEllipse(Display *display,Window window,
4742% GC annotate_context,const RectangleInfo *highlight_info)
4743%
4744% A description of each parameter follows:
4745%
4746% o display: Specifies a connection to an X server; returned from
4747% XOpenDisplay.
4748%
4749% o window: Specifies a pointer to a Window structure.
4750%
4751% o annotate_context: Specifies a pointer to a GC structure.
4752%
4753% o highlight_info: Specifies a pointer to a RectangleInfo structure. It
4754% contains the extents of any highlighting rectangle.
4755%
4756*/
cristybcbda3f2011-09-03 13:01:22 +00004757MagickPrivate void XHighlightEllipse(Display *display,Window window,
cristy3ed852e2009-09-05 21:47:34 +00004758 GC annotate_context,const RectangleInfo *highlight_info)
4759{
4760 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
4761 assert(display != (Display *) NULL);
4762 assert(window != (Window) NULL);
4763 assert(annotate_context != (GC) NULL);
4764 assert(highlight_info != (RectangleInfo *) NULL);
4765 if ((highlight_info->width < 4) || (highlight_info->height < 4))
4766 return;
4767 (void) XDrawArc(display,window,annotate_context,(int) highlight_info->x,
4768 (int) highlight_info->y,(unsigned int) highlight_info->width-1,
4769 (unsigned int) highlight_info->height-1,0,360*64);
4770 (void) XDrawArc(display,window,annotate_context,(int) highlight_info->x+1,
4771 (int) highlight_info->y+1,(unsigned int) highlight_info->width-3,
4772 (unsigned int) highlight_info->height-3,0,360*64);
4773}
4774
4775/*
4776%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4777% %
4778% %
4779% %
4780% X H i g h l i g h t L i n e %
4781% %
4782% %
4783% %
4784%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4785%
4786% XHighlightLine() puts a border on the X server around a region defined by
4787% highlight_info.
4788%
4789% The format of the XHighlightLine method is:
4790%
4791% void XHighlightLine(Display *display,Window window,GC annotate_context,
4792% const XSegment *highlight_info)
4793%
4794% A description of each parameter follows:
4795%
4796% o display: Specifies a connection to an X server; returned from
4797% XOpenDisplay.
4798%
4799% o window: Specifies a pointer to a Window structure.
4800%
4801% o annotate_context: Specifies a pointer to a GC structure.
4802%
4803% o highlight_info: Specifies a pointer to a RectangleInfo structure. It
4804% contains the extents of any highlighting rectangle.
4805%
4806*/
cristybcbda3f2011-09-03 13:01:22 +00004807MagickPrivate void XHighlightLine(Display *display,Window window,
cristy3ed852e2009-09-05 21:47:34 +00004808 GC annotate_context,const XSegment *highlight_info)
4809{
4810 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
4811 assert(display != (Display *) NULL);
4812 assert(window != (Window) NULL);
4813 assert(annotate_context != (GC) NULL);
4814 assert(highlight_info != (XSegment *) NULL);
4815 (void) XDrawLine(display,window,annotate_context,highlight_info->x1,
4816 highlight_info->y1,highlight_info->x2,highlight_info->y2);
4817}
4818
4819/*
4820%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4821% %
4822% %
4823% %
4824% X H i g h l i g h t R e c t a n g l e %
4825% %
4826% %
4827% %
4828%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4829%
4830% XHighlightRectangle() puts a border on the X server around a region defined
4831% by highlight_info.
4832%
4833% The format of the XHighlightRectangle method is:
4834%
4835% void XHighlightRectangle(Display *display,Window window,
4836% GC annotate_context,const RectangleInfo *highlight_info)
4837%
4838% A description of each parameter follows:
4839%
4840% o display: Specifies a connection to an X server; returned from
4841% XOpenDisplay.
4842%
4843% o window: Specifies a pointer to a Window structure.
4844%
4845% o annotate_context: Specifies a pointer to a GC structure.
4846%
4847% o highlight_info: Specifies a pointer to a RectangleInfo structure. It
4848% contains the extents of any highlighting rectangle.
4849%
4850*/
cristybcbda3f2011-09-03 13:01:22 +00004851MagickPrivate void XHighlightRectangle(Display *display,Window window,
cristy3ed852e2009-09-05 21:47:34 +00004852 GC annotate_context,const RectangleInfo *highlight_info)
4853{
4854 assert(display != (Display *) NULL);
4855 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
4856 assert(window != (Window) NULL);
4857 assert(annotate_context != (GC) NULL);
4858 assert(highlight_info != (RectangleInfo *) NULL);
4859 if ((highlight_info->width < 4) || (highlight_info->height < 4))
4860 return;
4861 (void) XDrawRectangle(display,window,annotate_context,(int) highlight_info->x,
4862 (int) highlight_info->y,(unsigned int) highlight_info->width-1,
4863 (unsigned int) highlight_info->height-1);
4864 (void) XDrawRectangle(display,window,annotate_context,(int) highlight_info->x+
4865 1,(int) highlight_info->y+1,(unsigned int) highlight_info->width-3,
4866 (unsigned int) highlight_info->height-3);
4867}
4868
4869/*
4870%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4871% %
4872% %
4873% %
4874% X I m p o r t I m a g e %
4875% %
4876% %
4877% %
4878%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4879%
4880% XImportImage() reads an image from an X window.
4881%
4882% The format of the XImportImage method is:
4883%
cristy6710d842011-10-20 23:23:00 +00004884% Image *XImportImage(const ImageInfo *image_info,XImportInfo *ximage_info,
4885% ExceptionInfo *exception)
cristy3ed852e2009-09-05 21:47:34 +00004886%
4887% A description of each parameter follows:
4888%
4889% o image_info: the image info.
4890%
4891% o ximage_info: Specifies a pointer to an XImportInfo structure.
4892%
cristy6710d842011-10-20 23:23:00 +00004893% o exception: return any errors or warnings in this structure.
4894%
cristy3ed852e2009-09-05 21:47:34 +00004895*/
4896MagickExport Image *XImportImage(const ImageInfo *image_info,
cristy6710d842011-10-20 23:23:00 +00004897 XImportInfo *ximage_info,ExceptionInfo *exception)
cristy3ed852e2009-09-05 21:47:34 +00004898{
4899 Colormap
4900 *colormaps;
4901
4902 Display
4903 *display;
4904
4905 Image
4906 *image;
4907
4908 int
4909 number_colormaps,
4910 number_windows,
4911 x;
4912
4913 RectangleInfo
4914 crop_info;
4915
4916 Status
4917 status;
4918
4919 Window
4920 *children,
4921 client,
4922 prior_target,
4923 root,
4924 target;
4925
4926 XTextProperty
4927 window_name;
4928
4929 /*
4930 Open X server connection.
4931 */
4932 assert(image_info != (const ImageInfo *) NULL);
4933 assert(image_info->signature == MagickSignature);
4934 if (image_info->debug != MagickFalse)
4935 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
4936 image_info->filename);
4937 assert(ximage_info != (XImportInfo *) NULL);
4938 display=XOpenDisplay(image_info->server_name);
4939 if (display == (Display *) NULL)
4940 {
4941 ThrowXWindowFatalException(XServerError,"UnableToOpenXServer",
4942 XDisplayName(image_info->server_name));
4943 return((Image *) NULL);
4944 }
4945 /*
4946 Set our forgiving exception handler.
4947 */
4948 (void) XSetErrorHandler(XError);
4949 /*
4950 Select target window.
4951 */
4952 crop_info.x=0;
4953 crop_info.y=0;
4954 crop_info.width=0;
4955 crop_info.height=0;
4956 root=XRootWindow(display,XDefaultScreen(display));
4957 target=(Window) NULL;
4958 if ((image_info->filename != (char *) NULL) &&
4959 (*image_info->filename != '\0'))
4960 {
4961 if (LocaleCompare(image_info->filename,"root") == 0)
4962 target=root;
4963 else
4964 {
4965 /*
4966 Select window by ID or name.
4967 */
4968 if (isdigit((unsigned char) *image_info->filename) != 0)
4969 target=XWindowByID(display,root,(Window)
4970 strtol(image_info->filename,(char **) NULL,0));
4971 if (target == (Window) NULL)
4972 target=XWindowByName(display,root,image_info->filename);
4973 if (target == (Window) NULL)
4974 ThrowXWindowFatalException(XServerError,
4975 "NoWindowWithSpecifiedIDExists",image_info->filename);
4976 }
4977 }
4978 /*
4979 If target window is not defined, interactively select one.
4980 */
4981 prior_target=target;
4982 if (target == (Window) NULL)
4983 target=XSelectWindow(display,&crop_info);
4984 if (target == (Window) NULL)
4985 ThrowXWindowFatalException(XServerError,"UnableToReadXWindowImage",
4986 image_info->filename);
4987 client=target; /* obsolete */
4988 if (target != root)
4989 {
4990 unsigned int
4991 d;
4992
4993 status=XGetGeometry(display,target,&root,&x,&x,&d,&d,&d,&d);
4994 if (status != False)
4995 {
4996 for ( ; ; )
4997 {
4998 Window
4999 parent;
5000
5001 /*
5002 Find window manager frame.
5003 */
5004 status=XQueryTree(display,target,&root,&parent,&children,&d);
5005 if ((status != False) && (children != (Window *) NULL))
5006 (void) XFree((char *) children);
5007 if ((status == False) || (parent == (Window) NULL) ||
5008 (parent == root))
5009 break;
5010 target=parent;
5011 }
5012 /*
5013 Get client window.
5014 */
5015 client=XClientWindow(display,target);
5016 if (ximage_info->frame == MagickFalse)
5017 target=client;
5018 if ((ximage_info->frame == MagickFalse) &&
5019 (prior_target != MagickFalse))
5020 target=prior_target;
cristy3ed852e2009-09-05 21:47:34 +00005021 }
5022 }
5023 if (ximage_info->screen)
5024 {
5025 int
5026 y;
5027
5028 Window
5029 child;
5030
5031 XWindowAttributes
5032 window_attributes;
5033
5034 /*
5035 Obtain window image directly from screen.
5036 */
5037 status=XGetWindowAttributes(display,target,&window_attributes);
5038 if (status == False)
5039 {
5040 ThrowXWindowFatalException(XServerError,
5041 "UnableToReadXWindowAttributes",image_info->filename);
5042 (void) XCloseDisplay(display);
5043 return((Image *) NULL);
5044 }
5045 (void) XTranslateCoordinates(display,target,root,0,0,&x,&y,&child);
cristyc57f6942010-11-12 01:47:39 +00005046 crop_info.x=(ssize_t) x;
5047 crop_info.y=(ssize_t) y;
cristybb503372010-05-27 20:51:26 +00005048 crop_info.width=(size_t) window_attributes.width;
5049 crop_info.height=(size_t) window_attributes.height;
cristy553743c2010-03-03 15:04:17 +00005050 if (ximage_info->borders != 0)
cristy3ed852e2009-09-05 21:47:34 +00005051 {
5052 /*
5053 Include border in image.
5054 */
5055 crop_info.x-=window_attributes.border_width;
5056 crop_info.y-=window_attributes.border_width;
5057 crop_info.width+=window_attributes.border_width << 1;
5058 crop_info.height+=window_attributes.border_width << 1;
5059 }
5060 target=root;
5061 }
5062 /*
5063 If WM_COLORMAP_WINDOWS property is set or multiple colormaps, descend.
5064 */
5065 number_windows=0;
5066 status=XGetWMColormapWindows(display,target,&children,&number_windows);
5067 if ((status == True) && (number_windows > 0))
5068 {
5069 ximage_info->descend=MagickTrue;
5070 (void) XFree ((char *) children);
5071 }
5072 colormaps=XListInstalledColormaps(display,target,&number_colormaps);
5073 if (number_colormaps > 0)
5074 {
5075 if (number_colormaps > 1)
5076 ximage_info->descend=MagickTrue;
5077 (void) XFree((char *) colormaps);
5078 }
5079 /*
5080 Alert the user not to alter the screen.
5081 */
5082 if (ximage_info->silent == MagickFalse)
5083 (void) XBell(display,0);
5084 /*
5085 Get image by window id.
5086 */
5087 (void) XGrabServer(display);
5088 image=XGetWindowImage(display,target,ximage_info->borders,
cristy6710d842011-10-20 23:23:00 +00005089 ximage_info->descend ? 1U : 0U,exception);
cristy3ed852e2009-09-05 21:47:34 +00005090 (void) XUngrabServer(display);
5091 if (image == (Image *) NULL)
5092 ThrowXWindowFatalException(XServerError,"UnableToReadXWindowImage",
5093 image_info->filename)
5094 else
5095 {
5096 (void) CopyMagickString(image->filename,image_info->filename,
5097 MaxTextExtent);
5098 if ((crop_info.width != 0) && (crop_info.height != 0))
5099 {
5100 Image
5101 *clone_image,
5102 *crop_image;
5103
5104 /*
5105 Crop image as defined by the cropping rectangle.
5106 */
cristy6710d842011-10-20 23:23:00 +00005107 clone_image=CloneImage(image,0,0,MagickTrue,exception);
cristy3ed852e2009-09-05 21:47:34 +00005108 if (clone_image != (Image *) NULL)
5109 {
cristy6710d842011-10-20 23:23:00 +00005110 crop_image=CropImage(clone_image,&crop_info,exception);
cristy3ed852e2009-09-05 21:47:34 +00005111 if (crop_image != (Image *) NULL)
5112 {
5113 image=DestroyImage(image);
5114 image=crop_image;
5115 }
5116 }
5117 }
5118 status=XGetWMName(display,target,&window_name);
5119 if (status == True)
5120 {
5121 if ((image_info->filename != (char *) NULL) &&
5122 (*image_info->filename == '\0'))
5123 (void) CopyMagickString(image->filename,(char *) window_name.value,
5124 (size_t) window_name.nitems+1);
5125 (void) XFree((void *) window_name.value);
5126 }
5127 }
5128 if (ximage_info->silent == MagickFalse)
5129 {
5130 /*
5131 Alert the user we're done.
5132 */
5133 (void) XBell(display,0);
5134 (void) XBell(display,0);
5135 }
5136 (void) XCloseDisplay(display);
5137 return(image);
5138}
5139
5140/*
5141%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5142% %
5143% %
5144% %
5145% X I n i t i a l i z e W i n d o w s %
5146% %
5147% %
5148% %
5149%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5150%
5151% XInitializeWindows() initializes the XWindows structure.
5152%
5153% The format of the XInitializeWindows method is:
5154%
5155% XWindows *XInitializeWindows(Display *display,
5156% XResourceInfo *resource_info)
5157%
5158% A description of each parameter follows:
5159%
5160% o windows: XInitializeWindows returns a pointer to a XWindows structure.
5161%
5162% o display: Specifies a connection to an X server; returned from
5163% XOpenDisplay.
5164%
5165% o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
5166%
5167*/
cristybcbda3f2011-09-03 13:01:22 +00005168MagickPrivate XWindows *XInitializeWindows(Display *display,
cristy3ed852e2009-09-05 21:47:34 +00005169 XResourceInfo *resource_info)
5170{
5171 Window
5172 root_window;
5173
5174 XWindows
5175 *windows;
5176
5177 /*
5178 Allocate windows structure.
5179 */
cristy73bd4a52010-10-05 11:24:23 +00005180 windows=(XWindows *) AcquireMagickMemory(sizeof(*windows));
cristy3ed852e2009-09-05 21:47:34 +00005181 if (windows == (XWindows *) NULL)
5182 {
5183 ThrowXWindowFatalException(XServerFatalError,"MemoryAllocationFailed",
5184 "...");
5185 return((XWindows *) NULL);
5186 }
5187 (void) ResetMagickMemory(windows,0,sizeof(*windows));
5188 windows->pixel_info=(XPixelInfo *) AcquireMagickMemory(
5189 sizeof(*windows->pixel_info));
5190 windows->icon_pixel=(XPixelInfo *) AcquireMagickMemory(
5191 sizeof(*windows->icon_pixel));
5192 windows->icon_resources=(XResourceInfo *) AcquireMagickMemory(
5193 sizeof(*windows->icon_resources));
5194 if ((windows->pixel_info == (XPixelInfo *) NULL) ||
5195 (windows->icon_pixel == (XPixelInfo *) NULL) ||
5196 (windows->icon_resources == (XResourceInfo *) NULL))
5197 {
5198 ThrowXWindowFatalException(XServerFatalError,"MemoryAllocationFailed",
5199 "...");
5200 return((XWindows *) NULL);
5201 }
5202 /*
5203 Initialize windows structure.
5204 */
5205 windows->display=display;
5206 windows->wm_protocols=XInternAtom(display,"WM_PROTOCOLS",MagickFalse);
5207 windows->wm_delete_window=XInternAtom(display,"WM_DELETE_WINDOW",MagickFalse);
5208 windows->wm_take_focus=XInternAtom(display,"WM_TAKE_FOCUS",MagickFalse);
5209 windows->im_protocols=XInternAtom(display,"IM_PROTOCOLS",MagickFalse);
5210 windows->im_remote_command=
5211 XInternAtom(display,"IM_REMOTE_COMMAND",MagickFalse);
5212 windows->im_update_widget=XInternAtom(display,"IM_UPDATE_WIDGET",MagickFalse);
5213 windows->im_update_colormap=
5214 XInternAtom(display,"IM_UPDATE_COLORMAP",MagickFalse);
5215 windows->im_former_image=XInternAtom(display,"IM_FORMER_IMAGE",MagickFalse);
5216 windows->im_next_image=XInternAtom(display,"IM_NEXT_IMAGE",MagickFalse);
5217 windows->im_retain_colors=XInternAtom(display,"IM_RETAIN_COLORS",MagickFalse);
5218 windows->im_exit=XInternAtom(display,"IM_EXIT",MagickFalse);
5219 windows->dnd_protocols=XInternAtom(display,"DndProtocol",MagickFalse);
cristy0157aea2010-04-24 21:12:18 +00005220#if defined(MAGICKCORE_WINDOWS_SUPPORT)
cristy3ed852e2009-09-05 21:47:34 +00005221 (void) XSynchronize(display,IsWindows95());
5222#endif
5223 if (IsEventLogging())
5224 {
5225 (void) XSynchronize(display,MagickTrue);
5226 (void) LogMagickEvent(X11Event,GetMagickModule(),"Version: %s",
cristybb503372010-05-27 20:51:26 +00005227 GetMagickVersion((size_t *) NULL));
cristy3ed852e2009-09-05 21:47:34 +00005228 (void) LogMagickEvent(X11Event,GetMagickModule(),"Protocols:");
5229 (void) LogMagickEvent(X11Event,GetMagickModule(),
5230 " Window Manager: 0x%lx",windows->wm_protocols);
5231 (void) LogMagickEvent(X11Event,GetMagickModule(),
5232 " delete window: 0x%lx",windows->wm_delete_window);
5233 (void) LogMagickEvent(X11Event,GetMagickModule()," take focus: 0x%lx",
5234 windows->wm_take_focus);
5235 (void) LogMagickEvent(X11Event,GetMagickModule()," ImageMagick: 0x%lx",
5236 windows->im_protocols);
5237 (void) LogMagickEvent(X11Event,GetMagickModule(),
5238 " remote command: 0x%lx",windows->im_remote_command);
5239 (void) LogMagickEvent(X11Event,GetMagickModule(),
5240 " update widget: 0x%lx",windows->im_update_widget);
5241 (void) LogMagickEvent(X11Event,GetMagickModule(),
5242 " update colormap: 0x%lx",windows->im_update_colormap);
5243 (void) LogMagickEvent(X11Event,GetMagickModule(),
5244 " former image: 0x%lx",windows->im_former_image);
5245 (void) LogMagickEvent(X11Event,GetMagickModule()," next image: 0x%lx",
5246 windows->im_next_image);
5247 (void) LogMagickEvent(X11Event,GetMagickModule(),
5248 " retain colors: 0x%lx",windows->im_retain_colors);
5249 (void) LogMagickEvent(X11Event,GetMagickModule()," exit: 0x%lx",
5250 windows->im_exit);
5251 (void) LogMagickEvent(X11Event,GetMagickModule()," Drag and Drop: 0x%lx",
5252 windows->dnd_protocols);
5253 }
5254 /*
5255 Allocate standard colormap.
5256 */
5257 windows->map_info=XAllocStandardColormap();
5258 windows->icon_map=XAllocStandardColormap();
5259 if ((windows->map_info == (XStandardColormap *) NULL) ||
5260 (windows->icon_map == (XStandardColormap *) NULL))
5261 ThrowXWindowFatalException(ResourceLimitFatalError,
5262 "MemoryAllocationFailed","...");
5263 windows->map_info->colormap=(Colormap) NULL;
5264 windows->icon_map->colormap=(Colormap) NULL;
cristyf2faecf2010-05-28 19:19:36 +00005265 windows->pixel_info->pixels=(unsigned long *) NULL;
cristy3ed852e2009-09-05 21:47:34 +00005266 windows->pixel_info->annotate_context=(GC) NULL;
5267 windows->pixel_info->highlight_context=(GC) NULL;
5268 windows->pixel_info->widget_context=(GC) NULL;
5269 windows->font_info=(XFontStruct *) NULL;
5270 windows->icon_pixel->annotate_context=(GC) NULL;
cristyf2faecf2010-05-28 19:19:36 +00005271 windows->icon_pixel->pixels=(unsigned long *) NULL;
cristy3ed852e2009-09-05 21:47:34 +00005272 /*
5273 Allocate visual.
5274 */
5275 *windows->icon_resources=(*resource_info);
5276 windows->icon_resources->visual_type=(char *) "default";
5277 windows->icon_resources->colormap=SharedColormap;
5278 windows->visual_info=
5279 XBestVisualInfo(display,windows->map_info,resource_info);
5280 windows->icon_visual=
5281 XBestVisualInfo(display,windows->icon_map,windows->icon_resources);
5282 if ((windows->visual_info == (XVisualInfo *) NULL) ||
5283 (windows->icon_visual == (XVisualInfo *) NULL))
5284 ThrowXWindowFatalException(XServerFatalError,"UnableToGetVisual",
5285 resource_info->visual_type);
5286 if (IsEventLogging())
5287 {
5288 (void) LogMagickEvent(X11Event,GetMagickModule(),"Visual:");
5289 (void) LogMagickEvent(X11Event,GetMagickModule()," visual id: 0x%lx",
5290 windows->visual_info->visualid);
5291 (void) LogMagickEvent(X11Event,GetMagickModule()," class: %s",
5292 XVisualClassName(windows->visual_info->klass));
5293 (void) LogMagickEvent(X11Event,GetMagickModule()," depth: %d planes",
5294 windows->visual_info->depth);
5295 (void) LogMagickEvent(X11Event,GetMagickModule(),
5296 " size of colormap: %d entries",windows->visual_info->colormap_size);
5297 (void) LogMagickEvent(X11Event,GetMagickModule(),
5298 " red, green, blue masks: 0x%lx 0x%lx 0x%lx",
5299 windows->visual_info->red_mask,windows->visual_info->green_mask,
5300 windows->visual_info->blue_mask);
5301 (void) LogMagickEvent(X11Event,GetMagickModule(),
5302 " significant bits in color: %d bits",
5303 windows->visual_info->bits_per_rgb);
5304 }
5305 /*
5306 Allocate class and manager hints.
5307 */
5308 windows->class_hints=XAllocClassHint();
5309 windows->manager_hints=XAllocWMHints();
5310 if ((windows->class_hints == (XClassHint *) NULL) ||
5311 (windows->manager_hints == (XWMHints *) NULL))
5312 ThrowXWindowFatalException(ResourceLimitFatalError,
5313 "MemoryAllocationFailed","...");
5314 /*
5315 Determine group leader if we have one.
5316 */
5317 root_window=XRootWindow(display,windows->visual_info->screen);
5318 windows->group_leader.id=(Window) NULL;
5319 if (resource_info->window_group != (char *) NULL)
5320 {
5321 if (isdigit((unsigned char) *resource_info->window_group) != 0)
5322 windows->group_leader.id=XWindowByID(display,root_window,(Window)
5323 strtol((char *) resource_info->window_group,(char **) NULL,0));
5324 if (windows->group_leader.id == (Window) NULL)
5325 windows->group_leader.id=
5326 XWindowByName(display,root_window,resource_info->window_group);
5327 }
5328 return(windows);
5329}
5330
5331/*
5332%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5333% %
5334% %
5335% %
5336% X M a k e C u r s o r %
5337% %
5338% %
5339% %
5340%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5341%
5342% XMakeCursor() creates a crosshairs X11 cursor.
5343%
5344% The format of the XMakeCursor method is:
5345%
5346% Cursor XMakeCursor(Display *display,Window window,Colormap colormap,
5347% char *background_color,char *foreground_color)
5348%
5349% A description of each parameter follows:
5350%
5351% o display: Specifies a connection to an X server; returned from
5352% XOpenDisplay.
5353%
5354% o window: Specifies the ID of the window for which the cursor is
5355% assigned.
5356%
5357% o colormap: Specifies the ID of the colormap from which the background
5358% and foreground color will be retrieved.
5359%
5360% o background_color: Specifies the color to use for the cursor background.
5361%
5362% o foreground_color: Specifies the color to use for the cursor foreground.
5363%
5364*/
cristybcbda3f2011-09-03 13:01:22 +00005365MagickPrivate Cursor XMakeCursor(Display *display,Window window,
cristy3ed852e2009-09-05 21:47:34 +00005366 Colormap colormap,char *background_color,char *foreground_color)
5367{
5368#define scope_height 17
5369#define scope_x_hot 8
5370#define scope_y_hot 8
5371#define scope_width 17
5372
5373 static const unsigned char
5374 scope_bits[] =
5375 {
5376 0x80, 0x03, 0x00, 0x80, 0x02, 0x00, 0x80, 0x02, 0x00, 0x80, 0x02,
5377 0x00, 0x80, 0x02, 0x00, 0x80, 0x02, 0x00, 0x80, 0x02, 0x00, 0x7f,
5378 0xfc, 0x01, 0x01, 0x00, 0x01, 0x7f, 0xfc, 0x01, 0x80, 0x02, 0x00,
5379 0x80, 0x02, 0x00, 0x80, 0x02, 0x00, 0x80, 0x02, 0x00, 0x80, 0x02,
5380 0x00, 0x80, 0x02, 0x00, 0x80, 0x03, 0x00
5381 },
5382 scope_mask_bits[] =
5383 {
5384 0xc0, 0x07, 0x00, 0xc0, 0x07, 0x00, 0xc0, 0x06, 0x00, 0xc0, 0x06,
5385 0x00, 0xc0, 0x06, 0x00, 0xc0, 0x06, 0x00, 0xff, 0xfe, 0x01, 0x7f,
5386 0xfc, 0x01, 0x03, 0x80, 0x01, 0x7f, 0xfc, 0x01, 0xff, 0xfe, 0x01,
5387 0xc0, 0x06, 0x00, 0xc0, 0x06, 0x00, 0xc0, 0x06, 0x00, 0xc0, 0x06,
5388 0x00, 0xc0, 0x07, 0x00, 0xc0, 0x07, 0x00
5389 };
5390
5391 Cursor
5392 cursor;
5393
5394 Pixmap
5395 mask,
5396 source;
5397
5398 XColor
5399 background,
5400 foreground;
5401
5402 assert(display != (Display *) NULL);
5403 assert(window != (Window) NULL);
5404 assert(colormap != (Colormap) NULL);
5405 assert(background_color != (char *) NULL);
5406 assert(foreground_color != (char *) NULL);
5407 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",background_color);
5408 source=XCreateBitmapFromData(display,window,(char *) scope_bits,scope_width,
5409 scope_height);
5410 mask=XCreateBitmapFromData(display,window,(char *) scope_mask_bits,
5411 scope_width,scope_height);
5412 if ((source == (Pixmap) NULL) || (mask == (Pixmap) NULL))
5413 {
5414 ThrowXWindowFatalException(XServerError,"UnableToCreatePixmap","...");
5415 return((Cursor) NULL);
5416 }
5417 (void) XParseColor(display,colormap,background_color,&background);
5418 (void) XParseColor(display,colormap,foreground_color,&foreground);
5419 cursor=XCreatePixmapCursor(display,source,mask,&foreground,&background,
5420 scope_x_hot,scope_y_hot);
5421 (void) XFreePixmap(display,source);
5422 (void) XFreePixmap(display,mask);
5423 return(cursor);
5424}
5425
5426/*
5427%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5428% %
5429% %
5430% %
5431% X M a k e I m a g e %
5432% %
5433% %
5434% %
5435%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5436%
5437% XMakeImage() creates an X11 image. If the image size differs from the X11
5438% image size, the image is first resized.
5439%
5440% The format of the XMakeImage method is:
5441%
5442% MagickBooleanType XMakeImage(Display *display,
5443% const XResourceInfo *resource_info,XWindowInfo *window,Image *image,
cristy051718b2011-08-28 22:49:25 +00005444% unsigned int width,unsigned int height,ExceptionInfo *exception)
cristy3ed852e2009-09-05 21:47:34 +00005445%
5446% A description of each parameter follows:
5447%
5448% o display: Specifies a connection to an X server; returned from
5449% XOpenDisplay.
5450%
5451% o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
5452%
5453% o window: Specifies a pointer to a XWindowInfo structure.
5454%
5455% o image: the image.
5456%
5457% o width: Specifies the width in pixels of the rectangular area to
5458% display.
5459%
5460% o height: Specifies the height in pixels of the rectangular area to
5461% display.
5462%
cristy051718b2011-08-28 22:49:25 +00005463% o exception: return any errors or warnings in this structure.
5464%
cristy3ed852e2009-09-05 21:47:34 +00005465*/
cristybcbda3f2011-09-03 13:01:22 +00005466MagickPrivate MagickBooleanType XMakeImage(Display *display,
cristy3ed852e2009-09-05 21:47:34 +00005467 const XResourceInfo *resource_info,XWindowInfo *window,Image *image,
cristy051718b2011-08-28 22:49:25 +00005468 unsigned int width,unsigned int height,ExceptionInfo *exception)
cristy3ed852e2009-09-05 21:47:34 +00005469{
5470#define CheckOverflowException(length,width,height) \
5471 (((height) != 0) && ((length)/((size_t) height) != ((size_t) width)))
5472
5473 int
5474 depth,
5475 format;
5476
5477 size_t
5478 length;
5479
5480 XImage
5481 *matte_image,
5482 *ximage;
5483
5484 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
5485 assert(display != (Display *) NULL);
5486 assert(resource_info != (XResourceInfo *) NULL);
5487 assert(window != (XWindowInfo *) NULL);
5488 assert(width != 0);
5489 assert(height != 0);
5490 if ((window->width == 0) || (window->height == 0))
5491 return(MagickFalse);
5492 /*
5493 Apply user transforms to the image.
5494 */
5495 (void) XCheckDefineCursor(display,window->id,window->busy_cursor);
5496 (void) XFlush(display);
5497 depth=(int) window->depth;
5498 if (window->destroy)
5499 window->image=DestroyImage(window->image);
5500 window->image=image;
5501 window->destroy=MagickFalse;
5502 if (window->image != (Image *) NULL)
5503 {
5504 if (window->crop_geometry != (char *) NULL)
5505 {
5506 Image
5507 *crop_image;
5508
5509 RectangleInfo
5510 crop_info;
5511
5512 /*
5513 Crop image.
5514 */
5515 window->image->page.x=0;
5516 window->image->page.y=0;
5517 (void) ParsePageGeometry(window->image,window->crop_geometry,
cristy6710d842011-10-20 23:23:00 +00005518 &crop_info,exception);
5519 crop_image=CropImage(window->image,&crop_info,exception);
cristy3ed852e2009-09-05 21:47:34 +00005520 if (crop_image != (Image *) NULL)
5521 {
5522 if (window->image != image)
5523 window->image=DestroyImage(window->image);
5524 window->image=crop_image;
5525 window->destroy=MagickTrue;
5526 }
5527 }
5528 if ((width != (unsigned int) window->image->columns) ||
5529 (height != (unsigned int) window->image->rows))
5530 {
5531 Image
5532 *resize_image;
5533
5534 /*
5535 Resize image.
5536 */
5537 resize_image=NewImageList();
5538 if (window->pixel_info->colors != 0)
cristy6710d842011-10-20 23:23:00 +00005539 resize_image=SampleImage(window->image,width,height,exception);
cristy3ed852e2009-09-05 21:47:34 +00005540 else
cristy6710d842011-10-20 23:23:00 +00005541 resize_image=ThumbnailImage(window->image,width,height,exception);
cristy3ed852e2009-09-05 21:47:34 +00005542 if (resize_image != (Image *) NULL)
5543 {
5544 if (window->image != image)
5545 window->image=DestroyImage(window->image);
5546 window->image=resize_image;
5547 window->destroy=MagickTrue;
5548 }
5549 }
5550 width=(unsigned int) window->image->columns;
cristybb503372010-05-27 20:51:26 +00005551 assert((size_t) width == window->image->columns);
cristy3ed852e2009-09-05 21:47:34 +00005552 height=(unsigned int) window->image->rows;
cristybb503372010-05-27 20:51:26 +00005553 assert((size_t) height == window->image->rows);
cristy3ed852e2009-09-05 21:47:34 +00005554 }
5555 /*
5556 Create X image.
5557 */
5558 ximage=(XImage *) NULL;
5559 format=(depth == 1) ? XYBitmap : ZPixmap;
5560#if defined(MAGICKCORE_HAVE_SHARED_MEMORY)
5561 if (window->shared_memory != MagickFalse)
5562 {
5563 XShmSegmentInfo
5564 *segment_info;
5565
5566 segment_info=(XShmSegmentInfo *) window->segment_info;
5567 segment_info[1].shmid=(-1);
5568 segment_info[1].shmaddr=(char *) NULL;
5569 ximage=XShmCreateImage(display,window->visual,(unsigned int) depth,format,
5570 (char *) NULL,&segment_info[1],width,height);
5571 if (ximage == (XImage *) NULL)
5572 window->shared_memory=MagickFalse;
5573 length=(size_t) ximage->bytes_per_line*ximage->height;
5574 if (CheckOverflowException(length,ximage->bytes_per_line,ximage->height))
5575 window->shared_memory=MagickFalse;
5576 if (window->shared_memory != MagickFalse)
5577 segment_info[1].shmid=shmget(IPC_PRIVATE,length,IPC_CREAT | 0777);
5578 if (window->shared_memory != MagickFalse)
5579 segment_info[1].shmaddr=(char *) shmat(segment_info[1].shmid,0,0);
5580 if (segment_info[1].shmid < 0)
5581 window->shared_memory=MagickFalse;
5582 if (window->shared_memory != MagickFalse)
5583 (void) shmctl(segment_info[1].shmid,IPC_RMID,0);
5584 else
5585 {
5586 if (ximage != (XImage *) NULL)
5587 XDestroyImage(ximage);
5588 ximage=(XImage *) NULL;
5589 if (segment_info[1].shmaddr)
5590 {
5591 (void) shmdt(segment_info[1].shmaddr);
5592 segment_info[1].shmaddr=(char *) NULL;
5593 }
5594 if (segment_info[1].shmid >= 0)
5595 {
5596 (void) shmctl(segment_info[1].shmid,IPC_RMID,0);
5597 segment_info[1].shmid=(-1);
5598 }
5599 }
5600 }
5601#endif
5602 /*
5603 Allocate X image pixel data.
5604 */
5605#if defined(MAGICKCORE_HAVE_SHARED_MEMORY)
5606 if (window->shared_memory)
5607 {
5608 Status
5609 status;
5610
5611 XShmSegmentInfo
5612 *segment_info;
5613
5614 (void) XSync(display,MagickFalse);
5615 xerror_alert=MagickFalse;
5616 segment_info=(XShmSegmentInfo *) window->segment_info;
5617 ximage->data=segment_info[1].shmaddr;
5618 segment_info[1].readOnly=MagickFalse;
5619 status=XShmAttach(display,&segment_info[1]);
5620 if (status != False)
5621 (void) XSync(display,MagickFalse);
5622 if ((status == False) || (xerror_alert != MagickFalse))
5623 {
5624 window->shared_memory=MagickFalse;
5625 if (status != False)
5626 XShmDetach(display,&segment_info[1]);
5627 if (ximage != (XImage *) NULL)
5628 {
5629 ximage->data=NULL;
5630 XDestroyImage(ximage);
5631 ximage=(XImage *) NULL;
5632 }
5633 if (segment_info[1].shmid >= 0)
5634 {
5635 if (segment_info[1].shmaddr != NULL)
5636 (void) shmdt(segment_info[1].shmaddr);
5637 (void) shmctl(segment_info[1].shmid,IPC_RMID,0);
5638 segment_info[1].shmid=(-1);
5639 segment_info[1].shmaddr=(char *) NULL;
5640 }
5641 }
5642 }
5643#endif
5644 if (window->shared_memory == MagickFalse)
5645 ximage=XCreateImage(display,window->visual,(unsigned int) depth,format,0,
5646 (char *) NULL,width,height,XBitmapPad(display),0);
5647 if (ximage == (XImage *) NULL)
5648 {
5649 /*
5650 Unable to create X image.
5651 */
5652 (void) XCheckDefineCursor(display,window->id,window->cursor);
5653 return(MagickFalse);
5654 }
5655 length=(size_t) ximage->bytes_per_line*ximage->height;
5656 if (IsEventLogging())
5657 {
5658 (void) LogMagickEvent(X11Event,GetMagickModule(),"XImage:");
5659 (void) LogMagickEvent(X11Event,GetMagickModule()," width, height: %dx%d",
5660 ximage->width,ximage->height);
5661 (void) LogMagickEvent(X11Event,GetMagickModule()," format: %d",
5662 ximage->format);
5663 (void) LogMagickEvent(X11Event,GetMagickModule()," byte order: %d",
5664 ximage->byte_order);
5665 (void) LogMagickEvent(X11Event,GetMagickModule(),
5666 " bitmap unit, bit order, pad: %d %d %d",ximage->bitmap_unit,
5667 ximage->bitmap_bit_order,ximage->bitmap_pad);
5668 (void) LogMagickEvent(X11Event,GetMagickModule()," depth: %d",
5669 ximage->depth);
5670 (void) LogMagickEvent(X11Event,GetMagickModule()," bytes per line: %d",
5671 ximage->bytes_per_line);
5672 (void) LogMagickEvent(X11Event,GetMagickModule()," bits per pixel: %d",
5673 ximage->bits_per_pixel);
5674 (void) LogMagickEvent(X11Event,GetMagickModule(),
5675 " red, green, blue masks: 0x%lx 0x%lx 0x%lx",ximage->red_mask,
5676 ximage->green_mask,ximage->blue_mask);
5677 }
5678 if (window->shared_memory == MagickFalse)
5679 {
5680 if (ximage->format != XYBitmap)
5681 ximage->data=(char *) AcquireQuantumMemory((size_t)
5682 ximage->bytes_per_line,(size_t) ximage->height);
5683 else
5684 ximage->data=(char *) AcquireQuantumMemory((size_t)
5685 ximage->bytes_per_line*ximage->depth,(size_t) ximage->height);
5686 }
5687 if (ximage->data == (char *) NULL)
5688 {
5689 /*
5690 Unable to allocate pixel data.
5691 */
5692 XDestroyImage(ximage);
5693 ximage=(XImage *) NULL;
5694 (void) XCheckDefineCursor(display,window->id,window->cursor);
5695 return(MagickFalse);
5696 }
5697 if (window->ximage != (XImage *) NULL)
5698 {
5699 /*
5700 Destroy previous X image.
5701 */
5702 length=(size_t) window->ximage->bytes_per_line*window->ximage->height;
5703#if defined(MAGICKCORE_HAVE_SHARED_MEMORY)
5704 if (window->segment_info != (XShmSegmentInfo *) NULL)
5705 {
5706 XShmSegmentInfo
5707 *segment_info;
5708
5709 segment_info=(XShmSegmentInfo *) window->segment_info;
5710 if (segment_info[0].shmid >= 0)
5711 {
5712 (void) XSync(display,MagickFalse);
5713 (void) XShmDetach(display,&segment_info[0]);
5714 (void) XSync(display,MagickFalse);
5715 if (segment_info[0].shmaddr != (char *) NULL)
5716 (void) shmdt(segment_info[0].shmaddr);
5717 (void) shmctl(segment_info[0].shmid,IPC_RMID,0);
5718 segment_info[0].shmid=(-1);
5719 segment_info[0].shmaddr=(char *) NULL;
5720 window->ximage->data=(char *) NULL;
5721 }
5722 }
5723#endif
5724 if (window->ximage->data != (char *) NULL)
5725 free(window->ximage->data);
5726 window->ximage->data=(char *) NULL;
5727 XDestroyImage(window->ximage);
5728 window->ximage=(XImage *) NULL;
5729 }
5730#if defined(MAGICKCORE_HAVE_SHARED_MEMORY)
5731 if (window->segment_info != (XShmSegmentInfo *) NULL)
5732 {
5733 XShmSegmentInfo
5734 *segment_info;
5735
5736 segment_info=(XShmSegmentInfo *) window->segment_info;
5737 segment_info[0]=segment_info[1];
5738 }
5739#endif
5740 window->ximage=ximage;
5741 matte_image=(XImage *) NULL;
5742 if ((window->shape != MagickFalse) && (window->image != (Image *) NULL))
5743 if ((window->image->matte != MagickFalse) &&
cristyc57f6942010-11-12 01:47:39 +00005744 ((int) width <= XDisplayWidth(display,window->screen)) &&
5745 ((int) height <= XDisplayHeight(display,window->screen)))
cristy3ed852e2009-09-05 21:47:34 +00005746 {
5747 /*
5748 Create matte image.
5749 */
5750 matte_image=XCreateImage(display,window->visual,1,XYBitmap,0,
5751 (char *) NULL,width,height,XBitmapPad(display),0);
5752 if (IsEventLogging())
5753 {
5754 (void) LogMagickEvent(X11Event,GetMagickModule(),"Matte Image:");
5755 (void) LogMagickEvent(X11Event,GetMagickModule(),
5756 " width, height: %dx%d",matte_image->width,matte_image->height);
5757 }
5758 if (matte_image != (XImage *) NULL)
5759 {
5760 /*
5761 Allocate matte image pixel data.
5762 */
5763 matte_image->data=(char *) AcquireQuantumMemory((size_t)
5764 matte_image->bytes_per_line*matte_image->depth,
5765 (size_t) matte_image->height);
5766 if (matte_image->data == (char *) NULL)
5767 {
5768 XDestroyImage(matte_image);
5769 matte_image=(XImage *) NULL;
5770 }
5771 }
5772 }
5773 if (window->matte_image != (XImage *) NULL)
5774 {
5775 /*
5776 Free matte image.
5777 */
5778 if (window->matte_image->data != (char *) NULL)
5779 free(window->matte_image->data);
5780 window->matte_image->data=(char *) NULL;
5781 XDestroyImage(window->matte_image);
5782 window->matte_image=(XImage *) NULL;
5783 }
5784 window->matte_image=matte_image;
5785 if (window->matte_pixmap != (Pixmap) NULL)
5786 {
5787 (void) XFreePixmap(display,window->matte_pixmap);
5788 window->matte_pixmap=(Pixmap) NULL;
5789#if defined(MAGICKCORE_HAVE_SHAPE)
5790 if (window->shape != MagickFalse)
5791 XShapeCombineMask(display,window->id,ShapeBounding,0,0,None,ShapeSet);
5792#endif
5793 }
5794 window->stasis=MagickFalse;
5795 /*
5796 Convert pixels to X image data.
5797 */
5798 if (window->image != (Image *) NULL)
5799 {
5800 if ((ximage->byte_order == LSBFirst) || ((ximage->format == XYBitmap) &&
5801 (ximage->bitmap_bit_order == LSBFirst)))
5802 XMakeImageLSBFirst(resource_info,window,window->image,ximage,
cristye941a752011-10-15 01:52:48 +00005803 matte_image,exception);
cristy3ed852e2009-09-05 21:47:34 +00005804 else
5805 XMakeImageMSBFirst(resource_info,window,window->image,ximage,
cristye941a752011-10-15 01:52:48 +00005806 matte_image,exception);
cristy3ed852e2009-09-05 21:47:34 +00005807 }
5808 if (window->matte_image != (XImage *) NULL)
5809 {
5810 /*
5811 Create matte pixmap.
5812 */
5813 window->matte_pixmap=XCreatePixmap(display,window->id,width,height,1);
5814 if (window->matte_pixmap != (Pixmap) NULL)
5815 {
5816 GC
5817 graphics_context;
5818
5819 XGCValues
5820 context_values;
5821
5822 /*
5823 Copy matte image to matte pixmap.
5824 */
cristy4c08aed2011-07-01 19:47:50 +00005825 context_values.background=0;
5826 context_values.foreground=1;
cristy3ed852e2009-09-05 21:47:34 +00005827 graphics_context=XCreateGC(display,window->matte_pixmap,
cristybb503372010-05-27 20:51:26 +00005828 (size_t) (GCBackground | GCForeground),&context_values);
cristy3ed852e2009-09-05 21:47:34 +00005829 (void) XPutImage(display,window->matte_pixmap,graphics_context,
5830 window->matte_image,0,0,0,0,width,height);
5831 (void) XFreeGC(display,graphics_context);
5832#if defined(MAGICKCORE_HAVE_SHAPE)
5833 if (window->shape != MagickFalse)
5834 XShapeCombineMask(display,window->id,ShapeBounding,0,0,
5835 window->matte_pixmap,ShapeSet);
5836#endif
5837 }
5838 }
5839 (void) XMakePixmap(display,resource_info,window);
5840 /*
5841 Restore cursor.
5842 */
5843 (void) XCheckDefineCursor(display,window->id,window->cursor);
5844 return(MagickTrue);
5845}
5846
5847/*
5848%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5849% %
5850% %
5851% %
5852+ X M a k e I m a g e L S B F i r s t %
5853% %
5854% %
5855% %
5856%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5857%
5858% XMakeImageLSBFirst() initializes the pixel data of an X11 Image. The X image
5859% pixels are copied in least-significant bit and byte first order. The
5860% server's scanline pad is respected. Rather than using one or two general
5861% cases, many special cases are found here to help speed up the image
5862% conversion.
5863%
5864% The format of the XMakeImageLSBFirst method is:
5865%
cristye941a752011-10-15 01:52:48 +00005866% void XMakeImageLSBFirst(Display *display,XWindows *windows,
5867% ExceptionInfo *exception)
cristy3ed852e2009-09-05 21:47:34 +00005868%
5869% A description of each parameter follows:
5870%
5871% o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
5872%
5873% o window: Specifies a pointer to a XWindowInfo structure.
5874%
5875% o image: the image.
5876%
5877% o ximage: Specifies a pointer to a XImage structure; returned from
5878% XCreateImage.
5879%
5880% o matte_image: Specifies a pointer to a XImage structure; returned from
5881% XCreateImage.
5882%
cristye941a752011-10-15 01:52:48 +00005883% o exception: return any errors or warnings in this structure.
5884%
cristy3ed852e2009-09-05 21:47:34 +00005885*/
5886static void XMakeImageLSBFirst(const XResourceInfo *resource_info,
cristye941a752011-10-15 01:52:48 +00005887 const XWindowInfo *window,Image *image,XImage *ximage,XImage *matte_image,
5888 ExceptionInfo *exception)
cristy3ed852e2009-09-05 21:47:34 +00005889{
cristyc57f6942010-11-12 01:47:39 +00005890 CacheView
5891 *canvas_view;
5892
cristy3ed852e2009-09-05 21:47:34 +00005893 Image
5894 *canvas;
5895
5896 int
5897 y;
5898
cristy4c08aed2011-07-01 19:47:50 +00005899 register const Quantum
cristy3ed852e2009-09-05 21:47:34 +00005900 *p;
5901
5902 register int
5903 x;
5904
5905 register unsigned char
5906 *q;
5907
5908 unsigned char
5909 bit,
5910 byte;
5911
5912 unsigned int
5913 scanline_pad;
5914
cristyf2faecf2010-05-28 19:19:36 +00005915 unsigned long
cristy3ed852e2009-09-05 21:47:34 +00005916 pixel,
5917 *pixels;
5918
5919 XStandardColormap
5920 *map_info;
5921
5922 assert(resource_info != (XResourceInfo *) NULL);
5923 assert(window != (XWindowInfo *) NULL);
5924 assert(image != (Image *) NULL);
5925 if (image->debug != MagickFalse)
5926 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
5927 canvas=image;
cristybab87c32010-02-09 20:54:22 +00005928 if ((window->immutable == MagickFalse) &&
cristy54666e82010-02-03 23:34:26 +00005929 (image->storage_class == DirectClass) && (image->matte != MagickFalse))
cristy3ed852e2009-09-05 21:47:34 +00005930 {
5931 char
5932 size[MaxTextExtent];
5933
5934 Image
5935 *pattern;
5936
5937 ImageInfo
5938 *image_info;
5939
5940 image_info=AcquireImageInfo();
5941 (void) CopyMagickString(image_info->filename,
5942 resource_info->image_info->texture != (char *) NULL ?
5943 resource_info->image_info->texture : "pattern:checkerboard",
5944 MaxTextExtent);
cristyb51dff52011-05-19 16:55:47 +00005945 (void) FormatLocaleString(size,MaxTextExtent,"%.20gx%.20g",(double)
cristye8c25f92010-06-03 00:53:06 +00005946 image->columns,(double) image->rows);
cristy3ed852e2009-09-05 21:47:34 +00005947 image_info->size=ConstantString(size);
cristy6710d842011-10-20 23:23:00 +00005948 pattern=ReadImage(image_info,exception);
cristy3ed852e2009-09-05 21:47:34 +00005949 image_info=DestroyImageInfo(image_info);
5950 if (pattern != (Image *) NULL)
5951 {
cristy6710d842011-10-20 23:23:00 +00005952 canvas=CloneImage(image,0,0,MagickTrue,exception);
cristy3ed852e2009-09-05 21:47:34 +00005953 if (canvas != (Image *) NULL)
cristye941a752011-10-15 01:52:48 +00005954 (void) CompositeImage(canvas,DstOverCompositeOp,pattern,0,0,
5955 exception);
cristy3ed852e2009-09-05 21:47:34 +00005956 pattern=DestroyImage(pattern);
5957 }
5958 }
5959 scanline_pad=(unsigned int) (ximage->bytes_per_line-((ximage->width*
5960 ximage->bits_per_pixel) >> 3));
5961 map_info=window->map_info;
5962 pixels=window->pixel_info->pixels;
5963 q=(unsigned char *) ximage->data;
5964 x=0;
cristyc57f6942010-11-12 01:47:39 +00005965 canvas_view=AcquireCacheView(canvas);
cristy3ed852e2009-09-05 21:47:34 +00005966 if (ximage->format == XYBitmap)
5967 {
5968 register unsigned short
5969 polarity;
5970
5971 unsigned char
5972 background,
5973 foreground;
5974
5975 /*
5976 Convert canvas to big-endian bitmap.
5977 */
5978 background=(unsigned char)
5979 (XPixelIntensity(&window->pixel_info->foreground_color) <
5980 XPixelIntensity(&window->pixel_info->background_color) ? 0x80 : 0x00);
5981 foreground=(unsigned char)
5982 (XPixelIntensity(&window->pixel_info->background_color) <
5983 XPixelIntensity(&window->pixel_info->foreground_color) ? 0x80 : 0x00);
cristy101ab702011-10-13 13:06:32 +00005984 polarity=(unsigned short) ((GetPixelInfoIntensity(
cristy3ed852e2009-09-05 21:47:34 +00005985 &canvas->colormap[0])) < ((Quantum) QuantumRange/2) ? 1 : 0);
5986 if (canvas->colors == 2)
cristy101ab702011-10-13 13:06:32 +00005987 polarity=GetPixelInfoIntensity(&canvas->colormap[0]) <
5988 GetPixelInfoIntensity(&canvas->colormap[1]);
cristy3ed852e2009-09-05 21:47:34 +00005989 for (y=0; y < (int) canvas->rows; y++)
5990 {
cristyc57f6942010-11-12 01:47:39 +00005991 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,canvas->columns,1,
cristy6710d842011-10-20 23:23:00 +00005992 exception);
cristy4c08aed2011-07-01 19:47:50 +00005993 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00005994 break;
cristy3ed852e2009-09-05 21:47:34 +00005995 bit=0;
5996 byte=0;
5997 for (x=0; x < (int) canvas->columns; x++)
5998 {
5999 byte>>=1;
cristy4c08aed2011-07-01 19:47:50 +00006000 if (GetPixelIndex(canvas,p) == (Quantum) polarity)
cristy3ed852e2009-09-05 21:47:34 +00006001 byte|=foreground;
6002 else
6003 byte|=background;
6004 bit++;
6005 if (bit == 8)
6006 {
6007 *q++=byte;
6008 bit=0;
6009 byte=0;
6010 }
cristyed231572011-07-14 02:18:59 +00006011 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00006012 }
6013 if (bit != 0)
6014 *q=byte >> (8-bit);
6015 q+=scanline_pad;
6016 }
6017 }
6018 else
6019 if (window->pixel_info->colors != 0)
6020 switch (ximage->bits_per_pixel)
6021 {
6022 case 2:
6023 {
6024 register unsigned int
6025 nibble;
6026
6027 /*
6028 Convert to 2 bit color-mapped X canvas.
6029 */
6030 for (y=0; y < (int) canvas->rows; y++)
6031 {
cristyc57f6942010-11-12 01:47:39 +00006032 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
cristy6710d842011-10-20 23:23:00 +00006033 canvas->columns,1,exception);
cristy4c08aed2011-07-01 19:47:50 +00006034 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00006035 break;
cristy3ed852e2009-09-05 21:47:34 +00006036 nibble=0;
6037 for (x=0; x < (int) canvas->columns; x++)
6038 {
cristy4c08aed2011-07-01 19:47:50 +00006039 pixel=pixels[(ssize_t) GetPixelIndex(canvas,p)] & 0x0f;
cristy3ed852e2009-09-05 21:47:34 +00006040 switch (nibble)
6041 {
6042 case 0:
6043 {
6044 *q=(unsigned char) pixel;
6045 nibble++;
6046 break;
6047 }
6048 case 1:
6049 {
6050 *q|=(unsigned char) (pixel << 2);
6051 nibble++;
6052 break;
6053 }
6054 case 2:
6055 {
6056 *q|=(unsigned char) (pixel << 4);
6057 nibble++;
6058 break;
6059 }
6060 case 3:
6061 {
6062 *q|=(unsigned char) (pixel << 6);
6063 q++;
6064 nibble=0;
6065 break;
6066 }
6067 }
cristyed231572011-07-14 02:18:59 +00006068 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00006069 }
6070 q+=scanline_pad;
6071 }
6072 break;
6073 }
6074 case 4:
6075 {
6076 register unsigned int
6077 nibble;
6078
6079 /*
6080 Convert to 4 bit color-mapped X canvas.
6081 */
6082 for (y=0; y < (int) canvas->rows; y++)
6083 {
cristyc57f6942010-11-12 01:47:39 +00006084 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
cristy6710d842011-10-20 23:23:00 +00006085 canvas->columns,1,exception);
cristy4c08aed2011-07-01 19:47:50 +00006086 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00006087 break;
cristy3ed852e2009-09-05 21:47:34 +00006088 nibble=0;
6089 for (x=0; x < (int) canvas->columns; x++)
6090 {
cristy4c08aed2011-07-01 19:47:50 +00006091 pixel=pixels[(ssize_t) GetPixelIndex(canvas,p)] & 0xf;
cristy3ed852e2009-09-05 21:47:34 +00006092 switch (nibble)
6093 {
6094 case 0:
6095 {
6096 *q=(unsigned char) pixel;
6097 nibble++;
6098 break;
6099 }
6100 case 1:
6101 {
6102 *q|=(unsigned char) (pixel << 4);
6103 q++;
6104 nibble=0;
6105 break;
6106 }
6107 }
cristyed231572011-07-14 02:18:59 +00006108 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00006109 }
6110 q+=scanline_pad;
6111 }
6112 break;
6113 }
6114 case 6:
6115 case 8:
6116 {
6117 /*
6118 Convert to 8 bit color-mapped X canvas.
6119 */
6120 if (resource_info->color_recovery &&
6121 resource_info->quantize_info->dither)
6122 {
cristy6710d842011-10-20 23:23:00 +00006123 XDitherImage(canvas,ximage,exception);
cristy3ed852e2009-09-05 21:47:34 +00006124 break;
6125 }
6126 for (y=0; y < (int) canvas->rows; y++)
6127 {
cristyc57f6942010-11-12 01:47:39 +00006128 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
cristy6710d842011-10-20 23:23:00 +00006129 canvas->columns,1,exception);
cristy4c08aed2011-07-01 19:47:50 +00006130 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00006131 break;
cristy3ed852e2009-09-05 21:47:34 +00006132 for (x=0; x < (int) canvas->columns; x++)
6133 {
cristy4c08aed2011-07-01 19:47:50 +00006134 pixel=pixels[(ssize_t) GetPixelIndex(canvas,p)];
cristy3ed852e2009-09-05 21:47:34 +00006135 *q++=(unsigned char) pixel;
cristyed231572011-07-14 02:18:59 +00006136 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00006137 }
6138 q+=scanline_pad;
6139 }
6140 break;
6141 }
6142 default:
6143 {
6144 register int
6145 k;
6146
6147 register unsigned int
6148 bytes_per_pixel;
6149
6150 unsigned char
cristybb503372010-05-27 20:51:26 +00006151 channel[sizeof(size_t)];
cristy3ed852e2009-09-05 21:47:34 +00006152
6153 /*
6154 Convert to multi-byte color-mapped X canvas.
6155 */
6156 bytes_per_pixel=(unsigned int) (ximage->bits_per_pixel >> 3);
6157 for (y=0; y < (int) canvas->rows; y++)
6158 {
cristyc57f6942010-11-12 01:47:39 +00006159 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
cristy6710d842011-10-20 23:23:00 +00006160 canvas->columns,1,exception);
cristy4c08aed2011-07-01 19:47:50 +00006161 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00006162 break;
cristy3ed852e2009-09-05 21:47:34 +00006163 for (x=0; x < (int) canvas->columns; x++)
6164 {
cristy4c08aed2011-07-01 19:47:50 +00006165 pixel=pixels[(ssize_t) GetPixelIndex(canvas,p)];
cristy3ed852e2009-09-05 21:47:34 +00006166 for (k=0; k < (int) bytes_per_pixel; k++)
6167 {
6168 channel[k]=(unsigned char) pixel;
6169 pixel>>=8;
6170 }
6171 for (k=0; k < (int) bytes_per_pixel; k++)
6172 *q++=channel[k];
cristyed231572011-07-14 02:18:59 +00006173 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00006174 }
6175 q+=scanline_pad;
6176 }
6177 break;
6178 }
6179 }
6180 else
6181 switch (ximage->bits_per_pixel)
6182 {
6183 case 2:
6184 {
6185 register unsigned int
6186 nibble;
6187
6188 /*
6189 Convert to contiguous 2 bit continuous-tone X canvas.
6190 */
6191 for (y=0; y < (int) canvas->rows; y++)
6192 {
6193 nibble=0;
cristyc57f6942010-11-12 01:47:39 +00006194 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
cristy6710d842011-10-20 23:23:00 +00006195 canvas->columns,1,exception);
cristy4c08aed2011-07-01 19:47:50 +00006196 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00006197 break;
6198 for (x=0; x < (int) canvas->columns; x++)
6199 {
cristy4c08aed2011-07-01 19:47:50 +00006200 pixel=XGammaPixel(canvas,map_info,p);
cristy3ed852e2009-09-05 21:47:34 +00006201 pixel&=0xf;
6202 switch (nibble)
6203 {
6204 case 0:
6205 {
6206 *q=(unsigned char) pixel;
6207 nibble++;
6208 break;
6209 }
6210 case 1:
6211 {
6212 *q|=(unsigned char) (pixel << 2);
6213 nibble++;
6214 break;
6215 }
6216 case 2:
6217 {
6218 *q|=(unsigned char) (pixel << 4);
6219 nibble++;
6220 break;
6221 }
6222 case 3:
6223 {
6224 *q|=(unsigned char) (pixel << 6);
6225 q++;
6226 nibble=0;
6227 break;
6228 }
6229 }
cristyed231572011-07-14 02:18:59 +00006230 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00006231 }
6232 q+=scanline_pad;
6233 }
6234 break;
6235 }
6236 case 4:
6237 {
6238 register unsigned int
6239 nibble;
6240
6241 /*
6242 Convert to contiguous 4 bit continuous-tone X canvas.
6243 */
6244 for (y=0; y < (int) canvas->rows; y++)
6245 {
cristyc57f6942010-11-12 01:47:39 +00006246 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
cristy6710d842011-10-20 23:23:00 +00006247 canvas->columns,1,exception);
cristy4c08aed2011-07-01 19:47:50 +00006248 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00006249 break;
6250 nibble=0;
6251 for (x=0; x < (int) canvas->columns; x++)
6252 {
cristy4c08aed2011-07-01 19:47:50 +00006253 pixel=XGammaPixel(canvas,map_info,p);
cristy3ed852e2009-09-05 21:47:34 +00006254 pixel&=0xf;
6255 switch (nibble)
6256 {
6257 case 0:
6258 {
6259 *q=(unsigned char) pixel;
6260 nibble++;
6261 break;
6262 }
6263 case 1:
6264 {
6265 *q|=(unsigned char) (pixel << 4);
6266 q++;
6267 nibble=0;
6268 break;
6269 }
6270 }
cristyed231572011-07-14 02:18:59 +00006271 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00006272 }
6273 q+=scanline_pad;
6274 }
6275 break;
6276 }
6277 case 6:
6278 case 8:
6279 {
6280 /*
6281 Convert to contiguous 8 bit continuous-tone X canvas.
6282 */
6283 if (resource_info->color_recovery &&
6284 resource_info->quantize_info->dither)
6285 {
cristy6710d842011-10-20 23:23:00 +00006286 XDitherImage(canvas,ximage,exception);
cristy3ed852e2009-09-05 21:47:34 +00006287 break;
6288 }
6289 for (y=0; y < (int) canvas->rows; y++)
6290 {
cristyc57f6942010-11-12 01:47:39 +00006291 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
cristy6710d842011-10-20 23:23:00 +00006292 canvas->columns,1,exception);
cristy4c08aed2011-07-01 19:47:50 +00006293 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00006294 break;
6295 for (x=0; x < (int) canvas->columns; x++)
6296 {
cristy4c08aed2011-07-01 19:47:50 +00006297 pixel=XGammaPixel(canvas,map_info,p);
cristy3ed852e2009-09-05 21:47:34 +00006298 *q++=(unsigned char) pixel;
cristyed231572011-07-14 02:18:59 +00006299 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00006300 }
6301 q+=scanline_pad;
6302 }
6303 break;
6304 }
6305 default:
6306 {
6307 if ((ximage->bits_per_pixel == 32) && (map_info->red_max == 255) &&
6308 (map_info->green_max == 255) && (map_info->blue_max == 255) &&
6309 (map_info->red_mult == 65536L) && (map_info->green_mult == 256) &&
6310 (map_info->blue_mult == 1))
6311 {
6312 /*
6313 Convert to 32 bit continuous-tone X canvas.
6314 */
6315 for (y=0; y < (int) canvas->rows; y++)
6316 {
cristyc57f6942010-11-12 01:47:39 +00006317 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
cristy6710d842011-10-20 23:23:00 +00006318 canvas->columns,1,exception);
cristy4c08aed2011-07-01 19:47:50 +00006319 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00006320 break;
6321 if ((red_gamma != 1.0) || (green_gamma != 1.0) ||
6322 (blue_gamma != 1.0))
6323 {
6324 /*
6325 Gamma correct canvas.
6326 */
6327 for (x=(int) canvas->columns-1; x >= 0; x--)
6328 {
cristyccf844f2010-02-03 23:28:16 +00006329 *q++=ScaleQuantumToChar(XBlueGamma(
cristy4c08aed2011-07-01 19:47:50 +00006330 GetPixelBlue(canvas,p)));
cristyccf844f2010-02-03 23:28:16 +00006331 *q++=ScaleQuantumToChar(XGreenGamma(
cristy4c08aed2011-07-01 19:47:50 +00006332 GetPixelGreen(canvas,p)));
cristyccf844f2010-02-03 23:28:16 +00006333 *q++=ScaleQuantumToChar(XRedGamma(
cristy4c08aed2011-07-01 19:47:50 +00006334 GetPixelRed(canvas,p)));
cristy3ed852e2009-09-05 21:47:34 +00006335 *q++=0;
cristyed231572011-07-14 02:18:59 +00006336 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00006337 }
6338 continue;
6339 }
6340 for (x=(int) canvas->columns-1; x >= 0; x--)
6341 {
cristy4c08aed2011-07-01 19:47:50 +00006342 *q++=ScaleQuantumToChar((Quantum)
6343 GetPixelBlue(canvas,p));
6344 *q++=ScaleQuantumToChar((Quantum)
6345 GetPixelGreen(canvas,p));
6346 *q++=ScaleQuantumToChar((Quantum)
6347 GetPixelRed(canvas,p));
cristy3ed852e2009-09-05 21:47:34 +00006348 *q++=0;
cristyed231572011-07-14 02:18:59 +00006349 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00006350 }
6351 }
6352 }
6353 else
6354 if ((ximage->bits_per_pixel == 32) && (map_info->red_max == 255) &&
6355 (map_info->green_max == 255) && (map_info->blue_max == 255) &&
6356 (map_info->red_mult == 1) && (map_info->green_mult == 256) &&
6357 (map_info->blue_mult == 65536L))
6358 {
6359 /*
6360 Convert to 32 bit continuous-tone X canvas.
6361 */
6362 for (y=0; y < (int) canvas->rows; y++)
6363 {
cristyc57f6942010-11-12 01:47:39 +00006364 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
cristy6710d842011-10-20 23:23:00 +00006365 canvas->columns,1,exception);
cristy4c08aed2011-07-01 19:47:50 +00006366 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00006367 break;
6368 if ((red_gamma != 1.0) || (green_gamma != 1.0) ||
6369 (blue_gamma != 1.0))
6370 {
6371 /*
6372 Gamma correct canvas.
6373 */
6374 for (x=(int) canvas->columns-1; x >= 0; x--)
6375 {
cristyccf844f2010-02-03 23:28:16 +00006376 *q++=ScaleQuantumToChar(XRedGamma(
cristy4c08aed2011-07-01 19:47:50 +00006377 GetPixelRed(canvas,p)));
cristyccf844f2010-02-03 23:28:16 +00006378 *q++=ScaleQuantumToChar(XGreenGamma(
cristy4c08aed2011-07-01 19:47:50 +00006379 GetPixelGreen(canvas,p)));
cristyccf844f2010-02-03 23:28:16 +00006380 *q++=ScaleQuantumToChar(XBlueGamma(
cristy4c08aed2011-07-01 19:47:50 +00006381 GetPixelBlue(canvas,p)));
cristy3ed852e2009-09-05 21:47:34 +00006382 *q++=0;
cristyed231572011-07-14 02:18:59 +00006383 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00006384 }
6385 continue;
6386 }
6387 for (x=(int) canvas->columns-1; x >= 0; x--)
6388 {
cristyccf844f2010-02-03 23:28:16 +00006389 *q++=ScaleQuantumToChar((Quantum)
cristy4c08aed2011-07-01 19:47:50 +00006390 GetPixelRed(canvas,p));
cristyccf844f2010-02-03 23:28:16 +00006391 *q++=ScaleQuantumToChar((Quantum)
cristy4c08aed2011-07-01 19:47:50 +00006392 GetPixelGreen(canvas,p));
cristyccf844f2010-02-03 23:28:16 +00006393 *q++=ScaleQuantumToChar((Quantum)
cristy4c08aed2011-07-01 19:47:50 +00006394 GetPixelBlue(canvas,p));
cristy3ed852e2009-09-05 21:47:34 +00006395 *q++=0;
cristyed231572011-07-14 02:18:59 +00006396 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00006397 }
6398 }
6399 }
6400 else
6401 {
6402 register int
6403 k;
6404
6405 register unsigned int
6406 bytes_per_pixel;
6407
6408 unsigned char
cristybb503372010-05-27 20:51:26 +00006409 channel[sizeof(size_t)];
cristy3ed852e2009-09-05 21:47:34 +00006410
6411 /*
6412 Convert to multi-byte continuous-tone X canvas.
6413 */
6414 bytes_per_pixel=(unsigned int) (ximage->bits_per_pixel >> 3);
6415 for (y=0; y < (int) canvas->rows; y++)
6416 {
cristyc57f6942010-11-12 01:47:39 +00006417 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
cristy6710d842011-10-20 23:23:00 +00006418 canvas->columns,1,exception);
cristy4c08aed2011-07-01 19:47:50 +00006419 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00006420 break;
cristyc57f6942010-11-12 01:47:39 +00006421 for (x=0; x < (int) canvas->columns; x++)
cristy3ed852e2009-09-05 21:47:34 +00006422 {
cristy4c08aed2011-07-01 19:47:50 +00006423 pixel=XGammaPixel(canvas,map_info,p);
cristy3ed852e2009-09-05 21:47:34 +00006424 for (k=0; k < (int) bytes_per_pixel; k++)
6425 {
6426 channel[k]=(unsigned char) pixel;
6427 pixel>>=8;
6428 }
6429 for (k=0; k < (int) bytes_per_pixel; k++)
6430 *q++=channel[k];
cristyed231572011-07-14 02:18:59 +00006431 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00006432 }
6433 q+=scanline_pad;
6434 }
6435 }
6436 break;
6437 }
6438 }
6439 if (matte_image != (XImage *) NULL)
6440 {
6441 /*
6442 Initialize matte canvas.
6443 */
6444 scanline_pad=(unsigned int) (matte_image->bytes_per_line-
6445 ((matte_image->width*matte_image->bits_per_pixel) >> 3));
6446 q=(unsigned char *) matte_image->data;
6447 for (y=0; y < (int) canvas->rows; y++)
6448 {
cristyc57f6942010-11-12 01:47:39 +00006449 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,canvas->columns,1,
cristy6710d842011-10-20 23:23:00 +00006450 exception);
cristy4c08aed2011-07-01 19:47:50 +00006451 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00006452 break;
6453 bit=0;
6454 byte=0;
6455 for (x=(int) canvas->columns-1; x >= 0; x--)
6456 {
6457 byte>>=1;
cristy4c08aed2011-07-01 19:47:50 +00006458 if (GetPixelAlpha(canvas,p) > (QuantumRange/2))
cristy3ed852e2009-09-05 21:47:34 +00006459 byte|=0x80;
6460 bit++;
6461 if (bit == 8)
6462 {
6463 *q++=byte;
6464 bit=0;
6465 byte=0;
6466 }
cristyed231572011-07-14 02:18:59 +00006467 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00006468 }
6469 if (bit != 0)
6470 *q=byte >> (8-bit);
6471 q+=scanline_pad;
6472 }
6473 }
cristyc57f6942010-11-12 01:47:39 +00006474 canvas_view=DestroyCacheView(canvas_view);
cristy3ed852e2009-09-05 21:47:34 +00006475 if (canvas != image)
6476 canvas=DestroyImage(canvas);
6477}
6478
6479/*
6480%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
6481% %
6482% %
6483% %
6484+ X M a k e I m a g e M S B F i r s t %
6485% %
6486% %
6487% %
6488%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
6489%
6490% XMakeImageMSBFirst() initializes the pixel data of an X11 Image. The X
6491% image pixels are copied in most-significant bit and byte first order. The
6492% server's scanline pad is also respected. Rather than using one or two
6493% general cases, many special cases are found here to help speed up the image
6494% conversion.
6495%
6496% The format of the XMakeImageMSBFirst method is:
6497%
cristye941a752011-10-15 01:52:48 +00006498% XMakeImageMSBFirst(resource_info,window,image,ximage,matte_image,
6499% ExceptionInfo *exception)
cristy3ed852e2009-09-05 21:47:34 +00006500%
6501% A description of each parameter follows:
6502%
6503% o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
6504%
6505% o window: Specifies a pointer to a XWindowInfo structure.
6506%
6507% o image: the image.
6508%
6509% o ximage: Specifies a pointer to a XImage structure; returned from
6510% XCreateImage.
6511%
6512% o matte_image: Specifies a pointer to a XImage structure; returned from
6513% XCreateImage.
6514%
cristye941a752011-10-15 01:52:48 +00006515% o exception: return any errors or warnings in this structure.
6516%
cristy3ed852e2009-09-05 21:47:34 +00006517*/
6518static void XMakeImageMSBFirst(const XResourceInfo *resource_info,
cristye941a752011-10-15 01:52:48 +00006519 const XWindowInfo *window,Image *image,XImage *ximage,XImage *matte_image,
6520 ExceptionInfo *exception)
cristy3ed852e2009-09-05 21:47:34 +00006521{
cristyc57f6942010-11-12 01:47:39 +00006522 CacheView
6523 *canvas_view;
6524
cristy3ed852e2009-09-05 21:47:34 +00006525 Image
6526 *canvas;
6527
6528 int
6529 y;
6530
6531 register int
6532 x;
6533
cristy4c08aed2011-07-01 19:47:50 +00006534 register const Quantum
cristy3ed852e2009-09-05 21:47:34 +00006535 *p;
6536
6537 register unsigned char
6538 *q;
6539
6540 unsigned char
6541 bit,
6542 byte;
6543
6544 unsigned int
6545 scanline_pad;
6546
cristyf2faecf2010-05-28 19:19:36 +00006547 unsigned long
cristy3ed852e2009-09-05 21:47:34 +00006548 pixel,
6549 *pixels;
6550
6551 XStandardColormap
6552 *map_info;
6553
6554 assert(resource_info != (XResourceInfo *) NULL);
6555 assert(window != (XWindowInfo *) NULL);
6556 assert(image != (Image *) NULL);
6557 if (image->debug != MagickFalse)
6558 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
6559 canvas=image;
cristy54666e82010-02-03 23:34:26 +00006560 if ((window->immutable != MagickFalse) &&
6561 (image->storage_class == DirectClass) && (image->matte != MagickFalse))
cristy3ed852e2009-09-05 21:47:34 +00006562 {
6563 char
6564 size[MaxTextExtent];
6565
6566 Image
6567 *pattern;
6568
6569 ImageInfo
6570 *image_info;
6571
6572 image_info=AcquireImageInfo();
6573 (void) CopyMagickString(image_info->filename,
6574 resource_info->image_info->texture != (char *) NULL ?
6575 resource_info->image_info->texture : "pattern:checkerboard",
6576 MaxTextExtent);
cristyb51dff52011-05-19 16:55:47 +00006577 (void) FormatLocaleString(size,MaxTextExtent,"%.20gx%.20g",(double)
cristye8c25f92010-06-03 00:53:06 +00006578 image->columns,(double) image->rows);
cristy3ed852e2009-09-05 21:47:34 +00006579 image_info->size=ConstantString(size);
cristy6710d842011-10-20 23:23:00 +00006580 pattern=ReadImage(image_info,exception);
cristy3ed852e2009-09-05 21:47:34 +00006581 image_info=DestroyImageInfo(image_info);
6582 if (pattern != (Image *) NULL)
6583 {
cristy6710d842011-10-20 23:23:00 +00006584 canvas=CloneImage(image,0,0,MagickTrue,exception);
cristy3ed852e2009-09-05 21:47:34 +00006585 if (canvas != (Image *) NULL)
cristye941a752011-10-15 01:52:48 +00006586 (void) CompositeImage(canvas,DstOverCompositeOp,pattern,0,0,
6587 exception);
cristy3ed852e2009-09-05 21:47:34 +00006588 pattern=DestroyImage(pattern);
6589 }
6590 }
cristy4c08aed2011-07-01 19:47:50 +00006591 scanline_pad=(unsigned int) (ximage->bytes_per_line-((ximage->width*
6592 ximage->bits_per_pixel) >> 3));
cristy3ed852e2009-09-05 21:47:34 +00006593 map_info=window->map_info;
6594 pixels=window->pixel_info->pixels;
6595 q=(unsigned char *) ximage->data;
6596 x=0;
cristyc57f6942010-11-12 01:47:39 +00006597 canvas_view=AcquireCacheView(canvas);
cristy3ed852e2009-09-05 21:47:34 +00006598 if (ximage->format == XYBitmap)
6599 {
6600 register unsigned short
6601 polarity;
6602
6603 unsigned char
6604 background,
6605 foreground;
6606
6607 /*
6608 Convert canvas to big-endian bitmap.
6609 */
6610 background=(unsigned char)
6611 (XPixelIntensity(&window->pixel_info->foreground_color) <
6612 XPixelIntensity(&window->pixel_info->background_color) ? 0x01 : 0x00);
6613 foreground=(unsigned char)
6614 (XPixelIntensity(&window->pixel_info->background_color) <
6615 XPixelIntensity(&window->pixel_info->foreground_color) ? 0x01 : 0x00);
cristy101ab702011-10-13 13:06:32 +00006616 polarity=(unsigned short) ((GetPixelInfoIntensity(
cristy3ed852e2009-09-05 21:47:34 +00006617 &canvas->colormap[0])) < ((Quantum) QuantumRange/2) ? 1 : 0);
6618 if (canvas->colors == 2)
cristy101ab702011-10-13 13:06:32 +00006619 polarity=GetPixelInfoIntensity(&canvas->colormap[0]) <
6620 GetPixelInfoIntensity(&canvas->colormap[1]);
cristy3ed852e2009-09-05 21:47:34 +00006621 for (y=0; y < (int) canvas->rows; y++)
6622 {
cristyc57f6942010-11-12 01:47:39 +00006623 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,canvas->columns,1,
cristy6710d842011-10-20 23:23:00 +00006624 exception);
cristy4c08aed2011-07-01 19:47:50 +00006625 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00006626 break;
cristy3ed852e2009-09-05 21:47:34 +00006627 bit=0;
6628 byte=0;
6629 for (x=(int) canvas->columns-1; x >= 0; x--)
6630 {
6631 byte<<=1;
cristy4c08aed2011-07-01 19:47:50 +00006632 if (GetPixelIndex(canvas,p) == (Quantum) polarity)
cristy3ed852e2009-09-05 21:47:34 +00006633 byte|=foreground;
6634 else
6635 byte|=background;
6636 bit++;
6637 if (bit == 8)
6638 {
6639 *q++=byte;
6640 bit=0;
6641 byte=0;
6642 }
cristyed231572011-07-14 02:18:59 +00006643 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00006644 }
6645 if (bit != 0)
6646 *q=byte << (8-bit);
6647 q+=scanline_pad;
6648 }
6649 }
6650 else
6651 if (window->pixel_info->colors != 0)
6652 switch (ximage->bits_per_pixel)
6653 {
6654 case 2:
6655 {
6656 register unsigned int
6657 nibble;
6658
6659 /*
6660 Convert to 2 bit color-mapped X canvas.
6661 */
6662 for (y=0; y < (int) canvas->rows; y++)
6663 {
cristyc57f6942010-11-12 01:47:39 +00006664 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
cristy6710d842011-10-20 23:23:00 +00006665 canvas->columns,1,exception);
cristy4c08aed2011-07-01 19:47:50 +00006666 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00006667 break;
cristy3ed852e2009-09-05 21:47:34 +00006668 nibble=0;
6669 for (x=0; x < (int) canvas->columns; x++)
6670 {
cristy4c08aed2011-07-01 19:47:50 +00006671 pixel=pixels[(ssize_t)
6672 GetPixelIndex(canvas,p)] & 0xf;
cristy3ed852e2009-09-05 21:47:34 +00006673 switch (nibble)
6674 {
6675 case 0:
6676 {
6677 *q=(unsigned char) (pixel << 6);
6678 nibble++;
6679 break;
6680 }
6681 case 1:
6682 {
6683 *q|=(unsigned char) (pixel << 4);
6684 nibble++;
6685 break;
6686 }
6687 case 2:
6688 {
6689 *q|=(unsigned char) (pixel << 2);
6690 nibble++;
6691 break;
6692 }
6693 case 3:
6694 {
6695 *q|=(unsigned char) pixel;
6696 q++;
6697 nibble=0;
6698 break;
6699 }
6700 }
cristyed231572011-07-14 02:18:59 +00006701 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00006702 }
6703 q+=scanline_pad;
6704 }
6705 break;
6706 }
6707 case 4:
6708 {
6709 register unsigned int
6710 nibble;
6711
6712 /*
6713 Convert to 4 bit color-mapped X canvas.
6714 */
6715 for (y=0; y < (int) canvas->rows; y++)
6716 {
cristyc57f6942010-11-12 01:47:39 +00006717 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
cristy6710d842011-10-20 23:23:00 +00006718 canvas->columns,1,exception);
cristy4c08aed2011-07-01 19:47:50 +00006719 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00006720 break;
cristy3ed852e2009-09-05 21:47:34 +00006721 nibble=0;
6722 for (x=0; x < (int) canvas->columns; x++)
6723 {
cristy4c08aed2011-07-01 19:47:50 +00006724 pixel=pixels[(ssize_t)
6725 GetPixelIndex(canvas,p)] & 0xf;
cristy3ed852e2009-09-05 21:47:34 +00006726 switch (nibble)
6727 {
6728 case 0:
6729 {
6730 *q=(unsigned char) (pixel << 4);
6731 nibble++;
6732 break;
6733 }
6734 case 1:
6735 {
6736 *q|=(unsigned char) pixel;
6737 q++;
6738 nibble=0;
6739 break;
6740 }
6741 }
cristyed231572011-07-14 02:18:59 +00006742 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00006743 }
6744 q+=scanline_pad;
6745 }
6746 break;
6747 }
6748 case 6:
6749 case 8:
6750 {
6751 /*
6752 Convert to 8 bit color-mapped X canvas.
6753 */
6754 if (resource_info->color_recovery &&
6755 resource_info->quantize_info->dither)
6756 {
cristy6710d842011-10-20 23:23:00 +00006757 XDitherImage(canvas,ximage,exception);
cristy3ed852e2009-09-05 21:47:34 +00006758 break;
6759 }
6760 for (y=0; y < (int) canvas->rows; y++)
6761 {
cristyc57f6942010-11-12 01:47:39 +00006762 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
cristy6710d842011-10-20 23:23:00 +00006763 canvas->columns,1,exception);
cristy4c08aed2011-07-01 19:47:50 +00006764 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00006765 break;
cristy3ed852e2009-09-05 21:47:34 +00006766 for (x=0; x < (int) canvas->columns; x++)
6767 {
cristy6710d842011-10-20 23:23:00 +00006768 pixel=pixels[(ssize_t) GetPixelIndex(canvas,p)];
cristy3ed852e2009-09-05 21:47:34 +00006769 *q++=(unsigned char) pixel;
cristyed231572011-07-14 02:18:59 +00006770 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00006771 }
6772 q+=scanline_pad;
6773 }
6774 break;
6775 }
6776 default:
6777 {
6778 register int
6779 k;
6780
6781 register unsigned int
6782 bytes_per_pixel;
6783
6784 unsigned char
cristybb503372010-05-27 20:51:26 +00006785 channel[sizeof(size_t)];
cristy3ed852e2009-09-05 21:47:34 +00006786
6787 /*
6788 Convert to 8 bit color-mapped X canvas.
6789 */
6790 bytes_per_pixel=(unsigned int) (ximage->bits_per_pixel >> 3);
6791 for (y=0; y < (int) canvas->rows; y++)
6792 {
cristyc57f6942010-11-12 01:47:39 +00006793 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
cristy6710d842011-10-20 23:23:00 +00006794 canvas->columns,1,exception);
cristy4c08aed2011-07-01 19:47:50 +00006795 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00006796 break;
cristy3ed852e2009-09-05 21:47:34 +00006797 for (x=0; x < (int) canvas->columns; x++)
6798 {
cristy4c08aed2011-07-01 19:47:50 +00006799 pixel=pixels[(ssize_t)
6800 GetPixelIndex(canvas,p)];
cristy3ed852e2009-09-05 21:47:34 +00006801 for (k=(int) bytes_per_pixel-1; k >= 0; k--)
6802 {
6803 channel[k]=(unsigned char) pixel;
6804 pixel>>=8;
6805 }
6806 for (k=0; k < (int) bytes_per_pixel; k++)
6807 *q++=channel[k];
cristyed231572011-07-14 02:18:59 +00006808 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00006809 }
6810 q+=scanline_pad;
6811 }
6812 break;
6813 }
6814 }
6815 else
6816 switch (ximage->bits_per_pixel)
6817 {
6818 case 2:
6819 {
6820 register unsigned int
6821 nibble;
6822
6823 /*
6824 Convert to 4 bit continuous-tone X canvas.
6825 */
6826 for (y=0; y < (int) canvas->rows; y++)
6827 {
cristyc57f6942010-11-12 01:47:39 +00006828 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
cristy6710d842011-10-20 23:23:00 +00006829 canvas->columns,1,exception);
cristy4c08aed2011-07-01 19:47:50 +00006830 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00006831 break;
6832 nibble=0;
6833 for (x=(int) canvas->columns-1; x >= 0; x--)
6834 {
cristy4c08aed2011-07-01 19:47:50 +00006835 pixel=XGammaPixel(canvas,map_info,p);
cristy3ed852e2009-09-05 21:47:34 +00006836 pixel&=0xf;
6837 switch (nibble)
6838 {
6839 case 0:
6840 {
6841 *q=(unsigned char) (pixel << 6);
6842 nibble++;
6843 break;
6844 }
6845 case 1:
6846 {
6847 *q|=(unsigned char) (pixel << 4);
6848 nibble++;
6849 break;
6850 }
6851 case 2:
6852 {
6853 *q|=(unsigned char) (pixel << 2);
6854 nibble++;
6855 break;
6856 }
6857 case 3:
6858 {
6859 *q|=(unsigned char) pixel;
6860 q++;
6861 nibble=0;
6862 break;
6863 }
6864 }
cristyed231572011-07-14 02:18:59 +00006865 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00006866 }
6867 q+=scanline_pad;
6868 }
6869 break;
6870 }
6871 case 4:
6872 {
6873 register unsigned int
6874 nibble;
6875
6876 /*
6877 Convert to 4 bit continuous-tone X canvas.
6878 */
6879 for (y=0; y < (int) canvas->rows; y++)
6880 {
cristyc57f6942010-11-12 01:47:39 +00006881 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
cristy6710d842011-10-20 23:23:00 +00006882 canvas->columns,1,exception);
cristy4c08aed2011-07-01 19:47:50 +00006883 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00006884 break;
6885 nibble=0;
6886 for (x=(int) canvas->columns-1; x >= 0; x--)
6887 {
cristy4c08aed2011-07-01 19:47:50 +00006888 pixel=XGammaPixel(canvas,map_info,p);
cristy3ed852e2009-09-05 21:47:34 +00006889 pixel&=0xf;
6890 switch (nibble)
6891 {
6892 case 0:
6893 {
6894 *q=(unsigned char) (pixel << 4);
6895 nibble++;
6896 break;
6897 }
6898 case 1:
6899 {
6900 *q|=(unsigned char) pixel;
6901 q++;
6902 nibble=0;
6903 break;
6904 }
6905 }
cristyed231572011-07-14 02:18:59 +00006906 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00006907 }
6908 q+=scanline_pad;
6909 }
6910 break;
6911 }
6912 case 6:
6913 case 8:
6914 {
6915 /*
6916 Convert to 8 bit continuous-tone X canvas.
6917 */
6918 if (resource_info->color_recovery &&
6919 resource_info->quantize_info->dither)
6920 {
cristy6710d842011-10-20 23:23:00 +00006921 XDitherImage(canvas,ximage,exception);
cristy3ed852e2009-09-05 21:47:34 +00006922 break;
6923 }
6924 for (y=0; y < (int) canvas->rows; y++)
6925 {
cristyc57f6942010-11-12 01:47:39 +00006926 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
cristy6710d842011-10-20 23:23:00 +00006927 canvas->columns,1,exception);
cristy4c08aed2011-07-01 19:47:50 +00006928 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00006929 break;
6930 for (x=(int) canvas->columns-1; x >= 0; x--)
6931 {
cristy4c08aed2011-07-01 19:47:50 +00006932 pixel=XGammaPixel(canvas,map_info,p);
cristy3ed852e2009-09-05 21:47:34 +00006933 *q++=(unsigned char) pixel;
cristyed231572011-07-14 02:18:59 +00006934 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00006935 }
6936 q+=scanline_pad;
6937 }
6938 break;
6939 }
6940 default:
6941 {
6942 if ((ximage->bits_per_pixel == 32) && (map_info->red_max == 255) &&
6943 (map_info->green_max == 255) && (map_info->blue_max == 255) &&
6944 (map_info->red_mult == 65536L) && (map_info->green_mult == 256) &&
6945 (map_info->blue_mult == 1))
6946 {
6947 /*
6948 Convert to 32 bit continuous-tone X canvas.
6949 */
6950 for (y=0; y < (int) canvas->rows; y++)
6951 {
cristyc57f6942010-11-12 01:47:39 +00006952 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
cristy6710d842011-10-20 23:23:00 +00006953 canvas->columns,1,exception);
cristy4c08aed2011-07-01 19:47:50 +00006954 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00006955 break;
6956 if ((red_gamma != 1.0) || (green_gamma != 1.0) ||
6957 (blue_gamma != 1.0))
6958 {
6959 /*
6960 Gamma correct canvas.
6961 */
6962 for (x=(int) canvas->columns-1; x >= 0; x--)
6963 {
6964 *q++=0;
cristyccf844f2010-02-03 23:28:16 +00006965 *q++=ScaleQuantumToChar(XRedGamma(
cristy4c08aed2011-07-01 19:47:50 +00006966 GetPixelRed(canvas,p)));
cristyccf844f2010-02-03 23:28:16 +00006967 *q++=ScaleQuantumToChar(XGreenGamma(
cristy4c08aed2011-07-01 19:47:50 +00006968 GetPixelGreen(canvas,p)));
cristyccf844f2010-02-03 23:28:16 +00006969 *q++=ScaleQuantumToChar(XBlueGamma(
cristy4c08aed2011-07-01 19:47:50 +00006970 GetPixelBlue(canvas,p)));
cristyed231572011-07-14 02:18:59 +00006971 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00006972 }
6973 continue;
6974 }
6975 for (x=(int) canvas->columns-1; x >= 0; x--)
6976 {
6977 *q++=0;
cristy4c08aed2011-07-01 19:47:50 +00006978 *q++=ScaleQuantumToChar((Quantum)
6979 GetPixelRed(canvas,p));
6980 *q++=ScaleQuantumToChar((Quantum)
6981 GetPixelGreen(canvas,p));
6982 *q++=ScaleQuantumToChar((Quantum)
6983 GetPixelBlue(canvas,p));
cristyed231572011-07-14 02:18:59 +00006984 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00006985 }
6986 }
6987 }
6988 else
6989 if ((ximage->bits_per_pixel == 32) && (map_info->red_max == 255) &&
6990 (map_info->green_max == 255) && (map_info->blue_max == 255) &&
6991 (map_info->red_mult == 1) && (map_info->green_mult == 256) &&
6992 (map_info->blue_mult == 65536L))
6993 {
6994 /*
6995 Convert to 32 bit continuous-tone X canvas.
6996 */
6997 for (y=0; y < (int) canvas->rows; y++)
6998 {
cristyc57f6942010-11-12 01:47:39 +00006999 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
cristy6710d842011-10-20 23:23:00 +00007000 canvas->columns,1,exception);
cristy4c08aed2011-07-01 19:47:50 +00007001 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00007002 break;
7003 if ((red_gamma != 1.0) || (green_gamma != 1.0) ||
7004 (blue_gamma != 1.0))
7005 {
7006 /*
7007 Gamma correct canvas.
7008 */
7009 for (x=(int) canvas->columns-1; x >= 0; x--)
7010 {
7011 *q++=0;
cristyccf844f2010-02-03 23:28:16 +00007012 *q++=ScaleQuantumToChar(XBlueGamma(
cristy4c08aed2011-07-01 19:47:50 +00007013 GetPixelBlue(canvas,p)));
cristyccf844f2010-02-03 23:28:16 +00007014 *q++=ScaleQuantumToChar(XGreenGamma(
cristy4c08aed2011-07-01 19:47:50 +00007015 GetPixelGreen(canvas,p)));
cristyccf844f2010-02-03 23:28:16 +00007016 *q++=ScaleQuantumToChar(XRedGamma(
cristy4c08aed2011-07-01 19:47:50 +00007017 GetPixelRed(canvas,p)));
cristyed231572011-07-14 02:18:59 +00007018 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00007019 }
7020 continue;
7021 }
7022 for (x=(int) canvas->columns-1; x >= 0; x--)
7023 {
7024 *q++=0;
cristyccf844f2010-02-03 23:28:16 +00007025 *q++=ScaleQuantumToChar((Quantum)
cristy4c08aed2011-07-01 19:47:50 +00007026 GetPixelBlue(canvas,p));
cristyccf844f2010-02-03 23:28:16 +00007027 *q++=ScaleQuantumToChar((Quantum)
cristy4c08aed2011-07-01 19:47:50 +00007028 GetPixelGreen(canvas,p));
cristyccf844f2010-02-03 23:28:16 +00007029 *q++=ScaleQuantumToChar((Quantum)
cristy4c08aed2011-07-01 19:47:50 +00007030 GetPixelRed(canvas,p));
cristyed231572011-07-14 02:18:59 +00007031 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00007032 }
7033 }
7034 }
7035 else
7036 {
7037 register int
7038 k;
7039
7040 register unsigned int
7041 bytes_per_pixel;
7042
7043 unsigned char
cristybb503372010-05-27 20:51:26 +00007044 channel[sizeof(size_t)];
cristy3ed852e2009-09-05 21:47:34 +00007045
7046 /*
7047 Convert to multi-byte continuous-tone X canvas.
7048 */
7049 bytes_per_pixel=(unsigned int) (ximage->bits_per_pixel >> 3);
7050 for (y=0; y < (int) canvas->rows; y++)
7051 {
cristyc57f6942010-11-12 01:47:39 +00007052 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
cristy6710d842011-10-20 23:23:00 +00007053 canvas->columns,1,exception);
cristy4c08aed2011-07-01 19:47:50 +00007054 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00007055 break;
7056 for (x=(int) canvas->columns-1; x >= 0; x--)
7057 {
cristy4c08aed2011-07-01 19:47:50 +00007058 pixel=XGammaPixel(canvas,map_info,p);
cristy3ed852e2009-09-05 21:47:34 +00007059 for (k=(int) bytes_per_pixel-1; k >= 0; k--)
7060 {
7061 channel[k]=(unsigned char) pixel;
7062 pixel>>=8;
7063 }
7064 for (k=0; k < (int) bytes_per_pixel; k++)
7065 *q++=channel[k];
cristyed231572011-07-14 02:18:59 +00007066 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00007067 }
7068 q+=scanline_pad;
7069 }
7070 }
7071 break;
7072 }
7073 }
7074 if (matte_image != (XImage *) NULL)
7075 {
7076 /*
7077 Initialize matte canvas.
7078 */
7079 scanline_pad=(unsigned int) (matte_image->bytes_per_line-
7080 ((matte_image->width*matte_image->bits_per_pixel) >> 3));
7081 q=(unsigned char *) matte_image->data;
7082 for (y=0; y < (int) canvas->rows; y++)
7083 {
cristyc57f6942010-11-12 01:47:39 +00007084 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,canvas->columns,1,
cristy6710d842011-10-20 23:23:00 +00007085 exception);
cristy4c08aed2011-07-01 19:47:50 +00007086 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00007087 break;
7088 bit=0;
7089 byte=0;
7090 for (x=(int) canvas->columns-1; x >= 0; x--)
7091 {
7092 byte<<=1;
cristy4c08aed2011-07-01 19:47:50 +00007093 if (GetPixelAlpha(canvas,p) > (QuantumRange/2))
cristy3ed852e2009-09-05 21:47:34 +00007094 byte|=0x01;
7095 bit++;
7096 if (bit == 8)
7097 {
7098 *q++=byte;
7099 bit=0;
7100 byte=0;
7101 }
cristyed231572011-07-14 02:18:59 +00007102 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00007103 }
7104 if (bit != 0)
7105 *q=byte << (8-bit);
7106 q+=scanline_pad;
7107 }
7108 }
cristyc57f6942010-11-12 01:47:39 +00007109 canvas_view=DestroyCacheView(canvas_view);
cristy3ed852e2009-09-05 21:47:34 +00007110 if (canvas != image)
7111 canvas=DestroyImage(canvas);
7112}
7113
7114/*
7115%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
7116% %
7117% %
7118% %
7119% X M a k e M a g n i f y I m a g e %
7120% %
7121% %
7122% %
7123%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
7124%
7125% XMakeMagnifyImage() magnifies a region of an X image and displays it.
7126%
7127% The format of the XMakeMagnifyImage method is:
7128%
cristy6710d842011-10-20 23:23:00 +00007129% void XMakeMagnifyImage(Display *display,XWindows *windows,
7130% ExceptionInfo *exception)
cristy3ed852e2009-09-05 21:47:34 +00007131%
7132% A description of each parameter follows:
7133%
7134% o display: Specifies a connection to an X server; returned from
7135% XOpenDisplay.
7136%
7137% o windows: Specifies a pointer to a XWindows structure.
7138%
cristy6710d842011-10-20 23:23:00 +00007139% o exception: return any errors or warnings in this structure.
7140%
cristy3ed852e2009-09-05 21:47:34 +00007141*/
cristy6710d842011-10-20 23:23:00 +00007142MagickPrivate void XMakeMagnifyImage(Display *display,XWindows *windows,
7143 ExceptionInfo *exception)
cristy3ed852e2009-09-05 21:47:34 +00007144{
7145 char
7146 tuple[MaxTextExtent];
7147
7148 int
7149 y;
7150
cristy4c08aed2011-07-01 19:47:50 +00007151 PixelInfo
cristy3ed852e2009-09-05 21:47:34 +00007152 pixel;
7153
7154 register int
7155 x;
7156
cristybb503372010-05-27 20:51:26 +00007157 register ssize_t
cristy3ed852e2009-09-05 21:47:34 +00007158 i;
7159
7160 register unsigned char
7161 *p,
7162 *q;
7163
cristy9d314ff2011-03-09 01:30:28 +00007164 ssize_t
7165 n;
7166
cristy3ed852e2009-09-05 21:47:34 +00007167 static unsigned int
7168 previous_magnify = 0;
7169
7170 static XWindowInfo
7171 magnify_window;
7172
7173 unsigned int
7174 height,
7175 j,
7176 k,
7177 l,
7178 magnify,
7179 scanline_pad,
7180 width;
7181
7182 XImage
7183 *ximage;
7184
7185 /*
7186 Check boundary conditions.
7187 */
7188 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
7189 assert(display != (Display *) NULL);
7190 assert(windows != (XWindows *) NULL);
7191 magnify=1;
cristybb503372010-05-27 20:51:26 +00007192 for (n=1; n < (ssize_t) windows->magnify.data; n++)
cristy3ed852e2009-09-05 21:47:34 +00007193 magnify<<=1;
7194 while ((magnify*windows->image.ximage->width) < windows->magnify.width)
7195 magnify<<=1;
7196 while ((magnify*windows->image.ximage->height) < windows->magnify.height)
7197 magnify<<=1;
7198 while (magnify > windows->magnify.width)
7199 magnify>>=1;
7200 while (magnify > windows->magnify.height)
7201 magnify>>=1;
7202 if (magnify != previous_magnify)
7203 {
7204 Status
7205 status;
7206
7207 XTextProperty
7208 window_name;
7209
7210 /*
7211 New magnify factor: update magnify window name.
7212 */
7213 i=0;
7214 while ((1 << i) <= (int) magnify)
7215 i++;
cristyb51dff52011-05-19 16:55:47 +00007216 (void) FormatLocaleString(windows->magnify.name,MaxTextExtent,
cristye8c25f92010-06-03 00:53:06 +00007217 "Magnify %.20gX",(double) i);
cristy3ed852e2009-09-05 21:47:34 +00007218 status=XStringListToTextProperty(&windows->magnify.name,1,&window_name);
7219 if (status != False)
7220 {
7221 XSetWMName(display,windows->magnify.id,&window_name);
7222 XSetWMIconName(display,windows->magnify.id,&window_name);
7223 (void) XFree((void *) window_name.value);
7224 }
7225 }
7226 previous_magnify=magnify;
7227 ximage=windows->image.ximage;
7228 width=(unsigned int) windows->magnify.ximage->width;
7229 height=(unsigned int) windows->magnify.ximage->height;
7230 if ((windows->magnify.x < 0) ||
7231 (windows->magnify.x >= windows->image.ximage->width))
7232 windows->magnify.x=windows->image.ximage->width >> 1;
7233 x=windows->magnify.x-((width/magnify) >> 1);
7234 if (x < 0)
7235 x=0;
7236 else
7237 if (x > (int) (ximage->width-(width/magnify)))
7238 x=ximage->width-width/magnify;
7239 if ((windows->magnify.y < 0) ||
7240 (windows->magnify.y >= windows->image.ximage->height))
7241 windows->magnify.y=windows->image.ximage->height >> 1;
7242 y=windows->magnify.y-((height/magnify) >> 1);
7243 if (y < 0)
7244 y=0;
7245 else
7246 if (y > (int) (ximage->height-(height/magnify)))
7247 y=ximage->height-height/magnify;
7248 q=(unsigned char *) windows->magnify.ximage->data;
7249 scanline_pad=(unsigned int) (windows->magnify.ximage->bytes_per_line-
7250 ((width*windows->magnify.ximage->bits_per_pixel) >> 3));
7251 if (ximage->bits_per_pixel < 8)
7252 {
7253 register unsigned char
7254 background,
7255 byte,
7256 foreground,
7257 p_bit,
7258 q_bit;
7259
7260 register unsigned int
7261 plane;
7262
7263 XPixelInfo
7264 *pixel_info;
7265
7266 pixel_info=windows->magnify.pixel_info;
7267 switch (ximage->bitmap_bit_order)
7268 {
7269 case LSBFirst:
7270 {
7271 /*
7272 Magnify little-endian bitmap.
7273 */
7274 background=0x00;
7275 foreground=0x80;
7276 if (ximage->format == XYBitmap)
7277 {
7278 background=(unsigned char)
7279 (XPixelIntensity(&pixel_info->foreground_color) <
7280 XPixelIntensity(&pixel_info->background_color) ? 0x80 : 0x00);
7281 foreground=(unsigned char)
7282 (XPixelIntensity(&pixel_info->background_color) <
7283 XPixelIntensity(&pixel_info->foreground_color) ? 0x80 : 0x00);
7284 if (windows->magnify.depth > 1)
7285 Swap(background,foreground);
7286 }
cristybb503372010-05-27 20:51:26 +00007287 for (i=0; i < (ssize_t) height; i+=magnify)
cristy3ed852e2009-09-05 21:47:34 +00007288 {
7289 /*
7290 Propogate pixel magnify rows.
7291 */
7292 for (j=0; j < magnify; j++)
7293 {
7294 p=(unsigned char *) ximage->data+y*ximage->bytes_per_line+
7295 ((x*ximage->bits_per_pixel) >> 3);
7296 p_bit=(unsigned char) (x*ximage->bits_per_pixel) & 0x07;
7297 q_bit=0;
7298 byte=0;
7299 for (k=0; k < width; k+=magnify)
7300 {
7301 /*
7302 Propogate pixel magnify columns.
7303 */
7304 for (l=0; l < magnify; l++)
7305 {
7306 /*
7307 Propogate each bit plane.
7308 */
7309 for (plane=0; (int) plane < ximage->bits_per_pixel; plane++)
7310 {
7311 byte>>=1;
7312 if (*p & (0x01 << (p_bit+plane)))
7313 byte|=foreground;
7314 else
7315 byte|=background;
7316 q_bit++;
7317 if (q_bit == 8)
7318 {
7319 *q++=byte;
7320 q_bit=0;
7321 byte=0;
7322 }
7323 }
7324 }
7325 p_bit+=ximage->bits_per_pixel;
7326 if (p_bit == 8)
7327 {
7328 p++;
7329 p_bit=0;
7330 }
7331 if (q_bit != 0)
7332 *q=byte >> (8-q_bit);
7333 q+=scanline_pad;
7334 }
7335 }
7336 y++;
7337 }
7338 break;
7339 }
7340 case MSBFirst:
7341 default:
7342 {
7343 /*
7344 Magnify big-endian bitmap.
7345 */
7346 background=0x00;
7347 foreground=0x01;
7348 if (ximage->format == XYBitmap)
7349 {
7350 background=(unsigned char)
7351 (XPixelIntensity(&pixel_info->foreground_color) <
7352 XPixelIntensity(&pixel_info->background_color) ? 0x01 : 0x00);
7353 foreground=(unsigned char)
7354 (XPixelIntensity(&pixel_info->background_color) <
7355 XPixelIntensity(&pixel_info->foreground_color) ? 0x01 : 0x00);
7356 if (windows->magnify.depth > 1)
7357 Swap(background,foreground);
7358 }
cristybb503372010-05-27 20:51:26 +00007359 for (i=0; i < (ssize_t) height; i+=magnify)
cristy3ed852e2009-09-05 21:47:34 +00007360 {
7361 /*
7362 Propogate pixel magnify rows.
7363 */
7364 for (j=0; j < magnify; j++)
7365 {
7366 p=(unsigned char *) ximage->data+y*ximage->bytes_per_line+
7367 ((x*ximage->bits_per_pixel) >> 3);
7368 p_bit=(unsigned char) (x*ximage->bits_per_pixel) & 0x07;
7369 q_bit=0;
7370 byte=0;
7371 for (k=0; k < width; k+=magnify)
7372 {
7373 /*
7374 Propogate pixel magnify columns.
7375 */
7376 for (l=0; l < magnify; l++)
7377 {
7378 /*
7379 Propogate each bit plane.
7380 */
7381 for (plane=0; (int) plane < ximage->bits_per_pixel; plane++)
7382 {
7383 byte<<=1;
7384 if (*p & (0x80 >> (p_bit+plane)))
7385 byte|=foreground;
7386 else
7387 byte|=background;
7388 q_bit++;
7389 if (q_bit == 8)
7390 {
7391 *q++=byte;
7392 q_bit=0;
7393 byte=0;
7394 }
7395 }
7396 }
7397 p_bit+=ximage->bits_per_pixel;
7398 if (p_bit == 8)
7399 {
7400 p++;
7401 p_bit=0;
7402 }
7403 if (q_bit != 0)
7404 *q=byte << (8-q_bit);
7405 q+=scanline_pad;
7406 }
7407 }
7408 y++;
7409 }
7410 break;
7411 }
7412 }
7413 }
7414 else
7415 switch (ximage->bits_per_pixel)
7416 {
7417 case 6:
7418 case 8:
7419 {
7420 /*
7421 Magnify 8 bit X image.
7422 */
cristybb503372010-05-27 20:51:26 +00007423 for (i=0; i < (ssize_t) height; i+=magnify)
cristy3ed852e2009-09-05 21:47:34 +00007424 {
7425 /*
7426 Propogate pixel magnify rows.
7427 */
7428 for (j=0; j < magnify; j++)
7429 {
7430 p=(unsigned char *) ximage->data+y*ximage->bytes_per_line+
7431 ((x*ximage->bits_per_pixel) >> 3);
7432 for (k=0; k < width; k+=magnify)
7433 {
7434 /*
7435 Propogate pixel magnify columns.
7436 */
7437 for (l=0; l < magnify; l++)
7438 *q++=(*p);
7439 p++;
7440 }
7441 q+=scanline_pad;
7442 }
7443 y++;
7444 }
7445 break;
7446 }
7447 default:
7448 {
7449 register unsigned int
7450 bytes_per_pixel,
7451 m;
7452
7453 /*
7454 Magnify multi-byte X image.
7455 */
7456 bytes_per_pixel=(unsigned int) ximage->bits_per_pixel >> 3;
cristybb503372010-05-27 20:51:26 +00007457 for (i=0; i < (ssize_t) height; i+=magnify)
cristy3ed852e2009-09-05 21:47:34 +00007458 {
7459 /*
7460 Propogate pixel magnify rows.
7461 */
7462 for (j=0; j < magnify; j++)
7463 {
7464 p=(unsigned char *) ximage->data+y*ximage->bytes_per_line+
7465 ((x*ximage->bits_per_pixel) >> 3);
7466 for (k=0; k < width; k+=magnify)
7467 {
7468 /*
7469 Propogate pixel magnify columns.
7470 */
7471 for (l=0; l < magnify; l++)
7472 for (m=0; m < bytes_per_pixel; m++)
7473 *q++=(*(p+m));
7474 p+=bytes_per_pixel;
7475 }
7476 q+=scanline_pad;
7477 }
7478 y++;
7479 }
7480 break;
7481 }
7482 }
7483 /*
7484 Copy X image to magnify pixmap.
7485 */
7486 x=windows->magnify.x-((width/magnify) >> 1);
7487 if (x < 0)
7488 x=(int) ((width >> 1)-windows->magnify.x*magnify);
7489 else
7490 if (x > (int) (ximage->width-(width/magnify)))
7491 x=(int) ((ximage->width-windows->magnify.x)*magnify-(width >> 1));
7492 else
7493 x=0;
7494 y=windows->magnify.y-((height/magnify) >> 1);
7495 if (y < 0)
7496 y=(int) ((height >> 1)-windows->magnify.y*magnify);
7497 else
7498 if (y > (int) (ximage->height-(height/magnify)))
7499 y=(int) ((ximage->height-windows->magnify.y)*magnify-(height >> 1));
7500 else
7501 y=0;
7502 if ((x != 0) || (y != 0))
7503 (void) XFillRectangle(display,windows->magnify.pixmap,
7504 windows->magnify.annotate_context,0,0,width,height);
7505 (void) XPutImage(display,windows->magnify.pixmap,
7506 windows->magnify.annotate_context,windows->magnify.ximage,0,0,x,y,width-x,
7507 height-y);
7508 if ((magnify > 1) && ((magnify <= (width >> 1)) &&
7509 (magnify <= (height >> 1))))
7510 {
7511 RectangleInfo
7512 highlight_info;
7513
7514 /*
7515 Highlight center pixel.
7516 */
cristybb503372010-05-27 20:51:26 +00007517 highlight_info.x=(ssize_t) windows->magnify.width >> 1;
7518 highlight_info.y=(ssize_t) windows->magnify.height >> 1;
cristy3ed852e2009-09-05 21:47:34 +00007519 highlight_info.width=magnify;
7520 highlight_info.height=magnify;
7521 (void) XDrawRectangle(display,windows->magnify.pixmap,
7522 windows->magnify.highlight_context,(int) highlight_info.x,
7523 (int) highlight_info.y,(unsigned int) highlight_info.width-1,
7524 (unsigned int) highlight_info.height-1);
7525 if (magnify > 2)
7526 (void) XDrawRectangle(display,windows->magnify.pixmap,
7527 windows->magnify.annotate_context,(int) highlight_info.x+1,
7528 (int) highlight_info.y+1,(unsigned int) highlight_info.width-3,
7529 (unsigned int) highlight_info.height-3);
7530 }
7531 /*
7532 Show center pixel color.
7533 */
cristy3aa93752011-12-18 15:54:24 +00007534 (void) GetOneVirtualPixelInfo(windows->image.image,TileVirtualPixelMethod,
cristy52010022011-10-21 18:07:37 +00007535 (ssize_t) windows->magnify.x,(ssize_t) windows->magnify.y,&pixel,exception);
cristyb51dff52011-05-19 16:55:47 +00007536 (void) FormatLocaleString(tuple,MaxTextExtent,"%d,%d: ",
cristy3ed852e2009-09-05 21:47:34 +00007537 windows->magnify.x,windows->magnify.y);
7538 (void) ConcatenateMagickString(tuple,"(",MaxTextExtent);
cristyed231572011-07-14 02:18:59 +00007539 ConcatenateColorComponent(&pixel,RedPixelChannel,X11Compliance,tuple);
cristy3ed852e2009-09-05 21:47:34 +00007540 (void) ConcatenateMagickString(tuple,",",MaxTextExtent);
cristyed231572011-07-14 02:18:59 +00007541 ConcatenateColorComponent(&pixel,GreenPixelChannel,X11Compliance,tuple);
cristy3ed852e2009-09-05 21:47:34 +00007542 (void) ConcatenateMagickString(tuple,",",MaxTextExtent);
cristyed231572011-07-14 02:18:59 +00007543 ConcatenateColorComponent(&pixel,BluePixelChannel,X11Compliance,tuple);
cristy3ed852e2009-09-05 21:47:34 +00007544 if (pixel.colorspace == CMYKColorspace)
7545 {
7546 (void) ConcatenateMagickString(tuple,",",MaxTextExtent);
cristyed231572011-07-14 02:18:59 +00007547 ConcatenateColorComponent(&pixel,BlackPixelChannel,X11Compliance,tuple);
cristy3ed852e2009-09-05 21:47:34 +00007548 }
7549 if (pixel.matte != MagickFalse)
7550 {
7551 (void) ConcatenateMagickString(tuple,",",MaxTextExtent);
cristyed231572011-07-14 02:18:59 +00007552 ConcatenateColorComponent(&pixel,AlphaPixelChannel,X11Compliance,tuple);
cristy3ed852e2009-09-05 21:47:34 +00007553 }
7554 (void) ConcatenateMagickString(tuple,")",MaxTextExtent);
7555 height=(unsigned int) windows->magnify.font_info->ascent+
7556 windows->magnify.font_info->descent;
7557 x=windows->magnify.font_info->max_bounds.width >> 1;
7558 y=windows->magnify.font_info->ascent+(height >> 2);
7559 (void) XDrawImageString(display,windows->magnify.pixmap,
7560 windows->magnify.annotate_context,x,y,tuple,(int) strlen(tuple));
7561 GetColorTuple(&pixel,MagickTrue,tuple);
7562 y+=height;
7563 (void) XDrawImageString(display,windows->magnify.pixmap,
7564 windows->magnify.annotate_context,x,y,tuple,(int) strlen(tuple));
cristy269c9412011-10-13 23:41:15 +00007565 (void) QueryColorname(windows->image.image,&pixel,SVGCompliance,tuple,
cristy6710d842011-10-20 23:23:00 +00007566 exception);
cristy3ed852e2009-09-05 21:47:34 +00007567 y+=height;
7568 (void) XDrawImageString(display,windows->magnify.pixmap,
7569 windows->magnify.annotate_context,x,y,tuple,(int) strlen(tuple));
7570 /*
7571 Refresh magnify window.
7572 */
7573 magnify_window=windows->magnify;
7574 magnify_window.x=0;
7575 magnify_window.y=0;
7576 XRefreshWindow(display,&magnify_window,(XEvent *) NULL);
7577}
7578
7579/*
7580%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
7581% %
7582% %
7583% %
7584% X M a k e P i x m a p %
7585% %
7586% %
7587% %
7588%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
7589%
7590% XMakePixmap() creates an X11 pixmap.
7591%
7592% The format of the XMakePixmap method is:
7593%
7594% void XMakeStandardColormap(Display *display,XVisualInfo *visual_info,
7595% XResourceInfo *resource_info,Image *image,XStandardColormap *map_info,
7596% XPixelInfo *pixel)
7597%
7598% A description of each parameter follows:
7599%
7600% o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
7601%
7602% o display: Specifies a connection to an X server; returned from
7603% XOpenDisplay.
7604%
7605% o window: Specifies a pointer to a XWindowInfo structure.
7606%
cristy3ed852e2009-09-05 21:47:34 +00007607*/
7608static MagickBooleanType XMakePixmap(Display *display,
7609 const XResourceInfo *resource_info,XWindowInfo *window)
7610{
7611 unsigned int
7612 height,
7613 width;
7614
7615 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
7616 assert(display != (Display *) NULL);
7617 assert(resource_info != (XResourceInfo *) NULL);
7618 assert(window != (XWindowInfo *) NULL);
7619 if (window->pixmap != (Pixmap) NULL)
7620 {
7621 /*
7622 Destroy previous X pixmap.
7623 */
7624 (void) XFreePixmap(display,window->pixmap);
7625 window->pixmap=(Pixmap) NULL;
7626 }
7627 if (window->use_pixmap == MagickFalse)
7628 return(MagickFalse);
7629 if (window->ximage == (XImage *) NULL)
7630 return(MagickFalse);
7631 /*
7632 Display busy cursor.
7633 */
7634 (void) XCheckDefineCursor(display,window->id,window->busy_cursor);
7635 (void) XFlush(display);
7636 /*
7637 Create pixmap.
7638 */
7639 width=(unsigned int) window->ximage->width;
7640 height=(unsigned int) window->ximage->height;
7641 window->pixmap=XCreatePixmap(display,window->id,width,height,window->depth);
7642 if (window->pixmap == (Pixmap) NULL)
7643 {
7644 /*
7645 Unable to allocate pixmap.
7646 */
7647 (void) XCheckDefineCursor(display,window->id,window->cursor);
7648 return(MagickFalse);
7649 }
7650 /*
7651 Copy X image to pixmap.
7652 */
7653#if defined(MAGICKCORE_HAVE_SHARED_MEMORY)
7654 if (window->shared_memory)
7655 (void) XShmPutImage(display,window->pixmap,window->annotate_context,
7656 window->ximage,0,0,0,0,width,height,MagickTrue);
7657#endif
7658 if (window->shared_memory == MagickFalse)
7659 (void) XPutImage(display,window->pixmap,window->annotate_context,
7660 window->ximage,0,0,0,0,width,height);
7661 if (IsEventLogging())
7662 {
7663 (void) LogMagickEvent(X11Event,GetMagickModule(),"Pixmap:");
7664 (void) LogMagickEvent(X11Event,GetMagickModule()," width, height: %ux%u",
7665 width,height);
7666 }
7667 /*
7668 Restore cursor.
7669 */
7670 (void) XCheckDefineCursor(display,window->id,window->cursor);
7671 return(MagickTrue);
7672}
7673
7674/*
7675%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
7676% %
7677% %
7678% %
7679% X M a k e S t a n d a r d C o l o r m a p %
7680% %
7681% %
7682% %
7683%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
7684%
7685% XMakeStandardColormap() creates an X11 Standard Colormap.
7686%
7687% The format of the XMakeStandardColormap method is:
7688%
cristy6710d842011-10-20 23:23:00 +00007689% void XMakeStandardColormap(Display *display,XVisualInfo *visual_info,
7690% XResourceInfo *resource_info,Image *image,XStandardColormap *map_info,
7691% XPixelInfo *pixel,ExceptionInfo *exception)
cristy3ed852e2009-09-05 21:47:34 +00007692%
7693% A description of each parameter follows:
7694%
7695% o display: Specifies a connection to an X server; returned from
7696% XOpenDisplay.
7697%
7698% o visual_info: Specifies a pointer to a X11 XVisualInfo structure;
7699% returned from XGetVisualInfo.
7700%
7701% o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
7702%
7703% o image: the image.
7704%
7705% o map_info: If a Standard Colormap type is specified, this structure is
7706% initialized with info from the Standard Colormap.
7707%
7708% o pixel: Specifies a pointer to a XPixelInfo structure.
7709%
cristy6710d842011-10-20 23:23:00 +00007710% o exception: return any errors or warnings in this structure.
7711%
cristy3ed852e2009-09-05 21:47:34 +00007712*/
7713
7714#if defined(__cplusplus) || defined(c_plusplus)
7715extern "C" {
7716#endif
7717
7718static inline MagickRealType DiversityPixelIntensity(
7719 const DiversityPacket *pixel)
7720{
7721 MagickRealType
7722 intensity;
7723
7724 intensity=0.299*pixel->red+0.587*pixel->green+0.114*pixel->blue;
7725 return(intensity);
7726}
7727
7728static int IntensityCompare(const void *x,const void *y)
7729{
7730 DiversityPacket
7731 *color_1,
7732 *color_2;
7733
7734 int
7735 diversity;
7736
7737 color_1=(DiversityPacket *) x;
7738 color_2=(DiversityPacket *) y;
7739 diversity=(int) (DiversityPixelIntensity(color_2)-
7740 DiversityPixelIntensity(color_1));
7741 return(diversity);
7742}
7743
7744static int PopularityCompare(const void *x,const void *y)
7745{
7746 DiversityPacket
7747 *color_1,
7748 *color_2;
7749
7750 color_1=(DiversityPacket *) x;
7751 color_2=(DiversityPacket *) y;
7752 return((int) color_2->count-(int) color_1->count);
7753}
7754
7755#if defined(__cplusplus) || defined(c_plusplus)
7756}
7757#endif
7758
cristybb503372010-05-27 20:51:26 +00007759static inline Quantum ScaleXToQuantum(const size_t x,
7760 const size_t scale)
cristy3ed852e2009-09-05 21:47:34 +00007761{
7762 return((Quantum) (((MagickRealType) QuantumRange*x)/scale+0.5));
7763}
7764
cristybcbda3f2011-09-03 13:01:22 +00007765MagickPrivate void XMakeStandardColormap(Display *display,
cristy3ed852e2009-09-05 21:47:34 +00007766 XVisualInfo *visual_info,XResourceInfo *resource_info,Image *image,
cristy6710d842011-10-20 23:23:00 +00007767 XStandardColormap *map_info,XPixelInfo *pixel,ExceptionInfo *exception)
cristy3ed852e2009-09-05 21:47:34 +00007768{
7769 Colormap
7770 colormap;
7771
cristybb503372010-05-27 20:51:26 +00007772 register ssize_t
cristy3ed852e2009-09-05 21:47:34 +00007773 i;
7774
7775 Status
7776 status;
7777
cristybb503372010-05-27 20:51:26 +00007778 size_t
cristy3ed852e2009-09-05 21:47:34 +00007779 number_colors,
7780 retain_colors;
7781
7782 unsigned short
7783 gray_value;
7784
7785 XColor
7786 color,
7787 *colors,
7788 *p;
7789
7790 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
7791 assert(display != (Display *) NULL);
7792 assert(visual_info != (XVisualInfo *) NULL);
7793 assert(map_info != (XStandardColormap *) NULL);
7794 assert(resource_info != (XResourceInfo *) NULL);
7795 assert(pixel != (XPixelInfo *) NULL);
cristy3ed852e2009-09-05 21:47:34 +00007796 if (resource_info->map_type != (char *) NULL)
7797 {
7798 /*
7799 Standard Colormap is already defined (i.e. xstdcmap).
7800 */
cristy4c08aed2011-07-01 19:47:50 +00007801 XGetPixelInfo(display,visual_info,map_info,resource_info,image,
cristy3ed852e2009-09-05 21:47:34 +00007802 pixel);
7803 number_colors=(unsigned int) (map_info->base_pixel+
7804 (map_info->red_max+1)*(map_info->green_max+1)*(map_info->blue_max+1));
7805 if ((map_info->red_max*map_info->green_max*map_info->blue_max) != 0)
7806 if ((image->matte == MagickFalse) &&
7807 (resource_info->color_recovery == MagickFalse) &&
7808 resource_info->quantize_info->dither &&
7809 (number_colors < MaxColormapSize))
7810 {
7811 Image
7812 *affinity_image;
7813
cristy4c08aed2011-07-01 19:47:50 +00007814 register Quantum
cristyc47d1f82009-11-26 01:44:43 +00007815 *restrict q;
cristy3ed852e2009-09-05 21:47:34 +00007816
7817 /*
7818 Improve image appearance with error diffusion.
7819 */
cristy6710d842011-10-20 23:23:00 +00007820 affinity_image=AcquireImage((ImageInfo *) NULL,exception);
cristy3ed852e2009-09-05 21:47:34 +00007821 if (affinity_image == (Image *) NULL)
7822 ThrowXWindowFatalException(ResourceLimitFatalError,
7823 "UnableToDitherImage",image->filename);
7824 affinity_image->columns=number_colors;
7825 affinity_image->rows=1;
7826 /*
7827 Initialize colormap image.
7828 */
7829 q=QueueAuthenticPixels(affinity_image,0,0,affinity_image->columns,
7830 1,exception);
cristy4c08aed2011-07-01 19:47:50 +00007831 if (q != (Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00007832 {
cristybb503372010-05-27 20:51:26 +00007833 for (i=0; i < (ssize_t) number_colors; i++)
cristy3ed852e2009-09-05 21:47:34 +00007834 {
cristy4c08aed2011-07-01 19:47:50 +00007835 SetPixelRed(affinity_image,0,q);
cristy3ed852e2009-09-05 21:47:34 +00007836 if (map_info->red_max != 0)
cristy4c08aed2011-07-01 19:47:50 +00007837 SetPixelRed(affinity_image,
7838 ScaleXToQuantum((size_t) (i/map_info->red_mult),
7839 map_info->red_max),q);
7840 SetPixelGreen(affinity_image,0,q);
cristy3ed852e2009-09-05 21:47:34 +00007841 if (map_info->green_max != 0)
cristy4c08aed2011-07-01 19:47:50 +00007842 SetPixelGreen(affinity_image,
7843 ScaleXToQuantum((size_t) ((i/map_info->green_mult) %
7844 (map_info->green_max+1)),map_info->green_max),q);
7845 SetPixelBlue(affinity_image,0,q);
cristy3ed852e2009-09-05 21:47:34 +00007846 if (map_info->blue_max != 0)
cristy4c08aed2011-07-01 19:47:50 +00007847 SetPixelBlue(affinity_image,
7848 ScaleXToQuantum((size_t) (i % map_info->green_mult),
7849 map_info->blue_max),q);
7850 SetPixelAlpha(affinity_image,
7851 TransparentAlpha,q);
cristyed231572011-07-14 02:18:59 +00007852 q+=GetPixelChannels(affinity_image);
cristy3ed852e2009-09-05 21:47:34 +00007853 }
7854 (void) SyncAuthenticPixels(affinity_image,exception);
7855 (void) RemapImage(resource_info->quantize_info,image,
cristy018f07f2011-09-04 21:15:19 +00007856 affinity_image,exception);
cristy3ed852e2009-09-05 21:47:34 +00007857 }
cristy4c08aed2011-07-01 19:47:50 +00007858 XGetPixelInfo(display,visual_info,map_info,resource_info,image,
cristy3ed852e2009-09-05 21:47:34 +00007859 pixel);
cristy574cc262011-08-05 01:23:58 +00007860 (void) SetImageStorageClass(image,DirectClass,exception);
cristy3ed852e2009-09-05 21:47:34 +00007861 affinity_image=DestroyImage(affinity_image);
7862 }
7863 if (IsEventLogging())
7864 {
7865 (void) LogMagickEvent(X11Event,GetMagickModule(),
7866 "Standard Colormap:");
7867 (void) LogMagickEvent(X11Event,GetMagickModule(),
7868 " colormap id: 0x%lx",map_info->colormap);
7869 (void) LogMagickEvent(X11Event,GetMagickModule(),
7870 " red, green, blue max: %lu %lu %lu",map_info->red_max,
7871 map_info->green_max,map_info->blue_max);
7872 (void) LogMagickEvent(X11Event,GetMagickModule(),
7873 " red, green, blue mult: %lu %lu %lu",map_info->red_mult,
7874 map_info->green_mult,map_info->blue_mult);
7875 }
7876 return;
7877 }
7878 if ((visual_info->klass != DirectColor) &&
7879 (visual_info->klass != TrueColor))
7880 if ((image->storage_class == DirectClass) ||
7881 ((int) image->colors > visual_info->colormap_size))
7882 {
7883 QuantizeInfo
7884 quantize_info;
7885
7886 /*
7887 Image has more colors than the visual supports.
7888 */
7889 quantize_info=(*resource_info->quantize_info);
cristybb503372010-05-27 20:51:26 +00007890 quantize_info.number_colors=(size_t) visual_info->colormap_size;
cristy018f07f2011-09-04 21:15:19 +00007891 (void) QuantizeImage(&quantize_info,image,exception);
cristy3ed852e2009-09-05 21:47:34 +00007892 }
7893 /*
7894 Free previous and create new colormap.
7895 */
7896 (void) XFreeStandardColormap(display,visual_info,map_info,pixel);
7897 colormap=XDefaultColormap(display,visual_info->screen);
7898 if (visual_info->visual != XDefaultVisual(display,visual_info->screen))
7899 colormap=XCreateColormap(display,XRootWindow(display,visual_info->screen),
7900 visual_info->visual,visual_info->klass == DirectColor ?
7901 AllocAll : AllocNone);
7902 if (colormap == (Colormap) NULL)
7903 ThrowXWindowFatalException(ResourceLimitFatalError,"UnableToCreateColormap",
7904 image->filename);
7905 /*
7906 Initialize the map and pixel info structures.
7907 */
7908 XGetMapInfo(visual_info,colormap,map_info);
cristy4c08aed2011-07-01 19:47:50 +00007909 XGetPixelInfo(display,visual_info,map_info,resource_info,image,pixel);
cristy3ed852e2009-09-05 21:47:34 +00007910 /*
7911 Allocating colors in server colormap is based on visual class.
7912 */
7913 switch (visual_info->klass)
7914 {
7915 case StaticGray:
7916 case StaticColor:
7917 {
7918 /*
7919 Define Standard Colormap for StaticGray or StaticColor visual.
7920 */
7921 number_colors=image->colors;
7922 colors=(XColor *) AcquireQuantumMemory((size_t)
7923 visual_info->colormap_size,sizeof(*colors));
7924 if (colors == (XColor *) NULL)
7925 ThrowXWindowFatalException(ResourceLimitFatalError,
7926 "UnableToCreateColormap",image->filename);
7927 p=colors;
7928 color.flags=(char) (DoRed | DoGreen | DoBlue);
cristybb503372010-05-27 20:51:26 +00007929 for (i=0; i < (ssize_t) image->colors; i++)
cristy3ed852e2009-09-05 21:47:34 +00007930 {
7931 color.red=ScaleQuantumToShort(XRedGamma(image->colormap[i].red));
7932 color.green=ScaleQuantumToShort(XGreenGamma(image->colormap[i].green));
7933 color.blue=ScaleQuantumToShort(XBlueGamma(image->colormap[i].blue));
7934 if (visual_info->klass != StaticColor)
7935 {
7936 gray_value=(unsigned short) XPixelIntensity(&color);
7937 color.red=gray_value;
7938 color.green=gray_value;
7939 color.blue=gray_value;
7940 }
7941 status=XAllocColor(display,colormap,&color);
7942 if (status == False)
7943 {
7944 colormap=XCopyColormapAndFree(display,colormap);
7945 (void) XAllocColor(display,colormap,&color);
7946 }
7947 pixel->pixels[i]=color.pixel;
7948 *p++=color;
7949 }
7950 break;
7951 }
7952 case GrayScale:
7953 case PseudoColor:
7954 {
7955 unsigned int
7956 colormap_type;
7957
7958 /*
7959 Define Standard Colormap for GrayScale or PseudoColor visual.
7960 */
7961 number_colors=image->colors;
7962 colors=(XColor *) AcquireQuantumMemory((size_t)
7963 visual_info->colormap_size,sizeof(*colors));
7964 if (colors == (XColor *) NULL)
7965 ThrowXWindowFatalException(ResourceLimitFatalError,
7966 "UnableToCreateColormap",image->filename);
7967 /*
7968 Preallocate our GUI colors.
7969 */
7970 (void) XAllocColor(display,colormap,&pixel->foreground_color);
7971 (void) XAllocColor(display,colormap,&pixel->background_color);
7972 (void) XAllocColor(display,colormap,&pixel->border_color);
7973 (void) XAllocColor(display,colormap,&pixel->matte_color);
7974 (void) XAllocColor(display,colormap,&pixel->highlight_color);
7975 (void) XAllocColor(display,colormap,&pixel->shadow_color);
7976 (void) XAllocColor(display,colormap,&pixel->depth_color);
7977 (void) XAllocColor(display,colormap,&pixel->trough_color);
7978 for (i=0; i < MaxNumberPens; i++)
7979 (void) XAllocColor(display,colormap,&pixel->pen_colors[i]);
7980 /*
7981 Determine if image colors will "fit" into X server colormap.
7982 */
7983 colormap_type=resource_info->colormap;
cristyf2faecf2010-05-28 19:19:36 +00007984 status=XAllocColorCells(display,colormap,MagickFalse,(unsigned long *)
cristy3ed852e2009-09-05 21:47:34 +00007985 NULL,0,pixel->pixels,(unsigned int) image->colors);
7986 if (status != False)
7987 colormap_type=PrivateColormap;
7988 if (colormap_type == SharedColormap)
7989 {
cristyc57f6942010-11-12 01:47:39 +00007990 CacheView
7991 *image_view;
7992
cristy3ed852e2009-09-05 21:47:34 +00007993 DiversityPacket
7994 *diversity;
7995
7996 int
7997 y;
7998
7999 register int
8000 x;
8001
8002 unsigned short
8003 index;
8004
8005 XColor
8006 *server_colors;
8007
8008 /*
8009 Define Standard colormap for shared GrayScale or PseudoColor visual.
8010 */
8011 diversity=(DiversityPacket *) AcquireQuantumMemory(image->colors,
8012 sizeof(*diversity));
8013 if (diversity == (DiversityPacket *) NULL)
8014 ThrowXWindowFatalException(ResourceLimitFatalError,
8015 "UnableToCreateColormap",image->filename);
cristybb503372010-05-27 20:51:26 +00008016 for (i=0; i < (ssize_t) image->colors; i++)
cristy3ed852e2009-09-05 21:47:34 +00008017 {
cristye42f6582012-02-11 17:59:50 +00008018 diversity[i].red=ClampToQuantum(image->colormap[i].red);
8019 diversity[i].green=ClampToQuantum(image->colormap[i].green);
8020 diversity[i].blue=ClampToQuantum(image->colormap[i].blue);
cristy3ed852e2009-09-05 21:47:34 +00008021 diversity[i].index=(unsigned short) i;
8022 diversity[i].count=0;
8023 }
cristyc57f6942010-11-12 01:47:39 +00008024 image_view=AcquireCacheView(image);
cristy3ed852e2009-09-05 21:47:34 +00008025 for (y=0; y < (int) image->rows; y++)
8026 {
cristyc57f6942010-11-12 01:47:39 +00008027 register int
cristy3ed852e2009-09-05 21:47:34 +00008028 x;
8029
cristy4c08aed2011-07-01 19:47:50 +00008030 register const Quantum
cristyc57f6942010-11-12 01:47:39 +00008031 *restrict p;
cristy3ed852e2009-09-05 21:47:34 +00008032
cristyc57f6942010-11-12 01:47:39 +00008033 p=GetCacheViewAuthenticPixels(image_view,0,(ssize_t) y,
8034 image->columns,1,exception);
cristy4c08aed2011-07-01 19:47:50 +00008035 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00008036 break;
cristyc57f6942010-11-12 01:47:39 +00008037 for (x=(int) image->columns-1; x >= 0; x--)
cristy4c08aed2011-07-01 19:47:50 +00008038 {
8039 diversity[(ssize_t) GetPixelIndex(image,p)].count++;
cristyed231572011-07-14 02:18:59 +00008040 p+=GetPixelChannels(image);
cristy4c08aed2011-07-01 19:47:50 +00008041 }
cristy3ed852e2009-09-05 21:47:34 +00008042 }
cristyc57f6942010-11-12 01:47:39 +00008043 image_view=DestroyCacheView(image_view);
cristy3ed852e2009-09-05 21:47:34 +00008044 /*
8045 Sort colors by decreasing intensity.
8046 */
8047 qsort((void *) diversity,image->colors,sizeof(*diversity),
8048 IntensityCompare);
cristybb503372010-05-27 20:51:26 +00008049 for (i=0; i < (ssize_t) image->colors; )
cristy3ed852e2009-09-05 21:47:34 +00008050 {
8051 diversity[i].count<<=4; /* increase this colors popularity */
cristydfe2b662010-08-22 16:17:24 +00008052 i+=MagickMax((int) (image->colors >> 4),2);
cristy3ed852e2009-09-05 21:47:34 +00008053 }
8054 diversity[image->colors-1].count<<=4;
8055 qsort((void *) diversity,image->colors,sizeof(*diversity),
8056 PopularityCompare);
8057 /*
8058 Allocate colors.
8059 */
8060 p=colors;
8061 color.flags=(char) (DoRed | DoGreen | DoBlue);
cristybb503372010-05-27 20:51:26 +00008062 for (i=0; i < (ssize_t) image->colors; i++)
cristy3ed852e2009-09-05 21:47:34 +00008063 {
8064 index=diversity[i].index;
8065 color.red=
8066 ScaleQuantumToShort(XRedGamma(image->colormap[index].red));
8067 color.green=
8068 ScaleQuantumToShort(XGreenGamma(image->colormap[index].green));
8069 color.blue=
8070 ScaleQuantumToShort(XBlueGamma(image->colormap[index].blue));
8071 if (visual_info->klass != PseudoColor)
8072 {
8073 gray_value=(unsigned short) XPixelIntensity(&color);
8074 color.red=gray_value;
8075 color.green=gray_value;
8076 color.blue=gray_value;
8077 }
8078 status=XAllocColor(display,colormap,&color);
8079 if (status == False)
8080 break;
8081 pixel->pixels[index]=color.pixel;
8082 *p++=color;
8083 }
8084 /*
8085 Read X server colormap.
8086 */
8087 server_colors=(XColor *) AcquireQuantumMemory((size_t)
8088 visual_info->colormap_size,sizeof(*server_colors));
8089 if (server_colors == (XColor *) NULL)
8090 ThrowXWindowFatalException(ResourceLimitFatalError,
8091 "UnableToCreateColormap",image->filename);
8092 for (x=visual_info->colormap_size-1; x >= 0; x--)
cristybb503372010-05-27 20:51:26 +00008093 server_colors[x].pixel=(size_t) x;
cristy3ed852e2009-09-05 21:47:34 +00008094 (void) XQueryColors(display,colormap,server_colors,
8095 (int) MagickMin((unsigned int) visual_info->colormap_size,256));
8096 /*
8097 Select remaining colors from X server colormap.
8098 */
cristybb503372010-05-27 20:51:26 +00008099 for (; i < (ssize_t) image->colors; i++)
cristy3ed852e2009-09-05 21:47:34 +00008100 {
8101 index=diversity[i].index;
8102 color.red=
8103 ScaleQuantumToShort(XRedGamma(image->colormap[index].red));
8104 color.green=
8105 ScaleQuantumToShort(XGreenGamma(image->colormap[index].green));
8106 color.blue=
8107 ScaleQuantumToShort(XBlueGamma(image->colormap[index].blue));
8108 if (visual_info->klass != PseudoColor)
8109 {
8110 gray_value=(unsigned short) XPixelIntensity(&color);
8111 color.red=gray_value;
8112 color.green=gray_value;
8113 color.blue=gray_value;
8114 }
8115 XBestPixel(display,colormap,server_colors,(unsigned int)
8116 visual_info->colormap_size,&color);
8117 pixel->pixels[index]=color.pixel;
8118 *p++=color;
8119 }
8120 if ((int) image->colors < visual_info->colormap_size)
8121 {
8122 /*
8123 Fill up colors array-- more choices for pen colors.
8124 */
8125 retain_colors=MagickMin((unsigned int)
8126 (visual_info->colormap_size-image->colors),256);
cristybb503372010-05-27 20:51:26 +00008127 for (i=0; i < (ssize_t) retain_colors; i++)
cristy3ed852e2009-09-05 21:47:34 +00008128 *p++=server_colors[i];
8129 number_colors+=retain_colors;
8130 }
8131 server_colors=(XColor *) RelinquishMagickMemory(server_colors);
8132 diversity=(DiversityPacket *) RelinquishMagickMemory(diversity);
8133 break;
8134 }
8135 /*
8136 Define Standard colormap for private GrayScale or PseudoColor visual.
8137 */
8138 if (status == False)
8139 {
8140 /*
8141 Not enough colormap entries in the colormap-- Create a new colormap.
8142 */
8143 colormap=XCreateColormap(display,
8144 XRootWindow(display,visual_info->screen),visual_info->visual,
8145 AllocNone);
8146 if (colormap == (Colormap) NULL)
8147 ThrowXWindowFatalException(ResourceLimitFatalError,
8148 "UnableToCreateColormap",image->filename);
8149 map_info->colormap=colormap;
8150 if ((int) image->colors < visual_info->colormap_size)
8151 {
8152 /*
8153 Retain colors from the default colormap to help lessens the
8154 effects of colormap flashing.
8155 */
8156 retain_colors=MagickMin((unsigned int)
8157 (visual_info->colormap_size-image->colors),256);
8158 p=colors+image->colors;
cristybb503372010-05-27 20:51:26 +00008159 for (i=0; i < (ssize_t) retain_colors; i++)
cristy3ed852e2009-09-05 21:47:34 +00008160 {
cristyc57f6942010-11-12 01:47:39 +00008161 p->pixel=(unsigned long) i;
cristy3ed852e2009-09-05 21:47:34 +00008162 p++;
8163 }
8164 (void) XQueryColors(display,
8165 XDefaultColormap(display,visual_info->screen),
8166 colors+image->colors,(int) retain_colors);
8167 /*
8168 Transfer colors from default to private colormap.
8169 */
8170 (void) XAllocColorCells(display,colormap,MagickFalse,
cristyf2faecf2010-05-28 19:19:36 +00008171 (unsigned long *) NULL,0,pixel->pixels,(unsigned int)
cristy3ed852e2009-09-05 21:47:34 +00008172 retain_colors);
8173 p=colors+image->colors;
cristybb503372010-05-27 20:51:26 +00008174 for (i=0; i < (ssize_t) retain_colors; i++)
cristy3ed852e2009-09-05 21:47:34 +00008175 {
8176 p->pixel=pixel->pixels[i];
8177 p++;
8178 }
8179 (void) XStoreColors(display,colormap,colors+image->colors,
8180 (int) retain_colors);
8181 number_colors+=retain_colors;
8182 }
8183 (void) XAllocColorCells(display,colormap,MagickFalse,
cristyf2faecf2010-05-28 19:19:36 +00008184 (unsigned long *) NULL,0,pixel->pixels,(unsigned int)
cristy3ed852e2009-09-05 21:47:34 +00008185 image->colors);
8186 }
8187 /*
8188 Store the image colormap.
8189 */
8190 p=colors;
8191 color.flags=(char) (DoRed | DoGreen | DoBlue);
cristybb503372010-05-27 20:51:26 +00008192 for (i=0; i < (ssize_t) image->colors; i++)
cristy3ed852e2009-09-05 21:47:34 +00008193 {
8194 color.red=ScaleQuantumToShort(XRedGamma(image->colormap[i].red));
8195 color.green=ScaleQuantumToShort(XGreenGamma(image->colormap[i].green));
8196 color.blue=ScaleQuantumToShort(XBlueGamma(image->colormap[i].blue));
8197 if (visual_info->klass != PseudoColor)
8198 {
8199 gray_value=(unsigned short) XPixelIntensity(&color);
8200 color.red=gray_value;
8201 color.green=gray_value;
8202 color.blue=gray_value;
8203 }
8204 color.pixel=pixel->pixels[i];
8205 *p++=color;
8206 }
8207 (void) XStoreColors(display,colormap,colors,(int) image->colors);
8208 break;
8209 }
8210 case TrueColor:
8211 case DirectColor:
8212 default:
8213 {
8214 MagickBooleanType
8215 linear_colormap;
8216
8217 /*
8218 Define Standard Colormap for TrueColor or DirectColor visual.
8219 */
8220 number_colors=(unsigned int) ((map_info->red_max*map_info->red_mult)+
8221 (map_info->green_max*map_info->green_mult)+
8222 (map_info->blue_max*map_info->blue_mult)+1);
8223 linear_colormap=(number_colors > 4096) ||
8224 (((int) (map_info->red_max+1) == visual_info->colormap_size) &&
8225 ((int) (map_info->green_max+1) == visual_info->colormap_size) &&
8226 ((int) (map_info->blue_max+1) == visual_info->colormap_size)) ?
8227 MagickTrue : MagickFalse;
8228 if (linear_colormap != MagickFalse)
cristybb503372010-05-27 20:51:26 +00008229 number_colors=(size_t) visual_info->colormap_size;
cristy3ed852e2009-09-05 21:47:34 +00008230 /*
8231 Allocate color array.
8232 */
8233 colors=(XColor *) AcquireQuantumMemory(number_colors,sizeof(*colors));
8234 if (colors == (XColor *) NULL)
8235 ThrowXWindowFatalException(ResourceLimitFatalError,
8236 "UnableToCreateColormap",image->filename);
8237 /*
8238 Initialize linear color ramp.
8239 */
8240 p=colors;
8241 color.flags=(char) (DoRed | DoGreen | DoBlue);
8242 if (linear_colormap != MagickFalse)
cristybb503372010-05-27 20:51:26 +00008243 for (i=0; i < (ssize_t) number_colors; i++)
cristy3ed852e2009-09-05 21:47:34 +00008244 {
8245 color.blue=(unsigned short) 0;
8246 if (map_info->blue_max != 0)
cristybb503372010-05-27 20:51:26 +00008247 color.blue=(unsigned short) ((size_t)
cristy3ed852e2009-09-05 21:47:34 +00008248 ((65535L*(i % map_info->green_mult))/map_info->blue_max));
8249 color.green=color.blue;
8250 color.red=color.blue;
8251 color.pixel=XStandardPixel(map_info,&color);
8252 *p++=color;
8253 }
8254 else
cristybb503372010-05-27 20:51:26 +00008255 for (i=0; i < (ssize_t) number_colors; i++)
cristy3ed852e2009-09-05 21:47:34 +00008256 {
8257 color.red=(unsigned short) 0;
8258 if (map_info->red_max != 0)
cristybb503372010-05-27 20:51:26 +00008259 color.red=(unsigned short) ((size_t)
cristy3ed852e2009-09-05 21:47:34 +00008260 ((65535L*(i/map_info->red_mult))/map_info->red_max));
8261 color.green=(unsigned int) 0;
8262 if (map_info->green_max != 0)
cristybb503372010-05-27 20:51:26 +00008263 color.green=(unsigned short) ((size_t)
cristy3ed852e2009-09-05 21:47:34 +00008264 ((65535L*((i/map_info->green_mult) % (map_info->green_max+1)))/
8265 map_info->green_max));
8266 color.blue=(unsigned short) 0;
8267 if (map_info->blue_max != 0)
cristybb503372010-05-27 20:51:26 +00008268 color.blue=(unsigned short) ((size_t)
cristy3ed852e2009-09-05 21:47:34 +00008269 ((65535L*(i % map_info->green_mult))/map_info->blue_max));
8270 color.pixel=XStandardPixel(map_info,&color);
8271 *p++=color;
8272 }
8273 if ((visual_info->klass == DirectColor) &&
8274 (colormap != XDefaultColormap(display,visual_info->screen)))
8275 (void) XStoreColors(display,colormap,colors,(int) number_colors);
8276 else
cristybb503372010-05-27 20:51:26 +00008277 for (i=0; i < (ssize_t) number_colors; i++)
cristy3ed852e2009-09-05 21:47:34 +00008278 (void) XAllocColor(display,colormap,&colors[i]);
8279 break;
8280 }
8281 }
8282 if ((visual_info->klass != DirectColor) &&
8283 (visual_info->klass != TrueColor))
8284 {
8285 /*
8286 Set foreground, background, border, etc. pixels.
8287 */
8288 XBestPixel(display,colormap,colors,(unsigned int) number_colors,
8289 &pixel->foreground_color);
8290 XBestPixel(display,colormap,colors,(unsigned int) number_colors,
8291 &pixel->background_color);
8292 if (pixel->background_color.pixel == pixel->foreground_color.pixel)
8293 {
8294 /*
8295 Foreground and background colors must differ.
8296 */
8297 pixel->background_color.red=(~pixel->foreground_color.red);
8298 pixel->background_color.green=
8299 (~pixel->foreground_color.green);
8300 pixel->background_color.blue=
8301 (~pixel->foreground_color.blue);
8302 XBestPixel(display,colormap,colors,(unsigned int) number_colors,
8303 &pixel->background_color);
8304 }
8305 XBestPixel(display,colormap,colors,(unsigned int) number_colors,
8306 &pixel->border_color);
8307 XBestPixel(display,colormap,colors,(unsigned int) number_colors,
8308 &pixel->matte_color);
8309 XBestPixel(display,colormap,colors,(unsigned int) number_colors,
8310 &pixel->highlight_color);
8311 XBestPixel(display,colormap,colors,(unsigned int) number_colors,
8312 &pixel->shadow_color);
8313 XBestPixel(display,colormap,colors,(unsigned int) number_colors,
8314 &pixel->depth_color);
8315 XBestPixel(display,colormap,colors,(unsigned int) number_colors,
8316 &pixel->trough_color);
8317 for (i=0; i < MaxNumberPens; i++)
8318 {
8319 XBestPixel(display,colormap,colors,(unsigned int) number_colors,
8320 &pixel->pen_colors[i]);
8321 pixel->pixels[image->colors+i]=pixel->pen_colors[i].pixel;
8322 }
cristyc57f6942010-11-12 01:47:39 +00008323 pixel->colors=(ssize_t) (image->colors+MaxNumberPens);
cristy3ed852e2009-09-05 21:47:34 +00008324 }
8325 colors=(XColor *) RelinquishMagickMemory(colors);
8326 if (IsEventLogging())
8327 {
8328 (void) LogMagickEvent(X11Event,GetMagickModule(),"Standard Colormap:");
8329 (void) LogMagickEvent(X11Event,GetMagickModule()," colormap id: 0x%lx",
8330 map_info->colormap);
8331 (void) LogMagickEvent(X11Event,GetMagickModule(),
8332 " red, green, blue max: %lu %lu %lu",map_info->red_max,
8333 map_info->green_max,map_info->blue_max);
8334 (void) LogMagickEvent(X11Event,GetMagickModule(),
8335 " red, green, blue mult: %lu %lu %lu",map_info->red_mult,
8336 map_info->green_mult,map_info->blue_mult);
8337 }
8338}
8339
8340/*
8341%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8342% %
8343% %
8344% %
8345% X M a k e W i n d o w %
8346% %
8347% %
8348% %
8349%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8350%
8351% XMakeWindow() creates an X11 window.
8352%
8353% The format of the XMakeWindow method is:
8354%
8355% void XMakeWindow(Display *display,Window parent,char **argv,int argc,
8356% XClassHint *class_hint,XWMHints *manager_hints,
8357% XWindowInfo *window_info)
8358%
8359% A description of each parameter follows:
8360%
8361% o display: Specifies a connection to an X server; returned from
8362% XOpenDisplay.
8363%
8364% o parent: Specifies the parent window_info.
8365%
8366% o argv: Specifies the application's argument list.
8367%
8368% o argc: Specifies the number of arguments.
8369%
8370% o class_hint: Specifies a pointer to a X11 XClassHint structure.
8371%
8372% o manager_hints: Specifies a pointer to a X11 XWMHints structure.
8373%
8374% o window_info: Specifies a pointer to a X11 XWindowInfo structure.
8375%
8376*/
cristybcbda3f2011-09-03 13:01:22 +00008377MagickPrivate void XMakeWindow(Display *display,Window parent,char **argv,
cristy3ed852e2009-09-05 21:47:34 +00008378 int argc,XClassHint *class_hint,XWMHints *manager_hints,
8379 XWindowInfo *window_info)
8380{
8381#define MinWindowSize 64
8382
8383 Atom
8384 atom_list[2];
8385
8386 int
8387 gravity;
8388
8389 static XTextProperty
8390 icon_name,
8391 window_name;
8392
8393 Status
8394 status;
8395
8396 XSizeHints
8397 *size_hints;
8398
8399 /*
8400 Set window info hints.
8401 */
8402 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
8403 assert(display != (Display *) NULL);
8404 assert(window_info != (XWindowInfo *) NULL);
8405 size_hints=XAllocSizeHints();
8406 if (size_hints == (XSizeHints *) NULL)
8407 ThrowXWindowFatalException(XServerFatalError,"UnableToMakeXWindow",argv[0]);
cristydfe2b662010-08-22 16:17:24 +00008408 size_hints->flags=(int) window_info->flags;
cristy3ed852e2009-09-05 21:47:34 +00008409 size_hints->x=window_info->x;
8410 size_hints->y=window_info->y;
8411 size_hints->width=(int) window_info->width;
8412 size_hints->height=(int) window_info->height;
8413 if (window_info->immutable != MagickFalse)
8414 {
8415 /*
8416 Window size cannot be changed.
8417 */
8418 size_hints->min_width=size_hints->width;
8419 size_hints->min_height=size_hints->height;
8420 size_hints->max_width=size_hints->width;
8421 size_hints->max_height=size_hints->height;
8422 size_hints->flags|=PMinSize;
8423 size_hints->flags|=PMaxSize;
8424 }
8425 else
8426 {
8427 /*
8428 Window size can be changed.
8429 */
8430 size_hints->min_width=(int) window_info->min_width;
8431 size_hints->min_height=(int) window_info->min_height;
8432 size_hints->flags|=PResizeInc;
8433 size_hints->width_inc=(int) window_info->width_inc;
8434 size_hints->height_inc=(int) window_info->height_inc;
8435#if !defined(PRE_R4_ICCCM)
8436 size_hints->flags|=PBaseSize;
8437 size_hints->base_width=size_hints->width_inc;
8438 size_hints->base_height=size_hints->height_inc;
8439#endif
8440 }
8441 gravity=NorthWestGravity;
8442 if (window_info->geometry != (char *) NULL)
8443 {
8444 char
8445 default_geometry[MaxTextExtent],
8446 geometry[MaxTextExtent];
8447
8448 int
8449 flags;
8450
8451 register char
8452 *p;
8453
8454 /*
8455 User specified geometry.
8456 */
cristyb51dff52011-05-19 16:55:47 +00008457 (void) FormatLocaleString(default_geometry,MaxTextExtent,"%dx%d",
cristy3ed852e2009-09-05 21:47:34 +00008458 size_hints->width,size_hints->height);
8459 (void) CopyMagickString(geometry,window_info->geometry,MaxTextExtent);
8460 p=geometry;
8461 while (strlen(p) != 0)
8462 {
8463 if ((isspace((int) ((unsigned char) *p)) == 0) && (*p != '%'))
8464 p++;
8465 else
8466 (void) CopyMagickString(p,p+1,MaxTextExtent);
8467 }
8468 flags=XWMGeometry(display,window_info->screen,geometry,default_geometry,
8469 window_info->border_width,size_hints,&size_hints->x,&size_hints->y,
8470 &size_hints->width,&size_hints->height,&gravity);
8471 if ((flags & WidthValue) && (flags & HeightValue))
8472 size_hints->flags|=USSize;
8473 if ((flags & XValue) && (flags & YValue))
8474 {
8475 size_hints->flags|=USPosition;
8476 window_info->x=size_hints->x;
8477 window_info->y=size_hints->y;
8478 }
8479 }
8480#if !defined(PRE_R4_ICCCM)
8481 size_hints->win_gravity=gravity;
8482 size_hints->flags|=PWinGravity;
8483#endif
8484 if (window_info->id == (Window) NULL)
8485 window_info->id=XCreateWindow(display,parent,window_info->x,window_info->y,
8486 (unsigned int) size_hints->width,(unsigned int) size_hints->height,
8487 window_info->border_width,(int) window_info->depth,InputOutput,
cristyc57f6942010-11-12 01:47:39 +00008488 window_info->visual,(unsigned long) window_info->mask,
8489 &window_info->attributes);
cristy3ed852e2009-09-05 21:47:34 +00008490 else
8491 {
8492 MagickStatusType
8493 mask;
8494
8495 XEvent
8496 sans_event;
8497
8498 XWindowChanges
8499 window_changes;
8500
8501 /*
8502 Window already exists; change relevant attributes.
8503 */
cristyc57f6942010-11-12 01:47:39 +00008504 (void) XChangeWindowAttributes(display,window_info->id,(unsigned long)
8505 window_info->mask,&window_info->attributes);
cristy3ed852e2009-09-05 21:47:34 +00008506 mask=ConfigureNotify;
8507 while (XCheckTypedWindowEvent(display,window_info->id,(int) mask,&sans_event)) ;
8508 window_changes.x=window_info->x;
8509 window_changes.y=window_info->y;
8510 window_changes.width=(int) window_info->width;
8511 window_changes.height=(int) window_info->height;
8512 mask=(MagickStatusType) (CWWidth | CWHeight);
8513 if (window_info->flags & USPosition)
8514 mask|=CWX | CWY;
8515 (void) XReconfigureWMWindow(display,window_info->id,window_info->screen,
8516 mask,&window_changes);
8517 }
8518 if (window_info->id == (Window) NULL)
8519 ThrowXWindowFatalException(XServerFatalError,"UnableToCreateWindow",
8520 window_info->name);
8521 status=XStringListToTextProperty(&window_info->name,1,&window_name);
8522 if (status == False)
8523 ThrowXWindowFatalException(XServerFatalError,"UnableToCreateTextProperty",
8524 window_info->name);
8525 status=XStringListToTextProperty(&window_info->icon_name,1,&icon_name);
8526 if (status == False)
8527 ThrowXWindowFatalException(XServerFatalError,"UnableToCreateTextProperty",
8528 window_info->icon_name);
8529 if (window_info->icon_geometry != (char *) NULL)
8530 {
8531 int
8532 flags,
8533 height,
8534 width;
8535
8536 /*
8537 User specified icon geometry.
8538 */
8539 size_hints->flags|=USPosition;
8540 flags=XWMGeometry(display,window_info->screen,window_info->icon_geometry,
8541 (char *) NULL,0,size_hints,&manager_hints->icon_x,
8542 &manager_hints->icon_y,&width,&height,&gravity);
8543 if ((flags & XValue) && (flags & YValue))
8544 manager_hints->flags|=IconPositionHint;
8545 }
8546 XSetWMProperties(display,window_info->id,&window_name,&icon_name,argv,argc,
8547 size_hints,manager_hints,class_hint);
8548 if (window_name.value != (void *) NULL)
8549 {
8550 (void) XFree((void *) window_name.value);
8551 window_name.value=(unsigned char *) NULL;
8552 window_name.nitems=0;
8553 }
8554 if (icon_name.value != (void *) NULL)
8555 {
8556 (void) XFree((void *) icon_name.value);
8557 icon_name.value=(unsigned char *) NULL;
8558 icon_name.nitems=0;
8559 }
8560 atom_list[0]=XInternAtom(display,"WM_DELETE_WINDOW",MagickFalse);
8561 atom_list[1]=XInternAtom(display,"WM_TAKE_FOCUS",MagickFalse);
8562 (void) XSetWMProtocols(display,window_info->id,atom_list,2);
8563 (void) XFree((void *) size_hints);
8564 if (window_info->shape != MagickFalse)
8565 {
8566#if defined(MAGICKCORE_HAVE_SHAPE)
8567 int
8568 error_base,
8569 event_base;
8570
8571 /*
8572 Can we apply a non-rectangular shaping mask?
8573 */
8574 error_base=0;
8575 event_base=0;
8576 if (XShapeQueryExtension(display,&error_base,&event_base) == 0)
8577 window_info->shape=MagickFalse;
8578#else
8579 window_info->shape=MagickFalse;
8580#endif
8581 }
8582 if (window_info->shared_memory)
8583 {
8584#if defined(MAGICKCORE_HAVE_SHARED_MEMORY)
8585 /*
8586 Can we use shared memory with this window?
8587 */
8588 if (XShmQueryExtension(display) == 0)
8589 window_info->shared_memory=MagickFalse;
8590#else
8591 window_info->shared_memory=MagickFalse;
8592#endif
8593 }
8594 window_info->image=NewImageList();
8595 window_info->destroy=MagickFalse;
8596}
8597
8598/*
8599%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8600% %
8601% %
8602% %
8603% X M a g i c k P r o g r e s s M o n i t o r %
8604% %
8605% %
8606% %
8607%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8608%
8609% XMagickProgressMonitor() displays the progress a task is making in
8610% completing a task.
8611%
8612% The format of the XMagickProgressMonitor method is:
8613%
8614% void XMagickProgressMonitor(const char *task,
8615% const MagickOffsetType quantum,const MagickSizeType span,
8616% void *client_data)
8617%
8618% A description of each parameter follows:
8619%
8620% o task: Identifies the task in progress.
8621%
8622% o quantum: Specifies the quantum position within the span which represents
8623% how much progress has been made in completing a task.
8624%
8625% o span: Specifies the span relative to completing a task.
8626%
8627% o client_data: Pointer to any client data.
8628%
8629*/
8630
8631static const char *GetLocaleMonitorMessage(const char *text)
8632{
8633 char
8634 message[MaxTextExtent],
8635 tag[MaxTextExtent];
8636
8637 const char
8638 *locale_message;
8639
8640 register char
8641 *p;
8642
8643 (void) CopyMagickMemory(tag,text,MaxTextExtent);
8644 p=strrchr(tag,'/');
8645 if (p != (char *) NULL)
8646 *p='\0';
cristyb51dff52011-05-19 16:55:47 +00008647 (void) FormatLocaleString(message,MaxTextExtent,"Monitor/%s",tag);
cristy3ed852e2009-09-05 21:47:34 +00008648 locale_message=GetLocaleMessage(message);
8649 if (locale_message == message)
8650 return(text);
8651 return(locale_message);
8652}
8653
cristybcbda3f2011-09-03 13:01:22 +00008654MagickPrivate MagickBooleanType XMagickProgressMonitor(const char *tag,
cristy3ed852e2009-09-05 21:47:34 +00008655 const MagickOffsetType quantum,const MagickSizeType span,
8656 void *magick_unused(client_data))
8657{
8658 XWindows
8659 *windows;
8660
8661 windows=XSetWindows((XWindows *) ~0);
8662 if (windows == (XWindows *) NULL)
8663 return(MagickTrue);
8664 if (windows->info.mapped != MagickFalse)
8665 XProgressMonitorWidget(windows->display,windows,
8666 GetLocaleMonitorMessage(tag),quantum,span);
8667 return(MagickTrue);
8668}
8669
8670/*
8671%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8672% %
8673% %
8674% %
8675% X Q u e r y C o l o r D a t a b a s e %
8676% %
8677% %
8678% %
8679%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8680%
cristy9950d572011-10-01 18:22:35 +00008681% XQueryColorCompliance() looks up a RGB values for a color given in the target
cristy3ed852e2009-09-05 21:47:34 +00008682% string.
8683%
8684% The format of the XQueryColorDatabase method is:
8685%
cristy9950d572011-10-01 18:22:35 +00008686% MagickBooleanType XQueryColorCompliance(const char *target,XColor *color)
cristy3ed852e2009-09-05 21:47:34 +00008687%
8688% A description of each parameter follows:
8689%
8690% o target: Specifies the color to lookup in the X color database.
8691%
cristy101ab702011-10-13 13:06:32 +00008692% o color: A pointer to an PixelInfo structure. The RGB value of the target
cristy3ed852e2009-09-05 21:47:34 +00008693% color is returned as this value.
8694%
8695*/
cristy9950d572011-10-01 18:22:35 +00008696MagickPrivate MagickBooleanType XQueryColorCompliance(const char *target,
cristy3ed852e2009-09-05 21:47:34 +00008697 XColor *color)
8698{
8699 Colormap
8700 colormap;
8701
8702 static Display
8703 *display = (Display *) NULL;
8704
8705 Status
8706 status;
8707
8708 XColor
8709 xcolor;
8710
8711 /*
8712 Initialize color return value.
8713 */
8714 assert(color != (XColor *) NULL);
8715 color->red=0;
8716 color->green=0;
8717 color->blue=0;
8718 color->flags=(char) (DoRed | DoGreen | DoBlue);
8719 if ((target == (char *) NULL) || (*target == '\0'))
8720 target="#ffffffffffff";
8721 /*
8722 Let the X server define the color for us.
8723 */
8724 if (display == (Display *) NULL)
8725 display=XOpenDisplay((char *) NULL);
8726 if (display == (Display *) NULL)
8727 {
8728 ThrowXWindowFatalException(XServerError,"ColorIsNotKnownToServer",target);
8729 return(MagickFalse);
8730 }
8731 colormap=XDefaultColormap(display,XDefaultScreen(display));
8732 status=XParseColor(display,colormap,(char *) target,&xcolor);
8733 if (status == False)
8734 ThrowXWindowFatalException(XServerError,"ColorIsNotKnownToServer",target)
8735 else
8736 {
8737 color->red=xcolor.red;
8738 color->green=xcolor.green;
8739 color->blue=xcolor.blue;
8740 color->flags=xcolor.flags;
8741 }
8742 return(status != False ? MagickTrue : MagickFalse);
8743}
8744
8745/*
8746%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8747% %
8748% %
8749% %
8750% X Q u e r y P o s i t i o n %
8751% %
8752% %
8753% %
8754%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8755%
8756% XQueryPosition() gets the pointer coordinates relative to a window.
8757%
8758% The format of the XQueryPosition method is:
8759%
8760% void XQueryPosition(Display *display,const Window window,int *x,int *y)
8761%
8762% A description of each parameter follows:
8763%
8764% o display: Specifies a connection to an X server; returned from
8765% XOpenDisplay.
8766%
8767% o window: Specifies a pointer to a Window.
8768%
8769% o x: Return the x coordinate of the pointer relative to the origin of the
8770% window.
8771%
8772% o y: Return the y coordinate of the pointer relative to the origin of the
8773% window.
8774%
8775*/
cristybcbda3f2011-09-03 13:01:22 +00008776MagickPrivate void XQueryPosition(Display *display,const Window window,int *x,int *y)
cristy3ed852e2009-09-05 21:47:34 +00008777{
8778 int
8779 x_root,
8780 y_root;
8781
8782 unsigned int
8783 mask;
8784
8785 Window
8786 root_window;
8787
8788 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
8789 assert(display != (Display *) NULL);
8790 assert(window != (Window) NULL);
8791 assert(x != (int *) NULL);
8792 assert(y != (int *) NULL);
8793 (void) XQueryPointer(display,window,&root_window,&root_window,&x_root,&y_root,
8794 x,y,&mask);
8795}
8796
8797/*
8798%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8799% %
8800% %
8801% %
8802% X R e f r e s h W i n d o w %
8803% %
8804% %
8805% %
8806%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8807%
8808% XRefreshWindow() refreshes an image in a X window.
8809%
8810% The format of the XRefreshWindow method is:
8811%
8812% void XRefreshWindow(Display *display,const XWindowInfo *window,
8813% const XEvent *event)
8814%
8815% A description of each parameter follows:
8816%
8817% o display: Specifies a connection to an X server; returned from
8818% XOpenDisplay.
8819%
8820% o window: Specifies a pointer to a XWindowInfo structure.
8821%
8822% o event: Specifies a pointer to a XEvent structure. If it is NULL,
8823% the entire image is refreshed.
8824%
8825*/
cristybcbda3f2011-09-03 13:01:22 +00008826MagickPrivate void XRefreshWindow(Display *display,const XWindowInfo *window,
cristy3ed852e2009-09-05 21:47:34 +00008827 const XEvent *event)
8828{
8829 int
8830 x,
8831 y;
8832
8833 unsigned int
8834 height,
8835 width;
8836
8837 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
8838 assert(display != (Display *) NULL);
8839 assert(window != (XWindowInfo *) NULL);
8840 if (window->ximage == (XImage *) NULL)
8841 return;
8842 if (event != (XEvent *) NULL)
8843 {
8844 /*
8845 Determine geometry from expose event.
8846 */
8847 x=event->xexpose.x;
8848 y=event->xexpose.y;
8849 width=(unsigned int) event->xexpose.width;
8850 height=(unsigned int) event->xexpose.height;
8851 }
8852 else
8853 {
8854 XEvent
8855 sans_event;
8856
8857 /*
8858 Refresh entire window; discard outstanding expose events.
8859 */
8860 x=0;
8861 y=0;
8862 width=window->width;
8863 height=window->height;
8864 while (XCheckTypedWindowEvent(display,window->id,Expose,&sans_event)) ;
cristya0e5ad52010-02-10 02:05:12 +00008865 if (window->matte_pixmap != (Pixmap) NULL)
8866 {
8867#if defined(MAGICKCORE_HAVE_SHAPE)
8868 if (window->shape != MagickFalse)
8869 XShapeCombineMask(display,window->id,ShapeBounding,0,0,
8870 window->matte_pixmap,ShapeSet);
8871#endif
8872 }
cristy3ed852e2009-09-05 21:47:34 +00008873 }
8874 /*
8875 Check boundary conditions.
8876 */
8877 if ((window->ximage->width-(x+window->x)) < (int) width)
8878 width=(unsigned int) (window->ximage->width-(x+window->x));
8879 if ((window->ximage->height-(y+window->y)) < (int) height)
8880 height=(unsigned int) (window->ximage->height-(y+window->y));
8881 /*
8882 Refresh image.
8883 */
8884 if (window->matte_pixmap != (Pixmap) NULL)
cristya0e5ad52010-02-10 02:05:12 +00008885 (void) XSetClipMask(display,window->annotate_context,window->matte_pixmap);
cristy3ed852e2009-09-05 21:47:34 +00008886 if (window->pixmap != (Pixmap) NULL)
8887 {
8888 if (window->depth > 1)
8889 (void) XCopyArea(display,window->pixmap,window->id,
8890 window->annotate_context,x+window->x,y+window->y,width,height,x,y);
8891 else
8892 (void) XCopyPlane(display,window->pixmap,window->id,
8893 window->highlight_context,x+window->x,y+window->y,width,height,x,y,
8894 1L);
8895 }
8896 else
8897 {
8898#if defined(MAGICKCORE_HAVE_SHARED_MEMORY)
8899 if (window->shared_memory)
8900 (void) XShmPutImage(display,window->id,window->annotate_context,
8901 window->ximage,x+window->x,y+window->y,x,y,width,height,MagickTrue);
8902#endif
8903 if (window->shared_memory == MagickFalse)
8904 (void) XPutImage(display,window->id,window->annotate_context,
8905 window->ximage,x+window->x,y+window->y,x,y,width,height);
8906 }
8907 if (window->matte_pixmap != (Pixmap) NULL)
8908 (void) XSetClipMask(display,window->annotate_context,None);
8909 (void) XFlush(display);
8910}
8911
8912/*
8913%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8914% %
8915% %
8916% %
8917% X R e m o t e C o m m a n d %
8918% %
8919% %
8920% %
8921%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8922%
8923% XRemoteCommand() forces a remote display(1) to display the specified
8924% image filename.
8925%
8926% The format of the XRemoteCommand method is:
8927%
8928% MagickBooleanType XRemoteCommand(Display *display,const char *window,
8929% const char *filename)
8930%
8931% A description of each parameter follows:
8932%
8933% o display: Specifies a connection to an X server; returned from
8934% XOpenDisplay.
8935%
8936% o window: Specifies the name or id of an X window.
8937%
8938% o filename: the name of the image filename to display.
8939%
8940*/
8941MagickExport MagickBooleanType XRemoteCommand(Display *display,
8942 const char *window,const char *filename)
8943{
8944 Atom
8945 remote_atom;
8946
8947 Window
8948 remote_window,
8949 root_window;
8950
8951 assert(filename != (char *) NULL);
8952 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",filename);
8953 if (display == (Display *) NULL)
8954 display=XOpenDisplay((char *) NULL);
8955 if (display == (Display *) NULL)
8956 {
8957 ThrowXWindowException(XServerError,"UnableToOpenXServer",filename);
8958 return(MagickFalse);
8959 }
8960 remote_atom=XInternAtom(display,"IM_PROTOCOLS",MagickFalse);
8961 remote_window=(Window) NULL;
8962 root_window=XRootWindow(display,XDefaultScreen(display));
8963 if (window != (char *) NULL)
8964 {
8965 /*
8966 Search window hierarchy and identify any clients by name or ID.
8967 */
8968 if (isdigit((unsigned char) *window) != 0)
8969 remote_window=XWindowByID(display,root_window,(Window)
8970 strtol((char *) window,(char **) NULL,0));
8971 if (remote_window == (Window) NULL)
8972 remote_window=XWindowByName(display,root_window,window);
8973 }
8974 if (remote_window == (Window) NULL)
8975 remote_window=XWindowByProperty(display,root_window,remote_atom);
8976 if (remote_window == (Window) NULL)
8977 {
8978 ThrowXWindowException(XServerError,"UnableToConnectToRemoteDisplay",
8979 filename);
8980 return(MagickFalse);
8981 }
8982 /*
8983 Send remote command.
8984 */
8985 remote_atom=XInternAtom(display,"IM_REMOTE_COMMAND",MagickFalse);
8986 (void) XChangeProperty(display,remote_window,remote_atom,XA_STRING,8,
8987 PropModeReplace,(unsigned char *) filename,(int) strlen(filename));
8988 (void) XSync(display,MagickFalse);
8989 return(MagickTrue);
8990}
8991
8992/*
8993%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8994% %
8995% %
8996% %
8997% X R e t a i n W i n d o w C o l o r s %
8998% %
8999% %
9000% %
9001%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9002%
9003% XRetainWindowColors() sets X11 color resources on a window. This preserves
9004% the colors associated with an image displayed on the window.
9005%
9006% The format of the XRetainWindowColors method is:
9007%
9008% void XRetainWindowColors(Display *display,const Window window)
9009%
9010% A description of each parameter follows:
9011%
9012% o display: Specifies a connection to an X server; returned from
9013% XOpenDisplay.
9014%
9015% o window: Specifies a pointer to a XWindowInfo structure.
9016%
9017*/
9018MagickExport void XRetainWindowColors(Display *display,const Window window)
9019{
9020 Atom
9021 property;
9022
9023 Pixmap
9024 pixmap;
9025
9026 /*
9027 Put property on the window.
9028 */
9029 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
9030 assert(display != (Display *) NULL);
9031 assert(window != (Window) NULL);
9032 property=XInternAtom(display,"_XSETROOT_ID",MagickFalse);
9033 if (property == (Atom) NULL)
9034 {
9035 ThrowXWindowFatalException(XServerError,"UnableToCreateProperty",
9036 "_XSETROOT_ID");
9037 return;
9038 }
9039 pixmap=XCreatePixmap(display,window,1,1,1);
9040 if (pixmap == (Pixmap) NULL)
9041 {
9042 ThrowXWindowFatalException(XServerError,"UnableToCreateBitmap","");
9043 return;
9044 }
9045 (void) XChangeProperty(display,window,property,XA_PIXMAP,32,PropModeReplace,
9046 (unsigned char *) &pixmap,1);
9047 (void) XSetCloseDownMode(display,RetainPermanent);
9048}
9049
9050/*
9051%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9052% %
9053% %
9054% %
9055% X S e l e c t W i n d o w %
9056% %
9057% %
9058% %
9059%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9060%
9061% XSelectWindow() allows a user to select a window using the mouse. If the
9062% mouse moves, a cropping rectangle is drawn and the extents of the rectangle
9063% is returned in the crop_info structure.
9064%
9065% The format of the XSelectWindow function is:
9066%
9067% target_window=XSelectWindow(display,crop_info)
9068%
9069% A description of each parameter follows:
9070%
9071% o window: XSelectWindow returns the window id.
9072%
9073% o display: Specifies a pointer to the Display structure; returned from
9074% XOpenDisplay.
9075%
9076% o crop_info: Specifies a pointer to a RectangleInfo structure. It
9077% contains the extents of any cropping rectangle.
9078%
cristy3ed852e2009-09-05 21:47:34 +00009079*/
9080static Window XSelectWindow(Display *display,RectangleInfo *crop_info)
9081{
9082#define MinimumCropArea (unsigned int) 9
9083
9084 Cursor
9085 target_cursor;
9086
9087 GC
9088 annotate_context;
9089
9090 int
9091 presses,
9092 x_offset,
9093 y_offset;
9094
9095 Status
9096 status;
9097
9098 Window
9099 root_window,
9100 target_window;
9101
9102 XEvent
9103 event;
9104
9105 XGCValues
9106 context_values;
9107
9108 /*
9109 Initialize graphic context.
9110 */
9111 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
9112 assert(display != (Display *) NULL);
9113 assert(crop_info != (RectangleInfo *) NULL);
9114 root_window=XRootWindow(display,XDefaultScreen(display));
9115 context_values.background=XBlackPixel(display,XDefaultScreen(display));
9116 context_values.foreground=XWhitePixel(display,XDefaultScreen(display));
9117 context_values.function=GXinvert;
9118 context_values.plane_mask=
9119 context_values.background ^ context_values.foreground;
9120 context_values.subwindow_mode=IncludeInferiors;
cristybb503372010-05-27 20:51:26 +00009121 annotate_context=XCreateGC(display,root_window,(size_t) (GCBackground |
cristy3ed852e2009-09-05 21:47:34 +00009122 GCForeground | GCFunction | GCSubwindowMode),&context_values);
9123 if (annotate_context == (GC) NULL)
9124 return(MagickFalse);
9125 /*
9126 Grab the pointer using target cursor.
9127 */
9128 target_cursor=XMakeCursor(display,root_window,XDefaultColormap(display,
9129 XDefaultScreen(display)),(char * ) "white",(char * ) "black");
9130 status=XGrabPointer(display,root_window,MagickFalse,(unsigned int)
9131 (ButtonPressMask | ButtonReleaseMask | ButtonMotionMask),GrabModeSync,
9132 GrabModeAsync,root_window,target_cursor,CurrentTime);
9133 if (status != GrabSuccess)
9134 {
9135 ThrowXWindowFatalException(XServerError,"UnableToGrabMouse","");
9136 return((Window) NULL);
9137 }
9138 /*
9139 Select a window.
9140 */
9141 crop_info->width=0;
9142 crop_info->height=0;
9143 presses=0;
9144 target_window=(Window) NULL;
9145 x_offset=0;
9146 y_offset=0;
9147 do
9148 {
9149 if ((crop_info->width*crop_info->height) >= MinimumCropArea)
9150 (void) XDrawRectangle(display,root_window,annotate_context,
9151 (int) crop_info->x,(int) crop_info->y,(unsigned int) crop_info->width-1,
9152 (unsigned int) crop_info->height-1);
9153 /*
9154 Allow another event.
9155 */
9156 (void) XAllowEvents(display,SyncPointer,CurrentTime);
9157 (void) XWindowEvent(display,root_window,ButtonPressMask |
9158 ButtonReleaseMask | ButtonMotionMask,&event);
9159 if ((crop_info->width*crop_info->height) >= MinimumCropArea)
9160 (void) XDrawRectangle(display,root_window,annotate_context,
9161 (int) crop_info->x,(int) crop_info->y,(unsigned int) crop_info->width-1,
9162 (unsigned int) crop_info->height-1);
9163 switch (event.type)
9164 {
9165 case ButtonPress:
9166 {
9167 target_window=XGetSubwindow(display,event.xbutton.subwindow,
9168 event.xbutton.x,event.xbutton.y);
9169 if (target_window == (Window) NULL)
9170 target_window=root_window;
9171 x_offset=event.xbutton.x_root;
9172 y_offset=event.xbutton.y_root;
cristyecd0ab52010-05-30 14:59:20 +00009173 crop_info->x=(ssize_t) x_offset;
9174 crop_info->y=(ssize_t) y_offset;
cristy3ed852e2009-09-05 21:47:34 +00009175 crop_info->width=0;
9176 crop_info->height=0;
9177 presses++;
9178 break;
9179 }
9180 case ButtonRelease:
9181 {
9182 presses--;
9183 break;
9184 }
9185 case MotionNotify:
9186 {
9187 /*
9188 Discard pending button motion events.
9189 */
9190 while (XCheckMaskEvent(display,ButtonMotionMask,&event)) ;
cristyecd0ab52010-05-30 14:59:20 +00009191 crop_info->x=(ssize_t) event.xmotion.x;
9192 crop_info->y=(ssize_t) event.xmotion.y;
cristy3ed852e2009-09-05 21:47:34 +00009193 /*
9194 Check boundary conditions.
9195 */
9196 if ((int) crop_info->x < x_offset)
cristyecd0ab52010-05-30 14:59:20 +00009197 crop_info->width=(size_t) (x_offset-crop_info->x);
cristy3ed852e2009-09-05 21:47:34 +00009198 else
9199 {
cristyecd0ab52010-05-30 14:59:20 +00009200 crop_info->width=(size_t) (crop_info->x-x_offset);
9201 crop_info->x=(ssize_t) x_offset;
cristy3ed852e2009-09-05 21:47:34 +00009202 }
9203 if ((int) crop_info->y < y_offset)
cristyecd0ab52010-05-30 14:59:20 +00009204 crop_info->height=(size_t) (y_offset-crop_info->y);
cristy3ed852e2009-09-05 21:47:34 +00009205 else
9206 {
cristyecd0ab52010-05-30 14:59:20 +00009207 crop_info->height=(size_t) (crop_info->y-y_offset);
9208 crop_info->y=(ssize_t) y_offset;
cristy3ed852e2009-09-05 21:47:34 +00009209 }
9210 }
9211 default:
9212 break;
9213 }
9214 } while ((target_window == (Window) NULL) || (presses > 0));
9215 (void) XUngrabPointer(display,CurrentTime);
9216 (void) XFreeCursor(display,target_cursor);
9217 (void) XFreeGC(display,annotate_context);
9218 if ((crop_info->width*crop_info->height) < MinimumCropArea)
9219 {
9220 crop_info->width=0;
9221 crop_info->height=0;
9222 }
9223 if ((crop_info->width != 0) && (crop_info->height != 0))
9224 target_window=root_window;
9225 return(target_window);
9226}
9227
9228/*
9229%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9230% %
9231% %
9232% %
9233% X S e t C u r s o r S t a t e %
9234% %
9235% %
9236% %
9237%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9238%
9239% XSetCursorState() sets the cursor state to busy, otherwise the cursor are
9240% reset to their default.
9241%
9242% The format of the XXSetCursorState method is:
9243%
9244% XSetCursorState(display,windows,const MagickStatusType state)
9245%
9246% A description of each parameter follows:
9247%
9248% o display: Specifies a connection to an X server; returned from
9249% XOpenDisplay.
9250%
9251% o windows: Specifies a pointer to a XWindows structure.
9252%
9253% o state: An unsigned integer greater than 0 sets the cursor state
9254% to busy, otherwise the cursor are reset to their default.
9255%
9256*/
cristybcbda3f2011-09-03 13:01:22 +00009257MagickPrivate void XSetCursorState(Display *display,XWindows *windows,
cristy3ed852e2009-09-05 21:47:34 +00009258 const MagickStatusType state)
9259{
9260 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
9261 assert(display != (Display *) NULL);
9262 assert(windows != (XWindows *) NULL);
9263 if (state)
9264 {
9265 (void) XCheckDefineCursor(display,windows->image.id,
9266 windows->image.busy_cursor);
9267 (void) XCheckDefineCursor(display,windows->pan.id,
9268 windows->pan.busy_cursor);
9269 (void) XCheckDefineCursor(display,windows->magnify.id,
9270 windows->magnify.busy_cursor);
9271 (void) XCheckDefineCursor(display,windows->command.id,
9272 windows->command.busy_cursor);
9273 }
9274 else
9275 {
9276 (void) XCheckDefineCursor(display,windows->image.id,
9277 windows->image.cursor);
9278 (void) XCheckDefineCursor(display,windows->pan.id,windows->pan.cursor);
9279 (void) XCheckDefineCursor(display,windows->magnify.id,
9280 windows->magnify.cursor);
9281 (void) XCheckDefineCursor(display,windows->command.id,
9282 windows->command.cursor);
9283 (void) XCheckDefineCursor(display,windows->command.id,
9284 windows->widget.cursor);
9285 (void) XWithdrawWindow(display,windows->info.id,windows->info.screen);
9286 }
9287 windows->info.mapped=MagickFalse;
9288}
9289
9290/*
9291%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9292% %
9293% %
9294% %
9295% X S e t W i n d o w s %
9296% %
9297% %
9298% %
9299%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9300%
9301% XSetWindows() sets the X windows structure if the windows info is specified.
9302% Otherwise the current windows structure is returned.
9303%
9304% The format of the XSetWindows method is:
9305%
9306% XWindows *XSetWindows(XWindows *windows_info)
9307%
9308% A description of each parameter follows:
9309%
9310% o windows_info: Initialize the Windows structure with this information.
9311%
9312*/
cristybcbda3f2011-09-03 13:01:22 +00009313MagickPrivate XWindows *XSetWindows(XWindows *windows_info)
cristy3ed852e2009-09-05 21:47:34 +00009314{
9315 static XWindows
9316 *windows = (XWindows *) NULL;
9317
9318 if (windows_info != (XWindows *) ~0)
9319 {
9320 windows=(XWindows *) RelinquishMagickMemory(windows);
9321 windows=windows_info;
9322 }
9323 return(windows);
9324}
9325/*
9326%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9327% %
9328% %
9329% %
9330% X U s e r P r e f e r e n c e s %
9331% %
9332% %
9333% %
9334%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9335%
9336% XUserPreferences() saves the preferences in a configuration file in the
9337% users' home directory.
9338%
9339% The format of the XUserPreferences method is:
9340%
9341% void XUserPreferences(XResourceInfo *resource_info)
9342%
9343% A description of each parameter follows:
9344%
9345% o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
9346%
9347*/
cristybcbda3f2011-09-03 13:01:22 +00009348MagickPrivate void XUserPreferences(XResourceInfo *resource_info)
cristy3ed852e2009-09-05 21:47:34 +00009349{
9350#if defined(X11_PREFERENCES_PATH)
9351 char
9352 cache[MaxTextExtent],
9353 filename[MaxTextExtent],
9354 specifier[MaxTextExtent];
9355
9356 const char
cristy104cea82009-10-25 02:26:51 +00009357 *client_name,
cristy3ed852e2009-09-05 21:47:34 +00009358 *value;
9359
9360 XrmDatabase
9361 preferences_database;
9362
9363 /*
9364 Save user preferences to the client configuration file.
9365 */
9366 assert(resource_info != (XResourceInfo *) NULL);
cristy104cea82009-10-25 02:26:51 +00009367 client_name=GetClientName();
cristy3ed852e2009-09-05 21:47:34 +00009368 preferences_database=XrmGetStringDatabase("");
cristyb51dff52011-05-19 16:55:47 +00009369 (void) FormatLocaleString(specifier,MaxTextExtent,"%s.backdrop",client_name);
cristy3ed852e2009-09-05 21:47:34 +00009370 value=resource_info->backdrop ? "True" : "False";
9371 XrmPutStringResource(&preferences_database,specifier,(char *) value);
cristyb51dff52011-05-19 16:55:47 +00009372 (void) FormatLocaleString(specifier,MaxTextExtent,"%s.colormap",client_name);
cristy3ed852e2009-09-05 21:47:34 +00009373 value=resource_info->colormap == SharedColormap ? "Shared" : "Private";
9374 XrmPutStringResource(&preferences_database,specifier,(char *) value);
cristyb51dff52011-05-19 16:55:47 +00009375 (void) FormatLocaleString(specifier,MaxTextExtent,"%s.confirmExit",
cristy104cea82009-10-25 02:26:51 +00009376 client_name);
cristy3ed852e2009-09-05 21:47:34 +00009377 value=resource_info->confirm_exit ? "True" : "False";
9378 XrmPutStringResource(&preferences_database,specifier,(char *) value);
cristyb51dff52011-05-19 16:55:47 +00009379 (void) FormatLocaleString(specifier,MaxTextExtent,"%s.confirmEdit",
cristy104cea82009-10-25 02:26:51 +00009380 client_name);
cristy3ed852e2009-09-05 21:47:34 +00009381 value=resource_info->confirm_edit ? "True" : "False";
9382 XrmPutStringResource(&preferences_database,specifier,(char *) value);
cristyb51dff52011-05-19 16:55:47 +00009383 (void) FormatLocaleString(specifier,MaxTextExtent,"%s.displayWarnings",
cristy104cea82009-10-25 02:26:51 +00009384 client_name);
cristy3ed852e2009-09-05 21:47:34 +00009385 value=resource_info->display_warnings ? "True" : "False";
9386 XrmPutStringResource(&preferences_database,specifier,(char *) value);
cristyb51dff52011-05-19 16:55:47 +00009387 (void) FormatLocaleString(specifier,MaxTextExtent,"%s.dither",client_name);
cristy3ed852e2009-09-05 21:47:34 +00009388 value=resource_info->quantize_info->dither ? "True" : "False";
9389 XrmPutStringResource(&preferences_database,specifier,(char *) value);
cristyb51dff52011-05-19 16:55:47 +00009390 (void) FormatLocaleString(specifier,MaxTextExtent,"%s.gammaCorrect",
cristy104cea82009-10-25 02:26:51 +00009391 client_name);
cristy3ed852e2009-09-05 21:47:34 +00009392 value=resource_info->gamma_correct ? "True" : "False";
9393 XrmPutStringResource(&preferences_database,specifier,(char *) value);
cristyb51dff52011-05-19 16:55:47 +00009394 (void) FormatLocaleString(specifier,MaxTextExtent,"%s.undoCache",client_name);
9395 (void) FormatLocaleString(cache,MaxTextExtent,"%.20g",(double)
cristy3ed852e2009-09-05 21:47:34 +00009396 resource_info->undo_cache);
9397 XrmPutStringResource(&preferences_database,specifier,cache);
cristyb51dff52011-05-19 16:55:47 +00009398 (void) FormatLocaleString(specifier,MaxTextExtent,"%s.usePixmap",client_name);
cristy3ed852e2009-09-05 21:47:34 +00009399 value=resource_info->use_pixmap ? "True" : "False";
9400 XrmPutStringResource(&preferences_database,specifier,(char *) value);
cristyb51dff52011-05-19 16:55:47 +00009401 (void) FormatLocaleString(filename,MaxTextExtent,"%s%src",
cristy104cea82009-10-25 02:26:51 +00009402 X11_PREFERENCES_PATH,client_name);
cristy3ed852e2009-09-05 21:47:34 +00009403 ExpandFilename(filename);
9404 XrmPutFileDatabase(preferences_database,filename);
9405#endif
9406}
9407
9408/*
9409%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9410% %
9411% %
9412% %
9413% X V i s u a l C l a s s N a m e %
9414% %
9415% %
9416% %
9417%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9418%
9419% XVisualClassName() returns the visual class name as a character string.
9420%
9421% The format of the XVisualClassName method is:
9422%
9423% char *XVisualClassName(const int visual_class)
9424%
9425% A description of each parameter follows:
9426%
9427% o visual_type: XVisualClassName returns the visual class as a character
9428% string.
9429%
9430% o class: Specifies the visual class.
9431%
cristy3ed852e2009-09-05 21:47:34 +00009432*/
9433static const char *XVisualClassName(const int visual_class)
9434{
9435 switch (visual_class)
9436 {
9437 case StaticGray: return("StaticGray");
9438 case GrayScale: return("GrayScale");
9439 case StaticColor: return("StaticColor");
9440 case PseudoColor: return("PseudoColor");
9441 case TrueColor: return("TrueColor");
9442 case DirectColor: return("DirectColor");
9443 }
9444 return("unknown visual class");
9445}
9446
9447/*
9448%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9449% %
9450% %
9451% %
9452% X W a r n i n g %
9453% %
9454% %
9455% %
9456%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9457%
9458% XWarning() displays a warning reason in a Notice widget.
9459%
9460% The format of the XWarning method is:
9461%
9462% void XWarning(const unsigned int warning,const char *reason,
9463% const char *description)
9464%
9465% A description of each parameter follows:
9466%
9467% o warning: Specifies the numeric warning category.
9468%
9469% o reason: Specifies the reason to display before terminating the
9470% program.
9471%
9472% o description: Specifies any description to the reason.
9473%
9474*/
cristybcbda3f2011-09-03 13:01:22 +00009475MagickPrivate void XWarning(const ExceptionType magick_unused(warning),
cristy3ed852e2009-09-05 21:47:34 +00009476 const char *reason,const char *description)
9477{
9478 char
9479 text[MaxTextExtent];
9480
9481 XWindows
9482 *windows;
9483
9484 if (reason == (char *) NULL)
9485 return;
9486 (void) CopyMagickString(text,reason,MaxTextExtent);
9487 (void) ConcatenateMagickString(text,":",MaxTextExtent);
9488 windows=XSetWindows((XWindows *) ~0);
9489 XNoticeWidget(windows->display,windows,text,(char *) description);
9490}
9491
9492/*
9493%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9494% %
9495% %
9496% %
9497% X W i n d o w B y I D %
9498% %
9499% %
9500% %
9501%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9502%
9503% XWindowByID() locates a child window with a given ID. If not window with
9504% the given name is found, 0 is returned. Only the window specified and its
9505% subwindows are searched.
9506%
9507% The format of the XWindowByID function is:
9508%
9509% child=XWindowByID(display,window,id)
9510%
9511% A description of each parameter follows:
9512%
9513% o child: XWindowByID returns the window with the specified
9514% id. If no windows are found, XWindowByID returns 0.
9515%
9516% o display: Specifies a pointer to the Display structure; returned from
9517% XOpenDisplay.
9518%
9519% o id: Specifies the id of the window to locate.
9520%
9521*/
cristybcbda3f2011-09-03 13:01:22 +00009522MagickPrivate Window XWindowByID(Display *display,const Window root_window,
cristybb503372010-05-27 20:51:26 +00009523 const size_t id)
cristy3ed852e2009-09-05 21:47:34 +00009524{
9525 RectangleInfo
9526 rectangle_info;
9527
9528 register int
9529 i;
9530
9531 Status
9532 status;
9533
9534 unsigned int
9535 number_children;
9536
9537 Window
9538 child,
9539 *children,
9540 window;
9541
9542 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
9543 assert(display != (Display *) NULL);
9544 assert(root_window != (Window) NULL);
9545 if (id == 0)
9546 return(XSelectWindow(display,&rectangle_info));
9547 if (root_window == id)
cristydfe2b662010-08-22 16:17:24 +00009548 return(root_window);
cristy3ed852e2009-09-05 21:47:34 +00009549 status=XQueryTree(display,root_window,&child,&child,&children,
9550 &number_children);
9551 if (status == False)
9552 return((Window) NULL);
9553 window=(Window) NULL;
9554 for (i=0; i < (int) number_children; i++)
9555 {
9556 /*
9557 Search each child and their children.
9558 */
9559 window=XWindowByID(display,children[i],id);
9560 if (window != (Window) NULL)
9561 break;
9562 }
9563 if (children != (Window *) NULL)
9564 (void) XFree((void *) children);
9565 return(window);
9566}
9567
9568/*
9569%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9570% %
9571% %
9572% %
9573% X W i n d o w B y N a m e %
9574% %
9575% %
9576% %
9577%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9578%
9579% XWindowByName() locates a window with a given name on a display. If no
9580% window with the given name is found, 0 is returned. If more than one window
9581% has the given name, the first one is returned. Only root and its children
9582% are searched.
9583%
9584% The format of the XWindowByName function is:
9585%
9586% window=XWindowByName(display,root_window,name)
9587%
9588% A description of each parameter follows:
9589%
9590% o window: XWindowByName returns the window id.
9591%
9592% o display: Specifies a pointer to the Display structure; returned from
9593% XOpenDisplay.
9594%
9595% o root_window: Specifies the id of the root window.
9596%
9597% o name: Specifies the name of the window to locate.
9598%
9599*/
cristybcbda3f2011-09-03 13:01:22 +00009600MagickPrivate Window XWindowByName(Display *display,const Window root_window,
cristy3ed852e2009-09-05 21:47:34 +00009601 const char *name)
9602{
9603 register int
9604 i;
9605
9606 Status
9607 status;
9608
9609 unsigned int
9610 number_children;
9611
9612 Window
9613 *children,
9614 child,
9615 window;
9616
9617 XTextProperty
9618 window_name;
9619
9620 assert(display != (Display *) NULL);
9621 assert(root_window != (Window) NULL);
9622 assert(name != (char *) NULL);
9623 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",name);
9624 if (XGetWMName(display,root_window,&window_name) != 0)
9625 if (LocaleCompare((char *) window_name.value,name) == 0)
9626 return(root_window);
9627 status=XQueryTree(display,root_window,&child,&child,&children,
9628 &number_children);
9629 if (status == False)
9630 return((Window) NULL);
9631 window=(Window) NULL;
9632 for (i=0; i < (int) number_children; i++)
9633 {
9634 /*
9635 Search each child and their children.
9636 */
9637 window=XWindowByName(display,children[i],name);
9638 if (window != (Window) NULL)
9639 break;
9640 }
9641 if (children != (Window *) NULL)
9642 (void) XFree((void *) children);
9643 return(window);
9644}
9645
9646/*
9647%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9648% %
9649% %
9650% %
9651% X W i n d o w B y P r o p e r y %
9652% %
9653% %
9654% %
9655%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9656%
9657% XWindowByProperty() locates a child window with a given property. If not
9658% window with the given name is found, 0 is returned. If more than one window
9659% has the given property, the first one is returned. Only the window
9660% specified and its subwindows are searched.
9661%
9662% The format of the XWindowByProperty function is:
9663%
9664% child=XWindowByProperty(display,window,property)
9665%
9666% A description of each parameter follows:
9667%
9668% o child: XWindowByProperty returns the window id with the specified
9669% property. If no windows are found, XWindowByProperty returns 0.
9670%
9671% o display: Specifies a pointer to the Display structure; returned from
9672% XOpenDisplay.
9673%
9674% o property: Specifies the property of the window to locate.
9675%
9676*/
cristybcbda3f2011-09-03 13:01:22 +00009677MagickPrivate Window XWindowByProperty(Display *display,const Window window,
cristy3ed852e2009-09-05 21:47:34 +00009678 const Atom property)
9679{
9680 Atom
9681 type;
9682
9683 int
9684 format;
9685
9686 Status
9687 status;
9688
9689 unsigned char
9690 *data;
9691
9692 unsigned int
9693 i,
9694 number_children;
9695
cristyf2faecf2010-05-28 19:19:36 +00009696 unsigned long
cristy3ed852e2009-09-05 21:47:34 +00009697 after,
9698 number_items;
9699
9700 Window
9701 child,
9702 *children,
9703 parent,
9704 root;
9705
9706 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
9707 assert(display != (Display *) NULL);
9708 assert(window != (Window) NULL);
9709 assert(property != (Atom) NULL);
9710 status=XQueryTree(display,window,&root,&parent,&children,&number_children);
9711 if (status == False)
9712 return((Window) NULL);
9713 type=(Atom) NULL;
9714 child=(Window) NULL;
9715 for (i=0; (i < number_children) && (child == (Window) NULL); i++)
9716 {
9717 status=XGetWindowProperty(display,children[i],property,0L,0L,MagickFalse,
9718 (Atom) AnyPropertyType,&type,&format,&number_items,&after,&data);
9719 if (data != NULL)
9720 (void) XFree((void *) data);
9721 if ((status == Success) && (type != (Atom) NULL))
9722 child=children[i];
9723 }
9724 for (i=0; (i < number_children) && (child == (Window) NULL); i++)
9725 child=XWindowByProperty(display,children[i],property);
9726 if (children != (Window *) NULL)
9727 (void) XFree((void *) children);
9728 return(child);
9729}
9730#else
9731
9732/*
9733%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9734% %
9735% %
9736% %
9737% X I m p o r t I m a g e %
9738% %
9739% %
9740% %
9741%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9742%
9743% XImportImage() reads an image from an X window.
9744%
9745% The format of the XImportImage method is:
9746%
cristya0dc96a2011-12-19 23:58:54 +00009747% Image *XImportImage(const ImageInfo *image_info,XImportInfo *ximage_info,
9748% ExceptionInfo *exception)
cristy3ed852e2009-09-05 21:47:34 +00009749%
9750% A description of each parameter follows:
9751%
9752% o image_info: the image info..
9753%
9754% o ximage_info: Specifies a pointer to an XImportInfo structure.
9755%
cristya0dc96a2011-12-19 23:58:54 +00009756% o exception: return any errors or warnings in this structure.
9757%
cristy3ed852e2009-09-05 21:47:34 +00009758*/
cristybcbda3f2011-09-03 13:01:22 +00009759MagickPrivate Image *XImportImage(const ImageInfo *image_info,
cristya0dc96a2011-12-19 23:58:54 +00009760 XImportInfo *ximage_info,ExceptionInfo *exception)
cristy3ed852e2009-09-05 21:47:34 +00009761{
9762 assert(image_info != (const ImageInfo *) NULL);
9763 assert(image_info->signature == MagickSignature);
9764 if (image_info->debug != MagickFalse)
9765 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
9766 image_info->filename);
9767 assert(ximage_info != (XImportInfo *) NULL);
cristya0dc96a2011-12-19 23:58:54 +00009768 assert(exception != (ExceptionInfo *) NULL);
9769 assert(exception->signature == MagickSignature);
cristy3ed852e2009-09-05 21:47:34 +00009770 return((Image *) NULL);
9771}
9772#endif
9773
9774/*
9775%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9776% %
9777% %
9778% %
cristy576974e2009-10-25 20:45:31 +00009779+ X C o m p o n e n t G e n e s i s %
9780% %
9781% %
9782% %
9783%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9784%
9785% XComponentGenesis() instantiates the X component.
9786%
9787% The format of the XComponentGenesis method is:
9788%
9789% MagickBooleanType XComponentGenesis(void)
9790%
9791*/
cristy5ff4eaf2011-09-03 01:38:02 +00009792MagickPrivate MagickBooleanType XComponentGenesis(void)
cristy576974e2009-10-25 20:45:31 +00009793{
9794 return(MagickTrue);
9795}
9796
9797/*
9798%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9799% %
9800% %
9801% %
cristy3ed852e2009-09-05 21:47:34 +00009802% X G e t I m p o r t I n f o %
9803% %
9804% %
9805% %
9806%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9807%
9808% XGetImportInfo() initializes the XImportInfo structure.
9809%
9810% The format of the XGetImportInfo method is:
9811%
9812% void XGetImportInfo(XImportInfo *ximage_info)
9813%
9814% A description of each parameter follows:
9815%
9816% o ximage_info: Specifies a pointer to an ImageInfo structure.
9817%
9818*/
9819MagickExport void XGetImportInfo(XImportInfo *ximage_info)
9820{
9821 assert(ximage_info != (XImportInfo *) NULL);
9822 ximage_info->frame=MagickFalse;
9823 ximage_info->borders=MagickFalse;
9824 ximage_info->screen=MagickFalse;
9825 ximage_info->descend=MagickTrue;
9826 ximage_info->silent=MagickFalse;
9827}