blob: 4304c161f69aa331e117399e19bed4a159f6deb7 [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 {
392 if (windows->class_hints->res_name != (char *) NULL)
393 XFree(windows->class_hints->res_name);
394 if (windows->class_hints->res_class != (char *) NULL)
395 XFree(windows->class_hints->res_class);
396 XFree(windows->class_hints);
397 windows->class_hints=(XClassHint *) NULL;
398 }
399 if (windows->manager_hints != (XWMHints *) NULL)
400 {
401 XFree(windows->manager_hints);
402 windows->manager_hints=(XWMHints *) NULL;
403 }
404 if (windows->map_info != (XStandardColormap *) NULL)
405 {
406 XFree(windows->map_info);
407 windows->map_info=(XStandardColormap *) NULL;
408 }
409 if (windows->icon_map != (XStandardColormap *) NULL)
410 {
411 XFree(windows->icon_map);
412 windows->icon_map=(XStandardColormap *) NULL;
413 }
414 if (windows->visual_info != (XVisualInfo *) NULL)
415 {
416 XFree(windows->visual_info);
417 windows->visual_info=(XVisualInfo *) NULL;
418 }
419 if (windows->icon_visual != (XVisualInfo *) NULL)
420 {
421 XFree(windows->icon_visual);
422 windows->icon_visual=(XVisualInfo *) NULL;
423 }
424 (void) XSetWindows((XWindows *) NULL);
425}
426
427/*
428%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
429% %
430% %
431% %
432% X A n n o t a t e I m a g e %
433% %
434% %
435% %
436%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
437%
438% XAnnotateImage() annotates the image with text.
439%
440% The format of the XAnnotateImage method is:
441%
442% MagickBooleanType XAnnotateImage(Display *display,
443% const XPixelInfo *pixel,XAnnotateInfo *annotate_info,Image *image)
444%
445% A description of each parameter follows:
446%
447% o display: Specifies a connection to an X server; returned from
448% XOpenDisplay.
449%
450% o pixel: Specifies a pointer to a XPixelInfo structure.
451%
452% o annotate_info: Specifies a pointer to a XAnnotateInfo structure.
453%
454% o image: the image.
455%
456*/
cristybcbda3f2011-09-03 13:01:22 +0000457MagickPrivate MagickBooleanType XAnnotateImage(Display *display,
cristy3ed852e2009-09-05 21:47:34 +0000458 const XPixelInfo *pixel,XAnnotateInfo *annotate_info,Image *image)
459{
cristyc57f6942010-11-12 01:47:39 +0000460 CacheView
461 *annotate_view;
462
cristy3ed852e2009-09-05 21:47:34 +0000463 GC
464 annotate_context;
465
466 ExceptionInfo
467 *exception;
468
469 Image
470 *annotate_image;
471
472 int
473 x,
474 y;
475
476 MagickBooleanType
477 matte;
478
479 Pixmap
480 annotate_pixmap;
481
482 unsigned int
483 depth,
484 height,
485 width;
486
487 Window
488 root_window;
489
490 XGCValues
491 context_values;
492
493 XImage
494 *annotate_ximage;
495
496 /*
497 Initialize annotated image.
498 */
499 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
500 assert(display != (Display *) NULL);
501 assert(pixel != (XPixelInfo *) NULL);
502 assert(annotate_info != (XAnnotateInfo *) NULL);
503 assert(image != (Image *) NULL);
504 /*
505 Initialize annotated pixmap.
506 */
507 root_window=XRootWindow(display,XDefaultScreen(display));
508 depth=(unsigned int) XDefaultDepth(display,XDefaultScreen(display));
509 annotate_pixmap=XCreatePixmap(display,root_window,annotate_info->width,
510 annotate_info->height,depth);
511 if (annotate_pixmap == (Pixmap) NULL)
512 return(MagickFalse);
513 /*
514 Initialize graphics info.
515 */
516 context_values.background=0;
cristybb503372010-05-27 20:51:26 +0000517 context_values.foreground=(size_t) (~0);
cristy3ed852e2009-09-05 21:47:34 +0000518 context_values.font=annotate_info->font_info->fid;
cristyc57f6942010-11-12 01:47:39 +0000519 annotate_context=XCreateGC(display,root_window,(unsigned long)
520 (GCBackground | GCFont | GCForeground),&context_values);
cristy3ed852e2009-09-05 21:47:34 +0000521 if (annotate_context == (GC) NULL)
522 return(MagickFalse);
523 /*
524 Draw text to pixmap.
525 */
526 (void) XDrawImageString(display,annotate_pixmap,annotate_context,0,
527 (int) annotate_info->font_info->ascent,annotate_info->text,
528 (int) strlen(annotate_info->text));
529 (void) XFreeGC(display,annotate_context);
530 /*
531 Initialize annotated X image.
532 */
533 annotate_ximage=XGetImage(display,annotate_pixmap,0,0,annotate_info->width,
534 annotate_info->height,AllPlanes,ZPixmap);
535 if (annotate_ximage == (XImage *) NULL)
536 return(MagickFalse);
537 (void) XFreePixmap(display,annotate_pixmap);
538 /*
539 Initialize annotated image.
540 */
541 annotate_image=AcquireImage((ImageInfo *) NULL);
542 if (annotate_image == (Image *) NULL)
543 return(MagickFalse);
544 annotate_image->columns=annotate_info->width;
545 annotate_image->rows=annotate_info->height;
546 /*
547 Transfer annotated X image to image.
548 */
549 width=(unsigned int) image->columns;
550 height=(unsigned int) image->rows;
551 x=0;
552 y=0;
553 (void) XParseGeometry(annotate_info->geometry,&x,&y,&width,&height);
cristyc57f6942010-11-12 01:47:39 +0000554 (void) GetOneVirtualPixel(image,(ssize_t) x,(ssize_t) y,
555 &annotate_image->background_color,&image->exception);
cristy3ed852e2009-09-05 21:47:34 +0000556 if (annotate_info->stencil == ForegroundStencil)
557 annotate_image->matte=MagickTrue;
558 exception=(&image->exception);
cristyc57f6942010-11-12 01:47:39 +0000559 annotate_view=AcquireCacheView(annotate_image);
cristy3ed852e2009-09-05 21:47:34 +0000560 for (y=0; y < (int) annotate_image->rows; y++)
561 {
cristyc57f6942010-11-12 01:47:39 +0000562 register int
cristy3ed852e2009-09-05 21:47:34 +0000563 x;
564
cristy4c08aed2011-07-01 19:47:50 +0000565 register Quantum
cristyc47d1f82009-11-26 01:44:43 +0000566 *restrict q;
cristy3ed852e2009-09-05 21:47:34 +0000567
cristyc57f6942010-11-12 01:47:39 +0000568 q=GetCacheViewAuthenticPixels(annotate_view,0,(ssize_t) y,
569 annotate_image->columns,1,exception);
cristyacd2ed22011-08-30 01:44:23 +0000570 if (q == (Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +0000571 break;
cristyc57f6942010-11-12 01:47:39 +0000572 for (x=0; x < (int) annotate_image->columns; x++)
cristy3ed852e2009-09-05 21:47:34 +0000573 {
cristy4c08aed2011-07-01 19:47:50 +0000574 SetPixelAlpha(annotate_image,OpaqueAlpha,q);
cristy3ed852e2009-09-05 21:47:34 +0000575 if (XGetPixel(annotate_ximage,x,y) == 0)
576 {
577 /*
578 Set this pixel to the background color.
579 */
cristy4c08aed2011-07-01 19:47:50 +0000580 SetPixelRed(annotate_image,ScaleShortToQuantum(
581 pixel->box_color.red),q);
582 SetPixelGreen(annotate_image,ScaleShortToQuantum(
583 pixel->box_color.green),q);
584 SetPixelBlue(annotate_image,ScaleShortToQuantum(
585 pixel->box_color.blue),q);
cristy3ed852e2009-09-05 21:47:34 +0000586 if ((annotate_info->stencil == ForegroundStencil) ||
587 (annotate_info->stencil == OpaqueStencil))
cristy4c08aed2011-07-01 19:47:50 +0000588 SetPixelAlpha(annotate_image,TransparentAlpha,q);
cristy3ed852e2009-09-05 21:47:34 +0000589 }
590 else
591 {
592 /*
593 Set this pixel to the pen color.
594 */
cristy4c08aed2011-07-01 19:47:50 +0000595 SetPixelRed(annotate_image,ScaleShortToQuantum(
596 pixel->pen_color.red),q);
597 SetPixelGreen(annotate_image,ScaleShortToQuantum(
598 pixel->pen_color.green),q);
599 SetPixelBlue(annotate_image,ScaleShortToQuantum(
600 pixel->pen_color.blue),q);
cristy3ed852e2009-09-05 21:47:34 +0000601 if (annotate_info->stencil == BackgroundStencil)
cristy4c08aed2011-07-01 19:47:50 +0000602 SetPixelAlpha(annotate_image,TransparentAlpha,q);
cristy3ed852e2009-09-05 21:47:34 +0000603 }
cristyed231572011-07-14 02:18:59 +0000604 q+=GetPixelChannels(annotate_image);
cristy3ed852e2009-09-05 21:47:34 +0000605 }
cristyc57f6942010-11-12 01:47:39 +0000606 if (SyncCacheViewAuthenticPixels(annotate_view,exception) == MagickFalse)
cristy3ed852e2009-09-05 21:47:34 +0000607 break;
608 }
cristyc57f6942010-11-12 01:47:39 +0000609 annotate_view=DestroyCacheView(annotate_view);
cristy3ed852e2009-09-05 21:47:34 +0000610 XDestroyImage(annotate_ximage);
611 /*
612 Determine annotate geometry.
613 */
614 (void) XParseGeometry(annotate_info->geometry,&x,&y,&width,&height);
615 if ((width != (unsigned int) annotate_image->columns) ||
616 (height != (unsigned int) annotate_image->rows))
617 {
618 char
619 image_geometry[MaxTextExtent];
620
621 /*
622 Scale image.
623 */
cristyb51dff52011-05-19 16:55:47 +0000624 (void) FormatLocaleString(image_geometry,MaxTextExtent,"%ux%u",
cristy3ed852e2009-09-05 21:47:34 +0000625 width,height);
626 (void) TransformImage(&annotate_image,(char *) NULL,image_geometry);
627 }
628 if (annotate_info->degrees != 0.0)
629 {
630 Image
631 *rotate_image;
632
633 int
634 rotations;
635
636 MagickRealType
637 normalized_degrees;
638
639 /*
640 Rotate image.
641 */
642 rotate_image=
643 RotateImage(annotate_image,annotate_info->degrees,&image->exception);
644 if (rotate_image == (Image *) NULL)
645 return(MagickFalse);
646 annotate_image=DestroyImage(annotate_image);
647 annotate_image=rotate_image;
648 /*
649 Annotation is relative to the degree of rotation.
650 */
651 normalized_degrees=annotate_info->degrees;
652 while (normalized_degrees < -45.0)
653 normalized_degrees+=360.0;
654 for (rotations=0; normalized_degrees > 45.0; rotations++)
655 normalized_degrees-=90.0;
656 switch (rotations % 4)
657 {
658 default:
659 case 0:
660 break;
661 case 1:
662 {
663 /*
664 Rotate 90 degrees.
665 */
666 x-=(int) annotate_image->columns/2;
667 y+=(int) annotate_image->columns/2;
668 break;
669 }
670 case 2:
671 {
672 /*
673 Rotate 180 degrees.
674 */
675 x=x-(int) annotate_image->columns;
676 break;
677 }
678 case 3:
679 {
680 /*
681 Rotate 270 degrees.
682 */
683 x=x-(int) annotate_image->columns/2;
684 y=y-(int) (annotate_image->rows-(annotate_image->columns/2));
685 break;
686 }
687 }
688 }
689 /*
690 Composite text onto the image.
691 */
692 (void) XParseGeometry(annotate_info->geometry,&x,&y,&width,&height);
693 matte=image->matte;
694 (void) CompositeImage(image,annotate_image->matte != MagickFalse ?
cristyc57f6942010-11-12 01:47:39 +0000695 OverCompositeOp : CopyCompositeOp,annotate_image,(ssize_t) x,(ssize_t) y);
cristy3ed852e2009-09-05 21:47:34 +0000696 image->matte=matte;
697 annotate_image=DestroyImage(annotate_image);
698 return(MagickTrue);
699}
700
701/*
702%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
703% %
704% %
705% %
706% X B e s t F o n t %
707% %
708% %
709% %
710%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
711%
712% XBestFont() returns the "best" font. "Best" is defined as a font specified
713% in the X resource database or a font such that the text width displayed
714% with the font does not exceed the specified maximum width.
715%
716% The format of the XBestFont method is:
717%
718% XFontStruct *XBestFont(Display *display,
719% const XResourceInfo *resource_info,const MagickBooleanType text_font)
720%
721% A description of each parameter follows:
722%
723% o font: XBestFont returns a pointer to a XFontStruct structure.
724%
725% o display: Specifies a connection to an X server; returned from
726% XOpenDisplay.
727%
728% o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
729%
730% o text_font: True is font should be mono-spaced (typewriter style).
731%
cristy3ed852e2009-09-05 21:47:34 +0000732*/
733
734static char **FontToList(char *font)
735{
736 char
737 **fontlist;
738
739 register char
740 *p,
741 *q;
742
743 register int
744 i;
745
746 unsigned int
747 fonts;
748
749 if (font == (char *) NULL)
750 return((char **) NULL);
751 /*
752 Convert string to an ASCII list.
753 */
754 fonts=1U;
755 for (p=font; *p != '\0'; p++)
756 if ((*p == ':') || (*p == ';') || (*p == ','))
757 fonts++;
758 fontlist=(char **) AcquireQuantumMemory((size_t) fonts+1UL,sizeof(*fontlist));
759 if (fontlist == (char **) NULL)
760 {
761 ThrowXWindowFatalException(ResourceLimitError,"MemoryAllocationFailed",
762 font);
763 return((char **) NULL);
764 }
765 p=font;
766 for (i=0; i < (int) fonts; i++)
767 {
768 for (q=p; *q != '\0'; q++)
769 if ((*q == ':') || (*q == ';') || (*q == ','))
770 break;
771 fontlist[i]=(char *) AcquireQuantumMemory((size_t) (q-p)+1UL,
772 sizeof(*fontlist[i]));
773 if (fontlist[i] == (char *) NULL)
774 {
775 ThrowXWindowFatalException(ResourceLimitError,"MemoryAllocationFailed",
776 font);
777 return((char **) NULL);
778 }
779 (void) CopyMagickString(fontlist[i],p,(size_t) (q-p+1));
780 p=q+1;
781 }
782 fontlist[i]=(char *) NULL;
783 return(fontlist);
784}
785
cristybcbda3f2011-09-03 13:01:22 +0000786MagickPrivate XFontStruct *XBestFont(Display *display,
cristy3ed852e2009-09-05 21:47:34 +0000787 const XResourceInfo *resource_info,const MagickBooleanType text_font)
788{
789 static const char
790 *Fonts[]=
791 {
792 "-*-helvetica-medium-r-normal--12-*-*-*-*-*-iso8859-1",
793 "-*-arial-medium-r-normal--12-*-*-*-*-*-iso8859-1",
794 "-*-helvetica-medium-r-normal--12-*-*-*-*-*-iso8859-15",
795 "-*-arial-medium-r-normal--12-*-*-*-*-*-iso8859-15",
796 "-*-helvetica-medium-r-normal--12-*-*-*-*-*-*-*",
797 "-*-arial-medium-r-normal--12-*-*-*-*-*-*-*",
798 "variable",
799 "fixed",
800 (char *) NULL
801 },
802 *TextFonts[]=
803 {
804 "-*-courier-medium-r-normal-*-12-*-*-*-*-*-iso8859-1",
805 "-*-courier-medium-r-normal-*-12-*-*-*-*-*-iso8859-15",
806 "-*-fixed-medium-r-normal-*-12-*-*-*-*-*-*-*",
807 "fixed",
808 (char *) NULL
809 };
810
811 char
812 *font_name;
813
814 register const char
815 **p;
816
817 XFontStruct
818 *font_info;
819
820 font_info=(XFontStruct *) NULL;
821 font_name=resource_info->font;
822 if (text_font != MagickFalse)
823 font_name=resource_info->text_font;
824 if ((font_name != (char *) NULL) && (*font_name != '\0'))
825 {
826 char
827 **fontlist;
828
829 register int
830 i;
831
832 /*
833 Load preferred font specified in the X resource database.
834 */
835 fontlist=FontToList(font_name);
836 if (fontlist != (char **) NULL)
837 {
838 for (i=0; fontlist[i] != (char *) NULL; i++)
839 {
840 if (font_info == (XFontStruct *) NULL)
841 font_info=XLoadQueryFont(display,fontlist[i]);
842 fontlist[i]=DestroyString(fontlist[i]);
843 }
844 fontlist=(char **) RelinquishMagickMemory(fontlist);
845 }
846 if (font_info == (XFontStruct *) NULL)
847 ThrowXWindowFatalException(XServerError,"UnableToLoadFont",font_name);
848 }
849 /*
850 Load fonts from list of fonts until one is found.
851 */
852 p=Fonts;
853 if (text_font != MagickFalse)
854 p=TextFonts;
855 if (XDisplayHeight(display,XDefaultScreen(display)) >= 748)
856 p++;
857 while (*p != (char *) NULL)
858 {
859 if (font_info != (XFontStruct *) NULL)
860 break;
861 font_info=XLoadQueryFont(display,(char *) *p);
862 p++;
863 }
864 return(font_info);
865}
866
867/*
868%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
869% %
870% %
871% %
872% X B e s t I c o n S i z e %
873% %
874% %
875% %
876%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
877%
878% XBestIconSize() returns the "best" icon size. "Best" is defined as an icon
879% size that maintains the aspect ratio of the image. If the window manager
880% has preferred icon sizes, one of the preferred sizes is used.
881%
882% The format of the XBestIconSize method is:
883%
884% void XBestIconSize(Display *display,XWindowInfo *window,Image *image)
885%
886% A description of each parameter follows:
887%
888% o display: Specifies a connection to an X server; returned from
889% XOpenDisplay.
890%
891% o image: the image.
892%
893*/
cristybcbda3f2011-09-03 13:01:22 +0000894MagickPrivate void XBestIconSize(Display *display,XWindowInfo *window,
cristy3ed852e2009-09-05 21:47:34 +0000895 Image *image)
896{
897 int
898 i,
899 number_sizes;
900
901 MagickRealType
902 scale_factor;
903
904 unsigned int
905 height,
906 icon_height,
907 icon_width,
908 width;
909
910 Window
911 root_window;
912
913 XIconSize
914 *icon_size,
915 *size_list;
916
917 /*
918 Determine if the window manager has specified preferred icon sizes.
919 */
920 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
921 assert(display != (Display *) NULL);
922 assert(window != (XWindowInfo *) NULL);
923 assert(image != (Image *) NULL);
924 window->width=MaxIconSize;
925 window->height=MaxIconSize;
926 icon_size=(XIconSize *) NULL;
927 number_sizes=0;
928 root_window=XRootWindow(display,window->screen);
929 if (XGetIconSizes(display,root_window,&size_list,&number_sizes) != 0)
930 if ((number_sizes > 0) && (size_list != (XIconSize *) NULL))
931 icon_size=size_list;
932 if (icon_size == (XIconSize *) NULL)
933 {
934 /*
935 Window manager does not restrict icon size.
936 */
937 icon_size=XAllocIconSize();
938 if (icon_size == (XIconSize *) NULL)
939 {
940 ThrowXWindowFatalException(ResourceLimitError,
941 "MemoryAllocationFailed",image->filename);
942 return;
943 }
944 icon_size->min_width=1;
945 icon_size->max_width=MaxIconSize;
946 icon_size->min_height=1;
947 icon_size->max_height=MaxIconSize;
948 icon_size->width_inc=1;
949 icon_size->height_inc=1;
950 }
951 /*
952 Determine aspect ratio of image.
953 */
954 width=(unsigned int) image->columns;
955 height=(unsigned int) image->rows;
956 i=0;
957 if (window->crop_geometry)
958 (void) XParseGeometry(window->crop_geometry,&i,&i,&width,&height);
959 /*
960 Look for an icon size that maintains the aspect ratio of image.
961 */
962 scale_factor=(MagickRealType) icon_size->max_width/width;
963 if (scale_factor > ((MagickRealType) icon_size->max_height/height))
964 scale_factor=(MagickRealType) icon_size->max_height/height;
965 icon_width=(unsigned int) icon_size->min_width;
966 while ((int) icon_width < icon_size->max_width)
967 {
968 if (icon_width >= (unsigned int) (scale_factor*width+0.5))
969 break;
970 icon_width+=icon_size->width_inc;
971 }
972 icon_height=(unsigned int) icon_size->min_height;
973 while ((int) icon_height < icon_size->max_height)
974 {
975 if (icon_height >= (unsigned int) (scale_factor*height+0.5))
976 break;
977 icon_height+=icon_size->height_inc;
978 }
979 (void) XFree((void *) icon_size);
980 window->width=icon_width;
981 window->height=icon_height;
982}
983
984/*
985%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
986% %
987% %
988% %
989% X B e s t P i x e l %
990% %
991% %
992% %
993%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
994%
995% XBestPixel() returns a pixel from an array of pixels that is closest to the
996% requested color. If the color array is NULL, the colors are obtained from
997% the X server.
998%
999% The format of the XBestPixel method is:
1000%
1001% void XBestPixel(Display *display,const Colormap colormap,XColor *colors,
1002% unsigned int number_colors,XColor *color)
1003%
1004% A description of each parameter follows:
1005%
1006% o pixel: XBestPixel returns the pixel value closest to the requested
1007% color.
1008%
1009% o display: Specifies a connection to an X server; returned from
1010% XOpenDisplay.
1011%
1012% o colormap: Specifies the ID of the X server colormap.
1013%
1014% o colors: Specifies an array of XColor structures.
1015%
1016% o number_colors: Specifies the number of XColor structures in the
1017% color definition array.
1018%
1019% o color: Specifies the desired RGB value to find in the colors array.
1020%
1021*/
cristybcbda3f2011-09-03 13:01:22 +00001022MagickPrivate void XBestPixel(Display *display,const Colormap colormap,
cristy3ed852e2009-09-05 21:47:34 +00001023 XColor *colors,unsigned int number_colors,XColor *color)
1024{
1025 MagickBooleanType
1026 query_server;
1027
cristy4c08aed2011-07-01 19:47:50 +00001028 PixelInfo
cristy3ed852e2009-09-05 21:47:34 +00001029 pixel;
1030
1031 MagickRealType
1032 min_distance;
1033
1034 register MagickRealType
1035 distance;
1036
1037 register int
1038 i,
1039 j;
1040
1041 Status
1042 status;
1043
1044 /*
1045 Find closest representation for the requested RGB color.
1046 */
1047 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
1048 assert(display != (Display *) NULL);
1049 assert(color != (XColor *) NULL);
1050 status=XAllocColor(display,colormap,color);
1051 if (status != False)
1052 return;
1053 query_server=colors == (XColor *) NULL ? MagickTrue : MagickFalse;
1054 if (query_server != MagickFalse)
1055 {
1056 /*
1057 Read X server colormap.
1058 */
1059 colors=(XColor *) AcquireQuantumMemory(number_colors,sizeof(*colors));
1060 if (colors == (XColor *) NULL)
1061 {
1062 ThrowXWindowFatalException(ResourceLimitError,
1063 "MemoryAllocationFailed","...");
1064 return;
1065 }
1066 for (i=0; i < (int) number_colors; i++)
cristybb503372010-05-27 20:51:26 +00001067 colors[i].pixel=(size_t) i;
cristy3ed852e2009-09-05 21:47:34 +00001068 if (number_colors > 256)
1069 number_colors=256;
1070 (void) XQueryColors(display,colormap,colors,(int) number_colors);
1071 }
1072 min_distance=3.0*((MagickRealType) QuantumRange+1.0)*((MagickRealType)
1073 QuantumRange+1.0);
1074 j=0;
1075 for (i=0; i < (int) number_colors; i++)
1076 {
1077 pixel.red=colors[i].red-(MagickRealType) color->red;
1078 distance=pixel.red*pixel.red;
1079 if (distance > min_distance)
1080 continue;
1081 pixel.green=colors[i].green-(MagickRealType) color->green;
1082 distance+=pixel.green*pixel.green;
1083 if (distance > min_distance)
1084 continue;
1085 pixel.blue=colors[i].blue-(MagickRealType) color->blue;
1086 distance+=pixel.blue*pixel.blue;
1087 if (distance > min_distance)
1088 continue;
1089 min_distance=distance;
1090 color->pixel=colors[i].pixel;
1091 j=i;
1092 }
1093 (void) XAllocColor(display,colormap,&colors[j]);
1094 if (query_server != MagickFalse)
1095 colors=(XColor *) RelinquishMagickMemory(colors);
1096}
1097
1098/*
1099%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1100% %
1101% %
1102% %
1103% X B e s t V i s u a l I n f o %
1104% %
1105% %
1106% %
1107%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1108%
1109% XBestVisualInfo() returns visual information for a visual that is the "best"
1110% the server supports. "Best" is defined as:
1111%
1112% 1. Restrict the visual list to those supported by the default screen.
1113%
1114% 2. If a visual type is specified, restrict the visual list to those of
1115% that type.
1116%
1117% 3. If a map type is specified, choose the visual that matches the id
1118% specified by the Standard Colormap.
1119%
1120% 4 From the list of visuals, choose one that can display the most
1121% simultaneous colors. If more than one visual can display the same
1122% number of simultaneous colors, one is chosen based on a rank.
1123%
1124% The format of the XBestVisualInfo method is:
1125%
1126% XVisualInfo *XBestVisualInfo(Display *display,
1127% XStandardColormap *map_info,XResourceInfo *resource_info)
1128%
1129% A description of each parameter follows:
1130%
1131% o visual_info: XBestVisualInfo returns a pointer to a X11 XVisualInfo
1132% structure.
1133%
1134% o display: Specifies a connection to an X server; returned from
1135% XOpenDisplay.
1136%
1137% o map_info: If map_type is specified, this structure is initialized
1138% with info from the Standard Colormap.
1139%
1140% o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
1141%
1142*/
1143
1144static inline int MagickMax(const int x,const int y)
1145{
1146 if (x > y)
1147 return(x);
1148 return(y);
1149}
1150
cristybb503372010-05-27 20:51:26 +00001151static inline size_t MagickMin(const unsigned int x,
cristy3ed852e2009-09-05 21:47:34 +00001152 const unsigned int y)
1153{
1154 if (x < y)
1155 return(x);
1156 return(y);
1157}
1158
cristybcbda3f2011-09-03 13:01:22 +00001159MagickPrivate XVisualInfo *XBestVisualInfo(Display *display,
cristy3ed852e2009-09-05 21:47:34 +00001160 XStandardColormap *map_info,XResourceInfo *resource_info)
1161{
1162#define MaxStandardColormaps 7
1163#define XVisualColormapSize(visual_info) MagickMin((unsigned int) (\
1164 (visual_info->klass == TrueColor) || (visual_info->klass == DirectColor) ? \
1165 visual_info->red_mask | visual_info->green_mask | visual_info->blue_mask : \
1166 (unsigned int) visual_info->colormap_size),1U << visual_info->depth)
1167
1168 char
1169 *map_type,
1170 *visual_type;
1171
cristyc57f6942010-11-12 01:47:39 +00001172 int
1173 visual_mask;
1174
cristy3ed852e2009-09-05 21:47:34 +00001175 register int
1176 i;
1177
cristy8891f9c2010-06-04 23:32:17 +00001178 size_t
1179 one;
1180
cristy3ed852e2009-09-05 21:47:34 +00001181 static int
1182 number_visuals;
1183
1184 static XVisualInfo
1185 visual_template;
1186
1187 XVisualInfo
1188 *visual_info,
1189 *visual_list;
1190
1191 /*
1192 Restrict visual search by screen number.
1193 */
1194 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
1195 assert(display != (Display *) NULL);
1196 assert(map_info != (XStandardColormap *) NULL);
1197 assert(resource_info != (XResourceInfo *) NULL);
1198 map_type=resource_info->map_type;
1199 visual_type=resource_info->visual_type;
1200 visual_mask=VisualScreenMask;
1201 visual_template.screen=XDefaultScreen(display);
1202 visual_template.depth=XDefaultDepth(display,XDefaultScreen(display));
cristy8891f9c2010-06-04 23:32:17 +00001203 one=1;
cristy3ed852e2009-09-05 21:47:34 +00001204 if ((resource_info->immutable != MagickFalse) && (resource_info->colors != 0))
cristy8891f9c2010-06-04 23:32:17 +00001205 if (resource_info->colors <= (one << (size_t) visual_template.depth))
cristy3ed852e2009-09-05 21:47:34 +00001206 visual_mask|=VisualDepthMask;
1207 if (visual_type != (char *) NULL)
1208 {
1209 /*
1210 Restrict visual search by class or visual id.
1211 */
1212 if (LocaleCompare("staticgray",visual_type) == 0)
1213 {
1214 visual_mask|=VisualClassMask;
1215 visual_template.klass=StaticGray;
1216 }
1217 else
1218 if (LocaleCompare("grayscale",visual_type) == 0)
1219 {
1220 visual_mask|=VisualClassMask;
1221 visual_template.klass=GrayScale;
1222 }
1223 else
1224 if (LocaleCompare("staticcolor",visual_type) == 0)
1225 {
1226 visual_mask|=VisualClassMask;
1227 visual_template.klass=StaticColor;
1228 }
1229 else
1230 if (LocaleCompare("pseudocolor",visual_type) == 0)
1231 {
1232 visual_mask|=VisualClassMask;
1233 visual_template.klass=PseudoColor;
1234 }
1235 else
1236 if (LocaleCompare("truecolor",visual_type) == 0)
1237 {
1238 visual_mask|=VisualClassMask;
1239 visual_template.klass=TrueColor;
1240 }
1241 else
1242 if (LocaleCompare("directcolor",visual_type) == 0)
1243 {
1244 visual_mask|=VisualClassMask;
1245 visual_template.klass=DirectColor;
1246 }
1247 else
1248 if (LocaleCompare("default",visual_type) == 0)
1249 {
1250 visual_mask|=VisualIDMask;
1251 visual_template.visualid=XVisualIDFromVisual(
1252 XDefaultVisual(display,XDefaultScreen(display)));
1253 }
1254 else
1255 if (isdigit((int) ((unsigned char) *visual_type)) != 0)
1256 {
1257 visual_mask|=VisualIDMask;
1258 visual_template.visualid=
1259 strtol(visual_type,(char **) NULL,0);
1260 }
1261 else
1262 ThrowXWindowFatalException(XServerError,
1263 "UnrecognizedVisualSpecifier",visual_type);
1264 }
1265 /*
1266 Get all visuals that meet our criteria so far.
1267 */
1268 number_visuals=0;
1269 visual_list=XGetVisualInfo(display,visual_mask,&visual_template,
1270 &number_visuals);
1271 visual_mask=VisualScreenMask | VisualIDMask;
1272 if ((number_visuals == 0) || (visual_list == (XVisualInfo *) NULL))
1273 {
1274 /*
1275 Failed to get visual; try using the default visual.
1276 */
1277 ThrowXWindowFatalException(XServerWarning,"UnableToGetVisual",
1278 visual_type);
1279 visual_template.visualid=XVisualIDFromVisual(XDefaultVisual(display,
1280 XDefaultScreen(display)));
1281 visual_list=XGetVisualInfo(display,visual_mask,&visual_template,
1282 &number_visuals);
1283 if ((number_visuals == 0) || (visual_list == (XVisualInfo *) NULL))
1284 return((XVisualInfo *) NULL);
1285 ThrowXWindowFatalException(XServerWarning,"UsingDefaultVisual",
1286 XVisualClassName(visual_list->klass));
1287 }
1288 resource_info->color_recovery=MagickFalse;
1289 if ((map_info != (XStandardColormap *) NULL) && (map_type != (char *) NULL))
1290 {
1291 Atom
1292 map_property;
1293
1294 char
1295 map_name[MaxTextExtent];
1296
1297 int
1298 j,
1299 number_maps;
1300
1301 Status
1302 status;
1303
1304 Window
1305 root_window;
1306
1307 XStandardColormap
1308 *map_list;
1309
1310 /*
1311 Choose a visual associated with a standard colormap.
1312 */
1313 root_window=XRootWindow(display,XDefaultScreen(display));
1314 status=False;
1315 if (LocaleCompare(map_type,"list") != 0)
1316 {
1317 /*
1318 User specified Standard Colormap.
1319 */
cristyb51dff52011-05-19 16:55:47 +00001320 (void) FormatLocaleString((char *) map_name,MaxTextExtent,
cristy3ed852e2009-09-05 21:47:34 +00001321 "RGB_%s_MAP",map_type);
1322 LocaleUpper(map_name);
1323 map_property=XInternAtom(display,(char *) map_name,MagickTrue);
1324 if (map_property != (Atom) NULL)
1325 status=XGetRGBColormaps(display,root_window,&map_list,&number_maps,
1326 map_property);
1327 }
1328 else
1329 {
1330 static const char
1331 *colormap[MaxStandardColormaps]=
1332 {
1333 "_HP_RGB_SMOOTH_MAP_LIST",
1334 "RGB_BEST_MAP",
1335 "RGB_DEFAULT_MAP",
1336 "RGB_GRAY_MAP",
1337 "RGB_RED_MAP",
1338 "RGB_GREEN_MAP",
1339 "RGB_BLUE_MAP",
1340 };
1341
1342 /*
1343 Choose a standard colormap from a list.
1344 */
1345 for (i=0; i < MaxStandardColormaps; i++)
1346 {
1347 map_property=XInternAtom(display,(char *) colormap[i],MagickTrue);
1348 if (map_property == (Atom) NULL)
1349 continue;
1350 status=XGetRGBColormaps(display,root_window,&map_list,&number_maps,
1351 map_property);
1352 if (status != False)
1353 break;
1354 }
1355 resource_info->color_recovery=i == 0 ? MagickTrue : MagickFalse;
1356 }
1357 if (status == False)
1358 {
1359 ThrowXWindowFatalException(XServerError,"UnableToGetStandardColormap",
1360 map_type);
1361 return((XVisualInfo *) NULL);
1362 }
1363 /*
1364 Search all Standard Colormaps and visuals for ids that match.
1365 */
1366 *map_info=map_list[0];
1367#if !defined(PRE_R4_ICCCM)
1368 visual_template.visualid=XVisualIDFromVisual(visual_list[0].visual);
1369 for (i=0; i < number_maps; i++)
1370 for (j=0; j < number_visuals; j++)
1371 if (map_list[i].visualid ==
1372 XVisualIDFromVisual(visual_list[j].visual))
1373 {
1374 *map_info=map_list[i];
1375 visual_template.visualid=XVisualIDFromVisual(
1376 visual_list[j].visual);
1377 break;
1378 }
1379 if (map_info->visualid != visual_template.visualid)
1380 {
1381 ThrowXWindowFatalException(XServerError,
1382 "UnableToMatchVisualToStandardColormap",map_type);
1383 return((XVisualInfo *) NULL);
1384 }
1385#endif
1386 if (map_info->colormap == (Colormap) NULL)
1387 {
1388 ThrowXWindowFatalException(XServerError,
1389 "StandardColormapIsNotInitialized",map_type);
1390 return((XVisualInfo *) NULL);
1391 }
1392 (void) XFree((void *) map_list);
1393 }
1394 else
1395 {
1396 static const unsigned int
1397 rank[]=
1398 {
1399 StaticGray,
1400 GrayScale,
1401 StaticColor,
1402 DirectColor,
1403 TrueColor,
1404 PseudoColor
1405 };
1406
1407 XVisualInfo
1408 *p;
1409
1410 /*
1411 Pick one visual that displays the most simultaneous colors.
1412 */
1413 visual_info=visual_list;
1414 p=visual_list;
1415 for (i=1; i < number_visuals; i++)
1416 {
1417 p++;
1418 if (XVisualColormapSize(p) > XVisualColormapSize(visual_info))
1419 visual_info=p;
1420 else
1421 if (XVisualColormapSize(p) == XVisualColormapSize(visual_info))
1422 if (rank[p->klass] > rank[visual_info->klass])
1423 visual_info=p;
1424 }
1425 visual_template.visualid=XVisualIDFromVisual(visual_info->visual);
1426 }
1427 (void) XFree((void *) visual_list);
1428 /*
1429 Retrieve only one visual by its screen & id number.
1430 */
1431 visual_info=XGetVisualInfo(display,visual_mask,&visual_template,
1432 &number_visuals);
1433 if ((number_visuals == 0) || (visual_info == (XVisualInfo *) NULL))
1434 return((XVisualInfo *) NULL);
1435 return(visual_info);
1436}
1437
1438/*
1439%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1440% %
1441% %
1442% %
1443% X C h e c k D e f i n e C u r s o r %
1444% %
1445% %
1446% %
1447%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1448%
1449% XCheckDefineCursor() prevents cursor changes on the root window.
1450%
1451% The format of the XXCheckDefineCursor method is:
1452%
1453% XCheckDefineCursor(display,window,cursor)
1454%
1455% A description of each parameter follows:
1456%
1457% o display: Specifies a connection to an X server; returned from
1458% XOpenDisplay.
1459%
1460% o window: the window.
1461%
1462% o cursor: the cursor.
1463%
1464*/
cristybcbda3f2011-09-03 13:01:22 +00001465MagickPrivate int XCheckDefineCursor(Display *display,Window window,
cristy3ed852e2009-09-05 21:47:34 +00001466 Cursor cursor)
1467{
1468 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
1469 assert(display != (Display *) NULL);
1470 if (window == XRootWindow(display,XDefaultScreen(display)))
1471 return(0);
1472 return(XDefineCursor(display,window,cursor));
1473}
1474
1475/*
1476%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1477% %
1478% %
1479% %
1480% X C h e c k R e f r e s h W i n d o w s %
1481% %
1482% %
1483% %
1484%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1485%
1486% XCheckRefreshWindows() checks the X server for exposure events for a
1487% particular window and updates the areassociated with the exposure event.
1488%
1489% The format of the XCheckRefreshWindows method is:
1490%
1491% void XCheckRefreshWindows(Display *display,XWindows *windows)
1492%
1493% A description of each parameter follows:
1494%
1495% o display: Specifies a connection to an X server; returned from
1496% XOpenDisplay.
1497%
1498% o windows: Specifies a pointer to a XWindows structure.
1499%
1500*/
cristybcbda3f2011-09-03 13:01:22 +00001501MagickPrivate void XCheckRefreshWindows(Display *display,XWindows *windows)
cristy3ed852e2009-09-05 21:47:34 +00001502{
1503 Window
1504 id;
1505
1506 XEvent
1507 event;
1508
1509 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
1510 assert(display != (Display *) NULL);
1511 assert(windows != (XWindows *) NULL);
1512 XDelay(display,SuspendTime);
1513 id=windows->command.id;
1514 while (XCheckTypedWindowEvent(display,id,Expose,&event) != MagickFalse)
1515 (void) XCommandWidget(display,windows,(char const **) NULL,&event);
1516 id=windows->image.id;
1517 while (XCheckTypedWindowEvent(display,id,Expose,&event) != MagickFalse)
1518 XRefreshWindow(display,&windows->image,&event);
1519 XDelay(display,SuspendTime << 1);
1520 id=windows->command.id;
1521 while (XCheckTypedWindowEvent(display,id,Expose,&event) != MagickFalse)
1522 (void) XCommandWidget(display,windows,(char const **) NULL,&event);
1523 id=windows->image.id;
1524 while (XCheckTypedWindowEvent(display,id,Expose,&event) != MagickFalse)
1525 XRefreshWindow(display,&windows->image,&event);
1526}
1527
1528/*
1529%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1530% %
1531% %
1532% %
1533% X C l i e n t M e s s a g e %
1534% %
1535% %
1536% %
1537%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1538%
1539% XClientMessage() sends a reason to a window with XSendEvent. The reason is
1540% initialized with a particular protocol type and atom.
1541%
1542% The format of the XClientMessage function is:
1543%
1544% XClientMessage(display,window,protocol,reason,timestamp)
1545%
1546% A description of each parameter follows:
1547%
1548% o display: Specifies a pointer to the Display structure; returned from
1549% XOpenDisplay.
1550%
1551% o window: Specifies a pointer to a Window structure.
1552%
1553% o protocol: Specifies an atom value.
1554%
1555% o reason: Specifies an atom value which is the reason to send.
1556%
1557% o timestamp: Specifies a value of type Time.
1558%
1559*/
cristybcbda3f2011-09-03 13:01:22 +00001560MagickPrivate void XClientMessage(Display *display,const Window window,
cristy3ed852e2009-09-05 21:47:34 +00001561 const Atom protocol,const Atom reason,const Time timestamp)
1562{
1563 XClientMessageEvent
1564 client_event;
1565
1566 assert(display != (Display *) NULL);
1567 client_event.type=ClientMessage;
1568 client_event.window=window;
1569 client_event.message_type=protocol;
1570 client_event.format=32;
cristyc57f6942010-11-12 01:47:39 +00001571 client_event.data.l[0]=(long) reason;
1572 client_event.data.l[1]=(long) timestamp;
cristy3ed852e2009-09-05 21:47:34 +00001573 (void) XSendEvent(display,window,MagickFalse,NoEventMask,(XEvent *) &client_event);
1574}
1575
1576/*
1577%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1578% %
1579% %
1580% %
1581+ X C l i e n t W i n d o w %
1582% %
1583% %
1584% %
1585%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1586%
1587% XClientWindow() finds a window, at or below the specified window, which has
1588% a WM_STATE property. If such a window is found, it is returned, otherwise
1589% the argument window is returned.
1590%
1591% The format of the XClientWindow function is:
1592%
1593% client_window=XClientWindow(display,target_window)
1594%
1595% A description of each parameter follows:
1596%
1597% o client_window: XClientWindow returns a window, at or below the specified
1598% window, which has a WM_STATE property otherwise the argument
1599% target_window is returned.
1600%
1601% o display: Specifies a pointer to the Display structure; returned from
1602% XOpenDisplay.
1603%
1604% o target_window: Specifies the window to find a WM_STATE property.
1605%
cristy3ed852e2009-09-05 21:47:34 +00001606*/
1607static Window XClientWindow(Display *display,Window target_window)
1608{
1609 Atom
1610 state,
1611 type;
1612
1613 int
1614 format;
1615
1616 Status
1617 status;
1618
1619 unsigned char
1620 *data;
1621
cristyf2faecf2010-05-28 19:19:36 +00001622 unsigned long
cristy3ed852e2009-09-05 21:47:34 +00001623 after,
1624 number_items;
1625
1626 Window
1627 client_window;
1628
1629 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
1630 assert(display != (Display *) NULL);
1631 state=XInternAtom(display,"WM_STATE",MagickTrue);
1632 if (state == (Atom) NULL)
1633 return(target_window);
1634 type=(Atom) NULL;
1635 status=XGetWindowProperty(display,target_window,state,0L,0L,MagickFalse,
1636 (Atom) AnyPropertyType,&type,&format,&number_items,&after,&data);
1637 if ((status == Success) && (type != (Atom) NULL))
1638 return(target_window);
1639 client_window=XWindowByProperty(display,target_window,state);
1640 if (client_window == (Window) NULL)
1641 return(target_window);
1642 return(client_window);
1643}
1644
1645/*
1646%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1647% %
1648% %
1649% %
cristyf34a1452009-10-24 22:29:27 +00001650+ X C o m p o n e n t T e r m i n u s %
1651% %
1652% %
1653% %
1654%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1655%
1656% XComponentTerminus() destroys the module component.
1657%
1658% The format of the XComponentTerminus method is:
1659%
1660% XComponentTerminus(void)
1661%
1662*/
cristy5ff4eaf2011-09-03 01:38:02 +00001663MagickPrivate void XComponentTerminus(void)
cristyf34a1452009-10-24 22:29:27 +00001664{
1665 DestroyXResources();
1666}
1667
1668/*
1669%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1670% %
1671% %
1672% %
cristy3ed852e2009-09-05 21:47:34 +00001673% X C o n f i g u r e I m a g e C o l o r m a p %
1674% %
1675% %
1676% %
1677%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1678%
1679% XConfigureImageColormap() creates a new X colormap.
1680%
1681% The format of the XConfigureImageColormap method is:
1682%
1683% void XConfigureImageColormap(Display *display,
1684% XResourceInfo *resource_info,XWindows *windows,Image *image)
1685%
1686% A description of each parameter follows:
1687%
1688% o display: Specifies a connection to an X server; returned from
1689% XOpenDisplay.
1690%
1691% o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
1692%
1693% o windows: Specifies a pointer to a XWindows structure.
1694%
1695% o image: the image.
1696%
1697*/
cristybcbda3f2011-09-03 13:01:22 +00001698MagickPrivate void XConfigureImageColormap(Display *display,
cristy3ed852e2009-09-05 21:47:34 +00001699 XResourceInfo *resource_info,XWindows *windows,Image *image)
1700{
1701 Colormap
1702 colormap;
1703
1704 /*
1705 Make standard colormap.
1706 */
1707 XSetCursorState(display,windows,MagickTrue);
1708 XCheckRefreshWindows(display,windows);
1709 XMakeStandardColormap(display,windows->visual_info,resource_info,image,
1710 windows->map_info,windows->pixel_info);
1711 colormap=windows->map_info->colormap;
1712 (void) XSetWindowColormap(display,windows->image.id,colormap);
1713 (void) XSetWindowColormap(display,windows->command.id,colormap);
1714 (void) XSetWindowColormap(display,windows->widget.id,colormap);
1715 if (windows->magnify.mapped != MagickFalse)
1716 (void) XSetWindowColormap(display,windows->magnify.id,colormap);
1717 if (windows->pan.mapped != MagickFalse)
1718 (void) XSetWindowColormap(display,windows->pan.id,colormap);
1719 XSetCursorState(display,windows,MagickFalse);
1720 XClientMessage(display,windows->image.id,windows->im_protocols,
1721 windows->im_update_colormap,CurrentTime);
1722}
1723
1724/*
1725%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1726% %
1727% %
1728% %
1729% X C o n s t r a i n W i n d o w P o s i t i o n %
1730% %
1731% %
1732% %
1733%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1734%
1735% XConstrainWindowPosition() assures a window is positioned within the X
1736% server boundaries.
1737%
1738% The format of the XConstrainWindowPosition method is:
1739%
1740% void XConstrainWindowPosition(Display *display,XWindowInfo *window_info)
1741%
1742% A description of each parameter follows:
1743%
1744% o display: Specifies a pointer to the Display structure; returned from
1745% XOpenDisplay.
1746%
1747% o window_info: Specifies a pointer to a XWindowInfo structure.
1748%
1749*/
cristybcbda3f2011-09-03 13:01:22 +00001750MagickPrivate void XConstrainWindowPosition(Display *display,
cristy3ed852e2009-09-05 21:47:34 +00001751 XWindowInfo *window_info)
1752{
1753 int
1754 limit;
1755
1756 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
1757 assert(display != (Display *) NULL);
1758 assert(window_info != (XWindowInfo *) NULL);
1759 limit=XDisplayWidth(display,window_info->screen)-window_info->width;
1760 if (window_info->x < 0)
1761 window_info->x=0;
1762 else
1763 if (window_info->x > (int) limit)
1764 window_info->x=(int) limit;
1765 limit=XDisplayHeight(display,window_info->screen)-window_info->height;
1766 if (window_info->y < 0)
1767 window_info->y=0;
1768 else
1769 if (window_info->y > limit)
1770 window_info->y=limit;
1771}
1772
1773/*
1774%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1775% %
1776% %
1777% %
1778% X D e l a y %
1779% %
1780% %
1781% %
1782%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1783%
1784% XDelay() suspends program execution for the number of milliseconds
1785% specified.
1786%
1787% The format of the Delay method is:
1788%
cristybb503372010-05-27 20:51:26 +00001789% void XDelay(Display *display,const size_t milliseconds)
cristy3ed852e2009-09-05 21:47:34 +00001790%
1791% A description of each parameter follows:
1792%
1793% o display: Specifies a pointer to the Display structure; returned from
1794% XOpenDisplay.
1795%
1796% o milliseconds: Specifies the number of milliseconds to delay before
1797% returning.
1798%
1799*/
cristybcbda3f2011-09-03 13:01:22 +00001800MagickPrivate void XDelay(Display *display,const size_t milliseconds)
cristy3ed852e2009-09-05 21:47:34 +00001801{
1802 assert(display != (Display *) NULL);
1803 (void) XFlush(display);
cristya21afde2010-07-02 00:45:40 +00001804 MagickDelay(milliseconds);
cristy3ed852e2009-09-05 21:47:34 +00001805}
1806
1807/*
1808%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1809% %
1810% %
1811% %
1812% X D e s t r o y R e s o u r c e I n f o %
1813% %
1814% %
1815% %
1816%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1817%
1818% XDestroyResourceInfo() frees memory associated with the XResourceInfo
1819% structure.
1820%
1821% The format of the XDestroyResourceInfo method is:
1822%
1823% void XDestroyResourceInfo(XResourceInfo *resource_info)
1824%
1825% A description of each parameter follows:
1826%
1827% o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
1828%
1829*/
1830MagickExport void XDestroyResourceInfo(XResourceInfo *resource_info)
1831{
1832 if (resource_info->image_geometry != (char *) NULL)
1833 resource_info->image_geometry=(char *)
1834 RelinquishMagickMemory(resource_info->image_geometry);
1835 if (resource_info->quantize_info != (QuantizeInfo *) NULL)
1836 resource_info->quantize_info=DestroyQuantizeInfo(
1837 resource_info->quantize_info);
1838 if (resource_info->client_name != (char *) NULL)
1839 resource_info->client_name=(char *)
1840 RelinquishMagickMemory(resource_info->client_name);
1841 if (resource_info->name != (char *) NULL)
1842 resource_info->name=DestroyString(resource_info->name);
1843 (void) ResetMagickMemory(resource_info,0,sizeof(*resource_info));
1844}
1845
1846/*
1847%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1848% %
1849% %
1850% %
1851% X D e s t r o y W i n d o w C o l o r s %
1852% %
1853% %
1854% %
1855%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1856%
1857% XDestroyWindowColors() frees X11 color resources previously saved on a
1858% window by XRetainWindowColors or programs like xsetroot.
1859%
1860% The format of the XDestroyWindowColors method is:
1861%
1862% void XDestroyWindowColors(Display *display,Window window)
1863%
1864% A description of each parameter follows:
1865%
1866% o display: Specifies a connection to an X server; returned from
1867% XOpenDisplay.
1868%
1869% o window: Specifies a pointer to a Window structure.
1870%
1871*/
cristybcbda3f2011-09-03 13:01:22 +00001872MagickPrivate void XDestroyWindowColors(Display *display,Window window)
cristy3ed852e2009-09-05 21:47:34 +00001873{
1874 Atom
1875 property,
1876 type;
1877
1878 int
1879 format;
1880
1881 Status
1882 status;
1883
1884 unsigned char
1885 *data;
1886
cristyf2faecf2010-05-28 19:19:36 +00001887 unsigned long
cristy3ed852e2009-09-05 21:47:34 +00001888 after,
1889 length;
1890
1891 /*
1892 If there are previous resources on the root window, destroy them.
1893 */
1894 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
1895 assert(display != (Display *) NULL);
1896 property=XInternAtom(display,"_XSETROOT_ID",MagickFalse);
1897 if (property == (Atom) NULL)
1898 {
1899 ThrowXWindowFatalException(XServerError,"UnableToCreateProperty",
1900 "_XSETROOT_ID");
1901 return;
1902 }
1903 status=XGetWindowProperty(display,window,property,0L,1L,MagickTrue,
1904 (Atom) AnyPropertyType,&type,&format,&length,&after,&data);
1905 if (status != Success)
1906 return;
1907 if ((type == XA_PIXMAP) && (format == 32) && (length == 1) && (after == 0))
1908 {
1909 (void) XKillClient(display,(XID) (*((Pixmap *) data)));
1910 (void) XDeleteProperty(display,window,property);
1911 }
1912 if (type != None)
1913 (void) XFree((void *) data);
1914}
1915
1916/*
1917%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1918% %
1919% %
1920% %
1921% X D i s p l a y I m a g e I n f o %
1922% %
1923% %
1924% %
1925%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1926%
1927% XDisplayImageInfo() displays information about an X image.
1928%
1929% The format of the XDisplayImageInfo method is:
1930%
1931% void XDisplayImageInfo(Display *display,
1932% const XResourceInfo *resource_info,XWindows *windows,Image *undo_image,
1933% Image *image)
1934%
1935% A description of each parameter follows:
1936%
1937% o display: Specifies a connection to an X server; returned from
1938% XOpenDisplay.
1939%
1940% o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
1941%
1942% o windows: Specifies a pointer to a XWindows structure.
1943%
1944% o undo_image: the undo image.
1945%
1946% o image: the image.
1947%
1948*/
cristybcbda3f2011-09-03 13:01:22 +00001949MagickPrivate void XDisplayImageInfo(Display *display,
cristy3ed852e2009-09-05 21:47:34 +00001950 const XResourceInfo *resource_info,XWindows *windows,Image *undo_image,
1951 Image *image)
1952{
1953 char
1954 filename[MaxTextExtent],
1955 *text,
1956 **textlist;
1957
1958 FILE
1959 *file;
1960
1961 int
1962 unique_file;
1963
cristybb503372010-05-27 20:51:26 +00001964 register ssize_t
cristy3ed852e2009-09-05 21:47:34 +00001965 i;
1966
cristybb503372010-05-27 20:51:26 +00001967 size_t
cristy3ed852e2009-09-05 21:47:34 +00001968 number_pixels;
1969
cristy9d314ff2011-03-09 01:30:28 +00001970 ssize_t
1971 bytes;
1972
1973 unsigned int
1974 levels;
1975
cristy3ed852e2009-09-05 21:47:34 +00001976 /*
1977 Write info about the X server to a file.
1978 */
1979 assert(display != (Display *) NULL);
1980 assert(resource_info != (XResourceInfo *) NULL);
1981 assert(windows != (XWindows *) NULL);
1982 assert(image != (Image *) NULL);
1983 if (image->debug)
1984 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
1985 file=(FILE *) NULL;
1986 unique_file=AcquireUniqueFileResource(filename);
1987 if (unique_file != -1)
1988 file=fdopen(unique_file,"w");
1989 if ((unique_file == -1) || (file == (FILE *) NULL))
1990 {
1991 XNoticeWidget(display,windows,"Unable to display image info",filename);
1992 return;
1993 }
1994 if (resource_info->gamma_correct != MagickFalse)
1995 if (resource_info->display_gamma != (char *) NULL)
cristyb51dff52011-05-19 16:55:47 +00001996 (void) FormatLocaleFile(file,"Display\n gamma: %s\n\n",
cristy3ed852e2009-09-05 21:47:34 +00001997 resource_info->display_gamma);
1998 /*
1999 Write info about the X image to a file.
2000 */
cristyb51dff52011-05-19 16:55:47 +00002001 (void) FormatLocaleFile(file,"X\n visual: %s\n",
cristy3ed852e2009-09-05 21:47:34 +00002002 XVisualClassName((int) windows->image.storage_class));
cristyb51dff52011-05-19 16:55:47 +00002003 (void) FormatLocaleFile(file," depth: %d\n",windows->image.ximage->depth);
cristy3ed852e2009-09-05 21:47:34 +00002004 if (windows->visual_info->colormap_size != 0)
cristyb51dff52011-05-19 16:55:47 +00002005 (void) FormatLocaleFile(file," colormap size: %d\n",
cristy3ed852e2009-09-05 21:47:34 +00002006 windows->visual_info->colormap_size);
2007 if (resource_info->colormap== SharedColormap)
cristyb51dff52011-05-19 16:55:47 +00002008 (void) FormatLocaleFile(file," colormap type: Shared\n");
cristy3ed852e2009-09-05 21:47:34 +00002009 else
cristyb51dff52011-05-19 16:55:47 +00002010 (void) FormatLocaleFile(file," colormap type: Private\n");
cristy1e604812011-05-19 18:07:50 +00002011 (void) FormatLocaleFile(file," geometry: %dx%d\n",
2012 windows->image.ximage->width,windows->image.ximage->height);
cristy3ed852e2009-09-05 21:47:34 +00002013 if (windows->image.crop_geometry != (char *) NULL)
cristy1e604812011-05-19 18:07:50 +00002014 (void) FormatLocaleFile(file," crop geometry: %s\n",
2015 windows->image.crop_geometry);
cristy3ed852e2009-09-05 21:47:34 +00002016 if (windows->image.pixmap == (Pixmap) NULL)
cristyb51dff52011-05-19 16:55:47 +00002017 (void) FormatLocaleFile(file," type: X Image\n");
cristy3ed852e2009-09-05 21:47:34 +00002018 else
cristyb51dff52011-05-19 16:55:47 +00002019 (void) FormatLocaleFile(file," type: Pixmap\n");
cristy3ed852e2009-09-05 21:47:34 +00002020 if (windows->image.shape != MagickFalse)
cristyb51dff52011-05-19 16:55:47 +00002021 (void) FormatLocaleFile(file," non-rectangular shape: True\n");
cristy3ed852e2009-09-05 21:47:34 +00002022 else
cristyb51dff52011-05-19 16:55:47 +00002023 (void) FormatLocaleFile(file," non-rectangular shape: False\n");
cristy3ed852e2009-09-05 21:47:34 +00002024 if (windows->image.shared_memory != MagickFalse)
cristyb51dff52011-05-19 16:55:47 +00002025 (void) FormatLocaleFile(file," shared memory: True\n");
cristy3ed852e2009-09-05 21:47:34 +00002026 else
cristyb51dff52011-05-19 16:55:47 +00002027 (void) FormatLocaleFile(file," shared memory: False\n");
2028 (void) FormatLocaleFile(file,"\n");
cristy3ed852e2009-09-05 21:47:34 +00002029 if (resource_info->font != (char *) NULL)
cristyb51dff52011-05-19 16:55:47 +00002030 (void) FormatLocaleFile(file,"Font: %s\n\n",resource_info->font);
cristy3ed852e2009-09-05 21:47:34 +00002031 if (resource_info->text_font != (char *) NULL)
cristyb51dff52011-05-19 16:55:47 +00002032 (void) FormatLocaleFile(file,"Text font: %s\n\n",resource_info->text_font);
cristy3ed852e2009-09-05 21:47:34 +00002033 /*
2034 Write info about the undo cache to a file.
2035 */
2036 bytes=0;
2037 for (levels=0; undo_image != (Image *) NULL; levels++)
2038 {
2039 number_pixels=undo_image->list->columns*undo_image->list->rows;
2040 bytes+=number_pixels*sizeof(PixelPacket);
2041 undo_image=GetPreviousImageInList(undo_image);
2042 }
cristyb51dff52011-05-19 16:55:47 +00002043 (void) FormatLocaleFile(file,"Undo Edit Cache\n levels: %u\n",levels);
cristy1e604812011-05-19 18:07:50 +00002044 (void) FormatLocaleFile(file," bytes: %.20gmb\n",(double)
2045 ((bytes+(1 << 19)) >> 20));
cristyb51dff52011-05-19 16:55:47 +00002046 (void) FormatLocaleFile(file," limit: %.20gmb\n\n",(double)
cristyf2faecf2010-05-28 19:19:36 +00002047 resource_info->undo_cache);
cristy3ed852e2009-09-05 21:47:34 +00002048 /*
2049 Write info about the image to a file.
2050 */
cristya4037272011-08-28 15:11:39 +00002051 (void) IdentifyImage(image,file,MagickTrue,&image->exception);
cristy3ed852e2009-09-05 21:47:34 +00002052 (void) fclose(file);
2053 text=FileToString(filename,~0,&image->exception);
2054 (void) RelinquishUniqueFileResource(filename);
2055 if (text == (char *) NULL)
2056 {
2057 XNoticeWidget(display,windows,"MemoryAllocationFailed",
2058 "UnableToDisplayImageInfo");
2059 return;
2060 }
2061 textlist=StringToList(text);
2062 if (textlist != (char **) NULL)
2063 {
2064 char
2065 title[MaxTextExtent];
2066
2067 /*
2068 Display information about the image in the Text View widget.
2069 */
2070 (void) XWithdrawWindow(display,windows->info.id,windows->info.screen);
cristyb51dff52011-05-19 16:55:47 +00002071 (void) FormatLocaleString(title,MaxTextExtent,"Image Info: %s",
cristy3ed852e2009-09-05 21:47:34 +00002072 image->filename);
2073 XTextViewWidget(display,resource_info,windows,MagickTrue,title,
2074 (char const **) textlist);
2075 for (i=0; textlist[i] != (char *) NULL; i++)
2076 textlist[i]=DestroyString(textlist[i]);
2077 textlist=(char **) RelinquishMagickMemory(textlist);
2078 }
2079 text=DestroyString(text);
2080}
2081
2082/*
2083%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2084% %
2085% %
2086% %
2087+ X D i t h e r I m a g e %
2088% %
2089% %
2090% %
2091%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2092%
2093% XDitherImage() dithers the reference image as required by the HP Color
2094% Recovery algorithm. The color values are quantized to 3 bits of red and
2095% green, and 2 bits of blue (3/3/2) and can be used as indices into a 8-bit X
2096% standard colormap.
2097%
2098% The format of the XDitherImage method is:
2099%
2100% void XDitherImage(Image *image,XImage *ximage)
2101%
2102% A description of each parameter follows:
2103%
2104% o image: the image.
2105%
2106% o ximage: Specifies a pointer to a XImage structure; returned from
2107% XCreateImage.
2108%
cristy3ed852e2009-09-05 21:47:34 +00002109*/
2110static void XDitherImage(Image *image,XImage *ximage)
2111{
2112 static const short int
2113 dither_red[2][16]=
2114 {
2115 {-16, 4, -1, 11,-14, 6, -3, 9,-15, 5, -2, 10,-13, 7, -4, 8},
2116 { 15, -5, 0,-12, 13, -7, 2,-10, 14, -6, 1,-11, 12, -8, 3, -9}
2117 },
2118 dither_green[2][16]=
2119 {
2120 { 11,-15, 7, -3, 8,-14, 4, -2, 10,-16, 6, -4, 9,-13, 5, -1},
2121 {-12, 14, -8, 2, -9, 13, -5, 1,-11, 15, -7, 3,-10, 12, -6, 0}
2122 },
2123 dither_blue[2][16]=
2124 {
2125 { -3, 9,-13, 7, -1, 11,-15, 5, -4, 8,-14, 6, -2, 10,-16, 4},
2126 { 2,-10, 12, -8, 0,-12, 14, -6, 3, -9, 13, -7, 1,-11, 15, -5}
2127 };
2128
cristyc57f6942010-11-12 01:47:39 +00002129 CacheView
2130 *image_view;
cristy3ed852e2009-09-05 21:47:34 +00002131
2132 int
cristyc57f6942010-11-12 01:47:39 +00002133 value,
cristy3ed852e2009-09-05 21:47:34 +00002134 y;
2135
cristyc57f6942010-11-12 01:47:39 +00002136 PixelPacket
2137 color;
cristy3ed852e2009-09-05 21:47:34 +00002138
2139 register char
2140 *q;
2141
cristy4c08aed2011-07-01 19:47:50 +00002142 register const Quantum
cristy3ed852e2009-09-05 21:47:34 +00002143 *p;
2144
2145 register int
2146 i,
2147 j,
2148 x;
2149
2150 unsigned int
2151 scanline_pad;
2152
cristybb503372010-05-27 20:51:26 +00002153 register size_t
cristy3ed852e2009-09-05 21:47:34 +00002154 pixel;
2155
2156 unsigned char
2157 *blue_map[2][16],
2158 *green_map[2][16],
2159 *red_map[2][16];
2160
2161 /*
2162 Allocate and initialize dither maps.
2163 */
2164 for (i=0; i < 2; i++)
2165 for (j=0; j < 16; j++)
2166 {
2167 red_map[i][j]=(unsigned char *) AcquireQuantumMemory(256UL,
2168 sizeof(*red_map));
2169 green_map[i][j]=(unsigned char *) AcquireQuantumMemory(256UL,
2170 sizeof(*green_map));
2171 blue_map[i][j]=(unsigned char *) AcquireQuantumMemory(256UL,
2172 sizeof(*blue_map));
2173 if ((red_map[i][j] == (unsigned char *) NULL) ||
2174 (green_map[i][j] == (unsigned char *) NULL) ||
2175 (blue_map[i][j] == (unsigned char *) NULL))
2176 {
2177 ThrowXWindowFatalException(ResourceLimitError,
2178 "MemoryAllocationFailed",image->filename);
2179 return;
2180 }
2181 }
2182 /*
2183 Initialize dither tables.
2184 */
2185 for (i=0; i < 2; i++)
2186 for (j=0; j < 16; j++)
2187 for (x=0; x < 256; x++)
2188 {
2189 value=x-16;
2190 if (x < 48)
2191 value=x/2+8;
2192 value+=dither_red[i][j];
2193 red_map[i][j][x]=(unsigned char)
2194 ((value < 0) ? 0 : (value > 255) ? 255 : value);
2195 value=x-16;
2196 if (x < 48)
2197 value=x/2+8;
2198 value+=dither_green[i][j];
2199 green_map[i][j][x]=(unsigned char)
2200 ((value < 0) ? 0 : (value > 255) ? 255 : value);
2201 value=x-32;
2202 if (x < 112)
2203 value=x/2+24;
cristybb503372010-05-27 20:51:26 +00002204 value+=((size_t) dither_blue[i][j] << 1);
cristy3ed852e2009-09-05 21:47:34 +00002205 blue_map[i][j][x]=(unsigned char)
2206 ((value < 0) ? 0 : (value > 255) ? 255 : value);
2207 }
2208 /*
2209 Dither image.
2210 */
2211 scanline_pad=(unsigned int) (ximage->bytes_per_line-
cristybb503372010-05-27 20:51:26 +00002212 ((size_t) (ximage->width*ximage->bits_per_pixel) >> 3));
cristy3ed852e2009-09-05 21:47:34 +00002213 i=0;
2214 j=0;
2215 q=ximage->data;
cristyc57f6942010-11-12 01:47:39 +00002216 image_view=AcquireCacheView(image);
cristy3ed852e2009-09-05 21:47:34 +00002217 for (y=0; y < (int) image->rows; y++)
2218 {
cristyc57f6942010-11-12 01:47:39 +00002219 p=GetCacheViewVirtualPixels(image_view,0,(ssize_t) y,image->columns,1,
2220 &image->exception);
cristy4c08aed2011-07-01 19:47:50 +00002221 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00002222 break;
2223 for (x=0; x < (int) image->columns; x++)
2224 {
cristyce70c172010-01-07 17:15:30 +00002225 color.red=ClampToQuantum((MagickRealType) (red_map[i][j][(int)
cristy4c08aed2011-07-01 19:47:50 +00002226 ScaleQuantumToChar(GetPixelRed(image,p))] << 8));
cristyce70c172010-01-07 17:15:30 +00002227 color.green=ClampToQuantum((MagickRealType) (green_map[i][j][(int)
cristy4c08aed2011-07-01 19:47:50 +00002228 ScaleQuantumToChar(GetPixelGreen(image,p))] << 8));
cristyce70c172010-01-07 17:15:30 +00002229 color.blue=ClampToQuantum((MagickRealType) (blue_map[i][j][(int)
cristy4c08aed2011-07-01 19:47:50 +00002230 ScaleQuantumToChar(GetPixelBlue(image,p))] << 8));
cristybb503372010-05-27 20:51:26 +00002231 pixel=(size_t) (((size_t) color.red & 0xe0) |
2232 (((size_t) color.green & 0xe0) >> 3) |
2233 (((size_t) color.blue & 0xc0) >> 6));
cristy3ed852e2009-09-05 21:47:34 +00002234 *q++=(char) pixel;
cristyed231572011-07-14 02:18:59 +00002235 p+=GetPixelChannels(image);
cristy3ed852e2009-09-05 21:47:34 +00002236 j++;
2237 if (j == 16)
2238 j=0;
2239 }
2240 q+=scanline_pad;
2241 i++;
2242 if (i == 2)
2243 i=0;
2244 }
cristyc57f6942010-11-12 01:47:39 +00002245 image_view=DestroyCacheView(image_view);
cristy3ed852e2009-09-05 21:47:34 +00002246 /*
2247 Free allocated memory.
2248 */
2249 for (i=0; i < 2; i++)
2250 for (j=0; j < 16; j++)
2251 {
2252 green_map[i][j]=(unsigned char *) RelinquishMagickMemory(green_map[i][j]);
2253 blue_map[i][j]=(unsigned char *) RelinquishMagickMemory(blue_map[i][j]);
2254 red_map[i][j]=(unsigned char *) RelinquishMagickMemory(red_map[i][j]);
2255 }
2256}
2257
2258/*
2259%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2260% %
2261% %
2262% %
2263% X D r a w I m a g e %
2264% %
2265% %
2266% %
2267%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2268%
2269% XDrawImage() draws a line on the image.
2270%
2271% The format of the XDrawImage method is:
2272%
2273% MagickBooleanType XDrawImage(display,pixel,draw_info,image)
2274%
2275% A description of each parameter follows:
2276%
2277% o display: Specifies a connection to an X server; returned from
2278% XOpenDisplay.
2279%
2280% o pixel: Specifies a pointer to a XPixelInfo structure.
2281%
2282% o draw_info: Specifies a pointer to a XDrawInfo structure.
2283%
2284% o image: the image.
2285%
2286*/
cristybcbda3f2011-09-03 13:01:22 +00002287MagickPrivate MagickBooleanType XDrawImage(Display *display,
cristy3ed852e2009-09-05 21:47:34 +00002288 const XPixelInfo *pixel,XDrawInfo *draw_info,Image *image)
2289{
cristyc57f6942010-11-12 01:47:39 +00002290 CacheView
2291 *draw_view;
2292
cristy3ed852e2009-09-05 21:47:34 +00002293 ExceptionInfo
2294 *exception;
2295
2296 GC
2297 draw_context;
2298
2299 Image
2300 *draw_image;
2301
2302 int
2303 x,
2304 y;
2305
2306 MagickBooleanType
2307 matte;
2308
2309 Pixmap
2310 draw_pixmap;
2311
2312 unsigned int
2313 depth,
2314 height,
2315 width;
2316
2317 Window
2318 root_window;
2319
2320 XGCValues
2321 context_values;
2322
2323 XImage
2324 *draw_ximage;
2325
2326 /*
2327 Initialize drawd image.
2328 */
2329 assert(display != (Display *) NULL);
2330 assert(pixel != (XPixelInfo *) NULL);
2331 assert(draw_info != (XDrawInfo *) NULL);
2332 assert(image != (Image *) NULL);
2333 if (image->debug != MagickFalse)
2334 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
2335 /*
2336 Initialize drawd pixmap.
2337 */
2338 root_window=XRootWindow(display,XDefaultScreen(display));
2339 depth=(unsigned int) XDefaultDepth(display,XDefaultScreen(display));
2340 draw_pixmap=XCreatePixmap(display,root_window,draw_info->width,
2341 draw_info->height,depth);
2342 if (draw_pixmap == (Pixmap) NULL)
2343 return(MagickFalse);
2344 /*
2345 Initialize graphics info.
2346 */
cristybb503372010-05-27 20:51:26 +00002347 context_values.background=(size_t) (~0);
cristy3ed852e2009-09-05 21:47:34 +00002348 context_values.foreground=0;
2349 context_values.line_width=(int) draw_info->line_width;
cristybb503372010-05-27 20:51:26 +00002350 draw_context=XCreateGC(display,root_window,(size_t)
cristy3ed852e2009-09-05 21:47:34 +00002351 (GCBackground | GCForeground | GCLineWidth),&context_values);
2352 if (draw_context == (GC) NULL)
2353 return(MagickFalse);
2354 /*
2355 Clear pixmap.
2356 */
2357 (void) XFillRectangle(display,draw_pixmap,draw_context,0,0,draw_info->width,
2358 draw_info->height);
2359 /*
2360 Draw line to pixmap.
2361 */
2362 (void) XSetBackground(display,draw_context,0);
cristybb503372010-05-27 20:51:26 +00002363 (void) XSetForeground(display,draw_context,(size_t) (~0));
cristydd05beb2010-11-21 21:23:39 +00002364 if (draw_info->stipple != (Pixmap) NULL)
2365 {
2366 (void) XSetFillStyle(display,draw_context,FillOpaqueStippled);
2367 (void) XSetStipple(display,draw_context,draw_info->stipple);
2368 }
cristy3ed852e2009-09-05 21:47:34 +00002369 switch (draw_info->element)
2370 {
2371 case PointElement:
2372 default:
2373 {
2374 (void) XDrawLines(display,draw_pixmap,draw_context,
2375 draw_info->coordinate_info,(int) draw_info->number_coordinates,
2376 CoordModeOrigin);
2377 break;
2378 }
2379 case LineElement:
2380 {
2381 (void) XDrawLine(display,draw_pixmap,draw_context,draw_info->line_info.x1,
2382 draw_info->line_info.y1,draw_info->line_info.x2,
2383 draw_info->line_info.y2);
2384 break;
2385 }
2386 case RectangleElement:
2387 {
2388 (void) XDrawRectangle(display,draw_pixmap,draw_context,
2389 (int) draw_info->rectangle_info.x,(int) draw_info->rectangle_info.y,
2390 (unsigned int) draw_info->rectangle_info.width,
2391 (unsigned int) draw_info->rectangle_info.height);
2392 break;
2393 }
2394 case FillRectangleElement:
2395 {
2396 (void) XFillRectangle(display,draw_pixmap,draw_context,
2397 (int) draw_info->rectangle_info.x,(int) draw_info->rectangle_info.y,
2398 (unsigned int) draw_info->rectangle_info.width,
2399 (unsigned int) draw_info->rectangle_info.height);
2400 break;
2401 }
2402 case CircleElement:
2403 case EllipseElement:
2404 {
2405 (void) XDrawArc(display,draw_pixmap,draw_context,
2406 (int) draw_info->rectangle_info.x,(int) draw_info->rectangle_info.y,
2407 (unsigned int) draw_info->rectangle_info.width,
2408 (unsigned int) draw_info->rectangle_info.height,0,360*64);
2409 break;
2410 }
2411 case FillCircleElement:
2412 case FillEllipseElement:
2413 {
2414 (void) XFillArc(display,draw_pixmap,draw_context,
2415 (int) draw_info->rectangle_info.x,(int) draw_info->rectangle_info.y,
2416 (unsigned int) draw_info->rectangle_info.width,
2417 (unsigned int) draw_info->rectangle_info.height,0,360*64);
2418 break;
2419 }
2420 case PolygonElement:
2421 {
2422 XPoint
2423 *coordinate_info;
2424
2425 coordinate_info=draw_info->coordinate_info;
2426 (void) XDrawLines(display,draw_pixmap,draw_context,coordinate_info,
2427 (int) draw_info->number_coordinates,CoordModeOrigin);
2428 (void) XDrawLine(display,draw_pixmap,draw_context,
2429 coordinate_info[draw_info->number_coordinates-1].x,
2430 coordinate_info[draw_info->number_coordinates-1].y,
2431 coordinate_info[0].x,coordinate_info[0].y);
2432 break;
2433 }
2434 case FillPolygonElement:
2435 {
2436 (void) XFillPolygon(display,draw_pixmap,draw_context,
2437 draw_info->coordinate_info,(int) draw_info->number_coordinates,Complex,
2438 CoordModeOrigin);
2439 break;
2440 }
2441 }
2442 (void) XFreeGC(display,draw_context);
2443 /*
2444 Initialize X image.
2445 */
2446 draw_ximage=XGetImage(display,draw_pixmap,0,0,draw_info->width,
2447 draw_info->height,AllPlanes,ZPixmap);
2448 if (draw_ximage == (XImage *) NULL)
2449 return(MagickFalse);
2450 (void) XFreePixmap(display,draw_pixmap);
2451 /*
2452 Initialize draw image.
2453 */
2454 draw_image=AcquireImage((ImageInfo *) NULL);
2455 if (draw_image == (Image *) NULL)
2456 return(MagickFalse);
2457 draw_image->columns=draw_info->width;
2458 draw_image->rows=draw_info->height;
2459 /*
2460 Transfer drawn X image to image.
2461 */
2462 width=(unsigned int) image->columns;
2463 height=(unsigned int) image->rows;
2464 x=0;
2465 y=0;
2466 (void) XParseGeometry(draw_info->geometry,&x,&y,&width,&height);
cristyc57f6942010-11-12 01:47:39 +00002467 (void) GetOneVirtualPixel(image,(ssize_t) x,(ssize_t) y,
2468 &draw_image->background_color,&image->exception);
cristy574cc262011-08-05 01:23:58 +00002469 if (SetImageStorageClass(draw_image,DirectClass,&image->exception) == MagickFalse)
cristy3ed852e2009-09-05 21:47:34 +00002470 return(MagickFalse);
2471 draw_image->matte=MagickTrue;
2472 exception=(&image->exception);
cristyc57f6942010-11-12 01:47:39 +00002473 draw_view=AcquireCacheView(draw_image);
cristy3ed852e2009-09-05 21:47:34 +00002474 for (y=0; y < (int) draw_image->rows; y++)
2475 {
cristyc57f6942010-11-12 01:47:39 +00002476 register int
cristy3ed852e2009-09-05 21:47:34 +00002477 x;
2478
cristy4c08aed2011-07-01 19:47:50 +00002479 register Quantum
cristyc47d1f82009-11-26 01:44:43 +00002480 *restrict q;
cristy3ed852e2009-09-05 21:47:34 +00002481
cristyc57f6942010-11-12 01:47:39 +00002482 q=QueueCacheViewAuthenticPixels(draw_view,0,(ssize_t) y,draw_image->columns,
2483 1,exception);
cristyacd2ed22011-08-30 01:44:23 +00002484 if (q == (Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00002485 break;
cristyc57f6942010-11-12 01:47:39 +00002486 for (x=0; x < (int) draw_image->columns; x++)
cristy3ed852e2009-09-05 21:47:34 +00002487 {
2488 if (XGetPixel(draw_ximage,x,y) == 0)
2489 {
2490 /*
2491 Set this pixel to the background color.
2492 */
cristy4c08aed2011-07-01 19:47:50 +00002493 SetPixelPacket(draw_image,&draw_image->background_color,q);
2494 SetPixelAlpha(draw_image,(Quantum) (draw_info->stencil ==
2495 OpaqueStencil ? TransparentAlpha : OpaqueAlpha),q);
cristy3ed852e2009-09-05 21:47:34 +00002496 }
2497 else
2498 {
2499 /*
2500 Set this pixel to the pen color.
2501 */
cristy4c08aed2011-07-01 19:47:50 +00002502 SetPixelRed(draw_image,ScaleShortToQuantum(
2503 pixel->pen_color.red),q);
2504 SetPixelGreen(draw_image,ScaleShortToQuantum(
2505 pixel->pen_color.green),q);
2506 SetPixelBlue(draw_image,ScaleShortToQuantum(
2507 pixel->pen_color.blue),q);
2508 SetPixelAlpha(draw_image,(Quantum) (draw_info->stencil ==
2509 OpaqueStencil ? OpaqueAlpha : TransparentAlpha),q);
cristy3ed852e2009-09-05 21:47:34 +00002510 }
cristyed231572011-07-14 02:18:59 +00002511 q+=GetPixelChannels(draw_image);
cristy3ed852e2009-09-05 21:47:34 +00002512 }
cristyc57f6942010-11-12 01:47:39 +00002513 if (SyncCacheViewAuthenticPixels(draw_view,exception) == MagickFalse)
cristy3ed852e2009-09-05 21:47:34 +00002514 break;
2515 }
cristyc57f6942010-11-12 01:47:39 +00002516 draw_view=DestroyCacheView(draw_view);
cristy3ed852e2009-09-05 21:47:34 +00002517 XDestroyImage(draw_ximage);
2518 /*
2519 Determine draw geometry.
2520 */
2521 (void) XParseGeometry(draw_info->geometry,&x,&y,&width,&height);
2522 if ((width != (unsigned int) draw_image->columns) ||
2523 (height != (unsigned int) draw_image->rows))
2524 {
2525 char
2526 image_geometry[MaxTextExtent];
2527
2528 /*
2529 Scale image.
2530 */
cristyb51dff52011-05-19 16:55:47 +00002531 (void) FormatLocaleString(image_geometry,MaxTextExtent,"%ux%u",
cristy3ed852e2009-09-05 21:47:34 +00002532 width,height);
2533 (void) TransformImage(&draw_image,(char *) NULL,image_geometry);
2534 }
2535 if (draw_info->degrees != 0.0)
2536 {
2537 Image
2538 *rotate_image;
2539
2540 int
2541 rotations;
2542
2543 MagickRealType
2544 normalized_degrees;
2545
2546 /*
2547 Rotate image.
2548 */
2549 rotate_image=RotateImage(draw_image,draw_info->degrees,&image->exception);
2550 if (rotate_image == (Image *) NULL)
2551 return(MagickFalse);
2552 draw_image=DestroyImage(draw_image);
2553 draw_image=rotate_image;
2554 /*
2555 Annotation is relative to the degree of rotation.
2556 */
2557 normalized_degrees=draw_info->degrees;
2558 while (normalized_degrees < -45.0)
2559 normalized_degrees+=360.0;
2560 for (rotations=0; normalized_degrees > 45.0; rotations++)
2561 normalized_degrees-=90.0;
2562 switch (rotations % 4)
2563 {
2564 default:
2565 case 0:
2566 break;
2567 case 1:
2568 {
2569 /*
2570 Rotate 90 degrees.
2571 */
2572 x=x-(int) draw_image->columns/2;
2573 y=y+(int) draw_image->columns/2;
2574 break;
2575 }
2576 case 2:
2577 {
2578 /*
2579 Rotate 180 degrees.
2580 */
2581 x=x-(int) draw_image->columns;
2582 break;
2583 }
2584 case 3:
2585 {
2586 /*
2587 Rotate 270 degrees.
2588 */
2589 x=x-(int) draw_image->columns/2;
2590 y=y-(int) (draw_image->rows-(draw_image->columns/2));
2591 break;
2592 }
2593 }
2594 }
2595 /*
2596 Composite text onto the image.
2597 */
cristyc57f6942010-11-12 01:47:39 +00002598 draw_view=AcquireCacheView(draw_image);
cristy3ed852e2009-09-05 21:47:34 +00002599 for (y=0; y < (int) draw_image->rows; y++)
2600 {
cristyc57f6942010-11-12 01:47:39 +00002601 register int
cristy3ed852e2009-09-05 21:47:34 +00002602 x;
2603
cristy4c08aed2011-07-01 19:47:50 +00002604 register Quantum
cristyc47d1f82009-11-26 01:44:43 +00002605 *restrict q;
cristy3ed852e2009-09-05 21:47:34 +00002606
cristyc57f6942010-11-12 01:47:39 +00002607 q=GetCacheViewAuthenticPixels(draw_view,0,(ssize_t) y,draw_image->columns,1,
2608 exception);
cristyacd2ed22011-08-30 01:44:23 +00002609 if (q == (Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00002610 break;
cristyc57f6942010-11-12 01:47:39 +00002611 for (x=0; x < (int) draw_image->columns; x++)
cristy3ed852e2009-09-05 21:47:34 +00002612 {
cristy4c08aed2011-07-01 19:47:50 +00002613 if (GetPixelAlpha(image,q) != TransparentAlpha)
2614 SetPixelAlpha(draw_image,OpaqueAlpha,q);
cristyed231572011-07-14 02:18:59 +00002615 q+=GetPixelChannels(draw_image);
cristy3ed852e2009-09-05 21:47:34 +00002616 }
cristyc57f6942010-11-12 01:47:39 +00002617 if (SyncCacheViewAuthenticPixels(draw_view,exception) == MagickFalse)
cristy3ed852e2009-09-05 21:47:34 +00002618 break;
2619 }
cristyc57f6942010-11-12 01:47:39 +00002620 draw_view=DestroyCacheView(draw_view);
cristy3ed852e2009-09-05 21:47:34 +00002621 (void) XParseGeometry(draw_info->geometry,&x,&y,&width,&height);
2622 if (draw_info->stencil == TransparentStencil)
cristyc57f6942010-11-12 01:47:39 +00002623 (void) CompositeImage(image,CopyOpacityCompositeOp,draw_image,(ssize_t) x,
2624 (ssize_t) y);
cristy3ed852e2009-09-05 21:47:34 +00002625 else
2626 {
2627 matte=image->matte;
cristyc57f6942010-11-12 01:47:39 +00002628 (void) CompositeImage(image,OverCompositeOp,draw_image,(ssize_t) x,
2629 (ssize_t) y);
cristy3ed852e2009-09-05 21:47:34 +00002630 image->matte=matte;
2631 }
2632 draw_image=DestroyImage(draw_image);
2633 return(MagickTrue);
2634}
2635
2636/*
2637%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2638% %
2639% %
2640% %
2641% X E r r o r %
2642% %
2643% %
2644% %
2645%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2646%
2647% XError() ignores BadWindow errors for XQueryTree and XGetWindowAttributes,
2648% and ignores BadDrawable errors for XGetGeometry, and ignores BadValue errors
cristybcbda3f2011-09-03 13:01:22 +00002649% for XQueryColor. It returns MagickFalse in those cases. Otherwise it
2650% returns True.
cristy3ed852e2009-09-05 21:47:34 +00002651%
2652% The format of the XError function is:
2653%
cristybcbda3f2011-09-03 13:01:22 +00002654% int XError(display,error)
cristy3ed852e2009-09-05 21:47:34 +00002655%
2656% A description of each parameter follows:
2657%
2658% o display: Specifies a pointer to the Display structure; returned from
2659% XOpenDisplay.
2660%
2661% o error: Specifies the error event.
2662%
2663*/
2664
2665#if defined(__cplusplus) || defined(c_plusplus)
2666extern "C" {
2667#endif
2668
2669MagickExport int XError(Display *display,XErrorEvent *error)
2670{
2671 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
2672 assert(display != (Display *) NULL);
2673 assert(error != (XErrorEvent *) NULL);
2674 xerror_alert=MagickTrue;
2675 switch (error->request_code)
2676 {
2677 case X_GetGeometry:
2678 {
2679 if ((int) error->error_code == BadDrawable)
2680 return(MagickFalse);
2681 break;
2682 }
2683 case X_GetWindowAttributes:
2684 case X_QueryTree:
2685 {
2686 if ((int) error->error_code == BadWindow)
2687 return(MagickFalse);
2688 break;
2689 }
2690 case X_QueryColors:
2691 {
2692 if ((int) error->error_code == BadValue)
2693 return(MagickFalse);
2694 break;
2695 }
2696 }
2697 return(MagickTrue);
2698}
2699
2700#if defined(__cplusplus) || defined(c_plusplus)
2701}
2702#endif
2703
2704/*
2705%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2706% %
2707% %
2708% %
2709% X F r e e R e s o u r c e s %
2710% %
2711% %
2712% %
2713%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2714%
2715% XFreeResources() frees X11 resources.
2716%
2717% The format of the XFreeResources method is:
2718%
2719% void XFreeResources(Display *display,XVisualInfo *visual_info,
2720% XStandardColormap *map_info,XPixelInfo *pixel,XFontStruct *font_info,
2721% XResourceInfo *resource_info,XWindowInfo *window_info)
2722% resource_info,window_info)
2723%
2724% A description of each parameter follows:
2725%
2726% o display: Specifies a connection to an X server; returned from
2727% XOpenDisplay.
2728%
2729% o visual_info: Specifies a pointer to a X11 XVisualInfo structure;
2730% returned from XGetVisualInfo.
2731%
2732% o map_info: If map_type is specified, this structure is initialized
2733% with info from the Standard Colormap.
2734%
2735% o pixel: Specifies a pointer to a XPixelInfo structure.
2736%
2737% o font_info: Specifies a pointer to a XFontStruct structure.
2738%
2739% o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
2740%
2741% o window_info: Specifies a pointer to a X11 XWindowInfo structure.
2742%
2743*/
cristybcbda3f2011-09-03 13:01:22 +00002744MagickPrivate void XFreeResources(Display *display,XVisualInfo *visual_info,
cristy3ed852e2009-09-05 21:47:34 +00002745 XStandardColormap *map_info,XPixelInfo *pixel,XFontStruct *font_info,
2746 XResourceInfo *resource_info,XWindowInfo *window_info)
2747{
2748 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
2749 assert(display != (Display *) NULL);
2750 assert(resource_info != (XResourceInfo *) NULL);
2751 if (window_info != (XWindowInfo *) NULL)
2752 {
2753 /*
2754 Free X image.
2755 */
2756 if (window_info->ximage != (XImage *) NULL)
2757 XDestroyImage(window_info->ximage);
2758 if (window_info->id != (Window) NULL)
2759 {
2760 /*
2761 Free destroy window and free cursors.
2762 */
2763 if (window_info->id != XRootWindow(display,visual_info->screen))
2764 (void) XDestroyWindow(display,window_info->id);
2765 if (window_info->annotate_context != (GC) NULL)
2766 (void) XFreeGC(display,window_info->annotate_context);
2767 if (window_info->highlight_context != (GC) NULL)
2768 (void) XFreeGC(display,window_info->highlight_context);
2769 if (window_info->widget_context != (GC) NULL)
2770 (void) XFreeGC(display,window_info->widget_context);
2771 if (window_info->cursor != (Cursor) NULL)
2772 (void) XFreeCursor(display,window_info->cursor);
2773 window_info->cursor=(Cursor) NULL;
2774 if (window_info->busy_cursor != (Cursor) NULL)
2775 (void) XFreeCursor(display,window_info->busy_cursor);
2776 window_info->busy_cursor=(Cursor) NULL;
2777 }
2778 }
2779 /*
2780 Free font.
2781 */
2782 if (font_info != (XFontStruct *) NULL)
cristyaafc1922011-03-04 16:59:40 +00002783 {
2784 (void) XFreeFont(display,font_info);
2785 font_info=(XFontStruct *) NULL;
2786 }
cristy3ed852e2009-09-05 21:47:34 +00002787 if (map_info != (XStandardColormap *) NULL)
2788 {
2789 /*
2790 Free X Standard Colormap.
2791 */
2792 if (resource_info->map_type == (char *) NULL)
2793 (void) XFreeStandardColormap(display,visual_info,map_info,pixel);
2794 (void) XFree((void *) map_info);
2795 }
2796 /*
2797 Free X visual info.
2798 */
2799 if (visual_info != (XVisualInfo *) NULL)
2800 (void) XFree((void *) visual_info);
2801 if (resource_info->close_server != MagickFalse)
2802 (void) XCloseDisplay(display);
2803}
2804
2805/*
2806%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2807% %
2808% %
2809% %
2810% X F r e e S t a n d a r d C o l o r m a p %
2811% %
2812% %
2813% %
2814%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2815%
2816% XFreeStandardColormap() frees an X11 colormap.
2817%
2818% The format of the XFreeStandardColormap method is:
2819%
2820% void XFreeStandardColormap(Display *display,
2821% const XVisualInfo *visual_info,XStandardColormap *map_info,
2822% XPixelInfo *pixel)
2823%
2824% A description of each parameter follows:
2825%
2826% o display: Specifies a connection to an X server; returned from
2827% XOpenDisplay.
2828%
2829% o visual_info: Specifies a pointer to a X11 XVisualInfo structure;
2830% returned from XGetVisualInfo.
2831%
2832% o map_info: If map_type is specified, this structure is initialized
2833% with info from the Standard Colormap.
2834%
2835% o pixel: Specifies a pointer to a XPixelInfo structure.
2836%
2837*/
cristybcbda3f2011-09-03 13:01:22 +00002838MagickPrivate void XFreeStandardColormap(Display *display,
cristy3ed852e2009-09-05 21:47:34 +00002839 const XVisualInfo *visual_info,XStandardColormap *map_info,XPixelInfo *pixel)
2840{
2841 /*
2842 Free colormap.
2843 */
2844 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
2845 assert(display != (Display *) NULL);
2846 assert(visual_info != (XVisualInfo *) NULL);
2847 assert(map_info != (XStandardColormap *) NULL);
2848 (void) XFlush(display);
2849 if (map_info->colormap != (Colormap) NULL)
2850 {
2851 if (map_info->colormap != XDefaultColormap(display,visual_info->screen))
2852 (void) XFreeColormap(display,map_info->colormap);
2853 else
2854 if (pixel != (XPixelInfo *) NULL)
2855 if ((visual_info->klass != TrueColor) &&
2856 (visual_info->klass != DirectColor))
2857 (void) XFreeColors(display,map_info->colormap,pixel->pixels,
2858 (int) pixel->colors,0);
2859 }
2860 map_info->colormap=(Colormap) NULL;
2861 if (pixel != (XPixelInfo *) NULL)
2862 {
cristyf2faecf2010-05-28 19:19:36 +00002863 if (pixel->pixels != (unsigned long *) NULL)
2864 pixel->pixels=(unsigned long *) RelinquishMagickMemory(pixel->pixels);
2865 pixel->pixels=(unsigned long *) NULL;
cristy3ed852e2009-09-05 21:47:34 +00002866 }
2867}
2868
2869/*
2870%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2871% %
2872% %
2873% %
2874% X G e t A n n o t a t e I n f o %
2875% %
2876% %
2877% %
2878%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2879%
2880% XGetAnnotateInfo() initializes the AnnotateInfo structure.
2881%
2882% The format of the XGetAnnotateInfo method is:
2883%
2884% void XGetAnnotateInfo(XAnnotateInfo *annotate_info)
2885%
2886% A description of each parameter follows:
2887%
2888% o annotate_info: Specifies a pointer to a XAnnotateInfo structure.
2889%
2890*/
cristybcbda3f2011-09-03 13:01:22 +00002891MagickPrivate void XGetAnnotateInfo(XAnnotateInfo *annotate_info)
cristy3ed852e2009-09-05 21:47:34 +00002892{
2893 /*
2894 Initialize annotate structure.
2895 */
2896 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
2897 assert(annotate_info != (XAnnotateInfo *) NULL);
2898 annotate_info->x=0;
2899 annotate_info->y=0;
2900 annotate_info->width=0;
2901 annotate_info->height=0;
2902 annotate_info->stencil=ForegroundStencil;
2903 annotate_info->degrees=0.0;
2904 annotate_info->font_info=(XFontStruct *) NULL;
2905 annotate_info->text=(char *) NULL;
2906 *annotate_info->geometry='\0';
2907 annotate_info->previous=(XAnnotateInfo *) NULL;
2908 annotate_info->next=(XAnnotateInfo *) NULL;
2909 (void) XSupportsLocale();
2910 (void) XSetLocaleModifiers("");
2911}
2912
2913/*
2914%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2915% %
2916% %
2917% %
2918% X G e t M a p I n f o %
2919% %
2920% %
2921% %
2922%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2923%
2924% XGetMapInfo() initializes the XStandardColormap structure.
2925%
2926% The format of the XStandardColormap method is:
2927%
2928% void XGetMapInfo(const XVisualInfo *visual_info,const Colormap colormap,
2929% XStandardColormap *map_info)
2930%
2931% A description of each parameter follows:
2932%
2933% o colormap: Specifies the ID of the X server colormap.
2934%
2935% o visual_info: Specifies a pointer to a X11 XVisualInfo structure;
2936% returned from XGetVisualInfo.
2937%
2938% o map_info: Specifies a pointer to a X11 XStandardColormap structure.
2939%
2940*/
cristybcbda3f2011-09-03 13:01:22 +00002941MagickPrivate void XGetMapInfo(const XVisualInfo *visual_info,
cristy3ed852e2009-09-05 21:47:34 +00002942 const Colormap colormap,XStandardColormap *map_info)
2943{
2944 /*
2945 Initialize map info.
2946 */
2947 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
2948 assert(visual_info != (XVisualInfo *) NULL);
2949 assert(map_info != (XStandardColormap *) NULL);
2950 map_info->colormap=colormap;
2951 map_info->red_max=visual_info->red_mask;
cristybb503372010-05-27 20:51:26 +00002952 map_info->red_mult=(size_t) (map_info->red_max != 0 ? 1 : 0);
cristy3ed852e2009-09-05 21:47:34 +00002953 if (map_info->red_max != 0)
2954 while ((map_info->red_max & 0x01) == 0)
2955 {
2956 map_info->red_max>>=1;
2957 map_info->red_mult<<=1;
2958 }
2959 map_info->green_max=visual_info->green_mask;
cristybb503372010-05-27 20:51:26 +00002960 map_info->green_mult=(size_t) (map_info->green_max != 0 ? 1 : 0);
cristy3ed852e2009-09-05 21:47:34 +00002961 if (map_info->green_max != 0)
2962 while ((map_info->green_max & 0x01) == 0)
2963 {
2964 map_info->green_max>>=1;
2965 map_info->green_mult<<=1;
2966 }
2967 map_info->blue_max=visual_info->blue_mask;
cristybb503372010-05-27 20:51:26 +00002968 map_info->blue_mult=(size_t) (map_info->blue_max != 0 ? 1 : 0);
cristy3ed852e2009-09-05 21:47:34 +00002969 if (map_info->blue_max != 0)
2970 while ((map_info->blue_max & 0x01) == 0)
2971 {
2972 map_info->blue_max>>=1;
2973 map_info->blue_mult<<=1;
2974 }
2975 map_info->base_pixel=0;
2976}
2977
2978/*
2979%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2980% %
2981% %
2982% %
2983% X G e t P i x e l I n f o %
2984% %
2985% %
2986% %
2987%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2988%
cristy4c08aed2011-07-01 19:47:50 +00002989% XGetPixelInfo() initializes the PixelPacket structure.
cristy3ed852e2009-09-05 21:47:34 +00002990%
cristy4c08aed2011-07-01 19:47:50 +00002991% The format of the XGetPixelInfo method is:
cristy3ed852e2009-09-05 21:47:34 +00002992%
cristy4c08aed2011-07-01 19:47:50 +00002993% void XGetPixelInfo(Display *display,const XVisualInfo *visual_info,
cristy3ed852e2009-09-05 21:47:34 +00002994% const XStandardColormap *map_info,const XResourceInfo *resource_info,
2995% Image *image,XPixelInfo *pixel)
2996% pixel)
2997%
2998% A description of each parameter follows:
2999%
3000% o display: Specifies a connection to an X server; returned from
3001% XOpenDisplay.
3002%
3003% o visual_info: Specifies a pointer to a X11 XVisualInfo structure;
3004% returned from XGetVisualInfo.
3005%
3006% o map_info: If map_type is specified, this structure is initialized
3007% with info from the Standard Colormap.
3008%
3009% o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
3010%
3011% o image: the image.
3012%
3013% o pixel: Specifies a pointer to a XPixelInfo structure.
3014%
3015*/
cristybcbda3f2011-09-03 13:01:22 +00003016MagickPrivate void XGetPixelInfo(Display *display,
cristy3ed852e2009-09-05 21:47:34 +00003017 const XVisualInfo *visual_info,const XStandardColormap *map_info,
3018 const XResourceInfo *resource_info,Image *image,XPixelInfo *pixel)
3019{
3020 static const char
3021 *PenColors[MaxNumberPens]=
3022 {
3023 "#000000000000", /* black */
3024 "#00000000ffff", /* blue */
3025 "#0000ffffffff", /* cyan */
3026 "#0000ffff0000", /* green */
3027 "#bdbdbdbdbdbd", /* gray */
3028 "#ffff00000000", /* red */
3029 "#ffff0000ffff", /* magenta */
3030 "#ffffffff0000", /* yellow */
3031 "#ffffffffffff", /* white */
3032 "#bdbdbdbdbdbd", /* gray */
3033 "#bdbdbdbdbdbd" /* gray */
3034 };
3035
3036 Colormap
3037 colormap;
3038
cristybb503372010-05-27 20:51:26 +00003039 register ssize_t
cristy3ed852e2009-09-05 21:47:34 +00003040 i;
3041
3042 Status
3043 status;
3044
3045 unsigned int
3046 packets;
3047
3048 /*
3049 Initialize pixel info.
3050 */
3051 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
3052 assert(display != (Display *) NULL);
3053 assert(visual_info != (XVisualInfo *) NULL);
3054 assert(map_info != (XStandardColormap *) NULL);
3055 assert(resource_info != (XResourceInfo *) NULL);
3056 assert(pixel != (XPixelInfo *) NULL);
3057 pixel->colors=0;
3058 if (image != (Image *) NULL)
3059 if (image->storage_class == PseudoClass)
cristyc57f6942010-11-12 01:47:39 +00003060 pixel->colors=(ssize_t) image->colors;
cristy3ed852e2009-09-05 21:47:34 +00003061 packets=(unsigned int)
3062 MagickMax((int) pixel->colors,visual_info->colormap_size)+MaxNumberPens;
cristyf2faecf2010-05-28 19:19:36 +00003063 if (pixel->pixels != (unsigned long *) NULL)
3064 pixel->pixels=(unsigned long *) RelinquishMagickMemory(pixel->pixels);
3065 pixel->pixels=(unsigned long *) AcquireQuantumMemory(packets,
cristy3ed852e2009-09-05 21:47:34 +00003066 sizeof(pixel->pixels));
cristyf2faecf2010-05-28 19:19:36 +00003067 if (pixel->pixels == (unsigned long *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00003068 ThrowXWindowFatalException(ResourceLimitFatalError,"UnableToGetPixelInfo",
3069 image->filename);
3070 /*
3071 Set foreground color.
3072 */
3073 colormap=map_info->colormap;
3074 (void) XParseColor(display,colormap,(char *) ForegroundColor,
3075 &pixel->foreground_color);
3076 status=XParseColor(display,colormap,resource_info->foreground_color,
3077 &pixel->foreground_color);
3078 if (status == False)
3079 ThrowXWindowFatalException(XServerError,"ColorIsNotKnownToServer",
3080 resource_info->foreground_color);
3081 pixel->foreground_color.pixel=
3082 XStandardPixel(map_info,&pixel->foreground_color);
3083 pixel->foreground_color.flags=(char) (DoRed | DoGreen | DoBlue);
3084 /*
3085 Set background color.
3086 */
3087 (void) XParseColor(display,colormap,"#d6d6d6d6d6d6",&pixel->background_color);
3088 status=XParseColor(display,colormap,resource_info->background_color,
3089 &pixel->background_color);
3090 if (status == False)
3091 ThrowXWindowFatalException(XServerError,"ColorIsNotKnownToServer",
3092 resource_info->background_color);
3093 pixel->background_color.pixel=
3094 XStandardPixel(map_info,&pixel->background_color);
3095 pixel->background_color.flags=(char) (DoRed | DoGreen | DoBlue);
3096 /*
3097 Set border color.
3098 */
3099 (void) XParseColor(display,colormap,(char *) BorderColor,
3100 &pixel->border_color);
3101 status=XParseColor(display,colormap,resource_info->border_color,
3102 &pixel->border_color);
3103 if (status == False)
3104 ThrowXWindowFatalException(XServerError,"ColorIsNotKnownToServer",
3105 resource_info->border_color);
3106 pixel->border_color.pixel=XStandardPixel(map_info,&pixel->border_color);
3107 pixel->border_color.flags=(char) (DoRed | DoGreen | DoBlue);
3108 /*
3109 Set matte color.
3110 */
3111 pixel->matte_color=pixel->background_color;
3112 if (resource_info->matte_color != (char *) NULL)
3113 {
3114 /*
3115 Matte color is specified as a X resource or command line argument.
3116 */
3117 status=XParseColor(display,colormap,resource_info->matte_color,
3118 &pixel->matte_color);
3119 if (status == False)
3120 ThrowXWindowFatalException(XServerError,"ColorIsNotKnownToServer",
3121 resource_info->matte_color);
3122 pixel->matte_color.pixel=XStandardPixel(map_info,&pixel->matte_color);
3123 pixel->matte_color.flags=(char) (DoRed | DoGreen | DoBlue);
3124 }
3125 /*
3126 Set highlight color.
3127 */
3128 pixel->highlight_color.red=(unsigned short) ((
3129 pixel->matte_color.red*ScaleQuantumToShort(HighlightModulate))/65535L+
3130 (ScaleQuantumToShort((Quantum) (QuantumRange-HighlightModulate))));
3131 pixel->highlight_color.green=(unsigned short) ((
3132 pixel->matte_color.green*ScaleQuantumToShort(HighlightModulate))/65535L+
3133 (ScaleQuantumToShort((Quantum) (QuantumRange-HighlightModulate))));
3134 pixel->highlight_color.blue=(unsigned short) ((
3135 pixel->matte_color.blue*ScaleQuantumToShort(HighlightModulate))/65535L+
3136 (ScaleQuantumToShort((Quantum) (QuantumRange-HighlightModulate))));
3137 pixel->highlight_color.pixel=
3138 XStandardPixel(map_info,&pixel->highlight_color);
3139 pixel->highlight_color.flags=(char) (DoRed | DoGreen | DoBlue);
3140 /*
3141 Set shadow color.
3142 */
3143 pixel->shadow_color.red=(unsigned short) (((MagickRealType)
3144 pixel->matte_color.red*ScaleQuantumToShort(ShadowModulate))/65535L);
3145 pixel->shadow_color.green=(unsigned short) (((MagickRealType)
3146 pixel->matte_color.green*ScaleQuantumToShort(ShadowModulate))/65535L);
3147 pixel->shadow_color.blue=(unsigned short) (((MagickRealType)
3148 pixel->matte_color.blue*ScaleQuantumToShort(ShadowModulate))/65535L);
3149 pixel->shadow_color.pixel=XStandardPixel(map_info,&pixel->shadow_color);
3150 pixel->shadow_color.flags=(char) (DoRed | DoGreen | DoBlue);
3151 /*
3152 Set depth color.
3153 */
3154 pixel->depth_color.red=(unsigned short) (((MagickRealType)
3155 pixel->matte_color.red*ScaleQuantumToShort(DepthModulate))/65535L);
3156 pixel->depth_color.green=(unsigned short) (((MagickRealType)
3157 pixel->matte_color.green*ScaleQuantumToShort(DepthModulate))/65535L);
3158 pixel->depth_color.blue=(unsigned short) (((MagickRealType)
3159 pixel->matte_color.blue*ScaleQuantumToShort(DepthModulate))/65535L);
3160 pixel->depth_color.pixel=XStandardPixel(map_info,&pixel->depth_color);
3161 pixel->depth_color.flags=(char) (DoRed | DoGreen | DoBlue);
3162 /*
3163 Set trough color.
3164 */
3165 pixel->trough_color.red=(unsigned short) (((MagickRealType)
3166 pixel->matte_color.red*ScaleQuantumToShort(TroughModulate))/65535L);
3167 pixel->trough_color.green=(unsigned short) (((MagickRealType)
3168 pixel->matte_color.green*ScaleQuantumToShort(TroughModulate))/65535L);
3169 pixel->trough_color.blue=(unsigned short) (((MagickRealType)
3170 pixel->matte_color.blue*ScaleQuantumToShort(TroughModulate))/65535L);
3171 pixel->trough_color.pixel=XStandardPixel(map_info,&pixel->trough_color);
3172 pixel->trough_color.flags=(char) (DoRed | DoGreen | DoBlue);
3173 /*
3174 Set pen color.
3175 */
3176 for (i=0; i < MaxNumberPens; i++)
3177 {
3178 (void) XParseColor(display,colormap,(char *) PenColors[i],
3179 &pixel->pen_colors[i]);
3180 status=XParseColor(display,colormap,resource_info->pen_colors[i],
3181 &pixel->pen_colors[i]);
3182 if (status == False)
3183 ThrowXWindowFatalException(XServerError,"ColorIsNotKnownToServer",
3184 resource_info->pen_colors[i]);
3185 pixel->pen_colors[i].pixel=XStandardPixel(map_info,&pixel->pen_colors[i]);
3186 pixel->pen_colors[i].flags=(char) (DoRed | DoGreen | DoBlue);
3187 }
3188 pixel->box_color=pixel->background_color;
3189 pixel->pen_color=pixel->foreground_color;
3190 pixel->box_index=0;
3191 pixel->pen_index=1;
3192 if (image != (Image *) NULL)
3193 {
3194 if ((resource_info->gamma_correct != MagickFalse) &&
3195 (image->gamma != 0.0))
3196 {
3197 GeometryInfo
3198 geometry_info;
3199
3200 MagickStatusType
3201 flags;
3202
3203 /*
3204 Initialize map relative to display and image gamma.
3205 */
3206 flags=ParseGeometry(resource_info->display_gamma,&geometry_info);
3207 red_gamma=geometry_info.rho;
3208 green_gamma=geometry_info.sigma;
3209 if ((flags & SigmaValue) == 0)
3210 green_gamma=red_gamma;
3211 blue_gamma=geometry_info.xi;
3212 if ((flags & XiValue) == 0)
3213 blue_gamma=red_gamma;
3214 red_gamma*=image->gamma;
3215 green_gamma*=image->gamma;
3216 blue_gamma*=image->gamma;
3217 }
3218 if (image->storage_class == PseudoClass)
3219 {
3220 /*
3221 Initialize pixel array for images of type PseudoClass.
3222 */
cristybb503372010-05-27 20:51:26 +00003223 for (i=0; i < (ssize_t) image->colors; i++)
cristy4c08aed2011-07-01 19:47:50 +00003224 pixel->pixels[i]=XGammaPacket(map_info,image->colormap+i);
cristy3ed852e2009-09-05 21:47:34 +00003225 for (i=0; i < MaxNumberPens; i++)
3226 pixel->pixels[image->colors+i]=pixel->pen_colors[i].pixel;
3227 pixel->colors+=MaxNumberPens;
3228 }
3229 }
3230}
3231
3232/*
3233%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3234% %
3235% %
3236% %
3237% X G e t R e s o u r c e C l a s s %
3238% %
3239% %
3240% %
3241%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3242%
3243% XGetResourceClass() queries the X server for the specified resource name or
3244% class. If the resource name or class is not defined in the database, the
3245% supplied default value is returned.
3246%
3247% The format of the XGetResourceClass method is:
3248%
3249% char *XGetResourceClass(XrmDatabase database,const char *client_name,
3250% const char *keyword,char *resource_default)
3251%
3252% A description of each parameter follows:
3253%
3254% o database: Specifies a resource database; returned from
3255% XrmGetStringDatabase.
3256%
3257% o client_name: Specifies the application name used to retrieve resource
3258% info from the X server database.
3259%
3260% o keyword: Specifies the keyword of the value being retrieved.
3261%
3262% o resource_default: Specifies the default value to return if the query
3263% fails to find the specified keyword/class.
3264%
3265*/
3266MagickExport char *XGetResourceClass(XrmDatabase database,
3267 const char *client_name,const char *keyword,char *resource_default)
3268{
3269 char
3270 resource_class[MaxTextExtent],
3271 resource_name[MaxTextExtent];
3272
3273 static char
3274 *resource_type;
3275
3276 Status
3277 status;
3278
3279 XrmValue
3280 resource_value;
3281
3282 if (database == (XrmDatabase) NULL)
3283 return(resource_default);
3284 *resource_name='\0';
3285 *resource_class='\0';
3286 if (keyword != (char *) NULL)
3287 {
3288 int
3289 c,
3290 k;
3291
3292 /*
3293 Initialize resource keyword and class.
3294 */
cristyb51dff52011-05-19 16:55:47 +00003295 (void) FormatLocaleString(resource_name,MaxTextExtent,"%s.%s",
cristy3ed852e2009-09-05 21:47:34 +00003296 client_name,keyword);
3297 c=(int) (*client_name);
3298 if ((c >= XK_a) && (c <= XK_z))
3299 c-=(XK_a-XK_A);
3300 else
3301 if ((c >= XK_agrave) && (c <= XK_odiaeresis))
3302 c-=(XK_agrave-XK_Agrave);
3303 else
3304 if ((c >= XK_oslash) && (c <= XK_thorn))
3305 c-=(XK_oslash-XK_Ooblique);
3306 k=(int) (*keyword);
3307 if ((k >= XK_a) && (k <= XK_z))
3308 k-=(XK_a-XK_A);
3309 else
3310 if ((k >= XK_agrave) && (k <= XK_odiaeresis))
3311 k-=(XK_agrave-XK_Agrave);
3312 else
3313 if ((k >= XK_oslash) && (k <= XK_thorn))
3314 k-=(XK_oslash-XK_Ooblique);
cristyb51dff52011-05-19 16:55:47 +00003315 (void) FormatLocaleString(resource_class,MaxTextExtent,"%c%s.%c%s",c,
cristy3ed852e2009-09-05 21:47:34 +00003316 client_name+1,k,keyword+1);
3317 }
3318 status=XrmGetResource(database,resource_name,resource_class,&resource_type,
3319 &resource_value);
3320 if (status == False)
3321 return(resource_default);
3322 return(resource_value.addr);
3323}
3324
3325/*
3326%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3327% %
3328% %
3329% %
3330% X G e t R e s o u r c e D a t a b a s e %
3331% %
3332% %
3333% %
3334%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3335%
3336% XGetResourceDatabase() creates a new resource database and initializes it.
3337%
3338% The format of the XGetResourceDatabase method is:
3339%
3340% XrmDatabase XGetResourceDatabase(Display *display,
3341% const char *client_name)
3342%
3343% A description of each parameter follows:
3344%
3345% o database: XGetResourceDatabase() returns the database after it is
3346% initialized.
3347%
3348% o display: Specifies a connection to an X server; returned from
3349% XOpenDisplay.
3350%
3351% o client_name: Specifies the application name used to retrieve resource
3352% info from the X server database.
3353%
3354*/
3355MagickExport XrmDatabase XGetResourceDatabase(Display *display,
3356 const char *client_name)
3357{
3358 char
3359 filename[MaxTextExtent];
3360
3361 int
3362 c;
3363
3364 register const char
3365 *p;
3366
3367 XrmDatabase
3368 resource_database,
3369 server_database;
3370
3371 if (display == (Display *) NULL)
3372 return((XrmDatabase) NULL);
3373 assert(client_name != (char *) NULL);
3374 /*
3375 Initialize resource database.
3376 */
3377 XrmInitialize();
3378 (void) XGetDefault(display,(char *) client_name,"dummy");
3379 resource_database=XrmGetDatabase(display);
3380 /*
3381 Combine application database.
3382 */
3383 if (client_name != (char *) NULL)
3384 {
3385 /*
3386 Get basename of client.
3387 */
3388 p=client_name+(strlen(client_name)-1);
3389 while ((p > client_name) && (*p != '/'))
3390 p--;
3391 if (*p == '/')
3392 client_name=p+1;
3393 }
3394 c=(int) (*client_name);
3395 if ((c >= XK_a) && (c <= XK_z))
3396 c-=(XK_a-XK_A);
3397 else
3398 if ((c >= XK_agrave) && (c <= XK_odiaeresis))
3399 c-=(XK_agrave-XK_Agrave);
3400 else
3401 if ((c >= XK_oslash) && (c <= XK_thorn))
3402 c-=(XK_oslash-XK_Ooblique);
3403#if defined(X11_APPLICATION_PATH)
cristyb51dff52011-05-19 16:55:47 +00003404 (void) FormatLocaleString(filename,MaxTextExtent,"%s%c%s",
cristy3ed852e2009-09-05 21:47:34 +00003405 X11_APPLICATION_PATH,c,client_name+1);
3406 (void) XrmCombineFileDatabase(filename,&resource_database,MagickFalse);
3407#endif
3408 if (XResourceManagerString(display) != (char *) NULL)
3409 {
3410 /*
3411 Combine server database.
3412 */
3413 server_database=XrmGetStringDatabase(XResourceManagerString(display));
3414 XrmCombineDatabase(server_database,&resource_database,MagickFalse);
3415 }
3416 /*
3417 Merge user preferences database.
3418 */
3419#if defined(X11_PREFERENCES_PATH)
cristyb51dff52011-05-19 16:55:47 +00003420 (void) FormatLocaleString(filename,MaxTextExtent,"%s%src",
cristy3ed852e2009-09-05 21:47:34 +00003421 X11_PREFERENCES_PATH,client_name);
3422 ExpandFilename(filename);
3423 (void) XrmCombineFileDatabase(filename,&resource_database,MagickFalse);
3424#endif
3425 return(resource_database);
3426}
3427
3428/*
3429%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3430% %
3431% %
3432% %
3433% X G e t R e s o u r c e I n f o %
3434% %
3435% %
3436% %
3437%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3438%
3439% XGetResourceInfo(image_info,) initializes the ResourceInfo structure.
3440%
3441% The format of the XGetResourceInfo method is:
3442%
3443% void XGetResourceInfo(const ImageInfo *image_info,XrmDatabase database,
3444% const char *client_name,XResourceInfo *resource_info)
3445%
3446% A description of each parameter follows:
3447%
3448% o image_info: the image info.
3449%
3450% o database: Specifies a resource database; returned from
3451% XrmGetStringDatabase.
3452%
3453% o client_name: Specifies the application name used to retrieve
3454% resource info from the X server database.
3455%
3456% o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
3457%
3458*/
3459MagickExport void XGetResourceInfo(const ImageInfo *image_info,
3460 XrmDatabase database,const char *client_name,XResourceInfo *resource_info)
3461{
3462 char
cristy00976d82011-02-20 20:31:28 +00003463 *directory,
cristy3ed852e2009-09-05 21:47:34 +00003464 *resource_value;
3465
3466 /*
3467 Initialize resource info fields.
3468 */
3469 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
3470 assert(resource_info != (XResourceInfo *) NULL);
3471 (void) ResetMagickMemory(resource_info,0,sizeof(*resource_info));
3472 resource_info->resource_database=database;
3473 resource_info->image_info=(ImageInfo *) image_info;
3474 (void) SetImageInfoProgressMonitor(resource_info->image_info,
3475 XMagickProgressMonitor,(void *) NULL);
3476 resource_info->quantize_info=CloneQuantizeInfo((QuantizeInfo *) NULL);
3477 resource_info->close_server=MagickTrue;
3478 resource_info->client_name=AcquireString(client_name);
3479 resource_value=XGetResourceClass(database,client_name,"backdrop",
3480 (char *) "False");
3481 resource_info->backdrop=IsMagickTrue(resource_value);
3482 resource_info->background_color=XGetResourceInstance(database,client_name,
3483 "background",(char *) "#d6d6d6d6d6d6");
3484 resource_info->border_color=XGetResourceInstance(database,client_name,
3485 "borderColor",BorderColor);
3486 resource_value=XGetResourceClass(database,client_name,"borderWidth",
3487 (char *) "2");
cristy00976d82011-02-20 20:31:28 +00003488 resource_info->border_width=(unsigned int) StringToUnsignedLong(
3489 resource_value);
cristy3ed852e2009-09-05 21:47:34 +00003490 resource_value=XGetResourceClass(database,client_name,"colormap",
3491 (char *) "shared");
3492 resource_info->colormap=UndefinedColormap;
3493 if (LocaleCompare("private",resource_value) == 0)
3494 resource_info->colormap=PrivateColormap;
3495 if (LocaleCompare("shared",resource_value) == 0)
3496 resource_info->colormap=SharedColormap;
3497 if (resource_info->colormap == UndefinedColormap)
3498 ThrowXWindowFatalException(OptionError,"UnrecognizedColormapType",
3499 resource_value);
3500 resource_value=XGetResourceClass(database,client_name,
3501 "colorRecovery",(char *) "False");
3502 resource_info->color_recovery=IsMagickTrue(resource_value);
3503 resource_value=XGetResourceClass(database,client_name,"confirmExit",
3504 (char *) "False");
3505 resource_info->confirm_exit=IsMagickTrue(resource_value);
3506 resource_value=XGetResourceClass(database,client_name,"confirmEdit",
3507 (char *) "False");
3508 resource_info->confirm_edit=IsMagickTrue(resource_value);
cristyba0c3252010-06-27 13:31:44 +00003509 resource_value=XGetResourceClass(database,client_name,"delay",(char *) "1");
cristye27293e2009-12-18 02:53:20 +00003510 resource_info->delay=(unsigned int) StringToUnsignedLong(resource_value);
cristy3ed852e2009-09-05 21:47:34 +00003511 resource_info->display_gamma=XGetResourceClass(database,client_name,
3512 "displayGamma",(char *) "2.2");
3513 resource_value=XGetResourceClass(database,client_name,"displayWarnings",
3514 (char *) "True");
3515 resource_info->display_warnings=IsMagickTrue(resource_value);
3516 resource_info->font=XGetResourceClass(database,client_name,"font",
3517 (char *) NULL);
3518 resource_info->font=XGetResourceClass(database,client_name,"fontList",
3519 resource_info->font);
3520 resource_info->font_name[0]=XGetResourceClass(database,client_name,"font1",
3521 (char *) "fixed");
3522 resource_info->font_name[1]=XGetResourceClass(database,client_name,"font2",
3523 (char *) "variable");
3524 resource_info->font_name[2]=XGetResourceClass(database,client_name,"font3",
3525 (char *) "5x8");
3526 resource_info->font_name[3]=XGetResourceClass(database,client_name,"font4",
3527 (char *) "6x10");
3528 resource_info->font_name[4]=XGetResourceClass(database,client_name,"font5",
3529 (char *) "7x13bold");
3530 resource_info->font_name[5]=XGetResourceClass(database,client_name,"font6",
3531 (char *) "8x13bold");
3532 resource_info->font_name[6]=XGetResourceClass(database,client_name,"font7",
3533 (char *) "9x15bold");
3534 resource_info->font_name[7]=XGetResourceClass(database,client_name,"font8",
3535 (char *) "10x20");
3536 resource_info->font_name[8]=XGetResourceClass(database,client_name,"font9",
3537 (char *) "12x24");
3538 resource_info->font_name[9]=XGetResourceClass(database,client_name,"font0",
3539 (char *) "fixed");
3540 resource_info->font_name[10]=XGetResourceClass(database,client_name,"font0",
3541 (char *) "fixed");
3542 resource_info->foreground_color=XGetResourceInstance(database,client_name,
3543 "foreground",ForegroundColor);
3544 resource_value=XGetResourceClass(database,client_name,"gammaCorrect",
3545 (char *) "True");
3546 resource_info->gamma_correct=IsMagickTrue(resource_value);
3547 resource_info->image_geometry=ConstantString(XGetResourceClass(database,
3548 client_name,"geometry",(char *) NULL));
3549 resource_value=XGetResourceClass(database,client_name,"gravity",
3550 (char *) "Center");
cristy042ee782011-04-22 18:48:30 +00003551 resource_info->gravity=(GravityType) ParseCommandOption(MagickGravityOptions,
cristy3ed852e2009-09-05 21:47:34 +00003552 MagickFalse,resource_value);
cristy00976d82011-02-20 20:31:28 +00003553 directory=getcwd(resource_info->home_directory,MaxTextExtent);
3554 (void) directory;
cristy3ed852e2009-09-05 21:47:34 +00003555 resource_info->icon_geometry=XGetResourceClass(database,client_name,
3556 "iconGeometry",(char *) NULL);
3557 resource_value=XGetResourceClass(database,client_name,"iconic",
3558 (char *) "False");
3559 resource_info->iconic=IsMagickTrue(resource_value);
3560 resource_value=XGetResourceClass(database,client_name,"immutable",
3561 LocaleCompare(client_name,"PerlMagick") == 0 ? (char *) "True" :
3562 (char *) "False");
3563 resource_info->immutable=IsMagickTrue(resource_value);
3564 resource_value=XGetResourceClass(database,client_name,"magnify",
3565 (char *) "3");
cristye27293e2009-12-18 02:53:20 +00003566 resource_info->magnify=(unsigned int) StringToUnsignedLong(resource_value);
cristy3ed852e2009-09-05 21:47:34 +00003567 resource_info->map_type=XGetResourceClass(database,client_name,"map",
3568 (char *) NULL);
3569 resource_info->matte_color=XGetResourceInstance(database,client_name,
3570 "mattecolor",(char *) NULL);
3571 resource_info->name=ConstantString(XGetResourceClass(database,client_name,
3572 "name",(char *) NULL));
3573 resource_info->pen_colors[0]=XGetResourceClass(database,client_name,"pen1",
3574 (char *) "black");
3575 resource_info->pen_colors[1]=XGetResourceClass(database,client_name,"pen2",
3576 (char *) "blue");
3577 resource_info->pen_colors[2]=XGetResourceClass(database,client_name,"pen3",
3578 (char *) "cyan");
3579 resource_info->pen_colors[3]=XGetResourceClass(database,client_name,"pen4",
3580 (char *) "green");
3581 resource_info->pen_colors[4]=XGetResourceClass(database,client_name,"pen5",
3582 (char *) "gray");
3583 resource_info->pen_colors[5]=XGetResourceClass(database,client_name,"pen6",
3584 (char *) "red");
3585 resource_info->pen_colors[6]=XGetResourceClass(database,client_name,"pen7",
3586 (char *) "magenta");
3587 resource_info->pen_colors[7]=XGetResourceClass(database,client_name,"pen8",
3588 (char *) "yellow");
3589 resource_info->pen_colors[8]=XGetResourceClass(database,client_name,"pen9",
3590 (char *) "white");
3591 resource_info->pen_colors[9]=XGetResourceClass(database,client_name,"pen0",
3592 (char *) "gray");
3593 resource_info->pen_colors[10]=XGetResourceClass(database,client_name,"pen0",
3594 (char *) "gray");
3595 resource_value=XGetResourceClass(database,client_name,"pause",(char *) "0");
cristye27293e2009-12-18 02:53:20 +00003596 resource_info->pause=(unsigned int) StringToUnsignedLong(resource_value);
cristy3ed852e2009-09-05 21:47:34 +00003597 resource_value=XGetResourceClass(database,client_name,"quantum",(char *) "1");
cristyf2f27272009-12-17 14:48:46 +00003598 resource_info->quantum=StringToLong(resource_value);
cristy3ed852e2009-09-05 21:47:34 +00003599 resource_info->text_font=XGetResourceClass(database,client_name,(char *)
3600 "font",(char *) "fixed");
3601 resource_info->text_font=XGetResourceClass(database,client_name,
3602 "textFontList",resource_info->text_font);
3603 resource_info->title=XGetResourceClass(database,client_name,"title",
3604 (char *) NULL);
3605 resource_value=XGetResourceClass(database,client_name,"undoCache",
3606 (char *) "16");
cristye27293e2009-12-18 02:53:20 +00003607 resource_info->undo_cache=(unsigned int) StringToUnsignedLong(resource_value);
cristy3ed852e2009-09-05 21:47:34 +00003608 resource_value=XGetResourceClass(database,client_name,"update",
3609 (char *) "False");
3610 resource_info->update=IsMagickTrue(resource_value);
3611 resource_value=XGetResourceClass(database,client_name,"usePixmap",
3612 (char *) "True");
3613 resource_info->use_pixmap=IsMagickTrue(resource_value);
3614 resource_value=XGetResourceClass(database,client_name,"sharedMemory",
3615 (char *) "True");
3616 resource_info->use_shared_memory=IsMagickTrue(resource_value);
3617 resource_info->visual_type=XGetResourceClass(database,client_name,"visual",
3618 (char *) NULL);
3619 resource_info->window_group=XGetResourceClass(database,client_name,
3620 "windowGroup",(char *) NULL);
3621 resource_info->window_id=XGetResourceClass(database,client_name,"window",
3622 (char *) NULL);
3623 resource_info->write_filename=XGetResourceClass(database,client_name,
3624 "writeFilename",(char *) NULL);
3625}
3626
3627/*
3628%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3629% %
3630% %
3631% %
3632% X G e t R e s o u r c e I n s t a n c e %
3633% %
3634% %
3635% %
3636%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3637%
3638% XGetResourceInstance() queries the X server for the specified resource name.
3639% If the resource name is not defined in the database, the supplied default
3640% value is returned.
3641%
3642% The format of the XGetResourceInstance method is:
3643%
3644% char *XGetResourceInstance(XrmDatabase database,const char *client_name,
3645% const char *keyword,const char *resource_default)
3646%
3647% A description of each parameter follows:
3648%
3649% o database: Specifies a resource database; returned from
3650% XrmGetStringDatabase.
3651%
3652% o client_name: Specifies the application name used to retrieve
3653% resource info from the X server database.
3654%
3655% o keyword: Specifies the keyword of the value being retrieved.
3656%
3657% o resource_default: Specifies the default value to return if the query
3658% fails to find the specified keyword/class.
3659%
3660*/
3661MagickExport char *XGetResourceInstance(XrmDatabase database,
3662 const char *client_name,const char *keyword,const char *resource_default)
3663{
3664 char
3665 *resource_type,
3666 resource_name[MaxTextExtent];
3667
3668 Status
3669 status;
3670
3671 XrmValue
3672 resource_value;
3673
3674 if (database == (XrmDatabase) NULL)
3675 return((char *) resource_default);
3676 *resource_name='\0';
3677 if (keyword != (char *) NULL)
cristyb51dff52011-05-19 16:55:47 +00003678 (void) FormatLocaleString(resource_name,MaxTextExtent,"%s.%s",client_name,
cristy3ed852e2009-09-05 21:47:34 +00003679 keyword);
3680 status=XrmGetResource(database,resource_name,"ImageMagick",&resource_type,
3681 &resource_value);
3682 if (status == False)
3683 return((char *) resource_default);
3684 return(resource_value.addr);
3685}
3686
3687/*
3688%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3689% %
3690% %
3691% %
3692% X G e t S c r e e n D e n s i t y %
3693% %
3694% %
3695% %
3696%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3697%
3698% XGetScreenDensity() returns the density of the X server screen in
3699% dots-per-inch.
3700%
3701% The format of the XGetScreenDensity method is:
3702%
3703% char *XGetScreenDensity(Display *display)
3704%
3705% A description of each parameter follows:
3706%
3707% o density: XGetScreenDensity() returns the density of the X screen in
3708% dots-per-inch.
3709%
3710% o display: Specifies a connection to an X server; returned from
3711% XOpenDisplay.
3712%
3713*/
3714MagickExport char *XGetScreenDensity(Display *display)
3715{
3716 char
3717 density[MaxTextExtent];
3718
3719 double
3720 x_density,
3721 y_density;
3722
3723 /*
3724 Set density as determined by screen size.
3725 */
3726 x_density=((((double) DisplayWidth(display,XDefaultScreen(display)))*25.4)/
3727 ((double) DisplayWidthMM(display,XDefaultScreen(display))));
3728 y_density=((((double) DisplayHeight(display,XDefaultScreen(display)))*25.4)/
3729 ((double) DisplayHeightMM(display,XDefaultScreen(display))));
cristyb51dff52011-05-19 16:55:47 +00003730 (void) FormatLocaleString(density,MaxTextExtent,"%gx%g",x_density,
cristy8cd5b312010-01-07 01:10:24 +00003731 y_density);
cristy3ed852e2009-09-05 21:47:34 +00003732 return(GetPageGeometry(density));
3733}
3734
3735/*
3736%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3737% %
3738% %
3739% %
3740+ X G e t S u b w i n d o w %
3741% %
3742% %
3743% %
3744%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3745%
3746% XGetSubwindow() returns the subwindow of a window chosen the user with the
3747% pointer and a button press.
3748%
3749% The format of the XGetSubwindow method is:
3750%
3751% Window XGetSubwindow(Display *display,Window window,int x,int y)
3752%
3753% A description of each parameter follows:
3754%
3755% o subwindow: XGetSubwindow() returns NULL if no subwindow is found
3756% otherwise the subwindow is returned.
3757%
3758% o display: Specifies a connection to an X server; returned from
3759% XOpenDisplay.
3760%
3761% o window: Specifies a pointer to a Window.
3762%
3763% o x: the x coordinate of the pointer relative to the origin of the
3764% window.
3765%
3766% o y: the y coordinate of the pointer relative to the origin of the
3767% window.
3768%
cristy3ed852e2009-09-05 21:47:34 +00003769*/
3770static Window XGetSubwindow(Display *display,Window window,int x,int y)
3771{
3772 int
3773 x_offset,
3774 y_offset;
3775
3776 Status
3777 status;
3778
3779 Window
3780 source_window,
3781 target_window;
3782
3783 assert(display != (Display *) NULL);
3784 source_window=XRootWindow(display,XDefaultScreen(display));
3785 if (window == (Window) NULL)
3786 return(source_window);
3787 target_window=window;
3788 for ( ; ; )
3789 {
3790 status=XTranslateCoordinates(display,source_window,window,x,y,
3791 &x_offset,&y_offset,&target_window);
3792 if (status != True)
3793 break;
3794 if (target_window == (Window) NULL)
3795 break;
3796 source_window=window;
3797 window=target_window;
3798 x=x_offset;
3799 y=y_offset;
3800 }
3801 if (target_window == (Window) NULL)
3802 target_window=window;
3803 return(target_window);
3804}
3805
3806/*
3807%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3808% %
3809% %
3810% %
3811% X G e t W i n d o w C o l o r %
3812% %
3813% %
3814% %
3815%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3816%
3817% XGetWindowColor() returns the color of a pixel interactively chosen from the
3818% X server.
3819%
3820% The format of the XGetWindowColor method is:
3821%
3822% MagickBooleanType XGetWindowColor(Display *display,XWindows *windows,
3823% char *name)
3824%
3825% A description of each parameter follows:
3826%
3827% o display: Specifies a connection to an X server; returned from
3828% XOpenDisplay.
3829%
3830% o windows: Specifies a pointer to a XWindows structure.
3831%
3832% o name: the name of the color if found in the X Color Database is
3833% returned in this character string.
3834%
3835*/
cristybcbda3f2011-09-03 13:01:22 +00003836MagickPrivate MagickBooleanType XGetWindowColor(Display *display,
cristy3ed852e2009-09-05 21:47:34 +00003837 XWindows *windows,char *name)
3838{
3839 int
3840 x,
3841 y;
3842
3843 PixelPacket
3844 pixel;
3845
3846 RectangleInfo
3847 crop_info;
3848
3849 Status
3850 status;
3851
3852 Window
3853 child,
3854 client_window,
3855 root_window,
3856 target_window;
3857
3858 XColor
3859 color;
3860
3861 XImage
3862 *ximage;
3863
3864 XWindowAttributes
3865 window_attributes;
3866
3867 /*
3868 Choose a pixel from the X server.
3869 */
3870 assert(display != (Display *) NULL);
3871 assert(name != (char *) NULL);
3872 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",name);
3873 *name='\0';
3874 target_window=XSelectWindow(display,&crop_info);
3875 if (target_window == (Window) NULL)
3876 return(MagickFalse);
3877 root_window=XRootWindow(display,XDefaultScreen(display));
3878 client_window=target_window;
3879 if (target_window != root_window)
3880 {
3881 unsigned int
3882 d;
3883
3884 /*
3885 Get client window.
3886 */
3887 status=XGetGeometry(display,target_window,&root_window,&x,&x,&d,&d,&d,&d);
3888 if (status != False)
3889 {
3890 client_window=XClientWindow(display,target_window);
3891 target_window=client_window;
3892 }
3893 }
3894 /*
3895 Verify window is viewable.
3896 */
3897 status=XGetWindowAttributes(display,target_window,&window_attributes);
3898 if ((status == False) || (window_attributes.map_state != IsViewable))
3899 return(MagickFalse);
3900 /*
3901 Get window X image.
3902 */
3903 (void) XTranslateCoordinates(display,root_window,target_window,
3904 (int) crop_info.x,(int) crop_info.y,&x,&y,&child);
3905 ximage=XGetImage(display,target_window,x,y,1,1,AllPlanes,ZPixmap);
3906 if (ximage == (XImage *) NULL)
3907 return(MagickFalse);
3908 color.pixel=XGetPixel(ximage,0,0);
3909 XDestroyImage(ximage);
3910 /*
3911 Match color against the color database.
3912 */
3913 (void) XQueryColor(display,window_attributes.colormap,&color);
3914 pixel.red=ScaleShortToQuantum(color.red);
3915 pixel.green=ScaleShortToQuantum(color.green);
3916 pixel.blue=ScaleShortToQuantum(color.blue);
cristy4c08aed2011-07-01 19:47:50 +00003917 pixel.alpha=OpaqueAlpha;
cristy3ed852e2009-09-05 21:47:34 +00003918 (void) QueryColorname(windows->image.image,&pixel,X11Compliance,name,
3919 &windows->image.image->exception);
3920 return(MagickTrue);
3921}
3922
3923/*
3924%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3925% %
3926% %
3927% %
3928+ X G e t W i n d o w I m a g e %
3929% %
3930% %
3931% %
3932%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3933%
3934% XGetWindowImage() reads an image from the target X window and returns it.
3935% XGetWindowImage() optionally descends the window hierarchy and overlays the
3936% target image with each child image in an optimized fashion. Any child
3937% window that have the same visual, colormap, and are contained by its parent
3938% are exempted.
3939%
3940% The format of the XGetWindowImage method is:
3941%
3942% Image *XGetWindowImage(Display *display,const Window window,
3943% const unsigned int borders,const unsigned int level)
3944%
3945% A description of each parameter follows:
3946%
3947% o display: Specifies a connection to an X server; returned from
3948% XOpenDisplay.
3949%
3950% o window: Specifies the window to obtain the image from.
3951%
3952% o borders: Specifies whether borders pixels are to be saved with
3953% the image.
3954%
3955% o level: Specifies an unsigned integer representing the level of
3956% decent in the window hierarchy. This value must be zero or one on
3957% the initial call to XGetWindowImage. A value of zero returns after
3958% one call. A value of one causes the function to descend the window
3959% hierarchy and overlay the target image with each subwindow image.
3960%
cristy3ed852e2009-09-05 21:47:34 +00003961*/
3962static Image *XGetWindowImage(Display *display,const Window window,
3963 const unsigned int borders,const unsigned int level)
3964{
3965 typedef struct _ColormapInfo
3966 {
3967 Colormap
3968 colormap;
3969
3970 XColor
3971 *colors;
3972
3973 struct _ColormapInfo
3974 *next;
3975 } ColormapInfo;
3976
3977 typedef struct _WindowInfo
3978 {
3979 Window
3980 window,
3981 parent;
3982
3983 Visual
3984 *visual;
3985
3986 Colormap
3987 colormap;
3988
3989 XSegment
3990 bounds;
3991
3992 RectangleInfo
3993 crop_info;
3994 } WindowInfo;
3995
cristy3ed852e2009-09-05 21:47:34 +00003996 int
3997 display_height,
3998 display_width,
3999 id,
4000 x_offset,
4001 y_offset;
4002
cristy4c08aed2011-07-01 19:47:50 +00004003 Quantum
4004 index;
4005
cristy3ed852e2009-09-05 21:47:34 +00004006 RectangleInfo
4007 crop_info;
4008
cristy3ed852e2009-09-05 21:47:34 +00004009 register int
4010 i;
4011
4012 static ColormapInfo
4013 *colormap_info = (ColormapInfo *) NULL;
4014
4015 static int
4016 max_windows = 0,
4017 number_windows = 0;
4018
4019 static WindowInfo
4020 *window_info;
4021
4022 Status
4023 status;
4024
4025 Window
4026 child,
4027 root_window;
4028
4029 XWindowAttributes
4030 window_attributes;
4031
4032 /*
4033 Verify window is viewable.
4034 */
4035 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
4036 assert(display != (Display *) NULL);
4037 status=XGetWindowAttributes(display,window,&window_attributes);
4038 if ((status == False) || (window_attributes.map_state != IsViewable))
4039 return((Image *) NULL);
4040 /*
4041 Cropping rectangle is relative to root window.
4042 */
4043 root_window=XRootWindow(display,XDefaultScreen(display));
4044 (void) XTranslateCoordinates(display,window,root_window,0,0,&x_offset,
4045 &y_offset,&child);
cristybb503372010-05-27 20:51:26 +00004046 crop_info.x=(ssize_t) x_offset;
4047 crop_info.y=(ssize_t) y_offset;
4048 crop_info.width=(size_t) window_attributes.width;
4049 crop_info.height=(size_t) window_attributes.height;
cristy3ed852e2009-09-05 21:47:34 +00004050 if (borders != MagickFalse)
4051 {
4052 /*
4053 Include border in image.
4054 */
cristybb503372010-05-27 20:51:26 +00004055 crop_info.x-=(ssize_t) window_attributes.border_width;
4056 crop_info.y-=(ssize_t) window_attributes.border_width;
4057 crop_info.width+=(size_t) (window_attributes.border_width << 1);
4058 crop_info.height+=(size_t) (window_attributes.border_width << 1);
cristy3ed852e2009-09-05 21:47:34 +00004059 }
4060 /*
4061 Crop to root window.
4062 */
4063 if (crop_info.x < 0)
4064 {
4065 crop_info.width+=crop_info.x;
4066 crop_info.x=0;
4067 }
4068 if (crop_info.y < 0)
4069 {
4070 crop_info.height+=crop_info.y;
4071 crop_info.y=0;
4072 }
4073 display_width=XDisplayWidth(display,XDefaultScreen(display));
4074 if ((int) (crop_info.x+crop_info.width) > display_width)
cristybb503372010-05-27 20:51:26 +00004075 crop_info.width=(size_t) (display_width-crop_info.x);
cristy3ed852e2009-09-05 21:47:34 +00004076 display_height=XDisplayHeight(display,XDefaultScreen(display));
4077 if ((int) (crop_info.y+crop_info.height) > display_height)
cristybb503372010-05-27 20:51:26 +00004078 crop_info.height=(size_t) (display_height-crop_info.y);
cristy3ed852e2009-09-05 21:47:34 +00004079 /*
4080 Initialize window info attributes.
4081 */
4082 if (number_windows >= max_windows)
4083 {
4084 /*
4085 Allocate or resize window info buffer.
4086 */
4087 max_windows+=1024;
4088 if (window_info == (WindowInfo *) NULL)
4089 window_info=(WindowInfo *) AcquireQuantumMemory((size_t) max_windows,
4090 sizeof(*window_info));
4091 else
4092 window_info=(WindowInfo *) ResizeQuantumMemory(window_info,(size_t)
4093 max_windows,sizeof(*window_info));
4094 }
4095 if (window_info == (WindowInfo *) NULL)
4096 {
4097 ThrowXWindowFatalException(ResourceLimitError,
4098 "MemoryAllocationFailed","...");
4099 return((Image *) NULL);
4100 }
4101 id=number_windows++;
4102 window_info[id].window=window;
4103 window_info[id].visual=window_attributes.visual;
4104 window_info[id].colormap=window_attributes.colormap;
4105 window_info[id].bounds.x1=(short) crop_info.x;
4106 window_info[id].bounds.y1=(short) crop_info.y;
4107 window_info[id].bounds.x2=(short) (crop_info.x+(int) crop_info.width-1);
4108 window_info[id].bounds.y2=(short) (crop_info.y+(int) crop_info.height-1);
4109 crop_info.x-=x_offset;
4110 crop_info.y-=y_offset;
4111 window_info[id].crop_info=crop_info;
4112 if (level != 0)
4113 {
4114 unsigned int
4115 number_children;
4116
4117 Window
4118 *children;
4119
4120 /*
4121 Descend the window hierarchy.
4122 */
4123 status=XQueryTree(display,window,&root_window,&window_info[id].parent,
4124 &children,&number_children);
4125 for (i=0; i < id; i++)
4126 if ((window_info[i].window == window_info[id].parent) &&
4127 (window_info[i].visual == window_info[id].visual) &&
4128 (window_info[i].colormap == window_info[id].colormap))
4129 {
4130 if ((window_info[id].bounds.x1 <= window_info[i].bounds.x1) ||
4131 (window_info[id].bounds.x1 >= window_info[i].bounds.x2) ||
4132 (window_info[id].bounds.y1 <= window_info[i].bounds.y1) ||
4133 (window_info[id].bounds.y1 >= window_info[i].bounds.y2))
4134 {
4135 /*
4136 Eliminate windows not circumscribed by their parent.
4137 */
4138 number_windows--;
4139 break;
4140 }
4141 }
4142 if ((status == True) && (number_children != 0))
4143 {
4144 for (i=0; i < (int) number_children; i++)
4145 (void) XGetWindowImage(display,children[i],MagickFalse,level+1);
4146 (void) XFree((void *) children);
4147 }
4148 }
4149 if (level <= 1)
4150 {
cristyc57f6942010-11-12 01:47:39 +00004151 CacheView
4152 *composite_view;
4153
cristy3ed852e2009-09-05 21:47:34 +00004154 ColormapInfo
4155 *next;
4156
4157 ExceptionInfo
4158 *exception;
4159
4160 Image
4161 *composite_image,
4162 *image;
4163
4164 int
4165 y;
4166
4167 MagickBooleanType
4168 import;
4169
4170 register int
4171 j,
4172 x;
4173
cristy4c08aed2011-07-01 19:47:50 +00004174 register Quantum
cristyc47d1f82009-11-26 01:44:43 +00004175 *restrict q;
cristy3ed852e2009-09-05 21:47:34 +00004176
cristybb503372010-05-27 20:51:26 +00004177 register size_t
cristy3ed852e2009-09-05 21:47:34 +00004178 pixel;
4179
4180 unsigned int
4181 number_colors;
4182
4183 XColor
4184 *colors;
4185
4186 XImage
4187 *ximage;
4188
4189 /*
4190 Get X image for each window in the list.
4191 */
4192 image=NewImageList();
4193 for (id=0; id < number_windows; id++)
4194 {
4195 /*
4196 Does target window intersect top level window?
4197 */
4198 import=
4199 ((window_info[id].bounds.x2 >= window_info[0].bounds.x1) &&
4200 (window_info[id].bounds.x1 <= window_info[0].bounds.x2) &&
4201 (window_info[id].bounds.y2 >= window_info[0].bounds.y1) &&
4202 (window_info[id].bounds.y1 <= window_info[0].bounds.y2)) ?
4203 MagickTrue : MagickFalse;
4204 /*
4205 Is target window contained by another window with the same colormap?
4206 */
4207 for (j=0; j < id; j++)
4208 if ((window_info[id].visual == window_info[j].visual) &&
4209 (window_info[id].colormap == window_info[j].colormap))
4210 {
4211 if ((window_info[id].bounds.x1 <= window_info[j].bounds.x1) ||
4212 (window_info[id].bounds.x1 >= window_info[j].bounds.x2) ||
4213 (window_info[id].bounds.y1 <= window_info[j].bounds.y1) ||
4214 (window_info[id].bounds.y1 >= window_info[j].bounds.y2))
4215 import=MagickFalse;
4216 }
4217 else
4218 if ((window_info[id].visual != window_info[j].visual) ||
4219 (window_info[id].colormap != window_info[j].colormap))
4220 {
4221 if ((window_info[id].bounds.x2 > window_info[j].bounds.x1) &&
4222 (window_info[id].bounds.x1 < window_info[j].bounds.x2) &&
4223 (window_info[id].bounds.y2 > window_info[j].bounds.y1) &&
4224 (window_info[id].bounds.y1 < window_info[j].bounds.y2))
4225 import=MagickTrue;
4226 }
4227 if (import == MagickFalse)
4228 continue;
4229 /*
4230 Get X image.
4231 */
4232 ximage=XGetImage(display,window_info[id].window,(int)
4233 window_info[id].crop_info.x,(int) window_info[id].crop_info.y,
4234 (unsigned int) window_info[id].crop_info.width,(unsigned int)
4235 window_info[id].crop_info.height,AllPlanes,ZPixmap);
4236 if (ximage == (XImage *) NULL)
4237 continue;
4238 /*
4239 Initialize window colormap.
4240 */
4241 number_colors=0;
4242 colors=(XColor *) NULL;
4243 if (window_info[id].colormap != (Colormap) NULL)
4244 {
4245 ColormapInfo
4246 *p;
4247
4248 /*
4249 Search colormap list for window colormap.
4250 */
4251 number_colors=(unsigned int) window_info[id].visual->map_entries;
4252 for (p=colormap_info; p != (ColormapInfo *) NULL; p=p->next)
4253 if (p->colormap == window_info[id].colormap)
4254 break;
4255 if (p == (ColormapInfo *) NULL)
4256 {
4257 /*
4258 Get the window colormap.
4259 */
4260 colors=(XColor *) AcquireQuantumMemory(number_colors,
4261 sizeof(*colors));
4262 if (colors == (XColor *) NULL)
4263 {
4264 XDestroyImage(ximage);
4265 return((Image *) NULL);
4266 }
4267 if ((window_info[id].visual->klass != DirectColor) &&
4268 (window_info[id].visual->klass != TrueColor))
4269 for (i=0; i < (int) number_colors; i++)
4270 {
cristybb503372010-05-27 20:51:26 +00004271 colors[i].pixel=(size_t) i;
cristy3ed852e2009-09-05 21:47:34 +00004272 colors[i].pad='\0';
4273 }
4274 else
4275 {
cristybb503372010-05-27 20:51:26 +00004276 size_t
cristy3ed852e2009-09-05 21:47:34 +00004277 blue,
4278 blue_bit,
4279 green,
4280 green_bit,
4281 red,
4282 red_bit;
4283
4284 /*
4285 DirectColor or TrueColor visual.
4286 */
4287 red=0;
4288 green=0;
4289 blue=0;
4290 red_bit=window_info[id].visual->red_mask &
4291 (~(window_info[id].visual->red_mask)+1);
4292 green_bit=window_info[id].visual->green_mask &
4293 (~(window_info[id].visual->green_mask)+1);
4294 blue_bit=window_info[id].visual->blue_mask &
4295 (~(window_info[id].visual->blue_mask)+1);
4296 for (i=0; i < (int) number_colors; i++)
4297 {
cristy8891f9c2010-06-04 23:32:17 +00004298 colors[i].pixel=(unsigned long) (red | green | blue);
cristy3ed852e2009-09-05 21:47:34 +00004299 colors[i].pad='\0';
4300 red+=red_bit;
4301 if (red > window_info[id].visual->red_mask)
4302 red=0;
4303 green+=green_bit;
4304 if (green > window_info[id].visual->green_mask)
4305 green=0;
4306 blue+=blue_bit;
4307 if (blue > window_info[id].visual->blue_mask)
4308 blue=0;
4309 }
4310 }
4311 (void) XQueryColors(display,window_info[id].colormap,colors,
4312 (int) number_colors);
4313 /*
4314 Append colormap to colormap list.
4315 */
cristy73bd4a52010-10-05 11:24:23 +00004316 p=(ColormapInfo *) AcquireMagickMemory(sizeof(*p));
cristy3ed852e2009-09-05 21:47:34 +00004317 if (p == (ColormapInfo *) NULL)
4318 return((Image *) NULL);
4319 p->colormap=window_info[id].colormap;
4320 p->colors=colors;
4321 p->next=colormap_info;
4322 colormap_info=p;
4323 }
4324 colors=p->colors;
4325 }
4326 /*
4327 Allocate image structure.
4328 */
4329 composite_image=AcquireImage((ImageInfo *) NULL);
4330 if (composite_image == (Image *) NULL)
4331 {
4332 XDestroyImage(ximage);
4333 return((Image *) NULL);
4334 }
4335 /*
4336 Convert X image to MIFF format.
4337 */
4338 if ((window_info[id].visual->klass != TrueColor) &&
4339 (window_info[id].visual->klass != DirectColor))
4340 composite_image->storage_class=PseudoClass;
cristybb503372010-05-27 20:51:26 +00004341 composite_image->columns=(size_t) ximage->width;
4342 composite_image->rows=(size_t) ximage->height;
cristy3ed852e2009-09-05 21:47:34 +00004343 exception=(&composite_image->exception);
cristyc57f6942010-11-12 01:47:39 +00004344 composite_view=AcquireCacheView(composite_image);
cristy3ed852e2009-09-05 21:47:34 +00004345 switch (composite_image->storage_class)
4346 {
4347 case DirectClass:
4348 default:
4349 {
cristybb503372010-05-27 20:51:26 +00004350 register size_t
cristy3ed852e2009-09-05 21:47:34 +00004351 color,
4352 index;
4353
cristybb503372010-05-27 20:51:26 +00004354 size_t
cristy3ed852e2009-09-05 21:47:34 +00004355 blue_mask,
4356 blue_shift,
4357 green_mask,
4358 green_shift,
4359 red_mask,
4360 red_shift;
4361
4362 /*
4363 Determine shift and mask for red, green, and blue.
4364 */
4365 red_mask=window_info[id].visual->red_mask;
4366 red_shift=0;
4367 while ((red_mask != 0) && ((red_mask & 0x01) == 0))
4368 {
4369 red_mask>>=1;
4370 red_shift++;
4371 }
4372 green_mask=window_info[id].visual->green_mask;
4373 green_shift=0;
4374 while ((green_mask != 0) && ((green_mask & 0x01) == 0))
4375 {
4376 green_mask>>=1;
4377 green_shift++;
4378 }
4379 blue_mask=window_info[id].visual->blue_mask;
4380 blue_shift=0;
4381 while ((blue_mask != 0) && ((blue_mask & 0x01) == 0))
4382 {
4383 blue_mask>>=1;
4384 blue_shift++;
4385 }
4386 /*
4387 Convert X image to DirectClass packets.
4388 */
4389 if ((number_colors != 0) &&
4390 (window_info[id].visual->klass == DirectColor))
4391 for (y=0; y < (int) composite_image->rows; y++)
4392 {
cristyc57f6942010-11-12 01:47:39 +00004393 q=QueueCacheViewAuthenticPixels(composite_view,0,(ssize_t) y,
cristy3ed852e2009-09-05 21:47:34 +00004394 composite_image->columns,1,exception);
cristyacd2ed22011-08-30 01:44:23 +00004395 if (q == (Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00004396 break;
4397 for (x=0; x < (int) composite_image->columns; x++)
4398 {
4399 pixel=XGetPixel(ximage,x,y);
4400 index=(pixel >> red_shift) & red_mask;
cristy4c08aed2011-07-01 19:47:50 +00004401 SetPixelRed(composite_image,
4402 ScaleShortToQuantum(colors[index].red),q);
cristy3ed852e2009-09-05 21:47:34 +00004403 index=(pixel >> green_shift) & green_mask;
cristy4c08aed2011-07-01 19:47:50 +00004404 SetPixelGreen(composite_image,
4405 ScaleShortToQuantum(colors[index].green),q);
cristy3ed852e2009-09-05 21:47:34 +00004406 index=(pixel >> blue_shift) & blue_mask;
cristy4c08aed2011-07-01 19:47:50 +00004407 SetPixelBlue(composite_image,
4408 ScaleShortToQuantum(colors[index].blue),q);
cristyed231572011-07-14 02:18:59 +00004409 q+=GetPixelChannels(composite_image);
cristy3ed852e2009-09-05 21:47:34 +00004410 }
cristyc57f6942010-11-12 01:47:39 +00004411 if (SyncCacheViewAuthenticPixels(composite_view,exception) == MagickFalse)
cristy3ed852e2009-09-05 21:47:34 +00004412 break;
4413 }
4414 else
4415 for (y=0; y < (int) composite_image->rows; y++)
4416 {
cristyc57f6942010-11-12 01:47:39 +00004417 q=QueueCacheViewAuthenticPixels(composite_view,0,(ssize_t) y,
cristy3ed852e2009-09-05 21:47:34 +00004418 composite_image->columns,1,exception);
cristyacd2ed22011-08-30 01:44:23 +00004419 if (q == (Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00004420 break;
4421 for (x=0; x < (int) composite_image->columns; x++)
4422 {
4423 pixel=XGetPixel(ximage,x,y);
4424 color=(pixel >> red_shift) & red_mask;
4425 color=(65535UL*color)/red_mask;
cristy4c08aed2011-07-01 19:47:50 +00004426 SetPixelRed(composite_image,
4427 ScaleShortToQuantum((unsigned short) color),q);
cristy3ed852e2009-09-05 21:47:34 +00004428 color=(pixel >> green_shift) & green_mask;
4429 color=(65535UL*color)/green_mask;
cristy4c08aed2011-07-01 19:47:50 +00004430 SetPixelGreen(composite_image,
4431 ScaleShortToQuantum((unsigned short) color),q);
cristy3ed852e2009-09-05 21:47:34 +00004432 color=(pixel >> blue_shift) & blue_mask;
4433 color=(65535UL*color)/blue_mask;
cristy4c08aed2011-07-01 19:47:50 +00004434 SetPixelBlue(composite_image,
4435 ScaleShortToQuantum((unsigned short) color),q);
cristyed231572011-07-14 02:18:59 +00004436 q+=GetPixelChannels(composite_image);
cristy3ed852e2009-09-05 21:47:34 +00004437 }
cristyc57f6942010-11-12 01:47:39 +00004438 if (SyncCacheViewAuthenticPixels(composite_view,exception) == MagickFalse)
cristy3ed852e2009-09-05 21:47:34 +00004439 break;
4440 }
4441 break;
4442 }
4443 case PseudoClass:
4444 {
4445 /*
4446 Create colormap.
4447 */
4448 if (AcquireImageColormap(composite_image,number_colors) == MagickFalse)
4449 {
4450 XDestroyImage(ximage);
4451 composite_image=DestroyImage(composite_image);
4452 return((Image *) NULL);
4453 }
4454 for (i=0; i < (int) composite_image->colors; i++)
4455 {
4456 composite_image->colormap[colors[i].pixel].red=
4457 ScaleShortToQuantum(colors[i].red);
4458 composite_image->colormap[colors[i].pixel].green=
4459 ScaleShortToQuantum(colors[i].green);
4460 composite_image->colormap[colors[i].pixel].blue=
4461 ScaleShortToQuantum(colors[i].blue);
4462 }
4463 /*
4464 Convert X image to PseudoClass packets.
4465 */
4466 for (y=0; y < (int) composite_image->rows; y++)
4467 {
cristyc57f6942010-11-12 01:47:39 +00004468 q=QueueCacheViewAuthenticPixels(composite_view,0,(ssize_t) y,
4469 composite_image->columns,1,exception);
cristyacd2ed22011-08-30 01:44:23 +00004470 if (q == (Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00004471 break;
cristy3ed852e2009-09-05 21:47:34 +00004472 for (x=0; x < (int) composite_image->columns; x++)
4473 {
cristy4c08aed2011-07-01 19:47:50 +00004474 index=(Quantum) XGetPixel(ximage,x,y);
4475 SetPixelIndex(composite_image,index,q);
4476 SetPixelPacket(composite_image,
4477 composite_image->colormap+(ssize_t) index,q);
cristyed231572011-07-14 02:18:59 +00004478 q+=GetPixelChannels(composite_image);
cristy3ed852e2009-09-05 21:47:34 +00004479 }
cristyc57f6942010-11-12 01:47:39 +00004480 if (SyncCacheViewAuthenticPixels(composite_view,exception) == MagickFalse)
cristy3ed852e2009-09-05 21:47:34 +00004481 break;
4482 }
4483 break;
4484 }
4485 }
cristyc57f6942010-11-12 01:47:39 +00004486 composite_view=DestroyCacheView(composite_view);
cristy3ed852e2009-09-05 21:47:34 +00004487 XDestroyImage(ximage);
4488 if (image == (Image *) NULL)
4489 {
4490 image=composite_image;
4491 continue;
4492 }
4493 /*
4494 Composite any children in back-to-front order.
4495 */
4496 (void) XTranslateCoordinates(display,window_info[id].window,window,0,0,
4497 &x_offset,&y_offset,&child);
4498 x_offset-=(int) crop_info.x;
4499 if (x_offset < 0)
4500 x_offset=0;
4501 y_offset-=(int) crop_info.y;
4502 if (y_offset < 0)
4503 y_offset=0;
cristyc57f6942010-11-12 01:47:39 +00004504 (void) CompositeImage(image,CopyCompositeOp,composite_image,(ssize_t)
4505 x_offset,(ssize_t) y_offset);
cristy3ed852e2009-09-05 21:47:34 +00004506 }
4507 /*
4508 Relinquish resources.
4509 */
4510 while (colormap_info != (ColormapInfo *) NULL)
4511 {
4512 next=colormap_info->next;
4513 colormap_info->colors=(XColor *)
4514 RelinquishMagickMemory(colormap_info->colors);
4515 colormap_info=(ColormapInfo *) RelinquishMagickMemory(colormap_info);
4516 colormap_info=next;
4517 }
4518 /*
4519 Relinquish resources and restore initial state.
4520 */
4521 window_info=(WindowInfo *) RelinquishMagickMemory(window_info);
4522 max_windows=0;
4523 number_windows=0;
4524 colormap_info=(ColormapInfo *) NULL;
4525 return(image);
4526 }
4527 return((Image *) NULL);
4528}
4529
4530/*
4531%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4532% %
4533% %
4534% %
4535% X G e t W i n d o w I n f o %
4536% %
4537% %
4538% %
4539%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4540%
4541% XGetWindowInfo() initializes the XWindowInfo structure.
4542%
4543% The format of the XGetWindowInfo method is:
4544%
4545% void XGetWindowInfo(Display *display,XVisualInfo *visual_info,
4546% XStandardColormap *map_info,XPixelInfo *pixel,XFontStruct *font_info,
4547% XResourceInfo *resource_info,XWindowInfo *window)
4548% resource_info,window)
4549%
4550% A description of each parameter follows:
4551%
4552% o display: Specifies a connection to an X server; returned from
4553% XOpenDisplay.
4554%
4555% o visual_info: Specifies a pointer to a X11 XVisualInfo structure;
4556% returned from XGetVisualInfo.
4557%
4558% o map_info: If map_type is specified, this structure is initialized
4559% with info from the Standard Colormap.
4560%
4561% o pixel: Specifies a pointer to a XPixelInfo structure.
4562%
4563% o font_info: Specifies a pointer to a XFontStruct structure.
4564%
4565% o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
4566%
4567*/
cristybcbda3f2011-09-03 13:01:22 +00004568MagickPrivate void XGetWindowInfo(Display *display,XVisualInfo *visual_info,
cristy3ed852e2009-09-05 21:47:34 +00004569 XStandardColormap *map_info,XPixelInfo *pixel,XFontStruct *font_info,
4570 XResourceInfo *resource_info,XWindowInfo *window)
4571{
4572 /*
4573 Initialize window info.
4574 */
4575 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
4576 assert(display != (Display *) NULL);
4577 assert(visual_info != (XVisualInfo *) NULL);
4578 assert(map_info != (XStandardColormap *) NULL);
4579 assert(pixel != (XPixelInfo *) NULL);
4580 assert(resource_info != (XResourceInfo *) NULL);
4581 assert(window != (XWindowInfo *) NULL);
4582 if (window->id != (Window) NULL)
4583 {
4584 if (window->cursor != (Cursor) NULL)
4585 (void) XFreeCursor(display,window->cursor);
4586 if (window->busy_cursor != (Cursor) NULL)
4587 (void) XFreeCursor(display,window->busy_cursor);
4588 if (window->highlight_stipple != (Pixmap) NULL)
4589 (void) XFreePixmap(display,window->highlight_stipple);
4590 if (window->shadow_stipple != (Pixmap) NULL)
4591 (void) XFreePixmap(display,window->shadow_stipple);
4592 if (window->name == (char *) NULL)
4593 window->name=AcquireString("");
4594 if (window->icon_name == (char *) NULL)
4595 window->icon_name=AcquireString("");
4596 }
4597 else
4598 {
4599 /*
4600 Initialize these attributes just once.
4601 */
4602 window->id=(Window) NULL;
4603 if (window->name == (char *) NULL)
4604 window->name=AcquireString("");
4605 if (window->icon_name == (char *) NULL)
4606 window->icon_name=AcquireString("");
4607 window->x=XDisplayWidth(display,visual_info->screen) >> 1;
4608 window->y=XDisplayWidth(display,visual_info->screen) >> 1;
4609 window->ximage=(XImage *) NULL;
4610 window->matte_image=(XImage *) NULL;
4611 window->pixmap=(Pixmap) NULL;
4612 window->matte_pixmap=(Pixmap) NULL;
4613 window->mapped=MagickFalse;
4614 window->stasis=MagickFalse;
4615 window->shared_memory=MagickTrue;
4616 window->segment_info=(void *) NULL;
4617#if defined(MAGICKCORE_HAVE_SHARED_MEMORY)
4618 {
4619 XShmSegmentInfo
4620 *segment_info;
4621
4622 if (window->segment_info == (void *) NULL)
4623 window->segment_info=AcquireQuantumMemory(2,sizeof(*segment_info));
4624 segment_info=(XShmSegmentInfo *) window->segment_info;
4625 segment_info[0].shmid=(-1);
4626 segment_info[0].shmaddr=(char *) NULL;
4627 segment_info[1].shmid=(-1);
4628 segment_info[1].shmaddr=(char *) NULL;
4629 }
4630#endif
4631 }
4632 /*
4633 Initialize these attributes every time function is called.
4634 */
4635 window->screen=visual_info->screen;
4636 window->root=XRootWindow(display,visual_info->screen);
4637 window->visual=visual_info->visual;
4638 window->storage_class=(unsigned int) visual_info->klass;
4639 window->depth=(unsigned int) visual_info->depth;
4640 window->visual_info=visual_info;
4641 window->map_info=map_info;
4642 window->pixel_info=pixel;
4643 window->font_info=font_info;
4644 window->cursor=XCreateFontCursor(display,XC_left_ptr);
4645 window->busy_cursor=XCreateFontCursor(display,XC_watch);
4646 window->geometry=(char *) NULL;
4647 window->icon_geometry=(char *) NULL;
4648 if (resource_info->icon_geometry != (char *) NULL)
4649 (void) CloneString(&window->icon_geometry,resource_info->icon_geometry);
4650 window->crop_geometry=(char *) NULL;
cristybb503372010-05-27 20:51:26 +00004651 window->flags=(size_t) PSize;
cristy3ed852e2009-09-05 21:47:34 +00004652 window->width=1;
4653 window->height=1;
4654 window->min_width=1;
4655 window->min_height=1;
4656 window->width_inc=1;
4657 window->height_inc=1;
4658 window->border_width=resource_info->border_width;
4659 window->annotate_context=pixel->annotate_context;
4660 window->highlight_context=pixel->highlight_context;
4661 window->widget_context=pixel->widget_context;
4662 window->shadow_stipple=(Pixmap) NULL;
4663 window->highlight_stipple=(Pixmap) NULL;
4664 window->use_pixmap=MagickTrue;
4665 window->immutable=MagickFalse;
4666 window->shape=MagickFalse;
4667 window->data=0;
cristyc57f6942010-11-12 01:47:39 +00004668 window->mask=(int) (CWBackingStore | CWBackPixel | CWBackPixmap |
cristy3ed852e2009-09-05 21:47:34 +00004669 CWBitGravity | CWBorderPixel | CWColormap | CWCursor | CWDontPropagate |
4670 CWEventMask | CWOverrideRedirect | CWSaveUnder | CWWinGravity);
4671 window->attributes.background_pixel=pixel->background_color.pixel;
4672 window->attributes.background_pixmap=(Pixmap) NULL;
4673 window->attributes.bit_gravity=ForgetGravity;
4674 window->attributes.backing_store=WhenMapped;
4675 window->attributes.save_under=MagickTrue;
4676 window->attributes.border_pixel=pixel->border_color.pixel;
4677 window->attributes.colormap=map_info->colormap;
4678 window->attributes.cursor=window->cursor;
4679 window->attributes.do_not_propagate_mask=NoEventMask;
4680 window->attributes.event_mask=NoEventMask;
4681 window->attributes.override_redirect=MagickFalse;
4682 window->attributes.win_gravity=NorthWestGravity;
4683 window->orphan=MagickFalse;
4684}
4685
4686/*
4687%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4688% %
4689% %
4690% %
4691% X H i g h l i g h t E l l i p s e %
4692% %
4693% %
4694% %
4695%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4696%
4697% XHighlightEllipse() puts a border on the X server around a region defined by
4698% highlight_info.
4699%
4700% The format of the XHighlightEllipse method is:
4701%
4702% void XHighlightEllipse(Display *display,Window window,
4703% GC annotate_context,const RectangleInfo *highlight_info)
4704%
4705% A description of each parameter follows:
4706%
4707% o display: Specifies a connection to an X server; returned from
4708% XOpenDisplay.
4709%
4710% o window: Specifies a pointer to a Window structure.
4711%
4712% o annotate_context: Specifies a pointer to a GC structure.
4713%
4714% o highlight_info: Specifies a pointer to a RectangleInfo structure. It
4715% contains the extents of any highlighting rectangle.
4716%
4717*/
cristybcbda3f2011-09-03 13:01:22 +00004718MagickPrivate void XHighlightEllipse(Display *display,Window window,
cristy3ed852e2009-09-05 21:47:34 +00004719 GC annotate_context,const RectangleInfo *highlight_info)
4720{
4721 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
4722 assert(display != (Display *) NULL);
4723 assert(window != (Window) NULL);
4724 assert(annotate_context != (GC) NULL);
4725 assert(highlight_info != (RectangleInfo *) NULL);
4726 if ((highlight_info->width < 4) || (highlight_info->height < 4))
4727 return;
4728 (void) XDrawArc(display,window,annotate_context,(int) highlight_info->x,
4729 (int) highlight_info->y,(unsigned int) highlight_info->width-1,
4730 (unsigned int) highlight_info->height-1,0,360*64);
4731 (void) XDrawArc(display,window,annotate_context,(int) highlight_info->x+1,
4732 (int) highlight_info->y+1,(unsigned int) highlight_info->width-3,
4733 (unsigned int) highlight_info->height-3,0,360*64);
4734}
4735
4736/*
4737%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4738% %
4739% %
4740% %
4741% X H i g h l i g h t L i n e %
4742% %
4743% %
4744% %
4745%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4746%
4747% XHighlightLine() puts a border on the X server around a region defined by
4748% highlight_info.
4749%
4750% The format of the XHighlightLine method is:
4751%
4752% void XHighlightLine(Display *display,Window window,GC annotate_context,
4753% const XSegment *highlight_info)
4754%
4755% A description of each parameter follows:
4756%
4757% o display: Specifies a connection to an X server; returned from
4758% XOpenDisplay.
4759%
4760% o window: Specifies a pointer to a Window structure.
4761%
4762% o annotate_context: Specifies a pointer to a GC structure.
4763%
4764% o highlight_info: Specifies a pointer to a RectangleInfo structure. It
4765% contains the extents of any highlighting rectangle.
4766%
4767*/
cristybcbda3f2011-09-03 13:01:22 +00004768MagickPrivate void XHighlightLine(Display *display,Window window,
cristy3ed852e2009-09-05 21:47:34 +00004769 GC annotate_context,const XSegment *highlight_info)
4770{
4771 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
4772 assert(display != (Display *) NULL);
4773 assert(window != (Window) NULL);
4774 assert(annotate_context != (GC) NULL);
4775 assert(highlight_info != (XSegment *) NULL);
4776 (void) XDrawLine(display,window,annotate_context,highlight_info->x1,
4777 highlight_info->y1,highlight_info->x2,highlight_info->y2);
4778}
4779
4780/*
4781%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4782% %
4783% %
4784% %
4785% X H i g h l i g h t R e c t a n g l e %
4786% %
4787% %
4788% %
4789%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4790%
4791% XHighlightRectangle() puts a border on the X server around a region defined
4792% by highlight_info.
4793%
4794% The format of the XHighlightRectangle method is:
4795%
4796% void XHighlightRectangle(Display *display,Window window,
4797% GC annotate_context,const RectangleInfo *highlight_info)
4798%
4799% A description of each parameter follows:
4800%
4801% o display: Specifies a connection to an X server; returned from
4802% XOpenDisplay.
4803%
4804% o window: Specifies a pointer to a Window structure.
4805%
4806% o annotate_context: Specifies a pointer to a GC structure.
4807%
4808% o highlight_info: Specifies a pointer to a RectangleInfo structure. It
4809% contains the extents of any highlighting rectangle.
4810%
4811*/
cristybcbda3f2011-09-03 13:01:22 +00004812MagickPrivate void XHighlightRectangle(Display *display,Window window,
cristy3ed852e2009-09-05 21:47:34 +00004813 GC annotate_context,const RectangleInfo *highlight_info)
4814{
4815 assert(display != (Display *) NULL);
4816 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
4817 assert(window != (Window) NULL);
4818 assert(annotate_context != (GC) NULL);
4819 assert(highlight_info != (RectangleInfo *) NULL);
4820 if ((highlight_info->width < 4) || (highlight_info->height < 4))
4821 return;
4822 (void) XDrawRectangle(display,window,annotate_context,(int) highlight_info->x,
4823 (int) highlight_info->y,(unsigned int) highlight_info->width-1,
4824 (unsigned int) highlight_info->height-1);
4825 (void) XDrawRectangle(display,window,annotate_context,(int) highlight_info->x+
4826 1,(int) highlight_info->y+1,(unsigned int) highlight_info->width-3,
4827 (unsigned int) highlight_info->height-3);
4828}
4829
4830/*
4831%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4832% %
4833% %
4834% %
4835% X I m p o r t I m a g e %
4836% %
4837% %
4838% %
4839%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4840%
4841% XImportImage() reads an image from an X window.
4842%
4843% The format of the XImportImage method is:
4844%
4845% Image *XImportImage(const ImageInfo *image_info,XImportInfo *ximage_info)
4846%
4847% A description of each parameter follows:
4848%
4849% o image_info: the image info.
4850%
4851% o ximage_info: Specifies a pointer to an XImportInfo structure.
4852%
4853*/
4854MagickExport Image *XImportImage(const ImageInfo *image_info,
4855 XImportInfo *ximage_info)
4856{
4857 Colormap
4858 *colormaps;
4859
4860 Display
4861 *display;
4862
4863 Image
4864 *image;
4865
4866 int
4867 number_colormaps,
4868 number_windows,
4869 x;
4870
4871 RectangleInfo
4872 crop_info;
4873
4874 Status
4875 status;
4876
4877 Window
4878 *children,
4879 client,
4880 prior_target,
4881 root,
4882 target;
4883
4884 XTextProperty
4885 window_name;
4886
4887 /*
4888 Open X server connection.
4889 */
4890 assert(image_info != (const ImageInfo *) NULL);
4891 assert(image_info->signature == MagickSignature);
4892 if (image_info->debug != MagickFalse)
4893 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
4894 image_info->filename);
4895 assert(ximage_info != (XImportInfo *) NULL);
4896 display=XOpenDisplay(image_info->server_name);
4897 if (display == (Display *) NULL)
4898 {
4899 ThrowXWindowFatalException(XServerError,"UnableToOpenXServer",
4900 XDisplayName(image_info->server_name));
4901 return((Image *) NULL);
4902 }
4903 /*
4904 Set our forgiving exception handler.
4905 */
4906 (void) XSetErrorHandler(XError);
4907 /*
4908 Select target window.
4909 */
4910 crop_info.x=0;
4911 crop_info.y=0;
4912 crop_info.width=0;
4913 crop_info.height=0;
4914 root=XRootWindow(display,XDefaultScreen(display));
4915 target=(Window) NULL;
4916 if ((image_info->filename != (char *) NULL) &&
4917 (*image_info->filename != '\0'))
4918 {
4919 if (LocaleCompare(image_info->filename,"root") == 0)
4920 target=root;
4921 else
4922 {
4923 /*
4924 Select window by ID or name.
4925 */
4926 if (isdigit((unsigned char) *image_info->filename) != 0)
4927 target=XWindowByID(display,root,(Window)
4928 strtol(image_info->filename,(char **) NULL,0));
4929 if (target == (Window) NULL)
4930 target=XWindowByName(display,root,image_info->filename);
4931 if (target == (Window) NULL)
4932 ThrowXWindowFatalException(XServerError,
4933 "NoWindowWithSpecifiedIDExists",image_info->filename);
4934 }
4935 }
4936 /*
4937 If target window is not defined, interactively select one.
4938 */
4939 prior_target=target;
4940 if (target == (Window) NULL)
4941 target=XSelectWindow(display,&crop_info);
4942 if (target == (Window) NULL)
4943 ThrowXWindowFatalException(XServerError,"UnableToReadXWindowImage",
4944 image_info->filename);
4945 client=target; /* obsolete */
4946 if (target != root)
4947 {
4948 unsigned int
4949 d;
4950
4951 status=XGetGeometry(display,target,&root,&x,&x,&d,&d,&d,&d);
4952 if (status != False)
4953 {
4954 for ( ; ; )
4955 {
4956 Window
4957 parent;
4958
4959 /*
4960 Find window manager frame.
4961 */
4962 status=XQueryTree(display,target,&root,&parent,&children,&d);
4963 if ((status != False) && (children != (Window *) NULL))
4964 (void) XFree((char *) children);
4965 if ((status == False) || (parent == (Window) NULL) ||
4966 (parent == root))
4967 break;
4968 target=parent;
4969 }
4970 /*
4971 Get client window.
4972 */
4973 client=XClientWindow(display,target);
4974 if (ximage_info->frame == MagickFalse)
4975 target=client;
4976 if ((ximage_info->frame == MagickFalse) &&
4977 (prior_target != MagickFalse))
4978 target=prior_target;
4979 XDelay(display,SuspendTime << 4);
4980 }
4981 }
4982 if (ximage_info->screen)
4983 {
4984 int
4985 y;
4986
4987 Window
4988 child;
4989
4990 XWindowAttributes
4991 window_attributes;
4992
4993 /*
4994 Obtain window image directly from screen.
4995 */
4996 status=XGetWindowAttributes(display,target,&window_attributes);
4997 if (status == False)
4998 {
4999 ThrowXWindowFatalException(XServerError,
5000 "UnableToReadXWindowAttributes",image_info->filename);
5001 (void) XCloseDisplay(display);
5002 return((Image *) NULL);
5003 }
5004 (void) XTranslateCoordinates(display,target,root,0,0,&x,&y,&child);
cristyc57f6942010-11-12 01:47:39 +00005005 crop_info.x=(ssize_t) x;
5006 crop_info.y=(ssize_t) y;
cristybb503372010-05-27 20:51:26 +00005007 crop_info.width=(size_t) window_attributes.width;
5008 crop_info.height=(size_t) window_attributes.height;
cristy553743c2010-03-03 15:04:17 +00005009 if (ximage_info->borders != 0)
cristy3ed852e2009-09-05 21:47:34 +00005010 {
5011 /*
5012 Include border in image.
5013 */
5014 crop_info.x-=window_attributes.border_width;
5015 crop_info.y-=window_attributes.border_width;
5016 crop_info.width+=window_attributes.border_width << 1;
5017 crop_info.height+=window_attributes.border_width << 1;
5018 }
5019 target=root;
5020 }
5021 /*
5022 If WM_COLORMAP_WINDOWS property is set or multiple colormaps, descend.
5023 */
5024 number_windows=0;
5025 status=XGetWMColormapWindows(display,target,&children,&number_windows);
5026 if ((status == True) && (number_windows > 0))
5027 {
5028 ximage_info->descend=MagickTrue;
5029 (void) XFree ((char *) children);
5030 }
5031 colormaps=XListInstalledColormaps(display,target,&number_colormaps);
5032 if (number_colormaps > 0)
5033 {
5034 if (number_colormaps > 1)
5035 ximage_info->descend=MagickTrue;
5036 (void) XFree((char *) colormaps);
5037 }
5038 /*
5039 Alert the user not to alter the screen.
5040 */
5041 if (ximage_info->silent == MagickFalse)
5042 (void) XBell(display,0);
5043 /*
5044 Get image by window id.
5045 */
5046 (void) XGrabServer(display);
5047 image=XGetWindowImage(display,target,ximage_info->borders,
5048 ximage_info->descend ? 1U : 0U);
5049 (void) XUngrabServer(display);
5050 if (image == (Image *) NULL)
5051 ThrowXWindowFatalException(XServerError,"UnableToReadXWindowImage",
5052 image_info->filename)
5053 else
5054 {
5055 (void) CopyMagickString(image->filename,image_info->filename,
5056 MaxTextExtent);
5057 if ((crop_info.width != 0) && (crop_info.height != 0))
5058 {
5059 Image
5060 *clone_image,
5061 *crop_image;
5062
5063 /*
5064 Crop image as defined by the cropping rectangle.
5065 */
5066 clone_image=CloneImage(image,0,0,MagickTrue,&image->exception);
5067 if (clone_image != (Image *) NULL)
5068 {
5069 crop_image=CropImage(clone_image,&crop_info,&image->exception);
5070 if (crop_image != (Image *) NULL)
5071 {
5072 image=DestroyImage(image);
5073 image=crop_image;
5074 }
5075 }
5076 }
5077 status=XGetWMName(display,target,&window_name);
5078 if (status == True)
5079 {
5080 if ((image_info->filename != (char *) NULL) &&
5081 (*image_info->filename == '\0'))
5082 (void) CopyMagickString(image->filename,(char *) window_name.value,
5083 (size_t) window_name.nitems+1);
5084 (void) XFree((void *) window_name.value);
5085 }
5086 }
5087 if (ximage_info->silent == MagickFalse)
5088 {
5089 /*
5090 Alert the user we're done.
5091 */
5092 (void) XBell(display,0);
5093 (void) XBell(display,0);
5094 }
5095 (void) XCloseDisplay(display);
5096 return(image);
5097}
5098
5099/*
5100%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5101% %
5102% %
5103% %
5104% X I n i t i a l i z e W i n d o w s %
5105% %
5106% %
5107% %
5108%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5109%
5110% XInitializeWindows() initializes the XWindows structure.
5111%
5112% The format of the XInitializeWindows method is:
5113%
5114% XWindows *XInitializeWindows(Display *display,
5115% XResourceInfo *resource_info)
5116%
5117% A description of each parameter follows:
5118%
5119% o windows: XInitializeWindows returns a pointer to a XWindows structure.
5120%
5121% o display: Specifies a connection to an X server; returned from
5122% XOpenDisplay.
5123%
5124% o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
5125%
5126*/
cristybcbda3f2011-09-03 13:01:22 +00005127MagickPrivate XWindows *XInitializeWindows(Display *display,
cristy3ed852e2009-09-05 21:47:34 +00005128 XResourceInfo *resource_info)
5129{
5130 Window
5131 root_window;
5132
5133 XWindows
5134 *windows;
5135
5136 /*
5137 Allocate windows structure.
5138 */
cristy73bd4a52010-10-05 11:24:23 +00005139 windows=(XWindows *) AcquireMagickMemory(sizeof(*windows));
cristy3ed852e2009-09-05 21:47:34 +00005140 if (windows == (XWindows *) NULL)
5141 {
5142 ThrowXWindowFatalException(XServerFatalError,"MemoryAllocationFailed",
5143 "...");
5144 return((XWindows *) NULL);
5145 }
5146 (void) ResetMagickMemory(windows,0,sizeof(*windows));
5147 windows->pixel_info=(XPixelInfo *) AcquireMagickMemory(
5148 sizeof(*windows->pixel_info));
5149 windows->icon_pixel=(XPixelInfo *) AcquireMagickMemory(
5150 sizeof(*windows->icon_pixel));
5151 windows->icon_resources=(XResourceInfo *) AcquireMagickMemory(
5152 sizeof(*windows->icon_resources));
5153 if ((windows->pixel_info == (XPixelInfo *) NULL) ||
5154 (windows->icon_pixel == (XPixelInfo *) NULL) ||
5155 (windows->icon_resources == (XResourceInfo *) NULL))
5156 {
5157 ThrowXWindowFatalException(XServerFatalError,"MemoryAllocationFailed",
5158 "...");
5159 return((XWindows *) NULL);
5160 }
5161 /*
5162 Initialize windows structure.
5163 */
5164 windows->display=display;
5165 windows->wm_protocols=XInternAtom(display,"WM_PROTOCOLS",MagickFalse);
5166 windows->wm_delete_window=XInternAtom(display,"WM_DELETE_WINDOW",MagickFalse);
5167 windows->wm_take_focus=XInternAtom(display,"WM_TAKE_FOCUS",MagickFalse);
5168 windows->im_protocols=XInternAtom(display,"IM_PROTOCOLS",MagickFalse);
5169 windows->im_remote_command=
5170 XInternAtom(display,"IM_REMOTE_COMMAND",MagickFalse);
5171 windows->im_update_widget=XInternAtom(display,"IM_UPDATE_WIDGET",MagickFalse);
5172 windows->im_update_colormap=
5173 XInternAtom(display,"IM_UPDATE_COLORMAP",MagickFalse);
5174 windows->im_former_image=XInternAtom(display,"IM_FORMER_IMAGE",MagickFalse);
5175 windows->im_next_image=XInternAtom(display,"IM_NEXT_IMAGE",MagickFalse);
5176 windows->im_retain_colors=XInternAtom(display,"IM_RETAIN_COLORS",MagickFalse);
5177 windows->im_exit=XInternAtom(display,"IM_EXIT",MagickFalse);
5178 windows->dnd_protocols=XInternAtom(display,"DndProtocol",MagickFalse);
cristy0157aea2010-04-24 21:12:18 +00005179#if defined(MAGICKCORE_WINDOWS_SUPPORT)
cristy3ed852e2009-09-05 21:47:34 +00005180 (void) XSynchronize(display,IsWindows95());
5181#endif
5182 if (IsEventLogging())
5183 {
5184 (void) XSynchronize(display,MagickTrue);
5185 (void) LogMagickEvent(X11Event,GetMagickModule(),"Version: %s",
cristybb503372010-05-27 20:51:26 +00005186 GetMagickVersion((size_t *) NULL));
cristy3ed852e2009-09-05 21:47:34 +00005187 (void) LogMagickEvent(X11Event,GetMagickModule(),"Protocols:");
5188 (void) LogMagickEvent(X11Event,GetMagickModule(),
5189 " Window Manager: 0x%lx",windows->wm_protocols);
5190 (void) LogMagickEvent(X11Event,GetMagickModule(),
5191 " delete window: 0x%lx",windows->wm_delete_window);
5192 (void) LogMagickEvent(X11Event,GetMagickModule()," take focus: 0x%lx",
5193 windows->wm_take_focus);
5194 (void) LogMagickEvent(X11Event,GetMagickModule()," ImageMagick: 0x%lx",
5195 windows->im_protocols);
5196 (void) LogMagickEvent(X11Event,GetMagickModule(),
5197 " remote command: 0x%lx",windows->im_remote_command);
5198 (void) LogMagickEvent(X11Event,GetMagickModule(),
5199 " update widget: 0x%lx",windows->im_update_widget);
5200 (void) LogMagickEvent(X11Event,GetMagickModule(),
5201 " update colormap: 0x%lx",windows->im_update_colormap);
5202 (void) LogMagickEvent(X11Event,GetMagickModule(),
5203 " former image: 0x%lx",windows->im_former_image);
5204 (void) LogMagickEvent(X11Event,GetMagickModule()," next image: 0x%lx",
5205 windows->im_next_image);
5206 (void) LogMagickEvent(X11Event,GetMagickModule(),
5207 " retain colors: 0x%lx",windows->im_retain_colors);
5208 (void) LogMagickEvent(X11Event,GetMagickModule()," exit: 0x%lx",
5209 windows->im_exit);
5210 (void) LogMagickEvent(X11Event,GetMagickModule()," Drag and Drop: 0x%lx",
5211 windows->dnd_protocols);
5212 }
5213 /*
5214 Allocate standard colormap.
5215 */
5216 windows->map_info=XAllocStandardColormap();
5217 windows->icon_map=XAllocStandardColormap();
5218 if ((windows->map_info == (XStandardColormap *) NULL) ||
5219 (windows->icon_map == (XStandardColormap *) NULL))
5220 ThrowXWindowFatalException(ResourceLimitFatalError,
5221 "MemoryAllocationFailed","...");
5222 windows->map_info->colormap=(Colormap) NULL;
5223 windows->icon_map->colormap=(Colormap) NULL;
cristyf2faecf2010-05-28 19:19:36 +00005224 windows->pixel_info->pixels=(unsigned long *) NULL;
cristy3ed852e2009-09-05 21:47:34 +00005225 windows->pixel_info->annotate_context=(GC) NULL;
5226 windows->pixel_info->highlight_context=(GC) NULL;
5227 windows->pixel_info->widget_context=(GC) NULL;
5228 windows->font_info=(XFontStruct *) NULL;
5229 windows->icon_pixel->annotate_context=(GC) NULL;
cristyf2faecf2010-05-28 19:19:36 +00005230 windows->icon_pixel->pixels=(unsigned long *) NULL;
cristy3ed852e2009-09-05 21:47:34 +00005231 /*
5232 Allocate visual.
5233 */
5234 *windows->icon_resources=(*resource_info);
5235 windows->icon_resources->visual_type=(char *) "default";
5236 windows->icon_resources->colormap=SharedColormap;
5237 windows->visual_info=
5238 XBestVisualInfo(display,windows->map_info,resource_info);
5239 windows->icon_visual=
5240 XBestVisualInfo(display,windows->icon_map,windows->icon_resources);
5241 if ((windows->visual_info == (XVisualInfo *) NULL) ||
5242 (windows->icon_visual == (XVisualInfo *) NULL))
5243 ThrowXWindowFatalException(XServerFatalError,"UnableToGetVisual",
5244 resource_info->visual_type);
5245 if (IsEventLogging())
5246 {
5247 (void) LogMagickEvent(X11Event,GetMagickModule(),"Visual:");
5248 (void) LogMagickEvent(X11Event,GetMagickModule()," visual id: 0x%lx",
5249 windows->visual_info->visualid);
5250 (void) LogMagickEvent(X11Event,GetMagickModule()," class: %s",
5251 XVisualClassName(windows->visual_info->klass));
5252 (void) LogMagickEvent(X11Event,GetMagickModule()," depth: %d planes",
5253 windows->visual_info->depth);
5254 (void) LogMagickEvent(X11Event,GetMagickModule(),
5255 " size of colormap: %d entries",windows->visual_info->colormap_size);
5256 (void) LogMagickEvent(X11Event,GetMagickModule(),
5257 " red, green, blue masks: 0x%lx 0x%lx 0x%lx",
5258 windows->visual_info->red_mask,windows->visual_info->green_mask,
5259 windows->visual_info->blue_mask);
5260 (void) LogMagickEvent(X11Event,GetMagickModule(),
5261 " significant bits in color: %d bits",
5262 windows->visual_info->bits_per_rgb);
5263 }
5264 /*
5265 Allocate class and manager hints.
5266 */
5267 windows->class_hints=XAllocClassHint();
5268 windows->manager_hints=XAllocWMHints();
5269 if ((windows->class_hints == (XClassHint *) NULL) ||
5270 (windows->manager_hints == (XWMHints *) NULL))
5271 ThrowXWindowFatalException(ResourceLimitFatalError,
5272 "MemoryAllocationFailed","...");
5273 /*
5274 Determine group leader if we have one.
5275 */
5276 root_window=XRootWindow(display,windows->visual_info->screen);
5277 windows->group_leader.id=(Window) NULL;
5278 if (resource_info->window_group != (char *) NULL)
5279 {
5280 if (isdigit((unsigned char) *resource_info->window_group) != 0)
5281 windows->group_leader.id=XWindowByID(display,root_window,(Window)
5282 strtol((char *) resource_info->window_group,(char **) NULL,0));
5283 if (windows->group_leader.id == (Window) NULL)
5284 windows->group_leader.id=
5285 XWindowByName(display,root_window,resource_info->window_group);
5286 }
5287 return(windows);
5288}
5289
5290/*
5291%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5292% %
5293% %
5294% %
5295% X M a k e C u r s o r %
5296% %
5297% %
5298% %
5299%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5300%
5301% XMakeCursor() creates a crosshairs X11 cursor.
5302%
5303% The format of the XMakeCursor method is:
5304%
5305% Cursor XMakeCursor(Display *display,Window window,Colormap colormap,
5306% char *background_color,char *foreground_color)
5307%
5308% A description of each parameter follows:
5309%
5310% o display: Specifies a connection to an X server; returned from
5311% XOpenDisplay.
5312%
5313% o window: Specifies the ID of the window for which the cursor is
5314% assigned.
5315%
5316% o colormap: Specifies the ID of the colormap from which the background
5317% and foreground color will be retrieved.
5318%
5319% o background_color: Specifies the color to use for the cursor background.
5320%
5321% o foreground_color: Specifies the color to use for the cursor foreground.
5322%
5323*/
cristybcbda3f2011-09-03 13:01:22 +00005324MagickPrivate Cursor XMakeCursor(Display *display,Window window,
cristy3ed852e2009-09-05 21:47:34 +00005325 Colormap colormap,char *background_color,char *foreground_color)
5326{
5327#define scope_height 17
5328#define scope_x_hot 8
5329#define scope_y_hot 8
5330#define scope_width 17
5331
5332 static const unsigned char
5333 scope_bits[] =
5334 {
5335 0x80, 0x03, 0x00, 0x80, 0x02, 0x00, 0x80, 0x02, 0x00, 0x80, 0x02,
5336 0x00, 0x80, 0x02, 0x00, 0x80, 0x02, 0x00, 0x80, 0x02, 0x00, 0x7f,
5337 0xfc, 0x01, 0x01, 0x00, 0x01, 0x7f, 0xfc, 0x01, 0x80, 0x02, 0x00,
5338 0x80, 0x02, 0x00, 0x80, 0x02, 0x00, 0x80, 0x02, 0x00, 0x80, 0x02,
5339 0x00, 0x80, 0x02, 0x00, 0x80, 0x03, 0x00
5340 },
5341 scope_mask_bits[] =
5342 {
5343 0xc0, 0x07, 0x00, 0xc0, 0x07, 0x00, 0xc0, 0x06, 0x00, 0xc0, 0x06,
5344 0x00, 0xc0, 0x06, 0x00, 0xc0, 0x06, 0x00, 0xff, 0xfe, 0x01, 0x7f,
5345 0xfc, 0x01, 0x03, 0x80, 0x01, 0x7f, 0xfc, 0x01, 0xff, 0xfe, 0x01,
5346 0xc0, 0x06, 0x00, 0xc0, 0x06, 0x00, 0xc0, 0x06, 0x00, 0xc0, 0x06,
5347 0x00, 0xc0, 0x07, 0x00, 0xc0, 0x07, 0x00
5348 };
5349
5350 Cursor
5351 cursor;
5352
5353 Pixmap
5354 mask,
5355 source;
5356
5357 XColor
5358 background,
5359 foreground;
5360
5361 assert(display != (Display *) NULL);
5362 assert(window != (Window) NULL);
5363 assert(colormap != (Colormap) NULL);
5364 assert(background_color != (char *) NULL);
5365 assert(foreground_color != (char *) NULL);
5366 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",background_color);
5367 source=XCreateBitmapFromData(display,window,(char *) scope_bits,scope_width,
5368 scope_height);
5369 mask=XCreateBitmapFromData(display,window,(char *) scope_mask_bits,
5370 scope_width,scope_height);
5371 if ((source == (Pixmap) NULL) || (mask == (Pixmap) NULL))
5372 {
5373 ThrowXWindowFatalException(XServerError,"UnableToCreatePixmap","...");
5374 return((Cursor) NULL);
5375 }
5376 (void) XParseColor(display,colormap,background_color,&background);
5377 (void) XParseColor(display,colormap,foreground_color,&foreground);
5378 cursor=XCreatePixmapCursor(display,source,mask,&foreground,&background,
5379 scope_x_hot,scope_y_hot);
5380 (void) XFreePixmap(display,source);
5381 (void) XFreePixmap(display,mask);
5382 return(cursor);
5383}
5384
5385/*
5386%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5387% %
5388% %
5389% %
5390% X M a k e I m a g e %
5391% %
5392% %
5393% %
5394%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5395%
5396% XMakeImage() creates an X11 image. If the image size differs from the X11
5397% image size, the image is first resized.
5398%
5399% The format of the XMakeImage method is:
5400%
5401% MagickBooleanType XMakeImage(Display *display,
5402% const XResourceInfo *resource_info,XWindowInfo *window,Image *image,
cristy051718b2011-08-28 22:49:25 +00005403% unsigned int width,unsigned int height,ExceptionInfo *exception)
cristy3ed852e2009-09-05 21:47:34 +00005404%
5405% A description of each parameter follows:
5406%
5407% o display: Specifies a connection to an X server; returned from
5408% XOpenDisplay.
5409%
5410% o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
5411%
5412% o window: Specifies a pointer to a XWindowInfo structure.
5413%
5414% o image: the image.
5415%
5416% o width: Specifies the width in pixels of the rectangular area to
5417% display.
5418%
5419% o height: Specifies the height in pixels of the rectangular area to
5420% display.
5421%
cristy051718b2011-08-28 22:49:25 +00005422% o exception: return any errors or warnings in this structure.
5423%
cristy3ed852e2009-09-05 21:47:34 +00005424*/
cristybcbda3f2011-09-03 13:01:22 +00005425MagickPrivate MagickBooleanType XMakeImage(Display *display,
cristy3ed852e2009-09-05 21:47:34 +00005426 const XResourceInfo *resource_info,XWindowInfo *window,Image *image,
cristy051718b2011-08-28 22:49:25 +00005427 unsigned int width,unsigned int height,ExceptionInfo *exception)
cristy3ed852e2009-09-05 21:47:34 +00005428{
5429#define CheckOverflowException(length,width,height) \
5430 (((height) != 0) && ((length)/((size_t) height) != ((size_t) width)))
5431
5432 int
5433 depth,
5434 format;
5435
5436 size_t
5437 length;
5438
5439 XImage
5440 *matte_image,
5441 *ximage;
5442
5443 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
5444 assert(display != (Display *) NULL);
5445 assert(resource_info != (XResourceInfo *) NULL);
5446 assert(window != (XWindowInfo *) NULL);
5447 assert(width != 0);
5448 assert(height != 0);
5449 if ((window->width == 0) || (window->height == 0))
5450 return(MagickFalse);
5451 /*
5452 Apply user transforms to the image.
5453 */
5454 (void) XCheckDefineCursor(display,window->id,window->busy_cursor);
5455 (void) XFlush(display);
5456 depth=(int) window->depth;
5457 if (window->destroy)
5458 window->image=DestroyImage(window->image);
5459 window->image=image;
5460 window->destroy=MagickFalse;
5461 if (window->image != (Image *) NULL)
5462 {
5463 if (window->crop_geometry != (char *) NULL)
5464 {
5465 Image
5466 *crop_image;
5467
5468 RectangleInfo
5469 crop_info;
5470
5471 /*
5472 Crop image.
5473 */
5474 window->image->page.x=0;
5475 window->image->page.y=0;
5476 (void) ParsePageGeometry(window->image,window->crop_geometry,
5477 &crop_info,&image->exception);
5478 crop_image=CropImage(window->image,&crop_info,&image->exception);
5479 if (crop_image != (Image *) NULL)
5480 {
5481 if (window->image != image)
5482 window->image=DestroyImage(window->image);
5483 window->image=crop_image;
5484 window->destroy=MagickTrue;
5485 }
5486 }
5487 if ((width != (unsigned int) window->image->columns) ||
5488 (height != (unsigned int) window->image->rows))
5489 {
5490 Image
5491 *resize_image;
5492
5493 /*
5494 Resize image.
5495 */
5496 resize_image=NewImageList();
5497 if (window->pixel_info->colors != 0)
5498 resize_image=SampleImage(window->image,width,height,
5499 &image->exception);
5500 else
5501 resize_image=ThumbnailImage(window->image,width,height,
5502 &image->exception);
5503 if (resize_image != (Image *) NULL)
5504 {
5505 if (window->image != image)
5506 window->image=DestroyImage(window->image);
5507 window->image=resize_image;
5508 window->destroy=MagickTrue;
5509 }
5510 }
5511 width=(unsigned int) window->image->columns;
cristybb503372010-05-27 20:51:26 +00005512 assert((size_t) width == window->image->columns);
cristy3ed852e2009-09-05 21:47:34 +00005513 height=(unsigned int) window->image->rows;
cristybb503372010-05-27 20:51:26 +00005514 assert((size_t) height == window->image->rows);
cristy3ed852e2009-09-05 21:47:34 +00005515 }
5516 /*
5517 Create X image.
5518 */
5519 ximage=(XImage *) NULL;
5520 format=(depth == 1) ? XYBitmap : ZPixmap;
5521#if defined(MAGICKCORE_HAVE_SHARED_MEMORY)
5522 if (window->shared_memory != MagickFalse)
5523 {
5524 XShmSegmentInfo
5525 *segment_info;
5526
5527 segment_info=(XShmSegmentInfo *) window->segment_info;
5528 segment_info[1].shmid=(-1);
5529 segment_info[1].shmaddr=(char *) NULL;
5530 ximage=XShmCreateImage(display,window->visual,(unsigned int) depth,format,
5531 (char *) NULL,&segment_info[1],width,height);
5532 if (ximage == (XImage *) NULL)
5533 window->shared_memory=MagickFalse;
5534 length=(size_t) ximage->bytes_per_line*ximage->height;
5535 if (CheckOverflowException(length,ximage->bytes_per_line,ximage->height))
5536 window->shared_memory=MagickFalse;
5537 if (window->shared_memory != MagickFalse)
5538 segment_info[1].shmid=shmget(IPC_PRIVATE,length,IPC_CREAT | 0777);
5539 if (window->shared_memory != MagickFalse)
5540 segment_info[1].shmaddr=(char *) shmat(segment_info[1].shmid,0,0);
5541 if (segment_info[1].shmid < 0)
5542 window->shared_memory=MagickFalse;
5543 if (window->shared_memory != MagickFalse)
5544 (void) shmctl(segment_info[1].shmid,IPC_RMID,0);
5545 else
5546 {
5547 if (ximage != (XImage *) NULL)
5548 XDestroyImage(ximage);
5549 ximage=(XImage *) NULL;
5550 if (segment_info[1].shmaddr)
5551 {
5552 (void) shmdt(segment_info[1].shmaddr);
5553 segment_info[1].shmaddr=(char *) NULL;
5554 }
5555 if (segment_info[1].shmid >= 0)
5556 {
5557 (void) shmctl(segment_info[1].shmid,IPC_RMID,0);
5558 segment_info[1].shmid=(-1);
5559 }
5560 }
5561 }
5562#endif
5563 /*
5564 Allocate X image pixel data.
5565 */
5566#if defined(MAGICKCORE_HAVE_SHARED_MEMORY)
5567 if (window->shared_memory)
5568 {
5569 Status
5570 status;
5571
5572 XShmSegmentInfo
5573 *segment_info;
5574
5575 (void) XSync(display,MagickFalse);
5576 xerror_alert=MagickFalse;
5577 segment_info=(XShmSegmentInfo *) window->segment_info;
5578 ximage->data=segment_info[1].shmaddr;
5579 segment_info[1].readOnly=MagickFalse;
5580 status=XShmAttach(display,&segment_info[1]);
5581 if (status != False)
5582 (void) XSync(display,MagickFalse);
5583 if ((status == False) || (xerror_alert != MagickFalse))
5584 {
5585 window->shared_memory=MagickFalse;
5586 if (status != False)
5587 XShmDetach(display,&segment_info[1]);
5588 if (ximage != (XImage *) NULL)
5589 {
5590 ximage->data=NULL;
5591 XDestroyImage(ximage);
5592 ximage=(XImage *) NULL;
5593 }
5594 if (segment_info[1].shmid >= 0)
5595 {
5596 if (segment_info[1].shmaddr != NULL)
5597 (void) shmdt(segment_info[1].shmaddr);
5598 (void) shmctl(segment_info[1].shmid,IPC_RMID,0);
5599 segment_info[1].shmid=(-1);
5600 segment_info[1].shmaddr=(char *) NULL;
5601 }
5602 }
5603 }
5604#endif
5605 if (window->shared_memory == MagickFalse)
5606 ximage=XCreateImage(display,window->visual,(unsigned int) depth,format,0,
5607 (char *) NULL,width,height,XBitmapPad(display),0);
5608 if (ximage == (XImage *) NULL)
5609 {
5610 /*
5611 Unable to create X image.
5612 */
5613 (void) XCheckDefineCursor(display,window->id,window->cursor);
5614 return(MagickFalse);
5615 }
5616 length=(size_t) ximage->bytes_per_line*ximage->height;
5617 if (IsEventLogging())
5618 {
5619 (void) LogMagickEvent(X11Event,GetMagickModule(),"XImage:");
5620 (void) LogMagickEvent(X11Event,GetMagickModule()," width, height: %dx%d",
5621 ximage->width,ximage->height);
5622 (void) LogMagickEvent(X11Event,GetMagickModule()," format: %d",
5623 ximage->format);
5624 (void) LogMagickEvent(X11Event,GetMagickModule()," byte order: %d",
5625 ximage->byte_order);
5626 (void) LogMagickEvent(X11Event,GetMagickModule(),
5627 " bitmap unit, bit order, pad: %d %d %d",ximage->bitmap_unit,
5628 ximage->bitmap_bit_order,ximage->bitmap_pad);
5629 (void) LogMagickEvent(X11Event,GetMagickModule()," depth: %d",
5630 ximage->depth);
5631 (void) LogMagickEvent(X11Event,GetMagickModule()," bytes per line: %d",
5632 ximage->bytes_per_line);
5633 (void) LogMagickEvent(X11Event,GetMagickModule()," bits per pixel: %d",
5634 ximage->bits_per_pixel);
5635 (void) LogMagickEvent(X11Event,GetMagickModule(),
5636 " red, green, blue masks: 0x%lx 0x%lx 0x%lx",ximage->red_mask,
5637 ximage->green_mask,ximage->blue_mask);
5638 }
5639 if (window->shared_memory == MagickFalse)
5640 {
5641 if (ximage->format != XYBitmap)
5642 ximage->data=(char *) AcquireQuantumMemory((size_t)
5643 ximage->bytes_per_line,(size_t) ximage->height);
5644 else
5645 ximage->data=(char *) AcquireQuantumMemory((size_t)
5646 ximage->bytes_per_line*ximage->depth,(size_t) ximage->height);
5647 }
5648 if (ximage->data == (char *) NULL)
5649 {
5650 /*
5651 Unable to allocate pixel data.
5652 */
5653 XDestroyImage(ximage);
5654 ximage=(XImage *) NULL;
5655 (void) XCheckDefineCursor(display,window->id,window->cursor);
5656 return(MagickFalse);
5657 }
5658 if (window->ximage != (XImage *) NULL)
5659 {
5660 /*
5661 Destroy previous X image.
5662 */
5663 length=(size_t) window->ximage->bytes_per_line*window->ximage->height;
5664#if defined(MAGICKCORE_HAVE_SHARED_MEMORY)
5665 if (window->segment_info != (XShmSegmentInfo *) NULL)
5666 {
5667 XShmSegmentInfo
5668 *segment_info;
5669
5670 segment_info=(XShmSegmentInfo *) window->segment_info;
5671 if (segment_info[0].shmid >= 0)
5672 {
5673 (void) XSync(display,MagickFalse);
5674 (void) XShmDetach(display,&segment_info[0]);
5675 (void) XSync(display,MagickFalse);
5676 if (segment_info[0].shmaddr != (char *) NULL)
5677 (void) shmdt(segment_info[0].shmaddr);
5678 (void) shmctl(segment_info[0].shmid,IPC_RMID,0);
5679 segment_info[0].shmid=(-1);
5680 segment_info[0].shmaddr=(char *) NULL;
5681 window->ximage->data=(char *) NULL;
5682 }
5683 }
5684#endif
5685 if (window->ximage->data != (char *) NULL)
5686 free(window->ximage->data);
5687 window->ximage->data=(char *) NULL;
5688 XDestroyImage(window->ximage);
5689 window->ximage=(XImage *) NULL;
5690 }
5691#if defined(MAGICKCORE_HAVE_SHARED_MEMORY)
5692 if (window->segment_info != (XShmSegmentInfo *) NULL)
5693 {
5694 XShmSegmentInfo
5695 *segment_info;
5696
5697 segment_info=(XShmSegmentInfo *) window->segment_info;
5698 segment_info[0]=segment_info[1];
5699 }
5700#endif
5701 window->ximage=ximage;
5702 matte_image=(XImage *) NULL;
5703 if ((window->shape != MagickFalse) && (window->image != (Image *) NULL))
5704 if ((window->image->matte != MagickFalse) &&
cristyc57f6942010-11-12 01:47:39 +00005705 ((int) width <= XDisplayWidth(display,window->screen)) &&
5706 ((int) height <= XDisplayHeight(display,window->screen)))
cristy3ed852e2009-09-05 21:47:34 +00005707 {
5708 /*
5709 Create matte image.
5710 */
5711 matte_image=XCreateImage(display,window->visual,1,XYBitmap,0,
5712 (char *) NULL,width,height,XBitmapPad(display),0);
5713 if (IsEventLogging())
5714 {
5715 (void) LogMagickEvent(X11Event,GetMagickModule(),"Matte Image:");
5716 (void) LogMagickEvent(X11Event,GetMagickModule(),
5717 " width, height: %dx%d",matte_image->width,matte_image->height);
5718 }
5719 if (matte_image != (XImage *) NULL)
5720 {
5721 /*
5722 Allocate matte image pixel data.
5723 */
5724 matte_image->data=(char *) AcquireQuantumMemory((size_t)
5725 matte_image->bytes_per_line*matte_image->depth,
5726 (size_t) matte_image->height);
5727 if (matte_image->data == (char *) NULL)
5728 {
5729 XDestroyImage(matte_image);
5730 matte_image=(XImage *) NULL;
5731 }
5732 }
5733 }
5734 if (window->matte_image != (XImage *) NULL)
5735 {
5736 /*
5737 Free matte image.
5738 */
5739 if (window->matte_image->data != (char *) NULL)
5740 free(window->matte_image->data);
5741 window->matte_image->data=(char *) NULL;
5742 XDestroyImage(window->matte_image);
5743 window->matte_image=(XImage *) NULL;
5744 }
5745 window->matte_image=matte_image;
5746 if (window->matte_pixmap != (Pixmap) NULL)
5747 {
5748 (void) XFreePixmap(display,window->matte_pixmap);
5749 window->matte_pixmap=(Pixmap) NULL;
5750#if defined(MAGICKCORE_HAVE_SHAPE)
5751 if (window->shape != MagickFalse)
5752 XShapeCombineMask(display,window->id,ShapeBounding,0,0,None,ShapeSet);
5753#endif
5754 }
5755 window->stasis=MagickFalse;
5756 /*
5757 Convert pixels to X image data.
5758 */
5759 if (window->image != (Image *) NULL)
5760 {
5761 if ((ximage->byte_order == LSBFirst) || ((ximage->format == XYBitmap) &&
5762 (ximage->bitmap_bit_order == LSBFirst)))
5763 XMakeImageLSBFirst(resource_info,window,window->image,ximage,
5764 matte_image);
5765 else
5766 XMakeImageMSBFirst(resource_info,window,window->image,ximage,
5767 matte_image);
5768 }
5769 if (window->matte_image != (XImage *) NULL)
5770 {
5771 /*
5772 Create matte pixmap.
5773 */
5774 window->matte_pixmap=XCreatePixmap(display,window->id,width,height,1);
5775 if (window->matte_pixmap != (Pixmap) NULL)
5776 {
5777 GC
5778 graphics_context;
5779
5780 XGCValues
5781 context_values;
5782
5783 /*
5784 Copy matte image to matte pixmap.
5785 */
cristy4c08aed2011-07-01 19:47:50 +00005786 context_values.background=0;
5787 context_values.foreground=1;
cristy3ed852e2009-09-05 21:47:34 +00005788 graphics_context=XCreateGC(display,window->matte_pixmap,
cristybb503372010-05-27 20:51:26 +00005789 (size_t) (GCBackground | GCForeground),&context_values);
cristy3ed852e2009-09-05 21:47:34 +00005790 (void) XPutImage(display,window->matte_pixmap,graphics_context,
5791 window->matte_image,0,0,0,0,width,height);
5792 (void) XFreeGC(display,graphics_context);
5793#if defined(MAGICKCORE_HAVE_SHAPE)
5794 if (window->shape != MagickFalse)
5795 XShapeCombineMask(display,window->id,ShapeBounding,0,0,
5796 window->matte_pixmap,ShapeSet);
5797#endif
5798 }
5799 }
5800 (void) XMakePixmap(display,resource_info,window);
5801 /*
5802 Restore cursor.
5803 */
5804 (void) XCheckDefineCursor(display,window->id,window->cursor);
5805 return(MagickTrue);
5806}
5807
5808/*
5809%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5810% %
5811% %
5812% %
5813+ X M a k e I m a g e L S B F i r s t %
5814% %
5815% %
5816% %
5817%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5818%
5819% XMakeImageLSBFirst() initializes the pixel data of an X11 Image. The X image
5820% pixels are copied in least-significant bit and byte first order. The
5821% server's scanline pad is respected. Rather than using one or two general
5822% cases, many special cases are found here to help speed up the image
5823% conversion.
5824%
5825% The format of the XMakeImageLSBFirst method is:
5826%
5827% void XMakeImageLSBFirst(Display *display,XWindows *windows)
5828%
5829% A description of each parameter follows:
5830%
5831% o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
5832%
5833% o window: Specifies a pointer to a XWindowInfo structure.
5834%
5835% o image: the image.
5836%
5837% o ximage: Specifies a pointer to a XImage structure; returned from
5838% XCreateImage.
5839%
5840% o matte_image: Specifies a pointer to a XImage structure; returned from
5841% XCreateImage.
5842%
5843*/
5844static void XMakeImageLSBFirst(const XResourceInfo *resource_info,
5845 const XWindowInfo *window,Image *image,XImage *ximage,XImage *matte_image)
5846{
cristyc57f6942010-11-12 01:47:39 +00005847 CacheView
5848 *canvas_view;
5849
cristy3ed852e2009-09-05 21:47:34 +00005850 Image
5851 *canvas;
5852
5853 int
5854 y;
5855
cristy4c08aed2011-07-01 19:47:50 +00005856 register const Quantum
cristy3ed852e2009-09-05 21:47:34 +00005857 *p;
5858
5859 register int
5860 x;
5861
5862 register unsigned char
5863 *q;
5864
5865 unsigned char
5866 bit,
5867 byte;
5868
5869 unsigned int
5870 scanline_pad;
5871
cristyf2faecf2010-05-28 19:19:36 +00005872 unsigned long
cristy3ed852e2009-09-05 21:47:34 +00005873 pixel,
5874 *pixels;
5875
5876 XStandardColormap
5877 *map_info;
5878
5879 assert(resource_info != (XResourceInfo *) NULL);
5880 assert(window != (XWindowInfo *) NULL);
5881 assert(image != (Image *) NULL);
5882 if (image->debug != MagickFalse)
5883 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
5884 canvas=image;
cristybab87c32010-02-09 20:54:22 +00005885 if ((window->immutable == MagickFalse) &&
cristy54666e82010-02-03 23:34:26 +00005886 (image->storage_class == DirectClass) && (image->matte != MagickFalse))
cristy3ed852e2009-09-05 21:47:34 +00005887 {
5888 char
5889 size[MaxTextExtent];
5890
5891 Image
5892 *pattern;
5893
5894 ImageInfo
5895 *image_info;
5896
5897 image_info=AcquireImageInfo();
5898 (void) CopyMagickString(image_info->filename,
5899 resource_info->image_info->texture != (char *) NULL ?
5900 resource_info->image_info->texture : "pattern:checkerboard",
5901 MaxTextExtent);
cristyb51dff52011-05-19 16:55:47 +00005902 (void) FormatLocaleString(size,MaxTextExtent,"%.20gx%.20g",(double)
cristye8c25f92010-06-03 00:53:06 +00005903 image->columns,(double) image->rows);
cristy3ed852e2009-09-05 21:47:34 +00005904 image_info->size=ConstantString(size);
5905 pattern=ReadImage(image_info,&image->exception);
5906 image_info=DestroyImageInfo(image_info);
5907 if (pattern != (Image *) NULL)
5908 {
5909 canvas=CloneImage(image,0,0,MagickTrue,&image->exception);
5910 if (canvas != (Image *) NULL)
5911 (void) CompositeImage(canvas,DstOverCompositeOp,pattern,0,0);
5912 pattern=DestroyImage(pattern);
5913 }
5914 }
5915 scanline_pad=(unsigned int) (ximage->bytes_per_line-((ximage->width*
5916 ximage->bits_per_pixel) >> 3));
5917 map_info=window->map_info;
5918 pixels=window->pixel_info->pixels;
5919 q=(unsigned char *) ximage->data;
5920 x=0;
cristyc57f6942010-11-12 01:47:39 +00005921 canvas_view=AcquireCacheView(canvas);
cristy3ed852e2009-09-05 21:47:34 +00005922 if (ximage->format == XYBitmap)
5923 {
5924 register unsigned short
5925 polarity;
5926
5927 unsigned char
5928 background,
5929 foreground;
5930
5931 /*
5932 Convert canvas to big-endian bitmap.
5933 */
5934 background=(unsigned char)
5935 (XPixelIntensity(&window->pixel_info->foreground_color) <
5936 XPixelIntensity(&window->pixel_info->background_color) ? 0x80 : 0x00);
5937 foreground=(unsigned char)
5938 (XPixelIntensity(&window->pixel_info->background_color) <
5939 XPixelIntensity(&window->pixel_info->foreground_color) ? 0x80 : 0x00);
cristy4c08aed2011-07-01 19:47:50 +00005940 polarity=(unsigned short) ((GetPixelPacketIntensity(
cristy3ed852e2009-09-05 21:47:34 +00005941 &canvas->colormap[0])) < ((Quantum) QuantumRange/2) ? 1 : 0);
5942 if (canvas->colors == 2)
cristy4c08aed2011-07-01 19:47:50 +00005943 polarity=GetPixelPacketIntensity(&canvas->colormap[0]) <
5944 GetPixelPacketIntensity(&canvas->colormap[1]);
cristy3ed852e2009-09-05 21:47:34 +00005945 for (y=0; y < (int) canvas->rows; y++)
5946 {
cristyc57f6942010-11-12 01:47:39 +00005947 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,canvas->columns,1,
5948 &canvas->exception);
cristy4c08aed2011-07-01 19:47:50 +00005949 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00005950 break;
cristy3ed852e2009-09-05 21:47:34 +00005951 bit=0;
5952 byte=0;
5953 for (x=0; x < (int) canvas->columns; x++)
5954 {
5955 byte>>=1;
cristy4c08aed2011-07-01 19:47:50 +00005956 if (GetPixelIndex(canvas,p) == (Quantum) polarity)
cristy3ed852e2009-09-05 21:47:34 +00005957 byte|=foreground;
5958 else
5959 byte|=background;
5960 bit++;
5961 if (bit == 8)
5962 {
5963 *q++=byte;
5964 bit=0;
5965 byte=0;
5966 }
cristyed231572011-07-14 02:18:59 +00005967 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00005968 }
5969 if (bit != 0)
5970 *q=byte >> (8-bit);
5971 q+=scanline_pad;
5972 }
5973 }
5974 else
5975 if (window->pixel_info->colors != 0)
5976 switch (ximage->bits_per_pixel)
5977 {
5978 case 2:
5979 {
5980 register unsigned int
5981 nibble;
5982
5983 /*
5984 Convert to 2 bit color-mapped X canvas.
5985 */
5986 for (y=0; y < (int) canvas->rows; y++)
5987 {
cristyc57f6942010-11-12 01:47:39 +00005988 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
5989 canvas->columns,1,&canvas->exception);
cristy4c08aed2011-07-01 19:47:50 +00005990 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00005991 break;
cristy3ed852e2009-09-05 21:47:34 +00005992 nibble=0;
5993 for (x=0; x < (int) canvas->columns; x++)
5994 {
cristy4c08aed2011-07-01 19:47:50 +00005995 pixel=pixels[(ssize_t) GetPixelIndex(canvas,p)] & 0x0f;
cristy3ed852e2009-09-05 21:47:34 +00005996 switch (nibble)
5997 {
5998 case 0:
5999 {
6000 *q=(unsigned char) pixel;
6001 nibble++;
6002 break;
6003 }
6004 case 1:
6005 {
6006 *q|=(unsigned char) (pixel << 2);
6007 nibble++;
6008 break;
6009 }
6010 case 2:
6011 {
6012 *q|=(unsigned char) (pixel << 4);
6013 nibble++;
6014 break;
6015 }
6016 case 3:
6017 {
6018 *q|=(unsigned char) (pixel << 6);
6019 q++;
6020 nibble=0;
6021 break;
6022 }
6023 }
cristyed231572011-07-14 02:18:59 +00006024 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00006025 }
6026 q+=scanline_pad;
6027 }
6028 break;
6029 }
6030 case 4:
6031 {
6032 register unsigned int
6033 nibble;
6034
6035 /*
6036 Convert to 4 bit color-mapped X canvas.
6037 */
6038 for (y=0; y < (int) canvas->rows; y++)
6039 {
cristyc57f6942010-11-12 01:47:39 +00006040 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
6041 canvas->columns,1,&canvas->exception);
cristy4c08aed2011-07-01 19:47:50 +00006042 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00006043 break;
cristy3ed852e2009-09-05 21:47:34 +00006044 nibble=0;
6045 for (x=0; x < (int) canvas->columns; x++)
6046 {
cristy4c08aed2011-07-01 19:47:50 +00006047 pixel=pixels[(ssize_t) GetPixelIndex(canvas,p)] & 0xf;
cristy3ed852e2009-09-05 21:47:34 +00006048 switch (nibble)
6049 {
6050 case 0:
6051 {
6052 *q=(unsigned char) pixel;
6053 nibble++;
6054 break;
6055 }
6056 case 1:
6057 {
6058 *q|=(unsigned char) (pixel << 4);
6059 q++;
6060 nibble=0;
6061 break;
6062 }
6063 }
cristyed231572011-07-14 02:18:59 +00006064 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00006065 }
6066 q+=scanline_pad;
6067 }
6068 break;
6069 }
6070 case 6:
6071 case 8:
6072 {
6073 /*
6074 Convert to 8 bit color-mapped X canvas.
6075 */
6076 if (resource_info->color_recovery &&
6077 resource_info->quantize_info->dither)
6078 {
6079 XDitherImage(canvas,ximage);
6080 break;
6081 }
6082 for (y=0; y < (int) canvas->rows; y++)
6083 {
cristyc57f6942010-11-12 01:47:39 +00006084 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
6085 canvas->columns,1,&canvas->exception);
cristy4c08aed2011-07-01 19:47:50 +00006086 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00006087 break;
cristy3ed852e2009-09-05 21:47:34 +00006088 for (x=0; x < (int) canvas->columns; x++)
6089 {
cristy4c08aed2011-07-01 19:47:50 +00006090 pixel=pixels[(ssize_t) GetPixelIndex(canvas,p)];
cristy3ed852e2009-09-05 21:47:34 +00006091 *q++=(unsigned char) pixel;
cristyed231572011-07-14 02:18:59 +00006092 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00006093 }
6094 q+=scanline_pad;
6095 }
6096 break;
6097 }
6098 default:
6099 {
6100 register int
6101 k;
6102
6103 register unsigned int
6104 bytes_per_pixel;
6105
6106 unsigned char
cristybb503372010-05-27 20:51:26 +00006107 channel[sizeof(size_t)];
cristy3ed852e2009-09-05 21:47:34 +00006108
6109 /*
6110 Convert to multi-byte color-mapped X canvas.
6111 */
6112 bytes_per_pixel=(unsigned int) (ximage->bits_per_pixel >> 3);
6113 for (y=0; y < (int) canvas->rows; y++)
6114 {
cristyc57f6942010-11-12 01:47:39 +00006115 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
6116 canvas->columns,1,&canvas->exception);
cristy4c08aed2011-07-01 19:47:50 +00006117 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00006118 break;
cristy3ed852e2009-09-05 21:47:34 +00006119 for (x=0; x < (int) canvas->columns; x++)
6120 {
cristy4c08aed2011-07-01 19:47:50 +00006121 pixel=pixels[(ssize_t) GetPixelIndex(canvas,p)];
cristy3ed852e2009-09-05 21:47:34 +00006122 for (k=0; k < (int) bytes_per_pixel; k++)
6123 {
6124 channel[k]=(unsigned char) pixel;
6125 pixel>>=8;
6126 }
6127 for (k=0; k < (int) bytes_per_pixel; k++)
6128 *q++=channel[k];
cristyed231572011-07-14 02:18:59 +00006129 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00006130 }
6131 q+=scanline_pad;
6132 }
6133 break;
6134 }
6135 }
6136 else
6137 switch (ximage->bits_per_pixel)
6138 {
6139 case 2:
6140 {
6141 register unsigned int
6142 nibble;
6143
6144 /*
6145 Convert to contiguous 2 bit continuous-tone X canvas.
6146 */
6147 for (y=0; y < (int) canvas->rows; y++)
6148 {
6149 nibble=0;
cristyc57f6942010-11-12 01:47:39 +00006150 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
6151 canvas->columns,1,&canvas->exception);
cristy4c08aed2011-07-01 19:47:50 +00006152 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00006153 break;
6154 for (x=0; x < (int) canvas->columns; x++)
6155 {
cristy4c08aed2011-07-01 19:47:50 +00006156 pixel=XGammaPixel(canvas,map_info,p);
cristy3ed852e2009-09-05 21:47:34 +00006157 pixel&=0xf;
6158 switch (nibble)
6159 {
6160 case 0:
6161 {
6162 *q=(unsigned char) pixel;
6163 nibble++;
6164 break;
6165 }
6166 case 1:
6167 {
6168 *q|=(unsigned char) (pixel << 2);
6169 nibble++;
6170 break;
6171 }
6172 case 2:
6173 {
6174 *q|=(unsigned char) (pixel << 4);
6175 nibble++;
6176 break;
6177 }
6178 case 3:
6179 {
6180 *q|=(unsigned char) (pixel << 6);
6181 q++;
6182 nibble=0;
6183 break;
6184 }
6185 }
cristyed231572011-07-14 02:18:59 +00006186 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00006187 }
6188 q+=scanline_pad;
6189 }
6190 break;
6191 }
6192 case 4:
6193 {
6194 register unsigned int
6195 nibble;
6196
6197 /*
6198 Convert to contiguous 4 bit continuous-tone X canvas.
6199 */
6200 for (y=0; y < (int) canvas->rows; y++)
6201 {
cristyc57f6942010-11-12 01:47:39 +00006202 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
6203 canvas->columns,1,&canvas->exception);
cristy4c08aed2011-07-01 19:47:50 +00006204 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00006205 break;
6206 nibble=0;
6207 for (x=0; x < (int) canvas->columns; x++)
6208 {
cristy4c08aed2011-07-01 19:47:50 +00006209 pixel=XGammaPixel(canvas,map_info,p);
cristy3ed852e2009-09-05 21:47:34 +00006210 pixel&=0xf;
6211 switch (nibble)
6212 {
6213 case 0:
6214 {
6215 *q=(unsigned char) pixel;
6216 nibble++;
6217 break;
6218 }
6219 case 1:
6220 {
6221 *q|=(unsigned char) (pixel << 4);
6222 q++;
6223 nibble=0;
6224 break;
6225 }
6226 }
cristyed231572011-07-14 02:18:59 +00006227 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00006228 }
6229 q+=scanline_pad;
6230 }
6231 break;
6232 }
6233 case 6:
6234 case 8:
6235 {
6236 /*
6237 Convert to contiguous 8 bit continuous-tone X canvas.
6238 */
6239 if (resource_info->color_recovery &&
6240 resource_info->quantize_info->dither)
6241 {
6242 XDitherImage(canvas,ximage);
6243 break;
6244 }
6245 for (y=0; y < (int) canvas->rows; y++)
6246 {
cristyc57f6942010-11-12 01:47:39 +00006247 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
6248 canvas->columns,1,&canvas->exception);
cristy4c08aed2011-07-01 19:47:50 +00006249 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00006250 break;
6251 for (x=0; x < (int) canvas->columns; x++)
6252 {
cristy4c08aed2011-07-01 19:47:50 +00006253 pixel=XGammaPixel(canvas,map_info,p);
cristy3ed852e2009-09-05 21:47:34 +00006254 *q++=(unsigned char) pixel;
cristyed231572011-07-14 02:18:59 +00006255 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00006256 }
6257 q+=scanline_pad;
6258 }
6259 break;
6260 }
6261 default:
6262 {
6263 if ((ximage->bits_per_pixel == 32) && (map_info->red_max == 255) &&
6264 (map_info->green_max == 255) && (map_info->blue_max == 255) &&
6265 (map_info->red_mult == 65536L) && (map_info->green_mult == 256) &&
6266 (map_info->blue_mult == 1))
6267 {
6268 /*
6269 Convert to 32 bit continuous-tone X canvas.
6270 */
6271 for (y=0; y < (int) canvas->rows; y++)
6272 {
cristyc57f6942010-11-12 01:47:39 +00006273 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
6274 canvas->columns,1,&canvas->exception);
cristy4c08aed2011-07-01 19:47:50 +00006275 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00006276 break;
6277 if ((red_gamma != 1.0) || (green_gamma != 1.0) ||
6278 (blue_gamma != 1.0))
6279 {
6280 /*
6281 Gamma correct canvas.
6282 */
6283 for (x=(int) canvas->columns-1; x >= 0; x--)
6284 {
cristyccf844f2010-02-03 23:28:16 +00006285 *q++=ScaleQuantumToChar(XBlueGamma(
cristy4c08aed2011-07-01 19:47:50 +00006286 GetPixelBlue(canvas,p)));
cristyccf844f2010-02-03 23:28:16 +00006287 *q++=ScaleQuantumToChar(XGreenGamma(
cristy4c08aed2011-07-01 19:47:50 +00006288 GetPixelGreen(canvas,p)));
cristyccf844f2010-02-03 23:28:16 +00006289 *q++=ScaleQuantumToChar(XRedGamma(
cristy4c08aed2011-07-01 19:47:50 +00006290 GetPixelRed(canvas,p)));
cristy3ed852e2009-09-05 21:47:34 +00006291 *q++=0;
cristyed231572011-07-14 02:18:59 +00006292 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00006293 }
6294 continue;
6295 }
6296 for (x=(int) canvas->columns-1; x >= 0; x--)
6297 {
cristy4c08aed2011-07-01 19:47:50 +00006298 *q++=ScaleQuantumToChar((Quantum)
6299 GetPixelBlue(canvas,p));
6300 *q++=ScaleQuantumToChar((Quantum)
6301 GetPixelGreen(canvas,p));
6302 *q++=ScaleQuantumToChar((Quantum)
6303 GetPixelRed(canvas,p));
cristy3ed852e2009-09-05 21:47:34 +00006304 *q++=0;
cristyed231572011-07-14 02:18:59 +00006305 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00006306 }
6307 }
6308 }
6309 else
6310 if ((ximage->bits_per_pixel == 32) && (map_info->red_max == 255) &&
6311 (map_info->green_max == 255) && (map_info->blue_max == 255) &&
6312 (map_info->red_mult == 1) && (map_info->green_mult == 256) &&
6313 (map_info->blue_mult == 65536L))
6314 {
6315 /*
6316 Convert to 32 bit continuous-tone X canvas.
6317 */
6318 for (y=0; y < (int) canvas->rows; y++)
6319 {
cristyc57f6942010-11-12 01:47:39 +00006320 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
6321 canvas->columns,1,&canvas->exception);
cristy4c08aed2011-07-01 19:47:50 +00006322 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00006323 break;
6324 if ((red_gamma != 1.0) || (green_gamma != 1.0) ||
6325 (blue_gamma != 1.0))
6326 {
6327 /*
6328 Gamma correct canvas.
6329 */
6330 for (x=(int) canvas->columns-1; x >= 0; x--)
6331 {
cristyccf844f2010-02-03 23:28:16 +00006332 *q++=ScaleQuantumToChar(XRedGamma(
cristy4c08aed2011-07-01 19:47:50 +00006333 GetPixelRed(canvas,p)));
cristyccf844f2010-02-03 23:28:16 +00006334 *q++=ScaleQuantumToChar(XGreenGamma(
cristy4c08aed2011-07-01 19:47:50 +00006335 GetPixelGreen(canvas,p)));
cristyccf844f2010-02-03 23:28:16 +00006336 *q++=ScaleQuantumToChar(XBlueGamma(
cristy4c08aed2011-07-01 19:47:50 +00006337 GetPixelBlue(canvas,p)));
cristy3ed852e2009-09-05 21:47:34 +00006338 *q++=0;
cristyed231572011-07-14 02:18:59 +00006339 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00006340 }
6341 continue;
6342 }
6343 for (x=(int) canvas->columns-1; x >= 0; x--)
6344 {
cristyccf844f2010-02-03 23:28:16 +00006345 *q++=ScaleQuantumToChar((Quantum)
cristy4c08aed2011-07-01 19:47:50 +00006346 GetPixelRed(canvas,p));
cristyccf844f2010-02-03 23:28:16 +00006347 *q++=ScaleQuantumToChar((Quantum)
cristy4c08aed2011-07-01 19:47:50 +00006348 GetPixelGreen(canvas,p));
cristyccf844f2010-02-03 23:28:16 +00006349 *q++=ScaleQuantumToChar((Quantum)
cristy4c08aed2011-07-01 19:47:50 +00006350 GetPixelBlue(canvas,p));
cristy3ed852e2009-09-05 21:47:34 +00006351 *q++=0;
cristyed231572011-07-14 02:18:59 +00006352 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00006353 }
6354 }
6355 }
6356 else
6357 {
6358 register int
6359 k;
6360
6361 register unsigned int
6362 bytes_per_pixel;
6363
6364 unsigned char
cristybb503372010-05-27 20:51:26 +00006365 channel[sizeof(size_t)];
cristy3ed852e2009-09-05 21:47:34 +00006366
6367 /*
6368 Convert to multi-byte continuous-tone X canvas.
6369 */
6370 bytes_per_pixel=(unsigned int) (ximage->bits_per_pixel >> 3);
6371 for (y=0; y < (int) canvas->rows; y++)
6372 {
cristyc57f6942010-11-12 01:47:39 +00006373 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
6374 canvas->columns,1,&canvas->exception);
cristy4c08aed2011-07-01 19:47:50 +00006375 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00006376 break;
cristyc57f6942010-11-12 01:47:39 +00006377 for (x=0; x < (int) canvas->columns; x++)
cristy3ed852e2009-09-05 21:47:34 +00006378 {
cristy4c08aed2011-07-01 19:47:50 +00006379 pixel=XGammaPixel(canvas,map_info,p);
cristy3ed852e2009-09-05 21:47:34 +00006380 for (k=0; k < (int) bytes_per_pixel; k++)
6381 {
6382 channel[k]=(unsigned char) pixel;
6383 pixel>>=8;
6384 }
6385 for (k=0; k < (int) bytes_per_pixel; k++)
6386 *q++=channel[k];
cristyed231572011-07-14 02:18:59 +00006387 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00006388 }
6389 q+=scanline_pad;
6390 }
6391 }
6392 break;
6393 }
6394 }
6395 if (matte_image != (XImage *) NULL)
6396 {
6397 /*
6398 Initialize matte canvas.
6399 */
6400 scanline_pad=(unsigned int) (matte_image->bytes_per_line-
6401 ((matte_image->width*matte_image->bits_per_pixel) >> 3));
6402 q=(unsigned char *) matte_image->data;
6403 for (y=0; y < (int) canvas->rows; y++)
6404 {
cristyc57f6942010-11-12 01:47:39 +00006405 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,canvas->columns,1,
6406 &canvas->exception);
cristy4c08aed2011-07-01 19:47:50 +00006407 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00006408 break;
6409 bit=0;
6410 byte=0;
6411 for (x=(int) canvas->columns-1; x >= 0; x--)
6412 {
6413 byte>>=1;
cristy4c08aed2011-07-01 19:47:50 +00006414 if (GetPixelAlpha(canvas,p) > (QuantumRange/2))
cristy3ed852e2009-09-05 21:47:34 +00006415 byte|=0x80;
6416 bit++;
6417 if (bit == 8)
6418 {
6419 *q++=byte;
6420 bit=0;
6421 byte=0;
6422 }
cristyed231572011-07-14 02:18:59 +00006423 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00006424 }
6425 if (bit != 0)
6426 *q=byte >> (8-bit);
6427 q+=scanline_pad;
6428 }
6429 }
cristyc57f6942010-11-12 01:47:39 +00006430 canvas_view=DestroyCacheView(canvas_view);
cristy3ed852e2009-09-05 21:47:34 +00006431 if (canvas != image)
6432 canvas=DestroyImage(canvas);
6433}
6434
6435/*
6436%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
6437% %
6438% %
6439% %
6440+ X M a k e I m a g e M S B F i r s t %
6441% %
6442% %
6443% %
6444%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
6445%
6446% XMakeImageMSBFirst() initializes the pixel data of an X11 Image. The X
6447% image pixels are copied in most-significant bit and byte first order. The
6448% server's scanline pad is also respected. Rather than using one or two
6449% general cases, many special cases are found here to help speed up the image
6450% conversion.
6451%
6452% The format of the XMakeImageMSBFirst method is:
6453%
6454% XMakeImageMSBFirst(resource_info,window,image,ximage,matte_image)
6455%
6456% A description of each parameter follows:
6457%
6458% o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
6459%
6460% o window: Specifies a pointer to a XWindowInfo structure.
6461%
6462% o image: the image.
6463%
6464% o ximage: Specifies a pointer to a XImage structure; returned from
6465% XCreateImage.
6466%
6467% o matte_image: Specifies a pointer to a XImage structure; returned from
6468% XCreateImage.
6469%
cristy3ed852e2009-09-05 21:47:34 +00006470*/
6471static void XMakeImageMSBFirst(const XResourceInfo *resource_info,
6472 const XWindowInfo *window,Image *image,XImage *ximage,XImage *matte_image)
6473{
cristyc57f6942010-11-12 01:47:39 +00006474 CacheView
6475 *canvas_view;
6476
cristy3ed852e2009-09-05 21:47:34 +00006477 Image
6478 *canvas;
6479
6480 int
6481 y;
6482
6483 register int
6484 x;
6485
cristy4c08aed2011-07-01 19:47:50 +00006486 register const Quantum
cristy3ed852e2009-09-05 21:47:34 +00006487 *p;
6488
6489 register unsigned char
6490 *q;
6491
6492 unsigned char
6493 bit,
6494 byte;
6495
6496 unsigned int
6497 scanline_pad;
6498
cristyf2faecf2010-05-28 19:19:36 +00006499 unsigned long
cristy3ed852e2009-09-05 21:47:34 +00006500 pixel,
6501 *pixels;
6502
6503 XStandardColormap
6504 *map_info;
6505
6506 assert(resource_info != (XResourceInfo *) NULL);
6507 assert(window != (XWindowInfo *) NULL);
6508 assert(image != (Image *) NULL);
6509 if (image->debug != MagickFalse)
6510 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
6511 canvas=image;
cristy54666e82010-02-03 23:34:26 +00006512 if ((window->immutable != MagickFalse) &&
6513 (image->storage_class == DirectClass) && (image->matte != MagickFalse))
cristy3ed852e2009-09-05 21:47:34 +00006514 {
6515 char
6516 size[MaxTextExtent];
6517
6518 Image
6519 *pattern;
6520
6521 ImageInfo
6522 *image_info;
6523
6524 image_info=AcquireImageInfo();
6525 (void) CopyMagickString(image_info->filename,
6526 resource_info->image_info->texture != (char *) NULL ?
6527 resource_info->image_info->texture : "pattern:checkerboard",
6528 MaxTextExtent);
cristyb51dff52011-05-19 16:55:47 +00006529 (void) FormatLocaleString(size,MaxTextExtent,"%.20gx%.20g",(double)
cristye8c25f92010-06-03 00:53:06 +00006530 image->columns,(double) image->rows);
cristy3ed852e2009-09-05 21:47:34 +00006531 image_info->size=ConstantString(size);
6532 pattern=ReadImage(image_info,&image->exception);
6533 image_info=DestroyImageInfo(image_info);
6534 if (pattern != (Image *) NULL)
6535 {
6536 canvas=CloneImage(image,0,0,MagickTrue,&image->exception);
6537 if (canvas != (Image *) NULL)
6538 (void) CompositeImage(canvas,DstOverCompositeOp,pattern,0,0);
6539 pattern=DestroyImage(pattern);
6540 }
6541 }
cristy4c08aed2011-07-01 19:47:50 +00006542 scanline_pad=(unsigned int) (ximage->bytes_per_line-((ximage->width*
6543 ximage->bits_per_pixel) >> 3));
cristy3ed852e2009-09-05 21:47:34 +00006544 map_info=window->map_info;
6545 pixels=window->pixel_info->pixels;
6546 q=(unsigned char *) ximage->data;
6547 x=0;
cristyc57f6942010-11-12 01:47:39 +00006548 canvas_view=AcquireCacheView(canvas);
cristy3ed852e2009-09-05 21:47:34 +00006549 if (ximage->format == XYBitmap)
6550 {
6551 register unsigned short
6552 polarity;
6553
6554 unsigned char
6555 background,
6556 foreground;
6557
6558 /*
6559 Convert canvas to big-endian bitmap.
6560 */
6561 background=(unsigned char)
6562 (XPixelIntensity(&window->pixel_info->foreground_color) <
6563 XPixelIntensity(&window->pixel_info->background_color) ? 0x01 : 0x00);
6564 foreground=(unsigned char)
6565 (XPixelIntensity(&window->pixel_info->background_color) <
6566 XPixelIntensity(&window->pixel_info->foreground_color) ? 0x01 : 0x00);
cristy4c08aed2011-07-01 19:47:50 +00006567 polarity=(unsigned short) ((GetPixelPacketIntensity(
cristy3ed852e2009-09-05 21:47:34 +00006568 &canvas->colormap[0])) < ((Quantum) QuantumRange/2) ? 1 : 0);
6569 if (canvas->colors == 2)
cristy4c08aed2011-07-01 19:47:50 +00006570 polarity=GetPixelPacketIntensity(&canvas->colormap[0]) <
6571 GetPixelPacketIntensity(&canvas->colormap[1]);
cristy3ed852e2009-09-05 21:47:34 +00006572 for (y=0; y < (int) canvas->rows; y++)
6573 {
cristyc57f6942010-11-12 01:47:39 +00006574 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,canvas->columns,1,
6575 &canvas->exception);
cristy4c08aed2011-07-01 19:47:50 +00006576 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00006577 break;
cristy3ed852e2009-09-05 21:47:34 +00006578 bit=0;
6579 byte=0;
6580 for (x=(int) canvas->columns-1; x >= 0; x--)
6581 {
6582 byte<<=1;
cristy4c08aed2011-07-01 19:47:50 +00006583 if (GetPixelIndex(canvas,p) == (Quantum) polarity)
cristy3ed852e2009-09-05 21:47:34 +00006584 byte|=foreground;
6585 else
6586 byte|=background;
6587 bit++;
6588 if (bit == 8)
6589 {
6590 *q++=byte;
6591 bit=0;
6592 byte=0;
6593 }
cristyed231572011-07-14 02:18:59 +00006594 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00006595 }
6596 if (bit != 0)
6597 *q=byte << (8-bit);
6598 q+=scanline_pad;
6599 }
6600 }
6601 else
6602 if (window->pixel_info->colors != 0)
6603 switch (ximage->bits_per_pixel)
6604 {
6605 case 2:
6606 {
6607 register unsigned int
6608 nibble;
6609
6610 /*
6611 Convert to 2 bit color-mapped X canvas.
6612 */
6613 for (y=0; y < (int) canvas->rows; y++)
6614 {
cristyc57f6942010-11-12 01:47:39 +00006615 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
6616 canvas->columns,1,&canvas->exception);
cristy4c08aed2011-07-01 19:47:50 +00006617 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00006618 break;
cristy3ed852e2009-09-05 21:47:34 +00006619 nibble=0;
6620 for (x=0; x < (int) canvas->columns; x++)
6621 {
cristy4c08aed2011-07-01 19:47:50 +00006622 pixel=pixels[(ssize_t)
6623 GetPixelIndex(canvas,p)] & 0xf;
cristy3ed852e2009-09-05 21:47:34 +00006624 switch (nibble)
6625 {
6626 case 0:
6627 {
6628 *q=(unsigned char) (pixel << 6);
6629 nibble++;
6630 break;
6631 }
6632 case 1:
6633 {
6634 *q|=(unsigned char) (pixel << 4);
6635 nibble++;
6636 break;
6637 }
6638 case 2:
6639 {
6640 *q|=(unsigned char) (pixel << 2);
6641 nibble++;
6642 break;
6643 }
6644 case 3:
6645 {
6646 *q|=(unsigned char) pixel;
6647 q++;
6648 nibble=0;
6649 break;
6650 }
6651 }
cristyed231572011-07-14 02:18:59 +00006652 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00006653 }
6654 q+=scanline_pad;
6655 }
6656 break;
6657 }
6658 case 4:
6659 {
6660 register unsigned int
6661 nibble;
6662
6663 /*
6664 Convert to 4 bit color-mapped X canvas.
6665 */
6666 for (y=0; y < (int) canvas->rows; y++)
6667 {
cristyc57f6942010-11-12 01:47:39 +00006668 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
6669 canvas->columns,1,&canvas->exception);
cristy4c08aed2011-07-01 19:47:50 +00006670 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00006671 break;
cristy3ed852e2009-09-05 21:47:34 +00006672 nibble=0;
6673 for (x=0; x < (int) canvas->columns; x++)
6674 {
cristy4c08aed2011-07-01 19:47:50 +00006675 pixel=pixels[(ssize_t)
6676 GetPixelIndex(canvas,p)] & 0xf;
cristy3ed852e2009-09-05 21:47:34 +00006677 switch (nibble)
6678 {
6679 case 0:
6680 {
6681 *q=(unsigned char) (pixel << 4);
6682 nibble++;
6683 break;
6684 }
6685 case 1:
6686 {
6687 *q|=(unsigned char) pixel;
6688 q++;
6689 nibble=0;
6690 break;
6691 }
6692 }
cristyed231572011-07-14 02:18:59 +00006693 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00006694 }
6695 q+=scanline_pad;
6696 }
6697 break;
6698 }
6699 case 6:
6700 case 8:
6701 {
6702 /*
6703 Convert to 8 bit color-mapped X canvas.
6704 */
6705 if (resource_info->color_recovery &&
6706 resource_info->quantize_info->dither)
6707 {
6708 XDitherImage(canvas,ximage);
6709 break;
6710 }
6711 for (y=0; y < (int) canvas->rows; y++)
6712 {
cristyc57f6942010-11-12 01:47:39 +00006713 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
6714 canvas->columns,1,&canvas->exception);
cristy4c08aed2011-07-01 19:47:50 +00006715 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00006716 break;
cristy3ed852e2009-09-05 21:47:34 +00006717 for (x=0; x < (int) canvas->columns; x++)
6718 {
cristy4c08aed2011-07-01 19:47:50 +00006719 pixel=pixels[(ssize_t)
6720 GetPixelIndex(canvas,p)];
cristy3ed852e2009-09-05 21:47:34 +00006721 *q++=(unsigned char) pixel;
cristyed231572011-07-14 02:18:59 +00006722 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00006723 }
6724 q+=scanline_pad;
6725 }
6726 break;
6727 }
6728 default:
6729 {
6730 register int
6731 k;
6732
6733 register unsigned int
6734 bytes_per_pixel;
6735
6736 unsigned char
cristybb503372010-05-27 20:51:26 +00006737 channel[sizeof(size_t)];
cristy3ed852e2009-09-05 21:47:34 +00006738
6739 /*
6740 Convert to 8 bit color-mapped X canvas.
6741 */
6742 bytes_per_pixel=(unsigned int) (ximage->bits_per_pixel >> 3);
6743 for (y=0; y < (int) canvas->rows; y++)
6744 {
cristyc57f6942010-11-12 01:47:39 +00006745 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
6746 canvas->columns,1,&canvas->exception);
cristy4c08aed2011-07-01 19:47:50 +00006747 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00006748 break;
cristy3ed852e2009-09-05 21:47:34 +00006749 for (x=0; x < (int) canvas->columns; x++)
6750 {
cristy4c08aed2011-07-01 19:47:50 +00006751 pixel=pixels[(ssize_t)
6752 GetPixelIndex(canvas,p)];
cristy3ed852e2009-09-05 21:47:34 +00006753 for (k=(int) bytes_per_pixel-1; k >= 0; k--)
6754 {
6755 channel[k]=(unsigned char) pixel;
6756 pixel>>=8;
6757 }
6758 for (k=0; k < (int) bytes_per_pixel; k++)
6759 *q++=channel[k];
cristyed231572011-07-14 02:18:59 +00006760 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00006761 }
6762 q+=scanline_pad;
6763 }
6764 break;
6765 }
6766 }
6767 else
6768 switch (ximage->bits_per_pixel)
6769 {
6770 case 2:
6771 {
6772 register unsigned int
6773 nibble;
6774
6775 /*
6776 Convert to 4 bit continuous-tone X canvas.
6777 */
6778 for (y=0; y < (int) canvas->rows; y++)
6779 {
cristyc57f6942010-11-12 01:47:39 +00006780 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
6781 canvas->columns,1,&canvas->exception);
cristy4c08aed2011-07-01 19:47:50 +00006782 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00006783 break;
6784 nibble=0;
6785 for (x=(int) canvas->columns-1; x >= 0; x--)
6786 {
cristy4c08aed2011-07-01 19:47:50 +00006787 pixel=XGammaPixel(canvas,map_info,p);
cristy3ed852e2009-09-05 21:47:34 +00006788 pixel&=0xf;
6789 switch (nibble)
6790 {
6791 case 0:
6792 {
6793 *q=(unsigned char) (pixel << 6);
6794 nibble++;
6795 break;
6796 }
6797 case 1:
6798 {
6799 *q|=(unsigned char) (pixel << 4);
6800 nibble++;
6801 break;
6802 }
6803 case 2:
6804 {
6805 *q|=(unsigned char) (pixel << 2);
6806 nibble++;
6807 break;
6808 }
6809 case 3:
6810 {
6811 *q|=(unsigned char) pixel;
6812 q++;
6813 nibble=0;
6814 break;
6815 }
6816 }
cristyed231572011-07-14 02:18:59 +00006817 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00006818 }
6819 q+=scanline_pad;
6820 }
6821 break;
6822 }
6823 case 4:
6824 {
6825 register unsigned int
6826 nibble;
6827
6828 /*
6829 Convert to 4 bit continuous-tone X canvas.
6830 */
6831 for (y=0; y < (int) canvas->rows; y++)
6832 {
cristyc57f6942010-11-12 01:47:39 +00006833 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
6834 canvas->columns,1,&canvas->exception);
cristy4c08aed2011-07-01 19:47:50 +00006835 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00006836 break;
6837 nibble=0;
6838 for (x=(int) canvas->columns-1; x >= 0; x--)
6839 {
cristy4c08aed2011-07-01 19:47:50 +00006840 pixel=XGammaPixel(canvas,map_info,p);
cristy3ed852e2009-09-05 21:47:34 +00006841 pixel&=0xf;
6842 switch (nibble)
6843 {
6844 case 0:
6845 {
6846 *q=(unsigned char) (pixel << 4);
6847 nibble++;
6848 break;
6849 }
6850 case 1:
6851 {
6852 *q|=(unsigned char) pixel;
6853 q++;
6854 nibble=0;
6855 break;
6856 }
6857 }
cristyed231572011-07-14 02:18:59 +00006858 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00006859 }
6860 q+=scanline_pad;
6861 }
6862 break;
6863 }
6864 case 6:
6865 case 8:
6866 {
6867 /*
6868 Convert to 8 bit continuous-tone X canvas.
6869 */
6870 if (resource_info->color_recovery &&
6871 resource_info->quantize_info->dither)
6872 {
6873 XDitherImage(canvas,ximage);
6874 break;
6875 }
6876 for (y=0; y < (int) canvas->rows; y++)
6877 {
cristyc57f6942010-11-12 01:47:39 +00006878 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
6879 canvas->columns,1,&canvas->exception);
cristy4c08aed2011-07-01 19:47:50 +00006880 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00006881 break;
6882 for (x=(int) canvas->columns-1; x >= 0; x--)
6883 {
cristy4c08aed2011-07-01 19:47:50 +00006884 pixel=XGammaPixel(canvas,map_info,p);
cristy3ed852e2009-09-05 21:47:34 +00006885 *q++=(unsigned char) pixel;
cristyed231572011-07-14 02:18:59 +00006886 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00006887 }
6888 q+=scanline_pad;
6889 }
6890 break;
6891 }
6892 default:
6893 {
6894 if ((ximage->bits_per_pixel == 32) && (map_info->red_max == 255) &&
6895 (map_info->green_max == 255) && (map_info->blue_max == 255) &&
6896 (map_info->red_mult == 65536L) && (map_info->green_mult == 256) &&
6897 (map_info->blue_mult == 1))
6898 {
6899 /*
6900 Convert to 32 bit continuous-tone X canvas.
6901 */
6902 for (y=0; y < (int) canvas->rows; y++)
6903 {
cristyc57f6942010-11-12 01:47:39 +00006904 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
6905 canvas->columns,1,&canvas->exception);
cristy4c08aed2011-07-01 19:47:50 +00006906 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00006907 break;
6908 if ((red_gamma != 1.0) || (green_gamma != 1.0) ||
6909 (blue_gamma != 1.0))
6910 {
6911 /*
6912 Gamma correct canvas.
6913 */
6914 for (x=(int) canvas->columns-1; x >= 0; x--)
6915 {
6916 *q++=0;
cristyccf844f2010-02-03 23:28:16 +00006917 *q++=ScaleQuantumToChar(XRedGamma(
cristy4c08aed2011-07-01 19:47:50 +00006918 GetPixelRed(canvas,p)));
cristyccf844f2010-02-03 23:28:16 +00006919 *q++=ScaleQuantumToChar(XGreenGamma(
cristy4c08aed2011-07-01 19:47:50 +00006920 GetPixelGreen(canvas,p)));
cristyccf844f2010-02-03 23:28:16 +00006921 *q++=ScaleQuantumToChar(XBlueGamma(
cristy4c08aed2011-07-01 19:47:50 +00006922 GetPixelBlue(canvas,p)));
cristyed231572011-07-14 02:18:59 +00006923 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00006924 }
6925 continue;
6926 }
6927 for (x=(int) canvas->columns-1; x >= 0; x--)
6928 {
6929 *q++=0;
cristy4c08aed2011-07-01 19:47:50 +00006930 *q++=ScaleQuantumToChar((Quantum)
6931 GetPixelRed(canvas,p));
6932 *q++=ScaleQuantumToChar((Quantum)
6933 GetPixelGreen(canvas,p));
6934 *q++=ScaleQuantumToChar((Quantum)
6935 GetPixelBlue(canvas,p));
cristyed231572011-07-14 02:18:59 +00006936 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00006937 }
6938 }
6939 }
6940 else
6941 if ((ximage->bits_per_pixel == 32) && (map_info->red_max == 255) &&
6942 (map_info->green_max == 255) && (map_info->blue_max == 255) &&
6943 (map_info->red_mult == 1) && (map_info->green_mult == 256) &&
6944 (map_info->blue_mult == 65536L))
6945 {
6946 /*
6947 Convert to 32 bit continuous-tone X canvas.
6948 */
6949 for (y=0; y < (int) canvas->rows; y++)
6950 {
cristyc57f6942010-11-12 01:47:39 +00006951 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
6952 canvas->columns,1,&canvas->exception);
cristy4c08aed2011-07-01 19:47:50 +00006953 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00006954 break;
6955 if ((red_gamma != 1.0) || (green_gamma != 1.0) ||
6956 (blue_gamma != 1.0))
6957 {
6958 /*
6959 Gamma correct canvas.
6960 */
6961 for (x=(int) canvas->columns-1; x >= 0; x--)
6962 {
6963 *q++=0;
cristyccf844f2010-02-03 23:28:16 +00006964 *q++=ScaleQuantumToChar(XBlueGamma(
cristy4c08aed2011-07-01 19:47:50 +00006965 GetPixelBlue(canvas,p)));
cristyccf844f2010-02-03 23:28:16 +00006966 *q++=ScaleQuantumToChar(XGreenGamma(
cristy4c08aed2011-07-01 19:47:50 +00006967 GetPixelGreen(canvas,p)));
cristyccf844f2010-02-03 23:28:16 +00006968 *q++=ScaleQuantumToChar(XRedGamma(
cristy4c08aed2011-07-01 19:47:50 +00006969 GetPixelRed(canvas,p)));
cristyed231572011-07-14 02:18:59 +00006970 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00006971 }
6972 continue;
6973 }
6974 for (x=(int) canvas->columns-1; x >= 0; x--)
6975 {
6976 *q++=0;
cristyccf844f2010-02-03 23:28:16 +00006977 *q++=ScaleQuantumToChar((Quantum)
cristy4c08aed2011-07-01 19:47:50 +00006978 GetPixelBlue(canvas,p));
cristyccf844f2010-02-03 23:28:16 +00006979 *q++=ScaleQuantumToChar((Quantum)
cristy4c08aed2011-07-01 19:47:50 +00006980 GetPixelGreen(canvas,p));
cristyccf844f2010-02-03 23:28:16 +00006981 *q++=ScaleQuantumToChar((Quantum)
cristy4c08aed2011-07-01 19:47:50 +00006982 GetPixelRed(canvas,p));
cristyed231572011-07-14 02:18:59 +00006983 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00006984 }
6985 }
6986 }
6987 else
6988 {
6989 register int
6990 k;
6991
6992 register unsigned int
6993 bytes_per_pixel;
6994
6995 unsigned char
cristybb503372010-05-27 20:51:26 +00006996 channel[sizeof(size_t)];
cristy3ed852e2009-09-05 21:47:34 +00006997
6998 /*
6999 Convert to multi-byte continuous-tone X canvas.
7000 */
7001 bytes_per_pixel=(unsigned int) (ximage->bits_per_pixel >> 3);
7002 for (y=0; y < (int) canvas->rows; y++)
7003 {
cristyc57f6942010-11-12 01:47:39 +00007004 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
7005 canvas->columns,1,&canvas->exception);
cristy4c08aed2011-07-01 19:47:50 +00007006 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00007007 break;
7008 for (x=(int) canvas->columns-1; x >= 0; x--)
7009 {
cristy4c08aed2011-07-01 19:47:50 +00007010 pixel=XGammaPixel(canvas,map_info,p);
cristy3ed852e2009-09-05 21:47:34 +00007011 for (k=(int) bytes_per_pixel-1; k >= 0; k--)
7012 {
7013 channel[k]=(unsigned char) pixel;
7014 pixel>>=8;
7015 }
7016 for (k=0; k < (int) bytes_per_pixel; k++)
7017 *q++=channel[k];
cristyed231572011-07-14 02:18:59 +00007018 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00007019 }
7020 q+=scanline_pad;
7021 }
7022 }
7023 break;
7024 }
7025 }
7026 if (matte_image != (XImage *) NULL)
7027 {
7028 /*
7029 Initialize matte canvas.
7030 */
7031 scanline_pad=(unsigned int) (matte_image->bytes_per_line-
7032 ((matte_image->width*matte_image->bits_per_pixel) >> 3));
7033 q=(unsigned char *) matte_image->data;
7034 for (y=0; y < (int) canvas->rows; y++)
7035 {
cristyc57f6942010-11-12 01:47:39 +00007036 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,canvas->columns,1,
7037 &canvas->exception);
cristy4c08aed2011-07-01 19:47:50 +00007038 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00007039 break;
7040 bit=0;
7041 byte=0;
7042 for (x=(int) canvas->columns-1; x >= 0; x--)
7043 {
7044 byte<<=1;
cristy4c08aed2011-07-01 19:47:50 +00007045 if (GetPixelAlpha(canvas,p) > (QuantumRange/2))
cristy3ed852e2009-09-05 21:47:34 +00007046 byte|=0x01;
7047 bit++;
7048 if (bit == 8)
7049 {
7050 *q++=byte;
7051 bit=0;
7052 byte=0;
7053 }
cristyed231572011-07-14 02:18:59 +00007054 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00007055 }
7056 if (bit != 0)
7057 *q=byte << (8-bit);
7058 q+=scanline_pad;
7059 }
7060 }
cristyc57f6942010-11-12 01:47:39 +00007061 canvas_view=DestroyCacheView(canvas_view);
cristy3ed852e2009-09-05 21:47:34 +00007062 if (canvas != image)
7063 canvas=DestroyImage(canvas);
7064}
7065
7066/*
7067%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
7068% %
7069% %
7070% %
7071% X M a k e M a g n i f y I m a g e %
7072% %
7073% %
7074% %
7075%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
7076%
7077% XMakeMagnifyImage() magnifies a region of an X image and displays it.
7078%
7079% The format of the XMakeMagnifyImage method is:
7080%
7081% void XMakeMagnifyImage(display,windows)
7082%
7083% A description of each parameter follows:
7084%
7085% o display: Specifies a connection to an X server; returned from
7086% XOpenDisplay.
7087%
7088% o windows: Specifies a pointer to a XWindows structure.
7089%
7090*/
cristybcbda3f2011-09-03 13:01:22 +00007091MagickPrivate void XMakeMagnifyImage(Display *display,XWindows *windows)
cristy3ed852e2009-09-05 21:47:34 +00007092{
7093 char
7094 tuple[MaxTextExtent];
7095
7096 int
7097 y;
7098
cristy4c08aed2011-07-01 19:47:50 +00007099 PixelInfo
cristy3ed852e2009-09-05 21:47:34 +00007100 pixel;
7101
7102 register int
7103 x;
7104
cristybb503372010-05-27 20:51:26 +00007105 register ssize_t
cristy3ed852e2009-09-05 21:47:34 +00007106 i;
7107
7108 register unsigned char
7109 *p,
7110 *q;
7111
cristy9d314ff2011-03-09 01:30:28 +00007112 ssize_t
7113 n;
7114
cristy3ed852e2009-09-05 21:47:34 +00007115 static unsigned int
7116 previous_magnify = 0;
7117
7118 static XWindowInfo
7119 magnify_window;
7120
7121 unsigned int
7122 height,
7123 j,
7124 k,
7125 l,
7126 magnify,
7127 scanline_pad,
7128 width;
7129
7130 XImage
7131 *ximage;
7132
7133 /*
7134 Check boundary conditions.
7135 */
7136 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
7137 assert(display != (Display *) NULL);
7138 assert(windows != (XWindows *) NULL);
7139 magnify=1;
cristybb503372010-05-27 20:51:26 +00007140 for (n=1; n < (ssize_t) windows->magnify.data; n++)
cristy3ed852e2009-09-05 21:47:34 +00007141 magnify<<=1;
7142 while ((magnify*windows->image.ximage->width) < windows->magnify.width)
7143 magnify<<=1;
7144 while ((magnify*windows->image.ximage->height) < windows->magnify.height)
7145 magnify<<=1;
7146 while (magnify > windows->magnify.width)
7147 magnify>>=1;
7148 while (magnify > windows->magnify.height)
7149 magnify>>=1;
7150 if (magnify != previous_magnify)
7151 {
7152 Status
7153 status;
7154
7155 XTextProperty
7156 window_name;
7157
7158 /*
7159 New magnify factor: update magnify window name.
7160 */
7161 i=0;
7162 while ((1 << i) <= (int) magnify)
7163 i++;
cristyb51dff52011-05-19 16:55:47 +00007164 (void) FormatLocaleString(windows->magnify.name,MaxTextExtent,
cristye8c25f92010-06-03 00:53:06 +00007165 "Magnify %.20gX",(double) i);
cristy3ed852e2009-09-05 21:47:34 +00007166 status=XStringListToTextProperty(&windows->magnify.name,1,&window_name);
7167 if (status != False)
7168 {
7169 XSetWMName(display,windows->magnify.id,&window_name);
7170 XSetWMIconName(display,windows->magnify.id,&window_name);
7171 (void) XFree((void *) window_name.value);
7172 }
7173 }
7174 previous_magnify=magnify;
7175 ximage=windows->image.ximage;
7176 width=(unsigned int) windows->magnify.ximage->width;
7177 height=(unsigned int) windows->magnify.ximage->height;
7178 if ((windows->magnify.x < 0) ||
7179 (windows->magnify.x >= windows->image.ximage->width))
7180 windows->magnify.x=windows->image.ximage->width >> 1;
7181 x=windows->magnify.x-((width/magnify) >> 1);
7182 if (x < 0)
7183 x=0;
7184 else
7185 if (x > (int) (ximage->width-(width/magnify)))
7186 x=ximage->width-width/magnify;
7187 if ((windows->magnify.y < 0) ||
7188 (windows->magnify.y >= windows->image.ximage->height))
7189 windows->magnify.y=windows->image.ximage->height >> 1;
7190 y=windows->magnify.y-((height/magnify) >> 1);
7191 if (y < 0)
7192 y=0;
7193 else
7194 if (y > (int) (ximage->height-(height/magnify)))
7195 y=ximage->height-height/magnify;
7196 q=(unsigned char *) windows->magnify.ximage->data;
7197 scanline_pad=(unsigned int) (windows->magnify.ximage->bytes_per_line-
7198 ((width*windows->magnify.ximage->bits_per_pixel) >> 3));
7199 if (ximage->bits_per_pixel < 8)
7200 {
7201 register unsigned char
7202 background,
7203 byte,
7204 foreground,
7205 p_bit,
7206 q_bit;
7207
7208 register unsigned int
7209 plane;
7210
7211 XPixelInfo
7212 *pixel_info;
7213
7214 pixel_info=windows->magnify.pixel_info;
7215 switch (ximage->bitmap_bit_order)
7216 {
7217 case LSBFirst:
7218 {
7219 /*
7220 Magnify little-endian bitmap.
7221 */
7222 background=0x00;
7223 foreground=0x80;
7224 if (ximage->format == XYBitmap)
7225 {
7226 background=(unsigned char)
7227 (XPixelIntensity(&pixel_info->foreground_color) <
7228 XPixelIntensity(&pixel_info->background_color) ? 0x80 : 0x00);
7229 foreground=(unsigned char)
7230 (XPixelIntensity(&pixel_info->background_color) <
7231 XPixelIntensity(&pixel_info->foreground_color) ? 0x80 : 0x00);
7232 if (windows->magnify.depth > 1)
7233 Swap(background,foreground);
7234 }
cristybb503372010-05-27 20:51:26 +00007235 for (i=0; i < (ssize_t) height; i+=magnify)
cristy3ed852e2009-09-05 21:47:34 +00007236 {
7237 /*
7238 Propogate pixel magnify rows.
7239 */
7240 for (j=0; j < magnify; j++)
7241 {
7242 p=(unsigned char *) ximage->data+y*ximage->bytes_per_line+
7243 ((x*ximage->bits_per_pixel) >> 3);
7244 p_bit=(unsigned char) (x*ximage->bits_per_pixel) & 0x07;
7245 q_bit=0;
7246 byte=0;
7247 for (k=0; k < width; k+=magnify)
7248 {
7249 /*
7250 Propogate pixel magnify columns.
7251 */
7252 for (l=0; l < magnify; l++)
7253 {
7254 /*
7255 Propogate each bit plane.
7256 */
7257 for (plane=0; (int) plane < ximage->bits_per_pixel; plane++)
7258 {
7259 byte>>=1;
7260 if (*p & (0x01 << (p_bit+plane)))
7261 byte|=foreground;
7262 else
7263 byte|=background;
7264 q_bit++;
7265 if (q_bit == 8)
7266 {
7267 *q++=byte;
7268 q_bit=0;
7269 byte=0;
7270 }
7271 }
7272 }
7273 p_bit+=ximage->bits_per_pixel;
7274 if (p_bit == 8)
7275 {
7276 p++;
7277 p_bit=0;
7278 }
7279 if (q_bit != 0)
7280 *q=byte >> (8-q_bit);
7281 q+=scanline_pad;
7282 }
7283 }
7284 y++;
7285 }
7286 break;
7287 }
7288 case MSBFirst:
7289 default:
7290 {
7291 /*
7292 Magnify big-endian bitmap.
7293 */
7294 background=0x00;
7295 foreground=0x01;
7296 if (ximage->format == XYBitmap)
7297 {
7298 background=(unsigned char)
7299 (XPixelIntensity(&pixel_info->foreground_color) <
7300 XPixelIntensity(&pixel_info->background_color) ? 0x01 : 0x00);
7301 foreground=(unsigned char)
7302 (XPixelIntensity(&pixel_info->background_color) <
7303 XPixelIntensity(&pixel_info->foreground_color) ? 0x01 : 0x00);
7304 if (windows->magnify.depth > 1)
7305 Swap(background,foreground);
7306 }
cristybb503372010-05-27 20:51:26 +00007307 for (i=0; i < (ssize_t) height; i+=magnify)
cristy3ed852e2009-09-05 21:47:34 +00007308 {
7309 /*
7310 Propogate pixel magnify rows.
7311 */
7312 for (j=0; j < magnify; j++)
7313 {
7314 p=(unsigned char *) ximage->data+y*ximage->bytes_per_line+
7315 ((x*ximage->bits_per_pixel) >> 3);
7316 p_bit=(unsigned char) (x*ximage->bits_per_pixel) & 0x07;
7317 q_bit=0;
7318 byte=0;
7319 for (k=0; k < width; k+=magnify)
7320 {
7321 /*
7322 Propogate pixel magnify columns.
7323 */
7324 for (l=0; l < magnify; l++)
7325 {
7326 /*
7327 Propogate each bit plane.
7328 */
7329 for (plane=0; (int) plane < ximage->bits_per_pixel; plane++)
7330 {
7331 byte<<=1;
7332 if (*p & (0x80 >> (p_bit+plane)))
7333 byte|=foreground;
7334 else
7335 byte|=background;
7336 q_bit++;
7337 if (q_bit == 8)
7338 {
7339 *q++=byte;
7340 q_bit=0;
7341 byte=0;
7342 }
7343 }
7344 }
7345 p_bit+=ximage->bits_per_pixel;
7346 if (p_bit == 8)
7347 {
7348 p++;
7349 p_bit=0;
7350 }
7351 if (q_bit != 0)
7352 *q=byte << (8-q_bit);
7353 q+=scanline_pad;
7354 }
7355 }
7356 y++;
7357 }
7358 break;
7359 }
7360 }
7361 }
7362 else
7363 switch (ximage->bits_per_pixel)
7364 {
7365 case 6:
7366 case 8:
7367 {
7368 /*
7369 Magnify 8 bit X image.
7370 */
cristybb503372010-05-27 20:51:26 +00007371 for (i=0; i < (ssize_t) height; i+=magnify)
cristy3ed852e2009-09-05 21:47:34 +00007372 {
7373 /*
7374 Propogate pixel magnify rows.
7375 */
7376 for (j=0; j < magnify; j++)
7377 {
7378 p=(unsigned char *) ximage->data+y*ximage->bytes_per_line+
7379 ((x*ximage->bits_per_pixel) >> 3);
7380 for (k=0; k < width; k+=magnify)
7381 {
7382 /*
7383 Propogate pixel magnify columns.
7384 */
7385 for (l=0; l < magnify; l++)
7386 *q++=(*p);
7387 p++;
7388 }
7389 q+=scanline_pad;
7390 }
7391 y++;
7392 }
7393 break;
7394 }
7395 default:
7396 {
7397 register unsigned int
7398 bytes_per_pixel,
7399 m;
7400
7401 /*
7402 Magnify multi-byte X image.
7403 */
7404 bytes_per_pixel=(unsigned int) ximage->bits_per_pixel >> 3;
cristybb503372010-05-27 20:51:26 +00007405 for (i=0; i < (ssize_t) height; i+=magnify)
cristy3ed852e2009-09-05 21:47:34 +00007406 {
7407 /*
7408 Propogate pixel magnify rows.
7409 */
7410 for (j=0; j < magnify; j++)
7411 {
7412 p=(unsigned char *) ximage->data+y*ximage->bytes_per_line+
7413 ((x*ximage->bits_per_pixel) >> 3);
7414 for (k=0; k < width; k+=magnify)
7415 {
7416 /*
7417 Propogate pixel magnify columns.
7418 */
7419 for (l=0; l < magnify; l++)
7420 for (m=0; m < bytes_per_pixel; m++)
7421 *q++=(*(p+m));
7422 p+=bytes_per_pixel;
7423 }
7424 q+=scanline_pad;
7425 }
7426 y++;
7427 }
7428 break;
7429 }
7430 }
7431 /*
7432 Copy X image to magnify pixmap.
7433 */
7434 x=windows->magnify.x-((width/magnify) >> 1);
7435 if (x < 0)
7436 x=(int) ((width >> 1)-windows->magnify.x*magnify);
7437 else
7438 if (x > (int) (ximage->width-(width/magnify)))
7439 x=(int) ((ximage->width-windows->magnify.x)*magnify-(width >> 1));
7440 else
7441 x=0;
7442 y=windows->magnify.y-((height/magnify) >> 1);
7443 if (y < 0)
7444 y=(int) ((height >> 1)-windows->magnify.y*magnify);
7445 else
7446 if (y > (int) (ximage->height-(height/magnify)))
7447 y=(int) ((ximage->height-windows->magnify.y)*magnify-(height >> 1));
7448 else
7449 y=0;
7450 if ((x != 0) || (y != 0))
7451 (void) XFillRectangle(display,windows->magnify.pixmap,
7452 windows->magnify.annotate_context,0,0,width,height);
7453 (void) XPutImage(display,windows->magnify.pixmap,
7454 windows->magnify.annotate_context,windows->magnify.ximage,0,0,x,y,width-x,
7455 height-y);
7456 if ((magnify > 1) && ((magnify <= (width >> 1)) &&
7457 (magnify <= (height >> 1))))
7458 {
7459 RectangleInfo
7460 highlight_info;
7461
7462 /*
7463 Highlight center pixel.
7464 */
cristybb503372010-05-27 20:51:26 +00007465 highlight_info.x=(ssize_t) windows->magnify.width >> 1;
7466 highlight_info.y=(ssize_t) windows->magnify.height >> 1;
cristy3ed852e2009-09-05 21:47:34 +00007467 highlight_info.width=magnify;
7468 highlight_info.height=magnify;
7469 (void) XDrawRectangle(display,windows->magnify.pixmap,
7470 windows->magnify.highlight_context,(int) highlight_info.x,
7471 (int) highlight_info.y,(unsigned int) highlight_info.width-1,
7472 (unsigned int) highlight_info.height-1);
7473 if (magnify > 2)
7474 (void) XDrawRectangle(display,windows->magnify.pixmap,
7475 windows->magnify.annotate_context,(int) highlight_info.x+1,
7476 (int) highlight_info.y+1,(unsigned int) highlight_info.width-3,
7477 (unsigned int) highlight_info.height-3);
7478 }
7479 /*
7480 Show center pixel color.
7481 */
cristyc57f6942010-11-12 01:47:39 +00007482 (void) GetOneVirtualMagickPixel(windows->image.image,(ssize_t)
7483 windows->magnify.x,(ssize_t) windows->magnify.y,&pixel,
7484 &windows->image.image->exception);
cristyb51dff52011-05-19 16:55:47 +00007485 (void) FormatLocaleString(tuple,MaxTextExtent,"%d,%d: ",
cristy3ed852e2009-09-05 21:47:34 +00007486 windows->magnify.x,windows->magnify.y);
7487 (void) ConcatenateMagickString(tuple,"(",MaxTextExtent);
cristyed231572011-07-14 02:18:59 +00007488 ConcatenateColorComponent(&pixel,RedPixelChannel,X11Compliance,tuple);
cristy3ed852e2009-09-05 21:47:34 +00007489 (void) ConcatenateMagickString(tuple,",",MaxTextExtent);
cristyed231572011-07-14 02:18:59 +00007490 ConcatenateColorComponent(&pixel,GreenPixelChannel,X11Compliance,tuple);
cristy3ed852e2009-09-05 21:47:34 +00007491 (void) ConcatenateMagickString(tuple,",",MaxTextExtent);
cristyed231572011-07-14 02:18:59 +00007492 ConcatenateColorComponent(&pixel,BluePixelChannel,X11Compliance,tuple);
cristy3ed852e2009-09-05 21:47:34 +00007493 if (pixel.colorspace == CMYKColorspace)
7494 {
7495 (void) ConcatenateMagickString(tuple,",",MaxTextExtent);
cristyed231572011-07-14 02:18:59 +00007496 ConcatenateColorComponent(&pixel,BlackPixelChannel,X11Compliance,tuple);
cristy3ed852e2009-09-05 21:47:34 +00007497 }
7498 if (pixel.matte != MagickFalse)
7499 {
7500 (void) ConcatenateMagickString(tuple,",",MaxTextExtent);
cristyed231572011-07-14 02:18:59 +00007501 ConcatenateColorComponent(&pixel,AlphaPixelChannel,X11Compliance,tuple);
cristy3ed852e2009-09-05 21:47:34 +00007502 }
7503 (void) ConcatenateMagickString(tuple,")",MaxTextExtent);
7504 height=(unsigned int) windows->magnify.font_info->ascent+
7505 windows->magnify.font_info->descent;
7506 x=windows->magnify.font_info->max_bounds.width >> 1;
7507 y=windows->magnify.font_info->ascent+(height >> 2);
7508 (void) XDrawImageString(display,windows->magnify.pixmap,
7509 windows->magnify.annotate_context,x,y,tuple,(int) strlen(tuple));
7510 GetColorTuple(&pixel,MagickTrue,tuple);
7511 y+=height;
7512 (void) XDrawImageString(display,windows->magnify.pixmap,
7513 windows->magnify.annotate_context,x,y,tuple,(int) strlen(tuple));
7514 (void) QueryMagickColorname(windows->image.image,&pixel,SVGCompliance,tuple,
7515 &windows->image.image->exception);
7516 y+=height;
7517 (void) XDrawImageString(display,windows->magnify.pixmap,
7518 windows->magnify.annotate_context,x,y,tuple,(int) strlen(tuple));
7519 /*
7520 Refresh magnify window.
7521 */
7522 magnify_window=windows->magnify;
7523 magnify_window.x=0;
7524 magnify_window.y=0;
7525 XRefreshWindow(display,&magnify_window,(XEvent *) NULL);
7526}
7527
7528/*
7529%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
7530% %
7531% %
7532% %
7533% X M a k e P i x m a p %
7534% %
7535% %
7536% %
7537%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
7538%
7539% XMakePixmap() creates an X11 pixmap.
7540%
7541% The format of the XMakePixmap method is:
7542%
7543% void XMakeStandardColormap(Display *display,XVisualInfo *visual_info,
7544% XResourceInfo *resource_info,Image *image,XStandardColormap *map_info,
7545% XPixelInfo *pixel)
7546%
7547% A description of each parameter follows:
7548%
7549% o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
7550%
7551% o display: Specifies a connection to an X server; returned from
7552% XOpenDisplay.
7553%
7554% o window: Specifies a pointer to a XWindowInfo structure.
7555%
cristy3ed852e2009-09-05 21:47:34 +00007556*/
7557static MagickBooleanType XMakePixmap(Display *display,
7558 const XResourceInfo *resource_info,XWindowInfo *window)
7559{
7560 unsigned int
7561 height,
7562 width;
7563
7564 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
7565 assert(display != (Display *) NULL);
7566 assert(resource_info != (XResourceInfo *) NULL);
7567 assert(window != (XWindowInfo *) NULL);
7568 if (window->pixmap != (Pixmap) NULL)
7569 {
7570 /*
7571 Destroy previous X pixmap.
7572 */
7573 (void) XFreePixmap(display,window->pixmap);
7574 window->pixmap=(Pixmap) NULL;
7575 }
7576 if (window->use_pixmap == MagickFalse)
7577 return(MagickFalse);
7578 if (window->ximage == (XImage *) NULL)
7579 return(MagickFalse);
7580 /*
7581 Display busy cursor.
7582 */
7583 (void) XCheckDefineCursor(display,window->id,window->busy_cursor);
7584 (void) XFlush(display);
7585 /*
7586 Create pixmap.
7587 */
7588 width=(unsigned int) window->ximage->width;
7589 height=(unsigned int) window->ximage->height;
7590 window->pixmap=XCreatePixmap(display,window->id,width,height,window->depth);
7591 if (window->pixmap == (Pixmap) NULL)
7592 {
7593 /*
7594 Unable to allocate pixmap.
7595 */
7596 (void) XCheckDefineCursor(display,window->id,window->cursor);
7597 return(MagickFalse);
7598 }
7599 /*
7600 Copy X image to pixmap.
7601 */
7602#if defined(MAGICKCORE_HAVE_SHARED_MEMORY)
7603 if (window->shared_memory)
7604 (void) XShmPutImage(display,window->pixmap,window->annotate_context,
7605 window->ximage,0,0,0,0,width,height,MagickTrue);
7606#endif
7607 if (window->shared_memory == MagickFalse)
7608 (void) XPutImage(display,window->pixmap,window->annotate_context,
7609 window->ximage,0,0,0,0,width,height);
7610 if (IsEventLogging())
7611 {
7612 (void) LogMagickEvent(X11Event,GetMagickModule(),"Pixmap:");
7613 (void) LogMagickEvent(X11Event,GetMagickModule()," width, height: %ux%u",
7614 width,height);
7615 }
7616 /*
7617 Restore cursor.
7618 */
7619 (void) XCheckDefineCursor(display,window->id,window->cursor);
7620 return(MagickTrue);
7621}
7622
7623/*
7624%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
7625% %
7626% %
7627% %
7628% X M a k e S t a n d a r d C o l o r m a p %
7629% %
7630% %
7631% %
7632%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
7633%
7634% XMakeStandardColormap() creates an X11 Standard Colormap.
7635%
7636% The format of the XMakeStandardColormap method is:
7637%
7638% XMakeStandardColormap(display,visual_info,resource_info,image,
7639% map_info,pixel)
7640%
7641% A description of each parameter follows:
7642%
7643% o display: Specifies a connection to an X server; returned from
7644% XOpenDisplay.
7645%
7646% o visual_info: Specifies a pointer to a X11 XVisualInfo structure;
7647% returned from XGetVisualInfo.
7648%
7649% o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
7650%
7651% o image: the image.
7652%
7653% o map_info: If a Standard Colormap type is specified, this structure is
7654% initialized with info from the Standard Colormap.
7655%
7656% o pixel: Specifies a pointer to a XPixelInfo structure.
7657%
cristy3ed852e2009-09-05 21:47:34 +00007658*/
7659
7660#if defined(__cplusplus) || defined(c_plusplus)
7661extern "C" {
7662#endif
7663
7664static inline MagickRealType DiversityPixelIntensity(
7665 const DiversityPacket *pixel)
7666{
7667 MagickRealType
7668 intensity;
7669
7670 intensity=0.299*pixel->red+0.587*pixel->green+0.114*pixel->blue;
7671 return(intensity);
7672}
7673
7674static int IntensityCompare(const void *x,const void *y)
7675{
7676 DiversityPacket
7677 *color_1,
7678 *color_2;
7679
7680 int
7681 diversity;
7682
7683 color_1=(DiversityPacket *) x;
7684 color_2=(DiversityPacket *) y;
7685 diversity=(int) (DiversityPixelIntensity(color_2)-
7686 DiversityPixelIntensity(color_1));
7687 return(diversity);
7688}
7689
7690static int PopularityCompare(const void *x,const void *y)
7691{
7692 DiversityPacket
7693 *color_1,
7694 *color_2;
7695
7696 color_1=(DiversityPacket *) x;
7697 color_2=(DiversityPacket *) y;
7698 return((int) color_2->count-(int) color_1->count);
7699}
7700
7701#if defined(__cplusplus) || defined(c_plusplus)
7702}
7703#endif
7704
cristybb503372010-05-27 20:51:26 +00007705static inline Quantum ScaleXToQuantum(const size_t x,
7706 const size_t scale)
cristy3ed852e2009-09-05 21:47:34 +00007707{
7708 return((Quantum) (((MagickRealType) QuantumRange*x)/scale+0.5));
7709}
7710
cristybcbda3f2011-09-03 13:01:22 +00007711MagickPrivate void XMakeStandardColormap(Display *display,
cristy3ed852e2009-09-05 21:47:34 +00007712 XVisualInfo *visual_info,XResourceInfo *resource_info,Image *image,
7713 XStandardColormap *map_info,XPixelInfo *pixel)
7714{
7715 Colormap
7716 colormap;
7717
7718 ExceptionInfo
7719 *exception;
7720
cristybb503372010-05-27 20:51:26 +00007721 register ssize_t
cristy3ed852e2009-09-05 21:47:34 +00007722 i;
7723
7724 Status
7725 status;
7726
cristybb503372010-05-27 20:51:26 +00007727 size_t
cristy3ed852e2009-09-05 21:47:34 +00007728 number_colors,
7729 retain_colors;
7730
7731 unsigned short
7732 gray_value;
7733
7734 XColor
7735 color,
7736 *colors,
7737 *p;
7738
7739 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
7740 assert(display != (Display *) NULL);
7741 assert(visual_info != (XVisualInfo *) NULL);
7742 assert(map_info != (XStandardColormap *) NULL);
7743 assert(resource_info != (XResourceInfo *) NULL);
7744 assert(pixel != (XPixelInfo *) NULL);
7745 exception=(&image->exception);
7746 if (resource_info->map_type != (char *) NULL)
7747 {
7748 /*
7749 Standard Colormap is already defined (i.e. xstdcmap).
7750 */
cristy4c08aed2011-07-01 19:47:50 +00007751 XGetPixelInfo(display,visual_info,map_info,resource_info,image,
cristy3ed852e2009-09-05 21:47:34 +00007752 pixel);
7753 number_colors=(unsigned int) (map_info->base_pixel+
7754 (map_info->red_max+1)*(map_info->green_max+1)*(map_info->blue_max+1));
7755 if ((map_info->red_max*map_info->green_max*map_info->blue_max) != 0)
7756 if ((image->matte == MagickFalse) &&
7757 (resource_info->color_recovery == MagickFalse) &&
7758 resource_info->quantize_info->dither &&
7759 (number_colors < MaxColormapSize))
7760 {
7761 Image
7762 *affinity_image;
7763
cristy4c08aed2011-07-01 19:47:50 +00007764 register Quantum
cristyc47d1f82009-11-26 01:44:43 +00007765 *restrict q;
cristy3ed852e2009-09-05 21:47:34 +00007766
7767 /*
7768 Improve image appearance with error diffusion.
7769 */
7770 affinity_image=AcquireImage((ImageInfo *) NULL);
7771 if (affinity_image == (Image *) NULL)
7772 ThrowXWindowFatalException(ResourceLimitFatalError,
7773 "UnableToDitherImage",image->filename);
7774 affinity_image->columns=number_colors;
7775 affinity_image->rows=1;
7776 /*
7777 Initialize colormap image.
7778 */
7779 q=QueueAuthenticPixels(affinity_image,0,0,affinity_image->columns,
7780 1,exception);
cristy4c08aed2011-07-01 19:47:50 +00007781 if (q != (Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00007782 {
cristybb503372010-05-27 20:51:26 +00007783 for (i=0; i < (ssize_t) number_colors; i++)
cristy3ed852e2009-09-05 21:47:34 +00007784 {
cristy4c08aed2011-07-01 19:47:50 +00007785 SetPixelRed(affinity_image,0,q);
cristy3ed852e2009-09-05 21:47:34 +00007786 if (map_info->red_max != 0)
cristy4c08aed2011-07-01 19:47:50 +00007787 SetPixelRed(affinity_image,
7788 ScaleXToQuantum((size_t) (i/map_info->red_mult),
7789 map_info->red_max),q);
7790 SetPixelGreen(affinity_image,0,q);
cristy3ed852e2009-09-05 21:47:34 +00007791 if (map_info->green_max != 0)
cristy4c08aed2011-07-01 19:47:50 +00007792 SetPixelGreen(affinity_image,
7793 ScaleXToQuantum((size_t) ((i/map_info->green_mult) %
7794 (map_info->green_max+1)),map_info->green_max),q);
7795 SetPixelBlue(affinity_image,0,q);
cristy3ed852e2009-09-05 21:47:34 +00007796 if (map_info->blue_max != 0)
cristy4c08aed2011-07-01 19:47:50 +00007797 SetPixelBlue(affinity_image,
7798 ScaleXToQuantum((size_t) (i % map_info->green_mult),
7799 map_info->blue_max),q);
7800 SetPixelAlpha(affinity_image,
7801 TransparentAlpha,q);
cristyed231572011-07-14 02:18:59 +00007802 q+=GetPixelChannels(affinity_image);
cristy3ed852e2009-09-05 21:47:34 +00007803 }
7804 (void) SyncAuthenticPixels(affinity_image,exception);
7805 (void) RemapImage(resource_info->quantize_info,image,
7806 affinity_image);
7807 }
cristy4c08aed2011-07-01 19:47:50 +00007808 XGetPixelInfo(display,visual_info,map_info,resource_info,image,
cristy3ed852e2009-09-05 21:47:34 +00007809 pixel);
cristy574cc262011-08-05 01:23:58 +00007810 (void) SetImageStorageClass(image,DirectClass,exception);
cristy3ed852e2009-09-05 21:47:34 +00007811 affinity_image=DestroyImage(affinity_image);
7812 }
7813 if (IsEventLogging())
7814 {
7815 (void) LogMagickEvent(X11Event,GetMagickModule(),
7816 "Standard Colormap:");
7817 (void) LogMagickEvent(X11Event,GetMagickModule(),
7818 " colormap id: 0x%lx",map_info->colormap);
7819 (void) LogMagickEvent(X11Event,GetMagickModule(),
7820 " red, green, blue max: %lu %lu %lu",map_info->red_max,
7821 map_info->green_max,map_info->blue_max);
7822 (void) LogMagickEvent(X11Event,GetMagickModule(),
7823 " red, green, blue mult: %lu %lu %lu",map_info->red_mult,
7824 map_info->green_mult,map_info->blue_mult);
7825 }
7826 return;
7827 }
7828 if ((visual_info->klass != DirectColor) &&
7829 (visual_info->klass != TrueColor))
7830 if ((image->storage_class == DirectClass) ||
7831 ((int) image->colors > visual_info->colormap_size))
7832 {
7833 QuantizeInfo
7834 quantize_info;
7835
7836 /*
7837 Image has more colors than the visual supports.
7838 */
7839 quantize_info=(*resource_info->quantize_info);
cristybb503372010-05-27 20:51:26 +00007840 quantize_info.number_colors=(size_t) visual_info->colormap_size;
cristy3ed852e2009-09-05 21:47:34 +00007841 (void) QuantizeImage(&quantize_info,image);
7842 }
7843 /*
7844 Free previous and create new colormap.
7845 */
7846 (void) XFreeStandardColormap(display,visual_info,map_info,pixel);
7847 colormap=XDefaultColormap(display,visual_info->screen);
7848 if (visual_info->visual != XDefaultVisual(display,visual_info->screen))
7849 colormap=XCreateColormap(display,XRootWindow(display,visual_info->screen),
7850 visual_info->visual,visual_info->klass == DirectColor ?
7851 AllocAll : AllocNone);
7852 if (colormap == (Colormap) NULL)
7853 ThrowXWindowFatalException(ResourceLimitFatalError,"UnableToCreateColormap",
7854 image->filename);
7855 /*
7856 Initialize the map and pixel info structures.
7857 */
7858 XGetMapInfo(visual_info,colormap,map_info);
cristy4c08aed2011-07-01 19:47:50 +00007859 XGetPixelInfo(display,visual_info,map_info,resource_info,image,pixel);
cristy3ed852e2009-09-05 21:47:34 +00007860 /*
7861 Allocating colors in server colormap is based on visual class.
7862 */
7863 switch (visual_info->klass)
7864 {
7865 case StaticGray:
7866 case StaticColor:
7867 {
7868 /*
7869 Define Standard Colormap for StaticGray or StaticColor visual.
7870 */
7871 number_colors=image->colors;
7872 colors=(XColor *) AcquireQuantumMemory((size_t)
7873 visual_info->colormap_size,sizeof(*colors));
7874 if (colors == (XColor *) NULL)
7875 ThrowXWindowFatalException(ResourceLimitFatalError,
7876 "UnableToCreateColormap",image->filename);
7877 p=colors;
7878 color.flags=(char) (DoRed | DoGreen | DoBlue);
cristybb503372010-05-27 20:51:26 +00007879 for (i=0; i < (ssize_t) image->colors; i++)
cristy3ed852e2009-09-05 21:47:34 +00007880 {
7881 color.red=ScaleQuantumToShort(XRedGamma(image->colormap[i].red));
7882 color.green=ScaleQuantumToShort(XGreenGamma(image->colormap[i].green));
7883 color.blue=ScaleQuantumToShort(XBlueGamma(image->colormap[i].blue));
7884 if (visual_info->klass != StaticColor)
7885 {
7886 gray_value=(unsigned short) XPixelIntensity(&color);
7887 color.red=gray_value;
7888 color.green=gray_value;
7889 color.blue=gray_value;
7890 }
7891 status=XAllocColor(display,colormap,&color);
7892 if (status == False)
7893 {
7894 colormap=XCopyColormapAndFree(display,colormap);
7895 (void) XAllocColor(display,colormap,&color);
7896 }
7897 pixel->pixels[i]=color.pixel;
7898 *p++=color;
7899 }
7900 break;
7901 }
7902 case GrayScale:
7903 case PseudoColor:
7904 {
7905 unsigned int
7906 colormap_type;
7907
7908 /*
7909 Define Standard Colormap for GrayScale or PseudoColor visual.
7910 */
7911 number_colors=image->colors;
7912 colors=(XColor *) AcquireQuantumMemory((size_t)
7913 visual_info->colormap_size,sizeof(*colors));
7914 if (colors == (XColor *) NULL)
7915 ThrowXWindowFatalException(ResourceLimitFatalError,
7916 "UnableToCreateColormap",image->filename);
7917 /*
7918 Preallocate our GUI colors.
7919 */
7920 (void) XAllocColor(display,colormap,&pixel->foreground_color);
7921 (void) XAllocColor(display,colormap,&pixel->background_color);
7922 (void) XAllocColor(display,colormap,&pixel->border_color);
7923 (void) XAllocColor(display,colormap,&pixel->matte_color);
7924 (void) XAllocColor(display,colormap,&pixel->highlight_color);
7925 (void) XAllocColor(display,colormap,&pixel->shadow_color);
7926 (void) XAllocColor(display,colormap,&pixel->depth_color);
7927 (void) XAllocColor(display,colormap,&pixel->trough_color);
7928 for (i=0; i < MaxNumberPens; i++)
7929 (void) XAllocColor(display,colormap,&pixel->pen_colors[i]);
7930 /*
7931 Determine if image colors will "fit" into X server colormap.
7932 */
7933 colormap_type=resource_info->colormap;
cristyf2faecf2010-05-28 19:19:36 +00007934 status=XAllocColorCells(display,colormap,MagickFalse,(unsigned long *)
cristy3ed852e2009-09-05 21:47:34 +00007935 NULL,0,pixel->pixels,(unsigned int) image->colors);
7936 if (status != False)
7937 colormap_type=PrivateColormap;
7938 if (colormap_type == SharedColormap)
7939 {
cristyc57f6942010-11-12 01:47:39 +00007940 CacheView
7941 *image_view;
7942
cristy3ed852e2009-09-05 21:47:34 +00007943 DiversityPacket
7944 *diversity;
7945
7946 int
7947 y;
7948
7949 register int
7950 x;
7951
7952 unsigned short
7953 index;
7954
7955 XColor
7956 *server_colors;
7957
7958 /*
7959 Define Standard colormap for shared GrayScale or PseudoColor visual.
7960 */
7961 diversity=(DiversityPacket *) AcquireQuantumMemory(image->colors,
7962 sizeof(*diversity));
7963 if (diversity == (DiversityPacket *) NULL)
7964 ThrowXWindowFatalException(ResourceLimitFatalError,
7965 "UnableToCreateColormap",image->filename);
cristybb503372010-05-27 20:51:26 +00007966 for (i=0; i < (ssize_t) image->colors; i++)
cristy3ed852e2009-09-05 21:47:34 +00007967 {
7968 diversity[i].red=image->colormap[i].red;
7969 diversity[i].green=image->colormap[i].green;
7970 diversity[i].blue=image->colormap[i].blue;
7971 diversity[i].index=(unsigned short) i;
7972 diversity[i].count=0;
7973 }
cristyc57f6942010-11-12 01:47:39 +00007974 image_view=AcquireCacheView(image);
cristy3ed852e2009-09-05 21:47:34 +00007975 for (y=0; y < (int) image->rows; y++)
7976 {
cristyc57f6942010-11-12 01:47:39 +00007977 register int
cristy3ed852e2009-09-05 21:47:34 +00007978 x;
7979
cristy4c08aed2011-07-01 19:47:50 +00007980 register const Quantum
cristyc57f6942010-11-12 01:47:39 +00007981 *restrict p;
cristy3ed852e2009-09-05 21:47:34 +00007982
cristyc57f6942010-11-12 01:47:39 +00007983 p=GetCacheViewAuthenticPixels(image_view,0,(ssize_t) y,
7984 image->columns,1,exception);
cristy4c08aed2011-07-01 19:47:50 +00007985 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00007986 break;
cristyc57f6942010-11-12 01:47:39 +00007987 for (x=(int) image->columns-1; x >= 0; x--)
cristy4c08aed2011-07-01 19:47:50 +00007988 {
7989 diversity[(ssize_t) GetPixelIndex(image,p)].count++;
cristyed231572011-07-14 02:18:59 +00007990 p+=GetPixelChannels(image);
cristy4c08aed2011-07-01 19:47:50 +00007991 }
cristy3ed852e2009-09-05 21:47:34 +00007992 }
cristyc57f6942010-11-12 01:47:39 +00007993 image_view=DestroyCacheView(image_view);
cristy3ed852e2009-09-05 21:47:34 +00007994 /*
7995 Sort colors by decreasing intensity.
7996 */
7997 qsort((void *) diversity,image->colors,sizeof(*diversity),
7998 IntensityCompare);
cristybb503372010-05-27 20:51:26 +00007999 for (i=0; i < (ssize_t) image->colors; )
cristy3ed852e2009-09-05 21:47:34 +00008000 {
8001 diversity[i].count<<=4; /* increase this colors popularity */
cristydfe2b662010-08-22 16:17:24 +00008002 i+=MagickMax((int) (image->colors >> 4),2);
cristy3ed852e2009-09-05 21:47:34 +00008003 }
8004 diversity[image->colors-1].count<<=4;
8005 qsort((void *) diversity,image->colors,sizeof(*diversity),
8006 PopularityCompare);
8007 /*
8008 Allocate colors.
8009 */
8010 p=colors;
8011 color.flags=(char) (DoRed | DoGreen | DoBlue);
cristybb503372010-05-27 20:51:26 +00008012 for (i=0; i < (ssize_t) image->colors; i++)
cristy3ed852e2009-09-05 21:47:34 +00008013 {
8014 index=diversity[i].index;
8015 color.red=
8016 ScaleQuantumToShort(XRedGamma(image->colormap[index].red));
8017 color.green=
8018 ScaleQuantumToShort(XGreenGamma(image->colormap[index].green));
8019 color.blue=
8020 ScaleQuantumToShort(XBlueGamma(image->colormap[index].blue));
8021 if (visual_info->klass != PseudoColor)
8022 {
8023 gray_value=(unsigned short) XPixelIntensity(&color);
8024 color.red=gray_value;
8025 color.green=gray_value;
8026 color.blue=gray_value;
8027 }
8028 status=XAllocColor(display,colormap,&color);
8029 if (status == False)
8030 break;
8031 pixel->pixels[index]=color.pixel;
8032 *p++=color;
8033 }
8034 /*
8035 Read X server colormap.
8036 */
8037 server_colors=(XColor *) AcquireQuantumMemory((size_t)
8038 visual_info->colormap_size,sizeof(*server_colors));
8039 if (server_colors == (XColor *) NULL)
8040 ThrowXWindowFatalException(ResourceLimitFatalError,
8041 "UnableToCreateColormap",image->filename);
8042 for (x=visual_info->colormap_size-1; x >= 0; x--)
cristybb503372010-05-27 20:51:26 +00008043 server_colors[x].pixel=(size_t) x;
cristy3ed852e2009-09-05 21:47:34 +00008044 (void) XQueryColors(display,colormap,server_colors,
8045 (int) MagickMin((unsigned int) visual_info->colormap_size,256));
8046 /*
8047 Select remaining colors from X server colormap.
8048 */
cristybb503372010-05-27 20:51:26 +00008049 for (; i < (ssize_t) image->colors; i++)
cristy3ed852e2009-09-05 21:47:34 +00008050 {
8051 index=diversity[i].index;
8052 color.red=
8053 ScaleQuantumToShort(XRedGamma(image->colormap[index].red));
8054 color.green=
8055 ScaleQuantumToShort(XGreenGamma(image->colormap[index].green));
8056 color.blue=
8057 ScaleQuantumToShort(XBlueGamma(image->colormap[index].blue));
8058 if (visual_info->klass != PseudoColor)
8059 {
8060 gray_value=(unsigned short) XPixelIntensity(&color);
8061 color.red=gray_value;
8062 color.green=gray_value;
8063 color.blue=gray_value;
8064 }
8065 XBestPixel(display,colormap,server_colors,(unsigned int)
8066 visual_info->colormap_size,&color);
8067 pixel->pixels[index]=color.pixel;
8068 *p++=color;
8069 }
8070 if ((int) image->colors < visual_info->colormap_size)
8071 {
8072 /*
8073 Fill up colors array-- more choices for pen colors.
8074 */
8075 retain_colors=MagickMin((unsigned int)
8076 (visual_info->colormap_size-image->colors),256);
cristybb503372010-05-27 20:51:26 +00008077 for (i=0; i < (ssize_t) retain_colors; i++)
cristy3ed852e2009-09-05 21:47:34 +00008078 *p++=server_colors[i];
8079 number_colors+=retain_colors;
8080 }
8081 server_colors=(XColor *) RelinquishMagickMemory(server_colors);
8082 diversity=(DiversityPacket *) RelinquishMagickMemory(diversity);
8083 break;
8084 }
8085 /*
8086 Define Standard colormap for private GrayScale or PseudoColor visual.
8087 */
8088 if (status == False)
8089 {
8090 /*
8091 Not enough colormap entries in the colormap-- Create a new colormap.
8092 */
8093 colormap=XCreateColormap(display,
8094 XRootWindow(display,visual_info->screen),visual_info->visual,
8095 AllocNone);
8096 if (colormap == (Colormap) NULL)
8097 ThrowXWindowFatalException(ResourceLimitFatalError,
8098 "UnableToCreateColormap",image->filename);
8099 map_info->colormap=colormap;
8100 if ((int) image->colors < visual_info->colormap_size)
8101 {
8102 /*
8103 Retain colors from the default colormap to help lessens the
8104 effects of colormap flashing.
8105 */
8106 retain_colors=MagickMin((unsigned int)
8107 (visual_info->colormap_size-image->colors),256);
8108 p=colors+image->colors;
cristybb503372010-05-27 20:51:26 +00008109 for (i=0; i < (ssize_t) retain_colors; i++)
cristy3ed852e2009-09-05 21:47:34 +00008110 {
cristyc57f6942010-11-12 01:47:39 +00008111 p->pixel=(unsigned long) i;
cristy3ed852e2009-09-05 21:47:34 +00008112 p++;
8113 }
8114 (void) XQueryColors(display,
8115 XDefaultColormap(display,visual_info->screen),
8116 colors+image->colors,(int) retain_colors);
8117 /*
8118 Transfer colors from default to private colormap.
8119 */
8120 (void) XAllocColorCells(display,colormap,MagickFalse,
cristyf2faecf2010-05-28 19:19:36 +00008121 (unsigned long *) NULL,0,pixel->pixels,(unsigned int)
cristy3ed852e2009-09-05 21:47:34 +00008122 retain_colors);
8123 p=colors+image->colors;
cristybb503372010-05-27 20:51:26 +00008124 for (i=0; i < (ssize_t) retain_colors; i++)
cristy3ed852e2009-09-05 21:47:34 +00008125 {
8126 p->pixel=pixel->pixels[i];
8127 p++;
8128 }
8129 (void) XStoreColors(display,colormap,colors+image->colors,
8130 (int) retain_colors);
8131 number_colors+=retain_colors;
8132 }
8133 (void) XAllocColorCells(display,colormap,MagickFalse,
cristyf2faecf2010-05-28 19:19:36 +00008134 (unsigned long *) NULL,0,pixel->pixels,(unsigned int)
cristy3ed852e2009-09-05 21:47:34 +00008135 image->colors);
8136 }
8137 /*
8138 Store the image colormap.
8139 */
8140 p=colors;
8141 color.flags=(char) (DoRed | DoGreen | DoBlue);
cristybb503372010-05-27 20:51:26 +00008142 for (i=0; i < (ssize_t) image->colors; i++)
cristy3ed852e2009-09-05 21:47:34 +00008143 {
8144 color.red=ScaleQuantumToShort(XRedGamma(image->colormap[i].red));
8145 color.green=ScaleQuantumToShort(XGreenGamma(image->colormap[i].green));
8146 color.blue=ScaleQuantumToShort(XBlueGamma(image->colormap[i].blue));
8147 if (visual_info->klass != PseudoColor)
8148 {
8149 gray_value=(unsigned short) XPixelIntensity(&color);
8150 color.red=gray_value;
8151 color.green=gray_value;
8152 color.blue=gray_value;
8153 }
8154 color.pixel=pixel->pixels[i];
8155 *p++=color;
8156 }
8157 (void) XStoreColors(display,colormap,colors,(int) image->colors);
8158 break;
8159 }
8160 case TrueColor:
8161 case DirectColor:
8162 default:
8163 {
8164 MagickBooleanType
8165 linear_colormap;
8166
8167 /*
8168 Define Standard Colormap for TrueColor or DirectColor visual.
8169 */
8170 number_colors=(unsigned int) ((map_info->red_max*map_info->red_mult)+
8171 (map_info->green_max*map_info->green_mult)+
8172 (map_info->blue_max*map_info->blue_mult)+1);
8173 linear_colormap=(number_colors > 4096) ||
8174 (((int) (map_info->red_max+1) == visual_info->colormap_size) &&
8175 ((int) (map_info->green_max+1) == visual_info->colormap_size) &&
8176 ((int) (map_info->blue_max+1) == visual_info->colormap_size)) ?
8177 MagickTrue : MagickFalse;
8178 if (linear_colormap != MagickFalse)
cristybb503372010-05-27 20:51:26 +00008179 number_colors=(size_t) visual_info->colormap_size;
cristy3ed852e2009-09-05 21:47:34 +00008180 /*
8181 Allocate color array.
8182 */
8183 colors=(XColor *) AcquireQuantumMemory(number_colors,sizeof(*colors));
8184 if (colors == (XColor *) NULL)
8185 ThrowXWindowFatalException(ResourceLimitFatalError,
8186 "UnableToCreateColormap",image->filename);
8187 /*
8188 Initialize linear color ramp.
8189 */
8190 p=colors;
8191 color.flags=(char) (DoRed | DoGreen | DoBlue);
8192 if (linear_colormap != MagickFalse)
cristybb503372010-05-27 20:51:26 +00008193 for (i=0; i < (ssize_t) number_colors; i++)
cristy3ed852e2009-09-05 21:47:34 +00008194 {
8195 color.blue=(unsigned short) 0;
8196 if (map_info->blue_max != 0)
cristybb503372010-05-27 20:51:26 +00008197 color.blue=(unsigned short) ((size_t)
cristy3ed852e2009-09-05 21:47:34 +00008198 ((65535L*(i % map_info->green_mult))/map_info->blue_max));
8199 color.green=color.blue;
8200 color.red=color.blue;
8201 color.pixel=XStandardPixel(map_info,&color);
8202 *p++=color;
8203 }
8204 else
cristybb503372010-05-27 20:51:26 +00008205 for (i=0; i < (ssize_t) number_colors; i++)
cristy3ed852e2009-09-05 21:47:34 +00008206 {
8207 color.red=(unsigned short) 0;
8208 if (map_info->red_max != 0)
cristybb503372010-05-27 20:51:26 +00008209 color.red=(unsigned short) ((size_t)
cristy3ed852e2009-09-05 21:47:34 +00008210 ((65535L*(i/map_info->red_mult))/map_info->red_max));
8211 color.green=(unsigned int) 0;
8212 if (map_info->green_max != 0)
cristybb503372010-05-27 20:51:26 +00008213 color.green=(unsigned short) ((size_t)
cristy3ed852e2009-09-05 21:47:34 +00008214 ((65535L*((i/map_info->green_mult) % (map_info->green_max+1)))/
8215 map_info->green_max));
8216 color.blue=(unsigned short) 0;
8217 if (map_info->blue_max != 0)
cristybb503372010-05-27 20:51:26 +00008218 color.blue=(unsigned short) ((size_t)
cristy3ed852e2009-09-05 21:47:34 +00008219 ((65535L*(i % map_info->green_mult))/map_info->blue_max));
8220 color.pixel=XStandardPixel(map_info,&color);
8221 *p++=color;
8222 }
8223 if ((visual_info->klass == DirectColor) &&
8224 (colormap != XDefaultColormap(display,visual_info->screen)))
8225 (void) XStoreColors(display,colormap,colors,(int) number_colors);
8226 else
cristybb503372010-05-27 20:51:26 +00008227 for (i=0; i < (ssize_t) number_colors; i++)
cristy3ed852e2009-09-05 21:47:34 +00008228 (void) XAllocColor(display,colormap,&colors[i]);
8229 break;
8230 }
8231 }
8232 if ((visual_info->klass != DirectColor) &&
8233 (visual_info->klass != TrueColor))
8234 {
8235 /*
8236 Set foreground, background, border, etc. pixels.
8237 */
8238 XBestPixel(display,colormap,colors,(unsigned int) number_colors,
8239 &pixel->foreground_color);
8240 XBestPixel(display,colormap,colors,(unsigned int) number_colors,
8241 &pixel->background_color);
8242 if (pixel->background_color.pixel == pixel->foreground_color.pixel)
8243 {
8244 /*
8245 Foreground and background colors must differ.
8246 */
8247 pixel->background_color.red=(~pixel->foreground_color.red);
8248 pixel->background_color.green=
8249 (~pixel->foreground_color.green);
8250 pixel->background_color.blue=
8251 (~pixel->foreground_color.blue);
8252 XBestPixel(display,colormap,colors,(unsigned int) number_colors,
8253 &pixel->background_color);
8254 }
8255 XBestPixel(display,colormap,colors,(unsigned int) number_colors,
8256 &pixel->border_color);
8257 XBestPixel(display,colormap,colors,(unsigned int) number_colors,
8258 &pixel->matte_color);
8259 XBestPixel(display,colormap,colors,(unsigned int) number_colors,
8260 &pixel->highlight_color);
8261 XBestPixel(display,colormap,colors,(unsigned int) number_colors,
8262 &pixel->shadow_color);
8263 XBestPixel(display,colormap,colors,(unsigned int) number_colors,
8264 &pixel->depth_color);
8265 XBestPixel(display,colormap,colors,(unsigned int) number_colors,
8266 &pixel->trough_color);
8267 for (i=0; i < MaxNumberPens; i++)
8268 {
8269 XBestPixel(display,colormap,colors,(unsigned int) number_colors,
8270 &pixel->pen_colors[i]);
8271 pixel->pixels[image->colors+i]=pixel->pen_colors[i].pixel;
8272 }
cristyc57f6942010-11-12 01:47:39 +00008273 pixel->colors=(ssize_t) (image->colors+MaxNumberPens);
cristy3ed852e2009-09-05 21:47:34 +00008274 }
8275 colors=(XColor *) RelinquishMagickMemory(colors);
8276 if (IsEventLogging())
8277 {
8278 (void) LogMagickEvent(X11Event,GetMagickModule(),"Standard Colormap:");
8279 (void) LogMagickEvent(X11Event,GetMagickModule()," colormap id: 0x%lx",
8280 map_info->colormap);
8281 (void) LogMagickEvent(X11Event,GetMagickModule(),
8282 " red, green, blue max: %lu %lu %lu",map_info->red_max,
8283 map_info->green_max,map_info->blue_max);
8284 (void) LogMagickEvent(X11Event,GetMagickModule(),
8285 " red, green, blue mult: %lu %lu %lu",map_info->red_mult,
8286 map_info->green_mult,map_info->blue_mult);
8287 }
8288}
8289
8290/*
8291%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8292% %
8293% %
8294% %
8295% X M a k e W i n d o w %
8296% %
8297% %
8298% %
8299%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8300%
8301% XMakeWindow() creates an X11 window.
8302%
8303% The format of the XMakeWindow method is:
8304%
8305% void XMakeWindow(Display *display,Window parent,char **argv,int argc,
8306% XClassHint *class_hint,XWMHints *manager_hints,
8307% XWindowInfo *window_info)
8308%
8309% A description of each parameter follows:
8310%
8311% o display: Specifies a connection to an X server; returned from
8312% XOpenDisplay.
8313%
8314% o parent: Specifies the parent window_info.
8315%
8316% o argv: Specifies the application's argument list.
8317%
8318% o argc: Specifies the number of arguments.
8319%
8320% o class_hint: Specifies a pointer to a X11 XClassHint structure.
8321%
8322% o manager_hints: Specifies a pointer to a X11 XWMHints structure.
8323%
8324% o window_info: Specifies a pointer to a X11 XWindowInfo structure.
8325%
8326*/
cristybcbda3f2011-09-03 13:01:22 +00008327MagickPrivate void XMakeWindow(Display *display,Window parent,char **argv,
cristy3ed852e2009-09-05 21:47:34 +00008328 int argc,XClassHint *class_hint,XWMHints *manager_hints,
8329 XWindowInfo *window_info)
8330{
8331#define MinWindowSize 64
8332
8333 Atom
8334 atom_list[2];
8335
8336 int
8337 gravity;
8338
8339 static XTextProperty
8340 icon_name,
8341 window_name;
8342
8343 Status
8344 status;
8345
8346 XSizeHints
8347 *size_hints;
8348
8349 /*
8350 Set window info hints.
8351 */
8352 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
8353 assert(display != (Display *) NULL);
8354 assert(window_info != (XWindowInfo *) NULL);
8355 size_hints=XAllocSizeHints();
8356 if (size_hints == (XSizeHints *) NULL)
8357 ThrowXWindowFatalException(XServerFatalError,"UnableToMakeXWindow",argv[0]);
cristydfe2b662010-08-22 16:17:24 +00008358 size_hints->flags=(int) window_info->flags;
cristy3ed852e2009-09-05 21:47:34 +00008359 size_hints->x=window_info->x;
8360 size_hints->y=window_info->y;
8361 size_hints->width=(int) window_info->width;
8362 size_hints->height=(int) window_info->height;
8363 if (window_info->immutable != MagickFalse)
8364 {
8365 /*
8366 Window size cannot be changed.
8367 */
8368 size_hints->min_width=size_hints->width;
8369 size_hints->min_height=size_hints->height;
8370 size_hints->max_width=size_hints->width;
8371 size_hints->max_height=size_hints->height;
8372 size_hints->flags|=PMinSize;
8373 size_hints->flags|=PMaxSize;
8374 }
8375 else
8376 {
8377 /*
8378 Window size can be changed.
8379 */
8380 size_hints->min_width=(int) window_info->min_width;
8381 size_hints->min_height=(int) window_info->min_height;
8382 size_hints->flags|=PResizeInc;
8383 size_hints->width_inc=(int) window_info->width_inc;
8384 size_hints->height_inc=(int) window_info->height_inc;
8385#if !defined(PRE_R4_ICCCM)
8386 size_hints->flags|=PBaseSize;
8387 size_hints->base_width=size_hints->width_inc;
8388 size_hints->base_height=size_hints->height_inc;
8389#endif
8390 }
8391 gravity=NorthWestGravity;
8392 if (window_info->geometry != (char *) NULL)
8393 {
8394 char
8395 default_geometry[MaxTextExtent],
8396 geometry[MaxTextExtent];
8397
8398 int
8399 flags;
8400
8401 register char
8402 *p;
8403
8404 /*
8405 User specified geometry.
8406 */
cristyb51dff52011-05-19 16:55:47 +00008407 (void) FormatLocaleString(default_geometry,MaxTextExtent,"%dx%d",
cristy3ed852e2009-09-05 21:47:34 +00008408 size_hints->width,size_hints->height);
8409 (void) CopyMagickString(geometry,window_info->geometry,MaxTextExtent);
8410 p=geometry;
8411 while (strlen(p) != 0)
8412 {
8413 if ((isspace((int) ((unsigned char) *p)) == 0) && (*p != '%'))
8414 p++;
8415 else
8416 (void) CopyMagickString(p,p+1,MaxTextExtent);
8417 }
8418 flags=XWMGeometry(display,window_info->screen,geometry,default_geometry,
8419 window_info->border_width,size_hints,&size_hints->x,&size_hints->y,
8420 &size_hints->width,&size_hints->height,&gravity);
8421 if ((flags & WidthValue) && (flags & HeightValue))
8422 size_hints->flags|=USSize;
8423 if ((flags & XValue) && (flags & YValue))
8424 {
8425 size_hints->flags|=USPosition;
8426 window_info->x=size_hints->x;
8427 window_info->y=size_hints->y;
8428 }
8429 }
8430#if !defined(PRE_R4_ICCCM)
8431 size_hints->win_gravity=gravity;
8432 size_hints->flags|=PWinGravity;
8433#endif
8434 if (window_info->id == (Window) NULL)
8435 window_info->id=XCreateWindow(display,parent,window_info->x,window_info->y,
8436 (unsigned int) size_hints->width,(unsigned int) size_hints->height,
8437 window_info->border_width,(int) window_info->depth,InputOutput,
cristyc57f6942010-11-12 01:47:39 +00008438 window_info->visual,(unsigned long) window_info->mask,
8439 &window_info->attributes);
cristy3ed852e2009-09-05 21:47:34 +00008440 else
8441 {
8442 MagickStatusType
8443 mask;
8444
8445 XEvent
8446 sans_event;
8447
8448 XWindowChanges
8449 window_changes;
8450
8451 /*
8452 Window already exists; change relevant attributes.
8453 */
cristyc57f6942010-11-12 01:47:39 +00008454 (void) XChangeWindowAttributes(display,window_info->id,(unsigned long)
8455 window_info->mask,&window_info->attributes);
cristy3ed852e2009-09-05 21:47:34 +00008456 mask=ConfigureNotify;
8457 while (XCheckTypedWindowEvent(display,window_info->id,(int) mask,&sans_event)) ;
8458 window_changes.x=window_info->x;
8459 window_changes.y=window_info->y;
8460 window_changes.width=(int) window_info->width;
8461 window_changes.height=(int) window_info->height;
8462 mask=(MagickStatusType) (CWWidth | CWHeight);
8463 if (window_info->flags & USPosition)
8464 mask|=CWX | CWY;
8465 (void) XReconfigureWMWindow(display,window_info->id,window_info->screen,
8466 mask,&window_changes);
8467 }
8468 if (window_info->id == (Window) NULL)
8469 ThrowXWindowFatalException(XServerFatalError,"UnableToCreateWindow",
8470 window_info->name);
8471 status=XStringListToTextProperty(&window_info->name,1,&window_name);
8472 if (status == False)
8473 ThrowXWindowFatalException(XServerFatalError,"UnableToCreateTextProperty",
8474 window_info->name);
8475 status=XStringListToTextProperty(&window_info->icon_name,1,&icon_name);
8476 if (status == False)
8477 ThrowXWindowFatalException(XServerFatalError,"UnableToCreateTextProperty",
8478 window_info->icon_name);
8479 if (window_info->icon_geometry != (char *) NULL)
8480 {
8481 int
8482 flags,
8483 height,
8484 width;
8485
8486 /*
8487 User specified icon geometry.
8488 */
8489 size_hints->flags|=USPosition;
8490 flags=XWMGeometry(display,window_info->screen,window_info->icon_geometry,
8491 (char *) NULL,0,size_hints,&manager_hints->icon_x,
8492 &manager_hints->icon_y,&width,&height,&gravity);
8493 if ((flags & XValue) && (flags & YValue))
8494 manager_hints->flags|=IconPositionHint;
8495 }
8496 XSetWMProperties(display,window_info->id,&window_name,&icon_name,argv,argc,
8497 size_hints,manager_hints,class_hint);
8498 if (window_name.value != (void *) NULL)
8499 {
8500 (void) XFree((void *) window_name.value);
8501 window_name.value=(unsigned char *) NULL;
8502 window_name.nitems=0;
8503 }
8504 if (icon_name.value != (void *) NULL)
8505 {
8506 (void) XFree((void *) icon_name.value);
8507 icon_name.value=(unsigned char *) NULL;
8508 icon_name.nitems=0;
8509 }
8510 atom_list[0]=XInternAtom(display,"WM_DELETE_WINDOW",MagickFalse);
8511 atom_list[1]=XInternAtom(display,"WM_TAKE_FOCUS",MagickFalse);
8512 (void) XSetWMProtocols(display,window_info->id,atom_list,2);
8513 (void) XFree((void *) size_hints);
8514 if (window_info->shape != MagickFalse)
8515 {
8516#if defined(MAGICKCORE_HAVE_SHAPE)
8517 int
8518 error_base,
8519 event_base;
8520
8521 /*
8522 Can we apply a non-rectangular shaping mask?
8523 */
8524 error_base=0;
8525 event_base=0;
8526 if (XShapeQueryExtension(display,&error_base,&event_base) == 0)
8527 window_info->shape=MagickFalse;
8528#else
8529 window_info->shape=MagickFalse;
8530#endif
8531 }
8532 if (window_info->shared_memory)
8533 {
8534#if defined(MAGICKCORE_HAVE_SHARED_MEMORY)
8535 /*
8536 Can we use shared memory with this window?
8537 */
8538 if (XShmQueryExtension(display) == 0)
8539 window_info->shared_memory=MagickFalse;
8540#else
8541 window_info->shared_memory=MagickFalse;
8542#endif
8543 }
8544 window_info->image=NewImageList();
8545 window_info->destroy=MagickFalse;
8546}
8547
8548/*
8549%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8550% %
8551% %
8552% %
8553% X M a g i c k P r o g r e s s M o n i t o r %
8554% %
8555% %
8556% %
8557%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8558%
8559% XMagickProgressMonitor() displays the progress a task is making in
8560% completing a task.
8561%
8562% The format of the XMagickProgressMonitor method is:
8563%
8564% void XMagickProgressMonitor(const char *task,
8565% const MagickOffsetType quantum,const MagickSizeType span,
8566% void *client_data)
8567%
8568% A description of each parameter follows:
8569%
8570% o task: Identifies the task in progress.
8571%
8572% o quantum: Specifies the quantum position within the span which represents
8573% how much progress has been made in completing a task.
8574%
8575% o span: Specifies the span relative to completing a task.
8576%
8577% o client_data: Pointer to any client data.
8578%
8579*/
8580
8581static const char *GetLocaleMonitorMessage(const char *text)
8582{
8583 char
8584 message[MaxTextExtent],
8585 tag[MaxTextExtent];
8586
8587 const char
8588 *locale_message;
8589
8590 register char
8591 *p;
8592
8593 (void) CopyMagickMemory(tag,text,MaxTextExtent);
8594 p=strrchr(tag,'/');
8595 if (p != (char *) NULL)
8596 *p='\0';
cristyb51dff52011-05-19 16:55:47 +00008597 (void) FormatLocaleString(message,MaxTextExtent,"Monitor/%s",tag);
cristy3ed852e2009-09-05 21:47:34 +00008598 locale_message=GetLocaleMessage(message);
8599 if (locale_message == message)
8600 return(text);
8601 return(locale_message);
8602}
8603
cristybcbda3f2011-09-03 13:01:22 +00008604MagickPrivate MagickBooleanType XMagickProgressMonitor(const char *tag,
cristy3ed852e2009-09-05 21:47:34 +00008605 const MagickOffsetType quantum,const MagickSizeType span,
8606 void *magick_unused(client_data))
8607{
8608 XWindows
8609 *windows;
8610
8611 windows=XSetWindows((XWindows *) ~0);
8612 if (windows == (XWindows *) NULL)
8613 return(MagickTrue);
8614 if (windows->info.mapped != MagickFalse)
8615 XProgressMonitorWidget(windows->display,windows,
8616 GetLocaleMonitorMessage(tag),quantum,span);
8617 return(MagickTrue);
8618}
8619
8620/*
8621%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8622% %
8623% %
8624% %
8625% X Q u e r y C o l o r D a t a b a s e %
8626% %
8627% %
8628% %
8629%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8630%
8631% XQueryColorDatabase() looks up a RGB values for a color given in the target
8632% string.
8633%
8634% The format of the XQueryColorDatabase method is:
8635%
8636% MagickBooleanType XQueryColorDatabase(const char *target,XColor *color)
8637%
8638% A description of each parameter follows:
8639%
8640% o target: Specifies the color to lookup in the X color database.
8641%
8642% o color: A pointer to an PixelPacket structure. The RGB value of the target
8643% color is returned as this value.
8644%
8645*/
cristybcbda3f2011-09-03 13:01:22 +00008646MagickPrivate MagickBooleanType XQueryColorDatabase(const char *target,
cristy3ed852e2009-09-05 21:47:34 +00008647 XColor *color)
8648{
8649 Colormap
8650 colormap;
8651
8652 static Display
8653 *display = (Display *) NULL;
8654
8655 Status
8656 status;
8657
8658 XColor
8659 xcolor;
8660
8661 /*
8662 Initialize color return value.
8663 */
8664 assert(color != (XColor *) NULL);
8665 color->red=0;
8666 color->green=0;
8667 color->blue=0;
8668 color->flags=(char) (DoRed | DoGreen | DoBlue);
8669 if ((target == (char *) NULL) || (*target == '\0'))
8670 target="#ffffffffffff";
8671 /*
8672 Let the X server define the color for us.
8673 */
8674 if (display == (Display *) NULL)
8675 display=XOpenDisplay((char *) NULL);
8676 if (display == (Display *) NULL)
8677 {
8678 ThrowXWindowFatalException(XServerError,"ColorIsNotKnownToServer",target);
8679 return(MagickFalse);
8680 }
8681 colormap=XDefaultColormap(display,XDefaultScreen(display));
8682 status=XParseColor(display,colormap,(char *) target,&xcolor);
8683 if (status == False)
8684 ThrowXWindowFatalException(XServerError,"ColorIsNotKnownToServer",target)
8685 else
8686 {
8687 color->red=xcolor.red;
8688 color->green=xcolor.green;
8689 color->blue=xcolor.blue;
8690 color->flags=xcolor.flags;
8691 }
8692 return(status != False ? MagickTrue : MagickFalse);
8693}
8694
8695/*
8696%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8697% %
8698% %
8699% %
8700% X Q u e r y P o s i t i o n %
8701% %
8702% %
8703% %
8704%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8705%
8706% XQueryPosition() gets the pointer coordinates relative to a window.
8707%
8708% The format of the XQueryPosition method is:
8709%
8710% void XQueryPosition(Display *display,const Window window,int *x,int *y)
8711%
8712% A description of each parameter follows:
8713%
8714% o display: Specifies a connection to an X server; returned from
8715% XOpenDisplay.
8716%
8717% o window: Specifies a pointer to a Window.
8718%
8719% o x: Return the x coordinate of the pointer relative to the origin of the
8720% window.
8721%
8722% o y: Return the y coordinate of the pointer relative to the origin of the
8723% window.
8724%
8725*/
cristybcbda3f2011-09-03 13:01:22 +00008726MagickPrivate void XQueryPosition(Display *display,const Window window,int *x,int *y)
cristy3ed852e2009-09-05 21:47:34 +00008727{
8728 int
8729 x_root,
8730 y_root;
8731
8732 unsigned int
8733 mask;
8734
8735 Window
8736 root_window;
8737
8738 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
8739 assert(display != (Display *) NULL);
8740 assert(window != (Window) NULL);
8741 assert(x != (int *) NULL);
8742 assert(y != (int *) NULL);
8743 (void) XQueryPointer(display,window,&root_window,&root_window,&x_root,&y_root,
8744 x,y,&mask);
8745}
8746
8747/*
8748%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8749% %
8750% %
8751% %
8752% X R e f r e s h W i n d o w %
8753% %
8754% %
8755% %
8756%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8757%
8758% XRefreshWindow() refreshes an image in a X window.
8759%
8760% The format of the XRefreshWindow method is:
8761%
8762% void XRefreshWindow(Display *display,const XWindowInfo *window,
8763% const XEvent *event)
8764%
8765% A description of each parameter follows:
8766%
8767% o display: Specifies a connection to an X server; returned from
8768% XOpenDisplay.
8769%
8770% o window: Specifies a pointer to a XWindowInfo structure.
8771%
8772% o event: Specifies a pointer to a XEvent structure. If it is NULL,
8773% the entire image is refreshed.
8774%
8775*/
cristybcbda3f2011-09-03 13:01:22 +00008776MagickPrivate void XRefreshWindow(Display *display,const XWindowInfo *window,
cristy3ed852e2009-09-05 21:47:34 +00008777 const XEvent *event)
8778{
8779 int
8780 x,
8781 y;
8782
8783 unsigned int
8784 height,
8785 width;
8786
8787 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
8788 assert(display != (Display *) NULL);
8789 assert(window != (XWindowInfo *) NULL);
8790 if (window->ximage == (XImage *) NULL)
8791 return;
8792 if (event != (XEvent *) NULL)
8793 {
8794 /*
8795 Determine geometry from expose event.
8796 */
8797 x=event->xexpose.x;
8798 y=event->xexpose.y;
8799 width=(unsigned int) event->xexpose.width;
8800 height=(unsigned int) event->xexpose.height;
8801 }
8802 else
8803 {
8804 XEvent
8805 sans_event;
8806
8807 /*
8808 Refresh entire window; discard outstanding expose events.
8809 */
8810 x=0;
8811 y=0;
8812 width=window->width;
8813 height=window->height;
8814 while (XCheckTypedWindowEvent(display,window->id,Expose,&sans_event)) ;
cristya0e5ad52010-02-10 02:05:12 +00008815 if (window->matte_pixmap != (Pixmap) NULL)
8816 {
8817#if defined(MAGICKCORE_HAVE_SHAPE)
8818 if (window->shape != MagickFalse)
8819 XShapeCombineMask(display,window->id,ShapeBounding,0,0,
8820 window->matte_pixmap,ShapeSet);
8821#endif
8822 }
cristy3ed852e2009-09-05 21:47:34 +00008823 }
8824 /*
8825 Check boundary conditions.
8826 */
8827 if ((window->ximage->width-(x+window->x)) < (int) width)
8828 width=(unsigned int) (window->ximage->width-(x+window->x));
8829 if ((window->ximage->height-(y+window->y)) < (int) height)
8830 height=(unsigned int) (window->ximage->height-(y+window->y));
8831 /*
8832 Refresh image.
8833 */
8834 if (window->matte_pixmap != (Pixmap) NULL)
cristya0e5ad52010-02-10 02:05:12 +00008835 (void) XSetClipMask(display,window->annotate_context,window->matte_pixmap);
cristy3ed852e2009-09-05 21:47:34 +00008836 if (window->pixmap != (Pixmap) NULL)
8837 {
8838 if (window->depth > 1)
8839 (void) XCopyArea(display,window->pixmap,window->id,
8840 window->annotate_context,x+window->x,y+window->y,width,height,x,y);
8841 else
8842 (void) XCopyPlane(display,window->pixmap,window->id,
8843 window->highlight_context,x+window->x,y+window->y,width,height,x,y,
8844 1L);
8845 }
8846 else
8847 {
8848#if defined(MAGICKCORE_HAVE_SHARED_MEMORY)
8849 if (window->shared_memory)
8850 (void) XShmPutImage(display,window->id,window->annotate_context,
8851 window->ximage,x+window->x,y+window->y,x,y,width,height,MagickTrue);
8852#endif
8853 if (window->shared_memory == MagickFalse)
8854 (void) XPutImage(display,window->id,window->annotate_context,
8855 window->ximage,x+window->x,y+window->y,x,y,width,height);
8856 }
8857 if (window->matte_pixmap != (Pixmap) NULL)
8858 (void) XSetClipMask(display,window->annotate_context,None);
8859 (void) XFlush(display);
8860}
8861
8862/*
8863%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8864% %
8865% %
8866% %
8867% X R e m o t e C o m m a n d %
8868% %
8869% %
8870% %
8871%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8872%
8873% XRemoteCommand() forces a remote display(1) to display the specified
8874% image filename.
8875%
8876% The format of the XRemoteCommand method is:
8877%
8878% MagickBooleanType XRemoteCommand(Display *display,const char *window,
8879% const char *filename)
8880%
8881% A description of each parameter follows:
8882%
8883% o display: Specifies a connection to an X server; returned from
8884% XOpenDisplay.
8885%
8886% o window: Specifies the name or id of an X window.
8887%
8888% o filename: the name of the image filename to display.
8889%
8890*/
8891MagickExport MagickBooleanType XRemoteCommand(Display *display,
8892 const char *window,const char *filename)
8893{
8894 Atom
8895 remote_atom;
8896
8897 Window
8898 remote_window,
8899 root_window;
8900
8901 assert(filename != (char *) NULL);
8902 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",filename);
8903 if (display == (Display *) NULL)
8904 display=XOpenDisplay((char *) NULL);
8905 if (display == (Display *) NULL)
8906 {
8907 ThrowXWindowException(XServerError,"UnableToOpenXServer",filename);
8908 return(MagickFalse);
8909 }
8910 remote_atom=XInternAtom(display,"IM_PROTOCOLS",MagickFalse);
8911 remote_window=(Window) NULL;
8912 root_window=XRootWindow(display,XDefaultScreen(display));
8913 if (window != (char *) NULL)
8914 {
8915 /*
8916 Search window hierarchy and identify any clients by name or ID.
8917 */
8918 if (isdigit((unsigned char) *window) != 0)
8919 remote_window=XWindowByID(display,root_window,(Window)
8920 strtol((char *) window,(char **) NULL,0));
8921 if (remote_window == (Window) NULL)
8922 remote_window=XWindowByName(display,root_window,window);
8923 }
8924 if (remote_window == (Window) NULL)
8925 remote_window=XWindowByProperty(display,root_window,remote_atom);
8926 if (remote_window == (Window) NULL)
8927 {
8928 ThrowXWindowException(XServerError,"UnableToConnectToRemoteDisplay",
8929 filename);
8930 return(MagickFalse);
8931 }
8932 /*
8933 Send remote command.
8934 */
8935 remote_atom=XInternAtom(display,"IM_REMOTE_COMMAND",MagickFalse);
8936 (void) XChangeProperty(display,remote_window,remote_atom,XA_STRING,8,
8937 PropModeReplace,(unsigned char *) filename,(int) strlen(filename));
8938 (void) XSync(display,MagickFalse);
8939 return(MagickTrue);
8940}
8941
8942/*
8943%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8944% %
8945% %
8946% %
8947% X R e t a i n W i n d o w C o l o r s %
8948% %
8949% %
8950% %
8951%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8952%
8953% XRetainWindowColors() sets X11 color resources on a window. This preserves
8954% the colors associated with an image displayed on the window.
8955%
8956% The format of the XRetainWindowColors method is:
8957%
8958% void XRetainWindowColors(Display *display,const Window window)
8959%
8960% A description of each parameter follows:
8961%
8962% o display: Specifies a connection to an X server; returned from
8963% XOpenDisplay.
8964%
8965% o window: Specifies a pointer to a XWindowInfo structure.
8966%
8967*/
8968MagickExport void XRetainWindowColors(Display *display,const Window window)
8969{
8970 Atom
8971 property;
8972
8973 Pixmap
8974 pixmap;
8975
8976 /*
8977 Put property on the window.
8978 */
8979 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
8980 assert(display != (Display *) NULL);
8981 assert(window != (Window) NULL);
8982 property=XInternAtom(display,"_XSETROOT_ID",MagickFalse);
8983 if (property == (Atom) NULL)
8984 {
8985 ThrowXWindowFatalException(XServerError,"UnableToCreateProperty",
8986 "_XSETROOT_ID");
8987 return;
8988 }
8989 pixmap=XCreatePixmap(display,window,1,1,1);
8990 if (pixmap == (Pixmap) NULL)
8991 {
8992 ThrowXWindowFatalException(XServerError,"UnableToCreateBitmap","");
8993 return;
8994 }
8995 (void) XChangeProperty(display,window,property,XA_PIXMAP,32,PropModeReplace,
8996 (unsigned char *) &pixmap,1);
8997 (void) XSetCloseDownMode(display,RetainPermanent);
8998}
8999
9000/*
9001%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9002% %
9003% %
9004% %
9005% X S e l e c t W i n d o w %
9006% %
9007% %
9008% %
9009%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9010%
9011% XSelectWindow() allows a user to select a window using the mouse. If the
9012% mouse moves, a cropping rectangle is drawn and the extents of the rectangle
9013% is returned in the crop_info structure.
9014%
9015% The format of the XSelectWindow function is:
9016%
9017% target_window=XSelectWindow(display,crop_info)
9018%
9019% A description of each parameter follows:
9020%
9021% o window: XSelectWindow returns the window id.
9022%
9023% o display: Specifies a pointer to the Display structure; returned from
9024% XOpenDisplay.
9025%
9026% o crop_info: Specifies a pointer to a RectangleInfo structure. It
9027% contains the extents of any cropping rectangle.
9028%
cristy3ed852e2009-09-05 21:47:34 +00009029*/
9030static Window XSelectWindow(Display *display,RectangleInfo *crop_info)
9031{
9032#define MinimumCropArea (unsigned int) 9
9033
9034 Cursor
9035 target_cursor;
9036
9037 GC
9038 annotate_context;
9039
9040 int
9041 presses,
9042 x_offset,
9043 y_offset;
9044
9045 Status
9046 status;
9047
9048 Window
9049 root_window,
9050 target_window;
9051
9052 XEvent
9053 event;
9054
9055 XGCValues
9056 context_values;
9057
9058 /*
9059 Initialize graphic context.
9060 */
9061 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
9062 assert(display != (Display *) NULL);
9063 assert(crop_info != (RectangleInfo *) NULL);
9064 root_window=XRootWindow(display,XDefaultScreen(display));
9065 context_values.background=XBlackPixel(display,XDefaultScreen(display));
9066 context_values.foreground=XWhitePixel(display,XDefaultScreen(display));
9067 context_values.function=GXinvert;
9068 context_values.plane_mask=
9069 context_values.background ^ context_values.foreground;
9070 context_values.subwindow_mode=IncludeInferiors;
cristybb503372010-05-27 20:51:26 +00009071 annotate_context=XCreateGC(display,root_window,(size_t) (GCBackground |
cristy3ed852e2009-09-05 21:47:34 +00009072 GCForeground | GCFunction | GCSubwindowMode),&context_values);
9073 if (annotate_context == (GC) NULL)
9074 return(MagickFalse);
9075 /*
9076 Grab the pointer using target cursor.
9077 */
9078 target_cursor=XMakeCursor(display,root_window,XDefaultColormap(display,
9079 XDefaultScreen(display)),(char * ) "white",(char * ) "black");
9080 status=XGrabPointer(display,root_window,MagickFalse,(unsigned int)
9081 (ButtonPressMask | ButtonReleaseMask | ButtonMotionMask),GrabModeSync,
9082 GrabModeAsync,root_window,target_cursor,CurrentTime);
9083 if (status != GrabSuccess)
9084 {
9085 ThrowXWindowFatalException(XServerError,"UnableToGrabMouse","");
9086 return((Window) NULL);
9087 }
9088 /*
9089 Select a window.
9090 */
9091 crop_info->width=0;
9092 crop_info->height=0;
9093 presses=0;
9094 target_window=(Window) NULL;
9095 x_offset=0;
9096 y_offset=0;
9097 do
9098 {
9099 if ((crop_info->width*crop_info->height) >= MinimumCropArea)
9100 (void) XDrawRectangle(display,root_window,annotate_context,
9101 (int) crop_info->x,(int) crop_info->y,(unsigned int) crop_info->width-1,
9102 (unsigned int) crop_info->height-1);
9103 /*
9104 Allow another event.
9105 */
9106 (void) XAllowEvents(display,SyncPointer,CurrentTime);
9107 (void) XWindowEvent(display,root_window,ButtonPressMask |
9108 ButtonReleaseMask | ButtonMotionMask,&event);
9109 if ((crop_info->width*crop_info->height) >= MinimumCropArea)
9110 (void) XDrawRectangle(display,root_window,annotate_context,
9111 (int) crop_info->x,(int) crop_info->y,(unsigned int) crop_info->width-1,
9112 (unsigned int) crop_info->height-1);
9113 switch (event.type)
9114 {
9115 case ButtonPress:
9116 {
9117 target_window=XGetSubwindow(display,event.xbutton.subwindow,
9118 event.xbutton.x,event.xbutton.y);
9119 if (target_window == (Window) NULL)
9120 target_window=root_window;
9121 x_offset=event.xbutton.x_root;
9122 y_offset=event.xbutton.y_root;
cristyecd0ab52010-05-30 14:59:20 +00009123 crop_info->x=(ssize_t) x_offset;
9124 crop_info->y=(ssize_t) y_offset;
cristy3ed852e2009-09-05 21:47:34 +00009125 crop_info->width=0;
9126 crop_info->height=0;
9127 presses++;
9128 break;
9129 }
9130 case ButtonRelease:
9131 {
9132 presses--;
9133 break;
9134 }
9135 case MotionNotify:
9136 {
9137 /*
9138 Discard pending button motion events.
9139 */
9140 while (XCheckMaskEvent(display,ButtonMotionMask,&event)) ;
cristyecd0ab52010-05-30 14:59:20 +00009141 crop_info->x=(ssize_t) event.xmotion.x;
9142 crop_info->y=(ssize_t) event.xmotion.y;
cristy3ed852e2009-09-05 21:47:34 +00009143 /*
9144 Check boundary conditions.
9145 */
9146 if ((int) crop_info->x < x_offset)
cristyecd0ab52010-05-30 14:59:20 +00009147 crop_info->width=(size_t) (x_offset-crop_info->x);
cristy3ed852e2009-09-05 21:47:34 +00009148 else
9149 {
cristyecd0ab52010-05-30 14:59:20 +00009150 crop_info->width=(size_t) (crop_info->x-x_offset);
9151 crop_info->x=(ssize_t) x_offset;
cristy3ed852e2009-09-05 21:47:34 +00009152 }
9153 if ((int) crop_info->y < y_offset)
cristyecd0ab52010-05-30 14:59:20 +00009154 crop_info->height=(size_t) (y_offset-crop_info->y);
cristy3ed852e2009-09-05 21:47:34 +00009155 else
9156 {
cristyecd0ab52010-05-30 14:59:20 +00009157 crop_info->height=(size_t) (crop_info->y-y_offset);
9158 crop_info->y=(ssize_t) y_offset;
cristy3ed852e2009-09-05 21:47:34 +00009159 }
9160 }
9161 default:
9162 break;
9163 }
9164 } while ((target_window == (Window) NULL) || (presses > 0));
9165 (void) XUngrabPointer(display,CurrentTime);
9166 (void) XFreeCursor(display,target_cursor);
9167 (void) XFreeGC(display,annotate_context);
9168 if ((crop_info->width*crop_info->height) < MinimumCropArea)
9169 {
9170 crop_info->width=0;
9171 crop_info->height=0;
9172 }
9173 if ((crop_info->width != 0) && (crop_info->height != 0))
9174 target_window=root_window;
9175 return(target_window);
9176}
9177
9178/*
9179%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9180% %
9181% %
9182% %
9183% X S e t C u r s o r S t a t e %
9184% %
9185% %
9186% %
9187%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9188%
9189% XSetCursorState() sets the cursor state to busy, otherwise the cursor are
9190% reset to their default.
9191%
9192% The format of the XXSetCursorState method is:
9193%
9194% XSetCursorState(display,windows,const MagickStatusType state)
9195%
9196% A description of each parameter follows:
9197%
9198% o display: Specifies a connection to an X server; returned from
9199% XOpenDisplay.
9200%
9201% o windows: Specifies a pointer to a XWindows structure.
9202%
9203% o state: An unsigned integer greater than 0 sets the cursor state
9204% to busy, otherwise the cursor are reset to their default.
9205%
9206*/
cristybcbda3f2011-09-03 13:01:22 +00009207MagickPrivate void XSetCursorState(Display *display,XWindows *windows,
cristy3ed852e2009-09-05 21:47:34 +00009208 const MagickStatusType state)
9209{
9210 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
9211 assert(display != (Display *) NULL);
9212 assert(windows != (XWindows *) NULL);
9213 if (state)
9214 {
9215 (void) XCheckDefineCursor(display,windows->image.id,
9216 windows->image.busy_cursor);
9217 (void) XCheckDefineCursor(display,windows->pan.id,
9218 windows->pan.busy_cursor);
9219 (void) XCheckDefineCursor(display,windows->magnify.id,
9220 windows->magnify.busy_cursor);
9221 (void) XCheckDefineCursor(display,windows->command.id,
9222 windows->command.busy_cursor);
9223 }
9224 else
9225 {
9226 (void) XCheckDefineCursor(display,windows->image.id,
9227 windows->image.cursor);
9228 (void) XCheckDefineCursor(display,windows->pan.id,windows->pan.cursor);
9229 (void) XCheckDefineCursor(display,windows->magnify.id,
9230 windows->magnify.cursor);
9231 (void) XCheckDefineCursor(display,windows->command.id,
9232 windows->command.cursor);
9233 (void) XCheckDefineCursor(display,windows->command.id,
9234 windows->widget.cursor);
9235 (void) XWithdrawWindow(display,windows->info.id,windows->info.screen);
9236 }
9237 windows->info.mapped=MagickFalse;
9238}
9239
9240/*
9241%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9242% %
9243% %
9244% %
9245% X S e t W i n d o w s %
9246% %
9247% %
9248% %
9249%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9250%
9251% XSetWindows() sets the X windows structure if the windows info is specified.
9252% Otherwise the current windows structure is returned.
9253%
9254% The format of the XSetWindows method is:
9255%
9256% XWindows *XSetWindows(XWindows *windows_info)
9257%
9258% A description of each parameter follows:
9259%
9260% o windows_info: Initialize the Windows structure with this information.
9261%
9262*/
cristybcbda3f2011-09-03 13:01:22 +00009263MagickPrivate XWindows *XSetWindows(XWindows *windows_info)
cristy3ed852e2009-09-05 21:47:34 +00009264{
9265 static XWindows
9266 *windows = (XWindows *) NULL;
9267
9268 if (windows_info != (XWindows *) ~0)
9269 {
9270 windows=(XWindows *) RelinquishMagickMemory(windows);
9271 windows=windows_info;
9272 }
9273 return(windows);
9274}
9275/*
9276%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9277% %
9278% %
9279% %
9280% X U s e r P r e f e r e n c e s %
9281% %
9282% %
9283% %
9284%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9285%
9286% XUserPreferences() saves the preferences in a configuration file in the
9287% users' home directory.
9288%
9289% The format of the XUserPreferences method is:
9290%
9291% void XUserPreferences(XResourceInfo *resource_info)
9292%
9293% A description of each parameter follows:
9294%
9295% o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
9296%
9297*/
cristybcbda3f2011-09-03 13:01:22 +00009298MagickPrivate void XUserPreferences(XResourceInfo *resource_info)
cristy3ed852e2009-09-05 21:47:34 +00009299{
9300#if defined(X11_PREFERENCES_PATH)
9301 char
9302 cache[MaxTextExtent],
9303 filename[MaxTextExtent],
9304 specifier[MaxTextExtent];
9305
9306 const char
cristy104cea82009-10-25 02:26:51 +00009307 *client_name,
cristy3ed852e2009-09-05 21:47:34 +00009308 *value;
9309
9310 XrmDatabase
9311 preferences_database;
9312
9313 /*
9314 Save user preferences to the client configuration file.
9315 */
9316 assert(resource_info != (XResourceInfo *) NULL);
cristy104cea82009-10-25 02:26:51 +00009317 client_name=GetClientName();
cristy3ed852e2009-09-05 21:47:34 +00009318 preferences_database=XrmGetStringDatabase("");
cristyb51dff52011-05-19 16:55:47 +00009319 (void) FormatLocaleString(specifier,MaxTextExtent,"%s.backdrop",client_name);
cristy3ed852e2009-09-05 21:47:34 +00009320 value=resource_info->backdrop ? "True" : "False";
9321 XrmPutStringResource(&preferences_database,specifier,(char *) value);
cristyb51dff52011-05-19 16:55:47 +00009322 (void) FormatLocaleString(specifier,MaxTextExtent,"%s.colormap",client_name);
cristy3ed852e2009-09-05 21:47:34 +00009323 value=resource_info->colormap == SharedColormap ? "Shared" : "Private";
9324 XrmPutStringResource(&preferences_database,specifier,(char *) value);
cristyb51dff52011-05-19 16:55:47 +00009325 (void) FormatLocaleString(specifier,MaxTextExtent,"%s.confirmExit",
cristy104cea82009-10-25 02:26:51 +00009326 client_name);
cristy3ed852e2009-09-05 21:47:34 +00009327 value=resource_info->confirm_exit ? "True" : "False";
9328 XrmPutStringResource(&preferences_database,specifier,(char *) value);
cristyb51dff52011-05-19 16:55:47 +00009329 (void) FormatLocaleString(specifier,MaxTextExtent,"%s.confirmEdit",
cristy104cea82009-10-25 02:26:51 +00009330 client_name);
cristy3ed852e2009-09-05 21:47:34 +00009331 value=resource_info->confirm_edit ? "True" : "False";
9332 XrmPutStringResource(&preferences_database,specifier,(char *) value);
cristyb51dff52011-05-19 16:55:47 +00009333 (void) FormatLocaleString(specifier,MaxTextExtent,"%s.displayWarnings",
cristy104cea82009-10-25 02:26:51 +00009334 client_name);
cristy3ed852e2009-09-05 21:47:34 +00009335 value=resource_info->display_warnings ? "True" : "False";
9336 XrmPutStringResource(&preferences_database,specifier,(char *) value);
cristyb51dff52011-05-19 16:55:47 +00009337 (void) FormatLocaleString(specifier,MaxTextExtent,"%s.dither",client_name);
cristy3ed852e2009-09-05 21:47:34 +00009338 value=resource_info->quantize_info->dither ? "True" : "False";
9339 XrmPutStringResource(&preferences_database,specifier,(char *) value);
cristyb51dff52011-05-19 16:55:47 +00009340 (void) FormatLocaleString(specifier,MaxTextExtent,"%s.gammaCorrect",
cristy104cea82009-10-25 02:26:51 +00009341 client_name);
cristy3ed852e2009-09-05 21:47:34 +00009342 value=resource_info->gamma_correct ? "True" : "False";
9343 XrmPutStringResource(&preferences_database,specifier,(char *) value);
cristyb51dff52011-05-19 16:55:47 +00009344 (void) FormatLocaleString(specifier,MaxTextExtent,"%s.undoCache",client_name);
9345 (void) FormatLocaleString(cache,MaxTextExtent,"%.20g",(double)
cristy3ed852e2009-09-05 21:47:34 +00009346 resource_info->undo_cache);
9347 XrmPutStringResource(&preferences_database,specifier,cache);
cristyb51dff52011-05-19 16:55:47 +00009348 (void) FormatLocaleString(specifier,MaxTextExtent,"%s.usePixmap",client_name);
cristy3ed852e2009-09-05 21:47:34 +00009349 value=resource_info->use_pixmap ? "True" : "False";
9350 XrmPutStringResource(&preferences_database,specifier,(char *) value);
cristyb51dff52011-05-19 16:55:47 +00009351 (void) FormatLocaleString(filename,MaxTextExtent,"%s%src",
cristy104cea82009-10-25 02:26:51 +00009352 X11_PREFERENCES_PATH,client_name);
cristy3ed852e2009-09-05 21:47:34 +00009353 ExpandFilename(filename);
9354 XrmPutFileDatabase(preferences_database,filename);
9355#endif
9356}
9357
9358/*
9359%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9360% %
9361% %
9362% %
9363% X V i s u a l C l a s s N a m e %
9364% %
9365% %
9366% %
9367%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9368%
9369% XVisualClassName() returns the visual class name as a character string.
9370%
9371% The format of the XVisualClassName method is:
9372%
9373% char *XVisualClassName(const int visual_class)
9374%
9375% A description of each parameter follows:
9376%
9377% o visual_type: XVisualClassName returns the visual class as a character
9378% string.
9379%
9380% o class: Specifies the visual class.
9381%
cristy3ed852e2009-09-05 21:47:34 +00009382*/
9383static const char *XVisualClassName(const int visual_class)
9384{
9385 switch (visual_class)
9386 {
9387 case StaticGray: return("StaticGray");
9388 case GrayScale: return("GrayScale");
9389 case StaticColor: return("StaticColor");
9390 case PseudoColor: return("PseudoColor");
9391 case TrueColor: return("TrueColor");
9392 case DirectColor: return("DirectColor");
9393 }
9394 return("unknown visual class");
9395}
9396
9397/*
9398%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9399% %
9400% %
9401% %
9402% X W a r n i n g %
9403% %
9404% %
9405% %
9406%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9407%
9408% XWarning() displays a warning reason in a Notice widget.
9409%
9410% The format of the XWarning method is:
9411%
9412% void XWarning(const unsigned int warning,const char *reason,
9413% const char *description)
9414%
9415% A description of each parameter follows:
9416%
9417% o warning: Specifies the numeric warning category.
9418%
9419% o reason: Specifies the reason to display before terminating the
9420% program.
9421%
9422% o description: Specifies any description to the reason.
9423%
9424*/
cristybcbda3f2011-09-03 13:01:22 +00009425MagickPrivate void XWarning(const ExceptionType magick_unused(warning),
cristy3ed852e2009-09-05 21:47:34 +00009426 const char *reason,const char *description)
9427{
9428 char
9429 text[MaxTextExtent];
9430
9431 XWindows
9432 *windows;
9433
9434 if (reason == (char *) NULL)
9435 return;
9436 (void) CopyMagickString(text,reason,MaxTextExtent);
9437 (void) ConcatenateMagickString(text,":",MaxTextExtent);
9438 windows=XSetWindows((XWindows *) ~0);
9439 XNoticeWidget(windows->display,windows,text,(char *) description);
9440}
9441
9442/*
9443%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9444% %
9445% %
9446% %
9447% X W i n d o w B y I D %
9448% %
9449% %
9450% %
9451%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9452%
9453% XWindowByID() locates a child window with a given ID. If not window with
9454% the given name is found, 0 is returned. Only the window specified and its
9455% subwindows are searched.
9456%
9457% The format of the XWindowByID function is:
9458%
9459% child=XWindowByID(display,window,id)
9460%
9461% A description of each parameter follows:
9462%
9463% o child: XWindowByID returns the window with the specified
9464% id. If no windows are found, XWindowByID returns 0.
9465%
9466% o display: Specifies a pointer to the Display structure; returned from
9467% XOpenDisplay.
9468%
9469% o id: Specifies the id of the window to locate.
9470%
9471*/
cristybcbda3f2011-09-03 13:01:22 +00009472MagickPrivate Window XWindowByID(Display *display,const Window root_window,
cristybb503372010-05-27 20:51:26 +00009473 const size_t id)
cristy3ed852e2009-09-05 21:47:34 +00009474{
9475 RectangleInfo
9476 rectangle_info;
9477
9478 register int
9479 i;
9480
9481 Status
9482 status;
9483
9484 unsigned int
9485 number_children;
9486
9487 Window
9488 child,
9489 *children,
9490 window;
9491
9492 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
9493 assert(display != (Display *) NULL);
9494 assert(root_window != (Window) NULL);
9495 if (id == 0)
9496 return(XSelectWindow(display,&rectangle_info));
9497 if (root_window == id)
cristydfe2b662010-08-22 16:17:24 +00009498 return(root_window);
cristy3ed852e2009-09-05 21:47:34 +00009499 status=XQueryTree(display,root_window,&child,&child,&children,
9500 &number_children);
9501 if (status == False)
9502 return((Window) NULL);
9503 window=(Window) NULL;
9504 for (i=0; i < (int) number_children; i++)
9505 {
9506 /*
9507 Search each child and their children.
9508 */
9509 window=XWindowByID(display,children[i],id);
9510 if (window != (Window) NULL)
9511 break;
9512 }
9513 if (children != (Window *) NULL)
9514 (void) XFree((void *) children);
9515 return(window);
9516}
9517
9518/*
9519%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9520% %
9521% %
9522% %
9523% X W i n d o w B y N a m e %
9524% %
9525% %
9526% %
9527%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9528%
9529% XWindowByName() locates a window with a given name on a display. If no
9530% window with the given name is found, 0 is returned. If more than one window
9531% has the given name, the first one is returned. Only root and its children
9532% are searched.
9533%
9534% The format of the XWindowByName function is:
9535%
9536% window=XWindowByName(display,root_window,name)
9537%
9538% A description of each parameter follows:
9539%
9540% o window: XWindowByName returns the window id.
9541%
9542% o display: Specifies a pointer to the Display structure; returned from
9543% XOpenDisplay.
9544%
9545% o root_window: Specifies the id of the root window.
9546%
9547% o name: Specifies the name of the window to locate.
9548%
9549*/
cristybcbda3f2011-09-03 13:01:22 +00009550MagickPrivate Window XWindowByName(Display *display,const Window root_window,
cristy3ed852e2009-09-05 21:47:34 +00009551 const char *name)
9552{
9553 register int
9554 i;
9555
9556 Status
9557 status;
9558
9559 unsigned int
9560 number_children;
9561
9562 Window
9563 *children,
9564 child,
9565 window;
9566
9567 XTextProperty
9568 window_name;
9569
9570 assert(display != (Display *) NULL);
9571 assert(root_window != (Window) NULL);
9572 assert(name != (char *) NULL);
9573 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",name);
9574 if (XGetWMName(display,root_window,&window_name) != 0)
9575 if (LocaleCompare((char *) window_name.value,name) == 0)
9576 return(root_window);
9577 status=XQueryTree(display,root_window,&child,&child,&children,
9578 &number_children);
9579 if (status == False)
9580 return((Window) NULL);
9581 window=(Window) NULL;
9582 for (i=0; i < (int) number_children; i++)
9583 {
9584 /*
9585 Search each child and their children.
9586 */
9587 window=XWindowByName(display,children[i],name);
9588 if (window != (Window) NULL)
9589 break;
9590 }
9591 if (children != (Window *) NULL)
9592 (void) XFree((void *) children);
9593 return(window);
9594}
9595
9596/*
9597%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9598% %
9599% %
9600% %
9601% X W i n d o w B y P r o p e r y %
9602% %
9603% %
9604% %
9605%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9606%
9607% XWindowByProperty() locates a child window with a given property. If not
9608% window with the given name is found, 0 is returned. If more than one window
9609% has the given property, the first one is returned. Only the window
9610% specified and its subwindows are searched.
9611%
9612% The format of the XWindowByProperty function is:
9613%
9614% child=XWindowByProperty(display,window,property)
9615%
9616% A description of each parameter follows:
9617%
9618% o child: XWindowByProperty returns the window id with the specified
9619% property. If no windows are found, XWindowByProperty returns 0.
9620%
9621% o display: Specifies a pointer to the Display structure; returned from
9622% XOpenDisplay.
9623%
9624% o property: Specifies the property of the window to locate.
9625%
9626*/
cristybcbda3f2011-09-03 13:01:22 +00009627MagickPrivate Window XWindowByProperty(Display *display,const Window window,
cristy3ed852e2009-09-05 21:47:34 +00009628 const Atom property)
9629{
9630 Atom
9631 type;
9632
9633 int
9634 format;
9635
9636 Status
9637 status;
9638
9639 unsigned char
9640 *data;
9641
9642 unsigned int
9643 i,
9644 number_children;
9645
cristyf2faecf2010-05-28 19:19:36 +00009646 unsigned long
cristy3ed852e2009-09-05 21:47:34 +00009647 after,
9648 number_items;
9649
9650 Window
9651 child,
9652 *children,
9653 parent,
9654 root;
9655
9656 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
9657 assert(display != (Display *) NULL);
9658 assert(window != (Window) NULL);
9659 assert(property != (Atom) NULL);
9660 status=XQueryTree(display,window,&root,&parent,&children,&number_children);
9661 if (status == False)
9662 return((Window) NULL);
9663 type=(Atom) NULL;
9664 child=(Window) NULL;
9665 for (i=0; (i < number_children) && (child == (Window) NULL); i++)
9666 {
9667 status=XGetWindowProperty(display,children[i],property,0L,0L,MagickFalse,
9668 (Atom) AnyPropertyType,&type,&format,&number_items,&after,&data);
9669 if (data != NULL)
9670 (void) XFree((void *) data);
9671 if ((status == Success) && (type != (Atom) NULL))
9672 child=children[i];
9673 }
9674 for (i=0; (i < number_children) && (child == (Window) NULL); i++)
9675 child=XWindowByProperty(display,children[i],property);
9676 if (children != (Window *) NULL)
9677 (void) XFree((void *) children);
9678 return(child);
9679}
9680#else
9681
9682/*
9683%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9684% %
9685% %
9686% %
9687% X I m p o r t I m a g e %
9688% %
9689% %
9690% %
9691%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9692%
9693% XImportImage() reads an image from an X window.
9694%
9695% The format of the XImportImage method is:
9696%
9697% Image *XImportImage(const ImageInfo *image_info,XImportInfo *ximage_info)
9698%
9699% A description of each parameter follows:
9700%
9701% o image_info: the image info..
9702%
9703% o ximage_info: Specifies a pointer to an XImportInfo structure.
9704%
9705*/
cristybcbda3f2011-09-03 13:01:22 +00009706MagickPrivate Image *XImportImage(const ImageInfo *image_info,
cristy3ed852e2009-09-05 21:47:34 +00009707 XImportInfo *ximage_info)
9708{
9709 assert(image_info != (const ImageInfo *) NULL);
9710 assert(image_info->signature == MagickSignature);
9711 if (image_info->debug != MagickFalse)
9712 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
9713 image_info->filename);
9714 assert(ximage_info != (XImportInfo *) NULL);
9715 return((Image *) NULL);
9716}
9717#endif
9718
9719/*
9720%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9721% %
9722% %
9723% %
cristy576974e2009-10-25 20:45:31 +00009724+ X C o m p o n e n t G e n e s i s %
9725% %
9726% %
9727% %
9728%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9729%
9730% XComponentGenesis() instantiates the X component.
9731%
9732% The format of the XComponentGenesis method is:
9733%
9734% MagickBooleanType XComponentGenesis(void)
9735%
9736*/
cristy5ff4eaf2011-09-03 01:38:02 +00009737MagickPrivate MagickBooleanType XComponentGenesis(void)
cristy576974e2009-10-25 20:45:31 +00009738{
9739 return(MagickTrue);
9740}
9741
9742/*
9743%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9744% %
9745% %
9746% %
cristy3ed852e2009-09-05 21:47:34 +00009747% X G e t I m p o r t I n f o %
9748% %
9749% %
9750% %
9751%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9752%
9753% XGetImportInfo() initializes the XImportInfo structure.
9754%
9755% The format of the XGetImportInfo method is:
9756%
9757% void XGetImportInfo(XImportInfo *ximage_info)
9758%
9759% A description of each parameter follows:
9760%
9761% o ximage_info: Specifies a pointer to an ImageInfo structure.
9762%
9763*/
9764MagickExport void XGetImportInfo(XImportInfo *ximage_info)
9765{
9766 assert(ximage_info != (XImportInfo *) NULL);
9767 ximage_info->frame=MagickFalse;
9768 ximage_info->borders=MagickFalse;
9769 ximage_info->screen=MagickFalse;
9770 ximage_info->descend=MagickTrue;
9771 ximage_info->silent=MagickFalse;
9772}