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