blob: a4edffbfa2052066789a9a9e97cbb1c3031bbc4f [file] [log] [blame]
cristy3ed852e2009-09-05 21:47:34 +00001/*
2%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3% %
4% %
5% %
6% X X W W IIIII N N DDDD OOO W W %
7% X X W W I NN N D D O O W W %
8% X W W I N N N D D O O W W %
9% X X W W W I N NN D D O O W W W %
10% X X W W IIIII N N DDDD OOO W W %
11% %
12% %
13% MagickCore X11 Utility Methods %
14% %
15% Software Design %
16% John Cristy %
17% July 1992 %
18% %
19% %
cristy7e41fe82010-12-04 23:12:08 +000020% Copyright 1999-2011 ImageMagick Studio LLC, a non-profit organization %
cristy3ed852e2009-09-05 21:47:34 +000021% dedicated to making software imaging solutions freely available. %
22% %
23% You may not use this file except in compliance with the License. You may %
24% obtain a copy of the License at %
25% %
26% http://www.imagemagick.org/script/license.php %
27% %
28% Unless required by applicable law or agreed to in writing, software %
29% distributed under the License is distributed on an "AS IS" BASIS, %
30% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. %
31% See the License for the specific language governing permissions and %
32% limitations under the License. %
33% %
34%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
35%
36%
37*/
38
39/*
40 Include declarations.
41*/
cristy4c08aed2011-07-01 19:47:50 +000042#include "MagickCore/studio.h"
43#include "MagickCore/animate.h"
44#include "MagickCore/artifact.h"
45#include "MagickCore/blob.h"
46#include "MagickCore/cache.h"
47#include "MagickCore/client.h"
48#include "MagickCore/color.h"
49#include "MagickCore/color-private.h"
50#include "MagickCore/colormap.h"
51#include "MagickCore/composite.h"
52#include "MagickCore/display.h"
53#include "MagickCore/exception.h"
54#include "MagickCore/exception-private.h"
55#include "MagickCore/geometry.h"
56#include "MagickCore/identify.h"
57#include "MagickCore/image.h"
58#include "MagickCore/image-private.h"
59#include "MagickCore/list.h"
60#include "MagickCore/locale_.h"
61#include "MagickCore/log.h"
62#include "MagickCore/magick.h"
63#include "MagickCore/memory_.h"
64#include "MagickCore/monitor.h"
65#include "MagickCore/option.h"
66#include "MagickCore/pixel-accessor.h"
67#include "MagickCore/PreRvIcccm.h"
68#include "MagickCore/quantize.h"
69#include "MagickCore/quantum.h"
70#include "MagickCore/quantum-private.h"
71#include "MagickCore/resource_.h"
72#include "MagickCore/resize.h"
73#include "MagickCore/shear.h"
74#include "MagickCore/statistic.h"
75#include "MagickCore/string_.h"
76#include "MagickCore/string-private.h"
77#include "MagickCore/transform.h"
78#include "MagickCore/utility.h"
cristyd1dd6e42011-09-04 01:46:08 +000079#include "MagickCore/utility-private.h"
cristy4c08aed2011-07-01 19:47:50 +000080#include "MagickCore/widget.h"
cristybcbda3f2011-09-03 13:01:22 +000081#include "MagickCore/widget-private.h"
cristy4c08aed2011-07-01 19:47:50 +000082#include "MagickCore/xwindow.h"
83#include "MagickCore/xwindow-private.h"
84#include "MagickCore/version.h"
cristy3ed852e2009-09-05 21:47:34 +000085#if defined(__BEOS__)
86#include <OS.h>
87#endif
88#if defined(MAGICKCORE_X11_DELEGATE)
89#include <X11/Xproto.h>
90#include <X11/Xlocale.h>
91#if defined(MAGICK_HAVE_POLL)
92# include <sys/poll.h>
93#endif
94#if defined(MAGICKCORE_HAVE_SHARED_MEMORY)
95#if defined(MAGICKCORE_HAVE_MACHINE_PARAM_H)
96# include <machine/param.h>
97#endif
98#include <sys/ipc.h>
99#include <sys/shm.h>
100#include <X11/extensions/XShm.h>
101#endif
102#if defined(MAGICKCORE_HAVE_SHAPE)
103#include <X11/extensions/shape.h>
104#endif
105
106/*
107 X defines.
108*/
cristyce70c172010-01-07 17:15:30 +0000109#define XBlueGamma(color) ClampToQuantum(blue_gamma == 1.0 ? (double) \
cristy3ed852e2009-09-05 21:47:34 +0000110 (color) : ((pow(((double) QuantumScale*(color)),1.0/(double) blue_gamma)* \
111 QuantumRange)))
cristy4c08aed2011-07-01 19:47:50 +0000112#define XGammaPacket(map,color) (size_t) (map->base_pixel+ \
cristy7e9f2332011-04-22 23:12:22 +0000113 ((ScaleQuantumToShort(XRedGamma((color)->red))*map->red_max/65535L)* \
114 map->red_mult)+ \
115 ((ScaleQuantumToShort(XGreenGamma((color)->green))*map->green_max/65535L)* \
116 map->green_mult)+ \
117 ((ScaleQuantumToShort(XBlueGamma((color)->blue))*map->blue_max/65535L)* \
118 map->blue_mult))
cristy4c08aed2011-07-01 19:47:50 +0000119#define XGammaPixel(image,map,color) (size_t) (map->base_pixel+ \
120 ((ScaleQuantumToShort(XRedGamma(GetPixelRed(image,color)))*map->red_max/65535L)* \
121 map->red_mult)+ \
122 ((ScaleQuantumToShort(XGreenGamma(GetPixelGreen(image,color)))*map->green_max/65535L)* \
123 map->green_mult)+ \
124 ((ScaleQuantumToShort(XBlueGamma(GetPixelBlue(image,color)))*map->blue_max/65535L)* \
125 map->blue_mult))
cristyce70c172010-01-07 17:15:30 +0000126#define XGreenGamma(color) ClampToQuantum(green_gamma == 1.0 ? (double) \
cristy3ed852e2009-09-05 21:47:34 +0000127 (color) : ((pow(((double) QuantumScale*(color)),1.0/(double) green_gamma)* \
128 QuantumRange)))
cristyce70c172010-01-07 17:15:30 +0000129#define XRedGamma(color) ClampToQuantum(red_gamma == 1.0 ? (double) \
cristy3ed852e2009-09-05 21:47:34 +0000130 (color) : ((pow(((double) QuantumScale*(color)),1.0/(double) red_gamma)* \
131 QuantumRange)))
cristybb503372010-05-27 20:51:26 +0000132#define XStandardPixel(map,color) (size_t) (map->base_pixel+ \
cristy7e9f2332011-04-22 23:12:22 +0000133 (((color)->red*map->red_max/65535L)*map->red_mult)+ \
134 (((color)->green*map->green_max/65535L)*map->green_mult)+ \
135 (((color)->blue*map->blue_max/65535L)*map->blue_mult))
cristy3ed852e2009-09-05 21:47:34 +0000136
137#define AccentuateModulate ScaleCharToQuantum(80)
138#define HighlightModulate ScaleCharToQuantum(125)
139#define ShadowModulate ScaleCharToQuantum(135)
140#define DepthModulate ScaleCharToQuantum(185)
141#define TroughModulate ScaleCharToQuantum(110)
142
143#define XLIB_ILLEGAL_ACCESS 1
144#undef ForgetGravity
145#undef NorthWestGravity
146#undef NorthGravity
147#undef NorthEastGravity
148#undef WestGravity
149#undef CenterGravity
150#undef EastGravity
151#undef SouthWestGravity
152#undef SouthGravity
153#undef SouthEastGravity
154#undef StaticGravity
155
156#undef index
157#if defined(hpux9)
158#define XFD_SET int
159#else
160#define XFD_SET fd_set
161#endif
162
163/*
164 Enumeration declarations.
165*/
166typedef enum
167{
168#undef DoRed
169 DoRed = 0x0001,
170#undef DoGreen
171 DoGreen = 0x0002,
172#undef DoBlue
173 DoBlue = 0x0004,
174 DoMatte = 0x0008
175} XColorFlags;
176
177/*
178 Typedef declarations.
179*/
180typedef struct _DiversityPacket
181{
182 Quantum
183 red,
184 green,
185 blue;
186
187 unsigned short
188 index;
189
cristybb503372010-05-27 20:51:26 +0000190 size_t
cristy3ed852e2009-09-05 21:47:34 +0000191 count;
192} DiversityPacket;
193
194/*
195 Constant declaractions.
196*/
197static MagickBooleanType
198 xerror_alert = MagickFalse;
199
200/*
201 Method prototypes.
202*/
203static const char
204 *XVisualClassName(const int);
205
206static MagickRealType
207 blue_gamma = 1.0,
208 green_gamma = 1.0,
209 red_gamma = 1.0;
210
211static MagickBooleanType
212 XMakePixmap(Display *,const XResourceInfo *,XWindowInfo *);
213
214static void
215 XMakeImageLSBFirst(const XResourceInfo *,const XWindowInfo *,Image *,
216 XImage *,XImage *),
217 XMakeImageMSBFirst(const XResourceInfo *,const XWindowInfo *,Image *,
218 XImage *,XImage *);
219
220static Window
221 XSelectWindow(Display *,RectangleInfo *);
222
223/*
224%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
225% %
226% %
227% %
228% D e s t r o y X R e s o u r c e s %
229% %
230% %
231% %
232%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
233%
234% DestroyXResources() destroys any X resources.
235%
236% The format of the DestroyXResources method is:
237%
238% void DestroyXResources()
239%
240% A description of each parameter follows:
241%
242*/
243MagickExport void DestroyXResources(void)
244{
245 register int
246 i;
247
248 unsigned int
249 number_windows;
250
251 XWindowInfo
252 *magick_windows[MaxXWindows];
253
254 XWindows
255 *windows;
256
257 DestroyXWidget();
258 windows=XSetWindows((XWindows *) ~0);
259 if ((windows == (XWindows *) NULL) || (windows->display == (Display *) NULL))
260 return;
261 number_windows=0;
262 magick_windows[number_windows++]=(&windows->context);
263 magick_windows[number_windows++]=(&windows->group_leader);
264 magick_windows[number_windows++]=(&windows->backdrop);
265 magick_windows[number_windows++]=(&windows->icon);
266 magick_windows[number_windows++]=(&windows->image);
267 magick_windows[number_windows++]=(&windows->info);
268 magick_windows[number_windows++]=(&windows->magnify);
269 magick_windows[number_windows++]=(&windows->pan);
270 magick_windows[number_windows++]=(&windows->command);
271 magick_windows[number_windows++]=(&windows->widget);
272 magick_windows[number_windows++]=(&windows->popup);
273 magick_windows[number_windows++]=(&windows->context);
274 for (i=0; i < (int) number_windows; i++)
275 {
276 if (magick_windows[i]->mapped != MagickFalse)
277 {
278 (void) XWithdrawWindow(windows->display,magick_windows[i]->id,
279 magick_windows[i]->screen);
280 magick_windows[i]->mapped=MagickFalse;
281 }
282 if (magick_windows[i]->name != (char *) NULL)
283 magick_windows[i]->name=(char *)
284 RelinquishMagickMemory(magick_windows[i]->name);
285 if (magick_windows[i]->icon_name != (char *) NULL)
286 magick_windows[i]->icon_name=(char *)
287 RelinquishMagickMemory(magick_windows[i]->icon_name);
288 if (magick_windows[i]->cursor != (Cursor) NULL)
289 {
290 (void) XFreeCursor(windows->display,magick_windows[i]->cursor);
291 magick_windows[i]->cursor=(Cursor) NULL;
292 }
293 if (magick_windows[i]->busy_cursor != (Cursor) NULL)
294 {
295 (void) XFreeCursor(windows->display,magick_windows[i]->busy_cursor);
296 magick_windows[i]->busy_cursor=(Cursor) NULL;
297 }
298 if (magick_windows[i]->highlight_stipple != (Pixmap) NULL)
299 {
300 (void) XFreePixmap(windows->display,
301 magick_windows[i]->highlight_stipple);
302 magick_windows[i]->highlight_stipple=(Pixmap) NULL;
303 }
304 if (magick_windows[i]->shadow_stipple != (Pixmap) NULL)
305 {
306 (void) XFreePixmap(windows->display,magick_windows[i]->shadow_stipple);
307 magick_windows[i]->shadow_stipple=(Pixmap) NULL;
308 }
309 if (magick_windows[i]->ximage != (XImage *) NULL)
310 {
311 XDestroyImage(magick_windows[i]->ximage);
312 magick_windows[i]->ximage=(XImage *) NULL;
313 }
314 if (magick_windows[i]->pixmap != (Pixmap) NULL)
315 {
316 (void) XFreePixmap(windows->display,magick_windows[i]->pixmap);
317 magick_windows[i]->pixmap=(Pixmap) NULL;
318 }
319 if (magick_windows[i]->id != (Window) NULL)
320 {
321 (void) XDestroyWindow(windows->display,magick_windows[i]->id);
322 magick_windows[i]->id=(Window) NULL;
323 }
324 if (magick_windows[i]->destroy != MagickFalse)
325 {
326 if (magick_windows[i]->image != (Image *) NULL)
327 {
328 magick_windows[i]->image=DestroyImage(magick_windows[i]->image);
329 magick_windows[i]->image=NewImageList();
330 }
331 if (magick_windows[i]->matte_pixmap != (Pixmap) NULL)
332 {
333 (void) XFreePixmap(windows->display,
334 magick_windows[i]->matte_pixmap);
335 magick_windows[i]->matte_pixmap=(Pixmap) NULL;
336 }
337 }
338 if (magick_windows[i]->segment_info != (void *) NULL)
339 {
340#if defined(MAGICKCORE_HAVE_SHARED_MEMORY)
341 XShmSegmentInfo
342 *segment_info;
343
344 segment_info=(XShmSegmentInfo *) magick_windows[i]->segment_info;
345 if (segment_info != (XShmSegmentInfo *) NULL)
346 if (segment_info[0].shmid >= 0)
347 {
348 if (segment_info[0].shmaddr != NULL)
349 (void) shmdt(segment_info[0].shmaddr);
350 (void) shmctl(segment_info[0].shmid,IPC_RMID,0);
351 segment_info[0].shmaddr=NULL;
352 segment_info[0].shmid=(-1);
353 }
354#endif
355 magick_windows[i]->segment_info=(void *)
356 RelinquishMagickMemory(magick_windows[i]->segment_info);
357 }
358 }
359 windows->icon_resources=(XResourceInfo *)
360 RelinquishMagickMemory(windows->icon_resources);
361 if (windows->icon_pixel != (XPixelInfo *) NULL)
362 {
cristyf2faecf2010-05-28 19:19:36 +0000363 if (windows->icon_pixel->pixels != (unsigned long *) NULL)
364 windows->icon_pixel->pixels=(unsigned long *)
cristy3ed852e2009-09-05 21:47:34 +0000365 RelinquishMagickMemory(windows->icon_pixel->pixels);
366 if (windows->icon_pixel->annotate_context != (GC) NULL)
367 XFreeGC(windows->display,windows->icon_pixel->annotate_context);
368 windows->icon_pixel=(XPixelInfo *)
369 RelinquishMagickMemory(windows->icon_pixel);
370 }
371 if (windows->pixel_info != (XPixelInfo *) NULL)
372 {
cristyf2faecf2010-05-28 19:19:36 +0000373 if (windows->pixel_info->pixels != (unsigned long *) NULL)
374 windows->pixel_info->pixels=(unsigned long *)
cristy3ed852e2009-09-05 21:47:34 +0000375 RelinquishMagickMemory(windows->pixel_info->pixels);
376 if (windows->pixel_info->annotate_context != (GC) NULL)
377 XFreeGC(windows->display,windows->pixel_info->annotate_context);
378 if (windows->pixel_info->widget_context != (GC) NULL)
379 XFreeGC(windows->display,windows->pixel_info->widget_context);
380 if (windows->pixel_info->highlight_context != (GC) NULL)
381 XFreeGC(windows->display,windows->pixel_info->highlight_context);
382 windows->pixel_info=(XPixelInfo *)
383 RelinquishMagickMemory(windows->pixel_info);
384 }
385 if (windows->font_info != (XFontStruct *) NULL)
386 {
387 XFreeFont(windows->display,windows->font_info);
388 windows->font_info=(XFontStruct *) NULL;
389 }
390 if (windows->class_hints != (XClassHint *) NULL)
391 {
cristyc9cc4a72011-09-18 02:12:41 +0000392 if (windows->class_hints->res_name != (char *) NULL)
393 windows->class_hints->res_name=DestroyString(
394 windows->class_hints->res_name);
395 if (windows->class_hints->res_class != (char *) NULL)
396 windows->class_hints->res_class=DestroyString(
397 windows->class_hints->res_class);
cristy3ed852e2009-09-05 21:47:34 +0000398 XFree(windows->class_hints);
399 windows->class_hints=(XClassHint *) NULL;
400 }
401 if (windows->manager_hints != (XWMHints *) NULL)
402 {
403 XFree(windows->manager_hints);
404 windows->manager_hints=(XWMHints *) NULL;
405 }
406 if (windows->map_info != (XStandardColormap *) NULL)
407 {
408 XFree(windows->map_info);
409 windows->map_info=(XStandardColormap *) NULL;
410 }
411 if (windows->icon_map != (XStandardColormap *) NULL)
412 {
413 XFree(windows->icon_map);
414 windows->icon_map=(XStandardColormap *) NULL;
415 }
416 if (windows->visual_info != (XVisualInfo *) NULL)
417 {
418 XFree(windows->visual_info);
419 windows->visual_info=(XVisualInfo *) NULL;
420 }
421 if (windows->icon_visual != (XVisualInfo *) NULL)
422 {
423 XFree(windows->icon_visual);
424 windows->icon_visual=(XVisualInfo *) NULL;
425 }
426 (void) XSetWindows((XWindows *) NULL);
427}
428
429/*
430%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
431% %
432% %
433% %
434% X A n n o t a t e I m a g e %
435% %
436% %
437% %
438%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
439%
440% XAnnotateImage() annotates the image with text.
441%
442% The format of the XAnnotateImage method is:
443%
444% MagickBooleanType XAnnotateImage(Display *display,
445% const XPixelInfo *pixel,XAnnotateInfo *annotate_info,Image *image)
446%
447% A description of each parameter follows:
448%
449% o display: Specifies a connection to an X server; returned from
450% XOpenDisplay.
451%
452% o pixel: Specifies a pointer to a XPixelInfo structure.
453%
454% o annotate_info: Specifies a pointer to a XAnnotateInfo structure.
455%
456% o image: the image.
457%
458*/
cristybcbda3f2011-09-03 13:01:22 +0000459MagickPrivate MagickBooleanType XAnnotateImage(Display *display,
cristy3ed852e2009-09-05 21:47:34 +0000460 const XPixelInfo *pixel,XAnnotateInfo *annotate_info,Image *image)
461{
cristyc57f6942010-11-12 01:47:39 +0000462 CacheView
463 *annotate_view;
464
cristy3ed852e2009-09-05 21:47:34 +0000465 GC
466 annotate_context;
467
468 ExceptionInfo
469 *exception;
470
471 Image
472 *annotate_image;
473
474 int
475 x,
476 y;
477
478 MagickBooleanType
479 matte;
480
481 Pixmap
482 annotate_pixmap;
483
484 unsigned int
485 depth,
486 height,
487 width;
488
489 Window
490 root_window;
491
492 XGCValues
493 context_values;
494
495 XImage
496 *annotate_ximage;
497
498 /*
499 Initialize annotated image.
500 */
501 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
502 assert(display != (Display *) NULL);
503 assert(pixel != (XPixelInfo *) NULL);
504 assert(annotate_info != (XAnnotateInfo *) NULL);
505 assert(image != (Image *) NULL);
506 /*
507 Initialize annotated pixmap.
508 */
509 root_window=XRootWindow(display,XDefaultScreen(display));
510 depth=(unsigned int) XDefaultDepth(display,XDefaultScreen(display));
511 annotate_pixmap=XCreatePixmap(display,root_window,annotate_info->width,
512 annotate_info->height,depth);
513 if (annotate_pixmap == (Pixmap) NULL)
514 return(MagickFalse);
515 /*
516 Initialize graphics info.
517 */
518 context_values.background=0;
cristybb503372010-05-27 20:51:26 +0000519 context_values.foreground=(size_t) (~0);
cristy3ed852e2009-09-05 21:47:34 +0000520 context_values.font=annotate_info->font_info->fid;
cristyc57f6942010-11-12 01:47:39 +0000521 annotate_context=XCreateGC(display,root_window,(unsigned long)
522 (GCBackground | GCFont | GCForeground),&context_values);
cristy3ed852e2009-09-05 21:47:34 +0000523 if (annotate_context == (GC) NULL)
524 return(MagickFalse);
525 /*
526 Draw text to pixmap.
527 */
528 (void) XDrawImageString(display,annotate_pixmap,annotate_context,0,
529 (int) annotate_info->font_info->ascent,annotate_info->text,
530 (int) strlen(annotate_info->text));
531 (void) XFreeGC(display,annotate_context);
532 /*
533 Initialize annotated X image.
534 */
535 annotate_ximage=XGetImage(display,annotate_pixmap,0,0,annotate_info->width,
536 annotate_info->height,AllPlanes,ZPixmap);
537 if (annotate_ximage == (XImage *) NULL)
538 return(MagickFalse);
539 (void) XFreePixmap(display,annotate_pixmap);
540 /*
541 Initialize annotated image.
542 */
543 annotate_image=AcquireImage((ImageInfo *) NULL);
544 if (annotate_image == (Image *) NULL)
545 return(MagickFalse);
546 annotate_image->columns=annotate_info->width;
547 annotate_image->rows=annotate_info->height;
548 /*
549 Transfer annotated X image to image.
550 */
551 width=(unsigned int) image->columns;
552 height=(unsigned int) image->rows;
553 x=0;
554 y=0;
555 (void) XParseGeometry(annotate_info->geometry,&x,&y,&width,&height);
cristyc57f6942010-11-12 01:47:39 +0000556 (void) GetOneVirtualPixel(image,(ssize_t) x,(ssize_t) y,
557 &annotate_image->background_color,&image->exception);
cristy3ed852e2009-09-05 21:47:34 +0000558 if (annotate_info->stencil == ForegroundStencil)
559 annotate_image->matte=MagickTrue;
560 exception=(&image->exception);
cristyc57f6942010-11-12 01:47:39 +0000561 annotate_view=AcquireCacheView(annotate_image);
cristy3ed852e2009-09-05 21:47:34 +0000562 for (y=0; y < (int) annotate_image->rows; y++)
563 {
cristyc57f6942010-11-12 01:47:39 +0000564 register int
cristy3ed852e2009-09-05 21:47:34 +0000565 x;
566
cristy4c08aed2011-07-01 19:47:50 +0000567 register Quantum
cristyc47d1f82009-11-26 01:44:43 +0000568 *restrict q;
cristy3ed852e2009-09-05 21:47:34 +0000569
cristyc57f6942010-11-12 01:47:39 +0000570 q=GetCacheViewAuthenticPixels(annotate_view,0,(ssize_t) y,
571 annotate_image->columns,1,exception);
cristyacd2ed22011-08-30 01:44:23 +0000572 if (q == (Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +0000573 break;
cristyc57f6942010-11-12 01:47:39 +0000574 for (x=0; x < (int) annotate_image->columns; x++)
cristy3ed852e2009-09-05 21:47:34 +0000575 {
cristy4c08aed2011-07-01 19:47:50 +0000576 SetPixelAlpha(annotate_image,OpaqueAlpha,q);
cristy3ed852e2009-09-05 21:47:34 +0000577 if (XGetPixel(annotate_ximage,x,y) == 0)
578 {
579 /*
580 Set this pixel to the background color.
581 */
cristy4c08aed2011-07-01 19:47:50 +0000582 SetPixelRed(annotate_image,ScaleShortToQuantum(
583 pixel->box_color.red),q);
584 SetPixelGreen(annotate_image,ScaleShortToQuantum(
585 pixel->box_color.green),q);
586 SetPixelBlue(annotate_image,ScaleShortToQuantum(
587 pixel->box_color.blue),q);
cristy3ed852e2009-09-05 21:47:34 +0000588 if ((annotate_info->stencil == ForegroundStencil) ||
589 (annotate_info->stencil == OpaqueStencil))
cristy4c08aed2011-07-01 19:47:50 +0000590 SetPixelAlpha(annotate_image,TransparentAlpha,q);
cristy3ed852e2009-09-05 21:47:34 +0000591 }
592 else
593 {
594 /*
595 Set this pixel to the pen color.
596 */
cristy4c08aed2011-07-01 19:47:50 +0000597 SetPixelRed(annotate_image,ScaleShortToQuantum(
598 pixel->pen_color.red),q);
599 SetPixelGreen(annotate_image,ScaleShortToQuantum(
600 pixel->pen_color.green),q);
601 SetPixelBlue(annotate_image,ScaleShortToQuantum(
602 pixel->pen_color.blue),q);
cristy3ed852e2009-09-05 21:47:34 +0000603 if (annotate_info->stencil == BackgroundStencil)
cristy4c08aed2011-07-01 19:47:50 +0000604 SetPixelAlpha(annotate_image,TransparentAlpha,q);
cristy3ed852e2009-09-05 21:47:34 +0000605 }
cristyed231572011-07-14 02:18:59 +0000606 q+=GetPixelChannels(annotate_image);
cristy3ed852e2009-09-05 21:47:34 +0000607 }
cristyc57f6942010-11-12 01:47:39 +0000608 if (SyncCacheViewAuthenticPixels(annotate_view,exception) == MagickFalse)
cristy3ed852e2009-09-05 21:47:34 +0000609 break;
610 }
cristyc57f6942010-11-12 01:47:39 +0000611 annotate_view=DestroyCacheView(annotate_view);
cristy3ed852e2009-09-05 21:47:34 +0000612 XDestroyImage(annotate_ximage);
613 /*
614 Determine annotate geometry.
615 */
616 (void) XParseGeometry(annotate_info->geometry,&x,&y,&width,&height);
617 if ((width != (unsigned int) annotate_image->columns) ||
618 (height != (unsigned int) annotate_image->rows))
619 {
620 char
621 image_geometry[MaxTextExtent];
622
623 /*
624 Scale image.
625 */
cristyb51dff52011-05-19 16:55:47 +0000626 (void) FormatLocaleString(image_geometry,MaxTextExtent,"%ux%u",
cristy3ed852e2009-09-05 21:47:34 +0000627 width,height);
628 (void) TransformImage(&annotate_image,(char *) NULL,image_geometry);
629 }
630 if (annotate_info->degrees != 0.0)
631 {
632 Image
633 *rotate_image;
634
635 int
636 rotations;
637
638 MagickRealType
639 normalized_degrees;
640
641 /*
642 Rotate image.
643 */
644 rotate_image=
645 RotateImage(annotate_image,annotate_info->degrees,&image->exception);
646 if (rotate_image == (Image *) NULL)
647 return(MagickFalse);
648 annotate_image=DestroyImage(annotate_image);
649 annotate_image=rotate_image;
650 /*
651 Annotation is relative to the degree of rotation.
652 */
653 normalized_degrees=annotate_info->degrees;
654 while (normalized_degrees < -45.0)
655 normalized_degrees+=360.0;
656 for (rotations=0; normalized_degrees > 45.0; rotations++)
657 normalized_degrees-=90.0;
658 switch (rotations % 4)
659 {
660 default:
661 case 0:
662 break;
663 case 1:
664 {
665 /*
666 Rotate 90 degrees.
667 */
668 x-=(int) annotate_image->columns/2;
669 y+=(int) annotate_image->columns/2;
670 break;
671 }
672 case 2:
673 {
674 /*
675 Rotate 180 degrees.
676 */
677 x=x-(int) annotate_image->columns;
678 break;
679 }
680 case 3:
681 {
682 /*
683 Rotate 270 degrees.
684 */
685 x=x-(int) annotate_image->columns/2;
686 y=y-(int) (annotate_image->rows-(annotate_image->columns/2));
687 break;
688 }
689 }
690 }
691 /*
692 Composite text onto the image.
693 */
694 (void) XParseGeometry(annotate_info->geometry,&x,&y,&width,&height);
695 matte=image->matte;
696 (void) CompositeImage(image,annotate_image->matte != MagickFalse ?
cristyc57f6942010-11-12 01:47:39 +0000697 OverCompositeOp : CopyCompositeOp,annotate_image,(ssize_t) x,(ssize_t) y);
cristy3ed852e2009-09-05 21:47:34 +0000698 image->matte=matte;
699 annotate_image=DestroyImage(annotate_image);
700 return(MagickTrue);
701}
702
703/*
704%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
705% %
706% %
707% %
708% X B e s t F o n t %
709% %
710% %
711% %
712%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
713%
714% XBestFont() returns the "best" font. "Best" is defined as a font specified
715% in the X resource database or a font such that the text width displayed
716% with the font does not exceed the specified maximum width.
717%
718% The format of the XBestFont method is:
719%
720% XFontStruct *XBestFont(Display *display,
721% const XResourceInfo *resource_info,const MagickBooleanType text_font)
722%
723% A description of each parameter follows:
724%
725% o font: XBestFont returns a pointer to a XFontStruct structure.
726%
727% o display: Specifies a connection to an X server; returned from
728% XOpenDisplay.
729%
730% o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
731%
732% o text_font: True is font should be mono-spaced (typewriter style).
733%
cristy3ed852e2009-09-05 21:47:34 +0000734*/
735
736static char **FontToList(char *font)
737{
738 char
739 **fontlist;
740
741 register char
742 *p,
743 *q;
744
745 register int
746 i;
747
748 unsigned int
749 fonts;
750
751 if (font == (char *) NULL)
752 return((char **) NULL);
753 /*
754 Convert string to an ASCII list.
755 */
756 fonts=1U;
757 for (p=font; *p != '\0'; p++)
758 if ((*p == ':') || (*p == ';') || (*p == ','))
759 fonts++;
760 fontlist=(char **) AcquireQuantumMemory((size_t) fonts+1UL,sizeof(*fontlist));
761 if (fontlist == (char **) NULL)
762 {
763 ThrowXWindowFatalException(ResourceLimitError,"MemoryAllocationFailed",
764 font);
765 return((char **) NULL);
766 }
767 p=font;
768 for (i=0; i < (int) fonts; i++)
769 {
770 for (q=p; *q != '\0'; q++)
771 if ((*q == ':') || (*q == ';') || (*q == ','))
772 break;
773 fontlist[i]=(char *) AcquireQuantumMemory((size_t) (q-p)+1UL,
774 sizeof(*fontlist[i]));
775 if (fontlist[i] == (char *) NULL)
776 {
777 ThrowXWindowFatalException(ResourceLimitError,"MemoryAllocationFailed",
778 font);
779 return((char **) NULL);
780 }
781 (void) CopyMagickString(fontlist[i],p,(size_t) (q-p+1));
782 p=q+1;
783 }
784 fontlist[i]=(char *) NULL;
785 return(fontlist);
786}
787
cristybcbda3f2011-09-03 13:01:22 +0000788MagickPrivate XFontStruct *XBestFont(Display *display,
cristy3ed852e2009-09-05 21:47:34 +0000789 const XResourceInfo *resource_info,const MagickBooleanType text_font)
790{
791 static const char
792 *Fonts[]=
793 {
794 "-*-helvetica-medium-r-normal--12-*-*-*-*-*-iso8859-1",
795 "-*-arial-medium-r-normal--12-*-*-*-*-*-iso8859-1",
796 "-*-helvetica-medium-r-normal--12-*-*-*-*-*-iso8859-15",
797 "-*-arial-medium-r-normal--12-*-*-*-*-*-iso8859-15",
798 "-*-helvetica-medium-r-normal--12-*-*-*-*-*-*-*",
799 "-*-arial-medium-r-normal--12-*-*-*-*-*-*-*",
800 "variable",
801 "fixed",
802 (char *) NULL
803 },
804 *TextFonts[]=
805 {
806 "-*-courier-medium-r-normal-*-12-*-*-*-*-*-iso8859-1",
807 "-*-courier-medium-r-normal-*-12-*-*-*-*-*-iso8859-15",
808 "-*-fixed-medium-r-normal-*-12-*-*-*-*-*-*-*",
809 "fixed",
810 (char *) NULL
811 };
812
813 char
814 *font_name;
815
816 register const char
817 **p;
818
819 XFontStruct
820 *font_info;
821
822 font_info=(XFontStruct *) NULL;
823 font_name=resource_info->font;
824 if (text_font != MagickFalse)
825 font_name=resource_info->text_font;
826 if ((font_name != (char *) NULL) && (*font_name != '\0'))
827 {
828 char
829 **fontlist;
830
831 register int
832 i;
833
834 /*
835 Load preferred font specified in the X resource database.
836 */
837 fontlist=FontToList(font_name);
838 if (fontlist != (char **) NULL)
839 {
840 for (i=0; fontlist[i] != (char *) NULL; i++)
841 {
842 if (font_info == (XFontStruct *) NULL)
843 font_info=XLoadQueryFont(display,fontlist[i]);
844 fontlist[i]=DestroyString(fontlist[i]);
845 }
846 fontlist=(char **) RelinquishMagickMemory(fontlist);
847 }
848 if (font_info == (XFontStruct *) NULL)
849 ThrowXWindowFatalException(XServerError,"UnableToLoadFont",font_name);
850 }
851 /*
852 Load fonts from list of fonts until one is found.
853 */
854 p=Fonts;
855 if (text_font != MagickFalse)
856 p=TextFonts;
857 if (XDisplayHeight(display,XDefaultScreen(display)) >= 748)
858 p++;
859 while (*p != (char *) NULL)
860 {
861 if (font_info != (XFontStruct *) NULL)
862 break;
863 font_info=XLoadQueryFont(display,(char *) *p);
864 p++;
865 }
866 return(font_info);
867}
868
869/*
870%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
871% %
872% %
873% %
874% X B e s t I c o n S i z e %
875% %
876% %
877% %
878%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
879%
880% XBestIconSize() returns the "best" icon size. "Best" is defined as an icon
881% size that maintains the aspect ratio of the image. If the window manager
882% has preferred icon sizes, one of the preferred sizes is used.
883%
884% The format of the XBestIconSize method is:
885%
886% void XBestIconSize(Display *display,XWindowInfo *window,Image *image)
887%
888% A description of each parameter follows:
889%
890% o display: Specifies a connection to an X server; returned from
891% XOpenDisplay.
892%
893% o image: the image.
894%
895*/
cristybcbda3f2011-09-03 13:01:22 +0000896MagickPrivate void XBestIconSize(Display *display,XWindowInfo *window,
cristy3ed852e2009-09-05 21:47:34 +0000897 Image *image)
898{
899 int
900 i,
901 number_sizes;
902
903 MagickRealType
904 scale_factor;
905
906 unsigned int
907 height,
908 icon_height,
909 icon_width,
910 width;
911
912 Window
913 root_window;
914
915 XIconSize
916 *icon_size,
917 *size_list;
918
919 /*
920 Determine if the window manager has specified preferred icon sizes.
921 */
922 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
923 assert(display != (Display *) NULL);
924 assert(window != (XWindowInfo *) NULL);
925 assert(image != (Image *) NULL);
926 window->width=MaxIconSize;
927 window->height=MaxIconSize;
928 icon_size=(XIconSize *) NULL;
929 number_sizes=0;
930 root_window=XRootWindow(display,window->screen);
931 if (XGetIconSizes(display,root_window,&size_list,&number_sizes) != 0)
932 if ((number_sizes > 0) && (size_list != (XIconSize *) NULL))
933 icon_size=size_list;
934 if (icon_size == (XIconSize *) NULL)
935 {
936 /*
937 Window manager does not restrict icon size.
938 */
939 icon_size=XAllocIconSize();
940 if (icon_size == (XIconSize *) NULL)
941 {
942 ThrowXWindowFatalException(ResourceLimitError,
943 "MemoryAllocationFailed",image->filename);
944 return;
945 }
946 icon_size->min_width=1;
947 icon_size->max_width=MaxIconSize;
948 icon_size->min_height=1;
949 icon_size->max_height=MaxIconSize;
950 icon_size->width_inc=1;
951 icon_size->height_inc=1;
952 }
953 /*
954 Determine aspect ratio of image.
955 */
956 width=(unsigned int) image->columns;
957 height=(unsigned int) image->rows;
958 i=0;
959 if (window->crop_geometry)
960 (void) XParseGeometry(window->crop_geometry,&i,&i,&width,&height);
961 /*
962 Look for an icon size that maintains the aspect ratio of image.
963 */
964 scale_factor=(MagickRealType) icon_size->max_width/width;
965 if (scale_factor > ((MagickRealType) icon_size->max_height/height))
966 scale_factor=(MagickRealType) icon_size->max_height/height;
967 icon_width=(unsigned int) icon_size->min_width;
968 while ((int) icon_width < icon_size->max_width)
969 {
970 if (icon_width >= (unsigned int) (scale_factor*width+0.5))
971 break;
972 icon_width+=icon_size->width_inc;
973 }
974 icon_height=(unsigned int) icon_size->min_height;
975 while ((int) icon_height < icon_size->max_height)
976 {
977 if (icon_height >= (unsigned int) (scale_factor*height+0.5))
978 break;
979 icon_height+=icon_size->height_inc;
980 }
981 (void) XFree((void *) icon_size);
982 window->width=icon_width;
983 window->height=icon_height;
984}
985
986/*
987%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
988% %
989% %
990% %
991% X B e s t P i x e l %
992% %
993% %
994% %
995%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
996%
997% XBestPixel() returns a pixel from an array of pixels that is closest to the
998% requested color. If the color array is NULL, the colors are obtained from
999% the X server.
1000%
1001% The format of the XBestPixel method is:
1002%
1003% void XBestPixel(Display *display,const Colormap colormap,XColor *colors,
1004% unsigned int number_colors,XColor *color)
1005%
1006% A description of each parameter follows:
1007%
1008% o pixel: XBestPixel returns the pixel value closest to the requested
1009% color.
1010%
1011% o display: Specifies a connection to an X server; returned from
1012% XOpenDisplay.
1013%
1014% o colormap: Specifies the ID of the X server colormap.
1015%
1016% o colors: Specifies an array of XColor structures.
1017%
1018% o number_colors: Specifies the number of XColor structures in the
1019% color definition array.
1020%
1021% o color: Specifies the desired RGB value to find in the colors array.
1022%
1023*/
cristybcbda3f2011-09-03 13:01:22 +00001024MagickPrivate void XBestPixel(Display *display,const Colormap colormap,
cristy3ed852e2009-09-05 21:47:34 +00001025 XColor *colors,unsigned int number_colors,XColor *color)
1026{
1027 MagickBooleanType
1028 query_server;
1029
cristy4c08aed2011-07-01 19:47:50 +00001030 PixelInfo
cristy3ed852e2009-09-05 21:47:34 +00001031 pixel;
1032
1033 MagickRealType
1034 min_distance;
1035
1036 register MagickRealType
1037 distance;
1038
1039 register int
1040 i,
1041 j;
1042
1043 Status
1044 status;
1045
1046 /*
1047 Find closest representation for the requested RGB color.
1048 */
1049 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
1050 assert(display != (Display *) NULL);
1051 assert(color != (XColor *) NULL);
1052 status=XAllocColor(display,colormap,color);
1053 if (status != False)
1054 return;
1055 query_server=colors == (XColor *) NULL ? MagickTrue : MagickFalse;
1056 if (query_server != MagickFalse)
1057 {
1058 /*
1059 Read X server colormap.
1060 */
1061 colors=(XColor *) AcquireQuantumMemory(number_colors,sizeof(*colors));
1062 if (colors == (XColor *) NULL)
1063 {
1064 ThrowXWindowFatalException(ResourceLimitError,
1065 "MemoryAllocationFailed","...");
1066 return;
1067 }
1068 for (i=0; i < (int) number_colors; i++)
cristybb503372010-05-27 20:51:26 +00001069 colors[i].pixel=(size_t) i;
cristy3ed852e2009-09-05 21:47:34 +00001070 if (number_colors > 256)
1071 number_colors=256;
1072 (void) XQueryColors(display,colormap,colors,(int) number_colors);
1073 }
1074 min_distance=3.0*((MagickRealType) QuantumRange+1.0)*((MagickRealType)
1075 QuantumRange+1.0);
1076 j=0;
1077 for (i=0; i < (int) number_colors; i++)
1078 {
1079 pixel.red=colors[i].red-(MagickRealType) color->red;
1080 distance=pixel.red*pixel.red;
1081 if (distance > min_distance)
1082 continue;
1083 pixel.green=colors[i].green-(MagickRealType) color->green;
1084 distance+=pixel.green*pixel.green;
1085 if (distance > min_distance)
1086 continue;
1087 pixel.blue=colors[i].blue-(MagickRealType) color->blue;
1088 distance+=pixel.blue*pixel.blue;
1089 if (distance > min_distance)
1090 continue;
1091 min_distance=distance;
1092 color->pixel=colors[i].pixel;
1093 j=i;
1094 }
1095 (void) XAllocColor(display,colormap,&colors[j]);
1096 if (query_server != MagickFalse)
1097 colors=(XColor *) RelinquishMagickMemory(colors);
1098}
1099
1100/*
1101%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1102% %
1103% %
1104% %
1105% X B e s t V i s u a l I n f o %
1106% %
1107% %
1108% %
1109%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1110%
1111% XBestVisualInfo() returns visual information for a visual that is the "best"
1112% the server supports. "Best" is defined as:
1113%
1114% 1. Restrict the visual list to those supported by the default screen.
1115%
1116% 2. If a visual type is specified, restrict the visual list to those of
1117% that type.
1118%
1119% 3. If a map type is specified, choose the visual that matches the id
1120% specified by the Standard Colormap.
1121%
1122% 4 From the list of visuals, choose one that can display the most
1123% simultaneous colors. If more than one visual can display the same
1124% number of simultaneous colors, one is chosen based on a rank.
1125%
1126% The format of the XBestVisualInfo method is:
1127%
1128% XVisualInfo *XBestVisualInfo(Display *display,
1129% XStandardColormap *map_info,XResourceInfo *resource_info)
1130%
1131% A description of each parameter follows:
1132%
1133% o visual_info: XBestVisualInfo returns a pointer to a X11 XVisualInfo
1134% structure.
1135%
1136% o display: Specifies a connection to an X server; returned from
1137% XOpenDisplay.
1138%
1139% o map_info: If map_type is specified, this structure is initialized
1140% with info from the Standard Colormap.
1141%
1142% o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
1143%
1144*/
1145
1146static inline int MagickMax(const int x,const int y)
1147{
1148 if (x > y)
1149 return(x);
1150 return(y);
1151}
1152
cristybb503372010-05-27 20:51:26 +00001153static inline size_t MagickMin(const unsigned int x,
cristy3ed852e2009-09-05 21:47:34 +00001154 const unsigned int y)
1155{
1156 if (x < y)
1157 return(x);
1158 return(y);
1159}
1160
cristybcbda3f2011-09-03 13:01:22 +00001161MagickPrivate XVisualInfo *XBestVisualInfo(Display *display,
cristy3ed852e2009-09-05 21:47:34 +00001162 XStandardColormap *map_info,XResourceInfo *resource_info)
1163{
1164#define MaxStandardColormaps 7
1165#define XVisualColormapSize(visual_info) MagickMin((unsigned int) (\
1166 (visual_info->klass == TrueColor) || (visual_info->klass == DirectColor) ? \
1167 visual_info->red_mask | visual_info->green_mask | visual_info->blue_mask : \
1168 (unsigned int) visual_info->colormap_size),1U << visual_info->depth)
1169
1170 char
1171 *map_type,
1172 *visual_type;
1173
cristyc57f6942010-11-12 01:47:39 +00001174 int
1175 visual_mask;
1176
cristy3ed852e2009-09-05 21:47:34 +00001177 register int
1178 i;
1179
cristy8891f9c2010-06-04 23:32:17 +00001180 size_t
1181 one;
1182
cristy3ed852e2009-09-05 21:47:34 +00001183 static int
1184 number_visuals;
1185
1186 static XVisualInfo
1187 visual_template;
1188
1189 XVisualInfo
1190 *visual_info,
1191 *visual_list;
1192
1193 /*
1194 Restrict visual search by screen number.
1195 */
1196 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
1197 assert(display != (Display *) NULL);
1198 assert(map_info != (XStandardColormap *) NULL);
1199 assert(resource_info != (XResourceInfo *) NULL);
1200 map_type=resource_info->map_type;
1201 visual_type=resource_info->visual_type;
1202 visual_mask=VisualScreenMask;
1203 visual_template.screen=XDefaultScreen(display);
1204 visual_template.depth=XDefaultDepth(display,XDefaultScreen(display));
cristy8891f9c2010-06-04 23:32:17 +00001205 one=1;
cristy3ed852e2009-09-05 21:47:34 +00001206 if ((resource_info->immutable != MagickFalse) && (resource_info->colors != 0))
cristy8891f9c2010-06-04 23:32:17 +00001207 if (resource_info->colors <= (one << (size_t) visual_template.depth))
cristy3ed852e2009-09-05 21:47:34 +00001208 visual_mask|=VisualDepthMask;
1209 if (visual_type != (char *) NULL)
1210 {
1211 /*
1212 Restrict visual search by class or visual id.
1213 */
1214 if (LocaleCompare("staticgray",visual_type) == 0)
1215 {
1216 visual_mask|=VisualClassMask;
1217 visual_template.klass=StaticGray;
1218 }
1219 else
1220 if (LocaleCompare("grayscale",visual_type) == 0)
1221 {
1222 visual_mask|=VisualClassMask;
1223 visual_template.klass=GrayScale;
1224 }
1225 else
1226 if (LocaleCompare("staticcolor",visual_type) == 0)
1227 {
1228 visual_mask|=VisualClassMask;
1229 visual_template.klass=StaticColor;
1230 }
1231 else
1232 if (LocaleCompare("pseudocolor",visual_type) == 0)
1233 {
1234 visual_mask|=VisualClassMask;
1235 visual_template.klass=PseudoColor;
1236 }
1237 else
1238 if (LocaleCompare("truecolor",visual_type) == 0)
1239 {
1240 visual_mask|=VisualClassMask;
1241 visual_template.klass=TrueColor;
1242 }
1243 else
1244 if (LocaleCompare("directcolor",visual_type) == 0)
1245 {
1246 visual_mask|=VisualClassMask;
1247 visual_template.klass=DirectColor;
1248 }
1249 else
1250 if (LocaleCompare("default",visual_type) == 0)
1251 {
1252 visual_mask|=VisualIDMask;
1253 visual_template.visualid=XVisualIDFromVisual(
1254 XDefaultVisual(display,XDefaultScreen(display)));
1255 }
1256 else
1257 if (isdigit((int) ((unsigned char) *visual_type)) != 0)
1258 {
1259 visual_mask|=VisualIDMask;
1260 visual_template.visualid=
1261 strtol(visual_type,(char **) NULL,0);
1262 }
1263 else
1264 ThrowXWindowFatalException(XServerError,
1265 "UnrecognizedVisualSpecifier",visual_type);
1266 }
1267 /*
1268 Get all visuals that meet our criteria so far.
1269 */
1270 number_visuals=0;
1271 visual_list=XGetVisualInfo(display,visual_mask,&visual_template,
1272 &number_visuals);
1273 visual_mask=VisualScreenMask | VisualIDMask;
1274 if ((number_visuals == 0) || (visual_list == (XVisualInfo *) NULL))
1275 {
1276 /*
1277 Failed to get visual; try using the default visual.
1278 */
1279 ThrowXWindowFatalException(XServerWarning,"UnableToGetVisual",
1280 visual_type);
1281 visual_template.visualid=XVisualIDFromVisual(XDefaultVisual(display,
1282 XDefaultScreen(display)));
1283 visual_list=XGetVisualInfo(display,visual_mask,&visual_template,
1284 &number_visuals);
1285 if ((number_visuals == 0) || (visual_list == (XVisualInfo *) NULL))
1286 return((XVisualInfo *) NULL);
1287 ThrowXWindowFatalException(XServerWarning,"UsingDefaultVisual",
1288 XVisualClassName(visual_list->klass));
1289 }
1290 resource_info->color_recovery=MagickFalse;
1291 if ((map_info != (XStandardColormap *) NULL) && (map_type != (char *) NULL))
1292 {
1293 Atom
1294 map_property;
1295
1296 char
1297 map_name[MaxTextExtent];
1298
1299 int
1300 j,
1301 number_maps;
1302
1303 Status
1304 status;
1305
1306 Window
1307 root_window;
1308
1309 XStandardColormap
1310 *map_list;
1311
1312 /*
1313 Choose a visual associated with a standard colormap.
1314 */
1315 root_window=XRootWindow(display,XDefaultScreen(display));
1316 status=False;
1317 if (LocaleCompare(map_type,"list") != 0)
1318 {
1319 /*
1320 User specified Standard Colormap.
1321 */
cristyb51dff52011-05-19 16:55:47 +00001322 (void) FormatLocaleString((char *) map_name,MaxTextExtent,
cristy3ed852e2009-09-05 21:47:34 +00001323 "RGB_%s_MAP",map_type);
1324 LocaleUpper(map_name);
1325 map_property=XInternAtom(display,(char *) map_name,MagickTrue);
1326 if (map_property != (Atom) NULL)
1327 status=XGetRGBColormaps(display,root_window,&map_list,&number_maps,
1328 map_property);
1329 }
1330 else
1331 {
1332 static const char
1333 *colormap[MaxStandardColormaps]=
1334 {
1335 "_HP_RGB_SMOOTH_MAP_LIST",
1336 "RGB_BEST_MAP",
1337 "RGB_DEFAULT_MAP",
1338 "RGB_GRAY_MAP",
1339 "RGB_RED_MAP",
1340 "RGB_GREEN_MAP",
1341 "RGB_BLUE_MAP",
1342 };
1343
1344 /*
1345 Choose a standard colormap from a list.
1346 */
1347 for (i=0; i < MaxStandardColormaps; i++)
1348 {
1349 map_property=XInternAtom(display,(char *) colormap[i],MagickTrue);
1350 if (map_property == (Atom) NULL)
1351 continue;
1352 status=XGetRGBColormaps(display,root_window,&map_list,&number_maps,
1353 map_property);
1354 if (status != False)
1355 break;
1356 }
1357 resource_info->color_recovery=i == 0 ? MagickTrue : MagickFalse;
1358 }
1359 if (status == False)
1360 {
1361 ThrowXWindowFatalException(XServerError,"UnableToGetStandardColormap",
1362 map_type);
1363 return((XVisualInfo *) NULL);
1364 }
1365 /*
1366 Search all Standard Colormaps and visuals for ids that match.
1367 */
1368 *map_info=map_list[0];
1369#if !defined(PRE_R4_ICCCM)
1370 visual_template.visualid=XVisualIDFromVisual(visual_list[0].visual);
1371 for (i=0; i < number_maps; i++)
1372 for (j=0; j < number_visuals; j++)
1373 if (map_list[i].visualid ==
1374 XVisualIDFromVisual(visual_list[j].visual))
1375 {
1376 *map_info=map_list[i];
1377 visual_template.visualid=XVisualIDFromVisual(
1378 visual_list[j].visual);
1379 break;
1380 }
1381 if (map_info->visualid != visual_template.visualid)
1382 {
1383 ThrowXWindowFatalException(XServerError,
1384 "UnableToMatchVisualToStandardColormap",map_type);
1385 return((XVisualInfo *) NULL);
1386 }
1387#endif
1388 if (map_info->colormap == (Colormap) NULL)
1389 {
1390 ThrowXWindowFatalException(XServerError,
1391 "StandardColormapIsNotInitialized",map_type);
1392 return((XVisualInfo *) NULL);
1393 }
1394 (void) XFree((void *) map_list);
1395 }
1396 else
1397 {
1398 static const unsigned int
1399 rank[]=
1400 {
1401 StaticGray,
1402 GrayScale,
1403 StaticColor,
1404 DirectColor,
1405 TrueColor,
1406 PseudoColor
1407 };
1408
1409 XVisualInfo
1410 *p;
1411
1412 /*
1413 Pick one visual that displays the most simultaneous colors.
1414 */
1415 visual_info=visual_list;
1416 p=visual_list;
1417 for (i=1; i < number_visuals; i++)
1418 {
1419 p++;
1420 if (XVisualColormapSize(p) > XVisualColormapSize(visual_info))
1421 visual_info=p;
1422 else
1423 if (XVisualColormapSize(p) == XVisualColormapSize(visual_info))
1424 if (rank[p->klass] > rank[visual_info->klass])
1425 visual_info=p;
1426 }
1427 visual_template.visualid=XVisualIDFromVisual(visual_info->visual);
1428 }
1429 (void) XFree((void *) visual_list);
1430 /*
1431 Retrieve only one visual by its screen & id number.
1432 */
1433 visual_info=XGetVisualInfo(display,visual_mask,&visual_template,
1434 &number_visuals);
1435 if ((number_visuals == 0) || (visual_info == (XVisualInfo *) NULL))
1436 return((XVisualInfo *) NULL);
1437 return(visual_info);
1438}
1439
1440/*
1441%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1442% %
1443% %
1444% %
1445% X C h e c k D e f i n e C u r s o r %
1446% %
1447% %
1448% %
1449%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1450%
1451% XCheckDefineCursor() prevents cursor changes on the root window.
1452%
1453% The format of the XXCheckDefineCursor method is:
1454%
1455% XCheckDefineCursor(display,window,cursor)
1456%
1457% A description of each parameter follows:
1458%
1459% o display: Specifies a connection to an X server; returned from
1460% XOpenDisplay.
1461%
1462% o window: the window.
1463%
1464% o cursor: the cursor.
1465%
1466*/
cristybcbda3f2011-09-03 13:01:22 +00001467MagickPrivate int XCheckDefineCursor(Display *display,Window window,
cristy3ed852e2009-09-05 21:47:34 +00001468 Cursor cursor)
1469{
1470 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
1471 assert(display != (Display *) NULL);
1472 if (window == XRootWindow(display,XDefaultScreen(display)))
1473 return(0);
1474 return(XDefineCursor(display,window,cursor));
1475}
1476
1477/*
1478%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1479% %
1480% %
1481% %
1482% X C h e c k R e f r e s h W i n d o w s %
1483% %
1484% %
1485% %
1486%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1487%
1488% XCheckRefreshWindows() checks the X server for exposure events for a
1489% particular window and updates the areassociated with the exposure event.
1490%
1491% The format of the XCheckRefreshWindows method is:
1492%
1493% void XCheckRefreshWindows(Display *display,XWindows *windows)
1494%
1495% A description of each parameter follows:
1496%
1497% o display: Specifies a connection to an X server; returned from
1498% XOpenDisplay.
1499%
1500% o windows: Specifies a pointer to a XWindows structure.
1501%
1502*/
cristybcbda3f2011-09-03 13:01:22 +00001503MagickPrivate void XCheckRefreshWindows(Display *display,XWindows *windows)
cristy3ed852e2009-09-05 21:47:34 +00001504{
1505 Window
1506 id;
1507
1508 XEvent
1509 event;
1510
1511 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
1512 assert(display != (Display *) NULL);
1513 assert(windows != (XWindows *) NULL);
1514 XDelay(display,SuspendTime);
1515 id=windows->command.id;
1516 while (XCheckTypedWindowEvent(display,id,Expose,&event) != MagickFalse)
1517 (void) XCommandWidget(display,windows,(char const **) NULL,&event);
1518 id=windows->image.id;
1519 while (XCheckTypedWindowEvent(display,id,Expose,&event) != MagickFalse)
1520 XRefreshWindow(display,&windows->image,&event);
1521 XDelay(display,SuspendTime << 1);
1522 id=windows->command.id;
1523 while (XCheckTypedWindowEvent(display,id,Expose,&event) != MagickFalse)
1524 (void) XCommandWidget(display,windows,(char const **) NULL,&event);
1525 id=windows->image.id;
1526 while (XCheckTypedWindowEvent(display,id,Expose,&event) != MagickFalse)
1527 XRefreshWindow(display,&windows->image,&event);
1528}
1529
1530/*
1531%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1532% %
1533% %
1534% %
1535% X C l i e n t M e s s a g e %
1536% %
1537% %
1538% %
1539%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1540%
1541% XClientMessage() sends a reason to a window with XSendEvent. The reason is
1542% initialized with a particular protocol type and atom.
1543%
1544% The format of the XClientMessage function is:
1545%
1546% XClientMessage(display,window,protocol,reason,timestamp)
1547%
1548% A description of each parameter follows:
1549%
1550% o display: Specifies a pointer to the Display structure; returned from
1551% XOpenDisplay.
1552%
1553% o window: Specifies a pointer to a Window structure.
1554%
1555% o protocol: Specifies an atom value.
1556%
1557% o reason: Specifies an atom value which is the reason to send.
1558%
1559% o timestamp: Specifies a value of type Time.
1560%
1561*/
cristybcbda3f2011-09-03 13:01:22 +00001562MagickPrivate void XClientMessage(Display *display,const Window window,
cristy3ed852e2009-09-05 21:47:34 +00001563 const Atom protocol,const Atom reason,const Time timestamp)
1564{
1565 XClientMessageEvent
1566 client_event;
1567
1568 assert(display != (Display *) NULL);
1569 client_event.type=ClientMessage;
1570 client_event.window=window;
1571 client_event.message_type=protocol;
1572 client_event.format=32;
cristyc57f6942010-11-12 01:47:39 +00001573 client_event.data.l[0]=(long) reason;
1574 client_event.data.l[1]=(long) timestamp;
cristy3ed852e2009-09-05 21:47:34 +00001575 (void) XSendEvent(display,window,MagickFalse,NoEventMask,(XEvent *) &client_event);
1576}
1577
1578/*
1579%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1580% %
1581% %
1582% %
1583+ X C l i e n t W i n d o w %
1584% %
1585% %
1586% %
1587%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1588%
1589% XClientWindow() finds a window, at or below the specified window, which has
1590% a WM_STATE property. If such a window is found, it is returned, otherwise
1591% the argument window is returned.
1592%
1593% The format of the XClientWindow function is:
1594%
1595% client_window=XClientWindow(display,target_window)
1596%
1597% A description of each parameter follows:
1598%
1599% o client_window: XClientWindow returns a window, at or below the specified
1600% window, which has a WM_STATE property otherwise the argument
1601% target_window is returned.
1602%
1603% o display: Specifies a pointer to the Display structure; returned from
1604% XOpenDisplay.
1605%
1606% o target_window: Specifies the window to find a WM_STATE property.
1607%
cristy3ed852e2009-09-05 21:47:34 +00001608*/
1609static Window XClientWindow(Display *display,Window target_window)
1610{
1611 Atom
1612 state,
1613 type;
1614
1615 int
1616 format;
1617
1618 Status
1619 status;
1620
1621 unsigned char
1622 *data;
1623
cristyf2faecf2010-05-28 19:19:36 +00001624 unsigned long
cristy3ed852e2009-09-05 21:47:34 +00001625 after,
1626 number_items;
1627
1628 Window
1629 client_window;
1630
1631 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
1632 assert(display != (Display *) NULL);
1633 state=XInternAtom(display,"WM_STATE",MagickTrue);
1634 if (state == (Atom) NULL)
1635 return(target_window);
1636 type=(Atom) NULL;
1637 status=XGetWindowProperty(display,target_window,state,0L,0L,MagickFalse,
1638 (Atom) AnyPropertyType,&type,&format,&number_items,&after,&data);
1639 if ((status == Success) && (type != (Atom) NULL))
1640 return(target_window);
1641 client_window=XWindowByProperty(display,target_window,state);
1642 if (client_window == (Window) NULL)
1643 return(target_window);
1644 return(client_window);
1645}
1646
1647/*
1648%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1649% %
1650% %
1651% %
cristyf34a1452009-10-24 22:29:27 +00001652+ X C o m p o n e n t T e r m i n u s %
1653% %
1654% %
1655% %
1656%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1657%
1658% XComponentTerminus() destroys the module component.
1659%
1660% The format of the XComponentTerminus method is:
1661%
1662% XComponentTerminus(void)
1663%
1664*/
cristy5ff4eaf2011-09-03 01:38:02 +00001665MagickPrivate void XComponentTerminus(void)
cristyf34a1452009-10-24 22:29:27 +00001666{
1667 DestroyXResources();
1668}
1669
1670/*
1671%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1672% %
1673% %
1674% %
cristy3ed852e2009-09-05 21:47:34 +00001675% X C o n f i g u r e I m a g e C o l o r m a p %
1676% %
1677% %
1678% %
1679%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1680%
1681% XConfigureImageColormap() creates a new X colormap.
1682%
1683% The format of the XConfigureImageColormap method is:
1684%
1685% void XConfigureImageColormap(Display *display,
1686% XResourceInfo *resource_info,XWindows *windows,Image *image)
1687%
1688% A description of each parameter follows:
1689%
1690% o display: Specifies a connection to an X server; returned from
1691% XOpenDisplay.
1692%
1693% o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
1694%
1695% o windows: Specifies a pointer to a XWindows structure.
1696%
1697% o image: the image.
1698%
1699*/
cristybcbda3f2011-09-03 13:01:22 +00001700MagickPrivate void XConfigureImageColormap(Display *display,
cristy3ed852e2009-09-05 21:47:34 +00001701 XResourceInfo *resource_info,XWindows *windows,Image *image)
1702{
1703 Colormap
1704 colormap;
1705
1706 /*
1707 Make standard colormap.
1708 */
1709 XSetCursorState(display,windows,MagickTrue);
1710 XCheckRefreshWindows(display,windows);
1711 XMakeStandardColormap(display,windows->visual_info,resource_info,image,
1712 windows->map_info,windows->pixel_info);
1713 colormap=windows->map_info->colormap;
1714 (void) XSetWindowColormap(display,windows->image.id,colormap);
1715 (void) XSetWindowColormap(display,windows->command.id,colormap);
1716 (void) XSetWindowColormap(display,windows->widget.id,colormap);
1717 if (windows->magnify.mapped != MagickFalse)
1718 (void) XSetWindowColormap(display,windows->magnify.id,colormap);
1719 if (windows->pan.mapped != MagickFalse)
1720 (void) XSetWindowColormap(display,windows->pan.id,colormap);
1721 XSetCursorState(display,windows,MagickFalse);
1722 XClientMessage(display,windows->image.id,windows->im_protocols,
1723 windows->im_update_colormap,CurrentTime);
1724}
1725
1726/*
1727%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1728% %
1729% %
1730% %
1731% X C o n s t r a i n W i n d o w P o s i t i o n %
1732% %
1733% %
1734% %
1735%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1736%
1737% XConstrainWindowPosition() assures a window is positioned within the X
1738% server boundaries.
1739%
1740% The format of the XConstrainWindowPosition method is:
1741%
1742% void XConstrainWindowPosition(Display *display,XWindowInfo *window_info)
1743%
1744% A description of each parameter follows:
1745%
1746% o display: Specifies a pointer to the Display structure; returned from
1747% XOpenDisplay.
1748%
1749% o window_info: Specifies a pointer to a XWindowInfo structure.
1750%
1751*/
cristybcbda3f2011-09-03 13:01:22 +00001752MagickPrivate void XConstrainWindowPosition(Display *display,
cristy3ed852e2009-09-05 21:47:34 +00001753 XWindowInfo *window_info)
1754{
1755 int
1756 limit;
1757
1758 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
1759 assert(display != (Display *) NULL);
1760 assert(window_info != (XWindowInfo *) NULL);
1761 limit=XDisplayWidth(display,window_info->screen)-window_info->width;
1762 if (window_info->x < 0)
1763 window_info->x=0;
1764 else
1765 if (window_info->x > (int) limit)
1766 window_info->x=(int) limit;
1767 limit=XDisplayHeight(display,window_info->screen)-window_info->height;
1768 if (window_info->y < 0)
1769 window_info->y=0;
1770 else
1771 if (window_info->y > limit)
1772 window_info->y=limit;
1773}
1774
1775/*
1776%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1777% %
1778% %
1779% %
1780% X D e l a y %
1781% %
1782% %
1783% %
1784%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1785%
1786% XDelay() suspends program execution for the number of milliseconds
1787% specified.
1788%
1789% The format of the Delay method is:
1790%
cristybb503372010-05-27 20:51:26 +00001791% void XDelay(Display *display,const size_t milliseconds)
cristy3ed852e2009-09-05 21:47:34 +00001792%
1793% A description of each parameter follows:
1794%
1795% o display: Specifies a pointer to the Display structure; returned from
1796% XOpenDisplay.
1797%
1798% o milliseconds: Specifies the number of milliseconds to delay before
1799% returning.
1800%
1801*/
cristybcbda3f2011-09-03 13:01:22 +00001802MagickPrivate void XDelay(Display *display,const size_t milliseconds)
cristy3ed852e2009-09-05 21:47:34 +00001803{
1804 assert(display != (Display *) NULL);
1805 (void) XFlush(display);
cristya21afde2010-07-02 00:45:40 +00001806 MagickDelay(milliseconds);
cristy3ed852e2009-09-05 21:47:34 +00001807}
1808
1809/*
1810%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1811% %
1812% %
1813% %
1814% X D e s t r o y R e s o u r c e I n f o %
1815% %
1816% %
1817% %
1818%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1819%
1820% XDestroyResourceInfo() frees memory associated with the XResourceInfo
1821% structure.
1822%
1823% The format of the XDestroyResourceInfo method is:
1824%
1825% void XDestroyResourceInfo(XResourceInfo *resource_info)
1826%
1827% A description of each parameter follows:
1828%
1829% o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
1830%
1831*/
1832MagickExport void XDestroyResourceInfo(XResourceInfo *resource_info)
1833{
1834 if (resource_info->image_geometry != (char *) NULL)
1835 resource_info->image_geometry=(char *)
1836 RelinquishMagickMemory(resource_info->image_geometry);
1837 if (resource_info->quantize_info != (QuantizeInfo *) NULL)
1838 resource_info->quantize_info=DestroyQuantizeInfo(
1839 resource_info->quantize_info);
1840 if (resource_info->client_name != (char *) NULL)
1841 resource_info->client_name=(char *)
1842 RelinquishMagickMemory(resource_info->client_name);
1843 if (resource_info->name != (char *) NULL)
1844 resource_info->name=DestroyString(resource_info->name);
1845 (void) ResetMagickMemory(resource_info,0,sizeof(*resource_info));
1846}
1847
1848/*
1849%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1850% %
1851% %
1852% %
1853% X D e s t r o y W i n d o w C o l o r s %
1854% %
1855% %
1856% %
1857%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1858%
1859% XDestroyWindowColors() frees X11 color resources previously saved on a
1860% window by XRetainWindowColors or programs like xsetroot.
1861%
1862% The format of the XDestroyWindowColors method is:
1863%
1864% void XDestroyWindowColors(Display *display,Window window)
1865%
1866% A description of each parameter follows:
1867%
1868% o display: Specifies a connection to an X server; returned from
1869% XOpenDisplay.
1870%
1871% o window: Specifies a pointer to a Window structure.
1872%
1873*/
cristybcbda3f2011-09-03 13:01:22 +00001874MagickPrivate void XDestroyWindowColors(Display *display,Window window)
cristy3ed852e2009-09-05 21:47:34 +00001875{
1876 Atom
1877 property,
1878 type;
1879
1880 int
1881 format;
1882
1883 Status
1884 status;
1885
1886 unsigned char
1887 *data;
1888
cristyf2faecf2010-05-28 19:19:36 +00001889 unsigned long
cristy3ed852e2009-09-05 21:47:34 +00001890 after,
1891 length;
1892
1893 /*
1894 If there are previous resources on the root window, destroy them.
1895 */
1896 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
1897 assert(display != (Display *) NULL);
1898 property=XInternAtom(display,"_XSETROOT_ID",MagickFalse);
1899 if (property == (Atom) NULL)
1900 {
1901 ThrowXWindowFatalException(XServerError,"UnableToCreateProperty",
1902 "_XSETROOT_ID");
1903 return;
1904 }
1905 status=XGetWindowProperty(display,window,property,0L,1L,MagickTrue,
1906 (Atom) AnyPropertyType,&type,&format,&length,&after,&data);
1907 if (status != Success)
1908 return;
1909 if ((type == XA_PIXMAP) && (format == 32) && (length == 1) && (after == 0))
1910 {
1911 (void) XKillClient(display,(XID) (*((Pixmap *) data)));
1912 (void) XDeleteProperty(display,window,property);
1913 }
1914 if (type != None)
1915 (void) XFree((void *) data);
1916}
1917
1918/*
1919%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1920% %
1921% %
1922% %
1923% X D i s p l a y I m a g e I n f o %
1924% %
1925% %
1926% %
1927%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1928%
1929% XDisplayImageInfo() displays information about an X image.
1930%
1931% The format of the XDisplayImageInfo method is:
1932%
1933% void XDisplayImageInfo(Display *display,
1934% const XResourceInfo *resource_info,XWindows *windows,Image *undo_image,
1935% Image *image)
1936%
1937% A description of each parameter follows:
1938%
1939% o display: Specifies a connection to an X server; returned from
1940% XOpenDisplay.
1941%
1942% o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
1943%
1944% o windows: Specifies a pointer to a XWindows structure.
1945%
1946% o undo_image: the undo image.
1947%
1948% o image: the image.
1949%
1950*/
cristybcbda3f2011-09-03 13:01:22 +00001951MagickPrivate void XDisplayImageInfo(Display *display,
cristy3ed852e2009-09-05 21:47:34 +00001952 const XResourceInfo *resource_info,XWindows *windows,Image *undo_image,
1953 Image *image)
1954{
1955 char
1956 filename[MaxTextExtent],
1957 *text,
1958 **textlist;
1959
1960 FILE
1961 *file;
1962
1963 int
1964 unique_file;
1965
cristybb503372010-05-27 20:51:26 +00001966 register ssize_t
cristy3ed852e2009-09-05 21:47:34 +00001967 i;
1968
cristybb503372010-05-27 20:51:26 +00001969 size_t
cristy3ed852e2009-09-05 21:47:34 +00001970 number_pixels;
1971
cristy9d314ff2011-03-09 01:30:28 +00001972 ssize_t
1973 bytes;
1974
1975 unsigned int
1976 levels;
1977
cristy3ed852e2009-09-05 21:47:34 +00001978 /*
1979 Write info about the X server to a file.
1980 */
1981 assert(display != (Display *) NULL);
1982 assert(resource_info != (XResourceInfo *) NULL);
1983 assert(windows != (XWindows *) NULL);
1984 assert(image != (Image *) NULL);
1985 if (image->debug)
1986 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
1987 file=(FILE *) NULL;
1988 unique_file=AcquireUniqueFileResource(filename);
1989 if (unique_file != -1)
1990 file=fdopen(unique_file,"w");
1991 if ((unique_file == -1) || (file == (FILE *) NULL))
1992 {
1993 XNoticeWidget(display,windows,"Unable to display image info",filename);
1994 return;
1995 }
1996 if (resource_info->gamma_correct != MagickFalse)
1997 if (resource_info->display_gamma != (char *) NULL)
cristyb51dff52011-05-19 16:55:47 +00001998 (void) FormatLocaleFile(file,"Display\n gamma: %s\n\n",
cristy3ed852e2009-09-05 21:47:34 +00001999 resource_info->display_gamma);
2000 /*
2001 Write info about the X image to a file.
2002 */
cristyb51dff52011-05-19 16:55:47 +00002003 (void) FormatLocaleFile(file,"X\n visual: %s\n",
cristy3ed852e2009-09-05 21:47:34 +00002004 XVisualClassName((int) windows->image.storage_class));
cristyb51dff52011-05-19 16:55:47 +00002005 (void) FormatLocaleFile(file," depth: %d\n",windows->image.ximage->depth);
cristy3ed852e2009-09-05 21:47:34 +00002006 if (windows->visual_info->colormap_size != 0)
cristyb51dff52011-05-19 16:55:47 +00002007 (void) FormatLocaleFile(file," colormap size: %d\n",
cristy3ed852e2009-09-05 21:47:34 +00002008 windows->visual_info->colormap_size);
2009 if (resource_info->colormap== SharedColormap)
cristyb51dff52011-05-19 16:55:47 +00002010 (void) FormatLocaleFile(file," colormap type: Shared\n");
cristy3ed852e2009-09-05 21:47:34 +00002011 else
cristyb51dff52011-05-19 16:55:47 +00002012 (void) FormatLocaleFile(file," colormap type: Private\n");
cristy1e604812011-05-19 18:07:50 +00002013 (void) FormatLocaleFile(file," geometry: %dx%d\n",
2014 windows->image.ximage->width,windows->image.ximage->height);
cristy3ed852e2009-09-05 21:47:34 +00002015 if (windows->image.crop_geometry != (char *) NULL)
cristy1e604812011-05-19 18:07:50 +00002016 (void) FormatLocaleFile(file," crop geometry: %s\n",
2017 windows->image.crop_geometry);
cristy3ed852e2009-09-05 21:47:34 +00002018 if (windows->image.pixmap == (Pixmap) NULL)
cristyb51dff52011-05-19 16:55:47 +00002019 (void) FormatLocaleFile(file," type: X Image\n");
cristy3ed852e2009-09-05 21:47:34 +00002020 else
cristyb51dff52011-05-19 16:55:47 +00002021 (void) FormatLocaleFile(file," type: Pixmap\n");
cristy3ed852e2009-09-05 21:47:34 +00002022 if (windows->image.shape != MagickFalse)
cristyb51dff52011-05-19 16:55:47 +00002023 (void) FormatLocaleFile(file," non-rectangular shape: True\n");
cristy3ed852e2009-09-05 21:47:34 +00002024 else
cristyb51dff52011-05-19 16:55:47 +00002025 (void) FormatLocaleFile(file," non-rectangular shape: False\n");
cristy3ed852e2009-09-05 21:47:34 +00002026 if (windows->image.shared_memory != MagickFalse)
cristyb51dff52011-05-19 16:55:47 +00002027 (void) FormatLocaleFile(file," shared memory: True\n");
cristy3ed852e2009-09-05 21:47:34 +00002028 else
cristyb51dff52011-05-19 16:55:47 +00002029 (void) FormatLocaleFile(file," shared memory: False\n");
2030 (void) FormatLocaleFile(file,"\n");
cristy3ed852e2009-09-05 21:47:34 +00002031 if (resource_info->font != (char *) NULL)
cristyb51dff52011-05-19 16:55:47 +00002032 (void) FormatLocaleFile(file,"Font: %s\n\n",resource_info->font);
cristy3ed852e2009-09-05 21:47:34 +00002033 if (resource_info->text_font != (char *) NULL)
cristyb51dff52011-05-19 16:55:47 +00002034 (void) FormatLocaleFile(file,"Text font: %s\n\n",resource_info->text_font);
cristy3ed852e2009-09-05 21:47:34 +00002035 /*
2036 Write info about the undo cache to a file.
2037 */
2038 bytes=0;
2039 for (levels=0; undo_image != (Image *) NULL; levels++)
2040 {
2041 number_pixels=undo_image->list->columns*undo_image->list->rows;
2042 bytes+=number_pixels*sizeof(PixelPacket);
2043 undo_image=GetPreviousImageInList(undo_image);
2044 }
cristyb51dff52011-05-19 16:55:47 +00002045 (void) FormatLocaleFile(file,"Undo Edit Cache\n levels: %u\n",levels);
cristy1e604812011-05-19 18:07:50 +00002046 (void) FormatLocaleFile(file," bytes: %.20gmb\n",(double)
2047 ((bytes+(1 << 19)) >> 20));
cristyb51dff52011-05-19 16:55:47 +00002048 (void) FormatLocaleFile(file," limit: %.20gmb\n\n",(double)
cristyf2faecf2010-05-28 19:19:36 +00002049 resource_info->undo_cache);
cristy3ed852e2009-09-05 21:47:34 +00002050 /*
2051 Write info about the image to a file.
2052 */
cristya4037272011-08-28 15:11:39 +00002053 (void) IdentifyImage(image,file,MagickTrue,&image->exception);
cristy3ed852e2009-09-05 21:47:34 +00002054 (void) fclose(file);
2055 text=FileToString(filename,~0,&image->exception);
2056 (void) RelinquishUniqueFileResource(filename);
2057 if (text == (char *) NULL)
2058 {
2059 XNoticeWidget(display,windows,"MemoryAllocationFailed",
2060 "UnableToDisplayImageInfo");
2061 return;
2062 }
2063 textlist=StringToList(text);
2064 if (textlist != (char **) NULL)
2065 {
2066 char
2067 title[MaxTextExtent];
2068
2069 /*
2070 Display information about the image in the Text View widget.
2071 */
2072 (void) XWithdrawWindow(display,windows->info.id,windows->info.screen);
cristyb51dff52011-05-19 16:55:47 +00002073 (void) FormatLocaleString(title,MaxTextExtent,"Image Info: %s",
cristy3ed852e2009-09-05 21:47:34 +00002074 image->filename);
2075 XTextViewWidget(display,resource_info,windows,MagickTrue,title,
2076 (char const **) textlist);
2077 for (i=0; textlist[i] != (char *) NULL; i++)
2078 textlist[i]=DestroyString(textlist[i]);
2079 textlist=(char **) RelinquishMagickMemory(textlist);
2080 }
2081 text=DestroyString(text);
2082}
2083
2084/*
2085%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2086% %
2087% %
2088% %
2089+ X D i t h e r I m a g e %
2090% %
2091% %
2092% %
2093%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2094%
2095% XDitherImage() dithers the reference image as required by the HP Color
2096% Recovery algorithm. The color values are quantized to 3 bits of red and
2097% green, and 2 bits of blue (3/3/2) and can be used as indices into a 8-bit X
2098% standard colormap.
2099%
2100% The format of the XDitherImage method is:
2101%
2102% void XDitherImage(Image *image,XImage *ximage)
2103%
2104% A description of each parameter follows:
2105%
2106% o image: the image.
2107%
2108% o ximage: Specifies a pointer to a XImage structure; returned from
2109% XCreateImage.
2110%
cristy3ed852e2009-09-05 21:47:34 +00002111*/
2112static void XDitherImage(Image *image,XImage *ximage)
2113{
2114 static const short int
2115 dither_red[2][16]=
2116 {
2117 {-16, 4, -1, 11,-14, 6, -3, 9,-15, 5, -2, 10,-13, 7, -4, 8},
2118 { 15, -5, 0,-12, 13, -7, 2,-10, 14, -6, 1,-11, 12, -8, 3, -9}
2119 },
2120 dither_green[2][16]=
2121 {
2122 { 11,-15, 7, -3, 8,-14, 4, -2, 10,-16, 6, -4, 9,-13, 5, -1},
2123 {-12, 14, -8, 2, -9, 13, -5, 1,-11, 15, -7, 3,-10, 12, -6, 0}
2124 },
2125 dither_blue[2][16]=
2126 {
2127 { -3, 9,-13, 7, -1, 11,-15, 5, -4, 8,-14, 6, -2, 10,-16, 4},
2128 { 2,-10, 12, -8, 0,-12, 14, -6, 3, -9, 13, -7, 1,-11, 15, -5}
2129 };
2130
cristyc57f6942010-11-12 01:47:39 +00002131 CacheView
2132 *image_view;
cristy3ed852e2009-09-05 21:47:34 +00002133
2134 int
cristyc57f6942010-11-12 01:47:39 +00002135 value,
cristy3ed852e2009-09-05 21:47:34 +00002136 y;
2137
cristyc57f6942010-11-12 01:47:39 +00002138 PixelPacket
2139 color;
cristy3ed852e2009-09-05 21:47:34 +00002140
2141 register char
2142 *q;
2143
cristy4c08aed2011-07-01 19:47:50 +00002144 register const Quantum
cristy3ed852e2009-09-05 21:47:34 +00002145 *p;
2146
2147 register int
2148 i,
2149 j,
2150 x;
2151
2152 unsigned int
2153 scanline_pad;
2154
cristybb503372010-05-27 20:51:26 +00002155 register size_t
cristy3ed852e2009-09-05 21:47:34 +00002156 pixel;
2157
2158 unsigned char
2159 *blue_map[2][16],
2160 *green_map[2][16],
2161 *red_map[2][16];
2162
2163 /*
2164 Allocate and initialize dither maps.
2165 */
2166 for (i=0; i < 2; i++)
2167 for (j=0; j < 16; j++)
2168 {
2169 red_map[i][j]=(unsigned char *) AcquireQuantumMemory(256UL,
2170 sizeof(*red_map));
2171 green_map[i][j]=(unsigned char *) AcquireQuantumMemory(256UL,
2172 sizeof(*green_map));
2173 blue_map[i][j]=(unsigned char *) AcquireQuantumMemory(256UL,
2174 sizeof(*blue_map));
2175 if ((red_map[i][j] == (unsigned char *) NULL) ||
2176 (green_map[i][j] == (unsigned char *) NULL) ||
2177 (blue_map[i][j] == (unsigned char *) NULL))
2178 {
2179 ThrowXWindowFatalException(ResourceLimitError,
2180 "MemoryAllocationFailed",image->filename);
2181 return;
2182 }
2183 }
2184 /*
2185 Initialize dither tables.
2186 */
2187 for (i=0; i < 2; i++)
2188 for (j=0; j < 16; j++)
2189 for (x=0; x < 256; x++)
2190 {
2191 value=x-16;
2192 if (x < 48)
2193 value=x/2+8;
2194 value+=dither_red[i][j];
2195 red_map[i][j][x]=(unsigned char)
2196 ((value < 0) ? 0 : (value > 255) ? 255 : value);
2197 value=x-16;
2198 if (x < 48)
2199 value=x/2+8;
2200 value+=dither_green[i][j];
2201 green_map[i][j][x]=(unsigned char)
2202 ((value < 0) ? 0 : (value > 255) ? 255 : value);
2203 value=x-32;
2204 if (x < 112)
2205 value=x/2+24;
cristybb503372010-05-27 20:51:26 +00002206 value+=((size_t) dither_blue[i][j] << 1);
cristy3ed852e2009-09-05 21:47:34 +00002207 blue_map[i][j][x]=(unsigned char)
2208 ((value < 0) ? 0 : (value > 255) ? 255 : value);
2209 }
2210 /*
2211 Dither image.
2212 */
2213 scanline_pad=(unsigned int) (ximage->bytes_per_line-
cristybb503372010-05-27 20:51:26 +00002214 ((size_t) (ximage->width*ximage->bits_per_pixel) >> 3));
cristy3ed852e2009-09-05 21:47:34 +00002215 i=0;
2216 j=0;
2217 q=ximage->data;
cristyc57f6942010-11-12 01:47:39 +00002218 image_view=AcquireCacheView(image);
cristy3ed852e2009-09-05 21:47:34 +00002219 for (y=0; y < (int) image->rows; y++)
2220 {
cristyc57f6942010-11-12 01:47:39 +00002221 p=GetCacheViewVirtualPixels(image_view,0,(ssize_t) y,image->columns,1,
2222 &image->exception);
cristy4c08aed2011-07-01 19:47:50 +00002223 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00002224 break;
2225 for (x=0; x < (int) image->columns; x++)
2226 {
cristyce70c172010-01-07 17:15:30 +00002227 color.red=ClampToQuantum((MagickRealType) (red_map[i][j][(int)
cristy4c08aed2011-07-01 19:47:50 +00002228 ScaleQuantumToChar(GetPixelRed(image,p))] << 8));
cristyce70c172010-01-07 17:15:30 +00002229 color.green=ClampToQuantum((MagickRealType) (green_map[i][j][(int)
cristy4c08aed2011-07-01 19:47:50 +00002230 ScaleQuantumToChar(GetPixelGreen(image,p))] << 8));
cristyce70c172010-01-07 17:15:30 +00002231 color.blue=ClampToQuantum((MagickRealType) (blue_map[i][j][(int)
cristy4c08aed2011-07-01 19:47:50 +00002232 ScaleQuantumToChar(GetPixelBlue(image,p))] << 8));
cristybb503372010-05-27 20:51:26 +00002233 pixel=(size_t) (((size_t) color.red & 0xe0) |
2234 (((size_t) color.green & 0xe0) >> 3) |
2235 (((size_t) color.blue & 0xc0) >> 6));
cristy3ed852e2009-09-05 21:47:34 +00002236 *q++=(char) pixel;
cristyed231572011-07-14 02:18:59 +00002237 p+=GetPixelChannels(image);
cristy3ed852e2009-09-05 21:47:34 +00002238 j++;
2239 if (j == 16)
2240 j=0;
2241 }
2242 q+=scanline_pad;
2243 i++;
2244 if (i == 2)
2245 i=0;
2246 }
cristyc57f6942010-11-12 01:47:39 +00002247 image_view=DestroyCacheView(image_view);
cristy3ed852e2009-09-05 21:47:34 +00002248 /*
2249 Free allocated memory.
2250 */
2251 for (i=0; i < 2; i++)
2252 for (j=0; j < 16; j++)
2253 {
2254 green_map[i][j]=(unsigned char *) RelinquishMagickMemory(green_map[i][j]);
2255 blue_map[i][j]=(unsigned char *) RelinquishMagickMemory(blue_map[i][j]);
2256 red_map[i][j]=(unsigned char *) RelinquishMagickMemory(red_map[i][j]);
2257 }
2258}
2259
2260/*
2261%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2262% %
2263% %
2264% %
2265% X D r a w I m a g e %
2266% %
2267% %
2268% %
2269%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2270%
2271% XDrawImage() draws a line on the image.
2272%
2273% The format of the XDrawImage method is:
2274%
2275% MagickBooleanType XDrawImage(display,pixel,draw_info,image)
2276%
2277% A description of each parameter follows:
2278%
2279% o display: Specifies a connection to an X server; returned from
2280% XOpenDisplay.
2281%
2282% o pixel: Specifies a pointer to a XPixelInfo structure.
2283%
2284% o draw_info: Specifies a pointer to a XDrawInfo structure.
2285%
2286% o image: the image.
2287%
2288*/
cristybcbda3f2011-09-03 13:01:22 +00002289MagickPrivate MagickBooleanType XDrawImage(Display *display,
cristy3ed852e2009-09-05 21:47:34 +00002290 const XPixelInfo *pixel,XDrawInfo *draw_info,Image *image)
2291{
cristyc57f6942010-11-12 01:47:39 +00002292 CacheView
2293 *draw_view;
2294
cristy3ed852e2009-09-05 21:47:34 +00002295 ExceptionInfo
2296 *exception;
2297
2298 GC
2299 draw_context;
2300
2301 Image
2302 *draw_image;
2303
2304 int
2305 x,
2306 y;
2307
2308 MagickBooleanType
2309 matte;
2310
2311 Pixmap
2312 draw_pixmap;
2313
2314 unsigned int
2315 depth,
2316 height,
2317 width;
2318
2319 Window
2320 root_window;
2321
2322 XGCValues
2323 context_values;
2324
2325 XImage
2326 *draw_ximage;
2327
2328 /*
2329 Initialize drawd image.
2330 */
2331 assert(display != (Display *) NULL);
2332 assert(pixel != (XPixelInfo *) NULL);
2333 assert(draw_info != (XDrawInfo *) NULL);
2334 assert(image != (Image *) NULL);
2335 if (image->debug != MagickFalse)
2336 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
2337 /*
2338 Initialize drawd pixmap.
2339 */
2340 root_window=XRootWindow(display,XDefaultScreen(display));
2341 depth=(unsigned int) XDefaultDepth(display,XDefaultScreen(display));
2342 draw_pixmap=XCreatePixmap(display,root_window,draw_info->width,
2343 draw_info->height,depth);
2344 if (draw_pixmap == (Pixmap) NULL)
2345 return(MagickFalse);
2346 /*
2347 Initialize graphics info.
2348 */
cristybb503372010-05-27 20:51:26 +00002349 context_values.background=(size_t) (~0);
cristy3ed852e2009-09-05 21:47:34 +00002350 context_values.foreground=0;
2351 context_values.line_width=(int) draw_info->line_width;
cristybb503372010-05-27 20:51:26 +00002352 draw_context=XCreateGC(display,root_window,(size_t)
cristy3ed852e2009-09-05 21:47:34 +00002353 (GCBackground | GCForeground | GCLineWidth),&context_values);
2354 if (draw_context == (GC) NULL)
2355 return(MagickFalse);
2356 /*
2357 Clear pixmap.
2358 */
2359 (void) XFillRectangle(display,draw_pixmap,draw_context,0,0,draw_info->width,
2360 draw_info->height);
2361 /*
2362 Draw line to pixmap.
2363 */
2364 (void) XSetBackground(display,draw_context,0);
cristybb503372010-05-27 20:51:26 +00002365 (void) XSetForeground(display,draw_context,(size_t) (~0));
cristydd05beb2010-11-21 21:23:39 +00002366 if (draw_info->stipple != (Pixmap) NULL)
2367 {
2368 (void) XSetFillStyle(display,draw_context,FillOpaqueStippled);
2369 (void) XSetStipple(display,draw_context,draw_info->stipple);
2370 }
cristy3ed852e2009-09-05 21:47:34 +00002371 switch (draw_info->element)
2372 {
2373 case PointElement:
2374 default:
2375 {
2376 (void) XDrawLines(display,draw_pixmap,draw_context,
2377 draw_info->coordinate_info,(int) draw_info->number_coordinates,
2378 CoordModeOrigin);
2379 break;
2380 }
2381 case LineElement:
2382 {
2383 (void) XDrawLine(display,draw_pixmap,draw_context,draw_info->line_info.x1,
2384 draw_info->line_info.y1,draw_info->line_info.x2,
2385 draw_info->line_info.y2);
2386 break;
2387 }
2388 case RectangleElement:
2389 {
2390 (void) XDrawRectangle(display,draw_pixmap,draw_context,
2391 (int) draw_info->rectangle_info.x,(int) draw_info->rectangle_info.y,
2392 (unsigned int) draw_info->rectangle_info.width,
2393 (unsigned int) draw_info->rectangle_info.height);
2394 break;
2395 }
2396 case FillRectangleElement:
2397 {
2398 (void) XFillRectangle(display,draw_pixmap,draw_context,
2399 (int) draw_info->rectangle_info.x,(int) draw_info->rectangle_info.y,
2400 (unsigned int) draw_info->rectangle_info.width,
2401 (unsigned int) draw_info->rectangle_info.height);
2402 break;
2403 }
2404 case CircleElement:
2405 case EllipseElement:
2406 {
2407 (void) XDrawArc(display,draw_pixmap,draw_context,
2408 (int) draw_info->rectangle_info.x,(int) draw_info->rectangle_info.y,
2409 (unsigned int) draw_info->rectangle_info.width,
2410 (unsigned int) draw_info->rectangle_info.height,0,360*64);
2411 break;
2412 }
2413 case FillCircleElement:
2414 case FillEllipseElement:
2415 {
2416 (void) XFillArc(display,draw_pixmap,draw_context,
2417 (int) draw_info->rectangle_info.x,(int) draw_info->rectangle_info.y,
2418 (unsigned int) draw_info->rectangle_info.width,
2419 (unsigned int) draw_info->rectangle_info.height,0,360*64);
2420 break;
2421 }
2422 case PolygonElement:
2423 {
2424 XPoint
2425 *coordinate_info;
2426
2427 coordinate_info=draw_info->coordinate_info;
2428 (void) XDrawLines(display,draw_pixmap,draw_context,coordinate_info,
2429 (int) draw_info->number_coordinates,CoordModeOrigin);
2430 (void) XDrawLine(display,draw_pixmap,draw_context,
2431 coordinate_info[draw_info->number_coordinates-1].x,
2432 coordinate_info[draw_info->number_coordinates-1].y,
2433 coordinate_info[0].x,coordinate_info[0].y);
2434 break;
2435 }
2436 case FillPolygonElement:
2437 {
2438 (void) XFillPolygon(display,draw_pixmap,draw_context,
2439 draw_info->coordinate_info,(int) draw_info->number_coordinates,Complex,
2440 CoordModeOrigin);
2441 break;
2442 }
2443 }
2444 (void) XFreeGC(display,draw_context);
2445 /*
2446 Initialize X image.
2447 */
2448 draw_ximage=XGetImage(display,draw_pixmap,0,0,draw_info->width,
2449 draw_info->height,AllPlanes,ZPixmap);
2450 if (draw_ximage == (XImage *) NULL)
2451 return(MagickFalse);
2452 (void) XFreePixmap(display,draw_pixmap);
2453 /*
2454 Initialize draw image.
2455 */
2456 draw_image=AcquireImage((ImageInfo *) NULL);
2457 if (draw_image == (Image *) NULL)
2458 return(MagickFalse);
2459 draw_image->columns=draw_info->width;
2460 draw_image->rows=draw_info->height;
2461 /*
2462 Transfer drawn X image to image.
2463 */
2464 width=(unsigned int) image->columns;
2465 height=(unsigned int) image->rows;
2466 x=0;
2467 y=0;
2468 (void) XParseGeometry(draw_info->geometry,&x,&y,&width,&height);
cristyc57f6942010-11-12 01:47:39 +00002469 (void) GetOneVirtualPixel(image,(ssize_t) x,(ssize_t) y,
2470 &draw_image->background_color,&image->exception);
cristy574cc262011-08-05 01:23:58 +00002471 if (SetImageStorageClass(draw_image,DirectClass,&image->exception) == MagickFalse)
cristy3ed852e2009-09-05 21:47:34 +00002472 return(MagickFalse);
2473 draw_image->matte=MagickTrue;
2474 exception=(&image->exception);
cristyc57f6942010-11-12 01:47:39 +00002475 draw_view=AcquireCacheView(draw_image);
cristy3ed852e2009-09-05 21:47:34 +00002476 for (y=0; y < (int) draw_image->rows; y++)
2477 {
cristyc57f6942010-11-12 01:47:39 +00002478 register int
cristy3ed852e2009-09-05 21:47:34 +00002479 x;
2480
cristy4c08aed2011-07-01 19:47:50 +00002481 register Quantum
cristyc47d1f82009-11-26 01:44:43 +00002482 *restrict q;
cristy3ed852e2009-09-05 21:47:34 +00002483
cristyc57f6942010-11-12 01:47:39 +00002484 q=QueueCacheViewAuthenticPixels(draw_view,0,(ssize_t) y,draw_image->columns,
2485 1,exception);
cristyacd2ed22011-08-30 01:44:23 +00002486 if (q == (Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00002487 break;
cristyc57f6942010-11-12 01:47:39 +00002488 for (x=0; x < (int) draw_image->columns; x++)
cristy3ed852e2009-09-05 21:47:34 +00002489 {
2490 if (XGetPixel(draw_ximage,x,y) == 0)
2491 {
2492 /*
2493 Set this pixel to the background color.
2494 */
cristy4c08aed2011-07-01 19:47:50 +00002495 SetPixelPacket(draw_image,&draw_image->background_color,q);
2496 SetPixelAlpha(draw_image,(Quantum) (draw_info->stencil ==
2497 OpaqueStencil ? TransparentAlpha : OpaqueAlpha),q);
cristy3ed852e2009-09-05 21:47:34 +00002498 }
2499 else
2500 {
2501 /*
2502 Set this pixel to the pen color.
2503 */
cristy4c08aed2011-07-01 19:47:50 +00002504 SetPixelRed(draw_image,ScaleShortToQuantum(
2505 pixel->pen_color.red),q);
2506 SetPixelGreen(draw_image,ScaleShortToQuantum(
2507 pixel->pen_color.green),q);
2508 SetPixelBlue(draw_image,ScaleShortToQuantum(
2509 pixel->pen_color.blue),q);
2510 SetPixelAlpha(draw_image,(Quantum) (draw_info->stencil ==
2511 OpaqueStencil ? OpaqueAlpha : TransparentAlpha),q);
cristy3ed852e2009-09-05 21:47:34 +00002512 }
cristyed231572011-07-14 02:18:59 +00002513 q+=GetPixelChannels(draw_image);
cristy3ed852e2009-09-05 21:47:34 +00002514 }
cristyc57f6942010-11-12 01:47:39 +00002515 if (SyncCacheViewAuthenticPixels(draw_view,exception) == MagickFalse)
cristy3ed852e2009-09-05 21:47:34 +00002516 break;
2517 }
cristyc57f6942010-11-12 01:47:39 +00002518 draw_view=DestroyCacheView(draw_view);
cristy3ed852e2009-09-05 21:47:34 +00002519 XDestroyImage(draw_ximage);
2520 /*
2521 Determine draw geometry.
2522 */
2523 (void) XParseGeometry(draw_info->geometry,&x,&y,&width,&height);
2524 if ((width != (unsigned int) draw_image->columns) ||
2525 (height != (unsigned int) draw_image->rows))
2526 {
2527 char
2528 image_geometry[MaxTextExtent];
2529
2530 /*
2531 Scale image.
2532 */
cristyb51dff52011-05-19 16:55:47 +00002533 (void) FormatLocaleString(image_geometry,MaxTextExtent,"%ux%u",
cristy3ed852e2009-09-05 21:47:34 +00002534 width,height);
2535 (void) TransformImage(&draw_image,(char *) NULL,image_geometry);
2536 }
2537 if (draw_info->degrees != 0.0)
2538 {
2539 Image
2540 *rotate_image;
2541
2542 int
2543 rotations;
2544
2545 MagickRealType
2546 normalized_degrees;
2547
2548 /*
2549 Rotate image.
2550 */
2551 rotate_image=RotateImage(draw_image,draw_info->degrees,&image->exception);
2552 if (rotate_image == (Image *) NULL)
2553 return(MagickFalse);
2554 draw_image=DestroyImage(draw_image);
2555 draw_image=rotate_image;
2556 /*
2557 Annotation is relative to the degree of rotation.
2558 */
2559 normalized_degrees=draw_info->degrees;
2560 while (normalized_degrees < -45.0)
2561 normalized_degrees+=360.0;
2562 for (rotations=0; normalized_degrees > 45.0; rotations++)
2563 normalized_degrees-=90.0;
2564 switch (rotations % 4)
2565 {
2566 default:
2567 case 0:
2568 break;
2569 case 1:
2570 {
2571 /*
2572 Rotate 90 degrees.
2573 */
2574 x=x-(int) draw_image->columns/2;
2575 y=y+(int) draw_image->columns/2;
2576 break;
2577 }
2578 case 2:
2579 {
2580 /*
2581 Rotate 180 degrees.
2582 */
2583 x=x-(int) draw_image->columns;
2584 break;
2585 }
2586 case 3:
2587 {
2588 /*
2589 Rotate 270 degrees.
2590 */
2591 x=x-(int) draw_image->columns/2;
2592 y=y-(int) (draw_image->rows-(draw_image->columns/2));
2593 break;
2594 }
2595 }
2596 }
2597 /*
2598 Composite text onto the image.
2599 */
cristyc57f6942010-11-12 01:47:39 +00002600 draw_view=AcquireCacheView(draw_image);
cristy3ed852e2009-09-05 21:47:34 +00002601 for (y=0; y < (int) draw_image->rows; y++)
2602 {
cristyc57f6942010-11-12 01:47:39 +00002603 register int
cristy3ed852e2009-09-05 21:47:34 +00002604 x;
2605
cristy4c08aed2011-07-01 19:47:50 +00002606 register Quantum
cristyc47d1f82009-11-26 01:44:43 +00002607 *restrict q;
cristy3ed852e2009-09-05 21:47:34 +00002608
cristyc57f6942010-11-12 01:47:39 +00002609 q=GetCacheViewAuthenticPixels(draw_view,0,(ssize_t) y,draw_image->columns,1,
2610 exception);
cristyacd2ed22011-08-30 01:44:23 +00002611 if (q == (Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00002612 break;
cristyc57f6942010-11-12 01:47:39 +00002613 for (x=0; x < (int) draw_image->columns; x++)
cristy3ed852e2009-09-05 21:47:34 +00002614 {
cristy4c08aed2011-07-01 19:47:50 +00002615 if (GetPixelAlpha(image,q) != TransparentAlpha)
2616 SetPixelAlpha(draw_image,OpaqueAlpha,q);
cristyed231572011-07-14 02:18:59 +00002617 q+=GetPixelChannels(draw_image);
cristy3ed852e2009-09-05 21:47:34 +00002618 }
cristyc57f6942010-11-12 01:47:39 +00002619 if (SyncCacheViewAuthenticPixels(draw_view,exception) == MagickFalse)
cristy3ed852e2009-09-05 21:47:34 +00002620 break;
2621 }
cristyc57f6942010-11-12 01:47:39 +00002622 draw_view=DestroyCacheView(draw_view);
cristy3ed852e2009-09-05 21:47:34 +00002623 (void) XParseGeometry(draw_info->geometry,&x,&y,&width,&height);
2624 if (draw_info->stencil == TransparentStencil)
cristyc57f6942010-11-12 01:47:39 +00002625 (void) CompositeImage(image,CopyOpacityCompositeOp,draw_image,(ssize_t) x,
2626 (ssize_t) y);
cristy3ed852e2009-09-05 21:47:34 +00002627 else
2628 {
2629 matte=image->matte;
cristyc57f6942010-11-12 01:47:39 +00002630 (void) CompositeImage(image,OverCompositeOp,draw_image,(ssize_t) x,
2631 (ssize_t) y);
cristy3ed852e2009-09-05 21:47:34 +00002632 image->matte=matte;
2633 }
2634 draw_image=DestroyImage(draw_image);
2635 return(MagickTrue);
2636}
2637
2638/*
2639%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2640% %
2641% %
2642% %
2643% X E r r o r %
2644% %
2645% %
2646% %
2647%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2648%
2649% XError() ignores BadWindow errors for XQueryTree and XGetWindowAttributes,
2650% and ignores BadDrawable errors for XGetGeometry, and ignores BadValue errors
cristybcbda3f2011-09-03 13:01:22 +00002651% for XQueryColor. It returns MagickFalse in those cases. Otherwise it
2652% returns True.
cristy3ed852e2009-09-05 21:47:34 +00002653%
2654% The format of the XError function is:
2655%
cristybcbda3f2011-09-03 13:01:22 +00002656% int XError(display,error)
cristy3ed852e2009-09-05 21:47:34 +00002657%
2658% A description of each parameter follows:
2659%
2660% o display: Specifies a pointer to the Display structure; returned from
2661% XOpenDisplay.
2662%
2663% o error: Specifies the error event.
2664%
2665*/
2666
2667#if defined(__cplusplus) || defined(c_plusplus)
2668extern "C" {
2669#endif
2670
2671MagickExport int XError(Display *display,XErrorEvent *error)
2672{
2673 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
2674 assert(display != (Display *) NULL);
2675 assert(error != (XErrorEvent *) NULL);
2676 xerror_alert=MagickTrue;
2677 switch (error->request_code)
2678 {
2679 case X_GetGeometry:
2680 {
2681 if ((int) error->error_code == BadDrawable)
2682 return(MagickFalse);
2683 break;
2684 }
2685 case X_GetWindowAttributes:
2686 case X_QueryTree:
2687 {
2688 if ((int) error->error_code == BadWindow)
2689 return(MagickFalse);
2690 break;
2691 }
2692 case X_QueryColors:
2693 {
2694 if ((int) error->error_code == BadValue)
2695 return(MagickFalse);
2696 break;
2697 }
2698 }
2699 return(MagickTrue);
2700}
2701
2702#if defined(__cplusplus) || defined(c_plusplus)
2703}
2704#endif
2705
2706/*
2707%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2708% %
2709% %
2710% %
2711% X F r e e R e s o u r c e s %
2712% %
2713% %
2714% %
2715%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2716%
2717% XFreeResources() frees X11 resources.
2718%
2719% The format of the XFreeResources method is:
2720%
2721% void XFreeResources(Display *display,XVisualInfo *visual_info,
2722% XStandardColormap *map_info,XPixelInfo *pixel,XFontStruct *font_info,
2723% XResourceInfo *resource_info,XWindowInfo *window_info)
2724% resource_info,window_info)
2725%
2726% A description of each parameter follows:
2727%
2728% o display: Specifies a connection to an X server; returned from
2729% XOpenDisplay.
2730%
2731% o visual_info: Specifies a pointer to a X11 XVisualInfo structure;
2732% returned from XGetVisualInfo.
2733%
2734% o map_info: If map_type is specified, this structure is initialized
2735% with info from the Standard Colormap.
2736%
2737% o pixel: Specifies a pointer to a XPixelInfo structure.
2738%
2739% o font_info: Specifies a pointer to a XFontStruct structure.
2740%
2741% o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
2742%
2743% o window_info: Specifies a pointer to a X11 XWindowInfo structure.
2744%
2745*/
cristybcbda3f2011-09-03 13:01:22 +00002746MagickPrivate void XFreeResources(Display *display,XVisualInfo *visual_info,
cristy3ed852e2009-09-05 21:47:34 +00002747 XStandardColormap *map_info,XPixelInfo *pixel,XFontStruct *font_info,
2748 XResourceInfo *resource_info,XWindowInfo *window_info)
2749{
2750 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
2751 assert(display != (Display *) NULL);
2752 assert(resource_info != (XResourceInfo *) NULL);
2753 if (window_info != (XWindowInfo *) NULL)
2754 {
2755 /*
2756 Free X image.
2757 */
2758 if (window_info->ximage != (XImage *) NULL)
2759 XDestroyImage(window_info->ximage);
2760 if (window_info->id != (Window) NULL)
2761 {
2762 /*
2763 Free destroy window and free cursors.
2764 */
2765 if (window_info->id != XRootWindow(display,visual_info->screen))
2766 (void) XDestroyWindow(display,window_info->id);
2767 if (window_info->annotate_context != (GC) NULL)
2768 (void) XFreeGC(display,window_info->annotate_context);
2769 if (window_info->highlight_context != (GC) NULL)
2770 (void) XFreeGC(display,window_info->highlight_context);
2771 if (window_info->widget_context != (GC) NULL)
2772 (void) XFreeGC(display,window_info->widget_context);
2773 if (window_info->cursor != (Cursor) NULL)
2774 (void) XFreeCursor(display,window_info->cursor);
2775 window_info->cursor=(Cursor) NULL;
2776 if (window_info->busy_cursor != (Cursor) NULL)
2777 (void) XFreeCursor(display,window_info->busy_cursor);
2778 window_info->busy_cursor=(Cursor) NULL;
2779 }
2780 }
2781 /*
2782 Free font.
2783 */
2784 if (font_info != (XFontStruct *) NULL)
cristyaafc1922011-03-04 16:59:40 +00002785 {
2786 (void) XFreeFont(display,font_info);
2787 font_info=(XFontStruct *) NULL;
2788 }
cristy3ed852e2009-09-05 21:47:34 +00002789 if (map_info != (XStandardColormap *) NULL)
2790 {
2791 /*
2792 Free X Standard Colormap.
2793 */
2794 if (resource_info->map_type == (char *) NULL)
2795 (void) XFreeStandardColormap(display,visual_info,map_info,pixel);
2796 (void) XFree((void *) map_info);
2797 }
2798 /*
2799 Free X visual info.
2800 */
2801 if (visual_info != (XVisualInfo *) NULL)
2802 (void) XFree((void *) visual_info);
2803 if (resource_info->close_server != MagickFalse)
2804 (void) XCloseDisplay(display);
2805}
2806
2807/*
2808%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2809% %
2810% %
2811% %
2812% X F r e e S t a n d a r d C o l o r m a p %
2813% %
2814% %
2815% %
2816%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2817%
2818% XFreeStandardColormap() frees an X11 colormap.
2819%
2820% The format of the XFreeStandardColormap method is:
2821%
2822% void XFreeStandardColormap(Display *display,
2823% const XVisualInfo *visual_info,XStandardColormap *map_info,
2824% XPixelInfo *pixel)
2825%
2826% A description of each parameter follows:
2827%
2828% o display: Specifies a connection to an X server; returned from
2829% XOpenDisplay.
2830%
2831% o visual_info: Specifies a pointer to a X11 XVisualInfo structure;
2832% returned from XGetVisualInfo.
2833%
2834% o map_info: If map_type is specified, this structure is initialized
2835% with info from the Standard Colormap.
2836%
2837% o pixel: Specifies a pointer to a XPixelInfo structure.
2838%
2839*/
cristybcbda3f2011-09-03 13:01:22 +00002840MagickPrivate void XFreeStandardColormap(Display *display,
cristy3ed852e2009-09-05 21:47:34 +00002841 const XVisualInfo *visual_info,XStandardColormap *map_info,XPixelInfo *pixel)
2842{
2843 /*
2844 Free colormap.
2845 */
2846 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
2847 assert(display != (Display *) NULL);
2848 assert(visual_info != (XVisualInfo *) NULL);
2849 assert(map_info != (XStandardColormap *) NULL);
2850 (void) XFlush(display);
2851 if (map_info->colormap != (Colormap) NULL)
2852 {
2853 if (map_info->colormap != XDefaultColormap(display,visual_info->screen))
2854 (void) XFreeColormap(display,map_info->colormap);
2855 else
2856 if (pixel != (XPixelInfo *) NULL)
2857 if ((visual_info->klass != TrueColor) &&
2858 (visual_info->klass != DirectColor))
2859 (void) XFreeColors(display,map_info->colormap,pixel->pixels,
2860 (int) pixel->colors,0);
2861 }
2862 map_info->colormap=(Colormap) NULL;
2863 if (pixel != (XPixelInfo *) NULL)
2864 {
cristyf2faecf2010-05-28 19:19:36 +00002865 if (pixel->pixels != (unsigned long *) NULL)
2866 pixel->pixels=(unsigned long *) RelinquishMagickMemory(pixel->pixels);
2867 pixel->pixels=(unsigned long *) NULL;
cristy3ed852e2009-09-05 21:47:34 +00002868 }
2869}
2870
2871/*
2872%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2873% %
2874% %
2875% %
2876% X G e t A n n o t a t e I n f o %
2877% %
2878% %
2879% %
2880%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2881%
2882% XGetAnnotateInfo() initializes the AnnotateInfo structure.
2883%
2884% The format of the XGetAnnotateInfo method is:
2885%
2886% void XGetAnnotateInfo(XAnnotateInfo *annotate_info)
2887%
2888% A description of each parameter follows:
2889%
2890% o annotate_info: Specifies a pointer to a XAnnotateInfo structure.
2891%
2892*/
cristybcbda3f2011-09-03 13:01:22 +00002893MagickPrivate void XGetAnnotateInfo(XAnnotateInfo *annotate_info)
cristy3ed852e2009-09-05 21:47:34 +00002894{
2895 /*
2896 Initialize annotate structure.
2897 */
2898 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
2899 assert(annotate_info != (XAnnotateInfo *) NULL);
2900 annotate_info->x=0;
2901 annotate_info->y=0;
2902 annotate_info->width=0;
2903 annotate_info->height=0;
2904 annotate_info->stencil=ForegroundStencil;
2905 annotate_info->degrees=0.0;
2906 annotate_info->font_info=(XFontStruct *) NULL;
2907 annotate_info->text=(char *) NULL;
2908 *annotate_info->geometry='\0';
2909 annotate_info->previous=(XAnnotateInfo *) NULL;
2910 annotate_info->next=(XAnnotateInfo *) NULL;
2911 (void) XSupportsLocale();
2912 (void) XSetLocaleModifiers("");
2913}
2914
2915/*
2916%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2917% %
2918% %
2919% %
2920% X G e t M a p I n f o %
2921% %
2922% %
2923% %
2924%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2925%
2926% XGetMapInfo() initializes the XStandardColormap structure.
2927%
2928% The format of the XStandardColormap method is:
2929%
2930% void XGetMapInfo(const XVisualInfo *visual_info,const Colormap colormap,
2931% XStandardColormap *map_info)
2932%
2933% A description of each parameter follows:
2934%
2935% o colormap: Specifies the ID of the X server colormap.
2936%
2937% o visual_info: Specifies a pointer to a X11 XVisualInfo structure;
2938% returned from XGetVisualInfo.
2939%
2940% o map_info: Specifies a pointer to a X11 XStandardColormap structure.
2941%
2942*/
cristybcbda3f2011-09-03 13:01:22 +00002943MagickPrivate void XGetMapInfo(const XVisualInfo *visual_info,
cristy3ed852e2009-09-05 21:47:34 +00002944 const Colormap colormap,XStandardColormap *map_info)
2945{
2946 /*
2947 Initialize map info.
2948 */
2949 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
2950 assert(visual_info != (XVisualInfo *) NULL);
2951 assert(map_info != (XStandardColormap *) NULL);
2952 map_info->colormap=colormap;
2953 map_info->red_max=visual_info->red_mask;
cristybb503372010-05-27 20:51:26 +00002954 map_info->red_mult=(size_t) (map_info->red_max != 0 ? 1 : 0);
cristy3ed852e2009-09-05 21:47:34 +00002955 if (map_info->red_max != 0)
2956 while ((map_info->red_max & 0x01) == 0)
2957 {
2958 map_info->red_max>>=1;
2959 map_info->red_mult<<=1;
2960 }
2961 map_info->green_max=visual_info->green_mask;
cristybb503372010-05-27 20:51:26 +00002962 map_info->green_mult=(size_t) (map_info->green_max != 0 ? 1 : 0);
cristy3ed852e2009-09-05 21:47:34 +00002963 if (map_info->green_max != 0)
2964 while ((map_info->green_max & 0x01) == 0)
2965 {
2966 map_info->green_max>>=1;
2967 map_info->green_mult<<=1;
2968 }
2969 map_info->blue_max=visual_info->blue_mask;
cristybb503372010-05-27 20:51:26 +00002970 map_info->blue_mult=(size_t) (map_info->blue_max != 0 ? 1 : 0);
cristy3ed852e2009-09-05 21:47:34 +00002971 if (map_info->blue_max != 0)
2972 while ((map_info->blue_max & 0x01) == 0)
2973 {
2974 map_info->blue_max>>=1;
2975 map_info->blue_mult<<=1;
2976 }
2977 map_info->base_pixel=0;
2978}
2979
2980/*
2981%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2982% %
2983% %
2984% %
2985% X G e t P i x e l I n f o %
2986% %
2987% %
2988% %
2989%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2990%
cristy4c08aed2011-07-01 19:47:50 +00002991% XGetPixelInfo() initializes the PixelPacket structure.
cristy3ed852e2009-09-05 21:47:34 +00002992%
cristy4c08aed2011-07-01 19:47:50 +00002993% The format of the XGetPixelInfo method is:
cristy3ed852e2009-09-05 21:47:34 +00002994%
cristy4c08aed2011-07-01 19:47:50 +00002995% void XGetPixelInfo(Display *display,const XVisualInfo *visual_info,
cristy3ed852e2009-09-05 21:47:34 +00002996% const XStandardColormap *map_info,const XResourceInfo *resource_info,
2997% Image *image,XPixelInfo *pixel)
2998% pixel)
2999%
3000% A description of each parameter follows:
3001%
3002% o display: Specifies a connection to an X server; returned from
3003% XOpenDisplay.
3004%
3005% o visual_info: Specifies a pointer to a X11 XVisualInfo structure;
3006% returned from XGetVisualInfo.
3007%
3008% o map_info: If map_type is specified, this structure is initialized
3009% with info from the Standard Colormap.
3010%
3011% o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
3012%
3013% o image: the image.
3014%
3015% o pixel: Specifies a pointer to a XPixelInfo structure.
3016%
3017*/
cristybcbda3f2011-09-03 13:01:22 +00003018MagickPrivate void XGetPixelInfo(Display *display,
cristy3ed852e2009-09-05 21:47:34 +00003019 const XVisualInfo *visual_info,const XStandardColormap *map_info,
3020 const XResourceInfo *resource_info,Image *image,XPixelInfo *pixel)
3021{
3022 static const char
3023 *PenColors[MaxNumberPens]=
3024 {
3025 "#000000000000", /* black */
3026 "#00000000ffff", /* blue */
3027 "#0000ffffffff", /* cyan */
3028 "#0000ffff0000", /* green */
3029 "#bdbdbdbdbdbd", /* gray */
3030 "#ffff00000000", /* red */
3031 "#ffff0000ffff", /* magenta */
3032 "#ffffffff0000", /* yellow */
3033 "#ffffffffffff", /* white */
3034 "#bdbdbdbdbdbd", /* gray */
3035 "#bdbdbdbdbdbd" /* gray */
3036 };
3037
3038 Colormap
3039 colormap;
3040
cristybb503372010-05-27 20:51:26 +00003041 register ssize_t
cristy3ed852e2009-09-05 21:47:34 +00003042 i;
3043
3044 Status
3045 status;
3046
3047 unsigned int
3048 packets;
3049
3050 /*
3051 Initialize pixel info.
3052 */
3053 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
3054 assert(display != (Display *) NULL);
3055 assert(visual_info != (XVisualInfo *) NULL);
3056 assert(map_info != (XStandardColormap *) NULL);
3057 assert(resource_info != (XResourceInfo *) NULL);
3058 assert(pixel != (XPixelInfo *) NULL);
3059 pixel->colors=0;
3060 if (image != (Image *) NULL)
3061 if (image->storage_class == PseudoClass)
cristyc57f6942010-11-12 01:47:39 +00003062 pixel->colors=(ssize_t) image->colors;
cristy3ed852e2009-09-05 21:47:34 +00003063 packets=(unsigned int)
3064 MagickMax((int) pixel->colors,visual_info->colormap_size)+MaxNumberPens;
cristyf2faecf2010-05-28 19:19:36 +00003065 if (pixel->pixels != (unsigned long *) NULL)
3066 pixel->pixels=(unsigned long *) RelinquishMagickMemory(pixel->pixels);
3067 pixel->pixels=(unsigned long *) AcquireQuantumMemory(packets,
cristy3ed852e2009-09-05 21:47:34 +00003068 sizeof(pixel->pixels));
cristyf2faecf2010-05-28 19:19:36 +00003069 if (pixel->pixels == (unsigned long *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00003070 ThrowXWindowFatalException(ResourceLimitFatalError,"UnableToGetPixelInfo",
3071 image->filename);
3072 /*
3073 Set foreground color.
3074 */
3075 colormap=map_info->colormap;
3076 (void) XParseColor(display,colormap,(char *) ForegroundColor,
3077 &pixel->foreground_color);
3078 status=XParseColor(display,colormap,resource_info->foreground_color,
3079 &pixel->foreground_color);
3080 if (status == False)
3081 ThrowXWindowFatalException(XServerError,"ColorIsNotKnownToServer",
3082 resource_info->foreground_color);
3083 pixel->foreground_color.pixel=
3084 XStandardPixel(map_info,&pixel->foreground_color);
3085 pixel->foreground_color.flags=(char) (DoRed | DoGreen | DoBlue);
3086 /*
3087 Set background color.
3088 */
3089 (void) XParseColor(display,colormap,"#d6d6d6d6d6d6",&pixel->background_color);
3090 status=XParseColor(display,colormap,resource_info->background_color,
3091 &pixel->background_color);
3092 if (status == False)
3093 ThrowXWindowFatalException(XServerError,"ColorIsNotKnownToServer",
3094 resource_info->background_color);
3095 pixel->background_color.pixel=
3096 XStandardPixel(map_info,&pixel->background_color);
3097 pixel->background_color.flags=(char) (DoRed | DoGreen | DoBlue);
3098 /*
3099 Set border color.
3100 */
3101 (void) XParseColor(display,colormap,(char *) BorderColor,
3102 &pixel->border_color);
3103 status=XParseColor(display,colormap,resource_info->border_color,
3104 &pixel->border_color);
3105 if (status == False)
3106 ThrowXWindowFatalException(XServerError,"ColorIsNotKnownToServer",
3107 resource_info->border_color);
3108 pixel->border_color.pixel=XStandardPixel(map_info,&pixel->border_color);
3109 pixel->border_color.flags=(char) (DoRed | DoGreen | DoBlue);
3110 /*
3111 Set matte color.
3112 */
3113 pixel->matte_color=pixel->background_color;
3114 if (resource_info->matte_color != (char *) NULL)
3115 {
3116 /*
3117 Matte color is specified as a X resource or command line argument.
3118 */
3119 status=XParseColor(display,colormap,resource_info->matte_color,
3120 &pixel->matte_color);
3121 if (status == False)
3122 ThrowXWindowFatalException(XServerError,"ColorIsNotKnownToServer",
3123 resource_info->matte_color);
3124 pixel->matte_color.pixel=XStandardPixel(map_info,&pixel->matte_color);
3125 pixel->matte_color.flags=(char) (DoRed | DoGreen | DoBlue);
3126 }
3127 /*
3128 Set highlight color.
3129 */
3130 pixel->highlight_color.red=(unsigned short) ((
3131 pixel->matte_color.red*ScaleQuantumToShort(HighlightModulate))/65535L+
3132 (ScaleQuantumToShort((Quantum) (QuantumRange-HighlightModulate))));
3133 pixel->highlight_color.green=(unsigned short) ((
3134 pixel->matte_color.green*ScaleQuantumToShort(HighlightModulate))/65535L+
3135 (ScaleQuantumToShort((Quantum) (QuantumRange-HighlightModulate))));
3136 pixel->highlight_color.blue=(unsigned short) ((
3137 pixel->matte_color.blue*ScaleQuantumToShort(HighlightModulate))/65535L+
3138 (ScaleQuantumToShort((Quantum) (QuantumRange-HighlightModulate))));
3139 pixel->highlight_color.pixel=
3140 XStandardPixel(map_info,&pixel->highlight_color);
3141 pixel->highlight_color.flags=(char) (DoRed | DoGreen | DoBlue);
3142 /*
3143 Set shadow color.
3144 */
3145 pixel->shadow_color.red=(unsigned short) (((MagickRealType)
3146 pixel->matte_color.red*ScaleQuantumToShort(ShadowModulate))/65535L);
3147 pixel->shadow_color.green=(unsigned short) (((MagickRealType)
3148 pixel->matte_color.green*ScaleQuantumToShort(ShadowModulate))/65535L);
3149 pixel->shadow_color.blue=(unsigned short) (((MagickRealType)
3150 pixel->matte_color.blue*ScaleQuantumToShort(ShadowModulate))/65535L);
3151 pixel->shadow_color.pixel=XStandardPixel(map_info,&pixel->shadow_color);
3152 pixel->shadow_color.flags=(char) (DoRed | DoGreen | DoBlue);
3153 /*
3154 Set depth color.
3155 */
3156 pixel->depth_color.red=(unsigned short) (((MagickRealType)
3157 pixel->matte_color.red*ScaleQuantumToShort(DepthModulate))/65535L);
3158 pixel->depth_color.green=(unsigned short) (((MagickRealType)
3159 pixel->matte_color.green*ScaleQuantumToShort(DepthModulate))/65535L);
3160 pixel->depth_color.blue=(unsigned short) (((MagickRealType)
3161 pixel->matte_color.blue*ScaleQuantumToShort(DepthModulate))/65535L);
3162 pixel->depth_color.pixel=XStandardPixel(map_info,&pixel->depth_color);
3163 pixel->depth_color.flags=(char) (DoRed | DoGreen | DoBlue);
3164 /*
3165 Set trough color.
3166 */
3167 pixel->trough_color.red=(unsigned short) (((MagickRealType)
3168 pixel->matte_color.red*ScaleQuantumToShort(TroughModulate))/65535L);
3169 pixel->trough_color.green=(unsigned short) (((MagickRealType)
3170 pixel->matte_color.green*ScaleQuantumToShort(TroughModulate))/65535L);
3171 pixel->trough_color.blue=(unsigned short) (((MagickRealType)
3172 pixel->matte_color.blue*ScaleQuantumToShort(TroughModulate))/65535L);
3173 pixel->trough_color.pixel=XStandardPixel(map_info,&pixel->trough_color);
3174 pixel->trough_color.flags=(char) (DoRed | DoGreen | DoBlue);
3175 /*
3176 Set pen color.
3177 */
3178 for (i=0; i < MaxNumberPens; i++)
3179 {
3180 (void) XParseColor(display,colormap,(char *) PenColors[i],
3181 &pixel->pen_colors[i]);
3182 status=XParseColor(display,colormap,resource_info->pen_colors[i],
3183 &pixel->pen_colors[i]);
3184 if (status == False)
3185 ThrowXWindowFatalException(XServerError,"ColorIsNotKnownToServer",
3186 resource_info->pen_colors[i]);
3187 pixel->pen_colors[i].pixel=XStandardPixel(map_info,&pixel->pen_colors[i]);
3188 pixel->pen_colors[i].flags=(char) (DoRed | DoGreen | DoBlue);
3189 }
3190 pixel->box_color=pixel->background_color;
3191 pixel->pen_color=pixel->foreground_color;
3192 pixel->box_index=0;
3193 pixel->pen_index=1;
3194 if (image != (Image *) NULL)
3195 {
3196 if ((resource_info->gamma_correct != MagickFalse) &&
3197 (image->gamma != 0.0))
3198 {
3199 GeometryInfo
3200 geometry_info;
3201
3202 MagickStatusType
3203 flags;
3204
3205 /*
3206 Initialize map relative to display and image gamma.
3207 */
3208 flags=ParseGeometry(resource_info->display_gamma,&geometry_info);
3209 red_gamma=geometry_info.rho;
3210 green_gamma=geometry_info.sigma;
3211 if ((flags & SigmaValue) == 0)
3212 green_gamma=red_gamma;
3213 blue_gamma=geometry_info.xi;
3214 if ((flags & XiValue) == 0)
3215 blue_gamma=red_gamma;
3216 red_gamma*=image->gamma;
3217 green_gamma*=image->gamma;
3218 blue_gamma*=image->gamma;
3219 }
3220 if (image->storage_class == PseudoClass)
3221 {
3222 /*
3223 Initialize pixel array for images of type PseudoClass.
3224 */
cristybb503372010-05-27 20:51:26 +00003225 for (i=0; i < (ssize_t) image->colors; i++)
cristy4c08aed2011-07-01 19:47:50 +00003226 pixel->pixels[i]=XGammaPacket(map_info,image->colormap+i);
cristy3ed852e2009-09-05 21:47:34 +00003227 for (i=0; i < MaxNumberPens; i++)
3228 pixel->pixels[image->colors+i]=pixel->pen_colors[i].pixel;
3229 pixel->colors+=MaxNumberPens;
3230 }
3231 }
3232}
3233
3234/*
3235%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3236% %
3237% %
3238% %
3239% X G e t R e s o u r c e C l a s s %
3240% %
3241% %
3242% %
3243%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3244%
3245% XGetResourceClass() queries the X server for the specified resource name or
3246% class. If the resource name or class is not defined in the database, the
3247% supplied default value is returned.
3248%
3249% The format of the XGetResourceClass method is:
3250%
3251% char *XGetResourceClass(XrmDatabase database,const char *client_name,
3252% const char *keyword,char *resource_default)
3253%
3254% A description of each parameter follows:
3255%
3256% o database: Specifies a resource database; returned from
3257% XrmGetStringDatabase.
3258%
3259% o client_name: Specifies the application name used to retrieve resource
3260% info from the X server database.
3261%
3262% o keyword: Specifies the keyword of the value being retrieved.
3263%
3264% o resource_default: Specifies the default value to return if the query
3265% fails to find the specified keyword/class.
3266%
3267*/
3268MagickExport char *XGetResourceClass(XrmDatabase database,
3269 const char *client_name,const char *keyword,char *resource_default)
3270{
3271 char
3272 resource_class[MaxTextExtent],
3273 resource_name[MaxTextExtent];
3274
3275 static char
3276 *resource_type;
3277
3278 Status
3279 status;
3280
3281 XrmValue
3282 resource_value;
3283
3284 if (database == (XrmDatabase) NULL)
3285 return(resource_default);
3286 *resource_name='\0';
3287 *resource_class='\0';
3288 if (keyword != (char *) NULL)
3289 {
3290 int
3291 c,
3292 k;
3293
3294 /*
3295 Initialize resource keyword and class.
3296 */
cristyb51dff52011-05-19 16:55:47 +00003297 (void) FormatLocaleString(resource_name,MaxTextExtent,"%s.%s",
cristy3ed852e2009-09-05 21:47:34 +00003298 client_name,keyword);
3299 c=(int) (*client_name);
3300 if ((c >= XK_a) && (c <= XK_z))
3301 c-=(XK_a-XK_A);
3302 else
3303 if ((c >= XK_agrave) && (c <= XK_odiaeresis))
3304 c-=(XK_agrave-XK_Agrave);
3305 else
3306 if ((c >= XK_oslash) && (c <= XK_thorn))
3307 c-=(XK_oslash-XK_Ooblique);
3308 k=(int) (*keyword);
3309 if ((k >= XK_a) && (k <= XK_z))
3310 k-=(XK_a-XK_A);
3311 else
3312 if ((k >= XK_agrave) && (k <= XK_odiaeresis))
3313 k-=(XK_agrave-XK_Agrave);
3314 else
3315 if ((k >= XK_oslash) && (k <= XK_thorn))
3316 k-=(XK_oslash-XK_Ooblique);
cristyb51dff52011-05-19 16:55:47 +00003317 (void) FormatLocaleString(resource_class,MaxTextExtent,"%c%s.%c%s",c,
cristy3ed852e2009-09-05 21:47:34 +00003318 client_name+1,k,keyword+1);
3319 }
3320 status=XrmGetResource(database,resource_name,resource_class,&resource_type,
3321 &resource_value);
3322 if (status == False)
3323 return(resource_default);
3324 return(resource_value.addr);
3325}
3326
3327/*
3328%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3329% %
3330% %
3331% %
3332% X G e t R e s o u r c e D a t a b a s e %
3333% %
3334% %
3335% %
3336%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3337%
3338% XGetResourceDatabase() creates a new resource database and initializes it.
3339%
3340% The format of the XGetResourceDatabase method is:
3341%
3342% XrmDatabase XGetResourceDatabase(Display *display,
3343% const char *client_name)
3344%
3345% A description of each parameter follows:
3346%
3347% o database: XGetResourceDatabase() returns the database after it is
3348% initialized.
3349%
3350% o display: Specifies a connection to an X server; returned from
3351% XOpenDisplay.
3352%
3353% o client_name: Specifies the application name used to retrieve resource
3354% info from the X server database.
3355%
3356*/
3357MagickExport XrmDatabase XGetResourceDatabase(Display *display,
3358 const char *client_name)
3359{
3360 char
3361 filename[MaxTextExtent];
3362
3363 int
3364 c;
3365
3366 register const char
3367 *p;
3368
3369 XrmDatabase
3370 resource_database,
3371 server_database;
3372
3373 if (display == (Display *) NULL)
3374 return((XrmDatabase) NULL);
3375 assert(client_name != (char *) NULL);
3376 /*
3377 Initialize resource database.
3378 */
3379 XrmInitialize();
3380 (void) XGetDefault(display,(char *) client_name,"dummy");
3381 resource_database=XrmGetDatabase(display);
3382 /*
3383 Combine application database.
3384 */
3385 if (client_name != (char *) NULL)
3386 {
3387 /*
3388 Get basename of client.
3389 */
3390 p=client_name+(strlen(client_name)-1);
3391 while ((p > client_name) && (*p != '/'))
3392 p--;
3393 if (*p == '/')
3394 client_name=p+1;
3395 }
3396 c=(int) (*client_name);
3397 if ((c >= XK_a) && (c <= XK_z))
3398 c-=(XK_a-XK_A);
3399 else
3400 if ((c >= XK_agrave) && (c <= XK_odiaeresis))
3401 c-=(XK_agrave-XK_Agrave);
3402 else
3403 if ((c >= XK_oslash) && (c <= XK_thorn))
3404 c-=(XK_oslash-XK_Ooblique);
3405#if defined(X11_APPLICATION_PATH)
cristyb51dff52011-05-19 16:55:47 +00003406 (void) FormatLocaleString(filename,MaxTextExtent,"%s%c%s",
cristy3ed852e2009-09-05 21:47:34 +00003407 X11_APPLICATION_PATH,c,client_name+1);
3408 (void) XrmCombineFileDatabase(filename,&resource_database,MagickFalse);
3409#endif
3410 if (XResourceManagerString(display) != (char *) NULL)
3411 {
3412 /*
3413 Combine server database.
3414 */
3415 server_database=XrmGetStringDatabase(XResourceManagerString(display));
3416 XrmCombineDatabase(server_database,&resource_database,MagickFalse);
3417 }
3418 /*
3419 Merge user preferences database.
3420 */
3421#if defined(X11_PREFERENCES_PATH)
cristyb51dff52011-05-19 16:55:47 +00003422 (void) FormatLocaleString(filename,MaxTextExtent,"%s%src",
cristy3ed852e2009-09-05 21:47:34 +00003423 X11_PREFERENCES_PATH,client_name);
3424 ExpandFilename(filename);
3425 (void) XrmCombineFileDatabase(filename,&resource_database,MagickFalse);
3426#endif
3427 return(resource_database);
3428}
3429
3430/*
3431%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3432% %
3433% %
3434% %
3435% X G e t R e s o u r c e I n f o %
3436% %
3437% %
3438% %
3439%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3440%
3441% XGetResourceInfo(image_info,) initializes the ResourceInfo structure.
3442%
3443% The format of the XGetResourceInfo method is:
3444%
3445% void XGetResourceInfo(const ImageInfo *image_info,XrmDatabase database,
3446% const char *client_name,XResourceInfo *resource_info)
3447%
3448% A description of each parameter follows:
3449%
3450% o image_info: the image info.
3451%
3452% o database: Specifies a resource database; returned from
3453% XrmGetStringDatabase.
3454%
3455% o client_name: Specifies the application name used to retrieve
3456% resource info from the X server database.
3457%
3458% o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
3459%
3460*/
3461MagickExport void XGetResourceInfo(const ImageInfo *image_info,
3462 XrmDatabase database,const char *client_name,XResourceInfo *resource_info)
3463{
3464 char
cristy00976d82011-02-20 20:31:28 +00003465 *directory,
cristy3ed852e2009-09-05 21:47:34 +00003466 *resource_value;
3467
3468 /*
3469 Initialize resource info fields.
3470 */
3471 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
3472 assert(resource_info != (XResourceInfo *) NULL);
3473 (void) ResetMagickMemory(resource_info,0,sizeof(*resource_info));
3474 resource_info->resource_database=database;
3475 resource_info->image_info=(ImageInfo *) image_info;
3476 (void) SetImageInfoProgressMonitor(resource_info->image_info,
3477 XMagickProgressMonitor,(void *) NULL);
3478 resource_info->quantize_info=CloneQuantizeInfo((QuantizeInfo *) NULL);
3479 resource_info->close_server=MagickTrue;
3480 resource_info->client_name=AcquireString(client_name);
3481 resource_value=XGetResourceClass(database,client_name,"backdrop",
3482 (char *) "False");
3483 resource_info->backdrop=IsMagickTrue(resource_value);
3484 resource_info->background_color=XGetResourceInstance(database,client_name,
3485 "background",(char *) "#d6d6d6d6d6d6");
3486 resource_info->border_color=XGetResourceInstance(database,client_name,
3487 "borderColor",BorderColor);
3488 resource_value=XGetResourceClass(database,client_name,"borderWidth",
3489 (char *) "2");
cristy00976d82011-02-20 20:31:28 +00003490 resource_info->border_width=(unsigned int) StringToUnsignedLong(
3491 resource_value);
cristy3ed852e2009-09-05 21:47:34 +00003492 resource_value=XGetResourceClass(database,client_name,"colormap",
3493 (char *) "shared");
3494 resource_info->colormap=UndefinedColormap;
3495 if (LocaleCompare("private",resource_value) == 0)
3496 resource_info->colormap=PrivateColormap;
3497 if (LocaleCompare("shared",resource_value) == 0)
3498 resource_info->colormap=SharedColormap;
3499 if (resource_info->colormap == UndefinedColormap)
3500 ThrowXWindowFatalException(OptionError,"UnrecognizedColormapType",
3501 resource_value);
3502 resource_value=XGetResourceClass(database,client_name,
3503 "colorRecovery",(char *) "False");
3504 resource_info->color_recovery=IsMagickTrue(resource_value);
3505 resource_value=XGetResourceClass(database,client_name,"confirmExit",
3506 (char *) "False");
3507 resource_info->confirm_exit=IsMagickTrue(resource_value);
3508 resource_value=XGetResourceClass(database,client_name,"confirmEdit",
3509 (char *) "False");
3510 resource_info->confirm_edit=IsMagickTrue(resource_value);
cristyba0c3252010-06-27 13:31:44 +00003511 resource_value=XGetResourceClass(database,client_name,"delay",(char *) "1");
cristye27293e2009-12-18 02:53:20 +00003512 resource_info->delay=(unsigned int) StringToUnsignedLong(resource_value);
cristy3ed852e2009-09-05 21:47:34 +00003513 resource_info->display_gamma=XGetResourceClass(database,client_name,
3514 "displayGamma",(char *) "2.2");
3515 resource_value=XGetResourceClass(database,client_name,"displayWarnings",
3516 (char *) "True");
3517 resource_info->display_warnings=IsMagickTrue(resource_value);
3518 resource_info->font=XGetResourceClass(database,client_name,"font",
3519 (char *) NULL);
3520 resource_info->font=XGetResourceClass(database,client_name,"fontList",
3521 resource_info->font);
3522 resource_info->font_name[0]=XGetResourceClass(database,client_name,"font1",
3523 (char *) "fixed");
3524 resource_info->font_name[1]=XGetResourceClass(database,client_name,"font2",
3525 (char *) "variable");
3526 resource_info->font_name[2]=XGetResourceClass(database,client_name,"font3",
3527 (char *) "5x8");
3528 resource_info->font_name[3]=XGetResourceClass(database,client_name,"font4",
3529 (char *) "6x10");
3530 resource_info->font_name[4]=XGetResourceClass(database,client_name,"font5",
3531 (char *) "7x13bold");
3532 resource_info->font_name[5]=XGetResourceClass(database,client_name,"font6",
3533 (char *) "8x13bold");
3534 resource_info->font_name[6]=XGetResourceClass(database,client_name,"font7",
3535 (char *) "9x15bold");
3536 resource_info->font_name[7]=XGetResourceClass(database,client_name,"font8",
3537 (char *) "10x20");
3538 resource_info->font_name[8]=XGetResourceClass(database,client_name,"font9",
3539 (char *) "12x24");
3540 resource_info->font_name[9]=XGetResourceClass(database,client_name,"font0",
3541 (char *) "fixed");
3542 resource_info->font_name[10]=XGetResourceClass(database,client_name,"font0",
3543 (char *) "fixed");
3544 resource_info->foreground_color=XGetResourceInstance(database,client_name,
3545 "foreground",ForegroundColor);
3546 resource_value=XGetResourceClass(database,client_name,"gammaCorrect",
3547 (char *) "True");
3548 resource_info->gamma_correct=IsMagickTrue(resource_value);
3549 resource_info->image_geometry=ConstantString(XGetResourceClass(database,
3550 client_name,"geometry",(char *) NULL));
3551 resource_value=XGetResourceClass(database,client_name,"gravity",
3552 (char *) "Center");
cristy042ee782011-04-22 18:48:30 +00003553 resource_info->gravity=(GravityType) ParseCommandOption(MagickGravityOptions,
cristy3ed852e2009-09-05 21:47:34 +00003554 MagickFalse,resource_value);
cristy00976d82011-02-20 20:31:28 +00003555 directory=getcwd(resource_info->home_directory,MaxTextExtent);
3556 (void) directory;
cristy3ed852e2009-09-05 21:47:34 +00003557 resource_info->icon_geometry=XGetResourceClass(database,client_name,
3558 "iconGeometry",(char *) NULL);
3559 resource_value=XGetResourceClass(database,client_name,"iconic",
3560 (char *) "False");
3561 resource_info->iconic=IsMagickTrue(resource_value);
3562 resource_value=XGetResourceClass(database,client_name,"immutable",
3563 LocaleCompare(client_name,"PerlMagick") == 0 ? (char *) "True" :
3564 (char *) "False");
3565 resource_info->immutable=IsMagickTrue(resource_value);
3566 resource_value=XGetResourceClass(database,client_name,"magnify",
3567 (char *) "3");
cristye27293e2009-12-18 02:53:20 +00003568 resource_info->magnify=(unsigned int) StringToUnsignedLong(resource_value);
cristy3ed852e2009-09-05 21:47:34 +00003569 resource_info->map_type=XGetResourceClass(database,client_name,"map",
3570 (char *) NULL);
3571 resource_info->matte_color=XGetResourceInstance(database,client_name,
3572 "mattecolor",(char *) NULL);
3573 resource_info->name=ConstantString(XGetResourceClass(database,client_name,
3574 "name",(char *) NULL));
3575 resource_info->pen_colors[0]=XGetResourceClass(database,client_name,"pen1",
3576 (char *) "black");
3577 resource_info->pen_colors[1]=XGetResourceClass(database,client_name,"pen2",
3578 (char *) "blue");
3579 resource_info->pen_colors[2]=XGetResourceClass(database,client_name,"pen3",
3580 (char *) "cyan");
3581 resource_info->pen_colors[3]=XGetResourceClass(database,client_name,"pen4",
3582 (char *) "green");
3583 resource_info->pen_colors[4]=XGetResourceClass(database,client_name,"pen5",
3584 (char *) "gray");
3585 resource_info->pen_colors[5]=XGetResourceClass(database,client_name,"pen6",
3586 (char *) "red");
3587 resource_info->pen_colors[6]=XGetResourceClass(database,client_name,"pen7",
3588 (char *) "magenta");
3589 resource_info->pen_colors[7]=XGetResourceClass(database,client_name,"pen8",
3590 (char *) "yellow");
3591 resource_info->pen_colors[8]=XGetResourceClass(database,client_name,"pen9",
3592 (char *) "white");
3593 resource_info->pen_colors[9]=XGetResourceClass(database,client_name,"pen0",
3594 (char *) "gray");
3595 resource_info->pen_colors[10]=XGetResourceClass(database,client_name,"pen0",
3596 (char *) "gray");
3597 resource_value=XGetResourceClass(database,client_name,"pause",(char *) "0");
cristye27293e2009-12-18 02:53:20 +00003598 resource_info->pause=(unsigned int) StringToUnsignedLong(resource_value);
cristy3ed852e2009-09-05 21:47:34 +00003599 resource_value=XGetResourceClass(database,client_name,"quantum",(char *) "1");
cristyf2f27272009-12-17 14:48:46 +00003600 resource_info->quantum=StringToLong(resource_value);
cristy3ed852e2009-09-05 21:47:34 +00003601 resource_info->text_font=XGetResourceClass(database,client_name,(char *)
3602 "font",(char *) "fixed");
3603 resource_info->text_font=XGetResourceClass(database,client_name,
3604 "textFontList",resource_info->text_font);
3605 resource_info->title=XGetResourceClass(database,client_name,"title",
3606 (char *) NULL);
3607 resource_value=XGetResourceClass(database,client_name,"undoCache",
3608 (char *) "16");
cristye27293e2009-12-18 02:53:20 +00003609 resource_info->undo_cache=(unsigned int) StringToUnsignedLong(resource_value);
cristy3ed852e2009-09-05 21:47:34 +00003610 resource_value=XGetResourceClass(database,client_name,"update",
3611 (char *) "False");
3612 resource_info->update=IsMagickTrue(resource_value);
3613 resource_value=XGetResourceClass(database,client_name,"usePixmap",
3614 (char *) "True");
3615 resource_info->use_pixmap=IsMagickTrue(resource_value);
3616 resource_value=XGetResourceClass(database,client_name,"sharedMemory",
3617 (char *) "True");
3618 resource_info->use_shared_memory=IsMagickTrue(resource_value);
3619 resource_info->visual_type=XGetResourceClass(database,client_name,"visual",
3620 (char *) NULL);
3621 resource_info->window_group=XGetResourceClass(database,client_name,
3622 "windowGroup",(char *) NULL);
3623 resource_info->window_id=XGetResourceClass(database,client_name,"window",
3624 (char *) NULL);
3625 resource_info->write_filename=XGetResourceClass(database,client_name,
3626 "writeFilename",(char *) NULL);
3627}
3628
3629/*
3630%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3631% %
3632% %
3633% %
3634% X G e t R e s o u r c e I n s t a n c e %
3635% %
3636% %
3637% %
3638%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3639%
3640% XGetResourceInstance() queries the X server for the specified resource name.
3641% If the resource name is not defined in the database, the supplied default
3642% value is returned.
3643%
3644% The format of the XGetResourceInstance method is:
3645%
3646% char *XGetResourceInstance(XrmDatabase database,const char *client_name,
3647% const char *keyword,const char *resource_default)
3648%
3649% A description of each parameter follows:
3650%
3651% o database: Specifies a resource database; returned from
3652% XrmGetStringDatabase.
3653%
3654% o client_name: Specifies the application name used to retrieve
3655% resource info from the X server database.
3656%
3657% o keyword: Specifies the keyword of the value being retrieved.
3658%
3659% o resource_default: Specifies the default value to return if the query
3660% fails to find the specified keyword/class.
3661%
3662*/
3663MagickExport char *XGetResourceInstance(XrmDatabase database,
3664 const char *client_name,const char *keyword,const char *resource_default)
3665{
3666 char
3667 *resource_type,
3668 resource_name[MaxTextExtent];
3669
3670 Status
3671 status;
3672
3673 XrmValue
3674 resource_value;
3675
3676 if (database == (XrmDatabase) NULL)
3677 return((char *) resource_default);
3678 *resource_name='\0';
3679 if (keyword != (char *) NULL)
cristyb51dff52011-05-19 16:55:47 +00003680 (void) FormatLocaleString(resource_name,MaxTextExtent,"%s.%s",client_name,
cristy3ed852e2009-09-05 21:47:34 +00003681 keyword);
3682 status=XrmGetResource(database,resource_name,"ImageMagick",&resource_type,
3683 &resource_value);
3684 if (status == False)
3685 return((char *) resource_default);
3686 return(resource_value.addr);
3687}
3688
3689/*
3690%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3691% %
3692% %
3693% %
3694% X G e t S c r e e n D e n s i t y %
3695% %
3696% %
3697% %
3698%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3699%
3700% XGetScreenDensity() returns the density of the X server screen in
3701% dots-per-inch.
3702%
3703% The format of the XGetScreenDensity method is:
3704%
3705% char *XGetScreenDensity(Display *display)
3706%
3707% A description of each parameter follows:
3708%
3709% o density: XGetScreenDensity() returns the density of the X screen in
3710% dots-per-inch.
3711%
3712% o display: Specifies a connection to an X server; returned from
3713% XOpenDisplay.
3714%
3715*/
3716MagickExport char *XGetScreenDensity(Display *display)
3717{
3718 char
3719 density[MaxTextExtent];
3720
3721 double
3722 x_density,
3723 y_density;
3724
3725 /*
3726 Set density as determined by screen size.
3727 */
3728 x_density=((((double) DisplayWidth(display,XDefaultScreen(display)))*25.4)/
3729 ((double) DisplayWidthMM(display,XDefaultScreen(display))));
3730 y_density=((((double) DisplayHeight(display,XDefaultScreen(display)))*25.4)/
3731 ((double) DisplayHeightMM(display,XDefaultScreen(display))));
cristyb51dff52011-05-19 16:55:47 +00003732 (void) FormatLocaleString(density,MaxTextExtent,"%gx%g",x_density,
cristy8cd5b312010-01-07 01:10:24 +00003733 y_density);
cristy3ed852e2009-09-05 21:47:34 +00003734 return(GetPageGeometry(density));
3735}
3736
3737/*
3738%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3739% %
3740% %
3741% %
3742+ X G e t S u b w i n d o w %
3743% %
3744% %
3745% %
3746%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3747%
3748% XGetSubwindow() returns the subwindow of a window chosen the user with the
3749% pointer and a button press.
3750%
3751% The format of the XGetSubwindow method is:
3752%
3753% Window XGetSubwindow(Display *display,Window window,int x,int y)
3754%
3755% A description of each parameter follows:
3756%
3757% o subwindow: XGetSubwindow() returns NULL if no subwindow is found
3758% otherwise the subwindow is returned.
3759%
3760% o display: Specifies a connection to an X server; returned from
3761% XOpenDisplay.
3762%
3763% o window: Specifies a pointer to a Window.
3764%
3765% o x: the x coordinate of the pointer relative to the origin of the
3766% window.
3767%
3768% o y: the y coordinate of the pointer relative to the origin of the
3769% window.
3770%
cristy3ed852e2009-09-05 21:47:34 +00003771*/
3772static Window XGetSubwindow(Display *display,Window window,int x,int y)
3773{
3774 int
3775 x_offset,
3776 y_offset;
3777
3778 Status
3779 status;
3780
3781 Window
3782 source_window,
3783 target_window;
3784
3785 assert(display != (Display *) NULL);
3786 source_window=XRootWindow(display,XDefaultScreen(display));
3787 if (window == (Window) NULL)
3788 return(source_window);
3789 target_window=window;
3790 for ( ; ; )
3791 {
3792 status=XTranslateCoordinates(display,source_window,window,x,y,
3793 &x_offset,&y_offset,&target_window);
3794 if (status != True)
3795 break;
3796 if (target_window == (Window) NULL)
3797 break;
3798 source_window=window;
3799 window=target_window;
3800 x=x_offset;
3801 y=y_offset;
3802 }
3803 if (target_window == (Window) NULL)
3804 target_window=window;
3805 return(target_window);
3806}
3807
3808/*
3809%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3810% %
3811% %
3812% %
3813% X G e t W i n d o w C o l o r %
3814% %
3815% %
3816% %
3817%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3818%
3819% XGetWindowColor() returns the color of a pixel interactively chosen from the
3820% X server.
3821%
3822% The format of the XGetWindowColor method is:
3823%
3824% MagickBooleanType XGetWindowColor(Display *display,XWindows *windows,
3825% char *name)
3826%
3827% A description of each parameter follows:
3828%
3829% o display: Specifies a connection to an X server; returned from
3830% XOpenDisplay.
3831%
3832% o windows: Specifies a pointer to a XWindows structure.
3833%
3834% o name: the name of the color if found in the X Color Database is
3835% returned in this character string.
3836%
3837*/
cristybcbda3f2011-09-03 13:01:22 +00003838MagickPrivate MagickBooleanType XGetWindowColor(Display *display,
cristy3ed852e2009-09-05 21:47:34 +00003839 XWindows *windows,char *name)
3840{
3841 int
3842 x,
3843 y;
3844
3845 PixelPacket
3846 pixel;
3847
3848 RectangleInfo
3849 crop_info;
3850
3851 Status
3852 status;
3853
3854 Window
3855 child,
3856 client_window,
3857 root_window,
3858 target_window;
3859
3860 XColor
3861 color;
3862
3863 XImage
3864 *ximage;
3865
3866 XWindowAttributes
3867 window_attributes;
3868
3869 /*
3870 Choose a pixel from the X server.
3871 */
3872 assert(display != (Display *) NULL);
3873 assert(name != (char *) NULL);
3874 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",name);
3875 *name='\0';
3876 target_window=XSelectWindow(display,&crop_info);
3877 if (target_window == (Window) NULL)
3878 return(MagickFalse);
3879 root_window=XRootWindow(display,XDefaultScreen(display));
3880 client_window=target_window;
3881 if (target_window != root_window)
3882 {
3883 unsigned int
3884 d;
3885
3886 /*
3887 Get client window.
3888 */
3889 status=XGetGeometry(display,target_window,&root_window,&x,&x,&d,&d,&d,&d);
3890 if (status != False)
3891 {
3892 client_window=XClientWindow(display,target_window);
3893 target_window=client_window;
3894 }
3895 }
3896 /*
3897 Verify window is viewable.
3898 */
3899 status=XGetWindowAttributes(display,target_window,&window_attributes);
3900 if ((status == False) || (window_attributes.map_state != IsViewable))
3901 return(MagickFalse);
3902 /*
3903 Get window X image.
3904 */
3905 (void) XTranslateCoordinates(display,root_window,target_window,
3906 (int) crop_info.x,(int) crop_info.y,&x,&y,&child);
3907 ximage=XGetImage(display,target_window,x,y,1,1,AllPlanes,ZPixmap);
3908 if (ximage == (XImage *) NULL)
3909 return(MagickFalse);
3910 color.pixel=XGetPixel(ximage,0,0);
3911 XDestroyImage(ximage);
3912 /*
3913 Match color against the color database.
3914 */
3915 (void) XQueryColor(display,window_attributes.colormap,&color);
3916 pixel.red=ScaleShortToQuantum(color.red);
3917 pixel.green=ScaleShortToQuantum(color.green);
3918 pixel.blue=ScaleShortToQuantum(color.blue);
cristy4c08aed2011-07-01 19:47:50 +00003919 pixel.alpha=OpaqueAlpha;
cristy3ed852e2009-09-05 21:47:34 +00003920 (void) QueryColorname(windows->image.image,&pixel,X11Compliance,name,
3921 &windows->image.image->exception);
3922 return(MagickTrue);
3923}
3924
3925/*
3926%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3927% %
3928% %
3929% %
3930+ X G e t W i n d o w I m a g e %
3931% %
3932% %
3933% %
3934%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3935%
3936% XGetWindowImage() reads an image from the target X window and returns it.
3937% XGetWindowImage() optionally descends the window hierarchy and overlays the
3938% target image with each child image in an optimized fashion. Any child
3939% window that have the same visual, colormap, and are contained by its parent
3940% are exempted.
3941%
3942% The format of the XGetWindowImage method is:
3943%
3944% Image *XGetWindowImage(Display *display,const Window window,
3945% const unsigned int borders,const unsigned int level)
3946%
3947% A description of each parameter follows:
3948%
3949% o display: Specifies a connection to an X server; returned from
3950% XOpenDisplay.
3951%
3952% o window: Specifies the window to obtain the image from.
3953%
3954% o borders: Specifies whether borders pixels are to be saved with
3955% the image.
3956%
3957% o level: Specifies an unsigned integer representing the level of
3958% decent in the window hierarchy. This value must be zero or one on
3959% the initial call to XGetWindowImage. A value of zero returns after
3960% one call. A value of one causes the function to descend the window
3961% hierarchy and overlay the target image with each subwindow image.
3962%
cristy3ed852e2009-09-05 21:47:34 +00003963*/
3964static Image *XGetWindowImage(Display *display,const Window window,
3965 const unsigned int borders,const unsigned int level)
3966{
3967 typedef struct _ColormapInfo
3968 {
3969 Colormap
3970 colormap;
3971
3972 XColor
3973 *colors;
3974
3975 struct _ColormapInfo
3976 *next;
3977 } ColormapInfo;
3978
3979 typedef struct _WindowInfo
3980 {
3981 Window
3982 window,
3983 parent;
3984
3985 Visual
3986 *visual;
3987
3988 Colormap
3989 colormap;
3990
3991 XSegment
3992 bounds;
3993
3994 RectangleInfo
3995 crop_info;
3996 } WindowInfo;
3997
cristy3ed852e2009-09-05 21:47:34 +00003998 int
3999 display_height,
4000 display_width,
4001 id,
4002 x_offset,
4003 y_offset;
4004
cristy4c08aed2011-07-01 19:47:50 +00004005 Quantum
4006 index;
4007
cristy3ed852e2009-09-05 21:47:34 +00004008 RectangleInfo
4009 crop_info;
4010
cristy3ed852e2009-09-05 21:47:34 +00004011 register int
4012 i;
4013
4014 static ColormapInfo
4015 *colormap_info = (ColormapInfo *) NULL;
4016
4017 static int
4018 max_windows = 0,
4019 number_windows = 0;
4020
4021 static WindowInfo
4022 *window_info;
4023
4024 Status
4025 status;
4026
4027 Window
4028 child,
4029 root_window;
4030
4031 XWindowAttributes
4032 window_attributes;
4033
4034 /*
4035 Verify window is viewable.
4036 */
4037 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
4038 assert(display != (Display *) NULL);
4039 status=XGetWindowAttributes(display,window,&window_attributes);
4040 if ((status == False) || (window_attributes.map_state != IsViewable))
4041 return((Image *) NULL);
4042 /*
4043 Cropping rectangle is relative to root window.
4044 */
4045 root_window=XRootWindow(display,XDefaultScreen(display));
4046 (void) XTranslateCoordinates(display,window,root_window,0,0,&x_offset,
4047 &y_offset,&child);
cristybb503372010-05-27 20:51:26 +00004048 crop_info.x=(ssize_t) x_offset;
4049 crop_info.y=(ssize_t) y_offset;
4050 crop_info.width=(size_t) window_attributes.width;
4051 crop_info.height=(size_t) window_attributes.height;
cristy3ed852e2009-09-05 21:47:34 +00004052 if (borders != MagickFalse)
4053 {
4054 /*
4055 Include border in image.
4056 */
cristybb503372010-05-27 20:51:26 +00004057 crop_info.x-=(ssize_t) window_attributes.border_width;
4058 crop_info.y-=(ssize_t) window_attributes.border_width;
4059 crop_info.width+=(size_t) (window_attributes.border_width << 1);
4060 crop_info.height+=(size_t) (window_attributes.border_width << 1);
cristy3ed852e2009-09-05 21:47:34 +00004061 }
4062 /*
4063 Crop to root window.
4064 */
4065 if (crop_info.x < 0)
4066 {
4067 crop_info.width+=crop_info.x;
4068 crop_info.x=0;
4069 }
4070 if (crop_info.y < 0)
4071 {
4072 crop_info.height+=crop_info.y;
4073 crop_info.y=0;
4074 }
4075 display_width=XDisplayWidth(display,XDefaultScreen(display));
4076 if ((int) (crop_info.x+crop_info.width) > display_width)
cristybb503372010-05-27 20:51:26 +00004077 crop_info.width=(size_t) (display_width-crop_info.x);
cristy3ed852e2009-09-05 21:47:34 +00004078 display_height=XDisplayHeight(display,XDefaultScreen(display));
4079 if ((int) (crop_info.y+crop_info.height) > display_height)
cristybb503372010-05-27 20:51:26 +00004080 crop_info.height=(size_t) (display_height-crop_info.y);
cristy3ed852e2009-09-05 21:47:34 +00004081 /*
4082 Initialize window info attributes.
4083 */
4084 if (number_windows >= max_windows)
4085 {
4086 /*
4087 Allocate or resize window info buffer.
4088 */
4089 max_windows+=1024;
4090 if (window_info == (WindowInfo *) NULL)
4091 window_info=(WindowInfo *) AcquireQuantumMemory((size_t) max_windows,
4092 sizeof(*window_info));
4093 else
4094 window_info=(WindowInfo *) ResizeQuantumMemory(window_info,(size_t)
4095 max_windows,sizeof(*window_info));
4096 }
4097 if (window_info == (WindowInfo *) NULL)
4098 {
4099 ThrowXWindowFatalException(ResourceLimitError,
4100 "MemoryAllocationFailed","...");
4101 return((Image *) NULL);
4102 }
4103 id=number_windows++;
4104 window_info[id].window=window;
4105 window_info[id].visual=window_attributes.visual;
4106 window_info[id].colormap=window_attributes.colormap;
4107 window_info[id].bounds.x1=(short) crop_info.x;
4108 window_info[id].bounds.y1=(short) crop_info.y;
4109 window_info[id].bounds.x2=(short) (crop_info.x+(int) crop_info.width-1);
4110 window_info[id].bounds.y2=(short) (crop_info.y+(int) crop_info.height-1);
4111 crop_info.x-=x_offset;
4112 crop_info.y-=y_offset;
4113 window_info[id].crop_info=crop_info;
4114 if (level != 0)
4115 {
4116 unsigned int
4117 number_children;
4118
4119 Window
4120 *children;
4121
4122 /*
4123 Descend the window hierarchy.
4124 */
4125 status=XQueryTree(display,window,&root_window,&window_info[id].parent,
4126 &children,&number_children);
4127 for (i=0; i < id; i++)
4128 if ((window_info[i].window == window_info[id].parent) &&
4129 (window_info[i].visual == window_info[id].visual) &&
4130 (window_info[i].colormap == window_info[id].colormap))
4131 {
4132 if ((window_info[id].bounds.x1 <= window_info[i].bounds.x1) ||
4133 (window_info[id].bounds.x1 >= window_info[i].bounds.x2) ||
4134 (window_info[id].bounds.y1 <= window_info[i].bounds.y1) ||
4135 (window_info[id].bounds.y1 >= window_info[i].bounds.y2))
4136 {
4137 /*
4138 Eliminate windows not circumscribed by their parent.
4139 */
4140 number_windows--;
4141 break;
4142 }
4143 }
4144 if ((status == True) && (number_children != 0))
4145 {
4146 for (i=0; i < (int) number_children; i++)
4147 (void) XGetWindowImage(display,children[i],MagickFalse,level+1);
4148 (void) XFree((void *) children);
4149 }
4150 }
4151 if (level <= 1)
4152 {
cristyc57f6942010-11-12 01:47:39 +00004153 CacheView
4154 *composite_view;
4155
cristy3ed852e2009-09-05 21:47:34 +00004156 ColormapInfo
4157 *next;
4158
4159 ExceptionInfo
4160 *exception;
4161
4162 Image
4163 *composite_image,
4164 *image;
4165
4166 int
4167 y;
4168
4169 MagickBooleanType
4170 import;
4171
4172 register int
4173 j,
4174 x;
4175
cristy4c08aed2011-07-01 19:47:50 +00004176 register Quantum
cristyc47d1f82009-11-26 01:44:43 +00004177 *restrict q;
cristy3ed852e2009-09-05 21:47:34 +00004178
cristybb503372010-05-27 20:51:26 +00004179 register size_t
cristy3ed852e2009-09-05 21:47:34 +00004180 pixel;
4181
4182 unsigned int
4183 number_colors;
4184
4185 XColor
4186 *colors;
4187
4188 XImage
4189 *ximage;
4190
4191 /*
4192 Get X image for each window in the list.
4193 */
4194 image=NewImageList();
4195 for (id=0; id < number_windows; id++)
4196 {
4197 /*
4198 Does target window intersect top level window?
4199 */
4200 import=
4201 ((window_info[id].bounds.x2 >= window_info[0].bounds.x1) &&
4202 (window_info[id].bounds.x1 <= window_info[0].bounds.x2) &&
4203 (window_info[id].bounds.y2 >= window_info[0].bounds.y1) &&
4204 (window_info[id].bounds.y1 <= window_info[0].bounds.y2)) ?
4205 MagickTrue : MagickFalse;
4206 /*
4207 Is target window contained by another window with the same colormap?
4208 */
4209 for (j=0; j < id; j++)
4210 if ((window_info[id].visual == window_info[j].visual) &&
4211 (window_info[id].colormap == window_info[j].colormap))
4212 {
4213 if ((window_info[id].bounds.x1 <= window_info[j].bounds.x1) ||
4214 (window_info[id].bounds.x1 >= window_info[j].bounds.x2) ||
4215 (window_info[id].bounds.y1 <= window_info[j].bounds.y1) ||
4216 (window_info[id].bounds.y1 >= window_info[j].bounds.y2))
4217 import=MagickFalse;
4218 }
4219 else
4220 if ((window_info[id].visual != window_info[j].visual) ||
4221 (window_info[id].colormap != window_info[j].colormap))
4222 {
4223 if ((window_info[id].bounds.x2 > window_info[j].bounds.x1) &&
4224 (window_info[id].bounds.x1 < window_info[j].bounds.x2) &&
4225 (window_info[id].bounds.y2 > window_info[j].bounds.y1) &&
4226 (window_info[id].bounds.y1 < window_info[j].bounds.y2))
4227 import=MagickTrue;
4228 }
4229 if (import == MagickFalse)
4230 continue;
4231 /*
4232 Get X image.
4233 */
4234 ximage=XGetImage(display,window_info[id].window,(int)
4235 window_info[id].crop_info.x,(int) window_info[id].crop_info.y,
4236 (unsigned int) window_info[id].crop_info.width,(unsigned int)
4237 window_info[id].crop_info.height,AllPlanes,ZPixmap);
4238 if (ximage == (XImage *) NULL)
4239 continue;
4240 /*
4241 Initialize window colormap.
4242 */
4243 number_colors=0;
4244 colors=(XColor *) NULL;
4245 if (window_info[id].colormap != (Colormap) NULL)
4246 {
4247 ColormapInfo
4248 *p;
4249
4250 /*
4251 Search colormap list for window colormap.
4252 */
4253 number_colors=(unsigned int) window_info[id].visual->map_entries;
4254 for (p=colormap_info; p != (ColormapInfo *) NULL; p=p->next)
4255 if (p->colormap == window_info[id].colormap)
4256 break;
4257 if (p == (ColormapInfo *) NULL)
4258 {
4259 /*
4260 Get the window colormap.
4261 */
4262 colors=(XColor *) AcquireQuantumMemory(number_colors,
4263 sizeof(*colors));
4264 if (colors == (XColor *) NULL)
4265 {
4266 XDestroyImage(ximage);
4267 return((Image *) NULL);
4268 }
4269 if ((window_info[id].visual->klass != DirectColor) &&
4270 (window_info[id].visual->klass != TrueColor))
4271 for (i=0; i < (int) number_colors; i++)
4272 {
cristybb503372010-05-27 20:51:26 +00004273 colors[i].pixel=(size_t) i;
cristy3ed852e2009-09-05 21:47:34 +00004274 colors[i].pad='\0';
4275 }
4276 else
4277 {
cristybb503372010-05-27 20:51:26 +00004278 size_t
cristy3ed852e2009-09-05 21:47:34 +00004279 blue,
4280 blue_bit,
4281 green,
4282 green_bit,
4283 red,
4284 red_bit;
4285
4286 /*
4287 DirectColor or TrueColor visual.
4288 */
4289 red=0;
4290 green=0;
4291 blue=0;
4292 red_bit=window_info[id].visual->red_mask &
4293 (~(window_info[id].visual->red_mask)+1);
4294 green_bit=window_info[id].visual->green_mask &
4295 (~(window_info[id].visual->green_mask)+1);
4296 blue_bit=window_info[id].visual->blue_mask &
4297 (~(window_info[id].visual->blue_mask)+1);
4298 for (i=0; i < (int) number_colors; i++)
4299 {
cristy8891f9c2010-06-04 23:32:17 +00004300 colors[i].pixel=(unsigned long) (red | green | blue);
cristy3ed852e2009-09-05 21:47:34 +00004301 colors[i].pad='\0';
4302 red+=red_bit;
4303 if (red > window_info[id].visual->red_mask)
4304 red=0;
4305 green+=green_bit;
4306 if (green > window_info[id].visual->green_mask)
4307 green=0;
4308 blue+=blue_bit;
4309 if (blue > window_info[id].visual->blue_mask)
4310 blue=0;
4311 }
4312 }
4313 (void) XQueryColors(display,window_info[id].colormap,colors,
4314 (int) number_colors);
4315 /*
4316 Append colormap to colormap list.
4317 */
cristy73bd4a52010-10-05 11:24:23 +00004318 p=(ColormapInfo *) AcquireMagickMemory(sizeof(*p));
cristy3ed852e2009-09-05 21:47:34 +00004319 if (p == (ColormapInfo *) NULL)
4320 return((Image *) NULL);
4321 p->colormap=window_info[id].colormap;
4322 p->colors=colors;
4323 p->next=colormap_info;
4324 colormap_info=p;
4325 }
4326 colors=p->colors;
4327 }
4328 /*
4329 Allocate image structure.
4330 */
4331 composite_image=AcquireImage((ImageInfo *) NULL);
4332 if (composite_image == (Image *) NULL)
4333 {
4334 XDestroyImage(ximage);
4335 return((Image *) NULL);
4336 }
4337 /*
4338 Convert X image to MIFF format.
4339 */
4340 if ((window_info[id].visual->klass != TrueColor) &&
4341 (window_info[id].visual->klass != DirectColor))
4342 composite_image->storage_class=PseudoClass;
cristybb503372010-05-27 20:51:26 +00004343 composite_image->columns=(size_t) ximage->width;
4344 composite_image->rows=(size_t) ximage->height;
cristy3ed852e2009-09-05 21:47:34 +00004345 exception=(&composite_image->exception);
cristyc57f6942010-11-12 01:47:39 +00004346 composite_view=AcquireCacheView(composite_image);
cristy3ed852e2009-09-05 21:47:34 +00004347 switch (composite_image->storage_class)
4348 {
4349 case DirectClass:
4350 default:
4351 {
cristybb503372010-05-27 20:51:26 +00004352 register size_t
cristy3ed852e2009-09-05 21:47:34 +00004353 color,
4354 index;
4355
cristybb503372010-05-27 20:51:26 +00004356 size_t
cristy3ed852e2009-09-05 21:47:34 +00004357 blue_mask,
4358 blue_shift,
4359 green_mask,
4360 green_shift,
4361 red_mask,
4362 red_shift;
4363
4364 /*
4365 Determine shift and mask for red, green, and blue.
4366 */
4367 red_mask=window_info[id].visual->red_mask;
4368 red_shift=0;
4369 while ((red_mask != 0) && ((red_mask & 0x01) == 0))
4370 {
4371 red_mask>>=1;
4372 red_shift++;
4373 }
4374 green_mask=window_info[id].visual->green_mask;
4375 green_shift=0;
4376 while ((green_mask != 0) && ((green_mask & 0x01) == 0))
4377 {
4378 green_mask>>=1;
4379 green_shift++;
4380 }
4381 blue_mask=window_info[id].visual->blue_mask;
4382 blue_shift=0;
4383 while ((blue_mask != 0) && ((blue_mask & 0x01) == 0))
4384 {
4385 blue_mask>>=1;
4386 blue_shift++;
4387 }
4388 /*
4389 Convert X image to DirectClass packets.
4390 */
4391 if ((number_colors != 0) &&
4392 (window_info[id].visual->klass == DirectColor))
4393 for (y=0; y < (int) composite_image->rows; y++)
4394 {
cristyc57f6942010-11-12 01:47:39 +00004395 q=QueueCacheViewAuthenticPixels(composite_view,0,(ssize_t) y,
cristy3ed852e2009-09-05 21:47:34 +00004396 composite_image->columns,1,exception);
cristyacd2ed22011-08-30 01:44:23 +00004397 if (q == (Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00004398 break;
4399 for (x=0; x < (int) composite_image->columns; x++)
4400 {
4401 pixel=XGetPixel(ximage,x,y);
4402 index=(pixel >> red_shift) & red_mask;
cristy4c08aed2011-07-01 19:47:50 +00004403 SetPixelRed(composite_image,
4404 ScaleShortToQuantum(colors[index].red),q);
cristy3ed852e2009-09-05 21:47:34 +00004405 index=(pixel >> green_shift) & green_mask;
cristy4c08aed2011-07-01 19:47:50 +00004406 SetPixelGreen(composite_image,
4407 ScaleShortToQuantum(colors[index].green),q);
cristy3ed852e2009-09-05 21:47:34 +00004408 index=(pixel >> blue_shift) & blue_mask;
cristy4c08aed2011-07-01 19:47:50 +00004409 SetPixelBlue(composite_image,
4410 ScaleShortToQuantum(colors[index].blue),q);
cristyed231572011-07-14 02:18:59 +00004411 q+=GetPixelChannels(composite_image);
cristy3ed852e2009-09-05 21:47:34 +00004412 }
cristyc57f6942010-11-12 01:47:39 +00004413 if (SyncCacheViewAuthenticPixels(composite_view,exception) == MagickFalse)
cristy3ed852e2009-09-05 21:47:34 +00004414 break;
4415 }
4416 else
4417 for (y=0; y < (int) composite_image->rows; y++)
4418 {
cristyc57f6942010-11-12 01:47:39 +00004419 q=QueueCacheViewAuthenticPixels(composite_view,0,(ssize_t) y,
cristy3ed852e2009-09-05 21:47:34 +00004420 composite_image->columns,1,exception);
cristyacd2ed22011-08-30 01:44:23 +00004421 if (q == (Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00004422 break;
4423 for (x=0; x < (int) composite_image->columns; x++)
4424 {
4425 pixel=XGetPixel(ximage,x,y);
4426 color=(pixel >> red_shift) & red_mask;
4427 color=(65535UL*color)/red_mask;
cristy4c08aed2011-07-01 19:47:50 +00004428 SetPixelRed(composite_image,
4429 ScaleShortToQuantum((unsigned short) color),q);
cristy3ed852e2009-09-05 21:47:34 +00004430 color=(pixel >> green_shift) & green_mask;
4431 color=(65535UL*color)/green_mask;
cristy4c08aed2011-07-01 19:47:50 +00004432 SetPixelGreen(composite_image,
4433 ScaleShortToQuantum((unsigned short) color),q);
cristy3ed852e2009-09-05 21:47:34 +00004434 color=(pixel >> blue_shift) & blue_mask;
4435 color=(65535UL*color)/blue_mask;
cristy4c08aed2011-07-01 19:47:50 +00004436 SetPixelBlue(composite_image,
4437 ScaleShortToQuantum((unsigned short) color),q);
cristyed231572011-07-14 02:18:59 +00004438 q+=GetPixelChannels(composite_image);
cristy3ed852e2009-09-05 21:47:34 +00004439 }
cristyc57f6942010-11-12 01:47:39 +00004440 if (SyncCacheViewAuthenticPixels(composite_view,exception) == MagickFalse)
cristy3ed852e2009-09-05 21:47:34 +00004441 break;
4442 }
4443 break;
4444 }
4445 case PseudoClass:
4446 {
4447 /*
4448 Create colormap.
4449 */
cristy018f07f2011-09-04 21:15:19 +00004450 if (AcquireImageColormap(composite_image,number_colors,exception) == MagickFalse)
cristy3ed852e2009-09-05 21:47:34 +00004451 {
4452 XDestroyImage(ximage);
4453 composite_image=DestroyImage(composite_image);
4454 return((Image *) NULL);
4455 }
4456 for (i=0; i < (int) composite_image->colors; i++)
4457 {
4458 composite_image->colormap[colors[i].pixel].red=
4459 ScaleShortToQuantum(colors[i].red);
4460 composite_image->colormap[colors[i].pixel].green=
4461 ScaleShortToQuantum(colors[i].green);
4462 composite_image->colormap[colors[i].pixel].blue=
4463 ScaleShortToQuantum(colors[i].blue);
4464 }
4465 /*
4466 Convert X image to PseudoClass packets.
4467 */
4468 for (y=0; y < (int) composite_image->rows; y++)
4469 {
cristyc57f6942010-11-12 01:47:39 +00004470 q=QueueCacheViewAuthenticPixels(composite_view,0,(ssize_t) y,
4471 composite_image->columns,1,exception);
cristyacd2ed22011-08-30 01:44:23 +00004472 if (q == (Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00004473 break;
cristy3ed852e2009-09-05 21:47:34 +00004474 for (x=0; x < (int) composite_image->columns; x++)
4475 {
cristy4c08aed2011-07-01 19:47:50 +00004476 index=(Quantum) XGetPixel(ximage,x,y);
4477 SetPixelIndex(composite_image,index,q);
4478 SetPixelPacket(composite_image,
4479 composite_image->colormap+(ssize_t) index,q);
cristyed231572011-07-14 02:18:59 +00004480 q+=GetPixelChannels(composite_image);
cristy3ed852e2009-09-05 21:47:34 +00004481 }
cristyc57f6942010-11-12 01:47:39 +00004482 if (SyncCacheViewAuthenticPixels(composite_view,exception) == MagickFalse)
cristy3ed852e2009-09-05 21:47:34 +00004483 break;
4484 }
4485 break;
4486 }
4487 }
cristyc57f6942010-11-12 01:47:39 +00004488 composite_view=DestroyCacheView(composite_view);
cristy3ed852e2009-09-05 21:47:34 +00004489 XDestroyImage(ximage);
4490 if (image == (Image *) NULL)
4491 {
4492 image=composite_image;
4493 continue;
4494 }
4495 /*
4496 Composite any children in back-to-front order.
4497 */
4498 (void) XTranslateCoordinates(display,window_info[id].window,window,0,0,
4499 &x_offset,&y_offset,&child);
4500 x_offset-=(int) crop_info.x;
4501 if (x_offset < 0)
4502 x_offset=0;
4503 y_offset-=(int) crop_info.y;
4504 if (y_offset < 0)
4505 y_offset=0;
cristyc57f6942010-11-12 01:47:39 +00004506 (void) CompositeImage(image,CopyCompositeOp,composite_image,(ssize_t)
4507 x_offset,(ssize_t) y_offset);
cristy3ed852e2009-09-05 21:47:34 +00004508 }
4509 /*
4510 Relinquish resources.
4511 */
4512 while (colormap_info != (ColormapInfo *) NULL)
4513 {
4514 next=colormap_info->next;
4515 colormap_info->colors=(XColor *)
4516 RelinquishMagickMemory(colormap_info->colors);
4517 colormap_info=(ColormapInfo *) RelinquishMagickMemory(colormap_info);
4518 colormap_info=next;
4519 }
4520 /*
4521 Relinquish resources and restore initial state.
4522 */
4523 window_info=(WindowInfo *) RelinquishMagickMemory(window_info);
4524 max_windows=0;
4525 number_windows=0;
4526 colormap_info=(ColormapInfo *) NULL;
4527 return(image);
4528 }
4529 return((Image *) NULL);
4530}
4531
4532/*
4533%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4534% %
4535% %
4536% %
4537% X G e t W i n d o w I n f o %
4538% %
4539% %
4540% %
4541%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4542%
4543% XGetWindowInfo() initializes the XWindowInfo structure.
4544%
4545% The format of the XGetWindowInfo method is:
4546%
4547% void XGetWindowInfo(Display *display,XVisualInfo *visual_info,
4548% XStandardColormap *map_info,XPixelInfo *pixel,XFontStruct *font_info,
4549% XResourceInfo *resource_info,XWindowInfo *window)
4550% resource_info,window)
4551%
4552% A description of each parameter follows:
4553%
4554% o display: Specifies a connection to an X server; returned from
4555% XOpenDisplay.
4556%
4557% o visual_info: Specifies a pointer to a X11 XVisualInfo structure;
4558% returned from XGetVisualInfo.
4559%
4560% o map_info: If map_type is specified, this structure is initialized
4561% with info from the Standard Colormap.
4562%
4563% o pixel: Specifies a pointer to a XPixelInfo structure.
4564%
4565% o font_info: Specifies a pointer to a XFontStruct structure.
4566%
4567% o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
4568%
4569*/
cristybcbda3f2011-09-03 13:01:22 +00004570MagickPrivate void XGetWindowInfo(Display *display,XVisualInfo *visual_info,
cristy3ed852e2009-09-05 21:47:34 +00004571 XStandardColormap *map_info,XPixelInfo *pixel,XFontStruct *font_info,
4572 XResourceInfo *resource_info,XWindowInfo *window)
4573{
4574 /*
4575 Initialize window info.
4576 */
4577 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
4578 assert(display != (Display *) NULL);
4579 assert(visual_info != (XVisualInfo *) NULL);
4580 assert(map_info != (XStandardColormap *) NULL);
4581 assert(pixel != (XPixelInfo *) NULL);
4582 assert(resource_info != (XResourceInfo *) NULL);
4583 assert(window != (XWindowInfo *) NULL);
4584 if (window->id != (Window) NULL)
4585 {
4586 if (window->cursor != (Cursor) NULL)
4587 (void) XFreeCursor(display,window->cursor);
4588 if (window->busy_cursor != (Cursor) NULL)
4589 (void) XFreeCursor(display,window->busy_cursor);
4590 if (window->highlight_stipple != (Pixmap) NULL)
4591 (void) XFreePixmap(display,window->highlight_stipple);
4592 if (window->shadow_stipple != (Pixmap) NULL)
4593 (void) XFreePixmap(display,window->shadow_stipple);
4594 if (window->name == (char *) NULL)
4595 window->name=AcquireString("");
4596 if (window->icon_name == (char *) NULL)
4597 window->icon_name=AcquireString("");
4598 }
4599 else
4600 {
4601 /*
4602 Initialize these attributes just once.
4603 */
4604 window->id=(Window) NULL;
4605 if (window->name == (char *) NULL)
4606 window->name=AcquireString("");
4607 if (window->icon_name == (char *) NULL)
4608 window->icon_name=AcquireString("");
4609 window->x=XDisplayWidth(display,visual_info->screen) >> 1;
4610 window->y=XDisplayWidth(display,visual_info->screen) >> 1;
4611 window->ximage=(XImage *) NULL;
4612 window->matte_image=(XImage *) NULL;
4613 window->pixmap=(Pixmap) NULL;
4614 window->matte_pixmap=(Pixmap) NULL;
4615 window->mapped=MagickFalse;
4616 window->stasis=MagickFalse;
4617 window->shared_memory=MagickTrue;
4618 window->segment_info=(void *) NULL;
4619#if defined(MAGICKCORE_HAVE_SHARED_MEMORY)
4620 {
4621 XShmSegmentInfo
4622 *segment_info;
4623
4624 if (window->segment_info == (void *) NULL)
4625 window->segment_info=AcquireQuantumMemory(2,sizeof(*segment_info));
4626 segment_info=(XShmSegmentInfo *) window->segment_info;
4627 segment_info[0].shmid=(-1);
4628 segment_info[0].shmaddr=(char *) NULL;
4629 segment_info[1].shmid=(-1);
4630 segment_info[1].shmaddr=(char *) NULL;
4631 }
4632#endif
4633 }
4634 /*
4635 Initialize these attributes every time function is called.
4636 */
4637 window->screen=visual_info->screen;
4638 window->root=XRootWindow(display,visual_info->screen);
4639 window->visual=visual_info->visual;
4640 window->storage_class=(unsigned int) visual_info->klass;
4641 window->depth=(unsigned int) visual_info->depth;
4642 window->visual_info=visual_info;
4643 window->map_info=map_info;
4644 window->pixel_info=pixel;
4645 window->font_info=font_info;
4646 window->cursor=XCreateFontCursor(display,XC_left_ptr);
4647 window->busy_cursor=XCreateFontCursor(display,XC_watch);
4648 window->geometry=(char *) NULL;
4649 window->icon_geometry=(char *) NULL;
4650 if (resource_info->icon_geometry != (char *) NULL)
4651 (void) CloneString(&window->icon_geometry,resource_info->icon_geometry);
4652 window->crop_geometry=(char *) NULL;
cristybb503372010-05-27 20:51:26 +00004653 window->flags=(size_t) PSize;
cristy3ed852e2009-09-05 21:47:34 +00004654 window->width=1;
4655 window->height=1;
4656 window->min_width=1;
4657 window->min_height=1;
4658 window->width_inc=1;
4659 window->height_inc=1;
4660 window->border_width=resource_info->border_width;
4661 window->annotate_context=pixel->annotate_context;
4662 window->highlight_context=pixel->highlight_context;
4663 window->widget_context=pixel->widget_context;
4664 window->shadow_stipple=(Pixmap) NULL;
4665 window->highlight_stipple=(Pixmap) NULL;
4666 window->use_pixmap=MagickTrue;
4667 window->immutable=MagickFalse;
4668 window->shape=MagickFalse;
4669 window->data=0;
cristyc57f6942010-11-12 01:47:39 +00004670 window->mask=(int) (CWBackingStore | CWBackPixel | CWBackPixmap |
cristy3ed852e2009-09-05 21:47:34 +00004671 CWBitGravity | CWBorderPixel | CWColormap | CWCursor | CWDontPropagate |
4672 CWEventMask | CWOverrideRedirect | CWSaveUnder | CWWinGravity);
4673 window->attributes.background_pixel=pixel->background_color.pixel;
4674 window->attributes.background_pixmap=(Pixmap) NULL;
4675 window->attributes.bit_gravity=ForgetGravity;
4676 window->attributes.backing_store=WhenMapped;
4677 window->attributes.save_under=MagickTrue;
4678 window->attributes.border_pixel=pixel->border_color.pixel;
4679 window->attributes.colormap=map_info->colormap;
4680 window->attributes.cursor=window->cursor;
4681 window->attributes.do_not_propagate_mask=NoEventMask;
4682 window->attributes.event_mask=NoEventMask;
4683 window->attributes.override_redirect=MagickFalse;
4684 window->attributes.win_gravity=NorthWestGravity;
4685 window->orphan=MagickFalse;
4686}
4687
4688/*
4689%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4690% %
4691% %
4692% %
4693% X H i g h l i g h t E l l i p s e %
4694% %
4695% %
4696% %
4697%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4698%
4699% XHighlightEllipse() puts a border on the X server around a region defined by
4700% highlight_info.
4701%
4702% The format of the XHighlightEllipse method is:
4703%
4704% void XHighlightEllipse(Display *display,Window window,
4705% GC annotate_context,const RectangleInfo *highlight_info)
4706%
4707% A description of each parameter follows:
4708%
4709% o display: Specifies a connection to an X server; returned from
4710% XOpenDisplay.
4711%
4712% o window: Specifies a pointer to a Window structure.
4713%
4714% o annotate_context: Specifies a pointer to a GC structure.
4715%
4716% o highlight_info: Specifies a pointer to a RectangleInfo structure. It
4717% contains the extents of any highlighting rectangle.
4718%
4719*/
cristybcbda3f2011-09-03 13:01:22 +00004720MagickPrivate void XHighlightEllipse(Display *display,Window window,
cristy3ed852e2009-09-05 21:47:34 +00004721 GC annotate_context,const RectangleInfo *highlight_info)
4722{
4723 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
4724 assert(display != (Display *) NULL);
4725 assert(window != (Window) NULL);
4726 assert(annotate_context != (GC) NULL);
4727 assert(highlight_info != (RectangleInfo *) NULL);
4728 if ((highlight_info->width < 4) || (highlight_info->height < 4))
4729 return;
4730 (void) XDrawArc(display,window,annotate_context,(int) highlight_info->x,
4731 (int) highlight_info->y,(unsigned int) highlight_info->width-1,
4732 (unsigned int) highlight_info->height-1,0,360*64);
4733 (void) XDrawArc(display,window,annotate_context,(int) highlight_info->x+1,
4734 (int) highlight_info->y+1,(unsigned int) highlight_info->width-3,
4735 (unsigned int) highlight_info->height-3,0,360*64);
4736}
4737
4738/*
4739%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4740% %
4741% %
4742% %
4743% X H i g h l i g h t L i n e %
4744% %
4745% %
4746% %
4747%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4748%
4749% XHighlightLine() puts a border on the X server around a region defined by
4750% highlight_info.
4751%
4752% The format of the XHighlightLine method is:
4753%
4754% void XHighlightLine(Display *display,Window window,GC annotate_context,
4755% const XSegment *highlight_info)
4756%
4757% A description of each parameter follows:
4758%
4759% o display: Specifies a connection to an X server; returned from
4760% XOpenDisplay.
4761%
4762% o window: Specifies a pointer to a Window structure.
4763%
4764% o annotate_context: Specifies a pointer to a GC structure.
4765%
4766% o highlight_info: Specifies a pointer to a RectangleInfo structure. It
4767% contains the extents of any highlighting rectangle.
4768%
4769*/
cristybcbda3f2011-09-03 13:01:22 +00004770MagickPrivate void XHighlightLine(Display *display,Window window,
cristy3ed852e2009-09-05 21:47:34 +00004771 GC annotate_context,const XSegment *highlight_info)
4772{
4773 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
4774 assert(display != (Display *) NULL);
4775 assert(window != (Window) NULL);
4776 assert(annotate_context != (GC) NULL);
4777 assert(highlight_info != (XSegment *) NULL);
4778 (void) XDrawLine(display,window,annotate_context,highlight_info->x1,
4779 highlight_info->y1,highlight_info->x2,highlight_info->y2);
4780}
4781
4782/*
4783%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4784% %
4785% %
4786% %
4787% X H i g h l i g h t R e c t a n g l e %
4788% %
4789% %
4790% %
4791%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4792%
4793% XHighlightRectangle() puts a border on the X server around a region defined
4794% by highlight_info.
4795%
4796% The format of the XHighlightRectangle method is:
4797%
4798% void XHighlightRectangle(Display *display,Window window,
4799% GC annotate_context,const RectangleInfo *highlight_info)
4800%
4801% A description of each parameter follows:
4802%
4803% o display: Specifies a connection to an X server; returned from
4804% XOpenDisplay.
4805%
4806% o window: Specifies a pointer to a Window structure.
4807%
4808% o annotate_context: Specifies a pointer to a GC structure.
4809%
4810% o highlight_info: Specifies a pointer to a RectangleInfo structure. It
4811% contains the extents of any highlighting rectangle.
4812%
4813*/
cristybcbda3f2011-09-03 13:01:22 +00004814MagickPrivate void XHighlightRectangle(Display *display,Window window,
cristy3ed852e2009-09-05 21:47:34 +00004815 GC annotate_context,const RectangleInfo *highlight_info)
4816{
4817 assert(display != (Display *) NULL);
4818 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
4819 assert(window != (Window) NULL);
4820 assert(annotate_context != (GC) NULL);
4821 assert(highlight_info != (RectangleInfo *) NULL);
4822 if ((highlight_info->width < 4) || (highlight_info->height < 4))
4823 return;
4824 (void) XDrawRectangle(display,window,annotate_context,(int) highlight_info->x,
4825 (int) highlight_info->y,(unsigned int) highlight_info->width-1,
4826 (unsigned int) highlight_info->height-1);
4827 (void) XDrawRectangle(display,window,annotate_context,(int) highlight_info->x+
4828 1,(int) highlight_info->y+1,(unsigned int) highlight_info->width-3,
4829 (unsigned int) highlight_info->height-3);
4830}
4831
4832/*
4833%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4834% %
4835% %
4836% %
4837% X I m p o r t I m a g e %
4838% %
4839% %
4840% %
4841%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4842%
4843% XImportImage() reads an image from an X window.
4844%
4845% The format of the XImportImage method is:
4846%
4847% Image *XImportImage(const ImageInfo *image_info,XImportInfo *ximage_info)
4848%
4849% A description of each parameter follows:
4850%
4851% o image_info: the image info.
4852%
4853% o ximage_info: Specifies a pointer to an XImportInfo structure.
4854%
4855*/
4856MagickExport Image *XImportImage(const ImageInfo *image_info,
4857 XImportInfo *ximage_info)
4858{
4859 Colormap
4860 *colormaps;
4861
4862 Display
4863 *display;
4864
4865 Image
4866 *image;
4867
4868 int
4869 number_colormaps,
4870 number_windows,
4871 x;
4872
4873 RectangleInfo
4874 crop_info;
4875
4876 Status
4877 status;
4878
4879 Window
4880 *children,
4881 client,
4882 prior_target,
4883 root,
4884 target;
4885
4886 XTextProperty
4887 window_name;
4888
4889 /*
4890 Open X server connection.
4891 */
4892 assert(image_info != (const ImageInfo *) NULL);
4893 assert(image_info->signature == MagickSignature);
4894 if (image_info->debug != MagickFalse)
4895 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
4896 image_info->filename);
4897 assert(ximage_info != (XImportInfo *) NULL);
4898 display=XOpenDisplay(image_info->server_name);
4899 if (display == (Display *) NULL)
4900 {
4901 ThrowXWindowFatalException(XServerError,"UnableToOpenXServer",
4902 XDisplayName(image_info->server_name));
4903 return((Image *) NULL);
4904 }
4905 /*
4906 Set our forgiving exception handler.
4907 */
4908 (void) XSetErrorHandler(XError);
4909 /*
4910 Select target window.
4911 */
4912 crop_info.x=0;
4913 crop_info.y=0;
4914 crop_info.width=0;
4915 crop_info.height=0;
4916 root=XRootWindow(display,XDefaultScreen(display));
4917 target=(Window) NULL;
4918 if ((image_info->filename != (char *) NULL) &&
4919 (*image_info->filename != '\0'))
4920 {
4921 if (LocaleCompare(image_info->filename,"root") == 0)
4922 target=root;
4923 else
4924 {
4925 /*
4926 Select window by ID or name.
4927 */
4928 if (isdigit((unsigned char) *image_info->filename) != 0)
4929 target=XWindowByID(display,root,(Window)
4930 strtol(image_info->filename,(char **) NULL,0));
4931 if (target == (Window) NULL)
4932 target=XWindowByName(display,root,image_info->filename);
4933 if (target == (Window) NULL)
4934 ThrowXWindowFatalException(XServerError,
4935 "NoWindowWithSpecifiedIDExists",image_info->filename);
4936 }
4937 }
4938 /*
4939 If target window is not defined, interactively select one.
4940 */
4941 prior_target=target;
4942 if (target == (Window) NULL)
4943 target=XSelectWindow(display,&crop_info);
4944 if (target == (Window) NULL)
4945 ThrowXWindowFatalException(XServerError,"UnableToReadXWindowImage",
4946 image_info->filename);
4947 client=target; /* obsolete */
4948 if (target != root)
4949 {
4950 unsigned int
4951 d;
4952
4953 status=XGetGeometry(display,target,&root,&x,&x,&d,&d,&d,&d);
4954 if (status != False)
4955 {
4956 for ( ; ; )
4957 {
4958 Window
4959 parent;
4960
4961 /*
4962 Find window manager frame.
4963 */
4964 status=XQueryTree(display,target,&root,&parent,&children,&d);
4965 if ((status != False) && (children != (Window *) NULL))
4966 (void) XFree((char *) children);
4967 if ((status == False) || (parent == (Window) NULL) ||
4968 (parent == root))
4969 break;
4970 target=parent;
4971 }
4972 /*
4973 Get client window.
4974 */
4975 client=XClientWindow(display,target);
4976 if (ximage_info->frame == MagickFalse)
4977 target=client;
4978 if ((ximage_info->frame == MagickFalse) &&
4979 (prior_target != MagickFalse))
4980 target=prior_target;
4981 XDelay(display,SuspendTime << 4);
4982 }
4983 }
4984 if (ximage_info->screen)
4985 {
4986 int
4987 y;
4988
4989 Window
4990 child;
4991
4992 XWindowAttributes
4993 window_attributes;
4994
4995 /*
4996 Obtain window image directly from screen.
4997 */
4998 status=XGetWindowAttributes(display,target,&window_attributes);
4999 if (status == False)
5000 {
5001 ThrowXWindowFatalException(XServerError,
5002 "UnableToReadXWindowAttributes",image_info->filename);
5003 (void) XCloseDisplay(display);
5004 return((Image *) NULL);
5005 }
5006 (void) XTranslateCoordinates(display,target,root,0,0,&x,&y,&child);
cristyc57f6942010-11-12 01:47:39 +00005007 crop_info.x=(ssize_t) x;
5008 crop_info.y=(ssize_t) y;
cristybb503372010-05-27 20:51:26 +00005009 crop_info.width=(size_t) window_attributes.width;
5010 crop_info.height=(size_t) window_attributes.height;
cristy553743c2010-03-03 15:04:17 +00005011 if (ximage_info->borders != 0)
cristy3ed852e2009-09-05 21:47:34 +00005012 {
5013 /*
5014 Include border in image.
5015 */
5016 crop_info.x-=window_attributes.border_width;
5017 crop_info.y-=window_attributes.border_width;
5018 crop_info.width+=window_attributes.border_width << 1;
5019 crop_info.height+=window_attributes.border_width << 1;
5020 }
5021 target=root;
5022 }
5023 /*
5024 If WM_COLORMAP_WINDOWS property is set or multiple colormaps, descend.
5025 */
5026 number_windows=0;
5027 status=XGetWMColormapWindows(display,target,&children,&number_windows);
5028 if ((status == True) && (number_windows > 0))
5029 {
5030 ximage_info->descend=MagickTrue;
5031 (void) XFree ((char *) children);
5032 }
5033 colormaps=XListInstalledColormaps(display,target,&number_colormaps);
5034 if (number_colormaps > 0)
5035 {
5036 if (number_colormaps > 1)
5037 ximage_info->descend=MagickTrue;
5038 (void) XFree((char *) colormaps);
5039 }
5040 /*
5041 Alert the user not to alter the screen.
5042 */
5043 if (ximage_info->silent == MagickFalse)
5044 (void) XBell(display,0);
5045 /*
5046 Get image by window id.
5047 */
5048 (void) XGrabServer(display);
5049 image=XGetWindowImage(display,target,ximage_info->borders,
5050 ximage_info->descend ? 1U : 0U);
5051 (void) XUngrabServer(display);
5052 if (image == (Image *) NULL)
5053 ThrowXWindowFatalException(XServerError,"UnableToReadXWindowImage",
5054 image_info->filename)
5055 else
5056 {
5057 (void) CopyMagickString(image->filename,image_info->filename,
5058 MaxTextExtent);
5059 if ((crop_info.width != 0) && (crop_info.height != 0))
5060 {
5061 Image
5062 *clone_image,
5063 *crop_image;
5064
5065 /*
5066 Crop image as defined by the cropping rectangle.
5067 */
5068 clone_image=CloneImage(image,0,0,MagickTrue,&image->exception);
5069 if (clone_image != (Image *) NULL)
5070 {
5071 crop_image=CropImage(clone_image,&crop_info,&image->exception);
5072 if (crop_image != (Image *) NULL)
5073 {
5074 image=DestroyImage(image);
5075 image=crop_image;
5076 }
5077 }
5078 }
5079 status=XGetWMName(display,target,&window_name);
5080 if (status == True)
5081 {
5082 if ((image_info->filename != (char *) NULL) &&
5083 (*image_info->filename == '\0'))
5084 (void) CopyMagickString(image->filename,(char *) window_name.value,
5085 (size_t) window_name.nitems+1);
5086 (void) XFree((void *) window_name.value);
5087 }
5088 }
5089 if (ximage_info->silent == MagickFalse)
5090 {
5091 /*
5092 Alert the user we're done.
5093 */
5094 (void) XBell(display,0);
5095 (void) XBell(display,0);
5096 }
5097 (void) XCloseDisplay(display);
5098 return(image);
5099}
5100
5101/*
5102%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5103% %
5104% %
5105% %
5106% X I n i t i a l i z e W i n d o w s %
5107% %
5108% %
5109% %
5110%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5111%
5112% XInitializeWindows() initializes the XWindows structure.
5113%
5114% The format of the XInitializeWindows method is:
5115%
5116% XWindows *XInitializeWindows(Display *display,
5117% XResourceInfo *resource_info)
5118%
5119% A description of each parameter follows:
5120%
5121% o windows: XInitializeWindows returns a pointer to a XWindows structure.
5122%
5123% o display: Specifies a connection to an X server; returned from
5124% XOpenDisplay.
5125%
5126% o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
5127%
5128*/
cristybcbda3f2011-09-03 13:01:22 +00005129MagickPrivate XWindows *XInitializeWindows(Display *display,
cristy3ed852e2009-09-05 21:47:34 +00005130 XResourceInfo *resource_info)
5131{
5132 Window
5133 root_window;
5134
5135 XWindows
5136 *windows;
5137
5138 /*
5139 Allocate windows structure.
5140 */
cristy73bd4a52010-10-05 11:24:23 +00005141 windows=(XWindows *) AcquireMagickMemory(sizeof(*windows));
cristy3ed852e2009-09-05 21:47:34 +00005142 if (windows == (XWindows *) NULL)
5143 {
5144 ThrowXWindowFatalException(XServerFatalError,"MemoryAllocationFailed",
5145 "...");
5146 return((XWindows *) NULL);
5147 }
5148 (void) ResetMagickMemory(windows,0,sizeof(*windows));
5149 windows->pixel_info=(XPixelInfo *) AcquireMagickMemory(
5150 sizeof(*windows->pixel_info));
5151 windows->icon_pixel=(XPixelInfo *) AcquireMagickMemory(
5152 sizeof(*windows->icon_pixel));
5153 windows->icon_resources=(XResourceInfo *) AcquireMagickMemory(
5154 sizeof(*windows->icon_resources));
5155 if ((windows->pixel_info == (XPixelInfo *) NULL) ||
5156 (windows->icon_pixel == (XPixelInfo *) NULL) ||
5157 (windows->icon_resources == (XResourceInfo *) NULL))
5158 {
5159 ThrowXWindowFatalException(XServerFatalError,"MemoryAllocationFailed",
5160 "...");
5161 return((XWindows *) NULL);
5162 }
5163 /*
5164 Initialize windows structure.
5165 */
5166 windows->display=display;
5167 windows->wm_protocols=XInternAtom(display,"WM_PROTOCOLS",MagickFalse);
5168 windows->wm_delete_window=XInternAtom(display,"WM_DELETE_WINDOW",MagickFalse);
5169 windows->wm_take_focus=XInternAtom(display,"WM_TAKE_FOCUS",MagickFalse);
5170 windows->im_protocols=XInternAtom(display,"IM_PROTOCOLS",MagickFalse);
5171 windows->im_remote_command=
5172 XInternAtom(display,"IM_REMOTE_COMMAND",MagickFalse);
5173 windows->im_update_widget=XInternAtom(display,"IM_UPDATE_WIDGET",MagickFalse);
5174 windows->im_update_colormap=
5175 XInternAtom(display,"IM_UPDATE_COLORMAP",MagickFalse);
5176 windows->im_former_image=XInternAtom(display,"IM_FORMER_IMAGE",MagickFalse);
5177 windows->im_next_image=XInternAtom(display,"IM_NEXT_IMAGE",MagickFalse);
5178 windows->im_retain_colors=XInternAtom(display,"IM_RETAIN_COLORS",MagickFalse);
5179 windows->im_exit=XInternAtom(display,"IM_EXIT",MagickFalse);
5180 windows->dnd_protocols=XInternAtom(display,"DndProtocol",MagickFalse);
cristy0157aea2010-04-24 21:12:18 +00005181#if defined(MAGICKCORE_WINDOWS_SUPPORT)
cristy3ed852e2009-09-05 21:47:34 +00005182 (void) XSynchronize(display,IsWindows95());
5183#endif
5184 if (IsEventLogging())
5185 {
5186 (void) XSynchronize(display,MagickTrue);
5187 (void) LogMagickEvent(X11Event,GetMagickModule(),"Version: %s",
cristybb503372010-05-27 20:51:26 +00005188 GetMagickVersion((size_t *) NULL));
cristy3ed852e2009-09-05 21:47:34 +00005189 (void) LogMagickEvent(X11Event,GetMagickModule(),"Protocols:");
5190 (void) LogMagickEvent(X11Event,GetMagickModule(),
5191 " Window Manager: 0x%lx",windows->wm_protocols);
5192 (void) LogMagickEvent(X11Event,GetMagickModule(),
5193 " delete window: 0x%lx",windows->wm_delete_window);
5194 (void) LogMagickEvent(X11Event,GetMagickModule()," take focus: 0x%lx",
5195 windows->wm_take_focus);
5196 (void) LogMagickEvent(X11Event,GetMagickModule()," ImageMagick: 0x%lx",
5197 windows->im_protocols);
5198 (void) LogMagickEvent(X11Event,GetMagickModule(),
5199 " remote command: 0x%lx",windows->im_remote_command);
5200 (void) LogMagickEvent(X11Event,GetMagickModule(),
5201 " update widget: 0x%lx",windows->im_update_widget);
5202 (void) LogMagickEvent(X11Event,GetMagickModule(),
5203 " update colormap: 0x%lx",windows->im_update_colormap);
5204 (void) LogMagickEvent(X11Event,GetMagickModule(),
5205 " former image: 0x%lx",windows->im_former_image);
5206 (void) LogMagickEvent(X11Event,GetMagickModule()," next image: 0x%lx",
5207 windows->im_next_image);
5208 (void) LogMagickEvent(X11Event,GetMagickModule(),
5209 " retain colors: 0x%lx",windows->im_retain_colors);
5210 (void) LogMagickEvent(X11Event,GetMagickModule()," exit: 0x%lx",
5211 windows->im_exit);
5212 (void) LogMagickEvent(X11Event,GetMagickModule()," Drag and Drop: 0x%lx",
5213 windows->dnd_protocols);
5214 }
5215 /*
5216 Allocate standard colormap.
5217 */
5218 windows->map_info=XAllocStandardColormap();
5219 windows->icon_map=XAllocStandardColormap();
5220 if ((windows->map_info == (XStandardColormap *) NULL) ||
5221 (windows->icon_map == (XStandardColormap *) NULL))
5222 ThrowXWindowFatalException(ResourceLimitFatalError,
5223 "MemoryAllocationFailed","...");
5224 windows->map_info->colormap=(Colormap) NULL;
5225 windows->icon_map->colormap=(Colormap) NULL;
cristyf2faecf2010-05-28 19:19:36 +00005226 windows->pixel_info->pixels=(unsigned long *) NULL;
cristy3ed852e2009-09-05 21:47:34 +00005227 windows->pixel_info->annotate_context=(GC) NULL;
5228 windows->pixel_info->highlight_context=(GC) NULL;
5229 windows->pixel_info->widget_context=(GC) NULL;
5230 windows->font_info=(XFontStruct *) NULL;
5231 windows->icon_pixel->annotate_context=(GC) NULL;
cristyf2faecf2010-05-28 19:19:36 +00005232 windows->icon_pixel->pixels=(unsigned long *) NULL;
cristy3ed852e2009-09-05 21:47:34 +00005233 /*
5234 Allocate visual.
5235 */
5236 *windows->icon_resources=(*resource_info);
5237 windows->icon_resources->visual_type=(char *) "default";
5238 windows->icon_resources->colormap=SharedColormap;
5239 windows->visual_info=
5240 XBestVisualInfo(display,windows->map_info,resource_info);
5241 windows->icon_visual=
5242 XBestVisualInfo(display,windows->icon_map,windows->icon_resources);
5243 if ((windows->visual_info == (XVisualInfo *) NULL) ||
5244 (windows->icon_visual == (XVisualInfo *) NULL))
5245 ThrowXWindowFatalException(XServerFatalError,"UnableToGetVisual",
5246 resource_info->visual_type);
5247 if (IsEventLogging())
5248 {
5249 (void) LogMagickEvent(X11Event,GetMagickModule(),"Visual:");
5250 (void) LogMagickEvent(X11Event,GetMagickModule()," visual id: 0x%lx",
5251 windows->visual_info->visualid);
5252 (void) LogMagickEvent(X11Event,GetMagickModule()," class: %s",
5253 XVisualClassName(windows->visual_info->klass));
5254 (void) LogMagickEvent(X11Event,GetMagickModule()," depth: %d planes",
5255 windows->visual_info->depth);
5256 (void) LogMagickEvent(X11Event,GetMagickModule(),
5257 " size of colormap: %d entries",windows->visual_info->colormap_size);
5258 (void) LogMagickEvent(X11Event,GetMagickModule(),
5259 " red, green, blue masks: 0x%lx 0x%lx 0x%lx",
5260 windows->visual_info->red_mask,windows->visual_info->green_mask,
5261 windows->visual_info->blue_mask);
5262 (void) LogMagickEvent(X11Event,GetMagickModule(),
5263 " significant bits in color: %d bits",
5264 windows->visual_info->bits_per_rgb);
5265 }
5266 /*
5267 Allocate class and manager hints.
5268 */
5269 windows->class_hints=XAllocClassHint();
5270 windows->manager_hints=XAllocWMHints();
5271 if ((windows->class_hints == (XClassHint *) NULL) ||
5272 (windows->manager_hints == (XWMHints *) NULL))
5273 ThrowXWindowFatalException(ResourceLimitFatalError,
5274 "MemoryAllocationFailed","...");
5275 /*
5276 Determine group leader if we have one.
5277 */
5278 root_window=XRootWindow(display,windows->visual_info->screen);
5279 windows->group_leader.id=(Window) NULL;
5280 if (resource_info->window_group != (char *) NULL)
5281 {
5282 if (isdigit((unsigned char) *resource_info->window_group) != 0)
5283 windows->group_leader.id=XWindowByID(display,root_window,(Window)
5284 strtol((char *) resource_info->window_group,(char **) NULL,0));
5285 if (windows->group_leader.id == (Window) NULL)
5286 windows->group_leader.id=
5287 XWindowByName(display,root_window,resource_info->window_group);
5288 }
5289 return(windows);
5290}
5291
5292/*
5293%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5294% %
5295% %
5296% %
5297% X M a k e C u r s o r %
5298% %
5299% %
5300% %
5301%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5302%
5303% XMakeCursor() creates a crosshairs X11 cursor.
5304%
5305% The format of the XMakeCursor method is:
5306%
5307% Cursor XMakeCursor(Display *display,Window window,Colormap colormap,
5308% char *background_color,char *foreground_color)
5309%
5310% A description of each parameter follows:
5311%
5312% o display: Specifies a connection to an X server; returned from
5313% XOpenDisplay.
5314%
5315% o window: Specifies the ID of the window for which the cursor is
5316% assigned.
5317%
5318% o colormap: Specifies the ID of the colormap from which the background
5319% and foreground color will be retrieved.
5320%
5321% o background_color: Specifies the color to use for the cursor background.
5322%
5323% o foreground_color: Specifies the color to use for the cursor foreground.
5324%
5325*/
cristybcbda3f2011-09-03 13:01:22 +00005326MagickPrivate Cursor XMakeCursor(Display *display,Window window,
cristy3ed852e2009-09-05 21:47:34 +00005327 Colormap colormap,char *background_color,char *foreground_color)
5328{
5329#define scope_height 17
5330#define scope_x_hot 8
5331#define scope_y_hot 8
5332#define scope_width 17
5333
5334 static const unsigned char
5335 scope_bits[] =
5336 {
5337 0x80, 0x03, 0x00, 0x80, 0x02, 0x00, 0x80, 0x02, 0x00, 0x80, 0x02,
5338 0x00, 0x80, 0x02, 0x00, 0x80, 0x02, 0x00, 0x80, 0x02, 0x00, 0x7f,
5339 0xfc, 0x01, 0x01, 0x00, 0x01, 0x7f, 0xfc, 0x01, 0x80, 0x02, 0x00,
5340 0x80, 0x02, 0x00, 0x80, 0x02, 0x00, 0x80, 0x02, 0x00, 0x80, 0x02,
5341 0x00, 0x80, 0x02, 0x00, 0x80, 0x03, 0x00
5342 },
5343 scope_mask_bits[] =
5344 {
5345 0xc0, 0x07, 0x00, 0xc0, 0x07, 0x00, 0xc0, 0x06, 0x00, 0xc0, 0x06,
5346 0x00, 0xc0, 0x06, 0x00, 0xc0, 0x06, 0x00, 0xff, 0xfe, 0x01, 0x7f,
5347 0xfc, 0x01, 0x03, 0x80, 0x01, 0x7f, 0xfc, 0x01, 0xff, 0xfe, 0x01,
5348 0xc0, 0x06, 0x00, 0xc0, 0x06, 0x00, 0xc0, 0x06, 0x00, 0xc0, 0x06,
5349 0x00, 0xc0, 0x07, 0x00, 0xc0, 0x07, 0x00
5350 };
5351
5352 Cursor
5353 cursor;
5354
5355 Pixmap
5356 mask,
5357 source;
5358
5359 XColor
5360 background,
5361 foreground;
5362
5363 assert(display != (Display *) NULL);
5364 assert(window != (Window) NULL);
5365 assert(colormap != (Colormap) NULL);
5366 assert(background_color != (char *) NULL);
5367 assert(foreground_color != (char *) NULL);
5368 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",background_color);
5369 source=XCreateBitmapFromData(display,window,(char *) scope_bits,scope_width,
5370 scope_height);
5371 mask=XCreateBitmapFromData(display,window,(char *) scope_mask_bits,
5372 scope_width,scope_height);
5373 if ((source == (Pixmap) NULL) || (mask == (Pixmap) NULL))
5374 {
5375 ThrowXWindowFatalException(XServerError,"UnableToCreatePixmap","...");
5376 return((Cursor) NULL);
5377 }
5378 (void) XParseColor(display,colormap,background_color,&background);
5379 (void) XParseColor(display,colormap,foreground_color,&foreground);
5380 cursor=XCreatePixmapCursor(display,source,mask,&foreground,&background,
5381 scope_x_hot,scope_y_hot);
5382 (void) XFreePixmap(display,source);
5383 (void) XFreePixmap(display,mask);
5384 return(cursor);
5385}
5386
5387/*
5388%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5389% %
5390% %
5391% %
5392% X M a k e I m a g e %
5393% %
5394% %
5395% %
5396%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5397%
5398% XMakeImage() creates an X11 image. If the image size differs from the X11
5399% image size, the image is first resized.
5400%
5401% The format of the XMakeImage method is:
5402%
5403% MagickBooleanType XMakeImage(Display *display,
5404% const XResourceInfo *resource_info,XWindowInfo *window,Image *image,
cristy051718b2011-08-28 22:49:25 +00005405% unsigned int width,unsigned int height,ExceptionInfo *exception)
cristy3ed852e2009-09-05 21:47:34 +00005406%
5407% A description of each parameter follows:
5408%
5409% o display: Specifies a connection to an X server; returned from
5410% XOpenDisplay.
5411%
5412% o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
5413%
5414% o window: Specifies a pointer to a XWindowInfo structure.
5415%
5416% o image: the image.
5417%
5418% o width: Specifies the width in pixels of the rectangular area to
5419% display.
5420%
5421% o height: Specifies the height in pixels of the rectangular area to
5422% display.
5423%
cristy051718b2011-08-28 22:49:25 +00005424% o exception: return any errors or warnings in this structure.
5425%
cristy3ed852e2009-09-05 21:47:34 +00005426*/
cristybcbda3f2011-09-03 13:01:22 +00005427MagickPrivate MagickBooleanType XMakeImage(Display *display,
cristy3ed852e2009-09-05 21:47:34 +00005428 const XResourceInfo *resource_info,XWindowInfo *window,Image *image,
cristy051718b2011-08-28 22:49:25 +00005429 unsigned int width,unsigned int height,ExceptionInfo *exception)
cristy3ed852e2009-09-05 21:47:34 +00005430{
5431#define CheckOverflowException(length,width,height) \
5432 (((height) != 0) && ((length)/((size_t) height) != ((size_t) width)))
5433
5434 int
5435 depth,
5436 format;
5437
5438 size_t
5439 length;
5440
5441 XImage
5442 *matte_image,
5443 *ximage;
5444
5445 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
5446 assert(display != (Display *) NULL);
5447 assert(resource_info != (XResourceInfo *) NULL);
5448 assert(window != (XWindowInfo *) NULL);
5449 assert(width != 0);
5450 assert(height != 0);
5451 if ((window->width == 0) || (window->height == 0))
5452 return(MagickFalse);
5453 /*
5454 Apply user transforms to the image.
5455 */
5456 (void) XCheckDefineCursor(display,window->id,window->busy_cursor);
5457 (void) XFlush(display);
5458 depth=(int) window->depth;
5459 if (window->destroy)
5460 window->image=DestroyImage(window->image);
5461 window->image=image;
5462 window->destroy=MagickFalse;
5463 if (window->image != (Image *) NULL)
5464 {
5465 if (window->crop_geometry != (char *) NULL)
5466 {
5467 Image
5468 *crop_image;
5469
5470 RectangleInfo
5471 crop_info;
5472
5473 /*
5474 Crop image.
5475 */
5476 window->image->page.x=0;
5477 window->image->page.y=0;
5478 (void) ParsePageGeometry(window->image,window->crop_geometry,
5479 &crop_info,&image->exception);
5480 crop_image=CropImage(window->image,&crop_info,&image->exception);
5481 if (crop_image != (Image *) NULL)
5482 {
5483 if (window->image != image)
5484 window->image=DestroyImage(window->image);
5485 window->image=crop_image;
5486 window->destroy=MagickTrue;
5487 }
5488 }
5489 if ((width != (unsigned int) window->image->columns) ||
5490 (height != (unsigned int) window->image->rows))
5491 {
5492 Image
5493 *resize_image;
5494
5495 /*
5496 Resize image.
5497 */
5498 resize_image=NewImageList();
5499 if (window->pixel_info->colors != 0)
5500 resize_image=SampleImage(window->image,width,height,
5501 &image->exception);
5502 else
5503 resize_image=ThumbnailImage(window->image,width,height,
5504 &image->exception);
5505 if (resize_image != (Image *) NULL)
5506 {
5507 if (window->image != image)
5508 window->image=DestroyImage(window->image);
5509 window->image=resize_image;
5510 window->destroy=MagickTrue;
5511 }
5512 }
5513 width=(unsigned int) window->image->columns;
cristybb503372010-05-27 20:51:26 +00005514 assert((size_t) width == window->image->columns);
cristy3ed852e2009-09-05 21:47:34 +00005515 height=(unsigned int) window->image->rows;
cristybb503372010-05-27 20:51:26 +00005516 assert((size_t) height == window->image->rows);
cristy3ed852e2009-09-05 21:47:34 +00005517 }
5518 /*
5519 Create X image.
5520 */
5521 ximage=(XImage *) NULL;
5522 format=(depth == 1) ? XYBitmap : ZPixmap;
5523#if defined(MAGICKCORE_HAVE_SHARED_MEMORY)
5524 if (window->shared_memory != MagickFalse)
5525 {
5526 XShmSegmentInfo
5527 *segment_info;
5528
5529 segment_info=(XShmSegmentInfo *) window->segment_info;
5530 segment_info[1].shmid=(-1);
5531 segment_info[1].shmaddr=(char *) NULL;
5532 ximage=XShmCreateImage(display,window->visual,(unsigned int) depth,format,
5533 (char *) NULL,&segment_info[1],width,height);
5534 if (ximage == (XImage *) NULL)
5535 window->shared_memory=MagickFalse;
5536 length=(size_t) ximage->bytes_per_line*ximage->height;
5537 if (CheckOverflowException(length,ximage->bytes_per_line,ximage->height))
5538 window->shared_memory=MagickFalse;
5539 if (window->shared_memory != MagickFalse)
5540 segment_info[1].shmid=shmget(IPC_PRIVATE,length,IPC_CREAT | 0777);
5541 if (window->shared_memory != MagickFalse)
5542 segment_info[1].shmaddr=(char *) shmat(segment_info[1].shmid,0,0);
5543 if (segment_info[1].shmid < 0)
5544 window->shared_memory=MagickFalse;
5545 if (window->shared_memory != MagickFalse)
5546 (void) shmctl(segment_info[1].shmid,IPC_RMID,0);
5547 else
5548 {
5549 if (ximage != (XImage *) NULL)
5550 XDestroyImage(ximage);
5551 ximage=(XImage *) NULL;
5552 if (segment_info[1].shmaddr)
5553 {
5554 (void) shmdt(segment_info[1].shmaddr);
5555 segment_info[1].shmaddr=(char *) NULL;
5556 }
5557 if (segment_info[1].shmid >= 0)
5558 {
5559 (void) shmctl(segment_info[1].shmid,IPC_RMID,0);
5560 segment_info[1].shmid=(-1);
5561 }
5562 }
5563 }
5564#endif
5565 /*
5566 Allocate X image pixel data.
5567 */
5568#if defined(MAGICKCORE_HAVE_SHARED_MEMORY)
5569 if (window->shared_memory)
5570 {
5571 Status
5572 status;
5573
5574 XShmSegmentInfo
5575 *segment_info;
5576
5577 (void) XSync(display,MagickFalse);
5578 xerror_alert=MagickFalse;
5579 segment_info=(XShmSegmentInfo *) window->segment_info;
5580 ximage->data=segment_info[1].shmaddr;
5581 segment_info[1].readOnly=MagickFalse;
5582 status=XShmAttach(display,&segment_info[1]);
5583 if (status != False)
5584 (void) XSync(display,MagickFalse);
5585 if ((status == False) || (xerror_alert != MagickFalse))
5586 {
5587 window->shared_memory=MagickFalse;
5588 if (status != False)
5589 XShmDetach(display,&segment_info[1]);
5590 if (ximage != (XImage *) NULL)
5591 {
5592 ximage->data=NULL;
5593 XDestroyImage(ximage);
5594 ximage=(XImage *) NULL;
5595 }
5596 if (segment_info[1].shmid >= 0)
5597 {
5598 if (segment_info[1].shmaddr != NULL)
5599 (void) shmdt(segment_info[1].shmaddr);
5600 (void) shmctl(segment_info[1].shmid,IPC_RMID,0);
5601 segment_info[1].shmid=(-1);
5602 segment_info[1].shmaddr=(char *) NULL;
5603 }
5604 }
5605 }
5606#endif
5607 if (window->shared_memory == MagickFalse)
5608 ximage=XCreateImage(display,window->visual,(unsigned int) depth,format,0,
5609 (char *) NULL,width,height,XBitmapPad(display),0);
5610 if (ximage == (XImage *) NULL)
5611 {
5612 /*
5613 Unable to create X image.
5614 */
5615 (void) XCheckDefineCursor(display,window->id,window->cursor);
5616 return(MagickFalse);
5617 }
5618 length=(size_t) ximage->bytes_per_line*ximage->height;
5619 if (IsEventLogging())
5620 {
5621 (void) LogMagickEvent(X11Event,GetMagickModule(),"XImage:");
5622 (void) LogMagickEvent(X11Event,GetMagickModule()," width, height: %dx%d",
5623 ximage->width,ximage->height);
5624 (void) LogMagickEvent(X11Event,GetMagickModule()," format: %d",
5625 ximage->format);
5626 (void) LogMagickEvent(X11Event,GetMagickModule()," byte order: %d",
5627 ximage->byte_order);
5628 (void) LogMagickEvent(X11Event,GetMagickModule(),
5629 " bitmap unit, bit order, pad: %d %d %d",ximage->bitmap_unit,
5630 ximage->bitmap_bit_order,ximage->bitmap_pad);
5631 (void) LogMagickEvent(X11Event,GetMagickModule()," depth: %d",
5632 ximage->depth);
5633 (void) LogMagickEvent(X11Event,GetMagickModule()," bytes per line: %d",
5634 ximage->bytes_per_line);
5635 (void) LogMagickEvent(X11Event,GetMagickModule()," bits per pixel: %d",
5636 ximage->bits_per_pixel);
5637 (void) LogMagickEvent(X11Event,GetMagickModule(),
5638 " red, green, blue masks: 0x%lx 0x%lx 0x%lx",ximage->red_mask,
5639 ximage->green_mask,ximage->blue_mask);
5640 }
5641 if (window->shared_memory == MagickFalse)
5642 {
5643 if (ximage->format != XYBitmap)
5644 ximage->data=(char *) AcquireQuantumMemory((size_t)
5645 ximage->bytes_per_line,(size_t) ximage->height);
5646 else
5647 ximage->data=(char *) AcquireQuantumMemory((size_t)
5648 ximage->bytes_per_line*ximage->depth,(size_t) ximage->height);
5649 }
5650 if (ximage->data == (char *) NULL)
5651 {
5652 /*
5653 Unable to allocate pixel data.
5654 */
5655 XDestroyImage(ximage);
5656 ximage=(XImage *) NULL;
5657 (void) XCheckDefineCursor(display,window->id,window->cursor);
5658 return(MagickFalse);
5659 }
5660 if (window->ximage != (XImage *) NULL)
5661 {
5662 /*
5663 Destroy previous X image.
5664 */
5665 length=(size_t) window->ximage->bytes_per_line*window->ximage->height;
5666#if defined(MAGICKCORE_HAVE_SHARED_MEMORY)
5667 if (window->segment_info != (XShmSegmentInfo *) NULL)
5668 {
5669 XShmSegmentInfo
5670 *segment_info;
5671
5672 segment_info=(XShmSegmentInfo *) window->segment_info;
5673 if (segment_info[0].shmid >= 0)
5674 {
5675 (void) XSync(display,MagickFalse);
5676 (void) XShmDetach(display,&segment_info[0]);
5677 (void) XSync(display,MagickFalse);
5678 if (segment_info[0].shmaddr != (char *) NULL)
5679 (void) shmdt(segment_info[0].shmaddr);
5680 (void) shmctl(segment_info[0].shmid,IPC_RMID,0);
5681 segment_info[0].shmid=(-1);
5682 segment_info[0].shmaddr=(char *) NULL;
5683 window->ximage->data=(char *) NULL;
5684 }
5685 }
5686#endif
5687 if (window->ximage->data != (char *) NULL)
5688 free(window->ximage->data);
5689 window->ximage->data=(char *) NULL;
5690 XDestroyImage(window->ximage);
5691 window->ximage=(XImage *) NULL;
5692 }
5693#if defined(MAGICKCORE_HAVE_SHARED_MEMORY)
5694 if (window->segment_info != (XShmSegmentInfo *) NULL)
5695 {
5696 XShmSegmentInfo
5697 *segment_info;
5698
5699 segment_info=(XShmSegmentInfo *) window->segment_info;
5700 segment_info[0]=segment_info[1];
5701 }
5702#endif
5703 window->ximage=ximage;
5704 matte_image=(XImage *) NULL;
5705 if ((window->shape != MagickFalse) && (window->image != (Image *) NULL))
5706 if ((window->image->matte != MagickFalse) &&
cristyc57f6942010-11-12 01:47:39 +00005707 ((int) width <= XDisplayWidth(display,window->screen)) &&
5708 ((int) height <= XDisplayHeight(display,window->screen)))
cristy3ed852e2009-09-05 21:47:34 +00005709 {
5710 /*
5711 Create matte image.
5712 */
5713 matte_image=XCreateImage(display,window->visual,1,XYBitmap,0,
5714 (char *) NULL,width,height,XBitmapPad(display),0);
5715 if (IsEventLogging())
5716 {
5717 (void) LogMagickEvent(X11Event,GetMagickModule(),"Matte Image:");
5718 (void) LogMagickEvent(X11Event,GetMagickModule(),
5719 " width, height: %dx%d",matte_image->width,matte_image->height);
5720 }
5721 if (matte_image != (XImage *) NULL)
5722 {
5723 /*
5724 Allocate matte image pixel data.
5725 */
5726 matte_image->data=(char *) AcquireQuantumMemory((size_t)
5727 matte_image->bytes_per_line*matte_image->depth,
5728 (size_t) matte_image->height);
5729 if (matte_image->data == (char *) NULL)
5730 {
5731 XDestroyImage(matte_image);
5732 matte_image=(XImage *) NULL;
5733 }
5734 }
5735 }
5736 if (window->matte_image != (XImage *) NULL)
5737 {
5738 /*
5739 Free matte image.
5740 */
5741 if (window->matte_image->data != (char *) NULL)
5742 free(window->matte_image->data);
5743 window->matte_image->data=(char *) NULL;
5744 XDestroyImage(window->matte_image);
5745 window->matte_image=(XImage *) NULL;
5746 }
5747 window->matte_image=matte_image;
5748 if (window->matte_pixmap != (Pixmap) NULL)
5749 {
5750 (void) XFreePixmap(display,window->matte_pixmap);
5751 window->matte_pixmap=(Pixmap) NULL;
5752#if defined(MAGICKCORE_HAVE_SHAPE)
5753 if (window->shape != MagickFalse)
5754 XShapeCombineMask(display,window->id,ShapeBounding,0,0,None,ShapeSet);
5755#endif
5756 }
5757 window->stasis=MagickFalse;
5758 /*
5759 Convert pixels to X image data.
5760 */
5761 if (window->image != (Image *) NULL)
5762 {
5763 if ((ximage->byte_order == LSBFirst) || ((ximage->format == XYBitmap) &&
5764 (ximage->bitmap_bit_order == LSBFirst)))
5765 XMakeImageLSBFirst(resource_info,window,window->image,ximage,
5766 matte_image);
5767 else
5768 XMakeImageMSBFirst(resource_info,window,window->image,ximage,
5769 matte_image);
5770 }
5771 if (window->matte_image != (XImage *) NULL)
5772 {
5773 /*
5774 Create matte pixmap.
5775 */
5776 window->matte_pixmap=XCreatePixmap(display,window->id,width,height,1);
5777 if (window->matte_pixmap != (Pixmap) NULL)
5778 {
5779 GC
5780 graphics_context;
5781
5782 XGCValues
5783 context_values;
5784
5785 /*
5786 Copy matte image to matte pixmap.
5787 */
cristy4c08aed2011-07-01 19:47:50 +00005788 context_values.background=0;
5789 context_values.foreground=1;
cristy3ed852e2009-09-05 21:47:34 +00005790 graphics_context=XCreateGC(display,window->matte_pixmap,
cristybb503372010-05-27 20:51:26 +00005791 (size_t) (GCBackground | GCForeground),&context_values);
cristy3ed852e2009-09-05 21:47:34 +00005792 (void) XPutImage(display,window->matte_pixmap,graphics_context,
5793 window->matte_image,0,0,0,0,width,height);
5794 (void) XFreeGC(display,graphics_context);
5795#if defined(MAGICKCORE_HAVE_SHAPE)
5796 if (window->shape != MagickFalse)
5797 XShapeCombineMask(display,window->id,ShapeBounding,0,0,
5798 window->matte_pixmap,ShapeSet);
5799#endif
5800 }
5801 }
5802 (void) XMakePixmap(display,resource_info,window);
5803 /*
5804 Restore cursor.
5805 */
5806 (void) XCheckDefineCursor(display,window->id,window->cursor);
5807 return(MagickTrue);
5808}
5809
5810/*
5811%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5812% %
5813% %
5814% %
5815+ X M a k e I m a g e L S B F i r s t %
5816% %
5817% %
5818% %
5819%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5820%
5821% XMakeImageLSBFirst() initializes the pixel data of an X11 Image. The X image
5822% pixels are copied in least-significant bit and byte first order. The
5823% server's scanline pad is respected. Rather than using one or two general
5824% cases, many special cases are found here to help speed up the image
5825% conversion.
5826%
5827% The format of the XMakeImageLSBFirst method is:
5828%
5829% void XMakeImageLSBFirst(Display *display,XWindows *windows)
5830%
5831% A description of each parameter follows:
5832%
5833% o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
5834%
5835% o window: Specifies a pointer to a XWindowInfo structure.
5836%
5837% o image: the image.
5838%
5839% o ximage: Specifies a pointer to a XImage structure; returned from
5840% XCreateImage.
5841%
5842% o matte_image: Specifies a pointer to a XImage structure; returned from
5843% XCreateImage.
5844%
5845*/
5846static void XMakeImageLSBFirst(const XResourceInfo *resource_info,
5847 const XWindowInfo *window,Image *image,XImage *ximage,XImage *matte_image)
5848{
cristyc57f6942010-11-12 01:47:39 +00005849 CacheView
5850 *canvas_view;
5851
cristy3ed852e2009-09-05 21:47:34 +00005852 Image
5853 *canvas;
5854
5855 int
5856 y;
5857
cristy4c08aed2011-07-01 19:47:50 +00005858 register const Quantum
cristy3ed852e2009-09-05 21:47:34 +00005859 *p;
5860
5861 register int
5862 x;
5863
5864 register unsigned char
5865 *q;
5866
5867 unsigned char
5868 bit,
5869 byte;
5870
5871 unsigned int
5872 scanline_pad;
5873
cristyf2faecf2010-05-28 19:19:36 +00005874 unsigned long
cristy3ed852e2009-09-05 21:47:34 +00005875 pixel,
5876 *pixels;
5877
5878 XStandardColormap
5879 *map_info;
5880
5881 assert(resource_info != (XResourceInfo *) NULL);
5882 assert(window != (XWindowInfo *) NULL);
5883 assert(image != (Image *) NULL);
5884 if (image->debug != MagickFalse)
5885 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
5886 canvas=image;
cristybab87c32010-02-09 20:54:22 +00005887 if ((window->immutable == MagickFalse) &&
cristy54666e82010-02-03 23:34:26 +00005888 (image->storage_class == DirectClass) && (image->matte != MagickFalse))
cristy3ed852e2009-09-05 21:47:34 +00005889 {
5890 char
5891 size[MaxTextExtent];
5892
5893 Image
5894 *pattern;
5895
5896 ImageInfo
5897 *image_info;
5898
5899 image_info=AcquireImageInfo();
5900 (void) CopyMagickString(image_info->filename,
5901 resource_info->image_info->texture != (char *) NULL ?
5902 resource_info->image_info->texture : "pattern:checkerboard",
5903 MaxTextExtent);
cristyb51dff52011-05-19 16:55:47 +00005904 (void) FormatLocaleString(size,MaxTextExtent,"%.20gx%.20g",(double)
cristye8c25f92010-06-03 00:53:06 +00005905 image->columns,(double) image->rows);
cristy3ed852e2009-09-05 21:47:34 +00005906 image_info->size=ConstantString(size);
5907 pattern=ReadImage(image_info,&image->exception);
5908 image_info=DestroyImageInfo(image_info);
5909 if (pattern != (Image *) NULL)
5910 {
5911 canvas=CloneImage(image,0,0,MagickTrue,&image->exception);
5912 if (canvas != (Image *) NULL)
5913 (void) CompositeImage(canvas,DstOverCompositeOp,pattern,0,0);
5914 pattern=DestroyImage(pattern);
5915 }
5916 }
5917 scanline_pad=(unsigned int) (ximage->bytes_per_line-((ximage->width*
5918 ximage->bits_per_pixel) >> 3));
5919 map_info=window->map_info;
5920 pixels=window->pixel_info->pixels;
5921 q=(unsigned char *) ximage->data;
5922 x=0;
cristyc57f6942010-11-12 01:47:39 +00005923 canvas_view=AcquireCacheView(canvas);
cristy3ed852e2009-09-05 21:47:34 +00005924 if (ximage->format == XYBitmap)
5925 {
5926 register unsigned short
5927 polarity;
5928
5929 unsigned char
5930 background,
5931 foreground;
5932
5933 /*
5934 Convert canvas to big-endian bitmap.
5935 */
5936 background=(unsigned char)
5937 (XPixelIntensity(&window->pixel_info->foreground_color) <
5938 XPixelIntensity(&window->pixel_info->background_color) ? 0x80 : 0x00);
5939 foreground=(unsigned char)
5940 (XPixelIntensity(&window->pixel_info->background_color) <
5941 XPixelIntensity(&window->pixel_info->foreground_color) ? 0x80 : 0x00);
cristy4c08aed2011-07-01 19:47:50 +00005942 polarity=(unsigned short) ((GetPixelPacketIntensity(
cristy3ed852e2009-09-05 21:47:34 +00005943 &canvas->colormap[0])) < ((Quantum) QuantumRange/2) ? 1 : 0);
5944 if (canvas->colors == 2)
cristy4c08aed2011-07-01 19:47:50 +00005945 polarity=GetPixelPacketIntensity(&canvas->colormap[0]) <
5946 GetPixelPacketIntensity(&canvas->colormap[1]);
cristy3ed852e2009-09-05 21:47:34 +00005947 for (y=0; y < (int) canvas->rows; y++)
5948 {
cristyc57f6942010-11-12 01:47:39 +00005949 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,canvas->columns,1,
5950 &canvas->exception);
cristy4c08aed2011-07-01 19:47:50 +00005951 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00005952 break;
cristy3ed852e2009-09-05 21:47:34 +00005953 bit=0;
5954 byte=0;
5955 for (x=0; x < (int) canvas->columns; x++)
5956 {
5957 byte>>=1;
cristy4c08aed2011-07-01 19:47:50 +00005958 if (GetPixelIndex(canvas,p) == (Quantum) polarity)
cristy3ed852e2009-09-05 21:47:34 +00005959 byte|=foreground;
5960 else
5961 byte|=background;
5962 bit++;
5963 if (bit == 8)
5964 {
5965 *q++=byte;
5966 bit=0;
5967 byte=0;
5968 }
cristyed231572011-07-14 02:18:59 +00005969 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00005970 }
5971 if (bit != 0)
5972 *q=byte >> (8-bit);
5973 q+=scanline_pad;
5974 }
5975 }
5976 else
5977 if (window->pixel_info->colors != 0)
5978 switch (ximage->bits_per_pixel)
5979 {
5980 case 2:
5981 {
5982 register unsigned int
5983 nibble;
5984
5985 /*
5986 Convert to 2 bit color-mapped X canvas.
5987 */
5988 for (y=0; y < (int) canvas->rows; y++)
5989 {
cristyc57f6942010-11-12 01:47:39 +00005990 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
5991 canvas->columns,1,&canvas->exception);
cristy4c08aed2011-07-01 19:47:50 +00005992 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00005993 break;
cristy3ed852e2009-09-05 21:47:34 +00005994 nibble=0;
5995 for (x=0; x < (int) canvas->columns; x++)
5996 {
cristy4c08aed2011-07-01 19:47:50 +00005997 pixel=pixels[(ssize_t) GetPixelIndex(canvas,p)] & 0x0f;
cristy3ed852e2009-09-05 21:47:34 +00005998 switch (nibble)
5999 {
6000 case 0:
6001 {
6002 *q=(unsigned char) pixel;
6003 nibble++;
6004 break;
6005 }
6006 case 1:
6007 {
6008 *q|=(unsigned char) (pixel << 2);
6009 nibble++;
6010 break;
6011 }
6012 case 2:
6013 {
6014 *q|=(unsigned char) (pixel << 4);
6015 nibble++;
6016 break;
6017 }
6018 case 3:
6019 {
6020 *q|=(unsigned char) (pixel << 6);
6021 q++;
6022 nibble=0;
6023 break;
6024 }
6025 }
cristyed231572011-07-14 02:18:59 +00006026 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00006027 }
6028 q+=scanline_pad;
6029 }
6030 break;
6031 }
6032 case 4:
6033 {
6034 register unsigned int
6035 nibble;
6036
6037 /*
6038 Convert to 4 bit color-mapped X canvas.
6039 */
6040 for (y=0; y < (int) canvas->rows; y++)
6041 {
cristyc57f6942010-11-12 01:47:39 +00006042 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
6043 canvas->columns,1,&canvas->exception);
cristy4c08aed2011-07-01 19:47:50 +00006044 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00006045 break;
cristy3ed852e2009-09-05 21:47:34 +00006046 nibble=0;
6047 for (x=0; x < (int) canvas->columns; x++)
6048 {
cristy4c08aed2011-07-01 19:47:50 +00006049 pixel=pixels[(ssize_t) GetPixelIndex(canvas,p)] & 0xf;
cristy3ed852e2009-09-05 21:47:34 +00006050 switch (nibble)
6051 {
6052 case 0:
6053 {
6054 *q=(unsigned char) pixel;
6055 nibble++;
6056 break;
6057 }
6058 case 1:
6059 {
6060 *q|=(unsigned char) (pixel << 4);
6061 q++;
6062 nibble=0;
6063 break;
6064 }
6065 }
cristyed231572011-07-14 02:18:59 +00006066 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00006067 }
6068 q+=scanline_pad;
6069 }
6070 break;
6071 }
6072 case 6:
6073 case 8:
6074 {
6075 /*
6076 Convert to 8 bit color-mapped X canvas.
6077 */
6078 if (resource_info->color_recovery &&
6079 resource_info->quantize_info->dither)
6080 {
6081 XDitherImage(canvas,ximage);
6082 break;
6083 }
6084 for (y=0; y < (int) canvas->rows; y++)
6085 {
cristyc57f6942010-11-12 01:47:39 +00006086 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
6087 canvas->columns,1,&canvas->exception);
cristy4c08aed2011-07-01 19:47:50 +00006088 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00006089 break;
cristy3ed852e2009-09-05 21:47:34 +00006090 for (x=0; x < (int) canvas->columns; x++)
6091 {
cristy4c08aed2011-07-01 19:47:50 +00006092 pixel=pixels[(ssize_t) GetPixelIndex(canvas,p)];
cristy3ed852e2009-09-05 21:47:34 +00006093 *q++=(unsigned char) pixel;
cristyed231572011-07-14 02:18:59 +00006094 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00006095 }
6096 q+=scanline_pad;
6097 }
6098 break;
6099 }
6100 default:
6101 {
6102 register int
6103 k;
6104
6105 register unsigned int
6106 bytes_per_pixel;
6107
6108 unsigned char
cristybb503372010-05-27 20:51:26 +00006109 channel[sizeof(size_t)];
cristy3ed852e2009-09-05 21:47:34 +00006110
6111 /*
6112 Convert to multi-byte color-mapped X canvas.
6113 */
6114 bytes_per_pixel=(unsigned int) (ximage->bits_per_pixel >> 3);
6115 for (y=0; y < (int) canvas->rows; y++)
6116 {
cristyc57f6942010-11-12 01:47:39 +00006117 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
6118 canvas->columns,1,&canvas->exception);
cristy4c08aed2011-07-01 19:47:50 +00006119 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00006120 break;
cristy3ed852e2009-09-05 21:47:34 +00006121 for (x=0; x < (int) canvas->columns; x++)
6122 {
cristy4c08aed2011-07-01 19:47:50 +00006123 pixel=pixels[(ssize_t) GetPixelIndex(canvas,p)];
cristy3ed852e2009-09-05 21:47:34 +00006124 for (k=0; k < (int) bytes_per_pixel; k++)
6125 {
6126 channel[k]=(unsigned char) pixel;
6127 pixel>>=8;
6128 }
6129 for (k=0; k < (int) bytes_per_pixel; k++)
6130 *q++=channel[k];
cristyed231572011-07-14 02:18:59 +00006131 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00006132 }
6133 q+=scanline_pad;
6134 }
6135 break;
6136 }
6137 }
6138 else
6139 switch (ximage->bits_per_pixel)
6140 {
6141 case 2:
6142 {
6143 register unsigned int
6144 nibble;
6145
6146 /*
6147 Convert to contiguous 2 bit continuous-tone X canvas.
6148 */
6149 for (y=0; y < (int) canvas->rows; y++)
6150 {
6151 nibble=0;
cristyc57f6942010-11-12 01:47:39 +00006152 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
6153 canvas->columns,1,&canvas->exception);
cristy4c08aed2011-07-01 19:47:50 +00006154 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00006155 break;
6156 for (x=0; x < (int) canvas->columns; x++)
6157 {
cristy4c08aed2011-07-01 19:47:50 +00006158 pixel=XGammaPixel(canvas,map_info,p);
cristy3ed852e2009-09-05 21:47:34 +00006159 pixel&=0xf;
6160 switch (nibble)
6161 {
6162 case 0:
6163 {
6164 *q=(unsigned char) pixel;
6165 nibble++;
6166 break;
6167 }
6168 case 1:
6169 {
6170 *q|=(unsigned char) (pixel << 2);
6171 nibble++;
6172 break;
6173 }
6174 case 2:
6175 {
6176 *q|=(unsigned char) (pixel << 4);
6177 nibble++;
6178 break;
6179 }
6180 case 3:
6181 {
6182 *q|=(unsigned char) (pixel << 6);
6183 q++;
6184 nibble=0;
6185 break;
6186 }
6187 }
cristyed231572011-07-14 02:18:59 +00006188 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00006189 }
6190 q+=scanline_pad;
6191 }
6192 break;
6193 }
6194 case 4:
6195 {
6196 register unsigned int
6197 nibble;
6198
6199 /*
6200 Convert to contiguous 4 bit continuous-tone X canvas.
6201 */
6202 for (y=0; y < (int) canvas->rows; y++)
6203 {
cristyc57f6942010-11-12 01:47:39 +00006204 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
6205 canvas->columns,1,&canvas->exception);
cristy4c08aed2011-07-01 19:47:50 +00006206 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00006207 break;
6208 nibble=0;
6209 for (x=0; x < (int) canvas->columns; x++)
6210 {
cristy4c08aed2011-07-01 19:47:50 +00006211 pixel=XGammaPixel(canvas,map_info,p);
cristy3ed852e2009-09-05 21:47:34 +00006212 pixel&=0xf;
6213 switch (nibble)
6214 {
6215 case 0:
6216 {
6217 *q=(unsigned char) pixel;
6218 nibble++;
6219 break;
6220 }
6221 case 1:
6222 {
6223 *q|=(unsigned char) (pixel << 4);
6224 q++;
6225 nibble=0;
6226 break;
6227 }
6228 }
cristyed231572011-07-14 02:18:59 +00006229 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00006230 }
6231 q+=scanline_pad;
6232 }
6233 break;
6234 }
6235 case 6:
6236 case 8:
6237 {
6238 /*
6239 Convert to contiguous 8 bit continuous-tone X canvas.
6240 */
6241 if (resource_info->color_recovery &&
6242 resource_info->quantize_info->dither)
6243 {
6244 XDitherImage(canvas,ximage);
6245 break;
6246 }
6247 for (y=0; y < (int) canvas->rows; y++)
6248 {
cristyc57f6942010-11-12 01:47:39 +00006249 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
6250 canvas->columns,1,&canvas->exception);
cristy4c08aed2011-07-01 19:47:50 +00006251 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00006252 break;
6253 for (x=0; x < (int) canvas->columns; x++)
6254 {
cristy4c08aed2011-07-01 19:47:50 +00006255 pixel=XGammaPixel(canvas,map_info,p);
cristy3ed852e2009-09-05 21:47:34 +00006256 *q++=(unsigned char) pixel;
cristyed231572011-07-14 02:18:59 +00006257 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00006258 }
6259 q+=scanline_pad;
6260 }
6261 break;
6262 }
6263 default:
6264 {
6265 if ((ximage->bits_per_pixel == 32) && (map_info->red_max == 255) &&
6266 (map_info->green_max == 255) && (map_info->blue_max == 255) &&
6267 (map_info->red_mult == 65536L) && (map_info->green_mult == 256) &&
6268 (map_info->blue_mult == 1))
6269 {
6270 /*
6271 Convert to 32 bit continuous-tone X canvas.
6272 */
6273 for (y=0; y < (int) canvas->rows; y++)
6274 {
cristyc57f6942010-11-12 01:47:39 +00006275 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
6276 canvas->columns,1,&canvas->exception);
cristy4c08aed2011-07-01 19:47:50 +00006277 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00006278 break;
6279 if ((red_gamma != 1.0) || (green_gamma != 1.0) ||
6280 (blue_gamma != 1.0))
6281 {
6282 /*
6283 Gamma correct canvas.
6284 */
6285 for (x=(int) canvas->columns-1; x >= 0; x--)
6286 {
cristyccf844f2010-02-03 23:28:16 +00006287 *q++=ScaleQuantumToChar(XBlueGamma(
cristy4c08aed2011-07-01 19:47:50 +00006288 GetPixelBlue(canvas,p)));
cristyccf844f2010-02-03 23:28:16 +00006289 *q++=ScaleQuantumToChar(XGreenGamma(
cristy4c08aed2011-07-01 19:47:50 +00006290 GetPixelGreen(canvas,p)));
cristyccf844f2010-02-03 23:28:16 +00006291 *q++=ScaleQuantumToChar(XRedGamma(
cristy4c08aed2011-07-01 19:47:50 +00006292 GetPixelRed(canvas,p)));
cristy3ed852e2009-09-05 21:47:34 +00006293 *q++=0;
cristyed231572011-07-14 02:18:59 +00006294 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00006295 }
6296 continue;
6297 }
6298 for (x=(int) canvas->columns-1; x >= 0; x--)
6299 {
cristy4c08aed2011-07-01 19:47:50 +00006300 *q++=ScaleQuantumToChar((Quantum)
6301 GetPixelBlue(canvas,p));
6302 *q++=ScaleQuantumToChar((Quantum)
6303 GetPixelGreen(canvas,p));
6304 *q++=ScaleQuantumToChar((Quantum)
6305 GetPixelRed(canvas,p));
cristy3ed852e2009-09-05 21:47:34 +00006306 *q++=0;
cristyed231572011-07-14 02:18:59 +00006307 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00006308 }
6309 }
6310 }
6311 else
6312 if ((ximage->bits_per_pixel == 32) && (map_info->red_max == 255) &&
6313 (map_info->green_max == 255) && (map_info->blue_max == 255) &&
6314 (map_info->red_mult == 1) && (map_info->green_mult == 256) &&
6315 (map_info->blue_mult == 65536L))
6316 {
6317 /*
6318 Convert to 32 bit continuous-tone X canvas.
6319 */
6320 for (y=0; y < (int) canvas->rows; y++)
6321 {
cristyc57f6942010-11-12 01:47:39 +00006322 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
6323 canvas->columns,1,&canvas->exception);
cristy4c08aed2011-07-01 19:47:50 +00006324 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00006325 break;
6326 if ((red_gamma != 1.0) || (green_gamma != 1.0) ||
6327 (blue_gamma != 1.0))
6328 {
6329 /*
6330 Gamma correct canvas.
6331 */
6332 for (x=(int) canvas->columns-1; x >= 0; x--)
6333 {
cristyccf844f2010-02-03 23:28:16 +00006334 *q++=ScaleQuantumToChar(XRedGamma(
cristy4c08aed2011-07-01 19:47:50 +00006335 GetPixelRed(canvas,p)));
cristyccf844f2010-02-03 23:28:16 +00006336 *q++=ScaleQuantumToChar(XGreenGamma(
cristy4c08aed2011-07-01 19:47:50 +00006337 GetPixelGreen(canvas,p)));
cristyccf844f2010-02-03 23:28:16 +00006338 *q++=ScaleQuantumToChar(XBlueGamma(
cristy4c08aed2011-07-01 19:47:50 +00006339 GetPixelBlue(canvas,p)));
cristy3ed852e2009-09-05 21:47:34 +00006340 *q++=0;
cristyed231572011-07-14 02:18:59 +00006341 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00006342 }
6343 continue;
6344 }
6345 for (x=(int) canvas->columns-1; x >= 0; x--)
6346 {
cristyccf844f2010-02-03 23:28:16 +00006347 *q++=ScaleQuantumToChar((Quantum)
cristy4c08aed2011-07-01 19:47:50 +00006348 GetPixelRed(canvas,p));
cristyccf844f2010-02-03 23:28:16 +00006349 *q++=ScaleQuantumToChar((Quantum)
cristy4c08aed2011-07-01 19:47:50 +00006350 GetPixelGreen(canvas,p));
cristyccf844f2010-02-03 23:28:16 +00006351 *q++=ScaleQuantumToChar((Quantum)
cristy4c08aed2011-07-01 19:47:50 +00006352 GetPixelBlue(canvas,p));
cristy3ed852e2009-09-05 21:47:34 +00006353 *q++=0;
cristyed231572011-07-14 02:18:59 +00006354 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00006355 }
6356 }
6357 }
6358 else
6359 {
6360 register int
6361 k;
6362
6363 register unsigned int
6364 bytes_per_pixel;
6365
6366 unsigned char
cristybb503372010-05-27 20:51:26 +00006367 channel[sizeof(size_t)];
cristy3ed852e2009-09-05 21:47:34 +00006368
6369 /*
6370 Convert to multi-byte continuous-tone X canvas.
6371 */
6372 bytes_per_pixel=(unsigned int) (ximage->bits_per_pixel >> 3);
6373 for (y=0; y < (int) canvas->rows; y++)
6374 {
cristyc57f6942010-11-12 01:47:39 +00006375 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
6376 canvas->columns,1,&canvas->exception);
cristy4c08aed2011-07-01 19:47:50 +00006377 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00006378 break;
cristyc57f6942010-11-12 01:47:39 +00006379 for (x=0; x < (int) canvas->columns; x++)
cristy3ed852e2009-09-05 21:47:34 +00006380 {
cristy4c08aed2011-07-01 19:47:50 +00006381 pixel=XGammaPixel(canvas,map_info,p);
cristy3ed852e2009-09-05 21:47:34 +00006382 for (k=0; k < (int) bytes_per_pixel; k++)
6383 {
6384 channel[k]=(unsigned char) pixel;
6385 pixel>>=8;
6386 }
6387 for (k=0; k < (int) bytes_per_pixel; k++)
6388 *q++=channel[k];
cristyed231572011-07-14 02:18:59 +00006389 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00006390 }
6391 q+=scanline_pad;
6392 }
6393 }
6394 break;
6395 }
6396 }
6397 if (matte_image != (XImage *) NULL)
6398 {
6399 /*
6400 Initialize matte canvas.
6401 */
6402 scanline_pad=(unsigned int) (matte_image->bytes_per_line-
6403 ((matte_image->width*matte_image->bits_per_pixel) >> 3));
6404 q=(unsigned char *) matte_image->data;
6405 for (y=0; y < (int) canvas->rows; y++)
6406 {
cristyc57f6942010-11-12 01:47:39 +00006407 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,canvas->columns,1,
6408 &canvas->exception);
cristy4c08aed2011-07-01 19:47:50 +00006409 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00006410 break;
6411 bit=0;
6412 byte=0;
6413 for (x=(int) canvas->columns-1; x >= 0; x--)
6414 {
6415 byte>>=1;
cristy4c08aed2011-07-01 19:47:50 +00006416 if (GetPixelAlpha(canvas,p) > (QuantumRange/2))
cristy3ed852e2009-09-05 21:47:34 +00006417 byte|=0x80;
6418 bit++;
6419 if (bit == 8)
6420 {
6421 *q++=byte;
6422 bit=0;
6423 byte=0;
6424 }
cristyed231572011-07-14 02:18:59 +00006425 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00006426 }
6427 if (bit != 0)
6428 *q=byte >> (8-bit);
6429 q+=scanline_pad;
6430 }
6431 }
cristyc57f6942010-11-12 01:47:39 +00006432 canvas_view=DestroyCacheView(canvas_view);
cristy3ed852e2009-09-05 21:47:34 +00006433 if (canvas != image)
6434 canvas=DestroyImage(canvas);
6435}
6436
6437/*
6438%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
6439% %
6440% %
6441% %
6442+ X M a k e I m a g e M S B F i r s t %
6443% %
6444% %
6445% %
6446%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
6447%
6448% XMakeImageMSBFirst() initializes the pixel data of an X11 Image. The X
6449% image pixels are copied in most-significant bit and byte first order. The
6450% server's scanline pad is also respected. Rather than using one or two
6451% general cases, many special cases are found here to help speed up the image
6452% conversion.
6453%
6454% The format of the XMakeImageMSBFirst method is:
6455%
6456% XMakeImageMSBFirst(resource_info,window,image,ximage,matte_image)
6457%
6458% A description of each parameter follows:
6459%
6460% o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
6461%
6462% o window: Specifies a pointer to a XWindowInfo structure.
6463%
6464% o image: the image.
6465%
6466% o ximage: Specifies a pointer to a XImage structure; returned from
6467% XCreateImage.
6468%
6469% o matte_image: Specifies a pointer to a XImage structure; returned from
6470% XCreateImage.
6471%
cristy3ed852e2009-09-05 21:47:34 +00006472*/
6473static void XMakeImageMSBFirst(const XResourceInfo *resource_info,
6474 const XWindowInfo *window,Image *image,XImage *ximage,XImage *matte_image)
6475{
cristyc57f6942010-11-12 01:47:39 +00006476 CacheView
6477 *canvas_view;
6478
cristy3ed852e2009-09-05 21:47:34 +00006479 Image
6480 *canvas;
6481
6482 int
6483 y;
6484
6485 register int
6486 x;
6487
cristy4c08aed2011-07-01 19:47:50 +00006488 register const Quantum
cristy3ed852e2009-09-05 21:47:34 +00006489 *p;
6490
6491 register unsigned char
6492 *q;
6493
6494 unsigned char
6495 bit,
6496 byte;
6497
6498 unsigned int
6499 scanline_pad;
6500
cristyf2faecf2010-05-28 19:19:36 +00006501 unsigned long
cristy3ed852e2009-09-05 21:47:34 +00006502 pixel,
6503 *pixels;
6504
6505 XStandardColormap
6506 *map_info;
6507
6508 assert(resource_info != (XResourceInfo *) NULL);
6509 assert(window != (XWindowInfo *) NULL);
6510 assert(image != (Image *) NULL);
6511 if (image->debug != MagickFalse)
6512 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
6513 canvas=image;
cristy54666e82010-02-03 23:34:26 +00006514 if ((window->immutable != MagickFalse) &&
6515 (image->storage_class == DirectClass) && (image->matte != MagickFalse))
cristy3ed852e2009-09-05 21:47:34 +00006516 {
6517 char
6518 size[MaxTextExtent];
6519
6520 Image
6521 *pattern;
6522
6523 ImageInfo
6524 *image_info;
6525
6526 image_info=AcquireImageInfo();
6527 (void) CopyMagickString(image_info->filename,
6528 resource_info->image_info->texture != (char *) NULL ?
6529 resource_info->image_info->texture : "pattern:checkerboard",
6530 MaxTextExtent);
cristyb51dff52011-05-19 16:55:47 +00006531 (void) FormatLocaleString(size,MaxTextExtent,"%.20gx%.20g",(double)
cristye8c25f92010-06-03 00:53:06 +00006532 image->columns,(double) image->rows);
cristy3ed852e2009-09-05 21:47:34 +00006533 image_info->size=ConstantString(size);
6534 pattern=ReadImage(image_info,&image->exception);
6535 image_info=DestroyImageInfo(image_info);
6536 if (pattern != (Image *) NULL)
6537 {
6538 canvas=CloneImage(image,0,0,MagickTrue,&image->exception);
6539 if (canvas != (Image *) NULL)
6540 (void) CompositeImage(canvas,DstOverCompositeOp,pattern,0,0);
6541 pattern=DestroyImage(pattern);
6542 }
6543 }
cristy4c08aed2011-07-01 19:47:50 +00006544 scanline_pad=(unsigned int) (ximage->bytes_per_line-((ximage->width*
6545 ximage->bits_per_pixel) >> 3));
cristy3ed852e2009-09-05 21:47:34 +00006546 map_info=window->map_info;
6547 pixels=window->pixel_info->pixels;
6548 q=(unsigned char *) ximage->data;
6549 x=0;
cristyc57f6942010-11-12 01:47:39 +00006550 canvas_view=AcquireCacheView(canvas);
cristy3ed852e2009-09-05 21:47:34 +00006551 if (ximage->format == XYBitmap)
6552 {
6553 register unsigned short
6554 polarity;
6555
6556 unsigned char
6557 background,
6558 foreground;
6559
6560 /*
6561 Convert canvas to big-endian bitmap.
6562 */
6563 background=(unsigned char)
6564 (XPixelIntensity(&window->pixel_info->foreground_color) <
6565 XPixelIntensity(&window->pixel_info->background_color) ? 0x01 : 0x00);
6566 foreground=(unsigned char)
6567 (XPixelIntensity(&window->pixel_info->background_color) <
6568 XPixelIntensity(&window->pixel_info->foreground_color) ? 0x01 : 0x00);
cristy4c08aed2011-07-01 19:47:50 +00006569 polarity=(unsigned short) ((GetPixelPacketIntensity(
cristy3ed852e2009-09-05 21:47:34 +00006570 &canvas->colormap[0])) < ((Quantum) QuantumRange/2) ? 1 : 0);
6571 if (canvas->colors == 2)
cristy4c08aed2011-07-01 19:47:50 +00006572 polarity=GetPixelPacketIntensity(&canvas->colormap[0]) <
6573 GetPixelPacketIntensity(&canvas->colormap[1]);
cristy3ed852e2009-09-05 21:47:34 +00006574 for (y=0; y < (int) canvas->rows; y++)
6575 {
cristyc57f6942010-11-12 01:47:39 +00006576 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,canvas->columns,1,
6577 &canvas->exception);
cristy4c08aed2011-07-01 19:47:50 +00006578 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00006579 break;
cristy3ed852e2009-09-05 21:47:34 +00006580 bit=0;
6581 byte=0;
6582 for (x=(int) canvas->columns-1; x >= 0; x--)
6583 {
6584 byte<<=1;
cristy4c08aed2011-07-01 19:47:50 +00006585 if (GetPixelIndex(canvas,p) == (Quantum) polarity)
cristy3ed852e2009-09-05 21:47:34 +00006586 byte|=foreground;
6587 else
6588 byte|=background;
6589 bit++;
6590 if (bit == 8)
6591 {
6592 *q++=byte;
6593 bit=0;
6594 byte=0;
6595 }
cristyed231572011-07-14 02:18:59 +00006596 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00006597 }
6598 if (bit != 0)
6599 *q=byte << (8-bit);
6600 q+=scanline_pad;
6601 }
6602 }
6603 else
6604 if (window->pixel_info->colors != 0)
6605 switch (ximage->bits_per_pixel)
6606 {
6607 case 2:
6608 {
6609 register unsigned int
6610 nibble;
6611
6612 /*
6613 Convert to 2 bit color-mapped X canvas.
6614 */
6615 for (y=0; y < (int) canvas->rows; y++)
6616 {
cristyc57f6942010-11-12 01:47:39 +00006617 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
6618 canvas->columns,1,&canvas->exception);
cristy4c08aed2011-07-01 19:47:50 +00006619 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00006620 break;
cristy3ed852e2009-09-05 21:47:34 +00006621 nibble=0;
6622 for (x=0; x < (int) canvas->columns; x++)
6623 {
cristy4c08aed2011-07-01 19:47:50 +00006624 pixel=pixels[(ssize_t)
6625 GetPixelIndex(canvas,p)] & 0xf;
cristy3ed852e2009-09-05 21:47:34 +00006626 switch (nibble)
6627 {
6628 case 0:
6629 {
6630 *q=(unsigned char) (pixel << 6);
6631 nibble++;
6632 break;
6633 }
6634 case 1:
6635 {
6636 *q|=(unsigned char) (pixel << 4);
6637 nibble++;
6638 break;
6639 }
6640 case 2:
6641 {
6642 *q|=(unsigned char) (pixel << 2);
6643 nibble++;
6644 break;
6645 }
6646 case 3:
6647 {
6648 *q|=(unsigned char) pixel;
6649 q++;
6650 nibble=0;
6651 break;
6652 }
6653 }
cristyed231572011-07-14 02:18:59 +00006654 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00006655 }
6656 q+=scanline_pad;
6657 }
6658 break;
6659 }
6660 case 4:
6661 {
6662 register unsigned int
6663 nibble;
6664
6665 /*
6666 Convert to 4 bit color-mapped X canvas.
6667 */
6668 for (y=0; y < (int) canvas->rows; y++)
6669 {
cristyc57f6942010-11-12 01:47:39 +00006670 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
6671 canvas->columns,1,&canvas->exception);
cristy4c08aed2011-07-01 19:47:50 +00006672 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00006673 break;
cristy3ed852e2009-09-05 21:47:34 +00006674 nibble=0;
6675 for (x=0; x < (int) canvas->columns; x++)
6676 {
cristy4c08aed2011-07-01 19:47:50 +00006677 pixel=pixels[(ssize_t)
6678 GetPixelIndex(canvas,p)] & 0xf;
cristy3ed852e2009-09-05 21:47:34 +00006679 switch (nibble)
6680 {
6681 case 0:
6682 {
6683 *q=(unsigned char) (pixel << 4);
6684 nibble++;
6685 break;
6686 }
6687 case 1:
6688 {
6689 *q|=(unsigned char) pixel;
6690 q++;
6691 nibble=0;
6692 break;
6693 }
6694 }
cristyed231572011-07-14 02:18:59 +00006695 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00006696 }
6697 q+=scanline_pad;
6698 }
6699 break;
6700 }
6701 case 6:
6702 case 8:
6703 {
6704 /*
6705 Convert to 8 bit color-mapped X canvas.
6706 */
6707 if (resource_info->color_recovery &&
6708 resource_info->quantize_info->dither)
6709 {
6710 XDitherImage(canvas,ximage);
6711 break;
6712 }
6713 for (y=0; y < (int) canvas->rows; y++)
6714 {
cristyc57f6942010-11-12 01:47:39 +00006715 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
6716 canvas->columns,1,&canvas->exception);
cristy4c08aed2011-07-01 19:47:50 +00006717 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00006718 break;
cristy3ed852e2009-09-05 21:47:34 +00006719 for (x=0; x < (int) canvas->columns; x++)
6720 {
cristy4c08aed2011-07-01 19:47:50 +00006721 pixel=pixels[(ssize_t)
6722 GetPixelIndex(canvas,p)];
cristy3ed852e2009-09-05 21:47:34 +00006723 *q++=(unsigned char) pixel;
cristyed231572011-07-14 02:18:59 +00006724 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00006725 }
6726 q+=scanline_pad;
6727 }
6728 break;
6729 }
6730 default:
6731 {
6732 register int
6733 k;
6734
6735 register unsigned int
6736 bytes_per_pixel;
6737
6738 unsigned char
cristybb503372010-05-27 20:51:26 +00006739 channel[sizeof(size_t)];
cristy3ed852e2009-09-05 21:47:34 +00006740
6741 /*
6742 Convert to 8 bit color-mapped X canvas.
6743 */
6744 bytes_per_pixel=(unsigned int) (ximage->bits_per_pixel >> 3);
6745 for (y=0; y < (int) canvas->rows; y++)
6746 {
cristyc57f6942010-11-12 01:47:39 +00006747 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
6748 canvas->columns,1,&canvas->exception);
cristy4c08aed2011-07-01 19:47:50 +00006749 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00006750 break;
cristy3ed852e2009-09-05 21:47:34 +00006751 for (x=0; x < (int) canvas->columns; x++)
6752 {
cristy4c08aed2011-07-01 19:47:50 +00006753 pixel=pixels[(ssize_t)
6754 GetPixelIndex(canvas,p)];
cristy3ed852e2009-09-05 21:47:34 +00006755 for (k=(int) bytes_per_pixel-1; k >= 0; k--)
6756 {
6757 channel[k]=(unsigned char) pixel;
6758 pixel>>=8;
6759 }
6760 for (k=0; k < (int) bytes_per_pixel; k++)
6761 *q++=channel[k];
cristyed231572011-07-14 02:18:59 +00006762 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00006763 }
6764 q+=scanline_pad;
6765 }
6766 break;
6767 }
6768 }
6769 else
6770 switch (ximage->bits_per_pixel)
6771 {
6772 case 2:
6773 {
6774 register unsigned int
6775 nibble;
6776
6777 /*
6778 Convert to 4 bit continuous-tone X canvas.
6779 */
6780 for (y=0; y < (int) canvas->rows; y++)
6781 {
cristyc57f6942010-11-12 01:47:39 +00006782 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
6783 canvas->columns,1,&canvas->exception);
cristy4c08aed2011-07-01 19:47:50 +00006784 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00006785 break;
6786 nibble=0;
6787 for (x=(int) canvas->columns-1; x >= 0; x--)
6788 {
cristy4c08aed2011-07-01 19:47:50 +00006789 pixel=XGammaPixel(canvas,map_info,p);
cristy3ed852e2009-09-05 21:47:34 +00006790 pixel&=0xf;
6791 switch (nibble)
6792 {
6793 case 0:
6794 {
6795 *q=(unsigned char) (pixel << 6);
6796 nibble++;
6797 break;
6798 }
6799 case 1:
6800 {
6801 *q|=(unsigned char) (pixel << 4);
6802 nibble++;
6803 break;
6804 }
6805 case 2:
6806 {
6807 *q|=(unsigned char) (pixel << 2);
6808 nibble++;
6809 break;
6810 }
6811 case 3:
6812 {
6813 *q|=(unsigned char) pixel;
6814 q++;
6815 nibble=0;
6816 break;
6817 }
6818 }
cristyed231572011-07-14 02:18:59 +00006819 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00006820 }
6821 q+=scanline_pad;
6822 }
6823 break;
6824 }
6825 case 4:
6826 {
6827 register unsigned int
6828 nibble;
6829
6830 /*
6831 Convert to 4 bit continuous-tone X canvas.
6832 */
6833 for (y=0; y < (int) canvas->rows; y++)
6834 {
cristyc57f6942010-11-12 01:47:39 +00006835 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
6836 canvas->columns,1,&canvas->exception);
cristy4c08aed2011-07-01 19:47:50 +00006837 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00006838 break;
6839 nibble=0;
6840 for (x=(int) canvas->columns-1; x >= 0; x--)
6841 {
cristy4c08aed2011-07-01 19:47:50 +00006842 pixel=XGammaPixel(canvas,map_info,p);
cristy3ed852e2009-09-05 21:47:34 +00006843 pixel&=0xf;
6844 switch (nibble)
6845 {
6846 case 0:
6847 {
6848 *q=(unsigned char) (pixel << 4);
6849 nibble++;
6850 break;
6851 }
6852 case 1:
6853 {
6854 *q|=(unsigned char) pixel;
6855 q++;
6856 nibble=0;
6857 break;
6858 }
6859 }
cristyed231572011-07-14 02:18:59 +00006860 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00006861 }
6862 q+=scanline_pad;
6863 }
6864 break;
6865 }
6866 case 6:
6867 case 8:
6868 {
6869 /*
6870 Convert to 8 bit continuous-tone X canvas.
6871 */
6872 if (resource_info->color_recovery &&
6873 resource_info->quantize_info->dither)
6874 {
6875 XDitherImage(canvas,ximage);
6876 break;
6877 }
6878 for (y=0; y < (int) canvas->rows; y++)
6879 {
cristyc57f6942010-11-12 01:47:39 +00006880 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
6881 canvas->columns,1,&canvas->exception);
cristy4c08aed2011-07-01 19:47:50 +00006882 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00006883 break;
6884 for (x=(int) canvas->columns-1; x >= 0; x--)
6885 {
cristy4c08aed2011-07-01 19:47:50 +00006886 pixel=XGammaPixel(canvas,map_info,p);
cristy3ed852e2009-09-05 21:47:34 +00006887 *q++=(unsigned char) pixel;
cristyed231572011-07-14 02:18:59 +00006888 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00006889 }
6890 q+=scanline_pad;
6891 }
6892 break;
6893 }
6894 default:
6895 {
6896 if ((ximage->bits_per_pixel == 32) && (map_info->red_max == 255) &&
6897 (map_info->green_max == 255) && (map_info->blue_max == 255) &&
6898 (map_info->red_mult == 65536L) && (map_info->green_mult == 256) &&
6899 (map_info->blue_mult == 1))
6900 {
6901 /*
6902 Convert to 32 bit continuous-tone X canvas.
6903 */
6904 for (y=0; y < (int) canvas->rows; y++)
6905 {
cristyc57f6942010-11-12 01:47:39 +00006906 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
6907 canvas->columns,1,&canvas->exception);
cristy4c08aed2011-07-01 19:47:50 +00006908 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00006909 break;
6910 if ((red_gamma != 1.0) || (green_gamma != 1.0) ||
6911 (blue_gamma != 1.0))
6912 {
6913 /*
6914 Gamma correct canvas.
6915 */
6916 for (x=(int) canvas->columns-1; x >= 0; x--)
6917 {
6918 *q++=0;
cristyccf844f2010-02-03 23:28:16 +00006919 *q++=ScaleQuantumToChar(XRedGamma(
cristy4c08aed2011-07-01 19:47:50 +00006920 GetPixelRed(canvas,p)));
cristyccf844f2010-02-03 23:28:16 +00006921 *q++=ScaleQuantumToChar(XGreenGamma(
cristy4c08aed2011-07-01 19:47:50 +00006922 GetPixelGreen(canvas,p)));
cristyccf844f2010-02-03 23:28:16 +00006923 *q++=ScaleQuantumToChar(XBlueGamma(
cristy4c08aed2011-07-01 19:47:50 +00006924 GetPixelBlue(canvas,p)));
cristyed231572011-07-14 02:18:59 +00006925 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00006926 }
6927 continue;
6928 }
6929 for (x=(int) canvas->columns-1; x >= 0; x--)
6930 {
6931 *q++=0;
cristy4c08aed2011-07-01 19:47:50 +00006932 *q++=ScaleQuantumToChar((Quantum)
6933 GetPixelRed(canvas,p));
6934 *q++=ScaleQuantumToChar((Quantum)
6935 GetPixelGreen(canvas,p));
6936 *q++=ScaleQuantumToChar((Quantum)
6937 GetPixelBlue(canvas,p));
cristyed231572011-07-14 02:18:59 +00006938 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00006939 }
6940 }
6941 }
6942 else
6943 if ((ximage->bits_per_pixel == 32) && (map_info->red_max == 255) &&
6944 (map_info->green_max == 255) && (map_info->blue_max == 255) &&
6945 (map_info->red_mult == 1) && (map_info->green_mult == 256) &&
6946 (map_info->blue_mult == 65536L))
6947 {
6948 /*
6949 Convert to 32 bit continuous-tone X canvas.
6950 */
6951 for (y=0; y < (int) canvas->rows; y++)
6952 {
cristyc57f6942010-11-12 01:47:39 +00006953 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
6954 canvas->columns,1,&canvas->exception);
cristy4c08aed2011-07-01 19:47:50 +00006955 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00006956 break;
6957 if ((red_gamma != 1.0) || (green_gamma != 1.0) ||
6958 (blue_gamma != 1.0))
6959 {
6960 /*
6961 Gamma correct canvas.
6962 */
6963 for (x=(int) canvas->columns-1; x >= 0; x--)
6964 {
6965 *q++=0;
cristyccf844f2010-02-03 23:28:16 +00006966 *q++=ScaleQuantumToChar(XBlueGamma(
cristy4c08aed2011-07-01 19:47:50 +00006967 GetPixelBlue(canvas,p)));
cristyccf844f2010-02-03 23:28:16 +00006968 *q++=ScaleQuantumToChar(XGreenGamma(
cristy4c08aed2011-07-01 19:47:50 +00006969 GetPixelGreen(canvas,p)));
cristyccf844f2010-02-03 23:28:16 +00006970 *q++=ScaleQuantumToChar(XRedGamma(
cristy4c08aed2011-07-01 19:47:50 +00006971 GetPixelRed(canvas,p)));
cristyed231572011-07-14 02:18:59 +00006972 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00006973 }
6974 continue;
6975 }
6976 for (x=(int) canvas->columns-1; x >= 0; x--)
6977 {
6978 *q++=0;
cristyccf844f2010-02-03 23:28:16 +00006979 *q++=ScaleQuantumToChar((Quantum)
cristy4c08aed2011-07-01 19:47:50 +00006980 GetPixelBlue(canvas,p));
cristyccf844f2010-02-03 23:28:16 +00006981 *q++=ScaleQuantumToChar((Quantum)
cristy4c08aed2011-07-01 19:47:50 +00006982 GetPixelGreen(canvas,p));
cristyccf844f2010-02-03 23:28:16 +00006983 *q++=ScaleQuantumToChar((Quantum)
cristy4c08aed2011-07-01 19:47:50 +00006984 GetPixelRed(canvas,p));
cristyed231572011-07-14 02:18:59 +00006985 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00006986 }
6987 }
6988 }
6989 else
6990 {
6991 register int
6992 k;
6993
6994 register unsigned int
6995 bytes_per_pixel;
6996
6997 unsigned char
cristybb503372010-05-27 20:51:26 +00006998 channel[sizeof(size_t)];
cristy3ed852e2009-09-05 21:47:34 +00006999
7000 /*
7001 Convert to multi-byte continuous-tone X canvas.
7002 */
7003 bytes_per_pixel=(unsigned int) (ximage->bits_per_pixel >> 3);
7004 for (y=0; y < (int) canvas->rows; y++)
7005 {
cristyc57f6942010-11-12 01:47:39 +00007006 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
7007 canvas->columns,1,&canvas->exception);
cristy4c08aed2011-07-01 19:47:50 +00007008 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00007009 break;
7010 for (x=(int) canvas->columns-1; x >= 0; x--)
7011 {
cristy4c08aed2011-07-01 19:47:50 +00007012 pixel=XGammaPixel(canvas,map_info,p);
cristy3ed852e2009-09-05 21:47:34 +00007013 for (k=(int) bytes_per_pixel-1; k >= 0; k--)
7014 {
7015 channel[k]=(unsigned char) pixel;
7016 pixel>>=8;
7017 }
7018 for (k=0; k < (int) bytes_per_pixel; k++)
7019 *q++=channel[k];
cristyed231572011-07-14 02:18:59 +00007020 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00007021 }
7022 q+=scanline_pad;
7023 }
7024 }
7025 break;
7026 }
7027 }
7028 if (matte_image != (XImage *) NULL)
7029 {
7030 /*
7031 Initialize matte canvas.
7032 */
7033 scanline_pad=(unsigned int) (matte_image->bytes_per_line-
7034 ((matte_image->width*matte_image->bits_per_pixel) >> 3));
7035 q=(unsigned char *) matte_image->data;
7036 for (y=0; y < (int) canvas->rows; y++)
7037 {
cristyc57f6942010-11-12 01:47:39 +00007038 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,canvas->columns,1,
7039 &canvas->exception);
cristy4c08aed2011-07-01 19:47:50 +00007040 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00007041 break;
7042 bit=0;
7043 byte=0;
7044 for (x=(int) canvas->columns-1; x >= 0; x--)
7045 {
7046 byte<<=1;
cristy4c08aed2011-07-01 19:47:50 +00007047 if (GetPixelAlpha(canvas,p) > (QuantumRange/2))
cristy3ed852e2009-09-05 21:47:34 +00007048 byte|=0x01;
7049 bit++;
7050 if (bit == 8)
7051 {
7052 *q++=byte;
7053 bit=0;
7054 byte=0;
7055 }
cristyed231572011-07-14 02:18:59 +00007056 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00007057 }
7058 if (bit != 0)
7059 *q=byte << (8-bit);
7060 q+=scanline_pad;
7061 }
7062 }
cristyc57f6942010-11-12 01:47:39 +00007063 canvas_view=DestroyCacheView(canvas_view);
cristy3ed852e2009-09-05 21:47:34 +00007064 if (canvas != image)
7065 canvas=DestroyImage(canvas);
7066}
7067
7068/*
7069%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
7070% %
7071% %
7072% %
7073% X M a k e M a g n i f y I m a g e %
7074% %
7075% %
7076% %
7077%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
7078%
7079% XMakeMagnifyImage() magnifies a region of an X image and displays it.
7080%
7081% The format of the XMakeMagnifyImage method is:
7082%
7083% void XMakeMagnifyImage(display,windows)
7084%
7085% A description of each parameter follows:
7086%
7087% o display: Specifies a connection to an X server; returned from
7088% XOpenDisplay.
7089%
7090% o windows: Specifies a pointer to a XWindows structure.
7091%
7092*/
cristybcbda3f2011-09-03 13:01:22 +00007093MagickPrivate void XMakeMagnifyImage(Display *display,XWindows *windows)
cristy3ed852e2009-09-05 21:47:34 +00007094{
7095 char
7096 tuple[MaxTextExtent];
7097
7098 int
7099 y;
7100
cristy4c08aed2011-07-01 19:47:50 +00007101 PixelInfo
cristy3ed852e2009-09-05 21:47:34 +00007102 pixel;
7103
7104 register int
7105 x;
7106
cristybb503372010-05-27 20:51:26 +00007107 register ssize_t
cristy3ed852e2009-09-05 21:47:34 +00007108 i;
7109
7110 register unsigned char
7111 *p,
7112 *q;
7113
cristy9d314ff2011-03-09 01:30:28 +00007114 ssize_t
7115 n;
7116
cristy3ed852e2009-09-05 21:47:34 +00007117 static unsigned int
7118 previous_magnify = 0;
7119
7120 static XWindowInfo
7121 magnify_window;
7122
7123 unsigned int
7124 height,
7125 j,
7126 k,
7127 l,
7128 magnify,
7129 scanline_pad,
7130 width;
7131
7132 XImage
7133 *ximage;
7134
7135 /*
7136 Check boundary conditions.
7137 */
7138 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
7139 assert(display != (Display *) NULL);
7140 assert(windows != (XWindows *) NULL);
7141 magnify=1;
cristybb503372010-05-27 20:51:26 +00007142 for (n=1; n < (ssize_t) windows->magnify.data; n++)
cristy3ed852e2009-09-05 21:47:34 +00007143 magnify<<=1;
7144 while ((magnify*windows->image.ximage->width) < windows->magnify.width)
7145 magnify<<=1;
7146 while ((magnify*windows->image.ximage->height) < windows->magnify.height)
7147 magnify<<=1;
7148 while (magnify > windows->magnify.width)
7149 magnify>>=1;
7150 while (magnify > windows->magnify.height)
7151 magnify>>=1;
7152 if (magnify != previous_magnify)
7153 {
7154 Status
7155 status;
7156
7157 XTextProperty
7158 window_name;
7159
7160 /*
7161 New magnify factor: update magnify window name.
7162 */
7163 i=0;
7164 while ((1 << i) <= (int) magnify)
7165 i++;
cristyb51dff52011-05-19 16:55:47 +00007166 (void) FormatLocaleString(windows->magnify.name,MaxTextExtent,
cristye8c25f92010-06-03 00:53:06 +00007167 "Magnify %.20gX",(double) i);
cristy3ed852e2009-09-05 21:47:34 +00007168 status=XStringListToTextProperty(&windows->magnify.name,1,&window_name);
7169 if (status != False)
7170 {
7171 XSetWMName(display,windows->magnify.id,&window_name);
7172 XSetWMIconName(display,windows->magnify.id,&window_name);
7173 (void) XFree((void *) window_name.value);
7174 }
7175 }
7176 previous_magnify=magnify;
7177 ximage=windows->image.ximage;
7178 width=(unsigned int) windows->magnify.ximage->width;
7179 height=(unsigned int) windows->magnify.ximage->height;
7180 if ((windows->magnify.x < 0) ||
7181 (windows->magnify.x >= windows->image.ximage->width))
7182 windows->magnify.x=windows->image.ximage->width >> 1;
7183 x=windows->magnify.x-((width/magnify) >> 1);
7184 if (x < 0)
7185 x=0;
7186 else
7187 if (x > (int) (ximage->width-(width/magnify)))
7188 x=ximage->width-width/magnify;
7189 if ((windows->magnify.y < 0) ||
7190 (windows->magnify.y >= windows->image.ximage->height))
7191 windows->magnify.y=windows->image.ximage->height >> 1;
7192 y=windows->magnify.y-((height/magnify) >> 1);
7193 if (y < 0)
7194 y=0;
7195 else
7196 if (y > (int) (ximage->height-(height/magnify)))
7197 y=ximage->height-height/magnify;
7198 q=(unsigned char *) windows->magnify.ximage->data;
7199 scanline_pad=(unsigned int) (windows->magnify.ximage->bytes_per_line-
7200 ((width*windows->magnify.ximage->bits_per_pixel) >> 3));
7201 if (ximage->bits_per_pixel < 8)
7202 {
7203 register unsigned char
7204 background,
7205 byte,
7206 foreground,
7207 p_bit,
7208 q_bit;
7209
7210 register unsigned int
7211 plane;
7212
7213 XPixelInfo
7214 *pixel_info;
7215
7216 pixel_info=windows->magnify.pixel_info;
7217 switch (ximage->bitmap_bit_order)
7218 {
7219 case LSBFirst:
7220 {
7221 /*
7222 Magnify little-endian bitmap.
7223 */
7224 background=0x00;
7225 foreground=0x80;
7226 if (ximage->format == XYBitmap)
7227 {
7228 background=(unsigned char)
7229 (XPixelIntensity(&pixel_info->foreground_color) <
7230 XPixelIntensity(&pixel_info->background_color) ? 0x80 : 0x00);
7231 foreground=(unsigned char)
7232 (XPixelIntensity(&pixel_info->background_color) <
7233 XPixelIntensity(&pixel_info->foreground_color) ? 0x80 : 0x00);
7234 if (windows->magnify.depth > 1)
7235 Swap(background,foreground);
7236 }
cristybb503372010-05-27 20:51:26 +00007237 for (i=0; i < (ssize_t) height; i+=magnify)
cristy3ed852e2009-09-05 21:47:34 +00007238 {
7239 /*
7240 Propogate pixel magnify rows.
7241 */
7242 for (j=0; j < magnify; j++)
7243 {
7244 p=(unsigned char *) ximage->data+y*ximage->bytes_per_line+
7245 ((x*ximage->bits_per_pixel) >> 3);
7246 p_bit=(unsigned char) (x*ximage->bits_per_pixel) & 0x07;
7247 q_bit=0;
7248 byte=0;
7249 for (k=0; k < width; k+=magnify)
7250 {
7251 /*
7252 Propogate pixel magnify columns.
7253 */
7254 for (l=0; l < magnify; l++)
7255 {
7256 /*
7257 Propogate each bit plane.
7258 */
7259 for (plane=0; (int) plane < ximage->bits_per_pixel; plane++)
7260 {
7261 byte>>=1;
7262 if (*p & (0x01 << (p_bit+plane)))
7263 byte|=foreground;
7264 else
7265 byte|=background;
7266 q_bit++;
7267 if (q_bit == 8)
7268 {
7269 *q++=byte;
7270 q_bit=0;
7271 byte=0;
7272 }
7273 }
7274 }
7275 p_bit+=ximage->bits_per_pixel;
7276 if (p_bit == 8)
7277 {
7278 p++;
7279 p_bit=0;
7280 }
7281 if (q_bit != 0)
7282 *q=byte >> (8-q_bit);
7283 q+=scanline_pad;
7284 }
7285 }
7286 y++;
7287 }
7288 break;
7289 }
7290 case MSBFirst:
7291 default:
7292 {
7293 /*
7294 Magnify big-endian bitmap.
7295 */
7296 background=0x00;
7297 foreground=0x01;
7298 if (ximage->format == XYBitmap)
7299 {
7300 background=(unsigned char)
7301 (XPixelIntensity(&pixel_info->foreground_color) <
7302 XPixelIntensity(&pixel_info->background_color) ? 0x01 : 0x00);
7303 foreground=(unsigned char)
7304 (XPixelIntensity(&pixel_info->background_color) <
7305 XPixelIntensity(&pixel_info->foreground_color) ? 0x01 : 0x00);
7306 if (windows->magnify.depth > 1)
7307 Swap(background,foreground);
7308 }
cristybb503372010-05-27 20:51:26 +00007309 for (i=0; i < (ssize_t) height; i+=magnify)
cristy3ed852e2009-09-05 21:47:34 +00007310 {
7311 /*
7312 Propogate pixel magnify rows.
7313 */
7314 for (j=0; j < magnify; j++)
7315 {
7316 p=(unsigned char *) ximage->data+y*ximage->bytes_per_line+
7317 ((x*ximage->bits_per_pixel) >> 3);
7318 p_bit=(unsigned char) (x*ximage->bits_per_pixel) & 0x07;
7319 q_bit=0;
7320 byte=0;
7321 for (k=0; k < width; k+=magnify)
7322 {
7323 /*
7324 Propogate pixel magnify columns.
7325 */
7326 for (l=0; l < magnify; l++)
7327 {
7328 /*
7329 Propogate each bit plane.
7330 */
7331 for (plane=0; (int) plane < ximage->bits_per_pixel; plane++)
7332 {
7333 byte<<=1;
7334 if (*p & (0x80 >> (p_bit+plane)))
7335 byte|=foreground;
7336 else
7337 byte|=background;
7338 q_bit++;
7339 if (q_bit == 8)
7340 {
7341 *q++=byte;
7342 q_bit=0;
7343 byte=0;
7344 }
7345 }
7346 }
7347 p_bit+=ximage->bits_per_pixel;
7348 if (p_bit == 8)
7349 {
7350 p++;
7351 p_bit=0;
7352 }
7353 if (q_bit != 0)
7354 *q=byte << (8-q_bit);
7355 q+=scanline_pad;
7356 }
7357 }
7358 y++;
7359 }
7360 break;
7361 }
7362 }
7363 }
7364 else
7365 switch (ximage->bits_per_pixel)
7366 {
7367 case 6:
7368 case 8:
7369 {
7370 /*
7371 Magnify 8 bit X image.
7372 */
cristybb503372010-05-27 20:51:26 +00007373 for (i=0; i < (ssize_t) height; i+=magnify)
cristy3ed852e2009-09-05 21:47:34 +00007374 {
7375 /*
7376 Propogate pixel magnify rows.
7377 */
7378 for (j=0; j < magnify; j++)
7379 {
7380 p=(unsigned char *) ximage->data+y*ximage->bytes_per_line+
7381 ((x*ximage->bits_per_pixel) >> 3);
7382 for (k=0; k < width; k+=magnify)
7383 {
7384 /*
7385 Propogate pixel magnify columns.
7386 */
7387 for (l=0; l < magnify; l++)
7388 *q++=(*p);
7389 p++;
7390 }
7391 q+=scanline_pad;
7392 }
7393 y++;
7394 }
7395 break;
7396 }
7397 default:
7398 {
7399 register unsigned int
7400 bytes_per_pixel,
7401 m;
7402
7403 /*
7404 Magnify multi-byte X image.
7405 */
7406 bytes_per_pixel=(unsigned int) ximage->bits_per_pixel >> 3;
cristybb503372010-05-27 20:51:26 +00007407 for (i=0; i < (ssize_t) height; i+=magnify)
cristy3ed852e2009-09-05 21:47:34 +00007408 {
7409 /*
7410 Propogate pixel magnify rows.
7411 */
7412 for (j=0; j < magnify; j++)
7413 {
7414 p=(unsigned char *) ximage->data+y*ximage->bytes_per_line+
7415 ((x*ximage->bits_per_pixel) >> 3);
7416 for (k=0; k < width; k+=magnify)
7417 {
7418 /*
7419 Propogate pixel magnify columns.
7420 */
7421 for (l=0; l < magnify; l++)
7422 for (m=0; m < bytes_per_pixel; m++)
7423 *q++=(*(p+m));
7424 p+=bytes_per_pixel;
7425 }
7426 q+=scanline_pad;
7427 }
7428 y++;
7429 }
7430 break;
7431 }
7432 }
7433 /*
7434 Copy X image to magnify pixmap.
7435 */
7436 x=windows->magnify.x-((width/magnify) >> 1);
7437 if (x < 0)
7438 x=(int) ((width >> 1)-windows->magnify.x*magnify);
7439 else
7440 if (x > (int) (ximage->width-(width/magnify)))
7441 x=(int) ((ximage->width-windows->magnify.x)*magnify-(width >> 1));
7442 else
7443 x=0;
7444 y=windows->magnify.y-((height/magnify) >> 1);
7445 if (y < 0)
7446 y=(int) ((height >> 1)-windows->magnify.y*magnify);
7447 else
7448 if (y > (int) (ximage->height-(height/magnify)))
7449 y=(int) ((ximage->height-windows->magnify.y)*magnify-(height >> 1));
7450 else
7451 y=0;
7452 if ((x != 0) || (y != 0))
7453 (void) XFillRectangle(display,windows->magnify.pixmap,
7454 windows->magnify.annotate_context,0,0,width,height);
7455 (void) XPutImage(display,windows->magnify.pixmap,
7456 windows->magnify.annotate_context,windows->magnify.ximage,0,0,x,y,width-x,
7457 height-y);
7458 if ((magnify > 1) && ((magnify <= (width >> 1)) &&
7459 (magnify <= (height >> 1))))
7460 {
7461 RectangleInfo
7462 highlight_info;
7463
7464 /*
7465 Highlight center pixel.
7466 */
cristybb503372010-05-27 20:51:26 +00007467 highlight_info.x=(ssize_t) windows->magnify.width >> 1;
7468 highlight_info.y=(ssize_t) windows->magnify.height >> 1;
cristy3ed852e2009-09-05 21:47:34 +00007469 highlight_info.width=magnify;
7470 highlight_info.height=magnify;
7471 (void) XDrawRectangle(display,windows->magnify.pixmap,
7472 windows->magnify.highlight_context,(int) highlight_info.x,
7473 (int) highlight_info.y,(unsigned int) highlight_info.width-1,
7474 (unsigned int) highlight_info.height-1);
7475 if (magnify > 2)
7476 (void) XDrawRectangle(display,windows->magnify.pixmap,
7477 windows->magnify.annotate_context,(int) highlight_info.x+1,
7478 (int) highlight_info.y+1,(unsigned int) highlight_info.width-3,
7479 (unsigned int) highlight_info.height-3);
7480 }
7481 /*
7482 Show center pixel color.
7483 */
cristyc57f6942010-11-12 01:47:39 +00007484 (void) GetOneVirtualMagickPixel(windows->image.image,(ssize_t)
7485 windows->magnify.x,(ssize_t) windows->magnify.y,&pixel,
7486 &windows->image.image->exception);
cristyb51dff52011-05-19 16:55:47 +00007487 (void) FormatLocaleString(tuple,MaxTextExtent,"%d,%d: ",
cristy3ed852e2009-09-05 21:47:34 +00007488 windows->magnify.x,windows->magnify.y);
7489 (void) ConcatenateMagickString(tuple,"(",MaxTextExtent);
cristyed231572011-07-14 02:18:59 +00007490 ConcatenateColorComponent(&pixel,RedPixelChannel,X11Compliance,tuple);
cristy3ed852e2009-09-05 21:47:34 +00007491 (void) ConcatenateMagickString(tuple,",",MaxTextExtent);
cristyed231572011-07-14 02:18:59 +00007492 ConcatenateColorComponent(&pixel,GreenPixelChannel,X11Compliance,tuple);
cristy3ed852e2009-09-05 21:47:34 +00007493 (void) ConcatenateMagickString(tuple,",",MaxTextExtent);
cristyed231572011-07-14 02:18:59 +00007494 ConcatenateColorComponent(&pixel,BluePixelChannel,X11Compliance,tuple);
cristy3ed852e2009-09-05 21:47:34 +00007495 if (pixel.colorspace == CMYKColorspace)
7496 {
7497 (void) ConcatenateMagickString(tuple,",",MaxTextExtent);
cristyed231572011-07-14 02:18:59 +00007498 ConcatenateColorComponent(&pixel,BlackPixelChannel,X11Compliance,tuple);
cristy3ed852e2009-09-05 21:47:34 +00007499 }
7500 if (pixel.matte != MagickFalse)
7501 {
7502 (void) ConcatenateMagickString(tuple,",",MaxTextExtent);
cristyed231572011-07-14 02:18:59 +00007503 ConcatenateColorComponent(&pixel,AlphaPixelChannel,X11Compliance,tuple);
cristy3ed852e2009-09-05 21:47:34 +00007504 }
7505 (void) ConcatenateMagickString(tuple,")",MaxTextExtent);
7506 height=(unsigned int) windows->magnify.font_info->ascent+
7507 windows->magnify.font_info->descent;
7508 x=windows->magnify.font_info->max_bounds.width >> 1;
7509 y=windows->magnify.font_info->ascent+(height >> 2);
7510 (void) XDrawImageString(display,windows->magnify.pixmap,
7511 windows->magnify.annotate_context,x,y,tuple,(int) strlen(tuple));
7512 GetColorTuple(&pixel,MagickTrue,tuple);
7513 y+=height;
7514 (void) XDrawImageString(display,windows->magnify.pixmap,
7515 windows->magnify.annotate_context,x,y,tuple,(int) strlen(tuple));
7516 (void) QueryMagickColorname(windows->image.image,&pixel,SVGCompliance,tuple,
7517 &windows->image.image->exception);
7518 y+=height;
7519 (void) XDrawImageString(display,windows->magnify.pixmap,
7520 windows->magnify.annotate_context,x,y,tuple,(int) strlen(tuple));
7521 /*
7522 Refresh magnify window.
7523 */
7524 magnify_window=windows->magnify;
7525 magnify_window.x=0;
7526 magnify_window.y=0;
7527 XRefreshWindow(display,&magnify_window,(XEvent *) NULL);
7528}
7529
7530/*
7531%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
7532% %
7533% %
7534% %
7535% X M a k e P i x m a p %
7536% %
7537% %
7538% %
7539%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
7540%
7541% XMakePixmap() creates an X11 pixmap.
7542%
7543% The format of the XMakePixmap method is:
7544%
7545% void XMakeStandardColormap(Display *display,XVisualInfo *visual_info,
7546% XResourceInfo *resource_info,Image *image,XStandardColormap *map_info,
7547% XPixelInfo *pixel)
7548%
7549% A description of each parameter follows:
7550%
7551% o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
7552%
7553% o display: Specifies a connection to an X server; returned from
7554% XOpenDisplay.
7555%
7556% o window: Specifies a pointer to a XWindowInfo structure.
7557%
cristy3ed852e2009-09-05 21:47:34 +00007558*/
7559static MagickBooleanType XMakePixmap(Display *display,
7560 const XResourceInfo *resource_info,XWindowInfo *window)
7561{
7562 unsigned int
7563 height,
7564 width;
7565
7566 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
7567 assert(display != (Display *) NULL);
7568 assert(resource_info != (XResourceInfo *) NULL);
7569 assert(window != (XWindowInfo *) NULL);
7570 if (window->pixmap != (Pixmap) NULL)
7571 {
7572 /*
7573 Destroy previous X pixmap.
7574 */
7575 (void) XFreePixmap(display,window->pixmap);
7576 window->pixmap=(Pixmap) NULL;
7577 }
7578 if (window->use_pixmap == MagickFalse)
7579 return(MagickFalse);
7580 if (window->ximage == (XImage *) NULL)
7581 return(MagickFalse);
7582 /*
7583 Display busy cursor.
7584 */
7585 (void) XCheckDefineCursor(display,window->id,window->busy_cursor);
7586 (void) XFlush(display);
7587 /*
7588 Create pixmap.
7589 */
7590 width=(unsigned int) window->ximage->width;
7591 height=(unsigned int) window->ximage->height;
7592 window->pixmap=XCreatePixmap(display,window->id,width,height,window->depth);
7593 if (window->pixmap == (Pixmap) NULL)
7594 {
7595 /*
7596 Unable to allocate pixmap.
7597 */
7598 (void) XCheckDefineCursor(display,window->id,window->cursor);
7599 return(MagickFalse);
7600 }
7601 /*
7602 Copy X image to pixmap.
7603 */
7604#if defined(MAGICKCORE_HAVE_SHARED_MEMORY)
7605 if (window->shared_memory)
7606 (void) XShmPutImage(display,window->pixmap,window->annotate_context,
7607 window->ximage,0,0,0,0,width,height,MagickTrue);
7608#endif
7609 if (window->shared_memory == MagickFalse)
7610 (void) XPutImage(display,window->pixmap,window->annotate_context,
7611 window->ximage,0,0,0,0,width,height);
7612 if (IsEventLogging())
7613 {
7614 (void) LogMagickEvent(X11Event,GetMagickModule(),"Pixmap:");
7615 (void) LogMagickEvent(X11Event,GetMagickModule()," width, height: %ux%u",
7616 width,height);
7617 }
7618 /*
7619 Restore cursor.
7620 */
7621 (void) XCheckDefineCursor(display,window->id,window->cursor);
7622 return(MagickTrue);
7623}
7624
7625/*
7626%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
7627% %
7628% %
7629% %
7630% X M a k e S t a n d a r d C o l o r m a p %
7631% %
7632% %
7633% %
7634%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
7635%
7636% XMakeStandardColormap() creates an X11 Standard Colormap.
7637%
7638% The format of the XMakeStandardColormap method is:
7639%
7640% XMakeStandardColormap(display,visual_info,resource_info,image,
7641% map_info,pixel)
7642%
7643% A description of each parameter follows:
7644%
7645% o display: Specifies a connection to an X server; returned from
7646% XOpenDisplay.
7647%
7648% o visual_info: Specifies a pointer to a X11 XVisualInfo structure;
7649% returned from XGetVisualInfo.
7650%
7651% o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
7652%
7653% o image: the image.
7654%
7655% o map_info: If a Standard Colormap type is specified, this structure is
7656% initialized with info from the Standard Colormap.
7657%
7658% o pixel: Specifies a pointer to a XPixelInfo structure.
7659%
cristy3ed852e2009-09-05 21:47:34 +00007660*/
7661
7662#if defined(__cplusplus) || defined(c_plusplus)
7663extern "C" {
7664#endif
7665
7666static inline MagickRealType DiversityPixelIntensity(
7667 const DiversityPacket *pixel)
7668{
7669 MagickRealType
7670 intensity;
7671
7672 intensity=0.299*pixel->red+0.587*pixel->green+0.114*pixel->blue;
7673 return(intensity);
7674}
7675
7676static int IntensityCompare(const void *x,const void *y)
7677{
7678 DiversityPacket
7679 *color_1,
7680 *color_2;
7681
7682 int
7683 diversity;
7684
7685 color_1=(DiversityPacket *) x;
7686 color_2=(DiversityPacket *) y;
7687 diversity=(int) (DiversityPixelIntensity(color_2)-
7688 DiversityPixelIntensity(color_1));
7689 return(diversity);
7690}
7691
7692static int PopularityCompare(const void *x,const void *y)
7693{
7694 DiversityPacket
7695 *color_1,
7696 *color_2;
7697
7698 color_1=(DiversityPacket *) x;
7699 color_2=(DiversityPacket *) y;
7700 return((int) color_2->count-(int) color_1->count);
7701}
7702
7703#if defined(__cplusplus) || defined(c_plusplus)
7704}
7705#endif
7706
cristybb503372010-05-27 20:51:26 +00007707static inline Quantum ScaleXToQuantum(const size_t x,
7708 const size_t scale)
cristy3ed852e2009-09-05 21:47:34 +00007709{
7710 return((Quantum) (((MagickRealType) QuantumRange*x)/scale+0.5));
7711}
7712
cristybcbda3f2011-09-03 13:01:22 +00007713MagickPrivate void XMakeStandardColormap(Display *display,
cristy3ed852e2009-09-05 21:47:34 +00007714 XVisualInfo *visual_info,XResourceInfo *resource_info,Image *image,
7715 XStandardColormap *map_info,XPixelInfo *pixel)
7716{
7717 Colormap
7718 colormap;
7719
7720 ExceptionInfo
7721 *exception;
7722
cristybb503372010-05-27 20:51:26 +00007723 register ssize_t
cristy3ed852e2009-09-05 21:47:34 +00007724 i;
7725
7726 Status
7727 status;
7728
cristybb503372010-05-27 20:51:26 +00007729 size_t
cristy3ed852e2009-09-05 21:47:34 +00007730 number_colors,
7731 retain_colors;
7732
7733 unsigned short
7734 gray_value;
7735
7736 XColor
7737 color,
7738 *colors,
7739 *p;
7740
7741 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
7742 assert(display != (Display *) NULL);
7743 assert(visual_info != (XVisualInfo *) NULL);
7744 assert(map_info != (XStandardColormap *) NULL);
7745 assert(resource_info != (XResourceInfo *) NULL);
7746 assert(pixel != (XPixelInfo *) NULL);
7747 exception=(&image->exception);
7748 if (resource_info->map_type != (char *) NULL)
7749 {
7750 /*
7751 Standard Colormap is already defined (i.e. xstdcmap).
7752 */
cristy4c08aed2011-07-01 19:47:50 +00007753 XGetPixelInfo(display,visual_info,map_info,resource_info,image,
cristy3ed852e2009-09-05 21:47:34 +00007754 pixel);
7755 number_colors=(unsigned int) (map_info->base_pixel+
7756 (map_info->red_max+1)*(map_info->green_max+1)*(map_info->blue_max+1));
7757 if ((map_info->red_max*map_info->green_max*map_info->blue_max) != 0)
7758 if ((image->matte == MagickFalse) &&
7759 (resource_info->color_recovery == MagickFalse) &&
7760 resource_info->quantize_info->dither &&
7761 (number_colors < MaxColormapSize))
7762 {
7763 Image
7764 *affinity_image;
7765
cristy4c08aed2011-07-01 19:47:50 +00007766 register Quantum
cristyc47d1f82009-11-26 01:44:43 +00007767 *restrict q;
cristy3ed852e2009-09-05 21:47:34 +00007768
7769 /*
7770 Improve image appearance with error diffusion.
7771 */
7772 affinity_image=AcquireImage((ImageInfo *) NULL);
7773 if (affinity_image == (Image *) NULL)
7774 ThrowXWindowFatalException(ResourceLimitFatalError,
7775 "UnableToDitherImage",image->filename);
7776 affinity_image->columns=number_colors;
7777 affinity_image->rows=1;
7778 /*
7779 Initialize colormap image.
7780 */
7781 q=QueueAuthenticPixels(affinity_image,0,0,affinity_image->columns,
7782 1,exception);
cristy4c08aed2011-07-01 19:47:50 +00007783 if (q != (Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00007784 {
cristybb503372010-05-27 20:51:26 +00007785 for (i=0; i < (ssize_t) number_colors; i++)
cristy3ed852e2009-09-05 21:47:34 +00007786 {
cristy4c08aed2011-07-01 19:47:50 +00007787 SetPixelRed(affinity_image,0,q);
cristy3ed852e2009-09-05 21:47:34 +00007788 if (map_info->red_max != 0)
cristy4c08aed2011-07-01 19:47:50 +00007789 SetPixelRed(affinity_image,
7790 ScaleXToQuantum((size_t) (i/map_info->red_mult),
7791 map_info->red_max),q);
7792 SetPixelGreen(affinity_image,0,q);
cristy3ed852e2009-09-05 21:47:34 +00007793 if (map_info->green_max != 0)
cristy4c08aed2011-07-01 19:47:50 +00007794 SetPixelGreen(affinity_image,
7795 ScaleXToQuantum((size_t) ((i/map_info->green_mult) %
7796 (map_info->green_max+1)),map_info->green_max),q);
7797 SetPixelBlue(affinity_image,0,q);
cristy3ed852e2009-09-05 21:47:34 +00007798 if (map_info->blue_max != 0)
cristy4c08aed2011-07-01 19:47:50 +00007799 SetPixelBlue(affinity_image,
7800 ScaleXToQuantum((size_t) (i % map_info->green_mult),
7801 map_info->blue_max),q);
7802 SetPixelAlpha(affinity_image,
7803 TransparentAlpha,q);
cristyed231572011-07-14 02:18:59 +00007804 q+=GetPixelChannels(affinity_image);
cristy3ed852e2009-09-05 21:47:34 +00007805 }
7806 (void) SyncAuthenticPixels(affinity_image,exception);
7807 (void) RemapImage(resource_info->quantize_info,image,
cristy018f07f2011-09-04 21:15:19 +00007808 affinity_image,exception);
cristy3ed852e2009-09-05 21:47:34 +00007809 }
cristy4c08aed2011-07-01 19:47:50 +00007810 XGetPixelInfo(display,visual_info,map_info,resource_info,image,
cristy3ed852e2009-09-05 21:47:34 +00007811 pixel);
cristy574cc262011-08-05 01:23:58 +00007812 (void) SetImageStorageClass(image,DirectClass,exception);
cristy3ed852e2009-09-05 21:47:34 +00007813 affinity_image=DestroyImage(affinity_image);
7814 }
7815 if (IsEventLogging())
7816 {
7817 (void) LogMagickEvent(X11Event,GetMagickModule(),
7818 "Standard Colormap:");
7819 (void) LogMagickEvent(X11Event,GetMagickModule(),
7820 " colormap id: 0x%lx",map_info->colormap);
7821 (void) LogMagickEvent(X11Event,GetMagickModule(),
7822 " red, green, blue max: %lu %lu %lu",map_info->red_max,
7823 map_info->green_max,map_info->blue_max);
7824 (void) LogMagickEvent(X11Event,GetMagickModule(),
7825 " red, green, blue mult: %lu %lu %lu",map_info->red_mult,
7826 map_info->green_mult,map_info->blue_mult);
7827 }
7828 return;
7829 }
7830 if ((visual_info->klass != DirectColor) &&
7831 (visual_info->klass != TrueColor))
7832 if ((image->storage_class == DirectClass) ||
7833 ((int) image->colors > visual_info->colormap_size))
7834 {
7835 QuantizeInfo
7836 quantize_info;
7837
7838 /*
7839 Image has more colors than the visual supports.
7840 */
7841 quantize_info=(*resource_info->quantize_info);
cristybb503372010-05-27 20:51:26 +00007842 quantize_info.number_colors=(size_t) visual_info->colormap_size;
cristy018f07f2011-09-04 21:15:19 +00007843 (void) QuantizeImage(&quantize_info,image,exception);
cristy3ed852e2009-09-05 21:47:34 +00007844 }
7845 /*
7846 Free previous and create new colormap.
7847 */
7848 (void) XFreeStandardColormap(display,visual_info,map_info,pixel);
7849 colormap=XDefaultColormap(display,visual_info->screen);
7850 if (visual_info->visual != XDefaultVisual(display,visual_info->screen))
7851 colormap=XCreateColormap(display,XRootWindow(display,visual_info->screen),
7852 visual_info->visual,visual_info->klass == DirectColor ?
7853 AllocAll : AllocNone);
7854 if (colormap == (Colormap) NULL)
7855 ThrowXWindowFatalException(ResourceLimitFatalError,"UnableToCreateColormap",
7856 image->filename);
7857 /*
7858 Initialize the map and pixel info structures.
7859 */
7860 XGetMapInfo(visual_info,colormap,map_info);
cristy4c08aed2011-07-01 19:47:50 +00007861 XGetPixelInfo(display,visual_info,map_info,resource_info,image,pixel);
cristy3ed852e2009-09-05 21:47:34 +00007862 /*
7863 Allocating colors in server colormap is based on visual class.
7864 */
7865 switch (visual_info->klass)
7866 {
7867 case StaticGray:
7868 case StaticColor:
7869 {
7870 /*
7871 Define Standard Colormap for StaticGray or StaticColor visual.
7872 */
7873 number_colors=image->colors;
7874 colors=(XColor *) AcquireQuantumMemory((size_t)
7875 visual_info->colormap_size,sizeof(*colors));
7876 if (colors == (XColor *) NULL)
7877 ThrowXWindowFatalException(ResourceLimitFatalError,
7878 "UnableToCreateColormap",image->filename);
7879 p=colors;
7880 color.flags=(char) (DoRed | DoGreen | DoBlue);
cristybb503372010-05-27 20:51:26 +00007881 for (i=0; i < (ssize_t) image->colors; i++)
cristy3ed852e2009-09-05 21:47:34 +00007882 {
7883 color.red=ScaleQuantumToShort(XRedGamma(image->colormap[i].red));
7884 color.green=ScaleQuantumToShort(XGreenGamma(image->colormap[i].green));
7885 color.blue=ScaleQuantumToShort(XBlueGamma(image->colormap[i].blue));
7886 if (visual_info->klass != StaticColor)
7887 {
7888 gray_value=(unsigned short) XPixelIntensity(&color);
7889 color.red=gray_value;
7890 color.green=gray_value;
7891 color.blue=gray_value;
7892 }
7893 status=XAllocColor(display,colormap,&color);
7894 if (status == False)
7895 {
7896 colormap=XCopyColormapAndFree(display,colormap);
7897 (void) XAllocColor(display,colormap,&color);
7898 }
7899 pixel->pixels[i]=color.pixel;
7900 *p++=color;
7901 }
7902 break;
7903 }
7904 case GrayScale:
7905 case PseudoColor:
7906 {
7907 unsigned int
7908 colormap_type;
7909
7910 /*
7911 Define Standard Colormap for GrayScale or PseudoColor visual.
7912 */
7913 number_colors=image->colors;
7914 colors=(XColor *) AcquireQuantumMemory((size_t)
7915 visual_info->colormap_size,sizeof(*colors));
7916 if (colors == (XColor *) NULL)
7917 ThrowXWindowFatalException(ResourceLimitFatalError,
7918 "UnableToCreateColormap",image->filename);
7919 /*
7920 Preallocate our GUI colors.
7921 */
7922 (void) XAllocColor(display,colormap,&pixel->foreground_color);
7923 (void) XAllocColor(display,colormap,&pixel->background_color);
7924 (void) XAllocColor(display,colormap,&pixel->border_color);
7925 (void) XAllocColor(display,colormap,&pixel->matte_color);
7926 (void) XAllocColor(display,colormap,&pixel->highlight_color);
7927 (void) XAllocColor(display,colormap,&pixel->shadow_color);
7928 (void) XAllocColor(display,colormap,&pixel->depth_color);
7929 (void) XAllocColor(display,colormap,&pixel->trough_color);
7930 for (i=0; i < MaxNumberPens; i++)
7931 (void) XAllocColor(display,colormap,&pixel->pen_colors[i]);
7932 /*
7933 Determine if image colors will "fit" into X server colormap.
7934 */
7935 colormap_type=resource_info->colormap;
cristyf2faecf2010-05-28 19:19:36 +00007936 status=XAllocColorCells(display,colormap,MagickFalse,(unsigned long *)
cristy3ed852e2009-09-05 21:47:34 +00007937 NULL,0,pixel->pixels,(unsigned int) image->colors);
7938 if (status != False)
7939 colormap_type=PrivateColormap;
7940 if (colormap_type == SharedColormap)
7941 {
cristyc57f6942010-11-12 01:47:39 +00007942 CacheView
7943 *image_view;
7944
cristy3ed852e2009-09-05 21:47:34 +00007945 DiversityPacket
7946 *diversity;
7947
7948 int
7949 y;
7950
7951 register int
7952 x;
7953
7954 unsigned short
7955 index;
7956
7957 XColor
7958 *server_colors;
7959
7960 /*
7961 Define Standard colormap for shared GrayScale or PseudoColor visual.
7962 */
7963 diversity=(DiversityPacket *) AcquireQuantumMemory(image->colors,
7964 sizeof(*diversity));
7965 if (diversity == (DiversityPacket *) NULL)
7966 ThrowXWindowFatalException(ResourceLimitFatalError,
7967 "UnableToCreateColormap",image->filename);
cristybb503372010-05-27 20:51:26 +00007968 for (i=0; i < (ssize_t) image->colors; i++)
cristy3ed852e2009-09-05 21:47:34 +00007969 {
7970 diversity[i].red=image->colormap[i].red;
7971 diversity[i].green=image->colormap[i].green;
7972 diversity[i].blue=image->colormap[i].blue;
7973 diversity[i].index=(unsigned short) i;
7974 diversity[i].count=0;
7975 }
cristyc57f6942010-11-12 01:47:39 +00007976 image_view=AcquireCacheView(image);
cristy3ed852e2009-09-05 21:47:34 +00007977 for (y=0; y < (int) image->rows; y++)
7978 {
cristyc57f6942010-11-12 01:47:39 +00007979 register int
cristy3ed852e2009-09-05 21:47:34 +00007980 x;
7981
cristy4c08aed2011-07-01 19:47:50 +00007982 register const Quantum
cristyc57f6942010-11-12 01:47:39 +00007983 *restrict p;
cristy3ed852e2009-09-05 21:47:34 +00007984
cristyc57f6942010-11-12 01:47:39 +00007985 p=GetCacheViewAuthenticPixels(image_view,0,(ssize_t) y,
7986 image->columns,1,exception);
cristy4c08aed2011-07-01 19:47:50 +00007987 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00007988 break;
cristyc57f6942010-11-12 01:47:39 +00007989 for (x=(int) image->columns-1; x >= 0; x--)
cristy4c08aed2011-07-01 19:47:50 +00007990 {
7991 diversity[(ssize_t) GetPixelIndex(image,p)].count++;
cristyed231572011-07-14 02:18:59 +00007992 p+=GetPixelChannels(image);
cristy4c08aed2011-07-01 19:47:50 +00007993 }
cristy3ed852e2009-09-05 21:47:34 +00007994 }
cristyc57f6942010-11-12 01:47:39 +00007995 image_view=DestroyCacheView(image_view);
cristy3ed852e2009-09-05 21:47:34 +00007996 /*
7997 Sort colors by decreasing intensity.
7998 */
7999 qsort((void *) diversity,image->colors,sizeof(*diversity),
8000 IntensityCompare);
cristybb503372010-05-27 20:51:26 +00008001 for (i=0; i < (ssize_t) image->colors; )
cristy3ed852e2009-09-05 21:47:34 +00008002 {
8003 diversity[i].count<<=4; /* increase this colors popularity */
cristydfe2b662010-08-22 16:17:24 +00008004 i+=MagickMax((int) (image->colors >> 4),2);
cristy3ed852e2009-09-05 21:47:34 +00008005 }
8006 diversity[image->colors-1].count<<=4;
8007 qsort((void *) diversity,image->colors,sizeof(*diversity),
8008 PopularityCompare);
8009 /*
8010 Allocate colors.
8011 */
8012 p=colors;
8013 color.flags=(char) (DoRed | DoGreen | DoBlue);
cristybb503372010-05-27 20:51:26 +00008014 for (i=0; i < (ssize_t) image->colors; i++)
cristy3ed852e2009-09-05 21:47:34 +00008015 {
8016 index=diversity[i].index;
8017 color.red=
8018 ScaleQuantumToShort(XRedGamma(image->colormap[index].red));
8019 color.green=
8020 ScaleQuantumToShort(XGreenGamma(image->colormap[index].green));
8021 color.blue=
8022 ScaleQuantumToShort(XBlueGamma(image->colormap[index].blue));
8023 if (visual_info->klass != PseudoColor)
8024 {
8025 gray_value=(unsigned short) XPixelIntensity(&color);
8026 color.red=gray_value;
8027 color.green=gray_value;
8028 color.blue=gray_value;
8029 }
8030 status=XAllocColor(display,colormap,&color);
8031 if (status == False)
8032 break;
8033 pixel->pixels[index]=color.pixel;
8034 *p++=color;
8035 }
8036 /*
8037 Read X server colormap.
8038 */
8039 server_colors=(XColor *) AcquireQuantumMemory((size_t)
8040 visual_info->colormap_size,sizeof(*server_colors));
8041 if (server_colors == (XColor *) NULL)
8042 ThrowXWindowFatalException(ResourceLimitFatalError,
8043 "UnableToCreateColormap",image->filename);
8044 for (x=visual_info->colormap_size-1; x >= 0; x--)
cristybb503372010-05-27 20:51:26 +00008045 server_colors[x].pixel=(size_t) x;
cristy3ed852e2009-09-05 21:47:34 +00008046 (void) XQueryColors(display,colormap,server_colors,
8047 (int) MagickMin((unsigned int) visual_info->colormap_size,256));
8048 /*
8049 Select remaining colors from X server colormap.
8050 */
cristybb503372010-05-27 20:51:26 +00008051 for (; i < (ssize_t) image->colors; i++)
cristy3ed852e2009-09-05 21:47:34 +00008052 {
8053 index=diversity[i].index;
8054 color.red=
8055 ScaleQuantumToShort(XRedGamma(image->colormap[index].red));
8056 color.green=
8057 ScaleQuantumToShort(XGreenGamma(image->colormap[index].green));
8058 color.blue=
8059 ScaleQuantumToShort(XBlueGamma(image->colormap[index].blue));
8060 if (visual_info->klass != PseudoColor)
8061 {
8062 gray_value=(unsigned short) XPixelIntensity(&color);
8063 color.red=gray_value;
8064 color.green=gray_value;
8065 color.blue=gray_value;
8066 }
8067 XBestPixel(display,colormap,server_colors,(unsigned int)
8068 visual_info->colormap_size,&color);
8069 pixel->pixels[index]=color.pixel;
8070 *p++=color;
8071 }
8072 if ((int) image->colors < visual_info->colormap_size)
8073 {
8074 /*
8075 Fill up colors array-- more choices for pen colors.
8076 */
8077 retain_colors=MagickMin((unsigned int)
8078 (visual_info->colormap_size-image->colors),256);
cristybb503372010-05-27 20:51:26 +00008079 for (i=0; i < (ssize_t) retain_colors; i++)
cristy3ed852e2009-09-05 21:47:34 +00008080 *p++=server_colors[i];
8081 number_colors+=retain_colors;
8082 }
8083 server_colors=(XColor *) RelinquishMagickMemory(server_colors);
8084 diversity=(DiversityPacket *) RelinquishMagickMemory(diversity);
8085 break;
8086 }
8087 /*
8088 Define Standard colormap for private GrayScale or PseudoColor visual.
8089 */
8090 if (status == False)
8091 {
8092 /*
8093 Not enough colormap entries in the colormap-- Create a new colormap.
8094 */
8095 colormap=XCreateColormap(display,
8096 XRootWindow(display,visual_info->screen),visual_info->visual,
8097 AllocNone);
8098 if (colormap == (Colormap) NULL)
8099 ThrowXWindowFatalException(ResourceLimitFatalError,
8100 "UnableToCreateColormap",image->filename);
8101 map_info->colormap=colormap;
8102 if ((int) image->colors < visual_info->colormap_size)
8103 {
8104 /*
8105 Retain colors from the default colormap to help lessens the
8106 effects of colormap flashing.
8107 */
8108 retain_colors=MagickMin((unsigned int)
8109 (visual_info->colormap_size-image->colors),256);
8110 p=colors+image->colors;
cristybb503372010-05-27 20:51:26 +00008111 for (i=0; i < (ssize_t) retain_colors; i++)
cristy3ed852e2009-09-05 21:47:34 +00008112 {
cristyc57f6942010-11-12 01:47:39 +00008113 p->pixel=(unsigned long) i;
cristy3ed852e2009-09-05 21:47:34 +00008114 p++;
8115 }
8116 (void) XQueryColors(display,
8117 XDefaultColormap(display,visual_info->screen),
8118 colors+image->colors,(int) retain_colors);
8119 /*
8120 Transfer colors from default to private colormap.
8121 */
8122 (void) XAllocColorCells(display,colormap,MagickFalse,
cristyf2faecf2010-05-28 19:19:36 +00008123 (unsigned long *) NULL,0,pixel->pixels,(unsigned int)
cristy3ed852e2009-09-05 21:47:34 +00008124 retain_colors);
8125 p=colors+image->colors;
cristybb503372010-05-27 20:51:26 +00008126 for (i=0; i < (ssize_t) retain_colors; i++)
cristy3ed852e2009-09-05 21:47:34 +00008127 {
8128 p->pixel=pixel->pixels[i];
8129 p++;
8130 }
8131 (void) XStoreColors(display,colormap,colors+image->colors,
8132 (int) retain_colors);
8133 number_colors+=retain_colors;
8134 }
8135 (void) XAllocColorCells(display,colormap,MagickFalse,
cristyf2faecf2010-05-28 19:19:36 +00008136 (unsigned long *) NULL,0,pixel->pixels,(unsigned int)
cristy3ed852e2009-09-05 21:47:34 +00008137 image->colors);
8138 }
8139 /*
8140 Store the image colormap.
8141 */
8142 p=colors;
8143 color.flags=(char) (DoRed | DoGreen | DoBlue);
cristybb503372010-05-27 20:51:26 +00008144 for (i=0; i < (ssize_t) image->colors; i++)
cristy3ed852e2009-09-05 21:47:34 +00008145 {
8146 color.red=ScaleQuantumToShort(XRedGamma(image->colormap[i].red));
8147 color.green=ScaleQuantumToShort(XGreenGamma(image->colormap[i].green));
8148 color.blue=ScaleQuantumToShort(XBlueGamma(image->colormap[i].blue));
8149 if (visual_info->klass != PseudoColor)
8150 {
8151 gray_value=(unsigned short) XPixelIntensity(&color);
8152 color.red=gray_value;
8153 color.green=gray_value;
8154 color.blue=gray_value;
8155 }
8156 color.pixel=pixel->pixels[i];
8157 *p++=color;
8158 }
8159 (void) XStoreColors(display,colormap,colors,(int) image->colors);
8160 break;
8161 }
8162 case TrueColor:
8163 case DirectColor:
8164 default:
8165 {
8166 MagickBooleanType
8167 linear_colormap;
8168
8169 /*
8170 Define Standard Colormap for TrueColor or DirectColor visual.
8171 */
8172 number_colors=(unsigned int) ((map_info->red_max*map_info->red_mult)+
8173 (map_info->green_max*map_info->green_mult)+
8174 (map_info->blue_max*map_info->blue_mult)+1);
8175 linear_colormap=(number_colors > 4096) ||
8176 (((int) (map_info->red_max+1) == visual_info->colormap_size) &&
8177 ((int) (map_info->green_max+1) == visual_info->colormap_size) &&
8178 ((int) (map_info->blue_max+1) == visual_info->colormap_size)) ?
8179 MagickTrue : MagickFalse;
8180 if (linear_colormap != MagickFalse)
cristybb503372010-05-27 20:51:26 +00008181 number_colors=(size_t) visual_info->colormap_size;
cristy3ed852e2009-09-05 21:47:34 +00008182 /*
8183 Allocate color array.
8184 */
8185 colors=(XColor *) AcquireQuantumMemory(number_colors,sizeof(*colors));
8186 if (colors == (XColor *) NULL)
8187 ThrowXWindowFatalException(ResourceLimitFatalError,
8188 "UnableToCreateColormap",image->filename);
8189 /*
8190 Initialize linear color ramp.
8191 */
8192 p=colors;
8193 color.flags=(char) (DoRed | DoGreen | DoBlue);
8194 if (linear_colormap != MagickFalse)
cristybb503372010-05-27 20:51:26 +00008195 for (i=0; i < (ssize_t) number_colors; i++)
cristy3ed852e2009-09-05 21:47:34 +00008196 {
8197 color.blue=(unsigned short) 0;
8198 if (map_info->blue_max != 0)
cristybb503372010-05-27 20:51:26 +00008199 color.blue=(unsigned short) ((size_t)
cristy3ed852e2009-09-05 21:47:34 +00008200 ((65535L*(i % map_info->green_mult))/map_info->blue_max));
8201 color.green=color.blue;
8202 color.red=color.blue;
8203 color.pixel=XStandardPixel(map_info,&color);
8204 *p++=color;
8205 }
8206 else
cristybb503372010-05-27 20:51:26 +00008207 for (i=0; i < (ssize_t) number_colors; i++)
cristy3ed852e2009-09-05 21:47:34 +00008208 {
8209 color.red=(unsigned short) 0;
8210 if (map_info->red_max != 0)
cristybb503372010-05-27 20:51:26 +00008211 color.red=(unsigned short) ((size_t)
cristy3ed852e2009-09-05 21:47:34 +00008212 ((65535L*(i/map_info->red_mult))/map_info->red_max));
8213 color.green=(unsigned int) 0;
8214 if (map_info->green_max != 0)
cristybb503372010-05-27 20:51:26 +00008215 color.green=(unsigned short) ((size_t)
cristy3ed852e2009-09-05 21:47:34 +00008216 ((65535L*((i/map_info->green_mult) % (map_info->green_max+1)))/
8217 map_info->green_max));
8218 color.blue=(unsigned short) 0;
8219 if (map_info->blue_max != 0)
cristybb503372010-05-27 20:51:26 +00008220 color.blue=(unsigned short) ((size_t)
cristy3ed852e2009-09-05 21:47:34 +00008221 ((65535L*(i % map_info->green_mult))/map_info->blue_max));
8222 color.pixel=XStandardPixel(map_info,&color);
8223 *p++=color;
8224 }
8225 if ((visual_info->klass == DirectColor) &&
8226 (colormap != XDefaultColormap(display,visual_info->screen)))
8227 (void) XStoreColors(display,colormap,colors,(int) number_colors);
8228 else
cristybb503372010-05-27 20:51:26 +00008229 for (i=0; i < (ssize_t) number_colors; i++)
cristy3ed852e2009-09-05 21:47:34 +00008230 (void) XAllocColor(display,colormap,&colors[i]);
8231 break;
8232 }
8233 }
8234 if ((visual_info->klass != DirectColor) &&
8235 (visual_info->klass != TrueColor))
8236 {
8237 /*
8238 Set foreground, background, border, etc. pixels.
8239 */
8240 XBestPixel(display,colormap,colors,(unsigned int) number_colors,
8241 &pixel->foreground_color);
8242 XBestPixel(display,colormap,colors,(unsigned int) number_colors,
8243 &pixel->background_color);
8244 if (pixel->background_color.pixel == pixel->foreground_color.pixel)
8245 {
8246 /*
8247 Foreground and background colors must differ.
8248 */
8249 pixel->background_color.red=(~pixel->foreground_color.red);
8250 pixel->background_color.green=
8251 (~pixel->foreground_color.green);
8252 pixel->background_color.blue=
8253 (~pixel->foreground_color.blue);
8254 XBestPixel(display,colormap,colors,(unsigned int) number_colors,
8255 &pixel->background_color);
8256 }
8257 XBestPixel(display,colormap,colors,(unsigned int) number_colors,
8258 &pixel->border_color);
8259 XBestPixel(display,colormap,colors,(unsigned int) number_colors,
8260 &pixel->matte_color);
8261 XBestPixel(display,colormap,colors,(unsigned int) number_colors,
8262 &pixel->highlight_color);
8263 XBestPixel(display,colormap,colors,(unsigned int) number_colors,
8264 &pixel->shadow_color);
8265 XBestPixel(display,colormap,colors,(unsigned int) number_colors,
8266 &pixel->depth_color);
8267 XBestPixel(display,colormap,colors,(unsigned int) number_colors,
8268 &pixel->trough_color);
8269 for (i=0; i < MaxNumberPens; i++)
8270 {
8271 XBestPixel(display,colormap,colors,(unsigned int) number_colors,
8272 &pixel->pen_colors[i]);
8273 pixel->pixels[image->colors+i]=pixel->pen_colors[i].pixel;
8274 }
cristyc57f6942010-11-12 01:47:39 +00008275 pixel->colors=(ssize_t) (image->colors+MaxNumberPens);
cristy3ed852e2009-09-05 21:47:34 +00008276 }
8277 colors=(XColor *) RelinquishMagickMemory(colors);
8278 if (IsEventLogging())
8279 {
8280 (void) LogMagickEvent(X11Event,GetMagickModule(),"Standard Colormap:");
8281 (void) LogMagickEvent(X11Event,GetMagickModule()," colormap id: 0x%lx",
8282 map_info->colormap);
8283 (void) LogMagickEvent(X11Event,GetMagickModule(),
8284 " red, green, blue max: %lu %lu %lu",map_info->red_max,
8285 map_info->green_max,map_info->blue_max);
8286 (void) LogMagickEvent(X11Event,GetMagickModule(),
8287 " red, green, blue mult: %lu %lu %lu",map_info->red_mult,
8288 map_info->green_mult,map_info->blue_mult);
8289 }
8290}
8291
8292/*
8293%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8294% %
8295% %
8296% %
8297% X M a k e W i n d o w %
8298% %
8299% %
8300% %
8301%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8302%
8303% XMakeWindow() creates an X11 window.
8304%
8305% The format of the XMakeWindow method is:
8306%
8307% void XMakeWindow(Display *display,Window parent,char **argv,int argc,
8308% XClassHint *class_hint,XWMHints *manager_hints,
8309% XWindowInfo *window_info)
8310%
8311% A description of each parameter follows:
8312%
8313% o display: Specifies a connection to an X server; returned from
8314% XOpenDisplay.
8315%
8316% o parent: Specifies the parent window_info.
8317%
8318% o argv: Specifies the application's argument list.
8319%
8320% o argc: Specifies the number of arguments.
8321%
8322% o class_hint: Specifies a pointer to a X11 XClassHint structure.
8323%
8324% o manager_hints: Specifies a pointer to a X11 XWMHints structure.
8325%
8326% o window_info: Specifies a pointer to a X11 XWindowInfo structure.
8327%
8328*/
cristybcbda3f2011-09-03 13:01:22 +00008329MagickPrivate void XMakeWindow(Display *display,Window parent,char **argv,
cristy3ed852e2009-09-05 21:47:34 +00008330 int argc,XClassHint *class_hint,XWMHints *manager_hints,
8331 XWindowInfo *window_info)
8332{
8333#define MinWindowSize 64
8334
8335 Atom
8336 atom_list[2];
8337
8338 int
8339 gravity;
8340
8341 static XTextProperty
8342 icon_name,
8343 window_name;
8344
8345 Status
8346 status;
8347
8348 XSizeHints
8349 *size_hints;
8350
8351 /*
8352 Set window info hints.
8353 */
8354 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
8355 assert(display != (Display *) NULL);
8356 assert(window_info != (XWindowInfo *) NULL);
8357 size_hints=XAllocSizeHints();
8358 if (size_hints == (XSizeHints *) NULL)
8359 ThrowXWindowFatalException(XServerFatalError,"UnableToMakeXWindow",argv[0]);
cristydfe2b662010-08-22 16:17:24 +00008360 size_hints->flags=(int) window_info->flags;
cristy3ed852e2009-09-05 21:47:34 +00008361 size_hints->x=window_info->x;
8362 size_hints->y=window_info->y;
8363 size_hints->width=(int) window_info->width;
8364 size_hints->height=(int) window_info->height;
8365 if (window_info->immutable != MagickFalse)
8366 {
8367 /*
8368 Window size cannot be changed.
8369 */
8370 size_hints->min_width=size_hints->width;
8371 size_hints->min_height=size_hints->height;
8372 size_hints->max_width=size_hints->width;
8373 size_hints->max_height=size_hints->height;
8374 size_hints->flags|=PMinSize;
8375 size_hints->flags|=PMaxSize;
8376 }
8377 else
8378 {
8379 /*
8380 Window size can be changed.
8381 */
8382 size_hints->min_width=(int) window_info->min_width;
8383 size_hints->min_height=(int) window_info->min_height;
8384 size_hints->flags|=PResizeInc;
8385 size_hints->width_inc=(int) window_info->width_inc;
8386 size_hints->height_inc=(int) window_info->height_inc;
8387#if !defined(PRE_R4_ICCCM)
8388 size_hints->flags|=PBaseSize;
8389 size_hints->base_width=size_hints->width_inc;
8390 size_hints->base_height=size_hints->height_inc;
8391#endif
8392 }
8393 gravity=NorthWestGravity;
8394 if (window_info->geometry != (char *) NULL)
8395 {
8396 char
8397 default_geometry[MaxTextExtent],
8398 geometry[MaxTextExtent];
8399
8400 int
8401 flags;
8402
8403 register char
8404 *p;
8405
8406 /*
8407 User specified geometry.
8408 */
cristyb51dff52011-05-19 16:55:47 +00008409 (void) FormatLocaleString(default_geometry,MaxTextExtent,"%dx%d",
cristy3ed852e2009-09-05 21:47:34 +00008410 size_hints->width,size_hints->height);
8411 (void) CopyMagickString(geometry,window_info->geometry,MaxTextExtent);
8412 p=geometry;
8413 while (strlen(p) != 0)
8414 {
8415 if ((isspace((int) ((unsigned char) *p)) == 0) && (*p != '%'))
8416 p++;
8417 else
8418 (void) CopyMagickString(p,p+1,MaxTextExtent);
8419 }
8420 flags=XWMGeometry(display,window_info->screen,geometry,default_geometry,
8421 window_info->border_width,size_hints,&size_hints->x,&size_hints->y,
8422 &size_hints->width,&size_hints->height,&gravity);
8423 if ((flags & WidthValue) && (flags & HeightValue))
8424 size_hints->flags|=USSize;
8425 if ((flags & XValue) && (flags & YValue))
8426 {
8427 size_hints->flags|=USPosition;
8428 window_info->x=size_hints->x;
8429 window_info->y=size_hints->y;
8430 }
8431 }
8432#if !defined(PRE_R4_ICCCM)
8433 size_hints->win_gravity=gravity;
8434 size_hints->flags|=PWinGravity;
8435#endif
8436 if (window_info->id == (Window) NULL)
8437 window_info->id=XCreateWindow(display,parent,window_info->x,window_info->y,
8438 (unsigned int) size_hints->width,(unsigned int) size_hints->height,
8439 window_info->border_width,(int) window_info->depth,InputOutput,
cristyc57f6942010-11-12 01:47:39 +00008440 window_info->visual,(unsigned long) window_info->mask,
8441 &window_info->attributes);
cristy3ed852e2009-09-05 21:47:34 +00008442 else
8443 {
8444 MagickStatusType
8445 mask;
8446
8447 XEvent
8448 sans_event;
8449
8450 XWindowChanges
8451 window_changes;
8452
8453 /*
8454 Window already exists; change relevant attributes.
8455 */
cristyc57f6942010-11-12 01:47:39 +00008456 (void) XChangeWindowAttributes(display,window_info->id,(unsigned long)
8457 window_info->mask,&window_info->attributes);
cristy3ed852e2009-09-05 21:47:34 +00008458 mask=ConfigureNotify;
8459 while (XCheckTypedWindowEvent(display,window_info->id,(int) mask,&sans_event)) ;
8460 window_changes.x=window_info->x;
8461 window_changes.y=window_info->y;
8462 window_changes.width=(int) window_info->width;
8463 window_changes.height=(int) window_info->height;
8464 mask=(MagickStatusType) (CWWidth | CWHeight);
8465 if (window_info->flags & USPosition)
8466 mask|=CWX | CWY;
8467 (void) XReconfigureWMWindow(display,window_info->id,window_info->screen,
8468 mask,&window_changes);
8469 }
8470 if (window_info->id == (Window) NULL)
8471 ThrowXWindowFatalException(XServerFatalError,"UnableToCreateWindow",
8472 window_info->name);
8473 status=XStringListToTextProperty(&window_info->name,1,&window_name);
8474 if (status == False)
8475 ThrowXWindowFatalException(XServerFatalError,"UnableToCreateTextProperty",
8476 window_info->name);
8477 status=XStringListToTextProperty(&window_info->icon_name,1,&icon_name);
8478 if (status == False)
8479 ThrowXWindowFatalException(XServerFatalError,"UnableToCreateTextProperty",
8480 window_info->icon_name);
8481 if (window_info->icon_geometry != (char *) NULL)
8482 {
8483 int
8484 flags,
8485 height,
8486 width;
8487
8488 /*
8489 User specified icon geometry.
8490 */
8491 size_hints->flags|=USPosition;
8492 flags=XWMGeometry(display,window_info->screen,window_info->icon_geometry,
8493 (char *) NULL,0,size_hints,&manager_hints->icon_x,
8494 &manager_hints->icon_y,&width,&height,&gravity);
8495 if ((flags & XValue) && (flags & YValue))
8496 manager_hints->flags|=IconPositionHint;
8497 }
8498 XSetWMProperties(display,window_info->id,&window_name,&icon_name,argv,argc,
8499 size_hints,manager_hints,class_hint);
8500 if (window_name.value != (void *) NULL)
8501 {
8502 (void) XFree((void *) window_name.value);
8503 window_name.value=(unsigned char *) NULL;
8504 window_name.nitems=0;
8505 }
8506 if (icon_name.value != (void *) NULL)
8507 {
8508 (void) XFree((void *) icon_name.value);
8509 icon_name.value=(unsigned char *) NULL;
8510 icon_name.nitems=0;
8511 }
8512 atom_list[0]=XInternAtom(display,"WM_DELETE_WINDOW",MagickFalse);
8513 atom_list[1]=XInternAtom(display,"WM_TAKE_FOCUS",MagickFalse);
8514 (void) XSetWMProtocols(display,window_info->id,atom_list,2);
8515 (void) XFree((void *) size_hints);
8516 if (window_info->shape != MagickFalse)
8517 {
8518#if defined(MAGICKCORE_HAVE_SHAPE)
8519 int
8520 error_base,
8521 event_base;
8522
8523 /*
8524 Can we apply a non-rectangular shaping mask?
8525 */
8526 error_base=0;
8527 event_base=0;
8528 if (XShapeQueryExtension(display,&error_base,&event_base) == 0)
8529 window_info->shape=MagickFalse;
8530#else
8531 window_info->shape=MagickFalse;
8532#endif
8533 }
8534 if (window_info->shared_memory)
8535 {
8536#if defined(MAGICKCORE_HAVE_SHARED_MEMORY)
8537 /*
8538 Can we use shared memory with this window?
8539 */
8540 if (XShmQueryExtension(display) == 0)
8541 window_info->shared_memory=MagickFalse;
8542#else
8543 window_info->shared_memory=MagickFalse;
8544#endif
8545 }
8546 window_info->image=NewImageList();
8547 window_info->destroy=MagickFalse;
8548}
8549
8550/*
8551%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8552% %
8553% %
8554% %
8555% X M a g i c k P r o g r e s s M o n i t o r %
8556% %
8557% %
8558% %
8559%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8560%
8561% XMagickProgressMonitor() displays the progress a task is making in
8562% completing a task.
8563%
8564% The format of the XMagickProgressMonitor method is:
8565%
8566% void XMagickProgressMonitor(const char *task,
8567% const MagickOffsetType quantum,const MagickSizeType span,
8568% void *client_data)
8569%
8570% A description of each parameter follows:
8571%
8572% o task: Identifies the task in progress.
8573%
8574% o quantum: Specifies the quantum position within the span which represents
8575% how much progress has been made in completing a task.
8576%
8577% o span: Specifies the span relative to completing a task.
8578%
8579% o client_data: Pointer to any client data.
8580%
8581*/
8582
8583static const char *GetLocaleMonitorMessage(const char *text)
8584{
8585 char
8586 message[MaxTextExtent],
8587 tag[MaxTextExtent];
8588
8589 const char
8590 *locale_message;
8591
8592 register char
8593 *p;
8594
8595 (void) CopyMagickMemory(tag,text,MaxTextExtent);
8596 p=strrchr(tag,'/');
8597 if (p != (char *) NULL)
8598 *p='\0';
cristyb51dff52011-05-19 16:55:47 +00008599 (void) FormatLocaleString(message,MaxTextExtent,"Monitor/%s",tag);
cristy3ed852e2009-09-05 21:47:34 +00008600 locale_message=GetLocaleMessage(message);
8601 if (locale_message == message)
8602 return(text);
8603 return(locale_message);
8604}
8605
cristybcbda3f2011-09-03 13:01:22 +00008606MagickPrivate MagickBooleanType XMagickProgressMonitor(const char *tag,
cristy3ed852e2009-09-05 21:47:34 +00008607 const MagickOffsetType quantum,const MagickSizeType span,
8608 void *magick_unused(client_data))
8609{
8610 XWindows
8611 *windows;
8612
8613 windows=XSetWindows((XWindows *) ~0);
8614 if (windows == (XWindows *) NULL)
8615 return(MagickTrue);
8616 if (windows->info.mapped != MagickFalse)
8617 XProgressMonitorWidget(windows->display,windows,
8618 GetLocaleMonitorMessage(tag),quantum,span);
8619 return(MagickTrue);
8620}
8621
8622/*
8623%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8624% %
8625% %
8626% %
8627% X Q u e r y C o l o r D a t a b a s e %
8628% %
8629% %
8630% %
8631%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8632%
8633% XQueryColorDatabase() looks up a RGB values for a color given in the target
8634% string.
8635%
8636% The format of the XQueryColorDatabase method is:
8637%
8638% MagickBooleanType XQueryColorDatabase(const char *target,XColor *color)
8639%
8640% A description of each parameter follows:
8641%
8642% o target: Specifies the color to lookup in the X color database.
8643%
8644% o color: A pointer to an PixelPacket structure. The RGB value of the target
8645% color is returned as this value.
8646%
8647*/
cristybcbda3f2011-09-03 13:01:22 +00008648MagickPrivate MagickBooleanType XQueryColorDatabase(const char *target,
cristy3ed852e2009-09-05 21:47:34 +00008649 XColor *color)
8650{
8651 Colormap
8652 colormap;
8653
8654 static Display
8655 *display = (Display *) NULL;
8656
8657 Status
8658 status;
8659
8660 XColor
8661 xcolor;
8662
8663 /*
8664 Initialize color return value.
8665 */
8666 assert(color != (XColor *) NULL);
8667 color->red=0;
8668 color->green=0;
8669 color->blue=0;
8670 color->flags=(char) (DoRed | DoGreen | DoBlue);
8671 if ((target == (char *) NULL) || (*target == '\0'))
8672 target="#ffffffffffff";
8673 /*
8674 Let the X server define the color for us.
8675 */
8676 if (display == (Display *) NULL)
8677 display=XOpenDisplay((char *) NULL);
8678 if (display == (Display *) NULL)
8679 {
8680 ThrowXWindowFatalException(XServerError,"ColorIsNotKnownToServer",target);
8681 return(MagickFalse);
8682 }
8683 colormap=XDefaultColormap(display,XDefaultScreen(display));
8684 status=XParseColor(display,colormap,(char *) target,&xcolor);
8685 if (status == False)
8686 ThrowXWindowFatalException(XServerError,"ColorIsNotKnownToServer",target)
8687 else
8688 {
8689 color->red=xcolor.red;
8690 color->green=xcolor.green;
8691 color->blue=xcolor.blue;
8692 color->flags=xcolor.flags;
8693 }
8694 return(status != False ? MagickTrue : MagickFalse);
8695}
8696
8697/*
8698%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8699% %
8700% %
8701% %
8702% X Q u e r y P o s i t i o n %
8703% %
8704% %
8705% %
8706%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8707%
8708% XQueryPosition() gets the pointer coordinates relative to a window.
8709%
8710% The format of the XQueryPosition method is:
8711%
8712% void XQueryPosition(Display *display,const Window window,int *x,int *y)
8713%
8714% A description of each parameter follows:
8715%
8716% o display: Specifies a connection to an X server; returned from
8717% XOpenDisplay.
8718%
8719% o window: Specifies a pointer to a Window.
8720%
8721% o x: Return the x coordinate of the pointer relative to the origin of the
8722% window.
8723%
8724% o y: Return the y coordinate of the pointer relative to the origin of the
8725% window.
8726%
8727*/
cristybcbda3f2011-09-03 13:01:22 +00008728MagickPrivate void XQueryPosition(Display *display,const Window window,int *x,int *y)
cristy3ed852e2009-09-05 21:47:34 +00008729{
8730 int
8731 x_root,
8732 y_root;
8733
8734 unsigned int
8735 mask;
8736
8737 Window
8738 root_window;
8739
8740 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
8741 assert(display != (Display *) NULL);
8742 assert(window != (Window) NULL);
8743 assert(x != (int *) NULL);
8744 assert(y != (int *) NULL);
8745 (void) XQueryPointer(display,window,&root_window,&root_window,&x_root,&y_root,
8746 x,y,&mask);
8747}
8748
8749/*
8750%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8751% %
8752% %
8753% %
8754% X R e f r e s h W i n d o w %
8755% %
8756% %
8757% %
8758%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8759%
8760% XRefreshWindow() refreshes an image in a X window.
8761%
8762% The format of the XRefreshWindow method is:
8763%
8764% void XRefreshWindow(Display *display,const XWindowInfo *window,
8765% const XEvent *event)
8766%
8767% A description of each parameter follows:
8768%
8769% o display: Specifies a connection to an X server; returned from
8770% XOpenDisplay.
8771%
8772% o window: Specifies a pointer to a XWindowInfo structure.
8773%
8774% o event: Specifies a pointer to a XEvent structure. If it is NULL,
8775% the entire image is refreshed.
8776%
8777*/
cristybcbda3f2011-09-03 13:01:22 +00008778MagickPrivate void XRefreshWindow(Display *display,const XWindowInfo *window,
cristy3ed852e2009-09-05 21:47:34 +00008779 const XEvent *event)
8780{
8781 int
8782 x,
8783 y;
8784
8785 unsigned int
8786 height,
8787 width;
8788
8789 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
8790 assert(display != (Display *) NULL);
8791 assert(window != (XWindowInfo *) NULL);
8792 if (window->ximage == (XImage *) NULL)
8793 return;
8794 if (event != (XEvent *) NULL)
8795 {
8796 /*
8797 Determine geometry from expose event.
8798 */
8799 x=event->xexpose.x;
8800 y=event->xexpose.y;
8801 width=(unsigned int) event->xexpose.width;
8802 height=(unsigned int) event->xexpose.height;
8803 }
8804 else
8805 {
8806 XEvent
8807 sans_event;
8808
8809 /*
8810 Refresh entire window; discard outstanding expose events.
8811 */
8812 x=0;
8813 y=0;
8814 width=window->width;
8815 height=window->height;
8816 while (XCheckTypedWindowEvent(display,window->id,Expose,&sans_event)) ;
cristya0e5ad52010-02-10 02:05:12 +00008817 if (window->matte_pixmap != (Pixmap) NULL)
8818 {
8819#if defined(MAGICKCORE_HAVE_SHAPE)
8820 if (window->shape != MagickFalse)
8821 XShapeCombineMask(display,window->id,ShapeBounding,0,0,
8822 window->matte_pixmap,ShapeSet);
8823#endif
8824 }
cristy3ed852e2009-09-05 21:47:34 +00008825 }
8826 /*
8827 Check boundary conditions.
8828 */
8829 if ((window->ximage->width-(x+window->x)) < (int) width)
8830 width=(unsigned int) (window->ximage->width-(x+window->x));
8831 if ((window->ximage->height-(y+window->y)) < (int) height)
8832 height=(unsigned int) (window->ximage->height-(y+window->y));
8833 /*
8834 Refresh image.
8835 */
8836 if (window->matte_pixmap != (Pixmap) NULL)
cristya0e5ad52010-02-10 02:05:12 +00008837 (void) XSetClipMask(display,window->annotate_context,window->matte_pixmap);
cristy3ed852e2009-09-05 21:47:34 +00008838 if (window->pixmap != (Pixmap) NULL)
8839 {
8840 if (window->depth > 1)
8841 (void) XCopyArea(display,window->pixmap,window->id,
8842 window->annotate_context,x+window->x,y+window->y,width,height,x,y);
8843 else
8844 (void) XCopyPlane(display,window->pixmap,window->id,
8845 window->highlight_context,x+window->x,y+window->y,width,height,x,y,
8846 1L);
8847 }
8848 else
8849 {
8850#if defined(MAGICKCORE_HAVE_SHARED_MEMORY)
8851 if (window->shared_memory)
8852 (void) XShmPutImage(display,window->id,window->annotate_context,
8853 window->ximage,x+window->x,y+window->y,x,y,width,height,MagickTrue);
8854#endif
8855 if (window->shared_memory == MagickFalse)
8856 (void) XPutImage(display,window->id,window->annotate_context,
8857 window->ximage,x+window->x,y+window->y,x,y,width,height);
8858 }
8859 if (window->matte_pixmap != (Pixmap) NULL)
8860 (void) XSetClipMask(display,window->annotate_context,None);
8861 (void) XFlush(display);
8862}
8863
8864/*
8865%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8866% %
8867% %
8868% %
8869% X R e m o t e C o m m a n d %
8870% %
8871% %
8872% %
8873%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8874%
8875% XRemoteCommand() forces a remote display(1) to display the specified
8876% image filename.
8877%
8878% The format of the XRemoteCommand method is:
8879%
8880% MagickBooleanType XRemoteCommand(Display *display,const char *window,
8881% const char *filename)
8882%
8883% A description of each parameter follows:
8884%
8885% o display: Specifies a connection to an X server; returned from
8886% XOpenDisplay.
8887%
8888% o window: Specifies the name or id of an X window.
8889%
8890% o filename: the name of the image filename to display.
8891%
8892*/
8893MagickExport MagickBooleanType XRemoteCommand(Display *display,
8894 const char *window,const char *filename)
8895{
8896 Atom
8897 remote_atom;
8898
8899 Window
8900 remote_window,
8901 root_window;
8902
8903 assert(filename != (char *) NULL);
8904 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",filename);
8905 if (display == (Display *) NULL)
8906 display=XOpenDisplay((char *) NULL);
8907 if (display == (Display *) NULL)
8908 {
8909 ThrowXWindowException(XServerError,"UnableToOpenXServer",filename);
8910 return(MagickFalse);
8911 }
8912 remote_atom=XInternAtom(display,"IM_PROTOCOLS",MagickFalse);
8913 remote_window=(Window) NULL;
8914 root_window=XRootWindow(display,XDefaultScreen(display));
8915 if (window != (char *) NULL)
8916 {
8917 /*
8918 Search window hierarchy and identify any clients by name or ID.
8919 */
8920 if (isdigit((unsigned char) *window) != 0)
8921 remote_window=XWindowByID(display,root_window,(Window)
8922 strtol((char *) window,(char **) NULL,0));
8923 if (remote_window == (Window) NULL)
8924 remote_window=XWindowByName(display,root_window,window);
8925 }
8926 if (remote_window == (Window) NULL)
8927 remote_window=XWindowByProperty(display,root_window,remote_atom);
8928 if (remote_window == (Window) NULL)
8929 {
8930 ThrowXWindowException(XServerError,"UnableToConnectToRemoteDisplay",
8931 filename);
8932 return(MagickFalse);
8933 }
8934 /*
8935 Send remote command.
8936 */
8937 remote_atom=XInternAtom(display,"IM_REMOTE_COMMAND",MagickFalse);
8938 (void) XChangeProperty(display,remote_window,remote_atom,XA_STRING,8,
8939 PropModeReplace,(unsigned char *) filename,(int) strlen(filename));
8940 (void) XSync(display,MagickFalse);
8941 return(MagickTrue);
8942}
8943
8944/*
8945%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8946% %
8947% %
8948% %
8949% X R e t a i n W i n d o w C o l o r s %
8950% %
8951% %
8952% %
8953%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8954%
8955% XRetainWindowColors() sets X11 color resources on a window. This preserves
8956% the colors associated with an image displayed on the window.
8957%
8958% The format of the XRetainWindowColors method is:
8959%
8960% void XRetainWindowColors(Display *display,const Window window)
8961%
8962% A description of each parameter follows:
8963%
8964% o display: Specifies a connection to an X server; returned from
8965% XOpenDisplay.
8966%
8967% o window: Specifies a pointer to a XWindowInfo structure.
8968%
8969*/
8970MagickExport void XRetainWindowColors(Display *display,const Window window)
8971{
8972 Atom
8973 property;
8974
8975 Pixmap
8976 pixmap;
8977
8978 /*
8979 Put property on the window.
8980 */
8981 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
8982 assert(display != (Display *) NULL);
8983 assert(window != (Window) NULL);
8984 property=XInternAtom(display,"_XSETROOT_ID",MagickFalse);
8985 if (property == (Atom) NULL)
8986 {
8987 ThrowXWindowFatalException(XServerError,"UnableToCreateProperty",
8988 "_XSETROOT_ID");
8989 return;
8990 }
8991 pixmap=XCreatePixmap(display,window,1,1,1);
8992 if (pixmap == (Pixmap) NULL)
8993 {
8994 ThrowXWindowFatalException(XServerError,"UnableToCreateBitmap","");
8995 return;
8996 }
8997 (void) XChangeProperty(display,window,property,XA_PIXMAP,32,PropModeReplace,
8998 (unsigned char *) &pixmap,1);
8999 (void) XSetCloseDownMode(display,RetainPermanent);
9000}
9001
9002/*
9003%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9004% %
9005% %
9006% %
9007% X S e l e c t W i n d o w %
9008% %
9009% %
9010% %
9011%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9012%
9013% XSelectWindow() allows a user to select a window using the mouse. If the
9014% mouse moves, a cropping rectangle is drawn and the extents of the rectangle
9015% is returned in the crop_info structure.
9016%
9017% The format of the XSelectWindow function is:
9018%
9019% target_window=XSelectWindow(display,crop_info)
9020%
9021% A description of each parameter follows:
9022%
9023% o window: XSelectWindow returns the window id.
9024%
9025% o display: Specifies a pointer to the Display structure; returned from
9026% XOpenDisplay.
9027%
9028% o crop_info: Specifies a pointer to a RectangleInfo structure. It
9029% contains the extents of any cropping rectangle.
9030%
cristy3ed852e2009-09-05 21:47:34 +00009031*/
9032static Window XSelectWindow(Display *display,RectangleInfo *crop_info)
9033{
9034#define MinimumCropArea (unsigned int) 9
9035
9036 Cursor
9037 target_cursor;
9038
9039 GC
9040 annotate_context;
9041
9042 int
9043 presses,
9044 x_offset,
9045 y_offset;
9046
9047 Status
9048 status;
9049
9050 Window
9051 root_window,
9052 target_window;
9053
9054 XEvent
9055 event;
9056
9057 XGCValues
9058 context_values;
9059
9060 /*
9061 Initialize graphic context.
9062 */
9063 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
9064 assert(display != (Display *) NULL);
9065 assert(crop_info != (RectangleInfo *) NULL);
9066 root_window=XRootWindow(display,XDefaultScreen(display));
9067 context_values.background=XBlackPixel(display,XDefaultScreen(display));
9068 context_values.foreground=XWhitePixel(display,XDefaultScreen(display));
9069 context_values.function=GXinvert;
9070 context_values.plane_mask=
9071 context_values.background ^ context_values.foreground;
9072 context_values.subwindow_mode=IncludeInferiors;
cristybb503372010-05-27 20:51:26 +00009073 annotate_context=XCreateGC(display,root_window,(size_t) (GCBackground |
cristy3ed852e2009-09-05 21:47:34 +00009074 GCForeground | GCFunction | GCSubwindowMode),&context_values);
9075 if (annotate_context == (GC) NULL)
9076 return(MagickFalse);
9077 /*
9078 Grab the pointer using target cursor.
9079 */
9080 target_cursor=XMakeCursor(display,root_window,XDefaultColormap(display,
9081 XDefaultScreen(display)),(char * ) "white",(char * ) "black");
9082 status=XGrabPointer(display,root_window,MagickFalse,(unsigned int)
9083 (ButtonPressMask | ButtonReleaseMask | ButtonMotionMask),GrabModeSync,
9084 GrabModeAsync,root_window,target_cursor,CurrentTime);
9085 if (status != GrabSuccess)
9086 {
9087 ThrowXWindowFatalException(XServerError,"UnableToGrabMouse","");
9088 return((Window) NULL);
9089 }
9090 /*
9091 Select a window.
9092 */
9093 crop_info->width=0;
9094 crop_info->height=0;
9095 presses=0;
9096 target_window=(Window) NULL;
9097 x_offset=0;
9098 y_offset=0;
9099 do
9100 {
9101 if ((crop_info->width*crop_info->height) >= MinimumCropArea)
9102 (void) XDrawRectangle(display,root_window,annotate_context,
9103 (int) crop_info->x,(int) crop_info->y,(unsigned int) crop_info->width-1,
9104 (unsigned int) crop_info->height-1);
9105 /*
9106 Allow another event.
9107 */
9108 (void) XAllowEvents(display,SyncPointer,CurrentTime);
9109 (void) XWindowEvent(display,root_window,ButtonPressMask |
9110 ButtonReleaseMask | ButtonMotionMask,&event);
9111 if ((crop_info->width*crop_info->height) >= MinimumCropArea)
9112 (void) XDrawRectangle(display,root_window,annotate_context,
9113 (int) crop_info->x,(int) crop_info->y,(unsigned int) crop_info->width-1,
9114 (unsigned int) crop_info->height-1);
9115 switch (event.type)
9116 {
9117 case ButtonPress:
9118 {
9119 target_window=XGetSubwindow(display,event.xbutton.subwindow,
9120 event.xbutton.x,event.xbutton.y);
9121 if (target_window == (Window) NULL)
9122 target_window=root_window;
9123 x_offset=event.xbutton.x_root;
9124 y_offset=event.xbutton.y_root;
cristyecd0ab52010-05-30 14:59:20 +00009125 crop_info->x=(ssize_t) x_offset;
9126 crop_info->y=(ssize_t) y_offset;
cristy3ed852e2009-09-05 21:47:34 +00009127 crop_info->width=0;
9128 crop_info->height=0;
9129 presses++;
9130 break;
9131 }
9132 case ButtonRelease:
9133 {
9134 presses--;
9135 break;
9136 }
9137 case MotionNotify:
9138 {
9139 /*
9140 Discard pending button motion events.
9141 */
9142 while (XCheckMaskEvent(display,ButtonMotionMask,&event)) ;
cristyecd0ab52010-05-30 14:59:20 +00009143 crop_info->x=(ssize_t) event.xmotion.x;
9144 crop_info->y=(ssize_t) event.xmotion.y;
cristy3ed852e2009-09-05 21:47:34 +00009145 /*
9146 Check boundary conditions.
9147 */
9148 if ((int) crop_info->x < x_offset)
cristyecd0ab52010-05-30 14:59:20 +00009149 crop_info->width=(size_t) (x_offset-crop_info->x);
cristy3ed852e2009-09-05 21:47:34 +00009150 else
9151 {
cristyecd0ab52010-05-30 14:59:20 +00009152 crop_info->width=(size_t) (crop_info->x-x_offset);
9153 crop_info->x=(ssize_t) x_offset;
cristy3ed852e2009-09-05 21:47:34 +00009154 }
9155 if ((int) crop_info->y < y_offset)
cristyecd0ab52010-05-30 14:59:20 +00009156 crop_info->height=(size_t) (y_offset-crop_info->y);
cristy3ed852e2009-09-05 21:47:34 +00009157 else
9158 {
cristyecd0ab52010-05-30 14:59:20 +00009159 crop_info->height=(size_t) (crop_info->y-y_offset);
9160 crop_info->y=(ssize_t) y_offset;
cristy3ed852e2009-09-05 21:47:34 +00009161 }
9162 }
9163 default:
9164 break;
9165 }
9166 } while ((target_window == (Window) NULL) || (presses > 0));
9167 (void) XUngrabPointer(display,CurrentTime);
9168 (void) XFreeCursor(display,target_cursor);
9169 (void) XFreeGC(display,annotate_context);
9170 if ((crop_info->width*crop_info->height) < MinimumCropArea)
9171 {
9172 crop_info->width=0;
9173 crop_info->height=0;
9174 }
9175 if ((crop_info->width != 0) && (crop_info->height != 0))
9176 target_window=root_window;
9177 return(target_window);
9178}
9179
9180/*
9181%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9182% %
9183% %
9184% %
9185% X S e t C u r s o r S t a t e %
9186% %
9187% %
9188% %
9189%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9190%
9191% XSetCursorState() sets the cursor state to busy, otherwise the cursor are
9192% reset to their default.
9193%
9194% The format of the XXSetCursorState method is:
9195%
9196% XSetCursorState(display,windows,const MagickStatusType state)
9197%
9198% A description of each parameter follows:
9199%
9200% o display: Specifies a connection to an X server; returned from
9201% XOpenDisplay.
9202%
9203% o windows: Specifies a pointer to a XWindows structure.
9204%
9205% o state: An unsigned integer greater than 0 sets the cursor state
9206% to busy, otherwise the cursor are reset to their default.
9207%
9208*/
cristybcbda3f2011-09-03 13:01:22 +00009209MagickPrivate void XSetCursorState(Display *display,XWindows *windows,
cristy3ed852e2009-09-05 21:47:34 +00009210 const MagickStatusType state)
9211{
9212 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
9213 assert(display != (Display *) NULL);
9214 assert(windows != (XWindows *) NULL);
9215 if (state)
9216 {
9217 (void) XCheckDefineCursor(display,windows->image.id,
9218 windows->image.busy_cursor);
9219 (void) XCheckDefineCursor(display,windows->pan.id,
9220 windows->pan.busy_cursor);
9221 (void) XCheckDefineCursor(display,windows->magnify.id,
9222 windows->magnify.busy_cursor);
9223 (void) XCheckDefineCursor(display,windows->command.id,
9224 windows->command.busy_cursor);
9225 }
9226 else
9227 {
9228 (void) XCheckDefineCursor(display,windows->image.id,
9229 windows->image.cursor);
9230 (void) XCheckDefineCursor(display,windows->pan.id,windows->pan.cursor);
9231 (void) XCheckDefineCursor(display,windows->magnify.id,
9232 windows->magnify.cursor);
9233 (void) XCheckDefineCursor(display,windows->command.id,
9234 windows->command.cursor);
9235 (void) XCheckDefineCursor(display,windows->command.id,
9236 windows->widget.cursor);
9237 (void) XWithdrawWindow(display,windows->info.id,windows->info.screen);
9238 }
9239 windows->info.mapped=MagickFalse;
9240}
9241
9242/*
9243%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9244% %
9245% %
9246% %
9247% X S e t W i n d o w s %
9248% %
9249% %
9250% %
9251%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9252%
9253% XSetWindows() sets the X windows structure if the windows info is specified.
9254% Otherwise the current windows structure is returned.
9255%
9256% The format of the XSetWindows method is:
9257%
9258% XWindows *XSetWindows(XWindows *windows_info)
9259%
9260% A description of each parameter follows:
9261%
9262% o windows_info: Initialize the Windows structure with this information.
9263%
9264*/
cristybcbda3f2011-09-03 13:01:22 +00009265MagickPrivate XWindows *XSetWindows(XWindows *windows_info)
cristy3ed852e2009-09-05 21:47:34 +00009266{
9267 static XWindows
9268 *windows = (XWindows *) NULL;
9269
9270 if (windows_info != (XWindows *) ~0)
9271 {
9272 windows=(XWindows *) RelinquishMagickMemory(windows);
9273 windows=windows_info;
9274 }
9275 return(windows);
9276}
9277/*
9278%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9279% %
9280% %
9281% %
9282% X U s e r P r e f e r e n c e s %
9283% %
9284% %
9285% %
9286%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9287%
9288% XUserPreferences() saves the preferences in a configuration file in the
9289% users' home directory.
9290%
9291% The format of the XUserPreferences method is:
9292%
9293% void XUserPreferences(XResourceInfo *resource_info)
9294%
9295% A description of each parameter follows:
9296%
9297% o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
9298%
9299*/
cristybcbda3f2011-09-03 13:01:22 +00009300MagickPrivate void XUserPreferences(XResourceInfo *resource_info)
cristy3ed852e2009-09-05 21:47:34 +00009301{
9302#if defined(X11_PREFERENCES_PATH)
9303 char
9304 cache[MaxTextExtent],
9305 filename[MaxTextExtent],
9306 specifier[MaxTextExtent];
9307
9308 const char
cristy104cea82009-10-25 02:26:51 +00009309 *client_name,
cristy3ed852e2009-09-05 21:47:34 +00009310 *value;
9311
9312 XrmDatabase
9313 preferences_database;
9314
9315 /*
9316 Save user preferences to the client configuration file.
9317 */
9318 assert(resource_info != (XResourceInfo *) NULL);
cristy104cea82009-10-25 02:26:51 +00009319 client_name=GetClientName();
cristy3ed852e2009-09-05 21:47:34 +00009320 preferences_database=XrmGetStringDatabase("");
cristyb51dff52011-05-19 16:55:47 +00009321 (void) FormatLocaleString(specifier,MaxTextExtent,"%s.backdrop",client_name);
cristy3ed852e2009-09-05 21:47:34 +00009322 value=resource_info->backdrop ? "True" : "False";
9323 XrmPutStringResource(&preferences_database,specifier,(char *) value);
cristyb51dff52011-05-19 16:55:47 +00009324 (void) FormatLocaleString(specifier,MaxTextExtent,"%s.colormap",client_name);
cristy3ed852e2009-09-05 21:47:34 +00009325 value=resource_info->colormap == SharedColormap ? "Shared" : "Private";
9326 XrmPutStringResource(&preferences_database,specifier,(char *) value);
cristyb51dff52011-05-19 16:55:47 +00009327 (void) FormatLocaleString(specifier,MaxTextExtent,"%s.confirmExit",
cristy104cea82009-10-25 02:26:51 +00009328 client_name);
cristy3ed852e2009-09-05 21:47:34 +00009329 value=resource_info->confirm_exit ? "True" : "False";
9330 XrmPutStringResource(&preferences_database,specifier,(char *) value);
cristyb51dff52011-05-19 16:55:47 +00009331 (void) FormatLocaleString(specifier,MaxTextExtent,"%s.confirmEdit",
cristy104cea82009-10-25 02:26:51 +00009332 client_name);
cristy3ed852e2009-09-05 21:47:34 +00009333 value=resource_info->confirm_edit ? "True" : "False";
9334 XrmPutStringResource(&preferences_database,specifier,(char *) value);
cristyb51dff52011-05-19 16:55:47 +00009335 (void) FormatLocaleString(specifier,MaxTextExtent,"%s.displayWarnings",
cristy104cea82009-10-25 02:26:51 +00009336 client_name);
cristy3ed852e2009-09-05 21:47:34 +00009337 value=resource_info->display_warnings ? "True" : "False";
9338 XrmPutStringResource(&preferences_database,specifier,(char *) value);
cristyb51dff52011-05-19 16:55:47 +00009339 (void) FormatLocaleString(specifier,MaxTextExtent,"%s.dither",client_name);
cristy3ed852e2009-09-05 21:47:34 +00009340 value=resource_info->quantize_info->dither ? "True" : "False";
9341 XrmPutStringResource(&preferences_database,specifier,(char *) value);
cristyb51dff52011-05-19 16:55:47 +00009342 (void) FormatLocaleString(specifier,MaxTextExtent,"%s.gammaCorrect",
cristy104cea82009-10-25 02:26:51 +00009343 client_name);
cristy3ed852e2009-09-05 21:47:34 +00009344 value=resource_info->gamma_correct ? "True" : "False";
9345 XrmPutStringResource(&preferences_database,specifier,(char *) value);
cristyb51dff52011-05-19 16:55:47 +00009346 (void) FormatLocaleString(specifier,MaxTextExtent,"%s.undoCache",client_name);
9347 (void) FormatLocaleString(cache,MaxTextExtent,"%.20g",(double)
cristy3ed852e2009-09-05 21:47:34 +00009348 resource_info->undo_cache);
9349 XrmPutStringResource(&preferences_database,specifier,cache);
cristyb51dff52011-05-19 16:55:47 +00009350 (void) FormatLocaleString(specifier,MaxTextExtent,"%s.usePixmap",client_name);
cristy3ed852e2009-09-05 21:47:34 +00009351 value=resource_info->use_pixmap ? "True" : "False";
9352 XrmPutStringResource(&preferences_database,specifier,(char *) value);
cristyb51dff52011-05-19 16:55:47 +00009353 (void) FormatLocaleString(filename,MaxTextExtent,"%s%src",
cristy104cea82009-10-25 02:26:51 +00009354 X11_PREFERENCES_PATH,client_name);
cristy3ed852e2009-09-05 21:47:34 +00009355 ExpandFilename(filename);
9356 XrmPutFileDatabase(preferences_database,filename);
9357#endif
9358}
9359
9360/*
9361%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9362% %
9363% %
9364% %
9365% X V i s u a l C l a s s N a m e %
9366% %
9367% %
9368% %
9369%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9370%
9371% XVisualClassName() returns the visual class name as a character string.
9372%
9373% The format of the XVisualClassName method is:
9374%
9375% char *XVisualClassName(const int visual_class)
9376%
9377% A description of each parameter follows:
9378%
9379% o visual_type: XVisualClassName returns the visual class as a character
9380% string.
9381%
9382% o class: Specifies the visual class.
9383%
cristy3ed852e2009-09-05 21:47:34 +00009384*/
9385static const char *XVisualClassName(const int visual_class)
9386{
9387 switch (visual_class)
9388 {
9389 case StaticGray: return("StaticGray");
9390 case GrayScale: return("GrayScale");
9391 case StaticColor: return("StaticColor");
9392 case PseudoColor: return("PseudoColor");
9393 case TrueColor: return("TrueColor");
9394 case DirectColor: return("DirectColor");
9395 }
9396 return("unknown visual class");
9397}
9398
9399/*
9400%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9401% %
9402% %
9403% %
9404% X W a r n i n g %
9405% %
9406% %
9407% %
9408%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9409%
9410% XWarning() displays a warning reason in a Notice widget.
9411%
9412% The format of the XWarning method is:
9413%
9414% void XWarning(const unsigned int warning,const char *reason,
9415% const char *description)
9416%
9417% A description of each parameter follows:
9418%
9419% o warning: Specifies the numeric warning category.
9420%
9421% o reason: Specifies the reason to display before terminating the
9422% program.
9423%
9424% o description: Specifies any description to the reason.
9425%
9426*/
cristybcbda3f2011-09-03 13:01:22 +00009427MagickPrivate void XWarning(const ExceptionType magick_unused(warning),
cristy3ed852e2009-09-05 21:47:34 +00009428 const char *reason,const char *description)
9429{
9430 char
9431 text[MaxTextExtent];
9432
9433 XWindows
9434 *windows;
9435
9436 if (reason == (char *) NULL)
9437 return;
9438 (void) CopyMagickString(text,reason,MaxTextExtent);
9439 (void) ConcatenateMagickString(text,":",MaxTextExtent);
9440 windows=XSetWindows((XWindows *) ~0);
9441 XNoticeWidget(windows->display,windows,text,(char *) description);
9442}
9443
9444/*
9445%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9446% %
9447% %
9448% %
9449% X W i n d o w B y I D %
9450% %
9451% %
9452% %
9453%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9454%
9455% XWindowByID() locates a child window with a given ID. If not window with
9456% the given name is found, 0 is returned. Only the window specified and its
9457% subwindows are searched.
9458%
9459% The format of the XWindowByID function is:
9460%
9461% child=XWindowByID(display,window,id)
9462%
9463% A description of each parameter follows:
9464%
9465% o child: XWindowByID returns the window with the specified
9466% id. If no windows are found, XWindowByID returns 0.
9467%
9468% o display: Specifies a pointer to the Display structure; returned from
9469% XOpenDisplay.
9470%
9471% o id: Specifies the id of the window to locate.
9472%
9473*/
cristybcbda3f2011-09-03 13:01:22 +00009474MagickPrivate Window XWindowByID(Display *display,const Window root_window,
cristybb503372010-05-27 20:51:26 +00009475 const size_t id)
cristy3ed852e2009-09-05 21:47:34 +00009476{
9477 RectangleInfo
9478 rectangle_info;
9479
9480 register int
9481 i;
9482
9483 Status
9484 status;
9485
9486 unsigned int
9487 number_children;
9488
9489 Window
9490 child,
9491 *children,
9492 window;
9493
9494 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
9495 assert(display != (Display *) NULL);
9496 assert(root_window != (Window) NULL);
9497 if (id == 0)
9498 return(XSelectWindow(display,&rectangle_info));
9499 if (root_window == id)
cristydfe2b662010-08-22 16:17:24 +00009500 return(root_window);
cristy3ed852e2009-09-05 21:47:34 +00009501 status=XQueryTree(display,root_window,&child,&child,&children,
9502 &number_children);
9503 if (status == False)
9504 return((Window) NULL);
9505 window=(Window) NULL;
9506 for (i=0; i < (int) number_children; i++)
9507 {
9508 /*
9509 Search each child and their children.
9510 */
9511 window=XWindowByID(display,children[i],id);
9512 if (window != (Window) NULL)
9513 break;
9514 }
9515 if (children != (Window *) NULL)
9516 (void) XFree((void *) children);
9517 return(window);
9518}
9519
9520/*
9521%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9522% %
9523% %
9524% %
9525% X W i n d o w B y N a m e %
9526% %
9527% %
9528% %
9529%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9530%
9531% XWindowByName() locates a window with a given name on a display. If no
9532% window with the given name is found, 0 is returned. If more than one window
9533% has the given name, the first one is returned. Only root and its children
9534% are searched.
9535%
9536% The format of the XWindowByName function is:
9537%
9538% window=XWindowByName(display,root_window,name)
9539%
9540% A description of each parameter follows:
9541%
9542% o window: XWindowByName returns the window id.
9543%
9544% o display: Specifies a pointer to the Display structure; returned from
9545% XOpenDisplay.
9546%
9547% o root_window: Specifies the id of the root window.
9548%
9549% o name: Specifies the name of the window to locate.
9550%
9551*/
cristybcbda3f2011-09-03 13:01:22 +00009552MagickPrivate Window XWindowByName(Display *display,const Window root_window,
cristy3ed852e2009-09-05 21:47:34 +00009553 const char *name)
9554{
9555 register int
9556 i;
9557
9558 Status
9559 status;
9560
9561 unsigned int
9562 number_children;
9563
9564 Window
9565 *children,
9566 child,
9567 window;
9568
9569 XTextProperty
9570 window_name;
9571
9572 assert(display != (Display *) NULL);
9573 assert(root_window != (Window) NULL);
9574 assert(name != (char *) NULL);
9575 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",name);
9576 if (XGetWMName(display,root_window,&window_name) != 0)
9577 if (LocaleCompare((char *) window_name.value,name) == 0)
9578 return(root_window);
9579 status=XQueryTree(display,root_window,&child,&child,&children,
9580 &number_children);
9581 if (status == False)
9582 return((Window) NULL);
9583 window=(Window) NULL;
9584 for (i=0; i < (int) number_children; i++)
9585 {
9586 /*
9587 Search each child and their children.
9588 */
9589 window=XWindowByName(display,children[i],name);
9590 if (window != (Window) NULL)
9591 break;
9592 }
9593 if (children != (Window *) NULL)
9594 (void) XFree((void *) children);
9595 return(window);
9596}
9597
9598/*
9599%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9600% %
9601% %
9602% %
9603% X W i n d o w B y P r o p e r y %
9604% %
9605% %
9606% %
9607%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9608%
9609% XWindowByProperty() locates a child window with a given property. If not
9610% window with the given name is found, 0 is returned. If more than one window
9611% has the given property, the first one is returned. Only the window
9612% specified and its subwindows are searched.
9613%
9614% The format of the XWindowByProperty function is:
9615%
9616% child=XWindowByProperty(display,window,property)
9617%
9618% A description of each parameter follows:
9619%
9620% o child: XWindowByProperty returns the window id with the specified
9621% property. If no windows are found, XWindowByProperty returns 0.
9622%
9623% o display: Specifies a pointer to the Display structure; returned from
9624% XOpenDisplay.
9625%
9626% o property: Specifies the property of the window to locate.
9627%
9628*/
cristybcbda3f2011-09-03 13:01:22 +00009629MagickPrivate Window XWindowByProperty(Display *display,const Window window,
cristy3ed852e2009-09-05 21:47:34 +00009630 const Atom property)
9631{
9632 Atom
9633 type;
9634
9635 int
9636 format;
9637
9638 Status
9639 status;
9640
9641 unsigned char
9642 *data;
9643
9644 unsigned int
9645 i,
9646 number_children;
9647
cristyf2faecf2010-05-28 19:19:36 +00009648 unsigned long
cristy3ed852e2009-09-05 21:47:34 +00009649 after,
9650 number_items;
9651
9652 Window
9653 child,
9654 *children,
9655 parent,
9656 root;
9657
9658 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
9659 assert(display != (Display *) NULL);
9660 assert(window != (Window) NULL);
9661 assert(property != (Atom) NULL);
9662 status=XQueryTree(display,window,&root,&parent,&children,&number_children);
9663 if (status == False)
9664 return((Window) NULL);
9665 type=(Atom) NULL;
9666 child=(Window) NULL;
9667 for (i=0; (i < number_children) && (child == (Window) NULL); i++)
9668 {
9669 status=XGetWindowProperty(display,children[i],property,0L,0L,MagickFalse,
9670 (Atom) AnyPropertyType,&type,&format,&number_items,&after,&data);
9671 if (data != NULL)
9672 (void) XFree((void *) data);
9673 if ((status == Success) && (type != (Atom) NULL))
9674 child=children[i];
9675 }
9676 for (i=0; (i < number_children) && (child == (Window) NULL); i++)
9677 child=XWindowByProperty(display,children[i],property);
9678 if (children != (Window *) NULL)
9679 (void) XFree((void *) children);
9680 return(child);
9681}
9682#else
9683
9684/*
9685%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9686% %
9687% %
9688% %
9689% X I m p o r t I m a g e %
9690% %
9691% %
9692% %
9693%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9694%
9695% XImportImage() reads an image from an X window.
9696%
9697% The format of the XImportImage method is:
9698%
9699% Image *XImportImage(const ImageInfo *image_info,XImportInfo *ximage_info)
9700%
9701% A description of each parameter follows:
9702%
9703% o image_info: the image info..
9704%
9705% o ximage_info: Specifies a pointer to an XImportInfo structure.
9706%
9707*/
cristybcbda3f2011-09-03 13:01:22 +00009708MagickPrivate Image *XImportImage(const ImageInfo *image_info,
cristy3ed852e2009-09-05 21:47:34 +00009709 XImportInfo *ximage_info)
9710{
9711 assert(image_info != (const ImageInfo *) NULL);
9712 assert(image_info->signature == MagickSignature);
9713 if (image_info->debug != MagickFalse)
9714 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
9715 image_info->filename);
9716 assert(ximage_info != (XImportInfo *) NULL);
9717 return((Image *) NULL);
9718}
9719#endif
9720
9721/*
9722%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9723% %
9724% %
9725% %
cristy576974e2009-10-25 20:45:31 +00009726+ X C o m p o n e n t G e n e s i s %
9727% %
9728% %
9729% %
9730%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9731%
9732% XComponentGenesis() instantiates the X component.
9733%
9734% The format of the XComponentGenesis method is:
9735%
9736% MagickBooleanType XComponentGenesis(void)
9737%
9738*/
cristy5ff4eaf2011-09-03 01:38:02 +00009739MagickPrivate MagickBooleanType XComponentGenesis(void)
cristy576974e2009-10-25 20:45:31 +00009740{
9741 return(MagickTrue);
9742}
9743
9744/*
9745%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9746% %
9747% %
9748% %
cristy3ed852e2009-09-05 21:47:34 +00009749% X G e t I m p o r t I n f o %
9750% %
9751% %
9752% %
9753%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9754%
9755% XGetImportInfo() initializes the XImportInfo structure.
9756%
9757% The format of the XGetImportInfo method is:
9758%
9759% void XGetImportInfo(XImportInfo *ximage_info)
9760%
9761% A description of each parameter follows:
9762%
9763% o ximage_info: Specifies a pointer to an ImageInfo structure.
9764%
9765*/
9766MagickExport void XGetImportInfo(XImportInfo *ximage_info)
9767{
9768 assert(ximage_info != (XImportInfo *) NULL);
9769 ximage_info->frame=MagickFalse;
9770 ximage_info->borders=MagickFalse;
9771 ximage_info->screen=MagickFalse;
9772 ximage_info->descend=MagickTrue;
9773 ximage_info->silent=MagickFalse;
9774}