blob: fdde2b5f76d337f7715ab9b609c5d629761de73d [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);
cristy5f257b22012-03-07 00:27:29 +00004545 composite_image=DestroyImage(composite_image);
cristy3ed852e2009-09-05 21:47:34 +00004546 }
4547 /*
4548 Relinquish resources.
4549 */
4550 while (colormap_info != (ColormapInfo *) NULL)
4551 {
4552 next=colormap_info->next;
cristye941a752011-10-15 01:52:48 +00004553 colormap_info->colors=(XColor *) RelinquishMagickMemory(
4554 colormap_info->colors);
cristy3ed852e2009-09-05 21:47:34 +00004555 colormap_info=(ColormapInfo *) RelinquishMagickMemory(colormap_info);
4556 colormap_info=next;
4557 }
4558 /*
4559 Relinquish resources and restore initial state.
4560 */
4561 window_info=(WindowInfo *) RelinquishMagickMemory(window_info);
4562 max_windows=0;
4563 number_windows=0;
4564 colormap_info=(ColormapInfo *) NULL;
4565 return(image);
4566 }
4567 return((Image *) NULL);
4568}
4569
4570/*
4571%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4572% %
4573% %
4574% %
4575% X G e t W i n d o w I n f o %
4576% %
4577% %
4578% %
4579%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4580%
4581% XGetWindowInfo() initializes the XWindowInfo structure.
4582%
4583% The format of the XGetWindowInfo method is:
4584%
4585% void XGetWindowInfo(Display *display,XVisualInfo *visual_info,
4586% XStandardColormap *map_info,XPixelInfo *pixel,XFontStruct *font_info,
4587% XResourceInfo *resource_info,XWindowInfo *window)
4588% resource_info,window)
4589%
4590% A description of each parameter follows:
4591%
4592% o display: Specifies a connection to an X server; returned from
4593% XOpenDisplay.
4594%
4595% o visual_info: Specifies a pointer to a X11 XVisualInfo structure;
4596% returned from XGetVisualInfo.
4597%
4598% o map_info: If map_type is specified, this structure is initialized
4599% with info from the Standard Colormap.
4600%
4601% o pixel: Specifies a pointer to a XPixelInfo structure.
4602%
4603% o font_info: Specifies a pointer to a XFontStruct structure.
4604%
4605% o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
4606%
4607*/
cristybcbda3f2011-09-03 13:01:22 +00004608MagickPrivate void XGetWindowInfo(Display *display,XVisualInfo *visual_info,
cristy3ed852e2009-09-05 21:47:34 +00004609 XStandardColormap *map_info,XPixelInfo *pixel,XFontStruct *font_info,
4610 XResourceInfo *resource_info,XWindowInfo *window)
4611{
4612 /*
4613 Initialize window info.
4614 */
4615 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
4616 assert(display != (Display *) NULL);
4617 assert(visual_info != (XVisualInfo *) NULL);
4618 assert(map_info != (XStandardColormap *) NULL);
4619 assert(pixel != (XPixelInfo *) NULL);
4620 assert(resource_info != (XResourceInfo *) NULL);
4621 assert(window != (XWindowInfo *) NULL);
4622 if (window->id != (Window) NULL)
4623 {
4624 if (window->cursor != (Cursor) NULL)
4625 (void) XFreeCursor(display,window->cursor);
4626 if (window->busy_cursor != (Cursor) NULL)
4627 (void) XFreeCursor(display,window->busy_cursor);
4628 if (window->highlight_stipple != (Pixmap) NULL)
4629 (void) XFreePixmap(display,window->highlight_stipple);
4630 if (window->shadow_stipple != (Pixmap) NULL)
4631 (void) XFreePixmap(display,window->shadow_stipple);
4632 if (window->name == (char *) NULL)
4633 window->name=AcquireString("");
4634 if (window->icon_name == (char *) NULL)
4635 window->icon_name=AcquireString("");
4636 }
4637 else
4638 {
4639 /*
4640 Initialize these attributes just once.
4641 */
4642 window->id=(Window) NULL;
4643 if (window->name == (char *) NULL)
4644 window->name=AcquireString("");
4645 if (window->icon_name == (char *) NULL)
4646 window->icon_name=AcquireString("");
4647 window->x=XDisplayWidth(display,visual_info->screen) >> 1;
4648 window->y=XDisplayWidth(display,visual_info->screen) >> 1;
4649 window->ximage=(XImage *) NULL;
4650 window->matte_image=(XImage *) NULL;
4651 window->pixmap=(Pixmap) NULL;
4652 window->matte_pixmap=(Pixmap) NULL;
4653 window->mapped=MagickFalse;
4654 window->stasis=MagickFalse;
4655 window->shared_memory=MagickTrue;
4656 window->segment_info=(void *) NULL;
4657#if defined(MAGICKCORE_HAVE_SHARED_MEMORY)
4658 {
4659 XShmSegmentInfo
4660 *segment_info;
4661
4662 if (window->segment_info == (void *) NULL)
4663 window->segment_info=AcquireQuantumMemory(2,sizeof(*segment_info));
4664 segment_info=(XShmSegmentInfo *) window->segment_info;
4665 segment_info[0].shmid=(-1);
4666 segment_info[0].shmaddr=(char *) NULL;
4667 segment_info[1].shmid=(-1);
4668 segment_info[1].shmaddr=(char *) NULL;
4669 }
4670#endif
4671 }
4672 /*
4673 Initialize these attributes every time function is called.
4674 */
4675 window->screen=visual_info->screen;
4676 window->root=XRootWindow(display,visual_info->screen);
4677 window->visual=visual_info->visual;
4678 window->storage_class=(unsigned int) visual_info->klass;
4679 window->depth=(unsigned int) visual_info->depth;
4680 window->visual_info=visual_info;
4681 window->map_info=map_info;
4682 window->pixel_info=pixel;
4683 window->font_info=font_info;
4684 window->cursor=XCreateFontCursor(display,XC_left_ptr);
4685 window->busy_cursor=XCreateFontCursor(display,XC_watch);
4686 window->geometry=(char *) NULL;
4687 window->icon_geometry=(char *) NULL;
4688 if (resource_info->icon_geometry != (char *) NULL)
4689 (void) CloneString(&window->icon_geometry,resource_info->icon_geometry);
4690 window->crop_geometry=(char *) NULL;
cristybb503372010-05-27 20:51:26 +00004691 window->flags=(size_t) PSize;
cristy3ed852e2009-09-05 21:47:34 +00004692 window->width=1;
4693 window->height=1;
4694 window->min_width=1;
4695 window->min_height=1;
4696 window->width_inc=1;
4697 window->height_inc=1;
4698 window->border_width=resource_info->border_width;
4699 window->annotate_context=pixel->annotate_context;
4700 window->highlight_context=pixel->highlight_context;
4701 window->widget_context=pixel->widget_context;
4702 window->shadow_stipple=(Pixmap) NULL;
4703 window->highlight_stipple=(Pixmap) NULL;
4704 window->use_pixmap=MagickTrue;
4705 window->immutable=MagickFalse;
4706 window->shape=MagickFalse;
4707 window->data=0;
cristyc57f6942010-11-12 01:47:39 +00004708 window->mask=(int) (CWBackingStore | CWBackPixel | CWBackPixmap |
cristy3ed852e2009-09-05 21:47:34 +00004709 CWBitGravity | CWBorderPixel | CWColormap | CWCursor | CWDontPropagate |
4710 CWEventMask | CWOverrideRedirect | CWSaveUnder | CWWinGravity);
4711 window->attributes.background_pixel=pixel->background_color.pixel;
4712 window->attributes.background_pixmap=(Pixmap) NULL;
4713 window->attributes.bit_gravity=ForgetGravity;
4714 window->attributes.backing_store=WhenMapped;
4715 window->attributes.save_under=MagickTrue;
4716 window->attributes.border_pixel=pixel->border_color.pixel;
4717 window->attributes.colormap=map_info->colormap;
4718 window->attributes.cursor=window->cursor;
4719 window->attributes.do_not_propagate_mask=NoEventMask;
4720 window->attributes.event_mask=NoEventMask;
4721 window->attributes.override_redirect=MagickFalse;
4722 window->attributes.win_gravity=NorthWestGravity;
4723 window->orphan=MagickFalse;
4724}
4725
4726/*
4727%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4728% %
4729% %
4730% %
4731% X H i g h l i g h t E l l i p s e %
4732% %
4733% %
4734% %
4735%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4736%
4737% XHighlightEllipse() puts a border on the X server around a region defined by
4738% highlight_info.
4739%
4740% The format of the XHighlightEllipse method is:
4741%
4742% void XHighlightEllipse(Display *display,Window window,
4743% GC annotate_context,const RectangleInfo *highlight_info)
4744%
4745% A description of each parameter follows:
4746%
4747% o display: Specifies a connection to an X server; returned from
4748% XOpenDisplay.
4749%
4750% o window: Specifies a pointer to a Window structure.
4751%
4752% o annotate_context: Specifies a pointer to a GC structure.
4753%
4754% o highlight_info: Specifies a pointer to a RectangleInfo structure. It
4755% contains the extents of any highlighting rectangle.
4756%
4757*/
cristybcbda3f2011-09-03 13:01:22 +00004758MagickPrivate void XHighlightEllipse(Display *display,Window window,
cristy3ed852e2009-09-05 21:47:34 +00004759 GC annotate_context,const RectangleInfo *highlight_info)
4760{
4761 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
4762 assert(display != (Display *) NULL);
4763 assert(window != (Window) NULL);
4764 assert(annotate_context != (GC) NULL);
4765 assert(highlight_info != (RectangleInfo *) NULL);
4766 if ((highlight_info->width < 4) || (highlight_info->height < 4))
4767 return;
4768 (void) XDrawArc(display,window,annotate_context,(int) highlight_info->x,
4769 (int) highlight_info->y,(unsigned int) highlight_info->width-1,
4770 (unsigned int) highlight_info->height-1,0,360*64);
4771 (void) XDrawArc(display,window,annotate_context,(int) highlight_info->x+1,
4772 (int) highlight_info->y+1,(unsigned int) highlight_info->width-3,
4773 (unsigned int) highlight_info->height-3,0,360*64);
4774}
4775
4776/*
4777%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4778% %
4779% %
4780% %
4781% X H i g h l i g h t L i n e %
4782% %
4783% %
4784% %
4785%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4786%
4787% XHighlightLine() puts a border on the X server around a region defined by
4788% highlight_info.
4789%
4790% The format of the XHighlightLine method is:
4791%
4792% void XHighlightLine(Display *display,Window window,GC annotate_context,
4793% const XSegment *highlight_info)
4794%
4795% A description of each parameter follows:
4796%
4797% o display: Specifies a connection to an X server; returned from
4798% XOpenDisplay.
4799%
4800% o window: Specifies a pointer to a Window structure.
4801%
4802% o annotate_context: Specifies a pointer to a GC structure.
4803%
4804% o highlight_info: Specifies a pointer to a RectangleInfo structure. It
4805% contains the extents of any highlighting rectangle.
4806%
4807*/
cristybcbda3f2011-09-03 13:01:22 +00004808MagickPrivate void XHighlightLine(Display *display,Window window,
cristy3ed852e2009-09-05 21:47:34 +00004809 GC annotate_context,const XSegment *highlight_info)
4810{
4811 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
4812 assert(display != (Display *) NULL);
4813 assert(window != (Window) NULL);
4814 assert(annotate_context != (GC) NULL);
4815 assert(highlight_info != (XSegment *) NULL);
4816 (void) XDrawLine(display,window,annotate_context,highlight_info->x1,
4817 highlight_info->y1,highlight_info->x2,highlight_info->y2);
4818}
4819
4820/*
4821%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4822% %
4823% %
4824% %
4825% X H i g h l i g h t R e c t a n g l e %
4826% %
4827% %
4828% %
4829%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4830%
4831% XHighlightRectangle() puts a border on the X server around a region defined
4832% by highlight_info.
4833%
4834% The format of the XHighlightRectangle method is:
4835%
4836% void XHighlightRectangle(Display *display,Window window,
4837% GC annotate_context,const RectangleInfo *highlight_info)
4838%
4839% A description of each parameter follows:
4840%
4841% o display: Specifies a connection to an X server; returned from
4842% XOpenDisplay.
4843%
4844% o window: Specifies a pointer to a Window structure.
4845%
4846% o annotate_context: Specifies a pointer to a GC structure.
4847%
4848% o highlight_info: Specifies a pointer to a RectangleInfo structure. It
4849% contains the extents of any highlighting rectangle.
4850%
4851*/
cristybcbda3f2011-09-03 13:01:22 +00004852MagickPrivate void XHighlightRectangle(Display *display,Window window,
cristy3ed852e2009-09-05 21:47:34 +00004853 GC annotate_context,const RectangleInfo *highlight_info)
4854{
4855 assert(display != (Display *) NULL);
4856 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
4857 assert(window != (Window) NULL);
4858 assert(annotate_context != (GC) NULL);
4859 assert(highlight_info != (RectangleInfo *) NULL);
4860 if ((highlight_info->width < 4) || (highlight_info->height < 4))
4861 return;
4862 (void) XDrawRectangle(display,window,annotate_context,(int) highlight_info->x,
4863 (int) highlight_info->y,(unsigned int) highlight_info->width-1,
4864 (unsigned int) highlight_info->height-1);
4865 (void) XDrawRectangle(display,window,annotate_context,(int) highlight_info->x+
4866 1,(int) highlight_info->y+1,(unsigned int) highlight_info->width-3,
4867 (unsigned int) highlight_info->height-3);
4868}
4869
4870/*
4871%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4872% %
4873% %
4874% %
4875% X I m p o r t I m a g e %
4876% %
4877% %
4878% %
4879%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4880%
4881% XImportImage() reads an image from an X window.
4882%
4883% The format of the XImportImage method is:
4884%
cristy6710d842011-10-20 23:23:00 +00004885% Image *XImportImage(const ImageInfo *image_info,XImportInfo *ximage_info,
4886% ExceptionInfo *exception)
cristy3ed852e2009-09-05 21:47:34 +00004887%
4888% A description of each parameter follows:
4889%
4890% o image_info: the image info.
4891%
4892% o ximage_info: Specifies a pointer to an XImportInfo structure.
4893%
cristy6710d842011-10-20 23:23:00 +00004894% o exception: return any errors or warnings in this structure.
4895%
cristy3ed852e2009-09-05 21:47:34 +00004896*/
4897MagickExport Image *XImportImage(const ImageInfo *image_info,
cristy6710d842011-10-20 23:23:00 +00004898 XImportInfo *ximage_info,ExceptionInfo *exception)
cristy3ed852e2009-09-05 21:47:34 +00004899{
4900 Colormap
4901 *colormaps;
4902
4903 Display
4904 *display;
4905
4906 Image
4907 *image;
4908
4909 int
4910 number_colormaps,
4911 number_windows,
4912 x;
4913
4914 RectangleInfo
4915 crop_info;
4916
4917 Status
4918 status;
4919
4920 Window
4921 *children,
4922 client,
4923 prior_target,
4924 root,
4925 target;
4926
4927 XTextProperty
4928 window_name;
4929
4930 /*
4931 Open X server connection.
4932 */
4933 assert(image_info != (const ImageInfo *) NULL);
4934 assert(image_info->signature == MagickSignature);
4935 if (image_info->debug != MagickFalse)
4936 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
4937 image_info->filename);
4938 assert(ximage_info != (XImportInfo *) NULL);
4939 display=XOpenDisplay(image_info->server_name);
4940 if (display == (Display *) NULL)
4941 {
4942 ThrowXWindowFatalException(XServerError,"UnableToOpenXServer",
4943 XDisplayName(image_info->server_name));
4944 return((Image *) NULL);
4945 }
4946 /*
4947 Set our forgiving exception handler.
4948 */
4949 (void) XSetErrorHandler(XError);
4950 /*
4951 Select target window.
4952 */
4953 crop_info.x=0;
4954 crop_info.y=0;
4955 crop_info.width=0;
4956 crop_info.height=0;
4957 root=XRootWindow(display,XDefaultScreen(display));
4958 target=(Window) NULL;
4959 if ((image_info->filename != (char *) NULL) &&
4960 (*image_info->filename != '\0'))
4961 {
4962 if (LocaleCompare(image_info->filename,"root") == 0)
4963 target=root;
4964 else
4965 {
4966 /*
4967 Select window by ID or name.
4968 */
4969 if (isdigit((unsigned char) *image_info->filename) != 0)
4970 target=XWindowByID(display,root,(Window)
4971 strtol(image_info->filename,(char **) NULL,0));
4972 if (target == (Window) NULL)
4973 target=XWindowByName(display,root,image_info->filename);
4974 if (target == (Window) NULL)
4975 ThrowXWindowFatalException(XServerError,
4976 "NoWindowWithSpecifiedIDExists",image_info->filename);
4977 }
4978 }
4979 /*
4980 If target window is not defined, interactively select one.
4981 */
4982 prior_target=target;
4983 if (target == (Window) NULL)
4984 target=XSelectWindow(display,&crop_info);
4985 if (target == (Window) NULL)
4986 ThrowXWindowFatalException(XServerError,"UnableToReadXWindowImage",
4987 image_info->filename);
4988 client=target; /* obsolete */
4989 if (target != root)
4990 {
4991 unsigned int
4992 d;
4993
4994 status=XGetGeometry(display,target,&root,&x,&x,&d,&d,&d,&d);
4995 if (status != False)
4996 {
4997 for ( ; ; )
4998 {
4999 Window
5000 parent;
5001
5002 /*
5003 Find window manager frame.
5004 */
5005 status=XQueryTree(display,target,&root,&parent,&children,&d);
5006 if ((status != False) && (children != (Window *) NULL))
5007 (void) XFree((char *) children);
5008 if ((status == False) || (parent == (Window) NULL) ||
5009 (parent == root))
5010 break;
5011 target=parent;
5012 }
5013 /*
5014 Get client window.
5015 */
5016 client=XClientWindow(display,target);
5017 if (ximage_info->frame == MagickFalse)
5018 target=client;
5019 if ((ximage_info->frame == MagickFalse) &&
5020 (prior_target != MagickFalse))
5021 target=prior_target;
cristy3ed852e2009-09-05 21:47:34 +00005022 }
5023 }
5024 if (ximage_info->screen)
5025 {
5026 int
5027 y;
5028
5029 Window
5030 child;
5031
5032 XWindowAttributes
5033 window_attributes;
5034
5035 /*
5036 Obtain window image directly from screen.
5037 */
5038 status=XGetWindowAttributes(display,target,&window_attributes);
5039 if (status == False)
5040 {
5041 ThrowXWindowFatalException(XServerError,
5042 "UnableToReadXWindowAttributes",image_info->filename);
5043 (void) XCloseDisplay(display);
5044 return((Image *) NULL);
5045 }
5046 (void) XTranslateCoordinates(display,target,root,0,0,&x,&y,&child);
cristyc57f6942010-11-12 01:47:39 +00005047 crop_info.x=(ssize_t) x;
5048 crop_info.y=(ssize_t) y;
cristybb503372010-05-27 20:51:26 +00005049 crop_info.width=(size_t) window_attributes.width;
5050 crop_info.height=(size_t) window_attributes.height;
cristy553743c2010-03-03 15:04:17 +00005051 if (ximage_info->borders != 0)
cristy3ed852e2009-09-05 21:47:34 +00005052 {
5053 /*
5054 Include border in image.
5055 */
5056 crop_info.x-=window_attributes.border_width;
5057 crop_info.y-=window_attributes.border_width;
5058 crop_info.width+=window_attributes.border_width << 1;
5059 crop_info.height+=window_attributes.border_width << 1;
5060 }
5061 target=root;
5062 }
5063 /*
5064 If WM_COLORMAP_WINDOWS property is set or multiple colormaps, descend.
5065 */
5066 number_windows=0;
5067 status=XGetWMColormapWindows(display,target,&children,&number_windows);
5068 if ((status == True) && (number_windows > 0))
5069 {
5070 ximage_info->descend=MagickTrue;
5071 (void) XFree ((char *) children);
5072 }
5073 colormaps=XListInstalledColormaps(display,target,&number_colormaps);
5074 if (number_colormaps > 0)
5075 {
5076 if (number_colormaps > 1)
5077 ximage_info->descend=MagickTrue;
5078 (void) XFree((char *) colormaps);
5079 }
5080 /*
5081 Alert the user not to alter the screen.
5082 */
5083 if (ximage_info->silent == MagickFalse)
5084 (void) XBell(display,0);
5085 /*
5086 Get image by window id.
5087 */
5088 (void) XGrabServer(display);
5089 image=XGetWindowImage(display,target,ximage_info->borders,
cristy6710d842011-10-20 23:23:00 +00005090 ximage_info->descend ? 1U : 0U,exception);
cristy3ed852e2009-09-05 21:47:34 +00005091 (void) XUngrabServer(display);
5092 if (image == (Image *) NULL)
5093 ThrowXWindowFatalException(XServerError,"UnableToReadXWindowImage",
5094 image_info->filename)
5095 else
5096 {
5097 (void) CopyMagickString(image->filename,image_info->filename,
5098 MaxTextExtent);
5099 if ((crop_info.width != 0) && (crop_info.height != 0))
5100 {
5101 Image
5102 *clone_image,
5103 *crop_image;
5104
5105 /*
5106 Crop image as defined by the cropping rectangle.
5107 */
cristy6710d842011-10-20 23:23:00 +00005108 clone_image=CloneImage(image,0,0,MagickTrue,exception);
cristy3ed852e2009-09-05 21:47:34 +00005109 if (clone_image != (Image *) NULL)
5110 {
cristy6710d842011-10-20 23:23:00 +00005111 crop_image=CropImage(clone_image,&crop_info,exception);
cristy3ed852e2009-09-05 21:47:34 +00005112 if (crop_image != (Image *) NULL)
5113 {
5114 image=DestroyImage(image);
5115 image=crop_image;
5116 }
5117 }
5118 }
5119 status=XGetWMName(display,target,&window_name);
5120 if (status == True)
5121 {
5122 if ((image_info->filename != (char *) NULL) &&
5123 (*image_info->filename == '\0'))
5124 (void) CopyMagickString(image->filename,(char *) window_name.value,
5125 (size_t) window_name.nitems+1);
5126 (void) XFree((void *) window_name.value);
5127 }
5128 }
5129 if (ximage_info->silent == MagickFalse)
5130 {
5131 /*
5132 Alert the user we're done.
5133 */
5134 (void) XBell(display,0);
5135 (void) XBell(display,0);
5136 }
5137 (void) XCloseDisplay(display);
5138 return(image);
5139}
5140
5141/*
5142%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5143% %
5144% %
5145% %
5146% X I n i t i a l i z e W i n d o w s %
5147% %
5148% %
5149% %
5150%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5151%
5152% XInitializeWindows() initializes the XWindows structure.
5153%
5154% The format of the XInitializeWindows method is:
5155%
5156% XWindows *XInitializeWindows(Display *display,
5157% XResourceInfo *resource_info)
5158%
5159% A description of each parameter follows:
5160%
5161% o windows: XInitializeWindows returns a pointer to a XWindows structure.
5162%
5163% o display: Specifies a connection to an X server; returned from
5164% XOpenDisplay.
5165%
5166% o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
5167%
5168*/
cristybcbda3f2011-09-03 13:01:22 +00005169MagickPrivate XWindows *XInitializeWindows(Display *display,
cristy3ed852e2009-09-05 21:47:34 +00005170 XResourceInfo *resource_info)
5171{
5172 Window
5173 root_window;
5174
5175 XWindows
5176 *windows;
5177
5178 /*
5179 Allocate windows structure.
5180 */
cristy73bd4a52010-10-05 11:24:23 +00005181 windows=(XWindows *) AcquireMagickMemory(sizeof(*windows));
cristy3ed852e2009-09-05 21:47:34 +00005182 if (windows == (XWindows *) NULL)
5183 {
5184 ThrowXWindowFatalException(XServerFatalError,"MemoryAllocationFailed",
5185 "...");
5186 return((XWindows *) NULL);
5187 }
5188 (void) ResetMagickMemory(windows,0,sizeof(*windows));
5189 windows->pixel_info=(XPixelInfo *) AcquireMagickMemory(
5190 sizeof(*windows->pixel_info));
5191 windows->icon_pixel=(XPixelInfo *) AcquireMagickMemory(
5192 sizeof(*windows->icon_pixel));
5193 windows->icon_resources=(XResourceInfo *) AcquireMagickMemory(
5194 sizeof(*windows->icon_resources));
5195 if ((windows->pixel_info == (XPixelInfo *) NULL) ||
5196 (windows->icon_pixel == (XPixelInfo *) NULL) ||
5197 (windows->icon_resources == (XResourceInfo *) NULL))
5198 {
5199 ThrowXWindowFatalException(XServerFatalError,"MemoryAllocationFailed",
5200 "...");
5201 return((XWindows *) NULL);
5202 }
5203 /*
5204 Initialize windows structure.
5205 */
5206 windows->display=display;
5207 windows->wm_protocols=XInternAtom(display,"WM_PROTOCOLS",MagickFalse);
5208 windows->wm_delete_window=XInternAtom(display,"WM_DELETE_WINDOW",MagickFalse);
5209 windows->wm_take_focus=XInternAtom(display,"WM_TAKE_FOCUS",MagickFalse);
5210 windows->im_protocols=XInternAtom(display,"IM_PROTOCOLS",MagickFalse);
5211 windows->im_remote_command=
5212 XInternAtom(display,"IM_REMOTE_COMMAND",MagickFalse);
5213 windows->im_update_widget=XInternAtom(display,"IM_UPDATE_WIDGET",MagickFalse);
5214 windows->im_update_colormap=
5215 XInternAtom(display,"IM_UPDATE_COLORMAP",MagickFalse);
5216 windows->im_former_image=XInternAtom(display,"IM_FORMER_IMAGE",MagickFalse);
5217 windows->im_next_image=XInternAtom(display,"IM_NEXT_IMAGE",MagickFalse);
5218 windows->im_retain_colors=XInternAtom(display,"IM_RETAIN_COLORS",MagickFalse);
5219 windows->im_exit=XInternAtom(display,"IM_EXIT",MagickFalse);
5220 windows->dnd_protocols=XInternAtom(display,"DndProtocol",MagickFalse);
cristy0157aea2010-04-24 21:12:18 +00005221#if defined(MAGICKCORE_WINDOWS_SUPPORT)
cristy3ed852e2009-09-05 21:47:34 +00005222 (void) XSynchronize(display,IsWindows95());
5223#endif
5224 if (IsEventLogging())
5225 {
5226 (void) XSynchronize(display,MagickTrue);
5227 (void) LogMagickEvent(X11Event,GetMagickModule(),"Version: %s",
cristybb503372010-05-27 20:51:26 +00005228 GetMagickVersion((size_t *) NULL));
cristy3ed852e2009-09-05 21:47:34 +00005229 (void) LogMagickEvent(X11Event,GetMagickModule(),"Protocols:");
5230 (void) LogMagickEvent(X11Event,GetMagickModule(),
5231 " Window Manager: 0x%lx",windows->wm_protocols);
5232 (void) LogMagickEvent(X11Event,GetMagickModule(),
5233 " delete window: 0x%lx",windows->wm_delete_window);
5234 (void) LogMagickEvent(X11Event,GetMagickModule()," take focus: 0x%lx",
5235 windows->wm_take_focus);
5236 (void) LogMagickEvent(X11Event,GetMagickModule()," ImageMagick: 0x%lx",
5237 windows->im_protocols);
5238 (void) LogMagickEvent(X11Event,GetMagickModule(),
5239 " remote command: 0x%lx",windows->im_remote_command);
5240 (void) LogMagickEvent(X11Event,GetMagickModule(),
5241 " update widget: 0x%lx",windows->im_update_widget);
5242 (void) LogMagickEvent(X11Event,GetMagickModule(),
5243 " update colormap: 0x%lx",windows->im_update_colormap);
5244 (void) LogMagickEvent(X11Event,GetMagickModule(),
5245 " former image: 0x%lx",windows->im_former_image);
5246 (void) LogMagickEvent(X11Event,GetMagickModule()," next image: 0x%lx",
5247 windows->im_next_image);
5248 (void) LogMagickEvent(X11Event,GetMagickModule(),
5249 " retain colors: 0x%lx",windows->im_retain_colors);
5250 (void) LogMagickEvent(X11Event,GetMagickModule()," exit: 0x%lx",
5251 windows->im_exit);
5252 (void) LogMagickEvent(X11Event,GetMagickModule()," Drag and Drop: 0x%lx",
5253 windows->dnd_protocols);
5254 }
5255 /*
5256 Allocate standard colormap.
5257 */
5258 windows->map_info=XAllocStandardColormap();
5259 windows->icon_map=XAllocStandardColormap();
5260 if ((windows->map_info == (XStandardColormap *) NULL) ||
5261 (windows->icon_map == (XStandardColormap *) NULL))
5262 ThrowXWindowFatalException(ResourceLimitFatalError,
5263 "MemoryAllocationFailed","...");
5264 windows->map_info->colormap=(Colormap) NULL;
5265 windows->icon_map->colormap=(Colormap) NULL;
cristyf2faecf2010-05-28 19:19:36 +00005266 windows->pixel_info->pixels=(unsigned long *) NULL;
cristy3ed852e2009-09-05 21:47:34 +00005267 windows->pixel_info->annotate_context=(GC) NULL;
5268 windows->pixel_info->highlight_context=(GC) NULL;
5269 windows->pixel_info->widget_context=(GC) NULL;
5270 windows->font_info=(XFontStruct *) NULL;
5271 windows->icon_pixel->annotate_context=(GC) NULL;
cristyf2faecf2010-05-28 19:19:36 +00005272 windows->icon_pixel->pixels=(unsigned long *) NULL;
cristy3ed852e2009-09-05 21:47:34 +00005273 /*
5274 Allocate visual.
5275 */
5276 *windows->icon_resources=(*resource_info);
5277 windows->icon_resources->visual_type=(char *) "default";
5278 windows->icon_resources->colormap=SharedColormap;
5279 windows->visual_info=
5280 XBestVisualInfo(display,windows->map_info,resource_info);
5281 windows->icon_visual=
5282 XBestVisualInfo(display,windows->icon_map,windows->icon_resources);
5283 if ((windows->visual_info == (XVisualInfo *) NULL) ||
5284 (windows->icon_visual == (XVisualInfo *) NULL))
5285 ThrowXWindowFatalException(XServerFatalError,"UnableToGetVisual",
5286 resource_info->visual_type);
5287 if (IsEventLogging())
5288 {
5289 (void) LogMagickEvent(X11Event,GetMagickModule(),"Visual:");
5290 (void) LogMagickEvent(X11Event,GetMagickModule()," visual id: 0x%lx",
5291 windows->visual_info->visualid);
5292 (void) LogMagickEvent(X11Event,GetMagickModule()," class: %s",
5293 XVisualClassName(windows->visual_info->klass));
5294 (void) LogMagickEvent(X11Event,GetMagickModule()," depth: %d planes",
5295 windows->visual_info->depth);
5296 (void) LogMagickEvent(X11Event,GetMagickModule(),
5297 " size of colormap: %d entries",windows->visual_info->colormap_size);
5298 (void) LogMagickEvent(X11Event,GetMagickModule(),
5299 " red, green, blue masks: 0x%lx 0x%lx 0x%lx",
5300 windows->visual_info->red_mask,windows->visual_info->green_mask,
5301 windows->visual_info->blue_mask);
5302 (void) LogMagickEvent(X11Event,GetMagickModule(),
5303 " significant bits in color: %d bits",
5304 windows->visual_info->bits_per_rgb);
5305 }
5306 /*
5307 Allocate class and manager hints.
5308 */
5309 windows->class_hints=XAllocClassHint();
5310 windows->manager_hints=XAllocWMHints();
5311 if ((windows->class_hints == (XClassHint *) NULL) ||
5312 (windows->manager_hints == (XWMHints *) NULL))
5313 ThrowXWindowFatalException(ResourceLimitFatalError,
5314 "MemoryAllocationFailed","...");
5315 /*
5316 Determine group leader if we have one.
5317 */
5318 root_window=XRootWindow(display,windows->visual_info->screen);
5319 windows->group_leader.id=(Window) NULL;
5320 if (resource_info->window_group != (char *) NULL)
5321 {
5322 if (isdigit((unsigned char) *resource_info->window_group) != 0)
5323 windows->group_leader.id=XWindowByID(display,root_window,(Window)
5324 strtol((char *) resource_info->window_group,(char **) NULL,0));
5325 if (windows->group_leader.id == (Window) NULL)
5326 windows->group_leader.id=
5327 XWindowByName(display,root_window,resource_info->window_group);
5328 }
5329 return(windows);
5330}
5331
5332/*
5333%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5334% %
5335% %
5336% %
5337% X M a k e C u r s o r %
5338% %
5339% %
5340% %
5341%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5342%
5343% XMakeCursor() creates a crosshairs X11 cursor.
5344%
5345% The format of the XMakeCursor method is:
5346%
5347% Cursor XMakeCursor(Display *display,Window window,Colormap colormap,
5348% char *background_color,char *foreground_color)
5349%
5350% A description of each parameter follows:
5351%
5352% o display: Specifies a connection to an X server; returned from
5353% XOpenDisplay.
5354%
5355% o window: Specifies the ID of the window for which the cursor is
5356% assigned.
5357%
5358% o colormap: Specifies the ID of the colormap from which the background
5359% and foreground color will be retrieved.
5360%
5361% o background_color: Specifies the color to use for the cursor background.
5362%
5363% o foreground_color: Specifies the color to use for the cursor foreground.
5364%
5365*/
cristybcbda3f2011-09-03 13:01:22 +00005366MagickPrivate Cursor XMakeCursor(Display *display,Window window,
cristy3ed852e2009-09-05 21:47:34 +00005367 Colormap colormap,char *background_color,char *foreground_color)
5368{
5369#define scope_height 17
5370#define scope_x_hot 8
5371#define scope_y_hot 8
5372#define scope_width 17
5373
5374 static const unsigned char
5375 scope_bits[] =
5376 {
5377 0x80, 0x03, 0x00, 0x80, 0x02, 0x00, 0x80, 0x02, 0x00, 0x80, 0x02,
5378 0x00, 0x80, 0x02, 0x00, 0x80, 0x02, 0x00, 0x80, 0x02, 0x00, 0x7f,
5379 0xfc, 0x01, 0x01, 0x00, 0x01, 0x7f, 0xfc, 0x01, 0x80, 0x02, 0x00,
5380 0x80, 0x02, 0x00, 0x80, 0x02, 0x00, 0x80, 0x02, 0x00, 0x80, 0x02,
5381 0x00, 0x80, 0x02, 0x00, 0x80, 0x03, 0x00
5382 },
5383 scope_mask_bits[] =
5384 {
5385 0xc0, 0x07, 0x00, 0xc0, 0x07, 0x00, 0xc0, 0x06, 0x00, 0xc0, 0x06,
5386 0x00, 0xc0, 0x06, 0x00, 0xc0, 0x06, 0x00, 0xff, 0xfe, 0x01, 0x7f,
5387 0xfc, 0x01, 0x03, 0x80, 0x01, 0x7f, 0xfc, 0x01, 0xff, 0xfe, 0x01,
5388 0xc0, 0x06, 0x00, 0xc0, 0x06, 0x00, 0xc0, 0x06, 0x00, 0xc0, 0x06,
5389 0x00, 0xc0, 0x07, 0x00, 0xc0, 0x07, 0x00
5390 };
5391
5392 Cursor
5393 cursor;
5394
5395 Pixmap
5396 mask,
5397 source;
5398
5399 XColor
5400 background,
5401 foreground;
5402
5403 assert(display != (Display *) NULL);
5404 assert(window != (Window) NULL);
5405 assert(colormap != (Colormap) NULL);
5406 assert(background_color != (char *) NULL);
5407 assert(foreground_color != (char *) NULL);
5408 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",background_color);
5409 source=XCreateBitmapFromData(display,window,(char *) scope_bits,scope_width,
5410 scope_height);
5411 mask=XCreateBitmapFromData(display,window,(char *) scope_mask_bits,
5412 scope_width,scope_height);
5413 if ((source == (Pixmap) NULL) || (mask == (Pixmap) NULL))
5414 {
5415 ThrowXWindowFatalException(XServerError,"UnableToCreatePixmap","...");
5416 return((Cursor) NULL);
5417 }
5418 (void) XParseColor(display,colormap,background_color,&background);
5419 (void) XParseColor(display,colormap,foreground_color,&foreground);
5420 cursor=XCreatePixmapCursor(display,source,mask,&foreground,&background,
5421 scope_x_hot,scope_y_hot);
5422 (void) XFreePixmap(display,source);
5423 (void) XFreePixmap(display,mask);
5424 return(cursor);
5425}
5426
5427/*
5428%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5429% %
5430% %
5431% %
5432% X M a k e I m a g e %
5433% %
5434% %
5435% %
5436%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5437%
5438% XMakeImage() creates an X11 image. If the image size differs from the X11
5439% image size, the image is first resized.
5440%
5441% The format of the XMakeImage method is:
5442%
5443% MagickBooleanType XMakeImage(Display *display,
5444% const XResourceInfo *resource_info,XWindowInfo *window,Image *image,
cristy051718b2011-08-28 22:49:25 +00005445% unsigned int width,unsigned int height,ExceptionInfo *exception)
cristy3ed852e2009-09-05 21:47:34 +00005446%
5447% A description of each parameter follows:
5448%
5449% o display: Specifies a connection to an X server; returned from
5450% XOpenDisplay.
5451%
5452% o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
5453%
5454% o window: Specifies a pointer to a XWindowInfo structure.
5455%
5456% o image: the image.
5457%
5458% o width: Specifies the width in pixels of the rectangular area to
5459% display.
5460%
5461% o height: Specifies the height in pixels of the rectangular area to
5462% display.
5463%
cristy051718b2011-08-28 22:49:25 +00005464% o exception: return any errors or warnings in this structure.
5465%
cristy3ed852e2009-09-05 21:47:34 +00005466*/
cristybcbda3f2011-09-03 13:01:22 +00005467MagickPrivate MagickBooleanType XMakeImage(Display *display,
cristy3ed852e2009-09-05 21:47:34 +00005468 const XResourceInfo *resource_info,XWindowInfo *window,Image *image,
cristy051718b2011-08-28 22:49:25 +00005469 unsigned int width,unsigned int height,ExceptionInfo *exception)
cristy3ed852e2009-09-05 21:47:34 +00005470{
5471#define CheckOverflowException(length,width,height) \
5472 (((height) != 0) && ((length)/((size_t) height) != ((size_t) width)))
5473
5474 int
5475 depth,
5476 format;
5477
5478 size_t
5479 length;
5480
5481 XImage
5482 *matte_image,
5483 *ximage;
5484
5485 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
5486 assert(display != (Display *) NULL);
5487 assert(resource_info != (XResourceInfo *) NULL);
5488 assert(window != (XWindowInfo *) NULL);
5489 assert(width != 0);
5490 assert(height != 0);
5491 if ((window->width == 0) || (window->height == 0))
5492 return(MagickFalse);
5493 /*
5494 Apply user transforms to the image.
5495 */
5496 (void) XCheckDefineCursor(display,window->id,window->busy_cursor);
5497 (void) XFlush(display);
5498 depth=(int) window->depth;
5499 if (window->destroy)
5500 window->image=DestroyImage(window->image);
5501 window->image=image;
5502 window->destroy=MagickFalse;
5503 if (window->image != (Image *) NULL)
5504 {
5505 if (window->crop_geometry != (char *) NULL)
5506 {
5507 Image
5508 *crop_image;
5509
5510 RectangleInfo
5511 crop_info;
5512
5513 /*
5514 Crop image.
5515 */
5516 window->image->page.x=0;
5517 window->image->page.y=0;
5518 (void) ParsePageGeometry(window->image,window->crop_geometry,
cristy6710d842011-10-20 23:23:00 +00005519 &crop_info,exception);
5520 crop_image=CropImage(window->image,&crop_info,exception);
cristy3ed852e2009-09-05 21:47:34 +00005521 if (crop_image != (Image *) NULL)
5522 {
5523 if (window->image != image)
5524 window->image=DestroyImage(window->image);
5525 window->image=crop_image;
5526 window->destroy=MagickTrue;
5527 }
5528 }
5529 if ((width != (unsigned int) window->image->columns) ||
5530 (height != (unsigned int) window->image->rows))
5531 {
5532 Image
5533 *resize_image;
5534
5535 /*
5536 Resize image.
5537 */
5538 resize_image=NewImageList();
5539 if (window->pixel_info->colors != 0)
cristy6710d842011-10-20 23:23:00 +00005540 resize_image=SampleImage(window->image,width,height,exception);
cristy3ed852e2009-09-05 21:47:34 +00005541 else
cristy6710d842011-10-20 23:23:00 +00005542 resize_image=ThumbnailImage(window->image,width,height,exception);
cristy3ed852e2009-09-05 21:47:34 +00005543 if (resize_image != (Image *) NULL)
5544 {
5545 if (window->image != image)
5546 window->image=DestroyImage(window->image);
5547 window->image=resize_image;
5548 window->destroy=MagickTrue;
5549 }
5550 }
5551 width=(unsigned int) window->image->columns;
cristybb503372010-05-27 20:51:26 +00005552 assert((size_t) width == window->image->columns);
cristy3ed852e2009-09-05 21:47:34 +00005553 height=(unsigned int) window->image->rows;
cristybb503372010-05-27 20:51:26 +00005554 assert((size_t) height == window->image->rows);
cristy3ed852e2009-09-05 21:47:34 +00005555 }
5556 /*
5557 Create X image.
5558 */
5559 ximage=(XImage *) NULL;
5560 format=(depth == 1) ? XYBitmap : ZPixmap;
5561#if defined(MAGICKCORE_HAVE_SHARED_MEMORY)
5562 if (window->shared_memory != MagickFalse)
5563 {
5564 XShmSegmentInfo
5565 *segment_info;
5566
5567 segment_info=(XShmSegmentInfo *) window->segment_info;
5568 segment_info[1].shmid=(-1);
5569 segment_info[1].shmaddr=(char *) NULL;
5570 ximage=XShmCreateImage(display,window->visual,(unsigned int) depth,format,
5571 (char *) NULL,&segment_info[1],width,height);
5572 if (ximage == (XImage *) NULL)
5573 window->shared_memory=MagickFalse;
5574 length=(size_t) ximage->bytes_per_line*ximage->height;
5575 if (CheckOverflowException(length,ximage->bytes_per_line,ximage->height))
5576 window->shared_memory=MagickFalse;
5577 if (window->shared_memory != MagickFalse)
5578 segment_info[1].shmid=shmget(IPC_PRIVATE,length,IPC_CREAT | 0777);
5579 if (window->shared_memory != MagickFalse)
5580 segment_info[1].shmaddr=(char *) shmat(segment_info[1].shmid,0,0);
5581 if (segment_info[1].shmid < 0)
5582 window->shared_memory=MagickFalse;
5583 if (window->shared_memory != MagickFalse)
5584 (void) shmctl(segment_info[1].shmid,IPC_RMID,0);
5585 else
5586 {
5587 if (ximage != (XImage *) NULL)
5588 XDestroyImage(ximage);
5589 ximage=(XImage *) NULL;
5590 if (segment_info[1].shmaddr)
5591 {
5592 (void) shmdt(segment_info[1].shmaddr);
5593 segment_info[1].shmaddr=(char *) NULL;
5594 }
5595 if (segment_info[1].shmid >= 0)
5596 {
5597 (void) shmctl(segment_info[1].shmid,IPC_RMID,0);
5598 segment_info[1].shmid=(-1);
5599 }
5600 }
5601 }
5602#endif
5603 /*
5604 Allocate X image pixel data.
5605 */
5606#if defined(MAGICKCORE_HAVE_SHARED_MEMORY)
5607 if (window->shared_memory)
5608 {
5609 Status
5610 status;
5611
5612 XShmSegmentInfo
5613 *segment_info;
5614
5615 (void) XSync(display,MagickFalse);
5616 xerror_alert=MagickFalse;
5617 segment_info=(XShmSegmentInfo *) window->segment_info;
5618 ximage->data=segment_info[1].shmaddr;
5619 segment_info[1].readOnly=MagickFalse;
5620 status=XShmAttach(display,&segment_info[1]);
5621 if (status != False)
5622 (void) XSync(display,MagickFalse);
5623 if ((status == False) || (xerror_alert != MagickFalse))
5624 {
5625 window->shared_memory=MagickFalse;
5626 if (status != False)
5627 XShmDetach(display,&segment_info[1]);
5628 if (ximage != (XImage *) NULL)
5629 {
5630 ximage->data=NULL;
5631 XDestroyImage(ximage);
5632 ximage=(XImage *) NULL;
5633 }
5634 if (segment_info[1].shmid >= 0)
5635 {
5636 if (segment_info[1].shmaddr != NULL)
5637 (void) shmdt(segment_info[1].shmaddr);
5638 (void) shmctl(segment_info[1].shmid,IPC_RMID,0);
5639 segment_info[1].shmid=(-1);
5640 segment_info[1].shmaddr=(char *) NULL;
5641 }
5642 }
5643 }
5644#endif
5645 if (window->shared_memory == MagickFalse)
5646 ximage=XCreateImage(display,window->visual,(unsigned int) depth,format,0,
5647 (char *) NULL,width,height,XBitmapPad(display),0);
5648 if (ximage == (XImage *) NULL)
5649 {
5650 /*
5651 Unable to create X image.
5652 */
5653 (void) XCheckDefineCursor(display,window->id,window->cursor);
5654 return(MagickFalse);
5655 }
5656 length=(size_t) ximage->bytes_per_line*ximage->height;
5657 if (IsEventLogging())
5658 {
5659 (void) LogMagickEvent(X11Event,GetMagickModule(),"XImage:");
5660 (void) LogMagickEvent(X11Event,GetMagickModule()," width, height: %dx%d",
5661 ximage->width,ximage->height);
5662 (void) LogMagickEvent(X11Event,GetMagickModule()," format: %d",
5663 ximage->format);
5664 (void) LogMagickEvent(X11Event,GetMagickModule()," byte order: %d",
5665 ximage->byte_order);
5666 (void) LogMagickEvent(X11Event,GetMagickModule(),
5667 " bitmap unit, bit order, pad: %d %d %d",ximage->bitmap_unit,
5668 ximage->bitmap_bit_order,ximage->bitmap_pad);
5669 (void) LogMagickEvent(X11Event,GetMagickModule()," depth: %d",
5670 ximage->depth);
5671 (void) LogMagickEvent(X11Event,GetMagickModule()," bytes per line: %d",
5672 ximage->bytes_per_line);
5673 (void) LogMagickEvent(X11Event,GetMagickModule()," bits per pixel: %d",
5674 ximage->bits_per_pixel);
5675 (void) LogMagickEvent(X11Event,GetMagickModule(),
5676 " red, green, blue masks: 0x%lx 0x%lx 0x%lx",ximage->red_mask,
5677 ximage->green_mask,ximage->blue_mask);
5678 }
5679 if (window->shared_memory == MagickFalse)
5680 {
5681 if (ximage->format != XYBitmap)
5682 ximage->data=(char *) AcquireQuantumMemory((size_t)
5683 ximage->bytes_per_line,(size_t) ximage->height);
5684 else
5685 ximage->data=(char *) AcquireQuantumMemory((size_t)
5686 ximage->bytes_per_line*ximage->depth,(size_t) ximage->height);
5687 }
5688 if (ximage->data == (char *) NULL)
5689 {
5690 /*
5691 Unable to allocate pixel data.
5692 */
5693 XDestroyImage(ximage);
5694 ximage=(XImage *) NULL;
5695 (void) XCheckDefineCursor(display,window->id,window->cursor);
5696 return(MagickFalse);
5697 }
5698 if (window->ximage != (XImage *) NULL)
5699 {
5700 /*
5701 Destroy previous X image.
5702 */
5703 length=(size_t) window->ximage->bytes_per_line*window->ximage->height;
5704#if defined(MAGICKCORE_HAVE_SHARED_MEMORY)
5705 if (window->segment_info != (XShmSegmentInfo *) NULL)
5706 {
5707 XShmSegmentInfo
5708 *segment_info;
5709
5710 segment_info=(XShmSegmentInfo *) window->segment_info;
5711 if (segment_info[0].shmid >= 0)
5712 {
5713 (void) XSync(display,MagickFalse);
5714 (void) XShmDetach(display,&segment_info[0]);
5715 (void) XSync(display,MagickFalse);
5716 if (segment_info[0].shmaddr != (char *) NULL)
5717 (void) shmdt(segment_info[0].shmaddr);
5718 (void) shmctl(segment_info[0].shmid,IPC_RMID,0);
5719 segment_info[0].shmid=(-1);
5720 segment_info[0].shmaddr=(char *) NULL;
5721 window->ximage->data=(char *) NULL;
5722 }
5723 }
5724#endif
5725 if (window->ximage->data != (char *) NULL)
5726 free(window->ximage->data);
5727 window->ximage->data=(char *) NULL;
5728 XDestroyImage(window->ximage);
5729 window->ximage=(XImage *) NULL;
5730 }
5731#if defined(MAGICKCORE_HAVE_SHARED_MEMORY)
5732 if (window->segment_info != (XShmSegmentInfo *) NULL)
5733 {
5734 XShmSegmentInfo
5735 *segment_info;
5736
5737 segment_info=(XShmSegmentInfo *) window->segment_info;
5738 segment_info[0]=segment_info[1];
5739 }
5740#endif
5741 window->ximage=ximage;
5742 matte_image=(XImage *) NULL;
5743 if ((window->shape != MagickFalse) && (window->image != (Image *) NULL))
5744 if ((window->image->matte != MagickFalse) &&
cristyc57f6942010-11-12 01:47:39 +00005745 ((int) width <= XDisplayWidth(display,window->screen)) &&
5746 ((int) height <= XDisplayHeight(display,window->screen)))
cristy3ed852e2009-09-05 21:47:34 +00005747 {
5748 /*
5749 Create matte image.
5750 */
5751 matte_image=XCreateImage(display,window->visual,1,XYBitmap,0,
5752 (char *) NULL,width,height,XBitmapPad(display),0);
5753 if (IsEventLogging())
5754 {
5755 (void) LogMagickEvent(X11Event,GetMagickModule(),"Matte Image:");
5756 (void) LogMagickEvent(X11Event,GetMagickModule(),
5757 " width, height: %dx%d",matte_image->width,matte_image->height);
5758 }
5759 if (matte_image != (XImage *) NULL)
5760 {
5761 /*
5762 Allocate matte image pixel data.
5763 */
5764 matte_image->data=(char *) AcquireQuantumMemory((size_t)
5765 matte_image->bytes_per_line*matte_image->depth,
5766 (size_t) matte_image->height);
5767 if (matte_image->data == (char *) NULL)
5768 {
5769 XDestroyImage(matte_image);
5770 matte_image=(XImage *) NULL;
5771 }
5772 }
5773 }
5774 if (window->matte_image != (XImage *) NULL)
5775 {
5776 /*
5777 Free matte image.
5778 */
5779 if (window->matte_image->data != (char *) NULL)
5780 free(window->matte_image->data);
5781 window->matte_image->data=(char *) NULL;
5782 XDestroyImage(window->matte_image);
5783 window->matte_image=(XImage *) NULL;
5784 }
5785 window->matte_image=matte_image;
5786 if (window->matte_pixmap != (Pixmap) NULL)
5787 {
5788 (void) XFreePixmap(display,window->matte_pixmap);
5789 window->matte_pixmap=(Pixmap) NULL;
5790#if defined(MAGICKCORE_HAVE_SHAPE)
5791 if (window->shape != MagickFalse)
5792 XShapeCombineMask(display,window->id,ShapeBounding,0,0,None,ShapeSet);
5793#endif
5794 }
5795 window->stasis=MagickFalse;
5796 /*
5797 Convert pixels to X image data.
5798 */
5799 if (window->image != (Image *) NULL)
5800 {
5801 if ((ximage->byte_order == LSBFirst) || ((ximage->format == XYBitmap) &&
5802 (ximage->bitmap_bit_order == LSBFirst)))
5803 XMakeImageLSBFirst(resource_info,window,window->image,ximage,
cristye941a752011-10-15 01:52:48 +00005804 matte_image,exception);
cristy3ed852e2009-09-05 21:47:34 +00005805 else
5806 XMakeImageMSBFirst(resource_info,window,window->image,ximage,
cristye941a752011-10-15 01:52:48 +00005807 matte_image,exception);
cristy3ed852e2009-09-05 21:47:34 +00005808 }
5809 if (window->matte_image != (XImage *) NULL)
5810 {
5811 /*
5812 Create matte pixmap.
5813 */
5814 window->matte_pixmap=XCreatePixmap(display,window->id,width,height,1);
5815 if (window->matte_pixmap != (Pixmap) NULL)
5816 {
5817 GC
5818 graphics_context;
5819
5820 XGCValues
5821 context_values;
5822
5823 /*
5824 Copy matte image to matte pixmap.
5825 */
cristy4c08aed2011-07-01 19:47:50 +00005826 context_values.background=0;
5827 context_values.foreground=1;
cristy3ed852e2009-09-05 21:47:34 +00005828 graphics_context=XCreateGC(display,window->matte_pixmap,
cristybb503372010-05-27 20:51:26 +00005829 (size_t) (GCBackground | GCForeground),&context_values);
cristy3ed852e2009-09-05 21:47:34 +00005830 (void) XPutImage(display,window->matte_pixmap,graphics_context,
5831 window->matte_image,0,0,0,0,width,height);
5832 (void) XFreeGC(display,graphics_context);
5833#if defined(MAGICKCORE_HAVE_SHAPE)
5834 if (window->shape != MagickFalse)
5835 XShapeCombineMask(display,window->id,ShapeBounding,0,0,
5836 window->matte_pixmap,ShapeSet);
5837#endif
5838 }
5839 }
5840 (void) XMakePixmap(display,resource_info,window);
5841 /*
5842 Restore cursor.
5843 */
5844 (void) XCheckDefineCursor(display,window->id,window->cursor);
5845 return(MagickTrue);
5846}
5847
5848/*
5849%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5850% %
5851% %
5852% %
5853+ X M a k e I m a g e L S B F i r s t %
5854% %
5855% %
5856% %
5857%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5858%
5859% XMakeImageLSBFirst() initializes the pixel data of an X11 Image. The X image
5860% pixels are copied in least-significant bit and byte first order. The
5861% server's scanline pad is respected. Rather than using one or two general
5862% cases, many special cases are found here to help speed up the image
5863% conversion.
5864%
5865% The format of the XMakeImageLSBFirst method is:
5866%
cristye941a752011-10-15 01:52:48 +00005867% void XMakeImageLSBFirst(Display *display,XWindows *windows,
5868% ExceptionInfo *exception)
cristy3ed852e2009-09-05 21:47:34 +00005869%
5870% A description of each parameter follows:
5871%
5872% o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
5873%
5874% o window: Specifies a pointer to a XWindowInfo structure.
5875%
5876% o image: the image.
5877%
5878% o ximage: Specifies a pointer to a XImage structure; returned from
5879% XCreateImage.
5880%
5881% o matte_image: Specifies a pointer to a XImage structure; returned from
5882% XCreateImage.
5883%
cristye941a752011-10-15 01:52:48 +00005884% o exception: return any errors or warnings in this structure.
5885%
cristy3ed852e2009-09-05 21:47:34 +00005886*/
5887static void XMakeImageLSBFirst(const XResourceInfo *resource_info,
cristye941a752011-10-15 01:52:48 +00005888 const XWindowInfo *window,Image *image,XImage *ximage,XImage *matte_image,
5889 ExceptionInfo *exception)
cristy3ed852e2009-09-05 21:47:34 +00005890{
cristyc57f6942010-11-12 01:47:39 +00005891 CacheView
5892 *canvas_view;
5893
cristy3ed852e2009-09-05 21:47:34 +00005894 Image
5895 *canvas;
5896
5897 int
5898 y;
5899
cristy4c08aed2011-07-01 19:47:50 +00005900 register const Quantum
cristy3ed852e2009-09-05 21:47:34 +00005901 *p;
5902
5903 register int
5904 x;
5905
5906 register unsigned char
5907 *q;
5908
5909 unsigned char
5910 bit,
5911 byte;
5912
5913 unsigned int
5914 scanline_pad;
5915
cristyf2faecf2010-05-28 19:19:36 +00005916 unsigned long
cristy3ed852e2009-09-05 21:47:34 +00005917 pixel,
5918 *pixels;
5919
5920 XStandardColormap
5921 *map_info;
5922
5923 assert(resource_info != (XResourceInfo *) NULL);
5924 assert(window != (XWindowInfo *) NULL);
5925 assert(image != (Image *) NULL);
5926 if (image->debug != MagickFalse)
5927 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
5928 canvas=image;
cristybab87c32010-02-09 20:54:22 +00005929 if ((window->immutable == MagickFalse) &&
cristy54666e82010-02-03 23:34:26 +00005930 (image->storage_class == DirectClass) && (image->matte != MagickFalse))
cristy3ed852e2009-09-05 21:47:34 +00005931 {
5932 char
5933 size[MaxTextExtent];
5934
5935 Image
5936 *pattern;
5937
5938 ImageInfo
5939 *image_info;
5940
5941 image_info=AcquireImageInfo();
5942 (void) CopyMagickString(image_info->filename,
5943 resource_info->image_info->texture != (char *) NULL ?
5944 resource_info->image_info->texture : "pattern:checkerboard",
5945 MaxTextExtent);
cristyb51dff52011-05-19 16:55:47 +00005946 (void) FormatLocaleString(size,MaxTextExtent,"%.20gx%.20g",(double)
cristye8c25f92010-06-03 00:53:06 +00005947 image->columns,(double) image->rows);
cristy3ed852e2009-09-05 21:47:34 +00005948 image_info->size=ConstantString(size);
cristy6710d842011-10-20 23:23:00 +00005949 pattern=ReadImage(image_info,exception);
cristy3ed852e2009-09-05 21:47:34 +00005950 image_info=DestroyImageInfo(image_info);
5951 if (pattern != (Image *) NULL)
5952 {
cristy6710d842011-10-20 23:23:00 +00005953 canvas=CloneImage(image,0,0,MagickTrue,exception);
cristy3ed852e2009-09-05 21:47:34 +00005954 if (canvas != (Image *) NULL)
cristye941a752011-10-15 01:52:48 +00005955 (void) CompositeImage(canvas,DstOverCompositeOp,pattern,0,0,
5956 exception);
cristy3ed852e2009-09-05 21:47:34 +00005957 pattern=DestroyImage(pattern);
5958 }
5959 }
5960 scanline_pad=(unsigned int) (ximage->bytes_per_line-((ximage->width*
5961 ximage->bits_per_pixel) >> 3));
5962 map_info=window->map_info;
5963 pixels=window->pixel_info->pixels;
5964 q=(unsigned char *) ximage->data;
5965 x=0;
cristyc57f6942010-11-12 01:47:39 +00005966 canvas_view=AcquireCacheView(canvas);
cristy3ed852e2009-09-05 21:47:34 +00005967 if (ximage->format == XYBitmap)
5968 {
5969 register unsigned short
5970 polarity;
5971
5972 unsigned char
5973 background,
5974 foreground;
5975
5976 /*
5977 Convert canvas to big-endian bitmap.
5978 */
5979 background=(unsigned char)
5980 (XPixelIntensity(&window->pixel_info->foreground_color) <
5981 XPixelIntensity(&window->pixel_info->background_color) ? 0x80 : 0x00);
5982 foreground=(unsigned char)
5983 (XPixelIntensity(&window->pixel_info->background_color) <
5984 XPixelIntensity(&window->pixel_info->foreground_color) ? 0x80 : 0x00);
cristy101ab702011-10-13 13:06:32 +00005985 polarity=(unsigned short) ((GetPixelInfoIntensity(
cristy3ed852e2009-09-05 21:47:34 +00005986 &canvas->colormap[0])) < ((Quantum) QuantumRange/2) ? 1 : 0);
5987 if (canvas->colors == 2)
cristy101ab702011-10-13 13:06:32 +00005988 polarity=GetPixelInfoIntensity(&canvas->colormap[0]) <
5989 GetPixelInfoIntensity(&canvas->colormap[1]);
cristy3ed852e2009-09-05 21:47:34 +00005990 for (y=0; y < (int) canvas->rows; y++)
5991 {
cristyc57f6942010-11-12 01:47:39 +00005992 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,canvas->columns,1,
cristy6710d842011-10-20 23:23:00 +00005993 exception);
cristy4c08aed2011-07-01 19:47:50 +00005994 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00005995 break;
cristy3ed852e2009-09-05 21:47:34 +00005996 bit=0;
5997 byte=0;
5998 for (x=0; x < (int) canvas->columns; x++)
5999 {
6000 byte>>=1;
cristy4c08aed2011-07-01 19:47:50 +00006001 if (GetPixelIndex(canvas,p) == (Quantum) polarity)
cristy3ed852e2009-09-05 21:47:34 +00006002 byte|=foreground;
6003 else
6004 byte|=background;
6005 bit++;
6006 if (bit == 8)
6007 {
6008 *q++=byte;
6009 bit=0;
6010 byte=0;
6011 }
cristyed231572011-07-14 02:18:59 +00006012 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00006013 }
6014 if (bit != 0)
6015 *q=byte >> (8-bit);
6016 q+=scanline_pad;
6017 }
6018 }
6019 else
6020 if (window->pixel_info->colors != 0)
6021 switch (ximage->bits_per_pixel)
6022 {
6023 case 2:
6024 {
6025 register unsigned int
6026 nibble;
6027
6028 /*
6029 Convert to 2 bit color-mapped X canvas.
6030 */
6031 for (y=0; y < (int) canvas->rows; y++)
6032 {
cristyc57f6942010-11-12 01:47:39 +00006033 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
cristy6710d842011-10-20 23:23:00 +00006034 canvas->columns,1,exception);
cristy4c08aed2011-07-01 19:47:50 +00006035 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00006036 break;
cristy3ed852e2009-09-05 21:47:34 +00006037 nibble=0;
6038 for (x=0; x < (int) canvas->columns; x++)
6039 {
cristy4c08aed2011-07-01 19:47:50 +00006040 pixel=pixels[(ssize_t) GetPixelIndex(canvas,p)] & 0x0f;
cristy3ed852e2009-09-05 21:47:34 +00006041 switch (nibble)
6042 {
6043 case 0:
6044 {
6045 *q=(unsigned char) pixel;
6046 nibble++;
6047 break;
6048 }
6049 case 1:
6050 {
6051 *q|=(unsigned char) (pixel << 2);
6052 nibble++;
6053 break;
6054 }
6055 case 2:
6056 {
6057 *q|=(unsigned char) (pixel << 4);
6058 nibble++;
6059 break;
6060 }
6061 case 3:
6062 {
6063 *q|=(unsigned char) (pixel << 6);
6064 q++;
6065 nibble=0;
6066 break;
6067 }
6068 }
cristyed231572011-07-14 02:18:59 +00006069 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00006070 }
6071 q+=scanline_pad;
6072 }
6073 break;
6074 }
6075 case 4:
6076 {
6077 register unsigned int
6078 nibble;
6079
6080 /*
6081 Convert to 4 bit color-mapped X canvas.
6082 */
6083 for (y=0; y < (int) canvas->rows; y++)
6084 {
cristyc57f6942010-11-12 01:47:39 +00006085 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
cristy6710d842011-10-20 23:23:00 +00006086 canvas->columns,1,exception);
cristy4c08aed2011-07-01 19:47:50 +00006087 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00006088 break;
cristy3ed852e2009-09-05 21:47:34 +00006089 nibble=0;
6090 for (x=0; x < (int) canvas->columns; x++)
6091 {
cristy4c08aed2011-07-01 19:47:50 +00006092 pixel=pixels[(ssize_t) GetPixelIndex(canvas,p)] & 0xf;
cristy3ed852e2009-09-05 21:47:34 +00006093 switch (nibble)
6094 {
6095 case 0:
6096 {
6097 *q=(unsigned char) pixel;
6098 nibble++;
6099 break;
6100 }
6101 case 1:
6102 {
6103 *q|=(unsigned char) (pixel << 4);
6104 q++;
6105 nibble=0;
6106 break;
6107 }
6108 }
cristyed231572011-07-14 02:18:59 +00006109 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00006110 }
6111 q+=scanline_pad;
6112 }
6113 break;
6114 }
6115 case 6:
6116 case 8:
6117 {
6118 /*
6119 Convert to 8 bit color-mapped X canvas.
6120 */
6121 if (resource_info->color_recovery &&
6122 resource_info->quantize_info->dither)
6123 {
cristy6710d842011-10-20 23:23:00 +00006124 XDitherImage(canvas,ximage,exception);
cristy3ed852e2009-09-05 21:47:34 +00006125 break;
6126 }
6127 for (y=0; y < (int) canvas->rows; y++)
6128 {
cristyc57f6942010-11-12 01:47:39 +00006129 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
cristy6710d842011-10-20 23:23:00 +00006130 canvas->columns,1,exception);
cristy4c08aed2011-07-01 19:47:50 +00006131 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00006132 break;
cristy3ed852e2009-09-05 21:47:34 +00006133 for (x=0; x < (int) canvas->columns; x++)
6134 {
cristy4c08aed2011-07-01 19:47:50 +00006135 pixel=pixels[(ssize_t) GetPixelIndex(canvas,p)];
cristy3ed852e2009-09-05 21:47:34 +00006136 *q++=(unsigned char) pixel;
cristyed231572011-07-14 02:18:59 +00006137 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00006138 }
6139 q+=scanline_pad;
6140 }
6141 break;
6142 }
6143 default:
6144 {
6145 register int
6146 k;
6147
6148 register unsigned int
6149 bytes_per_pixel;
6150
6151 unsigned char
cristybb503372010-05-27 20:51:26 +00006152 channel[sizeof(size_t)];
cristy3ed852e2009-09-05 21:47:34 +00006153
6154 /*
6155 Convert to multi-byte color-mapped X canvas.
6156 */
6157 bytes_per_pixel=(unsigned int) (ximage->bits_per_pixel >> 3);
6158 for (y=0; y < (int) canvas->rows; y++)
6159 {
cristyc57f6942010-11-12 01:47:39 +00006160 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
cristy6710d842011-10-20 23:23:00 +00006161 canvas->columns,1,exception);
cristy4c08aed2011-07-01 19:47:50 +00006162 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00006163 break;
cristy3ed852e2009-09-05 21:47:34 +00006164 for (x=0; x < (int) canvas->columns; x++)
6165 {
cristy4c08aed2011-07-01 19:47:50 +00006166 pixel=pixels[(ssize_t) GetPixelIndex(canvas,p)];
cristy3ed852e2009-09-05 21:47:34 +00006167 for (k=0; k < (int) bytes_per_pixel; k++)
6168 {
6169 channel[k]=(unsigned char) pixel;
6170 pixel>>=8;
6171 }
6172 for (k=0; k < (int) bytes_per_pixel; k++)
6173 *q++=channel[k];
cristyed231572011-07-14 02:18:59 +00006174 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00006175 }
6176 q+=scanline_pad;
6177 }
6178 break;
6179 }
6180 }
6181 else
6182 switch (ximage->bits_per_pixel)
6183 {
6184 case 2:
6185 {
6186 register unsigned int
6187 nibble;
6188
6189 /*
6190 Convert to contiguous 2 bit continuous-tone X canvas.
6191 */
6192 for (y=0; y < (int) canvas->rows; y++)
6193 {
6194 nibble=0;
cristyc57f6942010-11-12 01:47:39 +00006195 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
cristy6710d842011-10-20 23:23:00 +00006196 canvas->columns,1,exception);
cristy4c08aed2011-07-01 19:47:50 +00006197 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00006198 break;
6199 for (x=0; x < (int) canvas->columns; x++)
6200 {
cristy4c08aed2011-07-01 19:47:50 +00006201 pixel=XGammaPixel(canvas,map_info,p);
cristy3ed852e2009-09-05 21:47:34 +00006202 pixel&=0xf;
6203 switch (nibble)
6204 {
6205 case 0:
6206 {
6207 *q=(unsigned char) pixel;
6208 nibble++;
6209 break;
6210 }
6211 case 1:
6212 {
6213 *q|=(unsigned char) (pixel << 2);
6214 nibble++;
6215 break;
6216 }
6217 case 2:
6218 {
6219 *q|=(unsigned char) (pixel << 4);
6220 nibble++;
6221 break;
6222 }
6223 case 3:
6224 {
6225 *q|=(unsigned char) (pixel << 6);
6226 q++;
6227 nibble=0;
6228 break;
6229 }
6230 }
cristyed231572011-07-14 02:18:59 +00006231 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00006232 }
6233 q+=scanline_pad;
6234 }
6235 break;
6236 }
6237 case 4:
6238 {
6239 register unsigned int
6240 nibble;
6241
6242 /*
6243 Convert to contiguous 4 bit continuous-tone X canvas.
6244 */
6245 for (y=0; y < (int) canvas->rows; y++)
6246 {
cristyc57f6942010-11-12 01:47:39 +00006247 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
cristy6710d842011-10-20 23:23:00 +00006248 canvas->columns,1,exception);
cristy4c08aed2011-07-01 19:47:50 +00006249 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00006250 break;
6251 nibble=0;
6252 for (x=0; x < (int) canvas->columns; x++)
6253 {
cristy4c08aed2011-07-01 19:47:50 +00006254 pixel=XGammaPixel(canvas,map_info,p);
cristy3ed852e2009-09-05 21:47:34 +00006255 pixel&=0xf;
6256 switch (nibble)
6257 {
6258 case 0:
6259 {
6260 *q=(unsigned char) pixel;
6261 nibble++;
6262 break;
6263 }
6264 case 1:
6265 {
6266 *q|=(unsigned char) (pixel << 4);
6267 q++;
6268 nibble=0;
6269 break;
6270 }
6271 }
cristyed231572011-07-14 02:18:59 +00006272 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00006273 }
6274 q+=scanline_pad;
6275 }
6276 break;
6277 }
6278 case 6:
6279 case 8:
6280 {
6281 /*
6282 Convert to contiguous 8 bit continuous-tone X canvas.
6283 */
6284 if (resource_info->color_recovery &&
6285 resource_info->quantize_info->dither)
6286 {
cristy6710d842011-10-20 23:23:00 +00006287 XDitherImage(canvas,ximage,exception);
cristy3ed852e2009-09-05 21:47:34 +00006288 break;
6289 }
6290 for (y=0; y < (int) canvas->rows; y++)
6291 {
cristyc57f6942010-11-12 01:47:39 +00006292 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
cristy6710d842011-10-20 23:23:00 +00006293 canvas->columns,1,exception);
cristy4c08aed2011-07-01 19:47:50 +00006294 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00006295 break;
6296 for (x=0; x < (int) canvas->columns; x++)
6297 {
cristy4c08aed2011-07-01 19:47:50 +00006298 pixel=XGammaPixel(canvas,map_info,p);
cristy3ed852e2009-09-05 21:47:34 +00006299 *q++=(unsigned char) pixel;
cristyed231572011-07-14 02:18:59 +00006300 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00006301 }
6302 q+=scanline_pad;
6303 }
6304 break;
6305 }
6306 default:
6307 {
6308 if ((ximage->bits_per_pixel == 32) && (map_info->red_max == 255) &&
6309 (map_info->green_max == 255) && (map_info->blue_max == 255) &&
6310 (map_info->red_mult == 65536L) && (map_info->green_mult == 256) &&
6311 (map_info->blue_mult == 1))
6312 {
6313 /*
6314 Convert to 32 bit continuous-tone X canvas.
6315 */
6316 for (y=0; y < (int) canvas->rows; y++)
6317 {
cristyc57f6942010-11-12 01:47:39 +00006318 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
cristy6710d842011-10-20 23:23:00 +00006319 canvas->columns,1,exception);
cristy4c08aed2011-07-01 19:47:50 +00006320 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00006321 break;
6322 if ((red_gamma != 1.0) || (green_gamma != 1.0) ||
6323 (blue_gamma != 1.0))
6324 {
6325 /*
6326 Gamma correct canvas.
6327 */
6328 for (x=(int) canvas->columns-1; x >= 0; x--)
6329 {
cristyccf844f2010-02-03 23:28:16 +00006330 *q++=ScaleQuantumToChar(XBlueGamma(
cristy4c08aed2011-07-01 19:47:50 +00006331 GetPixelBlue(canvas,p)));
cristyccf844f2010-02-03 23:28:16 +00006332 *q++=ScaleQuantumToChar(XGreenGamma(
cristy4c08aed2011-07-01 19:47:50 +00006333 GetPixelGreen(canvas,p)));
cristyccf844f2010-02-03 23:28:16 +00006334 *q++=ScaleQuantumToChar(XRedGamma(
cristy4c08aed2011-07-01 19:47:50 +00006335 GetPixelRed(canvas,p)));
cristy3ed852e2009-09-05 21:47:34 +00006336 *q++=0;
cristyed231572011-07-14 02:18:59 +00006337 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00006338 }
6339 continue;
6340 }
6341 for (x=(int) canvas->columns-1; x >= 0; x--)
6342 {
cristy4c08aed2011-07-01 19:47:50 +00006343 *q++=ScaleQuantumToChar((Quantum)
6344 GetPixelBlue(canvas,p));
6345 *q++=ScaleQuantumToChar((Quantum)
6346 GetPixelGreen(canvas,p));
6347 *q++=ScaleQuantumToChar((Quantum)
6348 GetPixelRed(canvas,p));
cristy3ed852e2009-09-05 21:47:34 +00006349 *q++=0;
cristyed231572011-07-14 02:18:59 +00006350 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00006351 }
6352 }
6353 }
6354 else
6355 if ((ximage->bits_per_pixel == 32) && (map_info->red_max == 255) &&
6356 (map_info->green_max == 255) && (map_info->blue_max == 255) &&
6357 (map_info->red_mult == 1) && (map_info->green_mult == 256) &&
6358 (map_info->blue_mult == 65536L))
6359 {
6360 /*
6361 Convert to 32 bit continuous-tone X canvas.
6362 */
6363 for (y=0; y < (int) canvas->rows; y++)
6364 {
cristyc57f6942010-11-12 01:47:39 +00006365 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
cristy6710d842011-10-20 23:23:00 +00006366 canvas->columns,1,exception);
cristy4c08aed2011-07-01 19:47:50 +00006367 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00006368 break;
6369 if ((red_gamma != 1.0) || (green_gamma != 1.0) ||
6370 (blue_gamma != 1.0))
6371 {
6372 /*
6373 Gamma correct canvas.
6374 */
6375 for (x=(int) canvas->columns-1; x >= 0; x--)
6376 {
cristyccf844f2010-02-03 23:28:16 +00006377 *q++=ScaleQuantumToChar(XRedGamma(
cristy4c08aed2011-07-01 19:47:50 +00006378 GetPixelRed(canvas,p)));
cristyccf844f2010-02-03 23:28:16 +00006379 *q++=ScaleQuantumToChar(XGreenGamma(
cristy4c08aed2011-07-01 19:47:50 +00006380 GetPixelGreen(canvas,p)));
cristyccf844f2010-02-03 23:28:16 +00006381 *q++=ScaleQuantumToChar(XBlueGamma(
cristy4c08aed2011-07-01 19:47:50 +00006382 GetPixelBlue(canvas,p)));
cristy3ed852e2009-09-05 21:47:34 +00006383 *q++=0;
cristyed231572011-07-14 02:18:59 +00006384 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00006385 }
6386 continue;
6387 }
6388 for (x=(int) canvas->columns-1; x >= 0; x--)
6389 {
cristyccf844f2010-02-03 23:28:16 +00006390 *q++=ScaleQuantumToChar((Quantum)
cristy4c08aed2011-07-01 19:47:50 +00006391 GetPixelRed(canvas,p));
cristyccf844f2010-02-03 23:28:16 +00006392 *q++=ScaleQuantumToChar((Quantum)
cristy4c08aed2011-07-01 19:47:50 +00006393 GetPixelGreen(canvas,p));
cristyccf844f2010-02-03 23:28:16 +00006394 *q++=ScaleQuantumToChar((Quantum)
cristy4c08aed2011-07-01 19:47:50 +00006395 GetPixelBlue(canvas,p));
cristy3ed852e2009-09-05 21:47:34 +00006396 *q++=0;
cristyed231572011-07-14 02:18:59 +00006397 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00006398 }
6399 }
6400 }
6401 else
6402 {
6403 register int
6404 k;
6405
6406 register unsigned int
6407 bytes_per_pixel;
6408
6409 unsigned char
cristybb503372010-05-27 20:51:26 +00006410 channel[sizeof(size_t)];
cristy3ed852e2009-09-05 21:47:34 +00006411
6412 /*
6413 Convert to multi-byte continuous-tone X canvas.
6414 */
6415 bytes_per_pixel=(unsigned int) (ximage->bits_per_pixel >> 3);
6416 for (y=0; y < (int) canvas->rows; y++)
6417 {
cristyc57f6942010-11-12 01:47:39 +00006418 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
cristy6710d842011-10-20 23:23:00 +00006419 canvas->columns,1,exception);
cristy4c08aed2011-07-01 19:47:50 +00006420 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00006421 break;
cristyc57f6942010-11-12 01:47:39 +00006422 for (x=0; x < (int) canvas->columns; x++)
cristy3ed852e2009-09-05 21:47:34 +00006423 {
cristy4c08aed2011-07-01 19:47:50 +00006424 pixel=XGammaPixel(canvas,map_info,p);
cristy3ed852e2009-09-05 21:47:34 +00006425 for (k=0; k < (int) bytes_per_pixel; k++)
6426 {
6427 channel[k]=(unsigned char) pixel;
6428 pixel>>=8;
6429 }
6430 for (k=0; k < (int) bytes_per_pixel; k++)
6431 *q++=channel[k];
cristyed231572011-07-14 02:18:59 +00006432 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00006433 }
6434 q+=scanline_pad;
6435 }
6436 }
6437 break;
6438 }
6439 }
6440 if (matte_image != (XImage *) NULL)
6441 {
6442 /*
6443 Initialize matte canvas.
6444 */
6445 scanline_pad=(unsigned int) (matte_image->bytes_per_line-
6446 ((matte_image->width*matte_image->bits_per_pixel) >> 3));
6447 q=(unsigned char *) matte_image->data;
6448 for (y=0; y < (int) canvas->rows; y++)
6449 {
cristyc57f6942010-11-12 01:47:39 +00006450 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,canvas->columns,1,
cristy6710d842011-10-20 23:23:00 +00006451 exception);
cristy4c08aed2011-07-01 19:47:50 +00006452 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00006453 break;
6454 bit=0;
6455 byte=0;
6456 for (x=(int) canvas->columns-1; x >= 0; x--)
6457 {
6458 byte>>=1;
cristy4c08aed2011-07-01 19:47:50 +00006459 if (GetPixelAlpha(canvas,p) > (QuantumRange/2))
cristy3ed852e2009-09-05 21:47:34 +00006460 byte|=0x80;
6461 bit++;
6462 if (bit == 8)
6463 {
6464 *q++=byte;
6465 bit=0;
6466 byte=0;
6467 }
cristyed231572011-07-14 02:18:59 +00006468 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00006469 }
6470 if (bit != 0)
6471 *q=byte >> (8-bit);
6472 q+=scanline_pad;
6473 }
6474 }
cristyc57f6942010-11-12 01:47:39 +00006475 canvas_view=DestroyCacheView(canvas_view);
cristy3ed852e2009-09-05 21:47:34 +00006476 if (canvas != image)
6477 canvas=DestroyImage(canvas);
6478}
6479
6480/*
6481%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
6482% %
6483% %
6484% %
6485+ X M a k e I m a g e M S B F i r s t %
6486% %
6487% %
6488% %
6489%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
6490%
6491% XMakeImageMSBFirst() initializes the pixel data of an X11 Image. The X
6492% image pixels are copied in most-significant bit and byte first order. The
6493% server's scanline pad is also respected. Rather than using one or two
6494% general cases, many special cases are found here to help speed up the image
6495% conversion.
6496%
6497% The format of the XMakeImageMSBFirst method is:
6498%
cristye941a752011-10-15 01:52:48 +00006499% XMakeImageMSBFirst(resource_info,window,image,ximage,matte_image,
6500% ExceptionInfo *exception)
cristy3ed852e2009-09-05 21:47:34 +00006501%
6502% A description of each parameter follows:
6503%
6504% o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
6505%
6506% o window: Specifies a pointer to a XWindowInfo structure.
6507%
6508% o image: the image.
6509%
6510% o ximage: Specifies a pointer to a XImage structure; returned from
6511% XCreateImage.
6512%
6513% o matte_image: Specifies a pointer to a XImage structure; returned from
6514% XCreateImage.
6515%
cristye941a752011-10-15 01:52:48 +00006516% o exception: return any errors or warnings in this structure.
6517%
cristy3ed852e2009-09-05 21:47:34 +00006518*/
6519static void XMakeImageMSBFirst(const XResourceInfo *resource_info,
cristye941a752011-10-15 01:52:48 +00006520 const XWindowInfo *window,Image *image,XImage *ximage,XImage *matte_image,
6521 ExceptionInfo *exception)
cristy3ed852e2009-09-05 21:47:34 +00006522{
cristyc57f6942010-11-12 01:47:39 +00006523 CacheView
6524 *canvas_view;
6525
cristy3ed852e2009-09-05 21:47:34 +00006526 Image
6527 *canvas;
6528
6529 int
6530 y;
6531
6532 register int
6533 x;
6534
cristy4c08aed2011-07-01 19:47:50 +00006535 register const Quantum
cristy3ed852e2009-09-05 21:47:34 +00006536 *p;
6537
6538 register unsigned char
6539 *q;
6540
6541 unsigned char
6542 bit,
6543 byte;
6544
6545 unsigned int
6546 scanline_pad;
6547
cristyf2faecf2010-05-28 19:19:36 +00006548 unsigned long
cristy3ed852e2009-09-05 21:47:34 +00006549 pixel,
6550 *pixels;
6551
6552 XStandardColormap
6553 *map_info;
6554
6555 assert(resource_info != (XResourceInfo *) NULL);
6556 assert(window != (XWindowInfo *) NULL);
6557 assert(image != (Image *) NULL);
6558 if (image->debug != MagickFalse)
6559 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
6560 canvas=image;
cristy54666e82010-02-03 23:34:26 +00006561 if ((window->immutable != MagickFalse) &&
6562 (image->storage_class == DirectClass) && (image->matte != MagickFalse))
cristy3ed852e2009-09-05 21:47:34 +00006563 {
6564 char
6565 size[MaxTextExtent];
6566
6567 Image
6568 *pattern;
6569
6570 ImageInfo
6571 *image_info;
6572
6573 image_info=AcquireImageInfo();
6574 (void) CopyMagickString(image_info->filename,
6575 resource_info->image_info->texture != (char *) NULL ?
6576 resource_info->image_info->texture : "pattern:checkerboard",
6577 MaxTextExtent);
cristyb51dff52011-05-19 16:55:47 +00006578 (void) FormatLocaleString(size,MaxTextExtent,"%.20gx%.20g",(double)
cristye8c25f92010-06-03 00:53:06 +00006579 image->columns,(double) image->rows);
cristy3ed852e2009-09-05 21:47:34 +00006580 image_info->size=ConstantString(size);
cristy6710d842011-10-20 23:23:00 +00006581 pattern=ReadImage(image_info,exception);
cristy3ed852e2009-09-05 21:47:34 +00006582 image_info=DestroyImageInfo(image_info);
6583 if (pattern != (Image *) NULL)
6584 {
cristy6710d842011-10-20 23:23:00 +00006585 canvas=CloneImage(image,0,0,MagickTrue,exception);
cristy3ed852e2009-09-05 21:47:34 +00006586 if (canvas != (Image *) NULL)
cristye941a752011-10-15 01:52:48 +00006587 (void) CompositeImage(canvas,DstOverCompositeOp,pattern,0,0,
6588 exception);
cristy3ed852e2009-09-05 21:47:34 +00006589 pattern=DestroyImage(pattern);
6590 }
6591 }
cristy4c08aed2011-07-01 19:47:50 +00006592 scanline_pad=(unsigned int) (ximage->bytes_per_line-((ximage->width*
6593 ximage->bits_per_pixel) >> 3));
cristy3ed852e2009-09-05 21:47:34 +00006594 map_info=window->map_info;
6595 pixels=window->pixel_info->pixels;
6596 q=(unsigned char *) ximage->data;
6597 x=0;
cristyc57f6942010-11-12 01:47:39 +00006598 canvas_view=AcquireCacheView(canvas);
cristy3ed852e2009-09-05 21:47:34 +00006599 if (ximage->format == XYBitmap)
6600 {
6601 register unsigned short
6602 polarity;
6603
6604 unsigned char
6605 background,
6606 foreground;
6607
6608 /*
6609 Convert canvas to big-endian bitmap.
6610 */
6611 background=(unsigned char)
6612 (XPixelIntensity(&window->pixel_info->foreground_color) <
6613 XPixelIntensity(&window->pixel_info->background_color) ? 0x01 : 0x00);
6614 foreground=(unsigned char)
6615 (XPixelIntensity(&window->pixel_info->background_color) <
6616 XPixelIntensity(&window->pixel_info->foreground_color) ? 0x01 : 0x00);
cristy101ab702011-10-13 13:06:32 +00006617 polarity=(unsigned short) ((GetPixelInfoIntensity(
cristy3ed852e2009-09-05 21:47:34 +00006618 &canvas->colormap[0])) < ((Quantum) QuantumRange/2) ? 1 : 0);
6619 if (canvas->colors == 2)
cristy101ab702011-10-13 13:06:32 +00006620 polarity=GetPixelInfoIntensity(&canvas->colormap[0]) <
6621 GetPixelInfoIntensity(&canvas->colormap[1]);
cristy3ed852e2009-09-05 21:47:34 +00006622 for (y=0; y < (int) canvas->rows; y++)
6623 {
cristyc57f6942010-11-12 01:47:39 +00006624 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,canvas->columns,1,
cristy6710d842011-10-20 23:23:00 +00006625 exception);
cristy4c08aed2011-07-01 19:47:50 +00006626 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00006627 break;
cristy3ed852e2009-09-05 21:47:34 +00006628 bit=0;
6629 byte=0;
6630 for (x=(int) canvas->columns-1; x >= 0; x--)
6631 {
6632 byte<<=1;
cristy4c08aed2011-07-01 19:47:50 +00006633 if (GetPixelIndex(canvas,p) == (Quantum) polarity)
cristy3ed852e2009-09-05 21:47:34 +00006634 byte|=foreground;
6635 else
6636 byte|=background;
6637 bit++;
6638 if (bit == 8)
6639 {
6640 *q++=byte;
6641 bit=0;
6642 byte=0;
6643 }
cristyed231572011-07-14 02:18:59 +00006644 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00006645 }
6646 if (bit != 0)
6647 *q=byte << (8-bit);
6648 q+=scanline_pad;
6649 }
6650 }
6651 else
6652 if (window->pixel_info->colors != 0)
6653 switch (ximage->bits_per_pixel)
6654 {
6655 case 2:
6656 {
6657 register unsigned int
6658 nibble;
6659
6660 /*
6661 Convert to 2 bit color-mapped X canvas.
6662 */
6663 for (y=0; y < (int) canvas->rows; y++)
6664 {
cristyc57f6942010-11-12 01:47:39 +00006665 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
cristy6710d842011-10-20 23:23:00 +00006666 canvas->columns,1,exception);
cristy4c08aed2011-07-01 19:47:50 +00006667 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00006668 break;
cristy3ed852e2009-09-05 21:47:34 +00006669 nibble=0;
6670 for (x=0; x < (int) canvas->columns; x++)
6671 {
cristy4c08aed2011-07-01 19:47:50 +00006672 pixel=pixels[(ssize_t)
6673 GetPixelIndex(canvas,p)] & 0xf;
cristy3ed852e2009-09-05 21:47:34 +00006674 switch (nibble)
6675 {
6676 case 0:
6677 {
6678 *q=(unsigned char) (pixel << 6);
6679 nibble++;
6680 break;
6681 }
6682 case 1:
6683 {
6684 *q|=(unsigned char) (pixel << 4);
6685 nibble++;
6686 break;
6687 }
6688 case 2:
6689 {
6690 *q|=(unsigned char) (pixel << 2);
6691 nibble++;
6692 break;
6693 }
6694 case 3:
6695 {
6696 *q|=(unsigned char) pixel;
6697 q++;
6698 nibble=0;
6699 break;
6700 }
6701 }
cristyed231572011-07-14 02:18:59 +00006702 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00006703 }
6704 q+=scanline_pad;
6705 }
6706 break;
6707 }
6708 case 4:
6709 {
6710 register unsigned int
6711 nibble;
6712
6713 /*
6714 Convert to 4 bit color-mapped X canvas.
6715 */
6716 for (y=0; y < (int) canvas->rows; y++)
6717 {
cristyc57f6942010-11-12 01:47:39 +00006718 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
cristy6710d842011-10-20 23:23:00 +00006719 canvas->columns,1,exception);
cristy4c08aed2011-07-01 19:47:50 +00006720 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00006721 break;
cristy3ed852e2009-09-05 21:47:34 +00006722 nibble=0;
6723 for (x=0; x < (int) canvas->columns; x++)
6724 {
cristy4c08aed2011-07-01 19:47:50 +00006725 pixel=pixels[(ssize_t)
6726 GetPixelIndex(canvas,p)] & 0xf;
cristy3ed852e2009-09-05 21:47:34 +00006727 switch (nibble)
6728 {
6729 case 0:
6730 {
6731 *q=(unsigned char) (pixel << 4);
6732 nibble++;
6733 break;
6734 }
6735 case 1:
6736 {
6737 *q|=(unsigned char) pixel;
6738 q++;
6739 nibble=0;
6740 break;
6741 }
6742 }
cristyed231572011-07-14 02:18:59 +00006743 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00006744 }
6745 q+=scanline_pad;
6746 }
6747 break;
6748 }
6749 case 6:
6750 case 8:
6751 {
6752 /*
6753 Convert to 8 bit color-mapped X canvas.
6754 */
6755 if (resource_info->color_recovery &&
6756 resource_info->quantize_info->dither)
6757 {
cristy6710d842011-10-20 23:23:00 +00006758 XDitherImage(canvas,ximage,exception);
cristy3ed852e2009-09-05 21:47:34 +00006759 break;
6760 }
6761 for (y=0; y < (int) canvas->rows; y++)
6762 {
cristyc57f6942010-11-12 01:47:39 +00006763 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
cristy6710d842011-10-20 23:23:00 +00006764 canvas->columns,1,exception);
cristy4c08aed2011-07-01 19:47:50 +00006765 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00006766 break;
cristy3ed852e2009-09-05 21:47:34 +00006767 for (x=0; x < (int) canvas->columns; x++)
6768 {
cristy6710d842011-10-20 23:23:00 +00006769 pixel=pixels[(ssize_t) GetPixelIndex(canvas,p)];
cristy3ed852e2009-09-05 21:47:34 +00006770 *q++=(unsigned char) pixel;
cristyed231572011-07-14 02:18:59 +00006771 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00006772 }
6773 q+=scanline_pad;
6774 }
6775 break;
6776 }
6777 default:
6778 {
6779 register int
6780 k;
6781
6782 register unsigned int
6783 bytes_per_pixel;
6784
6785 unsigned char
cristybb503372010-05-27 20:51:26 +00006786 channel[sizeof(size_t)];
cristy3ed852e2009-09-05 21:47:34 +00006787
6788 /*
6789 Convert to 8 bit color-mapped X canvas.
6790 */
6791 bytes_per_pixel=(unsigned int) (ximage->bits_per_pixel >> 3);
6792 for (y=0; y < (int) canvas->rows; y++)
6793 {
cristyc57f6942010-11-12 01:47:39 +00006794 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
cristy6710d842011-10-20 23:23:00 +00006795 canvas->columns,1,exception);
cristy4c08aed2011-07-01 19:47:50 +00006796 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00006797 break;
cristy3ed852e2009-09-05 21:47:34 +00006798 for (x=0; x < (int) canvas->columns; x++)
6799 {
cristy4c08aed2011-07-01 19:47:50 +00006800 pixel=pixels[(ssize_t)
6801 GetPixelIndex(canvas,p)];
cristy3ed852e2009-09-05 21:47:34 +00006802 for (k=(int) bytes_per_pixel-1; k >= 0; k--)
6803 {
6804 channel[k]=(unsigned char) pixel;
6805 pixel>>=8;
6806 }
6807 for (k=0; k < (int) bytes_per_pixel; k++)
6808 *q++=channel[k];
cristyed231572011-07-14 02:18:59 +00006809 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00006810 }
6811 q+=scanline_pad;
6812 }
6813 break;
6814 }
6815 }
6816 else
6817 switch (ximage->bits_per_pixel)
6818 {
6819 case 2:
6820 {
6821 register unsigned int
6822 nibble;
6823
6824 /*
6825 Convert to 4 bit continuous-tone X canvas.
6826 */
6827 for (y=0; y < (int) canvas->rows; y++)
6828 {
cristyc57f6942010-11-12 01:47:39 +00006829 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
cristy6710d842011-10-20 23:23:00 +00006830 canvas->columns,1,exception);
cristy4c08aed2011-07-01 19:47:50 +00006831 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00006832 break;
6833 nibble=0;
6834 for (x=(int) canvas->columns-1; x >= 0; x--)
6835 {
cristy4c08aed2011-07-01 19:47:50 +00006836 pixel=XGammaPixel(canvas,map_info,p);
cristy3ed852e2009-09-05 21:47:34 +00006837 pixel&=0xf;
6838 switch (nibble)
6839 {
6840 case 0:
6841 {
6842 *q=(unsigned char) (pixel << 6);
6843 nibble++;
6844 break;
6845 }
6846 case 1:
6847 {
6848 *q|=(unsigned char) (pixel << 4);
6849 nibble++;
6850 break;
6851 }
6852 case 2:
6853 {
6854 *q|=(unsigned char) (pixel << 2);
6855 nibble++;
6856 break;
6857 }
6858 case 3:
6859 {
6860 *q|=(unsigned char) pixel;
6861 q++;
6862 nibble=0;
6863 break;
6864 }
6865 }
cristyed231572011-07-14 02:18:59 +00006866 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00006867 }
6868 q+=scanline_pad;
6869 }
6870 break;
6871 }
6872 case 4:
6873 {
6874 register unsigned int
6875 nibble;
6876
6877 /*
6878 Convert to 4 bit continuous-tone X canvas.
6879 */
6880 for (y=0; y < (int) canvas->rows; y++)
6881 {
cristyc57f6942010-11-12 01:47:39 +00006882 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
cristy6710d842011-10-20 23:23:00 +00006883 canvas->columns,1,exception);
cristy4c08aed2011-07-01 19:47:50 +00006884 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00006885 break;
6886 nibble=0;
6887 for (x=(int) canvas->columns-1; x >= 0; x--)
6888 {
cristy4c08aed2011-07-01 19:47:50 +00006889 pixel=XGammaPixel(canvas,map_info,p);
cristy3ed852e2009-09-05 21:47:34 +00006890 pixel&=0xf;
6891 switch (nibble)
6892 {
6893 case 0:
6894 {
6895 *q=(unsigned char) (pixel << 4);
6896 nibble++;
6897 break;
6898 }
6899 case 1:
6900 {
6901 *q|=(unsigned char) pixel;
6902 q++;
6903 nibble=0;
6904 break;
6905 }
6906 }
cristyed231572011-07-14 02:18:59 +00006907 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00006908 }
6909 q+=scanline_pad;
6910 }
6911 break;
6912 }
6913 case 6:
6914 case 8:
6915 {
6916 /*
6917 Convert to 8 bit continuous-tone X canvas.
6918 */
6919 if (resource_info->color_recovery &&
6920 resource_info->quantize_info->dither)
6921 {
cristy6710d842011-10-20 23:23:00 +00006922 XDitherImage(canvas,ximage,exception);
cristy3ed852e2009-09-05 21:47:34 +00006923 break;
6924 }
6925 for (y=0; y < (int) canvas->rows; y++)
6926 {
cristyc57f6942010-11-12 01:47:39 +00006927 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
cristy6710d842011-10-20 23:23:00 +00006928 canvas->columns,1,exception);
cristy4c08aed2011-07-01 19:47:50 +00006929 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00006930 break;
6931 for (x=(int) canvas->columns-1; x >= 0; x--)
6932 {
cristy4c08aed2011-07-01 19:47:50 +00006933 pixel=XGammaPixel(canvas,map_info,p);
cristy3ed852e2009-09-05 21:47:34 +00006934 *q++=(unsigned char) pixel;
cristyed231572011-07-14 02:18:59 +00006935 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00006936 }
6937 q+=scanline_pad;
6938 }
6939 break;
6940 }
6941 default:
6942 {
6943 if ((ximage->bits_per_pixel == 32) && (map_info->red_max == 255) &&
6944 (map_info->green_max == 255) && (map_info->blue_max == 255) &&
6945 (map_info->red_mult == 65536L) && (map_info->green_mult == 256) &&
6946 (map_info->blue_mult == 1))
6947 {
6948 /*
6949 Convert to 32 bit continuous-tone X canvas.
6950 */
6951 for (y=0; y < (int) canvas->rows; y++)
6952 {
cristyc57f6942010-11-12 01:47:39 +00006953 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
cristy6710d842011-10-20 23:23:00 +00006954 canvas->columns,1,exception);
cristy4c08aed2011-07-01 19:47:50 +00006955 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00006956 break;
6957 if ((red_gamma != 1.0) || (green_gamma != 1.0) ||
6958 (blue_gamma != 1.0))
6959 {
6960 /*
6961 Gamma correct canvas.
6962 */
6963 for (x=(int) canvas->columns-1; x >= 0; x--)
6964 {
6965 *q++=0;
cristyccf844f2010-02-03 23:28:16 +00006966 *q++=ScaleQuantumToChar(XRedGamma(
cristy4c08aed2011-07-01 19:47:50 +00006967 GetPixelRed(canvas,p)));
cristyccf844f2010-02-03 23:28:16 +00006968 *q++=ScaleQuantumToChar(XGreenGamma(
cristy4c08aed2011-07-01 19:47:50 +00006969 GetPixelGreen(canvas,p)));
cristyccf844f2010-02-03 23:28:16 +00006970 *q++=ScaleQuantumToChar(XBlueGamma(
cristy4c08aed2011-07-01 19:47:50 +00006971 GetPixelBlue(canvas,p)));
cristyed231572011-07-14 02:18:59 +00006972 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00006973 }
6974 continue;
6975 }
6976 for (x=(int) canvas->columns-1; x >= 0; x--)
6977 {
6978 *q++=0;
cristy4c08aed2011-07-01 19:47:50 +00006979 *q++=ScaleQuantumToChar((Quantum)
6980 GetPixelRed(canvas,p));
6981 *q++=ScaleQuantumToChar((Quantum)
6982 GetPixelGreen(canvas,p));
6983 *q++=ScaleQuantumToChar((Quantum)
6984 GetPixelBlue(canvas,p));
cristyed231572011-07-14 02:18:59 +00006985 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00006986 }
6987 }
6988 }
6989 else
6990 if ((ximage->bits_per_pixel == 32) && (map_info->red_max == 255) &&
6991 (map_info->green_max == 255) && (map_info->blue_max == 255) &&
6992 (map_info->red_mult == 1) && (map_info->green_mult == 256) &&
6993 (map_info->blue_mult == 65536L))
6994 {
6995 /*
6996 Convert to 32 bit continuous-tone X canvas.
6997 */
6998 for (y=0; y < (int) canvas->rows; y++)
6999 {
cristyc57f6942010-11-12 01:47:39 +00007000 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
cristy6710d842011-10-20 23:23:00 +00007001 canvas->columns,1,exception);
cristy4c08aed2011-07-01 19:47:50 +00007002 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00007003 break;
7004 if ((red_gamma != 1.0) || (green_gamma != 1.0) ||
7005 (blue_gamma != 1.0))
7006 {
7007 /*
7008 Gamma correct canvas.
7009 */
7010 for (x=(int) canvas->columns-1; x >= 0; x--)
7011 {
7012 *q++=0;
cristyccf844f2010-02-03 23:28:16 +00007013 *q++=ScaleQuantumToChar(XBlueGamma(
cristy4c08aed2011-07-01 19:47:50 +00007014 GetPixelBlue(canvas,p)));
cristyccf844f2010-02-03 23:28:16 +00007015 *q++=ScaleQuantumToChar(XGreenGamma(
cristy4c08aed2011-07-01 19:47:50 +00007016 GetPixelGreen(canvas,p)));
cristyccf844f2010-02-03 23:28:16 +00007017 *q++=ScaleQuantumToChar(XRedGamma(
cristy4c08aed2011-07-01 19:47:50 +00007018 GetPixelRed(canvas,p)));
cristyed231572011-07-14 02:18:59 +00007019 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00007020 }
7021 continue;
7022 }
7023 for (x=(int) canvas->columns-1; x >= 0; x--)
7024 {
7025 *q++=0;
cristyccf844f2010-02-03 23:28:16 +00007026 *q++=ScaleQuantumToChar((Quantum)
cristy4c08aed2011-07-01 19:47:50 +00007027 GetPixelBlue(canvas,p));
cristyccf844f2010-02-03 23:28:16 +00007028 *q++=ScaleQuantumToChar((Quantum)
cristy4c08aed2011-07-01 19:47:50 +00007029 GetPixelGreen(canvas,p));
cristyccf844f2010-02-03 23:28:16 +00007030 *q++=ScaleQuantumToChar((Quantum)
cristy4c08aed2011-07-01 19:47:50 +00007031 GetPixelRed(canvas,p));
cristyed231572011-07-14 02:18:59 +00007032 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00007033 }
7034 }
7035 }
7036 else
7037 {
7038 register int
7039 k;
7040
7041 register unsigned int
7042 bytes_per_pixel;
7043
7044 unsigned char
cristybb503372010-05-27 20:51:26 +00007045 channel[sizeof(size_t)];
cristy3ed852e2009-09-05 21:47:34 +00007046
7047 /*
7048 Convert to multi-byte continuous-tone X canvas.
7049 */
7050 bytes_per_pixel=(unsigned int) (ximage->bits_per_pixel >> 3);
7051 for (y=0; y < (int) canvas->rows; y++)
7052 {
cristyc57f6942010-11-12 01:47:39 +00007053 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
cristy6710d842011-10-20 23:23:00 +00007054 canvas->columns,1,exception);
cristy4c08aed2011-07-01 19:47:50 +00007055 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00007056 break;
7057 for (x=(int) canvas->columns-1; x >= 0; x--)
7058 {
cristy4c08aed2011-07-01 19:47:50 +00007059 pixel=XGammaPixel(canvas,map_info,p);
cristy3ed852e2009-09-05 21:47:34 +00007060 for (k=(int) bytes_per_pixel-1; k >= 0; k--)
7061 {
7062 channel[k]=(unsigned char) pixel;
7063 pixel>>=8;
7064 }
7065 for (k=0; k < (int) bytes_per_pixel; k++)
7066 *q++=channel[k];
cristyed231572011-07-14 02:18:59 +00007067 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00007068 }
7069 q+=scanline_pad;
7070 }
7071 }
7072 break;
7073 }
7074 }
7075 if (matte_image != (XImage *) NULL)
7076 {
7077 /*
7078 Initialize matte canvas.
7079 */
7080 scanline_pad=(unsigned int) (matte_image->bytes_per_line-
7081 ((matte_image->width*matte_image->bits_per_pixel) >> 3));
7082 q=(unsigned char *) matte_image->data;
7083 for (y=0; y < (int) canvas->rows; y++)
7084 {
cristyc57f6942010-11-12 01:47:39 +00007085 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,canvas->columns,1,
cristy6710d842011-10-20 23:23:00 +00007086 exception);
cristy4c08aed2011-07-01 19:47:50 +00007087 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00007088 break;
7089 bit=0;
7090 byte=0;
7091 for (x=(int) canvas->columns-1; x >= 0; x--)
7092 {
7093 byte<<=1;
cristy4c08aed2011-07-01 19:47:50 +00007094 if (GetPixelAlpha(canvas,p) > (QuantumRange/2))
cristy3ed852e2009-09-05 21:47:34 +00007095 byte|=0x01;
7096 bit++;
7097 if (bit == 8)
7098 {
7099 *q++=byte;
7100 bit=0;
7101 byte=0;
7102 }
cristyed231572011-07-14 02:18:59 +00007103 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00007104 }
7105 if (bit != 0)
7106 *q=byte << (8-bit);
7107 q+=scanline_pad;
7108 }
7109 }
cristyc57f6942010-11-12 01:47:39 +00007110 canvas_view=DestroyCacheView(canvas_view);
cristy3ed852e2009-09-05 21:47:34 +00007111 if (canvas != image)
7112 canvas=DestroyImage(canvas);
7113}
7114
7115/*
7116%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
7117% %
7118% %
7119% %
7120% X M a k e M a g n i f y I m a g e %
7121% %
7122% %
7123% %
7124%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
7125%
7126% XMakeMagnifyImage() magnifies a region of an X image and displays it.
7127%
7128% The format of the XMakeMagnifyImage method is:
7129%
cristy6710d842011-10-20 23:23:00 +00007130% void XMakeMagnifyImage(Display *display,XWindows *windows,
7131% ExceptionInfo *exception)
cristy3ed852e2009-09-05 21:47:34 +00007132%
7133% A description of each parameter follows:
7134%
7135% o display: Specifies a connection to an X server; returned from
7136% XOpenDisplay.
7137%
7138% o windows: Specifies a pointer to a XWindows structure.
7139%
cristy6710d842011-10-20 23:23:00 +00007140% o exception: return any errors or warnings in this structure.
7141%
cristy3ed852e2009-09-05 21:47:34 +00007142*/
cristy6710d842011-10-20 23:23:00 +00007143MagickPrivate void XMakeMagnifyImage(Display *display,XWindows *windows,
7144 ExceptionInfo *exception)
cristy3ed852e2009-09-05 21:47:34 +00007145{
7146 char
7147 tuple[MaxTextExtent];
7148
7149 int
7150 y;
7151
cristy4c08aed2011-07-01 19:47:50 +00007152 PixelInfo
cristy3ed852e2009-09-05 21:47:34 +00007153 pixel;
7154
7155 register int
7156 x;
7157
cristybb503372010-05-27 20:51:26 +00007158 register ssize_t
cristy3ed852e2009-09-05 21:47:34 +00007159 i;
7160
7161 register unsigned char
7162 *p,
7163 *q;
7164
cristy9d314ff2011-03-09 01:30:28 +00007165 ssize_t
7166 n;
7167
cristy3ed852e2009-09-05 21:47:34 +00007168 static unsigned int
7169 previous_magnify = 0;
7170
7171 static XWindowInfo
7172 magnify_window;
7173
7174 unsigned int
7175 height,
7176 j,
7177 k,
7178 l,
7179 magnify,
7180 scanline_pad,
7181 width;
7182
7183 XImage
7184 *ximage;
7185
7186 /*
7187 Check boundary conditions.
7188 */
7189 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
7190 assert(display != (Display *) NULL);
7191 assert(windows != (XWindows *) NULL);
7192 magnify=1;
cristybb503372010-05-27 20:51:26 +00007193 for (n=1; n < (ssize_t) windows->magnify.data; n++)
cristy3ed852e2009-09-05 21:47:34 +00007194 magnify<<=1;
7195 while ((magnify*windows->image.ximage->width) < windows->magnify.width)
7196 magnify<<=1;
7197 while ((magnify*windows->image.ximage->height) < windows->magnify.height)
7198 magnify<<=1;
7199 while (magnify > windows->magnify.width)
7200 magnify>>=1;
7201 while (magnify > windows->magnify.height)
7202 magnify>>=1;
7203 if (magnify != previous_magnify)
7204 {
7205 Status
7206 status;
7207
7208 XTextProperty
7209 window_name;
7210
7211 /*
7212 New magnify factor: update magnify window name.
7213 */
7214 i=0;
7215 while ((1 << i) <= (int) magnify)
7216 i++;
cristyb51dff52011-05-19 16:55:47 +00007217 (void) FormatLocaleString(windows->magnify.name,MaxTextExtent,
cristye8c25f92010-06-03 00:53:06 +00007218 "Magnify %.20gX",(double) i);
cristy3ed852e2009-09-05 21:47:34 +00007219 status=XStringListToTextProperty(&windows->magnify.name,1,&window_name);
7220 if (status != False)
7221 {
7222 XSetWMName(display,windows->magnify.id,&window_name);
7223 XSetWMIconName(display,windows->magnify.id,&window_name);
7224 (void) XFree((void *) window_name.value);
7225 }
7226 }
7227 previous_magnify=magnify;
7228 ximage=windows->image.ximage;
7229 width=(unsigned int) windows->magnify.ximage->width;
7230 height=(unsigned int) windows->magnify.ximage->height;
7231 if ((windows->magnify.x < 0) ||
7232 (windows->magnify.x >= windows->image.ximage->width))
7233 windows->magnify.x=windows->image.ximage->width >> 1;
7234 x=windows->magnify.x-((width/magnify) >> 1);
7235 if (x < 0)
7236 x=0;
7237 else
7238 if (x > (int) (ximage->width-(width/magnify)))
7239 x=ximage->width-width/magnify;
7240 if ((windows->magnify.y < 0) ||
7241 (windows->magnify.y >= windows->image.ximage->height))
7242 windows->magnify.y=windows->image.ximage->height >> 1;
7243 y=windows->magnify.y-((height/magnify) >> 1);
7244 if (y < 0)
7245 y=0;
7246 else
7247 if (y > (int) (ximage->height-(height/magnify)))
7248 y=ximage->height-height/magnify;
7249 q=(unsigned char *) windows->magnify.ximage->data;
7250 scanline_pad=(unsigned int) (windows->magnify.ximage->bytes_per_line-
7251 ((width*windows->magnify.ximage->bits_per_pixel) >> 3));
7252 if (ximage->bits_per_pixel < 8)
7253 {
7254 register unsigned char
7255 background,
7256 byte,
7257 foreground,
7258 p_bit,
7259 q_bit;
7260
7261 register unsigned int
7262 plane;
7263
7264 XPixelInfo
7265 *pixel_info;
7266
7267 pixel_info=windows->magnify.pixel_info;
7268 switch (ximage->bitmap_bit_order)
7269 {
7270 case LSBFirst:
7271 {
7272 /*
7273 Magnify little-endian bitmap.
7274 */
7275 background=0x00;
7276 foreground=0x80;
7277 if (ximage->format == XYBitmap)
7278 {
7279 background=(unsigned char)
7280 (XPixelIntensity(&pixel_info->foreground_color) <
7281 XPixelIntensity(&pixel_info->background_color) ? 0x80 : 0x00);
7282 foreground=(unsigned char)
7283 (XPixelIntensity(&pixel_info->background_color) <
7284 XPixelIntensity(&pixel_info->foreground_color) ? 0x80 : 0x00);
7285 if (windows->magnify.depth > 1)
7286 Swap(background,foreground);
7287 }
cristybb503372010-05-27 20:51:26 +00007288 for (i=0; i < (ssize_t) height; i+=magnify)
cristy3ed852e2009-09-05 21:47:34 +00007289 {
7290 /*
7291 Propogate pixel magnify rows.
7292 */
7293 for (j=0; j < magnify; j++)
7294 {
7295 p=(unsigned char *) ximage->data+y*ximage->bytes_per_line+
7296 ((x*ximage->bits_per_pixel) >> 3);
7297 p_bit=(unsigned char) (x*ximage->bits_per_pixel) & 0x07;
7298 q_bit=0;
7299 byte=0;
7300 for (k=0; k < width; k+=magnify)
7301 {
7302 /*
7303 Propogate pixel magnify columns.
7304 */
7305 for (l=0; l < magnify; l++)
7306 {
7307 /*
7308 Propogate each bit plane.
7309 */
7310 for (plane=0; (int) plane < ximage->bits_per_pixel; plane++)
7311 {
7312 byte>>=1;
7313 if (*p & (0x01 << (p_bit+plane)))
7314 byte|=foreground;
7315 else
7316 byte|=background;
7317 q_bit++;
7318 if (q_bit == 8)
7319 {
7320 *q++=byte;
7321 q_bit=0;
7322 byte=0;
7323 }
7324 }
7325 }
7326 p_bit+=ximage->bits_per_pixel;
7327 if (p_bit == 8)
7328 {
7329 p++;
7330 p_bit=0;
7331 }
7332 if (q_bit != 0)
7333 *q=byte >> (8-q_bit);
7334 q+=scanline_pad;
7335 }
7336 }
7337 y++;
7338 }
7339 break;
7340 }
7341 case MSBFirst:
7342 default:
7343 {
7344 /*
7345 Magnify big-endian bitmap.
7346 */
7347 background=0x00;
7348 foreground=0x01;
7349 if (ximage->format == XYBitmap)
7350 {
7351 background=(unsigned char)
7352 (XPixelIntensity(&pixel_info->foreground_color) <
7353 XPixelIntensity(&pixel_info->background_color) ? 0x01 : 0x00);
7354 foreground=(unsigned char)
7355 (XPixelIntensity(&pixel_info->background_color) <
7356 XPixelIntensity(&pixel_info->foreground_color) ? 0x01 : 0x00);
7357 if (windows->magnify.depth > 1)
7358 Swap(background,foreground);
7359 }
cristybb503372010-05-27 20:51:26 +00007360 for (i=0; i < (ssize_t) height; i+=magnify)
cristy3ed852e2009-09-05 21:47:34 +00007361 {
7362 /*
7363 Propogate pixel magnify rows.
7364 */
7365 for (j=0; j < magnify; j++)
7366 {
7367 p=(unsigned char *) ximage->data+y*ximage->bytes_per_line+
7368 ((x*ximage->bits_per_pixel) >> 3);
7369 p_bit=(unsigned char) (x*ximage->bits_per_pixel) & 0x07;
7370 q_bit=0;
7371 byte=0;
7372 for (k=0; k < width; k+=magnify)
7373 {
7374 /*
7375 Propogate pixel magnify columns.
7376 */
7377 for (l=0; l < magnify; l++)
7378 {
7379 /*
7380 Propogate each bit plane.
7381 */
7382 for (plane=0; (int) plane < ximage->bits_per_pixel; plane++)
7383 {
7384 byte<<=1;
7385 if (*p & (0x80 >> (p_bit+plane)))
7386 byte|=foreground;
7387 else
7388 byte|=background;
7389 q_bit++;
7390 if (q_bit == 8)
7391 {
7392 *q++=byte;
7393 q_bit=0;
7394 byte=0;
7395 }
7396 }
7397 }
7398 p_bit+=ximage->bits_per_pixel;
7399 if (p_bit == 8)
7400 {
7401 p++;
7402 p_bit=0;
7403 }
7404 if (q_bit != 0)
7405 *q=byte << (8-q_bit);
7406 q+=scanline_pad;
7407 }
7408 }
7409 y++;
7410 }
7411 break;
7412 }
7413 }
7414 }
7415 else
7416 switch (ximage->bits_per_pixel)
7417 {
7418 case 6:
7419 case 8:
7420 {
7421 /*
7422 Magnify 8 bit X image.
7423 */
cristybb503372010-05-27 20:51:26 +00007424 for (i=0; i < (ssize_t) height; i+=magnify)
cristy3ed852e2009-09-05 21:47:34 +00007425 {
7426 /*
7427 Propogate pixel magnify rows.
7428 */
7429 for (j=0; j < magnify; j++)
7430 {
7431 p=(unsigned char *) ximage->data+y*ximage->bytes_per_line+
7432 ((x*ximage->bits_per_pixel) >> 3);
7433 for (k=0; k < width; k+=magnify)
7434 {
7435 /*
7436 Propogate pixel magnify columns.
7437 */
7438 for (l=0; l < magnify; l++)
7439 *q++=(*p);
7440 p++;
7441 }
7442 q+=scanline_pad;
7443 }
7444 y++;
7445 }
7446 break;
7447 }
7448 default:
7449 {
7450 register unsigned int
7451 bytes_per_pixel,
7452 m;
7453
7454 /*
7455 Magnify multi-byte X image.
7456 */
7457 bytes_per_pixel=(unsigned int) ximage->bits_per_pixel >> 3;
cristybb503372010-05-27 20:51:26 +00007458 for (i=0; i < (ssize_t) height; i+=magnify)
cristy3ed852e2009-09-05 21:47:34 +00007459 {
7460 /*
7461 Propogate pixel magnify rows.
7462 */
7463 for (j=0; j < magnify; j++)
7464 {
7465 p=(unsigned char *) ximage->data+y*ximage->bytes_per_line+
7466 ((x*ximage->bits_per_pixel) >> 3);
7467 for (k=0; k < width; k+=magnify)
7468 {
7469 /*
7470 Propogate pixel magnify columns.
7471 */
7472 for (l=0; l < magnify; l++)
7473 for (m=0; m < bytes_per_pixel; m++)
7474 *q++=(*(p+m));
7475 p+=bytes_per_pixel;
7476 }
7477 q+=scanline_pad;
7478 }
7479 y++;
7480 }
7481 break;
7482 }
7483 }
7484 /*
7485 Copy X image to magnify pixmap.
7486 */
7487 x=windows->magnify.x-((width/magnify) >> 1);
7488 if (x < 0)
7489 x=(int) ((width >> 1)-windows->magnify.x*magnify);
7490 else
7491 if (x > (int) (ximage->width-(width/magnify)))
7492 x=(int) ((ximage->width-windows->magnify.x)*magnify-(width >> 1));
7493 else
7494 x=0;
7495 y=windows->magnify.y-((height/magnify) >> 1);
7496 if (y < 0)
7497 y=(int) ((height >> 1)-windows->magnify.y*magnify);
7498 else
7499 if (y > (int) (ximage->height-(height/magnify)))
7500 y=(int) ((ximage->height-windows->magnify.y)*magnify-(height >> 1));
7501 else
7502 y=0;
7503 if ((x != 0) || (y != 0))
7504 (void) XFillRectangle(display,windows->magnify.pixmap,
7505 windows->magnify.annotate_context,0,0,width,height);
7506 (void) XPutImage(display,windows->magnify.pixmap,
7507 windows->magnify.annotate_context,windows->magnify.ximage,0,0,x,y,width-x,
7508 height-y);
7509 if ((magnify > 1) && ((magnify <= (width >> 1)) &&
7510 (magnify <= (height >> 1))))
7511 {
7512 RectangleInfo
7513 highlight_info;
7514
7515 /*
7516 Highlight center pixel.
7517 */
cristybb503372010-05-27 20:51:26 +00007518 highlight_info.x=(ssize_t) windows->magnify.width >> 1;
7519 highlight_info.y=(ssize_t) windows->magnify.height >> 1;
cristy3ed852e2009-09-05 21:47:34 +00007520 highlight_info.width=magnify;
7521 highlight_info.height=magnify;
7522 (void) XDrawRectangle(display,windows->magnify.pixmap,
7523 windows->magnify.highlight_context,(int) highlight_info.x,
7524 (int) highlight_info.y,(unsigned int) highlight_info.width-1,
7525 (unsigned int) highlight_info.height-1);
7526 if (magnify > 2)
7527 (void) XDrawRectangle(display,windows->magnify.pixmap,
7528 windows->magnify.annotate_context,(int) highlight_info.x+1,
7529 (int) highlight_info.y+1,(unsigned int) highlight_info.width-3,
7530 (unsigned int) highlight_info.height-3);
7531 }
7532 /*
7533 Show center pixel color.
7534 */
cristy3aa93752011-12-18 15:54:24 +00007535 (void) GetOneVirtualPixelInfo(windows->image.image,TileVirtualPixelMethod,
cristy52010022011-10-21 18:07:37 +00007536 (ssize_t) windows->magnify.x,(ssize_t) windows->magnify.y,&pixel,exception);
cristyb51dff52011-05-19 16:55:47 +00007537 (void) FormatLocaleString(tuple,MaxTextExtent,"%d,%d: ",
cristy3ed852e2009-09-05 21:47:34 +00007538 windows->magnify.x,windows->magnify.y);
7539 (void) ConcatenateMagickString(tuple,"(",MaxTextExtent);
cristyed231572011-07-14 02:18:59 +00007540 ConcatenateColorComponent(&pixel,RedPixelChannel,X11Compliance,tuple);
cristy3ed852e2009-09-05 21:47:34 +00007541 (void) ConcatenateMagickString(tuple,",",MaxTextExtent);
cristyed231572011-07-14 02:18:59 +00007542 ConcatenateColorComponent(&pixel,GreenPixelChannel,X11Compliance,tuple);
cristy3ed852e2009-09-05 21:47:34 +00007543 (void) ConcatenateMagickString(tuple,",",MaxTextExtent);
cristyed231572011-07-14 02:18:59 +00007544 ConcatenateColorComponent(&pixel,BluePixelChannel,X11Compliance,tuple);
cristy3ed852e2009-09-05 21:47:34 +00007545 if (pixel.colorspace == CMYKColorspace)
7546 {
7547 (void) ConcatenateMagickString(tuple,",",MaxTextExtent);
cristyed231572011-07-14 02:18:59 +00007548 ConcatenateColorComponent(&pixel,BlackPixelChannel,X11Compliance,tuple);
cristy3ed852e2009-09-05 21:47:34 +00007549 }
7550 if (pixel.matte != MagickFalse)
7551 {
7552 (void) ConcatenateMagickString(tuple,",",MaxTextExtent);
cristyed231572011-07-14 02:18:59 +00007553 ConcatenateColorComponent(&pixel,AlphaPixelChannel,X11Compliance,tuple);
cristy3ed852e2009-09-05 21:47:34 +00007554 }
7555 (void) ConcatenateMagickString(tuple,")",MaxTextExtent);
7556 height=(unsigned int) windows->magnify.font_info->ascent+
7557 windows->magnify.font_info->descent;
7558 x=windows->magnify.font_info->max_bounds.width >> 1;
7559 y=windows->magnify.font_info->ascent+(height >> 2);
7560 (void) XDrawImageString(display,windows->magnify.pixmap,
7561 windows->magnify.annotate_context,x,y,tuple,(int) strlen(tuple));
7562 GetColorTuple(&pixel,MagickTrue,tuple);
7563 y+=height;
7564 (void) XDrawImageString(display,windows->magnify.pixmap,
7565 windows->magnify.annotate_context,x,y,tuple,(int) strlen(tuple));
cristy269c9412011-10-13 23:41:15 +00007566 (void) QueryColorname(windows->image.image,&pixel,SVGCompliance,tuple,
cristy6710d842011-10-20 23:23:00 +00007567 exception);
cristy3ed852e2009-09-05 21:47:34 +00007568 y+=height;
7569 (void) XDrawImageString(display,windows->magnify.pixmap,
7570 windows->magnify.annotate_context,x,y,tuple,(int) strlen(tuple));
7571 /*
7572 Refresh magnify window.
7573 */
7574 magnify_window=windows->magnify;
7575 magnify_window.x=0;
7576 magnify_window.y=0;
7577 XRefreshWindow(display,&magnify_window,(XEvent *) NULL);
7578}
7579
7580/*
7581%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
7582% %
7583% %
7584% %
7585% X M a k e P i x m a p %
7586% %
7587% %
7588% %
7589%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
7590%
7591% XMakePixmap() creates an X11 pixmap.
7592%
7593% The format of the XMakePixmap method is:
7594%
7595% void XMakeStandardColormap(Display *display,XVisualInfo *visual_info,
7596% XResourceInfo *resource_info,Image *image,XStandardColormap *map_info,
7597% XPixelInfo *pixel)
7598%
7599% A description of each parameter follows:
7600%
7601% o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
7602%
7603% o display: Specifies a connection to an X server; returned from
7604% XOpenDisplay.
7605%
7606% o window: Specifies a pointer to a XWindowInfo structure.
7607%
cristy3ed852e2009-09-05 21:47:34 +00007608*/
7609static MagickBooleanType XMakePixmap(Display *display,
7610 const XResourceInfo *resource_info,XWindowInfo *window)
7611{
7612 unsigned int
7613 height,
7614 width;
7615
7616 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
7617 assert(display != (Display *) NULL);
7618 assert(resource_info != (XResourceInfo *) NULL);
7619 assert(window != (XWindowInfo *) NULL);
7620 if (window->pixmap != (Pixmap) NULL)
7621 {
7622 /*
7623 Destroy previous X pixmap.
7624 */
7625 (void) XFreePixmap(display,window->pixmap);
7626 window->pixmap=(Pixmap) NULL;
7627 }
7628 if (window->use_pixmap == MagickFalse)
7629 return(MagickFalse);
7630 if (window->ximage == (XImage *) NULL)
7631 return(MagickFalse);
7632 /*
7633 Display busy cursor.
7634 */
7635 (void) XCheckDefineCursor(display,window->id,window->busy_cursor);
7636 (void) XFlush(display);
7637 /*
7638 Create pixmap.
7639 */
7640 width=(unsigned int) window->ximage->width;
7641 height=(unsigned int) window->ximage->height;
7642 window->pixmap=XCreatePixmap(display,window->id,width,height,window->depth);
7643 if (window->pixmap == (Pixmap) NULL)
7644 {
7645 /*
7646 Unable to allocate pixmap.
7647 */
7648 (void) XCheckDefineCursor(display,window->id,window->cursor);
7649 return(MagickFalse);
7650 }
7651 /*
7652 Copy X image to pixmap.
7653 */
7654#if defined(MAGICKCORE_HAVE_SHARED_MEMORY)
7655 if (window->shared_memory)
7656 (void) XShmPutImage(display,window->pixmap,window->annotate_context,
7657 window->ximage,0,0,0,0,width,height,MagickTrue);
7658#endif
7659 if (window->shared_memory == MagickFalse)
7660 (void) XPutImage(display,window->pixmap,window->annotate_context,
7661 window->ximage,0,0,0,0,width,height);
7662 if (IsEventLogging())
7663 {
7664 (void) LogMagickEvent(X11Event,GetMagickModule(),"Pixmap:");
7665 (void) LogMagickEvent(X11Event,GetMagickModule()," width, height: %ux%u",
7666 width,height);
7667 }
7668 /*
7669 Restore cursor.
7670 */
7671 (void) XCheckDefineCursor(display,window->id,window->cursor);
7672 return(MagickTrue);
7673}
7674
7675/*
7676%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
7677% %
7678% %
7679% %
7680% X M a k e S t a n d a r d C o l o r m a p %
7681% %
7682% %
7683% %
7684%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
7685%
7686% XMakeStandardColormap() creates an X11 Standard Colormap.
7687%
7688% The format of the XMakeStandardColormap method is:
7689%
cristy6710d842011-10-20 23:23:00 +00007690% void XMakeStandardColormap(Display *display,XVisualInfo *visual_info,
7691% XResourceInfo *resource_info,Image *image,XStandardColormap *map_info,
7692% XPixelInfo *pixel,ExceptionInfo *exception)
cristy3ed852e2009-09-05 21:47:34 +00007693%
7694% A description of each parameter follows:
7695%
7696% o display: Specifies a connection to an X server; returned from
7697% XOpenDisplay.
7698%
7699% o visual_info: Specifies a pointer to a X11 XVisualInfo structure;
7700% returned from XGetVisualInfo.
7701%
7702% o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
7703%
7704% o image: the image.
7705%
7706% o map_info: If a Standard Colormap type is specified, this structure is
7707% initialized with info from the Standard Colormap.
7708%
7709% o pixel: Specifies a pointer to a XPixelInfo structure.
7710%
cristy6710d842011-10-20 23:23:00 +00007711% o exception: return any errors or warnings in this structure.
7712%
cristy3ed852e2009-09-05 21:47:34 +00007713*/
7714
7715#if defined(__cplusplus) || defined(c_plusplus)
7716extern "C" {
7717#endif
7718
7719static inline MagickRealType DiversityPixelIntensity(
7720 const DiversityPacket *pixel)
7721{
7722 MagickRealType
7723 intensity;
7724
7725 intensity=0.299*pixel->red+0.587*pixel->green+0.114*pixel->blue;
7726 return(intensity);
7727}
7728
7729static int IntensityCompare(const void *x,const void *y)
7730{
7731 DiversityPacket
7732 *color_1,
7733 *color_2;
7734
7735 int
7736 diversity;
7737
7738 color_1=(DiversityPacket *) x;
7739 color_2=(DiversityPacket *) y;
7740 diversity=(int) (DiversityPixelIntensity(color_2)-
7741 DiversityPixelIntensity(color_1));
7742 return(diversity);
7743}
7744
7745static int PopularityCompare(const void *x,const void *y)
7746{
7747 DiversityPacket
7748 *color_1,
7749 *color_2;
7750
7751 color_1=(DiversityPacket *) x;
7752 color_2=(DiversityPacket *) y;
7753 return((int) color_2->count-(int) color_1->count);
7754}
7755
7756#if defined(__cplusplus) || defined(c_plusplus)
7757}
7758#endif
7759
cristybb503372010-05-27 20:51:26 +00007760static inline Quantum ScaleXToQuantum(const size_t x,
7761 const size_t scale)
cristy3ed852e2009-09-05 21:47:34 +00007762{
7763 return((Quantum) (((MagickRealType) QuantumRange*x)/scale+0.5));
7764}
7765
cristybcbda3f2011-09-03 13:01:22 +00007766MagickPrivate void XMakeStandardColormap(Display *display,
cristy3ed852e2009-09-05 21:47:34 +00007767 XVisualInfo *visual_info,XResourceInfo *resource_info,Image *image,
cristy6710d842011-10-20 23:23:00 +00007768 XStandardColormap *map_info,XPixelInfo *pixel,ExceptionInfo *exception)
cristy3ed852e2009-09-05 21:47:34 +00007769{
7770 Colormap
7771 colormap;
7772
cristybb503372010-05-27 20:51:26 +00007773 register ssize_t
cristy3ed852e2009-09-05 21:47:34 +00007774 i;
7775
7776 Status
7777 status;
7778
cristybb503372010-05-27 20:51:26 +00007779 size_t
cristy3ed852e2009-09-05 21:47:34 +00007780 number_colors,
7781 retain_colors;
7782
7783 unsigned short
7784 gray_value;
7785
7786 XColor
7787 color,
7788 *colors,
7789 *p;
7790
7791 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
7792 assert(display != (Display *) NULL);
7793 assert(visual_info != (XVisualInfo *) NULL);
7794 assert(map_info != (XStandardColormap *) NULL);
7795 assert(resource_info != (XResourceInfo *) NULL);
7796 assert(pixel != (XPixelInfo *) NULL);
cristy3ed852e2009-09-05 21:47:34 +00007797 if (resource_info->map_type != (char *) NULL)
7798 {
7799 /*
7800 Standard Colormap is already defined (i.e. xstdcmap).
7801 */
cristy4c08aed2011-07-01 19:47:50 +00007802 XGetPixelInfo(display,visual_info,map_info,resource_info,image,
cristy3ed852e2009-09-05 21:47:34 +00007803 pixel);
7804 number_colors=(unsigned int) (map_info->base_pixel+
7805 (map_info->red_max+1)*(map_info->green_max+1)*(map_info->blue_max+1));
7806 if ((map_info->red_max*map_info->green_max*map_info->blue_max) != 0)
7807 if ((image->matte == MagickFalse) &&
7808 (resource_info->color_recovery == MagickFalse) &&
7809 resource_info->quantize_info->dither &&
7810 (number_colors < MaxColormapSize))
7811 {
7812 Image
7813 *affinity_image;
7814
cristy4c08aed2011-07-01 19:47:50 +00007815 register Quantum
cristyc47d1f82009-11-26 01:44:43 +00007816 *restrict q;
cristy3ed852e2009-09-05 21:47:34 +00007817
7818 /*
7819 Improve image appearance with error diffusion.
7820 */
cristy6710d842011-10-20 23:23:00 +00007821 affinity_image=AcquireImage((ImageInfo *) NULL,exception);
cristy3ed852e2009-09-05 21:47:34 +00007822 if (affinity_image == (Image *) NULL)
7823 ThrowXWindowFatalException(ResourceLimitFatalError,
7824 "UnableToDitherImage",image->filename);
7825 affinity_image->columns=number_colors;
7826 affinity_image->rows=1;
7827 /*
7828 Initialize colormap image.
7829 */
7830 q=QueueAuthenticPixels(affinity_image,0,0,affinity_image->columns,
7831 1,exception);
cristy4c08aed2011-07-01 19:47:50 +00007832 if (q != (Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00007833 {
cristybb503372010-05-27 20:51:26 +00007834 for (i=0; i < (ssize_t) number_colors; i++)
cristy3ed852e2009-09-05 21:47:34 +00007835 {
cristy4c08aed2011-07-01 19:47:50 +00007836 SetPixelRed(affinity_image,0,q);
cristy3ed852e2009-09-05 21:47:34 +00007837 if (map_info->red_max != 0)
cristy4c08aed2011-07-01 19:47:50 +00007838 SetPixelRed(affinity_image,
7839 ScaleXToQuantum((size_t) (i/map_info->red_mult),
7840 map_info->red_max),q);
7841 SetPixelGreen(affinity_image,0,q);
cristy3ed852e2009-09-05 21:47:34 +00007842 if (map_info->green_max != 0)
cristy4c08aed2011-07-01 19:47:50 +00007843 SetPixelGreen(affinity_image,
7844 ScaleXToQuantum((size_t) ((i/map_info->green_mult) %
7845 (map_info->green_max+1)),map_info->green_max),q);
7846 SetPixelBlue(affinity_image,0,q);
cristy3ed852e2009-09-05 21:47:34 +00007847 if (map_info->blue_max != 0)
cristy4c08aed2011-07-01 19:47:50 +00007848 SetPixelBlue(affinity_image,
7849 ScaleXToQuantum((size_t) (i % map_info->green_mult),
7850 map_info->blue_max),q);
7851 SetPixelAlpha(affinity_image,
7852 TransparentAlpha,q);
cristyed231572011-07-14 02:18:59 +00007853 q+=GetPixelChannels(affinity_image);
cristy3ed852e2009-09-05 21:47:34 +00007854 }
7855 (void) SyncAuthenticPixels(affinity_image,exception);
7856 (void) RemapImage(resource_info->quantize_info,image,
cristy018f07f2011-09-04 21:15:19 +00007857 affinity_image,exception);
cristy3ed852e2009-09-05 21:47:34 +00007858 }
cristy4c08aed2011-07-01 19:47:50 +00007859 XGetPixelInfo(display,visual_info,map_info,resource_info,image,
cristy3ed852e2009-09-05 21:47:34 +00007860 pixel);
cristy574cc262011-08-05 01:23:58 +00007861 (void) SetImageStorageClass(image,DirectClass,exception);
cristy3ed852e2009-09-05 21:47:34 +00007862 affinity_image=DestroyImage(affinity_image);
7863 }
7864 if (IsEventLogging())
7865 {
7866 (void) LogMagickEvent(X11Event,GetMagickModule(),
7867 "Standard Colormap:");
7868 (void) LogMagickEvent(X11Event,GetMagickModule(),
7869 " colormap id: 0x%lx",map_info->colormap);
7870 (void) LogMagickEvent(X11Event,GetMagickModule(),
7871 " red, green, blue max: %lu %lu %lu",map_info->red_max,
7872 map_info->green_max,map_info->blue_max);
7873 (void) LogMagickEvent(X11Event,GetMagickModule(),
7874 " red, green, blue mult: %lu %lu %lu",map_info->red_mult,
7875 map_info->green_mult,map_info->blue_mult);
7876 }
7877 return;
7878 }
7879 if ((visual_info->klass != DirectColor) &&
7880 (visual_info->klass != TrueColor))
7881 if ((image->storage_class == DirectClass) ||
7882 ((int) image->colors > visual_info->colormap_size))
7883 {
7884 QuantizeInfo
7885 quantize_info;
7886
7887 /*
7888 Image has more colors than the visual supports.
7889 */
7890 quantize_info=(*resource_info->quantize_info);
cristybb503372010-05-27 20:51:26 +00007891 quantize_info.number_colors=(size_t) visual_info->colormap_size;
cristy018f07f2011-09-04 21:15:19 +00007892 (void) QuantizeImage(&quantize_info,image,exception);
cristy3ed852e2009-09-05 21:47:34 +00007893 }
7894 /*
7895 Free previous and create new colormap.
7896 */
7897 (void) XFreeStandardColormap(display,visual_info,map_info,pixel);
7898 colormap=XDefaultColormap(display,visual_info->screen);
7899 if (visual_info->visual != XDefaultVisual(display,visual_info->screen))
7900 colormap=XCreateColormap(display,XRootWindow(display,visual_info->screen),
7901 visual_info->visual,visual_info->klass == DirectColor ?
7902 AllocAll : AllocNone);
7903 if (colormap == (Colormap) NULL)
7904 ThrowXWindowFatalException(ResourceLimitFatalError,"UnableToCreateColormap",
7905 image->filename);
7906 /*
7907 Initialize the map and pixel info structures.
7908 */
7909 XGetMapInfo(visual_info,colormap,map_info);
cristy4c08aed2011-07-01 19:47:50 +00007910 XGetPixelInfo(display,visual_info,map_info,resource_info,image,pixel);
cristy3ed852e2009-09-05 21:47:34 +00007911 /*
7912 Allocating colors in server colormap is based on visual class.
7913 */
7914 switch (visual_info->klass)
7915 {
7916 case StaticGray:
7917 case StaticColor:
7918 {
7919 /*
7920 Define Standard Colormap for StaticGray or StaticColor visual.
7921 */
7922 number_colors=image->colors;
7923 colors=(XColor *) AcquireQuantumMemory((size_t)
7924 visual_info->colormap_size,sizeof(*colors));
7925 if (colors == (XColor *) NULL)
7926 ThrowXWindowFatalException(ResourceLimitFatalError,
7927 "UnableToCreateColormap",image->filename);
7928 p=colors;
7929 color.flags=(char) (DoRed | DoGreen | DoBlue);
cristybb503372010-05-27 20:51:26 +00007930 for (i=0; i < (ssize_t) image->colors; i++)
cristy3ed852e2009-09-05 21:47:34 +00007931 {
7932 color.red=ScaleQuantumToShort(XRedGamma(image->colormap[i].red));
7933 color.green=ScaleQuantumToShort(XGreenGamma(image->colormap[i].green));
7934 color.blue=ScaleQuantumToShort(XBlueGamma(image->colormap[i].blue));
7935 if (visual_info->klass != StaticColor)
7936 {
7937 gray_value=(unsigned short) XPixelIntensity(&color);
7938 color.red=gray_value;
7939 color.green=gray_value;
7940 color.blue=gray_value;
7941 }
7942 status=XAllocColor(display,colormap,&color);
7943 if (status == False)
7944 {
7945 colormap=XCopyColormapAndFree(display,colormap);
7946 (void) XAllocColor(display,colormap,&color);
7947 }
7948 pixel->pixels[i]=color.pixel;
7949 *p++=color;
7950 }
7951 break;
7952 }
7953 case GrayScale:
7954 case PseudoColor:
7955 {
7956 unsigned int
7957 colormap_type;
7958
7959 /*
7960 Define Standard Colormap for GrayScale or PseudoColor visual.
7961 */
7962 number_colors=image->colors;
7963 colors=(XColor *) AcquireQuantumMemory((size_t)
7964 visual_info->colormap_size,sizeof(*colors));
7965 if (colors == (XColor *) NULL)
7966 ThrowXWindowFatalException(ResourceLimitFatalError,
7967 "UnableToCreateColormap",image->filename);
7968 /*
7969 Preallocate our GUI colors.
7970 */
7971 (void) XAllocColor(display,colormap,&pixel->foreground_color);
7972 (void) XAllocColor(display,colormap,&pixel->background_color);
7973 (void) XAllocColor(display,colormap,&pixel->border_color);
7974 (void) XAllocColor(display,colormap,&pixel->matte_color);
7975 (void) XAllocColor(display,colormap,&pixel->highlight_color);
7976 (void) XAllocColor(display,colormap,&pixel->shadow_color);
7977 (void) XAllocColor(display,colormap,&pixel->depth_color);
7978 (void) XAllocColor(display,colormap,&pixel->trough_color);
7979 for (i=0; i < MaxNumberPens; i++)
7980 (void) XAllocColor(display,colormap,&pixel->pen_colors[i]);
7981 /*
7982 Determine if image colors will "fit" into X server colormap.
7983 */
7984 colormap_type=resource_info->colormap;
cristyf2faecf2010-05-28 19:19:36 +00007985 status=XAllocColorCells(display,colormap,MagickFalse,(unsigned long *)
cristy3ed852e2009-09-05 21:47:34 +00007986 NULL,0,pixel->pixels,(unsigned int) image->colors);
7987 if (status != False)
7988 colormap_type=PrivateColormap;
7989 if (colormap_type == SharedColormap)
7990 {
cristyc57f6942010-11-12 01:47:39 +00007991 CacheView
7992 *image_view;
7993
cristy3ed852e2009-09-05 21:47:34 +00007994 DiversityPacket
7995 *diversity;
7996
7997 int
7998 y;
7999
8000 register int
8001 x;
8002
8003 unsigned short
8004 index;
8005
8006 XColor
8007 *server_colors;
8008
8009 /*
8010 Define Standard colormap for shared GrayScale or PseudoColor visual.
8011 */
8012 diversity=(DiversityPacket *) AcquireQuantumMemory(image->colors,
8013 sizeof(*diversity));
8014 if (diversity == (DiversityPacket *) NULL)
8015 ThrowXWindowFatalException(ResourceLimitFatalError,
8016 "UnableToCreateColormap",image->filename);
cristybb503372010-05-27 20:51:26 +00008017 for (i=0; i < (ssize_t) image->colors; i++)
cristy3ed852e2009-09-05 21:47:34 +00008018 {
cristye42f6582012-02-11 17:59:50 +00008019 diversity[i].red=ClampToQuantum(image->colormap[i].red);
8020 diversity[i].green=ClampToQuantum(image->colormap[i].green);
8021 diversity[i].blue=ClampToQuantum(image->colormap[i].blue);
cristy3ed852e2009-09-05 21:47:34 +00008022 diversity[i].index=(unsigned short) i;
8023 diversity[i].count=0;
8024 }
cristyc57f6942010-11-12 01:47:39 +00008025 image_view=AcquireCacheView(image);
cristy3ed852e2009-09-05 21:47:34 +00008026 for (y=0; y < (int) image->rows; y++)
8027 {
cristyc57f6942010-11-12 01:47:39 +00008028 register int
cristy3ed852e2009-09-05 21:47:34 +00008029 x;
8030
cristy4c08aed2011-07-01 19:47:50 +00008031 register const Quantum
cristyc57f6942010-11-12 01:47:39 +00008032 *restrict p;
cristy3ed852e2009-09-05 21:47:34 +00008033
cristyc57f6942010-11-12 01:47:39 +00008034 p=GetCacheViewAuthenticPixels(image_view,0,(ssize_t) y,
8035 image->columns,1,exception);
cristy4c08aed2011-07-01 19:47:50 +00008036 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00008037 break;
cristyc57f6942010-11-12 01:47:39 +00008038 for (x=(int) image->columns-1; x >= 0; x--)
cristy4c08aed2011-07-01 19:47:50 +00008039 {
8040 diversity[(ssize_t) GetPixelIndex(image,p)].count++;
cristyed231572011-07-14 02:18:59 +00008041 p+=GetPixelChannels(image);
cristy4c08aed2011-07-01 19:47:50 +00008042 }
cristy3ed852e2009-09-05 21:47:34 +00008043 }
cristyc57f6942010-11-12 01:47:39 +00008044 image_view=DestroyCacheView(image_view);
cristy3ed852e2009-09-05 21:47:34 +00008045 /*
8046 Sort colors by decreasing intensity.
8047 */
8048 qsort((void *) diversity,image->colors,sizeof(*diversity),
8049 IntensityCompare);
cristybb503372010-05-27 20:51:26 +00008050 for (i=0; i < (ssize_t) image->colors; )
cristy3ed852e2009-09-05 21:47:34 +00008051 {
8052 diversity[i].count<<=4; /* increase this colors popularity */
cristydfe2b662010-08-22 16:17:24 +00008053 i+=MagickMax((int) (image->colors >> 4),2);
cristy3ed852e2009-09-05 21:47:34 +00008054 }
8055 diversity[image->colors-1].count<<=4;
8056 qsort((void *) diversity,image->colors,sizeof(*diversity),
8057 PopularityCompare);
8058 /*
8059 Allocate colors.
8060 */
8061 p=colors;
8062 color.flags=(char) (DoRed | DoGreen | DoBlue);
cristybb503372010-05-27 20:51:26 +00008063 for (i=0; i < (ssize_t) image->colors; i++)
cristy3ed852e2009-09-05 21:47:34 +00008064 {
8065 index=diversity[i].index;
8066 color.red=
8067 ScaleQuantumToShort(XRedGamma(image->colormap[index].red));
8068 color.green=
8069 ScaleQuantumToShort(XGreenGamma(image->colormap[index].green));
8070 color.blue=
8071 ScaleQuantumToShort(XBlueGamma(image->colormap[index].blue));
8072 if (visual_info->klass != PseudoColor)
8073 {
8074 gray_value=(unsigned short) XPixelIntensity(&color);
8075 color.red=gray_value;
8076 color.green=gray_value;
8077 color.blue=gray_value;
8078 }
8079 status=XAllocColor(display,colormap,&color);
8080 if (status == False)
8081 break;
8082 pixel->pixels[index]=color.pixel;
8083 *p++=color;
8084 }
8085 /*
8086 Read X server colormap.
8087 */
8088 server_colors=(XColor *) AcquireQuantumMemory((size_t)
8089 visual_info->colormap_size,sizeof(*server_colors));
8090 if (server_colors == (XColor *) NULL)
8091 ThrowXWindowFatalException(ResourceLimitFatalError,
8092 "UnableToCreateColormap",image->filename);
8093 for (x=visual_info->colormap_size-1; x >= 0; x--)
cristybb503372010-05-27 20:51:26 +00008094 server_colors[x].pixel=(size_t) x;
cristy3ed852e2009-09-05 21:47:34 +00008095 (void) XQueryColors(display,colormap,server_colors,
8096 (int) MagickMin((unsigned int) visual_info->colormap_size,256));
8097 /*
8098 Select remaining colors from X server colormap.
8099 */
cristybb503372010-05-27 20:51:26 +00008100 for (; i < (ssize_t) image->colors; i++)
cristy3ed852e2009-09-05 21:47:34 +00008101 {
8102 index=diversity[i].index;
8103 color.red=
8104 ScaleQuantumToShort(XRedGamma(image->colormap[index].red));
8105 color.green=
8106 ScaleQuantumToShort(XGreenGamma(image->colormap[index].green));
8107 color.blue=
8108 ScaleQuantumToShort(XBlueGamma(image->colormap[index].blue));
8109 if (visual_info->klass != PseudoColor)
8110 {
8111 gray_value=(unsigned short) XPixelIntensity(&color);
8112 color.red=gray_value;
8113 color.green=gray_value;
8114 color.blue=gray_value;
8115 }
8116 XBestPixel(display,colormap,server_colors,(unsigned int)
8117 visual_info->colormap_size,&color);
8118 pixel->pixels[index]=color.pixel;
8119 *p++=color;
8120 }
8121 if ((int) image->colors < visual_info->colormap_size)
8122 {
8123 /*
8124 Fill up colors array-- more choices for pen colors.
8125 */
8126 retain_colors=MagickMin((unsigned int)
8127 (visual_info->colormap_size-image->colors),256);
cristybb503372010-05-27 20:51:26 +00008128 for (i=0; i < (ssize_t) retain_colors; i++)
cristy3ed852e2009-09-05 21:47:34 +00008129 *p++=server_colors[i];
8130 number_colors+=retain_colors;
8131 }
8132 server_colors=(XColor *) RelinquishMagickMemory(server_colors);
8133 diversity=(DiversityPacket *) RelinquishMagickMemory(diversity);
8134 break;
8135 }
8136 /*
8137 Define Standard colormap for private GrayScale or PseudoColor visual.
8138 */
8139 if (status == False)
8140 {
8141 /*
8142 Not enough colormap entries in the colormap-- Create a new colormap.
8143 */
8144 colormap=XCreateColormap(display,
8145 XRootWindow(display,visual_info->screen),visual_info->visual,
8146 AllocNone);
8147 if (colormap == (Colormap) NULL)
8148 ThrowXWindowFatalException(ResourceLimitFatalError,
8149 "UnableToCreateColormap",image->filename);
8150 map_info->colormap=colormap;
8151 if ((int) image->colors < visual_info->colormap_size)
8152 {
8153 /*
8154 Retain colors from the default colormap to help lessens the
8155 effects of colormap flashing.
8156 */
8157 retain_colors=MagickMin((unsigned int)
8158 (visual_info->colormap_size-image->colors),256);
8159 p=colors+image->colors;
cristybb503372010-05-27 20:51:26 +00008160 for (i=0; i < (ssize_t) retain_colors; i++)
cristy3ed852e2009-09-05 21:47:34 +00008161 {
cristyc57f6942010-11-12 01:47:39 +00008162 p->pixel=(unsigned long) i;
cristy3ed852e2009-09-05 21:47:34 +00008163 p++;
8164 }
8165 (void) XQueryColors(display,
8166 XDefaultColormap(display,visual_info->screen),
8167 colors+image->colors,(int) retain_colors);
8168 /*
8169 Transfer colors from default to private colormap.
8170 */
8171 (void) XAllocColorCells(display,colormap,MagickFalse,
cristyf2faecf2010-05-28 19:19:36 +00008172 (unsigned long *) NULL,0,pixel->pixels,(unsigned int)
cristy3ed852e2009-09-05 21:47:34 +00008173 retain_colors);
8174 p=colors+image->colors;
cristybb503372010-05-27 20:51:26 +00008175 for (i=0; i < (ssize_t) retain_colors; i++)
cristy3ed852e2009-09-05 21:47:34 +00008176 {
8177 p->pixel=pixel->pixels[i];
8178 p++;
8179 }
8180 (void) XStoreColors(display,colormap,colors+image->colors,
8181 (int) retain_colors);
8182 number_colors+=retain_colors;
8183 }
8184 (void) XAllocColorCells(display,colormap,MagickFalse,
cristyf2faecf2010-05-28 19:19:36 +00008185 (unsigned long *) NULL,0,pixel->pixels,(unsigned int)
cristy3ed852e2009-09-05 21:47:34 +00008186 image->colors);
8187 }
8188 /*
8189 Store the image colormap.
8190 */
8191 p=colors;
8192 color.flags=(char) (DoRed | DoGreen | DoBlue);
cristybb503372010-05-27 20:51:26 +00008193 for (i=0; i < (ssize_t) image->colors; i++)
cristy3ed852e2009-09-05 21:47:34 +00008194 {
8195 color.red=ScaleQuantumToShort(XRedGamma(image->colormap[i].red));
8196 color.green=ScaleQuantumToShort(XGreenGamma(image->colormap[i].green));
8197 color.blue=ScaleQuantumToShort(XBlueGamma(image->colormap[i].blue));
8198 if (visual_info->klass != PseudoColor)
8199 {
8200 gray_value=(unsigned short) XPixelIntensity(&color);
8201 color.red=gray_value;
8202 color.green=gray_value;
8203 color.blue=gray_value;
8204 }
8205 color.pixel=pixel->pixels[i];
8206 *p++=color;
8207 }
8208 (void) XStoreColors(display,colormap,colors,(int) image->colors);
8209 break;
8210 }
8211 case TrueColor:
8212 case DirectColor:
8213 default:
8214 {
8215 MagickBooleanType
8216 linear_colormap;
8217
8218 /*
8219 Define Standard Colormap for TrueColor or DirectColor visual.
8220 */
8221 number_colors=(unsigned int) ((map_info->red_max*map_info->red_mult)+
8222 (map_info->green_max*map_info->green_mult)+
8223 (map_info->blue_max*map_info->blue_mult)+1);
8224 linear_colormap=(number_colors > 4096) ||
8225 (((int) (map_info->red_max+1) == visual_info->colormap_size) &&
8226 ((int) (map_info->green_max+1) == visual_info->colormap_size) &&
8227 ((int) (map_info->blue_max+1) == visual_info->colormap_size)) ?
8228 MagickTrue : MagickFalse;
8229 if (linear_colormap != MagickFalse)
cristybb503372010-05-27 20:51:26 +00008230 number_colors=(size_t) visual_info->colormap_size;
cristy3ed852e2009-09-05 21:47:34 +00008231 /*
8232 Allocate color array.
8233 */
8234 colors=(XColor *) AcquireQuantumMemory(number_colors,sizeof(*colors));
8235 if (colors == (XColor *) NULL)
8236 ThrowXWindowFatalException(ResourceLimitFatalError,
8237 "UnableToCreateColormap",image->filename);
8238 /*
8239 Initialize linear color ramp.
8240 */
8241 p=colors;
8242 color.flags=(char) (DoRed | DoGreen | DoBlue);
8243 if (linear_colormap != MagickFalse)
cristybb503372010-05-27 20:51:26 +00008244 for (i=0; i < (ssize_t) number_colors; i++)
cristy3ed852e2009-09-05 21:47:34 +00008245 {
8246 color.blue=(unsigned short) 0;
8247 if (map_info->blue_max != 0)
cristybb503372010-05-27 20:51:26 +00008248 color.blue=(unsigned short) ((size_t)
cristy3ed852e2009-09-05 21:47:34 +00008249 ((65535L*(i % map_info->green_mult))/map_info->blue_max));
8250 color.green=color.blue;
8251 color.red=color.blue;
8252 color.pixel=XStandardPixel(map_info,&color);
8253 *p++=color;
8254 }
8255 else
cristybb503372010-05-27 20:51:26 +00008256 for (i=0; i < (ssize_t) number_colors; i++)
cristy3ed852e2009-09-05 21:47:34 +00008257 {
8258 color.red=(unsigned short) 0;
8259 if (map_info->red_max != 0)
cristybb503372010-05-27 20:51:26 +00008260 color.red=(unsigned short) ((size_t)
cristy3ed852e2009-09-05 21:47:34 +00008261 ((65535L*(i/map_info->red_mult))/map_info->red_max));
8262 color.green=(unsigned int) 0;
8263 if (map_info->green_max != 0)
cristybb503372010-05-27 20:51:26 +00008264 color.green=(unsigned short) ((size_t)
cristy3ed852e2009-09-05 21:47:34 +00008265 ((65535L*((i/map_info->green_mult) % (map_info->green_max+1)))/
8266 map_info->green_max));
8267 color.blue=(unsigned short) 0;
8268 if (map_info->blue_max != 0)
cristybb503372010-05-27 20:51:26 +00008269 color.blue=(unsigned short) ((size_t)
cristy3ed852e2009-09-05 21:47:34 +00008270 ((65535L*(i % map_info->green_mult))/map_info->blue_max));
8271 color.pixel=XStandardPixel(map_info,&color);
8272 *p++=color;
8273 }
8274 if ((visual_info->klass == DirectColor) &&
8275 (colormap != XDefaultColormap(display,visual_info->screen)))
8276 (void) XStoreColors(display,colormap,colors,(int) number_colors);
8277 else
cristybb503372010-05-27 20:51:26 +00008278 for (i=0; i < (ssize_t) number_colors; i++)
cristy3ed852e2009-09-05 21:47:34 +00008279 (void) XAllocColor(display,colormap,&colors[i]);
8280 break;
8281 }
8282 }
8283 if ((visual_info->klass != DirectColor) &&
8284 (visual_info->klass != TrueColor))
8285 {
8286 /*
8287 Set foreground, background, border, etc. pixels.
8288 */
8289 XBestPixel(display,colormap,colors,(unsigned int) number_colors,
8290 &pixel->foreground_color);
8291 XBestPixel(display,colormap,colors,(unsigned int) number_colors,
8292 &pixel->background_color);
8293 if (pixel->background_color.pixel == pixel->foreground_color.pixel)
8294 {
8295 /*
8296 Foreground and background colors must differ.
8297 */
8298 pixel->background_color.red=(~pixel->foreground_color.red);
8299 pixel->background_color.green=
8300 (~pixel->foreground_color.green);
8301 pixel->background_color.blue=
8302 (~pixel->foreground_color.blue);
8303 XBestPixel(display,colormap,colors,(unsigned int) number_colors,
8304 &pixel->background_color);
8305 }
8306 XBestPixel(display,colormap,colors,(unsigned int) number_colors,
8307 &pixel->border_color);
8308 XBestPixel(display,colormap,colors,(unsigned int) number_colors,
8309 &pixel->matte_color);
8310 XBestPixel(display,colormap,colors,(unsigned int) number_colors,
8311 &pixel->highlight_color);
8312 XBestPixel(display,colormap,colors,(unsigned int) number_colors,
8313 &pixel->shadow_color);
8314 XBestPixel(display,colormap,colors,(unsigned int) number_colors,
8315 &pixel->depth_color);
8316 XBestPixel(display,colormap,colors,(unsigned int) number_colors,
8317 &pixel->trough_color);
8318 for (i=0; i < MaxNumberPens; i++)
8319 {
8320 XBestPixel(display,colormap,colors,(unsigned int) number_colors,
8321 &pixel->pen_colors[i]);
8322 pixel->pixels[image->colors+i]=pixel->pen_colors[i].pixel;
8323 }
cristyc57f6942010-11-12 01:47:39 +00008324 pixel->colors=(ssize_t) (image->colors+MaxNumberPens);
cristy3ed852e2009-09-05 21:47:34 +00008325 }
8326 colors=(XColor *) RelinquishMagickMemory(colors);
8327 if (IsEventLogging())
8328 {
8329 (void) LogMagickEvent(X11Event,GetMagickModule(),"Standard Colormap:");
8330 (void) LogMagickEvent(X11Event,GetMagickModule()," colormap id: 0x%lx",
8331 map_info->colormap);
8332 (void) LogMagickEvent(X11Event,GetMagickModule(),
8333 " red, green, blue max: %lu %lu %lu",map_info->red_max,
8334 map_info->green_max,map_info->blue_max);
8335 (void) LogMagickEvent(X11Event,GetMagickModule(),
8336 " red, green, blue mult: %lu %lu %lu",map_info->red_mult,
8337 map_info->green_mult,map_info->blue_mult);
8338 }
8339}
8340
8341/*
8342%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8343% %
8344% %
8345% %
8346% X M a k e W i n d o w %
8347% %
8348% %
8349% %
8350%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8351%
8352% XMakeWindow() creates an X11 window.
8353%
8354% The format of the XMakeWindow method is:
8355%
8356% void XMakeWindow(Display *display,Window parent,char **argv,int argc,
8357% XClassHint *class_hint,XWMHints *manager_hints,
8358% XWindowInfo *window_info)
8359%
8360% A description of each parameter follows:
8361%
8362% o display: Specifies a connection to an X server; returned from
8363% XOpenDisplay.
8364%
8365% o parent: Specifies the parent window_info.
8366%
8367% o argv: Specifies the application's argument list.
8368%
8369% o argc: Specifies the number of arguments.
8370%
8371% o class_hint: Specifies a pointer to a X11 XClassHint structure.
8372%
8373% o manager_hints: Specifies a pointer to a X11 XWMHints structure.
8374%
8375% o window_info: Specifies a pointer to a X11 XWindowInfo structure.
8376%
8377*/
cristybcbda3f2011-09-03 13:01:22 +00008378MagickPrivate void XMakeWindow(Display *display,Window parent,char **argv,
cristy3ed852e2009-09-05 21:47:34 +00008379 int argc,XClassHint *class_hint,XWMHints *manager_hints,
8380 XWindowInfo *window_info)
8381{
8382#define MinWindowSize 64
8383
8384 Atom
8385 atom_list[2];
8386
8387 int
8388 gravity;
8389
8390 static XTextProperty
8391 icon_name,
8392 window_name;
8393
8394 Status
8395 status;
8396
8397 XSizeHints
8398 *size_hints;
8399
8400 /*
8401 Set window info hints.
8402 */
8403 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
8404 assert(display != (Display *) NULL);
8405 assert(window_info != (XWindowInfo *) NULL);
8406 size_hints=XAllocSizeHints();
8407 if (size_hints == (XSizeHints *) NULL)
8408 ThrowXWindowFatalException(XServerFatalError,"UnableToMakeXWindow",argv[0]);
cristydfe2b662010-08-22 16:17:24 +00008409 size_hints->flags=(int) window_info->flags;
cristy3ed852e2009-09-05 21:47:34 +00008410 size_hints->x=window_info->x;
8411 size_hints->y=window_info->y;
8412 size_hints->width=(int) window_info->width;
8413 size_hints->height=(int) window_info->height;
8414 if (window_info->immutable != MagickFalse)
8415 {
8416 /*
8417 Window size cannot be changed.
8418 */
8419 size_hints->min_width=size_hints->width;
8420 size_hints->min_height=size_hints->height;
8421 size_hints->max_width=size_hints->width;
8422 size_hints->max_height=size_hints->height;
8423 size_hints->flags|=PMinSize;
8424 size_hints->flags|=PMaxSize;
8425 }
8426 else
8427 {
8428 /*
8429 Window size can be changed.
8430 */
8431 size_hints->min_width=(int) window_info->min_width;
8432 size_hints->min_height=(int) window_info->min_height;
8433 size_hints->flags|=PResizeInc;
8434 size_hints->width_inc=(int) window_info->width_inc;
8435 size_hints->height_inc=(int) window_info->height_inc;
8436#if !defined(PRE_R4_ICCCM)
8437 size_hints->flags|=PBaseSize;
8438 size_hints->base_width=size_hints->width_inc;
8439 size_hints->base_height=size_hints->height_inc;
8440#endif
8441 }
8442 gravity=NorthWestGravity;
8443 if (window_info->geometry != (char *) NULL)
8444 {
8445 char
8446 default_geometry[MaxTextExtent],
8447 geometry[MaxTextExtent];
8448
8449 int
8450 flags;
8451
8452 register char
8453 *p;
8454
8455 /*
8456 User specified geometry.
8457 */
cristyb51dff52011-05-19 16:55:47 +00008458 (void) FormatLocaleString(default_geometry,MaxTextExtent,"%dx%d",
cristy3ed852e2009-09-05 21:47:34 +00008459 size_hints->width,size_hints->height);
8460 (void) CopyMagickString(geometry,window_info->geometry,MaxTextExtent);
8461 p=geometry;
8462 while (strlen(p) != 0)
8463 {
8464 if ((isspace((int) ((unsigned char) *p)) == 0) && (*p != '%'))
8465 p++;
8466 else
8467 (void) CopyMagickString(p,p+1,MaxTextExtent);
8468 }
8469 flags=XWMGeometry(display,window_info->screen,geometry,default_geometry,
8470 window_info->border_width,size_hints,&size_hints->x,&size_hints->y,
8471 &size_hints->width,&size_hints->height,&gravity);
8472 if ((flags & WidthValue) && (flags & HeightValue))
8473 size_hints->flags|=USSize;
8474 if ((flags & XValue) && (flags & YValue))
8475 {
8476 size_hints->flags|=USPosition;
8477 window_info->x=size_hints->x;
8478 window_info->y=size_hints->y;
8479 }
8480 }
8481#if !defined(PRE_R4_ICCCM)
8482 size_hints->win_gravity=gravity;
8483 size_hints->flags|=PWinGravity;
8484#endif
8485 if (window_info->id == (Window) NULL)
8486 window_info->id=XCreateWindow(display,parent,window_info->x,window_info->y,
8487 (unsigned int) size_hints->width,(unsigned int) size_hints->height,
8488 window_info->border_width,(int) window_info->depth,InputOutput,
cristyc57f6942010-11-12 01:47:39 +00008489 window_info->visual,(unsigned long) window_info->mask,
8490 &window_info->attributes);
cristy3ed852e2009-09-05 21:47:34 +00008491 else
8492 {
8493 MagickStatusType
8494 mask;
8495
8496 XEvent
8497 sans_event;
8498
8499 XWindowChanges
8500 window_changes;
8501
8502 /*
8503 Window already exists; change relevant attributes.
8504 */
cristyc57f6942010-11-12 01:47:39 +00008505 (void) XChangeWindowAttributes(display,window_info->id,(unsigned long)
8506 window_info->mask,&window_info->attributes);
cristy3ed852e2009-09-05 21:47:34 +00008507 mask=ConfigureNotify;
8508 while (XCheckTypedWindowEvent(display,window_info->id,(int) mask,&sans_event)) ;
8509 window_changes.x=window_info->x;
8510 window_changes.y=window_info->y;
8511 window_changes.width=(int) window_info->width;
8512 window_changes.height=(int) window_info->height;
8513 mask=(MagickStatusType) (CWWidth | CWHeight);
8514 if (window_info->flags & USPosition)
8515 mask|=CWX | CWY;
8516 (void) XReconfigureWMWindow(display,window_info->id,window_info->screen,
8517 mask,&window_changes);
8518 }
8519 if (window_info->id == (Window) NULL)
8520 ThrowXWindowFatalException(XServerFatalError,"UnableToCreateWindow",
8521 window_info->name);
8522 status=XStringListToTextProperty(&window_info->name,1,&window_name);
8523 if (status == False)
8524 ThrowXWindowFatalException(XServerFatalError,"UnableToCreateTextProperty",
8525 window_info->name);
8526 status=XStringListToTextProperty(&window_info->icon_name,1,&icon_name);
8527 if (status == False)
8528 ThrowXWindowFatalException(XServerFatalError,"UnableToCreateTextProperty",
8529 window_info->icon_name);
8530 if (window_info->icon_geometry != (char *) NULL)
8531 {
8532 int
8533 flags,
8534 height,
8535 width;
8536
8537 /*
8538 User specified icon geometry.
8539 */
8540 size_hints->flags|=USPosition;
8541 flags=XWMGeometry(display,window_info->screen,window_info->icon_geometry,
8542 (char *) NULL,0,size_hints,&manager_hints->icon_x,
8543 &manager_hints->icon_y,&width,&height,&gravity);
8544 if ((flags & XValue) && (flags & YValue))
8545 manager_hints->flags|=IconPositionHint;
8546 }
8547 XSetWMProperties(display,window_info->id,&window_name,&icon_name,argv,argc,
8548 size_hints,manager_hints,class_hint);
8549 if (window_name.value != (void *) NULL)
8550 {
8551 (void) XFree((void *) window_name.value);
8552 window_name.value=(unsigned char *) NULL;
8553 window_name.nitems=0;
8554 }
8555 if (icon_name.value != (void *) NULL)
8556 {
8557 (void) XFree((void *) icon_name.value);
8558 icon_name.value=(unsigned char *) NULL;
8559 icon_name.nitems=0;
8560 }
8561 atom_list[0]=XInternAtom(display,"WM_DELETE_WINDOW",MagickFalse);
8562 atom_list[1]=XInternAtom(display,"WM_TAKE_FOCUS",MagickFalse);
8563 (void) XSetWMProtocols(display,window_info->id,atom_list,2);
8564 (void) XFree((void *) size_hints);
8565 if (window_info->shape != MagickFalse)
8566 {
8567#if defined(MAGICKCORE_HAVE_SHAPE)
8568 int
8569 error_base,
8570 event_base;
8571
8572 /*
8573 Can we apply a non-rectangular shaping mask?
8574 */
8575 error_base=0;
8576 event_base=0;
8577 if (XShapeQueryExtension(display,&error_base,&event_base) == 0)
8578 window_info->shape=MagickFalse;
8579#else
8580 window_info->shape=MagickFalse;
8581#endif
8582 }
8583 if (window_info->shared_memory)
8584 {
8585#if defined(MAGICKCORE_HAVE_SHARED_MEMORY)
8586 /*
8587 Can we use shared memory with this window?
8588 */
8589 if (XShmQueryExtension(display) == 0)
8590 window_info->shared_memory=MagickFalse;
8591#else
8592 window_info->shared_memory=MagickFalse;
8593#endif
8594 }
8595 window_info->image=NewImageList();
8596 window_info->destroy=MagickFalse;
8597}
8598
8599/*
8600%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8601% %
8602% %
8603% %
8604% X M a g i c k P r o g r e s s M o n i t o r %
8605% %
8606% %
8607% %
8608%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8609%
8610% XMagickProgressMonitor() displays the progress a task is making in
8611% completing a task.
8612%
8613% The format of the XMagickProgressMonitor method is:
8614%
8615% void XMagickProgressMonitor(const char *task,
8616% const MagickOffsetType quantum,const MagickSizeType span,
8617% void *client_data)
8618%
8619% A description of each parameter follows:
8620%
8621% o task: Identifies the task in progress.
8622%
8623% o quantum: Specifies the quantum position within the span which represents
8624% how much progress has been made in completing a task.
8625%
8626% o span: Specifies the span relative to completing a task.
8627%
8628% o client_data: Pointer to any client data.
8629%
8630*/
8631
8632static const char *GetLocaleMonitorMessage(const char *text)
8633{
8634 char
8635 message[MaxTextExtent],
8636 tag[MaxTextExtent];
8637
8638 const char
8639 *locale_message;
8640
8641 register char
8642 *p;
8643
8644 (void) CopyMagickMemory(tag,text,MaxTextExtent);
8645 p=strrchr(tag,'/');
8646 if (p != (char *) NULL)
8647 *p='\0';
cristyb51dff52011-05-19 16:55:47 +00008648 (void) FormatLocaleString(message,MaxTextExtent,"Monitor/%s",tag);
cristy3ed852e2009-09-05 21:47:34 +00008649 locale_message=GetLocaleMessage(message);
8650 if (locale_message == message)
8651 return(text);
8652 return(locale_message);
8653}
8654
cristybcbda3f2011-09-03 13:01:22 +00008655MagickPrivate MagickBooleanType XMagickProgressMonitor(const char *tag,
cristy3ed852e2009-09-05 21:47:34 +00008656 const MagickOffsetType quantum,const MagickSizeType span,
8657 void *magick_unused(client_data))
8658{
8659 XWindows
8660 *windows;
8661
8662 windows=XSetWindows((XWindows *) ~0);
8663 if (windows == (XWindows *) NULL)
8664 return(MagickTrue);
8665 if (windows->info.mapped != MagickFalse)
8666 XProgressMonitorWidget(windows->display,windows,
8667 GetLocaleMonitorMessage(tag),quantum,span);
8668 return(MagickTrue);
8669}
8670
8671/*
8672%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8673% %
8674% %
8675% %
8676% X Q u e r y C o l o r D a t a b a s e %
8677% %
8678% %
8679% %
8680%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8681%
cristy9950d572011-10-01 18:22:35 +00008682% XQueryColorCompliance() looks up a RGB values for a color given in the target
cristy3ed852e2009-09-05 21:47:34 +00008683% string.
8684%
8685% The format of the XQueryColorDatabase method is:
8686%
cristy9950d572011-10-01 18:22:35 +00008687% MagickBooleanType XQueryColorCompliance(const char *target,XColor *color)
cristy3ed852e2009-09-05 21:47:34 +00008688%
8689% A description of each parameter follows:
8690%
8691% o target: Specifies the color to lookup in the X color database.
8692%
cristy101ab702011-10-13 13:06:32 +00008693% o color: A pointer to an PixelInfo structure. The RGB value of the target
cristy3ed852e2009-09-05 21:47:34 +00008694% color is returned as this value.
8695%
8696*/
cristy9950d572011-10-01 18:22:35 +00008697MagickPrivate MagickBooleanType XQueryColorCompliance(const char *target,
cristy3ed852e2009-09-05 21:47:34 +00008698 XColor *color)
8699{
8700 Colormap
8701 colormap;
8702
8703 static Display
8704 *display = (Display *) NULL;
8705
8706 Status
8707 status;
8708
8709 XColor
8710 xcolor;
8711
8712 /*
8713 Initialize color return value.
8714 */
8715 assert(color != (XColor *) NULL);
8716 color->red=0;
8717 color->green=0;
8718 color->blue=0;
8719 color->flags=(char) (DoRed | DoGreen | DoBlue);
8720 if ((target == (char *) NULL) || (*target == '\0'))
8721 target="#ffffffffffff";
8722 /*
8723 Let the X server define the color for us.
8724 */
8725 if (display == (Display *) NULL)
8726 display=XOpenDisplay((char *) NULL);
8727 if (display == (Display *) NULL)
8728 {
8729 ThrowXWindowFatalException(XServerError,"ColorIsNotKnownToServer",target);
8730 return(MagickFalse);
8731 }
8732 colormap=XDefaultColormap(display,XDefaultScreen(display));
8733 status=XParseColor(display,colormap,(char *) target,&xcolor);
8734 if (status == False)
8735 ThrowXWindowFatalException(XServerError,"ColorIsNotKnownToServer",target)
8736 else
8737 {
8738 color->red=xcolor.red;
8739 color->green=xcolor.green;
8740 color->blue=xcolor.blue;
8741 color->flags=xcolor.flags;
8742 }
8743 return(status != False ? MagickTrue : MagickFalse);
8744}
8745
8746/*
8747%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8748% %
8749% %
8750% %
8751% X Q u e r y P o s i t i o n %
8752% %
8753% %
8754% %
8755%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8756%
8757% XQueryPosition() gets the pointer coordinates relative to a window.
8758%
8759% The format of the XQueryPosition method is:
8760%
8761% void XQueryPosition(Display *display,const Window window,int *x,int *y)
8762%
8763% A description of each parameter follows:
8764%
8765% o display: Specifies a connection to an X server; returned from
8766% XOpenDisplay.
8767%
8768% o window: Specifies a pointer to a Window.
8769%
8770% o x: Return the x coordinate of the pointer relative to the origin of the
8771% window.
8772%
8773% o y: Return the y coordinate of the pointer relative to the origin of the
8774% window.
8775%
8776*/
cristybcbda3f2011-09-03 13:01:22 +00008777MagickPrivate void XQueryPosition(Display *display,const Window window,int *x,int *y)
cristy3ed852e2009-09-05 21:47:34 +00008778{
8779 int
8780 x_root,
8781 y_root;
8782
8783 unsigned int
8784 mask;
8785
8786 Window
8787 root_window;
8788
8789 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
8790 assert(display != (Display *) NULL);
8791 assert(window != (Window) NULL);
8792 assert(x != (int *) NULL);
8793 assert(y != (int *) NULL);
8794 (void) XQueryPointer(display,window,&root_window,&root_window,&x_root,&y_root,
8795 x,y,&mask);
8796}
8797
8798/*
8799%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8800% %
8801% %
8802% %
8803% X R e f r e s h W i n d o w %
8804% %
8805% %
8806% %
8807%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8808%
8809% XRefreshWindow() refreshes an image in a X window.
8810%
8811% The format of the XRefreshWindow method is:
8812%
8813% void XRefreshWindow(Display *display,const XWindowInfo *window,
8814% const XEvent *event)
8815%
8816% A description of each parameter follows:
8817%
8818% o display: Specifies a connection to an X server; returned from
8819% XOpenDisplay.
8820%
8821% o window: Specifies a pointer to a XWindowInfo structure.
8822%
8823% o event: Specifies a pointer to a XEvent structure. If it is NULL,
8824% the entire image is refreshed.
8825%
8826*/
cristybcbda3f2011-09-03 13:01:22 +00008827MagickPrivate void XRefreshWindow(Display *display,const XWindowInfo *window,
cristy3ed852e2009-09-05 21:47:34 +00008828 const XEvent *event)
8829{
8830 int
8831 x,
8832 y;
8833
8834 unsigned int
8835 height,
8836 width;
8837
8838 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
8839 assert(display != (Display *) NULL);
8840 assert(window != (XWindowInfo *) NULL);
8841 if (window->ximage == (XImage *) NULL)
8842 return;
8843 if (event != (XEvent *) NULL)
8844 {
8845 /*
8846 Determine geometry from expose event.
8847 */
8848 x=event->xexpose.x;
8849 y=event->xexpose.y;
8850 width=(unsigned int) event->xexpose.width;
8851 height=(unsigned int) event->xexpose.height;
8852 }
8853 else
8854 {
8855 XEvent
8856 sans_event;
8857
8858 /*
8859 Refresh entire window; discard outstanding expose events.
8860 */
8861 x=0;
8862 y=0;
8863 width=window->width;
8864 height=window->height;
8865 while (XCheckTypedWindowEvent(display,window->id,Expose,&sans_event)) ;
cristya0e5ad52010-02-10 02:05:12 +00008866 if (window->matte_pixmap != (Pixmap) NULL)
8867 {
8868#if defined(MAGICKCORE_HAVE_SHAPE)
8869 if (window->shape != MagickFalse)
8870 XShapeCombineMask(display,window->id,ShapeBounding,0,0,
8871 window->matte_pixmap,ShapeSet);
8872#endif
8873 }
cristy3ed852e2009-09-05 21:47:34 +00008874 }
8875 /*
8876 Check boundary conditions.
8877 */
8878 if ((window->ximage->width-(x+window->x)) < (int) width)
8879 width=(unsigned int) (window->ximage->width-(x+window->x));
8880 if ((window->ximage->height-(y+window->y)) < (int) height)
8881 height=(unsigned int) (window->ximage->height-(y+window->y));
8882 /*
8883 Refresh image.
8884 */
8885 if (window->matte_pixmap != (Pixmap) NULL)
cristya0e5ad52010-02-10 02:05:12 +00008886 (void) XSetClipMask(display,window->annotate_context,window->matte_pixmap);
cristy3ed852e2009-09-05 21:47:34 +00008887 if (window->pixmap != (Pixmap) NULL)
8888 {
8889 if (window->depth > 1)
8890 (void) XCopyArea(display,window->pixmap,window->id,
8891 window->annotate_context,x+window->x,y+window->y,width,height,x,y);
8892 else
8893 (void) XCopyPlane(display,window->pixmap,window->id,
8894 window->highlight_context,x+window->x,y+window->y,width,height,x,y,
8895 1L);
8896 }
8897 else
8898 {
8899#if defined(MAGICKCORE_HAVE_SHARED_MEMORY)
8900 if (window->shared_memory)
8901 (void) XShmPutImage(display,window->id,window->annotate_context,
8902 window->ximage,x+window->x,y+window->y,x,y,width,height,MagickTrue);
8903#endif
8904 if (window->shared_memory == MagickFalse)
8905 (void) XPutImage(display,window->id,window->annotate_context,
8906 window->ximage,x+window->x,y+window->y,x,y,width,height);
8907 }
8908 if (window->matte_pixmap != (Pixmap) NULL)
8909 (void) XSetClipMask(display,window->annotate_context,None);
8910 (void) XFlush(display);
8911}
8912
8913/*
8914%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8915% %
8916% %
8917% %
8918% X R e m o t e C o m m a n d %
8919% %
8920% %
8921% %
8922%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8923%
8924% XRemoteCommand() forces a remote display(1) to display the specified
8925% image filename.
8926%
8927% The format of the XRemoteCommand method is:
8928%
8929% MagickBooleanType XRemoteCommand(Display *display,const char *window,
8930% const char *filename)
8931%
8932% A description of each parameter follows:
8933%
8934% o display: Specifies a connection to an X server; returned from
8935% XOpenDisplay.
8936%
8937% o window: Specifies the name or id of an X window.
8938%
8939% o filename: the name of the image filename to display.
8940%
8941*/
8942MagickExport MagickBooleanType XRemoteCommand(Display *display,
8943 const char *window,const char *filename)
8944{
8945 Atom
8946 remote_atom;
8947
8948 Window
8949 remote_window,
8950 root_window;
8951
8952 assert(filename != (char *) NULL);
8953 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",filename);
8954 if (display == (Display *) NULL)
8955 display=XOpenDisplay((char *) NULL);
8956 if (display == (Display *) NULL)
8957 {
8958 ThrowXWindowException(XServerError,"UnableToOpenXServer",filename);
8959 return(MagickFalse);
8960 }
8961 remote_atom=XInternAtom(display,"IM_PROTOCOLS",MagickFalse);
8962 remote_window=(Window) NULL;
8963 root_window=XRootWindow(display,XDefaultScreen(display));
8964 if (window != (char *) NULL)
8965 {
8966 /*
8967 Search window hierarchy and identify any clients by name or ID.
8968 */
8969 if (isdigit((unsigned char) *window) != 0)
8970 remote_window=XWindowByID(display,root_window,(Window)
8971 strtol((char *) window,(char **) NULL,0));
8972 if (remote_window == (Window) NULL)
8973 remote_window=XWindowByName(display,root_window,window);
8974 }
8975 if (remote_window == (Window) NULL)
8976 remote_window=XWindowByProperty(display,root_window,remote_atom);
8977 if (remote_window == (Window) NULL)
8978 {
8979 ThrowXWindowException(XServerError,"UnableToConnectToRemoteDisplay",
8980 filename);
8981 return(MagickFalse);
8982 }
8983 /*
8984 Send remote command.
8985 */
8986 remote_atom=XInternAtom(display,"IM_REMOTE_COMMAND",MagickFalse);
8987 (void) XChangeProperty(display,remote_window,remote_atom,XA_STRING,8,
8988 PropModeReplace,(unsigned char *) filename,(int) strlen(filename));
8989 (void) XSync(display,MagickFalse);
8990 return(MagickTrue);
8991}
8992
8993/*
8994%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8995% %
8996% %
8997% %
8998% X R e t a i n W i n d o w C o l o r s %
8999% %
9000% %
9001% %
9002%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9003%
9004% XRetainWindowColors() sets X11 color resources on a window. This preserves
9005% the colors associated with an image displayed on the window.
9006%
9007% The format of the XRetainWindowColors method is:
9008%
9009% void XRetainWindowColors(Display *display,const Window window)
9010%
9011% A description of each parameter follows:
9012%
9013% o display: Specifies a connection to an X server; returned from
9014% XOpenDisplay.
9015%
9016% o window: Specifies a pointer to a XWindowInfo structure.
9017%
9018*/
9019MagickExport void XRetainWindowColors(Display *display,const Window window)
9020{
9021 Atom
9022 property;
9023
9024 Pixmap
9025 pixmap;
9026
9027 /*
9028 Put property on the window.
9029 */
9030 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
9031 assert(display != (Display *) NULL);
9032 assert(window != (Window) NULL);
9033 property=XInternAtom(display,"_XSETROOT_ID",MagickFalse);
9034 if (property == (Atom) NULL)
9035 {
9036 ThrowXWindowFatalException(XServerError,"UnableToCreateProperty",
9037 "_XSETROOT_ID");
9038 return;
9039 }
9040 pixmap=XCreatePixmap(display,window,1,1,1);
9041 if (pixmap == (Pixmap) NULL)
9042 {
9043 ThrowXWindowFatalException(XServerError,"UnableToCreateBitmap","");
9044 return;
9045 }
9046 (void) XChangeProperty(display,window,property,XA_PIXMAP,32,PropModeReplace,
9047 (unsigned char *) &pixmap,1);
9048 (void) XSetCloseDownMode(display,RetainPermanent);
9049}
9050
9051/*
9052%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9053% %
9054% %
9055% %
9056% X S e l e c t W i n d o w %
9057% %
9058% %
9059% %
9060%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9061%
9062% XSelectWindow() allows a user to select a window using the mouse. If the
9063% mouse moves, a cropping rectangle is drawn and the extents of the rectangle
9064% is returned in the crop_info structure.
9065%
9066% The format of the XSelectWindow function is:
9067%
9068% target_window=XSelectWindow(display,crop_info)
9069%
9070% A description of each parameter follows:
9071%
9072% o window: XSelectWindow returns the window id.
9073%
9074% o display: Specifies a pointer to the Display structure; returned from
9075% XOpenDisplay.
9076%
9077% o crop_info: Specifies a pointer to a RectangleInfo structure. It
9078% contains the extents of any cropping rectangle.
9079%
cristy3ed852e2009-09-05 21:47:34 +00009080*/
9081static Window XSelectWindow(Display *display,RectangleInfo *crop_info)
9082{
9083#define MinimumCropArea (unsigned int) 9
9084
9085 Cursor
9086 target_cursor;
9087
9088 GC
9089 annotate_context;
9090
9091 int
9092 presses,
9093 x_offset,
9094 y_offset;
9095
9096 Status
9097 status;
9098
9099 Window
9100 root_window,
9101 target_window;
9102
9103 XEvent
9104 event;
9105
9106 XGCValues
9107 context_values;
9108
9109 /*
9110 Initialize graphic context.
9111 */
9112 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
9113 assert(display != (Display *) NULL);
9114 assert(crop_info != (RectangleInfo *) NULL);
9115 root_window=XRootWindow(display,XDefaultScreen(display));
9116 context_values.background=XBlackPixel(display,XDefaultScreen(display));
9117 context_values.foreground=XWhitePixel(display,XDefaultScreen(display));
9118 context_values.function=GXinvert;
9119 context_values.plane_mask=
9120 context_values.background ^ context_values.foreground;
9121 context_values.subwindow_mode=IncludeInferiors;
cristybb503372010-05-27 20:51:26 +00009122 annotate_context=XCreateGC(display,root_window,(size_t) (GCBackground |
cristy3ed852e2009-09-05 21:47:34 +00009123 GCForeground | GCFunction | GCSubwindowMode),&context_values);
9124 if (annotate_context == (GC) NULL)
9125 return(MagickFalse);
9126 /*
9127 Grab the pointer using target cursor.
9128 */
9129 target_cursor=XMakeCursor(display,root_window,XDefaultColormap(display,
9130 XDefaultScreen(display)),(char * ) "white",(char * ) "black");
9131 status=XGrabPointer(display,root_window,MagickFalse,(unsigned int)
9132 (ButtonPressMask | ButtonReleaseMask | ButtonMotionMask),GrabModeSync,
9133 GrabModeAsync,root_window,target_cursor,CurrentTime);
9134 if (status != GrabSuccess)
9135 {
9136 ThrowXWindowFatalException(XServerError,"UnableToGrabMouse","");
9137 return((Window) NULL);
9138 }
9139 /*
9140 Select a window.
9141 */
9142 crop_info->width=0;
9143 crop_info->height=0;
9144 presses=0;
9145 target_window=(Window) NULL;
9146 x_offset=0;
9147 y_offset=0;
9148 do
9149 {
9150 if ((crop_info->width*crop_info->height) >= MinimumCropArea)
9151 (void) XDrawRectangle(display,root_window,annotate_context,
9152 (int) crop_info->x,(int) crop_info->y,(unsigned int) crop_info->width-1,
9153 (unsigned int) crop_info->height-1);
9154 /*
9155 Allow another event.
9156 */
9157 (void) XAllowEvents(display,SyncPointer,CurrentTime);
9158 (void) XWindowEvent(display,root_window,ButtonPressMask |
9159 ButtonReleaseMask | ButtonMotionMask,&event);
9160 if ((crop_info->width*crop_info->height) >= MinimumCropArea)
9161 (void) XDrawRectangle(display,root_window,annotate_context,
9162 (int) crop_info->x,(int) crop_info->y,(unsigned int) crop_info->width-1,
9163 (unsigned int) crop_info->height-1);
9164 switch (event.type)
9165 {
9166 case ButtonPress:
9167 {
9168 target_window=XGetSubwindow(display,event.xbutton.subwindow,
9169 event.xbutton.x,event.xbutton.y);
9170 if (target_window == (Window) NULL)
9171 target_window=root_window;
9172 x_offset=event.xbutton.x_root;
9173 y_offset=event.xbutton.y_root;
cristyecd0ab52010-05-30 14:59:20 +00009174 crop_info->x=(ssize_t) x_offset;
9175 crop_info->y=(ssize_t) y_offset;
cristy3ed852e2009-09-05 21:47:34 +00009176 crop_info->width=0;
9177 crop_info->height=0;
9178 presses++;
9179 break;
9180 }
9181 case ButtonRelease:
9182 {
9183 presses--;
9184 break;
9185 }
9186 case MotionNotify:
9187 {
9188 /*
9189 Discard pending button motion events.
9190 */
9191 while (XCheckMaskEvent(display,ButtonMotionMask,&event)) ;
cristyecd0ab52010-05-30 14:59:20 +00009192 crop_info->x=(ssize_t) event.xmotion.x;
9193 crop_info->y=(ssize_t) event.xmotion.y;
cristy3ed852e2009-09-05 21:47:34 +00009194 /*
9195 Check boundary conditions.
9196 */
9197 if ((int) crop_info->x < x_offset)
cristyecd0ab52010-05-30 14:59:20 +00009198 crop_info->width=(size_t) (x_offset-crop_info->x);
cristy3ed852e2009-09-05 21:47:34 +00009199 else
9200 {
cristyecd0ab52010-05-30 14:59:20 +00009201 crop_info->width=(size_t) (crop_info->x-x_offset);
9202 crop_info->x=(ssize_t) x_offset;
cristy3ed852e2009-09-05 21:47:34 +00009203 }
9204 if ((int) crop_info->y < y_offset)
cristyecd0ab52010-05-30 14:59:20 +00009205 crop_info->height=(size_t) (y_offset-crop_info->y);
cristy3ed852e2009-09-05 21:47:34 +00009206 else
9207 {
cristyecd0ab52010-05-30 14:59:20 +00009208 crop_info->height=(size_t) (crop_info->y-y_offset);
9209 crop_info->y=(ssize_t) y_offset;
cristy3ed852e2009-09-05 21:47:34 +00009210 }
9211 }
9212 default:
9213 break;
9214 }
9215 } while ((target_window == (Window) NULL) || (presses > 0));
9216 (void) XUngrabPointer(display,CurrentTime);
9217 (void) XFreeCursor(display,target_cursor);
9218 (void) XFreeGC(display,annotate_context);
9219 if ((crop_info->width*crop_info->height) < MinimumCropArea)
9220 {
9221 crop_info->width=0;
9222 crop_info->height=0;
9223 }
9224 if ((crop_info->width != 0) && (crop_info->height != 0))
9225 target_window=root_window;
9226 return(target_window);
9227}
9228
9229/*
9230%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9231% %
9232% %
9233% %
9234% X S e t C u r s o r S t a t e %
9235% %
9236% %
9237% %
9238%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9239%
9240% XSetCursorState() sets the cursor state to busy, otherwise the cursor are
9241% reset to their default.
9242%
9243% The format of the XXSetCursorState method is:
9244%
9245% XSetCursorState(display,windows,const MagickStatusType state)
9246%
9247% A description of each parameter follows:
9248%
9249% o display: Specifies a connection to an X server; returned from
9250% XOpenDisplay.
9251%
9252% o windows: Specifies a pointer to a XWindows structure.
9253%
9254% o state: An unsigned integer greater than 0 sets the cursor state
9255% to busy, otherwise the cursor are reset to their default.
9256%
9257*/
cristybcbda3f2011-09-03 13:01:22 +00009258MagickPrivate void XSetCursorState(Display *display,XWindows *windows,
cristy3ed852e2009-09-05 21:47:34 +00009259 const MagickStatusType state)
9260{
9261 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
9262 assert(display != (Display *) NULL);
9263 assert(windows != (XWindows *) NULL);
9264 if (state)
9265 {
9266 (void) XCheckDefineCursor(display,windows->image.id,
9267 windows->image.busy_cursor);
9268 (void) XCheckDefineCursor(display,windows->pan.id,
9269 windows->pan.busy_cursor);
9270 (void) XCheckDefineCursor(display,windows->magnify.id,
9271 windows->magnify.busy_cursor);
9272 (void) XCheckDefineCursor(display,windows->command.id,
9273 windows->command.busy_cursor);
9274 }
9275 else
9276 {
9277 (void) XCheckDefineCursor(display,windows->image.id,
9278 windows->image.cursor);
9279 (void) XCheckDefineCursor(display,windows->pan.id,windows->pan.cursor);
9280 (void) XCheckDefineCursor(display,windows->magnify.id,
9281 windows->magnify.cursor);
9282 (void) XCheckDefineCursor(display,windows->command.id,
9283 windows->command.cursor);
9284 (void) XCheckDefineCursor(display,windows->command.id,
9285 windows->widget.cursor);
9286 (void) XWithdrawWindow(display,windows->info.id,windows->info.screen);
9287 }
9288 windows->info.mapped=MagickFalse;
9289}
9290
9291/*
9292%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9293% %
9294% %
9295% %
9296% X S e t W i n d o w s %
9297% %
9298% %
9299% %
9300%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9301%
9302% XSetWindows() sets the X windows structure if the windows info is specified.
9303% Otherwise the current windows structure is returned.
9304%
9305% The format of the XSetWindows method is:
9306%
9307% XWindows *XSetWindows(XWindows *windows_info)
9308%
9309% A description of each parameter follows:
9310%
9311% o windows_info: Initialize the Windows structure with this information.
9312%
9313*/
cristybcbda3f2011-09-03 13:01:22 +00009314MagickPrivate XWindows *XSetWindows(XWindows *windows_info)
cristy3ed852e2009-09-05 21:47:34 +00009315{
9316 static XWindows
9317 *windows = (XWindows *) NULL;
9318
9319 if (windows_info != (XWindows *) ~0)
9320 {
9321 windows=(XWindows *) RelinquishMagickMemory(windows);
9322 windows=windows_info;
9323 }
9324 return(windows);
9325}
9326/*
9327%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9328% %
9329% %
9330% %
9331% X U s e r P r e f e r e n c e s %
9332% %
9333% %
9334% %
9335%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9336%
9337% XUserPreferences() saves the preferences in a configuration file in the
9338% users' home directory.
9339%
9340% The format of the XUserPreferences method is:
9341%
9342% void XUserPreferences(XResourceInfo *resource_info)
9343%
9344% A description of each parameter follows:
9345%
9346% o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
9347%
9348*/
cristybcbda3f2011-09-03 13:01:22 +00009349MagickPrivate void XUserPreferences(XResourceInfo *resource_info)
cristy3ed852e2009-09-05 21:47:34 +00009350{
9351#if defined(X11_PREFERENCES_PATH)
9352 char
9353 cache[MaxTextExtent],
9354 filename[MaxTextExtent],
9355 specifier[MaxTextExtent];
9356
9357 const char
cristy104cea82009-10-25 02:26:51 +00009358 *client_name,
cristy3ed852e2009-09-05 21:47:34 +00009359 *value;
9360
9361 XrmDatabase
9362 preferences_database;
9363
9364 /*
9365 Save user preferences to the client configuration file.
9366 */
9367 assert(resource_info != (XResourceInfo *) NULL);
cristy104cea82009-10-25 02:26:51 +00009368 client_name=GetClientName();
cristy3ed852e2009-09-05 21:47:34 +00009369 preferences_database=XrmGetStringDatabase("");
cristyb51dff52011-05-19 16:55:47 +00009370 (void) FormatLocaleString(specifier,MaxTextExtent,"%s.backdrop",client_name);
cristy3ed852e2009-09-05 21:47:34 +00009371 value=resource_info->backdrop ? "True" : "False";
9372 XrmPutStringResource(&preferences_database,specifier,(char *) value);
cristyb51dff52011-05-19 16:55:47 +00009373 (void) FormatLocaleString(specifier,MaxTextExtent,"%s.colormap",client_name);
cristy3ed852e2009-09-05 21:47:34 +00009374 value=resource_info->colormap == SharedColormap ? "Shared" : "Private";
9375 XrmPutStringResource(&preferences_database,specifier,(char *) value);
cristyb51dff52011-05-19 16:55:47 +00009376 (void) FormatLocaleString(specifier,MaxTextExtent,"%s.confirmExit",
cristy104cea82009-10-25 02:26:51 +00009377 client_name);
cristy3ed852e2009-09-05 21:47:34 +00009378 value=resource_info->confirm_exit ? "True" : "False";
9379 XrmPutStringResource(&preferences_database,specifier,(char *) value);
cristyb51dff52011-05-19 16:55:47 +00009380 (void) FormatLocaleString(specifier,MaxTextExtent,"%s.confirmEdit",
cristy104cea82009-10-25 02:26:51 +00009381 client_name);
cristy3ed852e2009-09-05 21:47:34 +00009382 value=resource_info->confirm_edit ? "True" : "False";
9383 XrmPutStringResource(&preferences_database,specifier,(char *) value);
cristyb51dff52011-05-19 16:55:47 +00009384 (void) FormatLocaleString(specifier,MaxTextExtent,"%s.displayWarnings",
cristy104cea82009-10-25 02:26:51 +00009385 client_name);
cristy3ed852e2009-09-05 21:47:34 +00009386 value=resource_info->display_warnings ? "True" : "False";
9387 XrmPutStringResource(&preferences_database,specifier,(char *) value);
cristyb51dff52011-05-19 16:55:47 +00009388 (void) FormatLocaleString(specifier,MaxTextExtent,"%s.dither",client_name);
cristy3ed852e2009-09-05 21:47:34 +00009389 value=resource_info->quantize_info->dither ? "True" : "False";
9390 XrmPutStringResource(&preferences_database,specifier,(char *) value);
cristyb51dff52011-05-19 16:55:47 +00009391 (void) FormatLocaleString(specifier,MaxTextExtent,"%s.gammaCorrect",
cristy104cea82009-10-25 02:26:51 +00009392 client_name);
cristy3ed852e2009-09-05 21:47:34 +00009393 value=resource_info->gamma_correct ? "True" : "False";
9394 XrmPutStringResource(&preferences_database,specifier,(char *) value);
cristyb51dff52011-05-19 16:55:47 +00009395 (void) FormatLocaleString(specifier,MaxTextExtent,"%s.undoCache",client_name);
9396 (void) FormatLocaleString(cache,MaxTextExtent,"%.20g",(double)
cristy3ed852e2009-09-05 21:47:34 +00009397 resource_info->undo_cache);
9398 XrmPutStringResource(&preferences_database,specifier,cache);
cristyb51dff52011-05-19 16:55:47 +00009399 (void) FormatLocaleString(specifier,MaxTextExtent,"%s.usePixmap",client_name);
cristy3ed852e2009-09-05 21:47:34 +00009400 value=resource_info->use_pixmap ? "True" : "False";
9401 XrmPutStringResource(&preferences_database,specifier,(char *) value);
cristyb51dff52011-05-19 16:55:47 +00009402 (void) FormatLocaleString(filename,MaxTextExtent,"%s%src",
cristy104cea82009-10-25 02:26:51 +00009403 X11_PREFERENCES_PATH,client_name);
cristy3ed852e2009-09-05 21:47:34 +00009404 ExpandFilename(filename);
9405 XrmPutFileDatabase(preferences_database,filename);
9406#endif
9407}
9408
9409/*
9410%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9411% %
9412% %
9413% %
9414% X V i s u a l C l a s s N a m e %
9415% %
9416% %
9417% %
9418%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9419%
9420% XVisualClassName() returns the visual class name as a character string.
9421%
9422% The format of the XVisualClassName method is:
9423%
9424% char *XVisualClassName(const int visual_class)
9425%
9426% A description of each parameter follows:
9427%
9428% o visual_type: XVisualClassName returns the visual class as a character
9429% string.
9430%
9431% o class: Specifies the visual class.
9432%
cristy3ed852e2009-09-05 21:47:34 +00009433*/
9434static const char *XVisualClassName(const int visual_class)
9435{
9436 switch (visual_class)
9437 {
9438 case StaticGray: return("StaticGray");
9439 case GrayScale: return("GrayScale");
9440 case StaticColor: return("StaticColor");
9441 case PseudoColor: return("PseudoColor");
9442 case TrueColor: return("TrueColor");
9443 case DirectColor: return("DirectColor");
9444 }
9445 return("unknown visual class");
9446}
9447
9448/*
9449%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9450% %
9451% %
9452% %
9453% X W a r n i n g %
9454% %
9455% %
9456% %
9457%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9458%
9459% XWarning() displays a warning reason in a Notice widget.
9460%
9461% The format of the XWarning method is:
9462%
9463% void XWarning(const unsigned int warning,const char *reason,
9464% const char *description)
9465%
9466% A description of each parameter follows:
9467%
9468% o warning: Specifies the numeric warning category.
9469%
9470% o reason: Specifies the reason to display before terminating the
9471% program.
9472%
9473% o description: Specifies any description to the reason.
9474%
9475*/
cristybcbda3f2011-09-03 13:01:22 +00009476MagickPrivate void XWarning(const ExceptionType magick_unused(warning),
cristy3ed852e2009-09-05 21:47:34 +00009477 const char *reason,const char *description)
9478{
9479 char
9480 text[MaxTextExtent];
9481
9482 XWindows
9483 *windows;
9484
9485 if (reason == (char *) NULL)
9486 return;
9487 (void) CopyMagickString(text,reason,MaxTextExtent);
9488 (void) ConcatenateMagickString(text,":",MaxTextExtent);
9489 windows=XSetWindows((XWindows *) ~0);
9490 XNoticeWidget(windows->display,windows,text,(char *) description);
9491}
9492
9493/*
9494%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9495% %
9496% %
9497% %
9498% X W i n d o w B y I D %
9499% %
9500% %
9501% %
9502%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9503%
9504% XWindowByID() locates a child window with a given ID. If not window with
9505% the given name is found, 0 is returned. Only the window specified and its
9506% subwindows are searched.
9507%
9508% The format of the XWindowByID function is:
9509%
9510% child=XWindowByID(display,window,id)
9511%
9512% A description of each parameter follows:
9513%
9514% o child: XWindowByID returns the window with the specified
9515% id. If no windows are found, XWindowByID returns 0.
9516%
9517% o display: Specifies a pointer to the Display structure; returned from
9518% XOpenDisplay.
9519%
9520% o id: Specifies the id of the window to locate.
9521%
9522*/
cristybcbda3f2011-09-03 13:01:22 +00009523MagickPrivate Window XWindowByID(Display *display,const Window root_window,
cristybb503372010-05-27 20:51:26 +00009524 const size_t id)
cristy3ed852e2009-09-05 21:47:34 +00009525{
9526 RectangleInfo
9527 rectangle_info;
9528
9529 register int
9530 i;
9531
9532 Status
9533 status;
9534
9535 unsigned int
9536 number_children;
9537
9538 Window
9539 child,
9540 *children,
9541 window;
9542
9543 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
9544 assert(display != (Display *) NULL);
9545 assert(root_window != (Window) NULL);
9546 if (id == 0)
9547 return(XSelectWindow(display,&rectangle_info));
9548 if (root_window == id)
cristydfe2b662010-08-22 16:17:24 +00009549 return(root_window);
cristy3ed852e2009-09-05 21:47:34 +00009550 status=XQueryTree(display,root_window,&child,&child,&children,
9551 &number_children);
9552 if (status == False)
9553 return((Window) NULL);
9554 window=(Window) NULL;
9555 for (i=0; i < (int) number_children; i++)
9556 {
9557 /*
9558 Search each child and their children.
9559 */
9560 window=XWindowByID(display,children[i],id);
9561 if (window != (Window) NULL)
9562 break;
9563 }
9564 if (children != (Window *) NULL)
9565 (void) XFree((void *) children);
9566 return(window);
9567}
9568
9569/*
9570%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9571% %
9572% %
9573% %
9574% X W i n d o w B y N a m e %
9575% %
9576% %
9577% %
9578%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9579%
9580% XWindowByName() locates a window with a given name on a display. If no
9581% window with the given name is found, 0 is returned. If more than one window
9582% has the given name, the first one is returned. Only root and its children
9583% are searched.
9584%
9585% The format of the XWindowByName function is:
9586%
9587% window=XWindowByName(display,root_window,name)
9588%
9589% A description of each parameter follows:
9590%
9591% o window: XWindowByName returns the window id.
9592%
9593% o display: Specifies a pointer to the Display structure; returned from
9594% XOpenDisplay.
9595%
9596% o root_window: Specifies the id of the root window.
9597%
9598% o name: Specifies the name of the window to locate.
9599%
9600*/
cristybcbda3f2011-09-03 13:01:22 +00009601MagickPrivate Window XWindowByName(Display *display,const Window root_window,
cristy3ed852e2009-09-05 21:47:34 +00009602 const char *name)
9603{
9604 register int
9605 i;
9606
9607 Status
9608 status;
9609
9610 unsigned int
9611 number_children;
9612
9613 Window
9614 *children,
9615 child,
9616 window;
9617
9618 XTextProperty
9619 window_name;
9620
9621 assert(display != (Display *) NULL);
9622 assert(root_window != (Window) NULL);
9623 assert(name != (char *) NULL);
9624 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",name);
9625 if (XGetWMName(display,root_window,&window_name) != 0)
9626 if (LocaleCompare((char *) window_name.value,name) == 0)
9627 return(root_window);
9628 status=XQueryTree(display,root_window,&child,&child,&children,
9629 &number_children);
9630 if (status == False)
9631 return((Window) NULL);
9632 window=(Window) NULL;
9633 for (i=0; i < (int) number_children; i++)
9634 {
9635 /*
9636 Search each child and their children.
9637 */
9638 window=XWindowByName(display,children[i],name);
9639 if (window != (Window) NULL)
9640 break;
9641 }
9642 if (children != (Window *) NULL)
9643 (void) XFree((void *) children);
9644 return(window);
9645}
9646
9647/*
9648%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9649% %
9650% %
9651% %
9652% X W i n d o w B y P r o p e r y %
9653% %
9654% %
9655% %
9656%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9657%
9658% XWindowByProperty() locates a child window with a given property. If not
9659% window with the given name is found, 0 is returned. If more than one window
9660% has the given property, the first one is returned. Only the window
9661% specified and its subwindows are searched.
9662%
9663% The format of the XWindowByProperty function is:
9664%
9665% child=XWindowByProperty(display,window,property)
9666%
9667% A description of each parameter follows:
9668%
9669% o child: XWindowByProperty returns the window id with the specified
9670% property. If no windows are found, XWindowByProperty returns 0.
9671%
9672% o display: Specifies a pointer to the Display structure; returned from
9673% XOpenDisplay.
9674%
9675% o property: Specifies the property of the window to locate.
9676%
9677*/
cristybcbda3f2011-09-03 13:01:22 +00009678MagickPrivate Window XWindowByProperty(Display *display,const Window window,
cristy3ed852e2009-09-05 21:47:34 +00009679 const Atom property)
9680{
9681 Atom
9682 type;
9683
9684 int
9685 format;
9686
9687 Status
9688 status;
9689
9690 unsigned char
9691 *data;
9692
9693 unsigned int
9694 i,
9695 number_children;
9696
cristyf2faecf2010-05-28 19:19:36 +00009697 unsigned long
cristy3ed852e2009-09-05 21:47:34 +00009698 after,
9699 number_items;
9700
9701 Window
9702 child,
9703 *children,
9704 parent,
9705 root;
9706
9707 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
9708 assert(display != (Display *) NULL);
9709 assert(window != (Window) NULL);
9710 assert(property != (Atom) NULL);
9711 status=XQueryTree(display,window,&root,&parent,&children,&number_children);
9712 if (status == False)
9713 return((Window) NULL);
9714 type=(Atom) NULL;
9715 child=(Window) NULL;
9716 for (i=0; (i < number_children) && (child == (Window) NULL); i++)
9717 {
9718 status=XGetWindowProperty(display,children[i],property,0L,0L,MagickFalse,
9719 (Atom) AnyPropertyType,&type,&format,&number_items,&after,&data);
9720 if (data != NULL)
9721 (void) XFree((void *) data);
9722 if ((status == Success) && (type != (Atom) NULL))
9723 child=children[i];
9724 }
9725 for (i=0; (i < number_children) && (child == (Window) NULL); i++)
9726 child=XWindowByProperty(display,children[i],property);
9727 if (children != (Window *) NULL)
9728 (void) XFree((void *) children);
9729 return(child);
9730}
9731#else
9732
9733/*
9734%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9735% %
9736% %
9737% %
9738% X I m p o r t I m a g e %
9739% %
9740% %
9741% %
9742%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9743%
9744% XImportImage() reads an image from an X window.
9745%
9746% The format of the XImportImage method is:
9747%
cristya0dc96a2011-12-19 23:58:54 +00009748% Image *XImportImage(const ImageInfo *image_info,XImportInfo *ximage_info,
9749% ExceptionInfo *exception)
cristy3ed852e2009-09-05 21:47:34 +00009750%
9751% A description of each parameter follows:
9752%
9753% o image_info: the image info..
9754%
9755% o ximage_info: Specifies a pointer to an XImportInfo structure.
9756%
cristya0dc96a2011-12-19 23:58:54 +00009757% o exception: return any errors or warnings in this structure.
9758%
cristy3ed852e2009-09-05 21:47:34 +00009759*/
cristybcbda3f2011-09-03 13:01:22 +00009760MagickPrivate Image *XImportImage(const ImageInfo *image_info,
cristya0dc96a2011-12-19 23:58:54 +00009761 XImportInfo *ximage_info,ExceptionInfo *exception)
cristy3ed852e2009-09-05 21:47:34 +00009762{
9763 assert(image_info != (const ImageInfo *) NULL);
9764 assert(image_info->signature == MagickSignature);
9765 if (image_info->debug != MagickFalse)
9766 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
9767 image_info->filename);
9768 assert(ximage_info != (XImportInfo *) NULL);
cristya0dc96a2011-12-19 23:58:54 +00009769 assert(exception != (ExceptionInfo *) NULL);
9770 assert(exception->signature == MagickSignature);
cristy3ed852e2009-09-05 21:47:34 +00009771 return((Image *) NULL);
9772}
9773#endif
9774
9775/*
9776%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9777% %
9778% %
9779% %
cristy576974e2009-10-25 20:45:31 +00009780+ X C o m p o n e n t G e n e s i s %
9781% %
9782% %
9783% %
9784%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9785%
9786% XComponentGenesis() instantiates the X component.
9787%
9788% The format of the XComponentGenesis method is:
9789%
9790% MagickBooleanType XComponentGenesis(void)
9791%
9792*/
cristy5ff4eaf2011-09-03 01:38:02 +00009793MagickPrivate MagickBooleanType XComponentGenesis(void)
cristy576974e2009-10-25 20:45:31 +00009794{
9795 return(MagickTrue);
9796}
9797
9798/*
9799%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9800% %
9801% %
9802% %
cristy3ed852e2009-09-05 21:47:34 +00009803% X G e t I m p o r t I n f o %
9804% %
9805% %
9806% %
9807%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9808%
9809% XGetImportInfo() initializes the XImportInfo structure.
9810%
9811% The format of the XGetImportInfo method is:
9812%
9813% void XGetImportInfo(XImportInfo *ximage_info)
9814%
9815% A description of each parameter follows:
9816%
9817% o ximage_info: Specifies a pointer to an ImageInfo structure.
9818%
9819*/
9820MagickExport void XGetImportInfo(XImportInfo *ximage_info)
9821{
9822 assert(ximage_info != (XImportInfo *) NULL);
9823 ximage_info->frame=MagickFalse;
9824 ximage_info->borders=MagickFalse;
9825 ximage_info->screen=MagickFalse;
9826 ximage_info->descend=MagickTrue;
9827 ximage_info->silent=MagickFalse;
9828}