blob: 395dabbcf7a9d9f0e9f89785360df90c7ceae111 [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% %
cristy7e41fe82010-12-04 23:12:08 +000020% Copyright 1999-2011 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"
52#include "MagickCore/display.h"
53#include "MagickCore/exception.h"
54#include "MagickCore/exception-private.h"
55#include "MagickCore/geometry.h"
56#include "MagickCore/identify.h"
57#include "MagickCore/image.h"
58#include "MagickCore/image-private.h"
59#include "MagickCore/list.h"
60#include "MagickCore/locale_.h"
61#include "MagickCore/log.h"
62#include "MagickCore/magick.h"
63#include "MagickCore/memory_.h"
64#include "MagickCore/monitor.h"
65#include "MagickCore/option.h"
66#include "MagickCore/pixel-accessor.h"
67#include "MagickCore/PreRvIcccm.h"
68#include "MagickCore/quantize.h"
69#include "MagickCore/quantum.h"
70#include "MagickCore/quantum-private.h"
71#include "MagickCore/resource_.h"
72#include "MagickCore/resize.h"
73#include "MagickCore/shear.h"
74#include "MagickCore/statistic.h"
75#include "MagickCore/string_.h"
76#include "MagickCore/string-private.h"
77#include "MagickCore/transform.h"
78#include "MagickCore/utility.h"
cristyd1dd6e42011-09-04 01:46:08 +000079#include "MagickCore/utility-private.h"
cristy4c08aed2011-07-01 19:47:50 +000080#include "MagickCore/widget.h"
cristybcbda3f2011-09-03 13:01:22 +000081#include "MagickCore/widget-private.h"
cristy4c08aed2011-07-01 19:47:50 +000082#include "MagickCore/xwindow.h"
83#include "MagickCore/xwindow-private.h"
84#include "MagickCore/version.h"
cristy3ed852e2009-09-05 21:47:34 +000085#if defined(__BEOS__)
86#include <OS.h>
87#endif
88#if defined(MAGICKCORE_X11_DELEGATE)
89#include <X11/Xproto.h>
90#include <X11/Xlocale.h>
91#if defined(MAGICK_HAVE_POLL)
92# include <sys/poll.h>
93#endif
94#if defined(MAGICKCORE_HAVE_SHARED_MEMORY)
95#if defined(MAGICKCORE_HAVE_MACHINE_PARAM_H)
96# include <machine/param.h>
97#endif
98#include <sys/ipc.h>
99#include <sys/shm.h>
100#include <X11/extensions/XShm.h>
101#endif
102#if defined(MAGICKCORE_HAVE_SHAPE)
103#include <X11/extensions/shape.h>
104#endif
105
106/*
107 X defines.
108*/
cristyce70c172010-01-07 17:15:30 +0000109#define XBlueGamma(color) ClampToQuantum(blue_gamma == 1.0 ? (double) \
cristy3ed852e2009-09-05 21:47:34 +0000110 (color) : ((pow(((double) QuantumScale*(color)),1.0/(double) blue_gamma)* \
111 QuantumRange)))
cristy4c08aed2011-07-01 19:47:50 +0000112#define XGammaPacket(map,color) (size_t) (map->base_pixel+ \
cristy7e9f2332011-04-22 23:12:22 +0000113 ((ScaleQuantumToShort(XRedGamma((color)->red))*map->red_max/65535L)* \
114 map->red_mult)+ \
115 ((ScaleQuantumToShort(XGreenGamma((color)->green))*map->green_max/65535L)* \
116 map->green_mult)+ \
117 ((ScaleQuantumToShort(XBlueGamma((color)->blue))*map->blue_max/65535L)* \
118 map->blue_mult))
cristy4c08aed2011-07-01 19:47:50 +0000119#define XGammaPixel(image,map,color) (size_t) (map->base_pixel+ \
120 ((ScaleQuantumToShort(XRedGamma(GetPixelRed(image,color)))*map->red_max/65535L)* \
121 map->red_mult)+ \
122 ((ScaleQuantumToShort(XGreenGamma(GetPixelGreen(image,color)))*map->green_max/65535L)* \
123 map->green_mult)+ \
124 ((ScaleQuantumToShort(XBlueGamma(GetPixelBlue(image,color)))*map->blue_max/65535L)* \
125 map->blue_mult))
cristyce70c172010-01-07 17:15:30 +0000126#define XGreenGamma(color) ClampToQuantum(green_gamma == 1.0 ? (double) \
cristy3ed852e2009-09-05 21:47:34 +0000127 (color) : ((pow(((double) QuantumScale*(color)),1.0/(double) green_gamma)* \
128 QuantumRange)))
cristyce70c172010-01-07 17:15:30 +0000129#define XRedGamma(color) ClampToQuantum(red_gamma == 1.0 ? (double) \
cristy3ed852e2009-09-05 21:47:34 +0000130 (color) : ((pow(((double) QuantumScale*(color)),1.0/(double) red_gamma)* \
131 QuantumRange)))
cristybb503372010-05-27 20:51:26 +0000132#define XStandardPixel(map,color) (size_t) (map->base_pixel+ \
cristy7e9f2332011-04-22 23:12:22 +0000133 (((color)->red*map->red_max/65535L)*map->red_mult)+ \
134 (((color)->green*map->green_max/65535L)*map->green_mult)+ \
135 (((color)->blue*map->blue_max/65535L)*map->blue_mult))
cristy3ed852e2009-09-05 21:47:34 +0000136
137#define AccentuateModulate ScaleCharToQuantum(80)
138#define HighlightModulate ScaleCharToQuantum(125)
139#define ShadowModulate ScaleCharToQuantum(135)
140#define DepthModulate ScaleCharToQuantum(185)
141#define TroughModulate ScaleCharToQuantum(110)
142
143#define XLIB_ILLEGAL_ACCESS 1
144#undef ForgetGravity
145#undef NorthWestGravity
146#undef NorthGravity
147#undef NorthEastGravity
148#undef WestGravity
149#undef CenterGravity
150#undef EastGravity
151#undef SouthWestGravity
152#undef SouthGravity
153#undef SouthEastGravity
154#undef StaticGravity
155
156#undef index
157#if defined(hpux9)
158#define XFD_SET int
159#else
160#define XFD_SET fd_set
161#endif
162
163/*
164 Enumeration declarations.
165*/
166typedef enum
167{
168#undef DoRed
169 DoRed = 0x0001,
170#undef DoGreen
171 DoGreen = 0x0002,
172#undef DoBlue
173 DoBlue = 0x0004,
174 DoMatte = 0x0008
175} XColorFlags;
176
177/*
178 Typedef declarations.
179*/
180typedef struct _DiversityPacket
181{
182 Quantum
183 red,
184 green,
185 blue;
186
187 unsigned short
188 index;
189
cristybb503372010-05-27 20:51:26 +0000190 size_t
cristy3ed852e2009-09-05 21:47:34 +0000191 count;
192} DiversityPacket;
193
194/*
195 Constant declaractions.
196*/
197static MagickBooleanType
198 xerror_alert = MagickFalse;
199
200/*
201 Method prototypes.
202*/
203static const char
204 *XVisualClassName(const int);
205
206static MagickRealType
207 blue_gamma = 1.0,
208 green_gamma = 1.0,
209 red_gamma = 1.0;
210
211static MagickBooleanType
212 XMakePixmap(Display *,const XResourceInfo *,XWindowInfo *);
213
214static void
215 XMakeImageLSBFirst(const XResourceInfo *,const XWindowInfo *,Image *,
216 XImage *,XImage *),
217 XMakeImageMSBFirst(const XResourceInfo *,const XWindowInfo *,Image *,
218 XImage *,XImage *);
219
220static Window
221 XSelectWindow(Display *,RectangleInfo *);
222
223/*
224%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
225% %
226% %
227% %
228% D e s t r o y X R e s o u r c e s %
229% %
230% %
231% %
232%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
233%
234% DestroyXResources() destroys any X resources.
235%
236% The format of the DestroyXResources method is:
237%
238% void DestroyXResources()
239%
240% A description of each parameter follows:
241%
242*/
243MagickExport void DestroyXResources(void)
244{
245 register int
246 i;
247
248 unsigned int
249 number_windows;
250
251 XWindowInfo
252 *magick_windows[MaxXWindows];
253
254 XWindows
255 *windows;
256
257 DestroyXWidget();
258 windows=XSetWindows((XWindows *) ~0);
259 if ((windows == (XWindows *) NULL) || (windows->display == (Display *) NULL))
260 return;
261 number_windows=0;
262 magick_windows[number_windows++]=(&windows->context);
263 magick_windows[number_windows++]=(&windows->group_leader);
264 magick_windows[number_windows++]=(&windows->backdrop);
265 magick_windows[number_windows++]=(&windows->icon);
266 magick_windows[number_windows++]=(&windows->image);
267 magick_windows[number_windows++]=(&windows->info);
268 magick_windows[number_windows++]=(&windows->magnify);
269 magick_windows[number_windows++]=(&windows->pan);
270 magick_windows[number_windows++]=(&windows->command);
271 magick_windows[number_windows++]=(&windows->widget);
272 magick_windows[number_windows++]=(&windows->popup);
273 magick_windows[number_windows++]=(&windows->context);
274 for (i=0; i < (int) number_windows; i++)
275 {
276 if (magick_windows[i]->mapped != MagickFalse)
277 {
278 (void) XWithdrawWindow(windows->display,magick_windows[i]->id,
279 magick_windows[i]->screen);
280 magick_windows[i]->mapped=MagickFalse;
281 }
282 if (magick_windows[i]->name != (char *) NULL)
283 magick_windows[i]->name=(char *)
284 RelinquishMagickMemory(magick_windows[i]->name);
285 if (magick_windows[i]->icon_name != (char *) NULL)
286 magick_windows[i]->icon_name=(char *)
287 RelinquishMagickMemory(magick_windows[i]->icon_name);
288 if (magick_windows[i]->cursor != (Cursor) NULL)
289 {
290 (void) XFreeCursor(windows->display,magick_windows[i]->cursor);
291 magick_windows[i]->cursor=(Cursor) NULL;
292 }
293 if (magick_windows[i]->busy_cursor != (Cursor) NULL)
294 {
295 (void) XFreeCursor(windows->display,magick_windows[i]->busy_cursor);
296 magick_windows[i]->busy_cursor=(Cursor) NULL;
297 }
298 if (magick_windows[i]->highlight_stipple != (Pixmap) NULL)
299 {
300 (void) XFreePixmap(windows->display,
301 magick_windows[i]->highlight_stipple);
302 magick_windows[i]->highlight_stipple=(Pixmap) NULL;
303 }
304 if (magick_windows[i]->shadow_stipple != (Pixmap) NULL)
305 {
306 (void) XFreePixmap(windows->display,magick_windows[i]->shadow_stipple);
307 magick_windows[i]->shadow_stipple=(Pixmap) NULL;
308 }
309 if (magick_windows[i]->ximage != (XImage *) NULL)
310 {
311 XDestroyImage(magick_windows[i]->ximage);
312 magick_windows[i]->ximage=(XImage *) NULL;
313 }
314 if (magick_windows[i]->pixmap != (Pixmap) NULL)
315 {
316 (void) XFreePixmap(windows->display,magick_windows[i]->pixmap);
317 magick_windows[i]->pixmap=(Pixmap) NULL;
318 }
319 if (magick_windows[i]->id != (Window) NULL)
320 {
321 (void) XDestroyWindow(windows->display,magick_windows[i]->id);
322 magick_windows[i]->id=(Window) NULL;
323 }
324 if (magick_windows[i]->destroy != MagickFalse)
325 {
326 if (magick_windows[i]->image != (Image *) NULL)
327 {
328 magick_windows[i]->image=DestroyImage(magick_windows[i]->image);
329 magick_windows[i]->image=NewImageList();
330 }
331 if (magick_windows[i]->matte_pixmap != (Pixmap) NULL)
332 {
333 (void) XFreePixmap(windows->display,
334 magick_windows[i]->matte_pixmap);
335 magick_windows[i]->matte_pixmap=(Pixmap) NULL;
336 }
337 }
338 if (magick_windows[i]->segment_info != (void *) NULL)
339 {
340#if defined(MAGICKCORE_HAVE_SHARED_MEMORY)
341 XShmSegmentInfo
342 *segment_info;
343
344 segment_info=(XShmSegmentInfo *) magick_windows[i]->segment_info;
345 if (segment_info != (XShmSegmentInfo *) NULL)
346 if (segment_info[0].shmid >= 0)
347 {
348 if (segment_info[0].shmaddr != NULL)
349 (void) shmdt(segment_info[0].shmaddr);
350 (void) shmctl(segment_info[0].shmid,IPC_RMID,0);
351 segment_info[0].shmaddr=NULL;
352 segment_info[0].shmid=(-1);
353 }
354#endif
355 magick_windows[i]->segment_info=(void *)
356 RelinquishMagickMemory(magick_windows[i]->segment_info);
357 }
358 }
359 windows->icon_resources=(XResourceInfo *)
360 RelinquishMagickMemory(windows->icon_resources);
361 if (windows->icon_pixel != (XPixelInfo *) NULL)
362 {
cristyf2faecf2010-05-28 19:19:36 +0000363 if (windows->icon_pixel->pixels != (unsigned long *) NULL)
364 windows->icon_pixel->pixels=(unsigned long *)
cristy3ed852e2009-09-05 21:47:34 +0000365 RelinquishMagickMemory(windows->icon_pixel->pixels);
366 if (windows->icon_pixel->annotate_context != (GC) NULL)
367 XFreeGC(windows->display,windows->icon_pixel->annotate_context);
368 windows->icon_pixel=(XPixelInfo *)
369 RelinquishMagickMemory(windows->icon_pixel);
370 }
371 if (windows->pixel_info != (XPixelInfo *) NULL)
372 {
cristyf2faecf2010-05-28 19:19:36 +0000373 if (windows->pixel_info->pixels != (unsigned long *) NULL)
374 windows->pixel_info->pixels=(unsigned long *)
cristy3ed852e2009-09-05 21:47:34 +0000375 RelinquishMagickMemory(windows->pixel_info->pixels);
376 if (windows->pixel_info->annotate_context != (GC) NULL)
377 XFreeGC(windows->display,windows->pixel_info->annotate_context);
378 if (windows->pixel_info->widget_context != (GC) NULL)
379 XFreeGC(windows->display,windows->pixel_info->widget_context);
380 if (windows->pixel_info->highlight_context != (GC) NULL)
381 XFreeGC(windows->display,windows->pixel_info->highlight_context);
382 windows->pixel_info=(XPixelInfo *)
383 RelinquishMagickMemory(windows->pixel_info);
384 }
385 if (windows->font_info != (XFontStruct *) NULL)
386 {
387 XFreeFont(windows->display,windows->font_info);
388 windows->font_info=(XFontStruct *) NULL;
389 }
390 if (windows->class_hints != (XClassHint *) NULL)
391 {
cristyc9cc4a72011-09-18 02:12:41 +0000392 if (windows->class_hints->res_name != (char *) NULL)
393 windows->class_hints->res_name=DestroyString(
394 windows->class_hints->res_name);
395 if (windows->class_hints->res_class != (char *) NULL)
396 windows->class_hints->res_class=DestroyString(
397 windows->class_hints->res_class);
cristy3ed852e2009-09-05 21:47:34 +0000398 XFree(windows->class_hints);
399 windows->class_hints=(XClassHint *) NULL;
400 }
401 if (windows->manager_hints != (XWMHints *) NULL)
402 {
403 XFree(windows->manager_hints);
404 windows->manager_hints=(XWMHints *) NULL;
405 }
406 if (windows->map_info != (XStandardColormap *) NULL)
407 {
408 XFree(windows->map_info);
409 windows->map_info=(XStandardColormap *) NULL;
410 }
411 if (windows->icon_map != (XStandardColormap *) NULL)
412 {
413 XFree(windows->icon_map);
414 windows->icon_map=(XStandardColormap *) NULL;
415 }
416 if (windows->visual_info != (XVisualInfo *) NULL)
417 {
418 XFree(windows->visual_info);
419 windows->visual_info=(XVisualInfo *) NULL;
420 }
421 if (windows->icon_visual != (XVisualInfo *) NULL)
422 {
423 XFree(windows->icon_visual);
424 windows->icon_visual=(XVisualInfo *) NULL;
425 }
426 (void) XSetWindows((XWindows *) NULL);
427}
428
429/*
430%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
431% %
432% %
433% %
434% X A n n o t a t e I m a g e %
435% %
436% %
437% %
438%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
439%
440% XAnnotateImage() annotates the image with text.
441%
442% The format of the XAnnotateImage method is:
443%
444% MagickBooleanType XAnnotateImage(Display *display,
445% const XPixelInfo *pixel,XAnnotateInfo *annotate_info,Image *image)
446%
447% A description of each parameter follows:
448%
449% o display: Specifies a connection to an X server; returned from
450% XOpenDisplay.
451%
452% o pixel: Specifies a pointer to a XPixelInfo structure.
453%
454% o annotate_info: Specifies a pointer to a XAnnotateInfo structure.
455%
456% o image: the image.
457%
458*/
cristybcbda3f2011-09-03 13:01:22 +0000459MagickPrivate MagickBooleanType XAnnotateImage(Display *display,
cristy3ed852e2009-09-05 21:47:34 +0000460 const XPixelInfo *pixel,XAnnotateInfo *annotate_info,Image *image)
461{
cristyc57f6942010-11-12 01:47:39 +0000462 CacheView
463 *annotate_view;
464
cristy3ed852e2009-09-05 21:47:34 +0000465 GC
466 annotate_context;
467
468 ExceptionInfo
469 *exception;
470
471 Image
472 *annotate_image;
473
474 int
475 x,
476 y;
477
478 MagickBooleanType
479 matte;
480
481 Pixmap
482 annotate_pixmap;
483
cristy2ed42f62011-10-02 19:49:57 +0000484 Quantum
485 virtual_pixel[MaxPixelChannels];
486
cristy3ed852e2009-09-05 21:47:34 +0000487 unsigned int
488 depth,
489 height,
490 width;
491
492 Window
493 root_window;
494
495 XGCValues
496 context_values;
497
498 XImage
499 *annotate_ximage;
500
501 /*
502 Initialize annotated image.
503 */
504 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
505 assert(display != (Display *) NULL);
506 assert(pixel != (XPixelInfo *) NULL);
507 assert(annotate_info != (XAnnotateInfo *) NULL);
508 assert(image != (Image *) NULL);
509 /*
510 Initialize annotated pixmap.
511 */
512 root_window=XRootWindow(display,XDefaultScreen(display));
513 depth=(unsigned int) XDefaultDepth(display,XDefaultScreen(display));
514 annotate_pixmap=XCreatePixmap(display,root_window,annotate_info->width,
515 annotate_info->height,depth);
516 if (annotate_pixmap == (Pixmap) NULL)
517 return(MagickFalse);
518 /*
519 Initialize graphics info.
520 */
521 context_values.background=0;
cristybb503372010-05-27 20:51:26 +0000522 context_values.foreground=(size_t) (~0);
cristy3ed852e2009-09-05 21:47:34 +0000523 context_values.font=annotate_info->font_info->fid;
cristyc57f6942010-11-12 01:47:39 +0000524 annotate_context=XCreateGC(display,root_window,(unsigned long)
525 (GCBackground | GCFont | GCForeground),&context_values);
cristy3ed852e2009-09-05 21:47:34 +0000526 if (annotate_context == (GC) NULL)
527 return(MagickFalse);
528 /*
529 Draw text to pixmap.
530 */
531 (void) XDrawImageString(display,annotate_pixmap,annotate_context,0,
532 (int) annotate_info->font_info->ascent,annotate_info->text,
533 (int) strlen(annotate_info->text));
534 (void) XFreeGC(display,annotate_context);
535 /*
536 Initialize annotated X image.
537 */
538 annotate_ximage=XGetImage(display,annotate_pixmap,0,0,annotate_info->width,
539 annotate_info->height,AllPlanes,ZPixmap);
540 if (annotate_ximage == (XImage *) NULL)
541 return(MagickFalse);
542 (void) XFreePixmap(display,annotate_pixmap);
543 /*
544 Initialize annotated image.
545 */
cristy9950d572011-10-01 18:22:35 +0000546 annotate_image=AcquireImage((ImageInfo *) NULL,&image->exception);
cristy3ed852e2009-09-05 21:47:34 +0000547 if (annotate_image == (Image *) NULL)
548 return(MagickFalse);
549 annotate_image->columns=annotate_info->width;
550 annotate_image->rows=annotate_info->height;
551 /*
552 Transfer annotated X image to image.
553 */
554 width=(unsigned int) image->columns;
555 height=(unsigned int) image->rows;
556 x=0;
557 y=0;
558 (void) XParseGeometry(annotate_info->geometry,&x,&y,&width,&height);
cristy2ed42f62011-10-02 19:49:57 +0000559 (void) GetOneVirtualPixel(image,(ssize_t) x,(ssize_t) y,virtual_pixel,
560 &image->exception);
561 annotate_image->background_color.red=virtual_pixel[RedPixelChannel];
562 annotate_image->background_color.green=virtual_pixel[GreenPixelChannel];
563 annotate_image->background_color.blue=virtual_pixel[BluePixelChannel];
564 annotate_image->background_color.alpha=virtual_pixel[AlphaPixelChannel];
cristy3ed852e2009-09-05 21:47:34 +0000565 if (annotate_info->stencil == ForegroundStencil)
566 annotate_image->matte=MagickTrue;
567 exception=(&image->exception);
cristyc57f6942010-11-12 01:47:39 +0000568 annotate_view=AcquireCacheView(annotate_image);
cristy3ed852e2009-09-05 21:47:34 +0000569 for (y=0; y < (int) annotate_image->rows; y++)
570 {
cristyc57f6942010-11-12 01:47:39 +0000571 register int
cristy3ed852e2009-09-05 21:47:34 +0000572 x;
573
cristy4c08aed2011-07-01 19:47:50 +0000574 register Quantum
cristyc47d1f82009-11-26 01:44:43 +0000575 *restrict q;
cristy3ed852e2009-09-05 21:47:34 +0000576
cristyc57f6942010-11-12 01:47:39 +0000577 q=GetCacheViewAuthenticPixels(annotate_view,0,(ssize_t) y,
578 annotate_image->columns,1,exception);
cristyacd2ed22011-08-30 01:44:23 +0000579 if (q == (Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +0000580 break;
cristyc57f6942010-11-12 01:47:39 +0000581 for (x=0; x < (int) annotate_image->columns; x++)
cristy3ed852e2009-09-05 21:47:34 +0000582 {
cristy4c08aed2011-07-01 19:47:50 +0000583 SetPixelAlpha(annotate_image,OpaqueAlpha,q);
cristy3ed852e2009-09-05 21:47:34 +0000584 if (XGetPixel(annotate_ximage,x,y) == 0)
585 {
586 /*
587 Set this pixel to the background color.
588 */
cristy4c08aed2011-07-01 19:47:50 +0000589 SetPixelRed(annotate_image,ScaleShortToQuantum(
590 pixel->box_color.red),q);
591 SetPixelGreen(annotate_image,ScaleShortToQuantum(
592 pixel->box_color.green),q);
593 SetPixelBlue(annotate_image,ScaleShortToQuantum(
594 pixel->box_color.blue),q);
cristy3ed852e2009-09-05 21:47:34 +0000595 if ((annotate_info->stencil == ForegroundStencil) ||
596 (annotate_info->stencil == OpaqueStencil))
cristy4c08aed2011-07-01 19:47:50 +0000597 SetPixelAlpha(annotate_image,TransparentAlpha,q);
cristy3ed852e2009-09-05 21:47:34 +0000598 }
599 else
600 {
601 /*
602 Set this pixel to the pen color.
603 */
cristy4c08aed2011-07-01 19:47:50 +0000604 SetPixelRed(annotate_image,ScaleShortToQuantum(
605 pixel->pen_color.red),q);
606 SetPixelGreen(annotate_image,ScaleShortToQuantum(
607 pixel->pen_color.green),q);
608 SetPixelBlue(annotate_image,ScaleShortToQuantum(
609 pixel->pen_color.blue),q);
cristy3ed852e2009-09-05 21:47:34 +0000610 if (annotate_info->stencil == BackgroundStencil)
cristy4c08aed2011-07-01 19:47:50 +0000611 SetPixelAlpha(annotate_image,TransparentAlpha,q);
cristy3ed852e2009-09-05 21:47:34 +0000612 }
cristyed231572011-07-14 02:18:59 +0000613 q+=GetPixelChannels(annotate_image);
cristy3ed852e2009-09-05 21:47:34 +0000614 }
cristyc57f6942010-11-12 01:47:39 +0000615 if (SyncCacheViewAuthenticPixels(annotate_view,exception) == MagickFalse)
cristy3ed852e2009-09-05 21:47:34 +0000616 break;
617 }
cristyc57f6942010-11-12 01:47:39 +0000618 annotate_view=DestroyCacheView(annotate_view);
cristy3ed852e2009-09-05 21:47:34 +0000619 XDestroyImage(annotate_ximage);
620 /*
621 Determine annotate geometry.
622 */
623 (void) XParseGeometry(annotate_info->geometry,&x,&y,&width,&height);
624 if ((width != (unsigned int) annotate_image->columns) ||
625 (height != (unsigned int) annotate_image->rows))
626 {
627 char
628 image_geometry[MaxTextExtent];
629
630 /*
631 Scale image.
632 */
cristyb51dff52011-05-19 16:55:47 +0000633 (void) FormatLocaleString(image_geometry,MaxTextExtent,"%ux%u",
cristy3ed852e2009-09-05 21:47:34 +0000634 width,height);
635 (void) TransformImage(&annotate_image,(char *) NULL,image_geometry);
636 }
637 if (annotate_info->degrees != 0.0)
638 {
639 Image
640 *rotate_image;
641
642 int
643 rotations;
644
645 MagickRealType
646 normalized_degrees;
647
648 /*
649 Rotate image.
650 */
651 rotate_image=
652 RotateImage(annotate_image,annotate_info->degrees,&image->exception);
653 if (rotate_image == (Image *) NULL)
654 return(MagickFalse);
655 annotate_image=DestroyImage(annotate_image);
656 annotate_image=rotate_image;
657 /*
658 Annotation is relative to the degree of rotation.
659 */
660 normalized_degrees=annotate_info->degrees;
661 while (normalized_degrees < -45.0)
662 normalized_degrees+=360.0;
663 for (rotations=0; normalized_degrees > 45.0; rotations++)
664 normalized_degrees-=90.0;
665 switch (rotations % 4)
666 {
667 default:
668 case 0:
669 break;
670 case 1:
671 {
672 /*
673 Rotate 90 degrees.
674 */
675 x-=(int) annotate_image->columns/2;
676 y+=(int) annotate_image->columns/2;
677 break;
678 }
679 case 2:
680 {
681 /*
682 Rotate 180 degrees.
683 */
684 x=x-(int) annotate_image->columns;
685 break;
686 }
687 case 3:
688 {
689 /*
690 Rotate 270 degrees.
691 */
692 x=x-(int) annotate_image->columns/2;
693 y=y-(int) (annotate_image->rows-(annotate_image->columns/2));
694 break;
695 }
696 }
697 }
698 /*
699 Composite text onto the image.
700 */
701 (void) XParseGeometry(annotate_info->geometry,&x,&y,&width,&height);
702 matte=image->matte;
703 (void) CompositeImage(image,annotate_image->matte != MagickFalse ?
cristyc57f6942010-11-12 01:47:39 +0000704 OverCompositeOp : CopyCompositeOp,annotate_image,(ssize_t) x,(ssize_t) y);
cristy3ed852e2009-09-05 21:47:34 +0000705 image->matte=matte;
706 annotate_image=DestroyImage(annotate_image);
707 return(MagickTrue);
708}
709
710/*
711%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
712% %
713% %
714% %
715% X B e s t F o n t %
716% %
717% %
718% %
719%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
720%
721% XBestFont() returns the "best" font. "Best" is defined as a font specified
722% in the X resource database or a font such that the text width displayed
723% with the font does not exceed the specified maximum width.
724%
725% The format of the XBestFont method is:
726%
727% XFontStruct *XBestFont(Display *display,
728% const XResourceInfo *resource_info,const MagickBooleanType text_font)
729%
730% A description of each parameter follows:
731%
732% o font: XBestFont returns a pointer to a XFontStruct structure.
733%
734% o display: Specifies a connection to an X server; returned from
735% XOpenDisplay.
736%
737% o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
738%
739% o text_font: True is font should be mono-spaced (typewriter style).
740%
cristy3ed852e2009-09-05 21:47:34 +0000741*/
742
743static char **FontToList(char *font)
744{
745 char
746 **fontlist;
747
748 register char
749 *p,
750 *q;
751
752 register int
753 i;
754
755 unsigned int
756 fonts;
757
758 if (font == (char *) NULL)
759 return((char **) NULL);
760 /*
761 Convert string to an ASCII list.
762 */
763 fonts=1U;
764 for (p=font; *p != '\0'; p++)
765 if ((*p == ':') || (*p == ';') || (*p == ','))
766 fonts++;
767 fontlist=(char **) AcquireQuantumMemory((size_t) fonts+1UL,sizeof(*fontlist));
768 if (fontlist == (char **) NULL)
769 {
770 ThrowXWindowFatalException(ResourceLimitError,"MemoryAllocationFailed",
771 font);
772 return((char **) NULL);
773 }
774 p=font;
775 for (i=0; i < (int) fonts; i++)
776 {
777 for (q=p; *q != '\0'; q++)
778 if ((*q == ':') || (*q == ';') || (*q == ','))
779 break;
780 fontlist[i]=(char *) AcquireQuantumMemory((size_t) (q-p)+1UL,
781 sizeof(*fontlist[i]));
782 if (fontlist[i] == (char *) NULL)
783 {
784 ThrowXWindowFatalException(ResourceLimitError,"MemoryAllocationFailed",
785 font);
786 return((char **) NULL);
787 }
788 (void) CopyMagickString(fontlist[i],p,(size_t) (q-p+1));
789 p=q+1;
790 }
791 fontlist[i]=(char *) NULL;
792 return(fontlist);
793}
794
cristybcbda3f2011-09-03 13:01:22 +0000795MagickPrivate XFontStruct *XBestFont(Display *display,
cristy3ed852e2009-09-05 21:47:34 +0000796 const XResourceInfo *resource_info,const MagickBooleanType text_font)
797{
798 static const char
799 *Fonts[]=
800 {
801 "-*-helvetica-medium-r-normal--12-*-*-*-*-*-iso8859-1",
802 "-*-arial-medium-r-normal--12-*-*-*-*-*-iso8859-1",
803 "-*-helvetica-medium-r-normal--12-*-*-*-*-*-iso8859-15",
804 "-*-arial-medium-r-normal--12-*-*-*-*-*-iso8859-15",
805 "-*-helvetica-medium-r-normal--12-*-*-*-*-*-*-*",
806 "-*-arial-medium-r-normal--12-*-*-*-*-*-*-*",
807 "variable",
808 "fixed",
809 (char *) NULL
810 },
811 *TextFonts[]=
812 {
813 "-*-courier-medium-r-normal-*-12-*-*-*-*-*-iso8859-1",
814 "-*-courier-medium-r-normal-*-12-*-*-*-*-*-iso8859-15",
815 "-*-fixed-medium-r-normal-*-12-*-*-*-*-*-*-*",
816 "fixed",
817 (char *) NULL
818 };
819
820 char
821 *font_name;
822
823 register const char
824 **p;
825
826 XFontStruct
827 *font_info;
828
829 font_info=(XFontStruct *) NULL;
830 font_name=resource_info->font;
831 if (text_font != MagickFalse)
832 font_name=resource_info->text_font;
833 if ((font_name != (char *) NULL) && (*font_name != '\0'))
834 {
835 char
836 **fontlist;
837
838 register int
839 i;
840
841 /*
842 Load preferred font specified in the X resource database.
843 */
844 fontlist=FontToList(font_name);
845 if (fontlist != (char **) NULL)
846 {
847 for (i=0; fontlist[i] != (char *) NULL; i++)
848 {
849 if (font_info == (XFontStruct *) NULL)
850 font_info=XLoadQueryFont(display,fontlist[i]);
851 fontlist[i]=DestroyString(fontlist[i]);
852 }
853 fontlist=(char **) RelinquishMagickMemory(fontlist);
854 }
855 if (font_info == (XFontStruct *) NULL)
856 ThrowXWindowFatalException(XServerError,"UnableToLoadFont",font_name);
857 }
858 /*
859 Load fonts from list of fonts until one is found.
860 */
861 p=Fonts;
862 if (text_font != MagickFalse)
863 p=TextFonts;
864 if (XDisplayHeight(display,XDefaultScreen(display)) >= 748)
865 p++;
866 while (*p != (char *) NULL)
867 {
868 if (font_info != (XFontStruct *) NULL)
869 break;
870 font_info=XLoadQueryFont(display,(char *) *p);
871 p++;
872 }
873 return(font_info);
874}
875
876/*
877%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
878% %
879% %
880% %
881% X B e s t I c o n S i z e %
882% %
883% %
884% %
885%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
886%
887% XBestIconSize() returns the "best" icon size. "Best" is defined as an icon
888% size that maintains the aspect ratio of the image. If the window manager
889% has preferred icon sizes, one of the preferred sizes is used.
890%
891% The format of the XBestIconSize method is:
892%
893% void XBestIconSize(Display *display,XWindowInfo *window,Image *image)
894%
895% A description of each parameter follows:
896%
897% o display: Specifies a connection to an X server; returned from
898% XOpenDisplay.
899%
900% o image: the image.
901%
902*/
cristybcbda3f2011-09-03 13:01:22 +0000903MagickPrivate void XBestIconSize(Display *display,XWindowInfo *window,
cristy3ed852e2009-09-05 21:47:34 +0000904 Image *image)
905{
906 int
907 i,
908 number_sizes;
909
910 MagickRealType
911 scale_factor;
912
913 unsigned int
914 height,
915 icon_height,
916 icon_width,
917 width;
918
919 Window
920 root_window;
921
922 XIconSize
923 *icon_size,
924 *size_list;
925
926 /*
927 Determine if the window manager has specified preferred icon sizes.
928 */
929 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
930 assert(display != (Display *) NULL);
931 assert(window != (XWindowInfo *) NULL);
932 assert(image != (Image *) NULL);
933 window->width=MaxIconSize;
934 window->height=MaxIconSize;
935 icon_size=(XIconSize *) NULL;
936 number_sizes=0;
937 root_window=XRootWindow(display,window->screen);
938 if (XGetIconSizes(display,root_window,&size_list,&number_sizes) != 0)
939 if ((number_sizes > 0) && (size_list != (XIconSize *) NULL))
940 icon_size=size_list;
941 if (icon_size == (XIconSize *) NULL)
942 {
943 /*
944 Window manager does not restrict icon size.
945 */
946 icon_size=XAllocIconSize();
947 if (icon_size == (XIconSize *) NULL)
948 {
949 ThrowXWindowFatalException(ResourceLimitError,
950 "MemoryAllocationFailed",image->filename);
951 return;
952 }
953 icon_size->min_width=1;
954 icon_size->max_width=MaxIconSize;
955 icon_size->min_height=1;
956 icon_size->max_height=MaxIconSize;
957 icon_size->width_inc=1;
958 icon_size->height_inc=1;
959 }
960 /*
961 Determine aspect ratio of image.
962 */
963 width=(unsigned int) image->columns;
964 height=(unsigned int) image->rows;
965 i=0;
966 if (window->crop_geometry)
967 (void) XParseGeometry(window->crop_geometry,&i,&i,&width,&height);
968 /*
969 Look for an icon size that maintains the aspect ratio of image.
970 */
971 scale_factor=(MagickRealType) icon_size->max_width/width;
972 if (scale_factor > ((MagickRealType) icon_size->max_height/height))
973 scale_factor=(MagickRealType) icon_size->max_height/height;
974 icon_width=(unsigned int) icon_size->min_width;
975 while ((int) icon_width < icon_size->max_width)
976 {
977 if (icon_width >= (unsigned int) (scale_factor*width+0.5))
978 break;
979 icon_width+=icon_size->width_inc;
980 }
981 icon_height=(unsigned int) icon_size->min_height;
982 while ((int) icon_height < icon_size->max_height)
983 {
984 if (icon_height >= (unsigned int) (scale_factor*height+0.5))
985 break;
986 icon_height+=icon_size->height_inc;
987 }
988 (void) XFree((void *) icon_size);
989 window->width=icon_width;
990 window->height=icon_height;
991}
992
993/*
994%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
995% %
996% %
997% %
998% X B e s t P i x e l %
999% %
1000% %
1001% %
1002%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1003%
1004% XBestPixel() returns a pixel from an array of pixels that is closest to the
1005% requested color. If the color array is NULL, the colors are obtained from
1006% the X server.
1007%
1008% The format of the XBestPixel method is:
1009%
1010% void XBestPixel(Display *display,const Colormap colormap,XColor *colors,
1011% unsigned int number_colors,XColor *color)
1012%
1013% A description of each parameter follows:
1014%
1015% o pixel: XBestPixel returns the pixel value closest to the requested
1016% color.
1017%
1018% o display: Specifies a connection to an X server; returned from
1019% XOpenDisplay.
1020%
1021% o colormap: Specifies the ID of the X server colormap.
1022%
1023% o colors: Specifies an array of XColor structures.
1024%
1025% o number_colors: Specifies the number of XColor structures in the
1026% color definition array.
1027%
1028% o color: Specifies the desired RGB value to find in the colors array.
1029%
1030*/
cristybcbda3f2011-09-03 13:01:22 +00001031MagickPrivate void XBestPixel(Display *display,const Colormap colormap,
cristy3ed852e2009-09-05 21:47:34 +00001032 XColor *colors,unsigned int number_colors,XColor *color)
1033{
1034 MagickBooleanType
1035 query_server;
1036
cristy4c08aed2011-07-01 19:47:50 +00001037 PixelInfo
cristy3ed852e2009-09-05 21:47:34 +00001038 pixel;
1039
1040 MagickRealType
1041 min_distance;
1042
1043 register MagickRealType
1044 distance;
1045
1046 register int
1047 i,
1048 j;
1049
1050 Status
1051 status;
1052
1053 /*
1054 Find closest representation for the requested RGB color.
1055 */
1056 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
1057 assert(display != (Display *) NULL);
1058 assert(color != (XColor *) NULL);
1059 status=XAllocColor(display,colormap,color);
1060 if (status != False)
1061 return;
1062 query_server=colors == (XColor *) NULL ? MagickTrue : MagickFalse;
1063 if (query_server != MagickFalse)
1064 {
1065 /*
1066 Read X server colormap.
1067 */
1068 colors=(XColor *) AcquireQuantumMemory(number_colors,sizeof(*colors));
1069 if (colors == (XColor *) NULL)
1070 {
1071 ThrowXWindowFatalException(ResourceLimitError,
1072 "MemoryAllocationFailed","...");
1073 return;
1074 }
1075 for (i=0; i < (int) number_colors; i++)
cristybb503372010-05-27 20:51:26 +00001076 colors[i].pixel=(size_t) i;
cristy3ed852e2009-09-05 21:47:34 +00001077 if (number_colors > 256)
1078 number_colors=256;
1079 (void) XQueryColors(display,colormap,colors,(int) number_colors);
1080 }
1081 min_distance=3.0*((MagickRealType) QuantumRange+1.0)*((MagickRealType)
1082 QuantumRange+1.0);
1083 j=0;
1084 for (i=0; i < (int) number_colors; i++)
1085 {
1086 pixel.red=colors[i].red-(MagickRealType) color->red;
1087 distance=pixel.red*pixel.red;
1088 if (distance > min_distance)
1089 continue;
1090 pixel.green=colors[i].green-(MagickRealType) color->green;
1091 distance+=pixel.green*pixel.green;
1092 if (distance > min_distance)
1093 continue;
1094 pixel.blue=colors[i].blue-(MagickRealType) color->blue;
1095 distance+=pixel.blue*pixel.blue;
1096 if (distance > min_distance)
1097 continue;
1098 min_distance=distance;
1099 color->pixel=colors[i].pixel;
1100 j=i;
1101 }
1102 (void) XAllocColor(display,colormap,&colors[j]);
1103 if (query_server != MagickFalse)
1104 colors=(XColor *) RelinquishMagickMemory(colors);
1105}
1106
1107/*
1108%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1109% %
1110% %
1111% %
1112% X B e s t V i s u a l I n f o %
1113% %
1114% %
1115% %
1116%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1117%
1118% XBestVisualInfo() returns visual information for a visual that is the "best"
1119% the server supports. "Best" is defined as:
1120%
1121% 1. Restrict the visual list to those supported by the default screen.
1122%
1123% 2. If a visual type is specified, restrict the visual list to those of
1124% that type.
1125%
1126% 3. If a map type is specified, choose the visual that matches the id
1127% specified by the Standard Colormap.
1128%
1129% 4 From the list of visuals, choose one that can display the most
1130% simultaneous colors. If more than one visual can display the same
1131% number of simultaneous colors, one is chosen based on a rank.
1132%
1133% The format of the XBestVisualInfo method is:
1134%
1135% XVisualInfo *XBestVisualInfo(Display *display,
1136% XStandardColormap *map_info,XResourceInfo *resource_info)
1137%
1138% A description of each parameter follows:
1139%
1140% o visual_info: XBestVisualInfo returns a pointer to a X11 XVisualInfo
1141% structure.
1142%
1143% o display: Specifies a connection to an X server; returned from
1144% XOpenDisplay.
1145%
1146% o map_info: If map_type is specified, this structure is initialized
1147% with info from the Standard Colormap.
1148%
1149% o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
1150%
1151*/
1152
1153static inline int MagickMax(const int x,const int y)
1154{
1155 if (x > y)
1156 return(x);
1157 return(y);
1158}
1159
cristybb503372010-05-27 20:51:26 +00001160static inline size_t MagickMin(const unsigned int x,
cristy3ed852e2009-09-05 21:47:34 +00001161 const unsigned int y)
1162{
1163 if (x < y)
1164 return(x);
1165 return(y);
1166}
1167
cristybcbda3f2011-09-03 13:01:22 +00001168MagickPrivate XVisualInfo *XBestVisualInfo(Display *display,
cristy3ed852e2009-09-05 21:47:34 +00001169 XStandardColormap *map_info,XResourceInfo *resource_info)
1170{
1171#define MaxStandardColormaps 7
1172#define XVisualColormapSize(visual_info) MagickMin((unsigned int) (\
1173 (visual_info->klass == TrueColor) || (visual_info->klass == DirectColor) ? \
1174 visual_info->red_mask | visual_info->green_mask | visual_info->blue_mask : \
1175 (unsigned int) visual_info->colormap_size),1U << visual_info->depth)
1176
1177 char
1178 *map_type,
1179 *visual_type;
1180
cristyc57f6942010-11-12 01:47:39 +00001181 int
1182 visual_mask;
1183
cristy3ed852e2009-09-05 21:47:34 +00001184 register int
1185 i;
1186
cristy8891f9c2010-06-04 23:32:17 +00001187 size_t
1188 one;
1189
cristy3ed852e2009-09-05 21:47:34 +00001190 static int
1191 number_visuals;
1192
1193 static XVisualInfo
1194 visual_template;
1195
1196 XVisualInfo
1197 *visual_info,
1198 *visual_list;
1199
1200 /*
1201 Restrict visual search by screen number.
1202 */
1203 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
1204 assert(display != (Display *) NULL);
1205 assert(map_info != (XStandardColormap *) NULL);
1206 assert(resource_info != (XResourceInfo *) NULL);
1207 map_type=resource_info->map_type;
1208 visual_type=resource_info->visual_type;
1209 visual_mask=VisualScreenMask;
1210 visual_template.screen=XDefaultScreen(display);
1211 visual_template.depth=XDefaultDepth(display,XDefaultScreen(display));
cristy8891f9c2010-06-04 23:32:17 +00001212 one=1;
cristy3ed852e2009-09-05 21:47:34 +00001213 if ((resource_info->immutable != MagickFalse) && (resource_info->colors != 0))
cristy8891f9c2010-06-04 23:32:17 +00001214 if (resource_info->colors <= (one << (size_t) visual_template.depth))
cristy3ed852e2009-09-05 21:47:34 +00001215 visual_mask|=VisualDepthMask;
1216 if (visual_type != (char *) NULL)
1217 {
1218 /*
1219 Restrict visual search by class or visual id.
1220 */
1221 if (LocaleCompare("staticgray",visual_type) == 0)
1222 {
1223 visual_mask|=VisualClassMask;
1224 visual_template.klass=StaticGray;
1225 }
1226 else
1227 if (LocaleCompare("grayscale",visual_type) == 0)
1228 {
1229 visual_mask|=VisualClassMask;
1230 visual_template.klass=GrayScale;
1231 }
1232 else
1233 if (LocaleCompare("staticcolor",visual_type) == 0)
1234 {
1235 visual_mask|=VisualClassMask;
1236 visual_template.klass=StaticColor;
1237 }
1238 else
1239 if (LocaleCompare("pseudocolor",visual_type) == 0)
1240 {
1241 visual_mask|=VisualClassMask;
1242 visual_template.klass=PseudoColor;
1243 }
1244 else
1245 if (LocaleCompare("truecolor",visual_type) == 0)
1246 {
1247 visual_mask|=VisualClassMask;
1248 visual_template.klass=TrueColor;
1249 }
1250 else
1251 if (LocaleCompare("directcolor",visual_type) == 0)
1252 {
1253 visual_mask|=VisualClassMask;
1254 visual_template.klass=DirectColor;
1255 }
1256 else
1257 if (LocaleCompare("default",visual_type) == 0)
1258 {
1259 visual_mask|=VisualIDMask;
1260 visual_template.visualid=XVisualIDFromVisual(
1261 XDefaultVisual(display,XDefaultScreen(display)));
1262 }
1263 else
1264 if (isdigit((int) ((unsigned char) *visual_type)) != 0)
1265 {
1266 visual_mask|=VisualIDMask;
1267 visual_template.visualid=
1268 strtol(visual_type,(char **) NULL,0);
1269 }
1270 else
1271 ThrowXWindowFatalException(XServerError,
1272 "UnrecognizedVisualSpecifier",visual_type);
1273 }
1274 /*
1275 Get all visuals that meet our criteria so far.
1276 */
1277 number_visuals=0;
1278 visual_list=XGetVisualInfo(display,visual_mask,&visual_template,
1279 &number_visuals);
1280 visual_mask=VisualScreenMask | VisualIDMask;
1281 if ((number_visuals == 0) || (visual_list == (XVisualInfo *) NULL))
1282 {
1283 /*
1284 Failed to get visual; try using the default visual.
1285 */
1286 ThrowXWindowFatalException(XServerWarning,"UnableToGetVisual",
1287 visual_type);
1288 visual_template.visualid=XVisualIDFromVisual(XDefaultVisual(display,
1289 XDefaultScreen(display)));
1290 visual_list=XGetVisualInfo(display,visual_mask,&visual_template,
1291 &number_visuals);
1292 if ((number_visuals == 0) || (visual_list == (XVisualInfo *) NULL))
1293 return((XVisualInfo *) NULL);
1294 ThrowXWindowFatalException(XServerWarning,"UsingDefaultVisual",
1295 XVisualClassName(visual_list->klass));
1296 }
1297 resource_info->color_recovery=MagickFalse;
1298 if ((map_info != (XStandardColormap *) NULL) && (map_type != (char *) NULL))
1299 {
1300 Atom
1301 map_property;
1302
1303 char
1304 map_name[MaxTextExtent];
1305
1306 int
1307 j,
1308 number_maps;
1309
1310 Status
1311 status;
1312
1313 Window
1314 root_window;
1315
1316 XStandardColormap
1317 *map_list;
1318
1319 /*
1320 Choose a visual associated with a standard colormap.
1321 */
1322 root_window=XRootWindow(display,XDefaultScreen(display));
1323 status=False;
1324 if (LocaleCompare(map_type,"list") != 0)
1325 {
1326 /*
1327 User specified Standard Colormap.
1328 */
cristyb51dff52011-05-19 16:55:47 +00001329 (void) FormatLocaleString((char *) map_name,MaxTextExtent,
cristy3ed852e2009-09-05 21:47:34 +00001330 "RGB_%s_MAP",map_type);
1331 LocaleUpper(map_name);
1332 map_property=XInternAtom(display,(char *) map_name,MagickTrue);
1333 if (map_property != (Atom) NULL)
1334 status=XGetRGBColormaps(display,root_window,&map_list,&number_maps,
1335 map_property);
1336 }
1337 else
1338 {
1339 static const char
1340 *colormap[MaxStandardColormaps]=
1341 {
1342 "_HP_RGB_SMOOTH_MAP_LIST",
1343 "RGB_BEST_MAP",
1344 "RGB_DEFAULT_MAP",
1345 "RGB_GRAY_MAP",
1346 "RGB_RED_MAP",
1347 "RGB_GREEN_MAP",
1348 "RGB_BLUE_MAP",
1349 };
1350
1351 /*
1352 Choose a standard colormap from a list.
1353 */
1354 for (i=0; i < MaxStandardColormaps; i++)
1355 {
1356 map_property=XInternAtom(display,(char *) colormap[i],MagickTrue);
1357 if (map_property == (Atom) NULL)
1358 continue;
1359 status=XGetRGBColormaps(display,root_window,&map_list,&number_maps,
1360 map_property);
1361 if (status != False)
1362 break;
1363 }
1364 resource_info->color_recovery=i == 0 ? MagickTrue : MagickFalse;
1365 }
1366 if (status == False)
1367 {
1368 ThrowXWindowFatalException(XServerError,"UnableToGetStandardColormap",
1369 map_type);
1370 return((XVisualInfo *) NULL);
1371 }
1372 /*
1373 Search all Standard Colormaps and visuals for ids that match.
1374 */
1375 *map_info=map_list[0];
1376#if !defined(PRE_R4_ICCCM)
1377 visual_template.visualid=XVisualIDFromVisual(visual_list[0].visual);
1378 for (i=0; i < number_maps; i++)
1379 for (j=0; j < number_visuals; j++)
1380 if (map_list[i].visualid ==
1381 XVisualIDFromVisual(visual_list[j].visual))
1382 {
1383 *map_info=map_list[i];
1384 visual_template.visualid=XVisualIDFromVisual(
1385 visual_list[j].visual);
1386 break;
1387 }
1388 if (map_info->visualid != visual_template.visualid)
1389 {
1390 ThrowXWindowFatalException(XServerError,
1391 "UnableToMatchVisualToStandardColormap",map_type);
1392 return((XVisualInfo *) NULL);
1393 }
1394#endif
1395 if (map_info->colormap == (Colormap) NULL)
1396 {
1397 ThrowXWindowFatalException(XServerError,
1398 "StandardColormapIsNotInitialized",map_type);
1399 return((XVisualInfo *) NULL);
1400 }
1401 (void) XFree((void *) map_list);
1402 }
1403 else
1404 {
1405 static const unsigned int
1406 rank[]=
1407 {
1408 StaticGray,
1409 GrayScale,
1410 StaticColor,
1411 DirectColor,
1412 TrueColor,
1413 PseudoColor
1414 };
1415
1416 XVisualInfo
1417 *p;
1418
1419 /*
1420 Pick one visual that displays the most simultaneous colors.
1421 */
1422 visual_info=visual_list;
1423 p=visual_list;
1424 for (i=1; i < number_visuals; i++)
1425 {
1426 p++;
1427 if (XVisualColormapSize(p) > XVisualColormapSize(visual_info))
1428 visual_info=p;
1429 else
1430 if (XVisualColormapSize(p) == XVisualColormapSize(visual_info))
1431 if (rank[p->klass] > rank[visual_info->klass])
1432 visual_info=p;
1433 }
1434 visual_template.visualid=XVisualIDFromVisual(visual_info->visual);
1435 }
1436 (void) XFree((void *) visual_list);
1437 /*
1438 Retrieve only one visual by its screen & id number.
1439 */
1440 visual_info=XGetVisualInfo(display,visual_mask,&visual_template,
1441 &number_visuals);
1442 if ((number_visuals == 0) || (visual_info == (XVisualInfo *) NULL))
1443 return((XVisualInfo *) NULL);
1444 return(visual_info);
1445}
1446
1447/*
1448%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1449% %
1450% %
1451% %
1452% X C h e c k D e f i n e C u r s o r %
1453% %
1454% %
1455% %
1456%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1457%
1458% XCheckDefineCursor() prevents cursor changes on the root window.
1459%
1460% The format of the XXCheckDefineCursor method is:
1461%
1462% XCheckDefineCursor(display,window,cursor)
1463%
1464% A description of each parameter follows:
1465%
1466% o display: Specifies a connection to an X server; returned from
1467% XOpenDisplay.
1468%
1469% o window: the window.
1470%
1471% o cursor: the cursor.
1472%
1473*/
cristybcbda3f2011-09-03 13:01:22 +00001474MagickPrivate int XCheckDefineCursor(Display *display,Window window,
cristy3ed852e2009-09-05 21:47:34 +00001475 Cursor cursor)
1476{
1477 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
1478 assert(display != (Display *) NULL);
1479 if (window == XRootWindow(display,XDefaultScreen(display)))
1480 return(0);
1481 return(XDefineCursor(display,window,cursor));
1482}
1483
1484/*
1485%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1486% %
1487% %
1488% %
1489% X C h e c k R e f r e s h W i n d o w s %
1490% %
1491% %
1492% %
1493%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1494%
1495% XCheckRefreshWindows() checks the X server for exposure events for a
1496% particular window and updates the areassociated with the exposure event.
1497%
1498% The format of the XCheckRefreshWindows method is:
1499%
1500% void XCheckRefreshWindows(Display *display,XWindows *windows)
1501%
1502% A description of each parameter follows:
1503%
1504% o display: Specifies a connection to an X server; returned from
1505% XOpenDisplay.
1506%
1507% o windows: Specifies a pointer to a XWindows structure.
1508%
1509*/
cristybcbda3f2011-09-03 13:01:22 +00001510MagickPrivate void XCheckRefreshWindows(Display *display,XWindows *windows)
cristy3ed852e2009-09-05 21:47:34 +00001511{
1512 Window
1513 id;
1514
1515 XEvent
1516 event;
1517
1518 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
1519 assert(display != (Display *) NULL);
1520 assert(windows != (XWindows *) NULL);
1521 XDelay(display,SuspendTime);
1522 id=windows->command.id;
1523 while (XCheckTypedWindowEvent(display,id,Expose,&event) != MagickFalse)
1524 (void) XCommandWidget(display,windows,(char const **) NULL,&event);
1525 id=windows->image.id;
1526 while (XCheckTypedWindowEvent(display,id,Expose,&event) != MagickFalse)
1527 XRefreshWindow(display,&windows->image,&event);
1528 XDelay(display,SuspendTime << 1);
1529 id=windows->command.id;
1530 while (XCheckTypedWindowEvent(display,id,Expose,&event) != MagickFalse)
1531 (void) XCommandWidget(display,windows,(char const **) NULL,&event);
1532 id=windows->image.id;
1533 while (XCheckTypedWindowEvent(display,id,Expose,&event) != MagickFalse)
1534 XRefreshWindow(display,&windows->image,&event);
1535}
1536
1537/*
1538%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1539% %
1540% %
1541% %
1542% X C l i e n t M e s s a g e %
1543% %
1544% %
1545% %
1546%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1547%
1548% XClientMessage() sends a reason to a window with XSendEvent. The reason is
1549% initialized with a particular protocol type and atom.
1550%
1551% The format of the XClientMessage function is:
1552%
1553% XClientMessage(display,window,protocol,reason,timestamp)
1554%
1555% A description of each parameter follows:
1556%
1557% o display: Specifies a pointer to the Display structure; returned from
1558% XOpenDisplay.
1559%
1560% o window: Specifies a pointer to a Window structure.
1561%
1562% o protocol: Specifies an atom value.
1563%
1564% o reason: Specifies an atom value which is the reason to send.
1565%
1566% o timestamp: Specifies a value of type Time.
1567%
1568*/
cristybcbda3f2011-09-03 13:01:22 +00001569MagickPrivate void XClientMessage(Display *display,const Window window,
cristy3ed852e2009-09-05 21:47:34 +00001570 const Atom protocol,const Atom reason,const Time timestamp)
1571{
1572 XClientMessageEvent
1573 client_event;
1574
1575 assert(display != (Display *) NULL);
1576 client_event.type=ClientMessage;
1577 client_event.window=window;
1578 client_event.message_type=protocol;
1579 client_event.format=32;
cristyc57f6942010-11-12 01:47:39 +00001580 client_event.data.l[0]=(long) reason;
1581 client_event.data.l[1]=(long) timestamp;
cristy3ed852e2009-09-05 21:47:34 +00001582 (void) XSendEvent(display,window,MagickFalse,NoEventMask,(XEvent *) &client_event);
1583}
1584
1585/*
1586%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1587% %
1588% %
1589% %
1590+ X C l i e n t W i n d o w %
1591% %
1592% %
1593% %
1594%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1595%
1596% XClientWindow() finds a window, at or below the specified window, which has
1597% a WM_STATE property. If such a window is found, it is returned, otherwise
1598% the argument window is returned.
1599%
1600% The format of the XClientWindow function is:
1601%
1602% client_window=XClientWindow(display,target_window)
1603%
1604% A description of each parameter follows:
1605%
1606% o client_window: XClientWindow returns a window, at or below the specified
1607% window, which has a WM_STATE property otherwise the argument
1608% target_window is returned.
1609%
1610% o display: Specifies a pointer to the Display structure; returned from
1611% XOpenDisplay.
1612%
1613% o target_window: Specifies the window to find a WM_STATE property.
1614%
cristy3ed852e2009-09-05 21:47:34 +00001615*/
1616static Window XClientWindow(Display *display,Window target_window)
1617{
1618 Atom
1619 state,
1620 type;
1621
1622 int
1623 format;
1624
1625 Status
1626 status;
1627
1628 unsigned char
1629 *data;
1630
cristyf2faecf2010-05-28 19:19:36 +00001631 unsigned long
cristy3ed852e2009-09-05 21:47:34 +00001632 after,
1633 number_items;
1634
1635 Window
1636 client_window;
1637
1638 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
1639 assert(display != (Display *) NULL);
1640 state=XInternAtom(display,"WM_STATE",MagickTrue);
1641 if (state == (Atom) NULL)
1642 return(target_window);
1643 type=(Atom) NULL;
1644 status=XGetWindowProperty(display,target_window,state,0L,0L,MagickFalse,
1645 (Atom) AnyPropertyType,&type,&format,&number_items,&after,&data);
1646 if ((status == Success) && (type != (Atom) NULL))
1647 return(target_window);
1648 client_window=XWindowByProperty(display,target_window,state);
1649 if (client_window == (Window) NULL)
1650 return(target_window);
1651 return(client_window);
1652}
1653
1654/*
1655%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1656% %
1657% %
1658% %
cristyf34a1452009-10-24 22:29:27 +00001659+ X C o m p o n e n t T e r m i n u s %
1660% %
1661% %
1662% %
1663%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1664%
1665% XComponentTerminus() destroys the module component.
1666%
1667% The format of the XComponentTerminus method is:
1668%
1669% XComponentTerminus(void)
1670%
1671*/
cristy5ff4eaf2011-09-03 01:38:02 +00001672MagickPrivate void XComponentTerminus(void)
cristyf34a1452009-10-24 22:29:27 +00001673{
1674 DestroyXResources();
1675}
1676
1677/*
1678%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1679% %
1680% %
1681% %
cristy3ed852e2009-09-05 21:47:34 +00001682% X C o n f i g u r e I m a g e C o l o r m a p %
1683% %
1684% %
1685% %
1686%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1687%
1688% XConfigureImageColormap() creates a new X colormap.
1689%
1690% The format of the XConfigureImageColormap method is:
1691%
1692% void XConfigureImageColormap(Display *display,
1693% XResourceInfo *resource_info,XWindows *windows,Image *image)
1694%
1695% A description of each parameter follows:
1696%
1697% o display: Specifies a connection to an X server; returned from
1698% XOpenDisplay.
1699%
1700% o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
1701%
1702% o windows: Specifies a pointer to a XWindows structure.
1703%
1704% o image: the image.
1705%
1706*/
cristybcbda3f2011-09-03 13:01:22 +00001707MagickPrivate void XConfigureImageColormap(Display *display,
cristy3ed852e2009-09-05 21:47:34 +00001708 XResourceInfo *resource_info,XWindows *windows,Image *image)
1709{
1710 Colormap
1711 colormap;
1712
1713 /*
1714 Make standard colormap.
1715 */
1716 XSetCursorState(display,windows,MagickTrue);
1717 XCheckRefreshWindows(display,windows);
1718 XMakeStandardColormap(display,windows->visual_info,resource_info,image,
1719 windows->map_info,windows->pixel_info);
1720 colormap=windows->map_info->colormap;
1721 (void) XSetWindowColormap(display,windows->image.id,colormap);
1722 (void) XSetWindowColormap(display,windows->command.id,colormap);
1723 (void) XSetWindowColormap(display,windows->widget.id,colormap);
1724 if (windows->magnify.mapped != MagickFalse)
1725 (void) XSetWindowColormap(display,windows->magnify.id,colormap);
1726 if (windows->pan.mapped != MagickFalse)
1727 (void) XSetWindowColormap(display,windows->pan.id,colormap);
1728 XSetCursorState(display,windows,MagickFalse);
1729 XClientMessage(display,windows->image.id,windows->im_protocols,
1730 windows->im_update_colormap,CurrentTime);
1731}
1732
1733/*
1734%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1735% %
1736% %
1737% %
1738% X C o n s t r a i n W i n d o w P o s i t i o n %
1739% %
1740% %
1741% %
1742%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1743%
1744% XConstrainWindowPosition() assures a window is positioned within the X
1745% server boundaries.
1746%
1747% The format of the XConstrainWindowPosition method is:
1748%
1749% void XConstrainWindowPosition(Display *display,XWindowInfo *window_info)
1750%
1751% A description of each parameter follows:
1752%
1753% o display: Specifies a pointer to the Display structure; returned from
1754% XOpenDisplay.
1755%
1756% o window_info: Specifies a pointer to a XWindowInfo structure.
1757%
1758*/
cristybcbda3f2011-09-03 13:01:22 +00001759MagickPrivate void XConstrainWindowPosition(Display *display,
cristy3ed852e2009-09-05 21:47:34 +00001760 XWindowInfo *window_info)
1761{
1762 int
1763 limit;
1764
1765 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
1766 assert(display != (Display *) NULL);
1767 assert(window_info != (XWindowInfo *) NULL);
1768 limit=XDisplayWidth(display,window_info->screen)-window_info->width;
1769 if (window_info->x < 0)
1770 window_info->x=0;
1771 else
1772 if (window_info->x > (int) limit)
1773 window_info->x=(int) limit;
1774 limit=XDisplayHeight(display,window_info->screen)-window_info->height;
1775 if (window_info->y < 0)
1776 window_info->y=0;
1777 else
1778 if (window_info->y > limit)
1779 window_info->y=limit;
1780}
1781
1782/*
1783%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1784% %
1785% %
1786% %
1787% X D e l a y %
1788% %
1789% %
1790% %
1791%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1792%
1793% XDelay() suspends program execution for the number of milliseconds
1794% specified.
1795%
1796% The format of the Delay method is:
1797%
cristybb503372010-05-27 20:51:26 +00001798% void XDelay(Display *display,const size_t milliseconds)
cristy3ed852e2009-09-05 21:47:34 +00001799%
1800% A description of each parameter follows:
1801%
1802% o display: Specifies a pointer to the Display structure; returned from
1803% XOpenDisplay.
1804%
1805% o milliseconds: Specifies the number of milliseconds to delay before
1806% returning.
1807%
1808*/
cristybcbda3f2011-09-03 13:01:22 +00001809MagickPrivate void XDelay(Display *display,const size_t milliseconds)
cristy3ed852e2009-09-05 21:47:34 +00001810{
1811 assert(display != (Display *) NULL);
1812 (void) XFlush(display);
cristya21afde2010-07-02 00:45:40 +00001813 MagickDelay(milliseconds);
cristy3ed852e2009-09-05 21:47:34 +00001814}
1815
1816/*
1817%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1818% %
1819% %
1820% %
1821% X D e s t r o y R e s o u r c e I n f o %
1822% %
1823% %
1824% %
1825%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1826%
1827% XDestroyResourceInfo() frees memory associated with the XResourceInfo
1828% structure.
1829%
1830% The format of the XDestroyResourceInfo method is:
1831%
1832% void XDestroyResourceInfo(XResourceInfo *resource_info)
1833%
1834% A description of each parameter follows:
1835%
1836% o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
1837%
1838*/
1839MagickExport void XDestroyResourceInfo(XResourceInfo *resource_info)
1840{
1841 if (resource_info->image_geometry != (char *) NULL)
1842 resource_info->image_geometry=(char *)
1843 RelinquishMagickMemory(resource_info->image_geometry);
1844 if (resource_info->quantize_info != (QuantizeInfo *) NULL)
1845 resource_info->quantize_info=DestroyQuantizeInfo(
1846 resource_info->quantize_info);
1847 if (resource_info->client_name != (char *) NULL)
1848 resource_info->client_name=(char *)
1849 RelinquishMagickMemory(resource_info->client_name);
1850 if (resource_info->name != (char *) NULL)
1851 resource_info->name=DestroyString(resource_info->name);
1852 (void) ResetMagickMemory(resource_info,0,sizeof(*resource_info));
1853}
1854
1855/*
1856%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1857% %
1858% %
1859% %
1860% X D e s t r o y W i n d o w C o l o r s %
1861% %
1862% %
1863% %
1864%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1865%
1866% XDestroyWindowColors() frees X11 color resources previously saved on a
1867% window by XRetainWindowColors or programs like xsetroot.
1868%
1869% The format of the XDestroyWindowColors method is:
1870%
1871% void XDestroyWindowColors(Display *display,Window window)
1872%
1873% A description of each parameter follows:
1874%
1875% o display: Specifies a connection to an X server; returned from
1876% XOpenDisplay.
1877%
1878% o window: Specifies a pointer to a Window structure.
1879%
1880*/
cristybcbda3f2011-09-03 13:01:22 +00001881MagickPrivate void XDestroyWindowColors(Display *display,Window window)
cristy3ed852e2009-09-05 21:47:34 +00001882{
1883 Atom
1884 property,
1885 type;
1886
1887 int
1888 format;
1889
1890 Status
1891 status;
1892
1893 unsigned char
1894 *data;
1895
cristyf2faecf2010-05-28 19:19:36 +00001896 unsigned long
cristy3ed852e2009-09-05 21:47:34 +00001897 after,
1898 length;
1899
1900 /*
1901 If there are previous resources on the root window, destroy them.
1902 */
1903 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
1904 assert(display != (Display *) NULL);
1905 property=XInternAtom(display,"_XSETROOT_ID",MagickFalse);
1906 if (property == (Atom) NULL)
1907 {
1908 ThrowXWindowFatalException(XServerError,"UnableToCreateProperty",
1909 "_XSETROOT_ID");
1910 return;
1911 }
1912 status=XGetWindowProperty(display,window,property,0L,1L,MagickTrue,
1913 (Atom) AnyPropertyType,&type,&format,&length,&after,&data);
1914 if (status != Success)
1915 return;
1916 if ((type == XA_PIXMAP) && (format == 32) && (length == 1) && (after == 0))
1917 {
1918 (void) XKillClient(display,(XID) (*((Pixmap *) data)));
1919 (void) XDeleteProperty(display,window,property);
1920 }
1921 if (type != None)
1922 (void) XFree((void *) data);
1923}
1924
1925/*
1926%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1927% %
1928% %
1929% %
1930% X D i s p l a y I m a g e I n f o %
1931% %
1932% %
1933% %
1934%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1935%
1936% XDisplayImageInfo() displays information about an X image.
1937%
1938% The format of the XDisplayImageInfo method is:
1939%
1940% void XDisplayImageInfo(Display *display,
1941% const XResourceInfo *resource_info,XWindows *windows,Image *undo_image,
1942% Image *image)
1943%
1944% A description of each parameter follows:
1945%
1946% o display: Specifies a connection to an X server; returned from
1947% XOpenDisplay.
1948%
1949% o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
1950%
1951% o windows: Specifies a pointer to a XWindows structure.
1952%
1953% o undo_image: the undo image.
1954%
1955% o image: the image.
1956%
1957*/
cristybcbda3f2011-09-03 13:01:22 +00001958MagickPrivate void XDisplayImageInfo(Display *display,
cristy3ed852e2009-09-05 21:47:34 +00001959 const XResourceInfo *resource_info,XWindows *windows,Image *undo_image,
1960 Image *image)
1961{
1962 char
1963 filename[MaxTextExtent],
1964 *text,
1965 **textlist;
1966
1967 FILE
1968 *file;
1969
1970 int
1971 unique_file;
1972
cristybb503372010-05-27 20:51:26 +00001973 register ssize_t
cristy3ed852e2009-09-05 21:47:34 +00001974 i;
1975
cristybb503372010-05-27 20:51:26 +00001976 size_t
cristy3ed852e2009-09-05 21:47:34 +00001977 number_pixels;
1978
cristy9d314ff2011-03-09 01:30:28 +00001979 ssize_t
1980 bytes;
1981
1982 unsigned int
1983 levels;
1984
cristy3ed852e2009-09-05 21:47:34 +00001985 /*
1986 Write info about the X server to a file.
1987 */
1988 assert(display != (Display *) NULL);
1989 assert(resource_info != (XResourceInfo *) NULL);
1990 assert(windows != (XWindows *) NULL);
1991 assert(image != (Image *) NULL);
1992 if (image->debug)
1993 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
1994 file=(FILE *) NULL;
1995 unique_file=AcquireUniqueFileResource(filename);
1996 if (unique_file != -1)
1997 file=fdopen(unique_file,"w");
1998 if ((unique_file == -1) || (file == (FILE *) NULL))
1999 {
2000 XNoticeWidget(display,windows,"Unable to display image info",filename);
2001 return;
2002 }
2003 if (resource_info->gamma_correct != MagickFalse)
2004 if (resource_info->display_gamma != (char *) NULL)
cristyb51dff52011-05-19 16:55:47 +00002005 (void) FormatLocaleFile(file,"Display\n gamma: %s\n\n",
cristy3ed852e2009-09-05 21:47:34 +00002006 resource_info->display_gamma);
2007 /*
2008 Write info about the X image to a file.
2009 */
cristyb51dff52011-05-19 16:55:47 +00002010 (void) FormatLocaleFile(file,"X\n visual: %s\n",
cristy3ed852e2009-09-05 21:47:34 +00002011 XVisualClassName((int) windows->image.storage_class));
cristyb51dff52011-05-19 16:55:47 +00002012 (void) FormatLocaleFile(file," depth: %d\n",windows->image.ximage->depth);
cristy3ed852e2009-09-05 21:47:34 +00002013 if (windows->visual_info->colormap_size != 0)
cristyb51dff52011-05-19 16:55:47 +00002014 (void) FormatLocaleFile(file," colormap size: %d\n",
cristy3ed852e2009-09-05 21:47:34 +00002015 windows->visual_info->colormap_size);
2016 if (resource_info->colormap== SharedColormap)
cristyb51dff52011-05-19 16:55:47 +00002017 (void) FormatLocaleFile(file," colormap type: Shared\n");
cristy3ed852e2009-09-05 21:47:34 +00002018 else
cristyb51dff52011-05-19 16:55:47 +00002019 (void) FormatLocaleFile(file," colormap type: Private\n");
cristy1e604812011-05-19 18:07:50 +00002020 (void) FormatLocaleFile(file," geometry: %dx%d\n",
2021 windows->image.ximage->width,windows->image.ximage->height);
cristy3ed852e2009-09-05 21:47:34 +00002022 if (windows->image.crop_geometry != (char *) NULL)
cristy1e604812011-05-19 18:07:50 +00002023 (void) FormatLocaleFile(file," crop geometry: %s\n",
2024 windows->image.crop_geometry);
cristy3ed852e2009-09-05 21:47:34 +00002025 if (windows->image.pixmap == (Pixmap) NULL)
cristyb51dff52011-05-19 16:55:47 +00002026 (void) FormatLocaleFile(file," type: X Image\n");
cristy3ed852e2009-09-05 21:47:34 +00002027 else
cristyb51dff52011-05-19 16:55:47 +00002028 (void) FormatLocaleFile(file," type: Pixmap\n");
cristy3ed852e2009-09-05 21:47:34 +00002029 if (windows->image.shape != MagickFalse)
cristyb51dff52011-05-19 16:55:47 +00002030 (void) FormatLocaleFile(file," non-rectangular shape: True\n");
cristy3ed852e2009-09-05 21:47:34 +00002031 else
cristyb51dff52011-05-19 16:55:47 +00002032 (void) FormatLocaleFile(file," non-rectangular shape: False\n");
cristy3ed852e2009-09-05 21:47:34 +00002033 if (windows->image.shared_memory != MagickFalse)
cristyb51dff52011-05-19 16:55:47 +00002034 (void) FormatLocaleFile(file," shared memory: True\n");
cristy3ed852e2009-09-05 21:47:34 +00002035 else
cristyb51dff52011-05-19 16:55:47 +00002036 (void) FormatLocaleFile(file," shared memory: False\n");
2037 (void) FormatLocaleFile(file,"\n");
cristy3ed852e2009-09-05 21:47:34 +00002038 if (resource_info->font != (char *) NULL)
cristyb51dff52011-05-19 16:55:47 +00002039 (void) FormatLocaleFile(file,"Font: %s\n\n",resource_info->font);
cristy3ed852e2009-09-05 21:47:34 +00002040 if (resource_info->text_font != (char *) NULL)
cristyb51dff52011-05-19 16:55:47 +00002041 (void) FormatLocaleFile(file,"Text font: %s\n\n",resource_info->text_font);
cristy3ed852e2009-09-05 21:47:34 +00002042 /*
2043 Write info about the undo cache to a file.
2044 */
2045 bytes=0;
2046 for (levels=0; undo_image != (Image *) NULL; levels++)
2047 {
2048 number_pixels=undo_image->list->columns*undo_image->list->rows;
2049 bytes+=number_pixels*sizeof(PixelPacket);
2050 undo_image=GetPreviousImageInList(undo_image);
2051 }
cristyb51dff52011-05-19 16:55:47 +00002052 (void) FormatLocaleFile(file,"Undo Edit Cache\n levels: %u\n",levels);
cristy1e604812011-05-19 18:07:50 +00002053 (void) FormatLocaleFile(file," bytes: %.20gmb\n",(double)
2054 ((bytes+(1 << 19)) >> 20));
cristyb51dff52011-05-19 16:55:47 +00002055 (void) FormatLocaleFile(file," limit: %.20gmb\n\n",(double)
cristyf2faecf2010-05-28 19:19:36 +00002056 resource_info->undo_cache);
cristy3ed852e2009-09-05 21:47:34 +00002057 /*
2058 Write info about the image to a file.
2059 */
cristya4037272011-08-28 15:11:39 +00002060 (void) IdentifyImage(image,file,MagickTrue,&image->exception);
cristy3ed852e2009-09-05 21:47:34 +00002061 (void) fclose(file);
2062 text=FileToString(filename,~0,&image->exception);
2063 (void) RelinquishUniqueFileResource(filename);
2064 if (text == (char *) NULL)
2065 {
2066 XNoticeWidget(display,windows,"MemoryAllocationFailed",
2067 "UnableToDisplayImageInfo");
2068 return;
2069 }
2070 textlist=StringToList(text);
2071 if (textlist != (char **) NULL)
2072 {
2073 char
2074 title[MaxTextExtent];
2075
2076 /*
2077 Display information about the image in the Text View widget.
2078 */
2079 (void) XWithdrawWindow(display,windows->info.id,windows->info.screen);
cristyb51dff52011-05-19 16:55:47 +00002080 (void) FormatLocaleString(title,MaxTextExtent,"Image Info: %s",
cristy3ed852e2009-09-05 21:47:34 +00002081 image->filename);
2082 XTextViewWidget(display,resource_info,windows,MagickTrue,title,
2083 (char const **) textlist);
2084 for (i=0; textlist[i] != (char *) NULL; i++)
2085 textlist[i]=DestroyString(textlist[i]);
2086 textlist=(char **) RelinquishMagickMemory(textlist);
2087 }
2088 text=DestroyString(text);
2089}
2090
2091/*
2092%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2093% %
2094% %
2095% %
2096+ X D i t h e r I m a g e %
2097% %
2098% %
2099% %
2100%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2101%
2102% XDitherImage() dithers the reference image as required by the HP Color
2103% Recovery algorithm. The color values are quantized to 3 bits of red and
2104% green, and 2 bits of blue (3/3/2) and can be used as indices into a 8-bit X
2105% standard colormap.
2106%
2107% The format of the XDitherImage method is:
2108%
2109% void XDitherImage(Image *image,XImage *ximage)
2110%
2111% A description of each parameter follows:
2112%
2113% o image: the image.
2114%
2115% o ximage: Specifies a pointer to a XImage structure; returned from
2116% XCreateImage.
2117%
cristy3ed852e2009-09-05 21:47:34 +00002118*/
2119static void XDitherImage(Image *image,XImage *ximage)
2120{
2121 static const short int
2122 dither_red[2][16]=
2123 {
2124 {-16, 4, -1, 11,-14, 6, -3, 9,-15, 5, -2, 10,-13, 7, -4, 8},
2125 { 15, -5, 0,-12, 13, -7, 2,-10, 14, -6, 1,-11, 12, -8, 3, -9}
2126 },
2127 dither_green[2][16]=
2128 {
2129 { 11,-15, 7, -3, 8,-14, 4, -2, 10,-16, 6, -4, 9,-13, 5, -1},
2130 {-12, 14, -8, 2, -9, 13, -5, 1,-11, 15, -7, 3,-10, 12, -6, 0}
2131 },
2132 dither_blue[2][16]=
2133 {
2134 { -3, 9,-13, 7, -1, 11,-15, 5, -4, 8,-14, 6, -2, 10,-16, 4},
2135 { 2,-10, 12, -8, 0,-12, 14, -6, 3, -9, 13, -7, 1,-11, 15, -5}
2136 };
2137
cristyc57f6942010-11-12 01:47:39 +00002138 CacheView
2139 *image_view;
cristy3ed852e2009-09-05 21:47:34 +00002140
2141 int
cristyc57f6942010-11-12 01:47:39 +00002142 value,
cristy3ed852e2009-09-05 21:47:34 +00002143 y;
2144
cristyc57f6942010-11-12 01:47:39 +00002145 PixelPacket
2146 color;
cristy3ed852e2009-09-05 21:47:34 +00002147
2148 register char
2149 *q;
2150
cristy4c08aed2011-07-01 19:47:50 +00002151 register const Quantum
cristy3ed852e2009-09-05 21:47:34 +00002152 *p;
2153
2154 register int
2155 i,
2156 j,
2157 x;
2158
2159 unsigned int
2160 scanline_pad;
2161
cristybb503372010-05-27 20:51:26 +00002162 register size_t
cristy3ed852e2009-09-05 21:47:34 +00002163 pixel;
2164
2165 unsigned char
2166 *blue_map[2][16],
2167 *green_map[2][16],
2168 *red_map[2][16];
2169
2170 /*
2171 Allocate and initialize dither maps.
2172 */
2173 for (i=0; i < 2; i++)
2174 for (j=0; j < 16; j++)
2175 {
2176 red_map[i][j]=(unsigned char *) AcquireQuantumMemory(256UL,
2177 sizeof(*red_map));
2178 green_map[i][j]=(unsigned char *) AcquireQuantumMemory(256UL,
2179 sizeof(*green_map));
2180 blue_map[i][j]=(unsigned char *) AcquireQuantumMemory(256UL,
2181 sizeof(*blue_map));
2182 if ((red_map[i][j] == (unsigned char *) NULL) ||
2183 (green_map[i][j] == (unsigned char *) NULL) ||
2184 (blue_map[i][j] == (unsigned char *) NULL))
2185 {
2186 ThrowXWindowFatalException(ResourceLimitError,
2187 "MemoryAllocationFailed",image->filename);
2188 return;
2189 }
2190 }
2191 /*
2192 Initialize dither tables.
2193 */
2194 for (i=0; i < 2; i++)
2195 for (j=0; j < 16; j++)
2196 for (x=0; x < 256; x++)
2197 {
2198 value=x-16;
2199 if (x < 48)
2200 value=x/2+8;
2201 value+=dither_red[i][j];
2202 red_map[i][j][x]=(unsigned char)
2203 ((value < 0) ? 0 : (value > 255) ? 255 : value);
2204 value=x-16;
2205 if (x < 48)
2206 value=x/2+8;
2207 value+=dither_green[i][j];
2208 green_map[i][j][x]=(unsigned char)
2209 ((value < 0) ? 0 : (value > 255) ? 255 : value);
2210 value=x-32;
2211 if (x < 112)
2212 value=x/2+24;
cristybb503372010-05-27 20:51:26 +00002213 value+=((size_t) dither_blue[i][j] << 1);
cristy3ed852e2009-09-05 21:47:34 +00002214 blue_map[i][j][x]=(unsigned char)
2215 ((value < 0) ? 0 : (value > 255) ? 255 : value);
2216 }
2217 /*
2218 Dither image.
2219 */
2220 scanline_pad=(unsigned int) (ximage->bytes_per_line-
cristybb503372010-05-27 20:51:26 +00002221 ((size_t) (ximage->width*ximage->bits_per_pixel) >> 3));
cristy3ed852e2009-09-05 21:47:34 +00002222 i=0;
2223 j=0;
2224 q=ximage->data;
cristyc57f6942010-11-12 01:47:39 +00002225 image_view=AcquireCacheView(image);
cristy3ed852e2009-09-05 21:47:34 +00002226 for (y=0; y < (int) image->rows; y++)
2227 {
cristyc57f6942010-11-12 01:47:39 +00002228 p=GetCacheViewVirtualPixels(image_view,0,(ssize_t) y,image->columns,1,
2229 &image->exception);
cristy4c08aed2011-07-01 19:47:50 +00002230 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00002231 break;
2232 for (x=0; x < (int) image->columns; x++)
2233 {
cristyce70c172010-01-07 17:15:30 +00002234 color.red=ClampToQuantum((MagickRealType) (red_map[i][j][(int)
cristy4c08aed2011-07-01 19:47:50 +00002235 ScaleQuantumToChar(GetPixelRed(image,p))] << 8));
cristyce70c172010-01-07 17:15:30 +00002236 color.green=ClampToQuantum((MagickRealType) (green_map[i][j][(int)
cristy4c08aed2011-07-01 19:47:50 +00002237 ScaleQuantumToChar(GetPixelGreen(image,p))] << 8));
cristyce70c172010-01-07 17:15:30 +00002238 color.blue=ClampToQuantum((MagickRealType) (blue_map[i][j][(int)
cristy4c08aed2011-07-01 19:47:50 +00002239 ScaleQuantumToChar(GetPixelBlue(image,p))] << 8));
cristybb503372010-05-27 20:51:26 +00002240 pixel=(size_t) (((size_t) color.red & 0xe0) |
2241 (((size_t) color.green & 0xe0) >> 3) |
2242 (((size_t) color.blue & 0xc0) >> 6));
cristy3ed852e2009-09-05 21:47:34 +00002243 *q++=(char) pixel;
cristyed231572011-07-14 02:18:59 +00002244 p+=GetPixelChannels(image);
cristy3ed852e2009-09-05 21:47:34 +00002245 j++;
2246 if (j == 16)
2247 j=0;
2248 }
2249 q+=scanline_pad;
2250 i++;
2251 if (i == 2)
2252 i=0;
2253 }
cristyc57f6942010-11-12 01:47:39 +00002254 image_view=DestroyCacheView(image_view);
cristy3ed852e2009-09-05 21:47:34 +00002255 /*
2256 Free allocated memory.
2257 */
2258 for (i=0; i < 2; i++)
2259 for (j=0; j < 16; j++)
2260 {
2261 green_map[i][j]=(unsigned char *) RelinquishMagickMemory(green_map[i][j]);
2262 blue_map[i][j]=(unsigned char *) RelinquishMagickMemory(blue_map[i][j]);
2263 red_map[i][j]=(unsigned char *) RelinquishMagickMemory(red_map[i][j]);
2264 }
2265}
2266
2267/*
2268%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2269% %
2270% %
2271% %
2272% X D r a w I m a g e %
2273% %
2274% %
2275% %
2276%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2277%
2278% XDrawImage() draws a line on the image.
2279%
2280% The format of the XDrawImage method is:
2281%
2282% MagickBooleanType XDrawImage(display,pixel,draw_info,image)
2283%
2284% A description of each parameter follows:
2285%
2286% o display: Specifies a connection to an X server; returned from
2287% XOpenDisplay.
2288%
2289% o pixel: Specifies a pointer to a XPixelInfo structure.
2290%
2291% o draw_info: Specifies a pointer to a XDrawInfo structure.
2292%
2293% o image: the image.
2294%
2295*/
cristybcbda3f2011-09-03 13:01:22 +00002296MagickPrivate MagickBooleanType XDrawImage(Display *display,
cristy3ed852e2009-09-05 21:47:34 +00002297 const XPixelInfo *pixel,XDrawInfo *draw_info,Image *image)
2298{
cristyc57f6942010-11-12 01:47:39 +00002299 CacheView
2300 *draw_view;
2301
cristy3ed852e2009-09-05 21:47:34 +00002302 ExceptionInfo
2303 *exception;
2304
2305 GC
2306 draw_context;
2307
2308 Image
2309 *draw_image;
2310
2311 int
2312 x,
2313 y;
2314
2315 MagickBooleanType
2316 matte;
2317
cristy2ed42f62011-10-02 19:49:57 +00002318 Quantum
2319 virtual_pixel[MaxPixelChannels];
2320
cristy3ed852e2009-09-05 21:47:34 +00002321 Pixmap
2322 draw_pixmap;
2323
2324 unsigned int
2325 depth,
2326 height,
2327 width;
2328
2329 Window
2330 root_window;
2331
2332 XGCValues
2333 context_values;
2334
2335 XImage
2336 *draw_ximage;
2337
2338 /*
2339 Initialize drawd image.
2340 */
2341 assert(display != (Display *) NULL);
2342 assert(pixel != (XPixelInfo *) NULL);
2343 assert(draw_info != (XDrawInfo *) NULL);
2344 assert(image != (Image *) NULL);
2345 if (image->debug != MagickFalse)
2346 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
2347 /*
2348 Initialize drawd pixmap.
2349 */
2350 root_window=XRootWindow(display,XDefaultScreen(display));
2351 depth=(unsigned int) XDefaultDepth(display,XDefaultScreen(display));
2352 draw_pixmap=XCreatePixmap(display,root_window,draw_info->width,
2353 draw_info->height,depth);
2354 if (draw_pixmap == (Pixmap) NULL)
2355 return(MagickFalse);
2356 /*
2357 Initialize graphics info.
2358 */
cristybb503372010-05-27 20:51:26 +00002359 context_values.background=(size_t) (~0);
cristy3ed852e2009-09-05 21:47:34 +00002360 context_values.foreground=0;
2361 context_values.line_width=(int) draw_info->line_width;
cristybb503372010-05-27 20:51:26 +00002362 draw_context=XCreateGC(display,root_window,(size_t)
cristy3ed852e2009-09-05 21:47:34 +00002363 (GCBackground | GCForeground | GCLineWidth),&context_values);
2364 if (draw_context == (GC) NULL)
2365 return(MagickFalse);
2366 /*
2367 Clear pixmap.
2368 */
2369 (void) XFillRectangle(display,draw_pixmap,draw_context,0,0,draw_info->width,
2370 draw_info->height);
2371 /*
2372 Draw line to pixmap.
2373 */
2374 (void) XSetBackground(display,draw_context,0);
cristybb503372010-05-27 20:51:26 +00002375 (void) XSetForeground(display,draw_context,(size_t) (~0));
cristydd05beb2010-11-21 21:23:39 +00002376 if (draw_info->stipple != (Pixmap) NULL)
2377 {
2378 (void) XSetFillStyle(display,draw_context,FillOpaqueStippled);
2379 (void) XSetStipple(display,draw_context,draw_info->stipple);
2380 }
cristy3ed852e2009-09-05 21:47:34 +00002381 switch (draw_info->element)
2382 {
2383 case PointElement:
2384 default:
2385 {
2386 (void) XDrawLines(display,draw_pixmap,draw_context,
2387 draw_info->coordinate_info,(int) draw_info->number_coordinates,
2388 CoordModeOrigin);
2389 break;
2390 }
2391 case LineElement:
2392 {
2393 (void) XDrawLine(display,draw_pixmap,draw_context,draw_info->line_info.x1,
2394 draw_info->line_info.y1,draw_info->line_info.x2,
2395 draw_info->line_info.y2);
2396 break;
2397 }
2398 case RectangleElement:
2399 {
2400 (void) XDrawRectangle(display,draw_pixmap,draw_context,
2401 (int) draw_info->rectangle_info.x,(int) draw_info->rectangle_info.y,
2402 (unsigned int) draw_info->rectangle_info.width,
2403 (unsigned int) draw_info->rectangle_info.height);
2404 break;
2405 }
2406 case FillRectangleElement:
2407 {
2408 (void) XFillRectangle(display,draw_pixmap,draw_context,
2409 (int) draw_info->rectangle_info.x,(int) draw_info->rectangle_info.y,
2410 (unsigned int) draw_info->rectangle_info.width,
2411 (unsigned int) draw_info->rectangle_info.height);
2412 break;
2413 }
2414 case CircleElement:
2415 case EllipseElement:
2416 {
2417 (void) XDrawArc(display,draw_pixmap,draw_context,
2418 (int) draw_info->rectangle_info.x,(int) draw_info->rectangle_info.y,
2419 (unsigned int) draw_info->rectangle_info.width,
2420 (unsigned int) draw_info->rectangle_info.height,0,360*64);
2421 break;
2422 }
2423 case FillCircleElement:
2424 case FillEllipseElement:
2425 {
2426 (void) XFillArc(display,draw_pixmap,draw_context,
2427 (int) draw_info->rectangle_info.x,(int) draw_info->rectangle_info.y,
2428 (unsigned int) draw_info->rectangle_info.width,
2429 (unsigned int) draw_info->rectangle_info.height,0,360*64);
2430 break;
2431 }
2432 case PolygonElement:
2433 {
2434 XPoint
2435 *coordinate_info;
2436
2437 coordinate_info=draw_info->coordinate_info;
2438 (void) XDrawLines(display,draw_pixmap,draw_context,coordinate_info,
2439 (int) draw_info->number_coordinates,CoordModeOrigin);
2440 (void) XDrawLine(display,draw_pixmap,draw_context,
2441 coordinate_info[draw_info->number_coordinates-1].x,
2442 coordinate_info[draw_info->number_coordinates-1].y,
2443 coordinate_info[0].x,coordinate_info[0].y);
2444 break;
2445 }
2446 case FillPolygonElement:
2447 {
2448 (void) XFillPolygon(display,draw_pixmap,draw_context,
2449 draw_info->coordinate_info,(int) draw_info->number_coordinates,Complex,
2450 CoordModeOrigin);
2451 break;
2452 }
2453 }
2454 (void) XFreeGC(display,draw_context);
2455 /*
2456 Initialize X image.
2457 */
2458 draw_ximage=XGetImage(display,draw_pixmap,0,0,draw_info->width,
2459 draw_info->height,AllPlanes,ZPixmap);
2460 if (draw_ximage == (XImage *) NULL)
2461 return(MagickFalse);
2462 (void) XFreePixmap(display,draw_pixmap);
2463 /*
2464 Initialize draw image.
2465 */
cristy9950d572011-10-01 18:22:35 +00002466 draw_image=AcquireImage((ImageInfo *) NULL,&image->exception);
cristy3ed852e2009-09-05 21:47:34 +00002467 if (draw_image == (Image *) NULL)
2468 return(MagickFalse);
2469 draw_image->columns=draw_info->width;
2470 draw_image->rows=draw_info->height;
2471 /*
2472 Transfer drawn X image to image.
2473 */
2474 width=(unsigned int) image->columns;
2475 height=(unsigned int) image->rows;
2476 x=0;
2477 y=0;
2478 (void) XParseGeometry(draw_info->geometry,&x,&y,&width,&height);
cristy2ed42f62011-10-02 19:49:57 +00002479 (void) GetOneVirtualPixel(image,(ssize_t) x,(ssize_t) y,virtual_pixel,
2480 &image->exception);
2481 draw_image->background_color.red=virtual_pixel[RedPixelChannel];
2482 draw_image->background_color.green=virtual_pixel[GreenPixelChannel];
2483 draw_image->background_color.blue=virtual_pixel[BluePixelChannel];
2484 draw_image->background_color.alpha=virtual_pixel[AlphaPixelChannel];
cristy574cc262011-08-05 01:23:58 +00002485 if (SetImageStorageClass(draw_image,DirectClass,&image->exception) == MagickFalse)
cristy3ed852e2009-09-05 21:47:34 +00002486 return(MagickFalse);
2487 draw_image->matte=MagickTrue;
2488 exception=(&image->exception);
cristyc57f6942010-11-12 01:47:39 +00002489 draw_view=AcquireCacheView(draw_image);
cristy3ed852e2009-09-05 21:47:34 +00002490 for (y=0; y < (int) draw_image->rows; y++)
2491 {
cristyc57f6942010-11-12 01:47:39 +00002492 register int
cristy3ed852e2009-09-05 21:47:34 +00002493 x;
2494
cristy4c08aed2011-07-01 19:47:50 +00002495 register Quantum
cristyc47d1f82009-11-26 01:44:43 +00002496 *restrict q;
cristy3ed852e2009-09-05 21:47:34 +00002497
cristyc57f6942010-11-12 01:47:39 +00002498 q=QueueCacheViewAuthenticPixels(draw_view,0,(ssize_t) y,draw_image->columns,
2499 1,exception);
cristyacd2ed22011-08-30 01:44:23 +00002500 if (q == (Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00002501 break;
cristyc57f6942010-11-12 01:47:39 +00002502 for (x=0; x < (int) draw_image->columns; x++)
cristy3ed852e2009-09-05 21:47:34 +00002503 {
2504 if (XGetPixel(draw_ximage,x,y) == 0)
2505 {
2506 /*
2507 Set this pixel to the background color.
2508 */
cristy4c08aed2011-07-01 19:47:50 +00002509 SetPixelPacket(draw_image,&draw_image->background_color,q);
cristy76761582011-09-18 02:14:00 +00002510 SetPixelAlpha(draw_image,(Quantum) (draw_info->stencil ==
cristy4c08aed2011-07-01 19:47:50 +00002511 OpaqueStencil ? TransparentAlpha : OpaqueAlpha),q);
cristy3ed852e2009-09-05 21:47:34 +00002512 }
2513 else
2514 {
2515 /*
2516 Set this pixel to the pen color.
2517 */
cristy4c08aed2011-07-01 19:47:50 +00002518 SetPixelRed(draw_image,ScaleShortToQuantum(
2519 pixel->pen_color.red),q);
2520 SetPixelGreen(draw_image,ScaleShortToQuantum(
2521 pixel->pen_color.green),q);
2522 SetPixelBlue(draw_image,ScaleShortToQuantum(
2523 pixel->pen_color.blue),q);
2524 SetPixelAlpha(draw_image,(Quantum) (draw_info->stencil ==
2525 OpaqueStencil ? OpaqueAlpha : TransparentAlpha),q);
cristy3ed852e2009-09-05 21:47:34 +00002526 }
cristyed231572011-07-14 02:18:59 +00002527 q+=GetPixelChannels(draw_image);
cristy3ed852e2009-09-05 21:47:34 +00002528 }
cristyc57f6942010-11-12 01:47:39 +00002529 if (SyncCacheViewAuthenticPixels(draw_view,exception) == MagickFalse)
cristy3ed852e2009-09-05 21:47:34 +00002530 break;
2531 }
cristyc57f6942010-11-12 01:47:39 +00002532 draw_view=DestroyCacheView(draw_view);
cristy3ed852e2009-09-05 21:47:34 +00002533 XDestroyImage(draw_ximage);
2534 /*
2535 Determine draw geometry.
2536 */
2537 (void) XParseGeometry(draw_info->geometry,&x,&y,&width,&height);
2538 if ((width != (unsigned int) draw_image->columns) ||
2539 (height != (unsigned int) draw_image->rows))
2540 {
2541 char
2542 image_geometry[MaxTextExtent];
2543
2544 /*
2545 Scale image.
2546 */
cristyb51dff52011-05-19 16:55:47 +00002547 (void) FormatLocaleString(image_geometry,MaxTextExtent,"%ux%u",
cristy3ed852e2009-09-05 21:47:34 +00002548 width,height);
2549 (void) TransformImage(&draw_image,(char *) NULL,image_geometry);
2550 }
2551 if (draw_info->degrees != 0.0)
2552 {
2553 Image
2554 *rotate_image;
2555
2556 int
2557 rotations;
2558
2559 MagickRealType
2560 normalized_degrees;
2561
2562 /*
2563 Rotate image.
2564 */
2565 rotate_image=RotateImage(draw_image,draw_info->degrees,&image->exception);
2566 if (rotate_image == (Image *) NULL)
2567 return(MagickFalse);
2568 draw_image=DestroyImage(draw_image);
2569 draw_image=rotate_image;
2570 /*
2571 Annotation is relative to the degree of rotation.
2572 */
2573 normalized_degrees=draw_info->degrees;
2574 while (normalized_degrees < -45.0)
2575 normalized_degrees+=360.0;
2576 for (rotations=0; normalized_degrees > 45.0; rotations++)
2577 normalized_degrees-=90.0;
2578 switch (rotations % 4)
2579 {
2580 default:
2581 case 0:
2582 break;
2583 case 1:
2584 {
2585 /*
2586 Rotate 90 degrees.
2587 */
2588 x=x-(int) draw_image->columns/2;
2589 y=y+(int) draw_image->columns/2;
2590 break;
2591 }
2592 case 2:
2593 {
2594 /*
2595 Rotate 180 degrees.
2596 */
2597 x=x-(int) draw_image->columns;
2598 break;
2599 }
2600 case 3:
2601 {
2602 /*
2603 Rotate 270 degrees.
2604 */
2605 x=x-(int) draw_image->columns/2;
2606 y=y-(int) (draw_image->rows-(draw_image->columns/2));
2607 break;
2608 }
2609 }
2610 }
2611 /*
2612 Composite text onto the image.
2613 */
cristyc57f6942010-11-12 01:47:39 +00002614 draw_view=AcquireCacheView(draw_image);
cristy3ed852e2009-09-05 21:47:34 +00002615 for (y=0; y < (int) draw_image->rows; y++)
2616 {
cristyc57f6942010-11-12 01:47:39 +00002617 register int
cristy3ed852e2009-09-05 21:47:34 +00002618 x;
2619
cristy4c08aed2011-07-01 19:47:50 +00002620 register Quantum
cristyc47d1f82009-11-26 01:44:43 +00002621 *restrict q;
cristy3ed852e2009-09-05 21:47:34 +00002622
cristyc57f6942010-11-12 01:47:39 +00002623 q=GetCacheViewAuthenticPixels(draw_view,0,(ssize_t) y,draw_image->columns,1,
2624 exception);
cristyacd2ed22011-08-30 01:44:23 +00002625 if (q == (Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00002626 break;
cristyc57f6942010-11-12 01:47:39 +00002627 for (x=0; x < (int) draw_image->columns; x++)
cristy3ed852e2009-09-05 21:47:34 +00002628 {
cristy4c08aed2011-07-01 19:47:50 +00002629 if (GetPixelAlpha(image,q) != TransparentAlpha)
2630 SetPixelAlpha(draw_image,OpaqueAlpha,q);
cristyed231572011-07-14 02:18:59 +00002631 q+=GetPixelChannels(draw_image);
cristy3ed852e2009-09-05 21:47:34 +00002632 }
cristyc57f6942010-11-12 01:47:39 +00002633 if (SyncCacheViewAuthenticPixels(draw_view,exception) == MagickFalse)
cristy3ed852e2009-09-05 21:47:34 +00002634 break;
2635 }
cristyc57f6942010-11-12 01:47:39 +00002636 draw_view=DestroyCacheView(draw_view);
cristy3ed852e2009-09-05 21:47:34 +00002637 (void) XParseGeometry(draw_info->geometry,&x,&y,&width,&height);
2638 if (draw_info->stencil == TransparentStencil)
cristyc57f6942010-11-12 01:47:39 +00002639 (void) CompositeImage(image,CopyOpacityCompositeOp,draw_image,(ssize_t) x,
2640 (ssize_t) y);
cristy3ed852e2009-09-05 21:47:34 +00002641 else
2642 {
2643 matte=image->matte;
cristyc57f6942010-11-12 01:47:39 +00002644 (void) CompositeImage(image,OverCompositeOp,draw_image,(ssize_t) x,
2645 (ssize_t) y);
cristy3ed852e2009-09-05 21:47:34 +00002646 image->matte=matte;
2647 }
2648 draw_image=DestroyImage(draw_image);
2649 return(MagickTrue);
2650}
2651
2652/*
2653%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2654% %
2655% %
2656% %
2657% X E r r o r %
2658% %
2659% %
2660% %
2661%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2662%
2663% XError() ignores BadWindow errors for XQueryTree and XGetWindowAttributes,
2664% and ignores BadDrawable errors for XGetGeometry, and ignores BadValue errors
cristybcbda3f2011-09-03 13:01:22 +00002665% for XQueryColor. It returns MagickFalse in those cases. Otherwise it
2666% returns True.
cristy3ed852e2009-09-05 21:47:34 +00002667%
2668% The format of the XError function is:
2669%
cristybcbda3f2011-09-03 13:01:22 +00002670% int XError(display,error)
cristy3ed852e2009-09-05 21:47:34 +00002671%
2672% A description of each parameter follows:
2673%
2674% o display: Specifies a pointer to the Display structure; returned from
2675% XOpenDisplay.
2676%
2677% o error: Specifies the error event.
2678%
2679*/
2680
2681#if defined(__cplusplus) || defined(c_plusplus)
2682extern "C" {
2683#endif
2684
2685MagickExport int XError(Display *display,XErrorEvent *error)
2686{
2687 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
2688 assert(display != (Display *) NULL);
2689 assert(error != (XErrorEvent *) NULL);
2690 xerror_alert=MagickTrue;
2691 switch (error->request_code)
2692 {
2693 case X_GetGeometry:
2694 {
2695 if ((int) error->error_code == BadDrawable)
2696 return(MagickFalse);
2697 break;
2698 }
2699 case X_GetWindowAttributes:
2700 case X_QueryTree:
2701 {
2702 if ((int) error->error_code == BadWindow)
2703 return(MagickFalse);
2704 break;
2705 }
2706 case X_QueryColors:
2707 {
2708 if ((int) error->error_code == BadValue)
2709 return(MagickFalse);
2710 break;
2711 }
2712 }
2713 return(MagickTrue);
2714}
2715
2716#if defined(__cplusplus) || defined(c_plusplus)
2717}
2718#endif
2719
2720/*
2721%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2722% %
2723% %
2724% %
2725% X F r e e R e s o u r c e s %
2726% %
2727% %
2728% %
2729%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2730%
2731% XFreeResources() frees X11 resources.
2732%
2733% The format of the XFreeResources method is:
2734%
2735% void XFreeResources(Display *display,XVisualInfo *visual_info,
2736% XStandardColormap *map_info,XPixelInfo *pixel,XFontStruct *font_info,
2737% XResourceInfo *resource_info,XWindowInfo *window_info)
2738% resource_info,window_info)
2739%
2740% A description of each parameter follows:
2741%
2742% o display: Specifies a connection to an X server; returned from
2743% XOpenDisplay.
2744%
2745% o visual_info: Specifies a pointer to a X11 XVisualInfo structure;
2746% returned from XGetVisualInfo.
2747%
2748% o map_info: If map_type is specified, this structure is initialized
2749% with info from the Standard Colormap.
2750%
2751% o pixel: Specifies a pointer to a XPixelInfo structure.
2752%
2753% o font_info: Specifies a pointer to a XFontStruct structure.
2754%
2755% o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
2756%
2757% o window_info: Specifies a pointer to a X11 XWindowInfo structure.
2758%
2759*/
cristybcbda3f2011-09-03 13:01:22 +00002760MagickPrivate void XFreeResources(Display *display,XVisualInfo *visual_info,
cristy3ed852e2009-09-05 21:47:34 +00002761 XStandardColormap *map_info,XPixelInfo *pixel,XFontStruct *font_info,
2762 XResourceInfo *resource_info,XWindowInfo *window_info)
2763{
2764 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
2765 assert(display != (Display *) NULL);
2766 assert(resource_info != (XResourceInfo *) NULL);
2767 if (window_info != (XWindowInfo *) NULL)
2768 {
2769 /*
2770 Free X image.
2771 */
2772 if (window_info->ximage != (XImage *) NULL)
2773 XDestroyImage(window_info->ximage);
2774 if (window_info->id != (Window) NULL)
2775 {
2776 /*
2777 Free destroy window and free cursors.
2778 */
2779 if (window_info->id != XRootWindow(display,visual_info->screen))
2780 (void) XDestroyWindow(display,window_info->id);
2781 if (window_info->annotate_context != (GC) NULL)
2782 (void) XFreeGC(display,window_info->annotate_context);
2783 if (window_info->highlight_context != (GC) NULL)
2784 (void) XFreeGC(display,window_info->highlight_context);
2785 if (window_info->widget_context != (GC) NULL)
2786 (void) XFreeGC(display,window_info->widget_context);
2787 if (window_info->cursor != (Cursor) NULL)
2788 (void) XFreeCursor(display,window_info->cursor);
2789 window_info->cursor=(Cursor) NULL;
2790 if (window_info->busy_cursor != (Cursor) NULL)
2791 (void) XFreeCursor(display,window_info->busy_cursor);
2792 window_info->busy_cursor=(Cursor) NULL;
2793 }
2794 }
2795 /*
2796 Free font.
2797 */
2798 if (font_info != (XFontStruct *) NULL)
cristyaafc1922011-03-04 16:59:40 +00002799 {
2800 (void) XFreeFont(display,font_info);
2801 font_info=(XFontStruct *) NULL;
2802 }
cristy3ed852e2009-09-05 21:47:34 +00002803 if (map_info != (XStandardColormap *) NULL)
2804 {
2805 /*
2806 Free X Standard Colormap.
2807 */
2808 if (resource_info->map_type == (char *) NULL)
2809 (void) XFreeStandardColormap(display,visual_info,map_info,pixel);
2810 (void) XFree((void *) map_info);
2811 }
2812 /*
2813 Free X visual info.
2814 */
2815 if (visual_info != (XVisualInfo *) NULL)
2816 (void) XFree((void *) visual_info);
2817 if (resource_info->close_server != MagickFalse)
2818 (void) XCloseDisplay(display);
2819}
2820
2821/*
2822%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2823% %
2824% %
2825% %
2826% X F r e e S t a n d a r d C o l o r m a p %
2827% %
2828% %
2829% %
2830%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2831%
2832% XFreeStandardColormap() frees an X11 colormap.
2833%
2834% The format of the XFreeStandardColormap method is:
2835%
2836% void XFreeStandardColormap(Display *display,
2837% const XVisualInfo *visual_info,XStandardColormap *map_info,
2838% XPixelInfo *pixel)
2839%
2840% A description of each parameter follows:
2841%
2842% o display: Specifies a connection to an X server; returned from
2843% XOpenDisplay.
2844%
2845% o visual_info: Specifies a pointer to a X11 XVisualInfo structure;
2846% returned from XGetVisualInfo.
2847%
2848% o map_info: If map_type is specified, this structure is initialized
2849% with info from the Standard Colormap.
2850%
2851% o pixel: Specifies a pointer to a XPixelInfo structure.
2852%
2853*/
cristybcbda3f2011-09-03 13:01:22 +00002854MagickPrivate void XFreeStandardColormap(Display *display,
cristy3ed852e2009-09-05 21:47:34 +00002855 const XVisualInfo *visual_info,XStandardColormap *map_info,XPixelInfo *pixel)
2856{
2857 /*
2858 Free colormap.
2859 */
2860 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
2861 assert(display != (Display *) NULL);
2862 assert(visual_info != (XVisualInfo *) NULL);
2863 assert(map_info != (XStandardColormap *) NULL);
2864 (void) XFlush(display);
2865 if (map_info->colormap != (Colormap) NULL)
2866 {
2867 if (map_info->colormap != XDefaultColormap(display,visual_info->screen))
2868 (void) XFreeColormap(display,map_info->colormap);
2869 else
2870 if (pixel != (XPixelInfo *) NULL)
2871 if ((visual_info->klass != TrueColor) &&
2872 (visual_info->klass != DirectColor))
2873 (void) XFreeColors(display,map_info->colormap,pixel->pixels,
2874 (int) pixel->colors,0);
2875 }
2876 map_info->colormap=(Colormap) NULL;
2877 if (pixel != (XPixelInfo *) NULL)
2878 {
cristyf2faecf2010-05-28 19:19:36 +00002879 if (pixel->pixels != (unsigned long *) NULL)
2880 pixel->pixels=(unsigned long *) RelinquishMagickMemory(pixel->pixels);
2881 pixel->pixels=(unsigned long *) NULL;
cristy3ed852e2009-09-05 21:47:34 +00002882 }
2883}
2884
2885/*
2886%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2887% %
2888% %
2889% %
2890% X G e t A n n o t a t e I n f o %
2891% %
2892% %
2893% %
2894%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2895%
2896% XGetAnnotateInfo() initializes the AnnotateInfo structure.
2897%
2898% The format of the XGetAnnotateInfo method is:
2899%
2900% void XGetAnnotateInfo(XAnnotateInfo *annotate_info)
2901%
2902% A description of each parameter follows:
2903%
2904% o annotate_info: Specifies a pointer to a XAnnotateInfo structure.
2905%
2906*/
cristybcbda3f2011-09-03 13:01:22 +00002907MagickPrivate void XGetAnnotateInfo(XAnnotateInfo *annotate_info)
cristy3ed852e2009-09-05 21:47:34 +00002908{
2909 /*
2910 Initialize annotate structure.
2911 */
2912 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
2913 assert(annotate_info != (XAnnotateInfo *) NULL);
2914 annotate_info->x=0;
2915 annotate_info->y=0;
2916 annotate_info->width=0;
2917 annotate_info->height=0;
2918 annotate_info->stencil=ForegroundStencil;
2919 annotate_info->degrees=0.0;
2920 annotate_info->font_info=(XFontStruct *) NULL;
2921 annotate_info->text=(char *) NULL;
2922 *annotate_info->geometry='\0';
2923 annotate_info->previous=(XAnnotateInfo *) NULL;
2924 annotate_info->next=(XAnnotateInfo *) NULL;
2925 (void) XSupportsLocale();
2926 (void) XSetLocaleModifiers("");
2927}
2928
2929/*
2930%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2931% %
2932% %
2933% %
2934% X G e t M a p I n f o %
2935% %
2936% %
2937% %
2938%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2939%
2940% XGetMapInfo() initializes the XStandardColormap structure.
2941%
2942% The format of the XStandardColormap method is:
2943%
2944% void XGetMapInfo(const XVisualInfo *visual_info,const Colormap colormap,
2945% XStandardColormap *map_info)
2946%
2947% A description of each parameter follows:
2948%
2949% o colormap: Specifies the ID of the X server colormap.
2950%
2951% o visual_info: Specifies a pointer to a X11 XVisualInfo structure;
2952% returned from XGetVisualInfo.
2953%
2954% o map_info: Specifies a pointer to a X11 XStandardColormap structure.
2955%
2956*/
cristybcbda3f2011-09-03 13:01:22 +00002957MagickPrivate void XGetMapInfo(const XVisualInfo *visual_info,
cristy3ed852e2009-09-05 21:47:34 +00002958 const Colormap colormap,XStandardColormap *map_info)
2959{
2960 /*
2961 Initialize map info.
2962 */
2963 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
2964 assert(visual_info != (XVisualInfo *) NULL);
2965 assert(map_info != (XStandardColormap *) NULL);
2966 map_info->colormap=colormap;
2967 map_info->red_max=visual_info->red_mask;
cristybb503372010-05-27 20:51:26 +00002968 map_info->red_mult=(size_t) (map_info->red_max != 0 ? 1 : 0);
cristy3ed852e2009-09-05 21:47:34 +00002969 if (map_info->red_max != 0)
2970 while ((map_info->red_max & 0x01) == 0)
2971 {
2972 map_info->red_max>>=1;
2973 map_info->red_mult<<=1;
2974 }
2975 map_info->green_max=visual_info->green_mask;
cristybb503372010-05-27 20:51:26 +00002976 map_info->green_mult=(size_t) (map_info->green_max != 0 ? 1 : 0);
cristy3ed852e2009-09-05 21:47:34 +00002977 if (map_info->green_max != 0)
2978 while ((map_info->green_max & 0x01) == 0)
2979 {
2980 map_info->green_max>>=1;
2981 map_info->green_mult<<=1;
2982 }
2983 map_info->blue_max=visual_info->blue_mask;
cristybb503372010-05-27 20:51:26 +00002984 map_info->blue_mult=(size_t) (map_info->blue_max != 0 ? 1 : 0);
cristy3ed852e2009-09-05 21:47:34 +00002985 if (map_info->blue_max != 0)
2986 while ((map_info->blue_max & 0x01) == 0)
2987 {
2988 map_info->blue_max>>=1;
2989 map_info->blue_mult<<=1;
2990 }
2991 map_info->base_pixel=0;
2992}
2993
2994/*
2995%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2996% %
2997% %
2998% %
2999% X G e t P i x e l I n f o %
3000% %
3001% %
3002% %
3003%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3004%
cristy4c08aed2011-07-01 19:47:50 +00003005% XGetPixelInfo() initializes the PixelPacket structure.
cristy3ed852e2009-09-05 21:47:34 +00003006%
cristy4c08aed2011-07-01 19:47:50 +00003007% The format of the XGetPixelInfo method is:
cristy3ed852e2009-09-05 21:47:34 +00003008%
cristy4c08aed2011-07-01 19:47:50 +00003009% void XGetPixelInfo(Display *display,const XVisualInfo *visual_info,
cristy3ed852e2009-09-05 21:47:34 +00003010% const XStandardColormap *map_info,const XResourceInfo *resource_info,
3011% Image *image,XPixelInfo *pixel)
3012% pixel)
3013%
3014% A description of each parameter follows:
3015%
3016% o display: Specifies a connection to an X server; returned from
3017% XOpenDisplay.
3018%
3019% o visual_info: Specifies a pointer to a X11 XVisualInfo structure;
3020% returned from XGetVisualInfo.
3021%
3022% o map_info: If map_type is specified, this structure is initialized
3023% with info from the Standard Colormap.
3024%
3025% o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
3026%
3027% o image: the image.
3028%
3029% o pixel: Specifies a pointer to a XPixelInfo structure.
3030%
3031*/
cristybcbda3f2011-09-03 13:01:22 +00003032MagickPrivate void XGetPixelInfo(Display *display,
cristy3ed852e2009-09-05 21:47:34 +00003033 const XVisualInfo *visual_info,const XStandardColormap *map_info,
3034 const XResourceInfo *resource_info,Image *image,XPixelInfo *pixel)
3035{
3036 static const char
3037 *PenColors[MaxNumberPens]=
3038 {
3039 "#000000000000", /* black */
3040 "#00000000ffff", /* blue */
3041 "#0000ffffffff", /* cyan */
3042 "#0000ffff0000", /* green */
3043 "#bdbdbdbdbdbd", /* gray */
3044 "#ffff00000000", /* red */
3045 "#ffff0000ffff", /* magenta */
3046 "#ffffffff0000", /* yellow */
3047 "#ffffffffffff", /* white */
3048 "#bdbdbdbdbdbd", /* gray */
3049 "#bdbdbdbdbdbd" /* gray */
3050 };
3051
3052 Colormap
3053 colormap;
3054
cristybb503372010-05-27 20:51:26 +00003055 register ssize_t
cristy3ed852e2009-09-05 21:47:34 +00003056 i;
3057
3058 Status
3059 status;
3060
3061 unsigned int
3062 packets;
3063
3064 /*
3065 Initialize pixel info.
3066 */
3067 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
3068 assert(display != (Display *) NULL);
3069 assert(visual_info != (XVisualInfo *) NULL);
3070 assert(map_info != (XStandardColormap *) NULL);
3071 assert(resource_info != (XResourceInfo *) NULL);
3072 assert(pixel != (XPixelInfo *) NULL);
3073 pixel->colors=0;
3074 if (image != (Image *) NULL)
3075 if (image->storage_class == PseudoClass)
cristyc57f6942010-11-12 01:47:39 +00003076 pixel->colors=(ssize_t) image->colors;
cristy3ed852e2009-09-05 21:47:34 +00003077 packets=(unsigned int)
3078 MagickMax((int) pixel->colors,visual_info->colormap_size)+MaxNumberPens;
cristyf2faecf2010-05-28 19:19:36 +00003079 if (pixel->pixels != (unsigned long *) NULL)
3080 pixel->pixels=(unsigned long *) RelinquishMagickMemory(pixel->pixels);
3081 pixel->pixels=(unsigned long *) AcquireQuantumMemory(packets,
cristy3ed852e2009-09-05 21:47:34 +00003082 sizeof(pixel->pixels));
cristyf2faecf2010-05-28 19:19:36 +00003083 if (pixel->pixels == (unsigned long *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00003084 ThrowXWindowFatalException(ResourceLimitFatalError,"UnableToGetPixelInfo",
3085 image->filename);
3086 /*
3087 Set foreground color.
3088 */
3089 colormap=map_info->colormap;
3090 (void) XParseColor(display,colormap,(char *) ForegroundColor,
3091 &pixel->foreground_color);
3092 status=XParseColor(display,colormap,resource_info->foreground_color,
3093 &pixel->foreground_color);
3094 if (status == False)
3095 ThrowXWindowFatalException(XServerError,"ColorIsNotKnownToServer",
3096 resource_info->foreground_color);
3097 pixel->foreground_color.pixel=
3098 XStandardPixel(map_info,&pixel->foreground_color);
3099 pixel->foreground_color.flags=(char) (DoRed | DoGreen | DoBlue);
3100 /*
3101 Set background color.
3102 */
3103 (void) XParseColor(display,colormap,"#d6d6d6d6d6d6",&pixel->background_color);
3104 status=XParseColor(display,colormap,resource_info->background_color,
3105 &pixel->background_color);
3106 if (status == False)
3107 ThrowXWindowFatalException(XServerError,"ColorIsNotKnownToServer",
3108 resource_info->background_color);
3109 pixel->background_color.pixel=
3110 XStandardPixel(map_info,&pixel->background_color);
3111 pixel->background_color.flags=(char) (DoRed | DoGreen | DoBlue);
3112 /*
3113 Set border color.
3114 */
3115 (void) XParseColor(display,colormap,(char *) BorderColor,
3116 &pixel->border_color);
3117 status=XParseColor(display,colormap,resource_info->border_color,
3118 &pixel->border_color);
3119 if (status == False)
3120 ThrowXWindowFatalException(XServerError,"ColorIsNotKnownToServer",
3121 resource_info->border_color);
3122 pixel->border_color.pixel=XStandardPixel(map_info,&pixel->border_color);
3123 pixel->border_color.flags=(char) (DoRed | DoGreen | DoBlue);
3124 /*
3125 Set matte color.
3126 */
3127 pixel->matte_color=pixel->background_color;
3128 if (resource_info->matte_color != (char *) NULL)
3129 {
3130 /*
3131 Matte color is specified as a X resource or command line argument.
3132 */
3133 status=XParseColor(display,colormap,resource_info->matte_color,
3134 &pixel->matte_color);
3135 if (status == False)
3136 ThrowXWindowFatalException(XServerError,"ColorIsNotKnownToServer",
3137 resource_info->matte_color);
3138 pixel->matte_color.pixel=XStandardPixel(map_info,&pixel->matte_color);
3139 pixel->matte_color.flags=(char) (DoRed | DoGreen | DoBlue);
3140 }
3141 /*
3142 Set highlight color.
3143 */
3144 pixel->highlight_color.red=(unsigned short) ((
3145 pixel->matte_color.red*ScaleQuantumToShort(HighlightModulate))/65535L+
3146 (ScaleQuantumToShort((Quantum) (QuantumRange-HighlightModulate))));
3147 pixel->highlight_color.green=(unsigned short) ((
3148 pixel->matte_color.green*ScaleQuantumToShort(HighlightModulate))/65535L+
3149 (ScaleQuantumToShort((Quantum) (QuantumRange-HighlightModulate))));
3150 pixel->highlight_color.blue=(unsigned short) ((
3151 pixel->matte_color.blue*ScaleQuantumToShort(HighlightModulate))/65535L+
3152 (ScaleQuantumToShort((Quantum) (QuantumRange-HighlightModulate))));
3153 pixel->highlight_color.pixel=
3154 XStandardPixel(map_info,&pixel->highlight_color);
3155 pixel->highlight_color.flags=(char) (DoRed | DoGreen | DoBlue);
3156 /*
3157 Set shadow color.
3158 */
3159 pixel->shadow_color.red=(unsigned short) (((MagickRealType)
3160 pixel->matte_color.red*ScaleQuantumToShort(ShadowModulate))/65535L);
3161 pixel->shadow_color.green=(unsigned short) (((MagickRealType)
3162 pixel->matte_color.green*ScaleQuantumToShort(ShadowModulate))/65535L);
3163 pixel->shadow_color.blue=(unsigned short) (((MagickRealType)
3164 pixel->matte_color.blue*ScaleQuantumToShort(ShadowModulate))/65535L);
3165 pixel->shadow_color.pixel=XStandardPixel(map_info,&pixel->shadow_color);
3166 pixel->shadow_color.flags=(char) (DoRed | DoGreen | DoBlue);
3167 /*
3168 Set depth color.
3169 */
3170 pixel->depth_color.red=(unsigned short) (((MagickRealType)
3171 pixel->matte_color.red*ScaleQuantumToShort(DepthModulate))/65535L);
3172 pixel->depth_color.green=(unsigned short) (((MagickRealType)
3173 pixel->matte_color.green*ScaleQuantumToShort(DepthModulate))/65535L);
3174 pixel->depth_color.blue=(unsigned short) (((MagickRealType)
3175 pixel->matte_color.blue*ScaleQuantumToShort(DepthModulate))/65535L);
3176 pixel->depth_color.pixel=XStandardPixel(map_info,&pixel->depth_color);
3177 pixel->depth_color.flags=(char) (DoRed | DoGreen | DoBlue);
3178 /*
3179 Set trough color.
3180 */
3181 pixel->trough_color.red=(unsigned short) (((MagickRealType)
3182 pixel->matte_color.red*ScaleQuantumToShort(TroughModulate))/65535L);
3183 pixel->trough_color.green=(unsigned short) (((MagickRealType)
3184 pixel->matte_color.green*ScaleQuantumToShort(TroughModulate))/65535L);
3185 pixel->trough_color.blue=(unsigned short) (((MagickRealType)
3186 pixel->matte_color.blue*ScaleQuantumToShort(TroughModulate))/65535L);
3187 pixel->trough_color.pixel=XStandardPixel(map_info,&pixel->trough_color);
3188 pixel->trough_color.flags=(char) (DoRed | DoGreen | DoBlue);
3189 /*
3190 Set pen color.
3191 */
3192 for (i=0; i < MaxNumberPens; i++)
3193 {
3194 (void) XParseColor(display,colormap,(char *) PenColors[i],
3195 &pixel->pen_colors[i]);
3196 status=XParseColor(display,colormap,resource_info->pen_colors[i],
3197 &pixel->pen_colors[i]);
3198 if (status == False)
3199 ThrowXWindowFatalException(XServerError,"ColorIsNotKnownToServer",
3200 resource_info->pen_colors[i]);
3201 pixel->pen_colors[i].pixel=XStandardPixel(map_info,&pixel->pen_colors[i]);
3202 pixel->pen_colors[i].flags=(char) (DoRed | DoGreen | DoBlue);
3203 }
3204 pixel->box_color=pixel->background_color;
3205 pixel->pen_color=pixel->foreground_color;
3206 pixel->box_index=0;
3207 pixel->pen_index=1;
3208 if (image != (Image *) NULL)
3209 {
3210 if ((resource_info->gamma_correct != MagickFalse) &&
3211 (image->gamma != 0.0))
3212 {
3213 GeometryInfo
3214 geometry_info;
3215
3216 MagickStatusType
3217 flags;
3218
3219 /*
3220 Initialize map relative to display and image gamma.
3221 */
3222 flags=ParseGeometry(resource_info->display_gamma,&geometry_info);
3223 red_gamma=geometry_info.rho;
3224 green_gamma=geometry_info.sigma;
3225 if ((flags & SigmaValue) == 0)
3226 green_gamma=red_gamma;
3227 blue_gamma=geometry_info.xi;
3228 if ((flags & XiValue) == 0)
3229 blue_gamma=red_gamma;
3230 red_gamma*=image->gamma;
3231 green_gamma*=image->gamma;
3232 blue_gamma*=image->gamma;
3233 }
3234 if (image->storage_class == PseudoClass)
3235 {
3236 /*
3237 Initialize pixel array for images of type PseudoClass.
3238 */
cristybb503372010-05-27 20:51:26 +00003239 for (i=0; i < (ssize_t) image->colors; i++)
cristy4c08aed2011-07-01 19:47:50 +00003240 pixel->pixels[i]=XGammaPacket(map_info,image->colormap+i);
cristy3ed852e2009-09-05 21:47:34 +00003241 for (i=0; i < MaxNumberPens; i++)
3242 pixel->pixels[image->colors+i]=pixel->pen_colors[i].pixel;
3243 pixel->colors+=MaxNumberPens;
3244 }
3245 }
3246}
3247
3248/*
3249%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3250% %
3251% %
3252% %
3253% X G e t R e s o u r c e C l a s s %
3254% %
3255% %
3256% %
3257%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3258%
3259% XGetResourceClass() queries the X server for the specified resource name or
3260% class. If the resource name or class is not defined in the database, the
3261% supplied default value is returned.
3262%
3263% The format of the XGetResourceClass method is:
3264%
3265% char *XGetResourceClass(XrmDatabase database,const char *client_name,
3266% const char *keyword,char *resource_default)
3267%
3268% A description of each parameter follows:
3269%
3270% o database: Specifies a resource database; returned from
3271% XrmGetStringDatabase.
3272%
3273% o client_name: Specifies the application name used to retrieve resource
3274% info from the X server database.
3275%
3276% o keyword: Specifies the keyword of the value being retrieved.
3277%
3278% o resource_default: Specifies the default value to return if the query
3279% fails to find the specified keyword/class.
3280%
3281*/
3282MagickExport char *XGetResourceClass(XrmDatabase database,
3283 const char *client_name,const char *keyword,char *resource_default)
3284{
3285 char
3286 resource_class[MaxTextExtent],
3287 resource_name[MaxTextExtent];
3288
3289 static char
3290 *resource_type;
3291
3292 Status
3293 status;
3294
3295 XrmValue
3296 resource_value;
3297
3298 if (database == (XrmDatabase) NULL)
3299 return(resource_default);
3300 *resource_name='\0';
3301 *resource_class='\0';
3302 if (keyword != (char *) NULL)
3303 {
3304 int
3305 c,
3306 k;
3307
3308 /*
3309 Initialize resource keyword and class.
3310 */
cristyb51dff52011-05-19 16:55:47 +00003311 (void) FormatLocaleString(resource_name,MaxTextExtent,"%s.%s",
cristy3ed852e2009-09-05 21:47:34 +00003312 client_name,keyword);
3313 c=(int) (*client_name);
3314 if ((c >= XK_a) && (c <= XK_z))
3315 c-=(XK_a-XK_A);
3316 else
3317 if ((c >= XK_agrave) && (c <= XK_odiaeresis))
3318 c-=(XK_agrave-XK_Agrave);
3319 else
3320 if ((c >= XK_oslash) && (c <= XK_thorn))
3321 c-=(XK_oslash-XK_Ooblique);
3322 k=(int) (*keyword);
3323 if ((k >= XK_a) && (k <= XK_z))
3324 k-=(XK_a-XK_A);
3325 else
3326 if ((k >= XK_agrave) && (k <= XK_odiaeresis))
3327 k-=(XK_agrave-XK_Agrave);
3328 else
3329 if ((k >= XK_oslash) && (k <= XK_thorn))
3330 k-=(XK_oslash-XK_Ooblique);
cristyb51dff52011-05-19 16:55:47 +00003331 (void) FormatLocaleString(resource_class,MaxTextExtent,"%c%s.%c%s",c,
cristy3ed852e2009-09-05 21:47:34 +00003332 client_name+1,k,keyword+1);
3333 }
3334 status=XrmGetResource(database,resource_name,resource_class,&resource_type,
3335 &resource_value);
3336 if (status == False)
3337 return(resource_default);
3338 return(resource_value.addr);
3339}
3340
3341/*
3342%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3343% %
3344% %
3345% %
3346% X G e t R e s o u r c e D a t a b a s e %
3347% %
3348% %
3349% %
3350%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3351%
3352% XGetResourceDatabase() creates a new resource database and initializes it.
3353%
3354% The format of the XGetResourceDatabase method is:
3355%
3356% XrmDatabase XGetResourceDatabase(Display *display,
3357% const char *client_name)
3358%
3359% A description of each parameter follows:
3360%
3361% o database: XGetResourceDatabase() returns the database after it is
3362% initialized.
3363%
3364% o display: Specifies a connection to an X server; returned from
3365% XOpenDisplay.
3366%
3367% o client_name: Specifies the application name used to retrieve resource
3368% info from the X server database.
3369%
3370*/
3371MagickExport XrmDatabase XGetResourceDatabase(Display *display,
3372 const char *client_name)
3373{
3374 char
3375 filename[MaxTextExtent];
3376
3377 int
3378 c;
3379
3380 register const char
3381 *p;
3382
3383 XrmDatabase
3384 resource_database,
3385 server_database;
3386
3387 if (display == (Display *) NULL)
3388 return((XrmDatabase) NULL);
3389 assert(client_name != (char *) NULL);
3390 /*
3391 Initialize resource database.
3392 */
3393 XrmInitialize();
3394 (void) XGetDefault(display,(char *) client_name,"dummy");
3395 resource_database=XrmGetDatabase(display);
3396 /*
3397 Combine application database.
3398 */
3399 if (client_name != (char *) NULL)
3400 {
3401 /*
3402 Get basename of client.
3403 */
3404 p=client_name+(strlen(client_name)-1);
3405 while ((p > client_name) && (*p != '/'))
3406 p--;
3407 if (*p == '/')
3408 client_name=p+1;
3409 }
3410 c=(int) (*client_name);
3411 if ((c >= XK_a) && (c <= XK_z))
3412 c-=(XK_a-XK_A);
3413 else
3414 if ((c >= XK_agrave) && (c <= XK_odiaeresis))
3415 c-=(XK_agrave-XK_Agrave);
3416 else
3417 if ((c >= XK_oslash) && (c <= XK_thorn))
3418 c-=(XK_oslash-XK_Ooblique);
3419#if defined(X11_APPLICATION_PATH)
cristyb51dff52011-05-19 16:55:47 +00003420 (void) FormatLocaleString(filename,MaxTextExtent,"%s%c%s",
cristy3ed852e2009-09-05 21:47:34 +00003421 X11_APPLICATION_PATH,c,client_name+1);
3422 (void) XrmCombineFileDatabase(filename,&resource_database,MagickFalse);
3423#endif
3424 if (XResourceManagerString(display) != (char *) NULL)
3425 {
3426 /*
3427 Combine server database.
3428 */
3429 server_database=XrmGetStringDatabase(XResourceManagerString(display));
3430 XrmCombineDatabase(server_database,&resource_database,MagickFalse);
3431 }
3432 /*
3433 Merge user preferences database.
3434 */
3435#if defined(X11_PREFERENCES_PATH)
cristyb51dff52011-05-19 16:55:47 +00003436 (void) FormatLocaleString(filename,MaxTextExtent,"%s%src",
cristy3ed852e2009-09-05 21:47:34 +00003437 X11_PREFERENCES_PATH,client_name);
3438 ExpandFilename(filename);
3439 (void) XrmCombineFileDatabase(filename,&resource_database,MagickFalse);
3440#endif
3441 return(resource_database);
3442}
3443
3444/*
3445%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3446% %
3447% %
3448% %
3449% X G e t R e s o u r c e I n f o %
3450% %
3451% %
3452% %
3453%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3454%
3455% XGetResourceInfo(image_info,) initializes the ResourceInfo structure.
3456%
3457% The format of the XGetResourceInfo method is:
3458%
3459% void XGetResourceInfo(const ImageInfo *image_info,XrmDatabase database,
3460% const char *client_name,XResourceInfo *resource_info)
3461%
3462% A description of each parameter follows:
3463%
3464% o image_info: the image info.
3465%
3466% o database: Specifies a resource database; returned from
3467% XrmGetStringDatabase.
3468%
3469% o client_name: Specifies the application name used to retrieve
3470% resource info from the X server database.
3471%
3472% o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
3473%
3474*/
3475MagickExport void XGetResourceInfo(const ImageInfo *image_info,
3476 XrmDatabase database,const char *client_name,XResourceInfo *resource_info)
3477{
3478 char
cristy00976d82011-02-20 20:31:28 +00003479 *directory,
cristy3ed852e2009-09-05 21:47:34 +00003480 *resource_value;
3481
3482 /*
3483 Initialize resource info fields.
3484 */
3485 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
3486 assert(resource_info != (XResourceInfo *) NULL);
3487 (void) ResetMagickMemory(resource_info,0,sizeof(*resource_info));
3488 resource_info->resource_database=database;
3489 resource_info->image_info=(ImageInfo *) image_info;
3490 (void) SetImageInfoProgressMonitor(resource_info->image_info,
3491 XMagickProgressMonitor,(void *) NULL);
3492 resource_info->quantize_info=CloneQuantizeInfo((QuantizeInfo *) NULL);
3493 resource_info->close_server=MagickTrue;
3494 resource_info->client_name=AcquireString(client_name);
3495 resource_value=XGetResourceClass(database,client_name,"backdrop",
3496 (char *) "False");
3497 resource_info->backdrop=IsMagickTrue(resource_value);
3498 resource_info->background_color=XGetResourceInstance(database,client_name,
3499 "background",(char *) "#d6d6d6d6d6d6");
3500 resource_info->border_color=XGetResourceInstance(database,client_name,
3501 "borderColor",BorderColor);
3502 resource_value=XGetResourceClass(database,client_name,"borderWidth",
3503 (char *) "2");
cristy00976d82011-02-20 20:31:28 +00003504 resource_info->border_width=(unsigned int) StringToUnsignedLong(
3505 resource_value);
cristy3ed852e2009-09-05 21:47:34 +00003506 resource_value=XGetResourceClass(database,client_name,"colormap",
3507 (char *) "shared");
3508 resource_info->colormap=UndefinedColormap;
3509 if (LocaleCompare("private",resource_value) == 0)
3510 resource_info->colormap=PrivateColormap;
3511 if (LocaleCompare("shared",resource_value) == 0)
3512 resource_info->colormap=SharedColormap;
3513 if (resource_info->colormap == UndefinedColormap)
3514 ThrowXWindowFatalException(OptionError,"UnrecognizedColormapType",
3515 resource_value);
3516 resource_value=XGetResourceClass(database,client_name,
3517 "colorRecovery",(char *) "False");
3518 resource_info->color_recovery=IsMagickTrue(resource_value);
3519 resource_value=XGetResourceClass(database,client_name,"confirmExit",
3520 (char *) "False");
3521 resource_info->confirm_exit=IsMagickTrue(resource_value);
3522 resource_value=XGetResourceClass(database,client_name,"confirmEdit",
3523 (char *) "False");
3524 resource_info->confirm_edit=IsMagickTrue(resource_value);
cristyba0c3252010-06-27 13:31:44 +00003525 resource_value=XGetResourceClass(database,client_name,"delay",(char *) "1");
cristye27293e2009-12-18 02:53:20 +00003526 resource_info->delay=(unsigned int) StringToUnsignedLong(resource_value);
cristy3ed852e2009-09-05 21:47:34 +00003527 resource_info->display_gamma=XGetResourceClass(database,client_name,
3528 "displayGamma",(char *) "2.2");
3529 resource_value=XGetResourceClass(database,client_name,"displayWarnings",
3530 (char *) "True");
3531 resource_info->display_warnings=IsMagickTrue(resource_value);
3532 resource_info->font=XGetResourceClass(database,client_name,"font",
3533 (char *) NULL);
3534 resource_info->font=XGetResourceClass(database,client_name,"fontList",
3535 resource_info->font);
3536 resource_info->font_name[0]=XGetResourceClass(database,client_name,"font1",
3537 (char *) "fixed");
3538 resource_info->font_name[1]=XGetResourceClass(database,client_name,"font2",
3539 (char *) "variable");
3540 resource_info->font_name[2]=XGetResourceClass(database,client_name,"font3",
3541 (char *) "5x8");
3542 resource_info->font_name[3]=XGetResourceClass(database,client_name,"font4",
3543 (char *) "6x10");
3544 resource_info->font_name[4]=XGetResourceClass(database,client_name,"font5",
3545 (char *) "7x13bold");
3546 resource_info->font_name[5]=XGetResourceClass(database,client_name,"font6",
3547 (char *) "8x13bold");
3548 resource_info->font_name[6]=XGetResourceClass(database,client_name,"font7",
3549 (char *) "9x15bold");
3550 resource_info->font_name[7]=XGetResourceClass(database,client_name,"font8",
3551 (char *) "10x20");
3552 resource_info->font_name[8]=XGetResourceClass(database,client_name,"font9",
3553 (char *) "12x24");
3554 resource_info->font_name[9]=XGetResourceClass(database,client_name,"font0",
3555 (char *) "fixed");
3556 resource_info->font_name[10]=XGetResourceClass(database,client_name,"font0",
3557 (char *) "fixed");
3558 resource_info->foreground_color=XGetResourceInstance(database,client_name,
3559 "foreground",ForegroundColor);
3560 resource_value=XGetResourceClass(database,client_name,"gammaCorrect",
3561 (char *) "True");
3562 resource_info->gamma_correct=IsMagickTrue(resource_value);
3563 resource_info->image_geometry=ConstantString(XGetResourceClass(database,
3564 client_name,"geometry",(char *) NULL));
3565 resource_value=XGetResourceClass(database,client_name,"gravity",
3566 (char *) "Center");
cristy042ee782011-04-22 18:48:30 +00003567 resource_info->gravity=(GravityType) ParseCommandOption(MagickGravityOptions,
cristy3ed852e2009-09-05 21:47:34 +00003568 MagickFalse,resource_value);
cristy00976d82011-02-20 20:31:28 +00003569 directory=getcwd(resource_info->home_directory,MaxTextExtent);
3570 (void) directory;
cristy3ed852e2009-09-05 21:47:34 +00003571 resource_info->icon_geometry=XGetResourceClass(database,client_name,
3572 "iconGeometry",(char *) NULL);
3573 resource_value=XGetResourceClass(database,client_name,"iconic",
3574 (char *) "False");
3575 resource_info->iconic=IsMagickTrue(resource_value);
3576 resource_value=XGetResourceClass(database,client_name,"immutable",
3577 LocaleCompare(client_name,"PerlMagick") == 0 ? (char *) "True" :
3578 (char *) "False");
3579 resource_info->immutable=IsMagickTrue(resource_value);
3580 resource_value=XGetResourceClass(database,client_name,"magnify",
3581 (char *) "3");
cristye27293e2009-12-18 02:53:20 +00003582 resource_info->magnify=(unsigned int) StringToUnsignedLong(resource_value);
cristy3ed852e2009-09-05 21:47:34 +00003583 resource_info->map_type=XGetResourceClass(database,client_name,"map",
3584 (char *) NULL);
3585 resource_info->matte_color=XGetResourceInstance(database,client_name,
3586 "mattecolor",(char *) NULL);
3587 resource_info->name=ConstantString(XGetResourceClass(database,client_name,
3588 "name",(char *) NULL));
3589 resource_info->pen_colors[0]=XGetResourceClass(database,client_name,"pen1",
3590 (char *) "black");
3591 resource_info->pen_colors[1]=XGetResourceClass(database,client_name,"pen2",
3592 (char *) "blue");
3593 resource_info->pen_colors[2]=XGetResourceClass(database,client_name,"pen3",
3594 (char *) "cyan");
3595 resource_info->pen_colors[3]=XGetResourceClass(database,client_name,"pen4",
3596 (char *) "green");
3597 resource_info->pen_colors[4]=XGetResourceClass(database,client_name,"pen5",
3598 (char *) "gray");
3599 resource_info->pen_colors[5]=XGetResourceClass(database,client_name,"pen6",
3600 (char *) "red");
3601 resource_info->pen_colors[6]=XGetResourceClass(database,client_name,"pen7",
3602 (char *) "magenta");
3603 resource_info->pen_colors[7]=XGetResourceClass(database,client_name,"pen8",
3604 (char *) "yellow");
3605 resource_info->pen_colors[8]=XGetResourceClass(database,client_name,"pen9",
3606 (char *) "white");
3607 resource_info->pen_colors[9]=XGetResourceClass(database,client_name,"pen0",
3608 (char *) "gray");
3609 resource_info->pen_colors[10]=XGetResourceClass(database,client_name,"pen0",
3610 (char *) "gray");
3611 resource_value=XGetResourceClass(database,client_name,"pause",(char *) "0");
cristye27293e2009-12-18 02:53:20 +00003612 resource_info->pause=(unsigned int) StringToUnsignedLong(resource_value);
cristy3ed852e2009-09-05 21:47:34 +00003613 resource_value=XGetResourceClass(database,client_name,"quantum",(char *) "1");
cristyf2f27272009-12-17 14:48:46 +00003614 resource_info->quantum=StringToLong(resource_value);
cristy3ed852e2009-09-05 21:47:34 +00003615 resource_info->text_font=XGetResourceClass(database,client_name,(char *)
3616 "font",(char *) "fixed");
3617 resource_info->text_font=XGetResourceClass(database,client_name,
3618 "textFontList",resource_info->text_font);
3619 resource_info->title=XGetResourceClass(database,client_name,"title",
3620 (char *) NULL);
3621 resource_value=XGetResourceClass(database,client_name,"undoCache",
3622 (char *) "16");
cristye27293e2009-12-18 02:53:20 +00003623 resource_info->undo_cache=(unsigned int) StringToUnsignedLong(resource_value);
cristy3ed852e2009-09-05 21:47:34 +00003624 resource_value=XGetResourceClass(database,client_name,"update",
3625 (char *) "False");
3626 resource_info->update=IsMagickTrue(resource_value);
3627 resource_value=XGetResourceClass(database,client_name,"usePixmap",
3628 (char *) "True");
3629 resource_info->use_pixmap=IsMagickTrue(resource_value);
3630 resource_value=XGetResourceClass(database,client_name,"sharedMemory",
3631 (char *) "True");
3632 resource_info->use_shared_memory=IsMagickTrue(resource_value);
3633 resource_info->visual_type=XGetResourceClass(database,client_name,"visual",
3634 (char *) NULL);
3635 resource_info->window_group=XGetResourceClass(database,client_name,
3636 "windowGroup",(char *) NULL);
3637 resource_info->window_id=XGetResourceClass(database,client_name,"window",
3638 (char *) NULL);
3639 resource_info->write_filename=XGetResourceClass(database,client_name,
3640 "writeFilename",(char *) NULL);
3641}
3642
3643/*
3644%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3645% %
3646% %
3647% %
3648% X G e t R e s o u r c e I n s t a n c e %
3649% %
3650% %
3651% %
3652%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3653%
3654% XGetResourceInstance() queries the X server for the specified resource name.
3655% If the resource name is not defined in the database, the supplied default
3656% value is returned.
3657%
3658% The format of the XGetResourceInstance method is:
3659%
3660% char *XGetResourceInstance(XrmDatabase database,const char *client_name,
3661% const char *keyword,const char *resource_default)
3662%
3663% A description of each parameter follows:
3664%
3665% o database: Specifies a resource database; returned from
3666% XrmGetStringDatabase.
3667%
3668% o client_name: Specifies the application name used to retrieve
3669% resource info from the X server database.
3670%
3671% o keyword: Specifies the keyword of the value being retrieved.
3672%
3673% o resource_default: Specifies the default value to return if the query
3674% fails to find the specified keyword/class.
3675%
3676*/
3677MagickExport char *XGetResourceInstance(XrmDatabase database,
3678 const char *client_name,const char *keyword,const char *resource_default)
3679{
3680 char
3681 *resource_type,
3682 resource_name[MaxTextExtent];
3683
3684 Status
3685 status;
3686
3687 XrmValue
3688 resource_value;
3689
3690 if (database == (XrmDatabase) NULL)
3691 return((char *) resource_default);
3692 *resource_name='\0';
3693 if (keyword != (char *) NULL)
cristyb51dff52011-05-19 16:55:47 +00003694 (void) FormatLocaleString(resource_name,MaxTextExtent,"%s.%s",client_name,
cristy3ed852e2009-09-05 21:47:34 +00003695 keyword);
3696 status=XrmGetResource(database,resource_name,"ImageMagick",&resource_type,
3697 &resource_value);
3698 if (status == False)
3699 return((char *) resource_default);
3700 return(resource_value.addr);
3701}
3702
3703/*
3704%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3705% %
3706% %
3707% %
3708% X G e t S c r e e n D e n s i t y %
3709% %
3710% %
3711% %
3712%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3713%
3714% XGetScreenDensity() returns the density of the X server screen in
3715% dots-per-inch.
3716%
3717% The format of the XGetScreenDensity method is:
3718%
3719% char *XGetScreenDensity(Display *display)
3720%
3721% A description of each parameter follows:
3722%
3723% o density: XGetScreenDensity() returns the density of the X screen in
3724% dots-per-inch.
3725%
3726% o display: Specifies a connection to an X server; returned from
3727% XOpenDisplay.
3728%
3729*/
3730MagickExport char *XGetScreenDensity(Display *display)
3731{
3732 char
3733 density[MaxTextExtent];
3734
3735 double
3736 x_density,
3737 y_density;
3738
3739 /*
3740 Set density as determined by screen size.
3741 */
3742 x_density=((((double) DisplayWidth(display,XDefaultScreen(display)))*25.4)/
3743 ((double) DisplayWidthMM(display,XDefaultScreen(display))));
3744 y_density=((((double) DisplayHeight(display,XDefaultScreen(display)))*25.4)/
3745 ((double) DisplayHeightMM(display,XDefaultScreen(display))));
cristyb51dff52011-05-19 16:55:47 +00003746 (void) FormatLocaleString(density,MaxTextExtent,"%gx%g",x_density,
cristy8cd5b312010-01-07 01:10:24 +00003747 y_density);
cristy3ed852e2009-09-05 21:47:34 +00003748 return(GetPageGeometry(density));
3749}
3750
3751/*
3752%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3753% %
3754% %
3755% %
3756+ X G e t S u b w i n d o w %
3757% %
3758% %
3759% %
3760%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3761%
3762% XGetSubwindow() returns the subwindow of a window chosen the user with the
3763% pointer and a button press.
3764%
3765% The format of the XGetSubwindow method is:
3766%
3767% Window XGetSubwindow(Display *display,Window window,int x,int y)
3768%
3769% A description of each parameter follows:
3770%
3771% o subwindow: XGetSubwindow() returns NULL if no subwindow is found
3772% otherwise the subwindow is returned.
3773%
3774% o display: Specifies a connection to an X server; returned from
3775% XOpenDisplay.
3776%
3777% o window: Specifies a pointer to a Window.
3778%
3779% o x: the x coordinate of the pointer relative to the origin of the
3780% window.
3781%
3782% o y: the y coordinate of the pointer relative to the origin of the
3783% window.
3784%
cristy3ed852e2009-09-05 21:47:34 +00003785*/
3786static Window XGetSubwindow(Display *display,Window window,int x,int y)
3787{
3788 int
3789 x_offset,
3790 y_offset;
3791
3792 Status
3793 status;
3794
3795 Window
3796 source_window,
3797 target_window;
3798
3799 assert(display != (Display *) NULL);
3800 source_window=XRootWindow(display,XDefaultScreen(display));
3801 if (window == (Window) NULL)
3802 return(source_window);
3803 target_window=window;
3804 for ( ; ; )
3805 {
3806 status=XTranslateCoordinates(display,source_window,window,x,y,
3807 &x_offset,&y_offset,&target_window);
3808 if (status != True)
3809 break;
3810 if (target_window == (Window) NULL)
3811 break;
3812 source_window=window;
3813 window=target_window;
3814 x=x_offset;
3815 y=y_offset;
3816 }
3817 if (target_window == (Window) NULL)
3818 target_window=window;
3819 return(target_window);
3820}
3821
3822/*
3823%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3824% %
3825% %
3826% %
3827% X G e t W i n d o w C o l o r %
3828% %
3829% %
3830% %
3831%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3832%
3833% XGetWindowColor() returns the color of a pixel interactively chosen from the
3834% X server.
3835%
3836% The format of the XGetWindowColor method is:
3837%
3838% MagickBooleanType XGetWindowColor(Display *display,XWindows *windows,
3839% char *name)
3840%
3841% A description of each parameter follows:
3842%
3843% o display: Specifies a connection to an X server; returned from
3844% XOpenDisplay.
3845%
3846% o windows: Specifies a pointer to a XWindows structure.
3847%
3848% o name: the name of the color if found in the X Color Database is
3849% returned in this character string.
3850%
3851*/
cristybcbda3f2011-09-03 13:01:22 +00003852MagickPrivate MagickBooleanType XGetWindowColor(Display *display,
cristy3ed852e2009-09-05 21:47:34 +00003853 XWindows *windows,char *name)
3854{
3855 int
3856 x,
3857 y;
3858
3859 PixelPacket
3860 pixel;
3861
3862 RectangleInfo
3863 crop_info;
3864
3865 Status
3866 status;
3867
3868 Window
3869 child,
3870 client_window,
3871 root_window,
3872 target_window;
3873
3874 XColor
3875 color;
3876
3877 XImage
3878 *ximage;
3879
3880 XWindowAttributes
3881 window_attributes;
3882
3883 /*
3884 Choose a pixel from the X server.
3885 */
3886 assert(display != (Display *) NULL);
3887 assert(name != (char *) NULL);
3888 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",name);
3889 *name='\0';
3890 target_window=XSelectWindow(display,&crop_info);
3891 if (target_window == (Window) NULL)
3892 return(MagickFalse);
3893 root_window=XRootWindow(display,XDefaultScreen(display));
3894 client_window=target_window;
3895 if (target_window != root_window)
3896 {
3897 unsigned int
3898 d;
3899
3900 /*
3901 Get client window.
3902 */
3903 status=XGetGeometry(display,target_window,&root_window,&x,&x,&d,&d,&d,&d);
3904 if (status != False)
3905 {
3906 client_window=XClientWindow(display,target_window);
3907 target_window=client_window;
3908 }
3909 }
3910 /*
3911 Verify window is viewable.
3912 */
3913 status=XGetWindowAttributes(display,target_window,&window_attributes);
3914 if ((status == False) || (window_attributes.map_state != IsViewable))
3915 return(MagickFalse);
3916 /*
3917 Get window X image.
3918 */
3919 (void) XTranslateCoordinates(display,root_window,target_window,
3920 (int) crop_info.x,(int) crop_info.y,&x,&y,&child);
3921 ximage=XGetImage(display,target_window,x,y,1,1,AllPlanes,ZPixmap);
3922 if (ximage == (XImage *) NULL)
3923 return(MagickFalse);
3924 color.pixel=XGetPixel(ximage,0,0);
3925 XDestroyImage(ximage);
3926 /*
3927 Match color against the color database.
3928 */
3929 (void) XQueryColor(display,window_attributes.colormap,&color);
3930 pixel.red=ScaleShortToQuantum(color.red);
3931 pixel.green=ScaleShortToQuantum(color.green);
3932 pixel.blue=ScaleShortToQuantum(color.blue);
cristy4c08aed2011-07-01 19:47:50 +00003933 pixel.alpha=OpaqueAlpha;
cristy3ed852e2009-09-05 21:47:34 +00003934 (void) QueryColorname(windows->image.image,&pixel,X11Compliance,name,
3935 &windows->image.image->exception);
3936 return(MagickTrue);
3937}
3938
3939/*
3940%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3941% %
3942% %
3943% %
3944+ X G e t W i n d o w I m a g e %
3945% %
3946% %
3947% %
3948%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3949%
3950% XGetWindowImage() reads an image from the target X window and returns it.
3951% XGetWindowImage() optionally descends the window hierarchy and overlays the
3952% target image with each child image in an optimized fashion. Any child
3953% window that have the same visual, colormap, and are contained by its parent
3954% are exempted.
3955%
3956% The format of the XGetWindowImage method is:
3957%
3958% Image *XGetWindowImage(Display *display,const Window window,
3959% const unsigned int borders,const unsigned int level)
3960%
3961% A description of each parameter follows:
3962%
3963% o display: Specifies a connection to an X server; returned from
3964% XOpenDisplay.
3965%
3966% o window: Specifies the window to obtain the image from.
3967%
3968% o borders: Specifies whether borders pixels are to be saved with
3969% the image.
3970%
3971% o level: Specifies an unsigned integer representing the level of
3972% decent in the window hierarchy. This value must be zero or one on
3973% the initial call to XGetWindowImage. A value of zero returns after
3974% one call. A value of one causes the function to descend the window
3975% hierarchy and overlay the target image with each subwindow image.
3976%
cristy3ed852e2009-09-05 21:47:34 +00003977*/
3978static Image *XGetWindowImage(Display *display,const Window window,
3979 const unsigned int borders,const unsigned int level)
3980{
3981 typedef struct _ColormapInfo
3982 {
3983 Colormap
3984 colormap;
3985
3986 XColor
3987 *colors;
3988
3989 struct _ColormapInfo
3990 *next;
3991 } ColormapInfo;
3992
3993 typedef struct _WindowInfo
3994 {
3995 Window
3996 window,
3997 parent;
3998
3999 Visual
4000 *visual;
4001
4002 Colormap
4003 colormap;
4004
4005 XSegment
4006 bounds;
4007
4008 RectangleInfo
4009 crop_info;
4010 } WindowInfo;
4011
cristy3ed852e2009-09-05 21:47:34 +00004012 int
4013 display_height,
4014 display_width,
4015 id,
4016 x_offset,
4017 y_offset;
4018
cristy4c08aed2011-07-01 19:47:50 +00004019 Quantum
4020 index;
4021
cristy3ed852e2009-09-05 21:47:34 +00004022 RectangleInfo
4023 crop_info;
4024
cristy3ed852e2009-09-05 21:47:34 +00004025 register int
4026 i;
4027
4028 static ColormapInfo
4029 *colormap_info = (ColormapInfo *) NULL;
4030
4031 static int
4032 max_windows = 0,
4033 number_windows = 0;
4034
4035 static WindowInfo
4036 *window_info;
4037
4038 Status
4039 status;
4040
4041 Window
4042 child,
4043 root_window;
4044
4045 XWindowAttributes
4046 window_attributes;
4047
4048 /*
4049 Verify window is viewable.
4050 */
4051 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
4052 assert(display != (Display *) NULL);
4053 status=XGetWindowAttributes(display,window,&window_attributes);
4054 if ((status == False) || (window_attributes.map_state != IsViewable))
4055 return((Image *) NULL);
4056 /*
4057 Cropping rectangle is relative to root window.
4058 */
4059 root_window=XRootWindow(display,XDefaultScreen(display));
4060 (void) XTranslateCoordinates(display,window,root_window,0,0,&x_offset,
4061 &y_offset,&child);
cristybb503372010-05-27 20:51:26 +00004062 crop_info.x=(ssize_t) x_offset;
4063 crop_info.y=(ssize_t) y_offset;
4064 crop_info.width=(size_t) window_attributes.width;
4065 crop_info.height=(size_t) window_attributes.height;
cristy3ed852e2009-09-05 21:47:34 +00004066 if (borders != MagickFalse)
4067 {
4068 /*
4069 Include border in image.
4070 */
cristybb503372010-05-27 20:51:26 +00004071 crop_info.x-=(ssize_t) window_attributes.border_width;
4072 crop_info.y-=(ssize_t) window_attributes.border_width;
4073 crop_info.width+=(size_t) (window_attributes.border_width << 1);
4074 crop_info.height+=(size_t) (window_attributes.border_width << 1);
cristy3ed852e2009-09-05 21:47:34 +00004075 }
4076 /*
4077 Crop to root window.
4078 */
4079 if (crop_info.x < 0)
4080 {
4081 crop_info.width+=crop_info.x;
4082 crop_info.x=0;
4083 }
4084 if (crop_info.y < 0)
4085 {
4086 crop_info.height+=crop_info.y;
4087 crop_info.y=0;
4088 }
4089 display_width=XDisplayWidth(display,XDefaultScreen(display));
4090 if ((int) (crop_info.x+crop_info.width) > display_width)
cristybb503372010-05-27 20:51:26 +00004091 crop_info.width=(size_t) (display_width-crop_info.x);
cristy3ed852e2009-09-05 21:47:34 +00004092 display_height=XDisplayHeight(display,XDefaultScreen(display));
4093 if ((int) (crop_info.y+crop_info.height) > display_height)
cristybb503372010-05-27 20:51:26 +00004094 crop_info.height=(size_t) (display_height-crop_info.y);
cristy3ed852e2009-09-05 21:47:34 +00004095 /*
4096 Initialize window info attributes.
4097 */
4098 if (number_windows >= max_windows)
4099 {
4100 /*
4101 Allocate or resize window info buffer.
4102 */
4103 max_windows+=1024;
4104 if (window_info == (WindowInfo *) NULL)
4105 window_info=(WindowInfo *) AcquireQuantumMemory((size_t) max_windows,
4106 sizeof(*window_info));
4107 else
4108 window_info=(WindowInfo *) ResizeQuantumMemory(window_info,(size_t)
4109 max_windows,sizeof(*window_info));
4110 }
4111 if (window_info == (WindowInfo *) NULL)
4112 {
4113 ThrowXWindowFatalException(ResourceLimitError,
4114 "MemoryAllocationFailed","...");
4115 return((Image *) NULL);
4116 }
4117 id=number_windows++;
4118 window_info[id].window=window;
4119 window_info[id].visual=window_attributes.visual;
4120 window_info[id].colormap=window_attributes.colormap;
4121 window_info[id].bounds.x1=(short) crop_info.x;
4122 window_info[id].bounds.y1=(short) crop_info.y;
4123 window_info[id].bounds.x2=(short) (crop_info.x+(int) crop_info.width-1);
4124 window_info[id].bounds.y2=(short) (crop_info.y+(int) crop_info.height-1);
4125 crop_info.x-=x_offset;
4126 crop_info.y-=y_offset;
4127 window_info[id].crop_info=crop_info;
4128 if (level != 0)
4129 {
4130 unsigned int
4131 number_children;
4132
4133 Window
4134 *children;
4135
4136 /*
4137 Descend the window hierarchy.
4138 */
4139 status=XQueryTree(display,window,&root_window,&window_info[id].parent,
4140 &children,&number_children);
4141 for (i=0; i < id; i++)
4142 if ((window_info[i].window == window_info[id].parent) &&
4143 (window_info[i].visual == window_info[id].visual) &&
4144 (window_info[i].colormap == window_info[id].colormap))
4145 {
4146 if ((window_info[id].bounds.x1 <= window_info[i].bounds.x1) ||
4147 (window_info[id].bounds.x1 >= window_info[i].bounds.x2) ||
4148 (window_info[id].bounds.y1 <= window_info[i].bounds.y1) ||
4149 (window_info[id].bounds.y1 >= window_info[i].bounds.y2))
4150 {
4151 /*
4152 Eliminate windows not circumscribed by their parent.
4153 */
4154 number_windows--;
4155 break;
4156 }
4157 }
4158 if ((status == True) && (number_children != 0))
4159 {
4160 for (i=0; i < (int) number_children; i++)
4161 (void) XGetWindowImage(display,children[i],MagickFalse,level+1);
4162 (void) XFree((void *) children);
4163 }
4164 }
4165 if (level <= 1)
4166 {
cristyc57f6942010-11-12 01:47:39 +00004167 CacheView
4168 *composite_view;
4169
cristy3ed852e2009-09-05 21:47:34 +00004170 ColormapInfo
4171 *next;
4172
4173 ExceptionInfo
4174 *exception;
4175
4176 Image
4177 *composite_image,
4178 *image;
4179
4180 int
4181 y;
4182
4183 MagickBooleanType
4184 import;
4185
4186 register int
4187 j,
4188 x;
4189
cristy4c08aed2011-07-01 19:47:50 +00004190 register Quantum
cristyc47d1f82009-11-26 01:44:43 +00004191 *restrict q;
cristy3ed852e2009-09-05 21:47:34 +00004192
cristybb503372010-05-27 20:51:26 +00004193 register size_t
cristy3ed852e2009-09-05 21:47:34 +00004194 pixel;
4195
4196 unsigned int
4197 number_colors;
4198
4199 XColor
4200 *colors;
4201
4202 XImage
4203 *ximage;
4204
4205 /*
4206 Get X image for each window in the list.
4207 */
4208 image=NewImageList();
4209 for (id=0; id < number_windows; id++)
4210 {
4211 /*
4212 Does target window intersect top level window?
4213 */
4214 import=
4215 ((window_info[id].bounds.x2 >= window_info[0].bounds.x1) &&
4216 (window_info[id].bounds.x1 <= window_info[0].bounds.x2) &&
4217 (window_info[id].bounds.y2 >= window_info[0].bounds.y1) &&
4218 (window_info[id].bounds.y1 <= window_info[0].bounds.y2)) ?
4219 MagickTrue : MagickFalse;
4220 /*
4221 Is target window contained by another window with the same colormap?
4222 */
4223 for (j=0; j < id; j++)
4224 if ((window_info[id].visual == window_info[j].visual) &&
4225 (window_info[id].colormap == window_info[j].colormap))
4226 {
4227 if ((window_info[id].bounds.x1 <= window_info[j].bounds.x1) ||
4228 (window_info[id].bounds.x1 >= window_info[j].bounds.x2) ||
4229 (window_info[id].bounds.y1 <= window_info[j].bounds.y1) ||
4230 (window_info[id].bounds.y1 >= window_info[j].bounds.y2))
4231 import=MagickFalse;
4232 }
4233 else
4234 if ((window_info[id].visual != window_info[j].visual) ||
4235 (window_info[id].colormap != window_info[j].colormap))
4236 {
4237 if ((window_info[id].bounds.x2 > window_info[j].bounds.x1) &&
4238 (window_info[id].bounds.x1 < window_info[j].bounds.x2) &&
4239 (window_info[id].bounds.y2 > window_info[j].bounds.y1) &&
4240 (window_info[id].bounds.y1 < window_info[j].bounds.y2))
4241 import=MagickTrue;
4242 }
4243 if (import == MagickFalse)
4244 continue;
4245 /*
4246 Get X image.
4247 */
4248 ximage=XGetImage(display,window_info[id].window,(int)
4249 window_info[id].crop_info.x,(int) window_info[id].crop_info.y,
4250 (unsigned int) window_info[id].crop_info.width,(unsigned int)
4251 window_info[id].crop_info.height,AllPlanes,ZPixmap);
4252 if (ximage == (XImage *) NULL)
4253 continue;
4254 /*
4255 Initialize window colormap.
4256 */
4257 number_colors=0;
4258 colors=(XColor *) NULL;
4259 if (window_info[id].colormap != (Colormap) NULL)
4260 {
4261 ColormapInfo
4262 *p;
4263
4264 /*
4265 Search colormap list for window colormap.
4266 */
4267 number_colors=(unsigned int) window_info[id].visual->map_entries;
4268 for (p=colormap_info; p != (ColormapInfo *) NULL; p=p->next)
4269 if (p->colormap == window_info[id].colormap)
4270 break;
4271 if (p == (ColormapInfo *) NULL)
4272 {
4273 /*
4274 Get the window colormap.
4275 */
4276 colors=(XColor *) AcquireQuantumMemory(number_colors,
4277 sizeof(*colors));
4278 if (colors == (XColor *) NULL)
4279 {
4280 XDestroyImage(ximage);
4281 return((Image *) NULL);
4282 }
4283 if ((window_info[id].visual->klass != DirectColor) &&
4284 (window_info[id].visual->klass != TrueColor))
4285 for (i=0; i < (int) number_colors; i++)
4286 {
cristybb503372010-05-27 20:51:26 +00004287 colors[i].pixel=(size_t) i;
cristy3ed852e2009-09-05 21:47:34 +00004288 colors[i].pad='\0';
4289 }
4290 else
4291 {
cristybb503372010-05-27 20:51:26 +00004292 size_t
cristy3ed852e2009-09-05 21:47:34 +00004293 blue,
4294 blue_bit,
4295 green,
4296 green_bit,
4297 red,
4298 red_bit;
4299
4300 /*
4301 DirectColor or TrueColor visual.
4302 */
4303 red=0;
4304 green=0;
4305 blue=0;
4306 red_bit=window_info[id].visual->red_mask &
4307 (~(window_info[id].visual->red_mask)+1);
4308 green_bit=window_info[id].visual->green_mask &
4309 (~(window_info[id].visual->green_mask)+1);
4310 blue_bit=window_info[id].visual->blue_mask &
4311 (~(window_info[id].visual->blue_mask)+1);
4312 for (i=0; i < (int) number_colors; i++)
4313 {
cristy8891f9c2010-06-04 23:32:17 +00004314 colors[i].pixel=(unsigned long) (red | green | blue);
cristy3ed852e2009-09-05 21:47:34 +00004315 colors[i].pad='\0';
4316 red+=red_bit;
4317 if (red > window_info[id].visual->red_mask)
4318 red=0;
4319 green+=green_bit;
4320 if (green > window_info[id].visual->green_mask)
4321 green=0;
4322 blue+=blue_bit;
4323 if (blue > window_info[id].visual->blue_mask)
4324 blue=0;
4325 }
4326 }
4327 (void) XQueryColors(display,window_info[id].colormap,colors,
4328 (int) number_colors);
4329 /*
4330 Append colormap to colormap list.
4331 */
cristy73bd4a52010-10-05 11:24:23 +00004332 p=(ColormapInfo *) AcquireMagickMemory(sizeof(*p));
cristy3ed852e2009-09-05 21:47:34 +00004333 if (p == (ColormapInfo *) NULL)
4334 return((Image *) NULL);
4335 p->colormap=window_info[id].colormap;
4336 p->colors=colors;
4337 p->next=colormap_info;
4338 colormap_info=p;
4339 }
4340 colors=p->colors;
4341 }
4342 /*
4343 Allocate image structure.
4344 */
cristy9950d572011-10-01 18:22:35 +00004345 composite_image=AcquireImage((ImageInfo *) NULL,&image->exception);
cristy3ed852e2009-09-05 21:47:34 +00004346 if (composite_image == (Image *) NULL)
4347 {
4348 XDestroyImage(ximage);
4349 return((Image *) NULL);
4350 }
4351 /*
4352 Convert X image to MIFF format.
4353 */
4354 if ((window_info[id].visual->klass != TrueColor) &&
4355 (window_info[id].visual->klass != DirectColor))
4356 composite_image->storage_class=PseudoClass;
cristybb503372010-05-27 20:51:26 +00004357 composite_image->columns=(size_t) ximage->width;
4358 composite_image->rows=(size_t) ximage->height;
cristy3ed852e2009-09-05 21:47:34 +00004359 exception=(&composite_image->exception);
cristyc57f6942010-11-12 01:47:39 +00004360 composite_view=AcquireCacheView(composite_image);
cristy3ed852e2009-09-05 21:47:34 +00004361 switch (composite_image->storage_class)
4362 {
4363 case DirectClass:
4364 default:
4365 {
cristybb503372010-05-27 20:51:26 +00004366 register size_t
cristy3ed852e2009-09-05 21:47:34 +00004367 color,
4368 index;
4369
cristybb503372010-05-27 20:51:26 +00004370 size_t
cristy3ed852e2009-09-05 21:47:34 +00004371 blue_mask,
4372 blue_shift,
4373 green_mask,
4374 green_shift,
4375 red_mask,
4376 red_shift;
4377
4378 /*
4379 Determine shift and mask for red, green, and blue.
4380 */
4381 red_mask=window_info[id].visual->red_mask;
4382 red_shift=0;
4383 while ((red_mask != 0) && ((red_mask & 0x01) == 0))
4384 {
4385 red_mask>>=1;
4386 red_shift++;
4387 }
4388 green_mask=window_info[id].visual->green_mask;
4389 green_shift=0;
4390 while ((green_mask != 0) && ((green_mask & 0x01) == 0))
4391 {
4392 green_mask>>=1;
4393 green_shift++;
4394 }
4395 blue_mask=window_info[id].visual->blue_mask;
4396 blue_shift=0;
4397 while ((blue_mask != 0) && ((blue_mask & 0x01) == 0))
4398 {
4399 blue_mask>>=1;
4400 blue_shift++;
4401 }
4402 /*
4403 Convert X image to DirectClass packets.
4404 */
4405 if ((number_colors != 0) &&
4406 (window_info[id].visual->klass == DirectColor))
4407 for (y=0; y < (int) composite_image->rows; y++)
4408 {
cristyc57f6942010-11-12 01:47:39 +00004409 q=QueueCacheViewAuthenticPixels(composite_view,0,(ssize_t) y,
cristy3ed852e2009-09-05 21:47:34 +00004410 composite_image->columns,1,exception);
cristyacd2ed22011-08-30 01:44:23 +00004411 if (q == (Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00004412 break;
4413 for (x=0; x < (int) composite_image->columns; x++)
4414 {
4415 pixel=XGetPixel(ximage,x,y);
4416 index=(pixel >> red_shift) & red_mask;
cristy4c08aed2011-07-01 19:47:50 +00004417 SetPixelRed(composite_image,
4418 ScaleShortToQuantum(colors[index].red),q);
cristy3ed852e2009-09-05 21:47:34 +00004419 index=(pixel >> green_shift) & green_mask;
cristy4c08aed2011-07-01 19:47:50 +00004420 SetPixelGreen(composite_image,
4421 ScaleShortToQuantum(colors[index].green),q);
cristy3ed852e2009-09-05 21:47:34 +00004422 index=(pixel >> blue_shift) & blue_mask;
cristy4c08aed2011-07-01 19:47:50 +00004423 SetPixelBlue(composite_image,
4424 ScaleShortToQuantum(colors[index].blue),q);
cristyed231572011-07-14 02:18:59 +00004425 q+=GetPixelChannels(composite_image);
cristy3ed852e2009-09-05 21:47:34 +00004426 }
cristyc57f6942010-11-12 01:47:39 +00004427 if (SyncCacheViewAuthenticPixels(composite_view,exception) == MagickFalse)
cristy3ed852e2009-09-05 21:47:34 +00004428 break;
4429 }
4430 else
4431 for (y=0; y < (int) composite_image->rows; y++)
4432 {
cristyc57f6942010-11-12 01:47:39 +00004433 q=QueueCacheViewAuthenticPixels(composite_view,0,(ssize_t) y,
cristy3ed852e2009-09-05 21:47:34 +00004434 composite_image->columns,1,exception);
cristyacd2ed22011-08-30 01:44:23 +00004435 if (q == (Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00004436 break;
4437 for (x=0; x < (int) composite_image->columns; x++)
4438 {
4439 pixel=XGetPixel(ximage,x,y);
4440 color=(pixel >> red_shift) & red_mask;
4441 color=(65535UL*color)/red_mask;
cristy4c08aed2011-07-01 19:47:50 +00004442 SetPixelRed(composite_image,
4443 ScaleShortToQuantum((unsigned short) color),q);
cristy3ed852e2009-09-05 21:47:34 +00004444 color=(pixel >> green_shift) & green_mask;
4445 color=(65535UL*color)/green_mask;
cristy4c08aed2011-07-01 19:47:50 +00004446 SetPixelGreen(composite_image,
4447 ScaleShortToQuantum((unsigned short) color),q);
cristy3ed852e2009-09-05 21:47:34 +00004448 color=(pixel >> blue_shift) & blue_mask;
4449 color=(65535UL*color)/blue_mask;
cristy4c08aed2011-07-01 19:47:50 +00004450 SetPixelBlue(composite_image,
4451 ScaleShortToQuantum((unsigned short) color),q);
cristyed231572011-07-14 02:18:59 +00004452 q+=GetPixelChannels(composite_image);
cristy3ed852e2009-09-05 21:47:34 +00004453 }
cristyc57f6942010-11-12 01:47:39 +00004454 if (SyncCacheViewAuthenticPixels(composite_view,exception) == MagickFalse)
cristy3ed852e2009-09-05 21:47:34 +00004455 break;
4456 }
4457 break;
4458 }
4459 case PseudoClass:
4460 {
4461 /*
4462 Create colormap.
4463 */
cristy018f07f2011-09-04 21:15:19 +00004464 if (AcquireImageColormap(composite_image,number_colors,exception) == MagickFalse)
cristy3ed852e2009-09-05 21:47:34 +00004465 {
4466 XDestroyImage(ximage);
4467 composite_image=DestroyImage(composite_image);
4468 return((Image *) NULL);
4469 }
4470 for (i=0; i < (int) composite_image->colors; i++)
4471 {
4472 composite_image->colormap[colors[i].pixel].red=
4473 ScaleShortToQuantum(colors[i].red);
4474 composite_image->colormap[colors[i].pixel].green=
4475 ScaleShortToQuantum(colors[i].green);
4476 composite_image->colormap[colors[i].pixel].blue=
4477 ScaleShortToQuantum(colors[i].blue);
4478 }
4479 /*
4480 Convert X image to PseudoClass packets.
4481 */
4482 for (y=0; y < (int) composite_image->rows; y++)
4483 {
cristyc57f6942010-11-12 01:47:39 +00004484 q=QueueCacheViewAuthenticPixels(composite_view,0,(ssize_t) y,
4485 composite_image->columns,1,exception);
cristyacd2ed22011-08-30 01:44:23 +00004486 if (q == (Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00004487 break;
cristy3ed852e2009-09-05 21:47:34 +00004488 for (x=0; x < (int) composite_image->columns; x++)
4489 {
cristy4c08aed2011-07-01 19:47:50 +00004490 index=(Quantum) XGetPixel(ximage,x,y);
4491 SetPixelIndex(composite_image,index,q);
4492 SetPixelPacket(composite_image,
4493 composite_image->colormap+(ssize_t) index,q);
cristyed231572011-07-14 02:18:59 +00004494 q+=GetPixelChannels(composite_image);
cristy3ed852e2009-09-05 21:47:34 +00004495 }
cristyc57f6942010-11-12 01:47:39 +00004496 if (SyncCacheViewAuthenticPixels(composite_view,exception) == MagickFalse)
cristy3ed852e2009-09-05 21:47:34 +00004497 break;
4498 }
4499 break;
4500 }
4501 }
cristyc57f6942010-11-12 01:47:39 +00004502 composite_view=DestroyCacheView(composite_view);
cristy3ed852e2009-09-05 21:47:34 +00004503 XDestroyImage(ximage);
4504 if (image == (Image *) NULL)
4505 {
4506 image=composite_image;
4507 continue;
4508 }
4509 /*
4510 Composite any children in back-to-front order.
4511 */
4512 (void) XTranslateCoordinates(display,window_info[id].window,window,0,0,
4513 &x_offset,&y_offset,&child);
4514 x_offset-=(int) crop_info.x;
4515 if (x_offset < 0)
4516 x_offset=0;
4517 y_offset-=(int) crop_info.y;
4518 if (y_offset < 0)
4519 y_offset=0;
cristyc57f6942010-11-12 01:47:39 +00004520 (void) CompositeImage(image,CopyCompositeOp,composite_image,(ssize_t)
4521 x_offset,(ssize_t) y_offset);
cristy3ed852e2009-09-05 21:47:34 +00004522 }
4523 /*
4524 Relinquish resources.
4525 */
4526 while (colormap_info != (ColormapInfo *) NULL)
4527 {
4528 next=colormap_info->next;
4529 colormap_info->colors=(XColor *)
4530 RelinquishMagickMemory(colormap_info->colors);
4531 colormap_info=(ColormapInfo *) RelinquishMagickMemory(colormap_info);
4532 colormap_info=next;
4533 }
4534 /*
4535 Relinquish resources and restore initial state.
4536 */
4537 window_info=(WindowInfo *) RelinquishMagickMemory(window_info);
4538 max_windows=0;
4539 number_windows=0;
4540 colormap_info=(ColormapInfo *) NULL;
4541 return(image);
4542 }
4543 return((Image *) NULL);
4544}
4545
4546/*
4547%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4548% %
4549% %
4550% %
4551% X G e t W i n d o w I n f o %
4552% %
4553% %
4554% %
4555%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4556%
4557% XGetWindowInfo() initializes the XWindowInfo structure.
4558%
4559% The format of the XGetWindowInfo method is:
4560%
4561% void XGetWindowInfo(Display *display,XVisualInfo *visual_info,
4562% XStandardColormap *map_info,XPixelInfo *pixel,XFontStruct *font_info,
4563% XResourceInfo *resource_info,XWindowInfo *window)
4564% resource_info,window)
4565%
4566% A description of each parameter follows:
4567%
4568% o display: Specifies a connection to an X server; returned from
4569% XOpenDisplay.
4570%
4571% o visual_info: Specifies a pointer to a X11 XVisualInfo structure;
4572% returned from XGetVisualInfo.
4573%
4574% o map_info: If map_type is specified, this structure is initialized
4575% with info from the Standard Colormap.
4576%
4577% o pixel: Specifies a pointer to a XPixelInfo structure.
4578%
4579% o font_info: Specifies a pointer to a XFontStruct structure.
4580%
4581% o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
4582%
4583*/
cristybcbda3f2011-09-03 13:01:22 +00004584MagickPrivate void XGetWindowInfo(Display *display,XVisualInfo *visual_info,
cristy3ed852e2009-09-05 21:47:34 +00004585 XStandardColormap *map_info,XPixelInfo *pixel,XFontStruct *font_info,
4586 XResourceInfo *resource_info,XWindowInfo *window)
4587{
4588 /*
4589 Initialize window info.
4590 */
4591 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
4592 assert(display != (Display *) NULL);
4593 assert(visual_info != (XVisualInfo *) NULL);
4594 assert(map_info != (XStandardColormap *) NULL);
4595 assert(pixel != (XPixelInfo *) NULL);
4596 assert(resource_info != (XResourceInfo *) NULL);
4597 assert(window != (XWindowInfo *) NULL);
4598 if (window->id != (Window) NULL)
4599 {
4600 if (window->cursor != (Cursor) NULL)
4601 (void) XFreeCursor(display,window->cursor);
4602 if (window->busy_cursor != (Cursor) NULL)
4603 (void) XFreeCursor(display,window->busy_cursor);
4604 if (window->highlight_stipple != (Pixmap) NULL)
4605 (void) XFreePixmap(display,window->highlight_stipple);
4606 if (window->shadow_stipple != (Pixmap) NULL)
4607 (void) XFreePixmap(display,window->shadow_stipple);
4608 if (window->name == (char *) NULL)
4609 window->name=AcquireString("");
4610 if (window->icon_name == (char *) NULL)
4611 window->icon_name=AcquireString("");
4612 }
4613 else
4614 {
4615 /*
4616 Initialize these attributes just once.
4617 */
4618 window->id=(Window) NULL;
4619 if (window->name == (char *) NULL)
4620 window->name=AcquireString("");
4621 if (window->icon_name == (char *) NULL)
4622 window->icon_name=AcquireString("");
4623 window->x=XDisplayWidth(display,visual_info->screen) >> 1;
4624 window->y=XDisplayWidth(display,visual_info->screen) >> 1;
4625 window->ximage=(XImage *) NULL;
4626 window->matte_image=(XImage *) NULL;
4627 window->pixmap=(Pixmap) NULL;
4628 window->matte_pixmap=(Pixmap) NULL;
4629 window->mapped=MagickFalse;
4630 window->stasis=MagickFalse;
4631 window->shared_memory=MagickTrue;
4632 window->segment_info=(void *) NULL;
4633#if defined(MAGICKCORE_HAVE_SHARED_MEMORY)
4634 {
4635 XShmSegmentInfo
4636 *segment_info;
4637
4638 if (window->segment_info == (void *) NULL)
4639 window->segment_info=AcquireQuantumMemory(2,sizeof(*segment_info));
4640 segment_info=(XShmSegmentInfo *) window->segment_info;
4641 segment_info[0].shmid=(-1);
4642 segment_info[0].shmaddr=(char *) NULL;
4643 segment_info[1].shmid=(-1);
4644 segment_info[1].shmaddr=(char *) NULL;
4645 }
4646#endif
4647 }
4648 /*
4649 Initialize these attributes every time function is called.
4650 */
4651 window->screen=visual_info->screen;
4652 window->root=XRootWindow(display,visual_info->screen);
4653 window->visual=visual_info->visual;
4654 window->storage_class=(unsigned int) visual_info->klass;
4655 window->depth=(unsigned int) visual_info->depth;
4656 window->visual_info=visual_info;
4657 window->map_info=map_info;
4658 window->pixel_info=pixel;
4659 window->font_info=font_info;
4660 window->cursor=XCreateFontCursor(display,XC_left_ptr);
4661 window->busy_cursor=XCreateFontCursor(display,XC_watch);
4662 window->geometry=(char *) NULL;
4663 window->icon_geometry=(char *) NULL;
4664 if (resource_info->icon_geometry != (char *) NULL)
4665 (void) CloneString(&window->icon_geometry,resource_info->icon_geometry);
4666 window->crop_geometry=(char *) NULL;
cristybb503372010-05-27 20:51:26 +00004667 window->flags=(size_t) PSize;
cristy3ed852e2009-09-05 21:47:34 +00004668 window->width=1;
4669 window->height=1;
4670 window->min_width=1;
4671 window->min_height=1;
4672 window->width_inc=1;
4673 window->height_inc=1;
4674 window->border_width=resource_info->border_width;
4675 window->annotate_context=pixel->annotate_context;
4676 window->highlight_context=pixel->highlight_context;
4677 window->widget_context=pixel->widget_context;
4678 window->shadow_stipple=(Pixmap) NULL;
4679 window->highlight_stipple=(Pixmap) NULL;
4680 window->use_pixmap=MagickTrue;
4681 window->immutable=MagickFalse;
4682 window->shape=MagickFalse;
4683 window->data=0;
cristyc57f6942010-11-12 01:47:39 +00004684 window->mask=(int) (CWBackingStore | CWBackPixel | CWBackPixmap |
cristy3ed852e2009-09-05 21:47:34 +00004685 CWBitGravity | CWBorderPixel | CWColormap | CWCursor | CWDontPropagate |
4686 CWEventMask | CWOverrideRedirect | CWSaveUnder | CWWinGravity);
4687 window->attributes.background_pixel=pixel->background_color.pixel;
4688 window->attributes.background_pixmap=(Pixmap) NULL;
4689 window->attributes.bit_gravity=ForgetGravity;
4690 window->attributes.backing_store=WhenMapped;
4691 window->attributes.save_under=MagickTrue;
4692 window->attributes.border_pixel=pixel->border_color.pixel;
4693 window->attributes.colormap=map_info->colormap;
4694 window->attributes.cursor=window->cursor;
4695 window->attributes.do_not_propagate_mask=NoEventMask;
4696 window->attributes.event_mask=NoEventMask;
4697 window->attributes.override_redirect=MagickFalse;
4698 window->attributes.win_gravity=NorthWestGravity;
4699 window->orphan=MagickFalse;
4700}
4701
4702/*
4703%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4704% %
4705% %
4706% %
4707% X H i g h l i g h t E l l i p s e %
4708% %
4709% %
4710% %
4711%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4712%
4713% XHighlightEllipse() puts a border on the X server around a region defined by
4714% highlight_info.
4715%
4716% The format of the XHighlightEllipse method is:
4717%
4718% void XHighlightEllipse(Display *display,Window window,
4719% GC annotate_context,const RectangleInfo *highlight_info)
4720%
4721% A description of each parameter follows:
4722%
4723% o display: Specifies a connection to an X server; returned from
4724% XOpenDisplay.
4725%
4726% o window: Specifies a pointer to a Window structure.
4727%
4728% o annotate_context: Specifies a pointer to a GC structure.
4729%
4730% o highlight_info: Specifies a pointer to a RectangleInfo structure. It
4731% contains the extents of any highlighting rectangle.
4732%
4733*/
cristybcbda3f2011-09-03 13:01:22 +00004734MagickPrivate void XHighlightEllipse(Display *display,Window window,
cristy3ed852e2009-09-05 21:47:34 +00004735 GC annotate_context,const RectangleInfo *highlight_info)
4736{
4737 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
4738 assert(display != (Display *) NULL);
4739 assert(window != (Window) NULL);
4740 assert(annotate_context != (GC) NULL);
4741 assert(highlight_info != (RectangleInfo *) NULL);
4742 if ((highlight_info->width < 4) || (highlight_info->height < 4))
4743 return;
4744 (void) XDrawArc(display,window,annotate_context,(int) highlight_info->x,
4745 (int) highlight_info->y,(unsigned int) highlight_info->width-1,
4746 (unsigned int) highlight_info->height-1,0,360*64);
4747 (void) XDrawArc(display,window,annotate_context,(int) highlight_info->x+1,
4748 (int) highlight_info->y+1,(unsigned int) highlight_info->width-3,
4749 (unsigned int) highlight_info->height-3,0,360*64);
4750}
4751
4752/*
4753%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4754% %
4755% %
4756% %
4757% X H i g h l i g h t L i n e %
4758% %
4759% %
4760% %
4761%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4762%
4763% XHighlightLine() puts a border on the X server around a region defined by
4764% highlight_info.
4765%
4766% The format of the XHighlightLine method is:
4767%
4768% void XHighlightLine(Display *display,Window window,GC annotate_context,
4769% const XSegment *highlight_info)
4770%
4771% A description of each parameter follows:
4772%
4773% o display: Specifies a connection to an X server; returned from
4774% XOpenDisplay.
4775%
4776% o window: Specifies a pointer to a Window structure.
4777%
4778% o annotate_context: Specifies a pointer to a GC structure.
4779%
4780% o highlight_info: Specifies a pointer to a RectangleInfo structure. It
4781% contains the extents of any highlighting rectangle.
4782%
4783*/
cristybcbda3f2011-09-03 13:01:22 +00004784MagickPrivate void XHighlightLine(Display *display,Window window,
cristy3ed852e2009-09-05 21:47:34 +00004785 GC annotate_context,const XSegment *highlight_info)
4786{
4787 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
4788 assert(display != (Display *) NULL);
4789 assert(window != (Window) NULL);
4790 assert(annotate_context != (GC) NULL);
4791 assert(highlight_info != (XSegment *) NULL);
4792 (void) XDrawLine(display,window,annotate_context,highlight_info->x1,
4793 highlight_info->y1,highlight_info->x2,highlight_info->y2);
4794}
4795
4796/*
4797%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4798% %
4799% %
4800% %
4801% X H i g h l i g h t R e c t a n g l e %
4802% %
4803% %
4804% %
4805%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4806%
4807% XHighlightRectangle() puts a border on the X server around a region defined
4808% by highlight_info.
4809%
4810% The format of the XHighlightRectangle method is:
4811%
4812% void XHighlightRectangle(Display *display,Window window,
4813% GC annotate_context,const RectangleInfo *highlight_info)
4814%
4815% A description of each parameter follows:
4816%
4817% o display: Specifies a connection to an X server; returned from
4818% XOpenDisplay.
4819%
4820% o window: Specifies a pointer to a Window structure.
4821%
4822% o annotate_context: Specifies a pointer to a GC structure.
4823%
4824% o highlight_info: Specifies a pointer to a RectangleInfo structure. It
4825% contains the extents of any highlighting rectangle.
4826%
4827*/
cristybcbda3f2011-09-03 13:01:22 +00004828MagickPrivate void XHighlightRectangle(Display *display,Window window,
cristy3ed852e2009-09-05 21:47:34 +00004829 GC annotate_context,const RectangleInfo *highlight_info)
4830{
4831 assert(display != (Display *) NULL);
4832 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
4833 assert(window != (Window) NULL);
4834 assert(annotate_context != (GC) NULL);
4835 assert(highlight_info != (RectangleInfo *) NULL);
4836 if ((highlight_info->width < 4) || (highlight_info->height < 4))
4837 return;
4838 (void) XDrawRectangle(display,window,annotate_context,(int) highlight_info->x,
4839 (int) highlight_info->y,(unsigned int) highlight_info->width-1,
4840 (unsigned int) highlight_info->height-1);
4841 (void) XDrawRectangle(display,window,annotate_context,(int) highlight_info->x+
4842 1,(int) highlight_info->y+1,(unsigned int) highlight_info->width-3,
4843 (unsigned int) highlight_info->height-3);
4844}
4845
4846/*
4847%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4848% %
4849% %
4850% %
4851% X I m p o r t I m a g e %
4852% %
4853% %
4854% %
4855%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4856%
4857% XImportImage() reads an image from an X window.
4858%
4859% The format of the XImportImage method is:
4860%
4861% Image *XImportImage(const ImageInfo *image_info,XImportInfo *ximage_info)
4862%
4863% A description of each parameter follows:
4864%
4865% o image_info: the image info.
4866%
4867% o ximage_info: Specifies a pointer to an XImportInfo structure.
4868%
4869*/
4870MagickExport Image *XImportImage(const ImageInfo *image_info,
4871 XImportInfo *ximage_info)
4872{
4873 Colormap
4874 *colormaps;
4875
4876 Display
4877 *display;
4878
4879 Image
4880 *image;
4881
4882 int
4883 number_colormaps,
4884 number_windows,
4885 x;
4886
4887 RectangleInfo
4888 crop_info;
4889
4890 Status
4891 status;
4892
4893 Window
4894 *children,
4895 client,
4896 prior_target,
4897 root,
4898 target;
4899
4900 XTextProperty
4901 window_name;
4902
4903 /*
4904 Open X server connection.
4905 */
4906 assert(image_info != (const ImageInfo *) NULL);
4907 assert(image_info->signature == MagickSignature);
4908 if (image_info->debug != MagickFalse)
4909 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
4910 image_info->filename);
4911 assert(ximage_info != (XImportInfo *) NULL);
4912 display=XOpenDisplay(image_info->server_name);
4913 if (display == (Display *) NULL)
4914 {
4915 ThrowXWindowFatalException(XServerError,"UnableToOpenXServer",
4916 XDisplayName(image_info->server_name));
4917 return((Image *) NULL);
4918 }
4919 /*
4920 Set our forgiving exception handler.
4921 */
4922 (void) XSetErrorHandler(XError);
4923 /*
4924 Select target window.
4925 */
4926 crop_info.x=0;
4927 crop_info.y=0;
4928 crop_info.width=0;
4929 crop_info.height=0;
4930 root=XRootWindow(display,XDefaultScreen(display));
4931 target=(Window) NULL;
4932 if ((image_info->filename != (char *) NULL) &&
4933 (*image_info->filename != '\0'))
4934 {
4935 if (LocaleCompare(image_info->filename,"root") == 0)
4936 target=root;
4937 else
4938 {
4939 /*
4940 Select window by ID or name.
4941 */
4942 if (isdigit((unsigned char) *image_info->filename) != 0)
4943 target=XWindowByID(display,root,(Window)
4944 strtol(image_info->filename,(char **) NULL,0));
4945 if (target == (Window) NULL)
4946 target=XWindowByName(display,root,image_info->filename);
4947 if (target == (Window) NULL)
4948 ThrowXWindowFatalException(XServerError,
4949 "NoWindowWithSpecifiedIDExists",image_info->filename);
4950 }
4951 }
4952 /*
4953 If target window is not defined, interactively select one.
4954 */
4955 prior_target=target;
4956 if (target == (Window) NULL)
4957 target=XSelectWindow(display,&crop_info);
4958 if (target == (Window) NULL)
4959 ThrowXWindowFatalException(XServerError,"UnableToReadXWindowImage",
4960 image_info->filename);
4961 client=target; /* obsolete */
4962 if (target != root)
4963 {
4964 unsigned int
4965 d;
4966
4967 status=XGetGeometry(display,target,&root,&x,&x,&d,&d,&d,&d);
4968 if (status != False)
4969 {
4970 for ( ; ; )
4971 {
4972 Window
4973 parent;
4974
4975 /*
4976 Find window manager frame.
4977 */
4978 status=XQueryTree(display,target,&root,&parent,&children,&d);
4979 if ((status != False) && (children != (Window *) NULL))
4980 (void) XFree((char *) children);
4981 if ((status == False) || (parent == (Window) NULL) ||
4982 (parent == root))
4983 break;
4984 target=parent;
4985 }
4986 /*
4987 Get client window.
4988 */
4989 client=XClientWindow(display,target);
4990 if (ximage_info->frame == MagickFalse)
4991 target=client;
4992 if ((ximage_info->frame == MagickFalse) &&
4993 (prior_target != MagickFalse))
4994 target=prior_target;
4995 XDelay(display,SuspendTime << 4);
4996 }
4997 }
4998 if (ximage_info->screen)
4999 {
5000 int
5001 y;
5002
5003 Window
5004 child;
5005
5006 XWindowAttributes
5007 window_attributes;
5008
5009 /*
5010 Obtain window image directly from screen.
5011 */
5012 status=XGetWindowAttributes(display,target,&window_attributes);
5013 if (status == False)
5014 {
5015 ThrowXWindowFatalException(XServerError,
5016 "UnableToReadXWindowAttributes",image_info->filename);
5017 (void) XCloseDisplay(display);
5018 return((Image *) NULL);
5019 }
5020 (void) XTranslateCoordinates(display,target,root,0,0,&x,&y,&child);
cristyc57f6942010-11-12 01:47:39 +00005021 crop_info.x=(ssize_t) x;
5022 crop_info.y=(ssize_t) y;
cristybb503372010-05-27 20:51:26 +00005023 crop_info.width=(size_t) window_attributes.width;
5024 crop_info.height=(size_t) window_attributes.height;
cristy553743c2010-03-03 15:04:17 +00005025 if (ximage_info->borders != 0)
cristy3ed852e2009-09-05 21:47:34 +00005026 {
5027 /*
5028 Include border in image.
5029 */
5030 crop_info.x-=window_attributes.border_width;
5031 crop_info.y-=window_attributes.border_width;
5032 crop_info.width+=window_attributes.border_width << 1;
5033 crop_info.height+=window_attributes.border_width << 1;
5034 }
5035 target=root;
5036 }
5037 /*
5038 If WM_COLORMAP_WINDOWS property is set or multiple colormaps, descend.
5039 */
5040 number_windows=0;
5041 status=XGetWMColormapWindows(display,target,&children,&number_windows);
5042 if ((status == True) && (number_windows > 0))
5043 {
5044 ximage_info->descend=MagickTrue;
5045 (void) XFree ((char *) children);
5046 }
5047 colormaps=XListInstalledColormaps(display,target,&number_colormaps);
5048 if (number_colormaps > 0)
5049 {
5050 if (number_colormaps > 1)
5051 ximage_info->descend=MagickTrue;
5052 (void) XFree((char *) colormaps);
5053 }
5054 /*
5055 Alert the user not to alter the screen.
5056 */
5057 if (ximage_info->silent == MagickFalse)
5058 (void) XBell(display,0);
5059 /*
5060 Get image by window id.
5061 */
5062 (void) XGrabServer(display);
5063 image=XGetWindowImage(display,target,ximage_info->borders,
5064 ximage_info->descend ? 1U : 0U);
5065 (void) XUngrabServer(display);
5066 if (image == (Image *) NULL)
5067 ThrowXWindowFatalException(XServerError,"UnableToReadXWindowImage",
5068 image_info->filename)
5069 else
5070 {
5071 (void) CopyMagickString(image->filename,image_info->filename,
5072 MaxTextExtent);
5073 if ((crop_info.width != 0) && (crop_info.height != 0))
5074 {
5075 Image
5076 *clone_image,
5077 *crop_image;
5078
5079 /*
5080 Crop image as defined by the cropping rectangle.
5081 */
5082 clone_image=CloneImage(image,0,0,MagickTrue,&image->exception);
5083 if (clone_image != (Image *) NULL)
5084 {
5085 crop_image=CropImage(clone_image,&crop_info,&image->exception);
5086 if (crop_image != (Image *) NULL)
5087 {
5088 image=DestroyImage(image);
5089 image=crop_image;
5090 }
5091 }
5092 }
5093 status=XGetWMName(display,target,&window_name);
5094 if (status == True)
5095 {
5096 if ((image_info->filename != (char *) NULL) &&
5097 (*image_info->filename == '\0'))
5098 (void) CopyMagickString(image->filename,(char *) window_name.value,
5099 (size_t) window_name.nitems+1);
5100 (void) XFree((void *) window_name.value);
5101 }
5102 }
5103 if (ximage_info->silent == MagickFalse)
5104 {
5105 /*
5106 Alert the user we're done.
5107 */
5108 (void) XBell(display,0);
5109 (void) XBell(display,0);
5110 }
5111 (void) XCloseDisplay(display);
5112 return(image);
5113}
5114
5115/*
5116%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5117% %
5118% %
5119% %
5120% X I n i t i a l i z e W i n d o w s %
5121% %
5122% %
5123% %
5124%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5125%
5126% XInitializeWindows() initializes the XWindows structure.
5127%
5128% The format of the XInitializeWindows method is:
5129%
5130% XWindows *XInitializeWindows(Display *display,
5131% XResourceInfo *resource_info)
5132%
5133% A description of each parameter follows:
5134%
5135% o windows: XInitializeWindows returns a pointer to a XWindows structure.
5136%
5137% o display: Specifies a connection to an X server; returned from
5138% XOpenDisplay.
5139%
5140% o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
5141%
5142*/
cristybcbda3f2011-09-03 13:01:22 +00005143MagickPrivate XWindows *XInitializeWindows(Display *display,
cristy3ed852e2009-09-05 21:47:34 +00005144 XResourceInfo *resource_info)
5145{
5146 Window
5147 root_window;
5148
5149 XWindows
5150 *windows;
5151
5152 /*
5153 Allocate windows structure.
5154 */
cristy73bd4a52010-10-05 11:24:23 +00005155 windows=(XWindows *) AcquireMagickMemory(sizeof(*windows));
cristy3ed852e2009-09-05 21:47:34 +00005156 if (windows == (XWindows *) NULL)
5157 {
5158 ThrowXWindowFatalException(XServerFatalError,"MemoryAllocationFailed",
5159 "...");
5160 return((XWindows *) NULL);
5161 }
5162 (void) ResetMagickMemory(windows,0,sizeof(*windows));
5163 windows->pixel_info=(XPixelInfo *) AcquireMagickMemory(
5164 sizeof(*windows->pixel_info));
5165 windows->icon_pixel=(XPixelInfo *) AcquireMagickMemory(
5166 sizeof(*windows->icon_pixel));
5167 windows->icon_resources=(XResourceInfo *) AcquireMagickMemory(
5168 sizeof(*windows->icon_resources));
5169 if ((windows->pixel_info == (XPixelInfo *) NULL) ||
5170 (windows->icon_pixel == (XPixelInfo *) NULL) ||
5171 (windows->icon_resources == (XResourceInfo *) NULL))
5172 {
5173 ThrowXWindowFatalException(XServerFatalError,"MemoryAllocationFailed",
5174 "...");
5175 return((XWindows *) NULL);
5176 }
5177 /*
5178 Initialize windows structure.
5179 */
5180 windows->display=display;
5181 windows->wm_protocols=XInternAtom(display,"WM_PROTOCOLS",MagickFalse);
5182 windows->wm_delete_window=XInternAtom(display,"WM_DELETE_WINDOW",MagickFalse);
5183 windows->wm_take_focus=XInternAtom(display,"WM_TAKE_FOCUS",MagickFalse);
5184 windows->im_protocols=XInternAtom(display,"IM_PROTOCOLS",MagickFalse);
5185 windows->im_remote_command=
5186 XInternAtom(display,"IM_REMOTE_COMMAND",MagickFalse);
5187 windows->im_update_widget=XInternAtom(display,"IM_UPDATE_WIDGET",MagickFalse);
5188 windows->im_update_colormap=
5189 XInternAtom(display,"IM_UPDATE_COLORMAP",MagickFalse);
5190 windows->im_former_image=XInternAtom(display,"IM_FORMER_IMAGE",MagickFalse);
5191 windows->im_next_image=XInternAtom(display,"IM_NEXT_IMAGE",MagickFalse);
5192 windows->im_retain_colors=XInternAtom(display,"IM_RETAIN_COLORS",MagickFalse);
5193 windows->im_exit=XInternAtom(display,"IM_EXIT",MagickFalse);
5194 windows->dnd_protocols=XInternAtom(display,"DndProtocol",MagickFalse);
cristy0157aea2010-04-24 21:12:18 +00005195#if defined(MAGICKCORE_WINDOWS_SUPPORT)
cristy3ed852e2009-09-05 21:47:34 +00005196 (void) XSynchronize(display,IsWindows95());
5197#endif
5198 if (IsEventLogging())
5199 {
5200 (void) XSynchronize(display,MagickTrue);
5201 (void) LogMagickEvent(X11Event,GetMagickModule(),"Version: %s",
cristybb503372010-05-27 20:51:26 +00005202 GetMagickVersion((size_t *) NULL));
cristy3ed852e2009-09-05 21:47:34 +00005203 (void) LogMagickEvent(X11Event,GetMagickModule(),"Protocols:");
5204 (void) LogMagickEvent(X11Event,GetMagickModule(),
5205 " Window Manager: 0x%lx",windows->wm_protocols);
5206 (void) LogMagickEvent(X11Event,GetMagickModule(),
5207 " delete window: 0x%lx",windows->wm_delete_window);
5208 (void) LogMagickEvent(X11Event,GetMagickModule()," take focus: 0x%lx",
5209 windows->wm_take_focus);
5210 (void) LogMagickEvent(X11Event,GetMagickModule()," ImageMagick: 0x%lx",
5211 windows->im_protocols);
5212 (void) LogMagickEvent(X11Event,GetMagickModule(),
5213 " remote command: 0x%lx",windows->im_remote_command);
5214 (void) LogMagickEvent(X11Event,GetMagickModule(),
5215 " update widget: 0x%lx",windows->im_update_widget);
5216 (void) LogMagickEvent(X11Event,GetMagickModule(),
5217 " update colormap: 0x%lx",windows->im_update_colormap);
5218 (void) LogMagickEvent(X11Event,GetMagickModule(),
5219 " former image: 0x%lx",windows->im_former_image);
5220 (void) LogMagickEvent(X11Event,GetMagickModule()," next image: 0x%lx",
5221 windows->im_next_image);
5222 (void) LogMagickEvent(X11Event,GetMagickModule(),
5223 " retain colors: 0x%lx",windows->im_retain_colors);
5224 (void) LogMagickEvent(X11Event,GetMagickModule()," exit: 0x%lx",
5225 windows->im_exit);
5226 (void) LogMagickEvent(X11Event,GetMagickModule()," Drag and Drop: 0x%lx",
5227 windows->dnd_protocols);
5228 }
5229 /*
5230 Allocate standard colormap.
5231 */
5232 windows->map_info=XAllocStandardColormap();
5233 windows->icon_map=XAllocStandardColormap();
5234 if ((windows->map_info == (XStandardColormap *) NULL) ||
5235 (windows->icon_map == (XStandardColormap *) NULL))
5236 ThrowXWindowFatalException(ResourceLimitFatalError,
5237 "MemoryAllocationFailed","...");
5238 windows->map_info->colormap=(Colormap) NULL;
5239 windows->icon_map->colormap=(Colormap) NULL;
cristyf2faecf2010-05-28 19:19:36 +00005240 windows->pixel_info->pixels=(unsigned long *) NULL;
cristy3ed852e2009-09-05 21:47:34 +00005241 windows->pixel_info->annotate_context=(GC) NULL;
5242 windows->pixel_info->highlight_context=(GC) NULL;
5243 windows->pixel_info->widget_context=(GC) NULL;
5244 windows->font_info=(XFontStruct *) NULL;
5245 windows->icon_pixel->annotate_context=(GC) NULL;
cristyf2faecf2010-05-28 19:19:36 +00005246 windows->icon_pixel->pixels=(unsigned long *) NULL;
cristy3ed852e2009-09-05 21:47:34 +00005247 /*
5248 Allocate visual.
5249 */
5250 *windows->icon_resources=(*resource_info);
5251 windows->icon_resources->visual_type=(char *) "default";
5252 windows->icon_resources->colormap=SharedColormap;
5253 windows->visual_info=
5254 XBestVisualInfo(display,windows->map_info,resource_info);
5255 windows->icon_visual=
5256 XBestVisualInfo(display,windows->icon_map,windows->icon_resources);
5257 if ((windows->visual_info == (XVisualInfo *) NULL) ||
5258 (windows->icon_visual == (XVisualInfo *) NULL))
5259 ThrowXWindowFatalException(XServerFatalError,"UnableToGetVisual",
5260 resource_info->visual_type);
5261 if (IsEventLogging())
5262 {
5263 (void) LogMagickEvent(X11Event,GetMagickModule(),"Visual:");
5264 (void) LogMagickEvent(X11Event,GetMagickModule()," visual id: 0x%lx",
5265 windows->visual_info->visualid);
5266 (void) LogMagickEvent(X11Event,GetMagickModule()," class: %s",
5267 XVisualClassName(windows->visual_info->klass));
5268 (void) LogMagickEvent(X11Event,GetMagickModule()," depth: %d planes",
5269 windows->visual_info->depth);
5270 (void) LogMagickEvent(X11Event,GetMagickModule(),
5271 " size of colormap: %d entries",windows->visual_info->colormap_size);
5272 (void) LogMagickEvent(X11Event,GetMagickModule(),
5273 " red, green, blue masks: 0x%lx 0x%lx 0x%lx",
5274 windows->visual_info->red_mask,windows->visual_info->green_mask,
5275 windows->visual_info->blue_mask);
5276 (void) LogMagickEvent(X11Event,GetMagickModule(),
5277 " significant bits in color: %d bits",
5278 windows->visual_info->bits_per_rgb);
5279 }
5280 /*
5281 Allocate class and manager hints.
5282 */
5283 windows->class_hints=XAllocClassHint();
5284 windows->manager_hints=XAllocWMHints();
5285 if ((windows->class_hints == (XClassHint *) NULL) ||
5286 (windows->manager_hints == (XWMHints *) NULL))
5287 ThrowXWindowFatalException(ResourceLimitFatalError,
5288 "MemoryAllocationFailed","...");
5289 /*
5290 Determine group leader if we have one.
5291 */
5292 root_window=XRootWindow(display,windows->visual_info->screen);
5293 windows->group_leader.id=(Window) NULL;
5294 if (resource_info->window_group != (char *) NULL)
5295 {
5296 if (isdigit((unsigned char) *resource_info->window_group) != 0)
5297 windows->group_leader.id=XWindowByID(display,root_window,(Window)
5298 strtol((char *) resource_info->window_group,(char **) NULL,0));
5299 if (windows->group_leader.id == (Window) NULL)
5300 windows->group_leader.id=
5301 XWindowByName(display,root_window,resource_info->window_group);
5302 }
5303 return(windows);
5304}
5305
5306/*
5307%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5308% %
5309% %
5310% %
5311% X M a k e C u r s o r %
5312% %
5313% %
5314% %
5315%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5316%
5317% XMakeCursor() creates a crosshairs X11 cursor.
5318%
5319% The format of the XMakeCursor method is:
5320%
5321% Cursor XMakeCursor(Display *display,Window window,Colormap colormap,
5322% char *background_color,char *foreground_color)
5323%
5324% A description of each parameter follows:
5325%
5326% o display: Specifies a connection to an X server; returned from
5327% XOpenDisplay.
5328%
5329% o window: Specifies the ID of the window for which the cursor is
5330% assigned.
5331%
5332% o colormap: Specifies the ID of the colormap from which the background
5333% and foreground color will be retrieved.
5334%
5335% o background_color: Specifies the color to use for the cursor background.
5336%
5337% o foreground_color: Specifies the color to use for the cursor foreground.
5338%
5339*/
cristybcbda3f2011-09-03 13:01:22 +00005340MagickPrivate Cursor XMakeCursor(Display *display,Window window,
cristy3ed852e2009-09-05 21:47:34 +00005341 Colormap colormap,char *background_color,char *foreground_color)
5342{
5343#define scope_height 17
5344#define scope_x_hot 8
5345#define scope_y_hot 8
5346#define scope_width 17
5347
5348 static const unsigned char
5349 scope_bits[] =
5350 {
5351 0x80, 0x03, 0x00, 0x80, 0x02, 0x00, 0x80, 0x02, 0x00, 0x80, 0x02,
5352 0x00, 0x80, 0x02, 0x00, 0x80, 0x02, 0x00, 0x80, 0x02, 0x00, 0x7f,
5353 0xfc, 0x01, 0x01, 0x00, 0x01, 0x7f, 0xfc, 0x01, 0x80, 0x02, 0x00,
5354 0x80, 0x02, 0x00, 0x80, 0x02, 0x00, 0x80, 0x02, 0x00, 0x80, 0x02,
5355 0x00, 0x80, 0x02, 0x00, 0x80, 0x03, 0x00
5356 },
5357 scope_mask_bits[] =
5358 {
5359 0xc0, 0x07, 0x00, 0xc0, 0x07, 0x00, 0xc0, 0x06, 0x00, 0xc0, 0x06,
5360 0x00, 0xc0, 0x06, 0x00, 0xc0, 0x06, 0x00, 0xff, 0xfe, 0x01, 0x7f,
5361 0xfc, 0x01, 0x03, 0x80, 0x01, 0x7f, 0xfc, 0x01, 0xff, 0xfe, 0x01,
5362 0xc0, 0x06, 0x00, 0xc0, 0x06, 0x00, 0xc0, 0x06, 0x00, 0xc0, 0x06,
5363 0x00, 0xc0, 0x07, 0x00, 0xc0, 0x07, 0x00
5364 };
5365
5366 Cursor
5367 cursor;
5368
5369 Pixmap
5370 mask,
5371 source;
5372
5373 XColor
5374 background,
5375 foreground;
5376
5377 assert(display != (Display *) NULL);
5378 assert(window != (Window) NULL);
5379 assert(colormap != (Colormap) NULL);
5380 assert(background_color != (char *) NULL);
5381 assert(foreground_color != (char *) NULL);
5382 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",background_color);
5383 source=XCreateBitmapFromData(display,window,(char *) scope_bits,scope_width,
5384 scope_height);
5385 mask=XCreateBitmapFromData(display,window,(char *) scope_mask_bits,
5386 scope_width,scope_height);
5387 if ((source == (Pixmap) NULL) || (mask == (Pixmap) NULL))
5388 {
5389 ThrowXWindowFatalException(XServerError,"UnableToCreatePixmap","...");
5390 return((Cursor) NULL);
5391 }
5392 (void) XParseColor(display,colormap,background_color,&background);
5393 (void) XParseColor(display,colormap,foreground_color,&foreground);
5394 cursor=XCreatePixmapCursor(display,source,mask,&foreground,&background,
5395 scope_x_hot,scope_y_hot);
5396 (void) XFreePixmap(display,source);
5397 (void) XFreePixmap(display,mask);
5398 return(cursor);
5399}
5400
5401/*
5402%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5403% %
5404% %
5405% %
5406% X M a k e I m a g e %
5407% %
5408% %
5409% %
5410%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5411%
5412% XMakeImage() creates an X11 image. If the image size differs from the X11
5413% image size, the image is first resized.
5414%
5415% The format of the XMakeImage method is:
5416%
5417% MagickBooleanType XMakeImage(Display *display,
5418% const XResourceInfo *resource_info,XWindowInfo *window,Image *image,
cristy051718b2011-08-28 22:49:25 +00005419% unsigned int width,unsigned int height,ExceptionInfo *exception)
cristy3ed852e2009-09-05 21:47:34 +00005420%
5421% A description of each parameter follows:
5422%
5423% o display: Specifies a connection to an X server; returned from
5424% XOpenDisplay.
5425%
5426% o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
5427%
5428% o window: Specifies a pointer to a XWindowInfo structure.
5429%
5430% o image: the image.
5431%
5432% o width: Specifies the width in pixels of the rectangular area to
5433% display.
5434%
5435% o height: Specifies the height in pixels of the rectangular area to
5436% display.
5437%
cristy051718b2011-08-28 22:49:25 +00005438% o exception: return any errors or warnings in this structure.
5439%
cristy3ed852e2009-09-05 21:47:34 +00005440*/
cristybcbda3f2011-09-03 13:01:22 +00005441MagickPrivate MagickBooleanType XMakeImage(Display *display,
cristy3ed852e2009-09-05 21:47:34 +00005442 const XResourceInfo *resource_info,XWindowInfo *window,Image *image,
cristy051718b2011-08-28 22:49:25 +00005443 unsigned int width,unsigned int height,ExceptionInfo *exception)
cristy3ed852e2009-09-05 21:47:34 +00005444{
5445#define CheckOverflowException(length,width,height) \
5446 (((height) != 0) && ((length)/((size_t) height) != ((size_t) width)))
5447
5448 int
5449 depth,
5450 format;
5451
5452 size_t
5453 length;
5454
5455 XImage
5456 *matte_image,
5457 *ximage;
5458
5459 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
5460 assert(display != (Display *) NULL);
5461 assert(resource_info != (XResourceInfo *) NULL);
5462 assert(window != (XWindowInfo *) NULL);
5463 assert(width != 0);
5464 assert(height != 0);
5465 if ((window->width == 0) || (window->height == 0))
5466 return(MagickFalse);
5467 /*
5468 Apply user transforms to the image.
5469 */
5470 (void) XCheckDefineCursor(display,window->id,window->busy_cursor);
5471 (void) XFlush(display);
5472 depth=(int) window->depth;
5473 if (window->destroy)
5474 window->image=DestroyImage(window->image);
5475 window->image=image;
5476 window->destroy=MagickFalse;
5477 if (window->image != (Image *) NULL)
5478 {
5479 if (window->crop_geometry != (char *) NULL)
5480 {
5481 Image
5482 *crop_image;
5483
5484 RectangleInfo
5485 crop_info;
5486
5487 /*
5488 Crop image.
5489 */
5490 window->image->page.x=0;
5491 window->image->page.y=0;
5492 (void) ParsePageGeometry(window->image,window->crop_geometry,
5493 &crop_info,&image->exception);
5494 crop_image=CropImage(window->image,&crop_info,&image->exception);
5495 if (crop_image != (Image *) NULL)
5496 {
5497 if (window->image != image)
5498 window->image=DestroyImage(window->image);
5499 window->image=crop_image;
5500 window->destroy=MagickTrue;
5501 }
5502 }
5503 if ((width != (unsigned int) window->image->columns) ||
5504 (height != (unsigned int) window->image->rows))
5505 {
5506 Image
5507 *resize_image;
5508
5509 /*
5510 Resize image.
5511 */
5512 resize_image=NewImageList();
5513 if (window->pixel_info->colors != 0)
5514 resize_image=SampleImage(window->image,width,height,
5515 &image->exception);
5516 else
5517 resize_image=ThumbnailImage(window->image,width,height,
5518 &image->exception);
5519 if (resize_image != (Image *) NULL)
5520 {
5521 if (window->image != image)
5522 window->image=DestroyImage(window->image);
5523 window->image=resize_image;
5524 window->destroy=MagickTrue;
5525 }
5526 }
5527 width=(unsigned int) window->image->columns;
cristybb503372010-05-27 20:51:26 +00005528 assert((size_t) width == window->image->columns);
cristy3ed852e2009-09-05 21:47:34 +00005529 height=(unsigned int) window->image->rows;
cristybb503372010-05-27 20:51:26 +00005530 assert((size_t) height == window->image->rows);
cristy3ed852e2009-09-05 21:47:34 +00005531 }
5532 /*
5533 Create X image.
5534 */
5535 ximage=(XImage *) NULL;
5536 format=(depth == 1) ? XYBitmap : ZPixmap;
5537#if defined(MAGICKCORE_HAVE_SHARED_MEMORY)
5538 if (window->shared_memory != MagickFalse)
5539 {
5540 XShmSegmentInfo
5541 *segment_info;
5542
5543 segment_info=(XShmSegmentInfo *) window->segment_info;
5544 segment_info[1].shmid=(-1);
5545 segment_info[1].shmaddr=(char *) NULL;
5546 ximage=XShmCreateImage(display,window->visual,(unsigned int) depth,format,
5547 (char *) NULL,&segment_info[1],width,height);
5548 if (ximage == (XImage *) NULL)
5549 window->shared_memory=MagickFalse;
5550 length=(size_t) ximage->bytes_per_line*ximage->height;
5551 if (CheckOverflowException(length,ximage->bytes_per_line,ximage->height))
5552 window->shared_memory=MagickFalse;
5553 if (window->shared_memory != MagickFalse)
5554 segment_info[1].shmid=shmget(IPC_PRIVATE,length,IPC_CREAT | 0777);
5555 if (window->shared_memory != MagickFalse)
5556 segment_info[1].shmaddr=(char *) shmat(segment_info[1].shmid,0,0);
5557 if (segment_info[1].shmid < 0)
5558 window->shared_memory=MagickFalse;
5559 if (window->shared_memory != MagickFalse)
5560 (void) shmctl(segment_info[1].shmid,IPC_RMID,0);
5561 else
5562 {
5563 if (ximage != (XImage *) NULL)
5564 XDestroyImage(ximage);
5565 ximage=(XImage *) NULL;
5566 if (segment_info[1].shmaddr)
5567 {
5568 (void) shmdt(segment_info[1].shmaddr);
5569 segment_info[1].shmaddr=(char *) NULL;
5570 }
5571 if (segment_info[1].shmid >= 0)
5572 {
5573 (void) shmctl(segment_info[1].shmid,IPC_RMID,0);
5574 segment_info[1].shmid=(-1);
5575 }
5576 }
5577 }
5578#endif
5579 /*
5580 Allocate X image pixel data.
5581 */
5582#if defined(MAGICKCORE_HAVE_SHARED_MEMORY)
5583 if (window->shared_memory)
5584 {
5585 Status
5586 status;
5587
5588 XShmSegmentInfo
5589 *segment_info;
5590
5591 (void) XSync(display,MagickFalse);
5592 xerror_alert=MagickFalse;
5593 segment_info=(XShmSegmentInfo *) window->segment_info;
5594 ximage->data=segment_info[1].shmaddr;
5595 segment_info[1].readOnly=MagickFalse;
5596 status=XShmAttach(display,&segment_info[1]);
5597 if (status != False)
5598 (void) XSync(display,MagickFalse);
5599 if ((status == False) || (xerror_alert != MagickFalse))
5600 {
5601 window->shared_memory=MagickFalse;
5602 if (status != False)
5603 XShmDetach(display,&segment_info[1]);
5604 if (ximage != (XImage *) NULL)
5605 {
5606 ximage->data=NULL;
5607 XDestroyImage(ximage);
5608 ximage=(XImage *) NULL;
5609 }
5610 if (segment_info[1].shmid >= 0)
5611 {
5612 if (segment_info[1].shmaddr != NULL)
5613 (void) shmdt(segment_info[1].shmaddr);
5614 (void) shmctl(segment_info[1].shmid,IPC_RMID,0);
5615 segment_info[1].shmid=(-1);
5616 segment_info[1].shmaddr=(char *) NULL;
5617 }
5618 }
5619 }
5620#endif
5621 if (window->shared_memory == MagickFalse)
5622 ximage=XCreateImage(display,window->visual,(unsigned int) depth,format,0,
5623 (char *) NULL,width,height,XBitmapPad(display),0);
5624 if (ximage == (XImage *) NULL)
5625 {
5626 /*
5627 Unable to create X image.
5628 */
5629 (void) XCheckDefineCursor(display,window->id,window->cursor);
5630 return(MagickFalse);
5631 }
5632 length=(size_t) ximage->bytes_per_line*ximage->height;
5633 if (IsEventLogging())
5634 {
5635 (void) LogMagickEvent(X11Event,GetMagickModule(),"XImage:");
5636 (void) LogMagickEvent(X11Event,GetMagickModule()," width, height: %dx%d",
5637 ximage->width,ximage->height);
5638 (void) LogMagickEvent(X11Event,GetMagickModule()," format: %d",
5639 ximage->format);
5640 (void) LogMagickEvent(X11Event,GetMagickModule()," byte order: %d",
5641 ximage->byte_order);
5642 (void) LogMagickEvent(X11Event,GetMagickModule(),
5643 " bitmap unit, bit order, pad: %d %d %d",ximage->bitmap_unit,
5644 ximage->bitmap_bit_order,ximage->bitmap_pad);
5645 (void) LogMagickEvent(X11Event,GetMagickModule()," depth: %d",
5646 ximage->depth);
5647 (void) LogMagickEvent(X11Event,GetMagickModule()," bytes per line: %d",
5648 ximage->bytes_per_line);
5649 (void) LogMagickEvent(X11Event,GetMagickModule()," bits per pixel: %d",
5650 ximage->bits_per_pixel);
5651 (void) LogMagickEvent(X11Event,GetMagickModule(),
5652 " red, green, blue masks: 0x%lx 0x%lx 0x%lx",ximage->red_mask,
5653 ximage->green_mask,ximage->blue_mask);
5654 }
5655 if (window->shared_memory == MagickFalse)
5656 {
5657 if (ximage->format != XYBitmap)
5658 ximage->data=(char *) AcquireQuantumMemory((size_t)
5659 ximage->bytes_per_line,(size_t) ximage->height);
5660 else
5661 ximage->data=(char *) AcquireQuantumMemory((size_t)
5662 ximage->bytes_per_line*ximage->depth,(size_t) ximage->height);
5663 }
5664 if (ximage->data == (char *) NULL)
5665 {
5666 /*
5667 Unable to allocate pixel data.
5668 */
5669 XDestroyImage(ximage);
5670 ximage=(XImage *) NULL;
5671 (void) XCheckDefineCursor(display,window->id,window->cursor);
5672 return(MagickFalse);
5673 }
5674 if (window->ximage != (XImage *) NULL)
5675 {
5676 /*
5677 Destroy previous X image.
5678 */
5679 length=(size_t) window->ximage->bytes_per_line*window->ximage->height;
5680#if defined(MAGICKCORE_HAVE_SHARED_MEMORY)
5681 if (window->segment_info != (XShmSegmentInfo *) NULL)
5682 {
5683 XShmSegmentInfo
5684 *segment_info;
5685
5686 segment_info=(XShmSegmentInfo *) window->segment_info;
5687 if (segment_info[0].shmid >= 0)
5688 {
5689 (void) XSync(display,MagickFalse);
5690 (void) XShmDetach(display,&segment_info[0]);
5691 (void) XSync(display,MagickFalse);
5692 if (segment_info[0].shmaddr != (char *) NULL)
5693 (void) shmdt(segment_info[0].shmaddr);
5694 (void) shmctl(segment_info[0].shmid,IPC_RMID,0);
5695 segment_info[0].shmid=(-1);
5696 segment_info[0].shmaddr=(char *) NULL;
5697 window->ximage->data=(char *) NULL;
5698 }
5699 }
5700#endif
5701 if (window->ximage->data != (char *) NULL)
5702 free(window->ximage->data);
5703 window->ximage->data=(char *) NULL;
5704 XDestroyImage(window->ximage);
5705 window->ximage=(XImage *) NULL;
5706 }
5707#if defined(MAGICKCORE_HAVE_SHARED_MEMORY)
5708 if (window->segment_info != (XShmSegmentInfo *) NULL)
5709 {
5710 XShmSegmentInfo
5711 *segment_info;
5712
5713 segment_info=(XShmSegmentInfo *) window->segment_info;
5714 segment_info[0]=segment_info[1];
5715 }
5716#endif
5717 window->ximage=ximage;
5718 matte_image=(XImage *) NULL;
5719 if ((window->shape != MagickFalse) && (window->image != (Image *) NULL))
5720 if ((window->image->matte != MagickFalse) &&
cristyc57f6942010-11-12 01:47:39 +00005721 ((int) width <= XDisplayWidth(display,window->screen)) &&
5722 ((int) height <= XDisplayHeight(display,window->screen)))
cristy3ed852e2009-09-05 21:47:34 +00005723 {
5724 /*
5725 Create matte image.
5726 */
5727 matte_image=XCreateImage(display,window->visual,1,XYBitmap,0,
5728 (char *) NULL,width,height,XBitmapPad(display),0);
5729 if (IsEventLogging())
5730 {
5731 (void) LogMagickEvent(X11Event,GetMagickModule(),"Matte Image:");
5732 (void) LogMagickEvent(X11Event,GetMagickModule(),
5733 " width, height: %dx%d",matte_image->width,matte_image->height);
5734 }
5735 if (matte_image != (XImage *) NULL)
5736 {
5737 /*
5738 Allocate matte image pixel data.
5739 */
5740 matte_image->data=(char *) AcquireQuantumMemory((size_t)
5741 matte_image->bytes_per_line*matte_image->depth,
5742 (size_t) matte_image->height);
5743 if (matte_image->data == (char *) NULL)
5744 {
5745 XDestroyImage(matte_image);
5746 matte_image=(XImage *) NULL;
5747 }
5748 }
5749 }
5750 if (window->matte_image != (XImage *) NULL)
5751 {
5752 /*
5753 Free matte image.
5754 */
5755 if (window->matte_image->data != (char *) NULL)
5756 free(window->matte_image->data);
5757 window->matte_image->data=(char *) NULL;
5758 XDestroyImage(window->matte_image);
5759 window->matte_image=(XImage *) NULL;
5760 }
5761 window->matte_image=matte_image;
5762 if (window->matte_pixmap != (Pixmap) NULL)
5763 {
5764 (void) XFreePixmap(display,window->matte_pixmap);
5765 window->matte_pixmap=(Pixmap) NULL;
5766#if defined(MAGICKCORE_HAVE_SHAPE)
5767 if (window->shape != MagickFalse)
5768 XShapeCombineMask(display,window->id,ShapeBounding,0,0,None,ShapeSet);
5769#endif
5770 }
5771 window->stasis=MagickFalse;
5772 /*
5773 Convert pixels to X image data.
5774 */
5775 if (window->image != (Image *) NULL)
5776 {
5777 if ((ximage->byte_order == LSBFirst) || ((ximage->format == XYBitmap) &&
5778 (ximage->bitmap_bit_order == LSBFirst)))
5779 XMakeImageLSBFirst(resource_info,window,window->image,ximage,
5780 matte_image);
5781 else
5782 XMakeImageMSBFirst(resource_info,window,window->image,ximage,
5783 matte_image);
5784 }
5785 if (window->matte_image != (XImage *) NULL)
5786 {
5787 /*
5788 Create matte pixmap.
5789 */
5790 window->matte_pixmap=XCreatePixmap(display,window->id,width,height,1);
5791 if (window->matte_pixmap != (Pixmap) NULL)
5792 {
5793 GC
5794 graphics_context;
5795
5796 XGCValues
5797 context_values;
5798
5799 /*
5800 Copy matte image to matte pixmap.
5801 */
cristy4c08aed2011-07-01 19:47:50 +00005802 context_values.background=0;
5803 context_values.foreground=1;
cristy3ed852e2009-09-05 21:47:34 +00005804 graphics_context=XCreateGC(display,window->matte_pixmap,
cristybb503372010-05-27 20:51:26 +00005805 (size_t) (GCBackground | GCForeground),&context_values);
cristy3ed852e2009-09-05 21:47:34 +00005806 (void) XPutImage(display,window->matte_pixmap,graphics_context,
5807 window->matte_image,0,0,0,0,width,height);
5808 (void) XFreeGC(display,graphics_context);
5809#if defined(MAGICKCORE_HAVE_SHAPE)
5810 if (window->shape != MagickFalse)
5811 XShapeCombineMask(display,window->id,ShapeBounding,0,0,
5812 window->matte_pixmap,ShapeSet);
5813#endif
5814 }
5815 }
5816 (void) XMakePixmap(display,resource_info,window);
5817 /*
5818 Restore cursor.
5819 */
5820 (void) XCheckDefineCursor(display,window->id,window->cursor);
5821 return(MagickTrue);
5822}
5823
5824/*
5825%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5826% %
5827% %
5828% %
5829+ X M a k e I m a g e L S B F i r s t %
5830% %
5831% %
5832% %
5833%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5834%
5835% XMakeImageLSBFirst() initializes the pixel data of an X11 Image. The X image
5836% pixels are copied in least-significant bit and byte first order. The
5837% server's scanline pad is respected. Rather than using one or two general
5838% cases, many special cases are found here to help speed up the image
5839% conversion.
5840%
5841% The format of the XMakeImageLSBFirst method is:
5842%
5843% void XMakeImageLSBFirst(Display *display,XWindows *windows)
5844%
5845% A description of each parameter follows:
5846%
5847% o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
5848%
5849% o window: Specifies a pointer to a XWindowInfo structure.
5850%
5851% o image: the image.
5852%
5853% o ximage: Specifies a pointer to a XImage structure; returned from
5854% XCreateImage.
5855%
5856% o matte_image: Specifies a pointer to a XImage structure; returned from
5857% XCreateImage.
5858%
5859*/
5860static void XMakeImageLSBFirst(const XResourceInfo *resource_info,
5861 const XWindowInfo *window,Image *image,XImage *ximage,XImage *matte_image)
5862{
cristyc57f6942010-11-12 01:47:39 +00005863 CacheView
5864 *canvas_view;
5865
cristy3ed852e2009-09-05 21:47:34 +00005866 Image
5867 *canvas;
5868
5869 int
5870 y;
5871
cristy4c08aed2011-07-01 19:47:50 +00005872 register const Quantum
cristy3ed852e2009-09-05 21:47:34 +00005873 *p;
5874
5875 register int
5876 x;
5877
5878 register unsigned char
5879 *q;
5880
5881 unsigned char
5882 bit,
5883 byte;
5884
5885 unsigned int
5886 scanline_pad;
5887
cristyf2faecf2010-05-28 19:19:36 +00005888 unsigned long
cristy3ed852e2009-09-05 21:47:34 +00005889 pixel,
5890 *pixels;
5891
5892 XStandardColormap
5893 *map_info;
5894
5895 assert(resource_info != (XResourceInfo *) NULL);
5896 assert(window != (XWindowInfo *) NULL);
5897 assert(image != (Image *) NULL);
5898 if (image->debug != MagickFalse)
5899 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
5900 canvas=image;
cristybab87c32010-02-09 20:54:22 +00005901 if ((window->immutable == MagickFalse) &&
cristy54666e82010-02-03 23:34:26 +00005902 (image->storage_class == DirectClass) && (image->matte != MagickFalse))
cristy3ed852e2009-09-05 21:47:34 +00005903 {
5904 char
5905 size[MaxTextExtent];
5906
5907 Image
5908 *pattern;
5909
5910 ImageInfo
5911 *image_info;
5912
5913 image_info=AcquireImageInfo();
5914 (void) CopyMagickString(image_info->filename,
5915 resource_info->image_info->texture != (char *) NULL ?
5916 resource_info->image_info->texture : "pattern:checkerboard",
5917 MaxTextExtent);
cristyb51dff52011-05-19 16:55:47 +00005918 (void) FormatLocaleString(size,MaxTextExtent,"%.20gx%.20g",(double)
cristye8c25f92010-06-03 00:53:06 +00005919 image->columns,(double) image->rows);
cristy3ed852e2009-09-05 21:47:34 +00005920 image_info->size=ConstantString(size);
5921 pattern=ReadImage(image_info,&image->exception);
5922 image_info=DestroyImageInfo(image_info);
5923 if (pattern != (Image *) NULL)
5924 {
5925 canvas=CloneImage(image,0,0,MagickTrue,&image->exception);
5926 if (canvas != (Image *) NULL)
5927 (void) CompositeImage(canvas,DstOverCompositeOp,pattern,0,0);
5928 pattern=DestroyImage(pattern);
5929 }
5930 }
5931 scanline_pad=(unsigned int) (ximage->bytes_per_line-((ximage->width*
5932 ximage->bits_per_pixel) >> 3));
5933 map_info=window->map_info;
5934 pixels=window->pixel_info->pixels;
5935 q=(unsigned char *) ximage->data;
5936 x=0;
cristyc57f6942010-11-12 01:47:39 +00005937 canvas_view=AcquireCacheView(canvas);
cristy3ed852e2009-09-05 21:47:34 +00005938 if (ximage->format == XYBitmap)
5939 {
5940 register unsigned short
5941 polarity;
5942
5943 unsigned char
5944 background,
5945 foreground;
5946
5947 /*
5948 Convert canvas to big-endian bitmap.
5949 */
5950 background=(unsigned char)
5951 (XPixelIntensity(&window->pixel_info->foreground_color) <
5952 XPixelIntensity(&window->pixel_info->background_color) ? 0x80 : 0x00);
5953 foreground=(unsigned char)
5954 (XPixelIntensity(&window->pixel_info->background_color) <
5955 XPixelIntensity(&window->pixel_info->foreground_color) ? 0x80 : 0x00);
cristy4c08aed2011-07-01 19:47:50 +00005956 polarity=(unsigned short) ((GetPixelPacketIntensity(
cristy3ed852e2009-09-05 21:47:34 +00005957 &canvas->colormap[0])) < ((Quantum) QuantumRange/2) ? 1 : 0);
5958 if (canvas->colors == 2)
cristy4c08aed2011-07-01 19:47:50 +00005959 polarity=GetPixelPacketIntensity(&canvas->colormap[0]) <
5960 GetPixelPacketIntensity(&canvas->colormap[1]);
cristy3ed852e2009-09-05 21:47:34 +00005961 for (y=0; y < (int) canvas->rows; y++)
5962 {
cristyc57f6942010-11-12 01:47:39 +00005963 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,canvas->columns,1,
5964 &canvas->exception);
cristy4c08aed2011-07-01 19:47:50 +00005965 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00005966 break;
cristy3ed852e2009-09-05 21:47:34 +00005967 bit=0;
5968 byte=0;
5969 for (x=0; x < (int) canvas->columns; x++)
5970 {
5971 byte>>=1;
cristy4c08aed2011-07-01 19:47:50 +00005972 if (GetPixelIndex(canvas,p) == (Quantum) polarity)
cristy3ed852e2009-09-05 21:47:34 +00005973 byte|=foreground;
5974 else
5975 byte|=background;
5976 bit++;
5977 if (bit == 8)
5978 {
5979 *q++=byte;
5980 bit=0;
5981 byte=0;
5982 }
cristyed231572011-07-14 02:18:59 +00005983 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00005984 }
5985 if (bit != 0)
5986 *q=byte >> (8-bit);
5987 q+=scanline_pad;
5988 }
5989 }
5990 else
5991 if (window->pixel_info->colors != 0)
5992 switch (ximage->bits_per_pixel)
5993 {
5994 case 2:
5995 {
5996 register unsigned int
5997 nibble;
5998
5999 /*
6000 Convert to 2 bit color-mapped X canvas.
6001 */
6002 for (y=0; y < (int) canvas->rows; y++)
6003 {
cristyc57f6942010-11-12 01:47:39 +00006004 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
6005 canvas->columns,1,&canvas->exception);
cristy4c08aed2011-07-01 19:47:50 +00006006 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00006007 break;
cristy3ed852e2009-09-05 21:47:34 +00006008 nibble=0;
6009 for (x=0; x < (int) canvas->columns; x++)
6010 {
cristy4c08aed2011-07-01 19:47:50 +00006011 pixel=pixels[(ssize_t) GetPixelIndex(canvas,p)] & 0x0f;
cristy3ed852e2009-09-05 21:47:34 +00006012 switch (nibble)
6013 {
6014 case 0:
6015 {
6016 *q=(unsigned char) pixel;
6017 nibble++;
6018 break;
6019 }
6020 case 1:
6021 {
6022 *q|=(unsigned char) (pixel << 2);
6023 nibble++;
6024 break;
6025 }
6026 case 2:
6027 {
6028 *q|=(unsigned char) (pixel << 4);
6029 nibble++;
6030 break;
6031 }
6032 case 3:
6033 {
6034 *q|=(unsigned char) (pixel << 6);
6035 q++;
6036 nibble=0;
6037 break;
6038 }
6039 }
cristyed231572011-07-14 02:18:59 +00006040 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00006041 }
6042 q+=scanline_pad;
6043 }
6044 break;
6045 }
6046 case 4:
6047 {
6048 register unsigned int
6049 nibble;
6050
6051 /*
6052 Convert to 4 bit color-mapped X canvas.
6053 */
6054 for (y=0; y < (int) canvas->rows; y++)
6055 {
cristyc57f6942010-11-12 01:47:39 +00006056 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
6057 canvas->columns,1,&canvas->exception);
cristy4c08aed2011-07-01 19:47:50 +00006058 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00006059 break;
cristy3ed852e2009-09-05 21:47:34 +00006060 nibble=0;
6061 for (x=0; x < (int) canvas->columns; x++)
6062 {
cristy4c08aed2011-07-01 19:47:50 +00006063 pixel=pixels[(ssize_t) GetPixelIndex(canvas,p)] & 0xf;
cristy3ed852e2009-09-05 21:47:34 +00006064 switch (nibble)
6065 {
6066 case 0:
6067 {
6068 *q=(unsigned char) pixel;
6069 nibble++;
6070 break;
6071 }
6072 case 1:
6073 {
6074 *q|=(unsigned char) (pixel << 4);
6075 q++;
6076 nibble=0;
6077 break;
6078 }
6079 }
cristyed231572011-07-14 02:18:59 +00006080 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00006081 }
6082 q+=scanline_pad;
6083 }
6084 break;
6085 }
6086 case 6:
6087 case 8:
6088 {
6089 /*
6090 Convert to 8 bit color-mapped X canvas.
6091 */
6092 if (resource_info->color_recovery &&
6093 resource_info->quantize_info->dither)
6094 {
6095 XDitherImage(canvas,ximage);
6096 break;
6097 }
6098 for (y=0; y < (int) canvas->rows; y++)
6099 {
cristyc57f6942010-11-12 01:47:39 +00006100 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
6101 canvas->columns,1,&canvas->exception);
cristy4c08aed2011-07-01 19:47:50 +00006102 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00006103 break;
cristy3ed852e2009-09-05 21:47:34 +00006104 for (x=0; x < (int) canvas->columns; x++)
6105 {
cristy4c08aed2011-07-01 19:47:50 +00006106 pixel=pixels[(ssize_t) GetPixelIndex(canvas,p)];
cristy3ed852e2009-09-05 21:47:34 +00006107 *q++=(unsigned char) pixel;
cristyed231572011-07-14 02:18:59 +00006108 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00006109 }
6110 q+=scanline_pad;
6111 }
6112 break;
6113 }
6114 default:
6115 {
6116 register int
6117 k;
6118
6119 register unsigned int
6120 bytes_per_pixel;
6121
6122 unsigned char
cristybb503372010-05-27 20:51:26 +00006123 channel[sizeof(size_t)];
cristy3ed852e2009-09-05 21:47:34 +00006124
6125 /*
6126 Convert to multi-byte color-mapped X canvas.
6127 */
6128 bytes_per_pixel=(unsigned int) (ximage->bits_per_pixel >> 3);
6129 for (y=0; y < (int) canvas->rows; y++)
6130 {
cristyc57f6942010-11-12 01:47:39 +00006131 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
6132 canvas->columns,1,&canvas->exception);
cristy4c08aed2011-07-01 19:47:50 +00006133 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00006134 break;
cristy3ed852e2009-09-05 21:47:34 +00006135 for (x=0; x < (int) canvas->columns; x++)
6136 {
cristy4c08aed2011-07-01 19:47:50 +00006137 pixel=pixels[(ssize_t) GetPixelIndex(canvas,p)];
cristy3ed852e2009-09-05 21:47:34 +00006138 for (k=0; k < (int) bytes_per_pixel; k++)
6139 {
6140 channel[k]=(unsigned char) pixel;
6141 pixel>>=8;
6142 }
6143 for (k=0; k < (int) bytes_per_pixel; k++)
6144 *q++=channel[k];
cristyed231572011-07-14 02:18:59 +00006145 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00006146 }
6147 q+=scanline_pad;
6148 }
6149 break;
6150 }
6151 }
6152 else
6153 switch (ximage->bits_per_pixel)
6154 {
6155 case 2:
6156 {
6157 register unsigned int
6158 nibble;
6159
6160 /*
6161 Convert to contiguous 2 bit continuous-tone X canvas.
6162 */
6163 for (y=0; y < (int) canvas->rows; y++)
6164 {
6165 nibble=0;
cristyc57f6942010-11-12 01:47:39 +00006166 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
6167 canvas->columns,1,&canvas->exception);
cristy4c08aed2011-07-01 19:47:50 +00006168 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00006169 break;
6170 for (x=0; x < (int) canvas->columns; x++)
6171 {
cristy4c08aed2011-07-01 19:47:50 +00006172 pixel=XGammaPixel(canvas,map_info,p);
cristy3ed852e2009-09-05 21:47:34 +00006173 pixel&=0xf;
6174 switch (nibble)
6175 {
6176 case 0:
6177 {
6178 *q=(unsigned char) pixel;
6179 nibble++;
6180 break;
6181 }
6182 case 1:
6183 {
6184 *q|=(unsigned char) (pixel << 2);
6185 nibble++;
6186 break;
6187 }
6188 case 2:
6189 {
6190 *q|=(unsigned char) (pixel << 4);
6191 nibble++;
6192 break;
6193 }
6194 case 3:
6195 {
6196 *q|=(unsigned char) (pixel << 6);
6197 q++;
6198 nibble=0;
6199 break;
6200 }
6201 }
cristyed231572011-07-14 02:18:59 +00006202 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00006203 }
6204 q+=scanline_pad;
6205 }
6206 break;
6207 }
6208 case 4:
6209 {
6210 register unsigned int
6211 nibble;
6212
6213 /*
6214 Convert to contiguous 4 bit continuous-tone X canvas.
6215 */
6216 for (y=0; y < (int) canvas->rows; y++)
6217 {
cristyc57f6942010-11-12 01:47:39 +00006218 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
6219 canvas->columns,1,&canvas->exception);
cristy4c08aed2011-07-01 19:47:50 +00006220 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00006221 break;
6222 nibble=0;
6223 for (x=0; x < (int) canvas->columns; x++)
6224 {
cristy4c08aed2011-07-01 19:47:50 +00006225 pixel=XGammaPixel(canvas,map_info,p);
cristy3ed852e2009-09-05 21:47:34 +00006226 pixel&=0xf;
6227 switch (nibble)
6228 {
6229 case 0:
6230 {
6231 *q=(unsigned char) pixel;
6232 nibble++;
6233 break;
6234 }
6235 case 1:
6236 {
6237 *q|=(unsigned char) (pixel << 4);
6238 q++;
6239 nibble=0;
6240 break;
6241 }
6242 }
cristyed231572011-07-14 02:18:59 +00006243 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00006244 }
6245 q+=scanline_pad;
6246 }
6247 break;
6248 }
6249 case 6:
6250 case 8:
6251 {
6252 /*
6253 Convert to contiguous 8 bit continuous-tone X canvas.
6254 */
6255 if (resource_info->color_recovery &&
6256 resource_info->quantize_info->dither)
6257 {
6258 XDitherImage(canvas,ximage);
6259 break;
6260 }
6261 for (y=0; y < (int) canvas->rows; y++)
6262 {
cristyc57f6942010-11-12 01:47:39 +00006263 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
6264 canvas->columns,1,&canvas->exception);
cristy4c08aed2011-07-01 19:47:50 +00006265 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00006266 break;
6267 for (x=0; x < (int) canvas->columns; x++)
6268 {
cristy4c08aed2011-07-01 19:47:50 +00006269 pixel=XGammaPixel(canvas,map_info,p);
cristy3ed852e2009-09-05 21:47:34 +00006270 *q++=(unsigned char) pixel;
cristyed231572011-07-14 02:18:59 +00006271 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00006272 }
6273 q+=scanline_pad;
6274 }
6275 break;
6276 }
6277 default:
6278 {
6279 if ((ximage->bits_per_pixel == 32) && (map_info->red_max == 255) &&
6280 (map_info->green_max == 255) && (map_info->blue_max == 255) &&
6281 (map_info->red_mult == 65536L) && (map_info->green_mult == 256) &&
6282 (map_info->blue_mult == 1))
6283 {
6284 /*
6285 Convert to 32 bit continuous-tone X canvas.
6286 */
6287 for (y=0; y < (int) canvas->rows; y++)
6288 {
cristyc57f6942010-11-12 01:47:39 +00006289 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
6290 canvas->columns,1,&canvas->exception);
cristy4c08aed2011-07-01 19:47:50 +00006291 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00006292 break;
6293 if ((red_gamma != 1.0) || (green_gamma != 1.0) ||
6294 (blue_gamma != 1.0))
6295 {
6296 /*
6297 Gamma correct canvas.
6298 */
6299 for (x=(int) canvas->columns-1; x >= 0; x--)
6300 {
cristyccf844f2010-02-03 23:28:16 +00006301 *q++=ScaleQuantumToChar(XBlueGamma(
cristy4c08aed2011-07-01 19:47:50 +00006302 GetPixelBlue(canvas,p)));
cristyccf844f2010-02-03 23:28:16 +00006303 *q++=ScaleQuantumToChar(XGreenGamma(
cristy4c08aed2011-07-01 19:47:50 +00006304 GetPixelGreen(canvas,p)));
cristyccf844f2010-02-03 23:28:16 +00006305 *q++=ScaleQuantumToChar(XRedGamma(
cristy4c08aed2011-07-01 19:47:50 +00006306 GetPixelRed(canvas,p)));
cristy3ed852e2009-09-05 21:47:34 +00006307 *q++=0;
cristyed231572011-07-14 02:18:59 +00006308 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00006309 }
6310 continue;
6311 }
6312 for (x=(int) canvas->columns-1; x >= 0; x--)
6313 {
cristy4c08aed2011-07-01 19:47:50 +00006314 *q++=ScaleQuantumToChar((Quantum)
6315 GetPixelBlue(canvas,p));
6316 *q++=ScaleQuantumToChar((Quantum)
6317 GetPixelGreen(canvas,p));
6318 *q++=ScaleQuantumToChar((Quantum)
6319 GetPixelRed(canvas,p));
cristy3ed852e2009-09-05 21:47:34 +00006320 *q++=0;
cristyed231572011-07-14 02:18:59 +00006321 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00006322 }
6323 }
6324 }
6325 else
6326 if ((ximage->bits_per_pixel == 32) && (map_info->red_max == 255) &&
6327 (map_info->green_max == 255) && (map_info->blue_max == 255) &&
6328 (map_info->red_mult == 1) && (map_info->green_mult == 256) &&
6329 (map_info->blue_mult == 65536L))
6330 {
6331 /*
6332 Convert to 32 bit continuous-tone X canvas.
6333 */
6334 for (y=0; y < (int) canvas->rows; y++)
6335 {
cristyc57f6942010-11-12 01:47:39 +00006336 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
6337 canvas->columns,1,&canvas->exception);
cristy4c08aed2011-07-01 19:47:50 +00006338 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00006339 break;
6340 if ((red_gamma != 1.0) || (green_gamma != 1.0) ||
6341 (blue_gamma != 1.0))
6342 {
6343 /*
6344 Gamma correct canvas.
6345 */
6346 for (x=(int) canvas->columns-1; x >= 0; x--)
6347 {
cristyccf844f2010-02-03 23:28:16 +00006348 *q++=ScaleQuantumToChar(XRedGamma(
cristy4c08aed2011-07-01 19:47:50 +00006349 GetPixelRed(canvas,p)));
cristyccf844f2010-02-03 23:28:16 +00006350 *q++=ScaleQuantumToChar(XGreenGamma(
cristy4c08aed2011-07-01 19:47:50 +00006351 GetPixelGreen(canvas,p)));
cristyccf844f2010-02-03 23:28:16 +00006352 *q++=ScaleQuantumToChar(XBlueGamma(
cristy4c08aed2011-07-01 19:47:50 +00006353 GetPixelBlue(canvas,p)));
cristy3ed852e2009-09-05 21:47:34 +00006354 *q++=0;
cristyed231572011-07-14 02:18:59 +00006355 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00006356 }
6357 continue;
6358 }
6359 for (x=(int) canvas->columns-1; x >= 0; x--)
6360 {
cristyccf844f2010-02-03 23:28:16 +00006361 *q++=ScaleQuantumToChar((Quantum)
cristy4c08aed2011-07-01 19:47:50 +00006362 GetPixelRed(canvas,p));
cristyccf844f2010-02-03 23:28:16 +00006363 *q++=ScaleQuantumToChar((Quantum)
cristy4c08aed2011-07-01 19:47:50 +00006364 GetPixelGreen(canvas,p));
cristyccf844f2010-02-03 23:28:16 +00006365 *q++=ScaleQuantumToChar((Quantum)
cristy4c08aed2011-07-01 19:47:50 +00006366 GetPixelBlue(canvas,p));
cristy3ed852e2009-09-05 21:47:34 +00006367 *q++=0;
cristyed231572011-07-14 02:18:59 +00006368 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00006369 }
6370 }
6371 }
6372 else
6373 {
6374 register int
6375 k;
6376
6377 register unsigned int
6378 bytes_per_pixel;
6379
6380 unsigned char
cristybb503372010-05-27 20:51:26 +00006381 channel[sizeof(size_t)];
cristy3ed852e2009-09-05 21:47:34 +00006382
6383 /*
6384 Convert to multi-byte continuous-tone X canvas.
6385 */
6386 bytes_per_pixel=(unsigned int) (ximage->bits_per_pixel >> 3);
6387 for (y=0; y < (int) canvas->rows; y++)
6388 {
cristyc57f6942010-11-12 01:47:39 +00006389 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
6390 canvas->columns,1,&canvas->exception);
cristy4c08aed2011-07-01 19:47:50 +00006391 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00006392 break;
cristyc57f6942010-11-12 01:47:39 +00006393 for (x=0; x < (int) canvas->columns; x++)
cristy3ed852e2009-09-05 21:47:34 +00006394 {
cristy4c08aed2011-07-01 19:47:50 +00006395 pixel=XGammaPixel(canvas,map_info,p);
cristy3ed852e2009-09-05 21:47:34 +00006396 for (k=0; k < (int) bytes_per_pixel; k++)
6397 {
6398 channel[k]=(unsigned char) pixel;
6399 pixel>>=8;
6400 }
6401 for (k=0; k < (int) bytes_per_pixel; k++)
6402 *q++=channel[k];
cristyed231572011-07-14 02:18:59 +00006403 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00006404 }
6405 q+=scanline_pad;
6406 }
6407 }
6408 break;
6409 }
6410 }
6411 if (matte_image != (XImage *) NULL)
6412 {
6413 /*
6414 Initialize matte canvas.
6415 */
6416 scanline_pad=(unsigned int) (matte_image->bytes_per_line-
6417 ((matte_image->width*matte_image->bits_per_pixel) >> 3));
6418 q=(unsigned char *) matte_image->data;
6419 for (y=0; y < (int) canvas->rows; y++)
6420 {
cristyc57f6942010-11-12 01:47:39 +00006421 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,canvas->columns,1,
6422 &canvas->exception);
cristy4c08aed2011-07-01 19:47:50 +00006423 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00006424 break;
6425 bit=0;
6426 byte=0;
6427 for (x=(int) canvas->columns-1; x >= 0; x--)
6428 {
6429 byte>>=1;
cristy4c08aed2011-07-01 19:47:50 +00006430 if (GetPixelAlpha(canvas,p) > (QuantumRange/2))
cristy3ed852e2009-09-05 21:47:34 +00006431 byte|=0x80;
6432 bit++;
6433 if (bit == 8)
6434 {
6435 *q++=byte;
6436 bit=0;
6437 byte=0;
6438 }
cristyed231572011-07-14 02:18:59 +00006439 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00006440 }
6441 if (bit != 0)
6442 *q=byte >> (8-bit);
6443 q+=scanline_pad;
6444 }
6445 }
cristyc57f6942010-11-12 01:47:39 +00006446 canvas_view=DestroyCacheView(canvas_view);
cristy3ed852e2009-09-05 21:47:34 +00006447 if (canvas != image)
6448 canvas=DestroyImage(canvas);
6449}
6450
6451/*
6452%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
6453% %
6454% %
6455% %
6456+ X M a k e I m a g e M S B F i r s t %
6457% %
6458% %
6459% %
6460%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
6461%
6462% XMakeImageMSBFirst() initializes the pixel data of an X11 Image. The X
6463% image pixels are copied in most-significant bit and byte first order. The
6464% server's scanline pad is also respected. Rather than using one or two
6465% general cases, many special cases are found here to help speed up the image
6466% conversion.
6467%
6468% The format of the XMakeImageMSBFirst method is:
6469%
6470% XMakeImageMSBFirst(resource_info,window,image,ximage,matte_image)
6471%
6472% A description of each parameter follows:
6473%
6474% o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
6475%
6476% o window: Specifies a pointer to a XWindowInfo structure.
6477%
6478% o image: the image.
6479%
6480% o ximage: Specifies a pointer to a XImage structure; returned from
6481% XCreateImage.
6482%
6483% o matte_image: Specifies a pointer to a XImage structure; returned from
6484% XCreateImage.
6485%
cristy3ed852e2009-09-05 21:47:34 +00006486*/
6487static void XMakeImageMSBFirst(const XResourceInfo *resource_info,
6488 const XWindowInfo *window,Image *image,XImage *ximage,XImage *matte_image)
6489{
cristyc57f6942010-11-12 01:47:39 +00006490 CacheView
6491 *canvas_view;
6492
cristy3ed852e2009-09-05 21:47:34 +00006493 Image
6494 *canvas;
6495
6496 int
6497 y;
6498
6499 register int
6500 x;
6501
cristy4c08aed2011-07-01 19:47:50 +00006502 register const Quantum
cristy3ed852e2009-09-05 21:47:34 +00006503 *p;
6504
6505 register unsigned char
6506 *q;
6507
6508 unsigned char
6509 bit,
6510 byte;
6511
6512 unsigned int
6513 scanline_pad;
6514
cristyf2faecf2010-05-28 19:19:36 +00006515 unsigned long
cristy3ed852e2009-09-05 21:47:34 +00006516 pixel,
6517 *pixels;
6518
6519 XStandardColormap
6520 *map_info;
6521
6522 assert(resource_info != (XResourceInfo *) NULL);
6523 assert(window != (XWindowInfo *) NULL);
6524 assert(image != (Image *) NULL);
6525 if (image->debug != MagickFalse)
6526 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
6527 canvas=image;
cristy54666e82010-02-03 23:34:26 +00006528 if ((window->immutable != MagickFalse) &&
6529 (image->storage_class == DirectClass) && (image->matte != MagickFalse))
cristy3ed852e2009-09-05 21:47:34 +00006530 {
6531 char
6532 size[MaxTextExtent];
6533
6534 Image
6535 *pattern;
6536
6537 ImageInfo
6538 *image_info;
6539
6540 image_info=AcquireImageInfo();
6541 (void) CopyMagickString(image_info->filename,
6542 resource_info->image_info->texture != (char *) NULL ?
6543 resource_info->image_info->texture : "pattern:checkerboard",
6544 MaxTextExtent);
cristyb51dff52011-05-19 16:55:47 +00006545 (void) FormatLocaleString(size,MaxTextExtent,"%.20gx%.20g",(double)
cristye8c25f92010-06-03 00:53:06 +00006546 image->columns,(double) image->rows);
cristy3ed852e2009-09-05 21:47:34 +00006547 image_info->size=ConstantString(size);
6548 pattern=ReadImage(image_info,&image->exception);
6549 image_info=DestroyImageInfo(image_info);
6550 if (pattern != (Image *) NULL)
6551 {
6552 canvas=CloneImage(image,0,0,MagickTrue,&image->exception);
6553 if (canvas != (Image *) NULL)
6554 (void) CompositeImage(canvas,DstOverCompositeOp,pattern,0,0);
6555 pattern=DestroyImage(pattern);
6556 }
6557 }
cristy4c08aed2011-07-01 19:47:50 +00006558 scanline_pad=(unsigned int) (ximage->bytes_per_line-((ximage->width*
6559 ximage->bits_per_pixel) >> 3));
cristy3ed852e2009-09-05 21:47:34 +00006560 map_info=window->map_info;
6561 pixels=window->pixel_info->pixels;
6562 q=(unsigned char *) ximage->data;
6563 x=0;
cristyc57f6942010-11-12 01:47:39 +00006564 canvas_view=AcquireCacheView(canvas);
cristy3ed852e2009-09-05 21:47:34 +00006565 if (ximage->format == XYBitmap)
6566 {
6567 register unsigned short
6568 polarity;
6569
6570 unsigned char
6571 background,
6572 foreground;
6573
6574 /*
6575 Convert canvas to big-endian bitmap.
6576 */
6577 background=(unsigned char)
6578 (XPixelIntensity(&window->pixel_info->foreground_color) <
6579 XPixelIntensity(&window->pixel_info->background_color) ? 0x01 : 0x00);
6580 foreground=(unsigned char)
6581 (XPixelIntensity(&window->pixel_info->background_color) <
6582 XPixelIntensity(&window->pixel_info->foreground_color) ? 0x01 : 0x00);
cristy4c08aed2011-07-01 19:47:50 +00006583 polarity=(unsigned short) ((GetPixelPacketIntensity(
cristy3ed852e2009-09-05 21:47:34 +00006584 &canvas->colormap[0])) < ((Quantum) QuantumRange/2) ? 1 : 0);
6585 if (canvas->colors == 2)
cristy4c08aed2011-07-01 19:47:50 +00006586 polarity=GetPixelPacketIntensity(&canvas->colormap[0]) <
6587 GetPixelPacketIntensity(&canvas->colormap[1]);
cristy3ed852e2009-09-05 21:47:34 +00006588 for (y=0; y < (int) canvas->rows; y++)
6589 {
cristyc57f6942010-11-12 01:47:39 +00006590 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,canvas->columns,1,
6591 &canvas->exception);
cristy4c08aed2011-07-01 19:47:50 +00006592 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00006593 break;
cristy3ed852e2009-09-05 21:47:34 +00006594 bit=0;
6595 byte=0;
6596 for (x=(int) canvas->columns-1; x >= 0; x--)
6597 {
6598 byte<<=1;
cristy4c08aed2011-07-01 19:47:50 +00006599 if (GetPixelIndex(canvas,p) == (Quantum) polarity)
cristy3ed852e2009-09-05 21:47:34 +00006600 byte|=foreground;
6601 else
6602 byte|=background;
6603 bit++;
6604 if (bit == 8)
6605 {
6606 *q++=byte;
6607 bit=0;
6608 byte=0;
6609 }
cristyed231572011-07-14 02:18:59 +00006610 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00006611 }
6612 if (bit != 0)
6613 *q=byte << (8-bit);
6614 q+=scanline_pad;
6615 }
6616 }
6617 else
6618 if (window->pixel_info->colors != 0)
6619 switch (ximage->bits_per_pixel)
6620 {
6621 case 2:
6622 {
6623 register unsigned int
6624 nibble;
6625
6626 /*
6627 Convert to 2 bit color-mapped X canvas.
6628 */
6629 for (y=0; y < (int) canvas->rows; y++)
6630 {
cristyc57f6942010-11-12 01:47:39 +00006631 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
6632 canvas->columns,1,&canvas->exception);
cristy4c08aed2011-07-01 19:47:50 +00006633 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00006634 break;
cristy3ed852e2009-09-05 21:47:34 +00006635 nibble=0;
6636 for (x=0; x < (int) canvas->columns; x++)
6637 {
cristy4c08aed2011-07-01 19:47:50 +00006638 pixel=pixels[(ssize_t)
6639 GetPixelIndex(canvas,p)] & 0xf;
cristy3ed852e2009-09-05 21:47:34 +00006640 switch (nibble)
6641 {
6642 case 0:
6643 {
6644 *q=(unsigned char) (pixel << 6);
6645 nibble++;
6646 break;
6647 }
6648 case 1:
6649 {
6650 *q|=(unsigned char) (pixel << 4);
6651 nibble++;
6652 break;
6653 }
6654 case 2:
6655 {
6656 *q|=(unsigned char) (pixel << 2);
6657 nibble++;
6658 break;
6659 }
6660 case 3:
6661 {
6662 *q|=(unsigned char) pixel;
6663 q++;
6664 nibble=0;
6665 break;
6666 }
6667 }
cristyed231572011-07-14 02:18:59 +00006668 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00006669 }
6670 q+=scanline_pad;
6671 }
6672 break;
6673 }
6674 case 4:
6675 {
6676 register unsigned int
6677 nibble;
6678
6679 /*
6680 Convert to 4 bit color-mapped X canvas.
6681 */
6682 for (y=0; y < (int) canvas->rows; y++)
6683 {
cristyc57f6942010-11-12 01:47:39 +00006684 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
6685 canvas->columns,1,&canvas->exception);
cristy4c08aed2011-07-01 19:47:50 +00006686 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00006687 break;
cristy3ed852e2009-09-05 21:47:34 +00006688 nibble=0;
6689 for (x=0; x < (int) canvas->columns; x++)
6690 {
cristy4c08aed2011-07-01 19:47:50 +00006691 pixel=pixels[(ssize_t)
6692 GetPixelIndex(canvas,p)] & 0xf;
cristy3ed852e2009-09-05 21:47:34 +00006693 switch (nibble)
6694 {
6695 case 0:
6696 {
6697 *q=(unsigned char) (pixel << 4);
6698 nibble++;
6699 break;
6700 }
6701 case 1:
6702 {
6703 *q|=(unsigned char) pixel;
6704 q++;
6705 nibble=0;
6706 break;
6707 }
6708 }
cristyed231572011-07-14 02:18:59 +00006709 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00006710 }
6711 q+=scanline_pad;
6712 }
6713 break;
6714 }
6715 case 6:
6716 case 8:
6717 {
6718 /*
6719 Convert to 8 bit color-mapped X canvas.
6720 */
6721 if (resource_info->color_recovery &&
6722 resource_info->quantize_info->dither)
6723 {
6724 XDitherImage(canvas,ximage);
6725 break;
6726 }
6727 for (y=0; y < (int) canvas->rows; y++)
6728 {
cristyc57f6942010-11-12 01:47:39 +00006729 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
6730 canvas->columns,1,&canvas->exception);
cristy4c08aed2011-07-01 19:47:50 +00006731 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00006732 break;
cristy3ed852e2009-09-05 21:47:34 +00006733 for (x=0; x < (int) canvas->columns; x++)
6734 {
cristy4c08aed2011-07-01 19:47:50 +00006735 pixel=pixels[(ssize_t)
6736 GetPixelIndex(canvas,p)];
cristy3ed852e2009-09-05 21:47:34 +00006737 *q++=(unsigned char) pixel;
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 default:
6745 {
6746 register int
6747 k;
6748
6749 register unsigned int
6750 bytes_per_pixel;
6751
6752 unsigned char
cristybb503372010-05-27 20:51:26 +00006753 channel[sizeof(size_t)];
cristy3ed852e2009-09-05 21:47:34 +00006754
6755 /*
6756 Convert to 8 bit color-mapped X canvas.
6757 */
6758 bytes_per_pixel=(unsigned int) (ximage->bits_per_pixel >> 3);
6759 for (y=0; y < (int) canvas->rows; y++)
6760 {
cristyc57f6942010-11-12 01:47:39 +00006761 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
6762 canvas->columns,1,&canvas->exception);
cristy4c08aed2011-07-01 19:47:50 +00006763 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00006764 break;
cristy3ed852e2009-09-05 21:47:34 +00006765 for (x=0; x < (int) canvas->columns; x++)
6766 {
cristy4c08aed2011-07-01 19:47:50 +00006767 pixel=pixels[(ssize_t)
6768 GetPixelIndex(canvas,p)];
cristy3ed852e2009-09-05 21:47:34 +00006769 for (k=(int) bytes_per_pixel-1; k >= 0; k--)
6770 {
6771 channel[k]=(unsigned char) pixel;
6772 pixel>>=8;
6773 }
6774 for (k=0; k < (int) bytes_per_pixel; k++)
6775 *q++=channel[k];
cristyed231572011-07-14 02:18:59 +00006776 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00006777 }
6778 q+=scanline_pad;
6779 }
6780 break;
6781 }
6782 }
6783 else
6784 switch (ximage->bits_per_pixel)
6785 {
6786 case 2:
6787 {
6788 register unsigned int
6789 nibble;
6790
6791 /*
6792 Convert to 4 bit continuous-tone X canvas.
6793 */
6794 for (y=0; y < (int) canvas->rows; y++)
6795 {
cristyc57f6942010-11-12 01:47:39 +00006796 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
6797 canvas->columns,1,&canvas->exception);
cristy4c08aed2011-07-01 19:47:50 +00006798 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00006799 break;
6800 nibble=0;
6801 for (x=(int) canvas->columns-1; x >= 0; x--)
6802 {
cristy4c08aed2011-07-01 19:47:50 +00006803 pixel=XGammaPixel(canvas,map_info,p);
cristy3ed852e2009-09-05 21:47:34 +00006804 pixel&=0xf;
6805 switch (nibble)
6806 {
6807 case 0:
6808 {
6809 *q=(unsigned char) (pixel << 6);
6810 nibble++;
6811 break;
6812 }
6813 case 1:
6814 {
6815 *q|=(unsigned char) (pixel << 4);
6816 nibble++;
6817 break;
6818 }
6819 case 2:
6820 {
6821 *q|=(unsigned char) (pixel << 2);
6822 nibble++;
6823 break;
6824 }
6825 case 3:
6826 {
6827 *q|=(unsigned char) pixel;
6828 q++;
6829 nibble=0;
6830 break;
6831 }
6832 }
cristyed231572011-07-14 02:18:59 +00006833 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00006834 }
6835 q+=scanline_pad;
6836 }
6837 break;
6838 }
6839 case 4:
6840 {
6841 register unsigned int
6842 nibble;
6843
6844 /*
6845 Convert to 4 bit continuous-tone X canvas.
6846 */
6847 for (y=0; y < (int) canvas->rows; y++)
6848 {
cristyc57f6942010-11-12 01:47:39 +00006849 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
6850 canvas->columns,1,&canvas->exception);
cristy4c08aed2011-07-01 19:47:50 +00006851 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00006852 break;
6853 nibble=0;
6854 for (x=(int) canvas->columns-1; x >= 0; x--)
6855 {
cristy4c08aed2011-07-01 19:47:50 +00006856 pixel=XGammaPixel(canvas,map_info,p);
cristy3ed852e2009-09-05 21:47:34 +00006857 pixel&=0xf;
6858 switch (nibble)
6859 {
6860 case 0:
6861 {
6862 *q=(unsigned char) (pixel << 4);
6863 nibble++;
6864 break;
6865 }
6866 case 1:
6867 {
6868 *q|=(unsigned char) pixel;
6869 q++;
6870 nibble=0;
6871 break;
6872 }
6873 }
cristyed231572011-07-14 02:18:59 +00006874 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00006875 }
6876 q+=scanline_pad;
6877 }
6878 break;
6879 }
6880 case 6:
6881 case 8:
6882 {
6883 /*
6884 Convert to 8 bit continuous-tone X canvas.
6885 */
6886 if (resource_info->color_recovery &&
6887 resource_info->quantize_info->dither)
6888 {
6889 XDitherImage(canvas,ximage);
6890 break;
6891 }
6892 for (y=0; y < (int) canvas->rows; y++)
6893 {
cristyc57f6942010-11-12 01:47:39 +00006894 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
6895 canvas->columns,1,&canvas->exception);
cristy4c08aed2011-07-01 19:47:50 +00006896 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00006897 break;
6898 for (x=(int) canvas->columns-1; x >= 0; x--)
6899 {
cristy4c08aed2011-07-01 19:47:50 +00006900 pixel=XGammaPixel(canvas,map_info,p);
cristy3ed852e2009-09-05 21:47:34 +00006901 *q++=(unsigned char) pixel;
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 default:
6909 {
6910 if ((ximage->bits_per_pixel == 32) && (map_info->red_max == 255) &&
6911 (map_info->green_max == 255) && (map_info->blue_max == 255) &&
6912 (map_info->red_mult == 65536L) && (map_info->green_mult == 256) &&
6913 (map_info->blue_mult == 1))
6914 {
6915 /*
6916 Convert to 32 bit continuous-tone X canvas.
6917 */
6918 for (y=0; y < (int) canvas->rows; y++)
6919 {
cristyc57f6942010-11-12 01:47:39 +00006920 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
6921 canvas->columns,1,&canvas->exception);
cristy4c08aed2011-07-01 19:47:50 +00006922 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00006923 break;
6924 if ((red_gamma != 1.0) || (green_gamma != 1.0) ||
6925 (blue_gamma != 1.0))
6926 {
6927 /*
6928 Gamma correct canvas.
6929 */
6930 for (x=(int) canvas->columns-1; x >= 0; x--)
6931 {
6932 *q++=0;
cristyccf844f2010-02-03 23:28:16 +00006933 *q++=ScaleQuantumToChar(XRedGamma(
cristy4c08aed2011-07-01 19:47:50 +00006934 GetPixelRed(canvas,p)));
cristyccf844f2010-02-03 23:28:16 +00006935 *q++=ScaleQuantumToChar(XGreenGamma(
cristy4c08aed2011-07-01 19:47:50 +00006936 GetPixelGreen(canvas,p)));
cristyccf844f2010-02-03 23:28:16 +00006937 *q++=ScaleQuantumToChar(XBlueGamma(
cristy4c08aed2011-07-01 19:47:50 +00006938 GetPixelBlue(canvas,p)));
cristyed231572011-07-14 02:18:59 +00006939 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00006940 }
6941 continue;
6942 }
6943 for (x=(int) canvas->columns-1; x >= 0; x--)
6944 {
6945 *q++=0;
cristy4c08aed2011-07-01 19:47:50 +00006946 *q++=ScaleQuantumToChar((Quantum)
6947 GetPixelRed(canvas,p));
6948 *q++=ScaleQuantumToChar((Quantum)
6949 GetPixelGreen(canvas,p));
6950 *q++=ScaleQuantumToChar((Quantum)
6951 GetPixelBlue(canvas,p));
cristyed231572011-07-14 02:18:59 +00006952 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00006953 }
6954 }
6955 }
6956 else
6957 if ((ximage->bits_per_pixel == 32) && (map_info->red_max == 255) &&
6958 (map_info->green_max == 255) && (map_info->blue_max == 255) &&
6959 (map_info->red_mult == 1) && (map_info->green_mult == 256) &&
6960 (map_info->blue_mult == 65536L))
6961 {
6962 /*
6963 Convert to 32 bit continuous-tone X canvas.
6964 */
6965 for (y=0; y < (int) canvas->rows; y++)
6966 {
cristyc57f6942010-11-12 01:47:39 +00006967 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
6968 canvas->columns,1,&canvas->exception);
cristy4c08aed2011-07-01 19:47:50 +00006969 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00006970 break;
6971 if ((red_gamma != 1.0) || (green_gamma != 1.0) ||
6972 (blue_gamma != 1.0))
6973 {
6974 /*
6975 Gamma correct canvas.
6976 */
6977 for (x=(int) canvas->columns-1; x >= 0; x--)
6978 {
6979 *q++=0;
cristyccf844f2010-02-03 23:28:16 +00006980 *q++=ScaleQuantumToChar(XBlueGamma(
cristy4c08aed2011-07-01 19:47:50 +00006981 GetPixelBlue(canvas,p)));
cristyccf844f2010-02-03 23:28:16 +00006982 *q++=ScaleQuantumToChar(XGreenGamma(
cristy4c08aed2011-07-01 19:47:50 +00006983 GetPixelGreen(canvas,p)));
cristyccf844f2010-02-03 23:28:16 +00006984 *q++=ScaleQuantumToChar(XRedGamma(
cristy4c08aed2011-07-01 19:47:50 +00006985 GetPixelRed(canvas,p)));
cristyed231572011-07-14 02:18:59 +00006986 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00006987 }
6988 continue;
6989 }
6990 for (x=(int) canvas->columns-1; x >= 0; x--)
6991 {
6992 *q++=0;
cristyccf844f2010-02-03 23:28:16 +00006993 *q++=ScaleQuantumToChar((Quantum)
cristy4c08aed2011-07-01 19:47:50 +00006994 GetPixelBlue(canvas,p));
cristyccf844f2010-02-03 23:28:16 +00006995 *q++=ScaleQuantumToChar((Quantum)
cristy4c08aed2011-07-01 19:47:50 +00006996 GetPixelGreen(canvas,p));
cristyccf844f2010-02-03 23:28:16 +00006997 *q++=ScaleQuantumToChar((Quantum)
cristy4c08aed2011-07-01 19:47:50 +00006998 GetPixelRed(canvas,p));
cristyed231572011-07-14 02:18:59 +00006999 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00007000 }
7001 }
7002 }
7003 else
7004 {
7005 register int
7006 k;
7007
7008 register unsigned int
7009 bytes_per_pixel;
7010
7011 unsigned char
cristybb503372010-05-27 20:51:26 +00007012 channel[sizeof(size_t)];
cristy3ed852e2009-09-05 21:47:34 +00007013
7014 /*
7015 Convert to multi-byte continuous-tone X canvas.
7016 */
7017 bytes_per_pixel=(unsigned int) (ximage->bits_per_pixel >> 3);
7018 for (y=0; y < (int) canvas->rows; y++)
7019 {
cristyc57f6942010-11-12 01:47:39 +00007020 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
7021 canvas->columns,1,&canvas->exception);
cristy4c08aed2011-07-01 19:47:50 +00007022 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00007023 break;
7024 for (x=(int) canvas->columns-1; x >= 0; x--)
7025 {
cristy4c08aed2011-07-01 19:47:50 +00007026 pixel=XGammaPixel(canvas,map_info,p);
cristy3ed852e2009-09-05 21:47:34 +00007027 for (k=(int) bytes_per_pixel-1; k >= 0; k--)
7028 {
7029 channel[k]=(unsigned char) pixel;
7030 pixel>>=8;
7031 }
7032 for (k=0; k < (int) bytes_per_pixel; k++)
7033 *q++=channel[k];
cristyed231572011-07-14 02:18:59 +00007034 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00007035 }
7036 q+=scanline_pad;
7037 }
7038 }
7039 break;
7040 }
7041 }
7042 if (matte_image != (XImage *) NULL)
7043 {
7044 /*
7045 Initialize matte canvas.
7046 */
7047 scanline_pad=(unsigned int) (matte_image->bytes_per_line-
7048 ((matte_image->width*matte_image->bits_per_pixel) >> 3));
7049 q=(unsigned char *) matte_image->data;
7050 for (y=0; y < (int) canvas->rows; y++)
7051 {
cristyc57f6942010-11-12 01:47:39 +00007052 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,canvas->columns,1,
7053 &canvas->exception);
cristy4c08aed2011-07-01 19:47:50 +00007054 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00007055 break;
7056 bit=0;
7057 byte=0;
7058 for (x=(int) canvas->columns-1; x >= 0; x--)
7059 {
7060 byte<<=1;
cristy4c08aed2011-07-01 19:47:50 +00007061 if (GetPixelAlpha(canvas,p) > (QuantumRange/2))
cristy3ed852e2009-09-05 21:47:34 +00007062 byte|=0x01;
7063 bit++;
7064 if (bit == 8)
7065 {
7066 *q++=byte;
7067 bit=0;
7068 byte=0;
7069 }
cristyed231572011-07-14 02:18:59 +00007070 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00007071 }
7072 if (bit != 0)
7073 *q=byte << (8-bit);
7074 q+=scanline_pad;
7075 }
7076 }
cristyc57f6942010-11-12 01:47:39 +00007077 canvas_view=DestroyCacheView(canvas_view);
cristy3ed852e2009-09-05 21:47:34 +00007078 if (canvas != image)
7079 canvas=DestroyImage(canvas);
7080}
7081
7082/*
7083%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
7084% %
7085% %
7086% %
7087% X M a k e M a g n i f y I m a g e %
7088% %
7089% %
7090% %
7091%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
7092%
7093% XMakeMagnifyImage() magnifies a region of an X image and displays it.
7094%
7095% The format of the XMakeMagnifyImage method is:
7096%
7097% void XMakeMagnifyImage(display,windows)
7098%
7099% A description of each parameter follows:
7100%
7101% o display: Specifies a connection to an X server; returned from
7102% XOpenDisplay.
7103%
7104% o windows: Specifies a pointer to a XWindows structure.
7105%
7106*/
cristybcbda3f2011-09-03 13:01:22 +00007107MagickPrivate void XMakeMagnifyImage(Display *display,XWindows *windows)
cristy3ed852e2009-09-05 21:47:34 +00007108{
7109 char
7110 tuple[MaxTextExtent];
7111
7112 int
7113 y;
7114
cristy4c08aed2011-07-01 19:47:50 +00007115 PixelInfo
cristy3ed852e2009-09-05 21:47:34 +00007116 pixel;
7117
7118 register int
7119 x;
7120
cristybb503372010-05-27 20:51:26 +00007121 register ssize_t
cristy3ed852e2009-09-05 21:47:34 +00007122 i;
7123
7124 register unsigned char
7125 *p,
7126 *q;
7127
cristy9d314ff2011-03-09 01:30:28 +00007128 ssize_t
7129 n;
7130
cristy3ed852e2009-09-05 21:47:34 +00007131 static unsigned int
7132 previous_magnify = 0;
7133
7134 static XWindowInfo
7135 magnify_window;
7136
7137 unsigned int
7138 height,
7139 j,
7140 k,
7141 l,
7142 magnify,
7143 scanline_pad,
7144 width;
7145
7146 XImage
7147 *ximage;
7148
7149 /*
7150 Check boundary conditions.
7151 */
7152 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
7153 assert(display != (Display *) NULL);
7154 assert(windows != (XWindows *) NULL);
7155 magnify=1;
cristybb503372010-05-27 20:51:26 +00007156 for (n=1; n < (ssize_t) windows->magnify.data; n++)
cristy3ed852e2009-09-05 21:47:34 +00007157 magnify<<=1;
7158 while ((magnify*windows->image.ximage->width) < windows->magnify.width)
7159 magnify<<=1;
7160 while ((magnify*windows->image.ximage->height) < windows->magnify.height)
7161 magnify<<=1;
7162 while (magnify > windows->magnify.width)
7163 magnify>>=1;
7164 while (magnify > windows->magnify.height)
7165 magnify>>=1;
7166 if (magnify != previous_magnify)
7167 {
7168 Status
7169 status;
7170
7171 XTextProperty
7172 window_name;
7173
7174 /*
7175 New magnify factor: update magnify window name.
7176 */
7177 i=0;
7178 while ((1 << i) <= (int) magnify)
7179 i++;
cristyb51dff52011-05-19 16:55:47 +00007180 (void) FormatLocaleString(windows->magnify.name,MaxTextExtent,
cristye8c25f92010-06-03 00:53:06 +00007181 "Magnify %.20gX",(double) i);
cristy3ed852e2009-09-05 21:47:34 +00007182 status=XStringListToTextProperty(&windows->magnify.name,1,&window_name);
7183 if (status != False)
7184 {
7185 XSetWMName(display,windows->magnify.id,&window_name);
7186 XSetWMIconName(display,windows->magnify.id,&window_name);
7187 (void) XFree((void *) window_name.value);
7188 }
7189 }
7190 previous_magnify=magnify;
7191 ximage=windows->image.ximage;
7192 width=(unsigned int) windows->magnify.ximage->width;
7193 height=(unsigned int) windows->magnify.ximage->height;
7194 if ((windows->magnify.x < 0) ||
7195 (windows->magnify.x >= windows->image.ximage->width))
7196 windows->magnify.x=windows->image.ximage->width >> 1;
7197 x=windows->magnify.x-((width/magnify) >> 1);
7198 if (x < 0)
7199 x=0;
7200 else
7201 if (x > (int) (ximage->width-(width/magnify)))
7202 x=ximage->width-width/magnify;
7203 if ((windows->magnify.y < 0) ||
7204 (windows->magnify.y >= windows->image.ximage->height))
7205 windows->magnify.y=windows->image.ximage->height >> 1;
7206 y=windows->magnify.y-((height/magnify) >> 1);
7207 if (y < 0)
7208 y=0;
7209 else
7210 if (y > (int) (ximage->height-(height/magnify)))
7211 y=ximage->height-height/magnify;
7212 q=(unsigned char *) windows->magnify.ximage->data;
7213 scanline_pad=(unsigned int) (windows->magnify.ximage->bytes_per_line-
7214 ((width*windows->magnify.ximage->bits_per_pixel) >> 3));
7215 if (ximage->bits_per_pixel < 8)
7216 {
7217 register unsigned char
7218 background,
7219 byte,
7220 foreground,
7221 p_bit,
7222 q_bit;
7223
7224 register unsigned int
7225 plane;
7226
7227 XPixelInfo
7228 *pixel_info;
7229
7230 pixel_info=windows->magnify.pixel_info;
7231 switch (ximage->bitmap_bit_order)
7232 {
7233 case LSBFirst:
7234 {
7235 /*
7236 Magnify little-endian bitmap.
7237 */
7238 background=0x00;
7239 foreground=0x80;
7240 if (ximage->format == XYBitmap)
7241 {
7242 background=(unsigned char)
7243 (XPixelIntensity(&pixel_info->foreground_color) <
7244 XPixelIntensity(&pixel_info->background_color) ? 0x80 : 0x00);
7245 foreground=(unsigned char)
7246 (XPixelIntensity(&pixel_info->background_color) <
7247 XPixelIntensity(&pixel_info->foreground_color) ? 0x80 : 0x00);
7248 if (windows->magnify.depth > 1)
7249 Swap(background,foreground);
7250 }
cristybb503372010-05-27 20:51:26 +00007251 for (i=0; i < (ssize_t) height; i+=magnify)
cristy3ed852e2009-09-05 21:47:34 +00007252 {
7253 /*
7254 Propogate pixel magnify rows.
7255 */
7256 for (j=0; j < magnify; j++)
7257 {
7258 p=(unsigned char *) ximage->data+y*ximage->bytes_per_line+
7259 ((x*ximage->bits_per_pixel) >> 3);
7260 p_bit=(unsigned char) (x*ximage->bits_per_pixel) & 0x07;
7261 q_bit=0;
7262 byte=0;
7263 for (k=0; k < width; k+=magnify)
7264 {
7265 /*
7266 Propogate pixel magnify columns.
7267 */
7268 for (l=0; l < magnify; l++)
7269 {
7270 /*
7271 Propogate each bit plane.
7272 */
7273 for (plane=0; (int) plane < ximage->bits_per_pixel; plane++)
7274 {
7275 byte>>=1;
7276 if (*p & (0x01 << (p_bit+plane)))
7277 byte|=foreground;
7278 else
7279 byte|=background;
7280 q_bit++;
7281 if (q_bit == 8)
7282 {
7283 *q++=byte;
7284 q_bit=0;
7285 byte=0;
7286 }
7287 }
7288 }
7289 p_bit+=ximage->bits_per_pixel;
7290 if (p_bit == 8)
7291 {
7292 p++;
7293 p_bit=0;
7294 }
7295 if (q_bit != 0)
7296 *q=byte >> (8-q_bit);
7297 q+=scanline_pad;
7298 }
7299 }
7300 y++;
7301 }
7302 break;
7303 }
7304 case MSBFirst:
7305 default:
7306 {
7307 /*
7308 Magnify big-endian bitmap.
7309 */
7310 background=0x00;
7311 foreground=0x01;
7312 if (ximage->format == XYBitmap)
7313 {
7314 background=(unsigned char)
7315 (XPixelIntensity(&pixel_info->foreground_color) <
7316 XPixelIntensity(&pixel_info->background_color) ? 0x01 : 0x00);
7317 foreground=(unsigned char)
7318 (XPixelIntensity(&pixel_info->background_color) <
7319 XPixelIntensity(&pixel_info->foreground_color) ? 0x01 : 0x00);
7320 if (windows->magnify.depth > 1)
7321 Swap(background,foreground);
7322 }
cristybb503372010-05-27 20:51:26 +00007323 for (i=0; i < (ssize_t) height; i+=magnify)
cristy3ed852e2009-09-05 21:47:34 +00007324 {
7325 /*
7326 Propogate pixel magnify rows.
7327 */
7328 for (j=0; j < magnify; j++)
7329 {
7330 p=(unsigned char *) ximage->data+y*ximage->bytes_per_line+
7331 ((x*ximage->bits_per_pixel) >> 3);
7332 p_bit=(unsigned char) (x*ximage->bits_per_pixel) & 0x07;
7333 q_bit=0;
7334 byte=0;
7335 for (k=0; k < width; k+=magnify)
7336 {
7337 /*
7338 Propogate pixel magnify columns.
7339 */
7340 for (l=0; l < magnify; l++)
7341 {
7342 /*
7343 Propogate each bit plane.
7344 */
7345 for (plane=0; (int) plane < ximage->bits_per_pixel; plane++)
7346 {
7347 byte<<=1;
7348 if (*p & (0x80 >> (p_bit+plane)))
7349 byte|=foreground;
7350 else
7351 byte|=background;
7352 q_bit++;
7353 if (q_bit == 8)
7354 {
7355 *q++=byte;
7356 q_bit=0;
7357 byte=0;
7358 }
7359 }
7360 }
7361 p_bit+=ximage->bits_per_pixel;
7362 if (p_bit == 8)
7363 {
7364 p++;
7365 p_bit=0;
7366 }
7367 if (q_bit != 0)
7368 *q=byte << (8-q_bit);
7369 q+=scanline_pad;
7370 }
7371 }
7372 y++;
7373 }
7374 break;
7375 }
7376 }
7377 }
7378 else
7379 switch (ximage->bits_per_pixel)
7380 {
7381 case 6:
7382 case 8:
7383 {
7384 /*
7385 Magnify 8 bit X image.
7386 */
cristybb503372010-05-27 20:51:26 +00007387 for (i=0; i < (ssize_t) height; i+=magnify)
cristy3ed852e2009-09-05 21:47:34 +00007388 {
7389 /*
7390 Propogate pixel magnify rows.
7391 */
7392 for (j=0; j < magnify; j++)
7393 {
7394 p=(unsigned char *) ximage->data+y*ximage->bytes_per_line+
7395 ((x*ximage->bits_per_pixel) >> 3);
7396 for (k=0; k < width; k+=magnify)
7397 {
7398 /*
7399 Propogate pixel magnify columns.
7400 */
7401 for (l=0; l < magnify; l++)
7402 *q++=(*p);
7403 p++;
7404 }
7405 q+=scanline_pad;
7406 }
7407 y++;
7408 }
7409 break;
7410 }
7411 default:
7412 {
7413 register unsigned int
7414 bytes_per_pixel,
7415 m;
7416
7417 /*
7418 Magnify multi-byte X image.
7419 */
7420 bytes_per_pixel=(unsigned int) ximage->bits_per_pixel >> 3;
cristybb503372010-05-27 20:51:26 +00007421 for (i=0; i < (ssize_t) height; i+=magnify)
cristy3ed852e2009-09-05 21:47:34 +00007422 {
7423 /*
7424 Propogate pixel magnify rows.
7425 */
7426 for (j=0; j < magnify; j++)
7427 {
7428 p=(unsigned char *) ximage->data+y*ximage->bytes_per_line+
7429 ((x*ximage->bits_per_pixel) >> 3);
7430 for (k=0; k < width; k+=magnify)
7431 {
7432 /*
7433 Propogate pixel magnify columns.
7434 */
7435 for (l=0; l < magnify; l++)
7436 for (m=0; m < bytes_per_pixel; m++)
7437 *q++=(*(p+m));
7438 p+=bytes_per_pixel;
7439 }
7440 q+=scanline_pad;
7441 }
7442 y++;
7443 }
7444 break;
7445 }
7446 }
7447 /*
7448 Copy X image to magnify pixmap.
7449 */
7450 x=windows->magnify.x-((width/magnify) >> 1);
7451 if (x < 0)
7452 x=(int) ((width >> 1)-windows->magnify.x*magnify);
7453 else
7454 if (x > (int) (ximage->width-(width/magnify)))
7455 x=(int) ((ximage->width-windows->magnify.x)*magnify-(width >> 1));
7456 else
7457 x=0;
7458 y=windows->magnify.y-((height/magnify) >> 1);
7459 if (y < 0)
7460 y=(int) ((height >> 1)-windows->magnify.y*magnify);
7461 else
7462 if (y > (int) (ximage->height-(height/magnify)))
7463 y=(int) ((ximage->height-windows->magnify.y)*magnify-(height >> 1));
7464 else
7465 y=0;
7466 if ((x != 0) || (y != 0))
7467 (void) XFillRectangle(display,windows->magnify.pixmap,
7468 windows->magnify.annotate_context,0,0,width,height);
7469 (void) XPutImage(display,windows->magnify.pixmap,
7470 windows->magnify.annotate_context,windows->magnify.ximage,0,0,x,y,width-x,
7471 height-y);
7472 if ((magnify > 1) && ((magnify <= (width >> 1)) &&
7473 (magnify <= (height >> 1))))
7474 {
7475 RectangleInfo
7476 highlight_info;
7477
7478 /*
7479 Highlight center pixel.
7480 */
cristybb503372010-05-27 20:51:26 +00007481 highlight_info.x=(ssize_t) windows->magnify.width >> 1;
7482 highlight_info.y=(ssize_t) windows->magnify.height >> 1;
cristy3ed852e2009-09-05 21:47:34 +00007483 highlight_info.width=magnify;
7484 highlight_info.height=magnify;
7485 (void) XDrawRectangle(display,windows->magnify.pixmap,
7486 windows->magnify.highlight_context,(int) highlight_info.x,
7487 (int) highlight_info.y,(unsigned int) highlight_info.width-1,
7488 (unsigned int) highlight_info.height-1);
7489 if (magnify > 2)
7490 (void) XDrawRectangle(display,windows->magnify.pixmap,
7491 windows->magnify.annotate_context,(int) highlight_info.x+1,
7492 (int) highlight_info.y+1,(unsigned int) highlight_info.width-3,
7493 (unsigned int) highlight_info.height-3);
7494 }
7495 /*
7496 Show center pixel color.
7497 */
cristyc57f6942010-11-12 01:47:39 +00007498 (void) GetOneVirtualMagickPixel(windows->image.image,(ssize_t)
7499 windows->magnify.x,(ssize_t) windows->magnify.y,&pixel,
7500 &windows->image.image->exception);
cristyb51dff52011-05-19 16:55:47 +00007501 (void) FormatLocaleString(tuple,MaxTextExtent,"%d,%d: ",
cristy3ed852e2009-09-05 21:47:34 +00007502 windows->magnify.x,windows->magnify.y);
7503 (void) ConcatenateMagickString(tuple,"(",MaxTextExtent);
cristyed231572011-07-14 02:18:59 +00007504 ConcatenateColorComponent(&pixel,RedPixelChannel,X11Compliance,tuple);
cristy3ed852e2009-09-05 21:47:34 +00007505 (void) ConcatenateMagickString(tuple,",",MaxTextExtent);
cristyed231572011-07-14 02:18:59 +00007506 ConcatenateColorComponent(&pixel,GreenPixelChannel,X11Compliance,tuple);
cristy3ed852e2009-09-05 21:47:34 +00007507 (void) ConcatenateMagickString(tuple,",",MaxTextExtent);
cristyed231572011-07-14 02:18:59 +00007508 ConcatenateColorComponent(&pixel,BluePixelChannel,X11Compliance,tuple);
cristy3ed852e2009-09-05 21:47:34 +00007509 if (pixel.colorspace == CMYKColorspace)
7510 {
7511 (void) ConcatenateMagickString(tuple,",",MaxTextExtent);
cristyed231572011-07-14 02:18:59 +00007512 ConcatenateColorComponent(&pixel,BlackPixelChannel,X11Compliance,tuple);
cristy3ed852e2009-09-05 21:47:34 +00007513 }
7514 if (pixel.matte != MagickFalse)
7515 {
7516 (void) ConcatenateMagickString(tuple,",",MaxTextExtent);
cristyed231572011-07-14 02:18:59 +00007517 ConcatenateColorComponent(&pixel,AlphaPixelChannel,X11Compliance,tuple);
cristy3ed852e2009-09-05 21:47:34 +00007518 }
7519 (void) ConcatenateMagickString(tuple,")",MaxTextExtent);
7520 height=(unsigned int) windows->magnify.font_info->ascent+
7521 windows->magnify.font_info->descent;
7522 x=windows->magnify.font_info->max_bounds.width >> 1;
7523 y=windows->magnify.font_info->ascent+(height >> 2);
7524 (void) XDrawImageString(display,windows->magnify.pixmap,
7525 windows->magnify.annotate_context,x,y,tuple,(int) strlen(tuple));
7526 GetColorTuple(&pixel,MagickTrue,tuple);
7527 y+=height;
7528 (void) XDrawImageString(display,windows->magnify.pixmap,
7529 windows->magnify.annotate_context,x,y,tuple,(int) strlen(tuple));
7530 (void) QueryMagickColorname(windows->image.image,&pixel,SVGCompliance,tuple,
7531 &windows->image.image->exception);
7532 y+=height;
7533 (void) XDrawImageString(display,windows->magnify.pixmap,
7534 windows->magnify.annotate_context,x,y,tuple,(int) strlen(tuple));
7535 /*
7536 Refresh magnify window.
7537 */
7538 magnify_window=windows->magnify;
7539 magnify_window.x=0;
7540 magnify_window.y=0;
7541 XRefreshWindow(display,&magnify_window,(XEvent *) NULL);
7542}
7543
7544/*
7545%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
7546% %
7547% %
7548% %
7549% X M a k e P i x m a p %
7550% %
7551% %
7552% %
7553%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
7554%
7555% XMakePixmap() creates an X11 pixmap.
7556%
7557% The format of the XMakePixmap method is:
7558%
7559% void XMakeStandardColormap(Display *display,XVisualInfo *visual_info,
7560% XResourceInfo *resource_info,Image *image,XStandardColormap *map_info,
7561% XPixelInfo *pixel)
7562%
7563% A description of each parameter follows:
7564%
7565% o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
7566%
7567% o display: Specifies a connection to an X server; returned from
7568% XOpenDisplay.
7569%
7570% o window: Specifies a pointer to a XWindowInfo structure.
7571%
cristy3ed852e2009-09-05 21:47:34 +00007572*/
7573static MagickBooleanType XMakePixmap(Display *display,
7574 const XResourceInfo *resource_info,XWindowInfo *window)
7575{
7576 unsigned int
7577 height,
7578 width;
7579
7580 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
7581 assert(display != (Display *) NULL);
7582 assert(resource_info != (XResourceInfo *) NULL);
7583 assert(window != (XWindowInfo *) NULL);
7584 if (window->pixmap != (Pixmap) NULL)
7585 {
7586 /*
7587 Destroy previous X pixmap.
7588 */
7589 (void) XFreePixmap(display,window->pixmap);
7590 window->pixmap=(Pixmap) NULL;
7591 }
7592 if (window->use_pixmap == MagickFalse)
7593 return(MagickFalse);
7594 if (window->ximage == (XImage *) NULL)
7595 return(MagickFalse);
7596 /*
7597 Display busy cursor.
7598 */
7599 (void) XCheckDefineCursor(display,window->id,window->busy_cursor);
7600 (void) XFlush(display);
7601 /*
7602 Create pixmap.
7603 */
7604 width=(unsigned int) window->ximage->width;
7605 height=(unsigned int) window->ximage->height;
7606 window->pixmap=XCreatePixmap(display,window->id,width,height,window->depth);
7607 if (window->pixmap == (Pixmap) NULL)
7608 {
7609 /*
7610 Unable to allocate pixmap.
7611 */
7612 (void) XCheckDefineCursor(display,window->id,window->cursor);
7613 return(MagickFalse);
7614 }
7615 /*
7616 Copy X image to pixmap.
7617 */
7618#if defined(MAGICKCORE_HAVE_SHARED_MEMORY)
7619 if (window->shared_memory)
7620 (void) XShmPutImage(display,window->pixmap,window->annotate_context,
7621 window->ximage,0,0,0,0,width,height,MagickTrue);
7622#endif
7623 if (window->shared_memory == MagickFalse)
7624 (void) XPutImage(display,window->pixmap,window->annotate_context,
7625 window->ximage,0,0,0,0,width,height);
7626 if (IsEventLogging())
7627 {
7628 (void) LogMagickEvent(X11Event,GetMagickModule(),"Pixmap:");
7629 (void) LogMagickEvent(X11Event,GetMagickModule()," width, height: %ux%u",
7630 width,height);
7631 }
7632 /*
7633 Restore cursor.
7634 */
7635 (void) XCheckDefineCursor(display,window->id,window->cursor);
7636 return(MagickTrue);
7637}
7638
7639/*
7640%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
7641% %
7642% %
7643% %
7644% X M a k e S t a n d a r d C o l o r m a p %
7645% %
7646% %
7647% %
7648%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
7649%
7650% XMakeStandardColormap() creates an X11 Standard Colormap.
7651%
7652% The format of the XMakeStandardColormap method is:
7653%
7654% XMakeStandardColormap(display,visual_info,resource_info,image,
7655% map_info,pixel)
7656%
7657% A description of each parameter follows:
7658%
7659% o display: Specifies a connection to an X server; returned from
7660% XOpenDisplay.
7661%
7662% o visual_info: Specifies a pointer to a X11 XVisualInfo structure;
7663% returned from XGetVisualInfo.
7664%
7665% o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
7666%
7667% o image: the image.
7668%
7669% o map_info: If a Standard Colormap type is specified, this structure is
7670% initialized with info from the Standard Colormap.
7671%
7672% o pixel: Specifies a pointer to a XPixelInfo structure.
7673%
cristy3ed852e2009-09-05 21:47:34 +00007674*/
7675
7676#if defined(__cplusplus) || defined(c_plusplus)
7677extern "C" {
7678#endif
7679
7680static inline MagickRealType DiversityPixelIntensity(
7681 const DiversityPacket *pixel)
7682{
7683 MagickRealType
7684 intensity;
7685
7686 intensity=0.299*pixel->red+0.587*pixel->green+0.114*pixel->blue;
7687 return(intensity);
7688}
7689
7690static int IntensityCompare(const void *x,const void *y)
7691{
7692 DiversityPacket
7693 *color_1,
7694 *color_2;
7695
7696 int
7697 diversity;
7698
7699 color_1=(DiversityPacket *) x;
7700 color_2=(DiversityPacket *) y;
7701 diversity=(int) (DiversityPixelIntensity(color_2)-
7702 DiversityPixelIntensity(color_1));
7703 return(diversity);
7704}
7705
7706static int PopularityCompare(const void *x,const void *y)
7707{
7708 DiversityPacket
7709 *color_1,
7710 *color_2;
7711
7712 color_1=(DiversityPacket *) x;
7713 color_2=(DiversityPacket *) y;
7714 return((int) color_2->count-(int) color_1->count);
7715}
7716
7717#if defined(__cplusplus) || defined(c_plusplus)
7718}
7719#endif
7720
cristybb503372010-05-27 20:51:26 +00007721static inline Quantum ScaleXToQuantum(const size_t x,
7722 const size_t scale)
cristy3ed852e2009-09-05 21:47:34 +00007723{
7724 return((Quantum) (((MagickRealType) QuantumRange*x)/scale+0.5));
7725}
7726
cristybcbda3f2011-09-03 13:01:22 +00007727MagickPrivate void XMakeStandardColormap(Display *display,
cristy3ed852e2009-09-05 21:47:34 +00007728 XVisualInfo *visual_info,XResourceInfo *resource_info,Image *image,
7729 XStandardColormap *map_info,XPixelInfo *pixel)
7730{
7731 Colormap
7732 colormap;
7733
7734 ExceptionInfo
7735 *exception;
7736
cristybb503372010-05-27 20:51:26 +00007737 register ssize_t
cristy3ed852e2009-09-05 21:47:34 +00007738 i;
7739
7740 Status
7741 status;
7742
cristybb503372010-05-27 20:51:26 +00007743 size_t
cristy3ed852e2009-09-05 21:47:34 +00007744 number_colors,
7745 retain_colors;
7746
7747 unsigned short
7748 gray_value;
7749
7750 XColor
7751 color,
7752 *colors,
7753 *p;
7754
7755 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
7756 assert(display != (Display *) NULL);
7757 assert(visual_info != (XVisualInfo *) NULL);
7758 assert(map_info != (XStandardColormap *) NULL);
7759 assert(resource_info != (XResourceInfo *) NULL);
7760 assert(pixel != (XPixelInfo *) NULL);
7761 exception=(&image->exception);
7762 if (resource_info->map_type != (char *) NULL)
7763 {
7764 /*
7765 Standard Colormap is already defined (i.e. xstdcmap).
7766 */
cristy4c08aed2011-07-01 19:47:50 +00007767 XGetPixelInfo(display,visual_info,map_info,resource_info,image,
cristy3ed852e2009-09-05 21:47:34 +00007768 pixel);
7769 number_colors=(unsigned int) (map_info->base_pixel+
7770 (map_info->red_max+1)*(map_info->green_max+1)*(map_info->blue_max+1));
7771 if ((map_info->red_max*map_info->green_max*map_info->blue_max) != 0)
7772 if ((image->matte == MagickFalse) &&
7773 (resource_info->color_recovery == MagickFalse) &&
7774 resource_info->quantize_info->dither &&
7775 (number_colors < MaxColormapSize))
7776 {
7777 Image
7778 *affinity_image;
7779
cristy4c08aed2011-07-01 19:47:50 +00007780 register Quantum
cristyc47d1f82009-11-26 01:44:43 +00007781 *restrict q;
cristy3ed852e2009-09-05 21:47:34 +00007782
7783 /*
7784 Improve image appearance with error diffusion.
7785 */
cristy9950d572011-10-01 18:22:35 +00007786 affinity_image=AcquireImage((ImageInfo *) NULL,&image->exception);
cristy3ed852e2009-09-05 21:47:34 +00007787 if (affinity_image == (Image *) NULL)
7788 ThrowXWindowFatalException(ResourceLimitFatalError,
7789 "UnableToDitherImage",image->filename);
7790 affinity_image->columns=number_colors;
7791 affinity_image->rows=1;
7792 /*
7793 Initialize colormap image.
7794 */
7795 q=QueueAuthenticPixels(affinity_image,0,0,affinity_image->columns,
7796 1,exception);
cristy4c08aed2011-07-01 19:47:50 +00007797 if (q != (Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00007798 {
cristybb503372010-05-27 20:51:26 +00007799 for (i=0; i < (ssize_t) number_colors; i++)
cristy3ed852e2009-09-05 21:47:34 +00007800 {
cristy4c08aed2011-07-01 19:47:50 +00007801 SetPixelRed(affinity_image,0,q);
cristy3ed852e2009-09-05 21:47:34 +00007802 if (map_info->red_max != 0)
cristy4c08aed2011-07-01 19:47:50 +00007803 SetPixelRed(affinity_image,
7804 ScaleXToQuantum((size_t) (i/map_info->red_mult),
7805 map_info->red_max),q);
7806 SetPixelGreen(affinity_image,0,q);
cristy3ed852e2009-09-05 21:47:34 +00007807 if (map_info->green_max != 0)
cristy4c08aed2011-07-01 19:47:50 +00007808 SetPixelGreen(affinity_image,
7809 ScaleXToQuantum((size_t) ((i/map_info->green_mult) %
7810 (map_info->green_max+1)),map_info->green_max),q);
7811 SetPixelBlue(affinity_image,0,q);
cristy3ed852e2009-09-05 21:47:34 +00007812 if (map_info->blue_max != 0)
cristy4c08aed2011-07-01 19:47:50 +00007813 SetPixelBlue(affinity_image,
7814 ScaleXToQuantum((size_t) (i % map_info->green_mult),
7815 map_info->blue_max),q);
7816 SetPixelAlpha(affinity_image,
7817 TransparentAlpha,q);
cristyed231572011-07-14 02:18:59 +00007818 q+=GetPixelChannels(affinity_image);
cristy3ed852e2009-09-05 21:47:34 +00007819 }
7820 (void) SyncAuthenticPixels(affinity_image,exception);
7821 (void) RemapImage(resource_info->quantize_info,image,
cristy018f07f2011-09-04 21:15:19 +00007822 affinity_image,exception);
cristy3ed852e2009-09-05 21:47:34 +00007823 }
cristy4c08aed2011-07-01 19:47:50 +00007824 XGetPixelInfo(display,visual_info,map_info,resource_info,image,
cristy3ed852e2009-09-05 21:47:34 +00007825 pixel);
cristy574cc262011-08-05 01:23:58 +00007826 (void) SetImageStorageClass(image,DirectClass,exception);
cristy3ed852e2009-09-05 21:47:34 +00007827 affinity_image=DestroyImage(affinity_image);
7828 }
7829 if (IsEventLogging())
7830 {
7831 (void) LogMagickEvent(X11Event,GetMagickModule(),
7832 "Standard Colormap:");
7833 (void) LogMagickEvent(X11Event,GetMagickModule(),
7834 " colormap id: 0x%lx",map_info->colormap);
7835 (void) LogMagickEvent(X11Event,GetMagickModule(),
7836 " red, green, blue max: %lu %lu %lu",map_info->red_max,
7837 map_info->green_max,map_info->blue_max);
7838 (void) LogMagickEvent(X11Event,GetMagickModule(),
7839 " red, green, blue mult: %lu %lu %lu",map_info->red_mult,
7840 map_info->green_mult,map_info->blue_mult);
7841 }
7842 return;
7843 }
7844 if ((visual_info->klass != DirectColor) &&
7845 (visual_info->klass != TrueColor))
7846 if ((image->storage_class == DirectClass) ||
7847 ((int) image->colors > visual_info->colormap_size))
7848 {
7849 QuantizeInfo
7850 quantize_info;
7851
7852 /*
7853 Image has more colors than the visual supports.
7854 */
7855 quantize_info=(*resource_info->quantize_info);
cristybb503372010-05-27 20:51:26 +00007856 quantize_info.number_colors=(size_t) visual_info->colormap_size;
cristy018f07f2011-09-04 21:15:19 +00007857 (void) QuantizeImage(&quantize_info,image,exception);
cristy3ed852e2009-09-05 21:47:34 +00007858 }
7859 /*
7860 Free previous and create new colormap.
7861 */
7862 (void) XFreeStandardColormap(display,visual_info,map_info,pixel);
7863 colormap=XDefaultColormap(display,visual_info->screen);
7864 if (visual_info->visual != XDefaultVisual(display,visual_info->screen))
7865 colormap=XCreateColormap(display,XRootWindow(display,visual_info->screen),
7866 visual_info->visual,visual_info->klass == DirectColor ?
7867 AllocAll : AllocNone);
7868 if (colormap == (Colormap) NULL)
7869 ThrowXWindowFatalException(ResourceLimitFatalError,"UnableToCreateColormap",
7870 image->filename);
7871 /*
7872 Initialize the map and pixel info structures.
7873 */
7874 XGetMapInfo(visual_info,colormap,map_info);
cristy4c08aed2011-07-01 19:47:50 +00007875 XGetPixelInfo(display,visual_info,map_info,resource_info,image,pixel);
cristy3ed852e2009-09-05 21:47:34 +00007876 /*
7877 Allocating colors in server colormap is based on visual class.
7878 */
7879 switch (visual_info->klass)
7880 {
7881 case StaticGray:
7882 case StaticColor:
7883 {
7884 /*
7885 Define Standard Colormap for StaticGray or StaticColor visual.
7886 */
7887 number_colors=image->colors;
7888 colors=(XColor *) AcquireQuantumMemory((size_t)
7889 visual_info->colormap_size,sizeof(*colors));
7890 if (colors == (XColor *) NULL)
7891 ThrowXWindowFatalException(ResourceLimitFatalError,
7892 "UnableToCreateColormap",image->filename);
7893 p=colors;
7894 color.flags=(char) (DoRed | DoGreen | DoBlue);
cristybb503372010-05-27 20:51:26 +00007895 for (i=0; i < (ssize_t) image->colors; i++)
cristy3ed852e2009-09-05 21:47:34 +00007896 {
7897 color.red=ScaleQuantumToShort(XRedGamma(image->colormap[i].red));
7898 color.green=ScaleQuantumToShort(XGreenGamma(image->colormap[i].green));
7899 color.blue=ScaleQuantumToShort(XBlueGamma(image->colormap[i].blue));
7900 if (visual_info->klass != StaticColor)
7901 {
7902 gray_value=(unsigned short) XPixelIntensity(&color);
7903 color.red=gray_value;
7904 color.green=gray_value;
7905 color.blue=gray_value;
7906 }
7907 status=XAllocColor(display,colormap,&color);
7908 if (status == False)
7909 {
7910 colormap=XCopyColormapAndFree(display,colormap);
7911 (void) XAllocColor(display,colormap,&color);
7912 }
7913 pixel->pixels[i]=color.pixel;
7914 *p++=color;
7915 }
7916 break;
7917 }
7918 case GrayScale:
7919 case PseudoColor:
7920 {
7921 unsigned int
7922 colormap_type;
7923
7924 /*
7925 Define Standard Colormap for GrayScale or PseudoColor visual.
7926 */
7927 number_colors=image->colors;
7928 colors=(XColor *) AcquireQuantumMemory((size_t)
7929 visual_info->colormap_size,sizeof(*colors));
7930 if (colors == (XColor *) NULL)
7931 ThrowXWindowFatalException(ResourceLimitFatalError,
7932 "UnableToCreateColormap",image->filename);
7933 /*
7934 Preallocate our GUI colors.
7935 */
7936 (void) XAllocColor(display,colormap,&pixel->foreground_color);
7937 (void) XAllocColor(display,colormap,&pixel->background_color);
7938 (void) XAllocColor(display,colormap,&pixel->border_color);
7939 (void) XAllocColor(display,colormap,&pixel->matte_color);
7940 (void) XAllocColor(display,colormap,&pixel->highlight_color);
7941 (void) XAllocColor(display,colormap,&pixel->shadow_color);
7942 (void) XAllocColor(display,colormap,&pixel->depth_color);
7943 (void) XAllocColor(display,colormap,&pixel->trough_color);
7944 for (i=0; i < MaxNumberPens; i++)
7945 (void) XAllocColor(display,colormap,&pixel->pen_colors[i]);
7946 /*
7947 Determine if image colors will "fit" into X server colormap.
7948 */
7949 colormap_type=resource_info->colormap;
cristyf2faecf2010-05-28 19:19:36 +00007950 status=XAllocColorCells(display,colormap,MagickFalse,(unsigned long *)
cristy3ed852e2009-09-05 21:47:34 +00007951 NULL,0,pixel->pixels,(unsigned int) image->colors);
7952 if (status != False)
7953 colormap_type=PrivateColormap;
7954 if (colormap_type == SharedColormap)
7955 {
cristyc57f6942010-11-12 01:47:39 +00007956 CacheView
7957 *image_view;
7958
cristy3ed852e2009-09-05 21:47:34 +00007959 DiversityPacket
7960 *diversity;
7961
7962 int
7963 y;
7964
7965 register int
7966 x;
7967
7968 unsigned short
7969 index;
7970
7971 XColor
7972 *server_colors;
7973
7974 /*
7975 Define Standard colormap for shared GrayScale or PseudoColor visual.
7976 */
7977 diversity=(DiversityPacket *) AcquireQuantumMemory(image->colors,
7978 sizeof(*diversity));
7979 if (diversity == (DiversityPacket *) NULL)
7980 ThrowXWindowFatalException(ResourceLimitFatalError,
7981 "UnableToCreateColormap",image->filename);
cristybb503372010-05-27 20:51:26 +00007982 for (i=0; i < (ssize_t) image->colors; i++)
cristy3ed852e2009-09-05 21:47:34 +00007983 {
7984 diversity[i].red=image->colormap[i].red;
7985 diversity[i].green=image->colormap[i].green;
7986 diversity[i].blue=image->colormap[i].blue;
7987 diversity[i].index=(unsigned short) i;
7988 diversity[i].count=0;
7989 }
cristyc57f6942010-11-12 01:47:39 +00007990 image_view=AcquireCacheView(image);
cristy3ed852e2009-09-05 21:47:34 +00007991 for (y=0; y < (int) image->rows; y++)
7992 {
cristyc57f6942010-11-12 01:47:39 +00007993 register int
cristy3ed852e2009-09-05 21:47:34 +00007994 x;
7995
cristy4c08aed2011-07-01 19:47:50 +00007996 register const Quantum
cristyc57f6942010-11-12 01:47:39 +00007997 *restrict p;
cristy3ed852e2009-09-05 21:47:34 +00007998
cristyc57f6942010-11-12 01:47:39 +00007999 p=GetCacheViewAuthenticPixels(image_view,0,(ssize_t) y,
8000 image->columns,1,exception);
cristy4c08aed2011-07-01 19:47:50 +00008001 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00008002 break;
cristyc57f6942010-11-12 01:47:39 +00008003 for (x=(int) image->columns-1; x >= 0; x--)
cristy4c08aed2011-07-01 19:47:50 +00008004 {
8005 diversity[(ssize_t) GetPixelIndex(image,p)].count++;
cristyed231572011-07-14 02:18:59 +00008006 p+=GetPixelChannels(image);
cristy4c08aed2011-07-01 19:47:50 +00008007 }
cristy3ed852e2009-09-05 21:47:34 +00008008 }
cristyc57f6942010-11-12 01:47:39 +00008009 image_view=DestroyCacheView(image_view);
cristy3ed852e2009-09-05 21:47:34 +00008010 /*
8011 Sort colors by decreasing intensity.
8012 */
8013 qsort((void *) diversity,image->colors,sizeof(*diversity),
8014 IntensityCompare);
cristybb503372010-05-27 20:51:26 +00008015 for (i=0; i < (ssize_t) image->colors; )
cristy3ed852e2009-09-05 21:47:34 +00008016 {
8017 diversity[i].count<<=4; /* increase this colors popularity */
cristydfe2b662010-08-22 16:17:24 +00008018 i+=MagickMax((int) (image->colors >> 4),2);
cristy3ed852e2009-09-05 21:47:34 +00008019 }
8020 diversity[image->colors-1].count<<=4;
8021 qsort((void *) diversity,image->colors,sizeof(*diversity),
8022 PopularityCompare);
8023 /*
8024 Allocate colors.
8025 */
8026 p=colors;
8027 color.flags=(char) (DoRed | DoGreen | DoBlue);
cristybb503372010-05-27 20:51:26 +00008028 for (i=0; i < (ssize_t) image->colors; i++)
cristy3ed852e2009-09-05 21:47:34 +00008029 {
8030 index=diversity[i].index;
8031 color.red=
8032 ScaleQuantumToShort(XRedGamma(image->colormap[index].red));
8033 color.green=
8034 ScaleQuantumToShort(XGreenGamma(image->colormap[index].green));
8035 color.blue=
8036 ScaleQuantumToShort(XBlueGamma(image->colormap[index].blue));
8037 if (visual_info->klass != PseudoColor)
8038 {
8039 gray_value=(unsigned short) XPixelIntensity(&color);
8040 color.red=gray_value;
8041 color.green=gray_value;
8042 color.blue=gray_value;
8043 }
8044 status=XAllocColor(display,colormap,&color);
8045 if (status == False)
8046 break;
8047 pixel->pixels[index]=color.pixel;
8048 *p++=color;
8049 }
8050 /*
8051 Read X server colormap.
8052 */
8053 server_colors=(XColor *) AcquireQuantumMemory((size_t)
8054 visual_info->colormap_size,sizeof(*server_colors));
8055 if (server_colors == (XColor *) NULL)
8056 ThrowXWindowFatalException(ResourceLimitFatalError,
8057 "UnableToCreateColormap",image->filename);
8058 for (x=visual_info->colormap_size-1; x >= 0; x--)
cristybb503372010-05-27 20:51:26 +00008059 server_colors[x].pixel=(size_t) x;
cristy3ed852e2009-09-05 21:47:34 +00008060 (void) XQueryColors(display,colormap,server_colors,
8061 (int) MagickMin((unsigned int) visual_info->colormap_size,256));
8062 /*
8063 Select remaining colors from X server colormap.
8064 */
cristybb503372010-05-27 20:51:26 +00008065 for (; i < (ssize_t) image->colors; i++)
cristy3ed852e2009-09-05 21:47:34 +00008066 {
8067 index=diversity[i].index;
8068 color.red=
8069 ScaleQuantumToShort(XRedGamma(image->colormap[index].red));
8070 color.green=
8071 ScaleQuantumToShort(XGreenGamma(image->colormap[index].green));
8072 color.blue=
8073 ScaleQuantumToShort(XBlueGamma(image->colormap[index].blue));
8074 if (visual_info->klass != PseudoColor)
8075 {
8076 gray_value=(unsigned short) XPixelIntensity(&color);
8077 color.red=gray_value;
8078 color.green=gray_value;
8079 color.blue=gray_value;
8080 }
8081 XBestPixel(display,colormap,server_colors,(unsigned int)
8082 visual_info->colormap_size,&color);
8083 pixel->pixels[index]=color.pixel;
8084 *p++=color;
8085 }
8086 if ((int) image->colors < visual_info->colormap_size)
8087 {
8088 /*
8089 Fill up colors array-- more choices for pen colors.
8090 */
8091 retain_colors=MagickMin((unsigned int)
8092 (visual_info->colormap_size-image->colors),256);
cristybb503372010-05-27 20:51:26 +00008093 for (i=0; i < (ssize_t) retain_colors; i++)
cristy3ed852e2009-09-05 21:47:34 +00008094 *p++=server_colors[i];
8095 number_colors+=retain_colors;
8096 }
8097 server_colors=(XColor *) RelinquishMagickMemory(server_colors);
8098 diversity=(DiversityPacket *) RelinquishMagickMemory(diversity);
8099 break;
8100 }
8101 /*
8102 Define Standard colormap for private GrayScale or PseudoColor visual.
8103 */
8104 if (status == False)
8105 {
8106 /*
8107 Not enough colormap entries in the colormap-- Create a new colormap.
8108 */
8109 colormap=XCreateColormap(display,
8110 XRootWindow(display,visual_info->screen),visual_info->visual,
8111 AllocNone);
8112 if (colormap == (Colormap) NULL)
8113 ThrowXWindowFatalException(ResourceLimitFatalError,
8114 "UnableToCreateColormap",image->filename);
8115 map_info->colormap=colormap;
8116 if ((int) image->colors < visual_info->colormap_size)
8117 {
8118 /*
8119 Retain colors from the default colormap to help lessens the
8120 effects of colormap flashing.
8121 */
8122 retain_colors=MagickMin((unsigned int)
8123 (visual_info->colormap_size-image->colors),256);
8124 p=colors+image->colors;
cristybb503372010-05-27 20:51:26 +00008125 for (i=0; i < (ssize_t) retain_colors; i++)
cristy3ed852e2009-09-05 21:47:34 +00008126 {
cristyc57f6942010-11-12 01:47:39 +00008127 p->pixel=(unsigned long) i;
cristy3ed852e2009-09-05 21:47:34 +00008128 p++;
8129 }
8130 (void) XQueryColors(display,
8131 XDefaultColormap(display,visual_info->screen),
8132 colors+image->colors,(int) retain_colors);
8133 /*
8134 Transfer colors from default to private colormap.
8135 */
8136 (void) XAllocColorCells(display,colormap,MagickFalse,
cristyf2faecf2010-05-28 19:19:36 +00008137 (unsigned long *) NULL,0,pixel->pixels,(unsigned int)
cristy3ed852e2009-09-05 21:47:34 +00008138 retain_colors);
8139 p=colors+image->colors;
cristybb503372010-05-27 20:51:26 +00008140 for (i=0; i < (ssize_t) retain_colors; i++)
cristy3ed852e2009-09-05 21:47:34 +00008141 {
8142 p->pixel=pixel->pixels[i];
8143 p++;
8144 }
8145 (void) XStoreColors(display,colormap,colors+image->colors,
8146 (int) retain_colors);
8147 number_colors+=retain_colors;
8148 }
8149 (void) XAllocColorCells(display,colormap,MagickFalse,
cristyf2faecf2010-05-28 19:19:36 +00008150 (unsigned long *) NULL,0,pixel->pixels,(unsigned int)
cristy3ed852e2009-09-05 21:47:34 +00008151 image->colors);
8152 }
8153 /*
8154 Store the image colormap.
8155 */
8156 p=colors;
8157 color.flags=(char) (DoRed | DoGreen | DoBlue);
cristybb503372010-05-27 20:51:26 +00008158 for (i=0; i < (ssize_t) image->colors; i++)
cristy3ed852e2009-09-05 21:47:34 +00008159 {
8160 color.red=ScaleQuantumToShort(XRedGamma(image->colormap[i].red));
8161 color.green=ScaleQuantumToShort(XGreenGamma(image->colormap[i].green));
8162 color.blue=ScaleQuantumToShort(XBlueGamma(image->colormap[i].blue));
8163 if (visual_info->klass != PseudoColor)
8164 {
8165 gray_value=(unsigned short) XPixelIntensity(&color);
8166 color.red=gray_value;
8167 color.green=gray_value;
8168 color.blue=gray_value;
8169 }
8170 color.pixel=pixel->pixels[i];
8171 *p++=color;
8172 }
8173 (void) XStoreColors(display,colormap,colors,(int) image->colors);
8174 break;
8175 }
8176 case TrueColor:
8177 case DirectColor:
8178 default:
8179 {
8180 MagickBooleanType
8181 linear_colormap;
8182
8183 /*
8184 Define Standard Colormap for TrueColor or DirectColor visual.
8185 */
8186 number_colors=(unsigned int) ((map_info->red_max*map_info->red_mult)+
8187 (map_info->green_max*map_info->green_mult)+
8188 (map_info->blue_max*map_info->blue_mult)+1);
8189 linear_colormap=(number_colors > 4096) ||
8190 (((int) (map_info->red_max+1) == visual_info->colormap_size) &&
8191 ((int) (map_info->green_max+1) == visual_info->colormap_size) &&
8192 ((int) (map_info->blue_max+1) == visual_info->colormap_size)) ?
8193 MagickTrue : MagickFalse;
8194 if (linear_colormap != MagickFalse)
cristybb503372010-05-27 20:51:26 +00008195 number_colors=(size_t) visual_info->colormap_size;
cristy3ed852e2009-09-05 21:47:34 +00008196 /*
8197 Allocate color array.
8198 */
8199 colors=(XColor *) AcquireQuantumMemory(number_colors,sizeof(*colors));
8200 if (colors == (XColor *) NULL)
8201 ThrowXWindowFatalException(ResourceLimitFatalError,
8202 "UnableToCreateColormap",image->filename);
8203 /*
8204 Initialize linear color ramp.
8205 */
8206 p=colors;
8207 color.flags=(char) (DoRed | DoGreen | DoBlue);
8208 if (linear_colormap != MagickFalse)
cristybb503372010-05-27 20:51:26 +00008209 for (i=0; i < (ssize_t) number_colors; i++)
cristy3ed852e2009-09-05 21:47:34 +00008210 {
8211 color.blue=(unsigned short) 0;
8212 if (map_info->blue_max != 0)
cristybb503372010-05-27 20:51:26 +00008213 color.blue=(unsigned short) ((size_t)
cristy3ed852e2009-09-05 21:47:34 +00008214 ((65535L*(i % map_info->green_mult))/map_info->blue_max));
8215 color.green=color.blue;
8216 color.red=color.blue;
8217 color.pixel=XStandardPixel(map_info,&color);
8218 *p++=color;
8219 }
8220 else
cristybb503372010-05-27 20:51:26 +00008221 for (i=0; i < (ssize_t) number_colors; i++)
cristy3ed852e2009-09-05 21:47:34 +00008222 {
8223 color.red=(unsigned short) 0;
8224 if (map_info->red_max != 0)
cristybb503372010-05-27 20:51:26 +00008225 color.red=(unsigned short) ((size_t)
cristy3ed852e2009-09-05 21:47:34 +00008226 ((65535L*(i/map_info->red_mult))/map_info->red_max));
8227 color.green=(unsigned int) 0;
8228 if (map_info->green_max != 0)
cristybb503372010-05-27 20:51:26 +00008229 color.green=(unsigned short) ((size_t)
cristy3ed852e2009-09-05 21:47:34 +00008230 ((65535L*((i/map_info->green_mult) % (map_info->green_max+1)))/
8231 map_info->green_max));
8232 color.blue=(unsigned short) 0;
8233 if (map_info->blue_max != 0)
cristybb503372010-05-27 20:51:26 +00008234 color.blue=(unsigned short) ((size_t)
cristy3ed852e2009-09-05 21:47:34 +00008235 ((65535L*(i % map_info->green_mult))/map_info->blue_max));
8236 color.pixel=XStandardPixel(map_info,&color);
8237 *p++=color;
8238 }
8239 if ((visual_info->klass == DirectColor) &&
8240 (colormap != XDefaultColormap(display,visual_info->screen)))
8241 (void) XStoreColors(display,colormap,colors,(int) number_colors);
8242 else
cristybb503372010-05-27 20:51:26 +00008243 for (i=0; i < (ssize_t) number_colors; i++)
cristy3ed852e2009-09-05 21:47:34 +00008244 (void) XAllocColor(display,colormap,&colors[i]);
8245 break;
8246 }
8247 }
8248 if ((visual_info->klass != DirectColor) &&
8249 (visual_info->klass != TrueColor))
8250 {
8251 /*
8252 Set foreground, background, border, etc. pixels.
8253 */
8254 XBestPixel(display,colormap,colors,(unsigned int) number_colors,
8255 &pixel->foreground_color);
8256 XBestPixel(display,colormap,colors,(unsigned int) number_colors,
8257 &pixel->background_color);
8258 if (pixel->background_color.pixel == pixel->foreground_color.pixel)
8259 {
8260 /*
8261 Foreground and background colors must differ.
8262 */
8263 pixel->background_color.red=(~pixel->foreground_color.red);
8264 pixel->background_color.green=
8265 (~pixel->foreground_color.green);
8266 pixel->background_color.blue=
8267 (~pixel->foreground_color.blue);
8268 XBestPixel(display,colormap,colors,(unsigned int) number_colors,
8269 &pixel->background_color);
8270 }
8271 XBestPixel(display,colormap,colors,(unsigned int) number_colors,
8272 &pixel->border_color);
8273 XBestPixel(display,colormap,colors,(unsigned int) number_colors,
8274 &pixel->matte_color);
8275 XBestPixel(display,colormap,colors,(unsigned int) number_colors,
8276 &pixel->highlight_color);
8277 XBestPixel(display,colormap,colors,(unsigned int) number_colors,
8278 &pixel->shadow_color);
8279 XBestPixel(display,colormap,colors,(unsigned int) number_colors,
8280 &pixel->depth_color);
8281 XBestPixel(display,colormap,colors,(unsigned int) number_colors,
8282 &pixel->trough_color);
8283 for (i=0; i < MaxNumberPens; i++)
8284 {
8285 XBestPixel(display,colormap,colors,(unsigned int) number_colors,
8286 &pixel->pen_colors[i]);
8287 pixel->pixels[image->colors+i]=pixel->pen_colors[i].pixel;
8288 }
cristyc57f6942010-11-12 01:47:39 +00008289 pixel->colors=(ssize_t) (image->colors+MaxNumberPens);
cristy3ed852e2009-09-05 21:47:34 +00008290 }
8291 colors=(XColor *) RelinquishMagickMemory(colors);
8292 if (IsEventLogging())
8293 {
8294 (void) LogMagickEvent(X11Event,GetMagickModule(),"Standard Colormap:");
8295 (void) LogMagickEvent(X11Event,GetMagickModule()," colormap id: 0x%lx",
8296 map_info->colormap);
8297 (void) LogMagickEvent(X11Event,GetMagickModule(),
8298 " red, green, blue max: %lu %lu %lu",map_info->red_max,
8299 map_info->green_max,map_info->blue_max);
8300 (void) LogMagickEvent(X11Event,GetMagickModule(),
8301 " red, green, blue mult: %lu %lu %lu",map_info->red_mult,
8302 map_info->green_mult,map_info->blue_mult);
8303 }
8304}
8305
8306/*
8307%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8308% %
8309% %
8310% %
8311% X M a k e W i n d o w %
8312% %
8313% %
8314% %
8315%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8316%
8317% XMakeWindow() creates an X11 window.
8318%
8319% The format of the XMakeWindow method is:
8320%
8321% void XMakeWindow(Display *display,Window parent,char **argv,int argc,
8322% XClassHint *class_hint,XWMHints *manager_hints,
8323% XWindowInfo *window_info)
8324%
8325% A description of each parameter follows:
8326%
8327% o display: Specifies a connection to an X server; returned from
8328% XOpenDisplay.
8329%
8330% o parent: Specifies the parent window_info.
8331%
8332% o argv: Specifies the application's argument list.
8333%
8334% o argc: Specifies the number of arguments.
8335%
8336% o class_hint: Specifies a pointer to a X11 XClassHint structure.
8337%
8338% o manager_hints: Specifies a pointer to a X11 XWMHints structure.
8339%
8340% o window_info: Specifies a pointer to a X11 XWindowInfo structure.
8341%
8342*/
cristybcbda3f2011-09-03 13:01:22 +00008343MagickPrivate void XMakeWindow(Display *display,Window parent,char **argv,
cristy3ed852e2009-09-05 21:47:34 +00008344 int argc,XClassHint *class_hint,XWMHints *manager_hints,
8345 XWindowInfo *window_info)
8346{
8347#define MinWindowSize 64
8348
8349 Atom
8350 atom_list[2];
8351
8352 int
8353 gravity;
8354
8355 static XTextProperty
8356 icon_name,
8357 window_name;
8358
8359 Status
8360 status;
8361
8362 XSizeHints
8363 *size_hints;
8364
8365 /*
8366 Set window info hints.
8367 */
8368 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
8369 assert(display != (Display *) NULL);
8370 assert(window_info != (XWindowInfo *) NULL);
8371 size_hints=XAllocSizeHints();
8372 if (size_hints == (XSizeHints *) NULL)
8373 ThrowXWindowFatalException(XServerFatalError,"UnableToMakeXWindow",argv[0]);
cristydfe2b662010-08-22 16:17:24 +00008374 size_hints->flags=(int) window_info->flags;
cristy3ed852e2009-09-05 21:47:34 +00008375 size_hints->x=window_info->x;
8376 size_hints->y=window_info->y;
8377 size_hints->width=(int) window_info->width;
8378 size_hints->height=(int) window_info->height;
8379 if (window_info->immutable != MagickFalse)
8380 {
8381 /*
8382 Window size cannot be changed.
8383 */
8384 size_hints->min_width=size_hints->width;
8385 size_hints->min_height=size_hints->height;
8386 size_hints->max_width=size_hints->width;
8387 size_hints->max_height=size_hints->height;
8388 size_hints->flags|=PMinSize;
8389 size_hints->flags|=PMaxSize;
8390 }
8391 else
8392 {
8393 /*
8394 Window size can be changed.
8395 */
8396 size_hints->min_width=(int) window_info->min_width;
8397 size_hints->min_height=(int) window_info->min_height;
8398 size_hints->flags|=PResizeInc;
8399 size_hints->width_inc=(int) window_info->width_inc;
8400 size_hints->height_inc=(int) window_info->height_inc;
8401#if !defined(PRE_R4_ICCCM)
8402 size_hints->flags|=PBaseSize;
8403 size_hints->base_width=size_hints->width_inc;
8404 size_hints->base_height=size_hints->height_inc;
8405#endif
8406 }
8407 gravity=NorthWestGravity;
8408 if (window_info->geometry != (char *) NULL)
8409 {
8410 char
8411 default_geometry[MaxTextExtent],
8412 geometry[MaxTextExtent];
8413
8414 int
8415 flags;
8416
8417 register char
8418 *p;
8419
8420 /*
8421 User specified geometry.
8422 */
cristyb51dff52011-05-19 16:55:47 +00008423 (void) FormatLocaleString(default_geometry,MaxTextExtent,"%dx%d",
cristy3ed852e2009-09-05 21:47:34 +00008424 size_hints->width,size_hints->height);
8425 (void) CopyMagickString(geometry,window_info->geometry,MaxTextExtent);
8426 p=geometry;
8427 while (strlen(p) != 0)
8428 {
8429 if ((isspace((int) ((unsigned char) *p)) == 0) && (*p != '%'))
8430 p++;
8431 else
8432 (void) CopyMagickString(p,p+1,MaxTextExtent);
8433 }
8434 flags=XWMGeometry(display,window_info->screen,geometry,default_geometry,
8435 window_info->border_width,size_hints,&size_hints->x,&size_hints->y,
8436 &size_hints->width,&size_hints->height,&gravity);
8437 if ((flags & WidthValue) && (flags & HeightValue))
8438 size_hints->flags|=USSize;
8439 if ((flags & XValue) && (flags & YValue))
8440 {
8441 size_hints->flags|=USPosition;
8442 window_info->x=size_hints->x;
8443 window_info->y=size_hints->y;
8444 }
8445 }
8446#if !defined(PRE_R4_ICCCM)
8447 size_hints->win_gravity=gravity;
8448 size_hints->flags|=PWinGravity;
8449#endif
8450 if (window_info->id == (Window) NULL)
8451 window_info->id=XCreateWindow(display,parent,window_info->x,window_info->y,
8452 (unsigned int) size_hints->width,(unsigned int) size_hints->height,
8453 window_info->border_width,(int) window_info->depth,InputOutput,
cristyc57f6942010-11-12 01:47:39 +00008454 window_info->visual,(unsigned long) window_info->mask,
8455 &window_info->attributes);
cristy3ed852e2009-09-05 21:47:34 +00008456 else
8457 {
8458 MagickStatusType
8459 mask;
8460
8461 XEvent
8462 sans_event;
8463
8464 XWindowChanges
8465 window_changes;
8466
8467 /*
8468 Window already exists; change relevant attributes.
8469 */
cristyc57f6942010-11-12 01:47:39 +00008470 (void) XChangeWindowAttributes(display,window_info->id,(unsigned long)
8471 window_info->mask,&window_info->attributes);
cristy3ed852e2009-09-05 21:47:34 +00008472 mask=ConfigureNotify;
8473 while (XCheckTypedWindowEvent(display,window_info->id,(int) mask,&sans_event)) ;
8474 window_changes.x=window_info->x;
8475 window_changes.y=window_info->y;
8476 window_changes.width=(int) window_info->width;
8477 window_changes.height=(int) window_info->height;
8478 mask=(MagickStatusType) (CWWidth | CWHeight);
8479 if (window_info->flags & USPosition)
8480 mask|=CWX | CWY;
8481 (void) XReconfigureWMWindow(display,window_info->id,window_info->screen,
8482 mask,&window_changes);
8483 }
8484 if (window_info->id == (Window) NULL)
8485 ThrowXWindowFatalException(XServerFatalError,"UnableToCreateWindow",
8486 window_info->name);
8487 status=XStringListToTextProperty(&window_info->name,1,&window_name);
8488 if (status == False)
8489 ThrowXWindowFatalException(XServerFatalError,"UnableToCreateTextProperty",
8490 window_info->name);
8491 status=XStringListToTextProperty(&window_info->icon_name,1,&icon_name);
8492 if (status == False)
8493 ThrowXWindowFatalException(XServerFatalError,"UnableToCreateTextProperty",
8494 window_info->icon_name);
8495 if (window_info->icon_geometry != (char *) NULL)
8496 {
8497 int
8498 flags,
8499 height,
8500 width;
8501
8502 /*
8503 User specified icon geometry.
8504 */
8505 size_hints->flags|=USPosition;
8506 flags=XWMGeometry(display,window_info->screen,window_info->icon_geometry,
8507 (char *) NULL,0,size_hints,&manager_hints->icon_x,
8508 &manager_hints->icon_y,&width,&height,&gravity);
8509 if ((flags & XValue) && (flags & YValue))
8510 manager_hints->flags|=IconPositionHint;
8511 }
8512 XSetWMProperties(display,window_info->id,&window_name,&icon_name,argv,argc,
8513 size_hints,manager_hints,class_hint);
8514 if (window_name.value != (void *) NULL)
8515 {
8516 (void) XFree((void *) window_name.value);
8517 window_name.value=(unsigned char *) NULL;
8518 window_name.nitems=0;
8519 }
8520 if (icon_name.value != (void *) NULL)
8521 {
8522 (void) XFree((void *) icon_name.value);
8523 icon_name.value=(unsigned char *) NULL;
8524 icon_name.nitems=0;
8525 }
8526 atom_list[0]=XInternAtom(display,"WM_DELETE_WINDOW",MagickFalse);
8527 atom_list[1]=XInternAtom(display,"WM_TAKE_FOCUS",MagickFalse);
8528 (void) XSetWMProtocols(display,window_info->id,atom_list,2);
8529 (void) XFree((void *) size_hints);
8530 if (window_info->shape != MagickFalse)
8531 {
8532#if defined(MAGICKCORE_HAVE_SHAPE)
8533 int
8534 error_base,
8535 event_base;
8536
8537 /*
8538 Can we apply a non-rectangular shaping mask?
8539 */
8540 error_base=0;
8541 event_base=0;
8542 if (XShapeQueryExtension(display,&error_base,&event_base) == 0)
8543 window_info->shape=MagickFalse;
8544#else
8545 window_info->shape=MagickFalse;
8546#endif
8547 }
8548 if (window_info->shared_memory)
8549 {
8550#if defined(MAGICKCORE_HAVE_SHARED_MEMORY)
8551 /*
8552 Can we use shared memory with this window?
8553 */
8554 if (XShmQueryExtension(display) == 0)
8555 window_info->shared_memory=MagickFalse;
8556#else
8557 window_info->shared_memory=MagickFalse;
8558#endif
8559 }
8560 window_info->image=NewImageList();
8561 window_info->destroy=MagickFalse;
8562}
8563
8564/*
8565%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8566% %
8567% %
8568% %
8569% X M a g i c k P r o g r e s s M o n i t o r %
8570% %
8571% %
8572% %
8573%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8574%
8575% XMagickProgressMonitor() displays the progress a task is making in
8576% completing a task.
8577%
8578% The format of the XMagickProgressMonitor method is:
8579%
8580% void XMagickProgressMonitor(const char *task,
8581% const MagickOffsetType quantum,const MagickSizeType span,
8582% void *client_data)
8583%
8584% A description of each parameter follows:
8585%
8586% o task: Identifies the task in progress.
8587%
8588% o quantum: Specifies the quantum position within the span which represents
8589% how much progress has been made in completing a task.
8590%
8591% o span: Specifies the span relative to completing a task.
8592%
8593% o client_data: Pointer to any client data.
8594%
8595*/
8596
8597static const char *GetLocaleMonitorMessage(const char *text)
8598{
8599 char
8600 message[MaxTextExtent],
8601 tag[MaxTextExtent];
8602
8603 const char
8604 *locale_message;
8605
8606 register char
8607 *p;
8608
8609 (void) CopyMagickMemory(tag,text,MaxTextExtent);
8610 p=strrchr(tag,'/');
8611 if (p != (char *) NULL)
8612 *p='\0';
cristyb51dff52011-05-19 16:55:47 +00008613 (void) FormatLocaleString(message,MaxTextExtent,"Monitor/%s",tag);
cristy3ed852e2009-09-05 21:47:34 +00008614 locale_message=GetLocaleMessage(message);
8615 if (locale_message == message)
8616 return(text);
8617 return(locale_message);
8618}
8619
cristybcbda3f2011-09-03 13:01:22 +00008620MagickPrivate MagickBooleanType XMagickProgressMonitor(const char *tag,
cristy3ed852e2009-09-05 21:47:34 +00008621 const MagickOffsetType quantum,const MagickSizeType span,
8622 void *magick_unused(client_data))
8623{
8624 XWindows
8625 *windows;
8626
8627 windows=XSetWindows((XWindows *) ~0);
8628 if (windows == (XWindows *) NULL)
8629 return(MagickTrue);
8630 if (windows->info.mapped != MagickFalse)
8631 XProgressMonitorWidget(windows->display,windows,
8632 GetLocaleMonitorMessage(tag),quantum,span);
8633 return(MagickTrue);
8634}
8635
8636/*
8637%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8638% %
8639% %
8640% %
8641% X Q u e r y C o l o r D a t a b a s e %
8642% %
8643% %
8644% %
8645%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8646%
cristy9950d572011-10-01 18:22:35 +00008647% XQueryColorCompliance() looks up a RGB values for a color given in the target
cristy3ed852e2009-09-05 21:47:34 +00008648% string.
8649%
8650% The format of the XQueryColorDatabase method is:
8651%
cristy9950d572011-10-01 18:22:35 +00008652% MagickBooleanType XQueryColorCompliance(const char *target,XColor *color)
cristy3ed852e2009-09-05 21:47:34 +00008653%
8654% A description of each parameter follows:
8655%
8656% o target: Specifies the color to lookup in the X color database.
8657%
8658% o color: A pointer to an PixelPacket structure. The RGB value of the target
8659% color is returned as this value.
8660%
8661*/
cristy9950d572011-10-01 18:22:35 +00008662MagickPrivate MagickBooleanType XQueryColorCompliance(const char *target,
cristy3ed852e2009-09-05 21:47:34 +00008663 XColor *color)
8664{
8665 Colormap
8666 colormap;
8667
8668 static Display
8669 *display = (Display *) NULL;
8670
8671 Status
8672 status;
8673
8674 XColor
8675 xcolor;
8676
8677 /*
8678 Initialize color return value.
8679 */
8680 assert(color != (XColor *) NULL);
8681 color->red=0;
8682 color->green=0;
8683 color->blue=0;
8684 color->flags=(char) (DoRed | DoGreen | DoBlue);
8685 if ((target == (char *) NULL) || (*target == '\0'))
8686 target="#ffffffffffff";
8687 /*
8688 Let the X server define the color for us.
8689 */
8690 if (display == (Display *) NULL)
8691 display=XOpenDisplay((char *) NULL);
8692 if (display == (Display *) NULL)
8693 {
8694 ThrowXWindowFatalException(XServerError,"ColorIsNotKnownToServer",target);
8695 return(MagickFalse);
8696 }
8697 colormap=XDefaultColormap(display,XDefaultScreen(display));
8698 status=XParseColor(display,colormap,(char *) target,&xcolor);
8699 if (status == False)
8700 ThrowXWindowFatalException(XServerError,"ColorIsNotKnownToServer",target)
8701 else
8702 {
8703 color->red=xcolor.red;
8704 color->green=xcolor.green;
8705 color->blue=xcolor.blue;
8706 color->flags=xcolor.flags;
8707 }
8708 return(status != False ? MagickTrue : MagickFalse);
8709}
8710
8711/*
8712%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8713% %
8714% %
8715% %
8716% X Q u e r y P o s i t i o n %
8717% %
8718% %
8719% %
8720%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8721%
8722% XQueryPosition() gets the pointer coordinates relative to a window.
8723%
8724% The format of the XQueryPosition method is:
8725%
8726% void XQueryPosition(Display *display,const Window window,int *x,int *y)
8727%
8728% A description of each parameter follows:
8729%
8730% o display: Specifies a connection to an X server; returned from
8731% XOpenDisplay.
8732%
8733% o window: Specifies a pointer to a Window.
8734%
8735% o x: Return the x coordinate of the pointer relative to the origin of the
8736% window.
8737%
8738% o y: Return the y coordinate of the pointer relative to the origin of the
8739% window.
8740%
8741*/
cristybcbda3f2011-09-03 13:01:22 +00008742MagickPrivate void XQueryPosition(Display *display,const Window window,int *x,int *y)
cristy3ed852e2009-09-05 21:47:34 +00008743{
8744 int
8745 x_root,
8746 y_root;
8747
8748 unsigned int
8749 mask;
8750
8751 Window
8752 root_window;
8753
8754 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
8755 assert(display != (Display *) NULL);
8756 assert(window != (Window) NULL);
8757 assert(x != (int *) NULL);
8758 assert(y != (int *) NULL);
8759 (void) XQueryPointer(display,window,&root_window,&root_window,&x_root,&y_root,
8760 x,y,&mask);
8761}
8762
8763/*
8764%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8765% %
8766% %
8767% %
8768% X R e f r e s h W i n d o w %
8769% %
8770% %
8771% %
8772%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8773%
8774% XRefreshWindow() refreshes an image in a X window.
8775%
8776% The format of the XRefreshWindow method is:
8777%
8778% void XRefreshWindow(Display *display,const XWindowInfo *window,
8779% const XEvent *event)
8780%
8781% A description of each parameter follows:
8782%
8783% o display: Specifies a connection to an X server; returned from
8784% XOpenDisplay.
8785%
8786% o window: Specifies a pointer to a XWindowInfo structure.
8787%
8788% o event: Specifies a pointer to a XEvent structure. If it is NULL,
8789% the entire image is refreshed.
8790%
8791*/
cristybcbda3f2011-09-03 13:01:22 +00008792MagickPrivate void XRefreshWindow(Display *display,const XWindowInfo *window,
cristy3ed852e2009-09-05 21:47:34 +00008793 const XEvent *event)
8794{
8795 int
8796 x,
8797 y;
8798
8799 unsigned int
8800 height,
8801 width;
8802
8803 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
8804 assert(display != (Display *) NULL);
8805 assert(window != (XWindowInfo *) NULL);
8806 if (window->ximage == (XImage *) NULL)
8807 return;
8808 if (event != (XEvent *) NULL)
8809 {
8810 /*
8811 Determine geometry from expose event.
8812 */
8813 x=event->xexpose.x;
8814 y=event->xexpose.y;
8815 width=(unsigned int) event->xexpose.width;
8816 height=(unsigned int) event->xexpose.height;
8817 }
8818 else
8819 {
8820 XEvent
8821 sans_event;
8822
8823 /*
8824 Refresh entire window; discard outstanding expose events.
8825 */
8826 x=0;
8827 y=0;
8828 width=window->width;
8829 height=window->height;
8830 while (XCheckTypedWindowEvent(display,window->id,Expose,&sans_event)) ;
cristya0e5ad52010-02-10 02:05:12 +00008831 if (window->matte_pixmap != (Pixmap) NULL)
8832 {
8833#if defined(MAGICKCORE_HAVE_SHAPE)
8834 if (window->shape != MagickFalse)
8835 XShapeCombineMask(display,window->id,ShapeBounding,0,0,
8836 window->matte_pixmap,ShapeSet);
8837#endif
8838 }
cristy3ed852e2009-09-05 21:47:34 +00008839 }
8840 /*
8841 Check boundary conditions.
8842 */
8843 if ((window->ximage->width-(x+window->x)) < (int) width)
8844 width=(unsigned int) (window->ximage->width-(x+window->x));
8845 if ((window->ximage->height-(y+window->y)) < (int) height)
8846 height=(unsigned int) (window->ximage->height-(y+window->y));
8847 /*
8848 Refresh image.
8849 */
8850 if (window->matte_pixmap != (Pixmap) NULL)
cristya0e5ad52010-02-10 02:05:12 +00008851 (void) XSetClipMask(display,window->annotate_context,window->matte_pixmap);
cristy3ed852e2009-09-05 21:47:34 +00008852 if (window->pixmap != (Pixmap) NULL)
8853 {
8854 if (window->depth > 1)
8855 (void) XCopyArea(display,window->pixmap,window->id,
8856 window->annotate_context,x+window->x,y+window->y,width,height,x,y);
8857 else
8858 (void) XCopyPlane(display,window->pixmap,window->id,
8859 window->highlight_context,x+window->x,y+window->y,width,height,x,y,
8860 1L);
8861 }
8862 else
8863 {
8864#if defined(MAGICKCORE_HAVE_SHARED_MEMORY)
8865 if (window->shared_memory)
8866 (void) XShmPutImage(display,window->id,window->annotate_context,
8867 window->ximage,x+window->x,y+window->y,x,y,width,height,MagickTrue);
8868#endif
8869 if (window->shared_memory == MagickFalse)
8870 (void) XPutImage(display,window->id,window->annotate_context,
8871 window->ximage,x+window->x,y+window->y,x,y,width,height);
8872 }
8873 if (window->matte_pixmap != (Pixmap) NULL)
8874 (void) XSetClipMask(display,window->annotate_context,None);
8875 (void) XFlush(display);
8876}
8877
8878/*
8879%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8880% %
8881% %
8882% %
8883% X R e m o t e C o m m a n d %
8884% %
8885% %
8886% %
8887%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8888%
8889% XRemoteCommand() forces a remote display(1) to display the specified
8890% image filename.
8891%
8892% The format of the XRemoteCommand method is:
8893%
8894% MagickBooleanType XRemoteCommand(Display *display,const char *window,
8895% const char *filename)
8896%
8897% A description of each parameter follows:
8898%
8899% o display: Specifies a connection to an X server; returned from
8900% XOpenDisplay.
8901%
8902% o window: Specifies the name or id of an X window.
8903%
8904% o filename: the name of the image filename to display.
8905%
8906*/
8907MagickExport MagickBooleanType XRemoteCommand(Display *display,
8908 const char *window,const char *filename)
8909{
8910 Atom
8911 remote_atom;
8912
8913 Window
8914 remote_window,
8915 root_window;
8916
8917 assert(filename != (char *) NULL);
8918 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",filename);
8919 if (display == (Display *) NULL)
8920 display=XOpenDisplay((char *) NULL);
8921 if (display == (Display *) NULL)
8922 {
8923 ThrowXWindowException(XServerError,"UnableToOpenXServer",filename);
8924 return(MagickFalse);
8925 }
8926 remote_atom=XInternAtom(display,"IM_PROTOCOLS",MagickFalse);
8927 remote_window=(Window) NULL;
8928 root_window=XRootWindow(display,XDefaultScreen(display));
8929 if (window != (char *) NULL)
8930 {
8931 /*
8932 Search window hierarchy and identify any clients by name or ID.
8933 */
8934 if (isdigit((unsigned char) *window) != 0)
8935 remote_window=XWindowByID(display,root_window,(Window)
8936 strtol((char *) window,(char **) NULL,0));
8937 if (remote_window == (Window) NULL)
8938 remote_window=XWindowByName(display,root_window,window);
8939 }
8940 if (remote_window == (Window) NULL)
8941 remote_window=XWindowByProperty(display,root_window,remote_atom);
8942 if (remote_window == (Window) NULL)
8943 {
8944 ThrowXWindowException(XServerError,"UnableToConnectToRemoteDisplay",
8945 filename);
8946 return(MagickFalse);
8947 }
8948 /*
8949 Send remote command.
8950 */
8951 remote_atom=XInternAtom(display,"IM_REMOTE_COMMAND",MagickFalse);
8952 (void) XChangeProperty(display,remote_window,remote_atom,XA_STRING,8,
8953 PropModeReplace,(unsigned char *) filename,(int) strlen(filename));
8954 (void) XSync(display,MagickFalse);
8955 return(MagickTrue);
8956}
8957
8958/*
8959%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8960% %
8961% %
8962% %
8963% X R e t a i n W i n d o w C o l o r s %
8964% %
8965% %
8966% %
8967%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8968%
8969% XRetainWindowColors() sets X11 color resources on a window. This preserves
8970% the colors associated with an image displayed on the window.
8971%
8972% The format of the XRetainWindowColors method is:
8973%
8974% void XRetainWindowColors(Display *display,const Window window)
8975%
8976% A description of each parameter follows:
8977%
8978% o display: Specifies a connection to an X server; returned from
8979% XOpenDisplay.
8980%
8981% o window: Specifies a pointer to a XWindowInfo structure.
8982%
8983*/
8984MagickExport void XRetainWindowColors(Display *display,const Window window)
8985{
8986 Atom
8987 property;
8988
8989 Pixmap
8990 pixmap;
8991
8992 /*
8993 Put property on the window.
8994 */
8995 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
8996 assert(display != (Display *) NULL);
8997 assert(window != (Window) NULL);
8998 property=XInternAtom(display,"_XSETROOT_ID",MagickFalse);
8999 if (property == (Atom) NULL)
9000 {
9001 ThrowXWindowFatalException(XServerError,"UnableToCreateProperty",
9002 "_XSETROOT_ID");
9003 return;
9004 }
9005 pixmap=XCreatePixmap(display,window,1,1,1);
9006 if (pixmap == (Pixmap) NULL)
9007 {
9008 ThrowXWindowFatalException(XServerError,"UnableToCreateBitmap","");
9009 return;
9010 }
9011 (void) XChangeProperty(display,window,property,XA_PIXMAP,32,PropModeReplace,
9012 (unsigned char *) &pixmap,1);
9013 (void) XSetCloseDownMode(display,RetainPermanent);
9014}
9015
9016/*
9017%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9018% %
9019% %
9020% %
9021% X S e l e c t W i n d o w %
9022% %
9023% %
9024% %
9025%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9026%
9027% XSelectWindow() allows a user to select a window using the mouse. If the
9028% mouse moves, a cropping rectangle is drawn and the extents of the rectangle
9029% is returned in the crop_info structure.
9030%
9031% The format of the XSelectWindow function is:
9032%
9033% target_window=XSelectWindow(display,crop_info)
9034%
9035% A description of each parameter follows:
9036%
9037% o window: XSelectWindow returns the window id.
9038%
9039% o display: Specifies a pointer to the Display structure; returned from
9040% XOpenDisplay.
9041%
9042% o crop_info: Specifies a pointer to a RectangleInfo structure. It
9043% contains the extents of any cropping rectangle.
9044%
cristy3ed852e2009-09-05 21:47:34 +00009045*/
9046static Window XSelectWindow(Display *display,RectangleInfo *crop_info)
9047{
9048#define MinimumCropArea (unsigned int) 9
9049
9050 Cursor
9051 target_cursor;
9052
9053 GC
9054 annotate_context;
9055
9056 int
9057 presses,
9058 x_offset,
9059 y_offset;
9060
9061 Status
9062 status;
9063
9064 Window
9065 root_window,
9066 target_window;
9067
9068 XEvent
9069 event;
9070
9071 XGCValues
9072 context_values;
9073
9074 /*
9075 Initialize graphic context.
9076 */
9077 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
9078 assert(display != (Display *) NULL);
9079 assert(crop_info != (RectangleInfo *) NULL);
9080 root_window=XRootWindow(display,XDefaultScreen(display));
9081 context_values.background=XBlackPixel(display,XDefaultScreen(display));
9082 context_values.foreground=XWhitePixel(display,XDefaultScreen(display));
9083 context_values.function=GXinvert;
9084 context_values.plane_mask=
9085 context_values.background ^ context_values.foreground;
9086 context_values.subwindow_mode=IncludeInferiors;
cristybb503372010-05-27 20:51:26 +00009087 annotate_context=XCreateGC(display,root_window,(size_t) (GCBackground |
cristy3ed852e2009-09-05 21:47:34 +00009088 GCForeground | GCFunction | GCSubwindowMode),&context_values);
9089 if (annotate_context == (GC) NULL)
9090 return(MagickFalse);
9091 /*
9092 Grab the pointer using target cursor.
9093 */
9094 target_cursor=XMakeCursor(display,root_window,XDefaultColormap(display,
9095 XDefaultScreen(display)),(char * ) "white",(char * ) "black");
9096 status=XGrabPointer(display,root_window,MagickFalse,(unsigned int)
9097 (ButtonPressMask | ButtonReleaseMask | ButtonMotionMask),GrabModeSync,
9098 GrabModeAsync,root_window,target_cursor,CurrentTime);
9099 if (status != GrabSuccess)
9100 {
9101 ThrowXWindowFatalException(XServerError,"UnableToGrabMouse","");
9102 return((Window) NULL);
9103 }
9104 /*
9105 Select a window.
9106 */
9107 crop_info->width=0;
9108 crop_info->height=0;
9109 presses=0;
9110 target_window=(Window) NULL;
9111 x_offset=0;
9112 y_offset=0;
9113 do
9114 {
9115 if ((crop_info->width*crop_info->height) >= MinimumCropArea)
9116 (void) XDrawRectangle(display,root_window,annotate_context,
9117 (int) crop_info->x,(int) crop_info->y,(unsigned int) crop_info->width-1,
9118 (unsigned int) crop_info->height-1);
9119 /*
9120 Allow another event.
9121 */
9122 (void) XAllowEvents(display,SyncPointer,CurrentTime);
9123 (void) XWindowEvent(display,root_window,ButtonPressMask |
9124 ButtonReleaseMask | ButtonMotionMask,&event);
9125 if ((crop_info->width*crop_info->height) >= MinimumCropArea)
9126 (void) XDrawRectangle(display,root_window,annotate_context,
9127 (int) crop_info->x,(int) crop_info->y,(unsigned int) crop_info->width-1,
9128 (unsigned int) crop_info->height-1);
9129 switch (event.type)
9130 {
9131 case ButtonPress:
9132 {
9133 target_window=XGetSubwindow(display,event.xbutton.subwindow,
9134 event.xbutton.x,event.xbutton.y);
9135 if (target_window == (Window) NULL)
9136 target_window=root_window;
9137 x_offset=event.xbutton.x_root;
9138 y_offset=event.xbutton.y_root;
cristyecd0ab52010-05-30 14:59:20 +00009139 crop_info->x=(ssize_t) x_offset;
9140 crop_info->y=(ssize_t) y_offset;
cristy3ed852e2009-09-05 21:47:34 +00009141 crop_info->width=0;
9142 crop_info->height=0;
9143 presses++;
9144 break;
9145 }
9146 case ButtonRelease:
9147 {
9148 presses--;
9149 break;
9150 }
9151 case MotionNotify:
9152 {
9153 /*
9154 Discard pending button motion events.
9155 */
9156 while (XCheckMaskEvent(display,ButtonMotionMask,&event)) ;
cristyecd0ab52010-05-30 14:59:20 +00009157 crop_info->x=(ssize_t) event.xmotion.x;
9158 crop_info->y=(ssize_t) event.xmotion.y;
cristy3ed852e2009-09-05 21:47:34 +00009159 /*
9160 Check boundary conditions.
9161 */
9162 if ((int) crop_info->x < x_offset)
cristyecd0ab52010-05-30 14:59:20 +00009163 crop_info->width=(size_t) (x_offset-crop_info->x);
cristy3ed852e2009-09-05 21:47:34 +00009164 else
9165 {
cristyecd0ab52010-05-30 14:59:20 +00009166 crop_info->width=(size_t) (crop_info->x-x_offset);
9167 crop_info->x=(ssize_t) x_offset;
cristy3ed852e2009-09-05 21:47:34 +00009168 }
9169 if ((int) crop_info->y < y_offset)
cristyecd0ab52010-05-30 14:59:20 +00009170 crop_info->height=(size_t) (y_offset-crop_info->y);
cristy3ed852e2009-09-05 21:47:34 +00009171 else
9172 {
cristyecd0ab52010-05-30 14:59:20 +00009173 crop_info->height=(size_t) (crop_info->y-y_offset);
9174 crop_info->y=(ssize_t) y_offset;
cristy3ed852e2009-09-05 21:47:34 +00009175 }
9176 }
9177 default:
9178 break;
9179 }
9180 } while ((target_window == (Window) NULL) || (presses > 0));
9181 (void) XUngrabPointer(display,CurrentTime);
9182 (void) XFreeCursor(display,target_cursor);
9183 (void) XFreeGC(display,annotate_context);
9184 if ((crop_info->width*crop_info->height) < MinimumCropArea)
9185 {
9186 crop_info->width=0;
9187 crop_info->height=0;
9188 }
9189 if ((crop_info->width != 0) && (crop_info->height != 0))
9190 target_window=root_window;
9191 return(target_window);
9192}
9193
9194/*
9195%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9196% %
9197% %
9198% %
9199% X S e t C u r s o r S t a t e %
9200% %
9201% %
9202% %
9203%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9204%
9205% XSetCursorState() sets the cursor state to busy, otherwise the cursor are
9206% reset to their default.
9207%
9208% The format of the XXSetCursorState method is:
9209%
9210% XSetCursorState(display,windows,const MagickStatusType state)
9211%
9212% A description of each parameter follows:
9213%
9214% o display: Specifies a connection to an X server; returned from
9215% XOpenDisplay.
9216%
9217% o windows: Specifies a pointer to a XWindows structure.
9218%
9219% o state: An unsigned integer greater than 0 sets the cursor state
9220% to busy, otherwise the cursor are reset to their default.
9221%
9222*/
cristybcbda3f2011-09-03 13:01:22 +00009223MagickPrivate void XSetCursorState(Display *display,XWindows *windows,
cristy3ed852e2009-09-05 21:47:34 +00009224 const MagickStatusType state)
9225{
9226 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
9227 assert(display != (Display *) NULL);
9228 assert(windows != (XWindows *) NULL);
9229 if (state)
9230 {
9231 (void) XCheckDefineCursor(display,windows->image.id,
9232 windows->image.busy_cursor);
9233 (void) XCheckDefineCursor(display,windows->pan.id,
9234 windows->pan.busy_cursor);
9235 (void) XCheckDefineCursor(display,windows->magnify.id,
9236 windows->magnify.busy_cursor);
9237 (void) XCheckDefineCursor(display,windows->command.id,
9238 windows->command.busy_cursor);
9239 }
9240 else
9241 {
9242 (void) XCheckDefineCursor(display,windows->image.id,
9243 windows->image.cursor);
9244 (void) XCheckDefineCursor(display,windows->pan.id,windows->pan.cursor);
9245 (void) XCheckDefineCursor(display,windows->magnify.id,
9246 windows->magnify.cursor);
9247 (void) XCheckDefineCursor(display,windows->command.id,
9248 windows->command.cursor);
9249 (void) XCheckDefineCursor(display,windows->command.id,
9250 windows->widget.cursor);
9251 (void) XWithdrawWindow(display,windows->info.id,windows->info.screen);
9252 }
9253 windows->info.mapped=MagickFalse;
9254}
9255
9256/*
9257%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9258% %
9259% %
9260% %
9261% X S e t W i n d o w s %
9262% %
9263% %
9264% %
9265%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9266%
9267% XSetWindows() sets the X windows structure if the windows info is specified.
9268% Otherwise the current windows structure is returned.
9269%
9270% The format of the XSetWindows method is:
9271%
9272% XWindows *XSetWindows(XWindows *windows_info)
9273%
9274% A description of each parameter follows:
9275%
9276% o windows_info: Initialize the Windows structure with this information.
9277%
9278*/
cristybcbda3f2011-09-03 13:01:22 +00009279MagickPrivate XWindows *XSetWindows(XWindows *windows_info)
cristy3ed852e2009-09-05 21:47:34 +00009280{
9281 static XWindows
9282 *windows = (XWindows *) NULL;
9283
9284 if (windows_info != (XWindows *) ~0)
9285 {
9286 windows=(XWindows *) RelinquishMagickMemory(windows);
9287 windows=windows_info;
9288 }
9289 return(windows);
9290}
9291/*
9292%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9293% %
9294% %
9295% %
9296% X U s e r P r e f e r e n c e s %
9297% %
9298% %
9299% %
9300%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9301%
9302% XUserPreferences() saves the preferences in a configuration file in the
9303% users' home directory.
9304%
9305% The format of the XUserPreferences method is:
9306%
9307% void XUserPreferences(XResourceInfo *resource_info)
9308%
9309% A description of each parameter follows:
9310%
9311% o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
9312%
9313*/
cristybcbda3f2011-09-03 13:01:22 +00009314MagickPrivate void XUserPreferences(XResourceInfo *resource_info)
cristy3ed852e2009-09-05 21:47:34 +00009315{
9316#if defined(X11_PREFERENCES_PATH)
9317 char
9318 cache[MaxTextExtent],
9319 filename[MaxTextExtent],
9320 specifier[MaxTextExtent];
9321
9322 const char
cristy104cea82009-10-25 02:26:51 +00009323 *client_name,
cristy3ed852e2009-09-05 21:47:34 +00009324 *value;
9325
9326 XrmDatabase
9327 preferences_database;
9328
9329 /*
9330 Save user preferences to the client configuration file.
9331 */
9332 assert(resource_info != (XResourceInfo *) NULL);
cristy104cea82009-10-25 02:26:51 +00009333 client_name=GetClientName();
cristy3ed852e2009-09-05 21:47:34 +00009334 preferences_database=XrmGetStringDatabase("");
cristyb51dff52011-05-19 16:55:47 +00009335 (void) FormatLocaleString(specifier,MaxTextExtent,"%s.backdrop",client_name);
cristy3ed852e2009-09-05 21:47:34 +00009336 value=resource_info->backdrop ? "True" : "False";
9337 XrmPutStringResource(&preferences_database,specifier,(char *) value);
cristyb51dff52011-05-19 16:55:47 +00009338 (void) FormatLocaleString(specifier,MaxTextExtent,"%s.colormap",client_name);
cristy3ed852e2009-09-05 21:47:34 +00009339 value=resource_info->colormap == SharedColormap ? "Shared" : "Private";
9340 XrmPutStringResource(&preferences_database,specifier,(char *) value);
cristyb51dff52011-05-19 16:55:47 +00009341 (void) FormatLocaleString(specifier,MaxTextExtent,"%s.confirmExit",
cristy104cea82009-10-25 02:26:51 +00009342 client_name);
cristy3ed852e2009-09-05 21:47:34 +00009343 value=resource_info->confirm_exit ? "True" : "False";
9344 XrmPutStringResource(&preferences_database,specifier,(char *) value);
cristyb51dff52011-05-19 16:55:47 +00009345 (void) FormatLocaleString(specifier,MaxTextExtent,"%s.confirmEdit",
cristy104cea82009-10-25 02:26:51 +00009346 client_name);
cristy3ed852e2009-09-05 21:47:34 +00009347 value=resource_info->confirm_edit ? "True" : "False";
9348 XrmPutStringResource(&preferences_database,specifier,(char *) value);
cristyb51dff52011-05-19 16:55:47 +00009349 (void) FormatLocaleString(specifier,MaxTextExtent,"%s.displayWarnings",
cristy104cea82009-10-25 02:26:51 +00009350 client_name);
cristy3ed852e2009-09-05 21:47:34 +00009351 value=resource_info->display_warnings ? "True" : "False";
9352 XrmPutStringResource(&preferences_database,specifier,(char *) value);
cristyb51dff52011-05-19 16:55:47 +00009353 (void) FormatLocaleString(specifier,MaxTextExtent,"%s.dither",client_name);
cristy3ed852e2009-09-05 21:47:34 +00009354 value=resource_info->quantize_info->dither ? "True" : "False";
9355 XrmPutStringResource(&preferences_database,specifier,(char *) value);
cristyb51dff52011-05-19 16:55:47 +00009356 (void) FormatLocaleString(specifier,MaxTextExtent,"%s.gammaCorrect",
cristy104cea82009-10-25 02:26:51 +00009357 client_name);
cristy3ed852e2009-09-05 21:47:34 +00009358 value=resource_info->gamma_correct ? "True" : "False";
9359 XrmPutStringResource(&preferences_database,specifier,(char *) value);
cristyb51dff52011-05-19 16:55:47 +00009360 (void) FormatLocaleString(specifier,MaxTextExtent,"%s.undoCache",client_name);
9361 (void) FormatLocaleString(cache,MaxTextExtent,"%.20g",(double)
cristy3ed852e2009-09-05 21:47:34 +00009362 resource_info->undo_cache);
9363 XrmPutStringResource(&preferences_database,specifier,cache);
cristyb51dff52011-05-19 16:55:47 +00009364 (void) FormatLocaleString(specifier,MaxTextExtent,"%s.usePixmap",client_name);
cristy3ed852e2009-09-05 21:47:34 +00009365 value=resource_info->use_pixmap ? "True" : "False";
9366 XrmPutStringResource(&preferences_database,specifier,(char *) value);
cristyb51dff52011-05-19 16:55:47 +00009367 (void) FormatLocaleString(filename,MaxTextExtent,"%s%src",
cristy104cea82009-10-25 02:26:51 +00009368 X11_PREFERENCES_PATH,client_name);
cristy3ed852e2009-09-05 21:47:34 +00009369 ExpandFilename(filename);
9370 XrmPutFileDatabase(preferences_database,filename);
9371#endif
9372}
9373
9374/*
9375%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9376% %
9377% %
9378% %
9379% X V i s u a l C l a s s N a m e %
9380% %
9381% %
9382% %
9383%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9384%
9385% XVisualClassName() returns the visual class name as a character string.
9386%
9387% The format of the XVisualClassName method is:
9388%
9389% char *XVisualClassName(const int visual_class)
9390%
9391% A description of each parameter follows:
9392%
9393% o visual_type: XVisualClassName returns the visual class as a character
9394% string.
9395%
9396% o class: Specifies the visual class.
9397%
cristy3ed852e2009-09-05 21:47:34 +00009398*/
9399static const char *XVisualClassName(const int visual_class)
9400{
9401 switch (visual_class)
9402 {
9403 case StaticGray: return("StaticGray");
9404 case GrayScale: return("GrayScale");
9405 case StaticColor: return("StaticColor");
9406 case PseudoColor: return("PseudoColor");
9407 case TrueColor: return("TrueColor");
9408 case DirectColor: return("DirectColor");
9409 }
9410 return("unknown visual class");
9411}
9412
9413/*
9414%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9415% %
9416% %
9417% %
9418% X W a r n i n g %
9419% %
9420% %
9421% %
9422%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9423%
9424% XWarning() displays a warning reason in a Notice widget.
9425%
9426% The format of the XWarning method is:
9427%
9428% void XWarning(const unsigned int warning,const char *reason,
9429% const char *description)
9430%
9431% A description of each parameter follows:
9432%
9433% o warning: Specifies the numeric warning category.
9434%
9435% o reason: Specifies the reason to display before terminating the
9436% program.
9437%
9438% o description: Specifies any description to the reason.
9439%
9440*/
cristybcbda3f2011-09-03 13:01:22 +00009441MagickPrivate void XWarning(const ExceptionType magick_unused(warning),
cristy3ed852e2009-09-05 21:47:34 +00009442 const char *reason,const char *description)
9443{
9444 char
9445 text[MaxTextExtent];
9446
9447 XWindows
9448 *windows;
9449
9450 if (reason == (char *) NULL)
9451 return;
9452 (void) CopyMagickString(text,reason,MaxTextExtent);
9453 (void) ConcatenateMagickString(text,":",MaxTextExtent);
9454 windows=XSetWindows((XWindows *) ~0);
9455 XNoticeWidget(windows->display,windows,text,(char *) description);
9456}
9457
9458/*
9459%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9460% %
9461% %
9462% %
9463% X W i n d o w B y I D %
9464% %
9465% %
9466% %
9467%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9468%
9469% XWindowByID() locates a child window with a given ID. If not window with
9470% the given name is found, 0 is returned. Only the window specified and its
9471% subwindows are searched.
9472%
9473% The format of the XWindowByID function is:
9474%
9475% child=XWindowByID(display,window,id)
9476%
9477% A description of each parameter follows:
9478%
9479% o child: XWindowByID returns the window with the specified
9480% id. If no windows are found, XWindowByID returns 0.
9481%
9482% o display: Specifies a pointer to the Display structure; returned from
9483% XOpenDisplay.
9484%
9485% o id: Specifies the id of the window to locate.
9486%
9487*/
cristybcbda3f2011-09-03 13:01:22 +00009488MagickPrivate Window XWindowByID(Display *display,const Window root_window,
cristybb503372010-05-27 20:51:26 +00009489 const size_t id)
cristy3ed852e2009-09-05 21:47:34 +00009490{
9491 RectangleInfo
9492 rectangle_info;
9493
9494 register int
9495 i;
9496
9497 Status
9498 status;
9499
9500 unsigned int
9501 number_children;
9502
9503 Window
9504 child,
9505 *children,
9506 window;
9507
9508 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
9509 assert(display != (Display *) NULL);
9510 assert(root_window != (Window) NULL);
9511 if (id == 0)
9512 return(XSelectWindow(display,&rectangle_info));
9513 if (root_window == id)
cristydfe2b662010-08-22 16:17:24 +00009514 return(root_window);
cristy3ed852e2009-09-05 21:47:34 +00009515 status=XQueryTree(display,root_window,&child,&child,&children,
9516 &number_children);
9517 if (status == False)
9518 return((Window) NULL);
9519 window=(Window) NULL;
9520 for (i=0; i < (int) number_children; i++)
9521 {
9522 /*
9523 Search each child and their children.
9524 */
9525 window=XWindowByID(display,children[i],id);
9526 if (window != (Window) NULL)
9527 break;
9528 }
9529 if (children != (Window *) NULL)
9530 (void) XFree((void *) children);
9531 return(window);
9532}
9533
9534/*
9535%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9536% %
9537% %
9538% %
9539% X W i n d o w B y N a m e %
9540% %
9541% %
9542% %
9543%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9544%
9545% XWindowByName() locates a window with a given name on a display. If no
9546% window with the given name is found, 0 is returned. If more than one window
9547% has the given name, the first one is returned. Only root and its children
9548% are searched.
9549%
9550% The format of the XWindowByName function is:
9551%
9552% window=XWindowByName(display,root_window,name)
9553%
9554% A description of each parameter follows:
9555%
9556% o window: XWindowByName returns the window id.
9557%
9558% o display: Specifies a pointer to the Display structure; returned from
9559% XOpenDisplay.
9560%
9561% o root_window: Specifies the id of the root window.
9562%
9563% o name: Specifies the name of the window to locate.
9564%
9565*/
cristybcbda3f2011-09-03 13:01:22 +00009566MagickPrivate Window XWindowByName(Display *display,const Window root_window,
cristy3ed852e2009-09-05 21:47:34 +00009567 const char *name)
9568{
9569 register int
9570 i;
9571
9572 Status
9573 status;
9574
9575 unsigned int
9576 number_children;
9577
9578 Window
9579 *children,
9580 child,
9581 window;
9582
9583 XTextProperty
9584 window_name;
9585
9586 assert(display != (Display *) NULL);
9587 assert(root_window != (Window) NULL);
9588 assert(name != (char *) NULL);
9589 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",name);
9590 if (XGetWMName(display,root_window,&window_name) != 0)
9591 if (LocaleCompare((char *) window_name.value,name) == 0)
9592 return(root_window);
9593 status=XQueryTree(display,root_window,&child,&child,&children,
9594 &number_children);
9595 if (status == False)
9596 return((Window) NULL);
9597 window=(Window) NULL;
9598 for (i=0; i < (int) number_children; i++)
9599 {
9600 /*
9601 Search each child and their children.
9602 */
9603 window=XWindowByName(display,children[i],name);
9604 if (window != (Window) NULL)
9605 break;
9606 }
9607 if (children != (Window *) NULL)
9608 (void) XFree((void *) children);
9609 return(window);
9610}
9611
9612/*
9613%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9614% %
9615% %
9616% %
9617% X W i n d o w B y P r o p e r y %
9618% %
9619% %
9620% %
9621%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9622%
9623% XWindowByProperty() locates a child window with a given property. If not
9624% window with the given name is found, 0 is returned. If more than one window
9625% has the given property, the first one is returned. Only the window
9626% specified and its subwindows are searched.
9627%
9628% The format of the XWindowByProperty function is:
9629%
9630% child=XWindowByProperty(display,window,property)
9631%
9632% A description of each parameter follows:
9633%
9634% o child: XWindowByProperty returns the window id with the specified
9635% property. If no windows are found, XWindowByProperty returns 0.
9636%
9637% o display: Specifies a pointer to the Display structure; returned from
9638% XOpenDisplay.
9639%
9640% o property: Specifies the property of the window to locate.
9641%
9642*/
cristybcbda3f2011-09-03 13:01:22 +00009643MagickPrivate Window XWindowByProperty(Display *display,const Window window,
cristy3ed852e2009-09-05 21:47:34 +00009644 const Atom property)
9645{
9646 Atom
9647 type;
9648
9649 int
9650 format;
9651
9652 Status
9653 status;
9654
9655 unsigned char
9656 *data;
9657
9658 unsigned int
9659 i,
9660 number_children;
9661
cristyf2faecf2010-05-28 19:19:36 +00009662 unsigned long
cristy3ed852e2009-09-05 21:47:34 +00009663 after,
9664 number_items;
9665
9666 Window
9667 child,
9668 *children,
9669 parent,
9670 root;
9671
9672 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
9673 assert(display != (Display *) NULL);
9674 assert(window != (Window) NULL);
9675 assert(property != (Atom) NULL);
9676 status=XQueryTree(display,window,&root,&parent,&children,&number_children);
9677 if (status == False)
9678 return((Window) NULL);
9679 type=(Atom) NULL;
9680 child=(Window) NULL;
9681 for (i=0; (i < number_children) && (child == (Window) NULL); i++)
9682 {
9683 status=XGetWindowProperty(display,children[i],property,0L,0L,MagickFalse,
9684 (Atom) AnyPropertyType,&type,&format,&number_items,&after,&data);
9685 if (data != NULL)
9686 (void) XFree((void *) data);
9687 if ((status == Success) && (type != (Atom) NULL))
9688 child=children[i];
9689 }
9690 for (i=0; (i < number_children) && (child == (Window) NULL); i++)
9691 child=XWindowByProperty(display,children[i],property);
9692 if (children != (Window *) NULL)
9693 (void) XFree((void *) children);
9694 return(child);
9695}
9696#else
9697
9698/*
9699%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9700% %
9701% %
9702% %
9703% X I m p o r t I m a g e %
9704% %
9705% %
9706% %
9707%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9708%
9709% XImportImage() reads an image from an X window.
9710%
9711% The format of the XImportImage method is:
9712%
9713% Image *XImportImage(const ImageInfo *image_info,XImportInfo *ximage_info)
9714%
9715% A description of each parameter follows:
9716%
9717% o image_info: the image info..
9718%
9719% o ximage_info: Specifies a pointer to an XImportInfo structure.
9720%
9721*/
cristybcbda3f2011-09-03 13:01:22 +00009722MagickPrivate Image *XImportImage(const ImageInfo *image_info,
cristy3ed852e2009-09-05 21:47:34 +00009723 XImportInfo *ximage_info)
9724{
9725 assert(image_info != (const ImageInfo *) NULL);
9726 assert(image_info->signature == MagickSignature);
9727 if (image_info->debug != MagickFalse)
9728 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
9729 image_info->filename);
9730 assert(ximage_info != (XImportInfo *) NULL);
9731 return((Image *) NULL);
9732}
9733#endif
9734
9735/*
9736%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9737% %
9738% %
9739% %
cristy576974e2009-10-25 20:45:31 +00009740+ X C o m p o n e n t G e n e s i s %
9741% %
9742% %
9743% %
9744%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9745%
9746% XComponentGenesis() instantiates the X component.
9747%
9748% The format of the XComponentGenesis method is:
9749%
9750% MagickBooleanType XComponentGenesis(void)
9751%
9752*/
cristy5ff4eaf2011-09-03 01:38:02 +00009753MagickPrivate MagickBooleanType XComponentGenesis(void)
cristy576974e2009-10-25 20:45:31 +00009754{
9755 return(MagickTrue);
9756}
9757
9758/*
9759%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9760% %
9761% %
9762% %
cristy3ed852e2009-09-05 21:47:34 +00009763% X G e t I m p o r t I n f o %
9764% %
9765% %
9766% %
9767%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9768%
9769% XGetImportInfo() initializes the XImportInfo structure.
9770%
9771% The format of the XGetImportInfo method is:
9772%
9773% void XGetImportInfo(XImportInfo *ximage_info)
9774%
9775% A description of each parameter follows:
9776%
9777% o ximage_info: Specifies a pointer to an ImageInfo structure.
9778%
9779*/
9780MagickExport void XGetImportInfo(XImportInfo *ximage_info)
9781{
9782 assert(ximage_info != (XImportInfo *) NULL);
9783 ximage_info->frame=MagickFalse;
9784 ximage_info->borders=MagickFalse;
9785 ximage_info->screen=MagickFalse;
9786 ximage_info->descend=MagickTrue;
9787 ximage_info->silent=MagickFalse;
9788}