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